From 8f967ca4322ab39215ff91dbb143626567e38d1e Mon Sep 17 00:00:00 2001 From: Rim Date: Tue, 5 Dec 2023 14:22:58 -0500 Subject: [PATCH] Add deps locally, remove --dirty flag, add build script --- .gitmodules | 24 - build.bat | 5 + deps/GSL | 1 - deps/GSL/.clang-format | 34 + deps/GSL/.gitattributes | 1 + deps/GSL/.github/workflows/android.yml | 50 + .../.github/workflows/cmake_find_package.yml | 25 + deps/GSL/.github/workflows/ios.yml | 52 + deps/GSL/.gitignore | 16 + deps/GSL/CMakeLists.txt | 48 + deps/GSL/CMakeSettings.json | 18 + deps/GSL/CONTRIBUTING.md | 29 + deps/GSL/GSL.natvis | 32 + deps/GSL/LICENSE | 21 + deps/GSL/README.md | 218 + deps/GSL/SECURITY.md | 41 + deps/GSL/ThirdPartyNotices.txt | 41 + deps/GSL/azure-pipelines.yml | 66 + deps/GSL/docs/headers.md | 854 ++ deps/GSL/include/CMakeLists.txt | 13 + deps/GSL/include/gsl/algorithm | 63 + deps/GSL/include/gsl/assert | 136 + deps/GSL/include/gsl/byte | 202 + deps/GSL/include/gsl/gsl | 32 + deps/GSL/include/gsl/gsl_algorithm | 4 + deps/GSL/include/gsl/gsl_assert | 3 + deps/GSL/include/gsl/gsl_byte | 3 + deps/GSL/include/gsl/gsl_narrow | 3 + deps/GSL/include/gsl/gsl_util | 3 + deps/GSL/include/gsl/narrow | 84 + deps/GSL/include/gsl/pointers | 346 + deps/GSL/include/gsl/span | 842 ++ deps/GSL/include/gsl/span_ext | 214 + deps/GSL/include/gsl/string_span | 58 + deps/GSL/include/gsl/util | 157 + deps/GSL/pipelines/jobs.yml | 43 + deps/GSL/pipelines/setup_apple.yml | 9 + deps/GSL/pipelines/setup_clang.yml | 13 + deps/GSL/pipelines/setup_gcc.yml | 14 + deps/GSL/pipelines/steps.yml | 0 deps/GSL/tests/CMakeLists.txt | 306 + deps/GSL/tests/CMakeLists.txt.in | 14 + deps/GSL/tests/algorithm_tests.cpp | 224 + deps/GSL/tests/assertion_tests.cpp | 60 + deps/GSL/tests/at_tests.cpp | 173 + deps/GSL/tests/byte_tests.cpp | 137 + deps/GSL/tests/deathTestCommon.h | 11 + deps/GSL/tests/no_exception_ensure_tests.cpp | 55 + deps/GSL/tests/notnull_tests.cpp | 636 + deps/GSL/tests/owner_tests.cpp | 43 + deps/GSL/tests/span_compatibility_tests.cpp | 1023 ++ deps/GSL/tests/span_ext_tests.cpp | 380 + deps/GSL/tests/span_tests.cpp | 1383 +++ deps/GSL/tests/strict_notnull_tests.cpp | 304 + deps/GSL/tests/utils_tests.cpp | 165 + deps/discord-rpc | 1 - deps/discord-rpc/.clang-format | 92 + deps/discord-rpc/.gitignore | 5 + deps/discord-rpc/.travis.yml | 47 + deps/discord-rpc/CMakeLists.txt | 56 + deps/discord-rpc/LICENSE | 19 + deps/discord-rpc/README.md | 158 + deps/discord-rpc/appveyor.yml | 17 + deps/discord-rpc/build.py | 304 + deps/discord-rpc/documentation/hard-mode.md | 164 + .../documentation/images/rp-dev-dashboard.png | Bin 0 -> 325539 bytes .../documentation/images/rp-profile-view.png | Bin 0 -> 1398658 bytes .../images/rp-secret-example.png | Bin 0 -> 14447 bytes .../examples/button-clicker/.gitignore | 8 + .../Assets/DiscordController.cs | 125 + .../button-clicker/Assets/DiscordRpc.cs | 231 + .../Assets/Editor/BuildHelper.cs | 101 + .../examples/button-clicker/Assets/main.unity | 1278 ++ .../ProjectSettings/AudioManager.asset | 17 + .../ProjectSettings/ClusterInputManager.asset | 6 + .../ProjectSettings/DynamicsManager.asset | 20 + .../ProjectSettings/EditorBuildSettings.asset | 10 + .../ProjectSettings/EditorSettings.asset | 16 + .../ProjectSettings/GraphicsSettings.asset | 61 + .../ProjectSettings/InputManager.asset | 295 + .../ProjectSettings/NavMeshAreas.asset | 89 + .../ProjectSettings/NetworkManager.asset | 8 + .../ProjectSettings/Physics2DSettings.asset | 37 + .../ProjectSettings/ProjectSettings.asset | 610 + .../ProjectSettings/ProjectVersion.txt | 1 + .../ProjectSettings/QualitySettings.asset | 193 + .../ProjectSettings/TagManager.asset | 43 + .../ProjectSettings/TimeManager.asset | 9 + .../UnityConnectSettings.asset | 34 + .../UnityPackageManager/manifest.json | 4 + .../examples/send-presence/CMakeLists.txt | 21 + .../examples/send-presence/send-presence.c | 206 + .../examples/unrealstatus/.gitignore | 78 + .../unrealstatus/Config/DefaultEditor.ini | 0 .../unrealstatus/Config/DefaultEngine.ini | 54 + .../unrealstatus/Config/DefaultGame.ini | 7 + .../unrealstatus/Content/MainScreenBP.uasset | Bin 0 -> 50332 bytes .../Content/MouseGameModeBP.uasset | Bin 0 -> 17950 bytes .../Content/MousePlayerControllerBP.uasset | Bin 0 -> 16981 bytes .../unrealstatus/Content/ShowTheUILevel.umap | Bin 0 -> 806708 bytes .../Plugins/discordrpc/DiscordRpc.uplugin | 29 + .../Plugins/discordrpc/Resources/Icon128.png | Bin 0 -> 9834 bytes .../Plugins/discordrpc/Resources/discord.png | Bin 0 -> 9834 bytes .../Source/DiscordRpc/DiscordRpc.Build.cs | 57 + .../Source/DiscordRpc/Private/DiscordRpc.cpp | 76 + .../Private/DiscordRpcBlueprint.cpp | 172 + .../DiscordRpc/Private/DiscordRpcPrivatePCH.h | 2 + .../Source/DiscordRpc/Public/DiscordRpc.h | 20 + .../DiscordRpc/Public/DiscordRpcBlueprint.h | 181 + .../DiscordRpcLibrary.Build.cs | 59 + .../Source/unrealstatus.Target.cs | 14 + .../Source/unrealstatus/unrealstatus.Build.cs | 23 + .../Source/unrealstatus/unrealstatus.cpp | 6 + .../Source/unrealstatus/unrealstatus.h | 5 + .../unrealstatus/unrealstatusGameModeBase.cpp | 3 + .../unrealstatus/unrealstatusGameModeBase.h | 15 + .../Source/unrealstatusEditor.Target.cs | 14 + .../unrealstatus/unrealstatus.uproject | 19 + deps/discord-rpc/include/discord_register.h | 26 + deps/discord-rpc/include/discord_rpc.h | 90 + deps/discord-rpc/src/CMakeLists.txt | 147 + deps/discord-rpc/src/backoff.h | 40 + deps/discord-rpc/src/connection.h | 19 + deps/discord-rpc/src/connection_unix.cpp | 125 + deps/discord-rpc/src/connection_win.cpp | 128 + .../src/discord_register_linux.cpp | 102 + deps/discord-rpc/src/discord_register_osx.m | 80 + deps/discord-rpc/src/discord_register_win.cpp | 186 + deps/discord-rpc/src/discord_rpc.cpp | 504 + deps/discord-rpc/src/dllmain.cpp | 8 + deps/discord-rpc/src/msg_queue.h | 36 + deps/discord-rpc/src/rpc_connection.cpp | 137 + deps/discord-rpc/src/rpc_connection.h | 59 + deps/discord-rpc/src/serialization.cpp | 250 + deps/discord-rpc/src/serialization.h | 215 + deps/libtomcrypt | 1 - deps/libtomcrypt/.ci/build.sh | 75 + deps/libtomcrypt/.ci/check_source.sh | 15 + deps/libtomcrypt/.ci/clang-tidy.sh | 51 + deps/libtomcrypt/.ci/coverage.sh | 51 + deps/libtomcrypt/.ci/coverage_more.sh | 28 + deps/libtomcrypt/.ci/meta_builds.sh | 108 + deps/libtomcrypt/.ci/printinfo.sh | 24 + deps/libtomcrypt/.ci/run.sh | 49 + deps/libtomcrypt/.ci/testbuild.sh | 26 + deps/libtomcrypt/.ci/valgrind.sh | 37 + deps/libtomcrypt/.clang-format | 42 + deps/libtomcrypt/.gitattributes | 7 + deps/libtomcrypt/.github/ISSUE_TEMPLATE.md | 30 + .../.github/PULL_REQUEST_TEMPLATE.md | 13 + deps/libtomcrypt/.github/workflows/main.yml | 92 + deps/libtomcrypt/.gitignore | 111 + deps/libtomcrypt/CMakeLists.txt | 304 + deps/libtomcrypt/LICENSE | 26 + deps/libtomcrypt/README.md | 200 + deps/libtomcrypt/appveyor.yml | 29 + deps/libtomcrypt/changes | 1648 +++ deps/libtomcrypt/coverity.sh | 44 + deps/libtomcrypt/demos/CMakeLists.txt | 70 + deps/libtomcrypt/demos/aesgcm.c | 150 + deps/libtomcrypt/demos/constants.c | 77 + deps/libtomcrypt/demos/demo_dynamic.py | 309 + deps/libtomcrypt/demos/gcm-file/gcm_file.c | 84 + .../demos/gcm-file/gcm_filehandle.c | 192 + deps/libtomcrypt/demos/hashsum.c | 290 + deps/libtomcrypt/demos/ltcrypt.c | 195 + deps/libtomcrypt/demos/openssl-enc.c | 358 + deps/libtomcrypt/demos/sizes.c | 71 + deps/libtomcrypt/demos/small.c | 12 + deps/libtomcrypt/demos/timing.c | 1396 +++ deps/libtomcrypt/demos/tv_gen.c | 818 ++ deps/libtomcrypt/doc/Doxyfile | 2429 ++++ deps/libtomcrypt/doc/crypt.tex | 9518 +++++++++++++++ deps/libtomcrypt/doc/libtomsm.png | Bin 0 -> 17809 bytes deps/libtomcrypt/doc/makefile | 63 + deps/libtomcrypt/helper.pl | 411 + deps/libtomcrypt/hooks/pre-commit | 49 + deps/libtomcrypt/libtomcrypt.pc.in | 10 + deps/libtomcrypt/libtomcrypt_VS2008.sln | 26 + deps/libtomcrypt/libtomcrypt_VS2008.vcproj | 2898 +++++ deps/libtomcrypt/makefile | 142 + deps/libtomcrypt/makefile.mingw | 328 + deps/libtomcrypt/makefile.msvc | 313 + deps/libtomcrypt/makefile.shared | 94 + deps/libtomcrypt/makefile.unix | 334 + deps/libtomcrypt/makefile_include.mk | 535 + deps/libtomcrypt/notes/etc/NoekeonVects.java | 249 + deps/libtomcrypt/notes/etc/saferp_optimizer.c | 177 + deps/libtomcrypt/notes/etc/whirlgen.c | 95 + deps/libtomcrypt/notes/etc/whirltest.c | 19 + .../notes/rsa-testvectors/makefile | 11 + .../notes/rsa-testvectors/oaep-int.txt | 369 + .../notes/rsa-testvectors/oaep-vect.c | 1418 +++ .../notes/rsa-testvectors/oaep-vect.txt | 2212 ++++ .../rsa-testvectors/pkcs1v15crypt-vectors.c | 5463 +++++++++ .../rsa-testvectors/pkcs1v15crypt-vectors.txt | 9709 +++++++++++++++ .../rsa-testvectors/pkcs1v15sign-vectors.c | 4261 +++++++ .../rsa-testvectors/pkcs1v15sign-vectors.txt | 9049 ++++++++++++++ .../notes/rsa-testvectors/pss-int.txt | 162 + .../notes/rsa-testvectors/pss-vect.c | 1418 +++ .../notes/rsa-testvectors/pss-vect.txt | 2581 ++++ .../notes/rsa-testvectors/readme.txt | 22 + deps/libtomcrypt/notes/rsa-testvectors/rt.py | 253 + deps/libtomcrypt/notes/tech0001.txt | 73 + deps/libtomcrypt/notes/tech0002.txt | 52 + deps/libtomcrypt/notes/tech0003.txt | 52 + deps/libtomcrypt/notes/tech0004.txt | 91 + deps/libtomcrypt/notes/tech0005.txt | 20 + deps/libtomcrypt/notes/tech0006.txt | 91 + deps/libtomcrypt/notes/tech0007.txt | 5 + deps/libtomcrypt/sources.cmake | 525 + deps/libtomcrypt/src/ciphers/aes/aes.c | 744 ++ deps/libtomcrypt/src/ciphers/aes/aes_tab.c | 1022 ++ deps/libtomcrypt/src/ciphers/anubis.c | 1550 +++ deps/libtomcrypt/src/ciphers/blowfish.c | 658 + deps/libtomcrypt/src/ciphers/camellia.c | 720 ++ deps/libtomcrypt/src/ciphers/cast5.c | 705 ++ deps/libtomcrypt/src/ciphers/des.c | 2093 ++++ deps/libtomcrypt/src/ciphers/idea.c | 250 + deps/libtomcrypt/src/ciphers/kasumi.c | 307 + deps/libtomcrypt/src/ciphers/khazad.c | 840 ++ deps/libtomcrypt/src/ciphers/kseed.c | 366 + deps/libtomcrypt/src/ciphers/multi2.c | 309 + deps/libtomcrypt/src/ciphers/noekeon.c | 317 + deps/libtomcrypt/src/ciphers/rc2.c | 408 + deps/libtomcrypt/src/ciphers/rc5.c | 323 + deps/libtomcrypt/src/ciphers/rc6.c | 324 + deps/libtomcrypt/src/ciphers/safer/safer.c | 484 + .../libtomcrypt/src/ciphers/safer/safer_tab.c | 54 + deps/libtomcrypt/src/ciphers/safer/saferp.c | 567 + deps/libtomcrypt/src/ciphers/serpent.c | 717 ++ deps/libtomcrypt/src/ciphers/skipjack.c | 334 + deps/libtomcrypt/src/ciphers/tea.c | 209 + .../libtomcrypt/src/ciphers/twofish/twofish.c | 706 ++ .../src/ciphers/twofish/twofish_tab.c | 486 + deps/libtomcrypt/src/ciphers/xtea.c | 251 + .../libtomcrypt/src/encauth/ccm/ccm_add_aad.c | 53 + .../src/encauth/ccm/ccm_add_nonce.c | 106 + deps/libtomcrypt/src/encauth/ccm/ccm_done.c | 55 + deps/libtomcrypt/src/encauth/ccm/ccm_init.c | 64 + deps/libtomcrypt/src/encauth/ccm/ccm_memory.c | 372 + .../libtomcrypt/src/encauth/ccm/ccm_process.c | 78 + deps/libtomcrypt/src/encauth/ccm/ccm_reset.c | 25 + deps/libtomcrypt/src/encauth/ccm/ccm_test.c | 274 + .../chachapoly/chacha20poly1305_add_aad.c | 28 + .../chachapoly/chacha20poly1305_decrypt.c | 38 + .../chachapoly/chacha20poly1305_done.c | 36 + .../chachapoly/chacha20poly1305_encrypt.c | 37 + .../chachapoly/chacha20poly1305_init.c | 20 + .../chachapoly/chacha20poly1305_memory.c | 72 + .../chachapoly/chacha20poly1305_setiv.c | 58 + .../chacha20poly1305_setiv_rfc7905.c | 30 + .../chachapoly/chacha20poly1305_test.c | 159 + .../src/encauth/eax/eax_addheader.c | 26 + .../libtomcrypt/src/encauth/eax/eax_decrypt.c | 38 + .../encauth/eax/eax_decrypt_verify_memory.c | 99 + deps/libtomcrypt/src/encauth/eax/eax_done.c | 82 + .../libtomcrypt/src/encauth/eax/eax_encrypt.c | 39 + .../eax/eax_encrypt_authenticate_memory.c | 70 + deps/libtomcrypt/src/encauth/eax/eax_init.c | 132 + deps/libtomcrypt/src/encauth/eax/eax_test.c | 249 + .../libtomcrypt/src/encauth/gcm/gcm_add_aad.c | 114 + deps/libtomcrypt/src/encauth/gcm/gcm_add_iv.c | 82 + deps/libtomcrypt/src/encauth/gcm/gcm_done.c | 80 + .../libtomcrypt/src/encauth/gcm/gcm_gf_mult.c | 209 + deps/libtomcrypt/src/encauth/gcm/gcm_init.c | 95 + deps/libtomcrypt/src/encauth/gcm/gcm_memory.c | 114 + deps/libtomcrypt/src/encauth/gcm/gcm_mult_h.c | 47 + .../libtomcrypt/src/encauth/gcm/gcm_process.c | 150 + deps/libtomcrypt/src/encauth/gcm/gcm_reset.c | 32 + deps/libtomcrypt/src/encauth/gcm/gcm_test.c | 407 + .../libtomcrypt/src/encauth/ocb/ocb_decrypt.c | 67 + .../encauth/ocb/ocb_decrypt_verify_memory.c | 74 + .../src/encauth/ocb/ocb_done_decrypt.c | 68 + .../src/encauth/ocb/ocb_done_encrypt.c | 34 + .../libtomcrypt/src/encauth/ocb/ocb_encrypt.c | 60 + .../ocb/ocb_encrypt_authenticate_memory.c | 72 + deps/libtomcrypt/src/encauth/ocb/ocb_init.c | 129 + deps/libtomcrypt/src/encauth/ocb/ocb_ntz.c | 30 + .../src/encauth/ocb/ocb_shift_xor.c | 27 + deps/libtomcrypt/src/encauth/ocb/ocb_test.c | 205 + deps/libtomcrypt/src/encauth/ocb/s_ocb_done.c | 136 + .../src/encauth/ocb3/ocb3_add_aad.c | 96 + .../src/encauth/ocb3/ocb3_decrypt.c | 76 + .../src/encauth/ocb3/ocb3_decrypt_last.c | 101 + .../encauth/ocb3/ocb3_decrypt_verify_memory.c | 100 + deps/libtomcrypt/src/encauth/ocb3/ocb3_done.c | 82 + .../src/encauth/ocb3/ocb3_encrypt.c | 76 + .../ocb3/ocb3_encrypt_authenticate_memory.c | 72 + .../src/encauth/ocb3/ocb3_encrypt_last.c | 102 + deps/libtomcrypt/src/encauth/ocb3/ocb3_init.c | 186 + .../src/encauth/ocb3/ocb3_int_ntz.c | 29 + .../src/encauth/ocb3/ocb3_int_xor_blocks.c | 30 + deps/libtomcrypt/src/encauth/ocb3/ocb3_test.c | 299 + deps/libtomcrypt/src/hashes/blake2b.c | 628 + deps/libtomcrypt/src/hashes/blake2s.c | 603 + deps/libtomcrypt/src/hashes/chc/chc.c | 302 + .../libtomcrypt/src/hashes/helper/hash_file.c | 43 + .../src/hashes/helper/hash_filehandle.c | 64 + .../src/hashes/helper/hash_memory.c | 59 + .../src/hashes/helper/hash_memory_multi.c | 78 + deps/libtomcrypt/src/hashes/md2.c | 240 + deps/libtomcrypt/src/hashes/md4.c | 296 + deps/libtomcrypt/src/hashes/md5.c | 356 + deps/libtomcrypt/src/hashes/rmd128.c | 396 + deps/libtomcrypt/src/hashes/rmd160.c | 455 + deps/libtomcrypt/src/hashes/rmd256.c | 420 + deps/libtomcrypt/src/hashes/rmd320.c | 485 + deps/libtomcrypt/src/hashes/sha1.c | 276 + deps/libtomcrypt/src/hashes/sha2/sha224.c | 119 + deps/libtomcrypt/src/hashes/sha2/sha256.c | 322 + deps/libtomcrypt/src/hashes/sha2/sha384.c | 124 + deps/libtomcrypt/src/hashes/sha2/sha512.c | 303 + deps/libtomcrypt/src/hashes/sha2/sha512_224.c | 120 + deps/libtomcrypt/src/hashes/sha2/sha512_256.c | 120 + deps/libtomcrypt/src/hashes/sha3.c | 378 + deps/libtomcrypt/src/hashes/sha3_test.c | 719 ++ deps/libtomcrypt/src/hashes/tiger.c | 796 ++ deps/libtomcrypt/src/hashes/whirl/whirl.c | 296 + deps/libtomcrypt/src/hashes/whirl/whirltab.c | 586 + deps/libtomcrypt/src/headers/tomcrypt.h | 95 + .../libtomcrypt/src/headers/tomcrypt_argchk.h | 38 + deps/libtomcrypt/src/headers/tomcrypt_cfg.h | 323 + .../libtomcrypt/src/headers/tomcrypt_cipher.h | 1160 ++ .../libtomcrypt/src/headers/tomcrypt_custom.h | 741 ++ deps/libtomcrypt/src/headers/tomcrypt_hash.h | 503 + deps/libtomcrypt/src/headers/tomcrypt_mac.h | 567 + .../libtomcrypt/src/headers/tomcrypt_macros.h | 454 + deps/libtomcrypt/src/headers/tomcrypt_math.h | 519 + deps/libtomcrypt/src/headers/tomcrypt_misc.h | 179 + deps/libtomcrypt/src/headers/tomcrypt_pk.h | 803 ++ deps/libtomcrypt/src/headers/tomcrypt_pkcs.h | 99 + .../src/headers/tomcrypt_private.h | 477 + deps/libtomcrypt/src/headers/tomcrypt_prng.h | 223 + deps/libtomcrypt/src/mac/blake2/blake2bmac.c | 56 + .../src/mac/blake2/blake2bmac_file.c | 78 + .../src/mac/blake2/blake2bmac_memory.c | 38 + .../src/mac/blake2/blake2bmac_memory_multi.c | 52 + .../src/mac/blake2/blake2bmac_test.c | 304 + deps/libtomcrypt/src/mac/blake2/blake2smac.c | 56 + .../src/mac/blake2/blake2smac_file.c | 78 + .../src/mac/blake2/blake2smac_memory.c | 38 + .../src/mac/blake2/blake2smac_memory_multi.c | 52 + .../src/mac/blake2/blake2smac_test.c | 304 + deps/libtomcrypt/src/mac/f9/f9_done.c | 65 + deps/libtomcrypt/src/mac/f9/f9_file.c | 87 + deps/libtomcrypt/src/mac/f9/f9_init.c | 58 + deps/libtomcrypt/src/mac/f9/f9_memory.c | 59 + deps/libtomcrypt/src/mac/f9/f9_memory_multi.c | 78 + deps/libtomcrypt/src/mac/f9/f9_process.c | 66 + deps/libtomcrypt/src/mac/f9/f9_test.c | 66 + deps/libtomcrypt/src/mac/hmac/hmac_done.c | 96 + deps/libtomcrypt/src/mac/hmac/hmac_file.c | 90 + deps/libtomcrypt/src/mac/hmac/hmac_init.c | 94 + deps/libtomcrypt/src/mac/hmac/hmac_memory.c | 76 + .../src/mac/hmac/hmac_memory_multi.c | 80 + deps/libtomcrypt/src/mac/hmac/hmac_process.c | 31 + deps/libtomcrypt/src/mac/hmac/hmac_test.c | 618 + deps/libtomcrypt/src/mac/omac/omac_done.c | 74 + deps/libtomcrypt/src/mac/omac/omac_file.c | 87 + deps/libtomcrypt/src/mac/omac/omac_init.c | 89 + deps/libtomcrypt/src/mac/omac/omac_memory.c | 73 + .../src/mac/omac/omac_memory_multi.c | 78 + deps/libtomcrypt/src/mac/omac/omac_process.c | 80 + deps/libtomcrypt/src/mac/omac/omac_test.c | 93 + deps/libtomcrypt/src/mac/pelican/pelican.c | 154 + .../src/mac/pelican/pelican_memory.c | 47 + .../src/mac/pelican/pelican_test.c | 103 + deps/libtomcrypt/src/mac/pmac/pmac_done.c | 62 + deps/libtomcrypt/src/mac/pmac/pmac_file.c | 88 + deps/libtomcrypt/src/mac/pmac/pmac_init.c | 138 + deps/libtomcrypt/src/mac/pmac/pmac_memory.c | 62 + .../src/mac/pmac/pmac_memory_multi.c | 77 + deps/libtomcrypt/src/mac/pmac/pmac_ntz.c | 27 + deps/libtomcrypt/src/mac/pmac/pmac_process.c | 88 + .../libtomcrypt/src/mac/pmac/pmac_shift_xor.c | 32 + deps/libtomcrypt/src/mac/pmac/pmac_test.c | 144 + deps/libtomcrypt/src/mac/poly1305/poly1305.c | 258 + .../src/mac/poly1305/poly1305_file.c | 83 + .../src/mac/poly1305/poly1305_memory.c | 43 + .../src/mac/poly1305/poly1305_memory_multi.c | 57 + .../src/mac/poly1305/poly1305_test.c | 46 + deps/libtomcrypt/src/mac/xcbc/xcbc_done.c | 65 + deps/libtomcrypt/src/mac/xcbc/xcbc_file.c | 87 + deps/libtomcrypt/src/mac/xcbc/xcbc_init.c | 96 + deps/libtomcrypt/src/mac/xcbc/xcbc_memory.c | 59 + .../src/mac/xcbc/xcbc_memory_multi.c | 78 + deps/libtomcrypt/src/mac/xcbc/xcbc_process.c | 63 + deps/libtomcrypt/src/mac/xcbc/xcbc_test.c | 116 + .../src/math/fp/ltc_ecc_fp_mulmod.c | 1578 +++ deps/libtomcrypt/src/math/gmp_desc.c | 658 + deps/libtomcrypt/src/math/ltm_desc.c | 560 + deps/libtomcrypt/src/math/multi.c | 66 + deps/libtomcrypt/src/math/radix_to_bin.c | 52 + deps/libtomcrypt/src/math/rand_bn.c | 65 + deps/libtomcrypt/src/math/rand_prime.c | 78 + deps/libtomcrypt/src/math/tfm_desc.c | 857 ++ deps/libtomcrypt/src/misc/adler32.c | 123 + .../src/misc/base16/base16_decode.c | 65 + .../src/misc/base16/base16_encode.c | 64 + .../src/misc/base32/base32_decode.c | 111 + .../src/misc/base32/base32_encode.c | 86 + .../src/misc/base64/base64_decode.c | 229 + .../src/misc/base64/base64_encode.c | 159 + deps/libtomcrypt/src/misc/bcrypt/bcrypt.c | 191 + deps/libtomcrypt/src/misc/burn_stack.c | 23 + .../libtomcrypt/src/misc/compare_testvector.c | 81 + deps/libtomcrypt/src/misc/copy_or_zeromem.c | 51 + deps/libtomcrypt/src/misc/crc32.c | 193 + deps/libtomcrypt/src/misc/crypt/crypt.c | 552 + .../libtomcrypt/src/misc/crypt/crypt_argchk.c | 17 + .../src/misc/crypt/crypt_cipher_descriptor.c | 15 + .../src/misc/crypt/crypt_cipher_is_valid.c | 24 + .../src/misc/crypt/crypt_constants.c | 290 + .../src/misc/crypt/crypt_find_cipher.c | 29 + .../src/misc/crypt/crypt_find_cipher_any.c | 38 + .../src/misc/crypt/crypt_find_cipher_id.c | 28 + .../src/misc/crypt/crypt_find_hash.c | 28 + .../src/misc/crypt/crypt_find_hash_any.c | 37 + .../src/misc/crypt/crypt_find_hash_id.c | 28 + .../src/misc/crypt/crypt_find_hash_oid.c | 23 + .../src/misc/crypt/crypt_find_prng.c | 29 + deps/libtomcrypt/src/misc/crypt/crypt_fsa.c | 46 + .../src/misc/crypt/crypt_hash_descriptor.c | 15 + .../src/misc/crypt/crypt_hash_is_valid.c | 24 + deps/libtomcrypt/src/misc/crypt/crypt_inits.c | 81 + .../src/misc/crypt/crypt_ltc_mp_descriptor.c | 6 + .../src/misc/crypt/crypt_prng_descriptor.c | 14 + .../src/misc/crypt/crypt_prng_is_valid.c | 24 + .../misc/crypt/crypt_prng_rng_descriptor.c | 7 + .../misc/crypt/crypt_register_all_ciphers.c | 99 + .../misc/crypt/crypt_register_all_hashes.c | 95 + .../src/misc/crypt/crypt_register_all_prngs.c | 38 + .../src/misc/crypt/crypt_register_cipher.c | 42 + .../src/misc/crypt/crypt_register_hash.c | 42 + .../src/misc/crypt/crypt_register_prng.c | 42 + deps/libtomcrypt/src/misc/crypt/crypt_sizes.c | 351 + .../src/misc/crypt/crypt_unregister_cipher.c | 33 + .../src/misc/crypt/crypt_unregister_hash.c | 32 + .../src/misc/crypt/crypt_unregister_prng.c | 32 + deps/libtomcrypt/src/misc/error_to_string.c | 68 + deps/libtomcrypt/src/misc/hkdf/hkdf.c | 135 + deps/libtomcrypt/src/misc/hkdf/hkdf_test.c | 284 + deps/libtomcrypt/src/misc/mem_neq.c | 53 + .../src/misc/padding/padding_depad.c | 90 + .../src/misc/padding/padding_pad.c | 151 + deps/libtomcrypt/src/misc/pbes/pbes.c | 73 + deps/libtomcrypt/src/misc/pbes/pbes1.c | 117 + deps/libtomcrypt/src/misc/pbes/pbes2.c | 198 + deps/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c | 82 + .../src/misc/pkcs12/pkcs12_utf8_to_utf16.c | 59 + deps/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c | 185 + deps/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c | 121 + deps/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c | 221 + .../src/misc/ssh/ssh_decode_sequence_multi.c | 165 + .../src/misc/ssh/ssh_encode_sequence_multi.c | 158 + deps/libtomcrypt/src/misc/zeromem.c | 22 + deps/libtomcrypt/src/modes/cbc/cbc_decrypt.c | 84 + deps/libtomcrypt/src/modes/cbc/cbc_done.c | 30 + deps/libtomcrypt/src/modes/cbc/cbc_encrypt.c | 85 + deps/libtomcrypt/src/modes/cbc/cbc_getiv.c | 34 + deps/libtomcrypt/src/modes/cbc/cbc_setiv.c | 32 + deps/libtomcrypt/src/modes/cbc/cbc_start.c | 50 + deps/libtomcrypt/src/modes/cfb/cfb_decrypt.c | 55 + deps/libtomcrypt/src/modes/cfb/cfb_done.c | 30 + deps/libtomcrypt/src/modes/cfb/cfb_encrypt.c | 53 + deps/libtomcrypt/src/modes/cfb/cfb_getiv.c | 34 + deps/libtomcrypt/src/modes/cfb/cfb_setiv.c | 40 + deps/libtomcrypt/src/modes/cfb/cfb_start.c | 54 + deps/libtomcrypt/src/modes/ctr/ctr_decrypt.c | 30 + deps/libtomcrypt/src/modes/ctr/ctr_done.c | 30 + deps/libtomcrypt/src/modes/ctr/ctr_encrypt.c | 129 + deps/libtomcrypt/src/modes/ctr/ctr_getiv.c | 34 + deps/libtomcrypt/src/modes/ctr/ctr_setiv.c | 44 + deps/libtomcrypt/src/modes/ctr/ctr_start.c | 89 + deps/libtomcrypt/src/modes/ctr/ctr_test.c | 73 + deps/libtomcrypt/src/modes/ecb/ecb_decrypt.c | 48 + deps/libtomcrypt/src/modes/ecb/ecb_done.c | 30 + deps/libtomcrypt/src/modes/ecb/ecb_encrypt.c | 48 + deps/libtomcrypt/src/modes/ecb/ecb_start.c | 36 + deps/libtomcrypt/src/modes/f8/f8_decrypt.c | 31 + deps/libtomcrypt/src/modes/f8/f8_done.c | 30 + deps/libtomcrypt/src/modes/f8/f8_encrypt.c | 91 + deps/libtomcrypt/src/modes/f8/f8_getiv.c | 34 + deps/libtomcrypt/src/modes/f8/f8_setiv.c | 40 + deps/libtomcrypt/src/modes/f8/f8_start.c | 86 + deps/libtomcrypt/src/modes/f8/f8_test_mode.c | 64 + deps/libtomcrypt/src/modes/lrw/lrw_decrypt.c | 39 + deps/libtomcrypt/src/modes/lrw/lrw_done.c | 31 + deps/libtomcrypt/src/modes/lrw/lrw_encrypt.c | 39 + deps/libtomcrypt/src/modes/lrw/lrw_getiv.c | 34 + deps/libtomcrypt/src/modes/lrw/lrw_process.c | 109 + deps/libtomcrypt/src/modes/lrw/lrw_setiv.c | 68 + deps/libtomcrypt/src/modes/lrw/lrw_start.c | 92 + deps/libtomcrypt/src/modes/lrw/lrw_test.c | 124 + deps/libtomcrypt/src/modes/ofb/ofb_decrypt.c | 31 + deps/libtomcrypt/src/modes/ofb/ofb_done.c | 30 + deps/libtomcrypt/src/modes/ofb/ofb_encrypt.c | 48 + deps/libtomcrypt/src/modes/ofb/ofb_getiv.c | 34 + deps/libtomcrypt/src/modes/ofb/ofb_setiv.c | 40 + deps/libtomcrypt/src/modes/ofb/ofb_start.c | 48 + deps/libtomcrypt/src/modes/xts/xts_decrypt.c | 146 + deps/libtomcrypt/src/modes/xts/xts_done.c | 21 + deps/libtomcrypt/src/modes/xts/xts_encrypt.c | 147 + deps/libtomcrypt/src/modes/xts/xts_init.c | 51 + deps/libtomcrypt/src/modes/xts/xts_mult_x.c | 29 + deps/libtomcrypt/src/modes/xts/xts_test.c | 296 + .../pk/asn1/der/bit/der_decode_bit_string.c | 77 + .../asn1/der/bit/der_decode_raw_bit_string.c | 84 + .../pk/asn1/der/bit/der_encode_bit_string.c | 72 + .../asn1/der/bit/der_encode_raw_bit_string.c | 75 + .../pk/asn1/der/bit/der_length_bit_string.c | 36 + .../pk/asn1/der/boolean/der_decode_boolean.c | 35 + .../pk/asn1/der/boolean/der_encode_boolean.c | 39 + .../pk/asn1/der/boolean/der_length_boolean.c | 23 + .../pk/asn1/der/choice/der_decode_choice.c | 221 + .../der/custom_type/der_decode_custom_type.c | 426 + .../der/custom_type/der_encode_custom_type.c | 228 + .../der/custom_type/der_length_custom_type.c | 203 + .../src/pk/asn1/der/general/der_asn1_maps.c | 157 + .../der/general/der_decode_asn1_identifier.c | 123 + .../asn1/der/general/der_decode_asn1_length.c | 59 + .../der/general/der_encode_asn1_identifier.c | 86 + .../asn1/der/general/der_encode_asn1_length.c | 117 + .../der/general/der_length_asn1_identifier.c | 23 + .../asn1/der/general/der_length_asn1_length.c | 22 + .../der_decode_generalizedtime.c | 135 + .../der_encode_generalizedtime.c | 98 + .../der_length_generalizedtime.c | 48 + .../pk/asn1/der/ia5/der_decode_ia5_string.c | 73 + .../pk/asn1/der/ia5/der_encode_ia5_string.c | 61 + .../pk/asn1/der/ia5/der_length_ia5_string.c | 172 + .../pk/asn1/der/integer/der_decode_integer.c | 68 + .../pk/asn1/der/integer/der_encode_integer.c | 105 + .../pk/asn1/der/integer/der_length_integer.c | 55 + .../der_decode_object_identifier.c | 94 + .../der_encode_object_identifier.c | 92 + .../der_length_object_identifier.c | 77 + .../asn1/der/octet/der_decode_octet_string.c | 69 + .../asn1/der/octet/der_encode_octet_string.c | 62 + .../asn1/der/octet/der_length_octet_string.c | 33 + .../der_decode_printable_string.c | 73 + .../der_encode_printable_string.c | 61 + .../der_length_printable_string.c | 144 + .../der/sequence/der_decode_sequence_ex.c | 28 + .../der/sequence/der_decode_sequence_flexi.c | 541 + .../der/sequence/der_decode_sequence_multi.c | 181 + .../der/sequence/der_encode_sequence_ex.c | 202 + .../der/sequence/der_encode_sequence_multi.c | 139 + .../asn1/der/sequence/der_length_sequence.c | 179 + .../pk/asn1/der/sequence/der_sequence_free.c | 53 + .../asn1/der/sequence/der_sequence_shrink.c | 40 + .../src/pk/asn1/der/set/der_encode_set.c | 74 + .../src/pk/asn1/der/set/der_encode_setof.c | 151 + .../short_integer/der_decode_short_integer.c | 60 + .../short_integer/der_encode_short_integer.c | 85 + .../short_integer/der_length_short_integer.c | 52 + .../der_decode_teletex_string.c | 72 + .../der_length_teletex_string.c | 188 + .../pk/asn1/der/utctime/der_decode_utctime.c | 116 + .../pk/asn1/der/utctime/der_encode_utctime.c | 71 + .../pk/asn1/der/utctime/der_length_utctime.c | 34 + .../pk/asn1/der/utf8/der_decode_utf8_string.c | 117 + .../pk/asn1/der/utf8/der_encode_utf8_string.c | 75 + .../pk/asn1/der/utf8/der_length_utf8_string.c | 81 + deps/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c | 37 + deps/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c | 44 + deps/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c | 82 + .../src/pk/asn1/pkcs8/pkcs8_decode_flexi.c | 97 + .../x509_decode_public_key_from_certificate.c | 109 + .../x509_decode_subject_public_key_info.c | 119 + .../x509_encode_subject_public_key_info.c | 66 + deps/libtomcrypt/src/pk/dh/dh.c | 227 + deps/libtomcrypt/src/pk/dh/dh_check_pubkey.c | 55 + deps/libtomcrypt/src/pk/dh/dh_export.c | 52 + deps/libtomcrypt/src/pk/dh/dh_export_key.c | 37 + deps/libtomcrypt/src/pk/dh/dh_free.c | 18 + deps/libtomcrypt/src/pk/dh/dh_generate_key.c | 90 + deps/libtomcrypt/src/pk/dh/dh_import.c | 89 + deps/libtomcrypt/src/pk/dh/dh_set.c | 114 + .../libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c | 44 + deps/libtomcrypt/src/pk/dh/dh_shared_secret.c | 70 + deps/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c | 129 + deps/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c | 118 + deps/libtomcrypt/src/pk/dsa/dsa_export.c | 100 + deps/libtomcrypt/src/pk/dsa/dsa_free.c | 23 + .../libtomcrypt/src/pk/dsa/dsa_generate_key.c | 37 + .../libtomcrypt/src/pk/dsa/dsa_generate_pqg.c | 234 + deps/libtomcrypt/src/pk/dsa/dsa_import.c | 143 + deps/libtomcrypt/src/pk/dsa/dsa_make_key.c | 31 + deps/libtomcrypt/src/pk/dsa/dsa_set.c | 102 + .../src/pk/dsa/dsa_set_pqg_dsaparam.c | 57 + .../src/pk/dsa/dsa_shared_secret.c | 60 + deps/libtomcrypt/src/pk/dsa/dsa_sign_hash.c | 142 + deps/libtomcrypt/src/pk/dsa/dsa_verify_hash.c | 127 + deps/libtomcrypt/src/pk/dsa/dsa_verify_key.c | 189 + .../src/pk/ec25519/ec25519_crypto_ctx.c | 41 + .../src/pk/ec25519/ec25519_export.c | 90 + .../src/pk/ec25519/ec25519_import_pkcs8.c | 87 + deps/libtomcrypt/src/pk/ec25519/tweetnacl.c | 491 + deps/libtomcrypt/src/pk/ecc/ecc.c | 435 + .../src/pk/ecc/ecc_ansi_x963_export.c | 24 + .../src/pk/ecc/ecc_ansi_x963_import.c | 52 + deps/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c | 133 + deps/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c | 120 + deps/libtomcrypt/src/pk/ecc/ecc_export.c | 61 + .../src/pk/ecc/ecc_export_openssl.c | 167 + deps/libtomcrypt/src/pk/ecc/ecc_find_curve.c | 242 + deps/libtomcrypt/src/pk/ecc/ecc_free.c | 28 + deps/libtomcrypt/src/pk/ecc/ecc_get_key.c | 50 + deps/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c | 22 + deps/libtomcrypt/src/pk/ecc/ecc_get_size.c | 26 + deps/libtomcrypt/src/pk/ecc/ecc_import.c | 100 + .../src/pk/ecc/ecc_import_openssl.c | 120 + .../libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c | 186 + deps/libtomcrypt/src/pk/ecc/ecc_import_x509.c | 116 + deps/libtomcrypt/src/pk/ecc/ecc_make_key.c | 73 + deps/libtomcrypt/src/pk/ecc/ecc_recover_key.c | 260 + deps/libtomcrypt/src/pk/ecc/ecc_set_curve.c | 80 + .../src/pk/ecc/ecc_set_curve_internal.c | 119 + deps/libtomcrypt/src/pk/ecc/ecc_set_key.c | 56 + .../src/pk/ecc/ecc_shared_secret.c | 66 + deps/libtomcrypt/src/pk/ecc/ecc_sign_hash.c | 181 + deps/libtomcrypt/src/pk/ecc/ecc_sizes.c | 36 + .../src/pk/ecc/ecc_ssh_ecdsa_encode_name.c | 65 + deps/libtomcrypt/src/pk/ecc/ecc_verify_hash.c | 206 + .../src/pk/ecc/ltc_ecc_export_point.c | 53 + .../src/pk/ecc/ltc_ecc_import_point.c | 61 + .../libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c | 62 + .../src/pk/ecc/ltc_ecc_is_point_at_infinity.c | 53 + deps/libtomcrypt/src/pk/ecc/ltc_ecc_map.c | 63 + deps/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c | 192 + deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c | 204 + .../src/pk/ecc/ltc_ecc_mulmod_timing.c | 151 + deps/libtomcrypt/src/pk/ecc/ltc_ecc_points.c | 61 + .../src/pk/ecc/ltc_ecc_projective_add_point.c | 198 + .../src/pk/ecc/ltc_ecc_projective_dbl_point.c | 182 + .../src/pk/ecc/ltc_ecc_verify_key.c | 59 + .../src/pk/ed25519/ed25519_export.c | 31 + .../src/pk/ed25519/ed25519_import.c | 35 + .../src/pk/ed25519/ed25519_import_pkcs8.c | 28 + .../src/pk/ed25519/ed25519_import_raw.c | 41 + .../src/pk/ed25519/ed25519_import_x509.c | 45 + .../src/pk/ed25519/ed25519_make_key.c | 36 + .../libtomcrypt/src/pk/ed25519/ed25519_sign.c | 126 + .../src/pk/ed25519/ed25519_verify.c | 134 + deps/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c | 39 + deps/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c | 96 + .../src/pk/pkcs1/pkcs_1_oaep_decode.c | 175 + .../src/pk/pkcs1/pkcs_1_oaep_encode.c | 163 + deps/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c | 24 + .../src/pk/pkcs1/pkcs_1_pss_decode.c | 166 + .../src/pk/pkcs1/pkcs_1_pss_encode.c | 164 + .../src/pk/pkcs1/pkcs_1_v1_5_decode.c | 102 + .../src/pk/pkcs1/pkcs_1_v1_5_encode.c | 105 + deps/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c | 94 + deps/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c | 92 + deps/libtomcrypt/src/pk/rsa/rsa_export.c | 91 + deps/libtomcrypt/src/pk/rsa/rsa_exptmod.c | 172 + deps/libtomcrypt/src/pk/rsa/rsa_get_size.c | 30 + deps/libtomcrypt/src/pk/rsa/rsa_import.c | 143 + .../libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c | 116 + deps/libtomcrypt/src/pk/rsa/rsa_import_x509.c | 54 + deps/libtomcrypt/src/pk/rsa/rsa_key.c | 103 + deps/libtomcrypt/src/pk/rsa/rsa_make_key.c | 165 + deps/libtomcrypt/src/pk/rsa/rsa_set.c | 123 + deps/libtomcrypt/src/pk/rsa/rsa_sign_hash.c | 136 + .../src/pk/rsa/rsa_sign_saltlen_get.c | 37 + deps/libtomcrypt/src/pk/rsa/rsa_verify_hash.c | 183 + .../libtomcrypt/src/pk/x25519/x25519_export.c | 31 + .../libtomcrypt/src/pk/x25519/x25519_import.c | 35 + .../src/pk/x25519/x25519_import_pkcs8.c | 28 + .../src/pk/x25519/x25519_import_raw.c | 41 + .../src/pk/x25519/x25519_import_x509.c | 45 + .../src/pk/x25519/x25519_make_key.c | 42 + .../src/pk/x25519/x25519_shared_secret.c | 42 + deps/libtomcrypt/src/prngs/chacha20.c | 218 + deps/libtomcrypt/src/prngs/fortuna.c | 520 + deps/libtomcrypt/src/prngs/rc4.c | 221 + deps/libtomcrypt/src/prngs/rng_get_bytes.c | 152 + deps/libtomcrypt/src/prngs/rng_make_prng.c | 81 + deps/libtomcrypt/src/prngs/sober128.c | 220 + deps/libtomcrypt/src/prngs/sprng.c | 152 + deps/libtomcrypt/src/prngs/yarrow.c | 323 + .../src/stream/chacha/chacha_crypt.c | 91 + .../src/stream/chacha/chacha_done.c | 20 + .../src/stream/chacha/chacha_ivctr32.c | 37 + .../src/stream/chacha/chacha_ivctr64.c | 37 + .../src/stream/chacha/chacha_keystream.c | 28 + .../src/stream/chacha/chacha_memory.c | 41 + .../src/stream/chacha/chacha_setup.c | 57 + .../src/stream/chacha/chacha_test.c | 74 + deps/libtomcrypt/src/stream/rabbit/rabbit.c | 447 + .../src/stream/rabbit/rabbit_memory.c | 40 + deps/libtomcrypt/src/stream/rc4/rc4_stream.c | 101 + .../src/stream/rc4/rc4_stream_memory.c | 31 + deps/libtomcrypt/src/stream/rc4/rc4_test.c | 33 + .../src/stream/salsa20/salsa20_crypt.c | 86 + .../src/stream/salsa20/salsa20_done.c | 20 + .../src/stream/salsa20/salsa20_ivctr64.c | 38 + .../src/stream/salsa20/salsa20_keystream.c | 29 + .../src/stream/salsa20/salsa20_memory.c | 35 + .../src/stream/salsa20/salsa20_setup.c | 59 + .../src/stream/salsa20/salsa20_test.c | 86 + .../src/stream/salsa20/xsalsa20_memory.c | 34 + .../src/stream/salsa20/xsalsa20_setup.c | 127 + .../src/stream/salsa20/xsalsa20_test.c | 90 + .../src/stream/sober128/sober128_stream.c | 333 + .../stream/sober128/sober128_stream_memory.c | 35 + .../src/stream/sober128/sober128_test.c | 43 + .../src/stream/sober128/sober128tab.c | 166 + .../src/stream/sosemanuk/sosemanuk.c | 807 ++ .../src/stream/sosemanuk/sosemanuk_memory.c | 35 + .../src/stream/sosemanuk/sosemanuk_test.c | 79 + deps/libtomcrypt/testme.sh | 71 + deps/libtomcrypt/tests/CMakeLists.txt | 71 + deps/libtomcrypt/tests/asn1/0x00.crt | Bin 0 -> 3298 bytes deps/libtomcrypt/tests/asn1/0x80.crt | Bin 0 -> 3298 bytes deps/libtomcrypt/tests/asn1/0xff.crt | Bin 0 -> 3298 bytes .../tests/asn1/illegal_padding1.crt | Bin 0 -> 17651 bytes .../tests/asn1/illegal_padding2.crt | Bin 0 -> 17651 bytes .../tests/asn1/illegal_padding3.crt | Bin 0 -> 17651 bytes .../tests/asn1/oid_overflow_test.der | Bin 0 -> 3127 bytes deps/libtomcrypt/tests/asn1/oid_size_test.der | Bin 0 -> 20533 bytes deps/libtomcrypt/tests/asn1/private.der | Bin 0 -> 18477 bytes deps/libtomcrypt/tests/asn1/root-ca.der | Bin 0 -> 8476 bytes deps/libtomcrypt/tests/asn1/type0x08.crt | Bin 0 -> 3298 bytes deps/libtomcrypt/tests/base16_test.c | 48 + deps/libtomcrypt/tests/base32_test.c | 51 + deps/libtomcrypt/tests/base64_test.c | 178 + deps/libtomcrypt/tests/bcrypt_test.c | 146 + deps/libtomcrypt/tests/cipher_hash_test.c | 50 + deps/libtomcrypt/tests/common.c | 166 + deps/libtomcrypt/tests/common.h | 43 + deps/libtomcrypt/tests/der_test.c | 2024 ++++ deps/libtomcrypt/tests/dh_test.c | 406 + deps/libtomcrypt/tests/dsa_test.c | 379 + deps/libtomcrypt/tests/ecc_test.c | 1601 +++ deps/libtomcrypt/tests/ed25519_test.c | 428 + deps/libtomcrypt/tests/file_test.c | 110 + deps/libtomcrypt/tests/mac_test.c | 54 + deps/libtomcrypt/tests/misc_test.c | 39 + deps/libtomcrypt/tests/modes_test.c | 120 + deps/libtomcrypt/tests/mpi_test.c | 144 + deps/libtomcrypt/tests/multi_test.c | 236 + .../tests/no_null_termination_check_test.c | 12 + deps/libtomcrypt/tests/no_prng.c | 182 + deps/libtomcrypt/tests/padding_test.c | 220 + deps/libtomcrypt/tests/pkcs_1_eme_test.c | 69 + deps/libtomcrypt/tests/pkcs_1_emsa_test.c | 63 + deps/libtomcrypt/tests/pkcs_1_oaep_test.c | 69 + deps/libtomcrypt/tests/pkcs_1_pss_test.c | 70 + deps/libtomcrypt/tests/pkcs_1_test.c | 96 + deps/libtomcrypt/tests/prng_test.c | 109 + deps/libtomcrypt/tests/rotate_test.c | 406 + deps/libtomcrypt/tests/rsa-pkcs8/README.txt | 29 + .../libtomcrypt/tests/rsa-pkcs8/key_pkcs8.der | Bin 0 -> 636 bytes .../tests/rsa-pkcs8/key_pkcs8_pbe_md2_des.der | Bin 0 -> 677 bytes .../rsa-pkcs8/key_pkcs8_pbe_md2_rc2_64.der | Bin 0 -> 677 bytes .../tests/rsa-pkcs8/key_pkcs8_pbe_md5_des.der | Bin 0 -> 677 bytes .../rsa-pkcs8/key_pkcs8_pbe_md5_rc2_64.der | Bin 0 -> 677 bytes .../rsa-pkcs8/key_pkcs8_pbe_sha1_3des.der | Bin 0 -> 678 bytes .../rsa-pkcs8/key_pkcs8_pbe_sha1_des.der | Bin 0 -> 677 bytes .../rsa-pkcs8/key_pkcs8_pbe_sha1_rc2_64.der | Bin 0 -> 677 bytes .../rsa-pkcs8/key_pkcs8_pbkdf2_des_cbc.der | Bin 0 -> 711 bytes .../key_pkcs8_pbkdf2_des_ede3_cbc.der | Bin 0 -> 714 bytes .../rsa-pkcs8/key_pkcs8_pbkdf2_rc2_cbc.der | Bin 0 -> 722 bytes .../key_pkcs8_pbkdf2_sha224_des_ede3_cbc.der | Bin 0 -> 728 bytes .../key_pkcs8_pbkdf2_sha256_des_ede3_cbc.der | Bin 0 -> 728 bytes .../key_pkcs8_pbkdf2_sha384_des_ede3_cbc.der | Bin 0 -> 728 bytes ...key_pkcs8_pbkdf2_sha512_224_aes256_cbc.der | Bin 0 -> 737 bytes ...key_pkcs8_pbkdf2_sha512_256_aes256_cbc.der | Bin 0 -> 737 bytes ...key_pkcs8_pbkdf2_sha512_256_rc2_40_cbc.der | Bin 0 -> 737 bytes ...key_pkcs8_pbkdf2_sha512_256_rc2_64_cbc.der | Bin 0 -> 736 bytes .../key_pkcs8_pbkdf2_sha512_aes128_cbc.der | Bin 0 -> 737 bytes .../key_pkcs8_pbkdf2_sha512_aes192_cbc.der | Bin 0 -> 737 bytes .../key_pkcs8_pbkdf2_sha512_aes256_cbc.der | Bin 0 -> 737 bytes .../key_pkcs8_pbkdf2_sha512_des_ede3_cbc.der | Bin 0 -> 728 bytes .../key_pkcs8_pbkdf2_sha512_rc2_40_cbc.der | Bin 0 -> 737 bytes .../key_pkcs8_pbkdf2_sha512_rc2_64_cbc.der | Bin 0 -> 736 bytes .../tests/rsa/rsa_size_1024_bits.der | Bin 0 -> 1293 bytes .../tests/rsa/rsa_size_16384_bits.der | Bin 0 -> 5141 bytes .../tests/rsa/rsa_size_1999_bits.der | Bin 0 -> 1539 bytes .../tests/rsa/rsa_size_2048_bits.der | Bin 0 -> 1554 bytes .../tests/rsa/rsa_size_4096_bits.der | Bin 0 -> 2066 bytes .../tests/rsa/rsa_size_512_bits.der | Bin 0 -> 1157 bytes .../tests/rsa/rsa_size_8192_bits.der | Bin 0 -> 3090 bytes deps/libtomcrypt/tests/rsa_test.c | 762 ++ deps/libtomcrypt/tests/sources.cmake | 35 + deps/libtomcrypt/tests/ssh_test.c | 356 + deps/libtomcrypt/tests/store_test.c | 76 + deps/libtomcrypt/tests/test.c | 435 + deps/libtomcrypt/tests/test.der | Bin 0 -> 162 bytes deps/libtomcrypt/tests/test.key | 15 + deps/libtomcrypt/tests/test_dsa.key | 12 + deps/libtomcrypt/tests/tomcrypt_test.h | 52 + deps/libtomcrypt/tests/x25519_test.c | 250 + deps/libtomcrypt/updatemakes.sh | 16 + deps/libtommath | 1 - deps/libtommath/.gitattributes | 5 + deps/libtommath/.github/workflows/deploy.yml | 47 + deps/libtommath/.github/workflows/main.yml | 202 + deps/libtommath/.gitignore | 123 + deps/libtommath/CMakeLists.txt | 288 + deps/libtommath/LICENSE | 26 + deps/libtommath/Package.swift | 40 + deps/libtommath/README.md | 58 + deps/libtommath/appveyor.yml | 26 + deps/libtommath/astylerc | 30 + deps/libtommath/changes.txt | 497 + deps/libtommath/demo/CMakeLists.txt | 66 + deps/libtommath/demo/mtest_opponent.c | 441 + deps/libtommath/demo/s_mp_rand_jenkins.c | 55 + deps/libtommath/demo/shared.c | 49 + deps/libtommath/demo/shared.h | 27 + deps/libtommath/demo/test.c | 2553 ++++ deps/libtommath/demo/timing.c | 429 + deps/libtommath/demo/tommath_tests.swift | 94 + deps/libtommath/doc/.latexindent.yaml | 35 + deps/libtommath/doc/bn.tex | 2749 +++++ deps/libtommath/doc/makefile | 49 + deps/libtommath/etc/2kprime.1 | 2 + deps/libtommath/etc/2kprime.c | 81 + deps/libtommath/etc/drprime.c | 67 + deps/libtommath/etc/drprimes.28 | 25 + deps/libtommath/etc/drprimes.txt | 9 + deps/libtommath/etc/makefile | 43 + deps/libtommath/etc/makefile.icc | 67 + deps/libtommath/etc/makefile.msvc | 24 + deps/libtommath/etc/mersenne.c | 138 + deps/libtommath/etc/mont.c | 44 + deps/libtommath/etc/pprime.c | 411 + deps/libtommath/etc/prime.1024 | 414 + deps/libtommath/etc/prime.512 | 205 + deps/libtommath/etc/timer.asm | 37 + deps/libtommath/etc/tune.c | 544 + deps/libtommath/etc/tune_it.sh | 106 + deps/libtommath/helper.pl | 500 + deps/libtommath/libtommath.pc.in | 9 + deps/libtommath/libtommath_VS2008.sln | 29 + deps/libtommath/libtommath_VS2008.vcproj | 966 ++ deps/libtommath/logs/Makefile | 9 + deps/libtommath/logs/README | 13 + deps/libtommath/logs/before_after.dem | 36 + deps/libtommath/logs/before_after.html | 28 + deps/libtommath/logs/graphs.dem | 16 + deps/libtommath/logs/index.html | 24 + deps/libtommath/makefile | 207 + deps/libtommath/makefile.mingw | 99 + deps/libtommath/makefile.msvc | 102 + deps/libtommath/makefile.shared | 100 + deps/libtommath/makefile.unix | 97 + deps/libtommath/makefile_include.mk | 180 + deps/libtommath/modulemap/module.modulemap | 4 + deps/libtommath/mp_2expt.c | 31 + deps/libtommath/mp_abs.c | 24 + deps/libtommath/mp_add.c | 29 + deps/libtommath/mp_add_d.c | 86 + deps/libtommath/mp_addmod.c | 15 + deps/libtommath/mp_and.c | 54 + deps/libtommath/mp_clamp.c | 27 + deps/libtommath/mp_clear.c | 20 + deps/libtommath/mp_clear_multi.c | 18 + deps/libtommath/mp_cmp.c | 21 + deps/libtommath/mp_cmp_d.c | 26 + deps/libtommath/mp_cmp_mag.c | 25 + deps/libtommath/mp_cnt_lsb.c | 38 + deps/libtommath/mp_complement.c | 13 + deps/libtommath/mp_copy.c | 29 + deps/libtommath/mp_count_bits.c | 28 + deps/libtommath/mp_cutoffs.c | 14 + deps/libtommath/mp_div.c | 42 + deps/libtommath/mp_div_2.c | 40 + deps/libtommath/mp_div_2d.c | 61 + deps/libtommath/mp_div_d.c | 84 + deps/libtommath/mp_dr_is_modulus.c | 27 + deps/libtommath/mp_dr_reduce.c | 68 + deps/libtommath/mp_dr_setup.c | 15 + deps/libtommath/mp_error_to_string.c | 29 + deps/libtommath/mp_exch.c | 13 + deps/libtommath/mp_expt_n.c | 43 + deps/libtommath/mp_exptmod.c | 78 + deps/libtommath/mp_exteuclid.c | 72 + deps/libtommath/mp_fread.c | 66 + deps/libtommath/mp_from_sbin.c | 21 + deps/libtommath/mp_from_ubin.c | 30 + deps/libtommath/mp_fwrite.c | 34 + deps/libtommath/mp_gcd.c | 92 + deps/libtommath/mp_get_double.c | 18 + deps/libtommath/mp_get_i32.c | 7 + deps/libtommath/mp_get_i64.c | 7 + deps/libtommath/mp_get_l.c | 7 + deps/libtommath/mp_get_mag_u32.c | 7 + deps/libtommath/mp_get_mag_u64.c | 7 + deps/libtommath/mp_get_mag_ul.c | 7 + deps/libtommath/mp_grow.c | 40 + deps/libtommath/mp_hash.c | 36 + deps/libtommath/mp_init.c | 23 + deps/libtommath/mp_init_copy.c | 21 + deps/libtommath/mp_init_i32.c | 7 + deps/libtommath/mp_init_i64.c | 7 + deps/libtommath/mp_init_l.c | 7 + deps/libtommath/mp_init_multi.c | 41 + deps/libtommath/mp_init_set.c | 16 + deps/libtommath/mp_init_size.c | 28 + deps/libtommath/mp_init_u32.c | 7 + deps/libtommath/mp_init_u64.c | 7 + deps/libtommath/mp_init_ul.c | 7 + deps/libtommath/mp_invmod.c | 29 + deps/libtommath/mp_is_square.c | 94 + deps/libtommath/mp_kronecker.c | 129 + deps/libtommath/mp_lcm.c | 44 + deps/libtommath/mp_log.c | 168 + deps/libtommath/mp_log_n.c | 19 + deps/libtommath/mp_lshd.c | 42 + deps/libtommath/mp_mod.c | 15 + deps/libtommath/mp_mod_2d.c | 40 + .../mp_montgomery_calc_normalization.c | 43 + deps/libtommath/mp_montgomery_reduce.c | 89 + deps/libtommath/mp_montgomery_setup.c | 40 + deps/libtommath/mp_mul.c | 68 + deps/libtommath/mp_mul_2.c | 53 + deps/libtommath/mp_mul_2d.c | 63 + deps/libtommath/mp_mul_d.c | 68 + deps/libtommath/mp_mulmod.c | 15 + deps/libtommath/mp_neg.c | 18 + deps/libtommath/mp_or.c | 54 + deps/libtommath/mp_pack.c | 69 + deps/libtommath/mp_pack_count.c | 12 + deps/libtommath/mp_prime_fermat.c | 41 + .../libtommath/mp_prime_frobenius_underwood.c | 127 + deps/libtommath/mp_prime_is_prime.c | 282 + deps/libtommath/mp_prime_miller_rabin.c | 91 + deps/libtommath/mp_prime_next_prime.c | 127 + .../libtommath/mp_prime_rabin_miller_trials.c | 48 + deps/libtommath/mp_prime_rand.c | 123 + .../mp_prime_strong_lucas_selfridge.c | 281 + deps/libtommath/mp_radix_size.c | 34 + deps/libtommath/mp_radix_size_overestimate.c | 17 + deps/libtommath/mp_rand.c | 39 + deps/libtommath/mp_rand_source.c | 12 + deps/libtommath/mp_read_radix.c | 69 + deps/libtommath/mp_reduce.c | 83 + deps/libtommath/mp_reduce_2k.c | 49 + deps/libtommath/mp_reduce_2k_l.c | 52 + deps/libtommath/mp_reduce_2k_setup.c | 30 + deps/libtommath/mp_reduce_2k_setup_l.c | 28 + deps/libtommath/mp_reduce_is_2k.c | 34 + deps/libtommath/mp_reduce_is_2k_l.c | 27 + deps/libtommath/mp_reduce_setup.c | 17 + deps/libtommath/mp_root_n.c | 141 + deps/libtommath/mp_rshd.c | 43 + deps/libtommath/mp_sbin_size.c | 11 + deps/libtommath/mp_set.c | 15 + deps/libtommath/mp_set_double.c | 47 + deps/libtommath/mp_set_i32.c | 7 + deps/libtommath/mp_set_i64.c | 7 + deps/libtommath/mp_set_l.c | 7 + deps/libtommath/mp_set_u32.c | 7 + deps/libtommath/mp_set_u64.c | 7 + deps/libtommath/mp_set_ul.c | 7 + deps/libtommath/mp_shrink.c | 22 + deps/libtommath/mp_signed_rsh.c | 21 + deps/libtommath/mp_sqrmod.c | 15 + deps/libtommath/mp_sqrt.c | 67 + deps/libtommath/mp_sqrtmod_prime.c | 133 + deps/libtommath/mp_sub.c | 36 + deps/libtommath/mp_sub_d.c | 78 + deps/libtommath/mp_submod.c | 15 + deps/libtommath/mp_to_radix.c | 95 + deps/libtommath/mp_to_sbin.c | 22 + deps/libtommath/mp_to_ubin.c | 37 + deps/libtommath/mp_ubin_size.c | 12 + deps/libtommath/mp_unpack.c | 49 + deps/libtommath/mp_xor.c | 54 + deps/libtommath/mp_zero.c | 13 + deps/libtommath/s_mp_add.c | 70 + deps/libtommath/s_mp_copy_digs.c | 23 + deps/libtommath/s_mp_div_3.c | 64 + deps/libtommath/s_mp_div_recursive.c | 159 + deps/libtommath/s_mp_div_school.c | 159 + deps/libtommath/s_mp_div_small.c | 51 + deps/libtommath/s_mp_exptmod.c | 198 + deps/libtommath/s_mp_exptmod_fast.c | 254 + deps/libtommath/s_mp_fp_log.c | 83 + deps/libtommath/s_mp_fp_log_d.c | 83 + deps/libtommath/s_mp_get_bit.c | 21 + deps/libtommath/s_mp_invmod.c | 117 + deps/libtommath/s_mp_invmod_odd.c | 113 + deps/libtommath/s_mp_log_2expt.c | 12 + .../libtommath/s_mp_montgomery_reduce_comba.c | 119 + deps/libtommath/s_mp_mul.c | 61 + deps/libtommath/s_mp_mul_balance.c | 71 + deps/libtommath/s_mp_mul_comba.c | 78 + deps/libtommath/s_mp_mul_high.c | 52 + deps/libtommath/s_mp_mul_high_comba.c | 70 + deps/libtommath/s_mp_mul_karatsuba.c | 151 + deps/libtommath/s_mp_mul_toom.c | 202 + deps/libtommath/s_mp_prime_is_divisible.c | 33 + deps/libtommath/s_mp_prime_tab.c | 44 + deps/libtommath/s_mp_radix_map.c | 19 + .../libtommath/s_mp_radix_size_overestimate.c | 82 + deps/libtommath/s_mp_rand_platform.c | 149 + deps/libtommath/s_mp_sqr.c | 78 + deps/libtommath/s_mp_sqr_comba.c | 87 + deps/libtommath/s_mp_sqr_karatsuba.c | 92 + deps/libtommath/s_mp_sqr_toom.c | 133 + deps/libtommath/s_mp_sub.c | 56 + deps/libtommath/s_mp_zero_buf.c | 22 + deps/libtommath/s_mp_zero_digs.c | 23 + deps/libtommath/sources.cmake | 170 + deps/libtommath/testme.sh | 445 + deps/libtommath/tommath.def | 133 + deps/libtommath/tommath.h | 599 + deps/libtommath/tommath_c89.h | 41 + deps/libtommath/tommath_class.h | 1298 ++ deps/libtommath/tommath_cutoffs.h | 13 + deps/libtommath/tommath_private.h | 300 + deps/libtommath/tommath_superclass.h | 113 + deps/minhook | 1 - deps/minhook/.editorconfig | 22 + deps/minhook/.gitignore | 44 + deps/minhook/AUTHORS.txt | 8 + deps/minhook/CMakeLists.txt | 141 + deps/minhook/LICENSE.txt | 81 + deps/minhook/README.md | 87 + deps/minhook/cmake/minhook-config.cmake.in | 39 + deps/minhook/dll_resources/MinHook.def | 14 + deps/minhook/dll_resources/MinHook.rc | 32 + deps/minhook/include/MinHook.h | 185 + deps/minhook/src/buffer.c | 312 + deps/minhook/src/buffer.h | 42 + deps/minhook/src/hde/hde32.c | 324 + deps/minhook/src/hde/hde32.h | 105 + deps/minhook/src/hde/hde64.c | 335 + deps/minhook/src/hde/hde64.h | 112 + deps/minhook/src/hde/pstdint.h | 39 + deps/minhook/src/hde/table32.h | 73 + deps/minhook/src/hde/table64.h | 74 + deps/minhook/src/hook.c | 923 ++ deps/minhook/src/trampoline.c | 321 + deps/minhook/src/trampoline.h | 105 + deps/rapidjson | 1 - deps/rapidjson/.gitattributes | 22 + deps/rapidjson/.gitignore | 29 + deps/rapidjson/.gitmodules | 3 + deps/rapidjson/.travis.yml | 166 + deps/rapidjson/CHANGELOG.md | 158 + deps/rapidjson/CMakeLists.txt | 251 + .../rapidjson/CMakeModules/FindGTestSrc.cmake | 30 + deps/rapidjson/RapidJSON.pc.in | 7 + deps/rapidjson/RapidJSONConfig.cmake.in | 25 + .../rapidjson/RapidJSONConfigVersion.cmake.in | 10 + deps/rapidjson/appveyor.yml | 102 + deps/rapidjson/bin/data/abcde.txt | 1 + deps/rapidjson/bin/data/glossary.json | Bin 0 -> 603 bytes deps/rapidjson/bin/data/menu.json | Bin 0 -> 898 bytes deps/rapidjson/bin/data/readme.txt | 1 + deps/rapidjson/bin/data/sample.json | Bin 0 -> 687491 bytes deps/rapidjson/bin/data/webapp.json | Bin 0 -> 3554 bytes deps/rapidjson/bin/data/widget.json | Bin 0 -> 626 bytes deps/rapidjson/bin/encodings/utf16be.json | Bin 0 -> 368 bytes deps/rapidjson/bin/encodings/utf16bebom.json | Bin 0 -> 370 bytes deps/rapidjson/bin/encodings/utf16le.json | Bin 0 -> 368 bytes deps/rapidjson/bin/encodings/utf16lebom.json | Bin 0 -> 370 bytes deps/rapidjson/bin/encodings/utf32be.json | Bin 0 -> 736 bytes deps/rapidjson/bin/encodings/utf32bebom.json | Bin 0 -> 740 bytes deps/rapidjson/bin/encodings/utf32le.json | Bin 0 -> 736 bytes deps/rapidjson/bin/encodings/utf32lebom.json | Bin 0 -> 740 bytes deps/rapidjson/bin/encodings/utf8.json | Bin 0 -> 322 bytes deps/rapidjson/bin/encodings/utf8bom.json | Bin 0 -> 325 bytes deps/rapidjson/bin/jsonchecker/fail1.json | Bin 0 -> 60 bytes deps/rapidjson/bin/jsonchecker/fail10.json | Bin 0 -> 58 bytes deps/rapidjson/bin/jsonchecker/fail11.json | Bin 0 -> 29 bytes deps/rapidjson/bin/jsonchecker/fail12.json | Bin 0 -> 31 bytes deps/rapidjson/bin/jsonchecker/fail13.json | Bin 0 -> 43 bytes deps/rapidjson/bin/jsonchecker/fail14.json | Bin 0 -> 31 bytes deps/rapidjson/bin/jsonchecker/fail15.json | Bin 0 -> 34 bytes deps/rapidjson/bin/jsonchecker/fail16.json | Bin 0 -> 8 bytes deps/rapidjson/bin/jsonchecker/fail17.json | Bin 0 -> 34 bytes deps/rapidjson/bin/jsonchecker/fail18.json | Bin 0 -> 50 bytes deps/rapidjson/bin/jsonchecker/fail19.json | Bin 0 -> 22 bytes deps/rapidjson/bin/jsonchecker/fail2.json | Bin 0 -> 17 bytes deps/rapidjson/bin/jsonchecker/fail20.json | Bin 0 -> 23 bytes deps/rapidjson/bin/jsonchecker/fail21.json | Bin 0 -> 32 bytes deps/rapidjson/bin/jsonchecker/fail22.json | Bin 0 -> 33 bytes deps/rapidjson/bin/jsonchecker/fail23.json | Bin 0 -> 20 bytes deps/rapidjson/bin/jsonchecker/fail24.json | Bin 0 -> 16 bytes deps/rapidjson/bin/jsonchecker/fail25.json | Bin 0 -> 29 bytes deps/rapidjson/bin/jsonchecker/fail26.json | Bin 0 -> 38 bytes deps/rapidjson/bin/jsonchecker/fail27.json | Bin 0 -> 14 bytes deps/rapidjson/bin/jsonchecker/fail28.json | Bin 0 -> 15 bytes deps/rapidjson/bin/jsonchecker/fail29.json | Bin 0 -> 4 bytes deps/rapidjson/bin/jsonchecker/fail3.json | Bin 0 -> 37 bytes deps/rapidjson/bin/jsonchecker/fail30.json | Bin 0 -> 5 bytes deps/rapidjson/bin/jsonchecker/fail31.json | Bin 0 -> 7 bytes deps/rapidjson/bin/jsonchecker/fail32.json | Bin 0 -> 40 bytes deps/rapidjson/bin/jsonchecker/fail33.json | Bin 0 -> 12 bytes deps/rapidjson/bin/jsonchecker/fail4.json | Bin 0 -> 16 bytes deps/rapidjson/bin/jsonchecker/fail5.json | Bin 0 -> 24 bytes deps/rapidjson/bin/jsonchecker/fail6.json | Bin 0 -> 26 bytes deps/rapidjson/bin/jsonchecker/fail7.json | Bin 0 -> 26 bytes deps/rapidjson/bin/jsonchecker/fail8.json | Bin 0 -> 16 bytes deps/rapidjson/bin/jsonchecker/fail9.json | Bin 0 -> 22 bytes deps/rapidjson/bin/jsonchecker/pass1.json | Bin 0 -> 1441 bytes deps/rapidjson/bin/jsonchecker/pass2.json | Bin 0 -> 52 bytes deps/rapidjson/bin/jsonchecker/pass3.json | Bin 0 -> 148 bytes deps/rapidjson/bin/jsonchecker/readme.txt | 3 + deps/rapidjson/bin/types/alotofkeys.json | Bin 0 -> 30003 bytes deps/rapidjson/bin/types/booleans.json | Bin 0 -> 849 bytes deps/rapidjson/bin/types/floats.json | Bin 0 -> 1698 bytes deps/rapidjson/bin/types/guids.json | Bin 0 -> 4202 bytes deps/rapidjson/bin/types/integers.json | Bin 0 -> 1098 bytes deps/rapidjson/bin/types/mixed.json | Bin 0 -> 15142 bytes deps/rapidjson/bin/types/nulls.json | Bin 0 -> 802 bytes deps/rapidjson/bin/types/paragraphs.json | Bin 0 -> 33764 bytes deps/rapidjson/bin/types/readme.txt | 1 + .../rapidjson/bin/unittestschema/address.json | Bin 0 -> 3150 bytes .../bin/unittestschema/allOf_address.json | Bin 0 -> 84 bytes .../bin/unittestschema/anyOf_address.json | Bin 0 -> 84 bytes .../bin/unittestschema/idandref.json | Bin 0 -> 1315 bytes .../bin/unittestschema/oneOf_address.json | Bin 0 -> 84 bytes deps/rapidjson/contrib/natvis/LICENSE | 45 + deps/rapidjson/contrib/natvis/README.md | 7 + .../rapidjson/contrib/natvis/rapidjson.natvis | 38 + deps/rapidjson/doc/CMakeLists.txt | 27 + deps/rapidjson/doc/Doxyfile.in | 2369 ++++ deps/rapidjson/doc/Doxyfile.zh-cn.in | 2369 ++++ deps/rapidjson/doc/diagram/architecture.dot | 50 + deps/rapidjson/doc/diagram/architecture.png | Bin 0 -> 16569 bytes deps/rapidjson/doc/diagram/insituparsing.dot | 65 + deps/rapidjson/doc/diagram/insituparsing.png | Bin 0 -> 37281 bytes .../iterative-parser-states-diagram.dot | 62 + .../iterative-parser-states-diagram.png | Bin 0 -> 92378 bytes deps/rapidjson/doc/diagram/move1.dot | 47 + deps/rapidjson/doc/diagram/move1.png | Bin 0 -> 16081 bytes deps/rapidjson/doc/diagram/move2.dot | 62 + deps/rapidjson/doc/diagram/move2.png | Bin 0 -> 41517 bytes deps/rapidjson/doc/diagram/move3.dot | 60 + deps/rapidjson/doc/diagram/move3.png | Bin 0 -> 36371 bytes deps/rapidjson/doc/diagram/normalparsing.dot | 56 + deps/rapidjson/doc/diagram/normalparsing.png | Bin 0 -> 32887 bytes deps/rapidjson/doc/diagram/simpledom.dot | 54 + deps/rapidjson/doc/diagram/simpledom.png | Bin 0 -> 43670 bytes deps/rapidjson/doc/diagram/tutorial.dot | 58 + deps/rapidjson/doc/diagram/tutorial.png | Bin 0 -> 44634 bytes deps/rapidjson/doc/diagram/utilityclass.dot | 73 + deps/rapidjson/doc/diagram/utilityclass.png | Bin 0 -> 99993 bytes deps/rapidjson/doc/dom.md | 281 + deps/rapidjson/doc/dom.zh-cn.md | 285 + deps/rapidjson/doc/encoding.md | 146 + deps/rapidjson/doc/encoding.zh-cn.md | 152 + deps/rapidjson/doc/faq.md | 289 + deps/rapidjson/doc/faq.zh-cn.md | 290 + deps/rapidjson/doc/features.md | 106 + deps/rapidjson/doc/features.zh-cn.md | 103 + deps/rapidjson/doc/internals.md | 368 + deps/rapidjson/doc/internals.zh-cn.md | 363 + deps/rapidjson/doc/logo/rapidjson.png | Bin 0 -> 5259 bytes deps/rapidjson/doc/logo/rapidjson.svg | 119 + deps/rapidjson/doc/misc/DoxygenLayout.xml | 194 + deps/rapidjson/doc/misc/doxygenextra.css | 274 + deps/rapidjson/doc/misc/footer.html | 11 + deps/rapidjson/doc/misc/header.html | 24 + deps/rapidjson/doc/npm.md | 31 + deps/rapidjson/doc/performance.md | 26 + deps/rapidjson/doc/performance.zh-cn.md | 26 + deps/rapidjson/doc/pointer.md | 234 + deps/rapidjson/doc/pointer.zh-cn.md | 234 + deps/rapidjson/doc/sax.md | 509 + deps/rapidjson/doc/sax.zh-cn.md | 487 + deps/rapidjson/doc/schema.md | 513 + deps/rapidjson/doc/schema.zh-cn.md | 237 + deps/rapidjson/doc/stream.md | 429 + deps/rapidjson/doc/stream.zh-cn.md | 429 + deps/rapidjson/doc/tutorial.md | 536 + deps/rapidjson/doc/tutorial.zh-cn.md | 535 + deps/rapidjson/docker/debian/Dockerfile | 8 + deps/rapidjson/example/CMakeLists.txt | 46 + deps/rapidjson/example/archiver/archiver.cpp | 292 + deps/rapidjson/example/archiver/archiver.h | 145 + .../example/archiver/archivertest.cpp | 287 + .../example/capitalize/capitalize.cpp | 67 + deps/rapidjson/example/condense/condense.cpp | 32 + .../rapidjson/example/filterkey/filterkey.cpp | 135 + .../example/filterkeydom/filterkeydom.cpp | 170 + deps/rapidjson/example/jsonx/jsonx.cpp | 207 + .../lookaheadparser/lookaheadparser.cpp | 350 + .../example/messagereader/messagereader.cpp | 105 + .../example/parsebyparts/parsebyparts.cpp | 176 + deps/rapidjson/example/pretty/pretty.cpp | 30 + .../example/prettyauto/prettyauto.cpp | 56 + .../schemavalidator/schemavalidator.cpp | 199 + .../rapidjson/example/serialize/serialize.cpp | 173 + .../rapidjson/example/simpledom/simpledom.cpp | 29 + .../simplepullreader/simplepullreader.cpp | 53 + .../example/simplereader/simplereader.cpp | 42 + .../example/simplewriter/simplewriter.cpp | 36 + deps/rapidjson/example/sortkeys/sortkeys.cpp | 62 + deps/rapidjson/example/traverseaspointer.cpp | 39 + deps/rapidjson/example/tutorial/tutorial.cpp | 151 + deps/rapidjson/include/rapidjson/allocators.h | 693 ++ .../include/rapidjson/cursorstreamwrapper.h | 78 + deps/rapidjson/include/rapidjson/document.h | 3043 +++++ .../include/rapidjson/encodedstream.h | 299 + deps/rapidjson/include/rapidjson/encodings.h | 716 ++ deps/rapidjson/include/rapidjson/error/en.h | 176 + .../rapidjson/include/rapidjson/error/error.h | 285 + .../include/rapidjson/filereadstream.h | 99 + .../include/rapidjson/filewritestream.h | 104 + deps/rapidjson/include/rapidjson/fwd.h | 151 + .../include/rapidjson/internal/biginteger.h | 297 + .../include/rapidjson/internal/clzll.h | 71 + .../include/rapidjson/internal/diyfp.h | 261 + .../include/rapidjson/internal/dtoa.h | 249 + .../include/rapidjson/internal/ieee754.h | 78 + .../include/rapidjson/internal/itoa.h | 308 + .../include/rapidjson/internal/meta.h | 186 + .../include/rapidjson/internal/pow10.h | 55 + .../include/rapidjson/internal/regex.h | 739 ++ .../include/rapidjson/internal/stack.h | 232 + .../include/rapidjson/internal/strfunc.h | 83 + .../include/rapidjson/internal/strtod.h | 293 + .../include/rapidjson/internal/swap.h | 46 + .../include/rapidjson/istreamwrapper.h | 128 + .../include/rapidjson/memorybuffer.h | 70 + .../include/rapidjson/memorystream.h | 71 + .../include/rapidjson/msinttypes/inttypes.h | 316 + .../include/rapidjson/msinttypes/stdint.h | 300 + .../include/rapidjson/ostreamwrapper.h | 81 + deps/rapidjson/include/rapidjson/pointer.h | 1476 +++ .../include/rapidjson/prettywriter.h | 277 + deps/rapidjson/include/rapidjson/rapidjson.h | 741 ++ deps/rapidjson/include/rapidjson/reader.h | 2246 ++++ deps/rapidjson/include/rapidjson/schema.h | 3262 +++++ deps/rapidjson/include/rapidjson/stream.h | 223 + .../include/rapidjson/stringbuffer.h | 121 + deps/rapidjson/include/rapidjson/uri.h | 481 + deps/rapidjson/include/rapidjson/writer.h | 710 ++ deps/rapidjson/include_dirs.js | 2 + deps/rapidjson/library.json | Bin 0 -> 355 bytes deps/rapidjson/license.txt | 57 + deps/rapidjson/package.json | Bin 0 -> 561 bytes deps/rapidjson/rapidjson.autopkg | 77 + deps/rapidjson/readme.md | 210 + deps/rapidjson/readme.zh-cn.md | 152 + deps/rapidjson/test/CMakeLists.txt | 20 + deps/rapidjson/test/perftest/CMakeLists.txt | 28 + deps/rapidjson/test/perftest/misctest.cpp | 974 ++ deps/rapidjson/test/perftest/perftest.cpp | 24 + deps/rapidjson/test/perftest/perftest.h | 186 + deps/rapidjson/test/perftest/platformtest.cpp | 166 + .../rapidjson/test/perftest/rapidjsontest.cpp | 564 + deps/rapidjson/test/perftest/schematest.cpp | 223 + deps/rapidjson/test/unittest/CMakeLists.txt | 95 + .../test/unittest/allocatorstest.cpp | 292 + .../test/unittest/bigintegertest.cpp | 138 + deps/rapidjson/test/unittest/clzlltest.cpp | 34 + .../test/unittest/cursorstreamwrappertest.cpp | 115 + deps/rapidjson/test/unittest/documenttest.cpp | 674 ++ deps/rapidjson/test/unittest/dtoatest.cpp | 99 + .../test/unittest/encodedstreamtest.cpp | 313 + .../rapidjson/test/unittest/encodingstest.cpp | 451 + .../test/unittest/filestreamtest.cpp | 155 + deps/rapidjson/test/unittest/fwdtest.cpp | 230 + .../test/unittest/istreamwrappertest.cpp | 181 + deps/rapidjson/test/unittest/itoatest.cpp | 160 + .../test/unittest/jsoncheckertest.cpp | 143 + .../rapidjson/test/unittest/namespacetest.cpp | 70 + .../test/unittest/ostreamwrappertest.cpp | 92 + deps/rapidjson/test/unittest/platformtest.cpp | 40 + deps/rapidjson/test/unittest/pointertest.cpp | 1730 +++ .../test/unittest/prettywritertest.cpp | 373 + deps/rapidjson/test/unittest/readertest.cpp | 2370 ++++ deps/rapidjson/test/unittest/regextest.cpp | 639 + deps/rapidjson/test/unittest/schematest.cpp | 3575 ++++++ deps/rapidjson/test/unittest/simdtest.cpp | 219 + deps/rapidjson/test/unittest/strfunctest.cpp | 30 + .../test/unittest/stringbuffertest.cpp | 192 + deps/rapidjson/test/unittest/strtodtest.cpp | 132 + deps/rapidjson/test/unittest/unittest.cpp | 51 + deps/rapidjson/test/unittest/unittest.h | 143 + deps/rapidjson/test/unittest/uritest.cpp | 725 ++ deps/rapidjson/test/unittest/valuetest.cpp | 1861 +++ deps/rapidjson/test/unittest/writertest.cpp | 598 + deps/rapidjson/test/valgrind.supp | 26 + deps/rapidjson/thirdparty/gtest/.gitignore | 40 + deps/rapidjson/thirdparty/gtest/.travis.yml | 81 + deps/rapidjson/thirdparty/gtest/BUILD.bazel | 175 + .../rapidjson/thirdparty/gtest/CMakeLists.txt | 33 + .../thirdparty/gtest/CONTRIBUTING.md | 160 + deps/rapidjson/thirdparty/gtest/LICENSE | 28 + deps/rapidjson/thirdparty/gtest/Makefile.am | 14 + deps/rapidjson/thirdparty/gtest/README.md | 122 + deps/rapidjson/thirdparty/gtest/WORKSPACE | 8 + deps/rapidjson/thirdparty/gtest/appveyor.yml | 104 + .../gtest/ci/build-linux-autotools.sh | 44 + .../thirdparty/gtest/ci/build-linux-bazel.sh | 36 + .../thirdparty/gtest/ci/env-linux.sh | 41 + deps/rapidjson/thirdparty/gtest/ci/env-osx.sh | 40 + .../thirdparty/gtest/ci/get-nprocessors.sh | 48 + .../thirdparty/gtest/ci/install-linux.sh | 49 + .../thirdparty/gtest/ci/install-osx.sh | 39 + .../thirdparty/gtest/ci/log-config.sh | 51 + deps/rapidjson/thirdparty/gtest/ci/travis.sh | 44 + deps/rapidjson/thirdparty/gtest/configure.ac | 16 + .../thirdparty/gtest/googlemock/CHANGES | 126 + .../gtest/googlemock/CMakeLists.txt | 242 + .../thirdparty/gtest/googlemock/CONTRIBUTORS | 40 + .../thirdparty/gtest/googlemock/LICENSE | 28 + .../thirdparty/gtest/googlemock/Makefile.am | 224 + .../thirdparty/gtest/googlemock/README.md | 344 + .../gtest/googlemock/cmake/gmock.pc.in | 9 + .../gtest/googlemock/cmake/gmock_main.pc.in | 9 + .../thirdparty/gtest/googlemock/configure.ac | 146 + .../gtest/googlemock/docs/CheatSheet.md | 564 + .../gtest/googlemock/docs/CookBook.md | 3660 ++++++ .../gtest/googlemock/docs/DesignDoc.md | 280 + .../gtest/googlemock/docs/Documentation.md | 15 + .../gtest/googlemock/docs/ForDummies.md | 447 + .../docs/FrequentlyAskedQuestions.md | 627 + .../gtest/googlemock/docs/KnownIssues.md | 19 + .../googlemock/include/gmock/gmock-actions.h | 1262 ++ .../include/gmock/gmock-cardinalities.h | 147 + .../include/gmock/gmock-generated-actions.h | 2571 ++++ .../gmock/gmock-generated-actions.h.pump | 833 ++ .../gmock/gmock-generated-function-mockers.h | 1379 +++ .../gmock-generated-function-mockers.h.pump | 347 + .../include/gmock/gmock-generated-matchers.h | 2258 ++++ .../gmock/gmock-generated-matchers.h.pump | 675 ++ .../gmock/gmock-generated-nice-strict.h | 458 + .../gmock/gmock-generated-nice-strict.h.pump | 178 + .../googlemock/include/gmock/gmock-matchers.h | 5255 ++++++++ .../include/gmock/gmock-more-actions.h | 246 + .../include/gmock/gmock-more-matchers.h | 91 + .../include/gmock/gmock-spec-builders.h | 1918 +++ .../gtest/googlemock/include/gmock/gmock.h | 95 + .../internal/custom/gmock-generated-actions.h | 8 + .../custom/gmock-generated-actions.h.pump | 10 + .../gmock/internal/custom/gmock-matchers.h | 38 + .../gmock/internal/custom/gmock-port.h | 46 + .../internal/gmock-generated-internal-utils.h | 286 + .../gmock-generated-internal-utils.h.pump | 136 + .../gmock/internal/gmock-internal-utils.h | 574 + .../include/gmock/internal/gmock-port.h | 87 + .../gtest/googlemock/msvc/2005/gmock.sln | 32 + .../gtest/googlemock/msvc/2005/gmock.vcproj | 191 + .../googlemock/msvc/2005/gmock_config.vsprops | 15 + .../googlemock/msvc/2005/gmock_main.vcproj | 187 + .../googlemock/msvc/2005/gmock_test.vcproj | 201 + .../gtest/googlemock/msvc/2010/gmock.sln | 46 + .../gtest/googlemock/msvc/2010/gmock.vcxproj | 145 + .../googlemock/msvc/2010/gmock_config.props | 19 + .../googlemock/msvc/2010/gmock_main.vcxproj | 151 + .../googlemock/msvc/2010/gmock_test.vcxproj | 176 + .../gtest/googlemock/msvc/2015/gmock.sln | 46 + .../gtest/googlemock/msvc/2015/gmock.vcxproj | 145 + .../googlemock/msvc/2015/gmock_config.props | 19 + .../googlemock/msvc/2015/gmock_main.vcxproj | 151 + .../googlemock/msvc/2015/gmock_test.vcxproj | 176 + .../googlemock/scripts/fuse_gmock_files.py | 240 + .../googlemock/scripts/generator/LICENSE | 203 + .../gtest/googlemock/scripts/generator/README | 34 + .../scripts/generator/README.cppclean | 115 + .../scripts/generator/cpp/__init__.py | 0 .../googlemock/scripts/generator/cpp/ast.py | 1733 +++ .../scripts/generator/cpp/gmock_class.py | 227 + .../scripts/generator/cpp/gmock_class_test.py | 448 + .../scripts/generator/cpp/keywords.py | 59 + .../scripts/generator/cpp/tokenize.py | 287 + .../googlemock/scripts/generator/cpp/utils.py | 41 + .../googlemock/scripts/generator/gmock_gen.py | 31 + .../gtest/googlemock/scripts/gmock-config.in | 303 + .../gtest/googlemock/scripts/gmock_doctor.py | 640 + .../gtest/googlemock/scripts/upload.py | 1387 +++ .../gtest/googlemock/scripts/upload_gmock.py | 78 + .../gtest/googlemock/src/gmock-all.cc | 47 + .../googlemock/src/gmock-cardinalities.cc | 156 + .../googlemock/src/gmock-internal-utils.cc | 204 + .../gtest/googlemock/src/gmock-matchers.cc | 573 + .../googlemock/src/gmock-spec-builders.cc | 883 ++ .../thirdparty/gtest/googlemock/src/gmock.cc | 205 + .../gtest/googlemock/src/gmock_main.cc | 54 + .../gtest/googlemock/test/BUILD.bazel | 123 + .../googlemock/test/gmock-actions_test.cc | 1575 +++ .../test/gmock-cardinalities_test.cc | 428 + .../test/gmock-generated-actions_test.cc | 1230 ++ .../gmock-generated-function-mockers_test.cc | 647 + .../gmock-generated-internal-utils_test.cc | 129 + .../test/gmock-generated-matchers_test.cc | 1341 ++ .../test/gmock-internal-utils_test.cc | 718 ++ .../googlemock/test/gmock-matchers_test.cc | 6767 +++++++++++ .../test/gmock-more-actions_test.cc | 710 ++ .../googlemock/test/gmock-nice-strict_test.cc | 511 + .../gtest/googlemock/test/gmock-port_test.cc | 43 + .../test/gmock-spec-builders_test.cc | 2771 +++++ .../gtest/googlemock/test/gmock_all_test.cc | 51 + .../gtest/googlemock/test/gmock_ex_test.cc | 81 + .../gtest/googlemock/test/gmock_leak_test.py | 108 + .../gtest/googlemock/test/gmock_leak_test_.cc | 100 + .../gtest/googlemock/test/gmock_link2_test.cc | 40 + .../gtest/googlemock/test/gmock_link_test.cc | 40 + .../gtest/googlemock/test/gmock_link_test.h | 691 ++ .../googlemock/test/gmock_output_test.py | 183 + .../googlemock/test/gmock_output_test_.cc | 310 + .../test/gmock_output_test_golden.txt | 317 + .../googlemock/test/gmock_stress_test.cc | 323 + .../gtest/googlemock/test/gmock_test.cc | 262 + .../gtest/googlemock/test/gmock_test_utils.py | 110 + .../thirdparty/gtest/googletest/CHANGES | 157 + .../gtest/googletest/CMakeLists.txt | 312 + .../thirdparty/gtest/googletest/CONTRIBUTORS | 37 + .../thirdparty/gtest/googletest/LICENSE | 28 + .../thirdparty/gtest/googletest/Makefile.am | 339 + .../thirdparty/gtest/googletest/README.md | 341 + .../gtest/googletest/cmake/gtest.pc.in | 9 + .../gtest/googletest/cmake/gtest_main.pc.in | 10 + .../googletest/cmake/internal_utils.cmake | 280 + .../gtest/googletest/codegear/gtest.cbproj | 138 + .../gtest/googletest/codegear/gtest.groupproj | 54 + .../gtest/googletest/codegear/gtest_all.cc | 38 + .../gtest/googletest/codegear/gtest_link.cc | 40 + .../googletest/codegear/gtest_main.cbproj | 82 + .../googletest/codegear/gtest_unittest.cbproj | 88 + .../thirdparty/gtest/googletest/configure.ac | 68 + .../gtest/googletest/docs/Pkgconfig.md | 146 + .../gtest/googletest/docs/PumpManual.md | 177 + .../gtest/googletest/docs/XcodeGuide.md | 93 + .../gtest/googletest/docs/advanced.md | 2416 ++++ .../thirdparty/gtest/googletest/docs/faq.md | 1092 ++ .../gtest/googletest/docs/primer.md | 536 + .../gtest/googletest/docs/samples.md | 14 + .../include/gtest/gtest-death-test.h | 342 + .../googletest/include/gtest/gtest-message.h | 249 + .../include/gtest/gtest-param-test.h | 1438 +++ .../include/gtest/gtest-param-test.h.pump | 501 + .../googletest/include/gtest/gtest-printers.h | 1082 ++ .../googletest/include/gtest/gtest-spi.h | 231 + .../include/gtest/gtest-test-part.h | 179 + .../include/gtest/gtest-typed-test.h | 264 + .../gtest/googletest/include/gtest/gtest.h | 2332 ++++ .../include/gtest/gtest_pred_impl.h | 357 + .../googletest/include/gtest/gtest_prod.h | 61 + .../gtest/internal/custom/gtest-port.h | 70 + .../gtest/internal/custom/gtest-printers.h | 42 + .../include/gtest/internal/custom/gtest.h | 45 + .../internal/gtest-death-test-internal.h | 275 + .../include/gtest/internal/gtest-filepath.h | 205 + .../include/gtest/internal/gtest-internal.h | 1277 ++ .../include/gtest/internal/gtest-linked_ptr.h | 243 + .../internal/gtest-param-util-generated.h | 5139 ++++++++ .../gtest-param-util-generated.h.pump | 279 + .../include/gtest/internal/gtest-param-util.h | 723 ++ .../include/gtest/internal/gtest-port-arch.h | 100 + .../include/gtest/internal/gtest-port.h | 2687 ++++ .../include/gtest/internal/gtest-string.h | 167 + .../include/gtest/internal/gtest-tuple.h | 1020 ++ .../include/gtest/internal/gtest-tuple.h.pump | 347 + .../include/gtest/internal/gtest-type-util.h | 3347 +++++ .../gtest/internal/gtest-type-util.h.pump | 313 + .../gtest/googletest/m4/acx_pthread.m4 | 363 + .../thirdparty/gtest/googletest/m4/gtest.m4 | 74 + .../gtest/googletest/msvc/2010/gtest-md.sln | 55 + .../googletest/msvc/2010/gtest-md.vcxproj | 149 + .../msvc/2010/gtest-md.vcxproj.filters | 18 + .../gtest/googletest/msvc/2010/gtest.sln | 55 + .../gtest/googletest/msvc/2010/gtest.vcxproj | 149 + .../msvc/2010/gtest.vcxproj.filters | 18 + .../msvc/2010/gtest_main-md.vcxproj | 154 + .../msvc/2010/gtest_main-md.vcxproj.filters | 18 + .../googletest/msvc/2010/gtest_main.vcxproj | 162 + .../msvc/2010/gtest_main.vcxproj.filters | 18 + .../msvc/2010/gtest_prod_test-md.vcxproj | 199 + .../2010/gtest_prod_test-md.vcxproj.filters | 26 + .../msvc/2010/gtest_prod_test.vcxproj | 191 + .../msvc/2010/gtest_prod_test.vcxproj.filters | 26 + .../msvc/2010/gtest_unittest-md.vcxproj | 188 + .../2010/gtest_unittest-md.vcxproj.filters | 18 + .../msvc/2010/gtest_unittest.vcxproj | 180 + .../msvc/2010/gtest_unittest.vcxproj.filters | 18 + .../gtest/googletest/samples/prime_tables.h | 127 + .../gtest/googletest/samples/sample1.cc | 68 + .../gtest/googletest/samples/sample1.h | 43 + .../googletest/samples/sample10_unittest.cc | 140 + .../googletest/samples/sample1_unittest.cc | 154 + .../gtest/googletest/samples/sample2.cc | 56 + .../gtest/googletest/samples/sample2.h | 85 + .../googletest/samples/sample2_unittest.cc | 110 + .../gtest/googletest/samples/sample3-inl.h | 172 + .../googletest/samples/sample3_unittest.cc | 152 + .../gtest/googletest/samples/sample4.cc | 46 + .../gtest/googletest/samples/sample4.h | 53 + .../googletest/samples/sample4_unittest.cc | 49 + .../googletest/samples/sample5_unittest.cc | 199 + .../googletest/samples/sample6_unittest.cc | 225 + .../googletest/samples/sample7_unittest.cc | 118 + .../googletest/samples/sample8_unittest.cc | 174 + .../googletest/samples/sample9_unittest.cc | 157 + .../gtest/googletest/scripts/common.py | 83 + .../googletest/scripts/fuse_gtest_files.py | 253 + .../googletest/scripts/gen_gtest_pred_impl.py | 730 ++ .../gtest/googletest/scripts/gtest-config.in | 274 + .../gtest/googletest/scripts/pump.py | 855 ++ .../gtest/googletest/scripts/release_docs.py | 158 + .../gtest/googletest/scripts/upload.py | 1387 +++ .../gtest/googletest/scripts/upload_gtest.py | 78 + .../gtest/googletest/src/gtest-all.cc | 48 + .../gtest/googletest/src/gtest-death-test.cc | 1536 +++ .../gtest/googletest/src/gtest-filepath.cc | 385 + .../gtest/googletest/src/gtest-internal-inl.h | 1175 ++ .../gtest/googletest/src/gtest-port.cc | 1277 ++ .../gtest/googletest/src/gtest-printers.cc | 458 + .../gtest/googletest/src/gtest-test-part.cc | 102 + .../gtest/googletest/src/gtest-typed-test.cc | 119 + .../thirdparty/gtest/googletest/src/gtest.cc | 5846 +++++++++ .../gtest/googletest/src/gtest_main.cc | 38 + .../gtest/googletest/test/BUILD.bazel | 396 + .../test/gtest-death-test_ex_test.cc | 93 + .../googletest/test/gtest-death-test_test.cc | 1424 +++ .../googletest/test/gtest-filepath_test.cc | 652 + .../googletest/test/gtest-linked_ptr_test.cc | 154 + .../googletest/test/gtest-listener_test.cc | 311 + .../googletest/test/gtest-message_test.cc | 159 + .../googletest/test/gtest-options_test.cc | 213 + .../googletest/test/gtest-param-test2_test.cc | 61 + .../googletest/test/gtest-param-test_test.cc | 1110 ++ .../googletest/test/gtest-param-test_test.h | 53 + .../gtest/googletest/test/gtest-port_test.cc | 1303 ++ .../googletest/test/gtest-printers_test.cc | 1737 +++ .../googletest/test/gtest-test-part_test.cc | 208 + .../gtest/googletest/test/gtest-tuple_test.cc | 320 + .../googletest/test/gtest-typed-test2_test.cc | 45 + .../googletest/test/gtest-typed-test_test.cc | 380 + .../googletest/test/gtest-typed-test_test.h | 66 + .../test/gtest-unittest-api_test.cc | 341 + .../gtest/googletest/test/gtest_all_test.cc | 47 + .../test/gtest_assert_by_exception_test.cc | 119 + .../test/gtest_break_on_failure_unittest.py | 210 + .../test/gtest_break_on_failure_unittest_.cc | 87 + .../test/gtest_catch_exceptions_test.py | 235 + .../test/gtest_catch_exceptions_test_.cc | 311 + .../gtest/googletest/test/gtest_color_test.py | 129 + .../googletest/test/gtest_color_test_.cc | 63 + .../googletest/test/gtest_env_var_test.py | 119 + .../googletest/test/gtest_env_var_test_.cc | 124 + .../googletest/test/gtest_environment_test.cc | 189 + .../googletest/test/gtest_filter_unittest.py | 638 + .../googletest/test/gtest_filter_unittest_.cc | 138 + .../gtest/googletest/test/gtest_help_test.py | 172 + .../gtest/googletest/test/gtest_help_test_.cc | 46 + .../test/gtest_json_outfiles_test.py | 162 + .../test/gtest_json_output_unittest.py | 611 + .../googletest/test/gtest_json_test_utils.py | 60 + .../test/gtest_list_tests_unittest.py | 207 + .../test/gtest_list_tests_unittest_.cc | 157 + .../googletest/test/gtest_main_unittest.cc | 45 + .../googletest/test/gtest_no_test_unittest.cc | 56 + .../googletest/test/gtest_output_test.py | 344 + .../googletest/test/gtest_output_test_.cc | 1067 ++ .../test/gtest_output_test_golden_lin.txt | 781 ++ .../test/gtest_pred_impl_unittest.cc | 2427 ++++ .../test/gtest_premature_exit_test.cc | 127 + .../gtest/googletest/test/gtest_prod_test.cc | 57 + .../googletest/test/gtest_repeat_test.cc | 236 + .../googletest/test/gtest_shuffle_test.py | 325 + .../googletest/test/gtest_shuffle_test_.cc | 103 + .../googletest/test/gtest_sole_header_test.cc | 57 + .../googletest/test/gtest_stress_test.cc | 250 + .../gtest/googletest/test/gtest_test_utils.py | 318 + .../googletest/test/gtest_testbridge_test.py | 65 + .../googletest/test/gtest_testbridge_test_.cc | 44 + .../test/gtest_throw_on_failure_ex_test.cc | 92 + .../test/gtest_throw_on_failure_test.py | 171 + .../test/gtest_throw_on_failure_test_.cc | 72 + .../test/gtest_uninitialized_test.py | 69 + .../test/gtest_uninitialized_test_.cc | 43 + .../gtest/googletest/test/gtest_unittest.cc | 7797 ++++++++++++ .../test/gtest_xml_outfile1_test_.cc | 48 + .../test/gtest_xml_outfile2_test_.cc | 48 + .../test/gtest_xml_outfiles_test.py | 140 + .../test/gtest_xml_output_unittest.py | 378 + .../test/gtest_xml_output_unittest_.cc | 179 + .../googletest/test/gtest_xml_test_utils.py | 196 + .../gtest/googletest/test/production.cc | 36 + .../gtest/googletest/test/production.h | 55 + .../xcode/Config/DebugProject.xcconfig | 30 + .../xcode/Config/FrameworkTarget.xcconfig | 17 + .../googletest/xcode/Config/General.xcconfig | 41 + .../xcode/Config/ReleaseProject.xcconfig | 32 + .../xcode/Config/StaticLibraryTarget.xcconfig | 18 + .../xcode/Config/TestTarget.xcconfig | 8 + .../googletest/xcode/Resources/Info.plist | 30 + .../xcode/Samples/FrameworkSample/Info.plist | 28 + .../WidgetFramework.xcodeproj/project.pbxproj | 457 + .../xcode/Samples/FrameworkSample/runtests.sh | 62 + .../xcode/Samples/FrameworkSample/widget.cc | 63 + .../xcode/Samples/FrameworkSample/widget.h | 59 + .../Samples/FrameworkSample/widget_test.cc | 68 + .../googletest/xcode/Scripts/runtests.sh | 65 + .../xcode/Scripts/versiongenerate.py | 100 + .../xcode/gtest.xcodeproj/project.pbxproj | 1182 ++ deps/rapidjson/travis-doxygen.sh | 128 + deps/udis86 | 1 - deps/udis86/.gitignore | 74 + deps/udis86/BUILD-WINDOWS | 90 + deps/udis86/BuildVS2010/README.txt | 8 + deps/udis86/BuildVS2010/build.proj | 60 + deps/udis86/BuildVS2010/buildVS2010.bat | 7 + deps/udis86/BuildVS2010/libudis86.vcxproj | 294 + .../BuildVS2010/libudis86.vcxproj.filters | 63 + deps/udis86/BuildVS2010/udcli.vcxproj | 292 + deps/udis86/BuildVS2010/udcli.vcxproj.filters | 27 + deps/udis86/BuildVS2010/udis86.sln | 52 + deps/udis86/CHANGES | 47 + deps/udis86/INSTALL | 234 + deps/udis86/LICENSE | 22 + deps/udis86/Makefile.am | 38 + deps/udis86/README | 91 + deps/udis86/autogen.sh | 4 + deps/udis86/configure.ac | 83 + deps/udis86/docs/Makefile.am | 2 + deps/udis86/docs/manual/Makefile.am | 56 + deps/udis86/docs/manual/conf.py | 36 + deps/udis86/docs/manual/getstarted.rst | 57 + deps/udis86/docs/manual/index.rst | 27 + deps/udis86/docs/manual/libudis86.rst | 531 + deps/udis86/docs/manual/static/udis86.css | 115 + deps/udis86/docs/x86/Makefile.am | 4 + deps/udis86/docs/x86/README | 34 + deps/udis86/docs/x86/avx.xml | 3023 +++++ deps/udis86/docs/x86/optable.xml | 10099 ++++++++++++++++ deps/udis86/docs/x86/optable.xsl | 73 + deps/udis86/libudis86/Makefile.am | 51 + deps/udis86/libudis86/decode.c | 1266 ++ deps/udis86/libudis86/decode.h | 197 + deps/udis86/libudis86/extern.h | 113 + deps/udis86/libudis86/syn-att.c | 228 + deps/udis86/libudis86/syn-intel.c | 224 + deps/udis86/libudis86/syn.c | 212 + deps/udis86/libudis86/syn.h | 53 + deps/udis86/libudis86/types.h | 260 + deps/udis86/libudis86/udint.h | 99 + deps/udis86/libudis86/udis86.c | 458 + deps/udis86/m4/ax_compare_version.m4 | 177 + deps/udis86/m4/ax_prog_sphinx_version.m4 | 60 + deps/udis86/m4/ax_prog_yasm_version.m4 | 60 + deps/udis86/m4/ax_with_prog.m4 | 67 + deps/udis86/m4/ax_with_python.m4 | 32 + deps/udis86/scripts/Makefile.am | 9 + deps/udis86/scripts/asmtest.sh | 38 + deps/udis86/scripts/ud_itab.py | 379 + deps/udis86/scripts/ud_opcode.py | 622 + deps/udis86/tests/Makefile.am | 88 + deps/udis86/tests/asm/16/disp.asm | 6 + deps/udis86/tests/asm/16/test16.asm | 5 + deps/udis86/tests/asm/32/att.asm | 3 + deps/udis86/tests/asm/32/att.asm.Sref | 2 + deps/udis86/tests/asm/32/att.asm.ref | 2 + deps/udis86/tests/asm/32/avx.asm | 18 + deps/udis86/tests/asm/32/avx.asm.Sref | 17 + deps/udis86/tests/asm/32/avx.asm.ref | 17 + deps/udis86/tests/asm/32/corner.asm | 5 + deps/udis86/tests/asm/32/corner.asm.ref | 3 + deps/udis86/tests/asm/32/disp.asm | 6 + deps/udis86/tests/asm/32/disp.asm.Sref | 5 + deps/udis86/tests/asm/32/invalid_seg.asm | 2 + deps/udis86/tests/asm/32/invalid_seg.asm.ref | 1 + deps/udis86/tests/asm/32/obscure.asm | 12 + deps/udis86/tests/asm/32/obscure.asm.ref | 11 + deps/udis86/tests/asm/32/reljmp.asm | 24 + deps/udis86/tests/asm/32/reljmp.asm.ref | 17 + deps/udis86/tests/asm/32/sext.asm | 23 + deps/udis86/tests/asm/32/sext.asm.ref | 18 + deps/udis86/tests/asm/32/test32.asm | 282 + deps/udis86/tests/asm/64/amd/invalid.asm | 7 + deps/udis86/tests/asm/64/amd/invalid.asm.ref | 2 + deps/udis86/tests/asm/64/avx.asm | 5 + deps/udis86/tests/asm/64/avx.asm.ref | 4 + deps/udis86/tests/asm/64/branch.asm | 21 + deps/udis86/tests/asm/64/branch.asm.ref | 17 + deps/udis86/tests/asm/64/disp.asm | 7 + deps/udis86/tests/asm/64/disp.asm.Sref | 7 + deps/udis86/tests/asm/64/disp.asm.ref | 7 + deps/udis86/tests/asm/64/intel/invalid.asm | 8 + .../udis86/tests/asm/64/intel/invalid.asm.ref | 2 + deps/udis86/tests/asm/64/reljmp.asm | 24 + deps/udis86/tests/asm/64/reljmp.asm.ref | 17 + deps/udis86/tests/asm/64/sext.asm | 19 + deps/udis86/tests/asm/64/sext.asm.ref | 15 + deps/udis86/tests/asm/64/test64.asm | 158 + deps/udis86/tests/difftest.sh.in | 144 + deps/udis86/tests/installcheck.c | 18 + deps/udis86/tests/libcheck.c | 232 + deps/udis86/tests/oprgen.py | 1004 ++ deps/udis86/tests/symresolve.c | 53 + deps/udis86/tests/symresolve.ref | 42 + deps/udis86/udcli/Makefile.am | 5 + deps/udis86/udcli/udcli.c | 273 + deps/udis86/udis86.h | 33 + deps/zlib | 1 - deps/zlib/.github/workflows/cmake.yml | 89 + deps/zlib/.github/workflows/configure.yml | 136 + deps/zlib/.github/workflows/fuzz.yml | 25 + deps/zlib/.gitignore | 26 + deps/zlib/CMakeLists.txt | 213 + deps/zlib/ChangeLog | 1590 +++ deps/zlib/FAQ | 368 + deps/zlib/INDEX | 68 + deps/zlib/LICENSE | 22 + deps/zlib/Makefile | 5 + deps/zlib/Makefile.in | 404 + deps/zlib/README | 118 + deps/zlib/adler32.c | 186 + deps/zlib/amiga/Makefile.pup | 69 + deps/zlib/amiga/Makefile.sas | 68 + deps/zlib/compress.c | 86 + deps/zlib/configure | 922 ++ deps/zlib/contrib/README.contrib | 57 + deps/zlib/contrib/ada/buffer_demo.adb | 106 + deps/zlib/contrib/ada/mtest.adb | 156 + deps/zlib/contrib/ada/read.adb | 156 + deps/zlib/contrib/ada/readme.txt | 65 + deps/zlib/contrib/ada/test.adb | 463 + deps/zlib/contrib/ada/zlib-streams.adb | 225 + deps/zlib/contrib/ada/zlib-streams.ads | 114 + deps/zlib/contrib/ada/zlib-thin.adb | 141 + deps/zlib/contrib/ada/zlib-thin.ads | 450 + deps/zlib/contrib/ada/zlib.adb | 701 ++ deps/zlib/contrib/ada/zlib.ads | 328 + deps/zlib/contrib/ada/zlib.gpr | 20 + deps/zlib/contrib/blast/Makefile | 8 + deps/zlib/contrib/blast/README | 4 + deps/zlib/contrib/blast/blast.c | 466 + deps/zlib/contrib/blast/blast.h | 83 + deps/zlib/contrib/blast/test.pk | Bin 0 -> 8 bytes deps/zlib/contrib/blast/test.txt | 1 + deps/zlib/contrib/delphi/ZLib.pas | 557 + deps/zlib/contrib/delphi/ZLibConst.pas | 11 + deps/zlib/contrib/delphi/readme.txt | 76 + deps/zlib/contrib/delphi/zlibd32.mak | 99 + deps/zlib/contrib/dotzlib/DotZLib.build | 33 + deps/zlib/contrib/dotzlib/DotZLib.chm | Bin 0 -> 72726 bytes deps/zlib/contrib/dotzlib/DotZLib.sln | 21 + .../contrib/dotzlib/DotZLib/AssemblyInfo.cs | 58 + .../contrib/dotzlib/DotZLib/ChecksumImpl.cs | 202 + .../contrib/dotzlib/DotZLib/CircularBuffer.cs | 83 + .../zlib/contrib/dotzlib/DotZLib/CodecBase.cs | 198 + deps/zlib/contrib/dotzlib/DotZLib/Deflater.cs | 106 + deps/zlib/contrib/dotzlib/DotZLib/DotZLib.cs | 288 + .../contrib/dotzlib/DotZLib/DotZLib.csproj | 141 + .../contrib/dotzlib/DotZLib/GZipStream.cs | 301 + deps/zlib/contrib/dotzlib/DotZLib/Inflater.cs | 105 + .../zlib/contrib/dotzlib/DotZLib/UnitTests.cs | 274 + deps/zlib/contrib/dotzlib/LICENSE_1_0.txt | 23 + deps/zlib/contrib/dotzlib/readme.txt | 58 + deps/zlib/contrib/gcc_gvmat64/gvmat64.S | 574 + deps/zlib/contrib/infback9/README | 1 + deps/zlib/contrib/infback9/infback9.c | 615 + deps/zlib/contrib/infback9/infback9.h | 37 + deps/zlib/contrib/infback9/inffix9.h | 107 + deps/zlib/contrib/infback9/inflate9.h | 47 + deps/zlib/contrib/infback9/inftree9.c | 324 + deps/zlib/contrib/infback9/inftree9.h | 61 + deps/zlib/contrib/iostream/test.cpp | 24 + deps/zlib/contrib/iostream/zfstream.cpp | 329 + deps/zlib/contrib/iostream/zfstream.h | 128 + deps/zlib/contrib/iostream2/zstream.h | 307 + deps/zlib/contrib/iostream2/zstream_test.cpp | 25 + deps/zlib/contrib/iostream3/README | 35 + deps/zlib/contrib/iostream3/TODO | 17 + deps/zlib/contrib/iostream3/test.cc | 50 + deps/zlib/contrib/iostream3/zfstream.cc | 479 + deps/zlib/contrib/iostream3/zfstream.h | 466 + deps/zlib/contrib/minizip/Makefile | 29 + deps/zlib/contrib/minizip/Makefile.am | 45 + .../contrib/minizip/MiniZip64_Changes.txt | 6 + deps/zlib/contrib/minizip/MiniZip64_info.txt | 74 + deps/zlib/contrib/minizip/configure.ac | 32 + deps/zlib/contrib/minizip/crypt.h | 132 + deps/zlib/contrib/minizip/ioapi.c | 257 + deps/zlib/contrib/minizip/ioapi.h | 210 + deps/zlib/contrib/minizip/iowin32.c | 467 + deps/zlib/contrib/minizip/iowin32.h | 28 + deps/zlib/contrib/minizip/make_vms.com | 25 + deps/zlib/contrib/minizip/miniunz.c | 659 + deps/zlib/contrib/minizip/miniunzip.1 | 63 + deps/zlib/contrib/minizip/minizip.1 | 46 + deps/zlib/contrib/minizip/minizip.c | 521 + deps/zlib/contrib/minizip/minizip.pc.in | 12 + deps/zlib/contrib/minizip/mztools.c | 291 + deps/zlib/contrib/minizip/mztools.h | 37 + deps/zlib/contrib/minizip/unzip.c | 2130 ++++ deps/zlib/contrib/minizip/unzip.h | 437 + deps/zlib/contrib/minizip/zip.c | 2002 +++ deps/zlib/contrib/minizip/zip.h | 367 + deps/zlib/contrib/pascal/example.pas | 599 + deps/zlib/contrib/pascal/readme.txt | 76 + deps/zlib/contrib/pascal/zlibd32.mak | 99 + deps/zlib/contrib/pascal/zlibpas.pas | 276 + deps/zlib/contrib/puff/Makefile | 42 + deps/zlib/contrib/puff/README | 63 + deps/zlib/contrib/puff/puff.c | 840 ++ deps/zlib/contrib/puff/puff.h | 35 + deps/zlib/contrib/puff/pufftest.c | 165 + deps/zlib/contrib/puff/zeros.raw | Bin 0 -> 2517 bytes deps/zlib/contrib/testzlib/testzlib.c | 275 + deps/zlib/contrib/testzlib/testzlib.txt | 10 + deps/zlib/contrib/untgz/Makefile | 14 + deps/zlib/contrib/untgz/Makefile.msc | 17 + deps/zlib/contrib/untgz/untgz.c | 674 ++ deps/zlib/contrib/vstudio/readme.txt | 75 + .../zlib/contrib/vstudio/vc10/miniunz.vcxproj | 310 + .../vstudio/vc10/miniunz.vcxproj.filters | 22 + .../zlib/contrib/vstudio/vc10/minizip.vcxproj | 307 + .../vstudio/vc10/minizip.vcxproj.filters | 22 + .../contrib/vstudio/vc10/testzlib.vcxproj | 412 + .../vstudio/vc10/testzlib.vcxproj.filters | 55 + .../contrib/vstudio/vc10/testzlibdll.vcxproj | 310 + .../vstudio/vc10/testzlibdll.vcxproj.filters | 22 + deps/zlib/contrib/vstudio/vc10/zlib.rc | 32 + .../contrib/vstudio/vc10/zlibstat.vcxproj | 449 + .../vstudio/vc10/zlibstat.vcxproj.filters | 74 + deps/zlib/contrib/vstudio/vc10/zlibvc.def | 158 + deps/zlib/contrib/vstudio/vc10/zlibvc.sln | 135 + deps/zlib/contrib/vstudio/vc10/zlibvc.vcxproj | 633 + .../vstudio/vc10/zlibvc.vcxproj.filters | 115 + .../zlib/contrib/vstudio/vc11/miniunz.vcxproj | 314 + .../zlib/contrib/vstudio/vc11/minizip.vcxproj | 311 + .../contrib/vstudio/vc11/testzlib.vcxproj | 418 + .../contrib/vstudio/vc11/testzlibdll.vcxproj | 314 + deps/zlib/contrib/vstudio/vc11/zlib.rc | 32 + .../contrib/vstudio/vc11/zlibstat.vcxproj | 456 + deps/zlib/contrib/vstudio/vc11/zlibvc.def | 158 + deps/zlib/contrib/vstudio/vc11/zlibvc.sln | 117 + deps/zlib/contrib/vstudio/vc11/zlibvc.vcxproj | 664 + .../zlib/contrib/vstudio/vc12/miniunz.vcxproj | 316 + .../zlib/contrib/vstudio/vc12/minizip.vcxproj | 313 + .../contrib/vstudio/vc12/testzlib.vcxproj | 422 + .../contrib/vstudio/vc12/testzlibdll.vcxproj | 316 + deps/zlib/contrib/vstudio/vc12/zlib.rc | 32 + .../contrib/vstudio/vc12/zlibstat.vcxproj | 459 + deps/zlib/contrib/vstudio/vc12/zlibvc.def | 158 + deps/zlib/contrib/vstudio/vc12/zlibvc.sln | 119 + deps/zlib/contrib/vstudio/vc12/zlibvc.vcxproj | 668 + .../zlib/contrib/vstudio/vc14/miniunz.vcxproj | 316 + .../zlib/contrib/vstudio/vc14/minizip.vcxproj | 313 + .../contrib/vstudio/vc14/testzlib.vcxproj | 422 + .../contrib/vstudio/vc14/testzlibdll.vcxproj | 316 + deps/zlib/contrib/vstudio/vc14/zlib.rc | 32 + .../contrib/vstudio/vc14/zlibstat.vcxproj | 459 + deps/zlib/contrib/vstudio/vc14/zlibvc.def | 158 + deps/zlib/contrib/vstudio/vc14/zlibvc.sln | 119 + deps/zlib/contrib/vstudio/vc14/zlibvc.vcxproj | 668 + deps/zlib/contrib/vstudio/vc9/miniunz.vcproj | 565 + deps/zlib/contrib/vstudio/vc9/minizip.vcproj | 562 + deps/zlib/contrib/vstudio/vc9/testzlib.vcproj | 796 ++ .../contrib/vstudio/vc9/testzlibdll.vcproj | 565 + deps/zlib/contrib/vstudio/vc9/zlib.rc | 32 + deps/zlib/contrib/vstudio/vc9/zlibstat.vcproj | 781 ++ deps/zlib/contrib/vstudio/vc9/zlibvc.def | 158 + deps/zlib/contrib/vstudio/vc9/zlibvc.sln | 144 + deps/zlib/contrib/vstudio/vc9/zlibvc.vcproj | 1100 ++ deps/zlib/crc32.c | 1125 ++ deps/zlib/crc32.h | 9446 +++++++++++++++ deps/zlib/deflate.c | 2217 ++++ deps/zlib/deflate.h | 346 + deps/zlib/doc/algorithm.txt | 209 + deps/zlib/doc/crc-doc.1.0.pdf | Bin 0 -> 776142 bytes deps/zlib/doc/rfc1950.txt | 619 + deps/zlib/doc/rfc1951.txt | 955 ++ deps/zlib/doc/rfc1952.txt | 675 ++ deps/zlib/doc/txtvsbin.txt | 107 + deps/zlib/examples/README.examples | 54 + deps/zlib/examples/enough.c | 597 + deps/zlib/examples/fitblk.c | 233 + deps/zlib/examples/gun.c | 702 ++ deps/zlib/examples/gzappend.c | 504 + deps/zlib/examples/gzjoin.c | 449 + deps/zlib/examples/gzlog.c | 1061 ++ deps/zlib/examples/gzlog.h | 91 + deps/zlib/examples/gznorm.c | 470 + deps/zlib/examples/zlib_how.html | 545 + deps/zlib/examples/zpipe.c | 205 + deps/zlib/examples/zran.c | 479 + deps/zlib/examples/zran.h | 40 + deps/zlib/gzclose.c | 25 + deps/zlib/gzguts.h | 219 + deps/zlib/gzlib.c | 639 + deps/zlib/gzread.c | 650 + deps/zlib/gzwrite.c | 677 ++ deps/zlib/infback.c | 644 + deps/zlib/inffast.c | 323 + deps/zlib/inffast.h | 11 + deps/zlib/inffixed.h | 94 + deps/zlib/inflate.c | 1595 +++ deps/zlib/inflate.h | 126 + deps/zlib/inftrees.c | 304 + deps/zlib/inftrees.h | 62 + deps/zlib/make_vms.com | 867 ++ deps/zlib/msdos/Makefile.bor | 115 + deps/zlib/msdos/Makefile.dj2 | 104 + deps/zlib/msdos/Makefile.emx | 69 + deps/zlib/msdos/Makefile.msc | 112 + deps/zlib/msdos/Makefile.tc | 100 + deps/zlib/nintendods/Makefile | 126 + deps/zlib/nintendods/README | 5 + deps/zlib/old/Makefile.emx | 69 + deps/zlib/old/Makefile.riscos | 151 + deps/zlib/old/README | 3 + deps/zlib/old/descrip.mms | 48 + deps/zlib/old/os2/Makefile.os2 | 136 + deps/zlib/old/os2/zlib.def | 51 + deps/zlib/old/visual-basic.txt | 160 + deps/zlib/os400/README400 | 48 + deps/zlib/os400/bndsrc | 127 + deps/zlib/os400/make.sh | 366 + deps/zlib/os400/zlib.inc | 527 + deps/zlib/qnx/package.qpg | 141 + deps/zlib/test/example.c | 602 + deps/zlib/test/infcover.c | 671 + deps/zlib/test/minigzip.c | 651 + deps/zlib/treebuild.xml | 116 + deps/zlib/trees.c | 1181 ++ deps/zlib/trees.h | 128 + deps/zlib/uncompr.c | 93 + deps/zlib/watcom/watcom_f.mak | 43 + deps/zlib/watcom/watcom_l.mak | 43 + deps/zlib/win32/DLL_FAQ.txt | 397 + deps/zlib/win32/Makefile.bor | 109 + deps/zlib/win32/Makefile.gcc | 177 + deps/zlib/win32/Makefile.msc | 159 + deps/zlib/win32/README-WIN32.txt | 103 + deps/zlib/win32/VisualC.txt | 3 + deps/zlib/win32/zlib.def | 97 + deps/zlib/win32/zlib1.rc | 40 + deps/zlib/zconf.h | 547 + deps/zlib/zconf.h.cmakein | 549 + deps/zlib/zconf.h.in | 547 + deps/zlib/zlib.3 | 149 + deps/zlib/zlib.3.pdf | Bin 0 -> 19366 bytes deps/zlib/zlib.h | 1935 +++ deps/zlib/zlib.map | 100 + deps/zlib/zlib.pc.cmakein | 13 + deps/zlib/zlib.pc.in | 13 + deps/zlib/zlib2ansi | 152 + deps/zlib/zutil.c | 327 + deps/zlib/zutil.h | 275 + premake5.lua | 2 +- 1948 files changed, 484442 insertions(+), 33 deletions(-) delete mode 100644 .gitmodules create mode 100644 build.bat delete mode 160000 deps/GSL create mode 100644 deps/GSL/.clang-format create mode 100644 deps/GSL/.gitattributes create mode 100644 deps/GSL/.github/workflows/android.yml create mode 100644 deps/GSL/.github/workflows/cmake_find_package.yml create mode 100644 deps/GSL/.github/workflows/ios.yml create mode 100644 deps/GSL/.gitignore create mode 100644 deps/GSL/CMakeLists.txt create mode 100644 deps/GSL/CMakeSettings.json create mode 100644 deps/GSL/CONTRIBUTING.md create mode 100644 deps/GSL/GSL.natvis create mode 100644 deps/GSL/LICENSE create mode 100644 deps/GSL/README.md create mode 100644 deps/GSL/SECURITY.md create mode 100644 deps/GSL/ThirdPartyNotices.txt create mode 100644 deps/GSL/azure-pipelines.yml create mode 100644 deps/GSL/docs/headers.md create mode 100644 deps/GSL/include/CMakeLists.txt create mode 100644 deps/GSL/include/gsl/algorithm create mode 100644 deps/GSL/include/gsl/assert create mode 100644 deps/GSL/include/gsl/byte create mode 100644 deps/GSL/include/gsl/gsl create mode 100644 deps/GSL/include/gsl/gsl_algorithm create mode 100644 deps/GSL/include/gsl/gsl_assert create mode 100644 deps/GSL/include/gsl/gsl_byte create mode 100644 deps/GSL/include/gsl/gsl_narrow create mode 100644 deps/GSL/include/gsl/gsl_util create mode 100644 deps/GSL/include/gsl/narrow create mode 100644 deps/GSL/include/gsl/pointers create mode 100644 deps/GSL/include/gsl/span create mode 100644 deps/GSL/include/gsl/span_ext create mode 100644 deps/GSL/include/gsl/string_span create mode 100644 deps/GSL/include/gsl/util create mode 100644 deps/GSL/pipelines/jobs.yml create mode 100644 deps/GSL/pipelines/setup_apple.yml create mode 100644 deps/GSL/pipelines/setup_clang.yml create mode 100644 deps/GSL/pipelines/setup_gcc.yml create mode 100644 deps/GSL/pipelines/steps.yml create mode 100644 deps/GSL/tests/CMakeLists.txt create mode 100644 deps/GSL/tests/CMakeLists.txt.in create mode 100644 deps/GSL/tests/algorithm_tests.cpp create mode 100644 deps/GSL/tests/assertion_tests.cpp create mode 100644 deps/GSL/tests/at_tests.cpp create mode 100644 deps/GSL/tests/byte_tests.cpp create mode 100644 deps/GSL/tests/deathTestCommon.h create mode 100644 deps/GSL/tests/no_exception_ensure_tests.cpp create mode 100644 deps/GSL/tests/notnull_tests.cpp create mode 100644 deps/GSL/tests/owner_tests.cpp create mode 100644 deps/GSL/tests/span_compatibility_tests.cpp create mode 100644 deps/GSL/tests/span_ext_tests.cpp create mode 100644 deps/GSL/tests/span_tests.cpp create mode 100644 deps/GSL/tests/strict_notnull_tests.cpp create mode 100644 deps/GSL/tests/utils_tests.cpp delete mode 160000 deps/discord-rpc create mode 100644 deps/discord-rpc/.clang-format create mode 100644 deps/discord-rpc/.gitignore create mode 100644 deps/discord-rpc/.travis.yml create mode 100644 deps/discord-rpc/CMakeLists.txt create mode 100644 deps/discord-rpc/LICENSE create mode 100644 deps/discord-rpc/README.md create mode 100644 deps/discord-rpc/appveyor.yml create mode 100644 deps/discord-rpc/build.py create mode 100644 deps/discord-rpc/documentation/hard-mode.md create mode 100644 deps/discord-rpc/documentation/images/rp-dev-dashboard.png create mode 100644 deps/discord-rpc/documentation/images/rp-profile-view.png create mode 100644 deps/discord-rpc/documentation/images/rp-secret-example.png create mode 100644 deps/discord-rpc/examples/button-clicker/.gitignore create mode 100644 deps/discord-rpc/examples/button-clicker/Assets/DiscordController.cs create mode 100644 deps/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs create mode 100644 deps/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs create mode 100644 deps/discord-rpc/examples/button-clicker/Assets/main.unity create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/AudioManager.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/ClusterInputManager.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/DynamicsManager.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorBuildSettings.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorSettings.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/GraphicsSettings.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/InputManager.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/NavMeshAreas.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/NetworkManager.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/Physics2DSettings.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectSettings.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectVersion.txt create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/QualitySettings.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/TagManager.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/TimeManager.asset create mode 100644 deps/discord-rpc/examples/button-clicker/ProjectSettings/UnityConnectSettings.asset create mode 100644 deps/discord-rpc/examples/button-clicker/UnityPackageManager/manifest.json create mode 100644 deps/discord-rpc/examples/send-presence/CMakeLists.txt create mode 100644 deps/discord-rpc/examples/send-presence/send-presence.c create mode 100644 deps/discord-rpc/examples/unrealstatus/.gitignore create mode 100644 deps/discord-rpc/examples/unrealstatus/Config/DefaultEditor.ini create mode 100644 deps/discord-rpc/examples/unrealstatus/Config/DefaultEngine.ini create mode 100644 deps/discord-rpc/examples/unrealstatus/Config/DefaultGame.ini create mode 100644 deps/discord-rpc/examples/unrealstatus/Content/MainScreenBP.uasset create mode 100644 deps/discord-rpc/examples/unrealstatus/Content/MouseGameModeBP.uasset create mode 100644 deps/discord-rpc/examples/unrealstatus/Content/MousePlayerControllerBP.uasset create mode 100644 deps/discord-rpc/examples/unrealstatus/Content/ShowTheUILevel.umap create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/Icon128.png create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/discord.png create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/DiscordRpc.Build.cs create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpc.cpp create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcPrivatePCH.h create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpc.h create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h create mode 100644 deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/DiscordRpcLibrary/DiscordRpcLibrary.Build.cs create mode 100644 deps/discord-rpc/examples/unrealstatus/Source/unrealstatus.Target.cs create mode 100644 deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.Build.cs create mode 100644 deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.cpp create mode 100644 deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.h create mode 100644 deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.cpp create mode 100644 deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.h create mode 100644 deps/discord-rpc/examples/unrealstatus/Source/unrealstatusEditor.Target.cs create mode 100644 deps/discord-rpc/examples/unrealstatus/unrealstatus.uproject create mode 100644 deps/discord-rpc/include/discord_register.h create mode 100644 deps/discord-rpc/include/discord_rpc.h create mode 100644 deps/discord-rpc/src/CMakeLists.txt create mode 100644 deps/discord-rpc/src/backoff.h create mode 100644 deps/discord-rpc/src/connection.h create mode 100644 deps/discord-rpc/src/connection_unix.cpp create mode 100644 deps/discord-rpc/src/connection_win.cpp create mode 100644 deps/discord-rpc/src/discord_register_linux.cpp create mode 100644 deps/discord-rpc/src/discord_register_osx.m create mode 100644 deps/discord-rpc/src/discord_register_win.cpp create mode 100644 deps/discord-rpc/src/discord_rpc.cpp create mode 100644 deps/discord-rpc/src/dllmain.cpp create mode 100644 deps/discord-rpc/src/msg_queue.h create mode 100644 deps/discord-rpc/src/rpc_connection.cpp create mode 100644 deps/discord-rpc/src/rpc_connection.h create mode 100644 deps/discord-rpc/src/serialization.cpp create mode 100644 deps/discord-rpc/src/serialization.h delete mode 160000 deps/libtomcrypt create mode 100644 deps/libtomcrypt/.ci/build.sh create mode 100644 deps/libtomcrypt/.ci/check_source.sh create mode 100644 deps/libtomcrypt/.ci/clang-tidy.sh create mode 100644 deps/libtomcrypt/.ci/coverage.sh create mode 100644 deps/libtomcrypt/.ci/coverage_more.sh create mode 100644 deps/libtomcrypt/.ci/meta_builds.sh create mode 100644 deps/libtomcrypt/.ci/printinfo.sh create mode 100644 deps/libtomcrypt/.ci/run.sh create mode 100644 deps/libtomcrypt/.ci/testbuild.sh create mode 100644 deps/libtomcrypt/.ci/valgrind.sh create mode 100644 deps/libtomcrypt/.clang-format create mode 100644 deps/libtomcrypt/.gitattributes create mode 100644 deps/libtomcrypt/.github/ISSUE_TEMPLATE.md create mode 100644 deps/libtomcrypt/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 deps/libtomcrypt/.github/workflows/main.yml create mode 100644 deps/libtomcrypt/.gitignore create mode 100644 deps/libtomcrypt/CMakeLists.txt create mode 100644 deps/libtomcrypt/LICENSE create mode 100644 deps/libtomcrypt/README.md create mode 100644 deps/libtomcrypt/appveyor.yml create mode 100644 deps/libtomcrypt/changes create mode 100644 deps/libtomcrypt/coverity.sh create mode 100644 deps/libtomcrypt/demos/CMakeLists.txt create mode 100644 deps/libtomcrypt/demos/aesgcm.c create mode 100644 deps/libtomcrypt/demos/constants.c create mode 100644 deps/libtomcrypt/demos/demo_dynamic.py create mode 100644 deps/libtomcrypt/demos/gcm-file/gcm_file.c create mode 100644 deps/libtomcrypt/demos/gcm-file/gcm_filehandle.c create mode 100644 deps/libtomcrypt/demos/hashsum.c create mode 100644 deps/libtomcrypt/demos/ltcrypt.c create mode 100644 deps/libtomcrypt/demos/openssl-enc.c create mode 100644 deps/libtomcrypt/demos/sizes.c create mode 100644 deps/libtomcrypt/demos/small.c create mode 100644 deps/libtomcrypt/demos/timing.c create mode 100644 deps/libtomcrypt/demos/tv_gen.c create mode 100644 deps/libtomcrypt/doc/Doxyfile create mode 100644 deps/libtomcrypt/doc/crypt.tex create mode 100644 deps/libtomcrypt/doc/libtomsm.png create mode 100644 deps/libtomcrypt/doc/makefile create mode 100644 deps/libtomcrypt/helper.pl create mode 100644 deps/libtomcrypt/hooks/pre-commit create mode 100644 deps/libtomcrypt/libtomcrypt.pc.in create mode 100644 deps/libtomcrypt/libtomcrypt_VS2008.sln create mode 100644 deps/libtomcrypt/libtomcrypt_VS2008.vcproj create mode 100644 deps/libtomcrypt/makefile create mode 100644 deps/libtomcrypt/makefile.mingw create mode 100644 deps/libtomcrypt/makefile.msvc create mode 100644 deps/libtomcrypt/makefile.shared create mode 100644 deps/libtomcrypt/makefile.unix create mode 100644 deps/libtomcrypt/makefile_include.mk create mode 100644 deps/libtomcrypt/notes/etc/NoekeonVects.java create mode 100644 deps/libtomcrypt/notes/etc/saferp_optimizer.c create mode 100644 deps/libtomcrypt/notes/etc/whirlgen.c create mode 100644 deps/libtomcrypt/notes/etc/whirltest.c create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/makefile create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/oaep-int.txt create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.c create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.txt create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.c create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.txt create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.c create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.txt create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/pss-int.txt create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/pss-vect.c create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/pss-vect.txt create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/readme.txt create mode 100644 deps/libtomcrypt/notes/rsa-testvectors/rt.py create mode 100644 deps/libtomcrypt/notes/tech0001.txt create mode 100644 deps/libtomcrypt/notes/tech0002.txt create mode 100644 deps/libtomcrypt/notes/tech0003.txt create mode 100644 deps/libtomcrypt/notes/tech0004.txt create mode 100644 deps/libtomcrypt/notes/tech0005.txt create mode 100644 deps/libtomcrypt/notes/tech0006.txt create mode 100644 deps/libtomcrypt/notes/tech0007.txt create mode 100644 deps/libtomcrypt/sources.cmake create mode 100644 deps/libtomcrypt/src/ciphers/aes/aes.c create mode 100644 deps/libtomcrypt/src/ciphers/aes/aes_tab.c create mode 100644 deps/libtomcrypt/src/ciphers/anubis.c create mode 100644 deps/libtomcrypt/src/ciphers/blowfish.c create mode 100644 deps/libtomcrypt/src/ciphers/camellia.c create mode 100644 deps/libtomcrypt/src/ciphers/cast5.c create mode 100644 deps/libtomcrypt/src/ciphers/des.c create mode 100644 deps/libtomcrypt/src/ciphers/idea.c create mode 100644 deps/libtomcrypt/src/ciphers/kasumi.c create mode 100644 deps/libtomcrypt/src/ciphers/khazad.c create mode 100644 deps/libtomcrypt/src/ciphers/kseed.c create mode 100644 deps/libtomcrypt/src/ciphers/multi2.c create mode 100644 deps/libtomcrypt/src/ciphers/noekeon.c create mode 100644 deps/libtomcrypt/src/ciphers/rc2.c create mode 100644 deps/libtomcrypt/src/ciphers/rc5.c create mode 100644 deps/libtomcrypt/src/ciphers/rc6.c create mode 100644 deps/libtomcrypt/src/ciphers/safer/safer.c create mode 100644 deps/libtomcrypt/src/ciphers/safer/safer_tab.c create mode 100644 deps/libtomcrypt/src/ciphers/safer/saferp.c create mode 100644 deps/libtomcrypt/src/ciphers/serpent.c create mode 100644 deps/libtomcrypt/src/ciphers/skipjack.c create mode 100644 deps/libtomcrypt/src/ciphers/tea.c create mode 100644 deps/libtomcrypt/src/ciphers/twofish/twofish.c create mode 100644 deps/libtomcrypt/src/ciphers/twofish/twofish_tab.c create mode 100644 deps/libtomcrypt/src/ciphers/xtea.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_add_aad.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_done.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_init.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_memory.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_process.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_reset.c create mode 100644 deps/libtomcrypt/src/encauth/ccm/ccm_test.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c create mode 100644 deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_addheader.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_decrypt.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_done.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_encrypt.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_init.c create mode 100644 deps/libtomcrypt/src/encauth/eax/eax_test.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_add_aad.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_add_iv.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_done.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_init.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_memory.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_mult_h.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_process.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_reset.c create mode 100644 deps/libtomcrypt/src/encauth/gcm/gcm_test.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_decrypt.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_encrypt.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_init.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_ntz.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/ocb_test.c create mode 100644 deps/libtomcrypt/src/encauth/ocb/s_ocb_done.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_done.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_init.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c create mode 100644 deps/libtomcrypt/src/encauth/ocb3/ocb3_test.c create mode 100644 deps/libtomcrypt/src/hashes/blake2b.c create mode 100644 deps/libtomcrypt/src/hashes/blake2s.c create mode 100644 deps/libtomcrypt/src/hashes/chc/chc.c create mode 100644 deps/libtomcrypt/src/hashes/helper/hash_file.c create mode 100644 deps/libtomcrypt/src/hashes/helper/hash_filehandle.c create mode 100644 deps/libtomcrypt/src/hashes/helper/hash_memory.c create mode 100644 deps/libtomcrypt/src/hashes/helper/hash_memory_multi.c create mode 100644 deps/libtomcrypt/src/hashes/md2.c create mode 100644 deps/libtomcrypt/src/hashes/md4.c create mode 100644 deps/libtomcrypt/src/hashes/md5.c create mode 100644 deps/libtomcrypt/src/hashes/rmd128.c create mode 100644 deps/libtomcrypt/src/hashes/rmd160.c create mode 100644 deps/libtomcrypt/src/hashes/rmd256.c create mode 100644 deps/libtomcrypt/src/hashes/rmd320.c create mode 100644 deps/libtomcrypt/src/hashes/sha1.c create mode 100644 deps/libtomcrypt/src/hashes/sha2/sha224.c create mode 100644 deps/libtomcrypt/src/hashes/sha2/sha256.c create mode 100644 deps/libtomcrypt/src/hashes/sha2/sha384.c create mode 100644 deps/libtomcrypt/src/hashes/sha2/sha512.c create mode 100644 deps/libtomcrypt/src/hashes/sha2/sha512_224.c create mode 100644 deps/libtomcrypt/src/hashes/sha2/sha512_256.c create mode 100644 deps/libtomcrypt/src/hashes/sha3.c create mode 100644 deps/libtomcrypt/src/hashes/sha3_test.c create mode 100644 deps/libtomcrypt/src/hashes/tiger.c create mode 100644 deps/libtomcrypt/src/hashes/whirl/whirl.c create mode 100644 deps/libtomcrypt/src/hashes/whirl/whirltab.c create mode 100644 deps/libtomcrypt/src/headers/tomcrypt.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_argchk.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_cfg.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_cipher.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_custom.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_hash.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_mac.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_macros.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_math.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_misc.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_pk.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_pkcs.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_private.h create mode 100644 deps/libtomcrypt/src/headers/tomcrypt_prng.h create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2bmac.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2bmac_file.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2bmac_memory.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2bmac_test.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2smac.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2smac_file.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2smac_memory.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/blake2/blake2smac_test.c create mode 100644 deps/libtomcrypt/src/mac/f9/f9_done.c create mode 100644 deps/libtomcrypt/src/mac/f9/f9_file.c create mode 100644 deps/libtomcrypt/src/mac/f9/f9_init.c create mode 100644 deps/libtomcrypt/src/mac/f9/f9_memory.c create mode 100644 deps/libtomcrypt/src/mac/f9/f9_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/f9/f9_process.c create mode 100644 deps/libtomcrypt/src/mac/f9/f9_test.c create mode 100644 deps/libtomcrypt/src/mac/hmac/hmac_done.c create mode 100644 deps/libtomcrypt/src/mac/hmac/hmac_file.c create mode 100644 deps/libtomcrypt/src/mac/hmac/hmac_init.c create mode 100644 deps/libtomcrypt/src/mac/hmac/hmac_memory.c create mode 100644 deps/libtomcrypt/src/mac/hmac/hmac_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/hmac/hmac_process.c create mode 100644 deps/libtomcrypt/src/mac/hmac/hmac_test.c create mode 100644 deps/libtomcrypt/src/mac/omac/omac_done.c create mode 100644 deps/libtomcrypt/src/mac/omac/omac_file.c create mode 100644 deps/libtomcrypt/src/mac/omac/omac_init.c create mode 100644 deps/libtomcrypt/src/mac/omac/omac_memory.c create mode 100644 deps/libtomcrypt/src/mac/omac/omac_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/omac/omac_process.c create mode 100644 deps/libtomcrypt/src/mac/omac/omac_test.c create mode 100644 deps/libtomcrypt/src/mac/pelican/pelican.c create mode 100644 deps/libtomcrypt/src/mac/pelican/pelican_memory.c create mode 100644 deps/libtomcrypt/src/mac/pelican/pelican_test.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_done.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_file.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_init.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_memory.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_ntz.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_process.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_shift_xor.c create mode 100644 deps/libtomcrypt/src/mac/pmac/pmac_test.c create mode 100644 deps/libtomcrypt/src/mac/poly1305/poly1305.c create mode 100644 deps/libtomcrypt/src/mac/poly1305/poly1305_file.c create mode 100644 deps/libtomcrypt/src/mac/poly1305/poly1305_memory.c create mode 100644 deps/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/poly1305/poly1305_test.c create mode 100644 deps/libtomcrypt/src/mac/xcbc/xcbc_done.c create mode 100644 deps/libtomcrypt/src/mac/xcbc/xcbc_file.c create mode 100644 deps/libtomcrypt/src/mac/xcbc/xcbc_init.c create mode 100644 deps/libtomcrypt/src/mac/xcbc/xcbc_memory.c create mode 100644 deps/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c create mode 100644 deps/libtomcrypt/src/mac/xcbc/xcbc_process.c create mode 100644 deps/libtomcrypt/src/mac/xcbc/xcbc_test.c create mode 100644 deps/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c create mode 100644 deps/libtomcrypt/src/math/gmp_desc.c create mode 100644 deps/libtomcrypt/src/math/ltm_desc.c create mode 100644 deps/libtomcrypt/src/math/multi.c create mode 100644 deps/libtomcrypt/src/math/radix_to_bin.c create mode 100644 deps/libtomcrypt/src/math/rand_bn.c create mode 100644 deps/libtomcrypt/src/math/rand_prime.c create mode 100644 deps/libtomcrypt/src/math/tfm_desc.c create mode 100644 deps/libtomcrypt/src/misc/adler32.c create mode 100644 deps/libtomcrypt/src/misc/base16/base16_decode.c create mode 100644 deps/libtomcrypt/src/misc/base16/base16_encode.c create mode 100644 deps/libtomcrypt/src/misc/base32/base32_decode.c create mode 100644 deps/libtomcrypt/src/misc/base32/base32_encode.c create mode 100644 deps/libtomcrypt/src/misc/base64/base64_decode.c create mode 100644 deps/libtomcrypt/src/misc/base64/base64_encode.c create mode 100644 deps/libtomcrypt/src/misc/bcrypt/bcrypt.c create mode 100644 deps/libtomcrypt/src/misc/burn_stack.c create mode 100644 deps/libtomcrypt/src/misc/compare_testvector.c create mode 100644 deps/libtomcrypt/src/misc/copy_or_zeromem.c create mode 100644 deps/libtomcrypt/src/misc/crc32.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_argchk.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_constants.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_cipher.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_hash.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_find_prng.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_fsa.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_inits.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_register_cipher.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_register_hash.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_register_prng.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_sizes.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c create mode 100644 deps/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c create mode 100644 deps/libtomcrypt/src/misc/error_to_string.c create mode 100644 deps/libtomcrypt/src/misc/hkdf/hkdf.c create mode 100644 deps/libtomcrypt/src/misc/hkdf/hkdf_test.c create mode 100644 deps/libtomcrypt/src/misc/mem_neq.c create mode 100644 deps/libtomcrypt/src/misc/padding/padding_depad.c create mode 100644 deps/libtomcrypt/src/misc/padding/padding_pad.c create mode 100644 deps/libtomcrypt/src/misc/pbes/pbes.c create mode 100644 deps/libtomcrypt/src/misc/pbes/pbes1.c create mode 100644 deps/libtomcrypt/src/misc/pbes/pbes2.c create mode 100644 deps/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c create mode 100644 deps/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c create mode 100644 deps/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c create mode 100644 deps/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c create mode 100644 deps/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c create mode 100644 deps/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c create mode 100644 deps/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c create mode 100644 deps/libtomcrypt/src/misc/zeromem.c create mode 100644 deps/libtomcrypt/src/modes/cbc/cbc_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/cbc/cbc_done.c create mode 100644 deps/libtomcrypt/src/modes/cbc/cbc_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/cbc/cbc_getiv.c create mode 100644 deps/libtomcrypt/src/modes/cbc/cbc_setiv.c create mode 100644 deps/libtomcrypt/src/modes/cbc/cbc_start.c create mode 100644 deps/libtomcrypt/src/modes/cfb/cfb_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/cfb/cfb_done.c create mode 100644 deps/libtomcrypt/src/modes/cfb/cfb_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/cfb/cfb_getiv.c create mode 100644 deps/libtomcrypt/src/modes/cfb/cfb_setiv.c create mode 100644 deps/libtomcrypt/src/modes/cfb/cfb_start.c create mode 100644 deps/libtomcrypt/src/modes/ctr/ctr_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/ctr/ctr_done.c create mode 100644 deps/libtomcrypt/src/modes/ctr/ctr_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/ctr/ctr_getiv.c create mode 100644 deps/libtomcrypt/src/modes/ctr/ctr_setiv.c create mode 100644 deps/libtomcrypt/src/modes/ctr/ctr_start.c create mode 100644 deps/libtomcrypt/src/modes/ctr/ctr_test.c create mode 100644 deps/libtomcrypt/src/modes/ecb/ecb_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/ecb/ecb_done.c create mode 100644 deps/libtomcrypt/src/modes/ecb/ecb_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/ecb/ecb_start.c create mode 100644 deps/libtomcrypt/src/modes/f8/f8_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/f8/f8_done.c create mode 100644 deps/libtomcrypt/src/modes/f8/f8_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/f8/f8_getiv.c create mode 100644 deps/libtomcrypt/src/modes/f8/f8_setiv.c create mode 100644 deps/libtomcrypt/src/modes/f8/f8_start.c create mode 100644 deps/libtomcrypt/src/modes/f8/f8_test_mode.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_done.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_getiv.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_process.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_setiv.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_start.c create mode 100644 deps/libtomcrypt/src/modes/lrw/lrw_test.c create mode 100644 deps/libtomcrypt/src/modes/ofb/ofb_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/ofb/ofb_done.c create mode 100644 deps/libtomcrypt/src/modes/ofb/ofb_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/ofb/ofb_getiv.c create mode 100644 deps/libtomcrypt/src/modes/ofb/ofb_setiv.c create mode 100644 deps/libtomcrypt/src/modes/ofb/ofb_start.c create mode 100644 deps/libtomcrypt/src/modes/xts/xts_decrypt.c create mode 100644 deps/libtomcrypt/src/modes/xts/xts_done.c create mode 100644 deps/libtomcrypt/src/modes/xts/xts_encrypt.c create mode 100644 deps/libtomcrypt/src/modes/xts/xts_init.c create mode 100644 deps/libtomcrypt/src/modes/xts/xts_mult_x.c create mode 100644 deps/libtomcrypt/src/modes/xts/xts_test.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c create mode 100644 deps/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c create mode 100644 deps/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c create mode 100644 deps/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c create mode 100644 deps/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c create mode 100644 deps/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c create mode 100644 deps/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c create mode 100644 deps/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_check_pubkey.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_export.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_export_key.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_free.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_generate_key.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_import.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_set.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c create mode 100644 deps/libtomcrypt/src/pk/dh/dh_shared_secret.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_export.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_free.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_generate_key.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_import.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_make_key.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_set.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_shared_secret.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_sign_hash.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_verify_hash.c create mode 100644 deps/libtomcrypt/src/pk/dsa/dsa_verify_key.c create mode 100644 deps/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c create mode 100644 deps/libtomcrypt/src/pk/ec25519/ec25519_export.c create mode 100644 deps/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c create mode 100644 deps/libtomcrypt/src/pk/ec25519/tweetnacl.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_export.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_export_openssl.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_find_curve.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_free.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_get_key.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_get_size.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_import.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_import_openssl.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_import_x509.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_make_key.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_recover_key.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_set_curve.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_set_key.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_shared_secret.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_sign_hash.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_sizes.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ecc_verify_hash.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_map.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_points.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c create mode 100644 deps/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_export.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_import.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_make_key.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_sign.c create mode 100644 deps/libtomcrypt/src/pk/ed25519/ed25519_verify.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c create mode 100644 deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_export.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_exptmod.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_get_size.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_import.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_import_x509.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_key.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_make_key.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_set.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_sign_hash.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c create mode 100644 deps/libtomcrypt/src/pk/rsa/rsa_verify_hash.c create mode 100644 deps/libtomcrypt/src/pk/x25519/x25519_export.c create mode 100644 deps/libtomcrypt/src/pk/x25519/x25519_import.c create mode 100644 deps/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c create mode 100644 deps/libtomcrypt/src/pk/x25519/x25519_import_raw.c create mode 100644 deps/libtomcrypt/src/pk/x25519/x25519_import_x509.c create mode 100644 deps/libtomcrypt/src/pk/x25519/x25519_make_key.c create mode 100644 deps/libtomcrypt/src/pk/x25519/x25519_shared_secret.c create mode 100644 deps/libtomcrypt/src/prngs/chacha20.c create mode 100644 deps/libtomcrypt/src/prngs/fortuna.c create mode 100644 deps/libtomcrypt/src/prngs/rc4.c create mode 100644 deps/libtomcrypt/src/prngs/rng_get_bytes.c create mode 100644 deps/libtomcrypt/src/prngs/rng_make_prng.c create mode 100644 deps/libtomcrypt/src/prngs/sober128.c create mode 100644 deps/libtomcrypt/src/prngs/sprng.c create mode 100644 deps/libtomcrypt/src/prngs/yarrow.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_crypt.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_done.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_ivctr32.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_ivctr64.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_keystream.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_memory.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_setup.c create mode 100644 deps/libtomcrypt/src/stream/chacha/chacha_test.c create mode 100644 deps/libtomcrypt/src/stream/rabbit/rabbit.c create mode 100644 deps/libtomcrypt/src/stream/rabbit/rabbit_memory.c create mode 100644 deps/libtomcrypt/src/stream/rc4/rc4_stream.c create mode 100644 deps/libtomcrypt/src/stream/rc4/rc4_stream_memory.c create mode 100644 deps/libtomcrypt/src/stream/rc4/rc4_test.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/salsa20_crypt.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/salsa20_done.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/salsa20_keystream.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/salsa20_memory.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/salsa20_setup.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/salsa20_test.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c create mode 100644 deps/libtomcrypt/src/stream/salsa20/xsalsa20_test.c create mode 100644 deps/libtomcrypt/src/stream/sober128/sober128_stream.c create mode 100644 deps/libtomcrypt/src/stream/sober128/sober128_stream_memory.c create mode 100644 deps/libtomcrypt/src/stream/sober128/sober128_test.c create mode 100644 deps/libtomcrypt/src/stream/sober128/sober128tab.c create mode 100644 deps/libtomcrypt/src/stream/sosemanuk/sosemanuk.c create mode 100644 deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c create mode 100644 deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c create mode 100644 deps/libtomcrypt/testme.sh create mode 100644 deps/libtomcrypt/tests/CMakeLists.txt create mode 100644 deps/libtomcrypt/tests/asn1/0x00.crt create mode 100644 deps/libtomcrypt/tests/asn1/0x80.crt create mode 100644 deps/libtomcrypt/tests/asn1/0xff.crt create mode 100644 deps/libtomcrypt/tests/asn1/illegal_padding1.crt create mode 100644 deps/libtomcrypt/tests/asn1/illegal_padding2.crt create mode 100644 deps/libtomcrypt/tests/asn1/illegal_padding3.crt create mode 100644 deps/libtomcrypt/tests/asn1/oid_overflow_test.der create mode 100644 deps/libtomcrypt/tests/asn1/oid_size_test.der create mode 100644 deps/libtomcrypt/tests/asn1/private.der create mode 100644 deps/libtomcrypt/tests/asn1/root-ca.der create mode 100644 deps/libtomcrypt/tests/asn1/type0x08.crt create mode 100644 deps/libtomcrypt/tests/base16_test.c create mode 100644 deps/libtomcrypt/tests/base32_test.c create mode 100644 deps/libtomcrypt/tests/base64_test.c create mode 100644 deps/libtomcrypt/tests/bcrypt_test.c create mode 100644 deps/libtomcrypt/tests/cipher_hash_test.c create mode 100644 deps/libtomcrypt/tests/common.c create mode 100644 deps/libtomcrypt/tests/common.h create mode 100644 deps/libtomcrypt/tests/der_test.c create mode 100644 deps/libtomcrypt/tests/dh_test.c create mode 100644 deps/libtomcrypt/tests/dsa_test.c create mode 100644 deps/libtomcrypt/tests/ecc_test.c create mode 100644 deps/libtomcrypt/tests/ed25519_test.c create mode 100644 deps/libtomcrypt/tests/file_test.c create mode 100644 deps/libtomcrypt/tests/mac_test.c create mode 100644 deps/libtomcrypt/tests/misc_test.c create mode 100644 deps/libtomcrypt/tests/modes_test.c create mode 100644 deps/libtomcrypt/tests/mpi_test.c create mode 100644 deps/libtomcrypt/tests/multi_test.c create mode 100644 deps/libtomcrypt/tests/no_null_termination_check_test.c create mode 100644 deps/libtomcrypt/tests/no_prng.c create mode 100644 deps/libtomcrypt/tests/padding_test.c create mode 100644 deps/libtomcrypt/tests/pkcs_1_eme_test.c create mode 100644 deps/libtomcrypt/tests/pkcs_1_emsa_test.c create mode 100644 deps/libtomcrypt/tests/pkcs_1_oaep_test.c create mode 100644 deps/libtomcrypt/tests/pkcs_1_pss_test.c create mode 100644 deps/libtomcrypt/tests/pkcs_1_test.c create mode 100644 deps/libtomcrypt/tests/prng_test.c create mode 100644 deps/libtomcrypt/tests/rotate_test.c create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/README.txt create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md2_des.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md2_rc2_64.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md5_des.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md5_rc2_64.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_sha1_3des.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_sha1_des.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_sha1_rc2_64.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_des_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_des_ede3_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_rc2_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha224_des_ede3_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha256_des_ede3_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha384_des_ede3_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_224_aes256_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_256_aes256_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_256_rc2_40_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_256_rc2_64_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes128_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes192_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes256_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_des_ede3_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_rc2_40_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_rc2_64_cbc.der create mode 100644 deps/libtomcrypt/tests/rsa/rsa_size_1024_bits.der create mode 100644 deps/libtomcrypt/tests/rsa/rsa_size_16384_bits.der create mode 100644 deps/libtomcrypt/tests/rsa/rsa_size_1999_bits.der create mode 100644 deps/libtomcrypt/tests/rsa/rsa_size_2048_bits.der create mode 100644 deps/libtomcrypt/tests/rsa/rsa_size_4096_bits.der create mode 100644 deps/libtomcrypt/tests/rsa/rsa_size_512_bits.der create mode 100644 deps/libtomcrypt/tests/rsa/rsa_size_8192_bits.der create mode 100644 deps/libtomcrypt/tests/rsa_test.c create mode 100644 deps/libtomcrypt/tests/sources.cmake create mode 100644 deps/libtomcrypt/tests/ssh_test.c create mode 100644 deps/libtomcrypt/tests/store_test.c create mode 100644 deps/libtomcrypt/tests/test.c create mode 100644 deps/libtomcrypt/tests/test.der create mode 100644 deps/libtomcrypt/tests/test.key create mode 100644 deps/libtomcrypt/tests/test_dsa.key create mode 100644 deps/libtomcrypt/tests/tomcrypt_test.h create mode 100644 deps/libtomcrypt/tests/x25519_test.c create mode 100644 deps/libtomcrypt/updatemakes.sh delete mode 160000 deps/libtommath create mode 100644 deps/libtommath/.gitattributes create mode 100644 deps/libtommath/.github/workflows/deploy.yml create mode 100644 deps/libtommath/.github/workflows/main.yml create mode 100644 deps/libtommath/.gitignore create mode 100644 deps/libtommath/CMakeLists.txt create mode 100644 deps/libtommath/LICENSE create mode 100644 deps/libtommath/Package.swift create mode 100644 deps/libtommath/README.md create mode 100644 deps/libtommath/appveyor.yml create mode 100644 deps/libtommath/astylerc create mode 100644 deps/libtommath/changes.txt create mode 100644 deps/libtommath/demo/CMakeLists.txt create mode 100644 deps/libtommath/demo/mtest_opponent.c create mode 100644 deps/libtommath/demo/s_mp_rand_jenkins.c create mode 100644 deps/libtommath/demo/shared.c create mode 100644 deps/libtommath/demo/shared.h create mode 100644 deps/libtommath/demo/test.c create mode 100644 deps/libtommath/demo/timing.c create mode 100644 deps/libtommath/demo/tommath_tests.swift create mode 100644 deps/libtommath/doc/.latexindent.yaml create mode 100644 deps/libtommath/doc/bn.tex create mode 100644 deps/libtommath/doc/makefile create mode 100644 deps/libtommath/etc/2kprime.1 create mode 100644 deps/libtommath/etc/2kprime.c create mode 100644 deps/libtommath/etc/drprime.c create mode 100644 deps/libtommath/etc/drprimes.28 create mode 100644 deps/libtommath/etc/drprimes.txt create mode 100644 deps/libtommath/etc/makefile create mode 100644 deps/libtommath/etc/makefile.icc create mode 100644 deps/libtommath/etc/makefile.msvc create mode 100644 deps/libtommath/etc/mersenne.c create mode 100644 deps/libtommath/etc/mont.c create mode 100644 deps/libtommath/etc/pprime.c create mode 100644 deps/libtommath/etc/prime.1024 create mode 100644 deps/libtommath/etc/prime.512 create mode 100644 deps/libtommath/etc/timer.asm create mode 100644 deps/libtommath/etc/tune.c create mode 100644 deps/libtommath/etc/tune_it.sh create mode 100644 deps/libtommath/helper.pl create mode 100644 deps/libtommath/libtommath.pc.in create mode 100644 deps/libtommath/libtommath_VS2008.sln create mode 100644 deps/libtommath/libtommath_VS2008.vcproj create mode 100644 deps/libtommath/logs/Makefile create mode 100644 deps/libtommath/logs/README create mode 100644 deps/libtommath/logs/before_after.dem create mode 100644 deps/libtommath/logs/before_after.html create mode 100644 deps/libtommath/logs/graphs.dem create mode 100644 deps/libtommath/logs/index.html create mode 100644 deps/libtommath/makefile create mode 100644 deps/libtommath/makefile.mingw create mode 100644 deps/libtommath/makefile.msvc create mode 100644 deps/libtommath/makefile.shared create mode 100644 deps/libtommath/makefile.unix create mode 100644 deps/libtommath/makefile_include.mk create mode 100644 deps/libtommath/modulemap/module.modulemap create mode 100644 deps/libtommath/mp_2expt.c create mode 100644 deps/libtommath/mp_abs.c create mode 100644 deps/libtommath/mp_add.c create mode 100644 deps/libtommath/mp_add_d.c create mode 100644 deps/libtommath/mp_addmod.c create mode 100644 deps/libtommath/mp_and.c create mode 100644 deps/libtommath/mp_clamp.c create mode 100644 deps/libtommath/mp_clear.c create mode 100644 deps/libtommath/mp_clear_multi.c create mode 100644 deps/libtommath/mp_cmp.c create mode 100644 deps/libtommath/mp_cmp_d.c create mode 100644 deps/libtommath/mp_cmp_mag.c create mode 100644 deps/libtommath/mp_cnt_lsb.c create mode 100644 deps/libtommath/mp_complement.c create mode 100644 deps/libtommath/mp_copy.c create mode 100644 deps/libtommath/mp_count_bits.c create mode 100644 deps/libtommath/mp_cutoffs.c create mode 100644 deps/libtommath/mp_div.c create mode 100644 deps/libtommath/mp_div_2.c create mode 100644 deps/libtommath/mp_div_2d.c create mode 100644 deps/libtommath/mp_div_d.c create mode 100644 deps/libtommath/mp_dr_is_modulus.c create mode 100644 deps/libtommath/mp_dr_reduce.c create mode 100644 deps/libtommath/mp_dr_setup.c create mode 100644 deps/libtommath/mp_error_to_string.c create mode 100644 deps/libtommath/mp_exch.c create mode 100644 deps/libtommath/mp_expt_n.c create mode 100644 deps/libtommath/mp_exptmod.c create mode 100644 deps/libtommath/mp_exteuclid.c create mode 100644 deps/libtommath/mp_fread.c create mode 100644 deps/libtommath/mp_from_sbin.c create mode 100644 deps/libtommath/mp_from_ubin.c create mode 100644 deps/libtommath/mp_fwrite.c create mode 100644 deps/libtommath/mp_gcd.c create mode 100644 deps/libtommath/mp_get_double.c create mode 100644 deps/libtommath/mp_get_i32.c create mode 100644 deps/libtommath/mp_get_i64.c create mode 100644 deps/libtommath/mp_get_l.c create mode 100644 deps/libtommath/mp_get_mag_u32.c create mode 100644 deps/libtommath/mp_get_mag_u64.c create mode 100644 deps/libtommath/mp_get_mag_ul.c create mode 100644 deps/libtommath/mp_grow.c create mode 100644 deps/libtommath/mp_hash.c create mode 100644 deps/libtommath/mp_init.c create mode 100644 deps/libtommath/mp_init_copy.c create mode 100644 deps/libtommath/mp_init_i32.c create mode 100644 deps/libtommath/mp_init_i64.c create mode 100644 deps/libtommath/mp_init_l.c create mode 100644 deps/libtommath/mp_init_multi.c create mode 100644 deps/libtommath/mp_init_set.c create mode 100644 deps/libtommath/mp_init_size.c create mode 100644 deps/libtommath/mp_init_u32.c create mode 100644 deps/libtommath/mp_init_u64.c create mode 100644 deps/libtommath/mp_init_ul.c create mode 100644 deps/libtommath/mp_invmod.c create mode 100644 deps/libtommath/mp_is_square.c create mode 100644 deps/libtommath/mp_kronecker.c create mode 100644 deps/libtommath/mp_lcm.c create mode 100644 deps/libtommath/mp_log.c create mode 100644 deps/libtommath/mp_log_n.c create mode 100644 deps/libtommath/mp_lshd.c create mode 100644 deps/libtommath/mp_mod.c create mode 100644 deps/libtommath/mp_mod_2d.c create mode 100644 deps/libtommath/mp_montgomery_calc_normalization.c create mode 100644 deps/libtommath/mp_montgomery_reduce.c create mode 100644 deps/libtommath/mp_montgomery_setup.c create mode 100644 deps/libtommath/mp_mul.c create mode 100644 deps/libtommath/mp_mul_2.c create mode 100644 deps/libtommath/mp_mul_2d.c create mode 100644 deps/libtommath/mp_mul_d.c create mode 100644 deps/libtommath/mp_mulmod.c create mode 100644 deps/libtommath/mp_neg.c create mode 100644 deps/libtommath/mp_or.c create mode 100644 deps/libtommath/mp_pack.c create mode 100644 deps/libtommath/mp_pack_count.c create mode 100644 deps/libtommath/mp_prime_fermat.c create mode 100644 deps/libtommath/mp_prime_frobenius_underwood.c create mode 100644 deps/libtommath/mp_prime_is_prime.c create mode 100644 deps/libtommath/mp_prime_miller_rabin.c create mode 100644 deps/libtommath/mp_prime_next_prime.c create mode 100644 deps/libtommath/mp_prime_rabin_miller_trials.c create mode 100644 deps/libtommath/mp_prime_rand.c create mode 100644 deps/libtommath/mp_prime_strong_lucas_selfridge.c create mode 100644 deps/libtommath/mp_radix_size.c create mode 100644 deps/libtommath/mp_radix_size_overestimate.c create mode 100644 deps/libtommath/mp_rand.c create mode 100644 deps/libtommath/mp_rand_source.c create mode 100644 deps/libtommath/mp_read_radix.c create mode 100644 deps/libtommath/mp_reduce.c create mode 100644 deps/libtommath/mp_reduce_2k.c create mode 100644 deps/libtommath/mp_reduce_2k_l.c create mode 100644 deps/libtommath/mp_reduce_2k_setup.c create mode 100644 deps/libtommath/mp_reduce_2k_setup_l.c create mode 100644 deps/libtommath/mp_reduce_is_2k.c create mode 100644 deps/libtommath/mp_reduce_is_2k_l.c create mode 100644 deps/libtommath/mp_reduce_setup.c create mode 100644 deps/libtommath/mp_root_n.c create mode 100644 deps/libtommath/mp_rshd.c create mode 100644 deps/libtommath/mp_sbin_size.c create mode 100644 deps/libtommath/mp_set.c create mode 100644 deps/libtommath/mp_set_double.c create mode 100644 deps/libtommath/mp_set_i32.c create mode 100644 deps/libtommath/mp_set_i64.c create mode 100644 deps/libtommath/mp_set_l.c create mode 100644 deps/libtommath/mp_set_u32.c create mode 100644 deps/libtommath/mp_set_u64.c create mode 100644 deps/libtommath/mp_set_ul.c create mode 100644 deps/libtommath/mp_shrink.c create mode 100644 deps/libtommath/mp_signed_rsh.c create mode 100644 deps/libtommath/mp_sqrmod.c create mode 100644 deps/libtommath/mp_sqrt.c create mode 100644 deps/libtommath/mp_sqrtmod_prime.c create mode 100644 deps/libtommath/mp_sub.c create mode 100644 deps/libtommath/mp_sub_d.c create mode 100644 deps/libtommath/mp_submod.c create mode 100644 deps/libtommath/mp_to_radix.c create mode 100644 deps/libtommath/mp_to_sbin.c create mode 100644 deps/libtommath/mp_to_ubin.c create mode 100644 deps/libtommath/mp_ubin_size.c create mode 100644 deps/libtommath/mp_unpack.c create mode 100644 deps/libtommath/mp_xor.c create mode 100644 deps/libtommath/mp_zero.c create mode 100644 deps/libtommath/s_mp_add.c create mode 100644 deps/libtommath/s_mp_copy_digs.c create mode 100644 deps/libtommath/s_mp_div_3.c create mode 100644 deps/libtommath/s_mp_div_recursive.c create mode 100644 deps/libtommath/s_mp_div_school.c create mode 100644 deps/libtommath/s_mp_div_small.c create mode 100644 deps/libtommath/s_mp_exptmod.c create mode 100644 deps/libtommath/s_mp_exptmod_fast.c create mode 100644 deps/libtommath/s_mp_fp_log.c create mode 100644 deps/libtommath/s_mp_fp_log_d.c create mode 100644 deps/libtommath/s_mp_get_bit.c create mode 100644 deps/libtommath/s_mp_invmod.c create mode 100644 deps/libtommath/s_mp_invmod_odd.c create mode 100644 deps/libtommath/s_mp_log_2expt.c create mode 100644 deps/libtommath/s_mp_montgomery_reduce_comba.c create mode 100644 deps/libtommath/s_mp_mul.c create mode 100644 deps/libtommath/s_mp_mul_balance.c create mode 100644 deps/libtommath/s_mp_mul_comba.c create mode 100644 deps/libtommath/s_mp_mul_high.c create mode 100644 deps/libtommath/s_mp_mul_high_comba.c create mode 100644 deps/libtommath/s_mp_mul_karatsuba.c create mode 100644 deps/libtommath/s_mp_mul_toom.c create mode 100644 deps/libtommath/s_mp_prime_is_divisible.c create mode 100644 deps/libtommath/s_mp_prime_tab.c create mode 100644 deps/libtommath/s_mp_radix_map.c create mode 100644 deps/libtommath/s_mp_radix_size_overestimate.c create mode 100644 deps/libtommath/s_mp_rand_platform.c create mode 100644 deps/libtommath/s_mp_sqr.c create mode 100644 deps/libtommath/s_mp_sqr_comba.c create mode 100644 deps/libtommath/s_mp_sqr_karatsuba.c create mode 100644 deps/libtommath/s_mp_sqr_toom.c create mode 100644 deps/libtommath/s_mp_sub.c create mode 100644 deps/libtommath/s_mp_zero_buf.c create mode 100644 deps/libtommath/s_mp_zero_digs.c create mode 100644 deps/libtommath/sources.cmake create mode 100644 deps/libtommath/testme.sh create mode 100644 deps/libtommath/tommath.def create mode 100644 deps/libtommath/tommath.h create mode 100644 deps/libtommath/tommath_c89.h create mode 100644 deps/libtommath/tommath_class.h create mode 100644 deps/libtommath/tommath_cutoffs.h create mode 100644 deps/libtommath/tommath_private.h create mode 100644 deps/libtommath/tommath_superclass.h delete mode 160000 deps/minhook create mode 100644 deps/minhook/.editorconfig create mode 100644 deps/minhook/.gitignore create mode 100644 deps/minhook/AUTHORS.txt create mode 100644 deps/minhook/CMakeLists.txt create mode 100644 deps/minhook/LICENSE.txt create mode 100644 deps/minhook/README.md create mode 100644 deps/minhook/cmake/minhook-config.cmake.in create mode 100644 deps/minhook/dll_resources/MinHook.def create mode 100644 deps/minhook/dll_resources/MinHook.rc create mode 100644 deps/minhook/include/MinHook.h create mode 100644 deps/minhook/src/buffer.c create mode 100644 deps/minhook/src/buffer.h create mode 100644 deps/minhook/src/hde/hde32.c create mode 100644 deps/minhook/src/hde/hde32.h create mode 100644 deps/minhook/src/hde/hde64.c create mode 100644 deps/minhook/src/hde/hde64.h create mode 100644 deps/minhook/src/hde/pstdint.h create mode 100644 deps/minhook/src/hde/table32.h create mode 100644 deps/minhook/src/hde/table64.h create mode 100644 deps/minhook/src/hook.c create mode 100644 deps/minhook/src/trampoline.c create mode 100644 deps/minhook/src/trampoline.h delete mode 160000 deps/rapidjson create mode 100644 deps/rapidjson/.gitattributes create mode 100644 deps/rapidjson/.gitignore create mode 100644 deps/rapidjson/.gitmodules create mode 100644 deps/rapidjson/.travis.yml create mode 100644 deps/rapidjson/CHANGELOG.md create mode 100644 deps/rapidjson/CMakeLists.txt create mode 100644 deps/rapidjson/CMakeModules/FindGTestSrc.cmake create mode 100644 deps/rapidjson/RapidJSON.pc.in create mode 100644 deps/rapidjson/RapidJSONConfig.cmake.in create mode 100644 deps/rapidjson/RapidJSONConfigVersion.cmake.in create mode 100644 deps/rapidjson/appveyor.yml create mode 100644 deps/rapidjson/bin/data/abcde.txt create mode 100644 deps/rapidjson/bin/data/glossary.json create mode 100644 deps/rapidjson/bin/data/menu.json create mode 100644 deps/rapidjson/bin/data/readme.txt create mode 100644 deps/rapidjson/bin/data/sample.json create mode 100644 deps/rapidjson/bin/data/webapp.json create mode 100644 deps/rapidjson/bin/data/widget.json create mode 100644 deps/rapidjson/bin/encodings/utf16be.json create mode 100644 deps/rapidjson/bin/encodings/utf16bebom.json create mode 100644 deps/rapidjson/bin/encodings/utf16le.json create mode 100644 deps/rapidjson/bin/encodings/utf16lebom.json create mode 100644 deps/rapidjson/bin/encodings/utf32be.json create mode 100644 deps/rapidjson/bin/encodings/utf32bebom.json create mode 100644 deps/rapidjson/bin/encodings/utf32le.json create mode 100644 deps/rapidjson/bin/encodings/utf32lebom.json create mode 100644 deps/rapidjson/bin/encodings/utf8.json create mode 100644 deps/rapidjson/bin/encodings/utf8bom.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail1.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail10.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail11.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail12.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail13.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail14.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail15.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail16.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail17.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail18.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail19.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail2.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail20.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail21.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail22.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail23.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail24.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail25.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail26.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail27.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail28.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail29.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail3.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail30.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail31.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail32.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail33.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail4.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail5.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail6.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail7.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail8.json create mode 100644 deps/rapidjson/bin/jsonchecker/fail9.json create mode 100644 deps/rapidjson/bin/jsonchecker/pass1.json create mode 100644 deps/rapidjson/bin/jsonchecker/pass2.json create mode 100644 deps/rapidjson/bin/jsonchecker/pass3.json create mode 100644 deps/rapidjson/bin/jsonchecker/readme.txt create mode 100644 deps/rapidjson/bin/types/alotofkeys.json create mode 100644 deps/rapidjson/bin/types/booleans.json create mode 100644 deps/rapidjson/bin/types/floats.json create mode 100644 deps/rapidjson/bin/types/guids.json create mode 100644 deps/rapidjson/bin/types/integers.json create mode 100644 deps/rapidjson/bin/types/mixed.json create mode 100644 deps/rapidjson/bin/types/nulls.json create mode 100644 deps/rapidjson/bin/types/paragraphs.json create mode 100644 deps/rapidjson/bin/types/readme.txt create mode 100644 deps/rapidjson/bin/unittestschema/address.json create mode 100644 deps/rapidjson/bin/unittestschema/allOf_address.json create mode 100644 deps/rapidjson/bin/unittestschema/anyOf_address.json create mode 100644 deps/rapidjson/bin/unittestschema/idandref.json create mode 100644 deps/rapidjson/bin/unittestschema/oneOf_address.json create mode 100644 deps/rapidjson/contrib/natvis/LICENSE create mode 100644 deps/rapidjson/contrib/natvis/README.md create mode 100644 deps/rapidjson/contrib/natvis/rapidjson.natvis create mode 100644 deps/rapidjson/doc/CMakeLists.txt create mode 100644 deps/rapidjson/doc/Doxyfile.in create mode 100644 deps/rapidjson/doc/Doxyfile.zh-cn.in create mode 100644 deps/rapidjson/doc/diagram/architecture.dot create mode 100644 deps/rapidjson/doc/diagram/architecture.png create mode 100644 deps/rapidjson/doc/diagram/insituparsing.dot create mode 100644 deps/rapidjson/doc/diagram/insituparsing.png create mode 100644 deps/rapidjson/doc/diagram/iterative-parser-states-diagram.dot create mode 100644 deps/rapidjson/doc/diagram/iterative-parser-states-diagram.png create mode 100644 deps/rapidjson/doc/diagram/move1.dot create mode 100644 deps/rapidjson/doc/diagram/move1.png create mode 100644 deps/rapidjson/doc/diagram/move2.dot create mode 100644 deps/rapidjson/doc/diagram/move2.png create mode 100644 deps/rapidjson/doc/diagram/move3.dot create mode 100644 deps/rapidjson/doc/diagram/move3.png create mode 100644 deps/rapidjson/doc/diagram/normalparsing.dot create mode 100644 deps/rapidjson/doc/diagram/normalparsing.png create mode 100644 deps/rapidjson/doc/diagram/simpledom.dot create mode 100644 deps/rapidjson/doc/diagram/simpledom.png create mode 100644 deps/rapidjson/doc/diagram/tutorial.dot create mode 100644 deps/rapidjson/doc/diagram/tutorial.png create mode 100644 deps/rapidjson/doc/diagram/utilityclass.dot create mode 100644 deps/rapidjson/doc/diagram/utilityclass.png create mode 100644 deps/rapidjson/doc/dom.md create mode 100644 deps/rapidjson/doc/dom.zh-cn.md create mode 100644 deps/rapidjson/doc/encoding.md create mode 100644 deps/rapidjson/doc/encoding.zh-cn.md create mode 100644 deps/rapidjson/doc/faq.md create mode 100644 deps/rapidjson/doc/faq.zh-cn.md create mode 100644 deps/rapidjson/doc/features.md create mode 100644 deps/rapidjson/doc/features.zh-cn.md create mode 100644 deps/rapidjson/doc/internals.md create mode 100644 deps/rapidjson/doc/internals.zh-cn.md create mode 100644 deps/rapidjson/doc/logo/rapidjson.png create mode 100644 deps/rapidjson/doc/logo/rapidjson.svg create mode 100644 deps/rapidjson/doc/misc/DoxygenLayout.xml create mode 100644 deps/rapidjson/doc/misc/doxygenextra.css create mode 100644 deps/rapidjson/doc/misc/footer.html create mode 100644 deps/rapidjson/doc/misc/header.html create mode 100644 deps/rapidjson/doc/npm.md create mode 100644 deps/rapidjson/doc/performance.md create mode 100644 deps/rapidjson/doc/performance.zh-cn.md create mode 100644 deps/rapidjson/doc/pointer.md create mode 100644 deps/rapidjson/doc/pointer.zh-cn.md create mode 100644 deps/rapidjson/doc/sax.md create mode 100644 deps/rapidjson/doc/sax.zh-cn.md create mode 100644 deps/rapidjson/doc/schema.md create mode 100644 deps/rapidjson/doc/schema.zh-cn.md create mode 100644 deps/rapidjson/doc/stream.md create mode 100644 deps/rapidjson/doc/stream.zh-cn.md create mode 100644 deps/rapidjson/doc/tutorial.md create mode 100644 deps/rapidjson/doc/tutorial.zh-cn.md create mode 100644 deps/rapidjson/docker/debian/Dockerfile create mode 100644 deps/rapidjson/example/CMakeLists.txt create mode 100644 deps/rapidjson/example/archiver/archiver.cpp create mode 100644 deps/rapidjson/example/archiver/archiver.h create mode 100644 deps/rapidjson/example/archiver/archivertest.cpp create mode 100644 deps/rapidjson/example/capitalize/capitalize.cpp create mode 100644 deps/rapidjson/example/condense/condense.cpp create mode 100644 deps/rapidjson/example/filterkey/filterkey.cpp create mode 100644 deps/rapidjson/example/filterkeydom/filterkeydom.cpp create mode 100644 deps/rapidjson/example/jsonx/jsonx.cpp create mode 100644 deps/rapidjson/example/lookaheadparser/lookaheadparser.cpp create mode 100644 deps/rapidjson/example/messagereader/messagereader.cpp create mode 100644 deps/rapidjson/example/parsebyparts/parsebyparts.cpp create mode 100644 deps/rapidjson/example/pretty/pretty.cpp create mode 100644 deps/rapidjson/example/prettyauto/prettyauto.cpp create mode 100644 deps/rapidjson/example/schemavalidator/schemavalidator.cpp create mode 100644 deps/rapidjson/example/serialize/serialize.cpp create mode 100644 deps/rapidjson/example/simpledom/simpledom.cpp create mode 100644 deps/rapidjson/example/simplepullreader/simplepullreader.cpp create mode 100644 deps/rapidjson/example/simplereader/simplereader.cpp create mode 100644 deps/rapidjson/example/simplewriter/simplewriter.cpp create mode 100644 deps/rapidjson/example/sortkeys/sortkeys.cpp create mode 100644 deps/rapidjson/example/traverseaspointer.cpp create mode 100644 deps/rapidjson/example/tutorial/tutorial.cpp create mode 100644 deps/rapidjson/include/rapidjson/allocators.h create mode 100644 deps/rapidjson/include/rapidjson/cursorstreamwrapper.h create mode 100644 deps/rapidjson/include/rapidjson/document.h create mode 100644 deps/rapidjson/include/rapidjson/encodedstream.h create mode 100644 deps/rapidjson/include/rapidjson/encodings.h create mode 100644 deps/rapidjson/include/rapidjson/error/en.h create mode 100644 deps/rapidjson/include/rapidjson/error/error.h create mode 100644 deps/rapidjson/include/rapidjson/filereadstream.h create mode 100644 deps/rapidjson/include/rapidjson/filewritestream.h create mode 100644 deps/rapidjson/include/rapidjson/fwd.h create mode 100644 deps/rapidjson/include/rapidjson/internal/biginteger.h create mode 100644 deps/rapidjson/include/rapidjson/internal/clzll.h create mode 100644 deps/rapidjson/include/rapidjson/internal/diyfp.h create mode 100644 deps/rapidjson/include/rapidjson/internal/dtoa.h create mode 100644 deps/rapidjson/include/rapidjson/internal/ieee754.h create mode 100644 deps/rapidjson/include/rapidjson/internal/itoa.h create mode 100644 deps/rapidjson/include/rapidjson/internal/meta.h create mode 100644 deps/rapidjson/include/rapidjson/internal/pow10.h create mode 100644 deps/rapidjson/include/rapidjson/internal/regex.h create mode 100644 deps/rapidjson/include/rapidjson/internal/stack.h create mode 100644 deps/rapidjson/include/rapidjson/internal/strfunc.h create mode 100644 deps/rapidjson/include/rapidjson/internal/strtod.h create mode 100644 deps/rapidjson/include/rapidjson/internal/swap.h create mode 100644 deps/rapidjson/include/rapidjson/istreamwrapper.h create mode 100644 deps/rapidjson/include/rapidjson/memorybuffer.h create mode 100644 deps/rapidjson/include/rapidjson/memorystream.h create mode 100644 deps/rapidjson/include/rapidjson/msinttypes/inttypes.h create mode 100644 deps/rapidjson/include/rapidjson/msinttypes/stdint.h create mode 100644 deps/rapidjson/include/rapidjson/ostreamwrapper.h create mode 100644 deps/rapidjson/include/rapidjson/pointer.h create mode 100644 deps/rapidjson/include/rapidjson/prettywriter.h create mode 100644 deps/rapidjson/include/rapidjson/rapidjson.h create mode 100644 deps/rapidjson/include/rapidjson/reader.h create mode 100644 deps/rapidjson/include/rapidjson/schema.h create mode 100644 deps/rapidjson/include/rapidjson/stream.h create mode 100644 deps/rapidjson/include/rapidjson/stringbuffer.h create mode 100644 deps/rapidjson/include/rapidjson/uri.h create mode 100644 deps/rapidjson/include/rapidjson/writer.h create mode 100644 deps/rapidjson/include_dirs.js create mode 100644 deps/rapidjson/library.json create mode 100644 deps/rapidjson/license.txt create mode 100644 deps/rapidjson/package.json create mode 100644 deps/rapidjson/rapidjson.autopkg create mode 100644 deps/rapidjson/readme.md create mode 100644 deps/rapidjson/readme.zh-cn.md create mode 100644 deps/rapidjson/test/CMakeLists.txt create mode 100644 deps/rapidjson/test/perftest/CMakeLists.txt create mode 100644 deps/rapidjson/test/perftest/misctest.cpp create mode 100644 deps/rapidjson/test/perftest/perftest.cpp create mode 100644 deps/rapidjson/test/perftest/perftest.h create mode 100644 deps/rapidjson/test/perftest/platformtest.cpp create mode 100644 deps/rapidjson/test/perftest/rapidjsontest.cpp create mode 100644 deps/rapidjson/test/perftest/schematest.cpp create mode 100644 deps/rapidjson/test/unittest/CMakeLists.txt create mode 100644 deps/rapidjson/test/unittest/allocatorstest.cpp create mode 100644 deps/rapidjson/test/unittest/bigintegertest.cpp create mode 100644 deps/rapidjson/test/unittest/clzlltest.cpp create mode 100644 deps/rapidjson/test/unittest/cursorstreamwrappertest.cpp create mode 100644 deps/rapidjson/test/unittest/documenttest.cpp create mode 100644 deps/rapidjson/test/unittest/dtoatest.cpp create mode 100644 deps/rapidjson/test/unittest/encodedstreamtest.cpp create mode 100644 deps/rapidjson/test/unittest/encodingstest.cpp create mode 100644 deps/rapidjson/test/unittest/filestreamtest.cpp create mode 100644 deps/rapidjson/test/unittest/fwdtest.cpp create mode 100644 deps/rapidjson/test/unittest/istreamwrappertest.cpp create mode 100644 deps/rapidjson/test/unittest/itoatest.cpp create mode 100644 deps/rapidjson/test/unittest/jsoncheckertest.cpp create mode 100644 deps/rapidjson/test/unittest/namespacetest.cpp create mode 100644 deps/rapidjson/test/unittest/ostreamwrappertest.cpp create mode 100644 deps/rapidjson/test/unittest/platformtest.cpp create mode 100644 deps/rapidjson/test/unittest/pointertest.cpp create mode 100644 deps/rapidjson/test/unittest/prettywritertest.cpp create mode 100644 deps/rapidjson/test/unittest/readertest.cpp create mode 100644 deps/rapidjson/test/unittest/regextest.cpp create mode 100644 deps/rapidjson/test/unittest/schematest.cpp create mode 100644 deps/rapidjson/test/unittest/simdtest.cpp create mode 100644 deps/rapidjson/test/unittest/strfunctest.cpp create mode 100644 deps/rapidjson/test/unittest/stringbuffertest.cpp create mode 100644 deps/rapidjson/test/unittest/strtodtest.cpp create mode 100644 deps/rapidjson/test/unittest/unittest.cpp create mode 100644 deps/rapidjson/test/unittest/unittest.h create mode 100644 deps/rapidjson/test/unittest/uritest.cpp create mode 100644 deps/rapidjson/test/unittest/valuetest.cpp create mode 100644 deps/rapidjson/test/unittest/writertest.cpp create mode 100644 deps/rapidjson/test/valgrind.supp create mode 100644 deps/rapidjson/thirdparty/gtest/.gitignore create mode 100644 deps/rapidjson/thirdparty/gtest/.travis.yml create mode 100644 deps/rapidjson/thirdparty/gtest/BUILD.bazel create mode 100644 deps/rapidjson/thirdparty/gtest/CMakeLists.txt create mode 100644 deps/rapidjson/thirdparty/gtest/CONTRIBUTING.md create mode 100644 deps/rapidjson/thirdparty/gtest/LICENSE create mode 100644 deps/rapidjson/thirdparty/gtest/Makefile.am create mode 100644 deps/rapidjson/thirdparty/gtest/README.md create mode 100644 deps/rapidjson/thirdparty/gtest/WORKSPACE create mode 100644 deps/rapidjson/thirdparty/gtest/appveyor.yml create mode 100644 deps/rapidjson/thirdparty/gtest/ci/build-linux-autotools.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/build-linux-bazel.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/env-linux.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/env-osx.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/get-nprocessors.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/install-linux.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/install-osx.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/log-config.sh create mode 100644 deps/rapidjson/thirdparty/gtest/ci/travis.sh create mode 100644 deps/rapidjson/thirdparty/gtest/configure.ac create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/CHANGES create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/CMakeLists.txt create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/CONTRIBUTORS create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/LICENSE create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/Makefile.am create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/README.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock.pc.in create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock_main.pc.in create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/configure.ac create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/docs/CheatSheet.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/docs/CookBook.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/docs/DesignDoc.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/docs/Documentation.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/docs/ForDummies.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/docs/FrequentlyAskedQuestions.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/docs/KnownIssues.md create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-actions.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-cardinalities.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-matchers.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-more-actions.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-more-matchers.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-spec-builders.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-generated-actions.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-matchers.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/custom/gmock-port.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-internal-utils.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/internal/gmock-port.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock.sln create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock.vcproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_config.vsprops create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_main.vcproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2005/gmock_test.vcproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock.sln create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_config.props create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_main.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2010/gmock_test.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock.sln create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock_config.props create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock_main.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/msvc/2015/gmock_test.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/fuse_gmock_files.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/LICENSE create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/README create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/README.cppclean create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/__init__.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/ast.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/gmock_class.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/gmock_class_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/keywords.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/tokenize.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/cpp/utils.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/generator/gmock_gen.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/gmock-config.in create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/gmock_doctor.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/upload.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/scripts/upload_gmock.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/src/gmock-all.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/src/gmock-cardinalities.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/src/gmock-internal-utils.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/src/gmock-matchers.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/src/gmock-spec-builders.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/src/gmock.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/src/gmock_main.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/BUILD.bazel create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-actions_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-cardinalities_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-actions_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-function-mockers_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-internal-utils_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-generated-matchers_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-internal-utils_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-matchers_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-more-actions_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-nice-strict_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-port_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock-spec-builders_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_all_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_ex_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_leak_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_leak_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_link2_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_link_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_link_test.h create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_output_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_output_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_output_test_golden.txt create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_stress_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googlemock/test/gmock_test_utils.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/CHANGES create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/CMakeLists.txt create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/CONTRIBUTORS create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/LICENSE create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/Makefile.am create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/README.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/cmake/gtest.pc.in create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/cmake/gtest_main.pc.in create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/cmake/internal_utils.cmake create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/codegear/gtest.cbproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/codegear/gtest.groupproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/codegear/gtest_all.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/codegear/gtest_link.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/codegear/gtest_main.cbproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/codegear/gtest_unittest.cbproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/configure.ac create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/docs/Pkgconfig.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/docs/PumpManual.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/docs/XcodeGuide.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/docs/advanced.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/docs/faq.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/docs/primer.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/docs/samples.md create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-death-test.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-message.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-param-test.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-param-test.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-printers.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-spi.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-test-part.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest-typed-test.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest_pred_impl.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/gtest_prod.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/custom/gtest-port.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/custom/gtest-printers.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/custom/gtest.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-death-test-internal.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-filepath.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-internal.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-linked_ptr.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-param-util-generated.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-param-util-generated.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-param-util.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-port-arch.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-port.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-string.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-tuple.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-tuple.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-type-util.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/include/gtest/internal/gtest-type-util.h.pump create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/m4/acx_pthread.m4 create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/m4/gtest.m4 create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest-md.sln create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest-md.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest-md.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest.sln create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_main-md.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_main-md.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_main.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_main.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_prod_test-md.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_prod_test-md.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_prod_test.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_prod_test.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_unittest-md.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_unittest-md.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_unittest.vcxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/msvc/2010/gtest_unittest.vcxproj.filters create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/prime_tables.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample1.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample1.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample10_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample1_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample2.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample2.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample2_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample3-inl.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample3_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample4.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample4.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample4_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample5_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample6_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample7_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample8_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/samples/sample9_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/common.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/fuse_gtest_files.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/gen_gtest_pred_impl.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/gtest-config.in create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/pump.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/release_docs.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/upload.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/scripts/upload_gtest.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-all.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-death-test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-filepath.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-internal-inl.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-port.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-printers.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-test-part.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest-typed-test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/src/gtest_main.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/BUILD.bazel create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-death-test_ex_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-death-test_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-filepath_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-linked_ptr_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-listener_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-message_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-options_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-param-test2_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-param-test_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-param-test_test.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-port_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-printers_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-test-part_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-tuple_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-typed-test2_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-typed-test_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-typed-test_test.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest-unittest-api_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_all_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_assert_by_exception_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_break_on_failure_unittest.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_break_on_failure_unittest_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_catch_exceptions_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_catch_exceptions_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_color_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_color_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_env_var_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_env_var_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_environment_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_filter_unittest.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_filter_unittest_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_help_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_help_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_json_outfiles_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_json_output_unittest.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_json_test_utils.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_list_tests_unittest.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_list_tests_unittest_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_main_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_no_test_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_output_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_output_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_output_test_golden_lin.txt create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_pred_impl_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_premature_exit_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_prod_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_repeat_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_shuffle_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_shuffle_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_sole_header_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_stress_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_test_utils.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_testbridge_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_testbridge_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_throw_on_failure_ex_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_throw_on_failure_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_throw_on_failure_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_uninitialized_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_uninitialized_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_unittest.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_outfile1_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_outfile2_test_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_outfiles_test.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_output_unittest.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_output_unittest_.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/gtest_xml_test_utils.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/production.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/test/production.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Config/DebugProject.xcconfig create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Config/FrameworkTarget.xcconfig create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Config/General.xcconfig create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Config/ReleaseProject.xcconfig create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Config/StaticLibraryTarget.xcconfig create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Config/TestTarget.xcconfig create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Resources/Info.plist create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/Info.plist create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/WidgetFramework.xcodeproj/project.pbxproj create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/runtests.sh create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/widget.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/widget.h create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Samples/FrameworkSample/widget_test.cc create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Scripts/runtests.sh create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/Scripts/versiongenerate.py create mode 100644 deps/rapidjson/thirdparty/gtest/googletest/xcode/gtest.xcodeproj/project.pbxproj create mode 100644 deps/rapidjson/travis-doxygen.sh delete mode 160000 deps/udis86 create mode 100644 deps/udis86/.gitignore create mode 100644 deps/udis86/BUILD-WINDOWS create mode 100644 deps/udis86/BuildVS2010/README.txt create mode 100644 deps/udis86/BuildVS2010/build.proj create mode 100644 deps/udis86/BuildVS2010/buildVS2010.bat create mode 100644 deps/udis86/BuildVS2010/libudis86.vcxproj create mode 100644 deps/udis86/BuildVS2010/libudis86.vcxproj.filters create mode 100644 deps/udis86/BuildVS2010/udcli.vcxproj create mode 100644 deps/udis86/BuildVS2010/udcli.vcxproj.filters create mode 100644 deps/udis86/BuildVS2010/udis86.sln create mode 100644 deps/udis86/CHANGES create mode 100644 deps/udis86/INSTALL create mode 100644 deps/udis86/LICENSE create mode 100644 deps/udis86/Makefile.am create mode 100644 deps/udis86/README create mode 100644 deps/udis86/autogen.sh create mode 100644 deps/udis86/configure.ac create mode 100644 deps/udis86/docs/Makefile.am create mode 100644 deps/udis86/docs/manual/Makefile.am create mode 100644 deps/udis86/docs/manual/conf.py create mode 100644 deps/udis86/docs/manual/getstarted.rst create mode 100644 deps/udis86/docs/manual/index.rst create mode 100644 deps/udis86/docs/manual/libudis86.rst create mode 100644 deps/udis86/docs/manual/static/udis86.css create mode 100644 deps/udis86/docs/x86/Makefile.am create mode 100644 deps/udis86/docs/x86/README create mode 100644 deps/udis86/docs/x86/avx.xml create mode 100644 deps/udis86/docs/x86/optable.xml create mode 100644 deps/udis86/docs/x86/optable.xsl create mode 100644 deps/udis86/libudis86/Makefile.am create mode 100644 deps/udis86/libudis86/decode.c create mode 100644 deps/udis86/libudis86/decode.h create mode 100644 deps/udis86/libudis86/extern.h create mode 100644 deps/udis86/libudis86/syn-att.c create mode 100644 deps/udis86/libudis86/syn-intel.c create mode 100644 deps/udis86/libudis86/syn.c create mode 100644 deps/udis86/libudis86/syn.h create mode 100644 deps/udis86/libudis86/types.h create mode 100644 deps/udis86/libudis86/udint.h create mode 100644 deps/udis86/libudis86/udis86.c create mode 100644 deps/udis86/m4/ax_compare_version.m4 create mode 100644 deps/udis86/m4/ax_prog_sphinx_version.m4 create mode 100644 deps/udis86/m4/ax_prog_yasm_version.m4 create mode 100644 deps/udis86/m4/ax_with_prog.m4 create mode 100644 deps/udis86/m4/ax_with_python.m4 create mode 100644 deps/udis86/scripts/Makefile.am create mode 100644 deps/udis86/scripts/asmtest.sh create mode 100644 deps/udis86/scripts/ud_itab.py create mode 100644 deps/udis86/scripts/ud_opcode.py create mode 100644 deps/udis86/tests/Makefile.am create mode 100644 deps/udis86/tests/asm/16/disp.asm create mode 100644 deps/udis86/tests/asm/16/test16.asm create mode 100644 deps/udis86/tests/asm/32/att.asm create mode 100644 deps/udis86/tests/asm/32/att.asm.Sref create mode 100644 deps/udis86/tests/asm/32/att.asm.ref create mode 100644 deps/udis86/tests/asm/32/avx.asm create mode 100644 deps/udis86/tests/asm/32/avx.asm.Sref create mode 100644 deps/udis86/tests/asm/32/avx.asm.ref create mode 100644 deps/udis86/tests/asm/32/corner.asm create mode 100644 deps/udis86/tests/asm/32/corner.asm.ref create mode 100644 deps/udis86/tests/asm/32/disp.asm create mode 100644 deps/udis86/tests/asm/32/disp.asm.Sref create mode 100644 deps/udis86/tests/asm/32/invalid_seg.asm create mode 100644 deps/udis86/tests/asm/32/invalid_seg.asm.ref create mode 100644 deps/udis86/tests/asm/32/obscure.asm create mode 100644 deps/udis86/tests/asm/32/obscure.asm.ref create mode 100644 deps/udis86/tests/asm/32/reljmp.asm create mode 100644 deps/udis86/tests/asm/32/reljmp.asm.ref create mode 100644 deps/udis86/tests/asm/32/sext.asm create mode 100644 deps/udis86/tests/asm/32/sext.asm.ref create mode 100644 deps/udis86/tests/asm/32/test32.asm create mode 100644 deps/udis86/tests/asm/64/amd/invalid.asm create mode 100644 deps/udis86/tests/asm/64/amd/invalid.asm.ref create mode 100644 deps/udis86/tests/asm/64/avx.asm create mode 100644 deps/udis86/tests/asm/64/avx.asm.ref create mode 100644 deps/udis86/tests/asm/64/branch.asm create mode 100644 deps/udis86/tests/asm/64/branch.asm.ref create mode 100644 deps/udis86/tests/asm/64/disp.asm create mode 100644 deps/udis86/tests/asm/64/disp.asm.Sref create mode 100644 deps/udis86/tests/asm/64/disp.asm.ref create mode 100644 deps/udis86/tests/asm/64/intel/invalid.asm create mode 100644 deps/udis86/tests/asm/64/intel/invalid.asm.ref create mode 100644 deps/udis86/tests/asm/64/reljmp.asm create mode 100644 deps/udis86/tests/asm/64/reljmp.asm.ref create mode 100644 deps/udis86/tests/asm/64/sext.asm create mode 100644 deps/udis86/tests/asm/64/sext.asm.ref create mode 100644 deps/udis86/tests/asm/64/test64.asm create mode 100644 deps/udis86/tests/difftest.sh.in create mode 100644 deps/udis86/tests/installcheck.c create mode 100644 deps/udis86/tests/libcheck.c create mode 100644 deps/udis86/tests/oprgen.py create mode 100644 deps/udis86/tests/symresolve.c create mode 100644 deps/udis86/tests/symresolve.ref create mode 100644 deps/udis86/udcli/Makefile.am create mode 100644 deps/udis86/udcli/udcli.c create mode 100644 deps/udis86/udis86.h delete mode 160000 deps/zlib create mode 100644 deps/zlib/.github/workflows/cmake.yml create mode 100644 deps/zlib/.github/workflows/configure.yml create mode 100644 deps/zlib/.github/workflows/fuzz.yml create mode 100644 deps/zlib/.gitignore create mode 100644 deps/zlib/CMakeLists.txt create mode 100644 deps/zlib/ChangeLog create mode 100644 deps/zlib/FAQ create mode 100644 deps/zlib/INDEX create mode 100644 deps/zlib/LICENSE create mode 100644 deps/zlib/Makefile create mode 100644 deps/zlib/Makefile.in create mode 100644 deps/zlib/README create mode 100644 deps/zlib/adler32.c create mode 100644 deps/zlib/amiga/Makefile.pup create mode 100644 deps/zlib/amiga/Makefile.sas create mode 100644 deps/zlib/compress.c create mode 100644 deps/zlib/configure create mode 100644 deps/zlib/contrib/README.contrib create mode 100644 deps/zlib/contrib/ada/buffer_demo.adb create mode 100644 deps/zlib/contrib/ada/mtest.adb create mode 100644 deps/zlib/contrib/ada/read.adb create mode 100644 deps/zlib/contrib/ada/readme.txt create mode 100644 deps/zlib/contrib/ada/test.adb create mode 100644 deps/zlib/contrib/ada/zlib-streams.adb create mode 100644 deps/zlib/contrib/ada/zlib-streams.ads create mode 100644 deps/zlib/contrib/ada/zlib-thin.adb create mode 100644 deps/zlib/contrib/ada/zlib-thin.ads create mode 100644 deps/zlib/contrib/ada/zlib.adb create mode 100644 deps/zlib/contrib/ada/zlib.ads create mode 100644 deps/zlib/contrib/ada/zlib.gpr create mode 100644 deps/zlib/contrib/blast/Makefile create mode 100644 deps/zlib/contrib/blast/README create mode 100644 deps/zlib/contrib/blast/blast.c create mode 100644 deps/zlib/contrib/blast/blast.h create mode 100644 deps/zlib/contrib/blast/test.pk create mode 100644 deps/zlib/contrib/blast/test.txt create mode 100644 deps/zlib/contrib/delphi/ZLib.pas create mode 100644 deps/zlib/contrib/delphi/ZLibConst.pas create mode 100644 deps/zlib/contrib/delphi/readme.txt create mode 100644 deps/zlib/contrib/delphi/zlibd32.mak create mode 100644 deps/zlib/contrib/dotzlib/DotZLib.build create mode 100644 deps/zlib/contrib/dotzlib/DotZLib.chm create mode 100644 deps/zlib/contrib/dotzlib/DotZLib.sln create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/CodecBase.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/Deflater.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/DotZLib.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/GZipStream.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/Inflater.cs create mode 100644 deps/zlib/contrib/dotzlib/DotZLib/UnitTests.cs create mode 100644 deps/zlib/contrib/dotzlib/LICENSE_1_0.txt create mode 100644 deps/zlib/contrib/dotzlib/readme.txt create mode 100644 deps/zlib/contrib/gcc_gvmat64/gvmat64.S create mode 100644 deps/zlib/contrib/infback9/README create mode 100644 deps/zlib/contrib/infback9/infback9.c create mode 100644 deps/zlib/contrib/infback9/infback9.h create mode 100644 deps/zlib/contrib/infback9/inffix9.h create mode 100644 deps/zlib/contrib/infback9/inflate9.h create mode 100644 deps/zlib/contrib/infback9/inftree9.c create mode 100644 deps/zlib/contrib/infback9/inftree9.h create mode 100644 deps/zlib/contrib/iostream/test.cpp create mode 100644 deps/zlib/contrib/iostream/zfstream.cpp create mode 100644 deps/zlib/contrib/iostream/zfstream.h create mode 100644 deps/zlib/contrib/iostream2/zstream.h create mode 100644 deps/zlib/contrib/iostream2/zstream_test.cpp create mode 100644 deps/zlib/contrib/iostream3/README create mode 100644 deps/zlib/contrib/iostream3/TODO create mode 100644 deps/zlib/contrib/iostream3/test.cc create mode 100644 deps/zlib/contrib/iostream3/zfstream.cc create mode 100644 deps/zlib/contrib/iostream3/zfstream.h create mode 100644 deps/zlib/contrib/minizip/Makefile create mode 100644 deps/zlib/contrib/minizip/Makefile.am create mode 100644 deps/zlib/contrib/minizip/MiniZip64_Changes.txt create mode 100644 deps/zlib/contrib/minizip/MiniZip64_info.txt create mode 100644 deps/zlib/contrib/minizip/configure.ac create mode 100644 deps/zlib/contrib/minizip/crypt.h create mode 100644 deps/zlib/contrib/minizip/ioapi.c create mode 100644 deps/zlib/contrib/minizip/ioapi.h create mode 100644 deps/zlib/contrib/minizip/iowin32.c create mode 100644 deps/zlib/contrib/minizip/iowin32.h create mode 100644 deps/zlib/contrib/minizip/make_vms.com create mode 100644 deps/zlib/contrib/minizip/miniunz.c create mode 100644 deps/zlib/contrib/minizip/miniunzip.1 create mode 100644 deps/zlib/contrib/minizip/minizip.1 create mode 100644 deps/zlib/contrib/minizip/minizip.c create mode 100644 deps/zlib/contrib/minizip/minizip.pc.in create mode 100644 deps/zlib/contrib/minizip/mztools.c create mode 100644 deps/zlib/contrib/minizip/mztools.h create mode 100644 deps/zlib/contrib/minizip/unzip.c create mode 100644 deps/zlib/contrib/minizip/unzip.h create mode 100644 deps/zlib/contrib/minizip/zip.c create mode 100644 deps/zlib/contrib/minizip/zip.h create mode 100644 deps/zlib/contrib/pascal/example.pas create mode 100644 deps/zlib/contrib/pascal/readme.txt create mode 100644 deps/zlib/contrib/pascal/zlibd32.mak create mode 100644 deps/zlib/contrib/pascal/zlibpas.pas create mode 100644 deps/zlib/contrib/puff/Makefile create mode 100644 deps/zlib/contrib/puff/README create mode 100644 deps/zlib/contrib/puff/puff.c create mode 100644 deps/zlib/contrib/puff/puff.h create mode 100644 deps/zlib/contrib/puff/pufftest.c create mode 100644 deps/zlib/contrib/puff/zeros.raw create mode 100644 deps/zlib/contrib/testzlib/testzlib.c create mode 100644 deps/zlib/contrib/testzlib/testzlib.txt create mode 100644 deps/zlib/contrib/untgz/Makefile create mode 100644 deps/zlib/contrib/untgz/Makefile.msc create mode 100644 deps/zlib/contrib/untgz/untgz.c create mode 100644 deps/zlib/contrib/vstudio/readme.txt create mode 100644 deps/zlib/contrib/vstudio/vc10/miniunz.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters create mode 100644 deps/zlib/contrib/vstudio/vc10/minizip.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters create mode 100644 deps/zlib/contrib/vstudio/vc10/testzlib.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters create mode 100644 deps/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters create mode 100644 deps/zlib/contrib/vstudio/vc10/zlib.rc create mode 100644 deps/zlib/contrib/vstudio/vc10/zlibstat.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters create mode 100644 deps/zlib/contrib/vstudio/vc10/zlibvc.def create mode 100644 deps/zlib/contrib/vstudio/vc10/zlibvc.sln create mode 100644 deps/zlib/contrib/vstudio/vc10/zlibvc.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters create mode 100644 deps/zlib/contrib/vstudio/vc11/miniunz.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc11/minizip.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc11/testzlib.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc11/zlib.rc create mode 100644 deps/zlib/contrib/vstudio/vc11/zlibstat.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc11/zlibvc.def create mode 100644 deps/zlib/contrib/vstudio/vc11/zlibvc.sln create mode 100644 deps/zlib/contrib/vstudio/vc11/zlibvc.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc12/miniunz.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc12/minizip.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc12/testzlib.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc12/zlib.rc create mode 100644 deps/zlib/contrib/vstudio/vc12/zlibstat.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc12/zlibvc.def create mode 100644 deps/zlib/contrib/vstudio/vc12/zlibvc.sln create mode 100644 deps/zlib/contrib/vstudio/vc12/zlibvc.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc14/miniunz.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc14/minizip.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc14/testzlib.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc14/zlib.rc create mode 100644 deps/zlib/contrib/vstudio/vc14/zlibstat.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc14/zlibvc.def create mode 100644 deps/zlib/contrib/vstudio/vc14/zlibvc.sln create mode 100644 deps/zlib/contrib/vstudio/vc14/zlibvc.vcxproj create mode 100644 deps/zlib/contrib/vstudio/vc9/miniunz.vcproj create mode 100644 deps/zlib/contrib/vstudio/vc9/minizip.vcproj create mode 100644 deps/zlib/contrib/vstudio/vc9/testzlib.vcproj create mode 100644 deps/zlib/contrib/vstudio/vc9/testzlibdll.vcproj create mode 100644 deps/zlib/contrib/vstudio/vc9/zlib.rc create mode 100644 deps/zlib/contrib/vstudio/vc9/zlibstat.vcproj create mode 100644 deps/zlib/contrib/vstudio/vc9/zlibvc.def create mode 100644 deps/zlib/contrib/vstudio/vc9/zlibvc.sln create mode 100644 deps/zlib/contrib/vstudio/vc9/zlibvc.vcproj create mode 100644 deps/zlib/crc32.c create mode 100644 deps/zlib/crc32.h create mode 100644 deps/zlib/deflate.c create mode 100644 deps/zlib/deflate.h create mode 100644 deps/zlib/doc/algorithm.txt create mode 100644 deps/zlib/doc/crc-doc.1.0.pdf create mode 100644 deps/zlib/doc/rfc1950.txt create mode 100644 deps/zlib/doc/rfc1951.txt create mode 100644 deps/zlib/doc/rfc1952.txt create mode 100644 deps/zlib/doc/txtvsbin.txt create mode 100644 deps/zlib/examples/README.examples create mode 100644 deps/zlib/examples/enough.c create mode 100644 deps/zlib/examples/fitblk.c create mode 100644 deps/zlib/examples/gun.c create mode 100644 deps/zlib/examples/gzappend.c create mode 100644 deps/zlib/examples/gzjoin.c create mode 100644 deps/zlib/examples/gzlog.c create mode 100644 deps/zlib/examples/gzlog.h create mode 100644 deps/zlib/examples/gznorm.c create mode 100644 deps/zlib/examples/zlib_how.html create mode 100644 deps/zlib/examples/zpipe.c create mode 100644 deps/zlib/examples/zran.c create mode 100644 deps/zlib/examples/zran.h create mode 100644 deps/zlib/gzclose.c create mode 100644 deps/zlib/gzguts.h create mode 100644 deps/zlib/gzlib.c create mode 100644 deps/zlib/gzread.c create mode 100644 deps/zlib/gzwrite.c create mode 100644 deps/zlib/infback.c create mode 100644 deps/zlib/inffast.c create mode 100644 deps/zlib/inffast.h create mode 100644 deps/zlib/inffixed.h create mode 100644 deps/zlib/inflate.c create mode 100644 deps/zlib/inflate.h create mode 100644 deps/zlib/inftrees.c create mode 100644 deps/zlib/inftrees.h create mode 100644 deps/zlib/make_vms.com create mode 100644 deps/zlib/msdos/Makefile.bor create mode 100644 deps/zlib/msdos/Makefile.dj2 create mode 100644 deps/zlib/msdos/Makefile.emx create mode 100644 deps/zlib/msdos/Makefile.msc create mode 100644 deps/zlib/msdos/Makefile.tc create mode 100644 deps/zlib/nintendods/Makefile create mode 100644 deps/zlib/nintendods/README create mode 100644 deps/zlib/old/Makefile.emx create mode 100644 deps/zlib/old/Makefile.riscos create mode 100644 deps/zlib/old/README create mode 100644 deps/zlib/old/descrip.mms create mode 100644 deps/zlib/old/os2/Makefile.os2 create mode 100644 deps/zlib/old/os2/zlib.def create mode 100644 deps/zlib/old/visual-basic.txt create mode 100644 deps/zlib/os400/README400 create mode 100644 deps/zlib/os400/bndsrc create mode 100644 deps/zlib/os400/make.sh create mode 100644 deps/zlib/os400/zlib.inc create mode 100644 deps/zlib/qnx/package.qpg create mode 100644 deps/zlib/test/example.c create mode 100644 deps/zlib/test/infcover.c create mode 100644 deps/zlib/test/minigzip.c create mode 100644 deps/zlib/treebuild.xml create mode 100644 deps/zlib/trees.c create mode 100644 deps/zlib/trees.h create mode 100644 deps/zlib/uncompr.c create mode 100644 deps/zlib/watcom/watcom_f.mak create mode 100644 deps/zlib/watcom/watcom_l.mak create mode 100644 deps/zlib/win32/DLL_FAQ.txt create mode 100644 deps/zlib/win32/Makefile.bor create mode 100644 deps/zlib/win32/Makefile.gcc create mode 100644 deps/zlib/win32/Makefile.msc create mode 100644 deps/zlib/win32/README-WIN32.txt create mode 100644 deps/zlib/win32/VisualC.txt create mode 100644 deps/zlib/win32/zlib.def create mode 100644 deps/zlib/win32/zlib1.rc create mode 100644 deps/zlib/zconf.h create mode 100644 deps/zlib/zconf.h.cmakein create mode 100644 deps/zlib/zconf.h.in create mode 100644 deps/zlib/zlib.3 create mode 100644 deps/zlib/zlib.3.pdf create mode 100644 deps/zlib/zlib.h create mode 100644 deps/zlib/zlib.map create mode 100644 deps/zlib/zlib.pc.cmakein create mode 100644 deps/zlib/zlib.pc.in create mode 100644 deps/zlib/zlib2ansi create mode 100644 deps/zlib/zutil.c create mode 100644 deps/zlib/zutil.h diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 1cd37f2..0000000 --- a/.gitmodules +++ /dev/null @@ -1,24 +0,0 @@ -[submodule "deps/GSL"] - path = deps/GSL - url = https://github.com/microsoft/GSL.git -[submodule "deps/udis86"] - path = deps/udis86 - url = https://github.com/vmt/udis86.git -[submodule "deps/minhook"] - path = deps/minhook - url = https://github.com/TsudaKageyu/minhook.git -[submodule "deps/zlib"] - path = deps/zlib - url = https://github.com/madler/zlib.git -[submodule "deps/rapidjson"] - path = deps/rapidjson - url = https://github.com/Tencent/rapidjson.git -[submodule "deps/discord-rpc"] - path = deps/discord-rpc - url = https://github.com/discord/discord-rpc.git -[submodule "deps/libtommath"] - path = deps/libtommath - url = https://github.com/libtom/libtommath.git -[submodule "deps/libtomcrypt"] - path = deps/libtomcrypt - url = https://github.com/libtom/libtomcrypt.git diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..f8f8fec --- /dev/null +++ b/build.bat @@ -0,0 +1,5 @@ +@echo off + +"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\msbuild.exe" build\iw4-sp.sln /p:Configuration=Release /p:Platform=Win32 + +pause \ No newline at end of file diff --git a/deps/GSL b/deps/GSL deleted file mode 160000 index 303d964..0000000 --- a/deps/GSL +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 303d964a241cb2f2a058fe0baa14013eb9afa116 diff --git a/deps/GSL/.clang-format b/deps/GSL/.clang-format new file mode 100644 index 0000000..c12d3bf --- /dev/null +++ b/deps/GSL/.clang-format @@ -0,0 +1,34 @@ +ColumnLimit: 100 + +UseTab: Never +IndentWidth: 4 +AccessModifierOffset: -4 +NamespaceIndentation: Inner + +BreakBeforeBraces: Custom +BraceWrapping: + AfterNamespace: true + AfterEnum: true + AfterStruct: true + AfterClass: true + SplitEmptyFunction: false + AfterControlStatement: true + AfterFunction: true + AfterUnion: true + BeforeElse: true + + +AlwaysBreakTemplateDeclarations: true +BreakConstructorInitializersBeforeComma: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true +AllowShortBlocksOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: true + +PointerAlignment: Left +AlignConsecutiveAssignments: false +AlignTrailingComments: true + +SpaceAfterCStyleCast: true +CommentPragmas: '^ NO-FORMAT:' diff --git a/deps/GSL/.gitattributes b/deps/GSL/.gitattributes new file mode 100644 index 0000000..3455dc9 --- /dev/null +++ b/deps/GSL/.gitattributes @@ -0,0 +1 @@ +include/gsl/* linguist-language=C++ diff --git a/deps/GSL/.github/workflows/android.yml b/deps/GSL/.github/workflows/android.yml new file mode 100644 index 0000000..dd0b5a4 --- /dev/null +++ b/deps/GSL/.github/workflows/android.yml @@ -0,0 +1,50 @@ +name: CI_Android +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + Android: + runs-on: macos-latest + defaults: + run: + working-directory: build + steps: + - uses: actions/checkout@v2 + + - name: Create build directory + run: mkdir -p build + working-directory: . + + - name: Start emulator + run: | + echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-24;default;x86_64' + echo "no" | $ANDROID_HOME/tools/bin/avdmanager create avd -n xamarin_android_emulator -k 'system-images;android-24;default;x86_64' --force + $ANDROID_HOME/emulator/emulator -list-avds + echo "Starting emulator" + # Start emulator in background + nohup $ANDROID_HOME/emulator/emulator -avd xamarin_android_emulator -no-snapshot > /dev/null 2>&1 & + echo "Emulator starting" + + - name: Configure + run: cmake -Werror=dev -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_LATEST_HOME/build/cmake/android.toolchain.cmake -DANDROID_PLATFORM=16 -DANDROID_ABI=x86_64 -DCMAKE_BUILD_TYPE=Debug .. + + - name: Build + run: cmake --build . --parallel + + - name: Wait for emulator ready + run: | + $ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 10; done; input keyevent 82' + $ANDROID_HOME/platform-tools/adb devices + $ANDROID_HOME/platform-tools/adb shell getprop ro.product.cpu.abi + echo "Emulator started" + + - name: Deploy tests + run: | + adb push tests /data/local/tmp + adb shell find /data/local/tmp/tests -maxdepth 1 -exec chmod +x {} \\\; + + - name: Test + run: adb shell find /data/local/tmp/tests -name "*_tests" -maxdepth 1 -exec {} \\\; diff --git a/deps/GSL/.github/workflows/cmake_find_package.yml b/deps/GSL/.github/workflows/cmake_find_package.yml new file mode 100644 index 0000000..5155d9c --- /dev/null +++ b/deps/GSL/.github/workflows/cmake_find_package.yml @@ -0,0 +1,25 @@ +name: cmake_find_package +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + cmake-find-package: + name: Build ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest, macos-latest ] + steps: + - uses: actions/checkout@v3 + - uses: lukka/get-cmake@latest + with: + cmakeVersion: 3.14.0 + - name: Configure GSL + run: cmake -S . -B build -G "Ninja" -D GSL_TEST=OFF -D CMAKE_INSTALL_PREFIX=${GITHUB_WORKSPACE}/build/install + - name: Install GSL + run: cmake --build build --target install + - name: Test GSL find_package support + run: cmake -S tests/ -B build/tests_find_package -G "Ninja" -D CMAKE_PREFIX_PATH=${GITHUB_WORKSPACE}/build/install -D CMAKE_BUILD_TYPE=Release diff --git a/deps/GSL/.github/workflows/ios.yml b/deps/GSL/.github/workflows/ios.yml new file mode 100644 index 0000000..d231b4c --- /dev/null +++ b/deps/GSL/.github/workflows/ios.yml @@ -0,0 +1,52 @@ +name: CI_iOS +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + iOS: + runs-on: macos-latest + defaults: + run: + working-directory: build + steps: + - uses: actions/checkout@v2 + + - name: Create build directory + run: mkdir -p build + working-directory: . + + - name: Configure + run: | + cmake \ + -Werror=dev \ + -GXcode \ + -DCMAKE_SYSTEM_NAME=iOS \ + "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" \ + -DCMAKE_OSX_DEPLOYMENT_TARGET=9 \ + -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \ + "-DMACOSX_BUNDLE_GUI_IDENTIFIER=GSL.\$(EXECUTABLE_NAME)" \ + -DMACOSX_BUNDLE_BUNDLE_VERSION=3.1.0 \ + -DMACOSX_BUNDLE_SHORT_VERSION_STRING=3.1.0 \ + .. + + - name: Build + run: cmake --build . --parallel `sysctl -n hw.ncpu` --config Release -- -sdk iphonesimulator + + - name: Start simulator + run: | + RUNTIME=`xcrun simctl list runtimes iOS -j|jq '.runtimes|last.identifier'` + UDID=`xcrun simctl list devices iPhone available -j|jq -r ".devices[$RUNTIME]|last.udid"` + xcrun simctl bootstatus $UDID -b + + - name: Test + run: | + for TEST in `find tests/Release-iphonesimulator -depth 1 -name "*.app"` + do + xcrun simctl install booted $TEST + TEST_ID=`plutil -convert json -o - $TEST/Info.plist|jq -r ".CFBundleIdentifier"` + xcrun simctl launch --console booted $TEST_ID + xcrun simctl uninstall booted $TEST_ID + done diff --git a/deps/GSL/.gitignore b/deps/GSL/.gitignore new file mode 100644 index 0000000..326971f --- /dev/null +++ b/deps/GSL/.gitignore @@ -0,0 +1,16 @@ +CMakeFiles +build +tests/CMakeFiles +tests/Debug +*.opensdf +*.sdf +tests/*tests.dir +*.vcxproj +*.vcxproj.filters +*.sln +*.tlog +Testing/Temporary/*.* +CMakeCache.txt +*.suo +.vs/ +.vscode/ diff --git a/deps/GSL/CMakeLists.txt b/deps/GSL/CMakeLists.txt new file mode 100644 index 0000000..71bb997 --- /dev/null +++ b/deps/GSL/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.14...3.16) + +project(GSL VERSION 4.0.0 LANGUAGES CXX) + +add_library(GSL INTERFACE) +add_library(Microsoft.GSL::GSL ALIAS GSL) + +# https://cmake.org/cmake/help/latest/variable/PROJECT_IS_TOP_LEVEL.html +string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} PROJECT_IS_TOP_LEVEL) + +option(GSL_INSTALL "Generate and install GSL target" ${PROJECT_IS_TOP_LEVEL}) +option(GSL_TEST "Build and perform GSL tests" ${PROJECT_IS_TOP_LEVEL}) + +# The implementation generally assumes a platform that implements C++14 support +target_compile_features(GSL INTERFACE "cxx_std_14") + +# Setup include directory +add_subdirectory(include) + +target_sources(GSL INTERFACE $) + +if (GSL_TEST) + enable_testing() + add_subdirectory(tests) +endif() + +if (GSL_INSTALL) + include(GNUInstallDirs) + include(CMakePackageConfigHelpers) + + install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/gsl" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + + set(export_name "Microsoft.GSLConfig") + set(namespace "Microsoft.GSL::") + set(cmake_files_install_dir ${CMAKE_INSTALL_DATADIR}/cmake/Microsoft.GSL) + + install(TARGETS GSL EXPORT ${export_name} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(EXPORT ${export_name} NAMESPACE ${namespace} DESTINATION ${cmake_files_install_dir}) + export(TARGETS GSL NAMESPACE ${namespace} FILE ${export_name}.cmake) + + set(gls_config_version "${CMAKE_CURRENT_BINARY_DIR}/Microsoft.GSLConfigVersion.cmake") + + write_basic_package_version_file(${gls_config_version} COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT) + + install(FILES ${gls_config_version} DESTINATION ${cmake_files_install_dir}) + + install(FILES GSL.natvis DESTINATION ${cmake_files_install_dir}) +endif() diff --git a/deps/GSL/CMakeSettings.json b/deps/GSL/CMakeSettings.json new file mode 100644 index 0000000..2e1ad24 --- /dev/null +++ b/deps/GSL/CMakeSettings.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ + "msvc_x64_x64" + ], + "buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}", + "installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}", + "cmakeCommandArgs": "-DGSL_CXX_STANDARD=17", + "buildCommandArgs": "-v", + "ctestCommandArgs": "", + "codeAnalysisRuleset": "CppCoreCheckRules.ruleset" + } + ] +} \ No newline at end of file diff --git a/deps/GSL/CONTRIBUTING.md b/deps/GSL/CONTRIBUTING.md new file mode 100644 index 0000000..e28f534 --- /dev/null +++ b/deps/GSL/CONTRIBUTING.md @@ -0,0 +1,29 @@ +## Contributing to the Guidelines Support Library + +The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the +[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines). GSL design changes are made only as a result of modifications to the Guidelines. + +GSL is accepting contributions that improve or refine any of the types in this library as well as ports to other platforms. Changes should have an issue +tracking the suggestion that has been approved by the maintainers. Your pull request should include a link to the bug that you are fixing. If you've submitted +a PR, please post a comment in the associated issue to avoid duplication of effort. + +## Legal +You will need to complete a Contributor License Agreement (CLA). Briefly, this agreement testifies that you are granting us and the community permission to +use the submitted change according to the terms of the project's license, and that the work being submitted is under appropriate copyright. + +Please submit a Contributor License Agreement (CLA) before submitting a pull request. You may visit https://cla.microsoft.com to sign digitally. + +## Housekeeping +Your pull request should: + +* Include a description of what your change intends to do +* Be a child commit of a reasonably recent commit in the **main** branch + * Requests need not be a single commit, but should be a linear sequence of commits (i.e. no merge commits in your PR) +* It is desirable, but not necessary, for the tests to pass at each commit. Please see [README.md](./README.md) for instructions to build the test suite. +* Have clear commit messages + * e.g. "Fix issue", "Add tests for type", etc. +* Include appropriate tests + * Tests should include reasonable permutations of the target fix/change + * Include baseline changes with your change + * All changed code must have 100% code coverage +* To avoid line ending issues, set `autocrlf = input` and `whitespace = cr-at-eol` in your git configuration diff --git a/deps/GSL/GSL.natvis b/deps/GSL/GSL.natvis new file mode 100644 index 0000000..965888c --- /dev/null +++ b/deps/GSL/GSL.natvis @@ -0,0 +1,32 @@ + + + + + + {{ invoke = {invoke_}, action = {f_} }} + + invoke_ + f_ + + + + + + {{ extent = {storage_.size_} }} + + + storage_.size_ + storage_.data_ + + + + + + + + value = {*ptr_} + + diff --git a/deps/GSL/LICENSE b/deps/GSL/LICENSE new file mode 100644 index 0000000..aa58667 --- /dev/null +++ b/deps/GSL/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2015 Microsoft Corporation. All rights reserved. + +This code is licensed under the MIT License (MIT). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/deps/GSL/README.md b/deps/GSL/README.md new file mode 100644 index 0000000..725bf66 --- /dev/null +++ b/deps/GSL/README.md @@ -0,0 +1,218 @@ +# GSL: Guidelines Support Library +[![Build Status](https://dev.azure.com/cppstat/GSL/_apis/build/status/microsoft.GSL?branchName=main)](https://dev.azure.com/cppstat/GSL/_build/latest?definitionId=1&branchName=main) + +The Guidelines Support Library (GSL) contains functions and types that are suggested for use by the +[C++ Core Guidelines](https://github.com/isocpp/CppCoreGuidelines) maintained by the [Standard C++ Foundation](https://isocpp.org). +This repo contains Microsoft's implementation of GSL. + +The entire implementation is provided inline in the headers under the [gsl](./include/gsl) directory. The implementation generally assumes a platform that implements C++14 support. + +While some types have been broken out into their own headers (e.g. [gsl/span](./include/gsl/span)), +it is simplest to just include [gsl/gsl](./include/gsl/gsl) and gain access to the entire library. + +> NOTE: We encourage contributions that improve or refine any of the types in this library as well as ports to +other platforms. Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for more information about contributing. + +# Project Code of Conduct +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +# Usage of Third Party Libraries +This project makes use of the [Google Test](https://github.com/google/googletest) testing library. Please see the [ThirdPartyNotices.txt](./ThirdPartyNotices.txt) file for details regarding the licensing of Google Test. + +# Supported features +## Microsoft GSL implements the following from the C++ Core Guidelines: + +Feature | Supported? | Description +-------------------------------------------------------------------------|:----------:|------------- +[**1. Views**][cg-views] | | +[owner](docs/headers.md#user-content-H-pointers-owner) | ☑ | An alias for a raw pointer +[not_null](docs/headers.md#user-content-H-pointers-not_null) | ☑ | Restricts a pointer / smart pointer to hold non-null values +[span](docs/headers.md#user-content-H-span-span) | ☑ | A view over a contiguous sequence of memory. Based on the standardized version of `std::span`, however `gsl::span` enforces bounds checking. +span_p | ☐ | Spans a range starting from a pointer to the first place for which the predicate is true +[basic_zstring](docs/headers.md#user-content-H-string_span) | ☑ | A pointer to a C-string (zero-terminated array) with a templated char type +[zstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of char +[czstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const char +[wzstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of wchar_t +[cwzstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const wchar_t +[u16zstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of char16_t +[cu16zstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const char16_t +[u32zstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of char32_t +[cu32zstring](docs/headers.md#user-content-H-string_span) | ☑ | An alias to `basic_zstring` with dynamic extent and a char type of const char32_t +[**2. Owners**][cg-owners] | | +[unique_ptr](docs/headers.md#user-content-H-pointers-unique_ptr) | ☑ | An alias to `std::unique_ptr` +[shared_ptr](docs/headers.md#user-content-H-pointers-shared_ptr) | ☑ | An alias to `std::shared_ptr` +stack_array | ☐ | A stack-allocated array +dyn_array | ☐ | A heap-allocated array +[**3. Assertions**][cg-assertions] | | +[Expects](docs/headers.md#user-content-H-assert-expects) | ☑ | A precondition assertion; on failure it terminates +[Ensures](docs/headers.md#user-content-H-assert-ensures) | ☑ | A postcondition assertion; on failure it terminates +[**4. Utilities**][cg-utilities] | | +move_owner | ☐ | A helper function that moves one `owner` to the other +[byte](docs/headers.md#user-content-H-byte-byte) | ☑ | Either an alias to `std::byte` or a byte type +[final_action](docs/headers.md#user-content-H-util-final_action) | ☑ | A RAII style class that invokes a functor on its destruction +[finally](docs/headers.md#user-content-H-util-finally) | ☑ | A helper function instantiating `final_action` +[GSL_SUPPRESS](docs/headers.md#user-content-H-assert-gsl_suppress) | ☑ | A macro that takes an argument and turns it into `[[gsl::suppress(x)]]` or `[[gsl::suppress("x")]]` +[[implicit]] | ☐ | A "marker" to put on single-argument constructors to explicitly make them non-explicit +[index](docs/headers.md#user-content-H-util-index) | ☑ | A type to use for all container and array indexing (currently an alias for `std::ptrdiff_t`) +joining_thread | ☐ | A RAII style version of `std::thread` that joins +[narrow](docs/headers.md#user-content-H-narrow-narrow) | ☑ | A checked version of `narrow_cast`; it can throw `narrowing_error` +[narrow_cast](docs/headers.md#user-content-H-util-narrow_cast) | ☑ | A narrowing cast for values and a synonym for `static_cast` +[narrowing_error](docs/headers.md#user-content-H-narrow-narrowing_error) | ☑ | A custom exception type thrown by `narrow()` +[**5. Concepts**][cg-concepts] | ☐ | + +## The following features do not exist in or have been removed from the C++ Core Guidelines: +Feature | Supported? | Description +-----------------------------------|:----------:|------------- +[strict_not_null](docs/headers.md#user-content-H-pointers-strict_not_null) | ☑ | A stricter version of `not_null` with explicit constructors +multi_span | ☐ | Deprecated. Multi-dimensional span. +strided_span | ☐ | Deprecated. Support for this type has been discontinued. +basic_string_span | ☐ | Deprecated. Like `span` but for strings with a templated char type +string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of char +cstring_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const char +wstring_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of wchar_t +cwstring_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const wchar_t +u16string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of char16_t +cu16string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const char16_t +u32string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of char32_t +cu32string_span | ☐ | Deprecated. An alias to `basic_string_span` with a char type of const char32_t + +This is based on [CppCoreGuidelines semi-specification](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gsl-guidelines-support-library). + +[cg-views]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslview-views +[cg-owners]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslowner-ownership-pointers +[cg-assertions]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslassert-assertions +[cg-utilities]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslutil-utilities +[cg-concepts]: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#gslconcept-concepts + +# Quick Start +## Supported Compilers / Toolsets +The GSL officially supports the latest and previous major versions of VS with MSVC & LLVM, GCC, Clang, and XCode with Apple-Clang. +Within these two major versions, we try to target the latest minor updates / revisions (although this may be affected by +delays between a toolchain's release and when it becomes widely available for use). +Below is a table showing the versions currently being tested. + +Compiler |Toolset Versions Currently Tested +:------- |--: + XCode | 13.2.1 & 12.5.1 + GCC | 11[^1] & 10[^2] + Clang | 12[^2] & 11[^2] + Visual Studio with MSVC | VS2022[^3] & VS2019[^4] + Visual Studio with LLVM | VS2022[^3] & VS2019[^4] + + +[^1]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26). +[^2]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26). Should be the version specified [here](https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md#language-and-runtime). +[^3]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26). Should be the version specified [here](https://github.com/actions/virtual-environments/blob/main/images/win/Windows2022-Readme.md#visual-studio-enterprise-2022). +[^4]: Precise version may be found in the [latest CI results](https://dev.azure.com/cppstat/GSL/_build?definitionId=1&branchFilter=26). Should be the version specified [here](https://github.com/actions/virtual-environments/blob/main/images/win/Windows2019-Readme.md#visual-studio-enterprise-2019). + +--- +If you successfully port GSL to another platform, we would love to hear from you! +- Submit an issue specifying the platform and target. +- Consider contributing your changes by filing a pull request with any necessary changes. +- If at all possible, add a CI/CD step and add the button to the table below! + +Target | CI/CD Status +:------- | -----------: +iOS | ![CI_iOS](https://github.com/microsoft/GSL/workflows/CI_iOS/badge.svg) +Android | ![CI_Android](https://github.com/microsoft/GSL/workflows/CI_Android/badge.svg) + +Note: These CI/CD steps are run with each pull request, however failures in them are non-blocking. + +## Building the tests +To build the tests, you will require the following: + +* [CMake](http://cmake.org), version 3.14 or later to be installed and in your PATH. + +These steps assume the source code of this repository has been cloned into a directory named `c:\GSL`. + +1. Create a directory to contain the build outputs for a particular architecture (we name it `c:\GSL\build-x86` in this example). + + cd GSL + md build-x86 + cd build-x86 + +2. Configure CMake to use the compiler of your choice (you can see a list by running `cmake --help`). + + cmake -G "Visual Studio 15 2017" c:\GSL + +3. Build the test suite (in this case, in the Debug configuration, Release is another good choice). + + cmake --build . --config Debug + +4. Run the test suite. + + ctest -C Debug + +All tests should pass - indicating your platform is fully supported and you are ready to use the GSL types! + +## Building GSL - Using vcpkg + +You can download and install GSL using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + vcpkg install ms-gsl + +The GSL port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + +## Using the libraries +As the types are entirely implemented inline in headers, there are no linking requirements. + +You can copy the [gsl](./include/gsl) directory into your source tree so it is available +to your compiler, then include the appropriate headers in your program. + +Alternatively set your compiler's *include path* flag to point to the GSL development folder (`c:\GSL\include` in the example above) or installation folder (after running the install). Eg. + +MSVC++ + + /I c:\GSL\include + +GCC/clang + + -I$HOME/dev/GSL/include + +Include the library using: + + #include + +## Usage in CMake + +The library provides a Config file for CMake, once installed it can be found via `find_package`. + +Which, when successful, will add library target called `Microsoft.GSL::GSL` which you can use via the usual +`target_link_libraries` mechanism. + +```cmake +find_package(Microsoft.GSL CONFIG REQUIRED) + +target_link_libraries(foobar PRIVATE Microsoft.GSL::GSL) +``` + +### FetchContent + +If you are using CMake version 3.11+ you can use the offical [FetchContent module](https://cmake.org/cmake/help/latest/module/FetchContent.html). +This allows you to easily incorporate GSL into your project. + +```cmake +# NOTE: This example uses CMake version 3.14 (FetchContent_MakeAvailable). +# Since it streamlines the FetchContent process +cmake_minimum_required(VERSION 3.14) + +include(FetchContent) + +FetchContent_Declare(GSL + GIT_REPOSITORY "https://github.com/microsoft/GSL" + GIT_TAG "v4.0.0" + GIT_SHALLOW ON +) + +FetchContent_MakeAvailable(GSL) + +target_link_libraries(foobar PRIVATE Microsoft.GSL::GSL) +``` + +## Debugging visualization support + +For Visual Studio users, the file [GSL.natvis](./GSL.natvis) in the root directory of the repository can be added to your project if you would like more helpful visualization of GSL types in the Visual Studio debugger than would be offered by default. diff --git a/deps/GSL/SECURITY.md b/deps/GSL/SECURITY.md new file mode 100644 index 0000000..869fdfe --- /dev/null +++ b/deps/GSL/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/deps/GSL/ThirdPartyNotices.txt b/deps/GSL/ThirdPartyNotices.txt new file mode 100644 index 0000000..552b254 --- /dev/null +++ b/deps/GSL/ThirdPartyNotices.txt @@ -0,0 +1,41 @@ + +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +GSL: Guidelines Support Library incorporates third party material from the projects listed below. + +------------------------------------------------------------------------------- +Software: Google Test +Owner: Google Inc. +Source URL: github.com/google/googletest +License: BSD 3 - Clause +Text: + Copyright 2008, Google Inc. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT + OWNER 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. +------------------------------------------------------------------------------- diff --git a/deps/GSL/azure-pipelines.yml b/deps/GSL/azure-pipelines.yml new file mode 100644 index 0000000..ba16ee9 --- /dev/null +++ b/deps/GSL/azure-pipelines.yml @@ -0,0 +1,66 @@ +trigger: + - main + +pr: + autoCancel: true + +stages: +- stage: GCC + dependsOn: [] + jobs: + - template: ./pipelines/jobs.yml + parameters: + compiler: gcc + image: ubuntu-20.04 + compilerVersions: [ 11, 10 ] + setupfile: 'setup_gcc.yml' + +- stage: Clang + dependsOn: [] + jobs: + - template: ./pipelines/jobs.yml + parameters: + compiler: clang + image: ubuntu-20.04 + compilerVersions: [ 12, 11 ] + setupfile: 'setup_clang.yml' + +- stage: Xcode + dependsOn: [] + jobs: + - template: ./pipelines/jobs.yml + parameters: + compiler: 'Xcode' + image: macOS-11 + compilerVersions: [ '12.5.1', '13.2.1' ] + setupfile: 'setup_apple.yml' + +- stage: VS_MSVC + dependsOn: [] + jobs: + - template: ./pipelines/jobs.yml + parameters: + compiler: 'VS2019 (MSVC)' + compilerVersions: [ 'default' ] + image: windows-2019 + - template: ./pipelines/jobs.yml + parameters: + compiler: 'VS2022 (MSVC)' + compilerVersions: [ 'default' ] + image: windows-2022 + +- stage: VS_LLVM + dependsOn: [] + jobs: + - template: ./pipelines/jobs.yml + parameters: + compiler: 'VS2019 (LLVM)' + compilerVersions: [ 'default' ] + image: windows-2019 + extraCmakeArgs: '-T ClangCL' + - template: ./pipelines/jobs.yml + parameters: + compiler: 'VS2022 (LLVM)' + compilerVersions: [ 'default' ] + image: windows-2022 + extraCmakeArgs: '-T ClangCL' diff --git a/deps/GSL/docs/headers.md b/deps/GSL/docs/headers.md new file mode 100644 index 0000000..e870eaf --- /dev/null +++ b/deps/GSL/docs/headers.md @@ -0,0 +1,854 @@ +The Guidelines Support Library (GSL) interface is very lightweight and exposed via a header-only library. This document attempts to document all of the headers and their exposed classes and functions. + +Types and functions are exported in the namespace `gsl`. + +See [GSL: Guidelines support library](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#S-gsl) + +# Headers + +- [``](#user-content-H-algorithms) +- [``](#user-content-H-assert) +- [``](#user-content-H-byte) +- [``](#user-content-H-gsl) +- [``](#user-content-H-narrow) +- [``](#user-content-H-pointers) +- [``](#user-content-H-span) +- [``](#user-content-H-span_ext) +- [``](#user-content-H-string_span) +- [``](#user-content-H-util) + +## `` + +This header contains some common algorithms that have been wrapped in GSL safety features. + +- [`gsl::copy`](#user-content-H-algorithms-copy) + +### `gsl::copy` + +```cpp +template +void copy(span src, span dest); +``` + +This function copies the content from the `src` [`span`](#user-content-H-span-span) to the `dest` [`span`](#user-content-H-span-span). It [`Expects`](#user-content-H-assert-expects) +that the destination `span` is at least as large as the source `span`. + +## `` + +This header contains some macros used for contract checking and suppressing code analysis warnings. + +See [GSL.assert: Assertions](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-assertions) + +- [`GSL_SUPPRESS`](#user-content-H-assert-gsl_suppress) +- [`Expects`](#user-content-H-assert-expects) +- [`Ensures`](#user-content-H-assert-ensures) + +### `GSL_SUPPRESS` + +This macro can be used to suppress a code analysis warning. + +The core guidelines request tools that check for the rules to respect suppressing a rule by writing +`[[gsl::suppress(tag)]]` or `[[gsl::suppress(tag, justification: "message")]]`. + +Clang does not use exactly that syntax, but requires `tag` to be put in double quotes `[[gsl::suppress("tag")]]`. + +For portable code you can use `GSL_SUPPRESS(tag)`. + +See [In.force: Enforcement](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#inforce-enforcement). + +### `Expects` + +This macro can be used for expressing a precondition. If the precondition is not held, then `std::terminate` will be called. + +See [I.6: Prefer `Expects()` for expressing preconditions](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i6-prefer-expects-for-expressing-preconditions) + +### `Ensures` + +This macro can be used for expressing a postcondition. If the postcondition is not held, then `std::terminate` will be called. + +See [I.8: Prefer `Ensures()` for expressing postconditions](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#i8-prefer-ensures-for-expressing-postconditions) + +## `` + +This header contains the definition of a byte type, implementing `std::byte` before it was standardized into C++17. + +- [`gsl::byte`](#user-content-H-byte-byte) + +### `gsl::byte` + +If `GSL_USE_STD_BYTE` is defined to be `1`, then `gsl::byte` will be an alias to `std::byte`. +If `GSL_USE_STD_BYTE` is defined to be `0`, then `gsl::byte` will be a distinct type that implements the concept of byte. +If `GSL_USE_STD_BYTE` is not defined, then the header file will check if `std::byte` is available (C\+\+17 or higher). If yes, +`gsl::byte` will be an alias to `std::byte`, otherwise `gsl::byte` will be a distinct type that implements the concept of byte. + +⚠ Take care when linking projects that were compiled with different language standards (before C\+\+17 and C\+\+17 or higher). +If you do so, you might want to `#define GSL_USE_STD_BYTE 0` to a fixed value to be sure that both projects use exactly +the same type. Otherwise you might get linker errors. + +See [SL.str.5: Use `std::byte` to refer to byte values that do not necessarily represent characters](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rstr-byte) + +### Non-member functions + +```cpp +template ::value>> +constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept; + +template ::value>> +constexpr byte operator<<(byte b, IntegerType shift) noexcept; + +template ::value>> +constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept; + +template ::value>> +constexpr byte operator>>(byte b, IntegerType shift) noexcept; +``` + +Left or right shift a `byte` by a given number of bits. + +```cpp +constexpr byte& operator|=(byte& l, byte r) noexcept; +constexpr byte operator|(byte l, byte r) noexcept; +``` + +Bitwise "or" of two `byte`s. + +```cpp +constexpr byte& operator&=(byte& l, byte r) noexcept; +constexpr byte operator&(byte l, byte r) noexcept; +``` + +Bitwise "and" of two `byte`s. + +```cpp +constexpr byte& operator^=(byte& l, byte r) noexcept; +constexpr byte operator^(byte l, byte r) noexcept; +``` + +Bitwise xor of two `byte`s. + +```cpp +constexpr byte operator~(byte b) noexcept; +``` + +Bitwise negation of a `byte`. Flips all bits. Zeroes become ones, ones become zeroes. + +```cpp +template +constexpr byte to_byte(T t) noexcept; +``` + +Convert the given value to a `byte`. The template requires `T` to be an `unsigned char` so that no data loss can occur. +If you want to convert an integer constant to a `byte` you probably want to call `to_byte()`. + +```cpp +template +constexpr byte to_byte() noexcept; +``` + +Convert the given value `I` to a `byte`. The template requires `I` to be in the valid range 0..255 for a `gsl::byte`. + +## `` + +This header is a convenience header that includes all other [GSL headers](#user-content-H). +Since `` requires exceptions, it will only be included if exceptions are enabled. + +## `` + +This header contains utility functions and classes, for narrowing casts, which require exceptions. The narrowing-related utilities that don't require exceptions are found inside [util](#user-content-H-util). + +See [GSL.util: Utilities](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-utilities) + +- [`gsl::narrowing_error`](#user-content-H-narrow-narrowing_error) +- [`gsl::narrow`](#user-content-H-narrow-narrow) + +### `gsl::narrowing_error` + +`gsl::narrowing_error` is the exception thrown by [`gsl::narrow`](#user-content-H-narrow-narrow) when a narrowing conversion fails. It is derived from `std::exception`. + +### `gsl::narrow` + +`gsl::narrow(x)` is a named cast that does a `static_cast(x)` for narrowing conversions with no signedness promotions. +If the argument `x` cannot be represented in the target type `T`, then the function throws a [`gsl::narrowing_error`](#user-content-H-narrow-narrowing_error) (e.g., `narrow(-42)` and `narrow(300)` throw). + +Note: compare [`gsl::narrow_cast`](#user-content-H-util-narrow_cast) in header [util](#user-content-H-util). + +See [ES.46: Avoid lossy (narrowing, truncating) arithmetic conversions](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-narrowing) and [ES.49: If you must use a cast, use a named cast](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-casts-named) + +## `` + +This header contains some pointer types. + +See [GSL.view](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-views) + +- [`gsl::unique_ptr`](#user-content-H-pointers-unique_ptr) +- [`gsl::shared_ptr`](#user-content-H-pointers-shared_ptr) +- [`gsl::owner`](#user-content-H-pointers-owner) +- [`gsl::not_null`](#user-content-H-pointers-not_null) +- [`gsl::strict_not_null`](#user-content-H-pointers-strict_not_null) + +### `gsl::unique_ptr` + +`gsl::unique_ptr` is an alias to `std::unique_ptr`. + +See [GSL.owner: Ownership pointers](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-ownership) + +### `gsl::shared_ptr` + +`gsl::shared_ptr` is an alias to `std::shared_ptr`. + +See [GSL.owner: Ownership pointers](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-ownership) + +### `gsl::owner` + +`gsl::owner` is designed as a safety mechanism for code that must deal directly with raw pointers that own memory. Ideally such code should be restricted to the implementation of low-level abstractions. `gsl::owner` can also be used as a stepping point in converting legacy code to use more modern RAII constructs such as smart pointers. +`T` must be a pointer type (`std::is_pointer`). + +A `gsl::owner` is a typedef to `T`. It adds no runtime overhead whatsoever, as it is purely syntactic and does not add any runtime checks. Instead, it serves as an annotation for static analysis tools which check for memory safety, and as a code comprehension guide for human readers. + +See Enforcement section of [C.31: All resources acquired by a class must be released by the class’s destructor](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-dtor-release). + +### `gsl::not_null` + +`gsl::not_null` restricts a pointer or smart pointer to only hold non-null values. It has no size overhead over `T`. + +The checks for ensuring that the pointer is not null are done in the constructor. There is no overhead when retrieving or dereferencing the checked pointer. +When a nullptr check fails, `std::terminate` is called. + +See [F.23: Use a `not_null` to indicate that “null†is not a valid value](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-nullptr) + +#### Member functions + +##### Construct/Copy + +```cpp +template ::value>> +constexpr not_null(U&& u); + +template ::value>> +constexpr not_null(T u); +``` + +Constructs a `gsl_owner` from a pointer that is convertible to `T` or that is a `T`. It [`Expects`](#user-content-H-assert-expects) that the provided pointer is not `== nullptr`. + +```cpp +template ::value>> +constexpr not_null(const not_null& other); +``` + +Constructs a `gsl_owner` from another `gsl_owner` where the other pointer is convertible to `T`. It [`Expects`](#user-content-H-assert-expects) that the provided pointer is not `== nullptr`. + +```cpp +not_null(const not_null& other) = default; +not_null& operator=(const not_null& other) = default; +``` + +Copy construction and assignment. + +```cpp +not_null(std::nullptr_t) = delete; +not_null& operator=(std::nullptr_t) = delete; +``` + +Construction from `std::nullptr_t` and assignment of `std::nullptr_t` are explicitly deleted. + +##### Modifiers + +```cpp +not_null& operator++() = delete; +not_null& operator--() = delete; +not_null operator++(int) = delete; +not_null operator--(int) = delete; +not_null& operator+=(std::ptrdiff_t) = delete; +not_null& operator-=(std::ptrdiff_t) = delete; +``` + +Explicitly deleted operators. Pointers point to single objects ([I.13: Do not pass an array as a single pointer](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-array)), so don't allow these operators. + +##### Observers + +```cpp +constexpr details::value_or_reference_return_t get() const; +constexpr operator T() const { return get(); } +``` + +Get the underlying pointer. + +```cpp +constexpr decltype(auto) operator->() const { return get(); } +constexpr decltype(auto) operator*() const { return *get(); } +``` + +Dereference the underlying pointer. + +```cpp +void operator[](std::ptrdiff_t) const = delete; +``` + +Array index operator is explicitly deleted. Pointers point to single objects ([I.13: Do not pass an array as a single pointer](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-array)), so don't allow treating them as an array. + +#### Non-member functions + +```cpp +template +auto make_not_null(T&& t) noexcept; +``` + +Creates a `gsl::not_null` object, deducing the target type from the type of the argument. + +```cpp +template +auto operator==(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get())) + -> decltype(lhs.get() == rhs.get()); +template +auto operator!=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get())) + -> decltype(lhs.get() != rhs.get()); +template +auto operator<(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() < rhs.get())) + -> decltype(lhs.get() < rhs.get()); +template +auto operator<=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() <= rhs.get())) + -> decltype(lhs.get() <= rhs.get()); +template +auto operator>(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() > rhs.get())) + -> decltype(lhs.get() > rhs.get()); +template +auto operator>=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() >= rhs.get())) + -> decltype(lhs.get() >= rhs.get()); +``` + +Comparison of pointers that are convertible to each other. + +##### Input/Output + +```cpp +template +std::ostream& operator<<(std::ostream& os, const not_null& val); +``` + +Performs stream output on a `not_null` pointer, invoking `os << val.get()`. This function is only available when `GSL_NO_IOSTREAMS` is not defined. + +##### Modifiers + +```cpp +template +std::ptrdiff_t operator-(const not_null&, const not_null&) = delete; +template +not_null operator-(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(std::ptrdiff_t, const not_null&) = delete; +``` + +Addition and subtraction are explicitly deleted. Pointers point to single objects ([I.13: Do not pass an array as a single pointer](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Ri-array)), so don't allow these operators. + +##### STL integration + +```cpp +template +struct std::hash> { ... }; +``` + +Specialization of `std::hash` for `gsl::not_null`. + +### `gsl::strict_not_null` + +`strict_not_null` is the same as [`not_null`](#user-content-H-pointers-not_null) except that the constructors are `explicit`. + +The free function that deduces the target type from the type of the argument and creates a `gsl::strict_not_null` object is `gsl::make_strict_not_null`. + +## `` + +This header file exports the class `gsl::span`, a bounds-checked implementation of `std::span`. + +- [`gsl::span`](#user-content-H-span-span) + +### `gsl::span` + +```cpp +template +class span; +``` + +`gsl::span` is a view over memory. It does not own the memory and is only a way to access contiguous sequences of objects. +The extent can be either a fixed size or [`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent). + +The `gsl::span` is based on the standardized version of `std::span` which was added to C++20. Originally, the plan was to +deprecate `gsl::span` when `std::span` finished standardization, however that plan changed when the runtime bounds checking +was removed from `std::span`'s design. + +The only difference between `gsl::span` and `std::span` is that `gsl::span` strictly enforces runtime bounds checking. +Any violations of the bounds check results in termination of the program. +Like `gsl::span`, `gsl::span`'s iterators also differ from `std::span`'s iterator in that all access operations are bounds checked. + +#### Which version of span should I use? + +##### Use `gsl::span` if + +- you want to guarantee bounds safety in your project. + - All data accessing operations use bounds checking to ensure you are only accessing valid memory. +- your project uses C++14 or C++17. + - `std::span` is not available as it was not introduced into the STL until C++20. + +##### Use `std::span` if + +- your project is C++20 and you need the performance offered by `std::span`. + +#### Types + +```cpp +using element_type = ElementType; +using value_type = std::remove_cv_t; +using size_type = std::size_t; +using pointer = element_type*; +using const_pointer = const element_type*; +using reference = element_type&; +using const_reference = const element_type&; +using difference_type = std::ptrdiff_t; + +using iterator = details::span_iterator; +using reverse_iterator = std::reverse_iterator; +``` + +#### Member functions + +```cpp +constexpr span() noexcept; +``` + +Constructs an empty `span`. This constructor is only available if `Extent` is 0 or [`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent). +`span::data()` will return `nullptr`. + +```cpp +constexpr explicit(Extent != gsl::dynamic_extent) span(pointer ptr, size_type count) noexcept; +``` + +Constructs a `span` from a pointer and a size. If `Extent` is not [`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent), +then the constructor [`Expects`](#user-content-H-assert-expects) that `count == Extent`. + +```cpp +constexpr explicit(Extent != gsl::dynamic_extent) span(pointer firstElem, pointer lastElem) noexcept; +``` + +Constructs a `span` from a pointer to the begin and the end of the data. If `Extent` is not [`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent), +then the constructor [`Expects`](#user-content-H-assert-expects) that `lastElem - firstElem == Extent`. + +```cpp +template +constexpr span(element_type (&arr)[N]) noexcept; +``` + +Constructs a `span` from a C style array. This overload is available if `Extent ==`[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) +or `N == Extent`. + +```cpp +template +constexpr span(std::array& arr) noexcept; + +template +constexpr span(const std::array& arr) noexcept; +``` + +Constructs a `span` from a `std::array`. These overloads are available if `Extent ==`[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) +or `N == Extent`, and if the array can be interpreted as a `ElementType` array. + +```cpp +template +constexpr explicit(Extent != gsl::dynamic_extent) span(Container& cont) noexcept; + +template +constexpr explicit(Extent != gsl::dynamic_extent) span(const Container& cont) noexcept; +``` + +Constructs a `span` from a container. These overloads are available if `Extent ==`[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) +or `N == Extent`, and if the container can be interpreted as a contiguous `ElementType` array. + +```cpp +constexpr span(const span& other) noexcept = default; +``` + +Copy constructor. + +```cpp +template +explicit(Extent != gsl::dynamic_extent && OtherExtent == dynamic_extent) +constexpr span(const span& other) noexcept; +``` + +Constructs a `span` from another `span`. This constructor is available if `OtherExtent == Extent || Extent ==`[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent)` || OtherExtent ==`[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) +and if `ElementType` and `OtherElementType` are compatible. + +If `Extent !=`[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) and `OtherExtent ==`[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent), +then the constructor [`Expects`](#user-content-H-assert-expects) that `other.size() == Extent`. + +```cpp +constexpr span& operator=(const span& other) noexcept = default; +``` + +Copy assignment + +```cpp +template +constexpr span first() const noexcept; + +constexpr span first(size_type count) const noexcept; + +template +constexpr span last() const noexcept; + +constexpr span last(size_type count) const noexcept; +``` + +Return a subspan of the first/last `Count` elements. [`Expects`](#user-content-H-assert-expects) that `Count` does not exceed the `span`'s size. + +```cpp +template +constexpr auto subspan() const noexcept; + +constexpr span +subspan(size_type offset, size_type count = dynamic_extent) const noexcept; +``` + +Return a subspan starting at `offset` and having size `count`. [`Expects`](#user-content-H-assert-expects) that `offset` does not exceed the `span`'s size, +and that `offset == `[`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) or `offset + count` does not exceed the `span`'s size. +If `count` is `gsl::dynamic_extent`, the number of elements in the subspan is `size() - offset`. + +```cpp +constexpr size_type size() const noexcept; + +constexpr size_type size_bytes() const noexcept; +``` + +Returns the size respective the size in bytes of the `span`. + +```cpp +constexpr bool empty() const noexcept; +``` + +Is the `span` empty? + +```cpp +constexpr reference operator[](size_type idx) const noexcept; +``` + +Returns a reference to the element at the given index. [`Expects`](#user-content-H-assert-expects) that `idx` is less than the `span`'s size. + +```cpp +constexpr reference front() const noexcept; +constexpr reference back() const noexcept; +``` + +Returns a reference to the first/last element in the `span`. [`Expects`](#user-content-H-assert-expects) that the `span` is not empty. + +```cpp +constexpr pointer data() const noexcept; +``` + +Returns a pointer to the beginning of the contained data. + +```cpp +constexpr iterator begin() const noexcept; +constexpr iterator end() const noexcept; +constexpr reverse_iterator rbegin() const noexcept; +constexpr reverse_iterator rend() const noexcept; +``` + +Returns an iterator to the first/last normal/reverse iterator. + +```cpp +template +span(Type (&)[Extent]) -> span; + +template +span(std::array&) -> span; + +template +span(const std::array&) -> span; + +template ().data())>> +span(Container&) -> span; + +template ().data())>> +span(const Container&) -> span; +``` + +Deduction guides. + +```cpp +template +span::value> +as_bytes(span s) noexcept; + +template +span::value> +as_writable_bytes(span s) noexcept; +``` + +Converts a `span` into a `span` of `byte`s. + +`as_writable_bytes` will only be available for non-const `ElementType`s. + +## `` + +This file is a companion for and included by [``](#user-content-H-span), and should not be used on its own. It contains useful features that aren't part of the `std::span` API as found inside the STL `` header (with the exception of [`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent), which is included here due to implementation constraints). + +- [`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) +- [`gsl::span`](#user-content-H-span_ext-span) +- [`gsl::span` comparison operators](#user-content-H-span_ext-span_comparison_operators) +- [`gsl::make_span`](#user-content-H-span_ext-make_span) +- [`gsl::at`](#user-content-H-span_ext-at) +- [`gsl::ssize`](#user-content-H-span_ext-ssize) +- [`gsl::span` iterator functions](#user-content-H-span_ext-span_iterator_functions) + +### `gsl::dynamic_extent` + +Defines the extent value to be used by all `gsl::span` with dynamic extent. + +Note: `std::dynamic_extent` is exposed by the STL `` header and so ideally `gsl::dynamic_extent` would be under [``](#user-content-H-span), but to avoid cyclic dependency issues it is under `` instead. + +### `gsl::span` + +```cpp +template +class span; +``` + +Forward declaration of `gsl::span`. + +### `gsl::span` comparison operators + +```cpp +template +constexpr bool operator==(span l, span r); +template +constexpr bool operator!=(span l, span r); +template +constexpr bool operator<(span l, span r); +template +constexpr bool operator<=(span l, span r); +template +constexpr bool operator>(span l, span r); +template +constexpr bool operator>=(span l, span r); +``` + +The comparison operators for two `span`s lexicographically compare the elements in the `span`s. + +### `gsl::make_span` + +```cpp +template +constexpr span make_span(ElementType* ptr, typename span::size_type count); +template +constexpr span make_span(ElementType* firstElem, ElementType* lastElem); +template +constexpr span make_span(ElementType (&arr)[N]) noexcept; +template +constexpr span make_span(Container& cont); +template +constexpr span make_span(const Container& cont); +template +constexpr span make_span(Ptr& cont, std::size_t count); +template +constexpr span make_span(Ptr& cont); +``` + +Utility function for creating a `span` with [`gsl::dynamic_extent`](#user-content-H-span_ext-dynamic_extent) from +- pointer and length, +- pointer to start and pointer to end, +- a C style array, or +- a container. + +### `gsl::at` + +```cpp +template +constexpr ElementType& at(span s, index i); +``` + +The function `gsl::at` offers a safe way to access data with index bounds checking. + +This is the specialization of [`gsl::at`](#user-content-H-util-at) for [`span`](#user-content-H-span-span). It returns a reference to the `i`th element and +[`Expects`](#user-content-H-assert-expects) that the provided index is within the bounds of the `span`. + +Note: `gsl::at` supports indexes up to `PTRDIFF_MAX`. + +### `gsl::ssize` + +```cpp +template +constexpr std::ptrdiff_t ssize(const span& s) noexcept; +``` + +Return the size of a [`span`](#user-content-H-span-span) as a `ptrdiff_t`. + +### `gsl::span` iterator functions + +```cpp +template +constexpr typename span::iterator +begin(const span& s) noexcept; + +template +constexpr typename span::iterator +end(const span& s) noexcept; + +template +constexpr typename span::reverse_iterator +rbegin(const span& s) noexcept; + +template +constexpr typename span::reverse_iterator +rend(const span& s) noexcept; + +template +constexpr typename span::iterator +cbegin(const span& s) noexcept; + +template +constexpr typename span::iterator +cend(const span& s) noexcept; + +template +constexpr typename span::reverse_iterator +crbegin(const span& s) noexcept; + +template +constexpr typename span::reverse_iterator +crend(const span& s) noexcept; +``` + +Free functions for getting a non-const/const begin/end normal/reverse iterator for a [`span`](#user-content-H-span-span). + +## `` + +This header exports a family of `*zstring` types. + +A `gsl::XXzstring` is a typedef to `T`. It adds no checks whatsoever, it is just for having a syntax to describe +that a pointer points to a zero terminated C style string. This helps static code analysis, and it helps human readers. + +`basic_zstring` is a pointer to a C-string (zero-terminated array) with a templated char type. Used to implement the rest of the `*zstring` family. +`zstring` is a zero terminated `char` string. +`czstring` is a const zero terminated `char` string. +`wzstring` is a zero terminated `wchar_t` string. +`cwzstring` is a const zero terminated `wchar_t` string. +`u16zstring` is a zero terminated `char16_t` string. +`cu16zstring` is a const zero terminated `char16_t` string. +`u32zstring` is a zero terminated `char32_t` string. +`cu32zstring` is a const zero terminated `char32_t` string. + +See [GSL.view](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-views) and [SL.str.3: Use zstring or czstring to refer to a C-style, zero-terminated, sequence of characters](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rstr-zstring). + +## `` + +This header contains utility functions and classes. This header works without exceptions being available. The parts that require +exceptions being available are in their own header file [narrow](#user-content-H-narrow). + +See [GSL.util: Utilities](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-utilities) + +- [`gsl::narrow_cast`](#user-content-H-util-narrow_cast) +- [`gsl::final_action`](#user-content-H-util-final_action) +- [`gsl::at`](#user-content-H-util-at) + +### `gsl::index` + +An alias to `std::ptrdiff_t`. It serves as the index type for all container indexes/subscripts/sizes. + +### `gsl::narrow_cast` + +`gsl::narrow_cast(x)` is a named cast that is identical to a `static_cast(x)`. It exists to make clear to static code analysis tools and to human readers that a lossy conversion is acceptable. + +Note: compare the throwing version [`gsl::narrow`](#user-content-H-narrow-narrow) in header [narrow](#user-content-H-narrow). + +See [ES.46: Avoid lossy (narrowing, truncating) arithmetic conversions](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-narrowing) and [ES.49: If you must use a cast, use a named cast](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-casts-named) + +### `gsl::final_action` + +```cpp +template +class final_action { ... }; +``` + +`final_action` allows you to ensure something gets run at the end of a scope. + +See [E.19: Use a final_action object to express cleanup if no suitable resource handle is available](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Re-finally) + +#### Member functions + +```cpp +explicit final_action(const F& ff) noexcept; +explicit final_action(F&& ff) noexcept; +``` + +Construct an object with the action to invoke in the destructor. + +```cpp +~final_action() noexcept; +``` + +The destructor will call the action that was passed in the constructor. + +```cpp +final_action(final_action&& other) noexcept; +final_action(const final_action&) = delete; +void operator=(const final_action&) = delete; +void operator=(final_action&&) = delete; +``` + +Move construction is allowed. Copy construction is deleted. Copy and move assignment are also explicitely deleted. + +#### Non-member functions + +```cpp +template +auto finally(F&& f) noexcept; +``` + +Creates a `gsl::final_action` object, deducing the template argument type from the type of the argument. + +### `gsl::at` + +The function `gsl::at` offers a safe way to access data with index bounds checking. + +Note: `gsl::at` supports indexes up to `PTRDIFF_MAX`. + +See [ES.42: Keep use of pointers simple and straightforward](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-ptr) + +```cpp +template +constexpr T& at(T (&arr)[N], const index i); +``` + +This overload returns a reference to the `i`s element of a C style array `arr`. It [`Expects`](#user-content-H-assert-expects) that the provided index is within the bounds of the array. + +```cpp +template +constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]); +``` + +This overload returns a reference to the `i`s element of the container `cont`. It [`Expects`](#user-content-H-assert-expects) that the provided index is within the bounds of the array. + +```cpp +template +constexpr T at(const std::initializer_list cont, const index i); +``` + +This overload returns a reference to the `i`s element of the initializer list `cont`. It [`Expects`](#user-content-H-assert-expects) that the provided index is within the bounds of the array. + +```cpp +template +constexpr auto at(std::span sp, const index i) -> decltype(sp[sp.size()]); +``` + +This overload returns a reference to the `i`s element of the `std::span` `sp`. It [`Expects`](#user-content-H-assert-expects) that the provided index is within the bounds of the array. + +For [`gsl::at`](#user-content-H-span_ext-at) for [`gsl::span`](#user-content-H-span-span) see header [`span_ext`](#user-content-H-span_ext). diff --git a/deps/GSL/include/CMakeLists.txt b/deps/GSL/include/CMakeLists.txt new file mode 100644 index 0000000..fe4eed9 --- /dev/null +++ b/deps/GSL/include/CMakeLists.txt @@ -0,0 +1,13 @@ +# Add include folders to the library and targets that consume it +# the SYSTEM keyword suppresses warnings for users of the library +# +# By adding this directory as an include directory the user gets a +# namespace effect. +# +# IE: +# #include +if(PROJECT_IS_TOP_LEVEL) + target_include_directories(GSL INTERFACE $) +else() + target_include_directories(GSL SYSTEM INTERFACE $) +endif() diff --git a/deps/GSL/include/gsl/algorithm b/deps/GSL/include/gsl/algorithm new file mode 100644 index 0000000..584f5cd --- /dev/null +++ b/deps/GSL/include/gsl/algorithm @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_ALGORITHM_H +#define GSL_ALGORITHM_H + +#include "assert" // for Expects +#include "span" // for dynamic_extent, span + +#include // for copy_n +#include // for ptrdiff_t +#include // for is_assignable + +#ifdef _MSC_VER +#pragma warning(push) + +// turn off some warnings that are noisy about our Expects statements +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4996) // unsafe use of std::copy_n + +#endif // _MSC_VER + +namespace gsl +{ +// Note: this will generate faster code than std::copy using span iterator in older msvc+stl +// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915) +template +void copy(span src, span dest) +{ + static_assert(std::is_assignable::value, + "Elements of source span can not be assigned to elements of destination span"); + static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent || + (SrcExtent <= DestExtent), + "Source range is longer than target range"); + + Expects(dest.size() >= src.size()); + // clang-format off + GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute + // clang-format on + std::copy_n(src.data(), src.size(), dest.data()); +} + +} // namespace gsl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // GSL_ALGORITHM_H diff --git a/deps/GSL/include/gsl/assert b/deps/GSL/include/gsl/assert new file mode 100644 index 0000000..78a9e8c --- /dev/null +++ b/deps/GSL/include/gsl/assert @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_ASSERT_H +#define GSL_ASSERT_H + +// +// Temporary until MSVC STL supports no-exceptions mode. +// Currently terminate is a no-op in this mode, so we add termination behavior back +// +#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)) +#define GSL_KERNEL_MODE + +#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND +#include +#define RANGE_CHECKS_FAILURE 0 + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winvalid-noreturn" +#endif // defined(__clang__) + +#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && + // !_HAS_EXCEPTIONS)) + +#include + +#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && + // !_HAS_EXCEPTIONS)) + +// +// make suppress attributes parse for some compilers +// Hopefully temporary until suppression standardization occurs +// +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__NVCC__) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#define GSL_SUPPRESS(x) +#endif // _MSC_VER +#endif // __clang__ + +#define GSL_STRINGIFY_DETAIL(x) #x +#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x) + +#if defined(__clang__) || defined(__GNUC__) +#define GSL_LIKELY(x) __builtin_expect(!!(x), 1) +#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0) + +#else + +#define GSL_LIKELY(x) (!!(x)) +#define GSL_UNLIKELY(x) (!!(x)) +#endif // defined(__clang__) || defined(__GNUC__) + +// +// GSL_ASSUME(cond) +// +// Tell the optimizer that the predicate cond must hold. It is unspecified +// whether or not cond is actually evaluated. +// +#ifdef _MSC_VER +#define GSL_ASSUME(cond) __assume(cond) +#elif defined(__GNUC__) +#define GSL_ASSUME(cond) ((cond) ? static_cast(0) : __builtin_unreachable()) +#else +#define GSL_ASSUME(cond) static_cast((cond) ? 0 : 0) +#endif + +// +// GSL.assert: assertions +// + +namespace gsl +{ + +namespace details +{ +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + typedef void(__cdecl* terminate_handler)(); + + // clang-format off + GSL_SUPPRESS(f.6) // NO-FORMAT: attribute + // clang-format on + [[noreturn]] inline void __cdecl default_terminate_handler() + { + __fastfail(RANGE_CHECKS_FAILURE); + } + + inline gsl::details::terminate_handler& get_terminate_handler() noexcept + { + static terminate_handler handler = &default_terminate_handler; + return handler; + } + +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + [[noreturn]] inline void terminate() noexcept + { +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + (*gsl::details::get_terminate_handler())(); +#else + std::terminate(); +#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + } + +} // namespace details +} // namespace gsl + +#define GSL_CONTRACT_CHECK(type, cond) \ + (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate()) + +#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond) +#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond) + +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__) +#pragma clang diagnostic pop +#endif + +#endif // GSL_ASSERT_H diff --git a/deps/GSL/include/gsl/byte b/deps/GSL/include/gsl/byte new file mode 100644 index 0000000..a721dc6 --- /dev/null +++ b/deps/GSL/include/gsl/byte @@ -0,0 +1,202 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_BYTE_H +#define GSL_BYTE_H + +// +// make suppress attributes work for some compilers +// Hopefully temporary until suppression standardization occurs +// +#if defined(__clang__) +#define GSL_SUPPRESS(x) [[gsl::suppress("x")]] +#else +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__NVCC__) +#define GSL_SUPPRESS(x) [[gsl::suppress(x)]] +#else +#define GSL_SUPPRESS(x) +#endif // _MSC_VER +#endif // __clang__ + +#include + +// VS2017 15.8 added support for the __cpp_lib_byte definition +// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires +#ifdef _MSC_VER + +#pragma warning(push) + +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates + // does not always work + +#ifndef GSL_USE_STD_BYTE +// this tests if we are under MSVC and the standard lib has std::byte and it is enabled +#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \ + (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603) + +#define GSL_USE_STD_BYTE 1 + +#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= + // 201603) + +#define GSL_USE_STD_BYTE 0 + +#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >= + // 201603) +#endif // GSL_USE_STD_BYTE + +#else // _MSC_VER + +#ifndef GSL_USE_STD_BYTE +#include /* __cpp_lib_byte */ +// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte +// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte +#if defined(__cplusplus) && (__cplusplus >= 201703L) && \ + (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \ + defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) + +#define GSL_USE_STD_BYTE 1 + +#else // defined(__cplusplus) && (__cplusplus >= 201703L) && + // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || + // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) + +#define GSL_USE_STD_BYTE 0 + +#endif // defined(__cplusplus) && (__cplusplus >= 201703L) && + // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || + // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000)) +#endif // GSL_USE_STD_BYTE + +#endif // _MSC_VER + +// Use __may_alias__ attribute on gcc and clang +#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5) +#define byte_may_alias __attribute__((__may_alias__)) +#else // defined __clang__ || defined __GNUC__ +#define byte_may_alias +#endif // defined __clang__ || defined __GNUC__ + +#if GSL_USE_STD_BYTE +#include +#endif + +namespace gsl +{ +#if GSL_USE_STD_BYTE + +using std::byte; +using std::to_integer; + +#else // GSL_USE_STD_BYTE + +// This is a simple definition for now that allows +// use of byte within span<> to be standards-compliant +enum class byte_may_alias byte : unsigned char +{ +}; + +template ::value>> +constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast(b) << shift); +} + +template ::value>> +constexpr byte operator<<(byte b, IntegerType shift) noexcept +{ + return byte(static_cast(b) << shift); +} + +template ::value>> +constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept +{ + return b = byte(static_cast(b) >> shift); +} + +template ::value>> +constexpr byte operator>>(byte b, IntegerType shift) noexcept +{ + return byte(static_cast(b) >> shift); +} + +constexpr byte& operator|=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) | static_cast(r)); +} + +constexpr byte operator|(byte l, byte r) noexcept +{ + return byte(static_cast(l) | static_cast(r)); +} + +constexpr byte& operator&=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) & static_cast(r)); +} + +constexpr byte operator&(byte l, byte r) noexcept +{ + return byte(static_cast(l) & static_cast(r)); +} + +constexpr byte& operator^=(byte& l, byte r) noexcept +{ + return l = byte(static_cast(l) ^ static_cast(r)); +} + +constexpr byte operator^(byte l, byte r) noexcept +{ + return byte(static_cast(l) ^ static_cast(r)); +} + +constexpr byte operator~(byte b) noexcept { return byte(~static_cast(b)); } + +template ::value>> +constexpr IntegerType to_integer(byte b) noexcept +{ + return static_cast(b); +} + +#endif // GSL_USE_STD_BYTE + +template +// NOTE: need suppression since c++14 does not allow "return {t}" +// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work +constexpr byte to_byte(T t) noexcept +{ + static_assert(std::is_same::value, + "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. " + "If you are calling to_byte with an integer contant use: gsl::to_byte() version."); + return byte(t); +} + +template +constexpr byte to_byte() noexcept +{ + static_assert(I >= 0 && I <= 255, + "gsl::byte only has 8 bits of storage, values must be in range 0-255"); + return static_cast(I); +} + +} // namespace gsl + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // GSL_BYTE_H diff --git a/deps/GSL/include/gsl/gsl b/deps/GSL/include/gsl/gsl new file mode 100644 index 0000000..3d9e288 --- /dev/null +++ b/deps/GSL/include/gsl/gsl @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_GSL_H +#define GSL_GSL_H + +#include "algorithm" // copy +#include "assert" // Ensures/Expects +#include "byte" // byte +#include "pointers" // owner, not_null +#include "span" // span +#include "string_span" // zstring, string_span, zstring_builder... +#include "util" // finally()/narrow_cast()... + +#ifdef __cpp_exceptions +#include "narrow" // narrow() +#endif + +#endif // GSL_GSL_H diff --git a/deps/GSL/include/gsl/gsl_algorithm b/deps/GSL/include/gsl/gsl_algorithm new file mode 100644 index 0000000..d516e2e --- /dev/null +++ b/deps/GSL/include/gsl/gsl_algorithm @@ -0,0 +1,4 @@ +#pragma once +#pragma message( \ + "This header will soon be removed. Use instead of ") +#include "algorithm" diff --git a/deps/GSL/include/gsl/gsl_assert b/deps/GSL/include/gsl/gsl_assert new file mode 100644 index 0000000..35a6e78 --- /dev/null +++ b/deps/GSL/include/gsl/gsl_assert @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include "assert" diff --git a/deps/GSL/include/gsl/gsl_byte b/deps/GSL/include/gsl/gsl_byte new file mode 100644 index 0000000..399025c --- /dev/null +++ b/deps/GSL/include/gsl/gsl_byte @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include "byte" diff --git a/deps/GSL/include/gsl/gsl_narrow b/deps/GSL/include/gsl/gsl_narrow new file mode 100644 index 0000000..59685fc --- /dev/null +++ b/deps/GSL/include/gsl/gsl_narrow @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include "narrow" diff --git a/deps/GSL/include/gsl/gsl_util b/deps/GSL/include/gsl/gsl_util new file mode 100644 index 0000000..bd17d3e --- /dev/null +++ b/deps/GSL/include/gsl/gsl_util @@ -0,0 +1,3 @@ +#pragma once +#pragma message("This header will soon be removed. Use instead of ") +#include "util" diff --git a/deps/GSL/include/gsl/narrow b/deps/GSL/include/gsl/narrow new file mode 100644 index 0000000..14db3d9 --- /dev/null +++ b/deps/GSL/include/gsl/narrow @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_NARROW_H +#define GSL_NARROW_H +#include "assert" // for GSL_SUPPRESS +#include "util" // for narrow_cast +#include // for std::exception +namespace gsl +{ +struct narrowing_error : public std::exception +{ + const char* what() const noexcept override { return "narrowing_error"; } +}; + +// narrow() : a checked version of narrow_cast() that throws if the cast changed the value +template ::value>::type* = nullptr> +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) +GSL_SUPPRESS(es.46) // NO-FORMAT: attribute // The warning suggests that a floating->unsigned conversion can occur + // in the static_cast below, and that gsl::narrow should be used instead. + // Suppress this warning, since gsl::narrow is defined in terms of + // static_cast + // clang-format on + constexpr T narrow(U u) noexcept(false) +{ + constexpr const bool is_different_signedness = + (std::is_signed::value != std::is_signed::value); + +GSL_SUPPRESS(es.103) // NO-FORMAT: attribute // don't overflow +GSL_SUPPRESS(es.104) // NO-FORMAT: attribute // don't underflow +GSL_SUPPRESS(p.2) // NO-FORMAT: attribute // don't rely on undefined behavior + const T t = narrow_cast(u); // While this is technically undefined behavior in some cases (i.e., if the source value is of floating-point type + // and cannot fit into the destination integral type), the resultant behavior is benign on the platforms + // that we target (i.e., no hardware trap representations are hit). + +#if defined(__clang__) || defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + // Note: NaN will always throw, since NaN != NaN + if (static_cast(t) != u || (is_different_signedness && ((t < T{}) != (u < U{})))) + { + throw narrowing_error{}; + } +#if defined(__clang__) || defined(__GNUC__) + #pragma GCC diagnostic pop +#endif + + return t; +} + +template ::value>::type* = nullptr> +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute +GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false) + // clang-format on + constexpr T narrow(U u) noexcept(false) +{ + const T t = narrow_cast(u); + + if (static_cast(t) != u) + { + throw narrowing_error{}; + } + + return t; +} +} // namespace gsl +#endif // GSL_NARROW_H diff --git a/deps/GSL/include/gsl/pointers b/deps/GSL/include/gsl/pointers new file mode 100644 index 0000000..0759c53 --- /dev/null +++ b/deps/GSL/include/gsl/pointers @@ -0,0 +1,346 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_POINTERS_H +#define GSL_POINTERS_H + +#include "assert" // for Ensures, Expects + +#include // for forward +#include // for ptrdiff_t, nullptr_t, size_t +#include // for shared_ptr, unique_ptr +#include // for hash +#include // for enable_if_t, is_convertible, is_assignable + +#if !defined(GSL_NO_IOSTREAMS) +#include // for ostream +#endif // !defined(GSL_NO_IOSTREAMS) + +namespace gsl +{ + +namespace details +{ + template + struct is_comparable_to_nullptr : std::false_type + { + }; + + template + struct is_comparable_to_nullptr< + T, + std::enable_if_t() != nullptr), bool>::value>> + : std::true_type + { + }; + + // Resolves to the more efficient of `const T` or `const T&`, in the context of returning a const-qualified value + // of type T. + // + // Copied from cppfront's implementation of the CppCoreGuidelines F.16 (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-in) + template + using value_or_reference_return_t = std::conditional_t< + sizeof(T) < 2*sizeof(void*) && std::is_trivially_copy_constructible::value, + const T, + const T&>; + +} // namespace details + +// +// GSL.owner: ownership pointers +// +using std::shared_ptr; +using std::unique_ptr; + +// +// owner +// +// `gsl::owner` is designed as a safety mechanism for code that must deal directly with raw pointers that own memory. +// Ideally such code should be restricted to the implementation of low-level abstractions. `gsl::owner` can also be used +// as a stepping point in converting legacy code to use more modern RAII constructs, such as smart pointers. +// +// T must be a pointer type +// - disallow construction from any type other than pointer type +// +template ::value>> +using owner = T; + +// +// not_null +// +// Restricts a pointer or smart pointer to only hold non-null values. +// +// Has zero size overhead over T. +// +// If T is a pointer (i.e. T == U*) then +// - allow construction from U* +// - disallow construction from nullptr_t +// - disallow default construction +// - ensure construction from null U* fails +// - allow implicit conversion to U* +// +template +class not_null +{ +public: + static_assert(details::is_comparable_to_nullptr::value, "T cannot be compared to nullptr."); + + template ::value>> + constexpr not_null(U&& u) : ptr_(std::forward(u)) + { + Expects(ptr_ != nullptr); + } + + template ::value>> + constexpr not_null(T u) : ptr_(std::move(u)) + { + Expects(ptr_ != nullptr); + } + + template ::value>> + constexpr not_null(const not_null& other) : not_null(other.get()) + {} + + not_null(const not_null& other) = default; + not_null& operator=(const not_null& other) = default; + constexpr details::value_or_reference_return_t get() const + { + return ptr_; + } + + constexpr operator T() const { return get(); } + constexpr decltype(auto) operator->() const { return get(); } + constexpr decltype(auto) operator*() const { return *get(); } + + // prevents compilation when someone attempts to assign a null pointer constant + not_null(std::nullptr_t) = delete; + not_null& operator=(std::nullptr_t) = delete; + + // unwanted operators...pointers only point to single objects! + not_null& operator++() = delete; + not_null& operator--() = delete; + not_null operator++(int) = delete; + not_null operator--(int) = delete; + not_null& operator+=(std::ptrdiff_t) = delete; + not_null& operator-=(std::ptrdiff_t) = delete; + void operator[](std::ptrdiff_t) const = delete; + +private: + T ptr_; +}; + +template +auto make_not_null(T&& t) noexcept +{ + return not_null>>{std::forward(t)}; +} + +#if !defined(GSL_NO_IOSTREAMS) +template +std::ostream& operator<<(std::ostream& os, const not_null& val) +{ + os << val.get(); + return os; +} +#endif // !defined(GSL_NO_IOSTREAMS) + +template +auto operator==(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get())) + -> decltype(lhs.get() == rhs.get()) +{ + return lhs.get() == rhs.get(); +} + +template +auto operator!=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get())) + -> decltype(lhs.get() != rhs.get()) +{ + return lhs.get() != rhs.get(); +} + +template +auto operator<(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(std::less<>{}(lhs.get(), rhs.get()))) + -> decltype(std::less<>{}(lhs.get(), rhs.get())) +{ + return std::less<>{}(lhs.get(), rhs.get()); +} + +template +auto operator<=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(std::less_equal<>{}(lhs.get(), rhs.get()))) + -> decltype(std::less_equal<>{}(lhs.get(), rhs.get())) +{ + return std::less_equal<>{}(lhs.get(), rhs.get()); +} + +template +auto operator>(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(std::greater<>{}(lhs.get(), rhs.get()))) + -> decltype(std::greater<>{}(lhs.get(), rhs.get())) +{ + return std::greater<>{}(lhs.get(), rhs.get()); +} + +template +auto operator>=(const not_null& lhs, + const not_null& rhs) noexcept(noexcept(std::greater_equal<>{}(lhs.get(), rhs.get()))) + -> decltype(std::greater_equal<>{}(lhs.get(), rhs.get())) +{ + return std::greater_equal<>{}(lhs.get(), rhs.get()); +} + +// more unwanted operators +template +std::ptrdiff_t operator-(const not_null&, const not_null&) = delete; +template +not_null operator-(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(const not_null&, std::ptrdiff_t) = delete; +template +not_null operator+(std::ptrdiff_t, const not_null&) = delete; + + +template ().get()), bool = std::is_default_constructible>::value> +struct not_null_hash +{ + std::size_t operator()(const T& value) const { return std::hash{}(value.get()); } +}; + +template +struct not_null_hash +{ + not_null_hash() = delete; + not_null_hash(const not_null_hash&) = delete; + not_null_hash& operator=(const not_null_hash&) = delete; +}; + +} // namespace gsl + +namespace std +{ +template +struct hash> : gsl::not_null_hash> +{ +}; + +} // namespace std + +namespace gsl +{ + +// +// strict_not_null +// +// Restricts a pointer or smart pointer to only hold non-null values, +// +// - provides a strict (i.e. explicit constructor from T) wrapper of not_null +// - to be used for new code that wishes the design to be cleaner and make not_null +// checks intentional, or in old code that would like to make the transition. +// +// To make the transition from not_null, incrementally replace not_null +// by strict_not_null and fix compilation errors +// +// Expect to +// - remove all unneeded conversions from raw pointer to not_null and back +// - make API clear by specifying not_null in parameters where needed +// - remove unnecessary asserts +// +template +class strict_not_null : public not_null +{ +public: + template ::value>> + constexpr explicit strict_not_null(U&& u) : not_null(std::forward(u)) + {} + + template ::value>> + constexpr explicit strict_not_null(T u) : not_null(u) + {} + + template ::value>> + constexpr strict_not_null(const not_null& other) : not_null(other) + {} + + template ::value>> + constexpr strict_not_null(const strict_not_null& other) : not_null(other) + {} + + // To avoid invalidating the "not null" invariant, the contained pointer is actually copied + // instead of moved. If it is a custom pointer, its constructor could in theory throw exceptions. + strict_not_null(strict_not_null&& other) noexcept(std::is_nothrow_copy_constructible::value) = default; + strict_not_null(const strict_not_null& other) = default; + strict_not_null& operator=(const strict_not_null& other) = default; + strict_not_null& operator=(const not_null& other) + { + not_null::operator=(other); + return *this; + } + + // prevents compilation when someone attempts to assign a null pointer constant + strict_not_null(std::nullptr_t) = delete; + strict_not_null& operator=(std::nullptr_t) = delete; + + // unwanted operators...pointers only point to single objects! + strict_not_null& operator++() = delete; + strict_not_null& operator--() = delete; + strict_not_null operator++(int) = delete; + strict_not_null operator--(int) = delete; + strict_not_null& operator+=(std::ptrdiff_t) = delete; + strict_not_null& operator-=(std::ptrdiff_t) = delete; + void operator[](std::ptrdiff_t) const = delete; +}; + +// more unwanted operators +template +std::ptrdiff_t operator-(const strict_not_null&, const strict_not_null&) = delete; +template +strict_not_null operator-(const strict_not_null&, std::ptrdiff_t) = delete; +template +strict_not_null operator+(const strict_not_null&, std::ptrdiff_t) = delete; +template +strict_not_null operator+(std::ptrdiff_t, const strict_not_null&) = delete; + +template +auto make_strict_not_null(T&& t) noexcept +{ + return strict_not_null>>{std::forward(t)}; +} + +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) + +// deduction guides to prevent the ctad-maybe-unsupported warning +template +not_null(T) -> not_null; +template +strict_not_null(T) -> strict_not_null; + +#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) + +} // namespace gsl + +namespace std +{ +template +struct hash> : gsl::not_null_hash> +{ +}; + +} // namespace std + +#endif // GSL_POINTERS_H diff --git a/deps/GSL/include/gsl/span b/deps/GSL/include/gsl/span new file mode 100644 index 0000000..f61fd11 --- /dev/null +++ b/deps/GSL/include/gsl/span @@ -0,0 +1,842 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_SPAN_H +#define GSL_SPAN_H + +#include "assert" // for Expects +#include "byte" // for byte +#include "span_ext" // for span specialization of gsl::at and other span-related extensions +#include "util" // for narrow_cast + +#include // for array +#include // for ptrdiff_t, size_t, nullptr_t +#include // for reverse_iterator, distance, random_access_... +#include // for pointer_traits +#include // for enable_if_t, declval, is_convertible, inte... + +#if defined(__has_include) && __has_include() +#include +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) + +// turn off some warnings that are noisy about our Expects statements +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning( \ + disable : 4146) // unary minus operator applied to unsigned type, result still unsigned +#pragma warning(disable : 4702) // unreachable code + +// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool. +#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor +#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates + +#endif // _MSC_VER + +// See if we have enough C++17 power to use a static constexpr data member +// without needing an out-of-line definition +#if !(defined(__cplusplus) && (__cplusplus >= 201703L)) +#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND +#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L)) + +// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t) +// While there is a conversion from signed to unsigned, it happens at +// compiletime, so the compiler wouldn't have to warn indiscriminately, but +// could check if the source value actually doesn't fit into the target type +// and only warn in those cases. +#if defined(__GNUC__) && __GNUC__ > 6 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + +namespace gsl +{ + +// implementation details +namespace details +{ + template + struct is_span_oracle : std::false_type + { + }; + + template + struct is_span_oracle> : std::true_type + { + }; + + template + struct is_span : public is_span_oracle> + { + }; + + template + struct is_std_array_oracle : std::false_type + { + }; + + template + struct is_std_array_oracle> : std::true_type + { + }; + + template + struct is_std_array : is_std_array_oracle> + { + }; + + template + struct is_allowed_extent_conversion + : std::integral_constant + { + }; + + template + struct is_allowed_element_type_conversion + : std::integral_constant::value> + { + }; + + template + class span_iterator + { + public: +#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts)) + using iterator_concept = std::contiguous_iterator_tag; +#endif // __cpp_lib_ranges + using iterator_category = std::random_access_iterator_tag; + using value_type = std::remove_cv_t; + using difference_type = std::ptrdiff_t; + using pointer = Type*; + using reference = Type&; + +#ifdef _MSC_VER + using _Unchecked_type = pointer; + using _Prevent_inheriting_unwrap = span_iterator; +#endif // _MSC_VER + constexpr span_iterator() = default; + + constexpr span_iterator(pointer begin, pointer end, pointer current) + : begin_(begin), end_(end), current_(current) + {} + + constexpr operator span_iterator() const noexcept + { + return {begin_, end_, current_}; + } + + constexpr reference operator*() const noexcept + { + Expects(begin_ && end_); + Expects(begin_ <= current_ && current_ < end_); + return *current_; + } + + constexpr pointer operator->() const noexcept + { + Expects(begin_ && end_); + Expects(begin_ <= current_ && current_ < end_); + return current_; + } + constexpr span_iterator& operator++() noexcept + { + Expects(begin_ && current_ && end_); + Expects(current_ < end_); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + ++current_; + return *this; + } + + constexpr span_iterator operator++(int) noexcept + { + span_iterator ret = *this; + ++*this; + return ret; + } + + constexpr span_iterator& operator--() noexcept + { + Expects(begin_ && end_); + Expects(begin_ < current_); + --current_; + return *this; + } + + constexpr span_iterator operator--(int) noexcept + { + span_iterator ret = *this; + --*this; + return ret; + } + + constexpr span_iterator& operator+=(const difference_type n) noexcept + { + if (n != 0) Expects(begin_ && current_ && end_); + if (n > 0) Expects(end_ - current_ >= n); + if (n < 0) Expects(current_ - begin_ >= -n); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + current_ += n; + return *this; + } + + constexpr span_iterator operator+(const difference_type n) const noexcept + { + span_iterator ret = *this; + ret += n; + return ret; + } + + friend constexpr span_iterator operator+(const difference_type n, + const span_iterator& rhs) noexcept + { + return rhs + n; + } + + constexpr span_iterator& operator-=(const difference_type n) noexcept + { + if (n != 0) Expects(begin_ && current_ && end_); + if (n > 0) Expects(current_ - begin_ >= n); + if (n < 0) Expects(end_ - current_ >= -n); + GSL_SUPPRESS(bounds .1) + current_ -= n; + return *this; + } + + constexpr span_iterator operator-(const difference_type n) const noexcept + { + span_iterator ret = *this; + ret -= n; + return ret; + } + + template < + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr difference_type operator-(const span_iterator& rhs) const noexcept + { + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ - rhs.current_; + } + + constexpr reference operator[](const difference_type n) const noexcept + { + return *(*this + n); + } + + template < + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator==(const span_iterator& rhs) const noexcept + { + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ == rhs.current_; + } + + template < + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator!=(const span_iterator& rhs) const noexcept + { + return !(*this == rhs); + } + + template < + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator<(const span_iterator& rhs) const noexcept + { + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ < rhs.current_; + } + + template < + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator>(const span_iterator& rhs) const noexcept + { + return rhs < *this; + } + + template < + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator<=(const span_iterator& rhs) const noexcept + { + return !(rhs < *this); + } + + template < + class Type2, + std::enable_if_t, value_type>::value, int> = 0> + constexpr bool operator>=(const span_iterator& rhs) const noexcept + { + return !(*this < rhs); + } + +#ifdef _MSC_VER + // MSVC++ iterator debugging support; allows STL algorithms in 15.8+ + // to unwrap span_iterator to a pointer type after a range check in STL + // algorithm calls + friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept + { // test that [lhs, rhs) forms a valid range inside an STL algorithm + Expects(lhs.begin_ == rhs.begin_ // range spans have to match + && lhs.end_ == rhs.end_ && + lhs.current_ <= rhs.current_); // range must not be transposed + } + + constexpr void _Verify_offset(const difference_type n) const noexcept + { // test that *this + n is within the range of this call + if (n != 0) Expects(begin_ && current_ && end_); + if (n > 0) Expects(end_ - current_ >= n); + if (n < 0) Expects(current_ - begin_ >= -n); + } + + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr pointer _Unwrapped() const noexcept + { // after seeking *this to a high water mark, or using one of the + // _Verify_xxx functions above, unwrap this span_iterator to a raw + // pointer + return current_; + } + + // Tell the STL that span_iterator should not be unwrapped if it can't + // validate in advance, even in release / optimized builds: +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const bool _Unwrap_when_unverified = false; +#else + static constexpr bool _Unwrap_when_unverified = false; +#endif + // clang-format off + GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive + // clang-format on + constexpr void _Seek_to(const pointer p) noexcept + { // adjust the position of *this to previously verified location p + // after _Unwrapped + current_ = p; + } +#endif + + pointer begin_ = nullptr; + pointer end_ = nullptr; + pointer current_ = nullptr; + + template + friend struct std::pointer_traits; + }; +}} // namespace gsl::details + +namespace std +{ +template +struct pointer_traits<::gsl::details::span_iterator> +{ + using pointer = ::gsl::details::span_iterator; + using element_type = Type; + using difference_type = ptrdiff_t; + + static constexpr element_type* to_address(const pointer i) noexcept { return i.current_; } +}; +} // namespace std + +namespace gsl { namespace details { + template + class extent_type + { + public: + using size_type = std::size_t; + + constexpr extent_type() noexcept = default; + + constexpr explicit extent_type(extent_type); + + constexpr explicit extent_type(size_type size) { Expects(size == Ext); } + + constexpr size_type size() const noexcept { return Ext; } + + private: +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const size_type size_ = Ext; // static size equal to Ext +#else + static constexpr size_type size_ = Ext; // static size equal to Ext +#endif + }; + + template <> + class extent_type + { + public: + using size_type = std::size_t; + + template + constexpr explicit extent_type(extent_type ext) : size_(ext.size()) + {} + + constexpr explicit extent_type(size_type size) : size_(size) + { + Expects(size != dynamic_extent); + } + + constexpr size_type size() const noexcept { return size_; } + + private: + size_type size_; + }; + + template + constexpr extent_type::extent_type(extent_type ext) + { + Expects(ext.size() == Ext); + } + + template + struct calculate_subspan_type + { + using type = span; + }; +} // namespace details + +// [span], class template span +template +class span +{ +public: + // constants and types + using element_type = ElementType; + using value_type = std::remove_cv_t; + using size_type = std::size_t; + using pointer = element_type*; + using const_pointer = const element_type*; + using reference = element_type&; + using const_reference = const element_type&; + using difference_type = std::ptrdiff_t; + + using iterator = details::span_iterator; + using reverse_iterator = std::reverse_iterator; + +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) + static constexpr const size_type extent{Extent}; +#else + static constexpr size_type extent{Extent}; +#endif + + // [span.cons], span constructors, copy, assignment, and destructor + template " SFINAE, since "std::enable_if_t" is ill-formed when Extent is greater than 0. + class = std::enable_if_t<(Dependent || + details::is_allowed_extent_conversion<0, Extent>::value)>> + constexpr span() noexcept : storage_(nullptr, details::extent_type<0>()) + {} + + template = 0> + constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count) + { + Expects(count == Extent); + } + + template = 0> + constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count) + {} + + template = 0> + constexpr explicit span(pointer firstElem, pointer lastElem) noexcept + : storage_(firstElem, narrow_cast(lastElem - firstElem)) + { + Expects(lastElem - firstElem == static_cast(Extent)); + } + + template = 0> + constexpr span(pointer firstElem, pointer lastElem) noexcept + : storage_(firstElem, narrow_cast(lastElem - firstElem)) + {} + + template ::value, int> = 0> + constexpr span(element_type (&arr)[N]) noexcept + : storage_(KnownNotNull{arr}, details::extent_type()) + {} + + template < + class T, std::size_t N, + std::enable_if_t<(details::is_allowed_extent_conversion::value && + details::is_allowed_element_type_conversion::value), + int> = 0> + constexpr span(std::array& arr) noexcept + : storage_(KnownNotNull{arr.data()}, details::extent_type()) + {} + + template ::value && + details::is_allowed_element_type_conversion::value), + int> = 0> + constexpr span(const std::array& arr) noexcept + : storage_(KnownNotNull{arr.data()}, details::extent_type()) + {} + + // NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the + // requirement on Container to be a contiguous sequence container. + template ::value && + !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + template ::value && + !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + template < + std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent != dynamic_extent && std::is_const::value && + !details::is_span::value && !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + template < + std::size_t MyExtent = Extent, class Container, + std::enable_if_t< + MyExtent == dynamic_extent && std::is_const::value && + !details::is_span::value && !details::is_std_array::value && + std::is_pointer().data())>::value && + std::is_convertible< + std::remove_pointer_t().data())> (*)[], + element_type (*)[]>::value, + int> = 0> + constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) + {} + + constexpr span(const span& other) noexcept = default; + + template ::value, + int> = 0> + constexpr span(const span& other) noexcept + : storage_(other.data(), details::extent_type(other.size())) + {} + + template ::value, + int> = 0> + constexpr explicit span(const span& other) noexcept + : storage_(other.data(), details::extent_type(other.size())) + {} + + ~span() noexcept = default; + constexpr span& operator=(const span& other) noexcept = default; + + // [span.sub], span subviews + template + constexpr span first() const noexcept + { + Expects(Count <= size()); + return span{data(), Count}; + } + + template + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr span last() const noexcept + { + Expects(Count <= size()); + return span{data() + (size() - Count), Count}; + } + + template + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr auto subspan() const noexcept -> + typename details::calculate_subspan_type::type + { + Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); + using type = + typename details::calculate_subspan_type::type; + return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count}; + } + + constexpr span first(size_type count) const noexcept + { + Expects(count <= size()); + return {data(), count}; + } + + constexpr span last(size_type count) const noexcept + { + Expects(count <= size()); + return make_subspan(size() - count, dynamic_extent, subspan_selector{}); + } + + constexpr span + subspan(size_type offset, size_type count = dynamic_extent) const noexcept + { + return make_subspan(offset, count, subspan_selector{}); + } + + // [span.obs], span observers + constexpr size_type size() const noexcept { return storage_.size(); } + + constexpr size_type size_bytes() const noexcept { return size() * sizeof(element_type); } + + constexpr bool empty() const noexcept { return size() == 0; } + + // [span.elem], span element access + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr reference operator[](size_type idx) const noexcept + { + Expects(idx < size()); + return data()[idx]; + } + + constexpr reference front() const noexcept + { + Expects(size() > 0); + return data()[0]; + } + + constexpr reference back() const noexcept + { + Expects(size() > 0); + return data()[size() - 1]; + } + + constexpr pointer data() const noexcept { return storage_.data(); } + + // [span.iter], span iterator support + constexpr iterator begin() const noexcept + { + const auto data = storage_.data(); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + return {data, data + size(), data}; + } + + constexpr iterator end() const noexcept + { + const auto data = storage_.data(); + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + const auto endData = data + storage_.size(); + return {data, endData, endData}; + } + + constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } + constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } + +#ifdef _MSC_VER + // Tell MSVC how to unwrap spans in range-based-for + constexpr pointer _Unchecked_begin() const noexcept { return data(); } + constexpr pointer _Unchecked_end() const noexcept + { + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + return data() + size(); + } +#endif // _MSC_VER + +private: + // Needed to remove unnecessary null check in subspans + struct KnownNotNull + { + pointer p; + }; + + // this implementation detail class lets us take advantage of the + // empty base class optimization to pay for only storage of a single + // pointer in the case of fixed-size spans + template + class storage_type : public ExtentType + { + public: + // KnownNotNull parameter is needed to remove unnecessary null check + // in subspans and constructors from arrays + template + constexpr storage_type(KnownNotNull data, OtherExtentType ext) + : ExtentType(ext), data_(data.p) + {} + + template + constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data) + { + Expects(data || ExtentType::size() == 0); + } + + constexpr pointer data() const noexcept { return data_; } + + private: + pointer data_; + }; + + storage_type> storage_; + + // The rest is needed to remove unnecessary null check + // in subspans and constructors from arrays + constexpr span(KnownNotNull ptr, size_type count) noexcept : storage_(ptr, count) {} + + template + class subspan_selector + { + }; + + template + constexpr span + make_subspan(size_type offset, size_type count, subspan_selector) const noexcept + { + const span tmp(*this); + return tmp.subspan(offset, count); + } + + // clang-format off + GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr span + make_subspan(size_type offset, size_type count, subspan_selector) const noexcept + { + Expects(size() >= offset); + + if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; } + + Expects(size() - offset >= count); + return {KnownNotNull{data() + offset}, count}; + } +}; + +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) + +// Deduction Guides +template +span(Type (&)[Extent]) -> span; + +template +span(std::array&) -> span; + +template +span(const std::array&) -> span; + +template ().data())>> +span(Container&) -> span; + +template ().data())>> +span(const Container&) -> span; + +#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) ) + +#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) +template +constexpr const typename span::size_type span::extent; +#endif + +namespace details +{ + // if we only supported compilers with good constexpr support then + // this pair of classes could collapse down to a constexpr function + + // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as + // constexpr + // and so will fail compilation of the template + template + struct calculate_byte_size : std::integral_constant + { + static_assert(Extent < dynamic_extent / sizeof(ElementType), "Size is too big."); + }; + + template + struct calculate_byte_size + : std::integral_constant + { + }; +} // namespace details + +// [span.objectrep], views of object representation +template +span::value> +as_bytes(span s) noexcept +{ + using type = span::value>; + + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return type{reinterpret_cast(s.data()), s.size_bytes()}; +} + +template ::value, int> = 0> +span::value> +as_writable_bytes(span s) noexcept +{ + using type = span::value>; + + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return type{reinterpret_cast(s.data()), s.size_bytes()}; +} + +} // namespace gsl + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(pop) +#endif // _MSC_VER + +#if defined(__GNUC__) && __GNUC__ > 6 +#pragma GCC diagnostic pop +#endif // __GNUC__ > 6 + +#endif // GSL_SPAN_H diff --git a/deps/GSL/include/gsl/span_ext b/deps/GSL/include/gsl/span_ext new file mode 100644 index 0000000..6873efc --- /dev/null +++ b/deps/GSL/include/gsl/span_ext @@ -0,0 +1,214 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_SPAN_EXT_H +#define GSL_SPAN_EXT_H + +/////////////////////////////////////////////////////////////////////////////// +// +// File: span_ext +// Purpose: continue offering features that have been cut from the official +// implementation of span. +// While modernizing gsl::span a number of features needed to be removed to +// be compliant with the design of std::span +// +/////////////////////////////////////////////////////////////////////////////// + +#include "assert" // GSL_KERNEL_MODE +#include "util" // for narrow_cast, narrow + +#include // for ptrdiff_t, size_t +#include + +#ifndef GSL_KERNEL_MODE +#include // for lexicographical_compare +#endif // GSL_KERNEL_MODE + +namespace gsl +{ + +// [span.views.constants], constants +GSL_INLINE constexpr const std::size_t dynamic_extent = narrow_cast(-1); + +template +class span; + +// std::equal and std::lexicographical_compare are not /kernel compatible +// so all comparison operators must be removed for kernel mode. +#ifndef GSL_KERNEL_MODE + +// [span.comparison], span comparison operators +template +constexpr bool operator==(span l, span r) +{ + return std::equal(l.begin(), l.end(), r.begin(), r.end()); +} + +template +constexpr bool operator!=(span l, span r) +{ + return !(l == r); +} + +template +constexpr bool operator<(span l, span r) +{ + return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); +} + +template +constexpr bool operator<=(span l, span r) +{ + return !(l > r); +} + +template +constexpr bool operator>(span l, span r) +{ + return r < l; +} + +template +constexpr bool operator>=(span l, span r) +{ + return !(l < r); +} + +#endif // GSL_KERNEL_MODE + +// +// make_span() - Utility functions for creating spans +// +template +constexpr span make_span(ElementType* ptr, typename span::size_type count) +{ + return span(ptr, count); +} + +template +constexpr span make_span(ElementType* firstElem, ElementType* lastElem) +{ + return span(firstElem, lastElem); +} + +template +constexpr span make_span(ElementType (&arr)[N]) noexcept +{ + return span(arr); +} + +template +constexpr span make_span(Container& cont) +{ + return span(cont); +} + +template +constexpr span make_span(const Container& cont) +{ + return span(cont); +} + +template +[[deprecated("This function is deprecated. See GSL issue #1092.")]] +constexpr span make_span(Ptr& cont, std::size_t count) +{ + return span(cont, count); +} + +template +[[deprecated("This function is deprecated. See GSL issue #1092.")]] +constexpr span make_span(Ptr& cont) +{ + return span(cont); +} + +// Specialization of gsl::at for span +template +constexpr ElementType& at(span s, index i) +{ + // No bounds checking here because it is done in span::operator[] called below + Ensures(i >= 0); + return s[narrow_cast(i)]; +} + +// [span.obs] Free observer functions +template +constexpr std::ptrdiff_t ssize(const span& s) noexcept +{ + return static_cast(s.size()); +} + +// [span.iter] Free functions for begin/end functions +template +constexpr typename span::iterator +begin(const span& s) noexcept +{ + return s.begin(); +} + +template +constexpr typename span::iterator +end(const span& s) noexcept +{ + return s.end(); +} + +template +constexpr typename span::reverse_iterator +rbegin(const span& s) noexcept +{ + return s.rbegin(); +} + +template +constexpr typename span::reverse_iterator +rend(const span& s) noexcept +{ + return s.rend(); +} + +template +constexpr typename span::iterator +cbegin(const span& s) noexcept +{ + return s.begin(); +} + +template +constexpr typename span::iterator +cend(const span& s) noexcept +{ + return s.end(); +} + +template +constexpr typename span::reverse_iterator +crbegin(const span& s) noexcept +{ + return s.rbegin(); +} + +template +constexpr typename span::reverse_iterator +crend(const span& s) noexcept +{ + return s.rend(); +} + +} // namespace gsl + +#endif // GSL_SPAN_EXT_H diff --git a/deps/GSL/include/gsl/string_span b/deps/GSL/include/gsl/string_span new file mode 100644 index 0000000..f27a0e4 --- /dev/null +++ b/deps/GSL/include/gsl/string_span @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_STRING_SPAN_H +#define GSL_STRING_SPAN_H + +#include "span_ext" // for dynamic_extent + +#include // for size_t, nullptr_t + +namespace gsl +{ +// +// czstring and wzstring +// +// These are "tag" typedefs for C-style strings (i.e. null-terminated character arrays) +// that allow static analysis to help find bugs. +// +// There are no additional features/semantics that we can find a way to add inside the +// type system for these types that will not either incur significant runtime costs or +// (sometimes needlessly) break existing programs when introduced. +// + +template +using basic_zstring = CharT*; + +using czstring = basic_zstring; + +using cwzstring = basic_zstring; + +using cu16zstring = basic_zstring; + +using cu32zstring = basic_zstring; + +using zstring = basic_zstring; + +using wzstring = basic_zstring; + +using u16zstring = basic_zstring; + +using u32zstring = basic_zstring; + +} // namespace gsl + +#endif // GSL_STRING_SPAN_H diff --git a/deps/GSL/include/gsl/util b/deps/GSL/include/gsl/util new file mode 100644 index 0000000..71f942d --- /dev/null +++ b/deps/GSL/include/gsl/util @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef GSL_UTIL_H +#define GSL_UTIL_H + +#include "assert" // for Expects + +#include +#include // for ptrdiff_t, size_t +#include // for numeric_limits +#include // for initializer_list +#include // for is_signed, integral_constant +#include // for exchange, forward + +#if defined(__has_include) && __has_include() +#include +#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L +#include +#endif // __cpp_lib_span >= 202002L +#endif //__has_include() + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(push) +#pragma warning(disable : 4127) // conditional expression is constant + +#endif // _MSC_VER + +#if defined(__cplusplus) && (__cplusplus >= 201703L) +#define GSL_NODISCARD [[nodiscard]] +#else +#define GSL_NODISCARD +#endif // defined(__cplusplus) && (__cplusplus >= 201703L) + +#if defined(__cpp_inline_variables) +#define GSL_INLINE inline +#else +#define GSL_INLINE +#endif + +namespace gsl +{ +// +// GSL.util: utilities +// + +// index type for all container indexes/subscripts/sizes +using index = std::ptrdiff_t; + +// final_action allows you to ensure something gets run at the end of a scope +template +class final_action +{ +public: + explicit final_action(const F& ff) noexcept : f{ff} { } + explicit final_action(F&& ff) noexcept : f{std::move(ff)} { } + + ~final_action() noexcept { if (invoke) f(); } + + final_action(final_action&& other) noexcept + : f(std::move(other.f)), invoke(std::exchange(other.invoke, false)) + { } + + final_action(const final_action&) = delete; + void operator=(const final_action&) = delete; + void operator=(final_action&&) = delete; + +private: + F f; + bool invoke = true; +}; + +// finally() - convenience function to generate a final_action +template +GSL_NODISCARD auto finally(F&& f) noexcept +{ + return final_action>{std::forward(f)}; +} + +// narrow_cast(): a searchable way to do narrowing casts of values +template +// clang-format off +GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + constexpr T narrow_cast(U&& u) noexcept +{ + return static_cast(std::forward(u)); +} + +// +// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector +// +template +// clang-format off +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute + // clang-format on + constexpr T& at(T (&arr)[N], const index i) +{ + static_assert(N <= static_cast((std::numeric_limits::max)()), "We only support arrays up to PTRDIFF_MAX bytes."); + Expects(i >= 0 && i < narrow_cast(N)); + return arr[narrow_cast(i)]; +} + +template +// clang-format off +GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute +GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute + // clang-format on + constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()]) +{ + Expects(i >= 0 && i < narrow_cast(cont.size())); + using size_type = decltype(cont.size()); + return cont[narrow_cast(i)]; +} + +template +// clang-format off +GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute + // clang-format on + constexpr T at(const std::initializer_list cont, const index i) +{ + Expects(i >= 0 && i < narrow_cast(cont.size())); + return *(cont.begin() + i); +} + +#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L +template +constexpr auto at(std::span sp, const index i) -> decltype(sp[sp.size()]) +{ + Expects(i >= 0 && i < narrow_cast(sp.size())); + return sp[gsl::narrow_cast(i)]; +} +#endif // __cpp_lib_span >= 202002L +} // namespace gsl + +#if defined(_MSC_VER) && !defined(__clang__) + +#pragma warning(pop) + +#endif // _MSC_VER + +#endif // GSL_UTIL_H diff --git a/deps/GSL/pipelines/jobs.yml b/deps/GSL/pipelines/jobs.yml new file mode 100644 index 0000000..0d6b9eb --- /dev/null +++ b/deps/GSL/pipelines/jobs.yml @@ -0,0 +1,43 @@ +parameters: + CXXVersions: [ 14, 17, 20 ] + buildTypes: [ 'Debug', 'Release' ] + image: '' + + compiler: '' + compilerVersions: ["default"] # if default value, simply uses whatever version is on the machine. + # the text of this default value doesn't actually matter. + setupfile: '' + extraCmakeArgs: '' + +jobs: +- ${{ each compilerVersion in parameters.compilerVersions }}: + - ${{ each CXXVersion in parameters.CXXVersions }}: + - ${{ each buildType in parameters.buildTypes }}: + - job: + displayName: ${{ format('{0} {1} C++{2} {3}', parameters.compiler, compilerVersion, CXXVersion, buildType) }} + pool: + vmImage: ${{ parameters.image }} + continueOnError: false + + steps: + - ${{ if not(eq(parameters.setupfile, '')) }}: + - template: ${{ parameters.setupfile }} + parameters: + version: ${{ compilerVersion }} + + - task: CMake@1 + name: Configure + inputs: + workingDirectory: build + cmakeArgs: '-DGSL_CXX_STANDARD=${{ CXXVersion }} -DCMAKE_BUILD_TYPE=${{ buildType }} -DCI_TESTING:BOOL=ON -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -Werror=dev ${{ parameters.extraCmakeArgs }} .. ' + + - task: CMake@1 + name: Build + inputs: + workingDirectory: build + cmakeArgs: '--build . ' + + - script: ctest . --output-on-failure --no-compress-output + name: CTest + workingDirectory: build + failOnStderr: true diff --git a/deps/GSL/pipelines/setup_apple.yml b/deps/GSL/pipelines/setup_apple.yml new file mode 100644 index 0000000..6a256a5 --- /dev/null +++ b/deps/GSL/pipelines/setup_apple.yml @@ -0,0 +1,9 @@ +parameters: + version: 0 + +steps: + - script: | + if [ "${{ parameters.version }}" != "default" ]; then sudo xcode-select -switch /Applications/Xcode_${{ parameters.version }}.app; fi + + displayName: "Setup Xcode Version" + failOnStderr: true diff --git a/deps/GSL/pipelines/setup_clang.yml b/deps/GSL/pipelines/setup_clang.yml new file mode 100644 index 0000000..58403b4 --- /dev/null +++ b/deps/GSL/pipelines/setup_clang.yml @@ -0,0 +1,13 @@ +parameters: + version: 0 + +steps: + - script: | + echo "##vso[task.setvariable variable=CXX;]${CXX}" + echo "##vso[task.setvariable variable=CC;]${CC}" + + displayName: "Setup Clang Version" + failOnStderr: true + env: + CC: clang-${{ parameters.version }} + CXX: clang++-${{ parameters.version }} diff --git a/deps/GSL/pipelines/setup_gcc.yml b/deps/GSL/pipelines/setup_gcc.yml new file mode 100644 index 0000000..6480f67 --- /dev/null +++ b/deps/GSL/pipelines/setup_gcc.yml @@ -0,0 +1,14 @@ +parameters: + version: 0 + +steps: + - script: | + echo "##vso[task.setvariable variable=CXX;]${CXX}" + echo "##vso[task.setvariable variable=CC;]${CC}" + if [ "${{ parameters.version }}" = "11" ]; then sudo apt-get install $CXX; fi + + displayName: "Setup GCC Version" + failOnStderr: true + env: + CC: gcc-${{ parameters.version }} + CXX: g++-${{ parameters.version }} diff --git a/deps/GSL/pipelines/steps.yml b/deps/GSL/pipelines/steps.yml new file mode 100644 index 0000000..e69de29 diff --git a/deps/GSL/tests/CMakeLists.txt b/deps/GSL/tests/CMakeLists.txt new file mode 100644 index 0000000..7a00fec --- /dev/null +++ b/deps/GSL/tests/CMakeLists.txt @@ -0,0 +1,306 @@ +cmake_minimum_required(VERSION 3.14...3.16) + +project(GSLTests LANGUAGES CXX) + +set(GSL_CXX_STANDARD "14" CACHE STRING "Use c++ standard") + +set(CMAKE_CXX_STANDARD ${GSL_CXX_STANDARD}) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(FindPkgConfig) +include(ExternalProject) + +# will make visual studio generated project group files +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +if(CI_TESTING AND GSL_CXX_STANDARD EQUAL 20) + add_compile_definitions(FORCE_STD_SPAN_TESTS=1) +endif() + +if(IOS) + add_compile_definitions(GTEST_HAS_DEATH_TEST=1 IOS_PROCESS_DELAY_WORKAROUND=1) +endif() + +pkg_search_module(GTestMain gtest_main) +if (NOT GTestMain_FOUND) + # No pre-installed GTest is available, try to download it using Git. + find_package(Git REQUIRED QUIET) + + configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download + ) + if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") + endif() + + execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download + ) + if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") + endif() + + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + set(GTestMain_LIBRARIES gtest_main) + + add_subdirectory( + ${CMAKE_CURRENT_BINARY_DIR}/googletest-src + ${CMAKE_CURRENT_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL + ) +endif() + +if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + find_package(Microsoft.GSL CONFIG REQUIRED) + enable_testing() + + if (NOT DEFINED Microsoft.GSL_VERSION) + message(FATAL_ERROR "Microsoft.GSL_VERSION not defined!") + endif() + + message(STATUS "Microsoft.GSL_VERSION = ${Microsoft.GSL_VERSION}") +endif() + +if (MSVC AND (GSL_CXX_STANDARD GREATER_EQUAL 17)) + set(GSL_CPLUSPLUS_OPT -Zc:__cplusplus -permissive-) +endif() + +include(CheckCXXCompilerFlag) +# this interface adds compile options to how the tests are run +# please try to keep entries ordered =) +add_library(gsl_tests_config INTERFACE) +if(MSVC) # MSVC or simulating MSVC + target_compile_options(gsl_tests_config INTERFACE + ${GSL_CPLUSPLUS_OPT} + /EHsc + /W4 + /WX + $<$: + /wd4996 # Use of function or classes marked [[deprecated]] + /wd26409 # CppCoreCheck - GTest + /wd26426 # CppCoreCheck - GTest + /wd26440 # CppCoreCheck - GTest + /wd26446 # CppCoreCheck - prefer gsl::at() + /wd26472 # CppCoreCheck - use gsl::narrow(_cast) + /wd26481 # CppCoreCheck - use span instead of pointer arithmetic + $<$,1920>: # VS2015 + /wd4189 # variable is initialized but not referenced + $<$>: # Release, RelWithDebInfo + /wd4702 # Unreachable code + > + > + > + $<$: + -Weverything + -Wfloat-equal + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-covered-switch-default # GTest + -Wno-deprecated-declarations # Allow tests for [[deprecated]] elements + -Wno-global-constructors # GTest + -Wno-language-extension-token # GTest gtest-port.h + -Wno-missing-braces + -Wno-missing-prototypes + -Wno-shift-sign-overflow # GTest gtest-port.h + -Wno-undef # GTest + -Wno-used-but-marked-unused # GTest EXPECT_DEATH + $<$: # no support for [[maybe_unused]] + -Wno-unused-member-function + -Wno-unused-variable + $<$,15.0.1>: + -Wno-deprecated # False positive in MSVC Clang 15.0.1 raises a C++17 warning + > + > + > + ) + check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID) + if (WARN_RESERVED_ID) + target_compile_options(gsl_tests_config INTERFACE "-Wno-reserved-identifier") + endif() +else() + target_compile_options(gsl_tests_config INTERFACE + -fno-strict-aliasing + -Wall + -Wcast-align + -Wconversion + -Wctor-dtor-privacy + -Werror + -Wextra + -Wpedantic + -Wshadow + -Wsign-conversion + -Wfloat-equal + -Wno-deprecated-declarations # Allow tests for [[deprecated]] elements + $<$,$>: + -Weverything + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-missing-braces + -Wno-covered-switch-default # GTest + -Wno-global-constructors # GTest + -Wno-missing-prototypes + -Wno-padded + -Wno-unknown-attributes + -Wno-used-but-marked-unused # GTest EXPECT_DEATH + -Wno-weak-vtables + $<$: # no support for [[maybe_unused]] + -Wno-unused-member-function + -Wno-unused-variable + > + > + $<$: + $<$,4.99>,$,6>>: + $<$:-Wno-undefined-func-template> + > + $<$,$,$>>: + -Wno-zero-as-null-pointer-constant # failing Clang Ubuntu 20.04 tests, seems to be a bug with clang 10.0.0 + # and clang 11.0.0. (operator< is being re-written by the compiler + # as operator<=> and raising the warning) + > + > + $<$: + $<$,9.1>,$,10>>: + $<$:-Wno-undefined-func-template> + > + > + $<$: + -Wdouble-promotion # float implicit to double + -Wlogical-op # suspicious uses of logical operators + $<$,6>>: + -Wduplicated-cond # duplicated if-else conditions + -Wmisleading-indentation + -Wnull-dereference + $<$: # no support for [[maybe_unused]] + -Wno-unused-variable + > + > + $<$,7>>: + -Wduplicated-branches # identical if-else branches + > + > + ) +endif(MSVC) + +# for tests to find the gtest header +target_include_directories(gsl_tests_config SYSTEM INTERFACE + googletest/googletest/include +) + +add_executable(gsl_tests + algorithm_tests.cpp + assertion_tests.cpp + at_tests.cpp + byte_tests.cpp + notnull_tests.cpp + owner_tests.cpp + span_compatibility_tests.cpp + span_ext_tests.cpp + span_tests.cpp + strict_notnull_tests.cpp + + utils_tests.cpp +) + +target_link_libraries(gsl_tests + Microsoft.GSL::GSL + gsl_tests_config + ${GTestMain_LIBRARIES} +) +add_test(gsl_tests gsl_tests) + +# No exception tests + +foreach(flag_var + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + STRING (REGEX REPLACE "/EHsc" "" ${flag_var} "${${flag_var}}") +endforeach(flag_var) + +# this interface adds compile options to how the tests are run +# please try to keep entries ordered =) +add_library(gsl_tests_config_noexcept INTERFACE) +if(MSVC) # MSVC or simulating MSVC + target_compile_definitions(gsl_tests_config_noexcept INTERFACE + _HAS_EXCEPTIONS=0 # disable exceptions in the Microsoft STL + ) + target_compile_options(gsl_tests_config_noexcept INTERFACE + ${GSL_CPLUSPLUS_OPT} + /W4 + /WX + $<$: + /wd4577 + /wd4702 + /wd26440 # CppCoreCheck - GTest + /wd26446 # CppCoreCheck - prefer gsl::at() + > + $<$: + -Weverything + -Wfloat-equal + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-missing-prototypes + -Wno-unknown-attributes + $<$: + $<$,15.0.1>: + -Wno-deprecated # False positive in MSVC Clang 15.0.1 raises a C++17 warning + > + > + > + ) + check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID) + if (WARN_RESERVED_ID) + target_compile_options(gsl_tests_config_noexcept INTERFACE "-Wno-reserved-identifier") + endif() +else() + target_compile_options(gsl_tests_config_noexcept INTERFACE + -fno-exceptions + -fno-strict-aliasing + -Wall + -Wcast-align + -Wconversion + -Wctor-dtor-privacy + -Werror + -Wextra + -Wpedantic + -Wshadow + -Wsign-conversion + -Wfloat-equal + $<$,$>: + -Weverything + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-missing-prototypes + -Wno-unknown-attributes + -Wno-weak-vtables + > + $<$: + -Wdouble-promotion # float implicit to double + -Wlogical-op # suspicious uses of logical operators + -Wuseless-cast # casting to its own type + $<$,6>>: + -Wduplicated-cond # duplicated if-else conditions + -Wmisleading-indentation + -Wnull-dereference + > + $<$,7>>: + -Wduplicated-branches # identical if-else branches + > + $<$,8>>: + -Wcast-align=strict # increase alignment (i.e. char* to int*) + > + > + ) +endif(MSVC) + +add_executable(gsl_noexcept_tests no_exception_ensure_tests.cpp) +target_link_libraries(gsl_noexcept_tests + Microsoft.GSL::GSL + gsl_tests_config_noexcept +) +add_test(gsl_noexcept_tests gsl_noexcept_tests) diff --git a/deps/GSL/tests/CMakeLists.txt.in b/deps/GSL/tests/CMakeLists.txt.in new file mode 100644 index 0000000..2535f8f --- /dev/null +++ b/deps/GSL/tests/CMakeLists.txt.in @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.0.2) +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG 1b18723e874b256c1e39378c6774a90701d70f7a + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/deps/GSL/tests/algorithm_tests.cpp b/deps/GSL/tests/algorithm_tests.cpp new file mode 100644 index 0000000..e369be0 --- /dev/null +++ b/deps/GSL/tests/algorithm_tests.cpp @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include // for array +#include // for size_t +#include // for copy +#include // for span +#include + +#include "deathTestCommon.h" + +namespace gsl +{ +struct fail_fast; +} // namespace gsl + +using namespace gsl; + +TEST(algorithm_tests, same_type) +{ + // dynamic source and destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const span src_span(src); + const span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } + + // static source and dynamic destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const span src_span(src); + const span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } + + // dynamic source and static destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const gsl::span src_span(src); + const gsl::span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } + + // static source and destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const span src_span(src); + const span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } +} + +TEST(algorithm_tests, compatible_type) +{ + // dynamic source and destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const span src_span(src); + const span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } + + // static source and dynamic destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const span src_span(src); + const span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } + + // dynamic source and static destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const span src_span(src); + const span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } + + // static source and destination span + { + std::array src{1, 2, 3, 4, 5}; + std::array dst{}; + + const span src_span(src); + const span dst_span(dst); + + copy(src_span, dst_span); + copy(src_span, dst_span.subspan(src_span.size())); + + for (std::size_t i = 0; i < src.size(); ++i) + { + EXPECT_TRUE(dst[i] == src[i]); + EXPECT_TRUE(dst[i + src.size()] == src[i]); + } + } +} + +#ifdef CONFIRM_COMPILATION_ERRORS +TEST(algorithm_tests, incompatible_type) +{ + std::array src{1, 2, 3, 4}; + std::array dst{}; + + span src_span_dyn(src); + span src_span_static(src); + span dst_span_dyn(dst); + span dst_span_static(dst); + + // every line should produce a compilation error + copy(src_span_dyn, dst_span_dyn); + copy(src_span_dyn, dst_span_static); + copy(src_span_static, dst_span_dyn); + copy(src_span_static, dst_span_static); +} +#endif + +TEST(algorithm_tests, small_destination_span) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. small_destination_span"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + std::array src{1, 2, 3, 4}; + std::array dst{}; + + const span src_span_dyn(src); + const span src_span_static(src); + const span dst_span_dyn(dst); + const span dst_span_static(dst); + + EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), expected); + EXPECT_DEATH(copy(src_span_dyn, dst_span_static), expected); + EXPECT_DEATH(copy(src_span_static, dst_span_dyn), expected); + +#ifdef CONFIRM_COMPILATION_ERRORS + copy(src_span_static, dst_span_static); +#endif +} diff --git a/deps/GSL/tests/assertion_tests.cpp b/deps/GSL/tests/assertion_tests.cpp new file mode 100644 index 0000000..231befc --- /dev/null +++ b/deps/GSL/tests/assertion_tests.cpp @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "deathTestCommon.h" +#include // for Ensures, Expects +#include + +using namespace gsl; + +namespace +{ + +int f(int i) +{ + Expects(i > 0 && i < 10); + return i; +} + +int g(int i) +{ + i++; + Ensures(i > 0 && i < 10); + return i; +} +} // namespace + +TEST(assertion_tests, expects) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. expects"; + std::abort(); + }); + + EXPECT_TRUE(f(2) == 2); + EXPECT_DEATH(f(10), GetExpectedDeathString(terminateHandler)); +} + +TEST(assertion_tests, ensures) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. ensures"; + std::abort(); + }); + + EXPECT_TRUE(g(2) == 3); + EXPECT_DEATH(g(9), GetExpectedDeathString(terminateHandler)); +} diff --git a/deps/GSL/tests/at_tests.cpp b/deps/GSL/tests/at_tests.cpp new file mode 100644 index 0000000..42b2241 --- /dev/null +++ b/deps/GSL/tests/at_tests.cpp @@ -0,0 +1,173 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for at + +#include // for array +#include // for size_t +#include // for terminate +#include // for initializer_list +#include // for vector +#if defined(__cplusplus) && __cplusplus >= 202002L +#include +#endif // __cplusplus >= 202002L + +#include "deathTestCommon.h" + +TEST(at_tests, static_array) +{ + int a[4] = {1, 2, 3, 4}; + const int(&c_a)[4] = a; + + for (int i = 0; i < 4; ++i) + { + EXPECT_TRUE(&gsl::at(a, i) == &a[i]); + EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. static_array"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + EXPECT_DEATH(gsl::at(a, -1), expected); + EXPECT_DEATH(gsl::at(a, 4), expected); + EXPECT_DEATH(gsl::at(c_a, -1), expected); + EXPECT_DEATH(gsl::at(c_a, 4), expected); +} + +TEST(at_tests, std_array) +{ + std::array a = {1, 2, 3, 4}; + const std::array& c_a = a; + + for (int i = 0; i < 4; ++i) + { + EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); + EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. std_array"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + EXPECT_DEATH(gsl::at(a, -1), expected); + EXPECT_DEATH(gsl::at(a, 4), expected); + EXPECT_DEATH(gsl::at(c_a, -1), expected); + EXPECT_DEATH(gsl::at(c_a, 4), expected); +} + +TEST(at_tests, std_vector) +{ + std::vector a = {1, 2, 3, 4}; + const std::vector& c_a = a; + + for (int i = 0; i < 4; ++i) + { + EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast(i)]); + EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast(i)]); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. std_vector"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + EXPECT_DEATH(gsl::at(a, -1), expected); + EXPECT_DEATH(gsl::at(a, 4), expected); + EXPECT_DEATH(gsl::at(c_a, -1), expected); + EXPECT_DEATH(gsl::at(c_a, 4), expected); +} + +TEST(at_tests, InitializerList) +{ + const std::initializer_list a = {1, 2, 3, 4}; + + for (int i = 0; i < 4; ++i) + { + EXPECT_TRUE(gsl::at(a, i) == i + 1); + EXPECT_TRUE(gsl::at({1, 2, 3, 4}, i) == i + 1); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. InitializerList"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + EXPECT_DEATH(gsl::at(a, -1), expected); + EXPECT_DEATH(gsl::at(a, 4), expected); + EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), expected); + EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), expected); +} + +#if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L +TEST(at_tests, std_span) +{ + std::vector vec{1, 2, 3, 4, 5}; + std::span sp{vec}; + + std::vector cvec{1, 2, 3, 4, 5}; + std::span csp{cvec}; + + for (gsl::index i = 0; i < gsl::narrow_cast(vec.size()); ++i) + { + EXPECT_TRUE(&gsl::at(sp, i) == &vec[gsl::narrow_cast(i)]); + EXPECT_TRUE(&gsl::at(csp, i) == &cvec[gsl::narrow_cast(i)]); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. std_span"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + EXPECT_DEATH(gsl::at(sp, -1), expected); + EXPECT_DEATH(gsl::at(sp, gsl::narrow_cast(sp.size())), expected); + EXPECT_DEATH(gsl::at(csp, -1), expected); + EXPECT_DEATH(gsl::at(csp, gsl::narrow_cast(sp.size())), expected); +} +#endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L + +#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910 +static constexpr bool test_constexpr() +{ + int a1[4] = {1, 2, 3, 4}; + const int(&c_a1)[4] = a1; + std::array a2 = {1, 2, 3, 4}; + const std::array& c_a2 = a2; + + for (int i = 0; i < 4; ++i) + { + if (&gsl::at(a1, i) != &a1[i]) return false; + if (&gsl::at(c_a1, i) != &a1[i]) return false; + // requires C++17: + // if (&gsl::at(a2, i) != &a2[static_cast(i)]) return false; + if (&gsl::at(c_a2, i) != &c_a2[static_cast(i)]) return false; + if (gsl::at({1, 2, 3, 4}, i) != i + 1) return false; + } + + return true; +} + +static_assert(test_constexpr(), "FAIL"); +#endif diff --git a/deps/GSL/tests/byte_tests.cpp b/deps/GSL/tests/byte_tests.cpp new file mode 100644 index 0000000..fbef36f --- /dev/null +++ b/deps/GSL/tests/byte_tests.cpp @@ -0,0 +1,137 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for to_byte, to_integer, byte, operator&, ope... + +using namespace std; +using namespace gsl; + +namespace +{ +int modify_both(gsl::byte& b, int& i) +{ + i = 10; + b = to_byte<5>(); + return i; +} + +TEST(byte_tests, construction) +{ + { + const byte b = static_cast(4); + EXPECT_TRUE(static_cast(b) == 4); + } + + // clang-format off + GSL_SUPPRESS(es.49) + // clang-format on + { + const byte b = byte(12); + EXPECT_TRUE(static_cast(b) == 12); + } + + { + const byte b = to_byte<12>(); + EXPECT_TRUE(static_cast(b) == 12); + } + { + const unsigned char uc = 12; + const byte b = to_byte(uc); + EXPECT_TRUE(static_cast(b) == 12); + } + +#if defined(__cplusplus) && (__cplusplus >= 201703L) + { + const byte b{14}; + EXPECT_TRUE(static_cast(b) == 14); + } +#endif + +#ifdef CONFIRM_COMPILATION_ERRORS + to_byte(char{}); + to_byte(3); + to_byte(3u); +#endif +} + +TEST(byte_tests, bitwise_operations) +{ + const byte b = to_byte<0xFF>(); + + byte a = to_byte<0x00>(); + EXPECT_TRUE((b | a) == to_byte<0xFF>()); + EXPECT_TRUE(a == to_byte<0x00>()); + + a |= b; + EXPECT_TRUE(a == to_byte<0xFF>()); + + a = to_byte<0x01>(); + EXPECT_TRUE((b & a) == to_byte<0x01>()); + + a &= b; + EXPECT_TRUE(a == to_byte<0x01>()); + + EXPECT_TRUE((b ^ a) == to_byte<0xFE>()); + + EXPECT_TRUE(a == to_byte<0x01>()); + a ^= b; + EXPECT_TRUE(a == to_byte<0xFE>()); + + a = to_byte<0x01>(); + EXPECT_TRUE(~a == to_byte<0xFE>()); + + a = to_byte<0xFF>(); + EXPECT_TRUE((a << 4) == to_byte<0xF0>()); + EXPECT_TRUE((a >> 4) == to_byte<0x0F>()); + + a <<= 4; + EXPECT_TRUE(a == to_byte<0xF0>()); + a >>= 4; + EXPECT_TRUE(a == to_byte<0x0F>()); +} + +TEST(byte_tests, to_integer) +{ + const byte b = to_byte<0x12>(); + + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + EXPECT_TRUE(0x12 == gsl::to_integer(b)); + + // EXPECT_TRUE(0x12 == gsl::to_integer(b)); // expect compile-time error + // EXPECT_TRUE(0x12 == gsl::to_integer(b)); // expect compile-time error +} + +TEST(byte_tests, aliasing) +{ + int i{0}; + const int res = modify_both(reinterpret_cast(i), i); + EXPECT_TRUE(res == i); +} + +} // namespace + +#ifdef CONFIRM_COMPILATION_ERRORS +copy(src_span_static, dst_span_static); +#endif diff --git a/deps/GSL/tests/deathTestCommon.h b/deps/GSL/tests/deathTestCommon.h new file mode 100644 index 0000000..e92beb3 --- /dev/null +++ b/deps/GSL/tests/deathTestCommon.h @@ -0,0 +1,11 @@ +#pragma once +#include + +constexpr char deathstring[] = "Expected Death"; +constexpr char failed_set_terminate_deathstring[] = ".*"; + +// This prevents a failed call to set_terminate from failing the test suite. +constexpr const char* GetExpectedDeathString(std::terminate_handler handle) +{ + return handle ? deathstring : failed_set_terminate_deathstring; +} diff --git a/deps/GSL/tests/no_exception_ensure_tests.cpp b/deps/GSL/tests/no_exception_ensure_tests.cpp new file mode 100644 index 0000000..5e5d682 --- /dev/null +++ b/deps/GSL/tests/no_exception_ensure_tests.cpp @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include // for std::exit +#include // for span +#include +#include + +int operator_subscript_no_throw() noexcept +{ + int arr[10]; + const gsl::span sp{arr}; + return sp[11]; +} + +[[noreturn]] void test_terminate() { std::exit(0); } + +void setup_termination_handler() noexcept +{ +#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) + + auto& handler = gsl::details::get_terminate_handler(); + handler = &test_terminate; + +#else + + std::set_terminate(test_terminate); + +#endif +} + +int main() noexcept +{ + std::cout << "Running main() from " __FILE__ "\n"; +#if defined(IOS_PROCESS_DELAY_WORKAROUND) + std::this_thread::sleep_for(std::chrono::seconds(1)); +#endif + setup_termination_handler(); + operator_subscript_no_throw(); + return -1; +} diff --git a/deps/GSL/tests/notnull_tests.cpp b/deps/GSL/tests/notnull_tests.cpp new file mode 100644 index 0000000..4c317d9 --- /dev/null +++ b/deps/GSL/tests/notnull_tests.cpp @@ -0,0 +1,636 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for not_null, operator<, operator<=, operator> + +#include // for addressof +#include // for uint16_t +#include // for shared_ptr, make_shared, operator<, opera... +#include // for operator<<, ostringstream, basic_ostream:... +#include // for basic_string, operator==, string, operator<< +#include // for type_info + +#include "deathTestCommon.h" +using namespace gsl; + +struct MyBase +{ +}; +struct MyDerived : public MyBase +{ +}; +struct Unrelated +{ +}; + +// stand-in for a user-defined ref-counted class +template +struct RefCounted +{ + RefCounted(T* p) : p_(p) {} + operator T*() { return p_; } + T* p_; +}; + +// user defined smart pointer with comparison operators returning non bool value +template +struct CustomPtr +{ + CustomPtr(T* p) : p_(p) {} + operator T*() const { return p_; } + bool operator!=(std::nullptr_t) const { return p_ != nullptr; } + T* p_ = nullptr; +}; + +template +std::string operator==(CustomPtr const& lhs, CustomPtr const& rhs) +{ + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return reinterpret_cast(lhs.p_) == reinterpret_cast(rhs.p_) ? "true" + : "false"; +} + +template +std::string operator!=(CustomPtr const& lhs, CustomPtr const& rhs) +{ + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return reinterpret_cast(lhs.p_) != reinterpret_cast(rhs.p_) ? "true" + : "false"; +} + +template +std::string operator<(CustomPtr const& lhs, CustomPtr const& rhs) +{ + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return reinterpret_cast(lhs.p_) < reinterpret_cast(rhs.p_) ? "true" + : "false"; +} + +template +std::string operator>(CustomPtr const& lhs, CustomPtr const& rhs) +{ + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return reinterpret_cast(lhs.p_) > reinterpret_cast(rhs.p_) ? "true" + : "false"; +} + +template +std::string operator<=(CustomPtr const& lhs, CustomPtr const& rhs) +{ + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return reinterpret_cast(lhs.p_) <= reinterpret_cast(rhs.p_) ? "true" + : "false"; +} + +template +std::string operator>=(CustomPtr const& lhs, CustomPtr const& rhs) +{ + // clang-format off + GSL_SUPPRESS(type.1) // NO-FORMAT: attribute + // clang-format on + return reinterpret_cast(lhs.p_) >= reinterpret_cast(rhs.p_) ? "true" + : "false"; +} + +struct NonCopyableNonMovable +{ + NonCopyableNonMovable() = default; + NonCopyableNonMovable(const NonCopyableNonMovable&) = delete; + NonCopyableNonMovable& operator=(const NonCopyableNonMovable&) = delete; + NonCopyableNonMovable(NonCopyableNonMovable&&) = delete; + NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete; +}; + +namespace +{ +// clang-format off +GSL_SUPPRESS(f .4) // NO-FORMAT: attribute +// clang-format on +bool helper(not_null p) { return *p == 12; } +// clang-format off +GSL_SUPPRESS(f .4) // NO-FORMAT: attribute +// clang-format on +bool helper_const(not_null p) { return *p == 12; } + +int* return_pointer() { return nullptr; } +} // namespace + +TEST(notnull_tests, TestNotNullConstructors) +{ + { +#ifdef CONFIRM_COMPILATION_ERRORS + not_null p = nullptr; // yay...does not compile! + not_null*> p1 = 0; // yay...does not compile! + not_null p2; // yay...does not compile! + std::unique_ptr up = std::make_unique(120); + not_null p3 = up; + + // Forbid non-nullptr assignable types + not_null> f(std::vector{1}); + not_null z(10); + not_null> y({1, 2}); +#endif + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. TestNotNullConstructors"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + // from shared pointer + int i = 12; + auto rp = RefCounted(&i); + not_null p(rp); + EXPECT_TRUE(p.get() == &i); + + not_null> x( + std::make_shared(10)); // shared_ptr is nullptr assignable + + int* pi = nullptr; + EXPECT_DEATH((not_null(pi)), expected); + } + + { + // from pointer to local + int t = 42; + + not_null x = &t; + helper(&t); + helper_const(&t); + + EXPECT_TRUE(*x == 42); + } + + { + // from raw pointer + // from not_null pointer + + int t = 42; + int* p = &t; + + not_null x = p; + helper(p); + helper_const(p); + helper(x); + helper_const(x); + + EXPECT_TRUE(*x == 42); + } + + { + // from raw const pointer + // from not_null const pointer + + int t = 42; + const int* cp = &t; + + not_null x = cp; + helper_const(cp); + helper_const(x); + + EXPECT_TRUE(*x == 42); + } + + { + // from not_null const pointer, using auto + int t = 42; + const int* cp = &t; + + auto x = not_null{cp}; + + EXPECT_TRUE(*x == 42); + } + + { + // from returned pointer + + EXPECT_DEATH(helper(return_pointer()), expected); + EXPECT_DEATH(helper_const(return_pointer()), expected); + } +} + +template +void ostream_helper(T v) +{ + not_null p(&v); + { + std::ostringstream os; + std::ostringstream ref; + os << static_cast(p); + ref << static_cast(&v); + EXPECT_TRUE(os.str() == ref.str()); + } + { + std::ostringstream os; + std::ostringstream ref; + os << *p; + ref << v; + EXPECT_TRUE(os.str() == ref.str()); + } +} + +TEST(notnull_tests, TestNotNullostream) +{ + ostream_helper(17); + ostream_helper(21.5f); + ostream_helper(3.4566e-7); + ostream_helper('c'); + ostream_helper(0x0123u); + ostream_helper("cstring"); + ostream_helper("string"); +} + +TEST(notnull_tests, TestNotNullCasting) +{ + MyBase base; + MyDerived derived; + Unrelated unrelated; + not_null u{&unrelated}; + (void) u; + not_null p{&derived}; + not_null q(&base); + q = p; // allowed with heterogeneous copy ctor + EXPECT_TRUE(q == p); + +#ifdef CONFIRM_COMPILATION_ERRORS + q = u; // no viable conversion possible between MyBase* and Unrelated* + p = q; // not possible to implicitly convert MyBase* to MyDerived* + + not_null r = p; + not_null s = reinterpret_cast(p); +#endif + not_null t(reinterpret_cast(p.get())); + EXPECT_TRUE(reinterpret_cast(p.get()) == reinterpret_cast(t.get())); +} + +TEST(notnull_tests, TestNotNullAssignment) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. TestNotNullAssignmentd"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int i = 12; + not_null p(&i); + EXPECT_TRUE(helper(p)); + + int* q = nullptr; + EXPECT_DEATH(p = not_null(q), expected); +} + +TEST(notnull_tests, TestNotNullRawPointerComparison) +{ + int ints[2] = {42, 43}; + int* p1 = &ints[0]; + const int* p2 = &ints[1]; + + using NotNull1 = not_null; + using NotNull2 = not_null; + + EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == true); + EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == false); + + EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == false); + EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == true); + + EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == false); + EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); + EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); + + EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == false); + EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); + EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); + + EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == true); + EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); + EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); +} + +TEST(notnull_tests, TestNotNullDereferenceOperator) +{ + { + auto sp1 = std::make_shared(); + + using NotNullSp1 = not_null; + EXPECT_TRUE(typeid(*sp1) == typeid(*NotNullSp1(sp1))); + EXPECT_TRUE(std::addressof(*NotNullSp1(sp1)) == std::addressof(*sp1)); + } + + { + int ints[1] = {42}; + CustomPtr p1(&ints[0]); + + using NotNull1 = not_null; + EXPECT_TRUE(typeid(*NotNull1(p1)) == typeid(*p1)); + EXPECT_TRUE(*NotNull1(p1) == 42); + *NotNull1(p1) = 43; + EXPECT_TRUE(ints[0] == 43); + } + + { + int v = 42; + gsl::not_null p(&v); + EXPECT_TRUE(typeid(*p) == typeid(*(&v))); + *p = 43; + EXPECT_TRUE(v == 43); + } +} + +TEST(notnull_tests, TestNotNullSharedPtrComparison) +{ + auto sp1 = std::make_shared(42); + auto sp2 = std::make_shared(43); + + using NotNullSp1 = not_null; + using NotNullSp2 = not_null; + + EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp1(sp1)) == true); + EXPECT_TRUE((NotNullSp1(sp1) == NotNullSp2(sp2)) == false); + + EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp1(sp1)) == false); + EXPECT_TRUE((NotNullSp1(sp1) != NotNullSp2(sp2)) == true); + + EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp1(sp1)) == false); + EXPECT_TRUE((NotNullSp1(sp1) < NotNullSp2(sp2)) == (sp1 < sp2)); + EXPECT_TRUE((NotNullSp2(sp2) < NotNullSp1(sp1)) == (sp2 < sp1)); + + EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp1(sp1)) == false); + EXPECT_TRUE((NotNullSp1(sp1) > NotNullSp2(sp2)) == (sp1 > sp2)); + EXPECT_TRUE((NotNullSp2(sp2) > NotNullSp1(sp1)) == (sp2 > sp1)); + + EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp1(sp1)) == true); + EXPECT_TRUE((NotNullSp1(sp1) <= NotNullSp2(sp2)) == (sp1 <= sp2)); + EXPECT_TRUE((NotNullSp2(sp2) <= NotNullSp1(sp1)) == (sp2 <= sp1)); + + EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp1(sp1)) == true); + EXPECT_TRUE((NotNullSp1(sp1) >= NotNullSp2(sp2)) == (sp1 >= sp2)); + EXPECT_TRUE((NotNullSp2(sp2) >= NotNullSp1(sp1)) == (sp2 >= sp1)); +} + +TEST(notnull_tests, TestNotNullCustomPtrComparison) +{ + int ints[2] = {42, 43}; + CustomPtr p1(&ints[0]); + CustomPtr p2(&ints[1]); + + using NotNull1 = not_null; + using NotNull2 = not_null; + + EXPECT_TRUE((NotNull1(p1) == NotNull1(p1)) == "true"); + EXPECT_TRUE((NotNull1(p1) == NotNull2(p2)) == "false"); + + EXPECT_TRUE((NotNull1(p1) != NotNull1(p1)) == "false"); + EXPECT_TRUE((NotNull1(p1) != NotNull2(p2)) == "true"); + + EXPECT_TRUE((NotNull1(p1) < NotNull1(p1)) == "false"); + EXPECT_TRUE((NotNull1(p1) < NotNull2(p2)) == (p1 < p2)); + EXPECT_TRUE((NotNull2(p2) < NotNull1(p1)) == (p2 < p1)); + + EXPECT_TRUE((NotNull1(p1) > NotNull1(p1)) == "false"); + EXPECT_TRUE((NotNull1(p1) > NotNull2(p2)) == (p1 > p2)); + EXPECT_TRUE((NotNull2(p2) > NotNull1(p1)) == (p2 > p1)); + + EXPECT_TRUE((NotNull1(p1) <= NotNull1(p1)) == "true"); + EXPECT_TRUE((NotNull1(p1) <= NotNull2(p2)) == (p1 <= p2)); + EXPECT_TRUE((NotNull2(p2) <= NotNull1(p1)) == (p2 <= p1)); + + EXPECT_TRUE((NotNull1(p1) >= NotNull1(p1)) == "true"); + EXPECT_TRUE((NotNull1(p1) >= NotNull2(p2)) == (p1 >= p2)); + EXPECT_TRUE((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1)); +} + +#if defined(__cplusplus) && (__cplusplus >= 201703L) + +TEST(notnull_tests, TestNotNullConstructorTypeDeduction) +{ + { + int i = 42; + + not_null x{&i}; + helper(not_null{&i}); + helper_const(not_null{&i}); + + EXPECT_TRUE(*x == 42); + } + + { + const int i = 42; + + not_null x{&i}; +#ifdef CONFIRM_COMPILATION_ERRORS + helper(not_null{&i}); +#endif + helper_const(not_null{&i}); + + EXPECT_TRUE(*x == 42); + } + + { + int i = 42; + int* p = &i; + + not_null x{p}; + helper(not_null{p}); + helper_const(not_null{p}); + + EXPECT_TRUE(*x == 42); + } + + { + const int i = 42; + const int* p = &i; + + not_null x{p}; +#ifdef CONFIRM_COMPILATION_ERRORS + helper(not_null{p}); +#endif + helper_const(not_null{p}); + + EXPECT_TRUE(*x == 42); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. TestNotNullConstructorTypeDeduction"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + auto workaround_macro = []() { + int* p1 = nullptr; + const not_null x{p1}; + }; + EXPECT_DEATH(workaround_macro(), expected); + } + + { + auto workaround_macro = []() { + const int* p1 = nullptr; + const not_null x{p1}; + }; + EXPECT_DEATH(workaround_macro(), expected); + } + + { + int* p = nullptr; + + EXPECT_DEATH(helper(not_null{p}), expected); + EXPECT_DEATH(helper_const(not_null{p}), expected); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + not_null x{nullptr}; + helper(not_null{nullptr}); + helper_const(not_null{nullptr}); + } +#endif +} +#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) + +TEST(notnull_tests, TestMakeNotNull) +{ + { + int i = 42; + + const auto x = make_not_null(&i); + helper(make_not_null(&i)); + helper_const(make_not_null(&i)); + + EXPECT_TRUE(*x == 42); + } + + { + const int i = 42; + + const auto x = make_not_null(&i); +#ifdef CONFIRM_COMPILATION_ERRORS + helper(make_not_null(&i)); +#endif + helper_const(make_not_null(&i)); + + EXPECT_TRUE(*x == 42); + } + + { + int i = 42; + int* p = &i; + + const auto x = make_not_null(p); + helper(make_not_null(p)); + helper_const(make_not_null(p)); + + EXPECT_TRUE(*x == 42); + } + + { + const int i = 42; + const int* p = &i; + + const auto x = make_not_null(p); +#ifdef CONFIRM_COMPILATION_ERRORS + helper(make_not_null(p)); +#endif + helper_const(make_not_null(p)); + + EXPECT_TRUE(*x == 42); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. TestMakeNotNull"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + const auto workaround_macro = []() { + int* p1 = nullptr; + const auto x = make_not_null(p1); + EXPECT_TRUE(*x == 42); + }; + EXPECT_DEATH(workaround_macro(), expected); + } + + { + const auto workaround_macro = []() { + const int* p1 = nullptr; + const auto x = make_not_null(p1); + EXPECT_TRUE(*x == 42); + }; + EXPECT_DEATH(workaround_macro(), expected); + } + + { + int* p = nullptr; + + EXPECT_DEATH(helper(make_not_null(p)), expected); + EXPECT_DEATH(helper_const(make_not_null(p)), expected); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + EXPECT_DEATH(make_not_null(nullptr), expected); + EXPECT_DEATH(helper(make_not_null(nullptr)), expected); + EXPECT_DEATH(helper_const(make_not_null(nullptr)), expected); + } +#endif +} + +TEST(notnull_tests, TestStdHash) +{ + { + int x = 42; + int y = 99; + not_null nn{&x}; + const not_null cnn{&x}; + + std::hash> hash_nn; + std::hash hash_intptr; + + EXPECT_TRUE(hash_nn(nn) == hash_intptr(&x)); + EXPECT_FALSE(hash_nn(nn) == hash_intptr(&y)); + EXPECT_FALSE(hash_nn(nn) == hash_intptr(nullptr)); + } + + { + const int x = 42; + const int y = 99; + not_null nn{&x}; + const not_null cnn{&x}; + + std::hash> hash_nn; + std::hash hash_intptr; + + EXPECT_TRUE(hash_nn(nn) == hash_intptr(&x)); + EXPECT_FALSE(hash_nn(nn) == hash_intptr(&y)); + EXPECT_FALSE(hash_nn(nn) == hash_intptr(nullptr)); + } +} diff --git a/deps/GSL/tests/owner_tests.cpp b/deps/GSL/tests/owner_tests.cpp new file mode 100644 index 0000000..87c7cec --- /dev/null +++ b/deps/GSL/tests/owner_tests.cpp @@ -0,0 +1,43 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for owner + +using namespace gsl; + +GSL_SUPPRESS(f .23) // NO-FORMAT: attribute +void f(int* i) { *i += 1; } + +TEST(owner_tests, basic_test) +{ + owner p = new int(120); + EXPECT_TRUE(*p == 120); + f(p); + EXPECT_TRUE(*p == 121); + delete p; +} + +TEST(owner_tests, check_pointer_constraint) +{ +#ifdef CONFIRM_COMPILATION_ERRORS + { + owner integerTest = 10; + owner> sharedPtrTest(new int(10)); + } +#endif +} diff --git a/deps/GSL/tests/span_compatibility_tests.cpp b/deps/GSL/tests/span_compatibility_tests.cpp new file mode 100644 index 0000000..95d8223 --- /dev/null +++ b/deps/GSL/tests/span_compatibility_tests.cpp @@ -0,0 +1,1023 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for byte +#include // for span, span_iterator, operator==, operator!= + +#include // for array +#include // for ptrdiff_t +#include // for reverse_iterator, operator-, operator== +#include // for integral_constant<>::value, is_default_co... +#include +#include // for vector + +using namespace std; +using namespace gsl; + +// Below are tests that verify the gsl interface support the same things as the std +// Ranges and Concepts support need to be added later. + +struct Base +{ +}; +struct Derived : Base +{ +}; +static_assert(std::is_convertible::value, "std::is_convertible"); +static_assert(!std::is_convertible::value, + "!std::is_convertible"); + +// int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was +// provided with N4261. +template +void ArrayConvertibilityCheck() +{ +#if __cplusplus >= 201703l + if constexpr (std::is_convertible::value) + { + std::array stl_nullptr{{nullptr, nullptr, nullptr}}; + gsl::span sp_const_nullptr_1{stl_nullptr}; + EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data()); + EXPECT_TRUE(sp_const_nullptr_1.size() == 3); + + gsl::span sp_const_nullptr_2{std::as_const(stl_nullptr)}; + EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); + EXPECT_TRUE(sp_const_nullptr_2.size() == 3); + + static_assert(std::is_same>::value, + "std::is_same< decltype(span{stl_nullptr}), span>::value"); + static_assert( + std::is_same>::value, + "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span>::value"); + } +#endif +} + +TEST(span_compatibility_tests, assertion_tests) +{ + int arr[3]{10, 20, 30}; + std::array stl{{100, 200, 300}}; + + ArrayConvertibilityCheck(); + + { + gsl::span sp_dyn; + EXPECT_TRUE(sp_dyn.data() == nullptr); + EXPECT_TRUE(sp_dyn.size() == 0); + EXPECT_TRUE(sp_dyn.empty()); + } + { + gsl::span sp_zero; + EXPECT_TRUE(sp_zero.data() == nullptr); + EXPECT_TRUE(sp_zero.size() == 0); + EXPECT_TRUE(sp_zero.empty()); + + gsl::span sp_dyn_a(arr, 3); + gsl::span sp_dyn_b(begin(arr), 3); + EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_a.size() == 3); + EXPECT_TRUE(sp_dyn_b.size() == 3); + + gsl::span sp_three_a(arr, 3); + gsl::span sp_three_b(begin(arr), 3); + EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_a.size() == 3); + EXPECT_TRUE(sp_three_b.size() == 3); + + gsl::span sp_const_a(arr, 3); + gsl::span sp_const_b(begin(arr), 3); + EXPECT_TRUE(sp_const_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_a.size() == 3); + EXPECT_TRUE(sp_const_b.size() == 3); + +#if __cplusplus >= 201703l + gsl::span sp_const_c(std::as_const(arr), 3); + EXPECT_TRUE(sp_const_c.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_c.size() == 3); +#endif // __cplusplus >= 201703l + + gsl::span sp_const_d(cbegin(arr), 3); + EXPECT_TRUE(sp_const_d.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_d.size() == 3); + } + { + gsl::span sp_dyn_a(begin(arr), std::end(arr)); + EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_a.size() == 3); + + gsl::span sp_three_a(begin(arr), std::end(arr)); + EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_a.size() == 3); + + gsl::span sp_const_a(begin(arr), std::end(arr)); + gsl::span sp_const_b(begin(arr), std::cend(arr)); + gsl::span sp_const_c(cbegin(arr), std::end(arr)); + gsl::span sp_const_d(cbegin(arr), std::cend(arr)); + EXPECT_TRUE(sp_const_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_c.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_d.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_a.size() == 3); + EXPECT_TRUE(sp_const_b.size() == 3); + EXPECT_TRUE(sp_const_c.size() == 3); + EXPECT_TRUE(sp_const_d.size() == 3); + } + { + gsl::span sp_dyn_a(arr); + gsl::span sp_dyn_b(stl); + gsl::span sp_dyn_c{stl}; + gsl::span sp_dyn_d{stl}; + EXPECT_TRUE(sp_dyn_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn_b.data() == stl.data()); + EXPECT_TRUE(sp_dyn_a.size() == 3); + EXPECT_TRUE(sp_dyn_b.size() == 3); + + gsl::span sp_three_a(arr); + gsl::span sp_three_b(stl); + EXPECT_TRUE(sp_three_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_three_b.data() == stl.data()); + EXPECT_TRUE(sp_three_a.size() == 3); + EXPECT_TRUE(sp_three_b.size() == 3); + + gsl::span sp_const_w(arr); + gsl::span sp_const_y(stl); + EXPECT_TRUE(sp_const_w.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_y.data() == stl.data()); + EXPECT_TRUE(sp_const_w.size() == 3); + EXPECT_TRUE(sp_const_y.size() == 3); + +#if __cplusplus >= 201703l + gsl::span sp_const_x(std::as_const(arr)); + EXPECT_TRUE(sp_const_x.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_x.size() == 3); + + gsl::span sp_const_z(std::as_const(stl)); + EXPECT_TRUE(sp_const_z.data() == stl.data()); + EXPECT_TRUE(sp_const_z.size() == 3); +#endif // __cplusplus >= 201703l + } + { + const gsl::span orig_dyn(arr); + const gsl::span orig_three(arr); + const gsl::span orig_const_dyn(arr); + const gsl::span orig_const_three(arr); + + gsl::span sp_a(orig_dyn); + gsl::span sp_b(orig_three); + + gsl::span sp_c(orig_three); + + gsl::span sp_d(orig_dyn); + gsl::span sp_e(orig_three); + gsl::span sp_f(orig_const_dyn); + gsl::span sp_g(orig_const_three); + + gsl::span sp_h(orig_three); + gsl::span sp_i(orig_const_three); + + EXPECT_TRUE(sp_a.data() == std::begin(arr)); + EXPECT_TRUE(sp_b.data() == std::begin(arr)); + EXPECT_TRUE(sp_c.data() == std::begin(arr)); + EXPECT_TRUE(sp_d.data() == std::begin(arr)); + EXPECT_TRUE(sp_e.data() == std::begin(arr)); + EXPECT_TRUE(sp_f.data() == std::begin(arr)); + EXPECT_TRUE(sp_g.data() == std::begin(arr)); + EXPECT_TRUE(sp_h.data() == std::begin(arr)); + EXPECT_TRUE(sp_i.data() == std::begin(arr)); + EXPECT_TRUE(sp_a.size() == 3); + EXPECT_TRUE(sp_b.size() == 3); + EXPECT_TRUE(sp_c.size() == 3); + EXPECT_TRUE(sp_d.size() == 3); + EXPECT_TRUE(sp_e.size() == 3); + EXPECT_TRUE(sp_f.size() == 3); + EXPECT_TRUE(sp_g.size() == 3); + EXPECT_TRUE(sp_h.size() == 3); + EXPECT_TRUE(sp_i.size() == 3); + } + { + gsl::span sp_dyn(arr); + gsl::span sp_three(arr); + gsl::span sp_const_dyn(arr); + gsl::span sp_const_three(arr); + + EXPECT_TRUE(sp_dyn.data() == std::begin(arr)); + EXPECT_TRUE(sp_three.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_dyn.data() == std::begin(arr)); + EXPECT_TRUE(sp_const_three.data() == std::begin(arr)); + EXPECT_TRUE(sp_dyn.size() == 3); + EXPECT_TRUE(sp_three.size() == 3); + EXPECT_TRUE(sp_const_dyn.size() == 3); + EXPECT_TRUE(sp_const_three.size() == 3); + + int other[4]{12, 34, 56, 78}; + + sp_dyn = gsl::span{other}; + sp_three = gsl::span{stl}; + sp_const_dyn = gsl::span{other}; + sp_const_three = gsl::span{stl}; + + EXPECT_TRUE(sp_dyn.data() == std::begin(other)); + EXPECT_TRUE(sp_three.data() == stl.data()); + EXPECT_TRUE(sp_const_dyn.data() == std::begin(other)); + EXPECT_TRUE(sp_const_three.data() == stl.data()); + EXPECT_TRUE(sp_dyn.size() == 4); + EXPECT_TRUE(sp_three.size() == 3); + EXPECT_TRUE(sp_const_dyn.size() == 4); + EXPECT_TRUE(sp_const_three.size() == 3); + } + { + gsl::span::iterator it_dyn{}; + + { + gsl::span sp_dyn(arr); + it_dyn = sp_dyn.begin(); + } + + EXPECT_TRUE(*it_dyn == arr[0]); + EXPECT_TRUE(it_dyn[2] == arr[2]); + + gsl::span::iterator it_three{}; + + { + gsl::span sp_three(stl); + it_three = sp_three.begin(); + } + + EXPECT_TRUE(*it_three == stl[0]); + EXPECT_TRUE(it_three[2] == stl[2]); + } + + { + int sequence[9]{10, 20, 30, 40, 50, 60, 70, 80, 90}; + + const gsl::span sp_dyn(sequence); + const gsl::span sp_nine(sequence); + + auto first_3 = sp_dyn.first<3>(); + auto first_4 = sp_nine.first<4>(); + auto first_5 = sp_dyn.first(5); + auto first_6 = sp_nine.first(6); + static_assert(noexcept(sp_dyn.first<3>()), "noexcept(sp_dyn.first<3>())"); // strengthened + static_assert(noexcept(sp_nine.first<4>()), "noexcept(sp_nine.first<4>())"); // strengthened + static_assert(noexcept(sp_dyn.first(5)), "noexcept(sp_dyn.first(5))"); // strengthened + static_assert(noexcept(sp_nine.first(6)), "noexcept(sp_nine.first(6))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(first_3.data() == std::begin(sequence)); + EXPECT_TRUE(first_4.data() == std::begin(sequence)); + EXPECT_TRUE(first_5.data() == std::begin(sequence)); + EXPECT_TRUE(first_6.data() == std::begin(sequence)); + EXPECT_TRUE(first_3.size() == 3); + EXPECT_TRUE(first_4.size() == 4); + EXPECT_TRUE(first_5.size() == 5); + EXPECT_TRUE(first_6.size() == 6); + + auto last_3 = sp_dyn.last<3>(); + auto last_4 = sp_nine.last<4>(); + auto last_5 = sp_dyn.last(5); + auto last_6 = sp_nine.last(6); + static_assert(noexcept(sp_dyn.last<3>()), "noexcept(sp_dyn.last<3>())"); // strengthened + static_assert(noexcept(sp_nine.last<4>()), "noexcept(sp_nine.last<4>())"); // strengthened + static_assert(noexcept(sp_dyn.last(5)), "noexcept(sp_dyn.last(5))"); // strengthened + static_assert(noexcept(sp_nine.last(6)), "noexcept(sp_nine.last(6))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(last_3.data() == std::begin(sequence) + 6); + EXPECT_TRUE(last_4.data() == std::begin(sequence) + 5); + EXPECT_TRUE(last_5.data() == std::begin(sequence) + 4); + EXPECT_TRUE(last_6.data() == std::begin(sequence) + 3); + EXPECT_TRUE(last_3.size() == 3); + EXPECT_TRUE(last_4.size() == 4); + EXPECT_TRUE(last_5.size() == 5); + EXPECT_TRUE(last_6.size() == 6); + + auto offset_3 = sp_dyn.subspan<3>(); + auto offset_4 = sp_nine.subspan<4>(); + auto offset_5 = sp_dyn.subspan(5); + auto offset_6 = sp_nine.subspan(6); + static_assert(noexcept(sp_dyn.subspan<3>()), + "noexcept(sp_dyn.subspan<3>())"); // strengthened + static_assert(noexcept(sp_nine.subspan<4>()), + "noexcept(sp_nine.subspan<4>())"); // strengthened + static_assert(noexcept(sp_dyn.subspan(5)), "noexcept(sp_dyn.subspan(5))"); // strengthened + static_assert(noexcept(sp_nine.subspan(6)), "noexcept(sp_nine.subspan(6))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(offset_3.data() == std::begin(sequence) + 3); + EXPECT_TRUE(offset_4.data() == std::begin(sequence) + 4); + EXPECT_TRUE(offset_5.data() == std::begin(sequence) + 5); + EXPECT_TRUE(offset_6.data() == std::begin(sequence) + 6); + EXPECT_TRUE(offset_3.size() == 6); + EXPECT_TRUE(offset_4.size() == 5); + EXPECT_TRUE(offset_5.size() == 4); + EXPECT_TRUE(offset_6.size() == 3); + + auto subspan_3 = sp_dyn.subspan<3, 2>(); + auto subspan_4 = sp_nine.subspan<4, 2>(); + auto subspan_5 = sp_dyn.subspan(5, 2); + auto subspan_6 = sp_nine.subspan(6, 2); + static_assert(noexcept(sp_dyn.subspan<3, 2>()), + "noexcept(sp_dyn.subspan<3, 2>())"); // strengthened + static_assert(noexcept(sp_nine.subspan<4, 2>()), + "noexcept(sp_nine.subspan<4, 2>())"); // strengthened + static_assert(noexcept(sp_dyn.subspan(5, 2)), + "noexcept(sp_dyn.subspan(5, 2))"); // strengthened + static_assert(noexcept(sp_nine.subspan(6, 2)), + "noexcept(sp_nine.subspan(6, 2))"); // strengthened + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + EXPECT_TRUE(subspan_3.data() == std::begin(sequence) + 3); + EXPECT_TRUE(subspan_4.data() == std::begin(sequence) + 4); + EXPECT_TRUE(subspan_5.data() == std::begin(sequence) + 5); + EXPECT_TRUE(subspan_6.data() == std::begin(sequence) + 6); + EXPECT_TRUE(subspan_3.size() == 2); + EXPECT_TRUE(subspan_4.size() == 2); + EXPECT_TRUE(subspan_5.size() == 2); + EXPECT_TRUE(subspan_6.size() == 2); + + static_assert(noexcept(sp_dyn.size()), "noexcept(sp_dyn.size())"); + static_assert(noexcept(sp_dyn.size_bytes()), "noexcept(sp_dyn.size_bytes())"); + static_assert(noexcept(sp_dyn.empty()), "noexcept(sp_dyn.empty())"); + static_assert(noexcept(sp_dyn[0]), "noexcept(sp_dyn[0])"); // strengthened + static_assert(noexcept(sp_dyn.front()), "noexcept(sp_dyn.front())"); // strengthened + static_assert(noexcept(sp_dyn.back()), "noexcept(sp_dyn.back())"); // strengthened + static_assert(noexcept(sp_dyn.data()), "noexcept(sp_dyn.data())"); + static_assert(noexcept(sp_dyn.begin()), "noexcept(sp_dyn.begin())"); + static_assert(noexcept(sp_dyn.end()), "noexcept(sp_dyn.end())"); + static_assert(noexcept(sp_dyn.rbegin()), "noexcept(sp_dyn.rbegin())"); + static_assert(noexcept(sp_dyn.rend()), "noexcept(sp_dyn.rend())"); + + static_assert(noexcept(sp_nine.size()), "noexcept(sp_nine.size())"); + static_assert(noexcept(sp_nine.size_bytes()), "noexcept(sp_nine.size_bytes())"); + static_assert(noexcept(sp_nine.empty()), "noexcept(sp_nine.empty())"); + static_assert(noexcept(sp_nine[0]), "noexcept(sp_nine[0])"); // strengthened + static_assert(noexcept(sp_nine.front()), "noexcept(sp_nine.front())"); // strengthened + static_assert(noexcept(sp_nine.back()), "noexcept(sp_nine.back())"); // strengthened + static_assert(noexcept(sp_nine.data()), "noexcept(sp_nine.data())"); + static_assert(noexcept(sp_nine.begin()), "noexcept(sp_nine.begin())"); + static_assert(noexcept(sp_nine.end()), "noexcept(sp_nine.end())"); + static_assert(noexcept(sp_nine.rbegin()), "noexcept(sp_nine.rbegin())"); + static_assert(noexcept(sp_nine.rend()), "noexcept(sp_nine.rend())"); + + EXPECT_TRUE(sp_dyn.size() == 9); + EXPECT_TRUE(sp_nine.size() == 9); + + EXPECT_TRUE(sp_dyn.size_bytes() == 9 * sizeof(int)); + EXPECT_TRUE(sp_nine.size_bytes() == 9 * sizeof(int)); + + EXPECT_TRUE(!sp_dyn.empty()); + EXPECT_TRUE(!sp_nine.empty()); + + EXPECT_TRUE(sp_dyn[0] == 10); + EXPECT_TRUE(sp_nine[0] == 10); + EXPECT_TRUE(sp_dyn[8] == 90); + EXPECT_TRUE(sp_nine[8] == 90); + + EXPECT_TRUE(sp_dyn.front() == 10); + EXPECT_TRUE(sp_nine.front() == 10); + + EXPECT_TRUE(sp_dyn.back() == 90); + EXPECT_TRUE(sp_nine.back() == 90); + + EXPECT_TRUE(&sp_dyn.front() == std::begin(sequence)); + EXPECT_TRUE(&sp_nine.front() == std::begin(sequence)); + EXPECT_TRUE(&sp_dyn[4] == std::begin(sequence) + 4); + EXPECT_TRUE(&sp_nine[4] == std::begin(sequence) + 4); + EXPECT_TRUE(&sp_dyn.back() == std::begin(sequence) + 8); + EXPECT_TRUE(&sp_nine.back() == std::begin(sequence) + 8); + + EXPECT_TRUE(sp_dyn.data() == std::begin(sequence)); + EXPECT_TRUE(sp_nine.data() == std::begin(sequence)); + + EXPECT_TRUE(*sp_dyn.begin() == 10); + EXPECT_TRUE(*sp_nine.begin() == 10); + + EXPECT_TRUE(sp_dyn.end()[-2] == 80); + EXPECT_TRUE(sp_nine.end()[-2] == 80); + + EXPECT_TRUE(*sp_dyn.rbegin() == 90); + EXPECT_TRUE(*sp_nine.rbegin() == 90); + + EXPECT_TRUE(sp_dyn.rend()[-2] == 20); + EXPECT_TRUE(sp_nine.rend()[-2] == 20); + + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert(is_same::iterator>::value, + "is_same::iterator>::value"); + static_assert( + is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + static_assert( + is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + static_assert(is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + static_assert( + is_same::reverse_iterator>::value, + "is_same::reverse_iterator>::value"); + } + { + int sequence[9]{10, 20, 30, 40, 50, 60, 70, 80, 90}; + + constexpr size_t SizeBytes = sizeof(sequence); + + const gsl::span sp_dyn(sequence); + const gsl::span sp_nine(sequence); + const gsl::span sp_const_dyn(sequence); + const gsl::span sp_const_nine(sequence); + + static_assert(noexcept(as_bytes(sp_dyn)), "noexcept(as_bytes(sp_dyn))"); + static_assert(noexcept(as_bytes(sp_nine)), "noexcept(as_bytes(sp_nine))"); + static_assert(noexcept(as_bytes(sp_const_dyn)), "noexcept(as_bytes(sp_const_dyn))"); + static_assert(noexcept(as_bytes(sp_const_nine)), "noexcept(as_bytes(sp_const_nine))"); + static_assert(noexcept(as_writable_bytes(sp_dyn)), "noexcept(as_writable_bytes(sp_dyn))"); + static_assert(noexcept(as_writable_bytes(sp_nine)), "noexcept(as_writable_bytes(sp_nine))"); + + auto sp_1 = as_bytes(sp_dyn); + auto sp_2 = as_bytes(sp_nine); + auto sp_3 = as_bytes(sp_const_dyn); + auto sp_4 = as_bytes(sp_const_nine); + auto sp_5 = as_writable_bytes(sp_dyn); + auto sp_6 = as_writable_bytes(sp_nine); + + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + static_assert(is_same>::value, + "is_same>::value"); + + EXPECT_TRUE(sp_1.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_2.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_3.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_4.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_5.data() == reinterpret_cast(begin(sequence))); + EXPECT_TRUE(sp_6.data() == reinterpret_cast(begin(sequence))); + + EXPECT_TRUE(sp_1.size() == SizeBytes); + EXPECT_TRUE(sp_2.size() == SizeBytes); + EXPECT_TRUE(sp_3.size() == SizeBytes); + EXPECT_TRUE(sp_4.size() == SizeBytes); + EXPECT_TRUE(sp_5.size() == SizeBytes); + EXPECT_TRUE(sp_6.size() == SizeBytes); + } +} + +// assertions for span's definition +static_assert(std::is_same::value, + "gsl::dynamic_extent must be respresented as std::size_t"); +static_assert(gsl::dynamic_extent == static_cast(-1), + "gsl::dynamic_extent must be defined as the max value of std::size_t"); + +static_assert(std::is_same::extent), const std::size_t>::value, + "Ensure that the type of gsl::span::extent is std::size_t"); +static_assert(gsl::span::extent == gsl::dynamic_extent, + "gsl::span::extent should be equivalent to gsl::dynamic_extent"); + +static_assert(std::is_same::extent), const std::size_t>::value, + "Ensure that the type of gsl::span::extent is std::size_t"); +static_assert(gsl::span::extent == 3, "Ensure that span::extent is equal to 3"); + +static_assert(std::is_same::element_type, int>::value, + "span::element_type should be int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be std::size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be std::ptrdiff_t"); +static_assert(std::is_same::pointer, int*>::value, + "span::pointer should be int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, int&>::value, + "span::reference should be int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +static_assert(std::is_same::element_type, int>::value, + "span::element_type should be int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be std::size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be std::ptrdiff_t"); +static_assert(std::is_same::pointer, int*>::value, + "span::pointer should be int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, int&>::value, + "span::reference should be int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +static_assert(std::is_same::element_type, const int>::value, + "span::element_type should be const int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be ptrdiff_t"); +static_assert(std::is_same::pointer, const int*>::value, + "span::pointer should be const int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, const int&>::value, + "span::reference should be const int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +static_assert(std::is_same::element_type, const int>::value, + "span::element_type should be const int"); +static_assert(std::is_same::value_type, int>::value, + "span::value_type should be int"); +static_assert(std::is_same::size_type, std::size_t>::value, + "span::size_type should be size_t"); +static_assert(std::is_same::difference_type, ptrdiff_t>::value, + "span::difference_type should be ptrdiff_t"); +static_assert(std::is_same::pointer, const int*>::value, + "span::pointer should be const int*"); +static_assert(std::is_same::const_pointer, const int*>::value, + "span::const_pointer should be const int*"); +static_assert(std::is_same::reference, const int&>::value, + "span::reference should be const int&"); +static_assert(std::is_same::const_reference, const int&>::value, + "span::const_reference should be const int&"); + +// assertions for span_iterator +static_assert(std::is_same::iterator>::pointer, int*>::value, + "span::iterator's pointer should be int*"); +static_assert( + std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); + +static_assert(std::is_same::iterator>::pointer, int*>::value, + "span::iterator's pointer should be int*"); +static_assert( + std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); + +static_assert( + std::is_same::iterator>::pointer, const int*>::value, + "span::iterator's pointer should be int*"); +static_assert(std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); + +static_assert(std::is_same::iterator>::pointer, + const int*>::value, + "span::iterator's pointer should be int*"); +static_assert(std::is_same::reverse_iterator, + std::reverse_iterator::iterator>>::value, + "span::reverse_iterator should equal std::reverse_iterator::iterator>"); + +// copyability assertions +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); + +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); + +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); + +static_assert(std::is_trivially_copyable>::value, + "span should be trivially copyable"); +static_assert(std::is_trivially_copyable::iterator>::value, + "span::iterator should be trivially copyable"); + +// nothrow constructible assertions +static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, + "std::is_nothrow_constructible, int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, int*, std::uint16_t>::value, + "std::is_nothrow_constructible, int*, std::uint16_t>"); +static_assert(std::is_nothrow_constructible, int*, int*>::value, + "std::is_nothrow_constructible, int*, int*>"); +static_assert(std::is_nothrow_constructible, int (&)[3]>::value, + "std::is_nothrow_constructible, int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, + "std::is_nothrow_constructible, int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, int*, std::uint16_t>::value, + "std::is_nothrow_constructible, int*, std::uint16_t>"); +static_assert(std::is_nothrow_constructible, int*, int*>::value, + "std::is_nothrow_constructible, int*, int*>"); +static_assert(std::is_nothrow_constructible, int (&)[3]>::value, + "std::is_nothrow_constructible, int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, int*, std::size_t>::value, + "std::is_nothrow_constructible, int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, int*, int*>::value, + "std::is_nothrow_constructible, int*, int*>"); +static_assert(std::is_nothrow_constructible, int*, const int*>::value, + "std::is_nothrow_constructible, int*, const int*>"); +static_assert(std::is_nothrow_constructible, int (&)[3]>::value, + "std::is_nothrow_constructible, int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const int*, int*>::value, + "std::is_nothrow_constructible, const int*, int*>"); +static_assert(std::is_nothrow_constructible, const int*, const int*>::value, + "std::is_nothrow_constructible, const int*, const int*>"); +static_assert(std::is_nothrow_constructible, const int*, std::size_t>::value, + "std::is_nothrow_constructible, const int*, std::size_t>"); +static_assert(std::is_nothrow_constructible, const int (&)[3]>::value, + "std::is_nothrow_constructible, const int(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); +static_assert(std::is_nothrow_constructible, const std::array&>::value, + "std::is_nothrow_constructible, const std::array&>"); + +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); + +static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, + "std::is_nothrow_constructible, Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, + "std::is_nothrow_constructible, Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); + +static_assert(std::is_nothrow_constructible, Base (&)[3]>::value, + "std::is_nothrow_constructible, Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const Base (&)[3]>::value, + "std::is_nothrow_constructible, const Base(&)[3]>"); +static_assert(std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert(std::is_nothrow_constructible, std::array&>::value, + "std::is_nothrow_constructible, std::array&>"); +static_assert( + std::is_nothrow_constructible, const std::array&>::value, + "std::is_nothrow_constructible, const std::array&>"); + +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); +static_assert( + std::is_nothrow_constructible, const gsl::span&>::value, + "std::is_nothrow_constructible, const gsl::span&>"); + +// non-constructible assertions +static_assert(!std::is_constructible, const int*, int*>::value, + "!std::is_constructible, const int*, int*>"); +static_assert(!std::is_constructible, const int*, const int*>::value, + "!std::is_constructible, const int*, const int*>"); +static_assert(!std::is_constructible, const int*, double*>::value, + "!std::is_constructible, const int*, double*>"); +static_assert(!std::is_constructible, const int*, std::size_t>::value, + "!std::is_constructible, const int*, std::size_t>"); +static_assert(!std::is_constructible, const int (&)[3]>::value, + "!std::is_constructible, const int(&)[3]>"); +static_assert(!std::is_constructible, double*, int*>::value, + "!std::is_constructible, double*, int*>"); +static_assert(!std::is_constructible, double*, const int*>::value, + "!std::is_constructible, double*, const int*>"); +static_assert(!std::is_constructible, double*, double*>::value, + "!std::is_constructible, double*, double*>"); +static_assert(!std::is_constructible, double*, std::size_t>::value, + "!std::is_constructible, double*, std::size_t>"); +static_assert(!std::is_constructible, double (&)[3]>::value, + "!std::is_constructible, double(&)[3]>"); +static_assert(!std::is_constructible, int*, double*>::value, + "!std::is_constructible, int*, double*>"); +static_assert(!std::is_constructible, std::size_t, int*>::value, + "!std::is_constructible, std::size_t, int*>"); +static_assert(!std::is_constructible, std::size_t, std::size_t>::value, + "!std::is_constructible, std::size_t, std::size_t>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); + +static_assert(!std::is_constructible, int*, double*>::value, + "!std::is_constructible, int*, double*>"); +static_assert(!std::is_constructible, int (&)[500]>::value, + "!std::is_constructible, int(&)[500]>"); +static_assert(!std::is_constructible, const int*, int*>::value, + "!std::is_constructible, const int*, int*>"); +static_assert(!std::is_constructible, const int*, const int*>::value, + "!std::is_constructible, const int*, const int*>"); +static_assert(!std::is_constructible, const int*, std::size_t>::value, + "!std::is_constructible, const int*, std::size_t>"); +static_assert(!std::is_constructible, const int*, double*>::value, + "!std::is_constructible, const int*, double*>"); +static_assert(!std::is_constructible, const int (&)[3]>::value, + "!std::is_constructible, const int(&)[3]>"); +static_assert(!std::is_constructible, double*, std::size_t>::value, + "!std::is_constructible, double*, std::size_t>"); +static_assert(!std::is_constructible, double*, int*>::value, + "!std::is_constructible, double*, int*>"); +static_assert(!std::is_constructible, double*, const int*>::value, + "!std::is_constructible, double*, const int*>"); +static_assert(!std::is_constructible, double*, double*>::value, + "!std::is_constructible, double*, double*>"); +static_assert(!std::is_constructible, double (&)[3]>::value, + "!std::is_constructible, double(&)[3]>"); + +static_assert(!std::is_constructible, std::size_t, int*>::value, + "!std::is_constructible, std::size_t, int*>"); +static_assert(!std::is_constructible, std::size_t, std::size_t>::value, + "!std::is_constructible, std::size_t, std::size_t>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, double (&)[3]>::value, + "!std::is_constructible, double(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert( + !std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, Derived (&)[3]>::value, + "!std::is_constructible, Derived(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, std::vector&>::value, + "!std::is_constructible, std::vector&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, Derived (&)[3]>::value, + "!std::is_constructible, Derived(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); + +static_assert(!std::is_constructible, Derived (&)[3]>::value, + "!std::is_constructible, Derived(&)[3]>"); +static_assert(!std::is_constructible, const Derived (&)[3]>::value, + "!std::is_constructible, const Derived(&)[3]>"); +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert( + !std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); +static_assert( + !std::is_constructible, const gsl::span&>::value, + "!std::is_constructible, const gsl::span&>"); + +static_assert(!std::is_constructible, std::array&>::value, + "!std::is_constructible, std::array&>"); +static_assert(!std::is_constructible, const std::array&>::value, + "!std::is_constructible, const std::array&>"); + +// Explicit construction enabled in P1976R2 +static_assert(std::is_constructible, const gsl::span&>::value, + "std::is_constructible, const gsl::span&>"); +static_assert(std::is_constructible, const gsl::span&>::value, + "std::is_constructible, const gsl::span&>"); +static_assert(std::is_constructible, const gsl::span&>::value, + "std::is_constructible, const gsl::span&>"); + +// no throw copy constructor +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); +static_assert(std::is_nothrow_copy_constructible>::value, + "std::is_nothrow_copy_constructible>"); + +// no throw copy assignment +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); +static_assert(std::is_nothrow_copy_assignable>::value, + "std::is_nothrow_copy_assignable>"); + +// no throw destruction +static_assert(std::is_nothrow_destructible>::value, + "std::is_nothrow_destructible>"); +static_assert(std::is_nothrow_destructible>::value, + "std::is_nothrow_destructible>"); +static_assert(std::is_nothrow_destructible>::value, + "std::is_nothrow_destructible>"); + +// conversions +static_assert(std::is_convertible>::value, + "std::is_convertible>"); +static_assert(std::is_convertible>::value, + "std::is_convertible>"); +static_assert(std::is_convertible>::value, + "std::is_convertible>"); + +static_assert(std::is_convertible>::value, + "std::is_convertible>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +static_assert(std::is_convertible&, gsl::span>::value, + "std::is_convertible&, gsl::span>"); + +#if __cplusplus >= 201703l +template +static constexpr bool AsWritableBytesCompilesFor = false; + +template +static constexpr bool + AsWritableBytesCompilesFor()))>> = true; + +static_assert(AsWritableBytesCompilesFor>, + "AsWritableBytesCompilesFor>"); +static_assert(AsWritableBytesCompilesFor>, + "AsWritableBytesCompilesFor>"); +static_assert(!AsWritableBytesCompilesFor>, + "!AsWritableBytesCompilesFor>"); +static_assert(!AsWritableBytesCompilesFor>, + "!AsWritableBytesCompilesFor>"); +#endif // __cplusplus >= 201703l diff --git a/deps/GSL/tests/span_ext_tests.cpp b/deps/GSL/tests/span_ext_tests.cpp new file mode 100644 index 0000000..bc29007 --- /dev/null +++ b/deps/GSL/tests/span_ext_tests.cpp @@ -0,0 +1,380 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for span and span_ext +#include // for narrow_cast, at + +#include // for array +#include // for terminate +#include // for cerr +#include // for vector + +using namespace std; +using namespace gsl; + +#include "deathTestCommon.h" + +TEST(span_ext_test, make_span_from_pointer_length_constructor) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. from_pointer_length_constructor"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int arr[4] = {1, 2, 3, 4}; + + { + auto s = make_span(&arr[0], 2); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); + } + + { + int* p = nullptr; + auto s = make_span(p, narrow_cast::size_type>(0)); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + } + + { + int* p = nullptr; + auto workaround_macro = [=]() { make_span(p, 2); }; + EXPECT_DEATH(workaround_macro(), expected); + } +} + +TEST(span_ext_test, make_span_from_pointer_pointer_construction) +{ + int arr[4] = {1, 2, 3, 4}; + + { + auto s = make_span(&arr[0], &arr[2]); + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); + } + + { + auto s = make_span(&arr[0], &arr[0]); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); + } + + { + int* p = nullptr; + auto s = make_span(p, p); + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + } +} + +TEST(span_ext_test, make_span_from_array_constructor) +{ + int arr[5] = {1, 2, 3, 4, 5}; + int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; + int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + + { + const auto s = make_span(arr); + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == std::addressof(arr[0])); + } + + { + const auto s = make_span(std::addressof(arr2d[0]), 1); + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); + } + + { + const auto s = make_span(std::addressof(arr3d[0]), 1); + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr3d[0])); + } +} + +TEST(span_ext_test, make_span_from_dynamic_array_constructor) +{ + double(*arr)[3][4] = new double[100][3][4]; + + { + auto s = make_span(&arr[0][0][0], 10); + EXPECT_TRUE(s.size() == 10); + EXPECT_TRUE(s.data() == &arr[0][0][0]); + } + + delete[] arr; +} + +TEST(span_ext_test, make_span_from_std_array_constructor) +{ + std::array arr = {1, 2, 3, 4}; + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + + // This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590 + { + gsl::span s1 = make_span(arr); + + static gsl::span s2; + s2 = s1; + +#if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \ + __GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__) + // Known to be broken in gcc 6.4 and 6.5 with optimizations + // Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116 + EXPECT_TRUE(s1.size() == 4); + EXPECT_TRUE(s2.size() == 0); +#else + EXPECT_TRUE(s1.size() == s2.size()); +#endif + } +} + +TEST(span_ext_test, make_span_from_const_std_array_constructor) +{ + const std::array arr = {1, 2, 3, 4}; + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } +} + +TEST(span_ext_test, make_span_from_std_array_const_constructor) +{ + std::array arr = {1, 2, 3, 4}; + + { + auto s = make_span(arr); + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } +} + +TEST(span_ext_test, make_span_from_container_constructor) +{ + std::vector v = {1, 2, 3}; + const std::vector cv = v; + + { + auto s = make_span(v); + EXPECT_TRUE(s.size() == v.size()); + EXPECT_TRUE(s.data() == v.data()); + + auto cs = make_span(cv); + EXPECT_TRUE(cs.size() == cv.size()); + EXPECT_TRUE(cs.data() == cv.data()); + } +} + +TEST(span_test, interop_with_gsl_at) +{ + std::vector vec{1, 2, 3, 4, 5}; + gsl::span sp{vec}; + + std::vector cvec{1, 2, 3, 4, 5}; + gsl::span csp{cvec}; + + for (gsl::index i = 0; i < gsl::narrow_cast(vec.size()); ++i) + { + EXPECT_TRUE(&gsl::at(sp, i) == &vec[gsl::narrow_cast(i)]); + EXPECT_TRUE(&gsl::at(csp, i) == &cvec[gsl::narrow_cast(i)]); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. interop_with_gsl_at"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + EXPECT_DEATH(gsl::at(sp, -1), expected); + EXPECT_DEATH(gsl::at(sp, gsl::narrow_cast(sp.size())), expected); + EXPECT_DEATH(gsl::at(csp, -1), expected); + EXPECT_DEATH(gsl::at(csp, gsl::narrow_cast(sp.size())), expected); +} + +TEST(span_ext_test, iterator_free_functions) +{ + int a[] = {1, 2, 3, 4}; + gsl::span s{a}; + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE((std::is_same::value)); + EXPECT_TRUE((std::is_same::value)); + + EXPECT_TRUE(s.begin() == begin(s)); + EXPECT_TRUE(s.end() == end(s)); + + EXPECT_TRUE(s.rbegin() == rbegin(s)); + EXPECT_TRUE(s.rend() == rend(s)); + + EXPECT_TRUE(s.begin() == cbegin(s)); + EXPECT_TRUE(s.end() == cend(s)); + + EXPECT_TRUE(s.rbegin() == crbegin(s)); + EXPECT_TRUE(s.rend() == crend(s)); +} + +TEST(span_ext_test, ssize_free_function) +{ + int a[] = {1, 2, 3, 4}; + gsl::span s{a}; + + EXPECT_FALSE((std::is_same::value)); + EXPECT_TRUE(s.size() == static_cast(ssize(s))); +} + +#ifndef GSL_KERNEL_MODE +TEST(span_ext_test, comparison_operators) +{ + { + gsl::span s1; + gsl::span s2; + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 != s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {2, 1}; + gsl::span s1 = arr; + gsl::span s2 = arr; + + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {2, 1}; // bigger + + gsl::span s1; + gsl::span s2 = arr; + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; + int arr2[] = {1, 2}; + gsl::span s1 = arr1; + gsl::span s2 = arr2; + + EXPECT_TRUE(s1 == s2); + EXPECT_FALSE(s1 != s2); + EXPECT_FALSE(s1 < s2); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s1 >= s2); + EXPECT_TRUE(s2 == s1); + EXPECT_FALSE(s2 != s1); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s2 <= s1); + EXPECT_FALSE(s2 > s1); + EXPECT_TRUE(s2 >= s1); + } + + { + int arr[] = {1, 2, 3}; + + gsl::span s1 = {&arr[0], 2}; // shorter + gsl::span s2 = arr; // longer + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } + + { + int arr1[] = {1, 2}; // smaller + int arr2[] = {2, 1}; // bigger + + gsl::span s1 = arr1; + gsl::span s2 = arr2; + + EXPECT_TRUE(s1 != s2); + EXPECT_TRUE(s2 != s1); + EXPECT_FALSE(s1 == s2); + EXPECT_FALSE(s2 == s1); + EXPECT_TRUE(s1 < s2); + EXPECT_FALSE(s2 < s1); + EXPECT_TRUE(s1 <= s2); + EXPECT_FALSE(s2 <= s1); + EXPECT_TRUE(s2 > s1); + EXPECT_FALSE(s1 > s2); + EXPECT_TRUE(s2 >= s1); + EXPECT_FALSE(s1 >= s2); + } +} +#endif // GSL_KERNEL_MODE diff --git a/deps/GSL/tests/span_tests.cpp b/deps/GSL/tests/span_tests.cpp new file mode 100644 index 0000000..44ae205 --- /dev/null +++ b/deps/GSL/tests/span_tests.cpp @@ -0,0 +1,1383 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for byte +#include // for span, span_iterator, operator==, operator!= +#include // for narrow_cast, at + +#include // for array +#include // for ptrdiff_t +#include // for ptrdiff_t +#include // for reverse_iterator, operator-, operator== +#include // for unique_ptr, shared_ptr, make_unique, allo... +#include // for match_results, sub_match, match_results<>... +#include // for string +#include // for integral_constant<>::value, is_default_co... +#include +#include // for vector + +// the string_view include and macro are used in the deduction guide verification +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) +#ifdef __has_include +#if __has_include() +#include +#define HAS_STRING_VIEW +#endif // __has_include() +#endif // __has_include +#endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) +#if defined(__cplusplus) && __cplusplus >= 202002L +#include +#endif // __cplusplus >= 202002L + +#include "deathTestCommon.h" + +using namespace gsl; + +namespace +{ + +struct BaseClass +{ +}; +struct DerivedClass : BaseClass +{ +}; +struct AddressOverloaded +{ +#if (__cplusplus > 201402L) + [[maybe_unused]] +#endif + AddressOverloaded + operator&() const + { + return {}; + } +}; +} // namespace + +TEST(span_test, constructors) +{ + span s; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + + span cs; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); +} + +TEST(span_test, constructors_with_extent) +{ + span s; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + + span cs; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); +} + +TEST(span_test, constructors_with_bracket_init) +{ + span s{}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + + span cs{}; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); +} + +TEST(span_test, size_optimization) +{ + span s; + EXPECT_TRUE(sizeof(s) == sizeof(int*) + sizeof(ptrdiff_t)); + + span se; + EXPECT_TRUE(sizeof(se) == sizeof(int*)); +} + +TEST(span_test, from_nullptr_size_constructor) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. from_nullptr_size_constructor"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + span s{nullptr, narrow_cast::size_type>(0)}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + + span cs{nullptr, narrow_cast::size_type>(0)}; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); + } + { + auto workaround_macro = []() { + const span s{nullptr, narrow_cast::size_type>(0)}; + }; + EXPECT_DEATH(workaround_macro(), expected); + } + { + auto workaround_macro = []() { const span s{nullptr, 1}; }; + EXPECT_DEATH(workaround_macro(), expected); + + auto const_workaround_macro = []() { const span s{nullptr, 1}; }; + EXPECT_DEATH(const_workaround_macro(), expected); + } + { + auto workaround_macro = []() { const span s{nullptr, 1}; }; + EXPECT_DEATH(workaround_macro(), expected); + + auto const_workaround_macro = []() { const span s{nullptr, 1}; }; + EXPECT_DEATH(const_workaround_macro(), expected); + } + { + span s{nullptr, narrow_cast::size_type>(0)}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + + span cs{nullptr, narrow_cast::size_type>(0)}; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == nullptr); + } +} + +TEST(span_test, from_pointer_length_constructor) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. from_pointer_length_constructor"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int arr[4] = {1, 2, 3, 4}; + + { + for (int i = 0; i < 4; ++i) + { + { + span s = {&arr[0], narrow_cast(i)}; + EXPECT_TRUE(s.size() == narrow_cast(i)); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s.empty() == (i == 0)); + for (int j = 0; j < i; ++j) EXPECT_TRUE(arr[j] == s[narrow_cast(j)]); + } + { + span s = {&arr[i], 4 - narrow_cast(i)}; + EXPECT_TRUE(s.size() == 4 - narrow_cast(i)); + EXPECT_TRUE(s.data() == &arr[i]); + EXPECT_TRUE(s.empty() == ((4 - i) == 0)); + + for (int j = 0; j < 4 - i; ++j) + EXPECT_TRUE(arr[j + i] == s[narrow_cast(j)]); + } + } + } + + { + span s{&arr[0], 2}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); + } + + { + int* p = nullptr; + span s{p, narrow_cast::size_type>(0)}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + } + + { + int* p = nullptr; + auto workaround_macro = [=]() { const span s{p, 2}; }; + EXPECT_DEATH(workaround_macro(), expected); + } +} + +TEST(span_test, from_pointer_pointer_construction) +{ + int arr[4] = {1, 2, 3, 4}; + + { + span s{&arr[0], &arr[2]}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); + } + { + span s{&arr[0], &arr[2]}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[1] == 2); + } + + { + span s{&arr[0], &arr[0]}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); + } + + { + span s{&arr[0], &arr[0]}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); + } + + // this will fail the std::distance() precondition, which asserts on MSVC debug builds + //{ + // auto workaround_macro = [&]() { span s{&arr[1], &arr[0]}; }; + // EXPECT_DEATH(workaround_macro(), expected); + //} + + // this will fail the std::distance() precondition, which asserts on MSVC debug builds + //{ + // int* p = nullptr; + // auto workaround_macro = [&]() { span s{&arr[0], p}; }; + // EXPECT_DEATH(workaround_macro(), expected); + //} + + { + int* p = nullptr; + span s{p, p}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + } + + { + int* p = nullptr; + span s{p, p}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == nullptr); + } + + // this will fail the std::distance() precondition, which asserts on MSVC debug builds + //{ + // int* p = nullptr; + // auto workaround_macro = [&]() { span s{&arr[0], p}; }; + // EXPECT_DEATH(workaround_macro(), expected); + //} +} + +TEST(span_test, from_array_constructor) +{ + int arr[5] = {1, 2, 3, 4, 5}; + + { + const span s{arr}; + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == &arr[0]); + } + + { + const span s{arr}; + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == &arr[0]); + } + + int arr2d[2][3] = {1, 2, 3, 4, 5, 6}; + +#ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr[0]); + } + + { + span s{arr2d}; + EXPECT_TRUE(s.size() == 6); + EXPECT_TRUE(s.data() == &arr2d[0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[5] == 6); + } + + { + span s{arr2d}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr2d[0][0]); + } + + { + span s{arr2d}; + } +#endif + { + const span s{std::addressof(arr2d[0]), 1}; + EXPECT_TRUE(s.size() == 1); + EXPECT_TRUE(s.data() == std::addressof(arr2d[0])); + } + + int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + +#ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr3d}; + EXPECT_TRUE(s.size() == 12); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[11] == 12); + } + + { + span s{arr3d}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + } + + { + span s{arr3d}; + } + + { + span s{arr3d}; + EXPECT_TRUE(s.size() == 12); + EXPECT_TRUE(s.data() == &arr3d[0][0][0]); + EXPECT_TRUE(s[0] == 1); + EXPECT_TRUE(s[5] == 6); + } +#endif + { + const span s{std::addressof(arr3d[0]), 1}; + EXPECT_TRUE(s.size() == 1); + } + + AddressOverloaded ao_arr[5] = {}; + + { + const span s{ao_arr}; + EXPECT_TRUE(s.size() == 5); + EXPECT_TRUE(s.data() == std::addressof(ao_arr[0])); + } +} + +TEST(span_test, from_dynamic_array_constructor) +{ + double(*arr)[3][4] = new double[100][3][4]; + + { + span s(&arr[0][0][0], 10); + EXPECT_TRUE(s.size() == 10); + EXPECT_TRUE(s.data() == &arr[0][0][0]); + } + + delete[] arr; +} + +TEST(span_test, from_std_array_constructor) +{ + std::array arr = {1, 2, 3, 4}; + + { + span s{arr}; + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == arr.size()); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == arr.size()); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + std::array empty_arr{}; + span s{empty_arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.empty()); + } + + std::array ao_arr{}; + + { + span fs{ao_arr}; + EXPECT_TRUE(fs.size() == ao_arr.size()); + EXPECT_TRUE(ao_arr.data() == fs.data()); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == 2); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); + + span cs{arr}; + EXPECT_TRUE(cs.size() == 0); + EXPECT_TRUE(cs.data() == arr.data()); + } + + { + span s{arr}; + } + + { + auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; + auto take_a_span = [](span s) { static_cast(s); }; + // try to take a temporary std::array + take_a_span(get_an_array()); + } +#endif + + { + auto get_an_array = []() -> std::array { return {1, 2, 3, 4}; }; + auto take_a_span = [](span s) { static_cast(s); }; + // try to take a temporary std::array + take_a_span(get_an_array()); + } +} + +TEST(span_test, from_const_std_array_constructor) +{ + const std::array arr = {1, 2, 3, 4}; + + { + span s{arr}; + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + + const std::array ao_arr{}; + + { + span s{ao_arr}; + EXPECT_TRUE(s.size() == ao_arr.size()); + EXPECT_TRUE(s.data() == ao_arr.data()); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + } +#endif + + { + auto get_an_array = []() -> const std::array { return {1, 2, 3, 4}; }; + auto take_a_span = [](span s) { static_cast(s); }; + // try to take a temporary std::array + take_a_span(get_an_array()); + } +} + +TEST(span_test, from_std_array_const_constructor) +{ + std::array arr = {1, 2, 3, 4}; + + { + span s{arr}; + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == arr.size()); + EXPECT_TRUE(s.data() == arr.data()); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + span s{arr}; + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + EXPECT_TRUE(s.size() == 0); + EXPECT_TRUE(s.data() == arr.data()); + } + + { + span s{arr}; + } + + { + span s{arr}; + } +#endif +} + +TEST(span_test, from_container_constructor) +{ + std::vector v = {1, 2, 3}; + const std::vector cv = v; + + { + span s{v}; + EXPECT_TRUE(s.size() == v.size()); + EXPECT_TRUE(s.data() == v.data()); + + span cs{v}; + EXPECT_TRUE(cs.size() == v.size()); + EXPECT_TRUE(cs.data() == v.data()); + } + + std::string str = "hello"; + const std::string cstr = "hello"; + + { +#ifdef CONFIRM_COMPILATION_ERRORS + span s{str}; + EXPECT_TRUE(s.size() == str.size()); + EXPECT_TRUE(s.data() == str.data())); +#endif + span cs{str}; + EXPECT_TRUE(cs.size() == str.size()); + EXPECT_TRUE(cs.data() == str.data()); + } + + { +#ifdef CONFIRM_COMPILATION_ERRORS + span s{cstr}; +#endif + span cs{cstr}; + EXPECT_TRUE(cs.size() == cstr.size()); + EXPECT_TRUE(cs.data() == cstr.data()); + } + + { +#ifdef CONFIRM_COMPILATION_ERRORS + auto get_temp_vector = []() -> std::vector { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_vector()); +#endif + } + + { + auto get_temp_vector = []() -> std::vector { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_vector()); + } + + { +#ifdef CONFIRM_COMPILATION_ERRORS + auto get_temp_string = []() -> std::string { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_string()); +#endif + } + + { + auto get_temp_string = []() -> std::string { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_string()); + } + + { +#ifdef CONFIRM_COMPILATION_ERRORS + auto get_temp_vector = []() -> const std::vector { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_vector()); +#endif + } + + { + auto get_temp_string = []() -> const std::string { return {}; }; + auto use_span = [](span s) { static_cast(s); }; + use_span(get_temp_string()); + } + + { +#ifdef CONFIRM_COMPILATION_ERRORS + std::map m; + span s{m}; +#endif + } +} + +TEST(span_test, from_convertible_span_constructor) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. from_convertible_span_constructor"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + span avd; + span avcd = avd; + static_cast(avcd); + } + + { + std::array arr{}; + span avd{arr}; + span avcd = avd; + static_cast(avcd); + } + + { + std::array arr{}; + span avd{arr}; + span avcd = avd; + static_cast(avcd); + } + + { + std::array arr{}; + span avd{arr}; + span avcd{avd}; + static_cast(avcd); + } + + { + std::array arr{}; + span avd{arr}; + using T = span; + EXPECT_DEATH(T{avd}, expected); + } + + { + std::array arr{}; + span avd{arr}; + using T = span; + EXPECT_DEATH(T{avd}, expected); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + std::array arr{}; + span avd{arr}; + span avcd = avd; + static_cast(avcd); + } + + { + std::array arr{}; + span avd{arr}; + span avcd = avd; + static_cast(avcd); + } + + { + std::array arr{}; + span avd{arr}; + span avcd = avd; + static_cast(avcd); + } + + { + span avd; + span avb = avd; + static_cast(avb); + } + + { + span s; + span s2 = s; + static_cast(s2); + } + + { + span s; + span s2 = s; + static_cast(s2); + } + + { + span s; + span s2 = s; + static_cast(s2); + } +#endif +} + +TEST(span_test, copy_move_and_assignment) +{ + span s1; + EXPECT_TRUE(s1.empty()); + + int arr[] = {3, 4, 5}; + + span s2 = arr; + EXPECT_TRUE(s2.size() == 3); + EXPECT_TRUE(s2.data() == &arr[0]); + + s2 = s1; + EXPECT_TRUE(s2.empty()); + + auto get_temp_span = [&]() -> span { return {&arr[1], 2}; }; + auto use_span = [&](span s) { + EXPECT_TRUE(s.size() == 2); + EXPECT_TRUE(s.data() == &arr[1]); + }; + use_span(get_temp_span()); + + s1 = get_temp_span(); + EXPECT_TRUE(s1.size() == 2); + EXPECT_TRUE(s1.data() == &arr[1]); +} + +TEST(span_test, first) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. first"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_TRUE(av.first<2>().size() == 2); + EXPECT_TRUE(av.first(2).size() == 2); + } + + { + span av = arr; + EXPECT_TRUE(av.first<0>().size() == 0); + EXPECT_TRUE(av.first(0).size() == 0); + } + + { + span av = arr; + EXPECT_TRUE(av.first<5>().size() == 5); + EXPECT_TRUE(av.first(5).size() == 5); + } + + { + span av = arr; +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(av.first<6>().size() == 6); + EXPECT_TRUE(av.first<-1>().size() == -1); +#endif + EXPECT_DEATH(av.first(6).size(), expected); + } + + { + span av; + EXPECT_TRUE(av.first<0>().size() == 0); + EXPECT_TRUE(av.first(0).size() == 0); + } +} + +TEST(span_test, last) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. last"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_TRUE(av.last<2>().size() == 2); + EXPECT_TRUE(av.last(2).size() == 2); + } + + { + span av = arr; + EXPECT_TRUE(av.last<0>().size() == 0); + EXPECT_TRUE(av.last(0).size() == 0); + } + + { + span av = arr; + EXPECT_TRUE(av.last<5>().size() == 5); + EXPECT_TRUE(av.last(5).size() == 5); + } + + { + span av = arr; +#ifdef CONFIRM_COMPILATION_ERRORS + EXPECT_TRUE(av.last<6>().size() == 6); +#endif + EXPECT_DEATH(av.last(6).size(), expected); + } + + { + span av; + EXPECT_TRUE(av.last<0>().size() == 0); + EXPECT_TRUE(av.last(0).size() == 0); + } +} + +TEST(span_test, subspan) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. subspan"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int arr[5] = {1, 2, 3, 4, 5}; + + { + span av = arr; + EXPECT_TRUE((av.subspan<2, 2>().size()) == 2); + EXPECT_TRUE(decltype(av.subspan<2, 2>())::extent == 2); + EXPECT_TRUE(av.subspan(2, 2).size() == 2); + EXPECT_TRUE(av.subspan(2, 3).size() == 3); + } + + { + span av = arr; + EXPECT_TRUE((av.subspan<0, 0>().size()) == 0); + EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0); + EXPECT_TRUE(av.subspan(0, 0).size() == 0); + } + + { + span av = arr; + EXPECT_TRUE((av.subspan<0, 5>().size()) == 5); + EXPECT_TRUE(decltype(av.subspan<0, 5>())::extent == 5); + EXPECT_TRUE(av.subspan(0, 5).size() == 5); + + EXPECT_DEATH(av.subspan(0, 6).size(), expected); + EXPECT_DEATH(av.subspan(1, 5).size(), expected); + } + + { + span av = arr; + EXPECT_TRUE((av.subspan<4, 0>().size()) == 0); + EXPECT_TRUE(decltype(av.subspan<4, 0>())::extent == 0); + EXPECT_TRUE(av.subspan(4, 0).size() == 0); + EXPECT_TRUE(av.subspan(5, 0).size() == 0); + EXPECT_DEATH(av.subspan(6, 0).size(), expected); + } + + { + span av = arr; + EXPECT_TRUE(av.subspan<1>().size() == 4); + EXPECT_TRUE(decltype(av.subspan<1>())::extent == 4); + } + + { + span av; + EXPECT_TRUE((av.subspan<0, 0>().size()) == 0); + EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0); + EXPECT_TRUE(av.subspan(0, 0).size() == 0); + EXPECT_DEATH((av.subspan<1, 0>().size()), expected); + } + + { + span av; + EXPECT_TRUE(av.subspan(0).size() == 0); + EXPECT_DEATH(av.subspan(1).size(), expected); + } + + { + span av = arr; + EXPECT_TRUE(av.subspan(0).size() == 5); + EXPECT_TRUE(av.subspan(1).size() == 4); + EXPECT_TRUE(av.subspan(4).size() == 1); + EXPECT_TRUE(av.subspan(5).size() == 0); + EXPECT_DEATH(av.subspan(6).size(), expected); + const auto av2 = av.subspan(1); + for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast(i) + 2); + } + + { + span av = arr; + EXPECT_TRUE(av.subspan(0).size() == 5); + EXPECT_TRUE(av.subspan(1).size() == 4); + EXPECT_TRUE(av.subspan(4).size() == 1); + EXPECT_TRUE(av.subspan(5).size() == 0); + EXPECT_DEATH(av.subspan(6).size(), expected); + const auto av2 = av.subspan(1); + for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast(i) + 2); + } +} + +TEST(span_test, iterator_default_init) +{ + span::iterator it1; + span::iterator it2; + EXPECT_TRUE(it1 == it2); +} + +TEST(span_test, iterator_comparisons) +{ + int a[] = {1, 2, 3, 4}; + { + span s = a; + span::iterator it = s.begin(); + auto it2 = it + 1; + + EXPECT_TRUE(it == it); + EXPECT_TRUE(it == s.begin()); + EXPECT_TRUE(s.begin() == it); + + EXPECT_TRUE(it != it2); + EXPECT_TRUE(it2 != it); + EXPECT_TRUE(it != s.end()); + EXPECT_TRUE(it2 != s.end()); + EXPECT_TRUE(s.end() != it); + + EXPECT_TRUE(it < it2); + EXPECT_TRUE(it <= it2); + EXPECT_TRUE(it2 <= s.end()); + EXPECT_TRUE(it < s.end()); + + EXPECT_TRUE(it2 > it); + EXPECT_TRUE(it2 >= it); + EXPECT_TRUE(s.end() > it2); + EXPECT_TRUE(s.end() >= it2); + } +} + +TEST(span_test, incomparable_iterators) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. incomparable_iterators"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int a[] = {1, 2, 3, 4}; + int b[] = {1, 2, 3, 4}; + { + span s = a; + span s2 = b; +#if (__cplusplus > 201402L) + EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() == s2.begin()), expected); + EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() <= s2.begin()), expected); +#else + EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), expected); + EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), expected); +#endif + } +} + +TEST(span_test, begin_end) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. begin_end"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + int a[] = {1, 2, 3, 4}; + span s = a; + + span::iterator it = s.begin(); + span::iterator it2 = std::begin(s); + EXPECT_TRUE(it == it2); + + it = s.end(); + it2 = std::end(s); + EXPECT_TRUE(it == it2); + } + + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.begin(); + auto first = it; + EXPECT_TRUE(it == first); + EXPECT_TRUE(*it == 1); + + auto beyond = s.end(); + EXPECT_TRUE(it != beyond); + EXPECT_DEATH(*beyond, expected); + + EXPECT_TRUE(beyond - first == 4); + EXPECT_TRUE(first - first == 0); + EXPECT_TRUE(beyond - beyond == 0); + + ++it; + EXPECT_TRUE(it - first == 1); + EXPECT_TRUE(*it == 2); + *it = 22; + EXPECT_TRUE(*it == 22); + EXPECT_TRUE(beyond - it == 3); + + it = first; + EXPECT_TRUE(it == first); + while (it != s.end()) + { + *it = 5; + ++it; + } + + EXPECT_TRUE(it == beyond); + EXPECT_TRUE(it - beyond == 0); + + for (const auto& n : s) { EXPECT_TRUE(n == 5); } + } +} + +TEST(span_test, rbegin_rend) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. rbegin_rend"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + int a[] = {1, 2, 3, 4}; + span s = a; + + auto it = s.rbegin(); + auto first = it; + EXPECT_TRUE(it == first); + EXPECT_TRUE(*it == 4); + + auto beyond = s.rend(); + EXPECT_TRUE(it != beyond); +#if (__cplusplus > 201402L) + EXPECT_DEATH([[maybe_unused]] auto _ = *beyond, expected); +#else + EXPECT_DEATH(auto _ = *beyond, expected); +#endif + + EXPECT_TRUE(beyond - first == 4); + EXPECT_TRUE(first - first == 0); + EXPECT_TRUE(beyond - beyond == 0); + + ++it; + EXPECT_TRUE(it - s.rbegin() == 1); + EXPECT_TRUE(*it == 3); + *it = 22; + EXPECT_TRUE(*it == 22); + EXPECT_TRUE(beyond - it == 3); + + it = first; + EXPECT_TRUE(it == first); + while (it != s.rend()) + { + *it = 5; + ++it; + } + + EXPECT_TRUE(it == beyond); + EXPECT_TRUE(it - beyond == 0); + + for (const auto& n : s) { EXPECT_TRUE(n == 5); } + } +} + +TEST(span_test, as_bytes) +{ + int a[] = {1, 2, 3, 4}; + { + const span s = a; + EXPECT_TRUE(s.size() == 4); + const span bs = as_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); + } + + { + span s; + const auto bs = as_bytes(s); + EXPECT_TRUE(bs.size() == s.size()); + EXPECT_TRUE(bs.size() == 0); + EXPECT_TRUE(bs.size_bytes() == 0); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.data() == nullptr); + } + + { + span s = a; + const auto bs = as_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); + } +} + +TEST(span_test, as_writable_bytes) +{ + int a[] = {1, 2, 3, 4}; + + { +#ifdef CONFIRM_COMPILATION_ERRORS + // you should not be able to get writeable bytes for const objects + span s = a; + EXPECT_TRUE(s.size() == 4); + span bs = as_writable_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); +#endif + } + + { + span s; + const auto bs = as_writable_bytes(s); + EXPECT_TRUE(bs.size() == s.size()); + EXPECT_TRUE(bs.size() == 0); + EXPECT_TRUE(bs.size_bytes() == 0); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.data() == nullptr); + } + + { + span s = a; + const auto bs = as_writable_bytes(s); + EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); + EXPECT_TRUE(bs.size() == s.size_bytes()); + } +} + +TEST(span_test, fixed_size_conversions) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. fixed_size_conversions"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + int arr[] = {1, 2, 3, 4}; + + // converting to an span from an equal size array is ok + span s4 = arr; + EXPECT_TRUE(s4.size() == 4); + + // converting to dynamic_range is always ok + { + span s = s4; + EXPECT_TRUE(s.size() == s4.size()); + static_cast(s); + } + +// initialization or assignment to static span that REDUCES size is NOT ok +#ifdef CONFIRM_COMPILATION_ERRORS + { + span s = arr; + } + { + span s2 = s4; + static_cast(s2); + } +#endif + + // even when done dynamically + { + /* + // this now results in a compile-time error, rather than runtime. + // There is no suitable conversion from dynamic span to fixed span. + span s = arr; + auto f = [&]() { + const span s2 = s; + static_cast(s2); + }; + EXPECT_DEATH(f(), expected); + */ + } + + // but doing so explicitly is ok + + // you can convert statically + { + const span s2{&arr[0], 2}; + static_cast(s2); + } + { + const span s1 = s4.first<1>(); + static_cast(s1); + } + + /* + // this is not a legal operation in std::span, so we are no longer supporting it + // conversion from span to span via call to `first` + // then convert from span to span + // The dynamic to fixed extents are not supported in the standard + // to make this work, span would need to be span. + { + + // NB: implicit conversion to span from span + span s1 = s4.first(1); + static_cast(s1); + } + */ + + // initialization or assignment to static span that requires size INCREASE is not ok. + int arr2[2] = {1, 2}; + +#ifdef CONFIRM_COMPILATION_ERRORS + { + span s3 = arr2; + } + { + span s2 = arr2; + span s4a = s2; + } +#endif + { + auto f = [&]() { + const span _s4{arr2, 2}; + static_cast(_s4); + }; + EXPECT_DEATH(f(), expected); + } + + /* + // This no longer compiles. There is no suitable conversion from dynamic span to a fixed size + span. + // this should fail - we are trying to assign a small dynamic span to a fixed_size larger one + span av = arr2; auto f = [&]() { + const span _s4 = av; + static_cast(_s4); + }; + EXPECT_DEATH(f(), expected); + */ +} + +TEST(span_test, interop_with_std_regex) +{ + char lat[] = {'1', '2', '3', '4', '5', '6', 'E', 'F', 'G'}; + span s = lat; + const auto f_it = s.begin() + 7; + + std::match_results::iterator> match; + + std::regex_match(s.begin(), s.end(), match, std::regex(".*")); + EXPECT_TRUE(match.ready()); + EXPECT_FALSE(match.empty()); + EXPECT_TRUE(match[0].matched); + EXPECT_TRUE(match[0].first == s.begin()); + EXPECT_TRUE(match[0].second == s.end()); + + std::regex_search(s.begin(), s.end(), match, std::regex("F")); + EXPECT_TRUE(match.ready()); + EXPECT_FALSE(match.empty()); + EXPECT_TRUE(match[0].matched); + EXPECT_TRUE(match[0].first == f_it); + EXPECT_TRUE(match[0].second == (f_it + 1)); +} + +TEST(span_test, default_constructible) +{ + EXPECT_TRUE((std::is_default_constructible>::value)); + EXPECT_TRUE((std::is_default_constructible>::value)); + EXPECT_FALSE((std::is_default_constructible>::value)); +} + +TEST(span_test, std_container_ctad) +{ +#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) + // this test is just to verify that these compile + { + std::vector v{1, 2, 3, 4}; + gsl::span sp{v}; + static_assert(std::is_same>::value); + } + { + std::string str{"foo"}; + gsl::span sp{str}; + static_assert(std::is_same>::value); + } +#ifdef HAS_STRING_VIEW + { + std::string_view sv{"foo"}; + gsl::span sp{sv}; + static_assert(std::is_same>::value); + } +#endif +#endif +} + +TEST(span_test, front_back) +{ + int arr[5] = {1, 2, 3, 4, 5}; + span s{arr}; + EXPECT_TRUE(s.front() == 1); + EXPECT_TRUE(s.back() == 5); + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. front_back"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + span s2; + EXPECT_DEATH(s2.front(), expected); + EXPECT_DEATH(s2.back(), expected); +} + +#if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L +TEST(span_test, std_span) +{ + // make sure std::span can be constructed from gsl::span + int arr[5] = {1, 2, 3, 4, 5}; + gsl::span gsl_span{arr}; +#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts)) + EXPECT_TRUE(std::to_address(gsl_span.begin()) == gsl_span.data()); + EXPECT_TRUE(std::to_address(gsl_span.end()) == gsl_span.data() + gsl_span.size()); +#endif // __cpp_lib_ranges + + std::span std_span = gsl_span; + EXPECT_TRUE(std_span.data() == gsl_span.data()); + EXPECT_TRUE(std_span.size() == gsl_span.size()); +} +#endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L + +#if defined(__cpp_lib_span) && defined(__cpp_lib_ranges) +// This test covers the changes in PR #1100 +TEST(span_test, msvc_compile_error_PR1100) +{ + int arr[]{1, 7, 2, 9}; + gsl::span sp{arr, std::size(arr)}; + std::ranges::sort(sp); + for (const auto& e : sp) { + (void)e; + } +} +#endif // defined(__cpp_lib_span) && defined(__cpp_lib_ranges) diff --git a/deps/GSL/tests/strict_notnull_tests.cpp b/deps/GSL/tests/strict_notnull_tests.cpp new file mode 100644 index 0000000..c1b1f54 --- /dev/null +++ b/deps/GSL/tests/strict_notnull_tests.cpp @@ -0,0 +1,304 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include // for not_null, operator<, operator<=, operator> +#include + +#include "deathTestCommon.h" + +using namespace gsl; + +namespace +{ +// clang-format off +GSL_SUPPRESS(f.4) // NO-FORMAT: attribute +// clang-format on +bool helper(not_null p) { return *p == 12; } + +// clang-format off +GSL_SUPPRESS(f.4) // NO-FORMAT: attribute +// clang-format on +bool helper_const(not_null p) { return *p == 12; } + +// clang-format off +GSL_SUPPRESS(f.4) // NO-FORMAT: attribute +// clang-format on +bool strict_helper(strict_not_null p) { return *p == 12; } + +// clang-format off +GSL_SUPPRESS(f.4) // NO-FORMAT: attribute +// clang-format on +bool strict_helper_const(strict_not_null p) { return *p == 12; } + +#ifdef CONFIRM_COMPILATION_ERRORS +int* return_pointer() { return nullptr; } +const int* return_pointer_const() { return nullptr; } +#endif +} // namespace + +TEST(strict_notnull_tests, TestStrictNotNull) +{ + { + // raw ptr <-> strict_not_null + int x = 42; + +#ifdef CONFIRM_COMPILATION_ERRORS + strict_not_null snn = &x; + strict_helper(&x); + strict_helper_const(&x); + strict_helper(return_pointer()); + strict_helper_const(return_pointer_const()); +#endif + + const strict_not_null snn1{&x}; + + helper(snn1); + helper_const(snn1); + + EXPECT_TRUE(*snn1 == 42); + } + + { + // raw ptr <-> strict_not_null + const int x = 42; + +#ifdef CONFIRM_COMPILATION_ERRORS + strict_not_null snn = &x; + strict_helper(&x); + strict_helper_const(&x); + strict_helper(return_pointer()); + strict_helper_const(return_pointer_const()); +#endif + + const strict_not_null snn1{&x}; + +#ifdef CONFIRM_COMPILATION_ERRORS + helper(snn1); +#endif + helper_const(snn1); + + EXPECT_TRUE(*snn1 == 42); + } + + { + // strict_not_null -> strict_not_null + int x = 42; + + strict_not_null snn1{&x}; + const strict_not_null snn2{&x}; + + strict_helper(snn1); + strict_helper_const(snn1); + strict_helper_const(snn2); + + EXPECT_TRUE(snn1 == snn2); + } + + { + // strict_not_null -> strict_not_null + const int x = 42; + + strict_not_null snn1{&x}; + const strict_not_null snn2{&x}; + +#ifdef CONFIRM_COMPILATION_ERRORS + strict_helper(snn1); +#endif + strict_helper_const(snn1); + strict_helper_const(snn2); + + EXPECT_TRUE(snn1 == snn2); + } + + { + // strict_not_null -> not_null + int x = 42; + + strict_not_null snn{&x}; + + const not_null nn1 = snn; + const not_null nn2{snn}; + + helper(snn); + helper_const(snn); + + EXPECT_TRUE(snn == nn1); + EXPECT_TRUE(snn == nn2); + } + + { + // strict_not_null -> not_null + const int x = 42; + + strict_not_null snn{&x}; + + const not_null nn1 = snn; + const not_null nn2{snn}; + +#ifdef CONFIRM_COMPILATION_ERRORS + helper(snn); +#endif + helper_const(snn); + + EXPECT_TRUE(snn == nn1); + EXPECT_TRUE(snn == nn2); + } + + { + // not_null -> strict_not_null + int x = 42; + + not_null nn{&x}; + + const strict_not_null snn1{nn}; + const strict_not_null snn2{nn}; + + strict_helper(nn); + strict_helper_const(nn); + + EXPECT_TRUE(snn1 == nn); + EXPECT_TRUE(snn2 == nn); + + std::hash> hash_snn; + std::hash> hash_nn; + + EXPECT_TRUE(hash_nn(snn1) == hash_nn(nn)); + EXPECT_TRUE(hash_snn(snn1) == hash_nn(nn)); + EXPECT_TRUE(hash_nn(snn1) == hash_nn(snn2)); + EXPECT_TRUE(hash_snn(snn1) == hash_snn(nn)); + } + + { + // not_null -> strict_not_null + const int x = 42; + + not_null nn{&x}; + + const strict_not_null snn1{nn}; + const strict_not_null snn2{nn}; + +#ifdef CONFIRM_COMPILATION_ERRORS + strict_helper(nn); +#endif + strict_helper_const(nn); + + EXPECT_TRUE(snn1 == nn); + EXPECT_TRUE(snn2 == nn); + + std::hash> hash_snn; + std::hash> hash_nn; + + EXPECT_TRUE(hash_nn(snn1) == hash_nn(nn)); + EXPECT_TRUE(hash_snn(snn1) == hash_nn(nn)); + EXPECT_TRUE(hash_nn(snn1) == hash_nn(snn2)); + EXPECT_TRUE(hash_snn(snn1) == hash_snn(nn)); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + strict_not_null p{nullptr}; + } +#endif +} + +#if defined(__cplusplus) && (__cplusplus >= 201703L) + +TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction) +{ + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. TestStrictNotNullConstructorTypeDeduction"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + { + int i = 42; + + strict_not_null x{&i}; + helper(strict_not_null{&i}); + helper_const(strict_not_null{&i}); + + EXPECT_TRUE(*x == 42); + } + + { + const int i = 42; + + strict_not_null x{&i}; +#ifdef CONFIRM_COMPILATION_ERRORS + helper(strict_not_null{&i}); +#endif + helper_const(strict_not_null{&i}); + + EXPECT_TRUE(*x == 42); + } + + { + int i = 42; + int* p = &i; + + strict_not_null x{p}; + helper(strict_not_null{p}); + helper_const(strict_not_null{p}); + + EXPECT_TRUE(*x == 42); + } + + { + const int i = 42; + const int* p = &i; + + strict_not_null x{p}; +#ifdef CONFIRM_COMPILATION_ERRORS + helper(strict_not_null{p}); +#endif + helper_const(strict_not_null{p}); + + EXPECT_TRUE(*x == 42); + } + + { + auto workaround_macro = []() { + int* p1 = nullptr; + const strict_not_null x{p1}; + }; + EXPECT_DEATH(workaround_macro(), expected); + } + + { + auto workaround_macro = []() { + const int* p1 = nullptr; + const strict_not_null x{p1}; + }; + EXPECT_DEATH(workaround_macro(), expected); + } + + { + int* p = nullptr; + + EXPECT_DEATH(helper(strict_not_null{p}), expected); + EXPECT_DEATH(helper_const(strict_not_null{p}), expected); + } + +#ifdef CONFIRM_COMPILATION_ERRORS + { + strict_not_null x{nullptr}; + helper(strict_not_null{nullptr}); + helper_const(strict_not_null{nullptr}); + } +#endif +} +#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L) diff --git a/deps/GSL/tests/utils_tests.cpp b/deps/GSL/tests/utils_tests.cpp new file mode 100644 index 0000000..5b64e20 --- /dev/null +++ b/deps/GSL/tests/utils_tests.cpp @@ -0,0 +1,165 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2015 Microsoft Corporation. All rights reserved. +// +// This code is licensed under the MIT License (MIT). +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +/////////////////////////////////////////////////////////////////////////////// + +#include + +#include // for move +#include +#include // for std::ptrdiff_t +#include // for uint32_t, int32_t +#include // for reference_wrapper, _Bind_helper<>::type +#include // for narrow, narrowing_error +#include // finally, narrow_cast +#include // for numeric_limits +#include // for is_same + +using namespace gsl; + +namespace +{ +void f(int& i) { i += 1; } +static int j = 0; +void g() { j += 1; } +} // namespace + +TEST(utils_tests, sanity_check_for_gsl_index_typedef) +{ + static_assert(std::is_same::value, + "gsl::index represents wrong arithmetic type"); +} + +TEST(utils_tests, finally_lambda) +{ + int i = 0; + { + auto _ = finally([&]() { f(i); }); + EXPECT_TRUE(i == 0); + } + EXPECT_TRUE(i == 1); +} + +TEST(utils_tests, finally_lambda_move) +{ + int i = 0; + { + auto _1 = finally([&]() { f(i); }); + { + auto _2 = std::move(_1); + EXPECT_TRUE(i == 0); + } + EXPECT_TRUE(i == 1); + { + auto _2 = std::move(_1); + EXPECT_TRUE(i == 1); + } + EXPECT_TRUE(i == 1); + } + EXPECT_TRUE(i == 1); +} + +TEST(utils_tests, finally_const_lvalue_lambda) +{ + int i = 0; + { + const auto const_lvalue_lambda = [&]() { f(i); }; + auto _ = finally(const_lvalue_lambda); + EXPECT_TRUE(i == 0); + } + EXPECT_TRUE(i == 1); +} + +TEST(utils_tests, finally_mutable_lvalue_lambda) +{ + int i = 0; + { + auto mutable_lvalue_lambda = [&]() { f(i); }; + auto _ = finally(mutable_lvalue_lambda); + EXPECT_TRUE(i == 0); + } + EXPECT_TRUE(i == 1); +} + +TEST(utils_tests, finally_function_with_bind) +{ + int i = 0; + { + auto _ = finally([&i] { return f(i); }); + EXPECT_TRUE(i == 0); + } + EXPECT_TRUE(i == 1); +} + +TEST(utils_tests, finally_function_ptr) +{ + j = 0; + { + auto _ = finally(&g); + EXPECT_TRUE(j == 0); + } + EXPECT_TRUE(j == 1); +} + +TEST(utils_tests, finally_function) +{ + j = 0; + { + auto _ = finally(g); + EXPECT_TRUE(j == 0); + } + EXPECT_TRUE(j == 1); +} + +TEST(utils_tests, narrow_cast) +{ + int n = 120; + char c = narrow_cast(n); + EXPECT_TRUE(c == 120); + + n = 300; + unsigned char uc = narrow_cast(n); + EXPECT_TRUE(uc == 44); +} + +#ifndef GSL_KERNEL_MODE +TEST(utils_tests, narrow) +{ + int n = 120; + const char c = narrow(n); + EXPECT_TRUE(c == 120); + + n = 300; + EXPECT_THROW(narrow(n), narrowing_error); + + const auto int32_max = std::numeric_limits::max(); + const auto int32_min = std::numeric_limits::min(); + + EXPECT_TRUE(narrow(int32_t(0)) == 0); + EXPECT_TRUE(narrow(int32_t(1)) == 1); + EXPECT_TRUE(narrow(int32_max) == static_cast(int32_max)); + + EXPECT_THROW(narrow(int32_t(-1)), narrowing_error); + EXPECT_THROW(narrow(int32_min), narrowing_error); + + n = -42; + EXPECT_THROW(narrow(n), narrowing_error); + + EXPECT_TRUE( + narrow>(std::complex(4, 2)) == std::complex(4, 2)); + EXPECT_THROW(narrow>(std::complex(4.2)), narrowing_error); + + EXPECT_TRUE(narrow(float(1)) == 1); +} +#endif // GSL_KERNEL_MODE diff --git a/deps/discord-rpc b/deps/discord-rpc deleted file mode 160000 index 963aa9f..0000000 --- a/deps/discord-rpc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 963aa9f3e5ce81a4682c6ca3d136cddda614db33 diff --git a/deps/discord-rpc/.clang-format b/deps/discord-rpc/.clang-format new file mode 100644 index 0000000..1be8390 --- /dev/null +++ b/deps/discord-rpc/.clang-format @@ -0,0 +1,92 @@ +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: true +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: false +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: InlineOnly +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Stroustrup +BreakBeforeInheritanceComma: true +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +FixNamespaceComments: true +ForEachMacros: [] +IndentCaseLabels: false +IncludeCategories: + - Regex: '^("|<)stdafx\.h(pp)?("|>)' + Priority: -1 + - Regex: '^<(W|w)indows.h>' + Priority: 1 + - Regex: '^<' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '(_test|_win|_linux|_mac|_ios|_osx|_null)?$' +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakAssignment: 0 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 9999999 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: true +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +--- +Language: Cpp +--- +Language: ObjC +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +--- +Language: Java +BasedOnStyle: Google +BreakAfterJavaFieldAnnotations: true +... diff --git a/deps/discord-rpc/.gitignore b/deps/discord-rpc/.gitignore new file mode 100644 index 0000000..223c07d --- /dev/null +++ b/deps/discord-rpc/.gitignore @@ -0,0 +1,5 @@ +/build*/ +/.vscode/ +/thirdparty/ +.vs/ +.DS_Store \ No newline at end of file diff --git a/deps/discord-rpc/.travis.yml b/deps/discord-rpc/.travis.yml new file mode 100644 index 0000000..42cc09d --- /dev/null +++ b/deps/discord-rpc/.travis.yml @@ -0,0 +1,47 @@ +language: cpp + +env: + global: + - CLANG_FORMAT_SUFFIX="-dummy" # don't use formatting on Travis, this is + # needed not to use default 3.5 version + # which is too old. + +matrix: + include: + - os: linux + env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5" + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-5 + - os: linux + env: MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0" + addons: + apt: + sources: + - llvm-toolchain-trusty-4.0 + packages: + - clang-4.0 + - os: linux + env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0" + addons: + apt: + sources: + - llvm-toolchain-trusty-5.0 + packages: + - clang-5.0 + - os: osx + osx_image: xcode9 + +# prevent Travis from overwriting our CXX variables +before_install: + - eval "${MATRIX_EVAL}" + - echo $CXX + +script: + - mkdir build + - cd build + - cmake -DCLANG_FORMAT_SUFFIX=$CLANG_FORMAT_SUFFIX -DWARNINGS_AS_ERRORS=On --config Release .. + - cmake --build . -- -j2 diff --git a/deps/discord-rpc/CMakeLists.txt b/deps/discord-rpc/CMakeLists.txt new file mode 100644 index 0000000..5dad9e9 --- /dev/null +++ b/deps/discord-rpc/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required (VERSION 3.2.0) +project (DiscordRPC) + +include(GNUInstallDirs) + +option(BUILD_EXAMPLES "Build example apps" ON) + +# format +file(GLOB_RECURSE ALL_SOURCE_FILES + examples/*.cpp examples/*.h examples/*.c + include/*.h + src/*.cpp src/*.h src/*.c +) + +# Set CLANG_FORMAT_SUFFIX if you are using custom clang-format, e.g. clang-format-5.0 +find_program(CLANG_FORMAT_CMD clang-format${CLANG_FORMAT_SUFFIX}) + +if (CLANG_FORMAT_CMD) + add_custom_target( + clangformat + COMMAND ${CLANG_FORMAT_CMD} + -i -style=file -fallback-style=none + ${ALL_SOURCE_FILES} + DEPENDS + ${ALL_SOURCE_FILES} + ) +endif(CLANG_FORMAT_CMD) + +# thirdparty stuff +execute_process( + COMMAND mkdir ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty + ERROR_QUIET +) + +find_file(RAPIDJSONTEST NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) +if (NOT RAPIDJSONTEST) + message("no rapidjson, download") + set(RJ_TAR_FILE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/v1.1.0.tar.gz) + file(DOWNLOAD https://github.com/miloyip/rapidjson/archive/v1.1.0.tar.gz ${RJ_TAR_FILE}) + execute_process( + COMMAND ${CMAKE_COMMAND} -E tar xzf ${RJ_TAR_FILE} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty + ) + file(REMOVE ${RJ_TAR_FILE}) +endif(NOT RAPIDJSONTEST) + +find_file(RAPIDJSON NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH) + +add_library(rapidjson STATIC IMPORTED ${RAPIDJSON}) + +# add subdirs + +add_subdirectory(src) +if (BUILD_EXAMPLES) + add_subdirectory(examples/send-presence) +endif(BUILD_EXAMPLES) diff --git a/deps/discord-rpc/LICENSE b/deps/discord-rpc/LICENSE new file mode 100644 index 0000000..17fca3d --- /dev/null +++ b/deps/discord-rpc/LICENSE @@ -0,0 +1,19 @@ +Copyright 2017 Discord, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/deps/discord-rpc/README.md b/deps/discord-rpc/README.md new file mode 100644 index 0000000..1285fb8 --- /dev/null +++ b/deps/discord-rpc/README.md @@ -0,0 +1,158 @@ +# Discord RPC + +## Deprecation Notice + +This library has been deprecated in favor of Discord's GameSDK. [Learn more here](https://discordapp.com/developers/docs/game-sdk/sdk-starter-guide) + +--- + +This is a library for interfacing your game with a locally running Discord desktop client. It's known to work on Windows, macOS, and Linux. You can use the lib directly if you like, or use it as a guide to writing your own if it doesn't suit your game as is. PRs/feedback welcome if you have an improvement everyone might want, or can describe how this doesn't meet your needs. + +Included here are some quick demos that implement the very minimal subset to show current status, and +have callbacks for where a more complete game would do more things (joining, spectating, etc). + +## Documentation + +The most up to date documentation for Rich Presence can always be found on our [developer site](https://discordapp.com/developers/docs/rich-presence/how-to)! If you're interested in rolling your own native implementation of Rich Presence via IPC sockets instead of using our SDK—hey, you've got free time, right?—check out the ["Hard Mode" documentation](https://github.com/discordapp/discord-rpc/blob/master/documentation/hard-mode.md). + +## Basic Usage + +Zeroith, you should be set up to build things because you are a game developer, right? + +First, head on over to the [Discord developers site](https://discordapp.com/developers/applications/me) and make yourself an app. Keep track of `Client ID` -- you'll need it here to pass to the init function. + +### Unreal Engine 4 Setup + +To use the Rich Presense plugin with Unreal Engine Projects: + +1. Download the latest [release](https://github.com/discordapp/discord-rpc/releases) for each operating system you are targeting and the zipped source code +2. In the source code zip, copy the UE plugin—`examples/unrealstatus/Plugins/discordrpc`—to your project's plugin directory +3. At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create an `Include` folder and copy `discord_rpc.h` and `discord_register.h` to it from the zip +4. Follow the steps below for each OS +5. Build your UE4 project +6. Launch the editor, and enable the Discord plugin. + +#### Windows + +- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Win64` folder +- Copy `lib/discord-rpc.lib` and `bin/discord-rpc.dll` from `[RELEASE_ZIP]/win64-dynamic` to the `Win64` folder + +#### Mac + +- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Mac` folder +- Copy `libdiscord-rpc.dylib` from `[RELEASE_ZIP]/osx-dynamic/lib` to the `Mac` folder + +#### Linux + +- At `[YOUR_UE_PROJECT]/Plugins/discordrpc/source/ThirdParty/DiscordRpcLibrary/`, create a `Linux` folder +- Inside, create another folder `x86_64-unknown-linux-gnu` +- Copy `libdiscord-rpc.so` from `[RELEASE_ZIP]/linux-dynamic/lib` to `Linux/x86_64-unknown-linux-gnu` + +### Unity Setup + +If you're a Unity developer looking to integrate Rich Presence into your game, follow this simple guide to get started towards success: + +1. Download the DLLs for any platform that you need from [our releases](https://github.com/discordapp/discord-rpc/releases) +2. In your Unity project, create a `Plugins` folder inside your `Assets` folder if you don't already have one +3. Copy the file `DiscordRpc.cs` from [here](https://github.com/discordapp/discord-rpc/blob/master/examples/button-clicker/Assets/DiscordRpc.cs) into your `Assets` folder. This is basically your header file for the SDK + +We've got our `Plugins` folder ready, so let's get platform-specific! + +#### Windows + +4. Create `x86` and `x86_64` folders inside `Assets/Plugins/` +5. Copy `discord-rpc-win/win64-dynamic/bin/discord-rpc.dll` to `Assets/Plugins/x86_64/` +6. Copy `discord-rpc-win/win32-dynamic/bin/discord-rpc.dll` to `Assets/Plugins/x86/` +7. Click on both DLLs and make sure they are targetting the correct architectures in the Unity editor properties pane +8. Done! + +#### MacOS + +4. Copy `discord-rpc-osx/osx-dynamic/lib/libdiscord-rpc.dylib` to `Assets/Plugins/` +5. Rename `libdiscord-rpc.dylib` to `discord-rpc.bundle` +6. Done! + +#### Linux + +4. Copy `discord-rpc-linux/linux-dynamic-lib/libdiscord-rpc.so` to `Assets/Plugins/` +5. Done! + +You're ready to roll! For code examples on how to interact with the SDK using the `DiscordRpc.cs` header file, check out [our example](https://github.com/discordapp/discord-rpc/blob/master/examples/button-clicker/Assets/DiscordController.cs) + +### From package + +Download a release package for your platform(s) -- they have subdirs with various prebuilt options, select the one you need add `/include` to your compile includes, `/lib` to your linker paths, and link with `discord-rpc`. For the dynamically linked builds, you'll need to ship the associated file along with your game. + +### From repo + +First-eth, you'll want `CMake`. There's a few different ways to install it on your system, and you should refer to [their website](https://cmake.org/install/). Many package managers provide ways of installing CMake as well. + +To make sure it's installed correctly, type `cmake --version` into your flavor of terminal/cmd. If you get a response with a version number, you're good to go! + +There's a [CMake](https://cmake.org/download/) file that should be able to generate the lib for you; Sometimes I use it like this: + +```sh + cd + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX= + cmake --build . --config Release --target install +``` + +There is a wrapper build script `build.py` that runs `cmake` with a few different options. + +Usually, I run `build.py` to get things started, then use the generated project files as I work on things. It does depend on `click` library, so do a quick `pip install click` to make sure you have it if you want to run `build.py`. + +There are some CMake options you might care about: + +| flag | default | does | +| ---------------------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ENABLE_IO_THREAD` | `ON` | When enabled, we start up a thread to do io processing, if disabled you should call `Discord_UpdateConnection` yourself. | +| `USE_STATIC_CRT` | `OFF` | (Windows) Enable to statically link the CRT, avoiding requiring users install the redistributable package. (The prebuilt binaries enable this option) | +| [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/v3.7/variable/BUILD_SHARED_LIBS.html) | `OFF` | Build library as a DLL | +| `WARNINGS_AS_ERRORS` | `OFF` | When enabled, compiles with `-Werror` (on \*nix platforms). | + +## Continuous Builds + +Why do we have three of these? Three times the fun! + +| CI | badge | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| TravisCI | [![Build status](https://travis-ci.org/discordapp/discord-rpc.svg?branch=master)](https://travis-ci.org/discordapp/discord-rpc) | +| AppVeyor | [![Build status](https://ci.appveyor.com/api/projects/status/qvkoc0w1c4f4b8tj?svg=true)](https://ci.appveyor.com/project/crmarsh/discord-rpc) | +| Buildkite (internal) | [![Build status](https://badge.buildkite.com/e103d79d247f6776605a15246352a04b8fd83d69211b836111.svg)](https://buildkite.com/discord/discord-rpc) | + +## Sample: send-presence + +This is a text adventure "game" that inits/deinits the connection to Discord, and sends a presence update on each command. + +## Sample: button-clicker + +This is a sample [Unity](https://unity3d.com/) project that wraps a DLL version of the library, and sends presence updates when you click on a button. Run `python build.py unity` in the root directory to build the correct library files and place them in their respective folders. + +## Sample: unrealstatus + +This is a sample [Unreal](https://www.unrealengine.com) project that wraps the DLL version of the library with an Unreal plugin, exposes a blueprint class for interacting with it, and uses that to make a very simple UI. Run `python build.py unreal` in the root directory to build the correct library files and place them in their respective folders. + +## Wrappers and Implementations + +Below is a table of unofficial, community-developed wrappers for and implementations of Rich Presence in various languages. If you would like to have yours added, please make a pull request adding your repository to the table. The repository should include: + +- The code +- A brief ReadMe of how to use it +- A working example + +###### Rich Presence Wrappers and Implementations + +| Name | Language | +| ------------------------------------------------------------------------- | --------------------------------- | +| [Discord RPC C#](https://github.com/Lachee/discord-rpc-csharp) | C# | +| [Discord RPC D](https://github.com/voidblaster/discord-rpc-d) | [D](https://dlang.org/) | +| [discord-rpc.jar](https://github.com/Vatuu/discord-rpc 'Discord-RPC.jar') | Java | +| [java-discord-rpc](https://github.com/MinnDevelopment/java-discord-rpc) | Java | +| [Discord-IPC](https://github.com/jagrosh/DiscordIPC) | Java | +| [Discord Rich Presence](https://npmjs.org/discord-rich-presence) | JavaScript | +| [drpc4k](https://github.com/Bluexin/drpc4k) | [Kotlin](https://kotlinlang.org/) | +| [lua-discordRPC](https://github.com/pfirsich/lua-discordRPC) | LuaJIT (FFI) | +| [pypresence](https://github.com/qwertyquerty/pypresence) | [Python](https://python.org/) | +| [SwordRPC](https://github.com/Azoy/SwordRPC) | [Swift](https://swift.org) | diff --git a/deps/discord-rpc/appveyor.yml b/deps/discord-rpc/appveyor.yml new file mode 100644 index 0000000..1c328b8 --- /dev/null +++ b/deps/discord-rpc/appveyor.yml @@ -0,0 +1,17 @@ +version: '{build}' +install: + - python -m pip install click + +build_script: + - mkdir examples\unrealstatus\Plugins\discordrpc\Binaries\ThirdParty\discordrpcLibrary\Win64 + - python build.py + +artifacts: +- path: builds\install\win32-dynamic + name: win32-dynamic +- path: builds\install\win32-static + name: win32-static +- path: builds\install\win64-dynamic + name: win64-dynamic +- path: builds\install\win64-static + name: win64-static diff --git a/deps/discord-rpc/build.py b/deps/discord-rpc/build.py new file mode 100644 index 0000000..215d358 --- /dev/null +++ b/deps/discord-rpc/build.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python + +import os +import subprocess +import sys +import shutil +import zipfile +from contextlib import contextmanager +import click + + +def get_platform(): + """ a name for the platform """ + if sys.platform.startswith('win'): + return 'win' + elif sys.platform == 'darwin': + return 'osx' + elif sys.platform.startswith('linux'): + return 'linux' + raise Exception('Unsupported platform ' + sys.platform) + + +SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) +# we use Buildkite which sets this env variable by default +IS_BUILD_MACHINE = os.environ.get('CI', '') == 'true' +PLATFORM = get_platform() +INSTALL_ROOT = os.path.join(SCRIPT_PATH, 'builds', 'install') + + +def get_signtool(): + """ get path to code signing tool """ + if PLATFORM == 'win': + sdk_dir = 'c:\\Program Files (x86)\\Windows Kits\\10' # os.environ['WindowsSdkDir'] + return os.path.join(sdk_dir, 'bin', 'x86', 'signtool.exe') + elif PLATFORM == 'osx': + return '/usr/bin/codesign' + + +@contextmanager +def cd(new_dir): + """ Temporarily change current directory """ + if new_dir: + old_dir = os.getcwd() + os.chdir(new_dir) + yield + if new_dir: + os.chdir(old_dir) + + +def mkdir_p(path): + """ mkdir -p """ + if not os.path.isdir(path): + click.secho('Making ' + path, fg='yellow') + os.makedirs(path) + + +@click.group(invoke_without_command=True) +@click.pass_context +@click.option('--clean', is_flag=True) +def cli(ctx, clean): + """ click wrapper for command line stuff """ + if ctx.invoked_subcommand is None: + ctx.invoke(libs, clean=clean) + if IS_BUILD_MACHINE: + ctx.invoke(sign) + ctx.invoke(archive) + + +@cli.command() +@click.pass_context +def unity(ctx): + """ build just dynamic libs for use in unity project """ + ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True) + BUILDS = [] + + click.echo('--- Copying libs and header into unity example') + UNITY_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'button-clicker', 'Assets', 'Plugins') + + if sys.platform.startswith('win'): + LIBRARY_NAME = 'discord-rpc.dll' + BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release') + UNITY_64_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86_64') + BUILDS.append({BUILD_64_BASE_PATH: UNITY_64_DLL_PATH}) + + BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release') + UNITY_32_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86') + BUILDS.append({BUILD_32_BASE_PATH: UNITY_32_DLL_PATH}) + + elif sys.platform == 'darwin': + LIBRARY_NAME = 'discord-rpc.bundle' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src') + UNITY_DLL_PATH = UNITY_PROJECT_PATH + os.rename( + os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.dylib'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.bundle')) + + BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH}) + + elif sys.platform.startswith('linux'): + LIBRARY_NAME = 'discord-rpc.so' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src') + UNITY_DLL_PATH = os.path.join(UNITY_PROJECT_PATH, 'x86') + os.rename(os.path.join(BUILD_BASE_PATH, 'libdiscord-rpc.so'), os.path.join(BUILD_BASE_PATH, 'discord-rpc.so')) + + BUILDS.append({BUILD_BASE_PATH: UNITY_DLL_PATH}) + + else: + raise Exception('Unsupported platform ' + sys.platform) + + for build in BUILDS: + for i in build: + mkdir_p(build[i]) + shutil.copy(os.path.join(i, LIBRARY_NAME), build[i]) + + +@cli.command() +@click.pass_context +def unreal(ctx): + """ build libs and copy them into the unreal project """ + ctx.invoke(libs, clean=False, static=False, shared=True, skip_formatter=True, just_release=True) + BUILDS = [] + + click.echo('--- Copying libs and header into unreal example') + UNREAL_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'Plugins', 'discordrpc') + UNREAL_INCLUDE_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Include') + mkdir_p(UNREAL_INCLUDE_PATH) + shutil.copy(os.path.join(SCRIPT_PATH, 'include', 'discord_rpc.h'), UNREAL_INCLUDE_PATH) + + if sys.platform.startswith('win'): + LIBRARY_NAME = 'discord-rpc.lib' + BUILD_64_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release') + UNREAL_64_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win64') + BUILDS.append({BUILD_64_BASE_PATH: UNREAL_64_DLL_PATH}) + + BUILD_32_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win32-dynamic', 'src', 'Release') + UNREAL_32_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win32') + BUILDS.append({BUILD_32_BASE_PATH: UNREAL_32_DLL_PATH}) + + elif sys.platform == 'darwin': + LIBRARY_NAME = 'libdiscord-rpc.dylib' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'osx-dynamic', 'src') + UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Mac') + + BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH}) + + elif sys.platform.startswith('linux'): + LIBRARY_NAME = 'libdiscord-rpc.so' + BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'linux-dynamic', 'src') + UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Linux') + + BUILDS.append({BUILD_BASE_PATH: UNREAL_DLL_PATH}) + + else: + raise Exception('Unsupported platform ' + sys.platform) + + for build in BUILDS: + for i in build: + mkdir_p(build[i]) + shutil.copy(os.path.join(i, LIBRARY_NAME), build[i]) + + +def build_lib(build_name, generator, options, just_release): + """ Create a dir under builds, run build and install in it """ + build_path = os.path.join(SCRIPT_PATH, 'builds', build_name) + install_path = os.path.join(INSTALL_ROOT, build_name) + mkdir_p(build_path) + mkdir_p(install_path) + with cd(build_path): + initial_cmake = ['cmake', SCRIPT_PATH, '-DCMAKE_INSTALL_PREFIX=%s' % os.path.join('..', 'install', build_name)] + if generator: + initial_cmake.extend(['-G', generator]) + for key in options: + val = options[key] + if type(val) is bool: + val = 'ON' if val else 'OFF' + initial_cmake.append('-D%s=%s' % (key, val)) + click.echo('--- Building ' + build_name) + subprocess.check_call(initial_cmake) + if not just_release: + subprocess.check_call(['cmake', '--build', '.', '--config', 'Debug']) + subprocess.check_call(['cmake', '--build', '.', '--config', 'Release', '--target', 'install']) + + +@cli.command() +def archive(): + """ create zip of install dir """ + click.echo('--- Archiving') + archive_file_path = os.path.join(SCRIPT_PATH, 'builds', 'discord-rpc-%s.zip' % get_platform()) + archive_file = zipfile.ZipFile(archive_file_path, 'w', zipfile.ZIP_DEFLATED) + archive_src_base_path = INSTALL_ROOT + archive_dst_base_path = 'discord-rpc' + with cd(archive_src_base_path): + for path, _, filenames in os.walk('.'): + for fname in filenames: + fpath = os.path.join(path, fname) + dst_path = os.path.normpath(os.path.join(archive_dst_base_path, fpath)) + click.echo('Adding ' + dst_path) + archive_file.write(fpath, dst_path) + + +@cli.command() +def sign(): + """ Do code signing within install directory using our cert """ + tool = get_signtool() + signable_extensions = set() + if PLATFORM == 'win': + signable_extensions.add('.dll') + sign_command_base = [ + tool, + 'sign', + '/n', + 'Discord Inc.', + '/a', + '/tr', + 'http://timestamp.digicert.com/rfc3161', + '/as', + '/td', + 'sha256', + '/fd', + 'sha256', + ] + elif PLATFORM == 'osx': + signable_extensions.add('.dylib') + sign_command_base = [ + tool, + '--keychain', + os.path.expanduser('~/Library/Keychains/login.keychain'), + '-vvvv', + '--deep', + '--force', + '--sign', + 'Developer ID Application: Hammer & Chisel Inc. (53Q6R32WPB)', + ] + else: + click.secho('Not signing things on this platform yet', fg='red') + return + + click.echo('--- Signing') + for path, _, filenames in os.walk(INSTALL_ROOT): + for fname in filenames: + ext = os.path.splitext(fname)[1] + if ext not in signable_extensions: + continue + fpath = os.path.join(path, fname) + click.echo('Sign ' + fpath) + sign_command = sign_command_base + [fpath] + subprocess.check_call(sign_command) + + +@cli.command() +@click.option('--clean', is_flag=True) +@click.option('--static', is_flag=True) +@click.option('--shared', is_flag=True) +@click.option('--skip_formatter', is_flag=True) +@click.option('--just_release', is_flag=True) +def libs(clean, static, shared, skip_formatter, just_release): + """ Do all the builds for this platform """ + if clean: + shutil.rmtree('builds', ignore_errors=True) + + mkdir_p('builds') + + if not (static or shared): + static = True + shared = True + + static_options = {} + dynamic_options = { + 'BUILD_SHARED_LIBS': True, + 'USE_STATIC_CRT': True, + } + + if skip_formatter or IS_BUILD_MACHINE: + static_options['CLANG_FORMAT_SUFFIX'] = 'none' + dynamic_options['CLANG_FORMAT_SUFFIX'] = 'none' + + if IS_BUILD_MACHINE: + just_release = True + static_options['WARNINGS_AS_ERRORS'] = True + dynamic_options['WARNINGS_AS_ERRORS'] = True + + if PLATFORM == 'win': + generator32 = 'Visual Studio 14 2015' + generator64 = 'Visual Studio 14 2015 Win64' + if static: + build_lib('win32-static', generator32, static_options, just_release) + build_lib('win64-static', generator64, static_options, just_release) + if shared: + build_lib('win32-dynamic', generator32, dynamic_options, just_release) + build_lib('win64-dynamic', generator64, dynamic_options, just_release) + elif PLATFORM == 'osx': + if static: + build_lib('osx-static', None, static_options, just_release) + if shared: + build_lib('osx-dynamic', None, dynamic_options, just_release) + elif PLATFORM == 'linux': + if static: + build_lib('linux-static', None, static_options, just_release) + if shared: + build_lib('linux-dynamic', None, dynamic_options, just_release) + + +if __name__ == '__main__': + os.chdir(SCRIPT_PATH) + sys.exit(cli()) diff --git a/deps/discord-rpc/documentation/hard-mode.md b/deps/discord-rpc/documentation/hard-mode.md new file mode 100644 index 0000000..35042cb --- /dev/null +++ b/deps/discord-rpc/documentation/hard-mode.md @@ -0,0 +1,164 @@ +# Hard Mode: Roll Your Own Client + +Discord's Rich Presence feature is designed as an obfuscated addition to our existing [RPC infrastructure](https://discordapp.com/developers/docs/topics/rpc). The standalone library and header files make it easy for any dev to drop it into their game. + +Our library communicates with Discord over the local Discord RPC socket. We've already done the work in connecting properly, handling disconnects and reconnects, and other RPC intracacies, but those who have done this implementation for our private alpha Voice and Chat SDK can simply make use of the new RPC commands and events to implement Rich Presence. + +## Hark! A warning! + +By committing to an RPC-only integration, you decide to forego the work our library and header file have done for you in the way of error handling, state storage, disconnecting and reconnecting, and other quality of life abstractions. While simply implementing the new RPC command and events will enable Rich Presence for your game, we highly suggest that you do your best to mimic the functionality of the SDK the most that you can. It ensure not only code quality on your part, but also an excellent experience on the part of your players. + +## Application Protocol Registration + +One thing that cannot be explicitly done over RPC is registering an application protocol for your game. If you choose to do an RPC-only implementation, you will have to register your application protocol yourself in the format of `discord-[your_app_id]://`. You can use `Discord_Register()` as a good(?) example of how to properly register an application protocol for use with Discord. For OSX and Linux it is probably simpler to handle the protocol registration as part of your install/packaging. + +## New RPC Command + +The new RPC command for Rich Presence is `SET_ACTIVITY`. The fields are similar to what is outlined in the SDK; we've combined similar fields into objects for the sake of less data on the wire. + +The one major difference is the `party.size` field. It is an array with a size of two. The first element is the current party size, `partySize` from the main documentation. The second element is the maximum party size, `partyMax` from the main documentation. + +Below is a full example of a `SET_ACTIVITY` command. Field restrictions like size are the same as outlined in the main documentation. + +``` +{ + "cmd": "SET_ACTIVITY", + "args": { + "pid": 9999, // Your application's process id - required field + "activity": { + "state": "In a Group", + "details": "Competitive | In a Match", + "timestamps": { + "start": time(nullptr), + "end": time(nullptr) + ((60 * 5) + 23) + }, + "assets": { + "large_image": "numbani_map", + "large_text": "Numbani", + "small_image": "pharah_profile", + "small_text": "Pharah" + }, + "party": { + "id": GameEngine.GetPartyId(), + "size": [3, 6] + }, + "secrets": { + "join": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f", + "spectate": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0", + "match": "4b2fdce12f639de8bfa7e3591b71a0d679d7c93f" + }, + "instance": true + } + }, + "nonce": "647d814a-4cf8-4fbb-948f-898abd24f55b" +} +``` + +## New RPC Events + +The three new RPC events for Rich Presence power the ability to join and spectate your friends' games. + +First is the `ACTIVITY_JOIN` event: + +```json +{ + "cmd": "DISPATCH", + "data": { + "secret": "025ed05c71f639de8bfaa0d679d7c94b2fdce12f" + }, + "evt": "ACTIVITY_JOIN" +} +``` + +Second is the `ACTIVITY_SPECTATE` event: + +```json +{ + "cmd": "DISPATCH", + "data": { + "secret": "e7eb30d2ee025ed05c71ea495f770b76454ee4e0" + }, + "evt": "ACTIVITY_SPECTATE" +} +``` + +And third is the `ACTIVITY_JOIN_REQUEST` event: + +```json +{ + "cmd": "DISPATCH", + "data": { + "user": { + "id": "53908232506183680", + "username": "Mason", + "discriminator": "1337", + "avatar": "a_bab14f271d565501444b2ca3be944b25" + } + }, + "evt": "ACTIVITY_JOIN_REQUEST" +} +``` + +In order to receive these events, you need to [subscribe](https://discordapp.com/developers/docs/topics/rpc#subscribe) to them like so: + +```json +{ + "nonce": "be9a6de3-31d0-4767-a8e9-4818c5690015", + "evt": "ACTIVITY_JOIN", + "cmd": "SUBSCRIBE" +} +``` + +```json +{ + "nonce": "ae9qdde3-31d0-8989-a8e9-dnakwy174he", + "evt": "ACTIVITY_SPECTATE", + "cmd": "SUBSCRIBE" +} +``` + +```json +{ + "nonce": "5dc0c062-98c6-47a0-8922-bbb52e9d6afa", + "evt": "ACTIVITY_JOIN_REQUEST", + "cmd": "SUBSCRIBE" +} +``` + +To unsubscribe from these events, resend with the command `UNSUBSCRIBE` + +## Responding +A discord user will request access to the game. If the ACTIVITY_JOIN_REQUEST has been subscribed too, the ACTIVITY_JOIN_REQUEST event will be sent to the host's game. Accept it with following model: +```json +{ + "nonce": "5dc0c062-98c6-47a0-8922-15aerg126", + "cmd": "SEND_ACTIVITY_JOIN_INVITE", + "args": + { + "user_id": "53908232506183680" + } +} +``` + +To reject the request, use `CLOSE_ACTIVITY_REQUEST`: +```json +{ + "nonce": "5dc0c062-98c6-47a0-8922-dasg256eafg", + "cmd": "CLOSE_ACTIVITY_REQUEST", + "args": + { + "user_id": "53908232506183680" + } +} +``` + +## Notes +Here are just some quick notes to help with some common troubleshooting problems. +* IPC will echo back every command you send as a response. Use this as a lock-step feature to avoid flooding messages. Can be used to validate messages such as the Presence or Subscribes. +* The pipe expects for frames to be written in a single byte array. You cannot do multiple `stream.Write(opcode);` `stream.Write(length);` as it will break the pipe. Instead create a buffer, write the data to the buffer, then send the entire buffer to the stream. +* Discord can be on any pipe ranging from `discord-ipc-0` to `discord-ipc-9`. It is a good idea to try and connect to each one and keeping the first one you connect too. For multiple clients (eg Discord and Canary), you might want to add a feature to manually select the pipe so you can more easily debug the application. +* All enums are `lower_snake_case`. +* The opcode and length in the header are `Little Endian Unsigned Integers (32bits)`. In some languages, you must convert them as they can be architecture specific. +* [Discord Rich Presence How-To](https://discordapp.com/developers/docs/rich-presence/how-to) contains a lot of the information this document doesn't. For example, it will tell you about the response payload. +* In the documentation, DISCORD_REPLY_IGNORE is just implemented the same as DISCORD_REPLY_NO. +* You can test the Join / Spectate feature by enabling them in your profile and whitelisting a test account. Use Canary to run 2 accounts on the same machine. diff --git a/deps/discord-rpc/documentation/images/rp-dev-dashboard.png b/deps/discord-rpc/documentation/images/rp-dev-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..f246cfb2dda158fa5b3688392ea1ed4532944c36 GIT binary patch literal 325539 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 z

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

pxqyj%q8x;kRQqE05>l)$TU)9TLXyMSgma zf=nG5RT;~NS9*#!oaKkh10EkN^>6-Ex73;llMQ*mhYgvVWObSB#D%|8Rw(_E+e0b= zfJI6Ax6#)knb7nmy^YP#x0F64NVCoq^bMU352mH=));;0__UvLHanFkvhBf(X+=j# zjKrRz8@PEkojEp;OU~1Z_(H4jLY|znvJ9DJw&wqIkXFB|Ls7vxrMiqTV>pg$dVg@! zm*9qG0@$F-WGk2b7MjM+~YblT9;2-N7)BL?FAzHkv(I^<3%3J0n6_u&LGxe$KEAziN zddL%Lc&b59ka+qTexVy_ZfWyDk6$C5oXSTY9lDviz>eSUX5P@aw2&F4L`v%WfKT)B zuH8MY9g~iO9e?WB90pB`slFK4!DdQG-G0hNQ9zLcuoYy<3=w`NRQ_F?3%}p2jOFTV z^x2jXc~d^%akd`3bpyXyd7V#-%cl9h8jiw3PtiwFbYgAkw`Fe2)ZD=+S5*Uew}kzl z|2%wkrAVL8QKB9Rpt5fJ>R#V~9D2Z2%#yU}T>iBJNTLp=x4_}E&}!7AI-nFN!NaP) zvi*4&%F{F@-4rboY}?}16c|;7JjG57{E?=Ur`A=gq)Lp`s`^Ykc~6{_HhMfxV&4!I zp&pHfCg=2pFzaK#P zg==J3P!>S;=YQp&35u2eS|;Yt z%?=+L6o7*SO2!mjZOyZ5nL{H03P7p0HnD94MO0gagx-3+v?rVR<8aADvOw^?APPkwc#ub7OsNlr`{pXc~)fnfndXoVn#|YZ(TOD|%8- zH%^+%EyewFx5Y!~pt(Sq4t?V5gjrKQHwE&!o2)v77!|a7t z76UQ^gd-oDYa`<2j~gd1RB<$W{l2~HE_^`NedHmL#(2g1tT^cYkHs8=OfZPx4MyBW z3gqj%dj4p06moip=(q@oauaTw@hTBL9cpF9(udla!$}8#Wpi=S3g-_de%42GA*Ri# zyDAT+qBiFYiqIHAqV2KajG+<@9CD<)_-fBH=a=BV&rA%xpfsIU4^Qo5!zI=L%in00 zO!R6@?!!54UpbZWj*n>bgow`r@ulgwV*Rsqb)pvJF$h?L$+iKM1f00_!{JTw$vi73 z19M4coUw``8q;GjF}@dN4V}ouD8faIvWm_1QyoW~s6Znm{*tzJ@;+OSgGmRqz(D`~ zkeh8o6Vl^uHlx!%t@2vKte)#fo5X+-zZ+_a=1|#*$Kz_A?=OO$&ri?cSE!Bq zXT1m5%VhF3w;hht=ZrI&AqVW7#p#rk4-xdi!_NBOHm{=7m-Hqx`Jr+I(d1dsCM@aB zf)JiTa%3Ir`Us>yv2Ty^Y=;e8t>FM9M*9#k00^mTru4h#7#70cJWI9Q$2dZ?ftWwR zG2N4x8(51G1)RBk_kGeD5Dh`}g5N>ZWwJe|WCDg&2>%1U7pz4JfoZz4L_vSQ9pnZ8 zlRxrr3~{T*%QJvkvFP5O5_;%OerF(47r+41MWZp1k9sbaP0NHtT>o@HTq&Xcr=Ogj zUi;hYd9SC@&0d(0SNS;iA_rj}{P)uv93T_`s7S*O$BwcBx#U)MPE2vqp*vB}M*%g( zD(Gft$>y>ip~xy&GzE0Ba(}8T{~7U0(}C%Nd1g*Z1)B$XS!P^-Ay`OsRc5{iGuwOy zBnofBkZ~OoBet_r{dC`>cd07VkdX5EZH%gN_F`AEnaj}0w#J8zMyJ53YnfNFVq2*W z{qg7A|J{h**)Eez6QZzD$tGjQjVf1pSV`!X3fC)I*7KVesfHQkh`F<|p}UBDw*FUi zH`LTHIfa#lgk@n*LH~yl!X_%uUa+(nxT*FjFQ|%zDc7f=F{rLXi0{`L+G6zDipvh| z6BPAyxR_R7GH@r)G@-m~YkhXI!w-;|Sx@;4H8^a4pR9hTV?1+!mIW zykvbf0m2?K62|0AB5ChJ(NCT#w@&V8CGT8%V!Y3q5CLM}Sjp689IQEl=jj+Ox6b+k#)=0N*=8Puje`!R5Nj!*F*MDCzZwt_frjHbXEqMLHV9DSYYYvY@dACL z{mmVF4jN*fo-A>d1|X48Oj5ETkL$uL?4#L$iPKGq_?zbO{L{tdN9k^(m((udSr+Q@| zbUA7Af3Fzq?y6j82*O!`pf_o*uK$i|4W5b>xG3_nP>JQfSA;17xId5kRaPZ2RMNY3 z`Q!81@YB()JHIL9KgO-+0RkE7qmc*Z2$KP<06yku9b(8S7KR~L5`~6_JL2qrK!S-S z_?rHb5lPp|b0dxKE-y{usn-z4?k|2djh@kB3*XA(;!+q`@-2x!32WN^^{3lMzT#!P zajs8W2Jg{hvG?yBRJBjq5Bs+-cI9)ZMm5wq!dVs;%KFTZ3iRzUg7xBqjk94Y7xo8? zmMvX$FrEtG)oTNT6{Ghgg6tux6;iLY4$Jig3! zEihU*KGp5`yhWCOw_W~>0k{{uI@+CuSMUeMwSTp|X8a?HRs5zjdx*Ayl1T24Xe*Jn z20$(?o@W%Qz59M<5vr{H%W!6kwh97NChoj2&Wgs=&KYI+De8!V0>OY?eZ!(7WMxIF zd?%Tkz|`hmn3pFV!VnX^C{l}Iscf_|)v5-?IBeDWtgcuA5l03Ih)B0O9NQWrfeYF* zKb39Hd_dtg@}T)|6dlzzzISwIK|IfXH~M*}}eIC!%Q z2!EDGl$1_V-7U6<_shD4rQ3%}#BvCKj~L;Em#?%r40Sw%aPQc1*IBCMbefE(oVB**bHkKoL#za{HWt9njwe5O&K{>9beDluU^c_m`@R}$VNLn zJfQf6(J}smtbV!&Z_bq_nQeQWpq_|n`!85~KLMix_kk`IS(HYD7I7_5qVsi5W-VN{r7&`Wos zTdfSuiul>iGP|Mj(?#G*1@6grKpWUmVB-0K7q9MG*6v%Dx-pJ>y7pDD-FCCaE~vIE zh));*Ke$$2p1indL?rc|cD;fo(DAySe_C#7cB29!+m&9<*LrUFm}&eU*2FlK1#49i zCb&U@FFk8dt5SZO%RLXjQ9>*DXuY0$t54o7bh}M(C@H?2T}_`Dbshe44wzSipRKt_ zdBg2(HtL$RPS%2UGaOUDKPh;L-}bCr<-$Gx29Nfux#T_63O_w^nFKnSWOW=Zb@Udg z2r?H{O(~-;UiplMNIFc15^8GYXzC7WzJ3Lo8^o@fO>I|41x2ePb!C)^mfq2@gy?!8 z$yB_48{LLE1!mC6A|0?5zcM~>)@M-O5>}ip2)i;0NY{vgVT2Tf{dUv|y(J9MB`L99 zD3Pqb$2|B+21O2A>~{0=7@({l)KiMu%N5cb8vqT2p(UY09Kyps6OXZERx3(;DFTr5 zbN@8tIt*9sZ^~(Hu8gvQb4q;FZ>_XDEvvmtTv* z`AgvaKQXxXsnN}`iOGbT(W}@Hy7xcsr~8IH{&sa7?HTX#W5i*f4AXPTf=*eAu)xZh z&`+Pq#E7Igs=x!b4*z7gyO`@8wfOB|deOMj)^A4G&B0f0qfjV@duU+G@|CKQPBrxh zOs3!hI*&{~Yc0n-xtxIu1!C6fX2Ja1;`7b@@kx|Wp&+&^G|7JjG4jbDetrZFD49A> zKA%;%+b0NF1aTg4Z68`my3r3}0%r?AAvZJab6V zvA*owB~l}(v0XW9moH!L8W}Gf;OAQ{*Ec~sOJtF=9&h#~K3)wJccpbLt|x!x%A+(6 z@bSKT^>Dnm@Ry5AB8T#!8|6m4!zb`-w*Qczl>6rLn%8i5(tA<^Fd$D8Dj-MdgsGNYZ&hYQ)^jBKQNw5QSCY zSzR4M@xD=DaCn}BtpbZarA(tXl~~qBCaIA zD?&kb*)kORvSE&?`jA%}?86Cdg8D*APk<2M-~DJls-BmH`v%=7uIE#ylh)n0q|1pC zcf&ia^w|F#B*KP&dip+1@)K*}yUj0b_?J^==xG;_i&tPUppl{H9_5~;9j%bu)pdoM z9e+~<#vxg&GrrN`jzVm8dx(t!nee5l>G2fqrq(3v;4Y4GXq_c{UopcB$5zQ7 z%W>CJyr1)vP5#Sjx!?ryk3T9wJJUTPXWOc2LGVc-T3YJ8OmC5+m)^w*<4nirfr0W9 z15w{!>!wogZfq`SMelyQbX{fue!P|5c6VStF&00Mw2}0(_aFfT9+pM|*2~stfZij+ zXY*XN4_;h>|7Mp#n-6#^7ng&JWL}(IjqZ0Hcs(1z+c~sGVvB1WJ;O%C&r8bhjD*bDIh@c2kf;#^s-(vxM|~Je48Xn{t@Rb)UQe1atr- z!lH`LX=-g=}4`t<#Dh|e)hvahNa`tVe+%Kc(&He zm62MPzQZhY8%j}wNdlwFZ!3y4MPemmtK&gn{`N$ckdS(MHR@yKCaf5YqTgYxlF`CS zuc05;(8J|x^ucX>QD@?)Cu}0EHj-(bD)Qlyy+U{)$KRDkk%Fc8ogb-j7>l8-sYw46) z3)H^*fx%m~f@mNe|63X2cnXJ$-9?1%^cPB8YEcHETu|Ku?KGB>g^a{pcPT zS=RYpA$Vv#YbX?OcaHbk_pIn|mzqU`@SgMWKb&&zYQyA2Y(|GSb;{}0RwD#NC~`D? zt)Br)IVYbBS>LtP)k)|rMc1>3L7338mTaZjYP*4K#=rFB0Do1bKIi-LF1GY|owT5Y zL)=Rw(v--lKZfbx6(VyTOt`mVy)Wn!&)6u%?vfCyUGsE3&%$OR|E7hS9EAhZq7~;| zyq)^~Vv}ETBkub8eJP@OOm*Nd<+B~GP}6yu8wo#6RP$ecz+W}Nrf%b6?gql9i@yT6 zqv{7*(E(E4|D51KmmGla2!F5K5)Y-@y0`)4cFlU(}-QSZNkX6sPGl)(L5*u&7 z%bYC)0IF=&rT=8zpnR!%`}!Mb7MGKffh7gG!o8;I3w{;YGwBU70GhmSt*`z{?IVda zlq6a7LK|VPO;C>n!Bp+U-h`x4sCzP5Mqv>WfCxvKwC!`zk_obS>IcaYcAnLS(x9oC z?AE+i4IR5doLRs}<9%*)Oh*n8+8I<0IUR@i%H?0u1d7_77i;LYSMi9m#(c?-NzuXo z#96noWvE<&xz+pd0>aPQE6oz$@4JIOJ`Cjh9nXk3yk0fxLlLEoVeKbi`*U><0BDm; zW~EU=q#=ge!GFkE~N-0evozoB}Ng;|VY9jW243I*X}4 z-uauq^OpRK!AH9^`rZ3RR1Z@dZ80+dJ%BVlJ=*DJD1Jg*!1mI*EN%RM4jXZd&HZh) z#OrF~QqNky;O>ZOtkm3Q=6` zfRgXp9=cDqH@1WB7vaWH9X&VIFMoShtiMvm9`NPtJ`Y&*%s;DlV>PKx_PZL=>h^vh zTGJ8zKC}&RI#4kciY~@mw6#|_;K!y1f;2Q3k>3*%U=seCi&S^f=#Xn%L-+&K41$nP=ff{>^r8Fh6=0T|6pq5;Lb zz(c|X2+Ckh>{N_!>oTe2PIX+ z++cx0-~!;8q-AbJ*C`^Hj6;zX9ti(iN4p?Ys2b{ADi{#}a}29lvFm%<`@1Ii?cGSm z_=0emZ#pV5Ag2Cu?R(uI_xJ&p1X2Yd1cC!2P}d35(6`DRD2~K?YlA9=V)2@ZHJ8+w zJ(S2w9Wdof_zI;GslPgUWZ;$l{_{-BYIBg^qM*cXq%I}@?R(6*W0?|0DDo%7NB7W3Q|-$8L5#5@is95LY)Gl zU}yvlUfZ_5u2`HN2lekEfgCe?R_i@pJJ` z>hO~`f_%H`6Y;(4t086 z9V?}dWqjf^8gF5$c?>Rg;RvOAKP^O(I#HWT-LdKC;#*9&#LA2ayPorzNCjss zK+wyA!OQK6#qQvIrtQC&oCiO6(BAWEdEk|xnp57>M4D<*|@E#=R_~) zq$hAEahdi{#%!GRC!E|np=?SWTUI&kvZk@ z`X(d!CIpL4T5HJYLFO$ZV5sL=>iNdNrR(Zn7T?RX)U!T;S=h^I2W@tK{)=wUWo%;L zHQ$W4Hl<2rmP0Hi9e1I?puFR2rDW88by1C`C%Zde3zyp@4Qo8Q74_+70fmzQ z5JbA^*&B}-1OtRJo%2^*TL+h(4#-8=s0s_ce_0RpT1$KG z_Uhg`ItjF?JIZ{MFRId@I@dHvpOYq?!oxtIkWLV+NTAW5pycK3&db=jUlz{5q|t5> zbkbjUIfOt>$fsoPZIUY~FkdeRJpDWE?*97o{=0{9>bHj0#-xn(E?9bYVuNbEAgjtn zVI>qTvr+PzUBLZ`zd3GGql-=eai5@wTP!C~fpZXxB?~TA9d2`Gj&Y(MNIlwkTtfv8 zs{6>z*tLBUk$U+8?>3#1e!)F?e^A9s2XMs1$pZB;r4xCGv|=&QoMS3~GUcs_aoc_e zz$n<0=wlg1bI=`TO~NPE?hFA(!SFTj)Z40({NJup9TCQFM&U-Dj?KGXB7Vm)WpOea z<{kWQ_ZLjS?X+&*?NJ8pH7l*K$BWEVhm-Ra2V09#rsLyOYEY|2LhQOKUTvr6i4#2V zwEO1U+5j}jZDT+7ZYNfZ?8HR$Iz4Uc*S((!jd7sI(M;3+_|XNragT?iiQw(lMdFx3 zuGhbgEs3vQ0oO|-h=^y7)TJ?caai`h+|*KY`XaGp;PX=W&~voj)iQeY(4V$zveJFq zBJniu|9j75Ui4sY;n0V=_8yIXj90)|hb^{MY+ah)-33%cUm>HevULl8=`acUwG5v- zxgki-A|oT?GU|T3-BMFlB9p1;6Yca`Yg-SEAq=52mkIqHheNKvoPWq@CzzW)-Knk) z%$6&pFCv7|gUl>PZvx;qG?E{^Uk;wD$KuKI{O|}~dexr$H>akUX#@AtE^Hji(TWJ^ z+$Hj5pte!;4n+$K{AK(o4$?Cjj0MoHxGfBA0w5$b)F11PI2WBaV(YDJ(t6Z)=dS7j zdMJOy;`gYS2+oIXmXn+EFXkF@RBg?4#fWjFTAmN+3Q9^N^ZApu{uX(yw%`&`+0f5T zf>f^wqtT>VTJN9pAH%D!ux;|6F1J(FjvQ;YQ#njjORBW{QOn0;-}gs=(wydK*=uMd zT`xFV)&g#F;4kZ&{@3k7k}r`jH<5jxcw8_TD{hBoobbMu3R7&S(bdoWO;aBJp1R9; z_&odEo5qQP0VvvmdA%Zke8iXUIgezP@?wR<<0p1^q$GAv*2v(VEK5QeN4Y(Z3)l{a zRK*s*@WwnF#JQAhCe;)|SuQPdbg>8xlZFf9DG=}_|5Ic;N{(wyVqN9I4`~G*MEjcf zlNdiNh3RluH;|2)cG9}oiX9BLv)s>q7Rg8NSBLrkGdeC$T^kOxO4<r1?o9UA~0?euCSZI@Mo^dG9S|#A-@Jp<1DW%`ISZxdm(z zmO?9xOD9(V)2J~`1=8NGdxOJ)Qw5sm0>&D|geHxF)Rip$(~{w5 zl5W<4c@zJSTmOPyPSHDjyo6!klAv7@8#w=jLiUL9H(?obJ zae_lsidAdB78P%luowk=QE5{O_~F?fZf}W0aPt1=V_*LBevj|%#@JQUQaCbS8yY0p zTlYN}C=+L%uod-fKo})Q2BSBlYS?X9F=kzw8+gu`jv5Yw#juQ)aa!|4=qT!hfKnh3 zb&^?d6;?!PhT@kf%8m6Ad*q}>UE}}T975cm`KXgX;z}D+)8$-Mv%ia>LP;=TqIx2a zgMGiM=>WSiZX&sVQ&&1xIx63}_FAnbL>GUXH&6jedNa?;>`3 zp30TybGAj8lZ0B8^xvgwQebT6qb^?>Vq4gdZLx&4S4{yJc*E2&nA##0u=fzuGYqp~ESM?ITL3Ef z3$>)bnS=Yu-+Goe@8X7wkbp%If#X?^)i zIJEvZm^F@_2`MBDLW-d;rs(B4Z+z1|;y!+oxZ9s(STL>pJK95u4G(dd9tL9}+VeRHPzzdEWX-zjG@ZR2&yG1*#5GiEFdS=AT zE<&}ixzJ%%R4`VbZnefN9bcT@{D(9YiVyxVUrlv#8Qc4vw?Si@SBBMu6jOiC+UhoO<6>2xfJ-4cTX3)wLr`4n&_@iN5XQF)>{ffkp@IdDzE3{TdX? z{r=o6_#vqk%kc929_C}Y%-Q5A*evMVY>58m_GRTC57^djEJ8`C%O@g`nyK53F&ueGh>r$l^$06{DEidL*D zMEsSZU98ZQa?17lsj+RJ?tlkDfXUOrJoIlVSHM{W?jcgj?ZmiB(y z1mS$-b3Yw)YC-#O+kCWad^el{_dRsVzdcN}q2uR?Y2@>&={auKQkA$WDwjAy=L#Hr z*Mfp>T&<5=gb;6WxMwk>FUbZw@S)b zTm}e3#osLZKV^y|8FFLAN~GK(8?8C`68{alOZE0uJlMu}LkB5unnpuPJhFFQL!tB- z1?nV|-+s%Mr*5}Z{Y2sm@1u;$w(1pli>8s$C=rQS4+9e-^PV{;1fsXSMR8eA^~qci z7ipl#S-Sr>8AzipyzVw*%@shrFE^1U%|S@OCGPgLm3R>Jn2+y&eQ>vtf^$)qL)N9W zt1r26aWVUhvKSFRtJ!4M+2S)&_v>Woa=SL*>zCN?OL8ORPI|qTMPKFK#w&=&1EP4+ z(|o2q+>bmTd}eqkZVWU}QXg%}TJcxPNzz(N3foT!n}H_hdV-!h@As+kpkSl}STWL|5J#@x^Pd{> zj^i4RKOhPI-;@eO#jEfcHPOwd?J-?f0z6r#p@?$l!Xx&y(E5Z)P?|P##+n3WMDBQ0 zh0L@Gg>(6oSM*VSlIr=qdvpnzqGxN(-PSD2nvP;l375p}YtowAk)_cINJg?Jpq^w-( z37w3TH1Gxg*>yMJm6U7m9hs5GM!D3LkmoBoYU?+KcMm;JqobFjse$Vu`96IUWVv{- z8MRBVz$d9070(q+X2a_uGO3HH-B(S1UUPOf*^fi{fqMq<`|IWBX)(FKH)~JVS(Rcz zPg31}H^&wm=Z!XoSnDtTn_RUIJM$Cb51py1ek&32ROq2{?w>==zUAl%sc506u@mo1 z_1hlHs59S+26^#gdu;CD8*U$!9u;yjgfo!Kdozx~h0$Yb<7u{2T$&!oe@GX}XNu&Z9R5olj zK30G;ZffE#10c3Sv+=wsHZo4j^;EQR?(>_#@l-Y|h|r zmsW8!O_9)`f9T%#N!7?#SGccAsW|^=6cj>41A+ygKyf=AWp^`pANZmXHovy`G2|ixCyjb_Zy%cDEQUx8C=lkvRk&$JL;y{f5u66>r z#e}>bUin$??jZeJ?Kl~i@R}GKLsC!MN{|qJvbwnmx)It}5Z?XLkj;dQ=H;#gZx&g* zx^4;Bn|O8{N&ocDEuBoR+5p3XwP)(#+)3A=DnMHH_XV*G++%v|;v)2NNGM=; z(3p$%Xi?0d`517jCH0WL?J0J4$yd{L&vs=hY)Cn$^X9bZHw-kkG8JY-^|>k9Qvdfy zx7x#Y!em>BC88MqCtUV|Nu&X-6(ylt`tL7&vv(7cDEFe9A3kEn6tGf?X2)+A7Sk!D zE73qvv?YK;z&797So$cjkY1qlru8(+W@$wno=?l_?G!3fKkN^UmRBUklIRhO)8Awy zPR%~5mJdH`RJwxv&T6`1$L4$Zg0`C;BHa)6`pkcWET?OZx{AG2j6ILmRD)!jogXaA z#dvroXJX&uM<8$-z5iT=*&|hYQmYRm>ezGfgGENge->xX?9e1*GW^YYSC);6i##y; zymh12Nm=rbaRS%*1uye3Sltn;q=#Vb-u|2ew2_w6&j!JwkRVvzLv;Q zNLEa&#ej!oJP?<4A?RT@3i_@=c0!}b1G ziCtwhcpEgYczo}zJ*{k`R=Qjco`P=IOuR3+I9^H&nvWg_OadKr(xsj(xI`|ZZC?K6 zz_FxRVkUL>&I1s-C)c<`k~}9XOCO<=6r}ELOnUCI`pF|_|2+q|PrIuaReIOzX8Oh1 z^CaAV1~B!RNqnQ$cNNNw&Y4^8*PG)P6z!FT_QOJ>qK?)0$cc0F(306FI=a67HX2w7 zX0gkAXMbEP9ZHYVo_%$p{x<#f-xO4!C$4&0!Jg&XVM!&x)h$%`ktIW90EZ#6oLzRg z%f%oY2^<&G_R6(Yn%K2fhFBf!W!Ik$jsdNcFtks2H*Z(Ot0g`9wQ$)|GOI7&wx1c4 z`#&8ic})oMU0@q=*`%X+PJ`b?_!mh@E{+UP&Gdcz{{4HaUX0r1d7UZ*^aGds$0!4R zj6LGMUeD@ST0AwW4ePk`Xf8TB+UQqqqt9}}vh(fSdcyKWb-bld)5&<lnGg`{Q|1S_uoG%r;*0$QX3n zMRt~2S1P^iKsCP{{uZaAwHwueTeFM1V#Lgm za{pRv!uy^=t>g5PC~=uHsdDkI?XLIxC6ljHlsfpwOtBwyx*&S4e_=*NUqHuVZ9!$; zM5^oNSlu@0X=mA`Q=iPbp;PZmUhhl`NfFCBM5|ZH8`DLdqwoVnt6fg0@hp*!(i9ZQ z!KD&LIkO&N)Um~8!tH(+-e4eh(f8pticypr(eA4M$Xm)Wr1vKD^ph>t`+Ka?VO$>c zDT1_Xl~=cTR}X9_c1dS~%bSRZOAl}F5!R2Y^`Oc&{lYtmf_hdbPf93g}Sy}ZLC_DYDj%IP7ZB?jHLQAG6UcwYi-q)jR^WYug!=qI`9 z(U55ZF>1=-XWYlu*TeOayKOMSD)g;i*Fwe2=1#lN67T@c1%j7 zp0`^%&#EV;oVx{eXCtnH;rF8-yifN6)Kp3|SWiDe+1EL%MylnPSERK=BiOYFfVf9P zBvDa7#bOJ_)s(8^g>I)$pAZy>#nO5~wfJbur}m-J(%`a>LIlD3(=(n{$E+X%bZrE; zfk4|=?ssT~H-^vT{z-23NB79+x9XTjAOiyL77V$vH!PUae2OHj2n5l{$4skit13BW z55H`()6rq1&Y}CQqF2&r5P^0fW3HKthA~sc6+!1Een-|LPlCwp6`3||tEXsl$B)8d zEy6u}Ogr3se3=6?jZM1!9EUlbe2)D^Ia%l#Y~3xG_1}y(((d&TD4y`Py@!EV@WcKkO>kk$ysSX-Hs14%;%zmde$;974Jj|J2K6rW*6c zpH;{Bn+M!>**?xU_MZGZ5-;AqG}haV%}u4#!nceSsPTZ}`vkPinyUo6Q4V{UWrAuM zpL=Ym^pP{Sd#pVveR{-pJiN=I)56SoBXjM!62Uv#f12W#EJxfivJu7jCCenmN;1+x>U;N3mUcbeLZH@jgp@ ztHB2YbV^y2)>eZs#WFfz&k^KB9hF)~pJyFRk46nuC}W?9?Ax$^@q02Ma@E#p67-`O zpP1ObTNteVHHw>^HQ*cghh0a7NJ5nV?HumZgj3OR0PeEF*`x_)URuD_v`Tfba)4f){SaTk3b zd(CsLstB!Z$Pfd-HSN?`=6QCt%Q;`jxnlnCdpaI?_!rC%3iON&JIA`d?$`Op?onsNguqgt5V#dD_= z8L0@IPXV@6?vTO|HIt656X%s?G})GzsIQ`IZbAaWrF#f1EaNXXHf@whfQcNE^KiJq}TfpcRZZS5s}!$KUv z|HIl}M^*KNf5R}L64Hotsvr&0EpPxq0qHK0l$34+frChiw16JE1!<(DnwFd*+%eKG$bv&wO4U$^?gM@CpjzhQ!$BB6$>yB4p}l z-?nHe2hCMwpkoo!I+MRK#DFPG9pps5EPHr$+^K#xKg0#oNcPtH~*l z6j6u8Alx=>Ur>NWyWOiHB(_hGMHx@)Iv?*7xJ9yAKNjR=N=1PY>TW<4$oqY97JCKx z(&?qak^2bR-zU<;?s-EYR9Fwo_yYylX5}#-#)cp*19RaKtUOMpMf56C=U)p$M>#bv zt2|B(-3w*~M`vnkoV{(-8VU;5lcf=Zmx~Bz27*xL9o|Hhm?Azw%5uw^*NMSXee53O zVRZ`e9Gh;k#&}`NL!ngmtkVyLB+SfrtJ){)nWHEDb!O@PPkj*PC8yh)5@RIn{A43= zJa~=HHtRVBdRV*rtD^glgYPm_4Qu^1b8&{wQ~QkhAv2;D&E4X|tMh_slSbL7MTtXcYyD3+GWZ6q46J!B~f>x@Whb%U1LHUTnhyj)|W%?F3q{iSg7o+eD zqx~bTcw};|-ms?~!`&EZjkiYLV%uZ$@X%k*&MLtxi<=dxIDH7sz6Lcsxo1n%husve zCK5?*g@+uDrbI~*p428;^v^I3gI_&MrQwV1QpO>sjn!?Dc3oTc@^4bm)Yj?PFU?2l z_V#V{-X4YQ-<*YaW;}SdzNDx9z>S+eYI#&wK}`BS4yDWs`|b8ox$k<@7xaPXM%9QI z5?!hWZ{hVWGciLlYlzGD-6Wd$_gQ~7kx38UGGQU_KTk=jIbdSB6DZvWM~kR@#cif* zCJY&V@ktRQ28)A(vwwh_Z3dCOoo0$&pfF)LbDlTH~$n1MA>+S4k`q zhx>_*qD6C)M`Ps9WtsOQ61c&Z6djFSp*Z>EzC4`E96fhOel<6BR@Est zohkeHj(ulh1?DUH3 zv4>5cW@Zz{BR|2@)AxlFKPyU?DoKc{UnAU&i-Mr{n$N|?GBc?j>ebg)t@2=#nSa=J zRZUD)bopa_VoEaRVQUXRX|zDmWQBt-qRn%Rb!CN+qpv^e_#)(cJ25~>J9Ag(YV&!OdSOe zN2P^bxN%O}-74^n!~8);ZJAe@D|waMKj%VL{{2uO?|2w}eLQs>+FskR=O@lt5Qq(W2@2My(e1s9G~)9M@Q$?VAKq+D^|_|&HY9* znd~sH*SsO}$C|Z?mSr5dA_WAPXuQ?f5i9sb72ZVN=2Mia$_aNij459kwkso@g3+DA z@fV1c$*50trB@;bbd9=At@kuLFsiFe!rSjL!Ck!@k(rTD3MV4?X_MF^CQ4ZRB*J`2(zC)|71>_|df7_cg!aj{)Yd#(}Wuu#3 ze_{hI(xZL>F`=W~EGS?rct(|n=m~!1+N!?X+CfHQG!rB8OiqZ9iR2O9(0AOLJ7KNg zW1iZKROMH={2u;Dj@2gNMo6ZnYwHW(I+@Fz8tPZ3@Pcxs{K$KeZkbPiwEV(j;uUll z5^u)W&Of64LS^49(H|9(Yyjae!{(3bXfU=>S#U~vfmrt}-QdR*eyp757WPT>?~JZ? zDhV;@11xObKdg%gZeFtX;Kd;Ulz@dPQ!zi2x3pk^Kv4h-OQ7jUO)Qe=S+_jppM#o- zBatBfe24(zd0n_B!Iw|m$iREFyD)3t*Y$EjFSf1ml9lL!l&CXa5VhgiOnj1oNt@bF z<6#YjvIJuC))hoNf`+0sBQ$5G!e`O?@CmFnMxXqSBgcivq5b|8<9b=5cTX)EUi`r_ zedW{3#fMK)zN5ct8{!JD6kyL+k)8Hu&>K6tq)Q!;!FfKsAs_asfA+S)621OUSmCu>r-YcoiUU{Oz*(B z)_p&}yo{_gl1EJGamFy@?7(Np7FO<&f2Y!hhJt0Pci&*QAgCi!R`p7);6&8Yu6KyT zAg9cT)ZFK-w6o3T7uxc@Sf2H^Olz*x&Ax&r6qfMe34Pt^$ap9ez-VG(_^C~{&0{#G z12cU`0V2c3#Vu1uJ4jfVbmKl zSn&e*eNU=9zy`+Tnc~*E1QLMmclGI!^ zT^GHbGXxBJUh;*Bn$A|aSq%J}=~y$f8);U?BrcwZn2$XEvSub>I`tVdNN|Nh>phxN z{Bqu#5%CB1vy2PwuMv<>(uUe4$LKZ+)m5z1EpWw8T94EGyMrHG7lmsJ9lIKCuT?i8Pb7up~@-`~B5 z7Jst$siHQdwOvlUUq^9#f4!&aI#q|@qL-p~RUa~wct}8*re(v@`>FmNc8E-{P-L|U ztCLHZAhDJ`Z_b*GA>PodztjXmLVSF}51dBhA zhr?3uhO~pDXU$)Y5-~zs@rU5z2A|QcUeo>TrsttKzoY!5?4xC7 zhVU`FTQoD>-N<@I+SmJ4-vOB5@k}{o+CHa+n!b7F?lU2@eQDYH69=0^=n0BwfIuol zwMH|=rR4s~W%Dh5$65}|S@`6`KlMUZ*GPvXyoz3dstiNVrj8dE0#SFnE1yl59}=2H zt>++?@;=u6=f;8gFX!kI+`NcCiwCvjP)xUq?laVjD2|LlhC1T z8d$4P6CqY~O)#vFwoNfnL16C|R)yvBNoA%M!OXINxNJ?Y!=m|$Nlc6)PMBb$ZyX$M zc>xiI)FS*a{PbwPL zBOdOnSMw;Riu!bogz6gUz_1djx0o*SjI8^O-EZFUuZ1;2%7&kL@29LvYsx%CZahRt zq@eFCuraaOIyjB0{Qw@*aA?F$kHDvaH*QE%`Dsw9fyj^wy&M)n63z^w4gaCpm}DuF z?}%^P6xexJp$l5{6;|_nezT)^JYGWRz6<{U1iqu|kJP>7I()Q!rrKkh^4aR@aUl-v#NRCCciBrpG`w?ml+x;);Eo8YoB&VW5?2) zV#6j=OY#m3>oYg;gJ(Hwyp#&W_zNjamCxcl#g={&8CuyvyYkwF^y%X?17Zb!mso~3 zT+60V>ok88_1zJUw(_1Hxo!>P#h;p$W=vcdj>s|p)ZT6R@9cvD(gswESd|alx)?%( z4<3P!AyA40A*6G_p1He?ynm18=rv)|vPdb`ar0NTFu0n8j6vfMw!M+D1><(y682oR zC1mYS*0;mU`ozvI`+~^kywb4GGLeE_`zO?VP%zai@Rcr=LUxC=r9j@6oR3_{#f4Oh z?9NL?$c5P*X})H4>9FT`CB!8>a?Ay=9ZO4$Xmy6oh#cpiEi{0#V}HNoNLVIJ11+ydA(OPz zT7Bz1b<_!&XH<0dC6)3Ad-})Ls#y$?pY6kfKi~Yos42|(@RV(KK({5YJtSxSDHH3j z7v~*oQ^r{hSB~uD>K-aWsv=4TW3kM&6@H2mY1b6}rgGRn#&>lX*|9KB_1lB%3v2^B zbvv!c&|p-CZ47nq>zDz#G^4DgrJ;83&C%0H492&JaJRH>{1i7+vV|{yI6vwpo;%@u zQOSR@4)iAo4o4v9RKCt0C^xPH7tGh;yn zXB3iZYL;UV#Zy*!g_gv2DmCTt4Oir`faDAABo|B>cFiflhwHXRT7F-BiwuMA(~wLt zZjsOu;n*C#>vxouG!71bpdiYP`FWr} ztNN9ecY{ho*n1w1UPdH_hYQ*E(#Bp+c;sk{0HK~3onTr+?8#X~tNCZvCN;98Fb7B9 z))ke289Bsl{H&aA~g^t^k4LGl}Y z2fC?nbDurom59Jk&!Hx^p#Tcire!G$3k*kt+OlVo3D7lY3u@XJN=MwAt0|B9e0X!b z(U+n*r0l(nQ}A#3HB2 zTEEXnTGR7;#I({NB_Sp*Ceu3Z8c?mBV`M$;7A8nJTz@`&v!6b04spfKNMaA*V4?Ed za}AEgA}&@(t%iV(eX6ZJ?_9aqprcgq&bZ9O#Ny6^(iK}RG-Np8JpA!nt!>|_q@3=c5W05h%`9naA_s9z zG6kzU!e+0oFv#bf9!3~jt#F|oPlV?4aXEO$rLBtznH*MAZPpJo*j){5T1AU>9_)l} zHu22VytA3!M_^Vv)?PT?$-CUl9jK{EpD^s(LAY+u>CH|CTo7(w9hjgciQE`MOK!ng zRSIdME(>?Lo_QUPk0X2qbS{5B`-gF7Zl43)Ji#WJ{Sw zcpE0h?ddF0W#&70jCLY1|D{Y~eD~ri>~2-f;#;&bvBsLkC3}jJU)~ze1sddQ30{l={E~T48NDhSm0$I+6+atLC%$%+(3h?kW;Dl*(4V zKbMn^^fntWR^Rxm z;`pqtX`md&*I-p+li23HlEp$Rd@Q3&V<(wX*w|5;NWyiOI3pJViN>H)V+3RRKhSM) zkEACXU&yz1U1dvZ+h)4)1P6*C>AWfQcnpnS@O1KI_RvIYp6elco={-@+C(}v!M6*| z@cs#-IpSuyUoA6B{U%sEK={ArnG(~Qbwb0ziXOEVT$E*XbfQWvL0E3&+=Z_|t%d*i zqKrV-y~EMAoPn7}U$Z(ogIlBtMS-+nlF@`0ZeR#)?#lh)A9U_Hr)??${->1Y9~lKK{>Et@8S$5-ATR(EPG~egVY#Eoc`1JLS^VR@@2MovoJ{s@AO0lEAM=z?z}TDl zJNSDIJ_wrAE91{{ygwCeq(8=gfIe)VQ0@X`cxP1VQm*^2js~54Iu&O zHLBwQi_4+m9Z<8VdKnffK|_^d?|+^QGzn@wx(Hq@derk}TP~bHK`s~Vb^KNv zSOpDHU;s6`uJsRcI}t+(WaCIl(Qpu_gr!12E24D&uWR+=A-y70tpW+ z2DX2%WMcAm1yh*7jm8D3e4y5#!N>|X+Ylq+SiSbA7oxV zmAdHit6+PXLk%84jn|q9)82PnxOqRqoHX$srivOPX!)Zgu=3~J@GeaDot>SXx3@l8 zSHoa^1dTika`#eZr^jc8g_-3n;0fr8L>5?CvMdozGn-1!BwAk9{S+lOQ2v+X{tYCg zkPaoAf8~E^0&2vdP;H6-kRZ6fV&fkoN8Jt6iUy&hn1~A<)b0F88d6C5|5Zh<0iMtV zP-~4n157LAUlRX+Terqgens**No@RI%>Gti{M8Bjod|TT3?-NyGcWTuyzd3TvuiEw z)~8c4M8p!>D4y@SuplMkIcVMt4-woJ74dg$G!3cDISRjQqEw48i=(&3@SyvU6>_B8 z3$TSNH%8V8wU%Bd^Fz5Gj88o{!A*D2cswG?3fR(B8DXuspeuER#QRn4)}I9_@X*78 zl@)*^dqHq9C%tP1^fekK6W6BH#Q4vdh&t@Yax{G+pkZTcCrG-0qO1GE_<(psDG=6F z+YI|6g}rr67-}Gw)6h|u?7$`c*3>VT%oL~BcxXGOhB249^6i{;YoZKcndY0S$+y;sQr7@%Afp$4czL&y@~k zI6F)fwnT8VK(c>{0I08Gqbw*Gs$VpP%E|(+xq?P%fJDviVi6;JOk}_fZOV6vi$zh! zMNJGUSQrcXPkUy9obIEp&zKVZ=VMT>L}`{F|cWHr|&^L1?E>%VP^UpxFt-Kf~aQdnDXEGSFJ?ba@#@Z2RR_Iq+5AZjn}vCNHcwu zm_k25wc(DBfho~`=5G8qIz*5PDpdP}PniddP|nY!E3f1lgurpd3rDLFmee=l$m>64tC*058zDRmVqReP~{``deb zdooe{P{@C~7%e5I_9)DRM@-De+R;R7P-Jxrtdw3U1nU&*=NiHZHBkZQFkK>S&v>lVz@sH@AYhmNYL!KDzHhW%d$4gy zZ#|NuH{EN0nDBf%Ix@21^mOhzN9g8?x8CD0RuLt31yqPV!oE0=GTN`mmD-GS^zL=i z#qezJHNiEtvDv#KH}>y#N%v@toDUX+8vj zt}~V*TmQ5I7S{HN4b=Jmw8eBUgxi1p6ML!elm@rHkjUgV_(G>+_B4GCb1!Pn?^Mg= zoGmcd@N7w^;ef1@?$_mtfkVRvyUBGkmegH-0a;4`&QjPxCbX~spW(AC!F?b7mEA=!Vg*XKHQ3vd-*7{RAK}=Bx+^lj1 z!0(%!@`0@d4E~Liz8nhDMb~t9hw}}3iU(3V)Hn;%Sn3I%OqfSWoFo~SVj+R9ZW@8D zzx7mo|AgXG4|p$-reA)u;trUvbK9KVubPuw{u&3Y=_DoNDx6eRcwTzP0t|`!&I~#- zO6&w};-~+0Stp$fT#mf)aJ$I`eE38kuvIo)Wq-YgHFt|iF1|iJ*XVCobX%a)xX|Bp zc7OeTz%CFu*n6OH@kC5iZvSdkLWp+G^ZOw8!PSI$G#Jdqo1;hcbwE7hr6#vqFVoM1 zdeaF_fg%PR#1cwwCX+kPHEt)FyEm;V81smT;2_f+Z_^SRmk#RkPiM+jVL;(JZk^5^2Yt)YHv?d8X`#t+CgVp;EP|`%yQ-*{q5s~>=Dukc zYMehBR=J+-ucqvhakwenV^-wUhdVdJeM3R=>?Zo=Jm4k1g4BMu zDrbN-(92XI`-@y)5Su&o0av4?8^_)zms6ushoL5Cqqlq1Xz91VS5;oUqWR_HkzjE@ zB4XEfe7E7uLdqK~xpr=k*TDcnH)-7G_T7Ieb*>?G4b%<`d388&caK!+W&@}V#p3kb zc}d1u_qhMsquXQPA0NJJ;G0Xu3`QAd+mN_YDmAA%p2}w!o%z2VubGlQS+u0&Y44Zl!!q zX~#Q~R|&7gU6tL2@&29d+1Z`#ZNxUhe(rMFJx&=R%vCl_E4I@> z?$mnsv;8Yx(-bsD9L2o;s~ZXhwa1KavB(z&FXPAAJ^8(RPQ6y74=pSq5N`2PJYu;{ z$nAK*jXrZ6De>T;jZMBn6x}Uk%Q!6LzW>!!p{m4rTjMoW0_QChT4g_1W_mN@Y~E>S z*t7!K@8)haREC6yayB+zs^kveKB-4=SqMR2 zl*Ew6%KV67Lx987iM?hVs;95xGH$NcS?KBcyfrfzUdd=Tu$%0R|Y)aW(sf2 z5U{QM8nr(s&6r3^-07??lAUd}o_cBBn2M}f?XStiQe6?7g^y;kVSO1w9-RXSbdjjKx?Zltmt2V;8q%_; zq=Se~nVdoH%c|hX9H-bL`B6tpD=jU)o#?RFZ9vI`xe#x=F5g-(`e-z{I+f7cZEjr+0j;vP_>2+fguz!d} z=ihhxq;&kU+sZ_If8vqsJwoHd<=h~K3A>YImlcy}OW&*YRlXe6mnte38xg86m0oIS zsDnNCJ?Da>@w)oYcjvA;lfV4!>0w)ErTE)GZM03F^C_M_K-Bz#KYex1d+}DBj&Sg> z^lFU-i;%XYpk!yfdN(z|=XzqF^nI=G+0P&BlKPcz*Wb@kulA>LTF@I`c1wAqv+IU_)PEAGq^5tMTN2l|*&PCJ-pXY-&Hk#5c-5R+mksV7* zkMs8%^CZuj{aQouZES7n#I0W|D0H?)ORPHyr=+Bkl9HtRt>k0T{|>n5t5ucQ*LA{4 zsz3>6XcNhpiROebD#|-MI^>q1i$*wPJo9?fT)2B{-d#?{zU?m7%EMV)>~pfSD7@p% zzqmD7ZgRC*`tIH4m$*2~{%^6#$+gbI4}VRn>*xerLH5B2dCZnQWo5Owj4}#18#ei~ z1w>O`?jm*DUdlB-P8vJCE$OruGx^539sv%UHlY!B)&24MRXV@(QC`qN1R3b^#caFt zOdsWN_!2iN*R!FcB=X(E46HAge}LwlAfL&b{0fhl_Z5#-^05P8G?CE=x*EIy^S^kR~DKGAwu4X4_q%`Ly^zoSvL~ zdTMHgz&l1^?QV*hXFB18Ug4;>czPhWXl(B?RpiuLTSBhKl9B`SYe$2rFErW6I-MK0 z&6Gfsum^3+E+h|ms!zh`(ay|dgD}6ZG6JJVL#rlyER2SH_`yIE)pSt4kAtiK{TIz! z0$lvB{QvQ1hj-o$#y?)4IjTK<;N5U@`89voCSJ*6>5~1y``{L*LOJ<-%?-CY`evel zL3Di5uvBUoGT%qz%<^(n<( zf8dKD55RfTF)GjBba~ytHp`Vs|xoo(1$J!4VIqn*vrM z#rwzdMx!MUhz1X1o1Pq?(+WE^e_kJEikAJzxRDQEci))(%5Z5}zZ;eg8Pcu9z6`I>v zl9KXq!ofg$4#tJy+uvUne$W2;v6zxFf3DY6v#HW`C}hB+7vx|OdwEgY*x2%3qn@6c zRLpH-X}3u=u-3&=!G>R`h+HMHFee9m6=EFyN10i}+sT+;FzlAXC@4Kv!Vpns#fiXYR09gb+y~ zDcbX_LQxqswDE4Zd8fk4>hbolRU33(A)2;&(vBAnKU^JDhDJNu*-cegyz}w7OoC?$ zM~S)C#6Z)%7xqiX{Otu(v#ZHJ_a*i&v$A%t+t_4V^?sILoZ!tg;u^2Rr;hAMP|L)< zM@W@7zPYinG441)L2I8RW_5Bv#vX3H_g$Kjay_-$F1|-mSvgtQ-}j9=Y|?JF!N*bA zp0kxlBli^@zqP5ARqk#{GKgmyIj<6WmxGYS#l?raU6`kHJ|}jQYw*kww$TBE&&Auf zOG|G@M@CBY>bV33-CKUwvTK(x!Mfv^r|ha0Sw3ZZ;8TiQpY8p4tgf!UkXSfAQ|3AU z&-WK#?KGXroVW94-luWz1o)zW+vq^6&3WeAB;Tc#<<#~G%FzUr#@#s@U)<+NlBzao z@~?`DlDIt4(bQatq>!}LL?1k~uvm59ouq!P=~I6`>$9U?@Rhsi=ueLpJv&*C-Y?6x zj*cn{gGT*JH!CX^V%B)2TR-RvYBIN736JcYoUaM#h%y(U!NbGVenmw^OTC??ZjCSk z^4VI?SV6Xp`7kq&vo#&S;7b#fdojWq_W-wj%w7y5h1cv#IMj@QMjQf(Am^pOz0kJ zX89`Bwn`U7ZCx#`N~>M}!qI|Zo7Mj0xEP{2xLN&yVs?Evx%kDGz?1Qjk!N_yAOwNH zY|lJARXRRxR~1ON{MPE6zN!(1QGiYVoM}PV{pPpG0X_BbLLCC>@v$;ICUfoRf!}a5f^TUFm^z*?S@3blY%ANRuM!rEaDcJ86frW^_iDUslHYmi)boOO8r% z(d(yd>}*2zlRZ4Ibb95StT16CcKjFg+WN(U458{GwY4Id_i>?&4aQ9;n{L7P@V|+A zk#NVw$EQu#zN==yzCjcLbOwv*^?!VQ%&7;E5{_>3Bg3?f%}vY|t7>4_&D-~MoY0z& z7xq0*=!J!?28up^K7u_`fLg<0cir5;#vrQ=mga{GA@{R1#Nw5nY?ltd6FHfdQ_RKhb$zckSkEd>B(;@7Vg00Am1_sfRiF~V{>a*j8JZmx?x;&HuH+_hbPsg({tY3qEM z9FmfvZz3X?dhKKeH*jq7soI)ZgWrYlziHd+^Y@cFU;0%#Rr}O6 zsMtLTY`Mv}`U8~THWFkAO1<4Z`n4Owr0pzLgX!xgaDcX^o^DU?HU{MVwC?f9=pi1O z11XtpW`*O;^)`O0V0Bd$FCL%$##b%+fI85-WpeI&u3eJ9M$ zGCOy7Z7Zu)EP5_7MUVU4GTrrB>bm-TbQI4nrPpMZiI~Su4{K5I zOM1k6X1b~?$ig!Hrp))}l5EuSfjk}yEaY%Cb!z&y?Ctu8U@Sj&#iVd@8h4Y(mTetY zEw04PV8X=kAYld}mKp{0u;RxxpZ3rnGlj^&CnkpHD} z^LR_jX~?o#h%z!92M01TF~aXT)ErK^X#VC6EHhJ1P24~`AvM*!N>^R|i%zNDCVN&x zgT$0+l7Nf%d-d{H9i(dR+P8d9vhA5ki50Dg{hmDo`v4>A zgaRMF^5yR@$Xh{!5!=dk+wFq=AO_C{_j*iYQP-NEnVE~P6xWZ|HOyg|e$$u7 zo9v4gAmo@)Fh7z=TlI?WeAMt@Xl^4e7x>?YoZmnu;H;s+M{HD5+H{&;uk!7wq=7rv zTQ!G7gU4TPmW&N_guMPjBIPxF55C@}Vc%T7*l%*p4~1^Ihv{clO>P6vare<-+!qp& z^x<_^dGm;hrrSfRAWRjAfI#K6#}?jPC$g&|`4zgr#m(5ZiRCPG-l5v(APWbwwC@dC z*Xv@agQ>6Mp;tPduUXL7=N}@caA9?_3Al;@MW*Or$3d{4(p%@`mkC^_p5lHNZ}0GD z7H!cC9`5fuD~5;1$B(MyvVZBavOEzpQnxMB<$U-~!^H)_%*HFVy^-SlV*EU&FCR#M z2O;K#-ycyBS5{OA3J3^LN4keSLf&EhWimHxrIa;InPu~khcGx7WeJZ{5nKY9XCwK^ z!@0Cv92>(d=GPs{X=!Q7{rz*yXLaeGjIDI#*JZrC?qQif*RY8Ns8dI6-JGIj=&D+@ z_=N<*2)~23sri0^s-#Ks6__rq^F8TSRNT%vsTg@stc?P-ljSZg65F=kAH{PpEAwUbHWB&9;A*}yR842;AGwi97 z)gQWOg9ma^izPoG>$lP3N2cZ)8t~Z6zm&AZX{@Xb=5U#~Zr3u{pWAO~jO!jOP92`VIG+meS zZYjY=g}}qkdhOD;hT$7kINjuHSP_sv^t)-_*xD-kP2754KFYApS1t*b6<2Z*8hZ7c zcu?x{2q4Z!zZs<%8RzG*cISS1%mL)rN#~VUh(IYLIHnz?h#yPgO?~da^h7U3-yi9Q zRhkbWrH%0O7_iC6*~9QCIdI=7u1|*CUzyxKiDOYUnr09bqSp8l_w4U5FvdGV!BC}_ zFR_+Zn32jf2Jzv>s-+q5d&x`^`pWe~c5YZERN-{{0`_A0m+<1W(y(nzV zticu^#Bi1o<}rN}W42px-NLl4=0p}7z{u6<{4Dvi1*O`9=!~cCwMLL7XCIl9io$i` zgCtxce_|IOadfwRnq7mK(og*Ae+Mmpg+POR6d*d4Oy?c!rhi<8R_Bi8);`+$|-wYIm9h^#%Zdb_@By4VrL%6dMKF?De|DDIi}v%H*5Q1GNj zF&~~3m)2iy2h`8dj)RyoHFAC3hALA2M+{+Cf8=ism0XQ%%>!|8#4NB{e}$aRMKv~A zS0&~|VmKg-#OYMuy(@I|@$-`f6})`;PDA4tm?!c}A>1iFvIUwY=CL!-^!R$tENx#UN2cOA3O^@e0xVTHy5TCCU3iq8 z3a?B1&!G^PJZ=fIPh$I{@pS30pQw9%>zlH+_DnD(9SBT!aSd^n$6?wU$c~QW9;ygXG&2V3`p?44)S2j;XJ2gS-I;yCb&i z2_BH3Q$|6OU3;jxXsv9Y^$Kx+Tky6c5h>)(J3F;O5tA~kWBN`B8TtEn!@ZV$vmo0+p5*)w3?{a#dv)-V zyUWx6_CqiTrjFJBSEW!_$+-c$lGyjKxAt(AkVg2yLCyV#2QToveinW$NHpUV~t;^wavVGcg z_C$B@g`bE0t;+6F;%2>3Y*3-KgTrj~EfS=v4pq9q-Mniw9v^*AT>k4{P+|%<)6h7a zZ9bO z(#G>4%y1|n_34?T^_&B-+??!)_c!(YBR{dg$7elDFS?cw0=b=&o_Ue94y89-Vx9og z+&sQ#%)tGf^*0P3(8 zJ?kJkP<)+8N>ZTnT8k8#JCNhyR&Qu zh;(-Wi8_g#5-(!lB+MKJ*WI)J9C3XiV_hoiE-wn;2G;ImB`e?Up({rrn_%IUzU%%4 zOEtA{+i|b-54KKj%po{>QNO5hP`t1BdL9eSf5Pc57TSz;3;lWtXED*<{K38gy&4-? zuXYjMEZ^Jn7NJ!W1HK>wk{CYRb6);Fg{u!Hqc&x;9+-{JCQ%#hBIlBL_uQ)I7Kve=lan4hDsfvivGTi29 zC=hZtP)T}JRw#`_@M6zlp2avR&wUz+qy=EgtYB?pf-v0(eKHc6?ymLnW8ts>$D47% zL0Q~2qsQ#(UFLiY>?5P~Oom>*j?p~AK@5=hKkw|iR9@pJBcN~H03n5ohK7RkHFQpQ zJC(t=wEdQc#d8B|*1?l@>l+S1)02eU&uBUU@{Ed#GB#>I79;UWAGhXjSoqn{Z1ul%o{_gbxZD7lq~UxEK<)O*>oiyKo61eryj_gjx)$6_dJg*QhTeLDEKfIOpVmk zg1NE4O_@w>uzXKed~oh4LHuAZ*aK0fTNt@P=1eVVx7LQU=%6$Tzt<{DC^@tZwjC+M z!NIA1QG+YL5=}`8_xOPD88pJ#*FkLET=S9P%9W<8jeobiIHa@K-7#{xd6Ou3Lp8hh z>63G)pLuVLUettS%d~{8ta*z>^&l>H*V4(^tE(JL!1&_-V|;~;N zA%V-ptW1~psl=PJpJpPHdew?ns{_fj+3*={KBdPbZ*5`IM;BkCDj1_a-k7<+t`Is% zdsu|&;P#o-3S$9?teT3B5%jTTaUYOW$Q&VA=0zhe@=#2k%SuF!x%+O+h<;Dg$*54dy8NjHIvDf~g+6 zvj!Rlh1!K6Fi=vHzvHL!N-r&GbX`~P|8w`yRn!QimddHsHHIYsU@AniA-x)lwq|xD zeEi}&APR#SQbLT9jb&vv!wJROg~vazc7T$g$Ul&W(-2@0116brIETtWUmlO%veF%} zMIH-n`(QLa1c!Z6O<(Zx2ZR)0P&s zx!dW?XZ4Djhhco(b!YO|?acWhMbgEQLObl}af6d>=$ET&sw|Y7)Dd{QppQyBY=u<8(_nVpjXj7I9PrKKZHOj*|Jr+}OwwzLk#qx@|R$M`k*+hgtqz$b*f=gyYiR9;>fy*IM? zM{9dKOSbfWh8kOT`E(#DTtij7(fKf8WyLaE{rt>4n#15m?W;WLUI&=wbf)oGbNW$n ztMjhOlEQN1Yd3jMZ)YTB1DM1!;qHj07Gn^~{WUykX{%8gCGx7Z(Y(v_B(60p5I@ZbA=dENXNo(j}x#+(wGS9}3rM zWGsDFi7McZ5UC#2`I z3E7m7nR+Ynlis}Sv6L8CJH!%DUglDMwHc$=Etf$Y%lb}ywY-cjSHPa<(HD)37|%C| z_?<%hoGqM@Rg$Opk&6s2^BiPIgk>5PS<}p!gQhCS!L*84s zMHRjOqJSWX(jeU+DIncBgh+QI9nxI`NOwv%NDD~E5F#bQNH;@w3Pb1J`2C%GzUQ7l z;qJ%haU5Z0?{}}g-uL~)TAp7qwhj+Z82C=vZky>h6gC8f>;_vaQulUFgZ-?+1A4u} zd8mF)Hxz7jUegSGBKb35z)!_tAii7!I)z9y(OYJ?yg_d_u>Te(0+GVc_(l6##q8?& zU(64{^irdsE3}!hQ8-v+4RD3?pq-~A2&pt&F$@s`2_$5 z0&tr7!#MTQ5mvp16}R`h`p4}IQ9l8i^Hq;RmY~JdKwkBgwdQqS^g{}pUPFHM(JAl~ zGj?`H?M|O(_6_f+^rEM3x|51KxlH0L>g($Tg@nYeoXX|azGX}R(xzJXg$w8Pe%!=? zb%B5azw0Q?O3?>5pw~qY%{H6M&bEv0JMB)w5=b2)eJ8B&jHcZ5{|nUtIL(9&A-i6S z=W!=i8e2_8MJhV6CWjhnG58jCiAC^QF+(^qLMEP>kwxh8Lg<))Tx8EJj6W1@rxX8< zmWvC;T)-^!SdD26g~r?za^AtE2R=F{i1z5^PPgR zJI(G6;dIQZ64=yb%*rLYmezs_hd3OnnZBof$(E>}r5^@Oxo{-q&ybrmWNx~E!kHV& zebe@sKPyhM7lmJg(PF4mgEbFjBkRuD~}#7$x5!<3v& z^v~MXBj)uHdLb#YCT_a7SF>0@?M zY|T5WzeuqVt2QuL+@^h09$piATaK!YJ)}Dkh5}-x`bpE1?!xef{FjReV!Ez=fT*XxL_MI z6zukK0^|Khg(7CX&HiO(avC7QjcTlbUV|6XF=(w(IR%2#omfS0wm&JpljDgJ^ROpj6z1E{{V+K0Jk_gdUYu45lTZZ(7N+W z6(Av7{>s_fMj5bqwi?n!0qPcf>E&FH@bzC~W*(5D;^Om-@(HMn8Ca@F2E57rt-QST zqxr*uE*F1pvI{pa#Bja~0O0^$(2(bcaXK?6*KH0PQ=`teloU+>i36a(v%z21Ha1LM zI%9KlHk^$g=+E|Nvu z?|}7r$Hx9Q1cXxcci{z8l!P;J%E+4V6f_YL&faA!Ku9-MfAXaLUjk&$>g zCTVCh5ji^o=&t2o#4TnYjE~nFx-+LUMj2Nd0kXOMg~Ewl1EsW?eRshe-Ymu6t|%k3 z924vt5h1Ia1i&0WkucBcl`4y~8L=+~a`~WctQyJ&X7QQ%tkT*?DGi@=Wows5TSJuWA7vlebgGbCu^)rU?H#8P{9W7)wL9q3P z27T@_kjk^aWazEp-j@85#f%~I(VijoQ(9`qz!u0oZ;6aJZy~}ZI6U8aFdNP&+IUSX zMdQDTi10%(1Q2ShSYB=2`TbvD<_m@ zxw(r5$R=HH+AzWxvR1e2D3&4OfyhF}oM<0m2UUE5ILN#QJsq9!-O4>6))7)yyP2iM zLTUf)Ovaw+5%bLmOhUlMb*{A+2F3QUN?EQoWrYj}Tt?h>WNyxJT(XB_}23OWXcfX1y) z#gaIyAa`Hkaj>T7)KnTksR>^WtFtxxUgm;fe`Y^Y%hKJEMu6-OZTk0VXr}iGB1vSI z8JfBGE8@709Ia4}Tl!0@In_vYQbCD0?V#Q$3K~^&{zp^kRLv%>$}E;hIc;!u2+P~! z3K4B13nEkE#C7RZGnA1OQSU{y)x@UJ{jJ5gNHN*Fnj-mM<(Lws^xhg(@hXJCi zss)cP#_j2;smy6ZK!@`;hg5dy9uQIjZ3%koqHUv=mX;!!*wN3>XzI)V69kA_n~v%`kKvuY4{68}5nt6k zAmH=NM)(#qHa>pe*5OKx^i>a_p_#Nj{I0_alev<&()^uZ-&t|3rKiUmaFh)+Ax1TP z8>Bf(rCOErh1mz+R@h6IvevmUe~cNrNUKs)q|C5Z_+!ysW$ zH!avx$3V3fJz90z#HI2an5wE`BLyJ(mR#Q4VYzzf{J;;S3nigqtID2=XF%~2)PWwf z?QF0vjyJS#M|BshjUHkXFQ*{8_wkR(I=NPHd3S0$?e}(l`<tYVAUX5;>5DUa(qyApd#>!QIFz?8Gxk++3X3QJm=O z#WVKh_F=EtsW@Jaj4xjzPTq@(qNXY3HKKcS8i6volUUhikFb7@#u=(nsGdeu-_)NA zE4HmZ;Qs1`ubLXOdUg05sF6{gklCzVfR_Z68H$Yj*5_-)}#^>>B1Rnk}8bId$3jqE4SkDWr*Xy=T9?cL#xqa?4GOzAm zYYM1Xw{yLJPcAvwcDXc1$d~(E_igLO@$fd=E!QfsrJ-_DIre@@ot{RkWMpM-gU9s& zEpSlG_9Z31HFpzH`R3#<*AuR%jm^x=ED%Ru*b^%4x$HggsiqUiXe1=0EX>Ss_-S4J z4ItW3Dun~>Z8;OuGgsGm3K5S+*riWLqkCGhFC#NEi)=h|f>Mf9cF%$xAq#V!?*&uy z5NzIO(_A~xsWH!^)e^V@5Wo(wFvOI$MwC`jdPzRH?CQriZX4+c~dx1IwI_}+<}To zA-G1k{VClMPy_?QwJ!ICxauXZho7N$ckMI&XY!hwDeRNoubw{}r~?}O`%4(DS12Gl z2n9-3CAt&4I~&=9Jnt|8cW#18?`O z_q(U4j)t|?BT%*;iijm5#2T4aG{KvyW=n-_=3t}MsKI6QIl?PVq(#J~a*W@v z^A~4!CD+55Wf%y2KDK27-!BoSb!lH+GihxMjrdZ<P zo*Y+w)Y;gxt$!10FlOT6g-Tzc|HO+s?n|h1nnIcdqa+$=W#=urbJsArFn}@_OgIz45wU!`LQbj zkT5nc(4t8?eFm7&D^i(ipvb%g6Ik0R4ATPKWPg?;kVGF@pFchq2IPQw0j)O`%oq-0 zBXEj%1~0z&f&EJDwgiyv!j-ex+t(ieX6MsRCpT7cdOa&CXAE`GsxQQV4GwF-<=}qR z^PQCxo8{5St#2l2<&E?>(=tM61}S1Nk?7A(=M$JJt{R>F2RXTx{Xc!j9gh-Md|}zo z9*$b~|G){^JBtpU08uN2wX{4x|C*rK#@@cl(K^8hz2!mdDiK?BnF}HT zq8=f5_UHLMsZ(Lgl`RW~L%=Vtg+SO>R6lvK=Ee+3|L_lVZ%;<-Lq{A!V!{}s9xz@K zWv;l1r+44{xt`*C`@%tuF6UH}q@-;{{e}YvlZ#Dzswon$e|viyaD@~s04VUxKke0k zxrK!@YvptqI4#6L(}VUD=lWtJB*GPJ^`&OH+%6r^7`vw^qRr*5*h&6%kQl+E4+Fhf zTXN5Wp)KbE+vYF}B()Jqe3WZxiaj+;4c}d zhC!iFG%DbvLT|FpcR)^Z2dqZ`2v-@qvozv?*~9h zmse$PPaS`BDC7an6u1WrB~OecAjwE&)eUO_7-Dg+Csw4IJx56&=p<(L$+_A-_WoUU zX>ETJ!@Spa0)+j%@{OdcE`R|8foXJM(#4Y=6ld%U;-To&Np z8}HR@utdBbJ7EiHY~EO(QFc1EMzWG~QqBP|322G0d7qQPp44LthyEv_R(QB;Vg^k= z?P{qUfLLHZ@hwi|g8;ZBIW{?I0N4!yxp03RIk@0%4d_NdUnguMtuMY27c%0iy4EK~ z05%9}v>?VP`OqK>-S~mz)J#Fkv$C(fpzQ{b8nBSu-1$LP?!~`0bZ*bweo4lMYlE3I~)=CWb(7;8zrU1RX2do<8d#o>+vw4N*C_# z;gK5f8Bjvr-B~??K;h9*m}LARXwS~nfQT=Bjl=_P1;llRf(!;+?Tz>slQz^>XLmA~tTruGGl4-e4L`?aj8HGwMM_|ojl(8WO95L zP~AUuuI_DD8-u;QAe!G$=pYnIT^JXKnT>>aW`r5O4p^$-K%|H8;>B*pe#bkz0oVHD za^TevX)Ghc8EdSJ8D|C&jcNK1DK_gNMLLl?nzPrclY0#!?TZ`=zvRLEad5!upl@ns z`i-3Y>L-36WyMMn1%eN4W#8WIaL?jAr9Z+-IL4E776bQ9BlQc>krQwL9l{+IHRQ>r zA%ccQ{B&=DQ7=b{(5SD{>%71HH@tmd zy?Y!P2#c7;zlZ;2tW4E}jixPuB%%|`3Lt_R{lsk>@-&zGm!+F{7vZ1;=887Yq$|7$ ziy(UQH{s>H3tnX5?B>6_HDgc*pwzn!PgXdxI3m$40^7D+T`N2NuykqPF>EbYB$Jzc&Z~0s?pu5n)uizfg(=wEGB7 zpCtcTbR5dqMfK0w#U5?`UI1+UThbYzl`xz!IIW{U76YWc<;Ur?G7Cbr9Q>m&3P)RgoLbFAg#Q zVDZI?GY}c2QeU9!N={C?`odjFny%1+R6pH+@Nd(Ym5tAw5n85p z8h{(->$;FXWoyrSTl^vIjWT+>zsbX*0MPlJ`P^SJJq~A#8{Z9$INaA>ZPq;84^4gI zU;sYK2m4U%ilap$??|b>DI@Ki4cdHyw4!M$DPGvTJNDH8gqQL>$=hXt#{3h;_K+VAK^!(Ac$J$N+VDJV@^OnKer;){vh9v{iztes%Tr6V`TfZT7bzFV?I5#!ctajJyv4d!l8%H|z!j z_@<9fCAa|tAnE|dGn)Y$0JOKY+9%`!iy#2vW8Ag%o3lZxLT~t%-E2cf1S_z9+~uK^ z4B({=IQ#v9viG@g84O66?3Q4Q4L zvQhp*Q2;o((e-~VLW`jetJdybWR_gb%!e1464<=DNfd`}>--{r!Mz$H#}iMapiPPyVWj-BXd^p6wr>r2wax=;iRlObvTZ4&by@ z+TDJdmo+5|T~Jl@_ci|RJE zZ>d373u(t+t73b1ePSfq^1Uy%8qG)4)SLnVa|OTi&z9@xBS70pWC~>8EEFI~12c7O z5g^*xVlj45(=@cVr~7gbR3+&G_wjA!h)d`pV1HTEVU12{8na)-*tfSEQL2 z@@>eD_wn2@U}R(jZZBY{#tGEx<-|bQe_U9|t-avi$LIO`YjJVs-^F^s6+lN*Ix*;+ zeRehO555(3dIS?$11CX>1)PNVh%1m-kbb=VXEPu2=A!H=m@#aXmaYSEHekXzo2^~% ze0yjaeWqADq+NY8#qR$wTNKZj66LvkJ8)HN=6CywjAI43%|60LfZ^J%PZlur>{hhd zFL(}T@Jw8eG=7@7zghNgwdv6-owx=D_AP}qNx_FSTT7+9rW?4jPAYxa68M-B;E8By zlFPy8+MmP>8-Ln1WR=V;$n5=E<_lu=O&3AG&hZiFhRm<&40_M z`uFYHlV+|;DZ1d!XsB{$3zQXexM5)=bB0bso5YBl_$x^~=ogw%d{Du=R^p!LXP3NF zvT!4;cSfJ_I)ZixM1r)jBTS?vu=NiqN)5Q|ey%(`8;`&d5EvNJ4V5P@p7t>~b>03{ zQCZ<`+xSM_v9>i!pS5Z$?jp{kv_6P!{RjhXEq>;vM(8pm4nQSKiXN za(}*6I{^hba*1ZKj=RKSJE$G~tK;D3t>nE9Oes|(bEyGNIn9>AI8 zb+)0Be_Y#-6AJ;a@c&hClSHZ|`#?j>$(r~p;?=ue>`2xgbRZIBw0~Jy z(9K=jcvyStv(x;r)VZ68~G>O!zbcrAdd=U^J)&2Gh7blVq zyS5N`DMy0?uwZC3wKVVOaDi7zRGit2_v%zN+ACg()QOq1WjfHu{OLx1;Yj@R|#R;o$w7Oj87 zEYf{TIMGPV#6&z{`3KhQxjoOW<=x?>^0P`3JA`8ng9iPV!xf|nfRVr>2Qu24LOE;< ztsEu5)AN)M?!@azvX z9T*#f_xnL-8-P)k*(lR=@s;)cgf{?}r%Buv2nDVyl|Re^6ecX}zGtqKqV?9SgS7{( zm%k$hI;aQiYpRcrjH?rOj=TLmVSzP*LhEnR3Vk;Vx=|ty5pD$0XJoC9C`ud15+8Mx z@Z~l@iO3T8@Bc=qwJGg7^5+68I>pXB@qeg=zG_OWbzQD`y%Umixx|b8I%aa4*$hjwq{#d-&mo zXTN)~q?EW03Zp$mFZ>l@B(o7=5&<%ez#%sM8Z8iEr5hSUpu30P>JhGAslfpn=b@ls z;TWI7jgh0{d^PmF9m>{}dEn42TaX}2YAT&rn@L`E_$C=TZ&L5smK{S?p(Cx3&Fd*H zZ`lQk4dQEFnAabEEAv58l6hnZ_>M3Wom3NknpDtd90TUP$w3&|02k}K-Uyna6fP2h zjDy_Ak)@oz*<6cViO1>rTe0kS{X*N&;orj*zu7$b3}NZrN!>biD<~n~(nEEpZ!zL59^x8EEzYc|F_FBE8U)+hQ=@M@l-$Q= zzG^Wt6waeqPMeLIjw{I|qaeSY%{d%L$r|`LC3iEgd_PHfryXz-@NoPH@~(W40uZ#; zE)}DYLdGb-`SU{+zweQ93x2&o?3B&6FZTC5zUzLslCsmMejyeg2QMOt&BgP@b#yLX zRJ~+b1v*mIo*|zb6SUBj(k?-T@VEa?u=orX%raZi66(k6)23Hbt<`gA-vx6RaL%vS zBBO)`?6FY#ZGJi)!CGayj+pyeHGdv$wVjnC;^&n2wJeGm?K2Wm+gH(>G8{K#VC_1d z`FzD6ioG9|mL2S~>OOBdIE6z-!IWKSnq+LR=(^c+-|ULd4v;C~%zV#Va0-vk8W#^1 zlxWLpk$kptEBp%)4N0x3%BHA-nfORvMziYmP_p{(A62S4e5#TN&ftsPK?r4t?n|tM ze3K;wZ?{p5?X*xpXg4ar)y|IB%puzdUnT7O(vgQ@UO!HQU`S6-ALMv3;23txzyNO>?D@08>=1`lA3 z{nKCJS(mE%2hX-FVo*MfgoG!*GokBZ2ih718QN_kX3!N47JA5Ya`mG{<}oTxWco!p zoT|M(mp!2wMZ-v!S0=v$56|}x&%Gze-g!k}G)@an!*}iKjqFEwxS7~iDx#L*z5&bZ z_sRjM_Ckg0IwUkeh=4zcva0yfC;Hc?ka`aRXa_lIT<7W8I=jgA**UOE+0E(RO~3jy zl?puqAwzFf)VB&jh=#j)%&osF(k;yhc;d|}I-*mp4v}>@@7nj;f2+u;?!Yh&`3Ds5uTeC)cVKA`R zibUpjTqIm#nq6*mgfhmD9U9TtK|!jBIF{(DJjsJD8NYO=kbfn(R5fm%Y@J(0Pk4sD z7msYTjhOJ^%{#B$H))r!mga7`tFE~}U|+3z$*)!E?w$8q8i5MK zyOG0K1KEqW@p;+)XID#E`wNcXhrR2pdXv9_B$#g^2{L|9i7af8Z$f!k_EA-T}cgM)J))##MT@&K{iC$6NnF{d0v2){}p>qUGRCo$9b{$-coxAz@exIDY7pVOg4t)BR zr!nInQ$ORFdU$TdLr`{%$LY9EZvUtMDyl2lLjm5~W{1V~E z>sWjY8b^De_ho2qVm{Qj{WvNhd<2-`FjI-Vdyx#BOfYAIBNmrsLq{5iQ03@GJO@M(p3SL;NS<&HP6lHpwHbEl zLSm0fZgDZLI+=pMKFWOBTRu-zU!>phUkajHIoeZ_v~fz>I(ntl1`(K~OZQqN^oRUU zS5qPHc1mY*`kG>_tsF5%%4Y3pj6@Y8lK~Ox!q`9GI`msJh6LD#eR=kldV8|w^t<9r znseK?v?0sR9Wt)>V)xw;WAE)jIQ-?lHq{GMqC(IMC&^a{_jg&8caR^M7qK@8iNu}hC{<$~1g=~xgE<7=I*>xMx@b7hmiUui~)x?^;2 zZr%7b`;cQDmHQ~M_)J*yL>6RlXTi=}{EckL*Nd9}Mz9gSL?G<3xaQOZrWJhY7yM5# zTAq|-p=I6rHmoPD&GkVlE!<>r@yh&lnk>|Ai$3Sml7ZOrsrezh3=<+Q~2S{dRlhjAAX%_UR z%G->!Y4XMK^GDT5)Jb;Om~Xen?nMba;~=7kfo%GZh2)cPnLTnTJYV!q{jm)V*slpO3nQ8Q;8=6ansl7{7~{R#(^xhks2 z{Dy{=gCUw#G1K;r>_#J4@$X-*?Y(at|DBcTUO#JBlL;HLWZvxk&&>KIum~6y`3uGxt{pN?uRaOo|W z9=yDW7^88m93jQ36kInH1MLuWP%RgxKid}(;rAy{$~4sUH=+`?ZR{MDDj1= zhGk0V`AURgEymCHo#2eLATFqFQWvAno6+w*}K9#1b^o0`~4%$*zJnSN`GTI%(H7%ED(mOLff|CMj^tVQ#> zau5d?lS@jhUvr(5Nk}P~Thjmes9F*6+s|#pyFv5x%h?r?5(DvtMfRdG79w)sGyKWJ zjeGV0znd}CYOCbUqJgRN&8b75DNiB$l7d{^?z&dy z5Hn7UY>jM18W+tO5+u;2zQzTbr}Kh)4>ZioTC)SGNF2GGG~9lB&YEJeHt#-PT;e(W z8v@fuWC^TE1Z~DC@>K_!5V~C@ZBMkFH6*U&SI{+0-j{nNC9k^sf=NN|2VgJPuyK?v zrATZtK=@IlY$MgASa4KX^fI;gLue5iINdilwzcV8Suc~~KTFW}uDpwSSM4~nS*7=1 z0a+WknzrDN^_c8`PeA*2Bb!`6qoOWP&`BajFL6#Fv-p>Sx|Ds)XHRg>?LIA%q{1S# z;>4eL%;PS&M)A$X@?Aee*FzOn=V^D(?d980`(_~l(bmh4&R}ov2cPp*opV_ zuSa)h*;9B3i;<{8Z{1|jTHr^K2;2lXjIeUsEt=79ndNiD*`K+CXFFdYOClkmlC8-z z;|69gy5xWOQjus0_AXN04o9u#4xIY}3YAL$glABE?%Ac97;I#P5guo1M)rrc>qb*aw;F6G8Qe5BtD~`sR z!%zhRCSps?4gTlert*>r73~46TrJSDI-vot{Im zg2`3U{p^cMASTHURjBUUV06!+U~lAnlG6EVBSX2S>!M^b1WOC8kWt>OsV34knW=Hc zAjBdf6g0WSIrU2*-%jm$dO2)X8P;mxKdR`kZf#2cue^(b@J;psYPEf$+0vXXB9bed z`&(6nqS2Yx#*C*{SOp~RUM5AY8!TQYFl7;-zR9*uB|$hUja*`H8u7o{g;0XeR=QW=+S=M#whi7B2~Z95^cmrnE+UVtdN{Q0I0U01&b@3On?)6I z<@P0qSX*%+_r_9HJa=Nc0qT#s7>MYl2(+&?o}E#W129nFnVHS;LHx`z8n7FxE1Dci z>OH2PWBi0P*4~1dLyq@Fb|@4Kn2vJmL$jrnNWL(06Y^9XREn=`bV}pDy2WU8`vK)L zi70%huz$TdN1$1H8An7{{7x^pWOsIXsrrbLd@N)yg2+Xy`EYY?JI`PAm7zfG=0NFF zRr0TI2HHX*k~iV8B&SohIcfn{5K%p{KcW!PN{{`XHou!zdlBTszWNh2+wG6lH}w|RbkUu4$S z7vT)Ky+h6GynCqU8xd88!0hT+8JeEL^FMW)*dWI%$6dVR>1Tz#99hH4N~KJP4!qf9 zOWO7Ioni}Tt}zVBwo4kC8eTHf4#<~aQY38rQHdYo4A~(e4X~w7f9IPGXCA{aBKuib zz^VCStk~VT@uw|lPcZ#Ww;ie%0h;EFb>aS4DBcVGjYEE9N81)u`2=yoh)AMdi{-D> z)ecpMuL~&m-;kbKuR8@lgtam#%Auo3q9U=vq5GB878p^?Ekq#m<;()TPxu4SLtZQo zKaQ$-Fb@+M4IAQD5)d?|aPLT_89Zf8M{ao=BfGNpyhVr#f1!_m0(*xXM?`(N>bEAT zN_a(Pbq(*qH&G)!`-EN_*V?&_FVi!GdEgsZ+VbPl;bGJ>NlUt$!v!zxLI+!fb(PG2 zmD_(B=RU_CeP5`*>LBl?a7^$`{YWz*yJ3F)_1S87clT;x2AkNv$8tc2KWB7lY(sK7 z(AH#WH*V$ALVt)b^pd*;@!D6o`GVnVeH~bD-XXuF9s{1UB@frztxc=rfLRK*h3%S} z2EdAnJ0)MRhRcXOZGv&^nN^z!LClYM)~QS;etBOcQ1o3>=o>6^@_a69mj2kqaec?K z8%l5+L7Vl8DLx}2WkS+096Ozhc)m{(dC9X8sdqM>&=OVl&`uC1{AEvP#3YJS_?|z3 z9WNKg7WdCpbZ5e=cu|SZEM#;2Czd zBLUZsS1+~GMw%h9xS9l%-0oy2H~o&cXTaRFX^OaF%E;pKA28-WFhiEFr*59(P1X9w zl3mc*pN`E<`^Ov0^A4-#Q_f*4^$9QMjt2*IF+n3?eo=m5d}&Tw&3a5hOytW)h5`tr zMLiV0d5~WYnPHy^M@7A)&@|ev#d1Gi8Zd@cIs7p)%w6&&Q!&nV%$E=E!N8Q%n60^` z9=rED5YJNtjI>2rOjNxRTy5H_%usuxEG9L){+J=f5t9!?Yfa1hk_CuN#SX)T67N;$ znp8|&#AC2kk%AdNmG?m>&Z|g!y6p<_FTr|aX-ot$M7lyG|GkrGlUa?E14+}>65?m{&?VGh*}@M@`)9_sk`cykty1;t=NH4Qnk$;S1(7a}cN7Sqph^ynJx zWQhn5u3@b_}_a|64&-tS36bS9_1;*z(S__z2yuE%%5V;v8s zXX2HyZaOIqLY;p8IKVG`Zz$W(nArq@?c^e>kz(|AfI}l*H>|=fZTIa5ShL+(3Ja zG8``@P@nZ@hkXGBSG3SV3=Eg-)SEyFwVk5bjSTf$e|PwssxCkEF>ZKtpsx*G)9^Fi zqP_uLL~9QBCg~5q4h}nz2$IUb^?r?j6oGJ*dGoPC1}9$gS$TwN@CP(Z})@0fi zCdG29s8zUqW64oufa=_@*nyK5Gu~jNDwg%mfRmj0`EwUM=t8M-=%BC{gzwq*msopu z{aoC^{=ObwH)kD0Q=D-AMc?h5q3CG1Ri3bq4mrh$QErWNQF@O;nG=q@hM~fz7}2<* zB^0V7go_ubFVwONhneEdI9(GYP}V(&Jm$)f#pxGWi|vS$=kOKXUF&^a8#`yu^l5SA z&<7$ar5A)n_Lf8pDHK^I$E2y7<__?EzNZJ{het?VkZK_mW$5w_QN-qAAhoDpcxpIZ zUeTR0Mt&aGDo9Ib4JN7B8T&NRQU^ZA(`x%jxLs z5Ec{mZdrN-`K&hede~6H`HdH^9yY36LBf%z6j>ov1{C^M{#UAt{G38ax6M5p#xq3R z+t@lLeI?1A5>hrttr7O-;Qh6~e+O4LKB{R_yTwg8w70fB9L*g@FF?~M-*(*{^<2AI znhn$*w;8_5hFVt0M@>wo&{$UMvL18Av8sOj%jlzx{}bX~iyg`r^(IW!KwQP70!NYP z9-gJ_e;5k7&4{PygnN0r(I^TX-P9iMow)GL{gkcdllp7-rM8*cg6a#<;Qo93{u8$@ zu~n6dPa2jr+>$t7LV|zdG&p^?w)^#NgKQMJDR~cALTSR@*vRoCQfM$6w_KqmDyTTq zOGwPv6E)hSHa*wa5Z3AUF3XPyNpg+3 zGjK^kF=AC;QC0X{I)ZqoZNMt6IZxF0dVhpnYyWJ@^EhXiB!%Pa!G6{A45c?z2q?!T z?}s�%DgnKJKnyX94k?k+lx@_1DT1|o`; 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

eDzOz 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 literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/documentation/images/rp-profile-view.png b/deps/discord-rpc/documentation/images/rp-profile-view.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ddc31304cc5df538a5757d0a1a0f7d753cc598 GIT binary patch literal 1398658 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

F!X&BmX=CEog6-6*+R&zHTr@6hQs1d5WDU+w zsoY;*m^rI=_vqcMkjB6xaGEY$yQyqLPTch6=7-VaekVs;K+Z2WPq1@C?J#EzXyS$u z7-fooTc_k_M8qIf{FLOweMRe`mM=j|Zm7xwQY-f@jA5~)mCqU)!Ho?J-`vvBC2B(G zWP!VEy^c^NW-#Pu-e~3MsY#V$SC@UHhSDFqN=WYKY|6JuJx@3vc?yxU6%h?Di^LAi zHRwY(pl`SE(v{oegi6vP=wNBU@1(%zUXgE&&v;kQ6#o*rBqcFr{7D|3b9}RgnHiZp z+H@8$K@sE)h4OBds*4U%AC{#QQO>!eg)?^%p9O2eaQCg;@`~kulMQU+I!D_EexLD- z+jxM&OIFypH5IACVuispDLe1H4+!j27o8E1*I3qp%!Ivqo-X3<1Wi4K9IHVW=~9S+ zPRPq%i{hTw2{lUZqe0}MYc|D}5!Cm(u@Uqq!`6|CFNIg`WR9oW@XdaLkGGnM*lD|B zOh0kfBoK4S33#d=DJ-SE{tkXhk?wP!Oq@>Xy#x&ps&-8*ca}*z{=J|_*dT?)?DkNB zAxmT@{qu zO^n+EX3u0I6Z~d;ecKK;NO=VB=G_Ga9&y#cI$RoG!k|avKwT#r%#UzN*LA;VO?B!L zvv$p1A||oi^E3TYdKSrVI{mm7JDm^r4eX^ABa4mal`SUbE-2NsE|IcP%foRnyu-nv zGrD9E;*;ro=WXQXDCnV|tDzXtyR*m-SZCcII<3V=WnJ*f_nT(Mo4R`MFYHcNdOmyYQ;picR1TFyJBqY5qvB8UANgr{0_$uGx#jdywww) z#d{T-T3CBU7Zv}d(+hIx$ghsQ`X?M!-+2C+$C?U+_LL=8CMm&xd-eKroF9 zC2`=}@Vt`rf6FTVnNyWXcoZs`ze%Df4>O8^jVRj({S9Um<59igZB|2A&HV9qvXl!K zdG*eya%FPE-FN7~E#~y;d~owliJp;E22j`akUh1@CN5#^cMsLkmki#QOkd1-sW%kk z3cZ=~ITA&k}(G9E@)ry}n% z%%C<(U+QC?b^cIqa>N^wwhBRPjXBh#43l9giv6PBsG?{A=6LyvpcX~Dy_Z7Xw>|+( z*+6V0M+}Umhb@blc%<%K@E)ap?L8{u8Q#@dH|BQA`#L=~`mpFTy+-F|$khxbOBXEq znRyONK;w4ls^Wm6qt0l?L8X;b9*}!pxhED|3U%(FvL6YZ);*ES`% z!n8!m2nG4;>c*!<*Gf@XxvAUq&KYN=jUMgrdgaSSqB+FxdKse#5#BYb29lY3)b@s)>Y7b%pSQ$~He&1{d}SSOSASvoRiqrG-m9Q~E4MX|ucvqmG_ z+oMm-*nC$23zsrooxNor%*8znCRhw|6SjwBG8fA~Cf0}-X|RSow9Ufe|Gcs8#YJPclctC>&!1kI{j96`yjwkq;%|MV(+!2eFh)fV-`NQ zpuC{LmJ5d~2NE0iCUO}fC}!ab(h1)WBY)B`9x*QeYDKKxO07}`JF!n6U|{?9`wM6X zb~-sDbcM)5jKIjEVQm4}b@3tr``<~rEL(ixu#``UAv+OMdG zEGHJ8lMG4|hUzA7z;E>=2AsBTUEQ};9fOe!(Uz?J}>d{@=8N)*;{r1U~P%*I+ zIevUoL)iO+g^lzRUtsOMRg9eRSx_gx{#e(MG>Lh}KwgsW@=wobvc5B3>pPLnF2&;c z>B53;Q3T(`@R^%u%yn492k*^BD=J?6eg}Uy#s{WrIpB#rX=R?vnUR%v4H+Mi}IQocJ z$3gLq*zULTeVOs$=9MV{(i<+;-i{>_fjqsp34B*k9&ye3&X@zdv<1Gbh%_jzl#Jid zd~V4img_nDj&In)Z-oa9O5*UB8;hN&w?{g|jwfy%`rJ^OTMB&1)JrmxQ!d~q;Z**r z;s4P2?ef!27bXuBM;rv>&P~o&&OlE@lAkxlGzP7&#e}^olEtz-RVeFKDWvVW3m%S~ z2B&8d1GqI|3!|otwhK=5HS-R`jgM>7N!)81#bZh3-TBFsh^Dg3FnTMQ#JlZ1B)y^S zOD`xeUL2L7Eq;`5tuYD~pRwE1(vBQ`vF1<<;KVxGvel(QE9tYzDgg}*_qXD zhbER7Kkm>*7sy){^Liq^vp>|OnjQoKKm-KBjU-gBh_`N&|;u4GGl zeAF*BGEDyym_m12$fXNTdrs@_1o&$|3aZX%b`tHrVx`JzNo+3iPR0+3A_(^EWLVwg zGvSJN7KUk0j}~IO>gJyvpQ;8w(%B=rHs{=%DXqOB^IU##$*nQ|ea_@^nPVQcM>$vv zgTX=GYJg~&vYxQLL3_ttFXgkTBl0ecDogICx64nMQuf@J8EooUyrWR#`wcrOXO%@9 z*pLgheDAPbuCO$4oc;SamEQZt-62WdyAX>XK`_bqHz9;V=+?BSdcb)vWDXoLCBmi_c;60mEyi1-xo@G=~i_o3X(1?DZ7GI@0-bR)~^A5yDGL?&&wGH zYni=Y$JRYaN=#-{pp@i!m4SlA!IAOx&RESFh7fHCe+*-Mw!YrQ>UrR)@7eyg+S}8u z+*3F$bckqA*_{9PQ>EusH6r5=k&1N;f(yKAIneL5z>H95wQ-GcDn-!2r{&-Tu7i`c$N?&TyJi zc>rs0rs0-*cwdox9ivZ^V%fOsQq~u0lkSAafHhQ+VECISq>*3=n_Y;b$;PwkO-XMu zk~go+TsB*Cdf_{1UnFO^3rw{pT;Lv=8e&GhQB(uj3eEyfUljjNwn8-@nYAg$OYSSz@4ZCR@>9%^*CF;DNjov)04Gev_ zeUzmd6 zj(R2bhIQod2Z3l$fhW!Fsfo+)T;uk|T%^wE=R^X@gWdNmlj>>~4ISqD-}hRLo285v zAk3R>U<(=41qE4jk_+14v+$h%Ra+0(^Mt7AtM&Txr(_*tqV~$VILzf}6Jysm{X@%l zUs;44d0nJ#%y=TBcR7a`#YRdam`Cqx11B280|(tct+gcL)QbGTP`7F*+e+H#DJ)`3t?Ogd!@A*%BdvHB(IO@Nw2N$BEY8k2>S?H`IbU0=KiM0_La1jaQIh!^;uhJnT zL2y!HnghOgEO#U^WH)dvE>Gs(Ex$g5?8Ze7J9+ClEAb=HWA#PLi;1pP@s4b1Qc-{| zsKi<*S3am$jCSD^uGpF%LU5Sq8W5g-s`6FS#Zi3TuA43x-nF9n*eJNg$v`Kq+dA*v zSfbkEEf?OnZpEgX-=@?mzjP~#CdM5DlyOL+9iu4)7ijb`->WxJ#jl&y z8wCOvkyj!WIG7;hToP8ZeLpZ&Q*Nkhwjqo@u%VcRlU=@)v4GmbrO1U+rf*E2vi2g5Cw32zVcG%?pu%zOQpV8M^M+ndI8)eA;1;16)w@(&E z6_oJ=CC+7Iv-DiSgX#@5n9qaH^Js;;koDeuKf>mS=Q)d&E!$6{rN6`+7mB^^OHQbd zQFpy3YLHB0jQd%;%5Q(I6)W0>4!@*>mWk-nh>LjSYE#eVc1FqJ!c8pfh<1=LO4Fv| z_QuyA{e`A)L`Mva*wYQsyUq)3ubYqK=Uuc1=1G1fD9oz@a1)PC+@nIjN#WQ6jg zSV>)o=N`Qc8B&+lD=*r&qW@a0M7D9Xo?jL;S6~`TfNae#c=ydnfW(={^48s^vL7<9 zj6-I{5=-Tm_OrUu%zp;hHNM|t9+rq{9la9i!r_-3=@v3r@3BGU*D}D~9)1BO-VW_u z0W(TDgMvf!7Um&)LbZ97N_krm*;C4b=W0l}_p7UYHcapa^!EiXkdQ^M28(?R3<%H? zTckP~K9TiqTcTY+w>?ppp0x(D+&)P%7I$$l3*8#%T>2{y$a|L6f`{A-N7{a|qYfKm zjdL_H{!7iV(Ldmmq0|y0PvNfIp`l{0Wo_E}0HH2baL#Gpq} zMZSQO?eYHfjAY{-Ho56zURz_^qg_YuhnKEAC1yjN8oU)30Os3OmN6PZ z^ynn^0T3&Nr*pz#+;p+>BLEmZx24f5cdc&^yjrCM{=`WEh*VAMjda2#ax76J4? z^?y`VdgRJ{f$Ry!$g{eRE!j!9IxWRY^hk$jIZ++kYc$hz05{UVxDcAGdgckwbvj1x z4R(S_+c(2|0gz!y5xv&Zkc(RdzTCr>N#X0)@`A;4Aiq6t6byL@$ZHLHzu2#v?x|~l zL_dI}`Mn%{ms8WK0C`*4dHcWaop8#3gRi#M^U^;La4oZ5E_9y@B7vbJXY!s`dW!s4q~ z;LCt3@dXbl31ini><+bGs*k{5Q-YP7S{voUNG5CLsPpZJM2Cy<(H<^3SX(MMmkO)1=)C~!3>t&P+< z70r4#(PLv$<>h2}-`%(3y)jfPX;6+cNLCL0?Pm5w4^1H5Z#8@KeB^nc;rC=1HN!Ig zTbA+i`9oq?E%!K4t=Y-J1<<#aZ{bn^;AO&BvlTNlel@|I{~_Zoq$S-(&Uod%yior) zQ6*18FRboEnG@!i!xp^=WLZ3NjcC#k;F7bC6H~F4QRYL4_V7JI){rn*+UsdLPF`0c zJWgGXS87-cCEsh54Y^$iNA@Zej~>+*?678WldTN1+C@85Ts4Ykg~sgwUBgM%T+-)& z%K!(FAm(9E4=-K`w4sLTkF&<7G5`QAkfJHCGF6azZiuUi>v4=M571!{3-wdHXk9rl+K_JozP6QCT8szH9isbmTy+lXt(Sx~Ij& zEf>{x&6`SIQ_OMuK~d?hVI=&wz%~p2P0tmTR1b z0-3-u&nZRBL}~6J#=S<^Ui_wtOArI^eR_?lfKl?6=oX2jxjEUePIPHo#ok!O+umzB z4$futpoh|{s!t|P#S*Yw1D0!Uur}kGVO_j8(I-jgx(@MpiFe)!FtMnHki!nb1OswD zc3VMiADlpn4ahE^1S_qBb9KZ&XF%3Z;Khlo0;{3_(mF7cpEiEGDHz_j3B0)0cWo;n zl;1OA1*M2ICef|bDIP_XT2Yvw5_T;dd%3*IFIR8ZsG~gd76=LjQz&stgV}d zJA+Z%si4~KLSB&MaSpt0!E~@*cOLdWNm&F@-duToXM@R+KwYH1C8X~d;Z7gB!{gNa zM_ua%pv6xYK5AE(PU>7#cJFbdk#v0Tg=7t#LptweKGAk$=R?G9h^p$vF9<|Kba$@^ z1J4^ew53Oo&wC8*SQxz)N>_uXfVxJDG|`JT@^>K#Y0{y@CtkU+$X9*4a&7Y#XP9@% zf%0()qw8Oz`qM(!f|)^j7!Ac76=F(@H5j@vavELbEVthkAtt`wVsy%8bmNVwzc!Ct ziB;Slo)M7+DmDfZ)^LT@i_SM?#mGc$z;*0b*_y?7YGRwBs`a-Ev34rlppy8coqGn{ z+jra-$|*+3Kq^oVkG$v$*bVlH+r5=Qh!MJ$jw~pfvOPaYf|z`jOoel5;W_MgW!w#u zzQTtg4+VV4pz&`Gb4ZDC@*yEtwW&7&w3e@@xR5Bz?4?!8ZCJ!dW+`p_;$upe{W zNlXv+6U|a0)*SHxZm%c7a}7xNT+OX4H1QEnKeC$T1GAINO7gy`BhhU0+&1U&86`Kr z%nUQLiQ(8pz3|vn-6fghvfJ@+h5#Xtg9u3XBkz9u12})YnD^vFH_Ua_hYddUslBhm z#GZJp6DDajFa&-H&DaMm2V@s4rL-=BXL|xe=HAO9jaFzacym=X1d8oap=ymZCK}&2$yb-$@8%F{G9wmx4 z&>bR^NOxpwsB&$Qj~cD@oy2MzLYRwwJJp>RWPSOimcp{GX``V&QVnZux36MDJA#lh z8>68s9DPbcli5i6W-FBj!yDcM{t_PJ-8g!$B{aXlk>$!EKY(X_Xg`R4FX2$>>>E!B z%^17y^s`UETO}%Bs#**`j^Xv^XG7c>H_tjTT9AI!OMH7K@vK~vV;!7oxb0KZ^ zs036xk@KWnM8e?7KFE{H!sK6~ig#}*=3zaFk<`{Pr5b4BHssve0kfmBJ;xC3W%n6n zpODG|D))zk>;P6idJ3>hBS0aDpQ&vtLcrMHO1UzF$p?RZ zXR0M?t{*>Z67vN~+0|(J1o*tWa&bKYr1(^PxYJmOEK}hY19itu z8E`LL!-?+x{Q1WYL)Ult0SC2eTf6wh0+6+@LPOQjL&UFW{v#!o=431=8VLB)C(t5YWpMy~U3T!}z@=2Hu<^>+Pz#VA}W7wd>OjAwM55(CG&x3FxB7 zFoaq(Z>1`|SOk5Ki`Zr%B&@w2iE+R6p?C*hfj*c?B zBPAHzxw5S#oPl$kW#Dr(!vMvd*MMgcvtjqFa#S$gb@wgCi6GgH>f_erY|0>{7lJv7 zc2O%ahCR@rQA5$3iPl$B#DtIl_g!&SMP*d2J+KsRS5AyjHY)|`o}sZb5~8CX6rXAu z1<|z1oNR#m{R~c(W!N_;pq$%c;x{Vv&)ix-M0N|pn$H-5YT(u_#vgmVjP4|6>Pt#9R72)w z&Vlh;EgC+v?Ya>`bp2!2`miOI%mW0emYqqp%rXIeJ<~ArPK`ZqOJl`z=nThI4m5~s zr3=0VFh71J|DaEP);gm_i~rXEuiiz$^VDKxwS?g6ui2 zrBU$ev>2ee9k3F&qCwRLQ^ih@L5ys=cChQ`bq#*w4{aaexn{CbCfbFNSAX16$xCBH zT%}v@umsI5TSds{kc!VIFI0k0r5E|R9<0MArr$sRhjB&G1gZ^0BQ! z>r45z_K$U*^pq9zj^9hlO@mP#$MN!>;K;FYdM}%xJ#%A;AL;9AX}M#5_%mcrp@*?^ zgVpGW^~SzSjcGlLV@& z{9w4oDNNX$;~vB}wkj((Wc*M}XUA$I%6(w`5n=zONLkhQBTUdeE&)3rP7lQs%K-I@%|o1_e3LsORQbh}38wFhhhP0^#` z3lE0w6ciyIGk&HY$1R%i)s#_<;=s+lkvoumC0<_m$y2L4#x_d=I8UHzoHVEe=?2;t?cb4KhOk{gXyF((KZZxJd*#R{Zh(zBMP8nqFGot`?8nvFzYmBx z|9<7$WwfAyUR{hro>w?q?d~IIeof5}s~ho-{7>w!#JX@V)U12oopy!}Qd7Jlzc-vU za7%YedayF%gI5VtCOrKic~^hY3PdN@`+RKmXYWQQqJ_=}oH_s&`zy*|>wFHKs#yHp!q!+0!fsKPY+jPL|Lu&mZ$~3H#B|mIcD&CKaVPGKeuPxpUOf zmt~YeuDmN0=e%DU1J9LTqGcqI;of`k#|FvCYhB!ArQTBgQc>uZ!Ug2`Y*OY#RSwtuBRnMiQNU@9V#~lj?n@8L`LmX};U1H=+i9ss z?;5*LRpnRey5*hJm3th-Koq+NKN)?lZrFNeVoqstuE`i9=Z8=n1I@8wjEGSoy*Xs5 z0?TlQ$_n3LkwjdA4Cw;f{Z>3xaQMMcv4ccnorcvjt7&Y9;^xVFtR69-t%x($VvV7hecg@*o__aA9FRFv#1}Z?u!wz}+-H;ye`p@;) zS9j*@oeRfD#uz0?iQ4>X_%Dom1d?^zNO|=;*g1w;*iQv+se#= z6paj(%FNo%^Nf`WPKZ;ABaWcrgg5~LAMJh4`~A;*-v9Z&Z!H$<2TNHG55IeO?)$#3 zYyE^E#{B$p03)LeMs1Uu`GiAx3=`*_^6@cSH@(_cX(wr_&wq}g#o(v2?8c+E-M!$p z9>|CuAlhftDO*OYb2v3EEzL5bF8PDrd^|6Obdusk{Q0UrG5O{#x#nS)yujL|I0h$o z9`5gVhFI4gIGI>>3WPVPXgY4v9enzb7XB8HI60G+^#coV#z?VU-8#Zb{ZX+U9#??CT&9OYI(!Y)Ilv3u5T$ERa5@o4n~(!*Q`(-0N3 z)9f@s&8b!~x?M}@Q83viyj35((w=CRJbkS=e7rx%0Nyxw9rD%ts5lb~j?j}d5adIq zeRfzm&sKq^jp-?}LC8*du(Q(ku0trVD$bvo`6h!eY4{o5wAtFq(MzQ80=Nf%j_DxV z09>Ed^5LF&ihX@Q8a`{e`Ed#P9DBFL(zob~jD>OUACSoH*S&=-^}WwzM)(d*^Y@6- zW_l}aErVeyjOE6rGItMeHGjVgsi98`@%2|q)n+h~Imb|a*>9IkQJCxj^sb~MRWX5Cej1_*a%4{D#i{ClTJTC!IjoHRsSbvdknT}bFX{^7 z=prx13>m`@5A)?D$4a zggMQ6z$`)7$X#*!4{E6YZy5h#b#OW3F4FQe=GhwZq%Muu9j>D)e4fGbuSV3-v+(P+ zT1I|W?wbbzS!)et8-$oT>y&k{?GX_?e3fD{3m6(5n67*37XkaTKzd1gAQ|uu_{or& zjbwPBn$BHq42K_wa5cS{r&N|Gbr@Oqz+mWJzodnR?NBePsk0{NNLE@KD_ytjANZ@-2=dRz^ZGT15K1HJi&(wTbk`c zlScdK=&RkV`RIH#&Am}Y1ubnE3y1ADXv^Mm4f9Q{2&|1#jcRlv$vfdW=eO0cE%g5E z-bZ$KeOE`jhW|soz&Q?+)yce{#NG$8^__1^gP~r@=dI znU>5oS8mvo^u0Fa_8pO+L&E2t30~UG4wkOy5Ak%C zyG&JgymrLgp04jw{FUXGx*rPWh#&8@Z9dTh@Q&W`*jjZ4Y<_U5&x*&pZ%gSgyJqK3 zx2J3yT#Zo?maWIjtJIt2x}?VilCKQ4x^RE?3)x&=tXa|-l^jv_#Os$2+;Ns{1nvB0 z$nS=zzC&H|kEulkeBWF;Q%YC_hCE%qj2W21Z|#V$=O4*l*tx#5fBq$AGaB@mGskC7J21qW#UazwIT{ zk(J?G=9&I>ZEgp@PBI{V#-}~Lm9zVfP2sP(Ik^qFU2!o&wd!@Jq&ky8vQFT-O8J6i z(E$R1+&OxOF>M{ZkhA53<$~6d^NzeKKxZ7&yE1XcGNiN236S!X5=lr6-C@wluGhUFG@A5?i%WS zwYFb%Tju}wLL(u^!a|Ln_lCWS8;6mk#pPQhe%J49|D>7}vExTB(^I&T~x`=*Gi z+0t`={K@WP2a8GEZI{eVKoOw^4yEin@{kW!0lz486SyC7 z<?Uq^901A{5oWTl@T}${s^uw)jkx2Nmdp3XfOBs zBu!o(v?3s!H)jeS$$>lsq%xjRb^{2Rg5Iq^^x%Dk^g&3s!*HArvk{r!ZI|x9j3J`xtEXcLw+PG~`r}vhh>vzm{)r<H=u7Vv)4x&3Sn zwr8tRCd3)@)8S9B!_ZTJUYmm|h9)8U4`eDmaqiwxI(nA}L(=)X@G5IIaaUh#%15qF zAMhpZ?!Ks~^sRRBLnkEL_KT$3B}Ip5-d z&)`w=9ZhA}CQmN*lam~y%d9D1^CYdPH*s8`sAc1*I-={W1Ur)&1YT(~>yRSM_~_hk zz_hMKsf0Y4`IHIS!rDHp?CbN54V<*EypNY%*}7kd^d-&2>I=zkydU5_$%%vid1?Om ztyk5syB*KUQ${KSq21q~naG4G)^zQ11stNv`C}wiD_wN@8|u8l-0tJhiiCITED{AC z+D(kRw60~+3i|G#EBZWn&g>(Mt0+JH`_`)j@sDa>LeLlu=mU2C$8+*FfeZr)u ze2s|Z|32S_lmjkA;5<)tFMcADJnk*^=O1xrsQiRkSzQJkk6WXEb4oMTdnJD33*Haj zTV-3Hq7LsRNZ=ikj=ek6&nVVFo>FBR0AzNTc*gL*;{i`Ro;F1hRx zJy3!qk9PMUK#p^V%g#V952owzvnAtt*?SymeW86-!Y`!cwE*3g(IXmj$LXfMMV6f* z@XJ@-jYsA$bSKi=)<9&(8M*qky}&^Jc;xTGmw<%zhrinmqE2sIHd!5!A9!FBtz)tH z?vFEdr6uvOgb91HBc%Q3_i%pB)r?12_VPQTF(Ns%Bgd9G=)13wf^@ta>_Y-uuaUG8e%WcV2RLToj|Y*VXu{(x=pC9Ebj|#~#1-fpvOuN5UBCGCz0zVDQOqCwu|xWknC{g{EqdX1ks_qF9q{9MQX%P6nx-PB3!mjRIv4}sX;2dJkw5B zbpL`AlPK&wTSHh64F$!3)CS`|2v;u%x>pQzs=O~4yUV?YW88qgK$Cn+BE8EUnzrV> zZ_1Y~nckvlbT4Xcw|GJvI_4O!zkdC8y&7U<%FxaB2;ziZ#$AODP3!g>t*@NT+p}=y zR<5B>k%tu9l6&ml;%Q0)29DI**E573>9Xurx`N=i&B214$Yg!eGkXvJR{0Mx=tgX# zWziD%ZS})vKNGlb7mDIft8R$A7UCn%%^mN17V3&EelhY99Ut0FR>1n7`FE7PK&vB5 z?Pk%;@R1t*C3Q*LY)gXwH^{H$l?1HJ#L+~fWi4$R_8Hkv%`Wte>>96Up+paT-io{J zh$?8JoJQ-1l+TmV&$`3XmU|t}LjVvHv$s>I(v2b#dj*xa@pAAb`HzvEyix0tkb_GP zDjqML1boxszQ`~`KCNY4PpG*Az8kA)v6_hwMA*nfLOt**lgY*lbttBq2xc=GdKyiB zlpgX8|D4ZBMfq2G+dr^rY_T5s3o&f@<#vY~lu-!S)2MnUU5iF~iL7qjgX&+;p|@sC zn?ww@swN55`f=~Hw{UfD{P;;Pg`J{Y1{nBZsjKN6N`PFSK-ODXRxL?=Ycb2rX3u6naBP?VUFKMPQRs=*yIzFMBC1jR;}v03!nS-+k#S!wXS#*fsdC_s99f2jf1|43@vDo^(#{v}n@>x2)tW!yd- zd6bU}S8?X;Zw7=6Xz;$^q_4Xnm4$fB;cs@L8Nw0mnZ3ksDRwKHp0)9&p=|+=_{6vM z-LP0FaG`Kq!^TdrZ>2Pn%cN@3%A!0u*K>tha5r8~_rVlG77BiC-d#172kD&K=B_K~4KITs++c z7vIRX*k?q=r&fs0Z%Z#ig-+iL#h+t3F<%&+FKExowc(`-R`RS7RYAz@W&94>FVyWr}$_%ehlcvtYJvwfq;hhxD zM!i@_A9l;;98qI)%nyPb$B#|b81h$FT;CSSxd>z|RLTuPyNe`4`k_yfv6C|>j!8=` z2<>~}4XVFw(9Ngd2ToT4_V*hWLB-7($*Oeg;`-Q_y04_8<#q#^WWf&8f!Jb9qucsx z7kFeE>NI-Jj<2B`sjE7`C}G8p08mmB0GUffo9g2s%g`uuUzdf38lAgd!#|_qJas%t zPyB-eThpx5$rzh2SbX}&Q>NmOHwz1I{E1z;J@W`=#T~m|Vcjg-vyvDw2Hwx%Z2Fi)4eECDuGDMfk-PRX$>`9m8^C`ddPiTR zwEK*5Z_}k3nJ}&mLy|OuSB{dEZ(`DN2HS6Uxr_MyUEPvV;!#ie$k5GC#D|;m^ugxC zhqyTHYJNdMcc1V4?S5bPbcS#-tjC3E$=AGv)m}?hT+$_Ndi){_Fn6g9Sy*;|(DNP0 z{(7No2NT&&_r2is(3fDdE?$m?oLWR9!Z_<|71?X?>E&@gZXY_EmVU574t9lc+ZD#< zZ|}Yk*UTbfzyt4dw7HH$zG8@I5_0H=enTa%gDM{xU%sjieXqkdwQ-N z=j9>et*xU4AMM)hN&9NA&~&@3V}3`Km~OgY+Lwu(CZE5ITFZ4U$Hy0dk_v3erkt55 zRIeLTT=+85e_gRZb;ru9?-lq@ORB!u2+3)H`y?_>(A-;)Efrl&R3&{uEv%$O)$v;= z`lyVn0iTHL?U&9o+-kO_#zs*H4htdR*Iy9_xKyy=$c zsD7Ov3=rBG%4vHxjGu}bBFy?C%ql_6TpaA7e)$h)Z13%>CJMNgtJP;*u`=E=%%tEQ zhYg&pwf&qbLUL-XwjU4OnvD6j7roEhYx}2@|M+dwgxXdC=MpV1dRrL%!9doy(E^4Y z(I18#!8E*BeQJYYe!H~*UqPsSSjHK`CgW(->0c^qHoAo07Y|dujoe<&YLt{llzh0O zmTjzlU_tP!B?uN@@zJQRuqJG2ib}027v#PrhQ}U=Tt|!u7vPwhL9)yR;tnSan?F@l zwsFC)!i^0;)@(HtdAVUp8=d1!e)yCAJObzn#1*2|wCI?mugkFB1Y3WDx|`%diYa8Z z4TP?WyfHpcDc}mK7;4pBVBh94`qun zaN;oW0Y;5xG13;iL@_WS@orwJ(migwAur+p#DNRkxK6Xx8sHd7!*sCUoO)KzawBva zs!2QC65erg$(l|}W_9vUn`t}AQ>0Thed5)Nm?E3Lg)`24gs9RdB{{^$`VIH_LUXx9 zD4_E8PNZ9<#nj=+v~-q#2mCtA;PObB>#JrKqSfb#-%sX~1CwKKbZa`MNVP%y+wrbN zkgALtCKJ&SwvXHF15BL{=Q!Q5O~vGYH?n5VJNX{`$lK>BWm!BYp)t?oJ+rDjp`v8$ zT^PJIo%%^{Yf2eE{(U9lKw)3PV>7AZk0eV+s4xMufUGd04RB@^CSy^gAnAh+9;Q=0 zMb!-BhJ=$yBUI1&)M~G;zHs^C#<9Az zsDIfG`06w{x*GRg3LjGP$}^8B3kR83hVA2xv!mkU^z_kp z1p0~8R^C{T9bP-e7X9lAH6!*#(!NOXvaGmpP`*Yl6j5|-j>xq}GJ)hq8wW=6S)YYX zb*+ysn{n#5IL~~+oeiC7GcU6X82BT~+@BL|`;MWTCv)R;tBoBBlN;p~7dE{tL1aM3 zyyol+bt`j@62+CFi{Z8P3&{g*Cb12WYe&MkWLbEb+J#pt+=kTLa>pi1AR=f!#;zXh zch9`|aRMxenGAiT?Cvq4HaXY##-H+7mwC{MlB&0kJ4TZY=Thbz`So~dvekIUtK5aX z%8~Ogv=RIE5;_|{X%ir+?Ya?z9w6@yrdE$0u!RmX{`f7xy=B+XR9WV7gHu*r)Ld{(7M{Il2$mFU zoBw#0%iGT&H?z1sXB~$g@|%yVuAzw7e4qUK2@ggHP9~D?5#>t!TD6XAD>F@Nex72R z^x6}I%J)puCBf`k0WYmf4zzH%J{_TSpN{eqZz}n13Ri7 z{G)g%xNf&2V9mtdR=Lb#1zy`_6J#d^y zR7Wo5893BHRK5-cPWMq@Ie-$#v|N8_I^vB>P(IMt(#~|P-Ojx`m)K|Mbpva&&KyNFw48Nro(r#W$#huR|J?&@e1#hmY`>#PWJ z9RI;qf8w#9pmMy(w26xYO3`Is?65bc}JB1T(iz>s>RkN2q+UTiak-V zwQI%&xkG*LJ8hq+nAks~sFlfq`@hFm?ar}A_kJLSrmaM`yX*!8^NuF(xKmR&6|c_P zaR|sT+N9F8Tw=6M{SC2P}t*evNe6$gNAFy8KGF zNrwWVlGLq z=nXFZcJb@uq})2a7?{!BPugJdpudLDYNF(EoNOR)y-?2rvi_c6RQA23!^3`qc`st% z(^Xq0_Gjrktv5P#F-F`h1)1$*xu<+@JY=1^3a zb%uNhFbiZEy_$&)D?UcaIHicE-fVew_E>g?BMTYF1`?%1``n!CF;$m|E(r&6JtP^e zq=w$K|G_A;`d#p%2DMtx>55{Np(g9>(f(huxWfvBxuoi%#zU^qS=yRf|1tfl@{{{c^ zQ^zxZ#evtG8WQwU6C4ftUFv6>2d`Aac#wThw1_b3L)7T&s8hG9V^XDykv!$ZETm47 zO&Y&Reu&wcK)W8qcb!BrIiLN9x8CIIY@@7#yyDk#;M`l_pag91MoYUMsDhNum@x%m zvrrK*8hQ=IQ85Lph>LJR%3gzJbjM(znG- zB`eY#TQy7aEG?`c?94jdnrCPK4ZFyf@cqq8-t~|XY%~1EhFs86+v|&c@EhTCi7DA> zfg6k6l=6tx4z+bCXo6t3RywkAy28vIQ4b&8Yv#RSLmBZ)9`0|4^UN%RA=mdIwVF=& z;eNxGUB-A|;r>vYzkwC~*mL=_RSDU>OWfWy2J36PcPgzr2Mp!v$!?6NfLUgS+<{jt zpKy(P`ExC)KqX#BBJG+N-yGPE{)A*K53kx}FR_;a@>!;D% zMFnjR#?$;GG@ z)FCa3E5QY#J_Cv)-JsE#5M5oL!X3L#$Y_Ktb31>%DBtH&8*kOM=W5o|RcN$Ir*N!G ztPxX3Z*S7(G%`vX0$^IGmqrIB?9|vpCVgj>FnQVY7~%y80A0V?qXxx}+q*zBzp1T$5gF$L4T+#$S~ z*jVYnlJUKJF|bP@LNfhTT#pYiEh#s=5IBty7$`o?3Jfvvh$Y>qH}YC5Z0xBtJi)Fw zM5gbThjhoCcdd6+gO@z;xMGF1Y1!p~E=J#_S;8!_@cB~eh4$c%qCY>Mv1!sq;Y&gL_`PiM6=N_Az{ zv8Z$6#jyHFb2wM?QNa6mLMhevlww`4PFk9;H=Vb= zf}A&%PbzDf{F>37Rw8m*`hHm~8DMqUy{-QzRu1BH|4~#DT2t78@y%fPQ4%4mxEPZq zFIFY{G5alhn_^()GtO^SGcRHj*uU2G4xC|DTR0#k!@?O6!Lu#%HRvK5@hYY4vUeM+ zHc(j9;C|4QtUihCX=7y;xh(PYI|@E@$SS2)u*>{{@|$2q=WijIDY>#zS;@v)O}}TD z`&+rge1S5gCM_Gr)a;8P)}tE}GzD`IvLh+he3F?`ZhVNkYi&{&4Ul1GzxRN08hp=q(g^WY)9qHejGa$xfD5QMjx#-?# z%=Bv^D%6`XMf;e1L-<!ty3QRJUg9lgw70mJUEn&s3QvtS=50|C=MgC_vubR_n|P#Z zcVgKZD;yAcV;=WTaP&jC%ctmQeTp4FMWLDe;GRkPxr~Jjoxt)$WxP+xN(1+@-+g~p z*lful_ydGC6rQWnoeH(56lu=3@$%Z!+O18YUFqxPYs##|_yre0DQ>nyVKuw1EYfYk zuVkCa5oO1LQ`>*nDMWuz*n0=MZFea8#GlURBH&4z)a{?SYB{WPwDWpG&g9gM74;f= zVn`?Ri+O?EvJG?PXxkm#aqV%x9%{XCs6KCj2V{Sy5rR;ka1Mt{Z2RbgGc>(B!_WF* zW+2u2E0iqhs;w6nh=6Y1x3_ko`!??`yk1qqxH%Tr!y?gh3cW zPXrKi06BYC4yLB&0SNqNpsi>s)x&*wYkAz}yTWTNRC(NFEPgGqSpnDFRq;&Bg^0Pg z@emO2sGV)=*$X4DC!=)~Lz_Rxx)Ly!CYjIgij>aMMFzpB0 z9NBxrwV@rRVpnUFM$N93@xz(PuCg6>g>O;CMyxgy?A z4lYRdRpr})#+$&AV8OtCEhX~69aE0xz!5(;kCcN-t`Wgo4JYSU6q_}wkhrYM|y(lwKq7!K(3NYLaxAbky^E(kr=k5y)n2|o<*ED z3|NI;Af_?C`lL4Kjm%22oUZD; z{jlZd@7@Q3s+yBzFG7M#h0TdBuUQkh>5-y~8lfu}Vu-v3eW|yBPDo^@oWmCXNHez2 zd~tB?)y|-UPR?tkfgNugwS-qRDNnn1IePJ%n~fz}5c!iQL*t$8ixZ-hqo?x14+?yH z5(nC(G9wZc*Hx4fZmuaC#9(!cuRvky96MX&Kyp(kQ+<~cBaK+@X>fpe5Wt^qwDl>M z!%2Ud!-ddKh&Qt#i(t|Q=T9wAsP{2kr3Wsp+B1zY3kh0efnv z&jFwllmh_p={7G$==MopHQCSYgAe+wI!hEm(sZ}6hzOeTYp#uZ$9QswYltT5O0h&Q zB_o0TZ2nofUy5I}f{TNTCCZ}P;1Eim=XTj)sH~@w?H!bFInfPFyy>t)>|Ud;Y4qQ& zW?r#?4DlPYl6e{p82}?sHN2>C{lUCc91lkE`pC%!<=}U)lcH1q-PJGK1U#+H| z;E+9@RPQGUYS1Yv2eqa=L=I|)O@AD5!VZ_)MY#>X~^CFj?$xw8K*mvC*nkNQ|xJ|hhc z%wd856xZZd)DvosQtivcjYtIV19Ct1XVEN z^L)zSW~)!|qJKepzl7h!ghTKHGoIx8qpuJXdF}0KY6jVgO7qh^cUX5#0+P8^jvzO> zq)6HyviuLoifuOTsu1P#$aN?)`Q{niV$R21a>aY*h=l~GbklV!Oi-_6Y~v$`@A@x-vh z$uNix^pU<{!8rWc^jQ#Wy3)Qlo58W{h+xNp1u@p{`rcSribOoG5h33Mg*z0`n zmP3kGm>YBCP4ZRu`9%AEicivdT;O_6ta^FN)1Lu@FcXarn`c1NeP5^T<~tMBz4~5d zgm?j=WX_dg&Uq>8l^dR=UghQB(uTBvgHG#lCAxlqD+50n3dhbnw16X9V4rlkhoP;ig^HFC_j2h@P`BDYaO;>j& zk66^4amxZ2`ktj6w$Pa%bP)$>TVp&uB*Cp9F|e)~`>@}jUwWOZ0#^b6y8CYBR|F3{ zKv5g^h+K(ri9O&2t{&pDa;h$ooHP)dTUDsZJr4{bA4e5sovDw@QdRMH(FcZR%}S`Y zh`h%2lM>lzCt@1?AOnVDIdt1$0b8X#^|#zwW@tX4d}lXTNv`Vsq(ql(MzIItCmV`N zb#0sl{?N{P)r0 z3WjSg!!+Z24oIPdil+9bZ~i^`Q>njm#aQdD%OscgHhG0-3^C;L3V(4Khomx)GUEtc z1Q*u*nr2LFnUjc%jqp^|Tvl_m7T{M*QCGmLcJ&SlJ)hrsQ4K20SRWqY&@C?ND|{SR z1*$SnB<|l`LEPukm7vUy849DvUNuH<#?mS{mXx9snovq0+p&X}IvL_;O4%rfNOIBc zTOCGCM87LYPqXP>^Cf;6{U`r!rw=aoZt#~|H1-#^I2kDcwqJACsVu@hHQ#k+1@^hE z>UkG6no+x~C?A`f0kHB&FpDI=>4^T~0tjJ0t_bOfIFUyb_S54J`lJ z-V~3`JzJMs1nsEz=m>;LiNRd9ZSmA0pamfXCsaMN`Z0H~LEx;d9)h ztT&X=+P>K^*DILdmZ|EwYS!VoU60sr{CtW-^VO?JO&0lqgGn?@XmeNFS(|-ZSyb#r zY%bevOI=6UW#9dq4>KpuoJ1cpJ$0j4t)vaU%DY9J9KEBW$Z3MZV)PI;TfUThv}SqH zq#E(&6s|>a5(xgr7}n2FaHY&1##MxH;nnD!xs#w-#MR3s?bVi+nx@Z^^go)j6Rq4^ zXS~c7{8OPxqj8!+e3_=Ob`s*a=6ZHPoPS$;gE9Jqx~Rv~gR%)0QznQ-77&uH5+P{& z-cKI?$psJtC+o3`&W3bnrxhorqSZ{Nz0J4YTci8r+~-UGos@Cd(U*)rdDPjBkAl1C zupAa|*U;c%>?}@F(UjgeFk=;r5MRZ>$k8`4>Z2T*_HN>M{x(1hJs_!Bqa&}QrgQ|b zZwLCg|Hj!7=Y5RLUw0U1r3ng_CTdLnF4{QY&*gIk$J!mivd1P%tUG)x_yzYhJ3JBk zM5M+baiZoAnpLDfQnebGQDw6WoHMKG1^v;zbjQfwm69jsWN3mV)a4sIAENusQ}AEq zWpL-`lD|_Oeqksp8H1Pao1{OQoH=IS$I1nlv!crI%IqbBX`@JIVhk~Zj<6vJdqVjw zDp$hMha@bUa_$Hf4^w@4r_oJ}m?(z3e#Y?d7$=GGyW0tF=stjK_r62fZZ)RaLgRyl zKUr0!1U}v$^^p10F>de%(#WZCe&S>gYIAw~Pd|e(T{I_l#K9d^=GNYl%Km{NuODsx z(=Mo}qLA!=!_#3OsN@H5Sqn&N*^<;coDJhv8i2+muwcHV%u|gM+hZolD4)tbNiU7Z zW#Yo~&eu&6xwVguXC(jrW-V-A(S6AV;xB#)=`FJi$`ee)>h`f;mHSZ&&}&-Xe}oR} zBQJGd^U_9M;rDl!1@Y{}t9I7Z}3ib9& zzmxxyd~fWLG2_z6q+&tpAn0WHu5`@SQdKFd(+zg9!`wQktL}N_Xzxd(5r^Lhn@w9h z7O{XfYYy)ZJ3V4FwCnwnD%fem^v<)rx7_&4KN|BRrVj=-!VvXf`4hjfM`wBesJCaO#?G zogbBN&L{lE*jRmVlL|+di1vEA|ABLz9DYb_S?ky+M2hXN@N`m_Jb4NDpuu}}|E5#% zPZ&oB?%blaErA~dvBwPBYY2x(8zbv+Ep@jx?9F%JhY@9WorguTIZ{3GC3TNHz%-WS zK7O(8m_&O1WhR(bOz$fBWKuK{WdaMIZ+*lbREIZyx(h!go8-Lx_|IQ_f z_dpmZ-M&UY`}yw;QQIcILtUeW{Vv}0N4pyUCP`Y=%&K*DKlVnQoyUdNHT~(q0m$F} z@ZUc_*tT;e&S(Qz)rqIl2IuT`if7djPA#ZgoT>22*TYe3aqjx))9HabR;fy1m_{JU zY@@Y=w_5fu4!v@8rw%I286Ed^hJr0mqkaRuyL@F5y??+3rWPx?HwtGARTUTL@7vsh zXS-U+hX`*F&EPR?zh|H1c=!8)3%2(^%;msxop%3OhCBk*17vB04Qiqcx#sb; z)qd}Cb*w%A`lEm8`~UOh*!$g6s-BBhE0Y5yKFx}4=5|mAo+yjnnD&s`Al}BmV-hXh ziF}r#Fw6>BauEJc_HjN1aAc6T&7-6ca1_0tcOEFfzZ+hV1P7U`n{M#zz z9@qp)hb*+j1HqCiB|p3?uvdb)knD)zHpUtfh)}U-3Y-ESaPdoC`QZjiT-VNro~uRU zk#}IT|FieqIR6FJGQ2dkbdr%13;=ChPYGHqJ6SIl2^yL^D!1{cV{wKyh$KO+W>1*W zqlABv?R1gfjwfw1fq+&frHoK$g_hB4_vK;%fdiGf8PXBk(gD{8$ulSGv`yAFmnTmv zz2-hUmt_dX(Vm?{c_cDruY~#|HFUuo`b=)}M+|Ar(tY1x5nIY_^jja5diyEiJFm;!>|@tQhYH&$k5 z(Z2z${taOL@?B#L{b5Sg>&D{sYDnst>0<;^vx~*7=(7<5a&upmWlk^V^hjm+gH8Ha zNj7BN(#TY1c@v{^)80DJ8 zN&+qW+*ntpWkEqszJ1kb%*a~Kf4V`&ccyeGqs%*q%1ys|qa&BLL0j0M&@gU{(;; z;b5%KT1J}|M7Y{xA7c71S|AVVcBh4JJOgMa0d&x2?fSx;FPfN{%_21)ZhE}>JUwn+ zx&<`LJGv?vpU;C_ftj?(X36W~r8^A|)f?jDyR2JAWASZ6yo`lVT81usxkebYF~9;W zi6(SK9veR#YzK*T&+4v_{Hz)}RlB}~0QAjvSwY#%K&3S!;2JT@c{ z(FGE39m{sk1b|&czp-N}Y~>7dcl1SbOsS}_S^@(-Oe>y_2usqduIiN!Fbr78FgG9Q zOgC=A0z7%w%Xfvf0yxLBGW3Pof6){J9uJQNQXkZDZV7&5JqI`U@2-r|=4BX)&r{|N zLr?G$2uoE(DNDK0t0uSpO@rf~4wrTQi+Ov`A~d59ql%{8Zzw@o#f7IniOidY+!s#| zxOF2o7Gp%U6s=da`xZWlwR8&M3oOy2VJV3JVR*6B_?eOQANTMVTIv^MKqa=J_K**f zan=<2*D@vPL-dza!*j&5aWIPvdDNOG;TCd_1JgbBF!$?t!zE*bfo7aQB32UyIx|FP z`J=ZkIm~1DJw!Kn94C`4@nr=VBxfU9B8#)eRP={*AKVN1A#+nbn~G8@Ex9`+yEnCd zt8&8OO_l<*|KnlJtH&xr*Z=av|Jwxq>s|JLe*ep2x8b=+c1b)5w9R^8Gp$<#N=VqK z3xo%p@>VnP6z;W+80}8OP<_n^NnBk3Ml68jDt(NPY0|it1!7D!9wLm+v}cry1jO{( zn?K~5*@UJMFmL5rvITJ18-oD4O6 za3!Q@S%9dSffN+mw2jWSf0U+y&a`0x5VTNZ249n%10jJWrggI~t#;2Fm-!fjRC6am zAJsHRn^5KjUi-`I|KIQJ7sA12QcTZOjr{l-{RQ10*>=Ou1Xp)izp%f>)+KT7$9It9 z9!=C8oC9qex_D~n*HfDQu<}6qCR_HEQboTFx#(_MuHo6Cop}thk5W>Jrjv8IF^?SY zT)^l!wM!}8=afe$6K4xDWaH|2>&)sFzJwUo#qiuvuC{Gx@jGLsjQAE`f&=JWiF(FV zKUb|+(qs7-zwtl5^f}Ur+U@hm;rkDh`_G4#<(TA#8QPa-^OXc^18s}!DK=BE!5Cy6z=c8s7}kj%?!^GLR)C>cB20O#jxXc(pCW-XL;yLQNlb zxyTL^@I}P!2f`x`;iYM?=Qmw7;Bh1LzE{m7wSmQ-2`GQw|nEeCL*`eJqxk6n=%Rq1L!Uc7uBzT<>Z#%pp z2n=g}iHEXlmPpQwpQJ;{H-Pmc4{~k#KTgxLvNIHBAn26|OQk>8)DsQsVUNmFO&6Ny z-A3I|tc7k(YBcdLH}#);_Rr1x|GhBMdOVLZ%1NL5FA?&~&A;+mf0>SFo`eL{cn5Q` z>amgjm6$XnqN~WsQ5@P(Sl;fYj{zOcCTc@rmo-ZQO+ay~4G7`l`N+f0aGU!I7KAvHkB2R6Wm zfc~diXdhN4S{mdBA+nJZMQ){$#^G}aBBow~74<{H(4S--msPfH@25fQsk)7Q3Mt9 z>7aa!IrWy$XU5J|(_7bdi5rv{-z?Ud9*qQ>&k>W`lyS?GE~5^M#rfI~!z=vVCbfZ) zPWA8NxvjCXZX7U-3YLxh#^g@e5L=@zjqSNx?=qwq%`p)kr^B!d#FEYQ%FmVmS(n5A z;E3MJdHtBZtpIX(3@KRZt%g8B9^`k@WqZhQM&In}mFr4Yj$m)!PM%51?&wTlfGeXD|JBIGRD5%Yw?UBhJ-ibY-KYQ^Fq{*I10w&@V}{PhrFI zWLrxMc58DP=LYqL1i~=#wK`04*MqaxQH?Y#C*tXUc-ns?e}8)P|I5Y9{f&pTe+xgD zn*%$K*7^bEO7R7L1v$DY75nI2PUswC;|NX%Kr+1DlRVj8{PYZ6pja`cp#j8hjt!gG7H(17?9y|4kSbMdU7gEPPFqmOcf3&>jBXlIJ71Pd zm2n9Z>ufAFf>AFV^#X^}-H^o-{~3w$|7EfM2zIqL zPCPcEa#|*=+k)^u)q(b5f6;$GSYM=)>mP!ESN!!Z?k}ih*8=S1$zs`TH||4T2Gg7x zjQr_PN{+d9{bNvJ^|^od1bp1_#lDqI%=YaoPA9dqMTfXj%<9@)^ShD8y>vGs)KBH9 zj7?w(AFr)1lo6}oU^`r@$=o^{_TWWZNbtg(3Byoqm$Z3Ze4{-E3`J}Q-wpa6IVvQ& zyq(yV;rM@z-~U^y*?Q!T5%sgt`+vW8mdb&D-0S_`M^j-1y~jS#}dL*_DR_y17sIgbqaQ7+~CATnqT|2zEmN zI64MoQ~tfDE`NGztxGdXv}$~(cjUr%YdhwpJzQRn0+4h!27Dw<$?YfbeQRXiGFA5E z7c8xYXW=?<|MnX5zMXml`Sz|QgdeI|n=DRq9RLIb;blS&edoDjz4!C?zBOdqD{y`@ zuCG%~mU90Ge&PR&>OMZxZ2Y+QZ452~EDGh^8r9k@lZklcC`u_6c~b(Oho|bvay)=B zR-qhYjzvUV{StYkD&l{q)&G_M|G!@M1%9qY`Rr&qQfJ?ja2uu856~ouppJ!1biFaP zJke53&$?VAOz_bgu<1=elg#)xs9AeQ5UJGWf9r?dD*R%ycgOY5##+P3%k{R*ZUK2t z^}E~2@_qtj7`iG7XKbu#k{d%-Yns=<+P|-}umcq7SZ?IYfTn+I8>v!KU+Io{pN0tC z+2Fg;kNRouJ>eK#bT4cJ{Po!R{EQBIpNmx#o=LLOC0o%ghNV`O>8`ULrPPprYnc@~ zyT)4u4x#PUmhNsS7O4%ig>5^HB0EHj!9%L>o>3V zv}#V&7i|8Ur!xk4OZ3gQkqGHTef4+gT3@y2^D9IR;Q>FY)%pBSLfL=$#+N=HzW4g^ z$hN&#z#9?0{Lfb_q9S+&67Que)PHNCp(j6Y0415Lrtn!Gev_sJ+Ly_0jN(j5`w1!Q z3B=eUp_#Hlmx*@Q%lF;+4=t-Hja{}aVkFOIR5a0BuwvY>JU%|rmJ}b)EAnYkP5oFY zY(+O;6wlDeb!e1m&O!Fg&=}K=veh;sI-B`5feC=I>^7G-Cdey9L0lT%CQW5U8sZ!B zRx;NkC;UvZ$3nML0-)GUbid5>g_~sJTF)~3(Laa-L zoQVc?z%nIiO=-=v=~X~C*Ko0g)E4o?;#Mt;PQfO(Zm8xqvB(qTkjzgI0-s{B8V=nv z4!~2QG?vvdAdu2Xp-%F>7M`3{D2Ag!r;B4O!uQpP?a|Jb5vqJ9-T;<4p|jE> zow6SqzAfI}2Up3X{=(ThvB2Tj_6Qlnwt)OF7tg%cwnOU|nvyRrYbSg_R5lQ|GE;T7 z)1Fqr?&tswE%bQ}Vu|06cqY|Xa}DCBcgH?UuafsX_Ll2aK-d$0?C{F!P-&r)s+`ie zuf-H-vo1naDpaVpsr4_!drGuvX9Q5y2*z?X$%waUGv@of+XHrT1vV8FHKa9%MQ_U_d z*MV1o>vPRbEZF%CVdx|TA1b*(v^{)PU=r%pbN2*zu)#r1uGyQz?g{P7xJfu|Njfe+ zgm7w(;W7S}(IpYltx1yA&YBNN4k{#)1$HZl+PY53DGP31DEp#5Oy-fwXTc|w`z@%& zIw@ojJkrOyklb`kje}#06RX6=2oE-LzKUgT)k$kEd4^g zH{9xeOl{)dmo3lT-}Rt4@$&B3jqI=>h99q%AG*T!{cw5Xc-4|voRVEA!d>A1liT_T z-Q_FW`*uv*(&uY>gpSStd(>t{60!kXkq!P$j{Wc9<4C5!W~5)Mmw=o~P=OtN>xIPR zb#L%NkoK=7+A!2(;b_}Bb0%=2VY%9-m^~4QTte4a9AS+YNf8(#egc& zrpkrO(+t+YqZt+<}D9a8LC26o{9QM%i9B|w1RjzJgMbSY# zg1hwyQF`>d{To&^R%U;W{AtzBJL*Cy7BCwX<7&k%x#hfp>9_>QQ+2cFpVhjsc%&u2 zYf=1sS1^XfM7&5GvYE@Vm|WZ3-M0c9Y9H+z7bk6nxo4gFNZHjF<2P~k7!OUG^fZQP z!9+2jihkV{Z`Y>S->{5=*TJ@YD=o%E;9h^D&qW*AuVY-CQI!TF3$?g5L>szvZk%xz zyhJ?y$n~Ecf@#L5d>51MoO~(YApRZfOr{KGQuQ}P_V1y{>y&S=DNSdOjMnUy&xz(t zPC@ee8NG#^N8`eRB5s!I&BU&u!F2fSimbgBJ))wdg!~ znfnO-gQ1-tc#L?8)e7pgN6vYis4=^KnuLL_J{WIR`^Z6u05rm0(+uVuL zl@#z!g8H>#YiwVM8nJZ?g=!StJ)fg1CMirGlWD4a<|PiMI83%gd`* z=I09Dnu%RY_NK4yt_G<7tvaIZ{v_Z|z)$WJ4%1xBr+juBdaT>*T6aBtp~Y0+hE$#& zp3K?s3-?@6?(ZT&dk3pGgj>*EL0|ccd@s3eZTwmUorK--71ccZ=D@7w_bqecldtSj zVxVQU%ijDP{EguE5va4Oty{;BKRZ7{s$NK|#-=b5)Tz?`EA78#M5>7O>fhuL* zdGIZatcqCf_WJB;woeRtp06a7Q{zt5-oaF{ecLOR#7`WG{<$*Ccbn>o{0VyB685z# zu4SHZovt7r^4$27gKR%`joe*>O_+GwGDrkP*7|`Bsa}x35(4XCfWmMUh(6jn6fp6T zN@|tKXsdAxKHzW1i zix++8ZXF*0ANBRzQ@Sg1!O4|u$9FfuS%xEic~muDq!?UBuu7xX>ARWf@o&U(^vecr&# z3G{DSiu^xt+MVDE}5SfS;^b`oSE0u-JrDvfnA;4Y(-uT3ByOdLGvE5JDymwStHDEg|i9LK#Q?h zV$I%ddOzDHNsxB?R=@3t3amo7h(5cTiH$4~a?h$Gnm?0Q{KBr@Oo>xa)e~{vRbqu| z>K}AIph`W=b{KmRM`8`j#ivdWTg9^1xz=TcQA?%0`cp|+!Mdvx=wujbZT<&U{E%Cw ziXXn)J>C)@sZ@&A76uCPGlH6+0l$lgc;V@S5EuZoe(cpDcS_#u#`itF8C8=Y!nZ0H zDETtKpPGbx#HbChvyM09dV{Oa2X)<<*TLtvfLw^BL;25WP%Z z^%aT$7T2hkALK?MQA#_%L2&N%zilAeP1prYuC=zlOP`Zh z7O^;ajZU##Jw3eLpKUV-R1av=PQvfALb;SSbQQF3E@~#NNVT>jbGY~4#j`ODjJXw+ z(96&!Tfv3!eLt1yCU7Bkr>qyNdE_EZl9Edx&n0Zd(E;_tKQ2mfI|eux=Ja#48Zb!x%DAHCD`$4Y{lYEP<{B9yBczk zX_29FE6RuUQ}wq_&~s&8+B&S+l}kONyd|Unv)T=8`BeJmErqK_sI0`X(W3sIbQ1|{ zbF~-bDarh5p;io?9Xp(qz*S7&H6iuVa>^myejNz5wFab9knc|bGc0A3x_bm*#m z;;1=cRMiSakoOmCtqG0#&CU8b(L8(kulM;n>BiKSe{y(XD2CrHZ}O_5si4Rah!Fg5kGlr zQ#tXeE4>O+_0{c9Am-mloQ(GPyuJ)#p9v;2rFiW|Swtb4T)zBdRe63Q_TZKwwT`;a z6x#*ld*o&Mv0qIQ{bEJ*j@HhfFFctYF>t!Cr)#)bAKN@#eG*Y6e@tft4DU!3(jnT4 z_gV;s4gJ|!xJSjvyS-x_zcYp1p;dc>gC+e&o9RySxj~Pk%sMCMQAf;7>gLNvo;q>E z9X)+g&wE@$7aAPJIM|jGd~#`a3K@>Ce<2r)Kp;EF-@{ajd8mV#4!29P{*`98b$fL{q`_R@2DX|1@Dspx#d zG3>KISf^&?pWzH>d7o0=0O^pE19h>8woN8~_~+L}&H%9C=yp`)p!L%KMsl*2i~9)@;^gbJ*3O0A#Q<1d^(pU27R48x2^f!xiLk z$|I6@RmPk;3(v6;l0mt_i9!3x70_X}w3e5&d$Z~e(%v3v0ZrU+=Y~0Bau>N7B=Mt~ zNrhAyA%Ll)p>hncDmccWz)qf`L4A_uV#oiSY z7;Y1{CL$&$F9c)O(yX94@~&Bhtwi?98uoE#)+b>oKB8`A&+=bBw(ksZn0{!kG}JH8 zXPM15sKZor*{zMl2(&am!)}h!9NXh%dA;0;_8|s3Ptb`{iB1BID7Ols3#FB&Ru|{5 z?(}}nZ}hmzuE=||)RA}Cv&3WbZT1W#q(e4HC&uh_gMOIcoaP=rfv6hI+^wR338c3o zrp~c#PsOc~pRv!r6JH{vA4X$OY2|Wz)+HN=<^EauNdw79_X=8VBnYPHqL*%_z znNxZB2`8#mQx&3zy34S+FL?5A{Glb%{d+cgj@YoeY?hTY3xr6Fas(2$m;bRHTVX*Z z0pm6wy>Q(^x}oU5QrMf4hL&ooEHQqiD2Y#Mr;6Mcj`ABS5*ZL{ZpW5)X7zRt{v}n7 z{J`f;&;x|wO8uKjDR85?+9uCu1^-`$tM%O!Jw5=`aUtW+>@)QI7p)&z@OxU2apQo9 zTOjR}NaF(V0Z^8A@)_lLBRE(4T*R452;tW%afsmYA^aRz`JSXk8MP?_LCSu0v8f(( zHIX8idwCyLL;$e+cxzi`MZ{2p7f74fCS&CsT9^>U`lkxYRKdVZ>Mxs8Cw8ofP_*q> z%-O8Robt2I*d8l446eUo1xIXtk)kh~FOD!a#N3F)g!tY-W)8fA_12LT!ru^!i@dz# z+b3G8`|h5sS$h*bnlB#t9*z1be>41s#g*U&_$WQ-U_fw(LF&L=yAax%h}>@>!PMv} z0FF|}+cGD+ap{=+d$sb9t114`@*t3CfT0+~&3Gh95a?Wm!38jQJ>!CbHNp^X6oS;X zhITt&Nj1aVpdUIUFtPwG;kzTe`A)uuVu#Uem8ybfYCASYr{iKV+|!C2MIsQw@>05M znp5&)B7)159Ty;y3@3TCafxn|6k)TvDA(MhyEK2@>D^_6Y==-psbLv5Gm@U3X0OI& zmL6;hH|9@q-Dccu4F{N1YXXTXZZJdL#AO86cc6_g-1mRtrb{@oddmkp<5^}gfV4M_ zi^}I$!{9H<(wA!s2Z0i9I~F&~fs`c6M&#Mub;p{00P^mBtB`XKEj5jfr25JS5n!md zi*EFWyMW{Xk+`$Va8Pr1MX_E08T*wEHvNL>#AulqX9mT%vPR7Hs8-nbS3>OuW9$NL z%mu&P+bkX#HrOzbd!$U(w}s>jbA;zS9k(3#W#OwH+!5i8yO$Ga+%-4V{4H8%*3%%f6im#?d1<#!C{mujfU^Ku$0WaC#-_t+ z9A@hcqa9Pz4Y>tadCkSBns!9lU``=;e1$F<&DTfwm(0}7FuKxE>Hcu=?qH^Z2ppNRjTe8QWF;~ zAL%xGsi$oy?q}{)cGHS==;Q#qD4X>`{rKnNc6Qgovj&%U5QF7n)Hn^`<6%&f(gWW# zORMfU&8pEY?7_rX&az8=hqn#C&mhZQT)?M5Wzs-j0HwO`-QU(NBg8Xx{L9kOB zBXiBa!xH7~XE9}u(V@tp0WH|*g1*)U%_21U1&+mVNs?suE4o&kgvJ%^o%J< z7htJs5?{>iq>X+FLbKG5`TsZ1Jf)PXa|R#;bZOr? z3+oMyCVYc=Dr$@vr*PAj+a@r#18Pzcn73qGfmv=8v=5YjqTKcnw()%Y==*g8zE(k> z10F?i3cCEj5WXmc#Ucv&o}GlI_Ky^Z;qnwDlXN3yh`b~FY_64|EU*11-=Rx}*-oV( zm$n6vBq~EqR_QF5^>rXrcuk&}llJ95*GdwG*<$eJVR?}Ab4R(;`bneN6I$%r8~Nce zE^4IeboTtKYEaGLNUM;2@**u8+8Vh)*tKHBL9m}dg(n%6{ScB{Xec<8s~>ae(S-bX z%+=?(;>>uYR~cNS-wtT1n5*UOz2PqCgF}T!iBZ>qJCwIIeFWE;&Ok$R$GAtOXqxR8 zdG&Cbxa3E-r%Do0*yl#2SXE^_&N=%O3_piYq_I*fy_wP*a|GWlc)Z*h(2{C@M9AD5aeeRR(YRT~vtOaXzzk(c7bcQd;>XiytG&OA1*%K$2OUz2gp z<$GJyfZx74o~vs7j>0dYp_SjMn#Y0Q9QjPIEcR<5nR!w0gkB3YFa!EjpNw{pThJ~h zd~E?)ZA8*bTTu^(>Hdq3OY^jq`o6|!ntcSr$)+X-DOt!1B}(7BB1ac`5tm2bWg)pl z@t2z6M|ha1i?Eod64|er9FW*hTe&1V7hhU2Eg*Ah3SRK8jq^J7ld$8wE!fisdlna=D1^#;vS!b7zYG%Jwyi>b0`( z(DqTyXh#rS5{0m%Ml7KY6OZgO(~pBVP+aA#OLCXAmL^K~|Je7>*4lMCZG z+OCZN^Q;CSdW0be@7jz$hz4;GNlSqxKk}SxFsUZdGo0bZ!~Jxt0;c`y*uf-P=~m@9 z61Y#~=x3D$3U|OKS{8$ph6`nSSgwAE|DtNAud~X4_PmD}iK%&rX_>66*+AtvJMz!g zRdH3yyZWk#D1P~5=P;5dB}UyRP}0jlo2<7GaZr3NBcnJUyQa}#b%UPym&6!fh= z!AiROq(CRLQ;3Mj8Hia&gro9>5&Pr?J>1f|n|%6N;Yh#3ID^;`j+W<(o~RAB6Py+H z>_)Fr3JG&V?qqigC3=^+HS)bm{NXexM1zedy89T|djbgb_t3314onnml$`E>$IjfU zWQu!GkFn@-*Ng7-A%w?da)fccMb_oUe`QHcKKK^$E%mFaFaJ#7698{TTdZ?eRqVY7 zZD&zUb(Hb_(562MwcGi77v{Lj-FrCzy(ioqqUBEY$S&WA0P5z7WHoeQE?2TBpNl3- zFZJ}#4+M|z4~VP+MJC6Qef)eQeq{U7mW@f(+67wiy_K62X(2a3xzNZvk{$Em*4!)% z%OwKE`nlz7ROP5;;FF#1-YrWR@`|SJ{$}kBpU^SM@nhK`9y%5w&O~|Nf=2}W6e6S8 z_KBBvFA)QNUfn0{9xX(^%3P+H(?7G5i~eelH0;#GFMza9N?0m&wgz)j!xAxE*x#7G zK%QJ9f0m-QX_3Z4cSZ7EXOiGT=FV4wd*>YE%@D633sGrkONdnz`Gj@BVCFsh-Ub4-}W0I{`ZkRWxC!=(kRRmL-SP7sUsB4 z>Nw=@#9VXrxaT%Y#gU7A3wsi)_(@7WQfR21r*Tfu5jU#1n1ZfKaZK09v)*73Ze5|N zCj~xpwo{Jc!`3vnQys`|cGep-F^ORH(rrwo`!ez*BzV3*AO1DRBgOYUn6g%;wlh46 zd&fc>%ue_f{dM+nZNCt1N4y$xomJqM zwjSKW0l2Do$x!N%Dv|ilbF*#P;(6s5+qBu#&$_F=fm<^x8 za0~X7XWFGX?_gqcJ$$%xu!Sdl zhCug4hUks)%Y=At^FkIoN97wjtDDao47b%jp6TJi1^m1q$eeGHW-4H-KR%4IFpK_j ztIvXT4^c6nXI^NIag5V+lf!|kZc0PBVOBu^374?oumA&ZU6$%>^`Xprsa}sdwMrfF z>FIVD^HkU=pJ_|XtTfF(xXWp+{bZt{*q(^IZBZ3TsE20~`|cuX90(m}wi&$I({(gy zp!P!`+p2@uR}Zz-^c*^t%yCkqzgLl3CGw<9_6dy*iq_b+B*D6i00?b0(kcA?>uxXz)aBR?<_gM-3yX?^h07sO<1uI9uIfPGBv8dDYl zPjB-sj8how1J6VfKY=u9o%zATUSW)s)zT58tPztWN+z>l0VTx6AJ z_n$c(M8iAUAToYo_WnAulJLvK^#K1Obi3Vk2sLkOyzB8GuC z?Sf^0pwJ~}9?5>EXA#D`d*O!XhQWAZPSXqCU(*ux%$@g<3wQ1c%zadqC3-| zvI=C|P9>N1&l@fLipV8tPAr_WlXIQpx$_aRp#-(DHPKHe)eCg><)TaHt#Bmdw@;Mh zWvq}e;=zc5s+UwUE0GDLj0@aj^?j-Pn(*ey#>sJJjtrf7r)lh{Jlg^3nAlT{e4U0V zIf$1!_*n6|CAw`n$l^kGKoYq?nz7_Wm(qvQ!$x;&&Dnx^&8ZFs?V0ZNxgMr*`r1~? zneQ`+wHd@iMAAv~_g6q1RWp04w_*Lr@oKx?8$MgeNIs1<8me@l)p)xBuvRN@ZiMtC+Fu>`|z*mEx{2?9}HqUb3bJ#f+v- z67<-&J0AdA6s-$8uCFS7vGY+d8{LVbV~FsQ^m2QHm}?Nxlu?+?usuxMo9#{0Lz!F9 z>BeP#!oD-H9~Mg7?4p8k9Xg2NM#{CuyfNvl5+AIcyMcpXJ zkq>c?1DsNEzT7hBE!$1abF}&5mDxFj;JC9ns~q=6BJ&fYPPnv z8!pSI(z>R)tDDhZzsuIpk`0Q}?m5q{IRu{|kPIOkCy0-#&R@*8=%g8Eh`wU=x!JI> zT^+y;tL1^bN8{@RlGIMZ1{EF7BvbB9cy3z0gt) zI9dli)M!Zz3Nliry5WC`geHlzv#P8@?DX>vch?k|oC=+*(9YVrd`qUezpJ8{V3Jd5hJXofbJ2^Vq;1`nL0_+NAN5L zDbP6iv4g;&XC%LbG{2CwloMkcJsslg_n^w%d9{}GrQd6!l$o!o@3}Yx8LsYr;2)g{ zs?lg#veIl(ZQy|bhe?h9tp)IiWVPN!rwxw9W0;MW^NvDD`0oTC+Vir4SmqOvP1t!; z{=toR6S+sSbmuC_<>7kBmwenpX@swhxeu(Y4o>uUM}}rDz$(+Lq5}#FM>K3&YA78@ z6Rz-FN~=x_N!KP=gOihLf(gcHoav33 z>_cvz=RU-KlX^Tv5!t6KJ|a^)$>=D6Py1z6kA(k=GTkeIq2Vuown`e7pwGefpmls6 z;ho+prFl0DY$vh+nDa_W1ZuBSp{IlT{zwyWM56YZXl}<=x%M#gaT-N?0O1hvibumn zaLK&;A{85u*{k0YB9e5s-;G7Hc7^lm`k8udcGRevzXm7i+l0qBz6bI?`wRe^r0nnJ zdpy0Hzw^rz^zP<`-t83?OUB)!-)del6f>J8H@dg~EW7pdcyRt+WcC4{#hCEHA|ThQ ztV72R{2s#jvCKYz5fyt?AZG=G)L-@k)niA@X@^|78ral{9lUd?%8sMDtAZ}kXG*9I z+J4AV8y5)vc7f^JcRY$*4FjKkm#Nlt&M@-AgB2;!EI2(&C&n8Fw=j(bcR5$U=Piqt;?)8kkS6b33Go zcczKUIa(Wm_`|9uk#`QGWmtjq3AnSUUosRS=tvovwaU}+uqa$B3HAxH=MI=zs|1FD zmTA$9H{Jo91y>yJ2?2uFZ=M$g$t>GDM&4oA{cn!bS^Ebbb+@&?xO2 zJ(+C1h<@eZ?-w9=w_8)WT1HH6?m0!f_nqIDd?geUg+1}xm5M>s~iE12#uOpOKx z`4J}t0(@xtIA}DfDT_TA=t(fuy&>;?S_&h!i4uO()~yc$3i}=vH05TyIQPK$bWh}~ zyr!3;5JvDTjmV+&d|}^>s(@J;f{=e67?a^IK=QuQjbz0r4M2g$JD?|_nI$)DkU?x= zwk++!16!6=0LKE?zvG!W%GpD*Y4+9fNG$x?F)#=3^aO9uec`MSoJyucP&JO;CvX+I zvJOqXp83d-d2djCXJw!78p2f`T}Uc(@n;CLy+XT_6`a=;#40Qk@9s8KUR}bwy-m9aBiJ+LA@+_=#qR$2*?)J=q+&lDE3y zM$J#qZ}`##+eJJ1%mYHq+d2}ucsiP8s?ouM@1?=}JmLZ-(6YxJ zv>i$B^9jkE=^WIJG`z0LLkX(3_X5Hbg__#gMf6-L$rF-`e(JASHex;Sw*=~ya8iiU z30k2@-|UyW(#exTlgOrbb4H42=QOxMa<>qYWuGV$bf0}x0R?y9%|&2J9ZaPb^3SBs zTTfn3msO|4+Fbq9^^atOslT>oMQ*-{irzlfFT!ch!^Tx~|BtH*R`-@fNGsRwH;go~ z`K=9w!t8HAq9^TqCX+X!QBtX5Hgr9$1Osm(2|gS0ezbFclhtx*En$M+zsQU50!1$R z>P;nL#2Wq49-|o_ODM>nC5_ioL)U|v{z|k8=ez}s9f{fQLtQ=Bh|hR@ma%=CsMAcn z-hln;wU?hc#idL*-g86LUYPO)$pI!Dd3^vovwG=!e4XSs!>9{ct;t|+!WygVZcfvk zp2YVKI*W7-6*q@buj2!5ym#CuflgUX15qsJXFfH&@*3Pu^J^oW0qme@EdaEW->O-* z_t*l{`fHr%Si#BnFRSZo1{x%n zV#WCGNX-@pmDJK>irt&gpyn+sQ_{XHq!+>(m){* zIR?p+PJ08=1qd%kVg{v!#7s6&xWW5KnmdAOmch4X50|)2dIbe}vTMVgkx0}nT_1Uu zi;e0TkixK^H&trZB}5nRpuBYR&Gdd*)z8(z-KUbp^M)l$UbC|L&>{DN>Uo_O=tCf( zkKUJw8_}}i4kRloKGTz)%S@i(aJ-Ox)5wTGKs{~H58F2un;woC%F^3_!cK%4i++6Y zhhl`=ZmAmSZAs^W=BY+XVUfxGj?$CmgG?}M z?M3hO&wG!k!hycd*5K4O_`(Qp_*3n7*dPcb{JPybO4A@E%@_=~T24=6^Iq2V@|@QC z&0+@ZbK7Q5I~cE>B0W^s2dgwUom!71X(y+qxGoA#>0uVFHaigG0lQf z-jPkc0}>S%fZ_CmC`p%|lhDn6=!&BZ{UdW+zk1ebt1s0jAQK?zcm)5p0Log(V%ToU z@-%z|zuXbGKXg?*`onWmHPHBqvI7DKBJNHR=Iygw7afHqZqBJj7^|vo$C)ScFkU%~ z3=_kLwT9!Ns%mtsT92X_mfU%AF5#;%=|{x4@SsZ5)5SO@e1y?-Bj4DszV6g&>OJJ@ znD16ha`ldNMYpiMIx#`>tCae~9c4KxPhzFLKHnSIab?JHJa}Otjrn0j3U_9V8p$4y zJUmfk3gxNmxv#weFy~*8FW3W2XQCAMVB1zSTH z$5QeGytPOVT=0!%j?Ri}_Wo3Bz^J)yeNnlaP2%hvhNlI{w$R&{1)1YP>_-U}!#SC5 zq$g#@deK&e9r>uI<;5T{=@L-0X;3_n>Lk0=VJB6i)+5Vq9Ri?*@fZ3J zUgQOG_qZ;A5l=4%6DYl+qGV%T5%a$E@$?~AdAs9_0(4&_trH2IIX%49K3Ndn9p#H? z-MRb0^RLIA+B@aeC<>G~o z!gZ}|@5}hqn>;ri^E^Wha%~Q*`qG-?huR3-0-RQ-|DH(y9 z(C$#CXKWAfi2tVUxudY|g}A=yA}859`?Yp|ot!0T)AYTFgdUT0*3A!h0{S~Os^M0! z1q5>+h)oMdUzcRrIWq#}Yx|+-OEt70GF~dQOKr2197u}BWJE~ht6BEdLc^xBv)ZX1 z6E^Uq16$xT@IK3%XFP#DR4?hOjlHHiC)${1*Y239Bnt3E9 zINT=XL1dN7R?AFko;Q29P`|Y+b8~id)0jHL30wV*p6l$^uyb!;_YcrP`jBstN3Xp| ze(Ub;q{KvZsta2I-IqLfP$FMEFeXFHWaMRFzB9-}_IT_=>TV>QtA`N zdMehWJ@&~9b)jo7pJ9I7_aXipY}`Ux>Vtl$TAHSMfNhQ|YQWCE^BK%X`~iUJ;03sx z-IU&_a%&jxAr^AV8rNPzT8=JHHLm0eajX=RJW!i7h>n`EoyuAn%cH@ zH6_j(Rp}&Rot3{PL3x|b>pwCJ_p+awxx+=#H!44-5lr#}gFptLyrB8=3t96w1=6>D z8#~n&eznU2SUxU{N zWM5ToxV3<{sTvZ4A(;T|2v$5?2Bs8*MX`!L9CM`~-9pz&THfyk<;^gCn=HAOBD?!v zv-PnIl|)tbN`htPM#a}aw$tFIWGvE6?3Uj7wkIt-taN=d&7d^K7;8CwLDpV=AGxX? zDSH-7tBe`}YNmvnjE@{F66U+v2uJd??2@*rr+W9&)7u&7)wp&GP^VUlbWjGO*ai6t zR*Mkn>UrwWR=IypHG`B~{F9wu*p&=LoaqT04Z?;0!;am1y>vh-{c>_CJeT`V2JYT# zt;2V+{2QD9IQ#|3Hvor8P`>@x3qq=++W55TIL(kGOZh!eIMr0L*qfD%5;?IO<$oD5 zb&P-3uvwB-zw>qd&fnPBsExm5q>NRc2-kWJdoyObZ$&GYO>MsAy!97#7phd~a?q-6 zYw`ogGFdu(IS3H09#mwiM{V%SnKbQ%N#{>dqwD-$CEpNn0_RN_y#SXvdB_4wrh*M|{|aU$NqrKluUfrsU{3E>ZaC2R++8+k>}b0Ua&b}-}w*i*OP3wF-!0MAmI`smz!+jmUcF^`?;=l9SA@->>F~n z@Fcco$?lzk-TJ9uR3|_eH`BcWo=td6Xs!hLP|{pND?6t=aJc5#1*!XXW7f?@_Y}po zQwVG6v>H$-y&#zCEW0{e0QG9TRz== zA@k-eTL^az?H_sbBtJ5#h;uhn`E^zE!i&3+^aB{HH|_zZfhP90!VcNQN^-+WNz?sq z;L7+D%KgP@Q#V=i)&`p$V-Z0d-MJbDN-0yEIebI$#~+)Qit2veIW8rG(Z3hyZXvry z(CaPiiLhC~j^Jp{o+}F0x#+(J{gD{}oyQMcP>6aNS4D=V=JlouZ%y&m<~kKyYd?DT z_FPCnSBvuXWOHpmM*}SpjXEsid!Cw8h=^PHEp|Im-P$b9Do6XuVxdrYrWmv{@%QGn zR|6gQb^V%txxmv%o-JjqXL?(Wz)!p1&6jln0sFVOw)db&6s&FTP?SEhRF1Hj*j?LF|G+g->O5h1`O%j%&U5tLlDe zARP|Q{A|S{SduzAIu`gBtl4b4zZyk2Wm+{UySGm;C}wUcm@Vur8F7mh5*?~NdHakk z)y^UFXwbmZ-v@+K=ny4VLMARHyrzmTrLDtJHhDL01{%SV=f(I-<%+7ut7 zdPOl`8jXC_;98kx8C0IJuVP6H)!zDau(L4p$?U5@r>p|y9)#IPSty+t>rS?;tP{@; zn05XY1Ex^@wX1>~SelLD#i|davmAig#LUVHk*Y zE=v3W9VJeqsK zWXUh#^;`p0xs-WVAq=%!0w#GCPGW@>S>n*5X~KAkhU+Msz!lZ1={$ zs&Z-hT2i+9i51(M%$rEe%B!8pt2m+nItMg>MHlZ>Zx*ge14~ov)Xu2p6VyDW#@vz5 zxzG~_21es)(wUcSoGf)da-WA#r=g%_YEHq}w?i>NDzkyTc@RnJAgRxf#BfhnE-${m zTN$$wu-U8{o6x?#j(&LoiF(rPigt1v;Vkkn^67^$^f=Rhwe!-6P(K^Knp*~7_5+3BBrZaY^qDcRULJ~+;>C% zP%XBsAJt*?P}g}{A3(24XiJH&x|8O$wif++sRUnFlOi3|2{;{W1flENh((&Iz_|LG z{bi$rZyLlur$~{~sYvb)3lcCp?AMh^cE^6LP?|2_)_o96&~-MZaRjs&-Pd^K=dDka zXZ20VGHrwQp>BuuD{`LnYmn^Giw}w9%PFlLNMrMAiJw4;a4++_-G|97SSoCwuqRic0WwL8XUF zWz127Ke=R_{#)5}>7)>osYCBF>!%BtEECqB+_9Vb9r3ocf%Z6*|9|8kf6F>P-n;nQ z9@w|Hj(;B$H9wtK6_Fbk1%22&HR#KOX;eqF@djF1<-@+N77q$*t!^^GkrO>BZw;g)Q7amr)oS-Tp_$gP~E1 zIZPhm!aCL7VszO}`Hp9HB_?WavDD!(B8=Je*P<(sc1E_gnd};~?C?ab6(ULdi0=WS zf`8VE&?57w;zkd(pyo;+T0O6>q6H6i_n(vtWvK2{!0u!T4EPfC9$Fsc&ToggS5$k|$Y#@0s(Kw>MLn!5O07>?fK z5TI7~(nICL0;)qd`((Amin7Vk@f?6pMnJu+UT<}lYzfJskQaJW{})?t9+!05wvEqy zH#0V4W!){fLS<=94#zmL*$;rv9L|{*iU9IC1daa}7dhbwdJ8 z_`^Fp&*eF5-$8>sR^-YrK=K};KUd5kTo(5`zEKp zz{TxadaR9(@n6PPqjk@93z9+n3Vrg03x{Ufg8k57u92T(d*p{Y+NL=E{!Dff)|>&K zNt3t0I~vXt8%;oSpBx#Q<2Akf_aD>{?Yc7+A+PB8_t2Hgjwu4$4=(j7fy}|2r{K(N zi@|BHeGWlrMT<4s&7pqdvK)xBe&xM>;W|}%6x+pLyRv-=asqonFVU|@1;Gti12RZ8 ziJ|z8L8#I78fK{1CAl;8dJMZNt9!i|zHRQ2n{v5}?cRDS^ITvtdo0X0H4;#eD|#3X zY3|Rq813KK5K!-ACHEtXrt#YK=4YzfW#>aUb?h)0N!+m@e>g6CUQ>#DF{lQ-dYAM> z(bbS5S_w*2uMM2l<1c20WUTaalPJe`QSbvbaYfZ!r=UNrrNfPWtp0p)_sWOTsN^;* z_&$-h!(1W{SQcu?TebFy*DCTHBNg&nS(l<&dWploE#X4n!{l4Zj;UW7ql*`gizez; z?ru)p84haZoU_#+He6T%*^Ip6{3C$R<(g#>2aZ%)&gku)imX3Rzy1H<0soBxL=kpY z%l6Lm@?O7U{y+Qo`yLOye?N|K2~h5FCgRIb)3mB9J~bVgM5fsz;<^U!mVjUC5Ld@~ zAFU|Du<78FD5J`h?;_#n+8RmNg~p3r;u!W+DGf&ew3WkBud zY{Zt?`GbmxXk{z!wRcU5H=u1D?ep=9@eJyub>ArPe$!q4jnE$G5IMb}R_$Z$&G$h; zbEAiX_32bshe}DH$NHeQpWVj!xoiEMNJvfV+i1oEov0^re>OqBI@sBtUlV)0Ab+TR zbg?uD`a>i@@WXv=u1E2@JOcM*>G7o#0q?RG*PzD^fouCZ5)3QKyJwRY%r)-U9c_YJ zkw;%P?DiYV&(ei!MT=iN3Z<1DFv}&)Z!lA*K{}fsVUiA8VV9#ta6q6WiET7Y47=fF z%(t9_yt*7IE6s?@9DDmn_V?5XhIz+)#jPwsJ zI#CpHK|w7Gl`HTN4Tt(@iC#aYhGsxB9p-R-I{K5~+{KI5{#%VI`yyw$YYWOT33D7) zwc=tCuOhZ8S1CeYn`##wGJkkWoE|W94>Q!mH@;f&EU0}bXa4SZm(`4IXlB&q?&+4i z<-3ex1f#;81z<ha`B_= z7>|3{x8@4VLy$@vvMV;Fi(b~h2YXs@d}e%vih|J04M^G87Qq*C#VzdLK@={*=YXX_BR{)PZMC>{-TI+PO{e~-3Cq_s6WiF7K?!s}s(Wwtq_j}{u8^o~n)jgZCrj4Zsw@us4r8XY@ zWmi7&k}`|bCqsfe#}l5J%%ZeV9=gO4_j1Lt^*+h9I(hGoJcqTdD*-wYd9E0y*xY`q z>gVDBh?6|p8FHm-Zsr1{Lp)Ijz2VfaOV`A{F^sx7P5|$N-~w(!Hh|F3nzFm@j-!XX zh)-v>Tv(G#b<@s9;(xFXJq!;8eGWED| zUt5DF41GrQ>96%Qqd%rDZ>&Y?veouvY4lR^>)qG&P^f%;G+C!8Iu#_$SZ`r#H`vyP zlys~WLSZ%we#O@IlL4SR#gI%1qUjrt5``QB35^m*I8TOTWsRpfH0RS_-|})WMX8&c$%N5_0`1> zq7P$MW!7IWKpB=<;{(E<$Rd=;?<;Cg`}7fN!x@uifmx+VbKl@KoK>f3uJd%2IW4tO z>(Tck-FZn60B5SdmS%j^F313S;zL3SCvAiMof)ZMtJ^o5I><;vmRikv1>(lG@xZkw zG;P<|EJ-Hqvdi2fQgrphSFm@HI`2}Ticeo-I=c-PdN8v|;R}}Q(S_#6@)GeU#Jc$y zaUm_=O!YMndDCtfybdjm@;|X$_rSK-ht71N&?G;2TQR>_7W^CoOBKHAj zMEZ(oWkJa!XQ4F1Z5tYRhX%A79Eu|qKm8f}>@Xpemb8K5V~`g1{`uKi{D)xC18Kn} zkC5A-j~jQAuL-^tx+P5F=43Kch-P2n38ByWP2wLL*H@o`$$j0LhwB`GIR5TjSdbrUP|X!Zy25X>a$~9rx%^BWE{`NYQZlMn)A-!+nm=IUvayY2ZNebyc*CC!(jfO<8zC(o(sz)`)0ylKFtay%2%zl-044(w8_umO~5Dl>Ik2C~`O#{pHOskZ3#nw{g@wY}G!eq%6Y)P$RF(G{?-7^5!v z`FXzv6m0SpS;`dd|Db!4Kl-VAw9n4_FU9y^q6U!qla zR9GB@4`AouTA$K~FII5OG6Z)B{WPj1$!O7B1Da8{Yxd{l>BE_NX56#=n(TxR9iYCl zAtrxxe@;-KVwV}$suY3ReiR4)K~%OxFD!XzSD-NrIE7S5R2r3~E7!*zYIGoXa_ zG_>`4qXKT;>kwI#rR`SCr$aM2ziioVFnIue!rF`>YbAj!_qrucIkxf94uf-&w16w^ zIKAMS;!Rm!z~)Qd8WL>4(^`bDF{(6J@O2N@){Okspnd=c=x zzSHie4Yz5V-*`DtJ3}0jdwq2Mg=KSmY>>udm56W~2uX2_7vE4voV+{dL~qJV2I^J( zof2Wlo^+5EYO}`OJtljqUAz0q`l$z_-qZk!gx$IGM``P`1Lq=!bq#(_$RkBz_-m1e z35^r1;O%fSNY8F;d?LUpF*crrrMUZ&Jp&FU2AhAt_G>SD!9y?Y{taAqFWXk0j==#1 z&}Qu03P10aQHC-@a>dZo(t2|!H00Y%bP1-c&H>dn_0=v5nW3^H@fa)4a%a`yK{V$4 z+#P2pQBl4)fei*kdw5N0|AM9l?8r%Ng5Gh zy@WqV(CD(K=c)3Uazfv0C%iS+181>o)67#o*nJ-Cp=f+}ZLm{A|3qnfceg$Uneps; zrdJ1n#%tZ{JK0oXzM^P~{*5l$hH_PLKb=ZR3vFOM>Bsu#dgSKFw_bbd!Y9nexx=0% zV|9%lmH!JsuF(GkyiX%uNMZcjc1PX*vG(G!SFkrAY1A@!vRZ8?U;g5;`qam`fd_tL zO}Fth*Z{iYUG#(WqQ}I{Nf`k68 zys1!Smaa3dJ)DOddDZGdd^UkFxN7w}Sy%q`h@R|1vGi#TD#!*Qj51OS?!kh7l(|L= zN9}4?BZ{c&eQp|KQPT;Ex9X63H$$tBS+EhCTxrEooU-Tb%7cRuGq}<_p!Wz9%BK$* zMB9WBuzdAxT1u5^=F;8>*MKWoUKhS1Br|q#8XKLQo+@|sI~|3J+!0R6K7sSerJm8+Pj=r0^`dZ90*g4r$+QageX;_Q zuw6>Uwcy_%N^y{*Y9*T5i_)Ms6if85$jQk^l({;oP4=LWt7(QN3FgWjDqaL|)|gGi zrHcLt&uatyLdC7-*V@Ehh8k+nDcU+VWEnp%)^J&G_)sI2htQ#K(N@e?wjS%RBcXcX zr7~4WPu+sb)2NBi*Xm^FWxM@flvGTZGw~?R`!FgDOI!x+6aO?Zmb{iOe7gZzAg#Gp z=hGE6MkAAt$T%Tt`p>Z$?g5jw-WyBpiht&X+YY@F>is$FxFS{N{49BuBj=W&t&r&f z?n-`_8QGTbca-F$MwQj$w8sOIkz}0oh+nNlW7?}HWmq`C(%WGc>0QxLTc`*Q*t$j3 zJQZV7WN_}R2^*(}k$=Po`=L$7}>f@-4{1uFg-Hv68D&2|=q4U9YzKS&x2Hr^Z? zZi1vxv@?@A&c=cMA;+`pO+ozLOT&A~F)5#*SJVbMpzgz)9g(zh`o@=SCZalF)ynqO zzs5agFYk!T0?D_$+uB!84@(p(ae%V1B@Lxbw&W$F+d$^zUV39rc%PPu7Aop>hhvNH z2(L3<9%d`MXIaHm&P7k=@(Tb+J_t^)AKtJaECtA_O-E~8G>k0Pk(6aCW`@AA1yZIL26&8Q7Ga6y@W{k&m}P2Sd7 z-d}Vcb9@R!&aRID{AETC*`o@aF^PW z+5hA0-}g__&U+6An(jd{vaAhJ+|=;h0W~me#Ke^zrMQtFFk*6KvZ z8-C>5$SZxy?~Hh$y)N!IlsYngT1=@@pOKvvrj(e}=55?#@h0Pj6CMxklj}=Zj;H&d z^>RzqLsX-0PYvbnW0(6`_ghk!q8M)y=31J{s)nPrSP?Z_OKcHPa%=7*&j#_1I= z^s_BFgXua8$r;@w6xDD^(s>b2Yuu}@m4Yng_Ozd=cb#e1uRy&6x`*oLiRFDJgQyp* z*cEx*rT0$@>xCUQ*zJ9PB`OsfCBXDoq}&~~Bu)leD$t-TXX%}R;>PTVdnuI>%uxD2aGm=e^j97ALhuF(klA$IxB^!i0>EY zT7FW`^Ur2DM$hvvnP1nJ+~G1@B#+E&u%~GqUluzXz5Ozy-e%C;&1sDj8o-nz+Zt^u z{m=7WQ2dO^;y91&n-DJ3H<4dpqeUBXa}M0Pd{#JR)`vza22%VTNwRk|GI{q>)rzgGElnoZ?m_A?m0L z-W>T#;1txljCIFhPdR#h-HXbC{xEG>7%{CcVz>`>)h)?fM1%R|(@GQbLOVOJJv>V% zLII=h=@600jZYzZV;R{YwiWEmx|UfNLu$+1my`~VqnkM7G4U(?v3L@=#2aa{xDzT3 zF+lnO#wMFEJlXj%;zTP9?mvkDk307a9qLbM=wa}T6gh!ITKdtqpA?6;(Fg!fdejdE zxYB~3mL+LY_HfiPMF3{ZZ_ki&s^;7Pl{dElLb07zb9Y{7_8}Idb*HU<&fLs`w6oL= z^n&t2)MNeqvrD3l$C5=&v(?8V37zqJ@Q`(@;hNf&i@o@G*3Z4{>23BE`Qc zfEr-FwEJtK5YiCX&VqFSL{NKcrQBFz|kh6fBcDb^bqWn z-AUGt>mA!&g$WW$e%r>?HduFlomnLMd!dd)mvch>iJoQjLu6&sr)Ci)G{wp)USHU8 ztFPG-y5LommnX@L7dQ3~QKFKDP6n@sNw*!?@kd{F<8E)!6wgR&EU6VtuxL6$)2)x4 z(67l9q>vr(!3#~hbe5ZOahGx;Uw+y7voz09@H~e4wXw86I2P4_nExUqObQ)RzkJ$g znGYenXFaahoIjk$vLH9*A;(BcqldmXWdI@8_axzS>TTaA}2XexyqFxhcb3LFP4Y%}F{`ZLD-Y zJidNI*=uLuzb_{&8iF4Z>L{zQE%ppi} z%Jwl15)?XO-LE3xE6RHNm2&|k!WS(I(T^jIH3>w*EPrm`_*D?9`QBH=&7bvuWCLBF zgP@Wx@hAvG_ERWKQZ5pN3NN=gU{m1{=iH4^#r-C@zf$z=o0wMudga}-eompsQW)(d zf`z0EU7QylI`XA|Ks&39X@S~!z*=jf*XLHDE(Rbeq4(GGoMAkHr4;-#NY1BJe(6@IH3!Y5%i%p>Dnc~h>~^@8rwxqsXak5mRzBe%I` z^!d$n&{Q=cE_DdFRGKKEd(_OZ_GWzra~1t4>}qQYDtZFnjNNq|J6Mf3 zQ4``m1qF>Aru!H10=%@982)<5uh{huF@E(nNZjhAnuc-?v?5Y}ABo@0H?cY>d^*>m z3!c;HgT)gINQhF)=H&5I-9)BJP~jT=!GRHdCa#R94`*gGXhR%>4QKI%EPpbFH~%iB z-SlT$vc&F`X{%Gpnttr0$N3#*5!0X6^!i-G zI?N3Mwy$W9%N%9zpvJLYBfXo4u?&qrNvi139_;YS3PbZ|6o+kkq3p%cyC{h zadqGs@-7HPm&S+NZi3ZhZw5G`=oRm^OhXlUt3$VRu3SCMeg^jyK%eOwq-w&j&EBEA zf95(lX=uf1y%H{ho2nSTXh{dp0~7t(B)+k;XISH_pN--cnS_51 znknuOJ;gg0`v)!+q?k}wC2!Qp_skGpx5a@ge;fy}fsj6N?{S#uw}EpE!N5r)hdd3Z}1d6+eI038I#wE<`*SCVQ;?{-jiWX^K?p}Rjn59balqzW|N03O2%ok6=Xd8F>m)f-h)Zs7}pWpy_nMp&C0(` zs4XK~XZtC&HIunJ^iIG=IQO@o*jRlDyo$k`+qNAUx+R7pdN2?sDSLf6=|iZnR*fx>w2-DCfs(X1QEaL>?&VP~f^9h>21gJI6bX>=0R?frm$JORdelVl=GD+ZB>|oJIue5^y;z?b z$UGU$>TMu)oDE~nPNl^rL+wC7^BS$HO6=#Q51Rg6u8~q4D+N{kRDE+(F}^vFWb%Jl`C0rI;NH@=*NZ1H&9SXCi;nz&Jb=3j>`i?r5673%B%T_BMlc+OMJe-g!T$ zx8@Vp3sF$<9FkZotD5P{rlpI0b9gRzA8v=I^7x--Iv8=^uh;dX)02fN)+lZAg5lz9 ztBwZ0U)clMH(YCZRlc9dV2sno{Brpis#cLU6Tw9%h@E%sh<9^Cd#Y8(Onv1Cr=&Tt^H0v*LFze z^^9StQ`1>WX(j35%lbXBcj1X~%nb;Qp8$QV?S~HOm+IDPYcXEWNFsqX2#`iF*a7`Kt0*`uL@ zi=HSXLoW(7{_j@ibpO8Y@bP7C(H8W5yK%>`Vmj{pwHt z2zI=%q6lkL_7fHTYTws!z3iQX;kZ1mI1fczwIS_tyoO8G|+su1kp0Vy~Yr^ zpiwCKV`(Zvcd%+P)99r48E_`&tG(@e&rtJ6NA)UGIyUu)bve7i^ABSl7kOWk57QOH zzzmJj9+!@LF906VuL16>yL5@-29S!wwei&o9(KcC&2dEh_!0hD(6JpCB!&Rwaz{Ya z>KA|=tl6vUR8+Cuf)fkYic#usHZOy^G z$WK95EHr#v57o6Yz-YX%(c5ki$TtcC*+369*9&D(MtToy28z=!7cp(jeZh}0JtkEhdqvf@z2}imqLW|q443207Y^m{ zQfG#N%a)ui_ECNA?b^2DaNv49W*A?$;tRItB_{5w#C<$3Up2{P&-?rr%pm6& z!UwtXRbJ{FaCRToj*;!2U=AyY^t#u0W~r%9Xw>(eH>U=dc9J@ptH%5%=+iN9^Ut6C zZb$@v#3y%)2L=q6ibFoII?_MB0%3pYJkQPqhXgkj@j%V1_M%6Yi4Kw>3a<4$aH=$~ ze<%%0^o~p%=i4Jjc<1cM-}C`v*Z&-Vp<}=IxDl4d#sAj&sz1Qme{S*ww0eAs zcstM(WDAJZ7rIg@xb&DKJl9XCyvW>QBl zfn{sCLDaxCSE)2CnSU4GHk$hT=$m``%>&ZH2PGN$%;Zu-77-^x2Yxyn0Dp1|^fy5C z#?Mo1GTu|b%#3%!%r&NzYoA>Bay2nMxN=Yr|3Y8Vzq&Z*-R2RDJz5!+bWMDYoT!7? zO42a_3nv`(w@K}{2}b-+Uoo%oN{&YV!IihkM9!ZKBhsl z&?DF3nu`!+Wj08JzFli|B*+$fgJClxeId(VD))nR?a_OX{|IXQYa} z?ko5HIwCtKo|TZ-wPXEG@U`orhos$m4P~Fqf|dsO0N?L^Zjo473(dYn!jK|(`o$HxX}&zrUG#-mBpwXNWlyM zmsl$;;IaH{lro8bcP@DKty^-2tqQgJv*c#8UwEut#f7ZJ7mlNA69?!WheavjF?HTl zqUL8c57{>U+5X^07c9SegLDE`MDsJJKB1C$Hs+I0+JDomK=3+BGHGr52luR>f z9%`I^F$sx5swsj68*qL44^;o{T-cwhY=mS#eK|4|*g%>?7p8F)P}J^BRi3{J#vxm3e-OEg24_8>}NB0-L~ zF2QBY2{he{Fhp@rMRWs?Kq8tE)=fsl6Q*m48Uf3=!{a{3`@fQmGrx{!w#l??rqilQ zBl_7c^Xbu${x}`;612tEP0Ppm_PH*8yZ{UTFxW=+b%hv`lxl7*e@&_pbIeH2A+^b~ z4c}<9n&(V{cr;u_+yNBh*FR(M*I^jzrH$q+mTM^42r4(S*e33S%;Zsvz*O-wm&7QX z{)y1asR@?(g|am0s6*IM+BJEbW%JUlaP5sjMDY=vpF9m&9mgJXPdEZy@2KXN@AaPP z(}Z7_ksPh!ZaQ7PAoR{bAb?NUiKx)Z6c{nO#bad5Z_w(hwdYWbSDf>5VB1n!pQ|lT z+iH&cR~{M<8}P?f7)rK+tR9k-x=B?#67_k7$0tdf_l$`3VlhOLmrN6zLA)D9!J>Zj z-=6>D*8lyjj*4B6UQYPU;s2Ko{de80M*QeGfIeRPrAGiK?aT%_IxrdC7mS1YE< zP~M{F9)O2u>$QovnAt}umFg42TiS;YE0&zbBECe+u3Q>}4Vb{_)uo>DF46skz914~ z5mU|}_JgC{Wuy2YTLl8_Ic_^RBbbhq5%Wy`Uf2|Okd@1iQ{ws-1HxdezrD-$zS&V+ z>rRc_@-Cx9>s6kRzw(L#ZN5H>XNt?upnyg4&x zAvf0icajoZp9cqz-Z!Bl zy27`mdqG-k6(xz^1(Szc6 zR^;h%MN?g(Pfw>pv`=T@N&MjDAXwA658|YMwx?%Zp!0u^dCf__8j>6Lp>pg@oUnBHI>#r_Uo6;bxXEn1a{=iTR&l<`01-Hg zJkc-z!^G+Y&%twDEKjOX>lv@*85Z?g1^dL!@>wO+IG62xZ>DqCS4n@mQdV1eZAoAi zubq{I>w63$gmJ%AT?@;ib4soQXu92D%v}n>B#ZWk30?5U0q8s96Sg|=JnoSTOp>Ed zA*^Sabah`rh2pJFI=#+{uIW7M|23}bFc>Ltww8FYN*=R=Wc{*ZnM>->`KWIjMhlCB z&jQ>N>%K%CHGz89UMdT0pNw05QNEOU)0lKdgIQJaEH++nxjPQPOx4jcUETT6_XbfuaWm@ij7SV56$ct?&Pjf)%8^^b z2Z{xNxMNuF(gBoI{!_+Og{n9DvV|7*?B+2i&H2H&-faIML5z!XaIcxwu;5X-l^#bZ zw3^ZT9h5cn5UO|uUH!k6=kl%YcpK}& zvWNdM_m$bbQJ?f^?5mqyc^3ponXCR*STiv?aCUlQtWNp}7150d1r&9vd$`m3LfxKq zkjIo_WAvtOT#q;5+(E6J>$?9A`H6=YIksh#09L)syeKO-&fg`JE*x9CImw3Kxk zLUIj>vV|&$ce1s6Yp2TRAaJJFTk`nwLK+Etq|&`Q_Z*C4{%G6Q4`*Wkt0evRDjy;aHuA8brOPRAna6zLH zy=Hu1e@G20$I3Ir);obdc%z}p`=@N&w+sflQvNY!dpe;t84AZ?et!v@@*Zks*ZBAC zP7Gvn-}o_9&JUS8HOL+L24K_Y!B!77h*4o{LU~&*b*^-B3m6q8xDpyJOa@xfTvwmP zAd#fCri&S|iET{Cu-RPOQv@wGmZfB&c=7K%73X zbwhU;z+a!bz1YHOACp`&R_>{*oy_wM!7m`e@k61L%|yo?lh17x0)3?6U@1_UOUcQ^ zS5EB@|6CZ#Es7;Hrqr&^?unyXznJVK1vx!-!8b1*)$Dde)0w+b1lJH;^emp<3bLAt zu_ZShHUe4nokxF(W3W15xC_ENihZ|z*# z^Tyb7NddU-OLf<{(9qo27gu6Zy;AeajXW1}$??l~j}9OI6%Hl#x|ztQ@*9H3lr1F8 zz$?1}M>y_t%nqyJ)m%f-QCneQ9`QGZKzQFUtM5Gcb?PD})i~>VZ0%}Xzvs3s_3}mi z1Q<{e(goO!T0DX^eTIAu9A5pJ2jVg$iFX;MR$6Wej{I_Nxh_B6@DZC+&P*&x#et?f zMiL5(GZz7b%#=K1U>3$Ser_UVH?{LFo$iJraQ>-UwuVH)rRn1hj5s7HQ7RcbpV)5| z1NOG97=O&^9`kZ>uM|Ar4TF{m&Orj#_^s+=g7)0->13KJ31Tx*J+;chM?1~eeH#q= zLp+0A@iwMKd>>vmhVRd_D+!ldM$EFX&FT)y!KaQU;~|qEIyGGw{?w!?#XC5UDEVBW zIO1d;3F|I2N|&_g<;Qq18cGSljc1GX+-R4iVd74>pM0v8Cjww!j;Zw3 zhgD#f+GY8@GGIt*^q!3E^-qkiOU1qRR|)sIc)cyeqBx zKR&~rooE15>Kq3L0?JV%CjScRFZTFBxf-+dm=&`$BkS9g1O>rrPfhsBL~2$bs^A`0 z9M(Pl#3+B!iEQZZG9{TeiyLhks7gU=b=K^MV~O4GCJueZ)y_zFHBLTQ%RA*^xCXqDoq*?uejz{cElpnA*54AQCq^QvcpNHEWbR$US4Nhs?p13o5agyP<9}@QB>8TDd zEm-5mD@yuooWuBb9jPjQ=XfrqUCxPmFTZ7G`i`}+W@PY={klj;|K>w5QL|d|GAKeW zJpWkbsR3UUKQ`6ERtT2>w|j!!lLcd0?(}bOjXcFd7h7e#@QQI;gOLIgaOkx?N}pw) z-OHv7XzR)QQA9i`#n^LN@Eo90Al7O*Z2XttjHFW&aulYso#I|_(=QM#N4--)v`fd7 zXzfaZ;MCIK{7%4_wpM*#vQv$A-P}hf3`2f1ztfwItZq0{Xiu0G>?WbwGmYWR9~IxW zPp?HxivDR-%PnxJvhCPqL*sN|9%Cg>vVde}Q?kAr|2dW4Exb>zr|$j#+!$f<|0iC9JUcwr(9$}9QJJnSv8l8Bs`C` z9qeXPgz6wy8rNAVg5YUA2*$NhMXeWqEyS0U%gzdJP{*g9ZI(QVbVlj*dTw`yZ_aTt zmOaK%nBO0+_#bh)_HwsvZlW$f@ethcuE3kD!7wV@*OK1VM5eo+>#Nz1wJ4vAT%2u6 z*2of-yS@wANzoqsmJ*BMtHzU8WpT=)?rP}StJGC5Fi52MYv^yk-HF_*ND?(wg*$_l z%i{Nj2vNvA_sem%&qw&2-E3VHTCBnacgESm>ynoq729{bCPajB3MS_yeY5&_eqn&r zd5c@{+>AqJR6Xh%GJu2gV?Psq7sRfY_YSH1+`FUk{H)jaORBoJRa$wcVTvJ;deLHx zJa?OuUTST4b^cC!g76EHCb+aTx6;~gI>!lUwvn=27H$Hys)#%Zi1y?{Af6ch1IkuD z<%Da=ISRi5f?98NGK1Kju&wO)B}`=;-{S*s)c^q{H|z`-XOzDIv+g*Xh?B*8;?Pn= zRz9-%@p5DS2w$AzVpM6Hl)mU4LWq|XbwWCpyCkoWw1y(#3(MnS1Uv4?wQUhoEk8{@ zGEzjzZcsmUHsW;ug@_Mfl4?wUg-qYu4~TQBX6~j#9jji0ptgxhzT_R8L=yQgY;6z$ zKx;W(r9qqXl3U}}EyFb`B5(NY$1fv8E#s-#zzP>}I$0xYWnf;vgvEt5)=O>ArPc$<9->9@b7#WrOZ{wWV{Y7wFGoFbP?_LnVOku^V4H*!*Om&j zYV|DcJzceLrG!jDThm(K%G;WXX2gP*khI$8)BC_}@k?gbA2HqExz_>;IXG>CsZxO) zac?rBhn3|a&>+j$X_px2_Q>!7vUrhC9cR^r8o-|o_pwXy9F;TN!Jg{U~Uv$5ex`be` zP@AHD1=xL+N%nq~UEi@N5J3GI&j`VT;i zN88e0Xral!>b5Ta^BzFr@q2^cJKEg&Gzf^Db4YO;$;H9Rf@P0`=TSR_uSUdZz)h4F3XzM_c>! z@jrGy!b^RQcm|LiHM{R#Fo2Dsbq9q1gr}?daw#Nk|6Ex-QCXtV3gwO)QTEu-hUcAC;c{c^(L{6A4 ztf8gO0rFB4PhH!?-hL2r-P|@J@T*TGVF?2A3ESma^Yt5{G%t@5@&;tT*w}Rtb4i&o z-s8tc(HdUC39W8~D0IPO(qSGMTzMo-=b>1#Gln#!C5&VDWxr$7qHxtu({{+s8-aT% z1VOyeV{vgJp)Id1l`_0@yw@0U2yV;B$tkqV1}_Ab@#trn6(ZRNQsrokf7<1`uB+c!jFS z4MG#bfU7(NlN4zNAtlk_QB1a$u6>qV@uF7QsEI zfdV6aoDv0x0n=i$2--wu=3T<-N%892Z2w)(4$V6{0~{q!pJl9sOcCePlJD>(aVc=j zIWW<(ef=+oXw8P3%~KliY)`wU4-E)eP-{U<0-mDk81>167GN56po-Yu6bPRzpQPXq z23gE=85;=e@>lBF-VZ>w%8Fv)2xz?u#f)cCj;_HfYP(`kDM1C1Fm9BzYFiwCaZ{(HxjzJ$uL52@*J}p z(4ZS0SeDSA>JinFXFK@3vl|h{MU>Fi2KdEbc&!;5_sBsaxSLr&!pg4>IRdero}*(1 z4wea=A_0NmFji^m%vefGfx}(-w=XQe1qQKrsBwZ}{VA_-Z!E~TPM!jnB`z?{oSFe% zaVT`J7An4vCsuYKqWM=8Qm@JJGhV%oNulDGks($u)kXz2Q~US1g_JF36;dfJfN@Lt ztY+*ftCx`rZ%iD4pYA30v>veGx0{{z}3k$wk|$`?8LlGY^&S9c>3?SuXCFXg)SPf z+WWTPJ(2&ADm37P-;>Dte8vWL_@_COuoZ=G?4}Ba6+c04C>GQQz4%ogGh^$s_IXo> zWJT+}f8yKg@_#V$4mp7b$UG*3a77uO32mBOy0V4GwtnLy<4Av^;6BX`*@+ymf4L`P zVMEBk*|fUrUTm#?&XslvpLc54(E!->FA-*7TP>68;qhU^= z0rmL%LOvJZ!}Jfifq0Dh{5TT~9nMgx>$9f1U*$Yrons=z4iPq0H038b~H^# zwsPG%`Zi5gz&8yZYqupdoI}rD&ZD_9NiVa9Yy)p}Ag~cb-Ta;L^|^U|?j#p<@g2pQ z9mrrSdHhrTQMd(;$FO}7W3aipBNP*O@-kH%71(POo9}i(J_m+(=ar&cp=kHT5p zsWo1{^jE<3%8*@=e+I81T0sPXgRE+UaomSRs+NXWlvJ)Z*qrr>wTd^q;zqsalfx|s zQmO}MCA}Pk--~E|14$!VSeR6P*HL)MUAbB?ZkeUEV3}(syv5FQXT~=jBd$;Ht)jNl zZJ#BRqz*h6Ou4-m0)CMOOEV<9v{3U!Fx?O8DY<1!zjPGh@ zTP9Kbt{Wj21TD(#0TsUDT^^yP$;qW`L{x8gVJU+R8|P0ZlfC8#%kNM%N>JkGp#jN( zGmz-105glslhxLU$n2SzAbHvr;vi2$gCKu+RI4tqJm1q|-aHa*Oz}VH=N7-nPiSbg z)RR6z9f}N*J-AThKeD$nMG#0R;n^99iauoCus89Iex*Mw()1KH1CM+NG9DgZJ!6Kb zxB{}-Zl0|$sU{>Pi_f8NlEAs<_qYF*q4rL8#f{J7dna;8joWmlqvd)+W&~u!Grije zkut@)?i@$Gk=Hzb74$EL_7k@p!_AO3yf0Y`4P}MpXM`M#| zsY0rMVs z*H(3Ef?tw2+C1I$9~Cn5)Eo5%58J++8I$bp;8WG=8z#CLL12wBOjLNo=Y(I{fAVhs z$zP>VpJ*G8uQ00u(7!SJ>xO?q0}2Cxna!Il5sTfu+|<4j&;K&6R07U*afyj>8`l?# zW32z~JEM^?RFu4JG6~XW7?%PHeMwa<*5;3?F6AUt`CF9!(pxJ^!bw*xvNL-663 z9m)b1SWkgov0eQ+=*riA>%Dba&sw#}D;SX^Yy@sCiYzS52+&*U(CBp|^psKhFee~S zc6su)nc5Br#$=$)(^r+^-!`P9UqoKY>Yn!25YCo;lNyi{XMAmg9x}}rXSH+ud#2}h zf!1b}jWOjgD-Y{LkaY280D4=fh2#SY*eu^)0}Pmk6cxhpu-p-{7={Q%`WR9^?I(*L zAz@8dw&;mwoX1l&tmiuO^C_8<#{ZA5H;-%b+S5b=i&htL! z={bM$`Gh;U?|bdN*IN79-^gs>mRZy< zM-ilB%P$2G8rjkS9FVvhZrEVrY#b;3Dv<8DDi3%5@ZenoYajC7Y!u^gjM&R@r(}A? zGNAS>T0XfOXbmHJ%C(ZOOvOM>Gla1ig?*k@k^=>|rI1a!Q@vL6r{kvCbJ_Vn#BfX{ zBjfDuEk)e8*GhS>R^DRG8%JLp^YdVi)j6L%uod6x8qEVT6(N={^LdrH>HO|8VUZZH zce*F&@Vn)5>kphYnYg1L;llq6Jx-Tp>}3a;00YvShSUopG_2!{ z+B4({l#Gd*ResbNuJc{ck;qFfik@oDnK~%l9+lKCHJWunmz%3`4EbTxMmu}!nQW>k zmE=FmiTh>>=b78T7I5nzmUrW{JjGNe#`4R8i%TXm1Z~;Gjt9nu)py_+j{X?ugG&p^ zooYYe`=Nsb`dHdHmxX;hysHL?Q+Oai@(;eo)A9)_+9EUcId{5p?2k$aVnAzt7maKF zU{jZ)kpxOYd!9mh&Gk6S4&4iG0TwRj(huaOk=la4a|#d-{drrPx4@7&4 ziE~0%%3^e%?>{P@nNXp@;-+aF7({t(F~vDL~1!_l_+me;CycS2~0jQ4GpJYbywUHn>iSGYu5 z^8e84B*KB^QTH)M@L6XBhde%dx$!^f`GdB{O=?s`HC2@=*IGSN1)3dWY1MJ+uz?=X}#3E3L!o zG6IJj6guWZ&Vueg4`9%XjlraQ;T5>aZjoaODPJh~YZuJ_NEijb=I5|qetbB@Ml~Vh!jzEsXTD}qo63JD$(lX4GFDC(Fb@EH$J7hYywX{>R{#r?)!-yr4 zULV5uLBxXnx`DtOi^EZXD>?LM{*;-(uSe+Ln9x0?ub|uJ4Y1lnbYWJ$51G)l>Yp}5 z`Yxb;bf6GVq;Qdabq3_c7fi@n2B3eSuBq-vzN)6G20W7AKeA3hu%{@7|H)R(Pdq_J zrr>$ynUScijv~93EMB;~C**&1lt*;eQqI)sPpVi_T^9CBPZcU7X=EhT?hz6Z#NN~* zZexsO$_uPl;-UaxQm>)p6n@4q99$r3r zS4NLhb}a1Ze(qKD1QzG>2C@8qbZ!5VYk3;WSj~7NcDZVdwOCw|2C}-ugKQNZCdy2HzQQpPf zQ>oI3DCAP$@VaXdTB!O!qiJtPJH#RBaN3?h+lThwq(xe>df)!*HvdoUqYWN>P%mON zOgdlbwH^2mHm){2q6rlALQ7zF97lP22wphyNL^6Q{S=))e(nnmQrY*7)|r=T^IwFM5E_2YF{8w-e&qrwoC^>z^vS zQ5J1RRPGrxz#jWmoyT#oRn)Rqanxc_8o6QQTP@*hqC@j}%hz&kNs7V2fM$PBgT8!u zrDId9#Y;i`9}Piiw7YNrNdtEJ+74JI5^aC#3cK@tMP&94XWuDTjAxei^CzD*&Kw68 z3iik=y8=&Q$F`LN?&ClE77)iG@gNaW@QtsrYnv*LDM}Z7oF!~8A2WvF%XU2%g-Rhk zhwbDK(n7^#_}9f%sGp^a7Y0^q+*4FMz^x12e-DMFtNSB(I@%}p8E7N|nY-jQQRa>4 zPR1Dd3;r25fR44`%sj$+{J#W0 z@oTR1^jMdoG*;97&4HM*MzyirG4xKU^s4sXp=og;qimx*pPjjUT(&s#rr zdgUFN6i$)QfBrN1|Haq8-EaN=h%&$l#d(yH9jSbQ$^z@|m99?&2WVey`CyvK&ssnW z{>K;jT{_QZ_TreJ#*%>xFd63pSUjqyzy;NJ%MSO z!=J{m27!3w_Hux}gYDW;YkP{0O|_jQXGHM^H@3YtO6@JsFcsgxGL>BUbFAQaq<|@Q ztNzbX4%=3nrt^$P+X{Sy`8Jj?`?Q^*Yr>1l8>jp*8QuNe@GL2Zn`G^P_#`^M@J4(c zrQN8mHlJ^hj$r}51UbhE0B7!53>ksE{&0MClg}VKVQYf;J$JOv!(^Zj+$GOFV2avH%ja8acc6d0*CBpUoA~W zV6F>hgKGEVGB$RiE}@G>?!S01j+&sx+mSB?HbvBVzpJ<>+tZ~$SK~9OH7P~RLmK>z9ly#2d?!eobQ=ftQ{HRbAj81fQY&56}DG z;$E6?V%!y-6)?`y|JOv2pU?y~WeR~RrMJrO{P?epip6@xF^5#!7&BD&PZQ`9O_Wg0 zoFN=gS7P*KSpdy6++xXk+UF|usuaOX84I%Vsi6E9k7uX$POOpr2|AO^Q)r;2{lZc5RR(tA=L>yUI z{poS>Gj031f05+6CHfpaO&U9f4q}S>+!3Q%R}f_76qsCM;T8R)##4`dM#Kc?oWhTDrHiw^#RDNH zou*UpXo=o~OP3xOJOFPUsO)3EhTLK=ci-#l`hvFIFlpH@(~F;1u&<@^nf{k8$_+d= zAKjq8F6joX$$#Sd8c1y|DH=Qn>aECeK~d$}K?{Uvsk|l50z$8*>SnTHWYLNF%Jv=H zVHwD3L`lck(Sl;r#iwxDL_AQ?AYvpjVTw?N%Y?6YC}A|So_brAsZnxiU`;nTTpZ1$ zthW>9@98UQegX6n8Baef&)xwRqZWGyFki;cuypfy^mP27bgM-Q+enBlg2U#wAm2~d zgPSdjLnF#e72@GXt}FSgUQA5HJ(9$!JZUN}#Xfw?`-owfV@+`CjZ~T#Jd}BU)au*dTX#uMvrj)rP*ih-3d|cjQhRQHyRawS? zQ&;O(gNTIyN8U63YQ2D>U~7-J6NHsy)x0>T^2vgm&D&glCO<^s12;UXz(`~%+@wZn zJs*jl6Ol4g#-qZW!{oSkkHIWG)>Zyk^hi(&KXtqnrcsJC6?s}VSOZ)m_=u2|bcC{P z%*o7Hs2oS%jr#&xuFO$btN{l zj=_brZ>P%d!VMdzBz`f9oUVg)kBL<-hsP-7ftHtKWv7QS+i;L!g!0ZQzK4qMo5s1Bw<#`rk+#waA=wMmyk024Y)xnjz62c;3X-KDVwAyRnqZs#+GP% zr-3)yYqDy5sineL^FqK@HfrM-B|P*aR{hjF>l@_4YS!|rN?^oyB)cKOf-y7yw9T9~ zrvvUpCSn!Jxo{dHYq>Wc{@$HHs1(MAg5|1BkbWS9_Lh=d$;?;sR+n=!5v$ta@qb3k zWs3;+4WQ}uGj6Bx-TN?zK-^@X;-}t$w0x6EM6t=REt!N{W(2%j!DZNU$SKY-VlJ+o z-;n{4TiQ)cXAwOPff{6=jS<{ms*_c+2y-1nTN0tkujY?`AC%g!xqAZ*2%#v>NedR; z>!nwM!iYr7cia*?+tDe^Y_4Ee)MAI&2`~e_zH&LqnD`LfXp{EGSiT78v|!VXnTb7o z3N^21^spc#Y`pSteqFunVx@uNP(SV~z6`d*3cur&viZ~MQ#w_LRN@F@zM|_XSG`WE zD1xiBRyRd={5%El@rp}8Juj#fQOmBIDvwnjQnb6*<}Et=+ddA748U!v&Q;k<8?uhm z4{yf$KwnXdhy>P(0%JUm!5;}!S=x-f?8=;$!lFl4BH)(0mfoh6Q~v zDtJGub+lH!j}4~9EwY#{y*^FY+yghAvcFEM17@zqXn>_>bxI z|HR9L?ePea?kD{2^M4@N(nj!3%rkxx9>ya)O266V;TDctJi}6c<~ePC=tA&Vy|GXA zcF^dys{!U&4?tgTeK3lp2PFuzgi313e@{r(Ix~a?E;TPOay|}2hUlp z*i<-Whe!;sHqOl+3Zu6>`e_AKYG>}dn^Qw|vLg7h{SdVu1*wUQEYh@Aj+^xPXzsIW z61~RIPzwjK%y#mfSTuXl+$U%iDyZzri8YQKmHc%lKrxc>Mv&1a*jGA^B6((_u=Ek{ zdRxll1eE$X55%*S=XV*Ai-blg^v|wmQA+QnQBP^{)fDhM3fmU!GO9D`Nk6Q)M3Se7 zEo(uZA4Q*#w*36v;Ksd~0yiZc(ySm8BX%YGe7g(Q=7F@y^sZp@E!9Q2@e-FW&8<~jfV>(gux)1x)Fo=7~XT79f zSMWmk>gV5!SC@skCdW^`o9B`?&IfZVN9nNW&6SY%%4CsvT?fSqu{4YGTU`IwY{1#~ z#(61S3V$;)arZSwl37iT@75hTs|CZG`^kTsCUSRV(x z)vDL@2P#_HIZ95bs9TOL4)1j3Q{L^7!i)uq-A53O>8xMS`DU7sTU5bb+!73x+0uS+ zcK!8;JFgDWS-(Ji-&`X%{gpO1i~B^oacl17cam_>pWku2)B> zXiKJL&-+Ua$6k@?m6R30U`<(IC!Jx7S_sKOwMjj$&6XFtlSp~SlI~%hV4YM2P`|?86nOj0=4*^Hse#udFdF_Y?C5G+ za71>r?*f*V+7`cEeFP7lEz2@triHoF2M5) z@WkB$K|+}3%x~WZ7^M1hfNlOv=zI@9Q-t^y7(Qf>>f1z!eycYBSIYaZ0b+i9BIi*j z*3}MBG2#{C%U#-Arg>d)XOtDAG{8$o)vxl18Yyvnu>gC2be(Xqh*OqRUJJjSYNlLd ziANDZv84jVdWFq46c@@nL-vs_iMjWr+Rf5*fFpi@gril&%zL_4B~8ipXcD#JFX;G# z)+YeU*MgK1GO;exroYp{soD8^){#-4)mf4NuXjZ4X*x3P4sZ(@cxTC~@JQxYT1XA{ zlP>09>h84&4eH90Z7puO!&!3g;#^gISp|k4wCH9VCWh}q&9y?D(hD0^tz$X$O!2kI zxZnA$;=Hy#UrPI$QMUk!SXA(CaaaM&Sr8JK?-TG7cBR@`}Z=`&uOD;eQ9&kN|&Uui7SL++fnhk{pBFSHjr z?pZX?5aT=p$U!*TFwd4p1QP^PD05B8YHc>QA)RM~bCI=RN@G)ENHA8fhcQLq+Ndy- zT2Jqz5EpHavM3}XT0yXmUdjJC%m1mMR{e%N`hA1ud(N51kfas-rR8{m z^80>Z8IHNV#eBH2%XS>snP4)`eeXyP3qMX$EFa;%wa(db2;T**_n!`+0M}+@s+C+4 zx^2%5DiX%F3UmYghvXo{AOc=cmsV^WgDC5+i(ODh!$y|(BF9KMA7i6Pm}v+ZJGq!U z*n^HM=#tSsTT8YT?HO@RGVy)rL+4>EWK+$x+-Bv$L`N&!LtB^FLS7kT^;r3<`is+i z`v-)`sKafRN)Hm~=awJjmI=op@S23eS9NFPVC+^%U#);ciOFV6{vKd)7va6CzV)NV zbZ^M;nb%ydTHEEoBL@sv3HuE3S=Q1|4riBBS5(RTUvXE`B7VADWW$aPx&dgeb35E7t_e-SqXj6;S?C+Pmh*&8MjlO><;QDm@^J* zP}TV>elSa?*zX81)`UG!`g|pSscXP5`<*R}LuNYmxkJgjV3nh~wy~uT++-3$=o|Y! za>h8lmJ`QxldshH!i#uDlv)RC;!F75ah?K3LJf}ubZn4w9C(CFj&$r~zG-`C3QCO%a_TIJFgcZ6U;OGhvM6~3yU>pSm1`O3lpy>Y&5e+l(J=Atnh%!&2XASFdMgSYss zc=HSH^b67YIKl(Fw7cO##^71iSU&)~EMDIQJdgOZN|n~rSQcO)9vbuY)y!pifWFRf z53*h9^Vke)Yc*1ESE4GL$z!zvN;$F(VD&OxLCEwb{w)V_|NfKeh-lF)d3H2D26C-b zfoa4dq=ldpu=6NzvCW zw?;rt(Fe2V8a>W@w8c)j$y{i4FXLNccbRDoc&m|d`CrljOKbE-FI9;_#C~;Wx75j& zAj%vMh3v+3f0D0o(hw9ib+t3ib&&0gpLvIHq(cP?Kko^%0n$msX+TdJ5Co z@TM8jAC%4dhcrLEtt!4UEOflASAj}T_``GoY$l@->3oewuAZICHm@G*geokk1(|gOO_!i%s5L+YrV_<3YA`f1V%e28Lr+<1xAcP8 z^jx#h2#R!kg|q8J&(E($fqwh@bnV@7UBPhs><}#N4uuXxQimH0>*$0vLk`tA-wj(* zu@ien4s>kO9lV0|!fElAEQB1;!j%C@6}>f3^b;?~%e_MXptca=y+ zj!YaZxF{d8?&^8Uf;*i96j0aaI=D5mf49!&uKzh?rQa+3nnL*Hm_Q!=v1%4O@#q*$ zkQLH-s6L7`n8x3cNAD!24frMJnsoNhlqzZlVw)|mg^S4*=Ev0d%V)FKK~J=&y9PtU`I*^4O#tG0hXmyt2W1>cGV*}_>Dfxj?Y8=Mhyo% z~86$)^Pn~F)Q*72|H^Ljx>eO!n|MsQqP*{99wfgbSla(LzUS{BzrHcr!4FW z(4I*XKAOvX$NPb@3rzfe>Lu1C+WhE$nvX7jAEDf^{1#@hm{bpm7wP&zW+H{04@uiZ zS2hw@4Mq|BIeaj{rE4LY@YTM_AM!*e(09Rx+>Q^S%h@psp+*5LQ?IXD5$PT`1{K!J z2Gi{yuX{pJ9vioy;%Jh{6{UOA%#;7=bN*|E5A$mxUgm*%9EvI2S7%G)(s3dYyL&E8 z+p$k7BPjZkq!iIu5?RY38Fq-4es(x8yN3LaCS#J;XePKG5NN9PrWKa}1&z|N7(poR zG)z97x}dl&*zpAdfoPgUwC@65v>k!7Vj(`R8iu_f)OK=PJ~mRyqV&j0ClC{2upavc z$yO>_UIFiWM>Yj(&DjDKMF>?e_BtpQBNed4=lNOtbgbC0}SY+C<8R2o!H!PQew(sIlY>3z?DhJfIn%5!NMm*1Fn zw)-tA#x?4^nv3%se^%@X1DLkmdku_}3BvMR7^X)h(uW#9+2J#XOd!IX<# zatU?maYv32;*!(_2FZ$_SA{pua`am2OyFB(Q=g$=4GPdMCweebUj({MoA0`Brg&{e|5`e-V2vPo(@u?GEm7duVrYcY=hKY)W zBsh`JtWo9ahn(|PHphqa)}9Ui9*pSE0h{}!CXg*}r$UUCl5@OcV7^N02^&7LbPj>t z0nBDHfTHqA7if&XZ0_!+#*`+LN!rIsYh?X+c2Cmvb#Ra&~Tvy%RFb%7`x{4?^-u-%kPvE*c< z%~Ddxy&zcsq>~n>b8+#Nn4eW8>A!#HN_ZW}D=4lt0|)CZSFx5*n`BhUn#r zYOM|HdOEu!w_;!1WLc~#3Lsmkp*Aku(uNY22d*bLYFw&HG zJV4mHwMIx)^Qn{+fk*r%D_&|D2s<#Wk`fi1|oLz5eIK604Ac#MyzI&y_%C^f{HJ1{yU# zY*?z0zmGsD=c*9Gz{cJmr=RD$mEp9$YcyV|rCX+5$&Dd`T0{<~u>K&*|@! zhq)G&*b;nrGc*lfdt)rJ7SvC(HO?* zkZ)mOt=rtTEW|2WJQEKScs5`A*5JxxRZUb2zaX;+Q;L$%@*5aYoe}bA zsH^#!Gu~VjpXOi`nmk!^NOIq%O*xC-@bO5BJ{Z^133Bq^KH>qamVDFs(o&y}zT!H0 z!f50@Z*{^T2HiKt8`huZfRz(W&;vJI#bD7c2~|-~9gaGd9{+&UKjs!<+1~A|@2Yih z)nR;G10jmF{>5f%=9HeKp*1_-akpsY1DyaB$%+7Mp3hJ%@W z6h-5fdduI6bQt~5s+P)q9QwXR81#gP_n&B6aTr$A&cPQla zHpn7A^u3!iMwrwPV8)z{ZXtbjiwC#y((uVO{dDv=rRAFRtKhd*{U@*O$p)UkN8{vA zYTLN{LhsqhO?uhU*BX1*nr7QB6uk0$|Efk4@%&U()9Ij4_&`r^%;FSeQ9LwVrfIqX zaUg~~G;Z9GV5Bvif6ccy;?8)w$1v90bR?ar&X9ji;OAF7?!cuF*an)KT9}$nros)Y zmt8bnOMvRO(6_$lU%J)E*pt7F>yEH9=&nZHlVz&4>zZ#2DE)qiAVj#K@MBgfdNB6v zCj5wD58txFQZ(Dy@hWi&H>dnQA7;RINr~+1*=`A~9x(AcpMc$2^~f*{Wj1xFxH86L zwlBYmEQ^IV=b`!Ek_~Q_Z6HAf6wzWH51Cj$EGZii1JAR%$PS{NV>*yun6u8 zQ5WYNmCcn^yowG77t+z|^)@r$tgQ;)GD`nB5}e;R)>~ABdL^P)*fttugPq31z2QrJ zzHA7^VEO$<;JKu6`-vCsE#2x}`5{xq&QOd0GJm{pnj$*l%paQ@{fCr#-#XC#s}4tn zzx~YLmz;12^b`8G$Db;mOOMgw4Mn(C;cp+}cLT0KzttmWk2&rHFgnrY>>rtK-xQa( zbUT_3T)ye!kk-2HsCddTSsoXW2(Fl+br&H_qC^AG)4VlqfVUBSEfp(DPM>S3+)EcQ zclTha?6{6k?HtVwU_N0=`_wU7VO#BR;AVxxpZJszD4Vf5OVy``m8?35X*sjRN3p-mzDh#-rj0-l%?kHvXX^61u zjI5UixK>tYMU@MvmCvC+x9l5e`L;AJr7H4*^vN`c*m^$q)Lk!7`t*fd{M&K5`qpvL zQpJMZuPl&m&A=?J2jsP666BC2T0O=pTrQ(W>xU{Dh?kvD!>ml!1`34K6?xPVn5CzqfmTbAh5uF-Y%VzLZ zz@(mgN{MZvo_HX?_Lu(;%j$gm`j+jt7FpB*-19&D$7HK z&2W;3muF_h{)0f9gd|cRqXKPVY31KdPYys$eq%kq653u&9e@Q4>4x_8j`b+qjXEIe z*4+?H1yX=vS9Y$}QY&D~Egul!C2xQ-7Y+<)7YnmQ2l$4toUREXj+_K@w zRd~e>mil^6U2_^~fSWj0_Z*<4V%-Bs# zh6TK0W+g%|K#hr+?=#8A2u}=T!XJhXBpuP;PB+-P*516Y&|Ir@$Tjerv2&!4VXOg_ zaVraO+o}S$O0>l&uX=H?t!u;l1I=sq?Ea5A?{yiLA^PykZ(Zh-Epav%lYC8t6ypYE zixnfn?<@=53IK=~?9)MRy^u1?8>dw$q5_!d7kuq<^CqxE7Pqgt27d*Rh~i5#<%36c zV6C@wh|3-8NfyQy;m#?NaNYq;|7%M~zkY=3KlZ|1JDaB9`>^b_?*BmwF@f0t4P8Ew ztK$Odk1L;ClbB!$`bs;YtVvJU>#)tAH+d0o3wm}RZSMJfoo^jJeHO9qaoPo#RzS$C z--FeO3%bhkf(yCS1Hnytl-^gqB?-Uz1KsCk+mAC0nZ9GP<_G&>ZB8!F9oKsr*{D@IziYdq+h?AOoY<(0+@Li9LJ4HuFqF>j38cfqXSt!yzLY zR3$Yvz{SZ-4_R#>+kU=H$kZ>Li!ZaAv8=W^A8*N;CzbZFfeEUe!Y~>l+wXe*NZdtt z%bCHe%LEk|g1E09B@!Wi0HV0%8GFs0x1?&z+dY-mZYuv^X1MTF$V1UTdVTf)-Rgjus{Tm1h0zo`zt zlss{_H^-%SuiFB!{^5;7lbqY<2nU>ne*K*PoRn~M#i0q6m8^3C^yJQPi(U-v3ik9z zWIOkXEgqB37}hQcE`+=`f^S6MSd}0+bVx_aFgwsBFkWeCZm8>$}oQ^iSa}?;PBE&p$Cd zg^@GiWSUbE7g=uV`{BEbti3UfcRuSzM$Ny8E*|}^ywyi2J`O8ZSUzH{zV7h!aEfN1 zSg^zh2M_u8G;Vr|?tP}eWkVJAv>*E%7EAKgrf+svgKHAlr&X<%&F|Q!kBW}9n~_v{ zAo(xpUDze^%d-5Sma^)a1sSEWcDcEXQu{n)@qDQG0gCLJhAVrjXC1mUm=u@SQc*!P zyMP*zuXAUCEDB$V14Fh9UOLWtBVT(;T*;d5PZ|duOQ~F5WX)#m0T1VSew^|!k>sg{ zVJ(jXqHSY;v8>pKLq5+BC?j}#f~L><){H4gRM7-Lr#t*MpxLblT@MTJH02 zSwo~pR9nB9vVSG(yO>p8nQb*V=(v)?i7JUWN;1-__KZ?!)q)9CSs9}7<;%c|c^_p$ z<%lw(B`q6?8hmqlX5f-u%;}IdDAxBDll)g+tOiESQ$61h^Dv8+-*Am``jZ;d?X|ycsP2Q zBjrBznvZ1O0 z)N%RT@gti{&2aLU9pe>GKIu95zU7KjIG^sO2`usQyX$}>FGGH&hjPk&=Zl{XMeHT= z%kl%Pg|5(9j#(P+=c7}e)hV>zA$VqsiLwGdeXbsJ`P2M4%bo;X-xsW1g=#1U;*Thc<9Kr$JBq=)wmhtEvrF*xy1Mry>o! zbg-@BCh_@jYGCYJ;;2btGwcTOKg&MCHWve*k%#Xdh5oImG5w>dWeea3uHzwk6<0G& zLNwak&z6JkpbdK01p^Z9=p1tRphvnQi66hV9<*b8c|h(uc9C zpGR+YHB^6aGTjQF`gyZ|DSluzBcO;Abe5cq**Gq#oRWaBvLB{`{TydJ%a(f*F61PTYNLsfo{7Vxn~z_2(k0`;=KCqm z%4SEfOZqC+p*#uB+mi*;G+Yl%8Q=NNdY=SR!J59=g)e!x&{2Cn6HPDgFZ8(=)z;q4 zi>*p>I||*-YW7{enPg`4C6DraYdx?t-lzJQ$V>-8pPl{&>o970-l!UKwdbS5BhV$4KwpD zFDHo~U-?76&~}K*24<2x|4TQdsp*=lQ;y?$-Il-0$(Al}ju`Sw6!=`@sEzxmX@n3SD*@3B$uUuzlMIYokTo2ts zGb4n2blGe)*Rqz}#`{IK9pL4#G%P5QB!lvT)1!?!Hr8dZkOMK^U7ig;pO`prKij-d z;dQdKzuD0TJ6*|yVJ8u=mE|WEppL4t-C@aPjUG_`ap@`g>_8Q)>w>1Zpke;B6^7t{ zKe1yqJqbdu3LQ-9UKb2F zM{FkCx|GG&w!j%RHdbJrg z_SES+BwXwD#|{=?eQZs%uF28R_pi%9jRDo#NB7sKjso*Kb_z-R*G9v&HNb6s&8N=B zJ&d%^F~}h5H8wEZYuP))kA*N0C<&7PRob4Z7w_bHblImA7`5>-ch4otoH?% z+&~Qk<)%HQU2U8w--Lu3! ztzgV!a@Gcii7U)s?K@p|rK6^nlc8|kEQ#XWPS7-13A>mB4U&PiUgCrw8&~>wG8JeW zOG#)SjZ&2veHKww-ec#Kg;@S141v=G0W3(q!*4KtpYO#?RK7^BI-(|gfzF`!>q4s7 zlRrZD=eOO?(bAAefC`23QDzQ4>u$3-++w4Hp?bNa=n5Qv*Bu-tzQEFt`mY@fZTXQ1 zy!;CBf5m=K(+yA~;pM^vw{rBr1BT=F0090@0?3WGuU;n_)G+6;S9tkV+N+uAiPUl2 zozIR>&18vi&?jgfPA%sRw}8dXC1`_}^mzH1&+F^}&wA%>Sf(toUu_1wHll|^Tbu8h zA#gu1nd=VI+g^&Fhclo#4(Si$bFz^Z#ysj4U-h{oI8T6}wOtwyfDQPsoFE|v?s>V% zC#Kv{oq}Hmk~Xz;IK>Yen1?_p76lh2FW*(iW7QRuV|Pb8tom-~@c#r^tvw?uAN_9m zu36r|aMI5j;T-YRHO-?VDTkzyH9>ul@% zt8Xo4b_5^??i5j8+S2>>5uh1m!qiI9NBN*PGAo?hSKyvsi<|tc)JyQ&n^87udoItH$5xbY;L@-17Ucj%fWQ zLZ)X#vpl#)Zt2Guk^weP%;J!~HZGT|VcCc;=grzmESsxVy>*97zsL$=oSUg3x9;mKii!?OR7OB)A`0VBLZr9E z8B|0BMp5ZR2!cT9JtRa$MWjST4LvFfB0>mAhoF=Mq(o{$@1YAJg(QUVX6AQhzV|)n zJ8M0EJX!1cEBn6peeJ#P>$)aGlhmRXR{^70wk=2c=06UnWn|&=bE9;;bXGS|-^LLi zExQnGKhmIMvc)`5P_9+M97tlw#J9dB1INn~%eg@-(AVLBDLyk1DwuAaZ{#8C6o+Cs znz6;#f|I7=$?}a$OPTb{{@j4#xrfchsUqj5H}S5>d3Vq-b>pjgWF_GK1lSM#G49KO zs(lz()KJr)TVJ!dMeM+@(w!;EiCx`>N@jK1ZE0Frn%oQsybM?nRoV)&*AH8lEq~NN z0r=U=a|U-)2MN`zhdG8PMh8^zmpZ3Jxu^666i5^mdg~o$ap01=$oO3(yF&qNMuL3= z&k(Ip6t9pnpI(R%Q`#gP9|qWndoJg&XYosh)+o+{DwKaog~f|%Rg zr8ghqZzw*Cy1e)%P5iW3(A#DA93#Lj(>)uz9=_yqa0m{im*g+uSou zWh7M2L_JBRD?8A>`69Y@c^%eP1j(^)fb56D)LGy7ZftL|~?y&&I-NcD}*ZDn( zXnp~D*zJaBvJ`JM9sTS4UOmL2OHs-0N9<#RZ-WZj->Wu6U8q;QZDd2aWV(D>rljG9 zzrTFZMfmbpiy0~M;FrV(?JS8b`E@1`3o=>uP8k>7W^a+{;2JdYy1Z0gjh24je5Nhn zB+Al9r0CNL4bcGO;MqG@LaSlG2_Tx+K}{bz61$?iTgT1);UO(p^puRfnW0QpgA?=q zu3P#IS0BM*ambB!Y1^wj?vjEZC)#1jy-EE38|>sjztO&UAKYE_6gqT41s|dYT_nQi?=sIgk&Xj{hU4&=`h@ZTo_Qn5>U5^wUyJ| zf@|^F^BkaXig|K){A;mOv8J&8WM0Y|dS@%k8fbdOdxZ}JXCr-mm-xFH+3{*ulV`4E zS9>R_Rct)!3;#)6Ks!E@D5|q2!0%NzZHZx=!6!(`R?(~;~ zYVB&dEnz8+=CZ9IHA#Y2bqL&yE2W=Okw+<5L#@Tgi8D{&E2rUc66p23$Ah99Ud|IG z1*J~TgsJAZ%$1wrPU6A3^-uD&n8+aq0D^kZNS7Q^KBtZ!RnJ0^*(F40~hwAtV(tLD3SAl*ziG>>?`W%OPK?SY*2h) zOkZ|zv0t9koM+w<$~dO96h8riGDNQ4=*!w_uZ)t%BB1;cyjwkUHB#SH_ySmO z{heACY8sr7@k;^9LsB~XLyUgR=L$QCl-ttH@*;+<61wS90LWc4)|kAwDo&(}+{uix z=e;rC6R3!caw-bkK5wk@$}s3I^3zS1bpkkad-ii>$degM*th$3i>*xi*fsTM&uow|qa?eaIAA6B%-~ND zROIWp-~HjMSi_?Li!d&$NkrsLY=Cd&L^d*qD^UgeIK^qOVzb>AF?;Px?AF`QDk;3d zWLXDK1G)o-puVqcC!%+Y)d$bZMhK?6Y2o|5^s?~xY3Z(nMJIDuct)DtA^2J->PB7Y zA6Ic~e##a`$H^|r{k9Zmov=7;U%a&4ZW~)xtWtl%jeC@^a_E$5BPZF2!SZbp4SVGD zwhn%QMXkj_sjlI-LM#CN^M}=|yR$J@>yO5iEJ<{=7(U0Wp?}$S1{B($z8s3Q&gMbOg}hs$Sb!MR4l_@k@egRjKd~7zmX74iqCB z%UA@u)r%ZSD=CM9Thq(~2>oYME~!}vS{*@Mh40Ol<;i(baP|owRCC2y>OcIpDE))g zgHqIGCo%$ez_qWANP*!FSqfdZ*l^T7?n+NzLc8q*>MF>KQWYa6bP}>MDesO`1fAYU zpK^;*w8rw++&E4Iew1>#^2gTNwf+3~6##D+5v*Tz*uiLKLR-&eY+2EiR2`VMNUB}-57)I z4}0RO?c}$n9xIuE5&YQxcJNhq|5$!$u!{m*@YCu1_=`iCRK)tN9|E>ssHKqtQ!NT4 zS(U4Ro>|eKkwVkBpzb)`)y;`|1W)RgwFYP@Q4PEpPfD?xGDI7bPoUEoKca*|gBX+) z8nEf5>A?~^Ts7W6Ir}GqA)DSI1)x8v8G4E;sgl01>OKo7r{$PWn^fY84+I}X>$^|ewtO(i zm90u(kX`&g04TObmAYohSK{8l`D75XxTbze+rGpI zcL)M9@sjc~5*5j^GfopA4fnAJ+1%#b9IsBI^k!GEff`Y@>O>}R(9|B$b026D`mmA9 zah9L+);hSVwA`C0y=oB3ga5v>E-s0PXw6_Icg<1MAPAUY3K&;^4_2%f>wB7^B0Mu? z{!KLNmwoI}mgrYe1zv(49nr;ib=s+E z{3b4DN=NK^&+I}y%pSDX{OE^2ULETp?4K&?-fSqwW$epIlp2ZA*uI0TF;;wv1(+!jI*%`_m8`GEM4W~r4n@e%;Avr=&79{-y!sW3HRFl;T5h|o zOsF`Sy6WVinyzGPbbm#OH4A0Xy1IT97oR+buNvkV3Far+sE0TBPDww=BF4 zNW~+PThGY=rt<9Y%MV;Qe{kIs>`^X{k^|_!;i5z5UZ}?|ZhS4ODP34)3KEYLu$(ws zP7AG`V#_TB(wx@20b)ABQl9|QWh%n3(xBGsDgF||h?Ttd0D7qWzN(~#-BVi`r7%mT z9d+~?5F1`Pv3iL5hC8F4el}V=jeji`#L4~)Z8^;!;_8zd`7LD2on5X( zwvIP#u1N_hJ1{9U#ql>x#$nR-&6=VsQ7s_F&emN}cABHeTU5zrW{|AtHy zEKsY{FXa0Gtx}|>H|N_mWFl!*sh!}S@=K%H0+%9W4a{c;Z=E+Kte+oN=UgYw>B?L( z4sQBNRqT+Kgq>R+`{iFr5mWVj{G?qU{We$R4A%IzOI2|U@1^8TVMb*GX8vDw_`JWvNKsWyQKI?z$YxA}QuZX;1IE3TgTt9d&0sZc*_< zFFQ`c8AL0~09t0}J;b;mbx-BS>z#&onb2WwKNM*XO_cP_e)B*NTOrn{BC zF3>2qve&;{wrFvWv7~*7YrOOn!pzDFm)4nx$|8mdW}nopZ|HQBjQiSur;ur4PJmrA z7C_ak^=|nf#(Sy0>iDQ>M=`UU3I@<4;XovTci1>06ZNw?+OUrqn9@LV62d!p#yjYG zKDBms4O*3G5UwZP+_-W2aeRD~HdHdIx7D$Ju?Qv>O2<^6j-6ATE+m9@1|O;#`bv>` z71YHaI%cJ$g#wj<0zcg;h~NeN8ZQkF?PjP)a zW9$}lzK-IUj1TyJ5_-(4+0Q?X8t`(HO6-=0!mPD4ZOZS*r9f%PJm^t^H>?APi&{@i z`!Z;n)tyM6@&T63QO467Kyrv=bTagL!*-s2lYJZ(gL)@}Nx^t&yy6aGwLsYKOguQ$ zx6ph|b6_RC_?2r-H`^DMg_GT=#DBC6&`*HHB$=UQb+gwa$9k*OXj#C= z!*lES?+kLe5i)$-_MWH?|?Z%scvYm-e=8aSm2QVWPFmz^t=ayB(pxG5gg%oNeU5iMp0{)tHC+*ndfotwEiY7%)+Yr& zP@iuq<`%uLy?yWHjW}3zU-=n@a-G2@x6!WkCLFT=O?c;-s~+Fbzv*YKuOF~-S)4KG zZt`7qnc!^+bQ&Aco5wGIQaJ)O-D-*MED%h8vsjS}6~2!IKU9D$lkDwu%o+u)k%!im z$h<~OwnzgdMZ42Dxgsb&wY!>!;7;e-#7^&MpSR)pO96Mj$WTg42WDQ&q$h%6X1Wd1 zn_6WI24_3)M1fLuXQ4^sbo=oX$M|Tl6Vs3^VG@g|X?>aY{iambaJH0~4KYEUM~AvK z=)-Cx%hY_&NgE)EkO;stw}Wg?KwQHg@qwEcv@@#qErn=Qx=C~hw&Nx~AF=KJN2+68 zAiM4uak_+UNk!p)Z}I;9c}Xsjl7Bod*BWx}#y5?OHkG z-c-}>O7PWId>|2ACz7myI6<;~8K==?O!Dd*KUc zS8cjFeutWo!Y)Vxf)KCgTFse?+%K&q;)bN9NjoWX7w`bhVZu}k@ubB-gJjVpy>FCr zt~Balqv?=rUl;p&7SEUDxU3=>+f`_gw8A4WPxi&R>94fnGzIjQ^`D+8p$YCXn3e>P zf(e1PFt^#XM?k0b`J{9}vyq!ZxE^l`&(VIO0zm@~E0mu_a}dIn7Kw6@h>Ld;w1CKP zr+*cz3v-Xmj?FS%fd4eK%&x0ugy-rx~iSi7#9u(zq z!jIu<9r78yussJIAreYFxy8P!Z4@wz~64J@%=h2Bnhj#9Fp`1x<@5p#v-g@ z&g1!2>qRcJe<#`ulWYA6>(yG zj;z`3ioPtn0Yuk4ZMAnD9L|oKW=&(3E6vnw!prQWG^W%0l4iQ(ucb*}3YKezm((L- z-2;vPd3=C4Xg>8}ml7m=etD0Y>YR@vn*m)pvp|@VHt@dmOj8NBXW{ zXseAvHU34+!kwVca=$(AG!|P8h?PA`IN-YM+cg_^U(02xE!TS4@hVqDV3;>9GO};| z)qDOa&G!b5=6=^jk__L}bP>4s(mpOO2o>fBZYi1_957(CovB1A<1(9CQ`}HI=?-}l z;RYepKVoN!<|3q*;e;f3SL$^8%Mv1QIzSS*^FkuR?-V4nt+>lH~9*}F%x*Ot3No<#k~KNw25Y& zuiN&2HAzi@`{>@!{337`?C-U?YcW*xbom2M2<-c&qc$17Q4|mR85O#?1z&W?4wBu< zJ{5B?OlL6Lz@{m)n8<}sEANCd`zmRe0i|MS`W${R3^}txSTC;rJO51<$~pkgLyj@k z*ZzA;cJlbS?-=Fn4}F-^v0R2&LcA#=BD5s_rrYFt>AQHV6}s3F0CYj%&;oU-Y~5aO z20+W3N?!F!{C3(Dk?iV`t#}J|3JST-KL5lY5Juz5IC?F|V%G$S^)o*{**1jnNg=Iqzobm1h%u5|??ZJY z%j01i3_Cln!n|FvHs||6+jqGQmp1espRwV^99HwLHd4fQ!1gh zt4|6{mtXEM^UGxp!Mnvp{ctf{XqT9?2X58KLoJfMzFpMFFY2-#D}EUs_DLjSN2%hL ztJeH@a72;g1QQ&Ut?1shMFE%O!>1c%2X==>@rKYIU#%dkB9P1YTmmHpefBE8Ilmhs zJb|v{>gN~b(q}P#Fy{JQ5?v&u7gvwn6X4K#N@Nu)^u6y7EKRouY%Te$>~)9LH~C)8 zSAxcN&8cgp+zuHVpgmH95WaQ1f@JyXSac4^mv>aL^Acn9i}5ZVNBxEs8NijVZIA}z zxzwsqk5E%aytSdzgl~Fv%{LL@sdEPFmSo5|^|F2(#Z8@ zzuS*b|6;EZ(W)WrXST*W1TCTkGfIK97A-bs7oQ4VPLZIi339B@%yk-x7b4_L5wL}sq);I5>svI6r)BVn`d{hQt(j^ zO-}_N>WDzH`e+zf~JpK)Gg= zUSt-@gaW5zusQN!9!9F#4=3u4dh1~^`*ORXIKZlUj2le6&QEP5C?OeJ zjfE;QN$-Y>qV3$cQa0gZ-sl4jc*m=|?HM!eu}P5?oaa@t4885dJnwRf-n=a%CJe>G z!;4(wB*4|P36W8qGYu8NS9c81OoNl~%8^L`nkz-U4t4@9wyLrQyAkap(J~hFxo;`B znT_}^25P-1Auy_WuXAl_l~ySJc)1SQ2D1Fi{PXHpABX1eQL+RKFAXqqRV1c9sr#zD zer5A0SePs_d34^~-mV+H0FHf!=xVoqx?1fr*v~s;Ul}};4&I5PKu|bfACx#~eNYol zpMHc1KI%Pn#2hA8B-=G-!YmJW?JbWZ)UyS&Ck0&-@lDc-4QS=8hsllH#o0*L2R%-U z6&tcu`XuDk0}5|4T@k#M)E%t^lL!hphrR^VwML)IEFxos7sFyKsZr?Bl znfbNwSXV->rr z=u;o#gM5<$K}oGI?HWQA7H=o36Hmy2-DhP=khJwa1EpB+I*Y2coQM21@#j zK2s&0h>}>^PBngX?I0{Pbf?!R=urk9AukgTX~gXa=11a?z~5LQ4WZLTcp_r^LArzc zpHeH_UYe5(4lte7NAqLIHN@CoZoL7oA%;}r)!Q6pg z8%L)zbOxC^WLu5mPzmo9T>{Hvap(wf=}3nQBWclhW7y7j+Bu+RA@Pjb0gQ_UZeorM z$ev~oDQZRO1~)6ofR(Zm)nuDJvWue_1AJPeAR)R5Tf(1wJ7WTS5$^^wr>1M#xa&WL z1hn+a%Q!2Evyj=1)%VHuPP);Z^UgN>pbYBm@0W!uLkb7#w96Zph0kU7$-fwJ7#-{) zgky@Ap`Zl;k>++E>y4GQTU zBEPbtLPBn-^+Nu*3!x>>7Emr2(A1I#+=t3Drk>TMPrabZ*Oh*?U30)^PzI4g()VjwUU{EYw&1pSn^rCqBy;m*9bmB zWJv8p=y|GRjD%xVT$I;v!W)JP(?Q<)Afe?zxlKO}2gw#TOlzsgQ#M-YF&g zri#7Lf5e6+hd`6Ywk}nh#eVhCR3?g<@rE7!o!uxhQY#C+%85Wl)MujfaLMEKl-G8_ zov9&ZYC}t1Jw-PsM!gJ$@4O2b%$iJapT{w(X?p-C2$C;fjH3ib`EBVTufo+if1}5! zEBjJ#=fP)c|7VsIF&Xj>vSzFy&tB9kT`{FG{*32-jpttT2AiJCXC6+%%{&~BlK~Vl zH}ei=x!K$q!CVr^EpK<|GLJ(lJ=uqE*zQb-2Y0u1pKX%QF^7VB@5y5sZ#_x9I$ zMBkfFPtI;-JbMx={4m&j3fcbE4X6gG)~!jXQAxEh-8pJoZ!As8rVWTE(l%75?3`sM zy_zYtEqmb}%thsN!-gc4OBLVCo26Vlq$7!K%@#QxbVgpna#d7~uEK1igIkG^s3_)O1p_ir&lU9Q0_rC?gYGx7Ubi(aBL2Hl%-) ztVcvOV14(;p_RuKgL0l>+!`8w`YsmKP|ecjc=UsXLhjw2$~Ep#W14r(<@sW>)_grZ zHLwfwqJ6~l^bx>PZwp<0pVG#VH?CpaZpAsze`5|;=;yk4`?fVOc46T60zK&o(<9CSW^(f=kaOHh@i7P!&O6;2n&kY4S^;cpHvmDVw;aw&HbO;| zQqsF2Jj>{z0x6xV>qn4J?suHNS{`VF{yA$qS;7nwJu8j-5)k|CvxJ;0W99`O;Zz=! zfHxZa)WiCk7Hte#f0P)8Fy^&T4a5u57ZqkYO-+&w1Cj+2MW;=>dI}rZp;sp#SU{*n zQ7k7H{^*}+Ff$N+1U&viM)>8B5~OD8IyPz`Fc<7R)!*A#>YqFUSueCQEjEIITheow zjZ9l0(a1~?Qs!sdw9DR@$$OLxF(GqG-J09sL0{yh37y_RvRli|xLkQuY*7Oi*;)?e zb-X_!dm>T7)^7-<G)9>%eDCDzWlkb^Ve6h=>CX z{Ea@QpZ_qV_|bSaky*99&o(^1b^M3og_Y_f=883zh6}t(rP(&s&Mmj`^{4o;JLqln z%J$H67lX=tznIUb2fXOMaH^9Z)^Y6on7ym5f?($>vFe<9QCyC?T=vtK=f+ekPl%jUm)>^8BK9?y`Ay&|v34Njc$_@S zv&F?be9gC!-~nApKv^cMoW2tZZ#osd`nK$gaMrt30XVL+9HYI{jnex5dqKo~qPAT` z*G8@icKJ1s!(Yy#z{-}|-@A^uE=M9ac)yI1t^vOnz~xtcI%3*s>PozqmUQnV7S$e% z3!Qb1tbJc3xjlqier>kqSlJ`DHBE z+jTN;%`?kh_|sqKiiRbZ&GwDY3^N0bU~?xHlv2Vxk>T)PI>i8U+U`~C1Te`nlr-RV z6}DiZI&;CoFyGY?lB&1{RMwbX?6<)l-g>Lz??W{Reg5-sf4m-vKQkM8^G|(m4Ua0s zOybhJl2Fq303>^oS-!2H9`~-o(W`Jw69M z;(FFkMLj=2Ax#kbL=v@U=D=AC%10gjv_w=9a(E!YbHUQl?b&1VrCZ0t3Bb*Tg+!O$ zmy{bq^~U-|{&6j)mqFcV-_Xlto_f}e@H2nzKC^yufB!E2?=Fu|T-*KE?|&Wu=AQWJ z=*ebdz!Q$ai~g7=9?T2AX{Y5Z^+(xN(WfdB@^U^Uzg*x%qLQPm(%)JY@e3L5Bv+tIM zl#lI=SXTMg7YRM-J=3jvEQWT;U~9TQZ^wAwanMYMoH}Z#OAA(~MSs5hF69%atv;&8 zD8$SN6=H`q3UbM_e{Bw(xw7c$FA3!=o5$b2n%%7R>78dA{fz?eb4OpG#y03}oPsAj z*5k$bl#&bQ4105UMJiZc$ArwrIHtR;EUpCp>o+yxVx~pB?o4@)Y+)J&xggbyy-NDV zzUghl_i;A=X1Vq}q5Gy5m5fZLs74oZ^J{vK)wwhqKCf0>uIL!u^w);W$c{J+zhA01 zSYRB79X#hfpCuJGj#ZBz+1O&Lz+zW=E;TY}S|`vcIwXW}n>jX*LxGov%7rabYF`lAJ>aUlH zw{tx=auYOr(6J1D%asTTl1$qIMb-E-zOn<&Xq5>qL2oZZBf}09s1@|pC@wb&*uZi# z2RzOZOi*OKD;!>cf`N^K7}9()$O;2s#KV8xy?OpZ=;|I1ZpoDbQ5{ zT`Cg@CWXeey;?ZKml&BcmPJZ;l7D~$DTQ?t_u8h-f$xVo)cZND-NhrV% zH@;l#7Z=knMl53dLra%s!dVi>ZQW3YA=*y!=YfO#)=C!kar6prc|uq##|oV7!{&tb zxUU3t(U#gW=STKzC!KY5Y?XvvR6}J*-I`k5)+$Xv2{nTz4@uPSshu4t2XX53hx@HA zuCnG&Shm+i;Je*ch1__^c)dlk`U3D7lh-<^*Q@*?PYuR1D8?YpjT`h7f>Cd+9F?}2 zYj#;Rh0XLi%#02zWGh%o!99y|z&J^n^y6g>MOy!7`cZ}J@U~i@EH!;;F1cA1w`Plj zr?{7!(qC*!Zn@~7F5H)l_^#|akGJ{d6lGsH|G;8AE}c)i=*|7GHPs3*;1ojVmzYC> z_V+u!aSU34W@y1g_0pmab*rh4*cdXFl!%uNr~!{#oT}@zXxL1qIH=W^Ln7jF#vydJ z7SdiAR)%%sy%@^glrUjg-cZGs=|&V9i2n{&4*hO_gQ#ArwjrYFF6M!k#rQ9!@&M#W z!bH7P65$eir9J(+d&QkwN!XiSP_1)S@1x2@a#xLer}}KcIZV#D-mAmgKY+B>oB&wJ1V?>|A8<`!@1 z3lXS=KXI}-B&k70d#UDT2&~NdB>s~b^NIEFK%F9~o4JeMc3avp-1A*}{@S;bI0)QX z#c^&=bi|qW&4y4klPy5HkWb~wb9$5qRDUL@Ghg_2gkzm>?>cYQvvi10FtG#+XTycf z{7qbJlP~pCbxCt_5=a{hUEN%Bc4d7+=_papPtXb*qvys8Y*)PMkV_#uR*o^GJT+=~ z#Ddj<7v~SW_!6f)$u#cSzI@{qKU)TsvUL?paZ+ZV_5NeAJikUM)iT!KcH;Blh0wprn&eR+DWa})MpsumT#!@pCUzg=0gf|nS_ z<_tLhm6;p$?#J!y?5yo%Owfho9j+4d^j@d~(vtc6Vn+sm^mxIbS(aCCe?w!> z4ybEoxaw^9PI^8-CFjwV>$jrt>hn`ij6=We1_FZmC!|gLOD}(iBtEKW6i*Lx+<#H6 zre!@%^@JMxxQ@P+RA5>n^7H3jobAmJ8$GG2bi0CIDf_O`>6`HNe?zbJb96 z{#E-^W5Z3*aV{K$W|p2+W)pSvw=xIKdJ<>KZsrE^55+?Vv)!xyW}_z z^S@VwXi@y<`7(3r+4jvnGSba zv6_z)#aYi7V%mipOU^1drHekBE8|mpNLi4|5r?RaMW7vXs#K5qpSxNq6Ed+q2T+kOH002ey1e%EQa&)d2^HNmA<54dWX2bsxtLqOZMyrHUm&T6vobGcfyu?H0HhNlo+=w3O8B97|33R%HY!m(((Ctdu+v&-1ph5pJ)i>g|KK( z=*EC;a2QpVaol0sb7O2#YvO5LSc4yGrOU+>Hp$YcsCu1io&8Q_D<5Pu`N)b@GS`VN z?kGP5JB_9q_7vtIS)*qfp^g0W7pPgJQEE@f-)r>JZov4i;VwE%GT{7jGP%p*>e$Hm zU5MAEwR2Sln)@~Wbcx%3bY32!+4)0aEAg`nUgMO;>;5x8M)JVnHFUorTF-F>Kclk9 zp*A6F1bdSbyC@XE5-VqQNWbAKI}QBZYbk2R&wVi|{bz1A4qFu5{-kl4`iMCUjF=C* zQ#%;@Z8lb6CARDAwYpifMv>4WGOqUn%&xATIw|Ti)+NmY~sKA)Idhl1O@OMJO?jRTWYaTEC ziGRc1zmcz0+ll+{2h9%*9vVLJ7Z(2eQB=Cmj;TZDV(Ys$g=B*fCjo80XL1eL`J6Z# zg#lL9hI;6O8xTfyFFQj>Ut;7#F{j@F$5zi%jr! z*nyR+ZKf}BVl_+2gGk&>3_%YJI#lkpB~UMdoXAe{zR4`Oqy|;{hkB%4G zI`T#53qzhigG6RW4Q46NIU+F^3f*+3yX?j;jmD4~pV{D}v&o ztRk%K_jtEOCtEH4AZXB3VG)OzV>zRLN~=xs`_!oxzU344kqR}^zha+LHAfY0)jDha zvjw=?dq#IcAyv}0QCStgd;VX$%5*m|E|G|v7oU$VVXl8FzSyX?ds!!s?bwr*Yqgy# z8(#8nsqvo|OxzcKj#mY3QxUYfL1g|qajXx5dcQkbc!0xy-_yD|slSu4z|-rc9X6po zXLQAj>6#3ty?!}#mUyx`&Q^Ih9 z{*}-%IbY%;@5Qd%^V^9(Gr2GDn#w1ijR4L8N5i`vyUDxh#PyB2jv;t<(j8^@)YHAk z8uq-*gBr;hEe)1J-NHYGkm`XK8ig4}NS0dQkqg)t*%7FUM8A_N&wE~hp8x2;qc)jg zr!N7Ihg;?W3oF_D50tmou`d&CP^YjwpAl?Vx}{EmPp2l(@wEkocsaeC8uf?g`;}qz znrA19xA0o00Mch+GlJOePqhm?*s~Q}p|++F@d2yaE9cdlqmCD z3)G_0H8$z+XN$n=?4Bb=;hT?Wg;16i$TCalCj_JX)&GrB(4J9z`950Yy&nyNW>;*A z%YPkiYgbNAu*WDy=Ov;qZIslGH0~LHbbc^By5s`3wk5J>jQHPTBsxfswr!s9A@8e0wTvyUj8Igv2xmll%1+f#+ZA9zMut2-Nlb_S>%@|woJ)as! zWan40?a|L6ah+Wn2CbNA;aW_9&3@^!QU^P>v}}N_Q-q;YWi&nrJl)&)G~S@Mxv z?{LJ23s*A&K(%a)^-_6M=kDu}wfK62cVTq1G~UIX*l%Ya!dKd260?Jo(|BdjAzAus zfW=7CnKN}9J5q`Zyk855vTNhAPUqW_U=rKBsy`$l*R)@q56Hn8OZ>S3Pf#qp4Hs2* z*Ki_5(+QiQI=8%DZma9yW;1H=Ty>z5BM8PJb|SX8ZX^?9gJ#fd25%j6}%)e0!6xoCZPf+$oQ-BYV zfw)J+7hl9rJ=>h;U$x4q@E!&~^HHe$C;9%9L50e@mp3z!fPycPS?n!qBJ)|Q%qb-W zA1mm&A>6#hWJbewYzT+mx~Xu>8HP8e$XpPY|L84)PB2ABIoGi|kSH}580n2)PB{`D z-Df!a77ZD&A44f~?hq{}`q#iY|5=yh^OIjq&WC>7N^h>UY()1(k7P}fJLg^JNng)N zJRRvRu*G#>Op!xN8%V?Cy(=0Px3L$UvmG>t7uqX2cT;G??^tP7T<(v$H7{4z-3||J ziSuizG#R;}J4uG!_snPo;jA^G@LpKWH%GY~OkrB6#Fi}a(++H4=G zv%dKHWv@if-2Sv92&?=0xo#su@Y)o zcBA_AujN=xuGi>iZ{b<1Q2*Jk1Z()qpIPxcpJahPiNpnM%+?>3{u5=cXbOT5GR| zq#*)T=`|x{-TChK|8JZpXH+NatU1kTB|5j}O)&F6e5h){FJG#uY#cv1b6l9oAAk45 z{9$LS@T*Ao8?voaR`BH#^99k`0cXD;0}f(#|;Huic7Pg-dB6WNFdG$ z!@Yg#rIr(I9~0|q>$quk>Yq5Npi3(SCY!70rtxj`i-G@ zw7iKERQ~K*Uti_FcoATGa{2Km6^9qKfIwHxe`CizvnK?&Ip)&IOoqNKLS31po_@AD z>u=JSFZ9#a^uP81BRu=qygD(!7q2F6M=Mmb@r^Bnnzx{ zbN1b;{iTPeIy3fWL_`;`Rh5hqk2W3*Jx553c@J-+&1N4I6hO9pHvcLlGWRmuzAOQVGcv z<-y&_Nv}WUnk_Lvs)`QkX>Z~JVCr(vwkCZxyjKPo%}mZ=6-MSP*yS((#YB`(>mubR zO3o0hUr@NiOmL7{+ftDh=UwL|>M7J>E zl&M&-{<8s9TeqO6m41&jRatUT88+r6B94oPyq^B4F z5A9k=?M+KJ^0QMb9g$rjX~0t7NQp&9JWr*n9o!JUuKQ0;G2~`cJL%;tNdq_L}L| z8gZFsziAeae{2>S^Mi;h>WEY0*qt5kD0#+RNIIipu5C(9DM+N0SJ?W7)mv+lm)jV8w?~O@fVcW+%wN$O`mu$UT z*AZwo1k1hi;TP`=YBw=-p?SvM+Hwy?b zY}g^65j^Iqbf5z{0y#TDA{y@TE(uPtMjJ0!=?1`i@^K-=(^0lT2c>DRqObG?>bo_* z3wRl7wm|sa9izHh``&ir+sex_2-K#x`;sx}9N^AcqT$Z-I`wA;mFFP}q{CfCGrrDq zZ3Wo^Csm;8X&nDWU#_n4yY>my7-!e8Pm8}*ExFwJ|C0Q_N#TEg!Q4O3XQ|*NOY4V;$~Hmp|{XJ}^X41HPNcR11a1uv*a%ko0Wg zB1F6<_8K`tD0g6)yYymlTXVPbBQAP<*O8&>K(r@XqR#lzU-1wvqwsseKW9yT;BCGn z$3RNDGxzle9C^0)>7%rZPs&7vX?OGQpeMc}u>Je4)`Xm+pOQeO7q<37{BDGgPmWIxlbJ(X4#5$fRol-Q>G zFWUOwBlB;fCttZerbfv%nb;LgRAyLDil6ktnZ@qkV&+p6V|pvhV0QrHvB;%UGTV!d z`Kgv4laXQH)$>zaHhRh@0%9NVK7l1S9>gBls_dz#RBOy{w;;!!$k}2CI;X@UXe*fv zzo{){CA3V4=XiL1RYg(AUvO{z%>mIE#~gY;WyfaEXmw~>!LJ64ciGN!?VbeHz~5Dz z_Bedl-&29dB-x?t<8Px_wiAVuP8Ral2U>rBrBc4PZ5XIuf|?shyF>mfJ!iqPgd3K9 zSR~6w>QU#JZR(5q=vFQLr*!qpI^O&?wHDHgwJWeRPErohQDh>K>)ETe(JN{zY1w?+ zVBHztptJK2$FB`crRO0^44fCvNt!gj3h2S^>ZSyz%&(UO!tH_I(`w%>^}gcJaM1+d z+DKdc{j%j_0V_R}#ctm7x2U;Kc+fel&lfXbDz?|Wipcu8x2=Wvp(Fdn+>n~JnHfJ{ z1J`zmy`{XJ_S{OTu=JHmfg9Mr$YnUh+CJz1Y99RCMfhJ|CJ9n)vC*8C)l@R>ysJQh z`}BhvMM+uwT`DF;FPXS*nZ;k}>ySvbZZO^uh$j_+BQCy5`XYV5UO#w11r0TcR)$@c zO0I#7f9#+Mw69m?w`Vn@?vJgVIA_6mntp~9d3xq9*7oW|WW}59zxouDZ;pHrW0}{T zs+i9?@JZsA#B&BQ5=Rn`6&gnype3G-vIY_!?7dfiV<%hGXN>(TCEMVKA0?et8XGno zT!OiD7cOzO7P9!C36|SfXl!&I#X~1`jDT?w5lAqSYUPy(Wa0fpI&BtZ<(>WswfJ575@~=OlOl<#x7|y9nHRD0 zLTxMmd=gg^obU)*!{%$$AB{+&7JTPuIOdDpvE-aO?l*L~gB!$gjR zrtrf5*ggOAMPQ5Mr$qNWSj_=m(^GcxWpi05OyXeeizhcNCOWY#Q-GcLPGL~c_0l=g zOSM<8WM20XpczA<>*$#RY!yGF#nz9Nt(c;bpd;Gdv~|%1Dw1~|G3#024Gd@IVCtKD zJ3ZBiPlN@X;2G0@%ops*3wHa5OnZQ{7`Q|1U}UFds*{@JvJFdB}-k@ zwoQ*<_p_Yp4rPGJ-z6g>AikNZ=qMsM;+AxlyanNAM8R(LOmFew??@}x4Dv}=#jl#lQhUy~4*s(}f57pdR>TJ0j5-4PK=v(NbvPf-l5dM|{}2wp6*WP?wQ zCgluS3XF~Ehiv5AcO?iKjKL{3>o;Lq`6ey6d!*1yvXw27didu8fy}Wf4lr&6gr)Qz z+VkbWB=?$!bW?wZb7anG&XwTn6>*8LOby)5^>;OI>o5T;JSl2DhxoTU>z^s*pAU@2 z%H#vw5hK9z>IFXon-m?`rpCF|4M{a6KaB6okSPtLkd2){e#5ui6$z&Ct;(JHS;`>1 z2bI!u;1Q)Iu7>&CZ55ftP%h|JF>@4LSa)L$Gz@lw{j#Hd7pTv6SY}i$QkQMWtt-Dz zUE1zIAxm`iWRA_@dB9Fj9|TQ&RBs?{gWE=ud|x!;sz`iTjN|aR&!z_3h((SaZ_VJX zhg}Yw@BVVOA&F&dt1Hz3i4tfgg*M%Oa!3=tSE=K|viK;zV5Eib10res66ikPZv~U41BXI=It9B-TYs*}gb;#b7WBd?X*N z=EnVWxWwodIw?cd+4oSZT!)GKN96#kXH};w8c=gXT?{S#e@!#~pH7Z^=Cf^?{vw+- zHy7==Zo7KS5IzuUxjaO}?v!^s$D3H5Mm8TKgX>bO3qA$p;ZH6oKZ8$3nK&pJi%R@! zq^Hus!tXPySvkB1j$q8oC=B9F%_<8vC**0rrW$aX_3qVrmzl_X(V5Krhhr=FVJ*r2 z7jy|GpLbZde7Sg7<*Ib1yXbMsdaZDvw)N@D6az+w-?g~SuLQV<3TUqo{ELJ{zen~V zD)ajy3P1d6Uw8J_ewB>85cc|y!c9NbtVvqE;2Nyt0$gdJRr{KiAkJ+4`{k}!ZDZ+@ zf(ydRC&d`w&cuZ%=McBpA+cd-EKhx0W8d=u)-vg_4fl|ARu@%at#NIO0&Q!7NpcjA zIl6`YhE~7zO-pDkm+0b_-n`TatUU4A$FyN~`94_X{((7)NIjg^QbE68Az59y~sT?MU=}T`WuR?vKk% z%?tBVPlYXv?5FLlU|xgQGGm8(;H77XI}Lsg8c$SH;MuBEY^2-2Hs-IEZmCz7a=yp5 zfNzP6{|DgvnS5!ql+UeBv<*F6g!#gn22Az|@74)X_U>3 z?naSsjj=_Z>|ucKi@B~7+nzye9AfWveA#&OCF4pHiz?3YE<6v~wn4hyOY1Pi-<=s=t zDrVZ{{~PzZBDZC*SjyeQ=GojsG}>zikNT9&XpS=@Ft1{)@})q8hXegx3&9ungMY67 zMLj_%iZ>?@Ps}~QnmwwS){ECj2>J3LtfDuTH=?tnb|4pEwPJASyw+r8F1r8s<$^pi zPu1;~N^Z1~{tWt>6rs(mD@$Adx^*8o24w!b4NY}D_uaPGpCM2%faBz~X@{ewXILp} z(RuhdXZp(mX8naInmf*5i5R)#I;Hk{Ns=LC%B3dR!u8e9KUgW-f_IB+iY1l}ziFuA zAD@n?j>QhQ;G=X72;RHk)xO8J>h;y=j6SF|waBd&6}*m#I$&yV$Zi=&{3cDRGH4k4 zV5?N!FN3U%r$XhcsH&|i4B0$avQ>@xq30wn0VPrY4jLI!gtJH=l0o_rQH8&oWzswf(>GZeo0$FXNi>5Jh>y?h^Wc zDs%l;@A_}jfolrSC{;j%-oF!6n@^7F+ksGo0^!NsBC?_EwQ zF&&XDE}LtctrhpuTI8hQF_m8PR|ckh<;mA6DP9jJA&p0G{xa?)&uA|??sKpUsB#kp z&n{5WNjF6Bzd|sXw#Po{*18Xr>Y_8aUyV?H^zlR&0o3aap1pH(NvB&B4*n7Qp?0S@ z9eo6J^LnGXmtl$A(qwO*Aj`V4`sP)$C6{_3b*NrU%vlwmD`$q!qN)gcFB(BbW8GS6YHDRNknO(KFZj8;PjHnm`5S?#51HYLv@pkW(a1&@lPL z@&2dSX3OjTN#^~`NL4p^ZDgmJ?d?i+qcJfOvOr=WPI$2`$2oz(ITcLwZ(YkYnFZ0OPBwrhy1r8Y+#ZktV-gvF(Z3y zv@#PA*X3cqN9z016NVKIM@v-sHX8sO|Bw`Kt}JD8K>C%}&#!agvA7e^i{7KZK+opF z6DMe=_~ODbgMf|!{M<&;u#;&o-TRBTVq5;RJQ5uQ+uTq6J?52&Qni5to zl@LAhSW=b9?!X>oKs_;XQ0LZEL%t1&*P)b9AE^OB`LwPzFjIouyguIq=NuKXUwi+o zrGk!5p8gC|Z%UTcpLll}v-X;`vj>%h@veYgAc6<1!EV0ybNgFk^U$66x{st*?DV*T~tdfJV+9~6lv=h+l2`I7^kA3bbU_V+xKt-5gdFlPn8odYa^la z{@ytOaj@t=!`c64<^LIY{{FzI-L92U>2?b!3uS<|f~SCo1}+)smA3>Jx8O1jS6=1L z7&NZeD7~d!X|z*|iB|;Dp2-^00^-aesSr-jdY}DUDpR?bZDWSY4HakxhH;QRlwv${Nq@qdV zZ;Vq4j-&Y<1Y4~q&ntR&K_~NSMR%w>EKs~dp-WvB)Pf#8XkjP$CrZs&IgeYMtV(EKXDyZld%;yF|O~V z6x{4tJ3S+jMQX2ljBa84T_S~oCYLr#cDwdqbgUQmFwrd6Oz;gBGNF+Rt2aR`Zc1jp z*kS+V)aB6og(G{zO_rXga(f)A8k`U_b`j9dY9pb-zmDqP8+@SFBf#ti{e`bvAuN&u zPxNtHgpe!5u6-~b9c+k=B_S2VCTV4j zdWFFBQetW?_xh($icBC^_S@Y{_?}} zS3~7RxF$Lzz#LO-QR5sqkt{@gWAPpC1T2*Aa&p-DEbOqHS3woGeopt#E?rYSZ6ed+$ zNE`i_gGsX6!$4N-ZaDOtGTA?Cr7z8$`xQ{}{$i)aDufo-{iT|MxczC6mOEpV#g(}j$bsCers zj>INjhq%lva%~7vS1BQDRYWDaq^APaQ0j}UIIq@gsiw}@E4>eh$3Hc3pLZ1Y$B7C_ z#iEHn84Z6k;QswFy%U=NpEnA$_6Jia;x6pqrNZM3<0X)xPNrS1fzRVqnW5l5oYwL& z%L}d=J&XEi?jhoS<3%ah#HtkPGF zh~6>f^SEfi2i=fStJb?R(HM7|47)Ezh%UDDPRrS|{M;anPEu$LS+Uzd$fX{I=LM+= zUOAk2JQ1b5r+5ELQ_GpFp!(IBiE;a!=v-!3CO9QMOlg&tWL$swk}PzgtIzWx43-?^ zE;pw|4w~E86St#4IYixYGD;rb0oKgqoAgm^5A-0Fjm0F9kP_tXJjf)?z; zv&JFIFC@mhJVRk}($4^=^r1@6^5kHOM?6g0D7dRleI7n58nx#oRaHylg0L|qf^0Qo zIEKL>iM@|-!q;c?@M`dOj=si`8g(nEr<08Y6iygN+xaC_nNe17fjys{Z;XCF`m=n% z-ulb9d&@JIb*taWc#r%7$@{ru4{)*M@w1)zKB+vemb0l?cIGDzLUTB`pN6g9roh~ zFvR>?vy_*-kG`wN(W`6A zp1L-EWtXHQ%BTw!&@&)K#T|}c(^*k+D#dYet$keWQ%kZt7UKBTPs6>8re1n)IyM$- z8xwao!iU?nBW327{`B+%{97s)YQMeR^Izz8|2DMx?*cO8bE9FpXArItU*OhW59sqP z{NzGToC-~HaBMBx&F3LJRM&Zl%bhrzZfllX-Fj6eo_^k((wUgZ;P_g_v|9;19|EHw zy1GxhHx@=jz%~7k&CI{DT^Y)({YUG>KU*dK?h5_m`FXY9!w`!UWsa}sFmxoREMroqol)Py>XuHCt7+%_vAqDJ}1( z$ZPsvJbhDD&NX}Z80dU)YZ1P#_}?UZ|8>|_&^v#`ND)$GYI3q+VO%r-fDN!xa%7T* zSdE3#$Ll)y{R=3F(KZ22OtuD$(r83#w=N<#hHlaZ4~6Mf^(xsaQuqj4JXR3tMd2ik z)OGpqJMF=Y1<8ykL3RW|o{X$q7=fPoKgJRN5q*r(4$Rjny~Se9GL<=Fo=klmojxU{ zR9ARAN&Zb3ID(1lRHIWDP`D61#dMimRs53^-kU=Mv!H{HJsTPHg^@>mpyy*4P!VE4 zi0Y4wHF!fj+a~iaBJMPinVsD{Cgqk(vJ095_5J@GO{IT~rm>1yICT!P1d(p1Zha$j zip)$O`UWLCNVh450vIL@R-u(T5h^MvNNycODLITQaXF%LG2f+kc7kqo-F=v@A?-J; z6wL<$t=ax$)#ju&W-x3KUJlb;^$LLE2w)>l*PbIJ=l-ld<(@y5+5hRHR(2C;aHAj) zvf@2~CmQ&K0#$$@kd5vI5KdZ(nMk{%=nAhTEi6As4N)XAhh}{tR}CgS{r$CCD*Z!i z4lB90P(!w78ft)M!|EnH19h;To=&+Wr68Or#J|L=Y+_m;m)1y7M9*J_%uN5zp8wlm z*1x#mwY`!t(EgebzV|XhG=uQ}!RDTw;ND$cBr~*;2515I2qw7RCEU9uQ=&IK|l`*MZD#p!ELfNH4NIikIuJiNn?xsrb#~YeqDavl-iYz z5&AwDhpgL_yR#{I9KUY~I9y0cuzE<9nb~@NFpqt2d8#XWNDM1Olo?a9#v^8odD0O5 zRCJ$jhW|Ks3z?Lx)8i1JshCZa;FoE^#cF^+$miCknm-80@t=1*iY!PCN%TA&da?U& zPTKtR&ayIpL&5w07A5e{s(z z^vJ;9e5HT$7)a(34btOXRIO;NdE6&=a&4_qg|K!^x}76A?sXlZ7+?mkXSE%aVp_rV zMM)cKr>(7J5A+=EQDHSl&PY0`Ct4(utUFO>`e( z{jsZSpM3Ux=-il(=4y!CW+B^b_#b%N?3ypE8MNUV@g5I~4 z2e|$Kzi&|O(#ld0Yxz)hQCrMEwE!CJ1~t9#8C!7#=sCjnT$(j=s0&gMT&g=@V)dG|D=VDZelh5n@7q61`GLNYi^_S3R}R$z<`J8)zXh(1*6nIIN~t}K_LTYU z?C*{r`}nioMjd#Y;sfYlD1S0hmw2u=Xz9UnV(r@G4w>?iM^Ai~^n@reS{p{2ne+_R znw4AFA;65Z<{IKU-e=1ctt~9DJY$BVHQpk2T+Q7~=8Q?|D`w#H(Zw`5v@zrvsaL-YS#BDt4bD%@41fKDm1lhAZV<>PXOi9GoDjEI z=-B4}Bg#Bc+qW?&jdp$v^;Sd0I_7YS;Znx|6=o}+e^(pljd#*he2ae&5@;#Kd^+0p z2}gd~$QJyRylNQT#P=t(CgEt|LAd9yOI zzKR(U&Uj!3g#0$lus%iq+?`tIP238u66+}|4ikO@gP z`S4(Z!7wEts^KH6qNjwu6;U<4v9mO$x9Rs^6m!!Run2la3-k@CFhubRZXa649p|b| zc7&J0{ZqBG`*;=13Hecf*z#!T=QMOaXisjJCV%=`&fYJft+na9 zW^Di2za(xOJMd^G?S*FaQcPEjl&TAK8aF^KH`*6N+3JF#;uCrd*yeF1LMipU_bLBE zH~fno`g2r%eKZ1i#7?n^L04*ryQoaH64=FtOWk166_4-N|7kqR4$K=#IZ@h(L}I0w z${Q2+6f;;Y-W6m%RC<4e6p^&xUq*r5S}9accSZY}=_qCv zCRDo}LtXW;vYP(4cIvOTY;^g`Xi0TZWHu)_b}gf=W{$&z>ZQ)kjMV?fzb=dZtS|>u zOopB@5a;L1;vNCkT1aSUjm!`(1|CjpTzg7M09q@#EzydcFsV4J+3nOm6u%gbCwNo> z*FEvnRL0hJ+P<<|irru^flZ0fZvQrE6B)@;;{vc<(tjop^Hw{{+Ms?tbI!=QmP0%G(#My zi=jPiovw8-K)*GHc^mf(1cQ_-DOtbUXW_2Ebcv!gXctVp$5J77INyvUjgBbKs5Da<`(_MSJpuD&=;!WAR_(OC0`i~n~Q^TGS? z)}9D<&{!f*llS5{&)qKvkVyQis}Gf{M;WI@ozr@4%*Beau$a?u^oLH9#B(Ng;SBv>-IES2vdwHgJV*OyUaF9w|ND@D|oJ=#NGMNM(1h!N$E7w zSrp_9!FrZryQ2q)*)7`Qk^GmWAW%{ARs?O}#IWMq(vg=Q`~~xTzVBCM85d<2!bf2V zx5+#)_)E|x?t|txwZ!0*zqcUM5AS3!GL8hPhcwL&;}vxMX&Vko!=Xkii!J zN(<1*TzJm!bEdyrJZId#zP`0@(nN+h$0539lGG89V4)LJUrZC>S#< z`$uRw1_!&OD$^HIKFpk-ZCw~l4kw4LFO(hen$42o8v8ctzW!sgvnE1HCAf4hZmF$} z+T)TzNVf)k&-u8#bbIn|vKFz?53AKzom?!JyJF1D-1Yf=@_qRs!>T9g5JN zcRMvQvU!XfQVc!I5V%IhK$6$rDBrU9(;$afZW?fIbItE=WVKnLd~VdtEl(N_hs94z zon8gFj5DiBsDuA*iT%s{{9O&UZ(fN#wNTY*E%^y)>>?V4g5pvEdDIzCy9-#K#t8Ff>>ah!y(B8-YU`o82B6xO@_v2PB5StLtX7VtLNnHp zs$_t3{UcP&A`&2J+tE^9&xRHK5jG>E_g2P+g|21hZAY>eb`R~HL_`;~ntkx z#>nn3&VYs;wI3s?1OS=vc;4k#qF-&0pVm^UqCuaKgB9TSnJ47(P~X(dH0jF?ixDFA9*nC?&Cg(a`W7@gj>1Rg2d zL@WBBqnH^1-+Re}eddH_5qfGk&ur6$v*CHJ=vm+XvPl`;@-xj>p*jPooq8lA~ z!`9YabV(}0(Eo!DXe8YIUb@{LS9(!KCsZ$8@G=i zH+JTvzT9dMoi`2Qh#8DqqP0=*=*Z3K-9w7(ooN}{=krz^q)+Y zJC>yOGDhOU;)XgF%I+hgQdnizDkn{bcCP2GFXoXRITS_9yaH1qeCj4WjpVXE2|$Qy zxd4-Z?uE0c%a_3AeH4?3l*pT;;ry-`?-`$*?)2H!!nQj+#H`lblLlVO!2-mDFq%tp7l0C2Oiumg}nAntS$n~wT`+#SZuU>c*hHlr;WXQKmNXW z>Se*+0f4y3Y7a5AGJ^5$o{ZdOJlOcaT80my*Pqp5d-fywN56}7jmvmK^3pKO}c(-GaSaT z(+&0W9?d9Rhy+P%roZ~FS)+DC--O3yY{abBv{FE8>ovPUce1{(oS*RW2e84a@05W7 zM$?yyDbv;E9Y3V)U=8t?Td!D`;|Ah(26~TY27Fo_Th*WjuI{v@dtPqv^KAaJP3qT2 z%V$SbRfg9N1Eg!eh#nj|P9i{b0OfAC$p?IouPg>t7iG{L@bXXddUOlP?sZHSg(Z6&DByFawN9-%OX!2iMl>i%6T)Q zK(*&AFe&IH{uIb)d7tpJ0_SRzo`%KI?spMDuTQNKTiBd-F-1k?X_%nw5i`DsYb3Sm3JqE0+*4Ng&9k+(Ni+Hr&H8@ZX+Zg0})OGco7qeoRThRxQ zkGS@8pLwqtCWJrb0Q!0>T+KC4Nm|MU-kM&ds~GG759f{4_1-RYRMVOWPw9b-E|Lq& z+x#KYX*gALAFPLh2k??S&EV>T8j+5pV%SW?eX}b=NImc~Ub{O8#a!oQAEtc& z(p60LxxOS;0a=Eos$EdgH9$3mI~KOYewM0^<3SZ#0AoXaNzqWDj-C3Q8*YQEV>SDo z|7eID-MF(sy{-R35-YI(6ZAY{{Xu|R3g)abr9JhYs~wDe(JrGS@tDg2zvoSYm3yf* z)V)Z4Z2yXfsPP2gMobKOZZJH1(MiGJP_38c5d-V13~)0c3e;c|9ieON8w0AYUR0^6 z*I5{pon077BWfuRwpff@I~BH&Qe_O%%h}4wIP$cxxMZoUxI{Dm(_66)Ov=Q2-ph>*n{nS^kE*wKq<(2^TpH8rk#3iMh_lP!N#};kE?&u7)>piU zx;ug$>^*kdd?_R|(}g2m4)%(2C{zg4T&K&&cQ3ndhqAv)Pq2{%GR|$bAX*qr@^YFO z>-|gv&TMFHR!gXzy0ji4U8au~_%8Q35=>RaJoj3!hxCggE6CPbv!75Ny;kEJgks51 z%JPfl9V2CIm1?j8Z@DNc9d19c@0Qgov-O*~d~u*E?i<(DJwrNWaP^ffrYs7Zbj=6N zQT8=1oB5?`P{UDHWu~>o(>o!i?L;lF@#C~FM4|GU=Wh^sZ5zjFJRx$x#QO(s%$^~s zf`Z62hak^WaDQM)1%FVsTj46~m$<3rR?ml-DLZgGdc~Gjr+LcE%ph62C=rYvwQXIS zoaA3DHGdaS*;+RWQ*d{ygl!EfergTNSL^qvylHm)FX^hq5zhgEyVAW7!0;FA2{*u5 zdWDycuj=Fh%>)uUiSi#nEbt}frw?0BH&Zyl<0kH}qe?7KOQIlHlWJ+6rs zw2e{bZ}rj1)0aMRgWl3620M(Wqtnt)^#cHwD75q3eSTatZdubqZ zY@sG-B&ibm^U+{Srf!&6)eB0Qh_y*>UFIzX->DXTITpA4K}T=%71mPzQ3^$niRk2e zObB%35jTvrkSh2WO>(1)4W8YHJy; z>3sulHL|Ls(z6S&UKL`7_M2dDlH97B6m8;?t}5>=PI6|2k%sP9)7lhZfkbu&Qq$Nf zacgedLh2ROk%XUQgU|9@GMYe!4SMW=h0;P|JepKg-G*`?Tsl^7fmMRWpQf$v<=N-_ zASi#j%mqx{<>{XNq=Zi^Q0%q^^pE;<52oS?6h!+sVbM9x0@{gHYG z1}PvX*!T0=vBb6#DxE8XUU|Ogfh5#QR)_xDw4T8(HRgnMoeW*$KUSmjzcr%@wOW7h zS9^oYbsJv188~|DQRckehiJZ2Kg1b>!K@FDxZQ6iYmgUD2KrAF4A1$ToNRwo> z1o#8NvMG%zxsZp%h1mCH?dd>FcdXES=scX^OzB7^0=IqLHIQTj9(1B36f%P{gl36X04A! zfI=7Fs`y`I-EJBE6uCzCao}f#-O;Gp6!vok5>?EA^t0H;cl4Ts+x!l)uva7MDa0?aK};FjiMg zBC8J12C}y~fbY%L^;yY>-a{(8&weXt-he!QpXo2RTOr&_8UNa+)Z@+SSzFvQSJ1Dk z&?ZP9;M4N%1kl$qgxyu2u?R_)_RHmG%MvQCu_u3Y6cBBOBe%N1{C;#Y zz+ju^*c+4%@gJJ#%*8lYX-_i0*ex$fwci4QV%+b@GH6G%VR~ei*n&M_P!~38VVr$u zoV-wKgIDUMvRW~qBA6#jM;|(@57ke`+}W?iZ*P_In&Os&_0ZlrDV(%2!ahSKh4VDT z_LR1^5{0!=QbB!dYs5*LiD(wxi1!UJpf{A-y6jisxQD?k-R|R_@~M=4t>6!!V0U2f zrcmpXgMOVHU&Z0`?zWDJ1%m?#x;;PB7d@(04o*G#w&Ian+z<_>a9`rQL~nw9a+i>0 zrn7zs6@6?!bof!+n~0k1g6@5J=5=+acutU`kqof$>xEx|E}CvWu1L4qqDtEyRs}06 zt`Ib4BP>Ig8|(wzi>ViM&QY*ri6o2knZO*DDjA`iEZx?kfE+D$PNwS%67?>QdL9Rn zt)^Y=a>*)#Cq0H%$G=6&Pkwy5G`2xFnTVjoz2MA~gZlgVY7s4U!M&@ecY#K>w#Wm# z`J#I@6Px`wLj6U%sRMA}A^xMoQjQ~-{JrxnS(_H8Xm>y2VSd*EBkHOOQE8MVPkk|m zf8D3)8xT#eCEFqB=NhJDA;7+-q+zR=+Wbt=;Qm zxx9}aO5*pbDJa}aM25}XZOCJd^|~bKK2S_I9w_lpvo{h>_DbkY$oTo{k&8UMPQl;S z?9=L1)0qg=zaAW7on2zEsPmxyu0{HsZ&9i)dH~ThNa*pnNuS5*t7b{Kcz#lu$n)|Rt>7v$9lrW~B+@-*3rV$fQ=7J&wj5Um@7Ku-ZU z#MG1;-oYq9yPnTz#135~vloFQDI6jzy+J$ZNcTJciUqfHkO!Ojb#cmRaTz^AKw^QFf|-uOhM%yP+_{0*-?>H6)=AS5I>7os*L%{O%T-xg*F6iKrC9GQhp;Yuat$z7V3Ngg-~99XOSa0iJrA$g`GF zXBh(IXfbn|}HH6@D_CV;9+AkGil`~`Ef~RMRk5;mG#Gfo)6WE zLx$MO8|-!oE$Yu?swq z;HV)6ZGS5n=-t{%(rgTURi!nTvMj#{JEfXAoF_Lhvb#q=M{^zK_S>x3OhlX=#fya? zKIe2ul`l?u9+GeLl`Hr7Ee~&BkAKdYpE|6rBWU-Y;uJcX1+>9X>ISC(^@Kf`rSS;< zMggDL<_^2TIiRAX`YVlFZ9z@&TSGq5jjdU>dHWUhwK%O1)WXP(+mXf$e8k4a}l z#A>2bA@W!nk_7hegnZq&{w|SR*K3NWAj(O$z=a1c0YgCD^r&->LspJ4~=E;5kWtJ_s>>noR- z^Ep=&|8(K8SnsHD3<*D|u=|}M6vbwioqUx}tI6*-W`x?uoxyy0gB1xEs46FxS95hb z{VgiiMPD>sZFCRl&31ZO=nuI(voZPIs{JRFXOd-tL*BUG%HkKaw~VdB`pq#tv6{)@9vd8xQ}wn zXQYnf5xl`HHM;t@UEnrK02mXf#?z>8{OXAGm=9XNiw1^Th#0=Z*2wk!s~S9g&wR#R z#Kj_yi9XSflMj+bWXu|QP{xiVOYp!9QGr{B>GupChA6(Dx!tHh21e)4BKm5td06Yr z40-0zE#32;n@(|w#t3ggZ^S_);N(m{Q(Z-BB3}yOx5zGP%UBZvM&{sVa3XB+aY2h= zU+CR>hln5n>y)E9PqNGI$eyR{2xg+ce}=v~m#DA9-GR+F&paN)I@p%^BP_+neXa?Z zk-|^bEmGgL#ySjE)mO7U2Ni|Ri=?q$Z;1U`kTEJmM>rwjA)H?=J~AG5wLvOft-H(s zJ~7M-^U*nh_wWjoy-&3t9sHa9ivH z8JBCg$42%7%)&WN33uuhk(QMm56YOF&xgHTYf&3CxYAirf^#Y?J$#eYoi?3=%GN4Y zb<=B=)&|+=A<-FcyGGp1o2ZDJNE=*)9Pr>>x}5~$KH$FImHE*p*1!|Y>AIiF8z$+7)&8i7Z20+z&QSBKqib_*mM++_50ose_T$PoNRchhB zZx$@Q$EwD#fv}H@9cPUidc~ToyLH9qX;KMS?)CG`XU@Suop57r#%#?mB;kB!fd#*} zpnK>w;y#jgCo$ATDZJ@m_v6!ZDFcG@0sTDc&Gr70Ze#MD(x(5Y*!&CV^vBov1#yv< zj1<$wQuWs2>q%27PPHxWsf>p4L2aLv!zYwmZAo>5)BTo{$%T&X{<|~Hdgf=w*EO+Q z_bE6gDkeDwX;DIlrJ*`X(i8mAiUpo{iGoTHS6JF_@M2|_k`->tJ=H`4LMa49CqrE;%inu;9K&YN+=Zx zGOmu_&Tx>Lm%FS>L{wO(LpEfW0?q@Z9Nh{u1;{Y11HAm3BZ@^xtQknBFO2|e>J#h9 zf>Pc;=0R)*YN;w}$k=p``xz(B-%5eDJBHS8m!dh7u-5NH?ER%N?`y=6?xKk`%D8Ee=GUG1DmI0D&?g{v6%0Di3(nDoxp8C1*W#o-L(6yEiWR~CXw z5t&paVJB(VQ-1S8tT?zfRBXaAcQwVM)a#c&(}SWJZ7$K@h8@T`wYG^dQYy*ESM|3q zo?x~}yuGH?AN9oE=&thZ+IK3a9W-4Jy~Qq)0Mq+=_E}zKoQ;Us5_-TLJ$oQBVlNck zE3w%RII#t_!A{>4D+TJb)>z~0JolUFjanEk)`I-g%;Qgxywwk83b(Z$L{b`J?+4Uh zB^1MM1573T>AKHg9qFchYn|YV?~%T<10QNXoOESfho=;1?4_LZ?F>+Z?^_-X07#Q&i*`#pM3Oa3M-KHEA?l!l-Et^dF`l?h#JGBj~rkYoxziTx(QIW6|2TzZYzTCi^R z(Z*6j*9?Tbp}66i6^CLHv09kJuN8wY(6Y@!*5{&Pen8Y||Df&*pOZfZ4C*t)Bu;yr zy%sJE8_sCb+Z@y#qtIIxYpU{UA&n7c_VP$=-g08X(3!=wB*0ooAf2RH!AX;cPP*PT zb} AEs=#CTQ~{5UftPYA;JZj;}KG|vcz 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 z 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%0Dt+P+FtDQD9E{*y#F_^Xx$n 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зayE@+LS)l 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

RRQ~B(L|9g0)CNy9<_c?|PwTG65=5mCH$NFu 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�Eg+Df}KhMcDR+JW7;vx+DO`|teu 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

FBsrw0@S(T3gU&Js5YD3cGPVo(WQ-^~tT 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

p4%6PnO4(NgIK^jkBsQ z_)i$=G{FdJ`+_orLF({mkCACMQGV%UZ8=PZNKIjI#8AwO`u6s3%Zp>rAPl?XH zUB0<4NuA&S#EGxoU1c==k@$uAJ3=vQeAm4OAS7^oi}OwCjA3PgKFg_RXi6gXw!r3i z4s~PVUk`A$?{}Um6547w#+90R4>Y4njyFV2h(9l_TSG@}!QZqZxyS3Qhf^4!+td?{ zyF&IH)RQa=H+pcFV45L9ho(aPMrxyn?nl*LM~a_z9ufj$=KVhruUglZfYPgI%lSHw zKc9L7vbT_8rLaRT1xN088;1(%;CWV)fQ}1f)dgLt^R9LwS-w!x80<)yi{l;>s#gnM^=!{NBhHloHEyd?N8CEUf`w zKhRI!-9Gi(IHt?YBYn^Xuuc#n#N5J~E7FvV~rZEN%4=g`24oc!X|N2N8 z#N(62d2#*KKl4O2yj7o{m-okZSu=Md$&Pb$+dM2V@bEIgCxC-JiNBFj6uImfyRg!L z*fjq=HtEv9&pu+^`HlRKJHOe_qHF{rxY~|;t}PX90y>p~St8n$UC7C7MZ zO4^3Wjd9q9`mqj1@HzxT8s*kDoc(gku-aPfu;r^KixqSHHrmG;jxDnudm>ksj=@t2 zX>#VQM4ktOUz(^X<29tZHATSC<8HY6{*QpN^i$BF=YeFDScE%!m`6^gdKnQ^m|s`a zI^r8;W&oY9>jdrJCG~%Dwf1*1ixUvP+Q+|TYMB26iHHV~wv&DY$>B*8v*1hPJ|UE# zvfwpsigxRXjD$3HHy`m!{`R@}_JfIYiI>JqvXg4H_Z`eMAmo%hy6cY+&95y~S)>6K zZj6pf;T;6fD^rSwn-|@Dxi3ZDYT_+fr(9}klUcQ>;EP^}xvXY8Ce9T`;5bUYXhI#= zoMg{L^hb30piI2&-goNjoOo8bOrfG8g;E%5UQZ$H9r|?uA|;)hcM{6#Rdbw7vsgl{I?!IsMja#rA>*T3NDVEyHcAp5mgwoS=TgC*Eb6b6+DB679!Y ztQgtj3%rgTgv7-2K2j@$?}9pm1@43QGVwe{?wu8l|Ma~*ssH48x<2HGLd|ChIp}Re z+pffm|rnfu^y@~uc=V6QjJuaFt(8pMC?+9<%1xZtgRZDDmA#qlrPv)THusLaEWug+2en#@AGV1 z0rdnq)%)lAMYJz@yf7Q2Jiqa$jKKG27BlwciQjk~eRd%PrdO|9b>OFyD3p}K3(hBh z1NVjZwOGD^Py%@}SD4cibtYNQ?$bxziF=nAqJN*i535q->Hv?U=v?Y7hl^VDI3XiwmvkJ z_A^$#(7G&+_cNa;VQx*jtE-GH0PPmyrcQHcW}8d*QzN93Jf<&(SaOz)$F2OeBw)=? zDyrDxR;53>rJVb&g@x9a%9=qX9j}K_Hmf>`>OD8e#!6kdyHhY(CP$6=3M-3>r~TPx z+Eh)veP4RL!w3T4yi;UXdR?6=WMGiTj*=3y=(ar#q!;2pI&W|S7-+L_0T9MXH0nm# zu}JYqJ%sJBSN+RcH)%c1!Y_^3+dZm!d!)W0{HUn)H$w0*XV>FmwJU{sXKJuToDA@!MYk5oIegA08fYHIE*? zi@lX*9fk@uWCZYGk|`tLKJRclK?Li2=;Vu45i!rK=43?j(J#4XEL_WGmH}ikRuQj$ zKcT(ugU-p+oZTn}E`Nt81hS=yNvdvyzMWWc zi&t(LG3tgxG~~pi{;9$Jlh2B3{#i));+~(C{$Hh9nRewiDy8v{K{$BSp9OdFy7OiE zvi7OfmPNhpJ?z8prRwA@d#^1%uRuXqN%fIe{}ooSn;cOw-H;+o>_%@al0!|XL8aSh zEmHF?BM=hrz$WQrsbX=V5(Rg1f76JIRP>ik6uv7YG!lchW$z+vW~m=`&in#?>c^ko z=k0_DkWY9Jw^GDaIy$`?v3o9Qh5jn!(EQS&(<`-RL`ozv-rgvBS3%lFA{jL`7B>Y@ z<>Z|3!LVBCmTKn`bs=NjpSaigukJTIpk}$IMCE6O55zWYDC7wNY@mIUg#L0W#lwih zsG$`9p#+7xt$L@-Gj>F)Tvsy#;%AUkU6-9km0T{EO;28!vO?8UQ!98&-0`fx5BgS7 zF0RRYZwh+*E3Bloi=&jIy3!gUX~u(V8Tt9GrbP~yg=sRc+X9}Jc*MQw;~HYyS-I^E z93fTwo`iP5CE45DRGK0yA-|H=WV4D1YhmuAyz^VpBpqzf(cMS2nj6wCDCGb&su1F= zw`==B;4e`y;jt3c+N^_^Dm$1{_*`Z;`lgU9=4*AH(Zf@A4EWuMRuPrNkE~?7CnXUv zGv+KT)C5R;-$r-ZY_8KMAs}uo9h*`P)y*VowN&Y}WG*E2h5heZBD z)h@89mUT%YB<6?B?GL0;BD#0sf@?-$l12nOs@oWGK+YK<@wwyu)E2Z_$f+?h;hW5& zw!-^LVym{(i;RXYGzntCZf@618kVN=J?m^-GzbU;E_4zP3HOoqxwx(y@!sczXn-OD z1(zCw$<;ch_9$U%UuaYN88KiDDQtHM-Rj%%5S+V;vh9~F4oZ7KYzp}3dSc@)M)aB> z%vIfQ+%+Pag|OqyCmIBxhdz_;2LMOLr8DHlgk2b&ETvQ$=W)Lt@^#Y03wFmq9bUCW zuKr)QAB(SFG2xH0^{0RJ`mYPQKZ0ubx{02Kn2Ek(ih7T2iyE<#`_zjs*Fvi!s!r>r zwB5@hLP0+=5c2)?W!nDTv0u@Au^7*Wu@_)2h*J#!JhTex(#A6Fn(KGA#|yWZJ9dgi zmE+voI<0$4(%`P1>cq16?Ri9d_v_)$XWtGp9G-b8R;zJ;mY-gatsAgNR_QN_XQb1O z*?nqYX1Q4#*^?s8Thuw+S~pa^YiVz}d0>jl^zHw76?y8r!OkK}+b9YU%k7vAal$^D z-bpX1GD3BY!;U&JVs2n9sO-3?2m3AQ*G7gCsS6(PkObUSX#x+ zD5I1stCXyCg!+@E=N-hIZi)Sw3mhX;#FHG#3MV^l1bN5vuLLA=gTW~oL$q!)(y;e* zZ8HYVBML8deJj@^^c++9RTZquY+q{S@fHO*PmdE}f9eXIZfPXjwJm3r)S({AKhIUr zPT@5_88u}QN-ApTH6PecC@y>lFVZPW8!8-b`^hUImNzQ{{ZzL%x)Y~i@4hEpJYp(r z*sSS9X;O9x^GXH3%2KmR_A_zqb%;pgnxsNgXB>T}&-PCa{kj`kFe9s;&5~VIT1{Uh zr~V#?!W1hY#Ix8SEG5Om%eH?x<;exQH8+W9YmfQV*w)r2oow`?Z_cgt$Md&hq7`L# zR6RJF9zEq3e=M0C*g?W*;wSj3FKgsl+AaFq`uh6o5sGQ>LVsTj?)A_xT-0lihyW+* zlguGuPcPqfM4LPi3&*;}uH!uEEYjP0rrAo*6g!nS+Rik}1?byEhv9TX`OaJBC5tU! zwEM3;t2p7^pL@R4pqv%VxNmISIptq{ApfL!?T-`}#Z-Sia#mA-47H5x+McL`G)zIbW#Iv4mH~JbP zi-Nr$a#Y`jaq`8Uwh9UfagFXQcY+mte|&_Lh5?) zUeQ8@=JVpIf~s7#Xrg0>h62r9D}~-vp88<}r<`R!`W=RMb5%O_l|)=;-ZnZf_)m2V zD#@~nbqpMvwbhA=^8Jf@&vyAfxA#Hw5 zx&^t_TFHm}uU=67q;%-6i+EXPKQWua>eRSZiUm_z*{yg9Luz&nHc-D3u)VaL#@v}_ ztykGNPwSBhrrjT+h=8s6U7nUD09>q+khLR5bGododR`C(iWh{+oFD&a{X_W*piH)Z zf#M;VTNKB=Zf9FgMvc*L($ImLNA|kq8e}#|6%Bt%|KyzHn$IJj!z15+C349&VC2~6 zhp)%;x?&mGNYX}p$EA;*6%uo^?6#i`H7c%EOx9mD=1T{v`w9kpF^PFOQ8i939&PJUhh#; zdzu7xCp&|D^c(n|FYP7Kfc8R_ac*gPQNIU=o{3qrs?h>Bho)~_PpN+Clt8`h);J`R zn0O|M=ElUtL1c5RFQd*2QDCJOhU>Kl$GaH`6H2{xY5JYdL$>gv!n;UNE$}7(-FUKc zRn8)zbXzM$<|}MnK#r+YE*ZrvmgPcVa}(Au5U|v3v+ODz{o~;%Am_|?LDRV8QtHa` z=(?$+JMdoc^Y0(><9>`~qA45NnWab=i76q9AVyM;mWMpn0`)e#)ZNtp&e#{@hXEhO z8*Q+dZjAItGzLiq?PDcj`;7KGWV+t>5rtX^eY!Vo37waEJXsFWk&*%{Ln}*ZYx7Y`ngVqW$g=cz;O5gAk?k-}wn(blH+X&d zI#&;2nZvQSSy-77s{uj$_a-cVaRJyHDV*(8re{QuyhRx#M~o=5uxXs`e)E#z-sMFs zMAqus+a-PKi*&SlZOcOb!XmVy8Pto(BWvZikV?7iXz<%I)NZ|?OL%EiIQAx#LqfN3 z`&g|m+cN!k;Lo2E3R%DPeKRea-`17PX8E!RJ6`VCM7-9?bw<^?k4#BnMqn3!)vce-##@ict+-nnIdYnx9$TfWUxig>~J9A#mv$3`_q8KZ-`L;MSThC-jxD} zg*NanRc-Z_Q^9YmOo6!rhXG5B5;*M(2#b=FD@cWaM_?fAX7d)J?L7+#t8+mWA0q9C z4r@O>XuchyW&xy1mlbJdAyJjrFLiP<`2t8A4Io z6n6zBThq|6<&W;b>#B&Dm-GR>^B?)gK{4nP_sgeWTD#s~1rY7-Xr>dELV=$FXB$9sVlVo4S^pe zYzaK_wlm3Qm^rPvfsdG!M_;coqWd{{bhkfEa@5k7+iSmr9M9=R&zXEp zF_pgi5VSBb5@^41yzq9DY~AsgC&#Gsf~(Kh5ZGL%9u|{$RO8c<1dWoIi88s(B1r~{ z;c2WJWiT>r%KscW=aD~8|4sF=5Ft<9Ev5J+Q9*%i$6F^F7Z*2{GLvERHy5S3Yk>h1-53sw;2w+ zvO%3(5M%W{*}yO3*wyhVSt`C?_D-5L^Ck)F6>T1e*Bo>{oD`TWDWq|*k#F3h>7NXA zH8to>-}TmAa5TVOq@c9hS*+;is4m*ue1|U5jV#?A-^_qV7zq9NIwPhwcP)n!AF9h9 zOs*skwn-+7;T&`|vINf&=A5j6X=a=CW)2^j)Y{cf)Tsd5R!k!oeCspp4Y^xyXmpTe z@xClF(Wv23fzSt@B$36{xpJI=7v7T%Wx6Cc0~g(s7ro@sZSn zNhHYzw#1CA=vy>a&Sh+BZ z@}bmbr+Sl4rEMIZW5C%L*Qxt|fcu@&0^_Dot7Pey3u#nBqxRYp zPlYz_s<}M15$qhy@{tBY->#NnzS0C~!K17rqGXd+`ouwmhPillUY?)d(=P5b+G@fB z>1!_nZf!17fG;%l2*+`cHJwgkf=R%mrfGgj5WgOt@4xHCOMt9Es|w0k3c>1Hsb{33 zJ!CTZ{2D(*(*B6#UO!{RpaS7bmwZcuYzb zch~?v)|b{YVwi40XSd(V$Y@u>$bQxHbfjg~YBb;Op0pYEcH1r*_|VtY_?{a+x|Ocn z|DZ7}?C<{Me>}1M-D{@HJdx{eJX@+}m4o02M){i$pBP`=WZSX}OCvoT$@be8rEBw} zqn#YG>i%-k#Z~!sM*ijulO1S_9)n)pW77QvoGb2jv&TXBcbD*#X%%=A_fZ{zBKrgv znVFe#4zD};6k-totMHhgkqUHd60ePt@nFc6)) zB~DBE(j{AI$M}J?`*0}LA#)U#aie^$I`jquyFu)s1)vuZ&ams#5K={`Y=3|MBob-g zENWU(gnTrappG1lutEwMjJ`Dpc6Ztq)G|lCrUBa7PfK^Cr@poG%k z+k6|@a#sqNb6{-R#S)iNYF9hQqF3nGBUU7!SAFoP*2%XOIoxV|LOZNEMi$q2_-Z!;=F=gpntD9D*>mcGhA>6xmt&lN)^JW|`+=;T^v99y;r~>AvuF;%| zvBgYF%CI!>lF?UReu%5?=;(8sTi&Q4U$x%(hcQR(FS zANh_tyGQ^5woexfGrP&6Ct=QVnH9XBtRpoCB#-SMTn}E7AVSZLw=i3iCAU5C z>A!DtHl%q?nOLR}2-x?hQ7O1r9e=#MIo7xpG+^1Cu4HMf4;Ax(qVeIOr@o+w0PyjA@!|K)x^4}KiRLxsoFLYX^E+( z)EU}&{T?}U3vUWTb%beb{BpONg^M9W6q8OZ`kqE*Iz!u#{$(eGH+)6_)Wh*+RZS%M zU6IQ~%gMsMy3;a|)@JK#Ts7TEdrU`IE*=A1sdtKaDvtx+*R^KVf2M99@P70sJlC+^ zH@HZ*&cW3cid!#T)So8~K41joKNKl}Z`IQ7gcfl`dYu(#KxJL@q$O-~3n5!u<tOIb)5Sp_i#AyvKEOfNrxCZP z74!7nCAO?ReIHau{5Bq58GS%|4DWbT*&h-f1XMvJ#Di`bpQ`Be#+m1Nz-=df8VZbr z9l@UX+pm*Mns=U)bm0zumeUYOipv1)gXp*Q8HN=pNuxwFOmQJGJ!)^>*o|aJnXB8R zy`}V}V%bRdHs$B`(d^%51NtlG&#|o^=mnCnmj%^nl>+3{(`UnqC8V_Al^4PId>%7Cqqw zMM=$>-zr@^{a=^{n*&}EFME^tA)+t9hrJ?gd>5^UTep6J7f#V>|4}W+W?X5ci+CY` zmX%C~D8|QBSn-!t?0)TaTMYl&`@~AfN@wx-;0j`wffzV*4d^s(k%Fj86TZwjzcaCiM{nhco z&AAjFLI;i8ID2Dw?$vCCf$CCdAG;guuPZvtNZB?71D-V$GS zTN|_gtKjVv)&5U^+;jT~@@jQ)u5+rBBdl)1iGy7>!{Bim(#eaL!`^LLoO)$%MmzAM zKG60_1IT(?7v^5z=A)c*$h!Hk`IEdn9@g4*$Ss66g9IeY!U%E}VQq`k%mYP##%HV00pLZQ;szQ4|W#r!kBa3!b_&E!*4 zc)T^UM|wqa$Buo`wg(3ML~@VxPubQL>4bg__57W;9r;7slHQ`%RDp(8N8=1av^&l2 zP+)y3S@;`1qBUk5vt@`9@|X|pWfGPxiTQtYon=_mf4A-jkPxIqq@_fpyJ0{YDHUm$ z0qO2;Q91=_7^IQz?#`jR2N=3@s5Ae4opY}J?C04p=bG>9^;>J*_xjvNeQegQ%w?rY zg+bfr%$5b?-g%jf!3cG;Q#QLBhs*g{hO3K%FHU#N4~J%U8nb7(I@gV}g|#(9@19$2 zN4I+-gPR=R5mFNst1Etd4FXb9gWZL)8ylBqXluD@cSAy-UwCMreUERek$$ty6{61m zgG*!1qNSvSEqPYZte6W=|Jof9H;zfP?Lz5ZKJ(+*HS!E@0c$gGAmyx=!cJ*M*7xD! zu=+#<7iAF*)7r+OGp*bECncVoy)PGniD~WGO=9coZKs*|75GVVz8LN-9uR2f;QH0dv14T1k5%ri9=xhHj6)zX-WCy{oXS5>-gZ0I z!hn07-b_3YPJ(0d7QLs9Ar#=07|lk$W5pE}3Ui}{MH?Y7TdD6TWpzlvakpBgAck}} zLwbHkSyGAo9!*9=(qrJ!X(btK_bT?u{yZpA0ZF6w69%S3gj;MbbW0OG(i}R3PO(}= zM#b=jzn=zXzd2iP#@oAekD8S9?0t1k1`FF)nU(YYPd>{&>;UQx`eCE#sRG7-Tik$b zo=wPNN4yEgrA{-tkax1H=PmkA( z-Ra4ldM}|ZF5jNX4yU9vZm!_rEtMsh*enR>mTr8c|4deBk!MymC>zOZaoytn7wmZ; zGT~EazBA0De$iNG)taSj`kin8$v-b_u^5`fH5cOYySC~)CpJ9nFlP=?=#cfhkZCe) zUcS#dJMV+j&+msy>4iL|tJw7HP>Ti!UdtK1tcb|2v}pk=AMdgnKC9cR-k86Ziv~a7 z3hKX&ZQ!zt$xhB%acDlWL8E`Ge3COVifepzvnHYY6DyFpl1{WbEB7ZDIj~&K?<$dc zdiC)ZLb^VW_07Z8mzOS@tE~7nOpL5yS7zxQR=tJ8i{qwa;IiWo+d_j8m>Z)3AL|;` zn@p}=k)wr|7SViFQ>MJ(Cvh?`bRP}Od?D_d-cBh+zTrU2@dl;u)?VoTjRQ1^!XAlj zeJ9^$Mk3bgTJfz1J5_3s)!I-%>B2+q^klPT zoxc_okjXqk9GN^~w(+i9ib#MBV)0v*dTo)>ezoOjbs5j_eB&H8#oqC>o=3}Is-?R2 za@GKoE;vDBH*=cHY;%w0j#{mwe|f7&qo}${O$5&TyR2AK(JXlP@!h5Ok=m6^sI1Rp z>b2!%uidT`2}qXbC8~46J23(M#Q{YUwTjUDHO%XMBFK$2_w4BgPUEXIk7TUj2K?rB z=NWCY-TQN>YA-ei<@D6|71ZQNuAe|t{Yd1UIkwo-PImM=kGYZQ%ieYQCWXAX0|-=c zcwdkN)Moc*s+yC>WS3#s2$n#1Q2sBT(i=m4|ot>1OMY$l{an~y|9OCvfFX| zoNVg5qr!-Qn8av+U?9^z6~dTYm2=fZMA?Z$=!&b;&h~=qyvarya&McT<}B`h%NCZ_ zM~-sD;sY=|IBSZ!Q}8obfsuBoQWN!x$zkQcKs+Dq<1+aSG+FmP@B(_z@?CsjM2&lG zIDA(RU)qPy4biOZGm7d52YZoa^qmtO?H0y){B)Yh5%f)r4Hm+LpT~mnZ-q>iVlrUP z6g~nLofGx$5BGVn#?XA^aYaGjqU^$d^6(J9?q?PQc4Mr4#?@)-F-8PO;qr-!?b8&?KID)2yPYw!PmVb z6iF`&!W)<8WE$e->Jt^46O&sXyM9v`_F*6^-nAMv3xTR_<1W&XdD_!>yn^}bPDj1w zBw6=GftZ+>D})5AktA)rcyw~c>drp@$a9U5UUfd-+RbkAb(ZvyN#c*8QE(4@vK~g5JH@~Qhc_#M#u{b8uLEl*5EQ1+45RyHslT8 z2pLkADD1;-BM6O2=@NYGm*f#Oe6pD8W7RGd;$Vj2PViVB_}<=be{GkHgjdi-Yju7`h|g$V>N8-j;hZWya_T(IZ3H0wuC zZa2(lj~mff;bgOzz&HJ>+B+C!$L1!oOY4LHBZSE4PtIr7v{Y|+E19$cd76@DX9eCh zO`d%NY?^gn`ZbD%@w(XFYI(gK*jVL~%$yAAfZPt7ReN6UNy|x)OZwRZEjb9)NzocU z^;-Z_)zn-fXRPN6<~Nvqc6IURajR;M)(Qp{hph3c^ivqU)OAcm=&pb{+hHby9qt+2 z-!hgbnG*8yBElon^tcl>Z5_uzuNR6Uatq5HAbc-f9ArugZ^)Gs)st6vvzlF!wTH}( z73MXGmDWeAtXS>X=W*<>e*VZZaY-p}_E;42Y@OK{ENQ)uh|P=~`>K|cVYgh`5-mns zqL=?${8a6)-R>01B8tnxS1UN;eA=m3?dr?KwQ}g}KBUc~Y301tV*1oH{!&hDmsw|R zu=PNMiq7nh){yP7b|2sUI!0~LnZNoLRPX;aYDgDckPA*49vx*&GO1Dy zQdQtK``|0vexSRG(5Or}^KwECqI+R1?26mm+XCg7n%+l!18;%(PU$4;9*!;K?FgpkDtS9=ZMwzG_rAIULl0NvKZoy(|Z*H7dy961j zqKsxtfwP3$eckKcHgf6gIj2H__aR7)o9wtc`W|bmkw8Us1L*OPBCkk3$ROUA0Wq4$ zJ&z?hbqvk-*}SfeS*3Ew>2RMS9h;8*cLISwZXosVh%{O`pUQi1nFKB#Y`lv97qZMB+h;J+zeD4^9 z6=K3Yp1TF&d4xI{y|h@W@8mkP?~0g(wbrfrlm=D`nUM&M5?+T&Ey3sZ>4tGXtYDmZ zP=s{7-!ySh0@6X^_}BIP8m-Hoc5dr!q}_hv>Z230iKb+bKKCmUJZ$vEk#Nr_x)^I(zOhvy*G|?S zCi2h-5?8N4N^}&|FRv`fL?T##(IfdQ130H)%WuKR0ckhQX;i_|WQjID@H5pJ@8yTT zCyl?J&s%qa;RhEP_@rg~9h3z?-42DhD7i%{$hfR;^ z*@(zT7r8kv0soE}J8ZeGhJUr(t9onJXxV!)uKZLc8)nA)MXfY1!IY03oSQOA%xts& zMZqQA^$?V;jfBvY`rD~q;N4w;b#NQ=a*dT$M9JDTZ!(KrUSvx_g)Zbbf?Ncnwb?_V1^#zLm+Mr!@leB#1kGQ~89cyvX0bSnV zK5Y%(* z{XFQ6E8X21+@}}rS~?!R>m)c)5AzIlTc3j}goE1ipPZ=c#j(zT>lYr3OP*xwZKBWG zc^>Eh9I~0w$jz01o6)F_-_{`Uz$mo4;+>3{Q(J=^(ClOb@WuMv0|{;LzYDj2s?U#5 z>s_mU2)d{km~(;~0!ZpH=Sd;Gr(#sBUeaIYZ@0Uwv~cYgN$ZwFfcys-aHyM}>t%~fo$)ZP~o z5P+sY0SxJ@hshF0(??S%$_LW+Go-&uj}|>@20;UlZ{N>Gvf75wWpFM?>Mn=CJetLB z;v?$~dxz-R40lCW@Hz`{J8B9*zd6@+^} z59X9iPg7&GASi?X9E`rvq((X7*%XX8wtf51F9-YvdFPkd>UDShOO@+suiWpA%E)HQxvRSwFtSMl?I#MS|UiwwvRlmS zSlpUUmo60l)~EQYzgQ5MTkBM8b19lwLG@1YFK<_=g)CN^$8Yi>(_&RM0~M)%SG`eh@)v^@I`$W zVv|w4@b0)xoM}75>qsFaJjPK~+-LdE8I7fjv-8gKv9FtC)MB+ooTe8tc+7@$fEHAu zRYBJgB{bM`jCoGzvkGfZ)fXAKM&7%E1XjJB9R22E?@0VkN#YI&)>Y6Q^w&H)UFhK) zvi;G%0SE1*5*+m^Gt}ca22X4cjUUkS=RcqzjUla{E7yhvn?Q>w%c-l)*<8yaq{KoTc zakUh3*8rJJnN2IS^jgecs?KC0YVx@1T=kZv%A+1Ul*v}oZ|Ds(J$T4^$b&cXniOvu zf?lN*%}n0vsH?nSsWWQYovvX%*0Ys11z}ZlY4sPi=JbOkE3MMre3p4)Cq|e#uaPZ| zG%UILvDY;~=SHkRcd1v8aZK9uU&y`GZ@HZq@@9D$u0U}u7d#fXW+i13?zLUU(*_RK zr)d=2l4^2^+afdai^?R&yVINUD>JksdqdggIF8Xl}uU+wKlM>lVv6CjfF*UG8>^z2aUtBLpKV^wqS{=%;H$@ySUccp_i;RkT=lPTB z&-}pe+i;RDf^Fdo45LG_V~^-Jo;$SZE;HH#iVEFoZ}!(N7W_}*KD#HQT6c6_V$ANg zsihgGLeF)Jhs(Wy*f5y4&!454e4o%q-?ITm8{9@bmBS?o4SiORRtzd08aJksK#xC`;&vr?p6 zjz@h{9YUTdoRpHngHGO}qM;Ff|E4MsU^Rzfv5HoB60?M4{Tuvety>C^jgHr09^lXw zEhMfdit$Qd#o)#shS^F1l$QcUXDbc58h!MHzuRcWrKE2~!(X?MikX!o-}^WlxX!!` zDvPcTnf*|o2*aS*cL4-8ah6czIbSYR{@ z4_7uj&y8IPH>{N~b9@$_nP~utJNDB<>K3kH&EV`s zjlxQ!8s_~}_4+fj_<;rZkH}{U5!VVVehJH2+{^+XjZi+X(SCvX26B_)W(3mzbJQ#m zxZGqTx8qA;Z5lyUaceXhQNdSBzul@&zE^Xyr=xsvpsuN#A6rEmG2c_Uo8nN1-GKBu z^O;rRKyomG=|iIpH_`!vTrj||sqUKyLT^i=O5%0?2%!@fU8^|m0XT=FotH*g1L6@Tl+=K~ z5gHDSBv?PHhef@m>MjXqZ9ly9EkrM&zjx!lb&;~k6 zkn3q#+2f3%@3?^RbM`ZZk9-sqL>u)bj;0^*Z<9UXoj4p*iLDn5$Rs(2A3}_ks;OTp zeQ5c(`Ewipl1E-d7mS|qI+skjB!aV=-YnYXz@JA_&E+=o8zh$MpUwLjYAxdmHOtf3{?eYuQ`7s~(Q9_aapzh6>zyL-!`~ynHFmL^wLs)?UR({4$Se9% zMSknKn1gqbrK&i>AzZGNI8HyI%B`~NDapsQtCglw?x*|ng{(r56diYkUOz?elR#>v zL6pALyO!0-VBp0cW6&LvLQ+sv)++3wKr>+eG{(jl&IzWEqID8XS_|p&0H5>z2oP!A z|2k*@G&@3y>3vmK9S!W;pcu^4N~9_Jx{`1Wcq4X_4jJz=IC4VenBan*)8)ja;9TAP z?FNyrr``2<}2@fjnkCN|isCFeuG+(I=$Fg*v*2J1iYqSmx%PVT{s zeObK)^#7(zs9-(g)H0Zom;m;5=li*p z9({2%VY5Lhh2s$lX6>d{!McXRCS2_pO+IBL{)DtXI@k9Rsy_A{_DM*K9myXb$sc~K zBYugw+c7?r$-baCPf4We6{=dtqpw0qP5o?+Hq;A^7Vnq2jZF&~ZIx*fE9q@M6D`^A zh5T)&2J~#U>*`MV!5-5zx$Q{tu;&%#-z3d!wDQZu8<$wPe(HFA0_xp@+UewAj;-NKpgW>Wz{V zQLTvcXhbow{$HK8L2e3{;^lrnWOXaO6%xBzlbXO=wD2&V>ereShNrPDG>^M}F?Fvj zagMDZEKVbHt>*RMqLc{1GuVa&c>kyLK8#UQMGKNhU@4RIp z--|ma*Aa0>ok{0ZRU~`bJ5KgkRKwx<-ytJD>heu?0_ zj?;fPe+U8E)lKwvb_yFAdK>@ZTIcBYXEEyO3G-e-I<}tnXxd4oRM%+4d5&nJxMhDW zyBrQZ7osoI)Lg*fxXS%L7$iHQyr}5V!=O`9tiIZG_k3jYBVX$w(}*olQ%&6^MbbgN zY%1gsYdLw5~}N+$IHlv6S7D#m;Bt-_a!yyF`AH~U)wdc+0}&nB}zkiWQv1kM1NUq*sQ>o zoFfHc>J$-1Vx?gU|taChJbgL|G+id58fmkMO()15dU^MKCtCS?k})1}L*jE%1Q zGbN!auBf~wnPxW+01rZa7za*ekpL`~H=-dRks=P~Xp|GeUss5z)E81MwM;52V3g$l$mG zWV2NNxk#g=^6ncH(|W~Z0RPs*(sR8IZU3DwvhXFJC#%J1s}0S=#T(skaU;{puu)rO zuTB-g2HuGJkym06N@aTQV#l;MT|oAM=$I%6CGx@Ziv8PDvg3>dryq_9b>LT4+zX>m63iaj}O^0@I-RCSS z*MmhIY^CW$eTHwpy=Z3ZW=o*2VM)jPhKY*TnoZn|_e_fT@-yD`TQ-CGo0U8m>}HOp z{m6*Dq(t_suLjNi+i(182YDu2wSoJF{ld`UgGs~&`)?EB%O^d=>Sa$`gSuL-EXLpY z{FD-Sf%{0!!gS(n3QpPNmH4C2UC_OlPD{mS5y)+n@XBeEr**wzL-NZ-b&nE4{aTBz z>Enq>0Y9bl65_q1RZD5MMWIt9-(0l)pmEUY0h*R9H0d=fPwt{y*=Rjq$vWiN!_PjK zm-IG9(N?}+8H>Q()>iVRB-Z*%tV4`I6pEcn!@$W*}hj25euOjT?B9FJ$zQLGnA%u$%x9I-kS5@4!tSQ`k3%a zJ9qAHhuC7t_2~WxznF3IPn$4?WowxlZGNXmUJ;jDJ)$@hw4a1VuCySH4~1uhbws-} zK6*Z%^0{grhoDn;vA6zrKfDs}QoOQUC#1urFXav@+LU#D9co$V^CiYSxQ`~V{@CBL zYdMDLd#`=7dU6PEseDvltZ|D@_nomwDD<6QT{4|k-@3XXQeBK7<9X2^wiEa8J*@n@ zcZYT5Os&ddvqx26jekp08DRf4tJYc;D#AI3DlAgw+3)~uXYE31n;NyCeY<}PK&U{R zhI2MC{#7Hd1Q{D!iH4dO##;wm|5Id3Vi_43X$wSc*Q+)k|MT9JDqZY50vo@Ba#`$w z-EW(4O}W>+mChIMMK8WgH9BgVxLwqmxC|pnW;99!!4_Ezq?YR#z|q97l4Pu0Vl~~X zclo6CbqAam0m59D$qp81UixVeDc5<8~h@?T<4z{Ud(fMboox7uVAnpvS+r%>%5)}w%E;1 z(dEf)GtgCb?P0jp(BYp&CcaEEw!bGsDi_i<1aE<&7(I8D`Wq*(B$oD;4m~*AWh;RF zkZN~UYpkV&iPP{Qfz-Ta`1|u2$Z&O!=2NJ?+qDmWOYLlJn``!nF35t4SQBa0j8<3X zs2maS>q69to1kk8%``m;6@hsNTs22)ZA}Dtb!^dQtZLNuig$BKO6V1R-xfB|={jkD z0cy9Jeau~Hrx93KTs2F+l}gC(Q7CDenQQkEfBCFsDoFF;&uc+_+ks!)aYL`-OT2(H z)+MNa;&S7v?U|OZc;7QO(<$TkG}+YG4dlJvSH{DvT^N<~EftUvWxN(Mxb&3zVM?f5 zza!aX|2Q9pQ8IkNA6$Hv9S9kJ)s|XXX!^<7Rc9t-%iNb*AzItCG)pRK`CEb-=Qiv^ zUP!ZWkku|5nUmQZCh#8fD$-6~?shQM*R_aEBj>2}2*|=dI4kxm9@?R4=Xkxcq*k5u zkw0grG`sPbyXKT^H6(h|cWVVyX&kB;ZP)+%ICm*3%C;pkdxwB#UYwKP&(W@mAPlQA z0`q8=NiC1^tS!Fpvbh4S;N@boNmHubY>6&>F!`_i+GL*c z?}(!O9h76m49R$EK-V5VS5(za^GrS;q0IChroMmj_f$#Y9oXB;pQn!&-N+jAN_WEP z+vd7BMAELkWGAwr*{WiOu?MUI!9FL~;?|g(aix!AnAVpmiL80ut9R>>SGj(O@7wG; zmKw!%NiRO$v7+S8wLV~`wcdkGR+>FjFcCp@76%J8L+Mgh843mTz$CL@U&JO2M2$|A zIw->+MG!rB)H$pnA2j7;6{x-kTGKW;T57<2NIDzy(a^adnMjTUI?F_VxkajRSMR=iuTilL8O(&f=`e5UJ%%(R&?oYAoaxj6cko$S`hFbSW zrb3zeN2+u5;08lKHj|q(73OyD4ajnR@Q&tj*Yf#7$J1i&Of0W8sRfyl-jLam)9?d$ zi$?DNZ%1xVZ17SP69Jc=xDmY_emI5$TB%3nRg)iu!FFIwae>IT1a6-Oy&LqMj)Cz|&JuduM6{nt;} zhk&l9%Psc;?EQBtnR1ZxtONr3Z; z0dY^K)NPsKFQZ!|Q&RwPL_JBfy=d%beHLpkt|YkbJ8lPA%A7y(aJsl&T!Nv^7iT(6 zuqYAAgKp|hCJMm>D1d5e--!Ay3Ay2BV0J;zYeYuA99}Kjx!Ffywlk%QgW8@Rj_a=V zJ?3f0`rEEj8&{AE4|eQxbP_#-S>K%pJl{v?)4i(KUSYo89de4s7XqY+BhW0-(9uZ5 zA1)@p2dC=a`Io#87SB-Q9|K&X+oSrUGGmZul~SH_ULu`To0&AFmt*9f6Dp79_`?$m z3%2UNO}idCtD#HHVTpPyhk1&zP!*cFaux*3nzXtkQEn7YlV zv&~!Tw))Kx8qA5+!5N87V0zk;g!=WY(`FLkw$dQ8P)La%CC3i6**=$s^ddqs`v_;35sAd_J zeDd9;E^k@ygi+Y=q8R6Pc-59uICgPU?q}Q6w=UHPt^D9`771!Pxu^7S$~gJ~N(zAl zW7=r%dwWPt9lx%vVZc^-k~GZ7;H!uFthVtwb}ILiv(*S&g)IuS%du%dT93f=k2>}a zkY?3tc~JB6VWU*px0H3Ax+#g)Q{T|_?Bo#YwMKI!*NU&W`2KeEZ&%-|0&57>% zRr%}dMWbl3?NM0UO{6NwncM?xFB$%`1XLbp{dz~&g9>;63hbyD0*R$+LLOL86bF3Rv?d4;JLin+6CnF zY84Gc6s)a&H2Q!a9?7}=1c&&o-0o?DJbFebSUn9_I`FF`!q3KkAir0BrfVXtXmgZF zl%L4-3s_FLaQ=)1^-!7jF0vyKeJfu9)e%6z!isy6IY z_Pqa3+Mz^_I%K!f6lb>26C~u6TXI#Y)@F zS<8O69kbk8}4gHS%9dYZM1M=qYmW6p43D{oh}GdG(1>s}JS+Jj&}dlLYJ$ zD#1A3sUNme?-GuS{o7_vA};P3?XE ztSM6#$FGpH!!H*O`r-uCwO7t9j$-15*(YC4u+bW_QmSm=MNSG$qoi6F-z$Ugx^+UcH-E%bE8JL`gN!*BAT#&a@#U6Tk#` z|47M)VvC|ht3&$ zEc1Ctz4}XM{4GA3kgr4`mLc?Gy#q{kv8ikz7kz1=&JGeTfvffX^Gpyf1!d+xv|Pb* z?3i%e5NwHfd9NuFEliqM=i{{VcLj-4IPz)z!R-U^G^eP*9FZo^<;!pq4%ZYkU$k#V zz`eI8ys{z|^be9=t$q*Dl<}i{Q=$AQL!U|Z(BJzEvDHydq&%V)V+hkz#mwXT-ALW_ zaQLog>7vcY2vDp|j0mhAwA=X$Mzp@goy|v8JlZt$jaiAN^-D2|pg$wUpFc^DL}W7^ z=2GrSiu1e+a0<~G65J5o73veD1>@^|egpT`9Se6Zg!`ng9D0?B+@1EeM2y?rT_3xp zwu$dZjS?xOnP)7Wuk1)wUjY)uRs1R)GH|oYgk+y0RFBJW?w)+nr_?smcj;wVXA+Ws zx_#-^cwkl6EED!>@K!I1?8ZE7FU63d)L>?NIarkZt@cD|a@o9V00m_@g~H9cdM9&R zPT9l*TW^sk>wQj*+7_ye6#hH5zYeday$BpP^ff3y=iL6`C&}gIVHrVeo-Z0@$yk}{ zE}Rt=Z&$Oh>WD2?@_dcE@wd!r_;Pumj`v)KZ(6wwR{Hm~+NGQ$J^wF=RSUUUpogWD za*f8<>G{ko-M*=q!+VuqkNKQr8?U= z(resn%4@byrI=2kox^k_-pmFZtw`$e%7fZuyvkOp7ws^GOuj09*z>z zQbv#OJuHPUW(*ZQk2rd$kWpd{11vloxwY-TmM35$bx#!wcMSP4%;(=3A9<>QQCx1% z8pd?HQ3d#|aCZZX77{(YJV$E84N{jqeL3V#)MHF8v{cX!?MpZA)kYv=5ZZe< zS)dtNME|U)6ql<2>_0(yDqa%+he?d9i!Gn)W%wCmn~}+i_%BA_#GPF4D;SQl zM{VaUw}6`Jh2e@EOGbb<^-1#mNzV-yqGNU%dZ#y3pGA3(>3JqL-EVYXF?D{N0KGu* z{6kG|(ER^c0Jk>|a$rvCli^Se5Ey9`9o_bbG1}}%uzVy%Op0&HJWb?#zY{;|Gx(Q^ z_bHtRb&~kM@bYv)qEQAMT{+@<~{p!aW!vX z7A$ja#TrXoGm%VGVxpTnA5=o8KT+Z{f>BlEavGA=Y5Kl1ElVozl4-;7cb2f5O|>YM zqAON0Q$LBfy7g|@rs#V_p45r#m(NU-*v}N9S|-H#?A5;*@)sI|#88XqHF*AvA+8F% z30cWZ=4bd&-;bFjsJ$%^UPUa(fN)K;O8^zULHyxLg_ZM(dd8_$=oHI-MdWIxm?__` z`uuK~?%Gx#gV?^Vd@C;zRQr6nCUGI8N^@D2myvY&L@1p>rW8^G|P+-?}-3X32Ex5n?C(`DFf^*R(}4P`u+jkT5AUb zbbF=POh$vHpyfNgO({A#HFm;esQ8mNraiy_Fa~%a7*A?ONd)BhhlC6&iG|$U{1YjN zcZ9kEc!%gDXrpTNpN@)(ip!TfIPaD305R+>7hmYJczk4XEG1ai zN|5G!;gGwCNmT|Gvv}2RiA?h996OG-dq>Uu1}9ZQf|+mNhds^19v^5^!BP&m+#n#! z=n5xj$Z;*MEDm~Z@3n_I9B)a9<}0ZyL4m&%6IF}0@rhdE4dO>+wO*gcD9Q{9*yB@} zD`%LPwmc7^42@14+ykDl znY$smqsn^3$btxKUQBIzdW(jJwt)*AY}i${WH4fLn6NTy64=DQSUu?yZQ4JJm3A0k zmWus8ox^XbdihoMe5I@lq_2sMQGYxUonLc$xEjqzY^G4Y1!=}tWH0}#wrWJ5%Q&A= zYdEB=Socy0+PY$^IJroP@r{1Q&0q{0+sV4Tt?#A6hg45~`8W!yareDMaCCyY&e6Th zApPvOBI=6us~l)|!)%Gekp!z;#8U)-CC1_X(1tyTwuR z!C*^)F@5uXAX%rG&rmYbTe3)(7p=R=>)IAm3-zQj=DDBLGovHjEK*okXy%J@Wb_ZT z{wJ?Q?~Qzx0MYY?tmf_(_3vJ3UQ{upeosi6$w)`1#Gc7k!`tIvLZDa8sF~-OXDB3B~AwEaw zvjSe1#oW2R8-L)WuZ>TKQ7;}f{Vp{%G}Yn2KLxz3fhF8obbe0V$QiNwNb0+)eXv72Yyb9YMkf6 zGJr;QP&!7_}+yi84eJVO!#p@#l&OzuuC41i-Jd_?gMNLv$7j8L-YW;8J z^gC)_K5E%h@7hf7#K108*WN$-hw9<9K(+IzRSprV*UHb9p#_`+8`gl2FEdI8AUMsBVW38b+GTcEVfI zH2W)zz#^7%pFo1|?|bMxDq;`LTFI8rGO;-@J=1CT^3{7T0cNEli!skxn~K50OZGV@ zLyI66oSSkVFPrz-gM&Pb+B&?7gsj92P7ANBsCTMA1bm!U9Iey{(CgXr^0A{?v+;e@o3E%Z zFkZhyaGty(#Ctk`J`RuSyIlR*-ZoAYp1XzuPaQNd=@eYAFGNm~&ro>%e?39Lexv$b zMf*%~{q3u_qizRw$YTJi7cHhEl!n)1ot(nmk2LaiD-+*@8mP-vxr-v09l2E2X?y&&qX-d-YUmK{HmLh<7 zhkVb=D+bE;AKU($z?b~!j>VOgodLt=<{Fy>-I6+)ZwxF)(688NtDQ1wA8!tTLVqAPY=KO;A z;m69G@-qatX{gpfQqD2g8J!O6!$*&cl4G!+{#+XmwzMoUt|sS6K^9*$GdYlGr(oq5 z=iq~2iXkI}clj^+3%3Ch^KaDwwlbrdo15w5s6(S{b!7Pv!x4O-@xY9!evu4^)Zy#d z)2k#(OV4hMv!ZAGIJV1G9hJQB*Es%BeRpguSpt~mtd~Xir8!5JS&mggimbw_1eVj@ z4ZdO|{aXoerZWpkoX`BF0;yt}WpBq8(Vr>Jnr+P?ra3~&LGPd5C6&=kZe)9^d?JfY zlVr&N_Ei=Q7E8rA&9>A%KRBw|PEfhS?5GoOI+erY93{r`I*9NXgZ?aptk(Ykw){l( z8>SrbL6wMD@73xL#D``4Ei0Sdc=Z9cM=jPbxb`|E;pg)zGpOq$1*8`>C7CCGp4Eo> z2^Jmun@7UxNPPuMBFFG(72jt^s%<;^l#g$kc(e_6tbi{aacqP_bpC9NV~pF5%;0J( z8Rg0ODvaka+wVrMv{f7#a)T73OiGt1#fBJOD!_x?-x!Rpjo_L=d}@b+Jp#<|hdHY0 z8oB)$A8&qzb2!8AqlwMfcxsVx4AUPL-W2Du6N)i<`bi>?U-br0m>;0WgP#nkz|fgK zCiA;gvT0X#v)QA*SgooXM}doyjM=_eix*%j-@ztLZ@|Av{`tigG$qLq0W>BY*K9o_ z#>6Bt^qMEjZvbwIITtFCANvBYfkECv+i=7bP{F3( zPB+@aQblC6$-GVfH=~z@Tn`8Uhd~|!{8hw^KxV%2}(U{$kmMHxE zCPSyRjsGC<-#4iLcf1#DeRb02Alhn4Y)SP0x2yki^lukLe-)~ILd;OS zfAu1!Y-bpIKZ$8fkg1*NouCz`K%b*onlZmqZLSP9D?Piv#WnvB<(^u1+mFlVfSr-y z%6o;&tYCk2?qW_&!<641W_E2g_)Mb=1}+LUTcbMP;xzQW?S6-(Uh4ip8*yNH&s?KG zHedU+r5RsFhZ%OeL%#R&BE?3ii^^10%sjM@x;iX_zi6xhdEaQj?DSRus$=wB0s9$! z`W-N}_TbC3%lB`xB=aq*qGqd2>ligk(jx`TFG=JRQV-krc!#D=>t;oE!02B0hHN3{57-Y83#35AcRgx@+i{p$ds{(=A#|LPFz z(8Hw~xen>3WwQxGwLB%Rb`YH$(eK!Tp>}~pJ;%`S1+4bpEMufJsh+5WZOGh37Z>!` z7$@x;4zj=8g=Lg5^z!aK&bR0D#UCs%#l6a(e=1fi7ar#fQ1)-sEY@1zi_q8!9QPf} z6~Szrn;oAtEd!lYg-m=4eha&KoNHy#M<$GCCH|cAe+b=Qe-8 z7w<#)QF90x&Uqk@Ie`#;aKQ?x2grH+wiE)W4!L?x6YP;0^q2*L+;1}4ARXuIe;ME` zEFbkZEf53*k&k&k?QZDkMiL}_{w6EK{eGhT-CUVWy)k8Iw}#a$(_@4Axlr#Mg^PS& z^MIqBz@rGWvu~;(>v&b6c2R5ZH{kp!Ze+xL-~J&Sty;$D$nA(Kt0eCA!#t1dKDs_C z-2}(VeareWzTeWZkSdr^VJdJeLe=h3c(v`({hzv-!_-+>|9P1std^Z1S%BV{z|xS>c;d)CWtxRa+dY4~ zeEl2Oh>&S%7vN6Rk}h!pkp-aYRGYMwJd?6T%?IfF@Q;yHIYrA0>kazScEhtB3P>a& zA$cmWWaTi~E&05EwZ-JymbQk@m-qELIM~Lb^oE*x4nKzyeI=uf4BH08xuI%|gT43$ z633!_9^w(=JtQ#+ycc{>^a!yt*amZCC>>DbXIio zEcvusOU~}-`RfZVjg~((tAeuPx#SB~x4=`2hx0F%3nxPVO(yyug$$+^P_cSL1#!Wt z!T!HO(*JmY{MpWu*)|*f_Su8ha4oNG9fjRZ1>FI5J@emJV%&=p=td0ae0`IZB_hct z+G^Wc9cet)oH`}%2i2q}ZEHF^-t>Id;2oHYxy1HnDoAIY$nD0Eb!4SIVah;W@ns9~ z7Z~w71(>8c6%w3%7`EU%wDI0B`zy8lft__hB`LbbG7tB~$)8@qPbx_UfP z_-dnSA*1|{i|V5P8YK3|-~n0r=V|C!QHcn0zdG-tQF$Xelv+28F�QQNQfG&tW~u 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 Z(6a-@C7~CI!zSR_{~7Vq#=TKr{U6ce*9HIp literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/documentation/images/rp-secret-example.png b/deps/discord-rpc/documentation/images/rp-secret-example.png new file mode 100644 index 0000000000000000000000000000000000000000..4ff21b093fc34e51b24d26e218974956877a90ae GIT binary patch literal 14447 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 Y#6+c~tb$d4owin1RDW3b!1UGs0=t7|wg3PC literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/examples/button-clicker/.gitignore b/deps/discord-rpc/examples/button-clicker/.gitignore new file mode 100644 index 0000000..2695047 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/.gitignore @@ -0,0 +1,8 @@ +/Library/ +/Temp/ +/obj/ +/Assets/Plugins/ +/Assets/Plugins.meta +*.sln +*.csproj +*.userprefs diff --git a/deps/discord-rpc/examples/button-clicker/Assets/DiscordController.cs b/deps/discord-rpc/examples/button-clicker/Assets/DiscordController.cs new file mode 100644 index 0000000..7319d5f --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/Assets/DiscordController.cs @@ -0,0 +1,125 @@ +using UnityEngine; + +[System.Serializable] +public class DiscordJoinEvent : UnityEngine.Events.UnityEvent { } + +[System.Serializable] +public class DiscordSpectateEvent : UnityEngine.Events.UnityEvent { } + +[System.Serializable] +public class DiscordJoinRequestEvent : UnityEngine.Events.UnityEvent { } + +public class DiscordController : MonoBehaviour +{ + public DiscordRpc.RichPresence presence = new DiscordRpc.RichPresence(); + public string applicationId; + public string optionalSteamId; + public int clickCounter; + public DiscordRpc.DiscordUser joinRequest; + public UnityEngine.Events.UnityEvent onConnect; + public UnityEngine.Events.UnityEvent onDisconnect; + public UnityEngine.Events.UnityEvent hasResponded; + public DiscordJoinEvent onJoin; + public DiscordJoinEvent onSpectate; + public DiscordJoinRequestEvent onJoinRequest; + + DiscordRpc.EventHandlers handlers; + + public void OnClick() + { + Debug.Log("Discord: on click!"); + clickCounter++; + + presence.details = string.Format("Button clicked {0} times", clickCounter); + presence.joinSecret = "aSecret"; + presence.partyId = "aPartyId"; + presence.partySize = 1; + presence.partyMax = 3; + presence.partyPrivacy = DiscordRpc.PartyPrivacy.Public; + + DiscordRpc.UpdatePresence(presence); + } + + public void RequestRespondYes() + { + Debug.Log("Discord: responding yes to Ask to Join request"); + DiscordRpc.Respond(joinRequest.userId, DiscordRpc.Reply.Yes); + hasResponded.Invoke(); + } + + public void RequestRespondNo() + { + Debug.Log("Discord: responding no to Ask to Join request"); + DiscordRpc.Respond(joinRequest.userId, DiscordRpc.Reply.No); + hasResponded.Invoke(); + } + + public void ReadyCallback(ref DiscordRpc.DiscordUser connectedUser) + { + Debug.Log(string.Format("Discord: connected to {0}#{1}: {2}", connectedUser.username, connectedUser.discriminator, connectedUser.userId)); + onConnect.Invoke(); + } + + public void DisconnectedCallback(int errorCode, string message) + { + Debug.Log(string.Format("Discord: disconnect {0}: {1}", errorCode, message)); + onDisconnect.Invoke(); + } + + public void ErrorCallback(int errorCode, string message) + { + Debug.Log(string.Format("Discord: error {0}: {1}", errorCode, message)); + } + + public void JoinCallback(string secret) + { + Debug.Log(string.Format("Discord: join ({0})", secret)); + onJoin.Invoke(secret); + } + + public void SpectateCallback(string secret) + { + Debug.Log(string.Format("Discord: spectate ({0})", secret)); + onSpectate.Invoke(secret); + } + + public void RequestCallback(ref DiscordRpc.DiscordUser request) + { + Debug.Log(string.Format("Discord: join request {0}#{1}: {2}", request.username, request.discriminator, request.userId)); + joinRequest = request; + onJoinRequest.Invoke(request); + } + + void Start() + { + } + + void Update() + { + DiscordRpc.RunCallbacks(); + } + + void OnEnable() + { + Debug.Log("Discord: init"); + handlers = new DiscordRpc.EventHandlers(); + handlers.readyCallback += ReadyCallback; + handlers.disconnectedCallback += DisconnectedCallback; + handlers.errorCallback += ErrorCallback; + handlers.joinCallback += JoinCallback; + handlers.spectateCallback += SpectateCallback; + handlers.requestCallback += RequestCallback; + DiscordRpc.Initialize(applicationId, ref handlers, true, optionalSteamId); + } + + void OnDisable() + { + Debug.Log("Discord: shutdown"); + DiscordRpc.Shutdown(); + } + + void OnDestroy() + { + + } +} diff --git a/deps/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs b/deps/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs new file mode 100644 index 0000000..f3b1ee5 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/Assets/DiscordRpc.cs @@ -0,0 +1,231 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using AOT; + +public class DiscordRpc +{ + [MonoPInvokeCallback(typeof(OnReadyInfo))] + public static void ReadyCallback(ref DiscordUser connectedUser) { Callbacks.readyCallback(ref connectedUser); } + public delegate void OnReadyInfo(ref DiscordUser connectedUser); + + [MonoPInvokeCallback(typeof(OnDisconnectedInfo))] + public static void DisconnectedCallback(int errorCode, string message) { Callbacks.disconnectedCallback(errorCode, message); } + public delegate void OnDisconnectedInfo(int errorCode, string message); + + [MonoPInvokeCallback(typeof(OnErrorInfo))] + public static void ErrorCallback(int errorCode, string message) { Callbacks.errorCallback(errorCode, message); } + public delegate void OnErrorInfo(int errorCode, string message); + + [MonoPInvokeCallback(typeof(OnJoinInfo))] + public static void JoinCallback(string secret) { Callbacks.joinCallback(secret); } + public delegate void OnJoinInfo(string secret); + + [MonoPInvokeCallback(typeof(OnSpectateInfo))] + public static void SpectateCallback(string secret) { Callbacks.spectateCallback(secret); } + public delegate void OnSpectateInfo(string secret); + + [MonoPInvokeCallback(typeof(OnRequestInfo))] + public static void RequestCallback(ref DiscordUser request) { Callbacks.requestCallback(ref request); } + public delegate void OnRequestInfo(ref DiscordUser request); + + static EventHandlers Callbacks { get; set; } + + public struct EventHandlers + { + public OnReadyInfo readyCallback; + public OnDisconnectedInfo disconnectedCallback; + public OnErrorInfo errorCallback; + public OnJoinInfo joinCallback; + public OnSpectateInfo spectateCallback; + public OnRequestInfo requestCallback; + } + + [Serializable, StructLayout(LayoutKind.Sequential)] + public struct RichPresenceStruct + { + public IntPtr state; /* max 128 bytes */ + public IntPtr details; /* max 128 bytes */ + public long startTimestamp; + public long endTimestamp; + public IntPtr largeImageKey; /* max 32 bytes */ + public IntPtr largeImageText; /* max 128 bytes */ + public IntPtr smallImageKey; /* max 32 bytes */ + public IntPtr smallImageText; /* max 128 bytes */ + public IntPtr partyId; /* max 128 bytes */ + public int partySize; + public int partyMax; + public int partyPrivacy; + public IntPtr matchSecret; /* max 128 bytes */ + public IntPtr joinSecret; /* max 128 bytes */ + public IntPtr spectateSecret; /* max 128 bytes */ + public bool instance; + } + + [Serializable] + public struct DiscordUser + { + public string userId; + public string username; + public string discriminator; + public string avatar; + } + + public enum Reply + { + No = 0, + Yes = 1, + Ignore = 2 + } + + public enum PartyPrivacy + { + Private = 0, + Public = 1 + } + + public static void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId) + { + Callbacks = handlers; + + EventHandlers staticEventHandlers = new EventHandlers(); + staticEventHandlers.readyCallback += DiscordRpc.ReadyCallback; + staticEventHandlers.disconnectedCallback += DiscordRpc.DisconnectedCallback; + staticEventHandlers.errorCallback += DiscordRpc.ErrorCallback; + staticEventHandlers.joinCallback += DiscordRpc.JoinCallback; + staticEventHandlers.spectateCallback += DiscordRpc.SpectateCallback; + staticEventHandlers.requestCallback += DiscordRpc.RequestCallback; + + InitializeInternal(applicationId, ref staticEventHandlers, autoRegister, optionalSteamId); + } + + [DllImport("discord-rpc", EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)] + static extern void InitializeInternal(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId); + + [DllImport("discord-rpc", EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)] + public static extern void Shutdown(); + + [DllImport("discord-rpc", EntryPoint = "Discord_RunCallbacks", CallingConvention = CallingConvention.Cdecl)] + public static extern void RunCallbacks(); + + [DllImport("discord-rpc", EntryPoint = "Discord_UpdatePresence", CallingConvention = CallingConvention.Cdecl)] + private static extern void UpdatePresenceNative(ref RichPresenceStruct presence); + + [DllImport("discord-rpc", EntryPoint = "Discord_ClearPresence", CallingConvention = CallingConvention.Cdecl)] + public static extern void ClearPresence(); + + [DllImport("discord-rpc", EntryPoint = "Discord_Respond", CallingConvention = CallingConvention.Cdecl)] + public static extern void Respond(string userId, Reply reply); + + [DllImport("discord-rpc", EntryPoint = "Discord_UpdateHandlers", CallingConvention = CallingConvention.Cdecl)] + public static extern void UpdateHandlers(ref EventHandlers handlers); + + public static void UpdatePresence(RichPresence presence) + { + var presencestruct = presence.GetStruct(); + UpdatePresenceNative(ref presencestruct); + presence.FreeMem(); + } + + public class RichPresence + { + private RichPresenceStruct _presence; + private readonly List _buffers = new List(10); + + public string state; /* max 128 bytes */ + public string details; /* max 128 bytes */ + public long startTimestamp; + public long endTimestamp; + public string largeImageKey; /* max 32 bytes */ + public string largeImageText; /* max 128 bytes */ + public string smallImageKey; /* max 32 bytes */ + public string smallImageText; /* max 128 bytes */ + public string partyId; /* max 128 bytes */ + public int partySize; + public int partyMax; + public PartyPrivacy partyPrivacy; + public string matchSecret; /* max 128 bytes */ + public string joinSecret; /* max 128 bytes */ + public string spectateSecret; /* max 128 bytes */ + public bool instance; + + ///

+ /// Get the reprensentation of this instance + /// + /// reprensentation of this instance + internal RichPresenceStruct GetStruct() + { + if (_buffers.Count > 0) + { + FreeMem(); + } + + _presence.state = StrToPtr(state); + _presence.details = StrToPtr(details); + _presence.startTimestamp = startTimestamp; + _presence.endTimestamp = endTimestamp; + _presence.largeImageKey = StrToPtr(largeImageKey); + _presence.largeImageText = StrToPtr(largeImageText); + _presence.smallImageKey = StrToPtr(smallImageKey); + _presence.smallImageText = StrToPtr(smallImageText); + _presence.partyId = StrToPtr(partyId); + _presence.partySize = partySize; + _presence.partyMax = partyMax; + _presence.partyPrivacy = (int)partyPrivacy; + _presence.matchSecret = StrToPtr(matchSecret); + _presence.joinSecret = StrToPtr(joinSecret); + _presence.spectateSecret = StrToPtr(spectateSecret); + _presence.instance = instance; + + return _presence; + } + + /// + /// Returns a pointer to a representation of the given string with a size of maxbytes + /// + /// String to convert + /// Pointer to the UTF-8 representation of + private IntPtr StrToPtr(string input) + { + if (string.IsNullOrEmpty(input)) return IntPtr.Zero; + var convbytecnt = Encoding.UTF8.GetByteCount(input); + var buffer = Marshal.AllocHGlobal(convbytecnt + 1); + for (int i = 0; i < convbytecnt + 1; i++) + { + Marshal.WriteByte(buffer, i, 0); + } + _buffers.Add(buffer); + Marshal.Copy(Encoding.UTF8.GetBytes(input), 0, buffer, convbytecnt); + return buffer; + } + + /// + /// Convert string to UTF-8 and add null termination + /// + /// string to convert + /// UTF-8 representation of with added null termination + private static string StrToUtf8NullTerm(string toconv) + { + var str = toconv.Trim(); + var bytes = Encoding.Default.GetBytes(str); + if (bytes.Length > 0 && bytes[bytes.Length - 1] != 0) + { + str += "\0\0"; + } + return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(str)); + } + + /// + /// Free the allocated memory for conversion to + /// + internal void FreeMem() + { + for (var i = _buffers.Count - 1; i >= 0; i--) + { + Marshal.FreeHGlobal(_buffers[i]); + _buffers.RemoveAt(i); + } + } + } +} \ No newline at end of file diff --git a/deps/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs b/deps/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs new file mode 100644 index 0000000..9777453 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/Assets/Editor/BuildHelper.cs @@ -0,0 +1,101 @@ +using UnityEditor; +using System.Diagnostics; +using System.IO; + +[InitializeOnLoad] +public class ScriptBatch +{ + static ScriptBatch() + { + EnsureDLL(); + } + + public static bool FileExists(string filename) + { + return new FileInfo(filename).Exists; + } + + public static bool RunRpcBuildScript() + { + UnityEngine.Debug.Log("Try to run build script"); + + Process proc = new Process(); +#if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX + proc.StartInfo.UseShellExecute = false; + // brew installs cmake in /usr/local/bin, which Unity seems to strip from PATH? + string newPath = proc.StartInfo.EnvironmentVariables["PATH"] + ":/usr/local/bin"; + proc.StartInfo.EnvironmentVariables["PATH"] = newPath; +#endif + proc.StartInfo.FileName = "python"; + proc.StartInfo.Arguments = "build.py unity"; + proc.StartInfo.WorkingDirectory = "../.."; + proc.Start(); + proc.WaitForExit(); + return proc.ExitCode == 0; + } + + public static void EnsureDLL() + { + #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN + string[] dstDirs = { "Assets/Plugins", "Assets/Plugins/x86", "Assets/Plugins/x86_64" }; + string[] dstDlls = { "Assets/Plugins/x86/discord-rpc.dll", "Assets/Plugins/x86_64/discord-rpc.dll" }; + string[] srcDlls = { "../../builds/install/win64-dynamic/bin/discord-rpc.dll", "../../builds/install/win64-dynamic/bin/discord-rpc.dll" }; + #elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX + string[] dstDirs = { "Assets/Plugins" }; + string[] dstDlls = { "Assets/Plugins/discord-rpc.bundle" }; + string[] srcDlls = { "../../builds/install/osx-dynamic/lib/libdiscord-rpc.dylib" }; + #else + string[] dstDirs = { "Assets/Plugins", "Assets/Plugins/x86", "Assets/Plugins/x86_64" }; + string[] dstDlls = { "Assets/Plugins/discord-rpc.so" }; + string[] srcDlls = { "../../builds/install/linux-dynamic/lib/libdiscord-rpc.so" }; + #endif + + Debug.Assert(dstDlls.Length == srcDlls.Length); + + bool exists = true; + foreach (string fname in dstDlls) + { + if (!FileExists(fname)) + { + exists = false; + break; + } + } + + if (exists) + { + return; + } + + exists = true; + foreach (string fname in srcDlls) + { + if (!FileExists(fname)) + { + exists = false; + break; + } + } + + if (!exists) + { + if (!RunRpcBuildScript()) + { + UnityEngine.Debug.LogError("Build failed"); + return; + } + } + + // make sure the dirs exist + foreach (string dirname in dstDirs) + { + Directory.CreateDirectory(dirname); + } + + // Copy dlls + for (int i = 0; i < dstDlls.Length; ++i) + { + FileUtil.CopyFileOrDirectory(srcDlls[i], dstDlls[i]); + } + } +} \ No newline at end of file diff --git a/deps/discord-rpc/examples/button-clicker/Assets/main.unity b/deps/discord-rpc/examples/button-clicker/Assets/main.unity new file mode 100644 index 0000000..c5074d5 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/Assets/main.unity @@ -0,0 +1,1278 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 8 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 1 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_TemporalCoherenceThreshold: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 9 + m_Resolution: 2 + m_BakeResolution: 40 + m_TextureWidth: 1024 + m_TextureHeight: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 2 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFiltering: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousColorSigma: 1 + m_PVRFilteringAtrousNormalSigma: 1 + m_PVRFilteringAtrousPositionSigma: 1 + m_LightingDataAsset: {fileID: 0} + m_UseShadowmask: 1 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &134146651 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 134146656} + - component: {fileID: 134146655} + - component: {fileID: 134146654} + - component: {fileID: 134146653} + - component: {fileID: 134146652} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &134146652 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 134146651} + m_Enabled: 1 +--- !u!124 &134146653 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 134146651} + m_Enabled: 1 +--- !u!92 &134146654 +Behaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 134146651} + m_Enabled: 1 +--- !u!20 &134146655 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 134146651} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 60 + orthographic: 1 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 1 + m_AllowMSAA: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 + m_StereoMirrorMode: 0 +--- !u!4 &134146656 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 134146651} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -10} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &359174702 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 359174703} + - component: {fileID: 359174705} + - component: {fileID: 359174704} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &359174703 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 359174702} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1032248339} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &359174704 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 359174702} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Button +--- !u!222 &359174705 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 359174702} +--- !u!1 &520806049 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 520806050} + - component: {fileID: 520806052} + - component: {fileID: 520806051} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &520806050 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 520806049} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 806911717} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &520806051 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 520806049} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Yes +--- !u!222 &520806052 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 520806049} +--- !u!1 &657463235 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 657463238} + - component: {fileID: 657463237} + - component: {fileID: 657463236} + m_Layer: 5 + m_Name: IsConnectedLabel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &657463236 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 657463235} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.89518255, g: 0.9338235, b: 0.23345588, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 24 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 2 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: Discord Disconnected +--- !u!222 &657463237 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 657463235} +--- !u!224 &657463238 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 657463235} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1766020814} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 0, y: 1} + m_AnchoredPosition: {x: 16, y: -19.00003} + m_SizeDelta: {x: 239.20001, y: 37.799988} + m_Pivot: {x: 0, y: 1} +--- !u!1 &806911716 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 806911717} + - component: {fileID: 806911720} + - component: {fileID: 806911719} + - component: {fileID: 806911718} + m_Layer: 5 + m_Name: ButtonRespondYes + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &806911717 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 806911716} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 520806050} + m_Father: {fileID: 1766020814} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -129.1, y: -116.3} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &806911718 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 806911716} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 0 + m_TargetGraphic: {fileID: 806911719} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1929635629} + m_MethodName: RequestRespondYes + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &806911719 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 806911716} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &806911720 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 806911716} +--- !u!1 &1032248338 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1032248339} + - component: {fileID: 1032248342} + - component: {fileID: 1032248341} + - component: {fileID: 1032248340} + m_Layer: 5 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1032248339 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1032248338} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 359174703} + m_Father: {fileID: 1766020814} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1032248340 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1032248338} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 1032248341} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1929635629} + m_MethodName: OnClick + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1032248341 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1032248338} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &1032248342 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1032248338} +--- !u!1 &1238162986 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1238162987} + - component: {fileID: 1238162989} + - component: {fileID: 1238162988} + m_Layer: 5 + m_Name: JoinRequestInfo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1238162987 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1238162986} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1766020814} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -0.0000085831, y: -66.9} + m_SizeDelta: {x: 323.38, y: 55.29} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1238162988 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1238162986} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 0.88965523, b: 0, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 1 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: No requests yet +--- !u!222 &1238162989 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1238162986} +--- !u!1 &1470895131 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1470895134} + - component: {fileID: 1470895133} + - component: {fileID: 1470895132} + m_Layer: 0 + m_Name: EventSystem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1470895132 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1470895131} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalAxis: Horizontal + m_VerticalAxis: Vertical + m_SubmitButton: Submit + m_CancelButton: Cancel + m_InputActionsPerSecond: 10 + m_RepeatDelay: 0.5 + m_ForceModuleActive: 0 +--- !u!114 &1470895133 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1470895131} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FirstSelected: {fileID: 0} + m_sendNavigationEvents: 1 + m_DragThreshold: 5 +--- !u!4 &1470895134 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1470895131} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1766020810 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1766020814} + - component: {fileID: 1766020813} + - component: {fileID: 1766020812} + - component: {fileID: 1766020811} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1766020811 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1766020810} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &1766020812 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1766020810} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!223 &1766020813 +Canvas: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1766020810} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &1766020814 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1766020810} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_Children: + - {fileID: 1032248339} + - {fileID: 657463238} + - {fileID: 806911717} + - {fileID: 1858885002} + - {fileID: 1238162987} + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!1 &1858885001 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1858885002} + - component: {fileID: 1858885005} + - component: {fileID: 1858885004} + - component: {fileID: 1858885003} + m_Layer: 5 + m_Name: ButtonRespondNo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1858885002 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1858885001} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1958982062} + m_Father: {fileID: 1766020814} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 128.7, y: -116.3} + m_SizeDelta: {x: 160, y: 30} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1858885003 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1858885001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1392445389, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 3 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0.1 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_DisabledTrigger: Disabled + m_Interactable: 0 + m_TargetGraphic: {fileID: 1858885004} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1929635629} + m_MethodName: RequestRespondNo + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0, + Culture=neutral, PublicKeyToken=null +--- !u!114 &1858885004 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1858885001} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -765806418, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 +--- !u!222 &1858885005 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1858885001} +--- !u!1 &1929635628 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1929635630} + - component: {fileID: 1929635629} + m_Layer: 0 + m_Name: Discord + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1929635629 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1929635628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 27f0a5f59ffffa84c86547736e2e730a, type: 3} + m_Name: + m_EditorClassIdentifier: + presence: + state: Button clicking + details: Best game ever + startTimestamp: 0 + endTimestamp: 0 + largeImageKey: stable-large + largeImageText: + smallImageKey: canary-small + smallImageText: + partyId: abcdefg + partySize: 1 + partyMax: 10 + matchSecret: match_secret + joinSecret: join_secret + spectateSecret: spectate_secret + instance: 1 + applicationId: 345229890980937739 + optionalSteamId: + callbackCalls: 0 + clickCounter: 0 + joinRequest: + userId: + username: + discriminator: + avatar: + onConnect: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 657463236} + m_MethodName: set_text + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Discord Connected + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + onDisconnect: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 657463236} + m_MethodName: set_text + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Discord Disconnected + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + hasResponded: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1238162988} + m_MethodName: set_text + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: No requests yet + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 806911718} + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 1858885003} + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + onJoin: + m_PersistentCalls: + m_Calls: [] + m_TypeName: DiscordJoinEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + onSpectate: + m_PersistentCalls: + m_Calls: [] + m_TypeName: DiscordJoinEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null + onJoinRequest: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1238162988} + m_MethodName: set_text + m_Mode: 5 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: Someone asked to join! + m_BoolArgument: 0 + m_CallState: 2 + - m_Target: {fileID: 806911718} + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + - m_Target: {fileID: 1858885003} + m_MethodName: set_interactable + m_Mode: 6 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 1 + m_CallState: 2 + m_TypeName: DiscordJoinRequestEvent, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null +--- !u!4 &1929635630 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1929635628} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1958982061 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1958982062} + - component: {fileID: 1958982064} + - component: {fileID: 1958982063} + m_Layer: 5 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1958982062 +RectTransform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1958982061} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1858885002} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1958982063 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1958982061} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 14 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 10 + m_MaxSize: 40 + m_Alignment: 4 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: No +--- !u!222 &1958982064 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1958982061} diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/AudioManager.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..da61125 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/AudioManager.asset @@ -0,0 +1,17 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 0 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/ClusterInputManager.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/DynamicsManager.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..0be3d78 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,20 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 3 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_EnablePCM: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 1 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorBuildSettings.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..d8fda84 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,10 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: + - enabled: 1 + path: Assets/main.unity + guid: 3b03d21bb25fa494e8694cd6e4b6d769 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorSettings.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..c0c814f --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/EditorSettings.asset @@ -0,0 +1,16 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_DefaultBehaviorMode: 1 + m_SpritePackerMode: 4 + m_SpritePackerPaddingPower: 1 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd + m_ProjectGenerationRootNamespace: + m_UserGeneratedProjectSuffix: + m_CollabEditorSettings: + inProgressEnabled: 1 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/GraphicsSettings.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..74d7b53 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,61 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 12 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/InputManager.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..17c8f53 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/NavMeshAreas.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000..6dd520f --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,89 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + m_SettingNames: + - Humanoid diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/NetworkManager.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/NetworkManager.asset new file mode 100644 index 0000000..5dc6a83 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/NetworkManager.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!149 &1 +NetworkManager: + m_ObjectHideFlags: 0 + m_DebugLevel: 0 + m_Sendrate: 15 + m_AssetToPrefab: {} diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/Physics2DSettings.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..132ee6b --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,37 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 3 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_ChangeStopsCallbacks: 0 + m_CallbacksOnDisable: 1 + m_AutoSyncTransforms: 1 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectSettings.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..f60fe83 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,610 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + productGUID: 5eccc60d3e382a346a65f512d6b81b84 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: Discord Inc. + productName: button-clicker + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1024 + defaultScreenHeight: 768 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 0 + m_MTRendering: 1 + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + tizenShowActivityIndicatorOnLoading: -1 + iosAppInBackgroundBehavior: 0 + displayResolutionDialog: 1 + iosAllowHTTPDownload: 1 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + disableDepthAndStencilBuffers: 0 + androidBlitType: 0 + defaultIsFullScreen: 1 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 0 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + submitAnalytics: 1 + usePlayerLog: 1 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 0 + graphicsJobs: 0 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + graphicsJobMode: 0 + macFullscreenMode: 2 + d3d9FullscreenMode: 1 + d3d11FullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + n3dsDisableStereoscopicView: 0 + n3dsEnableSharedListOpt: 1 + n3dsEnableVSync: 0 + ignoreAlphaClear: 0 + xboxOneResolution: 0 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOnePresentImmediateThreshold: 0 + videoMemoryForVertexBuffers: 0 + psp2PowerMode: 0 + psp2AcquireBGM: 1 + wiiUTVResolution: 0 + wiiUGamePadMSAA: 1 + wiiUSupportsNunchuk: 0 + wiiUSupportsClassicController: 0 + wiiUSupportsBalanceBoard: 0 + wiiUSupportsMotionPlus: 0 + wiiUSupportsProController: 0 + wiiUAllowScreenCapture: 1 + wiiUControllerCount: 0 + m_SupportedAspectRatios: + 4:3: 1 + 5:4: 1 + 16:10: 1 + 16:9: 1 + Others: 1 + bundleVersion: 1.0 + preloadedAssets: [] + metroInputSource: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 0 + xboxOneEnable7thCore: 0 + vrSettings: + cardboard: + depthFormat: 0 + enableTransitionView: 0 + daydream: + depthFormat: 0 + useSustainedPerformanceMode: 0 + enableVideoLayer: 0 + useProtectedVideoMemory: 0 + hololens: + depthFormat: 1 + protectGraphicsMemory: 0 + useHDRDisplay: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 0 + resolutionScalingMode: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: {} + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 16 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 0 + VertexChannelCompressionMask: + serializedVersion: 2 + m_Bits: 238 + iPhoneSdkVersion: 988 + iOSTargetOSVersionString: 7.0 + tvOSSdkVersion: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 9.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + iPhoneSplashScreen: {fileID: 0} + iPhoneHighResSplashScreen: {fileID: 0} + iPhoneTallHighResSplashScreen: {fileID: 0} + iPhone47inSplashScreen: {fileID: 0} + iPhone55inPortraitSplashScreen: {fileID: 0} + iPhone55inLandscapeSplashScreen: {fileID: 0} + iPadPortraitSplashScreen: {fileID: 0} + iPadHighResPortraitSplashScreen: {fileID: 0} + iPadLandscapeSplashScreen: {fileID: 0} + iPadHighResLandscapeSplashScreen: {fileID: 0} + appleTVSplashScreen: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSLargeIconLayers: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageWideLayers: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + iOSRenderExtraFrameOnPause: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + appleEnableAutomaticSigning: 0 + AndroidTargetDevice: 0 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidTVCompatibility: 1 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + resolutionDialogBanner: {fileID: 0} + m_BuildTargetIcons: [] + m_BuildTargetBatching: [] + m_BuildTargetGraphicsAPIs: [] + m_BuildTargetVRSettings: [] + m_BuildTargetEnableVuforiaSettings: [] + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + wiiUTitleID: 0005000011000000 + wiiUGroupID: 00010000 + wiiUCommonSaveSize: 4096 + wiiUAccountSaveSize: 2048 + wiiUOlvAccessKey: 0 + wiiUTinCode: 0 + wiiUJoinGameId: 0 + wiiUJoinGameModeMask: 0000000000000000 + wiiUCommonBossSize: 0 + wiiUAccountBossSize: 0 + wiiUAddOnUniqueIDs: [] + wiiUMainThreadStackSize: 3072 + wiiULoaderThreadStackSize: 1024 + wiiUSystemHeapSize: 128 + wiiUTVStartupScreen: {fileID: 0} + wiiUGamePadStartupScreen: {fileID: 0} + wiiUDrcBufferDisabled: 0 + wiiUProfilerLibPath: + playModeTestRunnerEnabled: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: 0x01004b9000490000 + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchTouchScreenUsage: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: 4 + switchCardSpecClock: 25 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchLocalCommunicationIds_0: 0x01004b9000490000 + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchDataLossConfirmation: 0 + switchSupportedNpadStyles: 3 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchPlayerConnectionEnabled: 1 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 120 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 1 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 0 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + monoEnv: + psp2Splashimage: {fileID: 0} + psp2NPTrophyPackPath: + psp2NPSupportGBMorGJP: 0 + psp2NPAgeRating: 12 + psp2NPTitleDatPath: + psp2NPCommsID: + psp2NPCommunicationsID: + psp2NPCommsPassphrase: + psp2NPCommsSig: + psp2ParamSfxPath: + psp2ManualPath: + psp2LiveAreaGatePath: + psp2LiveAreaBackroundPath: + psp2LiveAreaPath: + psp2LiveAreaTrialPath: + psp2PatchChangeInfoPath: + psp2PatchOriginalPackage: + psp2PackagePassword: F69AzBlax3CF3EDNhm3soLBPh71Yexui + psp2KeystoneFile: + psp2MemoryExpansionMode: 0 + psp2DRMType: 0 + psp2StorageType: 0 + psp2MediaCapacity: 0 + psp2DLCConfigPath: + psp2ThumbnailPath: + psp2BackgroundPath: + psp2SoundPath: + psp2TrophyCommId: + psp2TrophyPackagePath: + psp2PackagedResourcesPath: + psp2SaveDataQuota: 10240 + psp2ParentalLevel: 1 + psp2ShortTitle: Not Set + psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF + psp2Category: 0 + psp2MasterVersion: 01.00 + psp2AppVersion: 01.00 + psp2TVBootMode: 0 + psp2EnterButtonAssignment: 2 + psp2TVDisableEmu: 0 + psp2AllowTwitterDialog: 1 + psp2Upgradable: 0 + psp2HealthWarning: 0 + psp2UseLibLocation: 0 + psp2InfoBarOnStartup: 0 + psp2InfoBarColor: 0 + psp2ScriptOptimizationLevel: 0 + psmSplashimage: {fileID: 0} + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + spritePackerPolicy: + webGLMemorySize: 256 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLDataCaching: 0 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLUseWasm: 0 + webGLCompressionFormat: 1 + scriptingDefineSymbols: {} + platformArchitecture: {} + scriptingBackend: {} + incrementalIl2cppBuild: {} + additionalIl2CppArgs: + scriptingRuntimeVersion: 0 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: button-clicker + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: button-clicker + wsaImages: {} + metroTileShortName: + metroCommandLineArgsFile: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, + a: 1} + metroSplashScreenUseBackgroundColor: 0 + platformCapabilities: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + metroCompilationOverrides: 1 + tizenProductDescription: + tizenProductURL: + tizenSigningProfileName: + tizenGPSPermissions: 0 + tizenMicrophonePermissions: 0 + tizenDeploymentTarget: + tizenDeploymentTargetType: -1 + tizenMinOSVersion: 1 + n3dsUseExtSaveData: 0 + n3dsCompressStaticMem: 1 + n3dsExtSaveDataNumber: 0x12345 + n3dsStackSize: 131072 + n3dsTargetPlatform: 2 + n3dsRegion: 7 + n3dsMediaSize: 0 + n3dsLogoStyle: 3 + n3dsTitle: GameName + n3dsProductCode: + n3dsApplicationId: 0xFF3FF + stvDeviceAddress: + stvProductDescription: + stvProductAuthor: + stvProductAuthorEmail: + stvProductLink: + stvProductCategory: 0 + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnableGPUVariability: 0 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + xboxOneScriptCompiler: 0 + vrEditorSettings: + daydream: + daydreamIconForeground: {fileID: 0} + daydreamIconBackground: {fileID: 0} + cloudServicesEnabled: {} + facebookSdkVersion: 7.9.4 + apiCompatibilityLevel: 2 + cloudProjectId: + projectName: + organizationId: + cloudEnabled: 0 + enableNativePlatformBackendsForNewInputSystem: 0 + disableOldInputManagerSupport: 0 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectVersion.txt b/deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..7a6fffb --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/ProjectVersion.txt @@ -0,0 +1 @@ +m_EditorVersion: 2017.2.0f3 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/QualitySettings.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..86c047f --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/QualitySettings.asset @@ -0,0 +1,193 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 5 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 4 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PSM: 5 + PSP2: 2 + Samsung TV: 2 + Standalone: 5 + Tizen: 2 + Web: 5 + WebGL: 3 + WiiU: 5 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/TagManager.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..1c92a78 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/TimeManager.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..558a017 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.33333334 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/deps/discord-rpc/examples/button-clicker/ProjectSettings/UnityConnectSettings.asset b/deps/discord-rpc/examples/button-clicker/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..1cc5485 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + m_Enabled: 0 + m_TestMode: 0 + m_TestEventUrl: + m_TestConfigUrl: + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes + m_Enabled: 0 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_TestEventUrl: + m_TestConfigUrl: + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_EnabledPlatforms: 4294967295 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/deps/discord-rpc/examples/button-clicker/UnityPackageManager/manifest.json b/deps/discord-rpc/examples/button-clicker/UnityPackageManager/manifest.json new file mode 100644 index 0000000..526aca6 --- /dev/null +++ b/deps/discord-rpc/examples/button-clicker/UnityPackageManager/manifest.json @@ -0,0 +1,4 @@ +{ + "dependencies": { + } +} diff --git a/deps/discord-rpc/examples/send-presence/CMakeLists.txt b/deps/discord-rpc/examples/send-presence/CMakeLists.txt new file mode 100644 index 0000000..8a67d47 --- /dev/null +++ b/deps/discord-rpc/examples/send-presence/CMakeLists.txt @@ -0,0 +1,21 @@ +include_directories(${PROJECT_SOURCE_DIR}/include) +add_executable( + send-presence + MACOSX_BUNDLE + send-presence.c +) +set_target_properties(send-presence PROPERTIES + MACOSX_BUNDLE_BUNDLE_NAME "Send Presence" + MACOSX_BUNDLE_GUI_IDENTIFIER "com.discordapp.examples.send-presence" +) +target_link_libraries(send-presence discord-rpc) + +install( + TARGETS send-presence + RUNTIME + DESTINATION "bin" + CONFIGURATIONS Release + BUNDLE + DESTINATION "bin" + CONFIGURATIONS Release +) \ No newline at end of file diff --git a/deps/discord-rpc/examples/send-presence/send-presence.c b/deps/discord-rpc/examples/send-presence/send-presence.c new file mode 100644 index 0000000..1b651f2 --- /dev/null +++ b/deps/discord-rpc/examples/send-presence/send-presence.c @@ -0,0 +1,206 @@ +/* + This is a simple example in C of using the rich presence API asynchronously. +*/ + +#define _CRT_SECURE_NO_WARNINGS /* thanks Microsoft */ + +#include +#include +#include +#include + +#include "discord_rpc.h" + +static const char* APPLICATION_ID = "345229890980937739"; +static int FrustrationLevel = 0; +static int64_t StartTime; +static int SendPresence = 1; + +static int prompt(char* line, size_t size) +{ + int res; + char* nl; + printf("\n> "); + fflush(stdout); + res = fgets(line, (int)size, stdin) ? 1 : 0; + line[size - 1] = 0; + nl = strchr(line, '\n'); + if (nl) { + *nl = 0; + } + return res; +} + +static void updateDiscordPresence() +{ + if (SendPresence) { + char buffer[256]; + DiscordRichPresence discordPresence; + memset(&discordPresence, 0, sizeof(discordPresence)); + discordPresence.state = "West of House"; + sprintf(buffer, "Frustration level: %d", FrustrationLevel); + discordPresence.details = buffer; + discordPresence.startTimestamp = StartTime; + discordPresence.endTimestamp = time(0) + 5 * 60; + discordPresence.largeImageKey = "canary-large"; + discordPresence.smallImageKey = "ptb-small"; + discordPresence.partyId = "party1234"; + discordPresence.partySize = 1; + discordPresence.partyMax = 6; + discordPresence.partyPrivacy = DISCORD_PARTY_PUBLIC; + discordPresence.matchSecret = "xyzzy"; + discordPresence.joinSecret = "join"; + discordPresence.spectateSecret = "look"; + discordPresence.instance = 0; + Discord_UpdatePresence(&discordPresence); + } + else { + Discord_ClearPresence(); + } +} + +static void handleDiscordReady(const DiscordUser* connectedUser) +{ + printf("\nDiscord: connected to user %s#%s - %s\n", + connectedUser->username, + connectedUser->discriminator, + connectedUser->userId); +} + +static void handleDiscordDisconnected(int errcode, const char* message) +{ + printf("\nDiscord: disconnected (%d: %s)\n", errcode, message); +} + +static void handleDiscordError(int errcode, const char* message) +{ + printf("\nDiscord: error (%d: %s)\n", errcode, message); +} + +static void handleDiscordJoin(const char* secret) +{ + printf("\nDiscord: join (%s)\n", secret); +} + +static void handleDiscordSpectate(const char* secret) +{ + printf("\nDiscord: spectate (%s)\n", secret); +} + +static void handleDiscordJoinRequest(const DiscordUser* request) +{ + int response = -1; + char yn[4]; + printf("\nDiscord: join request from %s#%s - %s\n", + request->username, + request->discriminator, + request->userId); + do { + printf("Accept? (y/n)"); + if (!prompt(yn, sizeof(yn))) { + break; + } + + if (!yn[0]) { + continue; + } + + if (yn[0] == 'y') { + response = DISCORD_REPLY_YES; + break; + } + + if (yn[0] == 'n') { + response = DISCORD_REPLY_NO; + break; + } + } while (1); + if (response != -1) { + Discord_Respond(request->userId, response); + } +} + +static void discordInit() +{ + DiscordEventHandlers handlers; + memset(&handlers, 0, sizeof(handlers)); + handlers.ready = handleDiscordReady; + handlers.disconnected = handleDiscordDisconnected; + handlers.errored = handleDiscordError; + handlers.joinGame = handleDiscordJoin; + handlers.spectateGame = handleDiscordSpectate; + handlers.joinRequest = handleDiscordJoinRequest; + Discord_Initialize(APPLICATION_ID, &handlers, 1, NULL); +} + +static void gameLoop() +{ + char line[512]; + char* space; + + StartTime = time(0); + + printf("You are standing in an open field west of a white house.\n"); + while (prompt(line, sizeof(line))) { + if (line[0]) { + if (line[0] == 'q') { + break; + } + + if (line[0] == 't') { + printf("Shutting off Discord.\n"); + Discord_Shutdown(); + continue; + } + + if (line[0] == 'c') { + if (SendPresence) { + printf("Clearing presence information.\n"); + SendPresence = 0; + } + else { + printf("Restoring presence information.\n"); + SendPresence = 1; + } + updateDiscordPresence(); + continue; + } + + if (line[0] == 'y') { + printf("Reinit Discord.\n"); + discordInit(); + continue; + } + + if (time(NULL) & 1) { + printf("I don't understand that.\n"); + } + else { + space = strchr(line, ' '); + if (space) { + *space = 0; + } + printf("I don't know the word \"%s\".\n", line); + } + + ++FrustrationLevel; + + updateDiscordPresence(); + } + +#ifdef DISCORD_DISABLE_IO_THREAD + Discord_UpdateConnection(); +#endif + Discord_RunCallbacks(); + } +} + +int main(int argc, char* argv[]) +{ + discordInit(); + + gameLoop(); + + Discord_Shutdown(); + return 0; +} diff --git a/deps/discord-rpc/examples/unrealstatus/.gitignore b/deps/discord-rpc/examples/unrealstatus/.gitignore new file mode 100644 index 0000000..bd472d5 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/.gitignore @@ -0,0 +1,78 @@ +# Visual Studio 2015 user specific files +.vs/ + +# Visual Studio 2015 database file +*.VC.db + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +*.ipa + +# These project files can be generated by the engine +*.xcodeproj +*.xcworkspace +*.sln +*.suo +*.opensdf +*.sdf +*.VC.db +*.VC.opendb + +# Precompiled Assets +SourceArt/**/*.png +SourceArt/**/*.tga + +# Binary Files +Binaries/ + +# Builds +Build/* + +# Whitelist PakBlacklist-.txt files +!Build/*/ +Build/*/** +!Build/*/PakBlacklist*.txt + +# Don't ignore icon files in Build +!Build/**/*.ico + +# Built data for maps +*_BuiltData.uasset + +# Configuration files generated by the Editor +Saved/* + +# Compiled source files for the engine to use +Intermediate/ + +# Cache files for the editor to use +DerivedDataCache/ + +# Library headers must be copied automatically by the build script (build.py unreal) +Plugins/DiscordRpc/Source/ThirdParty/DiscordRpcLibrary/Include diff --git a/deps/discord-rpc/examples/unrealstatus/Config/DefaultEditor.ini b/deps/discord-rpc/examples/unrealstatus/Config/DefaultEditor.ini new file mode 100644 index 0000000..e69de29 diff --git a/deps/discord-rpc/examples/unrealstatus/Config/DefaultEngine.ini b/deps/discord-rpc/examples/unrealstatus/Config/DefaultEngine.ini new file mode 100644 index 0000000..84c38f3 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Config/DefaultEngine.ini @@ -0,0 +1,54 @@ +[URL] + +[/Script/HardwareTargeting.HardwareTargetingSettings] +TargetedHardwareClass=Desktop +AppliedTargetedHardwareClass=Desktop +DefaultGraphicsPerformance=Maximum +AppliedDefaultGraphicsPerformance=Maximum + +[/Script/Engine.EndUserSettings] +bSendAnonymousUsageDataToEpic=False + +[/Script/Engine.PhysicsSettings] +DefaultGravityZ=-980.000000 +DefaultTerminalVelocity=4000.000000 +DefaultFluidFriction=0.300000 +SimulateScratchMemorySize=262144 +RagdollAggregateThreshold=4 +TriangleMeshTriangleMinAreaThreshold=5.000000 +bEnableAsyncScene=False +bEnableShapeSharing=False +bEnablePCM=False +bEnableStabilization=False +bWarnMissingLocks=True +bEnable2DPhysics=False +LockedAxis=Invalid +DefaultDegreesOfFreedom=Full3D +BounceThresholdVelocity=200.000000 +FrictionCombineMode=Average +RestitutionCombineMode=Average +MaxAngularVelocity=3600.000000 +MaxDepenetrationVelocity=0.000000 +ContactOffsetMultiplier=0.010000 +MinContactOffset=0.000100 +MaxContactOffset=1.000000 +bSimulateSkeletalMeshOnDedicatedServer=True +DefaultShapeComplexity=CTF_UseSimpleAndComplex +bDefaultHasComplexCollision=True +bSuppressFaceRemapTable=False +bSupportUVFromHitResults=False +bDisableActiveActors=False +bDisableCCD=False +MaxPhysicsDeltaTime=0.033333 +bSubstepping=False +bSubsteppingAsync=False +MaxSubstepDeltaTime=0.016667 +MaxSubsteps=6 +SyncSceneSmoothingFactor=0.000000 +AsyncSceneSmoothingFactor=0.990000 +InitialAverageFrameRate=0.016667 + +[/Script/EngineSettings.GameMapsSettings] +EditorStartupMap=/Game/ShowTheUILevel.ShowTheUILevel +GameDefaultMap=/Game/ShowTheUILevel.ShowTheUILevel + diff --git a/deps/discord-rpc/examples/unrealstatus/Config/DefaultGame.ini b/deps/discord-rpc/examples/unrealstatus/Config/DefaultGame.ini new file mode 100644 index 0000000..7b5e2dc --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Config/DefaultGame.ini @@ -0,0 +1,7 @@ +[/Script/EngineSettings.GeneralProjectSettings] +ProjectID=E5977A24492699DF20B8ADBF736AF6C6 +ProjectName=Discord RPC Example +CompanyName=Discord Inc. +Homepage="https://discordapp.com/" +CopyrightNotice= + diff --git a/deps/discord-rpc/examples/unrealstatus/Content/MainScreenBP.uasset b/deps/discord-rpc/examples/unrealstatus/Content/MainScreenBP.uasset new file mode 100644 index 0000000000000000000000000000000000000000..e903b53830516d653b92961bd231de061b13a941 GIT binary patch literal 50332 zcmeHw34j#E)qfA7A_$@aqFlQOA}Yt;2OjLq9xUg=vZx>|v%9_Q=QxwsF@s^-Q#e;Z8qsAoOqGB`{;~CK?|M#n^H{H|IJu`b?zWDzddaC=qs`u(0 z_3Bl1@65K9$K0@c&z?Q=_t7+07fl=}K5e?|gOA;7zUuLM*7}l%%10keun)5Ta#zo3 z7Y*66{Kd`dC;pIs0Kwi~q-pz7IW-v2spzWxkvv5Wf^BFoXcwp^WpWP&09C`O7gIaq$gty!J^6<4@AS9*8oQ0AtDm3w!~6Oj(03 z5)8ThQN1PP3q)q<;b1gWuZPD}N4$XsZ>V94w>}gMYil2xaxeNero!8-kD2221*+>q zx*l*>Y4;93;QPaXB8aagGA2f>BIIpp(msCUtWr`*4DAVq^qOgPr|b0*?c2&xCmv+N z$xdmj#-Cq#hzVTn_eONI({jCMEh!(5wSQYvlpyvh%IQ0Wz4{-A!Yc zbVEA<3Tyvt@Yjhdp^&$=GSHwe(T)mjt?h*>09A#8EqW-@s#V_gz7HbSmH7R^#ieA_ zh%Xq>_I%#!?*@3L-rNEiwcOsf?*xrHk2g@ZNDoz!q9a<}!|#TAnxHd%^=D|07B`jk z6~JIK1aU{}>il|@FA&fhw1uOGPwtn1oaGDqsE#&$*zw0h33bqu7m&@v7S+N?b!AIh z$nJVWWuR0KlZy0^cGd4|r(qPheSrpFU_n?L-tgsa(RWg)9twE<)Klu^8MC&GfNkn3 z!!f#jSM6Rl9I(my0&jh5g-!%X&IXU)8xB{7OQI1{F!dqgTcm4|>!aQQM&+rx-Y_#* z6%8%WtIyE=GxWx=cG(@LjYH34KBo04%IP`O4Dke;TWFjHBGB~$Vy617?W;eK4c*4t zRz!Ub+Kc-iQ3LOdL91KC5xseq9ty)w=R^)THm=dk))rkm@Zc-oITeip4P}cWwYBbO zBoYkNW{)kZos>N_*r3Vs zfytO+a6+WB`yO>*|2XUvJ>rFzmjxoBR_*1hTUH2ftJeLEo*>zH3Ax~VXWcD$3rV%( zKe&EoI2{U465hx`u*r$tuYj9XXqqqV3wC+kM{kG z{XT~8klQcvhO4{*-LG})dcqOC<6(l)U7o&&!yi3l+XX@D@V}O?c}iB4fa+iGh$I!l+9emg?S-mi zBv|yR6eqO_uV*L}-VjYxnKgxd>)g2x-pV+rP?zR#=~E zmXQHOYhC*0I>^M>X^SZ;NF!COe{u9c6N

I+kVY!z~s{Nl&%2z=a}>j>m87M^}2 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 z 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 literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/examples/unrealstatus/Content/MouseGameModeBP.uasset b/deps/discord-rpc/examples/unrealstatus/Content/MouseGameModeBP.uasset new file mode 100644 index 0000000000000000000000000000000000000000..410af19a9c5524ea0e4e85e1278aee96580ede78 GIT binary patch literal 17950 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 T-su7EEem?_lHN`K8RmZgWf#IR literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/examples/unrealstatus/Content/MousePlayerControllerBP.uasset b/deps/discord-rpc/examples/unrealstatus/Content/MousePlayerControllerBP.uasset new file mode 100644 index 0000000000000000000000000000000000000000..0aaf50ba76c5e797c1dc13c21ac4f5fb024152b7 GIT binary patch literal 16981 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�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

Addition and Subtraction

+
+
+ +

Multiplication

+
+
+ +

Squaring

+
+
+ +

Exptmod

+
+
+ +

Modular Inverse

+
+
+ + + diff --git a/deps/libtommath/logs/graphs.dem b/deps/libtommath/logs/graphs.dem new file mode 100644 index 0000000..fc8ef1b --- /dev/null +++ b/deps/libtommath/logs/graphs.dem @@ -0,0 +1,16 @@ +set terminal png +set ylabel "Cycles per Operation" +set xlabel "Operand size (bits)" + +set output "addsub.png" +plot 'add.log' smooth bezier title "Addition", 'sub.log' smooth bezier title "Subtraction" + +set output "mult.png" +plot 'sqr.log' smooth bezier title "Squaring (without Karatsuba)", 'sqr_kara.log' smooth bezier title "Squaring (Karatsuba)", 'mult.log' smooth bezier title "Multiplication (without Karatsuba)", 'mult_kara.log' smooth bezier title "Multiplication (Karatsuba)" + +set output "expt.png" +plot 'expt.log' smooth bezier title "Exptmod (Montgomery)", 'expt_dr.log' smooth bezier title "Exptmod (Diminished Radix)", 'expt_2k.log' smooth bezier title "Exptmod (2k Reduction)" + +set output "invmod.png" +plot 'invmod.log' smooth bezier title "Modular Inverse" + diff --git a/deps/libtommath/logs/index.html b/deps/libtommath/logs/index.html new file mode 100644 index 0000000..8c1ed9d --- /dev/null +++ b/deps/libtommath/logs/index.html @@ -0,0 +1,24 @@ + + +LibTomMath Log Plots + + + +

Addition and Subtraction

+
+
+ +

Multipliers

+
+
+ +

Exptmod

+
+
+ +

Modular Inverse

+
+
+ + + diff --git a/deps/libtommath/makefile b/deps/libtommath/makefile new file mode 100644 index 0000000..25eda9c --- /dev/null +++ b/deps/libtommath/makefile @@ -0,0 +1,207 @@ +#Makefile for GCC +# +#Tom St Denis + +ifeq ($V,1) +silent= +else +silent=@ +endif + +#default files to install +ifndef LIBNAME + LIBNAME=libtommath.a +endif + +coverage: LIBNAME:=-Wl,--whole-archive $(LIBNAME) -Wl,--no-whole-archive + +include makefile_include.mk + +%.o: %.c $(HEADERS) +ifneq ($V,1) + @echo " * ${CC} $@" +endif + ${silent} ${CC} -c ${LTM_CFLAGS} $< -o $@ + +LCOV_ARGS=--directory . + +#START_INS +OBJECTS=mp_2expt.o mp_abs.o mp_add.o mp_add_d.o mp_addmod.o mp_and.o mp_clamp.o mp_clear.o mp_clear_multi.o \ +mp_cmp.o mp_cmp_d.o mp_cmp_mag.o mp_cnt_lsb.o mp_complement.o mp_copy.o mp_count_bits.o mp_cutoffs.o \ +mp_div.o mp_div_2.o mp_div_2d.o mp_div_d.o mp_dr_is_modulus.o mp_dr_reduce.o mp_dr_setup.o \ +mp_error_to_string.o mp_exch.o mp_expt_n.o mp_exptmod.o mp_exteuclid.o mp_fread.o mp_from_sbin.o \ +mp_from_ubin.o mp_fwrite.o mp_gcd.o mp_get_double.o mp_get_i32.o mp_get_i64.o mp_get_l.o mp_get_mag_u32.o \ +mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp_init_i32.o mp_init_i64.o \ +mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \ +mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \ +mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \ +mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \ +mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \ +mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \ +mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \ +mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o \ +mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ +mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ +mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ +mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ +s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ +s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ +s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ +s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ +s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ +s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o + +#END_INS + +$(LIBNAME): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + +#make a profiled library (takes a while!!!) +# +# This will build the library with profile generation +# then run the test demo and rebuild the library. +# +# So far I've seen improvements in the MP math +profiled: + make CFLAGS="$(CFLAGS) -fprofile-arcs" timing + ./timing + rm -f *.a *.o timing + make CFLAGS="$(CFLAGS) -fbranch-probabilities" + +#make a single object profiled library +amalgamated_timing: pre_gen + $(CC) $(LTM_CFLAGS) -fprofile-arcs -c pre_gen/tommath_amalgam.c -o tommath_amalgam.o + $(CC) $(LTM_CFLAGS) -DMP_VERSION=\"before\" demo/timing.c tommath_amalgam.o -lgcov -o timing + +profiled_single: amalgamated_timing + ./timing + rm -f *.o timing + $(CC) $(LTM_CFLAGS) -fbranch-probabilities -c pre_gen/tommath_amalgam.c -o tommath_amalgam.o + $(AR) $(ARFLAGS) $(LIBNAME) tommath_amalgam.o + +install: $(LIBNAME) + install -d $(DESTDIR)$(LIBPATH) + install -d $(DESTDIR)$(INCPATH) + install -m 644 $(LIBNAME) $(DESTDIR)$(LIBPATH) + install -m 644 $(HEADERS_PUB) $(DESTDIR)$(INCPATH) + +uninstall: + rm $(DESTDIR)$(LIBPATH)/$(LIBNAME) + rm $(HEADERS_PUB:%=$(DESTDIR)$(INCPATH)/%) + +DEMOS=test mtest_opponent + +define DEMO_template +$(1): demo/$(1).o demo/shared.o $$(LIBNAME) + $$(CC) $$(LTM_CFLAGS) $$(LTM_LFLAGS) $$^ -o $$@ +endef + +$(foreach demo, $(strip $(DEMOS)), $(eval $(call DEMO_template,$(demo)))) + +.PHONY: mtest +mtest: + cd mtest ; $(CC) $(LTM_CFLAGS) -O0 mtest.c $(LTM_LFLAGS) -o mtest + +timing: demo/timing.c $(LIBNAME) + $(CC) $(LTM_CFLAGS) $^ $(LTM_LFLAGS) -o timing + +tune: $(LIBNAME) + $(MAKE) -C etc tune CFLAGS="$(LTM_CFLAGS) -I../" + $(MAKE) + +# You have to create a file .coveralls.yml with the content "repo_token: " +# in the base folder to be able to submit to coveralls +coveralls: lcov + coveralls-lcov + +docs manual: + $(MAKE) -C doc/ $@ V=$(V) + +.PHONY: pre_gen cmp +pre_gen: + mkdir -p pre_gen + cat *mp_*.c > pre_gen/tommath_amalgam.c + +cmp: profiled_single + $(CC) $(LTM_CFLAGS) -DMP_VERSION=\"after\" demo/timing.c $(LIBNAME) -lgcov -o timing + ./timing + $(MAKE) -C logs/ cmp + +zipup: clean astyle new_file docs + @# Update the index, so diff-index won't fail in case the pdf has been created. + @# As the pdf creation modifies the tex files, git sometimes detects the + @# modified files, but misses that it's put back to its original version. + @git update-index --refresh + @git diff-index --quiet HEAD -- || ( echo "FAILURE: uncommitted changes or not a git" && exit 1 ) + rm -rf libtommath-$(VERSION) ltm-$(VERSION).* + @# files/dirs excluded from "git archive" are defined in .gitattributes + git archive --format=tar --prefix=libtommath-$(VERSION)/ HEAD | tar x + @echo 'fixme check' + -@(find libtommath-$(VERSION)/ -type f | xargs grep 'FIXM[E]') && echo '############## BEWARE: the "fixme" marker was found !!! ##############' || true + mkdir -p libtommath-$(VERSION)/doc + cp doc/bn.pdf libtommath-$(VERSION)/doc/ + $(MAKE) -C libtommath-$(VERSION)/ pre_gen + tar -c libtommath-$(VERSION)/ | xz -6e -c - > ltm-$(VERSION).tar.xz + zip -9rq ltm-$(VERSION).zip libtommath-$(VERSION) + cp doc/bn.pdf bn-$(VERSION).pdf + rm -rf libtommath-$(VERSION) + gpg -b -a ltm-$(VERSION).tar.xz + gpg -b -a ltm-$(VERSION).zip + +new_file: + perl helper.pl --update-files + +perlcritic: + perlcritic *.pl doc/*.pl + +c89: + @echo "Applying substitutions for c89 compatibility..." + @if grep mp_bool tommath.h > /dev/null; then echo "Already applied"; exit 1; fi + @sed -i \ + -e '/#include /d' \ + -e 's/#include /#include "tommath_c89.h"/g' \ + -e 's/#include /\/*#include *\//g' \ + -e 's/bool/mp_bool/g' \ + -e 's/true/MP_YES/g' \ + -e 's/false/MP_NO/g' \ + -e 's/UINT32_MAX/0xFFFFFFFFu/g' \ + -e 's/UINT64_MAX/(mp_u64)-1/g' \ + -e 's/INT32_MAX/0x7FFFFFFF/g' \ + -e 's/INT32_MIN/(-2147483647-1)/g' \ + -e 's/INT64_MAX/(mp_i64)(((mp_u64)1<<63)-1)/g' \ + -e 's/INT64_MIN/(mp_i64)((mp_u64)1<<63)/g' \ + -e 's/SIZE_MAX/((size_t)-1)/g' \ + -e 's/\(PRI[ioux]64\)/MP_\1/g' \ + -e 's/uint\([0-9][0-9]*\)_t/mp_u\1/g' \ + -e 's/int\([0-9][0-9]*\)_t/mp_i\1/g' \ + -e 's/__func__/MP_FUNCTION_NAME/g' \ + -e 's/set(C89 False/set(C89 True/g' \ + *.c tommath.h tommath_private.h demo/*.c demo/*.h etc/*.c CMakeLists.txt + +c99: + @echo "Applying substitutions for c99 compatibility..." + @if ! grep mp_bool tommath.h > /dev/null; then echo "Already applied"; exit 1; fi + @sed -i \ + -e 's/#include "tommath_c89.h"/#include \n#include /g' \ + -e 's/\/\*#include \*\//#include /g' \ + -e 's/mp_bool/bool/g' \ + -e 's/MP_YES/true/g' \ + -e 's/MP_NO/false/g' \ + -e 's/false_/MP_NO_/g' \ + -e 's/0xFFFFFFFFu/UINT32_MAX/g' \ + -e 's/(mp_u64)-1/UINT64_MAX/g' \ + -e 's/(-2147483647-1)/INT32_MIN/g' \ + -e 's/0x7FFFFFFF/INT32_MAX/g' \ + -e 's/(mp_i64)((mp_u64)1<<63)/INT64_MIN/g' \ + -e 's/(mp_i64)(((mp_u64)1<<63)-1)/INT64_MAX/g' \ + -e 's/((size_t)-1)/SIZE_MAX/g' \ + -e 's/MP_\(PRI[ioux]64\)/\1/g' \ + -e 's/mp_u\([0-9][0-9]*\)/uint\1_t/g' \ + -e 's/mp_i\([0-9][0-9]*\)/int\1_t/g' \ + -e 's/MP_FUNCTION_NAME/__func__/g' \ + -e 's/set(C89 True/set(C89 False/g' \ + *.c tommath.h tommath_private.h demo/*.c demo/*.h etc/*.c CMakeLists.txt + +astyle: + @echo " * run astyle on all sources" + @astyle --options=astylerc --formatted $(OBJECTS:.o=.c) tommath*.h demo/*.c etc/*.c mtest/mtest.c diff --git a/deps/libtommath/makefile.mingw b/deps/libtommath/makefile.mingw new file mode 100644 index 0000000..532747b --- /dev/null +++ b/deps/libtommath/makefile.mingw @@ -0,0 +1,99 @@ +# MAKEFILE for MS Windows (mingw + gcc + gmake) +# +# BEWARE: variable OBJECTS is updated via helper.pl + +### USAGE: +# Open a command prompt with gcc + gmake in PATH and start: +# +# gmake -f makefile.mingw all +# test.exe +# gmake -f makefile.mingw PREFIX=c:\devel\libtom install + +#The following can be overridden from command line e.g. make -f makefile.mingw CC=gcc ARFLAGS=rcs +PREFIX = c:\mingw +CC = gcc +AR = ar +ARFLAGS = rcs +STRIP = strip +CFLAGS = -O2 +LDFLAGS = + +#Compilation flags +LTM_CFLAGS = -I. $(CFLAGS) +LTM_LDFLAGS = $(LDFLAGS) -static-libgcc + +#Libraries to be created +LIBMAIN_S =libtommath.a +LIBMAIN_I =libtommath.dll.a +LIBMAIN_D =libtommath.dll + +#List of objects to compile (all goes to libtommath.a) +OBJECTS=mp_2expt.o mp_abs.o mp_add.o mp_add_d.o mp_addmod.o mp_and.o mp_clamp.o mp_clear.o mp_clear_multi.o \ +mp_cmp.o mp_cmp_d.o mp_cmp_mag.o mp_cnt_lsb.o mp_complement.o mp_copy.o mp_count_bits.o mp_cutoffs.o \ +mp_div.o mp_div_2.o mp_div_2d.o mp_div_d.o mp_dr_is_modulus.o mp_dr_reduce.o mp_dr_setup.o \ +mp_error_to_string.o mp_exch.o mp_expt_n.o mp_exptmod.o mp_exteuclid.o mp_fread.o mp_from_sbin.o \ +mp_from_ubin.o mp_fwrite.o mp_gcd.o mp_get_double.o mp_get_i32.o mp_get_i64.o mp_get_l.o mp_get_mag_u32.o \ +mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp_init_i32.o mp_init_i64.o \ +mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \ +mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \ +mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \ +mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \ +mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \ +mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \ +mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \ +mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o \ +mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ +mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ +mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ +mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ +s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ +s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ +s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ +s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ +s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ +s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#The default rule for make builds the libtommath.a library (static) +default: $(LIBMAIN_S) + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) + +.c.o: + $(CC) $(LTM_CFLAGS) -c $< -o $@ + +#Create libtommath.a +$(LIBMAIN_S): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + +#Create DLL + import library libtommath.dll.a +$(LIBMAIN_D) $(LIBMAIN_I): $(OBJECTS) + $(CC) -s -shared -o $(LIBMAIN_D) $^ tommath.def -Wl,--out-implib=$(LIBMAIN_I) $(LTM_LDFLAGS) + $(STRIP) -S $(LIBMAIN_D) + +#Build test suite +test.exe: demo/shared.o demo/test.o $(LIBMAIN_S) + $(CC) $(LTM_CFLAGS) $(LTM_LDFLAGS) $^ -o $@ + @echo NOTICE: start the tests by launching test.exe + +all: $(LIBMAIN_S) test.exe + +tune: $(LIBNAME_S) + $(MAKE) -C etc tune + $(MAKE) + +clean: + @-cmd /c del /Q /S *.o *.a *.exe *.dll 2>nul + +#Install the library + headers +install: $(LIBMAIN_S) $(LIBMAIN_I) $(LIBMAIN_D) + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + cmd /c if not exist "$(PREFIX)\lib" mkdir "$(PREFIX)\lib" + cmd /c if not exist "$(PREFIX)\include" mkdir "$(PREFIX)\include" + copy /Y $(LIBMAIN_S) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_I) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_D) "$(PREFIX)\bin" + copy /Y tommath*.h "$(PREFIX)\include" diff --git a/deps/libtommath/makefile.msvc b/deps/libtommath/makefile.msvc new file mode 100644 index 0000000..5d12854 --- /dev/null +++ b/deps/libtommath/makefile.msvc @@ -0,0 +1,102 @@ +# MAKEFILE for MS Windows (nmake + Windows SDK) +# +# BEWARE: variable OBJECTS is updated via helper.pl + +### USAGE: +# Open a command prompt with WinSDK variables set and start: +# +# nmake -f makefile.msvc all +# test.exe +# nmake -f makefile.msvc PREFIX=c:\devel\libtom install + +#The following can be overridden from command line e.g. make -f makefile.msvc CC=gcc ARFLAGS=rcs +PREFIX = c:\devel +CFLAGS = /Ox +LDFLAGS = + +#Compilation flags +LTM_CFLAGS = /nologo /I./ /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /D__STDC_WANT_SECURE_LIB__=1 /D_CRT_HAS_CXX17=0 /Wall /wd4146 /wd4127 /wd4668 /wd4710 /wd4711 /wd4820 /wd5045 /WX $(CFLAGS) +LTM_LDFLAGS = $(LDFLAGS) advapi32.lib + +#Libraries to be created +LIBMAIN_S = tommath.lib +LIBMAIN_I = tommath.dll.lib +LIBMAIN_D = tommath.dll + +#List of objects to compile (all goes to tommath.lib) +OBJECTS=mp_2expt.obj mp_abs.obj mp_add.obj mp_add_d.obj mp_addmod.obj mp_and.obj mp_clamp.obj mp_clear.obj mp_clear_multi.obj \ +mp_cmp.obj mp_cmp_d.obj mp_cmp_mag.obj mp_cnt_lsb.obj mp_complement.obj mp_copy.obj mp_count_bits.obj mp_cutoffs.obj \ +mp_div.obj mp_div_2.obj mp_div_2d.obj mp_div_d.obj mp_dr_is_modulus.obj mp_dr_reduce.obj mp_dr_setup.obj \ +mp_error_to_string.obj mp_exch.obj mp_expt_n.obj mp_exptmod.obj mp_exteuclid.obj mp_fread.obj mp_from_sbin.obj \ +mp_from_ubin.obj mp_fwrite.obj mp_gcd.obj mp_get_double.obj mp_get_i32.obj mp_get_i64.obj mp_get_l.obj mp_get_mag_u32.obj \ +mp_get_mag_u64.obj mp_get_mag_ul.obj mp_grow.obj mp_hash.obj mp_init.obj mp_init_copy.obj mp_init_i32.obj mp_init_i64.obj \ +mp_init_l.obj mp_init_multi.obj mp_init_set.obj mp_init_size.obj mp_init_u32.obj mp_init_u64.obj mp_init_ul.obj \ +mp_invmod.obj mp_is_square.obj mp_kronecker.obj mp_lcm.obj mp_log.obj mp_log_n.obj mp_lshd.obj mp_mod.obj mp_mod_2d.obj \ +mp_montgomery_calc_normalization.obj mp_montgomery_reduce.obj mp_montgomery_setup.obj mp_mul.obj mp_mul_2.obj \ +mp_mul_2d.obj mp_mul_d.obj mp_mulmod.obj mp_neg.obj mp_or.obj mp_pack.obj mp_pack_count.obj mp_prime_fermat.obj \ +mp_prime_frobenius_underwood.obj mp_prime_is_prime.obj mp_prime_miller_rabin.obj mp_prime_next_prime.obj \ +mp_prime_rabin_miller_trials.obj mp_prime_rand.obj mp_prime_strong_lucas_selfridge.obj mp_radix_size.obj \ +mp_radix_size_overestimate.obj mp_rand.obj mp_rand_source.obj mp_read_radix.obj mp_reduce.obj mp_reduce_2k.obj \ +mp_reduce_2k_l.obj mp_reduce_2k_setup.obj mp_reduce_2k_setup_l.obj mp_reduce_is_2k.obj mp_reduce_is_2k_l.obj \ +mp_reduce_setup.obj mp_root_n.obj mp_rshd.obj mp_sbin_size.obj mp_set.obj mp_set_double.obj mp_set_i32.obj mp_set_i64.obj \ +mp_set_l.obj mp_set_u32.obj mp_set_u64.obj mp_set_ul.obj mp_shrink.obj mp_signed_rsh.obj mp_sqrmod.obj mp_sqrt.obj \ +mp_sqrtmod_prime.obj mp_sub.obj mp_sub_d.obj mp_submod.obj mp_to_radix.obj mp_to_sbin.obj mp_to_ubin.obj mp_ubin_size.obj \ +mp_unpack.obj mp_xor.obj mp_zero.obj s_mp_add.obj s_mp_copy_digs.obj s_mp_div_3.obj s_mp_div_recursive.obj \ +s_mp_div_school.obj s_mp_div_small.obj s_mp_exptmod.obj s_mp_exptmod_fast.obj s_mp_fp_log.obj s_mp_fp_log_d.obj \ +s_mp_get_bit.obj s_mp_invmod.obj s_mp_invmod_odd.obj s_mp_log_2expt.obj s_mp_montgomery_reduce_comba.obj s_mp_mul.obj \ +s_mp_mul_balance.obj s_mp_mul_comba.obj s_mp_mul_high.obj s_mp_mul_high_comba.obj s_mp_mul_karatsuba.obj \ +s_mp_mul_toom.obj s_mp_prime_is_divisible.obj s_mp_prime_tab.obj s_mp_radix_map.obj \ +s_mp_radix_size_overestimate.obj s_mp_rand_platform.obj s_mp_sqr.obj s_mp_sqr_comba.obj s_mp_sqr_karatsuba.obj \ +s_mp_sqr_toom.obj s_mp_sub.obj s_mp_zero_buf.obj s_mp_zero_digs.obj + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#The default rule for make builds the tommath.lib library (static) +default: $(LIBMAIN_S) + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) + +.c.obj: + $(CC) $(LTM_CFLAGS) /c $< /Fo$@ + +#Create tommath.lib +$(LIBMAIN_S): $(OBJECTS) + lib /out:$(LIBMAIN_S) $(OBJECTS) + +#Create DLL + import library tommath.dll.lib +$(LIBMAIN_D) $(LIBMAIN_I): $(OBJECTS) tommath.def + link /dll /out:$(LIBMAIN_D) /implib:$(LIBMAIN_I) /def:tommath.def $(LTM_LDFLAGS) $(OBJECTS) + +#Build test suite +test.exe: $(LIBMAIN_S) demo/shared.obj demo/test.obj + link $(TOBJECTS) $(LTM_LDFLAGS) $? /out:$@ + @echo NOTICE: start the tests by launching test.exe + +#Build test suite for dll +test_dll.exe: $(LIBMAIN_I) demo/shared.obj demo/test.obj + link $(TOBJECTS) $(LTM_LDFLAGS) $? /out:$@ + @echo NOTICE: start the tests by launching test_dll.exe + +all: $(LIBMAIN_S) test.exe $(LIBMAIN_D) test_dll.exe + +tune: $(LIBMAIN_S) + $(MAKE) -C etc tune + $(MAKE) + +clean-obj: + @-cmd /c del /Q /S *.OBJ 2>nul + +clean: clean-obj + @-cmd /c del /Q /S *.LIB *.EXE *.DLL 2>nul + +#Install the library + headers +install: $(LIBMAIN_S) $(LIBMAIN_I) $(LIBMAIN_D) + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + cmd /c if not exist "$(PREFIX)\lib" mkdir "$(PREFIX)\lib" + cmd /c if not exist "$(PREFIX)\include" mkdir "$(PREFIX)\include" + copy /Y $(LIBMAIN_S) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_I) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_D) "$(PREFIX)\bin" + copy /Y tommath*.h "$(PREFIX)\include" diff --git a/deps/libtommath/makefile.shared b/deps/libtommath/makefile.shared new file mode 100644 index 0000000..fe077fc --- /dev/null +++ b/deps/libtommath/makefile.shared @@ -0,0 +1,100 @@ +#Makefile for GCC +# +#Tom St Denis + +#default files to install +ifndef LIBNAME + LIBNAME=libtommath.la +endif + +include makefile_include.mk + + +ifndef LIBTOOL + ifeq ($(PLATFORM), Darwin) + LIBTOOL:=glibtool + else + LIBTOOL:=libtool + endif +endif +LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(CC) +LTLINK = $(LIBTOOL) --mode=link --tag=CC $(CC) + +LCOV_ARGS=--directory .libs --directory . + +#START_INS +OBJECTS=mp_2expt.o mp_abs.o mp_add.o mp_add_d.o mp_addmod.o mp_and.o mp_clamp.o mp_clear.o mp_clear_multi.o \ +mp_cmp.o mp_cmp_d.o mp_cmp_mag.o mp_cnt_lsb.o mp_complement.o mp_copy.o mp_count_bits.o mp_cutoffs.o \ +mp_div.o mp_div_2.o mp_div_2d.o mp_div_d.o mp_dr_is_modulus.o mp_dr_reduce.o mp_dr_setup.o \ +mp_error_to_string.o mp_exch.o mp_expt_n.o mp_exptmod.o mp_exteuclid.o mp_fread.o mp_from_sbin.o \ +mp_from_ubin.o mp_fwrite.o mp_gcd.o mp_get_double.o mp_get_i32.o mp_get_i64.o mp_get_l.o mp_get_mag_u32.o \ +mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp_init_i32.o mp_init_i64.o \ +mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \ +mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \ +mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \ +mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \ +mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \ +mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \ +mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \ +mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o \ +mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ +mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ +mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ +mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ +s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ +s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ +s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ +s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ +s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ +s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o + +#END_INS + +objs: $(OBJECTS) + +.c.o: $(HEADERS) + $(LTCOMPILE) $(LTM_CFLAGS) $(LTM_LDFLAGS) -o $@ -c $< + +LOBJECTS = $(OBJECTS:.o=.lo) + +$(LIBNAME): $(OBJECTS) + $(LTLINK) $(LTM_LDFLAGS) $(LOBJECTS) -o $(LIBNAME) -rpath $(LIBPATH) -version-info $(VERSION_SO) $(LTM_LIBTOOLFLAGS) + +install: $(LIBNAME) + install -d $(DESTDIR)$(LIBPATH) + install -d $(DESTDIR)$(INCPATH) + $(LIBTOOL) --mode=install install -m 644 $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME) + install -m 644 $(HEADERS_PUB) $(DESTDIR)$(INCPATH) + sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' -e 's,@CMAKE_INSTALL_LIBDIR@,lib,' \ + -e 's,@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@,include/tommath,' libtommath.pc.in > libtommath.pc + install -d $(DESTDIR)$(LIBPATH)/pkgconfig + install -m 644 libtommath.pc $(DESTDIR)$(LIBPATH)/pkgconfig/ + +uninstall: + $(LIBTOOL) --mode=uninstall rm $(DESTDIR)$(LIBPATH)/$(LIBNAME) + rm $(HEADERS_PUB:%=$(DESTDIR)$(INCPATH)/%) + rm $(DESTDIR)$(LIBPATH)/pkgconfig/libtommath.pc + +DEMOS=mtest_opponent test timing +test: LTM_LDFLAGS+=-DLTM_TEST_DYNAMIC + +# build the demos from a template +define DEMO_template +$(1): $(call print-help,$(1),Builds the library and the '$(1)' demo) demo/$(1).o demo/shared.o $$(LIBNAME) +ifneq ($V,1) + @echo " * $${CC} $$@" ${silent_echo} +endif + $(LTLINK) $(LTM_CFLAGS) $(LTM_LDFLAGS) $$^ -o $(1) +endef + +$(foreach demo, $(strip $(DEMOS)), $(eval $(call DEMO_template,$(demo)))) + +.PHONY: mtest +mtest: + cd mtest ; $(CC) $(LTM_CFLAGS) -O0 mtest.c $(LTM_LDFLAGS) -o mtest + +tune: $(LIBNAME) + $(LTCOMPILE) $(LTM_CFLAGS) -c etc/tune.c -o etc/tune.o + $(LTLINK) $(LTM_LDFLAGS) -o etc/tune etc/tune.o $(LIBNAME) + cd etc/; /bin/sh tune_it.sh; cd .. + $(MAKE) -f makefile.shared diff --git a/deps/libtommath/makefile.unix b/deps/libtommath/makefile.unix new file mode 100644 index 0000000..9fe939f --- /dev/null +++ b/deps/libtommath/makefile.unix @@ -0,0 +1,97 @@ +# MAKEFILE that is intended to be compatible with any kind of make (GNU make, BSD make, ...) +# works on: Linux, *BSD, Cygwin, AIX, HP-UX and hopefully other UNIX systems +# +# Please do not use here neither any special make syntax nor any unusual tools/utilities! + +# using ICC compiler: +# make -f makefile.unix CC=icc CFLAGS="-O3 -xP -ip" + +# using Borland C++Builder: +# make -f makefile.unix CC=bcc32 + +#The following can be overridden from command line e.g. "make -f makefile.unix CC=gcc ARFLAGS=rcs" +DESTDIR = +PREFIX = /usr/local +LIBPATH = $(PREFIX)/lib +INCPATH = $(PREFIX)/include +CC = cc +AR = ar +ARFLAGS = rcs +CFLAGS = -O2 +LDFLAGS = + +VERSION = 1.2.0 + +#Compilation flags +LTM_CFLAGS = -I. $(CFLAGS) +LTM_LDFLAGS = $(LDFLAGS) + +#Library to be created (this makefile builds only static library) +LIBMAIN_S = libtommath.a + +OBJECTS=mp_2expt.o mp_abs.o mp_add.o mp_add_d.o mp_addmod.o mp_and.o mp_clamp.o mp_clear.o mp_clear_multi.o \ +mp_cmp.o mp_cmp_d.o mp_cmp_mag.o mp_cnt_lsb.o mp_complement.o mp_copy.o mp_count_bits.o mp_cutoffs.o \ +mp_div.o mp_div_2.o mp_div_2d.o mp_div_d.o mp_dr_is_modulus.o mp_dr_reduce.o mp_dr_setup.o \ +mp_error_to_string.o mp_exch.o mp_expt_n.o mp_exptmod.o mp_exteuclid.o mp_fread.o mp_from_sbin.o \ +mp_from_ubin.o mp_fwrite.o mp_gcd.o mp_get_double.o mp_get_i32.o mp_get_i64.o mp_get_l.o mp_get_mag_u32.o \ +mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp_init_i32.o mp_init_i64.o \ +mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \ +mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \ +mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \ +mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \ +mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \ +mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \ +mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \ +mp_reduce_2k_l.o mp_reduce_2k_setup.o mp_reduce_2k_setup_l.o mp_reduce_is_2k.o mp_reduce_is_2k_l.o \ +mp_reduce_setup.o mp_root_n.o mp_rshd.o mp_sbin_size.o mp_set.o mp_set_double.o mp_set_i32.o mp_set_i64.o \ +mp_set_l.o mp_set_u32.o mp_set_u64.o mp_set_ul.o mp_shrink.o mp_signed_rsh.o mp_sqrmod.o mp_sqrt.o \ +mp_sqrtmod_prime.o mp_sub.o mp_sub_d.o mp_submod.o mp_to_radix.o mp_to_sbin.o mp_to_ubin.o mp_ubin_size.o \ +mp_unpack.o mp_xor.o mp_zero.o s_mp_add.o s_mp_copy_digs.o s_mp_div_3.o s_mp_div_recursive.o \ +s_mp_div_school.o s_mp_div_small.o s_mp_exptmod.o s_mp_exptmod_fast.o s_mp_fp_log.o s_mp_fp_log_d.o \ +s_mp_get_bit.o s_mp_invmod.o s_mp_invmod_odd.o s_mp_log_2expt.o s_mp_montgomery_reduce_comba.o s_mp_mul.o \ +s_mp_mul_balance.o s_mp_mul_comba.o s_mp_mul_high.o s_mp_mul_high_comba.o s_mp_mul_karatsuba.o \ +s_mp_mul_toom.o s_mp_prime_is_divisible.o s_mp_prime_tab.o s_mp_radix_map.o \ +s_mp_radix_size_overestimate.o s_mp_rand_platform.o s_mp_sqr.o s_mp_sqr_comba.o s_mp_sqr_karatsuba.o \ +s_mp_sqr_toom.o s_mp_sub.o s_mp_zero_buf.o s_mp_zero_digs.o + + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#The default rule for make builds the libtommath.a library (static) +default: $(LIBMAIN_S) + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) + +#This is necessary for compatibility with BSD make (namely on OpenBSD) +.SUFFIXES: .o .c +.c.o: + $(CC) $(LTM_CFLAGS) -c $< -o $@ + +#Create libtommath.a +$(LIBMAIN_S): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + +#Build test_standalone suite +test: demo/shared.o demo/test.o $(LIBMAIN_S) + $(CC) $(LTM_CFLAGS) $(LTM_LDFLAGS) $^ -o $@ + @echo "NOTICE: start the tests by: ./test" + +all: $(LIBMAIN_S) test + +tune: $(LIBMAIN_S) + $(MAKE) -C etc tune + $(MAKE) + +#NOTE: this makefile works also on cygwin, thus we need to delete *.exe +clean: + -@rm -f $(OBJECTS) $(LIBMAIN_S) + -@rm -f demo/main.o demo/opponent.o demo/test.o test test.exe + +#Install the library + headers +install: $(LIBMAIN_S) + @mkdir -p $(DESTDIR)$(INCPATH) $(DESTDIR)$(LIBPATH)/pkgconfig + @cp $(LIBMAIN_S) $(DESTDIR)$(LIBPATH)/ + @cp $(HEADERS_PUB) $(DESTDIR)$(INCPATH)/ + @sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION),' libtommath.pc.in > $(DESTDIR)$(LIBPATH)/pkgconfig/libtommath.pc diff --git a/deps/libtommath/makefile_include.mk b/deps/libtommath/makefile_include.mk new file mode 100644 index 0000000..f88d18b --- /dev/null +++ b/deps/libtommath/makefile_include.mk @@ -0,0 +1,180 @@ +# +# Include makefile for libtommath +# + +#version of library +VERSION=1.2.0-develop +VERSION_PC=1.2.0 +VERSION_SO=3:0:2 + +PLATFORM := $(shell uname | sed -e 's/_.*//') + +# default make target +default: ${LIBNAME} + +# Compiler and Linker Names +ifndef CROSS_COMPILE + CROSS_COMPILE= +endif + +# We only need to go through this dance of determining the right compiler if we're using +# cross compilation, otherwise $(CC) is fine as-is. +ifneq (,$(CROSS_COMPILE)) +ifeq ($(origin CC),default) +CSTR := "\#ifdef __clang__\nCLANG\n\#endif\n" +ifeq ($(PLATFORM),FreeBSD) + # XXX: FreeBSD needs extra escaping for some reason + CSTR := $$$(CSTR) +endif +ifneq (,$(shell printf $(CSTR) | $(CC) -E - | grep CLANG)) + CC := $(CROSS_COMPILE)clang +else + CC := $(CROSS_COMPILE)gcc +endif # Clang +endif # cc is Make's default +endif # CROSS_COMPILE non-empty + +LD=$(CROSS_COMPILE)ld +AR=$(CROSS_COMPILE)ar + +ifndef MAKE +# BSDs refer to GNU Make as gmake +ifneq (,$(findstring $(PLATFORM),FreeBSD OpenBSD DragonFly NetBSD)) + MAKE=gmake +else + MAKE=make +endif +endif + +LTM_CFLAGS += -I./ -Wall -Wsign-compare -Wextra -Wshadow + +ifneq (,$(SANITIZER)) +LTM_CFLAGS += -fsanitize=undefined -fno-sanitize-recover=all -fno-sanitize=float-divide-by-zero +endif + +ifndef NO_ADDTL_WARNINGS +# additional warnings +LTM_CFLAGS += -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align +LTM_CFLAGS += -Wstrict-prototypes -Wpointer-arith +endif + +ifdef CONV_WARNINGS +LTM_CFLAGS += -std=c89 -Wconversion -Wsign-conversion +ifeq ($(CONV_WARNINGS), strict) +LTM_CFLAGS += -Wc++-compat +endif +else +LTM_CFLAGS += -Wsystem-headers +endif + +ifdef COMPILE_DEBUG +#debug +LTM_CFLAGS += -g3 +endif + +ifdef COMPILE_SIZE +#for size +LTM_CFLAGS += -Os +else + +ifndef IGNORE_SPEED +#for speed +LTM_CFLAGS += -O3 -funroll-loops + +#x86 optimizations [should be valid for any GCC install though] +LTM_CFLAGS += -fomit-frame-pointer +endif + +ifdef COMPILE_LTO +LTM_CFLAGS += -flto +LTM_LDFLAGS += -flto +AR = $(subst clang,llvm-ar,$(subst gcc,gcc-ar,$(CC))) +endif + +endif # COMPILE_SIZE + +ifneq ($(findstring clang,$(CC)),) +LTM_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header +ifdef IGNORE_SPEED +#for dead code eliminiation +LTM_CFLAGS += -O1 +endif +endif +ifneq ($(findstring mingw,$(CC)),) +LTM_CFLAGS += -Wno-shadow +endif +ifeq ($(PLATFORM), Darwin) +LTM_CFLAGS += -Wno-nullability-completeness +endif +ifneq ($(findstring $(PLATFORM),CYGWIN MINGW32 MINGW64 MSYS),) +LIBTOOLFLAGS += -no-undefined +endif + +# add in the standard FLAGS +LTM_CFLAGS += $(CFLAGS) +LTM_LFLAGS += $(LFLAGS) +LTM_LDFLAGS += $(LDFLAGS) +LTM_LIBTOOLFLAGS += $(LIBTOOLFLAGS) + + +ifeq ($(PLATFORM),FreeBSD) + _ARCH := $(shell sysctl -b hw.machine_arch) +else + _ARCH := $(shell uname -m) +endif + +# adjust coverage set +ifneq ($(filter $(_ARCH), i386 i686 x86_64 amd64 ia64),) + COVERAGE = test timing + COVERAGE_APP = ./test && ./timing +else + COVERAGE = test + COVERAGE_APP = ./test +endif + +HEADERS_PUB=tommath.h +HEADERS=tommath_private.h tommath_class.h tommath_superclass.h tommath_cutoffs.h $(HEADERS_PUB) + +#LIBPATH The directory for libtommath to be installed to. +#INCPATH The directory to install the header files for libtommath. +#DATAPATH The directory to install the pdf docs. +DESTDIR ?= +PREFIX ?= /usr/local +LIBPATH ?= $(PREFIX)/lib +INCPATH ?= $(PREFIX)/include +DATAPATH ?= $(PREFIX)/share/doc/libtommath/pdf + +# build & run test-suite +check: test + ./test + +#make the code coverage of the library +# +coverage: LTM_CFLAGS += -fprofile-arcs -ftest-coverage -DTIMING_NO_LOGS +coverage: LTM_LFLAGS += -lgcov +coverage: LTM_LDFLAGS += -lgcov + +coverage: $(COVERAGE) + $(COVERAGE_APP) + +lcov: coverage + rm -f coverage.info + lcov --capture --no-external --no-recursion $(LCOV_ARGS) --output-file coverage.info -q + genhtml coverage.info --output-directory coverage -q + +# target that removes all coverage output +cleancov-clean: + rm -f `find . -type f -name "*.info" | xargs` + rm -rf coverage/ + +# cleans everything - coverage output and standard 'clean' +cleancov: cleancov-clean clean + +clean: + rm -f *.gcda *.gcno *.gcov *.bat *.o *.a *.obj *.lib *.exe *.dll etclib/*.o \ + demo/*.o test timing mtest_opponent mtest/mtest mtest/mtest.exe tuning_list \ + *.s tommath_amalgam.c pre_gen/tommath_amalgam.c *.da *.dyn *.dpi tommath.tex \ + `find . -type f | grep [~] | xargs` *.lo *.la + rm -rf .libs/ demo/.libs + ${MAKE} -C etc/ clean MAKE=${MAKE} + ${MAKE} -C doc/ clean MAKE=${MAKE} diff --git a/deps/libtommath/modulemap/module.modulemap b/deps/libtommath/modulemap/module.modulemap new file mode 100644 index 0000000..7280be7 --- /dev/null +++ b/deps/libtommath/modulemap/module.modulemap @@ -0,0 +1,4 @@ +module libtommath [extern_c] { + header "../tommath.h" + export * +} diff --git a/deps/libtommath/mp_2expt.c b/deps/libtommath/mp_2expt.c new file mode 100644 index 0000000..4a5fc00 --- /dev/null +++ b/deps/libtommath/mp_2expt.c @@ -0,0 +1,31 @@ +#include "tommath_private.h" +#ifdef MP_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes a = 2**b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ +mp_err mp_2expt(mp_int *a, int b) +{ + mp_err err; + + /* zero a as per default */ + mp_zero(a); + + /* grow a to accommodate the single bit */ + if ((err = mp_grow(a, (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } + + /* set the used count of where the bit will go */ + a->used = (b / MP_DIGIT_BIT) + 1; + + /* put the single bit in its place */ + a->dp[b / MP_DIGIT_BIT] = (mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT); + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_abs.c b/deps/libtommath/mp_abs.c new file mode 100644 index 0000000..a87cc0c --- /dev/null +++ b/deps/libtommath/mp_abs.c @@ -0,0 +1,24 @@ +#include "tommath_private.h" +#ifdef MP_ABS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +mp_err mp_abs(const mp_int *a, mp_int *b) +{ + mp_err err; + + /* copy a to b */ + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + + /* force the sign of b to positive */ + b->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_add.c b/deps/libtommath/mp_add.c new file mode 100644 index 0000000..bf7a61e --- /dev/null +++ b/deps/libtommath/mp_add.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level addition (handles signs) */ +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) +{ + /* handle two cases, not four */ + if (a->sign == b->sign) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = a->sign; + return s_mp_add(a, b, c); + } + + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (mp_cmp_mag(a, b) == MP_LT) { + MP_EXCH(const mp_int *, a, b); + } + + c->sign = a->sign; + return s_mp_sub(a, b, c); +} + +#endif diff --git a/deps/libtommath/mp_add_d.c b/deps/libtommath/mp_add_d.c new file mode 100644 index 0000000..c57a80d --- /dev/null +++ b/deps/libtommath/mp_add_d.c @@ -0,0 +1,86 @@ +#include "tommath_private.h" +#ifdef MP_ADD_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit addition */ +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_err err; + int oldused; + + /* fast path for a == c */ + if (a == c) { + if (!mp_isneg(c) && + !mp_iszero(c) && + ((c->dp[0] + b) < MP_DIGIT_MAX)) { + c->dp[0] += b; + return MP_OKAY; + } + if (mp_isneg(c) && + (c->dp[0] > b)) { + c->dp[0] -= b; + return MP_OKAY; + } + } + + /* grow c as required */ + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if (mp_isneg(a) && ((a->used > 1) || (a->dp[0] >= b))) { + mp_int a_ = *a; + /* temporarily fix sign of a */ + a_.sign = MP_ZPOS; + + /* c = |a| - b */ + err = mp_sub_d(&a_, b, c); + + /* fix sign */ + c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return err; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* if a is positive */ + if (!mp_isneg(a)) { + /* add digits, mu is carry */ + int i; + mp_digit mu = b; + for (i = 0; i < a->used; i++) { + c->dp[i] = a->dp[i] + mu; + mu = c->dp[i] >> MP_DIGIT_BIT; + c->dp[i] &= MP_MASK; + } + /* set final carry */ + c->dp[i] = mu; + + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + c->dp[0] = (a->used == 1) ? b - a->dp[0] : b; + } + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* now zero to oldused */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + mp_clamp(c); + + return MP_OKAY; +} + +#endif diff --git a/deps/libtommath/mp_addmod.c b/deps/libtommath/mp_addmod.c new file mode 100644 index 0000000..91e2087 --- /dev/null +++ b/deps/libtommath/mp_addmod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_ADDMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a + b (mod c) */ +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + if ((err = mp_add(a, b, d)) != MP_OKAY) { + return err; + } + return mp_mod(d, c, d); +} +#endif diff --git a/deps/libtommath/mp_and.c b/deps/libtommath/mp_and.c new file mode 100644 index 0000000..b5230c4 --- /dev/null +++ b/deps/libtommath/mp_and.c @@ -0,0 +1,54 @@ +#include "tommath_private.h" +#ifdef MP_AND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement and */ +mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + bool neg = (mp_isneg(a) && mp_isneg(b)); + + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (mp_isneg(a)) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (mp_isneg(b)) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x & y; + + /* convert to to sign-magnitude if negative */ + if (neg) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = (neg ? MP_NEG : MP_ZPOS); + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_clamp.c b/deps/libtommath/mp_clamp.c new file mode 100644 index 0000000..463f22d --- /dev/null +++ b/deps/libtommath/mp_clamp.c @@ -0,0 +1,27 @@ +#include "tommath_private.h" +#ifdef MP_CLAMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimmed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ +void mp_clamp(mp_int *a) +{ + /* decrease used while the most significant digit is + * zero. + */ + while ((a->used > 0) && (a->dp[a->used - 1] == 0u)) { + --(a->used); + } + + /* reset the sign flag if zero */ + if (mp_iszero(a)) { + a->sign = MP_ZPOS; + } +} +#endif diff --git a/deps/libtommath/mp_clear.c b/deps/libtommath/mp_clear.c new file mode 100644 index 0000000..11094b2 --- /dev/null +++ b/deps/libtommath/mp_clear.c @@ -0,0 +1,20 @@ +#include "tommath_private.h" +#ifdef MP_CLEAR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* clear one (frees) */ +void mp_clear(mp_int *a) +{ + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + MP_FREE_DIGS(a->dp, a->alloc); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} +#endif diff --git a/deps/libtommath/mp_clear_multi.c b/deps/libtommath/mp_clear_multi.c new file mode 100644 index 0000000..9c7aed8 --- /dev/null +++ b/deps/libtommath/mp_clear_multi.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef MP_CLEAR_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +void mp_clear_multi(mp_int *mp, ...) +{ + va_list args; + va_start(args, mp); + while (mp != NULL) { + mp_clear(mp); + mp = va_arg(args, mp_int *); + } + va_end(args); +} +#endif diff --git a/deps/libtommath/mp_cmp.c b/deps/libtommath/mp_cmp.c new file mode 100644 index 0000000..9f3847b --- /dev/null +++ b/deps/libtommath/mp_cmp.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_CMP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare two ints (signed)*/ +mp_ord mp_cmp(const mp_int *a, const mp_int *b) +{ + /* compare based on sign */ + if (a->sign != b->sign) { + return mp_isneg(a) ? MP_LT : MP_GT; + } + + /* if negative compare opposite direction */ + if (mp_isneg(a)) { + MP_EXCH(const mp_int *, a, b); + } + + return mp_cmp_mag(a, b); +} +#endif diff --git a/deps/libtommath/mp_cmp_d.c b/deps/libtommath/mp_cmp_d.c new file mode 100644 index 0000000..42f7b16 --- /dev/null +++ b/deps/libtommath/mp_cmp_d.c @@ -0,0 +1,26 @@ +#include "tommath_private.h" +#ifdef MP_CMP_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare a digit */ +mp_ord mp_cmp_d(const mp_int *a, mp_digit b) +{ + /* compare based on sign */ + if (mp_isneg(a)) { + return MP_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return MP_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] != b) { + return a->dp[0] > b ? MP_GT : MP_LT; + } + + return MP_EQ; +} +#endif diff --git a/deps/libtommath/mp_cmp_mag.c b/deps/libtommath/mp_cmp_mag.c new file mode 100644 index 0000000..06f22e7 --- /dev/null +++ b/deps/libtommath/mp_cmp_mag.c @@ -0,0 +1,25 @@ +#include "tommath_private.h" +#ifdef MP_CMP_MAG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* compare magnitude of two ints (unsigned) */ +mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b) +{ + int n; + + /* compare based on # of non-zero digits */ + if (a->used != b->used) { + return a->used > b->used ? MP_GT : MP_LT; + } + + /* compare based on digits */ + for (n = a->used; n --> 0;) { + if (a->dp[n] != b->dp[n]) { + return a->dp[n] > b->dp[n] ? MP_GT : MP_LT; + } + } + + return MP_EQ; +} +#endif diff --git a/deps/libtommath/mp_cnt_lsb.c b/deps/libtommath/mp_cnt_lsb.c new file mode 100644 index 0000000..8519ad1 --- /dev/null +++ b/deps/libtommath/mp_cnt_lsb.c @@ -0,0 +1,38 @@ +#include "tommath_private.h" +#ifdef MP_CNT_LSB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static const char lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(const mp_int *a) +{ + int x; + mp_digit q; + + /* easy out */ + if (mp_iszero(a)) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; (x < a->used) && (a->dp[x] == 0u); x++) {} + q = a->dp[x]; + x *= MP_DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1u) == 0u) { + mp_digit p; + do { + p = q & 15u; + x += lnz[p]; + q >>= 4; + } while (p == 0u); + } + return x; +} + +#endif diff --git a/deps/libtommath/mp_complement.c b/deps/libtommath/mp_complement.c new file mode 100644 index 0000000..c16e25f --- /dev/null +++ b/deps/libtommath/mp_complement.c @@ -0,0 +1,13 @@ +#include "tommath_private.h" +#ifdef MP_COMPLEMENT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = ~a */ +mp_err mp_complement(const mp_int *a, mp_int *b) +{ + mp_int a_ = *a; + a_.sign = ((a_.sign == MP_ZPOS) && !mp_iszero(a)) ? MP_NEG : MP_ZPOS; + return mp_sub_d(&a_, 1uL, b); +} +#endif diff --git a/deps/libtommath/mp_copy.c b/deps/libtommath/mp_copy.c new file mode 100644 index 0000000..d79e2b8 --- /dev/null +++ b/deps/libtommath/mp_copy.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* copy, b = a */ +mp_err mp_copy(const mp_int *a, mp_int *b) +{ + mp_err err; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + + /* copy everything over and zero high digits */ + s_mp_copy_digs(b->dp, a->dp, a->used); + s_mp_zero_digs(b->dp + a->used, b->used - a->used); + b->used = a->used; + b->sign = a->sign; + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_count_bits.c b/deps/libtommath/mp_count_bits.c new file mode 100644 index 0000000..52b463d --- /dev/null +++ b/deps/libtommath/mp_count_bits.c @@ -0,0 +1,28 @@ +#include "tommath_private.h" +#ifdef MP_COUNT_BITS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* returns the number of bits in an int */ +int mp_count_bits(const mp_int *a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (mp_iszero(a)) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * MP_DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > 0u) { + ++r; + q >>= 1u; + } + return r; +} +#endif diff --git a/deps/libtommath/mp_cutoffs.c b/deps/libtommath/mp_cutoffs.c new file mode 100644 index 0000000..45b0bee --- /dev/null +++ b/deps/libtommath/mp_cutoffs.c @@ -0,0 +1,14 @@ +#include "tommath_private.h" +#ifdef MP_CUTOFFS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_FIXED_CUTOFFS +#include "tommath_cutoffs.h" +int MP_MUL_KARATSUBA_CUTOFF = MP_DEFAULT_MUL_KARATSUBA_CUTOFF, + MP_SQR_KARATSUBA_CUTOFF = MP_DEFAULT_SQR_KARATSUBA_CUTOFF, + MP_MUL_TOOM_CUTOFF = MP_DEFAULT_MUL_TOOM_CUTOFF, + MP_SQR_TOOM_CUTOFF = MP_DEFAULT_SQR_TOOM_CUTOFF; +#endif + +#endif diff --git a/deps/libtommath/mp_div.c b/deps/libtommath/mp_div.c new file mode 100644 index 0000000..b092d7b --- /dev/null +++ b/deps/libtommath/mp_div.c @@ -0,0 +1,42 @@ +#include "tommath_private.h" +#ifdef MP_DIV_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_err err; + + /* is divisor zero ? */ + if (mp_iszero(b)) { + return MP_VAL; + } + + /* if a < b then q = 0, r = a */ + if (mp_cmp_mag(a, b) == MP_LT) { + if (d != NULL) { + if ((err = mp_copy(a, d)) != MP_OKAY) { + return err; + } + } + if (c != NULL) { + mp_zero(c); + } + return MP_OKAY; + } + + if (MP_HAS(S_MP_DIV_RECURSIVE) + && (b->used > (2 * MP_MUL_KARATSUBA_CUTOFF)) + && (b->used <= ((a->used/3)*2))) { + err = s_mp_div_recursive(a, b, c, d); + } else if (MP_HAS(S_MP_DIV_SCHOOL)) { + err = s_mp_div_school(a, b, c, d); + } else if (MP_HAS(S_MP_DIV_SMALL)) { + err = s_mp_div_small(a, b, c, d); + } else { + err = MP_VAL; + } + + return err; +} +#endif diff --git a/deps/libtommath/mp_div_2.c b/deps/libtommath/mp_div_2.c new file mode 100644 index 0000000..8ab9bcb --- /dev/null +++ b/deps/libtommath/mp_div_2.c @@ -0,0 +1,40 @@ +#include "tommath_private.h" +#ifdef MP_DIV_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = a/2 */ +mp_err mp_div_2(const mp_int *a, mp_int *b) +{ + mp_err err; + int x, oldused; + mp_digit r; + + if ((err = mp_grow(b, a->used)) != MP_OKAY) { + return err; + } + + oldused = b->used; + b->used = a->used; + + /* carry */ + r = 0; + for (x = b->used; x --> 0;) { + /* get the carry for the next iteration */ + mp_digit rr = a->dp[x] & 1u; + + /* shift the current digit, add in carry and store */ + b->dp[x] = (a->dp[x] >> 1) | (r << (MP_DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + s_mp_zero_digs(b->dp + b->used, oldused - b->used); + + b->sign = a->sign; + mp_clamp(b); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_div_2d.c b/deps/libtommath/mp_div_2d.c new file mode 100644 index 0000000..e523465 --- /dev/null +++ b/deps/libtommath/mp_div_2d.c @@ -0,0 +1,61 @@ +#include "tommath_private.h" +#ifdef MP_DIV_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ +mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) +{ + mp_err err; + + if (b < 0) { + return MP_VAL; + } + + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + + /* 'a' should not be used after here - it might be the same as d */ + + /* get the remainder */ + if (d != NULL) { + if ((err = mp_mod_2d(a, b, d)) != MP_OKAY) { + return err; + } + } + + /* shift by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + mp_rshd(c, b / MP_DIGIT_BIT); + } + + /* shift any bit count < MP_DIGIT_BIT */ + b %= MP_DIGIT_BIT; + if (b != 0u) { + int x; + mp_digit r, mask, shift; + + /* mask */ + mask = ((mp_digit)1 << b) - 1uL; + + /* shift for lsb */ + shift = (mp_digit)(MP_DIGIT_BIT - b); + + /* carry */ + r = 0; + for (x = c->used; x --> 0;) { + /* get the lower bits of this word in a temp */ + mp_digit rr = c->dp[x] & mask; + + /* shift the current word and mix in the carry bits from the previous word */ + c->dp[x] = (c->dp[x] >> b) | (r << shift); + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + } + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_div_d.c b/deps/libtommath/mp_div_d.c new file mode 100644 index 0000000..5697e54 --- /dev/null +++ b/deps/libtommath/mp_div_d.c @@ -0,0 +1,84 @@ +#include "tommath_private.h" +#ifdef MP_DIV_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit division (based on routine from MPI) */ +mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) +{ + mp_int q; + mp_word w; + mp_err err; + int ix; + + /* cannot divide by zero */ + if (b == 0u) { + return MP_VAL; + } + + /* quick outs */ + if ((b == 1u) || mp_iszero(a)) { + if (d != NULL) { + *d = 0; + } + if (c != NULL) { + return mp_copy(a, c); + } + return MP_OKAY; + } + + /* power of two ? */ + if (MP_HAS(MP_DIV_2) && (b == 2u)) { + if (d != NULL) { + *d = mp_isodd(a) ? 1u : 0u; + } + return (c == NULL) ? MP_OKAY : mp_div_2(a, c); + } + if (MP_HAS(MP_DIV_2D) && MP_IS_2EXPT(b)) { + ix = 1; + while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<dp[0] & (((mp_digit)1<<(mp_digit)ix) - 1uL); + } + return (c == NULL) ? MP_OKAY : mp_div_2d(a, ix, c, NULL); + } + + /* three? */ + if (MP_HAS(S_MP_DIV_3) && (b == 3u)) { + return s_mp_div_3(a, c, d); + } + + /* no easy answer [c'est la vie]. Just division */ + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used; ix --> 0;) { + mp_digit t = 0; + w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; + if (w >= b) { + t = (mp_digit)(w / b); + w -= (mp_word)t * (mp_word)b; + } + q.dp[ix] = t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return MP_OKAY; +} + +#endif diff --git a/deps/libtommath/mp_dr_is_modulus.c b/deps/libtommath/mp_dr_is_modulus.c new file mode 100644 index 0000000..72b3c96 --- /dev/null +++ b/deps/libtommath/mp_dr_is_modulus.c @@ -0,0 +1,27 @@ +#include "tommath_private.h" +#ifdef MP_DR_IS_MODULUS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if a number is a valid DR modulus */ +bool mp_dr_is_modulus(const mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return false; + } + + /* must be of the form b**k - a [a <= b] so all + * but the first digit must be equal to -1 (mod b). + */ + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return false; + } + } + return true; +} + +#endif diff --git a/deps/libtommath/mp_dr_reduce.c b/deps/libtommath/mp_dr_reduce.c new file mode 100644 index 0000000..f0f6f35 --- /dev/null +++ b/deps/libtommath/mp_dr_reduce.c @@ -0,0 +1,68 @@ +#include "tommath_private.h" +#ifdef MP_DR_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. + * + * Based on algorithm from the paper + * + * "Generating Efficient Primes for Discrete Log Cryptosystems" + * Chae Hoon Lim, Pil Joong Lee, + * POSTECH Information Research Laboratories + * + * The modulus must be of a special format [see manual] + * + * Has been modified to use algorithm 7.10 from the LTM book instead + * + * Input x must be in the range 0 <= x <= (n-1)**2 + */ +mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k) +{ + mp_err err; + + /* m = digits in modulus */ + int m = n->used; + + /* ensure that "x" has at least 2m digits */ + if ((err = mp_grow(x, m + m)) != MP_OKAY) { + return err; + } + + /* top of loop, this is where the code resumes if + * another reduction pass is required. + */ + for (;;) { + int i; + mp_digit mu = 0; + + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ + for (i = 0; i < m; i++) { + mp_word r = ((mp_word)x->dp[i + m] * (mp_word)k) + x->dp[i] + mu; + x->dp[i] = (mp_digit)(r & MP_MASK); + mu = (mp_digit)(r >> ((mp_word)MP_DIGIT_BIT)); + } + + /* set final carry */ + x->dp[i] = mu; + + /* zero words above m */ + s_mp_zero_digs(x->dp + m + 1, (x->used - m) - 1); + + /* clamp, sub and return */ + mp_clamp(x); + + /* if x >= n then subtract and reduce again + * Each successive "recursion" makes the input smaller and smaller. + */ + if (mp_cmp_mag(x, n) == MP_LT) { + break; + } + + if ((err = s_mp_sub(x, n, x)) != MP_OKAY) { + return err; + } + } + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_dr_setup.c b/deps/libtommath/mp_dr_setup.c new file mode 100644 index 0000000..c5bb359 --- /dev/null +++ b/deps/libtommath/mp_dr_setup.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_DR_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +void mp_dr_setup(const mp_int *a, mp_digit *d) +{ + /* the casts are required if MP_DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. MP_DIGIT_BIT==31] + */ + *d = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - (mp_word)a->dp[0]); +} + +#endif diff --git a/deps/libtommath/mp_error_to_string.c b/deps/libtommath/mp_error_to_string.c new file mode 100644 index 0000000..39adcd1 --- /dev/null +++ b/deps/libtommath/mp_error_to_string.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_ERROR_TO_STRING_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* return a char * string for a given code */ +const char *mp_error_to_string(mp_err code) +{ + switch (code) { + case MP_OKAY: + return "Successful"; + case MP_ERR: + return "Unknown error"; + case MP_MEM: + return "Out of heap"; + case MP_VAL: + return "Value out of range"; + case MP_ITER: + return "Max. iterations reached"; + case MP_BUF: + return "Buffer overflow"; + case MP_OVF: + return "Integer overflow"; + default: + return "Invalid error code"; + } +} + +#endif diff --git a/deps/libtommath/mp_exch.c b/deps/libtommath/mp_exch.c new file mode 100644 index 0000000..50b97d9 --- /dev/null +++ b/deps/libtommath/mp_exch.c @@ -0,0 +1,13 @@ +#include "tommath_private.h" +#ifdef MP_EXCH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +void mp_exch(mp_int *a, mp_int *b) +{ + MP_EXCH(mp_int, *a, *b); +} +#endif diff --git a/deps/libtommath/mp_expt_n.c b/deps/libtommath/mp_expt_n.c new file mode 100644 index 0000000..93f9249 --- /dev/null +++ b/deps/libtommath/mp_expt_n.c @@ -0,0 +1,43 @@ +#include "tommath_private.h" +#ifdef MP_EXPT_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* calculate c = a**b using a square-multiply algorithm */ +mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) +{ + mp_err err; + mp_int g; + + if ((err = mp_init_copy(&g, a)) != MP_OKAY) { + return err; + } + + /* set initial result */ + mp_set(c, 1uL); + + while (b > 0) { + /* if the bit is set multiply */ + if ((b & 1) != 0) { + if ((err = mp_mul(c, &g, c)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* square */ + if (b > 1) { + if ((err = mp_sqr(&g, &g)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* shift to next bit */ + b >>= 1; + } + +LBL_ERR: + mp_clear(&g); + return err; +} + +#endif diff --git a/deps/libtommath/mp_exptmod.c b/deps/libtommath/mp_exptmod.c new file mode 100644 index 0000000..eaab861 --- /dev/null +++ b/deps/libtommath/mp_exptmod.c @@ -0,0 +1,78 @@ +#include "tommath_private.h" +#ifdef MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted a lot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) +{ + int dr; + + /* modulus P must be positive */ + if (mp_isneg(P)) { + return MP_VAL; + } + + /* if exponent X is negative we have to recurse */ + if (mp_isneg(X)) { + mp_int tmpG, tmpX; + mp_err err; + + if (!MP_HAS(MP_INVMOD)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&tmpG, &tmpX, NULL)) != MP_OKAY) { + return err; + } + + /* first compute 1/G mod P */ + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + goto LBL_ERR; + } + + /* now get |X| */ + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + goto LBL_ERR; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); +LBL_ERR: + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + /* modified diminished radix reduction */ + if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) && + mp_reduce_is_2k_l(P)) { + return s_mp_exptmod(G, X, P, Y, 1); + } + + /* is it a DR modulus? default to no */ + dr = (MP_HAS(MP_DR_IS_MODULUS) && mp_dr_is_modulus(P)) ? 1 : 0; + + /* if not, is it a unrestricted DR modulus? */ + if (MP_HAS(MP_REDUCE_IS_2K) && (dr == 0)) { + dr = (mp_reduce_is_2k(P)) ? 2 : 0; + } + + /* if the modulus is odd or dr != 0 use the montgomery method */ + if (MP_HAS(S_MP_EXPTMOD_FAST) && (mp_isodd(P) || (dr != 0))) { + return s_mp_exptmod_fast(G, X, P, Y, dr); + } + + /* otherwise use the generic Barrett reduction technique */ + if (MP_HAS(S_MP_EXPTMOD)) { + return s_mp_exptmod(G, X, P, Y, 0); + } + + /* no exptmod for evens */ + return MP_VAL; +} + +#endif diff --git a/deps/libtommath/mp_exteuclid.c b/deps/libtommath/mp_exteuclid.c new file mode 100644 index 0000000..649c4ca --- /dev/null +++ b/deps/libtommath/mp_exteuclid.c @@ -0,0 +1,72 @@ +#include "tommath_private.h" +#ifdef MP_EXTEUCLID_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Extended euclidean algorithm of (a, b) produces + a*u1 + b*u2 = u3 + */ +mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) +{ + mp_int u1, u2, u3, v1, v2, v3, t1, t2, t3, q, tmp; + mp_err err; + + if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { + return err; + } + + /* initialize, (u1,u2,u3) = (1,0,a) */ + mp_set(&u1, 1uL); + if ((err = mp_copy(a, &u3)) != MP_OKAY) goto LBL_ERR; + + /* initialize, (v1,v2,v3) = (0,1,b) */ + mp_set(&v2, 1uL); + if ((err = mp_copy(b, &v3)) != MP_OKAY) goto LBL_ERR; + + /* loop while v3 != 0 */ + while (!mp_iszero(&v3)) { + /* q = u3/v3 */ + if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) goto LBL_ERR; + + /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ + if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) goto LBL_ERR; + + /* (u1,u2,u3) = (v1,v2,v3) */ + if ((err = mp_copy(&v1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&v3, &u3)) != MP_OKAY) goto LBL_ERR; + + /* (v1,v2,v3) = (t1,t2,t3) */ + if ((err = mp_copy(&t1, &v1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t2, &v2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&t3, &v3)) != MP_OKAY) goto LBL_ERR; + } + + /* make sure U3 >= 0 */ + if (mp_isneg(&u3)) { + if ((err = mp_neg(&u1, &u1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u2, &u2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_neg(&u3, &u3)) != MP_OKAY) goto LBL_ERR; + } + + /* copy result out */ + if (U1 != NULL) { + mp_exch(U1, &u1); + } + if (U2 != NULL) { + mp_exch(U2, &u2); + } + if (U3 != NULL) { + mp_exch(U3, &u3); + } + +LBL_ERR: + mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); + return err; +} +#endif diff --git a/deps/libtommath/mp_fread.c b/deps/libtommath/mp_fread.c new file mode 100644 index 0000000..53c35e8 --- /dev/null +++ b/deps/libtommath/mp_fread.c @@ -0,0 +1,66 @@ +#include "tommath_private.h" +#ifdef MP_FREAD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_NO_FILE +/* read a bigint from a file stream in ASCII */ +mp_err mp_fread(mp_int *a, int radix, FILE *stream) +{ + mp_err err; + mp_sign sign = MP_ZPOS; + int ch; + + /* make sure the radix is ok */ + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* if first digit is - then set negative */ + ch = fgetc(stream); + if (ch == (int)'-') { + sign = MP_NEG; + ch = fgetc(stream); + } + + /* no digits, return error */ + if (ch == EOF) { + return MP_ERR; + } + + /* clear a */ + mp_zero(a); + + do { + uint8_t y; + unsigned pos; + ch = (radix <= 36) ? MP_TOUPPER(ch) : ch; + pos = (unsigned)(ch - (int)'+'); + if (MP_RADIX_MAP_REVERSE_SIZE <= pos) { + break; + } + + y = s_mp_radix_map_reverse[pos]; + + if (y >= radix) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + } while ((ch = fgetc(stream)) != EOF); + + if (!mp_iszero(a)) { + a->sign = sign; + } + + return MP_OKAY; +} +#endif + +#endif diff --git a/deps/libtommath/mp_from_sbin.c b/deps/libtommath/mp_from_sbin.c new file mode 100644 index 0000000..26eb0f1 --- /dev/null +++ b/deps/libtommath/mp_from_sbin.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_FROM_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* read signed bin, big endian, first byte is 0==positive or 1==negative */ +mp_err mp_from_sbin(mp_int *a, const uint8_t *buf, size_t size) +{ + mp_err err; + + /* read magnitude */ + if ((err = mp_from_ubin(a, buf + 1, size - 1u)) != MP_OKAY) { + return err; + } + + /* first byte is 0 for positive, non-zero for negative */ + a->sign = (buf[0] != (uint8_t)0) ? MP_NEG : MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_from_ubin.c b/deps/libtommath/mp_from_ubin.c new file mode 100644 index 0000000..8272185 --- /dev/null +++ b/deps/libtommath/mp_from_ubin.c @@ -0,0 +1,30 @@ +#include "tommath_private.h" +#ifdef MP_FROM_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reads a uint8_t array, assumes the msb is stored first [big endian] */ +mp_err mp_from_ubin(mp_int *a, const uint8_t *buf, size_t size) +{ + mp_err err; + + /* make sure there are at least two digits */ + if ((err = mp_grow(a, 2)) != MP_OKAY) { + return err; + } + + /* zero the int */ + mp_zero(a); + + /* read the bytes in */ + while (size-- > 0u) { + if ((err = mp_mul_2d(a, 8, a)) != MP_OKAY) { + return err; + } + a->dp[0] |= *buf++; + a->used += 1; + } + mp_clamp(a); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_fwrite.c b/deps/libtommath/mp_fwrite.c new file mode 100644 index 0000000..8ea9d32 --- /dev/null +++ b/deps/libtommath/mp_fwrite.c @@ -0,0 +1,34 @@ +#include "tommath_private.h" +#ifdef MP_FWRITE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef MP_NO_FILE +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) +{ + char *buf; + mp_err err; + size_t size, written; + + if ((err = mp_radix_size_overestimate(a, radix, &size)) != MP_OKAY) { + return err; + } + + buf = (char *) MP_MALLOC(size); + if (buf == NULL) { + return MP_MEM; + } + + if ((err = mp_to_radix(a, buf, size, &written, radix)) == MP_OKAY) { + written--; + if (fwrite(buf, written, 1uL, stream) != 1uL) { + err = MP_ERR; + } + } + + MP_FREE_BUF(buf, size); + return err; +} +#endif + +#endif diff --git a/deps/libtommath/mp_gcd.c b/deps/libtommath/mp_gcd.c new file mode 100644 index 0000000..4f6b6cc --- /dev/null +++ b/deps/libtommath/mp_gcd.c @@ -0,0 +1,92 @@ +#include "tommath_private.h" +#ifdef MP_GCD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Greatest Common Divisor using the binary method */ +mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int u, v; + int k, u_lsb, v_lsb; + mp_err err; + + /* either zero than gcd is the largest */ + if (mp_iszero(a)) { + return mp_abs(b, c); + } + if (mp_iszero(b)) { + return mp_abs(a, c); + } + + /* get copies of a and b we can modify */ + if ((err = mp_init_copy(&u, a)) != MP_OKAY) { + return err; + } + + if ((err = mp_init_copy(&v, b)) != MP_OKAY) { + goto LBL_U; + } + + /* must be positive for the remainder of the algorithm */ + u.sign = v.sign = MP_ZPOS; + + /* B1. Find the common power of two for u and v */ + u_lsb = mp_cnt_lsb(&u); + v_lsb = mp_cnt_lsb(&v); + k = MP_MIN(u_lsb, v_lsb); + + if (k > 0) { + /* divide the power of two out */ + if ((err = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + + if ((err = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((err = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + if (v_lsb != k) { + if ((err = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + while (!mp_iszero(&v)) { + /* make sure v is the largest */ + if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ + mp_exch(&u, &v); + } + + /* subtract smallest from largest */ + if ((err = s_mp_sub(&v, &u, &v)) != MP_OKAY) { + goto LBL_V; + } + + /* Divide out all factors of two */ + if ((err = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* multiply by 2**k which we divided out at the beginning */ + if ((err = mp_mul_2d(&u, k, c)) != MP_OKAY) { + goto LBL_V; + } + c->sign = MP_ZPOS; + err = MP_OKAY; +LBL_V: + mp_clear(&u); +LBL_U: + mp_clear(&v); + return err; +} +#endif diff --git a/deps/libtommath/mp_get_double.c b/deps/libtommath/mp_get_double.c new file mode 100644 index 0000000..f462eb8 --- /dev/null +++ b/deps/libtommath/mp_get_double.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef MP_GET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +double mp_get_double(const mp_int *a) +{ + int i; + double d = 0.0, fac = 1.0; + for (i = 0; i < MP_DIGIT_BIT; ++i) { + fac *= 2.0; + } + for (i = a->used; i --> 0;) { + d = (d * fac) + (double)a->dp[i]; + } + return mp_isneg(a) ? -d : d; +} +#endif diff --git a/deps/libtommath/mp_get_i32.c b/deps/libtommath/mp_get_i32.c new file mode 100644 index 0000000..6b3b6ad --- /dev/null +++ b/deps/libtommath/mp_get_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i32, mp_get_mag_u32, int32_t, uint32_t) +#endif diff --git a/deps/libtommath/mp_get_i64.c b/deps/libtommath/mp_get_i64.c new file mode 100644 index 0000000..8d38a1f --- /dev/null +++ b/deps/libtommath/mp_get_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_i64, mp_get_mag_u64, int64_t, uint64_t) +#endif diff --git a/deps/libtommath/mp_get_l.c b/deps/libtommath/mp_get_l.c new file mode 100644 index 0000000..3a1a2f7 --- /dev/null +++ b/deps/libtommath/mp_get_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_SIGNED(mp_get_l, mp_get_mag_ul, long, unsigned long) +#endif diff --git a/deps/libtommath/mp_get_mag_u32.c b/deps/libtommath/mp_get_mag_u32.c new file mode 100644 index 0000000..acddc58 --- /dev/null +++ b/deps/libtommath/mp_get_mag_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_MAG_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u32, uint32_t) +#endif diff --git a/deps/libtommath/mp_get_mag_u64.c b/deps/libtommath/mp_get_mag_u64.c new file mode 100644 index 0000000..f754639 --- /dev/null +++ b/deps/libtommath/mp_get_mag_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_MAG_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_u64, uint64_t) +#endif diff --git a/deps/libtommath/mp_get_mag_ul.c b/deps/libtommath/mp_get_mag_ul.c new file mode 100644 index 0000000..5c60430 --- /dev/null +++ b/deps/libtommath/mp_get_mag_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_GET_MAG_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_GET_MAG(mp_get_mag_ul, unsigned long) +#endif diff --git a/deps/libtommath/mp_grow.c b/deps/libtommath/mp_grow.c new file mode 100644 index 0000000..5bca1b5 --- /dev/null +++ b/deps/libtommath/mp_grow.c @@ -0,0 +1,40 @@ +#include "tommath_private.h" +#ifdef MP_GROW_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* grow as required */ +mp_err mp_grow(mp_int *a, int size) +{ + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size) { + mp_digit *dp; + + if (size > MP_MAX_DIGIT_COUNT) { + return MP_OVF; + } + + /* reallocate the array a->dp + * + * We store the return in a temporary variable + * in case the operation failed we don't want + * to overwrite the dp member of a. + */ + dp = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)size * sizeof(mp_digit)); + if (dp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return MP_MEM; + } + + /* reallocation succeeded so set a->dp */ + a->dp = dp; + + /* zero excess digits */ + s_mp_zero_digs(a->dp + a->alloc, size - a->alloc); + a->alloc = size; + } + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_hash.c b/deps/libtommath/mp_hash.c new file mode 100644 index 0000000..2add757 --- /dev/null +++ b/deps/libtommath/mp_hash.c @@ -0,0 +1,36 @@ +#include "tommath_private.h" +#ifdef MP_HASH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if defined(MP_16BIT) +#define FNV_1A_INIT ((uint32_t)0x811c9dc5) +#define FNV_1A_PRIME ((uint32_t)0x01000193) +#else +#define FNV_1A_INIT ((uint64_t)0xcbf29ce484222325ULL) +#define FNV_1A_PRIME ((uint64_t)0x100000001b3ULL) +#endif + +/* computes hash of mp_int. */ +mp_err mp_hash(mp_int *a, mp_hval *hash) +{ + int x; + mp_hval hval = FNV_1A_INIT; + mp_digit r, mask, shift; + + /* FNV-1a algorithm */ + mask = ((mp_digit)1 << 8) - 1uL; + shift = (mp_digit)(MP_DIGIT_BIT - 8); + r = 0; + for (x = a->used; x --> 0;) { + mp_digit rr = a->dp[x] & mask; + hval ^= (mp_hval)(a->dp[x] >> 8) | (r << shift); + hval *= FNV_1A_PRIME; + r = rr; + } + hval ^= mp_isneg(a) ? (mp_hval)1 : (mp_hval)0; + *hash = hval * FNV_1A_PRIME; + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_init.c b/deps/libtommath/mp_init.c new file mode 100644 index 0000000..af16744 --- /dev/null +++ b/deps/libtommath/mp_init.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef MP_INIT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* init a new mp_int */ +mp_err mp_init(mp_int *a) +{ + /* allocate memory required and clear it */ + a->dp = (mp_digit *) MP_CALLOC((size_t)MP_DEFAULT_DIGIT_COUNT, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_DEFAULT_DIGIT_COUNT; + a->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_init_copy.c b/deps/libtommath/mp_init_copy.c new file mode 100644 index 0000000..4d0773b --- /dev/null +++ b/deps/libtommath/mp_init_copy.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_INIT_COPY_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* creates "a" then copies b into it */ +mp_err mp_init_copy(mp_int *a, const mp_int *b) +{ + mp_err err; + + if ((err = mp_init_size(a, b->used)) != MP_OKAY) { + return err; + } + + if ((err = mp_copy(b, a)) != MP_OKAY) { + mp_clear(a); + } + + return err; +} +#endif diff --git a/deps/libtommath/mp_init_i32.c b/deps/libtommath/mp_init_i32.c new file mode 100644 index 0000000..434788f --- /dev/null +++ b/deps/libtommath/mp_init_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i32, mp_set_i32, int32_t) +#endif diff --git a/deps/libtommath/mp_init_i64.c b/deps/libtommath/mp_init_i64.c new file mode 100644 index 0000000..7185678 --- /dev/null +++ b/deps/libtommath/mp_init_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_i64, mp_set_i64, int64_t) +#endif diff --git a/deps/libtommath/mp_init_l.c b/deps/libtommath/mp_init_l.c new file mode 100644 index 0000000..16be8f6 --- /dev/null +++ b/deps/libtommath/mp_init_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_l, mp_set_l, long) +#endif diff --git a/deps/libtommath/mp_init_multi.c b/deps/libtommath/mp_init_multi.c new file mode 100644 index 0000000..908b4df --- /dev/null +++ b/deps/libtommath/mp_init_multi.c @@ -0,0 +1,41 @@ +#include "tommath_private.h" +#ifdef MP_INIT_MULTI_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +mp_err mp_init_multi(mp_int *mp, ...) +{ + mp_err err = MP_OKAY; + int n = 0; /* Number of ok inits */ + mp_int *cur_arg = mp; + va_list args; + + va_start(args, mp); /* init args to next argument from caller */ + while (cur_arg != NULL) { + err = mp_init(cur_arg); + if (err != MP_OKAY) { + /* Oops - error! Back-track and mp_clear what we already + succeeded in init-ing, then return error. + */ + va_list clean_args; + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n-- != 0) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int *); + } + va_end(clean_args); + break; + } + n++; + cur_arg = va_arg(args, mp_int *); + } + va_end(args); + return err; +} + +#endif diff --git a/deps/libtommath/mp_init_set.c b/deps/libtommath/mp_init_set.c new file mode 100644 index 0000000..e1f2ee9 --- /dev/null +++ b/deps/libtommath/mp_init_set.c @@ -0,0 +1,16 @@ +#include "tommath_private.h" +#ifdef MP_INIT_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* initialize and set a digit */ +mp_err mp_init_set(mp_int *a, mp_digit b) +{ + mp_err err; + if ((err = mp_init(a)) != MP_OKAY) { + return err; + } + mp_set(a, b); + return err; +} +#endif diff --git a/deps/libtommath/mp_init_size.c b/deps/libtommath/mp_init_size.c new file mode 100644 index 0000000..e28a3cd --- /dev/null +++ b/deps/libtommath/mp_init_size.c @@ -0,0 +1,28 @@ +#include "tommath_private.h" +#ifdef MP_INIT_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* init an mp_init for a given size */ +mp_err mp_init_size(mp_int *a, int size) +{ + size = MP_MAX(MP_MIN_DIGIT_COUNT, size); + + if (size > MP_MAX_DIGIT_COUNT) { + return MP_OVF; + } + + /* alloc mem */ + a->dp = (mp_digit *) MP_CALLOC((size_t)size, sizeof(mp_digit)); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_init_u32.c b/deps/libtommath/mp_init_u32.c new file mode 100644 index 0000000..d5a2b8f --- /dev/null +++ b/deps/libtommath/mp_init_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u32, mp_set_u32, uint32_t) +#endif diff --git a/deps/libtommath/mp_init_u64.c b/deps/libtommath/mp_init_u64.c new file mode 100644 index 0000000..ca75084 --- /dev/null +++ b/deps/libtommath/mp_init_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_u64, mp_set_u64, uint64_t) +#endif diff --git a/deps/libtommath/mp_init_ul.c b/deps/libtommath/mp_init_ul.c new file mode 100644 index 0000000..21ca3be --- /dev/null +++ b/deps/libtommath/mp_init_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_INIT_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_INIT_INT(mp_init_ul, mp_set_ul, unsigned long) +#endif diff --git a/deps/libtommath/mp_invmod.c b/deps/libtommath/mp_invmod.c new file mode 100644 index 0000000..2494acb --- /dev/null +++ b/deps/libtommath/mp_invmod.c @@ -0,0 +1,29 @@ +#include "tommath_private.h" +#ifdef MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* hac 14.61, pp608 */ +mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + /* for all n in N and n > 0, n = 0 mod 1 */ + if (!mp_isneg(a) && mp_cmp_d(b, 1uL) == MP_EQ) { + mp_zero(c); + return MP_OKAY; + } + + /* b cannot be negative and has to be >1 */ + if (mp_isneg(b) || (mp_cmp_d(b, 1uL) != MP_GT)) { + return MP_VAL; + } + + /* if the modulus is odd we can use a faster routine instead */ + if (MP_HAS(S_MP_INVMOD_ODD) && mp_isodd(b)) { + return s_mp_invmod_odd(a, b, c); + } + + return MP_HAS(S_MP_INVMOD) + ? s_mp_invmod(a, b, c) + : MP_VAL; +} +#endif diff --git a/deps/libtommath/mp_is_square.c b/deps/libtommath/mp_is_square.c new file mode 100644 index 0000000..d2856e2 --- /dev/null +++ b/deps/libtommath/mp_is_square.c @@ -0,0 +1,94 @@ +#include "tommath_private.h" +#ifdef MP_IS_SQUARE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Check if remainders are possible squares - fast exclude non-squares */ +static const char rem_128[128] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 +}; + +static const char rem_105[105] = { + 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 +}; + +/* Store non-zero to ret if arg is square, and zero if not */ +mp_err mp_is_square(const mp_int *arg, bool *ret) +{ + mp_err err; + mp_digit c; + mp_int t; + uint32_t r; + + /* Default to Non-square :) */ + *ret = false; + + if (mp_isneg(arg)) { + return MP_VAL; + } + + if (mp_iszero(arg)) { + *ret = true; + return MP_OKAY; + } + + /* First check mod 128 (suppose that MP_DIGIT_BIT is at least 7) */ + if (rem_128[127u & arg->dp[0]] == (char)1) { + return MP_OKAY; + } + + /* Next check mod 105 (3*5*7) */ + if ((err = mp_mod_d(arg, 105uL, &c)) != MP_OKAY) { + return err; + } + if (rem_105[c] == (char)1) { + return MP_OKAY; + } + + + if ((err = mp_init_u32(&t, 11u*13u*17u*19u*23u*29u*31u)) != MP_OKAY) { + return err; + } + if ((err = mp_mod(arg, &t, &t)) != MP_OKAY) { + goto LBL_ERR; + } + r = mp_get_u32(&t); + /* Check for other prime modules, note it's not an ERROR but we must + * free "t" so the easiest way is to goto LBL_ERR. We know that err + * is already equal to MP_OKAY from the mp_mod call + */ + if (((1uL<<(r%11uL)) & 0x5C4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%13uL)) & 0x9E4uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%17uL)) & 0x5CE8uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%19uL)) & 0x4F50CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%23uL)) & 0x7ACCA0uL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%29uL)) & 0xC2EDD0CuL) != 0uL) goto LBL_ERR; + if (((1uL<<(r%31uL)) & 0x6DE2B848uL) != 0uL) goto LBL_ERR; + + /* Final check - is sqr(sqrt(arg)) == arg ? */ + if ((err = mp_sqrt(arg, &t)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_sqr(&t, &t)) != MP_OKAY) { + goto LBL_ERR; + } + + *ret = (mp_cmp_mag(&t, arg) == MP_EQ); +LBL_ERR: + mp_clear(&t); + return err; +} +#endif diff --git a/deps/libtommath/mp_kronecker.c b/deps/libtommath/mp_kronecker.c new file mode 100644 index 0000000..e6bedc8 --- /dev/null +++ b/deps/libtommath/mp_kronecker.c @@ -0,0 +1,129 @@ +#include "tommath_private.h" +#ifdef MP_KRONECKER_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + Kronecker symbol (a|p) + Straightforward implementation of algorithm 1.4.10 in + Henri Cohen: "A Course in Computational Algebraic Number Theory" + + @book{cohen2013course, + title={A course in computational algebraic number theory}, + author={Cohen, Henri}, + volume={138}, + year={2013}, + publisher={Springer Science \& Business Media} + } + */ +mp_err mp_kronecker(const mp_int *a, const mp_int *p, int *c) +{ + mp_int a1, p1, r; + mp_err err; + int v, k; + + static const char table[] = {0, 1, 0, -1, 0, -1, 0, 1}; + + if (mp_iszero(p)) { + if ((a->used == 1) && (a->dp[0] == 1u)) { + *c = 1; + } else { + *c = 0; + } + return MP_OKAY; + } + + if (mp_iseven(a) && mp_iseven(p)) { + *c = 0; + return MP_OKAY; + } + + if ((err = mp_init_copy(&a1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_init_copy(&p1, p)) != MP_OKAY) { + goto LBL_KRON_0; + } + + v = mp_cnt_lsb(&p1); + if ((err = mp_div_2d(&p1, v, &p1, NULL)) != MP_OKAY) { + goto LBL_KRON_1; + } + + if ((v & 1) == 0) { + k = 1; + } else { + k = table[a->dp[0] & 7u]; + } + + if (mp_isneg(&p1)) { + p1.sign = MP_ZPOS; + if (mp_isneg(&a1)) { + k = -k; + } + } + + if ((err = mp_init(&r)) != MP_OKAY) { + goto LBL_KRON_1; + } + + for (;;) { + if (mp_iszero(&a1)) { + if (mp_cmp_d(&p1, 1uL) == MP_EQ) { + *c = k; + goto LBL_KRON; + } else { + *c = 0; + goto LBL_KRON; + } + } + + v = mp_cnt_lsb(&a1); + if ((err = mp_div_2d(&a1, v, &a1, NULL)) != MP_OKAY) { + goto LBL_KRON; + } + + if ((v & 1) == 1) { + k = k * table[p1.dp[0] & 7u]; + } + + if (mp_isneg(&a1)) { + /* + * Compute k = (-1)^((a1)*(p1-1)/4) * k + * a1.dp[0] + 1 cannot overflow because the MSB + * of the type mp_digit is not set by definition + */ + if (((a1.dp[0] + 1u) & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } else { + /* compute k = (-1)^((a1-1)*(p1-1)/4) * k */ + if ((a1.dp[0] & p1.dp[0] & 2u) != 0u) { + k = -k; + } + } + + if ((err = mp_copy(&a1, &r)) != MP_OKAY) { + goto LBL_KRON; + } + r.sign = MP_ZPOS; + if ((err = mp_mod(&p1, &r, &a1)) != MP_OKAY) { + goto LBL_KRON; + } + if ((err = mp_copy(&r, &p1)) != MP_OKAY) { + goto LBL_KRON; + } + } + +LBL_KRON: + mp_clear(&r); +LBL_KRON_1: + mp_clear(&p1); +LBL_KRON_0: + mp_clear(&a1); + + return err; +} + +#endif diff --git a/deps/libtommath/mp_lcm.c b/deps/libtommath/mp_lcm.c new file mode 100644 index 0000000..f2044f0 --- /dev/null +++ b/deps/libtommath/mp_lcm.c @@ -0,0 +1,44 @@ +#include "tommath_private.h" +#ifdef MP_LCM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes least common multiple as |a*b|/(a, b) */ +mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + mp_int t1, t2; + + + if ((err = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) { + return err; + } + + /* t1 = get the GCD of the two inputs */ + if ((err = mp_gcd(a, b, &t1)) != MP_OKAY) { + goto LBL_T; + } + + /* divide the smallest by the GCD */ + if (mp_cmp_mag(a, b) == MP_LT) { + /* store quotient in t2 such that t2 * b is the LCM */ + if ((err = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(b, &t2, c); + } else { + /* store quotient in t2 such that t2 * a is the LCM */ + if ((err = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + err = mp_mul(a, &t2, c); + } + + /* fix the sign to positive */ + c->sign = MP_ZPOS; + +LBL_T: + mp_clear_multi(&t1, &t2, NULL); + return err; +} +#endif diff --git a/deps/libtommath/mp_log.c b/deps/libtommath/mp_log.c new file mode 100644 index 0000000..0d5d893 --- /dev/null +++ b/deps/libtommath/mp_log.c @@ -0,0 +1,168 @@ +#include "tommath_private.h" +#ifdef MP_LOG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define MP_LOG2_EXPT(a,b) ((mp_count_bits((a)) - 1) / mp_cnt_lsb((b))) + +static mp_err s_approx_log_d(const mp_int *a, const mp_int *b, int *lb) +{ + mp_word La, Lb; + mp_err err; + + /* Approximation of the individual logarithms with low precision */ + if ((err = s_mp_fp_log_d(a, &La)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_fp_log_d(b, &Lb)) != MP_OKAY) goto LTM_ERR; + + /* Approximation of log_b(a) with low precision. */ + *lb = (int)(((La - (Lb + 1)/2) / Lb) + 1); + /* TODO: just floor it instead? Multiplication is cheaper than division. */ + /* *lb = (int)(la_word / lb_word); */ + err = MP_OKAY; +LTM_ERR: + return err; +} + +static mp_err s_approx_log(const mp_int *a, const mp_int *b, int *lb) +{ + mp_int La, Lb, t; + mp_err err; + + if ((err = mp_init_multi(&La, &Lb, &t, NULL)) != MP_OKAY) { + return err; + } + + if ((err = s_mp_fp_log(a, &La)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_fp_log(b, &Lb)) != MP_OKAY) goto LTM_ERR; + + if ((err = mp_add_d(&Lb, 1u, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div_2(&t, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_sub(&La, &t, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div(&t, &Lb, &t, NULL)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_add_d(&t, 1u, &t)) != MP_OKAY) goto LTM_ERR; + + *lb = mp_get_i32(&t); + err = MP_OKAY; +LTM_ERR: + mp_clear_multi(&t, &Lb, &La, NULL); + return err; +} + +mp_err mp_log(const mp_int *a, const mp_int *b, int *lb) +{ + mp_int bn; + int n, fla, flb; + mp_err err; + mp_ord cmp; + + if (mp_isneg(a) || mp_iszero(a) || (mp_cmp_d(b, 2u) == MP_LT)) { + return MP_VAL; + } + + if (MP_IS_POWER_OF_TWO(b)) { + *lb = MP_LOG2_EXPT(a, b); + return MP_OKAY; + } + + /* floor(log_2(x)) for cut-off */ + fla = mp_count_bits(a) - 1; + flb = mp_count_bits(b) - 1; + + cmp = mp_cmp(a, b); + + /* "a < b -> 0" and "(b == a) -> 1" */ + if ((cmp == MP_LT) || (cmp == MP_EQ)) { + *lb = (cmp == MP_EQ); + return MP_OKAY; + } + + /* "a < b^2 -> 1" (bit-count is sufficient, doesn't need to be exact) */ + if (((2 * flb)-1) > fla) { + *lb = 1; + return MP_OKAY; + } + + if (MP_HAS(S_MP_WORD_TOO_SMALL)) { + err = s_approx_log(a, b, &n); + } else { + err = s_approx_log_d(a, b, &n); + } + if (err != MP_OKAY) { + return err; + } + + if ((err = mp_init(&bn)) != MP_OKAY) { + return err; + } + + /* Check result. Result is wrong by 2(two) at most. */ + if ((err = mp_expt_n(b, n, &bn)) != MP_OKAY) { + /* If the approximation overshot we can give it another try */ + if (err == MP_OVF) { + n--; + /* But only one */ + if ((err = mp_expt_n(b, n, &bn)) != MP_OKAY) goto LTM_ERR; + } else { + goto LTM_ERR; + } + } + + cmp = mp_cmp(&bn, a); + + /* The rare case of a perfect power makes a perfect shortcut, too. */ + if (cmp == MP_EQ) { + *lb = n; + goto LTM_OUT; + } + + /* We have to make at least one multiplication because it could still be a perfect power. */ + if (cmp == MP_LT) { + do { + /* Full big-integer operations are to be avoided if possible */ + if (b->used == 1) { + if ((err = mp_mul_d(&bn, b->dp[0], &bn)) != MP_OKAY) { + if (err == MP_OVF) { + goto LTM_OUT; + } + goto LTM_ERR; + } + } else { + if ((err = mp_mul(&bn, b, &bn)) != MP_OKAY) { + if (err == MP_OVF) { + goto LTM_OUT; + } + goto LTM_ERR; + } + } + n++; + } while ((cmp = mp_cmp(&bn, a)) == MP_LT); + /* Overshot, take it back. */ + if (cmp == MP_GT) { + n--; + } + goto LTM_OUT; + } + + /* But it can overestimate, too, for example if "a" is closely below some "b^k" */ + if (cmp == MP_GT) { + do { + if (b->used == 1) { + /* These are cheaper exact divisions, but that function is not available in LTM */ + if ((err = mp_div_d(&bn, b->dp[0], &bn, NULL)) != MP_OKAY) goto LTM_ERR; + + } else { + if ((err = mp_div(&bn, b, &bn, NULL)) != MP_OKAY) goto LTM_ERR; + } + n--; + } while ((cmp = mp_cmp(&bn, a)) == MP_GT); + } + +LTM_OUT: + *lb = n; + err = MP_OKAY; +LTM_ERR: + mp_clear(&bn); + return err; +} + +#endif diff --git a/deps/libtommath/mp_log_n.c b/deps/libtommath/mp_log_n.c new file mode 100644 index 0000000..364e28a --- /dev/null +++ b/deps/libtommath/mp_log_n.c @@ -0,0 +1,19 @@ +#include "tommath_private.h" +#ifdef MP_LOG_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_log_n(const mp_int *a, int base, int *c) +{ + mp_int b; + mp_err err; + + if ((err = mp_init_i32(&b, base)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_log(a, &b, c)) != MP_OKAY) goto LTM_ERR; + +LTM_ERR: + mp_clear(&b); + return err; +} + +#endif diff --git a/deps/libtommath/mp_lshd.c b/deps/libtommath/mp_lshd.c new file mode 100644 index 0000000..90014e4 --- /dev/null +++ b/deps/libtommath/mp_lshd.c @@ -0,0 +1,42 @@ +#include "tommath_private.h" +#ifdef MP_LSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift left a certain amount of digits */ +mp_err mp_lshd(mp_int *a, int b) +{ + mp_err err; + int x; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + /* no need to shift 0 around */ + if (mp_iszero(a)) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if ((err = mp_grow(a, a->used + b)) != MP_OKAY) { + return err; + } + + /* increment the used by the shift amount then copy upwards */ + a->used += b; + + /* much like mp_rshd this is implemented using a sliding window + * except the window goes the other way around. Copying from + * the bottom to the top. see mp_rshd.c for more info. + */ + for (x = a->used; x --> b;) { + a->dp[x] = a->dp[x - b]; + } + + /* zero the lower digits */ + s_mp_zero_digs(a->dp, b); + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_mod.c b/deps/libtommath/mp_mod.c new file mode 100644 index 0000000..beae13e --- /dev/null +++ b/deps/libtommath/mp_mod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_MOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = a mod b, 0 <= c < b if b > 0, b < c <= 0 if b < 0 */ +mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + if ((err = mp_div(a, b, NULL, c)) != MP_OKAY) { + return err; + } + return mp_iszero(c) || (c->sign == b->sign) ? MP_OKAY : mp_add(b, c, c); +} +#endif diff --git a/deps/libtommath/mp_mod_2d.c b/deps/libtommath/mp_mod_2d.c new file mode 100644 index 0000000..82c64f0 --- /dev/null +++ b/deps/libtommath/mp_mod_2d.c @@ -0,0 +1,40 @@ +#include "tommath_private.h" +#ifdef MP_MOD_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* calc a value mod 2**b */ +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) +{ + int x; + mp_err err; + + if (b < 0) { + return MP_VAL; + } + + if (b == 0) { + mp_zero(c); + return MP_OKAY; + } + + /* if the modulus is larger than the value than return */ + if (b >= (a->used * MP_DIGIT_BIT)) { + return mp_copy(a, c); + } + + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + + /* zero digits above the last digit of the modulus */ + x = (b / MP_DIGIT_BIT) + (((b % MP_DIGIT_BIT) == 0) ? 0 : 1); + s_mp_zero_digs(c->dp + x, c->used - x); + + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / MP_DIGIT_BIT] &= + ((mp_digit)1 << (mp_digit)(b % MP_DIGIT_BIT)) - (mp_digit)1; + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_montgomery_calc_normalization.c b/deps/libtommath/mp_montgomery_calc_normalization.c new file mode 100644 index 0000000..bbb3adb --- /dev/null +++ b/deps/libtommath/mp_montgomery_calc_normalization.c @@ -0,0 +1,43 @@ +#include "tommath_private.h" +#ifdef MP_MONTGOMERY_CALC_NORMALIZATION_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally upto just under + * the leading bit of b. This saves a lot of multiple precision shifting. + */ +mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b) +{ + int x, bits; + mp_err err; + + /* how many bits of last digit does b use */ + bits = mp_count_bits(b) % MP_DIGIT_BIT; + + if (b->used > 1) { + if ((err = mp_2expt(a, ((b->used - 1) * MP_DIGIT_BIT) + bits - 1)) != MP_OKAY) { + return err; + } + } else { + mp_set(a, 1uL); + bits = 1; + } + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)MP_DIGIT_BIT; x++) { + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + return err; + } + if (mp_cmp_mag(a, b) != MP_LT) { + if ((err = s_mp_sub(a, b, a)) != MP_OKAY) { + return err; + } + } + } + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_montgomery_reduce.c b/deps/libtommath/mp_montgomery_reduce.c new file mode 100644 index 0000000..dbf45d3 --- /dev/null +++ b/deps/libtommath/mp_montgomery_reduce.c @@ -0,0 +1,89 @@ +#include "tommath_private.h" +#ifdef MP_MONTGOMERY_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) +{ + mp_err err; + int ix, digs; + + /* can the fast reduction [comba] method be used? + * + * Note that unlike in mul you're safely allowed *less* + * than the available columns [255 per default] since carries + * are fixed up in the inner loop. + */ + digs = (n->used * 2) + 1; + if ((digs < MP_WARRAY) && + (x->used <= MP_WARRAY) && + (n->used < MP_MAX_COMBA)) { + return s_mp_montgomery_reduce_comba(x, n, rho); + } + + /* grow the input as required */ + if ((err = mp_grow(x, digs)) != MP_OKAY) { + return err; + } + x->used = digs; + + for (ix = 0; ix < n->used; ix++) { + int iy; + mp_digit u, mu; + + /* mu = ai * rho mod b + * + * The value of rho must be precalculated via + * montgomery_setup() such that + * it equals -1/n0 mod b this allows the + * following inner loop to reduce the + * input one digit at a time + */ + mu = (mp_digit)(((mp_word)x->dp[ix] * (mp_word)rho) & MP_MASK); + + /* a = a + mu * m * b**i */ + + /* Multiply and add in place */ + u = 0; + for (iy = 0; iy < n->used; iy++) { + /* compute product and sum */ + mp_word r = ((mp_word)mu * (mp_word)n->dp[iy]) + + (mp_word)u + (mp_word)x->dp[ix + iy]; + + /* get carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + + /* fix digit */ + x->dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + } + /* At this point the ix'th digit of x should be zero */ + + /* propagate carries upwards as required*/ + while (u != 0u) { + x->dp[ix + iy] += u; + u = x->dp[ix + iy] >> MP_DIGIT_BIT; + x->dp[ix + iy] &= MP_MASK; + ++iy; + } + } + + /* at this point the n.used'th least + * significant digits of x are all zero + * which means we can shift x to the + * right by n.used digits and the + * residue is unchanged. + */ + + /* x = x/b**n.used */ + mp_clamp(x); + mp_rshd(x, n->used); + + /* if x >= n then x = x - n */ + if (mp_cmp_mag(x, n) != MP_LT) { + return s_mp_sub(x, n, x); + } + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_montgomery_setup.c b/deps/libtommath/mp_montgomery_setup.c new file mode 100644 index 0000000..de57dc3 --- /dev/null +++ b/deps/libtommath/mp_montgomery_setup.c @@ -0,0 +1,40 @@ +#include "tommath_private.h" +#ifdef MP_MONTGOMERY_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* setups the montgomery reduction stuff */ +mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho) +{ + mp_digit x, b; + + /* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = n->dp[0]; + + if ((b & 1u) == 0u) { + return MP_VAL; + } + + x = (((b + 2u) & 4u) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2u - (b * x); /* here x*a==1 mod 2**8 */ + x *= 2u - (b * x); /* here x*a==1 mod 2**16 */ +#if defined(MP_64BIT) || !(defined(MP_16BIT)) + x *= 2u - (b * x); /* here x*a==1 mod 2**32 */ +#endif +#ifdef MP_64BIT + x *= 2u - (b * x); /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + *rho = (mp_digit)(((mp_word)1 << (mp_word)MP_DIGIT_BIT) - x) & MP_MASK; + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_mul.c b/deps/libtommath/mp_mul.c new file mode 100644 index 0000000..8180740 --- /dev/null +++ b/deps/libtommath/mp_mul.c @@ -0,0 +1,68 @@ +#include "tommath_private.h" +#ifdef MP_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level multiplication (handles sign) */ +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + int min = MP_MIN(a->used, b->used), + max = MP_MAX(a->used, b->used), + digs = a->used + b->used + 1; + bool neg = (a->sign != b->sign); + + if ((a == b) && + MP_HAS(S_MP_SQR_TOOM) && /* use Toom-Cook? */ + (a->used >= MP_SQR_TOOM_CUTOFF)) { + err = s_mp_sqr_toom(a, c); + } else if ((a == b) && + MP_HAS(S_MP_SQR_KARATSUBA) && /* Karatsuba? */ + (a->used >= MP_SQR_KARATSUBA_CUTOFF)) { + err = s_mp_sqr_karatsuba(a, c); + } else if ((a == b) && + MP_HAS(S_MP_SQR_COMBA) && /* can we use the fast comba multiplier? */ + (((a->used * 2) + 1) < MP_WARRAY) && + (a->used <= MP_MAX_COMBA)) { + err = s_mp_sqr_comba(a, c); + } else if ((a == b) && + MP_HAS(S_MP_SQR)) { + err = s_mp_sqr(a, c); + } else if (MP_HAS(S_MP_MUL_BALANCE) && + /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off. + * The bigger one needs to be at least about one MP_MUL_KARATSUBA_CUTOFF bigger + * to make some sense, but it depends on architecture, OS, position of the + * stars... so YMMV. + * Using it to cut the input into slices small enough for s_mp_mul_comba + * was actually slower on the author's machine, but YMMV. + */ + (min >= MP_MUL_KARATSUBA_CUTOFF) && + ((max / 2) >= MP_MUL_KARATSUBA_CUTOFF) && + /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */ + (max >= (2 * min))) { + err = s_mp_mul_balance(a,b,c); + } else if (MP_HAS(S_MP_MUL_TOOM) && + (min >= MP_MUL_TOOM_CUTOFF)) { + err = s_mp_mul_toom(a, b, c); + } else if (MP_HAS(S_MP_MUL_KARATSUBA) && + (min >= MP_MUL_KARATSUBA_CUTOFF)) { + err = s_mp_mul_karatsuba(a, b, c); + } else if (MP_HAS(S_MP_MUL_COMBA) && + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + (digs < MP_WARRAY) && + (min <= MP_MAX_COMBA)) { + err = s_mp_mul_comba(a, b, c, digs); + } else if (MP_HAS(S_MP_MUL)) { + err = s_mp_mul(a, b, c, digs); + } else { + err = MP_VAL; + } + c->sign = ((c->used > 0) && neg) ? MP_NEG : MP_ZPOS; + return err; +} +#endif diff --git a/deps/libtommath/mp_mul_2.c b/deps/libtommath/mp_mul_2.c new file mode 100644 index 0000000..459fbd2 --- /dev/null +++ b/deps/libtommath/mp_mul_2.c @@ -0,0 +1,53 @@ +#include "tommath_private.h" +#ifdef MP_MUL_2_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = a*2 */ +mp_err mp_mul_2(const mp_int *a, mp_int *b) +{ + mp_err err; + int x, oldused; + mp_digit r; + + /* grow to accommodate result */ + if ((err = mp_grow(b, a->used + 1)) != MP_OKAY) { + return err; + } + + oldused = b->used; + b->used = a->used; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + mp_digit rr = a->dp[x] >> (mp_digit)(MP_DIGIT_BIT - 1); + + /* now shift up this digit, add in the carry [from the previous] */ + b->dp[x] = ((a->dp[x] << 1uL) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0u) { + /* add a MSB which is always 1 at this point */ + b->dp[b->used++] = 1; + } + + /* now zero any excess digits on the destination + * that we didn't write to + */ + s_mp_zero_digs(b->dp + b->used, oldused - b->used); + + b->sign = a->sign; + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_mul_2d.c b/deps/libtommath/mp_mul_2d.c new file mode 100644 index 0000000..e458137 --- /dev/null +++ b/deps/libtommath/mp_mul_2d.c @@ -0,0 +1,63 @@ +#include "tommath_private.h" +#ifdef MP_MUL_2D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift left by a certain bit count */ +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) +{ + mp_err err; + + if (b < 0) { + return MP_VAL; + } + + if ((err = mp_copy(a, c)) != MP_OKAY) { + return err; + } + + if ((err = mp_grow(c, c->used + (b / MP_DIGIT_BIT) + 1)) != MP_OKAY) { + return err; + } + + /* shift by as many digits in the bit count */ + if (b >= MP_DIGIT_BIT) { + if ((err = mp_lshd(c, b / MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + } + + /* shift any bit count < MP_DIGIT_BIT */ + b %= MP_DIGIT_BIT; + if (b != 0u) { + mp_digit shift, mask, r; + int x; + + /* bitmask for carries */ + mask = ((mp_digit)1 << b) - (mp_digit)1; + + /* shift for msbs */ + shift = (mp_digit)(MP_DIGIT_BIT - b); + + /* carry */ + r = 0; + for (x = 0; x < c->used; x++) { + /* get the higher bits of the current word */ + mp_digit rr = (c->dp[x] >> shift) & mask; + + /* shift the current word and OR in the carry */ + c->dp[x] = ((c->dp[x] << b) | r) & MP_MASK; + + /* set the carry to the carry bits of the current word */ + r = rr; + } + + /* set final carry */ + if (r != 0u) { + c->dp[(c->used)++] = r; + } + } + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_mul_d.c b/deps/libtommath/mp_mul_d.c new file mode 100644 index 0000000..2585055 --- /dev/null +++ b/deps/libtommath/mp_mul_d.c @@ -0,0 +1,68 @@ +#include "tommath_private.h" +#ifdef MP_MUL_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiply by a digit */ +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_digit u; + mp_err err; + int ix, oldused; + + if (b == 1u) { + return mp_copy(a, c); + } + + /* power of two ? */ + if (MP_HAS(MP_MUL_2) && (b == 2u)) { + return mp_mul_2(a, c); + } + if (MP_HAS(MP_MUL_2D) && MP_IS_2EXPT(b)) { + ix = 1; + while ((ix < MP_DIGIT_BIT) && (b != (((mp_digit)1)<used + 1)) != MP_OKAY) { + return err; + } + + /* get the original destinations used count */ + oldused = c->used; + + /* set the sign */ + c->sign = a->sign; + + /* zero carry */ + u = 0; + + /* compute columns */ + for (ix = 0; ix < a->used; ix++) { + /* compute product and carry sum for this term */ + mp_word r = (mp_word)u + ((mp_word)a->dp[ix] * (mp_word)b); + + /* mask off higher bits to get a single digit */ + c->dp[ix] = (mp_digit)(r & (mp_word)MP_MASK); + + /* send carry into next iteration */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + + /* store final carry [if any] and increment ix offset */ + c->dp[ix] = u; + + /* set used count */ + c->used = a->used + 1; + + /* now zero digits above the top */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_mulmod.c b/deps/libtommath/mp_mulmod.c new file mode 100644 index 0000000..e158693 --- /dev/null +++ b/deps/libtommath/mp_mulmod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_MULMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a * b (mod c) */ +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + if ((err = mp_mul(a, b, d)) != MP_OKAY) { + return err; + } + return mp_mod(d, c, d); +} +#endif diff --git a/deps/libtommath/mp_neg.c b/deps/libtommath/mp_neg.c new file mode 100644 index 0000000..b445cd4 --- /dev/null +++ b/deps/libtommath/mp_neg.c @@ -0,0 +1,18 @@ +#include "tommath_private.h" +#ifdef MP_NEG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* b = -a */ +mp_err mp_neg(const mp_int *a, mp_int *b) +{ + mp_err err; + if ((err = mp_copy(a, b)) != MP_OKAY) { + return err; + } + + b->sign = ((!mp_iszero(b) && !mp_isneg(b)) ? MP_NEG : MP_ZPOS); + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_or.c b/deps/libtommath/mp_or.c new file mode 100644 index 0000000..1595852 --- /dev/null +++ b/deps/libtommath/mp_or.c @@ -0,0 +1,54 @@ +#include "tommath_private.h" +#ifdef MP_OR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement or */ +mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + bool neg = (mp_isneg(a) || mp_isneg(b)); + + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (mp_isneg(a)) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (mp_isneg(b)) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x | y; + + /* convert to to sign-magnitude if negative */ + if (neg) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = (neg ? MP_NEG : MP_ZPOS); + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_pack.c b/deps/libtommath/mp_pack.c new file mode 100644 index 0000000..447f1fd --- /dev/null +++ b/deps/libtommath/mp_pack.c @@ -0,0 +1,69 @@ +#include "tommath_private.h" +#ifdef MP_PACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_export. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j, count; + uint8_t odd_nail_mask; + + mp_int t; + + count = mp_pack_count(op, nails, size); + + if (count > maxcount) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, op)) != MP_OKAY) { + return err; + } + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0u; i < odd_nails; ++i) { + odd_nail_mask ^= (uint8_t)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0u; i < count; ++i) { + for (j = 0u; j < size; ++j) { + uint8_t *byte = (uint8_t *)rop + + (((order == MP_LSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_LITTLE_ENDIAN) ? j : ((size - 1u) - j)); + + if (j >= (size - nail_bytes)) { + *byte = 0; + continue; + } + + *byte = (uint8_t)((j == ((size - nail_bytes) - 1u)) ? (t.dp[0] & odd_nail_mask) : (t.dp[0] & 0xFFuL)); + + if ((err = mp_div_2d(&t, (j == ((size - nail_bytes) - 1u)) ? (int)(8u - odd_nails) : 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + } + } + + if (written != NULL) { + *written = count; + } + err = MP_OKAY; + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif diff --git a/deps/libtommath/mp_pack_count.c b/deps/libtommath/mp_pack_count.c new file mode 100644 index 0000000..aa682ba --- /dev/null +++ b/deps/libtommath/mp_pack_count.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef MP_PACK_COUNT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) +{ + size_t bits = (size_t)mp_count_bits(a); + return ((bits / ((size * 8u) - nails)) + (((bits % ((size * 8u) - nails)) != 0u) ? 1u : 0u)); +} + +#endif diff --git a/deps/libtommath/mp_prime_fermat.c b/deps/libtommath/mp_prime_fermat.c new file mode 100644 index 0000000..ac8116f --- /dev/null +++ b/deps/libtommath/mp_prime_fermat.c @@ -0,0 +1,41 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_FERMAT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* performs one Fermat test. + * + * If "a" were prime then b**a == b (mod a) since the order of + * the multiplicative sub-group would be phi(a) = a-1. That means + * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a). + * + * Sets result to 1 if the congruence holds, or zero otherwise. + */ +mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, bool *result) +{ + mp_int t; + mp_err err; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != MP_GT) { + return MP_VAL; + } + + /* init t */ + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + /* compute t = b**a mod a */ + if ((err = mp_exptmod(b, a, a, &t)) != MP_OKAY) { + goto LBL_ERR; + } + + /* is it equal to b? */ + *result = mp_cmp(&t, b) == MP_EQ; + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif diff --git a/deps/libtommath/mp_prime_frobenius_underwood.c b/deps/libtommath/mp_prime_frobenius_underwood.c new file mode 100644 index 0000000..62d3476 --- /dev/null +++ b/deps/libtommath/mp_prime_frobenius_underwood.c @@ -0,0 +1,127 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_FROBENIUS_UNDERWOOD_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +/* + * floor of positive solution of + * (2^16)-1 = (a+4)*(2*a+5) + * TODO: Both values are smaller than N^(1/4), would have to use a bigint + * for a instead but any a biger than about 120 are already so rare that + * it is possible to ignore them and still get enough pseudoprimes. + * But it is still a restriction of the set of available pseudoprimes + * which makes this implementation less secure if used stand-alone. + */ +#define LTM_FROBENIUS_UNDERWOOD_A 32764 + +mp_err mp_prime_frobenius_underwood(const mp_int *N, bool *result) +{ + mp_int T1z, T2z, Np1z, sz, tz; + int a, ap2, i; + mp_err err; + + if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) { + return err; + } + + for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) { + int j; + + /* TODO: That's ugly! No, really, it is! */ + if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) || + (a==14) || (a==18) || (a==23) || (a==26) || (a==28)) { + continue; + } + + mp_set_i32(&T1z, (int32_t)((a * a) - 4)); + + if ((err = mp_kronecker(&T1z, N, &j)) != MP_OKAY) goto LBL_END; + + if (j == -1) { + break; + } + + if (j == 0) { + /* composite */ + *result = false; + goto LBL_END; + } + } + /* Tell it a composite and set return value accordingly */ + if (a >= LTM_FROBENIUS_UNDERWOOD_A) { + err = MP_ITER; + goto LBL_END; + } + /* Composite if N and (a+4)*(2*a+5) are not coprime */ + mp_set_u32(&T1z, (uint32_t)((a+4)*((2*a)+5))); + + if ((err = mp_gcd(N, &T1z, &T1z)) != MP_OKAY) goto LBL_END; + + if (!((T1z.used == 1) && (T1z.dp[0] == 1u))) { + /* composite */ + *result = false; + goto LBL_END; + } + + ap2 = a + 2; + if ((err = mp_add_d(N, 1uL, &Np1z)) != MP_OKAY) goto LBL_END; + + mp_set(&sz, 1uL); + mp_set(&tz, 2uL); + + for (i = mp_count_bits(&Np1z) - 2; i >= 0; i--) { + /* + * temp = (sz*(a*sz+2*tz))%N; + * tz = ((tz-sz)*(tz+sz))%N; + * sz = temp; + */ + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_END; + + /* a = 0 at about 50% of the cases (non-square and odd input) */ + if (a != 0) { + if ((err = mp_mul_d(&sz, (mp_digit)a, &T1z)) != MP_OKAY) goto LBL_END; + if ((err = mp_add(&T1z, &T2z, &T2z)) != MP_OKAY) goto LBL_END; + } + + if ((err = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) goto LBL_END; + if ((err = mp_sub(&tz, &sz, &T2z)) != MP_OKAY) goto LBL_END; + if ((err = mp_add(&sz, &tz, &sz)) != MP_OKAY) goto LBL_END; + if ((err = mp_mul(&sz, &T2z, &tz)) != MP_OKAY) goto LBL_END; + if ((err = mp_mod(&tz, N, &tz)) != MP_OKAY) goto LBL_END; + if ((err = mp_mod(&T1z, N, &sz)) != MP_OKAY) goto LBL_END; + if (s_mp_get_bit(&Np1z, i)) { + /* + * temp = (a+2) * sz + tz + * tz = 2 * tz - sz + * sz = temp + */ + if (a == 0) { + if ((err = mp_mul_2(&sz, &T1z)) != MP_OKAY) goto LBL_END; + } else { + if ((err = mp_mul_d(&sz, (mp_digit)ap2, &T1z)) != MP_OKAY) goto LBL_END; + } + if ((err = mp_add(&T1z, &tz, &T1z)) != MP_OKAY) goto LBL_END; + if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_END; + if ((err = mp_sub(&T2z, &sz, &tz)) != MP_OKAY) goto LBL_END; + mp_exch(&sz, &T1z); + } + } + + mp_set_u32(&T1z, (uint32_t)((2 * a) + 5)); + if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_END; + + *result = mp_iszero(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ); + +LBL_END: + mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL); + return err; +} + +#endif +#endif diff --git a/deps/libtommath/mp_prime_is_prime.c b/deps/libtommath/mp_prime_is_prime.c new file mode 100644 index 0000000..bb24f59 --- /dev/null +++ b/deps/libtommath/mp_prime_is_prime.c @@ -0,0 +1,282 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_IS_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* portable integer log of two with small footprint */ +static unsigned int s_floor_ilog2(int value) +{ + unsigned int r = 0; + while ((value >>= 1) != 0) { + r++; + } + return r; +} + +mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) +{ + mp_int b; + int ix; + bool res; + mp_err err; + + /* default to no */ + *result = false; + + /* Some shortcuts */ + /* N > 3 */ + if (a->used == 1) { + if ((a->dp[0] == 0u) || (a->dp[0] == 1u)) { + *result = false; + return MP_OKAY; + } + if (a->dp[0] == 2u) { + *result = true; + return MP_OKAY; + } + } + + /* N must be odd */ + if (mp_iseven(a)) { + return MP_OKAY; + } + /* N is not a perfect square: floor(sqrt(N))^2 != N */ + if ((err = mp_is_square(a, &res)) != MP_OKAY) { + return err; + } + if (res) { + return MP_OKAY; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < MP_PRIME_TAB_SIZE; ix++) { + if (mp_cmp_d(a, s_mp_prime_tab[ix]) == MP_EQ) { + *result = true; + return MP_OKAY; + } + } + /* first perform trial division */ + if ((err = s_mp_prime_is_divisible(a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res) { + return MP_OKAY; + } + + /* + Run the Miller-Rabin test with base 2 for the BPSW test. + */ + if ((err = mp_init_set(&b, 2uL)) != MP_OKAY) { + return err; + } + + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + /* + Rumours have it that Mathematica does a second M-R test with base 3. + Other rumours have it that their strong L-S test is slightly different. + It does not hurt, though, beside a bit of extra runtime. + */ + b.dp[0]++; + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + + /* + * Both, the Frobenius-Underwood test and the the Lucas-Selfridge test are quite + * slow so if speed is an issue, define LTM_USE_ONLY_MR to use M-R tests with + * bases 2, 3 and t random bases. + */ +#ifndef LTM_USE_ONLY_MR + if (t >= 0) { +#ifdef LTM_USE_FROBENIUS_TEST + err = mp_prime_frobenius_underwood(a, &res); + if ((err != MP_OKAY) && (err != MP_ITER)) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } +#else + if ((err = mp_prime_strong_lucas_selfridge(a, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } +#endif + } +#endif + + /* run at least one Miller-Rabin test with a random base */ + if (t == 0) { + t = 1; + } + + /* + Only recommended if the input range is known to be < 3317044064679887385961981 + + It uses the bases necessary for a deterministic M-R test if the input is + smaller than 3317044064679887385961981 + The caller has to check the size. + TODO: can be made a bit finer grained but comparing is not free. + */ + if (t < 0) { + int p_max = 0; + + /* + Sorenson, Jonathan; Webster, Jonathan (2015). + "Strong Pseudoprimes to Twelve Prime Bases". + */ + /* 0x437ae92817f9fc85b7e5 = 318665857834031151167461 */ + if ((err = mp_read_radix(&b, "437ae92817f9fc85b7e5", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 12; + } else { + /* 0x2be6951adc5b22410a5fd = 3317044064679887385961981 */ + if ((err = mp_read_radix(&b, "2be6951adc5b22410a5fd", 16)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp(a, &b) == MP_LT) { + p_max = 13; + } else { + err = MP_VAL; + goto LBL_B; + } + } + + /* we did bases 2 and 3 already, skip them */ + for (ix = 2; ix < p_max; ix++) { + mp_set(&b, s_mp_prime_tab[ix]); + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + } + } + /* + Do "t" M-R tests with random bases between 3 and "a". + See Fips 186.4 p. 126ff + */ + else if (t > 0) { + unsigned int mask; + int size_a; + + /* + * The mp_digit's have a defined bit-size but the size of the + * array a.dp is a simple 'int' and this library can not assume full + * compliance to the current C-standard (ISO/IEC 9899:2011) because + * it gets used for small embedded processors, too. Some of those MCUs + * have compilers that one cannot call standard compliant by any means. + * Hence the ugly type-fiddling in the following code. + */ + size_a = mp_count_bits(a); + mask = (1u << s_floor_ilog2(size_a)) - 1u; + /* + Assuming the General Rieman hypothesis (never thought to write that in a + comment) the upper bound can be lowered to 2*(log a)^2. + E. Bach, "Explicit bounds for primality testing and related problems," + Math. Comp. 55 (1990), 355-380. + + size_a = (size_a/10) * 7; + len = 2 * (size_a * size_a); + + E.g.: a number of size 2^2048 would be reduced to the upper limit + + floor(2048/10)*7 = 1428 + 2 * 1428^2 = 4078368 + + (would have been ~4030331.9962 with floats and natural log instead) + That number is smaller than 2^28, the default bit-size of mp_digit. + */ + + /* + How many tests, you might ask? Dana Jacobsen of Math::Prime::Util fame + does exactly 1. In words: one. Look at the end of _GMP_is_prime() in + Math-Prime-Util-GMP-0.50/primality.c if you do not believe it. + + The function mp_rand() goes to some length to use a cryptographically + good PRNG. That also means that the chance to always get the same base + in the loop is non-zero, although very low. + If the BPSW test and/or the additional Frobenious test have been + performed instead of just the Miller-Rabin test with the bases 2 and 3, + a single extra test should suffice, so such a very unlikely event + will not do much harm. + + To preemptively answer the dangling question: no, a witness does not + need to be prime. + */ + for (ix = 0; ix < t; ix++) { + unsigned int fips_rand; + int len; + + /* mp_rand() guarantees the first digit to be non-zero */ + if ((err = mp_rand(&b, 1)) != MP_OKAY) { + goto LBL_B; + } + /* + * Reduce digit before casting because mp_digit might be bigger than + * an unsigned int and "mask" on the other side is most probably not. + */ + fips_rand = (unsigned int)(b.dp[0] & (mp_digit) mask); + if (fips_rand > (unsigned int)(INT_MAX - MP_DIGIT_BIT)) { + len = INT_MAX / MP_DIGIT_BIT; + } else { + len = (((int)fips_rand + MP_DIGIT_BIT) / MP_DIGIT_BIT); + } + /* Unlikely. */ + if (len < 0) { + ix--; + continue; + } + if ((err = mp_rand(&b, len)) != MP_OKAY) { + goto LBL_B; + } + /* + * That number might got too big and the witness has to be + * smaller than "a" + */ + len = mp_count_bits(&b); + if (len >= size_a) { + len = (len - size_a) + 1; + if ((err = mp_div_2d(&b, len, &b, NULL)) != MP_OKAY) { + goto LBL_B; + } + } + /* Although the chance for b <= 3 is miniscule, try again. */ + if (mp_cmp_d(&b, 3uL) != MP_GT) { + ix--; + continue; + } + if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + if (!res) { + goto LBL_B; + } + } + } + + /* passed the test */ + *result = true; +LBL_B: + mp_clear(&b); + return err; +} + +#endif diff --git a/deps/libtommath/mp_prime_miller_rabin.c b/deps/libtommath/mp_prime_miller_rabin.c new file mode 100644 index 0000000..4c23a9f --- /dev/null +++ b/deps/libtommath/mp_prime_miller_rabin.c @@ -0,0 +1,91 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_MILLER_RABIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, bool *result) +{ + mp_int n1, y, r; + mp_err err; + int s, j; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1uL) != MP_GT) { + return MP_VAL; + } + + /* get n1 = a - 1 */ + if ((err = mp_init_copy(&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d(&n1, 1uL, &n1)) != MP_OKAY) { + goto LBL_ERR1; + } + + /* set 2**s * r = n1 */ + if ((err = mp_init_copy(&r, &n1)) != MP_OKAY) { + goto LBL_ERR1; + } + + /* count the number of least significant bits + * which are zero + */ + s = mp_cnt_lsb(&r); + + /* now divide n - 1 by 2**s */ + if ((err = mp_div_2d(&r, s, &r, NULL)) != MP_OKAY) { + goto LBL_ERR2; + } + + /* compute y = b**r mod a */ + if ((err = mp_init(&y)) != MP_OKAY) { + goto LBL_ERR2; + } + if ((err = mp_exptmod(b, &r, a, &y)) != MP_OKAY) { + goto LBL_END; + } + + /* if y != 1 and y != n1 do */ + if ((mp_cmp_d(&y, 1uL) != MP_EQ) && (mp_cmp(&y, &n1) != MP_EQ)) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && (mp_cmp(&y, &n1) != MP_EQ)) { + if ((err = mp_sqrmod(&y, a, &y)) != MP_OKAY) { + goto LBL_END; + } + + /* if y == 1 then composite */ + if (mp_cmp_d(&y, 1uL) == MP_EQ) { + *result = false; + goto LBL_END; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp(&y, &n1) != MP_EQ) { + *result = false; + goto LBL_END; + } + } + + /* probably prime now */ + *result = true; + +LBL_END: + mp_clear(&y); +LBL_ERR2: + mp_clear(&r); +LBL_ERR1: + mp_clear(&n1); + return err; +} +#endif diff --git a/deps/libtommath/mp_prime_next_prime.c b/deps/libtommath/mp_prime_next_prime.c new file mode 100644 index 0000000..6faa08d --- /dev/null +++ b/deps/libtommath/mp_prime_next_prime.c @@ -0,0 +1,127 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_NEXT_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = true means the prime must be congruent to 3 mod 4 + */ +mp_err mp_prime_next_prime(mp_int *a, int t, bool bbs_style) +{ + int x; + mp_err err; + bool res = false; + mp_digit res_tab[MP_PRIME_TAB_SIZE], kstep; + mp_int b; + + /* force positive */ + a->sign = MP_ZPOS; + + /* simple algo if a is less than the largest prime in the table */ + if (mp_cmp_d(a, s_mp_prime_tab[MP_PRIME_TAB_SIZE-1]) == MP_LT) { + /* find which prime it is bigger than "a" */ + for (x = 0; x < MP_PRIME_TAB_SIZE; x++) { + mp_ord cmp = mp_cmp_d(a, s_mp_prime_tab[x]); + if (cmp == MP_EQ) { + continue; + } + if (cmp != MP_GT) { + if ((bbs_style) && ((s_mp_prime_tab[x] & 3u) != 3u)) { + /* try again until we get a prime congruent to 3 mod 4 */ + continue; + } else { + mp_set(a, s_mp_prime_tab[x]); + return MP_OKAY; + } + } + } + /* fall through to the sieve */ + } + + /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */ + kstep = bbs_style ? 4 : 2; + + /* at this point we will use a combination of a sieve and Miller-Rabin */ + + if (bbs_style) { + /* if a mod 4 != 3 subtract the correct value to make it so */ + if ((a->dp[0] & 3u) != 3u) { + if ((err = mp_sub_d(a, (a->dp[0] & 3u) + 1u, a)) != MP_OKAY) { + return err; + } + } + } else { + if (mp_iseven(a)) { + /* force odd */ + if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { + return err; + } + } + } + + /* generate the restable */ + for (x = 1; x < MP_PRIME_TAB_SIZE; x++) { + if ((err = mp_mod_d(a, s_mp_prime_tab[x], res_tab + x)) != MP_OKAY) { + return err; + } + } + + /* init temp used for Miller-Rabin Testing */ + if ((err = mp_init(&b)) != MP_OKAY) { + return err; + } + + for (;;) { + mp_digit step = 0; + bool y; + /* skip to the next non-trivially divisible candidate */ + do { + /* y == true if any residue was zero [e.g. cannot be prime] */ + y = false; + + /* increase step to next candidate */ + step += kstep; + + /* compute the new residue without using division */ + for (x = 1; x < MP_PRIME_TAB_SIZE; x++) { + /* add the step to each residue */ + res_tab[x] += kstep; + + /* subtract the modulus [instead of using division] */ + if (res_tab[x] >= s_mp_prime_tab[x]) { + res_tab[x] -= s_mp_prime_tab[x]; + } + + /* set flag if zero */ + if (res_tab[x] == 0u) { + y = true; + } + } + } while (y && (step < (((mp_digit)1 << MP_DIGIT_BIT) - kstep))); + + /* add the step */ + if ((err = mp_add_d(a, step, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* if didn't pass sieve and step == MP_MAX then skip test */ + if (y && (step >= (((mp_digit)1 << MP_DIGIT_BIT) - kstep))) { + continue; + } + + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; + } + if (res) { + break; + } + } + +LBL_ERR: + mp_clear(&b); + return err; +} + +#endif diff --git a/deps/libtommath/mp_prime_rabin_miller_trials.c b/deps/libtommath/mp_prime_rabin_miller_trials.c new file mode 100644 index 0000000..9f66f8d --- /dev/null +++ b/deps/libtommath/mp_prime_rabin_miller_trials.c @@ -0,0 +1,48 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_RABIN_MILLER_TRIALS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static const struct { + int k, t; +} sizes[] = { + { 80, -1 }, /* Use deterministic algorithm for size <= 80 bits */ + { 81, 37 }, /* max. error = 2^(-96)*/ + { 96, 32 }, /* max. error = 2^(-96)*/ + { 128, 40 }, /* max. error = 2^(-112)*/ + { 160, 35 }, /* max. error = 2^(-112)*/ + { 256, 27 }, /* max. error = 2^(-128)*/ + { 384, 16 }, /* max. error = 2^(-128)*/ + { 512, 18 }, /* max. error = 2^(-160)*/ + { 768, 11 }, /* max. error = 2^(-160)*/ + { 896, 10 }, /* max. error = 2^(-160)*/ + { 1024, 12 }, /* max. error = 2^(-192)*/ + { 1536, 8 }, /* max. error = 2^(-192)*/ + { 2048, 6 }, /* max. error = 2^(-192)*/ + { 3072, 4 }, /* max. error = 2^(-192)*/ + { 4096, 5 }, /* max. error = 2^(-256)*/ + { 5120, 4 }, /* max. error = 2^(-256)*/ + { 6144, 4 }, /* max. error = 2^(-256)*/ + { 8192, 3 }, /* max. error = 2^(-256)*/ + { 9216, 3 }, /* max. error = 2^(-256)*/ + { 10240, 2 } /* For bigger keysizes use always at least 2 Rounds */ +}; + +/* returns # of RM trials required for a given bit size */ +int mp_prime_rabin_miller_trials(int size) +{ + int x; + + for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) { + if (sizes[x].k == size) { + return sizes[x].t; + } + if (sizes[x].k > size) { + return (x == 0) ? sizes[0].t : sizes[x - 1].t; + } + } + return sizes[x-1].t; +} + + +#endif diff --git a/deps/libtommath/mp_prime_rand.c b/deps/libtommath/mp_prime_rand.c new file mode 100644 index 0000000..c5cebbd --- /dev/null +++ b/deps/libtommath/mp_prime_rand.c @@ -0,0 +1,123 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * MP_PRIME_BBS - make prime congruent to 3 mod 4 + * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS) + * MP_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ + +/* This is possibly the mother of all prime generation functions, muahahahahaha! */ +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) +{ + uint8_t *tmp, maskAND, maskOR_msb, maskOR_lsb; + int bsize, maskOR_msb_offset; + bool res; + mp_err err; + + /* sanity check the input */ + if ((size <= 1) || (t <= 0)) { + return MP_VAL; + } + + /* MP_PRIME_SAFE implies MP_PRIME_BBS */ + if ((flags & MP_PRIME_SAFE) != 0) { + flags |= MP_PRIME_BBS; + } + + /* calc the byte size */ + bsize = (size>>3) + ((size&7)?1:0); + + /* we need a buffer of bsize bytes */ + tmp = (uint8_t *) MP_MALLOC((size_t)bsize); + if (tmp == NULL) { + return MP_MEM; + } + + /* calc the maskAND value for the MSbyte*/ + maskAND = ((size&7) == 0) ? 0xFFu : (uint8_t)(0xFFu >> (8 - (size & 7))); + + /* calc the maskOR_msb */ + maskOR_msb = 0; + maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; + if ((flags & MP_PRIME_2MSB_ON) != 0) { + maskOR_msb |= (uint8_t)(0x80 >> ((9 - size) & 7)); + } + + /* get the maskOR_lsb */ + maskOR_lsb = 1u; + if ((flags & MP_PRIME_BBS) != 0) { + maskOR_lsb |= 3u; + } + + do { + /* read the bytes */ + if ((err = s_mp_rand_source(tmp, (size_t)bsize)) != MP_OKAY) { + goto LBL_ERR; + } + + /* work over the MSbyte */ + tmp[0] &= maskAND; + tmp[0] |= (uint8_t)(1 << ((size - 1) & 7)); + + /* mix in the maskORs */ + tmp[maskOR_msb_offset] |= maskOR_msb; + tmp[bsize-1] |= maskOR_lsb; + + /* read it in */ + /* TODO: casting only for now until all lengths have been changed to the type "size_t"*/ + if ((err = mp_from_ubin(a, tmp, (size_t)bsize)) != MP_OKAY) { + goto LBL_ERR; + } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; + } + if (!res) { + continue; + } + + if ((flags & MP_PRIME_SAFE) != 0) { + /* see if (a-1)/2 is prime */ + if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_div_2(a, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* is it prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + goto LBL_ERR; + } + } + } while (!res); + + if ((flags & MP_PRIME_SAFE) != 0) { + /* restore a to the original value */ + if ((err = mp_mul_2(a, a)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) { + goto LBL_ERR; + } + } + + err = MP_OKAY; +LBL_ERR: + MP_FREE_BUF(tmp, (size_t)bsize); + return err; +} + +#endif diff --git a/deps/libtommath/mp_prime_strong_lucas_selfridge.c b/deps/libtommath/mp_prime_strong_lucas_selfridge.c new file mode 100644 index 0000000..ffbd9d3 --- /dev/null +++ b/deps/libtommath/mp_prime_strong_lucas_selfridge.c @@ -0,0 +1,281 @@ +#include "tommath_private.h" +#ifdef MP_PRIME_STRONG_LUCAS_SELFRIDGE_C + +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * See file mp_prime_is_prime.c or the documentation in doc/bn.tex for the details + */ +#ifndef LTM_USE_ONLY_MR + +/* + * multiply bigint a with int d and put the result in c + * Like mp_mul_d() but with a signed long as the small input + */ +static mp_err s_mul_si(const mp_int *a, int32_t d, mp_int *c) +{ + mp_int t; + mp_err err; + + if ((err = mp_init(&t)) != MP_OKAY) { + return err; + } + + /* + * mp_digit might be smaller than a long, which excludes + * the use of mp_mul_d() here. + */ + mp_set_i32(&t, d); + err = mp_mul(a, &t, c); + mp_clear(&t); + return err; +} +/* + Strong Lucas-Selfridge test. + returns true if it is a strong L-S prime, false if it is composite + + Code ported from Thomas Ray Nicely's implementation of the BPSW test + at http://www.trnicely.net/misc/bpsw.html + + Freeware copyright (C) 2016 Thomas R. Nicely . + Released into the public domain by the author, who disclaims any legal + liability arising from its use + + The multi-line comments are made by Thomas R. Nicely and are copied verbatim. + Additional comments marked "CZ" (without the quotes) are by the code-portist. + + (If that name sounds familiar, he is the guy who found the fdiv bug in the + Pentium (P5x, I think) Intel processor) +*/ +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, bool *result) +{ + /* CZ TODO: choose better variable names! */ + mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz; + int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits; + mp_err err; + bool oddness; + + *result = false; + /* + Find the first element D in the sequence {5, -7, 9, -11, 13, ...} + such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory + indicates that, if N is not a perfect square, D will "nearly + always" be "small." Just in case, an overflow trap for D is + included. + */ + + if ((err = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz, + NULL)) != MP_OKAY) { + return err; + } + + D = 5; + sign = 1; + + for (;;) { + Ds = sign * D; + sign = -sign; + mp_set_u32(&Dz, (uint32_t)D); + if ((err = mp_gcd(a, &Dz, &gcd)) != MP_OKAY) goto LBL_LS_ERR; + + /* if 1 < GCD < N then N is composite with factor "D", and + Jacobi(D,N) is technically undefined (but often returned + as zero). */ + if ((mp_cmp_d(&gcd, 1uL) == MP_GT) && (mp_cmp(&gcd, a) == MP_LT)) { + goto LBL_LS_ERR; + } + if (Ds < 0) { + Dz.sign = MP_NEG; + } + if ((err = mp_kronecker(&Dz, a, &J)) != MP_OKAY) goto LBL_LS_ERR; + + if (J == -1) { + break; + } + D += 2; + + if (D > (INT_MAX - 2)) { + err = MP_VAL; + goto LBL_LS_ERR; + } + } + + + + P = 1; /* Selfridge's choice */ + Q = (1 - Ds) / 4; /* Required so D = P*P - 4*Q */ + + /* NOTE: The conditions (a) N does not divide Q, and + (b) D is square-free or not a perfect square, are included by + some authors; e.g., "Prime numbers and computer methods for + factorization," Hans Riesel (2nd ed., 1994, Birkhauser, Boston), + p. 130. For this particular application of Lucas sequences, + these conditions were found to be immaterial. */ + + /* Now calculate N - Jacobi(D,N) = N + 1 (even), and calculate the + odd positive integer d and positive integer s for which + N + 1 = 2^s*d (similar to the step for N - 1 in Miller's test). + The strong Lucas-Selfridge test then returns N as a strong + Lucas probable prime (slprp) if any of the following + conditions is met: U_d=0, V_d=0, V_2d=0, V_4d=0, V_8d=0, + V_16d=0, ..., etc., ending with V_{2^(s-1)*d}=V_{(N+1)/2}=0 + (all equalities mod N). Thus d is the highest index of U that + must be computed (since V_2m is independent of U), compared + to U_{N+1} for the standard Lucas-Selfridge test; and no + index of V beyond (N+1)/2 is required, just as in the + standard Lucas-Selfridge test. However, the quantity Q^d must + be computed for use (if necessary) in the latter stages of + the test. The result is that the strong Lucas-Selfridge test + has a running time only slightly greater (order of 10 %) than + that of the standard Lucas-Selfridge test, while producing + only (roughly) 30 % as many pseudoprimes (and every strong + Lucas pseudoprime is also a standard Lucas pseudoprime). Thus + the evidence indicates that the strong Lucas-Selfridge test is + more effective than the standard Lucas-Selfridge test, and a + Baillie-PSW test based on the strong Lucas-Selfridge test + should be more reliable. */ + + if ((err = mp_add_d(a, 1uL, &Np1)) != MP_OKAY) goto LBL_LS_ERR; + s = mp_cnt_lsb(&Np1); + + /* CZ + * This should round towards zero because + * Thomas R. Nicely used GMP's mpz_tdiv_q_2exp() + * and mp_div_2d() is equivalent. Additionally: + * dividing an even number by two does not produce + * any leftovers. + */ + if ((err = mp_div_2d(&Np1, s, &Dz, NULL)) != MP_OKAY) goto LBL_LS_ERR; + /* We must now compute U_d and V_d. Since d is odd, the accumulated + values U and V are initialized to U_1 and V_1 (if the target + index were even, U and V would be initialized instead to U_0=0 + and V_0=2). The values of U_2m and V_2m are also initialized to + U_1 and V_1; the FOR loop calculates in succession U_2 and V_2, + U_4 and V_4, U_8 and V_8, etc. If the corresponding bits + (1, 2, 3, ...) of t are on (the zero bit having been accounted + for in the initialization of U and V), these values are then + combined with the previous totals for U and V, using the + composition formulas for addition of indices. */ + + mp_set(&Uz, 1uL); /* U=U_1 */ + mp_set(&Vz, (mp_digit)P); /* V=V_1 */ + mp_set(&U2mz, 1uL); /* U_1 */ + mp_set(&V2mz, (mp_digit)P); /* V_1 */ + + mp_set_i32(&Qmz, Q); + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + /* Initializes calculation of Q^d */ + mp_set_i32(&Qkdz, Q); + + Nbits = mp_count_bits(&Dz); + + for (u = 1; u < Nbits; u++) { /* zero bit off, already accounted for */ + /* Formulas for doubling of indices (carried out mod N). Note that + * the indices denoted as "2m" are actually powers of 2, specifically + * 2^(ul-1) beginning each loop and 2^ul ending each loop. + * + * U_2m = U_m*V_m + * V_2m = V_m*V_m - 2*Q^m + */ + + if ((err = mp_mul(&U2mz, &V2mz, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&U2mz, a, &U2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sqr(&V2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&V2mz, &Q2mz, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&V2mz, a, &V2mz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Must calculate powers of Q for use in V_2m, also for Q^d later */ + if ((err = mp_sqr(&Qmz, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + + /* prevents overflow */ /* CZ still necessary without a fixed prealloc'd mem.? */ + if ((err = mp_mod(&Qmz, a, &Qmz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) goto LBL_LS_ERR; + + if (s_mp_get_bit(&Dz, u)) { + /* Formulas for addition of indices (carried out mod N); + * + * U_(m+n) = (U_m*V_n + U_n*V_m)/2 + * V_(m+n) = (V_m*V_n + D*U_m*U_n)/2 + * + * Be careful with division by 2 (mod N)! + */ + if ((err = mp_mul(&U2mz, &Vz, &T1z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&Uz, &V2mz, &T2z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&V2mz, &Vz, &T3z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul(&U2mz, &Uz, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = s_mul_si(&T4z, Ds, &T4z)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_add(&T1z, &T2z, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isodd(&Uz)) { + if ((err = mp_add(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + /* CZ + * This should round towards negative infinity because + * Thomas R. Nicely used GMP's mpz_fdiv_q_2exp(). + * But mp_div_2() does not do so, it is truncating instead. + */ + oddness = mp_isodd(&Uz); + if ((err = mp_div_2(&Uz, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isneg(&Uz) && oddness) { + if ((err = mp_sub_d(&Uz, 1uL, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_add(&T3z, &T4z, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isodd(&Vz)) { + if ((err = mp_add(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + oddness = mp_isodd(&Vz); + if ((err = mp_div_2(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_isneg(&Vz) && oddness) { + if ((err = mp_sub_d(&Vz, 1uL, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + } + if ((err = mp_mod(&Uz, a, &Uz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + + /* Calculating Q^d for later use */ + if ((err = mp_mul(&Qkdz, &Qmz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } + + /* If U_d or V_d is congruent to 0 mod N, then N is a prime or a + strong Lucas pseudoprime. */ + if (mp_iszero(&Uz) || mp_iszero(&Vz)) { + *result = true; + goto LBL_LS_ERR; + } + + /* NOTE: Ribenboim ("The new book of prime number records," 3rd ed., + 1995/6) omits the condition V0 on p.142, but includes it on + p. 130. The condition is NECESSARY; otherwise the test will + return false negatives---e.g., the primes 29 and 2000029 will be + returned as composite. */ + + /* Otherwise, we must compute V_2d, V_4d, V_8d, ..., V_{2^(s-1)*d} + by repeated use of the formula V_2m = V_m*V_m - 2*Q^m. If any of + these are congruent to 0 mod N, then N is a prime or a strong + Lucas pseudoprime. */ + + /* Initialize 2*Q^(d*2^r) for V_2m */ + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + + for (r = 1; r < s; r++) { + if ((err = mp_sqr(&Vz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_sub(&Vz, &Q2kdz, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Vz, a, &Vz)) != MP_OKAY) goto LBL_LS_ERR; + if (mp_iszero(&Vz)) { + *result = true; + goto LBL_LS_ERR; + } + /* Calculate Q^{d*2^r} for next r (final iteration irrelevant). */ + if (r < (s - 1)) { + if ((err = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) goto LBL_LS_ERR; + if ((err = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) goto LBL_LS_ERR; + } + } +LBL_LS_ERR: + mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL); + return err; +} +#endif +#endif diff --git a/deps/libtommath/mp_radix_size.c b/deps/libtommath/mp_radix_size.c new file mode 100644 index 0000000..ca08438 --- /dev/null +++ b/deps/libtommath/mp_radix_size.c @@ -0,0 +1,34 @@ +#include "tommath_private.h" +#ifdef MP_RADIX_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* returns size of ASCII representation */ +mp_err mp_radix_size(const mp_int *a, int radix, size_t *size) +{ + mp_err err; + mp_int a_; + int b; + + /* make sure the radix is in range */ + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + if (mp_iszero(a)) { + *size = 2; + return MP_OKAY; + } + + a_ = *a; + a_.sign = MP_ZPOS; + if ((err = mp_log_n(&a_, radix, &b)) != MP_OKAY) { + return err; + } + + /* mp_ilogb truncates to zero, hence we need one extra put on top and one for `\0`. */ + *size = (size_t)b + 2U + (mp_isneg(a) ? 1U : 0U); + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_radix_size_overestimate.c b/deps/libtommath/mp_radix_size_overestimate.c new file mode 100644 index 0000000..3fe81d7 --- /dev/null +++ b/deps/libtommath/mp_radix_size_overestimate.c @@ -0,0 +1,17 @@ +#include "tommath_private.h" +#ifdef MP_RADIX_SIZE_OVERESTIMATE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size) +{ + if (MP_HAS(S_MP_RADIX_SIZE_OVERESTIMATE)) { + return s_mp_radix_size_overestimate(a, radix, size); + } + if (MP_HAS(MP_RADIX_SIZE)) { + return mp_radix_size(a, radix, size); + } + return MP_ERR; +} + +#endif diff --git a/deps/libtommath/mp_rand.c b/deps/libtommath/mp_rand.c new file mode 100644 index 0000000..1936475 --- /dev/null +++ b/deps/libtommath/mp_rand.c @@ -0,0 +1,39 @@ +#include "tommath_private.h" +#ifdef MP_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err mp_rand(mp_int *a, int digits) +{ + int i; + mp_err err; + + mp_zero(a); + + if (digits <= 0) { + return MP_OKAY; + } + + if ((err = mp_grow(a, digits)) != MP_OKAY) { + return err; + } + + if ((err = s_mp_rand_source(a->dp, (size_t)digits * sizeof(mp_digit))) != MP_OKAY) { + return err; + } + + /* TODO: We ensure that the highest digit is nonzero. Should this be removed? */ + while ((a->dp[digits - 1] & MP_MASK) == 0u) { + if ((err = s_mp_rand_source(a->dp + digits - 1, sizeof(mp_digit))) != MP_OKAY) { + return err; + } + } + + a->used = digits; + for (i = 0; i < digits; ++i) { + a->dp[i] &= MP_MASK; + } + + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_rand_source.c b/deps/libtommath/mp_rand_source.c new file mode 100644 index 0000000..e9e8769 --- /dev/null +++ b/deps/libtommath/mp_rand_source.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef MP_RAND_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +mp_err(*s_mp_rand_source)(void *out, size_t size) = s_mp_rand_platform; + +void mp_rand_source(mp_err(*source)(void *out, size_t size)) +{ + s_mp_rand_source = (source == NULL) ? s_mp_rand_platform : source; +} +#endif diff --git a/deps/libtommath/mp_read_radix.c b/deps/libtommath/mp_read_radix.c new file mode 100644 index 0000000..28e6eb6 --- /dev/null +++ b/deps/libtommath/mp_read_radix.c @@ -0,0 +1,69 @@ +#include "tommath_private.h" +#ifdef MP_READ_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* read a string [ASCII] in a given radix */ +mp_err mp_read_radix(mp_int *a, const char *str, int radix) +{ + mp_err err; + mp_sign sign = MP_ZPOS; + + /* make sure the radix is ok */ + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + sign = MP_NEG; + } + + /* set the integer to the default of zero */ + mp_zero(a); + + /* process each digit of the string */ + while (*str != '\0') { + /* if the radix <= 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + uint8_t y; + char ch = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str; + unsigned pos = (unsigned)(ch - '+'); + if (MP_RADIX_MAP_REVERSE_SIZE <= pos) { + break; + } + y = s_mp_radix_map_reverse[pos]; + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y >= radix) { + break; + } + if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + ++str; + } + + /* if an illegal character was found, fail. */ + if ((*str != '\0') && (*str != '\r') && (*str != '\n')) { + return MP_VAL; + } + + /* set the sign only if a != 0 */ + if (!mp_iszero(a)) { + a->sign = sign; + } + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_reduce.c b/deps/libtommath/mp_reduce.c new file mode 100644 index 0000000..b6fae55 --- /dev/null +++ b/deps/libtommath/mp_reduce.c @@ -0,0 +1,83 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) +{ + mp_int q; + mp_err err; + int um = m->used; + + /* q = x */ + if ((err = mp_init_copy(&q, x)) != MP_OKAY) { + return err; + } + + /* q1 = x / b**(k-1) */ + mp_rshd(&q, um - 1); + + /* according to HAC this optimization is ok */ + if ((mp_digit)um > ((mp_digit)1 << (MP_DIGIT_BIT - 1))) { + if ((err = mp_mul(&q, mu, &q)) != MP_OKAY) { + goto LBL_ERR; + } + } else if (MP_HAS(S_MP_MUL_HIGH)) { + if ((err = s_mp_mul_high(&q, mu, &q, um)) != MP_OKAY) { + goto LBL_ERR; + } + } else if (MP_HAS(S_MP_MUL_HIGH_COMBA)) { + if ((err = s_mp_mul_high_comba(&q, mu, &q, um)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + err = MP_VAL; + goto LBL_ERR; + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd(&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((err = mp_mod_2d(x, MP_DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto LBL_ERR; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((err = s_mp_mul(&q, m, &q, um + 1)) != MP_OKAY) { + goto LBL_ERR; + } + + /* x = x - q */ + if ((err = mp_sub(x, &q, x)) != MP_OKAY) { + goto LBL_ERR; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d(x, 0uL) == MP_LT) { + mp_set(&q, 1uL); + if ((err = mp_lshd(&q, um + 1)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(x, &q, x)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* Back off if it's too big */ + while (mp_cmp(x, m) != MP_LT) { + if ((err = s_mp_sub(x, m, x)) != MP_OKAY) { + goto LBL_ERR; + } + } + +LBL_ERR: + mp_clear(&q); + + return err; +} +#endif diff --git a/deps/libtommath/mp_reduce_2k.c b/deps/libtommath/mp_reduce_2k.c new file mode 100644 index 0000000..e635f5b --- /dev/null +++ b/deps/libtommath/mp_reduce_2k.c @@ -0,0 +1,49 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces a modulo n where n is of the form 2**p - d */ +mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d) +{ + mp_int q; + mp_err err; + int p; + + if ((err = mp_init(&q)) != MP_OKAY) { + return err; + } + + p = mp_count_bits(n); + for (;;) { + /* q = a/2**p, a = a mod 2**p */ + if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (d != 1u) { + /* q = q * d */ + if ((err = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* a = a + q */ + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_cmp_mag(a, n) == MP_LT) { + break; + } + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } + } + +LBL_ERR: + mp_clear(&q); + return err; +} + +#endif diff --git a/deps/libtommath/mp_reduce_2k_l.c b/deps/libtommath/mp_reduce_2k_l.c new file mode 100644 index 0000000..31d9a18 --- /dev/null +++ b/deps/libtommath/mp_reduce_2k_l.c @@ -0,0 +1,52 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reduces a modulo n where n is of the form 2**p - d + This differs from reduce_2k since "d" can be larger + than a single digit. +*/ +mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d) +{ + mp_int q; + mp_err err; + int p; + + if ((err = mp_init(&q)) != MP_OKAY) { + return err; + } + + p = mp_count_bits(n); + + for (;;) { + /* q = a/2**p, a = a mod 2**p */ + if ((err = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + /* q = q * d */ + if ((err = mp_mul(&q, d, &q)) != MP_OKAY) { + goto LBL_ERR; + } + + /* a = a + q */ + if ((err = s_mp_add(a, &q, a)) != MP_OKAY) { + goto LBL_ERR; + } + + if (mp_cmp_mag(a, n) == MP_LT) { + break; + } + if ((err = s_mp_sub(a, n, a)) != MP_OKAY) { + goto LBL_ERR; + } + + } + +LBL_ERR: + mp_clear(&q); + return err; +} + +#endif diff --git a/deps/libtommath/mp_reduce_2k_setup.c b/deps/libtommath/mp_reduce_2k_setup.c new file mode 100644 index 0000000..51f8841 --- /dev/null +++ b/deps/libtommath/mp_reduce_2k_setup.c @@ -0,0 +1,30 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d) +{ + mp_err err; + mp_int tmp; + + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; + } + + if ((err = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + + *d = tmp.dp[0]; + +LBL_ERR: + mp_clear(&tmp); + return err; +} +#endif diff --git a/deps/libtommath/mp_reduce_2k_setup_l.c b/deps/libtommath/mp_reduce_2k_setup_l.c new file mode 100644 index 0000000..b647c9d --- /dev/null +++ b/deps/libtommath/mp_reduce_2k_setup_l.c @@ -0,0 +1,28 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_2K_SETUP_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines the setup value */ +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d) +{ + mp_err err; + mp_int tmp; + + if ((err = mp_init(&tmp)) != MP_OKAY) { + return err; + } + + if ((err = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto LBL_ERR; + } + + if ((err = s_mp_sub(&tmp, a, d)) != MP_OKAY) { + goto LBL_ERR; + } + +LBL_ERR: + mp_clear(&tmp); + return err; +} +#endif diff --git a/deps/libtommath/mp_reduce_is_2k.c b/deps/libtommath/mp_reduce_is_2k.c new file mode 100644 index 0000000..9774f96 --- /dev/null +++ b/deps/libtommath/mp_reduce_is_2k.c @@ -0,0 +1,34 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_IS_2K_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if mp_reduce_2k can be used */ +bool mp_reduce_is_2k(const mp_int *a) +{ + if (mp_iszero(a)) { + return false; + } else if (a->used == 1) { + return true; + } else if (a->used > 1) { + int ix, iy = mp_count_bits(a), iw = 1; + mp_digit iz = 1; + + /* Test every bit from the second digit up, must be 1 */ + for (ix = MP_DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[iw] & iz) == 0u) { + return false; + } + iz <<= 1; + if (iz > MP_DIGIT_MAX) { + ++iw; + iz = 1; + } + } + return true; + } else { + return true; + } +} + +#endif diff --git a/deps/libtommath/mp_reduce_is_2k_l.c b/deps/libtommath/mp_reduce_is_2k_l.c new file mode 100644 index 0000000..101b4a1 --- /dev/null +++ b/deps/libtommath/mp_reduce_is_2k_l.c @@ -0,0 +1,27 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_IS_2K_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if reduce_2k_l can be used */ +bool mp_reduce_is_2k_l(const mp_int *a) +{ + if (mp_iszero(a)) { + return false; + } else if (a->used == 1) { + return true; + } else if (a->used > 1) { + /* if more than half of the digits are -1 we're sold */ + int ix, iy; + for (iy = ix = 0; ix < a->used; ix++) { + if (a->dp[ix] == MP_DIGIT_MAX) { + ++iy; + } + } + return (iy >= (a->used/2)); + } else { + return false; + } +} + +#endif diff --git a/deps/libtommath/mp_reduce_setup.c b/deps/libtommath/mp_reduce_setup.c new file mode 100644 index 0000000..2ce5b96 --- /dev/null +++ b/deps/libtommath/mp_reduce_setup.c @@ -0,0 +1,17 @@ +#include "tommath_private.h" +#ifdef MP_REDUCE_SETUP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calculates the value required in "a" + */ +mp_err mp_reduce_setup(mp_int *a, const mp_int *b) +{ + mp_err err; + if ((err = mp_2expt(a, b->used * 2 * MP_DIGIT_BIT)) != MP_OKAY) { + return err; + } + return mp_div(a, b, a, NULL); +} +#endif diff --git a/deps/libtommath/mp_root_n.c b/deps/libtommath/mp_root_n.c new file mode 100644 index 0000000..d904df8 --- /dev/null +++ b/deps/libtommath/mp_root_n.c @@ -0,0 +1,141 @@ +#include "tommath_private.h" +#ifdef MP_ROOT_N_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* find the n'th root of an integer + * + * Result found such that (c)**b <= a and (c+1)**b > a + * + * This algorithm uses Newton's approximation + * x[i+1] = x[i] - f(x[i])/f'(x[i]) + * which will find the root in log(N) time where + * each step involves a fair bit. + */ +mp_err mp_root_n(const mp_int *a, int b, mp_int *c) +{ + mp_int t1, t2, t3, a_; + int ilog2; + mp_err err; + + if (b < 0 || (unsigned)b > (unsigned)MP_DIGIT_MAX) { + return MP_VAL; + } + + /* input must be positive if b is even */ + if (((b & 1) == 0) && mp_isneg(a)) { + return MP_VAL; + } + + if ((err = mp_init_multi(&t1, &t2, &t3, NULL)) != MP_OKAY) { + return err; + } + + /* if a is negative fudge the sign but keep track */ + a_ = *a; + a_.sign = MP_ZPOS; + + /* Compute seed: 2^(log_2(n)/b + 2)*/ + ilog2 = mp_count_bits(a); + + /* + If "b" is larger than INT_MAX it is also larger than + log_2(n) because the bit-length of the "n" is measured + with an int and hence the root is always < 2 (two). + */ + if (b > INT_MAX/2) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + + /* "b" is smaller than INT_MAX, we can cast safely */ + if (ilog2 < b) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + ilog2 = ilog2 / b; + if (ilog2 == 0) { + mp_set(c, 1uL); + c->sign = a->sign; + err = MP_OKAY; + goto LBL_ERR; + } + /* Start value must be larger than root */ + ilog2 += 2; + if ((err = mp_2expt(&t2,ilog2)) != MP_OKAY) goto LBL_ERR; + do { + /* t1 = t2 */ + if ((err = mp_copy(&t2, &t1)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ + + /* t3 = t1**(b-1) */ + if ((err = mp_expt_n(&t1, b - 1, &t3)) != MP_OKAY) goto LBL_ERR; + + /* numerator */ + /* t2 = t1**b */ + if ((err = mp_mul(&t3, &t1, &t2)) != MP_OKAY) goto LBL_ERR; + + /* t2 = t1**b - a */ + if ((err = mp_sub(&t2, &a_, &t2)) != MP_OKAY) goto LBL_ERR; + + /* denominator */ + /* t3 = t1**(b-1) * b */ + if ((err = mp_mul_d(&t3, (mp_digit)b, &t3)) != MP_OKAY) goto LBL_ERR; + + /* t3 = (t1**b - a)/(b * t1**(b-1)) */ + if ((err = mp_div(&t2, &t3, &t3, NULL)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&t1, &t3, &t2)) != MP_OKAY) goto LBL_ERR; + + /* + Number of rounds is at most log_2(root). If it is more it + got stuck, so break out of the loop and do the rest manually. + */ + if (ilog2-- == 0) { + break; + } + } while (mp_cmp(&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + /* Loop beneath can overshoot by one if found root is smaller than actual root */ + for (;;) { + mp_ord cmp; + if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + cmp = mp_cmp(&t2, &a_); + if (cmp == MP_EQ) { + err = MP_OKAY; + goto LBL_ERR; + } + if (cmp == MP_LT) { + if ((err = mp_add_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + /* correct overshoot from above or from recurrence */ + for (;;) { + if ((err = mp_expt_n(&t1, b, &t2)) != MP_OKAY) goto LBL_ERR; + if (mp_cmp(&t2, &a_) == MP_GT) { + if ((err = mp_sub_d(&t1, 1uL, &t1)) != MP_OKAY) goto LBL_ERR; + } else { + break; + } + } + + /* set the result */ + mp_exch(&t1, c); + + /* set the sign of the result */ + c->sign = a->sign; + +LBL_ERR: + mp_clear_multi(&t1, &t2, &t3, NULL); + return err; +} + +#endif diff --git a/deps/libtommath/mp_rshd.c b/deps/libtommath/mp_rshd.c new file mode 100644 index 0000000..3f0a941 --- /dev/null +++ b/deps/libtommath/mp_rshd.c @@ -0,0 +1,43 @@ +#include "tommath_private.h" +#ifdef MP_RSHD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right a certain amount of digits */ +void mp_rshd(mp_int *a, int b) +{ + int x; + + /* if b <= 0 then ignore it */ + if (b <= 0) { + return; + } + + /* if b > used then simply zero it and return */ + if (a->used <= b) { + mp_zero(a); + return; + } + + /* shift the digits down. + * this is implemented as a sliding window where + * the window is b-digits long and digits from + * the top of the window are copied to the bottom + * + * e.g. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + for (x = 0; x < (a->used - b); x++) { + a->dp[x] = a->dp[x + b]; + } + + /* zero the top digits */ + s_mp_zero_digs(a->dp + a->used - b, b); + + /* remove excess digits */ + a->used -= b; +} +#endif diff --git a/deps/libtommath/mp_sbin_size.c b/deps/libtommath/mp_sbin_size.c new file mode 100644 index 0000000..2f40df3 --- /dev/null +++ b/deps/libtommath/mp_sbin_size.c @@ -0,0 +1,11 @@ +#include "tommath_private.h" +#ifdef MP_SBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an signed equivalent */ +size_t mp_sbin_size(const mp_int *a) +{ + return 1u + mp_ubin_size(a); +} +#endif diff --git a/deps/libtommath/mp_set.c b/deps/libtommath/mp_set.c new file mode 100644 index 0000000..bc0c4da --- /dev/null +++ b/deps/libtommath/mp_set.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_SET_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* set to a digit */ +void mp_set(mp_int *a, mp_digit b) +{ + int oldused = a->used; + a->dp[0] = b & MP_MASK; + a->sign = MP_ZPOS; + a->used = (a->dp[0] != 0u) ? 1 : 0; + s_mp_zero_digs(a->dp + a->used, oldused - a->used); +} +#endif diff --git a/deps/libtommath/mp_set_double.c b/deps/libtommath/mp_set_double.c new file mode 100644 index 0000000..0ede359 --- /dev/null +++ b/deps/libtommath/mp_set_double.c @@ -0,0 +1,47 @@ +#include "tommath_private.h" +#ifdef MP_SET_DOUBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if defined(MP_HAS_SET_DOUBLE) +mp_err mp_set_double(mp_int *a, double b) +{ + uint64_t frac; + int exp; + mp_err err; + union { + double dbl; + uint64_t bits; + } cast; + cast.dbl = b; + + exp = (int)((unsigned)(cast.bits >> 52) & 0x7FFu); + frac = (cast.bits & (((uint64_t)1 << 52) - (uint64_t)1)) | ((uint64_t)1 << 52); + + if (exp == 0x7FF) { /* +-inf, NaN */ + return MP_VAL; + } + exp -= 1023 + 52; + + mp_set_u64(a, frac); + + err = (exp < 0) ? mp_div_2d(a, -exp, a, NULL) : mp_mul_2d(a, exp, a); + if (err != MP_OKAY) { + return err; + } + + if (((cast.bits >> 63) != 0u) && !mp_iszero(a)) { + a->sign = MP_NEG; + } + + return MP_OKAY; +} +#else +/* pragma message() not supported by several compilers (in mostly older but still used versions) */ +# ifdef _MSC_VER +# pragma message("mp_set_double implementation is only available on platforms with IEEE754 floating point format") +# else +# warning "mp_set_double implementation is only available on platforms with IEEE754 floating point format" +# endif +#endif +#endif diff --git a/deps/libtommath/mp_set_i32.c b/deps/libtommath/mp_set_i32.c new file mode 100644 index 0000000..123613e --- /dev/null +++ b/deps/libtommath/mp_set_i32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_I32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i32, mp_set_u32, int32_t, uint32_t) +#endif diff --git a/deps/libtommath/mp_set_i64.c b/deps/libtommath/mp_set_i64.c new file mode 100644 index 0000000..4635ca3 --- /dev/null +++ b/deps/libtommath/mp_set_i64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_I64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_i64, mp_set_u64, int64_t, uint64_t) +#endif diff --git a/deps/libtommath/mp_set_l.c b/deps/libtommath/mp_set_l.c new file mode 100644 index 0000000..411f6eb --- /dev/null +++ b/deps/libtommath/mp_set_l.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_L_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_SIGNED(mp_set_l, mp_set_ul, long, unsigned long) +#endif diff --git a/deps/libtommath/mp_set_u32.c b/deps/libtommath/mp_set_u32.c new file mode 100644 index 0000000..8ff84dc --- /dev/null +++ b/deps/libtommath/mp_set_u32.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_U32_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u32, uint32_t) +#endif diff --git a/deps/libtommath/mp_set_u64.c b/deps/libtommath/mp_set_u64.c new file mode 100644 index 0000000..9acb1fe --- /dev/null +++ b/deps/libtommath/mp_set_u64.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_U64_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_u64, uint64_t) +#endif diff --git a/deps/libtommath/mp_set_ul.c b/deps/libtommath/mp_set_ul.c new file mode 100644 index 0000000..baf8e18 --- /dev/null +++ b/deps/libtommath/mp_set_ul.c @@ -0,0 +1,7 @@ +#include "tommath_private.h" +#ifdef MP_SET_UL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +MP_SET_UNSIGNED(mp_set_ul, unsigned long) +#endif diff --git a/deps/libtommath/mp_shrink.c b/deps/libtommath/mp_shrink.c new file mode 100644 index 0000000..3d9b162 --- /dev/null +++ b/deps/libtommath/mp_shrink.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef MP_SHRINK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shrink a bignum */ +mp_err mp_shrink(mp_int *a) +{ + int alloc = MP_MAX(MP_MIN_DIGIT_COUNT, a->used); + if (a->alloc != alloc) { + mp_digit *dp = (mp_digit *) MP_REALLOC(a->dp, + (size_t)a->alloc * sizeof(mp_digit), + (size_t)alloc * sizeof(mp_digit)); + if (dp == NULL) { + return MP_MEM; + } + a->dp = dp; + a->alloc = alloc; + } + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_signed_rsh.c b/deps/libtommath/mp_signed_rsh.c new file mode 100644 index 0000000..3b7e232 --- /dev/null +++ b/deps/libtommath/mp_signed_rsh.c @@ -0,0 +1,21 @@ +#include "tommath_private.h" +#ifdef MP_SIGNED_RSH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* shift right by a certain bit count with sign extension */ +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c) +{ + mp_err err; + if (!mp_isneg(a)) { + return mp_div_2d(a, b, c, NULL); + } + + if ((err = mp_add_d(a, 1uL, c)) != MP_OKAY) { + return err; + } + + err = mp_div_2d(c, b, c, NULL); + return (err == MP_OKAY) ? mp_sub_d(c, 1uL, c) : err; +} +#endif diff --git a/deps/libtommath/mp_sqrmod.c b/deps/libtommath/mp_sqrmod.c new file mode 100644 index 0000000..bce2af0 --- /dev/null +++ b/deps/libtommath/mp_sqrmod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_SQRMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = a * a (mod b) */ +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_err err; + if ((err = mp_sqr(a, c)) != MP_OKAY) { + return err; + } + return mp_mod(c, b, c); +} +#endif diff --git a/deps/libtommath/mp_sqrt.c b/deps/libtommath/mp_sqrt.c new file mode 100644 index 0000000..1a9dca7 --- /dev/null +++ b/deps/libtommath/mp_sqrt.c @@ -0,0 +1,67 @@ +#include "tommath_private.h" +#ifdef MP_SQRT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* this function is less generic than mp_n_root, simpler and faster */ +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) +{ + mp_err err; + mp_int t1, t2; + + /* must be positive */ + if (mp_isneg(arg)) { + return MP_VAL; + } + + /* easy out */ + if (mp_iszero(arg)) { + mp_zero(ret); + return MP_OKAY; + } + + if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) { + return err; + } + + if ((err = mp_init(&t2)) != MP_OKAY) { + goto LBL_ERR2; + } + + /* First approx. (not very bad for large arg) */ + mp_rshd(&t1, t1.used/2); + + /* t1 > 0 */ + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + /* And now t1 > sqrt(arg) */ + do { + if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { + goto LBL_ERR1; + } + /* t1 >= sqrt(arg) >= t2 at this point */ + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + mp_exch(&t1, ret); + +LBL_ERR1: + mp_clear(&t2); +LBL_ERR2: + mp_clear(&t1); + return err; +} + +#endif diff --git a/deps/libtommath/mp_sqrtmod_prime.c b/deps/libtommath/mp_sqrtmod_prime.c new file mode 100644 index 0000000..0fae1d0 --- /dev/null +++ b/deps/libtommath/mp_sqrtmod_prime.c @@ -0,0 +1,133 @@ +#include "tommath_private.h" +#ifdef MP_SQRTMOD_PRIME_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Tonelli-Shanks algorithm + * https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm + * https://gmplib.org/list-archives/gmp-discuss/2013-April/005300.html + * + */ + +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) +{ + mp_err err; + int legendre; + /* The type is "int" because of the types in the mp_int struct. + Don't forget to change them here when you change them there! */ + int S, M, i; + mp_int t1, C, Q, Z, T, R, two; + + /* first handle the simple cases */ + if (mp_cmp_d(n, 0uL) == MP_EQ) { + mp_zero(ret); + return MP_OKAY; + } + /* "prime" must be odd and > 2 */ + if (mp_iseven(prime) || (mp_cmp_d(prime, 3uL) == MP_LT)) return MP_VAL; + if ((err = mp_kronecker(n, prime, &legendre)) != MP_OKAY) return err; + /* n \not\cong 0 (mod p) and n \cong r^2 (mod p) for some r \in N^+ */ + if (legendre != 1) return MP_VAL; + + if ((err = mp_init_multi(&t1, &C, &Q, &Z, &T, &R, &two, NULL)) != MP_OKAY) { + return err; + } + + /* SPECIAL CASE: if prime mod 4 == 3 + * compute directly: err = n^(prime+1)/4 mod prime + * Handbook of Applied Cryptography algorithm 3.36 + */ + /* x%4 == x&3 for x in N and x>0 */ + if ((prime->dp[0] & 3u) == 3u) { + if ((err = mp_add_d(prime, 1uL, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_exptmod(n, &t1, prime, ret)) != MP_OKAY) goto LBL_END; + err = MP_OKAY; + goto LBL_END; + } + + /* NOW: Tonelli-Shanks algorithm */ + + /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ + if ((err = mp_copy(prime, &Q)) != MP_OKAY) goto LBL_END; + if ((err = mp_sub_d(&Q, 1uL, &Q)) != MP_OKAY) goto LBL_END; + /* Q = prime - 1 */ + S = 0; + /* S = 0 */ + while (mp_iseven(&Q)) { + if ((err = mp_div_2(&Q, &Q)) != MP_OKAY) goto LBL_END; + /* Q = Q / 2 */ + S++; + /* S = S + 1 */ + } + + /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + mp_set(&Z, 2uL); + /* Z = 2 */ + for (;;) { + if ((err = mp_kronecker(&Z, prime, &legendre)) != MP_OKAY) goto LBL_END; + /* If "prime" (p) is an odd prime Jacobi(k|p) = 0 for k \cong 0 (mod p) */ + /* but there is at least one non-quadratic residue before k>=p if p is an odd prime. */ + if (legendre == 0) { + err = MP_VAL; + goto LBL_END; + } + if (legendre == -1) break; + if ((err = mp_add_d(&Z, 1uL, &Z)) != MP_OKAY) goto LBL_END; + /* Z = Z + 1 */ + } + + if ((err = mp_exptmod(&Z, &Q, prime, &C)) != MP_OKAY) goto LBL_END; + /* C = Z ^ Q mod prime */ + if ((err = mp_add_d(&Q, 1uL, &t1)) != MP_OKAY) goto LBL_END; + if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) goto LBL_END; + /* t1 = (Q + 1) / 2 */ + if ((err = mp_exptmod(n, &t1, prime, &R)) != MP_OKAY) goto LBL_END; + /* R = n ^ ((Q + 1) / 2) mod prime */ + if ((err = mp_exptmod(n, &Q, prime, &T)) != MP_OKAY) goto LBL_END; + /* T = n ^ Q mod prime */ + M = S; + /* M = S */ + mp_set(&two, 2uL); + + for (;;) { + if ((err = mp_copy(&T, &t1)) != MP_OKAY) goto LBL_END; + i = 0; + for (;;) { + if (mp_cmp_d(&t1, 1uL) == MP_EQ) break; + /* No exponent in the range 0 < i < M found + (M is at least 1 in the first round because "prime" > 2) */ + if (M == i) { + err = MP_VAL; + goto LBL_END; + } + if ((err = mp_exptmod(&t1, &two, prime, &t1)) != MP_OKAY) goto LBL_END; + i++; + } + if (i == 0) { + if ((err = mp_copy(&R, ret)) != MP_OKAY) goto LBL_END; + err = MP_OKAY; + goto LBL_END; + } + mp_set_i32(&t1, M - i - 1); + if ((err = mp_exptmod(&two, &t1, prime, &t1)) != MP_OKAY) goto LBL_END; + /* t1 = 2 ^ (M - i - 1) */ + if ((err = mp_exptmod(&C, &t1, prime, &t1)) != MP_OKAY) goto LBL_END; + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ + if ((err = mp_sqrmod(&t1, prime, &C)) != MP_OKAY) goto LBL_END; + /* C = (t1 * t1) mod prime */ + if ((err = mp_mulmod(&R, &t1, prime, &R)) != MP_OKAY) goto LBL_END; + /* R = (R * t1) mod prime */ + if ((err = mp_mulmod(&T, &C, prime, &T)) != MP_OKAY) goto LBL_END; + /* T = (T * C) mod prime */ + M = i; + /* M = i */ + } + +LBL_END: + mp_clear_multi(&t1, &C, &Q, &Z, &T, &R, &two, NULL); + return err; +} + +#endif diff --git a/deps/libtommath/mp_sub.c b/deps/libtommath/mp_sub.c new file mode 100644 index 0000000..1c95ad5 --- /dev/null +++ b/deps/libtommath/mp_sub.c @@ -0,0 +1,36 @@ +#include "tommath_private.h" +#ifdef MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* high level subtraction (handles signs) */ +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) +{ + if (a->sign != b->sign) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = a->sign; + return s_mp_add(a, b, c); + } + + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (mp_cmp_mag(a, b) == MP_LT) { + /* The second has a larger magnitude */ + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (!mp_isneg(a) ? MP_NEG : MP_ZPOS); + MP_EXCH(const mp_int *, a, b); + } else { + /* The first has a larger or equal magnitude */ + /* Copy the sign from the first */ + c->sign = a->sign; + } + return s_mp_sub(a, b, c); +} + +#endif diff --git a/deps/libtommath/mp_sub_d.c b/deps/libtommath/mp_sub_d.c new file mode 100644 index 0000000..b2b4d72 --- /dev/null +++ b/deps/libtommath/mp_sub_d.c @@ -0,0 +1,78 @@ +#include "tommath_private.h" +#ifdef MP_SUB_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single digit subtraction */ +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) +{ + mp_err err; + int oldused; + + /* fast path for a == c */ + if (a == c) { + if ((c->sign == MP_NEG) && + ((c->dp[0] + b) < MP_DIGIT_MAX)) { + c->dp[0] += b; + return MP_OKAY; + } + if ((c->sign == MP_ZPOS) && + (c->dp[0] > b)) { + c->dp[0] -= b; + return MP_OKAY; + } + } + + /* grow c as required */ + if ((err = mp_grow(c, a->used + 1)) != MP_OKAY) { + return err; + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + mp_int a_ = *a; + a_.sign = MP_ZPOS; + err = mp_add_d(&a_, b, c); + c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return err; + } + + oldused = c->used; + + /* if a <= b simply fix the single digit */ + if (((a->used == 1) && (a->dp[0] <= b)) || mp_iszero(a)) { + c->dp[0] = (a->used == 1) ? b - a->dp[0] : b; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + int i; + mp_digit mu = b; + + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract digits, mu is carry */ + for (i = 0; i < a->used; i++) { + c->dp[i] = a->dp[i] - mu; + mu = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u); + c->dp[i] &= MP_MASK; + } + } + + /* zero excess digits */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} + +#endif diff --git a/deps/libtommath/mp_submod.c b/deps/libtommath/mp_submod.c new file mode 100644 index 0000000..6e4d4f7 --- /dev/null +++ b/deps/libtommath/mp_submod.c @@ -0,0 +1,15 @@ +#include "tommath_private.h" +#ifdef MP_SUBMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* d = a - b (mod c) */ +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) +{ + mp_err err; + if ((err = mp_sub(a, b, d)) != MP_OKAY) { + return err; + } + return mp_mod(d, c, d); +} +#endif diff --git a/deps/libtommath/mp_to_radix.c b/deps/libtommath/mp_to_radix.c new file mode 100644 index 0000000..1e5e671 --- /dev/null +++ b/deps/libtommath/mp_to_radix.c @@ -0,0 +1,95 @@ +#include "tommath_private.h" +#ifdef MP_TO_RADIX_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* reverse an array, used for radix code */ +static void s_reverse(char *s, size_t len) +{ + size_t ix = 0, iy = len - 1u; + while (ix < iy) { + MP_EXCH(char, s[ix], s[iy]); + ++ix; + --iy; + } +} + +/* stores a bignum as a ASCII string in a given radix (2..64) + * + * Stores upto "size - 1" chars and always a NULL byte, puts the number of characters + * written, including the '\0', in "written". + */ +mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) +{ + size_t digs; + mp_err err; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of radix and size*/ + if (maxlen < 2u) { + return MP_BUF; + } + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a)) { + *str++ = '0'; + *str = '\0'; + if (written != NULL) { + *written = 2u; + } + return MP_OKAY; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + /* if it is negative output a - */ + if (mp_isneg(&t)) { + /* we have to reverse our digits later... but not the - sign!! */ + ++_s; + + /* store the flag and mark the number as positive */ + *str++ = '-'; + t.sign = MP_ZPOS; + + /* subtract a char */ + --maxlen; + } + digs = 0u; + while (!mp_iszero(&t)) { + if (--maxlen < 1u) { + /* no more room */ + err = MP_BUF; + goto LBL_ERR; + } + if ((err = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { + goto LBL_ERR; + } + *str++ = s_mp_radix_map[d]; + ++digs; + } + /* reverse the digits of the string. In this case _s points + * to the first digit [excluding the sign] of the number + */ + s_reverse(_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + digs++; + + if (written != NULL) { + *written = mp_isneg(a) ? (digs + 1u): digs; + } + +LBL_ERR: + mp_clear(&t); + return err; +} + +#endif diff --git a/deps/libtommath/mp_to_sbin.c b/deps/libtommath/mp_to_sbin.c new file mode 100644 index 0000000..00884c3 --- /dev/null +++ b/deps/libtommath/mp_to_sbin.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef MP_TO_SBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in signed [big endian] format */ +mp_err mp_to_sbin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) +{ + mp_err err; + if (maxlen == 0u) { + return MP_BUF; + } + if ((err = mp_to_ubin(a, buf + 1, maxlen - 1u, written)) != MP_OKAY) { + return err; + } + if (written != NULL) { + (*written)++; + } + buf[0] = mp_isneg(a) ? (uint8_t)1 : (uint8_t)0; + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_to_ubin.c b/deps/libtommath/mp_to_ubin.c new file mode 100644 index 0000000..e8643cc --- /dev/null +++ b/deps/libtommath/mp_to_ubin.c @@ -0,0 +1,37 @@ +#include "tommath_private.h" +#ifdef MP_TO_UBIN_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* store in unsigned [big endian] format */ +mp_err mp_to_ubin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) +{ + size_t x, count; + mp_err err; + mp_int t; + + count = mp_ubin_size(a); + if (count > maxlen) { + return MP_BUF; + } + + if ((err = mp_init_copy(&t, a)) != MP_OKAY) { + return err; + } + + for (x = count; x --> 0u;) { + buf[x] = (uint8_t)(t.dp[0] & 255u); + if ((err = mp_div_2d(&t, 8, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + } + + if (written != NULL) { + *written = count; + } + +LBL_ERR: + mp_clear(&t); + return err; +} +#endif diff --git a/deps/libtommath/mp_ubin_size.c b/deps/libtommath/mp_ubin_size.c new file mode 100644 index 0000000..4f16404 --- /dev/null +++ b/deps/libtommath/mp_ubin_size.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef MP_UBIN_SIZE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* get the size for an unsigned equivalent */ +size_t mp_ubin_size(const mp_int *a) +{ + size_t size = (size_t)mp_count_bits(a); + return (size / 8u) + (((size & 7u) != 0u) ? 1u : 0u); +} +#endif diff --git a/deps/libtommath/mp_unpack.c b/deps/libtommath/mp_unpack.c new file mode 100644 index 0000000..f0127fa --- /dev/null +++ b/deps/libtommath/mp_unpack.c @@ -0,0 +1,49 @@ +#include "tommath_private.h" +#ifdef MP_UNPACK_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on gmp's mpz_import. + * see http://gmplib.org/manual/Integer-Import-and-Export.html + */ +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, + mp_endian endian, size_t nails, const void *op) +{ + mp_err err; + size_t odd_nails, nail_bytes, i, j; + uint8_t odd_nail_mask; + + mp_zero(rop); + + if (endian == MP_NATIVE_ENDIAN) { + MP_GET_ENDIANNESS(endian); + } + + odd_nails = (nails % 8u); + odd_nail_mask = 0xff; + for (i = 0; i < odd_nails; ++i) { + odd_nail_mask ^= (uint8_t)(1u << (7u - i)); + } + nail_bytes = nails / 8u; + + for (i = 0; i < count; ++i) { + for (j = 0; j < (size - nail_bytes); ++j) { + uint8_t byte = *((const uint8_t *)op + + (((order == MP_MSB_FIRST) ? i : ((count - 1u) - i)) * size) + + ((endian == MP_BIG_ENDIAN) ? (j + nail_bytes) : (((size - 1u) - j) - nail_bytes))); + + if ((err = mp_mul_2d(rop, (j == 0u) ? (int)(8u - odd_nails) : 8, rop)) != MP_OKAY) { + return err; + } + + rop->dp[0] |= (j == 0u) ? (mp_digit)(byte & odd_nail_mask) : (mp_digit)byte; + rop->used += 1; + } + } + + mp_clamp(rop); + + return MP_OKAY; +} + +#endif diff --git a/deps/libtommath/mp_xor.c b/deps/libtommath/mp_xor.c new file mode 100644 index 0000000..ff26419 --- /dev/null +++ b/deps/libtommath/mp_xor.c @@ -0,0 +1,54 @@ +#include "tommath_private.h" +#ifdef MP_XOR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* two complement xor */ +mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c) +{ + int used = MP_MAX(a->used, b->used) + 1, i; + mp_err err; + mp_digit ac = 1, bc = 1, cc = 1; + bool neg = (a->sign != b->sign); + + if ((err = mp_grow(c, used)) != MP_OKAY) { + return err; + } + + for (i = 0; i < used; i++) { + mp_digit x, y; + + /* convert to two complement if negative */ + if (mp_isneg(a)) { + ac += (i >= a->used) ? MP_MASK : (~a->dp[i] & MP_MASK); + x = ac & MP_MASK; + ac >>= MP_DIGIT_BIT; + } else { + x = (i >= a->used) ? 0uL : a->dp[i]; + } + + /* convert to two complement if negative */ + if (mp_isneg(b)) { + bc += (i >= b->used) ? MP_MASK : (~b->dp[i] & MP_MASK); + y = bc & MP_MASK; + bc >>= MP_DIGIT_BIT; + } else { + y = (i >= b->used) ? 0uL : b->dp[i]; + } + + c->dp[i] = x ^ y; + + /* convert to to sign-magnitude if negative */ + if (neg) { + cc += ~c->dp[i] & MP_MASK; + c->dp[i] = cc & MP_MASK; + cc >>= MP_DIGIT_BIT; + } + } + + c->used = used; + c->sign = (neg ? MP_NEG : MP_ZPOS); + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/mp_zero.c b/deps/libtommath/mp_zero.c new file mode 100644 index 0000000..48b60e4 --- /dev/null +++ b/deps/libtommath/mp_zero.c @@ -0,0 +1,13 @@ +#include "tommath_private.h" +#ifdef MP_ZERO_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* set to zero */ +void mp_zero(mp_int *a) +{ + a->sign = MP_ZPOS; + s_mp_zero_digs(a->dp, a->used); + a->used = 0; +} +#endif diff --git a/deps/libtommath/s_mp_add.c b/deps/libtommath/s_mp_add.c new file mode 100644 index 0000000..2bda2fe --- /dev/null +++ b/deps/libtommath/s_mp_add.c @@ -0,0 +1,70 @@ +#include "tommath_private.h" +#ifdef S_MP_ADD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) +{ + int oldused, min, max, i; + mp_digit u; + mp_err err; + + /* find sizes, we let |a| <= |b| which means we have to sort + * them. "x" will point to the input with the most digits + */ + if (a->used < b->used) { + MP_EXCH(const mp_int *, a, b); + } + + min = b->used; + max = a->used; + + /* init result */ + if ((err = mp_grow(c, max + 1)) != MP_OKAY) { + return err; + } + + /* get old used digit count and set new one */ + oldused = c->used; + c->used = max + 1; + + /* zero the carry */ + u = 0; + for (i = 0; i < min; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + c->dp[i] = a->dp[i] + b->dp[i] + u; + + /* U = carry bit of T[i] */ + u = c->dp[i] >> (mp_digit)MP_DIGIT_BIT; + + /* take away carry bit from T[i] */ + c->dp[i] &= MP_MASK; + } + + /* now copy higher words if any, that is in A+B + * if A or B has more digits add those in + */ + if (min != max) { + for (; i < max; i++) { + /* T[i] = A[i] + U */ + c->dp[i] = a->dp[i] + u; + + /* U = carry bit of T[i] */ + u = c->dp[i] >> (mp_digit)MP_DIGIT_BIT; + + /* take away carry bit from T[i] */ + c->dp[i] &= MP_MASK; + } + } + + /* add carry */ + c->dp[i] = u; + + /* clear digits above oldused */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_copy_digs.c b/deps/libtommath/s_mp_copy_digs.c new file mode 100644 index 0000000..4079c33 --- /dev/null +++ b/deps/libtommath/s_mp_copy_digs.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef S_MP_COPY_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_USE_MEMOPS +# include +#endif + +void s_mp_copy_digs(mp_digit *d, const mp_digit *s, int digits) +{ +#ifdef MP_USE_MEMOPS + if (digits > 0) { + memcpy(d, s, (size_t)digits * sizeof(mp_digit)); + } +#else + while (digits-- > 0) { + *d++ = *s++; + } +#endif +} + +#endif diff --git a/deps/libtommath/s_mp_div_3.c b/deps/libtommath/s_mp_div_3.c new file mode 100644 index 0000000..1cc6d3d --- /dev/null +++ b/deps/libtommath/s_mp_div_3.c @@ -0,0 +1,64 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_3_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* divide by three (based on routine from MPI and the GMP manual) */ +mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) +{ + mp_int q; + mp_word w; + mp_digit b; + mp_err err; + int ix; + + /* b = 2**MP_DIGIT_BIT / 3 */ + b = ((mp_word)1 << (mp_word)MP_DIGIT_BIT) / (mp_word)3; + + if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { + return err; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used; ix --> 0;) { + mp_word t; + w = (w << (mp_word)MP_DIGIT_BIT) | (mp_word)a->dp[ix]; + + if (w >= 3u) { + /* multiply w by [1/3] */ + t = (w * (mp_word)b) >> (mp_word)MP_DIGIT_BIT; + + /* now subtract 3 * [w/3] from w, to get the remainder */ + w -= t+t+t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ + while (w >= 3u) { + t += 1u; + w -= 3u; + } + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + /* [optional] store the remainder */ + if (d != NULL) { + *d = (mp_digit)w; + } + + /* [optional] store the quotient */ + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return MP_OKAY; +} + +#endif diff --git a/deps/libtommath/s_mp_div_recursive.c b/deps/libtommath/s_mp_div_recursive.c new file mode 100644 index 0000000..d719c4e --- /dev/null +++ b/deps/libtommath/s_mp_div_recursive.c @@ -0,0 +1,159 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_RECURSIVE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + Direct implementation of algorithms 1.8 "RecursiveDivRem" and 1.9 "UnbalancedDivision" + from: + + Brent, Richard P., and Paul Zimmermann. "Modern computer arithmetic" + Vol. 18. Cambridge University Press, 2010 + Available online at https://arxiv.org/pdf/1004.4710 + + pages 19ff. in the above online document. +*/ + +static mp_err s_recursion(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) +{ + mp_err err; + mp_int A1, A2, B1, B0, Q1, Q0, R1, R0, t; + int m = a->used - b->used, k = m/2; + + if (m < (MP_MUL_KARATSUBA_CUTOFF)) { + return s_mp_div_school(a, b, q, r); + } + + if ((err = mp_init_multi(&A1, &A2, &B1, &B0, &Q1, &Q0, &R1, &R0, &t, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + /* B1 = b / beta^k, B0 = b % beta^k*/ + if ((err = mp_div_2d(b, k * MP_DIGIT_BIT, &B1, &B0)) != MP_OKAY) goto LBL_ERR; + + /* (Q1, R1) = RecursiveDivRem(A / beta^(2k), B1) */ + if ((err = mp_div_2d(a, 2*k * MP_DIGIT_BIT, &A1, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = s_recursion(&A1, &B1, &Q1, &R1)) != MP_OKAY) goto LBL_ERR; + + /* A1 = (R1 * beta^(2k)) + (A % beta^(2k)) - (Q1 * B0 * beta^k) */ + if ((err = mp_lshd(&R1, 2*k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&R1, &t, &A1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&Q1, &B0, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&t, k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&A1, &t, &A1)) != MP_OKAY) goto LBL_ERR; + + /* while A1 < 0 do Q1 = Q1 - 1, A1 = A1 + (beta^k * B) */ + if (mp_cmp_d(&A1, 0uL) == MP_LT) { + if ((err = mp_mul_2d(b, k * MP_DIGIT_BIT, &t)) != MP_OKAY) goto LBL_ERR; + do { + if ((err = mp_decr(&Q1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&A1, &t, &A1)) != MP_OKAY) goto LBL_ERR; + } while (mp_cmp_d(&A1, 0uL) == MP_LT); + } + /* (Q0, R0) = RecursiveDivRem(A1 / beta^(k), B1) */ + if ((err = mp_div_2d(&A1, k * MP_DIGIT_BIT, &A1, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = s_recursion(&A1, &B1, &Q0, &R0)) != MP_OKAY) goto LBL_ERR; + + /* A2 = (R0*beta^k) + (A1 % beta^k) - (Q0*B0) */ + if ((err = mp_lshd(&R0, k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&R0, &t, &A2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul(&Q0, &B0, &t)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&A2, &t, &A2)) != MP_OKAY) goto LBL_ERR; + + /* while A2 < 0 do Q0 = Q0 - 1, A2 = A2 + B */ + while (mp_cmp_d(&A2, 0uL) == MP_LT) { + if ((err = mp_decr(&Q0)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&A2, b, &A2)) != MP_OKAY) goto LBL_ERR; + } + /* return q = (Q1*beta^k) + Q0, r = A2 */ + if ((err = mp_lshd(&Q1, k)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&Q1, &Q0, q)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_copy(&A2, r)) != MP_OKAY) goto LBL_ERR; + +LBL_ERR: + mp_clear_multi(&A1, &A2, &B1, &B0, &Q1, &Q0, &R1, &R0, &t, NULL); + return err; +} + + +mp_err s_mp_div_recursive(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) +{ + int j, m, n, sigma; + mp_err err; + bool neg; + mp_digit msb_b, msb; + mp_int A, B, Q, Q1, R, A_div, A_mod; + + if ((err = mp_init_multi(&A, &B, &Q, &Q1, &R, &A_div, &A_mod, NULL)) != MP_OKAY) { + goto LBL_ERR; + } + + /* most significant bit of a limb */ + /* assumes MP_DIGIT_MAX < (sizeof(mp_digit) * CHAR_BIT) */ + msb = (MP_DIGIT_MAX + (mp_digit)(1)) >> 1; + sigma = 0; + msb_b = b->dp[b->used - 1]; + while (msb_b < msb) { + sigma++; + msb_b <<= 1; + } + /* Use that sigma to normalize B */ + if ((err = mp_mul_2d(b, sigma, &B)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_mul_2d(a, sigma, &A)) != MP_OKAY) { + goto LBL_ERR; + } + + /* fix the sign */ + neg = (a->sign != b->sign); + A.sign = B.sign = MP_ZPOS; + + /* + If the magnitude of "A" is not more more than twice that of "B" we can work + on them directly, otherwise we need to work at "A" in chunks + */ + n = B.used; + m = A.used - B.used; + + /* Q = 0 */ + mp_zero(&Q); + while (m > n) { + /* (q, r) = RecursiveDivRem(A / (beta^(m-n)), B) */ + j = (m - n) * MP_DIGIT_BIT; + if ((err = mp_div_2d(&A, j, &A_div, &A_mod)) != MP_OKAY) goto LBL_ERR; + if ((err = s_recursion(&A_div, &B, &Q1, &R)) != MP_OKAY) goto LBL_ERR; + /* Q = (Q*beta!(n)) + q */ + if ((err = mp_mul_2d(&Q, n * MP_DIGIT_BIT, &Q)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&Q, &Q1, &Q)) != MP_OKAY) goto LBL_ERR; + /* A = (r * beta^(m-n)) + (A % beta^(m-n))*/ + if ((err = mp_mul_2d(&R, (m - n) * MP_DIGIT_BIT, &R)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&R, &A_mod, &A)) != MP_OKAY) goto LBL_ERR; + /* m = m - n */ + m = m - n; + } + /* (q, r) = RecursiveDivRem(A, B) */ + if ((err = s_recursion(&A, &B, &Q1, &R)) != MP_OKAY) goto LBL_ERR; + /* Q = (Q * beta^m) + q, R = r */ + if ((err = mp_mul_2d(&Q, m * MP_DIGIT_BIT, &Q)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&Q, &Q1, &Q)) != MP_OKAY) goto LBL_ERR; + + /* get sign before writing to c */ + R.sign = (mp_iszero(&Q) ? MP_ZPOS : a->sign); + + if (q != NULL) { + mp_exch(&Q, q); + q->sign = (neg ? MP_NEG : MP_ZPOS); + } + if (r != NULL) { + /* de-normalize the remainder */ + if ((err = mp_div_2d(&R, sigma, &R, NULL)) != MP_OKAY) goto LBL_ERR; + mp_exch(&R, r); + } +LBL_ERR: + mp_clear_multi(&A, &B, &Q, &Q1, &R, &A_div, &A_mod, NULL); + return err; +} + +#endif diff --git a/deps/libtommath/s_mp_div_school.c b/deps/libtommath/s_mp_div_school.c new file mode 100644 index 0000000..304c7a9 --- /dev/null +++ b/deps/libtommath/s_mp_div_school.c @@ -0,0 +1,159 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_SCHOOL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* integer signed division. + * c*b + d == a [e.g. a/b, c=quotient, d=remainder] + * HAC pp.598 Algorithm 14.20 + * + * Note that the description in HAC is horribly + * incomplete. For example, it doesn't consider + * the case where digits are removed from 'x' in + * the inner loop. It also doesn't consider the + * case that y has fewer than three digits, etc.. + * + * The overall algorithm is as described as + * 14.20 from HAC but fixed to treat these cases. +*/ +mp_err s_mp_div_school(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_int q, x, y, t1, t2; + mp_digit xdpi; + int n, t, i, norm; + bool neg; + mp_err err; + + if ((err = mp_init_size(&q, a->used + 2)) != MP_OKAY) { + return err; + } + q.used = a->used + 2; + + if ((err = mp_init(&t1)) != MP_OKAY) goto LBL_Q; + if ((err = mp_init(&t2)) != MP_OKAY) goto LBL_T1; + if ((err = mp_init_copy(&x, a)) != MP_OKAY) goto LBL_T2; + if ((err = mp_init_copy(&y, b)) != MP_OKAY) goto LBL_X; + + /* fix the sign */ + neg = (a->sign != b->sign); + x.sign = y.sign = MP_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT] */ + norm = mp_count_bits(&y) % MP_DIGIT_BIT; + if (norm < (MP_DIGIT_BIT - 1)) { + norm = (MP_DIGIT_BIT - 1) - norm; + if ((err = mp_mul_2d(&x, norm, &x)) != MP_OKAY) goto LBL_Y; + if ((err = mp_mul_2d(&y, norm, &y)) != MP_OKAY) goto LBL_Y; + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + /* y = y*b**{n-t} */ + if ((err = mp_lshd(&y, n - t)) != MP_OKAY) goto LBL_Y; + + while (mp_cmp(&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((err = mp_sub(&x, &y, &x)) != MP_OKAY) goto LBL_Y; + } + + /* reset y by shifting it back down */ + mp_rshd(&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) { + continue; + } + /* Do not assume that more than enough memory is automatically allocated and set to '0' */ + xdpi = (i == x.used) ? 0u : x.dp[i]; + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (xdpi == y.dp[t]) { + q.dp[(i - t) - 1] = ((mp_digit)1 << (mp_digit)MP_DIGIT_BIT) - (mp_digit)1; + } else { + mp_word tmp; + tmp = (mp_word)xdpi << (mp_word)MP_DIGIT_BIT; + tmp |= (mp_word)x.dp[i - 1]; + tmp /= (mp_word)y.dp[t]; + if (tmp > (mp_word)MP_MASK) { + tmp = MP_MASK; + } + q.dp[(i - t) - 1] = (mp_digit)(tmp & (mp_word)MP_MASK); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] + 1uL) & (mp_digit)MP_MASK; + do { + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & (mp_digit)MP_MASK; + + /* find left hand */ + mp_zero(&t1); + t1.dp[0] = ((t - 1) < 0) ? 0u : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((err = mp_mul_d(&t1, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + + /* find right hand */ + t2.dp[0] = ((i - 2) < 0) ? 0u : x.dp[i - 2]; + t2.dp[1] = x.dp[i - 1]; /* i >= 1 always holds */ + t2.dp[2] = xdpi; + t2.used = 3; + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + if ((err = mp_mul_d(&y, q.dp[(i - t) - 1], &t1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_sub(&x, &t1, &x)) != MP_OKAY) goto LBL_Y; + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (mp_isneg(&x)) { + if ((err = mp_copy(&y, &t1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_lshd(&t1, (i - t) - 1)) != MP_OKAY) goto LBL_Y; + if ((err = mp_add(&x, &t1, &x)) != MP_OKAY) goto LBL_Y; + + q.dp[(i - t) - 1] = (q.dp[(i - t) - 1] - 1uL) & MP_MASK; + } + } + + /* now q is the quotient and x is the remainder + * [which we have to normalize] + */ + + /* get sign before writing to c */ + x.sign = mp_iszero(&x) ? MP_ZPOS : a->sign; + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + c->sign = (neg ? MP_NEG : MP_ZPOS); + } + + if (d != NULL) { + if ((err = mp_div_2d(&x, norm, &x, NULL)) != MP_OKAY) goto LBL_Y; + mp_exch(&x, d); + } + +LBL_Y: + mp_clear(&y); +LBL_X: + mp_clear(&x); +LBL_T2: + mp_clear(&t2); +LBL_T1: + mp_clear(&t1); +LBL_Q: + mp_clear(&q); + return err; +} + +#endif diff --git a/deps/libtommath/s_mp_div_small.c b/deps/libtommath/s_mp_div_small.c new file mode 100644 index 0000000..2d951be --- /dev/null +++ b/deps/libtommath/s_mp_div_small.c @@ -0,0 +1,51 @@ +#include "tommath_private.h" +#ifdef S_MP_DIV_SMALL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* slower bit-bang division... also smaller */ +mp_err s_mp_div_small(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) +{ + mp_int ta, tb, tq, q; + int n; + bool neg; + mp_err err; + + /* init our temps */ + if ((err = mp_init_multi(&ta, &tb, &tq, &q, NULL)) != MP_OKAY) { + return err; + } + + mp_set(&tq, 1uL); + n = mp_count_bits(a) - mp_count_bits(b); + if ((err = mp_abs(a, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_abs(b, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_mul_2d(&tq, n, &tq)) != MP_OKAY) goto LBL_ERR; + + while (n-- >= 0) { + if (mp_cmp(&tb, &ta) != MP_GT) { + if ((err = mp_sub(&ta, &tb, &ta)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&q, &tq, &q)) != MP_OKAY) goto LBL_ERR; + } + if ((err = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY) goto LBL_ERR; + } + + /* now q == quotient and ta == remainder */ + + neg = (a->sign != b->sign); + if (c != NULL) { + mp_exch(c, &q); + c->sign = ((neg && !mp_iszero(c)) ? MP_NEG : MP_ZPOS); + } + if (d != NULL) { + mp_exch(d, &ta); + d->sign = (mp_iszero(d) ? MP_ZPOS : a->sign); + } +LBL_ERR: + mp_clear_multi(&ta, &tb, &tq, &q, NULL); + return err; +} + +#endif diff --git a/deps/libtommath/s_mp_exptmod.c b/deps/libtommath/s_mp_exptmod.c new file mode 100644 index 0000000..2a89a2c --- /dev/null +++ b/deps/libtommath/s_mp_exptmod.c @@ -0,0 +1,198 @@ +#include "tommath_private.h" +#ifdef S_MP_EXPTMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_LOW_MEM +# define TAB_SIZE 32 +# define MAX_WINSIZE 5 +#else +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 +#endif + +mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + mp_int M[TAB_SIZE], res, mu; + mp_digit buf; + mp_err err; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err(*redux)(mp_int *x, const mp_int *m, const mp_int *mu); + + /* find window size */ + x = mp_count_bits(X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear(&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* create mu, used for Barrett reduction */ + if ((err = mp_init(&mu)) != MP_OKAY) goto LBL_M; + + if (redmode == 0) { + if ((err = mp_reduce_setup(&mu, P)) != MP_OKAY) goto LBL_MU; + redux = mp_reduce; + } else { + if ((err = mp_reduce_2k_setup_l(P, &mu)) != MP_OKAY) goto LBL_MU; + redux = mp_reduce_2k_l; + } + + /* create M table + * + * The M table contains powers of the base, + * e.g. M[x] = G**x mod P + * + * The first half of the table is not + * computed though accept for M[0] and M[1] + */ + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) goto LBL_MU; + + /* compute the value at M[1<<(winsize-1)] by squaring + * M[1] (winsize-1) times + */ + if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; + + for (x = 0; x < (winsize - 1); x++) { + /* square it */ + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], + &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_MU; + + /* reduce modulo P */ + if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, &mu)) != MP_OKAY) goto LBL_MU; + } + + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) goto LBL_MU; + if ((err = redux(&M[x], P, &mu)) != MP_OKAY) goto LBL_MU; + } + + /* setup result */ + if ((err = mp_init(&res)) != MP_OKAY) goto LBL_MU; + mp_set(&res, 1uL); + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ + if (digidx == -1) { + break; + } + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)MP_DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(MP_DIGIT_BIT - 1)) & 1uL; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if ((mode == 0) && (y == 0)) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if ((mode == 1) && (y == 0)) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + } + + /* then multiply */ + if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if ((mode == 2) && (bitcpy > 0)) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, &mu)) != MP_OKAY) goto LBL_RES; + } + } + } + + mp_exch(&res, Y); + err = MP_OKAY; +LBL_RES: + mp_clear(&res); +LBL_MU: + mp_clear(&mu); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear(&M[x]); + } + return err; +} +#endif diff --git a/deps/libtommath/s_mp_exptmod_fast.c b/deps/libtommath/s_mp_exptmod_fast.c new file mode 100644 index 0000000..e7729f4 --- /dev/null +++ b/deps/libtommath/s_mp_exptmod_fast.c @@ -0,0 +1,254 @@ +#include "tommath_private.h" +#ifdef S_MP_EXPTMOD_FAST_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 + * + * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. + * The value of k changes based on the size of the exponent. + * + * Uses Montgomery or Diminished Radix reduction [whichever appropriate] + */ + +#ifdef MP_LOW_MEM +# define TAB_SIZE 32 +# define MAX_WINSIZE 5 +#else +# define TAB_SIZE 256 +# define MAX_WINSIZE 0 +#endif + +mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) +{ + mp_int M[TAB_SIZE], res; + mp_digit buf, mp; + int bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_err err; + + /* use a pointer to the reduction algorithm. This allows us to use + * one of many reduction algorithms without modding the guts of + * the code with if statements everywhere. + */ + mp_err(*redux)(mp_int *x, const mp_int *n, mp_digit rho); + + /* find window size */ + x = mp_count_bits(X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; + + /* init M array */ + /* init first cell */ + if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear(&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* determine and setup reduction code */ + if (redmode == 0) { + if (MP_HAS(MP_MONTGOMERY_SETUP)) { + /* now setup montgomery */ + if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) goto LBL_M; + } else { + err = MP_VAL; + goto LBL_M; + } + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ + if (MP_HAS(S_MP_MONTGOMERY_REDUCE_COMBA) && + (((P->used * 2) + 1) < MP_WARRAY) && + (P->used < MP_MAX_COMBA)) { + redux = s_mp_montgomery_reduce_comba; + } else if (MP_HAS(MP_MONTGOMERY_REDUCE)) { + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; + } else { + err = MP_VAL; + goto LBL_M; + } + } else if (redmode == 1) { + if (MP_HAS(MP_DR_SETUP) && MP_HAS(MP_DR_REDUCE)) { + /* setup DR reduction for moduli of the form B**k - b */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; + } else { + err = MP_VAL; + goto LBL_M; + } + } else if (MP_HAS(MP_REDUCE_2K_SETUP) && MP_HAS(MP_REDUCE_2K)) { + /* setup DR reduction for moduli of the form 2**k - b */ + if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) goto LBL_M; + redux = mp_reduce_2k; + } else { + err = MP_VAL; + goto LBL_M; + } + + /* setup result */ + if ((err = mp_init_size(&res, P->alloc)) != MP_OKAY) goto LBL_M; + + /* create M table + * + + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + + if (redmode == 0) { + if (MP_HAS(MP_MONTGOMERY_CALC_NORMALIZATION)) { + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) goto LBL_RES; + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) goto LBL_RES; + } else { + err = MP_VAL; + goto LBL_RES; + } + } else { + mp_set(&res, 1uL); + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) goto LBL_RES; + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if ((err = mp_copy(&M[1], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr(&M[(size_t)1 << (winsize - 1)], &M[(size_t)1 << (winsize - 1)])) != MP_OKAY) goto LBL_RES; + if ((err = redux(&M[(size_t)1 << (winsize - 1)], P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul(&M[x - 1], &M[1], &M[x])) != MP_OKAY) goto LBL_RES; + if ((err = redux(&M[x], P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)MP_DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (MP_DIGIT_BIT - 1)) & 1uL; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if ((mode == 0) && (y == 0)) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if ((mode == 1) && (y == 0)) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* then multiply */ + if ((err = mp_mul(&res, &M[bitbuf], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if ((mode == 2) && (bitcpy > 0)) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr(&res, &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul(&res, &M[1], &res)) != MP_OKAY) goto LBL_RES; + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + } + } + } + + if (redmode == 0) { + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + if ((err = redux(&res, P, mp)) != MP_OKAY) goto LBL_RES; + } + + /* swap res with Y */ + mp_exch(&res, Y); + err = MP_OKAY; +LBL_RES: + mp_clear(&res); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear(&M[x]); + } + return err; +} +#endif diff --git a/deps/libtommath/s_mp_fp_log.c b/deps/libtommath/s_mp_fp_log.c new file mode 100644 index 0000000..90a89ab --- /dev/null +++ b/deps/libtommath/s_mp_fp_log.c @@ -0,0 +1,83 @@ +#include "tommath_private.h" +#ifdef S_MP_FP_LOG_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Fixed point bitwise logarithm base two of "a" with precision "p", Big-integer version. */ +static mp_err s_mp_fp_log_fraction(const mp_int *a, int p, mp_int *c) +{ + mp_int b, L_out, twoep, a_bar; + int L, pmL; + int i; + mp_err err; + + if ((err = mp_init_multi(&b, &L_out, &twoep, &a_bar, NULL)) != MP_OKAY) { + return err; + } + + L = mp_count_bits(a) - 1; + pmL = (p < L) ? L - p: p - L; + if ((err = mp_mul_2d(a, pmL, &a_bar)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_2expt(&b, p - 1)) != MP_OKAY) goto LTM_ERR; + mp_set_i32(&L_out, L); + if ((err = mp_mul_2d(&L_out, p, &L_out)) != MP_OKAY) goto LTM_ERR; + + if ((err = mp_2expt(&twoep, p + 1)) != MP_OKAY) goto LTM_ERR; + + for (i = 0; i < p; i++) { + if ((err = mp_sqr(&a_bar, &a_bar)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_div_2d(&a_bar, p, &a_bar, NULL)) != MP_OKAY) goto LTM_ERR; + if (mp_cmp(&a_bar, &twoep) != MP_LT) { + if ((err = mp_div_2(&a_bar, &a_bar)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_add(&L_out, &b, &L_out)) != MP_OKAY) goto LTM_ERR; + } + if ((err = mp_div_2(&b, &b)) != MP_OKAY) goto LTM_ERR; + } + + mp_exch(c, &L_out); + +LTM_ERR: + mp_clear_multi(&b, &L_out, &twoep, &a_bar, NULL); + return err; +} + +mp_err s_mp_fp_log(const mp_int *a, mp_int *c) +{ + mp_int La, t; + mp_err err; + int fla; + /* + We have arbitrary precision here and could adapt "prec" to actual precision, + there is no need for lowering precision for small numbers. Some quick runtime + tests revealed a gain that can only be called marginally at best. + But: YMMV, as always. + */ + int prec = MP_PRECISION_FIXED_LOG; + + fla = mp_count_bits(a) - 1; + + if ((err = mp_init_multi(&La, &t, NULL)) != MP_OKAY) { + return err; + } + + if (fla > prec) { + if ((err = mp_div_2d(a, fla - prec, &t, NULL)) != MP_OKAY) goto LTM_ERR; + if ((err = s_mp_fp_log_fraction(&t, prec, + &La)) != MP_OKAY) goto LTM_ERR; + mp_set_i32(&t,fla - prec); + if ((err = mp_mul_2d(&t,prec, &t)) != MP_OKAY) goto LTM_ERR; + if ((err = mp_add(&La, &t, &La)) != MP_OKAY) goto LTM_ERR; + } else { + if ((err = s_mp_fp_log_fraction(a, prec, + &La)) != MP_OKAY) goto LTM_ERR; + } + + mp_exch(&La, c); + +LTM_ERR: + mp_clear_multi(&La, &t, NULL); + return err; +} + + +#endif diff --git a/deps/libtommath/s_mp_fp_log_d.c b/deps/libtommath/s_mp_fp_log_d.c new file mode 100644 index 0000000..71d82dc --- /dev/null +++ b/deps/libtommath/s_mp_fp_log_d.c @@ -0,0 +1,83 @@ +#include "tommath_private.h" +#ifdef S_MP_FP_LOG_D_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +static mp_word s_mp_flog2_mp_word_d(mp_word value) +{ + mp_word r = 0u; + while ((value >>= 1) != 0u) { + r++; + } + return r; +} + +/* Fixed point bitwise logarithm base two of "x" with precision "p" */ +static mp_err s_mp_fp_log_fraction_d(mp_word x, int p, mp_word *c) +{ + mp_word b, L_out, L, a_bar, twoep; + int i; + + L = s_mp_flog2_mp_word_d(x); + + if ((L + (mp_word)p) > MP_UPPER_LIMIT_FIXED_LOG) { + return MP_VAL; + } + + a_bar = ((mp_word)p < L) ? x << (L - (mp_word)p) : x << ((mp_word)p - L); + b = (mp_word)(1u) << (p - 1); + L_out = L << p; + + twoep = (mp_word)(1u) << (p + 1); + + for (i = 0; i < p; i++) { + a_bar = (a_bar * a_bar) >> p; + if (a_bar >= twoep) { + a_bar >>= 1u; + L_out += b; + } + b >>= 1u; + } + *c = L_out; + return MP_OKAY; +} + +/* Approximate the base two logarithm of "a" */ +mp_err s_mp_fp_log_d(const mp_int *a, mp_word *c) +{ + mp_err err; + int la; + int prec = MP_PRECISION_FIXED_LOG; + mp_word tmp, la_word; + mp_int t; + + la = mp_count_bits(a) - 1; + + /* We don't use the whole number, just the most significant "prec" bits */ + if (la > prec) { + if ((err = mp_init(&t)) != MP_OKAY) goto LTM_ERR; + /* Get enough msb-bits for the chosen precision */ + if ((err = mp_div_2d(a, la - prec, &t, NULL)) != MP_OKAY) goto LTM_ERR; + tmp = mp_get_u64(&t); + /* Compute the low precision approximation for the fractional part */ + if ((err = s_mp_fp_log_fraction_d(tmp, prec, &la_word)) != MP_OKAY) goto LTM_ERR; + /* Compute the integer part and add it */ + tmp = ((mp_word)(la - prec))<= a->used) { + return false; + } + + bit = (mp_digit)1 << (b % MP_DIGIT_BIT); + return ((a->dp[limb] & bit) != 0u); +} + +#endif diff --git a/deps/libtommath/s_mp_invmod.c b/deps/libtommath/s_mp_invmod.c new file mode 100644 index 0000000..b2fb21d --- /dev/null +++ b/deps/libtommath/s_mp_invmod.c @@ -0,0 +1,117 @@ +#include "tommath_private.h" +#ifdef S_MP_INVMOD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* hac 14.61, pp608 */ +mp_err s_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, A, B, C, D; + mp_err err; + + /* b cannot be negative */ + if ((b->sign == MP_NEG) || mp_iszero(b)) { + return MP_VAL; + } + + /* init temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, + &A, &B, &C, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x = a, y = b */ + if ((err = mp_mod(a, b, &x)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(b, &y)) != MP_OKAY) goto LBL_ERR; + + /* 2. [modified] if x,y are both even then return an error! */ + if (mp_iseven(&x) && mp_iseven(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&A, 1uL); + mp_set(&D, 1uL); + + do { + /* 4. while u is even do */ + while (mp_iseven(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if A or B is odd then */ + if (mp_isodd(&A) || mp_isodd(&B)) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((err = mp_add(&A, &y, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* A = A/2, B = B/2 */ + if ((err = mp_div_2(&A, &A)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (mp_iseven(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if C or D is odd then */ + if (mp_isodd(&C) || mp_isodd(&D)) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((err = mp_add(&C, &y, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* C = C/2, D = D/2 */ + if ((err = mp_div_2(&C, &C)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2(&D, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* 6. if u >= v then */ + if (mp_cmp(&u, &v) != MP_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&A, &C, &A)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&C, &A, &C)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + } while (!mp_iszero(&u)); + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* if its too low */ + while (mp_isneg(&C)) { + if ((err = mp_add(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((err = mp_sub(&C, b, &C)) != MP_OKAY) goto LBL_ERR; + } + + /* C is now the inverse */ + mp_exch(&C, c); + +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return err; +} +#endif diff --git a/deps/libtommath/s_mp_invmod_odd.c b/deps/libtommath/s_mp_invmod_odd.c new file mode 100644 index 0000000..11fc357 --- /dev/null +++ b/deps/libtommath/s_mp_invmod_odd.c @@ -0,0 +1,113 @@ +#include "tommath_private.h" +#ifdef S_MP_INVMOD_ODD_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes the modular inverse via binary extended euclidean algorithm, + * that is c = 1/a mod b + * + * Based on slow invmod except this is optimized for the case where b is + * odd as per HAC Note 14.64 on pp. 610 + */ +mp_err s_mp_invmod_odd(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x, y, u, v, B, D; + mp_err err; + + /* 2. [modified] b must be odd */ + if (mp_iseven(b)) { + return MP_VAL; + } + + /* init all our temps */ + if ((err = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return err; + } + + /* x == modulus, y == value to invert */ + if ((err = mp_copy(b, &x)) != MP_OKAY) goto LBL_ERR; + + /* y needs to be positive but the remainder d of mp_div(a,b,c,d) might be negative */ + if ((err = mp_mod(a, b, &y)) != MP_OKAY) goto LBL_ERR; + + /* if one of x,y is zero return an error! */ + if (mp_iszero(&x) || mp_iszero(&y)) { + err = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((err = mp_copy(&x, &u)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_copy(&y, &v)) != MP_OKAY) goto LBL_ERR; + mp_set(&D, 1uL); + + do { + /* 4. while u is even do */ + while (mp_iseven(&u)) { + /* 4.1 u = u/2 */ + if ((err = mp_div_2(&u, &u)) != MP_OKAY) goto LBL_ERR; + + /* 4.2 if B is odd then */ + if (mp_isodd(&B)) { + if ((err = mp_sub(&B, &x, &B)) != MP_OKAY) goto LBL_ERR; + } + /* B = B/2 */ + if ((err = mp_div_2(&B, &B)) != MP_OKAY) goto LBL_ERR; + } + + /* 5. while v is even do */ + while (mp_iseven(&v)) { + /* 5.1 v = v/2 */ + if ((err = mp_div_2(&v, &v)) != MP_OKAY) goto LBL_ERR; + + /* 5.2 if D is odd then */ + if (mp_isodd(&D)) { + /* D = (D-x)/2 */ + if ((err = mp_sub(&D, &x, &D)) != MP_OKAY) goto LBL_ERR; + } + /* D = D/2 */ + if ((err = mp_div_2(&D, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* 6. if u >= v then */ + if (mp_cmp(&u, &v) != MP_LT) { + /* u = u - v, B = B - D */ + if ((err = mp_sub(&u, &v, &u)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&B, &D, &B)) != MP_OKAY) goto LBL_ERR; + } else { + /* v - v - u, D = D - B */ + if ((err = mp_sub(&v, &u, &v)) != MP_OKAY) goto LBL_ERR; + + if ((err = mp_sub(&D, &B, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* if not zero goto step 4 */ + } while (!mp_iszero(&u)); + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d(&v, 1uL) != MP_EQ) { + err = MP_VAL; + goto LBL_ERR; + } + + /* b is now the inverse */ + while (mp_isneg(&D)) { + if ((err = mp_add(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + /* too big */ + while (mp_cmp_mag(&D, b) != MP_LT) { + if ((err = mp_sub(&D, b, &D)) != MP_OKAY) goto LBL_ERR; + } + + mp_exch(&D, c); + err = MP_OKAY; + +LBL_ERR: + mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL); + return err; +} +#endif diff --git a/deps/libtommath/s_mp_log_2expt.c b/deps/libtommath/s_mp_log_2expt.c new file mode 100644 index 0000000..ec0fda3 --- /dev/null +++ b/deps/libtommath/s_mp_log_2expt.c @@ -0,0 +1,12 @@ +#include "tommath_private.h" +#ifdef S_MP_LOG_2EXPT_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +int s_mp_log_2expt(const mp_int *a, mp_digit base) +{ + int y; + for (y = 0; (base & 1) == 0; y++, base >>= 1) {} + return (mp_count_bits(a) - 1) / y; +} +#endif diff --git a/deps/libtommath/s_mp_montgomery_reduce_comba.c b/deps/libtommath/s_mp_montgomery_reduce_comba.c new file mode 100644 index 0000000..7472caf --- /dev/null +++ b/deps/libtommath/s_mp_montgomery_reduce_comba.c @@ -0,0 +1,119 @@ +#include "tommath_private.h" +#ifdef S_MP_MONTGOMERY_REDUCE_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* computes xR**-1 == x (mod N) via Montgomery Reduction + * + * This is an optimized implementation of montgomery_reduce + * which uses the comba method to quickly calculate the columns of the + * reduction. + * + * Based on Algorithm 14.32 on pp.601 of HAC. +*/ +mp_err s_mp_montgomery_reduce_comba(mp_int *x, const mp_int *n, mp_digit rho) +{ + int ix, oldused; + mp_err err; + mp_word W[MP_WARRAY]; + + if (x->used > MP_WARRAY) { + return MP_VAL; + } + + /* get old used count */ + oldused = x->used; + + /* grow a as required */ + if ((err = mp_grow(x, n->used + 1)) != MP_OKAY) { + return err; + } + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + + /* copy the digits of a into W[0..a->used-1] */ + for (ix = 0; ix < x->used; ix++) { + W[ix] = x->dp[ix]; + } + + /* zero the high words of W[a->used..m->used*2] */ + if (ix < ((n->used * 2) + 1)) { + s_mp_zero_buf(W + x->used, sizeof(mp_word) * (size_t)(((n->used * 2) + 1) - ix)); + } + + /* now we proceed to zero successive digits + * from the least significant upwards + */ + for (ix = 0; ix < n->used; ix++) { + int iy; + mp_digit mu; + + /* mu = ai * m' mod b + * + * We avoid a double precision multiplication (which isn't required) + * by casting the value down to a mp_digit. Note this requires + * that W[ix-1] have the carry cleared (see after the inner loop) + */ + mu = ((W[ix] & MP_MASK) * rho) & MP_MASK; + + /* a = a + mu * m * b**i + * + * This is computed in place and on the fly. The multiplication + * by b**i is handled by offsetting which columns the results + * are added to. + * + * Note the comba method normally doesn't handle carries in the + * inner loop In this case we fix the carry from the previous + * column since the Montgomery reduction requires digits of the + * result (so far) [see above] to work. This is + * handled by fixing up one carry after the inner loop. The + * carry fixups are done in order so after these loops the + * first m->used words of W[] have the carries fixed + */ + for (iy = 0; iy < n->used; iy++) { + W[ix + iy] += (mp_word)mu * (mp_word)n->dp[iy]; + } + + /* now fix carry for next digit, W[ix+1] */ + W[ix + 1] += W[ix] >> (mp_word)MP_DIGIT_BIT; + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + + for (; ix < (n->used * 2); ix++) { + W[ix + 1] += W[ix] >> (mp_word)MP_DIGIT_BIT; + } + + /* copy out, A = A/b**n + * + * The result is A/b**n but instead of converting from an + * array of mp_word to mp_digit than calling mp_rshd + * we just copy them in the right order + */ + + for (ix = 0; ix < (n->used + 1); ix++) { + x->dp[ix] = W[n->used + ix] & (mp_word)MP_MASK; + } + + /* set the max used */ + x->used = n->used + 1; + + /* zero oldused digits, if the input a was larger than + * m->used+1 we'll have to clear the digits + */ + s_mp_zero_digs(x->dp + x->used, oldused - x->used); + + mp_clamp(x); + + /* if A >= m then A = A - m */ + if (mp_cmp_mag(x, n) != MP_LT) { + return s_mp_sub(x, n, x); + } + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_mul.c b/deps/libtommath/s_mp_mul.c new file mode 100644 index 0000000..fb99d80 --- /dev/null +++ b/deps/libtommath/s_mp_mul.c @@ -0,0 +1,61 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiplies |a| * |b| and only computes upto digs digits of result + * HAC pp. 595, Algorithm 14.12 Modified so you can control how + * many digits of output are created. + */ +mp_err s_mp_mul(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + mp_int t; + mp_err err; + int pa, ix; + + /* can we use the fast multiplier? */ + if ((digs < MP_WARRAY) && + (MP_MIN(a->used, b->used) < MP_MAX_COMBA)) { + return s_mp_mul_comba(a, b, c, digs); + } + + if ((err = mp_init_size(&t, digs)) != MP_OKAY) { + return err; + } + t.used = digs; + + /* compute the digits of the product directly */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + int iy, pb; + mp_digit u = 0; + + /* limit ourselves to making digs digits of output */ + pb = MP_MIN(b->used, digs - ix); + + /* compute the columns of the output and propagate the carry */ + for (iy = 0; iy < pb; iy++) { + /* compute the column as a mp_word */ + mp_word r = (mp_word)t.dp[ix + iy] + + ((mp_word)a->dp[ix] * (mp_word)b->dp[iy]) + + (mp_word)u; + + /* the new column is the lower part of the result */ + t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + + /* get the carry word from the result */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + /* set carry if it is placed below digs */ + if ((ix + iy) < digs) { + t.dp[ix + pb] = u; + } + } + + mp_clamp(&t); + mp_exch(&t, c); + + mp_clear(&t); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_mul_balance.c b/deps/libtommath/s_mp_mul_balance.c new file mode 100644 index 0000000..f36f0d3 --- /dev/null +++ b/deps/libtommath/s_mp_mul_balance.c @@ -0,0 +1,71 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_BALANCE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* single-digit multiplication with the smaller number as the single-digit */ +mp_err s_mp_mul_balance(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int a0, tmp, r; + mp_err err; + int i, j, + nblocks = MP_MAX(a->used, b->used) / MP_MIN(a->used, b->used), + bsize = MP_MIN(a->used, b->used); + + if ((err = mp_init_size(&a0, bsize + 2)) != MP_OKAY) { + return err; + } + if ((err = mp_init_multi(&tmp, &r, NULL)) != MP_OKAY) { + mp_clear(&a0); + return err; + } + + /* Make sure that A is the larger one*/ + if (a->used < b->used) { + MP_EXCH(const mp_int *, a, b); + } + + for (i = 0, j=0; i < nblocks; i++) { + /* Cut a slice off of a */ + a0.used = bsize; + s_mp_copy_digs(a0.dp, a->dp + j, a0.used); + j += a0.used; + mp_clamp(&a0); + + /* Multiply with b */ + if ((err = mp_mul(&a0, b, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + /* Shift tmp to the correct position */ + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + /* Add to output. No carry needed */ + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* The left-overs; there are always left-overs */ + if (j < a->used) { + a0.used = a->used - j; + s_mp_copy_digs(a0.dp, a->dp + j, a0.used); + j += a0.used; + mp_clamp(&a0); + + if ((err = mp_mul(&a0, b, &tmp)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_lshd(&tmp, bsize * i)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_add(&r, &tmp, &r)) != MP_OKAY) { + goto LBL_ERR; + } + } + + mp_exch(&r,c); +LBL_ERR: + mp_clear_multi(&a0, &tmp, &r,NULL); + return err; +} +#endif diff --git a/deps/libtommath/s_mp_mul_comba.c b/deps/libtommath/s_mp_mul_comba.c new file mode 100644 index 0000000..1afa1fc --- /dev/null +++ b/deps/libtommath/s_mp_mul_comba.c @@ -0,0 +1,78 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Fast (comba) multiplier + * + * This is the fast column-array [comba] multiplier. It is + * designed to compute the columns of the product first + * then handle the carries afterwards. This has the effect + * of making the nested loops that compute the columns very + * simple and schedulable on super-scalar processors. + * + * This has been modified to produce a variable number of + * digits of output so if say only a half-product is required + * you don't have to compute the upper half (a feature + * required for fast Barrett reduction). + * + * Based on Algorithm 14.12 on pp.595 of HAC. + * + */ +mp_err s_mp_mul_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int oldused, pa, ix; + mp_err err; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + if ((err = mp_grow(c, digs)) != MP_OKAY) { + return err; + } + + /* number of output digits to produce */ + pa = MP_MIN(digs, a->used + b->used); + + /* clear the carry */ + _W = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy, iz; + + /* get offsets into the two bignums */ + ty = MP_MIN(b->used-1, ix); + tx = ix - ty; + + /* this is the number of times the loop will iterate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MP_MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; ++iz) { + _W += (mp_word)a->dp[tx + iz] * (mp_word)b->dp[ty - iz]; + } + + /* store term */ + W[ix] = (mp_digit)_W & MP_MASK; + + /* make next carry */ + _W = _W >> (mp_word)MP_DIGIT_BIT; + } + + /* setup dest */ + oldused = c->used; + c->used = pa; + + for (ix = 0; ix < pa; ix++) { + /* now extract the previous digit [below the carry] */ + c->dp[ix] = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_mul_high.c b/deps/libtommath/s_mp_mul_high.c new file mode 100644 index 0000000..1bde00a --- /dev/null +++ b/deps/libtommath/s_mp_mul_high.c @@ -0,0 +1,52 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_HIGH_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +mp_err s_mp_mul_high(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + mp_int t; + int pa, pb, ix; + mp_err err; + + /* can we use the fast multiplier? */ + if (MP_HAS(S_MP_MUL_HIGH_COMBA) + && ((a->used + b->used + 1) < MP_WARRAY) + && (MP_MIN(a->used, b->used) < MP_MAX_COMBA)) { + return s_mp_mul_high_comba(a, b, c, digs); + } + + if ((err = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) { + return err; + } + t.used = a->used + b->used + 1; + + pa = a->used; + pb = b->used; + for (ix = 0; ix < pa; ix++) { + int iy; + mp_digit u = 0; + + for (iy = digs - ix; iy < pb; iy++) { + /* calculate the double precision result */ + mp_word r = (mp_word)t.dp[ix + iy] + + ((mp_word)a->dp[ix] * (mp_word)b->dp[iy]) + + (mp_word)u; + + /* get the lower part */ + t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + + /* carry the carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + t.dp[ix + pb] = u; + } + mp_clamp(&t); + mp_exch(&t, c); + mp_clear(&t); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_mul_high_comba.c b/deps/libtommath/s_mp_mul_high_comba.c new file mode 100644 index 0000000..74960ac --- /dev/null +++ b/deps/libtommath/s_mp_mul_high_comba.c @@ -0,0 +1,70 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_HIGH_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* this is a modified version of s_mp_mul_comba that only produces + * output digits *above* digs. See the comments for s_mp_mul_comba + * to see how it works. + * + * This is used in the Barrett reduction since for one of the multiplications + * only the higher digits were needed. This essentially halves the work. + * + * Based on Algorithm 14.12 on pp.595 of HAC. + */ +mp_err s_mp_mul_high_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) +{ + int oldused, pa, ix; + mp_err err; + mp_digit W[MP_WARRAY]; + mp_word _W; + + /* grow the destination as required */ + pa = a->used + b->used; + if ((err = mp_grow(c, pa)) != MP_OKAY) { + return err; + } + + /* number of output digits to produce */ + pa = a->used + b->used; + _W = 0; + for (ix = digs; ix < pa; ix++) { + int tx, ty, iy, iz; + + /* get offsets into the two bignums */ + ty = MP_MIN(b->used-1, ix); + tx = ix - ty; + + /* this is the number of times the loop will iterate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MP_MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += (mp_word)a->dp[tx + iz] * (mp_word)b->dp[ty - iz]; + } + + /* store term */ + W[ix] = (mp_digit)_W & MP_MASK; + + /* make next carry */ + _W = _W >> (mp_word)MP_DIGIT_BIT; + } + + /* setup dest */ + oldused = c->used; + c->used = pa; + + for (ix = digs; ix < pa; ix++) { + /* now extract the previous digit [below the carry] */ + c->dp[ix] = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_mul_karatsuba.c b/deps/libtommath/s_mp_mul_karatsuba.c new file mode 100644 index 0000000..b465298 --- /dev/null +++ b/deps/libtommath/s_mp_mul_karatsuba.c @@ -0,0 +1,151 @@ +#include "tommath_private.h" +#ifdef S_MP_MUL_KARATSUBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**MP_DIGIT_BIT] and + * let n represent half of the number of digits in + * the min(a,b) + * + * a = a1 * B**n + a0 + * b = b1 * B**n + b0 + * + * Then, a * b => + a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0 + * + * Note that a1b1 and a0b0 are used twice and only need to be + * computed once. So in total three half size (half # of + * digit) multiplications are performed, a0b0, a1b1 and + * (a1+b1)(a0+b0) + * + * Note that a multiplication of half the digits requires + * 1/4th the number of single precision multiplications so in + * total after one call 25% of the single precision multiplications + * are saved. Note also that the call to mp_mul can end up back + * in this function if the a0, a1, b0, or b1 are above the threshold. + * This is known as divide-and-conquer and leads to the famous + * O(N**lg(3)) or O(N**1.584) work which is asymptotically lower than + * the standard O(N**2) that the baseline/comba methods use. + * Generally though the overhead of this method doesn't pay off + * until a certain size (N ~ 80) is reached. + */ +mp_err s_mp_mul_karatsuba(const mp_int *a, const mp_int *b, mp_int *c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B; + mp_err err; + + /* min # of digits */ + B = MP_MIN(a->used, b->used); + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if ((err = mp_init_size(&x0, B)) != MP_OKAY) { + goto LBL_ERR; + } + if ((err = mp_init_size(&x1, a->used - B)) != MP_OKAY) { + goto X0; + } + if ((err = mp_init_size(&y0, B)) != MP_OKAY) { + goto X1; + } + if ((err = mp_init_size(&y1, b->used - B)) != MP_OKAY) { + goto Y0; + } + + /* init temps */ + if ((err = mp_init_size(&t1, B * 2)) != MP_OKAY) { + goto Y1; + } + if ((err = mp_init_size(&x0y0, B * 2)) != MP_OKAY) { + goto T1; + } + if ((err = mp_init_size(&x1y1, B * 2)) != MP_OKAY) { + goto X0Y0; + } + + /* now shift the digits */ + x0.used = y0.used = B; + x1.used = a->used - B; + y1.used = b->used - B; + + /* we copy the digits directly instead of using higher level functions + * since we also need to shift the digits + */ + s_mp_copy_digs(x0.dp, a->dp, x0.used); + s_mp_copy_digs(y0.dp, b->dp, y0.used); + s_mp_copy_digs(x1.dp, a->dp + B, x1.used); + s_mp_copy_digs(y1.dp, b->dp + B, y1.used); + + /* only need to clamp the lower words since by definition the + * upper words x1/y1 must have a known number of digits + */ + mp_clamp(&x0); + mp_clamp(&y0); + + /* now calc the products x0y0 and x1y1 */ + /* after this x0 is no longer required, free temp [x0==t2]! */ + if ((err = mp_mul(&x0, &y0, &x0y0)) != MP_OKAY) { + goto X1Y1; /* x0y0 = x0*y0 */ + } + if ((err = mp_mul(&x1, &y1, &x1y1)) != MP_OKAY) { + goto X1Y1; /* x1y1 = x1*y1 */ + } + + /* now calc x1+x0 and y1+y0 */ + if ((err = s_mp_add(&x1, &x0, &t1)) != MP_OKAY) { + goto X1Y1; /* t1 = x1 - x0 */ + } + if ((err = s_mp_add(&y1, &y0, &x0)) != MP_OKAY) { + goto X1Y1; /* t2 = y1 - y0 */ + } + if ((err = mp_mul(&t1, &x0, &t1)) != MP_OKAY) { + goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */ + } + + /* add x0y0 */ + if ((err = mp_add(&x0y0, &x1y1, &x0)) != MP_OKAY) { + goto X1Y1; /* t2 = x0y0 + x1y1 */ + } + if ((err = s_mp_sub(&t1, &x0, &t1)) != MP_OKAY) { + goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */ + } + + /* shift by B */ + if ((err = mp_lshd(&t1, B)) != MP_OKAY) { + goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<used, b->used) / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + if ((err = mp_init_size(&a2, a->used - 2 * B)) != MP_OKAY) goto LBL_ERRa2; + + a0.used = a1.used = B; + a2.used = a->used - 2 * B; + s_mp_copy_digs(a0.dp, a->dp, a0.used); + s_mp_copy_digs(a1.dp, a->dp + B, a1.used); + s_mp_copy_digs(a2.dp, a->dp + 2 * B, a2.used); + mp_clamp(&a0); + mp_clamp(&a1); + mp_clamp(&a2); + + /** b = b2 * x^2 + b1 * x + b0; */ + if ((err = mp_init_size(&b0, B)) != MP_OKAY) goto LBL_ERRb0; + if ((err = mp_init_size(&b1, B)) != MP_OKAY) goto LBL_ERRb1; + if ((err = mp_init_size(&b2, b->used - 2 * B)) != MP_OKAY) goto LBL_ERRb2; + + b0.used = b1.used = B; + b2.used = b->used - 2 * B; + s_mp_copy_digs(b0.dp, b->dp, b0.used); + s_mp_copy_digs(b1.dp, b->dp + B, b1.used); + s_mp_copy_digs(b2.dp, b->dp + 2 * B, b2.used); + mp_clamp(&b0); + mp_clamp(&b1); + mp_clamp(&b2); + + /** \\ S1 = (a2+a1+a0) * (b2+b1+b0); */ + /** T1 = a2 + a1; */ + if ((err = mp_add(&a2, &a1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &S2)) != MP_OKAY) goto LBL_ERR; + + /** c = b2 + b1; */ + if ((err = mp_add(&b2, &b1, c)) != MP_OKAY) goto LBL_ERR; + + /** S1 = c + b0; */ + if ((err = mp_add(c, &b0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 * S2; */ + if ((err = mp_mul(&S1, &S2, &S1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (4*a2+2*a1+a0) * (4*b2+2*b1+b0); */ + /** T1 = T1 + a2; */ + if ((err = mp_add(&T1, &a2, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 << 1; */ + if ((err = mp_mul_2(&T1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = T1 + a0; */ + if ((err = mp_add(&T1, &a0, &T1)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b2; */ + if ((err = mp_add(c, &b2, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c << 1; */ + if ((err = mp_mul_2(c, c)) != MP_OKAY) goto LBL_ERR; + + /** c = c + b0; */ + if ((err = mp_add(c, &b0, c)) != MP_OKAY) goto LBL_ERR; + + /** S2 = T1 * c; */ + if ((err = mp_mul(&T1, c, &S2)) != MP_OKAY) goto LBL_ERR; + + /** \\S3 = (a2-a1+a0) * (b2-b1+b0); */ + /** a1 = a2 - a1; */ + if ((err = mp_sub(&a2, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 + a0; */ + if ((err = mp_add(&a1, &a0, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b2 - b1; */ + if ((err = mp_sub(&b2, &b1, &b1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = b1 + b0; */ + if ((err = mp_add(&b1, &b0, &b1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 * b1; */ + if ((err = mp_mul(&a1, &b1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** b1 = a2 * b2; */ + if ((err = mp_mul(&a2, &b2, &b1)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = (S2 - S3)/3; */ + /** S2 = S2 - a1; */ + if ((err = mp_sub(&S2, &a1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 / 3; \\ this is an exact division */ + if ((err = s_mp_div_3(&S2, &S2, NULL)) != MP_OKAY) goto LBL_ERR; + + /** a1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 >> 1; */ + if ((err = mp_div_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** a0 = a0 * b0; */ + if ((err = mp_mul(&a0, &b0, &a0)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a0; */ + if ((err = mp_sub(&S1, &a0, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - S1; */ + if ((err = mp_sub(&S2, &S1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 >> 1; */ + if ((err = mp_div_2(&S2, &S2)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - a1; */ + if ((err = mp_sub(&S1, &a1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** S1 = S1 - b1; */ + if ((err = mp_sub(&S1, &b1, &S1)) != MP_OKAY) goto LBL_ERR; + + /** T1 = b1 << 1; */ + if ((err = mp_mul_2(&b1, &T1)) != MP_OKAY) goto LBL_ERR; + + /** S2 = S2 - T1; */ + if ((err = mp_sub(&S2, &T1, &S2)) != MP_OKAY) goto LBL_ERR; + + /** a1 = a1 - S2; */ + if ((err = mp_sub(&a1, &S2, &a1)) != MP_OKAY) goto LBL_ERR; + + + /** P = b1*x^4+ S2*x^3+ S1*x^2+ a1*x + a0; */ + if ((err = mp_lshd(&b1, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S2, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S2, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&S1, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &S1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a1, &b1)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&b1, &a0, c)) != MP_OKAY) goto LBL_ERR; + + /** a * b - P */ + + +LBL_ERR: + mp_clear(&b2); +LBL_ERRb2: + mp_clear(&b1); +LBL_ERRb1: + mp_clear(&b0); +LBL_ERRb0: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear_multi(&S1, &S2, &T1, NULL); + return err; +} + +#endif diff --git a/deps/libtommath/s_mp_prime_is_divisible.c b/deps/libtommath/s_mp_prime_is_divisible.c new file mode 100644 index 0000000..63b2405 --- /dev/null +++ b/deps/libtommath/s_mp_prime_is_divisible.c @@ -0,0 +1,33 @@ +#include "tommath_private.h" +#ifdef S_MP_PRIME_IS_DIVISIBLE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* determines if an integers is divisible by one + * of the first PRIME_SIZE primes or not + * + * sets result to 0 if not, 1 if yes + */ +mp_err s_mp_prime_is_divisible(const mp_int *a, bool *result) +{ + int i; + for (i = 0; i < MP_PRIME_TAB_SIZE; i++) { + /* what is a mod LBL_prime_tab[i] */ + mp_err err; + mp_digit res; + if ((err = mp_mod_d(a, s_mp_prime_tab[i], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0u) { + *result = true; + return MP_OKAY; + } + } + + /* default to not */ + *result = false; + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_prime_tab.c b/deps/libtommath/s_mp_prime_tab.c new file mode 100644 index 0000000..87c07fd --- /dev/null +++ b/deps/libtommath/s_mp_prime_tab.c @@ -0,0 +1,44 @@ +#include "tommath_private.h" +#ifdef S_MP_PRIME_TAB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +const mp_digit s_mp_prime_tab[] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +}; + +#endif diff --git a/deps/libtommath/s_mp_radix_map.c b/deps/libtommath/s_mp_radix_map.c new file mode 100644 index 0000000..68e21f3 --- /dev/null +++ b/deps/libtommath/s_mp_radix_map.c @@ -0,0 +1,19 @@ +#include "tommath_private.h" +#ifdef S_MP_RADIX_MAP_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* chars used in radix conversions */ +const char s_mp_radix_map[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +const uint8_t s_mp_radix_map_reverse[] = { + 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x01, 0x02, 0x03, 0x04, /* +,-./01234 */ + 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56789:;<=> */ + 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, /* ?@ABCDEFGH */ + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, /* IJKLMNOPQR */ + 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0xff, 0xff, /* STUVWXYZ[\ */ + 0xff, 0xff, 0xff, 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* ]^_`abcdef */ + 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, /* ghijklmnop */ + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d /* qrstuvwxyz */ +}; +MP_STATIC_ASSERT(correct_radix_map_reverse_size, sizeof(s_mp_radix_map_reverse) == MP_RADIX_MAP_REVERSE_SIZE) +#endif diff --git a/deps/libtommath/s_mp_radix_size_overestimate.c b/deps/libtommath/s_mp_radix_size_overestimate.c new file mode 100644 index 0000000..4f05997 --- /dev/null +++ b/deps/libtommath/s_mp_radix_size_overestimate.c @@ -0,0 +1,82 @@ +#include "tommath_private.h" +#ifdef S_MP_RADIX_SIZE_OVERESTIMATE_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + Overestimate the size needed for the bigint to string conversion by a very small amount. + The error is about 10^-8; it will overestimate the result by at most 11 elements for + a number of the size 2^(2^31)-1 which is currently the largest possible in this library. + Some short tests gave no results larger than 5 (plus 2 for sign and EOS). + */ + +/* + Table of {0, INT(log_2([1..64])*2^p)+1 } where p is the scale + factor defined in MP_RADIX_SIZE_SCALE and INT() extracts the integer part (truncating). + Good for 32 bit "int". Set MP_RADIX_SIZE_SCALE = 61 and recompute values + for 64 bit "int". + */ +/* *INDENT-OFF* */ +#define MP_RADIX_SIZE_SCALE 29 +static const uint32_t s_log_bases[65] = { + 0u, 0u, 0x20000001u, 0x14309399u, 0x10000001u, + 0xdc81a35u, 0xc611924u, 0xb660c9eu, 0xaaaaaabu, 0xa1849cdu, + 0x9a209a9u, 0x94004e1u, 0x8ed19c2u, 0x8a5ca7du, 0x867a000u, + 0x830cee3u, 0x8000001u, 0x7d42d60u, 0x7ac8b32u, 0x7887847u, + 0x7677349u, 0x749131fu, 0x72d0163u, 0x712f657u, 0x6fab5dbu, + 0x6e40d1bu, 0x6ced0d0u, 0x6badbdeu, 0x6a80e3bu, 0x6964c19u, + 0x6857d31u, 0x6758c38u, 0x6666667u, 0x657fb21u, 0x64a3b9fu, + 0x63d1ab4u, 0x6308c92u, 0x624869eu, 0x618ff47u, 0x60dedeau, + 0x6034ab0u, 0x5f90e7bu, 0x5ef32cbu, 0x5e5b1b2u, 0x5dc85c3u, + 0x5d3aa02u, 0x5cb19d9u, 0x5c2d10fu, 0x5bacbbfu, 0x5b3064fu, + 0x5ab7d68u, 0x5a42df0u, 0x59d1506u, 0x5962ffeu, 0x58f7c57u, + 0x588f7bcu, 0x582a000u, 0x57c7319u, 0x5766f1du, 0x5709243u, + 0x56adad9u, 0x565474du, 0x55fd61fu, 0x55a85e8u, 0x5555556u +}; +/* *INDENT-ON* */ + +mp_err s_mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size) +{ + int bit_count; + mp_int bi_bit_count, bi_k; + mp_err err = MP_OKAY; + + if ((radix < 2) || (radix > 64)) { + return MP_VAL; + } + + if (mp_iszero(a)) { + *size = 2U; + return MP_OKAY; + } + + if (MP_HAS(S_MP_LOG_2EXPT) && MP_IS_2EXPT((mp_digit)radix)) { + /* floor(log_{2^n}(a)) + 1 + EOS + sign */ + *size = (size_t)(s_mp_log_2expt(a, (mp_digit)radix) + 3); + return MP_OKAY; + } + + if ((err = mp_init_multi(&bi_bit_count, &bi_k, NULL)) != MP_OKAY) { + return err; + } + + /* la = floor(log_2(a)) + 1 */ + bit_count = mp_count_bits(a); + + mp_set_u32(&bi_bit_count, (uint32_t)bit_count); + /* k = floor(2^29/log_2(radix)) + 1 */ + mp_set_u32(&bi_k, s_log_bases[radix]); + /* n = floor((la * k) / 2^29) + 1 */ + if ((err = mp_mul(&bi_bit_count, &bi_k, &bi_bit_count)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_div_2d(&bi_bit_count, MP_RADIX_SIZE_SCALE, &bi_bit_count, NULL)) != MP_OKAY) goto LBL_ERR; + + /* The "+1" here is the "+1" in "floor((la * k) / 2^29) + 1" */ + /* n = n + 1 + EOS + sign */ + *size = (size_t)(mp_get_u64(&bi_bit_count) + 3U); + +LBL_ERR: + mp_clear_multi(&bi_bit_count, &bi_k, NULL); + return err; +} + +#endif diff --git a/deps/libtommath/s_mp_rand_platform.c b/deps/libtommath/s_mp_rand_platform.c new file mode 100644 index 0000000..0a6982a --- /dev/null +++ b/deps/libtommath/s_mp_rand_platform.c @@ -0,0 +1,149 @@ +#include "tommath_private.h" +#ifdef S_MP_RAND_PLATFORM_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* First the OS-specific special cases + * - *BSD + * - Windows + */ +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +#define S_READ_ARC4RANDOM_C +static mp_err s_read_arc4random(void *p, size_t n) +{ + arc4random_buf(p, n); + return MP_OKAY; +} +#endif + +#if defined(_WIN32) +#define S_READ_WINCSP_C + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#ifndef WINVER +#define WINVER 0x0501 +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static mp_err s_read_wincsp(void *p, size_t n) +{ + static HCRYPTPROV hProv = 0; + if (hProv == 0) { + HCRYPTPROV h = 0; + if (!CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && + !CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) { + return MP_ERR; + } + hProv = h; + } + return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR; +} +#endif /* WIN32 */ + +#if !defined(S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 25) +#define S_READ_GETRANDOM_C +#include +#include + +static mp_err s_read_getrandom(void *p, size_t n) +{ + char *q = (char *)p; + while (n > 0u) { + ssize_t ret = getrandom(q, n, 0); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + return MP_OKAY; +} +#endif +#endif + +/* We assume all platforms besides windows provide "/dev/urandom". + * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time. + */ +#if !defined(S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM) +#define S_READ_URANDOM_C +#ifndef MP_DEV_URANDOM +#define MP_DEV_URANDOM "/dev/urandom" +#endif +#include +#include +#include + +static mp_err s_read_urandom(void *p, size_t n) +{ + int fd; + char *q = (char *)p; + + do { + fd = open(MP_DEV_URANDOM, O_RDONLY); + } while ((fd == -1) && (errno == EINTR)); + if (fd == -1) return MP_ERR; + + while (n > 0u) { + ssize_t ret = read(fd, q, n); + if (ret < 0) { + if (errno == EINTR) { + continue; + } + close(fd); + return MP_ERR; + } + q += ret; + n -= (size_t)ret; + } + + close(fd); + return MP_OKAY; +} +#endif + +mp_err s_read_arc4random(void *p, size_t n); +mp_err s_read_wincsp(void *p, size_t n); +mp_err s_read_getrandom(void *p, size_t n); +mp_err s_read_urandom(void *p, size_t n); + +/* + * Note: libtommath relies on dead code elimination + * for the configuration system, i.e., the MP_HAS macro. + * + * If you observe linking errors in this functions, + * your compiler does not perform the dead code compilation + * such that the unused functions are still referenced. + * + * This happens for example for MSVC if the /Od compilation + * option is given. The option /Od instructs MSVC to + * not perform any "optimizations", not even removal of + * dead code wrapped in `if (0)` blocks. + * + * If you still insist on compiling with /Od, simply + * comment out the lines which result in linking errors. + * + * We intentionally don't fix this issue in order + * to have a single point of failure for misconfigured compilers. + */ +mp_err s_mp_rand_platform(void *p, size_t n) +{ + mp_err err = MP_ERR; + if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n); + return err; +} + +#endif diff --git a/deps/libtommath/s_mp_sqr.c b/deps/libtommath/s_mp_sqr.c new file mode 100644 index 0000000..da9aa69 --- /dev/null +++ b/deps/libtommath/s_mp_sqr.c @@ -0,0 +1,78 @@ +#include "tommath_private.h" +#ifdef S_MP_SQR_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +mp_err s_mp_sqr(const mp_int *a, mp_int *b) +{ + mp_int t; + int ix, pa; + mp_err err; + + pa = a->used; + if ((err = mp_init_size(&t, (2 * pa) + 1)) != MP_OKAY) { + return err; + } + + /* default used is maximum possible size */ + t.used = (2 * pa) + 1; + + for (ix = 0; ix < pa; ix++) { + mp_digit u; + int iy; + + /* first calculate the digit at 2*ix */ + /* calculate double precision result */ + mp_word r = (mp_word)t.dp[2*ix] + + ((mp_word)a->dp[ix] * (mp_word)a->dp[ix]); + + /* store lower part in result */ + t.dp[ix+ix] = (mp_digit)(r & (mp_word)MP_MASK); + + /* get the carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + + for (iy = ix + 1; iy < pa; iy++) { + /* first calculate the product */ + r = (mp_word)a->dp[ix] * (mp_word)a->dp[iy]; + + /* now calculate the double precision result, note we use + * addition instead of *2 since it's easier to optimize. + */ + /* Some architectures and/or compilers seem to prefer a bit-shift nowadays */ + r = (mp_word)t.dp[ix + iy] + (r<<1) + (mp_word)u; + + /* store lower part */ + t.dp[ix + iy] = (mp_digit)(r & (mp_word)MP_MASK); + + /* get carry */ + u = (mp_digit)(r >> (mp_word)MP_DIGIT_BIT); + } + /* propagate upwards */ + while (u != 0uL) { + mp_digit tmp; + /* + "u" can get bigger than MP_DIGIT_MAX and would need a bigger type + for the sum (mp_word). That is costly if mp_word is not a native + integer but a bigint from the compiler library. We do a manual + multiword addition instead. + */ + /* t.dp[ix + iy] has been masked off by MP_MASK and is hence of the correct size + and we can just add the lower part of "u". Carry is guaranteed to fit into + the type used for mp_digit, too, so we can extract it later. */ + tmp = t.dp[ix + iy] + (u & MP_MASK); + /* t.dp[ix + iy] is set to the result minus the carry, carry is still in "tmp" */ + t.dp[ix + iy] = tmp & MP_MASK; + /* Add high part of "u" and the carry from "tmp" to get the next "u" */ + u = (u >> MP_DIGIT_BIT) + (tmp >> MP_DIGIT_BIT); + ++iy; + } + } + + mp_clamp(&t); + mp_exch(&t, b); + mp_clear(&t); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_sqr_comba.c b/deps/libtommath/s_mp_sqr_comba.c new file mode 100644 index 0000000..1bcc1f9 --- /dev/null +++ b/deps/libtommath/s_mp_sqr_comba.c @@ -0,0 +1,87 @@ +#include "tommath_private.h" +#ifdef S_MP_SQR_COMBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* the jist of squaring... + * you do like mult except the offset of the tmpx [one that + * starts closer to zero] can't equal the offset of tmpy. + * So basically you set up iy like before then you min it with + * (ty-tx) so that it never happens. You double all those + * you add in the inner loop + +After that loop you do the squares and add them in. +*/ + +mp_err s_mp_sqr_comba(const mp_int *a, mp_int *b) +{ + int oldused, pa, ix; + mp_digit W[MP_WARRAY]; + mp_word W1; + mp_err err; + + /* grow the destination as required */ + pa = a->used + a->used; + if ((err = mp_grow(b, pa)) != MP_OKAY) { + return err; + } + + /* number of output digits to produce */ + W1 = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy, iz; + mp_word _W; + + /* clear counter */ + _W = 0; + + /* get offsets into the two bignums */ + ty = MP_MIN(a->used-1, ix); + tx = ix - ty; + + /* this is the number of times the loop will iterate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MP_MIN(a->used-tx, ty+1); + + /* now for squaring tx can never equal ty + * we halve the distance since they approach at a rate of 2x + * and we have to round because odd cases need to be executed + */ + iy = MP_MIN(iy, ((ty-tx)+1)>>1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += (mp_word)a->dp[tx + iz] * (mp_word)a->dp[ty - iz]; + } + + /* double the inner product and add carry */ + _W = _W + _W + W1; + + /* even columns have the square term in them */ + if (((unsigned)ix & 1u) == 0u) { + _W += (mp_word)a->dp[ix>>1] * (mp_word)a->dp[ix>>1]; + } + + /* store it */ + W[ix] = (mp_digit)_W & MP_MASK; + + /* make next carry */ + W1 = _W >> (mp_word)MP_DIGIT_BIT; + } + + /* setup dest */ + oldused = b->used; + b->used = a->used+a->used; + + for (ix = 0; ix < pa; ix++) { + b->dp[ix] = W[ix] & MP_MASK; + } + + /* clear unused digits [that existed in the old copy of c] */ + s_mp_zero_digs(b->dp + b->used, oldused - b->used); + + mp_clamp(b); + return MP_OKAY; +} +#endif diff --git a/deps/libtommath/s_mp_sqr_karatsuba.c b/deps/libtommath/s_mp_sqr_karatsuba.c new file mode 100644 index 0000000..f064b46 --- /dev/null +++ b/deps/libtommath/s_mp_sqr_karatsuba.c @@ -0,0 +1,92 @@ +#include "tommath_private.h" +#ifdef S_MP_SQR_KARATSUBA_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Karatsuba squaring, computes b = a*a using three + * half size squarings + * + * See comments of mul_karatsuba for details. It + * is essentially the same algorithm but merely + * tuned to perform recursive squarings. + */ +mp_err s_mp_sqr_karatsuba(const mp_int *a, mp_int *b) +{ + mp_int x0, x1, t1, t2, x0x0, x1x1; + int B; + mp_err err; + + /* min # of digits */ + B = a->used; + + /* now divide in two */ + B = B >> 1; + + /* init copy all the temps */ + if ((err = mp_init_size(&x0, B)) != MP_OKAY) + goto LBL_ERR; + if ((err = mp_init_size(&x1, a->used - B)) != MP_OKAY) + goto X0; + + /* init temps */ + if ((err = mp_init_size(&t1, a->used * 2)) != MP_OKAY) + goto X1; + if ((err = mp_init_size(&t2, a->used * 2)) != MP_OKAY) + goto T1; + if ((err = mp_init_size(&x0x0, B * 2)) != MP_OKAY) + goto T2; + if ((err = mp_init_size(&x1x1, (a->used - B) * 2)) != MP_OKAY) + goto X0X0; + + /* now shift the digits */ + x0.used = B; + x1.used = a->used - B; + s_mp_copy_digs(x0.dp, a->dp, x0.used); + s_mp_copy_digs(x1.dp, a->dp + B, x1.used); + mp_clamp(&x0); + + /* now calc the products x0*x0 and x1*x1 */ + if ((err = mp_sqr(&x0, &x0x0)) != MP_OKAY) + goto X1X1; /* x0x0 = x0*x0 */ + if ((err = mp_sqr(&x1, &x1x1)) != MP_OKAY) + goto X1X1; /* x1x1 = x1*x1 */ + + /* now calc (x1+x0)**2 */ + if ((err = s_mp_add(&x1, &x0, &t1)) != MP_OKAY) + goto X1X1; /* t1 = x1 - x0 */ + if ((err = mp_sqr(&t1, &t1)) != MP_OKAY) + goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ + + /* add x0y0 */ + if ((err = s_mp_add(&x0x0, &x1x1, &t2)) != MP_OKAY) + goto X1X1; /* t2 = x0x0 + x1x1 */ + if ((err = s_mp_sub(&t1, &t2, &t1)) != MP_OKAY) + goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */ + + /* shift by B */ + if ((err = mp_lshd(&t1, B)) != MP_OKAY) + goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<used / 3; + + /** a = a2 * x^2 + a1 * x + a0; */ + if ((err = mp_init_size(&a0, B)) != MP_OKAY) goto LBL_ERRa0; + if ((err = mp_init_size(&a1, B)) != MP_OKAY) goto LBL_ERRa1; + if ((err = mp_init_size(&a2, a->used - (2 * B))) != MP_OKAY) goto LBL_ERRa2; + + a0.used = a1.used = B; + a2.used = a->used - 2 * B; + s_mp_copy_digs(a0.dp, a->dp, a0.used); + s_mp_copy_digs(a1.dp, a->dp + B, a1.used); + s_mp_copy_digs(a2.dp, a->dp + 2 * B, a2.used); + mp_clamp(&a0); + mp_clamp(&a1); + mp_clamp(&a2); + + /** S0 = a0^2; */ + if ((err = mp_sqr(&a0, &S0)) != MP_OKAY) goto LBL_ERR; + + /** \\S1 = (a2 + a1 + a0)^2 */ + /** \\S2 = (a2 - a1 + a0)^2 */ + /** \\S1 = a0 + a2; */ + /** a0 = a0 + a2; */ + if ((err = mp_add(&a0, &a2, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S1 - a1; */ + /** b = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, b)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 + a1; */ + /** a0 = a0 + a1; */ + if ((err = mp_add(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1^2; */ + /** a0 = a0^2; */ + if ((err = mp_sqr(&a0, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2^2; */ + /** b = b^2; */ + if ((err = mp_sqr(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S3 = 2 * a1 * a2 */ + /** \\S3 = a1 * a2; */ + /** a1 = a1 * a2; */ + if ((err = mp_mul(&a1, &a2, &a1)) != MP_OKAY) goto LBL_ERR; + /** \\S3 = S3 << 1; */ + /** a1 = a1 << 1; */ + if ((err = mp_mul_2(&a1, &a1)) != MP_OKAY) goto LBL_ERR; + + /** \\S4 = a2^2; */ + /** a2 = a2^2; */ + if ((err = mp_sqr(&a2, &a2)) != MP_OKAY) goto LBL_ERR; + + /** \\ tmp = (S1 + S2)/2 */ + /** \\tmp = S1 + S2; */ + /** b = a0 + b; */ + if ((err = mp_add(&a0, b, b)) != MP_OKAY) goto LBL_ERR; + /** \\tmp = tmp >> 1; */ + /** b = b >> 1; */ + if ((err = mp_div_2(b, b)) != MP_OKAY) goto LBL_ERR; + + /** \\ S1 = S1 - tmp - S3 */ + /** \\S1 = S1 - tmp; */ + /** a0 = a0 - b; */ + if ((err = mp_sub(&a0, b, &a0)) != MP_OKAY) goto LBL_ERR; + /** \\S1 = S1 - S3; */ + /** a0 = a0 - a1; */ + if ((err = mp_sub(&a0, &a1, &a0)) != MP_OKAY) goto LBL_ERR; + + /** \\S2 = tmp - S4 -S0 */ + /** \\S2 = tmp - S4; */ + /** b = b - a2; */ + if ((err = mp_sub(b, &a2, b)) != MP_OKAY) goto LBL_ERR; + /** \\S2 = S2 - S0; */ + /** b = b - S0; */ + if ((err = mp_sub(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + + + /** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */ + /** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */ + + if ((err = mp_lshd(&a2, 4 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a1, 3 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(b, 2 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_lshd(&a0, 1 * B)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, &a1, &a2)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(&a2, b, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &a0, b)) != MP_OKAY) goto LBL_ERR; + if ((err = mp_add(b, &S0, b)) != MP_OKAY) goto LBL_ERR; + /** a^2 - P */ + + +LBL_ERR: + mp_clear(&a2); +LBL_ERRa2: + mp_clear(&a1); +LBL_ERRa1: + mp_clear(&a0); +LBL_ERRa0: + mp_clear(&S0); + + return err; +} + +#endif diff --git a/deps/libtommath/s_mp_sub.c b/deps/libtommath/s_mp_sub.c new file mode 100644 index 0000000..b1a749e --- /dev/null +++ b/deps/libtommath/s_mp_sub.c @@ -0,0 +1,56 @@ +#include "tommath_private.h" +#ifdef S_MP_SUB_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) +{ + int oldused = c->used, min = b->used, max = a->used, i; + mp_digit u; + mp_err err; + + /* init result */ + if ((err = mp_grow(c, max)) != MP_OKAY) { + return err; + } + + c->used = max; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + c->dp[i] = (a->dp[i] - b->dp[i]) - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u); + + /* Clear carry from T[i] */ + c->dp[i] &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + c->dp[i] = a->dp[i] - u; + + /* U = carry bit of T[i] */ + u = c->dp[i] >> (MP_SIZEOF_BITS(mp_digit) - 1u); + + /* Clear carry from T[i] */ + c->dp[i] &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + s_mp_zero_digs(c->dp + c->used, oldused - c->used); + + mp_clamp(c); + return MP_OKAY; +} + +#endif diff --git a/deps/libtommath/s_mp_zero_buf.c b/deps/libtommath/s_mp_zero_buf.c new file mode 100644 index 0000000..23a458d --- /dev/null +++ b/deps/libtommath/s_mp_zero_buf.c @@ -0,0 +1,22 @@ +#include "tommath_private.h" +#ifdef S_MP_ZERO_BUF_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_USE_MEMOPS +# include +#endif + +void s_mp_zero_buf(void *mem, size_t size) +{ +#ifdef MP_USE_MEMOPS + memset(mem, 0, size); +#else + char *m = (char *)mem; + while (size-- > 0u) { + *m++ = '\0'; + } +#endif +} + +#endif diff --git a/deps/libtommath/s_mp_zero_digs.c b/deps/libtommath/s_mp_zero_digs.c new file mode 100644 index 0000000..79e8377 --- /dev/null +++ b/deps/libtommath/s_mp_zero_digs.c @@ -0,0 +1,23 @@ +#include "tommath_private.h" +#ifdef S_MP_ZERO_DIGS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef MP_USE_MEMOPS +# include +#endif + +void s_mp_zero_digs(mp_digit *d, int digits) +{ +#ifdef MP_USE_MEMOPS + if (digits > 0) { + memset(d, 0, (size_t)digits * sizeof(mp_digit)); + } +#else + while (digits-- > 0) { + *d++ = 0; + } +#endif +} + +#endif diff --git a/deps/libtommath/sources.cmake b/deps/libtommath/sources.cmake new file mode 100644 index 0000000..bbb2aea --- /dev/null +++ b/deps/libtommath/sources.cmake @@ -0,0 +1,170 @@ +# SPDX-License-Identifier: Unlicense +# Autogenerated File! Do not edit. + +set(SOURCES +mp_2expt.c +mp_abs.c +mp_add.c +mp_add_d.c +mp_addmod.c +mp_and.c +mp_clamp.c +mp_clear.c +mp_clear_multi.c +mp_cmp.c +mp_cmp_d.c +mp_cmp_mag.c +mp_cnt_lsb.c +mp_complement.c +mp_copy.c +mp_count_bits.c +mp_cutoffs.c +mp_div.c +mp_div_2.c +mp_div_2d.c +mp_div_d.c +mp_dr_is_modulus.c +mp_dr_reduce.c +mp_dr_setup.c +mp_error_to_string.c +mp_exch.c +mp_expt_n.c +mp_exptmod.c +mp_exteuclid.c +mp_fread.c +mp_from_sbin.c +mp_from_ubin.c +mp_fwrite.c +mp_gcd.c +mp_get_double.c +mp_get_i32.c +mp_get_i64.c +mp_get_l.c +mp_get_mag_u32.c +mp_get_mag_u64.c +mp_get_mag_ul.c +mp_grow.c +mp_hash.c +mp_init.c +mp_init_copy.c +mp_init_i32.c +mp_init_i64.c +mp_init_l.c +mp_init_multi.c +mp_init_set.c +mp_init_size.c +mp_init_u32.c +mp_init_u64.c +mp_init_ul.c +mp_invmod.c +mp_is_square.c +mp_kronecker.c +mp_lcm.c +mp_log.c +mp_log_n.c +mp_lshd.c +mp_mod.c +mp_mod_2d.c +mp_montgomery_calc_normalization.c +mp_montgomery_reduce.c +mp_montgomery_setup.c +mp_mul.c +mp_mul_2.c +mp_mul_2d.c +mp_mul_d.c +mp_mulmod.c +mp_neg.c +mp_or.c +mp_pack.c +mp_pack_count.c +mp_prime_fermat.c +mp_prime_frobenius_underwood.c +mp_prime_is_prime.c +mp_prime_miller_rabin.c +mp_prime_next_prime.c +mp_prime_rabin_miller_trials.c +mp_prime_rand.c +mp_prime_strong_lucas_selfridge.c +mp_radix_size.c +mp_radix_size_overestimate.c +mp_rand.c +mp_rand_source.c +mp_read_radix.c +mp_reduce.c +mp_reduce_2k.c +mp_reduce_2k_l.c +mp_reduce_2k_setup.c +mp_reduce_2k_setup_l.c +mp_reduce_is_2k.c +mp_reduce_is_2k_l.c +mp_reduce_setup.c +mp_root_n.c +mp_rshd.c +mp_sbin_size.c +mp_set.c +mp_set_double.c +mp_set_i32.c +mp_set_i64.c +mp_set_l.c +mp_set_u32.c +mp_set_u64.c +mp_set_ul.c +mp_shrink.c +mp_signed_rsh.c +mp_sqrmod.c +mp_sqrt.c +mp_sqrtmod_prime.c +mp_sub.c +mp_sub_d.c +mp_submod.c +mp_to_radix.c +mp_to_sbin.c +mp_to_ubin.c +mp_ubin_size.c +mp_unpack.c +mp_xor.c +mp_zero.c +s_mp_add.c +s_mp_copy_digs.c +s_mp_div_3.c +s_mp_div_recursive.c +s_mp_div_school.c +s_mp_div_small.c +s_mp_exptmod.c +s_mp_exptmod_fast.c +s_mp_fp_log.c +s_mp_fp_log_d.c +s_mp_get_bit.c +s_mp_invmod.c +s_mp_invmod_odd.c +s_mp_log_2expt.c +s_mp_montgomery_reduce_comba.c +s_mp_mul.c +s_mp_mul_balance.c +s_mp_mul_comba.c +s_mp_mul_high.c +s_mp_mul_high_comba.c +s_mp_mul_karatsuba.c +s_mp_mul_toom.c +s_mp_prime_is_divisible.c +s_mp_prime_tab.c +s_mp_radix_map.c +s_mp_radix_size_overestimate.c +s_mp_rand_platform.c +s_mp_sqr.c +s_mp_sqr_comba.c +s_mp_sqr_karatsuba.c +s_mp_sqr_toom.c +s_mp_sub.c +s_mp_zero_buf.c +s_mp_zero_digs.c +) + +set(HEADERS +tommath.h +tommath_c89.h +tommath_class.h +tommath_cutoffs.h +tommath_private.h +tommath_superclass.h +) diff --git a/deps/libtommath/testme.sh b/deps/libtommath/testme.sh new file mode 100644 index 0000000..089e42a --- /dev/null +++ b/deps/libtommath/testme.sh @@ -0,0 +1,445 @@ +#!/bin/bash +# +# return values of this script are: +# 0 success +# 128 a test failed +# >0 the number of timed-out tests +# 255 parsing of parameters failed + +set -e + +if [ -f /proc/cpuinfo ] +then + MAKE_JOBS=$(( ($(cat /proc/cpuinfo | grep -E '^processor[[:space:]]*:' | tail -n -1 | cut -d':' -f2) + 1) * 2 + 1 )) +else + MAKE_JOBS=8 +fi + +ret=0 +TEST_CFLAGS="" + +_help() +{ + cat << EOF +Usage options for $(basename $0) [--with-cc=arg [other options]] + +Executing this script without any parameter will only run the default +configuration that has automatically been determined for the +architecture you're running. + + --with-cc=* The compiler(s) to use for the tests + This is an option that will be iterated. + + --test-vs-mtest=* Run test vs. mtest for '*' operations. + Only the first of each options will be + taken into account. + +To be able to specify options a compiler has to be given with +the option --with-cc=compilername +All other options will be tested with all MP_xBIT configurations. + + --with-{m64,m32,mx32} The architecture(s) to build and test + for, e.g. --with-mx32. + This is an option that will be iterated, + multiple selections are possible. + The mx32 architecture is not supported + by clang and will not be executed. + + --cflags=* Give an option to the compiler, + e.g. --cflags=-g + This is an option that will always be + passed as parameter to CC. + + --make-option=* Give an option to make, + e.g. --make-option="-f makefile.shared" + This is an option that will always be + passed as parameter to make. + + --with-low-mp Also build&run tests with -DMP_{8,16,32}BIT. + + --mtest-real-rand Use real random data when running mtest. + + --with-valgrind + --with-valgrind=* Run in valgrind (slow!). + + --limit-valgrind Run with valgrind on CI only on specific branches. + + --valgrind-options Additional Valgrind options + Some of the options like e.g.: + --track-origins=yes add a lot of extra + runtime and may trigger the 30 minutes + timeout. + +Godmode: + + --all Choose all architectures and gcc and clang + as compilers but does not run valgrind. + + --format Runs the various source-code formatters + and generators and checks if the sources + are clean. + + -h + --help This message + + -v + --version Prints the version. It is just the number + of git commits to this file, no deeper + meaning attached +EOF + exit 0 +} + +_die() +{ + echo "error $2 while $1" + if [ "$2" != "124" ] + then + exit 128 + else + echo "assuming timeout while running test - continue" + local _tail="" + which tail >/dev/null && _tail="tail -n 1 test_${suffix}.log" && \ + echo "last line of test_"${suffix}".log was:" && $_tail && echo "" + ret=$(( $ret + 1 )) + fi +} + +_fixup_cflags() { + compiler_version=$(echo "$1="$($1 -dumpversion)) + case "$compiler_version" in + clang*=4.2.1) + # one of my versions of clang complains about some stuff in stdio.h and stdarg.h ... + TEST_CFLAGS="-Wno-typedef-redefinition" + ;; + gcc*=9) + # gcc 9 seems to sometimes think that variables are uninitialized, but they are. + TEST_CFLAGS="-Wno-maybe-uninitialized" + ;; + *) + TEST_CFLAGS="" + ;; + esac + echo $compiler_version +} + +_make() +{ + echo -ne " Compile $1 $2" + suffix=$(echo ${1}${2} | tr ' ' '_') + _fixup_cflags "$1" + CC="$1" CFLAGS="$2 $TEST_CFLAGS" make -j$MAKE_JOBS $3 $MAKE_OPTIONS 2>gcc_errors_${suffix}.log + errcnt=$(wc -l < gcc_errors_${suffix}.log) + if [[ ${errcnt} -gt 1 ]]; then + echo " failed" + cat gcc_errors_${suffix}.log + exit 128 + fi +} + + +_runtest() +{ + make clean > /dev/null + local _timeout="" + which timeout >/dev/null && _timeout="timeout --foreground 90" + if [[ "$MAKE_OPTIONS" =~ "tune" ]] + then + # "make tune" will run "tune_it.sh" automatically, hence "autotune", but it cannot + # get switched off without some effort, so we just let it run twice for testing purposes + echo -e "\rRun autotune $1 $2" + _make "$1" "$2" "" + $_timeout $TUNE_CMD > test_${suffix}.log || _die "running autotune" $? + else + _make "$1" "$2" "test" + echo -e "\rRun test $1 $2" + $_timeout ./test > test_${suffix}.log || _die "running tests" $? + fi +} + +# This is not much more of a C&P of _runtest with a different timeout +# and the additional valgrind call. +# TODO: merge +_runvalgrind() +{ + make clean > /dev/null + local _timeout="" + # 30 minutes? Yes. Had it at 20 minutes and the Valgrind run needed over 25 minutes. + # A bit too close for comfort. + which timeout >/dev/null && _timeout="timeout --foreground 1800" +echo "MAKE_OPTIONS = \"$MAKE_OPTIONS\"" + if [[ "$MAKE_OPTIONS" =~ "tune" ]] + then +echo "autotune branch" + _make "$1" "$2" "" + # The shell used for /bin/sh is DASH 0.5.7-4ubuntu1 on the author's machine which fails valgrind, so + # we just run on instance of etc/tune with the same options as in etc/tune_it.sh + echo -e "\rRun etc/tune $1 $2 once inside valgrind" + $_timeout $VALGRIND_BIN $VALGRIND_OPTS $TUNE_CMD > test_${suffix}.log || _die "running etc/tune" $? + else + _make "$1" "$2" "test" + echo -e "\rRun test $1 $2 inside valgrind" + $_timeout $VALGRIND_BIN $VALGRIND_OPTS ./test > test_${suffix}.log || _die "running tests" $? + fi +} + + +_banner() +{ + echo "uname="$(uname -a) + [[ "$#" != "0" ]] && (echo $1=$($1 -dumpversion)) || true +} + +_exit() +{ + if [ "$ret" == "0" ] + then + echo "Tests successful" + else + echo "$ret tests timed out" + fi + + exit $ret +} + +ARCHFLAGS="" +COMPILERS="" +CFLAGS="" +WITH_LOW_MP="" +TEST_VS_MTEST="" +MTEST_RAND="" +# timed with an AMD A8-6600K +# 25 minutes +#VALGRIND_OPTS=" --track-origins=yes --leak-check=full --show-leak-kinds=all --error-exitcode=1 " +# 9 minutes (14 minutes with --test-vs-mtest=333333 --mtest-real-rand) +VALGRIND_OPTS=" --leak-check=full --show-leak-kinds=all --error-exitcode=1 " +#VALGRIND_OPTS="" +VALGRIND_BIN="" +CHECK_FORMAT="" +CHECK_SYMBOLS="" +C89="" +C89_C99_ROUNDTRIP="" +TUNE_CMD="./etc/tune -t -r 10 -L 3" + +alive_pid=0 + +function kill_alive() { + disown $alive_pid || true + kill $alive_pid 2>/dev/null +} + +function start_alive_printing() { + [ "$alive_pid" == "0" ] || return 0; + for i in `seq 1 10` ; do sleep 300 && echo "Tests still in Progress..."; done & + alive_pid=$! + trap kill_alive EXIT +} + +while [ $# -gt 0 ]; +do + case $1 in + "--with-m64" | "--with-m32" | "--with-mx32") + ARCHFLAGS="$ARCHFLAGS ${1:6}" + ;; + --c89) + C89="1" + ;; + --c89-c99-roundtrip) + C89_C99_ROUNDTRIP="1" + ;; + --with-cc=*) + COMPILERS="$COMPILERS ${1#*=}" + ;; + --cflags=*) + CFLAGS="$CFLAGS ${1#*=}" + ;; + --valgrind-options=*) + VALGRIND_OPTS="$VALGRIND_OPTS ${1#*=}" + ;; + --with-valgrind*) + if [[ ${1#*d} != "" ]] + then + VALGRIND_BIN="${1#*=}" + else + VALGRIND_BIN="valgrind" + fi + start_alive_printing + ;; + --limit-valgrind*) + if [[ ("$GITHUB_BASE_REF" == "develop" && "$PR_NUMBER" == "") || "$GITHUB_REF_NAME" == *"valgrind"* || "$COMMIT_MESSAGE" == *"valgrind"* ]] + then + if [[ ${1#*d} != "" ]] + then + VALGRIND_BIN="${1#*=}" + else + VALGRIND_BIN="valgrind" + fi + start_alive_printing + fi + ;; + --make-option=*) + MAKE_OPTIONS="$MAKE_OPTIONS ${1#*=}" + ;; + --with-low-mp) + WITH_LOW_MP="1" + ;; + --test-vs-mtest=*) + TEST_VS_MTEST="${1#*=}" + if ! [ "$TEST_VS_MTEST" -eq "$TEST_VS_MTEST" ] 2> /dev/null + then + echo "--test-vs-mtest Parameter has to be int" + exit 255 + fi + start_alive_printing + ;; + --mtest-real-rand) + MTEST_RAND="-DLTM_MTEST_REAL_RAND" + ;; + --format) + CHECK_FORMAT="1" + ;; + --symbols) + CHECK_SYMBOLS="1" + ;; + --all) + COMPILERS="gcc clang" + ARCHFLAGS="-m64 -m32 -mx32" + ;; + --help | -h) + _help + ;; + --version | -v) + echo $(git rev-list HEAD --count -- testme.sh) || echo "Unknown. Please run in original libtommath git repository." + exit 0 + ;; + *) + echo "Ignoring option ${1}" + ;; + esac + shift +done + +function _check_git() { + git update-index --refresh >/dev/null || true + git diff-index --quiet HEAD -- . || ( echo "FAILURE: $*" && exit 1 ) +} + +[[ "$C89" == "1" ]] && make c89 + +if [[ "$C89_C99_ROUNDTRIP" == "1" ]] +then + make c89 + make c99 + _check_git "make c89; make c99" + exit $? +fi + +if [[ "$CHECK_SYMBOLS" == "1" ]] +then + make -f makefile.shared + cat << EOF + + +The following list shows the discrepancy between +the shared library and the Windows dynamic library. +To fix this error, one of the following things +has to be done: +* the script which generates tommath.def has to be modified + (function generate_def() in helper.pl). +* The exported symbols are really different for some reason + This has to be manually investigated. + +EOF + exit $(comm -3 <(nm -D --defined-only .libs/libtommath.so | cut -d' ' -f3 | grep -v '^_' | sort) <(tail -n+9 tommath.def | tr -d ' ' | sort) | tee /dev/tty | wc -l) +fi + +if [[ "$CHECK_FORMAT" == "1" ]] +then + make astyle + _check_git "make astyle" + perl helper.pl --update-files + _check_git "helper.pl --update-files" + perl helper.pl --check-all + _check_git "helper.pl --check-all" + exit $? +fi + +[[ "$VALGRIND_BIN" == "" ]] && VALGRIND_OPTS="" + +# default to CC environment variable if no compiler is defined but some other options +if [[ "$COMPILERS" == "" ]] && [[ "$ARCHFLAGS$MAKE_OPTIONS$CFLAGS" != "" ]] +then + COMPILERS="${CC:-cc}" +# default to CC environment variable and run only default config if no option is given +elif [[ "$COMPILERS" == "" ]] +then + _banner "$CC" + if [[ "$VALGRIND_BIN" != "" ]] + then + _runvalgrind "$CC" "" + else + _runtest "$CC" "" + fi + _exit +fi + + +archflags=( $ARCHFLAGS ) +compilers=( $COMPILERS ) + +# choosing a compiler without specifying an architecture will use the default architecture +if [ "${#archflags[@]}" == "0" ] +then + archflags[0]=" " +fi + +_banner + +if [[ "$TEST_VS_MTEST" != "" ]] +then + make clean > /dev/null + _make "${compilers[0]}" "${archflags[0]} $CFLAGS" "mtest_opponent" + echo + _make "gcc" "$MTEST_RAND" "mtest" + echo + echo "Run test vs. mtest for $TEST_VS_MTEST iterations" + _timeout="" + which timeout >/dev/null && _timeout="timeout --foreground 1800" + $_timeout ./mtest/mtest $TEST_VS_MTEST | $VALGRIND_BIN $VALGRIND_OPTS ./mtest_opponent > valgrind_test.log 2> test_vs_mtest_err.log + retval=$? + head -n 5 valgrind_test.log + tail -n 2 valgrind_test.log + exit $retval +fi + +for i in "${compilers[@]}" +do + if [ -z "$(which $i)" ] + then + echo "Skipped compiler $i, file not found" + continue + fi + + for a in "${archflags[@]}" + do + if [[ $(expr "$i" : "clang") -ne 0 && "$a" == "-mx32" ]] + then + echo "clang -mx32 tests skipped" + continue + fi + if [[ "$VALGRIND_BIN" != "" ]] + then + _runvalgrind "$i" "$a $CFLAGS" + [ "$WITH_LOW_MP" != "1" ] && continue + _runvalgrind "$i" "$a -DMP_16BIT $CFLAGS" + _runvalgrind "$i" "$a -DMP_32BIT $CFLAGS" + else + _runtest "$i" "$a $CFLAGS" + [ "$WITH_LOW_MP" != "1" ] && continue + _runtest "$i" "$a -DMP_16BIT $CFLAGS" + _runtest "$i" "$a -DMP_32BIT $CFLAGS" + fi + done +done + +_exit diff --git a/deps/libtommath/tommath.def b/deps/libtommath/tommath.def new file mode 100644 index 0000000..86f3487 --- /dev/null +++ b/deps/libtommath/tommath.def @@ -0,0 +1,133 @@ +; libtommath +; +; Use this command to produce a 32-bit .lib file, for use in any MSVC version +; lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; Use this command to produce a 64-bit .lib file, for use in any MSVC version +; lib -machine:X64 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; +EXPORTS + mp_2expt + mp_abs + mp_add + mp_add_d + mp_addmod + mp_and + mp_clamp + mp_clear + mp_clear_multi + mp_cmp + mp_cmp_d + mp_cmp_mag + mp_cnt_lsb + mp_complement + mp_copy + mp_count_bits + mp_div + mp_div_2 + mp_div_2d + mp_div_d + mp_dr_is_modulus + mp_dr_reduce + mp_dr_setup + mp_error_to_string + mp_exch + mp_expt_n + mp_exptmod + mp_exteuclid + mp_fread + mp_from_sbin + mp_from_ubin + mp_fwrite + mp_gcd + mp_get_double + mp_get_i32 + mp_get_i64 + mp_get_l + mp_get_mag_u32 + mp_get_mag_u64 + mp_get_mag_ul + mp_grow + mp_hash + mp_init + mp_init_copy + mp_init_i32 + mp_init_i64 + mp_init_l + mp_init_multi + mp_init_set + mp_init_size + mp_init_u32 + mp_init_u64 + mp_init_ul + mp_invmod + mp_is_square + mp_kronecker + mp_lcm + mp_log + mp_log_n + mp_lshd + mp_mod + mp_mod_2d + mp_montgomery_calc_normalization + mp_montgomery_reduce + mp_montgomery_setup + mp_mul + mp_mul_2 + mp_mul_2d + mp_mul_d + mp_mulmod + mp_neg + mp_or + mp_pack + mp_pack_count + mp_prime_fermat + mp_prime_frobenius_underwood + mp_prime_is_prime + mp_prime_miller_rabin + mp_prime_next_prime + mp_prime_rabin_miller_trials + mp_prime_rand + mp_prime_strong_lucas_selfridge + mp_radix_size + mp_radix_size_overestimate + mp_rand + mp_rand_source + mp_read_radix + mp_reduce + mp_reduce_2k + mp_reduce_2k_l + mp_reduce_2k_setup + mp_reduce_2k_setup_l + mp_reduce_is_2k + mp_reduce_is_2k_l + mp_reduce_setup + mp_root_n + mp_rshd + mp_sbin_size + mp_set + mp_set_double + mp_set_i32 + mp_set_i64 + mp_set_l + mp_set_u32 + mp_set_u64 + mp_set_ul + mp_shrink + mp_signed_rsh + mp_sqrmod + mp_sqrt + mp_sqrtmod_prime + mp_sub + mp_sub_d + mp_submod + mp_to_radix + mp_to_sbin + mp_to_ubin + mp_ubin_size + mp_unpack + mp_xor + mp_zero + MP_MUL_KARATSUBA_CUTOFF + MP_SQR_KARATSUBA_CUTOFF + MP_MUL_TOOM_CUTOFF + MP_SQR_TOOM_CUTOFF diff --git a/deps/libtommath/tommath.h b/deps/libtommath/tommath.h new file mode 100644 index 0000000..33aa5df --- /dev/null +++ b/deps/libtommath/tommath.h @@ -0,0 +1,599 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMMATH_H_ +#define TOMMATH_H_ + +#include +#include +#include + +#ifndef MP_NO_FILE +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */ +#if (defined(_MSC_VER) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)) && !defined(MP_64BIT) +# define MP_32BIT +#endif + +/* detect 64-bit mode if possible */ +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ + defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ + defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ + defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ + defined(__LP64__) || defined(_LP64) || defined(__64BIT__) +# if !(defined(MP_64BIT) || defined(MP_32BIT) || defined(MP_16BIT)) +# if defined(__GNUC__) && defined(__SIZEOF_INT128__) && !defined(__hppa) +/* we support 128bit integers only via: __attribute__((mode(TI))) */ +# define MP_64BIT +# else +/* otherwise we fall back to MP_32BIT even on 64bit platforms */ +# define MP_32BIT +# endif +# endif +#endif + +#ifdef MP_DIGIT_BIT +# error Defining MP_DIGIT_BIT is disallowed, use MP_16/31/32/64BIT +#endif + +/* some default configurations. + * + * A "mp_digit" must be able to hold MP_DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*MP_DIGIT_BIT + 1 bits + * + * At the very least a mp_digit must be able to hold 7 bits + * [any size beyond that is ok provided it doesn't overflow the data type] + */ + +#if defined(MP_16BIT) +typedef uint16_t mp_digit; +# define MP_DIGIT_BIT 15 +#elif ((defined (MP_64BIT)) && !(defined(MP_31BIT)) ) +typedef uint64_t mp_digit; +# define MP_DIGIT_BIT 60 +#else +typedef uint32_t mp_digit; +# ifdef MP_31BIT +/* + * This is an extension that uses 31-bit digits. + * Please be aware that not all functions support this size, especially s_mp_mul_comba + * will be reduced to work on small numbers only: + * Up to 8 limbs, 248 bits instead of up to 512 limbs, 15872 bits with MP_28BIT. + */ +# define MP_DIGIT_BIT 31 +# else +/* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ +# define MP_DIGIT_BIT 28 +# define MP_28BIT +# endif +#endif + +#define MP_MASK ((((mp_digit)1)<<((mp_digit)MP_DIGIT_BIT))-((mp_digit)1)) +#define MP_DIGIT_MAX MP_MASK + +/* Primality generation flags */ +#define MP_PRIME_BBS 0x0001 /* BBS style prime */ +#define MP_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define MP_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +typedef enum { + MP_ZPOS = 0, /* positive */ + MP_NEG = 1 /* negative */ +} mp_sign; + +typedef enum { + MP_LT = -1, /* less than */ + MP_EQ = 0, /* equal */ + MP_GT = 1 /* greater than */ +} mp_ord; + +typedef enum { + MP_OKAY = 0, /* no error */ + MP_ERR = -1, /* unknown error */ + MP_MEM = -2, /* out of mem */ + MP_VAL = -3, /* invalid input */ + MP_ITER = -4, /* maximum iterations reached */ + MP_BUF = -5, /* buffer overflow, supplied buffer too small */ + MP_OVF = -6 /* mp_int overflow, too many digits */ +} mp_err; + +typedef enum { + MP_LSB_FIRST = -1, + MP_MSB_FIRST = 1 +} mp_order; + +typedef enum { + MP_LITTLE_ENDIAN = -1, + MP_NATIVE_ENDIAN = 0, + MP_BIG_ENDIAN = 1 +} mp_endian; + +/* tunable cutoffs */ +#ifndef MP_FIXED_CUTOFFS +extern int +MP_MUL_KARATSUBA_CUTOFF, +MP_SQR_KARATSUBA_CUTOFF, +MP_MUL_TOOM_CUTOFF, +MP_SQR_TOOM_CUTOFF; +#endif + +/* define this to use lower memory usage routines (exptmods mostly) */ +/* #define MP_LOW_MEM */ + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define MP_NULL_TERMINATED __attribute__((sentinel)) +#else +# define MP_NULL_TERMINATED +#endif + +/* + * MP_WUR - warn unused result + * --------------------------- + * + * The result of functions annotated with MP_WUR must be + * checked and cannot be ignored. + * + * Most functions in libtommath return an error code. + * This error code must be checked in order to prevent crashes or invalid + * results. + */ +#if defined(__GNUC__) && __GNUC__ >= 4 +# define MP_WUR __attribute__((warn_unused_result)) +#else +# define MP_WUR +#endif + +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) +# define MP_DEPRECATED(x) __attribute__((deprecated("replaced by " #x))) +#elif defined(_MSC_VER) && _MSC_VER >= 1500 +# define MP_DEPRECATED(x) __declspec(deprecated("replaced by " #x)) +#else +# define MP_DEPRECATED(x) +#endif + +#ifndef MP_NO_DEPRECATED_PRAGMA +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) +# define PRIVATE_MP_DEPRECATED_PRAGMA(s) _Pragma(#s) +# define MP_DEPRECATED_PRAGMA(s) PRIVATE_MP_DEPRECATED_PRAGMA(GCC warning s) +#elif defined(_MSC_VER) && _MSC_VER >= 1500 +# define MP_DEPRECATED_PRAGMA(s) __pragma(message(s)) +#endif +#endif + +#ifndef MP_DEPRECATED_PRAGMA +# define MP_DEPRECATED_PRAGMA(s) +#endif + +/* the infamous mp_int structure */ +typedef struct { + int used, alloc; + mp_sign sign; + mp_digit *dp; +} mp_int; + +/* error code to char* string */ +const char *mp_error_to_string(mp_err code) MP_WUR; + +/* ---> init and deinit bignum functions <--- */ +/* init a bignum */ +mp_err mp_init(mp_int *a) MP_WUR; + +/* free a bignum */ +void mp_clear(mp_int *a); + +/* init a null terminated series of arguments */ +mp_err mp_init_multi(mp_int *mp, ...) MP_NULL_TERMINATED MP_WUR; + +/* clear a null terminated series of arguments */ +void mp_clear_multi(mp_int *mp, ...) MP_NULL_TERMINATED; + +/* exchange two ints */ +void mp_exch(mp_int *a, mp_int *b); + +/* shrink ram required for a bignum */ +mp_err mp_shrink(mp_int *a) MP_WUR; + +/* grow an int to a given size */ +mp_err mp_grow(mp_int *a, int size) MP_WUR; + +/* init to a given number of digits */ +mp_err mp_init_size(mp_int *a, int size) MP_WUR; + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) ((a)->used == 0) +#define mp_isneg(a) ((a)->sign == MP_NEG) +#define mp_iseven(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u)) +#define mp_isodd(a) (!mp_iseven(a)) + +/* set to zero */ +void mp_zero(mp_int *a); + +/* get and set doubles */ +double mp_get_double(const mp_int *a) MP_WUR; +mp_err mp_set_double(mp_int *a, double b) MP_WUR; + +/* get integer, set integer and init with integer (int32_t) */ +int32_t mp_get_i32(const mp_int *a) MP_WUR; +void mp_set_i32(mp_int *a, int32_t b); +mp_err mp_init_i32(mp_int *a, int32_t b) MP_WUR; + +/* get integer, set integer and init with integer, behaves like two complement for negative numbers (uint32_t) */ +#define mp_get_u32(a) ((uint32_t)mp_get_i32(a)) +void mp_set_u32(mp_int *a, uint32_t b); +mp_err mp_init_u32(mp_int *a, uint32_t b) MP_WUR; + +/* get integer, set integer and init with integer (int64_t) */ +int64_t mp_get_i64(const mp_int *a) MP_WUR; +void mp_set_i64(mp_int *a, int64_t b); +mp_err mp_init_i64(mp_int *a, int64_t b) MP_WUR; + +/* get integer, set integer and init with integer, behaves like two complement for negative numbers (uint64_t) */ +#define mp_get_u64(a) ((uint64_t)mp_get_i64(a)) +void mp_set_u64(mp_int *a, uint64_t b); +mp_err mp_init_u64(mp_int *a, uint64_t b) MP_WUR; + +/* get magnitude */ +uint32_t mp_get_mag_u32(const mp_int *a) MP_WUR; +uint64_t mp_get_mag_u64(const mp_int *a) MP_WUR; +unsigned long mp_get_mag_ul(const mp_int *a) MP_WUR; + +/* get integer, set integer (long) */ +long mp_get_l(const mp_int *a) MP_WUR; +void mp_set_l(mp_int *a, long b); +mp_err mp_init_l(mp_int *a, long b) MP_WUR; + +/* get integer, set integer (unsigned long) */ +#define mp_get_ul(a) ((unsigned long)mp_get_l(a)) +void mp_set_ul(mp_int *a, unsigned long b); +mp_err mp_init_ul(mp_int *a, unsigned long b) MP_WUR; + +/* set to single unsigned digit, up to MP_DIGIT_MAX */ +void mp_set(mp_int *a, mp_digit b); +mp_err mp_init_set(mp_int *a, mp_digit b) MP_WUR; + +/* copy, b = a */ +mp_err mp_copy(const mp_int *a, mp_int *b) MP_WUR; + +/* inits and copies, a = b */ +mp_err mp_init_copy(mp_int *a, const mp_int *b) MP_WUR; + +/* trim unused digits */ +void mp_clamp(mp_int *a); + +/* unpack binary data */ +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, mp_endian endian, + size_t nails, const void *op) MP_WUR; + +/* pack binary data */ +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size) MP_WUR; +mp_err mp_pack(void *rop, size_t maxcount, size_t *written, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op) MP_WUR; + +/* ---> digit manipulation <--- */ + +/* right shift by "b" digits */ +void mp_rshd(mp_int *a, int b); + +/* left shift by "b" digits */ +mp_err mp_lshd(mp_int *a, int b) MP_WUR; + +/* c = a / 2**b, implemented as c = a >> b */ +mp_err mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d) MP_WUR; + +/* b = a/2 */ +mp_err mp_div_2(const mp_int *a, mp_int *b) MP_WUR; + +/* c = a * 2**b, implemented as c = a << b */ +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* b = a*2 */ +mp_err mp_mul_2(const mp_int *a, mp_int *b) MP_WUR; + +/* c = a mod 2**b */ +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* computes a = 2**b */ +mp_err mp_2expt(mp_int *a, int b) MP_WUR; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(const mp_int *a) MP_WUR; + +/* I Love Earth! */ + +/* makes a pseudo-random mp_int of a given size */ +mp_err mp_rand(mp_int *a, int digits) MP_WUR; +/* use custom random data source instead of source provided the platform */ +void mp_rand_source(mp_err(*source)(void *out, size_t size)); + +/* ---> binary operations <--- */ + +/* c = a XOR b (two complement) */ +mp_err mp_xor(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a OR b (two complement) */ +mp_err mp_or(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a AND b (two complement) */ +mp_err mp_and(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* b = ~a (bitwise not, two complement) */ +mp_err mp_complement(const mp_int *a, mp_int *b) MP_WUR; + +/* right shift with sign extension */ +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* ---> Basic arithmetic <--- */ + +/* b = -a */ +mp_err mp_neg(const mp_int *a, mp_int *b) MP_WUR; + +/* b = |a| */ +mp_err mp_abs(const mp_int *a, mp_int *b) MP_WUR; + +/* compare a to b */ +mp_ord mp_cmp(const mp_int *a, const mp_int *b) MP_WUR; + +/* compare |a| to |b| */ +mp_ord mp_cmp_mag(const mp_int *a, const mp_int *b) MP_WUR; + +/* c = a + b */ +mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a - b */ +mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = a * b */ +mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* b = a*a */ +#define mp_sqr(a, b) mp_mul((a), (a), (b)) + +/* a/b => cb + d == a */ +mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) MP_WUR; + +/* c = a mod b, 0 <= c < b */ +mp_err mp_mod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* Increment "a" by one like "a++". Changes input! */ +#define mp_incr(a) mp_add_d((a), 1u, (a)) + +/* Decrement "a" by one like "a--". Changes input! */ +#define mp_decr(a) mp_sub_d((a), 1u, (a)) + +/* ---> single digit functions <--- */ + +/* compare against a single digit */ +mp_ord mp_cmp_d(const mp_int *a, mp_digit b) MP_WUR; + +/* c = a + b */ +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; + +/* c = a - b */ +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; + +/* c = a * b */ +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c) MP_WUR; + +/* a/b => cb + d == a */ +mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) MP_WUR; + +/* c = a mod b, 0 <= c < b */ +#define mp_mod_d(a, b, c) mp_div_d((a), (b), NULL, (c)) + +/* ---> number theory <--- */ + +/* d = a + b (mod c) */ +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; + +/* d = a - b (mod c) */ +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; + +/* d = a * b (mod c) */ +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) MP_WUR; + +/* c = a * a (mod b) */ +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = 1/a (mod b) */ +mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* c = (a, b) */ +mp_err mp_gcd(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* produces value such that U1*a + U2*b = U3 */ +mp_err mp_exteuclid(const mp_int *a, const mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) MP_WUR; + +/* c = [a, b] or (a*b)/(a, b) */ +mp_err mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +/* Integer logarithm to integer base */ +mp_err mp_log_n(const mp_int *a, int base, int *c) MP_WUR; + +/* Integer logarithm to bigint base */ +mp_err mp_log(const mp_int *a, const mp_int *base, int *c) MP_WUR; + +/* c = a**b */ +mp_err mp_expt_n(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* finds one of the b'th root of a, such that |c|**b <= |a| + * + * returns error if a < 0 and b is even + */ +mp_err mp_root_n(const mp_int *a, int b, mp_int *c) MP_WUR; + +/* special sqrt algo */ +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) MP_WUR; + +/* special sqrt (mod prime) */ +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *prime, mp_int *ret) MP_WUR; + +/* is number a square? */ +mp_err mp_is_square(const mp_int *arg, bool *ret) MP_WUR; + +/* computes the Kronecker symbol c = (a | p) (like jacobi() but with {a,p} in Z */ +mp_err mp_kronecker(const mp_int *a, const mp_int *p, int *c) MP_WUR; + +/* used to setup the Barrett reduction for a given modulus b */ +mp_err mp_reduce_setup(mp_int *a, const mp_int *b) MP_WUR; + +/* Barrett Reduction, computes a (mod b) with a precomputed value c + * + * Assumes that 0 < x <= m*m, note if 0 > x > -(m*m) then you can merely + * compute the reduction as -1 * mp_reduce(mp_abs(x)) [pseudo code]. + */ +mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) MP_WUR; + +/* setups the montgomery reduction */ +mp_err mp_montgomery_setup(const mp_int *n, mp_digit *rho) MP_WUR; + +/* computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +mp_err mp_montgomery_calc_normalization(mp_int *a, const mp_int *b) MP_WUR; + +/* computes x/R == x (mod N) via Montgomery Reduction */ +mp_err mp_montgomery_reduce(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; + +/* returns 1 if a is a valid DR modulus */ +bool mp_dr_is_modulus(const mp_int *a) MP_WUR; + +/* sets the value of "d" required for mp_dr_reduce */ +void mp_dr_setup(const mp_int *a, mp_digit *d); + +/* reduces a modulo n using the Diminished Radix method */ +mp_err mp_dr_reduce(mp_int *x, const mp_int *n, mp_digit k) MP_WUR; + +/* returns true if a can be reduced with mp_reduce_2k */ +bool mp_reduce_is_2k(const mp_int *a) MP_WUR; + +/* determines k value for 2k reduction */ +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d) MP_WUR; + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d) MP_WUR; + +/* returns true if a can be reduced with mp_reduce_2k_l */ +bool mp_reduce_is_2k_l(const mp_int *a) MP_WUR; + +/* determines k value for 2k reduction */ +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d) MP_WUR; + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d) MP_WUR; + +/* Y = G**X (mod P) */ +mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) MP_WUR; + +#if defined(MP_16BIT) +typedef uint32_t mp_hval; +#else +typedef uint64_t mp_hval; +#endif + +/* computes hash */ +mp_err mp_hash(mp_int *a, mp_hval *hash) MP_WUR; + +/* ---> Primes <--- */ + +/* performs one Fermat test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_fermat(const mp_int *a, const mp_int *b, bool *result) MP_WUR; + +/* performs one Miller-Rabin test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_miller_rabin(const mp_int *a, const mp_int *b, bool *result) MP_WUR; + +/* This gives [for a given bit size] the number of trials required + * such that Miller-Rabin gives a prob of failure lower than 2^-96 + */ +int mp_prime_rabin_miller_trials(int size) MP_WUR; + +/* performs one strong Lucas-Selfridge test of "a". + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, bool *result) MP_WUR; + +/* performs one Frobenius test of "a" as described by Paul Underwood. + * Sets result to 0 if composite or 1 if probable prime + */ +mp_err mp_prime_frobenius_underwood(const mp_int *N, bool *result) MP_WUR; + +/* performs t random rounds of Miller-Rabin on "a" additional to + * bases 2 and 3. Also performs an initial sieve of trial + * division. Determines if "a" is prime with probability + * of error no more than (1/4)**t. + * Both a strong Lucas-Selfridge to complete the BPSW test + * and a separate Frobenius test are available at compile time. + * With t<0 a deterministic test is run for primes up to + * 318665857834031151167461. With t<13 (abs(t)-13) additional + * tests with sequential small primes are run starting at 43. + * Is Fips 186.4 compliant if called with t as computed by + * mp_prime_rabin_miller_trials(); + * + * Sets result to 1 if probably prime, 0 otherwise + */ +mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) MP_WUR; + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = true means the prime must be congruent to 3 mod 4 + */ +mp_err mp_prime_next_prime(mp_int *a, int t, bool bbs_style) MP_WUR; + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * MP_PRIME_BBS - make prime congruent to 3 mod 4 + * MP_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS) + * MP_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags) MP_WUR; + +/* ---> radix conversion <--- */ +int mp_count_bits(const mp_int *a) MP_WUR; + +size_t mp_ubin_size(const mp_int *a) MP_WUR; +mp_err mp_from_ubin(mp_int *a, const uint8_t *buf, size_t size) MP_WUR; +mp_err mp_to_ubin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) MP_WUR; + +size_t mp_sbin_size(const mp_int *a) MP_WUR; +mp_err mp_from_sbin(mp_int *a, const uint8_t *buf, size_t size) MP_WUR; +mp_err mp_to_sbin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) MP_WUR; + +mp_err mp_read_radix(mp_int *a, const char *str, int radix) MP_WUR; +mp_err mp_to_radix(const mp_int *a, char *str, size_t maxlen, size_t *written, int radix) MP_WUR; + +mp_err mp_radix_size(const mp_int *a, int radix, size_t *size) MP_WUR; +mp_err mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size) MP_WUR; + +#ifndef MP_NO_FILE +mp_err mp_fread(mp_int *a, int radix, FILE *stream) MP_WUR; +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream) MP_WUR; +#endif + +#define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), NULL, 2) +#define mp_to_octal(M, S, N) mp_to_radix((M), (S), (N), NULL, 8) +#define mp_to_decimal(M, S, N) mp_to_radix((M), (S), (N), NULL, 10) +#define mp_to_hex(M, S, N) mp_to_radix((M), (S), (N), NULL, 16) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/deps/libtommath/tommath_c89.h b/deps/libtommath/tommath_c89.h new file mode 100644 index 0000000..49400a1 --- /dev/null +++ b/deps/libtommath/tommath_c89.h @@ -0,0 +1,41 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * This header defines custom types which + * are used in c89 mode. + * + * By default, the source uses stdbool.h + * and stdint.h. The command `make c89` + * can be used to convert the source, + * such that this header is used instead. + * Use `make c99` to convert back. + * + * Please adapt the following definitions to your needs! + */ + +/* stdbool.h replacement types */ +typedef enum { MP_NO, MP_YES } mp_bool; + +/* stdint.h replacement types */ +typedef __INT8_TYPE__ mp_i8; +typedef __INT16_TYPE__ mp_i16; +typedef __INT32_TYPE__ mp_i32; +typedef __INT64_TYPE__ mp_i64; +typedef __UINT8_TYPE__ mp_u8; +typedef __UINT16_TYPE__ mp_u16; +typedef __UINT32_TYPE__ mp_u32; +typedef __UINT64_TYPE__ mp_u64; + +/* inttypes.h replacement, printf format specifier */ +# if __WORDSIZE == 64 +# define MP_PRI64_PREFIX "l" +# else +# define MP_PRI64_PREFIX "ll" +# endif +#define MP_PRIi64 MP_PRI64_PREFIX "i" +#define MP_PRIu64 MP_PRI64_PREFIX "u" +#define MP_PRIx64 MP_PRI64_PREFIX "x" +#define MP_PRIo64 MP_PRI64_PREFIX "o" + +#define MP_FUNCTION_NAME __func__ diff --git a/deps/libtommath/tommath_class.h b/deps/libtommath/tommath_class.h new file mode 100644 index 0000000..e08bc5f --- /dev/null +++ b/deps/libtommath/tommath_class.h @@ -0,0 +1,1298 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#define LTM_INSIDE +#if defined(LTM2) +# define LTM3 +#endif +#if defined(LTM1) +# define LTM2 +#endif +#define LTM1 +#if defined(LTM_ALL) +# define MP_2EXPT_C +# define MP_ABS_C +# define MP_ADD_C +# define MP_ADD_D_C +# define MP_ADDMOD_C +# define MP_AND_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CMP_MAG_C +# define MP_CNT_LSB_C +# define MP_COMPLEMENT_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_CUTOFFS_C +# define MP_DIV_C +# define MP_DIV_2_C +# define MP_DIV_2D_C +# define MP_DIV_D_C +# define MP_DR_IS_MODULUS_C +# define MP_DR_REDUCE_C +# define MP_DR_SETUP_C +# define MP_ERROR_TO_STRING_C +# define MP_EXCH_C +# define MP_EXPT_N_C +# define MP_EXPTMOD_C +# define MP_EXTEUCLID_C +# define MP_FREAD_C +# define MP_FROM_SBIN_C +# define MP_FROM_UBIN_C +# define MP_FWRITE_C +# define MP_GCD_C +# define MP_GET_DOUBLE_C +# define MP_GET_I32_C +# define MP_GET_I64_C +# define MP_GET_L_C +# define MP_GET_MAG_U32_C +# define MP_GET_MAG_U64_C +# define MP_GET_MAG_UL_C +# define MP_GROW_C +# define MP_HASH_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_INIT_I32_C +# define MP_INIT_I64_C +# define MP_INIT_L_C +# define MP_INIT_MULTI_C +# define MP_INIT_SET_C +# define MP_INIT_SIZE_C +# define MP_INIT_U32_C +# define MP_INIT_U64_C +# define MP_INIT_UL_C +# define MP_INVMOD_C +# define MP_IS_SQUARE_C +# define MP_KRONECKER_C +# define MP_LCM_C +# define MP_LOG_C +# define MP_LOG_N_C +# define MP_LSHD_C +# define MP_MOD_C +# define MP_MOD_2D_C +# define MP_MONTGOMERY_CALC_NORMALIZATION_C +# define MP_MONTGOMERY_REDUCE_C +# define MP_MONTGOMERY_SETUP_C +# define MP_MUL_C +# define MP_MUL_2_C +# define MP_MUL_2D_C +# define MP_MUL_D_C +# define MP_MULMOD_C +# define MP_NEG_C +# define MP_OR_C +# define MP_PACK_C +# define MP_PACK_COUNT_C +# define MP_PRIME_FERMAT_C +# define MP_PRIME_FROBENIUS_UNDERWOOD_C +# define MP_PRIME_IS_PRIME_C +# define MP_PRIME_MILLER_RABIN_C +# define MP_PRIME_NEXT_PRIME_C +# define MP_PRIME_RABIN_MILLER_TRIALS_C +# define MP_PRIME_RAND_C +# define MP_PRIME_STRONG_LUCAS_SELFRIDGE_C +# define MP_RADIX_SIZE_C +# define MP_RADIX_SIZE_OVERESTIMATE_C +# define MP_RAND_C +# define MP_RAND_SOURCE_C +# define MP_READ_RADIX_C +# define MP_REDUCE_C +# define MP_REDUCE_2K_C +# define MP_REDUCE_2K_L_C +# define MP_REDUCE_2K_SETUP_C +# define MP_REDUCE_2K_SETUP_L_C +# define MP_REDUCE_IS_2K_C +# define MP_REDUCE_IS_2K_L_C +# define MP_REDUCE_SETUP_C +# define MP_ROOT_N_C +# define MP_RSHD_C +# define MP_SBIN_SIZE_C +# define MP_SET_C +# define MP_SET_DOUBLE_C +# define MP_SET_I32_C +# define MP_SET_I64_C +# define MP_SET_L_C +# define MP_SET_U32_C +# define MP_SET_U64_C +# define MP_SET_UL_C +# define MP_SHRINK_C +# define MP_SIGNED_RSH_C +# define MP_SQRMOD_C +# define MP_SQRT_C +# define MP_SQRTMOD_PRIME_C +# define MP_SUB_C +# define MP_SUB_D_C +# define MP_SUBMOD_C +# define MP_TO_RADIX_C +# define MP_TO_SBIN_C +# define MP_TO_UBIN_C +# define MP_UBIN_SIZE_C +# define MP_UNPACK_C +# define MP_XOR_C +# define MP_ZERO_C +# define S_MP_ADD_C +# define S_MP_COPY_DIGS_C +# define S_MP_DIV_3_C +# define S_MP_DIV_RECURSIVE_C +# define S_MP_DIV_SCHOOL_C +# define S_MP_DIV_SMALL_C +# define S_MP_EXPTMOD_C +# define S_MP_EXPTMOD_FAST_C +# define S_MP_FP_LOG_C +# define S_MP_FP_LOG_D_C +# define S_MP_GET_BIT_C +# define S_MP_INVMOD_C +# define S_MP_INVMOD_ODD_C +# define S_MP_LOG_2EXPT_C +# define S_MP_MONTGOMERY_REDUCE_COMBA_C +# define S_MP_MUL_C +# define S_MP_MUL_BALANCE_C +# define S_MP_MUL_COMBA_C +# define S_MP_MUL_HIGH_C +# define S_MP_MUL_HIGH_COMBA_C +# define S_MP_MUL_KARATSUBA_C +# define S_MP_MUL_TOOM_C +# define S_MP_PRIME_IS_DIVISIBLE_C +# define S_MP_PRIME_TAB_C +# define S_MP_RADIX_MAP_C +# define S_MP_RADIX_SIZE_OVERESTIMATE_C +# define S_MP_RAND_PLATFORM_C +# define S_MP_SQR_C +# define S_MP_SQR_COMBA_C +# define S_MP_SQR_KARATSUBA_C +# define S_MP_SQR_TOOM_C +# define S_MP_SUB_C +# define S_MP_ZERO_BUF_C +# define S_MP_ZERO_DIGS_C +#endif +#endif +#if defined(MP_2EXPT_C) +# define MP_GROW_C +# define MP_ZERO_C +#endif + +#if defined(MP_ABS_C) +# define MP_COPY_C +#endif + +#if defined(MP_ADD_C) +# define MP_CMP_MAG_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_ADD_D_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define MP_SUB_D_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_ADDMOD_C) +# define MP_ADD_C +# define MP_MOD_C +#endif + +#if defined(MP_AND_C) +# define MP_CLAMP_C +# define MP_GROW_C +#endif + +#if defined(MP_CLAMP_C) +#endif + +#if defined(MP_CLEAR_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_CLEAR_MULTI_C) +# define MP_CLEAR_C +#endif + +#if defined(MP_CMP_C) +# define MP_CMP_MAG_C +#endif + +#if defined(MP_CMP_D_C) +#endif + +#if defined(MP_CMP_MAG_C) +#endif + +#if defined(MP_CNT_LSB_C) +#endif + +#if defined(MP_COMPLEMENT_C) +# define MP_SUB_D_C +#endif + +#if defined(MP_COPY_C) +# define MP_GROW_C +# define S_MP_COPY_DIGS_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_COUNT_BITS_C) +#endif + +#if defined(MP_CUTOFFS_C) +#endif + +#if defined(MP_DIV_C) +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_ZERO_C +# define S_MP_DIV_RECURSIVE_C +# define S_MP_DIV_SCHOOL_C +# define S_MP_DIV_SMALL_C +#endif + +#if defined(MP_DIV_2_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_DIV_2D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_MOD_2D_C +# define MP_RSHD_C +#endif + +#if defined(MP_DIV_D_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_DIV_2D_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define S_MP_DIV_3_C +#endif + +#if defined(MP_DR_IS_MODULUS_C) +#endif + +#if defined(MP_DR_REDUCE_C) +# define MP_CLAMP_C +# define MP_CMP_MAG_C +# define MP_GROW_C +# define S_MP_SUB_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_DR_SETUP_C) +#endif + +#if defined(MP_ERROR_TO_STRING_C) +#endif + +#if defined(MP_EXCH_C) +#endif + +#if defined(MP_EXPT_N_C) +# define MP_CLEAR_C +# define MP_INIT_COPY_C +# define MP_MUL_C +# define MP_SET_C +#endif + +#if defined(MP_EXPTMOD_C) +# define MP_ABS_C +# define MP_CLEAR_MULTI_C +# define MP_DR_IS_MODULUS_C +# define MP_INIT_MULTI_C +# define MP_INVMOD_C +# define MP_REDUCE_IS_2K_C +# define MP_REDUCE_IS_2K_L_C +# define S_MP_EXPTMOD_C +# define S_MP_EXPTMOD_FAST_C +#endif + +#if defined(MP_EXTEUCLID_C) +# define MP_CLEAR_MULTI_C +# define MP_COPY_C +# define MP_DIV_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +# define MP_NEG_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(MP_FREAD_C) +# define MP_ADD_D_C +# define MP_MUL_D_C +# define MP_ZERO_C +#endif + +#if defined(MP_FROM_SBIN_C) +# define MP_FROM_UBIN_C +#endif + +#if defined(MP_FROM_UBIN_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define MP_MUL_2D_C +# define MP_ZERO_C +#endif + +#if defined(MP_FWRITE_C) +# define MP_RADIX_SIZE_OVERESTIMATE_C +# define MP_TO_RADIX_C +# define S_MP_ZERO_BUF_C +#endif + +#if defined(MP_GCD_C) +# define MP_ABS_C +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_CNT_LSB_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_COPY_C +# define MP_MUL_2D_C +# define S_MP_SUB_C +#endif + +#if defined(MP_GET_DOUBLE_C) +#endif + +#if defined(MP_GET_I32_C) +# define MP_GET_MAG_U32_C +#endif + +#if defined(MP_GET_I64_C) +# define MP_GET_MAG_U64_C +#endif + +#if defined(MP_GET_L_C) +# define MP_GET_MAG_UL_C +#endif + +#if defined(MP_GET_MAG_U32_C) +#endif + +#if defined(MP_GET_MAG_U64_C) +#endif + +#if defined(MP_GET_MAG_UL_C) +#endif + +#if defined(MP_GROW_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_HASH_C) +#endif + +#if defined(MP_INIT_C) +#endif + +#if defined(MP_INIT_COPY_C) +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_INIT_SIZE_C +#endif + +#if defined(MP_INIT_I32_C) +# define MP_INIT_C +# define MP_SET_I32_C +#endif + +#if defined(MP_INIT_I64_C) +# define MP_INIT_C +# define MP_SET_I64_C +#endif + +#if defined(MP_INIT_L_C) +# define MP_INIT_C +# define MP_SET_L_C +#endif + +#if defined(MP_INIT_MULTI_C) +# define MP_CLEAR_C +# define MP_INIT_C +#endif + +#if defined(MP_INIT_SET_C) +# define MP_INIT_C +# define MP_SET_C +#endif + +#if defined(MP_INIT_SIZE_C) +#endif + +#if defined(MP_INIT_U32_C) +# define MP_INIT_C +# define MP_SET_U32_C +#endif + +#if defined(MP_INIT_U64_C) +# define MP_INIT_C +# define MP_SET_U64_C +#endif + +#if defined(MP_INIT_UL_C) +# define MP_INIT_C +# define MP_SET_UL_C +#endif + +#if defined(MP_INVMOD_C) +# define MP_CMP_D_C +# define MP_ZERO_C +# define S_MP_INVMOD_C +# define S_MP_INVMOD_ODD_C +#endif + +#if defined(MP_IS_SQUARE_C) +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_DIV_D_C +# define MP_GET_I32_C +# define MP_INIT_U32_C +# define MP_MOD_C +# define MP_MUL_C +# define MP_SQRT_C +#endif + +#if defined(MP_KRONECKER_C) +# define MP_CLEAR_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_COPY_C +# define MP_DIV_2D_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_MOD_C +#endif + +#if defined(MP_LCM_C) +# define MP_CLEAR_MULTI_C +# define MP_CMP_MAG_C +# define MP_DIV_C +# define MP_GCD_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +#endif + +#if defined(MP_LOG_C) +# define MP_ADD_D_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_COUNT_BITS_C +# define MP_DIV_2_C +# define MP_DIV_C +# define MP_DIV_D_C +# define MP_EXPT_N_C +# define MP_GET_I32_C +# define MP_INIT_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +# define MP_MUL_D_C +# define MP_SUB_C +# define S_MP_FP_LOG_C +# define S_MP_FP_LOG_D_C +#endif + +#if defined(MP_LOG_N_C) +# define MP_CLEAR_C +# define MP_INIT_I32_C +# define MP_LOG_C +#endif + +#if defined(MP_LSHD_C) +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MOD_C) +# define MP_ADD_C +# define MP_DIV_C +#endif + +#if defined(MP_MOD_2D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_ZERO_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MONTGOMERY_CALC_NORMALIZATION_C) +# define MP_2EXPT_C +# define MP_CMP_MAG_C +# define MP_COUNT_BITS_C +# define MP_MUL_2_C +# define MP_SET_C +# define S_MP_SUB_C +#endif + +#if defined(MP_MONTGOMERY_REDUCE_C) +# define MP_CLAMP_C +# define MP_CMP_MAG_C +# define MP_GROW_C +# define MP_RSHD_C +# define S_MP_MONTGOMERY_REDUCE_COMBA_C +# define S_MP_SUB_C +#endif + +#if defined(MP_MONTGOMERY_SETUP_C) +#endif + +#if defined(MP_MUL_C) +# define S_MP_MUL_BALANCE_C +# define S_MP_MUL_C +# define S_MP_MUL_COMBA_C +# define S_MP_MUL_KARATSUBA_C +# define S_MP_MUL_TOOM_C +# define S_MP_SQR_C +# define S_MP_SQR_COMBA_C +# define S_MP_SQR_KARATSUBA_C +# define S_MP_SQR_TOOM_C +#endif + +#if defined(MP_MUL_2_C) +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MUL_2D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_GROW_C +# define MP_LSHD_C +#endif + +#if defined(MP_MUL_D_C) +# define MP_CLAMP_C +# define MP_COPY_C +# define MP_GROW_C +# define MP_MUL_2D_C +# define MP_MUL_2_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_MULMOD_C) +# define MP_MOD_C +# define MP_MUL_C +#endif + +#if defined(MP_NEG_C) +# define MP_COPY_C +#endif + +#if defined(MP_OR_C) +# define MP_CLAMP_C +# define MP_GROW_C +#endif + +#if defined(MP_PACK_C) +# define MP_CLEAR_C +# define MP_DIV_2D_C +# define MP_INIT_COPY_C +# define MP_PACK_COUNT_C +#endif + +#if defined(MP_PACK_COUNT_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(MP_PRIME_FERMAT_C) +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_EXPTMOD_C +# define MP_INIT_C +#endif + +#if defined(MP_PRIME_FROBENIUS_UNDERWOOD_C) +# define MP_ADD_C +# define MP_ADD_D_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COUNT_BITS_C +# define MP_EXCH_C +# define MP_GCD_C +# define MP_INIT_MULTI_C +# define MP_KRONECKER_C +# define MP_MOD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_MUL_D_C +# define MP_SET_C +# define MP_SET_I32_C +# define MP_SET_U32_C +# define MP_SUB_C +# define S_MP_GET_BIT_C +#endif + +#if defined(MP_PRIME_IS_PRIME_C) +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_INIT_SET_C +# define MP_IS_SQUARE_C +# define MP_PRIME_MILLER_RABIN_C +# define MP_PRIME_STRONG_LUCAS_SELFRIDGE_C +# define MP_RAND_C +# define MP_READ_RADIX_C +# define MP_SET_C +# define S_MP_PRIME_IS_DIVISIBLE_C +#endif + +#if defined(MP_PRIME_MILLER_RABIN_C) +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_DIV_2D_C +# define MP_EXPTMOD_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_SQRMOD_C +# define MP_SUB_D_C +#endif + +#if defined(MP_PRIME_NEXT_PRIME_C) +# define MP_ADD_D_C +# define MP_CLEAR_C +# define MP_CMP_D_C +# define MP_DIV_D_C +# define MP_INIT_C +# define MP_PRIME_IS_PRIME_C +# define MP_SET_C +# define MP_SUB_D_C +#endif + +#if defined(MP_PRIME_RABIN_MILLER_TRIALS_C) +#endif + +#if defined(MP_PRIME_RAND_C) +# define MP_ADD_D_C +# define MP_DIV_2_C +# define MP_FROM_UBIN_C +# define MP_MUL_2_C +# define MP_PRIME_IS_PRIME_C +# define MP_SUB_D_C +# define S_MP_RAND_SOURCE_C +# define S_MP_ZERO_BUF_C +#endif + +#if defined(MP_PRIME_STRONG_LUCAS_SELFRIDGE_C) +# define MP_ADD_C +# define MP_ADD_D_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CNT_LSB_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_DIV_2_C +# define MP_GCD_C +# define MP_INIT_C +# define MP_INIT_MULTI_C +# define MP_KRONECKER_C +# define MP_MOD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_SET_C +# define MP_SET_I32_C +# define MP_SET_U32_C +# define MP_SUB_C +# define MP_SUB_D_C +# define S_MP_GET_BIT_C +#endif + +#if defined(MP_RADIX_SIZE_C) +# define MP_LOG_N_C +#endif + +#if defined(MP_RADIX_SIZE_OVERESTIMATE_C) +# define MP_RADIX_SIZE_C +# define S_MP_RADIX_SIZE_OVERESTIMATE_C +#endif + +#if defined(MP_RAND_C) +# define MP_GROW_C +# define MP_ZERO_C +# define S_MP_RAND_SOURCE_C +#endif + +#if defined(MP_RAND_SOURCE_C) +# define S_MP_RAND_PLATFORM_C +#endif + +#if defined(MP_READ_RADIX_C) +# define MP_ADD_D_C +# define MP_MUL_D_C +# define MP_ZERO_C +#endif + +#if defined(MP_REDUCE_C) +# define MP_ADD_C +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_INIT_COPY_C +# define MP_LSHD_C +# define MP_MOD_2D_C +# define MP_MUL_C +# define MP_RSHD_C +# define MP_SET_C +# define MP_SUB_C +# define S_MP_MUL_C +# define S_MP_MUL_HIGH_C +# define S_MP_MUL_HIGH_COMBA_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_C) +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_INIT_C +# define MP_MUL_D_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_L_C) +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_INIT_C +# define MP_MUL_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_SETUP_C) +# define MP_2EXPT_C +# define MP_CLEAR_C +# define MP_COUNT_BITS_C +# define MP_INIT_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_2K_SETUP_L_C) +# define MP_2EXPT_C +# define MP_CLEAR_C +# define MP_COUNT_BITS_C +# define MP_INIT_C +# define S_MP_SUB_C +#endif + +#if defined(MP_REDUCE_IS_2K_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(MP_REDUCE_IS_2K_L_C) +#endif + +#if defined(MP_REDUCE_SETUP_C) +# define MP_2EXPT_C +# define MP_DIV_C +#endif + +#if defined(MP_ROOT_N_C) +# define MP_2EXPT_C +# define MP_ADD_D_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_DIV_C +# define MP_EXCH_C +# define MP_EXPT_N_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +# define MP_MUL_D_C +# define MP_SET_C +# define MP_SUB_C +# define MP_SUB_D_C +#endif + +#if defined(MP_RSHD_C) +# define MP_ZERO_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SBIN_SIZE_C) +# define MP_UBIN_SIZE_C +#endif + +#if defined(MP_SET_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SET_DOUBLE_C) +# define MP_DIV_2D_C +# define MP_MUL_2D_C +# define MP_SET_U64_C +#endif + +#if defined(MP_SET_I32_C) +# define MP_SET_U32_C +#endif + +#if defined(MP_SET_I64_C) +# define MP_SET_U64_C +#endif + +#if defined(MP_SET_L_C) +# define MP_SET_UL_C +#endif + +#if defined(MP_SET_U32_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SET_U64_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SET_UL_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SHRINK_C) +#endif + +#if defined(MP_SIGNED_RSH_C) +# define MP_ADD_D_C +# define MP_DIV_2D_C +# define MP_SUB_D_C +#endif + +#if defined(MP_SQRMOD_C) +# define MP_MOD_C +# define MP_MUL_C +#endif + +#if defined(MP_SQRT_C) +# define MP_ADD_C +# define MP_CLEAR_C +# define MP_CMP_MAG_C +# define MP_DIV_2_C +# define MP_DIV_C +# define MP_EXCH_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_RSHD_C +# define MP_ZERO_C +#endif + +#if defined(MP_SQRTMOD_PRIME_C) +# define MP_ADD_D_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_D_C +# define MP_COPY_C +# define MP_DIV_2_C +# define MP_EXPTMOD_C +# define MP_INIT_MULTI_C +# define MP_KRONECKER_C +# define MP_MULMOD_C +# define MP_SET_C +# define MP_SET_I32_C +# define MP_SQRMOD_C +# define MP_SUB_D_C +# define MP_ZERO_C +#endif + +#if defined(MP_SUB_C) +# define MP_CMP_MAG_C +# define S_MP_ADD_C +# define S_MP_SUB_C +#endif + +#if defined(MP_SUB_D_C) +# define MP_ADD_D_C +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(MP_SUBMOD_C) +# define MP_MOD_C +# define MP_SUB_C +#endif + +#if defined(MP_TO_RADIX_C) +# define MP_CLEAR_C +# define MP_DIV_D_C +# define MP_INIT_COPY_C +#endif + +#if defined(MP_TO_SBIN_C) +# define MP_TO_UBIN_C +#endif + +#if defined(MP_TO_UBIN_C) +# define MP_CLEAR_C +# define MP_DIV_2D_C +# define MP_INIT_COPY_C +# define MP_UBIN_SIZE_C +#endif + +#if defined(MP_UBIN_SIZE_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(MP_UNPACK_C) +# define MP_CLAMP_C +# define MP_MUL_2D_C +# define MP_ZERO_C +#endif + +#if defined(MP_XOR_C) +# define MP_CLAMP_C +# define MP_GROW_C +#endif + +#if defined(MP_ZERO_C) +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_ADD_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_COPY_DIGS_C) +#endif + +#if defined(S_MP_DIV_3_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +#endif + +#if defined(S_MP_DIV_RECURSIVE_C) +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_D_C +# define MP_COPY_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_LSHD_C +# define MP_MUL_2D_C +# define MP_MUL_C +# define MP_SUB_C +# define MP_SUB_D_C +# define MP_ZERO_C +# define S_MP_DIV_SCHOOL_C +#endif + +#if defined(S_MP_DIV_SCHOOL_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CMP_C +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_C +# define MP_INIT_COPY_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_2D_C +# define MP_MUL_D_C +# define MP_RSHD_C +# define MP_SUB_C +# define MP_ZERO_C +#endif + +#if defined(S_MP_DIV_SMALL_C) +# define MP_ABS_C +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MUL_2D_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(S_MP_EXPTMOD_C) +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_EXCH_C +# define MP_INIT_C +# define MP_MOD_C +# define MP_MUL_C +# define MP_REDUCE_2K_L_C +# define MP_REDUCE_2K_SETUP_L_C +# define MP_REDUCE_C +# define MP_REDUCE_SETUP_C +# define MP_SET_C +#endif + +#if defined(S_MP_EXPTMOD_FAST_C) +# define MP_CLEAR_C +# define MP_COPY_C +# define MP_COUNT_BITS_C +# define MP_DR_REDUCE_C +# define MP_DR_SETUP_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define MP_MOD_C +# define MP_MONTGOMERY_CALC_NORMALIZATION_C +# define MP_MONTGOMERY_REDUCE_C +# define MP_MONTGOMERY_SETUP_C +# define MP_MULMOD_C +# define MP_MUL_C +# define MP_REDUCE_2K_C +# define MP_REDUCE_2K_SETUP_C +# define MP_SET_C +# define S_MP_MONTGOMERY_REDUCE_COMBA_C +#endif + +#if defined(S_MP_FP_LOG_C) +# define MP_2EXPT_C +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MUL_2D_C +# define MP_MUL_C +# define MP_SET_I32_C +# define S_MP_FP_LOG_FRACTION_C +#endif + +#if defined(S_MP_FP_LOG_D_C) +# define MP_CLEAR_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_GET_I64_C +# define MP_INIT_C +# define S_MP_FLOG2_MP_WORD_D_C +# define S_MP_FP_LOG_FRACTION_D_C +#endif + +#if defined(S_MP_GET_BIT_C) +#endif + +#if defined(S_MP_INVMOD_C) +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MOD_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(S_MP_INVMOD_ODD_C) +# define MP_ADD_C +# define MP_CLEAR_MULTI_C +# define MP_CMP_C +# define MP_CMP_D_C +# define MP_CMP_MAG_C +# define MP_COPY_C +# define MP_DIV_2_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_MOD_C +# define MP_SET_C +# define MP_SUB_C +#endif + +#if defined(S_MP_LOG_2EXPT_C) +# define MP_COUNT_BITS_C +#endif + +#if defined(S_MP_MONTGOMERY_REDUCE_COMBA_C) +# define MP_CLAMP_C +# define MP_CMP_MAG_C +# define MP_GROW_C +# define S_MP_SUB_C +# define S_MP_ZERO_BUF_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_MUL_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define S_MP_MUL_COMBA_C +#endif + +#if defined(S_MP_MUL_BALANCE_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_EXCH_C +# define MP_INIT_MULTI_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_C +# define S_MP_COPY_DIGS_C +#endif + +#if defined(S_MP_MUL_COMBA_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_MUL_HIGH_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +# define S_MP_MUL_HIGH_COMBA_C +#endif + +#if defined(S_MP_MUL_HIGH_COMBA_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_MUL_KARATSUBA_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_C +# define S_MP_ADD_C +# define S_MP_COPY_DIGS_C +# define S_MP_SUB_C +#endif + +#if defined(S_MP_MUL_TOOM_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_CLEAR_MULTI_C +# define MP_DIV_2_C +# define MP_INIT_MULTI_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_SUB_C +# define S_MP_COPY_DIGS_C +# define S_MP_DIV_3_C +#endif + +#if defined(S_MP_PRIME_IS_DIVISIBLE_C) +# define MP_DIV_D_C +#endif + +#if defined(S_MP_PRIME_TAB_C) +#endif + +#if defined(S_MP_RADIX_MAP_C) +#endif + +#if defined(S_MP_RADIX_SIZE_OVERESTIMATE_C) +# define MP_CLEAR_MULTI_C +# define MP_COUNT_BITS_C +# define MP_DIV_2D_C +# define MP_GET_I64_C +# define MP_INIT_MULTI_C +# define MP_MUL_C +# define MP_SET_U32_C +# define S_MP_LOG_2EXPT_C +#endif + +#if defined(S_MP_RAND_PLATFORM_C) +#endif + +#if defined(S_MP_SQR_C) +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_EXCH_C +# define MP_INIT_SIZE_C +#endif + +#if defined(S_MP_SQR_COMBA_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_SQR_KARATSUBA_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_C +# define S_MP_ADD_C +# define S_MP_COPY_DIGS_C +# define S_MP_SUB_C +#endif + +#if defined(S_MP_SQR_TOOM_C) +# define MP_ADD_C +# define MP_CLAMP_C +# define MP_CLEAR_C +# define MP_DIV_2_C +# define MP_INIT_C +# define MP_INIT_SIZE_C +# define MP_LSHD_C +# define MP_MUL_2_C +# define MP_MUL_C +# define MP_SUB_C +# define S_MP_COPY_DIGS_C +#endif + +#if defined(S_MP_SUB_C) +# define MP_CLAMP_C +# define MP_GROW_C +# define S_MP_ZERO_DIGS_C +#endif + +#if defined(S_MP_ZERO_BUF_C) +#endif + +#if defined(S_MP_ZERO_DIGS_C) +#endif + +#ifdef LTM_INSIDE +#undef LTM_INSIDE +#ifdef LTM3 +# define LTM_LAST +#endif + +#include "tommath_superclass.h" +#include "tommath_class.h" +#else +# define LTM_LAST +#endif diff --git a/deps/libtommath/tommath_cutoffs.h b/deps/libtommath/tommath_cutoffs.h new file mode 100644 index 0000000..fb84160 --- /dev/null +++ b/deps/libtommath/tommath_cutoffs.h @@ -0,0 +1,13 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* + Current values evaluated on an AMD A8-6600K (64-bit). + Type "make tune" to optimize them for your machine but + be aware that it may take a long time. It took 2:30 minutes + on the aforementioned machine for example. + */ + +#define MP_DEFAULT_MUL_KARATSUBA_CUTOFF 80 +#define MP_DEFAULT_SQR_KARATSUBA_CUTOFF 120 +#define MP_DEFAULT_MUL_TOOM_CUTOFF 350 +#define MP_DEFAULT_SQR_TOOM_CUTOFF 400 diff --git a/deps/libtommath/tommath_private.h b/deps/libtommath/tommath_private.h new file mode 100644 index 0000000..d319a1d --- /dev/null +++ b/deps/libtommath/tommath_private.h @@ -0,0 +1,300 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMMATH_PRIVATE_H_ +#define TOMMATH_PRIVATE_H_ + +#include "tommath.h" +#include "tommath_class.h" +#include + +/* + * Private symbols + * --------------- + * + * On Unix symbols can be marked as hidden if libtommath is compiled + * as a shared object. By default, symbols are visible. + * On Win32 a .def file must be used to specify the exported symbols. + */ +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32) && !defined(__CYGWIN__) +# define MP_PRIVATE __attribute__ ((visibility ("hidden"))) +#else +# define MP_PRIVATE +#endif + +/* Hardening libtommath + * -------------------- + * + * By default memory is zeroed before calling + * MP_FREE to avoid leaking data. This is good + * practice in cryptographical applications. + * + * Note however that memory allocators used + * in cryptographical applications can often + * be configured by itself to clear memory, + * rendering the clearing in tommath unnecessary. + * See for example https://github.com/GrapheneOS/hardened_malloc + * and the option CONFIG_ZERO_ON_FREE. + * + * Furthermore there are applications which + * value performance more and want this + * feature to be disabled. For such applications + * define MP_NO_ZERO_ON_FREE during compilation. + */ +#ifdef MP_NO_ZERO_ON_FREE +# define MP_FREE_BUF(mem, size) MP_FREE((mem), (size)) +# define MP_FREE_DIGS(mem, digits) MP_FREE((mem), sizeof (mp_digit) * (size_t)(digits)) +#else +# define MP_FREE_BUF(mem, size) \ +do { \ + size_t fs_ = (size); \ + void* fm_ = (mem); \ + if (fm_ != NULL) { \ + s_mp_zero_buf(fm_, fs_); \ + MP_FREE(fm_, fs_); \ + } \ +} while (0) +# define MP_FREE_DIGS(mem, digits) \ +do { \ + int fd_ = (digits); \ + mp_digit* fm_ = (mem); \ + if (fm_ != NULL) { \ + s_mp_zero_digs(fm_, fd_); \ + MP_FREE(fm_, sizeof (mp_digit) * (size_t)fd_); \ + } \ +} while (0) +#endif + +/* Tunable cutoffs + * --------------- + * + * - In the default settings, a cutoff X can be modified at runtime + * by adjusting the corresponding X_CUTOFF variable. + * + * - Tunability of the library can be disabled at compile time + * by defining the MP_FIXED_CUTOFFS macro. + * + * - There is an additional file tommath_cutoffs.h, which defines + * the default cutoffs. These can be adjusted manually or by the + * autotuner. + * + */ + +#ifdef MP_FIXED_CUTOFFS +# include "tommath_cutoffs.h" +# define MP_MUL_KARATSUBA_CUTOFF MP_DEFAULT_MUL_KARATSUBA_CUTOFF +# define MP_SQR_KARATSUBA_CUTOFF MP_DEFAULT_SQR_KARATSUBA_CUTOFF +# define MP_MUL_TOOM_CUTOFF MP_DEFAULT_MUL_TOOM_CUTOFF +# define MP_SQR_TOOM_CUTOFF MP_DEFAULT_SQR_TOOM_CUTOFF +#endif + +/* define heap macros */ +#ifndef MP_MALLOC +/* default to libc stuff */ +# include +# define MP_MALLOC(size) malloc(size) +# define MP_REALLOC(mem, oldsize, newsize) realloc((mem), (newsize)) +# define MP_CALLOC(nmemb, size) calloc((nmemb), (size)) +# define MP_FREE(mem, size) free(mem) +#else +/* prototypes for our heap functions */ +extern void *MP_MALLOC(size_t size); +extern void *MP_REALLOC(void *mem, size_t oldsize, size_t newsize); +extern void *MP_CALLOC(size_t nmemb, size_t size); +extern void MP_FREE(void *mem, size_t size); +#endif + +/* feature detection macro */ +#ifdef _MSC_VER +/* Prevent false positive: not enough arguments for function-like macro invocation */ +#pragma warning(disable: 4003) +#endif +#define MP_STRINGIZE(x) MP__STRINGIZE(x) +#define MP__STRINGIZE(x) ""#x"" +#define MP_HAS(x) (sizeof(MP_STRINGIZE(x##_C)) == 1u) + +#define MP_MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MP_MAX(x, y) (((x) > (y)) ? (x) : (y)) + +#define MP_TOUPPER(c) ((((c) >= 'a') && ((c) <= 'z')) ? (((c) + 'A') - 'a') : (c)) + +#define MP_EXCH(t, a, b) do { t _c = a; a = b; b = _c; } while (0) + +#define MP_IS_2EXPT(x) (((x) != 0u) && (((x) & ((x) - 1u)) == 0u)) + +/* TODO: same as above for bigint, merge (is it used elsewhere?) or change name */ +#define MP_IS_POWER_OF_TWO(a) (((mp_count_bits((a)) - 1) == mp_cnt_lsb((a))) ) + +/* Static assertion */ +#define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1]; + +#define MP_SIZEOF_BITS(type) ((size_t)CHAR_BIT * sizeof(type)) + +#define MP_MAX_COMBA (int)(1uL << (MP_SIZEOF_BITS(mp_word) - (2u * (size_t)MP_DIGIT_BIT))) +#define MP_WARRAY (int)(1uL << ((MP_SIZEOF_BITS(mp_word) - (2u * (size_t)MP_DIGIT_BIT)) + 1u)) + +#if defined(MP_16BIT) +typedef uint32_t mp_word; +#define MP_WORD_SIZE 4 +#elif ((defined (MP_64BIT)) && !(defined(MP_31BIT)) ) +typedef unsigned long mp_word __attribute__((mode(TI))); +#define MP_WORD_SIZE 16 +#else +typedef uint64_t mp_word; +#define MP_WORD_SIZE 8 +#endif + +MP_STATIC_ASSERT(correct_word_size, sizeof(mp_word) == (2u * sizeof(mp_digit))) + +/* default number of digits */ +#ifndef MP_DEFAULT_DIGIT_COUNT +# ifndef MP_LOW_MEM +# define MP_DEFAULT_DIGIT_COUNT 32 +# else +# define MP_DEFAULT_DIGIT_COUNT 8 +# endif +#endif + +/* Minimum number of available digits in mp_int, MP_DEFAULT_DIGIT_COUNT >= MP_MIN_DIGIT_COUNT + * - Must be at least 3 for s_mp_div_school. + * - Must be large enough such that the mp_set_u64 setter can + * store uint64_t in the mp_int without growing + */ +#define MP_MIN_DIGIT_COUNT MP_MAX(3, (((int)MP_SIZEOF_BITS(uint64_t) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT) +MP_STATIC_ASSERT(prec_geq_min_prec, MP_DEFAULT_DIGIT_COUNT >= MP_MIN_DIGIT_COUNT) + +/* Maximum number of digits. + * - Must be small enough such that mp_bit_count does not overflow. + * - Must be small enough such that mp_radix_size for base 2 does not overflow. + * mp_radix_size needs two additional bytes for zero termination and sign. + */ +#define MP_MAX_DIGIT_COUNT ((INT_MAX - 2) / MP_DIGIT_BIT) + +#if defined(__STDC_IEC_559__) || defined(__GCC_IEC_559) \ + || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) \ + || defined(__i386__) || defined(_M_X86) || defined(_M_IX86) \ + || defined(__aarch64__) || defined(__arm__) +#define MP_HAS_SET_DOUBLE +#endif + +/* + The mp_log functions rely on the size of mp_word being larger than INT_MAX and in case + there is a really weird architecture we try to check for it. Not a 100% reliable + test but it has a safe fallback. + */ +#if !(((UINT_MAX == UINT32_MAX) && (MP_WORD_SIZE > 4)) \ + || ((UINT_MAX == UINT16_MAX) && (MP_WORD_SIZE > 2))) +#define S_MP_WORD_TOO_SMALL_C +#endif + +/* random number source */ +extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size); + +/* lowlevel functions, do not call! */ +MP_PRIVATE bool s_mp_get_bit(const mp_int *a, int b) MP_WUR; +MP_PRIVATE int s_mp_log_2expt(const mp_int *a, mp_digit base) MP_WUR; + +MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_div_3(const mp_int *a, mp_int *c, mp_digit *d) MP_WUR; +MP_PRIVATE mp_err s_mp_div_recursive(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r) MP_WUR; +MP_PRIVATE mp_err s_mp_div_school(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) MP_WUR; +MP_PRIVATE mp_err s_mp_div_small(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d) MP_WUR; +MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; +MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR; +MP_PRIVATE mp_err s_mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_invmod_odd(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; + +MP_PRIVATE mp_err s_mp_montgomery_reduce_comba(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR; +MP_PRIVATE mp_err s_mp_mul(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_balance(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_high(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_high_comba(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_karatsuba(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_mul_toom(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, bool *result) MP_WUR; +MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr_comba(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr_karatsuba(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sqr_toom(const mp_int *a, mp_int *b) MP_WUR; +MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR; +MP_PRIVATE void s_mp_copy_digs(mp_digit *d, const mp_digit *s, int digits); +MP_PRIVATE void s_mp_zero_buf(void *mem, size_t size); +MP_PRIVATE void s_mp_zero_digs(mp_digit *d, int digits); +MP_PRIVATE mp_err s_mp_radix_size_overestimate(const mp_int *a, const int radix, size_t *size); + +#define MP_PRECISION_FIXED_LOG ( (int) (((sizeof(mp_word) * CHAR_BIT) / 2) - 1)) +#define MP_UPPER_LIMIT_FIXED_LOG ( (int) ( (sizeof(mp_word) * CHAR_BIT) - 1)) +MP_PRIVATE mp_err s_mp_fp_log(const mp_int *a, mp_int *c) MP_WUR; +MP_PRIVATE mp_err s_mp_fp_log_d(const mp_int *a, mp_word *c) MP_WUR; + +#define MP_RADIX_MAP_REVERSE_SIZE 80u +extern MP_PRIVATE const char s_mp_radix_map[]; +extern MP_PRIVATE const uint8_t s_mp_radix_map_reverse[]; +extern MP_PRIVATE const mp_digit s_mp_prime_tab[]; + +/* number of primes */ +#define MP_PRIME_TAB_SIZE 256 + +#define MP_GET_ENDIANNESS(x) \ + do{\ + int16_t n = 0x1; \ + char *p = (char *)&n; \ + x = (p[0] == '\x01') ? MP_LITTLE_ENDIAN : MP_BIG_ENDIAN; \ + } while (0) + +/* code-generating macros */ +#define MP_SET_UNSIGNED(name, type) \ + void name(mp_int * a, type b) \ + { \ + int i = 0; \ + while (b != 0u) { \ + a->dp[i++] = ((mp_digit)b & MP_MASK); \ + if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \ + b >>= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \ + } \ + a->used = i; \ + a->sign = MP_ZPOS; \ + s_mp_zero_digs(a->dp + a->used, a->alloc - a->used); \ + } + +#define MP_SET_SIGNED(name, uname, type, utype) \ + void name(mp_int * a, type b) \ + { \ + uname(a, (b < 0) ? -(utype)b : (utype)b); \ + if (b < 0) { a->sign = MP_NEG; } \ + } + +#define MP_INIT_INT(name , set, type) \ + mp_err name(mp_int * a, type b) \ + { \ + mp_err err; \ + if ((err = mp_init(a)) != MP_OKAY) { \ + return err; \ + } \ + set(a, b); \ + return MP_OKAY; \ + } + +#define MP_GET_MAG(name, type) \ + type name(const mp_int* a) \ + { \ + int i = MP_MIN(a->used, (int)((MP_SIZEOF_BITS(type) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT)); \ + type res = 0u; \ + while (i --> 0) { \ + res <<= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \ + res |= (type)a->dp[i]; \ + if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \ + } \ + return res; \ + } + +#define MP_GET_SIGNED(name, mag, type, utype) \ + type name(const mp_int* a) \ + { \ + utype res = mag(a); \ + return mp_isneg(a) ? (type)-res : (type)res; \ + } + +#endif diff --git a/deps/libtommath/tommath_superclass.h b/deps/libtommath/tommath_superclass.h new file mode 100644 index 0000000..9245e00 --- /dev/null +++ b/deps/libtommath/tommath_superclass.h @@ -0,0 +1,113 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* super class file for PK algos */ + +/* default ... include all MPI */ +#ifndef LTM_NOTHING +#define LTM_ALL +#endif + +/* RSA only (does not support DH/DSA/ECC) */ +/* #define SC_RSA_1 */ +/* #define SC_RSA_1_WITH_TESTS */ + +/* For reference.... On an Athlon64 optimizing for speed... + + LTM's mpi.o with all functions [striped] is 142KiB in size. + +*/ + +#ifdef SC_RSA_1_WITH_TESTS +# define MP_ERROR_TO_STRING_C +# define MP_FREAD_C +# define MP_FWRITE_C +# define MP_INCR_C +# define MP_ISEVEN_C +# define MP_ISODD_C +# define MP_NEG_C +# define MP_PRIME_FROBENIUS_UNDERWOOD_C +# define MP_RADIX_SIZE_C +# define MP_RADIX_SIZE_OVERESTIMATE_C +# define MP_LOG_N_C +# define MP_RAND_C +# define MP_REDUCE_C +# define MP_REDUCE_2K_L_C +# define MP_FROM_SBIN_C +# define MP_ROOT_N_C +# define MP_SET_L_C +# define MP_SET_UL_C +# define MP_SET_U64_C +# define MP_SET_I64_C +# define MP_SBIN_SIZE_C +# define MP_TO_RADIX_C +# define MP_TO_SBIN_C +# define S_MP_RAND_JENKINS_C +# define S_MP_RAND_PLATFORM_C +#endif + +/* Works for RSA only, mpi.o is 68KiB */ +#if defined(SC_RSA_1) || defined (SC_RSA_1_WITH_TESTS) +# define MP_CUTOFFS_C +# define MP_ADDMOD_C +# define MP_CLEAR_MULTI_C +# define MP_EXPTMOD_C +# define MP_GCD_C +# define MP_INIT_MULTI_C +# define MP_INVMOD_C +# define MP_LCM_C +# define MP_MOD_C +# define MP_MOD_D_C +# define MP_MULMOD_C +# define MP_PRIME_IS_PRIME_C +# define MP_PRIME_RABIN_MILLER_TRIALS_C +# define MP_PRIME_RAND_C +# define MP_SET_INT_C +# define MP_SHRINK_C +# define MP_TO_UNSIGNED_BIN_C +# define MP_UNSIGNED_BIN_SIZE_C +# define S_MP_PRIME_TAB_C +# define S_MP_RADIX_MAP_C + +/* other modifiers */ + + + +/* here we are on the last pass so we turn things off. The functions classes are still there + * but we remove them specifically from the build. This also invokes tweaks in functions + * like removing support for even moduli, etc... + */ +# ifdef LTM_LAST +# undef MP_DR_IS_MODULUS_C +# undef MP_DR_REDUCE_C +# undef MP_DR_SETUP_C +# undef MP_REDUCE_2K_C +# undef MP_REDUCE_2K_SETUP_C +# undef MP_REDUCE_IS_2K_C +# undef MP_REDUCE_SETUP_C +# undef S_MP_DIV_3_C +# undef S_MP_EXPTMOD_C +# undef S_MP_INVMOD_ODD_C +# undef S_MP_MUL_BALANCE_C +# undef S_MP_MUL_HIGH_C +# undef S_MP_MUL_HIGH_COMBA_C +# undef S_MP_MUL_KARATSUBA_C +# undef S_MP_MUL_TOOM_C +# undef S_MP_SQR_KARATSUBA_C +# undef S_MP_SQR_TOOM_C + +# ifndef SC_RSA_1_WITH_TESTS +# undef MP_REDUCE_C +# endif + +/* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold + * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] + * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without + * trouble. + */ +# undef MP_MONTGOMERY_REDUCE_C +# undef S_MP_MUL_C +# undef S_MP_SQR_C +# endif + +#endif diff --git a/deps/minhook b/deps/minhook deleted file mode 160000 index 0f25a24..0000000 --- a/deps/minhook +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0f25a2449b3cf878bcbdbf91b693c38149ecf029 diff --git a/deps/minhook/.editorconfig b/deps/minhook/.editorconfig new file mode 100644 index 0000000..36c09e6 --- /dev/null +++ b/deps/minhook/.editorconfig @@ -0,0 +1,22 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Windows-style newlines with a newline ending every file +[*] +end_of_line = crlf +insert_final_newline = true + +# 4 space indentation +[*.{c,h,def}] +indent_style = space +indent_size = 4 + +# Trim trailing whitespaces +[*.{c,h,def,txt}] +trim_trailing_whitespace = true + +# UTF-8 with BOM +[*.{c,h,def,txt}] +charset=utf-8-bom diff --git a/deps/minhook/.gitignore b/deps/minhook/.gitignore new file mode 100644 index 0000000..ad165d5 --- /dev/null +++ b/deps/minhook/.gitignore @@ -0,0 +1,44 @@ +#OS junk files +[Tt]humbs.db +*.DS_Store + +#Visual Studio files +*.[Oo]bj +*.user +*.aps +*.pch +*.vspscc +*.vssscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.[Cc]ache +*.ilk +*.log +*.sbr +*.sdf +*.opensdf +*.unsuccessfulbuild +ipch/ +obj/ +[Ll]ib +[Bb]in +[Dd]ebug*/ +[Rr]elease*/ +Ankh.NoLoad +*.VC.db +.vs/ + +#GCC files +*.o +*.d +*.res +*.dll +*.a + +#Visual Studio Code files +.vscode/ diff --git a/deps/minhook/AUTHORS.txt b/deps/minhook/AUTHORS.txt new file mode 100644 index 0000000..ebef1a6 --- /dev/null +++ b/deps/minhook/AUTHORS.txt @@ -0,0 +1,8 @@ +Tsuda Kageyu + Creator, maintainer + +Michael Maltsev + Added "Queue" functions. A lot of bug fixes. + +Andrey Unis + Rewrote the hook engine in plain C. diff --git a/deps/minhook/CMakeLists.txt b/deps/minhook/CMakeLists.txt new file mode 100644 index 0000000..d45414e --- /dev/null +++ b/deps/minhook/CMakeLists.txt @@ -0,0 +1,141 @@ +# MinHook - The Minimalistic API Hooking Library for x64/x86 +# Copyright (C) 2009-2017 Tsuda Kageyu. +# 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER +# 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. + +cmake_minimum_required(VERSION 3.0) + +project(minhook LANGUAGES C) + +include(CMakePackageConfigHelpers) + +set(MINHOOK_MAJOR_VERSION 1) +set(MINHOOK_MINOR_VERSION 3) +set(MINHOOK_PATCH_VERSION 3) +set(MINHOOK_VERSION ${MINHOOK_MAJOR_VERSION}.${MINHOOK_MINOR_VERSION}.${MINHOOK_PATCH_VERSION}) + +################ +# BUILD # +################ + +option(BUILD_SHARED_LIBS "build shared version" OFF) + +set(SOURCES_MINHOOK + "src/buffer.c" + "src/hook.c" + "src/trampoline.c" +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(SOURCES_HDE "src/hde/hde64.c") +else() + set(SOURCES_HDE "src/hde/hde32.c") +endif() + +if(BUILD_SHARED_LIBS) + set(RESOURCES + "dll_resources/MinHook.rc" + "dll_resources/MinHook.def" + ) +endif() + +add_library(minhook ${SOURCES_MINHOOK} ${SOURCES_HDE} ${RESOURCES}) + +target_include_directories(minhook PUBLIC + $ + $ +) + +target_include_directories(minhook PRIVATE "src/") +target_include_directories(minhook PRIVATE "src/hde/") + +if(WIN32) + set_target_properties(minhook PROPERTIES PREFIX "") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set_target_properties(minhook PROPERTIES DEBUG_POSTFIX ".x64d") + set_target_properties(minhook PROPERTIES RELEASE_POSTFIX ".x64") + set_target_properties(minhook PROPERTIES RELWITHDEBINFO_POSTFIX ".x64") + set_target_properties(minhook PROPERTIES MINSIZEREL_POSTFIX ".x64") + else() + set_target_properties(minhook PROPERTIES DEBUG_POSTFIX ".x32d") + set_target_properties(minhook PROPERTIES RELEASE_POSTFIX ".x32") + set_target_properties(minhook PROPERTIES RELWITHDEBINFO_POSTFIX ".x32") + set_target_properties(minhook PROPERTIES MINSIZEREL_POSTFIX ".x32") + endif() +else() + set_target_properties(minhook PROPERTIES PREFIX "lib") + set_target_properties(minhook PROPERTIES POSTFIX "") + set_target_properties(minhook PROPERTIES DEBUG_POSTFIX "d") +endif() + +################ +# CMAKE CONFIG # +################ + +configure_package_config_file( + "cmake/minhook-config.cmake.in" + "minhook-config.cmake" + INSTALL_DESTINATION + "lib/minhook" +) + +write_basic_package_version_file( + "minhook-config-version.cmake" +VERSION + ${MINHOOK_VERSION} +COMPATIBILITY + AnyNewerVersion +) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/minhook-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/minhook-config-version.cmake" + DESTINATION + "lib/minhook" +) + +################### +# INSTALL # +################### + +install(TARGETS minhook + EXPORT minhook-targets + RUNTIME DESTINATION "bin" + ARCHIVE DESTINATION "lib" + LIBRARY DESTINATION "lib" +) + +install( + EXPORT + minhook-targets + NAMESPACE + minhook:: + DESTINATION + "lib/minhook" +) + +install( + DIRECTORY include DESTINATION . +) diff --git a/deps/minhook/LICENSE.txt b/deps/minhook/LICENSE.txt new file mode 100644 index 0000000..74dea27 --- /dev/null +++ b/deps/minhook/LICENSE.txt @@ -0,0 +1,81 @@ +MinHook - The Minimalistic API Hooking Library for x64/x86 +Copyright (C) 2009-2017 Tsuda Kageyu. +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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER +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. + +================================================================================ +Portions of this software are Copyright (c) 2008-2009, Vyacheslav Patkov. +================================================================================ +Hacker Disassembler Engine 32 C +Copyright (c) 2008-2009, Vyacheslav Patkov. +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 COPYRIGHT HOLDERS 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. + +------------------------------------------------------------------------------- +Hacker Disassembler Engine 64 C +Copyright (c) 2008-2009, Vyacheslav Patkov. +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 COPYRIGHT HOLDERS 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. diff --git a/deps/minhook/README.md b/deps/minhook/README.md new file mode 100644 index 0000000..21cc7d5 --- /dev/null +++ b/deps/minhook/README.md @@ -0,0 +1,87 @@ +# MinHook + +[![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg)](https://opensource.org/licenses/BSD-2-Clause) + +The Minimalistic x86/x64 API Hooking Library for Windows + +http://www.codeproject.com/KB/winsdk/LibMinHook.aspx + +### Version history + +- **v1.3.3 - 8 Jan 2017** + * Added a helper function ```MH_CreateHookApiEx```. (Thanks to asm256) + * Support Visual Studio 2017 RC. + +- **v1.3.2.1 - 9 Nov 2015** (Nuget package only) + * Fixed an insufficient support for Visual Studio 2015. + +- **v1.3.2 - 1 Nov 2015** + * Support Visual Studio 2015. + * Support MinGW. + +- **v1.3.2-beta3 - 21 Jul 2015** (Nuget package only) + * Support MinGW. (Experimental) + +- **v1.3.2-beta2 - 18 May 2015** + * Fixed some subtle bugs. (Thanks to RaMMicHaeL) + * Added a helper function ```MH_StatusToString```. (Thanks to Jan Klass) + +- **v1.3.2-beta - 12 May 2015** + * Fixed a possible thread deadlock in x64 mode. (Thanks to Aleh Kazakevich) + * Reduced the footprint a little more. + * Support Visual Studio 2015 RC. (Experimental) + +- **v1.3.1.1 - 7 Apr 2015** (Nuget package only) + * Support for WDK8.0 and 8.1. + +- **v1.3.1 - 19 Mar 2015** + * No major changes from v1.3.1-beta. + +- **v1.3.1-beta - 11 Mar 2015** + * Added a helper function ```MH_CreateHookApi```. (Thanks to uniskz). + * Fixed a false memory leak reported by some tools. + * Fixed a degradated compatibility issue. + +- **v1.3 - 13 Sep 2014** + * No major changes from v1.3-beta3. + +- **v1.3-beta3 - 31 Jul 2014** + * Fixed some small bugs. + * Improved the memory management. + +- **v1.3-beta2 - 21 Jul 2014** + * Changed the parameters to Windows-friendly types. (void* to LPVOID) + * Fixed some small bugs. + * Reorganized the source files. + * Reduced the footprint a little more. + +- **v1.3-beta - 17 Jul 2014** + * Rewrote in plain C to reduce the footprint and memory usage. (suggested by Andrey Unis) + * Simplified the overall code base to make it more readable and maintainable. + * Changed the license from 3-clause to 2-clause BSD License. + +- **v1.2 - 28 Sep 2013** + * Removed boost dependency ([jarredholman](https://github.com/jarredholman/minhook)). + * Fixed a small bug in the GetRelativeBranchDestination function ([pillbug99](http://www.codeproject.com/Messages/4058892/Small-Bug-Found.aspx)). + * Added the ```MH_RemoveHook``` function, which removes a hook created with the ```MH_CreateHook``` function. + * Added the following functions to enable or disable multiple hooks in one go: ```MH_QueueEnableHook```, ```MH_QueueDisableHook```, ```MH_ApplyQueued```. This is the preferred way of handling multiple hooks as every call to `MH_EnableHook` or `MH_DisableHook` suspends and resumes all threads. + * Made the functions ```MH_EnableHook``` and ```MH_DisableHook``` enable/disable all created hooks when the ```MH_ALL_HOOKS``` parameter is passed. This, too, is an efficient way of handling multiple hooks. + * If the target function is too small to be patched with a jump, MinHook tries to place the jump above the function. If that fails as well, the ```MH_CreateHook``` function returns ```MH_ERROR_UNSUPPORTED_FUNCTION```. This fixes an issue of hooking the LoadLibraryExW function on Windows 7 x64 ([reported by Obble](http://www.codeproject.com/Messages/4578613/Re-Bug-LoadLibraryExW-hook-fails-on-windows-2008-r.aspx)). + +- **v1.1 - 26 Nov 2009** + * Changed the interface to create a hook and a trampoline function in one go to prevent the detour function from being called before the trampoline function is created. ([reported by xliqz](http://www.codeproject.com/Messages/3280374/Unsafe.aspx)) + * Shortened the function names from ```MinHook_*``` to ```MH_*``` to make them handier. + +- **v1.0 - 22 Nov 2009** + * Initial release. + +### Building MinHook - Using vcpkg + +You can download and install MinHook using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/microsoft/vcpkg + .\vcpkg\bootstrap-vcpkg.bat + .\vcpkg\vcpkg integrate install + .\vcpkg\vcpkg install minhook + +The MinHook port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. diff --git a/deps/minhook/cmake/minhook-config.cmake.in b/deps/minhook/cmake/minhook-config.cmake.in new file mode 100644 index 0000000..14e6463 --- /dev/null +++ b/deps/minhook/cmake/minhook-config.cmake.in @@ -0,0 +1,39 @@ +# MinHook - The Minimalistic API Hooking Library for x64/x86 +# Copyright (C) 2009-2017 Tsuda Kageyu. +# 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER +# 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. + +set(MINHOOK_MAJOR_VERSION "@MINHOOK_MAJOR_VERSION@") +set(MINHOOK_MINOR_VERSION "@MINHOOK_MINOR_VERSION@") +set(MINHOOK_PATCH_VERSION "@MINHOOK_PATCH_VERSION@") +set(MINHOOK_VERSION "@MINHOOK_VERSION@") + +@PACKAGE_INIT@ + +set(MINHOOK_FOUND ON) + +set_and_check(MINHOOK_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include/") +set_and_check(MINHOOK_LIBRARY_DIRS "${PACKAGE_PREFIX_DIR}/lib") + +include("${PACKAGE_PREFIX_DIR}/lib/minhook/minhook-targets.cmake") diff --git a/deps/minhook/dll_resources/MinHook.def b/deps/minhook/dll_resources/MinHook.def new file mode 100644 index 0000000..c6af698 --- /dev/null +++ b/deps/minhook/dll_resources/MinHook.def @@ -0,0 +1,14 @@ +EXPORTS + MH_Initialize + MH_Uninitialize + + MH_CreateHook + MH_CreateHookApi + MH_CreateHookApiEx + MH_RemoveHook + MH_EnableHook + MH_DisableHook + MH_QueueEnableHook + MH_QueueDisableHook + MH_ApplyQueued + MH_StatusToString diff --git a/deps/minhook/dll_resources/MinHook.rc b/deps/minhook/dll_resources/MinHook.rc new file mode 100644 index 0000000..7cbacb7 --- /dev/null +++ b/deps/minhook/dll_resources/MinHook.rc @@ -0,0 +1,32 @@ +1 VERSIONINFO + FILEVERSION 1,3,3,0 + PRODUCTVERSION 1,3,3,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Tsuda Kageyu" + VALUE "FileDescription", "MinHook - The Minimalistic API Hook Library for x64/x86" + VALUE "FileVersion", "1.3.3.0" + VALUE "InternalName", "MinHookD" + VALUE "LegalCopyright", "Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved." + VALUE "LegalTrademarks", "Tsuda Kageyu" + VALUE "ProductName", "MinHook DLL" + VALUE "ProductVersion", "1.3.3.0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/deps/minhook/include/MinHook.h b/deps/minhook/include/MinHook.h new file mode 100644 index 0000000..492d83f --- /dev/null +++ b/deps/minhook/include/MinHook.h @@ -0,0 +1,185 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER + * 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. + */ + +#pragma once + +#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) + #error MinHook supports only x86 and x64 systems. +#endif + +#include + +// MinHook Error Codes. +typedef enum MH_STATUS +{ + // Unknown error. Should not be returned. + MH_UNKNOWN = -1, + + // Successful. + MH_OK = 0, + + // MinHook is already initialized. + MH_ERROR_ALREADY_INITIALIZED, + + // MinHook is not initialized yet, or already uninitialized. + MH_ERROR_NOT_INITIALIZED, + + // The hook for the specified target function is already created. + MH_ERROR_ALREADY_CREATED, + + // The hook for the specified target function is not created yet. + MH_ERROR_NOT_CREATED, + + // The hook for the specified target function is already enabled. + MH_ERROR_ENABLED, + + // The hook for the specified target function is not enabled yet, or already + // disabled. + MH_ERROR_DISABLED, + + // The specified pointer is invalid. It points the address of non-allocated + // and/or non-executable region. + MH_ERROR_NOT_EXECUTABLE, + + // The specified target function cannot be hooked. + MH_ERROR_UNSUPPORTED_FUNCTION, + + // Failed to allocate memory. + MH_ERROR_MEMORY_ALLOC, + + // Failed to change the memory protection. + MH_ERROR_MEMORY_PROTECT, + + // The specified module is not loaded. + MH_ERROR_MODULE_NOT_FOUND, + + // The specified function is not found. + MH_ERROR_FUNCTION_NOT_FOUND +} +MH_STATUS; + +// Can be passed as a parameter to MH_EnableHook, MH_DisableHook, +// MH_QueueEnableHook or MH_QueueDisableHook. +#define MH_ALL_HOOKS NULL + +#ifdef __cplusplus +extern "C" { +#endif + + // Initialize the MinHook library. You must call this function EXACTLY ONCE + // at the beginning of your program. + MH_STATUS WINAPI MH_Initialize(VOID); + + // Uninitialize the MinHook library. You must call this function EXACTLY + // ONCE at the end of your program. + MH_STATUS WINAPI MH_Uninitialize(VOID); + + // Creates a hook for the specified target function, in disabled state. + // Parameters: + // pTarget [in] A pointer to the target function, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszProcName [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApi( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); + + // Creates a hook for the specified API function, in disabled state. + // Parameters: + // pszModule [in] A pointer to the loaded module name which contains the + // target function. + // pszProcName [in] A pointer to the target function name, which will be + // overridden by the detour function. + // pDetour [in] A pointer to the detour function, which will override + // the target function. + // ppOriginal [out] A pointer to the trampoline function, which will be + // used to call the original target function. + // This parameter can be NULL. + // ppTarget [out] A pointer to the target function, which will be used + // with other functions. + // This parameter can be NULL. + MH_STATUS WINAPI MH_CreateHookApiEx( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); + + // Removes an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); + + // Enables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // enabled in one go. + MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); + + // Disables an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // disabled in one go. + MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); + + // Queues to enable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be enabled. + MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); + + // Queues to disable an already created hook. + // Parameters: + // pTarget [in] A pointer to the target function. + // If this parameter is MH_ALL_HOOKS, all created hooks are + // queued to be disabled. + MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); + + // Applies all queued changes in one go. + MH_STATUS WINAPI MH_ApplyQueued(VOID); + + // Translates the MH_STATUS to its name as a string. + const char * WINAPI MH_StatusToString(MH_STATUS status); + +#ifdef __cplusplus +} +#endif diff --git a/deps/minhook/src/buffer.c b/deps/minhook/src/buffer.c new file mode 100644 index 0000000..55412b0 --- /dev/null +++ b/deps/minhook/src/buffer.c @@ -0,0 +1,312 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER + * 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. + */ + +#include +#include "buffer.h" + +// Size of each memory block. (= page size of VirtualAlloc) +#define MEMORY_BLOCK_SIZE 0x1000 + +// Max range for seeking a memory block. (= 1024MB) +#define MAX_MEMORY_RANGE 0x40000000 + +// Memory protection flags to check the executable address. +#define PAGE_EXECUTE_FLAGS \ + (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY) + +// Memory slot. +typedef struct _MEMORY_SLOT +{ + union + { + struct _MEMORY_SLOT *pNext; + UINT8 buffer[MEMORY_SLOT_SIZE]; + }; +} MEMORY_SLOT, *PMEMORY_SLOT; + +// Memory block info. Placed at the head of each block. +typedef struct _MEMORY_BLOCK +{ + struct _MEMORY_BLOCK *pNext; + PMEMORY_SLOT pFree; // First element of the free slot list. + UINT usedCount; +} MEMORY_BLOCK, *PMEMORY_BLOCK; + +//------------------------------------------------------------------------- +// Global Variables: +//------------------------------------------------------------------------- + +// First element of the memory block list. +PMEMORY_BLOCK g_pMemoryBlocks; + +//------------------------------------------------------------------------- +VOID InitializeBuffer(VOID) +{ + // Nothing to do for now. +} + +//------------------------------------------------------------------------- +VOID UninitializeBuffer(VOID) +{ + PMEMORY_BLOCK pBlock = g_pMemoryBlocks; + g_pMemoryBlocks = NULL; + + while (pBlock) + { + PMEMORY_BLOCK pNext = pBlock->pNext; + VirtualFree(pBlock, 0, MEM_RELEASE); + pBlock = pNext; + } +} + +//------------------------------------------------------------------------- +#if defined(_M_X64) || defined(__x86_64__) +static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity) +{ + ULONG_PTR tryAddr = (ULONG_PTR)pAddress; + + // Round down to the allocation granularity. + tryAddr -= tryAddr % dwAllocationGranularity; + + // Start from the previous allocation granularity multiply. + tryAddr -= dwAllocationGranularity; + + while (tryAddr >= (ULONG_PTR)pMinAddr) + { + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0) + break; + + if (mbi.State == MEM_FREE) + return (LPVOID)tryAddr; + + if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity) + break; + + tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity; + } + + return NULL; +} +#endif + +//------------------------------------------------------------------------- +#if defined(_M_X64) || defined(__x86_64__) +static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity) +{ + ULONG_PTR tryAddr = (ULONG_PTR)pAddress; + + // Round down to the allocation granularity. + tryAddr -= tryAddr % dwAllocationGranularity; + + // Start from the next allocation granularity multiply. + tryAddr += dwAllocationGranularity; + + while (tryAddr <= (ULONG_PTR)pMaxAddr) + { + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0) + break; + + if (mbi.State == MEM_FREE) + return (LPVOID)tryAddr; + + tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize; + + // Round up to the next allocation granularity. + tryAddr += dwAllocationGranularity - 1; + tryAddr -= tryAddr % dwAllocationGranularity; + } + + return NULL; +} +#endif + +//------------------------------------------------------------------------- +static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin) +{ + PMEMORY_BLOCK pBlock; +#if defined(_M_X64) || defined(__x86_64__) + ULONG_PTR minAddr; + ULONG_PTR maxAddr; + + SYSTEM_INFO si; + GetSystemInfo(&si); + minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress; + maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress; + + // pOrigin ± 512MB + if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE) + minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE; + + if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE) + maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE; + + // Make room for MEMORY_BLOCK_SIZE bytes. + maxAddr -= MEMORY_BLOCK_SIZE - 1; +#endif + + // Look the registered blocks for a reachable one. + for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext) + { +#if defined(_M_X64) || defined(__x86_64__) + // Ignore the blocks too far. + if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr) + continue; +#endif + // The block has at least one unused slot. + if (pBlock->pFree != NULL) + return pBlock; + } + +#if defined(_M_X64) || defined(__x86_64__) + // Alloc a new block above if not found. + { + LPVOID pAlloc = pOrigin; + while ((ULONG_PTR)pAlloc >= minAddr) + { + pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity); + if (pAlloc == NULL) + break; + + pBlock = (PMEMORY_BLOCK)VirtualAlloc( + pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (pBlock != NULL) + break; + } + } + + // Alloc a new block below if not found. + if (pBlock == NULL) + { + LPVOID pAlloc = pOrigin; + while ((ULONG_PTR)pAlloc <= maxAddr) + { + pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity); + if (pAlloc == NULL) + break; + + pBlock = (PMEMORY_BLOCK)VirtualAlloc( + pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (pBlock != NULL) + break; + } + } +#else + // In x86 mode, a memory block can be placed anywhere. + pBlock = (PMEMORY_BLOCK)VirtualAlloc( + NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); +#endif + + if (pBlock != NULL) + { + // Build a linked list of all the slots. + PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1; + pBlock->pFree = NULL; + pBlock->usedCount = 0; + do + { + pSlot->pNext = pBlock->pFree; + pBlock->pFree = pSlot; + pSlot++; + } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE); + + pBlock->pNext = g_pMemoryBlocks; + g_pMemoryBlocks = pBlock; + } + + return pBlock; +} + +//------------------------------------------------------------------------- +LPVOID AllocateBuffer(LPVOID pOrigin) +{ + PMEMORY_SLOT pSlot; + PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin); + if (pBlock == NULL) + return NULL; + + // Remove an unused slot from the list. + pSlot = pBlock->pFree; + pBlock->pFree = pSlot->pNext; + pBlock->usedCount++; +#ifdef _DEBUG + // Fill the slot with INT3 for debugging. + memset(pSlot, 0xCC, sizeof(MEMORY_SLOT)); +#endif + return pSlot; +} + +//------------------------------------------------------------------------- +VOID FreeBuffer(LPVOID pBuffer) +{ + PMEMORY_BLOCK pBlock = g_pMemoryBlocks; + PMEMORY_BLOCK pPrev = NULL; + ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE; + + while (pBlock != NULL) + { + if ((ULONG_PTR)pBlock == pTargetBlock) + { + PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer; +#ifdef _DEBUG + // Clear the released slot for debugging. + memset(pSlot, 0x00, sizeof(MEMORY_SLOT)); +#endif + // Restore the released slot to the list. + pSlot->pNext = pBlock->pFree; + pBlock->pFree = pSlot; + pBlock->usedCount--; + + // Free if unused. + if (pBlock->usedCount == 0) + { + if (pPrev) + pPrev->pNext = pBlock->pNext; + else + g_pMemoryBlocks = pBlock->pNext; + + VirtualFree(pBlock, 0, MEM_RELEASE); + } + + break; + } + + pPrev = pBlock; + pBlock = pBlock->pNext; + } +} + +//------------------------------------------------------------------------- +BOOL IsExecutableAddress(LPVOID pAddress) +{ + MEMORY_BASIC_INFORMATION mi; + VirtualQuery(pAddress, &mi, sizeof(mi)); + + return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS)); +} diff --git a/deps/minhook/src/buffer.h b/deps/minhook/src/buffer.h new file mode 100644 index 0000000..204d551 --- /dev/null +++ b/deps/minhook/src/buffer.h @@ -0,0 +1,42 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER + * 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. + */ + +#pragma once + +// Size of each memory slot. +#if defined(_M_X64) || defined(__x86_64__) + #define MEMORY_SLOT_SIZE 64 +#else + #define MEMORY_SLOT_SIZE 32 +#endif + +VOID InitializeBuffer(VOID); +VOID UninitializeBuffer(VOID); +LPVOID AllocateBuffer(LPVOID pOrigin); +VOID FreeBuffer(LPVOID pBuffer); +BOOL IsExecutableAddress(LPVOID pAddress); diff --git a/deps/minhook/src/hde/hde32.c b/deps/minhook/src/hde/hde32.c new file mode 100644 index 0000000..eb6af9b --- /dev/null +++ b/deps/minhook/src/hde/hde32.c @@ -0,0 +1,324 @@ +/* + * Hacker Disassembler Engine 32 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#if defined(_M_IX86) || defined(__i386__) + +#include +#include "hde32.h" +#include "table32.h" + +unsigned int hde32_disasm(const void *code, hde32s *hs) +{ + uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; + uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0; + + memset(hs, 0, sizeof(hde32s)); + + for (x = 16; x; x--) + switch (c = *p++) { + case 0xf3: + hs->p_rep = c; + pref |= PRE_F3; + break; + case 0xf2: + hs->p_rep = c; + pref |= PRE_F2; + break; + case 0xf0: + hs->p_lock = c; + pref |= PRE_LOCK; + break; + case 0x26: case 0x2e: case 0x36: + case 0x3e: case 0x64: case 0x65: + hs->p_seg = c; + pref |= PRE_SEG; + break; + case 0x66: + hs->p_66 = c; + pref |= PRE_66; + break; + case 0x67: + hs->p_67 = c; + pref |= PRE_67; + break; + default: + goto pref_done; + } + pref_done: + + hs->flags = (uint32_t)pref << 23; + + if (!pref) + pref |= PRE_NONE; + + if ((hs->opcode = c) == 0x0f) { + hs->opcode2 = c = *p++; + ht += DELTA_OPCODES; + } else if (c >= 0xa0 && c <= 0xa3) { + if (pref & PRE_67) + pref |= PRE_66; + else + pref &= ~PRE_66; + } + + opcode = c; + cflags = ht[ht[opcode / 4] + (opcode % 4)]; + + if (cflags == C_ERROR) { + hs->flags |= F_ERROR | F_ERROR_OPCODE; + cflags = 0; + if ((opcode & -3) == 0x24) + cflags++; + } + + x = 0; + if (cflags & C_GROUP) { + uint16_t t; + t = *(uint16_t *)(ht + (cflags & 0x7f)); + cflags = (uint8_t)t; + x = (uint8_t)(t >> 8); + } + + if (hs->opcode2) { + ht = hde32_table + DELTA_PREFIXES; + if (ht[ht[opcode / 4] + (opcode % 4)] & pref) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (cflags & C_MODRM) { + hs->flags |= F_MODRM; + hs->modrm = c = *p++; + hs->modrm_mod = m_mod = c >> 6; + hs->modrm_rm = m_rm = c & 7; + hs->modrm_reg = m_reg = (c & 0x3f) >> 3; + + if (x && ((x << m_reg) & 0x80)) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + + if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { + uint8_t t = opcode - 0xd9; + if (m_mod == 3) { + ht = hde32_table + DELTA_FPU_MODRM + t*8; + t = ht[m_reg] << m_rm; + } else { + ht = hde32_table + DELTA_FPU_REG; + t = ht[t] << m_reg; + } + if (t & 0x80) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (pref & PRE_LOCK) { + if (m_mod == 3) { + hs->flags |= F_ERROR | F_ERROR_LOCK; + } else { + uint8_t *table_end, op = opcode; + if (hs->opcode2) { + ht = hde32_table + DELTA_OP2_LOCK_OK; + table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; + } else { + ht = hde32_table + DELTA_OP_LOCK_OK; + table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; + op &= -2; + } + for (; ht != table_end; ht++) + if (*ht++ == op) { + if (!((*ht << m_reg) & 0x80)) + goto no_lock_error; + else + break; + } + hs->flags |= F_ERROR | F_ERROR_LOCK; + no_lock_error: + ; + } + } + + if (hs->opcode2) { + switch (opcode) { + case 0x20: case 0x22: + m_mod = 3; + if (m_reg > 4 || m_reg == 1) + goto error_operand; + else + goto no_error_operand; + case 0x21: case 0x23: + m_mod = 3; + if (m_reg == 4 || m_reg == 5) + goto error_operand; + else + goto no_error_operand; + } + } else { + switch (opcode) { + case 0x8c: + if (m_reg > 5) + goto error_operand; + else + goto no_error_operand; + case 0x8e: + if (m_reg == 1 || m_reg > 5) + goto error_operand; + else + goto no_error_operand; + } + } + + if (m_mod == 3) { + uint8_t *table_end; + if (hs->opcode2) { + ht = hde32_table + DELTA_OP2_ONLY_MEM; + table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM; + } else { + ht = hde32_table + DELTA_OP_ONLY_MEM; + table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; + } + for (; ht != table_end; ht += 2) + if (*ht++ == opcode) { + if ((*ht++ & pref) && !((*ht << m_reg) & 0x80)) + goto error_operand; + else + break; + } + goto no_error_operand; + } else if (hs->opcode2) { + switch (opcode) { + case 0x50: case 0xd7: case 0xf7: + if (pref & (PRE_NONE | PRE_66)) + goto error_operand; + break; + case 0xd6: + if (pref & (PRE_F2 | PRE_F3)) + goto error_operand; + break; + case 0xc5: + goto error_operand; + } + goto no_error_operand; + } else + goto no_error_operand; + + error_operand: + hs->flags |= F_ERROR | F_ERROR_OPERAND; + no_error_operand: + + c = *p++; + if (m_reg <= 1) { + if (opcode == 0xf6) + cflags |= C_IMM8; + else if (opcode == 0xf7) + cflags |= C_IMM_P66; + } + + switch (m_mod) { + case 0: + if (pref & PRE_67) { + if (m_rm == 6) + disp_size = 2; + } else + if (m_rm == 5) + disp_size = 4; + break; + case 1: + disp_size = 1; + break; + case 2: + disp_size = 2; + if (!(pref & PRE_67)) + disp_size <<= 1; + break; + } + + if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) { + hs->flags |= F_SIB; + p++; + hs->sib = c; + hs->sib_scale = c >> 6; + hs->sib_index = (c & 0x3f) >> 3; + if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) + disp_size = 4; + } + + p--; + switch (disp_size) { + case 1: + hs->flags |= F_DISP8; + hs->disp.disp8 = *p; + break; + case 2: + hs->flags |= F_DISP16; + hs->disp.disp16 = *(uint16_t *)p; + break; + case 4: + hs->flags |= F_DISP32; + hs->disp.disp32 = *(uint32_t *)p; + break; + } + p += disp_size; + } else if (pref & PRE_LOCK) + hs->flags |= F_ERROR | F_ERROR_LOCK; + + if (cflags & C_IMM_P66) { + if (cflags & C_REL32) { + if (pref & PRE_66) { + hs->flags |= F_IMM16 | F_RELATIVE; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + goto disasm_done; + } + goto rel32_ok; + } + if (pref & PRE_66) { + hs->flags |= F_IMM16; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + } else { + hs->flags |= F_IMM32; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } + } + + if (cflags & C_IMM16) { + if (hs->flags & F_IMM32) { + hs->flags |= F_IMM16; + hs->disp.disp16 = *(uint16_t *)p; + } else if (hs->flags & F_IMM16) { + hs->flags |= F_2IMM16; + hs->disp.disp16 = *(uint16_t *)p; + } else { + hs->flags |= F_IMM16; + hs->imm.imm16 = *(uint16_t *)p; + } + p += 2; + } + if (cflags & C_IMM8) { + hs->flags |= F_IMM8; + hs->imm.imm8 = *p++; + } + + if (cflags & C_REL32) { + rel32_ok: + hs->flags |= F_IMM32 | F_RELATIVE; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } else if (cflags & C_REL8) { + hs->flags |= F_IMM8 | F_RELATIVE; + hs->imm.imm8 = *p++; + } + + disasm_done: + + if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { + hs->flags |= F_ERROR | F_ERROR_LENGTH; + hs->len = 15; + } + + return (unsigned int)hs->len; +} + +#endif // defined(_M_IX86) || defined(__i386__) diff --git a/deps/minhook/src/hde/hde32.h b/deps/minhook/src/hde/hde32.h new file mode 100644 index 0000000..1112450 --- /dev/null +++ b/deps/minhook/src/hde/hde32.h @@ -0,0 +1,105 @@ +/* + * Hacker Disassembler Engine 32 + * Copyright (c) 2006-2009, Vyacheslav Patkov. + * All rights reserved. + * + * hde32.h: C/C++ header file + * + */ + +#ifndef _HDE32_H_ +#define _HDE32_H_ + +/* stdint.h - C99 standard header + * http://en.wikipedia.org/wiki/stdint.h + * + * if your compiler doesn't contain "stdint.h" header (for + * example, Microsoft Visual C++), you can download file: + * http://www.azillionmonkeys.com/qed/pstdint.h + * and change next line to: + * #include "pstdint.h" + */ +#include "pstdint.h" + +#define F_MODRM 0x00000001 +#define F_SIB 0x00000002 +#define F_IMM8 0x00000004 +#define F_IMM16 0x00000008 +#define F_IMM32 0x00000010 +#define F_DISP8 0x00000020 +#define F_DISP16 0x00000040 +#define F_DISP32 0x00000080 +#define F_RELATIVE 0x00000100 +#define F_2IMM16 0x00000800 +#define F_ERROR 0x00001000 +#define F_ERROR_OPCODE 0x00002000 +#define F_ERROR_LENGTH 0x00004000 +#define F_ERROR_LOCK 0x00008000 +#define F_ERROR_OPERAND 0x00010000 +#define F_PREFIX_REPNZ 0x01000000 +#define F_PREFIX_REPX 0x02000000 +#define F_PREFIX_REP 0x03000000 +#define F_PREFIX_66 0x04000000 +#define F_PREFIX_67 0x08000000 +#define F_PREFIX_LOCK 0x10000000 +#define F_PREFIX_SEG 0x20000000 +#define F_PREFIX_ANY 0x3f000000 + +#define PREFIX_SEGMENT_CS 0x2e +#define PREFIX_SEGMENT_SS 0x36 +#define PREFIX_SEGMENT_DS 0x3e +#define PREFIX_SEGMENT_ES 0x26 +#define PREFIX_SEGMENT_FS 0x64 +#define PREFIX_SEGMENT_GS 0x65 +#define PREFIX_LOCK 0xf0 +#define PREFIX_REPNZ 0xf2 +#define PREFIX_REPX 0xf3 +#define PREFIX_OPERAND_SIZE 0x66 +#define PREFIX_ADDRESS_SIZE 0x67 + +#pragma pack(push,1) + +typedef struct { + uint8_t len; + uint8_t p_rep; + uint8_t p_lock; + uint8_t p_seg; + uint8_t p_66; + uint8_t p_67; + uint8_t opcode; + uint8_t opcode2; + uint8_t modrm; + uint8_t modrm_mod; + uint8_t modrm_reg; + uint8_t modrm_rm; + uint8_t sib; + uint8_t sib_scale; + uint8_t sib_index; + uint8_t sib_base; + union { + uint8_t imm8; + uint16_t imm16; + uint32_t imm32; + } imm; + union { + uint8_t disp8; + uint16_t disp16; + uint32_t disp32; + } disp; + uint32_t flags; +} hde32s; + +#pragma pack(pop) + +#ifdef __cplusplus +extern "C" { +#endif + +/* __cdecl */ +unsigned int hde32_disasm(const void *code, hde32s *hs); + +#ifdef __cplusplus +} +#endif + +#endif /* _HDE32_H_ */ diff --git a/deps/minhook/src/hde/hde64.c b/deps/minhook/src/hde/hde64.c new file mode 100644 index 0000000..ce773b1 --- /dev/null +++ b/deps/minhook/src/hde/hde64.c @@ -0,0 +1,335 @@ +/* + * Hacker Disassembler Engine 64 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#if defined(_M_X64) || defined(__x86_64__) + +#include +#include "hde64.h" +#include "table64.h" + +unsigned int hde64_disasm(const void *code, hde64s *hs) +{ + uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0; + uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0; + uint8_t op64 = 0; + + memset(hs, 0, sizeof(hde64s)); + + for (x = 16; x; x--) + switch (c = *p++) { + case 0xf3: + hs->p_rep = c; + pref |= PRE_F3; + break; + case 0xf2: + hs->p_rep = c; + pref |= PRE_F2; + break; + case 0xf0: + hs->p_lock = c; + pref |= PRE_LOCK; + break; + case 0x26: case 0x2e: case 0x36: + case 0x3e: case 0x64: case 0x65: + hs->p_seg = c; + pref |= PRE_SEG; + break; + case 0x66: + hs->p_66 = c; + pref |= PRE_66; + break; + case 0x67: + hs->p_67 = c; + pref |= PRE_67; + break; + default: + goto pref_done; + } + pref_done: + + hs->flags = (uint32_t)pref << 23; + + if (!pref) + pref |= PRE_NONE; + + if ((c & 0xf0) == 0x40) { + hs->flags |= F_PREFIX_REX; + if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8) + op64++; + hs->rex_r = (c & 7) >> 2; + hs->rex_x = (c & 3) >> 1; + hs->rex_b = c & 1; + if (((c = *p++) & 0xf0) == 0x40) { + opcode = c; + goto error_opcode; + } + } + + if ((hs->opcode = c) == 0x0f) { + hs->opcode2 = c = *p++; + ht += DELTA_OPCODES; + } else if (c >= 0xa0 && c <= 0xa3) { + op64++; + if (pref & PRE_67) + pref |= PRE_66; + else + pref &= ~PRE_66; + } + + opcode = c; + cflags = ht[ht[opcode / 4] + (opcode % 4)]; + + if (cflags == C_ERROR) { + error_opcode: + hs->flags |= F_ERROR | F_ERROR_OPCODE; + cflags = 0; + if ((opcode & -3) == 0x24) + cflags++; + } + + x = 0; + if (cflags & C_GROUP) { + uint16_t t; + t = *(uint16_t *)(ht + (cflags & 0x7f)); + cflags = (uint8_t)t; + x = (uint8_t)(t >> 8); + } + + if (hs->opcode2) { + ht = hde64_table + DELTA_PREFIXES; + if (ht[ht[opcode / 4] + (opcode % 4)] & pref) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (cflags & C_MODRM) { + hs->flags |= F_MODRM; + hs->modrm = c = *p++; + hs->modrm_mod = m_mod = c >> 6; + hs->modrm_rm = m_rm = c & 7; + hs->modrm_reg = m_reg = (c & 0x3f) >> 3; + + if (x && ((x << m_reg) & 0x80)) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + + if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) { + uint8_t t = opcode - 0xd9; + if (m_mod == 3) { + ht = hde64_table + DELTA_FPU_MODRM + t*8; + t = ht[m_reg] << m_rm; + } else { + ht = hde64_table + DELTA_FPU_REG; + t = ht[t] << m_reg; + } + if (t & 0x80) + hs->flags |= F_ERROR | F_ERROR_OPCODE; + } + + if (pref & PRE_LOCK) { + if (m_mod == 3) { + hs->flags |= F_ERROR | F_ERROR_LOCK; + } else { + uint8_t *table_end, op = opcode; + if (hs->opcode2) { + ht = hde64_table + DELTA_OP2_LOCK_OK; + table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK; + } else { + ht = hde64_table + DELTA_OP_LOCK_OK; + table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK; + op &= -2; + } + for (; ht != table_end; ht++) + if (*ht++ == op) { + if (!((*ht << m_reg) & 0x80)) + goto no_lock_error; + else + break; + } + hs->flags |= F_ERROR | F_ERROR_LOCK; + no_lock_error: + ; + } + } + + if (hs->opcode2) { + switch (opcode) { + case 0x20: case 0x22: + m_mod = 3; + if (m_reg > 4 || m_reg == 1) + goto error_operand; + else + goto no_error_operand; + case 0x21: case 0x23: + m_mod = 3; + if (m_reg == 4 || m_reg == 5) + goto error_operand; + else + goto no_error_operand; + } + } else { + switch (opcode) { + case 0x8c: + if (m_reg > 5) + goto error_operand; + else + goto no_error_operand; + case 0x8e: + if (m_reg == 1 || m_reg > 5) + goto error_operand; + else + goto no_error_operand; + } + } + + if (m_mod == 3) { + uint8_t *table_end; + if (hs->opcode2) { + ht = hde64_table + DELTA_OP2_ONLY_MEM; + table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM; + } else { + ht = hde64_table + DELTA_OP_ONLY_MEM; + table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM; + } + for (; ht != table_end; ht += 2) + if (*ht++ == opcode) { + if ((*ht++ & pref) && !((*ht << m_reg) & 0x80)) + goto error_operand; + else + break; + } + goto no_error_operand; + } else if (hs->opcode2) { + switch (opcode) { + case 0x50: case 0xd7: case 0xf7: + if (pref & (PRE_NONE | PRE_66)) + goto error_operand; + break; + case 0xd6: + if (pref & (PRE_F2 | PRE_F3)) + goto error_operand; + break; + case 0xc5: + goto error_operand; + } + goto no_error_operand; + } else + goto no_error_operand; + + error_operand: + hs->flags |= F_ERROR | F_ERROR_OPERAND; + no_error_operand: + + c = *p++; + if (m_reg <= 1) { + if (opcode == 0xf6) + cflags |= C_IMM8; + else if (opcode == 0xf7) + cflags |= C_IMM_P66; + } + + switch (m_mod) { + case 0: + if (pref & PRE_67) { + if (m_rm == 6) + disp_size = 2; + } else + if (m_rm == 5) + disp_size = 4; + break; + case 1: + disp_size = 1; + break; + case 2: + disp_size = 2; + if (!(pref & PRE_67)) + disp_size <<= 1; + break; + } + + if (m_mod != 3 && m_rm == 4) { + hs->flags |= F_SIB; + p++; + hs->sib = c; + hs->sib_scale = c >> 6; + hs->sib_index = (c & 0x3f) >> 3; + if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1)) + disp_size = 4; + } + + p--; + switch (disp_size) { + case 1: + hs->flags |= F_DISP8; + hs->disp.disp8 = *p; + break; + case 2: + hs->flags |= F_DISP16; + hs->disp.disp16 = *(uint16_t *)p; + break; + case 4: + hs->flags |= F_DISP32; + hs->disp.disp32 = *(uint32_t *)p; + break; + } + p += disp_size; + } else if (pref & PRE_LOCK) + hs->flags |= F_ERROR | F_ERROR_LOCK; + + if (cflags & C_IMM_P66) { + if (cflags & C_REL32) { + if (pref & PRE_66) { + hs->flags |= F_IMM16 | F_RELATIVE; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + goto disasm_done; + } + goto rel32_ok; + } + if (op64) { + hs->flags |= F_IMM64; + hs->imm.imm64 = *(uint64_t *)p; + p += 8; + } else if (!(pref & PRE_66)) { + hs->flags |= F_IMM32; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } else + goto imm16_ok; + } + + + if (cflags & C_IMM16) { + imm16_ok: + hs->flags |= F_IMM16; + hs->imm.imm16 = *(uint16_t *)p; + p += 2; + } + if (cflags & C_IMM8) { + hs->flags |= F_IMM8; + hs->imm.imm8 = *p++; + } + + if (cflags & C_REL32) { + rel32_ok: + hs->flags |= F_IMM32 | F_RELATIVE; + hs->imm.imm32 = *(uint32_t *)p; + p += 4; + } else if (cflags & C_REL8) { + hs->flags |= F_IMM8 | F_RELATIVE; + hs->imm.imm8 = *p++; + } + + disasm_done: + + if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) { + hs->flags |= F_ERROR | F_ERROR_LENGTH; + hs->len = 15; + } + + return (unsigned int)hs->len; +} + +#endif // defined(_M_X64) || defined(__x86_64__) diff --git a/deps/minhook/src/hde/hde64.h b/deps/minhook/src/hde/hde64.h new file mode 100644 index 0000000..ecbf4df --- /dev/null +++ b/deps/minhook/src/hde/hde64.h @@ -0,0 +1,112 @@ +/* + * Hacker Disassembler Engine 64 + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + * hde64.h: C/C++ header file + * + */ + +#ifndef _HDE64_H_ +#define _HDE64_H_ + +/* stdint.h - C99 standard header + * http://en.wikipedia.org/wiki/stdint.h + * + * if your compiler doesn't contain "stdint.h" header (for + * example, Microsoft Visual C++), you can download file: + * http://www.azillionmonkeys.com/qed/pstdint.h + * and change next line to: + * #include "pstdint.h" + */ +#include "pstdint.h" + +#define F_MODRM 0x00000001 +#define F_SIB 0x00000002 +#define F_IMM8 0x00000004 +#define F_IMM16 0x00000008 +#define F_IMM32 0x00000010 +#define F_IMM64 0x00000020 +#define F_DISP8 0x00000040 +#define F_DISP16 0x00000080 +#define F_DISP32 0x00000100 +#define F_RELATIVE 0x00000200 +#define F_ERROR 0x00001000 +#define F_ERROR_OPCODE 0x00002000 +#define F_ERROR_LENGTH 0x00004000 +#define F_ERROR_LOCK 0x00008000 +#define F_ERROR_OPERAND 0x00010000 +#define F_PREFIX_REPNZ 0x01000000 +#define F_PREFIX_REPX 0x02000000 +#define F_PREFIX_REP 0x03000000 +#define F_PREFIX_66 0x04000000 +#define F_PREFIX_67 0x08000000 +#define F_PREFIX_LOCK 0x10000000 +#define F_PREFIX_SEG 0x20000000 +#define F_PREFIX_REX 0x40000000 +#define F_PREFIX_ANY 0x7f000000 + +#define PREFIX_SEGMENT_CS 0x2e +#define PREFIX_SEGMENT_SS 0x36 +#define PREFIX_SEGMENT_DS 0x3e +#define PREFIX_SEGMENT_ES 0x26 +#define PREFIX_SEGMENT_FS 0x64 +#define PREFIX_SEGMENT_GS 0x65 +#define PREFIX_LOCK 0xf0 +#define PREFIX_REPNZ 0xf2 +#define PREFIX_REPX 0xf3 +#define PREFIX_OPERAND_SIZE 0x66 +#define PREFIX_ADDRESS_SIZE 0x67 + +#pragma pack(push,1) + +typedef struct { + uint8_t len; + uint8_t p_rep; + uint8_t p_lock; + uint8_t p_seg; + uint8_t p_66; + uint8_t p_67; + uint8_t rex; + uint8_t rex_w; + uint8_t rex_r; + uint8_t rex_x; + uint8_t rex_b; + uint8_t opcode; + uint8_t opcode2; + uint8_t modrm; + uint8_t modrm_mod; + uint8_t modrm_reg; + uint8_t modrm_rm; + uint8_t sib; + uint8_t sib_scale; + uint8_t sib_index; + uint8_t sib_base; + union { + uint8_t imm8; + uint16_t imm16; + uint32_t imm32; + uint64_t imm64; + } imm; + union { + uint8_t disp8; + uint16_t disp16; + uint32_t disp32; + } disp; + uint32_t flags; +} hde64s; + +#pragma pack(pop) + +#ifdef __cplusplus +extern "C" { +#endif + +/* __cdecl */ +unsigned int hde64_disasm(const void *code, hde64s *hs); + +#ifdef __cplusplus +} +#endif + +#endif /* _HDE64_H_ */ diff --git a/deps/minhook/src/hde/pstdint.h b/deps/minhook/src/hde/pstdint.h new file mode 100644 index 0000000..84d82a0 --- /dev/null +++ b/deps/minhook/src/hde/pstdint.h @@ -0,0 +1,39 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. 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 "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 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. + */ + +#pragma once + +#include + +// Integer types for HDE. +typedef INT8 int8_t; +typedef INT16 int16_t; +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; diff --git a/deps/minhook/src/hde/table32.h b/deps/minhook/src/hde/table32.h new file mode 100644 index 0000000..7b3e12e --- /dev/null +++ b/deps/minhook/src/hde/table32.h @@ -0,0 +1,73 @@ +/* + * Hacker Disassembler Engine 32 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#define C_NONE 0x00 +#define C_MODRM 0x01 +#define C_IMM8 0x02 +#define C_IMM16 0x04 +#define C_IMM_P66 0x10 +#define C_REL8 0x20 +#define C_REL32 0x40 +#define C_GROUP 0x80 +#define C_ERROR 0xff + +#define PRE_ANY 0x00 +#define PRE_NONE 0x01 +#define PRE_F2 0x02 +#define PRE_F3 0x04 +#define PRE_66 0x08 +#define PRE_67 0x10 +#define PRE_LOCK 0x20 +#define PRE_SEG 0x40 +#define PRE_ALL 0xff + +#define DELTA_OPCODES 0x4a +#define DELTA_FPU_REG 0xf1 +#define DELTA_FPU_MODRM 0xf8 +#define DELTA_PREFIXES 0x130 +#define DELTA_OP_LOCK_OK 0x1a1 +#define DELTA_OP2_LOCK_OK 0x1b9 +#define DELTA_OP_ONLY_MEM 0x1cb +#define DELTA_OP2_ONLY_MEM 0x1da + +unsigned char hde32_table[] = { + 0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3, + 0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f, + 0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3, + 0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa, + 0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90, + 0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f, + 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d, + 0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59, + 0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59, + 0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0, + 0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01, + 0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11, + 0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8, + 0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca, + 0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff, + 0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03, + 0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00, + 0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f, + 0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a, + 0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a, + 0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a, + 0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06, + 0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06, + 0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, + 0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08, + 0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01, + 0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba, + 0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00, + 0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00, + 0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07, + 0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf, + 0xe7,0x08,0x00,0xf0,0x02,0x00 +}; diff --git a/deps/minhook/src/hde/table64.h b/deps/minhook/src/hde/table64.h new file mode 100644 index 0000000..01d4541 --- /dev/null +++ b/deps/minhook/src/hde/table64.h @@ -0,0 +1,74 @@ +/* + * Hacker Disassembler Engine 64 C + * Copyright (c) 2008-2009, Vyacheslav Patkov. + * All rights reserved. + * + */ + +#define C_NONE 0x00 +#define C_MODRM 0x01 +#define C_IMM8 0x02 +#define C_IMM16 0x04 +#define C_IMM_P66 0x10 +#define C_REL8 0x20 +#define C_REL32 0x40 +#define C_GROUP 0x80 +#define C_ERROR 0xff + +#define PRE_ANY 0x00 +#define PRE_NONE 0x01 +#define PRE_F2 0x02 +#define PRE_F3 0x04 +#define PRE_66 0x08 +#define PRE_67 0x10 +#define PRE_LOCK 0x20 +#define PRE_SEG 0x40 +#define PRE_ALL 0xff + +#define DELTA_OPCODES 0x4a +#define DELTA_FPU_REG 0xfd +#define DELTA_FPU_MODRM 0x104 +#define DELTA_PREFIXES 0x13c +#define DELTA_OP_LOCK_OK 0x1ae +#define DELTA_OP2_LOCK_OK 0x1c6 +#define DELTA_OP_ONLY_MEM 0x1d8 +#define DELTA_OP2_ONLY_MEM 0x1e7 + +unsigned char hde64_table[] = { + 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5, + 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1, + 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea, + 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0, + 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab, + 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92, + 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90, + 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b, + 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b, + 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc, + 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20, + 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff, + 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00, + 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01, + 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10, + 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00, + 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00, + 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00, + 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40, + 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43, + 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40, + 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06, + 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07, + 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04, + 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10, + 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00, + 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb, + 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff, + 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09, + 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff, + 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08, + 0x00,0xf0,0x02,0x00 +}; diff --git a/deps/minhook/src/hook.c b/deps/minhook/src/hook.c new file mode 100644 index 0000000..2eb33c0 --- /dev/null +++ b/deps/minhook/src/hook.c @@ -0,0 +1,923 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER + * 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. + */ + +#include +#include +#include + +#include "../include/MinHook.h" +#include "buffer.h" +#include "trampoline.h" + +#ifndef ARRAYSIZE + #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + +// Initial capacity of the HOOK_ENTRY buffer. +#define INITIAL_HOOK_CAPACITY 32 + +// Initial capacity of the thread IDs buffer. +#define INITIAL_THREAD_CAPACITY 128 + +// Special hook position values. +#define INVALID_HOOK_POS UINT_MAX +#define ALL_HOOKS_POS UINT_MAX + +// Freeze() action argument defines. +#define ACTION_DISABLE 0 +#define ACTION_ENABLE 1 +#define ACTION_APPLY_QUEUED 2 + +// Thread access rights for suspending/resuming threads. +#define THREAD_ACCESS \ + (THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT) + +// Hook information. +typedef struct _HOOK_ENTRY +{ + LPVOID pTarget; // Address of the target function. + LPVOID pDetour; // Address of the detour or relay function. + LPVOID pTrampoline; // Address of the trampoline function. + UINT8 backup[8]; // Original prologue of the target function. + + UINT8 patchAbove : 1; // Uses the hot patch area. + UINT8 isEnabled : 1; // Enabled. + UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled. + + UINT nIP : 4; // Count of the instruction boundaries. + UINT8 oldIPs[8]; // Instruction boundaries of the target function. + UINT8 newIPs[8]; // Instruction boundaries of the trampoline function. +} HOOK_ENTRY, *PHOOK_ENTRY; + +// Suspended threads for Freeze()/Unfreeze(). +typedef struct _FROZEN_THREADS +{ + LPDWORD pItems; // Data heap + UINT capacity; // Size of allocated data heap, items + UINT size; // Actual number of data items +} FROZEN_THREADS, *PFROZEN_THREADS; + +//------------------------------------------------------------------------- +// Global Variables: +//------------------------------------------------------------------------- + +// Spin lock flag for EnterSpinLock()/LeaveSpinLock(). +volatile LONG g_isLocked = FALSE; + +// Private heap handle. If not NULL, this library is initialized. +HANDLE g_hHeap = NULL; + +// Hook entries. +struct +{ + PHOOK_ENTRY pItems; // Data heap + UINT capacity; // Size of allocated data heap, items + UINT size; // Actual number of data items +} g_hooks; + +//------------------------------------------------------------------------- +// Returns INVALID_HOOK_POS if not found. +static UINT FindHookEntry(LPVOID pTarget) +{ + UINT i; + for (i = 0; i < g_hooks.size; ++i) + { + if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget) + return i; + } + + return INVALID_HOOK_POS; +} + +//------------------------------------------------------------------------- +static PHOOK_ENTRY AddHookEntry() +{ + if (g_hooks.pItems == NULL) + { + g_hooks.capacity = INITIAL_HOOK_CAPACITY; + g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc( + g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY)); + if (g_hooks.pItems == NULL) + return NULL; + } + else if (g_hooks.size >= g_hooks.capacity) + { + PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc( + g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY)); + if (p == NULL) + return NULL; + + g_hooks.capacity *= 2; + g_hooks.pItems = p; + } + + return &g_hooks.pItems[g_hooks.size++]; +} + +//------------------------------------------------------------------------- +static VOID DeleteHookEntry(UINT pos) +{ + if (pos < g_hooks.size - 1) + g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1]; + + g_hooks.size--; + + if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size) + { + PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc( + g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY)); + if (p == NULL) + return; + + g_hooks.capacity /= 2; + g_hooks.pItems = p; + } +} + +//------------------------------------------------------------------------- +static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip) +{ + UINT i; + + if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL))) + return (DWORD_PTR)pHook->pTarget; + + for (i = 0; i < pHook->nIP; ++i) + { + if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i])) + return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]; + } + +#if defined(_M_X64) || defined(__x86_64__) + // Check relay function. + if (ip == (DWORD_PTR)pHook->pDetour) + return (DWORD_PTR)pHook->pTarget; +#endif + + return 0; +} + +//------------------------------------------------------------------------- +static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip) +{ + UINT i; + for (i = 0; i < pHook->nIP; ++i) + { + if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i])) + return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]; + } + + return 0; +} + +//------------------------------------------------------------------------- +static VOID ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action) +{ + // If the thread suspended in the overwritten area, + // move IP to the proper address. + + CONTEXT c; +#if defined(_M_X64) || defined(__x86_64__) + DWORD64 *pIP = &c.Rip; +#else + DWORD *pIP = &c.Eip; +#endif + UINT count; + + c.ContextFlags = CONTEXT_CONTROL; + if (!GetThreadContext(hThread, &c)) + return; + + if (pos == ALL_HOOKS_POS) + { + pos = 0; + count = g_hooks.size; + } + else + { + count = pos + 1; + } + + for (; pos < count; ++pos) + { + PHOOK_ENTRY pHook = &g_hooks.pItems[pos]; + BOOL enable; + DWORD_PTR ip; + + switch (action) + { + case ACTION_DISABLE: + enable = FALSE; + break; + + case ACTION_ENABLE: + enable = TRUE; + break; + + default: // ACTION_APPLY_QUEUED + enable = pHook->queueEnable; + break; + } + if (pHook->isEnabled == enable) + continue; + + if (enable) + ip = FindNewIP(pHook, *pIP); + else + ip = FindOldIP(pHook, *pIP); + + if (ip != 0) + { + *pIP = ip; + SetThreadContext(hThread, &c); + } + } +} + +//------------------------------------------------------------------------- +static BOOL EnumerateThreads(PFROZEN_THREADS pThreads) +{ + BOOL succeeded = FALSE; + + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hSnapshot != INVALID_HANDLE_VALUE) + { + THREADENTRY32 te; + te.dwSize = sizeof(THREADENTRY32); + if (Thread32First(hSnapshot, &te)) + { + succeeded = TRUE; + do + { + if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD)) + && te.th32OwnerProcessID == GetCurrentProcessId() + && te.th32ThreadID != GetCurrentThreadId()) + { + if (pThreads->pItems == NULL) + { + pThreads->capacity = INITIAL_THREAD_CAPACITY; + pThreads->pItems + = (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD)); + if (pThreads->pItems == NULL) + { + succeeded = FALSE; + break; + } + } + else if (pThreads->size >= pThreads->capacity) + { + pThreads->capacity *= 2; + LPDWORD p = (LPDWORD)HeapReAlloc( + g_hHeap, 0, pThreads->pItems, pThreads->capacity * sizeof(DWORD)); + if (p == NULL) + { + succeeded = FALSE; + break; + } + + pThreads->pItems = p; + } + pThreads->pItems[pThreads->size++] = te.th32ThreadID; + } + + te.dwSize = sizeof(THREADENTRY32); + } while (Thread32Next(hSnapshot, &te)); + + if (succeeded && GetLastError() != ERROR_NO_MORE_FILES) + succeeded = FALSE; + + if (!succeeded && pThreads->pItems != NULL) + { + HeapFree(g_hHeap, 0, pThreads->pItems); + pThreads->pItems = NULL; + } + } + CloseHandle(hSnapshot); + } + + return succeeded; +} + +//------------------------------------------------------------------------- +static MH_STATUS Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action) +{ + MH_STATUS status = MH_OK; + + pThreads->pItems = NULL; + pThreads->capacity = 0; + pThreads->size = 0; + if (!EnumerateThreads(pThreads)) + { + status = MH_ERROR_MEMORY_ALLOC; + } + else if (pThreads->pItems != NULL) + { + UINT i; + for (i = 0; i < pThreads->size; ++i) + { + HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]); + if (hThread != NULL) + { + SuspendThread(hThread); + ProcessThreadIPs(hThread, pos, action); + CloseHandle(hThread); + } + } + } + + return status; +} + +//------------------------------------------------------------------------- +static VOID Unfreeze(PFROZEN_THREADS pThreads) +{ + if (pThreads->pItems != NULL) + { + UINT i; + for (i = 0; i < pThreads->size; ++i) + { + HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]); + if (hThread != NULL) + { + ResumeThread(hThread); + CloseHandle(hThread); + } + } + + HeapFree(g_hHeap, 0, pThreads->pItems); + } +} + +//------------------------------------------------------------------------- +static MH_STATUS EnableHookLL(UINT pos, BOOL enable) +{ + PHOOK_ENTRY pHook = &g_hooks.pItems[pos]; + DWORD oldProtect; + SIZE_T patchSize = sizeof(JMP_REL); + LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget; + + if (pHook->patchAbove) + { + pPatchTarget -= sizeof(JMP_REL); + patchSize += sizeof(JMP_REL_SHORT); + } + + if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect)) + return MH_ERROR_MEMORY_PROTECT; + + if (enable) + { + PJMP_REL pJmp = (PJMP_REL)pPatchTarget; + pJmp->opcode = 0xE9; + pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL))); + + if (pHook->patchAbove) + { + PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget; + pShortJmp->opcode = 0xEB; + pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL))); + } + } + else + { + if (pHook->patchAbove) + memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT)); + else + memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL)); + } + + VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect); + + // Just-in-case measure. + FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize); + + pHook->isEnabled = enable; + pHook->queueEnable = enable; + + return MH_OK; +} + +//------------------------------------------------------------------------- +static MH_STATUS EnableAllHooksLL(BOOL enable) +{ + MH_STATUS status = MH_OK; + UINT i, first = INVALID_HOOK_POS; + + for (i = 0; i < g_hooks.size; ++i) + { + if (g_hooks.pItems[i].isEnabled != enable) + { + first = i; + break; + } + } + + if (first != INVALID_HOOK_POS) + { + FROZEN_THREADS threads; + status = Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE); + if (status == MH_OK) + { + for (i = first; i < g_hooks.size; ++i) + { + if (g_hooks.pItems[i].isEnabled != enable) + { + status = EnableHookLL(i, enable); + if (status != MH_OK) + break; + } + } + + Unfreeze(&threads); + } + } + + return status; +} + +//------------------------------------------------------------------------- +static VOID EnterSpinLock(VOID) +{ + SIZE_T spinCount = 0; + + // Wait until the flag is FALSE. + while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE) + { + // No need to generate a memory barrier here, since InterlockedCompareExchange() + // generates a full memory barrier itself. + + // Prevent the loop from being too busy. + if (spinCount < 32) + Sleep(0); + else + Sleep(1); + + spinCount++; + } +} + +//------------------------------------------------------------------------- +static VOID LeaveSpinLock(VOID) +{ + // No need to generate a memory barrier here, since InterlockedExchange() + // generates a full memory barrier itself. + + InterlockedExchange(&g_isLocked, FALSE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_Initialize(VOID) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap == NULL) + { + g_hHeap = HeapCreate(0, 0, 0); + if (g_hHeap != NULL) + { + // Initialize the internal function buffer. + InitializeBuffer(); + } + else + { + status = MH_ERROR_MEMORY_ALLOC; + } + } + else + { + status = MH_ERROR_ALREADY_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_Uninitialize(VOID) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + status = EnableAllHooksLL(FALSE); + if (status == MH_OK) + { + // Free the internal function buffer. + + // HeapFree is actually not required, but some tools detect a false + // memory leak without HeapFree. + + UninitializeBuffer(); + + HeapFree(g_hHeap, 0, g_hooks.pItems); + HeapDestroy(g_hHeap); + + g_hHeap = NULL; + + g_hooks.pItems = NULL; + g_hooks.capacity = 0; + g_hooks.size = 0; + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour)) + { + UINT pos = FindHookEntry(pTarget); + if (pos == INVALID_HOOK_POS) + { + LPVOID pBuffer = AllocateBuffer(pTarget); + if (pBuffer != NULL) + { + TRAMPOLINE ct; + + ct.pTarget = pTarget; + ct.pDetour = pDetour; + ct.pTrampoline = pBuffer; + if (CreateTrampolineFunction(&ct)) + { + PHOOK_ENTRY pHook = AddHookEntry(); + if (pHook != NULL) + { + pHook->pTarget = ct.pTarget; +#if defined(_M_X64) || defined(__x86_64__) + pHook->pDetour = ct.pRelay; +#else + pHook->pDetour = ct.pDetour; +#endif + pHook->pTrampoline = ct.pTrampoline; + pHook->patchAbove = ct.patchAbove; + pHook->isEnabled = FALSE; + pHook->queueEnable = FALSE; + pHook->nIP = ct.nIP; + memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs)); + memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs)); + + // Back up the target function. + + if (ct.patchAbove) + { + memcpy( + pHook->backup, + (LPBYTE)pTarget - sizeof(JMP_REL), + sizeof(JMP_REL) + sizeof(JMP_REL_SHORT)); + } + else + { + memcpy(pHook->backup, pTarget, sizeof(JMP_REL)); + } + + if (ppOriginal != NULL) + *ppOriginal = pHook->pTrampoline; + } + else + { + status = MH_ERROR_MEMORY_ALLOC; + } + } + else + { + status = MH_ERROR_UNSUPPORTED_FUNCTION; + } + + if (status != MH_OK) + { + FreeBuffer(pBuffer); + } + } + else + { + status = MH_ERROR_MEMORY_ALLOC; + } + } + else + { + status = MH_ERROR_ALREADY_CREATED; + } + } + else + { + status = MH_ERROR_NOT_EXECUTABLE; + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + UINT pos = FindHookEntry(pTarget); + if (pos != INVALID_HOOK_POS) + { + if (g_hooks.pItems[pos].isEnabled) + { + FROZEN_THREADS threads; + status = Freeze(&threads, pos, ACTION_DISABLE); + if (status == MH_OK) + { + status = EnableHookLL(pos, FALSE); + + Unfreeze(&threads); + } + } + + if (status == MH_OK) + { + FreeBuffer(g_hooks.pItems[pos].pTrampoline); + DeleteHookEntry(pos); + } + } + else + { + status = MH_ERROR_NOT_CREATED; + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + if (pTarget == MH_ALL_HOOKS) + { + status = EnableAllHooksLL(enable); + } + else + { + UINT pos = FindHookEntry(pTarget); + if (pos != INVALID_HOOK_POS) + { + if (g_hooks.pItems[pos].isEnabled != enable) + { + FROZEN_THREADS threads; + status = Freeze(&threads, pos, ACTION_ENABLE); + if (status == MH_OK) + { + status = EnableHookLL(pos, enable); + + Unfreeze(&threads); + } + } + else + { + status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED; + } + } + else + { + status = MH_ERROR_NOT_CREATED; + } + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget) +{ + return EnableHook(pTarget, TRUE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget) +{ + return EnableHook(pTarget, FALSE); +} + +//------------------------------------------------------------------------- +static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable) +{ + MH_STATUS status = MH_OK; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + if (pTarget == MH_ALL_HOOKS) + { + UINT i; + for (i = 0; i < g_hooks.size; ++i) + g_hooks.pItems[i].queueEnable = queueEnable; + } + else + { + UINT pos = FindHookEntry(pTarget); + if (pos != INVALID_HOOK_POS) + { + g_hooks.pItems[pos].queueEnable = queueEnable; + } + else + { + status = MH_ERROR_NOT_CREATED; + } + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget) +{ + return QueueHook(pTarget, TRUE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget) +{ + return QueueHook(pTarget, FALSE); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_ApplyQueued(VOID) +{ + MH_STATUS status = MH_OK; + UINT i, first = INVALID_HOOK_POS; + + EnterSpinLock(); + + if (g_hHeap != NULL) + { + for (i = 0; i < g_hooks.size; ++i) + { + if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable) + { + first = i; + break; + } + } + + if (first != INVALID_HOOK_POS) + { + FROZEN_THREADS threads; + status = Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED); + if (status == MH_OK) + { + for (i = first; i < g_hooks.size; ++i) + { + PHOOK_ENTRY pHook = &g_hooks.pItems[i]; + if (pHook->isEnabled != pHook->queueEnable) + { + status = EnableHookLL(i, pHook->queueEnable); + if (status != MH_OK) + break; + } + } + + Unfreeze(&threads); + } + } + } + else + { + status = MH_ERROR_NOT_INITIALIZED; + } + + LeaveSpinLock(); + + return status; +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_CreateHookApiEx( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, + LPVOID *ppOriginal, LPVOID *ppTarget) +{ + HMODULE hModule; + LPVOID pTarget; + + hModule = GetModuleHandleW(pszModule); + if (hModule == NULL) + return MH_ERROR_MODULE_NOT_FOUND; + + pTarget = (LPVOID)GetProcAddress(hModule, pszProcName); + if (pTarget == NULL) + return MH_ERROR_FUNCTION_NOT_FOUND; + + if(ppTarget != NULL) + *ppTarget = pTarget; + + return MH_CreateHook(pTarget, pDetour, ppOriginal); +} + +//------------------------------------------------------------------------- +MH_STATUS WINAPI MH_CreateHookApi( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal) +{ + return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL); +} + +//------------------------------------------------------------------------- +const char * WINAPI MH_StatusToString(MH_STATUS status) +{ +#define MH_ST2STR(x) \ + case x: \ + return #x; + + switch (status) { + MH_ST2STR(MH_UNKNOWN) + MH_ST2STR(MH_OK) + MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED) + MH_ST2STR(MH_ERROR_NOT_INITIALIZED) + MH_ST2STR(MH_ERROR_ALREADY_CREATED) + MH_ST2STR(MH_ERROR_NOT_CREATED) + MH_ST2STR(MH_ERROR_ENABLED) + MH_ST2STR(MH_ERROR_DISABLED) + MH_ST2STR(MH_ERROR_NOT_EXECUTABLE) + MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION) + MH_ST2STR(MH_ERROR_MEMORY_ALLOC) + MH_ST2STR(MH_ERROR_MEMORY_PROTECT) + MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND) + MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND) + } + +#undef MH_ST2STR + + return "(unknown)"; +} diff --git a/deps/minhook/src/trampoline.c b/deps/minhook/src/trampoline.c new file mode 100644 index 0000000..5060382 --- /dev/null +++ b/deps/minhook/src/trampoline.c @@ -0,0 +1,321 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER + * 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. + */ + +#include + +#if defined(_MSC_VER) && !defined(MINHOOK_DISABLE_INTRINSICS) + #define ALLOW_INTRINSICS + #include +#endif + +#ifndef ARRAYSIZE + #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#endif + +#if defined(_M_X64) || defined(__x86_64__) + #include "./hde/hde64.h" + typedef hde64s HDE; + #define HDE_DISASM(code, hs) hde64_disasm(code, hs) +#else + #include "./hde/hde32.h" + typedef hde32s HDE; + #define HDE_DISASM(code, hs) hde32_disasm(code, hs) +#endif + +#include "trampoline.h" +#include "buffer.h" + +// Maximum size of a trampoline function. +#if defined(_M_X64) || defined(__x86_64__) + #define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS)) +#else + #define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE +#endif + +//------------------------------------------------------------------------- +static BOOL IsCodePadding(LPBYTE pInst, UINT size) +{ + UINT i; + + if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC) + return FALSE; + + for (i = 1; i < size; ++i) + { + if (pInst[i] != pInst[0]) + return FALSE; + } + return TRUE; +} + +//------------------------------------------------------------------------- +BOOL CreateTrampolineFunction(PTRAMPOLINE ct) +{ +#if defined(_M_X64) || defined(__x86_64__) + CALL_ABS call = { + 0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8] + 0xEB, 0x08, // EB 08: JMP +10 + 0x0000000000000000ULL // Absolute destination address + }; + JMP_ABS jmp = { + 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] + 0x0000000000000000ULL // Absolute destination address + }; + JCC_ABS jcc = { + 0x70, 0x0E, // 7* 0E: J** +16 + 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6] + 0x0000000000000000ULL // Absolute destination address + }; +#else + CALL_REL call = { + 0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx + 0x00000000 // Relative destination address + }; + JMP_REL jmp = { + 0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx + 0x00000000 // Relative destination address + }; + JCC_REL jcc = { + 0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx + 0x00000000 // Relative destination address + }; +#endif + + UINT8 oldPos = 0; + UINT8 newPos = 0; + ULONG_PTR jmpDest = 0; // Destination address of an internal jump. + BOOL finished = FALSE; // Is the function completed? +#if defined(_M_X64) || defined(__x86_64__) + UINT8 instBuf[16]; +#endif + + ct->patchAbove = FALSE; + ct->nIP = 0; + + do + { + HDE hs; + UINT copySize; + LPVOID pCopySrc; + ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos; + ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos; + + copySize = HDE_DISASM((LPVOID)pOldInst, &hs); + if (hs.flags & F_ERROR) + return FALSE; + + pCopySrc = (LPVOID)pOldInst; + if (oldPos >= sizeof(JMP_REL)) + { + // The trampoline function is long enough. + // Complete the function with the jump to the target function. +#if defined(_M_X64) || defined(__x86_64__) + jmp.address = pOldInst; +#else + jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp))); +#endif + pCopySrc = &jmp; + copySize = sizeof(jmp); + + finished = TRUE; + } +#if defined(_M_X64) || defined(__x86_64__) + else if ((hs.modrm & 0xC7) == 0x05) + { + // Instructions using RIP relative addressing. (ModR/M = 00???101B) + + // Modify the RIP relative address. + PUINT32 pRelAddr; + + // Avoid using memcpy to reduce the footprint. +#ifndef ALLOW_INTRINSICS + memcpy(instBuf, (LPBYTE)pOldInst, copySize); +#else + __movsb(instBuf, (LPBYTE)pOldInst, copySize); +#endif + pCopySrc = instBuf; + + // Relative address is stored at (instruction length - immediate value length - 4). + pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4); + *pRelAddr + = (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len)); + + // Complete the function if JMP (FF /4). + if (hs.opcode == 0xFF && hs.modrm_reg == 4) + finished = TRUE; + } +#endif + else if (hs.opcode == 0xE8) + { + // Direct relative CALL + ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32; +#if defined(_M_X64) || defined(__x86_64__) + call.address = dest; +#else + call.operand = (UINT32)(dest - (pNewInst + sizeof(call))); +#endif + pCopySrc = &call; + copySize = sizeof(call); + } + else if ((hs.opcode & 0xFD) == 0xE9) + { + // Direct relative JMP (EB or E9) + ULONG_PTR dest = pOldInst + hs.len; + + if (hs.opcode == 0xEB) // isShort jmp + dest += (INT8)hs.imm.imm8; + else + dest += (INT32)hs.imm.imm32; + + // Simply copy an internal jump. + if ((ULONG_PTR)ct->pTarget <= dest + && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) + { + if (jmpDest < dest) + jmpDest = dest; + } + else + { +#if defined(_M_X64) || defined(__x86_64__) + jmp.address = dest; +#else + jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp))); +#endif + pCopySrc = &jmp; + copySize = sizeof(jmp); + + // Exit the function if it is not in the branch. + finished = (pOldInst >= jmpDest); + } + } + else if ((hs.opcode & 0xF0) == 0x70 + || (hs.opcode & 0xFC) == 0xE0 + || (hs.opcode2 & 0xF0) == 0x80) + { + // Direct relative Jcc + ULONG_PTR dest = pOldInst + hs.len; + + if ((hs.opcode & 0xF0) == 0x70 // Jcc + || (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ + dest += (INT8)hs.imm.imm8; + else + dest += (INT32)hs.imm.imm32; + + // Simply copy an internal jump. + if ((ULONG_PTR)ct->pTarget <= dest + && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL))) + { + if (jmpDest < dest) + jmpDest = dest; + } + else if ((hs.opcode & 0xFC) == 0xE0) + { + // LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported. + return FALSE; + } + else + { + UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F); +#if defined(_M_X64) || defined(__x86_64__) + // Invert the condition in x64 mode to simplify the conditional jump logic. + jcc.opcode = 0x71 ^ cond; + jcc.address = dest; +#else + jcc.opcode1 = 0x80 | cond; + jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc))); +#endif + pCopySrc = &jcc; + copySize = sizeof(jcc); + } + } + else if ((hs.opcode & 0xFE) == 0xC2) + { + // RET (C2 or C3) + + // Complete the function if not in a branch. + finished = (pOldInst >= jmpDest); + } + + // Can't alter the instruction length in a branch. + if (pOldInst < jmpDest && copySize != hs.len) + return FALSE; + + // Trampoline function is too large. + if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE) + return FALSE; + + // Trampoline function has too many instructions. + if (ct->nIP >= ARRAYSIZE(ct->oldIPs)) + return FALSE; + + ct->oldIPs[ct->nIP] = oldPos; + ct->newIPs[ct->nIP] = newPos; + ct->nIP++; + + // Avoid using memcpy to reduce the footprint. +#ifndef ALLOW_INTRINSICS + memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize); +#else + __movsb((LPBYTE)ct->pTrampoline + newPos, (LPBYTE)pCopySrc, copySize); +#endif + newPos += copySize; + oldPos += hs.len; + } + while (!finished); + + // Is there enough place for a long jump? + if (oldPos < sizeof(JMP_REL) + && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos)) + { + // Is there enough place for a short jump? + if (oldPos < sizeof(JMP_REL_SHORT) + && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos)) + { + return FALSE; + } + + // Can we place the long jump above the function? + if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL))) + return FALSE; + + if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL))) + return FALSE; + + ct->patchAbove = TRUE; + } + +#if defined(_M_X64) || defined(__x86_64__) + // Create a relay function. + jmp.address = (ULONG_PTR)ct->pDetour; + + ct->pRelay = (LPBYTE)ct->pTrampoline + newPos; + memcpy(ct->pRelay, &jmp, sizeof(jmp)); +#endif + + return TRUE; +} diff --git a/deps/minhook/src/trampoline.h b/deps/minhook/src/trampoline.h new file mode 100644 index 0000000..bdffdac --- /dev/null +++ b/deps/minhook/src/trampoline.h @@ -0,0 +1,105 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER + * 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. + */ + +#pragma once + +#pragma pack(push, 1) + +// Structs for writing x86/x64 instructions. + +// 8-bit relative jump. +typedef struct _JMP_REL_SHORT +{ + UINT8 opcode; // EB xx: JMP +2+xx + UINT8 operand; +} JMP_REL_SHORT, *PJMP_REL_SHORT; + +// 32-bit direct relative jump/call. +typedef struct _JMP_REL +{ + UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx + UINT32 operand; // Relative destination address +} JMP_REL, *PJMP_REL, CALL_REL; + +// 64-bit indirect absolute jump. +typedef struct _JMP_ABS +{ + UINT8 opcode0; // FF25 00000000: JMP [+6] + UINT8 opcode1; + UINT32 dummy; + UINT64 address; // Absolute destination address +} JMP_ABS, *PJMP_ABS; + +// 64-bit indirect absolute call. +typedef struct _CALL_ABS +{ + UINT8 opcode0; // FF15 00000002: CALL [+6] + UINT8 opcode1; + UINT32 dummy0; + UINT8 dummy1; // EB 08: JMP +10 + UINT8 dummy2; + UINT64 address; // Absolute destination address +} CALL_ABS; + +// 32-bit direct relative conditional jumps. +typedef struct _JCC_REL +{ + UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx + UINT8 opcode1; + UINT32 operand; // Relative destination address +} JCC_REL; + +// 64bit indirect absolute conditional jumps that x64 lacks. +typedef struct _JCC_ABS +{ + UINT8 opcode; // 7* 0E: J** +16 + UINT8 dummy0; + UINT8 dummy1; // FF25 00000000: JMP [+6] + UINT8 dummy2; + UINT32 dummy3; + UINT64 address; // Absolute destination address +} JCC_ABS; + +#pragma pack(pop) + +typedef struct _TRAMPOLINE +{ + LPVOID pTarget; // [In] Address of the target function. + LPVOID pDetour; // [In] Address of the detour function. + LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function. + +#if defined(_M_X64) || defined(__x86_64__) + LPVOID pRelay; // [Out] Address of the relay function. +#endif + BOOL patchAbove; // [Out] Should use the hot patch area? + UINT nIP; // [Out] Number of the instruction boundaries. + UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function. + UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function. +} TRAMPOLINE, *PTRAMPOLINE; + +BOOL CreateTrampolineFunction(PTRAMPOLINE ct); diff --git a/deps/rapidjson b/deps/rapidjson deleted file mode 160000 index 973dc9c..0000000 --- a/deps/rapidjson +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 973dc9c06dcd3d035ebd039cfb9ea457721ec213 diff --git a/deps/rapidjson/.gitattributes b/deps/rapidjson/.gitattributes new file mode 100644 index 0000000..6f598bb --- /dev/null +++ b/deps/rapidjson/.gitattributes @@ -0,0 +1,22 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cpp text +*.h text +*.txt text +*.md text +*.cmake text +*.svg text +*.dot text +*.yml text +*.in text +*.sh text +*.autopkg text +Dockerfile text + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.json binary \ No newline at end of file diff --git a/deps/rapidjson/.gitignore b/deps/rapidjson/.gitignore new file mode 100644 index 0000000..5932e82 --- /dev/null +++ b/deps/rapidjson/.gitignore @@ -0,0 +1,29 @@ +/bin/* +!/bin/data +!/bin/encodings +!/bin/jsonchecker +!/bin/types +!/bin/unittestschema +/build +/doc/html +/doc/doxygen_*.db +*.a + +# Temporary files created during CMake build +CMakeCache.txt +CMakeFiles +cmake_install.cmake +CTestTestfile.cmake +Makefile +RapidJSON*.cmake +RapidJSON.pc +Testing +/googletest +install_manifest.txt +Doxyfile +Doxyfile.zh-cn +DartConfiguration.tcl +*.nupkg + +# Files created by OS +*.DS_Store diff --git a/deps/rapidjson/.gitmodules b/deps/rapidjson/.gitmodules new file mode 100644 index 0000000..5e41f7c --- /dev/null +++ b/deps/rapidjson/.gitmodules @@ -0,0 +1,3 @@ +[submodule "thirdparty/gtest"] + path = thirdparty/gtest + url = https://github.com/google/googletest.git diff --git a/deps/rapidjson/.travis.yml b/deps/rapidjson/.travis.yml new file mode 100644 index 0000000..17d8f03 --- /dev/null +++ b/deps/rapidjson/.travis.yml @@ -0,0 +1,166 @@ +sudo: required +dist: xenial + +language: cpp +cache: + - ccache + +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - cmake + - valgrind + - clang-8 +env: + global: + - USE_CCACHE=1 + - CCACHE_SLOPPINESS=pch_defines,time_macros + - CCACHE_COMPRESS=1 + - CCACHE_MAXSIZE=100M + - ARCH_FLAGS_x86='-m32' # #266: don't use SSE on 32-bit + - ARCH_FLAGS_x86_64='-msse4.2' # use SSE4.2 on 64-bit + - ARCH_FLAGS_aarch64='-march=armv8-a' + - GITHUB_REPO='Tencent/rapidjson' + - secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk=" + +matrix: + include: + # gcc + - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=OFF + compiler: gcc + arch: amd64 + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF + compiler: gcc + arch: amd64 + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON + compiler: gcc + arch: amd64 + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF + compiler: gcc + arch: amd64 + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF + compiler: gcc + arch: amd64 + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' + compiler: gcc + arch: amd64 + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=ON CXX_FLAGS='-D_GLIBCXX_DEBUG' + compiler: gcc + arch: amd64 + - env: CONF=release ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF + compiler: gcc + arch: arm64 + - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=OFF + compiler: gcc + arch: arm64 + - env: CONF=release ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=ON + compiler: gcc + arch: arm64 + # clang + - env: CONF=release ARCH=x86 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + compiler: clang + arch: amd64 + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + compiler: clang + arch: amd64 + - env: CONF=release ARCH=x86_64 CXX11=ON CXX17=OFF MEMBERSMAP=OFF CCACHE_CPP2=yes + compiler: clang + arch: amd64 + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + compiler: clang + arch: amd64 + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + compiler: clang + arch: amd64 + - env: CONF=debug ARCH=x86 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes + compiler: clang + arch: amd64 + - env: CONF=debug ARCH=x86_64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes + compiler: clang + arch: amd64 + - env: CONF=debug ARCH=aarch64 CXX11=ON CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + compiler: clang + arch: arm64 + - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=OFF MEMBERSMAP=ON CCACHE_CPP2=yes + compiler: clang + arch: arm64 + - env: CONF=debug ARCH=aarch64 CXX11=OFF CXX17=ON MEMBERSMAP=OFF CCACHE_CPP2=yes + compiler: clang + arch: arm64 + # coverage report + - env: CONF=debug ARCH=x86 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=OFF + compiler: gcc + arch: amd64 + cache: + - ccache + - pip + after_success: + - pip install --user cpp-coveralls + - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h + - env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=ON CXX17=OFF MEMBERSMAP=ON + compiler: gcc + arch: amd64 + cache: + - ccache + - pip + after_success: + - pip install --user cpp-coveralls + - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h + - env: CONF=debug ARCH=aarch64 GCOV_FLAGS='--coverage' CXX_FLAGS='-O0' CXX11=OFF CXX17=ON + compiler: gcc + arch: arm64 + cache: + - ccache + - pip + after_success: + - pip install --user cpp-coveralls + - coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h + - script: # Documentation task + - cd build + - cmake .. -DRAPIDJSON_HAS_STDSTRING=ON -DCMAKE_VERBOSE_MAKEFILE=ON + - make travis_doc + cache: false + addons: + apt: + packages: + - doxygen + +before_install: + - if [ "x86_64" = "$(arch)" ]; then sudo apt-get install -y g++-multilib libc6-dbg:i386 --allow-unauthenticated; fi + +before_script: + # travis provides clang-7 for amd64 and clang-3.8 for arm64 + # here use clang-8 to all architectures as clang-7 is not available for arm64 + - if [ -f /usr/bin/clang++-8 ]; then + sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 1000; + sudo update-alternatives --config clang++; + export PATH=/usr/bin:$PATH; + fi + - if [ "$CXX" = "clang++" ]; then export CCACHE_CPP2=yes; fi + - ccache -s + # hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469), + # exposed by merging PR#163 (using -march=native) + # TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded. + - sed -i "s/-march=native//" CMakeLists.txt + - mkdir build + +script: + - if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-stdlib=libc++ ${CXXFLAGS}"; fi + - > + eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ; + (cd build && cmake + -DRAPIDJSON_HAS_STDSTRING=ON + -DRAPIDJSON_USE_MEMBERSMAP=$MEMBERSMAP + -DRAPIDJSON_BUILD_CXX11=$CXX11 + -DRAPIDJSON_BUILD_CXX17=$CXX17 + -DCMAKE_VERBOSE_MAKEFILE=ON + -DCMAKE_BUILD_TYPE=$CONF + -DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS $CXX_FLAGS" + -DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS + ..) + - cd build + - make tests -j 2 + - make examples -j 2 + - ctest -j 2 -V `[ "$CONF" = "release" ] || echo "-E perftest"` diff --git a/deps/rapidjson/CHANGELOG.md b/deps/rapidjson/CHANGELOG.md new file mode 100644 index 0000000..1c580bd --- /dev/null +++ b/deps/rapidjson/CHANGELOG.md @@ -0,0 +1,158 @@ +# Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## 1.1.0 - 2016-08-25 + +### Added +* Add GenericDocument ctor overload to specify JSON type (#369) +* Add FAQ (#372, #373, #374, #376) +* Add forward declaration header `fwd.h` +* Add @PlatformIO Library Registry manifest file (#400) +* Implement assignment operator for BigInteger (#404) +* Add comments support (#443) +* Adding coapp definition (#460) +* documenttest.cpp: EXPECT_THROW when checking empty allocator (470) +* GenericDocument: add implicit conversion to ParseResult (#480) +* Use with C++ linkage on Windows ARM (#485) +* Detect little endian for Microsoft ARM targets +* Check Nan/Inf when writing a double (#510) +* Add JSON Schema Implementation (#522) +* Add iostream wrapper (#530) +* Add Jsonx example for converting JSON into JSONx (a XML format) (#531) +* Add optional unresolvedTokenIndex parameter to Pointer::Get() (#532) +* Add encoding validation option for Writer/PrettyWriter (#534) +* Add Writer::SetMaxDecimalPlaces() (#536) +* Support {0, } and {0, m} in Regex (#539) +* Add Value::Get/SetFloat(), Value::IsLossLessFloat/Double() (#540) +* Add stream position check to reader unit tests (#541) +* Add Templated accessors and range-based for (#542) +* Add (Pretty)Writer::RawValue() (#543) +* Add Document::Parse(std::string), Document::Parse(const char*, size_t length) and related APIs. (#553) +* Add move constructor for GenericSchemaDocument (#554) +* Add VS2010 and VS2015 to AppVeyor CI (#555) +* Add parse-by-parts example (#556, #562) +* Support parse number as string (#564, #589) +* Add kFormatSingleLineArray for PrettyWriter (#577) +* Added optional support for trailing commas (#584) +* Added filterkey and filterkeydom examples (#615) +* Added npm docs (#639) +* Allow options for writing and parsing NaN/Infinity (#641) +* Add std::string overload to PrettyWriter::Key() when RAPIDJSON_HAS_STDSTRING is defined (#698) + +### Fixed +* Fix gcc/clang/vc warnings (#350, #394, #397, #444, #447, #473, #515, #582, #589, #595, #667) +* Fix documentation (#482, #511, #550, #557, #614, #635, #660) +* Fix emscripten alignment issue (#535) +* Fix missing allocator to uses of AddMember in document (#365) +* CMake will no longer complain that the minimum CMake version is not specified (#501) +* Make it usable with old VC8 (VS2005) (#383) +* Prohibit C++11 move from Document to Value (#391) +* Try to fix incorrect 64-bit alignment (#419) +* Check return of fwrite to avoid warn_unused_result build failures (#421) +* Fix UB in GenericDocument::ParseStream (#426) +* Keep Document value unchanged on parse error (#439) +* Add missing return statement (#450) +* Fix Document::Parse(const Ch*) for transcoding (#478) +* encodings.h: fix typo in preprocessor condition (#495) +* Custom Microsoft headers are necessary only for Visual Studio 2012 and lower (#559) +* Fix memory leak for invalid regex (26e69ffde95ba4773ab06db6457b78f308716f4b) +* Fix a bug in schema minimum/maximum keywords for 64-bit integer (e7149d665941068ccf8c565e77495521331cf390) +* Fix a crash bug in regex (#605) +* Fix schema "required" keyword cannot handle duplicated keys (#609) +* Fix cmake CMP0054 warning (#612) +* Added missing include guards in istreamwrapper.h and ostreamwrapper.h (#634) +* Fix undefined behaviour (#646) +* Fix buffer overrun using PutN (#673) +* Fix rapidjson::value::Get() may returns wrong data (#681) +* Add Flush() for all value types (#689) +* Handle malloc() fail in PoolAllocator (#691) +* Fix builds on x32 platform. #703 + +### Changed +* Clarify problematic JSON license (#392) +* Move Travis to container based infrastructure (#504, #558) +* Make whitespace array more compact (#513) +* Optimize Writer::WriteString() with SIMD (#544) +* x86-64 48-bit pointer optimization for GenericValue (#546) +* Define RAPIDJSON_HAS_CXX11_RVALUE_REFS directly in clang (#617) +* Make GenericSchemaDocument constructor explicit (#674) +* Optimize FindMember when use std::string (#690) + +## [1.0.2] - 2015-05-14 + +### Added +* Add Value::XXXMember(...) overloads for std::string (#335) + +### Fixed +* Include rapidjson.h for all internal/error headers. +* Parsing some numbers incorrectly in full-precision mode (`kFullPrecisionParseFlag`) (#342) +* Fix some numbers parsed incorrectly (#336) +* Fix alignment of 64bit platforms (#328) +* Fix MemoryPoolAllocator::Clear() to clear user-buffer (0691502573f1afd3341073dd24b12c3db20fbde4) + +### Changed +* CMakeLists for include as a thirdparty in projects (#334, #337) +* Change Document::ParseStream() to use stack allocator for Reader (ffbe38614732af8e0b3abdc8b50071f386a4a685) + +## [1.0.1] - 2015-04-25 + +### Added +* Changelog following [Keep a CHANGELOG](https://github.com/olivierlacan/keep-a-changelog) suggestions. + +### Fixed +* Parsing of some numbers (e.g. "1e-00011111111111") causing assertion (#314). +* Visual C++ 32-bit compilation error in `diyfp.h` (#317). + +## [1.0.0] - 2015-04-22 + +### Added +* 100% [Coverall](https://coveralls.io/r/Tencent/rapidjson?branch=master) coverage. +* Version macros (#311) + +### Fixed +* A bug in trimming long number sequence (4824f12efbf01af72b8cb6fc96fae7b097b73015). +* Double quote in unicode escape (#288). +* Negative zero roundtrip (double only) (#289). +* Standardize behavior of `memcpy()` and `malloc()` (0c5c1538dcfc7f160e5a4aa208ddf092c787be5a, #305, 0e8bbe5e3ef375e7f052f556878be0bd79e9062d). + +### Removed +* Remove an invalid `Document::ParseInsitu()` API (e7f1c6dd08b522cfcf9aed58a333bd9a0c0ccbeb). + +## 1.0-beta - 2015-04-8 + +### Added +* RFC 7159 (#101) +* Optional Iterative Parser (#76) +* Deep-copy values (#20) +* Error code and message (#27) +* ASCII Encoding (#70) +* `kParseStopWhenDoneFlag` (#83) +* `kParseFullPrecisionFlag` (881c91d696f06b7f302af6d04ec14dd08db66ceb) +* Add `Key()` to handler concept (#134) +* C++11 compatibility and support (#128) +* Optimized number-to-string and vice versa conversions (#137, #80) +* Short-String Optimization (#131) +* Local stream optimization by traits (#32) +* Travis & Appveyor Continuous Integration, with Valgrind verification (#24, #242) +* Redo all documentation (English, Simplified Chinese) + +### Changed +* Copyright ownership transferred to THL A29 Limited (a Tencent company). +* Migrating from Premake to CMAKE (#192) +* Resolve all warning reports + +### Removed +* Remove other JSON libraries for performance comparison (#180) + +## 0.11 - 2012-11-16 + +## 0.1 - 2011-11-18 + +[Unreleased]: https://github.com/Tencent/rapidjson/compare/v1.1.0...HEAD +[1.1.0]: https://github.com/Tencent/rapidjson/compare/v1.0.2...v1.1.0 +[1.0.2]: https://github.com/Tencent/rapidjson/compare/v1.0.1...v1.0.2 +[1.0.1]: https://github.com/Tencent/rapidjson/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/Tencent/rapidjson/compare/v1.0-beta...v1.0.0 diff --git a/deps/rapidjson/CMakeLists.txt b/deps/rapidjson/CMakeLists.txt new file mode 100644 index 0000000..dd1f173 --- /dev/null +++ b/deps/rapidjson/CMakeLists.txt @@ -0,0 +1,251 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +if(POLICY CMP0025) + # detect Apple's Clang + cmake_policy(SET CMP0025 NEW) +endif() +if(POLICY CMP0054) + cmake_policy(SET CMP0054 NEW) +endif() + +SET(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules) + +set(LIB_MAJOR_VERSION "1") +set(LIB_MINOR_VERSION "1") +set(LIB_PATCH_VERSION "0") +set(LIB_VERSION_STRING "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_PATCH_VERSION}") + +if (CMAKE_VERSION VERSION_LESS 3.0) + PROJECT(RapidJSON CXX) +else() + cmake_policy(SET CMP0048 NEW) + PROJECT(RapidJSON VERSION "${LIB_VERSION_STRING}" LANGUAGES CXX) +endif() + +# compile in release with debug info mode by default +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) +endif() + +# Build all binaries in a separate directory +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +option(RAPIDJSON_BUILD_DOC "Build rapidjson documentation." ON) +option(RAPIDJSON_BUILD_EXAMPLES "Build rapidjson examples." ON) +option(RAPIDJSON_BUILD_TESTS "Build rapidjson perftests and unittests." ON) +option(RAPIDJSON_BUILD_THIRDPARTY_GTEST + "Use gtest installation in `thirdparty/gtest` by default if available" OFF) + +option(RAPIDJSON_BUILD_CXX11 "Build rapidjson with C++11" ON) +option(RAPIDJSON_BUILD_CXX17 "Build rapidjson with C++17" OFF) +if(RAPIDJSON_BUILD_CXX11) + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED TRUE) +endif() + +option(RAPIDJSON_BUILD_ASAN "Build rapidjson with address sanitizer (gcc/clang)" OFF) +option(RAPIDJSON_BUILD_UBSAN "Build rapidjson with undefined behavior sanitizer (gcc/clang)" OFF) + +option(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT "Build rapidjson with -march or -mcpu options" ON) + +option(RAPIDJSON_HAS_STDSTRING "" OFF) +if(RAPIDJSON_HAS_STDSTRING) + add_definitions(-DRAPIDJSON_HAS_STDSTRING) +endif() + +option(RAPIDJSON_USE_MEMBERSMAP "" OFF) +if(RAPIDJSON_USE_MEMBERSMAP) + add_definitions(-DRAPIDJSON_USE_MEMBERSMAP=1) +endif() + +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics") + endif() +endif(CCACHE_FOUND) + +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(RAPIDJSON_ENABLE_INSTRUMENTATION_OPT AND NOT CMAKE_CROSSCOMPILING) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native") + else() + #FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + endif() + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") + set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wsign-conversion) + if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + endif() + if (RAPIDJSON_BUILD_ASAN) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.0") + message(FATAL_ERROR "GCC < 4.8 doesn't support the address sanitizer") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + endif() + endif() + if (RAPIDJSON_BUILD_UBSAN) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9.0") + message(FATAL_ERROR "GCC < 4.9 doesn't support the undefined behavior sanitizer") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") + endif() + endif() +elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(NOT CMAKE_CROSSCOMPILING) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "powerpc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=native") + else() + #FIXME: x86 is -march=native, but doesn't mean every arch is this option. To keep original project's compatibility, I leave this except POWER. + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native") + endif() + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -Wno-missing-field-initializers") + set(EXTRA_CXX_FLAGS -Weffc++ -Wswitch-default -Wfloat-equal -Wconversion -Wimplicit-fallthrough) + if (RAPIDJSON_BUILD_CXX11 AND CMAKE_VERSION VERSION_LESS 3.1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.0") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + endif() + if (RAPIDJSON_BUILD_ASAN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + endif() + if (RAPIDJSON_BUILD_UBSAN) + if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined") + endif() + endif() +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) + add_definitions(-DNOMINMAX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") + # CMake >= 3.10 should handle the above CMAKE_CXX_STANDARD fine, otherwise use /std:c++XX with MSVC >= 19.10 + if (RAPIDJSON_BUILD_CXX11 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.10") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++11") + elseif (RAPIDJSON_BUILD_CXX17 AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.14") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17") + endif() + # Always compile with /WX + if(CMAKE_CXX_FLAGS MATCHES "/WX-") + string(REGEX REPLACE "/WX-" "/WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") + endif() +elseif (CMAKE_CXX_COMPILER_ID MATCHES "XL") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -qarch=auto") +endif() + +#add extra search paths for libraries and includes +SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "The directory the headers are installed in") +SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE STRING "Directory where lib will install") +SET(DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}" CACHE PATH "Path to the documentation") + +IF(UNIX OR CYGWIN) + SET(_CMAKE_INSTALL_DIR "${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME}") +ELSEIF(WIN32) + SET(_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/cmake") +ENDIF() +SET(CMAKE_INSTALL_DIR "${_CMAKE_INSTALL_DIR}" CACHE PATH "The directory cmake files are installed in") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +if(RAPIDJSON_BUILD_DOC) + add_subdirectory(doc) +endif() + +add_custom_target(travis_doc) +add_custom_command(TARGET travis_doc + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/travis-doxygen.sh) + +if(RAPIDJSON_BUILD_EXAMPLES) + add_subdirectory(example) +endif() + +if(RAPIDJSON_BUILD_TESTS) + if(MSVC11) + # required for VS2012 due to missing support for variadic templates + add_definitions(-D_VARIADIC_MAX=10) + endif(MSVC11) + add_subdirectory(test) + include(CTest) +endif() + +# pkg-config +IF (UNIX OR CYGWIN) + CONFIGURE_FILE (${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY) + INSTALL (FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION "${LIB_INSTALL_DIR}/pkgconfig" + COMPONENT pkgconfig) +ENDIF() + +install(FILES readme.md + DESTINATION "${DOC_INSTALL_DIR}" + COMPONENT doc) + +install(DIRECTORY include/rapidjson + DESTINATION "${INCLUDE_INSTALL_DIR}" + COMPONENT dev) + +install(DIRECTORY example/ + DESTINATION "${DOC_INSTALL_DIR}/examples" + COMPONENT examples + # Following patterns are for excluding the intermediate/object files + # from an install of in-source CMake build. + PATTERN "CMakeFiles" EXCLUDE + PATTERN "Makefile" EXCLUDE + PATTERN "cmake_install.cmake" EXCLUDE) + +# Provide config and version files to be used by other applications +# =============================== + +################################################################################ +# Export package for use from the build tree +EXPORT( PACKAGE ${PROJECT_NAME} ) + +# Create the RapidJSONConfig.cmake file for other cmake projects. +# ... for the build tree +SET( CONFIG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +SET( CONFIG_DIR ${CMAKE_CURRENT_BINARY_DIR}) +SET( ${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_SOURCE_DIR}/include" ) + +CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY ) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}ConfigVersion.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake @ONLY) + +# ... for the install tree +SET( CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/${PROJECT_NAME} ) +FILE( RELATIVE_PATH REL_INCLUDE_DIR + "${CMAKECONFIG_INSTALL_DIR}" + "${CMAKE_INSTALL_PREFIX}/include" ) + +SET( ${PROJECT_NAME}_INCLUDE_DIR "\${${PROJECT_NAME}_CMAKE_DIR}/${REL_INCLUDE_DIR}" ) +SET( CONFIG_SOURCE_DIR ) +SET( CONFIG_DIR ) +CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake @ONLY ) + +INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${PROJECT_NAME}Config.cmake" + DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) + +# Install files +IF(CMAKE_INSTALL_DIR) + INSTALL(FILES + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION "${CMAKE_INSTALL_DIR}" + COMPONENT dev) +ENDIF() diff --git a/deps/rapidjson/CMakeModules/FindGTestSrc.cmake b/deps/rapidjson/CMakeModules/FindGTestSrc.cmake new file mode 100644 index 0000000..f3cb8c9 --- /dev/null +++ b/deps/rapidjson/CMakeModules/FindGTestSrc.cmake @@ -0,0 +1,30 @@ + +SET(GTEST_SEARCH_PATH + "${GTEST_SOURCE_DIR}" + "${CMAKE_CURRENT_LIST_DIR}/../thirdparty/gtest/googletest") + +IF(UNIX) + IF(RAPIDJSON_BUILD_THIRDPARTY_GTEST) + LIST(APPEND GTEST_SEARCH_PATH "/usr/src/gtest") + ELSE() + LIST(INSERT GTEST_SEARCH_PATH 1 "/usr/src/gtest") + ENDIF() +ENDIF() + +FIND_PATH(GTEST_SOURCE_DIR + NAMES CMakeLists.txt src/gtest_main.cc + PATHS ${GTEST_SEARCH_PATH}) + + +# Debian installs gtest include directory in /usr/include, thus need to look +# for include directory separately from source directory. +FIND_PATH(GTEST_INCLUDE_DIR + NAMES gtest/gtest.h + PATH_SUFFIXES include + HINTS ${GTEST_SOURCE_DIR} + PATHS ${GTEST_SEARCH_PATH}) + +INCLUDE(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GTestSrc DEFAULT_MSG + GTEST_SOURCE_DIR + GTEST_INCLUDE_DIR) diff --git a/deps/rapidjson/RapidJSON.pc.in b/deps/rapidjson/RapidJSON.pc.in new file mode 100644 index 0000000..6afb079 --- /dev/null +++ b/deps/rapidjson/RapidJSON.pc.in @@ -0,0 +1,7 @@ +includedir=@INCLUDE_INSTALL_DIR@ + +Name: @PROJECT_NAME@ +Description: A fast JSON parser/generator for C++ with both SAX/DOM style API +Version: @LIB_VERSION_STRING@ +URL: https://github.com/Tencent/rapidjson +Cflags: -I${includedir} diff --git a/deps/rapidjson/RapidJSONConfig.cmake.in b/deps/rapidjson/RapidJSONConfig.cmake.in new file mode 100644 index 0000000..c25d312 --- /dev/null +++ b/deps/rapidjson/RapidJSONConfig.cmake.in @@ -0,0 +1,25 @@ +################################################################################ +# CMake minimum version required +cmake_minimum_required(VERSION 3.0) + +################################################################################ +# RapidJSON source dir +set( RapidJSON_SOURCE_DIR "@CONFIG_SOURCE_DIR@") + +################################################################################ +# RapidJSON build dir +set( RapidJSON_DIR "@CONFIG_DIR@") + +################################################################################ +# Compute paths +get_filename_component(RapidJSON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +set( RapidJSON_INCLUDE_DIR "@RapidJSON_INCLUDE_DIR@" ) +set( RapidJSON_INCLUDE_DIRS "@RapidJSON_INCLUDE_DIR@" ) +message(STATUS "RapidJSON found. Headers: ${RapidJSON_INCLUDE_DIRS}") + +if(NOT TARGET rapidjson) + add_library(rapidjson INTERFACE IMPORTED) + set_property(TARGET rapidjson PROPERTY + INTERFACE_INCLUDE_DIRECTORIES ${RapidJSON_INCLUDE_DIRS}) +endif() diff --git a/deps/rapidjson/RapidJSONConfigVersion.cmake.in b/deps/rapidjson/RapidJSONConfigVersion.cmake.in new file mode 100644 index 0000000..25741fc --- /dev/null +++ b/deps/rapidjson/RapidJSONConfigVersion.cmake.in @@ -0,0 +1,10 @@ +SET(PACKAGE_VERSION "@LIB_VERSION_STRING@") + +IF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) + SET(PACKAGE_VERSION_EXACT "true") +ENDIF (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) +IF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + SET(PACKAGE_VERSION_COMPATIBLE "true") +ELSE (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) + SET(PACKAGE_VERSION_UNSUITABLE "true") +ENDIF (NOT PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION) diff --git a/deps/rapidjson/appveyor.yml b/deps/rapidjson/appveyor.yml new file mode 100644 index 0000000..4044ba6 --- /dev/null +++ b/deps/rapidjson/appveyor.yml @@ -0,0 +1,102 @@ +version: 1.1.0.{build} + +configuration: +- Debug +- Release + +environment: + matrix: + # - VS_VERSION: 9 2008 + # VS_PLATFORM: win32 + # - VS_VERSION: 9 2008 + # VS_PLATFORM: x64 + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 10 2010 + VS_PLATFORM: win32 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: OFF + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 10 2010 + VS_PLATFORM: x64 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: ON + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 11 2012 + VS_PLATFORM: win32 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: ON + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 11 2012 + VS_PLATFORM: x64 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: OFF + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 12 2013 + VS_PLATFORM: win32 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: OFF + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + VS_VERSION: 12 2013 + VS_PLATFORM: x64 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: ON + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + VS_VERSION: 14 2015 + VS_PLATFORM: win32 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: ON + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + VS_VERSION: 14 2015 + VS_PLATFORM: x64 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: OFF + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VS_VERSION: 15 2017 + VS_PLATFORM: win32 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: OFF + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VS_VERSION: 15 2017 + VS_PLATFORM: x64 + CXX11: OFF + CXX17: OFF + MEMBERSMAP: ON + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VS_VERSION: 15 2017 + VS_PLATFORM: x64 + CXX11: ON + CXX17: OFF + MEMBERSMAP: OFF + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + VS_VERSION: 15 2017 + VS_PLATFORM: x64 + CXX11: OFF + CXX17: ON + MEMBERSMAP: OFF + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + VS_VERSION: 16 2019 + VS_PLATFORM: x64 + CXX11: OFF + CXX17: ON + MEMBERSMAP: ON + +before_build: +- git submodule update --init --recursive +- cmake -H. -BBuild/VS -G "Visual Studio %VS_VERSION%" -DCMAKE_GENERATOR_PLATFORM=%VS_PLATFORM% -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=true -DRAPIDJSON_BUILD_CXX11=%CXX11% -DRAPIDJSON_BUILD_CXX17=%CXX17% -DRAPIDJSON_USE_MEMBERSMAP=%MEMBERSMAP% -Wno-dev + +build: + project: Build\VS\RapidJSON.sln + parallel: true + verbosity: minimal + +test_script: +- cd Build\VS && if %CONFIGURATION%==Debug (ctest --verbose -E perftest --build-config %CONFIGURATION%) else (ctest --verbose --build-config %CONFIGURATION%) diff --git a/deps/rapidjson/bin/data/abcde.txt b/deps/rapidjson/bin/data/abcde.txt new file mode 100644 index 0000000..6a81654 --- /dev/null +++ b/deps/rapidjson/bin/data/abcde.txt @@ -0,0 +1 @@ +abcde \ No newline at end of file diff --git a/deps/rapidjson/bin/data/glossary.json b/deps/rapidjson/bin/data/glossary.json new file mode 100644 index 0000000000000000000000000000000000000000..d6e6ca150773702f40bd64ec2611bf0d4456f62b GIT binary patch literal 603 zcmZWmO>cuR3_Z6}|AUotH))rR_Qu47DpBpg4wI%GT<{obASembx{Ck4d_XBB7bnkt z&oB0QwFGlm!G%&NPizZk4>?$unv=m8{bJQ{f=k_cwOlM%Y-v&XGo?+bDRZ@baZ)Nh zuXYS4_EPIx7dAN@wu`KtG~Oq@tZ|VFsY5l#o!}eE%B3{cIm#Sjs!1X*|0st&%46F= zf_2eiL8D}tNl~9XandV193}g*e_{4D@qOi9)V~Y4O3_2Y|hsnSGAS c9jw^c`4tTtHDv3}H)V55H-)aA{ndo-AEuR#9{>OV literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/data/menu.json b/deps/rapidjson/bin/data/menu.json new file mode 100644 index 0000000000000000000000000000000000000000..539c3af2013cb8e0a6e6ddc989f6116bbfa99106 GIT binary patch literal 898 zcmaizO=`n15QX=F++ol<_yFCRKz|mkTLM|MbRpM6Dv%{(TMfnd?$uaP@i=npoxb

&|O$VNHQSsEXW0gGP)O<5GCS zv)F;qvP2!tKyV%~PU}Se)!O>Ous9*`Y@UvNkXE?<+D|YQC|Y$=Mr!(1mWsl32rRnN z>5G$E_20}I+j^F+!=&=)dM>O~zg4DU{SnBrELoJa{3I1WH=+=5>Lm8INjFczbv2^@ zRP$GewLC=#rnaX6ECa;g&wzF92eM52@8^BH8OI-K%Hb9O literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/data/readme.txt b/deps/rapidjson/bin/data/readme.txt new file mode 100644 index 0000000..c53bfb8 --- /dev/null +++ b/deps/rapidjson/bin/data/readme.txt @@ -0,0 +1 @@ +sample.json is obtained from http://code.google.com/p/json-test-suite/downloads/detail?name=sample.zip diff --git a/deps/rapidjson/bin/data/sample.json b/deps/rapidjson/bin/data/sample.json new file mode 100644 index 0000000000000000000000000000000000000000..30930e765dc6e4c110e186a72cb423cf70bc3b2e GIT binary patch literal 687491 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�)AoC+O$!4~857g&7Se*8A$ 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

sgsp<)aT>Kd5}qVRSSx+#$1$k3wF=v6E~ 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

  • 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 F`7dEe6Al0X literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/data/webapp.json b/deps/rapidjson/bin/data/webapp.json new file mode 100644 index 0000000000000000000000000000000000000000..ee7b0f8bab2f64a97dcaee0abc5cb22fe9b6d91a GIT binary patch literal 3554 zcma)9QE%He5Pl!9{~+jL1%_Hm+GY<9f-SX^)`e!fk%K-Ad!QvsW7cl7tiw*m5-ci`2NT9JY4cB3I4ItK}iY< z5I+$ac^-{p|80eAK@v`sLX41kU~oZ_ssO-o?V{0PCDVg7k)*IZ&>I*_M47St6BkMm zxgD}nX~H?tOqAEi(VwpvCn@FY6(euG`E^6&P@AL$D{l(IIBGtq;;*$>if15K98+71 zCn{#AV0TN>=fkZw~<0O&^yz7EQ~?ArpfbGpVoj6eif7dZ{RfWA`*z zxO#)XZ!Y_dL?XxhLcifg$&ibL@KB2)AsRk%6(Svlw?F`&{YECxLPw%3vE_CP!R_U5 zXw?qUsTBu7`MrYDi&(+1!S0o&0|MuWK2j5@lrA@2Rt0&6C`Po*O(VNFJKOE*n3yTU z^mfb%m^8YxMAe>M{M^9t!Zcyvm{K^hG+O=hgpaNNvruMm!2jnh6)Uri3ZsE*@BCA# zU*mYuvS|1B0(Aqo)XnL>nmGuwH;sTQAeXsyQsqE7y*kp51Ht!R!b3730`U#s29qnVRleAU=zwAX8)P8>$t-l zhxFceSuda9wniTKtk+-iD`_DfVLZs`2JQe{-$3J!B(|6#)$0-g{!;#T8ok6t%;;$c$4Rio*%xntTwv(ryf zY}S)8c>B3=tqZm|(P*h|Q~ z*OzZz&pMS$;n)@Q%LVw4mhNjdlFaryls-q$E8rRBtSnOafS&?Ra{bJ52FyCu}wx$_oUhN zuEkZ2a@r&Uu`O;Qp?oR|8_GD_Mhx$N30y0Ql|bTSnLkCten2|$F{?KK$F@_W^TepG{o$Z~M$C3_hCHiszc}slSz}d8XVR XZr~`oufazj!wFm_*Hb0S#V~vUEoqfp literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/encodings/utf16be.json b/deps/rapidjson/bin/encodings/utf16be.json new file mode 100644 index 0000000000000000000000000000000000000000..e46dbfb9ddc489f4e26450bd86626a3a55235533 GIT binary patch literal 368 zcmZRmX5eMuV&G&@Vn}7k1Cmxi?8%_Okj#(>gf%3?5(;N+7l+2{!x4;thftTA|Lu+w1DjQa+a2Au{y z26YCJ222LAKvq6bep0}8gA{{6plGzgWHfWKfqn#=vth=jDGUn76?U%KS;L^P%ksDj tgTf&Rph(BjEytz+eXFqc$MzYUk1!}4b-BuN@&J(bI_d(HQ38iSEdbokSsefX literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/encodings/utf16bebom.json b/deps/rapidjson/bin/encodings/utf16bebom.json new file mode 100644 index 0000000000000000000000000000000000000000..0a23ae205cb3354e828cd3c0f3fce322b9618815 GIT binary patch literal 370 zcmezOpP`z8mw}6clR=3gl_3vES^=>qg91Y`Ln4r`02EDRC;`&x3^_nnF%T+%Wm152 zCRiqgAs?u!7^qqu%+FvbWher(a)IJ{K=X9qc2qHBFz7OPfK4cY*p?*N@Ha%xkGptx zNpk~_A8)|+zSXm?7%<_~SBzbsze?X~|6nwISwNe>eyTiZkZ-WY;HAM%gGn>)8&n!} z8uS>{8AKW|8N>ov`9S$e0ox5y3<80o(FT*z%*h7&5p2$e8JngsC>&SVxn^e#gTgM$ v<1P#eha`X^9Y?nun*#K$!rC9(XKX&gpm5aXD$B_OK-%l53s6Q090s)jyQo_l literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/encodings/utf16le.json b/deps/rapidjson/bin/encodings/utf16le.json new file mode 100644 index 0000000000000000000000000000000000000000..92d504530cda3c0f6c775907f544e5b60fb9dcf8 GIT binary patch literal 368 zcmbSxg4F^cCaKr{cf5FW4VdUl!0Nh@TEt<{PXrcxkZHV3NW88I=Z|20aFK z29X9#2C+a^zQMuDNe0^kQVartqR|GEf#S&aX9N8RF=xhxDVr1+6ppXiS+i4t!E%?& xaRmm6LkbKX$G04va!d~xDnHiF*nVWQ0)xv@ma7L&Dlm8*bpgsKfy1Dd0RZ`SSsefX literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/encodings/utf16lebom.json b/deps/rapidjson/bin/encodings/utf16lebom.json new file mode 100644 index 0000000000000000000000000000000000000000..eaba00132cdfbc222ddce1333d0268821d68db0d GIT binary patch literal 370 zcmezWubP3Efs28YL5U%iArDAe0kJ280z)!GB9N~D6is9(0n+IVIY3r15GsIWQh;Grs9GJ&&tNEJC<3!`f#P~V^K{^LR54^Q=rVYKO(=odCYbcMK`w;bZ+CHX z2~PvB-}ZpjeOG2N8Q{`aj6a&*cuJz%K(SUY3;k~;6rk2xc0Q&JsNLlrc^6f7n8&gAUj3}6Drz~2LKuH!Wb zU>X*{+G;|O#P&>r<5?(rtSy6U+2gzxD1M*ez78uT+9G%7w}WSHh2MK@pxN67-QbyA z+jZ?pb{nskcE6>eMyaoc5$;LZL#rjGW`9;XI+xDgq_86KmebEWmC-NN9QR8N{?l)c zy56azcKQ(yzh!s zTJ0ZbEYF#HCz&Y76i>eIJ@-BDGT%sF-;&m$1}dQf8ejqz;(L31c5wzU1|#6_0XWz3 z3Is3-b6{;bCWvEu#=-G46g<`z!L{shUK13)PjO#`r6O&fyYpMYGdIKUJ=W0dZGlek zOs?&^_Qbo5)=Jx-(m=h`Q^g3kr0k$o6H~J{EghUnCofW17JEzS=bcLEmuQUoCHnvA zH$z?TR8%{8kB8qfJcD=0z@e0S<4nRH?86oe0{eu+U=3g1Pri2!d6%#coI3MtL=>AX_ow;2pdo4ZLhWc;i-Xenk@RsURdrTA&o@;vuVo;bH;gPdZ;rmcDc$?A zz_(<_3;2c-9K%;A6_5vT2s@Ai_a6iMT<3b{`{q1y2%I|#Cs1ymd3NzTruPZ2q|@u@ z&4V}gDoI-qkk@r5W${^We2U~g_U#KbuhH8&_H!wPMd|q_%E=P1{*)fxBfAgVKG%45 J@*ixY{{az1SsefX literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/encodings/utf32lebom.json b/deps/rapidjson/bin/encodings/utf32lebom.json new file mode 100644 index 0000000000000000000000000000000000000000..d3db39bf732c7055cb6053c23947c89d6859b2e9 GIT binary patch literal 740 zcmb7?yDNop9EU&2;&KL?NpDgXWMw`B2A5bQ1CHD&m*KdjER@cG;myB*66$nVkV|%E zv;V;2@_c&Vw@!vrXL$PFZ}0E@{gE~#rJx$Bpb;ivG1fa{*^LZf0>;4c0Gw-k6#|%o zd9ZIKCWvjrdPUUiCvOv@ujfy{nBYpdOMLS+RLBko64Ej)ECVgM3$O2OJCnq z-1|Puw`9jN_=Ex+!bd1&k^67}+b|67KMMA_&h^gs%^BnXIClh&pwvEd?BaJU-Y2|} zjxVD(4_?@-AZ>h0U MT;tivf3SuA2hZtS8UO$Q literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/encodings/utf8.json b/deps/rapidjson/bin/encodings/utf8.json new file mode 100644 index 0000000000000000000000000000000000000000..c500c943f6b1f2d9008077bfcff8e6b818c40867 GIT binary patch literal 322 zcmaKmOHRU27=_1@u!ldLI1v`$3UnDa(txj$*gDae^xk$*5g*iQ>Vs+`hz1fSCKLrX z^A}sZ*FE^dKpidJS8K5%@%3I7dff*%Ox1dzjO=Ho5%I=N@ z+j>!3nh|@I!U{7i!alr4=8Pw2Q4$}eCvU0mWOhA?k0)Y~y>_SF0B!M?G5=wbQHz*l zeE!31Fsi2=j=Ybeht4yKAqs!`aEF}4A&NTkcjQ+@AaBlXf7Ta19YEef-k29|Q2efL zR%um=P}TxaxA*d~C)*>CPeavoL3tsl$Wxau>N+UG=OC6*C{HQ4aK8dqb!<{KG8Ak1 G+`%^sldGBl literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/encodings/utf8bom.json b/deps/rapidjson/bin/encodings/utf8bom.json new file mode 100644 index 0000000000000000000000000000000000000000..b9839fe2fa7d1b34749a999f8228f2a508a4bf81 GIT binary patch literal 325 zcmaKmOHRU27=_1@u!ldLI8heh3UnDa(ul8;*gDae^xk$*5g*iQ>Vs+`iUtxUCKLf( z%wKHrUgH-0VW5tjos)CElk?So+s)@@G~Lh^v?W+(2I$O!l?`T^z>FfST2L(OrZHkk_ZSGwBPT4j^wJuT2YA zD1KMh%d{#*C@TS|>s$HImiGgYk3Cg)L3tsl$W!Of>M|(6M>m#HD32*Pb3X%DHEmKA KG8Ak1+}<}B*RBHq literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail1.json b/deps/rapidjson/bin/jsonchecker/fail1.json new file mode 100644 index 0000000000000000000000000000000000000000..6216b865f10219c51c6af21e7a68641bab77ee4f GIT binary patch literal 60 zcmY##RPYM+_fsfHtjx(zOi?J#$S=)FQAkQvNX%2nPs&P7E>XxYQb;T+O03jT$jdKL PNK_~;Day=C*HZ!jV15)y literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail10.json b/deps/rapidjson/bin/jsonchecker/fail10.json new file mode 100644 index 0000000000000000000000000000000000000000..5d8c0047bd522dfa9fbc642051ed76bd3162d936 GIT binary patch literal 58 zcmbnII%qdM(NK7k9EmBC%$uCY-vQj81Dow3bP|D3LF33qtPEAoLEX^+g IQed@80BSK61poj5 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail11.json b/deps/rapidjson/bin/jsonchecker/fail11.json new file mode 100644 index 0000000000000000000000000000000000000000..76eb95b4583c8ee74eee3bdc25e1db69e1aaf4bb GIT binary patch literal 29 kcmb#{6tx&R3FsLvzsRaPA913p$ literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail15.json b/deps/rapidjson/bin/jsonchecker/fail15.json new file mode 100644 index 0000000000000000000000000000000000000000..fc8376b605da69dda23f3fcdd9816dcbf2e736cc GIT binary patch literal 34 pcma!6^32IeO;5~GNJ>o3F3w3T&QM4#PEIUHwNi+wFf>()1pv~}3#b49 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail16.json b/deps/rapidjson/bin/jsonchecker/fail16.json new file mode 100644 index 0000000000000000000000000000000000000000..3fe21d4b532498c8b90872ef571c6867f45e645f GIT binary patch literal 8 Pcma!!$xF;mO^F2n4c!A6 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail17.json b/deps/rapidjson/bin/jsonchecker/fail17.json new file mode 100644 index 0000000000000000000000000000000000000000..62b9214aeda6d74a72ebeceedf0aae3609f1c638 GIT binary patch literal 34 pcma!6^32IeO;5~GNJ>o3F3w3T&QM4#PEIUHwNi*NFf><+1pv`*3t|8O literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail18.json b/deps/rapidjson/bin/jsonchecker/fail18.json new file mode 100644 index 0000000000000000000000000000000000000000..edac92716f186e39d0e3c818b8b110b9a2c4add5 GIT binary patch literal 50 Xcma!!#so?s`S}Vdsi_4@u~+~Ay~`1m literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail19.json b/deps/rapidjson/bin/jsonchecker/fail19.json new file mode 100644 index 0000000000000000000000000000000000000000..3b9c46fa9a296c9d8c35ce4a6592d8bb7ffe748a GIT binary patch literal 22 dcmb*}E%1Kp7&dBQ%KIw$BQ%KIw%}rFYQb_&rYqhQcwbt#R|El#U%n+a literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail31.json b/deps/rapidjson/bin/jsonchecker/fail31.json new file mode 100644 index 0000000000000000000000000000000000000000..1cce602b518fc6e7f164a58cc710def27e64b8a5 GIT binary patch literal 7 OcmazxNY&Ogj0FG(j{(;J literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail32.json b/deps/rapidjson/bin/jsonchecker/fail32.json new file mode 100644 index 0000000000000000000000000000000000000000..45cba7396ff7462dd6de005c32fd2a95c5318e5f GIT binary patch literal 40 vcmb8Q%KIqFV4(MS4b*KOiop@QYa}ZP1OMaC2I~A literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail33.json b/deps/rapidjson/bin/jsonchecker/fail33.json new file mode 100644 index 0000000000000000000000000000000000000000..ca5eb19dc97f5ca363ff33a4c3644ad28e612679 GIT binary patch literal 12 Tcma!6%FQg!O)N>yP^tw099sl) literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail4.json b/deps/rapidjson/bin/jsonchecker/fail4.json new file mode 100644 index 0000000000000000000000000000000000000000..9de168bf34e2e368d044bccc099d44b02316de66 GIT binary patch literal 16 Xcma!6O06goVB&&^F#(uoBCFbf5G literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail5.json b/deps/rapidjson/bin/jsonchecker/fail5.json new file mode 100644 index 0000000000000000000000000000000000000000..ddf3ce3d2409467011ec7545551d5d078bce1bfd GIT binary patch literal 24 fcma!6O35!x%1Kp7ttcroVB$uCY-ij4&TF46^* literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/fail9.json b/deps/rapidjson/bin/jsonchecker/fail9.json new file mode 100644 index 0000000000000000000000000000000000000000..5815574f363e58cf91578e909ef4dabb402a75de GIT binary patch literal 22 dcmboVB&&^F#vQj81Doxd?1prvK2ebeH literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/pass1.json b/deps/rapidjson/bin/jsonchecker/pass1.json new file mode 100644 index 0000000000000000000000000000000000000000..70e26854369282e625e75b302782f581e610f2b3 GIT binary patch literal 1441 zcmZuxeOuEo5dVLl;_L(z(zmS}+d#C_AtC|_>Z8lltjk`YYe$CI=B`qU7(q~I9 z_q)3!cfVY>1o#<;XD7#S&Qk%WObDJtFk@-z8brZMBko`DK)`$=#^Az~Py0MET3v%B z30vH$dB~?c5=QT~a4Y6+FJGHpB^N}J@mw0RFfGI=3&X-sZK}>Si3A_Xt-!5Ry;^;{ z(R6Yn1t*+^h?&jCcHOFZ)rza593jVAIdao2_E)|g8Pr-u?QB&&Ei!_z!rV%yUe~}I zp2RY?rivrEo2zNk84IM&fFg@(*Q+cRN=pr0-DkmN8nSdO9VpeIAdW;5hp9sPbVwtb zP@!9_9Bo(!YU>aSXJaNkSw9%?;b=U$xD2OJJiAI#k^P=8Zggw^==8vs)_(i-o6i2* zgLjATk3JlqoPPXtcK-Rx*Kgl->%n9+5z^XOrC5hGE!yP957NVfiK?FQ%l-T0Rr%@K zkM+%G℘2FP0mvF6rI=*|B!*y_b5>F~3%M$YgYyNk-7D(e&FilP9K`yeG~0(DQXS zNjUVo=bfsBA|I+X5-Po9BC78RskDmf$a#Q*&Ptm<45PIKDA=AG4+aTORn2M+oCymK z*_5X!C7eGfUY5wcjIj{2mTk}Hb4$KOD^5la3K_&x^|sK|w!z+n-6y6Arm5eujBEVu z!KN)kKHwdsFarhwa2O!e>bj%?1gfPHDV02wYVzFjBl#r9`n?Eb`)<)A2A&4ljm4K? zNR@b`M(Si+Ps~M%yye%5AWQma1EJ_oA8jENdx(BB^=ec$*UMFJ2WaLvl?trk-?^4U z)r0jiN;|q2wJAO&WQM=rp;_B+RtWE#cpqjL~Lyk%icvU zmN2nCT=E43EP_4<7A+tZ$s`&Xs%;f4aI6}TX2Ysuew$6p^JJb~N461{W1GOfBqtY} Yk{lg}RQQ$}O~)w_BZ*Vq&jv>CA0fn2od5s; literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/pass2.json b/deps/rapidjson/bin/jsonchecker/pass2.json new file mode 100644 index 0000000000000000000000000000000000000000..d3c63c7ad845e4cedd0c70d13102b38c51ec197a GIT binary patch literal 52 bcma!!#sErw`6UV^`S}Vdsi_4@v6uh=;zJTn literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/pass3.json b/deps/rapidjson/bin/jsonchecker/pass3.json new file mode 100644 index 0000000000000000000000000000000000000000..4528d51f1ac615e7e11dbb1321dc99187705f0d8 GIT binary patch literal 148 zcmYL?!3u*g5Jd0!ieb;ii#Pwk9@>Kbz@{wNQWHrwf{6d#Z4PyA!@S4r4i>r&_ZvpZ ziU+Go3RpPjmOAVesL(hGVzG6O2Cn=mVgSv>nip_D^ly18VgjecTSJ%A?gMmsWvIRU Pv|eHDFEv!r!yWDmkRU3p literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/jsonchecker/readme.txt b/deps/rapidjson/bin/jsonchecker/readme.txt new file mode 100644 index 0000000..321d89d --- /dev/null +++ b/deps/rapidjson/bin/jsonchecker/readme.txt @@ -0,0 +1,3 @@ +Test suite from http://json.org/JSON_checker/. + +If the JSON_checker is working correctly, it must accept all of the pass*.json files and reject all of the fail*.json files. diff --git a/deps/rapidjson/bin/types/alotofkeys.json b/deps/rapidjson/bin/types/alotofkeys.json new file mode 100644 index 0000000000000000000000000000000000000000..3fc052e34fdd414108ae7d6f1ce0ef1213e175fd GIT binary patch literal 30003 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 Ie;c+jrNsOx;^!tf0}ci_*lfvq1`LGr%U_> zoSa3H+4G91@0BGYd)G~(n#;shxa1dyN-eP*^OC+$tCv|QbzE;iPBY`<{mT3{b@#-S zP2L-`bfV2eZ!fi%dP^siobOI+u|)uP&p$QcMVgK2&F~{Ip&@kq0t!KuaA9p1*N-!N zRY=_=W-F}poF9RE7WKF6@b|!V!HkUc6X7?xq|J8aOQABWO!lvhG!Z5bu#uM~P**dl^wjlU;?tHk&xVNY5z<)XVXvS{ha6KJ>>$+` zSldrJ8+yZIk&oqLC}^|)MUX`?tfKNcj^4Ec4N7mx(ONDI|qY&lxtvYw2gTve~E5}HIVZ$&a^mEJGj1a+USPmM4kiyAKT(#avM#78igu- zFviv>dL`Vwl!}Yz4A5%lX&Schr#Zl$gaH?ww%hv_MPr9NfOa@($7vT?%yC-Vz zNap7TM3+iXmN9<;*s_heApJt;^V+)0aQ=G(b_TYyGG2G1tRpz~Z$Op09SnayR z(srGt=E~~~IbSF=*S#YceKlqtW9AUSg*z3iShIIv+lzo&z;o&}yaRNe?CD{WRK Z({KVx*$F6S%YS8$Mc5mPY5x5C=Rb9MGfe;h literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/types/guids.json b/deps/rapidjson/bin/types/guids.json new file mode 100644 index 0000000000000000000000000000000000000000..9d7f5dbc8f9e0a8fcb6748412300c0c73b3e06c0 GIT binary patch literal 4202 zcmX|^NshEB4ug-!0L)G< zy7UCusRygG1Y5(;YQ5&x{`t?Jl`b*&E@5wPL0a)JhPE)J>J(Y()xMS4@|F}+@OpBP z=o+-w7gyC#vs;bP}Lb? z^XhBNJ=b{#J6cUEC~m zoAuUi!L*Ffe9W^o*WTn?>0*1PG(z=g+*4-oq8d^hn%Wf2_G;g8pE%t^%AJ*#H4LQ- zwM%lzqvrlrt{Ss8t6_Sl^KwL9yNF1DblFcA_uV8~G(EWqL!MzJ!d;3)i{C{ znkw58{Zz2jT0bDPw*C4!&1reeVa>IINR{Ae#L$+dEJJ!3ulB5Er8*|>o;Y1=3r;1W z#yWD%+bq46Nm{CXw$QV&GFDC>Bhj?Bt#v6&-#u-gb}|U*CBhD0nH!(Z>9xh`bF7fWMjSfN% zy^)?u7-z@8qSfM>I*xuT`&Re@!DA8Lh(f|BL&KzfvF$!ae|$fA`>A$9s}MuZ*}3CiABu zkfMOW9FpEQ8WYq}O{g||U&lEA?U{?xUk$}(T>8Xw=yGcWOnk^BTBmgk@J}Aay9+Y7Z6hI-tdm~+EZBH#^Q7W>G>Kz>+BMRWr zt`2^kx3~qQ$50$NOWKOaRMZu&pFM3)6amafNqX z=+2qcwL1!fay1wdp zNX{8W=$OG=8+k~ONh6)j%MW<+w({$IK1WNm5-MEhbVb1u?C`Y~9OP%beo~|Q2Abzw zolmz*!+MDQAPy}b`C&fqlwG9-_T_Y#$Q#j5lcF*JTG1fEJ3+rS- zs!{gy?ny5MORd)e=;soyDCS%{7n>6SJ3oZXD6P`;-7n^4&0vr>j9B{K=GN?Wsd?NZ zBG>cOyJtl@ts_ny!^ZrS$NFA#)nw)598hUc7ZrBca9(q7e0r( z;|J^RZSgruRDOJ)NYAECA$5dXF7))I9TKWnadPeX>8EUbb7s^Xjo`JfE+GJ6YD_#q zjVnHn>rE^E3_k5@NTf?6!A-@#212X$L$bCLfqO$gvCJDh(BxD3lRfyd(fhCVJngE_ zM7^Dr)gtKvWk5Y5xOGl{E7KS(MQyg#i^}UqhS=XEfb;-=dv54(6_vXsKy@+pRM*1k zC~Xr#UtSVG%K#RP>wh$P;q+tXNI!9%5+i2vYOkqyp?N^!>ij|#x#s0FF((ypz8^w} z8Yx}r!~$R(?}E#amyo*EZ@g*xFi&5q#=b+W1Ti@c9$gLDng7UH6M=XLahDn&i66hcG zUN+iHUK;7@=h_{~S6=&&Pv|FrL;DtL9qs(i;4gm9O>$$|yL z`0h!B-plz{aYvUXzdYhHB@LooYs>8+dGuw{QDOv+&J&2p^R$Z4ltibd^W)KI zxr2)Fcx>1m+JPl<++hHCNUlb`j{Wh@?0FhIVo^Yjn3ZDPJO7o+Ki&YznqZ(fptM4RrSdBxTr>gbz60;IDL2V`P&;00hWpY-5p z`gvSI`yvw?u1&BY1wjnFm06}W1EJ_gd`&yR{O^agwu^7!r2M!~QJm~ev}qWV)sWl$tZATRsokVO(5 zbulDuCL~6R#5;Ulf=7jZpmjt*R1pIi%o_-r@7!Vmiw~c~U|N$GU1U5ECq3w7ure6i zK>(0?d~Xak4i2x1*h+v+W$XLv<#yGK=Su=+8Y6tOzN`}@_ zsXa4ujnXNQOLd%|iT)*lK8VeKTsv=Ga|7o;ES46Hz_Iz{?P;VgmL6n~5K1^gBN*6_ m@XXlB=!1}brw=Owi$FQf)g{Qolk;b;Ae7Vy^5vhu{`Y@~_4(`o literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/types/integers.json b/deps/rapidjson/bin/types/integers.json new file mode 100644 index 0000000000000000000000000000000000000000..5dd05e097a4f89220957e18bd013c58ab7e4b44f GIT binary patch literal 1098 zcmXw2$+25O2)zF&egHlI%^Hi#`KRF?kV*$pGrWdg=I_t%Z>vRi{(0p@m&_|;D$VSb z+B`RZWlgpZ_7qWmpQ*NM?7g(g)GIv^?B3Ie02a%v#IOKxYs8**&U|`Jx^NBEslb9& zguBZFGtm<0;!bPMBBb!w+pAqww+?K|Yd3Ecw6-BNI&E222htY|A{?>hWQfZuVoB<; zr(`LWTl#dnZ9|HqWy!ZB*IjO@0@EdL?G5a-rjj|!Vhj=28$&ofFx8}jk6U`FViADw zIL2OGu1je0aXv7&`0%mE=&YD5%y}7ZCzCqqo`1$`-D@LI#_2pl(Bo*8iI3~Vx`uu} zA47i=!dzBaDiPb9hGM=4XLbks?;d{*&f}P9bsxUat*Gcr;>&iRegGRH1Zmt zhEEuZ_A(@|A;iY>q-i(~0gMwfw+KT$FVT#X_@%`|TYW!!so+Mhmr3b3@#qd?w1k4U z9;+@Ad?}{`DcEVsf7*7EFmR320W`kuC1`QVe%4XpUsp8j3{*PJ{J$M?%3O|6wMBhw z0i(GM3<$$;xLiPQ8pBv}y#o*HOG7@lzH#c&1LG6syfgV5ob3(o3 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/types/mixed.json b/deps/rapidjson/bin/types/mixed.json new file mode 100644 index 0000000000000000000000000000000000000000..43e9a1d7be070f5eb75a3925f99a54b701b4c65b GIT binary patch literal 15142 zcmd6uTXWmGy~W@ADNs!x+Bp_C?-xJ$5a)l z6Jk>}OS$KjsOxr*y{T5eXMbx4cFC^=^ISGGo!})~iN5Dc(K~eRqN_wx_Bi$LsxZ2y zx^BZ)LKRvqmsQiV4{h01{~E*>eYQHNDshObPyWwXr3Xv-8Kw2?v~F+9d*^%4IR7QT zWfvRqnRlCe=lgWN`uk7)U^?C`goHQbz)id8_@~*5@)AfRr1?CcE-EnlKI{q^Ib1w*}fOB z_h-6tGoH7DYK3p{sT)?T8S0udUZZJLYbL*}ik7Xrwkk!lVdAC`>x~#XCi)F)7mKQ> zIIGtEuyWYR_!MxE=!$BCsuCaY! zF|2V*DAr*Ym8{EH@Z?(MQ1z@TSJ_;~z7 z&HJkg9YA*WJ#@vUKtF%icAHCf%)7R(8otMp#Pz6z^<~?r?)yI;`y*P!pI8{Ab3aZ} zIzp^?Rm&?}RV!!NRd_X<%Y&lAt6Q}Z`p@?f5YNigR;@uQrVY35VEomFU(Hz-H5W%j>g5mDsjndfDxAEeyP zi$%sm&kF*1-|DWv8SNKWRnv%Wg7@tE=>7riq~z@9q2E+^UW6dLuxF$Fa40*DX4r3d zBT5n`D-X}X`=_e7x@E^wu&CMD0)9xom$J#)2R4(;FpqDxh4ZGRCXL5BWt}~KgoORh z%W4f06;jxD!#;K$Kl4IYYtt6&)6j{%Ebz2k?STEM$h(1ew=B`P5B9x;9p1~TW<~u|Vvn6dM(e8Ig9eCh)3OhhB!3hJx~R8o2qb%))}to=n3r4&fk7KfA{*BcI|@wnJP~oHATIq)z{&k+{w4%KG=(*!0}wF z^%J-+7J1<>@)+6}dUJ?mI?vs>oQuNsJ-=A+!lPbpaIYQYUEC)E(jg!ZaUA-I>pqEl zG&}w|7hQKtm3_d?e-O6~B(9$@Kl(oAA9cLEWuJImJ^(wrX>_Zk7FviBXlfzjlciH|3?*}X(FyG6lqH}64uCyir2eSr6# z6S|%oQ0LjU_GeP#VeQY0O^fCRW3OqS?z`SYw0|Lb(Mc>TdRuo4_o`seXmm4jTOB~+ z01vH(1fxynrN$xzfF6N%(7@=(MqEZp0}2PIuiJW9!?Ozv4{o%>wiU3~g@8Eh&q`O! z5JM7qRD!XZLX%!s8ire4h^)B0Xi0Y}&ovd)n8vUH$|0qS-j)3zH#_W|8ZKaD1JI-L zQfRDlk5|+FUzR^UJ1KR$6d+A}hPQ>mf)jvNwI{!$Q*~R{gu_)Vyjn5};eI5M?t=~?6 zz}E>As`rHc(D=Jvf01QDz_VgrgdU%Vp1+uLF9rM)KPjR(OA|LYC26luUF?q6PZk~y zj-${ExEqV#!0W#g*L(u~R2AM@MiKUV)f81(m4Kw(b|(Pr!-^kocfue9rm5nrve7_pg$dQJ*ZPlF2&`F7k%9?bo^ob7p zWizHxB&SlOsMP7$k)Gp?RV^jfh^pjE(a9P;JSC>6k5N}0pV5A%RZ53%GODAo7-U-c z5*3Z@(ycIc*$H3P!emsZ7*rv*hFYCp)%>zu;gcVGq3$hrbSn*HK$Xn{7q(fqd81nm zKc?|->?b$s~YN!2=1h1rg4L`yPvw_xR6`PCrRb&umH7KK3sE$DkevL0a5bMf4U_C(<2k}5OF`sXg`)w=5 zA|Tk^>flF2%#WNffQcecHxV%}!$>AYYu0^zTf{yNqE`c!pNIOErFO8AJtSkV8?yPz z-D{?UgCla`%z-egQlKMg8I2Wa3@{3X!_Jfxjo(c8Lm|*qKOO+Gg1Sz`bO}}Cu-C>e z*dd3$Jk`cj5l74U5n}QfT~QrJ7Ly{Vt4&mE&|HTA<38o^Y8SDyG(!Y{Niw9r?`4j@ z$6gHGtpKLqBRn54%E%Ivr*EZ9S)BffMG2-8Fy7G3VP@0kM(Q3kmmB;h>b z3o#ED1)pbuAI(#qv@bJ!JJyO(r}mT>>1d$spr< zCyQTqpV9P?5789K*P;4__&?DPYMvPLU*?SyUY`T$x0r-rXT=JZgQVKl;fLh2q?WnW zneN$kgTaE`r0`26*1H3^fj*=nX%KbLu!njD3-DN7@}yu zs$q{4$hpEU)4Ag&Lq`Nra`M5NizK`u_6pP39cH_F98B}Mf5F`N=e8~P*ac?SFWC!z)ouXdFpErzzfIuOm3}##gV81l zG6Y_sPdkfR;Qp5fIaYpr`NEyHTk1wJ1@O_y;fr5?J)}LmQl8VXFx#pOf+at`ioawA zzMa2Wm^!Y}oyYxhoR^64<9HtA-eMk#GM%Skk}uurfS55z~343Tp)X`uDNVm7~_~1Mg)D1U;ag|vyjaZ7=;m7USf5@ zy@H;D;x`?ZmtapRmllQ4_j4MM%C;u%N6q zIadQrvsccxPH&mcLl9(^+Kl19oE}!e#Yk(a3o`c+^aw4+Juvi|_UhWUibfz|+|@L& zJ`*R{xPz*yvYZj(;?JvQDx-q(H8kw)j>N}0Qr#*M>W)lCb|;OZ|JZD=m@qNN$wsd31E)lAmHD#Ff>@) zmWxQrg`{8rZrzPnR$L;;SwS3|_TUT3t+=zfrsL2fX!XypC+|MKeo`#XR6(}sPqac_ z=n=KJAFr4J; zizUOR(1eQ~87Waaq2F{7C~i{CkbK? zwgMkTdli%@GRrKVFt1mw>M_?Y+l~Z_9U*r%e*H-Bp{@inl24*rVY(J!Ns^cahIiN- zBP?;j-qgL%UUZu!vh4v&ZV&p~=4vS#N11R9=?Q!<{`T(8%aeDy#mshD^&?r9ZB_=p z3LKBH_kL1Bt>|0P8|kNjJ7W>`R9pA|4!;2UrJ|O!KK3+V+{?zPtNBU_2U+6 zqS<>G01WgVn$~>|eldW%Wp6R|=^u#Ke@OIFbYL4fR-}`5&F=42AhHKcZK>UAnKRiY zSN1)^;WWcCGi0FDQ6?b9E=<%!8F_O!xAfR?P~jI-*q1X@u6IVvK2e@ zdTFJaDIJ}=wZz7dYi=5^iBeSHGEQU~=R79G>_pmj6K5#yD@fmv^H#hiD@{+@Vdr{T zzqGKs^yk zZsZD6Swm>kn9{&YkLx<|RP0D$930qDN=x$rbRm>Wv(ykKHC13+&(=f(%?>Ml;k)Do z`7nE5VXco?LrRRuyb@h5f1QDK{^B!!&eL5%Wx~wF#oH>AKxM)xn)_*Ljxd2x4|+LY zI2=Adz~@r%9)8~#*{R69I(%_*cyXdT!A_O=RTXBtijf%!%CAwGfYv8}yUK)eS)7@v zctT}(5iQEx6?5S&@;R1iig}uP<-Fu!?B&8Oy@FP47=uq$yrVLF;krqJ)uSo*OW{8~ zfr`bBwRz|dtn@sCg~2bhemk9!;T(+FCyaDCnisFl3nPR69GQ88ML+n-$t0wvv!A0c zuQ256v5*cn>E6|UNO{?w5FLBEsrhW=n*BcgQJ3Mf-A&-NTNJ7v5tYbyk|2Tw(hhJU zDqigPQJR`Avn?tUdp~CK9)GnVKl1m4q<_H5?EDw-9*twRm zX>+g=61h%A(=pTJ{p{rI{KJ!3$|qHjZ9RswniY?r_WvPF@%MrZ#^#|g<$=YOm{iIZ z_`%_vV{PO-{~*{Jz<}MCnQp)A?1R?Q%nGnAuWc>*^Y`#vNJhCAa7(Jn z%n0)E@Q@LiRsA1-xm^D3)$^xM&kxU+myaLsKYe(L~x2Nxy zFJGUZ9v(k`zdZhNb9wdj@#D*<%a{AFPxs$nzFwX`e7Jx7fYYBoU!MQ@&!-Ph_ZJNJ z!NYQp54z_2OXbletY~{<9g=h->c;hBF#Y`;dA}hLEZp- zdn)=>Xa(lu%gyCC(dqsZ*aORIN=F7mZid+7isH@X?nU-If-n_Dg;l``X$L;D62$1V z$Vo;ZQ08l1To1gQm11aL>|9=dt7k5nUE$83yGvc4XwX#F0Y?Ci)X#B zL-!ABQn;Skj#wt#JQ!lWe80K8KVmi!G-!0``(@tel=MpY{eYDs1fUCDgr@$%-8O4S zCRQbfBLajD5ZqjTMZVc)0}glj*TU~sFieIQdSZU(a5<9c0`ho8{%_0ZVPe}MmB!p$ zetQ1){p-s^Nf%EPfp_j?DtHgc_;w-JLLI)a8uHTkT?_|ul?9g4VzomtNRQp(ZTU9u znb8jmpf}VW=FfIA)9Q*?S9<)1k{@D1r7I60P?w)=6}%#19H8{Rbey`r?1&&&@HvdU z+e&X!RbsZ2_cW9FDq&5S`ANKi3?TA2Ao#_VX z6rGW81eR?3@bdA?eG2~a>hDU}uwv?ND|zyia-8#8u!E-NJt>d58CKN&((9nnBO_J} z|LP*T#TY}X0eR=@%d7&RlNO>eU6eLWc5G;ST-a1`1LJsNR}|u>5&GPdsqi4qCTkLN zYlecmz`b>Uqfko|Dl?2Cvi=WR(}*Za#uB2(FgMos4~XmY*T+vsrHf#l^{>>BB&~+7 z{;<2hLR+1rQN-j+T|ymjF@xl>{gE70x<9T?F##_bmQg%!A`{-!ZvoJO>(XK@ll7(3)0DOig+lxU?eLFNmc*q#Qw5lC(jwyu)~<+}h$2dc z;O}ZG30DjnBm@tGFh!r7U~4k!z!YO6J*}=wMkSBNsRr<^+t|ZDA0~XRn;46!5eo;& zYU#@3n@cG`jw2vwDRGs8(1@|2bV(AKS*>|lHCX8DN!12(#1-SED7a}?$OWMeq1E!z zVKutA(7bw47swP<<32DdN-IL|NyFAfX?uBVNY13DEjO2DR~9 z4otA@`h-FXcz5Yr-f@UQX~tGXg;ppv5T9zN17T&`X`{(n)lIQ1*(kZ~Sfm6P036q9 zY!*s)B}$P4B4+X%-D;qj86LuMA2ry$@~)uF{R00eUa51HsW8sG;-HVI{mCK-HERUL zbBjU=d1bXYLXU9{LYalDAeqDB!XE6F-Vf=9oRByo(ZkuDE7QiH95>b=Fu zH&7gPV@`npSooCe>SzyQC^+&N?VM7f1}!WO=@2}6$`rC0D8=k_2sv8LX1K0w$81Mb ztCVReOzMuhf%_92u0PkY>Lle{s_GsT2AWY)gBqub;#!ZI90>;Kut|_YY#dg89fUKU zV7{h9Ls9z?C`P@k9-B9Ri5VQkzs}GV*V`II%hW($WFkNi(MGqgU38ChYl=Uv=;@%< z+V5l4U5U-;1*y?5)7>&55?`KD1Pe&QSTrCTT`(GiF8Jlv2Bf>nH+^o}SGJXz5+ccR zgD4fdYVwj!sLKNFcW*l7qUrQD^2E@*wis0xf2S6u`Uqpvc3LTcd#L8Dc9JaoN3f+He{<+ORCPif|TQ55}>Kno$EPh zbFOirOai&mcyfY-1%65zH|Jg?WFHWR#p~Vta0Qe#Y7yPZJ5#9$mc_wMHHlD`7C2Gc zy@)@7I<7S2h`e z8b{sKZ{F|ZYBN>)zSE(AP}&iat#l*}5=cV3G0b*nNoTF%7%LhYSj_aDK!m|?vn2{C z`9gX^k7}cW+@R8=hnRhp@{MlBj46>Fhy|8RwAK`Gpq-$3>!wvPv7aaUx=aPb$)6rn zCLlxTeZTAO9h%{HKH` zX2rG2GJ!C6HFP;7uat8{7H}1Fc5b6T8SvzXvkY4Xkgs*nnl!_SF-a8jFfO8^&zYE5 zht>F!Cz@vRYR%O7HSeLHDefs#GDi9|buRT&sw(ClRC;?apd77sgj=5WjerGeAb?8r8kyMe~SJZ2hrw|3qH77z)B;}lu zo#`J!{wkwNMFzjsf5o5B8>9up``&mt3gPhrJ9;v&J5NBF-d!f&T>h&2%w*ssMU{r` zuOHDT{#2%x@{!<54K2gM=_*b^(JEARRVN*G?H9e8Q*_jE>>@>~B9C00iVtlju&x|m zu)K9YHBvwk2)Q&!M6lr&DV2IT)giSy3SuxzLzQSH)Q2&pvWN|u63O|N{oQrRVf3&_kuha8p4Vnyd?;QiJqCL##V6zV5jl7^NTV zj3P#{Aif@pbEdW@t7c@_zc{r*Mio%I#U`P1vvi`B-pPTt$h3E?f&f1xwMOrpB?l2A zGl&#Gd2w9>b(7IfKPo$fAb<@4GRdI8Du^X#%lNvvk{SB!%$#A+pO4zTn(fdfD8&uC zGY3_CAGsFs)UuDnsKnIXzl5SOXek_ z)TD62-3to2vj^vSBEGz>j`;$;T0geY07lJ~jB`(K!acWjA zv^2Vy80OmiUIeBxUQPM4S6FI1S56c^y9L1uv2zlC6T0!;8f2+s!K(C)foB@WOp;*L zZ^q6ULv^v|wXia4X zC4&`#X49@bt5>8?RvH_#5PVEje4xtlqQAB>PT&^QV6cslSc|d&#b%}_XQ0jGjvHDq z_=_4odm_q8mBd#pTF*uloIIyrp$UVPkyr7J%n% zt-(nJFxjy!#9CbfMdGh)tqp*8YP~buFiT_@i9O-77Gm!AND=I&a#rm4GGP#BgDzIg zDCB&bH6o1no16fD;3#-kwRo-VnI6H@FbF#r7(MW4W)`D(j_Lz8iBv`T9u4DxrP-vN zumU|1*Y>jFpBF-k+2GPy89GW76;2Q^PQ#7e&!Rg{pNDkCh|0|x1xKAmD-~hO>bX)d zA`!?FRvW+1$sk*Wv1UViU4=#yNpV#Wy`)>3Kp^W!3P5{3IqXsfgl1g~Cz+5u9sIU! zu%YPfUF33I@G?2pw7A@%EgZxmCD|fFii%UH!X!$a&8QuIQo0w=de#(`IsNELomv zvc2^bX8!edCYT@XnhDP6h+iC^*dop(N@WDxW&bgY3*`}kYnRYZX%JqADfR8pU*L5#4d1VU1Q3RW(=!X}P&2tYz;pS3W;#gfs4Oc(n+F{ojA7#(Nj?~2<-S5bG zgQhY;)awbmKe^$rQe4&-;7+tnOP~c|uiDc!<;CJ?*L}A1V1N!ki#EMa{jnZOo1j%& zmbD^7=gh(#gr#Mc?m*dv7;evW4L}wmK#@MF@*dhUId%3uV_5Z!x?Jjt!OFgAM-PY^ zVEcK-EOx7}Z#h`aLFJo;73~$R?yMm!{4sB>wTuT}Tk=*@vT8Y0Vr3c2{s-_&kSc3e zR~9A!9%0q!D$2o_Ild-Q`XI$}!jaQE`)g(T<3Tjr5Uvnv4VBRl{5REDUB>|GLk%~-eC7aYGIfQwnXn_q7ei3wy#qzjZtNQl1_dy z&!zwTY$NW=sN1VXRb0*m+(Cr1(=xV3F>RD9-1Eq>5(b+M6)A!Dg1}H@gzut z&hpAn343$-oejJDsv(~5(t}p~=uaCkX!rp>ncI{&41^WdlZsIsv;iwNS`T+4m$md- zQ+mb1Jw*8&%hFpANJXCIS?PLIQQRIg0XYd~<`ut`Pu_Qf<#1yAiX1Qv?T&wGG+%uE zVWI~!S-s85&bw+|WM%0LWy3TWNr=Ir0N{!~wACUB^I4Cds}{@P1-?lI((ksyJy(xL z^o2~dqQg8sVA&u(R+^Z|1>3W-STw}O&C3r zANI;7%=DuozEWSHGpc>mv(C9vq^oF51Q>DOg>0f73Bt5*MNS%+DU}Aue`hYAQj0cq zbq1J;Z}z78d3V%C0iY2OAr(ge-NCD)1qTg1v1Qrlg&@GWIojQy1w!X+6u z8U-$4LjCcBYPQBJDQasnIcnUC!#+^LgY2zGhF+^uURiCDv*$>~Qyei^2i_1TVkleW zl9zMmgBNGmsE61@^gMB5#bn{|OZ07@4S6jE&p?g0t06^NjWQU6ZZ@s{A-8! zGwNA&M!OxLB4DK03i8^2o3)I$hz4(kyt6NOxhOE8$`WKk=|nZ@5+5zE%aqAz8mo9| zmE|q$(FwGCOoP?N!4n(ORofxecFgDv;Me8=ScZ^B&?sU{zluMHY zbIZ448s*GyP>##tx(0f(GpdH}k8y*P|*IwiaR_Ivs{|bjhh-ODt8`Y*ZioWDZ$AA<8WSOY- z%K9*BwnC2mpk;)~3@=^KK%2Z*aN4R_1+NUf%l1=CgY6^pLpQ)u1DS-$T#d^UGadP# zRSA4zgJO47wyO`zu-Plq7k(TyAep8-2!)s7@3>cNs3(-NX-YHG(8|($Adxj@XF#4> zL9Avpo#RUNlkW>bKF(sOv*LA=`c;SAeE}b*i?URC4r;aQ$($ONv|XLG)J0XBf?R9b zF}2ETp}#6@`zsLV++;xI%VzoH4&v-|a6;=^0CDoTPjJW3uY5M0cD8-kjmg zlYPIW?3tdWb@d;ZL+g6Uf6iS3kkEjJq^@-9H$B=~CwKud$y{OYgi^hNWp(P69EN!n zFWAAVI1aENY1x$go>)yj3B%I!o-?N-A|iw$z}PKbxC1W3S^`sj9A{LB6wyWFnVi>w zh3-pnV<13x(&Y5#we3Sp&Aj;gcsx8Bu}HSXNzQ><28xQc-!#X+Ks5HFm9s%oR3B@6G==bQfXPS7-f)pU~Qfm3b<=6>l)-5YWHSG^*CY@`57Sm?!WZ(RC=+jp7nfkUK z3$u^?Y(MRVYT%zDf0TmVe7&tD&PzF!16*qHcLHC|Dozj7MgBE{7 zWAd6;gGcoR8#v8_Ree#WRHo8=r5V9Ks<3w2?L(#D+@CIw6IleKp@kUHHjc}``m}Nw z5K5(J`#74kz~v@lB4~!O=7gi*)%88Y!*}dNx5^}ZSvc)Dk2Fc{VI74g)*u-Y(?cxJM|^o$;k&0pHM5y3ly}ENUU|3|kkVs?sKUnq)z71XyktvZARK4rJH{dfwNgZKk9ZvdE;PKHNc3=aWFCzkJCuz`w>4s# zX}PiwjB#bciiY0Tk3yxm1vk*@j&hIVE~xlSQIQ`7MhdZT|4pTxNjGeX3JsXDsaaGN z1h=Dl)B4Vf1m$!Sr|F0D+1kk5-@U-HOseTAk5+t(bd&|l1pWLuf~_~3Y~V@f7rl2C zNK+hx($<3zl=Z?g`)QF2pi~mTq|NoL4+x@!tEY8R0*SK_Wf~5-H)j5hfpbxA5*Y+# zQ4cK#Df;Kwz-6e!F1cs`+qT~!6yDxE+kXSH!o6=9B0^yLy0A^55lMksKT*^`bD`|axWN~eWm@mB;1@7i2jXIU9845OPKHn%gXk{XUz z$ZN0Qt)INKoWV;4Mw#STAqH^BA)+Le+TpRhsp_w_I~D;@`q<1y7K0q9S$2Vy(+R__ zjc*qVEd+Xy@llonCBZ71L~XH4Al;FWSQ&Ve{LTJkEtAn4P1;}#ro-lsSVs+JWTl^* zgqi|AZgZ@=uU0P@?s7+iX_@JnoxcKFgrVX@BSe9kew#C7aT7$vqpT6OP-A5Bc*eAw zqdlf+N6%Jh@2=AwbVw42HYOLgDMNJPLI>#strdS<%mGs!!IedL24VFiwxnP{0-jGn z7%U7RWK1$iR(cbqdO^vd(1S5(?e=N_K?yEJ>NlfNsZsw8bU5yQD*n--klofsOITA^ zycrY(ow{O@=$X0Svd(0uR;6B2Q13|6RlkSpf3i3f@l zsvOWIz4!IS0<)qub?p^|0YM7%t$~(7uS1)mty#qxBMZSYzY`x(RG+H$K0@Z)`XD`G zoN_q7N8BWYC*ye*AVIkB58l17X>d=y&DH;A3Idy{}nV`U27@UPK@l-^MW!pdr-Du;dPH zhsrHnp+=t4MOey39t(-(mpM>=P{mMbhF^tD`HkOmm5M^;hw?m>%basLiN%vpQdZ~N zfomYfQSB=li{d~!quH5Rr2fhKr#x{75CpPkBNOy*pOltkZ5oUraFrxEm zkf*NwIA-pECrK5+_DuO43si|fn#|Q0AGlnT!b`2$%N(mZ>^tl5k>p;J{|dBvdKFv8 z&MJWuzUfYNJ$fh>S_vf=Vr@0bORmO5le($}y+&6l4A^@j7SstR8lIydi=G-h9!GvQNi+Mh-CO8PvM z7zH6VR0AJXYpqH!-UE19n%uQfwWAp)iq>O9i0MUiFOIItwi{>fBOtxvc)T`isFWgk zSK%w}oI3+9MwJ8MEc1Z^!O{4a;~6~3;dOU%rQhpHep_F7b2PR0Ra+HdR0*F_fh!Wz zW~-7HtC_5`eKbmFNoO5fJEHe6F+OZ?wf!^Q*xZF%56q*%OtdSR0v7qF0u~d?F;xam-l-4)*n&_>AZjXqJkMQE*6KcgtZ zP1l^QlJ;%P;||%rrT15TibhYZ>tOUK%Ewf;6!kZwOP~^Spxau>a zwE{IP>^;xoW-f13jSH0;+l|Ys)236vCR`F(J~e!a7y#5oa@$vu3#R`c$tCO zW{X+!*l>hLOq(;l-HIuG;zKlnwf|U|I_K&}_3!T1VNubqRvawkDc(V@jK=9i;&>!02fbPVi-}2o6J;o5K z3s9{I<`Ix4OwrV_@4W1lo8Y$0*;GF3_KpuoB`S&L=l~qbo30E9nv%L`^Bx0ZQ?4B4 z6gmPO&>RVl7(fOU*{_3OA)Q78fp3%4pxZNzuQus!uQ^m@YmLBM?jU+}l#ooht$Wj~F7Tij(7 z;uMiuvZhK4Ohb|_SIuBIHqaWj_B|uZHtKlQL*u8XIL=$FeUCWdC`qZ6c}cwY29iN? zK2R2hbrN^l>N%)aSxGw~DMs$IzynkP;5M?!zQnFAzQ3(b7o&!IbzM3uF32m4(jzI6`h>+i-~5xcM9l}b5__S zCV0`;!y&8npDaQ-s%e@AhNbNH-s98qC%V$Ktrm;@vl30^=sB96(*>MdsEN8D&qj*;oXm-5kSs0e+=|gwMmU!)uG{W$p3!$b8izDH5uT(*)4fNd}k|kEviAn^tcSH%DPb*r( z{U$5iIGWcIf5oj$@s;+b+_c>Ue|_!oN$;tNr+g69#)N({*Es9K|99Wf!9C+PrHe|S zkFufb?IFvB?bBW?7Wmk*t32nVsqU1G6$g{DkP=B~XJ$)DDif=*cBZs-%BiMGRB`y| z%;v?!qfoU^3xYRlT6AypDB2~>s?*YpOi^9;t1h^W+a!#mcvSFBDaBp|#QM>G0KCdz zmYEs4XR}ia#SyqQA7V4fs7g|WFKQ<2W_XIk!ekrEW#yVLx(WhlnDJY$K@(!$k*HPb zs$rvaAz1m$-m)!HdR4%d_~a-EbHzS)F%mJ%FKA0B_V;c4z2a$!L4QVq)=Dn>RT&?n z%>uXsLmiL`Nv*izsvg2AN+AJXCMRV^i5Po;%7qS7iEMOqhK z?#d2JCVJnq07ScVDgjAQf1TR8%3|`+6-9}&%QgkR!+_dPVx5I z)wwNC!)WbFNLLJ}_R%nC&;8nQVId%Q?Txr?8uJRT`iPNZSk+;zP@E6!yeD=Y_(K5K z8U>y%J6~sWwkp;_4H&W*h2Z`FOQ-2g@`V|*e~m!QpySN^LGp(k{0)m#0s=y_y6c6D za6oiww=(pouc9=s6D9i4I+}NpO=rtMf0J@CctQ2XUoN$xQ62Q5VhNpNLuvua!hGG8 zYaW$UnL~s>FWN>NC$5L3%ck3E3~Z3{Sb4$qStnj}7yauo(Ap|UdSy@B4*1s=%R?!d zT;8~01L(|Qt$;F>9iq_nLT$oynnY)iE;Vw3pzQ@%AGM*xcT2z=k>C8e@Ojm1(%P?d zvJHF7yq%ZPVt>CMYNPq@D;=vD!1Z934GQ&JuYT&W4@XD#sjg9elo%x4%9`>lmEu6X a>RVy5&K2MF)3cB)rDfK6F6935pZ^DNFpARv literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/types/readme.txt b/deps/rapidjson/bin/types/readme.txt new file mode 100644 index 0000000..da1dae6 --- /dev/null +++ b/deps/rapidjson/bin/types/readme.txt @@ -0,0 +1 @@ +Test data obtained from https://github.com/xpol/lua-rapidjson/tree/master/performance diff --git a/deps/rapidjson/bin/unittestschema/address.json b/deps/rapidjson/bin/unittestschema/address.json new file mode 100644 index 0000000000000000000000000000000000000000..abec3ec577711a1edf3c5f443a5912682fe47fbe GIT binary patch literal 3150 zcmb7G-%r~x5PsiZ5qUh&tz}Iao8Sd8q)CXeA3}Rs3CK;3;wg2CA?Z=#6EFZcC z#xEqyRIs=XkI&BN!Wu`;SaJ4PfwfCffjeRbp)P^O?ao=#^5{m?;U*-or&z_IpL z0as0ir4)=$No2~o?bNs?E(@%tZVkblTo<>@*fe9)`Sz5b#(r0hvzH;d4Z;hlOirX@GAW82D6ipk6%e@3xP&QI1n+GPZ8+D!Fks5$vK`G% zl4b1D#Y*5p`UZR|AJ8ctTCwXQ;R16Kq92_UBxIbD)`qtX_g2ikK_yVMcI$A5&?sSaR6_cPU zg8lZ{YKHjx!-3&&)M{=lb|$SORz$1TJYhCYeM(H{wyu_zrit6qzc1C)oKsFSYIn7d zY1-Jd#=Xb4LS9#82@3^#T?qmBu8+tiaQtM6$ag9@YX=H-`kGL`Dwsg(0b__S=j#8n z99N`lN6M%))8Iw%#j~%a;$O!x%IH~NhduM#+zfmBgZ*LsOpLyx#516IlxV=`L;Q)8 zUhlMby4QUBv{a`%Ya~Q)D#FF>F-CE*nSRZ>RYYKs=2eNC{>mK&pGdgDj88o5@^Z(4 zmt|--Y(O#ifb{8Axn%RaUU2b26V0L-u?Jw1&0cIxY^piJY91!N6Z|=g04>MK`<)A3@sdqBWbRGrWn_ulGT50^W4_UerqajiFUZpS{`BB|1!~ss2KCQw WQmKUbi1#2ZV>6{S3B0b~tp5RR=_+9W literal 0 HcmV?d00001 diff --git a/deps/rapidjson/bin/unittestschema/allOf_address.json b/deps/rapidjson/bin/unittestschema/allOf_address.json new file mode 100644 index 0000000000000000000000000000000000000000..fd501f66d457484de2a462ff5db2441e80210c5b GIT binary patch literal 84 zcmb>CQczGz%*pXjQ?gQs267Y>s=*{sSfwZxB&w8AQc_^0ub-2joS2i5UtD5kXk=`n apO}(Tlv-S@msOmfr>q3lQwtCQczGz%&YWIQ?gQs267Y>s=*{sSfwZxB&w8AQc_^0ub-2joS2i5UtD5kXk=`n apO}(Tlv-S@msOmfr>q3lQwtf+Fh<`7;fNfkizyZ**Gdnws zZ?h<3^2k;ZJ8505I2Ygfr8qTQy)?(sD#o|*#CnVyjbd6Mb*&- zv8y)I-S@uQKJiXgvVaJ-NuC_7te<)>azo3L)`31Yn`9B<8^J7t7z`^dXvnjm*dh5k zlnBePaHC}Qy+_f-!cr{VL`CQczIJ&r9`BQ?gQs267Y>s=*{sSfwZxB&w8AQc_^0ub-2joS2i5UtD5kXk=`n apO}(Tlv-S@msOmfr>q3lQwt + + + + null + true + false + {(const Ch*)data_.ss.str,na} + {(const Ch*)((size_t)data_.s.str & 0x0000FFFFFFFFFFFF),[data_.s.length]na} + {data_.n.i.i} + {data_.n.u.u} + {data_.n.i64} + {data_.n.u64} + {data_.n.d} + Object members={data_.o.size} + Array members={data_.a.size} + + data_.o.size + data_.o.capacity + + data_.o.size + + (rapidjson::GenericMember<$T1,$T2>*)(((size_t)data_.o.members) & 0x0000FFFFFFFFFFFF) + + + data_.a.size + data_.a.capacity + + data_.a.size + + (rapidjson::GenericValue<$T1,$T2>*)(((size_t)data_.a.elements) & 0x0000FFFFFFFFFFFF) + + + + + + + diff --git a/deps/rapidjson/doc/CMakeLists.txt b/deps/rapidjson/doc/CMakeLists.txt new file mode 100644 index 0000000..c5345ba --- /dev/null +++ b/deps/rapidjson/doc/CMakeLists.txt @@ -0,0 +1,27 @@ +find_package(Doxygen) + +IF(NOT DOXYGEN_FOUND) + MESSAGE(STATUS "No Doxygen found. Documentation won't be built") +ELSE() + file(GLOB SOURCES ${CMAKE_CURRENT_LIST_DIR}/../include/*) + file(GLOB MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../doc/*.md) + list(APPEND MARKDOWN_DOC ${CMAKE_CURRENT_LIST_DIR}/../readme.md) + + CONFIGURE_FILE(Doxyfile.in Doxyfile @ONLY) + CONFIGURE_FILE(Doxyfile.zh-cn.in Doxyfile.zh-cn @ONLY) + + file(GLOB DOXYFILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile*) + + add_custom_command(OUTPUT html + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.zh-cn + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/html + DEPENDS ${MARKDOWN_DOC} ${SOURCES} ${DOXYFILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../ + ) + + add_custom_target(doc ALL DEPENDS html) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html + DESTINATION ${DOC_INSTALL_DIR} + COMPONENT doc) +ENDIF() diff --git a/deps/rapidjson/doc/Doxyfile.in b/deps/rapidjson/doc/Doxyfile.in new file mode 100644 index 0000000..6e79f93 --- /dev/null +++ b/deps/rapidjson/doc/Doxyfile.in @@ -0,0 +1,2369 @@ +# Doxyfile 1.8.7 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = RapidJSON + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "A fast JSON parser/generator for C++ with both SAX/DOM style API" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = YES + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = $(RAPIDJSON_SECTIONS) + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = readme.md \ + CHANGELOG.md \ + include/rapidjson/rapidjson.h \ + include/ \ + doc/features.md \ + doc/tutorial.md \ + doc/pointer.md \ + doc/stream.md \ + doc/encoding.md \ + doc/dom.md \ + doc/sax.md \ + doc/schema.md \ + doc/performance.md \ + doc/internals.md \ + doc/faq.md + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.inc \ + *.md + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ./include/rapidjson/msinttypes/ + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = internal + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = ./doc + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = readme.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = ./doc/misc/header.html + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = ./doc/misc/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = ./doc/misc/doxygenextra.css + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = YES + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /}", fillcolor=5] + helloworld [label="{string|}", fillcolor=5] + stars [label="{string|}", fillcolor=5] + ten [label="{number|10}", fillcolor=6] + } + } + + oldjson -> root [label=" ParseInsitu()" lhead="cluster1"] + edge [arrowhead=vee] + root -> { msg; stars } + + edge [arrowhead="none"] + msg -> helloworld + stars -> ten + + { + edge [arrowhead=vee, arrowtail=dot, arrowsize=0.5, dir=both, tailclip=false] + msg:a:c -> newjson:a + helloworld:a:c -> newjson:b + stars:a:c -> newjson:c + } + + //oldjson -> newjson [style=invis] +} \ No newline at end of file diff --git a/deps/rapidjson/doc/diagram/insituparsing.png b/deps/rapidjson/doc/diagram/insituparsing.png new file mode 100644 index 0000000000000000000000000000000000000000..4400c88466a8fb5ec0774b72acd52bf41c670c6e GIT binary patch literal 37281 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 F0sxnWX08AL literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/iterative-parser-states-diagram.dot b/deps/rapidjson/doc/diagram/iterative-parser-states-diagram.dot new file mode 100644 index 0000000..82ebfe1 --- /dev/null +++ b/deps/rapidjson/doc/diagram/iterative-parser-states-diagram.dot @@ -0,0 +1,62 @@ +digraph { + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + penwidth=0.0 + + node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + edge [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + + node [shape = doublecircle]; Start; Finish; + node [shape = box; style = "rounded, filled"; fillcolor=white ]; + + Start -> ArrayInitial [label=" ["]; + Start -> ObjectInitial [label=" {"]; + + subgraph clusterArray { + margin="10,10" + style=filled + fillcolor=gray95 + label = "Array" + + ArrayInitial; Element; ElementDelimiter; ArrayFinish; + } + + subgraph clusterObject { + margin="10,10" + style=filled + fillcolor=gray95 + label = "Object" + + ObjectInitial; MemberKey; KeyValueDelimiter; MemberValue; MemberDelimiter; ObjectFinish; + } + + ArrayInitial -> ArrayInitial [label="["]; + ArrayInitial -> ArrayFinish [label=" ]"]; + ArrayInitial -> ObjectInitial [label="{", constraint=false]; + ArrayInitial -> Element [label="string\nfalse\ntrue\nnull\nnumber"]; + + Element -> ArrayFinish [label="]"]; + Element -> ElementDelimiter [label=","]; + + ElementDelimiter -> ArrayInitial [label=" ["]; + ElementDelimiter -> ObjectInitial [label="{"]; + ElementDelimiter -> Element [label="string\nfalse\ntrue\nnull\nnumber"]; + + ObjectInitial -> ObjectFinish [label=" }"]; + ObjectInitial -> MemberKey [label=" string "]; + + MemberKey -> KeyValueDelimiter [label=":"]; + + KeyValueDelimiter -> ArrayInitial [label="["]; + KeyValueDelimiter -> ObjectInitial [label=" {"]; + KeyValueDelimiter -> MemberValue [label=" string\n false\n true\n null\n number"]; + + MemberValue -> ObjectFinish [label="}"]; + MemberValue -> MemberDelimiter [label=","]; + + MemberDelimiter -> MemberKey [label=" string "]; + + ArrayFinish -> Finish; + ObjectFinish -> Finish; +} diff --git a/deps/rapidjson/doc/diagram/iterative-parser-states-diagram.png b/deps/rapidjson/doc/diagram/iterative-parser-states-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..f315494db1d7b3a91ffef5eb395c0fc67e462d4c GIT binary patch literal 92378 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 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/move1.dot b/deps/rapidjson/doc/diagram/move1.dot new file mode 100644 index 0000000..a7c1464 --- /dev/null +++ b/deps/rapidjson/doc/diagram/move1.dot @@ -0,0 +1,47 @@ +digraph { + compound=true + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + ranksep=0.2 + penwidth=0.5 + + node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] + + subgraph cluster1 { + margin="10,10" + labeljust="left" + label = "Before" + style=filled + fillcolor=gray95 + + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + { + rank = same + b1 [label="{b:number|456}", fillcolor=6] + a1 [label="{a:number|123}", fillcolor=6] + } + + a1 -> b1 [style="dashed", label="Move", dir=back] + } + + subgraph cluster2 { + margin="10,10" + labeljust="left" + label = "After" + style=filled + fillcolor=gray95 + + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + { + rank = same + b2 [label="{b:null|}", fillcolor=1] + a2 [label="{a:number|456}", fillcolor=6] + } + a2 -> b2 [style=invis, dir=back] + } + b1 -> b2 [style=invis] +} \ No newline at end of file diff --git a/deps/rapidjson/doc/diagram/move1.png b/deps/rapidjson/doc/diagram/move1.png new file mode 100644 index 0000000000000000000000000000000000000000..ab322d084bd6d819fdb93a014d19e5fbf6e2b2b0 GIT binary patch literal 16081 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 aKn%h5W>`e-p#nYXpQObV#HvLM1OEpM8uU{D literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/move2.dot b/deps/rapidjson/doc/diagram/move2.dot new file mode 100644 index 0000000..2319871 --- /dev/null +++ b/deps/rapidjson/doc/diagram/move2.dot @@ -0,0 +1,62 @@ +digraph { + compound=true + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + ranksep=0.2 + penwidth=0.5 + + node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] + + subgraph cluster1 { + margin="10,10" + labeljust="left" + label = "Before Copying (Hypothetic)" + style=filled + fillcolor=gray95 + + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + c1 [label="{contacts:array|}", fillcolor=4] + c11 [label="{|}"] + c12 [label="{|}"] + c13 [shape="none", label="...", style="solid"] + o1 [label="{o:object|}", fillcolor=3] + ghost [label="{o:object|}", style=invis] + + c1 -> o1 [style="dashed", label="AddMember", constraint=false] + + edge [arrowhead=vee] + c1 -> { c11; c12; c13 } + o1 -> ghost [style=invis] + } + + subgraph cluster2 { + margin="10,10" + labeljust="left" + label = "After Copying (Hypothetic)" + style=filled + fillcolor=gray95 + + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + c2 [label="{contacts:array|}", fillcolor=4] + c3 [label="{array|}", fillcolor=4] + c21 [label="{|}"] + c22 [label="{|}"] + c23 [shape=none, label="...", style="solid"] + o2 [label="{o:object|}", fillcolor=3] + cs [label="{string|\"contacts\"}", fillcolor=5] + c31 [label="{|}"] + c32 [label="{|}"] + c33 [shape="none", label="...", style="solid"] + + edge [arrowhead=vee] + c2 -> { c21; c22; c23 } + o2 -> cs + cs -> c3 [arrowhead=none] + c3 -> { c31; c32; c33 } + } + ghost -> o2 [style=invis] +} diff --git a/deps/rapidjson/doc/diagram/move2.png b/deps/rapidjson/doc/diagram/move2.png new file mode 100644 index 0000000000000000000000000000000000000000..8d4fc5bcc2223e127f672666b8eddbce4020e01c GIT binary patch literal 41517 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 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/move3.dot b/deps/rapidjson/doc/diagram/move3.dot new file mode 100644 index 0000000..57adb4f --- /dev/null +++ b/deps/rapidjson/doc/diagram/move3.dot @@ -0,0 +1,60 @@ +digraph { + compound=true + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + ranksep=0.2 + penwidth=0.5 + forcelabels=true + + node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] + + subgraph cluster1 { + margin="10,10" + labeljust="left" + label = "Before Moving" + style=filled + fillcolor=gray95 + + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + c1 [label="{contacts:array|}", fillcolor=4] + c11 [label="{|}"] + c12 [label="{|}"] + c13 [shape=none, label="...", style="solid"] + o1 [label="{o:object|}", fillcolor=3] + ghost [label="{o:object|}", style=invis] + + c1 -> o1 [style="dashed", constraint=false, label="AddMember"] + + edge [arrowhead=vee] + c1 -> { c11; c12; c13 } + o1 -> ghost [style=invis] + } + + subgraph cluster2 { + margin="10,10" + labeljust="left" + label = "After Moving" + style=filled + fillcolor=gray95 + + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + c2 [label="{contacts:null|}", fillcolor=1] + c3 [label="{array|}", fillcolor=4] + c21 [label="{|}"] + c22 [label="{|}"] + c23 [shape="none", label="...", style="solid"] + o2 [label="{o:object|}", fillcolor=3] + cs [label="{string|\"contacts\"}", fillcolor=5] + c2 -> o2 [style="dashed", constraint=false, label="AddMember", style=invis] + + edge [arrowhead=vee] + c3 -> { c21; c22; c23 } + o2 -> cs + cs -> c3 [arrowhead=none] + } + ghost -> o2 [style=invis] +} diff --git a/deps/rapidjson/doc/diagram/move3.png b/deps/rapidjson/doc/diagram/move3.png new file mode 100644 index 0000000000000000000000000000000000000000..558470f1fab8390faa35fca1ef85c0e7f048d3c4 GIT binary patch literal 36371 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 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/normalparsing.dot b/deps/rapidjson/doc/diagram/normalparsing.dot new file mode 100644 index 0000000..b15941b --- /dev/null +++ b/deps/rapidjson/doc/diagram/normalparsing.dot @@ -0,0 +1,56 @@ +digraph { + compound=true + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + ranksep=0.2 + penwidth=0.5 + + node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] + + { + node [shape=record, fontsize="8", margin="0.04", height=0.2, color=gray] + normaljson [label="\{|\"|m|s|g|\"|:|\"|H|e|l|l|o|\\|n|W|o|r|l|d|!|\"|,|\"|\\|u|0|0|7|3|t|a|r|s\"|:|1|0|\}"] + + { + rank = same + msgstring [label="m|s|g|\\0"] + helloworldstring [label="H|e|l|l|o|\\n|W|o|r|l|d|!|\\0"] + starsstring [label="s|t|a|r|s\\0"] + } + } + + subgraph cluster1 { + margin="10,10" + labeljust="left" + label = "Document by Normal Parsing" + style=filled + fillcolor=gray95 + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + root [label="{object|}", fillcolor=3] + + { + msg [label="{string|}", fillcolor=5] + helloworld [label="{string|}", fillcolor=5] + stars [label="{string|}", fillcolor=5] + ten [label="{number|10}", fillcolor=6] + } + } + + normaljson -> root [label=" Parse()" lhead="cluster1"] + edge [arrowhead=vee] + root -> { msg; stars } + + edge [arrowhead="none"] + msg -> helloworld + stars -> ten + + edge [arrowhead=vee, arrowtail=dot, arrowsize=0.5, dir=both, tailclip=false] + msg:a:c -> msgstring:w + helloworld:a:c -> helloworldstring:w + stars:a:c -> starsstring:w + + msgstring -> helloworldstring -> starsstring [style=invis] +} \ No newline at end of file diff --git a/deps/rapidjson/doc/diagram/normalparsing.png b/deps/rapidjson/doc/diagram/normalparsing.png new file mode 100644 index 0000000000000000000000000000000000000000..702512ca3678f62f4a35100953d2dad02fc84fab GIT binary patch literal 32887 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 PMX$b!NDG$;>iYgK0)w4D literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/simpledom.dot b/deps/rapidjson/doc/diagram/simpledom.dot new file mode 100644 index 0000000..959cdbb --- /dev/null +++ b/deps/rapidjson/doc/diagram/simpledom.dot @@ -0,0 +1,54 @@ +digraph { + compound=true + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + ranksep=0.2 + penwidth=0.5 + + node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + edge [fontname="Inconsolata, Consolas", fontsize=10, arrowhead=normal] + + { + node [shape=record, fontsize="8", margin="0.04", height=0.2, color=gray] + srcjson [label="\{|\"|p|r|o|j|e|c|t|\"|:|\"|r|a|p|i|d|j|s|o|n|\"|,|\"|s|t|a|r|s|\"|:|1|0|\}"] + dstjson [label="\{|\"|p|r|o|j|e|c|t|\"|:|\"|r|a|p|i|d|j|s|o|n|\"|,|\"|s|t|a|r|s|\"|:|1|1|\}"] + } + + { + node [shape="box", style="filled", fillcolor="gray95"] + Document2 [label="(Modified) Document"] + Writer + } + + subgraph cluster1 { + margin="10,10" + labeljust="left" + label = "Document" + style=filled + fillcolor=gray95 + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + root [label="{object|}", fillcolor=3] + + { + project [label="{string|\"project\"}", fillcolor=5] + rapidjson [label="{string|\"rapidjson\"}", fillcolor=5] + stars [label="{string|\"stars\"}", fillcolor=5] + ten [label="{number|10}", fillcolor=6] + } + + edge [arrowhead=vee] + root -> { project; stars } + + edge [arrowhead="none"] + project -> rapidjson + stars -> ten + } + + srcjson -> root [label=" Parse()", lhead="cluster1"] + + ten -> Document2 [label=" Increase \"stars\"", ltail="cluster1" ] + Document2 -> Writer [label=" Traverse DOM by Accept()"] + Writer -> dstjson [label=" Output to StringBuffer"] +} \ No newline at end of file diff --git a/deps/rapidjson/doc/diagram/simpledom.png b/deps/rapidjson/doc/diagram/simpledom.png new file mode 100644 index 0000000000000000000000000000000000000000..38d9c5dc126f9f28e799b877cb4737cdfebd787e GIT binary patch literal 43670 zcmce;RaBf^v@9A39^5UsySpX0ySux4B@ytXWlab|RD%B#{vC5#GIfha@c}rth=n`o(RMZk2Yp_qk8h-(d6r?pp5bFII!7Bmtj!WlaL#uZm_3yRG@htB3rIl9p zD+{i%543^rF^nMP0^wO8sNy%Evf1?BYy3C(4we260~P8Q&DGcc{si76LJkaVi%GSR zsQ%|AyW|J_|NV468srifytUkHt91DH=6H#nhnF{^x5=zT;O_cBwXLnKSit_WGt+k} zPgv5#ge*HJM}Cx3PUK;qS+|9w9+zq$iCXc`;bG=+b|SOQA?cW`loTqT`ADL;komQ0 zwJ+z55`EUS#xjh}p_P_5r#bGfst!&^ERESj<~&R1i0P>0iFhxP>Zb~(P?x!;EMp

    d-WmRivHS`b^sdFqpGs`!Rk@*~d`T6-k9)`sUj$ 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 z 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 bNY2eb)1a^t{00J^Q}CyurmI?}Y!&=Jjhtmx literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/tutorial.dot b/deps/rapidjson/doc/diagram/tutorial.dot new file mode 100644 index 0000000..138ddc3 --- /dev/null +++ b/deps/rapidjson/doc/diagram/tutorial.dot @@ -0,0 +1,58 @@ +digraph { + compound=true + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + ranksep=0.2 + penwidth=0.5 + + node [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + edge [fontname="Inconsolata, Consolas", fontsize=10] + + subgraph cluster1 { + margin="10,10" + labeljust="left" + label = "Document" + style=filled + fillcolor=gray95 + node [shape=Mrecord, style=filled, colorscheme=spectral7] + + root [label="{object|}", fillcolor=3] + + { + hello [label="{string|\"hello\"}", fillcolor=5] + t [label="{string|\"t\"}", fillcolor=5] + f [label="{string|\"f\"}", fillcolor=5] + n [label="{string|\"n\"}", fillcolor=5] + i [label="{string|\"i\"}", fillcolor=5] + pi [label="{string|\"pi\"}", fillcolor=5] + a [label="{string|\"a\"}", fillcolor=5] + + world [label="{string|\"world\"}", fillcolor=5] + true [label="{true|}", fillcolor=7] + false [label="{false|}", fillcolor=2] + null [label="{null|}", fillcolor=1] + i1 [label="{number|123}", fillcolor=6] + pi1 [label="{number|3.1416}", fillcolor=6] + array [label="{array|size=4}", fillcolor=4] + + a1 [label="{number|1}", fillcolor=6] + a2 [label="{number|2}", fillcolor=6] + a3 [label="{number|3}", fillcolor=6] + a4 [label="{number|4}", fillcolor=6] + } + + edge [arrowhead=vee] + root -> { hello; t; f; n; i; pi; a } + array -> { a1; a2; a3; a4 } + + edge [arrowhead=none] + hello -> world + t -> true + f -> false + n -> null + i -> i1 + pi -> pi1 + a -> array + } +} \ No newline at end of file diff --git a/deps/rapidjson/doc/diagram/tutorial.png b/deps/rapidjson/doc/diagram/tutorial.png new file mode 100644 index 0000000000000000000000000000000000000000..8a12924acdd72a9c1b99c0a48a201b936f3557f4 GIT binary patch literal 44634 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 literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/diagram/utilityclass.dot b/deps/rapidjson/doc/diagram/utilityclass.dot new file mode 100644 index 0000000..1492a8a --- /dev/null +++ b/deps/rapidjson/doc/diagram/utilityclass.dot @@ -0,0 +1,73 @@ +digraph { + rankdir=LR + compound=true + fontname="Inconsolata, Consolas" + fontsize=10 + margin="0,0" + ranksep=0.3 + nodesep=0.15 + penwidth=0.5 + colorscheme=spectral7 + + node [shape=box, fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5, style=filled, fillcolor=white] + edge [fontname="Inconsolata, Consolas", fontsize=10, penwidth=0.5] + + subgraph cluster0 { + style=filled + fillcolor=4 + + Encoding [label="<>\nEncoding"] + + edge [arrowtail=onormal, dir=back] + Encoding -> { UTF8; UTF16; UTF32; ASCII; AutoUTF } + UTF16 -> { UTF16LE; UTF16BE } + UTF32 -> { UTF32LE; UTF32BE } + } + + subgraph cluster1 { + style=filled + fillcolor=5 + + Stream [label="<>\nStream"] + InputByteStream [label="<>\nInputByteStream"] + OutputByteStream [label="<>\nOutputByteStream"] + + edge [arrowtail=onormal, dir=back] + Stream -> { + StringStream; InsituStringStream; StringBuffer; + EncodedInputStream; EncodedOutputStream; + AutoUTFInputStream; AutoUTFOutputStream + InputByteStream; OutputByteStream + } + + InputByteStream -> { MemoryStream; FlieReadStream } + OutputByteStream -> { MemoryBuffer; FileWriteStream } + } + + subgraph cluster2 { + style=filled + fillcolor=3 + + Allocator [label="<>\nAllocator"] + + edge [arrowtail=onormal, dir=back] + Allocator -> { CrtAllocator; MemoryPoolAllocator } + } + + { + edge [arrowtail=odiamond, arrowhead=vee, dir=both] + EncodedInputStream -> InputByteStream + EncodedOutputStream -> OutputByteStream + AutoUTFInputStream -> InputByteStream + AutoUTFOutputStream -> OutputByteStream + MemoryPoolAllocator -> Allocator [label="base", tailport=s] + } + + { + edge [arrowhead=vee, style=dashed] + AutoUTFInputStream -> AutoUTF + AutoUTFOutputStream -> AutoUTF + } + + //UTF32LE -> Stream [style=invis] +} \ No newline at end of file diff --git a/deps/rapidjson/doc/diagram/utilityclass.png b/deps/rapidjson/doc/diagram/utilityclass.png new file mode 100644 index 0000000000000000000000000000000000000000..ce029a4d0670e0a358e3bdb8c030083f67b1ffcd GIT binary patch literal 99993 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 JR@TJ(e*o()o2UQ) literal 0 HcmV?d00001 diff --git a/deps/rapidjson/doc/dom.md b/deps/rapidjson/doc/dom.md new file mode 100644 index 0000000..6992e77 --- /dev/null +++ b/deps/rapidjson/doc/dom.md @@ -0,0 +1,281 @@ +# DOM + +Document Object Model(DOM) is an in-memory representation of JSON for query and manipulation. The basic usage of DOM is described in [Tutorial](doc/tutorial.md). This section will describe some details and more advanced usages. + +[TOC] + +# Template {#Template} + +In the tutorial, `Value` and `Document` was used. Similarly to `std::string`, these are actually `typedef` of template classes: + +~~~~~~~~~~cpp +namespace rapidjson { + +template > +class GenericValue { + // ... +}; + +template > +class GenericDocument : public GenericValue { + // ... +}; + +typedef GenericValue > Value; +typedef GenericDocument > Document; + +} // namespace rapidjson +~~~~~~~~~~ + +User can customize these template parameters. + +## Encoding {#Encoding} + +The `Encoding` parameter specifies the encoding of JSON String value in memory. Possible options are `UTF8`, `UTF16`, `UTF32`. Note that, these 3 types are also template class. `UTF8<>` is `UTF8`, which means using char to store the characters. You may refer to [Encoding](doc/encoding.md) for details. + +Suppose a Windows application would query localization strings stored in JSON files. Unicode-enabled functions in Windows use UTF-16 (wide character) encoding. No matter what encoding was used in JSON files, we can store the strings in UTF-16 in memory. + +~~~~~~~~~~cpp +using namespace rapidjson; + +typedef GenericDocument > WDocument; +typedef GenericValue > WValue; + +FILE* fp = fopen("localization.json", "rb"); // non-Windows use "r" + +char readBuffer[256]; +FileReadStream bis(fp, readBuffer, sizeof(readBuffer)); + +AutoUTFInputStream eis(bis); // wraps bis into eis + +WDocument d; +d.ParseStream<0, AutoUTF >(eis); + +const WValue locale(L"ja"); // Japanese + +MessageBoxW(hWnd, d[locale].GetString(), L"Test", MB_OK); +~~~~~~~~~~ + +## Allocator {#Allocator} + +The `Allocator` defines which allocator class is used when allocating/deallocating memory for `Document`/`Value`. `Document` owns, or references to an `Allocator` instance. On the other hand, `Value` does not do so, in order to reduce memory consumption. + +The default allocator used in `GenericDocument` is `MemoryPoolAllocator`. This allocator actually allocate memory sequentially, and cannot deallocate one by one. This is very suitable when parsing a JSON into a DOM tree. + +Another allocator is `CrtAllocator`, of which CRT is short for C RunTime library. This allocator simply calls the standard `malloc()`/`realloc()`/`free()`. When there is a lot of add and remove operations, this allocator may be preferred. But this allocator is far less efficient than `MemoryPoolAllocator`. + +# Parsing {#Parsing} + +`Document` provides several functions for parsing. In below, (1) is the fundamental function, while the others are helpers which call (1). + +~~~~~~~~~~cpp +using namespace rapidjson; + +// (1) Fundamental +template +GenericDocument& GenericDocument::ParseStream(InputStream& is); + +// (2) Using the same Encoding for stream +template +GenericDocument& GenericDocument::ParseStream(InputStream& is); + +// (3) Using default parse flags +template +GenericDocument& GenericDocument::ParseStream(InputStream& is); + +// (4) In situ parsing +template +GenericDocument& GenericDocument::ParseInsitu(Ch* str); + +// (5) In situ parsing, using default parse flags +GenericDocument& GenericDocument::ParseInsitu(Ch* str); + +// (6) Normal parsing of a string +template +GenericDocument& GenericDocument::Parse(const Ch* str); + +// (7) Normal parsing of a string, using same Encoding of Document +template +GenericDocument& GenericDocument::Parse(const Ch* str); + +// (8) Normal parsing of a string, using default parse flags +GenericDocument& GenericDocument::Parse(const Ch* str); +~~~~~~~~~~ + +The examples of [tutorial](doc/tutorial.md) uses (8) for normal parsing of string. The examples of [stream](doc/stream.md) uses the first three. *In situ* parsing will be described soon. + +The `parseFlags` are combination of the following bit-flags: + +Parse flags | Meaning +------------------------------|----------------------------------- +`kParseNoFlags` | No flag is set. +`kParseDefaultFlags` | Default parse flags. It is equal to macro `RAPIDJSON_PARSE_DEFAULT_FLAGS`, which is defined as `kParseNoFlags`. +`kParseInsituFlag` | In-situ(destructive) parsing. +`kParseValidateEncodingFlag` | Validate encoding of JSON strings. +`kParseIterativeFlag` | Iterative(constant complexity in terms of function call stack size) parsing. +`kParseStopWhenDoneFlag` | After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate `kParseErrorDocumentRootNotSingular` error. Using this flag for parsing multiple JSONs in the same stream. +`kParseFullPrecisionFlag` | Parse number in full precision (slower). If this flag is not set, the normal precision (faster) is used. Normal precision has maximum 3 [ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place) error. +`kParseCommentsFlag` | Allow one-line `// ...` and multi-line `/* ... */` comments (relaxed JSON syntax). +`kParseNumbersAsStringsFlag` | Parse numerical type values as strings. +`kParseTrailingCommasFlag` | Allow trailing commas at the end of objects and arrays (relaxed JSON syntax). +`kParseNanAndInfFlag` | Allow parsing `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (relaxed JSON syntax). +`kParseEscapedApostropheFlag` | Allow escaped apostrophe `\'` in strings (relaxed JSON syntax). + +By using a non-type template parameter, instead of a function parameter, C++ compiler can generate code which is optimized for specified combinations, improving speed, and reducing code size (if only using a single specialization). The downside is the flags needed to be determined in compile-time. + +The `SourceEncoding` parameter defines what encoding is in the stream. This can be differed to the `Encoding` of the `Document`. See [Transcoding and Validation](#TranscodingAndValidation) section for details. + +And the `InputStream` is type of input stream. + +## Parse Error {#ParseError} + +When the parse processing succeeded, the `Document` contains the parse results. When there is an error, the original DOM is *unchanged*. And the error state of parsing can be obtained by `bool HasParseError()`, `ParseErrorCode GetParseError()` and `size_t GetErrorOffset()`. + +Parse Error Code | Description +--------------------------------------------|--------------------------------------------------- +`kParseErrorNone` | No error. +`kParseErrorDocumentEmpty` | The document is empty. +`kParseErrorDocumentRootNotSingular` | The document root must not follow by other values. +`kParseErrorValueInvalid` | Invalid value. +`kParseErrorObjectMissName` | Missing a name for object member. +`kParseErrorObjectMissColon` | Missing a colon after a name of object member. +`kParseErrorObjectMissCommaOrCurlyBracket` | Missing a comma or `}` after an object member. +`kParseErrorArrayMissCommaOrSquareBracket` | Missing a comma or `]` after an array element. +`kParseErrorStringUnicodeEscapeInvalidHex` | Incorrect hex digit after `\\u` escape in string. +`kParseErrorStringUnicodeSurrogateInvalid` | The surrogate pair in string is invalid. +`kParseErrorStringEscapeInvalid` | Invalid escape character in string. +`kParseErrorStringMissQuotationMark` | Missing a closing quotation mark in string. +`kParseErrorStringInvalidEncoding` | Invalid encoding in string. +`kParseErrorNumberTooBig` | Number too big to be stored in `double`. +`kParseErrorNumberMissFraction` | Miss fraction part in number. +`kParseErrorNumberMissExponent` | Miss exponent in number. + +The offset of error is defined as the character number from beginning of stream. Currently RapidJSON does not keep track of line number. + +To get an error message, RapidJSON provided a English messages in `rapidjson/error/en.h`. User can customize it for other locales, or use a custom localization system. + +Here shows an example of parse error handling. + +~~~~~~~~~~cpp +#include "rapidjson/document.h" +#include "rapidjson/error/en.h" + +// ... +Document d; +if (d.Parse(json).HasParseError()) { + fprintf(stderr, "\nError(offset %u): %s\n", + (unsigned)d.GetErrorOffset(), + GetParseError_En(d.GetParseError())); + // ... +} +~~~~~~~~~~ + +## In Situ Parsing {#InSituParsing} + +From [Wikipedia](http://en.wikipedia.org/wiki/In_situ): + +> *In situ* ... is a Latin phrase that translates literally to "on site" or "in position". It means "locally", "on site", "on the premises" or "in place" to describe an event where it takes place, and is used in many different contexts. +> ... +> (In computer science) An algorithm is said to be an in situ algorithm, or in-place algorithm, if the extra amount of memory required to execute the algorithm is O(1), that is, does not exceed a constant no matter how large the input. For example, heapsort is an in situ sorting algorithm. + +In normal parsing process, a large overhead is to decode JSON strings and copy them to other buffers. *In situ* parsing decodes those JSON string at the place where it is stored. It is possible in JSON because the length of decoded string is always shorter than or equal to the one in JSON. In this context, decoding a JSON string means to process the escapes, such as `"\n"`, `"\u1234"`, etc., and add a null terminator (`'\0'`)at the end of string. + +The following diagrams compare normal and *in situ* parsing. The JSON string values contain pointers to the decoded string. + +![normal parsing](diagram/normalparsing.png) + +In normal parsing, the decoded string are copied to freshly allocated buffers. `"\\n"` (2 characters) is decoded as `"\n"` (1 character). `"\\u0073"` (6 characters) is decoded as `"s"` (1 character). + +![instiu parsing](diagram/insituparsing.png) + +*In situ* parsing just modified the original JSON. Updated characters are highlighted in the diagram. If the JSON string does not contain escape character, such as `"msg"`, the parsing process merely replace the closing double quotation mark with a null character. + +Since *in situ* parsing modify the input, the parsing API needs `char*` instead of `const char*`. + +~~~~~~~~~~cpp +// Read whole file into a buffer +FILE* fp = fopen("test.json", "r"); +fseek(fp, 0, SEEK_END); +size_t filesize = (size_t)ftell(fp); +fseek(fp, 0, SEEK_SET); +char* buffer = (char*)malloc(filesize + 1); +size_t readLength = fread(buffer, 1, filesize, fp); +buffer[readLength] = '\0'; +fclose(fp); + +// In situ parsing the buffer into d, buffer will also be modified +Document d; +d.ParseInsitu(buffer); + +// Query/manipulate the DOM here... + +free(buffer); +// Note: At this point, d may have dangling pointers pointed to the deallocated buffer. +~~~~~~~~~~ + +The JSON strings are marked as const-string. But they may not be really "constant". The life cycle of it depends on the JSON buffer. + +In situ parsing minimizes allocation overheads and memory copying. Generally this improves cache coherence, which is an important factor of performance in modern computer. + +There are some limitations of *in situ* parsing: + +1. The whole JSON is in memory. +2. The source encoding in stream and target encoding in document must be the same. +3. The buffer need to be retained until the document is no longer used. +4. If the DOM need to be used for long period after parsing, and there are few JSON strings in the DOM, retaining the buffer may be a memory waste. + +*In situ* parsing is mostly suitable for short-term JSON that only need to be processed once, and then be released from memory. In practice, these situation is very common, for example, deserializing JSON to C++ objects, processing web requests represented in JSON, etc. + +## Transcoding and Validation {#TranscodingAndValidation} + +RapidJSON supports conversion between Unicode formats (officially termed UCS Transformation Format) internally. During DOM parsing, the source encoding of the stream can be different from the encoding of the DOM. For example, the source stream contains a UTF-8 JSON, while the DOM is using UTF-16 encoding. There is an example code in [EncodedInputStream](doc/stream.md). + +When writing a JSON from DOM to output stream, transcoding can also be used. An example is in [EncodedOutputStream](doc/stream.md). + +During transcoding, the source string is decoded to into Unicode code points, and then the code points are encoded in the target format. During decoding, it will validate the byte sequence in the source string. If it is not a valid sequence, the parser will be stopped with `kParseErrorStringInvalidEncoding` error. + +When the source encoding of stream is the same as encoding of DOM, by default, the parser will *not* validate the sequence. User may use `kParseValidateEncodingFlag` to force validation. + +# Techniques {#Techniques} + +Some techniques about using DOM API is discussed here. + +## DOM as SAX Event Publisher + +In RapidJSON, stringifying a DOM with `Writer` may be look a little bit weird. + +~~~~~~~~~~cpp +// ... +Writer writer(buffer); +d.Accept(writer); +~~~~~~~~~~ + +Actually, `Value::Accept()` is responsible for publishing SAX events about the value to the handler. With this design, `Value` and `Writer` are decoupled. `Value` can generate SAX events, and `Writer` can handle those events. + +User may create custom handlers for transforming the DOM into other formats. For example, a handler which converts the DOM into XML. + +For more about SAX events and handler, please refer to [SAX](doc/sax.md). + +## User Buffer {#UserBuffer} + +Some applications may try to avoid memory allocations whenever possible. + +`MemoryPoolAllocator` can support this by letting user to provide a buffer. The buffer can be on the program stack, or a "scratch buffer" which is statically allocated (a static/global array) for storing temporary data. + +`MemoryPoolAllocator` will use the user buffer to satisfy allocations. When the user buffer is used up, it will allocate a chunk of memory from the base allocator (by default the `CrtAllocator`). + +Here is an example of using stack memory. The first allocator is for storing values, while the second allocator is for storing temporary data during parsing. + +~~~~~~~~~~cpp +typedef GenericDocument, MemoryPoolAllocator<>, MemoryPoolAllocator<>> DocumentType; +char valueBuffer[4096]; +char parseBuffer[1024]; +MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer)); +MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer)); +DocumentType d(&valueAllocator, sizeof(parseBuffer), &parseAllocator); +d.Parse(json); +~~~~~~~~~~ + +If the total size of allocation is less than 4096+1024 bytes during parsing, this code does not invoke any heap allocation (via `new` or `malloc()`) at all. + +User can query the current memory consumption in bytes via `MemoryPoolAllocator::Size()`. And then user can determine a suitable size of user buffer. diff --git a/deps/rapidjson/doc/dom.zh-cn.md b/deps/rapidjson/doc/dom.zh-cn.md new file mode 100644 index 0000000..7a555dc --- /dev/null +++ b/deps/rapidjson/doc/dom.zh-cn.md @@ -0,0 +1,285 @@ +# DOM + +文档对象模型(Document Object Model, DOM)是一ç§ç½äºŽå†…存中的 JSON 表示方å¼ï¼Œä»¥ä¾›æŸ¥è¯¢åŠæ“作。我们已于 [教程](doc/tutorial.zh-cn.md) 中介ç»äº† DOM 的基本用法,本节将讲述一些细节åŠé«˜çº§ç”¨æ³•ã€‚ + +[TOC] + +# æ¨¡æ¿ {#Template} + +教程中使用了 `Value` å’Œ `Document` 类型。与 `std::string` 相似,这些类型其实是两个模æ¿ç±»çš„ `typedef`: + +~~~~~~~~~~cpp +namespace rapidjson { + +template > +class GenericValue { + // ... +}; + +template > +class GenericDocument : public GenericValue { + // ... +}; + +typedef GenericValue > Value; +typedef GenericDocument > Document; + +} // namespace rapidjson +~~~~~~~~~~ + +使用者å¯ä»¥è‡ªå®šä¹‰è¿™äº›æ¨¡æ¿å‚数。 + +## ç¼–ç  {#Encoding} + +`Encoding` å‚数指明在内存中的 JSON String 使用哪ç§ç¼–ç ã€‚å¯è¡Œçš„选项有 `UTF8`ã€`UTF16`ã€`UTF32`。è¦æ³¨æ„è¿™ 3 个类型其实也是模æ¿ç±»ã€‚`UTF8<>` ç­‰åŒ `UTF8`,这代表它使用 `char` æ¥å­˜å‚¨å­—符串。更多细节å¯ä»¥å‚考 [ç¼–ç ](doc/encoding.zh-cn.md)。 + +这里是一个例å­ã€‚å‡è®¾ä¸€ä¸ª Windows 应用软件希望查询存储于 JSON 中的本地化字符串。Windows ä¸­å« Unicode 的函数使用 UTF-16(宽字符)编ç ã€‚无论 JSON 文件使用哪ç§ç¼–ç ï¼Œæˆ‘们都å¯ä»¥æŠŠå­—符串以 UTF-16 å½¢å¼å­˜å‚¨åœ¨å†…存。 + +~~~~~~~~~~cpp +using namespace rapidjson; + +typedef GenericDocument > WDocument; +typedef GenericValue > WValue; + +FILE* fp = fopen("localization.json", "rb"); // éž Windows å¹³å°ä½¿ç”¨ "r" + +char readBuffer[256]; +FileReadStream bis(fp, readBuffer, sizeof(readBuffer)); + +AutoUTFInputStream eis(bis); // 包装 bis æˆ eis + +WDocument d; +d.ParseStream<0, AutoUTF >(eis); + +const WValue locale(L"ja"); // Japanese + +MessageBoxW(hWnd, d[locale].GetString(), L"Test", MB_OK); +~~~~~~~~~~ + +## 分é…器 {#Allocator} + +`Allocator` 定义当 `Document`/`Value` 分é…或释放内存时使用那个分é…类。`Document` 拥有或引用到一个 `Allocator` 实例。而为了节çœå†…存,`Value` 没有这么åšã€‚ + +`GenericDocument` 的缺çœåˆ†é…器是 `MemoryPoolAllocator`。此分é…器实际上会顺åºåœ°åˆ†é…内存,并且ä¸èƒ½é€ä¸€é‡Šæ”¾ã€‚当è¦è§£æžä¸€ä¸ª JSON å¹¶ç”Ÿæˆ DOM,这ç§åˆ†é…器是éžå¸¸åˆé€‚的。 + +RapidJSON 还æä¾›å¦ä¸€ä¸ªåˆ†é…器 `CrtAllocator`,当中 CRT 是 C è¿è¡Œåº“(C RunTime library)的缩写。此分é…器简å•åœ°è¯»ç”¨æ ‡å‡†çš„ `malloc()`/`realloc()`/`free()`。当我们需è¦è®¸å¤šå¢žå‡æ“作,这ç§åˆ†é…器会更为适åˆã€‚然而这ç§åˆ†é…器远远比 `MemoryPoolAllocator` 低效。 + +# è§£æž {#Parsing} + +`Document` æ供几个解æžå‡½æ•°ã€‚以下的 (1) 是根本的函数,其他都是调用 (1) çš„å助函数。 + +~~~~~~~~~~cpp +using namespace rapidjson; + +// (1) 根本 +template +GenericDocument& GenericDocument::ParseStream(InputStream& is); + +// (2) 使用æµçš„ç¼–ç  +template +GenericDocument& GenericDocument::ParseStream(InputStream& is); + +// (3) 使用缺çœæ ‡å¿— +template +GenericDocument& GenericDocument::ParseStream(InputStream& is); + +// (4) 原ä½è§£æž +template +GenericDocument& GenericDocument::ParseInsitu(Ch* str); + +// (5) 原ä½è§£æžï¼Œä½¿ç”¨ç¼ºçœæ ‡å¿— +GenericDocument& GenericDocument::ParseInsitu(Ch* str); + +// (6) 正常解æžä¸€ä¸ªå­—符串 +template +GenericDocument& GenericDocument::Parse(const Ch* str); + +// (7) 正常解æžä¸€ä¸ªå­—符串,使用 Document çš„ç¼–ç  +template +GenericDocument& GenericDocument::Parse(const Ch* str); + +// (8) 正常解æžä¸€ä¸ªå­—符串,使用缺çœæ ‡å¿— +GenericDocument& GenericDocument::Parse(const Ch* str); +~~~~~~~~~~ + +[教程](doc/tutorial.zh-cn.md) 中的例使用 (8) 去正常解æžå­—符串。而 [æµ](doc/stream.zh-cn.md) 的例å­ä½¿ç”¨å‰ 3 个函数。我们将ç¨åŽä»‹ç»åŽŸä½ï¼ˆ*In situ*) 解æžã€‚ + +`parseFlags` 是以下ä½æ ‡ç½®çš„组åˆï¼š + +解æžä½æ ‡å¿— | æ„义 +------------------------------|----------------------------------- +`kParseNoFlags` | 没有任何标志。 +`kParseDefaultFlags` | 缺çœçš„解æžé€‰é¡¹ã€‚它等于 `RAPIDJSON_PARSE_DEFAULT_FLAGS` å®ï¼Œæ­¤å®å®šä¹‰ä¸º `kParseNoFlags`。 +`kParseInsituFlag` | 原ä½ï¼ˆç ´å性)解æžã€‚ +`kParseValidateEncodingFlag` | 校验 JSON 字符串的编ç ã€‚ +`kParseIterativeFlag` | 迭代å¼ï¼ˆè°ƒç”¨å †æ ˆå¤§å°ä¸ºå¸¸æ•°å¤æ‚度)解æžã€‚ +`kParseStopWhenDoneFlag` | 当从æµè§£æžäº†ä¸€ä¸ªå®Œæ•´çš„ JSON 根节点之åŽï¼Œåœæ­¢ç»§ç»­å¤„ç†ä½™ä¸‹çš„æµã€‚当使用了此标志,解æžå™¨ä¾¿ä¸ä¼šäº§ç”Ÿ `kParseErrorDocumentRootNotSingular` 错误。å¯ä½¿ç”¨æœ¬æ ‡å¿—去解æžåŒä¸€ä¸ªæµé‡Œçš„多个 JSON。 +`kParseFullPrecisionFlag` | 使用完整的精确度去解æžæ•°å­—(较慢)。如ä¸è®¾ç½®æ­¤æ ‡èŠ‚,则会使用正常的精确度(较快)。正常精确度会有最多 3 个 [ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place) 的误差。 +`kParseCommentsFlag` | 容许å•è¡Œ `// ...` åŠå¤šè¡Œ `/* ... */` 注释(放宽的 JSON 语法)。 +`kParseNumbersAsStringsFlag` | 把数字类型解æžæˆå­—符串。 +`kParseTrailingCommasFlag` | 容许在对象和数组结æŸå‰å«æœ‰é€—å·ï¼ˆæ”¾å®½çš„ JSON 语法)。 +`kParseNanAndInfFlag` | 容许 `NaN`ã€`Inf`ã€`Infinity`ã€`-Inf` åŠ `-Infinity` 作为 `double` 值(放宽的 JSON 语法)。 +`kParseEscapedApostropheFlag` | 容许字符串中转义å•å¼•å· `\'` (放宽的 JSON 语法)。 + +由于使用了éžç±»åž‹æ¨¡æ¿å‚数,而ä¸æ˜¯å‡½æ•°å‚数,C++ 编译器能为个别组åˆç”Ÿæˆä»£ç ï¼Œä»¥æ”¹å–„性能åŠå‡å°‘代ç å°ºå¯¸ï¼ˆå½“åªç”¨å•ç§ç‰¹åŒ–)。缺点是需è¦åœ¨ç¼–译期决定标志。 + +`SourceEncoding` å‚数定义æµä½¿ç”¨äº†ä»€ä¹ˆç¼–ç ã€‚这与 `Document` çš„ `Encoding` ä¸ç›¸åŒã€‚细节å¯å‚考 [转ç å’Œæ ¡éªŒ](#TranscodingAndValidation) 一节。 + +此外 `InputStream` 是输入æµçš„类型。 + +## 解æžé”™è¯¯ {#ParseError} + +当解æžè¿‡ç¨‹é¡ºåˆ©å®Œæˆï¼Œ`Document` 便会å«æœ‰è§£æžç»“果。当过程出现错误,原æ¥çš„ DOM 会*ç»´æŒä¸å˜*。å¯ä½¿ç”¨ `bool HasParseError()`ã€`ParseErrorCode GetParseError()` åŠ `size_t GetErrorOffset()` 获å–解æžçš„错误状æ€ã€‚ + +解æžé”™è¯¯ä»£å· | æè¿° +--------------------------------------------|--------------------------------------------------- +`kParseErrorNone` | 无错误。 +`kParseErrorDocumentEmpty` | 文档是空的。 +`kParseErrorDocumentRootNotSingular` | 文档的根åŽé¢ä¸èƒ½æœ‰å…¶å®ƒå€¼ã€‚ +`kParseErrorValueInvalid` | ä¸åˆæ³•çš„值。 +`kParseErrorObjectMissName` | Object æˆå‘˜ç¼ºå°‘å字。 +`kParseErrorObjectMissColon` | Object æˆå‘˜åå­—åŽç¼ºå°‘冒å·ã€‚ +`kParseErrorObjectMissCommaOrCurlyBracket` | Object æˆå‘˜åŽç¼ºå°‘逗å·æˆ– `}`。 +`kParseErrorArrayMissCommaOrSquareBracket` | Array 元素åŽç¼ºå°‘逗å·æˆ– `]` 。 +`kParseErrorStringUnicodeEscapeInvalidHex` | String 中的 `\\u` 转义符åŽå«éžåå…­è¿›ä½æ•°å­—。 +`kParseErrorStringUnicodeSurrogateInvalid` | String 中的代ç†å¯¹ï¼ˆsurrogate pair)ä¸åˆæ³•ã€‚ +`kParseErrorStringEscapeInvalid` | String å«éžæ³•è½¬ä¹‰å­—符。 +`kParseErrorStringMissQuotationMark` | String 缺少关闭引å·ã€‚ +`kParseErrorStringInvalidEncoding` | String å«éžæ³•ç¼–ç ã€‚ +`kParseErrorNumberTooBig` | Number 的值太大,ä¸èƒ½å­˜å‚¨äºŽ `double`。 +`kParseErrorNumberMissFraction` | Number 缺少了å°æ•°éƒ¨åˆ†ã€‚ +`kParseErrorNumberMissExponent` | Number 缺少了指数。 + +错误的å移é‡å®šä¹‰ä¸ºä»Žæµå¼€å§‹è‡³é”™è¯¯å¤„的字符数é‡ã€‚ç›®å‰ RapidJSON ä¸è®°å½•é”™è¯¯è¡Œå·ã€‚ + +è¦å–得错误讯æ¯ï¼ŒRapidJSON 在 `rapidjson/error/en.h` 中æ供了英文错误讯æ¯ã€‚使用者å¯ä»¥ä¿®æ”¹å®ƒç”¨äºŽå…¶ä»–语言环境,或使用一个自定义的本地化系统。 + +以下是一个处ç†é”™è¯¯çš„例å­ã€‚ + +~~~~~~~~~~cpp +#include "rapidjson/document.h" +#include "rapidjson/error/en.h" + +// ... +Document d; +if (d.Parse(json).HasParseError()) { + fprintf(stderr, "\nError(offset %u): %s\n", + (unsigned)d.GetErrorOffset(), + GetParseError_En(d.GetParseErrorCode())); + // ... +} +~~~~~~~~~~ + +## 原ä½è§£æž {#InSituParsing} + +æ ¹æ® [维基百科](http://en.wikipedia.org/wiki/In_situ): + +> *In situ* ... is a Latin phrase that translates literally to "on site" or "in position". It means "locally", "on site", "on the premises" or "in place" to describe an event where it takes place, and is used in many different contexts. +> ... +> (In computer science) An algorithm is said to be an in situ algorithm, or in-place algorithm, if the extra amount of memory required to execute the algorithm is O(1), that is, does not exceed a constant no matter how large the input. For example, heapsort is an in situ sorting algorithm. + +> 翻译:*In situ*……是一个拉ä¸æ–‡ç‰‡è¯­ï¼Œå­—é¢ä¸Šçš„æ„æ€æ˜¯æŒ‡ã€ŒçŽ°åœºã€ã€ã€Œåœ¨ä½ç½®ã€ã€‚在许多ä¸åŒè¯­å¢ƒä¸­ï¼Œå®ƒæ述一个事件å‘生的ä½ç½®ï¼Œæ„指「本地ã€ã€ã€ŒçŽ°åœºã€ã€ã€Œåœ¨å¤„所ã€ã€ã€Œå°±ä½ã€ã€‚ +> …… +> (在计算机科学中)一个算法若称为原ä½ç®—法,或在ä½ç®—法,是指执行该算法所需的é¢å¤–内存空间是 O(1) 的,æ¢å¥è¯è¯´ï¼Œæ— è®ºè¾“入大å°éƒ½åªéœ€è¦å¸¸æ•°ç©ºé—´ã€‚例如,堆排åºæ˜¯ä¸€ä¸ªåŽŸä½æŽ’åºç®—法。 + +在正常的解æžè¿‡ç¨‹ä¸­ï¼Œå¯¹ JSON string 解ç å¹¶å¤åˆ¶è‡³å…¶ä»–缓冲区是一个很大的开销。原ä½è§£æžï¼ˆ*in situ* parsing)把这些 JSON string 直接解ç äºŽå®ƒåŽŸæ¥å­˜å‚¨çš„地方。由于解ç åŽçš„ string 长度总是短于或等于原æ¥å‚¨å­˜äºŽ JSON çš„ string,所以这是å¯è¡Œçš„。在这个语境下,对 JSON string 进行解ç æ˜¯æŒ‡å¤„ç†è½¬ä¹‰ç¬¦ï¼Œå¦‚ `"\n"`ã€`"\u1234"` 等,以åŠåœ¨ string æœ«ç«¯åŠ å…¥ç©ºç»ˆæ­¢ç¬¦å· (`'\0'`)。 + +以下的图比较正常åŠåŽŸä½è§£æžã€‚JSON string 值包å«æŒ‡å‘解ç åŽçš„字符串。 + +![正常解æž](diagram/normalparsing.png) + +在正常解æžä¸­ï¼Œè§£ç åŽçš„字符串被å¤åˆ¶è‡³å…¨æ–°åˆ†é…的缓冲区中。`"\\n"`(2 个字符)被解ç æˆ `"\n"`(1 个字符)。`"\\u0073"`(6 个字符)被解ç æˆ `"s"`(1 个字符)。 + +![原ä½è§£æž](diagram/insituparsing.png) + +原ä½è§£æžç›´æŽ¥ä¿®æ”¹äº†åŽŸæ¥çš„ JSON。图中高亮了被更新的字符。若 JSON string ä¸å«è½¬ä¹‰ç¬¦ï¼Œä¾‹å¦‚ `"msg"`,那么解æžè¿‡ç¨‹ä»…仅是以空字符代替结æŸåŒå¼•å·ã€‚ + +由于原ä½è§£æžä¿®æ”¹äº†è¾“å…¥ï¼Œå…¶è§£æž API éœ€è¦ `char*` è€Œéž `const char*`。 + +~~~~~~~~~~cpp +// 把整个文件读入 buffer +FILE* fp = fopen("test.json", "r"); +fseek(fp, 0, SEEK_END); +size_t filesize = (size_t)ftell(fp); +fseek(fp, 0, SEEK_SET); +char* buffer = (char*)malloc(filesize + 1); +size_t readLength = fread(buffer, 1, filesize, fp); +buffer[readLength] = '\0'; +fclose(fp); + +// 原ä½è§£æž buffer 至 d,buffer 内容会被修改。 +Document d; +d.ParseInsitu(buffer); + +// 在此查询ã€ä¿®æ”¹ DOM…… + +free(buffer); +// 注æ„:在这个ä½ç½®ï¼Œd å¯èƒ½å«æœ‰æŒ‡å‘已被释放的 buffer 的悬空指针 +~~~~~~~~~~ + +JSON string 会被打上 const-string 的标志。但它们å¯èƒ½å¹¶éžçœŸæ­£çš„「常数ã€ã€‚它的生命周期å–决于存储 JSON 的缓冲区。 + +原ä½è§£æžæŠŠåˆ†é…开销åŠå†…å­˜å¤åˆ¶å‡è‡³æœ€å°ã€‚通常这样åšèƒ½æ”¹å–„缓存一致性,而这对现代计算机æ¥è¯´æ˜¯ä¸€ä¸ªé‡è¦çš„性能因素。 + +原ä½è§£æžæœ‰ä»¥ä¸‹é™åˆ¶ï¼š + +1. 整个 JSON 须存储在内存之中。 +2. æµçš„æ¥æºç¼“ç ä¸Žæ–‡æ¡£çš„目标编ç å¿…须相åŒã€‚ +3. 需è¦ä¿ç•™ç¼“冲区,直至文档ä¸å†è¢«ä½¿ç”¨ã€‚ +4. è‹¥ DOM 需è¦åœ¨è§£æžåŽè¢«é•¿æœŸä½¿ç”¨ï¼Œè€Œ DOM 内åªæœ‰å¾ˆå°‘ JSON string,ä¿ç•™ç¼“冲区å¯èƒ½é€ æˆå†…存浪费。 + +原ä½è§£æžæœ€é€‚åˆç”¨äºŽçŸ­æœŸçš„ã€ç”¨å®Œå³å¼ƒçš„ JSON。实际应用中,这些场åˆæ˜¯éžå¸¸æ™®é的,例如ååºåˆ—化 JSON 至 C++ 对象ã€å¤„ç†ä»¥ JSON 表示的 web 请求等。 + +## 转ç ä¸Žæ ¡éªŒ {#TranscodingAndValidation} + +RapidJSON 内部支æŒä¸åŒ Unicode æ ¼å¼ï¼ˆæ­£å¼çš„术语是 UCS å˜æ¢æ ¼å¼ï¼‰é—´çš„转æ¢ã€‚在 DOM 解æžæ—¶ï¼Œæµçš„æ¥æºç¼–ç ä¸Ž DOM çš„ç¼–ç å¯ä»¥ä¸åŒã€‚例如,æ¥æºæµå¯èƒ½å«æœ‰ UTF-8 çš„ JSON,而 DOM 则使用 UTF-16 ç¼–ç ã€‚在 [EncodedInputStream](doc/stream.zh-cn.md) 一节里有一个例å­ã€‚ + +当从 DOM 输出一个 JSON 至输出æµä¹‹æ—¶ï¼Œä¹Ÿå¯ä»¥ä½¿ç”¨è½¬ç åŠŸèƒ½ã€‚在 [EncodedOutputStream](doc/stream.zh-cn.md) 一节里有一个例å­ã€‚ + +在转ç è¿‡ç¨‹ä¸­ï¼Œä¼šæŠŠæ¥æº string 解ç æˆ Unicode ç ç‚¹ï¼Œç„¶åŽæŠŠç ç‚¹ç¼–ç æˆç›®æ ‡æ ¼å¼ã€‚在解ç æ—¶ï¼Œå®ƒä¼šæ ¡éªŒæ¥æº string 的字节åºåˆ—是å¦åˆæ³•ã€‚è‹¥é‡ä¸Šéžåˆæ³•åºåˆ—,解æžå™¨ä¼šåœæ­¢å¹¶è¿”回 `kParseErrorStringInvalidEncoding` 错误。 + +当æ¥æºç¼–ç ä¸Ž DOM çš„ç¼–ç ç›¸åŒï¼Œè§£æžå™¨ç¼ºçœåœ° * ä¸ä¼š * 校验åºåˆ—。使用者å¯å¼€å¯ `kParseValidateEncodingFlag` 去强制校验。 + +# 技巧 {#Techniques} + +这里讨论一些 DOM API 的使用技巧。 + +## 把 DOM 作为 SAX 事件å‘表者 + +在 RapidJSON 中,利用 `Writer` 把 DOM ç”Ÿæˆ JSON çš„åšæ³•ï¼Œçœ‹æ¥æœ‰ç‚¹å¥‡æ€ªã€‚ + +~~~~~~~~~~cpp +// ... +Writer writer(buffer); +d.Accept(writer); +~~~~~~~~~~ + +实际上,`Value::Accept()` 是负责å‘布该值相关的 SAX 事件至处ç†å™¨çš„。通过这个设计,`Value` åŠ `Writer` 解除了å¶åˆã€‚`Value` å¯ç”Ÿæˆ SAX 事件,而 `Writer` 则å¯ä»¥å¤„ç†è¿™äº›äº‹ä»¶ã€‚ + +使用者å¯ä»¥åˆ›å»ºè‡ªå®šä¹‰çš„处ç†å™¨ï¼ŒåŽ»æŠŠ DOM 转æ¢æˆå…¶å®ƒæ ¼å¼ã€‚例如,一个把 DOM 转æ¢æˆ XML 的处ç†å™¨ã€‚ + +è¦çŸ¥é“更多关于 SAX 事件与处ç†å™¨ï¼Œå¯å‚阅 [SAX](doc/sax.zh-cn.md)。 + +## 使用者缓冲区 {#UserBuffer} + +许多应用软件å¯èƒ½éœ€è¦å°½é‡å‡å°‘内存分é…。 + +`MemoryPoolAllocator` å¯ä»¥å¸®åŠ©è¿™æ–¹é¢ï¼Œå®ƒå®¹è®¸ä½¿ç”¨è€…æ供一个缓冲区。该缓冲区å¯èƒ½ç½®äºŽç¨‹åºå †æ ˆï¼Œæˆ–是一个é™æ€åˆ†é…的「è‰ç¨¿ç¼“冲区(scratch buffer)ã€ï¼ˆä¸€ä¸ªé™æ€ï¼å…¨å±€çš„数组),用于储存临时数æ®ã€‚ + +`MemoryPoolAllocator` 会先用使用者缓冲区去解决分é…请求。当使用者缓冲区用完,就会从基础分é…器(缺çœä¸º `CrtAllocator`)分é…一å—内存。 + +以下是使用堆栈内存的例å­ï¼Œç¬¬ä¸€ä¸ªåˆ†é…器用于存储值,第二个用于解æžæ—¶çš„临时缓冲。 + +~~~~~~~~~~cpp +typedef GenericDocument, MemoryPoolAllocator<>, MemoryPoolAllocator<>> DocumentType; +char valueBuffer[4096]; +char parseBuffer[1024]; +MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer)); +MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer)); +DocumentType d(&valueAllocator, sizeof(parseBuffer), &parseAllocator); +d.Parse(json); +~~~~~~~~~~ + +若解æžæ—¶åˆ†é…总é‡å°‘于 4096+1024 字节时,这段代ç ä¸ä¼šé€ æˆä»»ä½•å †å†…存分é…ï¼ˆç» `new` 或 `malloc()`)。 + +使用者å¯ä»¥é€šè¿‡ `MemoryPoolAllocator::Size()` 查询当å‰å·²åˆ†çš„内存大å°ã€‚那么使用者å¯ä»¥æ‹Ÿå®šä½¿ç”¨è€…缓冲区的åˆé€‚大å°ã€‚ diff --git a/deps/rapidjson/doc/encoding.md b/deps/rapidjson/doc/encoding.md new file mode 100644 index 0000000..e663aea --- /dev/null +++ b/deps/rapidjson/doc/encoding.md @@ -0,0 +1,146 @@ +# Encoding + +According to [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf), + +> (in Introduction) JSON text is a sequence of Unicode code points. + +The earlier [RFC4627](http://www.ietf.org/rfc/rfc4627.txt) stated that, + +> (in §3) JSON text SHALL be encoded in Unicode. The default encoding is UTF-8. + +> (in §6) JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON is written in UTF-8, JSON is 8bit compatible. When JSON is written in UTF-16 or UTF-32, the binary content-transfer-encoding must be used. + +RapidJSON supports various encodings. It can also validate the encodings of JSON, and transcoding JSON among encodings. All these features are implemented internally, without the need for external libraries (e.g. [ICU](http://site.icu-project.org/)). + +[TOC] + +# Unicode {#Unicode} +From [Unicode's official website](http://www.unicode.org/standard/WhatIsUnicode.html): +> Unicode provides a unique number for every character, +> no matter what the platform, +> no matter what the program, +> no matter what the language. + +Those unique numbers are called code points, which is in the range `0x0` to `0x10FFFF`. + +## Unicode Transformation Format {#UTF} + +There are various encodings for storing Unicode code points. These are called Unicode Transformation Format (UTF). RapidJSON supports the most commonly used UTFs, including + +* UTF-8: 8-bit variable-width encoding. It maps a code point to 1–4 bytes. +* UTF-16: 16-bit variable-width encoding. It maps a code point to 1–2 16-bit code units (i.e., 2–4 bytes). +* UTF-32: 32-bit fixed-width encoding. It directly maps a code point to a single 32-bit code unit (i.e. 4 bytes). + +For UTF-16 and UTF-32, the byte order (endianness) does matter. Within computer memory, they are often stored in the computer's endianness. However, when it is stored in file or transferred over network, we need to state the byte order of the byte sequence, either little-endian (LE) or big-endian (BE). + +RapidJSON provide these encodings via the structs in `rapidjson/encodings.h`: + +~~~~~~~~~~cpp +namespace rapidjson { + +template +struct UTF8; + +template +struct UTF16; + +template +struct UTF16LE; + +template +struct UTF16BE; + +template +struct UTF32; + +template +struct UTF32LE; + +template +struct UTF32BE; + +} // namespace rapidjson +~~~~~~~~~~ + +For processing text in memory, we normally use `UTF8`, `UTF16` or `UTF32`. For processing text via I/O, we may use `UTF8`, `UTF16LE`, `UTF16BE`, `UTF32LE` or `UTF32BE`. + +When using the DOM-style API, the `Encoding` template parameter in `GenericValue` and `GenericDocument` indicates the encoding to be used to represent JSON string in memory. So normally we will use `UTF8`, `UTF16` or `UTF32` for this template parameter. The choice depends on operating systems and other libraries that the application is using. For example, Windows API represents Unicode characters in UTF-16, while most Linux distributions and applications prefer UTF-8. + +Example of UTF-16 DOM declaration: + +~~~~~~~~~~cpp +typedef GenericDocument > WDocument; +typedef GenericValue > WValue; +~~~~~~~~~~ + +For a detail example, please check the example in [DOM's Encoding](doc/stream.md) section. + +## Character Type {#CharacterType} + +As shown in the declaration, each encoding has a `CharType` template parameter. Actually, it may be a little bit confusing, but each `CharType` stores a code unit, not a character (code point). As mentioned in previous section, a code point may be encoded to 1–4 code units for UTF-8. + +For `UTF16(LE|BE)`, `UTF32(LE|BE)`, the `CharType` must be integer type of at least 2 and 4 bytes respectively. + +Note that C++11 introduces `char16_t` and `char32_t`, which can be used for `UTF16` and `UTF32` respectively. + +## AutoUTF {#AutoUTF} + +Previous encodings are statically bound in compile-time. In other words, user must know exactly which encodings will be used in the memory or streams. However, sometimes we may need to read/write files of different encodings. The encoding needed to be decided in runtime. + +`AutoUTF` is an encoding designed for this purpose. It chooses which encoding to be used according to the input or output stream. Currently, it should be used with `EncodedInputStream` and `EncodedOutputStream`. + +## ASCII {#ASCII} + +Although the JSON standards did not mention about [ASCII](http://en.wikipedia.org/wiki/ASCII), sometimes we would like to write 7-bit ASCII JSON for applications that cannot handle UTF-8. Since any JSON can represent unicode characters in escaped sequence `\uXXXX`, JSON can always be encoded in ASCII. + +Here is an example for writing a UTF-8 DOM into ASCII: + +~~~~~~~~~~cpp +using namespace rapidjson; +Document d; // UTF8<> +// ... +StringBuffer buffer; +Writer > writer(buffer); +d.Accept(writer); +std::cout << buffer.GetString(); +~~~~~~~~~~ + +ASCII can be used in input stream. If the input stream contains bytes with values above 127, it will cause `kParseErrorStringInvalidEncoding` error. + +ASCII *cannot* be used in memory (encoding of `Document` or target encoding of `Reader`), as it cannot represent Unicode code points. + +# Validation & Transcoding {#ValidationTranscoding} + +When RapidJSON parses a JSON, it can validate the input JSON, whether it is a valid sequence of a specified encoding. This option can be turned on by adding `kParseValidateEncodingFlag` in `parseFlags` template parameter. + +If the input encoding and output encoding is different, `Reader` and `Writer` will automatically transcode (convert) the text. In this case, `kParseValidateEncodingFlag` is not necessary, as it must decode the input sequence. And if the sequence was unable to be decoded, it must be invalid. + +## Transcoder {#Transcoder} + +Although the encoding functions in RapidJSON are designed for JSON parsing/generation, user may abuse them for transcoding of non-JSON strings. + +Here is an example for transcoding a string from UTF-8 to UTF-16: + +~~~~~~~~~~cpp +#include "rapidjson/encodings.h" + +using namespace rapidjson; + +const char* s = "..."; // UTF-8 string +StringStream source(s); +GenericStringBuffer > target; + +bool hasError = false; +while (source.Peek() != '\0') + if (!Transcoder, UTF16<> >::Transcode(source, target)) { + hasError = true; + break; + } + +if (!hasError) { + const wchar_t* t = target.GetString(); + // ... +} +~~~~~~~~~~ + +You may also use `AutoUTF` and the associated streams for setting source/target encoding in runtime. diff --git a/deps/rapidjson/doc/encoding.zh-cn.md b/deps/rapidjson/doc/encoding.zh-cn.md new file mode 100644 index 0000000..808ba52 --- /dev/null +++ b/deps/rapidjson/doc/encoding.zh-cn.md @@ -0,0 +1,152 @@ +# ç¼–ç  + +æ ¹æ® [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf): + +> (in Introduction) JSON text is a sequence of Unicode code points. +> +> 翻译:JSON 文本是 Unicode ç ç‚¹çš„åºåˆ—。 + +较早的 [RFC4627](http://www.ietf.org/rfc/rfc4627.txt) 申明: + +> (in §3) JSON text SHALL be encoded in Unicode. The default encoding is UTF-8. +> +> 翻译:JSON 文本应该以 Unicode ç¼–ç ã€‚缺çœçš„ç¼–ç ä¸º UTF-8。 + +> (in §6) JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON is written in UTF-8, JSON is 8bit compatible. When JSON is written in UTF-16 or UTF-32, the binary content-transfer-encoding must be used. +> +> 翻译:JSON å¯ä½¿ç”¨ UTF-8ã€UTF-16 或 UTF-32 表示。当 JSON 以 UTF-8 写入,该 JSON 是 8 ä½å…¼å®¹çš„。当 JSON 以 UTF-16 或 UTF-32 写入,就必须使用二进制的内容传é€ç¼–ç ã€‚ + +RapidJSON 支æŒå¤šç§ç¼–ç ã€‚它也能检查 JSON çš„ç¼–ç ï¼Œä»¥åŠåœ¨ä¸åŒç¼–ç ä¸­è¿›è¡Œè½¬ç ã€‚所有这些功能都是在内部实现,无需使用外部的程åºåº“(如 [ICU](http://site.icu-project.org/))。 + +[TOC] + +# Unicode {#Unicode} +æ ¹æ® [Unicode 的官方网站](http://www.unicode.org/standard/translations/t-chinese.html): +>Unicode ç»™æ¯ä¸ªå­—符æ供了一个唯一的数字, +ä¸è®ºæ˜¯ä»€ä¹ˆå¹³å°ã€ +ä¸è®ºæ˜¯ä»€ä¹ˆç¨‹åºã€ +ä¸è®ºæ˜¯ä»€ä¹ˆè¯­è¨€ã€‚ + +这些唯一数字称为ç ç‚¹ï¼ˆcode point),其范围介乎 `0x0` 至 `0x10FFFF` 之间。 + +## Unicode 转æ¢æ ¼å¼ {#UTF} + +存储 Unicode ç ç‚¹æœ‰å¤šç§ç¼–ç æ–¹å¼ã€‚这些称为 Unicode 转æ¢æ ¼å¼ï¼ˆUnicode Transformation Format, UTF)。RapidJSON 支æŒæœ€å¸¸ç”¨çš„ UTF,包括: + +* UTF-8:8 ä½å¯å˜é•¿åº¦ç¼–ç ã€‚它把一个ç ç‚¹æ˜ å°„至 1 至 4 个字节。 +* UTF-16:16 ä½å¯å˜é•¿åº¦ç¼–ç ã€‚它把一个ç ç‚¹æ˜ å°„至 1 至 2 个 16 ä½ç¼–ç å•å…ƒï¼ˆå³ 2 至 4 个字节)。 +* UTF-32:32 ä½å›ºå®šé•¿åº¦ç¼–ç ã€‚它直接把ç ç‚¹æ˜ å°„至å•ä¸ª 32 ä½ç¼–ç å•å…ƒï¼ˆå³ 4 字节)。 + +对于 UTF-16 åŠ UTF-32 æ¥è¯´ï¼Œå­—节åºï¼ˆendianness)是有影å“的。在内存中,它们通常都是以该计算机的字节åºæ¥å­˜å‚¨ã€‚然而,当è¦å‚¨å­˜åœ¨æ–‡ä»¶ä¸­æˆ–在网上传输,我们需è¦æŒ‡æ˜Žå­—节åºåˆ—的字节åºï¼Œæ˜¯å°ç«¯ï¼ˆlittle endian, LE)还是大端(big-endian, BE)。 + +RapidJSON 通过 `rapidjson/encodings.h` 中的 struct 去æä¾›å„ç§ç¼–ç ï¼š + +~~~~~~~~~~cpp +namespace rapidjson { + +template +struct UTF8; + +template +struct UTF16; + +template +struct UTF16LE; + +template +struct UTF16BE; + +template +struct UTF32; + +template +struct UTF32LE; + +template +struct UTF32BE; + +} // namespace rapidjson +~~~~~~~~~~ + +对于在内存中的文本,我们正常会使用 `UTF8`ã€`UTF16` 或 `UTF32`。对于处ç†ç»è¿‡ I/O 的文本,我们å¯ä½¿ç”¨ `UTF8`ã€`UTF16LE`ã€`UTF16BE`ã€`UTF32LE` 或 `UTF32BE`。 + +当使用 DOM 风格的 API,`GenericValue` åŠ `GenericDocument` 里的 `Encoding` 模æ¿å‚数是用于指明内存中存储的 JSON 字符串使用哪ç§ç¼–ç ã€‚因此通常我们会在此å‚数中使用 `UTF8`ã€`UTF16` 或 `UTF32`。如何选择,视乎应用软件所使用的æ“作系统åŠå…¶ä»–程åºåº“。例如,Windows API 使用 UTF-16 表示 Unicode 字符,而多数的 Linux å‘行版本åŠåº”用软件则更喜欢 UTF-8。 + +使用 UTF-16 çš„ DOM 声明例å­ï¼š + +~~~~~~~~~~cpp +typedef GenericDocument > WDocument; +typedef GenericValue > WValue; +~~~~~~~~~~ + +å¯ä»¥åœ¨ [DOM's Encoding](doc/stream.zh-cn.md) 一节看到更详细的使用例å­ã€‚ + +## 字符类型 {#CharacterType} + +从之å‰çš„声明中å¯ä»¥çœ‹åˆ°ï¼Œæ¯ä¸ªç¼–ç éƒ½æœ‰ä¸€ä¸ª `CharType` 模æ¿å‚数。这å¯èƒ½æ¯”较容易混淆,实际上,æ¯ä¸ª `CharType` 存储一个编ç å•å…ƒï¼Œè€Œä¸æ˜¯ä¸€ä¸ªå­—符(ç ç‚¹ï¼‰ã€‚如之å‰æ‰€è°ˆåŠï¼Œåœ¨ UTF-8 中一个ç ç‚¹å¯èƒ½ä¼šç¼–ç æˆ 1 至 4 个编ç å•å…ƒã€‚ + +对于 `UTF16(LE|BE)` åŠ `UTF32(LE|BE)` æ¥è¯´ï¼Œ`CharType` 必须分别是一个至少 2 åŠ 4 字节的整数类型。 + +æ³¨æ„ C++11 新添了 `char16_t` åŠ `char32_t` 类型,也å¯åˆ†åˆ«ç”¨äºŽ `UTF16` åŠ `UTF32`。 + +## AutoUTF {#AutoUTF} + +上述所介ç»çš„ç¼–ç éƒ½æ˜¯åœ¨ç¼–译期é™æ€æŒ·å®šçš„。æ¢å¥è¯è¯´ï¼Œä½¿ç”¨è€…必须知é“内存或æµä¹‹ä¸­ä½¿ç”¨äº†å“ªç§ç¼–ç ã€‚然而,有时候我们å¯èƒ½éœ€è¦è¯»å†™ä¸åŒç¼–ç çš„文件,而且这些编ç éœ€è¦åœ¨è¿è¡Œæ—¶æ‰èƒ½å†³å®šã€‚ + +`AutoUTF` 是为此而设计的编ç ã€‚它根æ®è¾“入或输出æµæ¥é€‰æ‹©ä½¿ç”¨å“ªç§ç¼–ç ã€‚ç›®å‰å®ƒåº”该与 `EncodedInputStream` åŠ `EncodedOutputStream` 结åˆä½¿ç”¨ã€‚ + +## ASCII {#ASCII} + +虽然 JSON 标准并未æåŠ [ASCII](http://en.wikipedia.org/wiki/ASCII),有时候我们希望写入 7 ä½çš„ ASCII JSONï¼Œä»¥ä¾›æœªèƒ½å¤„ç† UTF-8 的应用程åºä½¿ç”¨ã€‚由于任 JSON 都å¯ä»¥æŠŠ Unicode 字符表示为 `\uXXXX` 转义åºåˆ—,JSON 总是å¯ç”¨ ASCII æ¥ç¼–ç ã€‚ + +以下的例å­æŠŠ UTF-8 çš„ DOM å†™æˆ ASCII çš„ JSON: + +~~~~~~~~~~cpp +using namespace rapidjson; +Document d; // UTF8<> +// ... +StringBuffer buffer; +Writer > writer(buffer); +d.Accept(writer); +std::cout << buffer.GetString(); +~~~~~~~~~~ + +ASCII å¯ç”¨äºŽè¾“å…¥æµã€‚当输入æµåŒ…å«å¤§äºŽ 127 的字节,就会导致 `kParseErrorStringInvalidEncoding` 错误。 + +ASCII * ä¸èƒ½ * 用于内存(`Document` çš„ç¼–ç ï¼Œæˆ– `Reader` 的目标编ç ),因为它ä¸èƒ½è¡¨ç¤º Unicode ç ç‚¹ã€‚ + +# 校验åŠè½¬ç  {#ValidationTranscoding} + +当 RapidJSON 解æžä¸€ä¸ª JSON 时,它能校验输入 JSON,判断它是å¦æ‰€æ ‡æ˜Žç¼–ç çš„åˆæ³•åºåˆ—。è¦å¼€å¯æ­¤é€‰é¡¹ï¼Œè¯·æŠŠ `kParseValidateEncodingFlag` 加入 `parseFlags` 模æ¿å‚数。 + +若输入编ç å’Œè¾“出编ç å¹¶ä¸ç›¸åŒï¼Œ`Reader` åŠ `Writer` 会算把文本转ç ã€‚在这ç§æƒ…况下,并ä¸éœ€è¦ `kParseValidateEncodingFlag`,因为它必须解ç è¾“å…¥åºåˆ—。若åºåˆ—ä¸èƒ½è¢«è§£ç ï¼Œå®ƒå¿…然是ä¸åˆæ³•çš„。 + +## 转ç å™¨ {#Transcoder} + +虽然 RapidJSON çš„ç¼–ç åŠŸèƒ½æ˜¯ä¸º JSON 解æžï¼ç”Ÿæˆè€Œè®¾è®¡ï¼Œä½¿ç”¨è€…也å¯ä»¥â€œæ»¥ç”¨â€å®ƒä»¬æ¥ä¸ºéž JSON 字符串转ç ã€‚ + +以下的例å­æŠŠ UTF-8 字符串转ç æˆ UTF-16: + +~~~~~~~~~~cpp +#include "rapidjson/encodings.h" + +using namespace rapidjson; + +const char* s = "..."; // UTF-8 string +StringStream source(s); +GenericStringBuffer > target; + +bool hasError = false; +while (source.Peek() != '\0') + if (!Transcoder, UTF16<> >::Transcode(source, target)) { + hasError = true; + break; + } + +if (!hasError) { + const wchar_t* t = target.GetString(); + // ... +} +~~~~~~~~~~ + +你也å¯ä»¥ç”¨ `AutoUTF` åŠå¯¹åº”çš„æµæ¥åœ¨è¿è¡Œæ—¶è®¾ç½®å†…æºï¼ç›®çš„之编ç ã€‚ diff --git a/deps/rapidjson/doc/faq.md b/deps/rapidjson/doc/faq.md new file mode 100644 index 0000000..55fa2af --- /dev/null +++ b/deps/rapidjson/doc/faq.md @@ -0,0 +1,289 @@ +# FAQ + +[TOC] + +## General + +1. What is RapidJSON? + + RapidJSON is a C++ library for parsing and generating JSON. You may check all [features](doc/features.md) of it. + +2. Why is RapidJSON named so? + + It is inspired by [RapidXML](http://rapidxml.sourceforge.net/), which is a fast XML DOM parser. + +3. Is RapidJSON similar to RapidXML? + + RapidJSON borrowed some designs of RapidXML, including *in situ* parsing, header-only library. But the two APIs are completely different. Also RapidJSON provide many features that are not in RapidXML. + +4. Is RapidJSON free? + + Yes, it is free under MIT license. It can be used in commercial applications. Please check the details in [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt). + +5. Is RapidJSON small? What are its dependencies? + + Yes. A simple executable which parses a JSON and prints its statistics is less than 30KB on Windows. + + RapidJSON depends on C++ standard library only. + +6. How to install RapidJSON? + + Check [Installation section](https://miloyip.github.io/rapidjson/). + +7. Can RapidJSON run on my platform? + + RapidJSON has been tested in many combinations of operating systems, compilers and CPU architecture by the community. But we cannot ensure that it can be run on your particular platform. Building and running the unit test suite will give you the answer. + +8. Does RapidJSON support C++03? C++11? + + RapidJSON was firstly implemented for C++03. Later it added optional support of some C++11 features (e.g., move constructor, `noexcept`). RapidJSON shall be compatible with C++03 or C++11 compliant compilers. + +9. Does RapidJSON really work in real applications? + + Yes. It is deployed in both client and server real applications. A community member reported that RapidJSON in their system parses 50 million JSONs daily. + +10. How RapidJSON is tested? + + RapidJSON contains a unit test suite for automatic testing. [Travis](https://travis-ci.org/Tencent/rapidjson/)(for Linux) and [AppVeyor](https://ci.appveyor.com/project/Tencent/rapidjson/)(for Windows) will compile and run the unit test suite for all modifications. The test process also uses Valgrind (in Linux) to detect memory leaks. + +11. Is RapidJSON well documented? + + RapidJSON provides user guide and API documentationn. + +12. Are there alternatives? + + Yes, there are a lot alternatives. For example, [nativejson-benchmark](https://github.com/miloyip/nativejson-benchmark) has a listing of open-source C/C++ JSON libraries. [json.org](http://www.json.org/) also has a list. + +## JSON + +1. What is JSON? + + JSON (JavaScript Object Notation) is a lightweight data-interchange format. It uses human readable text format. More details of JSON can be referred to [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) and [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm). + +2. What are applications of JSON? + + JSON are commonly used in web applications for transferring structured data. It is also used as a file format for data persistence. + +3. Does RapidJSON conform to the JSON standard? + + Yes. RapidJSON is fully compliance with [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) and [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm). It can handle corner cases, such as supporting null character and surrogate pairs in JSON strings. + +4. Does RapidJSON support relaxed syntax? + + Currently no. RapidJSON only support the strict standardized format. Support on related syntax is under discussion in this [issue](https://github.com/Tencent/rapidjson/issues/36). + +## DOM and SAX + +1. What is DOM style API? + + Document Object Model (DOM) is an in-memory representation of JSON for query and manipulation. + +2. What is SAX style API? + + SAX is an event-driven API for parsing and generation. + +3. Should I choose DOM or SAX? + + DOM is easy for query and manipulation. SAX is very fast and memory-saving but often more difficult to be applied. + +4. What is *in situ* parsing? + + *in situ* parsing decodes the JSON strings directly into the input JSON. This is an optimization which can reduce memory consumption and improve performance, but the input JSON will be modified. Check [in-situ parsing](doc/dom.md) for details. + +5. When does parsing generate an error? + + The parser generates an error when the input JSON contains invalid syntax, or a value can not be represented (a number is too big), or the handler of parsers terminate the parsing. Check [parse error](doc/dom.md) for details. + +6. What error information is provided? + + The error is stored in `ParseResult`, which includes the error code and offset (number of characters from the beginning of JSON). The error code can be translated into human-readable error message. + +7. Why not just using `double` to represent JSON number? + + Some applications use 64-bit unsigned/signed integers. And these integers cannot be converted into `double` without loss of precision. So the parsers detects whether a JSON number is convertible to different types of integers and/or `double`. + +8. How to clear-and-minimize a document or value? + + Call one of the `SetXXX()` methods - they call destructor which deallocates DOM data: + + ~~~~~~~~~~cpp + Document d; + ... + d.SetObject(); // clear and minimize + ~~~~~~~~~~ + + Alternatively, use equivalent of the [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize): + ~~~~~~~~~~cpp + Value(kObjectType).Swap(d); + ~~~~~~~~~~ + or equivalent, but slightly longer to type: + ~~~~~~~~~~cpp + d.Swap(Value(kObjectType).Move()); + ~~~~~~~~~~ + +9. How to insert a document node into another document? + + Let's take the following two DOM trees represented as JSON documents: + ~~~~~~~~~~cpp + Document person; + person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}"); + + Document address; + address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}"); + ~~~~~~~~~~ + Let's assume we want to merge them in such way that the whole `address` document becomes a node of the `person`: + ~~~~~~~~~~js + { "person": { + "name": { "first": "Adam", "last": "Thomas" }, + "address": { "city": "Moscow", "street": "Quiet" } + } + } + ~~~~~~~~~~ + + The most important requirement to take care of document and value life-cycle as well as consistent memory management using the right allocator during the value transfer. + + Simple yet most efficient way to achieve that is to modify the `address` definition above to initialize it with allocator of the `person` document, then we just add the root member of the value: + ~~~~~~~~~~cpp + Document address(&person.GetAllocator()); + ... + person["person"].AddMember("address", address["address"], person.GetAllocator()); + ~~~~~~~~~~ +Alternatively, if we don't want to explicitly refer to the root value of `address` by name, we can refer to it via iterator: + ~~~~~~~~~~cpp + auto addressRoot = address.MemberBegin(); + person["person"].AddMember(addressRoot->name, addressRoot->value, person.GetAllocator()); + ~~~~~~~~~~ + + Second way is to deep-clone the value from the address document: + ~~~~~~~~~~cpp + Value addressValue = Value(address["address"], person.GetAllocator()); + person["person"].AddMember("address", addressValue, person.GetAllocator()); + ~~~~~~~~~~ + +## Document/Value (DOM) + +1. What is move semantics? Why? + + Instead of copy semantics, move semantics is used in `Value`. That means, when assigning a source value to a target value, the ownership of source value is moved to the target value. + + Since moving is faster than copying, this design decision forces user to aware of the copying overhead. + +2. How to copy a value? + + There are two APIs: constructor with allocator, and `CopyFrom()`. See [Deep Copy Value](doc/tutorial.md) for an example. + +3. Why do I need to provide the length of string? + + Since C string is null-terminated, the length of string needs to be computed via `strlen()`, with linear runtime complexity. This incurs an unnecessary overhead of many operations, if the user already knows the length of string. + + Also, RapidJSON can handle `\u0000` (null character) within a string. If a string contains null characters, `strlen()` cannot return the true length of it. In such case user must provide the length of string explicitly. + +4. Why do I need to provide allocator parameter in many DOM manipulation API? + + Since the APIs are member functions of `Value`, we do not want to save an allocator pointer in every `Value`. + +5. Does it convert between numerical types? + + When using `GetInt()`, `GetUint()`, ... conversion may occur. For integer-to-integer conversion, it only convert when it is safe (otherwise it will assert). However, when converting a 64-bit signed/unsigned integer to double, it will convert but be aware that it may lose precision. A number with fraction, or an integer larger than 64-bit, can only be obtained by `GetDouble()`. + +## Reader/Writer (SAX) + +1. Why don't we just `printf` a JSON? Why do we need a `Writer`? + + Most importantly, `Writer` will ensure the output JSON is well-formed. Calling SAX events incorrectly (e.g. `StartObject()` pairing with `EndArray()`) will assert. Besides, `Writer` will escapes strings (e.g., `\n`). Finally, the numeric output of `printf()` may not be a valid JSON number, especially in some locale with digit delimiters. And the number-to-string conversion in `Writer` is implemented with very fast algorithms, which outperforms than `printf()` or `iostream`. + +2. Can I pause the parsing process and resume it later? + + This is not directly supported in the current version due to performance consideration. However, if the execution environment supports multi-threading, user can parse a JSON in a separate thread, and pause it by blocking in the input stream. + +## Unicode + +1. Does it support UTF-8, UTF-16 and other format? + + Yes. It fully support UTF-8, UTF-16 (LE/BE), UTF-32 (LE/BE) and ASCII. + +2. Can it validate the encoding? + + Yes, just pass `kParseValidateEncodingFlag` to `Parse()`. If there is invalid encoding in the stream, it will generate `kParseErrorStringInvalidEncoding` error. + +3. What is surrogate pair? Does RapidJSON support it? + + JSON uses UTF-16 encoding when escaping unicode character, e.g. `\u5927` representing Chinese character "big". To handle characters other than those in basic multilingual plane (BMP), UTF-16 encodes those characters with two 16-bit values, which is called UTF-16 surrogate pair. For example, the Emoji character U+1F602 can be encoded as `\uD83D\uDE02` in JSON. + + RapidJSON fully support parsing/generating UTF-16 surrogates. + +4. Can it handle `\u0000` (null character) in JSON string? + + Yes. RapidJSON fully support null character in JSON string. However, user need to be aware of it and using `GetStringLength()` and related APIs to obtain the true length of string. + +5. Can I output `\uxxxx` for all non-ASCII character? + + Yes, use `ASCII<>` as output encoding template parameter in `Writer` can enforce escaping those characters. + +## Stream + +1. I have a big JSON file. Should I load the whole file to memory? + + User can use `FileReadStream` to read the file chunk-by-chunk. But for *in situ* parsing, the whole file must be loaded. + +2. Can I parse JSON while it is streamed from network? + + Yes. User can implement a custom stream for this. Please refer to the implementation of `FileReadStream`. + +3. I don't know what encoding will the JSON be. How to handle them? + + You may use `AutoUTFInputStream` which detects the encoding of input stream automatically. However, it will incur some performance overhead. + +4. What is BOM? How RapidJSON handle it? + + [Byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark) sometimes reside at the beginning of file/stream to indicate the UTF encoding type of it. + + RapidJSON's `EncodedInputStream` can detect/consume BOM. `EncodedOutputStream` can optionally write a BOM. See [Encoded Streams](doc/stream.md) for example. + +5. Why little/big endian is related? + + little/big endian of stream is an issue for UTF-16 and UTF-32 streams, but not UTF-8 stream. + +## Performance + +1. Is RapidJSON really fast? + + Yes. It may be the fastest open source JSON library. There is a [benchmark](https://github.com/miloyip/nativejson-benchmark) for evaluating performance of C/C++ JSON libraries. + +2. Why is it fast? + + Many design decisions of RapidJSON is aimed at time/space performance. These may reduce user-friendliness of APIs. Besides, it also employs low-level optimizations (intrinsics, SIMD) and special algorithms (custom double-to-string, string-to-double conversions). + +3. What is SIMD? How it is applied in RapidJSON? + + [SIMD](http://en.wikipedia.org/wiki/SIMD) instructions can perform parallel computation in modern CPUs. RapidJSON support Intel's SSE2/SSE4.2 and ARM's Neon to accelerate whitespace/tabspace/carriage-return/line-feed skipping. This improves performance of parsing indent formatted JSON. Define `RAPIDJSON_SSE2`, `RAPIDJSON_SSE42` or `RAPIDJSON_NEON` macro to enable this feature. However, running the executable on a machine without such instruction set support will make it crash. + +4. Does it consume a lot of memory? + + The design of RapidJSON aims at reducing memory footprint. + + In the SAX API, `Reader` consumes memory proportional to maximum depth of JSON tree, plus maximum length of JSON string. + + In the DOM API, each `Value` consumes exactly 16/24 bytes for 32/64-bit architecture respectively. RapidJSON also uses a special memory allocator to minimize overhead of allocations. + +5. What is the purpose of being high performance? + + Some applications need to process very large JSON files. Some server-side applications need to process huge amount of JSONs. Being high performance can improve both latency and throughput. In a broad sense, it will also save energy. + +## Gossip + +1. Who are the developers of RapidJSON? + + Milo Yip ([miloyip](https://github.com/miloyip)) is the original author of RapidJSON. Many contributors from the world have improved RapidJSON. Philipp A. Hartmann ([pah](https://github.com/pah)) has implemented a lot of improvements, setting up automatic testing and also involves in a lot of discussions for the community. Don Ding ([thebusytypist](https://github.com/thebusytypist)) implemented the iterative parser. Andrii Senkovych ([jollyroger](https://github.com/jollyroger)) completed the CMake migration. Kosta ([Kosta-Github](https://github.com/Kosta-Github)) provided a very neat short-string optimization. Thank you for all other contributors and community members as well. + +2. Why do you develop RapidJSON? + + It was just a hobby project initially in 2011. Milo Yip is a game programmer and he just knew about JSON at that time and would like to apply JSON in future projects. As JSON seems very simple he would like to write a header-only and fast library. + +3. Why there is a long empty period of development? + + It is basically due to personal issues, such as getting new family members. Also, Milo Yip has spent a lot of spare time on translating "Game Engine Architecture" by Jason Gregory into Chinese. + +4. Why did the repository move from Google Code to GitHub? + + This is the trend. And GitHub is much more powerful and convenient. diff --git a/deps/rapidjson/doc/faq.zh-cn.md b/deps/rapidjson/doc/faq.zh-cn.md new file mode 100644 index 0000000..cf1124d --- /dev/null +++ b/deps/rapidjson/doc/faq.zh-cn.md @@ -0,0 +1,290 @@ +# 常è§é—®é¢˜ + +[TOC] + +## 一般问题 + +1. RapidJSON 是什么? + + RapidJSON 是一个 C++ 库,用于解æžåŠç”Ÿæˆ JSON。读者å¯å‚考它的所有 [特点](doc/features.zh-cn.md)。 + +2. 为什么称作 RapidJSON? + + 它的çµæ„Ÿæ¥è‡ªäºŽ [RapidXML](http://rapidxml.sourceforge.net/),RapidXML 是一个高速的 XML DOM 解æžå™¨ã€‚ + +3. RapidJSON 与 RapidXML 相似么? + + RapidJSON 借镜了 RapidXML 的一些设计, 包括原ä½ï¼ˆ*in situ*)解æžã€åªæœ‰å¤´æ–‡ä»¶çš„库。但两者的 API 是完全ä¸åŒçš„。此外 RapidJSON 也æ供许多 RapidXML 没有的特点。 + +4. RapidJSON 是å…费的么? + + 是的,它在 MIT å议下å…费。它å¯ç”¨äºŽå•†ä¸šè½¯ä»¶ã€‚详情请å‚看 [license.txt](https://github.com/Tencent/rapidjson/blob/master/license.txt)。 + +5. RapidJSON 很å°ä¹ˆï¼Ÿå®ƒæœ‰ä½•ä¾èµ–? + + 是的。在 Windows ä¸Šï¼Œä¸€ä¸ªè§£æž JSON 并打å°å‡ºç»Ÿè®¡çš„å¯æ‰§è¡Œæ–‡ä»¶å°‘于 30KB。 + + RapidJSON ä»…ä¾èµ–于 C++ 标准库。 + +6. 怎样安装 RapidJSON? + + è§ [安装一节](../readme.zh-cn.md#安装)。 + +7. RapidJSON 能å¦è¿è¡ŒäºŽæˆ‘çš„å¹³å°ï¼Ÿ + + 社区已在多个æ“作系统ï¼ç¼–译器ï¼CPU 架构的组åˆä¸Šæµ‹è¯• RapidJSON。但我们无法确ä¿å®ƒèƒ½è¿è¡ŒäºŽä½ ç‰¹å®šçš„å¹³å°ä¸Šã€‚åªéœ€è¦ç”ŸæˆåŠæ‰§è¡Œå•å…ƒæµ‹è¯•ä¾¿èƒ½èŽ·å–答案。 + +8. RapidJSON æ”¯æŒ C++03 么?C++11 呢? + + RapidJSON 开始时在 C++03 上实现。åŽæ¥åŠ å…¥äº†å¯é€‰çš„ C++11 特性支æŒï¼ˆå¦‚转移构造函数ã€`noexcept`)。RapidJSON 应该兼容所有éµä»Ž C++03 或 C++11 的编译器。 + +9. RapidJSON 是å¦çœŸçš„用于实际应用? + + 是的。它被é…置于å‰å°åŠåŽå°çš„真实应用中。一个社区æˆå‘˜è¯´ RapidJSON 在他们的系统中æ¯æ—¥è§£æž 5 åƒä¸‡ä¸ª JSON。 + +10. RapidJSON 是如何被测试的? + + RapidJSON 包å«ä¸€ç»„å•å…ƒæµ‹è¯•åŽ»æ‰§è¡Œè‡ªåŠ¨æµ‹è¯•ã€‚[Travis](https://travis-ci.org/Tencent/rapidjson/)(供 Linux å¹³å°ï¼‰åŠ [AppVeyor](https://ci.appveyor.com/project/Tencent/rapidjson/)(供 Windows å¹³å°ï¼‰ä¼šå¯¹æ‰€æœ‰ä¿®æ”¹è¿›è¡Œç¼–译åŠæ‰§è¡Œå•å…ƒæµ‹è¯•ã€‚在 Linux 下还会使用 Valgrind 去检测内存泄æ¼ã€‚ + +11. RapidJSON 是å¦æœ‰å®Œæ•´çš„文档? + + RapidJSON æä¾›äº†ä½¿ç”¨æ‰‹å†ŒåŠ API 说明文档。 + +12. 有没有其他替代å“? + + 有许多替代å“。例如 [nativejson-benchmark](https://github.com/miloyip/nativejson-benchmark) 列出了一些开æºçš„ C/C++ JSON 库。[json.org](http://www.json.org/) 也有一个列表。 + +## JSON + +1. 什么是 JSON? + + JSON (JavaScript Object Notation) 是一个轻é‡çš„æ•°æ®äº¤æ¢æ ¼å¼ã€‚它使用人类å¯è¯»çš„文本格å¼ã€‚更多关于 JSON 的细节å¯è€ƒ [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) åŠ [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)。 + +2. JSON 有什么应用场åˆï¼Ÿ + + JSON 常用于网页应用程åºï¼Œä»¥ä¼ é€ç»“构化数æ®ã€‚它也å¯ä½œä¸ºæ–‡ä»¶æ ¼å¼ç”¨äºŽæ•°æ®æŒä¹…化。 + +3. RapidJSON 是å¦ç¬¦åˆ JSON 标准? + + 是。RapidJSON å®Œå…¨ç¬¦åˆ [RFC7159](http://www.ietf.org/rfc/rfc7159.txt) åŠ [ECMA-404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)。它能处ç†ä¸€äº›ç‰¹æ®Šæƒ…å†µï¼Œä¾‹å¦‚æ”¯æŒ JSON 字符串中å«æœ‰ç©ºå­—符åŠä»£ç†å¯¹ï¼ˆsurrogate pair)。 + +4. RapidJSON 是å¦æ”¯æŒå®½æ¾çš„语法? + + ç›®å‰ä¸æ”¯æŒã€‚RapidJSON åªæ”¯æŒä¸¥æ ¼çš„标准格å¼ã€‚宽æ¾è¯­æ³•å¯ä»¥åœ¨è¿™ä¸ª [issue](https://github.com/Tencent/rapidjson/issues/36) 中进行讨论。 + +## DOM 与 SAX + +1. 什么是 DOM 风格 API? + + Document Object Model(DOM)是一个储存于内存的 JSON 表示方å¼ï¼Œç”¨äºŽæŸ¥è¯¢åŠä¿®æ”¹ JSON。 + +2. 什么是 SAX 风格 API? + + SAX 是一个事件驱动的 API,用于解æžåŠç”Ÿæˆ JSON。 + +3. 我应用 DOM 还是 SAX? + + DOM 易于查询åŠä¿®æ”¹ã€‚SAX 则是éžå¸¸å¿«åŠçœå†…存的,但通常较难使用。 + +4. 什么是原ä½ï¼ˆ*in situ*)解æžï¼Ÿ + + 原ä½è§£æžä¼šæŠŠ JSON 字符串直接解ç è‡³è¾“入的 JSON 中。这是一个优化,å¯å‡å°‘内存消耗åŠæå‡æ€§èƒ½ï¼Œä½†è¾“入的 JSON 会被更改。进一步细节请å‚考 [原ä½è§£æž](doc/dom.zh-cn.md) 。 + +5. 什么时候会产生解æžé”™è¯¯ï¼Ÿ + + 当输入的 JSON 包å«éžæ³•è¯­æ³•ï¼Œæˆ–ä¸èƒ½è¡¨ç¤ºä¸€ä¸ªå€¼ï¼ˆå¦‚ Number 太大),或解æžå™¨çš„处ç†å™¨ä¸­æ–­è§£æžè¿‡ç¨‹ï¼Œè§£æžå™¨éƒ½ä¼šäº§ç”Ÿä¸€ä¸ªé”™è¯¯ã€‚详情请å‚考 [解æžé”™è¯¯](doc/dom.zh-cn.md)。 + +6. 有什么错误信æ¯ï¼Ÿ + + 错误信æ¯å­˜å‚¨åœ¨ `ParseResult`,它包å«é”™è¯¯ä»£å·åŠå移值(从 JSON 开始至错误处的字符数目)。å¯ä»¥æŠŠé”™è¯¯ä»£å·ç¿»è¯‘为人类å¯è¯»çš„错误讯æ¯ã€‚ + +7. 为何ä¸åªä½¿ç”¨ `double` 去表示 JSON number? + + 一些应用需è¦ä½¿ç”¨ 64 ä½æ— å·ï¼æœ‰å·æ•´æ•°ã€‚这些整数ä¸èƒ½æ— æŸåœ°è½¬æ¢æˆ `double`。因此解æžå™¨ä¼šæ£€æµ‹ä¸€ä¸ª JSON number 是å¦èƒ½è½¬æ¢è‡³å„ç§æ•´æ•°ç±»åž‹åŠ `double`。 + +8. 如何清空并最å°åŒ– `document` 或 `value` 的容é‡ï¼Ÿ + + 调用 `SetXXX()` 方法 - 这些方法会调用æžæž„函数,并é‡å»ºç©ºçš„ Object 或 Array: + + ~~~~~~~~~~cpp + Document d; + ... + d.SetObject(); // clear and minimize + ~~~~~~~~~~ + + å¦å¤–,也å¯ä»¥å‚考在 [C++ swap with temporary idiom](https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Clear-and-minimize) 中的一ç§ç­‰ä»·çš„方法: + ~~~~~~~~~~cpp + Value(kObjectType).Swap(d); + ~~~~~~~~~~ + 或者,使用这个ç¨å¾®é•¿ä¸€ç‚¹çš„代ç ä¹Ÿèƒ½å®ŒæˆåŒæ ·çš„事情: + ~~~~~~~~~~cpp + d.Swap(Value(kObjectType).Move()); + ~~~~~~~~~~ + +9. 如何将一个 `document` 节点æ’入到å¦ä¸€ä¸ª `document` 中? + + 比如有以下两个 document(DOM): + ~~~~~~~~~~cpp + Document person; + person.Parse("{\"person\":{\"name\":{\"first\":\"Adam\",\"last\":\"Thomas\"}}}"); + + Document address; + address.Parse("{\"address\":{\"city\":\"Moscow\",\"street\":\"Quiet\"}}"); + ~~~~~~~~~~ + å‡è®¾æˆ‘们希望将整个 `address` æ’入到 `person` 中,作为其的一个å­èŠ‚点: + ~~~~~~~~~~js + { "person": { + "name": { "first": "Adam", "last": "Thomas" }, + "address": { "city": "Moscow", "street": "Quiet" } + } + } + ~~~~~~~~~~ + + 在æ’入节点的过程中需è¦æ³¨æ„ `document` å’Œ `value` 的生命周期并且正确地使用 allocator 进行内存分é…和管ç†ã€‚ + + 一个简å•æœ‰æ•ˆçš„方法就是修改上述 `address` å˜é‡çš„定义,让其使用 `person` çš„ allocator åˆå§‹åŒ–,然åŽå°†å…¶æ·»åŠ åˆ°æ ¹èŠ‚点。 + + ~~~~~~~~~~cpp + Documnet address(&person.GetAllocator()); + ... + person["person"].AddMember("address", address["address"], person.GetAllocator()); + ~~~~~~~~~~ + 当然,如果你ä¸æƒ³é€šè¿‡æ˜¾å¼åœ°å†™å‡º `address` çš„ key æ¥å¾—到其值,å¯ä»¥ä½¿ç”¨è¿­ä»£å™¨æ¥å®žçŽ°: + ~~~~~~~~~~cpp + auto addressRoot = address.MemberBegin(); + person["person"].AddMember(addressRoot->name, addressRoot->value, person.GetAllocator()); + ~~~~~~~~~~ + + 此外,还å¯ä»¥é€šè¿‡æ·±æ‹·è´ address document æ¥å®žçŽ°: + ~~~~~~~~~~cpp + Value addressValue = Value(address["address"], person.GetAllocator()); + person["person"].AddMember("address", addressValue, person.GetAllocator()); + ~~~~~~~~~~ + +## Document/Value (DOM) + +1. 什么是转移语义?为什么? + + `Value` ä¸ç”¨å¤åˆ¶è¯­ä¹‰ï¼Œè€Œä½¿ç”¨äº†è½¬ç§»è¯­ä¹‰ã€‚这是指,当把æ¥æºå€¼èµ‹å€¼äºŽç›®æ ‡å€¼æ—¶ï¼Œæ¥æºå€¼çš„所有æƒä¼šè½¬ç§»è‡³ç›®æ ‡å€¼ã€‚ + + 由于转移快于å¤åˆ¶ï¼Œæ­¤è®¾è®¡å†³å®šå¼ºè¿«ä½¿ç”¨è€…注æ„到å¤åˆ¶çš„消耗。 + +2. 怎样去å¤åˆ¶ä¸€ä¸ªå€¼ï¼Ÿ + + 有两个 API å¯ç”¨ï¼šå« allocator çš„æž„é€ å‡½æ•°ï¼Œä»¥åŠ `CopyFrom()`。å¯å‚考 [æ·±å¤åˆ¶ Value](doc/tutorial.zh-cn.md) 里的用例。 + +3. 为什么我需è¦æ供字符串的长度? + + 由于 C 字符串是空字符结尾的,需è¦ä½¿ç”¨ `strlen()` 去计算其长度,这是线性å¤æ‚度的æ“作。若使用者已知字符串的长度,对很多æ“作æ¥è¯´ä¼šé€ æˆä¸å¿…è¦çš„消耗。 + + 此外,RapidJSON å¯å¤„ç†å«æœ‰ `\u0000`(空字符)的字符串。若一个字符串å«æœ‰ç©ºå­—符,`strlen()` 便ä¸èƒ½è¿”回真正的字符串长度。在这ç§æƒ…况下使用者必须明确地æ供字符串长度。 + +4. 为什么在许多 DOM æ“作 API 中è¦æ供分é…器作为å‚数? + + 由于这些 API 是 `Value` çš„æˆå‘˜å‡½æ•°ï¼Œæˆ‘们ä¸å¸Œæœ›ä¸ºæ¯ä¸ª `Value` 储存一个分é…器指针。 + +5. 它会转æ¢å„ç§æ•°å€¼ç±»åž‹ä¹ˆï¼Ÿ + + 当使用 `GetInt()`ã€`GetUint()` ç­‰ API 时,å¯èƒ½ä¼šå‘生转æ¢ã€‚对于整数至整数转æ¢ï¼Œä»…当ä¿è¯è½¬æ¢å®‰å…¨æ‰ä¼šè½¬æ¢ï¼ˆå¦åˆ™ä¼šæ–­è¨€å¤±è´¥ï¼‰ã€‚然而,当把一个 64 ä½æœ‰å·ï¼æ— å·æ•´æ•°è½¬æ¢è‡³ double 时,它会转æ¢ï¼Œä½†æœ‰å¯èƒ½ä¼šæŸå¤±ç²¾åº¦ã€‚å«æœ‰å°æ•°çš„æ•°å­—ã€æˆ–大于 64 ä½çš„整数,都åªèƒ½ä½¿ç”¨ `GetDouble()` 获å–其值。 + +## Reader/Writer (SAX) + +1. 为什么ä¸ä»…仅用 `printf` 输出一个 JSONï¼Ÿä¸ºä»€ä¹ˆéœ€è¦ `Writer`? + + 最é‡è¦çš„是,`Writer` 能确ä¿è¾“出的 JSON 是格å¼æ­£ç¡®çš„。错误地调用 SAX 事件(如 `StartObject()` é”™é… `EndArray()`)会造æˆæ–­è¨€å¤±è´¥ã€‚此外,`Writer` 会把字符串进行转义(如 `\n`)。最åŽï¼Œ`printf()` 的数值输出å¯èƒ½å¹¶ä¸æ˜¯ä¸€ä¸ªåˆæ³•çš„ JSON number,特别是æŸäº› locale 会有数字分隔符。而且 `Writer` 的数值字符串转æ¢æ˜¯ä½¿ç”¨éžå¸¸å¿«çš„算法æ¥å®žçŽ°çš„,胜过 `printf()` åŠ `iostream`。 + +2. 我能å¦æš‚åœè§£æžè¿‡ç¨‹ï¼Œå¹¶åœ¨ç¨åŽç»§ç»­ï¼Ÿ + + 基于性能考虑,目å‰ç‰ˆæœ¬å¹¶ä¸ç›´æŽ¥æ”¯æŒæ­¤åŠŸèƒ½ã€‚然而,若执行环境支æŒå¤šçº¿ç¨‹ï¼Œä½¿ç”¨è€…å¯ä»¥åœ¨å¦ä¸€çº¿ç¨‹è§£æž JSON,并通过阻塞输入æµåŽ»æš‚åœã€‚ + +## Unicode + +1. 它是å¦æ”¯æŒ UTF-8ã€UTF-16 åŠå…¶ä»–æ ¼å¼ï¼Ÿ + + æ˜¯ã€‚å®ƒå®Œå…¨æ”¯æŒ UTF-8ã€UTF-16(大端ï¼å°ç«¯ï¼‰ã€UTF-32(大端ï¼å°ç«¯ï¼‰åŠ ASCII。 + +2. 它能å¦æ£€æµ‹ç¼–ç çš„åˆæ³•æ€§ï¼Ÿ + + 能。åªéœ€æŠŠ `kParseValidateEncodingFlag` å‚考传给 `Parse()`。若å‘现在输入æµä¸­æœ‰éžæ³•çš„ç¼–ç ï¼Œå®ƒå°±ä¼šäº§ç”Ÿ `kParseErrorStringInvalidEncoding` 错误。 + +3. 什么是代ç†å¯¹ï¼ˆsurrogate pair)?RapidJSON 是å¦æ”¯æŒï¼Ÿ + + JSON 使用 UTF-16 ç¼–ç åŽ»è½¬ä¹‰ Unicode 字符,例如 `\u5927` 表示中文字“大â€ã€‚è¦å¤„ç†åŸºæœ¬å¤šæ–‡ç§å¹³é¢ï¼ˆbasic multilingual plane,BMP)以外的字符时,UTF-16 会把那些字符编ç æˆä¸¤ä¸ª 16 ä½å€¼ï¼Œè¿™ç§°ä¸º UTF-16 代ç†å¯¹ã€‚例如,绘文字字符 U+1F602 在 JSON 中å¯è¢«ç¼–ç æˆ `\uD83D\uDE02`。 + + RapidJSON 完全支æŒè§£æžåŠç”Ÿæˆ UTF-16 代ç†å¯¹ã€‚ + +4. 它能å¦å¤„ç† JSON 字符串中的 `\u0000`(空字符)? + + 能。RapidJSON å®Œå…¨æ”¯æŒ JSON 字符串中的空字符。然而,使用者需è¦æ³¨æ„到这件事,并使用 `GetStringLength()` åŠç›¸å…³ API 去å–得字符串真正长度。 + +5. 能å¦å¯¹æ‰€æœ‰éž ASCII å­—ç¬¦è¾“å‡ºæˆ `\uxxxx` å½¢å¼ï¼Ÿ + + å¯ä»¥ã€‚åªè¦åœ¨ `Writer` 中使用 `ASCII<>` 作为输出编ç å‚数,就å¯ä»¥å¼ºé€¼è½¬ä¹‰é‚£äº›å­—符。 + +## æµ + +1. 我有一个很大的 JSON 文件。我应å¦æŠŠå®ƒæ•´ä¸ªè½½å…¥å†…存中? + + 使用者å¯ä½¿ç”¨ `FileReadStream` 去é€å—读入文件。但若使用于原ä½è§£æžï¼Œå¿…须载入整个文件。 + +2. 我能å¦è§£æžä¸€ä¸ªä»Žç½‘络上串æµè¿›æ¥çš„ JSON? + + å¯ä»¥ã€‚使用者å¯æ ¹æ® `FileReadStream` 的实现,去实现一个自定义的æµã€‚ + +3. 我ä¸çŸ¥é“一些 JSON 将会使用哪ç§ç¼–ç ã€‚怎样处ç†å®ƒä»¬ï¼Ÿ + + ä½ å¯ä»¥ä½¿ç”¨ `AutoUTFInputStream`,它能自动检测输入æµçš„ç¼–ç ã€‚然而,它会带æ¥ä¸€äº›æ€§èƒ½å¼€é”€ã€‚ + +4. 什么是 BOM?RapidJSON 怎样处ç†å®ƒï¼Ÿ + + [字节顺åºæ ‡è®°ï¼ˆbyte order mark, BOM)](http://en.wikipedia.org/wiki/Byte_order_mark) 有时会出现于文件ï¼æµçš„开始,以表示其 UTF ç¼–ç ç±»åž‹ã€‚ + + RapidJSON çš„ `EncodedInputStream` å¯æ£€æµ‹ï¼è·³è¿‡ BOM。`EncodedOutputStream` å¯é€‰æ‹©æ˜¯å¦å†™å…¥ BOM。å¯å‚考 [ç¼–ç æµ](doc/stream.zh-cn.md) 中的例å­ã€‚ + +5. 为什么会涉åŠå¤§ç«¯ï¼å°ç«¯ï¼Ÿ + + æµçš„大端ï¼å°ç«¯æ˜¯ UTF-16 åŠ UTF-32 æµè¦å¤„ç†çš„问题,而 UTF-8 ä¸éœ€è¦å¤„ç†ã€‚ + +## 性能 + +1. RapidJSON 是å¦çœŸçš„快? + + 是。它å¯èƒ½æ˜¯æœ€å¿«çš„å¼€æº JSON 库。有一个 [评测](https://github.com/miloyip/nativejson-benchmark) 评估 C/C++ JSON 库的性能。 + +2. 为什么它会快? + + RapidJSON 的许多设计是针对时间ï¼ç©ºé—´æ€§èƒ½æ¥è®¾è®¡çš„,这些决定å¯èƒ½ä¼šå½±å“ API 的易用性。此外,它也使用了许多底层优化(内部函数ï¼intrinsicã€SIMD)åŠç‰¹åˆ«çš„算法(自定义的 double 至字符串转æ¢ã€å­—符串至 double 的转æ¢ï¼‰ã€‚ + +3. 什是是 SIMD?它如何用于 RapidJSON? + + [SIMD](http://en.wikipedia.org/wiki/SIMD) 指令å¯ä»¥åœ¨çŽ°ä»£ CPU 中执行并行è¿ç®—。RapidJSON 支æŒä½¿ç”¨ Intel çš„ SSE2/SSE4.2 å’Œ ARM çš„ Neon æ¥åŠ é€Ÿå¯¹ç©ºç™½ç¬¦ã€åˆ¶è¡¨ç¬¦ã€å›žè½¦ç¬¦å’Œæ¢è¡Œç¬¦çš„过滤处ç†ã€‚在解æžå«ç¼©è¿›çš„ JSON 时,这能æå‡æ€§èƒ½ã€‚åªè¦å®šä¹‰å为 `RAPIDJSON_SSE2` ,`RAPIDJSON_SSE42` 或 `RAPIDJSON_NEON` çš„å®ï¼Œå°±èƒ½å¯åŠ¨è¿™ä¸ªåŠŸèƒ½ã€‚然而,若在ä¸æ”¯æŒè¿™äº›æŒ‡ä»¤é›†çš„机器上执行这些å¯æ‰§è¡Œæ–‡ä»¶ï¼Œä¼šå¯¼è‡´å´©æºƒã€‚ + +4. 它会消耗许多内存么? + + RapidJSON 的设计目标是å‡ä½Žå†…å­˜å ç”¨ã€‚ + + 在 SAX API 中,`Reader` 消耗的内存与 JSON 树深度加上最长 JSON 字符æˆæ­£æ¯”。 + + 在 DOM API 中,æ¯ä¸ª `Value` 在 32/64 ä½æž¶æž„下分别消耗 16/24 字节。RapidJSON 也使用一个特殊的内存分é…器去å‡å°‘分é…çš„é¢å¤–开销。 + +5. 高性能的æ„义何在? + + 有些应用程åºéœ€è¦å¤„ç†éžå¸¸å¤§çš„ JSON 文件。而有些åŽå°åº”用程åºéœ€è¦å¤„ç†å¤§é‡çš„ JSON。达到高性能åŒæ—¶æ”¹å–„延时åŠåžåé‡ã€‚更广义æ¥è¯´ï¼Œè¿™ä¹Ÿå¯ä»¥èŠ‚çœèƒ½æºã€‚ + +## å…«å¦ + +1. è°æ˜¯ RapidJSON çš„å¼€å‘者? + + å¶åŠ²å³°ï¼ˆMilo Yip,[miloyip](https://github.com/miloyip))是 RapidJSON 的原作者。全世界许多贡献者一直在改善 RapidJSON。Philipp A. Hartmann([pah](https://github.com/pah))实现了许多改进,也设置了自动化测试,而且还å‚与许多社区讨论。ä¸æ¬§å—(Don Ding,[thebusytypist](https://github.com/thebusytypist))实现了迭代å¼è§£æžå™¨ã€‚Andrii Senkovych([jollyroger](https://github.com/jollyroger))完æˆäº†å‘ CMake çš„è¿ç§»ã€‚Kosta([Kosta-Github](https://github.com/Kosta-Github))æ供了一个éžå¸¸çµå·§çš„短字符串优化。也需è¦æ„Ÿè°¢å…¶ä»–献者åŠç¤¾åŒºæˆå‘˜ã€‚ + +2. 为何你è¦å¼€å‘ RapidJSON? + + 在 2011 年开始这项目时,它åªæ˜¯ä¸€ä¸ªå…´è¶£é¡¹ç›®ã€‚Milo Yip 是一个游æˆç¨‹åºå‘˜ï¼Œä»–在那时候认识到 JSON 并希望在未æ¥çš„项目中使用。由于 JSON 好åƒå¾ˆç®€å•ï¼Œä»–希望写一个快速的仅有头文件的程åºåº“。 + +3. 为什么开å‘中段有一段长期空档? + + 主è¦æ˜¯ä¸ªäººå› ç´ ï¼Œä¾‹å¦‚加入新家庭æˆå‘˜ã€‚å¦å¤–,Milo Yip 也花了许多业余时间去翻译 Jason Gregory 的《Game Engine Architecture》至中文版《游æˆå¼•æ“Žæž¶æž„》。 + +4. 为什么这个项目从 Google Code æ¬åˆ° GitHub? + + 这是大势所趋,而且 GitHub 更为强大åŠæ–¹ä¾¿ã€‚ diff --git a/deps/rapidjson/doc/features.md b/deps/rapidjson/doc/features.md new file mode 100644 index 0000000..4d15937 --- /dev/null +++ b/deps/rapidjson/doc/features.md @@ -0,0 +1,106 @@ +# Features + +## General + +* Cross-platform + * Compilers: Visual Studio, gcc, clang, etc. + * Architectures: x86, x64, ARM, etc. + * Operating systems: Windows, Mac OS X, Linux, iOS, Android, etc. +* Easy installation + * Header files only library. Just copy the headers to your project. +* Self-contained, minimal dependences + * No STL, BOOST, etc. + * Only included ``, ``, ``, ``, ``, ``. +* Without C++ exception, RTTI +* High performance + * Use template and inline functions to reduce function call overheads. + * Internal optimized Grisu2 and floating point parsing implementations. + * Optional SSE2/SSE4.2 support. + +## Standard compliance + +* RapidJSON should be fully RFC4627/ECMA-404 compliance. +* Support JSON Pointer (RFC6901). +* Support JSON Schema Draft v4. +* Support Swagger v2 schema. +* Support OpenAPI v3.0.x schema. +* Support Unicode surrogate. +* Support null character (`"\u0000"`) +* For example, `["Hello\u0000World"]` can be parsed and handled gracefully. There is API for getting/setting lengths of string. +* Support optional relaxed syntax. +* Single line (`// ...`) and multiple line (`/* ... */`) comments (`kParseCommentsFlag`). +* Trailing commas at the end of objects and arrays (`kParseTrailingCommasFlag`). +* `NaN`, `Inf`, `Infinity`, `-Inf` and `-Infinity` as `double` values (`kParseNanAndInfFlag`) +* [NPM compliant](http://github.com/Tencent/rapidjson/blob/master/doc/npm.md). + +## Unicode + +* Support UTF-8, UTF-16, UTF-32 encodings, including little endian and big endian. + * These encodings are used in input/output streams and in-memory representation. +* Support automatic detection of encodings in input stream. +* Support transcoding between encodings internally. + * For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. +* Support encoding validation internally. + * For example, you can read a UTF-8 file, and let RapidJSON check whether all JSON strings are valid UTF-8 byte sequence. +* Support custom character types. + * By default the character types are `char` for UTF8, `wchar_t` for UTF16, `uint32_t` for UTF32. +* Support custom encodings. + +## API styles + +* SAX (Simple API for XML) style API + * Similar to [SAX](http://en.wikipedia.org/wiki/Simple_API_for_XML), RapidJSON provides a event sequential access parser API (`rapidjson::GenericReader`). It also provides a generator API (`rapidjson::Writer`) which consumes the same set of events. +* DOM (Document Object Model) style API + * Similar to [DOM](http://en.wikipedia.org/wiki/Document_Object_Model) for HTML/XML, RapidJSON can parse JSON into a DOM representation (`rapidjson::GenericDocument`), for easy manipulation, and finally stringify back to JSON if needed. + * The DOM style API (`rapidjson::GenericDocument`) is actually implemented with SAX style API (`rapidjson::GenericReader`). SAX is faster but sometimes DOM is easier. Users can pick their choices according to scenarios. + +## Parsing + +* Recursive (default) and iterative parser + * Recursive parser is faster but prone to stack overflow in extreme cases. + * Iterative parser use custom stack to keep parsing state. +* Support *in situ* parsing. + * Parse JSON string values in-place at the source JSON, and then the DOM points to addresses of those strings. + * Faster than convention parsing: no allocation for strings, no copy (if string does not contain escapes), cache-friendly. +* Support 32-bit/64-bit signed/unsigned integer and `double` for JSON number type. +* Support parsing multiple JSONs in input stream (`kParseStopWhenDoneFlag`). +* Error Handling + * Support comprehensive error code if parsing failed. + * Support error message localization. + +## DOM (Document) + +* RapidJSON checks range of numerical values for conversions. +* Optimization for string literal + * Only store pointer instead of copying +* Optimization for "short" strings + * Store short string in `Value` internally without additional allocation. + * For UTF-8 string: maximum 11 characters in 32-bit, 21 characters in 64-bit (13 characters in x86-64). +* Optionally support `std::string` (define `RAPIDJSON_HAS_STDSTRING=1`) + +## Generation + +* Support `rapidjson::PrettyWriter` for adding newlines and indentations. + +## Stream + +* Support `rapidjson::GenericStringBuffer` for storing the output JSON as string. +* Support `rapidjson::FileReadStream` and `rapidjson::FileWriteStream` for input/output `FILE` object. +* Support custom streams. + +## Memory + +* Minimize memory overheads for DOM. + * Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). +* Support fast default allocator. + * A stack-based allocator (allocate sequentially, prohibit to free individual allocations, suitable for parsing). + * User can provide a pre-allocated buffer. (Possible to parse a number of JSONs without any CRT allocation) +* Support standard CRT(C-runtime) allocator. +* Support custom allocators. + +## Miscellaneous + +* Some C++11 support (optional) + * Rvalue reference + * `noexcept` specifier + * Range-based for loop diff --git a/deps/rapidjson/doc/features.zh-cn.md b/deps/rapidjson/doc/features.zh-cn.md new file mode 100644 index 0000000..7662cc1 --- /dev/null +++ b/deps/rapidjson/doc/features.zh-cn.md @@ -0,0 +1,103 @@ +# 特点 + +## 总体 + +* è·¨å¹³å° + * 编译器:Visual Studioã€gccã€clang ç­‰ + * 架构:x86ã€x64ã€ARM ç­‰ + * æ“作系统:Windowsã€Mac OS Xã€Linuxã€iOSã€Android ç­‰ +* 容易安装 + * åªæœ‰å¤´æ–‡ä»¶çš„库。åªéœ€æŠŠå¤´æ–‡ä»¶å¤åˆ¶è‡³ä½ çš„项目中。 +* 独立ã€æœ€å°ä¾èµ– + * ä¸éœ€ä¾èµ– STLã€BOOST 等。 + * åªåŒ…å« ``, ``, ``, ``, ``, ``。 +* 没使用 C++ 异常ã€RTTI +* 高性能 + * 使用模版åŠå†…è”函数去é™ä½Žå‡½æ•°è°ƒç”¨å¼€é”€ã€‚ + * 内部ç»ä¼˜åŒ–çš„ Grisu2 åŠæµ®ç‚¹æ•°è§£æžå®žçŽ°ã€‚ + * å¯é€‰çš„ SSE2/SSE4.2 支æŒã€‚ + +## 符åˆæ ‡å‡† + +* RapidJSON åº”å®Œå…¨ç¬¦åˆ RFC4627/ECMA-404 标准。 +* æ”¯æŒ JSON Pointer (RFC6901). +* æ”¯æŒ JSON Schema Draft v4. +* æ”¯æŒ Unicode 代ç†å¯¹ï¼ˆsurrogate pair)。 +* 支æŒç©ºå­—符(`"\u0000"`)。 + * 例如,å¯ä»¥ä¼˜é›…地解æžåŠå¤„ç† `["Hello\u0000World"]`。å«è¯»å†™å­—符串长度的 API。 +* 支æŒå¯é€‰çš„放宽语法 + * å•è¡Œï¼ˆ`// ...`)åŠå¤šè¡Œï¼ˆ`/* ... */`) 注释 (`kParseCommentsFlag`)。 + * 在对象和数组结æŸå‰å«é€—å· (`kParseTrailingCommasFlag`)。 + * `NaN`ã€`Inf`ã€`Infinity`ã€`-Inf` åŠ `-Infinity` 作为 `double` 值 (`kParseNanAndInfFlag`) +* [NPM 兼容](https://github.com/Tencent/rapidjson/blob/master/doc/npm.md). + +## Unicode + +* æ”¯æŒ UTF-8ã€UTF-16ã€UTF-32 ç¼–ç ï¼ŒåŒ…括å°ç«¯åºå’Œå¤§ç«¯åºã€‚ + * 这些编ç ç”¨äºŽè¾“入输出æµï¼Œä»¥åŠå†…存中的表示。 +* 支æŒä»Žè¾“å…¥æµè‡ªåŠ¨æ£€æµ‹ç¼–ç ã€‚ +* 内部支æŒç¼–ç çš„转æ¢ã€‚ + * 例如,你å¯ä»¥è¯»å–一个 UTF-8 文件,让 RapidJSON 把 JSON 字符串转æ¢è‡³ UTF-16 çš„ DOM。 +* 内部支æŒç¼–ç æ ¡éªŒã€‚ + * 例如,你å¯ä»¥è¯»å–一个 UTF-8 文件,让 RapidJSON 检查是å¦æ‰€æœ‰ JSON 字符串是åˆæ³•çš„ UTF-8 字节åºåˆ—。 +* 支æŒè‡ªå®šä¹‰çš„字符类型。 + * 预设的字符类型是:UTF-8 为 `char`,UTF-16 为 `wchar_t`,UTF32 为 `uint32_t`。 +* 支æŒè‡ªå®šä¹‰çš„ç¼–ç ã€‚ + +## API 风格 + +* SAX(Simple API for XML)风格 API + * 类似于 [SAX](http://en.wikipedia.org/wiki/Simple_API_for_XML), RapidJSON æ供一个事件循åºè®¿é—®çš„解æžå™¨ API(`rapidjson::GenericReader`)。RapidJSON 也æ供一个生æˆå™¨ API(`rapidjson::Writer`),å¯ä»¥å¤„ç†ç›¸åŒçš„事件集åˆã€‚ +* DOM(Document Object Model)风格 API + * 类似于 HTMLï¼XML çš„ [DOM](http://en.wikipedia.org/wiki/Document_Object_Model),RapidJSON å¯æŠŠ JSON 解æžè‡³ä¸€ä¸ª DOM 表示方å¼ï¼ˆ`rapidjson::GenericDocument`),以方便æ“作。如有需è¦ï¼Œå¯æŠŠ DOM 转æ¢ï¼ˆstringify)回 JSON。 + * DOM 风格 API(`rapidjson::GenericDocument`)实际上是由 SAX 风格 API(`rapidjson::GenericReader`)实现的。SAX 更快,但有时 DOM 更易用。用户å¯æ ¹æ®æƒ…况作出选择。 + +## è§£æž + +* 递归å¼ï¼ˆé¢„设)åŠè¿­ä»£å¼è§£æžå™¨ + * 递归å¼è§£æžå™¨è¾ƒå¿«ï¼Œä½†åœ¨æžç«¯æƒ…况下å¯å‡ºçŽ°å †æ ˆæº¢å‡ºã€‚ + * 迭代å¼è§£æžå™¨ä½¿ç”¨è‡ªå®šä¹‰çš„堆栈去维æŒè§£æžçŠ¶æ€ã€‚ +* 支æŒåŽŸä½ï¼ˆ*in situ*)解æžã€‚ + * 把 JSON 字符串的值解æžè‡³åŽŸ JSON 之中,然åŽè®© DOM 指å‘那些字符串。 + * 比常规分æžæ›´å¿«ï¼šä¸éœ€å­—符串的内存分é…ã€ä¸éœ€å¤åˆ¶ï¼ˆå¦‚字符串ä¸å«è½¬ä¹‰ç¬¦ï¼‰ã€ç¼“å­˜å‹å¥½ã€‚ +* 对于 JSON æ•°å­—ç±»åž‹ï¼Œæ”¯æŒ 32-bit/64-bit 的有å·ï¼æ— å·æ•´æ•°ï¼Œä»¥åŠ `double`。 +* é”™è¯¯å¤„ç† + * 支æŒè¯¦å°½çš„解æžé”™è¯¯ä»£å·ã€‚ + * 支æŒæœ¬åœ°åŒ–错误信æ¯ã€‚ + +## DOM (Document) + +* RapidJSON 在类型转æ¢æ—¶ä¼šæ£€æŸ¥æ•°å€¼çš„范围。 +* 字符串字é¢é‡çš„优化 + * åªå‚¨å­˜æŒ‡é’ˆï¼Œä¸ä½œå¤åˆ¶ +* 优化“短â€å­—符串 + * 在 `Value` 内储存短字符串,无需é¢å¤–分é…。 + * 对 UTF-8 字符串æ¥è¯´ï¼Œ32 ä½æž¶æž„下å¯å­˜å‚¨æœ€å¤š 11 字符,64 ä½ä¸‹ 21 字符(x86-64 下 13 字符)。 +* å¯é€‰åœ°æ”¯æŒ `std::string`(定义 `RAPIDJSON_HAS_STDSTRING=1`) + +## ç”Ÿæˆ + +* æ”¯æŒ `rapidjson::PrettyWriter` 去加入æ¢è¡ŒåŠç¼©è¿›ã€‚ + +## è¾“å…¥è¾“å‡ºæµ + +* æ”¯æŒ `rapidjson::GenericStringBuffer`,把输出的 JSON 储存于字符串内。 +* æ”¯æŒ `rapidjson::FileReadStream` åŠ `rapidjson::FileWriteStream`,使用 `FILE` 对象作输入输出。 +* 支æŒè‡ªå®šä¹‰è¾“入输出æµã€‚ + +## 内存 + +* 最å°åŒ– DOM 的内存开销。 + * 对大部分 32ï¼64 ä½æœºå™¨è€Œè¨€ï¼Œæ¯ä¸ª JSON 值åªå  16 或 20 字节(ä¸åŒ…å«å­—符串)。 +* 支æŒå¿«é€Ÿçš„预设分é…器。 + * 它是一个堆栈形å¼çš„分é…器(顺åºåˆ†é…,ä¸å®¹è®¸å•ç‹¬é‡Šæ”¾ï¼Œé€‚åˆè§£æžè¿‡ç¨‹ä¹‹ç”¨ï¼‰ã€‚ + * 使用者也å¯æ供一个预分é…的缓冲区。(有å¯èƒ½è¾¾è‡³æ— éœ€ CRT 分é…就能解æžå¤šä¸ª JSON) +* 支æŒæ ‡å‡† CRT(C-runtime)分é…器。 +* 支æŒè‡ªå®šä¹‰åˆ†é…器。 + +## 其他 + +* 一些 C++11 的支æŒï¼ˆå¯é€‰ï¼‰ + * å³å€¼å¼•ç”¨ï¼ˆrvalue reference) + * `noexcept` 修饰符 + * 范围 for 循环 diff --git a/deps/rapidjson/doc/internals.md b/deps/rapidjson/doc/internals.md new file mode 100644 index 0000000..81fe9c1 --- /dev/null +++ b/deps/rapidjson/doc/internals.md @@ -0,0 +1,368 @@ +# Internals + +This section records some design and implementation details. + +[TOC] + +# Architecture {#Architecture} + +## SAX and DOM + +The basic relationships of SAX and DOM is shown in the following UML diagram. + +![Architecture UML class diagram](diagram/architecture.png) + +The core of the relationship is the `Handler` concept. From the SAX side, `Reader` parses a JSON from a stream and publish events to a `Handler`. `Writer` implements the `Handler` concept to handle the same set of events. From the DOM side, `Document` implements the `Handler` concept to build a DOM according to the events. `Value` supports a `Value::Accept(Handler&)` function, which traverses the DOM to publish events. + +With this design, SAX is not dependent on DOM. Even `Reader` and `Writer` have no dependencies between them. This provides flexibility to chain event publisher and handlers. Besides, `Value` does not depends on SAX as well. So, in addition to stringify a DOM to JSON, user may also stringify it to a XML writer, or do anything else. + +## Utility Classes + +Both SAX and DOM APIs depends on 3 additional concepts: `Allocator`, `Encoding` and `Stream`. Their inheritance hierarchy is shown as below. + +![Utility classes UML class diagram](diagram/utilityclass.png) + +# Value {#Value} + +`Value` (actually a typedef of `GenericValue>`) is the core of DOM API. This section describes the design of it. + +## Data Layout {#DataLayout} + +`Value` is a [variant type](http://en.wikipedia.org/wiki/Variant_type). In RapidJSON's context, an instance of `Value` can contain 1 of 6 JSON value types. This is possible by using `union`. Each `Value` contains two members: `union Data data_` and a`unsigned flags_`. The `flags_` indicates the JSON type, and also additional information. + +The following tables show the data layout of each type. The 32-bit/64-bit columns indicates the size of the field in bytes. + +| Null | |32-bit|64-bit| +|-------------------|----------------------------------|:----:|:----:| +| (unused) | |4 |8 | +| (unused) | |4 |4 | +| (unused) | |4 |4 | +| `unsigned flags_` | `kNullType kNullFlag` |4 |4 | + +| Bool | |32-bit|64-bit| +|-------------------|----------------------------------------------------|:----:|:----:| +| (unused) | |4 |8 | +| (unused) | |4 |4 | +| (unused) | |4 |4 | +| `unsigned flags_` | `kBoolType` (either `kTrueFlag` or `kFalseFlag`) |4 |4 | + +| String | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `Ch* str` | Pointer to the string (may own) |4 |8 | +| `SizeType length` | Length of string |4 |4 | +| (unused) | |4 |4 | +| `unsigned flags_` | `kStringType kStringFlag ...` |4 |4 | + +| Object | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `Member* members` | Pointer to array of members (owned) |4 |8 | +| `SizeType size` | Number of members |4 |4 | +| `SizeType capacity` | Capacity of members |4 |4 | +| `unsigned flags_` | `kObjectType kObjectFlag` |4 |4 | + +| Array | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `Value* values` | Pointer to array of values (owned) |4 |8 | +| `SizeType size` | Number of values |4 |4 | +| `SizeType capacity` | Capacity of values |4 |4 | +| `unsigned flags_` | `kArrayType kArrayFlag` |4 |4 | + +| Number (Int) | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `int i` | 32-bit signed integer |4 |4 | +| (zero padding) | 0 |4 |4 | +| (unused) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kIntFlag kInt64Flag ...` |4 |4 | + +| Number (UInt) | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `unsigned u` | 32-bit unsigned integer |4 |4 | +| (zero padding) | 0 |4 |4 | +| (unused) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 | + +| Number (Int64) | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `int64_t i64` | 64-bit signed integer |8 |8 | +| (unused) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kInt64Flag ...` |4 |4 | + +| Number (Uint64) | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `uint64_t i64` | 64-bit unsigned integer |8 |8 | +| (unused) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kInt64Flag ...` |4 |4 | + +| Number (Double) | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `uint64_t i64` | Double precision floating-point |8 |8 | +| (unused) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kDoubleFlag` |4 |4 | + +Here are some notes: +* To reduce memory consumption for 64-bit architecture, `SizeType` is typedef as `unsigned` instead of `size_t`. +* Zero padding for 32-bit number may be placed after or before the actual type, according to the endianness. This makes possible for interpreting a 32-bit integer as a 64-bit integer, without any conversion. +* An `Int` is always an `Int64`, but the converse is not always true. + +## Flags {#Flags} + +The 32-bit `flags_` contains both JSON type and other additional information. As shown in the above tables, each JSON type contains redundant `kXXXType` and `kXXXFlag`. This design is for optimizing the operation of testing bit-flags (`IsNumber()`) and obtaining a sequential number for each type (`GetType()`). + +String has two optional flags. `kCopyFlag` means that the string owns a copy of the string. `kInlineStrFlag` means using [Short-String Optimization](#ShortString). + +Number is a bit more complicated. For normal integer values, it can contains `kIntFlag`, `kUintFlag`, `kInt64Flag` and/or `kUint64Flag`, according to the range of the integer. For numbers with fraction, and integers larger than 64-bit range, they will be stored as `double` with `kDoubleFlag`. + +## Short-String Optimization {#ShortString} + + [Kosta](https://github.com/Kosta-Github) provided a very neat short-string optimization. The optimization idea is given as follow. Excluding the `flags_`, a `Value` has 12 or 16 bytes (32-bit or 64-bit) for storing actual data. Instead of storing a pointer to a string, it is possible to store short strings in these space internally. For encoding with 1-byte character type (e.g. `char`), it can store maximum 11 or 15 characters string inside the `Value` type. + +| ShortString (Ch=char) | |32-bit|64-bit| +|---------------------|-------------------------------------|:----:|:----:| +| `Ch str[MaxChars]` | String buffer |11 |15 | +| `Ch invLength` | MaxChars - Length |1 |1 | +| `unsigned flags_` | `kStringType kStringFlag ...` |4 |4 | + +A special technique is applied. Instead of storing the length of string directly, it stores (MaxChars - length). This make it possible to store 11 characters with trailing `\0`. + +This optimization can reduce memory usage for copy-string. It can also improve cache-coherence thus improve runtime performance. + +# Allocator {#InternalAllocator} + +`Allocator` is a concept in RapidJSON: +~~~cpp +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +~~~ + +Note that `Malloc()` and `Realloc()` are member functions but `Free()` is static member function. + +## MemoryPoolAllocator {#MemoryPoolAllocator} + +`MemoryPoolAllocator` is the default allocator for DOM. It allocate but do not free memory. This is suitable for building a DOM tree. + +Internally, it allocates chunks of memory from the base allocator (by default `CrtAllocator`) and stores the chunks as a singly linked list. When user requests an allocation, it allocates memory from the following order: + +1. User supplied buffer if it is available. (See [User Buffer section in DOM](doc/dom.md)) +2. If user supplied buffer is full, use the current memory chunk. +3. If the current block is full, allocate a new block of memory. + +# Parsing Optimization {#ParsingOptimization} + +## Skip Whitespaces with SIMD {#SkipwhitespaceWithSIMD} + +When parsing JSON from a stream, the parser need to skip 4 whitespace characters: + +1. Space (`U+0020`) +2. Character Tabulation (`U+000B`) +3. Line Feed (`U+000A`) +4. Carriage Return (`U+000D`) + +A simple implementation will be simply: +~~~cpp +void SkipWhitespace(InputStream& s) { + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); +} +~~~ + +However, this requires 4 comparisons and a few branching for each character. This was found to be a hot spot. + +To accelerate this process, SIMD was applied to compare 16 characters with 4 white spaces for each iteration. Currently RapidJSON supports SSE2, SSE4.2 and ARM Neon instructions for this. And it is only activated for UTF-8 memory streams, including string stream or *in situ* parsing. + +To enable this optimization, need to define `RAPIDJSON_SSE2`, `RAPIDJSON_SSE42` or `RAPIDJSON_NEON` before including `rapidjson.h`. Some compilers can detect the setting, as in `perftest.h`: + +~~~cpp +// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler. +// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported. +// Likewise, __ARM_NEON is used to detect Neon. +#if defined(__SSE4_2__) +# define RAPIDJSON_SSE42 +#elif defined(__SSE2__) +# define RAPIDJSON_SSE2 +#elif defined(__ARM_NEON) +# define RAPIDJSON_NEON +#endif +~~~ + +Note that, these are compile-time settings. Running the executable on a machine without such instruction set support will make it crash. + +### Page boundary issue + +In an early version of RapidJSON, [an issue](https://code.google.com/archive/p/rapidjson/issues/104) reported that the `SkipWhitespace_SIMD()` causes crash very rarely (around 1 in 500,000). After investigation, it is suspected that `_mm_loadu_si128()` accessed bytes after `'\0'`, and across a protected page boundary. + +In [Intel® 64 and IA-32 Architectures Optimization Reference Manual +](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html), section 10.2.1: + +> To support algorithms requiring unaligned 128-bit SIMD memory accesses, memory buffer allocation by a caller function should consider adding some pad space so that a callee function can safely use the address pointer safely with unaligned 128-bit SIMD memory operations. +> The minimal padding size should be the width of the SIMD register that might be used in conjunction with unaligned SIMD memory access. + +This is not feasible as RapidJSON should not enforce such requirement. + +To fix this issue, currently the routine process bytes up to the next aligned address. After tha, use aligned read to perform SIMD processing. Also see [#85](https://github.com/Tencent/rapidjson/issues/85). + +## Local Stream Copy {#LocalStreamCopy} + +During optimization, it is found that some compilers cannot localize some member data access of streams into local variables or registers. Experimental results show that for some stream types, making a copy of the stream and used it in inner-loop can improve performance. For example, the actual (non-SIMD) implementation of `SkipWhitespace()` is implemented as: + +~~~cpp +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); +} +~~~ + +Depending on the traits of stream, `StreamLocalCopy` will make (or not make) a copy of the stream object, use it locally and copy the states of stream back to the original stream. + +## Parsing to Double {#ParsingDouble} + +Parsing string into `double` is difficult. The standard library function `strtod()` can do the job but it is slow. By default, the parsers use normal precision setting. This has has maximum 3 [ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place) error and implemented in `internal::StrtodNormalPrecision()`. + +When using `kParseFullPrecisionFlag`, the parsers calls `internal::StrtodFullPrecision()` instead, and this function actually implemented 3 versions of conversion methods. +1. [Fast-Path](http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/). +2. Custom DIY-FP implementation as in [double-conversion](https://github.com/floitsch/double-conversion). +3. Big Integer Method as in (Clinger, William D. How to read floating point numbers accurately. Vol. 25. No. 6. ACM, 1990). + +If the first conversion methods fail, it will try the second, and so on. + +# Generation Optimization {#GenerationOptimization} + +## Integer-to-String conversion {#itoa} + +The naive algorithm for integer-to-string conversion involves division per each decimal digit. We have implemented various implementations and evaluated them in [itoa-benchmark](https://github.com/miloyip/itoa-benchmark). + +Although SSE2 version is the fastest but the difference is minor by comparing to the first running-up `branchlut`. And `branchlut` is pure C++ implementation so we adopt `branchlut` in RapidJSON. + +## Double-to-String conversion {#dtoa} + +Originally RapidJSON uses `snprintf(..., ..., "%g")` to achieve double-to-string conversion. This is not accurate as the default precision is 6. Later we also find that this is slow and there is an alternative. + +Google's V8 [double-conversion](https://github.com/floitsch/double-conversion +) implemented a newer, fast algorithm called Grisu3 (Loitsch, Florian. "Printing floating-point numbers quickly and accurately with integers." ACM Sigplan Notices 45.6 (2010): 233-243.). + +However, since it is not header-only so that we implemented a header-only version of Grisu2. This algorithm guarantees that the result is always accurate. And in most of cases it produces the shortest (optimal) string representation. + +The header-only conversion function has been evaluated in [dtoa-benchmark](https://github.com/miloyip/dtoa-benchmark). + +# Parser {#Parser} + +## Iterative Parser {#IterativeParser} + +The iterative parser is a recursive descent LL(1) parser +implemented in a non-recursive manner. + +### Grammar {#IterativeParserGrammar} + +The grammar used for this parser is based on strict JSON syntax: +~~~~~~~~~~ +S -> array | object +array -> [ values ] +object -> { members } +values -> non-empty-values | ε +non-empty-values -> value addition-values +addition-values -> ε | , non-empty-values +members -> non-empty-members | ε +non-empty-members -> member addition-members +addition-members -> ε | , non-empty-members +member -> STRING : value +value -> STRING | NUMBER | NULL | BOOLEAN | object | array +~~~~~~~~~~ + +Note that left factoring is applied to non-terminals `values` and `members` +to make the grammar be LL(1). + +### Parsing Table {#IterativeParserParsingTable} + +Based on the grammar, we can construct the FIRST and FOLLOW set. + +The FIRST set of non-terminals is listed below: + +| NON-TERMINAL | FIRST | +|:-----------------:|:--------------------------------:| +| array | [ | +| object | { | +| values | ε STRING NUMBER NULL BOOLEAN { [ | +| addition-values | ε COMMA | +| members | ε STRING | +| addition-members | ε COMMA | +| member | STRING | +| value | STRING NUMBER NULL BOOLEAN { [ | +| S | [ { | +| non-empty-members | STRING | +| non-empty-values | STRING NUMBER NULL BOOLEAN { [ | + +The FOLLOW set is listed below: + +| NON-TERMINAL | FOLLOW | +|:-----------------:|:-------:| +| S | $ | +| array | , $ } ] | +| object | , $ } ] | +| values | ] | +| non-empty-values | ] | +| addition-values | ] | +| members | } | +| non-empty-members | } | +| addition-members | } | +| member | , } | +| value | , } ] | + +Finally the parsing table can be constructed from FIRST and FOLLOW set: + +| NON-TERMINAL | [ | { | , | : | ] | } | STRING | NUMBER | NULL | BOOLEAN | +|:-----------------:|:---------------------:|:---------------------:|:-------------------:|:-:|:-:|:-:|:-----------------------:|:---------------------:|:---------------------:|:---------------------:| +| S | array | object | | | | | | | | | +| array | [ values ] | | | | | | | | | | +| object | | { members } | | | | | | | | | +| values | non-empty-values | non-empty-values | | | ε | | non-empty-values | non-empty-values | non-empty-values | non-empty-values | +| non-empty-values | value addition-values | value addition-values | | | | | value addition-values | value addition-values | value addition-values | value addition-values | +| addition-values | | | , non-empty-values | | ε | | | | | | +| members | | | | | | ε | non-empty-members | | | | +| non-empty-members | | | | | | | member addition-members | | | | +| addition-members | | | , non-empty-members | | | ε | | | | | +| member | | | | | | | STRING : value | | | | +| value | array | object | | | | | STRING | NUMBER | NULL | BOOLEAN | + +There is a great [tool](http://hackingoff.com/compilers/predict-first-follow-set) for above grammar analysis. + +### Implementation {#IterativeParserImplementation} + +Based on the parsing table, a direct(or conventional) implementation +that pushes the production body in reverse order +while generating a production could work. + +In RapidJSON, several modifications(or adaptations to current design) are made to a direct implementation. + +First, the parsing table is encoded in a state machine in RapidJSON. +States are constructed by the head and body of production. +State transitions are constructed by production rules. +Besides, extra states are added for productions involved with `array` and `object`. +In this way the generation of array values or object members would be a single state transition, +rather than several pop/push operations in the direct implementation. +This also makes the estimation of stack size more easier. + +The state diagram is shown as follows: + +![State Diagram](diagram/iterative-parser-states-diagram.png) + +Second, the iterative parser also keeps track of array's value count and object's member count +in its internal stack, which may be different from a conventional implementation. diff --git a/deps/rapidjson/doc/internals.zh-cn.md b/deps/rapidjson/doc/internals.zh-cn.md new file mode 100644 index 0000000..d414fc1 --- /dev/null +++ b/deps/rapidjson/doc/internals.zh-cn.md @@ -0,0 +1,363 @@ +# 内部架构 + +本部分记录了一些设计和实现细节。 + +[TOC] + +# 架构 {#Architecture} + +## SAX å’Œ DOM + +下é¢çš„ UML 图显示了 SAX å’Œ DOM 的基本关系。 + +![架构 UML 类图](diagram/architecture.png) + +关系的核心是 `Handler` 概念。在 SAX 一边,`Reader` 从æµè§£æž JSON 并将事件å‘é€åˆ° `Handler`。`Writer` 实现了 `Handler` 概念,用于处ç†ç›¸åŒçš„事件。在 DOM 一边,`Document` 实现了 `Handler` 概念,用于通过这些时间æ¥æž„建 DOM。`Value` 支æŒäº† `Value::Accept(Handler&)` 函数,它å¯ä»¥å°† DOM 转æ¢ä¸ºäº‹ä»¶è¿›è¡Œå‘é€ã€‚ + +在这个设计,SAX 是ä¸ä¾èµ–于 DOM 的。甚至 `Reader` å’Œ `Writer` 之间也没有ä¾èµ–。这æ供了连接事件å‘é€å™¨å’Œå¤„ç†å™¨çš„çµæ´»æ€§ã€‚除此之外,`Value` 也是ä¸ä¾èµ–于 SAX 的。所以,除了将 DOM åºåˆ—化为 JSON 之外,用户也å¯ä»¥å°†å…¶åºåˆ—化为 XML,或者åšä»»ä½•å…¶ä»–事情。 + +## 工具类 + +SAX å’Œ DOM API 都ä¾èµ–于3个é¢å¤–的概念:`Allocator`ã€`Encoding` å’Œ `Stream`。它们的继承层次结构如下图所示。 + +![工具类 UML 类图](diagram/utilityclass.png) + +# 值(Value) {#Value} + +`Value` (实际上被定义为 `GenericValue>`)是 DOM API 的核心。本部分æ述了它的设计。 + +## æ•°æ®å¸ƒå±€ {#DataLayout} + +`Value` 是[å¯å˜ç±»åž‹](http://en.wikipedia.org/wiki/Variant_type)。在 RapidJSON 的上下文中,一个 `Value` 的实例å¯ä»¥åŒ…å«6ç§ JSON æ•°æ®ç±»åž‹ä¹‹ä¸€ã€‚通过使用 `union` ,这是å¯èƒ½å®žçŽ°çš„。æ¯ä¸€ä¸ª `Value` 包å«ä¸¤ä¸ªæˆå‘˜ï¼š`union Data data_` å’Œ `unsigned flags_`。`flags_` 表明了 JSON 类型,以åŠé™„加的信æ¯ã€‚ + +下表显示了所有类型的数æ®å¸ƒå±€ã€‚32ä½/64ä½åˆ—表明了字段所å ç”¨çš„字节数。 + +| Null | | 32ä½ | 64ä½ | +|-------------------|----------------------------------|:----:|:----:| +| (未使用) | |4 |8 | +| (未使用) | |4 |4 | +| (未使用) | |4 |4 | +| `unsigned flags_` | `kNullType kNullFlag` |4 |4 | + +| Bool | | 32ä½ | 64ä½ | +|-------------------|----------------------------------------------------|:----:|:----:| +| (未使用) | |4 |8 | +| (未使用) | |4 |4 | +| (未使用) | |4 |4 | +| `unsigned flags_` | `kBoolType` (either `kTrueFlag` or `kFalseFlag`) |4 |4 | + +| String | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `Ch* str` | 指å‘字符串的指针(å¯èƒ½æ‹¥æœ‰æ‰€æœ‰æƒï¼‰ |4 |8 | +| `SizeType length` | 字符串长度 |4 |4 | +| (未使用) | |4 |4 | +| `unsigned flags_` | `kStringType kStringFlag ...` |4 |4 | + +| Object | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `Member* members` | 指å‘æˆå‘˜æ•°ç»„的指针(拥有所有æƒï¼‰ |4 |8 | +| `SizeType size` | æˆå‘˜æ•°é‡ |4 |4 | +| `SizeType capacity` | æˆå‘˜å®¹é‡ |4 |4 | +| `unsigned flags_` | `kObjectType kObjectFlag` |4 |4 | + +| Array | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `Value* values` | 指å‘值数组的指针(拥有所有æƒï¼‰ |4 |8 | +| `SizeType size` | å€¼æ•°é‡ |4 |4 | +| `SizeType capacity` | å€¼å®¹é‡ |4 |4 | +| `unsigned flags_` | `kArrayType kArrayFlag` |4 |4 | + +| Number (Int) | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `int i` | 32ä½æœ‰ç¬¦å·æ•´æ•° |4 |4 | +| (零填充) | 0 |4 |4 | +| (未使用) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kIntFlag kInt64Flag ...` |4 |4 | + +| Number (UInt) | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `unsigned u` | 32ä½æ— ç¬¦å·æ•´æ•° |4 |4 | +| (零填充) | 0 |4 |4 | +| (未使用) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kUintFlag kUint64Flag ...` |4 |4 | + +| Number (Int64) | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `int64_t i64` | 64ä½æœ‰ç¬¦å·æ•´æ•° |8 |8 | +| (未使用) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kInt64Flag ...` |4 |4 | + +| Number (Uint64) | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `uint64_t i64` | 64ä½æ— ç¬¦å·æ•´æ•° |8 |8 | +| (未使用) | |4 |8 | +| `unsigned flags_` | `kNumberType kNumberFlag kInt64Flag ...` |4 |4 | + +| Number (Double) | | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `uint64_t i64` | åŒç²¾åº¦æµ®ç‚¹æ•° |8 |8 | +| (未使用) | |4 |8 | +| `unsigned flags_` |`kNumberType kNumberFlag kDoubleFlag`|4 |4 | + +这里有一些需è¦æ³¨æ„的地方: +* 为了å‡å°‘在64ä½æž¶æž„上的内存消耗,`SizeType` 被定义为 `unsigned` 而ä¸æ˜¯ `size_t`。 +* 32ä½æ•´æ•°çš„零填充å¯èƒ½è¢«æ”¾åœ¨å®žé™…类型的å‰é¢æˆ–åŽé¢ï¼Œè¿™ä¾èµ–于字节åºã€‚这使得它å¯ä»¥å°†32ä½æ•´æ•°ä¸ç»è¿‡ä»»ä½•è½¬æ¢å°±å¯ä»¥è§£é‡Šä¸º64ä½æ•´æ•°ã€‚ +* `Int` 永远是 `Int64`,å之ä¸ç„¶ã€‚ + +## 标志 {#Flags} + +32ä½çš„ `flags_` 包å«äº† JSON 类型和其他信æ¯ã€‚如å‰æ–‡ä¸­çš„表所述,æ¯ä¸€ç§ JSON 类型包å«äº†å†—余的 `kXXXType` å’Œ `kXXXFlag`。这个设计是为了优化测试ä½æ ‡å¿—(`IsNumber()`)和获å–æ¯ä¸€ç§ç±»åž‹çš„åºåˆ—å·ï¼ˆ`GetType()`)。 + +字符串有两个å¯é€‰çš„标志。`kCopyFlag` 表明这个字符串拥有字符串拷è´çš„所有æƒã€‚而 `kInlineStrFlag` æ„味ç€ä½¿ç”¨äº†[短字符串优化](#ShortString)。 + +数字更加å¤æ‚一些。对于普通的整数值,它å¯ä»¥åŒ…å« `kIntFlag`ã€`kUintFlag`〠`kInt64Flag` å’Œ/或 `kUint64Flag`,这由整数的范围决定。带有å°æ•°æˆ–者超过64ä½æ‰€èƒ½è¡¨è¾¾çš„范围的整数的数字会被存储为带有 `kDoubleFlag` çš„ `double`。 + +## 短字符串优化 {#ShortString} + +[Kosta](https://github.com/Kosta-Github) æ供了很棒的短字符串优化。这个优化的xxx如下所述。除去 `flags_` ,`Value` 有12或16字节(对于32ä½æˆ–64ä½ï¼‰æ¥å­˜å‚¨å®žé™…çš„æ•°æ®ã€‚这为在其内部直接存储短字符串而ä¸æ˜¯å­˜å‚¨å­—符串的指针创造了å¯èƒ½ã€‚对于1字节的字符类型(例如 `char`),它å¯ä»¥åœ¨ `Value` 类型内部存储至多11或15个字符的字符串。 + +|ShortString (Ch=char)| | 32ä½ | 64ä½ | +|---------------------|-------------------------------------|:----:|:----:| +| `Ch str[MaxChars]` | 字符串缓冲区 |11 |15 | +| `Ch invLength` | MaxChars - Length |1 |1 | +| `unsigned flags_` | `kStringType kStringFlag ...` |4 |4 | + +这里使用了一项特殊的技术。它存储了 (MaxChars - length) 而ä¸ç›´æŽ¥å­˜å‚¨å­—符串的长度。这使得存储11个字符并且带有åŽç¼€ `\0` æˆä¸ºå¯èƒ½ã€‚ + +这个优化å¯ä»¥å‡å°‘字符串拷è´å†…å­˜å ç”¨ã€‚它也改善了缓存一致性,并进一步æ高了è¿è¡Œæ—¶æ€§èƒ½ã€‚ + +# 分é…器(Allocator) {#InternalAllocator} + +`Allocator` 是 RapidJSON 中的概念: +~~~cpp +concept Allocator { + static const bool kNeedFree; //!< 表明这个分é…器是å¦éœ€è¦è°ƒç”¨ Free()。 + + // 申请内存å—。 + // \param size 内存å—的大å°ï¼Œä»¥å­—节记。 + // \returns 指å‘内存å—的指针。 + void* Malloc(size_t size); + + // 调整内存å—的大å°ã€‚ + // \param originalPtr 当å‰å†…å­˜å—的指针。空指针是被å…许的。 + // \param originalSize 当å‰å¤§å°ï¼Œä»¥å­—节记。(设计问题:因为有些分é…器å¯èƒ½ä¸ä¼šè®°å½•å®ƒï¼Œæ˜¾ç¤ºçš„传递它å¯ä»¥èŠ‚约内存。) + // \param newSize 新大å°ï¼Œä»¥å­—节记。 + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // 释放内存å—。 + // \param ptr 指å‘内存å—的指针。空指针是被å…许的。 + static void Free(void *ptr); +}; +~~~ + +需è¦æ³¨æ„的是 `Malloc()` å’Œ `Realloc()` 是æˆå‘˜å‡½æ•°è€Œ `Free()` 是é™æ€æˆå‘˜å‡½æ•°ã€‚ + +## MemoryPoolAllocator {#MemoryPoolAllocator} + +`MemoryPoolAllocator` 是 DOM 的默认内存分é…器。它åªç”³è¯·å†…存而ä¸é‡Šæ”¾å†…存。这对于构建 DOM æ ‘éžå¸¸åˆé€‚。 + +在它的内部,它从基础的内存分é…器申请内存å—(默认为 `CrtAllocator`)并将这些内存å—存储为å•å‘链表。当用户请求申请内存,它会éµå¾ªä¸‹åˆ—步骤æ¥ç”³è¯·å†…存: + +1. 如果å¯ç”¨ï¼Œä½¿ç”¨ç”¨æˆ·æä¾›çš„ç¼“å†²åŒºã€‚ï¼ˆè§ [User Buffer section in DOM](doc/dom.md)) +2. 如果用户æ供的缓冲区已满,使用当å‰å†…å­˜å—。 +3. 如果当å‰å†…å­˜å—已满,申请新的内存å—。 + +# 解æžä¼˜åŒ– {#ParsingOptimization} + +## 使用 SIMD 跳过空格 {#SkipwhitespaceWithSIMD} + +当从æµä¸­è§£æž JSON 时,解æžå™¨éœ€è¦è·³è¿‡4ç§ç©ºæ ¼å­—符: + +1. 空格 (`U+0020`) +2. 制表符 (`U+000B`) +3. æ¢è¡Œ (`U+000A`) +4. 回车 (`U+000D`) + +这是一份简å•çš„实现: +~~~cpp +void SkipWhitespace(InputStream& s) { + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); +} +~~~ + +但是,这需è¦å¯¹æ¯ä¸ªå­—符进行4次比较以åŠä¸€äº›åˆ†æ”¯ã€‚这被å‘现是一个热点。 + +为了加速这一处ç†ï¼ŒRapidJSON 使用 SIMD æ¥åœ¨ä¸€æ¬¡è¿­ä»£ä¸­æ¯”较16个字符和4ä¸ªç©ºæ ¼ã€‚ç›®å‰ RapidJSON æ”¯æŒ SSE2 , SSE4.2 å’Œ ARM Neon 指令。åŒæ—¶å®ƒä¹Ÿåªä¼šå¯¹ UTF-8 内存æµå¯ç”¨ï¼ŒåŒ…括字符串æµæˆ– *原ä½* 解æžã€‚ + +ä½ å¯ä»¥é€šè¿‡åœ¨åŒ…å« `rapidjson.h` 之å‰å®šä¹‰ `RAPIDJSON_SSE2` , `RAPIDJSON_SSE42` 或 `RAPIDJSON_NEON` æ¥å¯ç”¨è¿™ä¸ªä¼˜åŒ–。一些编译器å¯ä»¥æ£€æµ‹è¿™ä¸ªè®¾ç½®ï¼Œå¦‚ `perftest.h`: + +~~~cpp +// __SSE2__ å’Œ __SSE4_2__ å¯è¢« gccã€clang å’Œ Intel 编译器识别: +// 如果支æŒçš„è¯ï¼Œæˆ‘们在 gmake 中使用了 -march=native æ¥å¯ç”¨ -msse2 å’Œ -msse4.2 +// åŒæ ·çš„, __ARM_NEON 被用于识别Neon +#if defined(__SSE4_2__) +# define RAPIDJSON_SSE42 +#elif defined(__SSE2__) +# define RAPIDJSON_SSE2 +#elif defined(__ARM_NEON) +# define RAPIDJSON_NEON +#endif +~~~ + +需è¦æ³¨æ„的是,这是编译期的设置。在ä¸æ”¯æŒè¿™äº›æŒ‡ä»¤çš„机器上è¿è¡Œå¯æ‰§è¡Œæ–‡ä»¶ä¼šä½¿å®ƒå´©æºƒã€‚ + +### 页é¢å¯¹é½é—®é¢˜ + +在 RapidJSON 的早期版本中,被报告了[一个问题](https://code.google.com/archive/p/rapidjson/issues/104):`SkipWhitespace_SIMD()` 会罕è§åœ°å¯¼è‡´å´©æºƒï¼ˆçº¦äº”å万分之一的几率)。在调查之åŽï¼Œæ€€ç–‘是 `_mm_loadu_si128()` 访问了 `'\0'` 之åŽçš„内存,并越过被ä¿æŠ¤çš„页é¢è¾¹ç•Œã€‚ + +在 [Intel® 64 and IA-32 Architectures Optimization Reference Manual +](http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-optimization-manual.html) 中,章节 10.2.1: + +> 为了支æŒéœ€è¦è´¹å¯¹é½çš„128ä½ SIMD 内存访问的算法,调用者的内存缓冲区申请应当考虑添加一些填充空间,这样被调用的函数å¯ä»¥å®‰å…¨åœ°å°†åœ°å€æŒ‡é’ˆç”¨äºŽæœªå¯¹é½çš„128ä½ SIMD 内存æ“作。 +> 在结åˆéžå¯¹é½çš„ SIMD 内存æ“作中,最å°çš„对é½å¤§å°åº”该等于 SIMD 寄存器的大å°ã€‚ + +对于 RapidJSON æ¥è¯´ï¼Œè¿™æ˜¾ç„¶æ˜¯ä¸å¯è¡Œçš„,因为 RapidJSON ä¸åº”当强迫用户进行内存对é½ã€‚ + +为了修å¤è¿™ä¸ªé—®é¢˜ï¼Œå½“å‰çš„代ç ä¼šå…ˆæŒ‰å­—节处ç†ç›´åˆ°ä¸‹ä¸€ä¸ªå¯¹é½çš„地å€ã€‚在这之åŽï¼Œä½¿ç”¨å¯¹é½è¯»å–æ¥è¿›è¡Œ SIMD 处ç†ã€‚è§ [#85](https://github.com/Tencent/rapidjson/issues/85)。 + +## 局部æµæ‹·è´ {#LocalStreamCopy} + +在优化的过程中,我们å‘现一些编译器ä¸èƒ½å°†è®¿é—®æµçš„一些æˆå‘˜æ•°æ®æ”¾å…¥å±€éƒ¨å˜é‡æˆ–者寄存器中。测试结果显示,对于一些æµç±»åž‹ï¼Œåˆ›å»ºæµçš„æ‹·è´å¹¶å°†å…¶ç”¨äºŽå†…层循环中å¯ä»¥æ”¹å–„æ€§èƒ½ã€‚ä¾‹å¦‚ï¼Œå®žé™…ï¼ˆéž SIMD)的 `SkipWhitespace()` 被实现为: + +~~~cpp +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); +} +~~~ + +基于æµçš„特å¾ï¼Œ`StreamLocalCopy` 会创建(或ä¸åˆ›å»ºï¼‰æµå¯¹è±¡çš„æ‹·è´ï¼Œåœ¨å±€éƒ¨ä½¿ç”¨å®ƒå¹¶å°†æµçš„状æ€æ‹·è´å›žåŽŸæ¥çš„æµã€‚ + +## 解æžä¸ºåŒç²¾åº¦æµ®ç‚¹æ•° {#ParsingDouble} + +将字符串解æžä¸º `double` 并ä¸ç®€å•ã€‚标准库函数 `strtod()` å¯ä»¥èƒœä»»è¿™é¡¹å·¥ä½œï¼Œä½†å®ƒæ¯”较缓慢。默认情况下,解æžå™¨ä½¿ç”¨é»˜è®¤çš„精度设置。这最多有 3[ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place) 的误差,并实现在 `internal::StrtodNormalPrecision()` 中。 + +当使用 `kParseFullPrecisionFlag` 时,编译器会改为调用 `internal::StrtodFullPrecision()` ,这个函数会自动调用三个版本的转æ¢ã€‚ +1. [Fast-Path](http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/)。 +2. [double-conversion](https://github.com/floitsch/double-conversion) 中的自定义 DIY-FP 实现。 +3. (Clinger, William D. How to read floating point numbers accurately. Vol. 25. No. 6. ACM, 1990) 中的大整数算法。 + +如果第一个转æ¢æ–¹æ³•å¤±è´¥ï¼Œåˆ™å°è¯•ä½¿ç”¨ç¬¬äºŒç§æ–¹æ³•ï¼Œä»¥æ­¤ç±»æŽ¨ã€‚ + +# 生æˆä¼˜åŒ– {#GenerationOptimization} + +## æ•´æ•°åˆ°å­—ç¬¦ä¸²çš„è½¬æ¢ {#itoa} + +整数到字符串转æ¢çš„朴素算法需è¦å¯¹æ¯ä¸€ä¸ªå进制ä½è¿›è¡Œä¸€æ¬¡é™¤æ³•ã€‚我们实现了若干版本并在 [itoa-benchmark](https://github.com/miloyip/itoa-benchmark) 中对它们进行了评估。 + +虽然 SSE2 版本是最快的,但它和第二快的 `branchlut` å·®è·ä¸å¤§ã€‚而且 `branchlut` 是纯C++实现,所以我们在 RapidJSON 中使用了 `branchlut`。 + +## åŒç²¾åº¦æµ®ç‚¹æ•°åˆ°å­—ç¬¦ä¸²çš„è½¬æ¢ {#dtoa} + +åŽŸæ¥ RapidJSON 使用 `snprintf(..., ..., "%g")` æ¥è¿›è¡ŒåŒç²¾åº¦æµ®ç‚¹æ•°åˆ°å­—符串的转æ¢ã€‚这是ä¸å‡†ç¡®çš„,因为默认的精度是6。éšåŽæˆ‘们å‘现它很缓慢,而且有其它的替代å“。 + +Google çš„ V8 [double-conversion](https://github.com/floitsch/double-conversion +) 实现了更新的ã€å¿«é€Ÿçš„被称为 Grisu3 的算法(Loitsch, Florian. "Printing floating-point numbers quickly and accurately with integers." ACM Sigplan Notices 45.6 (2010): 233-243.)。 + +然而,这个实现ä¸æ˜¯ä»…头文件的,所以我们实现了一个仅头文件的 Grisu2 版本。这个算法ä¿è¯äº†ç»“果永远精确。而且在大多数情况下,它会生æˆæœ€çŸ­çš„(å¯é€‰ï¼‰å­—符串表示。 + +这个仅头文件的转æ¢å‡½æ•°åœ¨ [dtoa-benchmark](https://github.com/miloyip/dtoa-benchmark) 中进行评估。 + +# 解æžå™¨ {#Parser} + +## è¿­ä»£è§£æž {#IterativeParser} + +迭代解æžå™¨æ˜¯ä¸€ä¸ªä»¥éžé€’å½’æ–¹å¼å®žçŽ°çš„递归下é™çš„ LL(1) 解æžå™¨ã€‚ + +### 语法 {#IterativeParserGrammar} + +解æžå™¨ä½¿ç”¨çš„语法是基于严格 JSON 语法的: +~~~~~~~~~~ +S -> array | object +array -> [ values ] +object -> { members } +values -> non-empty-values | ε +non-empty-values -> value addition-values +addition-values -> ε | , non-empty-values +members -> non-empty-members | ε +non-empty-members -> member addition-members +addition-members -> ε | , non-empty-members +member -> STRING : value +value -> STRING | NUMBER | NULL | BOOLEAN | object | array +~~~~~~~~~~ + +注æ„到左因å­è¢«åŠ å…¥äº†éžç»ˆç»“符的 `values` å’Œ `members` æ¥ä¿è¯è¯­æ³•æ˜¯ LL(1) 的。 + +### 解æžè¡¨ {#IterativeParserParsingTable} + +基于这份语法,我们å¯ä»¥æž„造 FIRST å’Œ FOLLOW 集åˆã€‚ + +éžç»ˆç»“符的 FIRST 集åˆå¦‚下所示: + +| NON-TERMINAL | FIRST | +|:-----------------:|:--------------------------------:| +| array | [ | +| object | { | +| values | ε STRING NUMBER NULL BOOLEAN { [ | +| addition-values | ε COMMA | +| members | ε STRING | +| addition-members | ε COMMA | +| member | STRING | +| value | STRING NUMBER NULL BOOLEAN { [ | +| S | [ { | +| non-empty-members | STRING | +| non-empty-values | STRING NUMBER NULL BOOLEAN { [ | + +FOLLOW 集åˆå¦‚下所示: + +| NON-TERMINAL | FOLLOW | +|:-----------------:|:-------:| +| S | $ | +| array | , $ } ] | +| object | , $ } ] | +| values | ] | +| non-empty-values | ] | +| addition-values | ] | +| members | } | +| non-empty-members | } | +| addition-members | } | +| member | , } | +| value | , } ] | + +最终å¯ä»¥ä»Ž FIRST å’Œ FOLLOW 集åˆç”Ÿæˆè§£æžè¡¨ï¼š + +| NON-TERMINAL | [ | { | , | : | ] | } | STRING | NUMBER | NULL | BOOLEAN | +|:-----------------:|:---------------------:|:---------------------:|:-------------------:|:-:|:-:|:-:|:-----------------------:|:---------------------:|:---------------------:|:---------------------:| +| S | array | object | | | | | | | | | +| array | [ values ] | | | | | | | | | | +| object | | { members } | | | | | | | | | +| values | non-empty-values | non-empty-values | | | ε | | non-empty-values | non-empty-values | non-empty-values | non-empty-values | +| non-empty-values | value addition-values | value addition-values | | | | | value addition-values | value addition-values | value addition-values | value addition-values | +| addition-values | | | , non-empty-values | | ε | | | | | | +| members | | | | | | ε | non-empty-members | | | | +| non-empty-members | | | | | | | member addition-members | | | | +| addition-members | | | , non-empty-members | | | ε | | | | | +| member | | | | | | | STRING : value | | | | +| value | array | object | | | | | STRING | NUMBER | NULL | BOOLEAN | + +对于上é¢çš„语法分æžï¼Œè¿™é‡Œæœ‰ä¸€ä¸ªå¾ˆæ£’çš„[工具](http://hackingoff.com/compilers/predict-first-follow-set)。 + +### 实现 {#IterativeParserImplementation} + +基于这份解æžè¡¨ï¼Œä¸€ä¸ªç›´æŽ¥çš„(常规的)将规则åå‘入栈的实现å¯ä»¥æ­£å¸¸å·¥ä½œã€‚ + +在 RapidJSON 中,对直接的实现进行了一些修改: + +首先,在 RapidJSON 中,这份解æžè¡¨è¢«ç¼–ç ä¸ºçŠ¶æ€æœºã€‚ +规则由头部和主体组æˆã€‚ +状æ€è½¬æ¢ç”±è§„则构造。 +除此之外,é¢å¤–的状æ€è¢«æ·»åŠ åˆ°ä¸Ž `array` å’Œ `object` 有关的规则。 +通过这ç§æ–¹å¼ï¼Œç”Ÿæˆæ•°ç»„值或对象æˆå‘˜å¯ä»¥åªç”¨ä¸€æ¬¡çŠ¶æ€è½¬ç§»ä¾¿å¯å®Œæˆï¼Œ +而ä¸éœ€è¦åœ¨ç›´æŽ¥çš„实现中的多次出栈/入栈æ“作。 +这也使得估计栈的大å°æ›´åŠ å®¹æ˜“。 + +状æ€å›¾å¦‚如下所示: + +![状æ€å›¾](diagram/iterative-parser-states-diagram.png) + +第二,迭代解æžå™¨ä¹Ÿåœ¨å†…部栈ä¿å­˜äº†æ•°ç»„的值个数和对象æˆå‘˜çš„æ•°é‡ï¼Œè¿™ä¹Ÿä¸Žä¼ ç»Ÿçš„实现ä¸åŒã€‚ diff --git a/deps/rapidjson/doc/logo/rapidjson.png b/deps/rapidjson/doc/logo/rapidjson.png new file mode 100644 index 0000000000000000000000000000000000000000..b3b2f80ccb9ce8ce63c13cb3e80dc94d8f165ca3 GIT binary patch literal 5259 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 RrWpVL002ovPDHLkV1jI2B + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + RapidJSON + + diff --git a/deps/rapidjson/doc/misc/DoxygenLayout.xml b/deps/rapidjson/doc/misc/DoxygenLayout.xml new file mode 100644 index 0000000..b7c9586 --- /dev/null +++ b/deps/rapidjson/doc/misc/DoxygenLayout.xml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deps/rapidjson/doc/misc/doxygenextra.css b/deps/rapidjson/doc/misc/doxygenextra.css new file mode 100644 index 0000000..bd67375 --- /dev/null +++ b/deps/rapidjson/doc/misc/doxygenextra.css @@ -0,0 +1,274 @@ +body code { + margin: 0; + border: 1px solid #ddd; + background-color: #f8f8f8; + border-radius: 3px; + padding: 0; +} + +a { + color: #4183c4; +} + +a.el { + font-weight: normal; +} + +body, table, div, p, dl { + color: #333333; + font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; + font-size: 15px; + font-style: normal; + font-variant: normal; + font-weight: normal; + line-height: 25.5px; +} + +body { + background-color: #eee; +} + +div.header { + background-image: none; + background-color: white; + margin: 0px; + border: 0px; +} + +div.headertitle { + width: 858px; + margin: 30px; + padding: 0px; +} + +div.toc { + background-color: #f8f8f8; + border-color: #ddd; + margin-right: 10px; + margin-left: 20px; +} +div.toc h3 { + color: #333333; + font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; + font-size: 18px; + font-style: normal; + font-variant: normal; + font-weight: normal; +} +div.toc li { + color: #333333; + font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; + font-size: 12px; + font-style: normal; + font-variant: normal; + font-weight: normal; +} + +.title { + font-size: 2.5em; + line-height: 63.75px; + border-bottom: 1px solid #ddd; + margin-bottom: 15px; + margin-left: 0px; + margin-right: 0px; + margin-top: 0px; +} + +.summary { + float: none !important; + width: auto !important; + padding-top: 10px; + padding-right: 10px !important; +} + +.summary + .headertitle .title { + font-size: 1.5em; + line-height: 2.0em; +} + +body h1 { + font-size: 2em; + line-height: 1.7; + border-bottom: 1px solid #eee; + margin: 1em 0 15px; + padding: 0; + overflow: hidden; +} + +body h2 { + font-size: 1.5em; + line-height: 1.7; + margin: 1em 0 15px; + padding: 0; +} + +pre.fragment { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 13px; + font-style: normal; + font-variant: normal; + font-weight: normal; + line-height: 19px; +} + +table.doxtable th { + background-color: #f8f8f8; + color: #333333; + font-size: 15px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #ddd; +} + +#doc-content { + background-color: #fff; + width: 918px; + height: auto !important; + margin-left: 270px !important; +} + +div.contents { + width: 858px; + margin: 30px; +} + +div.line { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 13px; + font-style: normal; + font-variant: normal; + font-weight: normal; + line-height: 19px; +} + +tt, code, pre { + font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 12px; +} + +div.fragment { + background-color: #f8f8f8; + border: 1px solid #ddd; + font-size: 13px; + line-height: 19px; + overflow: auto; + padding: 6px 10px; + border-radius: 3px; +} + +#topbanner { + position: fixed; + margin: 15px; + z-index: 101; +} + +#projectname +{ + font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; + font-size: 38px; + font-weight: bold; + line-height: 63.75px; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; + font-size: 16px; + line-height: 22.4px; + margin: 0px 0px 13px 0px; + padding: 2px; +} + +/* side bar and search */ + +#side-nav +{ + padding: 10px 0px 20px 20px; + border-top: 60px solid #2980b9; + background-color: #343131; + width: 250px !important; + height: 100% !important; + position: fixed; +} + +#nav-tree +{ + background-color: transparent; + background-image: none; + height: 100% !important; +} + +#nav-tree .label +{ + font-family: Helvetica, arial, freesans, clean, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; + line-height: 25.5px; + font-size: 15px; +} + +#nav-tree +{ + color: #b3b3b3; +} + +#nav-tree .selected { + background-image: none; +} + +#nav-tree a +{ + color: #b3b3b3; +} + +#github +{ + position: fixed; + left: auto; + right: auto; + width: 250px; +} + +#MSearchBox +{ + margin: 20px; + left: 40px; + right: auto; + position: fixed; + width: 180px; +} + +#MSearchField +{ + width: 121px; +} + +#MSearchResultsWindow +{ + left: 45px !important; +} + +#nav-sync +{ + display: none; +} + +.ui-resizable .ui-resizable-handle +{ + width: 0px; +} + +#nav-path +{ + display: none; +} + +/* external link icon */ +div.contents a[href ^= "http"]:after { + content: " " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=); +} + +.githublogo { + content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RERCMUIwOUY4NkNFMTFFM0FBNTJFRTMzNTJEMUJDNDYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RERCMUIwOUU4NkNFMTFFM0FBNTJFRTMzNTJEMUJDNDYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU1MTc4QTJBOTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU1MTc4QTJCOTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+jUqS1wAAApVJREFUeNq0l89rE1EQx3e3gVJoSPzZeNEWPKgHoa0HBak0iHiy/4C3WvDmoZ56qJ7txVsPQu8qlqqHIhRKJZceesmhioQEfxTEtsoSpdJg1u/ABJ7Pmc1m8zLwgWTmzcw3L+/te+tHUeQltONgCkyCi2AEDHLsJ6iBMlgHL8FeoqokoA2j4CloRMmtwTmj7erHBXPgCWhG6a3JNXKdCiDl1cidVbXZkJoXQRi5t5BrxwoY71FzU8S4JuAIqFkJ2+BFSlEh525b/hr3+k/AklDkNsf6wTT4yv46KIMNpsy+iMdMc47HNWxbsgVcUn7FmLAzzoFAWDsBx+wVP6bUpp5ewI+DOeUx0Wd9D8F70BTGNjkWtqnhmT1JQAHcUgZd8Lo3rQb1LAT8eJVUfgGvHQigGp+V2Z0iAUUl8QH47kAA1XioxIo+bRN8OG8F/oBjwv+Z1nJgX5jpdzQDw0LCjsPmrcW7I/iHScCAEDj03FtD8A0EyuChHgg4KTlJQF3wZ7WELppnBX+dBFSVpJsOBWi1qiRgSwnOgoyD5hmuJdkWCVhTgnTvW3AgYIFrSbZGh0UW/Io5Vp+DQoK7o80pztWMemZbgxeNwCNwDbw1fIfgGZjhU6xPaJgBV8BdsMw5cbZoHsenwYFxkZzl83xTSKTiviCAfCsJLysH3POfC8m8NegyGAGfLP/VmGmfSChgXroR0RSWjEFv2J/nG84cuKFMf4sTCZqXuJd4KaXFVjEG3+tw4eXbNK/YC9oXXs3O8NY8y99L4BXY5cvLY/Bb2VZ58EOJVcB18DHJq9lRsKr8inyKGVjlmh29mtHs3AHfuhCwy1vXT/Nu2GKQt+UHsGdctyX6eQyNvc+5sfX9Dl7Pe2J/BRgAl2CpwmrsHR0AAAAASUVORK5CYII=); +} \ No newline at end of file diff --git a/deps/rapidjson/doc/misc/footer.html b/deps/rapidjson/doc/misc/footer.html new file mode 100644 index 0000000..77f1131 --- /dev/null +++ b/deps/rapidjson/doc/misc/footer.html @@ -0,0 +1,11 @@ + + + +

    + + + diff --git a/deps/rapidjson/doc/misc/header.html b/deps/rapidjson/doc/misc/header.html new file mode 100644 index 0000000..a89ba46 --- /dev/null +++ b/deps/rapidjson/doc/misc/header.html @@ -0,0 +1,24 @@ + + + + + + + +$projectname: $title +$title + + + +$treeview +$search +$mathjax + +$extrastylesheet + + +
    +
    +$searchbox + + diff --git a/deps/rapidjson/doc/npm.md b/deps/rapidjson/doc/npm.md new file mode 100644 index 0000000..6f4e85a --- /dev/null +++ b/deps/rapidjson/doc/npm.md @@ -0,0 +1,31 @@ +## NPM + +# package.json {#package} + +~~~~~~~~~~js +{ + ... + "dependencies": { + ... + "rapidjson": "git@github.com:Tencent/rapidjson.git" + }, + ... + "gypfile": true +} +~~~~~~~~~~ + +# binding.gyp {#binding} + +~~~~~~~~~~js +{ + ... + 'targets': [ + { + ... + 'include_dirs': [ + 'SetInt(stars->GetInt() + 1); + +// { "project" : "RapidJSON", "stars" : 11 } + +// Set() and Create() automatically generate parents if not exist. +Pointer("/a/b/0").Create(d); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] } } + +// GetWithDefault() returns reference. And it deep clones the default value. +Value& hello = Pointer("/hello").GetWithDefault(d, "world"); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "world" } + +// Swap() is similar to Set() +Value x("C++"); +Pointer("/hello").Swap(d, x); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "C++" } +// x becomes "world" + +// Erase a member or element, return true if the value exists +bool success = Pointer("/a").Erase(d); +assert(success); + +// { "project" : "RapidJSON", "stars" : 10 } +~~~ + +# Helper Functions {#HelperFunctions} + +Since object-oriented calling convention may be non-intuitive, RapidJSON also provides helper functions, which just wrap the member functions with free-functions. + +The following example does exactly the same as the above one. + +~~~cpp +Document d; + +SetValueByPointer(d, "/project", "RapidJSON"); +SetValueByPointer(d, "/stars", 10); + +if (Value* stars = GetValueByPointer(d, "/stars")) + stars->SetInt(stars->GetInt() + 1); + +CreateValueByPointer(d, "/a/b/0"); + +Value& hello = GetValueByPointerWithDefault(d, "/hello", "world"); + +Value x("C++"); +SwapValueByPointer(d, "/hello", x); + +bool success = EraseValueByPointer(d, "/a"); +assert(success); +~~~ + +The conventions are shown here for comparison: + +1. `Pointer(source).(root, ...)` +2. `ValueByPointer(root, Pointer(source), ...)` +3. `ValueByPointer(root, source, ...)` + +# Resolving Pointer {#ResolvingPointer} + +`Pointer::Get()` or `GetValueByPointer()` function does not modify the DOM. If the tokens cannot match a value in the DOM, it returns `nullptr`. User can use this to check whether a value exists. + +Note that, numerical tokens can represent an array index or member name. The resolving process will match the values according to the types of value. + +~~~javascript +{ + "0" : 123, + "1" : [456] +} +~~~ + +1. `"/0"` → `123` +2. `"/1/0"` → `456` + +The token `"0"` is treated as member name in the first pointer. It is treated as an array index in the second pointer. + +The other functions, including `Create()`, `GetWithDefault()`, `Set()` and `Swap()`, will change the DOM. These functions will always succeed. They will create the parent values if they do not exist. If the parent values do not match the tokens, they will also be forced to change their type. Changing the type also mean fully removal of that DOM subtree. + +Parsing the above JSON into `d`, + +~~~cpp +SetValueByPointer(d, "1/a", 789); // { "0" : 123, "1" : { "a" : 789 } } +~~~ + +## Resolving Minus Sign Token + +Besides, [RFC6901] defines a special token `-` (single minus sign), which represents the pass-the-end element of an array. `Get()` only treats this token as a member name '"-"'. Yet the other functions can resolve this for array, equivalent to calling `Value::PushBack()` to the array. + +~~~cpp +Document d; +d.Parse("{\"foo\":[123]}"); +SetValueByPointer(d, "/foo/-", 456); // { "foo" : [123, 456] } +SetValueByPointer(d, "/-", 789); // { "foo" : [123, 456], "-" : 789 } +~~~ + +## Resolving Document and Value + +When using `p.Get(root)` or `GetValueByPointer(root, p)`, `root` is a (const) `Value&`. That means, it can be a subtree of the DOM. + +The other functions have two groups of signature. One group uses `Document& document` as parameter, another one uses `Value& root`. The first group uses `document.GetAllocator()` for creating values. And the second group needs user to supply an allocator, like the functions in DOM. + +All examples above do not require an allocator parameter, because the first parameter is a `Document&`. But if you want to resolve a pointer to a subtree, you need to supply the allocator as in the following example: + +~~~cpp +class Person { +public: + Person() { + document_ = new Document(); + // CreateValueByPointer() here no need allocator + SetLocation(CreateValueByPointer(*document_, "/residence"), ...); + SetLocation(CreateValueByPointer(*document_, "/office"), ...); + }; + +private: + void SetLocation(Value& location, const char* country, const char* addresses[2]) { + Value::Allocator& a = document_->GetAllocator(); + // SetValueByPointer() here need allocator + SetValueByPointer(location, "/country", country, a); + SetValueByPointer(location, "/address/0", address[0], a); + SetValueByPointer(location, "/address/1", address[1], a); + } + + // ... + + Document* document_; +}; +~~~ + +`Erase()` or `EraseValueByPointer()` does not need allocator. And they return `true` if the value is erased successfully. + +# Error Handling {#ErrorHandling} + +A `Pointer` parses a source string in its constructor. If there is parsing error, `Pointer::IsValid()` returns `false`. And you can use `Pointer::GetParseErrorCode()` and `GetParseErrorOffset()` to retrieve the error information. + +Note that, all resolving functions assumes valid pointer. Resolving with an invalid pointer causes assertion failure. + +# URI Fragment Representation {#URIFragment} + +In addition to the string representation of JSON pointer that we are using till now, [RFC6901] also defines the URI fragment representation of JSON pointer. URI fragment is specified in [RFC3986] "Uniform Resource Identifier (URI): Generic Syntax". + +The main differences are that a the URI fragment always has a `#` (pound sign) in the beginning, and some characters are encoded by percent-encoding in UTF-8 sequence. For example, the following table shows different C/C++ string literals of different representations. + +String Representation | URI Fragment Representation | Pointer Tokens (UTF-8) +----------------------|-----------------------------|------------------------ +`"/foo/0"` | `"#/foo/0"` | `{"foo", 0}` +`"/a~1b"` | `"#/a~1b"` | `{"a/b"}` +`"/m~0n"` | `"#/m~0n"` | `{"m~n"}` +`"/ "` | `"#/%20"` | `{" "}` +`"/\0"` | `"#/%00"` | `{"\0"}` +`"/€"` | `"#/%E2%82%AC"` | `{"€"}` + +RapidJSON fully support URI fragment representation. It automatically detects the pound sign during parsing. + +# Stringify + +You may also stringify a `Pointer` to a string or other output streams. This can be done by: + +~~~ +Pointer p(...); +StringBuffer sb; +p.Stringify(sb); +std::cout << sb.GetString() << std::endl; +~~~ + +It can also stringify to URI fragment representation by `StringifyUriFragment()`. + +# User-Supplied Tokens {#UserSuppliedTokens} + +If a pointer will be resolved multiple times, it should be constructed once, and then apply it to different DOMs or in different times. This reduce time and memory allocation for constructing `Pointer` multiple times. + +We can go one step further, to completely eliminate the parsing process and dynamic memory allocation, we can establish the token array directly: + +~~~cpp +#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } +#define INDEX(i) { #i, sizeof(#i) - 1, i } + +static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; +static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); +// Equivalent to static const Pointer p("/foo/123"); +~~~ + +This may be useful for memory constrained systems. + +[RFC3986]: https://tools.ietf.org/html/rfc3986 +[RFC6901]: https://tools.ietf.org/html/rfc6901 diff --git a/deps/rapidjson/doc/pointer.zh-cn.md b/deps/rapidjson/doc/pointer.zh-cn.md new file mode 100644 index 0000000..239569d --- /dev/null +++ b/deps/rapidjson/doc/pointer.zh-cn.md @@ -0,0 +1,234 @@ +# Pointer + +(本功能于 v1.1.0 å‘布) + +JSON Pointer 是一个标准化([RFC6901])的方å¼åŽ»é€‰å–一个 JSON Document(DOM)中的值。这类似于 XML çš„ XPath。然而,JSON Pointer 简å•å¾—多,而且æ¯ä¸ª JSON Pointer 仅指å‘å•ä¸ªå€¼ã€‚ + +使用 RapidJSON çš„ JSON Pointer 实现能简化一些 DOM çš„æ“作。 + +[TOC] + +# JSON Pointer {#JsonPointer} + +一个 JSON Pointer 由一串(零至多个)token 所组æˆï¼Œæ¯ä¸ª token 都有 `/` å‰ç¼€ã€‚æ¯ä¸ª token å¯ä»¥æ˜¯ä¸€ä¸ªå­—符串或数字。例如,给定一个 JSON: +~~~javascript +{ + "foo" : ["bar", "baz"], + "pi" : 3.1416 +} +~~~ + +以下的 JSON Pointer 解æžä¸ºï¼š + +1. `"/foo"` → `[ "bar", "baz" ]` +2. `"/foo/0"` → `"bar"` +3. `"/foo/1"` → `"baz"` +4. `"/pi"` → `3.1416` + +è¦æ³¨æ„,一个空 JSON Pointer `""` (零个 token)解æžä¸ºæ•´ä¸ª JSON。 + +# 基本使用方法 {#BasicUsage} + +以下的代ç èŒƒä¾‹ä¸è§£è‡ªæ˜Žã€‚ + +~~~cpp +#include "rapidjson/pointer.h" + +// ... +Document d; + +// 使用 Set() 创建 DOM +Pointer("/project").Set(d, "RapidJSON"); +Pointer("/stars").Set(d, 10); + +// { "project" : "RapidJSON", "stars" : 10 } + +// 使用 Get() 访问 DOM。若该值ä¸å­˜åœ¨åˆ™è¿”回 nullptr。 +if (Value* stars = Pointer("/stars").Get(d)) + stars->SetInt(stars->GetInt() + 1); + +// { "project" : "RapidJSON", "stars" : 11 } + +// Set() å’Œ Create() 自动生æˆçˆ¶å€¼ï¼ˆå¦‚果它们ä¸å­˜åœ¨ï¼‰ã€‚ +Pointer("/a/b/0").Create(d); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] } } + +// GetWithDefault() 返回引用。若该值ä¸å­˜åœ¨åˆ™ä¼šæ·±æ‹·è´ç¼ºçœå€¼ã€‚ +Value& hello = Pointer("/hello").GetWithDefault(d, "world"); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "world" } + +// Swap() å’Œ Set() 相似 +Value x("C++"); +Pointer("/hello").Swap(d, x); + +// { "project" : "RapidJSON", "stars" : 11, "a" : { "b" : [ null ] }, "hello" : "C++" } +// x å˜æˆ "world" + +// 删去一个æˆå‘˜æˆ–元素,若值存在返回 true +bool success = Pointer("/a").Erase(d); +assert(success); + +// { "project" : "RapidJSON", "stars" : 10 } +~~~ + +# 辅助函数 {#HelperFunctions} + +由于é¢å‘对象的调用习惯å¯èƒ½ä¸ç¬¦ç›´è§‰ï¼ŒRapidJSON 也æ供了一些辅助函数,它们把æˆå‘˜å‡½æ•°åŒ…装æˆè‡ªç”±å‡½æ•°ã€‚ + +以下的例å­ä¸Žä¸Šé¢ä¾‹å­æ‰€åšçš„事情完全相åŒã€‚ + +~~~cpp +Document d; + +SetValueByPointer(d, "/project", "RapidJSON"); +SetValueByPointer(d, "/stars", 10); + +if (Value* stars = GetValueByPointer(d, "/stars")) + stars->SetInt(stars->GetInt() + 1); + +CreateValueByPointer(d, "/a/b/0"); + +Value& hello = GetValueByPointerWithDefault(d, "/hello", "world"); + +Value x("C++"); +SwapValueByPointer(d, "/hello", x); + +bool success = EraseValueByPointer(d, "/a"); +assert(success); +~~~ + +以下对比 3 ç§è°ƒç”¨æ–¹å¼ï¼š + +1. `Pointer(source).(root, ...)` +2. `ValueByPointer(root, Pointer(source), ...)` +3. `ValueByPointer(root, source, ...)` + +# è§£æž Pointer {#ResolvingPointer} + +`Pointer::Get()` 或 `GetValueByPointer()` 函数并ä¸ä¿®æ”¹ DOM。若那些 token ä¸èƒ½åŒ¹é… DOM 里的值,这些函数便返回 `nullptr`。使用者å¯åˆ©ç”¨è¿™ä¸ªæ–¹æ³•æ¥æ£€æŸ¥ä¸€ä¸ªå€¼æ˜¯å¦å­˜åœ¨ã€‚ + +注æ„,数值 token å¯è¡¨ç¤ºæ•°ç»„索引或æˆå‘˜å字。解æžè¿‡ç¨‹ä¸­ä¼šæŒ‰å€¼çš„类型æ¥åŒ¹é…。 + +~~~javascript +{ + "0" : 123, + "1" : [456] +} +~~~ + +1. `"/0"` → `123` +2. `"/1/0"` → `456` + +Token `"0"` 在第一个 pointer 中被当作æˆå‘˜å字。它在第二个 pointer 中被当作æˆæ•°ç»„索引。 + +å…¶ä»–å‡½æ•°ä¼šæ”¹å˜ DOM,包括 `Create()`ã€`GetWithDefault()`ã€`Set()`ã€`Swap()`。这些函数总是æˆåŠŸçš„。若一些父值ä¸å­˜åœ¨ï¼Œå°±ä¼šåˆ›å»ºå®ƒä»¬ã€‚若父值类型ä¸åŒ¹é… token,也会强行改å˜å…¶ç±»åž‹ã€‚改å˜ç±»åž‹ä¹Ÿæ„味ç€å®Œå…¨ç§»é™¤å…¶ DOM å­æ ‘的内容。 + +例如,把上é¢çš„ JSON 解译至 `d` 之åŽï¼Œ + +~~~cpp +SetValueByPointer(d, "1/a", 789); // { "0" : 123, "1" : { "a" : 789 } } +~~~ + +## 解æžè´Ÿå· token + +å¦å¤–,[RFC6901] 定义了一个特殊 token `-` (å•ä¸ªè´Ÿå·ï¼‰ï¼Œç”¨äºŽè¡¨ç¤ºæ•°ç»„最åŽå…ƒç´ çš„下一个元素。 `Get()` åªä¼šæŠŠæ­¤ token 当作æˆå‘˜åå­— '"-"'。而其他函数则会以此解æžæ•°ç»„,等åŒäºŽå¯¹æ•°ç»„调用 `Value::PushBack()` 。 + +~~~cpp +Document d; +d.Parse("{\"foo\":[123]}"); +SetValueByPointer(d, "/foo/-", 456); // { "foo" : [123, 456] } +SetValueByPointer(d, "/-", 789); // { "foo" : [123, 456], "-" : 789 } +~~~ + +## è§£æž Document åŠ Value + +当使用 `p.Get(root)` 或 `GetValueByPointer(root, p)`,`root` 是一个(常数) `Value&`。这æ„味ç€ï¼Œå®ƒä¹Ÿå¯ä»¥æ˜¯ DOM 里的一个å­æ ‘。 + +其他函数有两组签å。一组使用 `Document& document` 作为å‚数,å¦ä¸€ç»„使用 `Value& root`。第一组使用 `document.GetAllocator()` 去创建值,而第二组则需è¦ä½¿ç”¨è€…æ供一个 allocatorï¼Œå¦‚åŒ DOM 里的函数。 + +以上例å­éƒ½ä¸éœ€è¦ allocator å‚数,因为它的第一个å‚数是 `Document&`。但如果你需è¦å¯¹ä¸€ä¸ªå­æ ‘进行解æžï¼Œå°±éœ€è¦å¦‚下é¢çš„例å­èˆ¬æä¾› allocator: + +~~~cpp +class Person { +public: + Person() { + document_ = new Document(); + // CreateValueByPointer() here no need allocator + SetLocation(CreateValueByPointer(*document_, "/residence"), ...); + SetLocation(CreateValueByPointer(*document_, "/office"), ...); + }; + +private: + void SetLocation(Value& location, const char* country, const char* addresses[2]) { + Value::Allocator& a = document_->GetAllocator(); + // SetValueByPointer() here need allocator + SetValueByPointer(location, "/country", country, a); + SetValueByPointer(location, "/address/0", address[0], a); + SetValueByPointer(location, "/address/1", address[1], a); + } + + // ... + + Document* document_; +}; +~~~ + +`Erase()` 或 `EraseValueByPointer()` ä¸éœ€è¦ allocator。而且它们æˆåŠŸåˆ é™¤å€¼ä¹‹åŽä¼šè¿”回 `true`。 + +# é”™è¯¯å¤„ç† {#ErrorHandling} + +`Pointer` 在其建构函数里会解译æºå­—符串。若有解æžé”™è¯¯ï¼Œ`Pointer::IsValid()` 返回 `false`。你å¯ä½¿ç”¨ `Pointer::GetParseErrorCode()` å’Œ `GetParseErrorOffset()` 去获å–错信æ¯ã€‚ + +è¦æ³¨æ„的是,所有解æžå‡½æ•°éƒ½å‡è®¾ pointer 是åˆæ³•çš„。对一个éžæ³• pointer 解æžä¼šé€ æˆæ–­è¨€å¤±è´¥ã€‚ + +# URI ç‰‡æ®µè¡¨ç¤ºæ–¹å¼ {#URIFragment} + +除了我们一直在使用的字符串方å¼è¡¨ç¤º JSON pointer,[RFC6901] 也定义了一个 JSON Pointer çš„ URI 片段(fragment)表示方å¼ã€‚URI 片段是定义于 [RFC3986] "Uniform Resource Identifier (URI): Generic Syntax"。 + +URI 片段的主è¦åˆ†åˆ«æ˜¯å¿…然以 `#` (pound sign)开头,而一些字符也会以百分比编ç æˆ UTF-8 åºåˆ—。例如,以下的表展示了ä¸åŒè¡¨ç¤ºæ³•ä¸‹çš„ C/C++ 字符串常数。 + +å­—ç¬¦ä¸²è¡¨ç¤ºæ–¹å¼ | URI ç‰‡æ®µè¡¨ç¤ºæ–¹å¼ | Pointer Tokens (UTF-8) +----------------------|-----------------------------|------------------------ +`"/foo/0"` | `"#/foo/0"` | `{"foo", 0}` +`"/a~1b"` | `"#/a~1b"` | `{"a/b"}` +`"/m~0n"` | `"#/m~0n"` | `{"m~n"}` +`"/ "` | `"#/%20"` | `{" "}` +`"/\0"` | `"#/%00"` | `{"\0"}` +`"/€"` | `"#/%E2%82%AC"` | `{"€"}` + +RapidJSON å®Œå…¨æ”¯æŒ URI 片段表示方å¼ã€‚它在解译时会自动检测 `#` å·ã€‚ + +# 字符串化 + +你也å¯ä»¥æŠŠä¸€ä¸ª `Pointer` 字符串化,储存于字符串或其他输出æµã€‚例如: + +~~~ +Pointer p(...); +StringBuffer sb; +p.Stringify(sb); +std::cout << sb.GetString() << std::endl; +~~~ + +使用 `StringifyUriFragment()` å¯ä»¥æŠŠ pointer 字符串化为 URI 片段表示法。 + +# 使用者æ供的 tokens {#UserSuppliedTokens} + +若一个 pointer 会用于多次解æžï¼Œå®ƒåº”该åªè¢«åˆ›å»ºä¸€æ¬¡ï¼Œç„¶åŽå†æ–½äºŽä¸åŒçš„ DOM ,或在ä¸åŒæ—¶é—´åšè§£æžã€‚这样å¯ä»¥é¿å…多次创键 `Pointer`,节çœæ—¶é—´å’Œå†…存分é…。 + +我们甚至å¯ä»¥å†æ›´è¿›ä¸€æ­¥ï¼Œå®Œå…¨æ¶ˆåŽ»è§£æžè¿‡ç¨‹åŠåŠ¨æ€å†…存分é…。我们å¯ä»¥ç›´æŽ¥ç”Ÿæˆ token 数组: + +~~~cpp +#define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } +#define INDEX(i) { #i, sizeof(#i) - 1, i } + +static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; +static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); +// Equivalent to static const Pointer p("/foo/123"); +~~~ + +è¿™ç§åšæ³•å¯èƒ½é€‚åˆå†…å­˜å—é™çš„系统。 + +[RFC3986]: https://tools.ietf.org/html/rfc3986 +[RFC6901]: https://tools.ietf.org/html/rfc6901 diff --git a/deps/rapidjson/doc/sax.md b/deps/rapidjson/doc/sax.md new file mode 100644 index 0000000..d42d043 --- /dev/null +++ b/deps/rapidjson/doc/sax.md @@ -0,0 +1,509 @@ +# SAX + +The term "SAX" originated from [Simple API for XML](http://en.wikipedia.org/wiki/Simple_API_for_XML). We borrowed this term for JSON parsing and generation. + +In RapidJSON, `Reader` (typedef of `GenericReader<...>`) is the SAX-style parser for JSON, and `Writer` (typedef of `GenericWriter<...>`) is the SAX-style generator for JSON. + +[TOC] + +# Reader {#Reader} + +`Reader` parses a JSON from a stream. While it reads characters from the stream, it analyzes the characters according to the syntax of JSON, and publishes events to a handler. + +For example, here is a JSON. + +~~~~~~~~~~js +{ + "hello": "world", + "t": true , + "f": false, + "n": null, + "i": 123, + "pi": 3.1416, + "a": [1, 2, 3, 4] +} +~~~~~~~~~~ + +When a `Reader` parses this JSON, it publishes the following events to the handler sequentially: + +~~~~~~~~~~ +StartObject() +Key("hello", 5, true) +String("world", 5, true) +Key("t", 1, true) +Bool(true) +Key("f", 1, true) +Bool(false) +Key("n", 1, true) +Null() +Key("i") +Uint(123) +Key("pi") +Double(3.1416) +Key("a") +StartArray() +Uint(1) +Uint(2) +Uint(3) +Uint(4) +EndArray(4) +EndObject(7) +~~~~~~~~~~ + +These events can be easily matched with the JSON, but some event parameters need further explanation. Let's see the `simplereader` example which produces exactly the same output as above: + +~~~~~~~~~~cpp +#include "rapidjson/reader.h" +#include + +using namespace rapidjson; +using namespace std; + +struct MyHandler : public BaseReaderHandler, MyHandler> { + bool Null() { cout << "Null()" << endl; return true; } + bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; } + bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; } + bool Uint(unsigned u) { cout << "Uint(" << u << ")" << endl; return true; } + bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; } + bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; } + bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; } + bool String(const char* str, SizeType length, bool copy) { + cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } + bool StartObject() { cout << "StartObject()" << endl; return true; } + bool Key(const char* str, SizeType length, bool copy) { + cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } + bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; } + bool StartArray() { cout << "StartArray()" << endl; return true; } + bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; } +}; + +void main() { + const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + + MyHandler handler; + Reader reader; + StringStream ss(json); + reader.Parse(ss, handler); +} +~~~~~~~~~~ + +Note that RapidJSON uses templates to statically bind the `Reader` type and the handler type, instead of using classes with virtual functions. This paradigm can improve performance by inlining functions. + +## Handler {#Handler} + +As shown in the previous example, the user needs to implement a handler which consumes the events (via function calls) from the `Reader`. The handler must contain the following member functions. + +~~~~~~~~~~cpp +class Handler { + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +~~~~~~~~~~ + +`Null()` is called when the `Reader` encounters a JSON null value. + +`Bool(bool)` is called when the `Reader` encounters a JSON true or false value. + +When the `Reader` encounters a JSON number, it chooses a suitable C++ type mapping. And then it calls *one* function out of `Int(int)`, `Uint(unsigned)`, `Int64(int64_t)`, `Uint64(uint64_t)` and `Double(double)`. If `kParseNumbersAsStrings` is enabled, `Reader` will always calls `RawNumber()` instead. + +`String(const char* str, SizeType length, bool copy)` is called when the `Reader` encounters a string. The first parameter is pointer to the string. The second parameter is the length of the string (excluding the null terminator). Note that RapidJSON supports null character `\0` inside a string. If such situation happens, `strlen(str) < length`. The last `copy` indicates whether the handler needs to make a copy of the string. For normal parsing, `copy = true`. Only when *insitu* parsing is used, `copy = false`. And be aware that the character type depends on the target encoding, which will be explained later. + +When the `Reader` encounters the beginning of an object, it calls `StartObject()`. An object in JSON is a set of name-value pairs. If the object contains members it first calls `Key()` for the name of member, and then calls functions depending on the type of the value. These calls of name-value pairs repeat until calling `EndObject(SizeType memberCount)`. Note that the `memberCount` parameter is just an aid for the handler; users who do not need this parameter may ignore it. + +Arrays are similar to objects, but simpler. At the beginning of an array, the `Reader` calls `BeginArray()`. If there is elements, it calls functions according to the types of element. Similarly, in the last call `EndArray(SizeType elementCount)`, the parameter `elementCount` is just an aid for the handler. + +Every handler function returns a `bool`. Normally it should return `true`. If the handler encounters an error, it can return `false` to notify the event publisher to stop further processing. + +For example, when we parse a JSON with `Reader` and the handler detects that the JSON does not conform to the required schema, the handler can return `false` and let the `Reader` stop further parsing. This will place the `Reader` in an error state, with error code `kParseErrorTermination`. + +## GenericReader {#GenericReader} + +As mentioned before, `Reader` is a typedef of a template class `GenericReader`: + +~~~~~~~~~~cpp +namespace rapidjson { + +template > +class GenericReader { + // ... +}; + +typedef GenericReader, UTF8<> > Reader; + +} // namespace rapidjson +~~~~~~~~~~ + +The `Reader` uses UTF-8 as both source and target encoding. The source encoding means the encoding in the JSON stream. The target encoding means the encoding of the `str` parameter in `String()` calls. For example, to parse a UTF-8 stream and output UTF-16 string events, you can define a reader by: + +~~~~~~~~~~cpp +GenericReader, UTF16<> > reader; +~~~~~~~~~~ + +Note that, the default character type of `UTF16` is `wchar_t`. So this `reader` needs to call `String(const wchar_t*, SizeType, bool)` of the handler. + +The third template parameter `Allocator` is the allocator type for internal data structure (actually a stack). + +## Parsing {#SaxParsing} + +The main function of `Reader` is used to parse JSON. + +~~~~~~~~~~cpp +template +bool Parse(InputStream& is, Handler& handler); + +// with parseFlags = kDefaultParseFlags +template +bool Parse(InputStream& is, Handler& handler); +~~~~~~~~~~ + +If an error occurs during parsing, it will return `false`. User can also call `bool HasParseError()`, `ParseErrorCode GetParseErrorCode()` and `size_t GetErrorOffset()` to obtain the error states. In fact, `Document` uses these `Reader` functions to obtain parse errors. Please refer to [DOM](doc/dom.md) for details about parse errors. + +## Token-by-Token Parsing {#TokenByTokenParsing} + +Some users may wish to parse a JSON input stream a single token at a time, instead of immediately parsing an entire document without stopping. To parse JSON this way, instead of calling `Parse`, you can use the `IterativeParse` set of functions: + +~~~~~~~~~~cpp + void IterativeParseInit(); + + template + bool IterativeParseNext(InputStream& is, Handler& handler); + + bool IterativeParseComplete(); +~~~~~~~~~~ + +Here is an example of iteratively parsing JSON, token by token: + +~~~~~~~~~~cpp + reader.IterativeParseInit(); + while (!reader.IterativeParseComplete()) { + reader.IterativeParseNext(is, handler); + // Your handler has been called once. + } +~~~~~~~~~~ + +# Writer {#Writer} + +`Reader` converts (parses) JSON into events. `Writer` does exactly the opposite. It converts events into JSON. + +`Writer` is very easy to use. If your application only need to converts some data into JSON, it may be a good choice to use `Writer` directly, instead of building a `Document` and then stringifying it with a `Writer`. + +In `simplewriter` example, we do exactly the reverse of `simplereader`. + +~~~~~~~~~~cpp +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; +using namespace std; + +void main() { + StringBuffer s; + Writer writer(s); + + writer.StartObject(); + writer.Key("hello"); + writer.String("world"); + writer.Key("t"); + writer.Bool(true); + writer.Key("f"); + writer.Bool(false); + writer.Key("n"); + writer.Null(); + writer.Key("i"); + writer.Uint(123); + writer.Key("pi"); + writer.Double(3.1416); + writer.Key("a"); + writer.StartArray(); + for (unsigned i = 0; i < 4; i++) + writer.Uint(i); + writer.EndArray(); + writer.EndObject(); + + cout << s.GetString() << endl; +} +~~~~~~~~~~ + +~~~~~~~~~~ +{"hello":"world","t":true,"f":false,"n":null,"i":123,"pi":3.1416,"a":[0,1,2,3]} +~~~~~~~~~~ + +There are two `String()` and `Key()` overloads. One is the same as defined in handler concept with 3 parameters. It can handle string with null characters. Another one is the simpler version used in the above example. + +Note that, the example code does not pass any parameters in `EndArray()` and `EndObject()`. An `SizeType` can be passed but it will be simply ignored by `Writer`. + +You may doubt that, why not just using `sprintf()` or `std::stringstream` to build a JSON? + +There are various reasons: +1. `Writer` must output a well-formed JSON. If there is incorrect event sequence (e.g. `Int()` just after `StartObject()`), it generates assertion fail in debug mode. +2. `Writer::String()` can handle string escaping (e.g. converting code point `U+000A` to `\n`) and Unicode transcoding. +3. `Writer` handles number output consistently. +4. `Writer` implements the event handler concept. It can be used to handle events from `Reader`, `Document` or other event publisher. +5. `Writer` can be optimized for different platforms. + +Anyway, using `Writer` API is even simpler than generating a JSON by ad hoc methods. + +## Template {#WriterTemplate} + +`Writer` has a minor design difference to `Reader`. `Writer` is a template class, not a typedef. There is no `GenericWriter`. The following is the declaration. + +~~~~~~~~~~cpp +namespace rapidjson { + +template, typename TargetEncoding = UTF8<>, typename Allocator = CrtAllocator<>, unsigned writeFlags = kWriteDefaultFlags> +class Writer { +public: + Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) +// ... +}; + +} // namespace rapidjson +~~~~~~~~~~ + +The `OutputStream` template parameter is the type of output stream. It cannot be deduced and must be specified by user. + +The `SourceEncoding` template parameter specifies the encoding to be used in `String(const Ch*, ...)`. + +The `TargetEncoding` template parameter specifies the encoding in the output stream. + +The `Allocator` is the type of allocator, which is used for allocating internal data structure (a stack). + +The `writeFlags` are combination of the following bit-flags: + +Parse flags | Meaning +------------------------------|----------------------------------- +`kWriteNoFlags` | No flag is set. +`kWriteDefaultFlags` | Default write flags. It is equal to macro `RAPIDJSON_WRITE_DEFAULT_FLAGS`, which is defined as `kWriteNoFlags`. +`kWriteValidateEncodingFlag` | Validate encoding of JSON strings. +`kWriteNanAndInfFlag` | Allow writing of `Infinity`, `-Infinity` and `NaN`. + +Besides, the constructor of `Writer` has a `levelDepth` parameter. This parameter affects the initial memory allocated for storing information per hierarchy level. + +## PrettyWriter {#PrettyWriter} + +While the output of `Writer` is the most condensed JSON without white-spaces, suitable for network transfer or storage, it is not easily readable by human. + +Therefore, RapidJSON provides a `PrettyWriter`, which adds indentation and line feeds in the output. + +The usage of `PrettyWriter` is exactly the same as `Writer`, expect that `PrettyWriter` provides a `SetIndent(Ch indentChar, unsigned indentCharCount)` function. The default is 4 spaces. + +## Completeness and Reset {#CompletenessReset} + +A `Writer` can only output a single JSON, which can be any JSON type at the root. Once the singular event for root (e.g. `String()`), or the last matching `EndObject()` or `EndArray()` event, is handled, the output JSON is well-formed and complete. User can detect this state by calling `Writer::IsComplete()`. + +When a JSON is complete, the `Writer` cannot accept any new events. Otherwise the output will be invalid (i.e. having more than one root). To reuse the `Writer` object, user can call `Writer::Reset(OutputStream& os)` to reset all internal states of the `Writer` with a new output stream. + +# Techniques {#SaxTechniques} + +## Parsing JSON to Custom Data Structure {#CustomDataStructure} + +`Document`'s parsing capability is completely based on `Reader`. Actually `Document` is a handler which receives events from a reader to build a DOM during parsing. + +User may uses `Reader` to build other data structures directly. This eliminates building of DOM, thus reducing memory and improving performance. + +In the following `messagereader` example, `ParseMessages()` parses a JSON which should be an object with key-string pairs. + +~~~~~~~~~~cpp +#include "rapidjson/reader.h" +#include "rapidjson/error/en.h" +#include +#include +#include + +using namespace std; +using namespace rapidjson; + +typedef map MessageMap; + +struct MessageHandler + : public BaseReaderHandler, MessageHandler> { + MessageHandler() : state_(kExpectObjectStart) { + } + + bool StartObject() { + switch (state_) { + case kExpectObjectStart: + state_ = kExpectNameOrObjectEnd; + return true; + default: + return false; + } + } + + bool String(const char* str, SizeType length, bool) { + switch (state_) { + case kExpectNameOrObjectEnd: + name_ = string(str, length); + state_ = kExpectValue; + return true; + case kExpectValue: + messages_.insert(MessageMap::value_type(name_, string(str, length))); + state_ = kExpectNameOrObjectEnd; + return true; + default: + return false; + } + } + + bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; } + + bool Default() { return false; } // All other events are invalid. + + MessageMap messages_; + enum State { + kExpectObjectStart, + kExpectNameOrObjectEnd, + kExpectValue, + }state_; + std::string name_; +}; + +void ParseMessages(const char* json, MessageMap& messages) { + Reader reader; + MessageHandler handler; + StringStream ss(json); + if (reader.Parse(ss, handler)) + messages.swap(handler.messages_); // Only change it if success. + else { + ParseErrorCode e = reader.GetParseErrorCode(); + size_t o = reader.GetErrorOffset(); + cout << "Error: " << GetParseError_En(e) << endl;; + cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl; + } +} + +int main() { + MessageMap messages; + + const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }"; + cout << json1 << endl; + ParseMessages(json1, messages); + + for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr) + cout << itr->first << ": " << itr->second << endl; + + cout << endl << "Parse a JSON with invalid schema." << endl; + const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }"; + cout << json2 << endl; + ParseMessages(json2, messages); + + return 0; +} +~~~~~~~~~~ + +~~~~~~~~~~ +{ "greeting" : "Hello!", "farewell" : "bye-bye!" } +farewell: bye-bye! +greeting: Hello! + +Parse a JSON with invalid schema. +{ "greeting" : "Hello!", "farewell" : "bye-bye!", "foo" : {} } +Error: Terminate parsing due to Handler error. + at offset 59 near '} }...' +~~~~~~~~~~ + +The first JSON (`json1`) was successfully parsed into `MessageMap`. Since `MessageMap` is a `std::map`, the printing order are sorted by the key. This order is different from the JSON's order. + +In the second JSON (`json2`), `foo`'s value is an empty object. As it is an object, `MessageHandler::StartObject()` will be called. However, at that moment `state_ = kExpectValue`, so that function returns `false` and cause the parsing process be terminated. The error code is `kParseErrorTermination`. + +## Filtering of JSON {#Filtering} + +As mentioned earlier, `Writer` can handle the events published by `Reader`. `condense` example simply set a `Writer` as handler of a `Reader`, so it can remove all white-spaces in JSON. `pretty` example uses the same relationship, but replacing `Writer` by `PrettyWriter`. So `pretty` can be used to reformat a JSON with indentation and line feed. + +Actually, we can add intermediate layer(s) to filter the contents of JSON via these SAX-style API. For example, `capitalize` example capitalize all strings in a JSON. + +~~~~~~~~~~cpp +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" +#include +#include + +using namespace rapidjson; + +template +struct CapitalizeFilter { + CapitalizeFilter(OutputHandler& out) : out_(out), buffer_() { + } + + bool Null() { return out_.Null(); } + bool Bool(bool b) { return out_.Bool(b); } + bool Int(int i) { return out_.Int(i); } + bool Uint(unsigned u) { return out_.Uint(u); } + bool Int64(int64_t i) { return out_.Int64(i); } + bool Uint64(uint64_t u) { return out_.Uint64(u); } + bool Double(double d) { return out_.Double(d); } + bool RawNumber(const char* str, SizeType length, bool copy) { return out_.RawNumber(str, length, copy); } + bool String(const char* str, SizeType length, bool) { + buffer_.clear(); + for (SizeType i = 0; i < length; i++) + buffer_.push_back(std::toupper(str[i])); + return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string + } + bool StartObject() { return out_.StartObject(); } + bool Key(const char* str, SizeType length, bool copy) { return String(str, length, copy); } + bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); } + bool StartArray() { return out_.StartArray(); } + bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); } + + OutputHandler& out_; + std::vector buffer_; +}; + +int main(int, char*[]) { + // Prepare JSON reader and input stream. + Reader reader; + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare JSON writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + Writer writer(os); + + // JSON reader parse from the input stream and let writer generate the output. + CapitalizeFilter > filter(writer); + if (!reader.Parse(is, filter)) { + fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} +~~~~~~~~~~ + +Note that, it is incorrect to simply capitalize the JSON as a string. For example: +~~~~~~~~~~ +["Hello\nWorld"] +~~~~~~~~~~ + +Simply capitalizing the whole JSON would contain incorrect escape character: +~~~~~~~~~~ +["HELLO\NWORLD"] +~~~~~~~~~~ + +The correct result by `capitalize`: +~~~~~~~~~~ +["HELLO\nWORLD"] +~~~~~~~~~~ + +More complicated filters can be developed. However, since SAX-style API can only provide information about a single event at a time, user may need to book-keeping the contextual information (e.g. the path from root value, storage of other related values). Some processing may be easier to be implemented in DOM than SAX. diff --git a/deps/rapidjson/doc/sax.zh-cn.md b/deps/rapidjson/doc/sax.zh-cn.md new file mode 100644 index 0000000..9b11e76 --- /dev/null +++ b/deps/rapidjson/doc/sax.zh-cn.md @@ -0,0 +1,487 @@ +# SAX + +"SAX" 此术语æºäºŽ [Simple API for XML](http://en.wikipedia.org/wiki/Simple_API_for_XML)。我们借了此术语去套用在 JSON 的解æžåŠç”Ÿæˆã€‚ + +在 RapidJSON 中,`Reader`(`GenericReader<...>` çš„ typedef)是 JSON çš„ SAX 风格解æžå™¨ï¼Œè€Œ `Writer`(`GenericWriter<...>` çš„ typedef)则是 JSON çš„ SAX 风格生æˆå™¨ã€‚ + +[TOC] + +# Reader {#Reader} + +`Reader` 从输入æµè§£æžä¸€ä¸ª JSON。当它从æµä¸­è¯»å–字符时,它会基于 JSON 的语法去分æžå­—符,并å‘处ç†å™¨å‘é€äº‹ä»¶ã€‚ + +例如,以下是一个 JSON。 + +~~~~~~~~~~js +{ + "hello": "world", + "t": true , + "f": false, + "n": null, + "i": 123, + "pi": 3.1416, + "a": [1, 2, 3, 4] +} +~~~~~~~~~~ + +当一个 `Reader` 解æžæ­¤ JSON 时,它会顺åºåœ°å‘处ç†å™¨å‘é€ä»¥ä¸‹çš„事件: + +~~~~~~~~~~ +StartObject() +Key("hello", 5, true) +String("world", 5, true) +Key("t", 1, true) +Bool(true) +Key("f", 1, true) +Bool(false) +Key("n", 1, true) +Null() +Key("i") +Uint(123) +Key("pi") +Double(3.1416) +Key("a") +StartArray() +Uint(1) +Uint(2) +Uint(3) +Uint(4) +EndArray(4) +EndObject(7) +~~~~~~~~~~ + +除了一些事件å‚数需è¦å†ä½œè§£é‡Šï¼Œè¿™äº›äº‹ä»¶å¯ä»¥è½»æ¾åœ°ä¸Ž JSON 对上。我们å¯ä»¥çœ‹çœ‹ `simplereader` 例å­æ€Žæ ·äº§ç”Ÿå’Œä»¥ä¸Šå®Œå…¨ç›¸åŒçš„结果: + +~~~~~~~~~~cpp +#include "rapidjson/reader.h" +#include + +using namespace rapidjson; +using namespace std; + +struct MyHandler : public BaseReaderHandler, MyHandler> { + bool Null() { cout << "Null()" << endl; return true; } + bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; } + bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; } + bool Uint(unsigned u) { cout << "Uint(" << u << ")" << endl; return true; } + bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; } + bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; } + bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; } + bool String(const char* str, SizeType length, bool copy) { + cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } + bool StartObject() { cout << "StartObject()" << endl; return true; } + bool Key(const char* str, SizeType length, bool copy) { + cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } + bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; } + bool StartArray() { cout << "StartArray()" << endl; return true; } + bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; } +}; + +void main() { + const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + + MyHandler handler; + Reader reader; + StringStream ss(json); + reader.Parse(ss, handler); +} +~~~~~~~~~~ + +æ³¨æ„ RapidJSON 使用模æ¿åŽ»é™æ€æŒ·å®š `Reader` 类型åŠå¤„ç†å™¨çš„类型,而ä¸æ˜¯ä½¿ç”¨å«è™šå‡½æ•°çš„类。这个范å¼å¯ä»¥é€šè¿‡æŠŠå‡½æ•°å†…è”而改善性能。 + +## 处ç†å™¨ {#Handler} + +如å‰ä¾‹æ‰€ç¤ºï¼Œä½¿ç”¨è€…需è¦å®žçŽ°ä¸€ä¸ªå¤„ç†å™¨ï¼ˆhandler),用于处ç†æ¥è‡ª `Reader` 的事件(函数调用)。处ç†å™¨å¿…须包å«ä»¥ä¸‹çš„æˆå‘˜å‡½æ•°ã€‚ + +~~~~~~~~~~cpp +class Handler { + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +~~~~~~~~~~ + +当 `Reader` é‡åˆ° JSON null 值时会调用 `Null()`。 + +当 `Reader` é‡åˆ° JSON true 或 false 值时会调用 `Bool(bool)`。 + +当 `Reader` é‡åˆ° JSON number,它会选择一个åˆé€‚çš„ C++ 类型映射,然åŽè°ƒç”¨ `Int(int)`ã€`Uint(unsigned)`ã€`Int64(int64_t)`ã€`Uint64(uint64_t)` åŠ `Double(double)` çš„ * 其中之一个 *。 若开å¯äº† `kParseNumbersAsStrings` 选项,`Reader` 便会改为调用 `RawNumber()`。 + +当 `Reader` é‡åˆ° JSON string,它会调用 `String(const char* str, SizeType length, bool copy)`。第一个å‚数是字符串的指针。第二个å‚数是字符串的长度(ä¸åŒ…å«ç©ºç»ˆæ­¢ç¬¦å·ï¼‰ã€‚æ³¨æ„ RapidJSON 支æŒå­—串中å«æœ‰ç©ºå­—符 `\0`。若出现这ç§æƒ…况,便会有 `strlen(str) < length`。最åŽçš„ `copy` å‚数表示处ç†å™¨æ˜¯å¦éœ€è¦å¤åˆ¶è¯¥å­—符串。在正常解æžæ—¶ï¼Œ`copy = true`。仅当使用原ä½è§£æžæ—¶ï¼Œ`copy = false`。此外,还è¦æ³¨æ„字符的类型与目标编ç ç›¸å…³ï¼Œæˆ‘们ç¨åŽä¼šå†è°ˆè¿™ä¸€ç‚¹ã€‚ + +当 `Reader` é‡åˆ° JSON object 的开始之时,它会调用 `StartObject()`。JSON çš„ object 是一个键值对(æˆå‘˜ï¼‰çš„集åˆã€‚è‹¥ object 包å«æˆå‘˜ï¼Œå®ƒä¼šå…ˆä¸ºæˆå‘˜çš„å字调用 `Key()`,然åŽå†æŒ‰å€¼çš„类型调用函数。它ä¸æ–­è°ƒç”¨è¿™äº›é”®å€¼å¯¹ï¼Œç›´è‡³æœ€ç»ˆè°ƒç”¨ `EndObject(SizeType memberCount)`ã€‚æ³¨æ„ `memberCount` å‚数对处ç†å™¨æ¥è¯´åªæ˜¯å助性质,使用者å¯èƒ½ä¸éœ€è¦æ­¤å‚数。 + +JSON array 与 object 相似,但更简å•ã€‚在 array 开始时,`Reader` 会调用 `BeginArary()`。若 array å«æœ‰å…ƒç´ ï¼Œå®ƒä¼šæŒ‰å…ƒç´ çš„类型æ¥è¯»ç”¨å‡½æ•°ã€‚相似地,最åŽå®ƒä¼šè°ƒç”¨ `EndArray(SizeType elementCount)`,其中 `elementCount` å‚数对处ç†å™¨æ¥è¯´åªæ˜¯å助性质。 + +æ¯ä¸ªå¤„ç†å™¨å‡½æ•°éƒ½è¿”回一个 `bool`。正常它们应返回 `true`。若处ç†å™¨é‡åˆ°é”™è¯¯ï¼Œå®ƒå¯ä»¥è¿”回 `false` 去通知事件å‘é€æ–¹åœæ­¢ç»§ç»­å¤„ç†ã€‚ + +例如,当我们用 `Reader` 解æžä¸€ä¸ª JSON 时,处ç†å™¨æ£€æµ‹åˆ°è¯¥ JSON 并ä¸ç¬¦åˆæ‰€éœ€çš„ schema,那么处ç†å™¨å¯ä»¥è¿”回 `false`,令 `Reader` åœæ­¢ä¹‹åŽçš„解æžå·¥ä½œã€‚而 `Reader` 会进入一个错误状æ€ï¼Œå¹¶ä»¥ `kParseErrorTermination` 错误ç æ ‡è¯†ã€‚ + +## GenericReader {#GenericReader} + +å‰é¢æåŠï¼Œ`Reader` 是 `GenericReader` 模æ¿ç±»çš„ typedef: + +~~~~~~~~~~cpp +namespace rapidjson { + +template > +class GenericReader { + // ... +}; + +typedef GenericReader, UTF8<> > Reader; + +} // namespace rapidjson +~~~~~~~~~~ + +`Reader` 使用 UTF-8 作为æ¥æºåŠç›®æ ‡ç¼–ç ã€‚æ¥æºç¼–ç æ˜¯æŒ‡ JSON æµçš„ç¼–ç ã€‚目标编ç æ˜¯æŒ‡ `String()` çš„ `str` å‚数所用的编ç ã€‚例如,è¦è§£æžä¸€ä¸ª UTF-8 æµå¹¶è¾“出至 UTF-16 string 事件,你需è¦è¿™ä¹ˆå®šä¹‰ä¸€ä¸ª reader: + +~~~~~~~~~~cpp +GenericReader, UTF16<> > reader; +~~~~~~~~~~ + +注æ„到 `UTF16` 的缺çœç±»åž‹æ˜¯ `wchar_t`。因此这个 `reader` 需è¦è°ƒç”¨å¤„ç†å™¨çš„ `String(const wchar_t*, SizeType, bool)`。 + +第三个模æ¿å‚æ•° `Allocator` 是内部数æ®ç»“构(实际上是一个堆栈)的分é…器类型。 + +## è§£æž {#SaxParsing} + +`Reader` çš„å”¯ä¸€åŠŸèƒ½å°±æ˜¯è§£æž JSON。 + +~~~~~~~~~~cpp +template +bool Parse(InputStream& is, Handler& handler); + +// 使用 parseFlags = kDefaultParseFlags +template +bool Parse(InputStream& is, Handler& handler); +~~~~~~~~~~ + +若在解æžä¸­å‡ºçŽ°é”™è¯¯ï¼Œå®ƒä¼šè¿”回 `false`。使用者å¯è°ƒç”¨ `bool HasParseEror()`, `ParseErrorCode GetParseErrorCode()` åŠ `size_t GetErrorOffset()` 获å–错误状æ€ã€‚实际上 `Document` 使用这些 `Reader` 函数去获å–解æžé”™è¯¯ã€‚请å‚考 [DOM](doc/dom.zh-cn.md) 去了解有关解æžé”™è¯¯çš„细节。 + +# Writer {#Writer} + +`Reader` 把 JSON 转æ¢ï¼ˆè§£æžï¼‰æˆä¸ºäº‹ä»¶ã€‚`Writer` åšå®Œå…¨ç›¸å的事情。它把事件转æ¢æˆ JSON。 + +`Writer` 是éžå¸¸å®¹æ˜“使用的。若你的应用程åºåªéœ€æŠŠä¸€äº›æ•°æ®è½¬æ¢æˆ JSON,å¯èƒ½ç›´æŽ¥ä½¿ç”¨ `Writer`,会比建立一个 `Document` 然åŽç”¨ `Writer` 把它转æ¢æˆ JSON 更加方便。 + +在 `simplewriter` 例å­é‡Œï¼Œæˆ‘ä»¬åš `simplereader` 完全相å的事情。 + +~~~~~~~~~~cpp +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; +using namespace std; + +void main() { + StringBuffer s; + Writer writer(s); + + writer.StartObject(); + writer.Key("hello"); + writer.String("world"); + writer.Key("t"); + writer.Bool(true); + writer.Key("f"); + writer.Bool(false); + writer.Key("n"); + writer.Null(); + writer.Key("i"); + writer.Uint(123); + writer.Key("pi"); + writer.Double(3.1416); + writer.Key("a"); + writer.StartArray(); + for (unsigned i = 0; i < 4; i++) + writer.Uint(i); + writer.EndArray(); + writer.EndObject(); + + cout << s.GetString() << endl; +} +~~~~~~~~~~ + +~~~~~~~~~~ +{"hello":"world","t":true,"f":false,"n":null,"i":123,"pi":3.1416,"a":[0,1,2,3]} +~~~~~~~~~~ + +`String()` åŠ `Key()` å„有两个é‡è½½ã€‚一个是如处ç†å™¨ concept 般,有 3 个å‚数。它能处ç†å«ç©ºå­—符的字符串。å¦ä¸€ä¸ªæ˜¯å¦‚上中使用的较简å•ç‰ˆæœ¬ã€‚ + +注æ„到,例å­ä»£ç ä¸­çš„ `EndArray()` åŠ `EndObject()` 并没有å‚数。å¯ä»¥ä¼ é€’一个 `SizeType` çš„å‚数,但它会被 `Writer` 忽略。 + +ä½ å¯èƒ½ä¼šæ€€ç–‘,为什么ä¸ä½¿ç”¨ `sprintf()` 或 `std::stringstream` 去建立一个 JSON? + +这有几个原因: +1. `Writer` 必然会输出一个结构良好(well-formed)的 JSON。若然有错误的事件次åºï¼ˆå¦‚ `Int()` ç´§éš `StartObject()` 出现),它会在调试模å¼ä¸­äº§ç”Ÿæ–­è¨€å¤±è´¥ã€‚ +2. `Writer::String()` å¯å¤„ç†å­—符串转义(如把ç ç‚¹ `U+000A` 转æ¢æˆ `\n`)åŠè¿›è¡Œ Unicode 转ç ã€‚ +3. `Writer` ä¸€è‡´åœ°å¤„ç† number 的输出。 +4. `Writer` 实现了事件处ç†å™¨ concept。å¯ç”¨äºŽå¤„ç†æ¥è‡ª `Reader`ã€`Document` 或其他事件å‘生器。 +5. `Writer` å¯å¯¹ä¸åŒå¹³å°è¿›è¡Œä¼˜åŒ–。 + +无论如何,使用 `Writer` API åŽ»ç”Ÿæˆ JSON 甚至乎比这些临时方法更简å•ã€‚ + +## æ¨¡æ¿ {#WriterTemplate} + +`Writer` 与 `Reader` 有少许设计区别。`Writer` 是一个模æ¿ç±»ï¼Œè€Œä¸æ˜¯ä¸€ä¸ª typedef。 并没有 `GenericWriter`。以下是 `Writer` 的声明。 + +~~~~~~~~~~cpp +namespace rapidjson { + +template, typename TargetEncoding = UTF8<>, typename Allocator = CrtAllocator<> > +class Writer { +public: + Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) +// ... +}; + +} // namespace rapidjson +~~~~~~~~~~ + +`OutputStream` 模æ¿å‚数是输出æµçš„类型。它的类型ä¸å¯ä»¥è¢«è‡ªåŠ¨æŽ¨æ–­ï¼Œå¿…须由使用者æ供。 + +`SourceEncoding` 模æ¿å‚数指定了 `String(const Ch*, ...)` çš„ç¼–ç ã€‚ + +`TargetEncoding` 模æ¿å‚数指定输出æµçš„ç¼–ç ã€‚ + +`Allocator` 是分é…器的类型,用于分é…内部数æ®ç»“构(一个堆栈)。 + +`writeFlags` 是以下ä½æ ‡å¿—的组åˆï¼š + +写入ä½æ ‡å¿— | æ„义 +------------------------------|----------------------------------- +`kWriteNoFlags` | 没有任何标志。 +`kWriteDefaultFlags` | 缺çœçš„解æžé€‰é¡¹ã€‚它等于 `RAPIDJSON_WRITE_DEFAULT_FLAGS` å®ï¼Œæ­¤å®å®šä¹‰ä¸º `kWriteNoFlags`。 +`kWriteValidateEncodingFlag` | 校验 JSON 字符串的编ç ã€‚ +`kWriteNanAndInfFlag` | 容许写入 `Infinity`, `-Infinity` åŠ `NaN`。 + +此外,`Writer` 的构造函数有一 `levelDepth` å‚数。存储æ¯å±‚阶信æ¯çš„åˆå§‹å†…存分é…é‡å—æ­¤å‚æ•°å½±å“。 + +## PrettyWriter {#PrettyWriter} + +`Writer` 所输出的是没有空格字符的最紧凑 JSON,适åˆç½‘络传输或储存,但ä¸é€‚åˆäººç±»é˜…读。 + +因此,RapidJSON æ供了一个 `PrettyWriter`,它在输出中加入缩进åŠæ¢è¡Œã€‚ + +`PrettyWriter` 的用法与 `Writer` 几乎一样,ä¸åŒä¹‹å¤„是 `PrettyWriter` æ供了一个 `SetIndent(Ch indentChar, unsigned indentCharCount)` 函数。缺çœçš„缩进是 4 个空格。 + +## 完整性åŠé‡ç½® {#CompletenessReset} + +一个 `Writer` åªå¯è¾“出å•ä¸ª JSON,其根节点å¯ä»¥æ˜¯ä»»ä½• JSON 类型。当处ç†å®Œå•ä¸ªæ ¹èŠ‚点事件(如 `String()`),或匹é…çš„æœ€åŽ `EndObject()` 或 `EndArray()` 事件,输出的 JSON 是结构完整(well-formed)åŠå®Œæ•´çš„。使用者å¯è°ƒç”¨ `Writer::IsComplete()` 去检测完整性。 + +当 JSON 完整时,`Writer` ä¸èƒ½å†æŽ¥å—新的事件。ä¸ç„¶å…¶è¾“出便会是ä¸åˆæ³•çš„(例如有超过一个根节点)。为了é‡æ–°åˆ©ç”¨ `Writer` 对象,使用者å¯è°ƒç”¨ `Writer::Reset(OutputStream& os)` 去é‡ç½®å…¶æ‰€æœ‰å†…部状æ€åŠè®¾ç½®æ–°çš„输出æµã€‚ + +# 技巧 {#SaxTechniques} + +## è§£æž JSON 至自定义结构 {#CustomDataStructure} + +`Document` 的解æžåŠŸèƒ½å®Œå…¨ä¾é  `Reader`。实际上 `Document` 是一个处ç†å™¨ï¼Œåœ¨è§£æž JSON 时接收事件去建立一个 DOM。 + +使用者å¯ä»¥ç›´æŽ¥ä½¿ç”¨ `Reader` 去建立其他数æ®ç»“构。这消除了建立 DOM 的步骤,从而å‡å°‘了内存开销并改善性能。 + +在以下的 `messagereader` 例å­ä¸­ï¼Œ`ParseMessages()` 解æžä¸€ä¸ª JSON,该 JSON 应该是一个å«é”®å€¼å¯¹çš„ object。 + +~~~~~~~~~~cpp +#include "rapidjson/reader.h" +#include "rapidjson/error/en.h" +#include +#include +#include + +using namespace std; +using namespace rapidjson; + +typedef map MessageMap; + +struct MessageHandler + : public BaseReaderHandler, MessageHandler> { + MessageHandler() : state_(kExpectObjectStart) { + } + + bool StartObject() { + switch (state_) { + case kExpectObjectStart: + state_ = kExpectNameOrObjectEnd; + return true; + default: + return false; + } + } + + bool String(const char* str, SizeType length, bool) { + switch (state_) { + case kExpectNameOrObjectEnd: + name_ = string(str, length); + state_ = kExpectValue; + return true; + case kExpectValue: + messages_.insert(MessageMap::value_type(name_, string(str, length))); + state_ = kExpectNameOrObjectEnd; + return true; + default: + return false; + } + } + + bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; } + + bool Default() { return false; } // All other events are invalid. + + MessageMap messages_; + enum State { + kExpectObjectStart, + kExpectNameOrObjectEnd, + kExpectValue, + }state_; + std::string name_; +}; + +void ParseMessages(const char* json, MessageMap& messages) { + Reader reader; + MessageHandler handler; + StringStream ss(json); + if (reader.Parse(ss, handler)) + messages.swap(handler.messages_); // Only change it if success. + else { + ParseErrorCode e = reader.GetParseErrorCode(); + size_t o = reader.GetErrorOffset(); + cout << "Error: " << GetParseError_En(e) << endl;; + cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl; + } +} + +int main() { + MessageMap messages; + + const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }"; + cout << json1 << endl; + ParseMessages(json1, messages); + + for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr) + cout << itr->first << ": " << itr->second << endl; + + cout << endl << "Parse a JSON with invalid schema." << endl; + const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }"; + cout << json2 << endl; + ParseMessages(json2, messages); + + return 0; +} +~~~~~~~~~~ + +~~~~~~~~~~ +{ "greeting" : "Hello!", "farewell" : "bye-bye!" } +farewell: bye-bye! +greeting: Hello! + +Parse a JSON with invalid schema. +{ "greeting" : "Hello!", "farewell" : "bye-bye!", "foo" : {} } +Error: Terminate parsing due to Handler error. + at offset 59 near '} }...' +~~~~~~~~~~ + +第一个 JSON(`json1`)被æˆåŠŸåœ°è§£æžè‡³ `MessageMap`。由于 `MessageMap` 是一个 `std::map`,打å°æ¬¡åºæŒ‰é”®å€¼æŽ’åºã€‚此次åºä¸Ž JSON 中的次åºä¸åŒã€‚ + +在第二个 JSON(`json2`)中,`foo` 的值是一个空 object。由于它是一个 object,`MessageHandler::StartObject()` 会被调用。然而,在 `state_ = kExpectValue` 的情况下,该函数会返回 `false`,并导致解æžè¿‡ç¨‹ç»ˆæ­¢ã€‚错误代ç æ˜¯ `kParseErrorTermination`。 + +## 过滤 JSON {#Filtering} + +如å‰é¢æåŠè¿‡ï¼Œ`Writer` å¯å¤„ç† `Reader` å‘出的事件。`example/condense/condense.cpp` 例å­ç®€å•åœ°è®¾ç½® `Writer` 作为一个 `Reader` 的处ç†å™¨ï¼Œå› æ­¤å®ƒèƒ½ç§»é™¤ JSON 中的所有空白字符。`example/pretty/pretty.cpp` 例å­ä½¿ç”¨åŒæ ·çš„关系,åªæ˜¯ä»¥ `PrettyWriter` å–代 `Writer`。因此 `pretty` 能够é‡æ–°æ ¼å¼åŒ– JSON,加入缩进åŠæ¢è¡Œã€‚ + +实际上,我们å¯ä»¥ä½¿ç”¨ SAX 风格 API 去加入(多个)中间层去过滤 JSON 的内容。例如 `capitalize` 例å­å¯ä»¥æŠŠæ‰€æœ‰ JSON string 改为大写。 + +~~~~~~~~~~cpp +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" +#include +#include + +using namespace rapidjson; + +template +struct CapitalizeFilter { + CapitalizeFilter(OutputHandler& out) : out_(out), buffer_() { + } + + bool Null() { return out_.Null(); } + bool Bool(bool b) { return out_.Bool(b); } + bool Int(int i) { return out_.Int(i); } + bool Uint(unsigned u) { return out_.Uint(u); } + bool Int64(int64_t i) { return out_.Int64(i); } + bool Uint64(uint64_t u) { return out_.Uint64(u); } + bool Double(double d) { return out_.Double(d); } + bool RawNumber(const char* str, SizeType length, bool copy) { return out_.RawNumber(str, length, copy); } + bool String(const char* str, SizeType length, bool) { + buffer_.clear(); + for (SizeType i = 0; i < length; i++) + buffer_.push_back(std::toupper(str[i])); + return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string + } + bool StartObject() { return out_.StartObject(); } + bool Key(const char* str, SizeType length, bool copy) { return String(str, length, copy); } + bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); } + bool StartArray() { return out_.StartArray(); } + bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); } + + OutputHandler& out_; + std::vector buffer_; +}; + +int main(int, char*[]) { + // Prepare JSON reader and input stream. + Reader reader; + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare JSON writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + Writer writer(os); + + // JSON reader parse from the input stream and let writer generate the output. + CapitalizeFilter > filter(writer); + if (!reader.Parse(is, filter)) { + fprintf(stderr, "\nError(%u): %s\n", (unsigned)reader.GetErrorOffset(), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} +~~~~~~~~~~ + +注æ„到,ä¸å¯ç®€å•åœ°æŠŠ JSON 当作字符串去改为大写。例如: +~~~~~~~~~~ +["Hello\nWorld"] +~~~~~~~~~~ + +简å•åœ°æŠŠæ•´ä¸ª JSON 转为大写的è¯ä¼šäº§ç”Ÿé”™è¯¯çš„转义符: +~~~~~~~~~~ +["HELLO\NWORLD"] +~~~~~~~~~~ + +而 `capitalize` 就会产生正确的结果: +~~~~~~~~~~ +["HELLO\nWORLD"] +~~~~~~~~~~ + +我们还å¯ä»¥å¼€å‘æ›´å¤æ‚的过滤器。然而,由于 SAX 风格 API 在æŸä¸€æ—¶é—´ç‚¹åªèƒ½æä¾›å•ä¸€äº‹ä»¶çš„ä¿¡æ¯ï¼Œä½¿ç”¨è€…需è¦è‡ªè¡Œè®°å½•ä¸€äº›ä¸Šä¸‹æ–‡ä¿¡æ¯ï¼ˆä¾‹å¦‚从根节点起的路径ã€å‚¨å­˜å…¶ä»–相关值)。对于处ç†æŸäº›æƒ…况,用 DOM 会比 SAX 更容易实现。 + diff --git a/deps/rapidjson/doc/schema.md b/deps/rapidjson/doc/schema.md new file mode 100644 index 0000000..4da4474 --- /dev/null +++ b/deps/rapidjson/doc/schema.md @@ -0,0 +1,513 @@ +# Schema + +(This feature was released in v1.1.0) + +JSON Schema is a draft standard for describing the format of JSON data. The schema itself is also JSON data. By validating a JSON structure with JSON Schema, your code can safely access the DOM without manually checking types, or whether a key exists, etc. It can also ensure that the serialized JSON conform to a specified schema. + +RapidJSON implemented a JSON Schema validator for [JSON Schema Draft v4](http://json-schema.org/documentation.html). If you are not familiar with JSON Schema, you may refer to [Understanding JSON Schema](http://spacetelescope.github.io/understanding-json-schema/). + +[TOC] + +# Basic Usage {#Basic} + +First of all, you need to parse a JSON Schema into `Document`, and then compile the `Document` into a `SchemaDocument`. + +Secondly, construct a `SchemaValidator` with the `SchemaDocument`. It is similar to a `Writer` in the sense of handling SAX events. So, you can use `document.Accept(validator)` to validate a document, and then check the validity. + +~~~cpp +#include "rapidjson/schema.h" + +// ... + +Document sd; +if (sd.Parse(schemaJson).HasParseError()) { + // the schema is not a valid JSON. + // ... +} + +SchemaDocument schema(sd); // Compile a Document to SchemaDocument +if (!schema.GetError().ObjectEmpty()) { + // there was a problem compiling the schema + StringBuffer sb; + Writer w(sb); + schema.GetError().Accept(w); + printf("Invalid schema: %s\n", sb.GetString()); +} +// sd is no longer needed here. + +Document d; +if (d.Parse(inputJson).HasParseError()) { + // the input is not a valid JSON. + // ... +} + +SchemaValidator validator(schema); +if (!d.Accept(validator)) { + // Input JSON is invalid according to the schema + // Output diagnostic information + StringBuffer sb; + validator.GetInvalidSchemaPointer().StringifyUriFragment(sb); + printf("Invalid schema: %s\n", sb.GetString()); + printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword()); + sb.Clear(); + validator.GetInvalidDocumentPointer().StringifyUriFragment(sb); + printf("Invalid document: %s\n", sb.GetString()); +} +~~~ + +Some notes: + +* One `SchemaDocument` can be referenced by multiple `SchemaValidator`s. It will not be modified by `SchemaValidator`s. +* A `SchemaValidator` may be reused to validate multiple documents. To run it for other documents, call `validator.Reset()` first. + +# Validation during parsing/serialization {#Fused} + +Unlike most JSON Schema validator implementations, RapidJSON provides a SAX-based schema validator. Therefore, you can parse a JSON from a stream while validating it on the fly. If the validator encounters a JSON value that invalidates the supplied schema, the parsing will be terminated immediately. This design is especially useful for parsing large JSON files. + +## DOM parsing {#DOM} + +For using DOM in parsing, `Document` needs some preparation and finalizing tasks, in addition to receiving SAX events, thus it needs some work to route the reader, validator and the document. `SchemaValidatingReader` is a helper class that doing such work. + +~~~cpp +#include "rapidjson/filereadstream.h" + +// ... +SchemaDocument schema(sd); // Compile a Document to SchemaDocument + +// Use reader to parse the JSON +FILE* fp = fopen("big.json", "r"); +FileReadStream is(fp, buffer, sizeof(buffer)); + +// Parse JSON from reader, validate the SAX events, and store in d. +Document d; +SchemaValidatingReader > reader(is, schema); +d.Populate(reader); + +if (!reader.GetParseResult()) { + // Not a valid JSON + // When reader.GetParseResult().Code() == kParseErrorTermination, + // it may be terminated by: + // (1) the validator found that the JSON is invalid according to schema; or + // (2) the input stream has I/O error. + + // Check the validation result + if (!reader.IsValid()) { + // Input JSON is invalid according to the schema + // Output diagnostic information + StringBuffer sb; + reader.GetInvalidSchemaPointer().StringifyUriFragment(sb); + printf("Invalid schema: %s\n", sb.GetString()); + printf("Invalid keyword: %s\n", reader.GetInvalidSchemaKeyword()); + sb.Clear(); + reader.GetInvalidDocumentPointer().StringifyUriFragment(sb); + printf("Invalid document: %s\n", sb.GetString()); + } +} +~~~ + +## SAX parsing {#SAX} + +For using SAX in parsing, it is much simpler. If it only need to validate the JSON without further processing, it is simply: + +~~~ +SchemaValidator validator(schema); +Reader reader; +if (!reader.Parse(stream, validator)) { + if (!validator.IsValid()) { + // ... + } +} +~~~ + +This is exactly the method used in the [schemavalidator](example/schemavalidator/schemavalidator.cpp) example. The distinct advantage is low memory usage, no matter how big the JSON was (the memory usage depends on the complexity of the schema). + +If you need to handle the SAX events further, then you need to use the template class `GenericSchemaValidator` to set the output handler of the validator: + +~~~ +MyHandler handler; +GenericSchemaValidator validator(schema, handler); +Reader reader; +if (!reader.Parse(ss, validator)) { + if (!validator.IsValid()) { + // ... + } +} +~~~ + +## Serialization {#Serialization} + +It is also possible to do validation during serializing. This can ensure the result JSON is valid according to the JSON schema. + +~~~ +StringBuffer sb; +Writer writer(sb); +GenericSchemaValidator > validator(s, writer); +if (!d.Accept(validator)) { + // Some problem during Accept(), it may be validation or encoding issues. + if (!validator.IsValid()) { + // ... + } +} +~~~ + +Of course, if your application only needs SAX-style serialization, it can simply send SAX events to `SchemaValidator` instead of `Writer`. + +# Remote Schema {#Remote} + +JSON Schema supports [`$ref` keyword](http://spacetelescope.github.io/understanding-json-schema/structuring.html), which is a [JSON pointer](doc/pointer.md) referencing to a local or remote schema. Local pointer is prefixed with `#`, while remote pointer is an relative or absolute URI. For example: + +~~~js +{ "$ref": "definitions.json#/address" } +~~~ + +As `SchemaDocument` does not know how to resolve such URI, it needs a user-provided `IRemoteSchemaDocumentProvider` instance to do so. + +~~~ +class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider { +public: + virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) { + // Resolve the uri and returns a pointer to that schema. + } +}; + +// ... + +MyRemoteSchemaDocumentProvider provider; +SchemaDocument schema(sd, &provider); +~~~ + +# Conformance {#Conformance} + +RapidJSON passed 262 out of 263 tests in [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) (Json Schema draft 4). + +The failed test is "changed scope ref invalid" of "change resolution scope" in `refRemote.json`. It is due to that `id` schema keyword and URI combining function are not implemented. + +Besides, the `format` schema keyword for string values is ignored, since it is not required by the specification. + +## Regular Expression {#Regex} + +The schema keyword `pattern` and `patternProperties` uses regular expression to match the required pattern. + +RapidJSON implemented a simple NFA regular expression engine, which is used by default. It supports the following syntax. + +|Syntax|Description| +|------|-----------| +|`ab` | Concatenation | +|a|b | Alternation | +|`a?` | Zero or one | +|`a*` | Zero or more | +|`a+` | One or more | +|`a{3}` | Exactly 3 times | +|`a{3,}` | At least 3 times | +|`a{3,5}`| 3 to 5 times | +|`(ab)` | Grouping | +|`^a` | At the beginning | +|`a$` | At the end | +|`.` | Any character | +|`[abc]` | Character classes | +|`[a-c]` | Character class range | +|`[a-z0-9_]` | Character class combination | +|`[^abc]` | Negated character classes | +|`[^a-c]` | Negated character class range | +|`[\b]` | Backspace (U+0008) | +|\\|, `\\`, ... | Escape characters | +|`\f` | Form feed (U+000C) | +|`\n` | Line feed (U+000A) | +|`\r` | Carriage return (U+000D) | +|`\t` | Tab (U+0009) | +|`\v` | Vertical tab (U+000B) | + +For C++11 compiler, it is also possible to use the `std::regex` by defining `RAPIDJSON_SCHEMA_USE_INTERNALREGEX=0` and `RAPIDJSON_SCHEMA_USE_STDREGEX=1`. If your schemas do not need `pattern` and `patternProperties`, you can set both macros to zero to disable this feature, which will reduce some code size. + +# Performance {#Performance} + +Most C++ JSON libraries do not yet support JSON Schema. So we tried to evaluate the performance of RapidJSON's JSON Schema validator according to [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark), which tests 11 JavaScript libraries running on Node.js. + +That benchmark runs validations on [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite), in which some test suites and tests are excluded. We made the same benchmarking procedure in [`schematest.cpp`](test/perftest/schematest.cpp). + +On a Mac Book Pro (2.8 GHz Intel Core i7), the following results are collected. + +|Validator|Relative speed|Number of test runs per second| +|---------|:------------:|:----------------------------:| +|RapidJSON|155%|30682| +|[`ajv`](https://github.com/epoberezkin/ajv)|100%|19770 (± 1.31%)| +|[`is-my-json-valid`](https://github.com/mafintosh/is-my-json-valid)|70%|13835 (± 2.84%)| +|[`jsen`](https://github.com/bugventure/jsen)|57.7%|11411 (± 1.27%)| +|[`schemasaurus`](https://github.com/AlexeyGrishin/schemasaurus)|26%|5145 (± 1.62%)| +|[`themis`](https://github.com/playlyfe/themis)|19.9%|3935 (± 2.69%)| +|[`z-schema`](https://github.com/zaggino/z-schema)|7%|1388 (± 0.84%)| +|[`jsck`](https://github.com/pandastrike/jsck#readme)|3.1%|606 (± 2.84%)| +|[`jsonschema`](https://github.com/tdegrunt/jsonschema#readme)|0.9%|185 (± 1.01%)| +|[`skeemas`](https://github.com/Prestaul/skeemas#readme)|0.8%|154 (± 0.79%)| +|tv4|0.5%|93 (± 0.94%)| +|[`jayschema`](https://github.com/natesilva/jayschema)|0.1%|21 (± 1.14%)| + +That is, RapidJSON is about 1.5x faster than the fastest JavaScript library (ajv). And 1400x faster than the slowest one. + +# Schema violation reporting {#Reporting} + +(Unreleased as of 2017-09-20) + +When validating an instance against a JSON Schema, +it is often desirable to report not only whether the instance is valid, +but also the ways in which it violates the schema. + +The `SchemaValidator` class +collects errors encountered during validation +into a JSON `Value`. +This error object can then be accessed as `validator.GetError()`. + +The structure of the error object is subject to change +in future versions of RapidJSON, +as there is no standard schema for violations. +The details below this point are provisional only. + +## General provisions {#ReportingGeneral} + +Validation of an instance value against a schema +produces an error value. +The error value is always an object. +An empty object `{}` indicates the instance is valid. + +* The name of each member + corresponds to the JSON Schema keyword that is violated. +* The value is either an object describing a single violation, + or an array of such objects. + +Each violation object contains two string-valued members +named `instanceRef` and `schemaRef`. +`instanceRef` contains the URI fragment serialization +of a JSON Pointer to the instance subobject +in which the violation was detected. +`schemaRef` contains the URI of the schema +and the fragment serialization of a JSON Pointer +to the subschema that was violated. + +Individual violation objects can contain other keyword-specific members. +These are detailed further. + +For example, validating this instance: + +~~~json +{"numbers": [1, 2, "3", 4, 5]} +~~~ + +against this schema: + +~~~json +{ + "type": "object", + "properties": { + "numbers": {"$ref": "numbers.schema.json"} + } +} +~~~ + +where `numbers.schema.json` refers +(via a suitable `IRemoteSchemaDocumentProvider`) +to this schema: + +~~~json +{ + "type": "array", + "items": {"type": "number"} +} +~~~ + +produces the following error object: + +~~~json +{ + "type": { + "instanceRef": "#/numbers/2", + "schemaRef": "numbers.schema.json#/items", + "expected": ["number"], + "actual": "string" + } +} +~~~ + +## Validation keywords for numbers {#Numbers} + +### multipleOf {#multipleof} + +* `expected`: required number strictly greater than 0. + The value of the `multipleOf` keyword specified in the schema. +* `actual`: required number. + The instance value. + +### maximum {#maximum} + +* `expected`: required number. + The value of the `maximum` keyword specified in the schema. +* `exclusiveMaximum`: optional boolean. + This will be true if the schema specified `"exclusiveMaximum": true`, + and will be omitted otherwise. +* `actual`: required number. + The instance value. + +### minimum {#minimum} + +* `expected`: required number. + The value of the `minimum` keyword specified in the schema. +* `exclusiveMinimum`: optional boolean. + This will be true if the schema specified `"exclusiveMinimum": true`, + and will be omitted otherwise. +* `actual`: required number. + The instance value. + +## Validation keywords for strings {#Strings} + +### maxLength {#maxLength} + +* `expected`: required number greater than or equal to 0. + The value of the `maxLength` keyword specified in the schema. +* `actual`: required string. + The instance value. + +### minLength {#minLength} + +* `expected`: required number greater than or equal to 0. + The value of the `minLength` keyword specified in the schema. +* `actual`: required string. + The instance value. + +### pattern {#pattern} + +* `actual`: required string. + The instance value. + +(The expected pattern is not reported +because the internal representation in `SchemaDocument` +does not store the pattern in original string form.) + +## Validation keywords for arrays {#Arrays} + +### additionalItems {#additionalItems} + +This keyword is reported +when the value of `items` schema keyword is an array, +the value of `additionalItems` is `false`, +and the instance is an array +with more items than specified in the `items` array. + +* `disallowed`: required integer greater than or equal to 0. + The index of the first item that has no corresponding schema. + +### maxItems and minItems {#maxItems-minItems} + +* `expected`: required integer greater than or equal to 0. + The value of `maxItems` (respectively, `minItems`) + specified in the schema. +* `actual`: required integer greater than or equal to 0. + Number of items in the instance array. + +### uniqueItems {#uniqueItems} + +* `duplicates`: required array + whose items are integers greater than or equal to 0. + Indices of items of the instance that are equal. + +(RapidJSON only reports the first two equal items, +for performance reasons.) + +## Validation keywords for objects + +### maxProperties and minProperties {#maxProperties-minProperties} + +* `expected`: required integer greater than or equal to 0. + The value of `maxProperties` (respectively, `minProperties`) + specified in the schema. +* `actual`: required integer greater than or equal to 0. + Number of properties in the instance object. + +### required {#required} + +* `missing`: required array of one or more unique strings. + The names of properties + that are listed in the value of the `required` schema keyword + but not present in the instance object. + +### additionalProperties {#additionalProperties} + +This keyword is reported +when the schema specifies `additionalProperties: false` +and the name of a property of the instance is +neither listed in the `properties` keyword +nor matches any regular expression in the `patternProperties` keyword. + +* `disallowed`: required string. + Name of the offending property of the instance. + +(For performance reasons, +RapidJSON only reports the first such property encountered.) + +### dependencies {#dependencies} + +* `errors`: required object with one or more properties. + Names and values of its properties are described below. + +Recall that JSON Schema Draft 04 supports +*schema dependencies*, +where presence of a named *controlling* property +requires the instance object to be valid against a subschema, +and *property dependencies*, +where presence of a controlling property +requires other *dependent* properties to be also present. + +For a violated schema dependency, +`errors` will contain a property +with the name of the controlling property +and its value will be the error object +produced by validating the instance object +against the dependent schema. + +For a violated property dependency, +`errors` will contain a property +with the name of the controlling property +and its value will be an array of one or more unique strings +listing the missing dependent properties. + +## Validation keywords for any instance type {#AnyTypes} + +### enum {#enum} + +This keyword has no additional properties +beyond `instanceRef` and `schemaRef`. + +* The allowed values are not listed + because `SchemaDocument` does not store them in original form. +* The violating value is not reported + because it might be unwieldy. + +If you need to report these details to your users, +you can access the necessary information +by following `instanceRef` and `schemaRef`. + +### type {#type} + +* `expected`: required array of one or more unique strings, + each of which is one of the seven primitive types + defined by the JSON Schema Draft 04 Core specification. + Lists the types allowed by the `type` schema keyword. +* `actual`: required string, also one of seven primitive types. + The primitive type of the instance. + +### allOf, anyOf, and oneOf {#allOf-anyOf-oneOf} + +* `errors`: required array of at least one object. + There will be as many items as there are subschemas + in the `allOf`, `anyOf` or `oneOf` schema keyword, respectively. + Each item will be the error value + produced by validating the instance + against the corresponding subschema. + +For `allOf`, at least one error value will be non-empty. +For `anyOf`, all error values will be non-empty. +For `oneOf`, either all error values will be non-empty, +or more than one will be empty. + +### not {#not} + +This keyword has no additional properties +apart from `instanceRef` and `schemaRef`. diff --git a/deps/rapidjson/doc/schema.zh-cn.md b/deps/rapidjson/doc/schema.zh-cn.md new file mode 100644 index 0000000..c85177f --- /dev/null +++ b/deps/rapidjson/doc/schema.zh-cn.md @@ -0,0 +1,237 @@ +# Schema + +(本功能于 v1.1.0 å‘布) + +JSON Schema 是æè¿° JSON æ ¼å¼çš„一个标准è‰æ¡ˆã€‚一个 schema 本身也是一个 JSON。使用 JSON Schema 去校验 JSON,å¯ä»¥è®©ä½ çš„代ç å®‰å…¨åœ°è®¿é—® DOM,而无须检查类型或键值是å¦å­˜åœ¨ç­‰ã€‚这也能确ä¿è¾“出的 JSON 是符åˆæŒ‡å®šçš„ schema。 + +RapidJSON 实现了一个 [JSON Schema Draft v4](http://json-schema.org/documentation.html) 的校验器。若你ä¸ç†Ÿæ‚‰ JSON Schema,å¯ä»¥å‚考 [Understanding JSON Schema](http://spacetelescope.github.io/understanding-json-schema/)。 + +[TOC] + +# 基本用法 {#BasicUsage} + +首先,你è¦æŠŠ JSON Schema 解æžæˆ `Document`,å†æŠŠå®ƒç¼–译æˆä¸€ä¸ª `SchemaDocument`。 + +然åŽï¼Œåˆ©ç”¨è¯¥ `SchemaDocument` 创建一个 `SchemaValidator`。它与 `Writer` ç›¸ä¼¼ï¼Œéƒ½æ˜¯èƒ½å¤Ÿå¤„ç† SAX 事件的。因此,你å¯ä»¥ç”¨ `document.Accept(validator)` 去校验一个 JSON,然åŽå†èŽ·å–校验结果。 + +~~~cpp +#include "rapidjson/schema.h" + +// ... + +Document sd; +if (sd.Parse(schemaJson).HasParseError()) { + // æ­¤ schema ä¸æ˜¯åˆæ³•çš„ JSON + // ... +} +SchemaDocument schema(sd); // 把一个 Document 编译至 SchemaDocument +// 之åŽä¸å†éœ€è¦ sd + +Document d; +if (d.Parse(inputJson).HasParseError()) { + // 输入ä¸æ˜¯ä¸€ä¸ªåˆæ³•çš„ JSON + // ... +} + +SchemaValidator validator(schema); +if (!d.Accept(validator)) { + // 输入的 JSON ä¸åˆä¹Ž schema + // 打å°è¯Šæ–­ä¿¡æ¯ + StringBuffer sb; + validator.GetInvalidSchemaPointer().StringifyUriFragment(sb); + printf("Invalid schema: %s\n", sb.GetString()); + printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword()); + sb.Clear(); + validator.GetInvalidDocumentPointer().StringifyUriFragment(sb); + printf("Invalid document: %s\n", sb.GetString()); +} +~~~ + +一些注æ„点: + +* 一个 `SchemaDocment` 能被多个 `SchemaValidator` 引用。它ä¸ä¼šè¢« `SchemaValidator` 修改。 +* å¯ä»¥é‡å¤ä½¿ç”¨ä¸€ä¸ª `SchemaValidator` æ¥æ ¡éªŒå¤šä¸ªæ–‡ä»¶ã€‚在校验其他文件å‰ï¼Œé¡»å…ˆè°ƒç”¨ `validator.Reset()`。 + +# 在解æžï¼ç”Ÿæˆæ—¶è¿›è¡Œæ ¡éªŒ {#ParsingSerialization} + +与大部分 JSON Schema 校验器有所ä¸åŒï¼ŒRapidJSON æ供了一个基于 SAX çš„ schema 校验器实现。因此,你å¯ä»¥åœ¨è¾“å…¥æµè§£æž JSON çš„åŒæ—¶è¿›è¡Œæ ¡éªŒã€‚若校验器é‡åˆ°ä¸€ä¸ªä¸Ž schema ä¸ç¬¦çš„值,就会立å³ç»ˆæ­¢è§£æžã€‚这设计对于解æžå¤§åž‹ JSON 文件时特别有用。 + +## DOM è§£æž {#DomParsing} + +在使用 DOM 进行解æžæ—¶ï¼Œ`Document` 除了接收 SAX 事件外,还需åšä¸€äº›å‡†å¤‡åŠç»“æŸå·¥ä½œï¼Œå› æ­¤ï¼Œä¸ºäº†è¿žæŽ¥ `Reader`ã€`SchemaValidator` å’Œ `Document` è¦åšå¤šä¸€ç‚¹äº‹æƒ…。`SchemaValidatingReader` 是一个辅助类去åšé‚£äº›å·¥ä½œã€‚ + +~~~cpp +#include "rapidjson/filereadstream.h" + +// ... +SchemaDocument schema(sd); // 把一个 Document 编译至 SchemaDocument + +// 使用 reader è§£æž JSON +FILE* fp = fopen("big.json", "r"); +FileReadStream is(fp, buffer, sizeof(buffer)); + +// 用 reader è§£æž JSON,校验它的 SAX 事件,并存储至 d +Document d; +SchemaValidatingReader > reader(is, schema); +d.Populate(reader); + +if (!reader.GetParseResult()) { + // ä¸æ˜¯ä¸€ä¸ªåˆæ³•çš„ JSON + // 当 reader.GetParseResult().Code() == kParseErrorTermination, + // 它å¯èƒ½æ˜¯è¢«ä»¥ä¸‹åŽŸå› ä¸­æ­¢ï¼š + // (1) 校验器å‘现 JSON ä¸åˆä¹Ž schema;或 + // (2) 输入æµæœ‰ I/O 错误。 + + // 检查校验结果 + if (!reader.IsValid()) { + // 输入的 JSON ä¸åˆä¹Ž schema + // 打å°è¯Šæ–­ä¿¡æ¯ + StringBuffer sb; + reader.GetInvalidSchemaPointer().StringifyUriFragment(sb); + printf("Invalid schema: %s\n", sb.GetString()); + printf("Invalid keyword: %s\n", reader.GetInvalidSchemaKeyword()); + sb.Clear(); + reader.GetInvalidDocumentPointer().StringifyUriFragment(sb); + printf("Invalid document: %s\n", sb.GetString()); + } +} +~~~ + +## SAX è§£æž {#SaxParsing} + +使用 SAX 解æžæ—¶ï¼Œæƒ…况就简å•å¾—多。若åªéœ€è¦æ ¡éªŒ JSON 而无需进一步处ç†ï¼Œé‚£ä¹ˆä»…需è¦ï¼š + +~~~ +SchemaValidator validator(schema); +Reader reader; +if (!reader.Parse(stream, validator)) { + if (!validator.IsValid()) { + // ... + } +} +~~~ + +è¿™ç§æ–¹å¼å’Œ [schemavalidator](example/schemavalidator/schemavalidator.cpp) 例å­å®Œå…¨ç›¸åŒã€‚这带æ¥çš„独特优势是,无论 JSON 多巨大,永远维æŒä½Žå†…存用é‡ï¼ˆå†…存用é‡åªä¸Ž Schema çš„å¤æ‚度相关)。 + +若你需è¦è¿›ä¸€æ­¥å¤„ç† SAX 事件,便å¯ä½¿ç”¨æ¨¡æ¿ç±» `GenericSchemaValidator` 去设置校验器的输出 `Handler`: + +~~~ +MyHandler handler; +GenericSchemaValidator validator(schema, handler); +Reader reader; +if (!reader.Parse(ss, validator)) { + if (!validator.IsValid()) { + // ... + } +} +~~~ + +## ç”Ÿæˆ {#Serialization} + +我们也å¯ä»¥åœ¨ç”Ÿæˆï¼ˆserialization)的时候进行校验。这能确ä¿è¾“出的 JSON 符åˆä¸€ä¸ª JSON Schema。 + +~~~ +StringBuffer sb; +Writer writer(sb); +GenericSchemaValidator > validator(s, writer); +if (!d.Accept(validator)) { + // Some problem during Accept(), it may be validation or encoding issues. + if (!validator.IsValid()) { + // ... + } +} +~~~ + +å½“ç„¶ï¼Œå¦‚æžœä½ çš„åº”ç”¨ä»…éœ€è¦ SAX 风格的生æˆï¼Œé‚£ä¹ˆåªéœ€è¦æŠŠ SAX 事件由原æ¥å‘é€åˆ° `Writer`,改为å‘é€åˆ° `SchemaValidator`。 + +# 远程 Schema {#RemoteSchema} + +JSON Schema æ”¯æŒ [`$ref` 关键字](http://spacetelescope.github.io/understanding-json-schema/structuring.html),它是一个 [JSON pointer](doc/pointer.zh-cn.md) 引用至一个本地(local)或远程(remote) schema。本地指针的首字符是 `#`,而远程指针是一个相对或ç»å¯¹ URI。例如: + +~~~js +{ "$ref": "definitions.json#/address" } +~~~ + +由于 `SchemaDocument` 并ä¸çŸ¥é“如何处ç†é‚£äº› URI,它需è¦ä½¿ç”¨è€…æ供一个 `IRemoteSchemaDocumentProvider` 的实例去处ç†ã€‚ + +~~~ +class MyRemoteSchemaDocumentProvider : public IRemoteSchemaDocumentProvider { +public: + virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) { + // Resolve the uri and returns a pointer to that schema. + } +}; + +// ... + +MyRemoteSchemaDocumentProvider provider; +SchemaDocument schema(sd, &provider); +~~~ + +# 标准的符åˆç¨‹åº¦ {#Conformance} + +RapidJSON 通过了 [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) (Json Schema draft 4) 中 263 个测试的 262 个。 + +没通过的测试是 `refRemote.json` 中的 "change resolution scope" - "changed scope ref invalid"。这是由于未实现 `id` schema å…³é”®å­—åŠ URI åˆå¹¶åŠŸèƒ½ã€‚ + +除此以外,关于字符串类型的 `format` schema 关键字也会被忽略,因为标准中并没需求必须实现。 + +## æ­£åˆ™è¡¨è¾¾å¼ {#RegEx} + +`pattern` åŠ `patternProperties` 这两个 schema 关键字使用了正则表达å¼åŽ»åŒ¹é…所需的模å¼ã€‚ + +RapidJSON 实现了一个简å•çš„ NFA 正则表达å¼å¼•æ“Žï¼Œå¹¶é¢„设使用。它支æŒä»¥ä¸‹è¯­æ³•ã€‚ + +|语法|æè¿°| +|------|-----------| +|`ab` | ä¸²è” | +|a|b | 交替 | +|`a?` | 零或一次 | +|`a*` | 零或多次 | +|`a+` | 一或多次 | +|`a{3}` | 刚好 3 次 | +|`a{3,}` | 至少 3 次 | +|`a{3,5}`| 3 至 5 次 | +|`(ab)` | 分组 | +|`^a` | 在开始处 | +|`a$` | 在结æŸå¤„ | +|`.` | 任何字符 | +|`[abc]` | 字符组 | +|`[a-c]` | 字符组范围 | +|`[a-z0-9_]` | å­—ç¬¦ç»„ç»„åˆ | +|`[^abc]` | 字符组å–å | +|`[^a-c]` | 字符组范围å–å | +|`[\b]` | 退格符 (U+0008) | +|\\|, `\\`, ... | 转义字符 | +|`\f` | 馈页 (U+000C) | +|`\n` | 馈行 (U+000A) | +|`\r` | 回车 (U+000D) | +|`\t` | 制表 (U+0009) | +|`\v` | 垂直制表 (U+000B) | + +对于使用 C++11 编译器的使用者,也å¯ä½¿ç”¨ `std::regex`,åªéœ€å®šä¹‰ `RAPIDJSON_SCHEMA_USE_INTERNALREGEX=0` åŠ `RAPIDJSON_SCHEMA_USE_STDREGEX=1`。若你的 schema 无需使用 `pattern` 或 `patternProperties`,å¯ä»¥æŠŠä¸¤ä¸ªå®éƒ½è®¾ä¸ºé›¶ï¼Œä»¥ç¦ç”¨æ­¤åŠŸèƒ½ï¼Œè¿™æ ·åšå¯èŠ‚çœä¸€äº›ä»£ç ä½“积。 + +# 性能 {#Performance} + +大部分 C++ JSON åº“éƒ½æœªæ”¯æŒ JSON Schema。因此我们å°è¯•æŒ‰ç…§ [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark) 去评估 RapidJSON çš„ JSON Schema 校验器。该评测测试了 11 个è¿è¡Œåœ¨ node.js 上的 JavaScript 库。 + +该评测校验 [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite) 中的测试,当中排除了一些测试套件åŠä¸ªåˆ«æµ‹è¯•ã€‚我们在 [`schematest.cpp`](test/perftest/schematest.cpp) 实现了相åŒçš„评测。 + +在 MacBook Pro (2.8 GHz Intel Core i7) 上收集到以下结果。 + +|校验器|相对速度|æ¯ç§’执行的测试数目| +|---------|:------------:|:----------------------------:| +|RapidJSON|155%|30682| +|[`ajv`](https://github.com/epoberezkin/ajv)|100%|19770 (± 1.31%)| +|[`is-my-json-valid`](https://github.com/mafintosh/is-my-json-valid)|70%|13835 (± 2.84%)| +|[`jsen`](https://github.com/bugventure/jsen)|57.7%|11411 (± 1.27%)| +|[`schemasaurus`](https://github.com/AlexeyGrishin/schemasaurus)|26%|5145 (± 1.62%)| +|[`themis`](https://github.com/playlyfe/themis)|19.9%|3935 (± 2.69%)| +|[`z-schema`](https://github.com/zaggino/z-schema)|7%|1388 (± 0.84%)| +|[`jsck`](https://github.com/pandastrike/jsck#readme)|3.1%|606 (± 2.84%)| +|[`jsonschema`](https://github.com/tdegrunt/jsonschema#readme)|0.9%|185 (± 1.01%)| +|[`skeemas`](https://github.com/Prestaul/skeemas#readme)|0.8%|154 (± 0.79%)| +|tv4|0.5%|93 (± 0.94%)| +|[`jayschema`](https://github.com/natesilva/jayschema)|0.1%|21 (± 1.14%)| + +æ¢è¨€ä¹‹ï¼ŒRapidJSON 比最快的 JavaScript 库(ajv)快约 1.5x。比最慢的快 1400x。 diff --git a/deps/rapidjson/doc/stream.md b/deps/rapidjson/doc/stream.md new file mode 100644 index 0000000..5d0b0f3 --- /dev/null +++ b/deps/rapidjson/doc/stream.md @@ -0,0 +1,429 @@ +# Stream + +In RapidJSON, `rapidjson::Stream` is a concept for reading/writing JSON. Here we'll first show you how to use provided streams. And then see how to create a custom stream. + +[TOC] + +# Memory Streams {#MemoryStreams} + +Memory streams store JSON in memory. + +## StringStream (Input) {#StringStream} + +`StringStream` is the most basic input stream. It represents a complete, read-only JSON stored in memory. It is defined in `rapidjson/rapidjson.h`. + +~~~~~~~~~~cpp +#include "rapidjson/document.h" // will include "rapidjson/rapidjson.h" + +using namespace rapidjson; + +// ... +const char json[] = "[1, 2, 3, 4]"; +StringStream s(json); + +Document d; +d.ParseStream(s); +~~~~~~~~~~ + +Since this is very common usage, `Document::Parse(const char*)` is provided to do exactly the same as above: + +~~~~~~~~~~cpp +// ... +const char json[] = "[1, 2, 3, 4]"; +Document d; +d.Parse(json); +~~~~~~~~~~ + +Note that, `StringStream` is a typedef of `GenericStringStream >`, user may use another encodings to represent the character set of the stream. + +## StringBuffer (Output) {#StringBuffer} + +`StringBuffer` is a simple output stream. It allocates a memory buffer for writing the whole JSON. Use `GetString()` to obtain the buffer. + +~~~~~~~~~~cpp +#include "rapidjson/stringbuffer.h" +#include + +StringBuffer buffer; +Writer writer(buffer); +d.Accept(writer); + +const char* output = buffer.GetString(); +~~~~~~~~~~ + +When the buffer is full, it will increases the capacity automatically. The default capacity is 256 characters (256 bytes for UTF8, 512 bytes for UTF16, etc.). User can provide an allocator and an initial capacity. + +~~~~~~~~~~cpp +StringBuffer buffer1(0, 1024); // Use its allocator, initial size = 1024 +StringBuffer buffer2(allocator, 1024); +~~~~~~~~~~ + +By default, `StringBuffer` will instantiate an internal allocator. + +Similarly, `StringBuffer` is a typedef of `GenericStringBuffer >`. + +# File Streams {#FileStreams} + +When parsing a JSON from file, you may read the whole JSON into memory and use ``StringStream`` above. + +However, if the JSON is big, or memory is limited, you can use `FileReadStream`. It only read a part of JSON from file into buffer, and then let the part be parsed. If it runs out of characters in the buffer, it will read the next part from file. + +## FileReadStream (Input) {#FileReadStream} + +`FileReadStream` reads the file via a `FILE` pointer. And user need to provide a buffer. + +~~~~~~~~~~cpp +#include "rapidjson/filereadstream.h" +#include + +using namespace rapidjson; + +FILE* fp = fopen("big.json", "rb"); // non-Windows use "r" + +char readBuffer[65536]; +FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + +Document d; +d.ParseStream(is); + +fclose(fp); +~~~~~~~~~~ + +Different from string streams, `FileReadStream` is byte stream. It does not handle encodings. If the file is not UTF-8, the byte stream can be wrapped in a `EncodedInputStream`. We will discuss more about this later in this tutorial. + +Apart from reading file, user can also use `FileReadStream` to read `stdin`. + +## FileWriteStream (Output) {#FileWriteStream} + +`FileWriteStream` is buffered output stream. Its usage is very similar to `FileReadStream`. + +~~~~~~~~~~cpp +#include "rapidjson/filewritestream.h" +#include +#include + +using namespace rapidjson; + +Document d; +d.Parse(json); +// ... + +FILE* fp = fopen("output.json", "wb"); // non-Windows use "w" + +char writeBuffer[65536]; +FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer)); + +Writer writer(os); +d.Accept(writer); + +fclose(fp); +~~~~~~~~~~ + +It can also redirect the output to `stdout`. + +# iostream Wrapper {#iostreamWrapper} + +Due to users' requests, RapidJSON also provides official wrappers for `std::basic_istream` and `std::basic_ostream`. However, please note that the performance will be much lower than the other streams above. + +## IStreamWrapper {#IStreamWrapper} + +`IStreamWrapper` wraps any class derived from `std::istream`, such as `std::istringstream`, `std::stringstream`, `std::ifstream`, `std::fstream`, into RapidJSON's input stream. + +~~~cpp +#include +#include +#include + +using namespace rapidjson; +using namespace std; + +ifstream ifs("test.json"); +IStreamWrapper isw(ifs); + +Document d; +d.ParseStream(isw); +~~~ + +For classes derived from `std::wistream`, use `WIStreamWrapper`. + +## OStreamWrapper {#OStreamWrapper} + +Similarly, `OStreamWrapper` wraps any class derived from `std::ostream`, such as `std::ostringstream`, `std::stringstream`, `std::ofstream`, `std::fstream`, into RapidJSON's input stream. + +~~~cpp +#include +#include +#include +#include + +using namespace rapidjson; +using namespace std; + +Document d; +d.Parse(json); + +// ... + +ofstream ofs("output.json"); +OStreamWrapper osw(ofs); + +Writer writer(osw); +d.Accept(writer); +~~~ + +For classes derived from `std::wostream`, use `WOStreamWrapper`. + +# Encoded Streams {#EncodedStreams} + +Encoded streams do not contain JSON itself, but they wrap byte streams to provide basic encoding/decoding function. + +As mentioned above, UTF-8 byte streams can be read directly. However, UTF-16 and UTF-32 have endian issue. To handle endian correctly, it needs to convert bytes into characters (e.g. `wchar_t` for UTF-16) while reading, and characters into bytes while writing. + +Besides, it also need to handle [byte order mark (BOM)](http://en.wikipedia.org/wiki/Byte_order_mark). When reading from a byte stream, it is needed to detect or just consume the BOM if exists. When writing to a byte stream, it can optionally write BOM. + +If the encoding of stream is known during compile-time, you may use `EncodedInputStream` and `EncodedOutputStream`. If the stream can be UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE JSON, and it is only known in runtime, you may use `AutoUTFInputStream` and `AutoUTFOutputStream`. These streams are defined in `rapidjson/encodedstream.h`. + +Note that, these encoded streams can be applied to streams other than file. For example, you may have a file in memory, or a custom byte stream, be wrapped in encoded streams. + +## EncodedInputStream {#EncodedInputStream} + +`EncodedInputStream` has two template parameters. The first one is a `Encoding` class, such as `UTF8`, `UTF16LE`, defined in `rapidjson/encodings.h`. The second one is the class of stream to be wrapped. + +~~~~~~~~~~cpp +#include "rapidjson/document.h" +#include "rapidjson/filereadstream.h" // FileReadStream +#include "rapidjson/encodedstream.h" // EncodedInputStream +#include + +using namespace rapidjson; + +FILE* fp = fopen("utf16le.json", "rb"); // non-Windows use "r" + +char readBuffer[256]; +FileReadStream bis(fp, readBuffer, sizeof(readBuffer)); + +EncodedInputStream, FileReadStream> eis(bis); // wraps bis into eis + +Document d; // Document is GenericDocument > +d.ParseStream<0, UTF16LE<> >(eis); // Parses UTF-16LE file into UTF-8 in memory + +fclose(fp); +~~~~~~~~~~ + +## EncodedOutputStream {#EncodedOutputStream} + +`EncodedOutputStream` is similar but it has a `bool putBOM` parameter in the constructor, controlling whether to write BOM into output byte stream. + +~~~~~~~~~~cpp +#include "rapidjson/filewritestream.h" // FileWriteStream +#include "rapidjson/encodedstream.h" // EncodedOutputStream +#include +#include + +Document d; // Document is GenericDocument > +// ... + +FILE* fp = fopen("output_utf32le.json", "wb"); // non-Windows use "w" + +char writeBuffer[256]; +FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer)); + +typedef EncodedOutputStream, FileWriteStream> OutputStream; +OutputStream eos(bos, true); // Write BOM + +Writer, UTF32LE<>> writer(eos); +d.Accept(writer); // This generates UTF32-LE file from UTF-8 in memory + +fclose(fp); +~~~~~~~~~~ + +## AutoUTFInputStream {#AutoUTFInputStream} + +Sometimes an application may want to handle all supported JSON encoding. `AutoUTFInputStream` will detection encoding by BOM first. If BOM is unavailable, it will use characteristics of valid JSON to make detection. If neither method success, it falls back to the UTF type provided in constructor. + +Since the characters (code units) may be 8-bit, 16-bit or 32-bit. `AutoUTFInputStream` requires a character type which can hold at least 32-bit. We may use `unsigned`, as in the template parameter: + +~~~~~~~~~~cpp +#include "rapidjson/document.h" +#include "rapidjson/filereadstream.h" // FileReadStream +#include "rapidjson/encodedstream.h" // AutoUTFInputStream +#include + +using namespace rapidjson; + +FILE* fp = fopen("any.json", "rb"); // non-Windows use "r" + +char readBuffer[256]; +FileReadStream bis(fp, readBuffer, sizeof(readBuffer)); + +AutoUTFInputStream eis(bis); // wraps bis into eis + +Document d; // Document is GenericDocument > +d.ParseStream<0, AutoUTF >(eis); // This parses any UTF file into UTF-8 in memory + +fclose(fp); +~~~~~~~~~~ + +When specifying the encoding of stream, uses `AutoUTF` as in `ParseStream()` above. + +You can obtain the type of UTF via `UTFType GetType()`. And check whether a BOM is found by `HasBOM()` + +## AutoUTFOutputStream {#AutoUTFOutputStream} + +Similarly, to choose encoding for output during runtime, we can use `AutoUTFOutputStream`. This class is not automatic *per se*. You need to specify the UTF type and whether to write BOM in runtime. + +~~~~~~~~~~cpp +using namespace rapidjson; + +void WriteJSONFile(FILE* fp, UTFType type, bool putBOM, const Document& d) { + char writeBuffer[256]; + FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer)); + + typedef AutoUTFOutputStream OutputStream; + OutputStream eos(bos, type, putBOM); + + Writer, AutoUTF<> > writer; + d.Accept(writer); +} +~~~~~~~~~~ + +`AutoUTFInputStream` and `AutoUTFOutputStream` is more convenient than `EncodedInputStream` and `EncodedOutputStream`. They just incur a little bit runtime overheads. + +# Custom Stream {#CustomStream} + +In addition to memory/file streams, user can create their own stream classes which fits RapidJSON's API. For example, you may create network stream, stream from compressed file, etc. + +RapidJSON combines different types using templates. A class containing all required interface can be a stream. The Stream interface is defined in comments of `rapidjson/rapidjson.h`: + +~~~~~~~~~~cpp +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +~~~~~~~~~~ + +For input stream, they must implement `Peek()`, `Take()` and `Tell()`. +For output stream, they must implement `Put()` and `Flush()`. +There are two special interface, `PutBegin()` and `PutEnd()`, which are only for *in situ* parsing. Normal streams do not implement them. However, if the interface is not needed for a particular stream, it is still need to a dummy implementation, otherwise will generate compilation error. + +## Example: istream wrapper {#ExampleIStreamWrapper} + +The following example is a simple wrapper of `std::istream`, which only implements 3 functions. + +~~~~~~~~~~cpp +class MyIStreamWrapper { +public: + typedef char Ch; + + MyIStreamWrapper(std::istream& is) : is_(is) { + } + + Ch Peek() const { // 1 + int c = is_.peek(); + return c == std::char_traits::eof() ? '\0' : (Ch)c; + } + + Ch Take() { // 2 + int c = is_.get(); + return c == std::char_traits::eof() ? '\0' : (Ch)c; + } + + size_t Tell() const { return (size_t)is_.tellg(); } // 3 + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch) { assert(false); } + void Flush() { assert(false); } + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + MyIStreamWrapper(const MyIStreamWrapper&); + MyIStreamWrapper& operator=(const MyIStreamWrapper&); + + std::istream& is_; +}; +~~~~~~~~~~ + +User can use it to wrap instances of `std::stringstream`, `std::ifstream`. + +~~~~~~~~~~cpp +const char* json = "[1,2,3,4]"; +std::stringstream ss(json); +MyIStreamWrapper is(ss); + +Document d; +d.ParseStream(is); +~~~~~~~~~~ + +Note that, this implementation may not be as efficient as RapidJSON's memory or file streams, due to internal overheads of the standard library. + +## Example: ostream wrapper {#ExampleOStreamWrapper} + +The following example is a simple wrapper of `std::istream`, which only implements 2 functions. + +~~~~~~~~~~cpp +class MyOStreamWrapper { +public: + typedef char Ch; + + MyOStreamWrapper(std::ostream& os) : os_(os) { + } + + Ch Peek() const { assert(false); return '\0'; } + Ch Take() { assert(false); return '\0'; } + size_t Tell() const { } + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch c) { os_.put(c); } // 1 + void Flush() { os_.flush(); } // 2 + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + MyOStreamWrapper(const MyOStreamWrapper&); + MyOStreamWrapper& operator=(const MyOStreamWrapper&); + + std::ostream& os_; +}; +~~~~~~~~~~ + +User can use it to wrap instances of `std::stringstream`, `std::ofstream`. + +~~~~~~~~~~cpp +Document d; +// ... + +std::stringstream ss; +MyOStreamWrapper os(ss); + +Writer writer(os); +d.Accept(writer); +~~~~~~~~~~ + +Note that, this implementation may not be as efficient as RapidJSON's memory or file streams, due to internal overheads of the standard library. + +# Summary {#Summary} + +This section describes stream classes available in RapidJSON. Memory streams are simple. File stream can reduce the memory required during JSON parsing and generation, if the JSON is stored in file system. Encoded streams converts between byte streams and character streams. Finally, user may create custom streams using a simple interface. diff --git a/deps/rapidjson/doc/stream.zh-cn.md b/deps/rapidjson/doc/stream.zh-cn.md new file mode 100644 index 0000000..6e379bb --- /dev/null +++ b/deps/rapidjson/doc/stream.zh-cn.md @@ -0,0 +1,429 @@ +# æµ + +在 RapidJSON 中,`rapidjson::Stream` 是用於读写 JSON 的概念(概念是指 C++ çš„ concept)。在这里我们先介ç»å¦‚何使用 RapidJSON æ供的å„ç§æµã€‚然åŽå†çœ‹çœ‹å¦‚何自行定义æµã€‚ + +[TOC] + +# å†…å­˜æµ {#MemoryStreams} + +内存æµæŠŠ JSON 存储在内存之中。 + +## StringStream(输入){#StringStream} + +`StringStream` 是最基本的输入æµï¼Œå®ƒè¡¨ç¤ºä¸€ä¸ªå®Œæ•´çš„ã€åªè¯»çš„ã€å­˜å‚¨äºŽå†…存的 JSON。它在 `rapidjson/rapidjson.h` 中定义。 + +~~~~~~~~~~cpp +#include "rapidjson/document.h" // ä¼šåŒ…å« "rapidjson/rapidjson.h" + +using namespace rapidjson; + +// ... +const char json[] = "[1, 2, 3, 4]"; +StringStream s(json); + +Document d; +d.ParseStream(s); +~~~~~~~~~~ + +由于这是éžå¸¸å¸¸ç”¨çš„用法,RapidJSON æä¾› `Document::Parse(const char*)` 去åšå®Œå…¨ç›¸åŒçš„事情: + +~~~~~~~~~~cpp +// ... +const char json[] = "[1, 2, 3, 4]"; +Document d; +d.Parse(json); +~~~~~~~~~~ + +需è¦æ³¨æ„,`StringStream` 是 `GenericStringStream >` çš„ typedef,使用者å¯ç”¨å…¶ä»–ç¼–ç ç±»åŽ»ä»£è¡¨æµæ‰€ä½¿ç”¨çš„字符集。 + +## StringBuffer(输出){#StringBuffer} + +`StringBuffer` 是一个简å•çš„输出æµã€‚它分é…一个内存缓冲区,供写入整个 JSON。å¯ä½¿ç”¨ `GetString()` æ¥èŽ·å–该缓冲区。 + +~~~~~~~~~~cpp +#include "rapidjson/stringbuffer.h" +#include + +StringBuffer buffer; +Writer writer(buffer); +d.Accept(writer); + +const char* output = buffer.GetString(); +~~~~~~~~~~ + +当缓冲区满溢,它将自动增加容é‡ã€‚缺çœå®¹é‡æ˜¯ 256 个字符(UTF8 是 256 字节,UTF16 是 512 字节等)。使用者能自行æ供分é…器åŠåˆå§‹å®¹é‡ã€‚ + +~~~~~~~~~~cpp +StringBuffer buffer1(0, 1024); // 使用它的分é…器,åˆå§‹å¤§å° = 1024 +StringBuffer buffer2(allocator, 1024); +~~~~~~~~~~ + +如无设置分é…器,`StringBuffer` 会自行实例化一个内部分é…器。 + +相似地,`StringBuffer` 是 `GenericStringBuffer >` çš„ typedef。 + +# æ–‡ä»¶æµ {#FileStreams} + +当è¦ä»Žæ–‡ä»¶è§£æžä¸€ä¸ª JSON,你å¯ä»¥æŠŠæ•´ä¸ª JSON 读入内存并使用上述的 `StringStream`。 + +然而,若 JSON 很大,或是内存有é™ï¼Œä½ å¯ä»¥æ”¹ç”¨ `FileReadStream`。它åªä¼šä»Žæ–‡ä»¶è¯»å–一部分至缓冲区,然åŽè®©é‚£éƒ¨åˆ†è¢«è§£æžã€‚若缓冲区的字符都被读完,它会å†ä»Žæ–‡ä»¶è¯»å–下一部分。 + +## FileReadStream(输入) {#FileReadStream} + +`FileReadStream` 通过 `FILE` 指针读å–文件。使用者需è¦æ供一个缓冲区。 + +~~~~~~~~~~cpp +#include "rapidjson/filereadstream.h" +#include + +using namespace rapidjson; + +FILE* fp = fopen("big.json", "rb"); // éž Windows å¹³å°ä½¿ç”¨ "r" + +char readBuffer[65536]; +FileReadStream is(fp, readBuffer, sizeof(readBuffer)); + +Document d; +d.ParseStream(is); + +fclose(fp); +~~~~~~~~~~ + +与 `StringStreams` ä¸ä¸€æ ·ï¼Œ`FileReadStream` 是一个字节æµã€‚它ä¸å¤„ç†ç¼–ç ã€‚è‹¥æ–‡ä»¶å¹¶éž UTF-8 ç¼–ç ï¼Œå¯ä»¥æŠŠå­—节æµç”¨ `EncodedInputStream` 包装。我们很快会讨论这个问题。 + +除了读å–文件,使用者也å¯ä»¥ä½¿ç”¨ `FileReadStream` æ¥è¯»å– `stdin`。 + +## FileWriteStream(输出){#FileWriteStream} + +`FileWriteStream` 是一个å«ç¼“冲功能的输出æµã€‚它的用法与 `FileReadStream` éžå¸¸ç›¸ä¼¼ã€‚ + +~~~~~~~~~~cpp +#include "rapidjson/filewritestream.h" +#include +#include + +using namespace rapidjson; + +Document d; +d.Parse(json); +// ... + +FILE* fp = fopen("output.json", "wb"); // éž Windows å¹³å°ä½¿ç”¨ "w" + +char writeBuffer[65536]; +FileWriteStream os(fp, writeBuffer, sizeof(writeBuffer)); + +Writer writer(os); +d.Accept(writer); + +fclose(fp); +~~~~~~~~~~ + +它也å¯ä»¥æŠŠè¾“å‡ºå¯¼å‘ `stdout`。 + +# iostream 包装类 {#iostreamWrapper} + +基于用户的è¦æ±‚,RapidJSON æ供了正å¼çš„ `std::basic_istream` å’Œ `std::basic_ostream` 包装类。然而,请注æ„其性能会大大低于以上的其他æµã€‚ + +## IStreamWrapper {#IStreamWrapper} + +`IStreamWrapper` 把任何继承自 `std::istream` 的类(如 `std::istringstream`ã€`std::stringstream`ã€`std::ifstream`ã€`std::fstream`ï¼‰åŒ…è£…æˆ RapidJSON 的输入æµã€‚ + +~~~cpp +#include +#include +#include + +using namespace rapidjson; +using namespace std; + +ifstream ifs("test.json"); +IStreamWrapper isw(ifs); + +Document d; +d.ParseStream(isw); +~~~ + +对于继承自 `std::wistream` 的类,则使用 `WIStreamWrapper`。 + +## OStreamWrapper {#OStreamWrapper} + +相似地,`OStreamWrapper` 把任何继承自 `std::ostream` 的类(如 `std::ostringstream`ã€`std::stringstream`ã€`std::ofstream`ã€`std::fstream`ï¼‰åŒ…è£…æˆ RapidJSON 的输出æµã€‚ + +~~~cpp +#include +#include +#include +#include + +using namespace rapidjson; +using namespace std; + +Document d; +d.Parse(json); + +// ... + +ofstream ofs("output.json"); +OStreamWrapper osw(ofs); + +Writer writer(osw); +d.Accept(writer); +~~~ + +对于继承自 `std::wistream` 的类,则使用 `WIStreamWrapper`。 + +# ç¼–ç æµ {#EncodedStreams} + +ç¼–ç æµï¼ˆencoded streams)本身ä¸å­˜å‚¨ JSON,它们是通过包装字节æµæ¥æ供基本的编ç ï¼è§£ç åŠŸèƒ½ã€‚ + +如上所述,我们å¯ä»¥ç›´æŽ¥è¯»å…¥ UTF-8 字节æµã€‚然而,UTF-16 åŠ UTF-32 有字节åºï¼ˆendian)问题。è¦æ­£ç¡®åœ°å¤„ç†å­—节åºï¼Œéœ€è¦åœ¨è¯»å–时把字节转æ¢æˆå­—符(如对 UTF-16 使用 `wchar_t`),以åŠåœ¨å†™å…¥æ—¶æŠŠå­—符转æ¢ä¸ºå­—节。 + +除此以外,我们也需è¦å¤„ç† [字节顺åºæ ‡è®°ï¼ˆbyte order mark, BOM)](http://en.wikipedia.org/wiki/Byte_order_mark)。当从一个字节æµè¯»å–时,需è¦æ£€æµ‹ BOM,或者仅仅是把存在的 BOM 消去。当把 JSON 写入字节æµæ—¶ï¼Œä¹Ÿå¯é€‰æ‹©å†™å…¥ BOM。 + +若一个æµçš„ç¼–ç åœ¨ç¼–译期已知,你å¯ä½¿ç”¨ `EncodedInputStream` åŠ `EncodedOutputStream`。若一个æµå¯èƒ½å­˜å‚¨ UTF-8ã€UTF-16LEã€UTF-16BEã€UTF-32LEã€UTF-32BE çš„ JSON,并且编ç åªèƒ½åœ¨è¿è¡Œæ—¶å¾—知,你便å¯ä»¥ä½¿ç”¨ `AutoUTFInputStream` åŠ `AutoUTFOutputStream`。这些æµå®šä¹‰åœ¨ `rapidjson/encodedstream.h`。 + +注æ„到,这些编ç æµå¯ä»¥æ–½äºŽæ–‡ä»¶ä»¥å¤–çš„æµã€‚例如,你å¯ä»¥ç”¨ç¼–ç æµåŒ…装内存中的文件或自定义的字节æµã€‚ + +## EncodedInputStream {#EncodedInputStream} + +`EncodedInputStream` å«ä¸¤ä¸ªæ¨¡æ¿å‚数。第一个是 `Encoding` 类型,例如定义于 `rapidjson/encodings.h` çš„ `UTF8`ã€`UTF16LE`。第二个å‚数是被包装的æµçš„类型。 + +~~~~~~~~~~cpp +#include "rapidjson/document.h" +#include "rapidjson/filereadstream.h" // FileReadStream +#include "rapidjson/encodedstream.h" // EncodedInputStream +#include + +using namespace rapidjson; + +FILE* fp = fopen("utf16le.json", "rb"); // éž Windows å¹³å°ä½¿ç”¨ "r" + +char readBuffer[256]; +FileReadStream bis(fp, readBuffer, sizeof(readBuffer)); + +EncodedInputStream, FileReadStream> eis(bis); // 用 eis 包装 bis + +Document d; // Document 为 GenericDocument > +d.ParseStream<0, UTF16LE<> >(eis); // 把 UTF-16LE 文件解æžè‡³å†…存中的 UTF-8 + +fclose(fp); +~~~~~~~~~~ + +## EncodedOutputStream {#EncodedOutputStream} + +`EncodedOutputStream` 也是相似的,但它的构造函数有一个 `bool putBOM` å‚数,用于控制是å¦åœ¨è¾“出字节æµå†™å…¥ BOM。 + +~~~~~~~~~~cpp +#include "rapidjson/filewritestream.h" // FileWriteStream +#include "rapidjson/encodedstream.h" // EncodedOutputStream +#include +#include + +Document d; // Document 为 GenericDocument > +// ... + +FILE* fp = fopen("output_utf32le.json", "wb"); // éž Windows å¹³å°ä½¿ç”¨ "w" + +char writeBuffer[256]; +FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer)); + +typedef EncodedOutputStream, FileWriteStream> OutputStream; +OutputStream eos(bos, true); // 写入 BOM + +Writer, UTF32LE<>> writer(eos); +d.Accept(writer); // 这里从内存的 UTF-8 ç”Ÿæˆ UTF32-LE 文件 + +fclose(fp); +~~~~~~~~~~ + +## AutoUTFInputStream {#AutoUTFInputStream} + +有时候,应用软件å¯èƒ½éœ€è¦ã²ƒç†æ‰€æœ‰å¯æ”¯æŒçš„ JSON ç¼–ç ã€‚`AutoUTFInputStream` 会先使用 BOM æ¥æ£€æµ‹ç¼–ç ã€‚è‹¥ BOM ä¸å­˜åœ¨ï¼Œå®ƒä¾¿ä¼šä½¿ç”¨åˆæ³• JSON 的特性æ¥æ£€æµ‹ã€‚若两ç§æ–¹æ³•éƒ½å¤±è´¥ï¼Œå®ƒå°±ä¼šå€’退至构造函数æ供的 UTF 类型。 + +由于字符(编ç å•å…ƒï¼code unit)å¯èƒ½æ˜¯ 8 ä½ã€16 ä½æˆ– 32 ä½ï¼Œ`AutoUTFInputStream` 需è¦ä¸€ä¸ªèƒ½è‡³å°‘储存 32 ä½çš„字符类型。我们å¯ä»¥ä½¿ç”¨ `unsigned` 作为模æ¿å‚数: + +~~~~~~~~~~cpp +#include "rapidjson/document.h" +#include "rapidjson/filereadstream.h" // FileReadStream +#include "rapidjson/encodedstream.h" // AutoUTFInputStream +#include + +using namespace rapidjson; + +FILE* fp = fopen("any.json", "rb"); // éž Windows å¹³å°ä½¿ç”¨ "r" + +char readBuffer[256]; +FileReadStream bis(fp, readBuffer, sizeof(readBuffer)); + +AutoUTFInputStream eis(bis); // 用 eis 包装 bis + +Document d; // Document 为 GenericDocument > +d.ParseStream<0, AutoUTF >(eis); // 把任何 UTF ç¼–ç çš„文件解æžè‡³å†…存中的 UTF-8 + +fclose(fp); +~~~~~~~~~~ + +当è¦æŒ‡å®šæµçš„ç¼–ç ï¼Œå¯ä½¿ç”¨ä¸Šé¢ä¾‹å­ä¸­ `ParseStream()` çš„å‚æ•° `AutoUTF`。 + +ä½ å¯ä»¥ä½¿ç”¨ `UTFType GetType()` åŽ»èŽ·å– UTF 类型,并且用 `HasBOM()` 检测输入æµæ˜¯å¦å«æœ‰ BOM。 + +## AutoUTFOutputStream {#AutoUTFOutputStream} + +相似地,è¦åœ¨è¿è¡Œæ—¶é€‰æ‹©è¾“出的编ç ï¼Œæˆ‘们å¯ä½¿ç”¨ `AutoUTFOutputStream`。这个类本身并éžã€Œè‡ªåŠ¨ã€ã€‚你需è¦åœ¨è¿è¡Œæ—¶æŒ‡å®š UTF 类型,以åŠæ˜¯å¦å†™å…¥ BOM。 + +~~~~~~~~~~cpp +using namespace rapidjson; + +void WriteJSONFile(FILE* fp, UTFType type, bool putBOM, const Document& d) { + char writeBuffer[256]; + FileWriteStream bos(fp, writeBuffer, sizeof(writeBuffer)); + + typedef AutoUTFOutputStream OutputStream; + OutputStream eos(bos, type, putBOM); + + Writer, AutoUTF<> > writer; + d.Accept(writer); +} +~~~~~~~~~~ + +`AutoUTFInputStream`ï¼`AutoUTFOutputStream` 是比 `EncodedInputStream`ï¼`EncodedOutputStream` 方便。但å‰è€…会产生一点è¿è¡ŒæœŸé¢å¤–开销。 + +# è‡ªå®šä¹‰æµ {#CustomStream} + +除了内存ï¼æ–‡ä»¶æµï¼Œä½¿ç”¨è€…å¯åˆ›å»ºè‡ªè¡Œå®šä¹‰é€‚é… RapidJSON API çš„æµç±»ã€‚例如,你å¯ä»¥åˆ›å»ºç½‘络æµã€ä»ŽåŽ‹ç¼©æ–‡ä»¶è¯»å–çš„æµç­‰ç­‰ã€‚ + +RapidJSON 利用模æ¿ç»“åˆä¸åŒçš„类型。åªè¦ä¸€ä¸ªç±»åŒ…å«æ‰€æœ‰æ‰€éœ€çš„接å£ï¼Œå°±å¯ä»¥ä½œä¸ºä¸€ä¸ªæµã€‚æµçš„接åˆå®šä¹‰åœ¨ `rapidjson/rapidjson.h` 的注释里: + +~~~~~~~~~~cpp +concept Stream { + typename Ch; //!< æµçš„字符类型 + + //! 从æµè¯»å–当å‰å­—符,ä¸ç§»åŠ¨è¯»å–指针(read cursor) + Ch Peek() const; + + //! 从æµè¯»å–当å‰å­—符,移动读å–指针至下一字符。 + Ch Take(); + + //! 获å–读å–指针。 + //! \return 从开始以æ¥æ‰€è¯»è¿‡çš„字符数é‡ã€‚ + size_t Tell(); + + //! 从当å‰è¯»å–指针开始写入æ“作。 + //! \return 返回开始写入的指针。 + Ch* PutBegin(); + + //! 写入一个字符。 + void Put(Ch c); + + //! 清空缓冲区。 + void Flush(); + + //! 完æˆå†™ä½œæ“作。 + //! \param begin PutBegin() 返回的开始写入指针。 + //! \return 已写入的字符数é‡ã€‚ + size_t PutEnd(Ch* begin); +} +~~~~~~~~~~ + +输入æµå¿…须实现 `Peek()`ã€`Take()` åŠ `Tell()`。 +输出æµå¿…须实现 `Put()` åŠ `Flush()`。 +`PutBegin()` åŠ `PutEnd()` 是特殊的接å£ï¼Œä»…用于原ä½ï¼ˆ*in situ*)解æžã€‚一般的æµä¸éœ€å®žçŽ°å®ƒä»¬ã€‚然而,å³ä½¿æŽ¥å£ä¸éœ€ç”¨äºŽæŸäº›æµï¼Œä»ç„¶éœ€è¦æ供空实现,å¦åˆ™ä¼šäº§ç”Ÿç¼–译错误。 + +## 例å­ï¼šistream 的包装类 {#ExampleIStreamWrapper} + +以下的简å•ä¾‹å­æ˜¯ `std::istream` 的包装类,它åªéœ€çŽ° 3 个函数。 + +~~~~~~~~~~cpp +class MyIStreamWrapper { +public: + typedef char Ch; + + MyIStreamWrapper(std::istream& is) : is_(is) { + } + + Ch Peek() const { // 1 + int c = is_.peek(); + return c == std::char_traits::eof() ? '\0' : (Ch)c; + } + + Ch Take() { // 2 + int c = is_.get(); + return c == std::char_traits::eof() ? '\0' : (Ch)c; + } + + size_t Tell() const { return (size_t)is_.tellg(); } // 3 + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch) { assert(false); } + void Flush() { assert(false); } + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + MyIStreamWrapper(const MyIStreamWrapper&); + MyIStreamWrapper& operator=(const MyIStreamWrapper&); + + std::istream& is_; +}; +~~~~~~~~~~ + +使用者能用它æ¥åŒ…装 `std::stringstream`ã€`std::ifstream` 的实例。 + +~~~~~~~~~~cpp +const char* json = "[1,2,3,4]"; +std::stringstream ss(json); +MyIStreamWrapper is(ss); + +Document d; +d.ParseStream(is); +~~~~~~~~~~ + +但è¦æ³¨æ„,由于标准库的内部开销问,此实现的性能å¯èƒ½ä¸å¦‚ RapidJSON 的内存ï¼æ–‡ä»¶æµã€‚ + +## 例å­ï¼šostream 的包装类 {#ExampleOStreamWrapper} + +以下的例å­æ˜¯ `std::istream` 的包装类,它åªéœ€å®žçŽ° 2 个函数。 + +~~~~~~~~~~cpp +class MyOStreamWrapper { +public: + typedef char Ch; + + OStreamWrapper(std::ostream& os) : os_(os) { + } + + Ch Peek() const { assert(false); return '\0'; } + Ch Take() { assert(false); return '\0'; } + size_t Tell() const { } + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch c) { os_.put(c); } // 1 + void Flush() { os_.flush(); } // 2 + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + MyOStreamWrapper(const MyOStreamWrapper&); + MyOStreamWrapper& operator=(const MyOStreamWrapper&); + + std::ostream& os_; +}; +~~~~~~~~~~ + +使用者能用它æ¥åŒ…装 `std::stringstream`ã€`std::ofstream` 的实例。 + +~~~~~~~~~~cpp +Document d; +// ... + +std::stringstream ss; +MyOStreamWrapper os(ss); + +Writer writer(os); +d.Accept(writer); +~~~~~~~~~~ + +但è¦æ³¨æ„,由于标准库的内部开销问,此实现的性能å¯èƒ½ä¸å¦‚ RapidJSON 的内存ï¼æ–‡ä»¶æµã€‚ + +# 总结 {#Summary} + +本节æ述了 RapidJSON æ供的å„ç§æµçš„类。内存æµå¾ˆç®€å•ã€‚è‹¥ JSON 存储在文件中,文件æµå¯å‡å°‘ JSON 解æžåŠç”Ÿæˆæ‰€éœ€çš„内存é‡ã€‚ç¼–ç æµåœ¨å­—节æµå’Œå­—符æµä¹‹é—´ä½œè½¬æ¢ã€‚最åŽï¼Œä½¿ç”¨è€…å¯ä½¿ç”¨ä¸€ä¸ªç®€å•æŽ¥å£åˆ›å»ºè‡ªå®šä¹‰çš„æµã€‚ diff --git a/deps/rapidjson/doc/tutorial.md b/deps/rapidjson/doc/tutorial.md new file mode 100644 index 0000000..a86aafd --- /dev/null +++ b/deps/rapidjson/doc/tutorial.md @@ -0,0 +1,536 @@ +# Tutorial + +This tutorial introduces the basics of the Document Object Model(DOM) API. + +As shown in [Usage at a glance](@ref index), JSON can be parsed into a DOM, and then the DOM can be queried and modified easily, and finally be converted back to JSON. + +[TOC] + +# Value & Document {#ValueDocument} + +Each JSON value is stored in a type called `Value`. A `Document`, representing the DOM, contains the root `Value` of the DOM tree. All public types and functions of RapidJSON are defined in the `rapidjson` namespace. + +# Query Value {#QueryValue} + +In this section, we will use excerpt from `example/tutorial/tutorial.cpp`. + +Assume we have the following JSON stored in a C string (`const char* json`): +~~~~~~~~~~js +{ + "hello": "world", + "t": true , + "f": false, + "n": null, + "i": 123, + "pi": 3.1416, + "a": [1, 2, 3, 4] +} +~~~~~~~~~~ + +Parse it into a `Document`: +~~~~~~~~~~cpp +#include "rapidjson/document.h" + +using namespace rapidjson; + +// ... +Document document; +document.Parse(json); +~~~~~~~~~~ + +The JSON is now parsed into `document` as a *DOM tree*: + +![DOM in the tutorial](diagram/tutorial.png) + +Since the update to RFC 7159, the root of a conforming JSON document can be any JSON value. In earlier RFC 4627, only objects or arrays were allowed as root values. In this case, the root is an object. +~~~~~~~~~~cpp +assert(document.IsObject()); +~~~~~~~~~~ + +Let's query whether a `"hello"` member exists in the root object. Since a `Value` can contain different types of value, we may need to verify its type and use suitable API to obtain the value. In this example, `"hello"` member associates with a JSON string. +~~~~~~~~~~cpp +assert(document.HasMember("hello")); +assert(document["hello"].IsString()); +printf("hello = %s\n", document["hello"].GetString()); +~~~~~~~~~~ + +~~~~~~~~~~ +hello = world +~~~~~~~~~~ + +JSON true/false values are represented as `bool`. +~~~~~~~~~~cpp +assert(document["t"].IsBool()); +printf("t = %s\n", document["t"].GetBool() ? "true" : "false"); +~~~~~~~~~~ + +~~~~~~~~~~ +t = true +~~~~~~~~~~ + +JSON null can be queried with `IsNull()`. +~~~~~~~~~~cpp +printf("n = %s\n", document["n"].IsNull() ? "null" : "?"); +~~~~~~~~~~ + +~~~~~~~~~~ +n = null +~~~~~~~~~~ + +JSON number type represents all numeric values. However, C++ needs more specific type for manipulation. + +~~~~~~~~~~cpp +assert(document["i"].IsNumber()); + +// In this case, IsUint()/IsInt64()/IsUint64() also return true. +assert(document["i"].IsInt()); +printf("i = %d\n", document["i"].GetInt()); +// Alternatively (int)document["i"] + +assert(document["pi"].IsNumber()); +assert(document["pi"].IsDouble()); +printf("pi = %g\n", document["pi"].GetDouble()); +~~~~~~~~~~ + +~~~~~~~~~~ +i = 123 +pi = 3.1416 +~~~~~~~~~~ + +JSON array contains a number of elements. +~~~~~~~~~~cpp +// Using a reference for consecutive access is handy and faster. +const Value& a = document["a"]; +assert(a.IsArray()); +for (SizeType i = 0; i < a.Size(); i++) // Uses SizeType instead of size_t + printf("a[%d] = %d\n", i, a[i].GetInt()); +~~~~~~~~~~ + +~~~~~~~~~~ +a[0] = 1 +a[1] = 2 +a[2] = 3 +a[3] = 4 +~~~~~~~~~~ + +Note that, RapidJSON does not automatically convert values between JSON types. For example, if a value is a string, it is invalid to call `GetInt()`. In debug mode it will fail on assertion. In release mode, the behavior is undefined. + +In the following sections we discuss details about querying individual types. + +## Query Array {#QueryArray} + +By default, `SizeType` is typedef of `unsigned`. In most systems, an array is limited to store up to 2^32-1 elements. + +You may access the elements in an array by integer literal, for example, `a[0]`, `a[1]`, `a[2]`. + +Array is similar to `std::vector`: instead of using indices, you may also use iterator to access all the elements. +~~~~~~~~~~cpp +for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + printf("%d ", itr->GetInt()); +~~~~~~~~~~ + +And other familiar query functions: +* `SizeType Capacity() const` +* `bool Empty() const` + +### Range-based For Loop (New in v1.1.0) + +When C++11 is enabled, you can use range-based for loop to access all elements in an array. + +~~~~~~~~~~cpp +for (auto& v : a.GetArray()) + printf("%d ", v.GetInt()); +~~~~~~~~~~ + +## Query Object {#QueryObject} + +Similar to Array, we can access all object members by iterator: + +~~~~~~~~~~cpp +static const char* kTypeNames[] = + { "Null", "False", "True", "Object", "Array", "String", "Number" }; + +for (Value::ConstMemberIterator itr = document.MemberBegin(); + itr != document.MemberEnd(); ++itr) +{ + printf("Type of member %s is %s\n", + itr->name.GetString(), kTypeNames[itr->value.GetType()]); +} +~~~~~~~~~~ + +~~~~~~~~~~ +Type of member hello is String +Type of member t is True +Type of member f is False +Type of member n is Null +Type of member i is Number +Type of member pi is Number +Type of member a is Array +~~~~~~~~~~ + +Note that, when `operator[](const char*)` cannot find the member, it will fail on assertion. + +If we are unsure whether a member exists, we need to call `HasMember()` before calling `operator[](const char*)`. However, this incurs two lookup. A better way is to call `FindMember()`, which can check the existence of a member and obtain its value at once: + +~~~~~~~~~~cpp +Value::ConstMemberIterator itr = document.FindMember("hello"); +if (itr != document.MemberEnd()) + printf("%s\n", itr->value.GetString()); +~~~~~~~~~~ + +### Range-based For Loop (New in v1.1.0) + +When C++11 is enabled, you can use range-based for loop to access all members in an object. + +~~~~~~~~~~cpp +for (auto& m : document.GetObject()) + printf("Type of member %s is %s\n", + m.name.GetString(), kTypeNames[m.value.GetType()]); +~~~~~~~~~~ + +## Querying Number {#QueryNumber} + +JSON provides a single numerical type called Number. Number can be an integer or a real number. RFC 4627 says the range of Number is specified by the parser implementation. + +As C++ provides several integer and floating point number types, the DOM tries to handle these with the widest possible range and good performance. + +When a Number is parsed, it is stored in the DOM as one of the following types: + +Type | Description +-----------|--------------------------------------- +`unsigned` | 32-bit unsigned integer +`int` | 32-bit signed integer +`uint64_t` | 64-bit unsigned integer +`int64_t` | 64-bit signed integer +`double` | 64-bit double precision floating point + +When querying a number, you can check whether the number can be obtained as the target type: + +Checking | Obtaining +------------------|--------------------- +`bool IsNumber()` | N/A +`bool IsUint()` | `unsigned GetUint()` +`bool IsInt()` | `int GetInt()` +`bool IsUint64()` | `uint64_t GetUint64()` +`bool IsInt64()` | `int64_t GetInt64()` +`bool IsDouble()` | `double GetDouble()` + +Note that, an integer value may be obtained in various ways without conversion. For example, A value `x` containing 123 will make `x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true`. But a value `y` containing -3000000000 will only make `x.IsInt64() == true`. + +When obtaining the numeric values, `GetDouble()` will convert internal integer representation to a `double`. Note that, `int` and `unsigned` can be safely converted to `double`, but `int64_t` and `uint64_t` may lose precision (since mantissa of `double` is only 52-bits). + +## Query String {#QueryString} + +In addition to `GetString()`, the `Value` class also contains `GetStringLength()`. Here explains why: + +According to RFC 4627, JSON strings can contain Unicode character `U+0000`, which must be escaped as `"\u0000"`. The problem is that, C/C++ often uses null-terminated string, which treats `\0` as the terminator symbol. + +To conform with RFC 4627, RapidJSON supports string containing `U+0000` character. If you need to handle this, you can use `GetStringLength()` to obtain the correct string length. + +For example, after parsing the following JSON to `Document d`: + +~~~~~~~~~~js +{ "s" : "a\u0000b" } +~~~~~~~~~~ +The correct length of the string `"a\u0000b"` is 3, as returned by `GetStringLength()`. But `strlen()` returns 1. + +`GetStringLength()` can also improve performance, as user may often need to call `strlen()` for allocating buffer. + +Besides, `std::string` also support a constructor: + +~~~~~~~~~~cpp +string(const char* s, size_t count); +~~~~~~~~~~ + +which accepts the length of string as parameter. This constructor supports storing null character within the string, and should also provide better performance. + +## Comparing values + +You can use `==` and `!=` to compare values. Two values are equal if and only if they have same type and contents. You can also compare values with primitive types. Here is an example: + +~~~~~~~~~~cpp +if (document["hello"] == document["n"]) /*...*/; // Compare values +if (document["hello"] == "world") /*...*/; // Compare value with literal string +if (document["i"] != 123) /*...*/; // Compare with integers +if (document["pi"] != 3.14) /*...*/; // Compare with double. +~~~~~~~~~~ + +Array/object compares their elements/members in order. They are equal if and only if their whole subtrees are equal. + +Note that, currently if an object contains duplicated named member, comparing equality with any object is always `false`. + +# Create/Modify Values {#CreateModifyValues} + +There are several ways to create values. After a DOM tree is created and/or modified, it can be saved as JSON again using `Writer`. + +## Change Value Type {#ChangeValueType} +When creating a `Value` or `Document` by default constructor, its type is Null. To change its type, call `SetXXX()` or assignment operator, for example: + +~~~~~~~~~~cpp +Document d; // Null +d.SetObject(); + +Value v; // Null +v.SetInt(10); +v = 10; // Shortcut, same as above +~~~~~~~~~~ + +### Overloaded Constructors +There are also overloaded constructors for several types: + +~~~~~~~~~~cpp +Value b(true); // calls Value(bool) +Value i(-123); // calls Value(int) +Value u(123u); // calls Value(unsigned) +Value d(1.5); // calls Value(double) +~~~~~~~~~~ + +To create empty object or array, you may use `SetObject()`/`SetArray()` after default constructor, or using the `Value(Type)` in one call: + +~~~~~~~~~~cpp +Value o(kObjectType); +Value a(kArrayType); +~~~~~~~~~~ + +## Move Semantics {#MoveSemantics} + +A very special decision during design of RapidJSON is that, assignment of value does not copy the source value to destination value. Instead, the value from source is moved to the destination. For example, + +~~~~~~~~~~cpp +Value a(123); +Value b(456); +a = b; // b becomes a Null value, a becomes number 456. +~~~~~~~~~~ + +![Assignment with move semantics.](diagram/move1.png) + +Why? What is the advantage of this semantics? + +The simple answer is performance. For fixed size JSON types (Number, True, False, Null), copying them is fast and easy. However, For variable size JSON types (String, Array, Object), copying them will incur a lot of overheads. And these overheads are often unnoticed. Especially when we need to create temporary object, copy it to another variable, and then destruct it. + +For example, if normal *copy* semantics was used: + +~~~~~~~~~~cpp +Document d; +Value o(kObjectType); +{ + Value contacts(kArrayType); + // adding elements to contacts array. + // ... + o.AddMember("contacts", contacts, d.GetAllocator()); // deep clone contacts (may be with lots of allocations) + // destruct contacts. +} +~~~~~~~~~~ + +![Copy semantics makes a lots of copy operations.](diagram/move2.png) + +The object `o` needs to allocate a buffer of same size as contacts, makes a deep clone of it, and then finally contacts is destructed. This will incur a lot of unnecessary allocations/deallocations and memory copying. + +There are solutions to prevent actual copying these data, such as reference counting and garbage collection(GC). + +To make RapidJSON simple and fast, we chose to use *move* semantics for assignment. It is similar to `std::auto_ptr` which transfer ownership during assignment. Move is much faster and simpler, it just destructs the original value, `memcpy()` the source to destination, and finally sets the source as Null type. + +So, with move semantics, the above example becomes: + +~~~~~~~~~~cpp +Document d; +Value o(kObjectType); +{ + Value contacts(kArrayType); + // adding elements to contacts array. + o.AddMember("contacts", contacts, d.GetAllocator()); // just memcpy() of contacts itself to the value of new member (16 bytes) + // contacts became Null here. Its destruction is trivial. +} +~~~~~~~~~~ + +![Move semantics makes no copying.](diagram/move3.png) + +This is called move assignment operator in C++11. As RapidJSON supports C++03, it adopts move semantics using assignment operator, and all other modifying function like `AddMember()`, `PushBack()`. + +### Move semantics and temporary values {#TemporaryValues} + +Sometimes, it is convenient to construct a Value in place, before passing it to one of the "moving" functions, like `PushBack()` or `AddMember()`. As temporary objects can't be converted to proper Value references, the convenience function `Move()` is available: + +~~~~~~~~~~cpp +Value a(kArrayType); +Document::AllocatorType& allocator = document.GetAllocator(); +// a.PushBack(Value(42), allocator); // will not compile +a.PushBack(Value().SetInt(42), allocator); // fluent API +a.PushBack(Value(42).Move(), allocator); // same as above +~~~~~~~~~~ + +## Create String {#CreateString} +RapidJSON provides two strategies for storing string. + +1. copy-string: allocates a buffer, and then copy the source data into it. +2. const-string: simply store a pointer of string. + +Copy-string is always safe because it owns a copy of the data. Const-string can be used for storing a string literal, and for in-situ parsing which will be mentioned in the DOM section. + +To make memory allocation customizable, RapidJSON requires users to pass an instance of allocator, whenever an operation may require allocation. This design is needed to prevent storing an allocator (or Document) pointer per Value. + +Therefore, when we assign a copy-string, we call this overloaded `SetString()` with allocator: + +~~~~~~~~~~cpp +Document document; +Value author; +char buffer[10]; +int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // dynamically created string. +author.SetString(buffer, len, document.GetAllocator()); +memset(buffer, 0, sizeof(buffer)); +// author.GetString() still contains "Milo Yip" after buffer is destroyed +~~~~~~~~~~ + +In this example, we get the allocator from a `Document` instance. This is a common idiom when using RapidJSON. But you may use other instances of allocator. + +Besides, the above `SetString()` requires length. This can handle null characters within a string. There is another `SetString()` overloaded function without the length parameter. And it assumes the input is null-terminated and calls a `strlen()`-like function to obtain the length. + +Finally, for a string literal or string with a safe life-cycle one can use the const-string version of `SetString()`, which lacks an allocator parameter. For string literals (or constant character arrays), simply passing the literal as parameter is safe and efficient: + +~~~~~~~~~~cpp +Value s; +s.SetString("rapidjson"); // can contain null character, length derived at compile time +s = "rapidjson"; // shortcut, same as above +~~~~~~~~~~ + +For a character pointer, RapidJSON requires it to be marked as safe before using it without copying. This can be achieved by using the `StringRef` function: + +~~~~~~~~~cpp +const char * cstr = getenv("USER"); +size_t cstr_len = ...; // in case length is available +Value s; +// s.SetString(cstr); // will not compile +s.SetString(StringRef(cstr)); // ok, assume safe lifetime, null-terminated +s = StringRef(cstr); // shortcut, same as above +s.SetString(StringRef(cstr,cstr_len)); // faster, can contain null character +s = StringRef(cstr,cstr_len); // shortcut, same as above + +~~~~~~~~~ + +## Modify Array {#ModifyArray} +Value with array type provides an API similar to `std::vector`. + +* `Clear()` +* `Reserve(SizeType, Allocator&)` +* `Value& PushBack(Value&, Allocator&)` +* `template GenericValue& PushBack(T, Allocator&)` +* `Value& PopBack()` +* `ValueIterator Erase(ConstValueIterator pos)` +* `ValueIterator Erase(ConstValueIterator first, ConstValueIterator last)` + +Note that, `Reserve(...)` and `PushBack(...)` may allocate memory for the array elements, therefore requiring an allocator. + +Here is an example of `PushBack()`: + +~~~~~~~~~~cpp +Value a(kArrayType); +Document::AllocatorType& allocator = document.GetAllocator(); + +for (int i = 5; i <= 10; i++) + a.PushBack(i, allocator); // allocator is needed for potential realloc(). + +// Fluent interface +a.PushBack("Lua", allocator).PushBack("Mio", allocator); +~~~~~~~~~~ + +This API differs from STL in that `PushBack()`/`PopBack()` return the array reference itself. This is called _fluent interface_. + +If you want to add a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)) to the array, you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place: + +~~~~~~~~~~cpp +// in-place Value parameter +contact.PushBack(Value("copy", document.GetAllocator()).Move(), // copy string + document.GetAllocator()); + +// explicit parameters +Value val("key", document.GetAllocator()); // copy string +contact.PushBack(val, document.GetAllocator()); +~~~~~~~~~~ + +## Modify Object {#ModifyObject} +The Object class is a collection of key-value pairs (members). Each key must be a string value. To modify an object, either add or remove members. The following API is for adding members: + +* `Value& AddMember(Value&, Value&, Allocator& allocator)` +* `Value& AddMember(StringRefType, Value&, Allocator&)` +* `template Value& AddMember(StringRefType, T value, Allocator&)` + +Here is an example. + +~~~~~~~~~~cpp +Value contact(kObject); +contact.AddMember("name", "Milo", document.GetAllocator()); +contact.AddMember("married", true, document.GetAllocator()); +~~~~~~~~~~ + +The name parameter with `StringRefType` is similar to the interface of the `SetString` function for string values. These overloads are used to avoid the need for copying the `name` string, since constant key names are very common in JSON objects. + +If you need to create a name from a non-constant string or a string without sufficient lifetime (see [Create String](#CreateString)), you need to create a string Value by using the copy-string API. To avoid the need for an intermediate variable, you can use a [temporary value](#TemporaryValues) in place: + +~~~~~~~~~~cpp +// in-place Value parameter +contact.AddMember(Value("copy", document.GetAllocator()).Move(), // copy string + Value().Move(), // null value + document.GetAllocator()); + +// explicit parameters +Value key("key", document.GetAllocator()); // copy string name +Value val(42); // some value +contact.AddMember(key, val, document.GetAllocator()); +~~~~~~~~~~ + +For removing members, there are several choices: + +* `bool RemoveMember(const Ch* name)`: Remove a member by search its name (linear time complexity). +* `bool RemoveMember(const Value& name)`: same as above but `name` is a Value. +* `MemberIterator RemoveMember(MemberIterator)`: Remove a member by iterator (_constant_ time complexity). +* `MemberIterator EraseMember(MemberIterator)`: similar to the above but it preserves order of members (linear time complexity). +* `MemberIterator EraseMember(MemberIterator first, MemberIterator last)`: remove a range of members, preserves order (linear time complexity). + +`MemberIterator RemoveMember(MemberIterator)` uses a "move-last" trick to achieve constant time complexity. Basically the member at iterator is destructed, and then the last element is moved to that position. So the order of the remaining members are changed. + +## Deep Copy Value {#DeepCopyValue} +If we really need to copy a DOM tree, we can use two APIs for deep copy: constructor with allocator, and `CopyFrom()`. + +~~~~~~~~~~cpp +Document d; +Document::AllocatorType& a = d.GetAllocator(); +Value v1("foo"); +// Value v2(v1); // not allowed + +Value v2(v1, a); // make a copy +assert(v1.IsString()); // v1 untouched +d.SetArray().PushBack(v1, a).PushBack(v2, a); +assert(v1.IsNull() && v2.IsNull()); // both moved to d + +v2.CopyFrom(d, a); // copy whole document to v2 +assert(d.IsArray() && d.Size() == 2); // d untouched +v1.SetObject().AddMember("array", v2, a); +d.PushBack(v1, a); +~~~~~~~~~~ + +## Swap Values {#SwapValues} + +`Swap()` is also provided. + +~~~~~~~~~~cpp +Value a(123); +Value b("Hello"); +a.Swap(b); +assert(a.IsString()); +assert(b.IsInt()); +~~~~~~~~~~ + +Swapping two DOM trees is fast (constant time), despite the complexity of the trees. + +# What's next {#WhatsNext} + +This tutorial shows the basics of DOM tree query and manipulation. There are several important concepts in RapidJSON: + +1. [Streams](doc/stream.md) are channels for reading/writing JSON, which can be a in-memory string, or file stream, etc. User can also create their streams. +2. [Encoding](doc/encoding.md) defines which character encoding is used in streams and memory. RapidJSON also provide Unicode conversion/validation internally. +3. [DOM](doc/dom.md)'s basics are already covered in this tutorial. Uncover more advanced features such as *in situ* parsing, other parsing options and advanced usages. +4. [SAX](doc/sax.md) is the foundation of parsing/generating facility in RapidJSON. Learn how to use `Reader`/`Writer` to implement even faster applications. Also try `PrettyWriter` to format the JSON. +5. [Performance](doc/performance.md) shows some in-house and third-party benchmarks. +6. [Internals](doc/internals.md) describes some internal designs and techniques of RapidJSON. + +You may also refer to the [FAQ](doc/faq.md), API documentation, examples and unit tests. diff --git a/deps/rapidjson/doc/tutorial.zh-cn.md b/deps/rapidjson/doc/tutorial.zh-cn.md new file mode 100644 index 0000000..8b24ff1 --- /dev/null +++ b/deps/rapidjson/doc/tutorial.zh-cn.md @@ -0,0 +1,535 @@ +# 教程 + +本教程简介文件对象模型(Document Object Model, DOM)API。 + +如 [用法一览](../readme.zh-cn.md#用法一览) 中所示,å¯ä»¥è§£æžä¸€ä¸ª JSON 至 DOM,然åŽå°±å¯ä»¥è½»æ¾æŸ¥è¯¢åŠä¿®æ”¹ DOM,并最终转æ¢å›ž JSON。 + +[TOC] + +# Value åŠ Document {#ValueDocument} + +æ¯ä¸ª JSON 值都储存为 `Value` 类,而 `Document` 类则表示整个 DOM,它存储了一个 DOM æ ‘çš„æ ¹ `Value`。RapidJSON 的所有公开类型åŠå‡½æ•°éƒ½åœ¨ `rapidjson` 命å空间中。 + +# 查询 Value {#QueryValue} + +在本节中,我们会使用到 `example/tutorial/tutorial.cpp` 中的代ç ç‰‡æ®µã€‚ + +å‡è®¾æˆ‘们用 C 语言的字符串储存一个 JSON(`const char* json`): +~~~~~~~~~~js +{ + "hello": "world", + "t": true , + "f": false, + "n": null, + "i": 123, + "pi": 3.1416, + "a": [1, 2, 3, 4] +} +~~~~~~~~~~ + +把它解æžè‡³ä¸€ä¸ª `Document`: +~~~~~~~~~~cpp +#include "rapidjson/document.h" + +using namespace rapidjson; + +// ... +Document document; +document.Parse(json); +~~~~~~~~~~ + +那么现在该 JSON 就会被解æžè‡³ `document` 中,æˆä¸ºä¸€æ£µ *DOM æ ‘ *: + +![教程中的 DOM](diagram/tutorial.png) + +自从 RFC 7159 作出更新,åˆæ³• JSON 文件的根å¯ä»¥æ˜¯ä»»ä½•ç±»åž‹çš„ JSON 值。而在较早的 RFC 4627 中,根值åªå…许是 Object 或 Array。而在上述例å­ä¸­ï¼Œæ ¹æ˜¯ä¸€ä¸ª Object。 +~~~~~~~~~~cpp +assert(document.IsObject()); +~~~~~~~~~~ + +让我们查询一下根 Object 中有没有 `"hello"` æˆå‘˜ã€‚由于一个 `Value` å¯åŒ…å«ä¸åŒç±»åž‹çš„值,我们å¯èƒ½éœ€è¦éªŒè¯å®ƒçš„类型,并使用åˆé€‚çš„ API 去获å–其值。在此例中,`"hello"` æˆå‘˜å…³è”到一个 JSON String。 +~~~~~~~~~~cpp +assert(document.HasMember("hello")); +assert(document["hello"].IsString()); +printf("hello = %s\n", document["hello"].GetString()); +~~~~~~~~~~ + +~~~~~~~~~~ +world +~~~~~~~~~~ + +JSON True/False 值是以 `bool` 表示的。 +~~~~~~~~~~cpp +assert(document["t"].IsBool()); +printf("t = %s\n", document["t"].GetBool() ? "true" : "false"); +~~~~~~~~~~ + +~~~~~~~~~~ +true +~~~~~~~~~~ + +JSON Null 值å¯ç”¨ `IsNull()` 查询。 +~~~~~~~~~~cpp +printf("n = %s\n", document["n"].IsNull() ? "null" : "?"); +~~~~~~~~~~ + +~~~~~~~~~~ +null +~~~~~~~~~~ + +JSON Number 类型表示所有数值。然而,C++ 需è¦ä½¿ç”¨æ›´ä¸“门的类型。 + +~~~~~~~~~~cpp +assert(document["i"].IsNumber()); + +// 在此情况下,IsUint()/IsInt64()/IsUint64() 也会返回 true +assert(document["i"].IsInt()); +printf("i = %d\n", document["i"].GetInt()); +// å¦ä¸€ç§ç”¨æ³•ï¼š (int)document["i"] + +assert(document["pi"].IsNumber()); +assert(document["pi"].IsDouble()); +printf("pi = %g\n", document["pi"].GetDouble()); +~~~~~~~~~~ + +~~~~~~~~~~ +i = 123 +pi = 3.1416 +~~~~~~~~~~ + +JSON Array 包å«ä¸€äº›å…ƒç´ ã€‚ +~~~~~~~~~~cpp +// 使用引用æ¥è¿žç»­è®¿é—®ï¼Œæ–¹ä¾¿ä¹‹ä½™è¿˜æ›´é«˜æ•ˆã€‚ +const Value& a = document["a"]; +assert(a.IsArray()); +for (SizeType i = 0; i < a.Size(); i++) // 使用 SizeType 而ä¸æ˜¯ size_t + printf("a[%d] = %d\n", i, a[i].GetInt()); +~~~~~~~~~~ + +~~~~~~~~~~ +a[0] = 1 +a[1] = 2 +a[2] = 3 +a[3] = 4 +~~~~~~~~~~ + +注æ„,RapidJSON 并ä¸è‡ªåŠ¨è½¬æ¢å„ç§ JSON 类型。例如,对一个 String çš„ Value 调用 `GetInt()` 是éžæ³•çš„。在调试模å¼ä¸‹ï¼Œå®ƒä¼šè¢«æ–­è¨€å¤±è´¥ã€‚在å‘布模å¼ä¸‹ï¼Œå…¶è¡Œä¸ºæ˜¯æœªå®šä¹‰çš„。 + +以下将会讨论有关查询å„类型的细节。 + +## 查询 Array {#QueryArray} + +缺çœæƒ…况下,`SizeType` 是 `unsigned` çš„ typedef。在多数系统中,Array 最多能存储 2^32-1 个元素。 + +ä½ å¯ä»¥ç”¨æ•´æ•°å­—é¢é‡è®¿é—®å…ƒç´ ï¼Œå¦‚ `a[0]`ã€`a[1]`ã€`a[2]`。 + +Array 与 `std::vector` 相似,除了使用索引,也å¯ä½¿ç”¨è¿­ä»£å™¨æ¥è®¿é—®æ‰€æœ‰å…ƒç´ ã€‚ +~~~~~~~~~~cpp +for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + printf("%d ", itr->GetInt()); +~~~~~~~~~~ + +还有一些熟悉的查询函数: +* `SizeType Capacity() const` +* `bool Empty() const` + +### 范围 for 循环 (v1.1.0 中的新功能) + +当使用 C++11 功能时,你å¯ä½¿ç”¨èŒƒå›´ for 循环去访问 Array 内的所有元素。 + +~~~~~~~~~~cpp +for (auto& v : a.GetArray()) + printf("%d ", v.GetInt()); +~~~~~~~~~~ + +## 查询 Object {#QueryObject} + +å’Œ Array 相似,我们å¯ä»¥ç”¨è¿­ä»£å™¨åŽ»è®¿é—®æ‰€æœ‰ Object æˆå‘˜ï¼š + +~~~~~~~~~~cpp +static const char* kTypeNames[] = + { "Null", "False", "True", "Object", "Array", "String", "Number" }; + +for (Value::ConstMemberIterator itr = document.MemberBegin(); + itr != document.MemberEnd(); ++itr) +{ + printf("Type of member %s is %s\n", + itr->name.GetString(), kTypeNames[itr->value.GetType()]); +} +~~~~~~~~~~ + +~~~~~~~~~~ +Type of member hello is String +Type of member t is True +Type of member f is False +Type of member n is Null +Type of member i is Number +Type of member pi is Number +Type of member a is Array +~~~~~~~~~~ + +注æ„,当 `operator[](const char*)` 找ä¸åˆ°æˆå‘˜ï¼Œå®ƒä¼šæ–­è¨€å¤±è´¥ã€‚ + +若我们ä¸ç¡®å®šä¸€ä¸ªæˆå‘˜æ˜¯å¦å­˜åœ¨ï¼Œä¾¿éœ€è¦åœ¨è°ƒç”¨ `operator[](const char*)` å‰å…ˆè°ƒç”¨ `HasMember()`。然而,这会导致两次查找。更好的åšæ³•æ˜¯è°ƒç”¨ `FindMember()`,它能åŒæ—¶æ£€æŸ¥æˆå‘˜æ˜¯å¦å­˜åœ¨å¹¶è¿”回它的 Value: + +~~~~~~~~~~cpp +Value::ConstMemberIterator itr = document.FindMember("hello"); +if (itr != document.MemberEnd()) + printf("%s\n", itr->value.GetString()); +~~~~~~~~~~ + +### 范围 for 循环 (v1.1.0 中的新功能) + +当使用 C++11 功能时,你å¯ä½¿ç”¨èŒƒå›´ for 循环去访问 Object 内的所有æˆå‘˜ã€‚ + +~~~~~~~~~~cpp +for (auto& m : document.GetObject()) + printf("Type of member %s is %s\n", + m.name.GetString(), kTypeNames[m.value.GetType()]); +~~~~~~~~~~ + +## 查询 Number {#QueryNumber} + +JSON åªæ供一ç§æ•°å€¼ç±»åž‹â”€â”€Number。数字å¯ä»¥æ˜¯æ•´æ•°æˆ–实数。RFC 4627 规定数字的范围由解æžå™¨æŒ‡å®šã€‚ + +由于 C++ æ供多ç§æ•´æ•°åŠæµ®ç‚¹æ•°ç±»åž‹ï¼ŒDOM å°è¯•å°½é‡æ供最广的范围åŠè‰¯å¥½æ€§èƒ½ã€‚ + +当解æžä¸€ä¸ª Number æ—¶, 它会被存储在 DOM 之中,æˆä¸ºä¸‹åˆ—其中一个类型: + +类型 | æè¿° +-----------|--------------------------------------- +`unsigned` | 32 ä½æ— å·æ•´æ•° +`int` | 32 ä½æœ‰å·æ•´æ•° +`uint64_t` | 64 ä½æ— å·æ•´æ•° +`int64_t` | 64 ä½æœ‰å·æ•´æ•° +`double` | 64 ä½åŒç²¾åº¦æµ®ç‚¹æ•° + +当查询一个 Number æ—¶, ä½ å¯ä»¥æ£€æŸ¥è¯¥æ•°å­—是å¦èƒ½ä»¥ç›®æ ‡ç±»åž‹æ¥æå–: + +查检 | æå– +------------------|--------------------- +`bool IsNumber()` | ä¸é€‚用 +`bool IsUint()` | `unsigned GetUint()` +`bool IsInt()` | `int GetInt()` +`bool IsUint64()` | `uint64_t GetUint64()` +`bool IsInt64()` | `int64_t GetInt64()` +`bool IsDouble()` | `double GetDouble()` + +注æ„,一个整数å¯èƒ½ç”¨å‡ ç§ç±»åž‹æ¥æå–,而无需转æ¢ã€‚例如,一个å为 `x` çš„ Value åŒ…å« 123,那么 `x.IsInt() == x.IsUint() == x.IsInt64() == x.IsUint64() == true`。但如果一个å为 `y` çš„ Value åŒ…å« -3000000000,那么仅会令 `x.IsInt64() == true`。 + +当è¦æå– Number 类型,`GetDouble()` 是会把内部整数的表示转æ¢æˆ `double`ã€‚æ³¨æ„ `int` å’Œ `unsigned` å¯ä»¥å®‰å…¨åœ°è½¬æ¢è‡³ `double`,但 `int64_t` åŠ `uint64_t` å¯èƒ½ä¼šä¸§å¤±ç²¾åº¦ï¼ˆå› ä¸º `double` 的尾数åªæœ‰ 52 ä½ï¼‰ã€‚ + +## 查询 String {#QueryString} + +除了 `GetString()`,`Value` 类也有一个 `GetStringLength()`。这里会解释个中原因。 + +æ ¹æ® RFC 4627,JSON String å¯åŒ…å« Unicode 字符 `U+0000`,在 JSON 中会表示为 `"\u0000"`。问题是,C/C++ 通常使用空字符结尾字符串(null-terminated string),这ç§å­—符串把 ``\0'` 作为结æŸç¬¦å·ã€‚ + +ä¸ºäº†ç¬¦åˆ RFC 4627,RapidJSON 支æŒåŒ…å« `U+0000` çš„ String。若你需è¦å¤„ç†è¿™äº› String,便å¯ä½¿ç”¨ `GetStringLength()` 去获得正确的字符串长度。 + +例如,当解æžä»¥ä¸‹çš„ JSON 至 `Document d` 之åŽï¼š + +~~~~~~~~~~js +{ "s" : "a\u0000b" } +~~~~~~~~~~ +`"a\u0000b"` 值的正确长度应该是 3。但 `strlen()` 会返回 1。 + +`GetStringLength()` 也å¯ä»¥æ高性能,因为用户å¯èƒ½éœ€è¦è°ƒç”¨ `strlen()` 去分é…缓冲。 + +此外,`std::string` 也支æŒè¿™ä¸ªæž„造函数: + +~~~~~~~~~~cpp +string(const char* s, size_t count); +~~~~~~~~~~ + +此构造函数接å—字符串长度作为å‚数。它支æŒåœ¨å­—符串中存储空字符,也应该会有更好的性能。 + +## 比较两个 Value + +ä½ å¯ä½¿ç”¨ `==` åŠ `!=` 去比较两个 Value。当且仅当两个 Value 的类型åŠå†…容相åŒï¼Œå®ƒä»¬æ‰å½“作相等。你也å¯ä»¥æ¯”较 Value 和它的原生类型值。以下是一个例å­ã€‚ + +~~~~~~~~~~cpp +if (document["hello"] == document["n"]) /*...*/; // 比较两个值 +if (document["hello"] == "world") /*...*/; // 与字符串字é¢é‡ä½œæ¯”较 +if (document["i"] != 123) /*...*/; // 与整数作比较 +if (document["pi"] != 3.14) /*...*/; // 与 double 作比较 +~~~~~~~~~~ + +Arrayï¼Object 顺åºä»¥å®ƒä»¬çš„元素ï¼æˆå‘˜ä½œæ¯”较。当且仅当它们的整个å­æ ‘相等,它们æ‰å½“作相等。 + +注æ„,现时若一个 Object å«æœ‰é‡å¤å‘½åçš„æˆå‘˜ï¼Œå®ƒä¸Žä»»ä½• Object 作比较都总会返回 `false`。 + +# 创建ï¼ä¿®æ”¹å€¼ {#CreateModifyValues} + +有多ç§æ–¹æ³•åŽ»åˆ›å»ºå€¼ã€‚ 当一个 DOM 树被创建或修改åŽï¼Œå¯ä½¿ç”¨ `Writer` å†æ¬¡å­˜å‚¨ä¸º JSON。 + +## æ”¹å˜ Value 类型 {#ChangeValueType} +当使用默认构造函数创建一个 Value 或 Document,它的类型便会是 Null。è¦æ”¹å˜å…¶ç±»åž‹ï¼Œéœ€è°ƒç”¨ `SetXXX()` 或赋值æ“作,例如: + +~~~~~~~~~~cpp +Document d; // Null +d.SetObject(); + +Value v; // Null +v.SetInt(10); +v = 10; // 简写,和上é¢çš„ç›¸åŒ +~~~~~~~~~~ + +### 构造函数的å„个é‡è½½ +几个类型也有é‡è½½æž„造函数: + +~~~~~~~~~~cpp +Value b(true); // 调用 Value(bool) +Value i(-123); // 调用 Value(int) +Value u(123u); // 调用 Value(unsigned) +Value d(1.5); // 调用 Value(double) +~~~~~~~~~~ + +è¦é‡å»ºç©º Object 或 Array,å¯åœ¨é»˜è®¤æž„造函数åŽä½¿ç”¨ `SetObject()`/`SetArray()`,或一次性使用 `Value(Type)`: + +~~~~~~~~~~cpp +Value o(kObjectType); +Value a(kArrayType); +~~~~~~~~~~ + +## 转移语义(Move Semantics) {#MoveSemantics} + +在设计 RapidJSON 时有一个éžå¸¸ç‰¹åˆ«çš„决定,就是 Value 赋值并ä¸æ˜¯æŠŠæ¥æº Value å¤åˆ¶è‡³ç›®çš„ Value,而是把æ¥æº Value 转移(move)至目的 Value。例如: + +~~~~~~~~~~cpp +Value a(123); +Value b(456); +b = a; // a å˜æˆ Null,b å˜æˆæ•°å­— 123。 +~~~~~~~~~~ + +![使用移动语义赋值。](diagram/move1.png) + +为什么?此语义有何优点? + +最简å•çš„答案就是性能。对于固定大å°çš„ JSON 类型(Numberã€Trueã€Falseã€Null),å¤åˆ¶å®ƒä»¬æ˜¯ç®€å•å¿«æ·ã€‚然而,对于å¯å˜å¤§å°çš„ JSON 类型(Stringã€Arrayã€Object),å¤åˆ¶å®ƒä»¬ä¼šäº§ç”Ÿå¤§é‡å¼€é”€ï¼Œè€Œä¸”这些开销常常ä¸è¢«å¯Ÿè§‰ã€‚尤其是当我们需è¦åˆ›å»ºä¸´æ—¶ Object,把它å¤åˆ¶è‡³å¦ä¸€å˜é‡ï¼Œç„¶åŽå†æžæž„它。 + +例如,若使用正常 * å¤åˆ¶ * 语义: + +~~~~~~~~~~cpp +Value o(kObjectType); +{ + Value contacts(kArrayType); + // 把元素加进 contacts 数组。 + // ... + o.AddMember("contacts", contacts, d.GetAllocator()); // 深度å¤åˆ¶ contacts (å¯èƒ½æœ‰å¤§é‡å†…存分é…) + // æžæž„ contacts。 +} +~~~~~~~~~~ + +![å¤åˆ¶è¯­ä¹‰äº§ç”Ÿå¤§é‡çš„å¤åˆ¶æ“作。](diagram/move2.png) + +那个 `o` Object 需è¦åˆ†é…一个和 contacts 相åŒå¤§å°çš„缓冲区,对 conacts åšæ·±åº¦å¤åˆ¶ï¼Œå¹¶æœ€ç»ˆè¦æžæž„ contacts。这样会产生大é‡æ— å¿…è¦çš„内存分é…ï¼é‡Šæ”¾ï¼Œä»¥åŠå†…å­˜å¤åˆ¶ã€‚ + +有一些方案å¯é¿å…实质地å¤åˆ¶è¿™äº›æ•°æ®ï¼Œä¾‹å¦‚引用计数(reference counting)ã€åžƒåœ¾å›žæ”¶ï¼ˆgarbage collection, GC)。 + +为了使 RapidJSON 简å•åŠå¿«é€Ÿï¼Œæˆ‘们选择了对赋值采用 * 转移 * 语义。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有æƒã€‚转移快得多简å•å¾—多,åªéœ€è¦æžæž„原æ¥çš„ Value,把æ¥æº `memcpy()` 至目标,最åŽæŠŠæ¥æºè®¾ç½®ä¸º Null 类型。 + +因此,使用转移语义åŽï¼Œä¸Šé¢çš„例å­å˜æˆï¼š + +~~~~~~~~~~cpp +Value o(kObjectType); +{ + Value contacts(kArrayType); + // adding elements to contacts array. + o.AddMember("contacts", contacts, d.GetAllocator()); // åªéœ€ memcpy() contacts 本身至新æˆå‘˜çš„ Value(16 字节) + // contacts 在这里å˜æˆ Null。它的æžæž„是平凡的。 +} +~~~~~~~~~~ + +![转移语义ä¸éœ€å¤åˆ¶ã€‚](diagram/move3.png) + +在 C++11 中这称为转移赋值æ“作(move assignment operator)。由于 RapidJSON æ”¯æŒ C++03,它在赋值æ“作采用转移语义,其它修改型函数如 `AddMember()`, `PushBack()` 也采用转移语义。 + +### 转移语义åŠä¸´æ—¶å€¼ {#TemporaryValues} + +有时候,我们想直接构造一个 Value 并传递给一个“转移â€å‡½æ•°ï¼ˆå¦‚ `PushBack()`ã€`AddMember()`)。由于临时对象是ä¸èƒ½è½¬æ¢ä¸ºæ­£å¸¸çš„ Value 引用,我们加入了一个方便的 `Move()` 函数: + +~~~~~~~~~~cpp +Value a(kArrayType); +Document::AllocatorType& allocator = document.GetAllocator(); +// a.PushBack(Value(42), allocator); // ä¸èƒ½é€šè¿‡ç¼–译 +a.PushBack(Value().SetInt(42), allocator); // fluent API +a.PushBack(Value(42).Move(), allocator); // å’Œä¸Šä¸€è¡Œç›¸åŒ +~~~~~~~~~~ + +## 创建 String {#CreateString} +RapidJSON æ供两个 String 的存储策略。 + +1. copy-string: 分é…缓冲区,然åŽæŠŠæ¥æºæ•°æ®å¤åˆ¶è‡³å®ƒã€‚ +2. const-string: 简å•åœ°å‚¨å­˜å­—符串的指针。 + +Copy-string 总是安全的,因为它拥有数æ®çš„克隆。Const-string å¯ç”¨äºŽå­˜å‚¨å­—符串字é¢é‡ï¼Œä»¥åŠç”¨äºŽåœ¨ DOM 一节中将会æ到的 in-situ 解æžä¸­ã€‚ + +为了让用户自定义内存分é…æ–¹å¼ï¼Œå½“一个æ“作å¯èƒ½éœ€è¦å†…存分é…时,RapidJSON è¦æ±‚用户传递一个 allocator 实例作为 API å‚数。此设计é¿å…了在æ¯ä¸ª Value 存储 allocator(或 document)的指针。 + +因此,当我们把一个 copy-string 赋值时, 调用å«æœ‰ allocator çš„ `SetString()` é‡è½½å‡½æ•°ï¼š + +~~~~~~~~~~cpp +Document document; +Value author; +char buffer[10]; +int len = sprintf(buffer, "%s %s", "Milo", "Yip"); // 动æ€åˆ›å»ºçš„字符串。 +author.SetString(buffer, len, document.GetAllocator()); +memset(buffer, 0, sizeof(buffer)); +// 清空 buffer åŽ author.GetString() ä»ç„¶åŒ…å« "Milo Yip" +~~~~~~~~~~ + +在此例å­ä¸­ï¼Œæˆ‘们使用 `Document` 实例的 allocator。这是使用 RapidJSON 时常用的惯用法。但你也å¯ä»¥ç”¨å…¶ä»– allocator 实例。 + +å¦å¤–,上é¢çš„ `SetString()` 需è¦é•¿åº¦å‚数。这个 API 能处ç†å«æœ‰ç©ºå­—符的字符串。å¦ä¸€ä¸ª `SetString()` é‡è½½å‡½æ•°æ²¡æœ‰é•¿åº¦å‚数,它å‡è®¾è¾“入是空字符结尾的,并会调用类似 `strlen()` 的函数去获å–长度。 + +最åŽï¼Œå¯¹äºŽå­—符串字é¢é‡æˆ–有安全生命周期的字符串,å¯ä»¥ä½¿ç”¨ const-string 版本的 `SetString()`,它没有 +allocator å‚数。对于字符串字é¢é‡ï¼ˆæˆ–字符数组常é‡ï¼‰ï¼Œåªéœ€ç®€å•åœ°ä¼ é€’å­—é¢é‡ï¼Œåˆå®‰å…¨åˆé«˜æ•ˆï¼š + +~~~~~~~~~~cpp +Value s; +s.SetString("rapidjson"); // å¯åŒ…å«ç©ºå­—符,长度在编译期推导 +s = "rapidjson"; // 上行的缩写 +~~~~~~~~~~ + +对于字符指针,RapidJSON 需è¦ä½œä¸€ä¸ªæ ‡è®°ï¼Œä»£è¡¨å®ƒä¸å¤åˆ¶ä¹Ÿæ˜¯å®‰å…¨çš„。å¯ä»¥ä½¿ç”¨ `StringRef` 函数: + +~~~~~~~~~cpp +const char * cstr = getenv("USER"); +size_t cstr_len = ...; // 如果有长度 +Value s; +// s.SetString(cstr); // è¿™ä¸èƒ½é€šè¿‡ç¼–译 +s.SetString(StringRef(cstr)); // å¯ä»¥ï¼Œå‡è®¾å®ƒçš„生命周期安全,并且是以空字符结尾的 +s = StringRef(cstr); // 上行的缩写 +s.SetString(StringRef(cstr, cstr_len));// 更快,å¯å¤„ç†ç©ºå­—符 +s = StringRef(cstr, cstr_len); // 上行的缩写 + +~~~~~~~~~ + +## 修改 Array {#ModifyArray} +Array 类型的 Value æ供与 `std::vector` 相似的 API。 + +* `Clear()` +* `Reserve(SizeType, Allocator&)` +* `Value& PushBack(Value&, Allocator&)` +* `template GenericValue& PushBack(T, Allocator&)` +* `Value& PopBack()` +* `ValueIterator Erase(ConstValueIterator pos)` +* `ValueIterator Erase(ConstValueIterator first, ConstValueIterator last)` + +注æ„,`Reserve(...)` åŠ `PushBack(...)` å¯èƒ½ä¼šä¸ºæ•°ç»„元素分é…内存,所以需è¦ä¸€ä¸ª allocator。 + +以下是 `PushBack()` 的例å­ï¼š + +~~~~~~~~~~cpp +Value a(kArrayType); +Document::AllocatorType& allocator = document.GetAllocator(); + +for (int i = 5; i <= 10; i++) + a.PushBack(i, allocator); // å¯èƒ½éœ€è¦è°ƒç”¨ realloc() æ‰€ä»¥éœ€è¦ allocator + +// æµç•…接å£ï¼ˆFluent interface) +a.PushBack("Lua", allocator).PushBack("Mio", allocator); +~~~~~~~~~~ + +与 STL ä¸ä¸€æ ·çš„是,`PushBack()`/`PopBack()` 返回 Array 本身的引用。这称为æµç•…接å£ï¼ˆ_fluent interface_)。 + +如果你想在 Array 中加入一个éžå¸¸é‡å­—ç¬¦ä¸²ï¼Œæˆ–æ˜¯ä¸€ä¸ªæ²¡æœ‰è¶³å¤Ÿç”Ÿå‘½å‘¨æœŸçš„å­—ç¬¦ä¸²ï¼ˆè§ [Create String](#CreateString)),你需è¦ä½¿ç”¨ copy-string API 去创建一个 String。为了é¿å…加入中间å˜é‡ï¼Œå¯ä»¥å°±åœ°ä½¿ç”¨ä¸€ä¸ª [临时值](#TemporaryValues): + +~~~~~~~~~~cpp +// 就地 Value å‚æ•° +contact.PushBack(Value("copy", document.GetAllocator()).Move(), // copy string + document.GetAllocator()); + +// æ˜¾å¼ Value å‚æ•° +Value val("key", document.GetAllocator()); // copy string +contact.PushBack(val, document.GetAllocator()); +~~~~~~~~~~ + +## 修改 Object {#ModifyObject} +Object 是键值对的集åˆã€‚æ¯ä¸ªé”®å¿…须为 String。è¦ä¿®æ”¹ Object,方法是增加或移除æˆå‘˜ã€‚以下的 API 用æ¥å¢žåŠ æˆå‘˜ï¼š + +* `Value& AddMember(Value&, Value&, Allocator& allocator)` +* `Value& AddMember(StringRefType, Value&, Allocator&)` +* `template Value& AddMember(StringRefType, T value, Allocator&)` + +以下是一个例å­ã€‚ + +~~~~~~~~~~cpp +Value contact(kObject); +contact.AddMember("name", "Milo", document.GetAllocator()); +contact.AddMember("married", true, document.GetAllocator()); +~~~~~~~~~~ + +使用 `StringRefType` 作为 name å‚æ•°çš„é‡è½½ç‰ˆæœ¬ä¸Žå­—符串的 `SetString` 的接å£ç›¸ä¼¼ã€‚ 这些é‡è½½æ˜¯ä¸ºäº†é¿å…å¤åˆ¶ `name` 字符串,因为 JSON object 中ç»å¸¸ä¼šä½¿ç”¨å¸¸æ•°é”®å。 + +如果你需è¦ä»Žéžå¸¸æ•°å­—符串或生命周期ä¸è¶³çš„字符串创建键åï¼ˆè§ [创建 String](#CreateString)),你需è¦ä½¿ç”¨ copy-string API。为了é¿å…中间å˜é‡ï¼Œå¯ä»¥å°±åœ°ä½¿ç”¨ [临时值](#TemporaryValues): + +~~~~~~~~~~cpp +// 就地 Value å‚æ•° +contact.AddMember(Value("copy", document.GetAllocator()).Move(), // copy string + Value().Move(), // null value + document.GetAllocator()); + +// 显å¼å‚æ•° +Value key("key", document.GetAllocator()); // copy string name +Value val(42); // æŸ Value +contact.AddMember(key, val, document.GetAllocator()); +~~~~~~~~~~ + +移除æˆå‘˜æœ‰å‡ ä¸ªé€‰æ‹©ï¼š + +* `bool RemoveMember(const Ch* name)`:使用键åæ¥ç§»é™¤æˆå‘˜ï¼ˆçº¿æ€§æ—¶é—´å¤æ‚度)。 +* `bool RemoveMember(const Value& name)`:除了 `name` 是一个 Value,和上一行相åŒã€‚ +* `MemberIterator RemoveMember(MemberIterator)`:使用迭代器移除æˆå‘˜ï¼ˆ_ 常数 _ 时间å¤æ‚度)。 +* `MemberIterator EraseMember(MemberIterator)`:和上行相似但维æŒæˆå‘˜æ¬¡åºï¼ˆçº¿æ€§æ—¶é—´å¤æ‚度)。 +* `MemberIterator EraseMember(MemberIterator first, MemberIterator last)`:移除一个范围内的æˆå‘˜ï¼Œç»´æŒæ¬¡åºï¼ˆçº¿æ€§æ—¶é—´å¤æ‚度)。 + +`MemberIterator RemoveMember(MemberIterator)` 使用了“转移最åŽâ€æ‰‹æ³•æ¥è¾¾æˆå¸¸æ•°æ—¶é—´å¤æ‚度。基本上就是æžæž„迭代器ä½ç½®çš„æˆå‘˜ï¼Œç„¶åŽæŠŠæœ€åŽçš„æˆå‘˜è½¬ç§»è‡³è¿­ä»£å™¨ä½ç½®ã€‚因此,æˆå‘˜çš„次åºä¼šè¢«æ”¹å˜ã€‚ + +## æ·±å¤åˆ¶ Value {#DeepCopyValue} +若我们真的è¦å¤åˆ¶ä¸€ä¸ª DOM 树,我们å¯ä½¿ç”¨ä¸¤ä¸ª APIs 作深å¤åˆ¶ï¼šå« allocator çš„æž„é€ å‡½æ•°åŠ `CopyFrom()`。 + +~~~~~~~~~~cpp +Document d; +Document::AllocatorType& a = d.GetAllocator(); +Value v1("foo"); +// Value v2(v1); // ä¸å®¹è®¸ + +Value v2(v1, a); // 制造一个克隆 +assert(v1.IsString()); // v1 ä¸å˜ +d.SetArray().PushBack(v1, a).PushBack(v2, a); +assert(v1.IsNull() && v2.IsNull()); // 两个都转移动 d + +v2.CopyFrom(d, a); // 把整个 document å¤åˆ¶è‡³ v2 +assert(d.IsArray() && d.Size() == 2); // d ä¸å˜ +v1.SetObject().AddMember("array", v2, a); +d.PushBack(v1, a); +~~~~~~~~~~ + +## äº¤æ¢ Value {#SwapValues} + +RapidJSON 也æä¾› `Swap()`。 + +~~~~~~~~~~cpp +Value a(123); +Value b("Hello"); +a.Swap(b); +assert(a.IsString()); +assert(b.IsInt()); +~~~~~~~~~~ + +无论两棵 DOM 树有多å¤æ‚,交æ¢æ˜¯å¾ˆå¿«çš„(常数时间)。 + +# 下一部分 {#WhatsNext} + +本教程展示了如何询查åŠä¿®æ”¹ DOM 树。RapidJSON 还有一个é‡è¦æ¦‚念: + +1. [æµ](doc/stream.zh-cn.md) 是读写 JSON 的通é“。æµå¯ä»¥æ˜¯å†…存字符串ã€æ–‡ä»¶æµç­‰ã€‚用户也å¯ä»¥è‡ªå®šä¹‰æµã€‚ +2. [ç¼–ç ](doc/encoding.zh-cn.md) 定义在æµæˆ–内存中使用的字符编ç ã€‚RapidJSON 也在内部æä¾› Unicode 转æ¢åŠæ ¡éªŒåŠŸèƒ½ã€‚ +3. [DOM](doc/dom.zh-cn.md) 的基本功能已在本教程里介ç»ã€‚还有更高级的功能,如原ä½ï¼ˆ*in situ*)解æžã€å…¶ä»–解æžé€‰é¡¹åŠé«˜çº§ç”¨æ³•ã€‚ +4. [SAX](doc/sax.zh-cn.md) 是 RapidJSON 解æžï¼ç”ŸæˆåŠŸèƒ½çš„基础。学习使用 `Reader`/`Writer` 去实现更高性能的应用程åºã€‚也å¯ä»¥ä½¿ç”¨ `PrettyWriter` 去格å¼åŒ– JSON。 +5. [性能](doc/performance.zh-cn.md) 展示一些我们åšçš„åŠç¬¬ä¸‰æ–¹çš„性能测试。 +6. [技术内幕](doc/internals.md) 讲述一些 RapidJSON 内部的设计åŠæŠ€æœ¯ã€‚ + +你也å¯ä»¥å‚考 [常è§é—®é¢˜](doc/faq.zh-cn.md)ã€API 文档ã€ä¾‹å­åŠå•å…ƒæµ‹è¯•ã€‚ diff --git a/deps/rapidjson/docker/debian/Dockerfile b/deps/rapidjson/docker/debian/Dockerfile new file mode 100644 index 0000000..76f0235 --- /dev/null +++ b/deps/rapidjson/docker/debian/Dockerfile @@ -0,0 +1,8 @@ +# BUILD: docker build -t rapidjson-debian . +# RUN: docker run -it -v "$PWD"/../..:/rapidjson rapidjson-debian + +FROM debian:jessie + +RUN apt-get update && apt-get install -y g++ cmake doxygen valgrind + +ENTRYPOINT ["/bin/bash"] diff --git a/deps/rapidjson/example/CMakeLists.txt b/deps/rapidjson/example/CMakeLists.txt new file mode 100644 index 0000000..9f53c9a --- /dev/null +++ b/deps/rapidjson/example/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 2.8) + +if(POLICY CMP0054) + cmake_policy(SET CMP0054 NEW) +endif() + +set(EXAMPLES + capitalize + condense + filterkey + filterkeydom + jsonx + lookaheadparser + messagereader + parsebyparts + pretty + prettyauto + schemavalidator + serialize + simpledom + simplereader + simplepullreader + simplewriter + sortkeys + tutorial) + +include_directories("../include/") + +add_definitions(-D__STDC_FORMAT_MACROS) +set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS}) + +if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") +endif() + +add_executable(archivertest archiver/archiver.cpp archiver/archivertest.cpp) + +foreach (example ${EXAMPLES}) + add_executable(${example} ${example}/${example}.cpp) +endforeach() + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + target_link_libraries(parsebyparts pthread) +endif() + +add_custom_target(examples ALL DEPENDS ${EXAMPLES}) diff --git a/deps/rapidjson/example/archiver/archiver.cpp b/deps/rapidjson/example/archiver/archiver.cpp new file mode 100644 index 0000000..59ae4c4 --- /dev/null +++ b/deps/rapidjson/example/archiver/archiver.cpp @@ -0,0 +1,292 @@ +#include "archiver.h" +#include +#include +#include "rapidjson/document.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/stringbuffer.h" + +using namespace rapidjson; + +struct JsonReaderStackItem { + enum State { + BeforeStart, //!< An object/array is in the stack but it is not yet called by StartObject()/StartArray(). + Started, //!< An object/array is called by StartObject()/StartArray(). + Closed //!< An array is closed after read all element, but before EndArray(). + }; + + JsonReaderStackItem(const Value* value, State state) : value(value), state(state), index() {} + + const Value* value; + State state; + SizeType index; // For array iteration +}; + +typedef std::stack JsonReaderStack; + +#define DOCUMENT reinterpret_cast(mDocument) +#define STACK (reinterpret_cast(mStack)) +#define TOP (STACK->top()) +#define CURRENT (*TOP.value) + +JsonReader::JsonReader(const char* json) : mDocument(), mStack(), mError(false) { + mDocument = new Document; + DOCUMENT->Parse(json); + if (DOCUMENT->HasParseError()) + mError = true; + else { + mStack = new JsonReaderStack; + STACK->push(JsonReaderStackItem(DOCUMENT, JsonReaderStackItem::BeforeStart)); + } +} + +JsonReader::~JsonReader() { + delete DOCUMENT; + delete STACK; +} + +// Archive concept +JsonReader& JsonReader::StartObject() { + if (!mError) { + if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::BeforeStart) + TOP.state = JsonReaderStackItem::Started; + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::EndObject() { + if (!mError) { + if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) + Next(); + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::Member(const char* name) { + if (!mError) { + if (CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) { + Value::ConstMemberIterator memberItr = CURRENT.FindMember(name); + if (memberItr != CURRENT.MemberEnd()) + STACK->push(JsonReaderStackItem(&memberItr->value, JsonReaderStackItem::BeforeStart)); + else + mError = true; + } + else + mError = true; + } + return *this; +} + +bool JsonReader::HasMember(const char* name) const { + if (!mError && CURRENT.IsObject() && TOP.state == JsonReaderStackItem::Started) + return CURRENT.HasMember(name); + return false; +} + +JsonReader& JsonReader::StartArray(size_t* size) { + if (!mError) { + if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::BeforeStart) { + TOP.state = JsonReaderStackItem::Started; + if (size) + *size = CURRENT.Size(); + + if (!CURRENT.Empty()) { + const Value* value = &CURRENT[TOP.index]; + STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart)); + } + else + TOP.state = JsonReaderStackItem::Closed; + } + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::EndArray() { + if (!mError) { + if (CURRENT.IsArray() && TOP.state == JsonReaderStackItem::Closed) + Next(); + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::operator&(bool& b) { + if (!mError) { + if (CURRENT.IsBool()) { + b = CURRENT.GetBool(); + Next(); + } + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::operator&(unsigned& u) { + if (!mError) { + if (CURRENT.IsUint()) { + u = CURRENT.GetUint(); + Next(); + } + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::operator&(int& i) { + if (!mError) { + if (CURRENT.IsInt()) { + i = CURRENT.GetInt(); + Next(); + } + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::operator&(double& d) { + if (!mError) { + if (CURRENT.IsNumber()) { + d = CURRENT.GetDouble(); + Next(); + } + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::operator&(std::string& s) { + if (!mError) { + if (CURRENT.IsString()) { + s = CURRENT.GetString(); + Next(); + } + else + mError = true; + } + return *this; +} + +JsonReader& JsonReader::SetNull() { + // This function is for JsonWriter only. + mError = true; + return *this; +} + +void JsonReader::Next() { + if (!mError) { + assert(!STACK->empty()); + STACK->pop(); + + if (!STACK->empty() && CURRENT.IsArray()) { + if (TOP.state == JsonReaderStackItem::Started) { // Otherwise means reading array item pass end + if (TOP.index < CURRENT.Size() - 1) { + const Value* value = &CURRENT[++TOP.index]; + STACK->push(JsonReaderStackItem(value, JsonReaderStackItem::BeforeStart)); + } + else + TOP.state = JsonReaderStackItem::Closed; + } + else + mError = true; + } + } +} + +#undef DOCUMENT +#undef STACK +#undef TOP +#undef CURRENT + +//////////////////////////////////////////////////////////////////////////////// +// JsonWriter + +#define WRITER reinterpret_cast*>(mWriter) +#define STREAM reinterpret_cast(mStream) + +JsonWriter::JsonWriter() : mWriter(), mStream() { + mStream = new StringBuffer; + mWriter = new PrettyWriter(*STREAM); +} + +JsonWriter::~JsonWriter() { + delete WRITER; + delete STREAM; +} + +const char* JsonWriter::GetString() const { + return STREAM->GetString(); +} + +JsonWriter& JsonWriter::StartObject() { + WRITER->StartObject(); + return *this; +} + +JsonWriter& JsonWriter::EndObject() { + WRITER->EndObject(); + return *this; +} + +JsonWriter& JsonWriter::Member(const char* name) { + WRITER->String(name, static_cast(strlen(name))); + return *this; +} + +bool JsonWriter::HasMember(const char*) const { + // This function is for JsonReader only. + assert(false); + return false; +} + +JsonWriter& JsonWriter::StartArray(size_t*) { + WRITER->StartArray(); + return *this; +} + +JsonWriter& JsonWriter::EndArray() { + WRITER->EndArray(); + return *this; +} + +JsonWriter& JsonWriter::operator&(bool& b) { + WRITER->Bool(b); + return *this; +} + +JsonWriter& JsonWriter::operator&(unsigned& u) { + WRITER->Uint(u); + return *this; +} + +JsonWriter& JsonWriter::operator&(int& i) { + WRITER->Int(i); + return *this; +} + +JsonWriter& JsonWriter::operator&(double& d) { + WRITER->Double(d); + return *this; +} + +JsonWriter& JsonWriter::operator&(std::string& s) { + WRITER->String(s.c_str(), static_cast(s.size())); + return *this; +} + +JsonWriter& JsonWriter::SetNull() { + WRITER->Null(); + return *this; +} + +#undef STREAM +#undef WRITER diff --git a/deps/rapidjson/example/archiver/archiver.h b/deps/rapidjson/example/archiver/archiver.h new file mode 100644 index 0000000..285ca73 --- /dev/null +++ b/deps/rapidjson/example/archiver/archiver.h @@ -0,0 +1,145 @@ +#ifndef ARCHIVER_H_ +#define ARCHIVER_H_ + +#include +#include + +/** +\class Archiver +\brief Archiver concept + +Archiver can be a reader or writer for serialization or deserialization respectively. + +class Archiver { +public: + /// \returns true if the archiver is in normal state. false if it has errors. + operator bool() const; + + /// Starts an object + Archiver& StartObject(); + + /// After calling StartObject(), assign a member with a name + Archiver& Member(const char* name); + + /// After calling StartObject(), check if a member presents + bool HasMember(const char* name) const; + + /// Ends an object + Archiver& EndObject(); + + /// Starts an array + /// \param size If Archiver::IsReader is true, the size of array is written. + Archiver& StartArray(size_t* size = 0); + + /// Ends an array + Archiver& EndArray(); + + /// Read/Write primitive types. + Archiver& operator&(bool& b); + Archiver& operator&(unsigned& u); + Archiver& operator&(int& i); + Archiver& operator&(double& d); + Archiver& operator&(std::string& s); + + /// Write primitive types. + Archiver& SetNull(); + + //! Whether it is a reader. + static const bool IsReader; + + //! Whether it is a writer. + static const bool IsWriter; +}; +*/ + +/// Represents a JSON reader which implements Archiver concept. +class JsonReader { +public: + /// Constructor. + /** + \param json A non-const source json string for in-situ parsing. + \note in-situ means the source JSON string will be modified after parsing. + */ + JsonReader(const char* json); + + /// Destructor. + ~JsonReader(); + + // Archive concept + + operator bool() const { return !mError; } + + JsonReader& StartObject(); + JsonReader& Member(const char* name); + bool HasMember(const char* name) const; + JsonReader& EndObject(); + + JsonReader& StartArray(size_t* size = 0); + JsonReader& EndArray(); + + JsonReader& operator&(bool& b); + JsonReader& operator&(unsigned& u); + JsonReader& operator&(int& i); + JsonReader& operator&(double& d); + JsonReader& operator&(std::string& s); + + JsonReader& SetNull(); + + static const bool IsReader = true; + static const bool IsWriter = !IsReader; + +private: + JsonReader(const JsonReader&); + JsonReader& operator=(const JsonReader&); + + void Next(); + + // PIMPL + void* mDocument; ///< DOM result of parsing. + void* mStack; ///< Stack for iterating the DOM + bool mError; ///< Whether an error has occurred. +}; + +class JsonWriter { +public: + /// Constructor. + JsonWriter(); + + /// Destructor. + ~JsonWriter(); + + /// Obtains the serialized JSON string. + const char* GetString() const; + + // Archive concept + + operator bool() const { return true; } + + JsonWriter& StartObject(); + JsonWriter& Member(const char* name); + bool HasMember(const char* name) const; + JsonWriter& EndObject(); + + JsonWriter& StartArray(size_t* size = 0); + JsonWriter& EndArray(); + + JsonWriter& operator&(bool& b); + JsonWriter& operator&(unsigned& u); + JsonWriter& operator&(int& i); + JsonWriter& operator&(double& d); + JsonWriter& operator&(std::string& s); + JsonWriter& SetNull(); + + static const bool IsReader = false; + static const bool IsWriter = !IsReader; + +private: + JsonWriter(const JsonWriter&); + JsonWriter& operator=(const JsonWriter&); + + // PIMPL idiom + void* mWriter; ///< JSON writer. + void* mStream; ///< Stream buffer. +}; + +#endif // ARCHIVER_H__ diff --git a/deps/rapidjson/example/archiver/archivertest.cpp b/deps/rapidjson/example/archiver/archivertest.cpp new file mode 100644 index 0000000..417a421 --- /dev/null +++ b/deps/rapidjson/example/archiver/archivertest.cpp @@ -0,0 +1,287 @@ +#include "archiver.h" +#include +#include + +////////////////////////////////////////////////////////////////////////////// +// Test1: simple object + +struct Student { + Student() : name(), age(), height(), canSwim() {} + Student(const std::string name, unsigned age, double height, bool canSwim) : + name(name), age(age), height(height), canSwim(canSwim) + {} + + std::string name; + unsigned age; + double height; + bool canSwim; +}; + +template +Archiver& operator&(Archiver& ar, Student& s) { + ar.StartObject(); + ar.Member("name") & s.name; + ar.Member("age") & s.age; + ar.Member("height") & s.height; + ar.Member("canSwim") & s.canSwim; + return ar.EndObject(); +} + +std::ostream& operator<<(std::ostream& os, const Student& s) { + return os << s.name << " " << s.age << " " << s.height << " " << s.canSwim; +} + +void test1() { + std::string json; + + // Serialize + { + Student s("Lua", 9, 150.5, true); + + JsonWriter writer; + writer & s; + json = writer.GetString(); + std::cout << json << std::endl; + } + + // Deserialize + { + Student s; + JsonReader reader(json.c_str()); + reader & s; + std::cout << s << std::endl; + } +} + +////////////////////////////////////////////////////////////////////////////// +// Test2: std::vector <=> JSON array +// +// You can map a JSON array to other data structures as well + +struct Group { + Group() : groupName(), students() {} + std::string groupName; + std::vector students; +}; + +template +Archiver& operator&(Archiver& ar, Group& g) { + ar.StartObject(); + + ar.Member("groupName"); + ar & g.groupName; + + ar.Member("students"); + size_t studentCount = g.students.size(); + ar.StartArray(&studentCount); + if (ar.IsReader) + g.students.resize(studentCount); + for (size_t i = 0; i < studentCount; i++) + ar & g.students[i]; + ar.EndArray(); + + return ar.EndObject(); +} + +std::ostream& operator<<(std::ostream& os, const Group& g) { + os << g.groupName << std::endl; + for (std::vector::const_iterator itr = g.students.begin(); itr != g.students.end(); ++itr) + os << *itr << std::endl; + return os; +} + +void test2() { + std::string json; + + // Serialize + { + Group g; + g.groupName = "Rainbow"; + + Student s1("Lua", 9, 150.5, true); + Student s2("Mio", 7, 120.0, false); + g.students.push_back(s1); + g.students.push_back(s2); + + JsonWriter writer; + writer & g; + json = writer.GetString(); + std::cout << json << std::endl; + } + + // Deserialize + { + Group g; + JsonReader reader(json.c_str()); + reader & g; + std::cout << g << std::endl; + } +} + +////////////////////////////////////////////////////////////////////////////// +// Test3: polymorphism & friend +// +// Note that friendship is not necessary but make things simpler. + +class Shape { +public: + virtual ~Shape() {} + virtual const char* GetType() const = 0; + virtual void Print(std::ostream& os) const = 0; + +protected: + Shape() : x_(), y_() {} + Shape(double x, double y) : x_(x), y_(y) {} + + template + friend Archiver& operator&(Archiver& ar, Shape& s); + + double x_, y_; +}; + +template +Archiver& operator&(Archiver& ar, Shape& s) { + ar.Member("x") & s.x_; + ar.Member("y") & s.y_; + return ar; +} + +class Circle : public Shape { +public: + Circle() : radius_() {} + Circle(double x, double y, double radius) : Shape(x, y), radius_(radius) {} + ~Circle() {} + + const char* GetType() const { return "Circle"; } + + void Print(std::ostream& os) const { + os << "Circle (" << x_ << ", " << y_ << ")" << " radius = " << radius_; + } + +private: + template + friend Archiver& operator&(Archiver& ar, Circle& c); + + double radius_; +}; + +template +Archiver& operator&(Archiver& ar, Circle& c) { + ar & static_cast(c); + ar.Member("radius") & c.radius_; + return ar; +} + +class Box : public Shape { +public: + Box() : width_(), height_() {} + Box(double x, double y, double width, double height) : Shape(x, y), width_(width), height_(height) {} + ~Box() {} + + const char* GetType() const { return "Box"; } + + void Print(std::ostream& os) const { + os << "Box (" << x_ << ", " << y_ << ")" << " width = " << width_ << " height = " << height_; + } + +private: + template + friend Archiver& operator&(Archiver& ar, Box& b); + + double width_, height_; +}; + +template +Archiver& operator&(Archiver& ar, Box& b) { + ar & static_cast(b); + ar.Member("width") & b.width_; + ar.Member("height") & b.height_; + return ar; +} + +class Canvas { +public: + Canvas() : shapes_() {} + ~Canvas() { Clear(); } + + void Clear() { + for (std::vector::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) + delete *itr; + } + + void AddShape(Shape* shape) { shapes_.push_back(shape); } + + void Print(std::ostream& os) { + for (std::vector::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) { + (*itr)->Print(os); + std::cout << std::endl; + } + } + +private: + template + friend Archiver& operator&(Archiver& ar, Canvas& c); + + std::vector shapes_; +}; + +template +Archiver& operator&(Archiver& ar, Shape*& shape) { + std::string type = ar.IsReader ? "" : shape->GetType(); + ar.StartObject(); + ar.Member("type") & type; + if (type == "Circle") { + if (ar.IsReader) shape = new Circle; + ar & static_cast(*shape); + } + else if (type == "Box") { + if (ar.IsReader) shape = new Box; + ar & static_cast(*shape); + } + return ar.EndObject(); +} + +template +Archiver& operator&(Archiver& ar, Canvas& c) { + size_t shapeCount = c.shapes_.size(); + ar.StartArray(&shapeCount); + if (ar.IsReader) { + c.Clear(); + c.shapes_.resize(shapeCount); + } + for (size_t i = 0; i < shapeCount; i++) + ar & c.shapes_[i]; + return ar.EndArray(); +} + +void test3() { + std::string json; + + // Serialize + { + Canvas c; + c.AddShape(new Circle(1.0, 2.0, 3.0)); + c.AddShape(new Box(4.0, 5.0, 6.0, 7.0)); + + JsonWriter writer; + writer & c; + json = writer.GetString(); + std::cout << json << std::endl; + } + + // Deserialize + { + Canvas c; + JsonReader reader(json.c_str()); + reader & c; + c.Print(std::cout); + } +} + +////////////////////////////////////////////////////////////////////////////// + +int main() { + test1(); + test2(); + test3(); +} diff --git a/deps/rapidjson/example/capitalize/capitalize.cpp b/deps/rapidjson/example/capitalize/capitalize.cpp new file mode 100644 index 0000000..7da37e9 --- /dev/null +++ b/deps/rapidjson/example/capitalize/capitalize.cpp @@ -0,0 +1,67 @@ +// JSON condenser example + +// This example parses JSON from stdin with validation, +// and re-output the JSON content to stdout with all string capitalized, and without whitespace. + +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" +#include +#include + +using namespace rapidjson; + +template +struct CapitalizeFilter { + CapitalizeFilter(OutputHandler& out) : out_(out), buffer_() {} + + bool Null() { return out_.Null(); } + bool Bool(bool b) { return out_.Bool(b); } + bool Int(int i) { return out_.Int(i); } + bool Uint(unsigned u) { return out_.Uint(u); } + bool Int64(int64_t i) { return out_.Int64(i); } + bool Uint64(uint64_t u) { return out_.Uint64(u); } + bool Double(double d) { return out_.Double(d); } + bool RawNumber(const char* str, SizeType length, bool copy) { return out_.RawNumber(str, length, copy); } + bool String(const char* str, SizeType length, bool) { + buffer_.clear(); + for (SizeType i = 0; i < length; i++) + buffer_.push_back(static_cast(std::toupper(str[i]))); + return out_.String(&buffer_.front(), length, true); // true = output handler need to copy the string + } + bool StartObject() { return out_.StartObject(); } + bool Key(const char* str, SizeType length, bool copy) { return String(str, length, copy); } + bool EndObject(SizeType memberCount) { return out_.EndObject(memberCount); } + bool StartArray() { return out_.StartArray(); } + bool EndArray(SizeType elementCount) { return out_.EndArray(elementCount); } + + OutputHandler& out_; + std::vector buffer_; + +private: + CapitalizeFilter(const CapitalizeFilter&); + CapitalizeFilter& operator=(const CapitalizeFilter&); +}; + +int main(int, char*[]) { + // Prepare JSON reader and input stream. + Reader reader; + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare JSON writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + Writer writer(os); + + // JSON reader parse from the input stream and let writer generate the output. + CapitalizeFilter > filter(writer); + if (!reader.Parse(is, filter)) { + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} diff --git a/deps/rapidjson/example/condense/condense.cpp b/deps/rapidjson/example/condense/condense.cpp new file mode 100644 index 0000000..46dc350 --- /dev/null +++ b/deps/rapidjson/example/condense/condense.cpp @@ -0,0 +1,32 @@ +// JSON condenser example + +// This example parses JSON text from stdin with validation, +// and re-output the JSON content to stdout without whitespace. + +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" + +using namespace rapidjson; + +int main(int, char*[]) { + // Prepare JSON reader and input stream. + Reader reader; + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare JSON writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + Writer writer(os); + + // JSON reader parse from the input stream and let writer generate the output. + if (!reader.Parse(is, writer)) { + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} diff --git a/deps/rapidjson/example/filterkey/filterkey.cpp b/deps/rapidjson/example/filterkey/filterkey.cpp new file mode 100644 index 0000000..c34a050 --- /dev/null +++ b/deps/rapidjson/example/filterkey/filterkey.cpp @@ -0,0 +1,135 @@ +// JSON filterkey example with SAX-style API. + +// This example parses JSON text from stdin with validation. +// During parsing, specified key will be filtered using a SAX handler. +// It re-output the JSON content to stdout without whitespace. + +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" +#include + +using namespace rapidjson; + +// This handler forwards event into an output handler, with filtering the descendent events of specified key. +template +class FilterKeyHandler { +public: + typedef char Ch; + + FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) : + outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_() + {} + + bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); } + bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); } + bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); } + bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); } + bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); } + bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); } + bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); } + bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); } + bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); } + + bool StartObject() { + if (filterValueDepth_ > 0) { + filterValueDepth_++; + return true; + } + else { + filteredKeyCount_.push(0); + return outputHandler_.StartObject(); + } + } + + bool Key(const Ch* str, SizeType len, bool copy) { + if (filterValueDepth_ > 0) + return true; + else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) { + filterValueDepth_ = 1; + return true; + } + else { + ++filteredKeyCount_.top(); + return outputHandler_.Key(str, len, copy); + } + } + + bool EndObject(SizeType) { + if (filterValueDepth_ > 0) { + filterValueDepth_--; + return EndValue(); + } + else { + // Use our own filtered memberCount + SizeType memberCount = filteredKeyCount_.top(); + filteredKeyCount_.pop(); + return outputHandler_.EndObject(memberCount) && EndValue(); + } + } + + bool StartArray() { + if (filterValueDepth_ > 0) { + filterValueDepth_++; + return true; + } + else + return outputHandler_.StartArray(); + } + + bool EndArray(SizeType elementCount) { + if (filterValueDepth_ > 0) { + filterValueDepth_--; + return EndValue(); + } + else + return outputHandler_.EndArray(elementCount) && EndValue(); + } + +private: + FilterKeyHandler(const FilterKeyHandler&); + FilterKeyHandler& operator=(const FilterKeyHandler&); + + bool EndValue() { + if (filterValueDepth_ == 1) // Just at the end of value after filtered key + filterValueDepth_ = 0; + return true; + } + + OutputHandler& outputHandler_; + const char* keyString_; + const SizeType keyLength_; + unsigned filterValueDepth_; + std::stack filteredKeyCount_; +}; + +int main(int argc, char* argv[]) { + if (argc != 2) { + fprintf(stderr, "filterkey key < input.json > output.json\n"); + return 1; + } + + // Prepare JSON reader and input stream. + Reader reader; + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare JSON writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + Writer writer(os); + + // Prepare Filter + FilterKeyHandler > filter(writer, argv[1], static_cast(strlen(argv[1]))); + + // JSON reader parse from the input stream, filter handler filters the events, and forward to writer. + // i.e. the events flow is: reader -> filter -> writer + if (!reader.Parse(is, filter)) { + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} diff --git a/deps/rapidjson/example/filterkeydom/filterkeydom.cpp b/deps/rapidjson/example/filterkeydom/filterkeydom.cpp new file mode 100644 index 0000000..732cc81 --- /dev/null +++ b/deps/rapidjson/example/filterkeydom/filterkeydom.cpp @@ -0,0 +1,170 @@ +// JSON filterkey example which populates filtered SAX events into a Document. + +// This example parses JSON text from stdin with validation. +// During parsing, specified key will be filtered using a SAX handler. +// And finally the filtered events are used to populate a Document. +// As an example, the document is written to standard output. + +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" +#include + +using namespace rapidjson; + +// This handler forwards event into an output handler, with filtering the descendent events of specified key. +template +class FilterKeyHandler { +public: + typedef char Ch; + + FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) : + outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_() + {} + + bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); } + bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); } + bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); } + bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); } + bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); } + bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); } + bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); } + bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); } + bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); } + + bool StartObject() { + if (filterValueDepth_ > 0) { + filterValueDepth_++; + return true; + } + else { + filteredKeyCount_.push(0); + return outputHandler_.StartObject(); + } + } + + bool Key(const Ch* str, SizeType len, bool copy) { + if (filterValueDepth_ > 0) + return true; + else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) { + filterValueDepth_ = 1; + return true; + } + else { + ++filteredKeyCount_.top(); + return outputHandler_.Key(str, len, copy); + } + } + + bool EndObject(SizeType) { + if (filterValueDepth_ > 0) { + filterValueDepth_--; + return EndValue(); + } + else { + // Use our own filtered memberCount + SizeType memberCount = filteredKeyCount_.top(); + filteredKeyCount_.pop(); + return outputHandler_.EndObject(memberCount) && EndValue(); + } + } + + bool StartArray() { + if (filterValueDepth_ > 0) { + filterValueDepth_++; + return true; + } + else + return outputHandler_.StartArray(); + } + + bool EndArray(SizeType elementCount) { + if (filterValueDepth_ > 0) { + filterValueDepth_--; + return EndValue(); + } + else + return outputHandler_.EndArray(elementCount) && EndValue(); + } + +private: + FilterKeyHandler(const FilterKeyHandler&); + FilterKeyHandler& operator=(const FilterKeyHandler&); + + bool EndValue() { + if (filterValueDepth_ == 1) // Just at the end of value after filtered key + filterValueDepth_ = 0; + return true; + } + + OutputHandler& outputHandler_; + const char* keyString_; + const SizeType keyLength_; + unsigned filterValueDepth_; + std::stack filteredKeyCount_; +}; + +// Implements a generator for Document::Populate() +template +class FilterKeyReader { +public: + typedef char Ch; + + FilterKeyReader(InputStream& is, const Ch* keyString, SizeType keyLength) : + is_(is), keyString_(keyString), keyLength_(keyLength), parseResult_() + {} + + // SAX event flow: reader -> filter -> handler + template + bool operator()(Handler& handler) { + FilterKeyHandler filter(handler, keyString_, keyLength_); + Reader reader; + parseResult_ = reader.Parse(is_, filter); + return parseResult_; + } + + const ParseResult& GetParseResult() const { return parseResult_; } + +private: + FilterKeyReader(const FilterKeyReader&); + FilterKeyReader& operator=(const FilterKeyReader&); + + InputStream& is_; + const char* keyString_; + const SizeType keyLength_; + ParseResult parseResult_; +}; + +int main(int argc, char* argv[]) { + if (argc != 2) { + fprintf(stderr, "filterkeydom key < input.json > output.json\n"); + return 1; + } + + // Prepare input stream. + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare Filter + FilterKeyReader reader(is, argv[1], static_cast(strlen(argv[1]))); + + // Populates the filtered events from reader + Document document; + document.Populate(reader); + ParseResult pr = reader.GetParseResult(); + if (!pr) { + fprintf(stderr, "\nError(%u): %s\n", static_cast(pr.Offset()), GetParseError_En(pr.Code())); + return 1; + } + + // Prepare JSON writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + Writer writer(os); + + // Write the document to standard output + document.Accept(writer); + return 0; +} diff --git a/deps/rapidjson/example/jsonx/jsonx.cpp b/deps/rapidjson/example/jsonx/jsonx.cpp new file mode 100644 index 0000000..954aa2b --- /dev/null +++ b/deps/rapidjson/example/jsonx/jsonx.cpp @@ -0,0 +1,207 @@ +// JSON to JSONx conversion example, using SAX API. +// JSONx is an IBM standard format to represent JSON as XML. +// https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html +// This example parses JSON text from stdin with validation, +// and convert to JSONx format to stdout. +// Need compile with -D__STDC_FORMAT_MACROS for defining PRId64 and PRIu64 macros. + +#include "rapidjson/reader.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" +#include + +using namespace rapidjson; + +// For simplicity, this example only read/write in UTF-8 encoding +template +class JsonxWriter { +public: + JsonxWriter(OutputStream& os) : os_(os), name_(), level_(0), hasName_(false) { + } + + bool Null() { + return WriteStartElement("null", true); + } + + bool Bool(bool b) { + return + WriteStartElement("boolean") && + WriteString(b ? "true" : "false") && + WriteEndElement("boolean"); + } + + bool Int(int i) { + char buffer[12]; + return WriteNumberElement(buffer, sprintf(buffer, "%d", i)); + } + + bool Uint(unsigned i) { + char buffer[11]; + return WriteNumberElement(buffer, sprintf(buffer, "%u", i)); + } + + bool Int64(int64_t i) { + char buffer[21]; + return WriteNumberElement(buffer, sprintf(buffer, "%" PRId64, i)); + } + + bool Uint64(uint64_t i) { + char buffer[21]; + return WriteNumberElement(buffer, sprintf(buffer, "%" PRIu64, i)); + } + + bool Double(double d) { + char buffer[30]; + return WriteNumberElement(buffer, sprintf(buffer, "%.17g", d)); + } + + bool RawNumber(const char* str, SizeType length, bool) { + return + WriteStartElement("number") && + WriteEscapedText(str, length) && + WriteEndElement("number"); + } + + bool String(const char* str, SizeType length, bool) { + return + WriteStartElement("string") && + WriteEscapedText(str, length) && + WriteEndElement("string"); + } + + bool StartObject() { + return WriteStartElement("object"); + } + + bool Key(const char* str, SizeType length, bool) { + // backup key to name_ + name_.Clear(); + for (SizeType i = 0; i < length; i++) + name_.Put(str[i]); + hasName_ = true; + return true; + } + + bool EndObject(SizeType) { + return WriteEndElement("object"); + } + + bool StartArray() { + return WriteStartElement("array"); + } + + bool EndArray(SizeType) { + return WriteEndElement("array"); + } + +private: + bool WriteString(const char* s) { + while (*s) + os_.Put(*s++); + return true; + } + + bool WriteEscapedAttributeValue(const char* s, size_t length) { + for (size_t i = 0; i < length; i++) { + switch (s[i]) { + case '&': WriteString("&"); break; + case '<': WriteString("<"); break; + case '"': WriteString("""); break; + default: os_.Put(s[i]); break; + } + } + return true; + } + + bool WriteEscapedText(const char* s, size_t length) { + for (size_t i = 0; i < length; i++) { + switch (s[i]) { + case '&': WriteString("&"); break; + case '<': WriteString("<"); break; + default: os_.Put(s[i]); break; + } + } + return true; + } + + bool WriteStartElement(const char* type, bool emptyElement = false) { + if (level_ == 0) + if (!WriteString("")) + return false; + + if (!WriteString(""); + else { + level_++; + return WriteString(">"); + } + } + + bool WriteEndElement(const char* type) { + if (!WriteString("")) + return false; + + // For the last end tag, flush the output stream. + if (--level_ == 0) + os_.Flush(); + + return true; + } + + bool WriteNumberElement(const char* buffer, int length) { + if (!WriteStartElement("number")) + return false; + for (int j = 0; j < length; j++) + os_.Put(buffer[j]); + return WriteEndElement("number"); + } + + OutputStream& os_; + StringBuffer name_; + unsigned level_; + bool hasName_; +}; + +int main(int, char*[]) { + // Prepare JSON reader and input stream. + Reader reader; + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare JSON writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + JsonxWriter writer(os); + + // JSON reader parse from the input stream and let writer generate the output. + if (!reader.Parse(is, writer)) { + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} diff --git a/deps/rapidjson/example/lookaheadparser/lookaheadparser.cpp b/deps/rapidjson/example/lookaheadparser/lookaheadparser.cpp new file mode 100644 index 0000000..f627f4d --- /dev/null +++ b/deps/rapidjson/example/lookaheadparser/lookaheadparser.cpp @@ -0,0 +1,350 @@ +#include "rapidjson/reader.h" +#include "rapidjson/document.h" +#include + +RAPIDJSON_DIAG_PUSH +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +#endif + +// This example demonstrates JSON token-by-token parsing with an API that is +// more direct; you don't need to design your logic around a handler object and +// callbacks. Instead, you retrieve values from the JSON stream by calling +// GetInt(), GetDouble(), GetString() and GetBool(), traverse into structures +// by calling EnterObject() and EnterArray(), and skip over unwanted data by +// calling SkipValue(). When you know your JSON's structure, this can be quite +// convenient. +// +// If you aren't sure of what's next in the JSON data, you can use PeekType() and +// PeekValue() to look ahead to the next object before reading it. +// +// If you call the wrong retrieval method--e.g. GetInt when the next JSON token is +// not an int, EnterObject or EnterArray when there isn't actually an object or array +// to read--the stream parsing will end immediately and no more data will be delivered. +// +// After calling EnterObject, you retrieve keys via NextObjectKey() and values via +// the normal getters. When NextObjectKey() returns null, you have exited the +// object, or you can call SkipObject() to skip to the end of the object +// immediately. If you fetch the entire object (i.e. NextObjectKey() returned null), +// you should not call SkipObject(). +// +// After calling EnterArray(), you must alternate between calling NextArrayValue() +// to see if the array has more data, and then retrieving values via the normal +// getters. You can call SkipArray() to skip to the end of the array immediately. +// If you fetch the entire array (i.e. NextArrayValue() returned null), +// you should not call SkipArray(). +// +// This parser uses in-situ strings, so the JSON buffer will be altered during the +// parse. + +using namespace rapidjson; + + +class LookaheadParserHandler { +public: + bool Null() { st_ = kHasNull; v_.SetNull(); return true; } + bool Bool(bool b) { st_ = kHasBool; v_.SetBool(b); return true; } + bool Int(int i) { st_ = kHasNumber; v_.SetInt(i); return true; } + bool Uint(unsigned u) { st_ = kHasNumber; v_.SetUint(u); return true; } + bool Int64(int64_t i) { st_ = kHasNumber; v_.SetInt64(i); return true; } + bool Uint64(uint64_t u) { st_ = kHasNumber; v_.SetUint64(u); return true; } + bool Double(double d) { st_ = kHasNumber; v_.SetDouble(d); return true; } + bool RawNumber(const char*, SizeType, bool) { return false; } + bool String(const char* str, SizeType length, bool) { st_ = kHasString; v_.SetString(str, length); return true; } + bool StartObject() { st_ = kEnteringObject; return true; } + bool Key(const char* str, SizeType length, bool) { st_ = kHasKey; v_.SetString(str, length); return true; } + bool EndObject(SizeType) { st_ = kExitingObject; return true; } + bool StartArray() { st_ = kEnteringArray; return true; } + bool EndArray(SizeType) { st_ = kExitingArray; return true; } + +protected: + LookaheadParserHandler(char* str); + void ParseNext(); + +protected: + enum LookaheadParsingState { + kInit, + kError, + kHasNull, + kHasBool, + kHasNumber, + kHasString, + kHasKey, + kEnteringObject, + kExitingObject, + kEnteringArray, + kExitingArray + }; + + Value v_; + LookaheadParsingState st_; + Reader r_; + InsituStringStream ss_; + + static const int parseFlags = kParseDefaultFlags | kParseInsituFlag; +}; + +LookaheadParserHandler::LookaheadParserHandler(char* str) : v_(), st_(kInit), r_(), ss_(str) { + r_.IterativeParseInit(); + ParseNext(); +} + +void LookaheadParserHandler::ParseNext() { + if (r_.HasParseError()) { + st_ = kError; + return; + } + + r_.IterativeParseNext(ss_, *this); +} + +class LookaheadParser : protected LookaheadParserHandler { +public: + LookaheadParser(char* str) : LookaheadParserHandler(str) {} + + bool EnterObject(); + bool EnterArray(); + const char* NextObjectKey(); + bool NextArrayValue(); + int GetInt(); + double GetDouble(); + const char* GetString(); + bool GetBool(); + void GetNull(); + + void SkipObject(); + void SkipArray(); + void SkipValue(); + Value* PeekValue(); + int PeekType(); // returns a rapidjson::Type, or -1 for no value (at end of object/array) + + bool IsValid() { return st_ != kError; } + +protected: + void SkipOut(int depth); +}; + +bool LookaheadParser::EnterObject() { + if (st_ != kEnteringObject) { + st_ = kError; + return false; + } + + ParseNext(); + return true; +} + +bool LookaheadParser::EnterArray() { + if (st_ != kEnteringArray) { + st_ = kError; + return false; + } + + ParseNext(); + return true; +} + +const char* LookaheadParser::NextObjectKey() { + if (st_ == kHasKey) { + const char* result = v_.GetString(); + ParseNext(); + return result; + } + + if (st_ != kExitingObject) { + st_ = kError; + return 0; + } + + ParseNext(); + return 0; +} + +bool LookaheadParser::NextArrayValue() { + if (st_ == kExitingArray) { + ParseNext(); + return false; + } + + if (st_ == kError || st_ == kExitingObject || st_ == kHasKey) { + st_ = kError; + return false; + } + + return true; +} + +int LookaheadParser::GetInt() { + if (st_ != kHasNumber || !v_.IsInt()) { + st_ = kError; + return 0; + } + + int result = v_.GetInt(); + ParseNext(); + return result; +} + +double LookaheadParser::GetDouble() { + if (st_ != kHasNumber) { + st_ = kError; + return 0.; + } + + double result = v_.GetDouble(); + ParseNext(); + return result; +} + +bool LookaheadParser::GetBool() { + if (st_ != kHasBool) { + st_ = kError; + return false; + } + + bool result = v_.GetBool(); + ParseNext(); + return result; +} + +void LookaheadParser::GetNull() { + if (st_ != kHasNull) { + st_ = kError; + return; + } + + ParseNext(); +} + +const char* LookaheadParser::GetString() { + if (st_ != kHasString) { + st_ = kError; + return 0; + } + + const char* result = v_.GetString(); + ParseNext(); + return result; +} + +void LookaheadParser::SkipOut(int depth) { + do { + if (st_ == kEnteringArray || st_ == kEnteringObject) { + ++depth; + } + else if (st_ == kExitingArray || st_ == kExitingObject) { + --depth; + } + else if (st_ == kError) { + return; + } + + ParseNext(); + } + while (depth > 0); +} + +void LookaheadParser::SkipValue() { + SkipOut(0); +} + +void LookaheadParser::SkipArray() { + SkipOut(1); +} + +void LookaheadParser::SkipObject() { + SkipOut(1); +} + +Value* LookaheadParser::PeekValue() { + if (st_ >= kHasNull && st_ <= kHasKey) { + return &v_; + } + + return 0; +} + +int LookaheadParser::PeekType() { + if (st_ >= kHasNull && st_ <= kHasKey) { + return v_.GetType(); + } + + if (st_ == kEnteringArray) { + return kArrayType; + } + + if (st_ == kEnteringObject) { + return kObjectType; + } + + return -1; +} + +//------------------------------------------------------------------------- + +int main() { + using namespace std; + + char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null," + "\"i\":123, \"pi\": 3.1416, \"a\":[-1, 2, 3, 4, \"array\", []], \"skipArrays\":[1, 2, [[[3]]]], " + "\"skipObject\":{ \"i\":0, \"t\":true, \"n\":null, \"d\":123.45 }, " + "\"skipNested\":[[[[{\"\":0}, {\"\":[-9.87]}]]], [], []], " + "\"skipString\":\"zzz\", \"reachedEnd\":null, \"t\":true }"; + + LookaheadParser r(json); + + RAPIDJSON_ASSERT(r.PeekType() == kObjectType); + + r.EnterObject(); + while (const char* key = r.NextObjectKey()) { + if (0 == strcmp(key, "hello")) { + RAPIDJSON_ASSERT(r.PeekType() == kStringType); + cout << key << ":" << r.GetString() << endl; + } + else if (0 == strcmp(key, "t") || 0 == strcmp(key, "f")) { + RAPIDJSON_ASSERT(r.PeekType() == kTrueType || r.PeekType() == kFalseType); + cout << key << ":" << r.GetBool() << endl; + continue; + } + else if (0 == strcmp(key, "n")) { + RAPIDJSON_ASSERT(r.PeekType() == kNullType); + r.GetNull(); + cout << key << endl; + continue; + } + else if (0 == strcmp(key, "pi")) { + RAPIDJSON_ASSERT(r.PeekType() == kNumberType); + cout << key << ":" << r.GetDouble() << endl; + continue; + } + else if (0 == strcmp(key, "a")) { + RAPIDJSON_ASSERT(r.PeekType() == kArrayType); + + r.EnterArray(); + + cout << key << ":[ "; + while (r.NextArrayValue()) { + if (r.PeekType() == kNumberType) { + cout << r.GetDouble() << " "; + } + else if (r.PeekType() == kStringType) { + cout << r.GetString() << " "; + } + else { + r.SkipArray(); + break; + } + } + + cout << "]" << endl; + } + else { + cout << key << ":skipped" << endl; + r.SkipValue(); + } + } + + return 0; +} + +RAPIDJSON_DIAG_POP diff --git a/deps/rapidjson/example/messagereader/messagereader.cpp b/deps/rapidjson/example/messagereader/messagereader.cpp new file mode 100644 index 0000000..3399bc9 --- /dev/null +++ b/deps/rapidjson/example/messagereader/messagereader.cpp @@ -0,0 +1,105 @@ +// Reading a message JSON with Reader (SAX-style API). +// The JSON should be an object with key-string pairs. + +#include "rapidjson/reader.h" +#include "rapidjson/error/en.h" +#include +#include +#include + +using namespace std; +using namespace rapidjson; + +typedef map MessageMap; + +#if defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + +struct MessageHandler + : public BaseReaderHandler, MessageHandler> { + MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {} + + bool StartObject() { + switch (state_) { + case kExpectObjectStart: + state_ = kExpectNameOrObjectEnd; + return true; + default: + return false; + } + } + + bool String(const char* str, SizeType length, bool) { + switch (state_) { + case kExpectNameOrObjectEnd: + name_ = string(str, length); + state_ = kExpectValue; + return true; + case kExpectValue: + messages_.insert(MessageMap::value_type(name_, string(str, length))); + state_ = kExpectNameOrObjectEnd; + return true; + default: + return false; + } + } + + bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; } + + bool Default() { return false; } // All other events are invalid. + + MessageMap messages_; + enum State { + kExpectObjectStart, + kExpectNameOrObjectEnd, + kExpectValue + }state_; + std::string name_; +}; + +#if defined(__GNUC__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +static void ParseMessages(const char* json, MessageMap& messages) { + Reader reader; + MessageHandler handler; + StringStream ss(json); + if (reader.Parse(ss, handler)) + messages.swap(handler.messages_); // Only change it if success. + else { + ParseErrorCode e = reader.GetParseErrorCode(); + size_t o = reader.GetErrorOffset(); + cout << "Error: " << GetParseError_En(e) << endl;; + cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl; + } +} + +int main() { + MessageMap messages; + + const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }"; + cout << json1 << endl; + ParseMessages(json1, messages); + + for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr) + cout << itr->first << ": " << itr->second << endl; + + cout << endl << "Parse a JSON with invalid schema." << endl; + const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }"; + cout << json2 << endl; + ParseMessages(json2, messages); + + return 0; +} diff --git a/deps/rapidjson/example/parsebyparts/parsebyparts.cpp b/deps/rapidjson/example/parsebyparts/parsebyparts.cpp new file mode 100644 index 0000000..ff73539 --- /dev/null +++ b/deps/rapidjson/example/parsebyparts/parsebyparts.cpp @@ -0,0 +1,176 @@ +// Example of parsing JSON to document by parts. + +// Using C++11 threads +// Temporarily disable for clang (older version) due to incompatibility with libstdc++ +#if (__cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)) && !defined(__clang__) + +#include "rapidjson/document.h" +#include "rapidjson/error/en.h" +#include "rapidjson/writer.h" +#include "rapidjson/ostreamwrapper.h" +#include +#include +#include +#include + +using namespace rapidjson; + +template +class AsyncDocumentParser { +public: + AsyncDocumentParser(Document& d) + : stream_(*this) + , d_(d) + , parseThread_() + , mutex_() + , notEmpty_() + , finish_() + , completed_() + { + // Create and execute thread after all member variables are initialized. + parseThread_ = std::thread(&AsyncDocumentParser::Parse, this); + } + + ~AsyncDocumentParser() { + if (!parseThread_.joinable()) + return; + + { + std::unique_lock lock(mutex_); + + // Wait until the buffer is read up (or parsing is completed) + while (!stream_.Empty() && !completed_) + finish_.wait(lock); + + // Automatically append '\0' as the terminator in the stream. + static const char terminator[] = ""; + stream_.src_ = terminator; + stream_.end_ = terminator + 1; + notEmpty_.notify_one(); // unblock the AsyncStringStream + } + + parseThread_.join(); + } + + void ParsePart(const char* buffer, size_t length) { + std::unique_lock lock(mutex_); + + // Wait until the buffer is read up (or parsing is completed) + while (!stream_.Empty() && !completed_) + finish_.wait(lock); + + // Stop further parsing if the parsing process is completed. + if (completed_) + return; + + // Set the buffer to stream and unblock the AsyncStringStream + stream_.src_ = buffer; + stream_.end_ = buffer + length; + notEmpty_.notify_one(); + } + +private: + void Parse() { + d_.ParseStream(stream_); + + // The stream may not be fully read, notify finish anyway to unblock ParsePart() + std::unique_lock lock(mutex_); + completed_ = true; // Parsing process is completed + finish_.notify_one(); // Unblock ParsePart() or destructor if they are waiting. + } + + struct AsyncStringStream { + typedef char Ch; + + AsyncStringStream(AsyncDocumentParser& parser) : parser_(parser), src_(), end_(), count_() {} + + char Peek() const { + std::unique_lock lock(parser_.mutex_); + + // If nothing in stream, block to wait. + while (Empty()) + parser_.notEmpty_.wait(lock); + + return *src_; + } + + char Take() { + std::unique_lock lock(parser_.mutex_); + + // If nothing in stream, block to wait. + while (Empty()) + parser_.notEmpty_.wait(lock); + + count_++; + char c = *src_++; + + // If all stream is read up, notify that the stream is finish. + if (Empty()) + parser_.finish_.notify_one(); + + return c; + } + + size_t Tell() const { return count_; } + + // Not implemented + char* PutBegin() { return 0; } + void Put(char) {} + void Flush() {} + size_t PutEnd(char*) { return 0; } + + bool Empty() const { return src_ == end_; } + + AsyncDocumentParser& parser_; + const char* src_; //!< Current read position. + const char* end_; //!< End of buffer + size_t count_; //!< Number of characters taken so far. + }; + + AsyncStringStream stream_; + Document& d_; + std::thread parseThread_; + std::mutex mutex_; + std::condition_variable notEmpty_; + std::condition_variable finish_; + bool completed_; +}; + +int main() { + Document d; + + { + AsyncDocumentParser<> parser(d); + + const char json1[] = " { \"hello\" : \"world\", \"t\" : tr"; + //const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // For test parsing error + const char json2[] = "ue, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.14"; + const char json3[] = "16, \"a\":[1, 2, 3, 4] } "; + + parser.ParsePart(json1, sizeof(json1) - 1); + parser.ParsePart(json2, sizeof(json2) - 1); + parser.ParsePart(json3, sizeof(json3) - 1); + } + + if (d.HasParseError()) { + std::cout << "Error at offset " << d.GetErrorOffset() << ": " << GetParseError_En(d.GetParseError()) << std::endl; + return EXIT_FAILURE; + } + + // Stringify the JSON to cout + OStreamWrapper os(std::cout); + Writer writer(os); + d.Accept(writer); + std::cout << std::endl; + + return EXIT_SUCCESS; +} + +#else // Not supporting C++11 + +#include +int main() { + std::cout << "This example requires C++11 compiler" << std::endl; +} + +#endif diff --git a/deps/rapidjson/example/pretty/pretty.cpp b/deps/rapidjson/example/pretty/pretty.cpp new file mode 100644 index 0000000..2feff5d --- /dev/null +++ b/deps/rapidjson/example/pretty/pretty.cpp @@ -0,0 +1,30 @@ +// JSON pretty formatting example +// This example can only handle UTF-8. For handling other encodings, see prettyauto example. + +#include "rapidjson/reader.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/error/en.h" + +using namespace rapidjson; + +int main(int, char*[]) { + // Prepare reader and input stream. + Reader reader; + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + // Prepare writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + PrettyWriter writer(os); + + // JSON reader parse from the input stream and let writer generate the output. + if (!reader.Parse(is, writer)) { + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} diff --git a/deps/rapidjson/example/prettyauto/prettyauto.cpp b/deps/rapidjson/example/prettyauto/prettyauto.cpp new file mode 100644 index 0000000..1687bae --- /dev/null +++ b/deps/rapidjson/example/prettyauto/prettyauto.cpp @@ -0,0 +1,56 @@ +// JSON pretty formatting example +// This example can handle UTF-8/UTF-16LE/UTF-16BE/UTF-32LE/UTF-32BE. +// The input firstly convert to UTF8, and then write to the original encoding with pretty formatting. + +#include "rapidjson/reader.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/encodedstream.h" // NEW +#include "rapidjson/error/en.h" +#ifdef _WIN32 +#include +#include +#endif + +using namespace rapidjson; + +int main(int, char*[]) { +#ifdef _WIN32 + // Prevent Windows converting between CR+LF and LF + _setmode(_fileno(stdin), _O_BINARY); // NEW + _setmode(_fileno(stdout), _O_BINARY); // NEW +#endif + + // Prepare reader and input stream. + //Reader reader; + GenericReader, UTF8<> > reader; // CHANGED + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + AutoUTFInputStream eis(is); // NEW + + // Prepare writer and output stream. + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + +#if 1 + // Use the same Encoding of the input. Also use BOM according to input. + typedef AutoUTFOutputStream OutputStream; // NEW + OutputStream eos(os, eis.GetType(), eis.HasBOM()); // NEW + PrettyWriter, AutoUTF > writer(eos); // CHANGED +#else + // You may also use static bound encoding type, such as output to UTF-16LE with BOM + typedef EncodedOutputStream,FileWriteStream> OutputStream; // NEW + OutputStream eos(os, true); // NEW + PrettyWriter, UTF16LE<> > writer(eos); // CHANGED +#endif + + // JSON reader parse from the input stream and let writer generate the output. + //if (!reader.Parse(is, writer)) { + if (!reader.Parse(eis, writer)) { // CHANGED + fprintf(stderr, "\nError(%u): %s\n", static_cast(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode())); + return 1; + } + + return 0; +} diff --git a/deps/rapidjson/example/schemavalidator/schemavalidator.cpp b/deps/rapidjson/example/schemavalidator/schemavalidator.cpp new file mode 100644 index 0000000..6ce3c39 --- /dev/null +++ b/deps/rapidjson/example/schemavalidator/schemavalidator.cpp @@ -0,0 +1,199 @@ +// Schema Validator example + +// The example validates JSON text from stdin with a JSON schema specified in the argument. + +#define RAPIDJSON_HAS_STDSTRING 1 + +#include "rapidjson/error/en.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/schema.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/prettywriter.h" +#include +#include +#include + +using namespace rapidjson; + +typedef GenericValue, CrtAllocator > ValueType; + +// Forward ref +static void CreateErrorMessages(const ValueType& errors, size_t depth, const char* context); + +// Convert GenericValue to std::string +static std::string GetString(const ValueType& val) { + std::ostringstream s; + if (val.IsString()) + s << val.GetString(); + else if (val.IsDouble()) + s << val.GetDouble(); + else if (val.IsUint()) + s << val.GetUint(); + else if (val.IsInt()) + s << val.GetInt(); + else if (val.IsUint64()) + s << val.GetUint64(); + else if (val.IsInt64()) + s << val.GetInt64(); + else if (val.IsBool() && val.GetBool()) + s << "true"; + else if (val.IsBool()) + s << "false"; + else if (val.IsFloat()) + s << val.GetFloat(); + return s.str(); +} + +// Create the error message for a named error +// The error object can either be empty or contain at least member properties: +// {"errorCode": , "instanceRef": "", "schemaRef": "" } +// Additional properties may be present for use as inserts. +// An "errors" property may be present if there are child errors. +static void HandleError(const char* errorName, const ValueType& error, size_t depth, const char* context) { + if (!error.ObjectEmpty()) { + // Get error code and look up error message text (English) + int code = error["errorCode"].GetInt(); + std::string message(GetValidateError_En(static_cast(code))); + // For each member property in the error, see if its name exists as an insert in the error message and if so replace with the stringified property value + // So for example - "Number '%actual' is not a multiple of the 'multipleOf' value '%expected'." - we would expect "actual" and "expected" members. + for (ValueType::ConstMemberIterator insertsItr = error.MemberBegin(); + insertsItr != error.MemberEnd(); ++insertsItr) { + std::string insertName("%"); + insertName += insertsItr->name.GetString(); // eg "%actual" + size_t insertPos = message.find(insertName); + if (insertPos != std::string::npos) { + std::string insertString(""); + const ValueType &insert = insertsItr->value; + if (insert.IsArray()) { + // Member is an array so create comma-separated list of items for the insert string + for (ValueType::ConstValueIterator itemsItr = insert.Begin(); itemsItr != insert.End(); ++itemsItr) { + if (itemsItr != insert.Begin()) insertString += ","; + insertString += GetString(*itemsItr); + } + } else { + insertString += GetString(insert); + } + message.replace(insertPos, insertName.length(), insertString); + } + } + // Output error message, references, context + std::string indent(depth * 2, ' '); + std::cout << indent << "Error Name: " << errorName << std::endl; + std::cout << indent << "Message: " << message.c_str() << std::endl; + std::cout << indent << "Instance: " << error["instanceRef"].GetString() << std::endl; + std::cout << indent << "Schema: " << error["schemaRef"].GetString() << std::endl; + if (depth > 0) std::cout << indent << "Context: " << context << std::endl; + std::cout << std::endl; + + // If child errors exist, apply the process recursively to each error structure. + // This occurs for "oneOf", "allOf", "anyOf" and "dependencies" errors, so pass the error name as context. + if (error.HasMember("errors")) { + depth++; + const ValueType &childErrors = error["errors"]; + if (childErrors.IsArray()) { + // Array - each item is an error structure - example + // "anyOf": {"errorCode": ..., "errors":[{"pattern": {"errorCode\": ...\"}}, {"pattern": {"errorCode\": ...}}] + for (ValueType::ConstValueIterator errorsItr = childErrors.Begin(); + errorsItr != childErrors.End(); ++errorsItr) { + CreateErrorMessages(*errorsItr, depth, errorName); + } + } else if (childErrors.IsObject()) { + // Object - each member is an error structure - example + // "dependencies": {"errorCode": ..., "errors": {"address": {"required": {"errorCode": ...}}, "name": {"required": {"errorCode": ...}}} + for (ValueType::ConstMemberIterator propsItr = childErrors.MemberBegin(); + propsItr != childErrors.MemberEnd(); ++propsItr) { + CreateErrorMessages(propsItr->value, depth, errorName); + } + } + } + } +} + +// Create error message for all errors in an error structure +// Context is used to indicate whether the error structure has a parent 'dependencies', 'allOf', 'anyOf' or 'oneOf' error +static void CreateErrorMessages(const ValueType& errors, size_t depth = 0, const char* context = 0) { + // Each member property contains one or more errors of a given type + for (ValueType::ConstMemberIterator errorTypeItr = errors.MemberBegin(); errorTypeItr != errors.MemberEnd(); ++errorTypeItr) { + const char* errorName = errorTypeItr->name.GetString(); + const ValueType& errorContent = errorTypeItr->value; + if (errorContent.IsArray()) { + // Member is an array where each item is an error - eg "type": [{"errorCode": ...}, {"errorCode": ...}] + for (ValueType::ConstValueIterator contentItr = errorContent.Begin(); contentItr != errorContent.End(); ++contentItr) { + HandleError(errorName, *contentItr, depth, context); + } + } else if (errorContent.IsObject()) { + // Member is an object which is a single error - eg "type": {"errorCode": ... } + HandleError(errorName, errorContent, depth, context); + } + } +} + +int main(int argc, char *argv[]) { + if (argc != 2) { + fprintf(stderr, "Usage: schemavalidator schema.json < input.json\n"); + return EXIT_FAILURE; + } + + // Read a JSON schema from file into Document + Document d; + char buffer[4096]; + + { + FILE *fp = fopen(argv[1], "r"); + if (!fp) { + printf("Schema file '%s' not found\n", argv[1]); + return -1; + } + FileReadStream fs(fp, buffer, sizeof(buffer)); + d.ParseStream(fs); + if (d.HasParseError()) { + fprintf(stderr, "Schema file '%s' is not a valid JSON\n", argv[1]); + fprintf(stderr, "Error(offset %u): %s\n", + static_cast(d.GetErrorOffset()), + GetParseError_En(d.GetParseError())); + fclose(fp); + return EXIT_FAILURE; + } + fclose(fp); + } + + // Then convert the Document into SchemaDocument + SchemaDocument sd(d); + + // Use reader to parse the JSON in stdin, and forward SAX events to validator + SchemaValidator validator(sd); + Reader reader; + FileReadStream is(stdin, buffer, sizeof(buffer)); + if (!reader.Parse(is, validator) && reader.GetParseErrorCode() != kParseErrorTermination) { + // Schema validator error would cause kParseErrorTermination, which will handle it in next step. + fprintf(stderr, "Input is not a valid JSON\n"); + fprintf(stderr, "Error(offset %u): %s\n", + static_cast(reader.GetErrorOffset()), + GetParseError_En(reader.GetParseErrorCode())); + } + + // Check the validation result + if (validator.IsValid()) { + printf("Input JSON is valid.\n"); + return EXIT_SUCCESS; + } + else { + printf("Input JSON is invalid.\n"); + StringBuffer sb; + validator.GetInvalidSchemaPointer().StringifyUriFragment(sb); + fprintf(stderr, "Invalid schema: %s\n", sb.GetString()); + fprintf(stderr, "Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword()); + fprintf(stderr, "Invalid code: %d\n", validator.GetInvalidSchemaCode()); + fprintf(stderr, "Invalid message: %s\n", GetValidateError_En(validator.GetInvalidSchemaCode())); + sb.Clear(); + validator.GetInvalidDocumentPointer().StringifyUriFragment(sb); + fprintf(stderr, "Invalid document: %s\n", sb.GetString()); + // Detailed violation report is available as a JSON value + sb.Clear(); + PrettyWriter w(sb); + validator.GetError().Accept(w); + fprintf(stderr, "Error report:\n%s\n", sb.GetString()); + CreateErrorMessages(validator.GetError()); + return EXIT_FAILURE; + } +} diff --git a/deps/rapidjson/example/serialize/serialize.cpp b/deps/rapidjson/example/serialize/serialize.cpp new file mode 100644 index 0000000..12d8715 --- /dev/null +++ b/deps/rapidjson/example/serialize/serialize.cpp @@ -0,0 +1,173 @@ +// Serialize example +// This example shows writing JSON string with writer directly. + +#include "rapidjson/prettywriter.h" // for stringify JSON +#include +#include +#include + +using namespace rapidjson; + +class Person { +public: + Person(const std::string& name, unsigned age) : name_(name), age_(age) {} + Person(const Person& rhs) : name_(rhs.name_), age_(rhs.age_) {} + virtual ~Person(); + + Person& operator=(const Person& rhs) { + name_ = rhs.name_; + age_ = rhs.age_; + return *this; + } + +protected: + template + void Serialize(Writer& writer) const { + // This base class just write out name-value pairs, without wrapping within an object. + writer.String("name"); +#if RAPIDJSON_HAS_STDSTRING + writer.String(name_); +#else + writer.String(name_.c_str(), static_cast(name_.length())); // Supplying length of string is faster. +#endif + writer.String("age"); + writer.Uint(age_); + } + +private: + std::string name_; + unsigned age_; +}; + +Person::~Person() { +} + +class Education { +public: + Education(const std::string& school, double GPA) : school_(school), GPA_(GPA) {} + Education(const Education& rhs) : school_(rhs.school_), GPA_(rhs.GPA_) {} + + template + void Serialize(Writer& writer) const { + writer.StartObject(); + + writer.String("school"); +#if RAPIDJSON_HAS_STDSTRING + writer.String(school_); +#else + writer.String(school_.c_str(), static_cast(school_.length())); +#endif + + writer.String("GPA"); + writer.Double(GPA_); + + writer.EndObject(); + } + +private: + std::string school_; + double GPA_; +}; + +class Dependent : public Person { +public: + Dependent(const std::string& name, unsigned age, Education* education = 0) : Person(name, age), education_(education) {} + Dependent(const Dependent& rhs) : Person(rhs), education_(0) { education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_); } + virtual ~Dependent(); + + Dependent& operator=(const Dependent& rhs) { + if (this == &rhs) + return *this; + delete education_; + education_ = (rhs.education_ == 0) ? 0 : new Education(*rhs.education_); + return *this; + } + + template + void Serialize(Writer& writer) const { + writer.StartObject(); + + Person::Serialize(writer); + + writer.String("education"); + if (education_) + education_->Serialize(writer); + else + writer.Null(); + + writer.EndObject(); + } + +private: + + Education *education_; +}; + +Dependent::~Dependent() { + delete education_; +} + +class Employee : public Person { +public: + Employee(const std::string& name, unsigned age, bool married) : Person(name, age), dependents_(), married_(married) {} + Employee(const Employee& rhs) : Person(rhs), dependents_(rhs.dependents_), married_(rhs.married_) {} + virtual ~Employee(); + + Employee& operator=(const Employee& rhs) { + static_cast(*this) = rhs; + dependents_ = rhs.dependents_; + married_ = rhs.married_; + return *this; + } + + void AddDependent(const Dependent& dependent) { + dependents_.push_back(dependent); + } + + template + void Serialize(Writer& writer) const { + writer.StartObject(); + + Person::Serialize(writer); + + writer.String("married"); + writer.Bool(married_); + + writer.String(("dependents")); + writer.StartArray(); + for (std::vector::const_iterator dependentItr = dependents_.begin(); dependentItr != dependents_.end(); ++dependentItr) + dependentItr->Serialize(writer); + writer.EndArray(); + + writer.EndObject(); + } + +private: + std::vector dependents_; + bool married_; +}; + +Employee::~Employee() { +} + +int main(int, char*[]) { + std::vector employees; + + employees.push_back(Employee("Milo YIP", 34, true)); + employees.back().AddDependent(Dependent("Lua YIP", 3, new Education("Happy Kindergarten", 3.5))); + employees.back().AddDependent(Dependent("Mio YIP", 1)); + + employees.push_back(Employee("Percy TSE", 30, false)); + + StringBuffer sb; + PrettyWriter writer(sb); + + writer.StartArray(); + for (std::vector::const_iterator employeeItr = employees.begin(); employeeItr != employees.end(); ++employeeItr) + employeeItr->Serialize(writer); + writer.EndArray(); + + puts(sb.GetString()); + + return 0; +} diff --git a/deps/rapidjson/example/simpledom/simpledom.cpp b/deps/rapidjson/example/simpledom/simpledom.cpp new file mode 100644 index 0000000..8038419 --- /dev/null +++ b/deps/rapidjson/example/simpledom/simpledom.cpp @@ -0,0 +1,29 @@ +// JSON simple example +// This example does not handle errors. + +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; + +int main() { + // 1. Parse a JSON string into DOM. + const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; + Document d; + d.Parse(json); + + // 2. Modify it by DOM. + Value& s = d["stars"]; + s.SetInt(s.GetInt() + 1); + + // 3. Stringify the DOM + StringBuffer buffer; + Writer writer(buffer); + d.Accept(writer); + + // Output {"project":"rapidjson","stars":11} + std::cout << buffer.GetString() << std::endl; + return 0; +} diff --git a/deps/rapidjson/example/simplepullreader/simplepullreader.cpp b/deps/rapidjson/example/simplepullreader/simplepullreader.cpp new file mode 100644 index 0000000..a4fb116 --- /dev/null +++ b/deps/rapidjson/example/simplepullreader/simplepullreader.cpp @@ -0,0 +1,53 @@ +#include "rapidjson/reader.h" +#include +#include + +using namespace rapidjson; +using namespace std; + +// If you can require C++11, you could use std::to_string here +template std::string stringify(T x) { + std::stringstream ss; + ss << x; + return ss.str(); +} + +struct MyHandler { + const char* type; + std::string data; + + MyHandler() : type(), data() {} + + bool Null() { type = "Null"; data.clear(); return true; } + bool Bool(bool b) { type = "Bool:"; data = b? "true": "false"; return true; } + bool Int(int i) { type = "Int:"; data = stringify(i); return true; } + bool Uint(unsigned u) { type = "Uint:"; data = stringify(u); return true; } + bool Int64(int64_t i) { type = "Int64:"; data = stringify(i); return true; } + bool Uint64(uint64_t u) { type = "Uint64:"; data = stringify(u); return true; } + bool Double(double d) { type = "Double:"; data = stringify(d); return true; } + bool RawNumber(const char* str, SizeType length, bool) { type = "Number:"; data = std::string(str, length); return true; } + bool String(const char* str, SizeType length, bool) { type = "String:"; data = std::string(str, length); return true; } + bool StartObject() { type = "StartObject"; data.clear(); return true; } + bool Key(const char* str, SizeType length, bool) { type = "Key:"; data = std::string(str, length); return true; } + bool EndObject(SizeType memberCount) { type = "EndObject:"; data = stringify(memberCount); return true; } + bool StartArray() { type = "StartArray"; data.clear(); return true; } + bool EndArray(SizeType elementCount) { type = "EndArray:"; data = stringify(elementCount); return true; } +private: + MyHandler(const MyHandler& noCopyConstruction); + MyHandler& operator=(const MyHandler& noAssignment); +}; + +int main() { + const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + + MyHandler handler; + Reader reader; + StringStream ss(json); + reader.IterativeParseInit(); + while (!reader.IterativeParseComplete()) { + reader.IterativeParseNext(ss, handler); + cout << handler.type << handler.data << endl; + } + + return 0; +} diff --git a/deps/rapidjson/example/simplereader/simplereader.cpp b/deps/rapidjson/example/simplereader/simplereader.cpp new file mode 100644 index 0000000..5aae8a1 --- /dev/null +++ b/deps/rapidjson/example/simplereader/simplereader.cpp @@ -0,0 +1,42 @@ +#include "rapidjson/reader.h" +#include + +using namespace rapidjson; +using namespace std; + +struct MyHandler { + bool Null() { cout << "Null()" << endl; return true; } + bool Bool(bool b) { cout << "Bool(" << boolalpha << b << ")" << endl; return true; } + bool Int(int i) { cout << "Int(" << i << ")" << endl; return true; } + bool Uint(unsigned u) { cout << "Uint(" << u << ")" << endl; return true; } + bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; } + bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; } + bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; } + bool RawNumber(const char* str, SizeType length, bool copy) { + cout << "Number(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } + bool String(const char* str, SizeType length, bool copy) { + cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } + bool StartObject() { cout << "StartObject()" << endl; return true; } + bool Key(const char* str, SizeType length, bool copy) { + cout << "Key(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl; + return true; + } + bool EndObject(SizeType memberCount) { cout << "EndObject(" << memberCount << ")" << endl; return true; } + bool StartArray() { cout << "StartArray()" << endl; return true; } + bool EndArray(SizeType elementCount) { cout << "EndArray(" << elementCount << ")" << endl; return true; } +}; + +int main() { + const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + + MyHandler handler; + Reader reader; + StringStream ss(json); + reader.Parse(ss, handler); + + return 0; +} diff --git a/deps/rapidjson/example/simplewriter/simplewriter.cpp b/deps/rapidjson/example/simplewriter/simplewriter.cpp new file mode 100644 index 0000000..8d1275c --- /dev/null +++ b/deps/rapidjson/example/simplewriter/simplewriter.cpp @@ -0,0 +1,36 @@ +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; +using namespace std; + +int main() { + StringBuffer s; + Writer writer(s); + + writer.StartObject(); // Between StartObject()/EndObject(), + writer.Key("hello"); // output a key, + writer.String("world"); // follow by a value. + writer.Key("t"); + writer.Bool(true); + writer.Key("f"); + writer.Bool(false); + writer.Key("n"); + writer.Null(); + writer.Key("i"); + writer.Uint(123); + writer.Key("pi"); + writer.Double(3.1416); + writer.Key("a"); + writer.StartArray(); // Between StartArray()/EndArray(), + for (unsigned i = 0; i < 4; i++) + writer.Uint(i); // all values are elements of the array. + writer.EndArray(); + writer.EndObject(); + + // {"hello":"world","t":true,"f":false,"n":null,"i":123,"pi":3.1416,"a":[0,1,2,3]} + cout << s.GetString() << endl; + + return 0; +} diff --git a/deps/rapidjson/example/sortkeys/sortkeys.cpp b/deps/rapidjson/example/sortkeys/sortkeys.cpp new file mode 100644 index 0000000..7ede9fb --- /dev/null +++ b/deps/rapidjson/example/sortkeys/sortkeys.cpp @@ -0,0 +1,62 @@ +#include "rapidjson/document.h" +#include "rapidjson/filewritestream.h" +#include + +#include +#include + +using namespace rapidjson; +using namespace std; + +static void printIt(const Value &doc) { + char writeBuffer[65536]; + FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer)); + PrettyWriter writer(os); + doc.Accept(writer); + cout << endl; +} + +struct NameComparator { + bool operator()(const Value::Member &lhs, const Value::Member &rhs) const { + return (strcmp(lhs.name.GetString(), rhs.name.GetString()) < 0); + } +}; + +int main() { + Document d(kObjectType); + Document::AllocatorType &allocator = d.GetAllocator(); + + d.AddMember("zeta", Value().SetBool(false), allocator); + d.AddMember("gama", Value().SetString("test string", allocator), allocator); + d.AddMember("delta", Value().SetInt(123), allocator); + d.AddMember("alpha", Value(kArrayType).Move(), allocator); + + printIt(d); + +/* +{ + "zeta": false, + "gama": "test string", + "delta": 123, + "alpha": [] +} +*/ + +// C++11 supports std::move() of Value so it always have no problem for std::sort(). +// Some C++03 implementations of std::sort() requires copy constructor which causes compilation error. +// Needs a sorting function only depends on std::swap() instead. +#if __cplusplus >= 201103L || (!defined(__GLIBCXX__) && (!defined(_MSC_VER) || _MSC_VER >= 1900)) + std::sort(d.MemberBegin(), d.MemberEnd(), NameComparator()); + + printIt(d); + +/* +{ + "alpha": [], + "delta": 123, + "gama": "test string", + "zeta": false +} +*/ +#endif +} diff --git a/deps/rapidjson/example/traverseaspointer.cpp b/deps/rapidjson/example/traverseaspointer.cpp new file mode 100644 index 0000000..7e0c899 --- /dev/null +++ b/deps/rapidjson/example/traverseaspointer.cpp @@ -0,0 +1,39 @@ +#include "rapidjson/document.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/pointer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; + +void traverse(const Value& v, const Pointer& p) { + StringBuffer sb; + p.Stringify(sb); + std::cout << sb.GetString() << std::endl; + + switch (v.GetType()) { + case kArrayType: + for (SizeType i = 0; i != v.Size(); ++i) + traverse(v[i], p.Append(i)); + break; + case kObjectType: + for (Value::ConstMemberIterator m = v.MemberBegin(); m != v.MemberEnd(); ++m) + traverse(m->value, p.Append(m->name.GetString(), m->name.GetStringLength())); + break; + default: + break; + } +} + +int main(int, char*[]) { + char readBuffer[65536]; + FileReadStream is(stdin, readBuffer, sizeof(readBuffer)); + + Document d; + d.ParseStream(is); + + Pointer root; + traverse(d, root); + + return 0; +} diff --git a/deps/rapidjson/example/tutorial/tutorial.cpp b/deps/rapidjson/example/tutorial/tutorial.cpp new file mode 100644 index 0000000..d6021c6 --- /dev/null +++ b/deps/rapidjson/example/tutorial/tutorial.cpp @@ -0,0 +1,151 @@ +// Hello World example +// This example shows basic usage of DOM-style API. + +#include "rapidjson/document.h" // rapidjson's DOM-style API +#include "rapidjson/prettywriter.h" // for stringify JSON +#include + +using namespace rapidjson; +using namespace std; + +int main(int, char*[]) { + //////////////////////////////////////////////////////////////////////////// + // 1. Parse a JSON text string to a document. + + const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + printf("Original JSON:\n %s\n", json); + + Document document; // Default template parameter uses UTF8 and MemoryPoolAllocator. + +#if 0 + // "normal" parsing, decode strings to new buffers. Can use other input stream via ParseStream(). + if (document.Parse(json).HasParseError()) + return 1; +#else + // In-situ parsing, decode strings directly in the source string. Source must be string. + char buffer[sizeof(json)]; + memcpy(buffer, json, sizeof(json)); + if (document.ParseInsitu(buffer).HasParseError()) + return 1; +#endif + + printf("\nParsing to document succeeded.\n"); + + //////////////////////////////////////////////////////////////////////////// + // 2. Access values in document. + + printf("\nAccess values in document:\n"); + assert(document.IsObject()); // Document is a JSON value represents the root of DOM. Root can be either an object or array. + + assert(document.HasMember("hello")); + assert(document["hello"].IsString()); + printf("hello = %s\n", document["hello"].GetString()); + + // Since version 0.2, you can use single lookup to check the existing of member and its value: + Value::MemberIterator hello = document.FindMember("hello"); + assert(hello != document.MemberEnd()); + assert(hello->value.IsString()); + assert(strcmp("world", hello->value.GetString()) == 0); + (void)hello; + + assert(document["t"].IsBool()); // JSON true/false are bool. Can also uses more specific function IsTrue(). + printf("t = %s\n", document["t"].GetBool() ? "true" : "false"); + + assert(document["f"].IsBool()); + printf("f = %s\n", document["f"].GetBool() ? "true" : "false"); + + printf("n = %s\n", document["n"].IsNull() ? "null" : "?"); + + assert(document["i"].IsNumber()); // Number is a JSON type, but C++ needs more specific type. + assert(document["i"].IsInt()); // In this case, IsUint()/IsInt64()/IsUint64() also return true. + printf("i = %d\n", document["i"].GetInt()); // Alternative (int)document["i"] + + assert(document["pi"].IsNumber()); + assert(document["pi"].IsDouble()); + printf("pi = %g\n", document["pi"].GetDouble()); + + { + const Value& a = document["a"]; // Using a reference for consecutive access is handy and faster. + assert(a.IsArray()); + for (SizeType i = 0; i < a.Size(); i++) // rapidjson uses SizeType instead of size_t. + printf("a[%d] = %d\n", i, a[i].GetInt()); + + int y = a[0].GetInt(); + (void)y; + + // Iterating array with iterators + printf("a = "); + for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + printf("%d ", itr->GetInt()); + printf("\n"); + } + + // Iterating object members + static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" }; + for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr) + printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]); + + //////////////////////////////////////////////////////////////////////////// + // 3. Modify values in document. + + // Change i to a bigger number + { + uint64_t f20 = 1; // compute factorial of 20 + for (uint64_t j = 1; j <= 20; j++) + f20 *= j; + document["i"] = f20; // Alternate form: document["i"].SetUint64(f20) + assert(!document["i"].IsInt()); // No longer can be cast as int or uint. + } + + // Adding values to array. + { + Value& a = document["a"]; // This time we uses non-const reference. + Document::AllocatorType& allocator = document.GetAllocator(); + for (int i = 5; i <= 10; i++) + a.PushBack(i, allocator); // May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's. + + // Fluent API + a.PushBack("Lua", allocator).PushBack("Mio", allocator); + } + + // Making string values. + + // This version of SetString() just store the pointer to the string. + // So it is for literal and string that exists within value's life-cycle. + { + document["hello"] = "rapidjson"; // This will invoke strlen() + // Faster version: + // document["hello"].SetString("rapidjson", 9); + } + + // This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer. + Value author; + { + char buffer2[10]; + int len = sprintf(buffer2, "%s %s", "Milo", "Yip"); // synthetic example of dynamically created string. + + author.SetString(buffer2, static_cast(len), document.GetAllocator()); + // Shorter but slower version: + // document["hello"].SetString(buffer, document.GetAllocator()); + + // Constructor version: + // Value author(buffer, len, document.GetAllocator()); + // Value author(buffer, document.GetAllocator()); + memset(buffer2, 0, sizeof(buffer2)); // For demonstration purpose. + } + // Variable 'buffer' is unusable now but 'author' has already made a copy. + document.AddMember("author", author, document.GetAllocator()); + + assert(author.IsNull()); // Move semantic for assignment. After this variable is assigned as a member, the variable becomes null. + + //////////////////////////////////////////////////////////////////////////// + // 4. Stringify JSON + + printf("\nModified JSON with reformatting:\n"); + StringBuffer sb; + PrettyWriter writer(sb); + document.Accept(writer); // Accept() traverses the DOM and generates Handler events. + puts(sb.GetString()); + + return 0; +} diff --git a/deps/rapidjson/include/rapidjson/allocators.h b/deps/rapidjson/include/rapidjson/allocators.h new file mode 100644 index 0000000..35650af --- /dev/null +++ b/deps/rapidjson/include/rapidjson/allocators.h @@ -0,0 +1,693 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ALLOCATORS_H_ +#define RAPIDJSON_ALLOCATORS_H_ + +#include "rapidjson.h" +#include "internal/meta.h" + +#include +#include + +#if RAPIDJSON_HAS_CXX11 +#include +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Allocator + +/*! \class rapidjson::Allocator + \brief Concept for allocating, resizing and freeing memory block. + + Note that Malloc() and Realloc() are non-static but Free() is static. + + So if an allocator need to support Free(), it needs to put its pointer in + the header of memory block. + +\code +concept Allocator { + static const bool kNeedFree; //!< Whether this allocator needs to call Free(). + + // Allocate a memory block. + // \param size of the memory block in bytes. + // \returns pointer to the memory block. + void* Malloc(size_t size); + + // Resize a memory block. + // \param originalPtr The pointer to current memory block. Null pointer is permitted. + // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.) + // \param newSize the new size in bytes. + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize); + + // Free a memory block. + // \param pointer to the memory block. Null pointer is permitted. + static void Free(void *ptr); +}; +\endcode +*/ + + +/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User-defined kDefaultChunkCapacity definition. + + User can define this as any \c size that is a power of 2. +*/ + +#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY +#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024) +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// CrtAllocator + +//! C-runtime library allocator. +/*! This class is just wrapper for standard C library memory routines. + \note implements Allocator concept +*/ +class CrtAllocator { +public: + static const bool kNeedFree = true; + void* Malloc(size_t size) { + if (size) // behavior of malloc(0) is implementation defined. + return RAPIDJSON_MALLOC(size); + else + return NULL; // standardize to returning NULL. + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + (void)originalSize; + if (newSize == 0) { + RAPIDJSON_FREE(originalPtr); + return NULL; + } + return RAPIDJSON_REALLOC(originalPtr, newSize); + } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); } + + bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return true; + } + bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT { + return false; + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// MemoryPoolAllocator + +//! Default memory allocator used by the parser and DOM. +/*! This allocator allocate memory blocks from pre-allocated memory chunks. + + It does not free memory blocks. And Realloc() only allocate new memory. + + The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default. + + User may also supply a buffer as the first chunk. + + If the user-buffer is full then additional chunks are allocated by BaseAllocator. + + The user-buffer is not deallocated by this allocator. + + \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator. + \note implements Allocator concept +*/ +template +class MemoryPoolAllocator { + //! Chunk header for perpending to each chunk. + /*! Chunks are stored as a singly linked list. + */ + struct ChunkHeader { + size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself). + size_t size; //!< Current size of allocated memory in bytes. + ChunkHeader *next; //!< Next chunk in the linked list. + }; + + struct SharedData { + ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation. + BaseAllocator* ownBaseAllocator; //!< base allocator created by this object. + size_t refcount; + bool ownBuffer; + }; + + static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData)); + static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader)); + + static inline ChunkHeader *GetChunkHead(SharedData *shared) + { + return reinterpret_cast(reinterpret_cast(shared) + SIZEOF_SHARED_DATA); + } + static inline uint8_t *GetChunkBuffer(SharedData *shared) + { + return reinterpret_cast(shared->chunkHead) + SIZEOF_CHUNK_HEADER; + } + + static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. + +public: + static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator) + static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy + + //! Constructor with chunkSize. + /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + explicit + MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()), + shared_(static_cast(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0)) + { + RAPIDJSON_ASSERT(baseAllocator_ != 0); + RAPIDJSON_ASSERT(shared_ != 0); + if (baseAllocator) { + shared_->ownBaseAllocator = 0; + } + else { + shared_->ownBaseAllocator = baseAllocator_; + } + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = 0; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBuffer = true; + shared_->refcount = 1; + } + + //! Constructor with user-supplied buffer. + /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size. + + The user buffer will not be deallocated when this allocator is destructed. + + \param buffer User supplied buffer. + \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader). + \param chunkSize The size of memory chunk. The default is kDefaultChunkSize. + \param baseAllocator The allocator for allocating memory chunks. + */ + MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) : + chunk_capacity_(chunkSize), + baseAllocator_(baseAllocator), + shared_(static_cast(AlignBuffer(buffer, size))) + { + RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER); + shared_->chunkHead = GetChunkHead(shared_); + shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER; + shared_->chunkHead->size = 0; + shared_->chunkHead->next = 0; + shared_->ownBaseAllocator = 0; + shared_->ownBuffer = false; + shared_->refcount = 1; + } + + MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + ++shared_->refcount; + } + MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + ++rhs.shared_->refcount; + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT : + chunk_capacity_(rhs.chunk_capacity_), + baseAllocator_(rhs.baseAllocator_), + shared_(rhs.shared_) + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + rhs.shared_ = 0; + } + MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT + { + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + this->~MemoryPoolAllocator(); + baseAllocator_ = rhs.baseAllocator_; + chunk_capacity_ = rhs.chunk_capacity_; + shared_ = rhs.shared_; + rhs.shared_ = 0; + return *this; + } +#endif + + //! Destructor. + /*! This deallocates all memory chunks, excluding the user-supplied buffer. + */ + ~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT { + if (!shared_) { + // do nothing if moved + return; + } + if (shared_->refcount > 1) { + --shared_->refcount; + return; + } + Clear(); + BaseAllocator *a = shared_->ownBaseAllocator; + if (shared_->ownBuffer) { + baseAllocator_->Free(shared_); + } + RAPIDJSON_DELETE(a); + } + + //! Deallocates all memory chunks, excluding the first/user one. + void Clear() RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + for (;;) { + ChunkHeader* c = shared_->chunkHead; + if (!c->next) { + break; + } + shared_->chunkHead = c->next; + baseAllocator_->Free(c); + } + shared_->chunkHead->size = 0; + } + + //! Computes the total capacity of allocated memory chunks. + /*! \return total capacity in bytes. + */ + size_t Capacity() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t capacity = 0; + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + capacity += c->capacity; + return capacity; + } + + //! Computes the memory blocks allocated. + /*! \return total used bytes. + */ + size_t Size() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + size_t size = 0; + for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next) + size += c->size; + return size; + } + + //! Whether the allocator is shared. + /*! \return true or false. + */ + bool Shared() const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + return shared_->refcount > 1; + } + + //! Allocates a memory block. (concept Allocator) + void* Malloc(size_t size) { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (!size) + return NULL; + + size = RAPIDJSON_ALIGN(size); + if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity)) + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; + + void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size; + shared_->chunkHead->size += size; + return buffer; + } + + //! Resizes a memory block (concept Allocator) + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { + if (originalPtr == 0) + return Malloc(newSize); + + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + if (newSize == 0) + return NULL; + + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); + + // Do not shrink if new size is smaller than original + if (originalSize >= newSize) + return originalPtr; + + // Simply expand it if it is the last allocation and there is sufficient space + if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) { + size_t increment = static_cast(newSize - originalSize); + if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) { + shared_->chunkHead->size += increment; + return originalPtr; + } + } + + // Realloc process: allocate and copy memory, do not free original buffer. + if (void* newBuffer = Malloc(newSize)) { + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + else + return NULL; + } + + //! Frees a memory block (concept Allocator) + static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing + + //! Compare (equality) with another MemoryPoolAllocator + bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0); + RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0); + return shared_ == rhs.shared_; + } + //! Compare (inequality) with another MemoryPoolAllocator + bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT { + return !operator==(rhs); + } + +private: + //! Creates a new chunk. + /*! \param capacity Capacity of the chunk in bytes. + \return true if success. + */ + bool AddChunk(size_t capacity) { + if (!baseAllocator_) + shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); + if (ChunkHeader* chunk = static_cast(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = shared_->chunkHead; + shared_->chunkHead = chunk; + return true; + } + else + return false; + } + + static inline void* AlignBuffer(void* buf, size_t &size) + { + RAPIDJSON_NOEXCEPT_ASSERT(buf != 0); + const uintptr_t mask = sizeof(void*) - 1; + const uintptr_t ubuf = reinterpret_cast(buf); + if (RAPIDJSON_UNLIKELY(ubuf & mask)) { + const uintptr_t abuf = (ubuf + mask) & ~mask; + RAPIDJSON_ASSERT(size >= abuf - ubuf); + buf = reinterpret_cast(abuf); + size -= abuf - ubuf; + } + return buf; + } + + size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated. + BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks. + SharedData *shared_; //!< The shared data of the allocator +}; + +namespace internal { + template + struct IsRefCounted : + public FalseType + { }; + template + struct IsRefCounted::Type> : + public TrueType + { }; +} + +template +inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n) +{ + RAPIDJSON_NOEXCEPT_ASSERT(old_n <= (std::numeric_limits::max)() / sizeof(T) && new_n <= (std::numeric_limits::max)() / sizeof(T)); + return static_cast(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T))); +} + +template +inline T *Malloc(A& a, size_t n = 1) +{ + return Realloc(a, NULL, 0, n); +} + +template +inline void Free(A& a, T *p, size_t n = 1) +{ + static_cast(Realloc(a, p, n, 0)); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited +#endif + +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; +#if RAPIDJSON_HAS_CXX11 + typedef std::allocator_traits traits_type; +#else + typedef allocator_type traits_type; +#endif + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(std::move(rhs)), + baseAllocator_(std::move(rhs.baseAllocator_)) + { } +#endif +#if RAPIDJSON_HAS_CXX11 + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_swap = std::true_type; +#endif + + /* implicit */ + StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(allocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; + }; + + typedef typename traits_type::size_type size_type; + typedef typename traits_type::difference_type difference_type; + + typedef typename traits_type::value_type value_type; + typedef typename traits_type::pointer pointer; + typedef typename traits_type::const_pointer const_pointer; + +#if RAPIDJSON_HAS_CXX11 + + typedef typename std::add_lvalue_reference::type &reference; + typedef typename std::add_lvalue_reference::type>::type &const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return std::addressof(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return traits_type::max_size(*this); + } + + template + void construct(pointer p, Args&&... args) + { + traits_type::construct(*this, p, std::forward(args)...); + } + void destroy(pointer p) + { + traits_type::destroy(*this, p); + } + +#else // !RAPIDJSON_HAS_CXX11 + + typedef typename allocator_type::reference reference; + typedef typename allocator_type::const_reference const_reference; + + pointer address(reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT + { + return allocator_type::address(r); + } + + size_type max_size() const RAPIDJSON_NOEXCEPT + { + return allocator_type::max_size(); + } + + void construct(pointer p, const_reference r) + { + allocator_type::construct(p, r); + } + void destroy(pointer p) + { + allocator_type::destroy(p); + } + +#endif // !RAPIDJSON_HAS_CXX11 + + template + U* allocate(size_type n = 1, const void* = 0) + { + return RAPIDJSON_NAMESPACE::Malloc(baseAllocator_, n); + } + template + void deallocate(U* p, size_type n = 1) + { + RAPIDJSON_NAMESPACE::Free(baseAllocator_, p, n); + } + + pointer allocate(size_type n = 1, const void* = 0) + { + return allocate(n); + } + void deallocate(pointer p, size_type n = 1) + { + deallocate(p, n); + } + +#if RAPIDJSON_HAS_CXX11 + using is_always_equal = std::is_empty; +#endif + + template + bool operator==(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return baseAllocator_ == rhs.baseAllocator_; + } + template + bool operator!=(const StdAllocator& rhs) const RAPIDJSON_NOEXCEPT + { + return !operator==(rhs); + } + + //! rapidjson Allocator concept + static const bool kNeedFree = BaseAllocator::kNeedFree; + static const bool kRefCounted = internal::IsRefCounted::Value; + void* Malloc(size_t size) + { + return baseAllocator_.Malloc(size); + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) + { + return baseAllocator_.Realloc(originalPtr, originalSize, newSize); + } + static void Free(void *ptr) RAPIDJSON_NOEXCEPT + { + BaseAllocator::Free(ptr); + } + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; +}; + +#if !RAPIDJSON_HAS_CXX17 // std::allocator deprecated in C++17 +template +class StdAllocator : + public std::allocator +{ + typedef std::allocator allocator_type; + +public: + typedef BaseAllocator BaseAllocatorType; + + StdAllocator() RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_() + { } + + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + template + StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT : + allocator_type(rhs), + baseAllocator_(rhs.baseAllocator_) + { } + + /* implicit */ + StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT : + allocator_type(), + baseAllocator_(baseAllocator) + { } + + ~StdAllocator() RAPIDJSON_NOEXCEPT + { } + + template + struct rebind { + typedef StdAllocator other; + }; + + typedef typename allocator_type::value_type value_type; + +private: + template + friend class StdAllocator; // access to StdAllocator.* + + BaseAllocator baseAllocator_; +}; +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/deps/rapidjson/include/rapidjson/cursorstreamwrapper.h b/deps/rapidjson/include/rapidjson/cursorstreamwrapper.h new file mode 100644 index 0000000..fd6513d --- /dev/null +++ b/deps/rapidjson/include/rapidjson/cursorstreamwrapper.h @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_ +#define RAPIDJSON_CURSORSTREAMWRAPPER_H_ + +#include "stream.h" + +#if defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4702) // unreachable code +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + + +//! Cursor stream wrapper for counting line and column number if error exists. +/*! + \tparam InputStream Any stream that implements Stream Concept +*/ +template > +class CursorStreamWrapper : public GenericStreamWrapper { +public: + typedef typename Encoding::Ch Ch; + + CursorStreamWrapper(InputStream& is): + GenericStreamWrapper(is), line_(1), col_(0) {} + + // counting line and column number + Ch Take() { + Ch ch = this->is_.Take(); + if(ch == '\n') { + line_ ++; + col_ = 0; + } else { + col_ ++; + } + return ch; + } + + //! Get the error line number, if error exists. + size_t GetLine() const { return line_; } + //! Get the error column number, if error exists. + size_t GetColumn() const { return col_; } + +private: + size_t line_; //!< Current Line + size_t col_; //!< Current Column +}; + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_POP +#endif + +#if defined(__GNUC__) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_ diff --git a/deps/rapidjson/include/rapidjson/document.h b/deps/rapidjson/include/rapidjson/document.h new file mode 100644 index 0000000..2cd9a70 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/document.h @@ -0,0 +1,3043 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_DOCUMENT_H_ +#define RAPIDJSON_DOCUMENT_H_ + +/*! \file document.h */ + +#include "reader.h" +#include "internal/meta.h" +#include "internal/strfunc.h" +#include "memorystream.h" +#include "encodedstream.h" +#include // placement new +#include +#ifdef __cpp_lib_three_way_comparison +#include +#endif + +RAPIDJSON_DIAG_PUSH +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +#endif // __GNUC__ + +#ifdef GetObject +// see https://github.com/Tencent/rapidjson/issues/1448 +// a former included windows.h might have defined a macro called GetObject, which affects +// GetObject defined here. This ensures the macro does not get applied +#pragma push_macro("GetObject") +#define RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#undef GetObject +#endif + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS +#include // std::random_access_iterator_tag +#endif + +#if RAPIDJSON_USE_MEMBERSMAP +#include // std::multimap +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +// Forward declaration. +template +class GenericValue; + +template +class GenericDocument; + +/*! \def RAPIDJSON_DEFAULT_ALLOCATOR + \ingroup RAPIDJSON_CONFIG + \brief Allows to choose default allocator. + + User can define this to use CrtAllocator or MemoryPoolAllocator. +*/ +#ifndef RAPIDJSON_DEFAULT_ALLOCATOR +#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<::RAPIDJSON_NAMESPACE::CrtAllocator> +#endif + +/*! \def RAPIDJSON_DEFAULT_STACK_ALLOCATOR + \ingroup RAPIDJSON_CONFIG + \brief Allows to choose default stack allocator for Document. + + User can define this to use CrtAllocator or MemoryPoolAllocator. +*/ +#ifndef RAPIDJSON_DEFAULT_STACK_ALLOCATOR +#define RAPIDJSON_DEFAULT_STACK_ALLOCATOR ::RAPIDJSON_NAMESPACE::CrtAllocator +#endif + +/*! \def RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User defined kDefaultObjectCapacity value. + + User can define this as any natural number. +*/ +#ifndef RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY +// number of objects that rapidjson::Value allocates memory for by default +#define RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY 16 +#endif + +/*! \def RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY + \ingroup RAPIDJSON_CONFIG + \brief User defined kDefaultArrayCapacity value. + + User can define this as any natural number. +*/ +#ifndef RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY +// number of array elements that rapidjson::Value allocates memory for by default +#define RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY 16 +#endif + +//! Name-value pair in a JSON object value. +/*! + This class was internal to GenericValue. It used to be a inner struct. + But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct. + https://code.google.com/p/rapidjson/issues/detail?id=64 +*/ +template +class GenericMember { +public: + GenericValue name; //!< name of member (must be a string) + GenericValue value; //!< value of member. + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericMember(GenericMember&& rhs) RAPIDJSON_NOEXCEPT + : name(std::move(rhs.name)), + value(std::move(rhs.value)) + { + } + + //! Move assignment in C++11 + GenericMember& operator=(GenericMember&& rhs) RAPIDJSON_NOEXCEPT { + return *this = static_cast(rhs); + } +#endif + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. Its name and value will become a null value after assignment. + */ + GenericMember& operator=(GenericMember& rhs) RAPIDJSON_NOEXCEPT { + if (RAPIDJSON_LIKELY(this != &rhs)) { + name = rhs.name; + value = rhs.value; + } + return *this; + } + + // swap() for std::sort() and other potential use in STL. + friend inline void swap(GenericMember& a, GenericMember& b) RAPIDJSON_NOEXCEPT { + a.name.Swap(b.name); + a.value.Swap(b.value); + } + +private: + //! Copy constructor is not permitted. + GenericMember(const GenericMember& rhs); +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericMemberIterator + +#ifndef RAPIDJSON_NOMEMBERITERATORCLASS + +//! (Constant) member iterator for a JSON object value +/*! + \tparam Const Is this a constant iterator? + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. + + This class implements a Random Access Iterator for GenericMember elements + of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements]. + + \note This iterator implementation is mainly intended to avoid implicit + conversions from iterator values to \c NULL, + e.g. from GenericValue::FindMember. + + \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a + pointer-based implementation, if your platform doesn't provide + the C++ header. + + \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator + */ +template +class GenericMemberIterator { + + friend class GenericValue; + template friend class GenericMemberIterator; + + typedef GenericMember PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + +public: + //! Iterator type itself + typedef GenericMemberIterator Iterator; + //! Constant iterator type + typedef GenericMemberIterator ConstIterator; + //! Non-constant iterator type + typedef GenericMemberIterator NonConstIterator; + + /** \name std::iterator_traits support */ + //@{ + typedef ValueType value_type; + typedef ValueType * pointer; + typedef ValueType & reference; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + //@} + + //! Pointer to (const) GenericMember + typedef pointer Pointer; + //! Reference to (const) GenericMember + typedef reference Reference; + //! Signed integer type (e.g. \c ptrdiff_t) + typedef difference_type DifferenceType; + + //! Default constructor (singular value) + /*! Creates an iterator pointing to no element. + \note All operations, except for comparisons, are undefined on such values. + */ + GenericMemberIterator() : ptr_() {} + + //! Iterator conversions to more const + /*! + \param it (Non-const) iterator to copy from + + Allows the creation of an iterator from another GenericMemberIterator + that is "less const". Especially, creating a non-constant iterator + from a constant iterator are disabled: + \li const -> non-const (not ok) + \li const -> const (ok) + \li non-const -> const (ok) + \li non-const -> non-const (ok) + + \note If the \c Const template parameter is already \c false, this + constructor effectively defines a regular copy-constructor. + Otherwise, the copy constructor is implicitly defined. + */ + GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } + + //! @name stepping + //@{ + Iterator& operator++(){ ++ptr_; return *this; } + Iterator& operator--(){ --ptr_; return *this; } + Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; } + Iterator operator--(int){ Iterator old(*this); --ptr_; return old; } + //@} + + //! @name increment/decrement + //@{ + Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); } + Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); } + + Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; } + Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; } + //@} + + //! @name relations + //@{ + template bool operator==(const GenericMemberIterator& that) const { return ptr_ == that.ptr_; } + template bool operator!=(const GenericMemberIterator& that) const { return ptr_ != that.ptr_; } + template bool operator<=(const GenericMemberIterator& that) const { return ptr_ <= that.ptr_; } + template bool operator>=(const GenericMemberIterator& that) const { return ptr_ >= that.ptr_; } + template bool operator< (const GenericMemberIterator& that) const { return ptr_ < that.ptr_; } + template bool operator> (const GenericMemberIterator& that) const { return ptr_ > that.ptr_; } + +#ifdef __cpp_lib_three_way_comparison + template std::strong_ordering operator<=>(const GenericMemberIterator& that) const { return ptr_ <=> that.ptr_; } +#endif + //@} + + //! @name dereference + //@{ + Reference operator*() const { return *ptr_; } + Pointer operator->() const { return ptr_; } + Reference operator[](DifferenceType n) const { return ptr_[n]; } + //@} + + //! Distance + DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; } + +private: + //! Internal constructor from plain pointer + explicit GenericMemberIterator(Pointer p) : ptr_(p) {} + + Pointer ptr_; //!< raw pointer +}; + +#else // RAPIDJSON_NOMEMBERITERATORCLASS + +// class-based member iterator implementation disabled, use plain pointers + +template +class GenericMemberIterator; + +//! non-const GenericMemberIterator +template +class GenericMemberIterator { +public: + //! use plain pointer as iterator type + typedef GenericMember* Iterator; +}; +//! const GenericMemberIterator +template +class GenericMemberIterator { +public: + //! use plain const pointer as iterator type + typedef const GenericMember* Iterator; +}; + +#endif // RAPIDJSON_NOMEMBERITERATORCLASS + +/////////////////////////////////////////////////////////////////////////////// +// GenericStringRef + +//! Reference to a constant string (not taking a copy) +/*! + \tparam CharType character type of the string + + This helper class is used to automatically infer constant string + references for string literals, especially from \c const \b (!) + character arrays. + + The main use is for creating JSON string values without copying the + source string via an \ref Allocator. This requires that the referenced + string pointers have a sufficient lifetime, which exceeds the lifetime + of the associated GenericValue. + + \b Example + \code + Value v("foo"); // ok, no need to copy & calculate length + const char foo[] = "foo"; + v.SetString(foo); // ok + + const char* bar = foo; + // Value x(bar); // not ok, can't rely on bar's lifetime + Value x(StringRef(bar)); // lifetime explicitly guaranteed by user + Value y(StringRef(bar, 3)); // ok, explicitly pass length + \endcode + + \see StringRef, GenericValue::SetString +*/ +template +struct GenericStringRef { + typedef CharType Ch; //!< character type of the string + + //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation + /*! + This constructor implicitly creates a constant string reference from + a \c const character array. It has better performance than + \ref StringRef(const CharType*) by inferring the string \ref length + from the array length, and also supports strings containing null + characters. + + \tparam N length of the string, automatically inferred + + \param str Constant character array, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note Constant complexity. + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + template + GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT + : s(str), length(N-1) {} + + //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation + /*! + This constructor can be used to \b explicitly create a reference to + a constant string pointer. + + \see StringRef(const CharType*) + + \param str Constant character pointer, lifetime assumed to be longer + than the use of the string in e.g. a GenericValue + + \post \ref s == str + + \note There is a hidden, private overload to disallow references to + non-const character arrays to be created via this constructor. + By this, e.g. function-scope arrays used to be filled via + \c snprintf are excluded from consideration. + In such cases, the referenced string should be \b copied to the + GenericValue instead. + */ +#endif + explicit GenericStringRef(const CharType* str) + : s(str), length(NotNullStrLen(str)) {} + + //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation + /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param len length of the string, excluding the trailing NULL terminator + + \post \ref s == str && \ref length == len + \note Constant complexity. + */ +#endif + GenericStringRef(const CharType* str, SizeType len) + : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} + + //! implicit conversion to plain CharType pointer + operator const Ch *() const { return s; } + + const Ch* const s; //!< plain CharType pointer + const SizeType length; //!< length of the string (excluding the trailing NULL terminator) + +private: + SizeType NotNullStrLen(const CharType* str) { + RAPIDJSON_ASSERT(str != 0); + return internal::StrLen(str); + } + + /// Empty string - used when passing in a NULL pointer + static const Ch emptyString[]; + + //! Disallow construction from non-const array + template + GenericStringRef(CharType (&str)[N]) /* = delete */; + //! Copy assignment operator not permitted - immutable type + GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; +}; + +template +const CharType GenericStringRef::emptyString[] = { CharType() }; + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + \tparam CharType Character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + + \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember +*/ +template +inline GenericStringRef StringRef(const CharType* str) { + return GenericStringRef(str); +} + +//! Mark a character pointer as constant string +/*! Mark a plain character pointer as a "string literal". This function + can be used to avoid copying a character string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + This version has better performance with supplied length, and also + supports string containing null characters. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \param length The length of source string. + \return GenericStringRef string reference object + \relatesalso GenericStringRef +*/ +template +inline GenericStringRef StringRef(const CharType* str, size_t length) { + return GenericStringRef(str, SizeType(length)); +} + +#if RAPIDJSON_HAS_STDSTRING +//! Mark a string object as constant string +/*! Mark a string object (e.g. \c std::string) as a "string literal". + This function can be used to avoid copying a string to be referenced as a + value in a JSON GenericValue object, if the string's lifetime is known + to be valid long enough. + + \tparam CharType character type of the string + \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue + \return GenericStringRef string reference object + \relatesalso GenericStringRef + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. +*/ +template +inline GenericStringRef StringRef(const std::basic_string& str) { + return GenericStringRef(str.data(), SizeType(str.size())); +} +#endif + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue type traits +namespace internal { + +template +struct IsGenericValueImpl : FalseType {}; + +// select candidates according to nested encoding and allocator types +template struct IsGenericValueImpl::Type, typename Void::Type> + : IsBaseOf, T>::Type {}; + +// helper to match arbitrary GenericValue instantiations, including derived classes +template struct IsGenericValue : IsGenericValueImpl::Type {}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template +struct TypeHelper {}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsBool(); } + static bool Get(const ValueType& v) { return v.GetBool(); } + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static int Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; + +#ifdef _MSC_VER +RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int)); +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static long Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned)); +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned long Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; +#endif + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt64(); } + static int64_t Get(const ValueType& v) { return v.GetInt64(); } + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint64(); } + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsDouble(); } + static double Get(const ValueType& v) { return v.GetDouble(); } + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsFloat(); } + static float Get(const ValueType& v) { return v.GetFloat(); } + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } +}; + +template +struct TypeHelper { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return v.GetString(); } + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; + +#if RAPIDJSON_HAS_STDSTRING +template +struct TypeHelper > { + typedef std::basic_string StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; +#endif + +template +struct TypeHelper { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(ValueType& v) { return v.GetArray(); } + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template +struct TypeHelper { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(ValueType& v) { return v.GetObject(); } + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(const ValueType& v) { return v.GetObject(); } +}; + +} // namespace internal + +// Forward declarations +template class GenericArray; +template class GenericObject; + +/////////////////////////////////////////////////////////////////////////////// +// GenericValue + +//! Represents a JSON value. Use Value for UTF8 encoding and default allocator. +/*! + A JSON value can be one of 7 types. This class is a variant type supporting + these types. + + Use the Value if UTF8 and default allocator + + \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document) + \tparam Allocator Allocator type for allocating memory of object, array and string. +*/ +template +class GenericValue { +public: + //! Name-value pair in an object. + typedef GenericMember Member; + typedef Encoding EncodingType; //!< Encoding type from template parameter. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericStringRef StringRefType; //!< Reference to a constant string + typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. + typedef typename GenericMemberIterator::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object. + typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. + typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. + typedef GenericValue ValueType; //!< Value type of itself. + typedef GenericArray Array; + typedef GenericArray ConstArray; + typedef GenericObject Object; + typedef GenericObject ConstObject; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor creates a null value. + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { + rhs.data_.f.flags = kNullFlag; // give up contents + } +#endif + +private: + //! Copy constructor is not permitted. + GenericValue(const GenericValue& rhs); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue& operator=(GenericDocument&& rhs); +#endif + +public: + + //! Constructor with JSON value type. + /*! This creates a Value of specified type with default content. + \param type Type of the value. + \note Default content for number is zero. + */ + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { + static const uint16_t defaultFlags[] = { + kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, + kNumberAnyFlag + }; + RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType); + data_.f.flags = defaultFlags[type]; + + // Use ShortString to store empty string. + if (type == kStringType) + data_.ss.SetLength(0); + } + + //! Explicit copy constructor (with allocator) + /*! Creates a copy of a Value by using the given Allocator + \tparam SourceAllocator allocator of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + \see CopyFrom() + */ + template + GenericValue(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + switch (rhs.GetType()) { + case kObjectType: + DoCopyMembers(rhs, allocator, copyConstStrings); + break; + case kArrayType: { + SizeType count = rhs.data_.a.size; + GenericValue* le = reinterpret_cast(allocator.Malloc(count * sizeof(GenericValue))); + const GenericValue* re = rhs.GetElementsPointer(); + for (SizeType i = 0; i < count; i++) + new (&le[i]) GenericValue(re[i], allocator, copyConstStrings); + data_.f.flags = kArrayFlag; + data_.a.size = data_.a.capacity = count; + SetElementsPointer(le); + } + break; + case kStringType: + if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + } + else + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + break; + } + } + + //! Constructor for boolean value. + /*! \param b Boolean value + \note This constructor is limited to \em real boolean values and rejects + implicitly converted types like arbitrary pointers. Use an explicit cast + to \c bool, if you want to construct a boolean JSON value in such cases. + */ +#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen + template + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT // See #472 +#else + explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT +#endif + : data_() { + // safe-guard against failing SFINAE + RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; + } + + //! Constructor for int value. + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; + } + + //! Constructor for unsigned value. + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); + } + + //! Constructor for int64_t value. + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; + if (i64 >= 0) { + data_.f.flags |= kNumberUint64Flag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for uint64_t value. + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { + data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) + data_.f.flags |= kInt64Flag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) + data_.f.flags |= kUintFlag; + if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) + data_.f.flags |= kIntFlag; + } + + //! Constructor for double value. + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for float value. + explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast(f); data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for constant string (i.e. do not make a copy of string) + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } + + //! Constructor for constant string (i.e. do not make a copy of string) + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } + + //! Constructor for copy-string (i.e. do make a copy of string) + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor for copy-string from a string object (i.e. do make a copy of string) + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue(const std::basic_string& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } +#endif + + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } + + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } + + //! Destructor. + /*! Need to destruct elements of array, members of object, or copy-string. + */ + ~GenericValue() { + // With RAPIDJSON_USE_MEMBERSMAP, the maps need to be destroyed to release + // their Allocator if it's refcounted (e.g. MemoryPoolAllocator). + if (Allocator::kNeedFree || (RAPIDJSON_USE_MEMBERSMAP+0 && + internal::IsRefCounted::Value)) { + switch(data_.f.flags) { + case kArrayFlag: + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(e); + } + } + break; + + case kObjectFlag: + DoFreeMembers(); + break; + + case kCopyStringFlag: + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Allocator::Free(const_cast(GetStringPointer())); + } + break; + + default: + break; // Do nothing for other types. + } + } + } + + //@} + + //!@name Assignment operators + //@{ + + //! Assignment with move semantics. + /*! \param rhs Source of the assignment. It will become a null value after assignment. + */ + GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + if (RAPIDJSON_LIKELY(this != &rhs)) { + // Can't destroy "this" before assigning "rhs", otherwise "rhs" + // could be used after free if it's an sub-Value of "this", + // hence the temporary danse. + GenericValue temp; + temp.RawAssign(rhs); + this->~GenericValue(); + RawAssign(temp); + } + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT { + return *this = rhs.Move(); + } +#endif + + //! Assignment of constant string reference (no copy) + /*! \param str Constant string reference to be assigned + \note This overload is needed to avoid clashes with the generic primitive type assignment overload below. + \see GenericStringRef, operator=(T) + */ + GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT { + GenericValue s(str); + return *this = s; + } + + //! Assignment with primitive types. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value The value to be assigned. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref SetString(const Ch*, Allocator&) (for copying) or + \ref StringRef() (to explicitly mark the pointer as constant) instead. + All other pointer types would implicitly convert to \c bool, + use \ref SetBool() instead. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (GenericValue&)) + operator=(T value) { + GenericValue v(value); + return *this = v; + } + + //! Deep-copy assignment from Value + /*! Assigns a \b copy of the Value to the current Value object + \tparam SourceAllocator Allocator type of \c rhs + \param rhs Value to copy from (read-only) + \param allocator Allocator to use for copying + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) + */ + template + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); + this->~GenericValue(); + new (this) GenericValue(rhs, allocator, copyConstStrings); + return *this; + } + + //! Exchange the contents of this value with those of other. + /*! + \param other Another value. + \note Constant complexity. + */ + GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT { + GenericValue temp; + temp.RawAssign(*this); + RawAssign(other); + other.RawAssign(temp); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Prepare Value for move semantics + /*! \return *this */ + GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } + //@} + + //!@name Equal-to and not-equal-to operators + //@{ + //! Equal-to operator + /*! + \note If an object contains duplicated named member, comparing equality with any object is always \c false. + \note Complexity is quadratic in Object's member number and linear for the rest (number of all values in the subtree and total lengths of all strings). + */ + template + bool operator==(const GenericValue& rhs) const { + typedef GenericValue RhsType; + if (GetType() != rhs.GetType()) + return false; + + switch (GetType()) { + case kObjectType: // Warning: O(n^2) inner-loop + if (data_.o.size != rhs.data_.o.size) + return false; + for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) { + typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name); + if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value) + return false; + } + return true; + + case kArrayType: + if (data_.a.size != rhs.data_.a.size) + return false; + for (SizeType i = 0; i < data_.a.size; i++) + if ((*this)[i] != rhs[i]) + return false; + return true; + + case kStringType: + return StringEqual(rhs); + + case kNumberType: + if (IsDouble() || rhs.IsDouble()) { + double a = GetDouble(); // May convert from integer to double. + double b = rhs.GetDouble(); // Ditto + return a >= b && a <= b; // Prevent -Wfloat-equal + } + else + return data_.n.u64 == rhs.data_.n.u64; + + default: + return true; + } + } + + //! Equal-to operator with const C-string pointer + bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); } + +#if RAPIDJSON_HAS_STDSTRING + //! Equal-to operator with string object + /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + bool operator==(const std::basic_string& rhs) const { return *this == GenericValue(StringRef(rhs)); } +#endif + + //! Equal-to operator with primitive types + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } + +#ifndef __cpp_impl_three_way_comparison + //! Not-equal-to operator + /*! \return !(*this == rhs) + */ + template + bool operator!=(const GenericValue& rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with const C-string pointer + bool operator!=(const Ch* rhs) const { return !(*this == rhs); } + + //! Not-equal-to operator with arbitrary types + /*! \return !(*this == rhs) + */ + template RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } + + //! Equal-to operator with arbitrary types (symmetric version) + /*! \return (rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } + + //! Not-Equal-to operator with arbitrary types (symmetric version) + /*! \return !(rhs == lhs) + */ + template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } + //@} +#endif + + //!@name Type + //@{ + + Type GetType() const { return static_cast(data_.f.flags & kTypeMask); } + bool IsNull() const { return data_.f.flags == kNullFlag; } + bool IsFalse() const { return data_.f.flags == kFalseFlag; } + bool IsTrue() const { return data_.f.flags == kTrueFlag; } + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } + bool IsObject() const { return data_.f.flags == kObjectFlag; } + bool IsArray() const { return data_.f.flags == kArrayFlag; } + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const { + if (!IsNumber()) return false; + if (IsUint64()) { + uint64_t u = GetUint64(); + volatile double d = static_cast(u); + return (d >= 0.0) + && (d < static_cast((std::numeric_limits::max)())) + && (u == static_cast(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast(i); + return (d >= static_cast((std::numeric_limits::min)())) + && (d < static_cast((std::numeric_limits::max)())) + && (i == static_cast(d)); + } + return true; // double, int, uint are always lossless + } + + // Checks whether a number is a float (possible lossy). + bool IsFloat() const { + if ((data_.f.flags & kDoubleFlag) == 0) + return false; + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); + if (a < static_cast(-(std::numeric_limits::max)()) + || a > static_cast((std::numeric_limits::max)())) + return false; + double b = static_cast(static_cast(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } + + //@} + + //!@name Null + //@{ + + GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; } + + //@} + + //!@name Bool + //@{ + + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } + //!< Set boolean value + /*! \post IsBool() == true */ + GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } + + //@} + + //!@name Object + //@{ + + //! Set this value as an empty object. + /*! \post IsObject() == true */ + GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; } + + //! Get the number of members in the object. + SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } + + //! Get the capacity of object. + SizeType MemberCapacity() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; } + + //! Check whether the object is empty. + bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType)) + \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7. + Since 0.2, if the name is not correct, it will assert. + If user is unsure whether a member exists, user should use HasMember() first. + A better approach is to use FindMember(). + \note Linear time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { + GenericValue n(StringRef(name)); + return (*this)[n]; + } + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*this)[name]; } + + //! Get a value from an object associated with the name. + /*! \pre IsObject() == true + \tparam SourceAllocator Allocator of the \c name value + + \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen(). + And it can also handle strings with embedded null characters. + + \note Linear time complexity. + */ + template + GenericValue& operator[](const GenericValue& name) { + MemberIterator member = FindMember(name); + if (member != MemberEnd()) + return member->value; + else { + RAPIDJSON_ASSERT(false); // see above note + +#if RAPIDJSON_HAS_CXX11 + // Use thread-local storage to prevent races between threads. + // Use static buffer and placement-new to prevent destruction, with + // alignas() to ensure proper alignment. + alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); +#elif defined(_MSC_VER) && _MSC_VER < 1900 + // There's no way to solve both thread locality and proper alignment + // simultaneously. + __declspec(thread) static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); +#elif defined(__GNUC__) || defined(__clang__) + // This will generate -Wexit-time-destructors in clang, but that's + // better than having under-alignment. + __thread static GenericValue buffer; + return buffer; +#else + // Don't know what compiler this is, so don't know how to ensure + // thread-locality. + static GenericValue buffer; + return buffer; +#endif + } + } + template + const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } + +#if RAPIDJSON_HAS_STDSTRING + //! Get a value from an object associated with name (string object). + GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } + const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } +#endif + + //! Const member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } + //! Const \em past-the-end member iterator + /*! \pre IsObject() == true */ + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } + //! Member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } + //! \em Past-the-end member iterator + /*! \pre IsObject() == true */ + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } + + //! Request the object to have enough capacity to store members. + /*! \param newCapacity The capacity that the object at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsObject()); + DoReserveMembers(newCapacity, allocator); + return *this; + } + + //! Check whether a member exists in the object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); } + +#if RAPIDJSON_HAS_STDSTRING + //! Check whether a member exists in the object with string object. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + bool HasMember(const std::basic_string& name) const { return FindMember(name) != MemberEnd(); } +#endif + + //! Check whether a member exists in the object with GenericValue name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Whether a member with that name exists. + \note It is better to use FindMember() directly if you need the obtain the value as well. + \note Linear time complexity. + */ + template + bool HasMember(const GenericValue& name) const { return FindMember(name) != MemberEnd(); } + + //! Find member by name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + MemberIterator FindMember(const Ch* name) { + GenericValue n(StringRef(name)); + return FindMember(n); + } + + ConstMemberIterator FindMember(const Ch* name) const { return const_cast(*this).FindMember(name); } + + //! Find member by name. + /*! + This version is faster because it does not need a StrLen(). It can also handle string with null character. + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + + \note Earlier versions of Rapidjson returned a \c NULL pointer, in case + the requested member doesn't exist. For consistency with e.g. + \c std::map, this has been changed to MemberEnd() now. + \note Linear time complexity. + */ + template + MemberIterator FindMember(const GenericValue& name) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + return DoFindMember(name); + } + template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } + +#if RAPIDJSON_HAS_STDSTRING + //! Find member by string object name. + /*! + \param name Member name to be searched. + \pre IsObject() == true + \return Iterator to member, if it exists. + Otherwise returns \ref MemberEnd(). + */ + MemberIterator FindMember(const std::basic_string& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(GenericValue(StringRef(name))); } +#endif + + //! Add a member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c name and \c value will be transferred to this object on success. + \pre IsObject() && name.IsString() + \post name.IsNull() && value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(name.IsString()); + DoAddMember(name, value, allocator); + return *this; + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Add a string object as member (name-value pair) to the object. + /*! \param name A string value as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(GenericValue& name, std::basic_string& value, Allocator& allocator) { + GenericValue v(value, allocator); + return AddMember(name, v, allocator); + } +#endif + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A string value as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(GenericValue& name, T value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) { + return AddMember(name, value, allocator); + } + GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + + //! Add a member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value Value of any type. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this object on success. + \pre IsObject() + \post value.IsNull() + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Add a constant string value as member (name-value pair) to the object. + /*! \param name A constant string reference as name of member. + \param value constant string reference as value of member. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below. + \note Amortized Constant time complexity. + */ + GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) { + GenericValue v(value); + return AddMember(name, v, allocator); + } + + //! Add any primitive value as member (name-value pair) to the object. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param name A constant string reference as name of member. + \param value Value of primitive type \c T as value of member + \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \pre IsObject() + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref + AddMember(StringRefType, StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized Constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + AddMember(StringRefType name, T value, Allocator& allocator) { + GenericValue n(name); + return AddMember(n, value, allocator); + } + + //! Remove all members in the object. + /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void RemoveAllMembers() { + RAPIDJSON_ASSERT(IsObject()); + DoClearMembers(); + } + + //! Remove a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Linear time complexity. + */ + bool RemoveMember(const Ch* name) { + GenericValue n(StringRef(name)); + return RemoveMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } +#endif + + template + bool RemoveMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + RemoveMember(m); + return true; + } + else + return false; + } + + //! Remove a member in object by iterator. + /*! \param m member iterator (obtained by FindMember() or MemberBegin()). + \return the new iterator after removal. + \note This function may reorder the object members. Use \ref + EraseMember(ConstMemberIterator) if you need to preserve the + relative order of the remaining members. + \note Constant time complexity. + */ + MemberIterator RemoveMember(MemberIterator m) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); + return DoRemoveMember(m); + } + + //! Remove a member from an object by iterator. + /*! \param pos iterator to the member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd() + \return Iterator following the removed element. + If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned. + \note This function preserves the relative order of the remaining object + members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator). + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator pos) { + return EraseMember(pos, pos +1); + } + + //! Remove members in the range [first, last) from an object. + /*! \param first iterator to the first member to remove + \param last iterator following the last member to remove + \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd() + \return Iterator following the last removed element. + \note This function preserves the relative order of the remaining object + members. + \note Linear time complexity. + */ + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { + RAPIDJSON_ASSERT(IsObject()); + RAPIDJSON_ASSERT(data_.o.size > 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); + RAPIDJSON_ASSERT(first >= MemberBegin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= MemberEnd()); + return DoEraseMembers(first, last); + } + + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template + bool EraseMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + Object GetObj() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + ConstObject GetObj() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + + //@} + + //!@name Array + //@{ + + //! Set this value as an empty array. + /*! \post IsArray == true */ + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + + //! Get the number of elements in array. + SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } + + //! Get the capacity of array. + SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; } + + //! Check whether the array is empty. + bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; } + + //! Remove all elements in the array. + /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged. + \note Linear time complexity. + */ + void Clear() { + RAPIDJSON_ASSERT(IsArray()); + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + data_.a.size = 0; + } + + //! Get an element from array by index. + /*! \pre IsArray() == true + \param index Zero-based index of element. + \see operator[](T*) + */ + GenericValue& operator[](SizeType index) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(index < data_.a.size); + return GetElementsPointer()[index]; + } + const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } + + //! Element iterator + /*! \pre IsArray() == true */ + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } + //! \em Past-the-end element iterator + /*! \pre IsArray() == true */ + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } + //! Constant element iterator + /*! \pre IsArray() == true */ + ConstValueIterator Begin() const { return const_cast(*this).Begin(); } + //! Constant \em past-the-end element iterator + /*! \pre IsArray() == true */ + ConstValueIterator End() const { return const_cast(*this).End(); } + + //! Request the array to have enough capacity to store elements. + /*! \param newCapacity The capacity that the array at least need to have. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \note Linear time complexity. + */ + GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (newCapacity > data_.a.capacity) { + SetElementsPointer(reinterpret_cast(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); + data_.a.capacity = newCapacity; + } + return *this; + } + + //! Append a GenericValue at the end of the array. + /*! \param value Value to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \post value.IsNull() == true + \return The value itself for fluent API. + \note The ownership of \c value will be transferred to this array on success. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + */ + GenericValue& PushBack(GenericValue& value, Allocator& allocator) { + RAPIDJSON_ASSERT(IsArray()); + if (data_.a.size >= data_.a.capacity) + Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); + GetElementsPointer()[data_.a.size++].RawAssign(value); + return *this; + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericValue& PushBack(GenericValue&& value, Allocator& allocator) { + return PushBack(value, allocator); + } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + + //! Append a constant string reference at the end of the array. + /*! \param value Constant string reference to be appended. + \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + \note Amortized constant time complexity. + \see GenericStringRef + */ + GenericValue& PushBack(StringRefType value, Allocator& allocator) { + return (*this).template PushBack(value, allocator); + } + + //! Append a primitive value at the end of the array. + /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t + \param value Value of primitive type T to be appended. + \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator(). + \pre IsArray() == true + \return The value itself for fluent API. + \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient. + + \note The source type \c T explicitly disallows all pointer types, + especially (\c const) \ref Ch*. This helps avoiding implicitly + referencing character strings with insufficient lifetime, use + \ref PushBack(GenericValue&, Allocator&) or \ref + PushBack(StringRefType, Allocator&). + All other pointer types would implicitly convert to \c bool, + use an explicit cast instead, if needed. + \note Amortized constant time complexity. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericValue&)) + PushBack(T value, Allocator& allocator) { + GenericValue v(value); + return PushBack(v, allocator); + } + + //! Remove the last element in the array. + /*! + \note Constant time complexity. + */ + GenericValue& PopBack() { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(!Empty()); + GetElementsPointer()[--data_.a.size].~GenericValue(); + return *this; + } + + //! Remove an element of array by iterator. + /*! + \param pos iterator to the element to remove + \pre IsArray() == true && \ref Begin() <= \c pos < \ref End() + \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator pos) { + return Erase(pos, pos + 1); + } + + //! Remove elements in the range [first, last) of the array. + /*! + \param first iterator to the first element to remove + \param last iterator following the last element to remove + \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End() + \return Iterator following the last removed element. + \note Linear time complexity. + */ + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { + RAPIDJSON_ASSERT(IsArray()); + RAPIDJSON_ASSERT(data_.a.size > 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); + RAPIDJSON_ASSERT(first >= Begin()); + RAPIDJSON_ASSERT(first <= last); + RAPIDJSON_ASSERT(last <= End()); + ValueIterator pos = Begin() + (first - Begin()); + for (ValueIterator itr = pos; itr != last; ++itr) + itr->~GenericValue(); + std::memmove(static_cast(pos), last, static_cast(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast(last - first); + return pos; + } + + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + + //@} + + //!@name Number + //@{ + + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ + double GetDouble() const { + RAPIDJSON_ASSERT(IsNumber()); + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((data_.f.flags & kInt64Flag) != 0) return static_cast(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) + } + + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const { + return static_cast(GetDouble()); + } + + GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } + GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; } + GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } + GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } + GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast(f)); return *this; } + + //@} + + //!@name String + //@{ + + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return DataString(data_); } + + //! Get the length of string. + /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). + */ + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return DataStringLength(data_); } + + //! Set this value as a string without copying source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string pointer. + \param length The length of source string, excluding the trailing null terminator. + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == length + \see SetString(StringRefType) + */ + GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); } + + //! Set this value as a string without copying source string. + /*! \param s source string reference + \return The value itself for fluent API. + \post IsString() == true && GetString() == s && GetStringLength() == s.length + */ + GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; } + + //! Set this value as a string by copying from source string. + /*! This version has better performance with supplied length, and also support string containing null character. + \param s source string. + \param length The length of source string, excluding the trailing null terminator. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string reference + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; } + +#if RAPIDJSON_HAS_STDSTRING + //! Set this value as a string by copying from source string. + /*! \param s source string. + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(StringRef(s), allocator); } +#endif + + //@} + + //!@name Array + //@{ + + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string + */ + template + bool Is() const { return internal::TypeHelper::Is(*this); } + + template + T Get() const { return internal::TypeHelper::Get(*this); } + + template + T Get() { return internal::TypeHelper::Get(*this); } + + template + ValueType& Set(const T& data) { return internal::TypeHelper::Set(*this, data); } + + template + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper::Set(*this, data, allocator); } + + //@} + + //! Generate events of this value to a Handler. + /*! This function adopts the GoF visitor pattern. + Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. + It can also be used to deep clone this value via GenericDocument, which is also a Handler. + \tparam Handler type of handler. + \param handler An object implementing concept Handler. + */ + template + bool Accept(Handler& handler) const { + switch(GetType()) { + case kNullType: return handler.Null(); + case kFalseType: return handler.Bool(false); + case kTrueType: return handler.Bool(true); + + case kObjectType: + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + return false; + for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { + RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) + return false; + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) + return false; + } + return handler.EndObject(data_.o.size); + + case kArrayType: + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + return false; + for (ConstValueIterator v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) + return false; + return handler.EndArray(data_.a.size); + + case kStringType: + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); + + default: + RAPIDJSON_ASSERT(GetType() == kNumberType); + if (IsDouble()) return handler.Double(data_.n.d); + else if (IsInt()) return handler.Int(data_.n.i.i); + else if (IsUint()) return handler.Uint(data_.n.u.u); + else if (IsInt64()) return handler.Int64(data_.n.i64); + else return handler.Uint64(data_.n.u64); + } + } + +private: + template friend class GenericValue; + template friend class GenericDocument; + + enum { + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, + + // Initial flags of different types. + kNullFlag = kNullType, + // These casts are added to suppress the warning on MSVC about bitwise operations between enums of different types. + kTrueFlag = static_cast(kTrueType) | static_cast(kBoolFlag), + kFalseFlag = static_cast(kFalseType) | static_cast(kBoolFlag), + kNumberIntFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag), + kNumberUintFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag), + kNumberInt64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kInt64Flag), + kNumberUint64Flag = static_cast(kNumberType) | static_cast(kNumberFlag | kUint64Flag), + kNumberDoubleFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kDoubleFlag), + kNumberAnyFlag = static_cast(kNumberType) | static_cast(kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag), + kConstStringFlag = static_cast(kStringType) | static_cast(kStringFlag), + kCopyStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag), + kShortStringFlag = static_cast(kStringType) | static_cast(kStringFlag | kCopyFlag | kInlineStrFlag), + kObjectFlag = kObjectType, + kArrayFlag = kArrayType, + + kTypeMask = 0x07 + }; + + static const SizeType kDefaultArrayCapacity = RAPIDJSON_VALUE_DEFAULT_ARRAY_CAPACITY; + static const SizeType kDefaultObjectCapacity = RAPIDJSON_VALUE_DEFAULT_OBJECT_CAPACITY; + + struct Flag { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer +#elif RAPIDJSON_64BIT + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes +#else + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes +#endif + uint16_t flags; + }; + + struct String { + SizeType length; + SizeType hashcode; //!< reserved + const Ch* str; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars + // (excluding the terminating zero) and store a value to determine the length of the contained + // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string + // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as + // the string terminator as well. For getting the string length back from that value just use + // "MaxSize - str[LenPos]". + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). + struct ShortString { + enum { MaxChars = sizeof(static_cast(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + Ch str[MaxChars]; + + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast(MaxSize - len); } + inline SizeType GetLength() const { return static_cast(MaxSize - str[LenPos]); } + }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + // By using proper binary layout, retrieval of different integer types do not need conversions. + union Number { +#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN + struct I { + int i; + char padding[4]; + }i; + struct U { + unsigned u; + char padding2[4]; + }u; +#else + struct I { + char padding[4]; + int i; + }i; + struct U { + char padding2[4]; + unsigned u; + }u; +#endif + int64_t i64; + uint64_t u64; + double d; + }; // 8 bytes + + struct ObjectData { + SizeType size; + SizeType capacity; + Member* members; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + struct ArrayData { + SizeType size; + SizeType capacity; + GenericValue* elements; + }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + + union Data { + String s; + ShortString ss; + Number n; + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + + static RAPIDJSON_FORCEINLINE const Ch* DataString(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.str : RAPIDJSON_GETPOINTER(Ch, data.s.str); + } + static RAPIDJSON_FORCEINLINE SizeType DataStringLength(const Data& data) { + return (data.f.flags & kInlineStrFlag) ? data.ss.GetLength() : data.s.length; + } + + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } + +#if RAPIDJSON_USE_MEMBERSMAP + + struct MapTraits { + struct Less { + bool operator()(const Data& s1, const Data& s2) const { + SizeType n1 = DataStringLength(s1), n2 = DataStringLength(s2); + int cmp = std::memcmp(DataString(s1), DataString(s2), sizeof(Ch) * (n1 < n2 ? n1 : n2)); + return cmp < 0 || (cmp == 0 && n1 < n2); + } + }; + typedef std::pair Pair; + typedef std::multimap > Map; + typedef typename Map::iterator Iterator; + }; + typedef typename MapTraits::Map Map; + typedef typename MapTraits::Less MapLess; + typedef typename MapTraits::Pair MapPair; + typedef typename MapTraits::Iterator MapIterator; + + // + // Layout of the members' map/array, re(al)located according to the needed capacity: + // + // {Map*}<>{capacity}<>{Member[capacity]}<>{MapIterator[capacity]} + // + // (where <> stands for the RAPIDJSON_ALIGN-ment, if needed) + // + + static RAPIDJSON_FORCEINLINE size_t GetMapLayoutSize(SizeType capacity) { + return RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(capacity * sizeof(Member)) + + capacity * sizeof(MapIterator); + } + + static RAPIDJSON_FORCEINLINE SizeType &GetMapCapacity(Map* &map) { + return *reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + static RAPIDJSON_FORCEINLINE Member* GetMapMembers(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType))); + } + + static RAPIDJSON_FORCEINLINE MapIterator* GetMapIterators(Map* &map) { + return reinterpret_cast(reinterpret_cast(&map) + + RAPIDJSON_ALIGN(sizeof(Map*)) + + RAPIDJSON_ALIGN(sizeof(SizeType)) + + RAPIDJSON_ALIGN(GetMapCapacity(map) * sizeof(Member))); + } + + static RAPIDJSON_FORCEINLINE Map* &GetMap(Member* members) { + RAPIDJSON_ASSERT(members != 0); + return *reinterpret_cast(reinterpret_cast(members) - + RAPIDJSON_ALIGN(sizeof(SizeType)) - + RAPIDJSON_ALIGN(sizeof(Map*))); + } + + // Some compilers' debug mechanisms want all iterators to be destroyed, for their accounting.. + RAPIDJSON_FORCEINLINE MapIterator DropMapIterator(MapIterator& rhs) { +#if RAPIDJSON_HAS_CXX11 + MapIterator ret = std::move(rhs); +#else + MapIterator ret = rhs; +#endif + rhs.~MapIterator(); + return ret; + } + + Map* &DoReallocMap(Map** oldMap, SizeType newCapacity, Allocator& allocator) { + Map **newMap = static_cast(allocator.Malloc(GetMapLayoutSize(newCapacity))); + GetMapCapacity(*newMap) = newCapacity; + if (!oldMap) { + *newMap = new (allocator.Malloc(sizeof(Map))) Map(MapLess(), allocator); + } + else { + *newMap = *oldMap; + size_t count = (*oldMap)->size(); + std::memcpy(static_cast(GetMapMembers(*newMap)), + static_cast(GetMapMembers(*oldMap)), + count * sizeof(Member)); + MapIterator *oldIt = GetMapIterators(*oldMap), + *newIt = GetMapIterators(*newMap); + while (count--) { + new (&newIt[count]) MapIterator(DropMapIterator(oldIt[count])); + } + Allocator::Free(oldMap); + } + return *newMap; + } + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return GetMapMembers(DoReallocMap(0, capacity, allocator)); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* oldMembers = GetMembersPointer(); + Map **oldMap = oldMembers ? &GetMap(oldMembers) : 0, + *&newMap = DoReallocMap(oldMap, newCapacity, allocator); + RAPIDJSON_SETPOINTER(Member, o.members, GetMapMembers(newMap)); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator mit = map->find(reinterpret_cast(name.data_)); + if (mit != map->end()) { + return MemberIterator(&members[mit->second]); + } + } + return MemberEnd(); + } + + void DoClearMembers() { + if (Member* members = GetMembersPointer()) { + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < data_.o.size; i++) { + map->erase(DropMapIterator(mit[i])); + members[i].~Member(); + } + data_.o.size = 0; + } + } + + void DoFreeMembers() { + if (Member* members = GetMembersPointer()) { + GetMap(members)->~Map(); + for (SizeType i = 0; i < data_.o.size; i++) { + members[i].~Member(); + } + if (Allocator::kNeedFree) { // Shortcut by Allocator's trait + Map** map = &GetMap(members); + Allocator::Free(*map); + Allocator::Free(map); + } + } + } + +#else // !RAPIDJSON_USE_MEMBERSMAP + + RAPIDJSON_FORCEINLINE Member* DoAllocMembers(SizeType capacity, Allocator& allocator) { + return Malloc(allocator, capacity); + } + + void DoReserveMembers(SizeType newCapacity, Allocator& allocator) { + ObjectData& o = data_.o; + if (newCapacity > o.capacity) { + Member* newMembers = Realloc(allocator, GetMembersPointer(), o.capacity, newCapacity); + RAPIDJSON_SETPOINTER(Member, o.members, newMembers); + o.capacity = newCapacity; + } + } + + template + MemberIterator DoFindMember(const GenericValue& name) { + MemberIterator member = MemberBegin(); + for ( ; member != MemberEnd(); ++member) + if (name.StringEqual(member->name)) + break; + return member; + } + + void DoClearMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + data_.o.size = 0; + } + + void DoFreeMembers() { + for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) + m->~Member(); + Allocator::Free(GetMembersPointer()); + } + +#endif // !RAPIDJSON_USE_MEMBERSMAP + + void DoAddMember(GenericValue& name, GenericValue& value, Allocator& allocator) { + ObjectData& o = data_.o; + if (o.size >= o.capacity) + DoReserveMembers(o.capacity ? (o.capacity + (o.capacity + 1) / 2) : kDefaultObjectCapacity, allocator); + Member* members = GetMembersPointer(); + Member* m = members + o.size; + m->name.RawAssign(name); + m->value.RawAssign(value); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + new (&mit[o.size]) MapIterator(map->insert(MapPair(m->name.data_, o.size))); +#endif + ++o.size; + } + + MemberIterator DoRemoveMember(MemberIterator m) { + ObjectData& o = data_.o; + Member* members = GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(members); + MapIterator* mit = GetMapIterators(map); + SizeType mpos = static_cast(&*m - members); + map->erase(DropMapIterator(mit[mpos])); +#endif + MemberIterator last(members + (o.size - 1)); + if (o.size > 1 && m != last) { +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[mpos]) MapIterator(DropMapIterator(mit[&*last - members])); + mit[mpos]->second = mpos; +#endif + *m = *last; // Move the last one to this place + } + else { + m->~Member(); // Only one left, just destroy + } + --o.size; + return m; + } + + MemberIterator DoEraseMembers(ConstMemberIterator first, ConstMemberIterator last) { + ObjectData& o = data_.o; + MemberIterator beg = MemberBegin(), + pos = beg + (first - beg), + end = MemberEnd(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(GetMembersPointer()); + MapIterator* mit = GetMapIterators(map); +#endif + for (MemberIterator itr = pos; itr != last; ++itr) { +#if RAPIDJSON_USE_MEMBERSMAP + map->erase(DropMapIterator(mit[itr - beg])); +#endif + itr->~Member(); + } +#if RAPIDJSON_USE_MEMBERSMAP + if (first != last) { + // Move remaining members/iterators + MemberIterator next = pos + (last - first); + for (MemberIterator itr = pos; next != end; ++itr, ++next) { + std::memcpy(static_cast(&*itr), &*next, sizeof(Member)); + SizeType mpos = static_cast(itr - beg); + new (&mit[mpos]) MapIterator(DropMapIterator(mit[next - beg])); + mit[mpos]->second = mpos; + } + } +#else + std::memmove(static_cast(&*pos), &*last, + static_cast(end - last) * sizeof(Member)); +#endif + o.size -= static_cast(last - first); + return pos; + } + + template + void DoCopyMembers(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings) { + RAPIDJSON_ASSERT(rhs.GetType() == kObjectType); + + data_.f.flags = kObjectFlag; + SizeType count = rhs.data_.o.size; + Member* lm = DoAllocMembers(count, allocator); + const typename GenericValue::Member* rm = rhs.GetMembersPointer(); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(lm); + MapIterator* mit = GetMapIterators(map); +#endif + for (SizeType i = 0; i < count; i++) { + new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings); + new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings); +#if RAPIDJSON_USE_MEMBERSMAP + new (&mit[i]) MapIterator(map->insert(MapPair(lm[i].name.data_, i))); +#endif + } + data_.o.size = data_.o.capacity = count; + SetMembersPointer(lm); + } + + // Initialize this value as array with initial data, without calling destructor. + void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { + data_.f.flags = kArrayFlag; + if (count) { + GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(static_cast(e), values, count * sizeof(GenericValue)); + } + else + SetElementsPointer(0); + data_.a.size = data_.a.capacity = count; + } + + //! Initialize this value as object with initial data, without calling destructor. + void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { + data_.f.flags = kObjectFlag; + if (count) { + Member* m = DoAllocMembers(count, allocator); + SetMembersPointer(m); + std::memcpy(static_cast(m), members, count * sizeof(Member)); +#if RAPIDJSON_USE_MEMBERSMAP + Map* &map = GetMap(m); + MapIterator* mit = GetMapIterators(map); + for (SizeType i = 0; i < count; i++) { + new (&mit[i]) MapIterator(map->insert(MapPair(m[i].name.data_, i))); + } +#endif + } + else + SetMembersPointer(0); + data_.o.size = data_.o.capacity = count; + } + + //! Initialize this value as constant string, without calling destructor. + void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { + data_.f.flags = kConstStringFlag; + SetStringPointer(s); + data_.s.length = s.length; + } + + //! Initialize this value as copy string with initial data, without calling destructor. + void SetStringRaw(StringRefType s, Allocator& allocator) { + Ch* str = 0; + if (ShortString::Usable(s.length)) { + data_.f.flags = kShortStringFlag; + data_.ss.SetLength(s.length); + str = data_.ss.str; + } else { + data_.f.flags = kCopyStringFlag; + data_.s.length = s.length; + str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); + } + std::memcpy(str, s, s.length * sizeof(Ch)); + str[s.length] = '\0'; + } + + //! Assignment without calling destructor + void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { + data_ = rhs.data_; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; + } + + template + bool StringEqual(const GenericValue& rhs) const { + RAPIDJSON_ASSERT(IsString()); + RAPIDJSON_ASSERT(rhs.IsString()); + + const SizeType len1 = GetStringLength(); + const SizeType len2 = rhs.GetStringLength(); + if(len1 != len2) { return false; } + + const Ch* const str1 = GetString(); + const Ch* const str2 = rhs.GetString(); + if(str1 == str2) { return true; } // fast path for constant string + + return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0); + } + + Data data_; +}; + +//! GenericValue with UTF8 encoding +typedef GenericValue > Value; + +/////////////////////////////////////////////////////////////////////////////// +// GenericDocument + +//! A document for parsing JSON text as DOM. +/*! + \note implements Handler concept + \tparam Encoding Encoding for both parsing and string storage. + \tparam Allocator Allocator for allocating memory for the DOM + \tparam StackAllocator Allocator for allocating memory for stack during parsing. + \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue. +*/ +template +class GenericDocument : public GenericValue { +public: + typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. + typedef GenericValue ValueType; //!< Value type of the document. + typedef Allocator AllocatorType; //!< Allocator type from template parameter. + typedef StackAllocator StackAllocatorType; //!< StackAllocator type from template parameter. + + //! Constructor + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(std::move(rhs.stack_)), + parseResult_(rhs.parseResult_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + } +#endif + + ~GenericDocument() { + // Clear the ::ValueType before ownAllocator is destroyed, ~ValueType() + // runs last and may access its elements or members which would be freed + // with an allocator like MemoryPoolAllocator (CrtAllocator does not + // free its data when destroyed, but MemoryPoolAllocator does). + if (ownAllocator_) { + ValueType::SetNull(); + } + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move assignment in C++11 + GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT + { + // The cast to ValueType is necessary here, because otherwise it would + // attempt to call GenericValue's templated assignment operator. + ValueType::operator=(std::forward(rhs)); + + // Calling the destructor here would prematurely call stack_'s destructor + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = std::move(rhs.stack_); + parseResult_ = rhs.parseResult_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.parseResult_ = ParseResult(); + + return *this; + } +#endif + + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + // Allow Swap with ValueType. + // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names. + using ValueType::Swap; + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with bool f(Handler) prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template + GenericDocument& Populate(Generator& g) { + ClearStackOnExit scope(*this); + if (g(*this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //!@name Parse from stream + //!@{ + + //! Parse JSON text from an input stream (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam SourceEncoding Encoding of input stream + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); + ClearStackOnExit scope(*this); + parseResult_ = reader.template Parse(is, *this); + if (parseResult_) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + + //! Parse JSON text from an input stream + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + + //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \param is Input stream to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); + } + //!@} + + //!@name Parse in-place from mutable string + //!@{ + + //! Parse JSON text from a mutable string + /*! \tparam parseFlags Combination of \ref ParseFlag. + \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + template + GenericDocument& ParseInsitu(Ch* str) { + GenericInsituStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) + /*! \param str Mutable zero-terminated string to be parsed. + \return The document itself for fluent API. + */ + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); + } + //!@} + + //!@name Parse from read-only string + //!@{ + + //! Parse JSON text from a read-only string (with Encoding conversion) + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \tparam SourceEncoding Transcoding from input Encoding + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + GenericStringStream s(str); + return ParseStream(s); + } + + //! Parse JSON text from a read-only string + /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). + \param str Read-only zero-terminated string to be parsed. + */ + template + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) + /*! \param str Read-only zero-terminated string to be parsed. + */ + GenericDocument& Parse(const Ch* str) { + return Parse(str); + } + + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(reinterpret_cast(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream is(ms); + ParseStream(is); + return *this; + } + + template + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template + GenericDocument& Parse(const std::basic_string& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse(str.c_str()); + } + + template + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str); + } +#endif // RAPIDJSON_HAS_STDSTRING + + //!@} + + //!@name Handling parse errors + //!@{ + + //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseError() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + + //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ +#endif + operator ParseResult() const { return parseResult_; } + //!@} + + //! Get the allocator of this document. + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + //! Get the capacity of stack in bytes. + size_t GetStackCapacity() const { return stack_.GetCapacity(); } + +private: + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericDocument& d) : d_(d) {} + ~ClearStackOnExit() { d_.ClearStack(); } + private: + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + GenericDocument& d_; + }; + + // callers of the following private Handler functions + // template friend class GenericReader; // for parsing + template friend class GenericValue; // for deep copying + +public: + // Implementation of Handler + bool Null() { new (stack_.template Push()) ValueType(); return true; } + bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } + bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } + bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } + bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool String(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + + bool StartObject() { new (stack_.template Push()) ValueType(kObjectType); return true; } + + bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); } + + bool EndObject(SizeType memberCount) { + typename ValueType::Member* members = stack_.template Pop(memberCount); + stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); + return true; + } + + bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } + + bool EndArray(SizeType elementCount) { + ValueType* elements = stack_.template Pop(elementCount); + stack_.template Top()->SetArrayRaw(elements, elementCount, GetAllocator()); + return true; + } + +private: + //! Prohibit copying + GenericDocument(const GenericDocument&); + //! Prohibit assignment + GenericDocument& operator=(const GenericDocument&); + + void ClearStack() { + if (Allocator::kNeedFree) + while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects) + (stack_.template Pop(1))->~ValueType(); + else + stack_.Clear(); + stack_.ShrinkToFit(); + } + + void Destroy() { + RAPIDJSON_DELETE(ownAllocator_); + } + + static const size_t kDefaultStackCapacity = 1024; + Allocator* allocator_; + Allocator* ownAllocator_; + internal::Stack stack_; + ParseResult parseResult_; +}; + +//! GenericDocument with UTF8 encoding +typedef GenericDocument > Document; + + +//! Helper class for accessing Value of array type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetArray(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericArray { +public: + typedef GenericArray ConstArray; + typedef GenericArray Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + + template + friend class GenericValue; + + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + + operator ValueType&() const { return value_; } + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } + void Clear() const { value_.Clear(); } + ValueType& operator[](SizeType index) const { return value_[index]; } + ValueIterator Begin() const { return value_.Begin(); } + ValueIterator End() const { return value_.End(); } + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PopBack() const { value_.PopBack(); return *this; } + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + ValueIterator begin() const { return value_.Begin(); } + ValueIterator end() const { return value_.End(); } +#endif + +private: + GenericArray(); + GenericArray(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +//! Helper class for accessing Value of object type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetObject(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericObject { +public: + typedef GenericObject ConstObject; + typedef GenericObject Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef GenericMemberIterator MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template + friend class GenericValue; + + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + + operator ValueType&() const { return value_; } + SizeType MemberCount() const { return value_.MemberCount(); } + SizeType MemberCapacity() const { return value_.MemberCapacity(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template ValueType& operator[](T* name) const { return value_[name]; } + template ValueType& operator[](const GenericValue& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string& name) const { return value_[name]; } +#endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } + GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string& name) const { return value_.HasMember(name); } +#endif + template bool HasMember(const GenericValue& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template MemberIterator FindMember(const GenericValue& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string& name) const { return value_.FindMember(name); } +#endif + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_STDSTRING + GenericObject AddMember(ValueType& name, std::basic_string& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + void RemoveAllMembers() { value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) const { return value_.RemoveMember(name); } +#endif + template bool RemoveMember(const GenericValue& name) const { return value_.RemoveMember(name); } + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template bool EraseMember(const GenericValue& name) const { return value_.EraseMember(name); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + MemberIterator begin() const { return value_.MemberBegin(); } + MemberIterator end() const { return value_.MemberEnd(); } +#endif + +private: + GenericObject(); + GenericObject(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#ifdef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#pragma pop_macro("GetObject") +#undef RAPIDJSON_WINDOWS_GETOBJECT_WORKAROUND_APPLIED +#endif + +#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/deps/rapidjson/include/rapidjson/encodedstream.h b/deps/rapidjson/include/rapidjson/encodedstream.h new file mode 100644 index 0000000..cf046b8 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/encodedstream.h @@ -0,0 +1,299 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODEDSTREAM_H_ +#define RAPIDJSON_ENCODEDSTREAM_H_ + +#include "stream.h" +#include "memorystream.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Input byte stream wrapper with a statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam InputByteStream Type of input byte stream. For example, FileReadStream. +*/ +template +class EncodedInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedInputStream(InputByteStream& is) : is_(is) { + current_ = Encoding::TakeBOM(is_); + } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); + + InputByteStream& is_; + Ch current_; +}; + +//! Specialized for UTF8 MemoryStream. +template <> +class EncodedInputStream, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBFu) is_.Take(); + } + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() { return 0; } + size_t PutEnd(Ch*) { return 0; } + + MemoryStream& is_; + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); +}; + +//! Output byte stream wrapper with statically bound encoding. +/*! + \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. + \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. +*/ +template +class EncodedOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef typename Encoding::Ch Ch; + + EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) { + if (putBOM) + Encoding::PutBOM(os_); + } + + void Put(Ch c) { Encoding::Put(os_, c); } + void Flush() { os_.Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + EncodedOutputStream(const EncodedOutputStream&); + EncodedOutputStream& operator=(const EncodedOutputStream&); + + OutputByteStream& os_; +}; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + +//! Input stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for reading. + \tparam InputByteStream type of input byte stream to be wrapped. +*/ +template +class AutoUTFInputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param is input stream to be wrapped. + \param type UTF encoding type if it is not detected from the stream. + */ + AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + DetectType(); + static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) }; + takeFunc_ = f[type_]; + current_ = takeFunc_(*is_); + } + + UTFType GetType() const { return type_; } + bool HasBOM() const { return hasBOM_; } + + Ch Peek() const { return current_; } + Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; } + size_t Tell() const { return is_->Tell(); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFInputStream(const AutoUTFInputStream&); + AutoUTFInputStream& operator=(const AutoUTFInputStream&); + + // Detect encoding type with BOM or RFC 4627 + void DetectType() { + // BOM (Byte Order Mark): + // 00 00 FE FF UTF-32BE + // FF FE 00 00 UTF-32LE + // FE FF UTF-16BE + // FF FE UTF-16LE + // EF BB BF UTF-8 + + const unsigned char* c = reinterpret_cast(is_->Peek4()); + if (!c) + return; + + unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); + hasBOM_ = false; + if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); } + else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); } + + // RFC 4627: Section 3 + // "Since the first two characters of a JSON text will always be ASCII + // characters [RFC0020], it is possible to determine whether an octet + // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking + // at the pattern of nulls in the first four octets." + // 00 00 00 xx UTF-32BE + // 00 xx 00 xx UTF-16BE + // xx 00 00 00 UTF-32LE + // xx 00 xx 00 UTF-16LE + // xx xx xx xx UTF-8 + + if (!hasBOM_) { + int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + switch (pattern) { + case 0x08: type_ = kUTF32BE; break; + case 0x0A: type_ = kUTF16BE; break; + case 0x01: type_ = kUTF32LE; break; + case 0x05: type_ = kUTF16LE; break; + case 0x0F: type_ = kUTF8; break; + default: break; // Use type defined by user. + } + } + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + } + + typedef Ch (*TakeFunc)(InputByteStream& is); + InputByteStream* is_; + UTFType type_; + Ch current_; + TakeFunc takeFunc_; + bool hasBOM_; +}; + +//! Output stream wrapper with dynamically bound encoding and automatic encoding detection. +/*! + \tparam CharType Type of character for writing. + \tparam OutputByteStream type of output byte stream to be wrapped. +*/ +template +class AutoUTFOutputStream { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); +public: + typedef CharType Ch; + + //! Constructor. + /*! + \param os output stream to be wrapped. + \param type UTF encoding type. + \param putBOM Whether to write BOM at the beginning of the stream. + */ + AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) { + RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE); + + // Runtime check whether the size of character type is sufficient. It only perform checks with assertion. + if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2); + if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4); + + static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) }; + putFunc_ = f[type_]; + + if (putBOM) + PutBOM(); + } + + UTFType GetType() const { return type_; } + + void Put(Ch c) { putFunc_(*os_, c); } + void Flush() { os_->Flush(); } + + // Not implemented + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + AutoUTFOutputStream(const AutoUTFOutputStream&); + AutoUTFOutputStream& operator=(const AutoUTFOutputStream&); + + void PutBOM() { + typedef void (*PutBOMFunc)(OutputByteStream&); + static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) }; + f[type_](*os_); + } + + typedef void (*PutFunc)(OutputByteStream&, Ch); + + OutputByteStream* os_; + UTFType type_; + PutFunc putFunc_; +}; + +#undef RAPIDJSON_ENCODINGS_FUNC + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/deps/rapidjson/include/rapidjson/encodings.h b/deps/rapidjson/include/rapidjson/encodings.h new file mode 100644 index 0000000..50ad18b --- /dev/null +++ b/deps/rapidjson/include/rapidjson/encodings.h @@ -0,0 +1,716 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ENCODINGS_H_ +#define RAPIDJSON_ENCODINGS_H_ + +#include "rapidjson.h" + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#elif defined(__GNUC__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(overflow) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Encoding + +/*! \class rapidjson::Encoding + \brief Concept for encoding of Unicode characters. + +\code +concept Encoding { + typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition. + + enum { supportUnicode = 1 }; // or 0 if not supporting unicode + + //! \brief Encode a Unicode codepoint to an output stream. + //! \param os Output stream. + //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively. + template + static void Encode(OutputStream& os, unsigned codepoint); + + //! \brief Decode a Unicode codepoint from an input stream. + //! \param is Input stream. + //! \param codepoint Output of the unicode codepoint. + //! \return true if a valid codepoint can be decoded from the stream. + template + static bool Decode(InputStream& is, unsigned* codepoint); + + //! \brief Validate one Unicode codepoint from an encoded stream. + //! \param is Input stream to obtain codepoint. + //! \param os Output for copying one codepoint. + //! \return true if it is valid. + //! \note This function just validating and copying the codepoint without actually decode it. + template + static bool Validate(InputStream& is, OutputStream& os); + + // The following functions are deal with byte streams. + + //! Take a character from input byte stream, skip BOM if exist. + template + static CharType TakeBOM(InputByteStream& is); + + //! Take a character from input byte stream. + template + static Ch Take(InputByteStream& is); + + //! Put BOM to output byte stream. + template + static void PutBOM(OutputByteStream& os); + + //! Put a character to output byte stream. + template + static void Put(OutputByteStream& os, Ch c); +}; +\endcode +*/ + +/////////////////////////////////////////////////////////////////////////////// +// UTF8 + +//! UTF-8 encoding. +/*! http://en.wikipedia.org/wiki/UTF-8 + http://tools.ietf.org/html/rfc3629 + \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char. + \note implements Encoding concept +*/ +template +struct UTF8 { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + os.Put(static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + os.Put(static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { +#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + typename InputStream::Ch c = is.Take(); + if (!(c & 0x80)) { + *codepoint = static_cast(c); + return true; + } + + unsigned char type = GetRange(static_cast(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFFu >> type) & static_cast(c); + } + bool result = true; + switch (type) { + case 2: RAPIDJSON_TAIL(); return result; + case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; + case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; + case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +#undef RAPIDJSON_COPY +#undef RAPIDJSON_TRANS +#undef RAPIDJSON_TAIL + } + + template + static bool Validate(InputStream& is, OutputStream& os) { +#define RAPIDJSON_COPY() os.Put(c = is.Take()) +#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) +#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70) + Ch c; + RAPIDJSON_COPY(); + if (!(c & 0x80)) + return true; + + bool result = true; + switch (GetRange(static_cast(c))) { + case 2: RAPIDJSON_TAIL(); return result; + case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result; + case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result; + case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result; + default: return false; + } +#undef RAPIDJSON_COPY +#undef RAPIDJSON_TRANS +#undef RAPIDJSON_TAIL + } + + static unsigned char GetRange(unsigned char c) { + // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ + // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types. + static const unsigned char type[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + }; + return type[c]; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + typename InputByteStream::Ch c = Take(is); + if (static_cast(c) != 0xEFu) return c; + c = is.Take(); + if (static_cast(c) != 0xBBu) return c; + c = is.Take(); + if (static_cast(c) != 0xBFu) return c; + c = is.Take(); + return c; + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xEFu)); + os.Put(static_cast(0xBBu)); + os.Put(static_cast(0xBFu)); + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF16 + +//! UTF-16 encoding. +/*! http://en.wikipedia.org/wiki/UTF-16 + http://tools.ietf.org/html/rfc2781 + \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF16LE and UTF16BE, which handle endianness. +*/ +template +struct UTF16 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + os.Put(static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + os.Put(static_cast((v >> 10) | 0xD800)); + os.Put(static_cast((v & 0x3FF) | 0xDC00)); + } + } + + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + PutUnsafe(os, static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast((v >> 10) | 0xD800)); + PutUnsafe(os, static_cast((v & 0x3FF) | 0xDC00)); + } + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + typename InputStream::Ch c = is.Take(); + if (c < 0xD800 || c > 0xDFFF) { + *codepoint = static_cast(c); + return true; + } + else if (c <= 0xDBFF) { + *codepoint = (static_cast(c) & 0x3FF) << 10; + c = is.Take(); + *codepoint |= (static_cast(c) & 0x3FF); + *codepoint += 0x10000; + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + typename InputStream::Ch c; + os.Put(static_cast(c = is.Take())); + if (c < 0xD800 || c > 0xDFFF) + return true; + else if (c <= 0xDBFF) { + os.Put(c = is.Take()); + return c >= 0xDC00 && c <= 0xDFFF; + } + return false; + } +}; + +//! UTF-16 little endian encoding. +template +struct UTF16LE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(static_cast(c) & 0xFFu)); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + } +}; + +//! UTF-16 big endian encoding. +template +struct UTF16BE : UTF16 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0xFEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + os.Put(static_cast(static_cast(c) & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// UTF32 + +//! UTF-32 encoding. +/*! http://en.wikipedia.org/wiki/UTF-32 + \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead. + \note implements Encoding concept + + \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness. + For streaming, use UTF32LE and UTF32BE, which handle endianness. +*/ +template +struct UTF32 { + typedef CharType Ch; + RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); + + enum { supportUnicode = 1 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + os.Put(codepoint); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c = is.Take(); + *codepoint = c; + return c <= 0x10FFFF; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); + Ch c; + os.Put(c = is.Take()); + return c <= 0x10FFFF; + } +}; + +//! UTF-32 little endian enocoding. +template +struct UTF32LE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 24; + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 24) & 0xFFu)); + } +}; + +//! UTF-32 big endian encoding. +template +struct UTF32BE : UTF32 { + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + CharType c = Take(is); + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; + } + + template + static CharType Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + unsigned c = static_cast(static_cast(is.Take())) << 24; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); + } + + template + static void Put(OutputByteStream& os, CharType c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast((c >> 24) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast(c & 0xFFu)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// ASCII + +//! ASCII encoding. +/*! http://en.wikipedia.org/wiki/ASCII + \tparam CharType Code unit for storing 7-bit ASCII data. Default is char. + \note implements Encoding concept +*/ +template +struct ASCII { + typedef CharType Ch; + + enum { supportUnicode = 0 }; + + template + static void Encode(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + os.Put(static_cast(codepoint & 0xFF)); + } + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast(codepoint & 0xFF)); + } + + template + static bool Decode(InputStream& is, unsigned* codepoint) { + uint8_t c = static_cast(is.Take()); + *codepoint = c; + return c <= 0X7F; + } + + template + static bool Validate(InputStream& is, OutputStream& os) { + uint8_t c = static_cast(is.Take()); + os.Put(static_cast(c)); + return c <= 0x7F; + } + + template + static CharType TakeBOM(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + uint8_t c = static_cast(Take(is)); + return static_cast(c); + } + + template + static Ch Take(InputByteStream& is) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); + return static_cast(is.Take()); + } + + template + static void PutBOM(OutputByteStream& os) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + (void)os; + } + + template + static void Put(OutputByteStream& os, Ch c) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); + os.Put(static_cast(c)); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// AutoUTF + +//! Runtime-specified UTF encoding type of a stream. +enum UTFType { + kUTF8 = 0, //!< UTF-8. + kUTF16LE = 1, //!< UTF-16 little endian. + kUTF16BE = 2, //!< UTF-16 big endian. + kUTF32LE = 3, //!< UTF-32 little endian. + kUTF32BE = 4 //!< UTF-32 big endian. +}; + +//! Dynamically select encoding according to stream's runtime-specified UTF encoding type. +/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType(). +*/ +template +struct AutoUTF { + typedef CharType Ch; + + enum { supportUnicode = 1 }; + +#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x + + template + static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; + (*f[os.GetType()])(os, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; + (*f[os.GetType()])(os, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) { + typedef bool (*DecodeFunc)(InputStream&, unsigned*); + static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; + return (*f[is.GetType()])(is, codepoint); + } + + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + typedef bool (*ValidateFunc)(InputStream&, OutputStream&); + static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; + return (*f[is.GetType()])(is, os); + } + +#undef RAPIDJSON_ENCODINGS_FUNC +}; + +/////////////////////////////////////////////////////////////////////////////// +// Transcoder + +//! Encoding conversion. +template +struct Transcoder { + //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. + template + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::Encode(os, codepoint); + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::EncodeUnsafe(os, codepoint); + return true; + } + + //! Validate one Unicode codepoint from an encoded stream. + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Transcode(is, os); // Since source/target encoding is different, must transcode. + } +}; + +// Forward declaration. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + +//! Specialization of Transcoder with same source and target encoding. +template +struct Transcoder { + template + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { + os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { + return Encoding::Validate(is, os); // source/target encoding are the same + } +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__)) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ENCODINGS_H_ diff --git a/deps/rapidjson/include/rapidjson/error/en.h b/deps/rapidjson/include/rapidjson/error/en.h new file mode 100644 index 0000000..c87b04e --- /dev/null +++ b/deps/rapidjson/include/rapidjson/error/en.h @@ -0,0 +1,176 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_EN_H_ +#define RAPIDJSON_ERROR_EN_H_ + +#include "error.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(covered-switch-default) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Maps error code of parsing into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param parseErrorCode Error code obtained in parsing. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { + switch (parseErrorCode) { + case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); + + case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); + + case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); + case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); + case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); + + case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); + + case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); + case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); + case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); + case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); + case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); + + case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); + case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); + case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); + + case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); + case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +//! Maps error code of validation into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param validateErrorCode Error code obtained from validator. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) { + switch (validateErrorCode) { + case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred"); + case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'."); + case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'."); + case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'."); + case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'."); + case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'."); + + case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'."); + case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'."); + case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression."); + + case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'."); + case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'."); + case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true."); + case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema."); + + case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'."); + case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'."); + case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'."); + case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema."); + case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema."); + case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors."); + + case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values."); + case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'."); + + case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors."); + case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf', indices '%matches'."); + case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors."); + case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors."); + case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'."); + + case kValidateErrorReadOnly: return RAPIDJSON_ERROR_STRING("Property is read-only but has been provided when validation is for writing."); + case kValidateErrorWriteOnly: return RAPIDJSON_ERROR_STRING("Property is write-only but has been provided when validation is for reading."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +//! Maps error code of schema document compilation into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param schemaErrorCode Error code obtained from compiling the schema document. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ + inline const RAPIDJSON_ERROR_CHARTYPE* GetSchemaError_En(SchemaErrorCode schemaErrorCode) { + switch (schemaErrorCode) { + case kSchemaErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kSchemaErrorStartUnknown: return RAPIDJSON_ERROR_STRING("Pointer '%value' to start of schema does not resolve to a location in the document."); + case kSchemaErrorRefPlainName: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' must be a JSON pointer."); + case kSchemaErrorRefInvalid: return RAPIDJSON_ERROR_STRING("$ref must not be an empty string."); + case kSchemaErrorRefPointerInvalid: return RAPIDJSON_ERROR_STRING("$ref fragment '%value' is not a valid JSON pointer at offset '%offset'."); + case kSchemaErrorRefUnknown: return RAPIDJSON_ERROR_STRING("$ref '%value' does not resolve to a location in the target document."); + case kSchemaErrorRefCyclical: return RAPIDJSON_ERROR_STRING("$ref '%value' is cyclical."); + case kSchemaErrorRefNoRemoteProvider: return RAPIDJSON_ERROR_STRING("$ref is remote but there is no remote provider."); + case kSchemaErrorRefNoRemoteSchema: return RAPIDJSON_ERROR_STRING("$ref '%value' is remote but the remote provider did not return a schema."); + case kSchemaErrorRegexInvalid: return RAPIDJSON_ERROR_STRING("Invalid regular expression '%value' in 'pattern' or 'patternProperties'."); + case kSchemaErrorSpecUnknown: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not recognized."); + case kSchemaErrorSpecUnsupported: return RAPIDJSON_ERROR_STRING("JSON schema draft or OpenAPI version is not supported."); + case kSchemaErrorSpecIllegal: return RAPIDJSON_ERROR_STRING("Both JSON schema draft and OpenAPI version found in document."); + case kSchemaErrorReadOnlyAndWriteOnly: return RAPIDJSON_ERROR_STRING("Property must not be both 'readOnly' and 'writeOnly'."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } + } + +//! Maps error code of pointer parse into error message. +/*! + \ingroup RAPIDJSON_ERRORS + \param pointerParseErrorCode Error code obtained from pointer parse. + \return the error message. + \note User can make a copy of this function for localization. + Using switch-case is safer for future modification of error codes. +*/ +inline const RAPIDJSON_ERROR_CHARTYPE* GetPointerParseError_En(PointerParseErrorCode pointerParseErrorCode) { + switch (pointerParseErrorCode) { + case kPointerParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); + + case kPointerParseErrorTokenMustBeginWithSolidus: return RAPIDJSON_ERROR_STRING("A token must begin with a '/'."); + case kPointerParseErrorInvalidEscape: return RAPIDJSON_ERROR_STRING("Invalid escape."); + case kPointerParseErrorInvalidPercentEncoding: return RAPIDJSON_ERROR_STRING("Invalid percent encoding in URI fragment."); + case kPointerParseErrorCharacterMustPercentEncode: return RAPIDJSON_ERROR_STRING("A character must be percent encoded in a URI fragment."); + + default: return RAPIDJSON_ERROR_STRING("Unknown error."); + } +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_EN_H_ diff --git a/deps/rapidjson/include/rapidjson/error/error.h b/deps/rapidjson/include/rapidjson/error/error.h new file mode 100644 index 0000000..cae345d --- /dev/null +++ b/deps/rapidjson/include/rapidjson/error/error.h @@ -0,0 +1,285 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ERROR_ERROR_H_ +#define RAPIDJSON_ERROR_ERROR_H_ + +#include "../rapidjson.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +/*! \file error.h */ + +/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_CHARTYPE + +//! Character type of error messages. +/*! \ingroup RAPIDJSON_ERRORS + The default character type is \c char. + On Windows, user can define this macro as \c TCHAR for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_CHARTYPE +#define RAPIDJSON_ERROR_CHARTYPE char +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ERROR_STRING + +//! Macro for converting string literal to \ref RAPIDJSON_ERROR_CHARTYPE[]. +/*! \ingroup RAPIDJSON_ERRORS + By default this conversion macro does nothing. + On Windows, user can define this macro as \c _T(x) for supporting both + unicode/non-unicode settings. +*/ +#ifndef RAPIDJSON_ERROR_STRING +#define RAPIDJSON_ERROR_STRING(x) x +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseErrorCode + +//! Error code of parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericReader::Parse, GenericReader::GetParseErrorCode +*/ +enum ParseErrorCode { + kParseErrorNone = 0, //!< No error. + + kParseErrorDocumentEmpty, //!< The document is empty. + kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. + + kParseErrorValueInvalid, //!< Invalid value. + + kParseErrorObjectMissName, //!< Missing a name for object member. + kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. + kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. + + kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. + + kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. + kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. + kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. + kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. + kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. + + kParseErrorNumberTooBig, //!< Number too big to be stored in double. + kParseErrorNumberMissFraction, //!< Miss fraction part in number. + kParseErrorNumberMissExponent, //!< Miss exponent in number. + + kParseErrorTermination, //!< Parsing was terminated. + kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. +}; + +//! Result of parsing (wraps ParseErrorCode) +/*! + \ingroup RAPIDJSON_ERRORS + \code + Document doc; + ParseResult ok = doc.Parse("[42]"); + if (!ok) { + fprintf(stderr, "JSON parse error: %s (%u)", + GetParseError_En(ok.Code()), ok.Offset()); + exit(EXIT_FAILURE); + } + \endcode + \see GenericReader::Parse, GenericDocument::Parse +*/ +struct ParseResult { + //!! Unspecified boolean type + typedef bool (ParseResult::*BooleanType)() const; +public: + //! Default constructor, no error. + ParseResult() : code_(kParseErrorNone), offset_(0) {} + //! Constructor to set an error. + ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} + + //! Get the error code. + ParseErrorCode Code() const { return code_; } + //! Get the error offset, if \ref IsError(), 0 otherwise. + size_t Offset() const { return offset_; } + + //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). + operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } + //! Whether the result is an error. + bool IsError() const { return code_ != kParseErrorNone; } + + bool operator==(const ParseResult& that) const { return code_ == that.code_; } + bool operator==(ParseErrorCode code) const { return code_ == code; } + friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + + bool operator!=(const ParseResult& that) const { return !(*this == that); } + bool operator!=(ParseErrorCode code) const { return !(*this == code); } + friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } + + //! Reset error code. + void Clear() { Set(kParseErrorNone); } + //! Update error code and offset. + void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } + +private: + ParseErrorCode code_; + size_t offset_; +}; + +//! Function pointer type of GetParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetParseErrorFunc GetParseError = GetParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// ValidateErrorCode + +//! Error codes when validating. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericSchemaValidator +*/ +enum ValidateErrorCode { + kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set. + kValidateErrorNone = 0, //!< No error. + + kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value. + kValidateErrorMaximum, //!< Number is greater than the 'maximum' value. + kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value. + kValidateErrorMinimum, //!< Number is less than the 'minimum' value. + kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value. + + kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value. + kValidateErrorMinLength, //!< String is longer than the 'maxLength' value. + kValidateErrorPattern, //!< String does not match the 'pattern' regular expression. + + kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value. + kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value. + kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true. + kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema. + + kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value. + kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value. + kValidateErrorRequired, //!< Object is missing one or more members required by the schema. + kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema. + kValidateErrorPatternProperties, //!< See other errors. + kValidateErrorDependencies, //!< Object has missing property or schema dependencies. + + kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values. + kValidateErrorType, //!< Property has a type that is not allowed by the schema. + + kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'. + kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'. + kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'. + kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'. + kValidateErrorNot, //!< Property matched the sub-schema specified by 'not'. + + kValidateErrorReadOnly, //!< Property is read-only but has been provided when validation is for writing + kValidateErrorWriteOnly //!< Property is write-only but has been provided when validation is for reading +}; + +//! Function pointer type of GetValidateError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetValidateError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// SchemaErrorCode + +//! Error codes when validating. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericSchemaValidator +*/ +enum SchemaErrorCode { + kSchemaErrorNone = 0, //!< No error. + + kSchemaErrorStartUnknown, //!< Pointer to start of schema does not resolve to a location in the document + kSchemaErrorRefPlainName, //!< $ref fragment must be a JSON pointer + kSchemaErrorRefInvalid, //!< $ref must not be an empty string + kSchemaErrorRefPointerInvalid, //!< $ref fragment is not a valid JSON pointer at offset + kSchemaErrorRefUnknown, //!< $ref does not resolve to a location in the target document + kSchemaErrorRefCyclical, //!< $ref is cyclical + kSchemaErrorRefNoRemoteProvider, //!< $ref is remote but there is no remote provider + kSchemaErrorRefNoRemoteSchema, //!< $ref is remote but the remote provider did not return a schema + kSchemaErrorRegexInvalid, //!< Invalid regular expression in 'pattern' or 'patternProperties' + kSchemaErrorSpecUnknown, //!< JSON schema draft or OpenAPI version is not recognized + kSchemaErrorSpecUnsupported, //!< JSON schema draft or OpenAPI version is not supported + kSchemaErrorSpecIllegal, //!< Both JSON schema draft and OpenAPI version found in document + kSchemaErrorReadOnlyAndWriteOnly //!< Property must not be both 'readOnly' and 'writeOnly' +}; + +//! Function pointer type of GetSchemaError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetSchemaError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetSchemaErrorFunc GetSchemaError = GetSchemaError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetSchemaError(validator.GetInvalidSchemaCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetSchemaErrorFunc)(SchemaErrorCode); + +/////////////////////////////////////////////////////////////////////////////// +// PointerParseErrorCode + +//! Error code of JSON pointer parsing. +/*! \ingroup RAPIDJSON_ERRORS + \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode +*/ +enum PointerParseErrorCode { + kPointerParseErrorNone = 0, //!< The parse is successful + + kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' + kPointerParseErrorInvalidEscape, //!< Invalid escape + kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment + kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment +}; + +//! Function pointer type of GetPointerParseError(). +/*! \ingroup RAPIDJSON_ERRORS + + This is the prototype for \c GetPointerParseError_X(), where \c X is a locale. + User can dynamically change locale in runtime, e.g.: +\code + GetPointerParseErrorFunc GetPointerParseError = GetPointerParseError_En; // or whatever + const RAPIDJSON_ERROR_CHARTYPE* s = GetPointerParseError(pointer.GetParseErrorCode()); +\endcode +*/ +typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetPointerParseErrorFunc)(PointerParseErrorCode); + + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_ERROR_H_ diff --git a/deps/rapidjson/include/rapidjson/filereadstream.h b/deps/rapidjson/include/rapidjson/filereadstream.h new file mode 100644 index 0000000..f8bb43c --- /dev/null +++ b/deps/rapidjson/include/rapidjson/filereadstream.h @@ -0,0 +1,99 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEREADSTREAM_H_ +#define RAPIDJSON_FILEREADSTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! File byte stream for input using fread(). +/*! + \note implements Stream concept +*/ +class FileReadStream { +public: + typedef char Ch; //!< Character type (byte). + + //! Constructor. + /*! + \param fp File pointer opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(fp_ != 0); + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + +private: + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (readCount_ < bufferSize_) { + buffer_[readCount_] = '\0'; + ++bufferLast_; + eof_ = true; + } + } + } + + std::FILE* fp_; + Ch *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/deps/rapidjson/include/rapidjson/filewritestream.h b/deps/rapidjson/include/rapidjson/filewritestream.h new file mode 100644 index 0000000..5d89588 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/filewritestream.h @@ -0,0 +1,104 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FILEWRITESTREAM_H_ +#define RAPIDJSON_FILEWRITESTREAM_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of C file stream for output using fwrite(). +/*! + \note implements Stream concept +*/ +class FileWriteStream { +public: + typedef char Ch; //!< Character type. Only support char. + + FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) { + RAPIDJSON_ASSERT(fp_ != 0); + } + + void Put(char c) { + if (current_ >= bufferEnd_) + Flush(); + + *current_++ = c; + } + + void PutN(char c, size_t n) { + size_t avail = static_cast(bufferEnd_ - current_); + while (n > avail) { + std::memset(current_, c, avail); + current_ += avail; + Flush(); + n -= avail; + avail = static_cast(bufferEnd_ - current_); + } + + if (n > 0) { + std::memset(current_, c, n); + current_ += n; + } + } + + void Flush() { + if (current_ != buffer_) { + size_t result = std::fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } + current_ = buffer_; + } + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + FileWriteStream(const FileWriteStream&); + FileWriteStream& operator=(const FileWriteStream&); + + std::FILE* fp_; + char *buffer_; + char *bufferEnd_; + char *current_; +}; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(FileWriteStream& stream, char c, size_t n) { + stream.PutN(c, n); +} + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_FILESTREAM_H_ diff --git a/deps/rapidjson/include/rapidjson/fwd.h b/deps/rapidjson/include/rapidjson/fwd.h new file mode 100644 index 0000000..d62f77f --- /dev/null +++ b/deps/rapidjson/include/rapidjson/fwd.h @@ -0,0 +1,151 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FWD_H_ +#define RAPIDJSON_FWD_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +// encodings.h + +template struct UTF8; +template struct UTF16; +template struct UTF16BE; +template struct UTF16LE; +template struct UTF32; +template struct UTF32BE; +template struct UTF32LE; +template struct ASCII; +template struct AutoUTF; + +template +struct Transcoder; + +// allocators.h + +class CrtAllocator; + +template +class MemoryPoolAllocator; + +// stream.h + +template +struct GenericStringStream; + +typedef GenericStringStream > StringStream; + +template +struct GenericInsituStringStream; + +typedef GenericInsituStringStream > InsituStringStream; + +// stringbuffer.h + +template +class GenericStringBuffer; + +typedef GenericStringBuffer, CrtAllocator> StringBuffer; + +// filereadstream.h + +class FileReadStream; + +// filewritestream.h + +class FileWriteStream; + +// memorybuffer.h + +template +struct GenericMemoryBuffer; + +typedef GenericMemoryBuffer MemoryBuffer; + +// memorystream.h + +struct MemoryStream; + +// reader.h + +template +struct BaseReaderHandler; + +template +class GenericReader; + +typedef GenericReader, UTF8, CrtAllocator> Reader; + +// writer.h + +template +class Writer; + +// prettywriter.h + +template +class PrettyWriter; + +// document.h + +template +class GenericMember; + +template +class GenericMemberIterator; + +template +struct GenericStringRef; + +template +class GenericValue; + +typedef GenericValue, MemoryPoolAllocator > Value; + +template +class GenericDocument; + +typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; + +// pointer.h + +template +class GenericPointer; + +typedef GenericPointer Pointer; + +// schema.h + +template +class IGenericRemoteSchemaDocumentProvider; + +template +class GenericSchemaDocument; + +typedef GenericSchemaDocument SchemaDocument; +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +template < + typename SchemaDocumentType, + typename OutputHandler, + typename StateAllocator> +class GenericSchemaValidator; + +typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSONFWD_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/biginteger.h b/deps/rapidjson/include/rapidjson/internal/biginteger.h new file mode 100644 index 0000000..4930043 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/biginteger.h @@ -0,0 +1,297 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_BIGINTEGER_H_ +#define RAPIDJSON_BIGINTEGER_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64) +#include // for _umul128 +#if !defined(_ARM64EC_) +#pragma intrinsic(_umul128) +#else +#pragma comment(lib,"softintrin") +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class BigInteger { +public: + typedef uint64_t Type; + + BigInteger(const BigInteger& rhs) : count_(rhs.count_) { + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + + explicit BigInteger(uint64_t u) : count_(1) { + digits_[0] = u; + } + + template + BigInteger(const Ch* decimals, size_t length) : count_(1) { + RAPIDJSON_ASSERT(length > 0); + digits_[0] = 0; + size_t i = 0; + const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 + while (length >= kMaxDigitPerIteration) { + AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); + length -= kMaxDigitPerIteration; + i += kMaxDigitPerIteration; + } + + if (length > 0) + AppendDecimal64(decimals + i, decimals + i + length); + } + + BigInteger& operator=(const BigInteger &rhs) + { + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } + + BigInteger& operator=(uint64_t u) { + digits_[0] = u; + count_ = 1; + return *this; + } + + BigInteger& operator+=(uint64_t u) { + Type backup = digits_[0]; + digits_[0] += u; + for (size_t i = 0; i < count_ - 1; i++) { + if (digits_[i] >= backup) + return *this; // no carry + backup = digits_[i + 1]; + digits_[i + 1] += 1; + } + + // Last carry + if (digits_[count_ - 1] < backup) + PushBack(1); + + return *this; + } + + BigInteger& operator*=(uint64_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + uint64_t hi; + digits_[i] = MulAdd64(digits_[i], u, k, &hi); + k = hi; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator*=(uint32_t u) { + if (u == 0) return *this = 0; + if (u == 1) return *this; + if (*this == 1) return *this = u; + + uint64_t k = 0; + for (size_t i = 0; i < count_; i++) { + const uint64_t c = digits_[i] >> 32; + const uint64_t d = digits_[i] & 0xFFFFFFFF; + const uint64_t uc = u * c; + const uint64_t ud = u * d; + const uint64_t p0 = ud + k; + const uint64_t p1 = uc + (p0 >> 32); + digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); + k = p1 >> 32; + } + + if (k > 0) + PushBack(k); + + return *this; + } + + BigInteger& operator<<=(size_t shift) { + if (IsZero() || shift == 0) return *this; + + size_t offset = shift / kTypeBit; + size_t interShift = shift % kTypeBit; + RAPIDJSON_ASSERT(count_ + offset <= kCapacity); + + if (interShift == 0) { + std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); + count_ += offset; + } + else { + digits_[count_] = 0; + for (size_t i = count_; i > 0; i--) + digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); + digits_[offset] = digits_[0] << interShift; + count_ += offset; + if (digits_[count_]) + count_++; + } + + std::memset(digits_, 0, offset * sizeof(Type)); + + return *this; + } + + bool operator==(const BigInteger& rhs) const { + return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; + } + + bool operator==(const Type rhs) const { + return count_ == 1 && digits_[0] == rhs; + } + + BigInteger& MultiplyPow5(unsigned exp) { + static const uint32_t kPow5[12] = { + 5, + 5 * 5, + 5 * 5 * 5, + 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, + 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 + }; + if (exp == 0) return *this; + for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 + for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 + if (exp > 0) *this *= kPow5[exp - 1]; + return *this; + } + + // Compute absolute difference of this and rhs. + // Assume this != rhs + bool Difference(const BigInteger& rhs, BigInteger* out) const { + int cmp = Compare(rhs); + RAPIDJSON_ASSERT(cmp != 0); + const BigInteger *a, *b; // Makes a > b + bool ret; + if (cmp < 0) { a = &rhs; b = this; ret = true; } + else { a = this; b = &rhs; ret = false; } + + Type borrow = 0; + for (size_t i = 0; i < a->count_; i++) { + Type d = a->digits_[i] - borrow; + if (i < b->count_) + d -= b->digits_[i]; + borrow = (d > a->digits_[i]) ? 1 : 0; + out->digits_[i] = d; + if (d != 0) + out->count_ = i + 1; + } + + return ret; + } + + int Compare(const BigInteger& rhs) const { + if (count_ != rhs.count_) + return count_ < rhs.count_ ? -1 : 1; + + for (size_t i = count_; i-- > 0;) + if (digits_[i] != rhs.digits_[i]) + return digits_[i] < rhs.digits_[i] ? -1 : 1; + + return 0; + } + + size_t GetCount() const { return count_; } + Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } + bool IsZero() const { return count_ == 1 && digits_[0] == 0; } + +private: + template + void AppendDecimal64(const Ch* begin, const Ch* end) { + uint64_t u = ParseUint64(begin, end); + if (IsZero()) + *this = u; + else { + unsigned exp = static_cast(end - begin); + (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u + } + } + + void PushBack(Type digit) { + RAPIDJSON_ASSERT(count_ < kCapacity); + digits_[count_++] = digit; + } + + template + static uint64_t ParseUint64(const Ch* begin, const Ch* end) { + uint64_t r = 0; + for (const Ch* p = begin; p != end; ++p) { + RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9')); + r = r * 10u + static_cast(*p - Ch('0')); + } + return r; + } + + // Assume a * b + k < 2^128 + static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t low = _umul128(a, b, outHigh) + k; + if (low < k) + (*outHigh)++; + return low; +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(a) * static_cast(b); + p += k; + *outHigh = static_cast(p >> 64); + return static_cast(p); +#else + const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; + uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; + x1 += (x0 >> 32); // can't give carry + x1 += x2; + if (x1 < x2) + x3 += (static_cast(1) << 32); + uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); + uint64_t hi = x3 + (x1 >> 32); + + lo += k; + if (lo < k) + hi++; + *outHigh = hi; + return lo; +#endif + } + + static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 + static const size_t kCapacity = kBitCount / sizeof(Type); + static const size_t kTypeBit = sizeof(Type) * 8; + + Type digits_[kCapacity]; + size_t count_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/clzll.h b/deps/rapidjson/include/rapidjson/internal/clzll.h new file mode 100644 index 0000000..8fc5118 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/clzll.h @@ -0,0 +1,71 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_CLZLL_H_ +#define RAPIDJSON_CLZLL_H_ + +#include "../rapidjson.h" + +#if defined(_MSC_VER) && !defined(UNDER_CE) +#include +#if defined(_WIN64) +#pragma intrinsic(_BitScanReverse64) +#else +#pragma intrinsic(_BitScanReverse) +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline uint32_t clzll(uint64_t x) { + // Passing 0 to __builtin_clzll is UB in GCC and results in an + // infinite loop in the software implementation. + RAPIDJSON_ASSERT(x != 0); + +#if defined(_MSC_VER) && !defined(UNDER_CE) + unsigned long r = 0; +#if defined(_WIN64) + _BitScanReverse64(&r, x); +#else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast(x >> 32))) + return 63 - (r + 32); + + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast(x & 0xFFFFFFFF)); +#endif // _WIN64 + + return 63 - r; +#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll) + // __builtin_clzll wrapper + return static_cast(__builtin_clzll(x)); +#else + // naive version + uint32_t r = 0; + while (!(x & (static_cast(1) << 63))) { + x <<= 1; + ++r; + } + + return r; +#endif // _MSC_VER +} + +#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_CLZLL_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/diyfp.h b/deps/rapidjson/include/rapidjson/internal/diyfp.h new file mode 100644 index 0000000..1f60fb6 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/diyfp.h @@ -0,0 +1,261 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DIYFP_H_ +#define RAPIDJSON_DIYFP_H_ + +#include "../rapidjson.h" +#include "clzll.h" +#include + +#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) +#include +#if !defined(_ARM64EC_) +#pragma intrinsic(_umul128) +#else +#pragma comment(lib,"softintrin") +#endif +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +struct DiyFp { + DiyFp() : f(), e() {} + + DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} + + explicit DiyFp(double d) { + union { + double d; + uint64_t u64; + } u = { d }; + + int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); + uint64_t significand = (u.u64 & kDpSignificandMask); + if (biased_e != 0) { + f = significand + kDpHiddenBit; + e = biased_e - kDpExponentBias; + } + else { + f = significand; + e = kDpMinExponent + 1; + } + } + + DiyFp operator-(const DiyFp& rhs) const { + return DiyFp(f - rhs.f, e); + } + + DiyFp operator*(const DiyFp& rhs) const { +#if defined(_MSC_VER) && defined(_M_AMD64) + uint64_t h; + uint64_t l = _umul128(f, rhs.f, &h); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) + __extension__ typedef unsigned __int128 uint128; + uint128 p = static_cast(f) * static_cast(rhs.f); + uint64_t h = static_cast(p >> 64); + uint64_t l = static_cast(p); + if (l & (uint64_t(1) << 63)) // rounding + h++; + return DiyFp(h, e + rhs.e + 64); +#else + const uint64_t M32 = 0xFFFFFFFF; + const uint64_t a = f >> 32; + const uint64_t b = f & M32; + const uint64_t c = rhs.f >> 32; + const uint64_t d = rhs.f & M32; + const uint64_t ac = a * c; + const uint64_t bc = b * c; + const uint64_t ad = a * d; + const uint64_t bd = b * d; + uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); + tmp += 1U << 31; /// mult_round + return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); +#endif + } + + DiyFp Normalize() const { + int s = static_cast(clzll(f)); + return DiyFp(f << s, e - s); + } + + DiyFp NormalizeBoundary() const { + DiyFp res = *this; + while (!(res.f & (kDpHiddenBit << 1))) { + res.f <<= 1; + res.e--; + } + res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); + res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); + return res; + } + + void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { + DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); + DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); + mi.f <<= mi.e - pl.e; + mi.e = pl.e; + *plus = pl; + *minus = mi; + } + + double ToDouble() const { + union { + double d; + uint64_t u64; + }u; + RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask); + if (e < kDpDenormalExponent) { + // Underflow. + return 0.0; + } + if (e >= kDpMaxExponent) { + // Overflow. + return std::numeric_limits::infinity(); + } + const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : + static_cast(e + kDpExponentBias); + u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); + return u.d; + } + + static const int kDiySignificandSize = 64; + static const int kDpSignificandSize = 52; + static const int kDpExponentBias = 0x3FF + kDpSignificandSize; + static const int kDpMaxExponent = 0x7FF - kDpExponentBias; + static const int kDpMinExponent = -kDpExponentBias; + static const int kDpDenormalExponent = -kDpExponentBias + 1; + static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + uint64_t f; + int e; +}; + +inline DiyFp GetCachedPowerByIndex(size_t index) { + // 10^-348, 10^-340, ..., 10^340 + static const uint64_t kCachedPowers_F[] = { + RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), + RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), + RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), + RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), + RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), + RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), + RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), + RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), + RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), + RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), + RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), + RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), + RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), + RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), + RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), + RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), + RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), + RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), + RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), + RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), + RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), + RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), + RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), + RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), + RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), + RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), + RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), + RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), + RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), + RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), + RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), + RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), + RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), + RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), + RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), + RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), + RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), + RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), + RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), + RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), + RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), + RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), + RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), + RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) + }; + static const int16_t kCachedPowers_E[] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, + -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, + -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, + -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, + -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, + 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, + 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, + 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, + 907, 933, 960, 986, 1013, 1039, 1066 + }; + RAPIDJSON_ASSERT(index < 87); + return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); +} + +inline DiyFp GetCachedPower(int e, int* K) { + + //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; + double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive + int k = static_cast(dk); + if (dk - k > 0.0) + k++; + + unsigned index = static_cast((k >> 3) + 1); + *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table + + return GetCachedPowerByIndex(index); +} + +inline DiyFp GetCachedPower10(int exp, int *outExp) { + RAPIDJSON_ASSERT(exp >= -348); + unsigned index = static_cast(exp + 348) / 8u; + *outExp = -348 + static_cast(index) * 8; + return GetCachedPowerByIndex(index); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +RAPIDJSON_DIAG_OFF(padded) +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DIYFP_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/dtoa.h b/deps/rapidjson/include/rapidjson/internal/dtoa.h new file mode 100644 index 0000000..cd45672 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/dtoa.h @@ -0,0 +1,249 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// This is a C++ header-only implementation of Grisu2 algorithm from the publication: +// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with +// integers." ACM Sigplan Notices 45.6 (2010): 233-243. + +#ifndef RAPIDJSON_DTOA_ +#define RAPIDJSON_DTOA_ + +#include "itoa.h" // GetDigitsLut() +#include "diyfp.h" +#include "ieee754.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 +#endif + +inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { + while (rest < wp_w && delta - rest >= ten_kappa && + (rest + ten_kappa < wp_w || /// closer + wp_w - rest > rest + ten_kappa - wp_w)) { + buffer[len - 1]--; + rest += ten_kappa; + } +} + +inline int CountDecimalDigit32(uint32_t n) { + // Simple pure C++ implementation was faster than __builtin_clz version in this situation. + if (n < 10) return 1; + if (n < 100) return 2; + if (n < 1000) return 3; + if (n < 10000) return 4; + if (n < 100000) return 5; + if (n < 1000000) return 6; + if (n < 10000000) return 7; + if (n < 100000000) return 8; + // Will not reach 10 digits in DigitGen() + //if (n < 1000000000) return 9; + //return 10; + return 9; +} + +inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { + static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL, + 1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL, + 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL, + 10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, + 10000000000000000000ULL }; + const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); + const DiyFp wp_w = Mp - W; + uint32_t p1 = static_cast(Mp.f >> -one.e); + uint64_t p2 = Mp.f & (one.f - 1); + int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] + *len = 0; + + while (kappa > 0) { + uint32_t d = 0; + switch (kappa) { + case 9: d = p1 / 100000000; p1 %= 100000000; break; + case 8: d = p1 / 10000000; p1 %= 10000000; break; + case 7: d = p1 / 1000000; p1 %= 1000000; break; + case 6: d = p1 / 100000; p1 %= 100000; break; + case 5: d = p1 / 10000; p1 %= 10000; break; + case 4: d = p1 / 1000; p1 %= 1000; break; + case 3: d = p1 / 100; p1 %= 100; break; + case 2: d = p1 / 10; p1 %= 10; break; + case 1: d = p1; p1 = 0; break; + default:; + } + if (d || *len) + buffer[(*len)++] = static_cast('0' + static_cast(d)); + kappa--; + uint64_t tmp = (static_cast(p1) << -one.e) + p2; + if (tmp <= delta) { + *K += kappa; + GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f); + return; + } + } + + // kappa = 0 + for (;;) { + p2 *= 10; + delta *= 10; + char d = static_cast(p2 >> -one.e); + if (d || *len) + buffer[(*len)++] = static_cast('0' + d); + p2 &= one.f - 1; + kappa--; + if (p2 < delta) { + *K += kappa; + int index = -kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0)); + return; + } + } +} + +inline void Grisu2(double value, char* buffer, int* length, int* K) { + const DiyFp v(value); + DiyFp w_m, w_p; + v.NormalizedBoundaries(&w_m, &w_p); + + const DiyFp c_mk = GetCachedPower(w_p.e, K); + const DiyFp W = v.Normalize() * c_mk; + DiyFp Wp = w_p * c_mk; + DiyFp Wm = w_m * c_mk; + Wm.f++; + Wp.f--; + DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); +} + +inline char* WriteExponent(int K, char* buffer) { + if (K < 0) { + *buffer++ = '-'; + K = -K; + } + + if (K >= 100) { + *buffer++ = static_cast('0' + static_cast(K / 100)); + K %= 100; + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else if (K >= 10) { + const char* d = GetDigitsLut() + K * 2; + *buffer++ = d[0]; + *buffer++ = d[1]; + } + else + *buffer++ = static_cast('0' + static_cast(K)); + + return buffer; +} + +inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { + const int kk = length + k; // 10^(kk-1) <= v < 10^kk + + if (0 <= k && kk <= 21) { + // 1234e7 -> 12340000000 + for (int i = length; i < kk; i++) + buffer[i] = '0'; + buffer[kk] = '.'; + buffer[kk + 1] = '0'; + return &buffer[kk + 2]; + } + else if (0 < kk && kk <= 21) { + // 1234e-2 -> 12.34 + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); + buffer[kk] = '.'; + if (0 > k + maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[kk + 2]; // Reserve one zero + } + else + return &buffer[length + 1]; + } + else if (-6 < kk && kk <= 0) { + // 1234e-6 -> 0.001234 + const int offset = 2 - kk; + std::memmove(&buffer[offset], &buffer[0], static_cast(length)); + buffer[0] = '0'; + buffer[1] = '.'; + for (int i = 2; i < offset; i++) + buffer[i] = '0'; + if (length - kk > maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = maxDecimalPlaces + 1; i > 2; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[3]; // Reserve one zero + } + else + return &buffer[length + offset]; + } + else if (kk < -maxDecimalPlaces) { + // Truncate to zero + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else if (length == 1) { + // 1e30 + buffer[1] = 'e'; + return WriteExponent(kk - 1, &buffer[2]); + } + else { + // 1234e30 -> 1.234e33 + std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); + buffer[1] = '.'; + buffer[length + 1] = 'e'; + return WriteExponent(kk - 1, &buffer[0 + length + 2]); + } +} + +inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { + RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); + Double d(value); + if (d.IsZero()) { + if (d.Sign()) + *buffer++ = '-'; // -0.0, Issue #289 + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; + } + else { + if (value < 0) { + *buffer++ = '-'; + value = -value; + } + int length, K; + Grisu2(value, buffer, &length, &K); + return Prettify(buffer, length, K, maxDecimalPlaces); + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_DTOA_ diff --git a/deps/rapidjson/include/rapidjson/internal/ieee754.h b/deps/rapidjson/include/rapidjson/internal/ieee754.h new file mode 100644 index 0000000..68c9e96 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/ieee754.h @@ -0,0 +1,78 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_IEEE754_ +#define RAPIDJSON_IEEE754_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +class Double { +public: + Double() {} + Double(double d) : d_(d) {} + Double(uint64_t u) : u_(u) {} + + double Value() const { return d_; } + uint64_t Uint64Value() const { return u_; } + + double NextPositiveDouble() const { + RAPIDJSON_ASSERT(!Sign()); + return Double(u_ + 1).Value(); + } + + bool Sign() const { return (u_ & kSignMask) != 0; } + uint64_t Significand() const { return u_ & kSignificandMask; } + int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } + + bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } + bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } + bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } + bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } + + uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } + int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } + uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } + + static int EffectiveSignificandSize(int order) { + if (order >= -1021) + return 53; + else if (order <= -1074) + return 0; + else + return order + 1074; + } + +private: + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const int kDenormalExponent = 1 - kExponentBias; + static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + union { + double d_; + uint64_t u_; + }; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_IEEE754_ diff --git a/deps/rapidjson/include/rapidjson/internal/itoa.h b/deps/rapidjson/include/rapidjson/internal/itoa.h new file mode 100644 index 0000000..9fe8c93 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/itoa.h @@ -0,0 +1,308 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ITOA_ +#define RAPIDJSON_ITOA_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline const char* GetDigitsLut() { + static const char cDigitsLut[200] = { + '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', + '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', + '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', + '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', + '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', + '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', + '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', + '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', + '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', + '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' + }; + return cDigitsLut; +} + +inline char* u32toa(uint32_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + + const char* cDigitsLut = GetDigitsLut(); + + if (value < 10000) { + const uint32_t d1 = (value / 100) << 1; + const uint32_t d2 = (value % 100) << 1; + + if (value >= 1000) + *buffer++ = cDigitsLut[d1]; + if (value >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else if (value < 100000000) { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + else { + // value = aabbbbcccc in decimal + + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a >= 10) { + const unsigned i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else + *buffer++ = static_cast('0' + static_cast(a)); + + const uint32_t b = value / 10000; // 0 to 9999 + const uint32_t c = value % 10000; // 0 to 9999 + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + return buffer; +} + +inline char* i32toa(int32_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + uint32_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u32toa(u, buffer); +} + +inline char* u64toa(uint64_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + const char* cDigitsLut = GetDigitsLut(); + const uint64_t kTen8 = 100000000; + const uint64_t kTen9 = kTen8 * 10; + const uint64_t kTen10 = kTen8 * 100; + const uint64_t kTen11 = kTen8 * 1000; + const uint64_t kTen12 = kTen8 * 10000; + const uint64_t kTen13 = kTen8 * 100000; + const uint64_t kTen14 = kTen8 * 1000000; + const uint64_t kTen15 = kTen8 * 10000000; + const uint64_t kTen16 = kTen8 * kTen8; + + if (value < kTen8) { + uint32_t v = static_cast(value); + if (v < 10000) { + const uint32_t d1 = (v / 100) << 1; + const uint32_t d2 = (v % 100) << 1; + + if (v >= 1000) + *buffer++ = cDigitsLut[d1]; + if (v >= 100) + *buffer++ = cDigitsLut[d1 + 1]; + if (v >= 10) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + } + else { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + const uint32_t d1 = (b / 100) << 1; + const uint32_t d2 = (b % 100) << 1; + + const uint32_t d3 = (c / 100) << 1; + const uint32_t d4 = (c % 100) << 1; + + if (value >= 10000000) + *buffer++ = cDigitsLut[d1]; + if (value >= 1000000) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= 100000) + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + } + } + else if (value < kTen16) { + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + if (value >= kTen15) + *buffer++ = cDigitsLut[d1]; + if (value >= kTen14) + *buffer++ = cDigitsLut[d1 + 1]; + if (value >= kTen13) + *buffer++ = cDigitsLut[d2]; + if (value >= kTen12) + *buffer++ = cDigitsLut[d2 + 1]; + if (value >= kTen11) + *buffer++ = cDigitsLut[d3]; + if (value >= kTen10) + *buffer++ = cDigitsLut[d3 + 1]; + if (value >= kTen9) + *buffer++ = cDigitsLut[d4]; + + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + else { + const uint32_t a = static_cast(value / kTen16); // 1 to 1844 + value %= kTen16; + + if (a < 10) + *buffer++ = static_cast('0' + static_cast(a)); + else if (a < 100) { + const uint32_t i = a << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else if (a < 1000) { + *buffer++ = static_cast('0' + static_cast(a / 100)); + + const uint32_t i = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + } + else { + const uint32_t i = (a / 100) << 1; + const uint32_t j = (a % 100) << 1; + *buffer++ = cDigitsLut[i]; + *buffer++ = cDigitsLut[i + 1]; + *buffer++ = cDigitsLut[j]; + *buffer++ = cDigitsLut[j + 1]; + } + + const uint32_t v0 = static_cast(value / kTen8); + const uint32_t v1 = static_cast(value % kTen8); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + const uint32_t d1 = (b0 / 100) << 1; + const uint32_t d2 = (b0 % 100) << 1; + + const uint32_t d3 = (c0 / 100) << 1; + const uint32_t d4 = (c0 % 100) << 1; + + const uint32_t b1 = v1 / 10000; + const uint32_t c1 = v1 % 10000; + + const uint32_t d5 = (b1 / 100) << 1; + const uint32_t d6 = (b1 % 100) << 1; + + const uint32_t d7 = (c1 / 100) << 1; + const uint32_t d8 = (c1 % 100) << 1; + + *buffer++ = cDigitsLut[d1]; + *buffer++ = cDigitsLut[d1 + 1]; + *buffer++ = cDigitsLut[d2]; + *buffer++ = cDigitsLut[d2 + 1]; + *buffer++ = cDigitsLut[d3]; + *buffer++ = cDigitsLut[d3 + 1]; + *buffer++ = cDigitsLut[d4]; + *buffer++ = cDigitsLut[d4 + 1]; + *buffer++ = cDigitsLut[d5]; + *buffer++ = cDigitsLut[d5 + 1]; + *buffer++ = cDigitsLut[d6]; + *buffer++ = cDigitsLut[d6 + 1]; + *buffer++ = cDigitsLut[d7]; + *buffer++ = cDigitsLut[d7 + 1]; + *buffer++ = cDigitsLut[d8]; + *buffer++ = cDigitsLut[d8 + 1]; + } + + return buffer; +} + +inline char* i64toa(int64_t value, char* buffer) { + RAPIDJSON_ASSERT(buffer != 0); + uint64_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + + return u64toa(u, buffer); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ITOA_ diff --git a/deps/rapidjson/include/rapidjson/internal/meta.h b/deps/rapidjson/include/rapidjson/internal/meta.h new file mode 100644 index 0000000..27092dc --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/meta.h @@ -0,0 +1,186 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_META_H_ +#define RAPIDJSON_INTERNAL_META_H_ + +#include "../rapidjson.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(6334) +#endif + +#if RAPIDJSON_HAS_CXX11_TYPETRAITS +#include +#endif + +//@cond RAPIDJSON_INTERNAL +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching +template struct Void { typedef void Type; }; + +/////////////////////////////////////////////////////////////////////////////// +// BoolType, TrueType, FalseType +// +template struct BoolType { + static const bool Value = Cond; + typedef BoolType Type; +}; +typedef BoolType TrueType; +typedef BoolType FalseType; + + +/////////////////////////////////////////////////////////////////////////////// +// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr +// + +template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; +template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; +template struct SelectIfCond : SelectIfImpl::template Apply {}; +template struct SelectIf : SelectIfCond {}; + +template struct AndExprCond : FalseType {}; +template <> struct AndExprCond : TrueType {}; +template struct OrExprCond : TrueType {}; +template <> struct OrExprCond : FalseType {}; + +template struct BoolExpr : SelectIf::Type {}; +template struct NotExpr : SelectIf::Type {}; +template struct AndExpr : AndExprCond::Type {}; +template struct OrExpr : OrExprCond::Type {}; + + +/////////////////////////////////////////////////////////////////////////////// +// AddConst, MaybeAddConst, RemoveConst +template struct AddConst { typedef const T Type; }; +template struct MaybeAddConst : SelectIfCond {}; +template struct RemoveConst { typedef T Type; }; +template struct RemoveConst { typedef T Type; }; + + +/////////////////////////////////////////////////////////////////////////////// +// IsSame, IsConst, IsMoreConst, IsPointer +// +template struct IsSame : FalseType {}; +template struct IsSame : TrueType {}; + +template struct IsConst : FalseType {}; +template struct IsConst : TrueType {}; + +template +struct IsMoreConst + : AndExpr::Type, typename RemoveConst::Type>, + BoolType::Value >= IsConst::Value> >::Type {}; + +template struct IsPointer : FalseType {}; +template struct IsPointer : TrueType {}; + +/////////////////////////////////////////////////////////////////////////////// +// IsBaseOf +// +#if RAPIDJSON_HAS_CXX11_TYPETRAITS + +template struct IsBaseOf + : BoolType< ::std::is_base_of::value> {}; + +#else // simplified version adopted from Boost + +template struct IsBaseOfImpl { + RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); + RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); + + typedef char (&Yes)[1]; + typedef char (&No) [2]; + + template + static Yes Check(const D*, T); + static No Check(const B*, int); + + struct Host { + operator const B*() const; + operator const D*(); + }; + + enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; +}; + +template struct IsBaseOf + : OrExpr, BoolExpr > >::Type {}; + +#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS + + +////////////////////////////////////////////////////////////////////////// +// EnableIf / DisableIf +// +template struct EnableIfCond { typedef T Type; }; +template struct EnableIfCond { /* empty */ }; + +template struct DisableIfCond { typedef T Type; }; +template struct DisableIfCond { /* empty */ }; + +template +struct EnableIf : EnableIfCond {}; + +template +struct DisableIf : DisableIfCond {}; + +// SFINAE helpers +struct SfinaeTag {}; +template struct RemoveSfinaeTag; +template struct RemoveSfinaeTag { typedef T Type; }; + +#define RAPIDJSON_REMOVEFPTR_(type) \ + typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ + < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type + +#define RAPIDJSON_ENABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type * = NULL + +#define RAPIDJSON_DISABLEIF(cond) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type * = NULL + +#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ + ::Type + +#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ + typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ + ::Type + +} // namespace internal +RAPIDJSON_NAMESPACE_END +//@endcond + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_META_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/pow10.h b/deps/rapidjson/include/rapidjson/internal/pow10.h new file mode 100644 index 0000000..eae1a43 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/pow10.h @@ -0,0 +1,55 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POW10_ +#define RAPIDJSON_POW10_ + +#include "../rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Computes integer powers of 10 in double (10.0^n). +/*! This function uses lookup table for fast and accurate results. + \param n non-negative exponent. Must <= 308. + \return 10.0^n +*/ +inline double Pow10(int n) { + static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes + 1e+0, + 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, + 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40, + 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60, + 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80, + 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100, + 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120, + 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140, + 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160, + 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180, + 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200, + 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220, + 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240, + 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260, + 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280, + 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300, + 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308 + }; + RAPIDJSON_ASSERT(n >= 0 && n <= 308); + return e[n]; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_POW10_ diff --git a/deps/rapidjson/include/rapidjson/internal/regex.h b/deps/rapidjson/include/rapidjson/internal/regex.h new file mode 100644 index 0000000..6446c40 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/regex.h @@ -0,0 +1,739 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_REGEX_H_ +#define RAPIDJSON_INTERNAL_REGEX_H_ + +#include "../allocators.h" +#include "../stream.h" +#include "stack.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifndef RAPIDJSON_REGEX_VERBOSE +#define RAPIDJSON_REGEX_VERBOSE 0 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// DecodedStream + +template +class DecodedStream { +public: + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } + unsigned Peek() { return codepoint_; } + unsigned Take() { + unsigned c = codepoint_; + if (c) // No further decoding when '\0' + Decode(); + return c; + } + +private: + void Decode() { + if (!Encoding::Decode(ss_, &codepoint_)) + codepoint_ = 0; + } + + SourceStream& ss_; + unsigned codepoint_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericRegex + +static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 +static const SizeType kRegexInvalidRange = ~SizeType(0); + +template +class GenericRegexSearch; + +//! Regular expression engine with subset of ECMAscript grammar. +/*! + Supported regular expression syntax: + - \c ab Concatenation + - \c a|b Alternation + - \c a? Zero or one + - \c a* Zero or more + - \c a+ One or more + - \c a{3} Exactly 3 times + - \c a{3,} At least 3 times + - \c a{3,5} 3 to 5 times + - \c (ab) Grouping + - \c ^a At the beginning + - \c a$ At the end + - \c . Any character + - \c [abc] Character classes + - \c [a-c] Character class range + - \c [a-z0-9_] Character class combination + - \c [^abc] Negated character classes + - \c [^a-c] Negated character class range + - \c [\b] Backspace (U+0008) + - \c \\| \\\\ ... Escape characters + - \c \\f Form feed (U+000C) + - \c \\n Line feed (U+000A) + - \c \\r Carriage return (U+000D) + - \c \\t Tab (U+0009) + - \c \\v Vertical tab (U+000B) + + \note This is a Thompson NFA engine, implemented with reference to + Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", + https://swtch.com/~rsc/regexp/regexp1.html +*/ +template +class GenericRegex { +public: + typedef Encoding EncodingType; + typedef typename Encoding::Ch Ch; + template friend class GenericRegexSearch; + + GenericRegex(const Ch* source, Allocator* allocator = 0) : + ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), + states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), + anchorBegin_(), anchorEnd_() + { + GenericStringStream ss(source); + DecodedStream, Encoding> ds(ss); + Parse(ds); + } + + ~GenericRegex() + { + RAPIDJSON_DELETE(ownAllocator_); + } + + bool IsValid() const { + return root_ != kRegexInvalidState; + } + +private: + enum Operator { + kZeroOrOne, + kZeroOrMore, + kOneOrMore, + kConcatenation, + kAlternation, + kLeftParenthesis + }; + + static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' + static const unsigned kRangeCharacterClass = 0xFFFFFFFE; + static const unsigned kRangeNegationFlag = 0x80000000; + + struct Range { + unsigned start; // + unsigned end; + SizeType next; + }; + + struct State { + SizeType out; //!< Equals to kInvalid for matching state + SizeType out1; //!< Equals to non-kInvalid for split + SizeType rangeStart; + unsigned codepoint; + }; + + struct Frag { + Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} + SizeType start; + SizeType out; //!< link-list of all output states + SizeType minIndex; + }; + + State& GetState(SizeType index) { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + const State& GetState(SizeType index) const { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + Range& GetRange(SizeType index) { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + const Range& GetRange(SizeType index) const { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + template + void Parse(DecodedStream& ds) { + Stack operandStack(allocator_, 256); // Frag + Stack operatorStack(allocator_, 256); // Operator + Stack atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push() = 0; + + unsigned codepoint; + while (ds.Peek() != 0) { + switch (codepoint = ds.Take()) { + case '^': + anchorBegin_ = true; + break; + + case '$': + anchorEnd_ = true; + break; + + case '|': + while (!operatorStack.Empty() && *operatorStack.template Top() < kAlternation) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + *operatorStack.template Push() = kAlternation; + *atomCountStack.template Top() = 0; + break; + + case '(': + *operatorStack.template Push() = kLeftParenthesis; + *atomCountStack.template Push() = 0; + break; + + case ')': + while (!operatorStack.Empty() && *operatorStack.template Top() != kLeftParenthesis) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + if (operatorStack.Empty()) + return; + operatorStack.template Pop(1); + atomCountStack.template Pop(1); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '?': + if (!Eval(operandStack, kZeroOrOne)) + return; + break; + + case '*': + if (!Eval(operandStack, kZeroOrMore)) + return; + break; + + case '+': + if (!Eval(operandStack, kOneOrMore)) + return; + break; + + case '{': + { + unsigned n, m; + if (!ParseUnsigned(ds, &n)) + return; + + if (ds.Peek() == ',') { + ds.Take(); + if (ds.Peek() == '}') + m = kInfinityQuantifier; + else if (!ParseUnsigned(ds, &m) || m < n) + return; + } + else + m = n; + + if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') + return; + ds.Take(); + } + break; + + case '.': + PushOperand(operandStack, kAnyCharacterClass); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '[': + { + SizeType range; + if (!ParseRange(ds, &range)) + return; + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); + GetState(s).rangeStart = range; + *operandStack.template Push() = Frag(s, s, s); + } + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '\\': // Escape character + if (!CharacterEscape(ds, &codepoint)) + return; // Unsupported escape character + // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: // Pattern character + PushOperand(operandStack, codepoint); + ImplicitConcatenation(atomCountStack, operatorStack); + } + } + + while (!operatorStack.Empty()) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + + // Link the operand to matching state. + if (operandStack.GetSize() == sizeof(Frag)) { + Frag* e = operandStack.template Pop(1); + Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); + root_ = e->start; + +#if RAPIDJSON_REGEX_VERBOSE + printf("root: %d\n", root_); + for (SizeType i = 0; i < stateCount_ ; i++) { + State& s = GetState(i); + printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); + } + printf("\n"); +#endif + } + } + + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { + State* s = states_.template Push(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } + + void PushOperand(Stack& operandStack, unsigned codepoint) { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push() = Frag(s, s, s); + } + + void ImplicitConcatenation(Stack& atomCountStack, Stack& operatorStack) { + if (*atomCountStack.template Top()) + *operatorStack.template Push() = kConcatenation; + (*atomCountStack.template Top())++; + } + + SizeType Append(SizeType l1, SizeType l2) { + SizeType old = l1; + while (GetState(l1).out != kRegexInvalidState) + l1 = GetState(l1).out; + GetState(l1).out = l2; + return old; + } + + void Patch(SizeType l, SizeType s) { + for (SizeType next; l != kRegexInvalidState; l = next) { + next = GetState(l).out; + GetState(l).out = s; + } + } + + bool Eval(Stack& operandStack, Operator op) { + switch (op) { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + Patch(e1.out, e2.start); + *operandStack.template Push() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); + } + return true; + + case kAlternation: + if (operandStack.GetSize() >= sizeof(Frag) * 2) { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); + return true; + } + return false; + + case kZeroOrOne: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; + + case kZeroOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(s, s, e.minIndex); + return true; + } + return false; + + case kOneOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + + default: + // syntax error (e.g. unclosed kLeftParenthesis) + return false; + } + } + + bool EvalQuantifier(Stack& operandStack, unsigned n, unsigned m) { + RAPIDJSON_ASSERT(n <= m); + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); + + if (n == 0) { + if (m == 0) // a{0} not support + return false; + else if (m == kInfinityQuantifier) + Eval(operandStack, kZeroOrMore); // a{0,} -> a* + else { + Eval(operandStack, kZeroOrOne); // a{0,5} -> a? + for (unsigned i = 0; i < m - 1; i++) + CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? + for (unsigned i = 0; i < m - 1; i++) + Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? + } + return true; + } + + for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a + CloneTopOperand(operandStack); + + if (m == kInfinityQuantifier) + Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ + else if (m > n) { + CloneTopOperand(operandStack); // a{3,5} -> a a a a + Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? + for (unsigned i = n; i < m - 1; i++) + CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? + for (unsigned i = n; i < m; i++) + Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? + } + + for (unsigned i = 0; i < n - 1; i++) + Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? + + return true; + } + + static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } + + void CloneTopOperand(Stack& operandStack) { + const Frag src = *operandStack.template Top(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push(count); + memcpy(s, &GetState(src.minIndex), count * sizeof(State)); + for (SizeType j = 0; j < count; j++) { + if (s[j].out != kRegexInvalidState) + s[j].out += count; + if (s[j].out1 != kRegexInvalidState) + s[j].out1 += count; + } + *operandStack.template Push() = Frag(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } + + template + bool ParseUnsigned(DecodedStream& ds, unsigned* u) { + unsigned r = 0; + if (ds.Peek() < '0' || ds.Peek() > '9') + return false; + while (ds.Peek() >= '0' && ds.Peek() <= '9') { + if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 + return false; // overflow + r = r * 10 + (ds.Take() - '0'); + } + *u = r; + return true; + } + + template + bool ParseRange(DecodedStream& ds, SizeType* range) { + bool isBegin = true; + bool negate = false; + int step = 0; + SizeType start = kRegexInvalidRange; + SizeType current = kRegexInvalidRange; + unsigned codepoint; + while ((codepoint = ds.Take()) != 0) { + if (isBegin) { + isBegin = false; + if (codepoint == '^') { + negate = true; + continue; + } + } + + switch (codepoint) { + case ']': + if (start == kRegexInvalidRange) + return false; // Error: nothing inside [] + if (step == 2) { // Add trailing '-' + SizeType r = NewRange('-'); + RAPIDJSON_ASSERT(current != kRegexInvalidRange); + GetRange(current).next = r; + } + if (negate) + GetRange(start).start |= kRangeNegationFlag; + *range = start; + return true; + + case '\\': + if (ds.Peek() == 'b') { + ds.Take(); + codepoint = 0x0008; // Escape backspace character + } + else if (!CharacterEscape(ds, &codepoint)) + return false; + // fall through to default + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + default: + switch (step) { + case 1: + if (codepoint == '-') { + step++; + break; + } + // fall through to step 0 for other characters + RAPIDJSON_DELIBERATE_FALLTHROUGH; + + case 0: + { + SizeType r = NewRange(codepoint); + if (current != kRegexInvalidRange) + GetRange(current).next = r; + if (start == kRegexInvalidRange) + start = r; + current = r; + } + step = 1; + break; + + default: + RAPIDJSON_ASSERT(step == 2); + GetRange(current).end = codepoint; + step = 0; + } + } + } + return false; + } + + SizeType NewRange(unsigned codepoint) { + Range* r = ranges_.template Push(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } + + template + bool CharacterEscape(DecodedStream& ds, unsigned* escapedCodepoint) { + unsigned codepoint; + switch (codepoint = ds.Take()) { + case '^': + case '$': + case '|': + case '(': + case ')': + case '?': + case '*': + case '+': + case '.': + case '[': + case ']': + case '{': + case '}': + case '\\': + *escapedCodepoint = codepoint; return true; + case 'f': *escapedCodepoint = 0x000C; return true; + case 'n': *escapedCodepoint = 0x000A; return true; + case 'r': *escapedCodepoint = 0x000D; return true; + case 't': *escapedCodepoint = 0x0009; return true; + case 'v': *escapedCodepoint = 0x000B; return true; + default: + return false; // Unsupported escape character + } + } + + Allocator* ownAllocator_; + Allocator* allocator_; + Stack states_; + Stack ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + bool anchorBegin_; + bool anchorEnd_; +}; + +template +class GenericRegexSearch { +public: + typedef typename RegexType::EncodingType Encoding; + typedef typename Encoding::Ch Ch; + + GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : + regex_(regex), allocator_(allocator), ownAllocator_(0), + state0_(allocator, 0), state1_(allocator, 0), stateSet_() + { + RAPIDJSON_ASSERT(regex_.IsValid()); + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); + state0_.template Reserve(regex_.stateCount_); + state1_.template Reserve(regex_.stateCount_); + } + + ~GenericRegexSearch() { + Allocator::Free(stateSet_); + RAPIDJSON_DELETE(ownAllocator_); + } + + template + bool Match(InputStream& is) { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) { + GenericStringStream is(s); + return Match(is); + } + + template + bool Search(InputStream& is) { + return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_); + } + + bool Search(const Ch* s) { + GenericStringStream is(s); + return Search(is); + } + +private: + typedef typename RegexType::State State; + typedef typename RegexType::Range Range; + + template + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) { + DecodedStream ds(is); + + state0_.Clear(); + Stack *current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); + + bool matched = AddState(*current, regex_.root_); + unsigned codepoint; + while (!current->Empty() && (codepoint = ds.Take()) != 0) { + std::memset(stateSet_, 0, stateSetSize); + next->Clear(); + matched = false; + for (const SizeType* s = current->template Bottom(); s != current->template End(); ++s) { + const State& sr = regex_.GetState(*s); + if (sr.codepoint == codepoint || + sr.codepoint == RegexType::kAnyCharacterClass || + (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + { + matched = AddState(*next, sr.out) || matched; + if (!anchorEnd && matched) + return true; + } + if (!anchorBegin) + AddState(*next, regex_.root_); + } + internal::Swap(current, next); + } + + return matched; + } + + size_t GetStateSetSize() const { + return (regex_.stateCount_ + 31) / 32 * 4; + } + + // Return whether the added states is a match state + bool AddState(Stack& l, SizeType index) { + RAPIDJSON_ASSERT(index != kRegexInvalidState); + + const State& s = regex_.GetState(index); + if (s.out1 != kRegexInvalidState) { // Split + bool matched = AddState(l, s.out); + return AddState(l, s.out1) || matched; + } + else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) { + stateSet_[index >> 5] |= (1u << (index & 31)); + *l.template PushUnsafe() = index; + } + return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. + } + + bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { + bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0; + while (rangeIndex != kRegexInvalidRange) { + const Range& r = regex_.GetRange(rangeIndex); + if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end) + return yes; + rangeIndex = r.next; + } + return !yes; + } + + const RegexType& regex_; + Allocator* allocator_; + Allocator* ownAllocator_; + Stack state0_; + Stack state1_; + uint32_t* stateSet_; +}; + +typedef GenericRegex > Regex; +typedef GenericRegexSearch RegexSearch; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_REGEX_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/stack.h b/deps/rapidjson/include/rapidjson/internal/stack.h new file mode 100644 index 0000000..73abd70 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/stack.h @@ -0,0 +1,232 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STACK_H_ +#define RAPIDJSON_INTERNAL_STACK_H_ + +#include "../allocators.h" +#include "swap.h" +#include + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// Stack + +//! A type-unsafe stack for storing different types of data. +/*! \tparam Allocator Allocator for allocating stack memory. +*/ +template +class Stack { +public: + // Optimization note: Do not allocate memory for stack_ in constructor. + // Do it lazily when first Push() -> Expand() -> Resize(). + Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack(Stack&& rhs) + : allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + stack_(rhs.stack_), + stackTop_(rhs.stackTop_), + stackEnd_(rhs.stackEnd_), + initialCapacity_(rhs.initialCapacity_) + { + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } +#endif + + ~Stack() { + Destroy(); + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Stack& operator=(Stack&& rhs) { + if (&rhs != this) + { + Destroy(); + + allocator_ = rhs.allocator_; + ownAllocator_ = rhs.ownAllocator_; + stack_ = rhs.stack_; + stackTop_ = rhs.stackTop_; + stackEnd_ = rhs.stackEnd_; + initialCapacity_ = rhs.initialCapacity_; + + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.stack_ = 0; + rhs.stackTop_ = 0; + rhs.stackEnd_ = 0; + rhs.initialCapacity_ = 0; + } + return *this; + } +#endif + + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + + void Clear() { stackTop_ = stack_; } + + void ShrinkToFit() { + if (Empty()) { + // If the stack is empty, completely deallocate the memory. + Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) + stack_ = 0; + stackTop_ = 0; + stackEnd_ = 0; + } + else + Resize(GetSize()); + } + + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. + template + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { + // Expand the stack if needed + if (RAPIDJSON_UNLIKELY(static_cast(sizeof(T) * count) > (stackEnd_ - stackTop_))) + Expand(count); + } + + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve(count); + return PushUnsafe(count); + } + + template + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_); + RAPIDJSON_ASSERT(static_cast(sizeof(T) * count) <= (stackEnd_ - stackTop_)); + T* ret = reinterpret_cast(stackTop_); + stackTop_ += sizeof(T) * count; + return ret; + } + + template + T* Pop(size_t count) { + RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); + stackTop_ -= count * sizeof(T); + return reinterpret_cast(stackTop_); + } + + template + T* Top() { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + T* End() { return reinterpret_cast(stackTop_); } + + template + const T* End() const { return reinterpret_cast(stackTop_); } + + template + T* Bottom() { return reinterpret_cast(stack_); } + + template + const T* Bottom() const { return reinterpret_cast(stack_); } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + + bool Empty() const { return stackTop_ == stack_; } + size_t GetSize() const { return static_cast(stackTop_ - stack_); } + size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } + +private: + template + void Expand(size_t count) { + // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity. + size_t newCapacity; + if (stack_ == 0) { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + newCapacity = initialCapacity_; + } else { + newCapacity = GetCapacity(); + newCapacity += (newCapacity + 1) / 2; + } + size_t newSize = GetSize() + sizeof(T) * count; + if (newCapacity < newSize) + newCapacity = newSize; + + Resize(newCapacity); + } + + void Resize(size_t newCapacity) { + const size_t size = GetSize(); // Backup the current size + stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); + stackTop_ = stack_ + size; + stackEnd_ = stack_ + newCapacity; + } + + void Destroy() { + Allocator::Free(stack_); + RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack + } + + // Prohibit copy constructor & assignment operator. + Stack(const Stack&); + Stack& operator=(const Stack&); + + Allocator* allocator_; + Allocator* ownAllocator_; + char *stack_; + char *stackTop_; + char *stackEnd_; + size_t initialCapacity_; +}; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STACK_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/strfunc.h b/deps/rapidjson/include/rapidjson/internal/strfunc.h new file mode 100644 index 0000000..b698a8f --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/strfunc.h @@ -0,0 +1,83 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ +#define RAPIDJSON_INTERNAL_STRFUNC_H_ + +#include "../stream.h" +#include + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom strlen() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s Null-terminated input string. + \return Number of characters in the string. + \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints. +*/ +template +inline SizeType StrLen(const Ch* s) { + RAPIDJSON_ASSERT(s != 0); + const Ch* p = s; + while (*p) ++p; + return SizeType(p - s); +} + +template <> +inline SizeType StrLen(const char* s) { + return SizeType(std::strlen(s)); +} + +template <> +inline SizeType StrLen(const wchar_t* s) { + return SizeType(std::wcslen(s)); +} + +//! Custom strcmpn() which works on different character types. +/*! \tparam Ch Character type (e.g. char, wchar_t, short) + \param s1 Null-terminated input string. + \param s2 Null-terminated input string. + \return 0 if equal +*/ +template +inline int StrCmp(const Ch* s1, const Ch* s2) { + RAPIDJSON_ASSERT(s1 != 0); + RAPIDJSON_ASSERT(s2 != 0); + while(*s1 && (*s1 == *s2)) { s1++; s2++; } + return static_cast(*s1) < static_cast(*s2) ? -1 : static_cast(*s1) > static_cast(*s2); +} + +//! Returns number of code points in a encoded string. +template +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + RAPIDJSON_ASSERT(s != 0); + RAPIDJSON_ASSERT(outCount != 0); + GenericStringStream is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_INTERNAL_STRFUNC_H_ diff --git a/deps/rapidjson/include/rapidjson/internal/strtod.h b/deps/rapidjson/include/rapidjson/internal/strtod.h new file mode 100644 index 0000000..55f0e38 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/strtod.h @@ -0,0 +1,293 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRTOD_ +#define RAPIDJSON_STRTOD_ + +#include "ieee754.h" +#include "biginteger.h" +#include "diyfp.h" +#include "pow10.h" +#include +#include + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +inline double FastPath(double significand, int exp) { + if (exp < -308) + return 0.0; + else if (exp >= 0) + return significand * internal::Pow10(exp); + else + return significand / internal::Pow10(-exp); +} + +inline double StrtodNormalPrecision(double d, int p) { + if (p < -308) { + // Prevent expSum < -308, making Pow10(p) = 0 + d = FastPath(d, -308); + d = FastPath(d, p + 308); + } + else + d = FastPath(d, p); + return d; +} + +template +inline T Min3(T a, T b, T c) { + T m = a; + if (m > b) m = b; + if (m > c) m = c; + return m; +} + +inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { + const Double db(b); + const uint64_t bInt = db.IntegerSignificand(); + const int bExp = db.IntegerExponent(); + const int hExp = bExp - 1; + + int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + BigInteger dS = d; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); + + BigInteger delta(0); + dS.Difference(bS, &delta); + + return delta.Compare(hS); +} + +inline bool StrtodFast(double d, int p, double* result) { + // Use fast path for string-to-double conversion if possible + // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ + if (p > 22 && p < 22 + 16) { + // Fast Path Cases In Disguise + d *= internal::Pow10(p - 22); + p = 22; + } + + if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 + *result = FastPath(d, p); + return true; + } + else + return false; +} + +// Compute an approximation and see if it is within 1/2 ULP +template +inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) { + uint64_t significand = 0; + int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 + for (; i < dLen; i++) { + if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || + (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5'))) + break; + significand = significand * 10u + static_cast(decimals[i] - Ch('0')); + } + + if (i < dLen && decimals[i] >= Ch('5')) // Rounding + significand++; + + int remaining = dLen - i; + const int kUlpShift = 3; + const int kUlp = 1 << kUlpShift; + int64_t error = (remaining == 0) ? 0 : kUlp / 2; + + DiyFp v(significand, 0); + v = v.Normalize(); + error <<= -v.e; + + dExp += remaining; + + int actualExp; + DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); + if (actualExp != dExp) { + static const DiyFp kPow10[] = { + DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1 + DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2 + DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3 + DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4 + DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5 + DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6 + DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7 + }; + int adjustment = dExp - actualExp; + RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8); + v = v * kPow10[adjustment - 1]; + if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit + error += kUlp / 2; + } + + v = v * cachedPower; + + error += kUlp + (error == 0 ? 0 : 1); + + const int oldExp = v.e; + v = v.Normalize(); + error <<= oldExp - v.e; + + const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + int precisionSize = 64 - effectiveSignificandSize; + if (precisionSize + kUlpShift >= 64) { + int scaleExp = (precisionSize + kUlpShift) - 63; + v.f >>= scaleExp; + v.e += scaleExp; + error = (error >> scaleExp) + 1 + kUlp; + precisionSize -= scaleExp; + } + + DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); + const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; + const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; + if (precisionBits >= halfWay + static_cast(error)) { + rounded.f++; + if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) + rounded.f >>= 1; + rounded.e++; + } + } + + *result = rounded.ToDouble(); + + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); +} + +template +inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) { + RAPIDJSON_ASSERT(dLen >= 0); + const BigInteger dInt(decimals, static_cast(dLen)); + Double a(approx); + int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); + if (cmp < 0) + return a.Value(); // within half ULP + else if (cmp == 0) { + // Round towards even + if (a.Significand() & 1) + return a.NextPositiveDouble(); + else + return a.Value(); + } + else // adjustment + return a.NextPositiveDouble(); +} + +template +inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) { + RAPIDJSON_ASSERT(d >= 0.0); + RAPIDJSON_ASSERT(length >= 1); + + double result = 0.0; + if (StrtodFast(d, p, &result)) + return result; + + RAPIDJSON_ASSERT(length <= INT_MAX); + int dLen = static_cast(length); + + RAPIDJSON_ASSERT(length >= decimalPosition); + RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX); + int dExpAdjust = static_cast(length - decimalPosition); + + RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust); + int dExp = exp - dExpAdjust; + + // Make sure length+dExp does not overflow + RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen); + + // Trim leading zeros + while (dLen > 0 && *decimals == '0') { + dLen--; + decimals++; + } + + // Trim trailing zeros + while (dLen > 0 && decimals[dLen - 1] == '0') { + dLen--; + dExp++; + } + + if (dLen == 0) { // Buffer only contains zeros. + return 0.0; + } + + // Trim right-most digits + const int kMaxDecimalDigit = 767 + 1; + if (dLen > kMaxDecimalDigit) { + dExp += dLen - kMaxDecimalDigit; + dLen = kMaxDecimalDigit; + } + + // If too small, underflow to zero. + // Any x <= 10^-324 is interpreted as zero. + if (dLen + dExp <= -324) + return 0.0; + + // If too large, overflow to infinity. + // Any x >= 10^309 is interpreted as +infinity. + if (dLen + dExp > 309) + return std::numeric_limits::infinity(); + + if (StrtodDiyFp(decimals, dLen, dExp, &result)) + return result; + + // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison + return StrtodBigInteger(result, decimals, dLen, dExp); +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STRTOD_ diff --git a/deps/rapidjson/include/rapidjson/internal/swap.h b/deps/rapidjson/include/rapidjson/internal/swap.h new file mode 100644 index 0000000..2cf92f9 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/internal/swap.h @@ -0,0 +1,46 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_SWAP_H_ +#define RAPIDJSON_INTERNAL_SWAP_H_ + +#include "../rapidjson.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +//! Custom swap() to avoid dependency on C++ header +/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. + \note This has the same semantics as std::swap(). +*/ +template +inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { + T tmp = a; + a = b; + b = tmp; +} + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/deps/rapidjson/include/rapidjson/istreamwrapper.h b/deps/rapidjson/include/rapidjson/istreamwrapper.h new file mode 100644 index 0000000..01437ec --- /dev/null +++ b/deps/rapidjson/include/rapidjson/istreamwrapper.h @@ -0,0 +1,128 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ISTREAMWRAPPER_H_ +#define RAPIDJSON_ISTREAMWRAPPER_H_ + +#include "stream.h" +#include +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::istringstream + - \c std::stringstream + - \c std::wistringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wifstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_istream. +*/ + +template +class BasicIStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + + //! Constructor. + /*! + \param stream stream opened for read. + */ + BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + Read(); + } + + //! Constructor. + /*! + \param stream stream opened for read. + \param buffer user-supplied buffer. + \param bufferSize size of buffer in bytes. Must >=4 bytes. + */ + BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { + RAPIDJSON_ASSERT(bufferSize >= 4); + Read(); + } + + Ch Peek() const { return *current_; } + Ch Take() { Ch c = *current_; Read(); return c; } + size_t Tell() const { return count_ + static_cast(current_ - buffer_); } + + // Not implemented + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; + } + +private: + BasicIStreamWrapper(); + BasicIStreamWrapper(const BasicIStreamWrapper&); + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + + void Read() { + if (current_ < bufferLast_) + ++current_; + else if (!eof_) { + count_ += readCount_; + readCount_ = bufferSize_; + bufferLast_ = buffer_ + readCount_ - 1; + current_ = buffer_; + + if (!stream_.read(buffer_, static_cast(bufferSize_))) { + readCount_ = static_cast(stream_.gcount()); + *(bufferLast_ = buffer_ + readCount_) = '\0'; + eof_ = true; + } + } + } + + StreamType &stream_; + Ch peekBuffer_[4], *buffer_; + size_t bufferSize_; + Ch *bufferLast_; + Ch *current_; + size_t readCount_; + size_t count_; //!< Number of characters read + bool eof_; +}; + +typedef BasicIStreamWrapper IStreamWrapper; +typedef BasicIStreamWrapper WIStreamWrapper; + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ISTREAMWRAPPER_H_ diff --git a/deps/rapidjson/include/rapidjson/memorybuffer.h b/deps/rapidjson/include/rapidjson/memorybuffer.h new file mode 100644 index 0000000..ffbc41e --- /dev/null +++ b/deps/rapidjson/include/rapidjson/memorybuffer.h @@ -0,0 +1,70 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYBUFFER_H_ +#define RAPIDJSON_MEMORYBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output byte stream. +/*! + This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. + + It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. + + Differences between MemoryBuffer and StringBuffer: + 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. + 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. + + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +struct GenericMemoryBuffer { + typedef char Ch; // byte + + GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + + void Put(Ch c) { *stack_.template Push() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { stack_.ShrinkToFit(); } + Ch* Push(size_t count) { return stack_.template Push(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetBuffer() const { + return stack_.template Bottom(); + } + + size_t GetSize() const { return stack_.GetSize(); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; +}; + +typedef GenericMemoryBuffer<> MemoryBuffer; + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { + std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/deps/rapidjson/include/rapidjson/memorystream.h b/deps/rapidjson/include/rapidjson/memorystream.h new file mode 100644 index 0000000..77af6c9 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/memorystream.h @@ -0,0 +1,71 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_MEMORYSTREAM_H_ +#define RAPIDJSON_MEMORYSTREAM_H_ + +#include "stream.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory input byte stream. +/*! + This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. + + It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. + + Differences between MemoryStream and StringStream: + 1. StringStream has encoding but MemoryStream is a byte stream. + 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. + 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). + \note implements Stream concept +*/ +struct MemoryStream { + typedef char Ch; // byte + + MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} + + Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } + Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } + size_t Tell() const { return static_cast(src_ - begin_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + return Tell() + 4 <= size_ ? src_ : 0; + } + + const Ch* src_; //!< Current read position. + const Ch* begin_; //!< Original head of the string. + const Ch* end_; //!< End of stream. + size_t size_; //!< Size of the stream. +}; + +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/deps/rapidjson/include/rapidjson/msinttypes/inttypes.h b/deps/rapidjson/include/rapidjson/msinttypes/inttypes.h new file mode 100644 index 0000000..1811128 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/msinttypes/inttypes.h @@ -0,0 +1,316 @@ +// ISO C9x compliant inttypes.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// 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 product 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 AUTHOR ``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 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. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_INTTYPES_H_ // [ +#define _MSC_INTTYPES_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "stdint.h" + +// miloyip: VC supports inttypes.h since VC2013 +#if _MSC_VER >= 1800 +#include +#else + +// 7.8 Format conversion of integer types + +typedef struct { + intmax_t quot; + intmax_t rem; +} imaxdiv_t; + +// 7.8.1 Macros for format specifiers + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 + +// The fprintf macros for signed integers are: +#define PRId8 "d" +#define PRIi8 "i" +#define PRIdLEAST8 "d" +#define PRIiLEAST8 "i" +#define PRIdFAST8 "d" +#define PRIiFAST8 "i" + +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIdLEAST16 "hd" +#define PRIiLEAST16 "hi" +#define PRIdFAST16 "hd" +#define PRIiFAST16 "hi" + +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIdLEAST32 "I32d" +#define PRIiLEAST32 "I32i" +#define PRIdFAST32 "I32d" +#define PRIiFAST32 "I32i" + +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIdLEAST64 "I64d" +#define PRIiLEAST64 "I64i" +#define PRIdFAST64 "I64d" +#define PRIiFAST64 "I64i" + +#define PRIdMAX "I64d" +#define PRIiMAX "I64i" + +#define PRIdPTR "Id" +#define PRIiPTR "Ii" + +// The fprintf macros for unsigned integers are: +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRIoLEAST8 "o" +#define PRIuLEAST8 "u" +#define PRIxLEAST8 "x" +#define PRIXLEAST8 "X" +#define PRIoFAST8 "o" +#define PRIuFAST8 "u" +#define PRIxFAST8 "x" +#define PRIXFAST8 "X" + +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRIoLEAST16 "ho" +#define PRIuLEAST16 "hu" +#define PRIxLEAST16 "hx" +#define PRIXLEAST16 "hX" +#define PRIoFAST16 "ho" +#define PRIuFAST16 "hu" +#define PRIxFAST16 "hx" +#define PRIXFAST16 "hX" + +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRIoLEAST32 "I32o" +#define PRIuLEAST32 "I32u" +#define PRIxLEAST32 "I32x" +#define PRIXLEAST32 "I32X" +#define PRIoFAST32 "I32o" +#define PRIuFAST32 "I32u" +#define PRIxFAST32 "I32x" +#define PRIXFAST32 "I32X" + +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" +#define PRIoLEAST64 "I64o" +#define PRIuLEAST64 "I64u" +#define PRIxLEAST64 "I64x" +#define PRIXLEAST64 "I64X" +#define PRIoFAST64 "I64o" +#define PRIuFAST64 "I64u" +#define PRIxFAST64 "I64x" +#define PRIXFAST64 "I64X" + +#define PRIoMAX "I64o" +#define PRIuMAX "I64u" +#define PRIxMAX "I64x" +#define PRIXMAX "I64X" + +#define PRIoPTR "Io" +#define PRIuPTR "Iu" +#define PRIxPTR "Ix" +#define PRIXPTR "IX" + +// The fscanf macros for signed integers are: +#define SCNd8 "d" +#define SCNi8 "i" +#define SCNdLEAST8 "d" +#define SCNiLEAST8 "i" +#define SCNdFAST8 "d" +#define SCNiFAST8 "i" + +#define SCNd16 "hd" +#define SCNi16 "hi" +#define SCNdLEAST16 "hd" +#define SCNiLEAST16 "hi" +#define SCNdFAST16 "hd" +#define SCNiFAST16 "hi" + +#define SCNd32 "ld" +#define SCNi32 "li" +#define SCNdLEAST32 "ld" +#define SCNiLEAST32 "li" +#define SCNdFAST32 "ld" +#define SCNiFAST32 "li" + +#define SCNd64 "I64d" +#define SCNi64 "I64i" +#define SCNdLEAST64 "I64d" +#define SCNiLEAST64 "I64i" +#define SCNdFAST64 "I64d" +#define SCNiFAST64 "I64i" + +#define SCNdMAX "I64d" +#define SCNiMAX "I64i" + +#ifdef _WIN64 // [ +# define SCNdPTR "I64d" +# define SCNiPTR "I64i" +#else // _WIN64 ][ +# define SCNdPTR "ld" +# define SCNiPTR "li" +#endif // _WIN64 ] + +// The fscanf macros for unsigned integers are: +#define SCNo8 "o" +#define SCNu8 "u" +#define SCNx8 "x" +#define SCNX8 "X" +#define SCNoLEAST8 "o" +#define SCNuLEAST8 "u" +#define SCNxLEAST8 "x" +#define SCNXLEAST8 "X" +#define SCNoFAST8 "o" +#define SCNuFAST8 "u" +#define SCNxFAST8 "x" +#define SCNXFAST8 "X" + +#define SCNo16 "ho" +#define SCNu16 "hu" +#define SCNx16 "hx" +#define SCNX16 "hX" +#define SCNoLEAST16 "ho" +#define SCNuLEAST16 "hu" +#define SCNxLEAST16 "hx" +#define SCNXLEAST16 "hX" +#define SCNoFAST16 "ho" +#define SCNuFAST16 "hu" +#define SCNxFAST16 "hx" +#define SCNXFAST16 "hX" + +#define SCNo32 "lo" +#define SCNu32 "lu" +#define SCNx32 "lx" +#define SCNX32 "lX" +#define SCNoLEAST32 "lo" +#define SCNuLEAST32 "lu" +#define SCNxLEAST32 "lx" +#define SCNXLEAST32 "lX" +#define SCNoFAST32 "lo" +#define SCNuFAST32 "lu" +#define SCNxFAST32 "lx" +#define SCNXFAST32 "lX" + +#define SCNo64 "I64o" +#define SCNu64 "I64u" +#define SCNx64 "I64x" +#define SCNX64 "I64X" +#define SCNoLEAST64 "I64o" +#define SCNuLEAST64 "I64u" +#define SCNxLEAST64 "I64x" +#define SCNXLEAST64 "I64X" +#define SCNoFAST64 "I64o" +#define SCNuFAST64 "I64u" +#define SCNxFAST64 "I64x" +#define SCNXFAST64 "I64X" + +#define SCNoMAX "I64o" +#define SCNuMAX "I64u" +#define SCNxMAX "I64x" +#define SCNXMAX "I64X" + +#ifdef _WIN64 // [ +# define SCNoPTR "I64o" +# define SCNuPTR "I64u" +# define SCNxPTR "I64x" +# define SCNXPTR "I64X" +#else // _WIN64 ][ +# define SCNoPTR "lo" +# define SCNuPTR "lu" +# define SCNxPTR "lx" +# define SCNXPTR "lX" +#endif // _WIN64 ] + +#endif // __STDC_FORMAT_MACROS ] + +// 7.8.2 Functions for greatest-width integer types + +// 7.8.2.1 The imaxabs function +#define imaxabs _abs64 + +// 7.8.2.2 The imaxdiv function + +// This is modified version of div() function from Microsoft's div.c found +// in %MSVC.NET%\crt\src\div.c +#ifdef STATIC_IMAXDIV // [ +static +#else // STATIC_IMAXDIV ][ +_inline +#endif // STATIC_IMAXDIV ] +imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + if (numer < 0 && result.rem > 0) { + // did division wrong; must fix up + ++result.quot; + result.rem -= denom; + } + + return result; +} + +// 7.8.2.3 The strtoimax and strtoumax functions +#define strtoimax _strtoi64 +#define strtoumax _strtoui64 + +// 7.8.2.4 The wcstoimax and wcstoumax functions +#define wcstoimax _wcstoi64 +#define wcstoumax _wcstoui64 + +#endif // _MSC_VER >= 1800 + +#endif // _MSC_INTTYPES_H_ ] diff --git a/deps/rapidjson/include/rapidjson/msinttypes/stdint.h b/deps/rapidjson/include/rapidjson/msinttypes/stdint.h new file mode 100644 index 0000000..3d4477b --- /dev/null +++ b/deps/rapidjson/include/rapidjson/msinttypes/stdint.h @@ -0,0 +1,300 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2013 Alexander Chemeris +// +// 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 product 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 AUTHOR ``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 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. +// +/////////////////////////////////////////////////////////////////////////////// + +// The above software in this distribution may have been modified by +// THL A29 Limited ("Tencent Modifications"). +// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. +#if _MSC_VER >= 1600 // [ +#include + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +#undef INT8_C +#undef INT16_C +#undef INT32_C +#undef INT64_C +#undef UINT8_C +#undef UINT16_C +#undef UINT32_C +#undef UINT64_C + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#else // ] _MSC_VER >= 1700 [ + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we have to wrap include with 'extern "C++" {}' +// or compiler would give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if defined(__cplusplus) && !defined(_M_ARM) +extern "C" { +#endif +# include +#if defined(__cplusplus) && !defined(_M_ARM) +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +// These #ifndef's are needed to prevent collisions with . +// Check out Issue 9 for the details. +#ifndef INTMAX_C // [ +# define INTMAX_C INT64_C +#endif // INTMAX_C ] +#ifndef UINTMAX_C // [ +# define UINTMAX_C UINT64_C +#endif // UINTMAX_C ] + +#endif // __STDC_CONSTANT_MACROS ] + +#endif // _MSC_VER >= 1600 ] + +#endif // _MSC_STDINT_H_ ] diff --git a/deps/rapidjson/include/rapidjson/ostreamwrapper.h b/deps/rapidjson/include/rapidjson/ostreamwrapper.h new file mode 100644 index 0000000..11ed4d3 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/ostreamwrapper.h @@ -0,0 +1,81 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_OSTREAMWRAPPER_H_ +#define RAPIDJSON_OSTREAMWRAPPER_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::ostringstream + - \c std::stringstream + - \c std::wpstringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wofstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_ostream. +*/ + +template +class BasicOStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} + + void Put(Ch c) { + stream_.put(c); + } + + void Flush() { + stream_.flush(); + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + BasicOStreamWrapper(const BasicOStreamWrapper&); + BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); + + StreamType& stream_; +}; + +typedef BasicOStreamWrapper OStreamWrapper; +typedef BasicOStreamWrapper WOStreamWrapper; + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_OSTREAMWRAPPER_H_ diff --git a/deps/rapidjson/include/rapidjson/pointer.h b/deps/rapidjson/include/rapidjson/pointer.h new file mode 100644 index 0000000..6f4ef38 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/pointer.h @@ -0,0 +1,1476 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_POINTER_H_ +#define RAPIDJSON_POINTER_H_ + +#include "document.h" +#include "uri.h" +#include "internal/itoa.h" +#include "error/error.h" // PointerParseErrorCode + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token + +/////////////////////////////////////////////////////////////////////////////// +// GenericPointer + +//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. +/*! + This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" + (https://tools.ietf.org/html/rfc6901). + + A JSON pointer is for identifying a specific value in a JSON document + (GenericDocument). It can simplify coding of DOM tree manipulation, because it + can access multiple-level depth of DOM tree with single API call. + + After it parses a string representation (e.g. "/foo/0" or URI fragment + representation (e.g. "#/foo/0") into its internal representation (tokens), + it can be used to resolve a specific value in multiple documents, or sub-tree + of documents. + + Contrary to GenericValue, Pointer can be copy constructed and copy assigned. + Apart from assignment, a Pointer cannot be modified after construction. + + Although Pointer is very convenient, please aware that constructing Pointer + involves parsing and dynamic memory allocation. A special constructor with user- + supplied tokens eliminates these. + + GenericPointer depends on GenericDocument and GenericValue. + + \tparam ValueType The value type of the DOM tree. E.g. GenericValue > + \tparam Allocator The allocator type for allocating memory for internal representation. + + \note GenericPointer uses same encoding of ValueType. + However, Allocator of GenericPointer is independent of Allocator of Value. +*/ +template +class GenericPointer { +public: + typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value + typedef GenericUri UriType; + + + //! A token is the basic units of internal representation. + /*! + A JSON pointer string representation "/foo/123" is parsed to two tokens: + "foo" and 123. 123 will be represented in both numeric form and string form. + They are resolved according to the actual value type (object or array). + + For token that are not numbers, or the numeric value is out of bound + (greater than limits of SizeType), they are only treated as string form + (i.e. the token's index will be equal to kPointerInvalidIndex). + + This struct is public so that user can create a Pointer without parsing and + allocation, using a special constructor. + */ + struct Token { + const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. + SizeType length; //!< Length of the name. + SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. + }; + + //!@name Constructors and destructor. + //@{ + + //! Default constructor. + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A null-terminated, string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + */ + explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, internal::StrLen(source)); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Constructor that parses a string or URI fragment representation. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. + */ + explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source.c_str(), source.size()); + } +#endif + + //! Constructor that parses a string or URI fragment representation, with length of the source string. + /*! + \param source A string or URI fragment representation of JSON pointer. + \param length Length of source. + \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. + \note Slightly faster than the overload without length. + */ + GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + Parse(source, length); + } + + //! Constructor with user-supplied tokens. + /*! + This constructor let user supplies const array of tokens. + This prevents the parsing process and eliminates allocation. + This is preferred for memory constrained environments. + + \param tokens An constant array of tokens representing the JSON pointer. + \param tokenCount Number of tokens. + + \b Example + \code + #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } + #define INDEX(i) { #i, sizeof(#i) - 1, i } + + static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; + static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + // Equivalent to static const Pointer p("/foo/123"); + + #undef NAME + #undef INDEX + \endcode + */ + GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Copy constructor. + GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + *this = rhs; + } + + //! Destructor. + ~GenericPointer() { + if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. + Allocator::Free(tokens_); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator. + GenericPointer& operator=(const GenericPointer& rhs) { + if (this != &rhs) { + // Do not delete ownAllcator + if (nameBuffer_) + Allocator::Free(tokens_); + + tokenCount_ = rhs.tokenCount_; + parseErrorOffset_ = rhs.parseErrorOffset_; + parseErrorCode_ = rhs.parseErrorCode_; + + if (rhs.nameBuffer_) + CopyFromRaw(rhs); // Normally parsed tokens. + else { + tokens_ = rhs.tokens_; // User supplied const tokens. + nameBuffer_ = 0; + } + } + return *this; + } + + //! Swap the content of this pointer with an other. + /*! + \param other The pointer to swap with. + \note Constant complexity. + */ + GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, other.allocator_); + internal::Swap(ownAllocator_, other.ownAllocator_); + internal::Swap(nameBuffer_, other.nameBuffer_); + internal::Swap(tokens_, other.tokens_); + internal::Swap(tokenCount_, other.tokenCount_); + internal::Swap(parseErrorOffset_, other.parseErrorOffset_); + internal::Swap(parseErrorCode_, other.parseErrorCode_); + return *this; + } + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.pointer, b.pointer); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //@} + + //!@name Append token + //@{ + + //! Append a token and return a new Pointer + /*! + \param token Token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Token& token, Allocator* allocator = 0) const { + GenericPointer r; + r.allocator_ = allocator; + Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); + std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); + r.tokens_[tokenCount_].name = p; + r.tokens_[tokenCount_].length = token.length; + r.tokens_[tokenCount_].index = token.index; + return r; + } + + //! Append a name token with length, and return a new Pointer + /*! + \param name Name to be appended. + \param length Length of name. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { + Token token = { name, length, kPointerInvalidIndex }; + return Append(token, allocator); + } + + //! Append a name token without length, and return a new Pointer + /*! + \param name Name (const Ch*) to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) + Append(T* name, Allocator* allocator = 0) const { + return Append(name, internal::StrLen(name), allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Append a name token, and return a new Pointer + /*! + \param name Name to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { + return Append(name.c_str(), static_cast(name.size()), allocator); + } +#endif + + //! Append a index token, and return a new Pointer + /*! + \param index Index to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(SizeType index, Allocator* allocator = 0) const { + char buffer[21]; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast(end - buffer); + buffer[length] = '\0'; + + if (sizeof(Ch) == 1) { + Token token = { reinterpret_cast(buffer), length, index }; + return Append(token, allocator); + } + else { + Ch name[21]; + for (size_t i = 0; i <= length; i++) + name[i] = static_cast(buffer[i]); + Token token = { name, length, index }; + return Append(token, allocator); + } + } + + //! Append a token by value, and return a new Pointer + /*! + \param token token to be appended. + \param allocator Allocator for the newly return Pointer. + \return A new Pointer with appended token. + */ + GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { + if (token.IsString()) + return Append(token.GetString(), token.GetStringLength(), allocator); + else { + RAPIDJSON_ASSERT(token.IsUint64()); + RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); + return Append(static_cast(token.GetUint64()), allocator); + } + } + + //!@name Handling Parse Error + //@{ + + //! Check whether this is a valid pointer. + bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } + + //! Get the parsing error offset in code unit. + size_t GetParseErrorOffset() const { return parseErrorOffset_; } + + //! Get the parsing error code. + PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } + + //@} + + //! Get the allocator of this pointer. + Allocator& GetAllocator() { return *allocator_; } + + //!@name Tokens + //@{ + + //! Get the token array (const version only). + const Token* GetTokens() const { return tokens_; } + + //! Get the number of tokens. + size_t GetTokenCount() const { return tokenCount_; } + + //@} + + //!@name Equality/inequality operators + //@{ + + //! Equality operator. + /*! + \note When any pointers are invalid, always returns false. + */ + bool operator==(const GenericPointer& rhs) const { + if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) + return false; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index || + tokens_[i].length != rhs.tokens_[i].length || + (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) + { + return false; + } + } + + return true; + } + + //! Inequality operator. + /*! + \note When any pointers are invalid, always returns true. + */ + bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } + + //! Less than operator. + /*! + \note Invalid pointers are always greater than valid ones. + */ + bool operator<(const GenericPointer& rhs) const { + if (!IsValid()) + return false; + if (!rhs.IsValid()) + return true; + + if (tokenCount_ != rhs.tokenCount_) + return tokenCount_ < rhs.tokenCount_; + + for (size_t i = 0; i < tokenCount_; i++) { + if (tokens_[i].index != rhs.tokens_[i].index) + return tokens_[i].index < rhs.tokens_[i].index; + + if (tokens_[i].length != rhs.tokens_[i].length) + return tokens_[i].length < rhs.tokens_[i].length; + + if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length)) + return cmp < 0; + } + + return false; + } + + //@} + + //!@name Stringify + //@{ + + //! Stringify the pointer into string representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + return Stringify(os); + } + + //! Stringify the pointer into URI fragment representation. + /*! + \tparam OutputStream Type of output stream. + \param os The output stream. + */ + template + bool StringifyUriFragment(OutputStream& os) const { + return Stringify(os); + } + + //@} + + //!@name Create value + //@{ + + //! Create a value in a subtree. + /*! + If the value is not exist, it creates all parent values and a JSON Null value. + So it always succeed and return the newly created or existing value. + + Remind that it may change types of parents according to tokens, so it + potentially removes previously stored values. For example, if a document + was an array, and "/foo" is used to create a value, then the document + will be changed to an object, and all existing array elements are lost. + + \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created (a JSON Null value), or already exists value. + */ + ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + bool exist = true; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + if (v->IsArray() && t->name[0] == '-' && t->length == 1) { + v->PushBack(ValueType().Move(), allocator); + v = &((*v)[v->Size() - 1]); + exist = false; + } + else { + if (t->index == kPointerInvalidIndex) { // must be object name + if (!v->IsObject()) + v->SetObject(); // Change to Object + } + else { // object name or array index + if (!v->IsArray() && !v->IsObject()) + v->SetArray(); // Change to Array + } + + if (v->IsArray()) { + if (t->index >= v->Size()) { + v->Reserve(t->index + 1, allocator); + while (t->index >= v->Size()) + v->PushBack(ValueType().Move(), allocator); + exist = false; + } + v = &((*v)[t->index]); + } + else { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) { + v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); + m = v->MemberEnd(); + v = &(--m)->value; // Assumes AddMember() appends at the end + exist = false; + } + else + v = &m->value; + } + } + } + + if (alreadyExist) + *alreadyExist = exist; + + return *v; + } + + //! Creates a value in a document. + /*! + \param document A document to be resolved. + \param alreadyExist If non-null, it stores whether the resolved value is already exist. + \return The resolved newly created, or already exists value. + */ + template + ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { + return Create(document, document.GetAllocator(), alreadyExist); + } + + //@} + + //!@name Compute URI + //@{ + + //! Compute the in-scope URI for a subtree. + // For use with JSON pointers into JSON schema documents. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param rootUri Root URI + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \param allocator Allocator for Uris + \return Uri if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a URI cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { + static const Ch kIdString[] = { 'i', 'd', '\0' }; + static const ValueType kIdValue(kIdString, 2); + UriType base = UriType(rootUri, allocator); + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + // See if we have an id, and if so resolve with the current base + typename ValueType::MemberIterator m = v->FindMember(kIdValue); + if (m != v->MemberEnd() && (m->value).IsString()) { + UriType here = UriType(m->value, allocator).Resolve(base, allocator); + base = here; + } + m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return UriType(allocator); + } + return base; + } + + UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const { + return GetUri(const_cast(root), rootUri, unresolvedTokenIndex, allocator); + } + + + //!@name Query value + //@{ + + //! Query a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. + \return Pointer to the value if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a value cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. + */ + ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { + RAPIDJSON_ASSERT(IsValid()); + ValueType* v = &root; + for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + break; + v = &m->value; + } + continue; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + break; + v = &((*v)[t->index]); + continue; + default: + break; + } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return 0; + } + return v; + } + + //! Query a const value in a const subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Pointer to the value if it can be resolved. Otherwise null. + */ + const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { + return Get(const_cast(root), unresolvedTokenIndex); + } + + //@} + + //!@name Query a value with default + //@{ + + //! Query a value in a subtree with default value. + /*! + Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. + So that this function always succeed. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param defaultValue Default value to be cloned if the value was not exists. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); + } + + //! Query a value in a subtree with default null-terminated string. + ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a subtree with default std::basic_string. + ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { + bool alreadyExist; + ValueType& v = Create(root, allocator, &alreadyExist); + return alreadyExist ? v : v.SetString(defaultValue, allocator); + } +#endif + + //! Query a value in a subtree with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { + return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); + } + + //! Query a value in a document with default value. + template + ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //! Query a value in a document with default null-terminated string. + template + ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Query a value in a document with default std::basic_string. + template + ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } +#endif + + //! Query a value in a document with default primitive value. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + GetWithDefault(GenericDocument& document, T defaultValue) const { + return GetWithDefault(document, defaultValue, document.GetAllocator()); + } + + //@} + + //!@name Set a value + //@{ + + //! Set a value in a subtree, with move semantics. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be set. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = value; + } + + //! Set a value in a subtree, with copy semantics. + ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).CopyFrom(value, allocator); + } + + //! Set a null-terminated string in a subtree. + ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Set a std::basic_string in a subtree. + ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value, allocator).Move(); + } +#endif + + //! Set a primitive value in a subtree. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator) = ValueType(value).Move(); + } + + //! Set a value in a document, with move semantics. + template + ValueType& Set(GenericDocument& document, ValueType& value) const { + return Create(document) = value; + } + + //! Set a value in a document, with copy semantics. + template + ValueType& Set(GenericDocument& document, const ValueType& value) const { + return Create(document).CopyFrom(value, document.GetAllocator()); + } + + //! Set a null-terminated string in a document. + template + ValueType& Set(GenericDocument& document, const Ch* value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } + +#if RAPIDJSON_HAS_STDSTRING + //! Sets a std::basic_string in a document. + template + ValueType& Set(GenericDocument& document, const std::basic_string& value) const { + return Create(document) = ValueType(value, document.GetAllocator()).Move(); + } +#endif + + //! Set a primitive value in a document. + /*! + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + */ + template + RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) + Set(GenericDocument& document, T value) const { + return Create(document) = value; + } + + //@} + + //!@name Swap a value + //@{ + + //! Swap a value with a value in a subtree. + /*! + It creates all parents if they are not exist or types are different to the tokens. + So this function always succeeds but potentially remove existing values. + + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param value Value to be swapped. + \param allocator Allocator for creating the values if the specified value or its parents are not exist. + \see Create() + */ + ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { + return Create(root, allocator).Swap(value); + } + + //! Swap a value with a value in a document. + template + ValueType& Swap(GenericDocument& document, ValueType& value) const { + return Create(document).Swap(value); + } + + //@} + + //! Erase a value in a subtree. + /*! + \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \return Whether the resolved value is found and erased. + + \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. + */ + bool Erase(ValueType& root) const { + RAPIDJSON_ASSERT(IsValid()); + if (tokenCount_ == 0) // Cannot erase the root + return false; + + ValueType* v = &root; + const Token* last = tokens_ + (tokenCount_ - 1); + for (const Token *t = tokens_; t != last; ++t) { + switch (v->GetType()) { + case kObjectType: + { + typename ValueType::MemberIterator m = v->FindMember(GenericValue(GenericStringRef(t->name, t->length))); + if (m == v->MemberEnd()) + return false; + v = &m->value; + } + break; + case kArrayType: + if (t->index == kPointerInvalidIndex || t->index >= v->Size()) + return false; + v = &((*v)[t->index]); + break; + default: + return false; + } + } + + switch (v->GetType()) { + case kObjectType: + return v->EraseMember(GenericStringRef(last->name, last->length)); + case kArrayType: + if (last->index == kPointerInvalidIndex || last->index >= v->Size()) + return false; + v->Erase(v->Begin() + last->index); + return true; + default: + return false; + } + } + +private: + //! Clone the content from rhs to this. + /*! + \param rhs Source pointer. + \param extraToken Extra tokens to be allocated. + \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. + \return Start of non-occupied name buffer, for storing extra names. + */ + Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { + if (!allocator_) // allocator is independently owned. + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens + for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) + nameBufferSize += t->length; + + tokenCount_ = rhs.tokenCount_ + extraToken; + tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); + nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + if (rhs.tokenCount_ > 0) { + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + } + if (nameBufferSize > 0) { + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + } + + // The names of each token point to a string in the nameBuffer_. The + // previous memcpy copied over string pointers into the rhs.nameBuffer_, + // but they should point to the strings in the new nameBuffer_. + for (size_t i = 0; i < rhs.tokenCount_; ++i) { + // The offset between the string address and the name buffer should + // still be constant, so we can just get this offset and set each new + // token name according the new buffer start + the known offset. + std::ptrdiff_t name_offset = rhs.tokens_[i].name - rhs.nameBuffer_; + tokens_[i].name = nameBuffer_ + name_offset; + } + + return nameBuffer_ + nameBufferSize; + } + + //! Check whether a character should be percent-encoded. + /*! + According to RFC 3986 2.3 Unreserved Characters. + \param c The character (code unit) to be tested. + */ + bool NeedPercentEncode(Ch c) const { + return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); + } + + //! Parse a JSON String or its URI fragment representation into tokens. +#ifndef __clang__ // -Wdocumentation + /*! + \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. + \param length Length of the source string. + \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. + */ +#endif + void Parse(const Ch* source, size_t length) { + RAPIDJSON_ASSERT(source != NULL); + RAPIDJSON_ASSERT(nameBuffer_ == 0); + RAPIDJSON_ASSERT(tokens_ == 0); + + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Count number of '/' as tokenCount + tokenCount_ = 0; + for (const Ch* s = source; s != source + length; s++) + if (*s == '/') + tokenCount_++; + + Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); + Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); + size_t i = 0; + + // Detect if it is a URI fragment + bool uriFragment = false; + if (source[i] == '#') { + uriFragment = true; + i++; + } + + if (i != length && source[i] != '/') { + parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; + goto error; + } + + while (i < length) { + RAPIDJSON_ASSERT(source[i] == '/'); + i++; // consumes '/' + + token->name = name; + bool isNumber = true; + + while (i < length && source[i] != '/') { + Ch c = source[i]; + if (uriFragment) { + // Decoding percent-encoding for URI fragment + if (c == '%') { + PercentDecodeStream is(&source[i], source + length); + GenericInsituStringStream os(name); + Ch* begin = os.PutBegin(); + if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { + parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; + goto error; + } + size_t len = os.PutEnd(begin); + i += is.Tell() - 1; + if (len == 1) + c = *name; + else { + name += len; + isNumber = false; + i++; + continue; + } + } + else if (NeedPercentEncode(c)) { + parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; + goto error; + } + } + + i++; + + // Escaping "~0" -> '~', "~1" -> '/' + if (c == '~') { + if (i < length) { + c = source[i]; + if (c == '0') c = '~'; + else if (c == '1') c = '/'; + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + i++; + } + else { + parseErrorCode_ = kPointerParseErrorInvalidEscape; + goto error; + } + } + + // First check for index: all of characters are digit + if (c < '0' || c > '9') + isNumber = false; + + *name++ = c; + } + token->length = static_cast(name - token->name); + if (token->length == 0) + isNumber = false; + *name++ = '\0'; // Null terminator + + // Second check for index: more than one digit cannot have leading zero + if (isNumber && token->length > 1 && token->name[0] == '0') + isNumber = false; + + // String to SizeType conversion + SizeType n = 0; + if (isNumber) { + for (size_t j = 0; j < token->length; j++) { + SizeType m = n * 10 + static_cast(token->name[j] - '0'); + if (m < n) { // overflow detection + isNumber = false; + break; + } + n = m; + } + } + + token->index = isNumber ? n : kPointerInvalidIndex; + token++; + } + + RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer + parseErrorCode_ = kPointerParseErrorNone; + return; + + error: + Allocator::Free(tokens_); + nameBuffer_ = 0; + tokens_ = 0; + tokenCount_ = 0; + parseErrorOffset_ = i; + return; + } + + //! Stringify to string or URI fragment representation. + /*! + \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. + \tparam OutputStream type of output stream. + \param os The output stream. + */ + template + bool Stringify(OutputStream& os) const { + RAPIDJSON_ASSERT(IsValid()); + + if (uriFragment) + os.Put('#'); + + for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { + os.Put('/'); + for (size_t j = 0; j < t->length; j++) { + Ch c = t->name[j]; + if (c == '~') { + os.Put('~'); + os.Put('0'); + } + else if (c == '/') { + os.Put('~'); + os.Put('1'); + } + else if (uriFragment && NeedPercentEncode(c)) { + // Transcode to UTF8 sequence + GenericStringStream source(&t->name[j]); + PercentEncodeStream target(os); + if (!Transcoder >().Validate(source, target)) + return false; + j += source.Tell() - 1; + } + else + os.Put(c); + } + } + return true; + } + + //! A helper stream for decoding a percent-encoded sequence into code unit. + /*! + This stream decodes %XY triplet into code unit (0-255). + If it encounters invalid characters, it sets output code unit as 0 and + mark invalid, and to be checked by IsValid(). + */ + class PercentDecodeStream { + public: + typedef typename ValueType::Ch Ch; + + //! Constructor + /*! + \param source Start of the stream + \param end Past-the-end of the stream. + */ + PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} + + Ch Take() { + if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet + valid_ = false; + return 0; + } + src_++; + Ch c = 0; + for (int j = 0; j < 2; j++) { + c = static_cast(c << 4); + Ch h = *src_; + if (h >= '0' && h <= '9') c = static_cast(c + h - '0'); + else if (h >= 'A' && h <= 'F') c = static_cast(c + h - 'A' + 10); + else if (h >= 'a' && h <= 'f') c = static_cast(c + h - 'a' + 10); + else { + valid_ = false; + return 0; + } + src_++; + } + return c; + } + + size_t Tell() const { return static_cast(src_ - head_); } + bool IsValid() const { return valid_; } + + private: + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. + const Ch* end_; //!< Past-the-end position. + bool valid_; //!< Whether the parsing is valid. + }; + + //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. + template + class PercentEncodeStream { + public: + PercentEncodeStream(OutputStream& os) : os_(os) {} + void Put(char c) { // UTF-8 must be byte + unsigned char u = static_cast(c); + static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + os_.Put('%'); + os_.Put(static_cast(hexDigits[u >> 4])); + os_.Put(static_cast(hexDigits[u & 15])); + } + private: + OutputStream& os_; + }; + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Pointer. + Ch* nameBuffer_; //!< A buffer containing all names in tokens. + Token* tokens_; //!< A list of tokens. + size_t tokenCount_; //!< Number of tokens in tokens_. + size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. + PointerParseErrorCode parseErrorCode_; //!< Parsing error code. +}; + +//! GenericPointer for Value (UTF-8, default allocator). +typedef GenericPointer Pointer; + +//!@name Helper functions for GenericPointer +//@{ + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { + return pointer.Create(root, a); +} + +template +typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Create(root, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { + return pointer.Create(document); +} + +template +typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Create(document); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); +} + +template +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +template +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { + return pointer.GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { + return pointer.GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { + return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { + return pointer.Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) +SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Set(root, value, a); +} + +// No allocator parameter + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { + return pointer.Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { + return pointer.Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { + return pointer.Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +#if RAPIDJSON_HAS_STDSTRING +template +typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { + return GenericPointer(source, N - 1).Set(document, value); +} +#endif + +template +RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) +SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { + return GenericPointer(source, N - 1).Set(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { + return pointer.Swap(root, value, a); +} + +template +typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { + return GenericPointer(source, N - 1).Swap(root, value, a); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { + return pointer.Swap(document, value); +} + +template +typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { + return GenericPointer(source, N - 1).Swap(document, value); +} + +////////////////////////////////////////////////////////////////////////////// + +template +bool EraseValueByPointer(T& root, const GenericPointer& pointer) { + return pointer.Erase(root); +} + +template +bool EraseValueByPointer(T& root, const CharType(&source)[N]) { + return GenericPointer(source, N - 1).Erase(root); +} + +//@} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_POINTER_H_ diff --git a/deps/rapidjson/include/rapidjson/prettywriter.h b/deps/rapidjson/include/rapidjson/prettywriter.h new file mode 100644 index 0000000..fe45df1 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/prettywriter.h @@ -0,0 +1,277 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_PRETTYWRITER_H_ +#define RAPIDJSON_PRETTYWRITER_H_ + +#include "writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Combination of PrettyWriter format flags. +/*! \see PrettyWriter::SetFormatOptions + */ +enum PrettyFormatOptions { + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. +}; + +//! Writer with indentation and spacing. +/*! + \tparam OutputStream Type of output os. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer { +public: + typedef Writer Base; + typedef typename Base::Ch Ch; + + //! Constructor + /*! \param os Output stream. + \param allocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + PrettyWriter(PrettyWriter&& rhs) : + Base(std::forward(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} +#endif + + //! Set custom indentation. + /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). + \param indentCharCount Number of indent characters for each indentation level. + \note The default indentation is 4 spaces. + */ + PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) { + RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r'); + indentChar_ = indentChar; + indentCharCount_ = indentCharCount; + return *this; + } + + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { + formatOptions_ = options; + return *this; + } + + /*! @name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); } + bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); } + bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); } + bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); } + bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); } + bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); } + bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kNumberType); + return Base::EndValue(Base::WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kStringType); + return Base::EndValue(Base::WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + PrettyPrefix(kObjectType); + new (Base::level_stack_.template Push()) typename Base::Level(false); + return Base::WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::EndValue(Base::WriteEndObject()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + bool StartArray() { + PrettyPrefix(kArrayType); + new (Base::level_stack_.template Push()) typename Base::Level(true); + return Base::WriteStartArray(); + } + + bool EndArray(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); + RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; + + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + bool ret = Base::EndValue(Base::WriteEndArray()); + (void)ret; + RAPIDJSON_ASSERT(ret == true); + if (Base::level_stack_.Empty()) // end of json text + Base::Flush(); + return true; + } + + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + PrettyPrefix(type); + return Base::EndValue(Base::WriteRawValue(json, length)); + } + +protected: + void PrettyPrefix(Type type) { + (void)type; + if (Base::level_stack_.GetSize() != 0) { // this value is not at root + typename Base::Level* level = Base::level_stack_.template Top(); + + if (level->inArray) { + if (level->valueCount > 0) { + Base::os_->Put(','); // add comma if it is not the first element in array + if (formatOptions_ & kFormatSingleLineArray) + Base::os_->Put(' '); + } + + if (!(formatOptions_ & kFormatSingleLineArray)) { + Base::os_->Put('\n'); + WriteIndent(); + } + } + else { // in object + if (level->valueCount > 0) { + if (level->valueCount % 2 == 0) { + Base::os_->Put(','); + Base::os_->Put('\n'); + } + else { + Base::os_->Put(':'); + Base::os_->Put(' '); + } + } + else + Base::os_->Put('\n'); + + if (level->valueCount % 2 == 0) + WriteIndent(); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root. + Base::hasRoot_ = true; + } + } + + void WriteIndent() { + size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; + PutN(*Base::os_, static_cast(indentChar_), count); + } + + Ch indentChar_; + unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; + +private: + // Prohibit copy constructor & assignment operator. + PrettyWriter(const PrettyWriter&); + PrettyWriter& operator=(const PrettyWriter&); +}; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/deps/rapidjson/include/rapidjson/rapidjson.h b/deps/rapidjson/include/rapidjson/rapidjson.h new file mode 100644 index 0000000..5ea6947 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/rapidjson.h @@ -0,0 +1,741 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_RAPIDJSON_H_ +#define RAPIDJSON_RAPIDJSON_H_ + +/*!\file rapidjson.h + \brief common definitions and configuration + + \see RAPIDJSON_CONFIG + */ + +/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration + \brief Configuration macros for library features + + Some RapidJSON features are configurable to adapt the library to a wide + variety of platforms, environments and usage scenarios. Most of the + features can be configured in terms of overridden or predefined + preprocessor macros at compile-time. + + Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs. + + \note These macros should be given on the compiler command-line + (where applicable) to avoid inconsistent values when compiling + different translation units of a single application. + */ + +#include // malloc(), realloc(), free(), size_t +#include // memset(), memcpy(), memmove(), memcmp() + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_VERSION_STRING +// +// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. +// + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +// token stringification +#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) +#define RAPIDJSON_DO_STRINGIFY(x) #x + +// token concatenation +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y +//!@endcond + +/*! \def RAPIDJSON_MAJOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Major version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_MINOR_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Minor version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_PATCH_VERSION + \ingroup RAPIDJSON_CONFIG + \brief Patch version of RapidJSON in integer. +*/ +/*! \def RAPIDJSON_VERSION_STRING + \ingroup RAPIDJSON_CONFIG + \brief Version of RapidJSON in ".." string format. +*/ +#define RAPIDJSON_MAJOR_VERSION 1 +#define RAPIDJSON_MINOR_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 0 +#define RAPIDJSON_VERSION_STRING \ + RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NAMESPACE_(BEGIN|END) +/*! \def RAPIDJSON_NAMESPACE + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace + + In order to avoid symbol clashes and/or "One Definition Rule" errors + between multiple inclusions of (different versions of) RapidJSON in + a single binary, users can customize the name of the main RapidJSON + namespace. + + In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE + to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple + levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref + RAPIDJSON_NAMESPACE_END need to be defined as well: + + \code + // in some .cpp file + #define RAPIDJSON_NAMESPACE my::rapidjson + #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson { + #define RAPIDJSON_NAMESPACE_END } } + #include "rapidjson/..." + \endcode + + \see rapidjson + */ +/*! \def RAPIDJSON_NAMESPACE_BEGIN + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (opening expression) + \see RAPIDJSON_NAMESPACE +*/ +/*! \def RAPIDJSON_NAMESPACE_END + \ingroup RAPIDJSON_CONFIG + \brief provide custom rapidjson namespace (closing expression) + \see RAPIDJSON_NAMESPACE +*/ +#ifndef RAPIDJSON_NAMESPACE +#define RAPIDJSON_NAMESPACE rapidjson +#endif +#ifndef RAPIDJSON_NAMESPACE_BEGIN +#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE { +#endif +#ifndef RAPIDJSON_NAMESPACE_END +#define RAPIDJSON_NAMESPACE_END } +#endif + +/////////////////////////////////////////////////////////////////////////////// +// __cplusplus macro + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#if defined(_MSC_VER) +#define RAPIDJSON_CPLUSPLUS _MSVC_LANG +#else +#define RAPIDJSON_CPLUSPLUS __cplusplus +#endif + +//!@endcond + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif // RAPIDJSON_HAS_STDSTRING + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_USE_MEMBERSMAP + +/*! \def RAPIDJSON_USE_MEMBERSMAP + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for object members handling in a \c std::multimap + + By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object + members are stored in a \c std::multimap for faster lookup and deletion times, a + trade off with a slightly slower insertion time and a small object allocat(or)ed + memory overhead. + + \hideinitializer +*/ +#ifndef RAPIDJSON_USE_MEMBERSMAP +#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_INT64DEFINE + +/*! \def RAPIDJSON_NO_INT64DEFINE + \ingroup RAPIDJSON_CONFIG + \brief Use external 64-bit integer types. + + RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types + to be available at global scope. + + If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to + prevent RapidJSON from defining its own types. +*/ +#ifndef RAPIDJSON_NO_INT64DEFINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 +#include "msinttypes/stdint.h" +#include "msinttypes/inttypes.h" +#else +// Other compilers should have this. +#include +#include +#endif +//!@endcond +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_INT64DEFINE +#endif +#endif // RAPIDJSON_NO_INT64TYPEDEF + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_FORCEINLINE + +#ifndef RAPIDJSON_FORCEINLINE +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#if defined(_MSC_VER) && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) +#else +#define RAPIDJSON_FORCEINLINE +#endif +//!@endcond +#endif // RAPIDJSON_FORCEINLINE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ENDIAN +#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine +#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine + +//! Endianness of the machine. +/*! + \def RAPIDJSON_ENDIAN + \ingroup RAPIDJSON_CONFIG + + GCC 4.6 provided macro for detecting endianness of the target machine. But other + compilers may not have this. User can define RAPIDJSON_ENDIAN to either + \ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN. + + Default detection implemented with reference to + \li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html + \li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp +*/ +#ifndef RAPIDJSON_ENDIAN +// Detect with GCC 4.6's macro +# ifdef __BYTE_ORDER__ +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __BYTE_ORDER__ +// Detect with GLIBC's endian.h +# elif defined(__GLIBC__) +# include +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif // __GLIBC__ +// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +// Detect with architecture macros +# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__) +# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN +# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(RAPIDJSON_DOXYGEN_RUNNING) +# define RAPIDJSON_ENDIAN +# else +# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN. +# endif +#endif // RAPIDJSON_ENDIAN + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_64BIT + +//! Whether using 64-bit architecture +#ifndef RAPIDJSON_64BIT +#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__) +#define RAPIDJSON_64BIT 1 +#else +#define RAPIDJSON_64BIT 0 +#endif +#endif // RAPIDJSON_64BIT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ALIGN + +//! Data alignment of the machine. +/*! \ingroup RAPIDJSON_CONFIG + \param x pointer to align + + Some machines require strict data alignment. The default is 8 bytes. + User can customize by defining the RAPIDJSON_ALIGN function macro. +*/ +#ifndef RAPIDJSON_ALIGN +#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_UINT64_C2 + +//! Construct a 64-bit literal by a pair of 32-bit integer. +/*! + 64-bit literal with or without ULL suffix is prone to compiler warnings. + UINT64_C() is C macro which cause compilation problems. + Use this macro to define 64-bit constants by a pair of 32-bit integer. +*/ +#ifndef RAPIDJSON_UINT64_C2 +#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast(high32) << 32) | static_cast(low32)) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_48BITPOINTER_OPTIMIZATION + +//! Use only lower 48-bit address for some pointers. +/*! + \ingroup RAPIDJSON_CONFIG + + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. + The higher 16-bit can be used for storing other data. + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. +*/ +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 +#else +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION + +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 +#if RAPIDJSON_64BIT != 1 +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 +#endif +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast((reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast(reinterpret_cast(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast(reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) +#else +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) +#define RAPIDJSON_GETPOINTER(type, p) (p) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD + +/*! \def RAPIDJSON_SIMD + \ingroup RAPIDJSON_CONFIG + \brief Enable SSE2/SSE4.2/Neon optimization. + + RapidJSON supports optimized implementations for some parsing operations + based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel + or ARM compatible processors. + + To enable these optimizations, three different symbols can be defined; + \code + // Enable SSE2 optimization. + #define RAPIDJSON_SSE2 + + // Enable SSE4.2 optimization. + #define RAPIDJSON_SSE42 + \endcode + + // Enable ARM Neon optimization. + #define RAPIDJSON_NEON + \endcode + + \c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined. + + If any of these symbols is defined, RapidJSON defines the macro + \c RAPIDJSON_SIMD to indicate the availability of the optimized code. +*/ +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ + || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) +#define RAPIDJSON_SIMD +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NO_SIZETYPEDEFINE + +#ifndef RAPIDJSON_NO_SIZETYPEDEFINE +/*! \def RAPIDJSON_NO_SIZETYPEDEFINE + \ingroup RAPIDJSON_CONFIG + \brief User-provided \c SizeType definition. + + In order to avoid using 32-bit size types for indexing strings and arrays, + define this preprocessor symbol and provide the type rapidjson::SizeType + before including RapidJSON: + \code + #define RAPIDJSON_NO_SIZETYPEDEFINE + namespace rapidjson { typedef ::std::size_t SizeType; } + #include "rapidjson/..." + \endcode + + \see rapidjson::SizeType +*/ +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_NO_SIZETYPEDEFINE +#endif +RAPIDJSON_NAMESPACE_BEGIN +//! Size type (for string lengths, array sizes, etc.) +/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms, + instead of using \c size_t. Users may override the SizeType by defining + \ref RAPIDJSON_NO_SIZETYPEDEFINE. +*/ +typedef unsigned SizeType; +RAPIDJSON_NAMESPACE_END +#endif + +// always import std::size_t to rapidjson namespace +RAPIDJSON_NAMESPACE_BEGIN +using std::size_t; +RAPIDJSON_NAMESPACE_END + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_ASSERT + +//! Assertion. +/*! \ingroup RAPIDJSON_CONFIG + By default, rapidjson uses C \c assert() for internal assertions. + User can override it by defining RAPIDJSON_ASSERT(x) macro. + + \note Parsing errors are handled and can be customized by the + \ref RAPIDJSON_ERRORS APIs. +*/ +#ifndef RAPIDJSON_ASSERT +#include +#define RAPIDJSON_ASSERT(x) assert(x) +#endif // RAPIDJSON_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_STATIC_ASSERT + +// Prefer C++11 static_assert, if available +#ifndef RAPIDJSON_STATIC_ASSERT +#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) +#define RAPIDJSON_STATIC_ASSERT(x) \ + static_assert(x, RAPIDJSON_STRINGIFY(x)) +#endif // C++11 +#endif // RAPIDJSON_STATIC_ASSERT + +// Adopt C++03 implementation from boost +#ifndef RAPIDJSON_STATIC_ASSERT +#ifndef __clang__ +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif +RAPIDJSON_NAMESPACE_BEGIN +template struct STATIC_ASSERTION_FAILURE; +template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; +template struct StaticAssertTest {}; +RAPIDJSON_NAMESPACE_END + +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +#else +#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif +#ifndef __clang__ +//!@endcond +#endif + +/*! \def RAPIDJSON_STATIC_ASSERT + \brief (Internal) macro to check for conditions at compile-time + \param x compile-time condition + \hideinitializer + */ +#define RAPIDJSON_STATIC_ASSERT(x) \ + typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ + sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ + RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif // RAPIDJSON_STATIC_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY + +//! Compiler branching hint for expression with high probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression likely to be true. +*/ +#ifndef RAPIDJSON_LIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define RAPIDJSON_LIKELY(x) (x) +#endif +#endif + +//! Compiler branching hint for expression with low probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression unlikely to be true. +*/ +#ifndef RAPIDJSON_UNLIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define RAPIDJSON_UNLIKELY(x) (x) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Helpers + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN + +#define RAPIDJSON_MULTILINEMACRO_BEGIN do { +#define RAPIDJSON_MULTILINEMACRO_END \ +} while((void)0, 0) + +// adopted from Boost +#define RAPIDJSON_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +#if defined(__has_builtin) +#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x) +#else +#define RAPIDJSON_HAS_BUILTIN(x) 0 +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF + +#if defined(__GNUC__) +#define RAPIDJSON_GNUC \ + RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__) +#endif + +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0)) + +#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x)) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x) +#define RAPIDJSON_DIAG_OFF(x) \ + RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x))) + +// push/pop support in Clang and GCC>=4.6 +#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) +#else // GCC >= 4.2, < 4.6 +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ +#endif + +#elif defined(_MSC_VER) + +// pragma (MSVC specific) +#define RAPIDJSON_PRAGMA(x) __pragma(x) +#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x)) + +#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x) +#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push) +#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop) + +#else + +#define RAPIDJSON_DIAG_OFF(x) /* ignored */ +#define RAPIDJSON_DIAG_PUSH /* ignored */ +#define RAPIDJSON_DIAG_POP /* ignored */ + +#endif // RAPIDJSON_DIAG_* + +/////////////////////////////////////////////////////////////////////////////// +// C++11 features + +#ifndef RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L) +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#elif defined(__clang__) +#if __has_feature(cxx_rvalue_references) && \ + (defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1600) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) + +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT +#if RAPIDJSON_HAS_CXX11 +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#elif defined(__clang__) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1900) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1 +#else +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 +#endif +#endif +#ifndef RAPIDJSON_NOEXCEPT +#if RAPIDJSON_HAS_CXX11_NOEXCEPT +#define RAPIDJSON_NOEXCEPT noexcept +#else +#define RAPIDJSON_NOEXCEPT throw() +#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT +#endif + +// no automatic detection, yet +#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS +#if (defined(_MSC_VER) && _MSC_VER >= 1700) +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1 +#else +#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 +#endif +#endif + +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1700) || \ + (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 +#else +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR + +/////////////////////////////////////////////////////////////////////////////// +// C++17 features + +#ifndef RAPIDJSON_HAS_CXX17 +#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L) +#endif + +#if RAPIDJSON_HAS_CXX17 +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]] +#elif defined(__has_cpp_attribute) +# if __has_cpp_attribute(clang::fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]] +# elif __has_cpp_attribute(fallthrough) +# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough)) +# else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +# endif +#else +# define RAPIDJSON_DELIBERATE_FALLTHROUGH +#endif + +//!@endcond + +//! Assertion (in non-throwing contexts). + /*! \ingroup RAPIDJSON_CONFIG + Some functions provide a \c noexcept guarantee, if the compiler supports it. + In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to + throw an exception. This macro adds a separate customization point for + such cases. + + Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is + supported, and to \ref RAPIDJSON_ASSERT otherwise. + */ + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_NOEXCEPT_ASSERT + +#ifndef RAPIDJSON_NOEXCEPT_ASSERT +#ifdef RAPIDJSON_ASSERT_THROWS +#include +#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x) +#else +#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x) +#endif // RAPIDJSON_ASSERT_THROWS +#endif // RAPIDJSON_NOEXCEPT_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// malloc/realloc/free + +#ifndef RAPIDJSON_MALLOC +///! customization point for global \c malloc +#define RAPIDJSON_MALLOC(size) std::malloc(size) +#endif +#ifndef RAPIDJSON_REALLOC +///! customization point for global \c realloc +#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size) +#endif +#ifndef RAPIDJSON_FREE +///! customization point for global \c free +#define RAPIDJSON_FREE(ptr) std::free(ptr) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// new/delete + +#ifndef RAPIDJSON_NEW +///! customization point for global \c new +#define RAPIDJSON_NEW(TypeName) new TypeName +#endif +#ifndef RAPIDJSON_DELETE +///! customization point for global \c delete +#define RAPIDJSON_DELETE(x) delete x +#endif + +/////////////////////////////////////////////////////////////////////////////// +// Type + +/*! \namespace rapidjson + \brief main RapidJSON namespace + \see RAPIDJSON_NAMESPACE +*/ +RAPIDJSON_NAMESPACE_BEGIN + +//! Type of JSON value +enum Type { + kNullType = 0, //!< null + kFalseType = 1, //!< false + kTrueType = 2, //!< true + kObjectType = 3, //!< object + kArrayType = 4, //!< array + kStringType = 5, //!< string + kNumberType = 6 //!< number +}; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/deps/rapidjson/include/rapidjson/reader.h b/deps/rapidjson/include/rapidjson/reader.h new file mode 100644 index 0000000..5554660 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/reader.h @@ -0,0 +1,2246 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_READER_H_ +#define RAPIDJSON_READER_H_ + +/*! \file reader.h */ + +#include "allocators.h" +#include "stream.h" +#include "encodedstream.h" +#include "internal/clzll.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strtod.h" +#include + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#elif defined(RAPIDJSON_NEON) +#include +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define RAPIDJSON_NOTHING /* deliberately empty */ +#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ + RAPIDJSON_MULTILINEMACRO_END +#endif +#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING) +//!@endcond + +/*! \def RAPIDJSON_PARSE_ERROR_NORETURN + \ingroup RAPIDJSON_ERRORS + \brief Macro to indicate a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + This macros can be used as a customization point for the internal + error handling mechanism of RapidJSON. + + A common usage model is to throw an exception instead of requiring the + caller to explicitly check the \ref rapidjson::GenericReader::Parse's + return value: + + \code + #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \ + throw ParseException(parseErrorCode, #parseErrorCode, offset) + + #include // std::runtime_error + #include "rapidjson/error/error.h" // rapidjson::ParseResult + + struct ParseException : std::runtime_error, rapidjson::ParseResult { + ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset) + : std::runtime_error(msg), ParseResult(code, offset) {} + }; + + #include "rapidjson/reader.h" + \endcode + + \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse + */ +#ifndef RAPIDJSON_PARSE_ERROR_NORETURN +#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \ + SetParseError(parseErrorCode, offset); \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +/*! \def RAPIDJSON_PARSE_ERROR + \ingroup RAPIDJSON_ERRORS + \brief (Internal) macro to indicate and handle a parse error. + \param parseErrorCode \ref rapidjson::ParseErrorCode of the error + \param offset position of the error in JSON input (\c size_t) + + Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing. + + \see RAPIDJSON_PARSE_ERROR_NORETURN + \hideinitializer + */ +#ifndef RAPIDJSON_PARSE_ERROR +#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \ + RAPIDJSON_MULTILINEMACRO_BEGIN \ + RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \ + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \ + RAPIDJSON_MULTILINEMACRO_END +#endif + +#include "error/error.h" // ParseErrorCode, ParseResult + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// ParseFlag + +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kParseDefaultFlags definition. + + User can define this as any \c ParseFlag combinations. +*/ +#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS +#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags +#endif + +//! Combination of parseFlags +/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream + */ +enum ParseFlag { + kParseNoFlags = 0, //!< No flags are set. + kParseInsituFlag = 1, //!< In-situ(destructive) parsing. + kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings. + kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. + kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. + kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. + kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. + kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. + kParseEscapedApostropheFlag = 512, //!< Allow escaped apostrophe in strings. + kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Handler + +/*! \class rapidjson::Handler + \brief Concept for receiving events from GenericReader upon parsing. + The functions return true if no error occurs. If they return false, + the event publisher should terminate the process. +\code +concept Handler { + typename Ch; + + bool Null(); + bool Bool(bool b); + bool Int(int i); + bool Uint(unsigned i); + bool Int64(int64_t i); + bool Uint64(uint64_t i); + bool Double(double d); + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType length, bool copy); + bool String(const Ch* str, SizeType length, bool copy); + bool StartObject(); + bool Key(const Ch* str, SizeType length, bool copy); + bool EndObject(SizeType memberCount); + bool StartArray(); + bool EndArray(SizeType elementCount); +}; +\endcode +*/ +/////////////////////////////////////////////////////////////////////////////// +// BaseReaderHandler + +//! Default implementation of Handler. +/*! This can be used as base class of any reader handler. + \note implements Handler concept +*/ +template, typename Derived = void> +struct BaseReaderHandler { + typedef typename Encoding::Ch Ch; + + typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; + + bool Default() { return true; } + bool Null() { return static_cast(*this).Default(); } + bool Bool(bool) { return static_cast(*this).Default(); } + bool Int(int) { return static_cast(*this).Default(); } + bool Uint(unsigned) { return static_cast(*this).Default(); } + bool Int64(int64_t) { return static_cast(*this).Default(); } + bool Uint64(uint64_t) { return static_cast(*this).Default(); } + bool Double(double) { return static_cast(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } + bool StartObject() { return static_cast(*this).Default(); } + bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } + bool EndObject(SizeType) { return static_cast(*this).Default(); } + bool StartArray() { return static_cast(*this).Default(); } + bool EndArray(SizeType) { return static_cast(*this).Default(); } +}; + +/////////////////////////////////////////////////////////////////////////////// +// StreamLocalCopy + +namespace internal { + +template::copyOptimization> +class StreamLocalCopy; + +//! Do copy optimization. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original), original_(original) {} + ~StreamLocalCopy() { original_ = s; } + + Stream s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; + + Stream& original_; +}; + +//! Keep reference. +template +class StreamLocalCopy { +public: + StreamLocalCopy(Stream& original) : s(original) {} + + Stream& s; + +private: + StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// SkipWhitespace + +//! Skip the JSON white spaces in a stream. +/*! \param is A input stream for skipping white spaces. + \note This function has SSE2/SSE4.2 specialization. +*/ +template +void SkipWhitespace(InputStream& is) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + typename InputStream::Ch c; + while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') + s.Take(); +} + +inline const char* SkipWhitespace(const char* p, const char* end) { + while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + return p; +} + +#ifdef RAPIDJSON_SSE42 +//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_SSE2) + +//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_NEON) + +//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + return p + 8 + (lz >> 3); + } + } else { + uint32_t lz = internal::clzll(low); + return p + (lz >> 3); + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (; p <= end - 16; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + return p + 8 + (lz >> 3); + } + } else { + uint32_t lz = internal::clzll(low); + return p + (lz >> 3); + } + } + + return SkipWhitespace(p, end); +} + +#endif // RAPIDJSON_NEON + +#ifdef RAPIDJSON_SIMD +//! Template function specialization for InsituStringStream +template<> inline void SkipWhitespace(InsituStringStream& is) { + is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); +} + +//! Template function specialization for StringStream +template<> inline void SkipWhitespace(StringStream& is) { + is.src_ = SkipWhitespace_SIMD(is.src_); +} + +template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream>& is) { + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); +} +#endif // RAPIDJSON_SIMD + +/////////////////////////////////////////////////////////////////////////////// +// GenericReader + +//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. +/*! GenericReader parses JSON text from a stream, and send events synchronously to an + object implementing Handler concept. + + It needs to allocate a stack for storing a single decoded string during + non-destructive parsing. + + For in-situ parsing, the decoded string is directly written to the source + text string, no temporary buffer is required. + + A GenericReader object can be reused for parsing multiple JSON text. + + \tparam SourceEncoding Encoding of the input stream. + \tparam TargetEncoding Encoding of the parse output. + \tparam StackAllocator Allocator type for stack. +*/ +template +class GenericReader { +public: + typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type + + //! Constructor. + /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) + \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing) + */ + GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : + stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {} + + //! Parse JSON text. + /*! \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + if (parseFlags & kParseIterativeFlag) + return IterativeParse(is, handler); + + parseResult_.Clear(); + + ClearStackOnExit scope(*this); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + else { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (!(parseFlags & kParseStopWhenDoneFlag)) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + + if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + } + } + + return parseResult_; + } + + //! Parse JSON text (with \ref kParseDefaultFlags) + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + ParseResult Parse(InputStream& is, Handler& handler) { + return Parse(is, handler); + } + + //! Initialize JSON text token-by-token parsing + /*! + */ + void IterativeParseInit() { + parseResult_.Clear(); + state_ = IterativeParsingStartState; + } + + //! Parse one token from JSON text + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + bool IterativeParseNext(InputStream& is, Handler& handler) { + while (RAPIDJSON_LIKELY(is.Peek() != '\0')) { + SkipWhitespaceAndComments(is); + + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state_, t); + IterativeParsingState d = Transit(state_, t, n, is, handler); + + // If we've finished or hit an error... + if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) { + // Report errors. + if (d == IterativeParsingErrorState) { + HandleError(state_, is); + return false; + } + + // Transition to the finish state. + RAPIDJSON_ASSERT(d == IterativeParsingFinishState); + state_ = d; + + // If StopWhenDone is not set... + if (!(parseFlags & kParseStopWhenDoneFlag)) { + // ... and extra non-whitespace data is found... + SkipWhitespaceAndComments(is); + if (is.Peek() != '\0') { + // ... this is considered an error. + HandleError(state_, is); + return false; + } + } + + // Success! We are done! + return true; + } + + // Transition to the new state. + state_ = d; + + // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now. + if (!IsIterativeParsingDelimiterState(n)) + return true; + } + + // We reached the end of file. + stack_.Clear(); + + if (state_ != IterativeParsingFinishState) { + HandleError(state_, is); + return false; + } + + return true; + } + + //! Check if token-by-token parsing JSON text is complete + /*! \return Whether the JSON has been fully decoded. + */ + RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const { + return IsIterativeParsingCompleteState(state_); + } + + //! Whether a parse error has occurred in the last parsing. + bool HasParseError() const { return parseResult_.IsError(); } + + //! Get the \ref ParseErrorCode of last parsing. + ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } + + //! Get the position of last parsing error in input, 0 otherwise. + size_t GetErrorOffset() const { return parseResult_.Offset(); } + +protected: + void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); } + +private: + // Prohibit copy constructor & assignment operator. + GenericReader(const GenericReader&); + GenericReader& operator=(const GenericReader&); + + void ClearStack() { stack_.Clear(); } + + // clear stack on any exit from ParseStream, e.g. due to exception + struct ClearStackOnExit { + explicit ClearStackOnExit(GenericReader& r) : r_(r) {} + ~ClearStackOnExit() { r_.ClearStack(); } + private: + GenericReader& r_; + ClearStackOnExit(const ClearStackOnExit&); + ClearStackOnExit& operator=(const ClearStackOnExit&); + }; + + template + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { + if (Consume(is, '*')) { + while (true) { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + else if (Consume(is, '*')) { + if (Consume(is, '/')) + break; + } + else + is.Take(); + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) + while (is.Peek() != '\0' && is.Take() != '\n') {} + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + SkipWhitespace(is); + } + } + } + + // Parse object: { string : value, ... } + template + void ParseObject(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '{'); + is.Take(); // Skip '{' + + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, '}')) { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType memberCount = 0;;) { + if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); + + ParseString(is, handler, true); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++memberCount; + + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy + } + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == '}') { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + // Parse array: [ value, ... ] + template + void ParseArray(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == '['); + is.Take(); // Skip '[' + + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + + for (SizeType elementCount = 0;;) { + ParseValue(is, handler); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + ++elementCount; + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ',')) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == ']') { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } + } + } + } + + template + void ParseNull(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'n'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { + if (RAPIDJSON_UNLIKELY(!handler.Null())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseTrue(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 't'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + void ParseFalse(InputStream& is, Handler& handler) { + RAPIDJSON_ASSERT(is.Peek() == 'f'); + is.Take(); + + if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { + if (RAPIDJSON_LIKELY(is.Peek() == expect)) { + is.Take(); + return true; + } + else + return false; + } + + // Helper function to parse four hexadecimal digits in \uXXXX in ParseString(). + template + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { + unsigned codepoint = 0; + for (int i = 0; i < 4; i++) { + Ch c = is.Peek(); + codepoint <<= 4; + codepoint += static_cast(c); + if (c >= '0' && c <= '9') + codepoint -= '0'; + else if (c >= 'A' && c <= 'F') + codepoint -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + codepoint -= 'a' - 10; + else { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); + } + is.Take(); + } + return codepoint; + } + + template + class StackStream { + public: + typedef CharType Ch; + + StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} + RAPIDJSON_FORCEINLINE void Put(Ch c) { + *stack_.template Push() = c; + ++length_; + } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push(count); + } + + size_t Length() const { return length_; } + + Ch* Pop() { + return stack_.template Pop(length_); + } + + private: + StackStream(const StackStream&); + StackStream& operator=(const StackStream&); + + internal::Stack& stack_; + SizeType length_; + }; + + // Parse string and generate String event. Different code paths for kParseInsituFlag. + template + void ParseString(InputStream& is, Handler& handler, bool isKey = false) { + internal::StreamLocalCopy copy(is); + InputStream& s(copy.s); + + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + + bool success = false; + if (parseFlags & kParseInsituFlag) { + typename InputStream::Ch *head = s.PutBegin(); + ParseStringToStream(s, s); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + size_t length = s.PutEnd(head) - 1; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); + } + else { + StackStream stackStream(stack_); + ParseStringToStream(s, stackStream); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + SizeType length = static_cast(stackStream.Length()) - 1; + const typename TargetEncoding::Ch* const str = stackStream.Pop(); + success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); + } + if (RAPIDJSON_UNLIKELY(!success)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + } + + // Parse string to an output is + // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation. + template + RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) { +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 + }; +#undef Z16 +//!@endcond + + for (;;) { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if (!(parseFlags & kParseValidateEncodingFlag)) + ScanCopyUnescapedString(is, os); + + Ch c = is.Peek(); + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape + size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset + is.Take(); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) { + is.Take(); + os.Put(static_cast(escape[static_cast(e)])); + } + else if ((parseFlags & kParseEscapedApostropheFlag) && RAPIDJSON_LIKELY(e == '\'')) { // Allow escaped apostrophe + is.Take(); + os.Put('\''); + } + else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDFFF)) { + // high surrogate, check if followed by valid low surrogate + if (RAPIDJSON_LIKELY(codepoint <= 0xDBFF)) { + // Handle UTF-16 surrogate pair + if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + unsigned codepoint2 = ParseHex4(is, escapeOffset); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; + } + // single low surrogate + else + { + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + } + } + TEncoding::Encode(os, codepoint); + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); + } + else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote + is.Take(); + os.Put('\0'); // null-terminate the string + return; + } + else if (RAPIDJSON_UNLIKELY(static_cast(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); + } + else { + size_t offset = is.Tell(); + if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } + } + } + + template + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType length; + #ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; + #else + length = static_cast(__builtin_ffs(r) - 1); + #endif + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + for (const char* pend = p + length; p != pend; ) + *q++ = *p++; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#elif defined(RAPIDJSON_NEON) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + vst1q_u8(reinterpret_cast(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16, q += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + for (const char* pend = p + length; p != pend; ) { + *q++ = *p++; + } + break; + } + vst1q_u8(reinterpret_cast(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + p += 8 + (lz >> 3); + break; + } + } else { + uint32_t lz = internal::clzll(low); + p += lz >> 3; + break; + } + } + + is.src_ = is.dst_ = p; + } +#endif // RAPIDJSON_NEON + + template + class NumberStream; + + template + class NumberStream { + public: + typedef typename InputStream::Ch Ch; + + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } + + RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } + RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } + RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + RAPIDJSON_FORCEINLINE void Push(char) {} + + size_t Tell() { return is.Tell(); } + size_t Length() { return 0; } + const StackCharacter* Pop() { return 0; } + + protected: + NumberStream& operator=(const NumberStream&); + + InputStream& is; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {} + + RAPIDJSON_FORCEINLINE Ch TakePush() { + stackStream.Put(static_cast(Base::is.Peek())); + return Base::is.Take(); + } + + RAPIDJSON_FORCEINLINE void Push(StackCharacter c) { + stackStream.Put(c); + } + + size_t Length() { return stackStream.Length(); } + + const StackCharacter* Pop() { + stackStream.Put('\0'); + return stackStream.Pop(); + } + + private: + StackStream stackStream; + }; + + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s) {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + + template + void ParseNumber(InputStream& is, Handler& handler) { + typedef typename internal::SelectIf, typename TargetEncoding::Ch, char>::Type NumberCharacter; + + internal::StreamLocalCopy copy(is); + NumberStream s(*this, copy.s); + + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; + + // Parse minus + bool minus = Consume(s, '-'); + + // Parse int: zero / ( digit1-9 *DIGIT ) + unsigned i = 0; + uint64_t i64 = 0; + bool use64bit = false; + int significandDigit = 0; + if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { + i = 0; + s.TakePush(); + } + else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { + i = static_cast(s.TakePush() - '0'); + + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 + if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 + if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { + i64 = i; + use64bit = true; + break; + } + } + i = i * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + // Parse NaN or Infinity here + else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { + if (Consume(s, 'N')) { + if (Consume(s, 'a') && Consume(s, 'N')) { + d = std::numeric_limits::quiet_NaN(); + useNanOrInf = true; + } + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) { + if (Consume(s, 'n') && Consume(s, 'f')) { + d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); + useNanOrInf = true; + + if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + } + + if (RAPIDJSON_UNLIKELY(!useNanOrInf)) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + + // Parse 64bit int + bool useDouble = false; + if (use64bit) { + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + else + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { + d = static_cast(i64); + useDouble = true; + break; + } + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + significandDigit++; + } + } + + // Force double for big integer + if (useDouble) { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + d = d * 10 + (s.TakePush() - '0'); + } + } + + // Parse frac = decimal-point 1*DIGIT + int expFrac = 0; + size_t decimalPosition; + if (Consume(s, '.')) { + decimalPosition = s.Length(); + + if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); + + if (!useDouble) { +#if RAPIDJSON_64BIT + // Use i64 to store significand in 64-bit architecture + if (!use64bit) + i64 = i; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path + break; + else { + i64 = i64 * 10 + static_cast(s.TakePush() - '0'); + --expFrac; + if (i64 != 0) + significandDigit++; + } + } + + d = static_cast(i64); +#else + // Use double to store significand in 32-bit architecture + d = static_cast(use64bit ? i64 : i); +#endif + useDouble = true; + } + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (significandDigit < 17) { + d = d * 10.0 + (s.TakePush() - '0'); + --expFrac; + if (RAPIDJSON_LIKELY(d > 0.0)) + significandDigit++; + } + else + s.TakePush(); + } + } + else + decimalPosition = s.Length(); // decimal position at the end of integer. + + // Parse exp = e [ minus / plus ] 1*DIGIT + int exp = 0; + if (Consume(s, 'e') || Consume(s, 'E')) { + if (!useDouble) { + d = static_cast(use64bit ? i64 : i); + useDouble = true; + } + + bool expMinus = false; + if (Consume(s, '+')) + ; + else if (Consume(s, '-')) + expMinus = true; + + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast(s.Take() - '0'); + if (expMinus) { + // (exp + expFrac) must not underflow int => we're detecting when -exp gets + // dangerously close to INT_MIN (a pessimistic next digit 9 would push it into + // underflow territory): + // + // -(exp * 10 + 9) + expFrac >= INT_MIN + // <=> exp <= (expFrac - INT_MIN - 9) / 10 + RAPIDJSON_ASSERT(expFrac <= 0); + int maxExp = (expFrac + 2147483639) / 10; + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) { + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent + s.Take(); + } + } + } + else { // positive exp + int maxExp = 308 - expFrac; + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + } + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell()); + + if (expMinus) + exp = -exp; + } + + // Finish parsing, call event according to the type of number. + bool cont = true; + + if (parseFlags & kParseNumbersAsStringsFlag) { + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + cont = handler.RawNumber(str, SizeType(length), false); + } + else { + SizeType numCharsToCopy = static_cast(s.Length()); + GenericStringStream > srcStream(s.Pop()); + StackStream dstStream(stack_); + while (numCharsToCopy--) { + Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); + } + } + else { + size_t length = s.Length(); + const NumberCharacter* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + // Use > max, instead of == inf, to fix bogus warning -Wfloat-equal + if (d > (std::numeric_limits::max)()) { + // Overflow + // TODO: internal::StrtodX should report overflow (or underflow) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); + } + + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { + cont = handler.Double(d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); + } + + // Parse any JSON value + template + void ParseValue(InputStream& is, Handler& handler) { + switch (is.Peek()) { + case 'n': ParseNull (is, handler); break; + case 't': ParseTrue (is, handler); break; + case 'f': ParseFalse (is, handler); break; + case '"': ParseString(is, handler); break; + case '{': ParseObject(is, handler); break; + case '[': ParseArray (is, handler); break; + default : + ParseNumber(is, handler); + break; + + } + } + + // Iterative Parsing + + // States + enum IterativeParsingState { + IterativeParsingFinishState = 0, // sink states at top + IterativeParsingErrorState, // sink states at top + IterativeParsingStartState, + + // Object states + IterativeParsingObjectInitialState, + IterativeParsingMemberKeyState, + IterativeParsingMemberValueState, + IterativeParsingObjectFinishState, + + // Array states + IterativeParsingArrayInitialState, + IterativeParsingElementState, + IterativeParsingArrayFinishState, + + // Single value state + IterativeParsingValueState, + + // Delimiter states (at bottom) + IterativeParsingElementDelimiterState, + IterativeParsingMemberDelimiterState, + IterativeParsingKeyValueDelimiterState, + + cIterativeParsingStateCount + }; + + // Tokens + enum Token { + LeftBracketToken = 0, + RightBracketToken, + + LeftCurlyBracketToken, + RightCurlyBracketToken, + + CommaToken, + ColonToken, + + StringToken, + FalseToken, + TrueToken, + NullToken, + NumberToken, + + kTokenCount + }; + + RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const { + +//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#define N NumberToken +#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N + // Maps from ASCII to Token + static const unsigned char tokenMap[256] = { + N16, // 00~0F + N16, // 10~1F + N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F + N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F + N16, // 40~4F + N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F + N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F + N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F + N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF + }; +#undef N +#undef N16 +//!@endcond + + if (sizeof(Ch) == 1 || static_cast(c) < 256) + return static_cast(tokenMap[static_cast(c)]); + else + return NumberToken; + } + + RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const { + // current state x one lookahead token -> new state + static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Start + { + IterativeParsingArrayInitialState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingValueState, // String + IterativeParsingValueState, // False + IterativeParsingValueState, // True + IterativeParsingValueState, // Null + IterativeParsingValueState // Number + }, + // ObjectInitial + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberKey + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingKeyValueDelimiterState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // MemberValue + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingMemberDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ObjectFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ArrayInitial + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // Element + { + IterativeParsingErrorState, // Left bracket + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingErrorState, // Right curly bracket + IterativeParsingElementDelimiterState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingErrorState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // ArrayFinish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Single Value (sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, + }; // End of G + + return static_cast(G[state][token]); + } + + // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). + // May return a new state on state pop. + template + RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) { + (void)token; + + switch (dst) { + case IterativeParsingErrorState: + return dst; + + case IterativeParsingObjectInitialState: + case IterativeParsingArrayInitialState: + { + // Push the state(Element or MemeberValue) if we are nested in another array or value of member. + // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop. + IterativeParsingState n = src; + if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState) + n = IterativeParsingElementState; + else if (src == IterativeParsingKeyValueDelimiterState) + n = IterativeParsingMemberValueState; + // Push current state. + *stack_.template Push(1) = n; + // Initialize and push the member/element count. + *stack_.template Push(1) = 0; + // Call handler + bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray(); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return dst; + } + } + + case IterativeParsingMemberKeyState: + ParseString(is, handler, true); + if (HasParseError()) + return IterativeParsingErrorState; + else + return dst; + + case IterativeParsingKeyValueDelimiterState: + RAPIDJSON_ASSERT(token == ColonToken); + is.Take(); + return dst; + + case IterativeParsingMemberValueState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingElementState: + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return dst; + + case IterativeParsingMemberDelimiterState: + case IterativeParsingElementDelimiterState: + is.Take(); + // Update member/element count. + *stack_.template Top() = *stack_.template Top() + 1; + return dst; + + case IterativeParsingObjectFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } + // Get member count. + SizeType c = *stack_.template Pop(1); + // If the object is not empty, count the last member. + if (src == IterativeParsingMemberValueState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndObject(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + case IterativeParsingArrayFinishState: + { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } + // Get element count. + SizeType c = *stack_.template Pop(1); + // If the array is not empty, count the last element. + if (src == IterativeParsingElementState) + ++c; + // Restore the state. + IterativeParsingState n = static_cast(*stack_.template Pop(1)); + // Transit to Finish state if this is the topmost scope. + if (n == IterativeParsingStartState) + n = IterativeParsingFinishState; + // Call handler + bool hr = handler.EndArray(c); + // On handler short circuits the parsing. + if (!hr) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell()); + return IterativeParsingErrorState; + } + else { + is.Take(); + return n; + } + } + + default: + // This branch is for IterativeParsingValueState actually. + // Use `default:` rather than + // `case IterativeParsingValueState:` is for code coverage. + + // The IterativeParsingStartState is not enumerated in this switch-case. + // It is impossible for that case. And it can be caught by following assertion. + + // The IterativeParsingFinishState is not enumerated in this switch-case either. + // It is a "derivative" state which cannot triggered from Predict() directly. + // Therefore it cannot happen here. And it can be caught by following assertion. + RAPIDJSON_ASSERT(dst == IterativeParsingValueState); + + // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. + ParseValue(is, handler); + if (HasParseError()) { + return IterativeParsingErrorState; + } + return IterativeParsingFinishState; + } + } + + template + void HandleError(IterativeParsingState src, InputStream& is) { + if (HasParseError()) { + // Error flag has been set. + return; + } + + switch (src) { + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; + case IterativeParsingObjectInitialState: + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; + default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + } + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const { + return s >= IterativeParsingElementDelimiterState; + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const { + return s <= IterativeParsingErrorState; + } + + template + ParseResult IterativeParse(InputStream& is, Handler& handler) { + parseResult_.Clear(); + ClearStackOnExit scope(*this); + IterativeParsingState state = IterativeParsingStartState; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + while (is.Peek() != '\0') { + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state, t); + IterativeParsingState d = Transit(state, t, n, is, handler); + + if (d == IterativeParsingErrorState) { + HandleError(state, is); + break; + } + + state = d; + + // Do not further consume streams if a root JSON has been parsed. + if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) + break; + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); + } + + // Handle the end of file. + if (state != IterativeParsingFinishState) + HandleError(state, is); + + return parseResult_; + } + + static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. + internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. + ParseResult parseResult_; + IterativeParsingState state_; +}; // class GenericReader + +//! Reader with UTF8 encoding and default allocator. +typedef GenericReader, UTF8<> > Reader; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_READER_H_ diff --git a/deps/rapidjson/include/rapidjson/schema.h b/deps/rapidjson/include/rapidjson/schema.h new file mode 100644 index 0000000..439133f --- /dev/null +++ b/deps/rapidjson/include/rapidjson/schema.h @@ -0,0 +1,3262 @@ +// Tencent is pleased to support the open source community by making RapidJSON available-> +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved-> +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License-> You may obtain a copy of the License at +// +// http://opensource->org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied-> See the License for the +// specific language governing permissions and limitations under the License-> + +#ifndef RAPIDJSON_SCHEMA_H_ +#define RAPIDJSON_SCHEMA_H_ + +#include "document.h" +#include "pointer.h" +#include "stringbuffer.h" +#include "error/en.h" +#include "uri.h" +#include // abs, floor + +#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 +#endif + +#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) +#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_STDREGEX 0 +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX +#include "internal/regex.h" +#elif RAPIDJSON_SCHEMA_USE_STDREGEX +#include +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX +#define RAPIDJSON_SCHEMA_HAS_REGEX 1 +#else +#define RAPIDJSON_SCHEMA_HAS_REGEX 0 +#endif + +#ifndef RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#endif + +RAPIDJSON_DIAG_PUSH + +#if defined(__GNUC__) +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(weak-vtables) +RAPIDJSON_DIAG_OFF(exit-time-destructors) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) +RAPIDJSON_DIAG_OFF(variadic-macros) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Verbose Utilities + +#if RAPIDJSON_SCHEMA_VERBOSE + +namespace internal { + +inline void PrintInvalidKeywordData(const char* keyword) { + printf(" Fail keyword: '%s'\n", keyword); +} + +inline void PrintInvalidKeywordData(const wchar_t* keyword) { + wprintf(L" Fail keyword: '%ls'\n", keyword); +} + +inline void PrintInvalidDocumentData(const char* document) { + printf(" Fail document: '%s'\n", document); +} + +inline void PrintInvalidDocumentData(const wchar_t* document) { + wprintf(L" Fail document: '%ls'\n", document); +} + +inline void PrintValidatorPointersData(const char* s, const char* d, unsigned depth) { + printf(" Sch: %*s'%s'\n Doc: %*s'%s'\n", depth * 4, " ", s, depth * 4, " ", d); +} + +inline void PrintValidatorPointersData(const wchar_t* s, const wchar_t* d, unsigned depth) { + wprintf(L" Sch: %*ls'%ls'\n Doc: %*ls'%ls'\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +inline void PrintSchemaIdsData(const char* base, const char* local, const char* resolved) { + printf(" Resolving id: Base: '%s', Local: '%s', Resolved: '%s'\n", base, local, resolved); +} + +inline void PrintSchemaIdsData(const wchar_t* base, const wchar_t* local, const wchar_t* resolved) { + wprintf(L" Resolving id: Base: '%ls', Local: '%ls', Resolved: '%ls'\n", base, local, resolved); +} + +inline void PrintMethodData(const char* method) { + printf("%s\n", method); +} + +inline void PrintMethodData(const char* method, bool b) { + printf("%s, Data: '%s'\n", method, b ? "true" : "false"); +} + +inline void PrintMethodData(const char* method, int64_t i) { + printf("%s, Data: '%" PRId64 "'\n", method, i); +} + +inline void PrintMethodData(const char* method, uint64_t u) { + printf("%s, Data: '%" PRIu64 "'\n", method, u); +} + +inline void PrintMethodData(const char* method, double d) { + printf("%s, Data: '%lf'\n", method, d); +} + +inline void PrintMethodData(const char* method, const char* s) { + printf("%s, Data: '%s'\n", method, s); +} + +inline void PrintMethodData(const char* method, const wchar_t* s) { + wprintf(L"%hs, Data: '%ls'\n", method, s); +} + +inline void PrintMethodData(const char* method, const char* s1, const char* s2) { + printf("%s, Data: '%s', '%s'\n", method, s1, s2); +} + +inline void PrintMethodData(const char* method, const wchar_t* s1, const wchar_t* s2) { + wprintf(L"%hs, Data: '%ls', '%ls'\n", method, s1, s2); +} + +} // namespace internal + +#endif // RAPIDJSON_SCHEMA_VERBOSE + +#ifndef RAPIDJSON_SCHEMA_PRINT +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_PRINT(name, ...) internal::Print##name##Data(__VA_ARGS__) +#else +#define RAPIDJSON_SCHEMA_PRINT(name, ...) +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_INVALID_KEYWORD_RETURN + +#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidCode = code;\ + context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\ + RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, context.invalidKeyword);\ + return false;\ +RAPIDJSON_MULTILINEMACRO_END + +/////////////////////////////////////////////////////////////////////////////// +// ValidateFlag + +/*! \def RAPIDJSON_VALIDATE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kValidateDefaultFlags definition. + + User can define this as any \c ValidateFlag combinations. +*/ +#ifndef RAPIDJSON_VALIDATE_DEFAULT_FLAGS +#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS kValidateNoFlags +#endif + +//! Combination of validate flags +/*! \see + */ +enum ValidateFlag { + kValidateNoFlags = 0, //!< No flags are set. + kValidateContinueOnErrorFlag = 1, //!< Don't stop after first validation error. + kValidateReadFlag = 2, //!< Validation is for a read semantic. + kValidateWriteFlag = 4, //!< Validation is for a write semantic. + kValidateDefaultFlags = RAPIDJSON_VALIDATE_DEFAULT_FLAGS //!< Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS +}; + +/////////////////////////////////////////////////////////////////////////////// +// Specification +enum SchemaDraft { + kDraftUnknown = -1, + kDraftNone = 0, + kDraft03 = 3, + kDraftMin = 4, //!< Current minimum supported draft + kDraft04 = 4, + kDraft05 = 5, + kDraftMax = 5, //!< Current maximum supported draft + kDraft06 = 6, + kDraft07 = 7, + kDraft2019_09 = 8, + kDraft2020_12 = 9 +}; + +enum OpenApiVersion { + kVersionUnknown = -1, + kVersionNone = 0, + kVersionMin = 2, //!< Current minimum supported version + kVersion20 = 2, + kVersion30 = 3, + kVersionMax = 3, //!< Current maximum supported version + kVersion31 = 4, +}; + +struct Specification { + Specification(SchemaDraft d) : draft(d), oapi(kVersionNone) {} + Specification(OpenApiVersion o) : oapi(o) { + if (oapi == kVersion20) draft = kDraft04; + else if (oapi == kVersion30) draft = kDraft05; + else if (oapi == kVersion31) draft = kDraft2020_12; + else draft = kDraft04; + } + ~Specification() {} + bool IsSupported() const { + return ((draft >= kDraftMin && draft <= kDraftMax) && ((oapi == kVersionNone) || (oapi >= kVersionMin && oapi <= kVersionMax))); + } + SchemaDraft draft; + OpenApiVersion oapi; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Forward declarations + +template +class GenericSchemaDocument; + +namespace internal { + +template +class Schema; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaValidator + +class ISchemaValidator { +public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; + virtual void SetValidateFlags(unsigned flags) = 0; + virtual unsigned GetValidateFlags() const = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaStateFactory + +template +class ISchemaStateFactory { +public: + virtual ~ISchemaStateFactory() {} + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; + virtual void DestroryHasher(void* hasher) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void FreeState(void* p) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// IValidationErrorHandler + +template +class IValidationErrorHandler { +public: + typedef typename SchemaType::Ch Ch; + typedef typename SchemaType::SValue SValue; + + virtual ~IValidationErrorHandler() {} + + virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0; + virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0; + virtual void NotMultipleOf(double actual, const SValue& expected) = 0; + virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0; + virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0; + + virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0; + virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0; + virtual void DoesNotMatch(const Ch* str, SizeType length) = 0; + + virtual void DisallowedItem(SizeType index) = 0; + virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0; + virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0; + virtual void DuplicateItems(SizeType index1, SizeType index2) = 0; + + virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0; + virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0; + virtual void StartMissingProperties() = 0; + virtual void AddMissingProperty(const SValue& name) = 0; + virtual bool EndMissingProperties() = 0; + virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void DisallowedProperty(const Ch* name, SizeType length) = 0; + + virtual void StartDependencyErrors() = 0; + virtual void StartMissingDependentProperties() = 0; + virtual void AddMissingDependentProperty(const SValue& targetName) = 0; + virtual void EndMissingDependentProperties(const SValue& sourceName) = 0; + virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0; + virtual bool EndDependencyErrors() = 0; + + virtual void DisallowedValue(const ValidateErrorCode code) = 0; + virtual void StartDisallowedType() = 0; + virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0; + virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0; + virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0; + virtual void MultipleOneOf(SizeType index1, SizeType index2) = 0; + virtual void Disallowed() = 0; + virtual void DisallowedWhenWriting() = 0; + virtual void DisallowedWhenReading() = 0; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Hasher + +// For comparison of compound value +template +class Hasher { +public: + typedef typename Encoding::Ch Ch; + + Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} + + bool Null() { return WriteType(kNullType); } + bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } + bool Int(int i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Double(double d) { + Number n; + if (d < 0) n.u.i = static_cast(d); + else n.u.u = static_cast(d); + n.d = d; + return WriteNumber(n); + } + + bool RawNumber(const Ch* str, SizeType len, bool) { + WriteBuffer(kNumberType, str, len * sizeof(Ch)); + return true; + } + + bool String(const Ch* str, SizeType len, bool) { + WriteBuffer(kStringType, str, len * sizeof(Ch)); + return true; + } + + bool StartObject() { return true; } + bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); } + bool EndObject(SizeType memberCount) { + uint64_t h = Hash(0, kObjectType); + uint64_t* kv = stack_.template Pop(memberCount * 2); + for (SizeType i = 0; i < memberCount; i++) + h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + *stack_.template Push() = h; + return true; + } + + bool StartArray() { return true; } + bool EndArray(SizeType elementCount) { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop(elementCount); + for (SizeType i = 0; i < elementCount; i++) + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + *stack_.template Push() = h; + return true; + } + + bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + + uint64_t GetHashCode() const { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top(); + } + +private: + static const size_t kDefaultSize = 256; + struct Number { + union U { + uint64_t u; + int64_t i; + }u; + double d; + }; + + bool WriteType(Type type) { return WriteBuffer(type, 0, 0); } + + bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); } + + bool WriteBuffer(Type type, const void* data, size_t len) { + // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + const unsigned char* d = static_cast(data); + for (size_t i = 0; i < len; i++) + h = Hash(h, d[i]); + *stack_.template Push() = h; + return true; + } + + static uint64_t Hash(uint64_t h, uint64_t d) { + static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); + h ^= d; + h *= kPrime; + return h; + } + + Stack stack_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidationContext + +template +struct SchemaValidationContext { + typedef Schema SchemaType; + typedef ISchemaStateFactory SchemaValidatorFactoryType; + typedef IValidationErrorHandler ErrorHandlerType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + + enum PatternValidatorType { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; + + SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh, const SchemaType* s, unsigned fl = 0) : + factory(f), + error_handler(eh), + schema(s), + flags(fl), + valueSchema(), + invalidKeyword(), + invalidCode(), + hasher(), + arrayElementHashCodes(), + validators(), + validatorCount(), + patternPropertiesValidators(), + patternPropertiesValidatorCount(), + patternPropertiesSchemas(), + patternPropertiesSchemaCount(), + valuePatternValidatorType(kPatternValidatorOnly), + propertyExist(), + inArray(false), + valueUniqueness(false), + arrayUniqueness(false) + { + } + + ~SchemaValidationContext() { + if (hasher) + factory.DestroryHasher(hasher); + if (validators) { + for (SizeType i = 0; i < validatorCount; i++) { + if (validators[i]) { + factory.DestroySchemaValidator(validators[i]); + } + } + factory.FreeState(validators); + } + if (patternPropertiesValidators) { + for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) { + if (patternPropertiesValidators[i]) { + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + } + } + factory.FreeState(patternPropertiesValidators); + } + if (patternPropertiesSchemas) + factory.FreeState(patternPropertiesSchemas); + if (propertyExist) + factory.FreeState(propertyExist); + } + + SchemaValidatorFactoryType& factory; + ErrorHandlerType& error_handler; + const SchemaType* schema; + unsigned flags; + const SchemaType* valueSchema; + const Ch* invalidKeyword; + ValidateErrorCode invalidCode; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; + SizeType validatorCount; + ISchemaValidator** patternPropertiesValidators; + SizeType patternPropertiesValidatorCount; + const SchemaType** patternPropertiesSchemas; + SizeType patternPropertiesSchemaCount; + PatternValidatorType valuePatternValidatorType; + PatternValidatorType objectPatternValidatorType; + SizeType arrayElementIndex; + bool* propertyExist; + bool inArray; + bool valueUniqueness; + bool arrayUniqueness; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Schema + +template +class Schema { +public: + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef SchemaValidationContext Context; + typedef Schema SchemaType; + typedef GenericValue SValue; + typedef IValidationErrorHandler ErrorHandler; + typedef GenericUri UriType; + friend class GenericSchemaDocument; + + Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator, const UriType& id = UriType()) : + allocator_(allocator), + uri_(schemaDocument->GetURI(), *allocator), + id_(id, allocator), + spec_(schemaDocument->GetSpecification()), + pointer_(p, allocator), + typeless_(schemaDocument->GetTypeless()), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), + notValidatorIndex_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), + patternPropertyCount_(), + propertyCount_(), + minProperties_(), + maxProperties_(SizeType(~0)), + additionalProperties_(true), + hasDependencies_(), + hasRequired_(), + hasSchemaDependencies_(), + additionalItemsSchema_(), + itemsList_(), + itemsTuple_(), + itemsTupleCount_(), + minItems_(), + maxItems_(SizeType(~0)), + additionalItems_(true), + uniqueItems_(false), + pattern_(), + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), + exclusiveMaximum_(false), + defaultValueLength_(0), + readOnly_(false), + writeOnly_(false), + nullable_(false) + { + GenericStringBuffer sb; + p.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Schema", sb.GetString(), id.GetString()); + + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + + // PR #1393 + // Early add this Schema and its $ref(s) in schemaDocument's map to avoid infinite + // recursion (with recursive schemas), since schemaDocument->getSchema() is always + // checked before creating a new one. Don't cache typeless_, though. + if (this != typeless_) { + typedef typename SchemaDocumentType::SchemaEntry SchemaEntry; + SchemaEntry *entry = schemaDocument->schemaMap_.template Push(); + new (entry) SchemaEntry(pointer_, this, true, allocator_); + schemaDocument->AddSchemaRefs(this); + } + + if (!value.IsObject()) + return; + + // If we have an id property, resolve it with the in-scope id + // Not supported for open api 2.0 or 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetIdString())) { + if (v->IsString()) { + UriType local(*v, allocator); + id_ = local.Resolve(id_, allocator); + RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), v->GetString(), id_.GetString()); + } + } + + if (const ValueType* v = GetMember(value, GetTypeString())) { + type_ = 0; + if (v->IsString()) + AddType(*v); + else if (v->IsArray()) + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + AddType(*itr); + } + + if (const ValueType* v = GetMember(value, GetEnumString())) { + if (v->IsArray() && v->Size() > 0) { + enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { + typedef Hasher > EnumHasherType; + char buffer[256u + 24]; + MemoryPoolAllocator hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } + } + + if (schemaDocument) + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + + // AnyOf, OneOf, Not not supported for open api 2.0 + if (schemaDocument && spec_.oapi != kVersion20) { + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); + + if (const ValueType* v = GetMember(value, GetNotString())) { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document, id_); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } + } + + // Object + + const ValueType* properties = GetMember(value, GetPropertiesString()); + const ValueType* required = GetMember(value, GetRequiredString()); + const ValueType* dependencies = GetMember(value, GetDependenciesString()); + { + // Gather properties from properties/required/dependencies + SValue allProperties(kArrayType); + + if (properties && properties->IsObject()) + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + AddUniqueElement(allProperties, itr->name); + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) + AddUniqueElement(allProperties, *itr); + + // Dependencies not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (dependencies && dependencies->IsObject()) + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + AddUniqueElement(allProperties, itr->name); + if (itr->value.IsArray()) + for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) + if (i->IsString()) + AddUniqueElement(allProperties, *i); + } + + if (allProperties.Size() > 0) { + propertyCount_ = allProperties.Size(); + properties_ = static_cast(allocator_->Malloc(sizeof(Property) * propertyCount_)); + for (SizeType i = 0; i < propertyCount_; i++) { + new (&properties_[i]) Property(); + properties_[i].name = allProperties[i]; + properties_[i].schema = typeless_; + } + } + } + + if (properties && properties->IsObject()) { + PointerType q = p.Append(GetPropertiesString(), allocator_); + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { + SizeType index; + if (FindPropertyIndex(itr->name, &index)) + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_); + } + } + + // PatternProperties not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); + patternPropertyCount_ = 0; + + for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { + new (&patternProperties_[patternPropertyCount_]) PatternProperty(); + PointerType r = q.Append(itr->name, allocator_); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name, schemaDocument, r); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, r, itr->value, document, id_); + patternPropertyCount_++; + } + } + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) { + SizeType index; + if (FindPropertyIndex(*itr, &index)) { + properties_[index].required = true; + hasRequired_ = true; + } + } + + // Dependencies not supported for open api 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (dependencies && dependencies->IsObject()) { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + SizeType sourceIndex; + if (FindPropertyIndex(itr->name, &sourceIndex)) { + if (itr->value.IsArray()) { + properties_[sourceIndex].dependencies = static_cast(allocator_->Malloc(sizeof(bool) * propertyCount_)); + std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); + for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { + SizeType targetIndex; + if (FindPropertyIndex(*targetItr, &targetIndex)) + properties_[sourceIndex].dependencies[targetIndex] = true; + } + } + else if (itr->value.IsObject()) { + hasSchemaDependencies_ = true; + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } + } + } + } + + if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) { + if (v->IsBool()) + additionalProperties_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_); + } + + AssignIfExist(minProperties_, value, GetMinPropertiesString()); + AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); + + // Array + if (const ValueType* v = GetMember(value, GetItemsString())) { + PointerType q = p.Append(GetItemsString(), allocator_); + if (v->IsObject()) // List validation + schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_); + else if (v->IsArray()) { // Tuple validation + itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); + SizeType index = 0; + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_); + } + } + + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); + + // AdditionalItems not supported for openapi 2.0 and 3.0 + if (spec_.oapi != kVersion20 && spec_.oapi != kVersion30) + if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { + if (v->IsBool()) + additionalItems_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_); + } + + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); + + // String + AssignIfExist(minLength_, value, GetMinLengthString()); + AssignIfExist(maxLength_, value, GetMaxLengthString()); + + if (const ValueType* v = GetMember(value, GetPatternString())) + pattern_ = CreatePattern(*v, schemaDocument, p.Append(GetPatternString(), allocator_)); + + // Number + if (const ValueType* v = GetMember(value, GetMinimumString())) + if (v->IsNumber()) + minimum_.CopyFrom(*v, *allocator_); + + if (const ValueType* v = GetMember(value, GetMaximumString())) + if (v->IsNumber()) + maximum_.CopyFrom(*v, *allocator_); + + AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); + AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + + if (const ValueType* v = GetMember(value, GetMultipleOfString())) + if (v->IsNumber() && v->GetDouble() > 0.0) + multipleOf_.CopyFrom(*v, *allocator_); + + // Default + if (const ValueType* v = GetMember(value, GetDefaultValueString())) + if (v->IsString()) + defaultValueLength_ = v->GetStringLength(); + + // ReadOnly - open api only (until draft 7 supported) + // WriteOnly - open api 3 only (until draft 7 supported) + // Both can't be true + if (spec_.oapi != kVersionNone) + AssignIfExist(readOnly_, value, GetReadOnlyString()); + if (spec_.oapi >= kVersion30) + AssignIfExist(writeOnly_, value, GetWriteOnlyString()); + if (readOnly_ && writeOnly_) + schemaDocument->SchemaError(kSchemaErrorReadOnlyAndWriteOnly, p); + + // Nullable - open api 3 only + // If true add 'null' as allowable type + if (spec_.oapi >= kVersion30) { + AssignIfExist(nullable_, value, GetNullableString()); + if (nullable_) + AddType(GetNullString()); + } + } + + ~Schema() { + AllocatorType::Free(enum_); + if (properties_) { + for (SizeType i = 0; i < propertyCount_; i++) + properties_[i].~Property(); + AllocatorType::Free(properties_); + } + if (patternProperties_) { + for (SizeType i = 0; i < patternPropertyCount_; i++) + patternProperties_[i].~PatternProperty(); + AllocatorType::Free(patternProperties_); + } + AllocatorType::Free(itemsTuple_); +#if RAPIDJSON_SCHEMA_HAS_REGEX + if (pattern_) { + pattern_->~RegexType(); + AllocatorType::Free(pattern_); + } +#endif + } + + const SValue& GetURI() const { + return uri_; + } + + const UriType& GetId() const { + return id_; + } + + const Specification& GetSpecification() const { + return spec_; + } + + const PointerType& GetPointer() const { + return pointer_; + } + + bool BeginValue(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::BeginValue"); + if (context.inArray) { + if (uniqueItems_) + context.valueUniqueness = true; + + if (itemsList_) + context.valueSchema = itemsList_; + else if (itemsTuple_) { + if (context.arrayElementIndex < itemsTupleCount_) + context.valueSchema = itemsTuple_[context.arrayElementIndex]; + else if (additionalItemsSchema_) + context.valueSchema = additionalItemsSchema_; + else if (additionalItems_) + context.valueSchema = typeless_; + else { + context.error_handler.DisallowedItem(context.arrayElementIndex); + // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error + context.valueSchema = typeless_; + // Must bump arrayElementIndex for when kValidateContinueOnErrorFlag is set + context.arrayElementIndex++; + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalItems); + } + } + else + context.valueSchema = typeless_; + + context.arrayElementIndex++; + } + return true; + } + + RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndValue"); + // Only check pattern properties if we have validators + if (context.patternPropertiesValidatorCount > 0) { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; + if (context.objectPatternValidatorType != Context::kPatternValidatorOnly) + otherValid = context.patternPropertiesValidators[--count]->IsValid(); + + bool patternValid = true; + for (SizeType i = 0; i < count; i++) + if (!context.patternPropertiesValidators[i]->IsValid()) { + patternValid = false; + break; + } + + if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { + if (!patternValid) { + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { + if (!patternValid || !otherValid) { + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty) + context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPatternProperties); + } + } + + // For enums only check if we have a hasher + if (enum_ && context.hasher) { + const uint64_t h = context.factory.GetHashCode(context.hasher); + for (SizeType i = 0; i < enumCount_; i++) + if (enum_[i] == h) + goto foundEnum; + context.error_handler.DisallowedValue(kValidateErrorEnum); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorEnum); + foundEnum:; + } + + // Only check allOf etc if we have validators + if (context.validatorCount > 0) { + if (allOf_.schemas) + for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if (!context.validators[i]->IsValid()) { + context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAllOf); + } + + if (anyOf_.schemas) { + for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if (context.validators[i]->IsValid()) + goto foundAny; + context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAnyOf); + foundAny:; + } + + if (oneOf_.schemas) { + bool oneValid = false; + SizeType firstMatch = 0; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) { + context.error_handler.MultipleOneOf(firstMatch, i - oneOf_.begin); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOfMatch); + } else { + oneValid = true; + firstMatch = i - oneOf_.begin; + } + } + if (!oneValid) { + context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorOneOf); + } + } + + if (not_ && context.validators[notValidatorIndex_]->IsValid()) { + context.error_handler.Disallowed(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorNot); + } + } + + return true; + } + + bool Null(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Null"); + if (!(type_ & (1 << kNullSchemaType))) { + DisallowedType(context, GetNullString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return CreateParallelValidator(context); + } + + bool Bool(Context& context, bool b) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Bool", b); + if (!CheckBool(context, b)) + return false; + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int", (int64_t)i); + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint", (uint64_t)u); + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Int64", i); + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Uint64", u); + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Double(Context& context, double d) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Double", d); + if (!(type_ & (1 << kNumberSchemaType))) { + DisallowedType(context, GetNumberString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) + return false; + + if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) + return false; + + if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) + return false; + + return CreateParallelValidator(context); + } + + bool String(Context& context, const Ch* str, SizeType length, bool) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::String", str); + if (!(type_ & (1 << kStringSchemaType))) { + DisallowedType(context, GetStringString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint(str, length, &count)) { + if (count < minLength_) { + context.error_handler.TooShort(str, length, minLength_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinLength); + } + if (count > maxLength_) { + context.error_handler.TooLong(str, length, maxLength_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxLength); + } + } + } + + if (pattern_ && !IsPatternMatch(pattern_, str, length)) { + context.error_handler.DoesNotMatch(str, length); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorPattern); + } + + return CreateParallelValidator(context); + } + + bool StartObject(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartObject"); + if (!(type_ & (1 << kObjectSchemaType))) { + DisallowedType(context, GetObjectString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); + std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); + } + + if (patternProperties_) { // pre-allocate schema array + SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType + context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof(const SchemaType*) * count)); + context.patternPropertiesSchemaCount = 0; + std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); + } + + return CreateParallelValidator(context); + } + + bool Key(Context& context, const Ch* str, SizeType len, bool) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::Key", str); + + if (patternProperties_) { + context.patternPropertiesSchemaCount = 0; + for (SizeType i = 0; i < patternPropertyCount_; i++) + if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; + context.valueSchema = typeless_; + } + } + + SizeType index = 0; + if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else + context.valueSchema = properties_[index].schema; + + if (context.propertyExist) + context.propertyExist[index] = true; + + return true; + } + + if (additionalPropertiesSchema_) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else + context.valueSchema = additionalPropertiesSchema_; + return true; + } + else if (additionalProperties_) { + context.valueSchema = typeless_; + return true; + } + + if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties + // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error + context.valueSchema = typeless_; + context.error_handler.DisallowedProperty(str, len); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorAdditionalProperties); + } + + return true; + } + + bool EndObject(Context& context, SizeType memberCount) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndObject"); + if (hasRequired_) { + context.error_handler.StartMissingProperties(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].required && !context.propertyExist[index]) + if (properties_[index].schema->defaultValueLength_ == 0 ) + context.error_handler.AddMissingProperty(properties_[index].name); + if (context.error_handler.EndMissingProperties()) + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorRequired); + } + + if (memberCount < minProperties_) { + context.error_handler.TooFewProperties(memberCount, minProperties_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinProperties); + } + + if (memberCount > maxProperties_) { + context.error_handler.TooManyProperties(memberCount, maxProperties_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxProperties); + } + + if (hasDependencies_) { + context.error_handler.StartDependencyErrors(); + for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) { + const Property& source = properties_[sourceIndex]; + if (context.propertyExist[sourceIndex]) { + if (source.dependencies) { + context.error_handler.StartMissingDependentProperties(); + for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) + if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex]) + context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name); + context.error_handler.EndMissingDependentProperties(source.name); + } + else if (source.dependenciesSchema) { + ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex]; + if (!dependenciesValidator->IsValid()) + context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator); + } + } + } + if (context.error_handler.EndDependencyErrors()) + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorDependencies); + } + + return true; + } + + bool StartArray(Context& context) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::StartArray"); + context.arrayElementIndex = 0; + context.inArray = true; // Ensure we note that we are in an array + + if (!(type_ & (1 << kArraySchemaType))) { + DisallowedType(context, GetArrayString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + return CreateParallelValidator(context); + } + + bool EndArray(Context& context, SizeType elementCount) const { + RAPIDJSON_SCHEMA_PRINT(Method, "Schema::EndArray"); + context.inArray = false; + + if (elementCount < minItems_) { + context.error_handler.TooFewItems(elementCount, minItems_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMinItems); + } + + if (elementCount > maxItems_) { + context.error_handler.TooManyItems(elementCount, maxItems_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMaxItems); + } + + return true; + } + + static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) { + switch (validateErrorCode) { + case kValidateErrorMultipleOf: return GetMultipleOfString(); + case kValidateErrorMaximum: return GetMaximumString(); + case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same + case kValidateErrorMinimum: return GetMinimumString(); + case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same + + case kValidateErrorMaxLength: return GetMaxLengthString(); + case kValidateErrorMinLength: return GetMinLengthString(); + case kValidateErrorPattern: return GetPatternString(); + + case kValidateErrorMaxItems: return GetMaxItemsString(); + case kValidateErrorMinItems: return GetMinItemsString(); + case kValidateErrorUniqueItems: return GetUniqueItemsString(); + case kValidateErrorAdditionalItems: return GetAdditionalItemsString(); + + case kValidateErrorMaxProperties: return GetMaxPropertiesString(); + case kValidateErrorMinProperties: return GetMinPropertiesString(); + case kValidateErrorRequired: return GetRequiredString(); + case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString(); + case kValidateErrorPatternProperties: return GetPatternPropertiesString(); + case kValidateErrorDependencies: return GetDependenciesString(); + + case kValidateErrorEnum: return GetEnumString(); + case kValidateErrorType: return GetTypeString(); + + case kValidateErrorOneOf: return GetOneOfString(); + case kValidateErrorOneOfMatch: return GetOneOfString(); // Same + case kValidateErrorAllOf: return GetAllOfString(); + case kValidateErrorAnyOf: return GetAnyOfString(); + case kValidateErrorNot: return GetNotString(); + + case kValidateErrorReadOnly: return GetReadOnlyString(); + case kValidateErrorWriteOnly: return GetWriteOnlyString(); + + default: return GetNullString(); + } + } + + + // Generate functions for string literal according to Ch +#define RAPIDJSON_STRING_(name, ...) \ + static const ValueType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const ValueType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1));\ + return v;\ + } + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') + RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') + RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') + RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') + RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') + RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') + RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') + RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') + RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') + RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') + RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') + RAPIDJSON_STRING_(Not, 'n', 'o', 't') + RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') + RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') + RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') + RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') + RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't') + RAPIDJSON_STRING_(Schema, '$', 's', 'c', 'h', 'e', 'm', 'a') + RAPIDJSON_STRING_(Ref, '$', 'r', 'e', 'f') + RAPIDJSON_STRING_(Id, 'i', 'd') + RAPIDJSON_STRING_(Swagger, 's', 'w', 'a', 'g', 'g', 'e', 'r') + RAPIDJSON_STRING_(OpenApi, 'o', 'p', 'e', 'n', 'a', 'p', 'i') + RAPIDJSON_STRING_(ReadOnly, 'r', 'e', 'a', 'd', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(WriteOnly, 'w', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(Nullable, 'n', 'u', 'l', 'l', 'a', 'b', 'l', 'e') + +#undef RAPIDJSON_STRING_ + +private: + enum SchemaValueType { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + typedef internal::GenericRegex RegexType; +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex RegexType; +#else + typedef char RegexType; +#endif + + struct SchemaArray { + SchemaArray() : schemas(), count() {} + ~SchemaArray() { AllocatorType::Free(schemas); } + const SchemaType** schemas; + SizeType begin; // begin index of context.validators + SizeType count; + }; + + template + void AddUniqueElement(V1& a, const V2& v) { + for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + if (*itr == v) + return; + V1 c(v, *allocator_); + a.PushBack(c, *allocator_); + } + + static const ValueType* GetMember(const ValueType& value, const ValueType& name) { + typename ValueType::ConstMemberIterator itr = value.FindMember(name); + return itr != value.MemberEnd() ? &(itr->value) : 0; + } + + static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsBool()) + out = v->GetBool(); + } + + static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) + out = static_cast(v->GetUint64()); + } + + void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) { + if (const ValueType* v = GetMember(value, name)) { + if (v->IsArray() && v->Size() > 0) { + PointerType q = p.Append(name, allocator_); + out.count = v->Size(); + out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); + memset(out.schemas, 0, sizeof(Schema*)* out.count); + for (SizeType i = 0; i < out.count; i++) + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document, id_); + out.begin = validatorCount_; + validatorCount_ += out.count; + } + } + } + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + template + RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { + if (value.IsString()) { + RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_); + if (!r->IsValid()) { + sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { + GenericRegexSearch rs(*pattern); + return rs.Search(str); + } +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + template + RegexType* CreatePattern(const ValueType& value, SchemaDocumentType* sd, const PointerType& p) { + if (value.IsString()) { + RegexType *r = static_cast(allocator_->Malloc(sizeof(RegexType))); + try { + return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } + catch (const std::regex_error& e) { + sd->SchemaErrorValue(kSchemaErrorRegexInvalid, p, value.GetString(), value.GetStringLength()); + AllocatorType::Free(r); + } + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { + std::match_results r; + return std::regex_search(str, str + length, r, *pattern); + } +#else + template + RegexType* CreatePattern(const ValueType&) { + return 0; + } + + static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } +#endif // RAPIDJSON_SCHEMA_USE_STDREGEX + + void AddType(const ValueType& type) { + if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; + else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; + else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; + else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; + else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; + else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; + else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + + // Creates parallel validators for allOf, anyOf, oneOf, not and schema dependencies, if required. + // Also creates a hasher for enums and array uniqueness, if required. + // Also a useful place to add type-independent error checks. + bool CreateParallelValidator(Context& context) const { + if (enum_ || context.arrayUniqueness) + context.hasher = context.factory.CreateHasher(); + + if (validatorCount_) { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); + std::memset(context.validators, 0, sizeof(ISchemaValidator*) * validatorCount_); + context.validatorCount = validatorCount_; + + // Always return after first failure for these sub-validators + if (allOf_.schemas) + CreateSchemaValidators(context, allOf_, false); + + if (anyOf_.schemas) + CreateSchemaValidators(context, anyOf_, false); + + if (oneOf_.schemas) + CreateSchemaValidators(context, oneOf_, false); + + if (not_) + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_, false); + + if (hasSchemaDependencies_) { + for (SizeType i = 0; i < propertyCount_; i++) + if (properties_[i].dependenciesSchema) + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema, false); + } + } + + // Add any other type-independent checks here + if (readOnly_ && (context.flags & kValidateWriteFlag)) { + context.error_handler.DisallowedWhenWriting(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorReadOnly); + } + if (writeOnly_ && (context.flags & kValidateReadFlag)) { + context.error_handler.DisallowedWhenReading(); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorWriteOnly); + } + + return true; + } + + void CreateSchemaValidators(Context& context, const SchemaArray& schemas, const bool inheritContinueOnErrors) const { + for (SizeType i = 0; i < schemas.count; i++) + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors); + } + + // O(n) + bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; + return true; + } + return false; + } + + bool CheckBool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) { + DisallowedType(context, GetBooleanString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + return true; + } + + bool CheckInt(Context& context, int64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { + DisallowedType(context, GetIntegerString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull()) { + if (minimum_.IsInt64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + } + else if (minimum_.IsUint64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); // i <= max(int64_t) < minimum.GetUint64() + } + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsInt64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + } + else if (maximum_.IsUint64()) { } + /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64() + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) { + context.error_handler.NotMultipleOf(i, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckUint(Context& context, uint64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) { + DisallowedType(context, GetIntegerString()); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorType); + } + + if (!minimum_.IsNull()) { + if (minimum_.IsUint64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) { + context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + } + else if (minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsUint64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + } + else if (maximum_.IsInt64()) { + context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); // i >= 0 > maximum_ + } + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (i % multipleOf_.GetUint64() != 0) { + context.error_handler.NotMultipleOf(i, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckDoubleMinimum(Context& context, double d) const { + if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) { + context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); + } + return true; + } + + bool CheckDoubleMaximum(Context& context, double d) const { + if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) { + context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_); + RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMaximum_ ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum); + } + return true; + } + + bool CheckDoubleMultipleOf(Context& context, double d) const { + double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); + double q = std::floor(a / b); + double r = a - q * b; + if (r > 0.0) { + context.error_handler.NotMultipleOf(d, multipleOf_); + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorMultipleOf); + } + return true; + } + + void DisallowedType(Context& context, const ValueType& actualType) const { + ErrorHandler& eh = context.error_handler; + eh.StartDisallowedType(); + + if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString()); + if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString()); + if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString()); + if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString()); + if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString()); + + if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString()); + else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString()); + + eh.EndDisallowedType(actualType); + } + + struct Property { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() { AllocatorType::Free(dependencies); } + SValue name; + const SchemaType* schema; + const SchemaType* dependenciesSchema; + SizeType dependenciesValidatorIndex; + bool* dependencies; + bool required; + }; + + struct PatternProperty { + PatternProperty() : schema(), pattern() {} + ~PatternProperty() { + if (pattern) { + pattern->~RegexType(); + AllocatorType::Free(pattern); + } + } + const SchemaType* schema; + RegexType* pattern; + }; + + AllocatorType* allocator_; + SValue uri_; + UriType id_; + Specification spec_; + PointerType pointer_; + const SchemaType* typeless_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; + SchemaArray anyOf_; + SchemaArray oneOf_; + const SchemaType* not_; + unsigned type_; // bitmask of kSchemaType + SizeType validatorCount_; + SizeType notValidatorIndex_; + + Property* properties_; + const SchemaType* additionalPropertiesSchema_; + PatternProperty* patternProperties_; + SizeType patternPropertyCount_; + SizeType propertyCount_; + SizeType minProperties_; + SizeType maxProperties_; + bool additionalProperties_; + bool hasDependencies_; + bool hasRequired_; + bool hasSchemaDependencies_; + + const SchemaType* additionalItemsSchema_; + const SchemaType* itemsList_; + const SchemaType** itemsTuple_; + SizeType itemsTupleCount_; + SizeType minItems_; + SizeType maxItems_; + bool additionalItems_; + bool uniqueItems_; + + RegexType* pattern_; + SizeType minLength_; + SizeType maxLength_; + + SValue minimum_; + SValue maximum_; + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; + + SizeType defaultValueLength_; + + bool readOnly_; + bool writeOnly_; + bool nullable_; +}; + +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + *documentStack.template Push() = '/'; + char buffer[21]; + size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) + *documentStack.template Push() = static_cast(buffer[i]); + } +}; + +// Partial specialized version for char to prevent buffer copying. +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + if (sizeof(SizeType) == 4) { + char *buffer = documentStack.template Push(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop(static_cast(10 - (end - buffer))); + } + else { + char *buffer = documentStack.template Push(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop(static_cast(20 - (end - buffer))); + } + } +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// IGenericRemoteSchemaDocumentProvider + +template +class IGenericRemoteSchemaDocumentProvider { +public: + typedef typename SchemaDocumentType::Ch Ch; + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; + virtual const SchemaDocumentType* GetRemoteDocument(const GenericUri uri, Specification& spec) { + // Default implementation just calls through for compatibility + // Following line suppresses unused parameter warning + (void)spec; + // printf("GetRemoteDocument: %d %d\n", spec.draft, spec.oapi); + return GetRemoteDocument(uri.GetBaseString(), uri.GetBaseStringLength()); + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaDocument + +//! JSON schema document. +/*! + A JSON schema document is a compiled version of a JSON schema. + It is basically a tree of internal::Schema. + + \note This is an immutable class (i.e. its instance cannot be modified after construction). + \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding. + \tparam Allocator Allocator type for allocating memory of this document. +*/ +template +class GenericSchemaDocument { +public: + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema SchemaType; + typedef GenericPointer PointerType; + typedef GenericValue GValue; + typedef GenericUri UriType; + typedef GenericStringRef StringRefType; + friend class internal::Schema; + template + friend class GenericSchemaValidator; + + //! Constructor. + /*! + Compile a JSON document into schema document. + + \param document A JSON document as source. + \param uri The base URI of this schema document for purposes of violation reporting. + \param uriLength Length of \c name, in code points. + \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. + \param allocator An optional allocator instance for allocating memory. Can be null. + \param pointer An optional JSON pointer to the start of the schema document + \param spec Optional schema draft or OpenAPI version. Used if no specification in document. Defaults to draft-04. + */ + explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0, + IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0, + const PointerType& pointer = PointerType(), // PR #1393 + const Specification& spec = Specification(kDraft04)) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + typeless_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize), + spec_(spec), + error_(kObjectType), + currentError_() + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::GenericSchemaDocument"); + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + Ch noUri[1] = {0}; + uri_.SetString(uri ? uri : noUri, uriLength, *allocator_); + docId_ = UriType(uri_, allocator_); + + typeless_ = static_cast(allocator_->Malloc(sizeof(SchemaType))); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_); + + // Establish the schema draft or open api version. + // We only ever look for '$schema' or 'swagger' or 'openapi' at the root of the document. + SetSchemaSpecification(document); + + // Generate root schema, it will call CreateSchema() to create sub-schemas, + // And call HandleRefSchema() if there are $ref. + // PR #1393 use input pointer if supplied + root_ = typeless_; + if (pointer.GetTokenCount() == 0) { + CreateSchemaRecursive(&root_, pointer, document, document, docId_); + } + else if (const ValueType* v = pointer.Get(document)) { + CreateSchema(&root_, pointer, *v, document, docId_); + } + else { + GenericStringBuffer sb; + pointer.StringifyUriFragment(sb); + SchemaErrorValue(kSchemaErrorStartUnknown, PointerType(), sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch))); + } + + RAPIDJSON_ASSERT(root_ != 0); + + schemaRef_.ShrinkToFit(); // Deallocate all memory for ref + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : + remoteProvider_(rhs.remoteProvider_), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), + typeless_(rhs.typeless_), + schemaMap_(std::move(rhs.schemaMap_)), + schemaRef_(std::move(rhs.schemaRef_)), + uri_(std::move(rhs.uri_)), + docId_(std::move(rhs.docId_)), + spec_(rhs.spec_), + error_(std::move(rhs.error_)), + currentError_(std::move(rhs.currentError_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.typeless_ = 0; + } +#endif + + //! Destructor + ~GenericSchemaDocument() { + while (!schemaMap_.Empty()) + schemaMap_.template Pop(1)->~SchemaEntry(); + + if (typeless_) { + typeless_->~SchemaType(); + Allocator::Free(typeless_); + } + + // these may contain some allocator data so clear before deleting ownAllocator_ + uri_.SetNull(); + error_.SetNull(); + currentError_.SetNull(); + + RAPIDJSON_DELETE(ownAllocator_); + } + + const GValue& GetURI() const { return uri_; } + + const Specification& GetSpecification() const { return spec_; } + bool IsSupportedSpecification() const { return spec_.IsSupported(); } + + //! Static method to get the specification of any schema document + // Returns kDraftNone if document is silent + static const Specification GetSpecification(const ValueType& document) { + SchemaDraft draft = GetSchemaDraft(document); + if (draft != kDraftNone) + return Specification(draft); + else { + OpenApiVersion oapi = GetOpenApiVersion(document); + if (oapi != kVersionNone) + return Specification(oapi); + } + return Specification(kDraftNone); + } + + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + + //! Gets the error object. + GValue& GetError() { return error_; } + const GValue& GetError() const { return error_; } + + static const StringRefType& GetSchemaErrorKeyword(SchemaErrorCode schemaErrorCode) { + switch (schemaErrorCode) { + case kSchemaErrorStartUnknown: return GetStartUnknownString(); + case kSchemaErrorRefPlainName: return GetRefPlainNameString(); + case kSchemaErrorRefInvalid: return GetRefInvalidString(); + case kSchemaErrorRefPointerInvalid: return GetRefPointerInvalidString(); + case kSchemaErrorRefUnknown: return GetRefUnknownString(); + case kSchemaErrorRefCyclical: return GetRefCyclicalString(); + case kSchemaErrorRefNoRemoteProvider: return GetRefNoRemoteProviderString(); + case kSchemaErrorRefNoRemoteSchema: return GetRefNoRemoteSchemaString(); + case kSchemaErrorRegexInvalid: return GetRegexInvalidString(); + case kSchemaErrorSpecUnknown: return GetSpecUnknownString(); + case kSchemaErrorSpecUnsupported: return GetSpecUnsupportedString(); + case kSchemaErrorSpecIllegal: return GetSpecIllegalString(); + case kSchemaErrorReadOnlyAndWriteOnly: return GetReadOnlyAndWriteOnlyString(); + default: return GetNullString(); + } + } + + //! Default error method + void SchemaError(const SchemaErrorCode code, const PointerType& location) { + currentError_ = GValue(kObjectType); + AddCurrentError(code, location); + } + + //! Method for error with single string value insert + void SchemaErrorValue(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length) { + currentError_ = GValue(kObjectType); + currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); + AddCurrentError(code, location); + } + + //! Method for error with invalid pointer + void SchemaErrorPointer(const SchemaErrorCode code, const PointerType& location, const Ch* value, SizeType length, const PointerType& pointer) { + currentError_ = GValue(kObjectType); + currentError_.AddMember(GetValueString(), GValue(value, length, *allocator_).Move(), *allocator_); + currentError_.AddMember(GetOffsetString(), static_cast(pointer.GetParseErrorOffset() / sizeof(Ch)), *allocator_); + AddCurrentError(code, location); + } + + private: + //! Prohibit copying + GenericSchemaDocument(const GenericSchemaDocument&); + //! Prohibit assignment + GenericSchemaDocument& operator=(const GenericSchemaDocument&); + + typedef const PointerType* SchemaRefPtr; // PR #1393 + + struct SchemaEntry { + SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} + ~SchemaEntry() { + if (owned) { + schema->~SchemaType(); + Allocator::Free(schema); + } + } + PointerType pointer; + SchemaType* schema; + bool owned; + }; + + void AddErrorInstanceLocation(GValue& result, const PointerType& location) { + GenericStringBuffer sb; + location.StringifyUriFragment(sb); + GValue instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), *allocator_); + result.AddMember(GetInstanceRefString(), instanceRef, *allocator_); + } + + void AddError(GValue& keyword, GValue& error) { + typename GValue::MemberIterator member = error_.FindMember(keyword); + if (member == error_.MemberEnd()) + error_.AddMember(keyword, error, *allocator_); + else { + if (member->value.IsObject()) { + GValue errors(kArrayType); + errors.PushBack(member->value, *allocator_); + member->value = errors; + } + member->value.PushBack(error, *allocator_); + } + } + + void AddCurrentError(const SchemaErrorCode code, const PointerType& location) { + RAPIDJSON_SCHEMA_PRINT(InvalidKeyword, GetSchemaErrorKeyword(code)); + currentError_.AddMember(GetErrorCodeString(), code, *allocator_); + AddErrorInstanceLocation(currentError_, location); + AddError(GValue(GetSchemaErrorKeyword(code)).Move(), currentError_); + } + +#define RAPIDJSON_STRING_(name, ...) \ + static const StringRefType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ + return v;\ + } + + RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') + RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') + RAPIDJSON_STRING_(Value, 'v', 'a', 'l', 'u', 'e') + RAPIDJSON_STRING_(Offset, 'o', 'f', 'f', 's', 'e', 't') + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(SpecUnknown, 'S', 'p', 'e', 'c', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(SpecUnsupported, 'S', 'p', 'e', 'c', 'U', 'n', 's', 'u', 'p', 'p', 'o', 'r', 't', 'e', 'd') + RAPIDJSON_STRING_(SpecIllegal, 'S', 'p', 'e', 'c', 'I', 'l', 'l', 'e', 'g', 'a', 'l') + RAPIDJSON_STRING_(StartUnknown, 'S', 't', 'a', 'r', 't', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(RefPlainName, 'R', 'e', 'f', 'P', 'l', 'a', 'i', 'n', 'N', 'a', 'm', 'e') + RAPIDJSON_STRING_(RefInvalid, 'R', 'e', 'f', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + RAPIDJSON_STRING_(RefPointerInvalid, 'R', 'e', 'f', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + RAPIDJSON_STRING_(RefUnknown, 'R', 'e', 'f', 'U', 'n', 'k', 'n', 'o', 'w', 'n') + RAPIDJSON_STRING_(RefCyclical, 'R', 'e', 'f', 'C', 'y', 'c', 'l', 'i', 'c', 'a', 'l') + RAPIDJSON_STRING_(RefNoRemoteProvider, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r') + RAPIDJSON_STRING_(RefNoRemoteSchema, 'R', 'e', 'f', 'N', 'o', 'R', 'e', 'm', 'o', 't', 'e', 'S', 'c', 'h', 'e', 'm', 'a') + RAPIDJSON_STRING_(ReadOnlyAndWriteOnly, 'R', 'e', 'a', 'd', 'O', 'n', 'l', 'y', 'A', 'n', 'd', 'W', 'r', 'i', 't', 'e', 'O', 'n', 'l', 'y') + RAPIDJSON_STRING_(RegexInvalid, 'R', 'e', 'g', 'e', 'x', 'I', 'n', 'v', 'a', 'l', 'i', 'd') + +#undef RAPIDJSON_STRING_ + + // Static method to get schema draft of any schema document + static SchemaDraft GetSchemaDraft(const ValueType& document) { + static const Ch kDraft03String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '3', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft04String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '4', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft05String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '5', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft06String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '6', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft07String[] = { 'h', 't', 't', 'p', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '-', '0', '7', '/', 's', 'c', 'h', 'e', 'm', 'a', '#', '\0' }; + static const Ch kDraft2019_09String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '1', '9', '-', '0', '9', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; + static const Ch kDraft2020_12String[] = { 'h', 't', 't', 'p', 's', ':', '/', '/', 'j', 's', 'o', 'n', '-', 's', 'c', 'h', 'e', 'm', 'a', '.', 'o', 'r', 'g', '/', 'd', 'r', 'a', 'f', 't', '/', '2', '0', '2', '0', '-', '1', '2', '/', 's', 'c', 'h', 'e', 'm', 'a', '\0' }; + + if (!document.IsObject()) { + return kDraftNone; + } + + // Get the schema draft from the $schema keyword at the supplied location + typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSchemaString()); + if (itr != document.MemberEnd()) { + if (!itr->value.IsString()) return kDraftUnknown; + const UriType draftUri(itr->value); + // Check base uri for match + if (draftUri.Match(UriType(kDraft04String), false)) return kDraft04; + if (draftUri.Match(UriType(kDraft05String), false)) return kDraft05; + if (draftUri.Match(UriType(kDraft06String), false)) return kDraft06; + if (draftUri.Match(UriType(kDraft07String), false)) return kDraft07; + if (draftUri.Match(UriType(kDraft03String), false)) return kDraft03; + if (draftUri.Match(UriType(kDraft2019_09String), false)) return kDraft2019_09; + if (draftUri.Match(UriType(kDraft2020_12String), false)) return kDraft2020_12; + return kDraftUnknown; + } + // $schema not found + return kDraftNone; + } + + + // Get open api version of any schema document + static OpenApiVersion GetOpenApiVersion(const ValueType& document) { + static const Ch kVersion20String[] = { '2', '.', '0', '\0' }; + static const Ch kVersion30String[] = { '3', '.', '0', '.', '\0' }; // ignore patch level + static const Ch kVersion31String[] = { '3', '.', '1', '.', '\0' }; // ignore patch level + static SizeType len = internal::StrLen(kVersion30String); + + if (!document.IsObject()) { + return kVersionNone; + } + + // Get the open api version from the swagger / openapi keyword at the supplied location + typename ValueType::ConstMemberIterator itr = document.FindMember(SchemaType::GetSwaggerString()); + if (itr == document.MemberEnd()) itr = document.FindMember(SchemaType::GetOpenApiString()); + if (itr != document.MemberEnd()) { + if (!itr->value.IsString()) return kVersionUnknown; + const ValueType kVersion20Value(kVersion20String); + if (kVersion20Value == itr->value) return kVersion20; // must match 2.0 exactly + const ValueType kVersion30Value(kVersion30String); + if (itr->value.GetStringLength() > len && kVersion30Value == ValueType(itr->value.GetString(), len)) return kVersion30; // must match 3.0.x + const ValueType kVersion31Value(kVersion31String); + if (itr->value.GetStringLength() > len && kVersion31Value == ValueType(itr->value.GetString(), len)) return kVersion31; // must match 3.1.x + return kVersionUnknown; + } + // swagger or openapi not found + return kVersionNone; + } + + // Get the draft of the schema or the open api version (which implies the draft). + // Report an error if schema draft or open api version not supported or not recognized, or both in document, and carry on. + void SetSchemaSpecification(const ValueType& document) { + // Look for '$schema', 'swagger' or 'openapi' keyword at document root + SchemaDraft docDraft = GetSchemaDraft(document); + OpenApiVersion docOapi = GetOpenApiVersion(document); + // Error if both in document + if (docDraft != kDraftNone && docOapi != kVersionNone) + SchemaError(kSchemaErrorSpecIllegal, PointerType()); + // Use document draft or open api version if present or use spec from constructor + if (docDraft != kDraftNone) + spec_ = Specification(docDraft); + else if (docOapi != kVersionNone) + spec_ = Specification(docOapi); + // Error if draft or version unknown + if (spec_.draft == kDraftUnknown || spec_.oapi == kVersionUnknown) + SchemaError(kSchemaErrorSpecUnknown, PointerType()); + else if (!spec_.IsSupported()) + SchemaError(kSchemaErrorSpecUnsupported, PointerType()); + } + + // Changed by PR #1393 + void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { + if (v.GetType() == kObjectType) { + UriType newid = UriType(CreateSchema(schema, pointer, v, document, id), allocator_); + + for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid); + } + else if (v.GetType() == kArrayType) + for (SizeType i = 0; i < v.Size(); i++) + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document, id); + } + + // Changed by PR #1393 + const UriType& CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { + RAPIDJSON_ASSERT(pointer.IsValid()); + GenericStringBuffer sb; + pointer.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::CreateSchema", sb.GetString(), id.GetString()); + if (v.IsObject()) { + if (const SchemaType* sc = GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast(sc)); + } + else if (!HandleRefSchema(pointer, schema, v, document, id)) { + // The new schema constructor adds itself and its $ref(s) to schemaMap_ + SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_, id); + if (schema) + *schema = s; + return s->GetId(); + } + } + else { + if (schema) + *schema = typeless_; + AddSchemaRefs(typeless_); + } + return id; + } + + // Changed by PR #1393 + // TODO should this return a UriType& ? + bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document, const UriType& id) { + typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString()); + if (itr == v.MemberEnd()) + return false; + + GenericStringBuffer sb; + source.StringifyUriFragment(sb); + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::HandleRefSchema", sb.GetString(), id.GetString()); + // Resolve the source pointer to the $ref'ed schema (finally) + new (schemaRef_.template Push()) SchemaRefPtr(&source); + + if (itr->value.IsString()) { + SizeType len = itr->value.GetStringLength(); + if (len == 0) + SchemaError(kSchemaErrorRefInvalid, source); + else { + // First resolve $ref against the in-scope id + UriType scopeId = UriType(id, allocator_); + UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_); + RAPIDJSON_SCHEMA_PRINT(SchemaIds, id.GetString(), itr->value.GetString(), ref.GetString()); + // See if the resolved $ref minus the fragment matches a resolved id in this document + // Search from the root. Returns the subschema in the document and its absolute JSON pointer. + PointerType basePointer = PointerType(); + const ValueType *base = FindId(document, ref, basePointer, docId_, false); + if (!base) { + // Remote reference - call the remote document provider + if (!remoteProvider_) + SchemaError(kSchemaErrorRefNoRemoteProvider, source); + else { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref, spec_)) { + const Ch* s = ref.GetFragString(); + len = ref.GetFragStringLength(); + if (len <= 1 || s[1] == '/') { + // JSON pointer fragment, absolute in the remote schema + const PointerType pointer(s, len, allocator_); + if (!pointer.IsValid()) + SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, pointer); + else { + // Get the subschema + if (const SchemaType *sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + AddSchemaRefs(const_cast(sc)); + return true; + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } else + // Plain name fragment, not allowed in remote schema + SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); + } else + SchemaErrorValue(kSchemaErrorRefNoRemoteSchema, source, ref.GetString(), ref.GetStringLength()); + } + } + else { // Local reference + const Ch* s = ref.GetFragString(); + len = ref.GetFragStringLength(); + if (len <= 1 || s[1] == '/') { + // JSON pointer fragment, relative to the resolved URI + const PointerType relPointer(s, len, allocator_); + if (!relPointer.IsValid()) + SchemaErrorPointer(kSchemaErrorRefPointerInvalid, source, s, len, relPointer); + else { + // Get the subschema + if (const ValueType *pv = relPointer.Get(*base)) { + // Now get the absolute JSON pointer by adding relative to base + PointerType pointer(basePointer, allocator_); + for (SizeType i = 0; i < relPointer.GetTokenCount(); i++) + pointer = pointer.Append(relPointer.GetTokens()[i], allocator_); + if (IsCyclicRef(pointer)) + SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); + else { + // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there + // TODO: cache pointer <-> id mapping + size_t unresolvedTokenIndex; + scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); + CreateSchema(schema, pointer, *pv, document, scopeId); + return true; + } + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } else { + // Plain name fragment, relative to the resolved URI + // Not supported in open api 2.0 and 3.0 + PointerType pointer(allocator_); + if (spec_.oapi == kVersion20 || spec_.oapi == kVersion30) + SchemaErrorValue(kSchemaErrorRefPlainName, source, s, len); + // See if the fragment matches an id in this document. + // Search from the base we just established. Returns the subschema in the document and its absolute JSON pointer. + else if (const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_), true, basePointer)) { + if (IsCyclicRef(pointer)) + SchemaErrorValue(kSchemaErrorRefCyclical, source, ref.GetString(), ref.GetStringLength()); + else { + // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there + // TODO: cache pointer <-> id mapping + size_t unresolvedTokenIndex; + scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_); + CreateSchema(schema, pointer, *pv, document, scopeId); + return true; + } + } else + SchemaErrorValue(kSchemaErrorRefUnknown, source, ref.GetString(), ref.GetStringLength()); + } + } + } + } + + // Invalid/Unknown $ref + if (schema) + *schema = typeless_; + AddSchemaRefs(typeless_); + return true; + } + + //! Find the first subschema with a resolved 'id' that matches the specified URI. + // If full specified use all URI else ignore fragment. + // If found, return a pointer to the subschema and its JSON pointer. + // TODO cache pointer <-> id mapping + ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const { + SizeType i = 0; + ValueType* resval = 0; + UriType tempuri = UriType(finduri, allocator_); + UriType localuri = UriType(baseuri, allocator_); + if (doc.GetType() == kObjectType) { + // Establish the base URI of this object + typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString()); + if (m != doc.MemberEnd() && m->value.GetType() == kStringType) { + localuri = UriType(m->value, allocator_).Resolve(baseuri, allocator_); + } + // See if it matches + if (localuri.Match(finduri, full)) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::FindId (match)", full ? localuri.GetString() : localuri.GetBaseString()); + resval = const_cast(&doc); + resptr = here; + return resval; + } + // No match, continue looking + for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) { + if (m->value.GetType() == kObjectType || m->value.GetType() == kArrayType) { + resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_)); + } + if (resval) break; + } + } else if (doc.GetType() == kArrayType) { + // Continue looking + for (typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) { + if (v->GetType() == kObjectType || v->GetType() == kArrayType) { + resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_)); + } + if (resval) break; + i++; + } + } + return resval; + } + + // Added by PR #1393 + void AddSchemaRefs(SchemaType* schema) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaDocument::AddSchemaRefs"); + while (!schemaRef_.Empty()) { + SchemaRefPtr *ref = schemaRef_.template Pop(1); + SchemaEntry *entry = schemaMap_.template Push(); + new (entry) SchemaEntry(**ref, schema, false, allocator_); + } + } + + // Added by PR #1393 + bool IsCyclicRef(const PointerType& pointer) const { + for (const SchemaRefPtr* ref = schemaRef_.template Bottom(); ref != schemaRef_.template End(); ++ref) + if (pointer == **ref) + return true; + return false; + } + + const SchemaType* GetSchema(const PointerType& pointer) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (pointer == target->pointer) + return target->schema; + return 0; + } + + PointerType GetPointer(const SchemaType* schema) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (schema == target->schema) + return target->pointer; + return PointerType(); + } + + const SchemaType* GetTypeless() const { return typeless_; } + + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; + + IRemoteSchemaDocumentProviderType* remoteProvider_; + Allocator *allocator_; + Allocator *ownAllocator_; + const SchemaType* root_; //!< Root schema. + SchemaType* typeless_; + internal::Stack schemaMap_; // Stores created Pointer -> Schemas + internal::Stack schemaRef_; // Stores Pointer(s) from $ref(s) until resolved + GValue uri_; // Schema document URI + UriType docId_; + Specification spec_; + GValue error_; + GValue currentError_; +}; + +//! GenericSchemaDocument using Value type. +typedef GenericSchemaDocument SchemaDocument; +//! IGenericRemoteSchemaDocumentProvider using SchemaDocument. +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaValidator + +//! JSON Schema Validator. +/*! + A SAX style JSON schema validator. + It uses a \c GenericSchemaDocument to validate SAX events. + It delegates the incoming SAX events to an output handler. + The default output handler does nothing. + It can be reused multiple times by calling \c Reset(). + + \tparam SchemaDocumentType Type of schema document. + \tparam OutputHandler Type of output handler. Default handler does nothing. + \tparam StateAllocator Allocator for storing the internal validation states. +*/ +template < + typename SchemaDocumentType, + typename OutputHandler = BaseReaderHandler, + typename StateAllocator = CrtAllocator> +class GenericSchemaValidator : + public internal::ISchemaStateFactory, + public internal::ISchemaValidator, + public internal::IValidationErrorHandler { +public: + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; + typedef typename SchemaType::SValue SValue; + typedef typename EncodingType::Ch Ch; + typedef GenericStringRef StringRefType; + typedef GenericValue ValueType; + + //! Constructor without output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags), + depth_(0) + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator"); + } + + //! Constructor with output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + OutputHandler& outputHandler, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(&outputHandler), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags), + depth_(0) + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (output handler)"); + } + + //! Destructor. + ~GenericSchemaValidator() { + Reset(); + RAPIDJSON_DELETE(ownStateAllocator_); + } + + //! Reset the internal states. + void Reset() { + while (!schemaStack_.Empty()) + PopSchema(); + documentStack_.Clear(); + ResetError(); + } + + //! Reset the error state. + void ResetError() { + error_.SetObject(); + currentError_.SetNull(); + missingDependents_.SetNull(); + valid_ = true; + } + + //! Implementation of ISchemaValidator + void SetValidateFlags(unsigned flags) { + flags_ = flags; + } + virtual unsigned GetValidateFlags() const { + return flags_; + } + + virtual bool IsValid() const { + if (!valid_) return false; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false; + return true; + } + //! End of Implementation of ISchemaValidator + + //! Gets the error object. + ValueType& GetError() { return error_; } + const ValueType& GetError() const { return error_; } + + //! Gets the JSON pointer pointed to the invalid schema. + // If reporting all errors, the stack will be empty. + PointerType GetInvalidSchemaPointer() const { + return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer(); + } + + //! Gets the keyword of invalid schema. + // If reporting all errors, the stack will be empty, so return "errors". + const Ch* GetInvalidSchemaKeyword() const { + if (!schemaStack_.Empty()) return CurrentContext().invalidKeyword; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return (const Ch*)GetErrorsString(); + return 0; + } + + //! Gets the error code of invalid schema. + // If reporting all errors, the stack will be empty, so return kValidateErrors. + ValidateErrorCode GetInvalidSchemaCode() const { + if (!schemaStack_.Empty()) return CurrentContext().invalidCode; + if (GetContinueOnErrors() && !error_.ObjectEmpty()) return kValidateErrors; + return kValidateErrorNone; + } + + //! Gets the JSON pointer pointed to the invalid value. + // If reporting all errors, the stack will be empty. + PointerType GetInvalidDocumentPointer() const { + if (documentStack_.Empty()) { + return PointerType(); + } + else { + return PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); + } + } + + void NotMultipleOf(int64_t actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void NotMultipleOf(uint64_t actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void NotMultipleOf(double actual, const SValue& expected) { + AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected); + } + void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void AboveMaximum(double actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMaximumString : 0); + } + void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + void BelowMinimum(double actual, const SValue& expected, bool exclusive) { + AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected, + exclusive ? &SchemaType::GetExclusiveMinimumString : 0); + } + + void TooLong(const Ch* str, SizeType length, SizeType expected) { + AddNumberError(kValidateErrorMaxLength, + ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); + } + void TooShort(const Ch* str, SizeType length, SizeType expected) { + AddNumberError(kValidateErrorMinLength, + ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move()); + } + void DoesNotMatch(const Ch* str, SizeType length) { + currentError_.SetObject(); + currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorPattern); + } + + void DisallowedItem(SizeType index) { + currentError_.SetObject(); + currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorAdditionalItems, true); + } + void TooFewItems(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMinItems, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void TooManyItems(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMaxItems, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void DuplicateItems(SizeType index1, SizeType index2) { + ValueType duplicates(kArrayType); + duplicates.PushBack(index1, GetStateAllocator()); + duplicates.PushBack(index2, GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator()); + AddCurrentError(kValidateErrorUniqueItems, true); + } + + void TooManyProperties(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMaxProperties, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void TooFewProperties(SizeType actualCount, SizeType expectedCount) { + AddNumberError(kValidateErrorMinProperties, + ValueType(actualCount).Move(), SValue(expectedCount).Move()); + } + void StartMissingProperties() { + currentError_.SetArray(); + } + void AddMissingProperty(const SValue& name) { + currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator()); + } + bool EndMissingProperties() { + if (currentError_.Empty()) + return false; + ValueType error(kObjectType); + error.AddMember(GetMissingString(), currentError_, GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorRequired); + return true; + } + void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) { + for (SizeType i = 0; i < count; ++i) + MergeError(static_cast(subvalidators[i])->GetError()); + } + void DisallowedProperty(const Ch* name, SizeType length) { + currentError_.SetObject(); + currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator()); + AddCurrentError(kValidateErrorAdditionalProperties, true); + } + + void StartDependencyErrors() { + currentError_.SetObject(); + } + void StartMissingDependentProperties() { + missingDependents_.SetArray(); + } + void AddMissingDependentProperty(const SValue& targetName) { + missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator()); + } + void EndMissingDependentProperties(const SValue& sourceName) { + if (!missingDependents_.Empty()) { + // Create equivalent 'required' error + ValueType error(kObjectType); + ValidateErrorCode code = kValidateErrorRequired; + error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator()); + AddErrorCode(error, code); + AddErrorInstanceLocation(error, false); + // When appending to a pointer ensure its allocator is used + PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator()); + AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator())); + ValueType wrapper(kObjectType); + wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator()); + currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator()); + } + } + void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) { + currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), + static_cast(subvalidator)->GetError(), GetStateAllocator()); + } + bool EndDependencyErrors() { + if (currentError_.ObjectEmpty()) + return false; + ValueType error(kObjectType); + error.AddMember(GetErrorsString(), currentError_, GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorDependencies); + return true; + } + + void DisallowedValue(const ValidateErrorCode code = kValidateErrorEnum) { + currentError_.SetObject(); + AddCurrentError(code); + } + void StartDisallowedType() { + currentError_.SetArray(); + } + void AddExpectedType(const typename SchemaType::ValueType& expectedType) { + currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator()); + } + void EndDisallowedType(const typename SchemaType::ValueType& actualType) { + ValueType error(kObjectType); + error.AddMember(GetExpectedString(), currentError_, GetStateAllocator()); + error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator()); + currentError_ = error; + AddCurrentError(kValidateErrorType); + } + void NotAllOf(ISchemaValidator** subvalidators, SizeType count) { + // Treat allOf like oneOf and anyOf to match https://rapidjson.org/md_doc_schema.html#allOf-anyOf-oneOf + AddErrorArray(kValidateErrorAllOf, subvalidators, count); + //for (SizeType i = 0; i < count; ++i) { + // MergeError(static_cast(subvalidators[i])->GetError()); + //} + } + void NoneOf(ISchemaValidator** subvalidators, SizeType count) { + AddErrorArray(kValidateErrorAnyOf, subvalidators, count); + } + void NotOneOf(ISchemaValidator** subvalidators, SizeType count) { + AddErrorArray(kValidateErrorOneOf, subvalidators, count); + } + void MultipleOneOf(SizeType index1, SizeType index2) { + ValueType matches(kArrayType); + matches.PushBack(index1, GetStateAllocator()); + matches.PushBack(index2, GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetMatchesString(), matches, GetStateAllocator()); + AddCurrentError(kValidateErrorOneOfMatch); + } + void Disallowed() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorNot); + } + void DisallowedWhenWriting() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorReadOnly); + } + void DisallowedWhenReading() { + currentError_.SetObject(); + AddCurrentError(kValidateErrorWriteOnly); + } + +#define RAPIDJSON_STRING_(name, ...) \ + static const StringRefType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const StringRefType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1)); \ + return v;\ + } + + RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f') + RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f') + RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd') + RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l') + RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd') + RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g') + RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's') + RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e') + RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e') + RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's') + RAPIDJSON_STRING_(Matches, 'm', 'a', 't', 'c', 'h', 'e', 's') + +#undef RAPIDJSON_STRING_ + +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ + if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ + *documentStack_.template Push() = '\0';\ + documentStack_.template Pop(1);\ + RAPIDJSON_SCHEMA_PRINT(InvalidDocument, documentStack_.template Bottom());\ + valid_ = false;\ + return valid_;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ + for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ + if (context->hasher)\ + static_cast(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast(context->patternPropertiesValidators[i_])->method arg2;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ + valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\ + return valid_; + +#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ + RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) + + bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); } + bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } + bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } + bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } + bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } + bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } + bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + bool String(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + + bool StartObject() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartObject"); + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + valid_ = !outputHandler_ || outputHandler_->StartObject(); + return valid_; + } + + bool Key(const Ch* str, SizeType len, bool copy) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::Key", str); + if (!valid_) return false; + AppendToken(str, len); + if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); + valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); + return valid_; + } + + bool EndObject(SizeType memberCount) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndObject"); + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); + if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::StartArray"); + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + valid_ = !outputHandler_ || outputHandler_->StartArray(); + return valid_; + } + + bool EndArray(SizeType elementCount) { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndArray"); + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); + if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) { + valid_ = false; + return valid_; + } + RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); + } + +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ +#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ +#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ + + // Implementation of ISchemaStateFactory + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) { + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom(), documentStack_.GetSize(), + depth_ + 1, + &GetStateAllocator()); + sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag); + return sv; + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { + GenericSchemaValidator* v = static_cast(validator); + v->~GenericSchemaValidator(); + StateAllocator::Free(v); + } + + virtual void* CreateHasher() { + return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); + } + + virtual uint64_t GetHashCode(void* hasher) { + return static_cast(hasher)->GetHashCode(); + } + + virtual void DestroryHasher(void* hasher) { + HasherType* h = static_cast(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } + + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void FreeState(void* p) { + StateAllocator::Free(p); + } + // End of implementation of ISchemaStateFactory + +private: + typedef typename SchemaType::Context Context; + typedef GenericValue, StateAllocator> HashCodeArray; + typedef internal::Hasher HasherType; + + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, + const char* basePath, size_t basePathSize, + unsigned depth, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(root), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + error_(kObjectType), + currentError_(), + missingDependents_(), + valid_(true), + flags_(kValidateDefaultFlags), + depth_(depth) + { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::GenericSchemaValidator (internal)", basePath && basePathSize ? basePath : ""); + if (basePath && basePathSize) + memcpy(documentStack_.template Push(basePathSize), basePath, basePathSize); + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)(); + return *stateAllocator_; + } + + bool GetContinueOnErrors() const { + return flags_ & kValidateContinueOnErrorFlag; + } + + bool BeginValue() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::BeginValue"); + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + + if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + + SizeType count = CurrentContext().patternPropertiesSchemaCount; + const SchemaType** sa = CurrentContext().patternPropertiesSchemas; + typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; + bool valueUniqueness = CurrentContext().valueUniqueness; + RAPIDJSON_ASSERT(CurrentContext().valueSchema); + PushSchema(*CurrentContext().valueSchema); + + if (count > 0) { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; + SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); + std::memset(va, 0, sizeof(ISchemaValidator*) * count); + for (SizeType i = 0; i < count; i++) + va[validatorCount++] = CreateSchemaValidator(*sa[i], true); // Inherit continueOnError + } + + CurrentContext().arrayUniqueness = valueUniqueness; + } + return true; + } + + bool EndValue() { + RAPIDJSON_SCHEMA_PRINT(Method, "GenericSchemaValidator::EndValue"); + if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors()) + return false; + + GenericStringBuffer sb; + schemaDocument_->GetPointer(&CurrentSchema()).StringifyUriFragment(sb); + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + RAPIDJSON_SCHEMA_PRINT(ValidatorPointers, sb.GetString(), documentStack_.template Bottom(), depth_); + void* hasher = CurrentContext().hasher; + uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast(hasher)->GetHashCode() : 0; + + PopSchema(); + + if (!schemaStack_.Empty()) { + Context& context = CurrentContext(); + // Only check uniqueness if there is a hasher + if (hasher && context.valueUniqueness) { + HashCodeArray* a = static_cast(context.arrayElementHashCodes); + if (!a) + CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); + for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) + if (itr->GetUint64() == h) { + DuplicateItems(static_cast(itr - a->Begin()), a->Size()); + // Cleanup before returning if continuing + if (GetContinueOnErrors()) { + a->PushBack(h, GetStateAllocator()); + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/'); + } + RAPIDJSON_INVALID_KEYWORD_RETURN(kValidateErrorUniqueItems); + } + a->PushBack(h, GetStateAllocator()); + } + } + + // Remove the last token of document pointer + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/') + ; + + return true; + } + + void AppendToken(const Ch* str, SizeType len) { + documentStack_.template Reserve(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe() = '/'; + for (SizeType i = 0; i < len; i++) { + if (str[i] == '~') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '0'; + } + else if (str[i] == '/') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '1'; + } + else + *documentStack_.template PushUnsafe() = str[i]; + } + } + + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, *this, &schema, flags_); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop(1); + if (HashCodeArray* a = static_cast(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } + + void AddErrorInstanceLocation(ValueType& result, bool parent) { + GenericStringBuffer sb; + PointerType instancePointer = GetInvalidDocumentPointer(); + ((parent && instancePointer.GetTokenCount() > 0) + ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1) + : instancePointer).StringifyUriFragment(sb); + ValueType instanceRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), + GetStateAllocator()); + result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator()); + } + + void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) { + GenericStringBuffer sb; + SizeType len = CurrentSchema().GetURI().GetStringLength(); + if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch)); + if (schema.GetTokenCount()) schema.StringifyUriFragment(sb); + else GetInvalidSchemaPointer().StringifyUriFragment(sb); + ValueType schemaRef(sb.GetString(), static_cast(sb.GetSize() / sizeof(Ch)), + GetStateAllocator()); + result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator()); + } + + void AddErrorCode(ValueType& result, const ValidateErrorCode code) { + result.AddMember(GetErrorCodeString(), code, GetStateAllocator()); + } + + void AddError(ValueType& keyword, ValueType& error) { + typename ValueType::MemberIterator member = error_.FindMember(keyword); + if (member == error_.MemberEnd()) + error_.AddMember(keyword, error, GetStateAllocator()); + else { + if (member->value.IsObject()) { + ValueType errors(kArrayType); + errors.PushBack(member->value, GetStateAllocator()); + member->value = errors; + } + member->value.PushBack(error, GetStateAllocator()); + } + } + + void AddCurrentError(const ValidateErrorCode code, bool parent = false) { + AddErrorCode(currentError_, code); + AddErrorInstanceLocation(currentError_, parent); + AddErrorSchemaLocation(currentError_); + AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(), false).Move(), currentError_); + } + + void MergeError(ValueType& other) { + for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) { + AddError(it->name, it->value); + } + } + + void AddNumberError(const ValidateErrorCode code, ValueType& actual, const SValue& expected, + const typename SchemaType::ValueType& (*exclusive)() = 0) { + currentError_.SetObject(); + currentError_.AddMember(GetActualString(), actual, GetStateAllocator()); + currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator()); + if (exclusive) + currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator()); + AddCurrentError(code); + } + + void AddErrorArray(const ValidateErrorCode code, + ISchemaValidator** subvalidators, SizeType count) { + ValueType errors(kArrayType); + for (SizeType i = 0; i < count; ++i) + errors.PushBack(static_cast(subvalidators[i])->GetError(), GetStateAllocator()); + currentError_.SetObject(); + currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator()); + AddCurrentError(code); + } + + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top(); } + const Context& CurrentContext() const { return *schemaStack_.template Top(); } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType& root_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) + OutputHandler* outputHandler_; + ValueType error_; + ValueType currentError_; + ValueType missingDependents_; + bool valid_; + unsigned flags_; + unsigned depth_; +}; + +typedef GenericSchemaValidator SchemaValidator; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidatingReader + +//! A helper class for parsing with validation. +/*! + This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate(). + + \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam SourceEncoding Encoding of the input stream. + \tparam SchemaDocumentType Type of schema document. + \tparam StackAllocator Allocator type for stack. +*/ +template < + unsigned parseFlags, + typename InputStream, + typename SourceEncoding, + typename SchemaDocumentType = SchemaDocument, + typename StackAllocator = CrtAllocator> +class SchemaValidatingReader { +public: + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; + typedef GenericValue ValueType; + + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ + SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), invalidSchemaCode_(kValidateErrorNone), error_(kObjectType), isValid_(true) {} + + template + bool operator()(Handler& handler) { + GenericReader reader; + GenericSchemaValidator validator(sd_, handler); + parseResult_ = reader.template Parse(is_, validator); + + isValid_ = validator.IsValid(); + if (isValid_) { + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); + error_.SetObject(); + } + else { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); + invalidSchemaCode_ = validator.GetInvalidSchemaCode(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); + error_.CopyFrom(validator.GetError(), allocator_); + } + + return parseResult_; + } + + const ParseResult& GetParseResult() const { return parseResult_; } + bool IsValid() const { return isValid_; } + const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } + const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } + const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } + const ValueType& GetError() const { return error_; } + ValidateErrorCode GetInvalidSchemaCode() const { return invalidSchemaCode_; } + +private: + InputStream& is_; + const SchemaDocumentType& sd_; + + ParseResult parseResult_; + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; + ValidateErrorCode invalidSchemaCode_; + StackAllocator allocator_; + ValueType error_; + bool isValid_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_SCHEMA_H_ diff --git a/deps/rapidjson/include/rapidjson/stream.h b/deps/rapidjson/include/rapidjson/stream.h new file mode 100644 index 0000000..1fd7091 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/stream.h @@ -0,0 +1,223 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "rapidjson.h" + +#ifndef RAPIDJSON_STREAM_H_ +#define RAPIDJSON_STREAM_H_ + +#include "encodings.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; +}; + +//! Reserve n characters for writing to a stream. +template +inline void PutReserve(Stream& stream, size_t count) { + (void)stream; + (void)count; +} + +//! Write character to a stream, presuming buffer is reserved. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { + stream.Put(c); +} + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + PutReserve(stream, n); + for (size_t i = 0; i < n; i++) + PutUnsafe(stream, c); +} + +/////////////////////////////////////////////////////////////////////////////// +// GenericStreamWrapper + +//! A Stream Wrapper +/*! \tThis string stream is a wrapper for any stream by just forwarding any + \treceived message to the origin stream. + \note implements Stream concept +*/ + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4702) // unreachable code +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +template > +class GenericStreamWrapper { +public: + typedef typename Encoding::Ch Ch; + GenericStreamWrapper(InputStream& is): is_(is) {} + + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() { return is_.Tell(); } + Ch* PutBegin() { return is_.PutBegin(); } + void Put(Ch ch) { is_.Put(ch); } + void Flush() { is_.Flush(); } + size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); } + + // wrapper for MemoryStream + const Ch* Peek4() const { return is_.Peek4(); } + + // wrapper for AutoUTFInputStream + UTFType GetType() const { return is_.GetType(); } + bool HasBOM() const { return is_.HasBOM(); } + +protected: + InputStream& is_; +}; + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +RAPIDJSON_DIAG_POP +#endif + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream > InsituStringStream; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STREAM_H_ diff --git a/deps/rapidjson/include/rapidjson/stringbuffer.h b/deps/rapidjson/include/rapidjson/stringbuffer.h new file mode 100644 index 0000000..82ad3ca --- /dev/null +++ b/deps/rapidjson/include/rapidjson/stringbuffer.h @@ -0,0 +1,121 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_STRINGBUFFER_H_ +#define RAPIDJSON_STRINGBUFFER_H_ + +#include "stream.h" +#include "internal/stack.h" + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +#include // std::move +#endif + +#include "internal/stack.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Represents an in-memory output stream. +/*! + \tparam Encoding Encoding of the stream. + \tparam Allocator type for allocating memory buffer. + \note implements Stream concept +*/ +template +class GenericStringBuffer { +public: + typedef typename Encoding::Ch Ch; + + GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {} + GenericStringBuffer& operator=(GenericStringBuffer&& rhs) { + if (&rhs != this) + stack_ = std::move(rhs.stack_); + return *this; + } +#endif + + void Put(Ch c) { *stack_.template Push() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } + void Flush() {} + + void Clear() { stack_.Clear(); } + void ShrinkToFit() { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.ShrinkToFit(); + stack_.template Pop(1); + } + + void Reserve(size_t count) { stack_.template Reserve(count); } + Ch* Push(size_t count) { return stack_.template Push(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } + void Pop(size_t count) { stack_.template Pop(count); } + + const Ch* GetString() const { + // Push and pop a null terminator. This is safe. + *stack_.template Push() = '\0'; + stack_.template Pop(1); + + return stack_.template Bottom(); + } + + //! Get the size of string in bytes in the string buffer. + size_t GetSize() const { return stack_.GetSize(); } + + //! Get the length of string in Ch in the string buffer. + size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } + + static const size_t kDefaultCapacity = 256; + mutable internal::Stack stack_; + +private: + // Prohibit copy constructor & assignment operator. + GenericStringBuffer(const GenericStringBuffer&); + GenericStringBuffer& operator=(const GenericStringBuffer&); +}; + +//! String buffer with UTF8 encoding +typedef GenericStringBuffer > StringBuffer; + +template +inline void PutReserve(GenericStringBuffer& stream, size_t count) { + stream.Reserve(count); +} + +template +inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + +//! Implement specialized version of PutN() with memset() for better performance. +template<> +inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { + std::memset(stream.stack_.Push(n), c, n * sizeof(c)); +} + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/deps/rapidjson/include/rapidjson/uri.h b/deps/rapidjson/include/rapidjson/uri.h new file mode 100644 index 0000000..f93e508 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/uri.h @@ -0,0 +1,481 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// (C) Copyright IBM Corporation 2021 +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_URI_H_ +#define RAPIDJSON_URI_H_ + +#include "internal/strfunc.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// GenericUri + +template +class GenericUri { +public: + typedef typename ValueType::Ch Ch; +#if RAPIDJSON_HAS_STDSTRING + typedef std::basic_string String; +#endif + + //! Constructors + GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + } + + GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, len); + } + + GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri, internal::StrLen(uri)); + } + + // Use with specializations of GenericValue + template GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + const Ch* u = uri.template Get(); // TypeHelper from document.h + Parse(u, internal::StrLen(u)); + } + +#if RAPIDJSON_HAS_STDSTRING + GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + Parse(uri.c_str(), internal::StrLen(uri.c_str())); + } +#endif + + //! Copy constructor + GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() { + *this = rhs; + } + + //! Copy constructor + GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() { + *this = rhs; + } + + //! Destructor. + ~GenericUri() { + Free(); + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Assignment operator + GenericUri& operator=(const GenericUri& rhs) { + if (this != &rhs) { + // Do not delete ownAllocator + Free(); + Allocate(rhs.GetStringLength()); + auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength()); + path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength()); + query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength()); + frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength()); + base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength()); + uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength()); + CopyPart(uri_, rhs.uri_, rhs.GetStringLength()); + } + return *this; + } + + //! Getters + // Use with specializations of GenericValue + template void Get(T& uri, Allocator& allocator) { + uri.template Set(this->GetString(), allocator); // TypeHelper from document.h + } + + const Ch* GetString() const { return uri_; } + SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen(uri_); } + const Ch* GetBaseString() const { return base_; } + SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen(base_); } + const Ch* GetSchemeString() const { return scheme_; } + SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen(scheme_); } + const Ch* GetAuthString() const { return auth_; } + SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen(auth_); } + const Ch* GetPathString() const { return path_; } + SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen(path_); } + const Ch* GetQueryString() const { return query_; } + SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen(query_); } + const Ch* GetFragString() const { return frag_; } + SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen(frag_); } + +#if RAPIDJSON_HAS_STDSTRING + static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); } + static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); } + static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); } + static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); } + static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); } + static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); } + static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); } +#endif + + //! Equality operators + bool operator==(const GenericUri& rhs) const { + return Match(rhs, true); + } + + bool operator!=(const GenericUri& rhs) const { + return !Match(rhs, true); + } + + bool Match(const GenericUri& uri, bool full = true) const { + Ch* s1; + Ch* s2; + if (full) { + s1 = uri_; + s2 = uri.uri_; + } else { + s1 = base_; + s2 = uri.base_; + } + if (s1 == s2) return true; + if (s1 == 0 || s2 == 0) return false; + return internal::StrCmp(s1, s2) == 0; + } + + //! Resolve this URI against another (base) URI in accordance with URI resolution rules. + // See https://tools.ietf.org/html/rfc3986 + // Use for resolving an id or $ref with an in-scope id. + // Returns a new GenericUri for the resolved URI. + GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) { + GenericUri resuri; + resuri.allocator_ = allocator; + // Ensure enough space for combining paths + resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash + + if (!(GetSchemeStringLength() == 0)) { + // Use all of this URI + resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength()); + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base scheme + resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength()); + if (!(GetAuthStringLength() == 0)) { + // Use this auth, path, query + resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength()); + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + resuri.RemoveDotSegments(); + } else { + // Use the base auth + resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength()); + if (GetPathStringLength() == 0) { + // Use the base path + resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength()); + if (GetQueryStringLength() == 0) { + // Use the base query + resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength()); + } else { + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } else { + if (path_[0] == '/') { + // Absolute path - use all of this path + resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } else { + // Relative path - append this path to base path after base path's last slash + size_t pos = 0; + if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) { + resuri.path_[pos] = '/'; + pos++; + } + size_t lastslashpos = baseuri.GetPathStringLength(); + while (lastslashpos > 0) { + if (baseuri.path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch)); + pos += lastslashpos; + resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength()); + resuri.RemoveDotSegments(); + } + // Use this query + resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength()); + } + } + } + // Always use this frag + resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength()); + + // Re-constitute base_ and uri_ + resuri.SetBase(); + resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1; + resuri.SetUri(); + return resuri; + } + + //! Get the allocator of this GenericUri. + Allocator& GetAllocator() { return *allocator_; } + +private: + // Allocate memory for a URI + // Returns total amount allocated + std::size_t Allocate(std::size_t len) { + // Create own allocator if user did not supply. + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + // Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated. + // Order: scheme, auth, path, query, frag, base, uri + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + size_t total = (3 * len + 7) * sizeof(Ch); + scheme_ = static_cast(allocator_->Malloc(total)); + *scheme_ = '\0'; + auth_ = scheme_; + auth_++; + *auth_ = '\0'; + path_ = auth_; + path_++; + *path_ = '\0'; + query_ = path_; + query_++; + *query_ = '\0'; + frag_ = query_; + frag_++; + *frag_ = '\0'; + base_ = frag_; + base_++; + *base_ = '\0'; + uri_ = base_; + uri_++; + *uri_ = '\0'; + return total; + } + + // Free memory for a URI + void Free() { + if (scheme_) { + Allocator::Free(scheme_); + scheme_ = 0; + } + } + + // Parse a URI into constituent scheme, authority, path, query, & fragment parts + // Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per + // https://tools.ietf.org/html/rfc3986 + void Parse(const Ch* uri, std::size_t len) { + std::size_t start = 0, pos1 = 0, pos2 = 0; + Allocate(len); + + // Look for scheme ([^:/?#]+):)? + if (start < len) { + while (pos1 < len) { + if (uri[pos1] == ':') break; + pos1++; + } + if (pos1 != len) { + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (pos1 < pos2) { + pos1++; + std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch)); + scheme_[pos1] = '\0'; + start = pos1; + } + } + } + // Look for auth (//([^/?#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + auth_ = scheme_ + GetSchemeStringLength(); + auth_++; + *auth_ = '\0'; + if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') { + pos2 = start + 2; + while (pos2 < len) { + if (uri[pos2] == '/') break; + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch)); + auth_[pos2 - start] = '\0'; + start = pos2; + } + // Look for path ([^?#]*) + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + path_ = auth_ + GetAuthStringLength(); + path_++; + *path_ = '\0'; + if (start < len) { + pos2 = start; + while (pos2 < len) { + if (uri[pos2] == '?') break; + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch)); + path_[pos2 - start] = '\0'; + if (path_[0] == '/') + RemoveDotSegments(); // absolute path - normalize + start = pos2; + } + } + // Look for query (\?([^#]*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + query_ = path_ + GetPathStringLength(); + query_++; + *query_ = '\0'; + if (start < len && uri[start] == '?') { + pos2 = start + 1; + while (pos2 < len) { + if (uri[pos2] == '#') break; + pos2++; + } + if (start != pos2) { + std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch)); + query_[pos2 - start] = '\0'; + start = pos2; + } + } + // Look for fragment (#(.*))? + // Note need to set, increment, assign in 3 stages to avoid compiler warning bug. + frag_ = query_ + GetQueryStringLength(); + frag_++; + *frag_ = '\0'; + if (start < len && uri[start] == '#') { + std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch)); + frag_[len - start] = '\0'; + } + + // Re-constitute base_ and uri_ + base_ = frag_ + GetFragStringLength() + 1; + SetBase(); + uri_ = base_ + GetBaseStringLength() + 1; + SetUri(); + } + + // Reconstitute base + void SetBase() { + Ch* next = base_; + std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch)); + next+= GetSchemeStringLength(); + std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch)); + next+= GetAuthStringLength(); + std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch)); + next+= GetPathStringLength(); + std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch)); + next+= GetQueryStringLength(); + *next = '\0'; + } + + // Reconstitute uri + void SetUri() { + Ch* next = uri_; + std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch)); + next+= GetBaseStringLength(); + std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch)); + next+= GetFragStringLength(); + *next = '\0'; + } + + // Copy a part from one GenericUri to another + // Return the pointer to the next part to be copied to + Ch* CopyPart(Ch* to, Ch* from, std::size_t len) { + RAPIDJSON_ASSERT(to != 0); + RAPIDJSON_ASSERT(from != 0); + std::memcpy(to, from, len * sizeof(Ch)); + to[len] = '\0'; + Ch* next = to + len + 1; + return next; + } + + // Remove . and .. segments from the path_ member. + // https://tools.ietf.org/html/rfc3986 + // This is done in place as we are only removing segments. + void RemoveDotSegments() { + std::size_t pathlen = GetPathStringLength(); + std::size_t pathpos = 0; // Position in path_ + std::size_t newpos = 0; // Position in new path_ + + // Loop through each segment in original path_ + while (pathpos < pathlen) { + // Get next segment, bounded by '/' or end + size_t slashpos = 0; + while ((pathpos + slashpos) < pathlen) { + if (path_[pathpos + slashpos] == '/') break; + slashpos++; + } + // Check for .. and . segments + if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') { + // Backup a .. segment in the new path_ + // We expect to find a previously added slash at the end or nothing + RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/'); + size_t lastslashpos = newpos; + // Make sure we don't go beyond the start segment + if (lastslashpos > 1) { + // Find the next to last slash and back up to it + lastslashpos--; + while (lastslashpos > 0) { + if (path_[lastslashpos - 1] == '/') break; + lastslashpos--; + } + // Set the new path_ position + newpos = lastslashpos; + } + } else if (slashpos == 1 && path_[pathpos] == '.') { + // Discard . segment, leaves new path_ unchanged + } else { + // Move any other kind of segment to the new path_ + RAPIDJSON_ASSERT(newpos <= pathpos); + std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch)); + newpos += slashpos; + // Add slash if not at end + if ((pathpos + slashpos) < pathlen) { + path_[newpos] = '/'; + newpos++; + } + } + // Move to next segment + pathpos += slashpos + 1; + } + path_[newpos] = '\0'; + } + + Ch* uri_; // Everything + Ch* base_; // Everything except fragment + Ch* scheme_; // Includes the : + Ch* auth_; // Includes the // + Ch* path_; // Absolute if starts with / + Ch* query_; // Includes the ? + Ch* frag_; // Includes the # + + Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. + Allocator* ownAllocator_; //!< Allocator owned by this Uri. +}; + +//! GenericUri for Value (UTF-8, default allocator). +typedef GenericUri Uri; + +RAPIDJSON_NAMESPACE_END + +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_URI_H_ diff --git a/deps/rapidjson/include/rapidjson/writer.h b/deps/rapidjson/include/rapidjson/writer.h new file mode 100644 index 0000000..8b38921 --- /dev/null +++ b/deps/rapidjson/include/rapidjson/writer.h @@ -0,0 +1,710 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_WRITER_H_ +#define RAPIDJSON_WRITER_H_ + +#include "stream.h" +#include "internal/clzll.h" +#include "internal/meta.h" +#include "internal/stack.h" +#include "internal/strfunc.h" +#include "internal/dtoa.h" +#include "internal/itoa.h" +#include "stringbuffer.h" +#include // placement new + +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#elif defined(RAPIDJSON_NEON) +#include +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(c++98-compat) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// WriteFlag + +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kWriteDefaultFlags definition. + + User can define this as any \c WriteFlag combinations. +*/ +#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS +#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags +#endif + +//! Combination of writeFlags +enum WriteFlag { + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +}; + +//! JSON writer +/*! Writer implements the concept Handler. + It generates JSON text by events to an output os. + + User may programmatically calls the functions of a writer to generate JSON text. + + On the other side, a writer can also be passed to objects that generates events, + + for example Reader::Parse() and Document::Accept(). + + \tparam OutputStream Type of output stream. + \tparam SourceEncoding Encoding of source string. + \tparam TargetEncoding Encoding of output stream. + \tparam StackAllocator Type of allocator for allocating memory of stack. + \note implements Handler concept +*/ +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class Writer { +public: + typedef typename SourceEncoding::Ch Ch; + + static const int kDefaultMaxDecimalPlaces = 324; + + //! Constructor + /*! \param os Output stream. + \param stackAllocator User supplied allocator. If it is null, it will create a private one. + \param levelDepth Initial capacity of stack. + */ + explicit + Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + + explicit + Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Writer(Writer&& rhs) : + os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { + rhs.os_ = 0; + } +#endif + + //! Reset the writer with a new stream. + /*! + This function reset the writer with a new stream and default settings, + in order to make a Writer object reusable for output multiple JSONs. + + \param os New output stream. + \code + Writer writer(os1); + writer.StartObject(); + // ... + writer.EndObject(); + + writer.Reset(os2); + writer.StartObject(); + // ... + writer.EndObject(); + \endcode + */ + void Reset(OutputStream& os) { + os_ = &os; + hasRoot_ = false; + level_stack_.Clear(); + } + + //! Checks whether the output is a complete JSON. + /*! + A complete JSON has a complete root object or array. + */ + bool IsComplete() const { + return hasRoot_ && level_stack_.Empty(); + } + + int GetMaxDecimalPlaces() const { + return maxDecimalPlaces_; + } + + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. + + For example, + + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode + + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) { + maxDecimalPlaces_ = maxDecimalPlaces; + } + + /*!@name Implementation of Handler + \see Handler + */ + //@{ + + bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } + bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } + bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } + bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } + + //! Writes the given \c double value to the stream + /*! + \param d The value to be written. + \return Whether it is succeed. + */ + bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } + + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kStringType); + return EndValue(WriteString(str, length)); + } + +#if RAPIDJSON_HAS_STDSTRING + bool String(const std::basic_string& str) { + return String(str.data(), SizeType(str.size())); + } +#endif + + bool StartObject() { + Prefix(kObjectType); + new (level_stack_.template Push()) Level(false); + return WriteStartObject(); + } + + bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) + { + return Key(str.data(), SizeType(str.size())); + } +#endif + + bool EndObject(SizeType memberCount = 0) { + (void)memberCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + level_stack_.template Pop(1); + return EndValue(WriteEndObject()); + } + + bool StartArray() { + Prefix(kArrayType); + new (level_stack_.template Push()) Level(true); + return WriteStartArray(); + } + + bool EndArray(SizeType elementCount = 0) { + (void)elementCount; + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); + RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); + level_stack_.template Pop(1); + return EndValue(WriteEndArray()); + } + //@} + + /*! @name Convenience extensions */ + //@{ + + //! Simpler but slower overload. + bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); } + + //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + Prefix(type); + return EndValue(WriteRawValue(json, length)); + } + + //! Flush the output stream. + /*! + Allows the user to flush the output stream immediately. + */ + void Flush() { + os_->Flush(); + } + + static const size_t kDefaultLevelDepth = 32; + +protected: + //! Information for each nested level + struct Level { + Level(bool inArray_) : valueCount(0), inArray(inArray_) {} + size_t valueCount; //!< number of values in this level + bool inArray; //!< true if in array, otherwise in object + }; + + bool WriteNull() { + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; + } + + bool WriteBool(bool b) { + if (b) { + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); + } + else { + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); + } + return true; + } + + bool WriteInt(int i) { + char buffer[11]; + const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint(unsigned u) { + char buffer[10]; + const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteInt64(int64_t i64) { + char buffer[21]; + const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (const char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char buffer[25]; + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast(end - buffer)); + for (char* p = buffer; p != end; ++p) + PutUnsafe(*os_, static_cast(*p)); + return true; + } + + bool WriteString(const Ch* str, SizeType length) { + static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const char escape[256] = { +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + //0 1 2 3 4 5 6 7 8 9 A B C D E F + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 + 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 + 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 + Z16, Z16, // 30~4F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 + Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF +#undef Z16 + }; + + if (TargetEncoding::supportUnicode) + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + else + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + + PutUnsafe(*os_, '\"'); + GenericStringStream is(str); + while (ScanWriteUnescapedString(is, length)) { + const Ch c = is.Peek(); + if (!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) { + // Unicode escaping + unsigned codepoint; + if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) + return false; + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); + } + else { + RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); + // Surrogate pair + unsigned s = codepoint - 0x010000; + unsigned lead = (s >> 10) + 0xD800; + unsigned trail = (s & 0x3FF) + 0xDC00; + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead ) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail ) & 15]); + } + } + else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast(c)])) { + is.Take(); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast(escape[static_cast(c)])); + if (escape[static_cast(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast(c) & 0xF]); + } + } + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; + } + PutUnsafe(*os_, '\"'); + return true; + } + + bool ScanWriteUnescapedString(GenericStringStream& is, size_t length) { + return RAPIDJSON_LIKELY(is.Tell() < length); + } + + bool WriteStartObject() { os_->Put('{'); return true; } + bool WriteEndObject() { os_->Put('}'); return true; } + bool WriteStartArray() { os_->Put('['); return true; } + bool WriteEndArray() { os_->Put(']'); return true; } + + bool WriteRawValue(const Ch* json, size_t length) { + PutReserve(*os_, length); + GenericStringStream is(json); + while (RAPIDJSON_LIKELY(is.Tell() < length)) { + RAPIDJSON_ASSERT(is.Peek() != '\0'); + if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; + } + return true; + } + + void Prefix(Type type) { + (void)type; + if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root + Level* level = level_stack_.template Top(); + if (level->valueCount > 0) { + if (level->inArray) + os_->Put(','); // add comma if it is not the first element in array + else // in object + os_->Put((level->valueCount % 2 == 0) ? ',' : ':'); + } + if (!level->inArray && level->valueCount % 2 == 0) + RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name + level->valueCount++; + } + else { + RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root. + hasRoot_ = true; + } + } + + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + Flush(); + return ret; + } + + OutputStream* os_; + internal::Stack level_stack_; + int maxDecimalPlaces_; + bool hasRoot_; + +private: + // Prohibit copy constructor & assignment operator. + Writer(const Writer&); + Writer& operator=(const Writer&); +}; + +// Full specialization for StringStream to prevent memory copying + +template<> +inline bool Writer::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(static_cast(11 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(static_cast(10 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(static_cast(21 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(static_cast(20 - (end - buffer))); + return true; +} + +template<> +inline bool Writer::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + + char *buffer = os_->Push(25); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast(25 - (end - buffer))); + return true; +} + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType len; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; +#else + len = static_cast(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#elif defined(RAPIDJSON_NEON) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (; p != endAligned; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract + uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract + + SizeType len = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + uint32_t lz = internal::clzll(high); + len = 8 + (lz >> 3); + escaped = true; + } + } else { + uint32_t lz = internal::clzll(low); + len = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + vst1q_u8(reinterpret_cast(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#endif // RAPIDJSON_NEON + +RAPIDJSON_NAMESPACE_END + +#if defined(_MSC_VER) || defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/deps/rapidjson/include_dirs.js b/deps/rapidjson/include_dirs.js new file mode 100644 index 0000000..b373e85 --- /dev/null +++ b/deps/rapidjson/include_dirs.js @@ -0,0 +1,2 @@ +var path = require('path'); +console.log(path.join(path.relative('.', __dirname), 'include')); diff --git a/deps/rapidjson/library.json b/deps/rapidjson/library.json new file mode 100644 index 0000000000000000000000000000000000000000..2210fcd61735c8cca63c19534e8df591eda60d58 GIT binary patch literal 355 zcmX|7Jx{|h5Z&`DP99q;rfaqc7AipzWngukYhy@k>wKY!s{VKEB(PYgdwyScD*%Mk zJ&Fp%yAHP59}llW=JgL!wBBW8SMJJ(W&4fO)l(Dm`YU=TA?i^=<9i7~Q$&(*L5HN- z(?V%58nS^`u^P@gGGwEbq5cVQ_5_dHEnF?PaPsLn)}QL>@B)#i4xxT~UPN&Wo;anr zrK~Bfb*3AdxyRp_fcxA8N8N`G=gjM@HfmFv5Ee1Q;G<1}Cs8HVD#=rr^)8m@Z^>n# hE*Ec^L#&iaNIRTL<9qdi&Y)vO`H1;2BHI`D;um*AY6JiP literal 0 HcmV?d00001 diff --git a/deps/rapidjson/license.txt b/deps/rapidjson/license.txt new file mode 100644 index 0000000..7ccc161 --- /dev/null +++ b/deps/rapidjson/license.txt @@ -0,0 +1,57 @@ +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* 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. +* Neither the name of copyright holder 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 AND 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. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/deps/rapidjson/package.json b/deps/rapidjson/package.json new file mode 100644 index 0000000000000000000000000000000000000000..129581a633512e5165e985041339c58f990efc24 GIT binary patch literal 561 zcma)4!A`?44889wLXaj9sAUqTT@eS)aAOE%iD^BxNo1#J)3krbNxQP+PIjJO-g~if zTqvcz=|QiRCKJ)^IC%Y-;a?y|Iml#HJyp*m>VPd_Ow;7%^Xtw9TX&%e^(;_D-`tP< z-e8eHZ@a<4w?pD;$CDTm*c1qX#pWok;wy65Gnbr05ZIeOb|vGvohAu5Wpb%PK9%HS z!VAeW4Qw0KM!ymTS}Pw^9w?4r@dv?ev|26|>@lg8p4A9qV3d@H|BUGnOPmJNIpjcH zP9n%dn^NR;T}$5%+scN%{s3>mr;8QktFwn0QX44W9~aZ1u(?>gy}yjuc4#i1G}&Ea cRU`8t8=l?T&_gs$k-tXZmcTgqBa74G50uQOi2wiq literal 0 HcmV?d00001 diff --git a/deps/rapidjson/rapidjson.autopkg b/deps/rapidjson/rapidjson.autopkg new file mode 100644 index 0000000..fe72030 --- /dev/null +++ b/deps/rapidjson/rapidjson.autopkg @@ -0,0 +1,77 @@ +nuget { + //Usage: Write-NuGetPackage rapidjson.autopkg -defines:MYVERSION=1.1.0 + //Be sure you are running Powershell 3.0 and have the CoApp powershell extensions installed properly. + nuspec { + id = rapidjson; + version : ${MYVERSION}; + title: "rapidjson"; + authors: {"https://github.com/Tencent/rapidjson/releases/tag/v1.1.0"}; + owners: {"@lsantos (github)"}; + licenseUrl: "https://github.com/Tencent/rapidjson/blob/master/license.txt"; + projectUrl: "https://github.com/Tencent/rapidjson/"; + iconUrl: "https://cdn1.iconfinder.com/data/icons/fatcow/32x32/json.png"; + requireLicenseAcceptance:false; + summary: @"A fast JSON parser/generator for C++ with both SAX/DOM style API"; + + // if you need to span several lines you can prefix a string with an @ symbol (exactly like c# does). + description: @"Rapidjson is an attempt to create the fastest JSON parser and generator. + + - Small but complete. Supports both SAX and DOM style API. SAX parser only a few hundred lines of code. + - Fast. In the order of magnitude of strlen(). Optionally supports SSE2/SSE4.2 for acceleration. + - Self-contained. Minimal dependency on standard libraries. No BOOST, not even STL. + - Compact. Each JSON value is 16 or 20 bytes for 32 or 64-bit machines respectively (excluding text string storage). With the custom memory allocator, parser allocates memory compactly during parsing. + - Full RFC4627 compliance. Supports UTF-8, UTF-16 and UTF-32. + - Support both in-situ parsing (directly decode strings into the source JSON text) and non-destructive parsing (decode strings into new buffers). + - Parse number to int/unsigned/int64_t/uint64_t/double depending on input + - Support custom memory allocation. Also, the default memory pool allocator can also be supplied with a user buffer (such as a buffer allocated on user's heap or - programme stack) to minimize allocation. + + As the name implies, rapidjson is inspired by rapidxml."; + + releaseNotes: @" +Added + Add Value::XXXMember(...) overloads for std::string (#335) + +Fixed + Include rapidjson.h for all internal/error headers. + Parsing some numbers incorrectly in full-precision mode (kFullPrecisionParseFlag) (#342) + Fix alignment of 64bit platforms (#328) + Fix MemoryPoolAllocator::Clear() to clear user-buffer (0691502) + +Changed + CMakeLists for include as a thirdparty in projects (#334, #337) + Change Document::ParseStream() to use stack allocator for Reader (ffbe386)"; + + copyright: "Copyright 2015"; + tags: { native, coapp, JSON, nativepackage }; + language: en-US; + }; + + dependencies { + packages : { + //TODO: Add dependencies here in [pkg.name]/[version] form per newline + //zlib/[1.2.8], + }; + } + + // the files that go into the content folders + files { + #defines { + SDK_ROOT = .\; + } + + // grab all the files in the include folder + // the folder that contains all the .h files will + // automatically get added to the Includes path. + nestedinclude += { + #destination = ${d_include}rapidjson; + "${SDK_ROOT}include\rapidjson\**\*.h" + }; + }; + + targets { + // We're trying to be standard about these sorts of thing. (Will help with config.h later :D) + //Defines += HAS_EQCORE; + // Fix creating the package with Raggles' fork of CoApp + Includes += "$(MSBuildThisFileDirectory)../..${d_include}"; + }; +} \ No newline at end of file diff --git a/deps/rapidjson/readme.md b/deps/rapidjson/readme.md new file mode 100644 index 0000000..ac683b0 --- /dev/null +++ b/deps/rapidjson/readme.md @@ -0,0 +1,210 @@ +![RapidJSON logo](doc/logo/rapidjson.png) + +![Release version](https://img.shields.io/badge/release-v1.1.0-blue.svg) + +## A fast JSON parser/generator for C++ with both SAX/DOM style API + +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + +* [RapidJSON GitHub](https://github.com/Tencent/rapidjson/) +* RapidJSON Documentation + * [English](http://rapidjson.org/) + * [简体中文](http://rapidjson.org/zh-cn/) + * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. + +## Build status + +| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] | +| :---------------: | :-----------------: | :-------------------: | +| ![lin-badge] | ![win-badge] | ![cov-badge] | + +[lin-badge]: https://travis-ci.org/Tencent/rapidjson.svg?branch=master "Travis build status" +[lin-link]: https://travis-ci.org/Tencent/rapidjson "Travis build status" +[win-badge]: https://ci.appveyor.com/api/projects/status/l6qulgqahcayidrf/branch/master?svg=true "AppVeyor build status" +[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson-0fdqj/branch/master "AppVeyor build status" +[cov-badge]: https://coveralls.io/repos/Tencent/rapidjson/badge.svg?branch=master "Coveralls coverage" +[cov-link]: https://coveralls.io/r/Tencent/rapidjson?branch=master "Coveralls coverage" + +## Introduction + +RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/). + +* RapidJSON is **small** but **complete**. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. + +* RapidJSON is **fast**. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. + +* RapidJSON is **self-contained** and **header-only**. It does not depend on external libraries such as BOOST. It even does not depend on STL. + +* RapidJSON is **memory-friendly**. Each JSON value occupies exactly 16 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. + +* RapidJSON is **Unicode-friendly**. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). + +More features can be read [here](doc/features.md). + +JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in full compliance with RFC7159/ECMA-404, with optional support of relaxed syntax. More information about JSON can be obtained at +* [Introducing JSON](http://json.org/) +* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159) +* [Standard ECMA-404: The JSON Data Interchange Format](https://www.ecma-international.org/publications/standards/Ecma-404.htm) + +## Highlights in v1.1 (2016-8-25) + +* Added [JSON Pointer](doc/pointer.md) +* Added [JSON Schema](doc/schema.md) +* Added [relaxed JSON syntax](doc/dom.md) (comment, trailing comma, NaN/Infinity) +* Iterating array/object with [C++11 Range-based for loop](doc/tutorial.md) +* Reduce memory overhead of each `Value` from 24 bytes to 16 bytes in x86-64 architecture. + +For other changes please refer to [change log](CHANGELOG.md). + +## Compatibility + +RapidJSON is cross-platform. Some platform/compiler combinations which have been tested are shown as follows. +* Visual C++ 2008/2010/2013 on Windows (32/64-bit) +* GNU C++ 3.8.x on Cygwin +* Clang 3.4 on Mac OS X (32/64-bit) and iOS +* Clang 3.4 on Android NDK + +Users can build and run the unit tests on their platform/compiler. + +## Installation + +RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path. + +Alternatively, if you are using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager you can download and install rapidjson with CMake integration in a single command: +* vcpkg install rapidjson + +RapidJSON uses following software as its dependencies: +* [CMake](https://cmake.org/) as a general build tool +* (optional) [Doxygen](http://www.doxygen.org) to build documentation +* (optional) [googletest](https://github.com/google/googletest) for unit and performance testing + +To generate user documentation and run tests please proceed with the steps below: + +1. Execute `git submodule update --init` to get the files of thirdparty submodules (google test). +2. Create directory called `build` in rapidjson source directory. +3. Change to `build` directory and run `cmake ..` command to configure your build. Windows users can do the same with cmake-gui application. +4. On Windows, build the solution found in the build directory. On Linux, run `make` from the build directory. + +On successful build you will find compiled test and example binaries in `bin` +directory. The generated documentation will be available in `doc/html` +directory of the build tree. To run tests after finished build please run `make +test` or `ctest` from your build tree. You can get detailed output using `ctest +-V` command. + +It is possible to install library system-wide by running `make install` command +from the build tree with administrative privileges. This will install all files +according to system preferences. Once RapidJSON is installed, it is possible +to use it from other CMake projects by adding `find_package(RapidJSON)` line to +your CMakeLists.txt. + +## Usage at a glance + +This simple example parses a JSON string into a document (DOM), make a simple modification of the DOM, and finally stringify the DOM to a JSON string. + +~~~~~~~~~~cpp +// rapidjson/example/simpledom/simpledom.cpp` +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; + +int main() { + // 1. Parse a JSON string into DOM. + const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; + Document d; + d.Parse(json); + + // 2. Modify it by DOM. + Value& s = d["stars"]; + s.SetInt(s.GetInt() + 1); + + // 3. Stringify the DOM + StringBuffer buffer; + Writer writer(buffer); + d.Accept(writer); + + // Output {"project":"rapidjson","stars":11} + std::cout << buffer.GetString() << std::endl; + return 0; +} +~~~~~~~~~~ + +Note that this example did not handle potential errors. + +The following diagram shows the process. + +![simpledom](doc/diagram/simpledom.png) + +More [examples](https://github.com/Tencent/rapidjson/tree/master/example) are available: + +* DOM API + * [tutorial](https://github.com/Tencent/rapidjson/blob/master/example/tutorial/tutorial.cpp): Basic usage of DOM API. + +* SAX API + * [simplereader](https://github.com/Tencent/rapidjson/blob/master/example/simplereader/simplereader.cpp): Dumps all SAX events while parsing a JSON by `Reader`. + * [condense](https://github.com/Tencent/rapidjson/blob/master/example/condense/condense.cpp): A command line tool to rewrite a JSON, with all whitespaces removed. + * [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp): A command line tool to rewrite a JSON with indents and newlines by `PrettyWriter`. + * [capitalize](https://github.com/Tencent/rapidjson/blob/master/example/capitalize/capitalize.cpp): A command line tool to capitalize strings in JSON. + * [messagereader](https://github.com/Tencent/rapidjson/blob/master/example/messagereader/messagereader.cpp): Parse a JSON message with SAX API. + * [serialize](https://github.com/Tencent/rapidjson/blob/master/example/serialize/serialize.cpp): Serialize a C++ object into JSON with SAX API. + * [jsonx](https://github.com/Tencent/rapidjson/blob/master/example/jsonx/jsonx.cpp): Implements a `JsonxWriter` which stringify SAX events into [JSONx](https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html) (a kind of XML) format. The example is a command line tool which converts input JSON into JSONx format. + +* Schema + * [schemavalidator](https://github.com/Tencent/rapidjson/blob/master/example/schemavalidator/schemavalidator.cpp) : A command line tool to validate a JSON with a JSON schema. + +* Advanced + * [prettyauto](https://github.com/Tencent/rapidjson/blob/master/example/prettyauto/prettyauto.cpp): A modified version of [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp) to automatically handle JSON with any UTF encodings. + * [parsebyparts](https://github.com/Tencent/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): Implements an `AsyncDocumentParser` which can parse JSON in parts, using C++11 thread. + * [filterkey](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): A command line tool to remove all values with user-specified key. + * [filterkeydom](https://github.com/Tencent/rapidjson/blob/master/example/filterkeydom/filterkeydom.cpp): Same tool as above, but it demonstrates how to use a generator to populate a `Document`. + +## Contributing + +RapidJSON welcomes contributions. When contributing, please follow the code below. + +### Issues + +Feel free to submit issues and enhancement requests. + +Please help us by providing **minimal reproducible examples**, because source code is easier to let other people understand what happens. +For crash problems on certain platforms, please bring stack dump content with the detail of the OS, compiler, etc. + +Please try breakpoint debugging first, tell us what you found, see if we can start exploring based on more information been prepared. + +### Workflow + +In general, we follow the "fork-and-pull" Git workflow. + + 1. **Fork** the repo on GitHub + 2. **Clone** the project to your own machine + 3. **Checkout** a new branch on your fork, start developing on the branch + 4. **Test** the change before commit, Make sure the changes pass all the tests, including `unittest` and `preftest`, please add test case for each new feature or bug-fix if needed. + 5. **Commit** changes to your own branch + 6. **Push** your work back up to your fork + 7. Submit a **Pull request** so that we can review your changes + +NOTE: Be sure to merge the latest from "upstream" before making a pull request! + +### Copyright and Licensing + +You can copy and paste the license summary from below. + +``` +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + +Licensed under the MIT License (the "License"); you may not use this file except +in compliance with the License. You may obtain a copy of the License at + +http://opensource.org/licenses/MIT + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +``` diff --git a/deps/rapidjson/readme.zh-cn.md b/deps/rapidjson/readme.zh-cn.md new file mode 100644 index 0000000..216802e --- /dev/null +++ b/deps/rapidjson/readme.zh-cn.md @@ -0,0 +1,152 @@ +![RapidJSON logo](doc/logo/rapidjson.png) + +![Release version](https://img.shields.io/badge/release-v1.1.0-blue.svg) + +## 高效的 C++ JSON 解æžï¼ç”Ÿæˆå™¨ï¼Œæä¾› SAX åŠ DOM 风格 API + +Tencent is pleased to support the open source community by making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. + +* [RapidJSON GitHub](https://github.com/Tencent/rapidjson/) +* RapidJSON 文档 + * [English](http://rapidjson.org/) + * [简体中文](http://rapidjson.org/zh-cn/) + * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/details/zh-cn) å¯ä¸‹è½½ PDF/EPUB/MOBI,但ä¸å« API å‚考手册。 + +## Build çŠ¶æ€ + +| [Linux][lin-link] | [Windows][win-link] | [Coveralls][cov-link] | +| :---------------: | :-----------------: | :-------------------: | +| ![lin-badge] | ![win-badge] | ![cov-badge] | + +[lin-badge]: https://travis-ci.org/Tencent/rapidjson.svg?branch=master "Travis build status" +[lin-link]: https://travis-ci.org/Tencent/rapidjson "Travis build status" +[win-badge]: https://ci.appveyor.com/api/projects/status/l6qulgqahcayidrf/branch/master?svg=true "AppVeyor build status" +[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson-0fdqj/branch/master "AppVeyor build status" +[cov-badge]: https://coveralls.io/repos/Tencent/rapidjson/badge.svg?branch=master "Coveralls coverage" +[cov-link]: https://coveralls.io/r/Tencent/rapidjson?branch=master "Coveralls coverage" + +## 简介 + +RapidJSON 是一个 C++ çš„ JSON 解æžå™¨åŠç”Ÿæˆå™¨ã€‚它的çµæ„Ÿæ¥è‡ª [RapidXml](http://rapidxml.sourceforge.net/)。 + +* RapidJSON å°è€Œå…¨ã€‚它åŒæ—¶æ”¯æŒ SAX å’Œ DOM 风格的 API。SAX 解æžå™¨åªæœ‰çº¦ 500 行代ç ã€‚ + +* RapidJSON 快。它的性能å¯ä¸Ž `strlen()` 相比。å¯æ”¯æŒ SSE2/SSE4.2 加速。 + +* RapidJSON 独立。它ä¸ä¾èµ–于 BOOST 等外部库。它甚至ä¸ä¾èµ–于 STL。 + +* RapidJSON 对内存å‹å¥½ã€‚在大部分 32/64 ä½æœºå™¨ä¸Šï¼Œæ¯ä¸ª JSON 值åªå  16 字节(除字符串外)。它预设使用一个快速的内存分é…器,令分æžå™¨å¯ä»¥ç´§å‡‘地分é…内存。 + +* RapidJSON 对 Unicode å‹å¥½ã€‚å®ƒæ”¯æŒ UTF-8ã€UTF-16ã€UTF-32 (大端åºï¼å°ç«¯åº),并内部支æŒè¿™äº›ç¼–ç çš„检测ã€æ ¡éªŒåŠè½¬ç ã€‚例如,RapidJSON å¯ä»¥åœ¨åˆ†æžä¸€ä¸ª UTF-8 文件至 DOM 时,把当中的 JSON 字符串转ç è‡³ UTF-16。它也支æŒä»£ç†å¯¹ï¼ˆsurrogate pairï¼‰åŠ `"\u0000"`(空字符)。 + +在 [这里](doc/features.zh-cn.md) å¯è¯»å–更多特点。 + +JSON(JavaScript Object Notation)是一个轻é‡çš„æ•°æ®äº¤æ¢æ ¼å¼ã€‚RapidJSON 应该完全éµä»Ž RFC7159/ECMA-404,并支æŒå¯é€‰çš„放宽语法。 关于 JSON 的更多信æ¯å¯å‚考: +* [Introducing JSON](http://json.org/) +* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159) +* [Standard ECMA-404: The JSON Data Interchange Format](https://www.ecma-international.org/publications/standards/Ecma-404.htm) + +## v1.1 中的亮点 (2016-8-25) + +* 加入 [JSON Pointer](doc/pointer.zh-cn.md) 功能,å¯æ›´ç®€å•åœ°è®¿é—®åŠæ›´æ”¹ DOM。 +* 加入 [JSON Schema](doc/schema.zh-cn.md) 功能,å¯åœ¨è§£æžæˆ–ç”Ÿæˆ JSON 时进行校验。 +* 加入 [放宽的 JSON 语法](doc/dom.zh-cn.md) (注释ã€å°¾éšé€—å·ã€NaN/Infinity) +* 使用 [C++11 范围 for 循环](doc/tutorial.zh-cn.md) 去é历 array å’Œ object。 +* 在 x86-64 架构下,缩å‡æ¯ä¸ª `Value` 的内存开销从 24 字节至 16 字节。 + +其他改动请å‚考 [change log](CHANGELOG.md). + +## 兼容性 + +RapidJSON 是跨平å°çš„。以下是一些曾测试的平å°ï¼ç¼–译器组åˆï¼š +* Visual C++ 2008/2010/2013 在 Windows (32/64-bit) +* GNU C++ 3.8.x 在 Cygwin +* Clang 3.4 在 Mac OS X (32/64-bit) åŠ iOS +* Clang 3.4 在 Android NDK + +用户也å¯ä»¥åœ¨ä»–们的平å°ä¸Šç”ŸæˆåŠæ‰§è¡Œå•å…ƒæµ‹è¯•ã€‚ + +## 安装 + +RapidJSON 是åªæœ‰å¤´æ–‡ä»¶çš„ C++ 库。åªéœ€æŠŠ `include/rapidjson` 目录å¤åˆ¶è‡³ç³»ç»Ÿæˆ–项目的 include 目录中。 + +RapidJSON ä¾èµ–于以下软件: +* [CMake](https://cmake.org/) 作为通用生æˆå·¥å…· +* (optional) [Doxygen](http://www.doxygen.org) 用于生æˆæ–‡æ¡£ +* (optional) [googletest](https://github.com/google/googletest) 用于å•å…ƒåŠæ€§èƒ½æµ‹è¯• + +生æˆæµ‹è¯•åŠä¾‹å­çš„步骤: + +1. 执行 `git submodule update --init` åŽ»èŽ·å– thirdparty submodules (google test)。 +2. 在 rapidjson 目录下,建立一个 `build` 目录。 +3. 在 `build` 目录下执行 `cmake ..` 命令以设置生æˆã€‚Windows 用户å¯ä½¿ç”¨ cmake-gui 应用程åºã€‚ +4. 在 Windows 下,编译生æˆåœ¨ build 目录中的 solution。在 Linux 下,于 build 目录è¿è¡Œ `make`。 + +æˆåŠŸç”ŸæˆåŽï¼Œä½ ä¼šåœ¨ `bin` 的目录下找到编译åŽçš„测试åŠä¾‹å­å¯æ‰§è¡Œæ–‡ä»¶ã€‚而生æˆçš„文档将ä½äºŽ build 下的 `doc/html` 目录。è¦æ‰§è¡Œæµ‹è¯•ï¼Œè¯·åœ¨ build 下执行 `make test` 或 `ctest`。使用 `ctest -V` 命令å¯èŽ·å–详细的输出。 + +我们也å¯ä»¥æŠŠç¨‹åºåº“安装至全系统中,åªè¦åœ¨å…·ç®¡ç†æƒé™ä¸‹ä»Ž build 目录执行 `make install` 命令。这样会按系统的å好设置安装所有文件。当安装 RapidJSON åŽï¼Œå…¶ä»–çš„ CMake 项目需è¦ä½¿ç”¨å®ƒæ—¶ï¼Œå¯ä»¥é€šè¿‡åœ¨ `CMakeLists.txt` åŠ å…¥ä¸€å¥ `find_package(RapidJSON)`。 + +## 用法一览 + +此简å•ä¾‹å­è§£æžä¸€ä¸ª JSON 字符串至一个 document (DOM),对 DOM 作出简å•ä¿®æ”¹ï¼Œæœ€ç»ˆæŠŠ DOM 转æ¢ï¼ˆstringify)至 JSON 字符串。 + +~~~~~~~~~~cpp +// rapidjson/example/simpledom/simpledom.cpp` +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include + +using namespace rapidjson; + +int main() { + // 1. 把 JSON 解æžè‡³ DOM。 + const char* json = "{\"project\":\"rapidjson\",\"stars\":10}"; + Document d; + d.Parse(json); + + // 2. 利用 DOM 作出修改。 + Value& s = d["stars"]; + s.SetInt(s.GetInt() + 1); + + // 3. 把 DOM 转æ¢ï¼ˆstringifyï¼‰æˆ JSON。 + StringBuffer buffer; + Writer writer(buffer); + d.Accept(writer); + + // Output {"project":"rapidjson","stars":11} + std::cout << buffer.GetString() << std::endl; + return 0; +} +~~~~~~~~~~ + +注æ„此例å­å¹¶æ²¡æœ‰å¤„ç†æ½œåœ¨é”™è¯¯ã€‚ + +下图展示执行过程。 + +![simpledom](doc/diagram/simpledom.png) + +还有许多 [例å­](https://github.com/Tencent/rapidjson/tree/master/example) å¯ä¾›å‚考: + +* DOM API + * [tutorial](https://github.com/Tencent/rapidjson/blob/master/example/tutorial/tutorial.cpp): DOM API 的基本使用方法。 + +* SAX API + * [simplereader](https://github.com/Tencent/rapidjson/blob/master/example/simplereader/simplereader.cpp): 使用 `Reader` è§£æž JSON 时,打å°æ‰€æœ‰ SAX 事件。 + * [condense](https://github.com/Tencent/rapidjson/blob/master/example/condense/condense.cpp): 移除 JSON 中所有空白符的命令行工具。 + * [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp): 为 JSON 加入缩进与æ¢è¡Œçš„命令行工具,当中使用了 `PrettyWriter`。 + * [capitalize](https://github.com/Tencent/rapidjson/blob/master/example/capitalize/capitalize.cpp): 把 JSON 中所有字符串改为大写的命令行工具。 + * [messagereader](https://github.com/Tencent/rapidjson/blob/master/example/messagereader/messagereader.cpp): 使用 SAX API 去解æžä¸€ä¸ª JSON 报文。 + * [serialize](https://github.com/Tencent/rapidjson/blob/master/example/serialize/serialize.cpp): 使用 SAX API 去åºåˆ—化 C++ å¯¹è±¡ï¼Œç”Ÿæˆ JSON。 + * [jsonx](https://github.com/Tencent/rapidjson/blob/master/example/jsonx/jsonx.cpp): 实现了一个 `JsonxWriter`,它能把 SAX äº‹ä»¶å†™æˆ [JSONx](https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html)ï¼ˆä¸€ç§ XML)格å¼ã€‚这个例å­æ˜¯æŠŠ JSON 输入转æ¢æˆ JSONx æ ¼å¼çš„命令行工具。 + +* Schema API + * [schemavalidator](https://github.com/Tencent/rapidjson/blob/master/example/schemavalidator/schemavalidator.cpp): 使用 JSON Schema 去校验 JSON 的命令行工具。 + +* 进阶 + * [prettyauto](https://github.com/Tencent/rapidjson/blob/master/example/prettyauto/prettyauto.cpp): [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp) 的修改版本,å¯è‡ªåŠ¨å¤„ç†ä»»ä½• UTF ç¼–ç çš„ JSON。 + * [parsebyparts](https://github.com/Tencent/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): 这例å­ä¸­çš„ `AsyncDocumentParser` 类使用 C++ 线程æ¥é€æ®µè§£æž JSON。 + * [filterkey](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): 移å–使用者指定的键值的命令行工具。 + * [filterkeydom](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): 如上的工具,但展示如何使用生æˆå™¨ï¼ˆgenerator)去填充一个 `Document`。 diff --git a/deps/rapidjson/test/CMakeLists.txt b/deps/rapidjson/test/CMakeLists.txt new file mode 100644 index 0000000..11c1b04 --- /dev/null +++ b/deps/rapidjson/test/CMakeLists.txt @@ -0,0 +1,20 @@ +find_package(GTestSrc) + +IF(GTESTSRC_FOUND) + enable_testing() + + if (WIN32 AND (NOT CYGWIN) AND (NOT MINGW)) + set(gtest_disable_pthreads ON) + set(gtest_force_shared_crt ON) + endif() + + add_subdirectory(${GTEST_SOURCE_DIR} ${CMAKE_BINARY_DIR}/googletest) + include_directories(SYSTEM ${GTEST_INCLUDE_DIR}) + + set(TEST_LIBRARIES gtest gtest_main) + + add_custom_target(tests ALL) + add_subdirectory(perftest) + add_subdirectory(unittest) + +ENDIF(GTESTSRC_FOUND) diff --git a/deps/rapidjson/test/perftest/CMakeLists.txt b/deps/rapidjson/test/perftest/CMakeLists.txt new file mode 100644 index 0000000..035e544 --- /dev/null +++ b/deps/rapidjson/test/perftest/CMakeLists.txt @@ -0,0 +1,28 @@ +set(PERFTEST_SOURCES + misctest.cpp + perftest.cpp + platformtest.cpp + rapidjsontest.cpp + schematest.cpp) + +add_executable(perftest ${PERFTEST_SOURCES}) +target_link_libraries(perftest ${TEST_LIBRARIES}) + +add_dependencies(tests perftest) + +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics") + endif() +endif(CCACHE_FOUND) + +set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS}) + +IF(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug")) +add_test(NAME perftest + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/perftest + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) +ENDIF() diff --git a/deps/rapidjson/test/perftest/misctest.cpp b/deps/rapidjson/test/perftest/misctest.cpp new file mode 100644 index 0000000..f43b050 --- /dev/null +++ b/deps/rapidjson/test/perftest/misctest.cpp @@ -0,0 +1,974 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "perftest.h" + +#if TEST_MISC + +#define __STDC_FORMAT_MACROS +#include "rapidjson/stringbuffer.h" + +#define protected public +#include "rapidjson/writer.h" +#undef private + +class Misc : public PerfTest { +}; + +// Copyright (c) 2008-2010 Bjoern Hoehrmann +// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 12 + +static const unsigned char utf8d[] = { + // The first part of the table maps bytes to character classes that + // to reduce the size of the transition table and create bitmasks. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + // The second part is a transition table that maps a combination + // of a state of the automaton and a character class to a state. + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, +}; + +static unsigned inline decode(unsigned* state, unsigned* codep, unsigned byte) { + unsigned type = utf8d[byte]; + + *codep = (*state != UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xff >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + +static bool IsUTF8(unsigned char* s) { + unsigned codepoint, state = 0; + + while (*s) + decode(&state, &codepoint, *s++); + + return state == UTF8_ACCEPT; +} + +TEST_F(Misc, Hoehrmann_IsUTF8) { + for (size_t i = 0; i < kTrialCount; i++) { + EXPECT_TRUE(IsUTF8((unsigned char*)json_)); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// CountDecimalDigit: Count number of decimal places + +inline unsigned CountDecimalDigit_naive(unsigned n) { + unsigned count = 1; + while (n >= 10) { + n /= 10; + count++; + } + return count; +} + +inline unsigned CountDecimalDigit_enroll4(unsigned n) { + unsigned count = 1; + while (n >= 10000) { + n /= 10000u; + count += 4; + } + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + return count + 3; +} + +inline unsigned CountDecimalDigit64_enroll4(uint64_t n) { + unsigned count = 1; + while (n >= 10000) { + n /= 10000u; + count += 4; + } + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + return count + 3; +} + +inline unsigned CountDecimalDigit_fast(unsigned n) { + static const uint32_t powers_of_10[] = { + 0, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000 + }; + +#if defined(_M_IX86) || defined(_M_X64) + unsigned long i = 0; + _BitScanReverse(&i, n | 1); + uint32_t t = (i + 1) * 1233 >> 12; +#elif defined(__GNUC__) + uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12; +#else +#error +#endif + return t - (n < powers_of_10[t]) + 1; +} + +inline unsigned CountDecimalDigit64_fast(uint64_t n) { + static const uint64_t powers_of_10[] = { + 0, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000, + 100000000000, + 1000000000000, + 10000000000000, + 100000000000000, + 1000000000000000, + 10000000000000000, + 100000000000000000, + 1000000000000000000, + 10000000000000000000U + }; + +#if defined(_M_IX86) + uint64_t m = n | 1; + unsigned long i = 0; + if (_BitScanReverse(&i, m >> 32)) + i += 32; + else + _BitScanReverse(&i, m & 0xFFFFFFFF); + uint32_t t = (i + 1) * 1233 >> 12; +#elif defined(_M_X64) + unsigned long i = 0; + _BitScanReverse64(&i, n | 1); + uint32_t t = (i + 1) * 1233 >> 12; +#elif defined(__GNUC__) + uint32_t t = (64 - __builtin_clzll(n | 1)) * 1233 >> 12; +#else +#error +#endif + + return t - (n < powers_of_10[t]) + 1; +} + +#if 0 +// Exhaustive, very slow +TEST_F(Misc, CountDecimalDigit_Verify) { + unsigned i = 0; + do { + if (i % (65536 * 256) == 0) + printf("%u\n", i); + ASSERT_EQ(CountDecimalDigit_enroll4(i), CountDecimalDigit_fast(i)); + i++; + } while (i != 0); +} + +static const unsigned kDigits10Trial = 1000000000u; +TEST_F(Misc, CountDecimalDigit_naive) { + unsigned sum = 0; + for (unsigned i = 0; i < kDigits10Trial; i++) + sum += CountDecimalDigit_naive(i); + printf("%u\n", sum); +} + +TEST_F(Misc, CountDecimalDigit_enroll4) { + unsigned sum = 0; + for (unsigned i = 0; i < kDigits10Trial; i++) + sum += CountDecimalDigit_enroll4(i); + printf("%u\n", sum); +} + +TEST_F(Misc, CountDecimalDigit_fast) { + unsigned sum = 0; + for (unsigned i = 0; i < kDigits10Trial; i++) + sum += CountDecimalDigit_fast(i); + printf("%u\n", sum); +} +#endif + +TEST_F(Misc, CountDecimalDigit64_VerifyFast) { + uint64_t i = 1, j; + do { + //printf("%" PRIu64 "\n", i); + ASSERT_EQ(CountDecimalDigit64_enroll4(i), CountDecimalDigit64_fast(i)); + j = i; + i *= 3; + } while (j < i); +} + +//////////////////////////////////////////////////////////////////////////////// +// integer-to-string conversion + +// https://gist.github.com/anonymous/7179097 +static const int randval[] ={ + 936116, 369532, 453755, -72860, 209713, 268347, 435278, -360266, -416287, -182064, + -644712, 944969, 640463, -366588, 471577, -69401, -744294, -505829, 923883, 831785, + -601136, -636767, -437054, 591718, 100758, 231907, -719038, 973540, -605220, 506659, + -871653, 462533, 764843, -919138, 404305, -630931, -288711, -751454, -173726, -718208, + 432689, -281157, 360737, 659827, 19174, -376450, 769984, -858198, 439127, 734703, + -683426, 7, 386135, 186997, -643900, -744422, -604708, -629545, 42313, -933592, + -635566, 182308, 439024, -367219, -73924, -516649, 421935, -470515, 413507, -78952, + -427917, -561158, 737176, 94538, 572322, 405217, 709266, -357278, -908099, -425447, + 601119, 750712, -862285, -177869, 900102, 384877, 157859, -641680, 503738, -702558, + 278225, 463290, 268378, -212840, 580090, 347346, -473985, -950968, -114547, -839893, + -738032, -789424, 409540, 493495, 432099, 119755, 905004, -174834, 338266, 234298, + 74641, -965136, -754593, 685273, 466924, 920560, 385062, 796402, -67229, 994864, + 376974, 299869, -647540, -128724, 469890, -163167, -547803, -743363, 486463, -621028, + 612288, 27459, -514224, 126342, -66612, 803409, -777155, -336453, -284002, 472451, + 342390, -163630, 908356, -456147, -825607, 268092, -974715, 287227, 227890, -524101, + 616370, -782456, 922098, -624001, -813690, 171605, -192962, 796151, 707183, -95696, + -23163, -721260, 508892, 430715, 791331, 482048, -996102, 863274, 275406, -8279, + -556239, -902076, 268647, -818565, 260069, -798232, -172924, -566311, -806503, -885992, + 813969, -78468, 956632, 304288, 494867, -508784, 381751, 151264, 762953, 76352, + 594902, 375424, 271700, -743062, 390176, 924237, 772574, 676610, 435752, -153847, + 3959, -971937, -294181, -538049, -344620, -170136, 19120, -703157, 868152, -657961, + -818631, 219015, -872729, -940001, -956570, 880727, -345910, 942913, -942271, -788115, + 225294, 701108, -517736, -416071, 281940, 488730, 942698, 711494, 838382, -892302, + -533028, 103052, 528823, 901515, 949577, 159364, 718227, -241814, -733661, -462928, + -495829, 165170, 513580, -629188, -509571, -459083, 198437, 77198, -644612, 811276, + -422298, -860842, -52584, 920369, 686424, -530667, -243476, 49763, 345866, -411960, + -114863, 470810, -302860, 683007, -509080, 2, -174981, -772163, -48697, 447770, + -268246, 213268, 269215, 78810, -236340, -639140, -864323, 505113, -986569, -325215, + 541859, 163070, -819998, -645161, -583336, 573414, 696417, -132375, 3, -294501, + 320435, 682591, 840008, 351740, 426951, 609354, 898154, -943254, 227321, -859793, + -727993, 44137, -497965, -782239, 14955, -746080, -243366, 9837, -233083, 606507, + -995864, -615287, -994307, 602715, 770771, -315040, 610860, 446102, -307120, 710728, + -590392, -230474, -762625, -637525, 134963, -202700, -766902, -985541, 218163, 682009, + 926051, 525156, -61195, 403211, -810098, 245539, -431733, 179998, -806533, 745943, + 447597, 131973, -187130, 826019, 286107, -937230, -577419, 20254, 681802, -340500, + 323080, 266283, -667617, 309656, 416386, 611863, 759991, -534257, 523112, -634892, + -169913, -204905, -909867, -882185, -944908, 741811, -717675, 967007, -317396, 407230, + -412805, 792905, 994873, 744793, -456797, 713493, 355232, 116900, -945199, 880539, + 342505, -580824, -262273, 982968, -349497, -735488, 311767, -455191, 570918, 389734, + -958386, 10262, -99267, 155481, 304210, 204724, 704367, -144893, -233664, -671441, + 896849, 408613, 762236, 322697, 981321, 688476, 13663, -970704, -379507, 896412, + 977084, 348869, 875948, 341348, 318710, 512081, 6163, 669044, 833295, 811883, + 708756, -802534, -536057, 608413, -389625, -694603, 541106, -110037, 720322, -540581, + 645420, 32980, 62442, 510157, -981870, -87093, -325960, -500494, -718291, -67889, + 991501, 374804, 769026, -978869, 294747, 714623, 413327, -199164, 671368, 804789, + -362507, 798196, -170790, -568895, -869379, 62020, -316693, -837793, 644994, -39341, + -417504, -243068, -957756, 99072, 622234, -739992, 225668, 8863, -505910, 82483, + -559244, 241572, 1315, -36175, -54990, 376813, -11, 162647, -688204, -486163, + -54934, -197470, 744223, -762707, 732540, 996618, 351561, -445933, -898491, 486531, + 456151, 15276, 290186, -817110, -52995, 313046, -452533, -96267, 94470, -500176, + -818026, -398071, -810548, -143325, -819741, 1338, -897676, -101577, -855445, 37309, + 285742, 953804, -777927, -926962, -811217, -936744, -952245, -802300, -490188, -964953, + -552279, 329142, -570048, -505756, 682898, -381089, -14352, 175138, 152390, -582268, + -485137, 717035, 805329, 239572, -730409, 209643, -184403, -385864, 675086, 819648, + 629058, -527109, -488666, -171981, 532788, 552441, 174666, 984921, 766514, 758787, + 716309, 338801, -978004, -412163, 876079, -734212, 789557, -160491, -522719, 56644, + -991, -286038, -53983, 663740, 809812, 919889, -717502, -137704, 220511, 184396, + -825740, -588447, 430870, 124309, 135956, 558662, -307087, -788055, -451328, 812260, + 931601, 324347, -482989, -117858, -278861, 189068, -172774, 929057, 293787, 198161, + -342386, -47173, 906555, -759955, -12779, 777604, -97869, 899320, 927486, -25284, + -848550, 259450, -485856, -17820, 88, 171400, 235492, -326783, -340793, 886886, + 112428, -246280, 5979, 648444, -114982, 991013, -56489, -9497, 419706, 632820, + -341664, 393926, -848977, -22538, 257307, 773731, -905319, 491153, 734883, -868212, + -951053, 644458, -580758, 764735, 584316, 297077, 28852, -397710, -953669, 201772, + 879050, -198237, -588468, 448102, -116837, 770007, -231812, 642906, -582166, -885828, + 9, 305082, -996577, 303559, 75008, -772956, -447960, 599825, -295552, 870739, + -386278, -950300, 485359, -457081, 629461, -850276, 550496, -451755, -620841, -11766, + -950137, 832337, 28711, -273398, -507197, 91921, -271360, -705991, -753220, -388968, + 967945, 340434, -320883, -662793, -554617, -574568, 477946, -6148, -129519, 689217, + 920020, -656315, -974523, -212525, 80921, -612532, 645096, 545655, 655713, -591631, + -307385, -816688, -618823, -113713, 526430, 673063, 735916, -809095, -850417, 639004, + 432281, -388185, 270708, 860146, -39902, -786157, -258180, -246169, -966720, -264957, + 548072, -306010, -57367, -635665, 933824, 70553, -989936, -488741, 72411, -452509, + 529831, 956277, 449019, -577850, -360986, -803418, 48833, 296073, 203430, 609591, + 715483, 470964, 658106, -718254, -96424, 790163, 334739, 181070, -373578, 5, + -435088, 329841, 330939, -256602, 394355, 912412, 231910, 927278, -661933, 788539, + -769664, -893274, -96856, 298205, 901043, -608122, -527430, 183618, -553963, -35246, + -393924, 948832, -483198, 594501, 35460, -407007, 93494, -336881, -634072, 984205, + -812161, 944664, -31062, 753872, 823933, -69566, 50445, 290147, 85134, 34706, + 551902, 405202, -991246, -84642, 154341, 316432, -695101, -651588, -5030, 137564, + -294665, 332541, 528307, -90572, -344923, 523766, -758498, -968047, 339028, 494578, + 593129, -725773, 31834, -718406, -208638, 159665, -2043, 673344, -442767, 75816, + 755442, 769257, -158730, -410272, 691688, 589550, -878398, -184121, 460679, 346312, + 294163, -544602, 653308, 254167, -276979, 52073, -892684, 887653, -41222, 983065, + -68258, -408799, -99069, -674069, -863635, -32890, 622757, -743862, 40872, -4837, + -967228, 522370, -903951, -818669, 524459, 514702, 925801, 20007, -299229, 579348, + 626021, 430089, 348139, -562692, -607728, -130606, -928451, -424793, -458647, -448892, + -312230, 143337, 109746, 880042, -339658, -785614, 938995, 540916, 118429, 661351, + -402967, 404729, -40918, -976535, 743230, 713110, 440182, -381314, -499252, 74613, + 193652, 912717, 491323, 583633, 324691, 459397, 281253, 195540, -2764, -888651, + 892449, 132663, -478373, -430002, -314551, 527826, 247165, 557966, 554778, 481531, + -946634, 431685, -769059, -348371, 174046, 184597, -354867, 584422, 227390, -850397, + -542924, -849093, -737769, 325359, 736314, 269101, 767940, 674809, 81413, -447458, + 445076, 189072, 906218, 502688, -718476, -863827, -731381, 100660, 623249, 710008, + 572060, 922203, 685740, 55096, 263394, -243695, -353910, -516788, 388471, 455165, + 844103, -643772, 363976, 268875, -899450, 104470, 104029, -238874, -274659, 732969, + -676443, 953291, -916289, -861849, -242344, 958083, -479593, -970395, 799831, 277841, + -243236, -283462, -201510, 166263, -259105, -575706, 878926, 891064, 895297, 655262, + -34807, -809833, -89281, 342585, 554920, 1, 902141, -333425, 139703, 852318, + -618438, 329498, -932596, -692836, -513372, 733656, -523411, 85779, 500478, -682697, + -502836, 138776, 156341, -420037, -557964, -556378, 710993, -50383, -877159, 916334, + 132996, 583516, -603392, -111615, -12288, -780214, 476780, 123327, 137607, 519956, + 745837, 17358, -158581, -53490 +}; +static const size_t randvalCount = sizeof(randval) / sizeof(randval[0]); +static const size_t kItoaTrialCount = 10000; + +static const char digits[201] = +"0001020304050607080910111213141516171819" +"2021222324252627282930313233343536373839" +"4041424344454647484950515253545556575859" +"6061626364656667686970717273747576777879" +"8081828384858687888990919293949596979899"; + +// Prevent code being optimized out +//#define OUTPUT_LENGTH(length) printf("", length) +#define OUTPUT_LENGTH(length) printf("%u\n", (unsigned)length) + +template +class Writer1 { +public: + Writer1() : os_() {} + Writer1(OutputStream& os) : os_(&os) {} + + void Reset(OutputStream& os) { + os_ = &os; + } + + bool WriteInt(int i) { + if (i < 0) { + os_->Put('-'); + i = -i; + } + return WriteUint((unsigned)i); + } + + bool WriteUint(unsigned u) { + char buffer[10]; + char *p = buffer; + do { + *p++ = char(u % 10) + '0'; + u /= 10; + } while (u > 0); + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + + bool WriteInt64(int64_t i64) { + if (i64 < 0) { + os_->Put('-'); + i64 = -i64; + } + WriteUint64((uint64_t)i64); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char *p = buffer; + do { + *p++ = char(u64 % 10) + '0'; + u64 /= 10; + } while (u64 > 0); + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + +private: + OutputStream* os_; +}; + +template<> +bool Writer1::WriteUint(unsigned u) { + char buffer[10]; + char* p = buffer; + do { + *p++ = char(u % 10) + '0'; + u /= 10; + } while (u > 0); + + char* d = os_->Push(p - buffer); + do { + --p; + *d++ = *p; + } while (p != buffer); + return true; +} + +// Using digits LUT to reduce division/modulo +template +class Writer2 { +public: + Writer2() : os_() {} + Writer2(OutputStream& os) : os_(&os) {} + + void Reset(OutputStream& os) { + os_ = &os; + } + + bool WriteInt(int i) { + if (i < 0) { + os_->Put('-'); + i = -i; + } + return WriteUint((unsigned)i); + } + + bool WriteUint(unsigned u) { + char buffer[10]; + char* p = buffer; + while (u >= 100) { + const unsigned i = (u % 100) << 1; + u /= 100; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + if (u < 10) + *p++ = char(u) + '0'; + else { + const unsigned i = u << 1; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + + bool WriteInt64(int64_t i64) { + if (i64 < 0) { + os_->Put('-'); + i64 = -i64; + } + WriteUint64((uint64_t)i64); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* p = buffer; + while (u64 >= 100) { + const unsigned i = static_cast(u64 % 100) << 1; + u64 /= 100; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + if (u64 < 10) + *p++ = char(u64) + '0'; + else { + const unsigned i = static_cast(u64) << 1; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + +private: + OutputStream* os_; +}; + +// First pass to count digits +template +class Writer3 { +public: + Writer3() : os_() {} + Writer3(OutputStream& os) : os_(&os) {} + + void Reset(OutputStream& os) { + os_ = &os; + } + + bool WriteInt(int i) { + if (i < 0) { + os_->Put('-'); + i = -i; + } + return WriteUint((unsigned)i); + } + + bool WriteUint(unsigned u) { + char buffer[10]; + char *p = buffer; + do { + *p++ = char(u % 10) + '0'; + u /= 10; + } while (u > 0); + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + + bool WriteInt64(int64_t i64) { + if (i64 < 0) { + os_->Put('-'); + i64 = -i64; + } + WriteUint64((uint64_t)i64); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char *p = buffer; + do { + *p++ = char(u64 % 10) + '0'; + u64 /= 10; + } while (u64 > 0); + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + +private: + void WriteUintReverse(char* d, unsigned u) { + do { + *--d = char(u % 10) + '0'; + u /= 10; + } while (u > 0); + } + + void WriteUint64Reverse(char* d, uint64_t u) { + do { + *--d = char(u % 10) + '0'; + u /= 10; + } while (u > 0); + } + + OutputStream* os_; +}; + +template<> +inline bool Writer3::WriteUint(unsigned u) { + unsigned digit = CountDecimalDigit_fast(u); + WriteUintReverse(os_->Push(digit) + digit, u); + return true; +} + +template<> +inline bool Writer3::WriteUint(unsigned u) { + unsigned digit = CountDecimalDigit_fast(u); + WriteUintReverse(os_->Push(digit) + digit, u); + return true; +} + +template<> +inline bool Writer3::WriteUint64(uint64_t u) { + unsigned digit = CountDecimalDigit64_fast(u); + WriteUint64Reverse(os_->Push(digit) + digit, u); + return true; +} + +template<> +inline bool Writer3::WriteUint64(uint64_t u) { + unsigned digit = CountDecimalDigit64_fast(u); + WriteUint64Reverse(os_->Push(digit) + digit, u); + return true; +} + +// Using digits LUT to reduce division/modulo, two passes +template +class Writer4 { +public: + Writer4() : os_() {} + Writer4(OutputStream& os) : os_(&os) {} + + void Reset(OutputStream& os) { + os_ = &os; + } + + bool WriteInt(int i) { + if (i < 0) { + os_->Put('-'); + i = -i; + } + return WriteUint((unsigned)i); + } + + bool WriteUint(unsigned u) { + char buffer[10]; + char* p = buffer; + while (u >= 100) { + const unsigned i = (u % 100) << 1; + u /= 100; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + if (u < 10) + *p++ = char(u) + '0'; + else { + const unsigned i = u << 1; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + + bool WriteInt64(int64_t i64) { + if (i64 < 0) { + os_->Put('-'); + i64 = -i64; + } + WriteUint64((uint64_t)i64); + return true; + } + + bool WriteUint64(uint64_t u64) { + char buffer[20]; + char* p = buffer; + while (u64 >= 100) { + const unsigned i = static_cast(u64 % 100) << 1; + u64 /= 100; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + if (u64 < 10) + *p++ = char(u64) + '0'; + else { + const unsigned i = static_cast(u64) << 1; + *p++ = digits[i + 1]; + *p++ = digits[i]; + } + + do { + --p; + os_->Put(*p); + } while (p != buffer); + return true; + } + +private: + void WriteUintReverse(char* d, unsigned u) { + while (u >= 100) { + const unsigned i = (u % 100) << 1; + u /= 100; + *--d = digits[i + 1]; + *--d = digits[i]; + } + if (u < 10) { + *--d = char(u) + '0'; + } + else { + const unsigned i = u << 1; + *--d = digits[i + 1]; + *--d = digits[i]; + } + } + + void WriteUint64Reverse(char* d, uint64_t u) { + while (u >= 100) { + const unsigned i = (u % 100) << 1; + u /= 100; + *--d = digits[i + 1]; + *--d = digits[i]; + } + if (u < 10) { + *--d = char(u) + '0'; + } + else { + const unsigned i = u << 1; + *--d = digits[i + 1]; + *--d = digits[i]; + } + } + + OutputStream* os_; +}; + +template<> +inline bool Writer4::WriteUint(unsigned u) { + unsigned digit = CountDecimalDigit_fast(u); + WriteUintReverse(os_->Push(digit) + digit, u); + return true; +} + +template<> +inline bool Writer4::WriteUint(unsigned u) { + unsigned digit = CountDecimalDigit_fast(u); + WriteUintReverse(os_->Push(digit) + digit, u); + return true; +} + +template<> +inline bool Writer4::WriteUint64(uint64_t u) { + unsigned digit = CountDecimalDigit64_fast(u); + WriteUint64Reverse(os_->Push(digit) + digit, u); + return true; +} + +template<> +inline bool Writer4::WriteUint64(uint64_t u) { + unsigned digit = CountDecimalDigit64_fast(u); + WriteUint64Reverse(os_->Push(digit) + digit, u); + return true; +} + +template +void itoa_Writer_StringBufferVerify() { + rapidjson::StringBuffer sb; + Writer writer(sb); + for (size_t j = 0; j < randvalCount; j++) { + char buffer[32]; + sprintf(buffer, "%d", randval[j]); + writer.WriteInt(randval[j]); + ASSERT_STREQ(buffer, sb.GetString()); + sb.Clear(); + } +} + +template +void itoa_Writer_InsituStringStreamVerify() { + Writer writer; + for (size_t j = 0; j < randvalCount; j++) { + char buffer[32]; + sprintf(buffer, "%d", randval[j]); + char buffer2[32]; + rapidjson::InsituStringStream ss(buffer2); + writer.Reset(ss); + char* begin = ss.PutBegin(); + writer.WriteInt(randval[j]); + ss.Put('\0'); + ss.PutEnd(begin); + ASSERT_STREQ(buffer, buffer2); + } +} + +template +void itoa_Writer_StringBuffer() { + size_t length = 0; + + rapidjson::StringBuffer sb; + Writer writer(sb); + + for (size_t i = 0; i < kItoaTrialCount; i++) { + for (size_t j = 0; j < randvalCount; j++) { + writer.WriteInt(randval[j]); + length += sb.GetSize(); + sb.Clear(); + } + } + OUTPUT_LENGTH(length); +} + +template +void itoa_Writer_InsituStringStream() { + size_t length = 0; + + char buffer[32]; + Writer writer; + for (size_t i = 0; i < kItoaTrialCount; i++) { + for (size_t j = 0; j < randvalCount; j++) { + rapidjson::InsituStringStream ss(buffer); + writer.Reset(ss); + char* begin = ss.PutBegin(); + writer.WriteInt(randval[j]); + length += ss.PutEnd(begin); + } + } + OUTPUT_LENGTH(length); +}; + +template +void itoa64_Writer_StringBufferVerify() { + rapidjson::StringBuffer sb; + Writer writer(sb); + for (size_t j = 0; j < randvalCount; j++) { + char buffer[32]; + int64_t x = randval[j] * randval[j]; + sprintf(buffer, "%" PRIi64, x); + writer.WriteInt64(x); + ASSERT_STREQ(buffer, sb.GetString()); + sb.Clear(); + } +} + +template +void itoa64_Writer_InsituStringStreamVerify() { + Writer writer; + for (size_t j = 0; j < randvalCount; j++) { + char buffer[32]; + int64_t x = randval[j] * randval[j]; + sprintf(buffer, "%" PRIi64, x); + char buffer2[32]; + rapidjson::InsituStringStream ss(buffer2); + writer.Reset(ss); + char* begin = ss.PutBegin(); + writer.WriteInt64(x); + ss.Put('\0'); + ss.PutEnd(begin); + ASSERT_STREQ(buffer, buffer2); + } +} + +template +void itoa64_Writer_StringBuffer() { + size_t length = 0; + + rapidjson::StringBuffer sb; + Writer writer(sb); + + for (size_t i = 0; i < kItoaTrialCount; i++) { + for (size_t j = 0; j < randvalCount; j++) { + writer.WriteInt64(randval[j] * randval[j]); + length += sb.GetSize(); + sb.Clear(); + } + } + OUTPUT_LENGTH(length); +} + +template +void itoa64_Writer_InsituStringStream() { + size_t length = 0; + + char buffer[32]; + Writer writer; + for (size_t i = 0; i < kItoaTrialCount; i++) { + for (size_t j = 0; j < randvalCount; j++) { + rapidjson::InsituStringStream ss(buffer); + writer.Reset(ss); + char* begin = ss.PutBegin(); + writer.WriteInt64(randval[j] * randval[j]); + length += ss.PutEnd(begin); + } + } + OUTPUT_LENGTH(length); +}; + +// Full specialization for InsituStringStream to prevent memory copying +// (normally we will not use InsituStringStream for writing, just for testing) + +namespace rapidjson { + +template<> +bool rapidjson::Writer::WriteInt(int i) { + char *buffer = os_->Push(11); + const char* end = internal::i32toa(i, buffer); + os_->Pop(11 - (end - buffer)); + return true; +} + +template<> +bool Writer::WriteUint(unsigned u) { + char *buffer = os_->Push(10); + const char* end = internal::u32toa(u, buffer); + os_->Pop(10 - (end - buffer)); + return true; +} + +template<> +bool Writer::WriteInt64(int64_t i64) { + char *buffer = os_->Push(21); + const char* end = internal::i64toa(i64, buffer); + os_->Pop(21 - (end - buffer)); + return true; +} + +template<> +bool Writer::WriteUint64(uint64_t u) { + char *buffer = os_->Push(20); + const char* end = internal::u64toa(u, buffer); + os_->Pop(20 - (end - buffer)); + return true; +} + +} // namespace rapidjson + +TEST_F(Misc, itoa_Writer_StringBufferVerify) { itoa_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa_Writer1_StringBufferVerify) { itoa_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa_Writer2_StringBufferVerify) { itoa_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa_Writer3_StringBufferVerify) { itoa_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa_Writer4_StringBufferVerify) { itoa_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa_Writer_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa_Writer1_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa_Writer2_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa_Writer3_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa_Writer4_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa_Writer_StringBuffer) { itoa_Writer_StringBuffer >(); } +TEST_F(Misc, itoa_Writer1_StringBuffer) { itoa_Writer_StringBuffer >(); } +TEST_F(Misc, itoa_Writer2_StringBuffer) { itoa_Writer_StringBuffer >(); } +TEST_F(Misc, itoa_Writer3_StringBuffer) { itoa_Writer_StringBuffer >(); } +TEST_F(Misc, itoa_Writer4_StringBuffer) { itoa_Writer_StringBuffer >(); } +TEST_F(Misc, itoa_Writer_InsituStringStream) { itoa_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa_Writer1_InsituStringStream) { itoa_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa_Writer2_InsituStringStream) { itoa_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa_Writer3_InsituStringStream) { itoa_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa_Writer4_InsituStringStream) { itoa_Writer_InsituStringStream >(); } + +TEST_F(Misc, itoa64_Writer_StringBufferVerify) { itoa64_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa64_Writer1_StringBufferVerify) { itoa64_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa64_Writer2_StringBufferVerify) { itoa64_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa64_Writer3_StringBufferVerify) { itoa64_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa64_Writer4_StringBufferVerify) { itoa64_Writer_StringBufferVerify >(); } +TEST_F(Misc, itoa64_Writer_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa64_Writer1_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa64_Writer2_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa64_Writer3_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa64_Writer4_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify >(); } +TEST_F(Misc, itoa64_Writer_StringBuffer) { itoa64_Writer_StringBuffer >(); } +TEST_F(Misc, itoa64_Writer1_StringBuffer) { itoa64_Writer_StringBuffer >(); } +TEST_F(Misc, itoa64_Writer2_StringBuffer) { itoa64_Writer_StringBuffer >(); } +TEST_F(Misc, itoa64_Writer3_StringBuffer) { itoa64_Writer_StringBuffer >(); } +TEST_F(Misc, itoa64_Writer4_StringBuffer) { itoa64_Writer_StringBuffer >(); } +TEST_F(Misc, itoa64_Writer_InsituStringStream) { itoa64_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa64_Writer1_InsituStringStream) { itoa64_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa64_Writer2_InsituStringStream) { itoa64_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa64_Writer3_InsituStringStream) { itoa64_Writer_InsituStringStream >(); } +TEST_F(Misc, itoa64_Writer4_InsituStringStream) { itoa64_Writer_InsituStringStream >(); } + +#endif // TEST_MISC diff --git a/deps/rapidjson/test/perftest/perftest.cpp b/deps/rapidjson/test/perftest/perftest.cpp new file mode 100644 index 0000000..b149a4c --- /dev/null +++ b/deps/rapidjson/test/perftest/perftest.cpp @@ -0,0 +1,24 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "perftest.h" + +int main(int argc, char **argv) { +#if _MSC_VER + _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); + //void *testWhetherMemoryLeakDetectionWorks = malloc(1); +#endif + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/deps/rapidjson/test/perftest/perftest.h b/deps/rapidjson/test/perftest/perftest.h new file mode 100644 index 0000000..31e3ca6 --- /dev/null +++ b/deps/rapidjson/test/perftest/perftest.h @@ -0,0 +1,186 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef PERFTEST_H_ +#define PERFTEST_H_ + +#define TEST_RAPIDJSON 1 +#define TEST_PLATFORM 0 +#define TEST_MISC 0 + +#define TEST_VERSION_CODE(x,y,z) \ + (((x)*100000) + ((y)*100) + (z)) + +// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler. +// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported. +// Likewise, __ARM_NEON is used to detect Neon. +#if defined(__SSE4_2__) +# define RAPIDJSON_SSE42 +#elif defined(__SSE2__) +# define RAPIDJSON_SSE2 +#elif defined(__ARM_NEON) +# define RAPIDJSON_NEON +#endif + +#define RAPIDJSON_HAS_STDSTRING 1 + +//////////////////////////////////////////////////////////////////////////////// +// Google Test + +#ifdef __cplusplus + +// gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS. +#ifndef __STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS 1 // required by C++ standard +#endif + +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) +#if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#pragma GCC diagnostic push +#endif +#pragma GCC diagnostic ignored "-Weffc++" +#endif + +#include "gtest/gtest.h" + +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#pragma GCC diagnostic pop +#endif + +#ifdef _MSC_VER +#define _CRTDBG_MAP_ALLOC +#include +#pragma warning(disable : 4996) // 'function': was declared deprecated +#endif + +//! Base class for all performance tests +class PerfTest : public ::testing::Test { +public: + PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {} + + virtual void SetUp() { + { + const char *paths[] = { + "data/sample.json", + "bin/data/sample.json", + "../bin/data/sample.json", + "../../bin/data/sample.json", + "../../../bin/data/sample.json" + }; + + FILE *fp = 0; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + fp = fopen(filename_ = paths[i], "rb"); + if (fp) + break; + } + ASSERT_TRUE(fp != 0); + + fseek(fp, 0, SEEK_END); + length_ = (size_t)ftell(fp); + fseek(fp, 0, SEEK_SET); + json_ = (char*)malloc(length_ + 1); + ASSERT_EQ(length_, fread(json_, 1, length_, fp)); + json_[length_] = '\0'; + fclose(fp); + } + + // whitespace test + { + whitespace_length_ = 1024 * 1024; + whitespace_ = (char *)malloc(whitespace_length_ + 4); + char *p = whitespace_; + for (size_t i = 0; i < whitespace_length_; i += 4) { + *p++ = ' '; + *p++ = '\n'; + *p++ = '\r'; + *p++ = '\t'; + } + *p++ = '['; + *p++ = '0'; + *p++ = ']'; + *p++ = '\0'; + } + + // types test + { + const char *typespaths[] = { + "data/types", + "bin/types", + "../bin/types", + "../../bin/types/", + "../../../bin/types" + }; + + const char* typesfilenames[] = { + "booleans.json", + "floats.json", + "guids.json", + "integers.json", + "mixed.json", + "nulls.json", + "paragraphs.json", + "alotofkeys.json" + }; + + for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) { + types_[j] = 0; + for (size_t i = 0; i < sizeof(typespaths) / sizeof(typespaths[0]); i++) { + char filename[256]; + sprintf(filename, "%s/%s", typespaths[i], typesfilenames[j]); + if (FILE* fp = fopen(filename, "rb")) { + fseek(fp, 0, SEEK_END); + typesLength_[j] = (size_t)ftell(fp); + fseek(fp, 0, SEEK_SET); + types_[j] = (char*)malloc(typesLength_[j] + 1); + ASSERT_EQ(typesLength_[j], fread(types_[j], 1, typesLength_[j], fp)); + types_[j][typesLength_[j]] = '\0'; + fclose(fp); + break; + } + } + } + } + } + + virtual void TearDown() { + free(json_); + free(whitespace_); + json_ = 0; + whitespace_ = 0; + for (size_t i = 0; i < 8; i++) { + free(types_[i]); + types_[i] = 0; + } + } + +private: + PerfTest(const PerfTest&); + PerfTest& operator=(const PerfTest&); + +protected: + const char* filename_; + char *json_; + size_t length_; + char *whitespace_; + size_t whitespace_length_; + char *types_[8]; + size_t typesLength_[8]; + + static const size_t kTrialCount = 1000; +}; + +#endif // __cplusplus + +#endif // PERFTEST_H_ diff --git a/deps/rapidjson/test/perftest/platformtest.cpp b/deps/rapidjson/test/perftest/platformtest.cpp new file mode 100644 index 0000000..c490da7 --- /dev/null +++ b/deps/rapidjson/test/perftest/platformtest.cpp @@ -0,0 +1,166 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "perftest.h" + +// This file is for giving the performance characteristics of the platform (compiler/OS/CPU). + +#if TEST_PLATFORM + +#include +#include + +// Windows +#ifdef _WIN32 +#include +#endif + +// UNIX +#if defined(unix) || defined(__unix__) || defined(__unix) +#include +#ifdef _POSIX_MAPPED_FILES +#include +#endif +#endif + +class Platform : public PerfTest { +public: + virtual void SetUp() { + PerfTest::SetUp(); + + // temp buffer for testing + temp_ = (char *)malloc(length_ + 1); + memcpy(temp_, json_, length_); + checkSum_ = CheckSum(); + } + + char CheckSum() { + char c = 0; + for (size_t i = 0; i < length_; ++i) + c += temp_[i]; + return c; + } + + virtual void TearDown() { + PerfTest::TearDown(); + free(temp_); + } + +protected: + char *temp_; + char checkSum_; +}; + +TEST_F(Platform, CheckSum) { + for (int i = 0; i < kTrialCount; i++) + EXPECT_EQ(checkSum_, CheckSum()); +} + +TEST_F(Platform, strlen) { + for (int i = 0; i < kTrialCount; i++) { + size_t l = strlen(json_); + EXPECT_EQ(length_, l); + } +} + +TEST_F(Platform, memcmp) { + for (int i = 0; i < kTrialCount; i++) { + EXPECT_EQ(0u, memcmp(temp_, json_, length_)); + } +} + +TEST_F(Platform, pow) { + double sum = 0; + for (int i = 0; i < kTrialCount * kTrialCount; i++) + sum += pow(10.0, i & 255); + EXPECT_GT(sum, 0.0); +} + +TEST_F(Platform, Whitespace_strlen) { + for (int i = 0; i < kTrialCount; i++) { + size_t l = strlen(whitespace_); + EXPECT_GT(l, whitespace_length_); + } +} + +TEST_F(Platform, Whitespace_strspn) { + for (int i = 0; i < kTrialCount; i++) { + size_t l = strspn(whitespace_, " \n\r\t"); + EXPECT_EQ(whitespace_length_, l); + } +} + +TEST_F(Platform, fread) { + for (int i = 0; i < kTrialCount; i++) { + FILE *fp = fopen(filename_, "rb"); + ASSERT_EQ(length_, fread(temp_, 1, length_, fp)); + EXPECT_EQ(checkSum_, CheckSum()); + fclose(fp); + } +} + +#ifdef _MSC_VER +TEST_F(Platform, read) { + for (int i = 0; i < kTrialCount; i++) { + int fd = _open(filename_, _O_BINARY | _O_RDONLY); + ASSERT_NE(-1, fd); + ASSERT_EQ(length_, _read(fd, temp_, length_)); + EXPECT_EQ(checkSum_, CheckSum()); + _close(fd); + } +} +#else +TEST_F(Platform, read) { + for (int i = 0; i < kTrialCount; i++) { + int fd = open(filename_, O_RDONLY); + ASSERT_NE(-1, fd); + ASSERT_EQ(length_, read(fd, temp_, length_)); + EXPECT_EQ(checkSum_, CheckSum()); + close(fd); + } +} +#endif + +#ifdef _WIN32 +TEST_F(Platform, MapViewOfFile) { + for (int i = 0; i < kTrialCount; i++) { + HANDLE file = CreateFile(filename_, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + ASSERT_NE(INVALID_HANDLE_VALUE, file); + HANDLE mapObject = CreateFileMapping(file, NULL, PAGE_READONLY, 0, length_, NULL); + ASSERT_NE(INVALID_HANDLE_VALUE, mapObject); + void *p = MapViewOfFile(mapObject, FILE_MAP_READ, 0, 0, length_); + ASSERT_TRUE(p != NULL); + EXPECT_EQ(checkSum_, CheckSum()); + ASSERT_TRUE(UnmapViewOfFile(p) == TRUE); + ASSERT_TRUE(CloseHandle(mapObject) == TRUE); + ASSERT_TRUE(CloseHandle(file) == TRUE); + } +} +#endif + +#ifdef _POSIX_MAPPED_FILES +TEST_F(Platform, mmap) { + for (int i = 0; i < kTrialCount; i++) { + int fd = open(filename_, O_RDONLY); + ASSERT_NE(-1, fd); + void *p = mmap(NULL, length_, PROT_READ, MAP_PRIVATE, fd, 0); + ASSERT_TRUE(p != NULL); + EXPECT_EQ(checkSum_, CheckSum()); + munmap(p, length_); + close(fd); + } +} +#endif + +#endif // TEST_PLATFORM diff --git a/deps/rapidjson/test/perftest/rapidjsontest.cpp b/deps/rapidjson/test/perftest/rapidjsontest.cpp new file mode 100644 index 0000000..ce41c10 --- /dev/null +++ b/deps/rapidjson/test/perftest/rapidjsontest.cpp @@ -0,0 +1,564 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "perftest.h" + +#if TEST_RAPIDJSON + +#include "rapidjson/rapidjson.h" +#include "rapidjson/document.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/istreamwrapper.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/memorystream.h" + +#include +#include + +#ifdef RAPIDJSON_SSE2 +#define SIMD_SUFFIX(name) name##_SSE2 +#elif defined(RAPIDJSON_SSE42) +#define SIMD_SUFFIX(name) name##_SSE42 +#elif defined(RAPIDJSON_NEON) +#define SIMD_SUFFIX(name) name##_NEON +#else +#define SIMD_SUFFIX(name) name +#endif + +using namespace rapidjson; + +class RapidJson : public PerfTest { +public: + RapidJson() : temp_(), doc_() {} + + virtual void SetUp() { + PerfTest::SetUp(); + + // temp buffer for insitu parsing. + temp_ = (char *)malloc(length_ + 1); + + // Parse as a document + EXPECT_FALSE(doc_.Parse(json_).HasParseError()); + + for (size_t i = 0; i < 8; i++) + EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError()); + } + + virtual void TearDown() { + PerfTest::TearDown(); + free(temp_); + } + +private: + RapidJson(const RapidJson&); + RapidJson& operator=(const RapidJson&); + +protected: + char *temp_; + Document doc_; + Document typesDoc_[8]; +}; + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + InsituStringStream s(temp_); + BaseReaderHandler<> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_ValidateEncoding)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + InsituStringStream s(temp_); + BaseReaderHandler<> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler)) { + for (size_t i = 0; i < kTrialCount; i++) { + StringStream s(json_); + BaseReaderHandler<> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +#define TEST_TYPED(index, Name)\ +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_##Name)) {\ + for (size_t i = 0; i < kTrialCount * 10; i++) {\ + StringStream s(types_[index]);\ + BaseReaderHandler<> h;\ + Reader reader;\ + EXPECT_TRUE(reader.Parse(s, h));\ + }\ +}\ +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_##Name)) {\ + for (size_t i = 0; i < kTrialCount * 10; i++) {\ + memcpy(temp_, types_[index], typesLength_[index] + 1);\ + InsituStringStream s(temp_);\ + BaseReaderHandler<> h;\ + Reader reader;\ + EXPECT_TRUE(reader.Parse(s, h));\ + }\ +} + +TEST_TYPED(0, Booleans) +TEST_TYPED(1, Floats) +TEST_TYPED(2, Guids) +TEST_TYPED(3, Integers) +TEST_TYPED(4, Mixed) +TEST_TYPED(5, Nulls) +TEST_TYPED(6, Paragraphs) + +#undef TEST_TYPED + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FullPrecision)) { + for (size_t i = 0; i < kTrialCount; i++) { + StringStream s(json_); + BaseReaderHandler<> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterative_DummyHandler)) { + for (size_t i = 0; i < kTrialCount; i++) { + StringStream s(json_); + BaseReaderHandler<> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativeInsitu_DummyHandler)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + InsituStringStream s(temp_); + BaseReaderHandler<> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePull_DummyHandler)) { + for (size_t i = 0; i < kTrialCount; i++) { + StringStream s(json_); + BaseReaderHandler<> h; + Reader reader; + reader.IterativeParseInit(); + while (!reader.IterativeParseComplete()) { + if (!reader.IterativeParseNext(s, h)) + break; + } + EXPECT_FALSE(reader.HasParseError()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePullInsitu_DummyHandler)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + InsituStringStream s(temp_); + BaseReaderHandler<> h; + Reader reader; + reader.IterativeParseInit(); + while (!reader.IterativeParseComplete()) { + if (!reader.IterativeParseNext(s, h)) + break; + } + EXPECT_FALSE(reader.HasParseError()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_ValidateEncoding)) { + for (size_t i = 0; i < kTrialCount; i++) { + StringStream s(json_); + BaseReaderHandler<> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseInsitu_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + Document doc; + doc.ParseInsitu(temp_); + ASSERT_TRUE(doc.IsObject()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterativeInsitu_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + Document doc; + doc.ParseInsitu(temp_); + ASSERT_TRUE(doc.IsObject()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + Document doc; + doc.Parse(json_); + ASSERT_TRUE(doc.IsObject()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseLength_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + Document doc; + doc.Parse(json_, length_); + ASSERT_TRUE(doc.IsObject()); + } +} + +#if RAPIDJSON_HAS_STDSTRING +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseStdString_MemoryPoolAllocator)) { + const std::string s(json_, length_); + for (size_t i = 0; i < kTrialCount; i++) { + Document doc; + doc.Parse(s); + ASSERT_TRUE(doc.IsObject()); + } +} +#endif + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + Document doc; + doc.Parse(json_); + ASSERT_TRUE(doc.IsObject()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_CrtAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + GenericDocument, CrtAllocator> doc; + doc.Parse(temp_); + ASSERT_TRUE(doc.IsObject()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseEncodedInputStream_MemoryStream)) { + for (size_t i = 0; i < kTrialCount; i++) { + MemoryStream ms(json_, length_); + EncodedInputStream, MemoryStream> is(ms); + Document doc; + doc.ParseStream<0, UTF8<> >(is); + ASSERT_TRUE(doc.IsObject()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseAutoUTFInputStream_MemoryStream)) { + for (size_t i = 0; i < kTrialCount; i++) { + MemoryStream ms(json_, length_); + AutoUTFInputStream is(ms); + Document doc; + doc.ParseStream<0, AutoUTF >(is); + ASSERT_TRUE(doc.IsObject()); + } +} + +template +size_t Traverse(const T& value) { + size_t count = 1; + switch(value.GetType()) { + case kObjectType: + for (typename T::ConstMemberIterator itr = value.MemberBegin(); itr != value.MemberEnd(); ++itr) { + count++; // name + count += Traverse(itr->value); + } + break; + + case kArrayType: + for (typename T::ConstValueIterator itr = value.Begin(); itr != value.End(); ++itr) + count += Traverse(*itr); + break; + + default: + // Do nothing. + break; + } + return count; +} + +TEST_F(RapidJson, DocumentTraverse) { + for (size_t i = 0; i < kTrialCount; i++) { + size_t count = Traverse(doc_); + EXPECT_EQ(4339u, count); + //if (i == 0) + // std::cout << count << std::endl; + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +struct ValueCounter : public BaseReaderHandler<> { + ValueCounter() : count_(1) {} // root + + bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; } + bool EndArray(SizeType elementCount) { count_ += elementCount; return true; } + + SizeType count_; +}; + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif + +TEST_F(RapidJson, DocumentAccept) { + for (size_t i = 0; i < kTrialCount; i++) { + ValueCounter counter; + doc_.Accept(counter); + EXPECT_EQ(4339u, counter.count_); + } +} + +TEST_F(RapidJson, DocumentFind) { + typedef Document::ValueType ValueType; + typedef ValueType::ConstMemberIterator ConstMemberIterator; + const Document &doc = typesDoc_[7]; // alotofkeys.json + if (doc.IsObject()) { + std::vector keys; + for (ConstMemberIterator it = doc.MemberBegin(); it != doc.MemberEnd(); ++it) { + keys.push_back(&it->name); + } + for (size_t i = 0; i < kTrialCount; i++) { + for (size_t j = 0; j < keys.size(); j++) { + EXPECT_TRUE(doc.FindMember(*keys[j]) != doc.MemberEnd()); + } + } + } +} + +struct NullStream { + typedef char Ch; + + NullStream() /*: length_(0)*/ {} + void Put(Ch) { /*++length_;*/ } + void Flush() {} + //size_t length_; +}; + +TEST_F(RapidJson, Writer_NullStream) { + for (size_t i = 0; i < kTrialCount; i++) { + NullStream s; + Writer writer(s); + doc_.Accept(writer); + //if (i == 0) + // std::cout << s.length_ << std::endl; + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer)) { + for (size_t i = 0; i < kTrialCount; i++) { + StringBuffer s(0, 1024 * 1024); + Writer writer(s); + doc_.Accept(writer); + const char* str = s.GetString(); + (void)str; + //if (i == 0) + // std::cout << strlen(str) << std::endl; + } +} + +#define TEST_TYPED(index, Name)\ +TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer_##Name)) {\ + for (size_t i = 0; i < kTrialCount * 10; i++) {\ + StringBuffer s(0, 1024 * 1024);\ + Writer writer(s);\ + typesDoc_[index].Accept(writer);\ + const char* str = s.GetString();\ + (void)str;\ + }\ +} + +TEST_TYPED(0, Booleans) +TEST_TYPED(1, Floats) +TEST_TYPED(2, Guids) +TEST_TYPED(3, Integers) +TEST_TYPED(4, Mixed) +TEST_TYPED(5, Nulls) +TEST_TYPED(6, Paragraphs) + +#undef TEST_TYPED + +TEST_F(RapidJson, SIMD_SUFFIX(PrettyWriter_StringBuffer)) { + for (size_t i = 0; i < kTrialCount; i++) { + StringBuffer s(0, 2048 * 1024); + PrettyWriter writer(s); + writer.SetIndent(' ', 1); + doc_.Accept(writer); + const char* str = s.GetString(); + (void)str; + //if (i == 0) + // std::cout << strlen(str) << std::endl; + } +} + +TEST_F(RapidJson, internal_Pow10) { + double sum = 0; + for (size_t i = 0; i < kTrialCount * kTrialCount; i++) + sum += internal::Pow10(int(i & 255)); + EXPECT_GT(sum, 0.0); +} + +TEST_F(RapidJson, SkipWhitespace_Basic) { + for (size_t i = 0; i < kTrialCount; i++) { + rapidjson::StringStream s(whitespace_); + while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + s.Take(); + ASSERT_EQ('[', s.Peek()); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(SkipWhitespace)) { + for (size_t i = 0; i < kTrialCount; i++) { + rapidjson::StringStream s(whitespace_); + rapidjson::SkipWhitespace(s); + ASSERT_EQ('[', s.Peek()); + } +} + +TEST_F(RapidJson, SkipWhitespace_strspn) { + for (size_t i = 0; i < kTrialCount; i++) { + const char* s = whitespace_ + std::strspn(whitespace_, " \t\r\n"); + ASSERT_EQ('[', *s); + } +} + +TEST_F(RapidJson, UTF8_Validate) { + NullStream os; + + for (size_t i = 0; i < kTrialCount; i++) { + StringStream is(json_); + bool result = true; + while (is.Peek() != '\0') + result &= UTF8<>::Validate(is, os); + EXPECT_TRUE(result); + } +} + +TEST_F(RapidJson, FileReadStream) { + for (size_t i = 0; i < kTrialCount; i++) { + FILE *fp = fopen(filename_, "rb"); + char buffer[65536]; + FileReadStream s(fp, buffer, sizeof(buffer)); + while (s.Take() != '\0') + ; + fclose(fp); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FileReadStream)) { + for (size_t i = 0; i < kTrialCount; i++) { + FILE *fp = fopen(filename_, "rb"); + char buffer[65536]; + FileReadStream s(fp, buffer, sizeof(buffer)); + BaseReaderHandler<> h; + Reader reader; + reader.Parse(s, h); + fclose(fp); + } +} + +TEST_F(RapidJson, IStreamWrapper) { + for (size_t i = 0; i < kTrialCount; i++) { + std::ifstream is(filename_, std::ios::in | std::ios::binary); + char buffer[65536]; + IStreamWrapper isw(is, buffer, sizeof(buffer)); + while (isw.Take() != '\0') + ; + is.close(); + } +} + +TEST_F(RapidJson, IStreamWrapper_Unbuffered) { + for (size_t i = 0; i < kTrialCount; i++) { + std::ifstream is(filename_, std::ios::in | std::ios::binary); + IStreamWrapper isw(is); + while (isw.Take() != '\0') + ; + is.close(); + } +} + +TEST_F(RapidJson, IStreamWrapper_Setbuffered) { + for (size_t i = 0; i < kTrialCount; i++) { + std::ifstream is; + char buffer[65536]; + is.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); + is.open(filename_, std::ios::in | std::ios::binary); + IStreamWrapper isw(is); + while (isw.Take() != '\0') + ; + is.close(); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_IStreamWrapper)) { + for (size_t i = 0; i < kTrialCount; i++) { + std::ifstream is(filename_, std::ios::in | std::ios::binary); + char buffer[65536]; + IStreamWrapper isw(is, buffer, sizeof(buffer)); + BaseReaderHandler<> h; + Reader reader; + reader.Parse(isw, h); + is.close(); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_IStreamWrapper_Unbuffered)) { + for (size_t i = 0; i < kTrialCount; i++) { + std::ifstream is(filename_, std::ios::in | std::ios::binary); + IStreamWrapper isw(is); + BaseReaderHandler<> h; + Reader reader; + reader.Parse(isw, h); + is.close(); + } +} + +TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_IStreamWrapper_Setbuffered)) { + for (size_t i = 0; i < kTrialCount; i++) { + std::ifstream is; + char buffer[65536]; + is.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); + is.open(filename_, std::ios::in | std::ios::binary); + IStreamWrapper isw(is); + BaseReaderHandler<> h; + Reader reader; + reader.Parse(isw, h); + is.close(); + } +} + +TEST_F(RapidJson, StringBuffer) { + StringBuffer sb; + for (int i = 0; i < 32 * 1024 * 1024; i++) + sb.Put(i & 0x7f); +} + +#endif // TEST_RAPIDJSON diff --git a/deps/rapidjson/test/perftest/schematest.cpp b/deps/rapidjson/test/perftest/schematest.cpp new file mode 100644 index 0000000..7d27344 --- /dev/null +++ b/deps/rapidjson/test/perftest/schematest.cpp @@ -0,0 +1,223 @@ +#include "perftest.h" + +#if TEST_RAPIDJSON + +#include "rapidjson/schema.h" +#include +#include +#include + +#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0]) + +using namespace rapidjson; + +RAPIDJSON_DIAG_PUSH +#if defined(__GNUC__) && __GNUC__ >= 7 +RAPIDJSON_DIAG_OFF(format-overflow) +#endif + +template +static char* ReadFile(const char* filename, Allocator& allocator) { + const char *paths[] = { + "", + "bin/", + "../bin/", + "../../bin/", + "../../../bin/" + }; + char buffer[1024]; + FILE *fp = 0; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + sprintf(buffer, "%s%s", paths[i], filename); + fp = fopen(buffer, "rb"); + if (fp) + break; + } + + if (!fp) + return 0; + + fseek(fp, 0, SEEK_END); + size_t length = static_cast(ftell(fp)); + fseek(fp, 0, SEEK_SET); + char* json = reinterpret_cast(allocator.Malloc(length + 1)); + size_t readLength = fread(json, 1, length, fp); + json[readLength] = '\0'; + fclose(fp); + return json; +} + +RAPIDJSON_DIAG_POP + +class Schema : public PerfTest { +public: + Schema() {} + + virtual void SetUp() { + PerfTest::SetUp(); + + const char* filenames[] = { + "additionalItems.json", + "additionalProperties.json", + "allOf.json", + "anyOf.json", + "default.json", + "definitions.json", + "dependencies.json", + "enum.json", + "items.json", + "maximum.json", + "maxItems.json", + "maxLength.json", + "maxProperties.json", + "minimum.json", + "minItems.json", + "minLength.json", + "minProperties.json", + "multipleOf.json", + "not.json", + "oneOf.json", + "pattern.json", + "patternProperties.json", + "properties.json", + "ref.json", + "refRemote.json", + "required.json", + "type.json", + "uniqueItems.json" + }; + + char jsonBuffer[65536]; + MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer)); + + for (size_t i = 0; i < ARRAY_SIZE(filenames); i++) { + char filename[FILENAME_MAX]; + sprintf(filename, "jsonschema/tests/draft4/%s", filenames[i]); + char* json = ReadFile(filename, jsonAllocator); + if (!json) { + printf("json test suite file %s not found", filename); + return; + } + + Document d; + d.Parse(json); + if (d.HasParseError()) { + printf("json test suite file %s has parse error", filename); + return; + } + + for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) { + std::string schemaDescription = (*schemaItr)["description"].GetString(); + if (IsExcludeTestSuite(schemaDescription)) + continue; + + TestSuite* ts = new TestSuite; + ts->schema = new SchemaDocument((*schemaItr)["schema"]); + + const Value& tests = (*schemaItr)["tests"]; + for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) { + if (IsExcludeTest(schemaDescription + ", " + (*testItr)["description"].GetString())) + continue; + + Document* d2 = new Document; + d2->CopyFrom((*testItr)["data"], d2->GetAllocator()); + ts->tests.push_back(d2); + } + testSuites.push_back(ts); + } + } + } + + virtual void TearDown() { + PerfTest::TearDown(); + for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr) + delete *itr; + testSuites.clear(); + } + +private: + // Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite + static bool IsExcludeTestSuite(const std::string& description) { + const char* excludeTestSuites[] = { + //lost failing these tests + "remote ref", + "remote ref, containing refs itself", + "fragment within remote ref", + "ref within remote ref", + "change resolution scope", + // these below were added to get jsck in the benchmarks) + "uniqueItems validation", + "valid definition", + "invalid definition" + }; + + for (size_t i = 0; i < ARRAY_SIZE(excludeTestSuites); i++) + if (excludeTestSuites[i] == description) + return true; + return false; + } + + // Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite + static bool IsExcludeTest(const std::string& description) { + const char* excludeTests[] = { + //lots of validators fail these + "invalid definition, invalid definition schema", + "maxLength validation, two supplementary Unicode code points is long enough", + "minLength validation, one supplementary Unicode code point is not long enough", + //this is to get tv4 in the benchmarks + "heterogeneous enum validation, something else is invalid" + }; + + for (size_t i = 0; i < ARRAY_SIZE(excludeTests); i++) + if (excludeTests[i] == description) + return true; + return false; + } + + Schema(const Schema&); + Schema& operator=(const Schema&); + +protected: + typedef std::vector DocumentList; + + struct TestSuite { + TestSuite() : schema() {} + ~TestSuite() { + delete schema; + for (DocumentList::iterator itr = tests.begin(); itr != tests.end(); ++itr) + delete *itr; + } + SchemaDocument* schema; + DocumentList tests; + }; + + typedef std::vector TestSuiteList; + TestSuiteList testSuites; +}; + +TEST_F(Schema, TestSuite) { + char validatorBuffer[65536]; + MemoryPoolAllocator<> validatorAllocator(validatorBuffer, sizeof(validatorBuffer)); + + const int trialCount = 100000; + int testCount = 0; + clock_t start = clock(); + for (int i = 0; i < trialCount; i++) { + for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr) { + const TestSuite& ts = **itr; + GenericSchemaValidator >, MemoryPoolAllocator<> > validator(*ts.schema, &validatorAllocator); + for (DocumentList::const_iterator testItr = ts.tests.begin(); testItr != ts.tests.end(); ++testItr) { + validator.Reset(); + (*testItr)->Accept(validator); + testCount++; + } + validatorAllocator.Clear(); + } + } + clock_t end = clock(); + double duration = double(end - start) / CLOCKS_PER_SEC; + printf("%d trials in %f s -> %f trials per sec\n", trialCount, duration, trialCount / duration); + printf("%d tests per trial\n", testCount / trialCount); +} + +#endif diff --git a/deps/rapidjson/test/unittest/CMakeLists.txt b/deps/rapidjson/test/unittest/CMakeLists.txt new file mode 100644 index 0000000..565ed98 --- /dev/null +++ b/deps/rapidjson/test/unittest/CMakeLists.txt @@ -0,0 +1,95 @@ +include(CheckCXXCompilerFlag) + +set(UNITTEST_SOURCES + allocatorstest.cpp + bigintegertest.cpp + clzlltest.cpp + cursorstreamwrappertest.cpp + documenttest.cpp + dtoatest.cpp + encodedstreamtest.cpp + encodingstest.cpp + fwdtest.cpp + filestreamtest.cpp + itoatest.cpp + istreamwrappertest.cpp + jsoncheckertest.cpp + namespacetest.cpp + pointertest.cpp + platformtest.cpp + prettywritertest.cpp + ostreamwrappertest.cpp + readertest.cpp + regextest.cpp + schematest.cpp + simdtest.cpp + strfunctest.cpp + stringbuffertest.cpp + strtodtest.cpp + unittest.cpp + uritest.cpp + valuetest.cpp + writertest.cpp) + +find_program(CCACHE_FOUND ccache) +if(CCACHE_FOUND) + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics") + endif() +endif(CCACHE_FOUND) + +set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS}) + +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # If the user is running a newer version of Clang that includes the + # -Wdouble-promotion, we will ignore that warning. + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.7) + CHECK_CXX_COMPILER_FLAG("-Wno-double-promotion" HAS_NO_DOUBLE_PROMOTION) + if (HAS_NO_DOUBLE_PROMOTION) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-double-promotion") + endif() + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + # Force to always compile with /W4 + if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") + string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") + endif() + + # Force to always compile with /WX + if(CMAKE_CXX_FLAGS MATCHES "/WX-") + string(REGEX REPLACE "/WX-" "/WX" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") + endif() +endif() + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRAPIDJSON_HAS_STDSTRING=1") + +add_library(namespacetest STATIC namespacetest.cpp) + +add_executable(unittest ${UNITTEST_SOURCES}) +target_link_libraries(unittest ${TEST_LIBRARIES} namespacetest) + +add_dependencies(tests unittest) + +add_test(NAME unittest + COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) + +if(NOT MSVC) + # Not running SIMD.* unit test cases for Valgrind + add_test(NAME valgrind_unittest + COMMAND valgrind --suppressions=${CMAKE_SOURCE_DIR}/test/valgrind.supp --leak-check=full --error-exitcode=1 ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/unittest --gtest_filter=-SIMD.* + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) + + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + add_test(NAME symbol_check + COMMAND sh -c "objdump -t -C libnamespacetest.a | grep rapidjson ; test $? -ne 0" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + endif(CMAKE_BUILD_TYPE STREQUAL "Debug") + +endif(NOT MSVC) diff --git a/deps/rapidjson/test/unittest/allocatorstest.cpp b/deps/rapidjson/test/unittest/allocatorstest.cpp new file mode 100644 index 0000000..2ffc325 --- /dev/null +++ b/deps/rapidjson/test/unittest/allocatorstest.cpp @@ -0,0 +1,292 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/allocators.h" + +#include +#include +#include +#include + +using namespace rapidjson; + +template +void TestAllocator(Allocator& a) { + EXPECT_TRUE(a.Malloc(0) == 0); + + uint8_t* p = static_cast(a.Malloc(100)); + EXPECT_TRUE(p != 0); + for (size_t i = 0; i < 100; i++) + p[i] = static_cast(i); + + // Expand + uint8_t* q = static_cast(a.Realloc(p, 100, 200)); + EXPECT_TRUE(q != 0); + for (size_t i = 0; i < 100; i++) + EXPECT_EQ(i, q[i]); + for (size_t i = 100; i < 200; i++) + q[i] = static_cast(i); + + // Shrink + uint8_t *r = static_cast(a.Realloc(q, 200, 150)); + EXPECT_TRUE(r != 0); + for (size_t i = 0; i < 150; i++) + EXPECT_EQ(i, r[i]); + + Allocator::Free(r); + + // Realloc to zero size + EXPECT_TRUE(a.Realloc(a.Malloc(1), 1, 0) == 0); +} + +struct TestStdAllocatorData { + TestStdAllocatorData(int &constructions, int &destructions) : + constructions_(&constructions), + destructions_(&destructions) + { + ++*constructions_; + } + TestStdAllocatorData(const TestStdAllocatorData& rhs) : + constructions_(rhs.constructions_), + destructions_(rhs.destructions_) + { + ++*constructions_; + } + TestStdAllocatorData& operator=(const TestStdAllocatorData& rhs) + { + this->~TestStdAllocatorData(); + constructions_ = rhs.constructions_; + destructions_ = rhs.destructions_; + ++*constructions_; + return *this; + } + ~TestStdAllocatorData() + { + ++*destructions_; + } +private: + TestStdAllocatorData(); + int *constructions_, + *destructions_; +}; + +template +void TestStdAllocator(const Allocator& a) { +#if RAPIDJSON_HAS_CXX17 + typedef StdAllocator BoolAllocator; +#else + typedef StdAllocator VoidAllocator; + typedef typename VoidAllocator::template rebind::other BoolAllocator; +#endif + BoolAllocator ba(a), ba2(a); + EXPECT_TRUE(ba == ba2); + EXPECT_FALSE(ba!= ba2); + ba.deallocate(ba.allocate()); + EXPECT_TRUE(ba == ba2); + EXPECT_FALSE(ba != ba2); + + unsigned long long ll = 0, *llp = ≪ + const unsigned long long cll = 0, *cllp = &cll; + StdAllocator lla(a); + EXPECT_EQ(lla.address(ll), llp); + EXPECT_EQ(lla.address(cll), cllp); + EXPECT_TRUE(lla.max_size() > 0 && lla.max_size() <= SIZE_MAX / sizeof(unsigned long long)); + + int *arr; + StdAllocator ia(a); + arr = ia.allocate(10 * sizeof(int)); + EXPECT_TRUE(arr != 0); + for (int i = 0; i < 10; ++i) { + arr[i] = 0x0f0f0f0f; + } + ia.deallocate(arr, 10); + arr = Malloc(ia, 10); + EXPECT_TRUE(arr != 0); + for (int i = 0; i < 10; ++i) { + arr[i] = 0x0f0f0f0f; + } + arr = Realloc(ia, arr, 10, 20); + EXPECT_TRUE(arr != 0); + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(arr[i], 0x0f0f0f0f); + } + for (int i = 10; i < 20; i++) { + arr[i] = 0x0f0f0f0f; + } + Free(ia, arr, 20); + + int cons = 0, dest = 0; + StdAllocator da(a); + for (int i = 1; i < 10; i++) { + TestStdAllocatorData *d = da.allocate(); + EXPECT_TRUE(d != 0); + + da.destroy(new(d) TestStdAllocatorData(cons, dest)); + EXPECT_EQ(cons, i); + EXPECT_EQ(dest, i); + + da.deallocate(d); + } + + typedef StdAllocator CharAllocator; + typedef std::basic_string, CharAllocator> String; +#if RAPIDJSON_HAS_CXX11 + String s(CharAllocator{a}); +#else + CharAllocator ca(a); + String s(ca); +#endif + for (int i = 0; i < 26; i++) { + s.push_back(static_cast('A' + i)); + } + EXPECT_TRUE(s == "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + + typedef StdAllocator, Allocator> MapAllocator; + typedef std::map, MapAllocator> Map; +#if RAPIDJSON_HAS_CXX11 + Map map(std::less(), MapAllocator{a}); +#else + MapAllocator ma(a); + Map map(std::less(), ma); +#endif + for (int i = 0; i < 10; i++) { + map.insert(std::make_pair(i, (i % 2) == 0)); + } + EXPECT_TRUE(map.size() == 10); + for (int i = 0; i < 10; i++) { + typename Map::iterator it = map.find(i); + EXPECT_TRUE(it != map.end()); + EXPECT_TRUE(it->second == ((i % 2) == 0)); + } +} + +TEST(Allocator, CrtAllocator) { + CrtAllocator a; + + TestAllocator(a); + TestStdAllocator(a); + + CrtAllocator a2; + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); + a2.Free(a2.Malloc(1)); + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); +} + +TEST(Allocator, MemoryPoolAllocator) { + const size_t capacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; + MemoryPoolAllocator<> a(capacity); + + a.Clear(); // noop + EXPECT_EQ(a.Size(), 0u); + EXPECT_EQ(a.Capacity(), 0u); + EXPECT_EQ(a.Shared(), false); + { + MemoryPoolAllocator<> a2(a); + EXPECT_EQ(a2.Shared(), true); + EXPECT_EQ(a.Shared(), true); + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); + a2.Free(a2.Malloc(1)); + EXPECT_TRUE(a == a2); + EXPECT_FALSE(a != a2); + } + EXPECT_EQ(a.Shared(), false); + EXPECT_EQ(a.Capacity(), capacity); + EXPECT_EQ(a.Size(), 8u); // aligned + a.Clear(); + EXPECT_EQ(a.Capacity(), 0u); + EXPECT_EQ(a.Size(), 0u); + + TestAllocator(a); + TestStdAllocator(a); + + for (size_t i = 1; i < 1000; i++) { + EXPECT_TRUE(a.Malloc(i) != 0); + EXPECT_LE(a.Size(), a.Capacity()); + } + + CrtAllocator baseAllocator; + a = MemoryPoolAllocator<>(capacity, &baseAllocator); + EXPECT_EQ(a.Capacity(), 0u); + EXPECT_EQ(a.Size(), 0u); + a.Free(a.Malloc(1)); + EXPECT_EQ(a.Capacity(), capacity); + EXPECT_EQ(a.Size(), 8u); // aligned + + { + a.Clear(); + const size_t bufSize = 1024; + char *buffer = (char *)a.Malloc(bufSize); + MemoryPoolAllocator<> aligned_a(buffer, bufSize); + EXPECT_TRUE(aligned_a.Capacity() > 0 && aligned_a.Capacity() <= bufSize); + EXPECT_EQ(aligned_a.Size(), 0u); + aligned_a.Free(aligned_a.Malloc(1)); + EXPECT_TRUE(aligned_a.Capacity() > 0 && aligned_a.Capacity() <= bufSize); + EXPECT_EQ(aligned_a.Size(), 8u); // aligned + } + + { + a.Clear(); + const size_t bufSize = 1024; + char *buffer = (char *)a.Malloc(bufSize); + RAPIDJSON_ASSERT(bufSize % sizeof(void*) == 0); + MemoryPoolAllocator<> unaligned_a(buffer + 1, bufSize - 1); + EXPECT_TRUE(unaligned_a.Capacity() > 0 && unaligned_a.Capacity() <= bufSize - sizeof(void*)); + EXPECT_EQ(unaligned_a.Size(), 0u); + unaligned_a.Free(unaligned_a.Malloc(1)); + EXPECT_TRUE(unaligned_a.Capacity() > 0 && unaligned_a.Capacity() <= bufSize - sizeof(void*)); + EXPECT_EQ(unaligned_a.Size(), 8u); // aligned + } +} + +TEST(Allocator, Alignment) { + if (sizeof(size_t) >= 8) { + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000000), RAPIDJSON_ALIGN(0)); + for (uint64_t i = 1; i < 8; i++) { + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008), RAPIDJSON_ALIGN(i)); + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000000, 0x00000010), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0x00000008) + i)); + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x00000001, 0x00000000), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0x00000000, 0xFFFFFFF8) + i)); + EXPECT_EQ(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF8), RAPIDJSON_ALIGN(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0) + i)); + } + } + + EXPECT_EQ(0u, RAPIDJSON_ALIGN(0u)); + for (uint32_t i = 1; i < 8; i++) { + EXPECT_EQ(8u, RAPIDJSON_ALIGN(i)); + EXPECT_EQ(0xFFFFFFF8u, RAPIDJSON_ALIGN(0xFFFFFFF0u + i)); + } +} + +TEST(Allocator, Issue399) { + MemoryPoolAllocator<> a; + void* p = a.Malloc(100); + void* q = a.Realloc(p, 100, 200); + EXPECT_EQ(p, q); + + // exhuasive testing + for (size_t j = 1; j < 32; j++) { + a.Clear(); + a.Malloc(j); // some unaligned size + p = a.Malloc(1); + for (size_t i = 1; i < 1024; i++) { + q = a.Realloc(p, i, i + 1); + EXPECT_EQ(p, q); + p = q; + } + } +} diff --git a/deps/rapidjson/test/unittest/bigintegertest.cpp b/deps/rapidjson/test/unittest/bigintegertest.cpp new file mode 100644 index 0000000..fad5438 --- /dev/null +++ b/deps/rapidjson/test/unittest/bigintegertest.cpp @@ -0,0 +1,138 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/internal/biginteger.h" + +using namespace rapidjson::internal; + +#define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1) + +static const BigInteger kZero(0); +static const BigInteger kOne(1); +static const BigInteger kUint64Max = BIGINTEGER_LITERAL("18446744073709551615"); +static const BigInteger kTwo64 = BIGINTEGER_LITERAL("18446744073709551616"); + +TEST(BigInteger, Constructor) { + EXPECT_TRUE(kZero.IsZero()); + EXPECT_TRUE(kZero == kZero); + EXPECT_TRUE(kZero == BIGINTEGER_LITERAL("0")); + EXPECT_TRUE(kZero == BIGINTEGER_LITERAL("00")); + + const BigInteger a(123); + EXPECT_TRUE(a == a); + EXPECT_TRUE(a == BIGINTEGER_LITERAL("123")); + EXPECT_TRUE(a == BIGINTEGER_LITERAL("0123")); + + EXPECT_EQ(2u, kTwo64.GetCount()); + EXPECT_EQ(0u, kTwo64.GetDigit(0)); + EXPECT_EQ(1u, kTwo64.GetDigit(1)); +} + +TEST(BigInteger, AddUint64) { + BigInteger a = kZero; + a += 0u; + EXPECT_TRUE(kZero == a); + + a += 1u; + EXPECT_TRUE(kOne == a); + + a += 1u; + EXPECT_TRUE(BigInteger(2) == a); + + EXPECT_TRUE(BigInteger(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)) == kUint64Max); + BigInteger b = kUint64Max; + b += 1u; + EXPECT_TRUE(kTwo64 == b); + b += RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF); + EXPECT_TRUE(BIGINTEGER_LITERAL("36893488147419103231") == b); +} + +TEST(BigInteger, MultiplyUint64) { + BigInteger a = kZero; + a *= static_cast (0); + EXPECT_TRUE(kZero == a); + a *= static_cast (123); + EXPECT_TRUE(kZero == a); + + BigInteger b = kOne; + b *= static_cast(1); + EXPECT_TRUE(kOne == b); + b *= static_cast(0); + EXPECT_TRUE(kZero == b); + + BigInteger c(123); + c *= static_cast(456u); + EXPECT_TRUE(BigInteger(123u * 456u) == c); + c *= RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF); + EXPECT_TRUE(BIGINTEGER_LITERAL("1034640981606221330982120") == c); + c *= RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF); + EXPECT_TRUE(BIGINTEGER_LITERAL("19085757395861596536664473018420572782123800") == c); +} + +TEST(BigInteger, MultiplyUint32) { + BigInteger a = kZero; + a *= static_cast (0); + EXPECT_TRUE(kZero == a); + a *= static_cast (123); + EXPECT_TRUE(kZero == a); + + BigInteger b = kOne; + b *= static_cast(1); + EXPECT_TRUE(kOne == b); + b *= static_cast(0); + EXPECT_TRUE(kZero == b); + + BigInteger c(123); + c *= static_cast(456u); + EXPECT_TRUE(BigInteger(123u * 456u) == c); + c *= 0xFFFFFFFFu; + EXPECT_TRUE(BIGINTEGER_LITERAL("240896125641960") == c); + c *= 0xFFFFFFFFu; + EXPECT_TRUE(BIGINTEGER_LITERAL("1034640981124429079698200") == c); +} + +TEST(BigInteger, LeftShift) { + BigInteger a = kZero; + a <<= 1; + EXPECT_TRUE(kZero == a); + a <<= 64; + EXPECT_TRUE(kZero == a); + + a = BigInteger(123); + a <<= 0; + EXPECT_TRUE(BigInteger(123) == a); + a <<= 1; + EXPECT_TRUE(BigInteger(246) == a); + a <<= 64; + EXPECT_TRUE(BIGINTEGER_LITERAL("4537899042132549697536") == a); + a <<= 99; + EXPECT_TRUE(BIGINTEGER_LITERAL("2876235222267216943024851750785644982682875244576768") == a); + + a = 1; + a <<= 64; // a.count_ != 1 + a <<= 256; // interShift == 0 + EXPECT_TRUE(BIGINTEGER_LITERAL("2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936576") == a); +} + +TEST(BigInteger, Compare) { + EXPECT_EQ(0, kZero.Compare(kZero)); + EXPECT_EQ(1, kOne.Compare(kZero)); + EXPECT_EQ(-1, kZero.Compare(kOne)); + EXPECT_EQ(0, kUint64Max.Compare(kUint64Max)); + EXPECT_EQ(0, kTwo64.Compare(kTwo64)); + EXPECT_EQ(-1, kUint64Max.Compare(kTwo64)); + EXPECT_EQ(1, kTwo64.Compare(kUint64Max)); +} diff --git a/deps/rapidjson/test/unittest/clzlltest.cpp b/deps/rapidjson/test/unittest/clzlltest.cpp new file mode 100644 index 0000000..ad465e1 --- /dev/null +++ b/deps/rapidjson/test/unittest/clzlltest.cpp @@ -0,0 +1,34 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/internal/clzll.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +#endif + +using namespace rapidjson::internal; + +TEST(clzll, normal) { + EXPECT_EQ(clzll(1), 63U); + EXPECT_EQ(clzll(2), 62U); + EXPECT_EQ(clzll(12), 60U); + EXPECT_EQ(clzll(0x0000000080000001UL), 32U); + EXPECT_EQ(clzll(0x8000000000000001UL), 0U); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/cursorstreamwrappertest.cpp b/deps/rapidjson/test/unittest/cursorstreamwrappertest.cpp new file mode 100644 index 0000000..49e3d5e --- /dev/null +++ b/deps/rapidjson/test/unittest/cursorstreamwrappertest.cpp @@ -0,0 +1,115 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/document.h" +#include "rapidjson/cursorstreamwrapper.h" + +using namespace rapidjson; + +// static const char json[] = "{\"string\"\n\n:\"my string\",\"array\"\n:[\"1\", \"2\", \"3\"]}"; + +static bool testJson(const char *json, size_t &line, size_t &col) { + StringStream ss(json); + CursorStreamWrapper csw(ss); + Document document; + document.ParseStream(csw); + bool ret = document.HasParseError(); + if (ret) { + col = csw.GetColumn(); + line = csw.GetLine(); + } + return ret; +} + +TEST(CursorStreamWrapper, MissingFirstBracket) { + const char json[] = "\"string\"\n\n:\"my string\",\"array\"\n:[\"1\", \"2\", \"3\"]}"; + size_t col, line; + bool ret = testJson(json, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 3u); + EXPECT_EQ(col, 0u); +} + +TEST(CursorStreamWrapper, MissingQuotes) { + const char json[] = "{\"string\n\n:\"my string\",\"array\"\n:[\"1\", \"2\", \"3\"]}"; + size_t col, line; + bool ret = testJson(json, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 1u); + EXPECT_EQ(col, 8u); +} + +TEST(CursorStreamWrapper, MissingColon) { + const char json[] = "{\"string\"\n\n\"my string\",\"array\"\n:[\"1\", \"2\", \"3\"]}"; + size_t col, line; + bool ret = testJson(json, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 3u); + EXPECT_EQ(col, 0u); +} + +TEST(CursorStreamWrapper, MissingSecondQuotes) { + const char json[] = "{\"string\"\n\n:my string\",\"array\"\n:[\"1\", \"2\", \"3\"]}"; + size_t col, line; + bool ret = testJson(json, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 3u); + EXPECT_EQ(col, 1u); +} + +TEST(CursorStreamWrapper, MissingComma) { + const char json[] = "{\"string\"\n\n:\"my string\"\"array\"\n:[\"1\", \"2\", \"3\"]}"; + size_t col, line; + bool ret = testJson(json, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 3u); + EXPECT_EQ(col, 12u); +} + +TEST(CursorStreamWrapper, MissingArrayBracket) { + const char json[] = "{\"string\"\n\n:\"my string\",\"array\"\n:\"1\", \"2\", \"3\"]}"; + size_t col, line; + bool ret = testJson(json, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 4u); + EXPECT_EQ(col, 9u); +} + +TEST(CursorStreamWrapper, MissingArrayComma) { + const char json[] = "{\"string\"\n\n:\"my string\",\"array\"\n:[\"1\" \"2\", \"3\"]}"; + size_t col, line; + bool ret = testJson(json, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 4u); + EXPECT_EQ(col, 6u); +} + +TEST(CursorStreamWrapper, MissingLastArrayBracket) { + const char json8[] = "{\"string\"\n\n:\"my string\",\"array\"\n:[\"1\", \"2\", \"3\"}"; + size_t col, line; + bool ret = testJson(json8, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 4u); + EXPECT_EQ(col, 15u); +} + +TEST(CursorStreamWrapper, MissingLastBracket) { + const char json9[] = "{\"string\"\n\n:\"my string\",\"array\"\n:[\"1\", \"2\", \"3\"]"; + size_t col, line; + bool ret = testJson(json9, line, col); + EXPECT_TRUE(ret); + EXPECT_EQ(line, 4u); + EXPECT_EQ(col, 16u); +} diff --git a/deps/rapidjson/test/unittest/documenttest.cpp b/deps/rapidjson/test/unittest/documenttest.cpp new file mode 100644 index 0000000..c3d1e48 --- /dev/null +++ b/deps/rapidjson/test/unittest/documenttest.cpp @@ -0,0 +1,674 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/stringbuffer.h" +#include +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +RAPIDJSON_DIAG_OFF(missing-variable-declarations) +#endif + +using namespace rapidjson; + +template +void ParseCheck(DocumentType& doc) { + typedef typename DocumentType::ValueType ValueType; + + EXPECT_FALSE(doc.HasParseError()); + if (doc.HasParseError()) + printf("Error: %d at %zu\n", static_cast(doc.GetParseError()), doc.GetErrorOffset()); + EXPECT_TRUE(static_cast(doc)); + + EXPECT_TRUE(doc.IsObject()); + + EXPECT_TRUE(doc.HasMember("hello")); + const ValueType& hello = doc["hello"]; + EXPECT_TRUE(hello.IsString()); + EXPECT_STREQ("world", hello.GetString()); + + EXPECT_TRUE(doc.HasMember("t")); + const ValueType& t = doc["t"]; + EXPECT_TRUE(t.IsTrue()); + + EXPECT_TRUE(doc.HasMember("f")); + const ValueType& f = doc["f"]; + EXPECT_TRUE(f.IsFalse()); + + EXPECT_TRUE(doc.HasMember("n")); + const ValueType& n = doc["n"]; + EXPECT_TRUE(n.IsNull()); + + EXPECT_TRUE(doc.HasMember("i")); + const ValueType& i = doc["i"]; + EXPECT_TRUE(i.IsNumber()); + EXPECT_EQ(123, i.GetInt()); + + EXPECT_TRUE(doc.HasMember("pi")); + const ValueType& pi = doc["pi"]; + EXPECT_TRUE(pi.IsNumber()); + EXPECT_DOUBLE_EQ(3.1416, pi.GetDouble()); + + EXPECT_TRUE(doc.HasMember("a")); + const ValueType& a = doc["a"]; + EXPECT_TRUE(a.IsArray()); + EXPECT_EQ(4u, a.Size()); + for (SizeType j = 0; j < 4; j++) + EXPECT_EQ(j + 1, a[j].GetUint()); +} + +template +void ParseTest() { + typedef GenericDocument, Allocator, StackAllocator> DocumentType; + DocumentType doc; + + const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + + doc.Parse(json); + ParseCheck(doc); + + doc.SetNull(); + StringStream s(json); + doc.template ParseStream<0>(s); + ParseCheck(doc); + + doc.SetNull(); + char *buffer = strdup(json); + doc.ParseInsitu(buffer); + ParseCheck(doc); + free(buffer); + + // Parse(const Ch*, size_t) + size_t length = strlen(json); + buffer = reinterpret_cast(malloc(length * 2)); + memcpy(buffer, json, length); + memset(buffer + length, 'X', length); +#if RAPIDJSON_HAS_STDSTRING + std::string s2(buffer, length); // backup buffer +#endif + doc.SetNull(); + doc.Parse(buffer, length); + free(buffer); + ParseCheck(doc); + +#if RAPIDJSON_HAS_STDSTRING + // Parse(std::string) + doc.SetNull(); + doc.Parse(s2); + ParseCheck(doc); +#endif +} + +TEST(Document, Parse) { + ParseTest, CrtAllocator>(); + ParseTest, MemoryPoolAllocator<> >(); + ParseTest >(); + ParseTest(); +} + +TEST(Document, UnchangedOnParseError) { + Document doc; + doc.SetArray().PushBack(0, doc.GetAllocator()); + + ParseResult noError; + EXPECT_TRUE(noError); + + ParseResult err = doc.Parse("{]"); + EXPECT_TRUE(doc.HasParseError()); + EXPECT_NE(err, noError); + EXPECT_NE(err.Code(), noError); + EXPECT_NE(noError, doc.GetParseError()); + EXPECT_EQ(err.Code(), doc.GetParseError()); + EXPECT_EQ(err.Offset(), doc.GetErrorOffset()); + EXPECT_TRUE(doc.IsArray()); + EXPECT_EQ(doc.Size(), 1u); + + err = doc.Parse("{}"); + EXPECT_FALSE(doc.HasParseError()); + EXPECT_FALSE(err.IsError()); + EXPECT_TRUE(err); + EXPECT_EQ(err, noError); + EXPECT_EQ(err.Code(), noError); + EXPECT_EQ(err.Code(), doc.GetParseError()); + EXPECT_EQ(err.Offset(), doc.GetErrorOffset()); + EXPECT_TRUE(doc.IsObject()); + EXPECT_EQ(doc.MemberCount(), 0u); +} + +static FILE* OpenEncodedFile(const char* filename) { + const char *paths[] = { + "encodings", + "bin/encodings", + "../bin/encodings", + "../../bin/encodings", + "../../../bin/encodings" + }; + char buffer[1024]; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + sprintf(buffer, "%s/%s", paths[i], filename); + FILE *fp = fopen(buffer, "rb"); + if (fp) + return fp; + } + return 0; +} + +TEST(Document, Parse_Encoding) { + const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "; + + typedef GenericDocument > DocumentType; + DocumentType doc; + + // Parse(const SourceEncoding::Ch*) + // doc.Parse >(json); + // EXPECT_FALSE(doc.HasParseError()); + // EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world")); + + // Parse(const SourceEncoding::Ch*, size_t) + size_t length = strlen(json); + char* buffer = reinterpret_cast(malloc(length * 2)); + memcpy(buffer, json, length); + memset(buffer + length, 'X', length); +#if RAPIDJSON_HAS_STDSTRING + std::string s2(buffer, length); // backup buffer +#endif + doc.SetNull(); + doc.Parse >(buffer, length); + free(buffer); + EXPECT_FALSE(doc.HasParseError()); + if (doc.HasParseError()) + printf("Error: %d at %zu\n", static_cast(doc.GetParseError()), doc.GetErrorOffset()); + EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world")); + +#if RAPIDJSON_HAS_STDSTRING + // Parse(std::string) + doc.SetNull(); + +#if defined(_MSC_VER) && _MSC_VER < 1800 + doc.Parse >(s2.c_str()); // VS2010 or below cannot handle templated function overloading. Use const char* instead. +#else + doc.Parse >(s2); +#endif + EXPECT_FALSE(doc.HasParseError()); + EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world")); +#endif +} + +TEST(Document, ParseStream_EncodedInputStream) { + // UTF8 -> UTF16 + FILE* fp = OpenEncodedFile("utf8.json"); + char buffer[256]; + FileReadStream bis(fp, buffer, sizeof(buffer)); + EncodedInputStream, FileReadStream> eis(bis); + + GenericDocument > d; + d.ParseStream<0, UTF8<> >(eis); + EXPECT_FALSE(d.HasParseError()); + + fclose(fp); + + wchar_t expected[] = L"I can eat glass and it doesn't hurt me."; + GenericValue >& v = d[L"en"]; + EXPECT_TRUE(v.IsString()); + EXPECT_EQ(sizeof(expected) / sizeof(wchar_t) - 1, v.GetStringLength()); + EXPECT_EQ(0, StrCmp(expected, v.GetString())); + + // UTF16 -> UTF8 in memory + StringBuffer bos; + typedef EncodedOutputStream, StringBuffer> OutputStream; + OutputStream eos(bos, false); // Not writing BOM + { + Writer, UTF8<> > writer(eos); + d.Accept(writer); + } + + // Condense the original file and compare. + fp = OpenEncodedFile("utf8.json"); + FileReadStream is(fp, buffer, sizeof(buffer)); + Reader reader; + StringBuffer bos2; + Writer writer2(bos2); + reader.Parse(is, writer2); + fclose(fp); + + EXPECT_EQ(bos.GetSize(), bos2.GetSize()); + EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); +} + +TEST(Document, ParseStream_AutoUTFInputStream) { + // Any -> UTF8 + FILE* fp = OpenEncodedFile("utf32be.json"); + char buffer[256]; + FileReadStream bis(fp, buffer, sizeof(buffer)); + AutoUTFInputStream eis(bis); + + Document d; + d.ParseStream<0, AutoUTF >(eis); + EXPECT_FALSE(d.HasParseError()); + + fclose(fp); + + char expected[] = "I can eat glass and it doesn't hurt me."; + Value& v = d["en"]; + EXPECT_TRUE(v.IsString()); + EXPECT_EQ(sizeof(expected) - 1, v.GetStringLength()); + EXPECT_EQ(0, StrCmp(expected, v.GetString())); + + // UTF8 -> UTF8 in memory + StringBuffer bos; + Writer writer(bos); + d.Accept(writer); + + // Condense the original file and compare. + fp = OpenEncodedFile("utf8.json"); + FileReadStream is(fp, buffer, sizeof(buffer)); + Reader reader; + StringBuffer bos2; + Writer writer2(bos2); + reader.Parse(is, writer2); + fclose(fp); + + EXPECT_EQ(bos.GetSize(), bos2.GetSize()); + EXPECT_EQ(0, memcmp(bos.GetString(), bos2.GetString(), bos2.GetSize())); +} + +TEST(Document, Swap) { + Document d1; + Document::AllocatorType& a = d1.GetAllocator(); + + d1.SetArray().PushBack(1, a).PushBack(2, a); + + Value o; + o.SetObject().AddMember("a", 1, a); + + // Swap between Document and Value + d1.Swap(o); + EXPECT_TRUE(d1.IsObject()); + EXPECT_TRUE(o.IsArray()); + + d1.Swap(o); + EXPECT_TRUE(d1.IsArray()); + EXPECT_TRUE(o.IsObject()); + + o.Swap(d1); + EXPECT_TRUE(d1.IsObject()); + EXPECT_TRUE(o.IsArray()); + + // Swap between Document and Document + Document d2; + d2.SetArray().PushBack(3, a); + d1.Swap(d2); + EXPECT_TRUE(d1.IsArray()); + EXPECT_TRUE(d2.IsObject()); + EXPECT_EQ(&d2.GetAllocator(), &a); + + // reset value + Value().Swap(d1); + EXPECT_TRUE(d1.IsNull()); + + // reset document, including allocator + // so clear o before so that it doesnt contain dangling elements + o.Clear(); + Document().Swap(d2); + EXPECT_TRUE(d2.IsNull()); + EXPECT_NE(&d2.GetAllocator(), &a); + + // testing std::swap compatibility + d1.SetBool(true); + using std::swap; + swap(d1, d2); + EXPECT_TRUE(d1.IsNull()); + EXPECT_TRUE(d2.IsTrue()); + + swap(o, d2); + EXPECT_TRUE(o.IsTrue()); + EXPECT_TRUE(d2.IsArray()); +} + + +// This should be slow due to assignment in inner-loop. +struct OutputStringStream : public std::ostringstream { + typedef char Ch; + + virtual ~OutputStringStream(); + + void Put(char c) { + put(c); + } + void Flush() {} +}; + +OutputStringStream::~OutputStringStream() {} + +TEST(Document, AcceptWriter) { + Document doc; + doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "); + + OutputStringStream os; + Writer writer(os); + doc.Accept(writer); + + EXPECT_EQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}", os.str()); +} + +TEST(Document, UserBuffer) { + typedef GenericDocument, MemoryPoolAllocator<>, MemoryPoolAllocator<> > DocumentType; + char valueBuffer[4096]; + char parseBuffer[1024]; + MemoryPoolAllocator<> valueAllocator(valueBuffer, sizeof(valueBuffer)); + MemoryPoolAllocator<> parseAllocator(parseBuffer, sizeof(parseBuffer)); + DocumentType doc(&valueAllocator, sizeof(parseBuffer) / 2, &parseAllocator); + doc.Parse(" { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } "); + EXPECT_FALSE(doc.HasParseError()); + EXPECT_LE(valueAllocator.Size(), sizeof(valueBuffer)); + EXPECT_LE(parseAllocator.Size(), sizeof(parseBuffer)); + + // Cover MemoryPoolAllocator::Capacity() + EXPECT_LE(valueAllocator.Size(), valueAllocator.Capacity()); + EXPECT_LE(parseAllocator.Size(), parseAllocator.Capacity()); +} + +// Issue 226: Value of string type should not point to NULL +TEST(Document, AssertAcceptInvalidNameType) { + Document doc; + doc.SetObject(); + doc.AddMember("a", 0, doc.GetAllocator()); + doc.FindMember("a")->name.SetNull(); // Change name to non-string type. + + OutputStringStream os; + Writer writer(os); + ASSERT_THROW(doc.Accept(writer), AssertException); +} + +// Issue 44: SetStringRaw doesn't work with wchar_t +TEST(Document, UTF16_Document) { + GenericDocument< UTF16<> > json; + json.Parse(L"[{\"created_at\":\"Wed Oct 30 17:13:20 +0000 2012\"}]"); + + ASSERT_TRUE(json.IsArray()); + GenericValue< UTF16<> >& v = json[0]; + ASSERT_TRUE(v.IsObject()); + + GenericValue< UTF16<> >& s = v[L"created_at"]; + ASSERT_TRUE(s.IsString()); + + EXPECT_EQ(0, memcmp(L"Wed Oct 30 17:13:20 +0000 2012", s.GetString(), (s.GetStringLength() + 1) * sizeof(wchar_t))); +} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#if 0 // Many old compiler does not support these. Turn it off temporaily. + +#include + +TEST(Document, Traits) { + static_assert(std::is_constructible::value, ""); + static_assert(std::is_default_constructible::value, ""); +#ifndef _MSC_VER + static_assert(!std::is_copy_constructible::value, ""); +#endif + static_assert(std::is_move_constructible::value, ""); + + static_assert(!std::is_nothrow_constructible::value, ""); + static_assert(!std::is_nothrow_default_constructible::value, ""); +#ifndef _MSC_VER + static_assert(!std::is_nothrow_copy_constructible::value, ""); + static_assert(std::is_nothrow_move_constructible::value, ""); +#endif + + static_assert(std::is_assignable::value, ""); +#ifndef _MSC_VER + static_assert(!std::is_copy_assignable::value, ""); +#endif + static_assert(std::is_move_assignable::value, ""); + +#ifndef _MSC_VER + static_assert(std::is_nothrow_assignable::value, ""); +#endif + static_assert(!std::is_nothrow_copy_assignable::value, ""); +#ifndef _MSC_VER + static_assert(std::is_nothrow_move_assignable::value, ""); +#endif + + static_assert( std::is_destructible::value, ""); +#ifndef _MSC_VER + static_assert(std::is_nothrow_destructible::value, ""); +#endif +} + +#endif + +template +struct DocumentMove: public ::testing::Test { +}; + +typedef ::testing::Types< CrtAllocator, MemoryPoolAllocator<> > MoveAllocatorTypes; +TYPED_TEST_CASE(DocumentMove, MoveAllocatorTypes); + +TYPED_TEST(DocumentMove, MoveConstructor) { + typedef TypeParam Allocator; + typedef GenericDocument, Allocator> D; + Allocator allocator; + + D a(&allocator); + a.Parse("[\"one\", \"two\", \"three\"]"); + EXPECT_FALSE(a.HasParseError()); + EXPECT_TRUE(a.IsArray()); + EXPECT_EQ(3u, a.Size()); + EXPECT_EQ(&a.GetAllocator(), &allocator); + + // Document b(a); // does not compile (!is_copy_constructible) + D b(std::move(a)); + EXPECT_TRUE(a.IsNull()); + EXPECT_TRUE(b.IsArray()); + EXPECT_EQ(3u, b.Size()); + EXPECT_THROW(a.GetAllocator(), AssertException); + EXPECT_EQ(&b.GetAllocator(), &allocator); + + b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}"); + EXPECT_FALSE(b.HasParseError()); + EXPECT_TRUE(b.IsObject()); + EXPECT_EQ(2u, b.MemberCount()); + + // Document c = a; // does not compile (!is_copy_constructible) + D c = std::move(b); + EXPECT_TRUE(b.IsNull()); + EXPECT_TRUE(c.IsObject()); + EXPECT_EQ(2u, c.MemberCount()); + EXPECT_THROW(b.GetAllocator(), AssertException); + EXPECT_EQ(&c.GetAllocator(), &allocator); +} + +TYPED_TEST(DocumentMove, MoveConstructorParseError) { + typedef TypeParam Allocator; + typedef GenericDocument, Allocator> D; + + ParseResult noError; + D a; + a.Parse("{ 4 = 4]"); + ParseResult error(a.GetParseError(), a.GetErrorOffset()); + EXPECT_TRUE(a.HasParseError()); + EXPECT_NE(error, noError); + EXPECT_NE(error.Code(), noError); + EXPECT_NE(error.Code(), noError.Code()); + EXPECT_NE(error.Offset(), noError.Offset()); + + D b(std::move(a)); + EXPECT_FALSE(a.HasParseError()); + EXPECT_TRUE(b.HasParseError()); + EXPECT_EQ(a.GetParseError(), noError); + EXPECT_EQ(a.GetParseError(), noError.Code()); + EXPECT_EQ(a.GetErrorOffset(), noError.Offset()); + EXPECT_EQ(b.GetParseError(), error); + EXPECT_EQ(b.GetParseError(), error.Code()); + EXPECT_EQ(b.GetErrorOffset(), error.Offset()); + + D c(std::move(b)); + EXPECT_FALSE(b.HasParseError()); + EXPECT_TRUE(c.HasParseError()); + EXPECT_EQ(b.GetParseError(), noError.Code()); + EXPECT_EQ(c.GetParseError(), error.Code()); + EXPECT_EQ(b.GetErrorOffset(), noError.Offset()); + EXPECT_EQ(c.GetErrorOffset(), error.Offset()); +} + +// This test does not properly use parsing, just for testing. +// It must call ClearStack() explicitly to prevent memory leak. +// But here we cannot as ClearStack() is private. +#if 0 +TYPED_TEST(DocumentMove, MoveConstructorStack) { + typedef TypeParam Allocator; + typedef UTF8<> Encoding; + typedef GenericDocument Document; + + Document a; + size_t defaultCapacity = a.GetStackCapacity(); + + // Trick Document into getting GetStackCapacity() to return non-zero + typedef GenericReader Reader; + Reader reader(&a.GetAllocator()); + GenericStringStream is("[\"one\", \"two\", \"three\"]"); + reader.template Parse(is, a); + size_t capacity = a.GetStackCapacity(); + EXPECT_GT(capacity, 0u); + + Document b(std::move(a)); + EXPECT_EQ(a.GetStackCapacity(), defaultCapacity); + EXPECT_EQ(b.GetStackCapacity(), capacity); + + Document c = std::move(b); + EXPECT_EQ(b.GetStackCapacity(), defaultCapacity); + EXPECT_EQ(c.GetStackCapacity(), capacity); +} +#endif + +TYPED_TEST(DocumentMove, MoveAssignment) { + typedef TypeParam Allocator; + typedef GenericDocument, Allocator> D; + Allocator allocator; + + D a(&allocator); + a.Parse("[\"one\", \"two\", \"three\"]"); + EXPECT_FALSE(a.HasParseError()); + EXPECT_TRUE(a.IsArray()); + EXPECT_EQ(3u, a.Size()); + EXPECT_EQ(&a.GetAllocator(), &allocator); + + // Document b; b = a; // does not compile (!is_copy_assignable) + D b; + b = std::move(a); + EXPECT_TRUE(a.IsNull()); + EXPECT_TRUE(b.IsArray()); + EXPECT_EQ(3u, b.Size()); + EXPECT_THROW(a.GetAllocator(), AssertException); + EXPECT_EQ(&b.GetAllocator(), &allocator); + + b.Parse("{\"Foo\": \"Bar\", \"Baz\": 42}"); + EXPECT_FALSE(b.HasParseError()); + EXPECT_TRUE(b.IsObject()); + EXPECT_EQ(2u, b.MemberCount()); + + // Document c; c = a; // does not compile (see static_assert) + D c; + c = std::move(b); + EXPECT_TRUE(b.IsNull()); + EXPECT_TRUE(c.IsObject()); + EXPECT_EQ(2u, c.MemberCount()); + EXPECT_THROW(b.GetAllocator(), AssertException); + EXPECT_EQ(&c.GetAllocator(), &allocator); +} + +TYPED_TEST(DocumentMove, MoveAssignmentParseError) { + typedef TypeParam Allocator; + typedef GenericDocument, Allocator> D; + + ParseResult noError; + D a; + a.Parse("{ 4 = 4]"); + ParseResult error(a.GetParseError(), a.GetErrorOffset()); + EXPECT_TRUE(a.HasParseError()); + EXPECT_NE(error.Code(), noError.Code()); + EXPECT_NE(error.Offset(), noError.Offset()); + + D b; + b = std::move(a); + EXPECT_FALSE(a.HasParseError()); + EXPECT_TRUE(b.HasParseError()); + EXPECT_EQ(a.GetParseError(), noError.Code()); + EXPECT_EQ(b.GetParseError(), error.Code()); + EXPECT_EQ(a.GetErrorOffset(), noError.Offset()); + EXPECT_EQ(b.GetErrorOffset(), error.Offset()); + + D c; + c = std::move(b); + EXPECT_FALSE(b.HasParseError()); + EXPECT_TRUE(c.HasParseError()); + EXPECT_EQ(b.GetParseError(), noError.Code()); + EXPECT_EQ(c.GetParseError(), error.Code()); + EXPECT_EQ(b.GetErrorOffset(), noError.Offset()); + EXPECT_EQ(c.GetErrorOffset(), error.Offset()); +} + +// This test does not properly use parsing, just for testing. +// It must call ClearStack() explicitly to prevent memory leak. +// But here we cannot as ClearStack() is private. +#if 0 +TYPED_TEST(DocumentMove, MoveAssignmentStack) { + typedef TypeParam Allocator; + typedef UTF8<> Encoding; + typedef GenericDocument D; + + D a; + size_t defaultCapacity = a.GetStackCapacity(); + + // Trick Document into getting GetStackCapacity() to return non-zero + typedef GenericReader Reader; + Reader reader(&a.GetAllocator()); + GenericStringStream is("[\"one\", \"two\", \"three\"]"); + reader.template Parse(is, a); + size_t capacity = a.GetStackCapacity(); + EXPECT_GT(capacity, 0u); + + D b; + b = std::move(a); + EXPECT_EQ(a.GetStackCapacity(), defaultCapacity); + EXPECT_EQ(b.GetStackCapacity(), capacity); + + D c; + c = std::move(b); + EXPECT_EQ(b.GetStackCapacity(), defaultCapacity); + EXPECT_EQ(c.GetStackCapacity(), capacity); +} +#endif + +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +// Issue 22: Memory corruption via operator= +// Fixed by making unimplemented assignment operator private. +//TEST(Document, Assignment) { +// Document d1; +// Document d2; +// d1 = d2; +//} + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/dtoatest.cpp b/deps/rapidjson/test/unittest/dtoatest.cpp new file mode 100644 index 0000000..3ec8982 --- /dev/null +++ b/deps/rapidjson/test/unittest/dtoatest.cpp @@ -0,0 +1,99 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/internal/dtoa.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(type-limits) +#endif + +using namespace rapidjson::internal; + +TEST(dtoa, normal) { + char buffer[30]; + +#define TEST_DTOA(d, a)\ + *dtoa(d, buffer) = '\0';\ + EXPECT_STREQ(a, buffer) + + TEST_DTOA(0.0, "0.0"); + TEST_DTOA(-0.0, "-0.0"); + TEST_DTOA(1.0, "1.0"); + TEST_DTOA(-1.0, "-1.0"); + TEST_DTOA(1.2345, "1.2345"); + TEST_DTOA(1.2345678, "1.2345678"); + TEST_DTOA(0.123456789012, "0.123456789012"); + TEST_DTOA(1234567.8, "1234567.8"); + TEST_DTOA(-79.39773355813419, "-79.39773355813419"); + TEST_DTOA(-36.973846435546875, "-36.973846435546875"); + TEST_DTOA(0.000001, "0.000001"); + TEST_DTOA(0.0000001, "1e-7"); + TEST_DTOA(1e30, "1e30"); + TEST_DTOA(1.234567890123456e30, "1.234567890123456e30"); + TEST_DTOA(5e-324, "5e-324"); // Min subnormal positive double + TEST_DTOA(2.225073858507201e-308, "2.225073858507201e-308"); // Max subnormal positive double + TEST_DTOA(2.2250738585072014e-308, "2.2250738585072014e-308"); // Min normal positive double + TEST_DTOA(1.7976931348623157e308, "1.7976931348623157e308"); // Max double + +#undef TEST_DTOA +} + +TEST(dtoa, maxDecimalPlaces) { + char buffer[30]; + +#define TEST_DTOA(m, d, a)\ + *dtoa(d, buffer, m) = '\0';\ + EXPECT_STREQ(a, buffer) + + TEST_DTOA(3, 0.0, "0.0"); + TEST_DTOA(1, 0.0, "0.0"); + TEST_DTOA(3, -0.0, "-0.0"); + TEST_DTOA(3, 1.0, "1.0"); + TEST_DTOA(3, -1.0, "-1.0"); + TEST_DTOA(3, 1.2345, "1.234"); + TEST_DTOA(2, 1.2345, "1.23"); + TEST_DTOA(1, 1.2345, "1.2"); + TEST_DTOA(3, 1.2345678, "1.234"); + TEST_DTOA(3, 1.0001, "1.0"); + TEST_DTOA(2, 1.0001, "1.0"); + TEST_DTOA(1, 1.0001, "1.0"); + TEST_DTOA(3, 0.123456789012, "0.123"); + TEST_DTOA(2, 0.123456789012, "0.12"); + TEST_DTOA(1, 0.123456789012, "0.1"); + TEST_DTOA(4, 0.0001, "0.0001"); + TEST_DTOA(3, 0.0001, "0.0"); + TEST_DTOA(2, 0.0001, "0.0"); + TEST_DTOA(1, 0.0001, "0.0"); + TEST_DTOA(3, 1234567.8, "1234567.8"); + TEST_DTOA(3, 1e30, "1e30"); + TEST_DTOA(3, 5e-324, "0.0"); // Min subnormal positive double + TEST_DTOA(3, 2.225073858507201e-308, "0.0"); // Max subnormal positive double + TEST_DTOA(3, 2.2250738585072014e-308, "0.0"); // Min normal positive double + TEST_DTOA(3, 1.7976931348623157e308, "1.7976931348623157e308"); // Max double + TEST_DTOA(5, -0.14000000000000001, "-0.14"); + TEST_DTOA(4, -0.14000000000000001, "-0.14"); + TEST_DTOA(3, -0.14000000000000001, "-0.14"); + TEST_DTOA(3, -0.10000000000000001, "-0.1"); + TEST_DTOA(2, -0.10000000000000001, "-0.1"); + TEST_DTOA(1, -0.10000000000000001, "-0.1"); + +#undef TEST_DTOA +} + + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/encodedstreamtest.cpp b/deps/rapidjson/test/unittest/encodedstreamtest.cpp new file mode 100644 index 0000000..1f0f0e7 --- /dev/null +++ b/deps/rapidjson/test/unittest/encodedstreamtest.cpp @@ -0,0 +1,313 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/memorystream.h" +#include "rapidjson/memorybuffer.h" + +using namespace rapidjson; + +class EncodedStreamTest : public ::testing::Test { +public: + EncodedStreamTest() : json_(), length_() {} + virtual ~EncodedStreamTest(); + + virtual void SetUp() { + json_ = ReadFile("utf8.json", true, &length_); + } + + virtual void TearDown() { + free(json_); + json_ = 0; + } + +private: + EncodedStreamTest(const EncodedStreamTest&); + EncodedStreamTest& operator=(const EncodedStreamTest&); + +protected: + static FILE* Open(const char* filename) { + const char *paths[] = { + "encodings", + "bin/encodings", + "../bin/encodings", + "../../bin/encodings", + "../../../bin/encodings" + }; + char buffer[1024]; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + sprintf(buffer, "%s/%s", paths[i], filename); + FILE *fp = fopen(buffer, "rb"); + if (fp) + return fp; + } + return 0; + } + + static char *ReadFile(const char* filename, bool appendPath, size_t* outLength) { + FILE *fp = appendPath ? Open(filename) : fopen(filename, "rb"); + + if (!fp) { + *outLength = 0; + return 0; + } + + fseek(fp, 0, SEEK_END); + *outLength = static_cast(ftell(fp)); + fseek(fp, 0, SEEK_SET); + char* buffer = static_cast(malloc(*outLength + 1)); + size_t readLength = fread(buffer, 1, *outLength, fp); + buffer[readLength] = '\0'; + fclose(fp); + return buffer; + } + + template + void TestEncodedInputStream(const char* filename) { + // Test FileReadStream + { + char buffer[16]; + FILE *fp = Open(filename); + ASSERT_TRUE(fp != 0); + FileReadStream fs(fp, buffer, sizeof(buffer)); + EncodedInputStream eis(fs); + StringStream s(json_); + + while (eis.Peek() != '\0') { + unsigned expected, actual; + EXPECT_TRUE(UTF8<>::Decode(s, &expected)); + EXPECT_TRUE(MemoryEncoding::Decode(eis, &actual)); + EXPECT_EQ(expected, actual); + } + EXPECT_EQ('\0', s.Peek()); + fclose(fp); + } + + // Test MemoryStream + { + size_t size; + char* data = ReadFile(filename, true, &size); + MemoryStream ms(data, size); + EncodedInputStream eis(ms); + StringStream s(json_); + + while (eis.Peek() != '\0') { + unsigned expected, actual; + EXPECT_TRUE(UTF8<>::Decode(s, &expected)); + EXPECT_TRUE(MemoryEncoding::Decode(eis, &actual)); + EXPECT_EQ(expected, actual); + } + EXPECT_EQ('\0', s.Peek()); + EXPECT_EQ(size, eis.Tell()); + free(data); + } + } + + void TestAutoUTFInputStream(const char *filename, bool expectHasBOM) { + // Test FileReadStream + { + char buffer[16]; + FILE *fp = Open(filename); + ASSERT_TRUE(fp != 0); + FileReadStream fs(fp, buffer, sizeof(buffer)); + AutoUTFInputStream eis(fs); + EXPECT_EQ(expectHasBOM, eis.HasBOM()); + StringStream s(json_); + while (eis.Peek() != '\0') { + unsigned expected, actual; + EXPECT_TRUE(UTF8<>::Decode(s, &expected)); + EXPECT_TRUE(AutoUTF::Decode(eis, &actual)); + EXPECT_EQ(expected, actual); + } + EXPECT_EQ('\0', s.Peek()); + fclose(fp); + } + + // Test MemoryStream + { + size_t size; + char* data = ReadFile(filename, true, &size); + MemoryStream ms(data, size); + AutoUTFInputStream eis(ms); + EXPECT_EQ(expectHasBOM, eis.HasBOM()); + StringStream s(json_); + + while (eis.Peek() != '\0') { + unsigned expected, actual; + EXPECT_TRUE(UTF8<>::Decode(s, &expected)); + EXPECT_TRUE(AutoUTF::Decode(eis, &actual)); + EXPECT_EQ(expected, actual); + } + EXPECT_EQ('\0', s.Peek()); + free(data); + EXPECT_EQ(size, eis.Tell()); + } + } + + template + void TestEncodedOutputStream(const char* expectedFilename, bool putBOM) { + // Test FileWriteStream + { + char filename[L_tmpnam]; + FILE* fp = TempFile(filename); + char buffer[16]; + FileWriteStream os(fp, buffer, sizeof(buffer)); + EncodedOutputStream eos(os, putBOM); + StringStream s(json_); + while (s.Peek() != '\0') { + bool success = Transcoder, MemoryEncoding>::Transcode(s, eos); + EXPECT_TRUE(success); + } + eos.Flush(); + fclose(fp); + EXPECT_TRUE(CompareFile(filename, expectedFilename)); + remove(filename); + } + + // Test MemoryBuffer + { + MemoryBuffer mb; + EncodedOutputStream eos(mb, putBOM); + StringStream s(json_); + while (s.Peek() != '\0') { + bool success = Transcoder, MemoryEncoding>::Transcode(s, eos); + EXPECT_TRUE(success); + } + eos.Flush(); + EXPECT_TRUE(CompareBufferFile(mb.GetBuffer(), mb.GetSize(), expectedFilename)); + } + } + + void TestAutoUTFOutputStream(UTFType type, bool putBOM, const char *expectedFilename) { + // Test FileWriteStream + { + char filename[L_tmpnam]; + FILE* fp = TempFile(filename); + + char buffer[16]; + FileWriteStream os(fp, buffer, sizeof(buffer)); + AutoUTFOutputStream eos(os, type, putBOM); + StringStream s(json_); + while (s.Peek() != '\0') { + bool success = Transcoder, AutoUTF >::Transcode(s, eos); + EXPECT_TRUE(success); + } + eos.Flush(); + fclose(fp); + EXPECT_TRUE(CompareFile(filename, expectedFilename)); + remove(filename); + } + + // Test MemoryBuffer + { + MemoryBuffer mb; + AutoUTFOutputStream eos(mb, type, putBOM); + StringStream s(json_); + while (s.Peek() != '\0') { + bool success = Transcoder, AutoUTF >::Transcode(s, eos); + EXPECT_TRUE(success); + } + eos.Flush(); + EXPECT_TRUE(CompareBufferFile(mb.GetBuffer(), mb.GetSize(), expectedFilename)); + } + } + + bool CompareFile(const char* filename, const char* expectedFilename) { + size_t actualLength, expectedLength; + char* actualBuffer = ReadFile(filename, false, &actualLength); + char* expectedBuffer = ReadFile(expectedFilename, true, &expectedLength); + bool ret = (expectedLength == actualLength) && memcmp(expectedBuffer, actualBuffer, actualLength) == 0; + free(actualBuffer); + free(expectedBuffer); + return ret; + } + + bool CompareBufferFile(const char* actualBuffer, size_t actualLength, const char* expectedFilename) { + size_t expectedLength; + char* expectedBuffer = ReadFile(expectedFilename, true, &expectedLength); + bool ret = (expectedLength == actualLength) && memcmp(expectedBuffer, actualBuffer, actualLength) == 0; + free(expectedBuffer); + return ret; + } + + char *json_; + size_t length_; +}; + +EncodedStreamTest::~EncodedStreamTest() {} + +TEST_F(EncodedStreamTest, EncodedInputStream) { + TestEncodedInputStream, UTF8<> >("utf8.json"); + TestEncodedInputStream, UTF8<> >("utf8bom.json"); + TestEncodedInputStream, UTF16<> >("utf16le.json"); + TestEncodedInputStream, UTF16<> >("utf16lebom.json"); + TestEncodedInputStream, UTF16<> >("utf16be.json"); + TestEncodedInputStream, UTF16<> >("utf16bebom.json"); + TestEncodedInputStream, UTF32<> >("utf32le.json"); + TestEncodedInputStream, UTF32<> >("utf32lebom.json"); + TestEncodedInputStream, UTF32<> >("utf32be.json"); + TestEncodedInputStream, UTF32<> >("utf32bebom.json"); +} + +TEST_F(EncodedStreamTest, AutoUTFInputStream) { + TestAutoUTFInputStream("utf8.json", false); + TestAutoUTFInputStream("utf8bom.json", true); + TestAutoUTFInputStream("utf16le.json", false); + TestAutoUTFInputStream("utf16lebom.json",true); + TestAutoUTFInputStream("utf16be.json", false); + TestAutoUTFInputStream("utf16bebom.json",true); + TestAutoUTFInputStream("utf32le.json", false); + TestAutoUTFInputStream("utf32lebom.json",true); + TestAutoUTFInputStream("utf32be.json", false); + TestAutoUTFInputStream("utf32bebom.json", true); + + { + // Auto detection fail, use user defined UTF type + const char json[] = "{ }"; + MemoryStream ms(json, sizeof(json)); + AutoUTFInputStream eis(ms, kUTF8); + EXPECT_FALSE(eis.HasBOM()); + EXPECT_EQ(kUTF8, eis.GetType()); + } +} + +TEST_F(EncodedStreamTest, EncodedOutputStream) { + TestEncodedOutputStream, UTF8<> >("utf8.json", false); + TestEncodedOutputStream, UTF8<> >("utf8bom.json", true); + TestEncodedOutputStream, UTF16<> >("utf16le.json", false); + TestEncodedOutputStream, UTF16<> >("utf16lebom.json",true); + TestEncodedOutputStream, UTF16<> >("utf16be.json", false); + TestEncodedOutputStream, UTF16<> >("utf16bebom.json",true); + TestEncodedOutputStream, UTF32<> >("utf32le.json", false); + TestEncodedOutputStream, UTF32<> >("utf32lebom.json",true); + TestEncodedOutputStream, UTF32<> >("utf32be.json", false); + TestEncodedOutputStream, UTF32<> >("utf32bebom.json",true); +} + +TEST_F(EncodedStreamTest, AutoUTFOutputStream) { + TestAutoUTFOutputStream(kUTF8, false, "utf8.json"); + TestAutoUTFOutputStream(kUTF8, true, "utf8bom.json"); + TestAutoUTFOutputStream(kUTF16LE, false, "utf16le.json"); + TestAutoUTFOutputStream(kUTF16LE, true, "utf16lebom.json"); + TestAutoUTFOutputStream(kUTF16BE, false, "utf16be.json"); + TestAutoUTFOutputStream(kUTF16BE, true, "utf16bebom.json"); + TestAutoUTFOutputStream(kUTF32LE, false, "utf32le.json"); + TestAutoUTFOutputStream(kUTF32LE, true, "utf32lebom.json"); + TestAutoUTFOutputStream(kUTF32BE, false, "utf32be.json"); + TestAutoUTFOutputStream(kUTF32BE, true, "utf32bebom.json"); +} diff --git a/deps/rapidjson/test/unittest/encodingstest.cpp b/deps/rapidjson/test/unittest/encodingstest.cpp new file mode 100644 index 0000000..455881e --- /dev/null +++ b/deps/rapidjson/test/unittest/encodingstest.cpp @@ -0,0 +1,451 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/stringbuffer.h" + +using namespace rapidjson; + +// Verification of encoders/decoders with Hoehrmann's UTF8 decoder + +// http://www.unicode.org/Public/UNIDATA/Blocks.txt +static const unsigned kCodepointRanges[] = { + 0x0000, 0x007F, // Basic Latin + 0x0080, 0x00FF, // Latin-1 Supplement + 0x0100, 0x017F, // Latin Extended-A + 0x0180, 0x024F, // Latin Extended-B + 0x0250, 0x02AF, // IPA Extensions + 0x02B0, 0x02FF, // Spacing Modifier Letters + 0x0300, 0x036F, // Combining Diacritical Marks + 0x0370, 0x03FF, // Greek and Coptic + 0x0400, 0x04FF, // Cyrillic + 0x0500, 0x052F, // Cyrillic Supplement + 0x0530, 0x058F, // Armenian + 0x0590, 0x05FF, // Hebrew + 0x0600, 0x06FF, // Arabic + 0x0700, 0x074F, // Syriac + 0x0750, 0x077F, // Arabic Supplement + 0x0780, 0x07BF, // Thaana + 0x07C0, 0x07FF, // NKo + 0x0800, 0x083F, // Samaritan + 0x0840, 0x085F, // Mandaic + 0x0900, 0x097F, // Devanagari + 0x0980, 0x09FF, // Bengali + 0x0A00, 0x0A7F, // Gurmukhi + 0x0A80, 0x0AFF, // Gujarati + 0x0B00, 0x0B7F, // Oriya + 0x0B80, 0x0BFF, // Tamil + 0x0C00, 0x0C7F, // Telugu + 0x0C80, 0x0CFF, // Kannada + 0x0D00, 0x0D7F, // Malayalam + 0x0D80, 0x0DFF, // Sinhala + 0x0E00, 0x0E7F, // Thai + 0x0E80, 0x0EFF, // Lao + 0x0F00, 0x0FFF, // Tibetan + 0x1000, 0x109F, // Myanmar + 0x10A0, 0x10FF, // Georgian + 0x1100, 0x11FF, // Hangul Jamo + 0x1200, 0x137F, // Ethiopic + 0x1380, 0x139F, // Ethiopic Supplement + 0x13A0, 0x13FF, // Cherokee + 0x1400, 0x167F, // Unified Canadian Aboriginal Syllabics + 0x1680, 0x169F, // Ogham + 0x16A0, 0x16FF, // Runic + 0x1700, 0x171F, // Tagalog + 0x1720, 0x173F, // Hanunoo + 0x1740, 0x175F, // Buhid + 0x1760, 0x177F, // Tagbanwa + 0x1780, 0x17FF, // Khmer + 0x1800, 0x18AF, // Mongolian + 0x18B0, 0x18FF, // Unified Canadian Aboriginal Syllabics Extended + 0x1900, 0x194F, // Limbu + 0x1950, 0x197F, // Tai Le + 0x1980, 0x19DF, // New Tai Lue + 0x19E0, 0x19FF, // Khmer Symbols + 0x1A00, 0x1A1F, // Buginese + 0x1A20, 0x1AAF, // Tai Tham + 0x1B00, 0x1B7F, // Balinese + 0x1B80, 0x1BBF, // Sundanese + 0x1BC0, 0x1BFF, // Batak + 0x1C00, 0x1C4F, // Lepcha + 0x1C50, 0x1C7F, // Ol Chiki + 0x1CD0, 0x1CFF, // Vedic Extensions + 0x1D00, 0x1D7F, // Phonetic Extensions + 0x1D80, 0x1DBF, // Phonetic Extensions Supplement + 0x1DC0, 0x1DFF, // Combining Diacritical Marks Supplement + 0x1E00, 0x1EFF, // Latin Extended Additional + 0x1F00, 0x1FFF, // Greek Extended + 0x2000, 0x206F, // General Punctuation + 0x2070, 0x209F, // Superscripts and Subscripts + 0x20A0, 0x20CF, // Currency Symbols + 0x20D0, 0x20FF, // Combining Diacritical Marks for Symbols + 0x2100, 0x214F, // Letterlike Symbols + 0x2150, 0x218F, // Number Forms + 0x2190, 0x21FF, // Arrows + 0x2200, 0x22FF, // Mathematical Operators + 0x2300, 0x23FF, // Miscellaneous Technical + 0x2400, 0x243F, // Control Pictures + 0x2440, 0x245F, // Optical Character Recognition + 0x2460, 0x24FF, // Enclosed Alphanumerics + 0x2500, 0x257F, // Box Drawing + 0x2580, 0x259F, // Block Elements + 0x25A0, 0x25FF, // Geometric Shapes + 0x2600, 0x26FF, // Miscellaneous Symbols + 0x2700, 0x27BF, // Dingbats + 0x27C0, 0x27EF, // Miscellaneous Mathematical Symbols-A + 0x27F0, 0x27FF, // Supplemental Arrows-A + 0x2800, 0x28FF, // Braille Patterns + 0x2900, 0x297F, // Supplemental Arrows-B + 0x2980, 0x29FF, // Miscellaneous Mathematical Symbols-B + 0x2A00, 0x2AFF, // Supplemental Mathematical Operators + 0x2B00, 0x2BFF, // Miscellaneous Symbols and Arrows + 0x2C00, 0x2C5F, // Glagolitic + 0x2C60, 0x2C7F, // Latin Extended-C + 0x2C80, 0x2CFF, // Coptic + 0x2D00, 0x2D2F, // Georgian Supplement + 0x2D30, 0x2D7F, // Tifinagh + 0x2D80, 0x2DDF, // Ethiopic Extended + 0x2DE0, 0x2DFF, // Cyrillic Extended-A + 0x2E00, 0x2E7F, // Supplemental Punctuation + 0x2E80, 0x2EFF, // CJK Radicals Supplement + 0x2F00, 0x2FDF, // Kangxi Radicals + 0x2FF0, 0x2FFF, // Ideographic Description Characters + 0x3000, 0x303F, // CJK Symbols and Punctuation + 0x3040, 0x309F, // Hiragana + 0x30A0, 0x30FF, // Katakana + 0x3100, 0x312F, // Bopomofo + 0x3130, 0x318F, // Hangul Compatibility Jamo + 0x3190, 0x319F, // Kanbun + 0x31A0, 0x31BF, // Bopomofo Extended + 0x31C0, 0x31EF, // CJK Strokes + 0x31F0, 0x31FF, // Katakana Phonetic Extensions + 0x3200, 0x32FF, // Enclosed CJK Letters and Months + 0x3300, 0x33FF, // CJK Compatibility + 0x3400, 0x4DBF, // CJK Unified Ideographs Extension A + 0x4DC0, 0x4DFF, // Yijing Hexagram Symbols + 0x4E00, 0x9FFF, // CJK Unified Ideographs + 0xA000, 0xA48F, // Yi Syllables + 0xA490, 0xA4CF, // Yi Radicals + 0xA4D0, 0xA4FF, // Lisu + 0xA500, 0xA63F, // Vai + 0xA640, 0xA69F, // Cyrillic Extended-B + 0xA6A0, 0xA6FF, // Bamum + 0xA700, 0xA71F, // Modifier Tone Letters + 0xA720, 0xA7FF, // Latin Extended-D + 0xA800, 0xA82F, // Syloti Nagri + 0xA830, 0xA83F, // Common Indic Number Forms + 0xA840, 0xA87F, // Phags-pa + 0xA880, 0xA8DF, // Saurashtra + 0xA8E0, 0xA8FF, // Devanagari Extended + 0xA900, 0xA92F, // Kayah Li + 0xA930, 0xA95F, // Rejang + 0xA960, 0xA97F, // Hangul Jamo Extended-A + 0xA980, 0xA9DF, // Javanese + 0xAA00, 0xAA5F, // Cham + 0xAA60, 0xAA7F, // Myanmar Extended-A + 0xAA80, 0xAADF, // Tai Viet + 0xAB00, 0xAB2F, // Ethiopic Extended-A + 0xABC0, 0xABFF, // Meetei Mayek + 0xAC00, 0xD7AF, // Hangul Syllables + 0xD7B0, 0xD7FF, // Hangul Jamo Extended-B + //0xD800, 0xDB7F, // High Surrogates + //0xDB80, 0xDBFF, // High Private Use Surrogates + //0xDC00, 0xDFFF, // Low Surrogates + 0xE000, 0xF8FF, // Private Use Area + 0xF900, 0xFAFF, // CJK Compatibility Ideographs + 0xFB00, 0xFB4F, // Alphabetic Presentation Forms + 0xFB50, 0xFDFF, // Arabic Presentation Forms-A + 0xFE00, 0xFE0F, // Variation Selectors + 0xFE10, 0xFE1F, // Vertical Forms + 0xFE20, 0xFE2F, // Combining Half Marks + 0xFE30, 0xFE4F, // CJK Compatibility Forms + 0xFE50, 0xFE6F, // Small Form Variants + 0xFE70, 0xFEFF, // Arabic Presentation Forms-B + 0xFF00, 0xFFEF, // Halfwidth and Fullwidth Forms + 0xFFF0, 0xFFFF, // Specials + 0x10000, 0x1007F, // Linear B Syllabary + 0x10080, 0x100FF, // Linear B Ideograms + 0x10100, 0x1013F, // Aegean Numbers + 0x10140, 0x1018F, // Ancient Greek Numbers + 0x10190, 0x101CF, // Ancient Symbols + 0x101D0, 0x101FF, // Phaistos Disc + 0x10280, 0x1029F, // Lycian + 0x102A0, 0x102DF, // Carian + 0x10300, 0x1032F, // Old Italic + 0x10330, 0x1034F, // Gothic + 0x10380, 0x1039F, // Ugaritic + 0x103A0, 0x103DF, // Old Persian + 0x10400, 0x1044F, // Deseret + 0x10450, 0x1047F, // Shavian + 0x10480, 0x104AF, // Osmanya + 0x10800, 0x1083F, // Cypriot Syllabary + 0x10840, 0x1085F, // Imperial Aramaic + 0x10900, 0x1091F, // Phoenician + 0x10920, 0x1093F, // Lydian + 0x10A00, 0x10A5F, // Kharoshthi + 0x10A60, 0x10A7F, // Old South Arabian + 0x10B00, 0x10B3F, // Avestan + 0x10B40, 0x10B5F, // Inscriptional Parthian + 0x10B60, 0x10B7F, // Inscriptional Pahlavi + 0x10C00, 0x10C4F, // Old Turkic + 0x10E60, 0x10E7F, // Rumi Numeral Symbols + 0x11000, 0x1107F, // Brahmi + 0x11080, 0x110CF, // Kaithi + 0x12000, 0x123FF, // Cuneiform + 0x12400, 0x1247F, // Cuneiform Numbers and Punctuation + 0x13000, 0x1342F, // Egyptian Hieroglyphs + 0x16800, 0x16A3F, // Bamum Supplement + 0x1B000, 0x1B0FF, // Kana Supplement + 0x1D000, 0x1D0FF, // Byzantine Musical Symbols + 0x1D100, 0x1D1FF, // Musical Symbols + 0x1D200, 0x1D24F, // Ancient Greek Musical Notation + 0x1D300, 0x1D35F, // Tai Xuan Jing Symbols + 0x1D360, 0x1D37F, // Counting Rod Numerals + 0x1D400, 0x1D7FF, // Mathematical Alphanumeric Symbols + 0x1F000, 0x1F02F, // Mahjong Tiles + 0x1F030, 0x1F09F, // Domino Tiles + 0x1F0A0, 0x1F0FF, // Playing Cards + 0x1F100, 0x1F1FF, // Enclosed Alphanumeric Supplement + 0x1F200, 0x1F2FF, // Enclosed Ideographic Supplement + 0x1F300, 0x1F5FF, // Miscellaneous Symbols And Pictographs + 0x1F600, 0x1F64F, // Emoticons + 0x1F680, 0x1F6FF, // Transport And Map Symbols + 0x1F700, 0x1F77F, // Alchemical Symbols + 0x20000, 0x2A6DF, // CJK Unified Ideographs Extension B + 0x2A700, 0x2B73F, // CJK Unified Ideographs Extension C + 0x2B740, 0x2B81F, // CJK Unified Ideographs Extension D + 0x2F800, 0x2FA1F, // CJK Compatibility Ideographs Supplement + 0xE0000, 0xE007F, // Tags + 0xE0100, 0xE01EF, // Variation Selectors Supplement + 0xF0000, 0xFFFFF, // Supplementary Private Use Area-A + 0x100000, 0x10FFFF, // Supplementary Private Use Area-B + 0xFFFFFFFF +}; + +// Copyright (c) 2008-2010 Bjoern Hoehrmann +// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. + +#define UTF8_ACCEPT 0u + +static const unsigned char utf8d[] = { + // The first part of the table maps bytes to character classes that + // to reduce the size of the transition table and create bitmasks. + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, + + // The second part is a transition table that maps a combination + // of a state of the automaton and a character class to a state. + 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, + 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, + 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, + 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, + 12,36,12,12,12,12,12,12,12,12,12,12, +}; + +static unsigned inline decode(unsigned* state, unsigned* codep, unsigned byte) { + unsigned type = utf8d[byte]; + + *codep = (*state != UTF8_ACCEPT) ? + (byte & 0x3fu) | (*codep << 6) : + (0xffu >> type) & (byte); + + *state = utf8d[256 + *state + type]; + return *state; +} + +//static bool IsUTF8(unsigned char* s) { +// unsigned codepoint, state = 0; +// +// while (*s) +// decode(&state, &codepoint, *s++); +// +// return state == UTF8_ACCEPT; +//} + +TEST(EncodingsTest, UTF8) { + StringBuffer os, os2; + for (const unsigned* range = kCodepointRanges; *range != 0xFFFFFFFF; range += 2) { + for (unsigned codepoint = range[0]; codepoint <= range[1]; ++codepoint) { + os.Clear(); + UTF8<>::Encode(os, codepoint); + const char* encodedStr = os.GetString(); + + // Decode with Hoehrmann + { + unsigned decodedCodepoint = 0; + unsigned state = 0; + + unsigned decodedCount = 0; + for (const char* s = encodedStr; *s; ++s) + if (!decode(&state, &decodedCodepoint, static_cast(*s))) { + EXPECT_EQ(codepoint, decodedCodepoint); + decodedCount++; + } + + if (*encodedStr) { // This decoder cannot handle U+0000 + EXPECT_EQ(1u, decodedCount); // Should only contain one code point + } + + EXPECT_EQ(UTF8_ACCEPT, state); + if (UTF8_ACCEPT != state) + std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl; + } + + // Decode + { + StringStream is(encodedStr); + unsigned decodedCodepoint; + bool result = UTF8<>::Decode(is, &decodedCodepoint); + EXPECT_TRUE(result); + EXPECT_EQ(codepoint, decodedCodepoint); + if (!result || codepoint != decodedCodepoint) + std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl; + } + + // Validate + { + StringStream is(encodedStr); + os2.Clear(); + bool result = UTF8<>::Validate(is, os2); + EXPECT_TRUE(result); + EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString())); + } + } + } +} + +TEST(EncodingsTest, UTF16) { + GenericStringBuffer > os, os2; + GenericStringBuffer > utf8os; + for (const unsigned* range = kCodepointRanges; *range != 0xFFFFFFFF; range += 2) { + for (unsigned codepoint = range[0]; codepoint <= range[1]; ++codepoint) { + os.Clear(); + UTF16<>::Encode(os, codepoint); + const UTF16<>::Ch* encodedStr = os.GetString(); + + // Encode with Hoehrmann's code + if (codepoint != 0) // cannot handle U+0000 + { + // encode with UTF8<> first + utf8os.Clear(); + UTF8<>::Encode(utf8os, codepoint); + + // transcode from UTF8 to UTF16 with Hoehrmann's code + unsigned decodedCodepoint = 0; + unsigned state = 0; + UTF16<>::Ch buffer[3], *p = &buffer[0]; + for (const char* s = utf8os.GetString(); *s; ++s) { + if (!decode(&state, &decodedCodepoint, static_cast(*s))) + break; + } + + if (codepoint <= 0xFFFF) + *p++ = static_cast::Ch>(decodedCodepoint); + else { + // Encode code points above U+FFFF as surrogate pair. + *p++ = static_cast::Ch>(0xD7C0 + (decodedCodepoint >> 10)); + *p++ = static_cast::Ch>(0xDC00 + (decodedCodepoint & 0x3FF)); + } + *p++ = '\0'; + + EXPECT_EQ(0, StrCmp(buffer, encodedStr)); + } + + // Decode + { + GenericStringStream > is(encodedStr); + unsigned decodedCodepoint; + bool result = UTF16<>::Decode(is, &decodedCodepoint); + EXPECT_TRUE(result); + EXPECT_EQ(codepoint, decodedCodepoint); + if (!result || codepoint != decodedCodepoint) + std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl; + } + + // Validate + { + GenericStringStream > is(encodedStr); + os2.Clear(); + bool result = UTF16<>::Validate(is, os2); + EXPECT_TRUE(result); + EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString())); + } + } + } +} + +TEST(EncodingsTest, UTF32) { + GenericStringBuffer > os, os2; + for (const unsigned* range = kCodepointRanges; *range != 0xFFFFFFFF; range += 2) { + for (unsigned codepoint = range[0]; codepoint <= range[1]; ++codepoint) { + os.Clear(); + UTF32<>::Encode(os, codepoint); + const UTF32<>::Ch* encodedStr = os.GetString(); + + // Decode + { + GenericStringStream > is(encodedStr); + unsigned decodedCodepoint; + bool result = UTF32<>::Decode(is, &decodedCodepoint); + EXPECT_TRUE(result); + EXPECT_EQ(codepoint, decodedCodepoint); + if (!result || codepoint != decodedCodepoint) + std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl; + } + + // Validate + { + GenericStringStream > is(encodedStr); + os2.Clear(); + bool result = UTF32<>::Validate(is, os2); + EXPECT_TRUE(result); + EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString())); + } + } + } +} + +TEST(EncodingsTest, ASCII) { + StringBuffer os, os2; + for (unsigned codepoint = 0; codepoint < 128; codepoint++) { + os.Clear(); + ASCII<>::Encode(os, codepoint); + const ASCII<>::Ch* encodedStr = os.GetString(); + { + StringStream is(encodedStr); + unsigned decodedCodepoint; + bool result = ASCII<>::Decode(is, &decodedCodepoint); + if (!result || codepoint != decodedCodepoint) + std::cout << std::hex << codepoint << " " << decodedCodepoint << std::endl; + } + + // Validate + { + StringStream is(encodedStr); + os2.Clear(); + bool result = ASCII<>::Validate(is, os2); + EXPECT_TRUE(result); + EXPECT_EQ(0, StrCmp(encodedStr, os2.GetString())); + } + } +} diff --git a/deps/rapidjson/test/unittest/filestreamtest.cpp b/deps/rapidjson/test/unittest/filestreamtest.cpp new file mode 100644 index 0000000..de0b4d1 --- /dev/null +++ b/deps/rapidjson/test/unittest/filestreamtest.cpp @@ -0,0 +1,155 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/encodedstream.h" + +using namespace rapidjson; + +class FileStreamTest : public ::testing::Test { +public: + FileStreamTest() : filename_(), json_(), length_(), abcde_() {} + virtual ~FileStreamTest(); + + virtual void SetUp() { + const char *paths[] = { + "data/sample.json", + "bin/data/sample.json", + "../bin/data/sample.json", + "../../bin/data/sample.json", + "../../../bin/data/sample.json" + }; + FILE* fp = 0; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + fp = fopen(paths[i], "rb"); + if (fp) { + filename_ = paths[i]; + break; + } + } + ASSERT_TRUE(fp != 0); + + fseek(fp, 0, SEEK_END); + length_ = static_cast(ftell(fp)); + fseek(fp, 0, SEEK_SET); + json_ = static_cast(malloc(length_ + 1)); + size_t readLength = fread(json_, 1, length_, fp); + json_[readLength] = '\0'; + fclose(fp); + + const char *abcde_paths[] = { + "data/abcde.txt", + "bin/data/abcde.txt", + "../bin/data/abcde.txt", + "../../bin/data/abcde.txt", + "../../../bin/data/abcde.txt" + }; + fp = 0; + for (size_t i = 0; i < sizeof(abcde_paths) / sizeof(abcde_paths[0]); i++) { + fp = fopen(abcde_paths[i], "rb"); + if (fp) { + abcde_ = abcde_paths[i]; + break; + } + } + ASSERT_TRUE(fp != 0); + fclose(fp); + } + + virtual void TearDown() { + free(json_); + json_ = 0; + } + +private: + FileStreamTest(const FileStreamTest&); + FileStreamTest& operator=(const FileStreamTest&); + +protected: + const char* filename_; + char *json_; + size_t length_; + const char* abcde_; +}; + +FileStreamTest::~FileStreamTest() {} + +TEST_F(FileStreamTest, FileReadStream) { + FILE *fp = fopen(filename_, "rb"); + ASSERT_TRUE(fp != 0); + char buffer[65536]; + FileReadStream s(fp, buffer, sizeof(buffer)); + + for (size_t i = 0; i < length_; i++) { + EXPECT_EQ(json_[i], s.Peek()); + EXPECT_EQ(json_[i], s.Peek()); // 2nd time should be the same + EXPECT_EQ(json_[i], s.Take()); + } + + EXPECT_EQ(length_, s.Tell()); + EXPECT_EQ('\0', s.Peek()); + + fclose(fp); +} + +TEST_F(FileStreamTest, FileReadStream_Peek4) { + FILE *fp = fopen(abcde_, "rb"); + ASSERT_TRUE(fp != 0); + char buffer[4]; + FileReadStream s(fp, buffer, sizeof(buffer)); + + const char* c = s.Peek4(); + for (int i = 0; i < 4; i++) + EXPECT_EQ('a' + i, c[i]); + EXPECT_EQ(0u, s.Tell()); + + for (int i = 0; i < 5; i++) { + EXPECT_EQ(static_cast(i), s.Tell()); + EXPECT_EQ('a' + i, s.Peek()); + EXPECT_EQ('a' + i, s.Peek()); + EXPECT_EQ('a' + i, s.Take()); + } + EXPECT_EQ(5u, s.Tell()); + EXPECT_EQ(0, s.Peek()); + EXPECT_EQ(0, s.Take()); + + fclose(fp); +} + +TEST_F(FileStreamTest, FileWriteStream) { + char filename[L_tmpnam]; + FILE* fp = TempFile(filename); + + char buffer[65536]; + FileWriteStream os(fp, buffer, sizeof(buffer)); + for (size_t i = 0; i < length_; i++) + os.Put(json_[i]); + os.Flush(); + fclose(fp); + + // Read it back to verify + fp = fopen(filename, "rb"); + FileReadStream is(fp, buffer, sizeof(buffer)); + + for (size_t i = 0; i < length_; i++) + EXPECT_EQ(json_[i], is.Take()); + + EXPECT_EQ(length_, is.Tell()); + fclose(fp); + + //std::cout << filename << std::endl; + remove(filename); +} diff --git a/deps/rapidjson/test/unittest/fwdtest.cpp b/deps/rapidjson/test/unittest/fwdtest.cpp new file mode 100644 index 0000000..e9c7078 --- /dev/null +++ b/deps/rapidjson/test/unittest/fwdtest.cpp @@ -0,0 +1,230 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +// Using forward declared types here. + +#include "rapidjson/fwd.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +using namespace rapidjson; + +struct Foo { + Foo(); + ~Foo(); + + // encodings.h + UTF8* utf8; + UTF16* utf16; + UTF16BE* utf16be; + UTF16LE* utf16le; + UTF32* utf32; + UTF32BE* utf32be; + UTF32LE* utf32le; + ASCII* ascii; + AutoUTF* autoutf; + Transcoder, UTF8 >* transcoder; + + // allocators.h + CrtAllocator* crtallocator; + MemoryPoolAllocator* memorypoolallocator; + + // stream.h + StringStream* stringstream; + InsituStringStream* insitustringstream; + + // stringbuffer.h + StringBuffer* stringbuffer; + + // // filereadstream.h + // FileReadStream* filereadstream; + + // // filewritestream.h + // FileWriteStream* filewritestream; + + // memorybuffer.h + MemoryBuffer* memorybuffer; + + // memorystream.h + MemoryStream* memorystream; + + // reader.h + BaseReaderHandler, void>* basereaderhandler; + Reader* reader; + + // writer.h + Writer, UTF8, CrtAllocator, 0>* writer; + + // prettywriter.h + PrettyWriter, UTF8, CrtAllocator, 0>* prettywriter; + + // document.h + Value* value; + Document* document; + + // pointer.h + Pointer* pointer; + + // schema.h + SchemaDocument* schemadocument; + SchemaValidator* schemavalidator; + + // char buffer[16]; +}; + +// Using type definitions here. + +#include "rapidjson/stringbuffer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/memorybuffer.h" +#include "rapidjson/memorystream.h" +#include "rapidjson/document.h" // -> reader.h +#include "rapidjson/writer.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/schema.h" // -> pointer.h + +typedef Transcoder, UTF8<> > TranscoderUtf8ToUtf8; +typedef BaseReaderHandler, void> BaseReaderHandlerUtf8Void; + +Foo::Foo() : + // encodings.h + utf8(RAPIDJSON_NEW(UTF8<>)), + utf16(RAPIDJSON_NEW(UTF16<>)), + utf16be(RAPIDJSON_NEW(UTF16BE<>)), + utf16le(RAPIDJSON_NEW(UTF16LE<>)), + utf32(RAPIDJSON_NEW(UTF32<>)), + utf32be(RAPIDJSON_NEW(UTF32BE<>)), + utf32le(RAPIDJSON_NEW(UTF32LE<>)), + ascii(RAPIDJSON_NEW(ASCII<>)), + autoutf(RAPIDJSON_NEW(AutoUTF)), + transcoder(RAPIDJSON_NEW(TranscoderUtf8ToUtf8)), + + // allocators.h + crtallocator(RAPIDJSON_NEW(CrtAllocator)), + memorypoolallocator(RAPIDJSON_NEW(MemoryPoolAllocator<>)), + + // stream.h + stringstream(RAPIDJSON_NEW(StringStream)(NULL)), + insitustringstream(RAPIDJSON_NEW(InsituStringStream)(NULL)), + + // stringbuffer.h + stringbuffer(RAPIDJSON_NEW(StringBuffer)), + + // // filereadstream.h + // filereadstream(RAPIDJSON_NEW(FileReadStream)(stdout, buffer, sizeof(buffer))), + + // // filewritestream.h + // filewritestream(RAPIDJSON_NEW(FileWriteStream)(stdout, buffer, sizeof(buffer))), + + // memorybuffer.h + memorybuffer(RAPIDJSON_NEW(MemoryBuffer)), + + // memorystream.h + memorystream(RAPIDJSON_NEW(MemoryStream)(NULL, 0)), + + // reader.h + basereaderhandler(RAPIDJSON_NEW(BaseReaderHandlerUtf8Void)), + reader(RAPIDJSON_NEW(Reader)), + + // writer.h + writer(RAPIDJSON_NEW(Writer)), + + // prettywriter.h + prettywriter(RAPIDJSON_NEW(PrettyWriter)), + + // document.h + value(RAPIDJSON_NEW(Value)), + document(RAPIDJSON_NEW(Document)), + + // pointer.h + pointer(RAPIDJSON_NEW(Pointer)), + + // schema.h + schemadocument(RAPIDJSON_NEW(SchemaDocument)(*document)), + schemavalidator(RAPIDJSON_NEW(SchemaValidator)(*schemadocument)) +{ + +} + +Foo::~Foo() { + // encodings.h + RAPIDJSON_DELETE(utf8); + RAPIDJSON_DELETE(utf16); + RAPIDJSON_DELETE(utf16be); + RAPIDJSON_DELETE(utf16le); + RAPIDJSON_DELETE(utf32); + RAPIDJSON_DELETE(utf32be); + RAPIDJSON_DELETE(utf32le); + RAPIDJSON_DELETE(ascii); + RAPIDJSON_DELETE(autoutf); + RAPIDJSON_DELETE(transcoder); + + // allocators.h + RAPIDJSON_DELETE(crtallocator); + RAPIDJSON_DELETE(memorypoolallocator); + + // stream.h + RAPIDJSON_DELETE(stringstream); + RAPIDJSON_DELETE(insitustringstream); + + // stringbuffer.h + RAPIDJSON_DELETE(stringbuffer); + + // // filereadstream.h + // RAPIDJSON_DELETE(filereadstream); + + // // filewritestream.h + // RAPIDJSON_DELETE(filewritestream); + + // memorybuffer.h + RAPIDJSON_DELETE(memorybuffer); + + // memorystream.h + RAPIDJSON_DELETE(memorystream); + + // reader.h + RAPIDJSON_DELETE(basereaderhandler); + RAPIDJSON_DELETE(reader); + + // writer.h + RAPIDJSON_DELETE(writer); + + // prettywriter.h + RAPIDJSON_DELETE(prettywriter); + + // document.h + RAPIDJSON_DELETE(value); + RAPIDJSON_DELETE(document); + + // pointer.h + RAPIDJSON_DELETE(pointer); + + // schema.h + RAPIDJSON_DELETE(schemadocument); + RAPIDJSON_DELETE(schemavalidator); +} + +TEST(Fwd, Fwd) { + Foo f; +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/istreamwrappertest.cpp b/deps/rapidjson/test/unittest/istreamwrappertest.cpp new file mode 100644 index 0000000..f0cdb2d --- /dev/null +++ b/deps/rapidjson/test/unittest/istreamwrappertest.cpp @@ -0,0 +1,181 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/istreamwrapper.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/document.h" +#include +#include + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4702) // unreachable code +#endif + +using namespace rapidjson; +using namespace std; + +template +static void TestStringStream() { + typedef typename StringStreamType::char_type Ch; + + { + StringStreamType iss; + BasicIStreamWrapper is(iss); + EXPECT_EQ(0u, is.Tell()); + if (sizeof(Ch) == 1) { + EXPECT_EQ(0, is.Peek4()); + EXPECT_EQ(0u, is.Tell()); + } + EXPECT_EQ(0, is.Peek()); + EXPECT_EQ(0, is.Take()); + EXPECT_EQ(0u, is.Tell()); + } + + { + Ch s[] = { 'A', 'B', 'C', '\0' }; + StringStreamType iss(s); + BasicIStreamWrapper is(iss); + EXPECT_EQ(0u, is.Tell()); + if (sizeof(Ch) == 1) { + EXPECT_EQ(0, is.Peek4()); // less than 4 bytes + } + for (int i = 0; i < 3; i++) { + EXPECT_EQ(static_cast(i), is.Tell()); + EXPECT_EQ('A' + i, is.Peek()); + EXPECT_EQ('A' + i, is.Peek()); + EXPECT_EQ('A' + i, is.Take()); + } + EXPECT_EQ(3u, is.Tell()); + EXPECT_EQ(0, is.Peek()); + EXPECT_EQ(0, is.Take()); + } + + { + Ch s[] = { 'A', 'B', 'C', 'D', 'E', '\0' }; + StringStreamType iss(s); + BasicIStreamWrapper is(iss); + if (sizeof(Ch) == 1) { + const Ch* c = is.Peek4(); + for (int i = 0; i < 4; i++) + EXPECT_EQ('A' + i, c[i]); + EXPECT_EQ(0u, is.Tell()); + } + for (int i = 0; i < 5; i++) { + EXPECT_EQ(static_cast(i), is.Tell()); + EXPECT_EQ('A' + i, is.Peek()); + EXPECT_EQ('A' + i, is.Peek()); + EXPECT_EQ('A' + i, is.Take()); + } + EXPECT_EQ(5u, is.Tell()); + EXPECT_EQ(0, is.Peek()); + EXPECT_EQ(0, is.Take()); + } +} + +TEST(IStreamWrapper, istringstream) { + TestStringStream(); +} + +TEST(IStreamWrapper, stringstream) { + TestStringStream(); +} + +TEST(IStreamWrapper, wistringstream) { + TestStringStream(); +} + +TEST(IStreamWrapper, wstringstream) { + TestStringStream(); +} + +template +static bool Open(FileStreamType& fs, const char* filename) { + const char *paths[] = { + "encodings", + "bin/encodings", + "../bin/encodings", + "../../bin/encodings", + "../../../bin/encodings" + }; + char buffer[1024]; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + sprintf(buffer, "%s/%s", paths[i], filename); + fs.open(buffer, ios_base::in | ios_base::binary); + if (fs.is_open()) + return true; + } + return false; +} + +TEST(IStreamWrapper, ifstream) { + ifstream ifs; + ASSERT_TRUE(Open(ifs, "utf8bom.json")); + IStreamWrapper isw(ifs); + EncodedInputStream, IStreamWrapper> eis(isw); + Document d; + EXPECT_TRUE(!d.ParseStream(eis).HasParseError()); + EXPECT_TRUE(d.IsObject()); + EXPECT_EQ(5u, d.MemberCount()); +} + +TEST(IStreamWrapper, fstream) { + fstream fs; + ASSERT_TRUE(Open(fs, "utf8bom.json")); + IStreamWrapper isw(fs); + EncodedInputStream, IStreamWrapper> eis(isw); + Document d; + EXPECT_TRUE(!d.ParseStream(eis).HasParseError()); + EXPECT_TRUE(d.IsObject()); + EXPECT_EQ(5u, d.MemberCount()); +} + +// wifstream/wfstream only works on C++11 with codecvt_utf16 +// But many C++11 library still not have it. +#if 0 +#include + +TEST(IStreamWrapper, wifstream) { + wifstream ifs; + ASSERT_TRUE(Open(ifs, "utf16bebom.json")); + ifs.imbue(std::locale(ifs.getloc(), + new std::codecvt_utf16)); + WIStreamWrapper isw(ifs); + GenericDocument > d; + d.ParseStream, WIStreamWrapper>(isw); + EXPECT_TRUE(!d.HasParseError()); + EXPECT_TRUE(d.IsObject()); + EXPECT_EQ(5, d.MemberCount()); +} + +TEST(IStreamWrapper, wfstream) { + wfstream fs; + ASSERT_TRUE(Open(fs, "utf16bebom.json")); + fs.imbue(std::locale(fs.getloc(), + new std::codecvt_utf16)); + WIStreamWrapper isw(fs); + GenericDocument > d; + d.ParseStream, WIStreamWrapper>(isw); + EXPECT_TRUE(!d.HasParseError()); + EXPECT_TRUE(d.IsObject()); + EXPECT_EQ(5, d.MemberCount()); +} + +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/itoatest.cpp b/deps/rapidjson/test/unittest/itoatest.cpp new file mode 100644 index 0000000..4c834de --- /dev/null +++ b/deps/rapidjson/test/unittest/itoatest.cpp @@ -0,0 +1,160 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/internal/itoa.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(type-limits) +#endif + +using namespace rapidjson::internal; + +template +struct Traits { +}; + +template <> +struct Traits { + enum { kBufferSize = 11 }; + enum { kMaxDigit = 10 }; + static uint32_t Negate(uint32_t x) { return x; } +}; + +template <> +struct Traits { + enum { kBufferSize = 12 }; + enum { kMaxDigit = 10 }; + static int32_t Negate(int32_t x) { return -x; } +}; + +template <> +struct Traits { + enum { kBufferSize = 21 }; + enum { kMaxDigit = 20 }; + static uint64_t Negate(uint64_t x) { return x; } +}; + +template <> +struct Traits { + enum { kBufferSize = 22 }; + enum { kMaxDigit = 20 }; + static int64_t Negate(int64_t x) { return -x; } +}; + +template +static void VerifyValue(T value, void(*f)(T, char*), char* (*g)(T, char*)) { + char buffer1[Traits::kBufferSize]; + char buffer2[Traits::kBufferSize]; + + f(value, buffer1); + *g(value, buffer2) = '\0'; + + + EXPECT_STREQ(buffer1, buffer2); +} + +template +static void Verify(void(*f)(T, char*), char* (*g)(T, char*)) { + // Boundary cases + VerifyValue(0, f, g); + VerifyValue((std::numeric_limits::min)(), f, g); + VerifyValue((std::numeric_limits::max)(), f, g); + + // 2^n - 1, 2^n, 10^n - 1, 10^n until overflow + for (int power = 2; power <= 10; power += 8) { + T i = 1, last; + do { + VerifyValue(i - 1, f, g); + VerifyValue(i, f, g); + if ((std::numeric_limits::min)() < 0) { + VerifyValue(Traits::Negate(i), f, g); + VerifyValue(Traits::Negate(i + 1), f, g); + } + last = i; + if (i > static_cast((std::numeric_limits::max)() / static_cast(power))) + break; + i *= static_cast(power); + } while (last < i); + } +} + +static void u32toa_naive(uint32_t value, char* buffer) { + char temp[10]; + char *p = temp; + do { + *p++ = static_cast(char(value % 10) + '0'); + value /= 10; + } while (value > 0); + + do { + *buffer++ = *--p; + } while (p != temp); + + *buffer = '\0'; +} + +static void i32toa_naive(int32_t value, char* buffer) { + uint32_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + u32toa_naive(u, buffer); +} + +static void u64toa_naive(uint64_t value, char* buffer) { + char temp[20]; + char *p = temp; + do { + *p++ = static_cast(char(value % 10) + '0'); + value /= 10; + } while (value > 0); + + do { + *buffer++ = *--p; + } while (p != temp); + + *buffer = '\0'; +} + +static void i64toa_naive(int64_t value, char* buffer) { + uint64_t u = static_cast(value); + if (value < 0) { + *buffer++ = '-'; + u = ~u + 1; + } + u64toa_naive(u, buffer); +} + +TEST(itoa, u32toa) { + Verify(u32toa_naive, u32toa); +} + +TEST(itoa, i32toa) { + Verify(i32toa_naive, i32toa); +} + +TEST(itoa, u64toa) { + Verify(u64toa_naive, u64toa); +} + +TEST(itoa, i64toa) { + Verify(i64toa_naive, i64toa); +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/jsoncheckertest.cpp b/deps/rapidjson/test/unittest/jsoncheckertest.cpp new file mode 100644 index 0000000..19e1f1c --- /dev/null +++ b/deps/rapidjson/test/unittest/jsoncheckertest.cpp @@ -0,0 +1,143 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/document.h" + +using namespace rapidjson; + +static char* ReadFile(const char* filename, size_t& length) { + const char *paths[] = { + "jsonchecker", + "bin/jsonchecker", + "../bin/jsonchecker", + "../../bin/jsonchecker", + "../../../bin/jsonchecker" + }; + char buffer[1024]; + FILE *fp = 0; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + sprintf(buffer, "%s/%s", paths[i], filename); + fp = fopen(buffer, "rb"); + if (fp) + break; + } + + if (!fp) + return 0; + + fseek(fp, 0, SEEK_END); + length = static_cast(ftell(fp)); + fseek(fp, 0, SEEK_SET); + char* json = static_cast(malloc(length + 1)); + size_t readLength = fread(json, 1, length, fp); + json[readLength] = '\0'; + fclose(fp); + return json; +} + +struct NoOpHandler { + bool Null() { return true; } + bool Bool(bool) { return true; } + bool Int(int) { return true; } + bool Uint(unsigned) { return true; } + bool Int64(int64_t) { return true; } + bool Uint64(uint64_t) { return true; } + bool Double(double) { return true; } + bool RawNumber(const char*, SizeType, bool) { return true; } + bool String(const char*, SizeType, bool) { return true; } + bool StartObject() { return true; } + bool Key(const char*, SizeType, bool) { return true; } + bool EndObject(SizeType) { return true; } + bool StartArray() { return true; } + bool EndArray(SizeType) { return true; } +}; + + +TEST(JsonChecker, Reader) { + char filename[256]; + + // jsonchecker/failXX.json + for (int i = 1; i <= 33; i++) { + if (i == 1) // fail1.json is valid in rapidjson, which has no limitation on type of root element (RFC 7159). + continue; + if (i == 18) // fail18.json is valid in rapidjson, which has no limitation on depth of nesting. + continue; + + sprintf(filename, "fail%d.json", i); + size_t length; + char* json = ReadFile(filename, length); + if (!json) { + printf("jsonchecker file %s not found", filename); + ADD_FAILURE(); + continue; + } + + // Test stack-based parsing. + GenericDocument, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak) + document.Parse(json); + EXPECT_TRUE(document.HasParseError()) << filename; + + // Test iterative parsing. + document.Parse(json); + EXPECT_TRUE(document.HasParseError()) << filename; + + // Test iterative pull-parsing. + Reader reader; + StringStream ss(json); + NoOpHandler h; + reader.IterativeParseInit(); + while (!reader.IterativeParseComplete()) { + if (!reader.IterativeParseNext(ss, h)) + break; + } + EXPECT_TRUE(reader.HasParseError()) << filename; + + free(json); + } + + // passX.json + for (int i = 1; i <= 3; i++) { + sprintf(filename, "pass%d.json", i); + size_t length; + char* json = ReadFile(filename, length); + if (!json) { + printf("jsonchecker file %s not found", filename); + continue; + } + + // Test stack-based parsing. + GenericDocument, CrtAllocator> document; // Use Crt allocator to check exception-safety (no memory leak) + document.Parse(json); + EXPECT_FALSE(document.HasParseError()) << filename; + + // Test iterative parsing. + document.Parse(json); + EXPECT_FALSE(document.HasParseError()) << filename; + + // Test iterative pull-parsing. + Reader reader; + StringStream ss(json); + NoOpHandler h; + reader.IterativeParseInit(); + while (!reader.IterativeParseComplete()) { + if (!reader.IterativeParseNext(ss, h)) + break; + } + EXPECT_FALSE(reader.HasParseError()) << filename; + + free(json); + } +} diff --git a/deps/rapidjson/test/unittest/namespacetest.cpp b/deps/rapidjson/test/unittest/namespacetest.cpp new file mode 100644 index 0000000..e33e6d5 --- /dev/null +++ b/deps/rapidjson/test/unittest/namespacetest.cpp @@ -0,0 +1,70 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +// test another instantiation of RapidJSON in a different namespace + +#define RAPIDJSON_NAMESPACE my::rapid::json +#define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapid { namespace json { +#define RAPIDJSON_NAMESPACE_END } } } + +// include lots of RapidJSON files + +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/filereadstream.h" +#include "rapidjson/filewritestream.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/stringbuffer.h" + +static const char json[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,4]}"; + +TEST(NamespaceTest,Using) { + using namespace RAPIDJSON_NAMESPACE; + typedef GenericDocument, CrtAllocator> DocumentType; + DocumentType doc; + + doc.Parse(json); + EXPECT_TRUE(!doc.HasParseError()); +} + +TEST(NamespaceTest,Direct) { + typedef RAPIDJSON_NAMESPACE::Document Document; + typedef RAPIDJSON_NAMESPACE::Reader Reader; + typedef RAPIDJSON_NAMESPACE::StringStream StringStream; + typedef RAPIDJSON_NAMESPACE::StringBuffer StringBuffer; + typedef RAPIDJSON_NAMESPACE::Writer WriterType; + + StringStream s(json); + StringBuffer buffer; + WriterType writer(buffer); + buffer.ShrinkToFit(); + Reader reader; + reader.Parse(s, writer); + + EXPECT_STREQ(json, buffer.GetString()); + EXPECT_EQ(sizeof(json)-1, buffer.GetSize()); + EXPECT_TRUE(writer.IsComplete()); + + Document doc; + doc.Parse(buffer.GetString()); + EXPECT_TRUE(!doc.HasParseError()); + + buffer.Clear(); + writer.Reset(buffer); + doc.Accept(writer); + EXPECT_STREQ(json, buffer.GetString()); + EXPECT_TRUE(writer.IsComplete()); +} diff --git a/deps/rapidjson/test/unittest/ostreamwrappertest.cpp b/deps/rapidjson/test/unittest/ostreamwrappertest.cpp new file mode 100644 index 0000000..be9e429 --- /dev/null +++ b/deps/rapidjson/test/unittest/ostreamwrappertest.cpp @@ -0,0 +1,92 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/ostreamwrapper.h" +#include "rapidjson/encodedstream.h" +#include "rapidjson/document.h" +#include +#include + +using namespace rapidjson; +using namespace std; + +template +static void TestStringStream() { + typedef typename StringStreamType::char_type Ch; + + Ch s[] = { 'A', 'B', 'C', '\0' }; + StringStreamType oss(s); + BasicOStreamWrapper os(oss); + for (size_t i = 0; i < 3; i++) + os.Put(s[i]); + os.Flush(); + for (size_t i = 0; i < 3; i++) + EXPECT_EQ(s[i], oss.str()[i]); +} + +TEST(OStreamWrapper, ostringstream) { + TestStringStream(); +} + +TEST(OStreamWrapper, stringstream) { + TestStringStream(); +} + +TEST(OStreamWrapper, wostringstream) { + TestStringStream(); +} + +TEST(OStreamWrapper, wstringstream) { + TestStringStream(); +} + +TEST(OStreamWrapper, cout) { + OStreamWrapper os(cout); + const char* s = "Hello World!\n"; + while (*s) + os.Put(*s++); + os.Flush(); +} + +template +static void TestFileStream() { + char filename[L_tmpnam]; + FILE* fp = TempFile(filename); + fclose(fp); + + const char* s = "Hello World!\n"; + { + FileStreamType ofs(filename, ios::out | ios::binary); + BasicOStreamWrapper osw(ofs); + for (const char* p = s; *p; p++) + osw.Put(*p); + osw.Flush(); + } + + fp = fopen(filename, "r"); + ASSERT_TRUE( fp != NULL ); + for (const char* p = s; *p; p++) + EXPECT_EQ(*p, static_cast(fgetc(fp))); + fclose(fp); +} + +TEST(OStreamWrapper, ofstream) { + TestFileStream(); +} + +TEST(OStreamWrapper, fstream) { + TestFileStream(); +} diff --git a/deps/rapidjson/test/unittest/platformtest.cpp b/deps/rapidjson/test/unittest/platformtest.cpp new file mode 100644 index 0000000..05eba3f --- /dev/null +++ b/deps/rapidjson/test/unittest/platformtest.cpp @@ -0,0 +1,40 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2021 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +// see https://github.com/Tencent/rapidjson/issues/1448 +// including windows.h on purpose to provoke a compile time problem as GetObject is a +// macro that gets defined when windows.h is included +#ifdef _WIN32 +#include +#endif + +#include "rapidjson/document.h" +#undef GetObject + +using namespace rapidjson; + +TEST(Platform, GetObject) { + Document doc; + doc.Parse(" { \"object\" : { \"pi\": 3.1416} } "); + EXPECT_TRUE(doc.IsObject()); + EXPECT_TRUE(doc.HasMember("object")); + const Document::ValueType& o = doc["object"]; + EXPECT_TRUE(o.IsObject()); + Value::ConstObject sub = o.GetObject(); + EXPECT_TRUE(sub.HasMember("pi")); + Value::ConstObject sub2 = o.GetObj(); + EXPECT_TRUE(sub2.HasMember("pi")); +} diff --git a/deps/rapidjson/test/unittest/pointertest.cpp b/deps/rapidjson/test/unittest/pointertest.cpp new file mode 100644 index 0000000..c35fa8f --- /dev/null +++ b/deps/rapidjson/test/unittest/pointertest.cpp @@ -0,0 +1,1730 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/pointer.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/ostreamwrapper.h" +#include +#include +#include + +using namespace rapidjson; + +static const char kJson[] = "{\n" +" \"foo\":[\"bar\", \"baz\"],\n" +" \"\" : 0,\n" +" \"a/b\" : 1,\n" +" \"c%d\" : 2,\n" +" \"e^f\" : 3,\n" +" \"g|h\" : 4,\n" +" \"i\\\\j\" : 5,\n" +" \"k\\\"l\" : 6,\n" +" \" \" : 7,\n" +" \"m~n\" : 8\n" +"}"; + +TEST(Pointer, DefaultConstructor) { + Pointer p; + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(0u, p.GetTokenCount()); +} + +TEST(Pointer, Parse) { + { + Pointer p(""); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(0u, p.GetTokenCount()); + } + + { + Pointer p("/"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + { + Pointer p("/foo"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + #if RAPIDJSON_HAS_STDSTRING + { + Pointer p(std::string("/foo")); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + #endif + + { + Pointer p("/foo/0"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("0", p.GetTokens()[1].name); + EXPECT_EQ(0u, p.GetTokens()[1].index); + } + + { + // Unescape ~1 + Pointer p("/a~1b"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("a/b", p.GetTokens()[0].name); + } + + { + // Unescape ~0 + Pointer p("/m~0n"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("m~n", p.GetTokens()[0].name); + } + + { + // empty name + Pointer p("/"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + } + + { + // empty and non-empty name + Pointer p("//a"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("a", p.GetTokens()[1].name); + } + + { + // Null characters + Pointer p("/\0\0", 3); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(2u, p.GetTokens()[0].length); + EXPECT_EQ('\0', p.GetTokens()[0].name[0]); + EXPECT_EQ('\0', p.GetTokens()[0].name[1]); + EXPECT_EQ('\0', p.GetTokens()[0].name[2]); + } + + { + // Valid index + Pointer p("/123"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("123", p.GetTokens()[0].name); + EXPECT_EQ(123u, p.GetTokens()[0].index); + } + + { + // Invalid index (with leading zero) + Pointer p("/01"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("01", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + if (sizeof(SizeType) == 4) { + // Invalid index (overflow) + Pointer p("/4294967296"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("4294967296", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + { + // kPointerParseErrorTokenMustBeginWithSolidus + Pointer p(" "); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode()); + EXPECT_EQ(0u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("/~"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("/~2"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } +} + +TEST(Pointer, Parse_URIFragment) { + { + Pointer p("#"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(0u, p.GetTokenCount()); + } + + { + Pointer p("#/foo"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + } + + { + Pointer p("#/foo/0"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("0", p.GetTokens()[1].name); + EXPECT_EQ(0u, p.GetTokens()[1].index); + } + + { + // Unescape ~1 + Pointer p("#/a~1b"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("a/b", p.GetTokens()[0].name); + } + + { + // Unescape ~0 + Pointer p("#/m~0n"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("m~n", p.GetTokens()[0].name); + } + + { + // empty name + Pointer p("#/"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + } + + { + // empty and non-empty name + Pointer p("#//a"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(0u, p.GetTokens()[0].length); + EXPECT_STREQ("", p.GetTokens()[0].name); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("a", p.GetTokens()[1].name); + } + + { + // Null characters + Pointer p("#/%00%00"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(2u, p.GetTokens()[0].length); + EXPECT_EQ('\0', p.GetTokens()[0].name[0]); + EXPECT_EQ('\0', p.GetTokens()[0].name[1]); + EXPECT_EQ('\0', p.GetTokens()[0].name[2]); + } + + { + // Percentage Escapes + EXPECT_STREQ("c%d", Pointer("#/c%25d").GetTokens()[0].name); + EXPECT_STREQ("e^f", Pointer("#/e%5Ef").GetTokens()[0].name); + EXPECT_STREQ("g|h", Pointer("#/g%7Ch").GetTokens()[0].name); + EXPECT_STREQ("i\\j", Pointer("#/i%5Cj").GetTokens()[0].name); + EXPECT_STREQ("k\"l", Pointer("#/k%22l").GetTokens()[0].name); + EXPECT_STREQ(" ", Pointer("#/%20").GetTokens()[0].name); + } + + { + // Valid index + Pointer p("#/123"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("123", p.GetTokens()[0].name); + EXPECT_EQ(123u, p.GetTokens()[0].index); + } + + { + // Invalid index (with leading zero) + Pointer p("#/01"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("01", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + if (sizeof(SizeType) == 4) { + // Invalid index (overflow) + Pointer p("#/4294967296"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("4294967296", p.GetTokens()[0].name); + EXPECT_EQ(kPointerInvalidIndex, p.GetTokens()[0].index); + } + + { + // Decode UTF-8 percent encoding to UTF-8 + Pointer p("#/%C2%A2"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_STREQ("\xC2\xA2", p.GetTokens()[0].name); + } + + { + // Decode UTF-8 percent encoding to UTF-16 + GenericPointer > > p(L"#/%C2%A2"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(static_cast::Ch>(0x00A2), p.GetTokens()[0].name[0]); + EXPECT_EQ(1u, p.GetTokens()[0].length); + } + + { + // Decode UTF-8 percent encoding to UTF-16 + GenericPointer > > p(L"#/%E2%82%AC"); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(1u, p.GetTokenCount()); + EXPECT_EQ(static_cast::Ch>(0x20AC), p.GetTokens()[0].name[0]); + EXPECT_EQ(1u, p.GetTokens()[0].length); + } + + { + // kPointerParseErrorTokenMustBeginWithSolidus + Pointer p("# "); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorTokenMustBeginWithSolidus, p.GetParseErrorCode()); + EXPECT_EQ(1u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("#/~"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(3u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidEscape + Pointer p("#/~2"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidEscape, p.GetParseErrorCode()); + EXPECT_EQ(3u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidPercentEncoding + Pointer p("#/%"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidPercentEncoding (invalid hex) + Pointer p("#/%g0"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidPercentEncoding (invalid hex) + Pointer p("#/%0g"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorInvalidPercentEncoding (incomplete UTF-8 sequence) + Pointer p("#/%C2"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorInvalidPercentEncoding, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorCharacterMustPercentEncode + Pointer p("#/ "); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } + + { + // kPointerParseErrorCharacterMustPercentEncode + Pointer p("#/\n"); + EXPECT_FALSE(p.IsValid()); + EXPECT_EQ(kPointerParseErrorCharacterMustPercentEncode, p.GetParseErrorCode()); + EXPECT_EQ(2u, p.GetParseErrorOffset()); + } +} + +TEST(Pointer, Stringify) { + // Test by roundtrip + const char* sources[] = { + "", + "/foo", + "/foo/0", + "/", + "/a~1b", + "/c%d", + "/e^f", + "/g|h", + "/i\\j", + "/k\"l", + "/ ", + "/m~0n", + "/\xC2\xA2", + "/\xE2\x82\xAC", + "/\xF0\x9D\x84\x9E" + }; + + for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) { + Pointer p(sources[i]); + StringBuffer s; + EXPECT_TRUE(p.Stringify(s)); + EXPECT_STREQ(sources[i], s.GetString()); + + // Stringify to URI fragment + StringBuffer s2; + EXPECT_TRUE(p.StringifyUriFragment(s2)); + Pointer p2(s2.GetString(), s2.GetSize()); + EXPECT_TRUE(p2.IsValid()); + EXPECT_TRUE(p == p2); + } + + { + // Strigify to URI fragment with an invalid UTF-8 sequence + Pointer p("/\xC2"); + StringBuffer s; + EXPECT_FALSE(p.StringifyUriFragment(s)); + } +} + +// Construct a Pointer with static tokens, no dynamic allocation involved. +#define NAME(s) { s, static_cast(sizeof(s) / sizeof(s[0]) - 1), kPointerInvalidIndex } +#define INDEX(i) { #i, static_cast(sizeof(#i) - 1), i } + +static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0" + +#undef NAME +#undef INDEX + +TEST(Pointer, ConstructorWithToken) { + Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("0", p.GetTokens()[1].name); + EXPECT_EQ(0u, p.GetTokens()[1].index); +} + +TEST(Pointer, CopyConstructor) { + { + CrtAllocator allocator; + Pointer p("/foo/0", &allocator); + Pointer q(p); + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1u, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0u, q.GetTokens()[1].index); + + // Copied pointer needs to have its own allocator + EXPECT_NE(&p.GetAllocator(), &q.GetAllocator()); + } + + // Static tokens + { + Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + Pointer q(p); + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1u, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0u, q.GetTokens()[1].index); + } +} + +TEST(Pointer, Assignment) { + { + CrtAllocator allocator; + Pointer p("/foo/0", &allocator); + Pointer q; + q = p; + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1u, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0u, q.GetTokens()[1].index); + EXPECT_NE(&p.GetAllocator(), &q.GetAllocator()); + q = static_cast(q); + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1u, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0u, q.GetTokens()[1].index); + EXPECT_NE(&p.GetAllocator(), &q.GetAllocator()); + } + + // Static tokens + { + Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); + Pointer q; + q = p; + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1u, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0u, q.GetTokens()[1].index); + } +} + +TEST(Pointer, Swap) { + Pointer p("/foo/0"); + Pointer q(&p.GetAllocator()); + + q.Swap(p); + EXPECT_EQ(&q.GetAllocator(), &p.GetAllocator()); + EXPECT_TRUE(p.IsValid()); + EXPECT_TRUE(q.IsValid()); + EXPECT_EQ(0u, p.GetTokenCount()); + EXPECT_EQ(2u, q.GetTokenCount()); + EXPECT_EQ(3u, q.GetTokens()[0].length); + EXPECT_STREQ("foo", q.GetTokens()[0].name); + EXPECT_EQ(1u, q.GetTokens()[1].length); + EXPECT_STREQ("0", q.GetTokens()[1].name); + EXPECT_EQ(0u, q.GetTokens()[1].index); + + // std::swap compatibility + std::swap(p, q); + EXPECT_EQ(&p.GetAllocator(), &q.GetAllocator()); + EXPECT_TRUE(q.IsValid()); + EXPECT_TRUE(p.IsValid()); + EXPECT_EQ(0u, q.GetTokenCount()); + EXPECT_EQ(2u, p.GetTokenCount()); + EXPECT_EQ(3u, p.GetTokens()[0].length); + EXPECT_STREQ("foo", p.GetTokens()[0].name); + EXPECT_EQ(1u, p.GetTokens()[1].length); + EXPECT_STREQ("0", p.GetTokens()[1].name); + EXPECT_EQ(0u, p.GetTokens()[1].index); +} + +TEST(Pointer, Append) { + { + Pointer p; + Pointer q = p.Append("foo"); + EXPECT_TRUE(Pointer("/foo") == q); + q = q.Append(1234); + EXPECT_TRUE(Pointer("/foo/1234") == q); + q = q.Append(""); + EXPECT_TRUE(Pointer("/foo/1234/") == q); + } + + { + Pointer p; + Pointer q = p.Append(Value("foo").Move()); + EXPECT_TRUE(Pointer("/foo") == q); + q = q.Append(Value(1234).Move()); + EXPECT_TRUE(Pointer("/foo/1234") == q); + q = q.Append(Value(kStringType).Move()); + EXPECT_TRUE(Pointer("/foo/1234/") == q); + } + +#if RAPIDJSON_HAS_STDSTRING + { + Pointer p; + Pointer q = p.Append(std::string("foo")); + EXPECT_TRUE(Pointer("/foo") == q); + } +#endif +} + +TEST(Pointer, Equality) { + EXPECT_TRUE(Pointer("/foo/0") == Pointer("/foo/0")); + EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/1")); + EXPECT_FALSE(Pointer("/foo/0") == Pointer("/foo/0/1")); + EXPECT_FALSE(Pointer("/foo/0") == Pointer("a")); + EXPECT_FALSE(Pointer("a") == Pointer("a")); // Invalid always not equal +} + +TEST(Pointer, Inequality) { + EXPECT_FALSE(Pointer("/foo/0") != Pointer("/foo/0")); + EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/1")); + EXPECT_TRUE(Pointer("/foo/0") != Pointer("/foo/0/1")); + EXPECT_TRUE(Pointer("/foo/0") != Pointer("a")); + EXPECT_TRUE(Pointer("a") != Pointer("a")); // Invalid always not equal +} + +TEST(Pointer, Create) { + Document d; + { + Value* v = &Pointer("").Create(d, d.GetAllocator()); + EXPECT_EQ(&d, v); + } + { + Value* v = &Pointer("/foo").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"], v); + } + { + Value* v = &Pointer("/foo/0").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"][0], v); + } + { + Value* v = &Pointer("/foo/-").Create(d, d.GetAllocator()); + EXPECT_EQ(&d["foo"][1], v); + } + + { + Value* v = &Pointer("/foo/-/-").Create(d, d.GetAllocator()); + // "foo/-" is a newly created null value x. + // "foo/-/-" finds that x is not an array, it converts x to empty object + // and treats - as "-" member name + EXPECT_EQ(&d["foo"][2]["-"], v); + } + + { + // Document with no allocator + Value* v = &Pointer("/foo/-").Create(d); + EXPECT_EQ(&d["foo"][3], v); + } + + { + // Value (not document) must give allocator + Value* v = &Pointer("/-").Create(d["foo"], d.GetAllocator()); + EXPECT_EQ(&d["foo"][4], v); + } +} + +static const char kJsonIds[] = "{\n" + " \"id\": \"/root/\"," + " \"foo\":[\"bar\", \"baz\", {\"id\": \"inarray\", \"child\": 1}],\n" + " \"int\" : 2,\n" + " \"str\" : \"val\",\n" + " \"obj\": {\"id\": \"inobj\", \"child\": 3},\n" + " \"jbo\": {\"id\": true, \"child\": 4}\n" + "}"; + + +TEST(Pointer, GetUri) { + CrtAllocator allocator; + Document d; + d.Parse(kJsonIds); + Pointer::UriType doc("http://doc"); + Pointer::UriType root("http://doc/root/"); + Pointer::UriType empty = Pointer::UriType(); + + EXPECT_TRUE(Pointer("").GetUri(d, doc) == doc); + EXPECT_TRUE(Pointer("/foo").GetUri(d, doc) == root); + EXPECT_TRUE(Pointer("/foo/0").GetUri(d, doc) == root); + EXPECT_TRUE(Pointer("/foo/2").GetUri(d, doc) == root); + EXPECT_TRUE(Pointer("/foo/2/child").GetUri(d, doc) == Pointer::UriType("http://doc/root/inarray")); + EXPECT_TRUE(Pointer("/int").GetUri(d, doc) == root); + EXPECT_TRUE(Pointer("/str").GetUri(d, doc) == root); + EXPECT_TRUE(Pointer("/obj").GetUri(d, doc) == root); + EXPECT_TRUE(Pointer("/obj/child").GetUri(d, doc) == Pointer::UriType("http://doc/root/inobj")); + EXPECT_TRUE(Pointer("/jbo").GetUri(d, doc) == root); + EXPECT_TRUE(Pointer("/jbo/child").GetUri(d, doc) == root); // id not string + + size_t unresolvedTokenIndex; + EXPECT_TRUE(Pointer("/abc").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary + EXPECT_EQ(0u, unresolvedTokenIndex); + EXPECT_TRUE(Pointer("/foo/3").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(Pointer("/foo/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo" is an array, cannot query by "a" + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(Pointer("/foo/0/0").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + EXPECT_TRUE(Pointer("/foo/0/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + + Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } }; + EXPECT_TRUE(Pointer(tokens, 1).GetUri(d, doc) == root); +} + +TEST(Pointer, Get) { + Document d; + d.Parse(kJson); + + EXPECT_EQ(&d, Pointer("").Get(d)); + EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d)); + EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d)); + EXPECT_EQ(&d[""], Pointer("/").Get(d)); + EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d)); + EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d)); + EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d)); + EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d)); + EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d)); + EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d)); + EXPECT_EQ(&d[" "], Pointer("/ ").Get(d)); + EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d)); + + EXPECT_TRUE(Pointer("/abc").Get(d) == 0); // Out of boundary + size_t unresolvedTokenIndex; + EXPECT_TRUE(Pointer("/foo/2").Get(d, &unresolvedTokenIndex) == 0); // Out of boundary + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(Pointer("/foo/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a" + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(Pointer("/foo/0/0").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + EXPECT_TRUE(Pointer("/foo/0/a").Get(d, &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + + Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } }; + EXPECT_EQ(&d["foo"], Pointer(tokens, 1).Get(d)); +} + +TEST(Pointer, GetWithDefault) { + Document d; + d.Parse(kJson); + + // Value version + Document::AllocatorType& a = d.GetAllocator(); + const Value v("qux"); + EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a)); + EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a)); + EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a)); + EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move(), a)); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move(), a).IsNull()); + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x", a).IsNull()); + + // Generic version + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1, a).GetInt()); + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2, a).GetInt()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321, a).GetUint()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678, a).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64, a).GetInt64()); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1, a).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64, a).GetUint64()); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1, a).GetUint64()); + + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true, a).IsTrue()); + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false, a).IsTrue()); + + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false, a).IsFalse()); + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true, a).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello", a).GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer, a).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++"), a).GetString()); +#endif +} + +TEST(Pointer, GetWithDefault_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + const Value v("qux"); + EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v)); + EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v)); + EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v)); + EXPECT_TRUE(Value("last") == Pointer("/foo/-").GetWithDefault(d, Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, Value().Move()).IsNull()); + EXPECT_TRUE(Pointer("/foo/null").GetWithDefault(d, "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -1).GetInt()); + EXPECT_EQ(-1, Pointer("/foo/int").GetWithDefault(d, -2).GetInt()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, Pointer("/foo/uint").GetWithDefault(d, 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64).GetInt64()); + EXPECT_EQ(i64, Pointer("/foo/int64").GetWithDefault(d, i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64).GetUint64()); + EXPECT_EQ(u64, Pointer("/foo/uint64").GetWithDefault(d, u64 - 1).GetUint64()); + + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, true).IsTrue()); + EXPECT_TRUE(Pointer("/foo/true").GetWithDefault(d, false).IsTrue()); + + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, false).IsFalse()); + EXPECT_TRUE(Pointer("/foo/false").GetWithDefault(d, true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", Pointer("/foo/hello").GetWithDefault(d, "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", Pointer("/foo/world").GetWithDefault(d, buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", Pointer("/foo/C++").GetWithDefault(d, std::string("C++")).GetString()); +#endif +} + +TEST(Pointer, Set) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + + // Value version + Pointer("/foo/0").Set(d, Value(123).Move(), a); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + Pointer("/foo/-").Set(d, Value(456).Move(), a); + EXPECT_EQ(456, d["foo"][2].GetInt()); + + Pointer("/foo/null").Set(d, Value().Move(), a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Const Value version + const Value foo(d["foo"], a); + Pointer("/clone").Set(d, foo, a); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + + // Generic version + Pointer("/foo/int").Set(d, -1, a); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + Pointer("/foo/uint").Set(d, 0x87654321, a); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + Pointer("/foo/int64").Set(d, i64, a); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + Pointer("/foo/uint64").Set(d, u64, a); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + Pointer("/foo/true").Set(d, true, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + Pointer("/foo/false").Set(d, false, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + Pointer("/foo/hello").Set(d, "Hello", a); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + Pointer("/foo/world").Set(d, buffer, a); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + Pointer("/foo/c++").Set(d, std::string("C++"), a); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif +} + +TEST(Pointer, Set_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + Pointer("/foo/0").Set(d, Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + Pointer("/foo/-").Set(d, Value(456).Move()); + EXPECT_EQ(456, d["foo"][2].GetInt()); + + Pointer("/foo/null").Set(d, Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + Pointer("/clone").Set(d, foo); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + + // Generic version + Pointer("/foo/int").Set(d, -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + Pointer("/foo/uint").Set(d, 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + Pointer("/foo/int64").Set(d, i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + Pointer("/foo/uint64").Set(d, u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + Pointer("/foo/true").Set(d, true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + Pointer("/foo/false").Set(d, false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + Pointer("/foo/hello").Set(d, "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + Pointer("/foo/world").Set(d, buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + Pointer("/foo/c++").Set(d, std::string("C++")); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif +} + +TEST(Pointer, Swap_Value) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); +} + +TEST(Pointer, Swap_Value_NoAllocator) { + Document d; + d.Parse(kJson); + Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d)); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); +} + +TEST(Pointer, Erase) { + Document d; + d.Parse(kJson); + + EXPECT_FALSE(Pointer("").Erase(d)); + EXPECT_FALSE(Pointer("/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/nonexist/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/nonexist/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/0/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/0/nonexist/nonexist").Erase(d)); + EXPECT_FALSE(Pointer("/foo/2/nonexist").Erase(d)); + EXPECT_TRUE(Pointer("/foo/0").Erase(d)); + EXPECT_EQ(1u, d["foo"].Size()); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_TRUE(Pointer("/foo/0").Erase(d)); + EXPECT_TRUE(d["foo"].Empty()); + EXPECT_TRUE(Pointer("/foo").Erase(d)); + EXPECT_TRUE(Pointer("/foo").Get(d) == 0); + + Pointer("/a/0/b/0").Create(d); + + EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) != 0); + EXPECT_TRUE(Pointer("/a/0/b/0").Erase(d)); + EXPECT_TRUE(Pointer("/a/0/b/0").Get(d) == 0); + + EXPECT_TRUE(Pointer("/a/0/b").Get(d) != 0); + EXPECT_TRUE(Pointer("/a/0/b").Erase(d)); + EXPECT_TRUE(Pointer("/a/0/b").Get(d) == 0); + + EXPECT_TRUE(Pointer("/a/0").Get(d) != 0); + EXPECT_TRUE(Pointer("/a/0").Erase(d)); + EXPECT_TRUE(Pointer("/a/0").Get(d) == 0); + + EXPECT_TRUE(Pointer("/a").Get(d) != 0); + EXPECT_TRUE(Pointer("/a").Erase(d)); + EXPECT_TRUE(Pointer("/a").Get(d) == 0); +} + +TEST(Pointer, CreateValueByPointer) { + Document d; + Document::AllocatorType& a = d.GetAllocator(); + + { + Value& v = CreateValueByPointer(d, Pointer("/foo/0"), a); + EXPECT_EQ(&d["foo"][0], &v); + } + { + Value& v = CreateValueByPointer(d, "/foo/1", a); + EXPECT_EQ(&d["foo"][1], &v); + } +} + +TEST(Pointer, CreateValueByPointer_NoAllocator) { + Document d; + + { + Value& v = CreateValueByPointer(d, Pointer("/foo/0")); + EXPECT_EQ(&d["foo"][0], &v); + } + { + Value& v = CreateValueByPointer(d, "/foo/1"); + EXPECT_EQ(&d["foo"][1], &v); + } +} + +TEST(Pointer, GetValueByPointer) { + Document d; + d.Parse(kJson); + + EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, Pointer("/foo/0"))); + EXPECT_EQ(&d["foo"][0], GetValueByPointer(d, "/foo/0")); + + size_t unresolvedTokenIndex; + EXPECT_TRUE(GetValueByPointer(d, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(GetValueByPointer(d, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a" + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(GetValueByPointer(d, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + EXPECT_TRUE(GetValueByPointer(d, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + + // const version + const Value& v = d; + EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, Pointer("/foo/0"))); + EXPECT_EQ(&d["foo"][0], GetValueByPointer(v, "/foo/0")); + + EXPECT_TRUE(GetValueByPointer(v, "/foo/2", &unresolvedTokenIndex) == 0); // Out of boundary + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(GetValueByPointer(v, "/foo/a", &unresolvedTokenIndex) == 0); // "/foo" is an array, cannot query by "a" + EXPECT_EQ(1u, unresolvedTokenIndex); + EXPECT_TRUE(GetValueByPointer(v, "/foo/0/0", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + EXPECT_TRUE(GetValueByPointer(v, "/foo/0/a", &unresolvedTokenIndex) == 0); // "/foo/0" is an string, cannot further query + EXPECT_EQ(2u, unresolvedTokenIndex); + +} + +TEST(Pointer, GetValueByPointerWithDefault_Pointer) { + Document d; + d.Parse(kJson); + + Document::AllocatorType& a = d.GetAllocator(); + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v, a)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v, a)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v, a)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move(), a)); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move(), a).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x", a).IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1, a).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2, a).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321, a).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678, a).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64, a).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1, a).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64, a).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1, a).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true, a).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false, a).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false, a).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true, a).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello", a).GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer, a).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++"), a).GetString()); +#endif +} + +TEST(Pointer, GetValueByPointerWithDefault_String) { + Document d; + d.Parse(kJson); + + Document::AllocatorType& a = d.GetAllocator(); + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v, a)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v, a)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v, a)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move(), a)); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move(), a).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x", a).IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1, a).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2, a).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321, a).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678, a).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64, a).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1, a).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64, a).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1, a).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true, a).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false, a).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false, a).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true, a).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello", a).GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer, a).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, "/foo/C++", std::string("C++"), a).GetString()); +#endif +} + +TEST(Pointer, GetValueByPointerWithDefault_Pointer_NoAllocator) { + Document d; + d.Parse(kJson); + + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, Pointer("/foo/0"), v)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, Pointer("/foo/1"), v)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, Pointer("/foo/2"), v)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, Pointer("/foo/-"), Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), Value().Move()).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/null"), "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -1).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, Pointer("/foo/int"), -2).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, Pointer("/foo/uint"), 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, Pointer("/foo/int64"), i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, Pointer("/foo/uint64"), u64 - 1).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), true).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/true"), false).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), false).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, Pointer("/foo/false"), true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, Pointer("/foo/hello"), "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, Pointer("/foo/world"), buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, Pointer("/foo/world"))->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString()); +#endif +} + +TEST(Pointer, GetValueByPointerWithDefault_String_NoAllocator) { + Document d; + d.Parse(kJson); + + const Value v("qux"); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v)); + EXPECT_TRUE(Value("bar") == GetValueByPointerWithDefault(d, "/foo/0", v)); + EXPECT_TRUE(Value("baz") == GetValueByPointerWithDefault(d, "/foo/1", v)); + EXPECT_TRUE(Value("qux") == GetValueByPointerWithDefault(d, "/foo/2", v)); + EXPECT_TRUE(Value("last") == GetValueByPointerWithDefault(d, "/foo/-", Value("last").Move())); + EXPECT_STREQ("last", d["foo"][3].GetString()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", Value().Move()).IsNull()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/null", "x").IsNull()); + + // Generic version + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -1).GetInt()); + EXPECT_EQ(-1, GetValueByPointerWithDefault(d, "/foo/int", -2).GetInt()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x87654321).GetUint()); + EXPECT_EQ(0x87654321, GetValueByPointerWithDefault(d, "/foo/uint", 0x12345678).GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64).GetInt64()); + EXPECT_EQ(i64, GetValueByPointerWithDefault(d, "/foo/int64", i64 + 1).GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64).GetUint64()); + EXPECT_EQ(u64, GetValueByPointerWithDefault(d, "/foo/uint64", u64 - 1).GetUint64()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", true).IsTrue()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/true", false).IsTrue()); + + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", false).IsFalse()); + EXPECT_TRUE(GetValueByPointerWithDefault(d, "/foo/false", true).IsFalse()); + + // StringRef version + EXPECT_STREQ("Hello", GetValueByPointerWithDefault(d, "/foo/hello", "Hello").GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + EXPECT_STREQ("World", GetValueByPointerWithDefault(d, "/foo/world", buffer).GetString()); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("C++", GetValueByPointerWithDefault(d, Pointer("/foo/C++"), std::string("C++")).GetString()); +#endif +} + +TEST(Pointer, SetValueByPointer_Pointer) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + + // Value version + SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move(), a); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, Pointer("/foo/null"), Value().Move(), a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, Pointer("/clone"), foo, a); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + + // Generic version + SetValueByPointer(d, Pointer("/foo/int"), -1, a); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321, a); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, Pointer("/foo/int64"), i64, a); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, Pointer("/foo/uint64"), u64, a); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, Pointer("/foo/true"), true, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, Pointer("/foo/false"), false, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, Pointer("/foo/hello"), "Hello", a); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, Pointer("/foo/world"), buffer, a); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++"), a); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif +} + +TEST(Pointer, SetValueByPointer_String) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + + // Value version + SetValueByPointer(d, "/foo/0", Value(123).Move(), a); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, "/foo/null", Value().Move(), a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, "/clone", foo, a); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + + // Generic version + SetValueByPointer(d, "/foo/int", -1, a); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, "/foo/uint", 0x87654321, a); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, "/foo/int64", i64, a); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, "/foo/uint64", u64, a); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, "/foo/true", true, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, "/foo/false", false, a); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, "/foo/hello", "Hello", a); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, "/foo/world", buffer, a); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, "/foo/c++", std::string("C++"), a); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif +} + +TEST(Pointer, SetValueByPointer_Pointer_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + SetValueByPointer(d, Pointer("/foo/0"), Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, Pointer("/foo/null"), Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, Pointer("/clone"), foo); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + + // Generic version + SetValueByPointer(d, Pointer("/foo/int"), -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, Pointer("/foo/uint"), 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, Pointer("/foo/int64"), i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, Pointer("/foo/uint64"), u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, Pointer("/foo/true"), true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, Pointer("/foo/false"), false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, Pointer("/foo/hello"), "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, Pointer("/foo/world"), buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, Pointer("/foo/c++"), std::string("C++")); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif +} + +TEST(Pointer, SetValueByPointer_String_NoAllocator) { + Document d; + d.Parse(kJson); + + // Value version + SetValueByPointer(d, "/foo/0", Value(123).Move()); + EXPECT_EQ(123, d["foo"][0].GetInt()); + + SetValueByPointer(d, "/foo/null", Value().Move()); + EXPECT_TRUE(GetValueByPointer(d, "/foo/null")->IsNull()); + + // Const Value version + const Value foo(d["foo"], d.GetAllocator()); + SetValueByPointer(d, "/clone", foo); + EXPECT_EQ(foo, *GetValueByPointer(d, "/clone")); + + // Generic version + SetValueByPointer(d, "/foo/int", -1); + EXPECT_EQ(-1, GetValueByPointer(d, "/foo/int")->GetInt()); + + SetValueByPointer(d, "/foo/uint", 0x87654321); + EXPECT_EQ(0x87654321, GetValueByPointer(d, "/foo/uint")->GetUint()); + + const int64_t i64 = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0)); + SetValueByPointer(d, "/foo/int64", i64); + EXPECT_EQ(i64, GetValueByPointer(d, "/foo/int64")->GetInt64()); + + const uint64_t u64 = RAPIDJSON_UINT64_C2(0xFFFFFFFFF, 0xFFFFFFFFF); + SetValueByPointer(d, "/foo/uint64", u64); + EXPECT_EQ(u64, GetValueByPointer(d, "/foo/uint64")->GetUint64()); + + SetValueByPointer(d, "/foo/true", true); + EXPECT_TRUE(GetValueByPointer(d, "/foo/true")->IsTrue()); + + SetValueByPointer(d, "/foo/false", false); + EXPECT_TRUE(GetValueByPointer(d, "/foo/false")->IsFalse()); + + // StringRef version + SetValueByPointer(d, "/foo/hello", "Hello"); + EXPECT_STREQ("Hello", GetValueByPointer(d, "/foo/hello")->GetString()); + + // Copy string version + { + char buffer[256]; + strcpy(buffer, "World"); + SetValueByPointer(d, "/foo/world", buffer); + memset(buffer, 0, sizeof(buffer)); + } + EXPECT_STREQ("World", GetValueByPointer(d, "/foo/world")->GetString()); + +#if RAPIDJSON_HAS_STDSTRING + SetValueByPointer(d, "/foo/c++", std::string("C++")); + EXPECT_STREQ("C++", GetValueByPointer(d, "/foo/c++")->GetString()); +#endif +} + +TEST(Pointer, SwapValueByPointer) { + Document d; + d.Parse(kJson); + Document::AllocatorType& a = d.GetAllocator(); + SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1"), a); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); + + SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1"), a); + EXPECT_STREQ("bar", d["foo"][0].GetString()); + EXPECT_STREQ("baz", d["foo"][1].GetString()); +} + +TEST(Pointer, SwapValueByPointer_NoAllocator) { + Document d; + d.Parse(kJson); + SwapValueByPointer(d, Pointer("/foo/0"), *GetValueByPointer(d, "/foo/1")); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_STREQ("bar", d["foo"][1].GetString()); + + SwapValueByPointer(d, "/foo/0", *GetValueByPointer(d, "/foo/1")); + EXPECT_STREQ("bar", d["foo"][0].GetString()); + EXPECT_STREQ("baz", d["foo"][1].GetString()); +} + +TEST(Pointer, EraseValueByPointer_Pointer) { + Document d; + d.Parse(kJson); + + EXPECT_FALSE(EraseValueByPointer(d, Pointer(""))); + EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0"))); + EXPECT_EQ(1u, d["foo"].Size()); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo/0"))); + EXPECT_TRUE(d["foo"].Empty()); + EXPECT_TRUE(EraseValueByPointer(d, Pointer("/foo"))); + EXPECT_TRUE(Pointer("/foo").Get(d) == 0); +} + +TEST(Pointer, EraseValueByPointer_String) { + Document d; + d.Parse(kJson); + + EXPECT_FALSE(EraseValueByPointer(d, "")); + EXPECT_FALSE(Pointer("/foo/nonexist").Erase(d)); + EXPECT_TRUE(EraseValueByPointer(d, "/foo/0")); + EXPECT_EQ(1u, d["foo"].Size()); + EXPECT_STREQ("baz", d["foo"][0].GetString()); + EXPECT_TRUE(EraseValueByPointer(d, "/foo/0")); + EXPECT_TRUE(d["foo"].Empty()); + EXPECT_TRUE(EraseValueByPointer(d, "/foo")); + EXPECT_TRUE(Pointer("/foo").Get(d) == 0); +} + +TEST(Pointer, Ambiguity) { + { + Document d; + d.Parse("{\"0\" : [123]}"); + EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt()); + Pointer("/0/a").Set(d, 456); // Change array [123] to object {456} + EXPECT_EQ(456, Pointer("/0/a").Get(d)->GetInt()); + } + + { + Document d; + EXPECT_FALSE(d.Parse("[{\"0\": 123}]").HasParseError()); + EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt()); + Pointer("/0/1").Set(d, 456); // 1 is treated as "1" to index object + EXPECT_EQ(123, Pointer("/0/0").Get(d)->GetInt()); + EXPECT_EQ(456, Pointer("/0/1").Get(d)->GetInt()); + } +} + +TEST(Pointer, ResolveOnObject) { + Document d; + EXPECT_FALSE(d.Parse("{\"a\": 123}").HasParseError()); + + { + Value::ConstObject o = static_cast(d).GetObject(); + EXPECT_EQ(123, Pointer("/a").Get(o)->GetInt()); + } + + { + Value::Object o = d.GetObject(); + Pointer("/a").Set(o, 456, d.GetAllocator()); + EXPECT_EQ(456, Pointer("/a").Get(o)->GetInt()); + } +} + +TEST(Pointer, ResolveOnArray) { + Document d; + EXPECT_FALSE(d.Parse("[1, 2, 3]").HasParseError()); + + { + Value::ConstArray a = static_cast(d).GetArray(); + EXPECT_EQ(2, Pointer("/1").Get(a)->GetInt()); + } + + { + Value::Array a = d.GetArray(); + Pointer("/1").Set(a, 123, d.GetAllocator()); + EXPECT_EQ(123, Pointer("/1").Get(a)->GetInt()); + } +} + +TEST(Pointer, LessThan) { + static const struct { + const char *str; + bool valid; + } pointers[] = { + { "/a/b", true }, + { "/a", true }, + { "/d/1", true }, + { "/d/2/z", true }, + { "/d/2/3", true }, + { "/d/2", true }, + { "/a/c", true }, + { "/e/f~g", false }, + { "/d/2/zz", true }, + { "/d/1", true }, + { "/d/2/z", true }, + { "/e/f~~g", false }, + { "/e/f~0g", true }, + { "/e/f~1g", true }, + { "/e/f.g", true }, + { "", true } + }; + static const char *ordered_pointers[] = { + "", + "/a", + "/a/b", + "/a/c", + "/d/1", + "/d/1", + "/d/2", + "/e/f.g", + "/e/f~1g", + "/e/f~0g", + "/d/2/3", + "/d/2/z", + "/d/2/z", + "/d/2/zz", + NULL, // was invalid "/e/f~g" + NULL // was invalid "/e/f~~g" + }; + typedef MemoryPoolAllocator<> AllocatorType; + typedef GenericPointer PointerType; + typedef std::multimap PointerMap; + PointerMap map; + PointerMap::iterator it; + AllocatorType allocator; + size_t i; + + EXPECT_EQ(sizeof(pointers) / sizeof(pointers[0]), + sizeof(ordered_pointers) / sizeof(ordered_pointers[0])); + + for (i = 0; i < sizeof(pointers) / sizeof(pointers[0]); ++i) { + it = map.insert(PointerMap::value_type(PointerType(pointers[i].str, &allocator), i)); + if (!it->first.IsValid()) { + EXPECT_EQ(++it, map.end()); + } + } + + for (i = 0, it = map.begin(); it != map.end(); ++it, ++i) { + EXPECT_TRUE(it->second < sizeof(pointers) / sizeof(pointers[0])); + EXPECT_EQ(it->first.IsValid(), pointers[it->second].valid); + EXPECT_TRUE(i < sizeof(ordered_pointers) / sizeof(ordered_pointers[0])); + EXPECT_EQ(it->first.IsValid(), !!ordered_pointers[i]); + if (it->first.IsValid()) { + std::stringstream ss; + OStreamWrapper os(ss); + EXPECT_TRUE(it->first.Stringify(os)); + EXPECT_EQ(ss.str(), pointers[it->second].str); + EXPECT_EQ(ss.str(), ordered_pointers[i]); + } + } +} + +// https://github.com/Tencent/rapidjson/issues/483 +namespace myjson { + +class MyAllocator +{ +public: + static const bool kNeedFree = true; + void * Malloc(size_t _size) { return malloc(_size); } + void * Realloc(void *_org_p, size_t _org_size, size_t _new_size) { (void)_org_size; return realloc(_org_p, _new_size); } + static void Free(void *_p) { return free(_p); } +}; + +typedef rapidjson::GenericDocument< + rapidjson::UTF8<>, + rapidjson::MemoryPoolAllocator< MyAllocator >, + MyAllocator + > Document; + +typedef rapidjson::GenericPointer< + ::myjson::Document::ValueType, + MyAllocator + > Pointer; + +typedef ::myjson::Document::ValueType Value; + +} + +TEST(Pointer, Issue483) { + std::string mystr, path; + myjson::Document document; + myjson::Value value(rapidjson::kStringType); + value.SetString(mystr.c_str(), static_cast(mystr.length()), document.GetAllocator()); + myjson::Pointer(path.c_str()).Set(document, value, document.GetAllocator()); +} + +TEST(Pointer, Issue1899) { + typedef GenericPointer > PointerType; + PointerType p; + PointerType q = p.Append("foo"); + EXPECT_TRUE(PointerType("/foo") == q); + q = q.Append(1234); + EXPECT_TRUE(PointerType("/foo/1234") == q); + q = q.Append(""); + EXPECT_TRUE(PointerType("/foo/1234/") == q); +} diff --git a/deps/rapidjson/test/unittest/prettywritertest.cpp b/deps/rapidjson/test/unittest/prettywritertest.cpp new file mode 100644 index 0000000..0b7feef --- /dev/null +++ b/deps/rapidjson/test/unittest/prettywritertest.cpp @@ -0,0 +1,373 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/reader.h" +#include "rapidjson/prettywriter.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/filewritestream.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +using namespace rapidjson; + +static const char kJson[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3,-1],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}"; +static const char kPrettyJson[] = +"{\n" +" \"hello\": \"world\",\n" +" \"t\": true,\n" +" \"f\": false,\n" +" \"n\": null,\n" +" \"i\": 123,\n" +" \"pi\": 3.1416,\n" +" \"a\": [\n" +" 1,\n" +" 2,\n" +" 3,\n" +" -1\n" +" ],\n" +" \"u64\": 1234567890123456789,\n" +" \"i64\": -1234567890123456789\n" +"}"; + +static const char kPrettyJson_FormatOptions_SLA[] = +"{\n" +" \"hello\": \"world\",\n" +" \"t\": true,\n" +" \"f\": false,\n" +" \"n\": null,\n" +" \"i\": 123,\n" +" \"pi\": 3.1416,\n" +" \"a\": [1, 2, 3, -1],\n" +" \"u64\": 1234567890123456789,\n" +" \"i64\": -1234567890123456789\n" +"}"; + +TEST(PrettyWriter, Basic) { + StringBuffer buffer; + PrettyWriter writer(buffer); + Reader reader; + StringStream s(kJson); + reader.Parse(s, writer); + EXPECT_STREQ(kPrettyJson, buffer.GetString()); +} + +TEST(PrettyWriter, FormatOptions) { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.SetFormatOptions(kFormatSingleLineArray); + Reader reader; + StringStream s(kJson); + reader.Parse(s, writer); + EXPECT_STREQ(kPrettyJson_FormatOptions_SLA, buffer.GetString()); +} + +TEST(PrettyWriter, SetIndent) { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.SetIndent('\t', 1); + Reader reader; + StringStream s(kJson); + reader.Parse(s, writer); + EXPECT_STREQ( + "{\n" + "\t\"hello\": \"world\",\n" + "\t\"t\": true,\n" + "\t\"f\": false,\n" + "\t\"n\": null,\n" + "\t\"i\": 123,\n" + "\t\"pi\": 3.1416,\n" + "\t\"a\": [\n" + "\t\t1,\n" + "\t\t2,\n" + "\t\t3,\n" + "\t\t-1\n" + "\t],\n" + "\t\"u64\": 1234567890123456789,\n" + "\t\"i64\": -1234567890123456789\n" + "}", + buffer.GetString()); +} + +TEST(PrettyWriter, String) { + StringBuffer buffer; + PrettyWriter writer(buffer); + EXPECT_TRUE(writer.StartArray()); + EXPECT_TRUE(writer.String("Hello\n")); + EXPECT_TRUE(writer.EndArray()); + EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString()); +} + +#if RAPIDJSON_HAS_STDSTRING +TEST(PrettyWriter, String_STDSTRING) { + StringBuffer buffer; + PrettyWriter writer(buffer); + EXPECT_TRUE(writer.StartArray()); + EXPECT_TRUE(writer.String(std::string("Hello\n"))); + EXPECT_TRUE(writer.EndArray()); + EXPECT_STREQ("[\n \"Hello\\n\"\n]", buffer.GetString()); +} +#endif + +#include + +class OStreamWrapper { +public: + typedef char Ch; + + OStreamWrapper(std::ostream& os) : os_(os) {} + + Ch Peek() const { assert(false); return '\0'; } + Ch Take() { assert(false); return '\0'; } + size_t Tell() const { return 0; } + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch c) { os_.put(c); } + void Flush() { os_.flush(); } + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + OStreamWrapper(const OStreamWrapper&); + OStreamWrapper& operator=(const OStreamWrapper&); + + std::ostream& os_; +}; + +// For covering PutN() generic version +TEST(PrettyWriter, OStreamWrapper) { + StringStream s(kJson); + + std::stringstream ss; + OStreamWrapper os(ss); + + PrettyWriter writer(os); + + Reader reader; + reader.Parse(s, writer); + + std::string actual = ss.str(); + EXPECT_STREQ(kPrettyJson, actual.c_str()); +} + +// For covering FileWriteStream::PutN() +TEST(PrettyWriter, FileWriteStream) { + char filename[L_tmpnam]; + FILE* fp = TempFile(filename); + ASSERT_TRUE(fp!=NULL); + char buffer[16]; + FileWriteStream os(fp, buffer, sizeof(buffer)); + PrettyWriter writer(os); + Reader reader; + StringStream s(kJson); + reader.Parse(s, writer); + fclose(fp); + + fp = fopen(filename, "rb"); + fseek(fp, 0, SEEK_END); + size_t size = static_cast(ftell(fp)); + fseek(fp, 0, SEEK_SET); + char* json = static_cast(malloc(size + 1)); + size_t readLength = fread(json, 1, size, fp); + json[readLength] = '\0'; + fclose(fp); + remove(filename); + EXPECT_STREQ(kPrettyJson, json); + free(json); +} + +TEST(PrettyWriter, RawValue) { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + writer.Key("a"); + writer.Int(1); + writer.Key("raw"); + const char json[] = "[\"Hello\\nWorld\", 123.456]"; + writer.RawValue(json, strlen(json), kArrayType); + writer.EndObject(); + EXPECT_TRUE(writer.IsComplete()); + EXPECT_STREQ( + "{\n" + " \"a\": 1,\n" + " \"raw\": [\"Hello\\nWorld\", 123.456]\n" // no indentation within raw value + "}", + buffer.GetString()); +} + +TEST(PrettyWriter, InvalidEventSequence) { + // {] + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + EXPECT_THROW(writer.EndArray(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // [} + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartArray(); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 1: + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + EXPECT_THROW(writer.Int(1), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 'a' } + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + writer.Key("a"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 'a':'b','c' } + { + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartObject(); + writer.Key("a"); + writer.String("b"); + writer.Key("c"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } +} + +TEST(PrettyWriter, NaN) { + double nan = std::numeric_limits::quiet_NaN(); + + EXPECT_TRUE(internal::Double(nan).IsNan()); + StringBuffer buffer; + { + PrettyWriter writer(buffer); + EXPECT_FALSE(writer.Double(nan)); + } + { + PrettyWriter, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer); + EXPECT_TRUE(writer.Double(nan)); + EXPECT_STREQ("NaN", buffer.GetString()); + } + GenericStringBuffer > buffer2; + PrettyWriter > > writer2(buffer2); + EXPECT_FALSE(writer2.Double(nan)); +} + +TEST(PrettyWriter, Inf) { + double inf = std::numeric_limits::infinity(); + + EXPECT_TRUE(internal::Double(inf).IsInf()); + StringBuffer buffer; + { + PrettyWriter writer(buffer); + EXPECT_FALSE(writer.Double(inf)); + } + { + PrettyWriter writer(buffer); + EXPECT_FALSE(writer.Double(-inf)); + } + { + PrettyWriter, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer); + EXPECT_TRUE(writer.Double(inf)); + } + { + PrettyWriter, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer); + EXPECT_TRUE(writer.Double(-inf)); + } + EXPECT_STREQ("Infinity-Infinity", buffer.GetString()); +} + +TEST(PrettyWriter, Issue_889) { + char buf[100] = "Hello"; + + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.StartArray(); + writer.String(buf); + writer.EndArray(); + + EXPECT_STREQ("[\n \"Hello\"\n]", buffer.GetString()); + EXPECT_TRUE(writer.IsComplete()); \ +} + + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + +static PrettyWriter WriterGen(StringBuffer &target) { + PrettyWriter writer(target); + writer.StartObject(); + writer.Key("a"); + writer.Int(1); + return writer; +} + +TEST(PrettyWriter, MoveCtor) { + StringBuffer buffer; + PrettyWriter writer(WriterGen(buffer)); + writer.EndObject(); + EXPECT_TRUE(writer.IsComplete()); + EXPECT_STREQ( + "{\n" + " \"a\": 1\n" + "}", + buffer.GetString()); +} +#endif + +TEST(PrettyWriter, Issue_1336) { +#define T(meth, val, expected) \ + { \ + StringBuffer buffer; \ + PrettyWriter writer(buffer); \ + writer.meth(val); \ + \ + EXPECT_STREQ(expected, buffer.GetString()); \ + EXPECT_TRUE(writer.IsComplete()); \ + } + + T(Bool, false, "false"); + T(Bool, true, "true"); + T(Int, 0, "0"); + T(Uint, 0, "0"); + T(Int64, 0, "0"); + T(Uint64, 0, "0"); + T(Double, 0, "0.0"); + T(String, "Hello", "\"Hello\""); +#undef T + + StringBuffer buffer; + PrettyWriter writer(buffer); + writer.Null(); + + EXPECT_STREQ("null", buffer.GetString()); + EXPECT_TRUE(writer.IsComplete()); +} + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/readertest.cpp b/deps/rapidjson/test/unittest/readertest.cpp new file mode 100644 index 0000000..f828dbb --- /dev/null +++ b/deps/rapidjson/test/unittest/readertest.cpp @@ -0,0 +1,2370 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/reader.h" +#include "rapidjson/internal/dtoa.h" +#include "rapidjson/internal/itoa.h" +#include "rapidjson/memorystream.h" + +#include + +using namespace rapidjson; + +RAPIDJSON_DIAG_PUSH +#ifdef __GNUC__ +RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(float-equal) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#if __GNUC__ >= 7 +RAPIDJSON_DIAG_OFF(dangling-else) +#endif +#endif // __GNUC__ + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(variadic-macros) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) +#endif + +template +struct ParseBoolHandler : BaseReaderHandler, ParseBoolHandler > { + ParseBoolHandler() : step_(0) {} + bool Default() { ADD_FAILURE(); return false; } + // gcc 4.8.x generates warning in EXPECT_EQ(bool, bool) on this gtest version. + // Workaround with EXPECT_TRUE(). + bool Bool(bool b) { /*EXPECT_EQ(expect, b); */EXPECT_TRUE(expect == b); ++step_; return true; } + + unsigned step_; +}; + +TEST(Reader, ParseTrue) { + StringStream s("true"); + ParseBoolHandler h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(1u, h.step_); +} + +TEST(Reader, ParseFalse) { + StringStream s("false"); + ParseBoolHandler h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(1u, h.step_); +} + +struct ParseIntHandler : BaseReaderHandler, ParseIntHandler> { + ParseIntHandler() : step_(0), actual_() {} + bool Default() { ADD_FAILURE(); return false; } + bool Int(int i) { actual_ = i; step_++; return true; } + + unsigned step_; + int actual_; +}; + +struct ParseUintHandler : BaseReaderHandler, ParseUintHandler> { + ParseUintHandler() : step_(0), actual_() {} + bool Default() { ADD_FAILURE(); return false; } + bool Uint(unsigned i) { actual_ = i; step_++; return true; } + + unsigned step_; + unsigned actual_; +}; + +struct ParseInt64Handler : BaseReaderHandler, ParseInt64Handler> { + ParseInt64Handler() : step_(0), actual_() {} + bool Default() { ADD_FAILURE(); return false; } + bool Int64(int64_t i) { actual_ = i; step_++; return true; } + + unsigned step_; + int64_t actual_; +}; + +struct ParseUint64Handler : BaseReaderHandler, ParseUint64Handler> { + ParseUint64Handler() : step_(0), actual_() {} + bool Default() { ADD_FAILURE(); return false; } + bool Uint64(uint64_t i) { actual_ = i; step_++; return true; } + + unsigned step_; + uint64_t actual_; +}; + +struct ParseDoubleHandler : BaseReaderHandler, ParseDoubleHandler> { + ParseDoubleHandler() : step_(0), actual_() {} + bool Default() { ADD_FAILURE(); return false; } + bool Double(double d) { actual_ = d; step_++; return true; } + + unsigned step_; + double actual_; +}; + +TEST(Reader, ParseNumber_Integer) { +#define TEST_INTEGER(Handler, str, x) \ + { \ + StringStream s(str); \ + Handler h; \ + Reader reader; \ + reader.Parse(s, h); \ + EXPECT_EQ(1u, h.step_); \ + EXPECT_EQ(x, h.actual_); \ + } + + TEST_INTEGER(ParseUintHandler, "0", 0u); + TEST_INTEGER(ParseUintHandler, "123", 123u); + TEST_INTEGER(ParseUintHandler, "2147483648", 2147483648u); // 2^31 - 1 (cannot be stored in int) + TEST_INTEGER(ParseUintHandler, "4294967295", 4294967295u); + + TEST_INTEGER(ParseIntHandler, "-123", -123); + TEST_INTEGER(ParseIntHandler, "-2147483648", static_cast(0x80000000)); // -2^31 (min of int) + + TEST_INTEGER(ParseUint64Handler, "4294967296", RAPIDJSON_UINT64_C2(1, 0)); // 2^32 (max of unsigned + 1, force to use uint64_t) + TEST_INTEGER(ParseUint64Handler, "18446744073709551615", RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)); // 2^64 - 1 (max of uint64_t) + + TEST_INTEGER(ParseInt64Handler, "-2147483649", static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x7FFFFFFF))); // -2^31 -1 (min of int - 1, force to use int64_t) + TEST_INTEGER(ParseInt64Handler, "-9223372036854775808", static_cast(RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))); // -2^63 (min of int64_t) + + // Random test for uint32_t/int32_t + { + union { + uint32_t u; + int32_t i; + }u; + Random r; + + for (unsigned i = 0; i < 100000; i++) { + u.u = r(); + + char buffer[32]; + *internal::u32toa(u.u, buffer) = '\0'; + TEST_INTEGER(ParseUintHandler, buffer, u.u); + + if (u.i < 0) { + *internal::i32toa(u.i, buffer) = '\0'; + TEST_INTEGER(ParseIntHandler, buffer, u.i); + } + } + } + + // Random test for uint64_t/int64_t + { + union { + uint64_t u; + int64_t i; + }u; + Random r; + + for (unsigned i = 0; i < 100000; i++) { + u.u = uint64_t(r()) << 32; + u.u |= r(); + + char buffer[32]; + if (u.u > uint64_t(4294967295u)) { + *internal::u64toa(u.u, buffer) = '\0'; + TEST_INTEGER(ParseUint64Handler, buffer, u.u); + } + + if (u.i < -int64_t(2147483648u)) { + *internal::i64toa(u.i, buffer) = '\0'; + TEST_INTEGER(ParseInt64Handler, buffer, u.i); + } + } + } +#undef TEST_INTEGER +} + +template +static void TestParseDouble() { +#define TEST_DOUBLE(fullPrecision, str, x) \ + { \ + StringStream s(str); \ + ParseDoubleHandler h; \ + Reader reader; \ + ASSERT_EQ(kParseErrorNone, reader.Parse(s, h).Code()); \ + EXPECT_EQ(1u, h.step_); \ + internal::Double e(x), a(h.actual_); \ + if (fullPrecision) { \ + EXPECT_EQ(e.Uint64Value(), a.Uint64Value()); \ + if (e.Uint64Value() != a.Uint64Value()) \ + printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", str, h.actual_, x); \ + } \ + else { \ + EXPECT_EQ(e.Sign(), a.Sign()); /* for 0.0 != -0.0 */ \ + EXPECT_DOUBLE_EQ(x, h.actual_); \ + } \ + } + + TEST_DOUBLE(fullPrecision, "0.0", 0.0); + TEST_DOUBLE(fullPrecision, "-0.0", -0.0); // For checking issue #289 + TEST_DOUBLE(fullPrecision, "0e100", 0.0); // For checking issue #1249 + TEST_DOUBLE(fullPrecision, "1.0", 1.0); + TEST_DOUBLE(fullPrecision, "-1.0", -1.0); + TEST_DOUBLE(fullPrecision, "1.5", 1.5); + TEST_DOUBLE(fullPrecision, "-1.5", -1.5); + TEST_DOUBLE(fullPrecision, "3.1416", 3.1416); + TEST_DOUBLE(fullPrecision, "1E10", 1E10); + TEST_DOUBLE(fullPrecision, "1e10", 1e10); + TEST_DOUBLE(fullPrecision, "1E+10", 1E+10); + TEST_DOUBLE(fullPrecision, "1E-10", 1E-10); + TEST_DOUBLE(fullPrecision, "-1E10", -1E10); + TEST_DOUBLE(fullPrecision, "-1e10", -1e10); + TEST_DOUBLE(fullPrecision, "-1E+10", -1E+10); + TEST_DOUBLE(fullPrecision, "-1E-10", -1E-10); + TEST_DOUBLE(fullPrecision, "1.234E+10", 1.234E+10); + TEST_DOUBLE(fullPrecision, "1.234E-10", 1.234E-10); + TEST_DOUBLE(fullPrecision, "1.79769e+308", 1.79769e+308); + TEST_DOUBLE(fullPrecision, "2.22507e-308", 2.22507e-308); + TEST_DOUBLE(fullPrecision, "-1.79769e+308", -1.79769e+308); + TEST_DOUBLE(fullPrecision, "-2.22507e-308", -2.22507e-308); + TEST_DOUBLE(fullPrecision, "4.9406564584124654e-324", 4.9406564584124654e-324); // minimum denormal + TEST_DOUBLE(fullPrecision, "2.2250738585072009e-308", 2.2250738585072009e-308); // Max subnormal double + TEST_DOUBLE(fullPrecision, "2.2250738585072014e-308", 2.2250738585072014e-308); // Min normal positive double + TEST_DOUBLE(fullPrecision, "1.7976931348623157e+308", 1.7976931348623157e+308); // Max double + TEST_DOUBLE(fullPrecision, "1e-10000", 0.0); // must underflow + TEST_DOUBLE(fullPrecision, "18446744073709551616", 18446744073709551616.0); // 2^64 (max of uint64_t + 1, force to use double) + TEST_DOUBLE(fullPrecision, "-9223372036854775809", -9223372036854775809.0); // -2^63 - 1(min of int64_t + 1, force to use double) + TEST_DOUBLE(fullPrecision, "0.9868011474609375", 0.9868011474609375); // https://github.com/Tencent/rapidjson/issues/120 + TEST_DOUBLE(fullPrecision, "123e34", 123e34); // Fast Path Cases In Disguise + TEST_DOUBLE(fullPrecision, "45913141877270640000.0", 45913141877270640000.0); + TEST_DOUBLE(fullPrecision, "2.2250738585072011e-308", 2.2250738585072011e-308); // http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ + TEST_DOUBLE(fullPrecision, "1e-00011111111111", 0.0); // Issue #313 + TEST_DOUBLE(fullPrecision, "-1e-00011111111111", -0.0); + TEST_DOUBLE(fullPrecision, "1e-214748363", 0.0); // Maximum supported negative exponent + TEST_DOUBLE(fullPrecision, "1e-214748364", 0.0); + TEST_DOUBLE(fullPrecision, "1e-21474836311", 0.0); + TEST_DOUBLE(fullPrecision, "1.00000000001e-2147483638", 0.0); + TEST_DOUBLE(fullPrecision, "0.017976931348623157e+310", 1.7976931348623157e+308); // Max double in another form + TEST_DOUBLE(fullPrecision, "128.74836467836484838364836483643636483648e-336", 0.0); // Issue #1251 + + // Since + // abs((2^-1022 - 2^-1074) - 2.2250738585072012e-308) = 3.109754131239141401123495768877590405345064751974375599... x 10^-324 + // abs((2^-1022) - 2.2250738585072012e-308) = 1.830902327173324040642192159804623318305533274168872044... x 10 ^ -324 + // So 2.2250738585072012e-308 should round to 2^-1022 = 2.2250738585072014e-308 + TEST_DOUBLE(fullPrecision, "2.2250738585072012e-308", 2.2250738585072014e-308); // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ + + // More closer to normal/subnormal boundary + // boundary = 2^-1022 - 2^-1075 = 2.225073858507201136057409796709131975934819546351645648... x 10^-308 + TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164564e-308", 2.2250738585072009e-308); + TEST_DOUBLE(fullPrecision, "2.22507385850720113605740979670913197593481954635164565e-308", 2.2250738585072014e-308); + + // 1.0 is in (1.0 - 2^-54, 1.0 + 2^-53) + // 1.0 - 2^-54 = 0.999999999999999944488848768742172978818416595458984375 + TEST_DOUBLE(fullPrecision, "0.999999999999999944488848768742172978818416595458984375", 1.0); // round to even + TEST_DOUBLE(fullPrecision, "0.999999999999999944488848768742172978818416595458984374", 0.99999999999999989); // previous double + TEST_DOUBLE(fullPrecision, "0.999999999999999944488848768742172978818416595458984376", 1.0); // next double + // 1.0 + 2^-53 = 1.00000000000000011102230246251565404236316680908203125 + TEST_DOUBLE(fullPrecision, "1.00000000000000011102230246251565404236316680908203125", 1.0); // round to even + TEST_DOUBLE(fullPrecision, "1.00000000000000011102230246251565404236316680908203124", 1.0); // previous double + TEST_DOUBLE(fullPrecision, "1.00000000000000011102230246251565404236316680908203126", 1.00000000000000022); // next double + + // Numbers from https://github.com/floitsch/double-conversion/blob/master/test/cctest/test-strtod.cc + + TEST_DOUBLE(fullPrecision, "72057594037927928.0", 72057594037927928.0); + TEST_DOUBLE(fullPrecision, "72057594037927936.0", 72057594037927936.0); + TEST_DOUBLE(fullPrecision, "72057594037927932.0", 72057594037927936.0); + TEST_DOUBLE(fullPrecision, "7205759403792793199999e-5", 72057594037927928.0); + TEST_DOUBLE(fullPrecision, "7205759403792793200001e-5", 72057594037927936.0); + + TEST_DOUBLE(fullPrecision, "9223372036854774784.0", 9223372036854774784.0); + TEST_DOUBLE(fullPrecision, "9223372036854775808.0", 9223372036854775808.0); + TEST_DOUBLE(fullPrecision, "9223372036854775296.0", 9223372036854775808.0); + TEST_DOUBLE(fullPrecision, "922337203685477529599999e-5", 9223372036854774784.0); + TEST_DOUBLE(fullPrecision, "922337203685477529600001e-5", 9223372036854775808.0); + + TEST_DOUBLE(fullPrecision, "10141204801825834086073718800384", 10141204801825834086073718800384.0); + TEST_DOUBLE(fullPrecision, "10141204801825835211973625643008", 10141204801825835211973625643008.0); + TEST_DOUBLE(fullPrecision, "10141204801825834649023672221696", 10141204801825835211973625643008.0); + TEST_DOUBLE(fullPrecision, "1014120480182583464902367222169599999e-5", 10141204801825834086073718800384.0); + TEST_DOUBLE(fullPrecision, "1014120480182583464902367222169600001e-5", 10141204801825835211973625643008.0); + + TEST_DOUBLE(fullPrecision, "5708990770823838890407843763683279797179383808", 5708990770823838890407843763683279797179383808.0); + TEST_DOUBLE(fullPrecision, "5708990770823839524233143877797980545530986496", 5708990770823839524233143877797980545530986496.0); + TEST_DOUBLE(fullPrecision, "5708990770823839207320493820740630171355185152", 5708990770823839524233143877797980545530986496.0); + TEST_DOUBLE(fullPrecision, "5708990770823839207320493820740630171355185151999e-3", 5708990770823838890407843763683279797179383808.0); + TEST_DOUBLE(fullPrecision, "5708990770823839207320493820740630171355185152001e-3", 5708990770823839524233143877797980545530986496.0); + + { + char n1e308[310]; // '1' followed by 308 '0' + n1e308[0] = '1'; + for (int i = 1; i < 309; i++) + n1e308[i] = '0'; + n1e308[309] = '\0'; + TEST_DOUBLE(fullPrecision, n1e308, 1E308); + } + + // Cover trimming + TEST_DOUBLE(fullPrecision, +"2.22507385850720113605740979670913197593481954635164564802342610972482222202107694551652952390813508" +"7914149158913039621106870086438694594645527657207407820621743379988141063267329253552286881372149012" +"9811224514518898490572223072852551331557550159143974763979834118019993239625482890171070818506906306" +"6665599493827577257201576306269066333264756530000924588831643303777979186961204949739037782970490505" +"1080609940730262937128958950003583799967207254304360284078895771796150945516748243471030702609144621" +"5722898802581825451803257070188608721131280795122334262883686223215037756666225039825343359745688844" +"2390026549819838548794829220689472168983109969836584681402285424333066033985088644580400103493397042" +"7567186443383770486037861622771738545623065874679014086723327636718751234567890123456789012345678901" +"e-308", + 2.2250738585072014e-308); + + { + static const unsigned count = 100; // Tested with 1000000 locally + Random r; + Reader reader; // Reusing reader to prevent heap allocation + + // Exhaustively test different exponents with random significant + for (uint64_t exp = 0; exp < 2047; exp++) { + ; + for (unsigned i = 0; i < count; i++) { + // Need to call r() in two statements for cross-platform coherent sequence. + uint64_t u = (exp << 52) | uint64_t(r() & 0x000FFFFF) << 32; + u |= uint64_t(r()); + internal::Double d = internal::Double(u); + + char buffer[32]; + *internal::dtoa(d.Value(), buffer) = '\0'; + + StringStream s(buffer); + ParseDoubleHandler h; + ASSERT_EQ(kParseErrorNone, reader.Parse(s, h).Code()); + EXPECT_EQ(1u, h.step_); + internal::Double a(h.actual_); + if (fullPrecision) { + EXPECT_EQ(d.Uint64Value(), a.Uint64Value()); + if (d.Uint64Value() != a.Uint64Value()) + printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value()); + } + else { + EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0 + EXPECT_DOUBLE_EQ(d.Value(), h.actual_); + } + } + } + } + + // Issue #340 + TEST_DOUBLE(fullPrecision, "7.450580596923828e-9", 7.450580596923828e-9); + { + internal::Double d(1.0); + for (int i = 0; i < 324; i++) { + char buffer[32]; + *internal::dtoa(d.Value(), buffer) = '\0'; + + StringStream s(buffer); + ParseDoubleHandler h; + Reader reader; + ASSERT_EQ(kParseErrorNone, reader.Parse(s, h).Code()); + EXPECT_EQ(1u, h.step_); + internal::Double a(h.actual_); + if (fullPrecision) { + EXPECT_EQ(d.Uint64Value(), a.Uint64Value()); + if (d.Uint64Value() != a.Uint64Value()) + printf(" String: %s\n Actual: %.17g\nExpected: %.17g\n", buffer, h.actual_, d.Value()); + } + else { + EXPECT_EQ(d.Sign(), a.Sign()); // for 0.0 != -0.0 + EXPECT_DOUBLE_EQ(d.Value(), h.actual_); + } + + + d = d.Value() * 0.5; + } + } + + // Issue 1249 + TEST_DOUBLE(fullPrecision, "0e100", 0.0); + + // Issue 1251 + TEST_DOUBLE(fullPrecision, "128.74836467836484838364836483643636483648e-336", 0.0); + + // Issue 1256 + TEST_DOUBLE(fullPrecision, + "6223372036854775296.1701512723685473547372536854755293372036854685477" + "529752233737201701512337200972013723685473123372036872036854236854737" + "247372368372367752975258547752975254729752547372368737201701512354737" + "83723677529752585477247372368372368547354737253685475529752", + 6223372036854775808.0); + +#if 0 + // Test (length + exponent) overflow + TEST_DOUBLE(fullPrecision, "0e+2147483647", 0.0); + TEST_DOUBLE(fullPrecision, "0e-2147483648", 0.0); + TEST_DOUBLE(fullPrecision, "1e-2147483648", 0.0); + TEST_DOUBLE(fullPrecision, "0e+9223372036854775807", 0.0); + TEST_DOUBLE(fullPrecision, "0e-9223372036854775808", 0.0); +#endif + + if (fullPrecision) + { + TEST_DOUBLE(fullPrecision, "1e-325", 0.0); + TEST_DOUBLE(fullPrecision, "1e-324", 0.0); + TEST_DOUBLE(fullPrecision, "2e-324", 0.0); + TEST_DOUBLE(fullPrecision, "2.4703282292062327e-324", 0.0); + TEST_DOUBLE(fullPrecision, "2.4703282292062328e-324", 5e-324); + TEST_DOUBLE(fullPrecision, "2.48e-324",5e-324); + TEST_DOUBLE(fullPrecision, "2.5e-324", 5e-324); + + // Slightly above max-normal + TEST_DOUBLE(fullPrecision, "1.7976931348623158e+308", 1.7976931348623158e+308); + + TEST_DOUBLE(fullPrecision, + "17976931348623157081452742373170435679807056752584499659891747680315726" + "07800285387605895586327668781715404589535143824642343213268894641827684" + "67546703537516986049910576551282076245490090389328944075868508455133942" + "30458323690322294816580855933212334827479782620414472316873817718091929" + "9881250404026184124858368", + (std::numeric_limits::max)()); + + TEST_DOUBLE(fullPrecision, + "243546080556034731077856379609316893158278902575447060151047" + "212703405344938119816206067372775299130836050315842578309818" + "316450894337978612745889730079163798234256495613858256849283" + "467066859489192118352020514036083287319232435355752493038825" + "828481044358810649108367633313557305310641892225870327827273" + "41408256.000000", + 2.4354608055603473e+307); + // 9007199254740991 * 2^971 (max normal) + TEST_DOUBLE(fullPrecision, + "1.797693134862315708145274237317043567980705675258449965989174768031572607800285" + "38760589558632766878171540458953514382464234321326889464182768467546703537516986" + "04991057655128207624549009038932894407586850845513394230458323690322294816580855" + "9332123348274797826204144723168738177180919299881250404026184124858368e+308", + 1.797693134862315708e+308 // 0x1.fffffffffffffp1023 + ); +#if 0 + // TODO: + // Should work at least in full-precision mode... + TEST_DOUBLE(fullPrecision, + "0.00000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000024703282292062327208828439643411068618252" + "9901307162382212792841250337753635104375932649918180817996189" + "8982823477228588654633283551779698981993873980053909390631503" + "5659515570226392290858392449105184435931802849936536152500319" + "3704576782492193656236698636584807570015857692699037063119282" + "7955855133292783433840935197801553124659726357957462276646527" + "2827220056374006485499977096599470454020828166226237857393450" + "7363390079677619305775067401763246736009689513405355374585166" + "6113422376667860416215968046191446729184030053005753084904876" + "5391711386591646239524912623653881879636239373280423891018672" + "3484976682350898633885879256283027559956575244555072551893136" + "9083625477918694866799496832404970582102851318545139621383772" + "2826145437693412532098591327667236328125", + 0.0); +#endif + // 9007199254740991 * 2^-1074 = (2^53 - 1) * 2^-1074 + TEST_DOUBLE(fullPrecision, + "4.450147717014402272114819593418263951869639092703291296046852219449644444042153" + "89103305904781627017582829831782607924221374017287738918929105531441481564124348" + "67599762821265346585071045737627442980259622449029037796981144446145705102663115" + "10031828794952795966823603998647925096578034214163701381261333311989876551545144" + "03152612538132666529513060001849177663286607555958373922409899478075565940981010" + "21612198814605258742579179000071675999344145086087205681577915435923018910334964" + "86942061405218289243144579760516365090360651414037721744226256159024466852576737" + "24464300755133324500796506867194913776884780053099639677097589658441378944337966" + "21993967316936280457084866613206797017728916080020698679408551343728867675409720" + "757232455434770912461317493580281734466552734375e-308", + 4.450147717014402272e-308 // 0x1.fffffffffffffp-1022 + ); + // 9007199254740990 * 2^-1074 + TEST_DOUBLE(fullPrecision, + "4.450147717014401778049173752171719775300846224481918930987049605124880018456471" + "39035755177760751831052846195619008686241717547743167145836439860405887584484471" + "19639655002484083577939142623582164522087943959208000909794783876158397872163051" + "22622675229968408654350206725478309956546318828765627255022767720818849892988457" + "26333908582101604036318532842699932130356061901518261174396928478121372742040102" + "17446565569357687263889031732270082446958029584739170416643195242132750803227473" + "16608838720742955671061336566907126801014814608027120593609275183716632624844904" + "31985250929886016737037234388448352929102742708402644340627409931664203093081360" + "70794835812045179006047003875039546061891526346421705014598610179523165038319441" + "51446491086954182492263498716056346893310546875e-308", + 4.450147717014401778e-308 // 0x1.ffffffffffffep-1022 + ); + // half way between the two numbers above. + // round to nearest even. + TEST_DOUBLE(fullPrecision, + "4.450147717014402025081996672794991863585242658592605113516950912287262231249312" + "64069530541271189424317838013700808305231545782515453032382772695923684574304409" + "93619708911874715081505094180604803751173783204118519353387964161152051487413083" + "16327252012460602310586905362063117526562176521464664318142050516404363222266800" + "64743260560117135282915796422274554896821334728738317548403413978098469341510556" + "19529382191981473003234105366170879223151087335413188049110555339027884856781219" + "01775450062980622457102958163711745945687733011032421168917765671370549738710820" + "78224775842509670618916870627821633352993761380751142008862499795052791018709663" + "46394401564490729731565935244123171539810221213221201847003580761626016356864581" + "1358486831521563686919762403704226016998291015625e-308", + 4.450147717014401778e-308 // 0x1.ffffffffffffep-1022 + ); + TEST_DOUBLE(fullPrecision, + "4.450147717014402025081996672794991863585242658592605113516950912287262231249312" + "64069530541271189424317838013700808305231545782515453032382772695923684574304409" + "93619708911874715081505094180604803751173783204118519353387964161152051487413083" + "16327252012460602310586905362063117526562176521464664318142050516404363222266800" + "64743260560117135282915796422274554896821334728738317548403413978098469341510556" + "19529382191981473003234105366170879223151087335413188049110555339027884856781219" + "01775450062980622457102958163711745945687733011032421168917765671370549738710820" + "78224775842509670618916870627821633352993761380751142008862499795052791018709663" + "46394401564490729731565935244123171539810221213221201847003580761626016356864581" + "13584868315215636869197624037042260169982910156250000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000e-308", + 4.450147717014401778e-308 // 0x1.ffffffffffffep-1022 + ); +#if 0 + // ... round up + // TODO: + // Should work at least in full-precision mode... + TEST_DOUBLE(fullPrecision, + "4.450147717014402025081996672794991863585242658592605113516950912287262231249312" + "64069530541271189424317838013700808305231545782515453032382772695923684574304409" + "93619708911874715081505094180604803751173783204118519353387964161152051487413083" + "16327252012460602310586905362063117526562176521464664318142050516404363222266800" + "64743260560117135282915796422274554896821334728738317548403413978098469341510556" + "19529382191981473003234105366170879223151087335413188049110555339027884856781219" + "01775450062980622457102958163711745945687733011032421168917765671370549738710820" + "78224775842509670618916870627821633352993761380751142008862499795052791018709663" + "46394401564490729731565935244123171539810221213221201847003580761626016356864581" + "13584868315215636869197624037042260169982910156250000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000001e-308", + 4.450147717014402272e-308 // 0x1.fffffffffffffp-1022 + ); +#endif + // ... round down + TEST_DOUBLE(fullPrecision, + "4.450147717014402025081996672794991863585242658592605113516950912287262231249312" + "64069530541271189424317838013700808305231545782515453032382772695923684574304409" + "93619708911874715081505094180604803751173783204118519353387964161152051487413083" + "16327252012460602310586905362063117526562176521464664318142050516404363222266800" + "64743260560117135282915796422274554896821334728738317548403413978098469341510556" + "19529382191981473003234105366170879223151087335413188049110555339027884856781219" + "01775450062980622457102958163711745945687733011032421168917765671370549738710820" + "78224775842509670618916870627821633352993761380751142008862499795052791018709663" + "46394401564490729731565935244123171539810221213221201847003580761626016356864581" + "13584868315215636869197624037042260169982910156249999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999e-308", + 4.450147717014401778e-308 // 0x1.ffffffffffffep-1022 + ); + // Slightly below half way between max-normal and infinity. + // Should round down. + TEST_DOUBLE(fullPrecision, + "1.797693134862315807937289714053034150799341327100378269361737789804449682927647" + "50946649017977587207096330286416692887910946555547851940402630657488671505820681" + "90890200070838367627385484581771153176447573027006985557136695962284291481986083" + "49364752927190741684443655107043427115596995080930428801779041744977919999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999" + "99999999999999999999999999999999999999999999999999999999999999999999999999999999e+308", + 1.797693134862315708e+308 // 0x1.fffffffffffffp1023 + ); + } + +#undef TEST_DOUBLE +} + +TEST(Reader, ParseNumber_NormalPrecisionDouble) { + TestParseDouble(); +} + +TEST(Reader, ParseNumber_FullPrecisionDouble) { + TestParseDouble(); +} + +TEST(Reader, ParseNumber_NormalPrecisionError) { + static unsigned count = 1000000; + Random r; + + double ulpSum = 0.0; + double ulpMax = 0.0; + for (unsigned i = 0; i < count; i++) { + internal::Double e, a; + do { + // Need to call r() in two statements for cross-platform coherent sequence. + uint64_t u = uint64_t(r()) << 32; + u |= uint64_t(r()); + e = u; + } while (e.IsNan() || e.IsInf() || !e.IsNormal()); + + char buffer[32]; + *internal::dtoa(e.Value(), buffer) = '\0'; + + StringStream s(buffer); + ParseDoubleHandler h; + Reader reader; + ASSERT_EQ(kParseErrorNone, reader.Parse(s, h).Code()); + EXPECT_EQ(1u, h.step_); + + a = h.actual_; + uint64_t bias1 = e.ToBias(); + uint64_t bias2 = a.ToBias(); + double ulp = static_cast(bias1 >= bias2 ? bias1 - bias2 : bias2 - bias1); + ulpMax = (std::max)(ulpMax, ulp); + ulpSum += ulp; + } + printf("ULP Average = %g, Max = %g \n", ulpSum / count, ulpMax); +} + +template +static void TestParseNumberError() { +#define TEST_NUMBER_ERROR(errorCode, str, errorOffset, streamPos) \ + { \ + char buffer[2048]; \ + ASSERT_LT(std::strlen(str), 2048u); \ + sprintf(buffer, "%s", str); \ + InsituStringStream s(buffer); \ + BaseReaderHandler<> h; \ + Reader reader; \ + EXPECT_FALSE(reader.Parse(s, h)); \ + EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ + EXPECT_EQ(errorOffset, reader.GetErrorOffset());\ + EXPECT_EQ(streamPos, s.Tell());\ + } + + // Number too big to be stored in double. + { + char n1e309[311]; // '1' followed by 309 '0' + n1e309[0] = '1'; + for (int i = 1; i < 310; i++) + n1e309[i] = '0'; + n1e309[310] = '\0'; + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, n1e309, 0u, 310u); + } + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e309", 0u, 5u); + + // Miss fraction part in number. + TEST_NUMBER_ERROR(kParseErrorNumberMissFraction, "1.", 2u, 2u); + TEST_NUMBER_ERROR(kParseErrorNumberMissFraction, "1.a", 2u, 2u); + + // Miss exponent in number. + TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e", 2u, 2u); + TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e_", 2u, 2u); + + // Issue 849 + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1.8e308", 0u, 7u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "5e308", 0u, 5u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e309", 0u, 5u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1.0e310", 0u, 7u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1.00e310", 0u, 8u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "-1.8e308", 0u, 8u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "-1e309", 0u, 6u); + + // Issue 1253 + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "2e308", 0u, 5u); + + // Issue 1259 + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, + "88474320368547737236837236775298547354737253685475547552933720368546854775297525" + "29337203685468547770151233720097201372368547312337203687203685423685123372036872" + "03685473724737236837236775297525854775297525472975254737236873720170151235473783" + "7236737247372368772473723683723456789012E66", 0u, 283u); + +#if 0 + // Test (length + exponent) overflow + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+2147483647", 0u, 13u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+9223372036854775807", 0u, 22u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+10000", 0u, 8u); + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+50000", 0u, 8u); +#endif + + // 9007199254740992 * 2^971 ("infinity") + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, + "1.797693134862315907729305190789024733617976978942306572734300811577326758055009" + "63132708477322407536021120113879871393357658789768814416622492847430639474124377" + "76789342486548527630221960124609411945308295208500576883815068234246288147391311" + "0540827237163350510684586298239947245938479716304835356329624224137216e+308", 0u, 315u); + + // TODO: + // These tests (currently) fail in normal-precision mode + if (fullPrecision) + { + // Half way between max-normal and infinity + // Should round to infinity in nearest-even mode. + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, + "1.797693134862315807937289714053034150799341327100378269361737789804449682927647" + "50946649017977587207096330286416692887910946555547851940402630657488671505820681" + "90890200070838367627385484581771153176447573027006985557136695962284291481986083" + "49364752927190741684443655107043427115596995080930428801779041744977920000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000e+308", 0u, 1125u); + // ...round up + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, + "1.797693134862315807937289714053034150799341327100378269361737789804449682927647" + "50946649017977587207096330286416692887910946555547851940402630657488671505820681" + "90890200070838367627385484581771153176447573027006985557136695962284291481986083" + "49364752927190741684443655107043427115596995080930428801779041744977920000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000001e+308", 0u, 1205u); + } + + TEST_NUMBER_ERROR(kParseErrorNumberTooBig, + "10000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000001", 0u, 310u); + +#undef TEST_NUMBER_ERROR +} + +TEST(Reader, ParseNumberError_NormalPrecisionDouble) { + TestParseNumberError(); +} + +TEST(Reader, ParseNumberError_FullPrecisionDouble) { + TestParseNumberError(); +} + +template +struct ParseStringHandler : BaseReaderHandler > { + ParseStringHandler() : str_(0), length_(0), copy_() {} + ~ParseStringHandler() { EXPECT_TRUE(str_ != 0); if (copy_) free(const_cast(str_)); } + + ParseStringHandler(const ParseStringHandler&); + ParseStringHandler& operator=(const ParseStringHandler&); + + bool Default() { ADD_FAILURE(); return false; } + bool String(const typename Encoding::Ch* str, size_t length, bool copy) { + EXPECT_EQ(0, str_); + if (copy) { + str_ = static_cast(malloc((length + 1) * sizeof(typename Encoding::Ch))); + memcpy(const_cast(str_), str, (length + 1) * sizeof(typename Encoding::Ch)); + } + else + str_ = str; + length_ = length; + copy_ = copy; + return true; + } + + const typename Encoding::Ch* str_; + size_t length_; + bool copy_; +}; + +TEST(Reader, ParseString) { +#define TEST_STRING(Encoding, e, x) \ + { \ + Encoding::Ch* buffer = StrDup(x); \ + GenericInsituStringStream is(buffer); \ + ParseStringHandler h; \ + GenericReader reader; \ + reader.Parse(is, h); \ + EXPECT_EQ(0, StrCmp(e, h.str_)); \ + EXPECT_EQ(StrLen(e), h.length_); \ + free(buffer); \ + GenericStringStream s(x); \ + ParseStringHandler h2; \ + GenericReader reader2; \ + reader2.Parse(s, h2); \ + EXPECT_EQ(0, StrCmp(e, h2.str_)); \ + EXPECT_EQ(StrLen(e), h2.length_); \ + } + + // String constant L"\xXX" can only specify character code in bytes, which is not endianness-neutral. + // And old compiler does not support u"" and U"" string literal. So here specify string literal by array of Ch. + // In addition, GCC 4.8 generates -Wnarrowing warnings when character code >= 128 are assigned to signed integer types. + // Therefore, utype is added for declaring unsigned array, and then cast it to Encoding::Ch. +#define ARRAY(...) { __VA_ARGS__ } +#define TEST_STRINGARRAY(Encoding, utype, array, x) \ + { \ + static const utype ue[] = array; \ + static const Encoding::Ch* e = reinterpret_cast(&ue[0]); \ + TEST_STRING(Encoding, e, x); \ + } + +#define TEST_STRINGARRAY2(Encoding, utype, earray, xarray) \ + { \ + static const utype ue[] = earray; \ + static const utype xe[] = xarray; \ + static const Encoding::Ch* e = reinterpret_cast(&ue[0]); \ + static const Encoding::Ch* x = reinterpret_cast(&xe[0]); \ + TEST_STRING(Encoding, e, x); \ + } + + TEST_STRING(UTF8<>, "", "\"\""); + TEST_STRING(UTF8<>, "Hello", "\"Hello\""); + TEST_STRING(UTF8<>, "Hello\nWorld", "\"Hello\\nWorld\""); + TEST_STRING(UTF8<>, "\"\\/\b\f\n\r\t", "\"\\\"\\\\/\\b\\f\\n\\r\\t\""); + TEST_STRING(UTF8<>, "\x24", "\"\\u0024\""); // Dollar sign U+0024 + TEST_STRING(UTF8<>, "\xC2\xA2", "\"\\u00A2\""); // Cents sign U+00A2 + TEST_STRING(UTF8<>, "\xE2\x82\xAC", "\"\\u20AC\""); // Euro sign U+20AC + TEST_STRING(UTF8<>, "\xF0\x9D\x84\x9E", "\"\\uD834\\uDD1E\""); // G clef sign U+1D11E + + // UTF16 + TEST_STRING(UTF16<>, L"", L"\"\""); + TEST_STRING(UTF16<>, L"Hello", L"\"Hello\""); + TEST_STRING(UTF16<>, L"Hello\nWorld", L"\"Hello\\nWorld\""); + TEST_STRING(UTF16<>, L"\"\\/\b\f\n\r\t", L"\"\\\"\\\\/\\b\\f\\n\\r\\t\""); + TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0x0024, 0x0000), L"\"\\u0024\""); + TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0x00A2, 0x0000), L"\"\\u00A2\""); // Cents sign U+00A2 + TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0x20AC, 0x0000), L"\"\\u20AC\""); // Euro sign U+20AC + TEST_STRINGARRAY(UTF16<>, wchar_t, ARRAY(0xD834, 0xDD1E, 0x0000), L"\"\\uD834\\uDD1E\""); // G clef sign U+1D11E + + // UTF32 + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('\0'), ARRAY('\"', '\"', '\0')); + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('H', 'e', 'l', 'l', 'o', '\0'), ARRAY('\"', 'H', 'e', 'l', 'l', 'o', '\"', '\0')); + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('H', 'e', 'l', 'l', 'o', '\n', 'W', 'o', 'r', 'l', 'd', '\0'), ARRAY('\"', 'H', 'e', 'l', 'l', 'o', '\\', 'n', 'W', 'o', 'r', 'l', 'd', '\"', '\0')); + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY('\"', '\\', '/', '\b', '\f', '\n', '\r', '\t', '\0'), ARRAY('\"', '\\', '\"', '\\', '\\', '/', '\\', 'b', '\\', 'f', '\\', 'n', '\\', 'r', '\\', 't', '\"', '\0')); + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x00024, 0x0000), ARRAY('\"', '\\', 'u', '0', '0', '2', '4', '\"', '\0')); + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x000A2, 0x0000), ARRAY('\"', '\\', 'u', '0', '0', 'A', '2', '\"', '\0')); // Cents sign U+00A2 + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x020AC, 0x0000), ARRAY('\"', '\\', 'u', '2', '0', 'A', 'C', '\"', '\0')); // Euro sign U+20AC + TEST_STRINGARRAY2(UTF32<>, unsigned, ARRAY(0x1D11E, 0x0000), ARRAY('\"', '\\', 'u', 'D', '8', '3', '4', '\\', 'u', 'D', 'D', '1', 'E', '\"', '\0')); // G clef sign U+1D11E + +#undef TEST_STRINGARRAY +#undef ARRAY +#undef TEST_STRING + + // Support of null character in string + { + StringStream s("\"Hello\\u0000World\""); + const char e[] = "Hello\0World"; + ParseStringHandler > h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(0, memcmp(e, h.str_, h.length_ + 1)); + EXPECT_EQ(11u, h.length_); + } +} + +TEST(Reader, ParseString_Transcoding) { + const char* x = "\"Hello\""; + const wchar_t* e = L"Hello"; + GenericStringStream > is(x); + GenericReader, UTF16<> > reader; + ParseStringHandler > h; + reader.Parse(is, h); + EXPECT_EQ(0, StrCmp::Ch>(e, h.str_)); + EXPECT_EQ(StrLen(e), h.length_); +} + +TEST(Reader, ParseString_TranscodingWithValidation) { + const char* x = "\"Hello\""; + const wchar_t* e = L"Hello"; + GenericStringStream > is(x); + GenericReader, UTF16<> > reader; + ParseStringHandler > h; + reader.Parse(is, h); + EXPECT_EQ(0, StrCmp::Ch>(e, h.str_)); + EXPECT_EQ(StrLen(e), h.length_); +} + +TEST(Reader, ParseString_NonDestructive) { + StringStream s("\"Hello\\nWorld\""); + ParseStringHandler > h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(0, StrCmp("Hello\nWorld", h.str_)); + EXPECT_EQ(11u, h.length_); +} + +template +ParseErrorCode TestString(const typename Encoding::Ch* str) { + GenericStringStream s(str); + BaseReaderHandler h; + GenericReader reader; + reader.template Parse(s, h); + return reader.GetParseErrorCode(); +} + +TEST(Reader, ParseString_Error) { +#define TEST_STRING_ERROR(errorCode, str, errorOffset, streamPos)\ +{\ + GenericStringStream > s(str);\ + BaseReaderHandler > h;\ + GenericReader , UTF8<> > reader;\ + reader.Parse(s, h);\ + EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ + EXPECT_EQ(errorOffset, reader.GetErrorOffset());\ + EXPECT_EQ(streamPos, s.Tell());\ +} + +#define ARRAY(...) { __VA_ARGS__ } +#define TEST_STRINGENCODING_ERROR(Encoding, TargetEncoding, utype, array) \ + { \ + static const utype ue[] = array; \ + static const Encoding::Ch* e = reinterpret_cast(&ue[0]); \ + EXPECT_EQ(kParseErrorStringInvalidEncoding, TestString(e));\ + /* decode error */\ + GenericStringStream s(e);\ + BaseReaderHandler h;\ + GenericReader reader;\ + reader.Parse(s, h);\ + EXPECT_EQ(kParseErrorStringInvalidEncoding, reader.GetParseErrorCode());\ + } + + // Invalid escape character in string. + TEST_STRING_ERROR(kParseErrorStringEscapeInvalid, "[\"\\a\"]", 2u, 3u); + + // Incorrect hex digit after \\u escape in string. + TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uABCG\"]", 2u, 7u); + + // Quotation in \\u escape in string (Issue #288) + TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uaaa\"]", 2u, 7u); + TEST_STRING_ERROR(kParseErrorStringUnicodeEscapeInvalidHex, "[\"\\uD800\\uFFF\"]", 2u, 13u); + + // The surrogate pair in string is invalid. + TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800X\"]", 2u, 8u); + TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\uD800\\uFFFF\"]", 2u, 14u); + + // Single low surrogate pair in string is invalid. + TEST_STRING_ERROR(kParseErrorStringUnicodeSurrogateInvalid, "[\"\\udc4d\"]", 2u, 8u); + + // Missing a closing quotation mark in string. + TEST_STRING_ERROR(kParseErrorStringMissQuotationMark, "[\"Test]", 7u, 7u); + + // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt + + // 3 Malformed sequences + + // 3.1 Unexpected continuation bytes + { + char e[] = { '[', '\"', 0, '\"', ']', '\0' }; + for (unsigned char c = 0x80u; c <= 0xBFu; c++) { + e[2] = static_cast(c); + ParseErrorCode error = TestString >(e); + EXPECT_EQ(kParseErrorStringInvalidEncoding, error); + if (error != kParseErrorStringInvalidEncoding) + std::cout << static_cast(c) << std::endl; + } + } + + // 3.2 Lonely start characters, 3.5 Impossible bytes + { + char e[] = { '[', '\"', 0, ' ', '\"', ']', '\0' }; + for (unsigned c = 0xC0u; c <= 0xFFu; c++) { + e[2] = static_cast(c); + unsigned streamPos; + if (c <= 0xC1u) + streamPos = 3; // 0xC0 - 0xC1 + else if (c <= 0xDFu) + streamPos = 4; // 0xC2 - 0xDF + else if (c <= 0xEFu) + streamPos = 5; // 0xE0 - 0xEF + else if (c <= 0xF4u) + streamPos = 6; // 0xF0 - 0xF4 + else + streamPos = 3; // 0xF5 - 0xFF + TEST_STRING_ERROR(kParseErrorStringInvalidEncoding, e, 2u, streamPos); + } + } + + // 4 Overlong sequences + + // 4.1 Examples of an overlong ASCII character + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0xAFu, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0xAFu, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0xAFu, '\"', ']', '\0')); + + // 4.2 Maximum overlong sequences + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC1u, 0xBFu, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x9Fu, 0xBFu, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x8Fu, 0xBFu, 0xBFu, '\"', ']', '\0')); + + // 4.3 Overlong representation of the NUL character + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xC0u, 0x80u, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xE0u, 0x80u, 0x80u, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xF0u, 0x80u, 0x80u, 0x80u, '\"', ']', '\0')); + + // 5 Illegal code positions + + // 5.1 Single UTF-16 surrogates + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xA0u, 0x80u, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xADu, 0xBFu, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAEu, 0x80u, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xAFu, 0xBFu, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xB0u, 0x80u, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xBEu, 0x80u, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF8<>, UTF16<>, unsigned char, ARRAY('[', '\"', 0xEDu, 0xBFu, 0xBFu, '\"', ']', '\0')); + + // Malform UTF-16 sequences + TEST_STRINGENCODING_ERROR(UTF16<>, UTF8<>, wchar_t, ARRAY('[', '\"', 0xDC00, 0xDC00, '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(UTF16<>, UTF8<>, wchar_t, ARRAY('[', '\"', 0xD800, 0xD800, '\"', ']', '\0')); + + // Malform UTF-32 sequence + TEST_STRINGENCODING_ERROR(UTF32<>, UTF8<>, unsigned, ARRAY('[', '\"', 0x110000, '\"', ']', '\0')); + + // Malform ASCII sequence + TEST_STRINGENCODING_ERROR(ASCII<>, UTF8<>, char, ARRAY('[', '\"', char(0x80u), '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(ASCII<>, UTF8<>, char, ARRAY('[', '\"', char(0x01u), '\"', ']', '\0')); + TEST_STRINGENCODING_ERROR(ASCII<>, UTF8<>, char, ARRAY('[', '\"', char(0x1Cu), '\"', ']', '\0')); + +#undef ARRAY +#undef TEST_STRINGARRAY_ERROR +} + +template +struct ParseArrayHandler : BaseReaderHandler, ParseArrayHandler > { + ParseArrayHandler() : step_(0) {} + + bool Default() { ADD_FAILURE(); return false; } + bool Uint(unsigned i) { EXPECT_EQ(step_, i); step_++; return true; } + bool StartArray() { EXPECT_EQ(0u, step_); step_++; return true; } + bool EndArray(SizeType) { step_++; return true; } + + unsigned step_; +}; + +TEST(Reader, ParseEmptyArray) { + char *json = StrDup("[ ] "); + InsituStringStream s(json); + ParseArrayHandler<0> h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(2u, h.step_); + free(json); +} + +TEST(Reader, ParseArray) { + char *json = StrDup("[1, 2, 3, 4]"); + InsituStringStream s(json); + ParseArrayHandler<4> h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(6u, h.step_); + free(json); +} + +TEST(Reader, ParseArray_Error) { +#define TEST_ARRAY_ERROR(errorCode, str, errorOffset) \ + { \ + unsigned streamPos = errorOffset; \ + char buffer[1001]; \ + strncpy(buffer, str, 1000); \ + InsituStringStream s(buffer); \ + BaseReaderHandler<> h; \ + GenericReader, UTF8<>, CrtAllocator> reader; \ + EXPECT_FALSE(reader.Parse(s, h)); \ + EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ + EXPECT_EQ(errorOffset, reader.GetErrorOffset());\ + EXPECT_EQ(streamPos, s.Tell());\ + } + + // Missing a comma or ']' after an array element. + TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1", 2u); + TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1}", 2u); + TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1 2]", 3u); + + // Array cannot have a trailing comma (without kParseTrailingCommasFlag); + // a value must follow a comma + TEST_ARRAY_ERROR(kParseErrorValueInvalid, "[1,]", 3u); + +#undef TEST_ARRAY_ERROR +} + +struct ParseObjectHandler : BaseReaderHandler, ParseObjectHandler> { + ParseObjectHandler() : step_(0) {} + + bool Default() { ADD_FAILURE(); return false; } + bool Null() { EXPECT_EQ(8u, step_); step_++; return true; } + bool Bool(bool b) { + switch(step_) { + case 4: EXPECT_TRUE(b); step_++; return true; + case 6: EXPECT_FALSE(b); step_++; return true; + default: ADD_FAILURE(); return false; + } + } + bool Int(int i) { + switch(step_) { + case 10: EXPECT_EQ(123, i); step_++; return true; + case 15: EXPECT_EQ(1, i); step_++; return true; + case 16: EXPECT_EQ(2, i); step_++; return true; + case 17: EXPECT_EQ(3, i); step_++; return true; + default: ADD_FAILURE(); return false; + } + } + bool Uint(unsigned i) { return Int(static_cast(i)); } + bool Double(double d) { EXPECT_EQ(12u, step_); EXPECT_DOUBLE_EQ(3.1416, d); step_++; return true; } + bool String(const char* str, size_t, bool) { + switch(step_) { + case 1: EXPECT_STREQ("hello", str); step_++; return true; + case 2: EXPECT_STREQ("world", str); step_++; return true; + case 3: EXPECT_STREQ("t", str); step_++; return true; + case 5: EXPECT_STREQ("f", str); step_++; return true; + case 7: EXPECT_STREQ("n", str); step_++; return true; + case 9: EXPECT_STREQ("i", str); step_++; return true; + case 11: EXPECT_STREQ("pi", str); step_++; return true; + case 13: EXPECT_STREQ("a", str); step_++; return true; + default: ADD_FAILURE(); return false; + } + } + bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; } + bool EndObject(SizeType memberCount) { EXPECT_EQ(19u, step_); EXPECT_EQ(7u, memberCount); step_++; return true; } + bool StartArray() { EXPECT_EQ(14u, step_); step_++; return true; } + bool EndArray(SizeType elementCount) { EXPECT_EQ(18u, step_); EXPECT_EQ(3u, elementCount); step_++; return true; } + + unsigned step_; +}; + +TEST(Reader, ParseObject) { + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } "; + + // Insitu + { + char* json2 = StrDup(json); + InsituStringStream s(json2); + ParseObjectHandler h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(20u, h.step_); + free(json2); + } + + // Normal + { + StringStream s(json); + ParseObjectHandler h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(20u, h.step_); + } +} + +struct ParseEmptyObjectHandler : BaseReaderHandler, ParseEmptyObjectHandler> { + ParseEmptyObjectHandler() : step_(0) {} + + bool Default() { ADD_FAILURE(); return false; } + bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; } + bool EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; return true; } + + unsigned step_; +}; + +TEST(Reader, Parse_EmptyObject) { + StringStream s("{ } "); + ParseEmptyObjectHandler h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(2u, h.step_); +} + +struct ParseMultipleRootHandler : BaseReaderHandler, ParseMultipleRootHandler> { + ParseMultipleRootHandler() : step_(0) {} + + bool Default() { ADD_FAILURE(); return false; } + bool StartObject() { EXPECT_EQ(0u, step_); step_++; return true; } + bool EndObject(SizeType) { EXPECT_EQ(1u, step_); step_++; return true; } + bool StartArray() { EXPECT_EQ(2u, step_); step_++; return true; } + bool EndArray(SizeType) { EXPECT_EQ(3u, step_); step_++; return true; } + + unsigned step_; +}; + +template +void TestMultipleRoot() { + StringStream s("{}[] a"); + ParseMultipleRootHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(2u, h.step_); + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(4u, h.step_); + EXPECT_EQ(' ', s.Take()); + EXPECT_EQ('a', s.Take()); +} + +TEST(Reader, Parse_MultipleRoot) { + TestMultipleRoot(); +} + +TEST(Reader, ParseIterative_MultipleRoot) { + TestMultipleRoot(); +} + +template +void TestInsituMultipleRoot() { + char* buffer = strdup("{}[] a"); + InsituStringStream s(buffer); + ParseMultipleRootHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(2u, h.step_); + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(4u, h.step_); + EXPECT_EQ(' ', s.Take()); + EXPECT_EQ('a', s.Take()); + free(buffer); +} + +TEST(Reader, ParseInsitu_MultipleRoot) { + TestInsituMultipleRoot(); +} + +TEST(Reader, ParseInsituIterative_MultipleRoot) { + TestInsituMultipleRoot(); +} + +#define TEST_ERROR(errorCode, str, errorOffset) \ + { \ + unsigned streamPos = errorOffset; \ + char buffer[1001]; \ + strncpy(buffer, str, 1000); \ + InsituStringStream s(buffer); \ + BaseReaderHandler<> h; \ + Reader reader; \ + EXPECT_FALSE(reader.Parse(s, h)); \ + EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ + EXPECT_EQ(errorOffset, reader.GetErrorOffset());\ + EXPECT_EQ(streamPos, s.Tell());\ + } + +TEST(Reader, ParseDocument_Error) { + // The document is empty. + TEST_ERROR(kParseErrorDocumentEmpty, "", 0u); + TEST_ERROR(kParseErrorDocumentEmpty, " ", 1u); + TEST_ERROR(kParseErrorDocumentEmpty, " \n", 2u); + + // The document root must not follow by other values. + TEST_ERROR(kParseErrorDocumentRootNotSingular, "[] 0", 3u); + TEST_ERROR(kParseErrorDocumentRootNotSingular, "{} 0", 3u); + TEST_ERROR(kParseErrorDocumentRootNotSingular, "null []", 5u); + TEST_ERROR(kParseErrorDocumentRootNotSingular, "0 {}", 2u); +} + +TEST(Reader, ParseValue_Error) { + // Invalid value. + TEST_ERROR(kParseErrorValueInvalid, "nulL", 3u); + TEST_ERROR(kParseErrorValueInvalid, "truE", 3u); + TEST_ERROR(kParseErrorValueInvalid, "falsE", 4u); + TEST_ERROR(kParseErrorValueInvalid, "a]", 0u); + TEST_ERROR(kParseErrorValueInvalid, ".1", 0u); +} + +TEST(Reader, ParseObject_Error) { + // Missing a name for object member. + TEST_ERROR(kParseErrorObjectMissName, "{1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{:1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{null:1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{true:1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{false:1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{1:1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{[]:1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{{}:1}", 1u); + TEST_ERROR(kParseErrorObjectMissName, "{xyz:1}", 1u); + + // Missing a colon after a name of object member. + TEST_ERROR(kParseErrorObjectMissColon, "{\"a\" 1}", 5u); + TEST_ERROR(kParseErrorObjectMissColon, "{\"a\",1}", 4u); + + // Must be a comma or '}' after an object member + TEST_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, "{\"a\":1]", 6u); + + // Object cannot have a trailing comma (without kParseTrailingCommasFlag); + // an object member name must follow a comma + TEST_ERROR(kParseErrorObjectMissName, "{\"a\":1,}", 7u); + + // This tests that MemoryStream is checking the length in Peek(). + { + MemoryStream ms("{\"a\"", 1); + BaseReaderHandler<> h; + Reader reader; + EXPECT_FALSE(reader.Parse(ms, h)); + EXPECT_EQ(kParseErrorObjectMissName, reader.GetParseErrorCode()); + } +} + +#undef TEST_ERROR + +TEST(Reader, SkipWhitespace) { + StringStream ss(" A \t\tB\n \n\nC\r\r \rD \t\n\r E"); + const char* expected = "ABCDE"; + for (size_t i = 0; i < 5; i++) { + SkipWhitespace(ss); + EXPECT_EQ(expected[i], ss.Take()); + } +} + +// Test implementing a stream without copy stream optimization. +// Clone from GenericStringStream except that copy constructor is disabled. +template +class CustomStringStream { +public: + typedef typename Encoding::Ch Ch; + + CustomStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + // Prohibit copy constructor & assignment operator. + CustomStringStream(const CustomStringStream&); + CustomStringStream& operator=(const CustomStringStream&); + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +// If the following code is compiled, it should generate compilation error as predicted. +// Because CustomStringStream<> is not copyable via making copy constructor private. +#if 0 +namespace rapidjson { + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +} // namespace rapidjson +#endif + +TEST(Reader, CustomStringStream) { + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } "; + CustomStringStream > s(json); + ParseObjectHandler h; + Reader reader; + reader.Parse(s, h); + EXPECT_EQ(20u, h.step_); +} + +#include + +class IStreamWrapper { +public: + typedef char Ch; + + IStreamWrapper(std::istream& is) : is_(is) {} + + Ch Peek() const { + int c = is_.peek(); + return c == std::char_traits::eof() ? '\0' : static_cast(c); + } + + Ch Take() { + int c = is_.get(); + return c == std::char_traits::eof() ? '\0' : static_cast(c); + } + + size_t Tell() const { return static_cast(is_.tellg()); } + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch) { assert(false); } + void Flush() { assert(false); } + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + IStreamWrapper(const IStreamWrapper&); + IStreamWrapper& operator=(const IStreamWrapper&); + + std::istream& is_; +}; + +class WIStreamWrapper { +public: + typedef wchar_t Ch; + + WIStreamWrapper(std::wistream& is) : is_(is) {} + + Ch Peek() const { + unsigned c = is_.peek(); + return c == std::char_traits::eof() ? Ch('\0') : static_cast(c); + } + + Ch Take() { + unsigned c = is_.get(); + return c == std::char_traits::eof() ? Ch('\0') : static_cast(c); + } + + size_t Tell() const { return static_cast(is_.tellg()); } + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch) { assert(false); } + void Flush() { assert(false); } + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + WIStreamWrapper(const WIStreamWrapper&); + WIStreamWrapper& operator=(const WIStreamWrapper&); + + std::wistream& is_; +}; + +TEST(Reader, Parse_IStreamWrapper_StringStream) { + const char* json = "[1,2,3,4]"; + + std::stringstream ss(json); + IStreamWrapper is(ss); + + Reader reader; + ParseArrayHandler<4> h; + reader.Parse(is, h); + EXPECT_FALSE(reader.HasParseError()); +} + +// Test iterative parsing. + +#define TESTERRORHANDLING(text, errorCode, offset)\ +{\ + unsigned streamPos = offset; \ + StringStream json(text); \ + BaseReaderHandler<> handler; \ + Reader reader; \ + reader.Parse(json, handler); \ + EXPECT_TRUE(reader.HasParseError()); \ + EXPECT_EQ(errorCode, reader.GetParseErrorCode()); \ + EXPECT_EQ(offset, reader.GetErrorOffset()); \ + EXPECT_EQ(streamPos, json.Tell()); \ +} + +TEST(Reader, IterativeParsing_ErrorHandling) { + TESTERRORHANDLING("{\"a\": a}", kParseErrorValueInvalid, 6u); + + TESTERRORHANDLING("", kParseErrorDocumentEmpty, 0u); + TESTERRORHANDLING("{}{}", kParseErrorDocumentRootNotSingular, 2u); + + TESTERRORHANDLING("{1}", kParseErrorObjectMissName, 1u); + TESTERRORHANDLING("{\"a\", 1}", kParseErrorObjectMissColon, 4u); + TESTERRORHANDLING("{\"a\"}", kParseErrorObjectMissColon, 4u); + TESTERRORHANDLING("{\"a\": 1", kParseErrorObjectMissCommaOrCurlyBracket, 7u); + TESTERRORHANDLING("[1 2 3]", kParseErrorArrayMissCommaOrSquareBracket, 3u); + TESTERRORHANDLING("{\"a: 1", kParseErrorStringMissQuotationMark, 6u); + TESTERRORHANDLING("{\"a\":}", kParseErrorValueInvalid, 5u); + TESTERRORHANDLING("{\"a\":]", kParseErrorValueInvalid, 5u); + TESTERRORHANDLING("[1,2,}", kParseErrorValueInvalid, 5u); + TESTERRORHANDLING("[}]", kParseErrorValueInvalid, 1u); + TESTERRORHANDLING("[,]", kParseErrorValueInvalid, 1u); + TESTERRORHANDLING("[1,,]", kParseErrorValueInvalid, 3u); + + // Trailing commas are not allowed without kParseTrailingCommasFlag + TESTERRORHANDLING("{\"a\": 1,}", kParseErrorObjectMissName, 8u); + TESTERRORHANDLING("[1,2,3,]", kParseErrorValueInvalid, 7u); + + // Any JSON value can be a valid root element in RFC7159. + TESTERRORHANDLING("\"ab", kParseErrorStringMissQuotationMark, 3u); + TESTERRORHANDLING("truE", kParseErrorValueInvalid, 3u); + TESTERRORHANDLING("False", kParseErrorValueInvalid, 0u); + TESTERRORHANDLING("true, false", kParseErrorDocumentRootNotSingular, 4u); + TESTERRORHANDLING("false, false", kParseErrorDocumentRootNotSingular, 5u); + TESTERRORHANDLING("nulL", kParseErrorValueInvalid, 3u); + TESTERRORHANDLING("null , null", kParseErrorDocumentRootNotSingular, 5u); + TESTERRORHANDLING("1a", kParseErrorDocumentRootNotSingular, 1u); +} + +template > +struct IterativeParsingReaderHandler { + typedef typename Encoding::Ch Ch; + + const static uint32_t LOG_NULL = 0x10000000; + const static uint32_t LOG_BOOL = 0x20000000; + const static uint32_t LOG_INT = 0x30000000; + const static uint32_t LOG_UINT = 0x40000000; + const static uint32_t LOG_INT64 = 0x50000000; + const static uint32_t LOG_UINT64 = 0x60000000; + const static uint32_t LOG_DOUBLE = 0x70000000; + const static uint32_t LOG_STRING = 0x80000000; + const static uint32_t LOG_STARTOBJECT = 0x90000000; + const static uint32_t LOG_KEY = 0xA0000000; + const static uint32_t LOG_ENDOBJECT = 0xB0000000; + const static uint32_t LOG_STARTARRAY = 0xC0000000; + const static uint32_t LOG_ENDARRAY = 0xD0000000; + + const static size_t LogCapacity = 256; + uint32_t Logs[LogCapacity]; + size_t LogCount; + + IterativeParsingReaderHandler() : LogCount(0) { + } + + bool Null() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_NULL; return true; } + + bool Bool(bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_BOOL; return true; } + + bool Int(int) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_INT; return true; } + + bool Uint(unsigned) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_INT; return true; } + + bool Int64(int64_t) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_INT64; return true; } + + bool Uint64(uint64_t) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_UINT64; return true; } + + bool Double(double) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_DOUBLE; return true; } + + bool RawNumber(const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STRING; return true; } + + bool String(const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STRING; return true; } + + bool StartObject() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTOBJECT; return true; } + + bool Key (const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_KEY; return true; } + + bool EndObject(SizeType c) { + RAPIDJSON_ASSERT(LogCount < LogCapacity); + RAPIDJSON_ASSERT((static_cast(c) & 0xF0000000) == 0); + Logs[LogCount++] = LOG_ENDOBJECT | static_cast(c); + return true; + } + + bool StartArray() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTARRAY; return true; } + + bool EndArray(SizeType c) { + RAPIDJSON_ASSERT(LogCount < LogCapacity); + RAPIDJSON_ASSERT((static_cast(c) & 0xF0000000) == 0); + Logs[LogCount++] = LOG_ENDARRAY | static_cast(c); + return true; + } +}; + +TEST(Reader, IterativeParsing_General) { + { + StringStream is("[1, {\"k\": [1, 2]}, null, false, true, \"string\", 1.2]"); + Reader reader; + IterativeParsingReaderHandler<> handler; + + ParseResult r = reader.Parse(is, handler); + + EXPECT_FALSE(r.IsError()); + EXPECT_FALSE(reader.HasParseError()); + + uint32_t e[] = { + handler.LOG_STARTARRAY, + handler.LOG_INT, + handler.LOG_STARTOBJECT, + handler.LOG_KEY, + handler.LOG_STARTARRAY, + handler.LOG_INT, + handler.LOG_INT, + handler.LOG_ENDARRAY | 2, + handler.LOG_ENDOBJECT | 1, + handler.LOG_NULL, + handler.LOG_BOOL, + handler.LOG_BOOL, + handler.LOG_STRING, + handler.LOG_DOUBLE, + handler.LOG_ENDARRAY | 7 + }; + + EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount); + + for (size_t i = 0; i < handler.LogCount; ++i) { + EXPECT_EQ(e[i], handler.Logs[i]) << "i = " << i; + } + } +} + +TEST(Reader, IterativeParsing_Count) { + { + StringStream is("[{}, {\"k\": 1}, [1], []]"); + Reader reader; + IterativeParsingReaderHandler<> handler; + + ParseResult r = reader.Parse(is, handler); + + EXPECT_FALSE(r.IsError()); + EXPECT_FALSE(reader.HasParseError()); + + uint32_t e[] = { + handler.LOG_STARTARRAY, + handler.LOG_STARTOBJECT, + handler.LOG_ENDOBJECT | 0, + handler.LOG_STARTOBJECT, + handler.LOG_KEY, + handler.LOG_INT, + handler.LOG_ENDOBJECT | 1, + handler.LOG_STARTARRAY, + handler.LOG_INT, + handler.LOG_ENDARRAY | 1, + handler.LOG_STARTARRAY, + handler.LOG_ENDARRAY | 0, + handler.LOG_ENDARRAY | 4 + }; + + EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount); + + for (size_t i = 0; i < handler.LogCount; ++i) { + EXPECT_EQ(e[i], handler.Logs[i]) << "i = " << i; + } + } +} + +TEST(Reader, IterativePullParsing_General) { + { + IterativeParsingReaderHandler<> handler; + uint32_t e[] = { + handler.LOG_STARTARRAY, + handler.LOG_INT, + handler.LOG_STARTOBJECT, + handler.LOG_KEY, + handler.LOG_STARTARRAY, + handler.LOG_INT, + handler.LOG_INT, + handler.LOG_ENDARRAY | 2, + handler.LOG_ENDOBJECT | 1, + handler.LOG_NULL, + handler.LOG_BOOL, + handler.LOG_BOOL, + handler.LOG_STRING, + handler.LOG_DOUBLE, + handler.LOG_ENDARRAY | 7 + }; + + StringStream is("[1, {\"k\": [1, 2]}, null, false, true, \"string\", 1.2]"); + Reader reader; + + reader.IterativeParseInit(); + while (!reader.IterativeParseComplete()) { + size_t oldLogCount = handler.LogCount; + EXPECT_TRUE(oldLogCount < sizeof(e) / sizeof(int)) << "overrun"; + + EXPECT_TRUE(reader.IterativeParseNext(is, handler)) << "parse fail"; + EXPECT_EQ(handler.LogCount, oldLogCount + 1) << "handler should be invoked exactly once each time"; + EXPECT_EQ(e[oldLogCount], handler.Logs[oldLogCount]) << "wrong event returned"; + } + + EXPECT_FALSE(reader.HasParseError()); + EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount) << "handler invoked wrong number of times"; + + // The handler should not be invoked when the JSON has been fully read, but it should not fail + size_t oldLogCount = handler.LogCount; + EXPECT_TRUE(reader.IterativeParseNext(is, handler)) << "parse-next past complete is allowed"; + EXPECT_EQ(handler.LogCount, oldLogCount) << "parse-next past complete should not invoke handler"; + EXPECT_FALSE(reader.HasParseError()) << "parse-next past complete should not generate parse error"; + } +} + +// Test iterative parsing on kParseErrorTermination. +struct HandlerTerminateAtStartObject : public IterativeParsingReaderHandler<> { + bool StartObject() { return false; } +}; + +struct HandlerTerminateAtStartArray : public IterativeParsingReaderHandler<> { + bool StartArray() { return false; } +}; + +struct HandlerTerminateAtEndObject : public IterativeParsingReaderHandler<> { + bool EndObject(SizeType) { return false; } +}; + +struct HandlerTerminateAtEndArray : public IterativeParsingReaderHandler<> { + bool EndArray(SizeType) { return false; } +}; + +TEST(Reader, IterativeParsing_ShortCircuit) { + { + HandlerTerminateAtStartObject handler; + Reader reader; + StringStream is("[1, {}]"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(4u, r.Offset()); + } + + { + HandlerTerminateAtStartArray handler; + Reader reader; + StringStream is("{\"a\": []}"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(6u, r.Offset()); + } + + { + HandlerTerminateAtEndObject handler; + Reader reader; + StringStream is("[1, {}]"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(5u, r.Offset()); + } + + { + HandlerTerminateAtEndArray handler; + Reader reader; + StringStream is("{\"a\": []}"); + + ParseResult r = reader.Parse(is, handler); + + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(7u, r.Offset()); + } +} + +// For covering BaseReaderHandler default functions +TEST(Reader, BaseReaderHandler_Default) { + BaseReaderHandler<> h; + Reader reader; + StringStream is("[null, true, -1, 1, -1234567890123456789, 1234567890123456789, 3.14, \"s\", { \"a\" : 1 }]"); + EXPECT_TRUE(reader.Parse(is, h)); +} + +template +struct TerminateHandler { + bool Null() { return e != 0; } + bool Bool(bool) { return e != 1; } + bool Int(int) { return e != 2; } + bool Uint(unsigned) { return e != 3; } + bool Int64(int64_t) { return e != 4; } + bool Uint64(uint64_t) { return e != 5; } + bool Double(double) { return e != 6; } + bool RawNumber(const char*, SizeType, bool) { return e != 7; } + bool String(const char*, SizeType, bool) { return e != 8; } + bool StartObject() { return e != 9; } + bool Key(const char*, SizeType, bool) { return e != 10; } + bool EndObject(SizeType) { return e != 11; } + bool StartArray() { return e != 12; } + bool EndArray(SizeType) { return e != 13; } +}; + +#define TEST_TERMINATION(e, json)\ +{\ + Reader reader;\ + TerminateHandler h;\ + StringStream is(json);\ + EXPECT_FALSE(reader.Parse(is, h));\ + EXPECT_EQ(kParseErrorTermination, reader.GetParseErrorCode());\ +} + +TEST(Reader, ParseTerminationByHandler) { + TEST_TERMINATION(0, "[null"); + TEST_TERMINATION(1, "[true"); + TEST_TERMINATION(1, "[false"); + TEST_TERMINATION(2, "[-1"); + TEST_TERMINATION(3, "[1"); + TEST_TERMINATION(4, "[-1234567890123456789"); + TEST_TERMINATION(5, "[1234567890123456789"); + TEST_TERMINATION(6, "[0.5]"); + // RawNumber() is never called + TEST_TERMINATION(8, "[\"a\""); + TEST_TERMINATION(9, "[{"); + TEST_TERMINATION(10, "[{\"a\""); + TEST_TERMINATION(11, "[{}"); + TEST_TERMINATION(11, "[{\"a\":1}"); // non-empty object + TEST_TERMINATION(12, "{\"a\":["); + TEST_TERMINATION(13, "{\"a\":[]"); + TEST_TERMINATION(13, "{\"a\":[1]"); // non-empty array +} + +TEST(Reader, ParseComments) { + const char* json = + "// Here is a one-line comment.\n" + "{// And here's another one\n" + " /*And here's an in-line one.*/\"hello\" : \"world\"," + " \"t\" :/* And one with '*' symbol*/true ," + "/* A multiline comment\n" + " goes here*/" + " \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3]" + "}/*And the last one to be sure */"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + +TEST(Reader, ParseEmptyInlineComment) { + const char* json = "{/**/\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + +TEST(Reader, ParseEmptyOnelineComment) { + const char* json = "{//\n\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + +TEST(Reader, ParseMultipleCommentsInARow) { + const char* json = + "{/* first comment *//* second */\n" + "/* third */ /*fourth*/// last one\n" + "\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); +} + +TEST(Reader, InlineCommentsAreDisabledByDefault) { + { + const char* json = "{/* Inline comment. */\"hello\" : \"world\", \"t\" : true, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + } + + { + const char* json = + "{\"hello\" : /* Multiline comment starts here\n" + " continues here\n" + " and ends here */\"world\", \"t\" :true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + } +} + +TEST(Reader, OnelineCommentsAreDisabledByDefault) { + const char* json = "{// One-line comment\n\"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); +} + +TEST(Reader, EofAfterOneLineComment) { + const char* json = "{\"hello\" : \"world\" // EOF is here -->\0 \n}"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + EXPECT_EQ(kParseErrorObjectMissCommaOrCurlyBracket, reader.GetParseErrorCode()); +} + +TEST(Reader, IncompleteMultilineComment) { + const char* json = "{\"hello\" : \"world\" /* EOF is here -->\0 */}"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode()); +} + +TEST(Reader, IncompleteMultilineComment2) { + const char* json = "{\"hello\" : \"world\" /* *\0 */}"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode()); +} + +TEST(Reader, UnrecognizedComment) { + const char* json = "{\"hello\" : \"world\" /! }"; + + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_FALSE(reader.Parse(s, h)); + EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode()); +} + +struct NumbersAsStringsHandler { + bool Null() { return true; } + bool Bool(bool) { return true; } + bool Int(int) { return true; } + bool Uint(unsigned) { return true; } + bool Int64(int64_t) { return true; } + bool Uint64(uint64_t) { return true; } + bool Double(double) { return true; } + // 'str' is not null-terminated + bool RawNumber(const char* str, SizeType length, bool) { + EXPECT_TRUE(str != 0); + EXPECT_TRUE(expected_len_ == length); + EXPECT_TRUE(strncmp(str, expected_, length) == 0); + return true; + } + bool String(const char*, SizeType, bool) { return true; } + bool StartObject() { return true; } + bool Key(const char*, SizeType, bool) { return true; } + bool EndObject(SizeType) { return true; } + bool StartArray() { return true; } + bool EndArray(SizeType) { return true; } + + NumbersAsStringsHandler(const char* expected) + : expected_(expected) + , expected_len_(strlen(expected)) {} + + const char* expected_; + size_t expected_len_; +}; + +TEST(Reader, NumbersAsStrings) { + { + const char* json = "{ \"pi\": 3.1416 } "; + StringStream s(json); + NumbersAsStringsHandler h("3.1416"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + char* json = StrDup("{ \"pi\": 3.1416 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("3.1416"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const char* json = "{ \"gigabyte\": 1.0e9 } "; + StringStream s(json); + NumbersAsStringsHandler h("1.0e9"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + char* json = StrDup("{ \"gigabyte\": 1.0e9 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("1.0e9"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const char* json = "{ \"pi\": 314.159e-2 } "; + StringStream s(json); + NumbersAsStringsHandler h("314.159e-2"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + char* json = StrDup("{ \"gigabyte\": 314.159e-2 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("314.159e-2"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const char* json = "{ \"negative\": -1.54321 } "; + StringStream s(json); + NumbersAsStringsHandler h("-1.54321"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + char* json = StrDup("{ \"negative\": -1.54321 } "); + InsituStringStream s(json); + NumbersAsStringsHandler h("-1.54321"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const char* json = "{ \"pi\": 314.159e-2 } "; + std::stringstream ss(json); + IStreamWrapper s(ss); + NumbersAsStringsHandler h("314.159e-2"); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + char n1e319[321]; // '1' followed by 319 '0' + n1e319[0] = '1'; + for (int i = 1; i < 320; i++) + n1e319[i] = '0'; + n1e319[320] = '\0'; + StringStream s(n1e319); + NumbersAsStringsHandler h(n1e319); + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +struct NumbersAsStringsHandlerWChar_t { + bool Null() { return true; } + bool Bool(bool) { return true; } + bool Int(int) { return true; } + bool Uint(unsigned) { return true; } + bool Int64(int64_t) { return true; } + bool Uint64(uint64_t) { return true; } + bool Double(double) { return true; } + // 'str' is not null-terminated + bool RawNumber(const wchar_t* str, SizeType length, bool) { + EXPECT_TRUE(str != 0); + EXPECT_TRUE(expected_len_ == length); + EXPECT_TRUE(wcsncmp(str, expected_, length) == 0); + return true; + } + bool String(const wchar_t*, SizeType, bool) { return true; } + bool StartObject() { return true; } + bool Key(const wchar_t*, SizeType, bool) { return true; } + bool EndObject(SizeType) { return true; } + bool StartArray() { return true; } + bool EndArray(SizeType) { return true; } + + NumbersAsStringsHandlerWChar_t(const wchar_t* expected) + : expected_(expected) + , expected_len_(wcslen(expected)) {} + + const wchar_t* expected_; + size_t expected_len_; +}; + +TEST(Reader, NumbersAsStringsWChar_t) { + { + const wchar_t* json = L"{ \"pi\": 3.1416 } "; + GenericStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"3.1416"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + wchar_t* json = StrDup(L"{ \"pi\": 3.1416 } "); + GenericInsituStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"3.1416"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const wchar_t* json = L"{ \"gigabyte\": 1.0e9 } "; + GenericStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"1.0e9"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + wchar_t* json = StrDup(L"{ \"gigabyte\": 1.0e9 } "); + GenericInsituStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"1.0e9"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const wchar_t* json = L"{ \"pi\": 314.159e-2 } "; + GenericStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"314.159e-2"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + wchar_t* json = StrDup(L"{ \"gigabyte\": 314.159e-2 } "); + GenericInsituStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"314.159e-2"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const wchar_t* json = L"{ \"negative\": -1.54321 } "; + GenericStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"-1.54321"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + wchar_t* json = StrDup(L"{ \"negative\": -1.54321 } "); + GenericInsituStringStream > s(json); + NumbersAsStringsHandlerWChar_t h(L"-1.54321"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + free(json); + } + { + const wchar_t* json = L"{ \"pi\": 314.159e-2 } "; + std::wstringstream ss(json); + WIStreamWrapper s(ss); + NumbersAsStringsHandlerWChar_t h(L"314.159e-2"); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + } + { + wchar_t n1e319[321]; // '1' followed by 319 '0' + n1e319[0] = L'1'; + for(int i = 1; i < 320; i++) + n1e319[i] = L'0'; + n1e319[320] = L'\0'; + GenericStringStream > s(n1e319); + NumbersAsStringsHandlerWChar_t h(n1e319); + GenericReader, UTF16<> > reader; + EXPECT_TRUE(reader.Parse(s, h)); + } +} + +template +void TestTrailingCommas() { + { + StringStream s("[1,2,3,]"); + ParseArrayHandler<3> h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(5u, h.step_); + } + { + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false," + "\"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3],}"; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); + } + { + // whitespace around trailing commas + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false," + "\"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3\n,\n]\n,\n} "; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); + } + { + // comments around trailing commas + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null," + "\"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3/*test*/,/*test*/]/*test*/,/*test*/}"; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + EXPECT_TRUE(reader.Parse(s, h)); + EXPECT_EQ(20u, h.step_); + } +} + +TEST(Reader, TrailingCommas) { + TestTrailingCommas(); +} + +TEST(Reader, TrailingCommasIterative) { + TestTrailingCommas(); +} + +template +void TestMultipleTrailingCommaErrors() { + // only a single trailing comma is allowed. + { + StringStream s("[1,2,3,,]"); + ParseArrayHandler<3> h; + Reader reader; + ParseResult r = reader.Parse(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorValueInvalid, r.Code()); + EXPECT_EQ(7u, r.Offset()); + } + { + const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false," + "\"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3,],,}"; + StringStream s(json); + ParseObjectHandler h; + Reader reader; + ParseResult r = reader.Parse(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorObjectMissName, r.Code()); + EXPECT_EQ(95u, r.Offset()); + } +} + +TEST(Reader, MultipleTrailingCommaErrors) { + TestMultipleTrailingCommaErrors(); +} + +TEST(Reader, MultipleTrailingCommaErrorsIterative) { + TestMultipleTrailingCommaErrors(); +} + +template +void TestEmptyExceptForCommaErrors() { + // not allowed even with trailing commas enabled; the + // trailing comma must follow a value. + { + StringStream s("[,]"); + ParseArrayHandler<3> h; + Reader reader; + ParseResult r = reader.Parse(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorValueInvalid, r.Code()); + EXPECT_EQ(1u, r.Offset()); + } + { + StringStream s("{,}"); + ParseObjectHandler h; + Reader reader; + ParseResult r = reader.Parse(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorObjectMissName, r.Code()); + EXPECT_EQ(1u, r.Offset()); + } +} + +TEST(Reader, EmptyExceptForCommaErrors) { + TestEmptyExceptForCommaErrors(); +} + +TEST(Reader, EmptyExceptForCommaErrorsIterative) { + TestEmptyExceptForCommaErrors(); +} + +template +void TestTrailingCommaHandlerTermination() { + { + HandlerTerminateAtEndArray h; + Reader reader; + StringStream s("[1,2,3,]"); + ParseResult r = reader.Parse(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(7u, r.Offset()); + } + { + HandlerTerminateAtEndObject h; + Reader reader; + StringStream s("{\"t\": true, \"f\": false,}"); + ParseResult r = reader.Parse(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorTermination, r.Code()); + EXPECT_EQ(23u, r.Offset()); + } +} + +TEST(Reader, TrailingCommaHandlerTermination) { + TestTrailingCommaHandlerTermination(); +} + +TEST(Reader, TrailingCommaHandlerTerminationIterative) { + TestTrailingCommaHandlerTermination(); +} + +TEST(Reader, ParseNanAndInfinity) { +#define TEST_NAN_INF(str, x) \ + { \ + { \ + StringStream s(str); \ + ParseDoubleHandler h; \ + Reader reader; \ + ASSERT_EQ(kParseErrorNone, reader.Parse(s, h).Code()); \ + EXPECT_EQ(1u, h.step_); \ + internal::Double e(x), a(h.actual_); \ + EXPECT_EQ(e.IsNan(), a.IsNan()); \ + EXPECT_EQ(e.IsInf(), a.IsInf()); \ + if (!e.IsNan()) \ + EXPECT_EQ(e.Sign(), a.Sign()); \ + } \ + { \ + const char* json = "{ \"naninfdouble\": " str " } "; \ + StringStream s(json); \ + NumbersAsStringsHandler h(str); \ + Reader reader; \ + EXPECT_TRUE(reader.Parse(s, h)); \ + } \ + { \ + char* json = StrDup("{ \"naninfdouble\": " str " } "); \ + InsituStringStream s(json); \ + NumbersAsStringsHandler h(str); \ + Reader reader; \ + EXPECT_TRUE(reader.Parse(s, h)); \ + free(json); \ + } \ + } +#define TEST_NAN_INF_ERROR(errorCode, str, errorOffset) \ + { \ + unsigned streamPos = errorOffset; \ + char buffer[1001]; \ + strncpy(buffer, str, 1000); \ + InsituStringStream s(buffer); \ + BaseReaderHandler<> h; \ + Reader reader; \ + EXPECT_FALSE(reader.Parse(s, h)); \ + EXPECT_EQ(errorCode, reader.GetParseErrorCode());\ + EXPECT_EQ(errorOffset, reader.GetErrorOffset());\ + EXPECT_EQ(streamPos, s.Tell());\ + } + + double nan = std::numeric_limits::quiet_NaN(); + double inf = std::numeric_limits::infinity(); + + TEST_NAN_INF("NaN", nan); + TEST_NAN_INF("-NaN", nan); + TEST_NAN_INF("Inf", inf); + TEST_NAN_INF("Infinity", inf); + TEST_NAN_INF("-Inf", -inf); + TEST_NAN_INF("-Infinity", -inf); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "NInf", 1u); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "NaInf", 2u); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "INan", 1u); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "InNan", 2u); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "nan", 1u); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "-nan", 1u); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "NAN", 1u); + TEST_NAN_INF_ERROR(kParseErrorValueInvalid, "-Infinty", 6u); + +#undef TEST_NAN_INF_ERROR +#undef TEST_NAN_INF +} + +TEST(Reader, EscapedApostrophe) { + const char json[] = " { \"foo\": \"bar\\'buzz\" } "; + + BaseReaderHandler<> h; + + { + StringStream s(json); + Reader reader; + ParseResult r = reader.Parse(s, h); + EXPECT_TRUE(reader.HasParseError()); + EXPECT_EQ(kParseErrorStringEscapeInvalid, r.Code()); + EXPECT_EQ(14u, r.Offset()); + } + + { + StringStream s(json); + Reader reader; + ParseResult r = reader.Parse(s, h); + EXPECT_FALSE(reader.HasParseError()); + EXPECT_EQ(kParseErrorNone, r.Code()); + EXPECT_EQ(0u, r.Offset()); + } +} + +RAPIDJSON_DIAG_POP diff --git a/deps/rapidjson/test/unittest/regextest.cpp b/deps/rapidjson/test/unittest/regextest.cpp new file mode 100644 index 0000000..a288622 --- /dev/null +++ b/deps/rapidjson/test/unittest/regextest.cpp @@ -0,0 +1,639 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/internal/regex.h" + +using namespace rapidjson::internal; + +TEST(Regex, Single) { + Regex re("a"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("b")); +} + +TEST(Regex, Concatenation) { + Regex re("abc"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abc")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("a")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("abcd")); +} + +TEST(Regex, Alternation1) { + Regex re("abab|abbb"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abab")); + EXPECT_TRUE(rs.Match("abbb")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("ababa")); + EXPECT_FALSE(rs.Match("abb")); + EXPECT_FALSE(rs.Match("abbbb")); +} + +TEST(Regex, Alternation2) { + Regex re("a|b|c"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match("c")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("aa")); + EXPECT_FALSE(rs.Match("ab")); +} + +TEST(Regex, Parenthesis1) { + Regex re("(ab)c"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abc")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("a")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("abcd")); +} + +TEST(Regex, Parenthesis2) { + Regex re("a(bc)"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abc")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("a")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("abcd")); +} + +TEST(Regex, Parenthesis3) { + Regex re("(a|b)(c|d)"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("ac")); + EXPECT_TRUE(rs.Match("ad")); + EXPECT_TRUE(rs.Match("bc")); + EXPECT_TRUE(rs.Match("bd")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("cd")); +} + +TEST(Regex, ZeroOrOne1) { + Regex re("a?"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("")); + EXPECT_TRUE(rs.Match("a")); + EXPECT_FALSE(rs.Match("aa")); +} + +TEST(Regex, ZeroOrOne2) { + Regex re("a?b"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("a")); + EXPECT_FALSE(rs.Match("aa")); + EXPECT_FALSE(rs.Match("bb")); + EXPECT_FALSE(rs.Match("ba")); +} + +TEST(Regex, ZeroOrOne3) { + Regex re("ab?"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("aa")); + EXPECT_FALSE(rs.Match("bb")); + EXPECT_FALSE(rs.Match("ba")); +} + +TEST(Regex, ZeroOrOne4) { + Regex re("a?b?"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("")); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_FALSE(rs.Match("aa")); + EXPECT_FALSE(rs.Match("bb")); + EXPECT_FALSE(rs.Match("ba")); + EXPECT_FALSE(rs.Match("abc")); +} + +TEST(Regex, ZeroOrOne5) { + Regex re("a(ab)?b"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_TRUE(rs.Match("aabb")); + EXPECT_FALSE(rs.Match("aab")); + EXPECT_FALSE(rs.Match("abb")); +} + +TEST(Regex, ZeroOrMore1) { + Regex re("a*"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("")); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("aa")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("ab")); +} + +TEST(Regex, ZeroOrMore2) { + Regex re("a*b"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_TRUE(rs.Match("aab")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("bb")); +} + +TEST(Regex, ZeroOrMore3) { + Regex re("a*b*"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("")); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("aa")); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match("bb")); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_TRUE(rs.Match("aabb")); + EXPECT_FALSE(rs.Match("ba")); +} + +TEST(Regex, ZeroOrMore4) { + Regex re("a(ab)*b"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_TRUE(rs.Match("aabb")); + EXPECT_TRUE(rs.Match("aababb")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("aa")); +} + +TEST(Regex, OneOrMore1) { + Regex re("a+"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("aa")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("ab")); +} + +TEST(Regex, OneOrMore2) { + Regex re("a+b"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_TRUE(rs.Match("aab")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("b")); +} + +TEST(Regex, OneOrMore3) { + Regex re("a+b+"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("ab")); + EXPECT_TRUE(rs.Match("aab")); + EXPECT_TRUE(rs.Match("abb")); + EXPECT_TRUE(rs.Match("aabb")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("ba")); +} + +TEST(Regex, OneOrMore4) { + Regex re("a(ab)+b"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("aabb")); + EXPECT_TRUE(rs.Match("aababb")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("ab")); +} + +TEST(Regex, QuantifierExact1) { + Regex re("ab{3}c"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abbbc")); + EXPECT_FALSE(rs.Match("ac")); + EXPECT_FALSE(rs.Match("abc")); + EXPECT_FALSE(rs.Match("abbc")); + EXPECT_FALSE(rs.Match("abbbbc")); +} + +TEST(Regex, QuantifierExact2) { + Regex re("a(bc){3}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abcbcbcd")); + EXPECT_FALSE(rs.Match("ad")); + EXPECT_FALSE(rs.Match("abcd")); + EXPECT_FALSE(rs.Match("abcbcd")); + EXPECT_FALSE(rs.Match("abcbcbcbcd")); +} + +TEST(Regex, QuantifierExact3) { + Regex re("a(b|c){3}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abbbd")); + EXPECT_TRUE(rs.Match("acccd")); + EXPECT_TRUE(rs.Match("abcbd")); + EXPECT_FALSE(rs.Match("ad")); + EXPECT_FALSE(rs.Match("abbd")); + EXPECT_FALSE(rs.Match("accccd")); + EXPECT_FALSE(rs.Match("abbbbd")); +} + +TEST(Regex, QuantifierMin1) { + Regex re("ab{3,}c"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abbbc")); + EXPECT_TRUE(rs.Match("abbbbc")); + EXPECT_TRUE(rs.Match("abbbbbc")); + EXPECT_FALSE(rs.Match("ac")); + EXPECT_FALSE(rs.Match("abc")); + EXPECT_FALSE(rs.Match("abbc")); +} + +TEST(Regex, QuantifierMin2) { + Regex re("a(bc){3,}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abcbcbcd")); + EXPECT_TRUE(rs.Match("abcbcbcbcd")); + EXPECT_FALSE(rs.Match("ad")); + EXPECT_FALSE(rs.Match("abcd")); + EXPECT_FALSE(rs.Match("abcbcd")); +} + +TEST(Regex, QuantifierMin3) { + Regex re("a(b|c){3,}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abbbd")); + EXPECT_TRUE(rs.Match("acccd")); + EXPECT_TRUE(rs.Match("abcbd")); + EXPECT_TRUE(rs.Match("accccd")); + EXPECT_TRUE(rs.Match("abbbbd")); + EXPECT_FALSE(rs.Match("ad")); + EXPECT_FALSE(rs.Match("abbd")); +} + +TEST(Regex, QuantifierMinMax1) { + Regex re("ab{3,5}c"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abbbc")); + EXPECT_TRUE(rs.Match("abbbbc")); + EXPECT_TRUE(rs.Match("abbbbbc")); + EXPECT_FALSE(rs.Match("ac")); + EXPECT_FALSE(rs.Match("abc")); + EXPECT_FALSE(rs.Match("abbc")); + EXPECT_FALSE(rs.Match("abbbbbbc")); +} + +TEST(Regex, QuantifierMinMax2) { + Regex re("a(bc){3,5}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abcbcbcd")); + EXPECT_TRUE(rs.Match("abcbcbcbcd")); + EXPECT_TRUE(rs.Match("abcbcbcbcbcd")); + EXPECT_FALSE(rs.Match("ad")); + EXPECT_FALSE(rs.Match("abcd")); + EXPECT_FALSE(rs.Match("abcbcd")); + EXPECT_FALSE(rs.Match("abcbcbcbcbcbcd")); +} + +TEST(Regex, QuantifierMinMax3) { + Regex re("a(b|c){3,5}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("abbbd")); + EXPECT_TRUE(rs.Match("acccd")); + EXPECT_TRUE(rs.Match("abcbd")); + EXPECT_TRUE(rs.Match("accccd")); + EXPECT_TRUE(rs.Match("abbbbd")); + EXPECT_TRUE(rs.Match("acccccd")); + EXPECT_TRUE(rs.Match("abbbbbd")); + EXPECT_FALSE(rs.Match("ad")); + EXPECT_FALSE(rs.Match("abbd")); + EXPECT_FALSE(rs.Match("accccccd")); + EXPECT_FALSE(rs.Match("abbbbbbd")); +} + +// Issue538 +TEST(Regex, QuantifierMinMax4) { + Regex re("a(b|c){0,3}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("ad")); + EXPECT_TRUE(rs.Match("abd")); + EXPECT_TRUE(rs.Match("acd")); + EXPECT_TRUE(rs.Match("abbd")); + EXPECT_TRUE(rs.Match("accd")); + EXPECT_TRUE(rs.Match("abcd")); + EXPECT_TRUE(rs.Match("abbbd")); + EXPECT_TRUE(rs.Match("acccd")); + EXPECT_FALSE(rs.Match("abbbbd")); + EXPECT_FALSE(rs.Match("add")); + EXPECT_FALSE(rs.Match("accccd")); + EXPECT_FALSE(rs.Match("abcbcd")); +} + +// Issue538 +TEST(Regex, QuantifierMinMax5) { + Regex re("a(b|c){0,}d"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("ad")); + EXPECT_TRUE(rs.Match("abd")); + EXPECT_TRUE(rs.Match("acd")); + EXPECT_TRUE(rs.Match("abbd")); + EXPECT_TRUE(rs.Match("accd")); + EXPECT_TRUE(rs.Match("abcd")); + EXPECT_TRUE(rs.Match("abbbd")); + EXPECT_TRUE(rs.Match("acccd")); + EXPECT_TRUE(rs.Match("abbbbd")); + EXPECT_TRUE(rs.Match("accccd")); + EXPECT_TRUE(rs.Match("abcbcd")); + EXPECT_FALSE(rs.Match("add")); + EXPECT_FALSE(rs.Match("aad")); +} + +#define EURO "\xE2\x82\xAC" // "\xE2\x82\xAC" is UTF-8 rsquence of Euro sign U+20AC + +TEST(Regex, Unicode) { + Regex re("a" EURO "+b"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a" EURO "b")); + EXPECT_TRUE(rs.Match("a" EURO EURO "b")); + EXPECT_FALSE(rs.Match("a?b")); + EXPECT_FALSE(rs.Match("a" EURO "\xAC" "b")); // unaware of UTF-8 will match +} + +TEST(Regex, AnyCharacter) { + Regex re("."); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match(EURO)); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("aa")); +} + +TEST(Regex, CharacterRange1) { + Regex re("[abc]"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match("c")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("`")); + EXPECT_FALSE(rs.Match("d")); + EXPECT_FALSE(rs.Match("aa")); +} + +TEST(Regex, CharacterRange2) { + Regex re("[^abc]"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("`")); + EXPECT_TRUE(rs.Match("d")); + EXPECT_FALSE(rs.Match("a")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("c")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("aa")); +} + +TEST(Regex, CharacterRange3) { + Regex re("[a-c]"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("b")); + EXPECT_TRUE(rs.Match("c")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("`")); + EXPECT_FALSE(rs.Match("d")); + EXPECT_FALSE(rs.Match("aa")); +} + +TEST(Regex, CharacterRange4) { + Regex re("[^a-c]"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("`")); + EXPECT_TRUE(rs.Match("d")); + EXPECT_FALSE(rs.Match("a")); + EXPECT_FALSE(rs.Match("b")); + EXPECT_FALSE(rs.Match("c")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("aa")); +} + +TEST(Regex, CharacterRange5) { + Regex re("[-]"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("-")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("a")); +} + +TEST(Regex, CharacterRange6) { + Regex re("[a-]"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("-")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("`")); + EXPECT_FALSE(rs.Match("b")); +} + +TEST(Regex, CharacterRange7) { + Regex re("[-a]"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("a")); + EXPECT_TRUE(rs.Match("-")); + EXPECT_FALSE(rs.Match("")); + EXPECT_FALSE(rs.Match("`")); + EXPECT_FALSE(rs.Match("b")); +} + +TEST(Regex, CharacterRange8) { + Regex re("[a-zA-Z0-9]*"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("Milo")); + EXPECT_TRUE(rs.Match("MT19937")); + EXPECT_TRUE(rs.Match("43")); + EXPECT_FALSE(rs.Match("a_b")); + EXPECT_FALSE(rs.Match("!")); +} + +TEST(Regex, Search) { + Regex re("abc"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Search("abc")); + EXPECT_TRUE(rs.Search("_abc")); + EXPECT_TRUE(rs.Search("abc_")); + EXPECT_TRUE(rs.Search("_abc_")); + EXPECT_TRUE(rs.Search("__abc__")); + EXPECT_TRUE(rs.Search("abcabc")); + EXPECT_FALSE(rs.Search("a")); + EXPECT_FALSE(rs.Search("ab")); + EXPECT_FALSE(rs.Search("bc")); + EXPECT_FALSE(rs.Search("cba")); +} + +TEST(Regex, Search_BeginAnchor) { + Regex re("^abc"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Search("abc")); + EXPECT_TRUE(rs.Search("abc_")); + EXPECT_TRUE(rs.Search("abcabc")); + EXPECT_FALSE(rs.Search("_abc")); + EXPECT_FALSE(rs.Search("_abc_")); + EXPECT_FALSE(rs.Search("a")); + EXPECT_FALSE(rs.Search("ab")); + EXPECT_FALSE(rs.Search("bc")); + EXPECT_FALSE(rs.Search("cba")); +} + +TEST(Regex, Search_EndAnchor) { + Regex re("abc$"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Search("abc")); + EXPECT_TRUE(rs.Search("_abc")); + EXPECT_TRUE(rs.Search("abcabc")); + EXPECT_FALSE(rs.Search("abc_")); + EXPECT_FALSE(rs.Search("_abc_")); + EXPECT_FALSE(rs.Search("a")); + EXPECT_FALSE(rs.Search("ab")); + EXPECT_FALSE(rs.Search("bc")); + EXPECT_FALSE(rs.Search("cba")); +} + +TEST(Regex, Search_BothAnchor) { + Regex re("^abc$"); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Search("abc")); + EXPECT_FALSE(rs.Search("")); + EXPECT_FALSE(rs.Search("a")); + EXPECT_FALSE(rs.Search("b")); + EXPECT_FALSE(rs.Search("ab")); + EXPECT_FALSE(rs.Search("abcd")); +} + +TEST(Regex, Escape) { + const char* s = "\\^\\$\\|\\(\\)\\?\\*\\+\\.\\[\\]\\{\\}\\\\\\f\\n\\r\\t\\v[\\b][\\[][\\]]"; + Regex re(s); + ASSERT_TRUE(re.IsValid()); + RegexSearch rs(re); + EXPECT_TRUE(rs.Match("^$|()?*+.[]{}\\\x0C\n\r\t\x0B\b[]")); + EXPECT_FALSE(rs.Match(s)); // Not escaping +} + +TEST(Regex, Invalid) { +#define TEST_INVALID(s) \ + {\ + Regex re(s);\ + EXPECT_FALSE(re.IsValid());\ + } + + TEST_INVALID(""); + TEST_INVALID("a|"); + TEST_INVALID("()"); + TEST_INVALID("("); + TEST_INVALID(")"); + TEST_INVALID("(a))"); + TEST_INVALID("(a|)"); + TEST_INVALID("(a||b)"); + TEST_INVALID("(|b)"); + TEST_INVALID("?"); + TEST_INVALID("*"); + TEST_INVALID("+"); + TEST_INVALID("{"); + TEST_INVALID("{}"); + TEST_INVALID("a{a}"); + TEST_INVALID("a{0}"); + TEST_INVALID("a{-1}"); + TEST_INVALID("a{}"); + // TEST_INVALID("a{0,}"); // Support now + TEST_INVALID("a{,0}"); + TEST_INVALID("a{1,0}"); + TEST_INVALID("a{-1,0}"); + TEST_INVALID("a{-1,1}"); + TEST_INVALID("a{4294967296}"); // overflow of unsigned + TEST_INVALID("a{1a}"); + TEST_INVALID("["); + TEST_INVALID("[]"); + TEST_INVALID("[^]"); + TEST_INVALID("[\\a]"); + TEST_INVALID("\\a"); + +#undef TEST_INVALID +} + +TEST(Regex, Issue538) { + Regex re("^[0-9]+(\\\\.[0-9]+){0,2}"); + EXPECT_TRUE(re.IsValid()); +} + +TEST(Regex, Issue583) { + Regex re("[0-9]{99999}"); + ASSERT_TRUE(re.IsValid()); +} + +#undef EURO diff --git a/deps/rapidjson/test/unittest/schematest.cpp b/deps/rapidjson/test/unittest/schematest.cpp new file mode 100644 index 0000000..7387c08 --- /dev/null +++ b/deps/rapidjson/test/unittest/schematest.cpp @@ -0,0 +1,3575 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#define RAPIDJSON_HAS_STDSTRING 1 + +#include "unittest.h" +#include "rapidjson/schema.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" +#include "rapidjson/error/error.h" +#include "rapidjson/error/en.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(variadic-macros) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4822) // local class member function does not have a body +#endif + +using namespace rapidjson; + +#define TEST_HASHER(json1, json2, expected) \ +{\ + Document d1, d2;\ + d1.Parse(json1);\ + ASSERT_FALSE(d1.HasParseError());\ + d2.Parse(json2);\ + ASSERT_FALSE(d2.HasParseError());\ + internal::Hasher h1, h2;\ + d1.Accept(h1);\ + d2.Accept(h2);\ + ASSERT_TRUE(h1.IsValid());\ + ASSERT_TRUE(h2.IsValid());\ + /*printf("%s: 0x%016llx\n%s: 0x%016llx\n\n", json1, h1.GetHashCode(), json2, h2.GetHashCode());*/\ + EXPECT_TRUE(expected == (h1.GetHashCode() == h2.GetHashCode()));\ +} + +TEST(SchemaValidator, Hasher) { + TEST_HASHER("null", "null", true); + + TEST_HASHER("true", "true", true); + TEST_HASHER("false", "false", true); + TEST_HASHER("true", "false", false); + TEST_HASHER("false", "true", false); + TEST_HASHER("true", "null", false); + TEST_HASHER("false", "null", false); + + TEST_HASHER("1", "1", true); + TEST_HASHER("2147483648", "2147483648", true); // 2^31 can only be fit in unsigned + TEST_HASHER("-2147483649", "-2147483649", true); // -2^31 - 1 can only be fit in int64_t + TEST_HASHER("2147483648", "2147483648", true); // 2^31 can only be fit in unsigned + TEST_HASHER("4294967296", "4294967296", true); // 2^32 can only be fit in int64_t + TEST_HASHER("9223372036854775808", "9223372036854775808", true); // 2^63 can only be fit in uint64_t + TEST_HASHER("1.5", "1.5", true); + TEST_HASHER("1", "1.0", true); + TEST_HASHER("1", "-1", false); + TEST_HASHER("0.0", "-0.0", false); + TEST_HASHER("1", "true", false); + TEST_HASHER("0", "false", false); + TEST_HASHER("0", "null", false); + + TEST_HASHER("\"\"", "\"\"", true); + TEST_HASHER("\"\"", "\"\\u0000\"", false); + TEST_HASHER("\"Hello\"", "\"Hello\"", true); + TEST_HASHER("\"Hello\"", "\"World\"", false); + TEST_HASHER("\"Hello\"", "null", false); + TEST_HASHER("\"Hello\\u0000\"", "\"Hello\"", false); + TEST_HASHER("\"\"", "null", false); + TEST_HASHER("\"\"", "true", false); + TEST_HASHER("\"\"", "false", false); + + TEST_HASHER("[]", "[ ]", true); + TEST_HASHER("[1, true, false]", "[1, true, false]", true); + TEST_HASHER("[1, true, false]", "[1, true]", false); + TEST_HASHER("[1, 2]", "[2, 1]", false); + TEST_HASHER("[[1], 2]", "[[1, 2]]", false); + TEST_HASHER("[1, 2]", "[1, [2]]", false); + TEST_HASHER("[]", "null", false); + TEST_HASHER("[]", "true", false); + TEST_HASHER("[]", "false", false); + TEST_HASHER("[]", "0", false); + TEST_HASHER("[]", "0.0", false); + TEST_HASHER("[]", "\"\"", false); + + TEST_HASHER("{}", "{ }", true); + TEST_HASHER("{\"a\":1}", "{\"a\":1}", true); + TEST_HASHER("{\"a\":1}", "{\"b\":1}", false); + TEST_HASHER("{\"a\":1}", "{\"a\":2}", false); + TEST_HASHER("{\"a\":1, \"b\":2}", "{\"b\":2, \"a\":1}", true); // Member order insensitive + TEST_HASHER("{}", "null", false); + TEST_HASHER("{}", "false", false); + TEST_HASHER("{}", "true", false); + TEST_HASHER("{}", "0", false); + TEST_HASHER("{}", "0.0", false); + TEST_HASHER("{}", "\"\"", false); +} + +// Test cases following http://spacetelescope.github.io/understanding-json-schema + +#define VALIDATE(schema, json, expected) \ +{\ + VALIDATE_(schema, json, expected, true) \ +} + +#define VALIDATE_(schema, json, expected, expected2) \ +{\ + EXPECT_TRUE(expected2 == schema.GetError().ObjectEmpty());\ + EXPECT_TRUE(schema.IsSupportedSpecification());\ + SchemaValidator validator(schema);\ + Document d;\ + /*printf("\n%s\n", json);*/\ + d.Parse(json);\ + EXPECT_FALSE(d.HasParseError());\ + EXPECT_TRUE(expected == d.Accept(validator));\ + EXPECT_TRUE(expected == validator.IsValid());\ + ValidateErrorCode code = validator.GetInvalidSchemaCode();\ + if (expected) {\ + EXPECT_TRUE(code == kValidateErrorNone);\ + EXPECT_TRUE(validator.GetInvalidSchemaKeyword() == 0);\ + }\ + if ((expected) && !validator.IsValid()) {\ + StringBuffer sb;\ + validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);\ + printf("Invalid schema: %s\n", sb.GetString());\ + printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());\ + printf("Invalid code: %d\n", code);\ + printf("Invalid message: %s\n", GetValidateError_En(code));\ + sb.Clear();\ + validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);\ + printf("Invalid document: %s\n", sb.GetString());\ + sb.Clear();\ + Writer w(sb);\ + validator.GetError().Accept(w);\ + printf("Validation error: %s\n", sb.GetString());\ + }\ +} + +#define INVALIDATE(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error) \ +{\ + INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, kValidateDefaultFlags, SchemaValidator, Pointer) \ +} + +#define INVALIDATE_(schema, json, invalidSchemaPointer, invalidSchemaKeyword, invalidDocumentPointer, error, \ + flags, SchemaValidatorType, PointerType) \ +{\ + EXPECT_TRUE(schema.GetError().ObjectEmpty());\ + EXPECT_TRUE(schema.IsSupportedSpecification());\ + SchemaValidatorType validator(schema);\ + validator.SetValidateFlags(flags);\ + Document d;\ + /*printf("\n%s\n", json);*/\ + d.Parse(json);\ + EXPECT_FALSE(d.HasParseError());\ + d.Accept(validator);\ + EXPECT_FALSE(validator.IsValid());\ + ValidateErrorCode code = validator.GetInvalidSchemaCode();\ + ASSERT_TRUE(code != kValidateErrorNone);\ + ASSERT_TRUE(strcmp(GetValidateError_En(code), "Unknown error.") != 0);\ + if (validator.GetInvalidSchemaPointer() != PointerType(invalidSchemaPointer)) {\ + StringBuffer sb;\ + validator.GetInvalidSchemaPointer().Stringify(sb);\ + printf("GetInvalidSchemaPointer() Expected: %s Actual: %s\n", invalidSchemaPointer, sb.GetString());\ + ADD_FAILURE();\ + }\ + ASSERT_TRUE(validator.GetInvalidSchemaKeyword() != 0);\ + if (strcmp(validator.GetInvalidSchemaKeyword(), invalidSchemaKeyword) != 0) {\ + printf("GetInvalidSchemaKeyword() Expected: %s Actual %s\n", invalidSchemaKeyword, validator.GetInvalidSchemaKeyword());\ + ADD_FAILURE();\ + }\ + if (validator.GetInvalidDocumentPointer() != PointerType(invalidDocumentPointer)) {\ + StringBuffer sb;\ + validator.GetInvalidDocumentPointer().Stringify(sb);\ + printf("GetInvalidDocumentPointer() Expected: %s Actual: %s\n", invalidDocumentPointer, sb.GetString());\ + ADD_FAILURE();\ + }\ + Document e;\ + e.Parse(error);\ + if (validator.GetError() != e) {\ + StringBuffer sb;\ + Writer w(sb);\ + validator.GetError().Accept(w);\ + printf("GetError() Expected: %s Actual: %s\n", error, sb.GetString());\ + ADD_FAILURE();\ + }\ +} + +// Use for checking whether a compiled schema document contains errors +#define SCHEMAERROR(schema, error) \ +{\ + Document e;\ + e.Parse(error);\ + if (schema.GetError() != e) {\ + StringBuffer sb;\ + Writer w(sb);\ + schema.GetError().Accept(w);\ + printf("GetError() Expected: %s Actual: %s\n", error, sb.GetString());\ + ADD_FAILURE();\ + }\ +} + +TEST(SchemaValidator, Typeless) { + Document sd; + sd.Parse("{}"); + SchemaDocument s(sd); + + VALIDATE(s, "42", true); + VALIDATE(s, "\"I'm a string\"", true); + VALIDATE(s, "{ \"an\": [ \"arbitrarily\", \"nested\" ], \"data\": \"structure\" }", true); +} + +TEST(SchemaValidator, MultiType) { + Document sd; + sd.Parse("{ \"type\": [\"number\", \"string\"] }"); + SchemaDocument s(sd); + + VALIDATE(s, "42", true); + VALIDATE(s, "\"Life, the universe, and everything\"", true); + INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\", \"number\"], \"actual\": \"array\"" + "}}"); +} + +TEST(SchemaValidator, Enum_Typed) { + Document sd; + sd.Parse("{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }"); + SchemaDocument s(sd); + + VALIDATE(s, "\"red\"", true); + INVALIDATE(s, "\"blue\"", "", "enum", "", + "{ \"enum\": { \"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}"); +} + +TEST(SchemaValidator, Enum_Typeless) { + Document sd; + sd.Parse("{ \"enum\": [\"red\", \"amber\", \"green\", null, 42] }"); + SchemaDocument s(sd); + + VALIDATE(s, "\"red\"", true); + VALIDATE(s, "null", true); + VALIDATE(s, "42", true); + INVALIDATE(s, "0", "", "enum", "", + "{ \"enum\": { \"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}"); +} + +TEST(SchemaValidator, Enum_InvalidType) { + Document sd; + sd.Parse("{ \"type\": \"string\", \"enum\": [\"red\", \"amber\", \"green\", null] }"); + SchemaDocument s(sd); + + VALIDATE(s, "\"red\"", true); + INVALIDATE(s, "null", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"null\"" + "}}"); +} + +TEST(SchemaValidator, AllOf) { + { + Document sd; + sd.Parse("{\"allOf\": [{ \"type\": \"string\" }, { \"type\": \"string\", \"maxLength\": 5 }]}"); + SchemaDocument s(sd); + + VALIDATE(s, "\"ok\"", true); + INVALIDATE(s, "\"too long\"", "", "allOf", "", + "{ \"allOf\": {" + " \"errors\": [" + " {}," + " {\"maxLength\": {\"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\", \"expected\": 5, \"actual\": \"too long\"}}" + " ]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + "}}"); + } + { + Document sd; + sd.Parse("{\"allOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }"); + SchemaDocument s(sd); + + VALIDATE(s, "\"No way\"", false); + INVALIDATE(s, "-1", "", "allOf", "", + "{ \"allOf\": {" + " \"errors\": [" + " {\"type\": { \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\", \"errorCode\": 20, \"expected\": [\"string\"], \"actual\": \"integer\"}}," + " {}" + " ]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + "}}"); + } +} + +TEST(SchemaValidator, AnyOf) { + Document sd; + sd.Parse("{\"anyOf\": [{ \"type\": \"string\" }, { \"type\": \"number\" } ] }"); + SchemaDocument s(sd); + + VALIDATE(s, "\"Yes\"", true); + VALIDATE(s, "42", true); + INVALIDATE(s, "{ \"Not a\": \"string or number\" }", "", "anyOf", "", + "{ \"anyOf\": {" + " \"errorCode\": 24," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\", " + " \"errors\": [" + " { \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/0\"," + " \"expected\": [\"string\"], \"actual\": \"object\"" + " }}," + " { \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/1\"," + " \"expected\": [\"number\"], \"actual\": \"object\"" + " }}" + " ]" + "}}"); +} + +TEST(SchemaValidator, OneOf) { + Document sd; + sd.Parse("{\"oneOf\": [{ \"type\": \"number\", \"multipleOf\": 5 }, { \"type\": \"number\", \"multipleOf\": 3 } ] }"); + SchemaDocument s(sd); + + VALIDATE(s, "10", true); + VALIDATE(s, "9", true); + INVALIDATE(s, "2", "", "oneOf", "", + "{ \"oneOf\": {" + " \"errorCode\": 21," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"errors\": [" + " { \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#/oneOf/0\"," + " \"expected\": 5, \"actual\": 2" + " }}," + " { \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#/oneOf/1\"," + " \"expected\": 3, \"actual\": 2" + " }}" + " ]" + "}}"); + INVALIDATE(s, "15", "", "oneOf", "", + "{ \"oneOf\": { \"errorCode\": 22, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"matches\": [0,1]}}"); +} + +TEST(SchemaValidator, Not) { + Document sd; + sd.Parse("{\"not\":{ \"type\": \"string\"}}"); + SchemaDocument s(sd); + + VALIDATE(s, "42", true); + VALIDATE(s, "{ \"key\": \"value\" }", true); + INVALIDATE(s, "\"I am a string\"", "", "not", "", + "{ \"not\": { \"errorCode\": 25, \"instanceRef\": \"#\", \"schemaRef\": \"#\" }}"); +} + +TEST(SchemaValidator, Ref) { + Document sd; + sd.Parse( + "{" + " \"$schema\": \"http://json-schema.org/draft-04/schema#\"," + "" + " \"definitions\": {" + " \"address\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"street_address\": { \"type\": \"string\" }," + " \"city\": { \"type\": \"string\" }," + " \"state\": { \"type\": \"string\" }" + " }," + " \"required\": [\"street_address\", \"city\", \"state\"]" + " }" + " }," + " \"type\": \"object\"," + " \"properties\": {" + " \"billing_address\": { \"$ref\": \"#/definitions/address\" }," + " \"shipping_address\": { \"$ref\": \"#/definitions/address\" }" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\"}, \"billing_address\": {\"street_address\": \"1st Street SE\", \"city\": \"Washington\", \"state\": \"DC\"} }", true); +} + +TEST(SchemaValidator, Ref_AllOf) { + Document sd; + sd.Parse( + "{" + " \"$schema\": \"http://json-schema.org/draft-04/schema#\"," + "" + " \"definitions\": {" + " \"address\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"street_address\": { \"type\": \"string\" }," + " \"city\": { \"type\": \"string\" }," + " \"state\": { \"type\": \"string\" }" + " }," + " \"required\": [\"street_address\", \"city\", \"state\"]" + " }" + " }," + " \"type\": \"object\"," + " \"properties\": {" + " \"billing_address\": { \"$ref\": \"#/definitions/address\" }," + " \"shipping_address\": {" + " \"allOf\": [" + " { \"$ref\": \"#/definitions/address\" }," + " { \"properties\":" + " { \"type\": { \"enum\": [ \"residential\", \"business\" ] } }," + " \"required\": [\"type\"]" + " }" + " ]" + " }" + " }" + "}"); + SchemaDocument s(sd); + + INVALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\"} }", "/properties/shipping_address", "allOf", "/shipping_address", + "{ \"allOf\": {" + " \"errors\": [" + " {}," + " {\"required\": {\"errorCode\": 15, \"instanceRef\": \"#/shipping_address\", \"schemaRef\": \"#/properties/shipping_address/allOf/1\", \"missing\": [\"type\"]}}" + " ]," + " \"errorCode\":23,\"instanceRef\":\"#/shipping_address\",\"schemaRef\":\"#/properties/shipping_address\"" + "}}"); + VALIDATE(s, "{\"shipping_address\": {\"street_address\": \"1600 Pennsylvania Avenue NW\", \"city\": \"Washington\", \"state\": \"DC\", \"type\": \"business\"} }", true); +} + +TEST(SchemaValidator, String) { + Document sd; + sd.Parse("{\"type\":\"string\"}"); + SchemaDocument s(sd); + + VALIDATE(s, "\"I'm a string\"", true); + INVALIDATE(s, "42", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); + INVALIDATE(s, "2147483648", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); // 2^31 can only be fit in unsigned + INVALIDATE(s, "-2147483649", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); // -2^31 - 1 can only be fit in int64_t + INVALIDATE(s, "4294967296", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); // 2^32 can only be fit in int64_t + INVALIDATE(s, "3.1415926", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"number\"" + "}}"); +} + +TEST(SchemaValidator, String_LengthRange) { + Document sd; + sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}"); + SchemaDocument s(sd); + + INVALIDATE(s, "\"A\"", "", "minLength", "", + "{ \"minLength\": {" + " \"errorCode\": 7," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 2, \"actual\": \"A\"" + "}}"); + VALIDATE(s, "\"AB\"", true); + VALIDATE(s, "\"ABC\"", true); + INVALIDATE(s, "\"ABCD\"", "", "maxLength", "", + "{ \"maxLength\": {" + " \"errorCode\": 6," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 3, \"actual\": \"ABCD\"" + "}}"); +} + +#if RAPIDJSON_SCHEMA_HAS_REGEX +TEST(SchemaValidator, String_Pattern) { + Document sd; + sd.Parse("{\"type\":\"string\",\"pattern\":\"^(\\\\([0-9]{3}\\\\))?[0-9]{3}-[0-9]{4}$\"}"); + SchemaDocument s(sd); + + VALIDATE(s, "\"555-1212\"", true); + VALIDATE(s, "\"(888)555-1212\"", true); + INVALIDATE(s, "\"(888)555-1212 ext. 532\"", "", "pattern", "", + "{ \"pattern\": {" + " \"errorCode\": 8," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"actual\": \"(888)555-1212 ext. 532\"" + "}}"); + INVALIDATE(s, "\"(800)FLOWERS\"", "", "pattern", "", + "{ \"pattern\": {" + " \"errorCode\": 8," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"actual\": \"(800)FLOWERS\"" + "}}"); +} + +TEST(SchemaValidator, String_Pattern_Invalid) { + Document sd; + sd.Parse("{\"type\":\"string\",\"pattern\":\"a{0}\"}"); + SchemaDocument s(sd); + SCHEMAERROR(s, "{\"RegexInvalid\":{\"errorCode\":9,\"instanceRef\":\"#/pattern\",\"value\":\"a{0}\"}}"); + + VALIDATE_(s, "\"\"", true, false); + VALIDATE_(s, "\"a\"", true, false); + VALIDATE_(s, "\"aa\"", true, false); +} +#endif + +TEST(SchemaValidator, Integer) { + Document sd; + sd.Parse("{\"type\":\"integer\"}"); + SchemaDocument s(sd); + + VALIDATE(s, "42", true); + VALIDATE(s, "-1", true); + VALIDATE(s, "2147483648", true); // 2^31 can only be fit in unsigned + VALIDATE(s, "-2147483649", true); // -2^31 - 1 can only be fit in int64_t + VALIDATE(s, "2147483648", true); // 2^31 can only be fit in unsigned + VALIDATE(s, "4294967296", true); // 2^32 can only be fit in int64_t + INVALIDATE(s, "3.1415926", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"integer\"], \"actual\": \"number\"" + "}}"); + INVALIDATE(s, "\"42\"", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"integer\"], \"actual\": \"string\"" + "}}"); +} + +TEST(SchemaValidator, Integer_Range) { + Document sd; + sd.Parse("{\"type\":\"integer\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-1", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 0, \"actual\": -1" + "}}"); + VALIDATE(s, "0", true); + VALIDATE(s, "10", true); + VALIDATE(s, "99", true); + INVALIDATE(s, "100", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100" + "}}"); + INVALIDATE(s, "101", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 101" + "}}"); +} + +TEST(SchemaValidator, Integer_Range64Boundary) { + Document sd; + sd.Parse("{\"type\":\"integer\",\"minimum\":-9223372036854775807,\"maximum\":9223372036854775806}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-9223372036854775808", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -9223372036854775807, \"actual\": -9223372036854775808" + "}}"); + VALIDATE(s, "-9223372036854775807", true); + VALIDATE(s, "-2147483648", true); // int min + VALIDATE(s, "0", true); + VALIDATE(s, "2147483647", true); // int max + VALIDATE(s, "2147483648", true); // unsigned first + VALIDATE(s, "4294967295", true); // unsigned max + VALIDATE(s, "9223372036854775806", true); + INVALIDATE(s, "9223372036854775807", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 2," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775806, \"actual\": 9223372036854775807" + "}}"); + INVALIDATE(s, "18446744073709551615", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 2," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775806, \"actual\": 18446744073709551615" + "}}"); // uint64_t max +} + +TEST(SchemaValidator, Integer_RangeU64Boundary) { + Document sd; + sd.Parse("{\"type\":\"integer\",\"minimum\":9223372036854775808,\"maximum\":18446744073709551614}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-9223372036854775808", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808, \"actual\": -9223372036854775808" + "}}"); + INVALIDATE(s, "9223372036854775807", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808, \"actual\": 9223372036854775807" + "}}"); + INVALIDATE(s, "-2147483648", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808, \"actual\": -2147483648" + "}}"); // int min + INVALIDATE(s, "0", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808, \"actual\": 0" + "}}"); + INVALIDATE(s, "2147483647", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808, \"actual\": 2147483647" + "}}"); // int max + INVALIDATE(s, "2147483648", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808, \"actual\": 2147483648" + "}}"); // unsigned first + INVALIDATE(s, "4294967295", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808, \"actual\": 4294967295" + "}}"); // unsigned max + VALIDATE(s, "9223372036854775808", true); + VALIDATE(s, "18446744073709551614", true); + INVALIDATE(s, "18446744073709551615", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 2," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 18446744073709551614, \"actual\": 18446744073709551615" + "}}"); +} + +TEST(SchemaValidator, Integer_Range64BoundaryExclusive) { + Document sd; + sd.Parse("{\"type\":\"integer\",\"minimum\":-9223372036854775808,\"maximum\":18446744073709551615,\"exclusiveMinimum\":true,\"exclusiveMaximum\":true}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-9223372036854775808", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 5," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -9223372036854775808, \"exclusiveMinimum\": true, " + " \"actual\": -9223372036854775808" + "}}"); + VALIDATE(s, "-9223372036854775807", true); + VALIDATE(s, "18446744073709551614", true); + INVALIDATE(s, "18446744073709551615", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 18446744073709551615, \"exclusiveMaximum\": true, " + " \"actual\": 18446744073709551615" + "}}"); +} + +TEST(SchemaValidator, Integer_MultipleOf) { + Document sd; + sd.Parse("{\"type\":\"integer\",\"multipleOf\":10}"); + SchemaDocument s(sd); + + VALIDATE(s, "0", true); + VALIDATE(s, "10", true); + VALIDATE(s, "-10", true); + VALIDATE(s, "20", true); + INVALIDATE(s, "23", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 10, \"actual\": 23" + "}}"); + INVALIDATE(s, "-23", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 10, \"actual\": -23" + "}}"); +} + +TEST(SchemaValidator, Integer_MultipleOf64Boundary) { + Document sd; + sd.Parse("{\"type\":\"integer\",\"multipleOf\":18446744073709551615}"); + SchemaDocument s(sd); + + VALIDATE(s, "0", true); + VALIDATE(s, "18446744073709551615", true); + INVALIDATE(s, "18446744073709551614", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 18446744073709551615, \"actual\": 18446744073709551614" + "}}"); +} + +TEST(SchemaValidator, Number_Range) { + Document sd; + sd.Parse("{\"type\":\"number\",\"minimum\":0,\"maximum\":100,\"exclusiveMaximum\":true}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-1", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 0, \"actual\": -1" + "}}"); + VALIDATE(s, "0", true); + VALIDATE(s, "0.1", true); + VALIDATE(s, "10", true); + VALIDATE(s, "99", true); + VALIDATE(s, "99.9", true); + INVALIDATE(s, "100", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100" + "}}"); + INVALIDATE(s, "100.0", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 100.0" + "}}"); + INVALIDATE(s, "101.5", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100, \"exclusiveMaximum\": true, \"actual\": 101.5" + "}}"); +} + +TEST(SchemaValidator, Number_RangeInt) { + Document sd; + sd.Parse("{\"type\":\"number\",\"minimum\":-100,\"maximum\":-1,\"exclusiveMaximum\":true}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-101", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -100, \"actual\": -101" + "}}"); + INVALIDATE(s, "-100.1", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -100, \"actual\": -100.1" + "}}"); + VALIDATE(s, "-100", true); + VALIDATE(s, "-2", true); + INVALIDATE(s, "-1", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": -1" + "}}"); + INVALIDATE(s, "-0.9", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": -0.9" + "}}"); + INVALIDATE(s, "0", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 0" + "}}"); + INVALIDATE(s, "2147483647", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 2147483647" + "}}"); // int max + INVALIDATE(s, "2147483648", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 2147483648" + "}}"); // unsigned first + INVALIDATE(s, "4294967295", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 4294967295" + "}}"); // unsigned max + INVALIDATE(s, "9223372036854775808", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 9223372036854775808" + "}}"); + INVALIDATE(s, "18446744073709551614", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614" + "}}"); + INVALIDATE(s, "18446744073709551615", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": -1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615" + "}}"); +} + +TEST(SchemaValidator, Number_RangeDouble) { + Document sd; + sd.Parse("{\"type\":\"number\",\"minimum\":0.1,\"maximum\":100.1,\"exclusiveMaximum\":true}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-9223372036854775808", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 0.1, \"actual\": -9223372036854775808" + "}}"); + INVALIDATE(s, "-2147483648", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 0.1, \"actual\": -2147483648" + "}}"); // int min + INVALIDATE(s, "-1", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 0.1, \"actual\": -1" + "}}"); + VALIDATE(s, "0.1", true); + VALIDATE(s, "10", true); + VALIDATE(s, "99", true); + VALIDATE(s, "100", true); + INVALIDATE(s, "101", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 101" + "}}"); + INVALIDATE(s, "101.5", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 101.5" + "}}"); + INVALIDATE(s, "18446744073709551614", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614" + "}}"); + INVALIDATE(s, "18446744073709551615", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615" + "}}"); + INVALIDATE(s, "2147483647", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 2147483647" + "}}"); // int max + INVALIDATE(s, "2147483648", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 2147483648" + "}}"); // unsigned first + INVALIDATE(s, "4294967295", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 4294967295" + "}}"); // unsigned max + INVALIDATE(s, "9223372036854775808", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 9223372036854775808" + "}}"); + INVALIDATE(s, "18446744073709551614", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551614" + "}}"); + INVALIDATE(s, "18446744073709551615", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 3," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 100.1, \"exclusiveMaximum\": true, \"actual\": 18446744073709551615" + "}}"); +} + +TEST(SchemaValidator, Number_RangeDoubleU64Boundary) { + Document sd; + sd.Parse("{\"type\":\"number\",\"minimum\":9223372036854775808.0,\"maximum\":18446744073709550000.0}"); + SchemaDocument s(sd); + + INVALIDATE(s, "-9223372036854775808", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808.0, \"actual\": -9223372036854775808" + "}}"); + INVALIDATE(s, "-2147483648", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808.0, \"actual\": -2147483648" + "}}"); // int min + INVALIDATE(s, "0", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808.0, \"actual\": 0" + "}}"); + INVALIDATE(s, "2147483647", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808.0, \"actual\": 2147483647" + "}}"); // int max + INVALIDATE(s, "2147483648", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808.0, \"actual\": 2147483648" + "}}"); // unsigned first + INVALIDATE(s, "4294967295", "", "minimum", "", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 9223372036854775808.0, \"actual\": 4294967295" + "}}"); // unsigned max + VALIDATE(s, "9223372036854775808", true); + VALIDATE(s, "18446744073709540000", true); + INVALIDATE(s, "18446744073709551615", "", "maximum", "", + "{ \"maximum\": {" + " \"errorCode\": 2," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 18446744073709550000.0, \"actual\": 18446744073709551615" + "}}"); +} + +TEST(SchemaValidator, Number_MultipleOf) { + Document sd; + sd.Parse("{\"type\":\"number\",\"multipleOf\":10.0}"); + SchemaDocument s(sd); + + VALIDATE(s, "0", true); + VALIDATE(s, "10", true); + VALIDATE(s, "-10", true); + VALIDATE(s, "20", true); + INVALIDATE(s, "23", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 10.0, \"actual\": 23" + "}}"); + INVALIDATE(s, "-2147483648", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 10.0, \"actual\": -2147483648" + "}}"); // int min + VALIDATE(s, "-2147483640", true); + INVALIDATE(s, "2147483647", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 10.0, \"actual\": 2147483647" + "}}"); // int max + INVALIDATE(s, "2147483648", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 10.0, \"actual\": 2147483648" + "}}"); // unsigned first + VALIDATE(s, "2147483650", true); + INVALIDATE(s, "4294967295", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 10.0, \"actual\": 4294967295" + "}}"); // unsigned max + VALIDATE(s, "4294967300", true); +} + +TEST(SchemaValidator, Number_MultipleOfOne) { + Document sd; + sd.Parse("{\"type\":\"number\",\"multipleOf\":1}"); + SchemaDocument s(sd); + + VALIDATE(s, "42", true); + VALIDATE(s, "42.0", true); + INVALIDATE(s, "3.1415926", "", "multipleOf", "", + "{ \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 1, \"actual\": 3.1415926" + "}}"); +} + +TEST(SchemaValidator, Object) { + Document sd; + sd.Parse("{\"type\":\"object\"}"); + SchemaDocument s(sd); + + VALIDATE(s, "{\"key\":\"value\",\"another_key\":\"another_value\"}", true); + VALIDATE(s, "{\"Sun\":1.9891e30,\"Jupiter\":1.8986e27,\"Saturn\":5.6846e26,\"Neptune\":10.243e25,\"Uranus\":8.6810e25,\"Earth\":5.9736e24,\"Venus\":4.8685e24,\"Mars\":6.4185e23,\"Mercury\":3.3022e23,\"Moon\":7.349e22,\"Pluto\":1.25e22}", true); + INVALIDATE(s, "[\"An\", \"array\", \"not\", \"an\", \"object\"]", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"object\"], \"actual\": \"array\"" + "}}"); + INVALIDATE(s, "\"Not an object\"", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"object\"], \"actual\": \"string\"" + "}}"); +} + +TEST(SchemaValidator, Object_Properties) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\" : {" + " \"number\": { \"type\": \"number\" }," + " \"street_name\" : { \"type\": \"string\" }," + " \"street_type\" : { \"type\": \"string\", \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"] }" + " }" + "}"); + + SchemaDocument s(sd); + + VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true); + INVALIDATE(s, "{ \"number\": \"1600\", \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", "/properties/number", "type", "/number", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/number\", \"schemaRef\": \"#/properties/number\"," + " \"expected\": [\"number\"], \"actual\": \"string\"" + "}}"); + INVALIDATE(s, "{ \"number\": \"One\", \"street_name\": \"Microsoft\", \"street_type\": \"Way\" }", + "/properties/number", "type", "/number", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/number\", \"schemaRef\": \"#/properties/number\"," + " \"expected\": [\"number\"], \"actual\": \"string\"" + "}}"); // fail fast + VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\" }", true); + VALIDATE(s, "{}", true); + VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true); +} + +TEST(SchemaValidator, Object_AdditionalPropertiesBoolean) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\" : {" + " \"number\": { \"type\": \"number\" }," + " \"street_name\" : { \"type\": \"string\" }," + " \"street_type\" : { \"type\": \"string\"," + " \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"]" + " }" + " }," + " \"additionalProperties\": false" + "}"); + + SchemaDocument s(sd); + + VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true); + INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", "", "additionalProperties", "/direction", + "{ \"additionalProperties\": {" + " \"errorCode\": 16," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"disallowed\": \"direction\"" + "}}"); +} + +TEST(SchemaValidator, Object_AdditionalPropertiesObject) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\" : {" + " \"number\": { \"type\": \"number\" }," + " \"street_name\" : { \"type\": \"string\" }," + " \"street_type\" : { \"type\": \"string\"," + " \"enum\" : [\"Street\", \"Avenue\", \"Boulevard\"]" + " }" + " }," + " \"additionalProperties\": { \"type\": \"string\" }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\" }", true); + VALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"direction\": \"NW\" }", true); + INVALIDATE(s, "{ \"number\": 1600, \"street_name\": \"Pennsylvania\", \"street_type\": \"Avenue\", \"office_number\": 201 }", "/additionalProperties", "type", "/office_number", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/office_number\", \"schemaRef\": \"#/additionalProperties\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); +} + +TEST(SchemaValidator, Object_Required) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\" : {" + " \"name\": { \"type\": \"string\" }," + " \"email\" : { \"type\": \"string\" }," + " \"address\" : { \"type\": \"string\" }," + " \"telephone\" : { \"type\": \"string\" }" + " }," + " \"required\":[\"name\", \"email\"]" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\" }", true); + VALIDATE(s, "{ \"name\": \"William Shakespeare\", \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}", true); + INVALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", "", "required", "", + "{ \"required\": {" + " \"errorCode\": 15," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"missing\": [\"email\"]" + "}}"); + INVALIDATE(s, "{}", "", "required", "", + "{ \"required\": {" + " \"errorCode\": 15," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"missing\": [\"name\", \"email\"]" + "}}"); +} + +TEST(SchemaValidator, Object_Required_PassWithDefault) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\" : {" + " \"name\": { \"type\": \"string\", \"default\": \"William Shakespeare\" }," + " \"email\" : { \"type\": \"string\", \"default\": \"\" }," + " \"address\" : { \"type\": \"string\" }," + " \"telephone\" : { \"type\": \"string\" }" + " }," + " \"required\":[\"name\", \"email\"]" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"email\" : \"bill@stratford-upon-avon.co.uk\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\", \"authorship\" : \"in question\"}", true); + INVALIDATE(s, "{ \"name\": \"William Shakespeare\", \"address\" : \"Henley Street, Stratford-upon-Avon, Warwickshire, England\" }", "", "required", "", + "{ \"required\": {" + " \"errorCode\": 15," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"missing\": [\"email\"]" + "}}"); + INVALIDATE(s, "{}", "", "required", "", + "{ \"required\": {" + " \"errorCode\": 15," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"missing\": [\"email\"]" + "}}"); +} + +TEST(SchemaValidator, Object_PropertiesRange) { + Document sd; + sd.Parse("{\"type\":\"object\", \"minProperties\":2, \"maxProperties\":3}"); + SchemaDocument s(sd); + + INVALIDATE(s, "{}", "", "minProperties", "", + "{ \"minProperties\": {" + " \"errorCode\": 14," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 2, \"actual\": 0" + "}}"); + INVALIDATE(s, "{\"a\":0}", "", "minProperties", "", + "{ \"minProperties\": {" + " \"errorCode\": 14," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 2, \"actual\": 1" + "}}"); + VALIDATE(s, "{\"a\":0,\"b\":1}", true); + VALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2}", true); + INVALIDATE(s, "{\"a\":0,\"b\":1,\"c\":2,\"d\":3}", "", "maxProperties", "", + "{ \"maxProperties\": {" + " \"errorCode\": 13," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\", " + " \"expected\": 3, \"actual\": 4" + "}}"); +} + +TEST(SchemaValidator, Object_PropertyDependencies) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\": {" + " \"name\": { \"type\": \"string\" }," + " \"credit_card\": { \"type\": \"number\" }," + " \"cvv_code\": { \"type\": \"number\" }," + " \"billing_address\": { \"type\": \"string\" }" + " }," + " \"required\": [\"name\"]," + " \"dependencies\": {" + " \"credit_card\": [\"cvv_code\", \"billing_address\"]" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555, \"cvv_code\": 777, " + "\"billing_address\": \"555 Debtor's Lane\" }", true); + INVALIDATE(s, "{ \"name\": \"John Doe\", \"credit_card\": 5555555555555555 }", "", "dependencies", "", + "{ \"dependencies\": {" + " \"errorCode\": 18," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"errors\": {" + " \"credit_card\": {" + " \"required\": {" + " \"errorCode\": 15," + " \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/credit_card\"," + " \"missing\": [\"cvv_code\", \"billing_address\"]" + " } } }" + "}}"); + VALIDATE(s, "{ \"name\": \"John Doe\"}", true); + VALIDATE(s, "{ \"name\": \"John Doe\", \"cvv_code\": 777, \"billing_address\": \"555 Debtor's Lane\" }", true); +} + +TEST(SchemaValidator, Object_SchemaDependencies) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\" : {" + " \"name\": { \"type\": \"string\" }," + " \"credit_card\" : { \"type\": \"number\" }" + " }," + " \"required\" : [\"name\"]," + " \"dependencies\" : {" + " \"credit_card\": {" + " \"properties\": {" + " \"billing_address\": { \"type\": \"string\" }" + " }," + " \"required\" : [\"billing_address\"]" + " }" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555,\"billing_address\" : \"555 Debtor's Lane\"}", true); + INVALIDATE(s, "{\"name\": \"John Doe\", \"credit_card\" : 5555555555555555 }", "", "dependencies", "", + "{ \"dependencies\": {" + " \"errorCode\": 18," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"errors\": {" + " \"credit_card\": {" + " \"required\": {" + " \"errorCode\": 15," + " \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/credit_card\"," + " \"missing\": [\"billing_address\"]" + " } } }" + "}}"); + VALIDATE(s, "{\"name\": \"John Doe\", \"billing_address\" : \"555 Debtor's Lane\"}", true); +} + +#if RAPIDJSON_SCHEMA_HAS_REGEX +TEST(SchemaValidator, Object_PatternProperties) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"patternProperties\": {" + " \"^S_\": { \"type\": \"string\" }," + " \"^I_\": { \"type\": \"integer\" }" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"S_25\": \"This is a string\" }", true); + VALIDATE(s, "{ \"I_0\": 42 }", true); + INVALIDATE(s, "{ \"S_0\": 42 }", "", "patternProperties", "/S_0", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/S_0\", \"schemaRef\": \"#/patternProperties/%5ES_\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); + INVALIDATE(s, "{ \"I_42\": \"This is a string\" }", "", "patternProperties", "/I_42", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/patternProperties/%5EI_\"," + " \"expected\": [\"integer\"], \"actual\": \"string\"" + "}}"); + VALIDATE(s, "{ \"keyword\": \"value\" }", true); +} + +TEST(SchemaValidator, Object_PatternProperties_ErrorConflict) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"patternProperties\": {" + " \"^I_\": { \"multipleOf\": 5 }," + " \"30$\": { \"multipleOf\": 6 }" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"I_30\": 30 }", true); + INVALIDATE(s, "{ \"I_30\": 7 }", "", "patternProperties", "/I_30", + "{ \"multipleOf\": [" + " {" + " \"errorCode\": 1," + " \"instanceRef\": \"#/I_30\", \"schemaRef\": \"#/patternProperties/%5EI_\"," + " \"expected\": 5, \"actual\": 7" + " }, {" + " \"errorCode\": 1," + " \"instanceRef\": \"#/I_30\", \"schemaRef\": \"#/patternProperties/30%24\"," + " \"expected\": 6, \"actual\": 7" + " }" + "]}"); +} + +TEST(SchemaValidator, Object_Properties_PatternProperties) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\": {" + " \"I_42\": { \"type\": \"integer\", \"minimum\": 73 }" + " }," + " \"patternProperties\": {" + " \"^I_\": { \"type\": \"integer\", \"multipleOf\": 6 }" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"I_6\": 6 }", true); + VALIDATE(s, "{ \"I_42\": 78 }", true); + INVALIDATE(s, "{ \"I_42\": 42 }", "", "patternProperties", "/I_42", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/properties/I_42\"," + " \"expected\": 73, \"actual\": 42" + "}}"); + INVALIDATE(s, "{ \"I_42\": 7 }", "", "patternProperties", "/I_42", + "{ \"minimum\": {" + " \"errorCode\": 4," + " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/properties/I_42\"," + " \"expected\": 73, \"actual\": 7" + " }," + " \"multipleOf\": {" + " \"errorCode\": 1," + " \"instanceRef\": \"#/I_42\", \"schemaRef\": \"#/patternProperties/%5EI_\"," + " \"expected\": 6, \"actual\": 7" + " }" + "}"); +} + +TEST(SchemaValidator, Object_PatternProperties_AdditionalPropertiesObject) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\": {" + " \"builtin\": { \"type\": \"number\" }" + " }," + " \"patternProperties\": {" + " \"^S_\": { \"type\": \"string\" }," + " \"^I_\": { \"type\": \"integer\" }" + " }," + " \"additionalProperties\": { \"type\": \"string\" }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"builtin\": 42 }", true); + VALIDATE(s, "{ \"keyword\": \"value\" }", true); + INVALIDATE(s, "{ \"keyword\": 42 }", "/additionalProperties", "type", "/keyword", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/keyword\", \"schemaRef\": \"#/additionalProperties\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); +} + +// Replaces test Issue285 and tests failure as well as success +TEST(SchemaValidator, Object_PatternProperties_AdditionalPropertiesBoolean) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"patternProperties\": {" + " \"^S_\": { \"type\": \"string\" }," + " \"^I_\": { \"type\": \"integer\" }" + " }," + " \"additionalProperties\": false" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"S_25\": \"This is a string\" }", true); + VALIDATE(s, "{ \"I_0\": 42 }", true); + INVALIDATE(s, "{ \"keyword\": \"value\" }", "", "additionalProperties", "/keyword", + "{ \"additionalProperties\": {" + " \"errorCode\": 16," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"disallowed\": \"keyword\"" + "}}"); +} +#endif + +TEST(SchemaValidator, Array) { + Document sd; + sd.Parse("{\"type\":\"array\"}"); + SchemaDocument s(sd); + + VALIDATE(s, "[1, 2, 3, 4, 5]", true); + VALIDATE(s, "[3, \"different\", { \"types\" : \"of values\" }]", true); + INVALIDATE(s, "{\"Not\": \"an array\"}", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"array\"], \"actual\": \"object\"" + "}}"); +} + +TEST(SchemaValidator, Array_ItemsList) { + Document sd; + sd.Parse( + "{" + " \"type\": \"array\"," + " \"items\" : {" + " \"type\": \"number\"" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "[1, 2, 3, 4, 5]", true); + INVALIDATE(s, "[1, 2, \"3\", 4, 5]", "/items", "type", "/2", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/2\", \"schemaRef\": \"#/items\"," + " \"expected\": [\"number\"], \"actual\": \"string\"" + "}}"); + VALIDATE(s, "[]", true); +} + +TEST(SchemaValidator, Array_ItemsTuple) { + Document sd; + sd.Parse( + "{" + " \"type\": \"array\"," + " \"items\": [" + " {" + " \"type\": \"number\"" + " }," + " {" + " \"type\": \"string\"" + " }," + " {" + " \"type\": \"string\"," + " \"enum\": [\"Street\", \"Avenue\", \"Boulevard\"]" + " }," + " {" + " \"type\": \"string\"," + " \"enum\": [\"NW\", \"NE\", \"SW\", \"SE\"]" + " }" + " ]" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true); + INVALIDATE(s, "[24, \"Sussex\", \"Drive\"]", "/items/2", "enum", "/2", + "{ \"enum\": { \"errorCode\": 19, \"instanceRef\": \"#/2\", \"schemaRef\": \"#/items/2\" }}"); + INVALIDATE(s, "[\"Palais de l'Elysee\"]", "/items/0", "type", "/0", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items/0\"," + " \"expected\": [\"number\"], \"actual\": \"string\"" + "}}"); + INVALIDATE(s, "[\"Twenty-four\", \"Sussex\", \"Drive\"]", "/items/0", "type", "/0", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items/0\"," + " \"expected\": [\"number\"], \"actual\": \"string\"" + "}}"); // fail fast + VALIDATE(s, "[10, \"Downing\", \"Street\"]", true); + VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", true); +} + +TEST(SchemaValidator, Array_AdditionalItems) { + Document sd; + sd.Parse( + "{" + " \"type\": \"array\"," + " \"items\": [" + " {" + " \"type\": \"number\"" + " }," + " {" + " \"type\": \"string\"" + " }," + " {" + " \"type\": \"string\"," + " \"enum\": [\"Street\", \"Avenue\", \"Boulevard\"]" + " }," + " {" + " \"type\": \"string\"," + " \"enum\": [\"NW\", \"NE\", \"SW\", \"SE\"]" + " }" + " ]," + " \"additionalItems\": false" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true); + VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\"]", true); + INVALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", "", "additionalItems", "/4", + "{ \"additionalItems\": {" + " \"errorCode\": 12," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"disallowed\": 4" + "}}"); +} + +TEST(SchemaValidator, Array_ItemsRange) { + Document sd; + sd.Parse("{\"type\": \"array\",\"minItems\": 2,\"maxItems\" : 3}"); + SchemaDocument s(sd); + + INVALIDATE(s, "[]", "", "minItems", "", + "{ \"minItems\": {" + " \"errorCode\": 10," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 2, \"actual\": 0" + "}}"); + INVALIDATE(s, "[1]", "", "minItems", "", + "{ \"minItems\": {" + " \"errorCode\": 10," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 2, \"actual\": 1" + "}}"); + VALIDATE(s, "[1, 2]", true); + VALIDATE(s, "[1, 2, 3]", true); + INVALIDATE(s, "[1, 2, 3, 4]", "", "maxItems", "", + "{ \"maxItems\": {" + " \"errorCode\": 9," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 3, \"actual\": 4" + "}}"); +} + +TEST(SchemaValidator, Array_UniqueItems) { + Document sd; + sd.Parse("{\"type\": \"array\", \"uniqueItems\": true}"); + SchemaDocument s(sd); + + VALIDATE(s, "[1, 2, 3, 4, 5]", true); + INVALIDATE(s, "[1, 2, 3, 3, 4]", "", "uniqueItems", "/3", + "{ \"uniqueItems\": {" + " \"errorCode\": 11," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"duplicates\": [2, 3]" + "}}"); + INVALIDATE(s, "[1, 2, 3, 3, 3]", "", "uniqueItems", "/3", + "{ \"uniqueItems\": {" + " \"errorCode\": 11," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"duplicates\": [2, 3]" + "}}"); // fail fast + VALIDATE(s, "[]", true); +} + +TEST(SchemaValidator, Boolean) { + Document sd; + sd.Parse("{\"type\":\"boolean\"}"); + SchemaDocument s(sd); + + VALIDATE(s, "true", true); + VALIDATE(s, "false", true); + INVALIDATE(s, "\"true\"", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"boolean\"], \"actual\": \"string\"" + "}}"); + INVALIDATE(s, "0", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"boolean\"], \"actual\": \"integer\"" + "}}"); +} + +TEST(SchemaValidator, Null) { + Document sd; + sd.Parse("{\"type\":\"null\"}"); + SchemaDocument s(sd); + + VALIDATE(s, "null", true); + INVALIDATE(s, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"null\"], \"actual\": \"boolean\"" + "}}"); + INVALIDATE(s, "0", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"null\"], \"actual\": \"integer\"" + "}}"); + INVALIDATE(s, "\"\"", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"null\"], \"actual\": \"string\"" + "}}"); +} + +// Additional tests + +TEST(SchemaValidator, ObjectInArray) { + Document sd; + sd.Parse("{\"type\":\"array\", \"items\": { \"type\":\"string\" }}"); + SchemaDocument s(sd); + + VALIDATE(s, "[\"a\"]", true); + INVALIDATE(s, "[1]", "/items", "type", "/0", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items\"," + " \"expected\": [\"string\"], \"actual\": \"integer\"" + "}}"); + INVALIDATE(s, "[{}]", "/items", "type", "/0", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/0\", \"schemaRef\": \"#/items\"," + " \"expected\": [\"string\"], \"actual\": \"object\"" + "}}"); +} + +TEST(SchemaValidator, MultiTypeInObject) { + Document sd; + sd.Parse( + "{" + " \"type\":\"object\"," + " \"properties\": {" + " \"tel\" : {" + " \"type\":[\"integer\", \"string\"]" + " }" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "{ \"tel\": 999 }", true); + VALIDATE(s, "{ \"tel\": \"123-456\" }", true); + INVALIDATE(s, "{ \"tel\": true }", "/properties/tel", "type", "/tel", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/tel\", \"schemaRef\": \"#/properties/tel\"," + " \"expected\": [\"string\", \"integer\"], \"actual\": \"boolean\"" + "}}"); +} + +TEST(SchemaValidator, MultiTypeWithObject) { + Document sd; + sd.Parse( + "{" + " \"type\": [\"object\",\"string\"]," + " \"properties\": {" + " \"tel\" : {" + " \"type\": \"integer\"" + " }" + " }" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "\"Hello\"", true); + VALIDATE(s, "{ \"tel\": 999 }", true); + INVALIDATE(s, "{ \"tel\": \"fail\" }", "/properties/tel", "type", "/tel", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/tel\", \"schemaRef\": \"#/properties/tel\"," + " \"expected\": [\"integer\"], \"actual\": \"string\"" + "}}"); +} + +TEST(SchemaValidator, AllOf_Nested) { + Document sd; + sd.Parse( + "{" + " \"allOf\": [" + " { \"type\": \"string\", \"minLength\": 2 }," + " { \"type\": \"string\", \"maxLength\": 5 }," + " { \"allOf\": [ { \"enum\" : [\"ok\", \"okay\", \"OK\", \"o\"] }, { \"enum\" : [\"ok\", \"OK\", \"o\"]} ] }" + " ]" + "}"); + SchemaDocument s(sd); + + VALIDATE(s, "\"ok\"", true); + VALIDATE(s, "\"OK\"", true); + INVALIDATE(s, "\"okay\"", "", "allOf", "", + "{ \"allOf\": {" + " \"errors\": [" + " {},{}," + " { \"allOf\": {" + " \"errors\": [" + " {}," + " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\" }}" + " ]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\"" + " }}]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + "}}"); + INVALIDATE(s, "\"o\"", "", "allOf", "", + "{ \"allOf\": {" + " \"errors\": [" + " { \"minLength\": {\"actual\": \"o\", \"expected\": 2, \"errorCode\": 7, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\" }}," + " {},{}" + " ]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + "}}"); + INVALIDATE(s, "\"n\"", "", "allOf", "", + "{ \"allOf\": {" + " \"errors\": [" + " { \"minLength\": {\"actual\": \"n\", \"expected\": 2, \"errorCode\": 7, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\" }}," + " {}," + " { \"allOf\": {" + " \"errors\": [" + " { \"enum\": {\"errorCode\": 19 ,\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"}}," + " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}}" + " ]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\"" + " }}" + " ]," + " \"errorCode\":23,\"instanceRef\":\"#\",\"schemaRef\":\"#\"" + "}}"); + INVALIDATE(s, "\"too long\"", "", "allOf", "", + "{ \"allOf\": {" + " \"errors\": [" + " {}," + " { \"maxLength\": {\"actual\": \"too long\", \"expected\": 5, \"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\" }}," + " { \"allOf\": {" + " \"errors\": [" + " { \"enum\": {\"errorCode\": 19 ,\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"}}," + " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}}" + " ]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\"" + " }}" + " ]," + " \"errorCode\":23,\"instanceRef\":\"#\",\"schemaRef\":\"#\"" + "}}"); + INVALIDATE(s, "123", "", "allOf", "", + "{ \"allOf\": {" + " \"errors\": [" + " {\"type\": {\"expected\": [\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/0\"}}," + " {\"type\": {\"expected\": [\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/1\"}}," + " { \"allOf\": {" + " \"errors\": [" + " { \"enum\": {\"errorCode\": 19 ,\"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/0\"}}," + " { \"enum\": {\"errorCode\": 19, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2/allOf/1\"}}" + " ]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#/allOf/2\"" + " }}" + " ]," + " \"errorCode\":23,\"instanceRef\":\"#\",\"schemaRef\":\"#\"" + "}}"); +} + +TEST(SchemaValidator, EscapedPointer) { + Document sd; + sd.Parse( + "{" + " \"type\": \"object\"," + " \"properties\": {" + " \"~/\": { \"type\": \"number\" }" + " }" + "}"); + SchemaDocument s(sd); + INVALIDATE(s, "{\"~/\":true}", "/properties/~0~1", "type", "/~0~1", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/~0~1\", \"schemaRef\": \"#/properties/~0~1\"," + " \"expected\": [\"number\"], \"actual\": \"boolean\"" + "}}"); +} + +TEST(SchemaValidator, SchemaPointer) { + Document sd; + sd.Parse( + "{" + " \"swagger\": \"2.0\"," + " \"paths\": {" + " \"/some/path\": {" + " \"post\": {" + " \"parameters\": [" + " {" + " \"in\": \"body\"," + " \"name\": \"body\"," + " \"schema\": {" + " \"properties\": {" + " \"a\": {" + " \"$ref\": \"#/definitions/Prop_a\"" + " }," + " \"b\": {" + " \"type\": \"integer\"" + " }" + " }," + " \"type\": \"object\"" + " }" + " }" + " ]," + " \"responses\": {" + " \"200\": {" + " \"schema\": {" + " \"$ref\": \"#/definitions/Resp_200\"" + " }" + " }" + " }" + " }" + " }" + " }," + " \"definitions\": {" + " \"Prop_a\": {" + " \"properties\": {" + " \"c\": {" + " \"enum\": [" + " \"C1\"," + " \"C2\"," + " \"C3\"" + " ]," + " \"type\": \"string\"" + " }," + " \"d\": {" + " \"$ref\": \"#/definitions/Prop_d\"" + " }," + " \"s\": {" + " \"type\": \"string\"" + " }" + " }," + " \"required\": [\"c\"]," + " \"type\": \"object\"" + " }," + " \"Prop_d\": {" + " \"properties\": {" + " \"a\": {" + " \"$ref\": \"#/definitions/Prop_a\"" + " }," + " \"c\": {" + " \"$ref\": \"#/definitions/Prop_a/properties/c\"" + " }" + " }," + " \"type\": \"object\"" + " }," + " \"Resp_200\": {" + " \"properties\": {" + " \"e\": {" + " \"type\": \"string\"" + " }," + " \"f\": {" + " \"type\": \"boolean\"" + " }" + " }," + " \"type\": \"object\"" + " }" + " }" + "}"); + SchemaDocument s1(sd, NULL, 0, NULL, NULL, Pointer("#/paths/~1some~1path/post/parameters/0/schema")); + VALIDATE(s1, + "{" + " \"a\": {" + " \"c\": \"C1\"," + " \"d\": {" + " \"a\": {" + " \"c\": \"C2\"" + " }," + " \"c\": \"C3\"" + " }" + " }," + " \"b\": 123" + "}", + true); + INVALIDATE(s1, + "{" + " \"a\": {" + " \"c\": \"C1\"," + " \"d\": {" + " \"a\": {" + " \"c\": \"C2\"" + " }," + " \"c\": \"C3\"" + " }" + " }," + " \"b\": \"should be an int\"" + "}", + "#/paths/~1some~1path/post/parameters/0/schema/properties/b", "type", "#/b", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\":\"#/b\"," + " \"schemaRef\":\"#/paths/~1some~1path/post/parameters/0/schema/properties/b\"," + " \"expected\": [\"integer\"], \"actual\":\"string\"" + "}}"); + INVALIDATE(s1, + "{" + " \"a\": {" + " \"c\": \"C1\"," + " \"d\": {" + " \"a\": {" + " \"c\": \"should be within enum\"" + " }," + " \"c\": \"C3\"" + " }" + " }," + " \"b\": 123" + "}", + "#/definitions/Prop_a/properties/c", "enum", "#/a/d/a/c", + "{ \"enum\": {" + " \"errorCode\": 19," + " \"instanceRef\":\"#/a/d/a/c\"," + " \"schemaRef\":\"#/definitions/Prop_a/properties/c\"" + "}}"); + INVALIDATE(s1, + "{" + " \"a\": {" + " \"c\": \"C1\"," + " \"d\": {" + " \"a\": {" + " \"s\": \"required 'c' is missing\"" + " }" + " }" + " }," + " \"b\": 123" + "}", + "#/definitions/Prop_a", "required", "#/a/d/a", + "{ \"required\": {" + " \"errorCode\": 15," + " \"missing\":[\"c\"]," + " \"instanceRef\":\"#/a/d/a\"," + " \"schemaRef\":\"#/definitions/Prop_a\"" + "}}"); + SchemaDocument s2(sd, NULL, 0, NULL, NULL, Pointer("#/paths/~1some~1path/post/responses/200/schema")); + VALIDATE(s2, + "{ \"e\": \"some string\", \"f\": false }", + true); + INVALIDATE(s2, + "{ \"e\": true, \"f\": false }", + "#/definitions/Resp_200/properties/e", "type", "#/e", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\":\"#/e\"," + " \"schemaRef\":\"#/definitions/Resp_200/properties/e\"," + " \"expected\": [\"string\"], \"actual\":\"boolean\"" + "}}"); + INVALIDATE(s2, + "{ \"e\": \"some string\", \"f\": 123 }", + "#/definitions/Resp_200/properties/f", "type", "#/f", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\":\"#/f\"," + " \"schemaRef\":\"#/definitions/Resp_200/properties/f\"," + " \"expected\": [\"boolean\"], \"actual\":\"integer\"" + "}}"); +} + +template +static char* ReadFile(const char* filename, Allocator& allocator) { + const char *paths[] = { + "", + "bin/", + "../bin/", + "../../bin/", + "../../../bin/" + }; + char buffer[1024]; + FILE *fp = 0; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + sprintf(buffer, "%s%s", paths[i], filename); + fp = fopen(buffer, "rb"); + if (fp) + break; + } + + if (!fp) + return 0; + + fseek(fp, 0, SEEK_END); + size_t length = static_cast(ftell(fp)); + fseek(fp, 0, SEEK_SET); + char* json = reinterpret_cast(allocator.Malloc(length + 1)); + size_t readLength = fread(json, 1, length, fp); + json[readLength] = '\0'; + fclose(fp); + return json; +} + +TEST(SchemaValidator, ValidateMetaSchema) { + CrtAllocator allocator; + char* json = ReadFile("draft-04/schema", allocator); + Document d; + d.Parse(json); + ASSERT_FALSE(d.HasParseError()); + SchemaDocument sd(d); + SchemaValidator validator(sd); + d.Accept(validator); + if (!validator.IsValid()) { + StringBuffer sb; + validator.GetInvalidSchemaPointer().StringifyUriFragment(sb); + printf("Invalid schema: %s\n", sb.GetString()); + printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword()); + printf("Invalid code: %d\n", validator.GetInvalidSchemaCode()); + printf("Invalid message: %s\n", GetValidateError_En(validator.GetInvalidSchemaCode())); + sb.Clear(); + validator.GetInvalidDocumentPointer().StringifyUriFragment(sb); + printf("Invalid document: %s\n", sb.GetString()); + sb.Clear(); + Writer w(sb); + validator.GetError().Accept(w); + printf("Validation error: %s\n", sb.GetString()); + ADD_FAILURE(); + } + CrtAllocator::Free(json); +} + +TEST(SchemaValidator, ValidateMetaSchema_UTF16) { + typedef GenericDocument > D; + typedef GenericSchemaDocument SD; + typedef GenericSchemaValidator SV; + + CrtAllocator allocator; + char* json = ReadFile("draft-04/schema", allocator); + + D d; + StringStream ss(json); + d.ParseStream<0, UTF8<> >(ss); + ASSERT_FALSE(d.HasParseError()); + SD sd(d); + SV validator(sd); + d.Accept(validator); + if (!validator.IsValid()) { + GenericStringBuffer > sb; + validator.GetInvalidSchemaPointer().StringifyUriFragment(sb); + wprintf(L"Invalid schema: %ls\n", sb.GetString()); + wprintf(L"Invalid keyword: %ls\n", validator.GetInvalidSchemaKeyword()); + sb.Clear(); + validator.GetInvalidDocumentPointer().StringifyUriFragment(sb); + wprintf(L"Invalid document: %ls\n", sb.GetString()); + sb.Clear(); + Writer >, UTF16<> > w(sb); + validator.GetError().Accept(w); + printf("Validation error: %ls\n", sb.GetString()); + ADD_FAILURE(); + } + CrtAllocator::Free(json); +} + +template +class RemoteSchemaDocumentProvider : public IGenericRemoteSchemaDocumentProvider { +public: + RemoteSchemaDocumentProvider() : + documentAllocator_(documentBuffer_, sizeof(documentBuffer_)), + schemaAllocator_(schemaBuffer_, sizeof(schemaBuffer_)) + { + const char* filenames[kCount] = { + "jsonschema/remotes/integer.json", + "jsonschema/remotes/subSchemas.json", + "jsonschema/remotes/folder/folderInteger.json", + "draft-04/schema", + "unittestschema/address.json" + }; + const char* uris[kCount] = { + "http://localhost:1234/integer.json", + "http://localhost:1234/subSchemas.json", + "http://localhost:1234/folder/folderInteger.json", + "http://json-schema.org/draft-04/schema", + "http://localhost:1234/address.json" + }; + + for (size_t i = 0; i < kCount; i++) { + sd_[i] = 0; + + char jsonBuffer[8192]; + MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer)); + char* json = ReadFile(filenames[i], jsonAllocator); + if (!json) { + printf("json remote file %s not found", filenames[i]); + ADD_FAILURE(); + } + else { + char stackBuffer[4096]; + MemoryPoolAllocator<> stackAllocator(stackBuffer, sizeof(stackBuffer)); + DocumentType d(&documentAllocator_, 1024, &stackAllocator); + d.Parse(json); + sd_[i] = new SchemaDocumentType(d, uris[i], static_cast(strlen(uris[i])), 0, &schemaAllocator_); + MemoryPoolAllocator<>::Free(json); + } + }; + } + + ~RemoteSchemaDocumentProvider() { + for (size_t i = 0; i < kCount; i++) + delete sd_[i]; + } + + virtual const SchemaDocumentType* GetRemoteDocument(const char* uri, SizeType length) { + //printf("GetRemoteDocument : %s\n", uri); + for (size_t i = 0; i < kCount; i++) + if (typename SchemaDocumentType::GValue(uri, length) == sd_[i]->GetURI()) { + //printf("Matched document"); + return sd_[i]; + } + //printf("No matched document"); + return 0; + } + +private: + typedef GenericDocument, MemoryPoolAllocator<> > DocumentType; + + RemoteSchemaDocumentProvider(const RemoteSchemaDocumentProvider&); + RemoteSchemaDocumentProvider& operator=(const RemoteSchemaDocumentProvider&); + + static const size_t kCount = 5; + SchemaDocumentType* sd_[kCount]; + typename DocumentType::AllocatorType documentAllocator_; + typename SchemaDocumentType::AllocatorType schemaAllocator_; + char documentBuffer_[16384]; + char schemaBuffer_[128u * 1024]; +}; + +TEST(SchemaValidator, TestSuite) { + const char* filenames[] = { + "additionalItems.json", + "additionalProperties.json", + "allOf.json", + "anyOf.json", + "default.json", + "definitions.json", + "dependencies.json", + "enum.json", + "items.json", + "maximum.json", + "maxItems.json", + "maxLength.json", + "maxProperties.json", + "minimum.json", + "minItems.json", + "minLength.json", + "minProperties.json", + "multipleOf.json", + "not.json", + "oneOf.json", + "pattern.json", + "patternProperties.json", + "properties.json", + "ref.json", + "refRemote.json", + "required.json", + "type.json", + "uniqueItems.json" + }; + + const char* onlyRunDescription = 0; + //const char* onlyRunDescription = "a string is a string"; + + unsigned testCount = 0; + unsigned passCount = 0; + + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + + char jsonBuffer[65536]; + char documentBuffer[65536]; + char documentStackBuffer[65536]; + char schemaBuffer[65536]; + char validatorBuffer[65536]; + MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer)); + MemoryPoolAllocator<> documentAllocator(documentBuffer, sizeof(documentBuffer)); + MemoryPoolAllocator<> documentStackAllocator(documentStackBuffer, sizeof(documentStackBuffer)); + MemoryPoolAllocator<> schemaAllocator(schemaBuffer, sizeof(schemaBuffer)); + MemoryPoolAllocator<> validatorAllocator(validatorBuffer, sizeof(validatorBuffer)); + + for (size_t i = 0; i < sizeof(filenames) / sizeof(filenames[0]); i++) { + char filename[FILENAME_MAX]; + sprintf(filename, "jsonschema/tests/draft4/%s", filenames[i]); + char* json = ReadFile(filename, jsonAllocator); + if (!json) { + printf("json test suite file %s not found", filename); + ADD_FAILURE(); + } + else { + //printf("\njson test suite file %s parsed ok\n", filename); + GenericDocument, MemoryPoolAllocator<>, MemoryPoolAllocator<> > d(&documentAllocator, 1024, &documentStackAllocator); + d.Parse(json); + if (d.HasParseError()) { + printf("json test suite file %s has parse error", filename); + ADD_FAILURE(); + } + else { + for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) { + { + const char* description1 = (*schemaItr)["description"].GetString(); + //printf("\ncompiling schema for json test %s \n", description1); + SchemaDocumentType schema((*schemaItr)["schema"], filenames[i], static_cast(strlen(filenames[i])), &provider, &schemaAllocator); + GenericSchemaValidator >, MemoryPoolAllocator<> > validator(schema, &validatorAllocator); + const Value& tests = (*schemaItr)["tests"]; + for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) { + const char* description2 = (*testItr)["description"].GetString(); + //printf("running json test %s \n", description2); + if (!onlyRunDescription || strcmp(description2, onlyRunDescription) == 0) { + const Value& data = (*testItr)["data"]; + bool expected = (*testItr)["valid"].GetBool(); + testCount++; + validator.Reset(); + data.Accept(validator); + bool actual = validator.IsValid(); + if (expected != actual) + printf("Fail: %30s \"%s\" \"%s\"\n", filename, description1, description2); + else { + //printf("Passed: %30s \"%s\" \"%s\"\n", filename, description1, description2); + passCount++; + } + } + } + //printf("%zu %zu %zu\n", documentAllocator.Size(), schemaAllocator.Size(), validatorAllocator.Size()); + } + schemaAllocator.Clear(); + validatorAllocator.Clear(); + } + } + } + documentAllocator.Clear(); + MemoryPoolAllocator<>::Free(json); + jsonAllocator.Clear(); + } + printf("%d / %d passed (%2d%%)\n", passCount, testCount, passCount * 100 / testCount); + if (passCount != testCount) + ADD_FAILURE(); +} + +TEST(SchemaValidatingReader, Simple) { + Document sd; + sd.Parse("{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }"); + SchemaDocument s(sd); + + Document d; + StringStream ss("\"red\""); + SchemaValidatingReader > reader(ss, s); + d.Populate(reader); + EXPECT_TRUE(reader.GetParseResult()); + EXPECT_TRUE(reader.IsValid()); + EXPECT_TRUE(d.IsString()); + EXPECT_STREQ("red", d.GetString()); +} + +TEST(SchemaValidatingReader, Invalid) { + Document sd; + sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}"); + SchemaDocument s(sd); + + Document d; + StringStream ss("\"ABCD\""); + SchemaValidatingReader > reader(ss, s); + d.Populate(reader); + EXPECT_FALSE(reader.GetParseResult()); + EXPECT_FALSE(reader.IsValid()); + EXPECT_EQ(kParseErrorTermination, reader.GetParseResult().Code()); + EXPECT_STREQ("maxLength", reader.GetInvalidSchemaKeyword()); + EXPECT_TRUE(reader.GetInvalidSchemaCode() == kValidateErrorMaxLength); + EXPECT_TRUE(reader.GetInvalidSchemaPointer() == SchemaDocument::PointerType("")); + EXPECT_TRUE(reader.GetInvalidDocumentPointer() == SchemaDocument::PointerType("")); + EXPECT_TRUE(d.IsNull()); + Document e; + e.Parse( + "{ \"maxLength\": {" + " \"errorCode\": 6," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 3, \"actual\": \"ABCD\"" + "}}"); + if (e != reader.GetError()) { + ADD_FAILURE(); + } +} + +TEST(SchemaValidatingWriter, Simple) { + Document sd; + sd.Parse("{\"type\":\"string\",\"minLength\":2,\"maxLength\":3}"); + SchemaDocument s(sd); + + Document d; + StringBuffer sb; + Writer writer(sb); + GenericSchemaValidator > validator(s, writer); + + d.Parse("\"red\""); + EXPECT_TRUE(d.Accept(validator)); + EXPECT_TRUE(validator.IsValid()); + EXPECT_STREQ("\"red\"", sb.GetString()); + + sb.Clear(); + validator.Reset(); + d.Parse("\"ABCD\""); + EXPECT_FALSE(d.Accept(validator)); + EXPECT_FALSE(validator.IsValid()); + EXPECT_TRUE(validator.GetInvalidSchemaPointer() == SchemaDocument::PointerType("")); + EXPECT_TRUE(validator.GetInvalidDocumentPointer() == SchemaDocument::PointerType("")); + EXPECT_TRUE(validator.GetInvalidSchemaCode() == kValidateErrorMaxLength); + Document e; + e.Parse( + "{ \"maxLength\": {" +" \"errorCode\": 6," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": 3, \"actual\": \"ABCD\"" + "}}"); + EXPECT_EQ(e, validator.GetError()); +} + +TEST(Schema, Issue848) { + rapidjson::Document d; + rapidjson::SchemaDocument s(d); + rapidjson::GenericSchemaValidator v(s); +} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + +static SchemaDocument ReturnSchemaDocument() { + Document sd; + sd.Parse("{ \"type\": [\"number\", \"string\"] }"); + SchemaDocument s(sd); + return s; +} + +TEST(Schema, Issue552) { + SchemaDocument s = ReturnSchemaDocument(); + VALIDATE(s, "42", true); + VALIDATE(s, "\"Life, the universe, and everything\"", true); + INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\", \"number\"], \"actual\": \"array\"" + "}}"); +} + +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +TEST(SchemaValidator, Issue608) { + Document sd; + sd.Parse("{\"required\": [\"a\", \"b\"] }"); + SchemaDocument s(sd); + + VALIDATE(s, "{\"a\" : null, \"b\": null}", true); + INVALIDATE(s, "{\"a\" : null, \"a\" : null}", "", "required", "", + "{ \"required\": {" + " \"errorCode\": 15," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"missing\": [\"b\"]" + "}}"); +} + +// Fail to resolve $ref in allOf causes crash in SchemaValidator::StartObject() +TEST(SchemaValidator, Issue728_AllOfRef) { + Document sd; + sd.Parse("{\"allOf\": [{\"$ref\": \"#/abc\"}]}"); + SchemaDocument s(sd); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/allOf/0\",\"value\":\"#/abc\"}}"); + + VALIDATE_(s, "{\"key1\": \"abc\", \"key2\": \"def\"}", true, false); +} + +TEST(SchemaValidator, Issue1017_allOfHandler) { + Document sd; + sd.Parse("{\"allOf\": [{\"type\": \"object\",\"properties\": {\"cyanArray2\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}}},{\"type\": \"object\",\"properties\": {\"blackArray\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}},\"required\": [ \"blackArray\" ]}]}"); + SchemaDocument s(sd); + StringBuffer sb; + Writer writer(sb); + GenericSchemaValidator > validator(s, writer); + EXPECT_TRUE(validator.StartObject()); + EXPECT_TRUE(validator.Key("cyanArray2", 10, false)); + EXPECT_TRUE(validator.StartArray()); + EXPECT_TRUE(validator.EndArray(0)); + EXPECT_TRUE(validator.Key("blackArray", 10, false)); + EXPECT_TRUE(validator.StartArray()); + EXPECT_TRUE(validator.EndArray(0)); + EXPECT_TRUE(validator.EndObject(0)); + EXPECT_TRUE(validator.IsValid()); + EXPECT_STREQ("{\"cyanArray2\":[],\"blackArray\":[]}", sb.GetString()); +} + +TEST(SchemaValidator, Ref_remote) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"$ref\": \"http://localhost:1234/subSchemas.json#/integer\"}"); + SchemaDocumentType s(sd, 0, 0, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "null", "/integer", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\"," + " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// Merge with id where $ref is full URI +TEST(SchemaValidator, Ref_remote_change_resolution_scope_uri) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"id\": \"http://ignore/blah#/ref\", \"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"http://localhost:1234/subSchemas.json#/integer\"}}}"); + SchemaDocumentType s(sd, 0, 0, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt\"," + " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// Merge with id where $ref is a relative path +TEST(SchemaValidator, Ref_remote_change_resolution_scope_relative_path) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"id\": \"http://localhost:1234/\", \"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"subSchemas.json#/integer\"}}}"); + SchemaDocumentType s(sd, 0, 0, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt\"," + " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// Merge with id where $ref is an absolute path +TEST(SchemaValidator, Ref_remote_change_resolution_scope_absolute_path) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"id\": \"http://localhost:1234/xxxx\", \"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/integer\"}}}"); + SchemaDocumentType s(sd, 0, 0, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt\"," + " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// Merge with id where $ref is an absolute path, and the document has a base URI +TEST(SchemaValidator, Ref_remote_change_resolution_scope_absolute_path_document) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/integer\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"myInt\": null}", "/integer", "type", "/myInt", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt\"," + " \"schemaRef\": \"http://localhost:1234/subSchemas.json#/integer\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// $ref is a non-JSON pointer fragment and there a matching id +TEST(SchemaValidator, Ref_internal_id_1) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myStr\": {\"type\": \"string\", \"id\": \"#myStrId\"}, \"myInt2\": {\"type\": \"integer\", \"id\": \"#myId\"}}}"); + SchemaDocumentType s(sd); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"myInt1\": null}", "/properties/myInt2", "type", "/myInt1", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt1\"," + " \"schemaRef\": \"#/properties/myInt2\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// $ref is a non-JSON pointer fragment and there are two matching ids so we take the first +TEST(SchemaValidator, Ref_internal_id_2) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myInt2\": {\"type\": \"integer\", \"id\": \"#myId\"}, \"myStr\": {\"type\": \"string\", \"id\": \"#myId\"}}}"); + SchemaDocumentType s(sd); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"myInt1\": null}", "/properties/myInt2", "type", "/myInt1", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt1\"," + " \"schemaRef\": \"#/properties/myInt2\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// $ref is a non-JSON pointer fragment and there is a matching id within array +TEST(SchemaValidator, Ref_internal_id_in_array) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myInt2\": {\"anyOf\": [{\"type\": \"string\", \"id\": \"#myStrId\"}, {\"type\": \"integer\", \"id\": \"#myId\"}]}}}"); + SchemaDocumentType s(sd); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"myInt1\": null}", "/properties/myInt2/anyOf/1", "type", "/myInt1", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt1\"," + " \"schemaRef\": \"#/properties/myInt2/anyOf/1\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// $ref is a non-JSON pointer fragment and there is a matching id, and the schema is embedded in the document +TEST(SchemaValidator, Ref_internal_id_and_schema_pointer) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{ \"schema\": {\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myInt2\": {\"anyOf\": [{\"type\": \"integer\", \"id\": \"#myId\"}]}}}}"); + typedef GenericPointer > PointerType; + SchemaDocumentType s(sd, 0, 0, 0, 0, PointerType("/schema")); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + INVALIDATE_(s, "{\"myInt1\": null}", "/schema/properties/myInt2/anyOf/0", "type", "/myInt1", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#/myInt1\"," + " \"schemaRef\": \"#/schema/properties/myInt2/anyOf/0\"," + " \"expected\": [\"integer\"], \"actual\": \"null\"" + "}}", + kValidateDefaultFlags, SchemaValidatorType, PointerType); +} + +// Test that $refs are correctly resolved when intermediate multiple ids are present +// Includes $ref to a part of the document with a different in-scope id, which also contains $ref.. +TEST(SchemaValidator, Ref_internal_multiple_ids) { + typedef GenericSchemaDocument > SchemaDocumentType; + //RemoteSchemaDocumentProvider provider; + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/idandref.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocumentType s(sd, "http://xyz", 10/*, &provider*/); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"PA1\": \"s\", \"PA2\": \"t\", \"PA3\": \"r\", \"PX1\": 1, \"PX2Y\": 2, \"PX3Z\": 3, \"PX4\": 4, \"PX5\": 5, \"PX6\": 6, \"PX7W\": 7, \"PX8N\": { \"NX\": 8}}", "#", "errors", "#", + "{ \"type\": [" + " {\"errorCode\": 20, \"instanceRef\": \"#/PA1\", \"schemaRef\": \"http://xyz#/definitions/A\", \"expected\": [\"integer\"], \"actual\": \"string\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PA2\", \"schemaRef\": \"http://xyz#/definitions/A\", \"expected\": [\"integer\"], \"actual\": \"string\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PA3\", \"schemaRef\": \"http://xyz#/definitions/A\", \"expected\": [\"integer\"], \"actual\": \"string\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX1\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX2Y\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX3Z\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX4\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX5\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX6\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX7W\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}," + " {\"errorCode\": 20, \"instanceRef\": \"#/PX8N/NX\", \"schemaRef\": \"http://xyz#/definitions/B/definitions/X\", \"expected\": [\"boolean\"], \"actual\": \"integer\"}" + "]}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType); + CrtAllocator::Free(schema); +} + +TEST(SchemaValidator, Ref_remote_issue1210) { + class SchemaDocumentProvider : public IRemoteSchemaDocumentProvider { + SchemaDocument** collection; + + // Dummy private copy constructor & assignment operator. + // Function bodies added so that they compile in MSVC 2019. + SchemaDocumentProvider(const SchemaDocumentProvider&) : collection(NULL) { + } + SchemaDocumentProvider& operator=(const SchemaDocumentProvider&) { + return *this; + } + + public: + SchemaDocumentProvider(SchemaDocument** collection) : collection(collection) { } + virtual const SchemaDocument* GetRemoteDocument(const char* uri, SizeType length) { + int i = 0; + while (collection[i] && SchemaDocument::GValue(uri, length) != collection[i]->GetURI()) ++i; + return collection[i]; + } + }; + SchemaDocument* collection[] = { 0, 0, 0 }; + SchemaDocumentProvider provider(collection); + + Document x, y, z; + x.Parse("{\"properties\":{\"country\":{\"$ref\":\"y.json#/definitions/country_remote\"}},\"type\":\"object\"}"); + y.Parse("{\"definitions\":{\"country_remote\":{\"$ref\":\"z.json#/definitions/country_list\"}}}"); + z.Parse("{\"definitions\":{\"country_list\":{\"enum\":[\"US\"]}}}"); + + SchemaDocument sz(z, "z.json", 6, &provider); + collection[0] = &sz; + SchemaDocument sy(y, "y.json", 6, &provider); + collection[1] = &sy; + SchemaDocument sx(x, "x.json", 6, &provider); + + VALIDATE(sx, "{\"country\":\"UK\"}", false); + VALIDATE(sx, "{\"country\":\"US\"}", true); +} + +// Test that when kValidateContinueOnErrorFlag is set, all errors are reported. +TEST(SchemaValidator, ContinueOnErrors) { + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + VALIDATE(s, "{\"version\": 1.0, \"address\": {\"number\": 24, \"street1\": \"The Woodlands\", \"street3\": \"Ham\", \"city\": \"Romsey\", \"area\": \"Kent\", \"country\": \"UK\", \"postcode\": \"SO51 0GP\"}, \"phones\": [\"0111-222333\", \"0777-666888\"], \"names\": [\"Fred\", \"Bloggs\"]}", true); + INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"Narnia\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#", + "{ \"multipleOf\": {" + " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01" + " }," + " \"minimum\": {" + " \"errorCode\": 5, \"instanceRef\": \"#/address/number\", \"schemaRef\": \"#/definitions/positiveInt_type\", \"expected\": 0, \"actual\": 0, \"exclusiveMinimum\": true" + " }," + " \"type\": [" + " {\"expected\": [\"null\", \"string\"], \"actual\": \"boolean\", \"errorCode\": 20, \"instanceRef\": \"#/address/street2\", \"schemaRef\": \"#/definitions/address_type/properties/street2\"}," + " {\"expected\": [\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#/extra/S_xxx\", \"schemaRef\": \"#/properties/extra/patternProperties/%5ES_\"}" + " ]," + " \"maxLength\": {" + " \"actual\": \"RomseyTownFC\", \"expected\": 10, \"errorCode\": 6, \"instanceRef\": \"#/address/city\", \"schemaRef\": \"#/definitions/address_type/properties/city\"" + " }," + " \"anyOf\": {" + " \"errors\":[" + " {\"pattern\": {\"actual\": \"999ABC\", \"errorCode\": 8, \"instanceRef\": \"#/address/postcode\", \"schemaRef\": \"#/definitions/address_type/properties/postcode/anyOf/0\"}}," + " {\"pattern\": {\"actual\": \"999ABC\", \"errorCode\": 8, \"instanceRef\": \"#/address/postcode\", \"schemaRef\": \"#/definitions/address_type/properties/postcode/anyOf/1\"}}" + " ]," + " \"errorCode\": 24, \"instanceRef\": \"#/address/postcode\", \"schemaRef\": \"#/definitions/address_type/properties/postcode\"" + " }," + " \"allOf\": {" + " \"errors\":[" + " {\"enum\":{\"errorCode\":19,\"instanceRef\":\"#/address/country\",\"schemaRef\":\"#/definitions/country_type\"}}" + " ]," + " \"errorCode\":23,\"instanceRef\":\"#/address/country\",\"schemaRef\":\"#/definitions/address_type/properties/country\"" + " }," + " \"minItems\": {" + " \"actual\": 0, \"expected\": 1, \"errorCode\": 10, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"" + " }," + " \"additionalProperties\": {" + " \"disallowed\": \"planet\", \"errorCode\": 16, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + " }," + " \"required\": {" + " \"missing\": [\"street1\"], \"errorCode\": 15, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\"" + " }," + " \"oneOf\": {" + " \"matches\": [0, 1], \"errorCode\": 22, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/address_type/properties/area\"" + " }" + "}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + INVALIDATE_(s, "{\"address\": {\"number\": 200, \"street1\": {}, \"street3\": null, \"city\": \"Rom\", \"area\": \"Dorset\", \"postcode\": \"SO51 0GP\"}, \"phones\": [\"0111-222333\", \"0777-666888\", \"0777-666888\"], \"names\": [\"Fred\", \"S\", \"M\", \"Bloggs\"]}", "#", "errors", "#", + "{ \"maximum\": {" + " \"errorCode\": 3, \"instanceRef\": \"#/address/number\", \"schemaRef\": \"#/definitions/positiveInt_type\", \"expected\": 100, \"actual\": 200, \"exclusiveMaximum\": true" + " }," + " \"type\": {" + " \"expected\": [\"string\"], \"actual\": \"object\", \"errorCode\": 20, \"instanceRef\": \"#/address/street1\", \"schemaRef\": \"#/definitions/address_type/properties/street1\"" + " }," + " \"not\": {" + " \"errorCode\": 25, \"instanceRef\": \"#/address/street3\", \"schemaRef\": \"#/definitions/address_type/properties/street3\"" + " }," + " \"minLength\": {" + " \"actual\": \"Rom\", \"expected\": 4, \"errorCode\": 7, \"instanceRef\": \"#/address/city\", \"schemaRef\": \"#/definitions/address_type/properties/city\"" + " }," + " \"maxItems\": {" + " \"actual\": 3, \"expected\": 2, \"errorCode\": 9, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"" + " }," + " \"uniqueItems\": {" + " \"duplicates\": [1, 2], \"errorCode\": 11, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"" + " }," + " \"minProperties\": {\"actual\": 6, \"expected\": 7, \"errorCode\": 14, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\"" + " }," + " \"additionalItems\": [" + " {\"disallowed\": 2, \"errorCode\": 12, \"instanceRef\": \"#/names\", \"schemaRef\": \"#/properties/names\"}," + " {\"disallowed\": 3, \"errorCode\": 12, \"instanceRef\": \"#/names\", \"schemaRef\": \"#/properties/names\"}" + " ]," + " \"dependencies\": {" + " \"errors\": {" + " \"address\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/address\"}}," + " \"names\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/names\"}}" + " }," + " \"errorCode\": 18, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + " }," + " \"oneOf\": {" + " \"errors\": [" + " {\"enum\": {\"errorCode\": 19, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/county_type\"}}," + " {\"enum\": {\"errorCode\": 19, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/province_type\"}}" + " ]," + " \"errorCode\": 21, \"instanceRef\": \"#/address/area\", \"schemaRef\": \"#/definitions/address_type/properties/area\"" + " }" + "}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, it is not propagated to oneOf sub-validator so we only get the first error. +TEST(SchemaValidator, ContinueOnErrors_OneOf) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/oneOf_address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocumentType s(sd, 0, 0, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#", + "{ \"oneOf\": {" + " \"errors\": [{" + " \"multipleOf\": {" + " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"http://localhost:1234/address.json#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01" + " }" + " }]," + " \"errorCode\": 21, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + " }" + "}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType); + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, it is not propagated to allOf sub-validator so we only get the first error. +TEST(SchemaValidator, ContinueOnErrors_AllOf) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/allOf_address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocumentType s(sd, 0, 0, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#", + "{ \"allOf\": {" + " \"errors\": [{" + " \"multipleOf\": {" + " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"http://localhost:1234/address.json#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01" + " }" + " }]," + " \"errorCode\": 23, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + " }" + "}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType); + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, it is not propagated to anyOf sub-validator so we only get the first error. +TEST(SchemaValidator, ContinueOnErrors_AnyOf) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/anyOf_address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocumentType s(sd, 0, 0, &provider); + typedef GenericSchemaValidator >, MemoryPoolAllocator<> > SchemaValidatorType; + typedef GenericPointer > PointerType; + INVALIDATE_(s, "{\"version\": 1.01, \"address\": {\"number\": 0, \"street2\": false, \"street3\": \"Ham\", \"city\": \"RomseyTownFC\", \"area\": \"BC\", \"country\": \"USA\", \"postcode\": \"999ABC\"}, \"phones\": [], \"planet\": \"Earth\", \"extra\": {\"S_xxx\": 123}}", "#", "errors", "#", + "{ \"anyOf\": {" + " \"errors\": [{" + " \"multipleOf\": {" + " \"errorCode\": 1, \"instanceRef\": \"#/version\", \"schemaRef\": \"http://localhost:1234/address.json#/definitions/decimal_type\", \"expected\": 1.0, \"actual\": 1.01" + " }" + " }]," + " \"errorCode\": 24, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + " }" + "}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidatorType, PointerType); + + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, arrays with uniqueItems:true are correctly processed when an item is invalid. +// This tests that we don't blow up if a hasher does not get created. +TEST(SchemaValidator, ContinueOnErrors_UniqueItems) { + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + VALIDATE(s, "{\"phones\":[\"12-34\",\"56-78\"]}", true); + INVALIDATE_(s, "{\"phones\":[\"12-34\",\"12-34\"]}", "#", "errors", "#", + "{\"uniqueItems\": {\"duplicates\": [0,1], \"errorCode\": 11, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"}}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + INVALIDATE_(s, "{\"phones\":[\"ab-34\",\"cd-78\"]}", "#", "errors", "#", + "{\"pattern\": [" + " {\"actual\": \"ab-34\", \"errorCode\": 8, \"instanceRef\": \"#/phones/0\", \"schemaRef\": \"#/definitions/phone_type\"}," + " {\"actual\": \"cd-78\", \"errorCode\": 8, \"instanceRef\": \"#/phones/1\", \"schemaRef\": \"#/definitions/phone_type\"}" + "]}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, an enum field is correctly processed when it has an invalid value. +// This tests that we don't blow up if a hasher does not get created. +TEST(SchemaValidator, ContinueOnErrors_Enum) { + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + VALIDATE(s, "{\"gender\":\"M\"}", true); + INVALIDATE_(s, "{\"gender\":\"X\"}", "#", "errors", "#", + "{\"enum\": {\"errorCode\": 19, \"instanceRef\": \"#/gender\", \"schemaRef\": \"#/properties/gender\"}}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + INVALIDATE_(s, "{\"gender\":1}", "#", "errors", "#", + "{\"type\": {\"expected\":[\"string\"], \"actual\": \"integer\", \"errorCode\": 20, \"instanceRef\": \"#/gender\", \"schemaRef\": \"#/properties/gender\"}}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, an array appearing for an object property is handled +// This tests that we don't blow up when there is a type mismatch. +TEST(SchemaValidator, ContinueOnErrors_RogueArray) { + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + INVALIDATE_(s, "{\"address\":[{\"number\": 0}]}", "#", "errors", "#", + "{\"type\": {\"expected\":[\"object\"], \"actual\": \"array\", \"errorCode\": 20, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\"}," + " \"dependencies\": {" + " \"errors\": {" + " \"address\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/address\"}}" + " },\"errorCode\": 18, \"instanceRef\": \"#\", \"schemaRef\": \"#\"}}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, an object appearing for an array property is handled +// This tests that we don't blow up when there is a type mismatch. +TEST(SchemaValidator, ContinueOnErrors_RogueObject) { + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + INVALIDATE_(s, "{\"phones\":{\"number\": 0}}", "#", "errors", "#", + "{\"type\": {\"expected\":[\"array\"], \"actual\": \"object\", \"errorCode\": 20, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"}}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, a string appearing for an array or object property is handled +// This tests that we don't blow up when there is a type mismatch. +TEST(SchemaValidator, ContinueOnErrors_RogueString) { + CrtAllocator allocator; + char* schema = ReadFile("unittestschema/address.json", allocator); + Document sd; + sd.Parse(schema); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + INVALIDATE_(s, "{\"address\":\"number\"}", "#", "errors", "#", + "{\"type\": {\"expected\":[\"object\"], \"actual\": \"string\", \"errorCode\": 20, \"instanceRef\": \"#/address\", \"schemaRef\": \"#/definitions/address_type\"}," + " \"dependencies\": {" + " \"errors\": {" + " \"address\": {\"required\": {\"missing\": [\"version\"], \"errorCode\": 15, \"instanceRef\": \"#\", \"schemaRef\": \"#/dependencies/address\"}}" + " },\"errorCode\": 18, \"instanceRef\": \"#\", \"schemaRef\": \"#\"}}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + INVALIDATE_(s, "{\"phones\":\"number\"}", "#", "errors", "#", + "{\"type\": {\"expected\":[\"array\"], \"actual\": \"string\", \"errorCode\": 20, \"instanceRef\": \"#/phones\", \"schemaRef\": \"#/properties/phones\"}}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + CrtAllocator::Free(schema); +} + +// Test that when kValidateContinueOnErrorFlag is set, an incorrect simple type with a sub-schema is handled correctly. +// This tests that we don't blow up when there is a type mismatch but there is a sub-schema present +TEST(SchemaValidator, ContinueOnErrors_BadSimpleType) { + Document sd; + sd.Parse("{\"type\":\"string\", \"anyOf\":[{\"maxLength\":2}]}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + VALIDATE(s, "\"AB\"", true); + INVALIDATE_(s, "\"ABC\"", "#", "errors", "#", + "{ \"anyOf\": {" + " \"errors\": [{" + " \"maxLength\": {" + " \"errorCode\": 6, \"instanceRef\": \"#\", \"schemaRef\": \"#/anyOf/0\", \"expected\": 2, \"actual\": \"ABC\"" + " }" + " }]," + " \"errorCode\": 24, \"instanceRef\": \"#\", \"schemaRef\": \"#\"" + " }" + "}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); + // Invalid type + INVALIDATE_(s, "333", "#", "errors", "#", + "{ \"type\": {" + " \"errorCode\": 20, \"instanceRef\": \"#\", \"schemaRef\": \"#\", \"expected\": [\"string\"], \"actual\": \"integer\"" + " }" + "}", + kValidateDefaultFlags | kValidateContinueOnErrorFlag, SchemaValidator, Pointer); +} + + +TEST(SchemaValidator, UnknownValidationError) { + ASSERT_TRUE(SchemaValidator::SchemaType::GetValidateErrorKeyword(kValidateErrors).GetString() == std::string("null")); +} + +// The first occurrence of a duplicate keyword is taken +TEST(SchemaValidator, DuplicateKeyword) { + Document sd; + sd.Parse("{ \"title\": \"test\",\"type\": \"number\", \"type\": \"string\" }"); + EXPECT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + VALIDATE(s, "42", true); + INVALIDATE(s, "\"Life, the universe, and everything\"", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"number\"], \"actual\": \"string\"" + "}}"); +} + + +// SchemaDocument tests + +// Specification (schema draft, open api version) +TEST(SchemaValidator, Schema_SupportedNotObject) { + Document sd; + sd.Parse("true"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedNoSpec) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedNoSpecStatic) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + Specification spec = SchemaDocumentType::GetSpecification(sd); + ASSERT_FALSE(spec.IsSupported()); + ASSERT_TRUE(spec.draft == kDraftNone); + ASSERT_TRUE(spec.oapi == kVersionNone); +} + +TEST(SchemaValidator, Schema_SupportedDraft5Static) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-05/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + Specification spec = SchemaDocumentType::GetSpecification(sd); + ASSERT_TRUE(spec.IsSupported()); + ASSERT_TRUE(spec.draft == kDraft05); + ASSERT_TRUE(spec.oapi == kVersionNone); +} + +TEST(SchemaValidator, Schema_SupportedDraft4) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-04/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraft4NoFrag) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-04/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraft5) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-05/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft05); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraft5NoFrag) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-05/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft05); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_IgnoreDraftEmbedded) { + Document sd; + sd.Parse("{\"root\": {\"$schema\":\"http://json-schema.org/draft-05/schema#\", \"type\": \"integer\"}}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, SchemaDocument::PointerType("/root")); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedDraftOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kDraft04)); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_UnknownDraftOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kDraftUnknown)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraftUnknown); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraftOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kDraft03)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft03); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownDraft) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-xxx/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraftUnknown); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownDraftNotString) { + Document sd; + sd.Parse("{\"$schema\": 4, \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraftUnknown); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft3) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-03/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft03); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft6) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-06/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft06); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft7) { + Document sd; + sd.Parse("{\"$schema\":\"http://json-schema.org/draft-07/schema#\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft07); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft2019_09) { + Document sd; + sd.Parse("{\"$schema\":\"https://json-schema.org/draft/2019-09/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2019_09); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedDraft2020_12) { + Document sd; + sd.Parse("{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\", \"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2020_12); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionNone); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_SupportedVersion20Static) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"swagger\":\"2.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + Specification spec = SchemaDocumentType::GetSpecification(sd); + ASSERT_TRUE(spec.IsSupported()); + ASSERT_TRUE(spec.draft == kDraft04); + ASSERT_TRUE(spec.oapi == kVersion20); +} + +TEST(SchemaValidator, Schema_SupportedVersion20) { + Document sd; + sd.Parse("{\"swagger\":\"2.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion20); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedVersion30x) { + Document sd; + sd.Parse("{\"openapi\":\"3.0.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion30); + ASSERT_TRUE(s.GetSpecification().draft == kDraft05); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_SupportedVersionOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion20)); + ASSERT_TRUE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion20); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + EXPECT_TRUE(s.GetError().ObjectEmpty()); +} + +TEST(SchemaValidator, Schema_UnknownVersionOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersionUnknown)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedVersionOverride) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion31)); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion31); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2020_12); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownVersion) { + Document sd; + sd.Parse("{\"openapi\":\"1.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownVersionShort) { + Document sd; + sd.Parse("{\"openapi\":\"3.0.\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnknownVersionNotString) { + Document sd; + sd.Parse("{\"swagger\": 2}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersionUnknown); + ASSERT_TRUE(s.GetSpecification().draft == kDraft04); + SCHEMAERROR(s, "{\"SpecUnknown\":{\"errorCode\":10,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_UnsupportedVersion31) { + Document sd; + sd.Parse("{\"openapi\":\"3.1.0\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_FALSE(s.IsSupportedSpecification()); + ASSERT_TRUE(s.GetSpecification().oapi == kVersion31); + ASSERT_TRUE(s.GetSpecification().draft == kDraft2020_12); + SCHEMAERROR(s, "{\"SpecUnsupported\":{\"errorCode\":11,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_DraftAndVersion) { + Document sd; + sd.Parse("{\"swagger\": \"2.0\", \"$schema\": \"http://json-schema.org/draft-04/schema#\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + ASSERT_TRUE(s.IsSupportedSpecification()); + SCHEMAERROR(s, "{\"SpecIllegal\":{\"errorCode\":12,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, Schema_StartUnknown) { + Document sd; + sd.Parse("{\"type\": \"integer\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd, 0, 0, 0, 0, SchemaDocument::PointerType("/nowhere")); + SCHEMAERROR(s, "{\"StartUnknown\":{\"errorCode\":1,\"instanceRef\":\"#\", \"value\":\"#/nowhere\"}}"); +} + +TEST(SchemaValidator, Schema_MultipleErrors) { + Document sd; + sd.Parse("{\"swagger\": \"foo\", \"$schema\": \"bar\"}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s(sd); + SCHEMAERROR(s, "{ \"SpecUnknown\": {\"errorCode\":10,\"instanceRef\":\"#\"}," + " \"SpecIllegal\": {\"errorCode\":12,\"instanceRef\":\"#\"}" + "}"); +} + +// $ref is a non-JSON pointer fragment - not allowed when OpenAPI +TEST(SchemaValidator, Schema_RefPlainNameOpenApi) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"swagger\": \"2.0\", \"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"#myId\"}, \"myStr\": {\"type\": \"string\", \"id\": \"#myStrId\"}, \"myInt2\": {\"type\": \"integer\", \"id\": \"#myId\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefPlainName\":{\"errorCode\":2,\"instanceRef\":\"#/properties/myInt1\",\"value\":\"#myId\"}}"); +} + +// $ref is a non-JSON pointer fragment - not allowed when remote document +TEST(SchemaValidator, Schema_RefPlainNameRemote) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#plainname\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefPlainName\":{\"errorCode\":2,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#plainname\"}}"); +} + +// $ref is an empty string +TEST(SchemaValidator, Schema_RefEmptyString) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt1\": {\"$ref\": \"\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefInvalid\":{\"errorCode\":3,\"instanceRef\":\"#/properties/myInt1\"}}"); +} + +// $ref is remote but no provider +TEST(SchemaValidator, Schema_RefNoRemoteProvider) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#plainname\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, 0); + SCHEMAERROR(s, "{\"RefNoRemoteProvider\":{\"errorCode\":7,\"instanceRef\":\"#/properties/myInt\"}}"); +} + +// $ref is remote but no schema returned +TEST(SchemaValidator, Schema_RefNoRemoteSchema) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/will-not-resolve.json\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefNoRemoteSchema\":{\"errorCode\":8,\"instanceRef\":\"#/properties/myInt\",\"value\":\"http://localhost:1234/will-not-resolve.json\"}}"); +} + +// $ref pointer is invalid +TEST(SchemaValidator, Schema_RefPointerInvalid) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"#/&&&&&\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefPointerInvalid\":{\"errorCode\":4,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#/&&&&&\",\"offset\":2}}"); +} + +// $ref is remote and pointer is invalid +TEST(SchemaValidator, Schema_RefPointerInvalidRemote) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/abc&&&&&\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefPointerInvalid\":{\"errorCode\":4,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#/abc&&&&&\",\"offset\":5}}"); +} + +// $ref is unknown non-pointer +TEST(SchemaValidator, Schema_RefUnknownPlainName) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"#plainname\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#plainname\"}}"); +} + +/// $ref is unknown pointer +TEST(SchemaValidator, Schema_RefUnknownPointer) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"#/a/b\"}}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/properties/myInt\",\"value\":\"#/a/b\"}}"); +} + +// $ref is remote and unknown pointer +TEST(SchemaValidator, Schema_RefUnknownPointerRemote) { + typedef GenericSchemaDocument > SchemaDocumentType; + RemoteSchemaDocumentProvider provider; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {\"myInt\": {\"$ref\": \"/subSchemas.json#/a/b\"}}}"); + SchemaDocumentType s(sd, "http://localhost:1234/xxxx", 26, &provider); + SCHEMAERROR(s, "{\"RefUnknown\":{\"errorCode\":5,\"instanceRef\":\"#/properties/myInt\",\"value\":\"http://localhost:1234/subSchemas.json#/a/b\"}}"); +} + +// $ref is cyclical +TEST(SchemaValidator, Schema_RefCyclical) { + typedef GenericSchemaDocument > SchemaDocumentType; + Document sd; + sd.Parse("{\"type\": \"object\", \"properties\": {" + " \"cyclic_source\": {" + " \"$ref\": \"#/properties/cyclic_target\"" + " }," + " \"cyclic_target\": {" + " \"$ref\": \"#/properties/cyclic_source\"" + " }" + "}}"); + SchemaDocumentType s(sd); + SCHEMAERROR(s, "{\"RefCyclical\":{\"errorCode\":6,\"instanceRef\":\"#/properties/cyclic_target\",\"value\":\"#/properties/cyclic_source\"}}"); +} + +TEST(SchemaValidator, Schema_ReadOnlyAndWriteOnly) { + Document sd; + sd.Parse("{\"type\": \"integer\", \"readOnly\": true, \"writeOnly\": true}"); + ASSERT_FALSE(sd.HasParseError()); + SchemaDocument s1(sd, 0, 0, 0, 0, 0, Specification(kDraft04)); + EXPECT_TRUE(s1.GetError().ObjectEmpty()); + SchemaDocument s2(sd, 0, 0, 0, 0, 0, Specification(kVersion30)); + SCHEMAERROR(s2, "{\"ReadOnlyAndWriteOnly\":{\"errorCode\":13,\"instanceRef\":\"#\"}}"); +} + +TEST(SchemaValidator, ReadOnlyWhenWriting) { + Document sd; + sd.Parse( + "{" + " \"type\":\"object\"," + " \"properties\": {" + " \"rprop\" : {" + " \"type\": \"string\"," + " \"readOnly\": true" + " }" + " }" + "}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion20)); + VALIDATE(s, "{ \"rprop\": \"hello\" }", true); + INVALIDATE_(s, "{ \"rprop\": \"hello\" }", "/properties/rprop", "readOnly", "/rprop", + "{ \"readOnly\": {" + " \"errorCode\": 26, \"instanceRef\": \"#/rprop\", \"schemaRef\": \"#/properties/rprop\"" + " }" + "}", + kValidateDefaultFlags | kValidateWriteFlag, SchemaValidator, Pointer); +} + +TEST(SchemaValidator, WriteOnlyWhenReading) { + Document sd; + sd.Parse( + "{" + " \"type\":\"object\"," + " \"properties\": {" + " \"wprop\" : {" + " \"type\": \"boolean\"," + " \"writeOnly\": true" + " }" + " }" + "}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, Specification(kVersion30)); + VALIDATE(s, "{ \"wprop\": true }", true); + INVALIDATE_(s, "{ \"wprop\": true }", "/properties/wprop", "writeOnly", "/wprop", + "{ \"writeOnly\": {" + " \"errorCode\": 27, \"instanceRef\": \"#/wprop\", \"schemaRef\": \"#/properties/wprop\"" + " }" + "}", + kValidateDefaultFlags | kValidateReadFlag, SchemaValidator, Pointer); +} + +TEST(SchemaValidator, NullableTrue) { + Document sd; + sd.Parse("{\"type\": \"string\", \"nullable\": true}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, kVersion20); + + VALIDATE(s, "\"hello\"", true); + INVALIDATE(s, "null", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"null\"" + "}}"); + INVALIDATE(s, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"boolean\"" + "}}"); + + SchemaDocument s30(sd, 0, 0, 0, 0, 0, kVersion30); + + VALIDATE(s30, "\"hello\"", true); + VALIDATE(s30, "null", true); + INVALIDATE(s30, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"null\", \"string\"], \"actual\": \"boolean\"" + "}}"); +} + +TEST(SchemaValidator, NullableFalse) { + Document sd; + sd.Parse("{\"type\": \"string\", \"nullable\": false}"); + SchemaDocument s(sd, 0, 0, 0, 0, 0, kVersion20); + + VALIDATE(s, "\"hello\"", true); + INVALIDATE(s, "null", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"null\"" + "}}"); + INVALIDATE(s, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"boolean\"" + "}}"); + + SchemaDocument s30(sd, 0, 0, 0, 0, 0, kVersion30); + + VALIDATE(s30, "\"hello\"", true); + INVALIDATE(s, "null", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"null\"" + "}}"); + INVALIDATE(s30, "false", "", "type", "", + "{ \"type\": {" + " \"errorCode\": 20," + " \"instanceRef\": \"#\", \"schemaRef\": \"#\"," + " \"expected\": [\"string\"], \"actual\": \"boolean\"" + "}}"); +} + +#if defined(_MSC_VER) || defined(__clang__) +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/simdtest.cpp b/deps/rapidjson/test/unittest/simdtest.cpp new file mode 100644 index 0000000..570b083 --- /dev/null +++ b/deps/rapidjson/test/unittest/simdtest.cpp @@ -0,0 +1,219 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +// Since Travis CI installs old Valgrind 3.7.0, which fails with some SSE4.2 +// The unit tests prefix with SIMD should be skipped by Valgrind test + +// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler. +// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported. +#if defined(__SSE4_2__) +# define RAPIDJSON_SSE42 +#elif defined(__SSE2__) +# define RAPIDJSON_SSE2 +#elif defined(__ARM_NEON) +# define RAPIDJSON_NEON +#endif + +#define RAPIDJSON_NAMESPACE rapidjson_simd + +#include "unittest.h" + +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#endif + +using namespace rapidjson_simd; + +#ifdef RAPIDJSON_SSE2 +#define SIMD_SUFFIX(name) name##_SSE2 +#elif defined(RAPIDJSON_SSE42) +#define SIMD_SUFFIX(name) name##_SSE42 +#elif defined(RAPIDJSON_NEON) +#define SIMD_SUFFIX(name) name##_NEON +#else +#define SIMD_SUFFIX(name) name +#endif + +#define SIMD_SIZE_ALIGN(n) ((size_t(n) + 15) & ~size_t(15)) + +template +void TestSkipWhitespace() { + for (size_t step = 1; step < 32; step++) { + char buffer[SIMD_SIZE_ALIGN(1025)]; + for (size_t i = 0; i < 1024; i++) + buffer[i] = " \t\r\n"[i % 4]; + for (size_t i = 0; i < 1024; i += step) + buffer[i] = 'X'; + buffer[1024] = '\0'; + + StreamType s(buffer); + size_t i = 0; + for (;;) { + SkipWhitespace(s); + if (s.Peek() == '\0') + break; + EXPECT_EQ(i, s.Tell()); + EXPECT_EQ('X', s.Take()); + i += step; + } + } +} + +TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) { + TestSkipWhitespace(); + TestSkipWhitespace(); +} + +TEST(SIMD, SIMD_SUFFIX(SkipWhitespace_EncodedMemoryStream)) { + for (size_t step = 1; step < 32; step++) { + char buffer[SIMD_SIZE_ALIGN(1024)]; + for (size_t i = 0; i < 1024; i++) + buffer[i] = " \t\r\n"[i % 4]; + for (size_t i = 0; i < 1024; i += step) + buffer[i] = 'X'; + + MemoryStream ms(buffer, 1024); + EncodedInputStream, MemoryStream> s(ms); + for (;;) { + SkipWhitespace(s); + if (s.Peek() == '\0') + break; + //EXPECT_EQ(i, s.Tell()); + EXPECT_EQ('X', s.Take()); + } + } +} + +struct ScanCopyUnescapedStringHandler : BaseReaderHandler, ScanCopyUnescapedStringHandler> { + bool String(const char* str, size_t length, bool) { + memcpy(buffer, str, length + 1); + return true; + } + char buffer[1024 + 5 + 32]; +}; + +template +void TestScanCopyUnescapedString() { + char buffer[SIMD_SIZE_ALIGN(1024u + 5 + 32)]; + char backup[SIMD_SIZE_ALIGN(1024u + 5 + 32)]; + + // Test "ABCDABCD...\\" + for (size_t offset = 0; offset < 32; offset++) { + for (size_t step = 0; step < 1024; step++) { + char* json = buffer + offset; + char *p = json; + *p++ = '\"'; + for (size_t i = 0; i < step; i++) + *p++ = "ABCD"[i % 4]; + *p++ = '\\'; + *p++ = '\\'; + *p++ = '\"'; + *p++ = '\0'; + strcpy(backup, json); // insitu parsing will overwrite buffer, so need to backup first + + StreamType s(json); + Reader reader; + ScanCopyUnescapedStringHandler h; + reader.Parse(s, h); + EXPECT_TRUE(memcmp(h.buffer, backup + 1, step) == 0); + EXPECT_EQ('\\', h.buffer[step]); // escaped + EXPECT_EQ('\0', h.buffer[step + 1]); + } + } + + // Test "\\ABCDABCD..." + for (size_t offset = 0; offset < 32; offset++) { + for (size_t step = 0; step < 1024; step++) { + char* json = buffer + offset; + char *p = json; + *p++ = '\"'; + *p++ = '\\'; + *p++ = '\\'; + for (size_t i = 0; i < step; i++) + *p++ = "ABCD"[i % 4]; + *p++ = '\"'; + *p++ = '\0'; + strcpy(backup, json); // insitu parsing will overwrite buffer, so need to backup first + + StreamType s(json); + Reader reader; + ScanCopyUnescapedStringHandler h; + reader.Parse(s, h); + EXPECT_TRUE(memcmp(h.buffer + 1, backup + 3, step) == 0); + EXPECT_EQ('\\', h.buffer[0]); // escaped + EXPECT_EQ('\0', h.buffer[step + 1]); + } + } +} + +TEST(SIMD, SIMD_SUFFIX(ScanCopyUnescapedString)) { + TestScanCopyUnescapedString(); + TestScanCopyUnescapedString(); +} + +TEST(SIMD, SIMD_SUFFIX(ScanWriteUnescapedString)) { + char buffer[SIMD_SIZE_ALIGN(2048 + 1 + 32)]; + for (size_t offset = 0; offset < 32; offset++) { + for (size_t step = 0; step < 1024; step++) { + char* s = buffer + offset; + char* p = s; + for (size_t i = 0; i < step; i++) + *p++ = "ABCD"[i % 4]; + char escape = "\0\n\\\""[step % 4]; + *p++ = escape; + for (size_t i = 0; i < step; i++) + *p++ = "ABCD"[i % 4]; + + StringBuffer sb; + Writer writer(sb); + writer.String(s, SizeType(step * 2 + 1)); + const char* q = sb.GetString(); + EXPECT_EQ('\"', *q++); + for (size_t i = 0; i < step; i++) + EXPECT_EQ("ABCD"[i % 4], *q++); + if (escape == '\0') { + EXPECT_EQ('\\', *q++); + EXPECT_EQ('u', *q++); + EXPECT_EQ('0', *q++); + EXPECT_EQ('0', *q++); + EXPECT_EQ('0', *q++); + EXPECT_EQ('0', *q++); + } + else if (escape == '\n') { + EXPECT_EQ('\\', *q++); + EXPECT_EQ('n', *q++); + } + else if (escape == '\\') { + EXPECT_EQ('\\', *q++); + EXPECT_EQ('\\', *q++); + } + else if (escape == '\"') { + EXPECT_EQ('\\', *q++); + EXPECT_EQ('\"', *q++); + } + for (size_t i = 0; i < step; i++) + EXPECT_EQ("ABCD"[i % 4], *q++); + EXPECT_EQ('\"', *q++); + EXPECT_EQ('\0', *q++); + } + } +} + +#ifdef __GNUC__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/strfunctest.cpp b/deps/rapidjson/test/unittest/strfunctest.cpp new file mode 100644 index 0000000..4112693 --- /dev/null +++ b/deps/rapidjson/test/unittest/strfunctest.cpp @@ -0,0 +1,30 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/internal/strfunc.h" + +using namespace rapidjson; +using namespace rapidjson::internal; + +TEST(StrFunc, CountStringCodePoint) { + SizeType count; + EXPECT_TRUE(CountStringCodePoint >("", 0, &count)); + EXPECT_EQ(0u, count); + EXPECT_TRUE(CountStringCodePoint >("Hello", 5, &count)); + EXPECT_EQ(5u, count); + EXPECT_TRUE(CountStringCodePoint >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E", 9, &count)); // cents euro G-clef + EXPECT_EQ(3u, count); + EXPECT_FALSE(CountStringCodePoint >("\xC2\xA2\xE2\x82\xAC\xF0\x9D\x84\x9E\x80", 10, &count)); +} diff --git a/deps/rapidjson/test/unittest/stringbuffertest.cpp b/deps/rapidjson/test/unittest/stringbuffertest.cpp new file mode 100644 index 0000000..eaa29e7 --- /dev/null +++ b/deps/rapidjson/test/unittest/stringbuffertest.cpp @@ -0,0 +1,192 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +using namespace rapidjson; + +TEST(StringBuffer, InitialSize) { + StringBuffer buffer; + EXPECT_EQ(0u, buffer.GetSize()); + EXPECT_EQ(0u, buffer.GetLength()); + EXPECT_STREQ("", buffer.GetString()); +} + +TEST(StringBuffer, Put) { + StringBuffer buffer; + buffer.Put('A'); + + EXPECT_EQ(1u, buffer.GetSize()); + EXPECT_EQ(1u, buffer.GetLength()); + EXPECT_STREQ("A", buffer.GetString()); +} + +TEST(StringBuffer, PutN_Issue672) { + GenericStringBuffer, MemoryPoolAllocator<> > buffer; + EXPECT_EQ(0u, buffer.GetSize()); + EXPECT_EQ(0u, buffer.GetLength()); + rapidjson::PutN(buffer, ' ', 1); + EXPECT_EQ(1u, buffer.GetSize()); + EXPECT_EQ(1u, buffer.GetLength()); +} + +TEST(StringBuffer, Clear) { + StringBuffer buffer; + buffer.Put('A'); + buffer.Put('B'); + buffer.Put('C'); + buffer.Clear(); + + EXPECT_EQ(0u, buffer.GetSize()); + EXPECT_EQ(0u, buffer.GetLength()); + EXPECT_STREQ("", buffer.GetString()); +} + +TEST(StringBuffer, Push) { + StringBuffer buffer; + buffer.Push(5); + + EXPECT_EQ(5u, buffer.GetSize()); + EXPECT_EQ(5u, buffer.GetLength()); + + // Causes sudden expansion to make the stack's capacity equal to size + buffer.Push(65536u); + EXPECT_EQ(5u + 65536u, buffer.GetSize()); +} + +TEST(StringBuffer, Pop) { + StringBuffer buffer; + buffer.Put('A'); + buffer.Put('B'); + buffer.Put('C'); + buffer.Put('D'); + buffer.Put('E'); + buffer.Pop(3); + + EXPECT_EQ(2u, buffer.GetSize()); + EXPECT_EQ(2u, buffer.GetLength()); + EXPECT_STREQ("AB", buffer.GetString()); +} + +TEST(StringBuffer, GetLength_Issue744) { + GenericStringBuffer > buffer; + buffer.Put('A'); + buffer.Put('B'); + buffer.Put('C'); + EXPECT_EQ(3u * sizeof(wchar_t), buffer.GetSize()); + EXPECT_EQ(3u, buffer.GetLength()); +} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#if 0 // Many old compiler does not support these. Turn it off temporaily. + +#include + +TEST(StringBuffer, Traits) { + static_assert( std::is_constructible::value, ""); + static_assert( std::is_default_constructible::value, ""); +#ifndef _MSC_VER + static_assert(!std::is_copy_constructible::value, ""); +#endif + static_assert( std::is_move_constructible::value, ""); + + static_assert(!std::is_nothrow_constructible::value, ""); + static_assert(!std::is_nothrow_default_constructible::value, ""); + +#if !defined(_MSC_VER) || _MSC_VER >= 1800 + static_assert(!std::is_nothrow_copy_constructible::value, ""); + static_assert(!std::is_nothrow_move_constructible::value, ""); +#endif + + static_assert( std::is_assignable::value, ""); +#ifndef _MSC_VER + static_assert(!std::is_copy_assignable::value, ""); +#endif + static_assert( std::is_move_assignable::value, ""); + +#if !defined(_MSC_VER) || _MSC_VER >= 1800 + static_assert(!std::is_nothrow_assignable::value, ""); +#endif + + static_assert(!std::is_nothrow_copy_assignable::value, ""); + static_assert(!std::is_nothrow_move_assignable::value, ""); + + static_assert( std::is_destructible::value, ""); +#ifndef _MSC_VER + static_assert(std::is_nothrow_destructible::value, ""); +#endif +} + +#endif + +TEST(StringBuffer, MoveConstructor) { + StringBuffer x; + x.Put('A'); + x.Put('B'); + x.Put('C'); + x.Put('D'); + + EXPECT_EQ(4u, x.GetSize()); + EXPECT_EQ(4u, x.GetLength()); + EXPECT_STREQ("ABCD", x.GetString()); + + // StringBuffer y(x); // does not compile (!is_copy_constructible) + StringBuffer y(std::move(x)); + EXPECT_EQ(0u, x.GetSize()); + EXPECT_EQ(0u, x.GetLength()); + EXPECT_EQ(4u, y.GetSize()); + EXPECT_EQ(4u, y.GetLength()); + EXPECT_STREQ("ABCD", y.GetString()); + + // StringBuffer z = y; // does not compile (!is_copy_assignable) + StringBuffer z = std::move(y); + EXPECT_EQ(0u, y.GetSize()); + EXPECT_EQ(0u, y.GetLength()); + EXPECT_EQ(4u, z.GetSize()); + EXPECT_EQ(4u, z.GetLength()); + EXPECT_STREQ("ABCD", z.GetString()); +} + +TEST(StringBuffer, MoveAssignment) { + StringBuffer x; + x.Put('A'); + x.Put('B'); + x.Put('C'); + x.Put('D'); + + EXPECT_EQ(4u, x.GetSize()); + EXPECT_EQ(4u, x.GetLength()); + EXPECT_STREQ("ABCD", x.GetString()); + + StringBuffer y; + // y = x; // does not compile (!is_copy_assignable) + y = std::move(x); + EXPECT_EQ(0u, x.GetSize()); + EXPECT_EQ(4u, y.GetLength()); + EXPECT_STREQ("ABCD", y.GetString()); +} + +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/strtodtest.cpp b/deps/rapidjson/test/unittest/strtodtest.cpp new file mode 100644 index 0000000..66167a4 --- /dev/null +++ b/deps/rapidjson/test/unittest/strtodtest.cpp @@ -0,0 +1,132 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/internal/strtod.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + +#define BIGINTEGER_LITERAL(s) BigInteger(s, sizeof(s) - 1) + +using namespace rapidjson::internal; + +TEST(Strtod, CheckApproximationCase) { + static const int kSignificandSize = 52; + static const int kExponentBias = 0x3FF; + static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); + static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); + static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); + + // http://www.exploringbinary.com/using-integers-to-check-a-floating-point-approximation/ + // Let b = 0x1.465a72e467d88p-149 + // = 5741268244528520 x 2^-201 + union { + double d; + uint64_t u; + }u; + u.u = 0x465a72e467d88 | ((static_cast(-149 + kExponentBias)) << kSignificandSize); + const double b = u.d; + const uint64_t bInt = (u.u & kSignificandMask) | kHiddenBit; + const int bExp = static_cast(((u.u & kExponentMask) >> kSignificandSize) - kExponentBias - kSignificandSize); + EXPECT_DOUBLE_EQ(1.7864e-45, b); + EXPECT_EQ(RAPIDJSON_UINT64_C2(0x001465a7, 0x2e467d88), bInt); + EXPECT_EQ(-201, bExp); + + // Let d = 17864 x 10-49 + const char dInt[] = "17864"; + const int dExp = -49; + + // Let h = 2^(bExp-1) + const int hExp = bExp - 1; + EXPECT_EQ(-202, hExp); + + int dS_Exp2 = 0; + int dS_Exp5 = 0; + int bS_Exp2 = 0; + int bS_Exp5 = 0; + int hS_Exp2 = 0; + int hS_Exp5 = 0; + + // Adjust for decimal exponent + if (dExp >= 0) { + dS_Exp2 += dExp; + dS_Exp5 += dExp; + } + else { + bS_Exp2 -= dExp; + bS_Exp5 -= dExp; + hS_Exp2 -= dExp; + hS_Exp5 -= dExp; + } + + // Adjust for binary exponent + if (bExp >= 0) + bS_Exp2 += bExp; + else { + dS_Exp2 -= bExp; + hS_Exp2 -= bExp; + } + + // Adjust for half ulp exponent + if (hExp >= 0) + hS_Exp2 += hExp; + else { + dS_Exp2 -= hExp; + bS_Exp2 -= hExp; + } + + // Remove common power of two factor from all three scaled values + int common_Exp2 = (std::min)(dS_Exp2, (std::min)(bS_Exp2, hS_Exp2)); + dS_Exp2 -= common_Exp2; + bS_Exp2 -= common_Exp2; + hS_Exp2 -= common_Exp2; + + EXPECT_EQ(153, dS_Exp2); + EXPECT_EQ(0, dS_Exp5); + EXPECT_EQ(1, bS_Exp2); + EXPECT_EQ(49, bS_Exp5); + EXPECT_EQ(0, hS_Exp2); + EXPECT_EQ(49, hS_Exp5); + + BigInteger dS = BIGINTEGER_LITERAL(dInt); + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); + + BigInteger bS(bInt); + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); + + BigInteger hS(1); + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); + + EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994138521801764465966248930731085529088") == dS); + EXPECT_TRUE(BIGINTEGER_LITERAL("203970822259994122305215569213032722473144531250000") == bS); + EXPECT_TRUE(BIGINTEGER_LITERAL("17763568394002504646778106689453125") == hS); + + EXPECT_EQ(1, dS.Compare(bS)); + + BigInteger delta(0); + EXPECT_FALSE(dS.Difference(bS, &delta)); + EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta); + EXPECT_TRUE(bS.Difference(dS, &delta)); + EXPECT_TRUE(BIGINTEGER_LITERAL("16216586195252933526457586554279088") == delta); + + EXPECT_EQ(-1, delta.Compare(hS)); +} + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/unittest.cpp b/deps/rapidjson/test/unittest/unittest.cpp new file mode 100644 index 0000000..879976a --- /dev/null +++ b/deps/rapidjson/test/unittest/unittest.cpp @@ -0,0 +1,51 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/rapidjson.h" + +#ifdef __clang__ +#pragma GCC diagnostic push +#if __has_warning("-Wdeprecated") +#pragma GCC diagnostic ignored "-Wdeprecated" +#endif +#endif + +AssertException::~AssertException() throw() {} + +#ifdef __clang__ +#pragma GCC diagnostic pop +#endif + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + + std::cout << "RapidJSON v" << RAPIDJSON_VERSION_STRING << std::endl; + +#ifdef _MSC_VER + _CrtMemState memoryState = { 0 }; + (void)memoryState; + _CrtMemCheckpoint(&memoryState); + //_CrtSetBreakAlloc(X); + //void *testWhetherMemoryLeakDetectionWorks = malloc(1); +#endif + + int ret = RUN_ALL_TESTS(); + +#ifdef _MSC_VER + // Current gtest constantly leak 2 blocks at exit + _CrtMemDumpAllObjectsSince(&memoryState); +#endif + return ret; +} diff --git a/deps/rapidjson/test/unittest/unittest.h b/deps/rapidjson/test/unittest/unittest.h new file mode 100644 index 0000000..0e64d39 --- /dev/null +++ b/deps/rapidjson/test/unittest/unittest.h @@ -0,0 +1,143 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef UNITTEST_H_ +#define UNITTEST_H_ + +// gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS. +#ifndef __STDC_CONSTANT_MACROS +#ifdef __clang__ +#pragma GCC diagnostic push +#if __has_warning("-Wreserved-id-macro") +#pragma GCC diagnostic ignored "-Wreserved-id-macro" +#endif +#endif + +# define __STDC_CONSTANT_MACROS 1 // required by C++ standard + +#ifdef __clang__ +#pragma GCC diagnostic pop +#endif +#endif + +#ifdef _MSC_VER +#define _CRTDBG_MAP_ALLOC +#include +#pragma warning(disable : 4996) // 'function': was declared deprecated +#endif + +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) +#if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#pragma GCC diagnostic push +#endif +#pragma GCC diagnostic ignored "-Weffc++" +#endif + +#include "gtest/gtest.h" +#include + +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +#pragma GCC diagnostic pop +#endif + +#ifdef __clang__ +// All TEST() macro generated this warning, disable globally +#pragma GCC diagnostic ignored "-Wglobal-constructors" +#endif + +template +inline unsigned StrLen(const Ch* s) { + const Ch* p = s; + while (*p) p++; + return unsigned(p - s); +} + +template +inline int StrCmp(const Ch* s1, const Ch* s2) { + while(*s1 && (*s1 == *s2)) { s1++; s2++; } + return static_cast(*s1) < static_cast(*s2) ? -1 : static_cast(*s1) > static_cast(*s2); +} + +template +inline Ch* StrDup(const Ch* str) { + size_t bufferSize = sizeof(Ch) * (StrLen(str) + 1); + Ch* buffer = static_cast(malloc(bufferSize)); + memcpy(buffer, str, bufferSize); + return buffer; +} + +inline FILE* TempFile(char *filename) { +#if defined(__WIN32__) || defined(_MSC_VER) + filename = tmpnam(filename); + + // For Visual Studio, tmpnam() adds a backslash in front. Remove it. + if (filename[0] == '\\') + for (int i = 0; filename[i] != '\0'; i++) + filename[i] = filename[i + 1]; + + return fopen(filename, "wb"); +#else + strcpy(filename, "/tmp/fileXXXXXX"); + int fd = mkstemp(filename); + return fdopen(fd, "w"); +#endif +} + +// Use exception for catching assert +#ifdef _MSC_VER +#pragma warning(disable : 4127) +#endif + +#ifdef __clang__ +#pragma GCC diagnostic push +#if __has_warning("-Wdeprecated") +#pragma GCC diagnostic ignored "-Wdeprecated" +#endif +#endif + +class AssertException : public std::logic_error { +public: + AssertException(const char* w) : std::logic_error(w) {} + AssertException(const AssertException& rhs) : std::logic_error(rhs) {} + virtual ~AssertException() throw(); +}; + +#ifdef __clang__ +#pragma GCC diagnostic pop +#endif + +// Not using noexcept for testing RAPIDJSON_ASSERT() +#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0 + +#ifndef RAPIDJSON_ASSERT +#define RAPIDJSON_ASSERT(x) (!(x) ? throw AssertException(RAPIDJSON_STRINGIFY(x)) : (void)0u) +#ifndef RAPIDJSON_ASSERT_THROWS +#define RAPIDJSON_ASSERT_THROWS +#endif +#endif + +class Random { +public: + Random(unsigned seed = 0) : mSeed(seed) {} + + unsigned operator()() { + mSeed = 214013 * mSeed + 2531011; + return mSeed; + } + +private: + unsigned mSeed; +}; + +#endif // UNITTEST_H_ diff --git a/deps/rapidjson/test/unittest/uritest.cpp b/deps/rapidjson/test/unittest/uritest.cpp new file mode 100644 index 0000000..789c9dd --- /dev/null +++ b/deps/rapidjson/test/unittest/uritest.cpp @@ -0,0 +1,725 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// (C) Copyright IBM Corporation 2021 +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#define RAPIDJSON_HAS_STDSTRING 1 + +#include "unittest.h" +#include "rapidjson/document.h" +#include "rapidjson/uri.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(variadic-macros) +#elif defined(_MSC_VER) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4822) // local class member function does not have a body +#endif + +using namespace rapidjson; + +TEST(Uri, DefaultConstructor) { + typedef GenericUri UriType; + UriType u; + EXPECT_TRUE(u.GetSchemeString() == 0); + EXPECT_TRUE(u.GetAuthString() == 0); + EXPECT_TRUE(u.GetPathString() == 0); + EXPECT_TRUE(u.GetBaseString() == 0); + EXPECT_TRUE(u.GetQueryString() == 0); + EXPECT_TRUE(u.GetFragString() == 0); + EXPECT_TRUE(u.GetString() == 0); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(u.GetPathStringLength() == 0); + EXPECT_TRUE(u.GetBaseStringLength() == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + EXPECT_TRUE(u.GetStringLength() == 0); +} + +TEST(Uri, Parse) { + typedef GenericUri > UriType; + MemoryPoolAllocator allocator; + Value v; + Value w; + + v.SetString("http://auth/path/xxx?query#frag", allocator); + UriType u = UriType(v, &allocator); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), "http:") == 0); + EXPECT_TRUE(StrCmp(u.GetAuthString(), "//auth") == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), "/path/xxx") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "http://auth/path/xxx?query") == 0); + EXPECT_TRUE(StrCmp(u.GetQueryString(), "?query") == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag") == 0); + u.Get(w, allocator); + EXPECT_TRUE(*w.GetString() == *v.GetString()); + + v.SetString("urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f", allocator); + u = UriType(v, &allocator); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), "urn:") == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), "uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + u.Get(w, allocator); + EXPECT_TRUE(*w.GetString() == *v.GetString()); + + v.SetString("", allocator); + u = UriType(v, &allocator); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(u.GetPathStringLength() == 0); + EXPECT_TRUE(u.GetBaseStringLength() == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + v.SetString("http://auth/", allocator); + u = UriType(v, &allocator); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), "http:") == 0); + EXPECT_TRUE(StrCmp(u.GetAuthString(), "//auth") == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), "/") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "http://auth/") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + u = UriType("/path/sub"); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), "/path/sub") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "/path/sub") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + // absolute path gets normalized + u = UriType("/path/../sub/"); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), "/sub/") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "/sub/") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + // relative path does not + u = UriType("path/../sub"); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), "path/../sub") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "path/../sub") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + u = UriType("http://auth#frag/stuff"); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), "http:") == 0); + EXPECT_TRUE(StrCmp(u.GetAuthString(), "//auth") == 0); + EXPECT_TRUE(u.GetPathStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "http://auth") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag/stuff") == 0); + EXPECT_TRUE(StrCmp(u.GetString(), "http://auth#frag/stuff") == 0); + + const Value::Ch c[] = { '#', 'f', 'r', 'a', 'g', '/', 's', 't', 'u', 'f', 'f', '\0'}; + SizeType len = internal::StrLen(c); + u = UriType(c, len); + EXPECT_TRUE(StrCmp(u.GetString(), "#frag/stuff") == 0); + EXPECT_TRUE(u.GetStringLength() == len); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "") == 0); + EXPECT_TRUE(u.GetBaseStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag/stuff") == 0); + EXPECT_TRUE(u.GetFragStringLength() == len); + + u = UriType(c); + EXPECT_TRUE(StrCmp(u.GetString(), "#frag/stuff") == 0); + EXPECT_TRUE(u.GetStringLength() == len); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "") == 0); + EXPECT_TRUE(u.GetBaseStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), "#frag/stuff") == 0); + EXPECT_TRUE(u.GetFragStringLength() == len); + + // Incomplete auth treated as path + u = UriType("http:/"); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), "http:") == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), "/") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), "http:/") == 0); +} + +TEST(Uri, Parse_UTF16) { + typedef GenericValue > Value16; + typedef GenericUri > UriType; + MemoryPoolAllocator allocator; + Value16 v; + Value16 w; + + v.SetString(L"http://auth/path/xxx?query#frag", allocator); + UriType u = UriType(v, &allocator); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0); + EXPECT_TRUE(StrCmp(u.GetAuthString(), L"//auth") == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), L"/path/xxx") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http://auth/path/xxx?query") == 0); + EXPECT_TRUE(StrCmp(u.GetQueryString(), L"?query") == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag") == 0); + u.Get(w, allocator); + EXPECT_TRUE(*w.GetString() == *v.GetString()); + + v.SetString(L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f", allocator); + u = UriType(v, &allocator); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"urn:") == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), L"uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + u.Get(w, allocator); + EXPECT_TRUE(*w.GetString() == *v.GetString()); + + v.SetString(L"", allocator); + u = UriType(v, &allocator); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(u.GetPathStringLength() == 0); + EXPECT_TRUE(u.GetBaseStringLength() == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + v.SetString(L"http://auth/", allocator); + u = UriType(v, &allocator); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0); + EXPECT_TRUE(StrCmp(u.GetAuthString(), L"//auth") == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), L"/") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http://auth/") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + u = UriType(L"/path/sub"); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), L"/path/sub") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"/path/sub") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + // absolute path gets normalized + u = UriType(L"/path/../sub/"); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), L"/sub/") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"/sub/") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + // relative path does not + u = UriType(L"path/../sub"); + EXPECT_TRUE(u.GetSchemeStringLength() == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), L"path/../sub") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"path/../sub") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(u.GetFragStringLength() == 0); + + u = UriType(L"http://auth#frag/stuff"); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0); + EXPECT_TRUE(StrCmp(u.GetAuthString(), L"//auth") == 0); + EXPECT_TRUE(u.GetPathStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http://auth") == 0); + EXPECT_TRUE(u.GetQueryStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag/stuff") == 0); + EXPECT_TRUE(StrCmp(u.GetString(), L"http://auth#frag/stuff") == 0); + + const Value16::Ch c[] = { '#', 'f', 'r', 'a', 'g', '/', 's', 't', 'u', 'f', 'f', '\0'}; + SizeType len = internal::StrLen(c); + u = UriType(c, len); + EXPECT_TRUE(StrCmp(u.GetString(), L"#frag/stuff") == 0); + EXPECT_TRUE(u.GetStringLength() == len); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"") == 0); + EXPECT_TRUE(u.GetBaseStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag/stuff") == 0); + EXPECT_TRUE(u.GetFragStringLength() == len); + + u = UriType(c); + EXPECT_TRUE(StrCmp(u.GetString(), L"#frag/stuff") == 0); + EXPECT_TRUE(u.GetStringLength() == len); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"") == 0); + EXPECT_TRUE(u.GetBaseStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetFragString(), L"#frag/stuff") == 0); + EXPECT_TRUE(u.GetFragStringLength() == len); + + // Incomplete auth treated as path + u = UriType(L"http:/"); + EXPECT_TRUE(StrCmp(u.GetSchemeString(), L"http:") == 0); + EXPECT_TRUE(u.GetAuthStringLength() == 0); + EXPECT_TRUE(StrCmp(u.GetPathString(), L"/") == 0); + EXPECT_TRUE(StrCmp(u.GetBaseString(), L"http:/") == 0); +} + +#if RAPIDJSON_HAS_STDSTRING +TEST(Uri, Parse_Std) { + typedef GenericUri > UriType; + MemoryPoolAllocator allocator; + typedef std::basic_string String; + + String str = "http://auth/path/xxx?query#frag"; + const UriType uri = UriType(str, &allocator); + EXPECT_TRUE(UriType::GetScheme(uri) == "http:"); + EXPECT_TRUE(UriType::GetAuth(uri) == "//auth"); + EXPECT_TRUE(UriType::GetPath(uri) == "/path/xxx"); + EXPECT_TRUE(UriType::GetBase(uri) == "http://auth/path/xxx?query"); + EXPECT_TRUE(UriType::GetQuery(uri) == "?query"); + EXPECT_TRUE(UriType::GetFrag(uri) == "#frag"); + EXPECT_TRUE(UriType::Get(uri) == str); +} + +TEST(Uri, Parse_UTF16_Std) { + typedef GenericValue > Value16; + typedef GenericUri > UriType; + MemoryPoolAllocator allocator; + typedef std::basic_string String; + + String str = L"http://auth/path/xxx?query#frag"; + const UriType uri = UriType(str, &allocator); + EXPECT_TRUE(UriType::GetScheme(uri) == L"http:"); + EXPECT_TRUE(UriType::GetAuth(uri) == L"//auth"); + EXPECT_TRUE(UriType::GetPath(uri) == L"/path/xxx"); + EXPECT_TRUE(UriType::GetBase(uri) == L"http://auth/path/xxx?query"); + EXPECT_TRUE(UriType::GetQuery(uri) == L"?query"); + EXPECT_TRUE(UriType::GetFrag(uri) == L"#frag"); + EXPECT_TRUE(UriType::Get(uri) == str); +} +#endif + +TEST(Uri, CopyConstructor) { + typedef GenericUri UriType; + CrtAllocator allocator; + + UriType u("http://auth/path/xxx?query#frag", &allocator); + UriType u2(u); + EXPECT_TRUE(u == u2); + EXPECT_NE(&u.GetAllocator(), &u2.GetAllocator()); +} + +TEST(Uri, Assignment) { + typedef GenericUri UriType; + CrtAllocator allocator; + + UriType u("http://auth/path/xxx?query#frag", &allocator); + UriType u2; + u2 = u; + EXPECT_TRUE(u == u2); + EXPECT_NE(&u.GetAllocator(), &u2.GetAllocator()); +} + +TEST(Uri, Resolve) { + typedef GenericUri UriType; + CrtAllocator allocator; + + // ref is full uri + UriType base = UriType("http://auth/path/#frag"); + UriType ref = UriType("http://newauth/newpath#newfrag"); + UriType res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://newauth/newpath#newfrag") == 0); + + base = UriType("/path/#frag", &allocator); + ref = UriType("http://newauth/newpath#newfrag", &allocator); + res = ref.Resolve(base, &allocator); + EXPECT_TRUE(StrCmp(res.GetString(), "http://newauth/newpath#newfrag") == 0); + + // ref is alternate uri + base = UriType("http://auth/path/#frag"); + ref = UriType("urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0); + + // ref is absolute path + base = UriType("http://auth/path/#"); + ref = UriType("/newpath#newfrag"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/newpath#newfrag") == 0); + + // ref is relative path + base = UriType("http://auth/path/file.json#frag"); + ref = UriType("newfile.json#"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/path/newfile.json#") == 0); + + base = UriType("http://auth/path/file.json#frag/stuff"); + ref = UriType("newfile.json#newfrag/newstuff"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/path/newfile.json#newfrag/newstuff") == 0); + + base = UriType("file.json", &allocator); + ref = UriType("newfile.json", &base.GetAllocator()); + res = ref.Resolve(base, &ref.GetAllocator()); + EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0); + + base = UriType("file.json", &allocator); + ref = UriType("./newfile.json", &allocator); + res = ref.Resolve(base, &allocator); + EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0); + + base = UriType("file.json"); + ref = UriType("parent/../newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0); + + base = UriType("file.json"); + ref = UriType("parent/./newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "parent/newfile.json") == 0); + + base = UriType("file.json"); + ref = UriType("../../parent/.././newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "newfile.json") == 0); + + // This adds a joining slash so resolved length is base length + ref length + 1 + base = UriType("http://auth"); + ref = UriType("newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://auth/newfile.json") == 0); + + // ref is fragment + base = UriType("#frag/stuff"); + ref = UriType("#newfrag/newstuff"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "#newfrag/newstuff") == 0); + + // test ref fragment always wins + base = UriType("/path#frag"); + ref = UriType(""); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "/path") == 0); + + // Examples from RFC3896 + base = UriType("http://a/b/c/d;p?q"); + ref = UriType("g:h"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "g:h") == 0); + ref = UriType("g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g") == 0); + ref = UriType("./g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g") == 0); + ref = UriType("g/"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g/") == 0); + ref = UriType("/g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0); + ref = UriType("//g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://g") == 0); + ref = UriType("?y"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/d;p?y") == 0); + ref = UriType("g?y"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g?y") == 0); + ref = UriType("#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/d;p?q#s") == 0); + ref = UriType("g#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g#s") == 0); + ref = UriType("g?y#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g?y#s") == 0); + ref = UriType(";x"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/;x") == 0); + ref = UriType("g;x"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g;x") == 0); + ref = UriType("g;x?y#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g;x?y#s") == 0); + ref = UriType(""); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/d;p?q") == 0); + ref = UriType("."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/") == 0); + ref = UriType("./"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/") == 0); + ref = UriType(".."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/") == 0); + ref = UriType("../"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/") == 0); + ref = UriType("../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/g") == 0); + ref = UriType("../.."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/") == 0); + ref = UriType("../../"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/") == 0); + ref = UriType("../../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0); + ref = UriType("../../../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0); + ref = UriType("../../../../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0); + ref = UriType("/./g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0); + ref = UriType("/../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/g") == 0); + ref = UriType("g."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g.") == 0); + ref = UriType(".g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/.g") == 0); + ref = UriType("g.."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g..") == 0); + ref = UriType("..g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/..g") == 0); + ref = UriType("g#s/../x"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://a/b/c/g#s/../x") == 0); +} + +TEST(Uri, Resolve_UTF16) { + typedef GenericValue > Value16; + typedef GenericUri UriType; + CrtAllocator allocator; + + // ref is full uri + UriType base = UriType(L"http://auth/path/#frag"); + UriType ref = UriType(L"http://newauth/newpath#newfrag"); + UriType res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://newauth/newpath#newfrag") == 0); + + base = UriType(L"/path/#frag"); + ref = UriType(L"http://newauth/newpath#newfrag"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://newauth/newpath#newfrag") == 0); + + // ref is alternate uri + base = UriType(L"http://auth/path/#frag"); + ref = UriType(L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f") == 0); + + // ref is absolute path + base = UriType(L"http://auth/path/#"); + ref = UriType(L"/newpath#newfrag"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/newpath#newfrag") == 0); + + // ref is relative path + base = UriType(L"http://auth/path/file.json#frag"); + ref = UriType(L"newfile.json#"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/path/newfile.json#") == 0); + + base = UriType(L"http://auth/path/file.json#frag/stuff"); + ref = UriType(L"newfile.json#newfrag/newstuff"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/path/newfile.json#newfrag/newstuff") == 0); + + base = UriType(L"file.json", &allocator); + ref = UriType(L"newfile.json", &base.GetAllocator()); + res = ref.Resolve(base, &ref.GetAllocator()); + EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0); + + base = UriType(L"file.json", &allocator); + ref = UriType(L"./newfile.json", &allocator); + res = ref.Resolve(base, &allocator); + EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0); + + base = UriType(L"file.json"); + ref = UriType(L"parent/../newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0); + + base = UriType(L"file.json"); + ref = UriType(L"parent/./newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"parent/newfile.json") == 0); + + base = UriType(L"file.json"); + ref = UriType(L"../../parent/.././newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"newfile.json") == 0); + + // This adds a joining slash so resolved length is base length + ref length + 1 + base = UriType(L"http://auth"); + ref = UriType(L"newfile.json"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://auth/newfile.json") == 0); + + // ref is fragment + base = UriType(L"#frag/stuff"); + ref = UriType(L"#newfrag/newstuff"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"#newfrag/newstuff") == 0); + + // test ref fragment always wins + base = UriType(L"/path#frag"); + ref = UriType(L""); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"/path") == 0); + + // Examples from RFC3896 + base = UriType(L"http://a/b/c/d;p?q"); + ref = UriType(L"g:h"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"g:h") == 0); + ref = UriType(L"g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g") == 0); + ref = UriType(L"./g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g") == 0); + ref = UriType(L"g/"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g/") == 0); + ref = UriType(L"/g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0); + ref = UriType(L"//g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://g") == 0); + ref = UriType(L"?y"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/d;p?y") == 0); + ref = UriType(L"g?y"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g?y") == 0); + ref = UriType(L"#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/d;p?q#s") == 0); + ref = UriType(L"g#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g#s") == 0); + ref = UriType(L"g?y#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g?y#s") == 0); + ref = UriType(L";x"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/;x") == 0); + ref = UriType(L"g;x"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g;x") == 0); + ref = UriType(L"g;x?y#s"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g;x?y#s") == 0); + ref = UriType(L""); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/d;p?q") == 0); + ref = UriType(L"."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/") == 0); + ref = UriType(L"./"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/") == 0); + ref = UriType(L".."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/") == 0); + ref = UriType(L"../"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/") == 0); + ref = UriType(L"../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/g") == 0); + ref = UriType(L"../.."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/") == 0); + ref = UriType(L"../../"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/") == 0); + ref = UriType(L"../../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0); + ref = UriType(L"../../../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0); + ref = UriType(L"../../../../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0); + ref = UriType(L"/./g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0); + ref = UriType(L"/../g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/g") == 0); + ref = UriType(L"g."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g.") == 0); + ref = UriType(L".g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/.g") == 0); + ref = UriType(L"g.."); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g..") == 0); + ref = UriType(L"..g"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/..g") == 0); + ref = UriType(L"g#s/../x"); + res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g#s/../x") == 0); +} + +TEST(Uri, Equals) { + typedef GenericUri UriType; + + UriType a = UriType("http://a/a#a"); + UriType b = UriType("http://a/a#b"); + UriType c = a; + + EXPECT_TRUE(a == a); + EXPECT_TRUE(a == c); + EXPECT_TRUE(a != b); +} + +TEST(Uri, Match) { + typedef GenericUri UriType; + + UriType a = UriType("http://a/a#a"); + UriType b = UriType("http://a/a#b"); + UriType c = a; + UriType d; + + EXPECT_TRUE(a.Match(a)); + EXPECT_TRUE(a.Match(c)); + EXPECT_FALSE(a.Match(b)); + EXPECT_FALSE(a.Match(b, true)); + EXPECT_TRUE(a.Match(b, false)); // Base Uri same + EXPECT_FALSE(a.Match(d)); + EXPECT_FALSE(d.Match(a)); +} + +TEST(Uri, Issue1899) { + typedef GenericUri > UriType; + + UriType base = UriType("http://auth/path/#frag"); + UriType ref = UriType("http://newauth/newpath#newfrag"); + UriType res = ref.Resolve(base); + EXPECT_TRUE(StrCmp(res.GetString(), "http://newauth/newpath#newfrag") == 0); +} + +#if defined(_MSC_VER) || defined(__clang__) +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/valuetest.cpp b/deps/rapidjson/test/unittest/valuetest.cpp new file mode 100644 index 0000000..13ae1d4 --- /dev/null +++ b/deps/rapidjson/test/unittest/valuetest.cpp @@ -0,0 +1,1861 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" +#include "rapidjson/document.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +using namespace rapidjson; + +TEST(Value, Size) { + if (sizeof(SizeType) == 4) { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + EXPECT_EQ(16u, sizeof(Value)); +#elif RAPIDJSON_64BIT + EXPECT_EQ(24u, sizeof(Value)); +#else + EXPECT_EQ(16u, sizeof(Value)); +#endif + } +} + +TEST(Value, DefaultConstructor) { + Value x; + EXPECT_EQ(kNullType, x.GetType()); + EXPECT_TRUE(x.IsNull()); + + //std::cout << "sizeof(Value): " << sizeof(x) << std::endl; +} + +// Should not pass compilation +//TEST(Value, copy_constructor) { +// Value x(1234); +// Value y = x; +//} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + +#if 0 // Many old compiler does not support these. Turn it off temporaily. + +#include + +TEST(Value, Traits) { + typedef GenericValue, CrtAllocator> Value; + static_assert(std::is_constructible::value, ""); + static_assert(std::is_default_constructible::value, ""); +#ifndef _MSC_VER + static_assert(!std::is_copy_constructible::value, ""); +#endif + static_assert(std::is_move_constructible::value, ""); + +#ifndef _MSC_VER + static_assert(std::is_nothrow_constructible::value, ""); + static_assert(std::is_nothrow_default_constructible::value, ""); + static_assert(!std::is_nothrow_copy_constructible::value, ""); + static_assert(std::is_nothrow_move_constructible::value, ""); +#endif + + static_assert(std::is_assignable::value, ""); +#ifndef _MSC_VER + static_assert(!std::is_copy_assignable::value, ""); +#endif + static_assert(std::is_move_assignable::value, ""); + +#ifndef _MSC_VER + static_assert(std::is_nothrow_assignable::value, ""); +#endif + static_assert(!std::is_nothrow_copy_assignable::value, ""); +#ifndef _MSC_VER + static_assert(std::is_nothrow_move_assignable::value, ""); +#endif + + static_assert(std::is_destructible::value, ""); +#ifndef _MSC_VER + static_assert(std::is_nothrow_destructible::value, ""); +#endif +} + +#endif + +TEST(Value, MoveConstructor) { + typedef GenericValue, CrtAllocator> V; + V::AllocatorType allocator; + + V x((V(kArrayType))); + x.Reserve(4u, allocator); + x.PushBack(1, allocator).PushBack(2, allocator).PushBack(3, allocator).PushBack(4, allocator); + EXPECT_TRUE(x.IsArray()); + EXPECT_EQ(4u, x.Size()); + + // Value y(x); // does not compile (!is_copy_constructible) + V y(std::move(x)); + EXPECT_TRUE(x.IsNull()); + EXPECT_TRUE(y.IsArray()); + EXPECT_EQ(4u, y.Size()); + + // Value z = y; // does not compile (!is_copy_assignable) + V z = std::move(y); + EXPECT_TRUE(y.IsNull()); + EXPECT_TRUE(z.IsArray()); + EXPECT_EQ(4u, z.Size()); +} + +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + +TEST(Value, AssignmentOperator) { + Value x(1234); + Value y; + y = x; + EXPECT_TRUE(x.IsNull()); // move semantic + EXPECT_EQ(1234, y.GetInt()); + + y = 5678; + EXPECT_TRUE(y.IsInt()); + EXPECT_EQ(5678, y.GetInt()); + + x = "Hello"; + EXPECT_TRUE(x.IsString()); + EXPECT_STREQ(x.GetString(),"Hello"); + + y = StringRef(x.GetString(),x.GetStringLength()); + EXPECT_TRUE(y.IsString()); + EXPECT_EQ(y.GetString(),x.GetString()); + EXPECT_EQ(y.GetStringLength(),x.GetStringLength()); + + static char mstr[] = "mutable"; + // y = mstr; // should not compile + y = StringRef(mstr); + EXPECT_TRUE(y.IsString()); + EXPECT_EQ(y.GetString(),mstr); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + // C++11 move assignment + x = Value("World"); + EXPECT_TRUE(x.IsString()); + EXPECT_STREQ("World", x.GetString()); + + x = std::move(y); + EXPECT_TRUE(y.IsNull()); + EXPECT_TRUE(x.IsString()); + EXPECT_EQ(x.GetString(), mstr); + + y = std::move(Value().SetInt(1234)); + EXPECT_TRUE(y.IsInt()); + EXPECT_EQ(1234, y); +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS +} + +template +void TestEqual(const A& a, const B& b) { + EXPECT_TRUE (a == b); + EXPECT_FALSE(a != b); + EXPECT_TRUE (b == a); + EXPECT_FALSE(b != a); +} + +template +void TestUnequal(const A& a, const B& b) { + EXPECT_FALSE(a == b); + EXPECT_TRUE (a != b); + EXPECT_FALSE(b == a); + EXPECT_TRUE (b != a); +} + +TEST(Value, EqualtoOperator) { + Value::AllocatorType allocator; + Value x(kObjectType); + x.AddMember("hello", "world", allocator) + .AddMember("t", Value(true).Move(), allocator) + .AddMember("f", Value(false).Move(), allocator) + .AddMember("n", Value(kNullType).Move(), allocator) + .AddMember("i", 123, allocator) + .AddMember("pi", 3.14, allocator) + .AddMember("a", Value(kArrayType).Move().PushBack(1, allocator).PushBack(2, allocator).PushBack(3, allocator), allocator); + + // Test templated operator==() and operator!=() + TestEqual(x["hello"], "world"); + const char* cc = "world"; + TestEqual(x["hello"], cc); + char* c = strdup("world"); + TestEqual(x["hello"], c); + free(c); + + TestEqual(x["t"], true); + TestEqual(x["f"], false); + TestEqual(x["i"], 123); + TestEqual(x["pi"], 3.14); + + // Test operator==() (including different allocators) + CrtAllocator crtAllocator; + GenericValue, CrtAllocator> y; + GenericDocument, CrtAllocator> z(&crtAllocator); + y.CopyFrom(x, crtAllocator); + z.CopyFrom(y, z.GetAllocator()); + TestEqual(x, y); + TestEqual(y, z); + TestEqual(z, x); + + // Swapping member order should be fine. + EXPECT_TRUE(y.RemoveMember("t")); + TestUnequal(x, y); + TestUnequal(z, y); + EXPECT_TRUE(z.RemoveMember("t")); + TestUnequal(x, z); + TestEqual(y, z); + y.AddMember("t", false, crtAllocator); + z.AddMember("t", false, z.GetAllocator()); + TestUnequal(x, y); + TestUnequal(z, x); + y["t"] = true; + z["t"] = true; + TestEqual(x, y); + TestEqual(y, z); + TestEqual(z, x); + + // Swapping element order is not OK + x["a"][0].Swap(x["a"][1]); + TestUnequal(x, y); + x["a"][0].Swap(x["a"][1]); + TestEqual(x, y); + + // Array of different size + x["a"].PushBack(4, allocator); + TestUnequal(x, y); + x["a"].PopBack(); + TestEqual(x, y); + + // Issue #129: compare Uint64 + x.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFF0)); + y.SetUint64(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)); + TestUnequal(x, y); +} + +template +void TestCopyFrom() { + typename Value::AllocatorType a; + Value v1(1234); + Value v2(v1, a); // deep copy constructor + EXPECT_TRUE(v1.GetType() == v2.GetType()); + EXPECT_EQ(v1.GetInt(), v2.GetInt()); + + v1.SetString("foo"); + v2.CopyFrom(v1, a); + EXPECT_TRUE(v1.GetType() == v2.GetType()); + EXPECT_STREQ(v1.GetString(), v2.GetString()); + EXPECT_EQ(v1.GetString(), v2.GetString()); // string NOT copied + + v1.SetString("bar", a); // copy string + v2.CopyFrom(v1, a); + EXPECT_TRUE(v1.GetType() == v2.GetType()); + EXPECT_STREQ(v1.GetString(), v2.GetString()); + EXPECT_NE(v1.GetString(), v2.GetString()); // string copied + + + v1.SetArray().PushBack(1234, a); + v2.CopyFrom(v1, a); + EXPECT_TRUE(v2.IsArray()); + EXPECT_EQ(v1.Size(), v2.Size()); + + v1.PushBack(Value().SetString("foo", a), a); // push string copy + EXPECT_TRUE(v1.Size() != v2.Size()); + v2.CopyFrom(v1, a); + EXPECT_TRUE(v1.Size() == v2.Size()); + EXPECT_STREQ(v1[1].GetString(), v2[1].GetString()); + EXPECT_NE(v1[1].GetString(), v2[1].GetString()); // string got copied +} + +TEST(Value, CopyFrom) { + TestCopyFrom(); + TestCopyFrom, CrtAllocator> >(); +} + +TEST(Value, Swap) { + Value v1(1234); + Value v2(kObjectType); + + EXPECT_EQ(&v1, &v1.Swap(v2)); + EXPECT_TRUE(v1.IsObject()); + EXPECT_TRUE(v2.IsInt()); + EXPECT_EQ(1234, v2.GetInt()); + + // testing std::swap compatibility + using std::swap; + swap(v1, v2); + EXPECT_TRUE(v1.IsInt()); + EXPECT_TRUE(v2.IsObject()); +} + +TEST(Value, Null) { + // Default constructor + Value x; + EXPECT_EQ(kNullType, x.GetType()); + EXPECT_TRUE(x.IsNull()); + + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsNumber()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + // Constructor with type + Value y(kNullType); + EXPECT_TRUE(y.IsNull()); + + // SetNull(); + Value z(true); + z.SetNull(); + EXPECT_TRUE(z.IsNull()); +} + +TEST(Value, True) { + // Constructor with bool + Value x(true); + EXPECT_EQ(kTrueType, x.GetType()); + EXPECT_TRUE(x.GetBool()); + EXPECT_TRUE(x.IsBool()); + EXPECT_TRUE(x.IsTrue()); + + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsNumber()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + // Constructor with type + Value y(kTrueType); + EXPECT_TRUE(y.IsTrue()); + + // SetBool() + Value z; + z.SetBool(true); + EXPECT_TRUE(z.IsTrue()); + + // Templated functions + EXPECT_TRUE(z.Is()); + EXPECT_TRUE(z.Get()); + EXPECT_FALSE(z.Set(false).Get()); + EXPECT_TRUE(z.Set(true).Get()); +} + +TEST(Value, False) { + // Constructor with bool + Value x(false); + EXPECT_EQ(kFalseType, x.GetType()); + EXPECT_TRUE(x.IsBool()); + EXPECT_TRUE(x.IsFalse()); + + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.GetBool()); + //EXPECT_FALSE((bool)x); + EXPECT_FALSE(x.IsNumber()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + // Constructor with type + Value y(kFalseType); + EXPECT_TRUE(y.IsFalse()); + + // SetBool() + Value z; + z.SetBool(false); + EXPECT_TRUE(z.IsFalse()); +} + +TEST(Value, Int) { + // Constructor with int + Value x(1234); + EXPECT_EQ(kNumberType, x.GetType()); + EXPECT_EQ(1234, x.GetInt()); + EXPECT_EQ(1234u, x.GetUint()); + EXPECT_EQ(1234, x.GetInt64()); + EXPECT_EQ(1234u, x.GetUint64()); + EXPECT_NEAR(1234.0, x.GetDouble(), 0.0); + //EXPECT_EQ(1234, (int)x); + //EXPECT_EQ(1234, (unsigned)x); + //EXPECT_EQ(1234, (int64_t)x); + //EXPECT_EQ(1234, (uint64_t)x); + //EXPECT_EQ(1234, (double)x); + EXPECT_TRUE(x.IsNumber()); + EXPECT_TRUE(x.IsInt()); + EXPECT_TRUE(x.IsUint()); + EXPECT_TRUE(x.IsInt64()); + EXPECT_TRUE(x.IsUint64()); + + EXPECT_FALSE(x.IsDouble()); + EXPECT_FALSE(x.IsFloat()); + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + Value nx(-1234); + EXPECT_EQ(-1234, nx.GetInt()); + EXPECT_EQ(-1234, nx.GetInt64()); + EXPECT_TRUE(nx.IsInt()); + EXPECT_TRUE(nx.IsInt64()); + EXPECT_FALSE(nx.IsUint()); + EXPECT_FALSE(nx.IsUint64()); + + // Constructor with type + Value y(kNumberType); + EXPECT_TRUE(y.IsNumber()); + EXPECT_TRUE(y.IsInt()); + EXPECT_EQ(0, y.GetInt()); + + // SetInt() + Value z; + z.SetInt(1234); + EXPECT_EQ(1234, z.GetInt()); + + // operator=(int) + z = 5678; + EXPECT_EQ(5678, z.GetInt()); + + // Templated functions + EXPECT_TRUE(z.Is()); + EXPECT_EQ(5678, z.Get()); + EXPECT_EQ(5679, z.Set(5679).Get()); + EXPECT_EQ(5680, z.Set(5680).Get()); + +#ifdef _MSC_VER + // long as int on MSC platforms + RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int)); + z.SetInt(2222); + EXPECT_TRUE(z.Is()); + EXPECT_EQ(2222l, z.Get()); + EXPECT_EQ(3333l, z.Set(3333l).Get()); + EXPECT_EQ(4444l, z.Set(4444l).Get()); + EXPECT_TRUE(z.IsInt()); +#endif +} + +TEST(Value, Uint) { + // Constructor with int + Value x(1234u); + EXPECT_EQ(kNumberType, x.GetType()); + EXPECT_EQ(1234, x.GetInt()); + EXPECT_EQ(1234u, x.GetUint()); + EXPECT_EQ(1234, x.GetInt64()); + EXPECT_EQ(1234u, x.GetUint64()); + EXPECT_TRUE(x.IsNumber()); + EXPECT_TRUE(x.IsInt()); + EXPECT_TRUE(x.IsUint()); + EXPECT_TRUE(x.IsInt64()); + EXPECT_TRUE(x.IsUint64()); + EXPECT_NEAR(1234.0, x.GetDouble(), 0.0); // Number can always be cast as double but !IsDouble(). + + EXPECT_FALSE(x.IsDouble()); + EXPECT_FALSE(x.IsFloat()); + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + // SetUint() + Value z; + z.SetUint(1234); + EXPECT_EQ(1234u, z.GetUint()); + + // operator=(unsigned) + z = 5678u; + EXPECT_EQ(5678u, z.GetUint()); + + z = 2147483648u; // 2^31, cannot cast as int + EXPECT_EQ(2147483648u, z.GetUint()); + EXPECT_FALSE(z.IsInt()); + EXPECT_TRUE(z.IsInt64()); // Issue 41: Incorrect parsing of unsigned int number types + + // Templated functions + EXPECT_TRUE(z.Is()); + EXPECT_EQ(2147483648u, z.Get()); + EXPECT_EQ(2147483649u, z.Set(2147483649u).Get()); + EXPECT_EQ(2147483650u, z.Set(2147483650u).Get()); + +#ifdef _MSC_VER + // unsigned long as unsigned on MSC platforms + RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned)); + z.SetUint(2222); + EXPECT_TRUE(z.Is()); + EXPECT_EQ(2222ul, z.Get()); + EXPECT_EQ(3333ul, z.Set(3333ul).Get()); + EXPECT_EQ(4444ul, z.Set(4444ul).Get()); + EXPECT_TRUE(x.IsUint()); +#endif +} + +TEST(Value, Int64) { + // Constructor with int + Value x(int64_t(1234)); + EXPECT_EQ(kNumberType, x.GetType()); + EXPECT_EQ(1234, x.GetInt()); + EXPECT_EQ(1234u, x.GetUint()); + EXPECT_EQ(1234, x.GetInt64()); + EXPECT_EQ(1234u, x.GetUint64()); + EXPECT_TRUE(x.IsNumber()); + EXPECT_TRUE(x.IsInt()); + EXPECT_TRUE(x.IsUint()); + EXPECT_TRUE(x.IsInt64()); + EXPECT_TRUE(x.IsUint64()); + + EXPECT_FALSE(x.IsDouble()); + EXPECT_FALSE(x.IsFloat()); + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + Value nx(int64_t(-1234)); + EXPECT_EQ(-1234, nx.GetInt()); + EXPECT_EQ(-1234, nx.GetInt64()); + EXPECT_TRUE(nx.IsInt()); + EXPECT_TRUE(nx.IsInt64()); + EXPECT_FALSE(nx.IsUint()); + EXPECT_FALSE(nx.IsUint64()); + + // SetInt64() + Value z; + z.SetInt64(1234); + EXPECT_EQ(1234, z.GetInt64()); + + z.SetInt64(2147483648u); // 2^31, cannot cast as int + EXPECT_FALSE(z.IsInt()); + EXPECT_TRUE(z.IsUint()); + EXPECT_NEAR(2147483648.0, z.GetDouble(), 0.0); + + z.SetInt64(int64_t(4294967295u) + 1); // 2^32, cannot cast as uint + EXPECT_FALSE(z.IsInt()); + EXPECT_FALSE(z.IsUint()); + EXPECT_NEAR(4294967296.0, z.GetDouble(), 0.0); + + z.SetInt64(-int64_t(2147483648u) - 1); // -2^31-1, cannot cast as int + EXPECT_FALSE(z.IsInt()); + EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0); + + int64_t i = static_cast(RAPIDJSON_UINT64_C2(0x80000000, 00000000)); + z.SetInt64(i); + EXPECT_DOUBLE_EQ(-9223372036854775808.0, z.GetDouble()); + + // Templated functions + EXPECT_TRUE(z.Is()); + EXPECT_EQ(i, z.Get()); +#if 0 // signed integer underflow is undefined behaviour + EXPECT_EQ(i - 1, z.Set(i - 1).Get()); + EXPECT_EQ(i - 2, z.Set(i - 2).Get()); +#endif +} + +TEST(Value, Uint64) { + // Constructor with int + Value x(uint64_t(1234)); + EXPECT_EQ(kNumberType, x.GetType()); + EXPECT_EQ(1234, x.GetInt()); + EXPECT_EQ(1234u, x.GetUint()); + EXPECT_EQ(1234, x.GetInt64()); + EXPECT_EQ(1234u, x.GetUint64()); + EXPECT_TRUE(x.IsNumber()); + EXPECT_TRUE(x.IsInt()); + EXPECT_TRUE(x.IsUint()); + EXPECT_TRUE(x.IsInt64()); + EXPECT_TRUE(x.IsUint64()); + + EXPECT_FALSE(x.IsDouble()); + EXPECT_FALSE(x.IsFloat()); + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + // SetUint64() + Value z; + z.SetUint64(1234); + EXPECT_EQ(1234u, z.GetUint64()); + + z.SetUint64(uint64_t(2147483648u)); // 2^31, cannot cast as int + EXPECT_FALSE(z.IsInt()); + EXPECT_TRUE(z.IsUint()); + EXPECT_TRUE(z.IsInt64()); + + z.SetUint64(uint64_t(4294967295u) + 1); // 2^32, cannot cast as uint + EXPECT_FALSE(z.IsInt()); + EXPECT_FALSE(z.IsUint()); + EXPECT_TRUE(z.IsInt64()); + + uint64_t u = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); + z.SetUint64(u); // 2^63 cannot cast as int64 + EXPECT_FALSE(z.IsInt64()); + EXPECT_EQ(u, z.GetUint64()); // Issue 48 + EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble()); + + // Templated functions + EXPECT_TRUE(z.Is()); + EXPECT_EQ(u, z.Get()); + EXPECT_EQ(u + 1, z.Set(u + 1).Get()); + EXPECT_EQ(u + 2, z.Set(u + 2).Get()); +} + +TEST(Value, Double) { + // Constructor with double + Value x(12.34); + EXPECT_EQ(kNumberType, x.GetType()); + EXPECT_NEAR(12.34, x.GetDouble(), 0.0); + EXPECT_TRUE(x.IsNumber()); + EXPECT_TRUE(x.IsDouble()); + + EXPECT_FALSE(x.IsInt()); + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + // SetDouble() + Value z; + z.SetDouble(12.34); + EXPECT_NEAR(12.34, z.GetDouble(), 0.0); + + z = 56.78; + EXPECT_NEAR(56.78, z.GetDouble(), 0.0); + + // Templated functions + EXPECT_TRUE(z.Is()); + EXPECT_EQ(56.78, z.Get()); + EXPECT_EQ(57.78, z.Set(57.78).Get()); + EXPECT_EQ(58.78, z.Set(58.78).Get()); +} + +TEST(Value, Float) { + // Constructor with double + Value x(12.34f); + EXPECT_EQ(kNumberType, x.GetType()); + EXPECT_NEAR(12.34f, x.GetFloat(), 0.0); + EXPECT_TRUE(x.IsNumber()); + EXPECT_TRUE(x.IsDouble()); + EXPECT_TRUE(x.IsFloat()); + + EXPECT_FALSE(x.IsInt()); + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + // SetFloat() + Value z; + z.SetFloat(12.34f); + EXPECT_NEAR(12.34f, z.GetFloat(), 0.0f); + + // Issue 573 + z.SetInt(0); + EXPECT_EQ(0.0f, z.GetFloat()); + + z = 56.78f; + EXPECT_NEAR(56.78f, z.GetFloat(), 0.0f); + + // Templated functions + EXPECT_TRUE(z.Is()); + EXPECT_EQ(56.78f, z.Get()); + EXPECT_EQ(57.78f, z.Set(57.78f).Get()); + EXPECT_EQ(58.78f, z.Set(58.78f).Get()); +} + +TEST(Value, IsLosslessDouble) { + EXPECT_TRUE(Value(0.0).IsLosslessDouble()); + EXPECT_TRUE(Value(12.34).IsLosslessDouble()); + EXPECT_TRUE(Value(-123).IsLosslessDouble()); + EXPECT_TRUE(Value(2147483648u).IsLosslessDouble()); + EXPECT_TRUE(Value(-static_cast(RAPIDJSON_UINT64_C2(0x40000000, 0x00000000))).IsLosslessDouble()); +#if !(defined(_MSC_VER) && _MSC_VER < 1800) // VC2010 has problem + EXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000, 0x00000000)).IsLosslessDouble()); +#endif + + EXPECT_FALSE(Value(static_cast(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); // INT64_MAX + EXPECT_FALSE(Value(-static_cast(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble()); // -INT64_MAX + EXPECT_TRUE(Value(-static_cast(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF)) - 1).IsLosslessDouble()); // INT64_MIN + EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble()); // UINT64_MAX + + EXPECT_TRUE(Value(3.4028234e38f).IsLosslessDouble()); // FLT_MAX + EXPECT_TRUE(Value(-3.4028234e38f).IsLosslessDouble()); // -FLT_MAX + EXPECT_TRUE(Value(1.17549435e-38f).IsLosslessDouble()); // FLT_MIN + EXPECT_TRUE(Value(-1.17549435e-38f).IsLosslessDouble()); // -FLT_MIN + EXPECT_TRUE(Value(1.7976931348623157e+308).IsLosslessDouble()); // DBL_MAX + EXPECT_TRUE(Value(-1.7976931348623157e+308).IsLosslessDouble()); // -DBL_MAX + EXPECT_TRUE(Value(2.2250738585072014e-308).IsLosslessDouble()); // DBL_MIN + EXPECT_TRUE(Value(-2.2250738585072014e-308).IsLosslessDouble()); // -DBL_MIN +} + +TEST(Value, IsLosslessFloat) { + EXPECT_TRUE(Value(12.25).IsLosslessFloat()); + EXPECT_TRUE(Value(-123).IsLosslessFloat()); + EXPECT_TRUE(Value(2147483648u).IsLosslessFloat()); + EXPECT_TRUE(Value(3.4028234e38f).IsLosslessFloat()); + EXPECT_TRUE(Value(-3.4028234e38f).IsLosslessFloat()); + EXPECT_FALSE(Value(3.4028235e38).IsLosslessFloat()); + EXPECT_FALSE(Value(0.3).IsLosslessFloat()); +} + +TEST(Value, String) { + // Construction with const string + Value x("Hello", 5); // literal + EXPECT_EQ(kStringType, x.GetType()); + EXPECT_TRUE(x.IsString()); + EXPECT_STREQ("Hello", x.GetString()); + EXPECT_EQ(5u, x.GetStringLength()); + + EXPECT_FALSE(x.IsNumber()); + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsObject()); + EXPECT_FALSE(x.IsArray()); + + static const char cstr[] = "World"; // const array + Value(cstr).Swap(x); + EXPECT_TRUE(x.IsString()); + EXPECT_EQ(x.GetString(), cstr); + EXPECT_EQ(x.GetStringLength(), sizeof(cstr)-1); + + static char mstr[] = "Howdy"; // non-const array + // Value(mstr).Swap(x); // should not compile + Value(StringRef(mstr)).Swap(x); + EXPECT_TRUE(x.IsString()); + EXPECT_EQ(x.GetString(), mstr); + EXPECT_EQ(x.GetStringLength(), sizeof(mstr)-1); + strncpy(mstr,"Hello", sizeof(mstr)); + EXPECT_STREQ(x.GetString(), "Hello"); + + const char* pstr = cstr; + //Value(pstr).Swap(x); // should not compile + Value(StringRef(pstr)).Swap(x); + EXPECT_TRUE(x.IsString()); + EXPECT_EQ(x.GetString(), cstr); + EXPECT_EQ(x.GetStringLength(), sizeof(cstr)-1); + + char* mpstr = mstr; + Value(StringRef(mpstr,sizeof(mstr)-1)).Swap(x); + EXPECT_TRUE(x.IsString()); + EXPECT_EQ(x.GetString(), mstr); + EXPECT_EQ(x.GetStringLength(), 5u); + EXPECT_STREQ(x.GetString(), "Hello"); + + // Constructor with copy string + MemoryPoolAllocator<> allocator; + Value c(x.GetString(), x.GetStringLength(), allocator); + EXPECT_NE(x.GetString(), c.GetString()); + EXPECT_EQ(x.GetStringLength(), c.GetStringLength()); + EXPECT_STREQ(x.GetString(), c.GetString()); + //x.SetString("World"); + x.SetString("World", 5); + EXPECT_STREQ("Hello", c.GetString()); + EXPECT_EQ(5u, c.GetStringLength()); + + // Constructor with type + Value y(kStringType); + EXPECT_TRUE(y.IsString()); + EXPECT_STREQ("", y.GetString()); // Empty string should be "" instead of 0 (issue 226) + EXPECT_EQ(0u, y.GetStringLength()); + + // SetConsttring() + Value z; + z.SetString("Hello"); + EXPECT_TRUE(x.IsString()); + z.SetString("Hello", 5); + EXPECT_STREQ("Hello", z.GetString()); + EXPECT_STREQ("Hello", z.GetString()); + EXPECT_EQ(5u, z.GetStringLength()); + + z.SetString("Hello"); + EXPECT_TRUE(z.IsString()); + EXPECT_STREQ("Hello", z.GetString()); + + //z.SetString(mstr); // should not compile + //z.SetString(pstr); // should not compile + z.SetString(StringRef(mstr)); + EXPECT_TRUE(z.IsString()); + EXPECT_STREQ(z.GetString(), mstr); + + z.SetString(cstr); + EXPECT_TRUE(z.IsString()); + EXPECT_EQ(cstr, z.GetString()); + + z = cstr; + EXPECT_TRUE(z.IsString()); + EXPECT_EQ(cstr, z.GetString()); + + // SetString() + char s[] = "World"; + Value w; + w.SetString(s, static_cast(strlen(s)), allocator); + s[0] = '\0'; + EXPECT_STREQ("World", w.GetString()); + EXPECT_EQ(5u, w.GetStringLength()); + + // templated functions + EXPECT_TRUE(z.Is()); + EXPECT_STREQ(cstr, z.Get()); + EXPECT_STREQ("Apple", z.Set("Apple").Get()); + +#if RAPIDJSON_HAS_STDSTRING + { + std::string str = "Hello World"; + str[5] = '\0'; + EXPECT_STREQ(str.data(),"Hello"); // embedded '\0' + EXPECT_EQ(str.size(), 11u); + + // no copy + Value vs0(StringRef(str)); + EXPECT_TRUE(vs0.IsString()); + EXPECT_EQ(vs0.GetString(), str.data()); + EXPECT_EQ(vs0.GetStringLength(), str.size()); + TestEqual(vs0, str); + + // do copy + Value vs1(str, allocator); + EXPECT_TRUE(vs1.IsString()); + EXPECT_NE(vs1.GetString(), str.data()); + EXPECT_NE(vs1.GetString(), str); // not equal due to embedded '\0' + EXPECT_EQ(vs1.GetStringLength(), str.size()); + TestEqual(vs1, str); + + // SetString + str = "World"; + vs0.SetNull().SetString(str, allocator); + EXPECT_TRUE(vs0.IsString()); + EXPECT_STREQ(vs0.GetString(), str.c_str()); + EXPECT_EQ(vs0.GetStringLength(), str.size()); + TestEqual(str, vs0); + TestUnequal(str, vs1); + + // vs1 = str; // should not compile + vs1 = StringRef(str); + TestEqual(str, vs1); + TestEqual(vs0, vs1); + + // Templated function. + EXPECT_TRUE(vs0.Is()); + EXPECT_EQ(str, vs0.Get()); + vs0.Set(std::string("Apple"), allocator); + EXPECT_EQ(std::string("Apple"), vs0.Get()); + vs0.Set(std::string("Orange"), allocator); + EXPECT_EQ(std::string("Orange"), vs0.Get()); + } +#endif // RAPIDJSON_HAS_STDSTRING +} + +// Issue 226: Value of string type should not point to NULL +TEST(Value, SetStringNull) { + + MemoryPoolAllocator<> allocator; + const char* nullPtr = 0; + { + // Construction with string type creates empty string + Value v(kStringType); + EXPECT_NE(v.GetString(), nullPtr); // non-null string returned + EXPECT_EQ(v.GetStringLength(), 0u); + + // Construction from/setting to null without length not allowed + EXPECT_THROW(Value(StringRef(nullPtr)), AssertException); + EXPECT_THROW(Value(StringRef(nullPtr), allocator), AssertException); + EXPECT_THROW(v.SetString(nullPtr, allocator), AssertException); + + // Non-empty length with null string is not allowed + EXPECT_THROW(v.SetString(nullPtr, 17u), AssertException); + EXPECT_THROW(v.SetString(nullPtr, 42u, allocator), AssertException); + + // Setting to null string with empty length is allowed + v.SetString(nullPtr, 0u); + EXPECT_NE(v.GetString(), nullPtr); // non-null string returned + EXPECT_EQ(v.GetStringLength(), 0u); + + v.SetNull(); + v.SetString(nullPtr, 0u, allocator); + EXPECT_NE(v.GetString(), nullPtr); // non-null string returned + EXPECT_EQ(v.GetStringLength(), 0u); + } + // Construction with null string and empty length is allowed + { + Value v(nullPtr,0u); + EXPECT_NE(v.GetString(), nullPtr); // non-null string returned + EXPECT_EQ(v.GetStringLength(), 0u); + } + { + Value v(nullPtr, 0u, allocator); + EXPECT_NE(v.GetString(), nullPtr); // non-null string returned + EXPECT_EQ(v.GetStringLength(), 0u); + } +} + +template +static void TestArray(T& x, Allocator& allocator) { + const T& y = x; + + // PushBack() + Value v; + x.PushBack(v, allocator); + v.SetBool(true); + x.PushBack(v, allocator); + v.SetBool(false); + x.PushBack(v, allocator); + v.SetInt(123); + x.PushBack(v, allocator); + //x.PushBack((const char*)"foo", allocator); // should not compile + x.PushBack("foo", allocator); + + EXPECT_FALSE(x.Empty()); + EXPECT_EQ(5u, x.Size()); + EXPECT_FALSE(y.Empty()); + EXPECT_EQ(5u, y.Size()); + EXPECT_TRUE(x[SizeType(0)].IsNull()); + EXPECT_TRUE(x[1].IsTrue()); + EXPECT_TRUE(x[2].IsFalse()); + EXPECT_TRUE(x[3].IsInt()); + EXPECT_EQ(123, x[3].GetInt()); + EXPECT_TRUE(y[SizeType(0)].IsNull()); + EXPECT_TRUE(y[1].IsTrue()); + EXPECT_TRUE(y[2].IsFalse()); + EXPECT_TRUE(y[3].IsInt()); + EXPECT_EQ(123, y[3].GetInt()); + EXPECT_TRUE(y[4].IsString()); + EXPECT_STREQ("foo", y[4].GetString()); + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + // PushBack(GenericValue&&, Allocator&); + { + Value y2(kArrayType); + y2.PushBack(Value(true), allocator); + y2.PushBack(std::move(Value(kArrayType).PushBack(Value(1), allocator).PushBack("foo", allocator)), allocator); + EXPECT_EQ(2u, y2.Size()); + EXPECT_TRUE(y2[0].IsTrue()); + EXPECT_TRUE(y2[1].IsArray()); + EXPECT_EQ(2u, y2[1].Size()); + EXPECT_TRUE(y2[1][0].IsInt()); + EXPECT_TRUE(y2[1][1].IsString()); + } +#endif + + // iterator + typename T::ValueIterator itr = x.Begin(); + EXPECT_TRUE(itr != x.End()); + EXPECT_TRUE(itr->IsNull()); + ++itr; + EXPECT_TRUE(itr != x.End()); + EXPECT_TRUE(itr->IsTrue()); + ++itr; + EXPECT_TRUE(itr != x.End()); + EXPECT_TRUE(itr->IsFalse()); + ++itr; + EXPECT_TRUE(itr != x.End()); + EXPECT_TRUE(itr->IsInt()); + EXPECT_EQ(123, itr->GetInt()); + ++itr; + EXPECT_TRUE(itr != x.End()); + EXPECT_TRUE(itr->IsString()); + EXPECT_STREQ("foo", itr->GetString()); + + // const iterator + typename T::ConstValueIterator citr = y.Begin(); + EXPECT_TRUE(citr != y.End()); + EXPECT_TRUE(citr->IsNull()); + ++citr; + EXPECT_TRUE(citr != y.End()); + EXPECT_TRUE(citr->IsTrue()); + ++citr; + EXPECT_TRUE(citr != y.End()); + EXPECT_TRUE(citr->IsFalse()); + ++citr; + EXPECT_TRUE(citr != y.End()); + EXPECT_TRUE(citr->IsInt()); + EXPECT_EQ(123, citr->GetInt()); + ++citr; + EXPECT_TRUE(citr != y.End()); + EXPECT_TRUE(citr->IsString()); + EXPECT_STREQ("foo", citr->GetString()); + + // PopBack() + x.PopBack(); + EXPECT_EQ(4u, x.Size()); + EXPECT_TRUE(y[SizeType(0)].IsNull()); + EXPECT_TRUE(y[1].IsTrue()); + EXPECT_TRUE(y[2].IsFalse()); + EXPECT_TRUE(y[3].IsInt()); + + // Clear() + x.Clear(); + EXPECT_TRUE(x.Empty()); + EXPECT_EQ(0u, x.Size()); + EXPECT_TRUE(y.Empty()); + EXPECT_EQ(0u, y.Size()); + + // Erase(ValueIterator) + + // Use array of array to ensure removed elements' destructor is called. + // [[0],[1],[2],...] + for (int i = 0; i < 10; i++) + x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allocator); + + // Erase the first + itr = x.Erase(x.Begin()); + EXPECT_EQ(x.Begin(), itr); + EXPECT_EQ(9u, x.Size()); + for (int i = 0; i < 9; i++) + EXPECT_EQ(i + 1, x[static_cast(i)][0].GetInt()); + + // Ease the last + itr = x.Erase(x.End() - 1); + EXPECT_EQ(x.End(), itr); + EXPECT_EQ(8u, x.Size()); + for (int i = 0; i < 8; i++) + EXPECT_EQ(i + 1, x[static_cast(i)][0].GetInt()); + + // Erase the middle + itr = x.Erase(x.Begin() + 4); + EXPECT_EQ(x.Begin() + 4, itr); + EXPECT_EQ(7u, x.Size()); + for (int i = 0; i < 4; i++) + EXPECT_EQ(i + 1, x[static_cast(i)][0].GetInt()); + for (int i = 4; i < 7; i++) + EXPECT_EQ(i + 2, x[static_cast(i)][0].GetInt()); + + // Erase(ValueIterator, ValueIterator) + // Exhaustive test with all 0 <= first < n, first <= last <= n cases + const unsigned n = 10; + for (unsigned first = 0; first < n; first++) { + for (unsigned last = first; last <= n; last++) { + x.Clear(); + for (unsigned i = 0; i < n; i++) + x.PushBack(Value(kArrayType).PushBack(i, allocator).Move(), allocator); + + itr = x.Erase(x.Begin() + first, x.Begin() + last); + if (last == n) + EXPECT_EQ(x.End(), itr); + else + EXPECT_EQ(x.Begin() + first, itr); + + size_t removeCount = last - first; + EXPECT_EQ(n - removeCount, x.Size()); + for (unsigned i = 0; i < first; i++) + EXPECT_EQ(i, x[i][0].GetUint()); + for (unsigned i = first; i < n - removeCount; i++) + EXPECT_EQ(i + removeCount, x[static_cast(i)][0].GetUint()); + } + } +} + +TEST(Value, Array) { + Value::AllocatorType allocator; + Value x(kArrayType); + const Value& y = x; + + EXPECT_EQ(kArrayType, x.GetType()); + EXPECT_TRUE(x.IsArray()); + EXPECT_TRUE(x.Empty()); + EXPECT_EQ(0u, x.Size()); + EXPECT_TRUE(y.IsArray()); + EXPECT_TRUE(y.Empty()); + EXPECT_EQ(0u, y.Size()); + + EXPECT_FALSE(x.IsNull()); + EXPECT_FALSE(x.IsBool()); + EXPECT_FALSE(x.IsFalse()); + EXPECT_FALSE(x.IsTrue()); + EXPECT_FALSE(x.IsString()); + EXPECT_FALSE(x.IsObject()); + + TestArray(x, allocator); + + // Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed. + // http://en.wikipedia.org/wiki/Erase-remove_idiom + x.Clear(); + for (int i = 0; i < 10; i++) + if (i % 2 == 0) + x.PushBack(i, allocator); + else + x.PushBack(Value(kNullType).Move(), allocator); + + const Value null(kNullType); + x.Erase(std::remove(x.Begin(), x.End(), null), x.End()); + EXPECT_EQ(5u, x.Size()); + for (int i = 0; i < 5; i++) + EXPECT_EQ(i * 2, x[static_cast(i)]); + + // SetArray() + Value z; + z.SetArray(); + EXPECT_TRUE(z.IsArray()); + EXPECT_TRUE(z.Empty()); + + // PR #1503: assign from inner Value + { + CrtAllocator a; // Free() is not a noop + GenericValue, CrtAllocator> nullValue; + GenericValue, CrtAllocator> arrayValue(kArrayType); + arrayValue.PushBack(nullValue, a); + arrayValue = arrayValue[0]; // shouldn't crash (use after free) + EXPECT_TRUE(arrayValue.IsNull()); + } +} + +TEST(Value, ArrayHelper) { + Value::AllocatorType allocator; + { + Value x(kArrayType); + Value::Array a = x.GetArray(); + TestArray(a, allocator); + } + + { + Value x(kArrayType); + Value::Array a = x.GetArray(); + a.PushBack(1, allocator); + + Value::Array a2(a); // copy constructor + EXPECT_EQ(1u, a2.Size()); + + Value::Array a3 = a; + EXPECT_EQ(1u, a3.Size()); + + Value::ConstArray y = static_cast(x).GetArray(); + (void)y; + // y.PushBack(1, allocator); // should not compile + + // Templated functions + x.Clear(); + EXPECT_TRUE(x.Is()); + EXPECT_TRUE(x.Is()); + a.PushBack(1, allocator); + EXPECT_EQ(1, x.Get()[0].GetInt()); + EXPECT_EQ(1, x.Get()[0].GetInt()); + + Value x2; + x2.Set(a); + EXPECT_TRUE(x.IsArray()); // IsArray() is invariant after moving. + EXPECT_EQ(1, x2.Get()[0].GetInt()); + } + + { + Value y(kArrayType); + y.PushBack(123, allocator); + + Value x(y.GetArray()); // Construct value form array. + EXPECT_TRUE(x.IsArray()); + EXPECT_EQ(123, x[0].GetInt()); + EXPECT_TRUE(y.IsArray()); // Invariant + EXPECT_TRUE(y.Empty()); + } + + { + Value x(kArrayType); + Value y(kArrayType); + y.PushBack(123, allocator); + x.PushBack(y.GetArray(), allocator); // Implicit constructor to convert Array to GenericValue + + EXPECT_EQ(1u, x.Size()); + EXPECT_EQ(123, x[0][0].GetInt()); + EXPECT_TRUE(y.IsArray()); + EXPECT_TRUE(y.Empty()); + } +} + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR +TEST(Value, ArrayHelperRangeFor) { + Value::AllocatorType allocator; + Value x(kArrayType); + + for (int i = 0; i < 10; i++) + x.PushBack(i, allocator); + + { + int i = 0; + for (auto& v : x.GetArray()) { + EXPECT_EQ(i, v.GetInt()); + i++; + } + EXPECT_EQ(i, 10); + } + { + int i = 0; + for (const auto& v : const_cast(x).GetArray()) { + EXPECT_EQ(i, v.GetInt()); + i++; + } + EXPECT_EQ(i, 10); + } + + // Array a = x.GetArray(); + // Array ca = const_cast(x).GetArray(); +} +#endif + +template +static void TestObject(T& x, Allocator& allocator) { + const T& y = x; // const version + + // AddMember() + x.AddMember("A", "Apple", allocator); + EXPECT_FALSE(x.ObjectEmpty()); + EXPECT_EQ(1u, x.MemberCount()); + + Value value("Banana", 6); + x.AddMember("B", "Banana", allocator); + EXPECT_EQ(2u, x.MemberCount()); + + // AddMember(StringRefType, T, Allocator) + { + Value o(kObjectType); + o.AddMember("true", true, allocator); + o.AddMember("false", false, allocator); + o.AddMember("int", -1, allocator); + o.AddMember("uint", 1u, allocator); + o.AddMember("int64", int64_t(-4294967296), allocator); + o.AddMember("uint64", uint64_t(4294967296), allocator); + o.AddMember("double", 3.14, allocator); + o.AddMember("string", "Jelly", allocator); + + EXPECT_TRUE(o["true"].GetBool()); + EXPECT_FALSE(o["false"].GetBool()); + EXPECT_EQ(-1, o["int"].GetInt()); + EXPECT_EQ(1u, o["uint"].GetUint()); + EXPECT_EQ(int64_t(-4294967296), o["int64"].GetInt64()); + EXPECT_EQ(uint64_t(4294967296), o["uint64"].GetUint64()); + EXPECT_STREQ("Jelly",o["string"].GetString()); + EXPECT_EQ(8u, o.MemberCount()); + } + + // AddMember(Value&, T, Allocator) + { + Value o(kObjectType); + + Value n("s"); + o.AddMember(n, "string", allocator); + EXPECT_EQ(1u, o.MemberCount()); + + Value count("#"); + o.AddMember(count, o.MemberCount(), allocator); + EXPECT_EQ(2u, o.MemberCount()); + } + +#if RAPIDJSON_HAS_STDSTRING + { + // AddMember(StringRefType, const std::string&, Allocator) + Value o(kObjectType); + o.AddMember("b", std::string("Banana"), allocator); + EXPECT_STREQ("Banana", o["b"].GetString()); + + // RemoveMember(const std::string&) + o.RemoveMember(std::string("b")); + EXPECT_TRUE(o.ObjectEmpty()); + } +#endif + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + // AddMember(GenericValue&&, ...) variants + { + Value o(kObjectType); + o.AddMember(Value("true"), Value(true), allocator); + o.AddMember(Value("false"), Value(false).Move(), allocator); // value is lvalue ref + o.AddMember(Value("int").Move(), Value(-1), allocator); // name is lvalue ref + o.AddMember("uint", std::move(Value().SetUint(1u)), allocator); // name is literal, value is rvalue + EXPECT_TRUE(o["true"].GetBool()); + EXPECT_FALSE(o["false"].GetBool()); + EXPECT_EQ(-1, o["int"].GetInt()); + EXPECT_EQ(1u, o["uint"].GetUint()); + EXPECT_EQ(4u, o.MemberCount()); + } +#endif + + // Tests a member with null character + Value name; + const Value C0D("C\0D", 3); + name.SetString(C0D.GetString(), 3); + value.SetString("CherryD", 7); + x.AddMember(name, value, allocator); + + // HasMember() + EXPECT_TRUE(x.HasMember("A")); + EXPECT_TRUE(x.HasMember("B")); + EXPECT_TRUE(y.HasMember("A")); + EXPECT_TRUE(y.HasMember("B")); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_TRUE(x.HasMember(std::string("A"))); +#endif + + name.SetString("C\0D"); + EXPECT_TRUE(x.HasMember(name)); + EXPECT_TRUE(y.HasMember(name)); + + GenericValue, CrtAllocator> othername("A"); + EXPECT_TRUE(x.HasMember(othername)); + EXPECT_TRUE(y.HasMember(othername)); + othername.SetString("C\0D"); + EXPECT_TRUE(x.HasMember(othername)); + EXPECT_TRUE(y.HasMember(othername)); + + // operator[] + EXPECT_STREQ("Apple", x["A"].GetString()); + EXPECT_STREQ("Banana", x["B"].GetString()); + EXPECT_STREQ("CherryD", x[C0D].GetString()); + EXPECT_STREQ("CherryD", x[othername].GetString()); + EXPECT_THROW(x["nonexist"], AssertException); + + // const operator[] + EXPECT_STREQ("Apple", y["A"].GetString()); + EXPECT_STREQ("Banana", y["B"].GetString()); + EXPECT_STREQ("CherryD", y[C0D].GetString()); + +#if RAPIDJSON_HAS_STDSTRING + EXPECT_STREQ("Apple", x["A"].GetString()); + EXPECT_STREQ("Apple", y[std::string("A")].GetString()); +#endif + + // member iterator + Value::MemberIterator itr = x.MemberBegin(); + EXPECT_TRUE(itr != x.MemberEnd()); + EXPECT_STREQ("A", itr->name.GetString()); + EXPECT_STREQ("Apple", itr->value.GetString()); + ++itr; + EXPECT_TRUE(itr != x.MemberEnd()); + EXPECT_STREQ("B", itr->name.GetString()); + EXPECT_STREQ("Banana", itr->value.GetString()); + ++itr; + EXPECT_TRUE(itr != x.MemberEnd()); + EXPECT_TRUE(memcmp(itr->name.GetString(), "C\0D", 4) == 0); + EXPECT_STREQ("CherryD", itr->value.GetString()); + ++itr; + EXPECT_FALSE(itr != x.MemberEnd()); + + // const member iterator + Value::ConstMemberIterator citr = y.MemberBegin(); + EXPECT_TRUE(citr != y.MemberEnd()); + EXPECT_STREQ("A", citr->name.GetString()); + EXPECT_STREQ("Apple", citr->value.GetString()); + ++citr; + EXPECT_TRUE(citr != y.MemberEnd()); + EXPECT_STREQ("B", citr->name.GetString()); + EXPECT_STREQ("Banana", citr->value.GetString()); + ++citr; + EXPECT_TRUE(citr != y.MemberEnd()); + EXPECT_TRUE(memcmp(citr->name.GetString(), "C\0D", 4) == 0); + EXPECT_STREQ("CherryD", citr->value.GetString()); + ++citr; + EXPECT_FALSE(citr != y.MemberEnd()); + + // member iterator conversions/relations + itr = x.MemberBegin(); + citr = x.MemberBegin(); // const conversion + TestEqual(itr, citr); + EXPECT_TRUE(itr < x.MemberEnd()); + EXPECT_FALSE(itr > y.MemberEnd()); + EXPECT_TRUE(citr < x.MemberEnd()); + EXPECT_FALSE(citr > y.MemberEnd()); + ++citr; + TestUnequal(itr, citr); + EXPECT_FALSE(itr < itr); + EXPECT_TRUE(itr < citr); + EXPECT_FALSE(itr > itr); + EXPECT_TRUE(citr > itr); + EXPECT_EQ(1, citr - x.MemberBegin()); + EXPECT_EQ(0, itr - y.MemberBegin()); + itr += citr - x.MemberBegin(); + EXPECT_EQ(1, itr - y.MemberBegin()); + TestEqual(citr, itr); + EXPECT_TRUE(itr <= citr); + EXPECT_TRUE(citr <= itr); + itr++; + EXPECT_TRUE(itr >= citr); + EXPECT_FALSE(citr >= itr); + + // RemoveMember() + EXPECT_TRUE(x.RemoveMember("A")); + EXPECT_FALSE(x.HasMember("A")); + + EXPECT_TRUE(x.RemoveMember("B")); + EXPECT_FALSE(x.HasMember("B")); + + EXPECT_FALSE(x.RemoveMember("nonexist")); + + EXPECT_TRUE(x.RemoveMember(othername)); + EXPECT_FALSE(x.HasMember(name)); + + EXPECT_TRUE(x.MemberBegin() == x.MemberEnd()); + + // EraseMember(ConstMemberIterator) + + // Use array members to ensure removed elements' destructor is called. + // { "a": [0], "b": [1],[2],...] + const char keys[][2] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" }; + for (int i = 0; i < 10; i++) + x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator); + + // MemberCount, iterator difference + EXPECT_EQ(x.MemberCount(), SizeType(x.MemberEnd() - x.MemberBegin())); + + // Erase the first + itr = x.EraseMember(x.MemberBegin()); + EXPECT_FALSE(x.HasMember(keys[0])); + EXPECT_EQ(x.MemberBegin(), itr); + EXPECT_EQ(9u, x.MemberCount()); + for (; itr != x.MemberEnd(); ++itr) { + size_t i = static_cast((itr - x.MemberBegin())) + 1; + EXPECT_STREQ(itr->name.GetString(), keys[i]); + EXPECT_EQ(static_cast(i), itr->value[0].GetInt()); + } + + // Erase the last + itr = x.EraseMember(x.MemberEnd() - 1); + EXPECT_FALSE(x.HasMember(keys[9])); + EXPECT_EQ(x.MemberEnd(), itr); + EXPECT_EQ(8u, x.MemberCount()); + for (; itr != x.MemberEnd(); ++itr) { + size_t i = static_cast(itr - x.MemberBegin()) + 1; + EXPECT_STREQ(itr->name.GetString(), keys[i]); + EXPECT_EQ(static_cast(i), itr->value[0].GetInt()); + } + + // Erase the middle + itr = x.EraseMember(x.MemberBegin() + 4); + EXPECT_FALSE(x.HasMember(keys[5])); + EXPECT_EQ(x.MemberBegin() + 4, itr); + EXPECT_EQ(7u, x.MemberCount()); + for (; itr != x.MemberEnd(); ++itr) { + size_t i = static_cast(itr - x.MemberBegin()); + i += (i < 4) ? 1 : 2; + EXPECT_STREQ(itr->name.GetString(), keys[i]); + EXPECT_EQ(static_cast(i), itr->value[0].GetInt()); + } + + // EraseMember(ConstMemberIterator, ConstMemberIterator) + // Exhaustive test with all 0 <= first < n, first <= last <= n cases + const unsigned n = 10; + for (unsigned first = 0; first < n; first++) { + for (unsigned last = first; last <= n; last++) { + x.RemoveAllMembers(); + for (unsigned i = 0; i < n; i++) + x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator); + + itr = x.EraseMember(x.MemberBegin() + static_cast(first), x.MemberBegin() + static_cast(last)); + if (last == n) + EXPECT_EQ(x.MemberEnd(), itr); + else + EXPECT_EQ(x.MemberBegin() + static_cast(first), itr); + + size_t removeCount = last - first; + EXPECT_EQ(n - removeCount, x.MemberCount()); + for (unsigned i = 0; i < first; i++) + EXPECT_EQ(i, x[keys[i]][0].GetUint()); + for (unsigned i = first; i < n - removeCount; i++) + EXPECT_EQ(i + removeCount, x[keys[i+removeCount]][0].GetUint()); + } + } + + // RemoveAllMembers() + x.RemoveAllMembers(); + EXPECT_TRUE(x.ObjectEmpty()); + EXPECT_EQ(0u, x.MemberCount()); +} + +TEST(Value, Object) { + Value::AllocatorType allocator; + Value x(kObjectType); + const Value& y = x; // const version + + EXPECT_EQ(kObjectType, x.GetType()); + EXPECT_TRUE(x.IsObject()); + EXPECT_TRUE(x.ObjectEmpty()); + EXPECT_EQ(0u, x.MemberCount()); + EXPECT_EQ(kObjectType, y.GetType()); + EXPECT_TRUE(y.IsObject()); + EXPECT_TRUE(y.ObjectEmpty()); + EXPECT_EQ(0u, y.MemberCount()); + + TestObject(x, allocator); + + // SetObject() + Value z; + z.SetObject(); + EXPECT_TRUE(z.IsObject()); +} + +TEST(Value, ObjectHelper) { + Value::AllocatorType allocator; + { + Value x(kObjectType); + Value::Object o = x.GetObject(); + TestObject(o, allocator); + } + + { + Value x(kObjectType); + Value::Object o = x.GetObject(); + o.AddMember("1", 1, allocator); + + Value::Object o2(o); // copy constructor + EXPECT_EQ(1u, o2.MemberCount()); + + Value::Object o3 = o; + EXPECT_EQ(1u, o3.MemberCount()); + + Value::ConstObject y = static_cast(x).GetObject(); + (void)y; + // y.AddMember("1", 1, allocator); // should not compile + + // Templated functions + x.RemoveAllMembers(); + EXPECT_TRUE(x.Is()); + EXPECT_TRUE(x.Is()); + o.AddMember("1", 1, allocator); + EXPECT_EQ(1, x.Get()["1"].GetInt()); + EXPECT_EQ(1, x.Get()["1"].GetInt()); + + Value x2; + x2.Set(o); + EXPECT_TRUE(x.IsObject()); // IsObject() is invariant after moving + EXPECT_EQ(1, x2.Get()["1"].GetInt()); + } + + { + Value x(kObjectType); + x.AddMember("a", "apple", allocator); + Value y(x.GetObject()); + EXPECT_STREQ("apple", y["a"].GetString()); + EXPECT_TRUE(x.IsObject()); // Invariant + } + + { + Value x(kObjectType); + x.AddMember("a", "apple", allocator); + Value y(kObjectType); + y.AddMember("fruits", x.GetObject(), allocator); + EXPECT_STREQ("apple", y["fruits"]["a"].GetString()); + EXPECT_TRUE(x.IsObject()); // Invariant + } +} + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR +TEST(Value, ObjectHelperRangeFor) { + Value::AllocatorType allocator; + Value x(kObjectType); + + for (int i = 0; i < 10; i++) { + char name[10]; + Value n(name, static_cast(sprintf(name, "%d", i)), allocator); + x.AddMember(n, i, allocator); + } + + { + int i = 0; + for (auto& m : x.GetObject()) { + char name[11]; + sprintf(name, "%d", i); + EXPECT_STREQ(name, m.name.GetString()); + EXPECT_EQ(i, m.value.GetInt()); + i++; + } + EXPECT_EQ(i, 10); + } + { + int i = 0; + for (const auto& m : const_cast(x).GetObject()) { + char name[11]; + sprintf(name, "%d", i); + EXPECT_STREQ(name, m.name.GetString()); + EXPECT_EQ(i, m.value.GetInt()); + i++; + } + EXPECT_EQ(i, 10); + } + + // Object a = x.GetObject(); + // Object ca = const_cast(x).GetObject(); +} +#endif + +TEST(Value, EraseMember_String) { + Value::AllocatorType allocator; + Value x(kObjectType); + x.AddMember("A", "Apple", allocator); + x.AddMember("B", "Banana", allocator); + + EXPECT_TRUE(x.EraseMember("B")); + EXPECT_FALSE(x.HasMember("B")); + + EXPECT_FALSE(x.EraseMember("nonexist")); + + GenericValue, CrtAllocator> othername("A"); + EXPECT_TRUE(x.EraseMember(othername)); + EXPECT_FALSE(x.HasMember("A")); + + EXPECT_TRUE(x.MemberBegin() == x.MemberEnd()); +} + +TEST(Value, BigNestedArray) { + MemoryPoolAllocator<> allocator; + Value x(kArrayType); + static const SizeType n = 200; + + for (SizeType i = 0; i < n; i++) { + Value y(kArrayType); + for (SizeType j = 0; j < n; j++) { + Value number(static_cast(i * n + j)); + y.PushBack(number, allocator); + } + x.PushBack(y, allocator); + } + + for (SizeType i = 0; i < n; i++) + for (SizeType j = 0; j < n; j++) { + EXPECT_TRUE(x[i][j].IsInt()); + EXPECT_EQ(static_cast(i * n + j), x[i][j].GetInt()); + } +} + +TEST(Value, BigNestedObject) { + MemoryPoolAllocator<> allocator; + Value x(kObjectType); + static const SizeType n = 200; + + for (SizeType i = 0; i < n; i++) { + char name1[10]; + sprintf(name1, "%d", i); + + // Value name(name1); // should not compile + Value name(name1, static_cast(strlen(name1)), allocator); + Value object(kObjectType); + + for (SizeType j = 0; j < n; j++) { + char name2[10]; + sprintf(name2, "%d", j); + + Value name3(name2, static_cast(strlen(name2)), allocator); + Value number(static_cast(i * n + j)); + object.AddMember(name3, number, allocator); + } + + // x.AddMember(name1, object, allocator); // should not compile + x.AddMember(name, object, allocator); + } + + for (SizeType i = 0; i < n; i++) { + char name1[10]; + sprintf(name1, "%d", i); + + for (SizeType j = 0; j < n; j++) { + char name2[10]; + sprintf(name2, "%d", j); + x[name1]; + EXPECT_EQ(static_cast(i * n + j), x[name1][name2].GetInt()); + } + } +} + +// Issue 18: Error removing last element of object +// http://code.google.com/p/rapidjson/issues/detail?id=18 +TEST(Value, RemoveLastElement) { + rapidjson::Document doc; + rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); + rapidjson::Value objVal(rapidjson::kObjectType); + objVal.AddMember("var1", 123, allocator); + objVal.AddMember("var2", "444", allocator); + objVal.AddMember("var3", 555, allocator); + EXPECT_TRUE(objVal.HasMember("var3")); + objVal.RemoveMember("var3"); // Assertion here in r61 + EXPECT_FALSE(objVal.HasMember("var3")); +} + +// Issue 38: Segmentation fault with CrtAllocator +TEST(Document, CrtAllocator) { + typedef GenericValue, CrtAllocator> V; + + V::AllocatorType allocator; + V o(kObjectType); + o.AddMember("x", 1, allocator); // Should not call destructor on uninitialized name/value of newly allocated members. + + V a(kArrayType); + a.PushBack(1, allocator); // Should not call destructor on uninitialized Value of newly allocated elements. +} + +static void TestShortStringOptimization(const char* str) { + const rapidjson::SizeType len = static_cast(strlen(str)); + + rapidjson::Document doc; + rapidjson::Value val; + val.SetString(str, len, doc.GetAllocator()); + + EXPECT_EQ(val.GetStringLength(), len); + EXPECT_STREQ(val.GetString(), str); +} + +TEST(Value, AllocateShortString) { + TestShortStringOptimization(""); // edge case: empty string + TestShortStringOptimization("12345678"); // regular case for short strings: 8 chars + TestShortStringOptimization("12345678901"); // edge case: 11 chars in 32-bit mode (=> short string) + TestShortStringOptimization("123456789012"); // edge case: 12 chars in 32-bit mode (=> regular string) + TestShortStringOptimization("123456789012345"); // edge case: 15 chars in 64-bit mode (=> short string) + TestShortStringOptimization("1234567890123456"); // edge case: 16 chars in 64-bit mode (=> regular string) +} + +template +struct TerminateHandler { + bool Null() { return e != 0; } + bool Bool(bool) { return e != 1; } + bool Int(int) { return e != 2; } + bool Uint(unsigned) { return e != 3; } + bool Int64(int64_t) { return e != 4; } + bool Uint64(uint64_t) { return e != 5; } + bool Double(double) { return e != 6; } + bool RawNumber(const char*, SizeType, bool) { return e != 7; } + bool String(const char*, SizeType, bool) { return e != 8; } + bool StartObject() { return e != 9; } + bool Key(const char*, SizeType, bool) { return e != 10; } + bool EndObject(SizeType) { return e != 11; } + bool StartArray() { return e != 12; } + bool EndArray(SizeType) { return e != 13; } +}; + +#define TEST_TERMINATION(e, json)\ +{\ + Document d; \ + EXPECT_FALSE(d.Parse(json).HasParseError()); \ + Reader reader; \ + TerminateHandler h;\ + EXPECT_FALSE(d.Accept(h));\ +} + +TEST(Value, AcceptTerminationByHandler) { + TEST_TERMINATION(0, "[null]"); + TEST_TERMINATION(1, "[true]"); + TEST_TERMINATION(1, "[false]"); + TEST_TERMINATION(2, "[-1]"); + TEST_TERMINATION(3, "[2147483648]"); + TEST_TERMINATION(4, "[-1234567890123456789]"); + TEST_TERMINATION(5, "[9223372036854775808]"); + TEST_TERMINATION(6, "[0.5]"); + // RawNumber() is never called + TEST_TERMINATION(8, "[\"a\"]"); + TEST_TERMINATION(9, "[{}]"); + TEST_TERMINATION(10, "[{\"a\":1}]"); + TEST_TERMINATION(11, "[{}]"); + TEST_TERMINATION(12, "{\"a\":[]}"); + TEST_TERMINATION(13, "{\"a\":[]}"); +} + +struct ValueIntComparer { + bool operator()(const Value& lhs, const Value& rhs) const { + return lhs.GetInt() < rhs.GetInt(); + } +}; + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +TEST(Value, Sorting) { + Value::AllocatorType allocator; + Value a(kArrayType); + a.PushBack(5, allocator); + a.PushBack(1, allocator); + a.PushBack(3, allocator); + std::sort(a.Begin(), a.End(), ValueIntComparer()); + EXPECT_EQ(1, a[0].GetInt()); + EXPECT_EQ(3, a[1].GetInt()); + EXPECT_EQ(5, a[2].GetInt()); +} +#endif + +// http://stackoverflow.com/questions/35222230/ + +static void MergeDuplicateKey(Value& v, Value::AllocatorType& a) { + if (v.IsObject()) { + // Convert all key:value into key:[value] + for (Value::MemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + itr->value = Value(kArrayType).Move().PushBack(itr->value, a); + + // Merge arrays if key is duplicated + for (Value::MemberIterator itr = v.MemberBegin(); itr != v.MemberEnd();) { + Value::MemberIterator itr2 = v.FindMember(itr->name); + if (itr != itr2) { + itr2->value.PushBack(itr->value[0], a); + itr = v.EraseMember(itr); + } + else + ++itr; + } + + // Convert key:[values] back to key:value if there is only one value + for (Value::MemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) { + if (itr->value.Size() == 1) + itr->value = itr->value[0]; + MergeDuplicateKey(itr->value, a); // Recursion on the value + } + } + else if (v.IsArray()) + for (Value::ValueIterator itr = v.Begin(); itr != v.End(); ++itr) + MergeDuplicateKey(*itr, a); +} + +TEST(Value, MergeDuplicateKey) { + Document d; + d.Parse( + "{" + " \"key1\": {" + " \"a\": \"asdf\"," + " \"b\": \"foo\"," + " \"b\": \"bar\"," + " \"c\": \"fdas\"" + " }" + "}"); + + Document d2; + d2.Parse( + "{" + " \"key1\": {" + " \"a\": \"asdf\"," + " \"b\": [" + " \"foo\"," + " \"bar\"" + " ]," + " \"c\": \"fdas\"" + " }" + "}"); + + EXPECT_NE(d2, d); + MergeDuplicateKey(d, d.GetAllocator()); + EXPECT_EQ(d2, d); +} + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/unittest/writertest.cpp b/deps/rapidjson/test/unittest/writertest.cpp new file mode 100644 index 0000000..ac9ad89 --- /dev/null +++ b/deps/rapidjson/test/unittest/writertest.cpp @@ -0,0 +1,598 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "unittest.h" + +#include "rapidjson/document.h" +#include "rapidjson/reader.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/memorybuffer.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +using namespace rapidjson; + +TEST(Writer, Compact) { + StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3] } "); + StringBuffer buffer; + Writer writer(buffer); + buffer.ShrinkToFit(); + Reader reader; + reader.Parse<0>(s, writer); + EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3]}", buffer.GetString()); + EXPECT_EQ(77u, buffer.GetSize()); + EXPECT_TRUE(writer.IsComplete()); +} + +// json -> parse -> writer -> json +#define TEST_ROUNDTRIP(json) \ + { \ + StringStream s(json); \ + StringBuffer buffer; \ + Writer writer(buffer); \ + Reader reader; \ + reader.Parse(s, writer); \ + EXPECT_STREQ(json, buffer.GetString()); \ + EXPECT_TRUE(writer.IsComplete()); \ + } + +TEST(Writer, Root) { + TEST_ROUNDTRIP("null"); + TEST_ROUNDTRIP("true"); + TEST_ROUNDTRIP("false"); + TEST_ROUNDTRIP("0"); + TEST_ROUNDTRIP("\"foo\""); + TEST_ROUNDTRIP("[]"); + TEST_ROUNDTRIP("{}"); +} + +TEST(Writer, Int) { + TEST_ROUNDTRIP("[-1]"); + TEST_ROUNDTRIP("[-123]"); + TEST_ROUNDTRIP("[-2147483648]"); +} + +TEST(Writer, UInt) { + TEST_ROUNDTRIP("[0]"); + TEST_ROUNDTRIP("[1]"); + TEST_ROUNDTRIP("[123]"); + TEST_ROUNDTRIP("[2147483647]"); + TEST_ROUNDTRIP("[4294967295]"); +} + +TEST(Writer, Int64) { + TEST_ROUNDTRIP("[-1234567890123456789]"); + TEST_ROUNDTRIP("[-9223372036854775808]"); +} + +TEST(Writer, Uint64) { + TEST_ROUNDTRIP("[1234567890123456789]"); + TEST_ROUNDTRIP("[9223372036854775807]"); +} + +TEST(Writer, String) { + TEST_ROUNDTRIP("[\"Hello\"]"); + TEST_ROUNDTRIP("[\"Hello\\u0000World\"]"); + TEST_ROUNDTRIP("[\"\\\"\\\\/\\b\\f\\n\\r\\t\"]"); + +#if RAPIDJSON_HAS_STDSTRING + { + StringBuffer buffer; + Writer writer(buffer); + writer.String(std::string("Hello\n")); + EXPECT_STREQ("\"Hello\\n\"", buffer.GetString()); + } +#endif +} + +TEST(Writer, Issue_889) { + char buf[100] = "Hello"; + + StringBuffer buffer; + Writer writer(buffer); + writer.StartArray(); + writer.String(buf); + writer.EndArray(); + + EXPECT_STREQ("[\"Hello\"]", buffer.GetString()); + EXPECT_TRUE(writer.IsComplete()); \ +} + +TEST(Writer, ScanWriteUnescapedString) { + const char json[] = "[\" \\\"0123456789ABCDEF\"]"; + // ^ scanning stops here. + char buffer2[sizeof(json) + 32]; + + // Use different offset to test different alignments + for (int i = 0; i < 32; i++) { + char* p = buffer2 + i; + memcpy(p, json, sizeof(json)); + TEST_ROUNDTRIP(p); + } +} + +TEST(Writer, Double) { + TEST_ROUNDTRIP("[1.2345,1.2345678,0.123456789012,1234567.8]"); + TEST_ROUNDTRIP("0.0"); + TEST_ROUNDTRIP("-0.0"); // Issue #289 + TEST_ROUNDTRIP("1e30"); + TEST_ROUNDTRIP("1.0"); + TEST_ROUNDTRIP("5e-324"); // Min subnormal positive double + TEST_ROUNDTRIP("2.225073858507201e-308"); // Max subnormal positive double + TEST_ROUNDTRIP("2.2250738585072014e-308"); // Min normal positive double + TEST_ROUNDTRIP("1.7976931348623157e308"); // Max double + +} + +// UTF8 -> TargetEncoding -> UTF8 +template +void TestTranscode(const char* json) { + StringStream s(json); + GenericStringBuffer buffer; + Writer, UTF8<>, TargetEncoding> writer(buffer); + Reader reader; + reader.Parse(s, writer); + + StringBuffer buffer2; + Writer writer2(buffer2); + GenericReader > reader2; + GenericStringStream s2(buffer.GetString()); + reader2.Parse(s2, writer2); + + EXPECT_STREQ(json, buffer2.GetString()); +} + +TEST(Writer, Transcode) { + const char json[] = "{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"dollar\":\"\x24\",\"cents\":\"\xC2\xA2\",\"euro\":\"\xE2\x82\xAC\",\"gclef\":\"\xF0\x9D\x84\x9E\"}"; + + // UTF8 -> UTF16 -> UTF8 + TestTranscode >(json); + + // UTF8 -> ASCII -> UTF8 + TestTranscode >(json); + + // UTF8 -> UTF16 -> UTF8 + TestTranscode >(json); + + // UTF8 -> UTF32 -> UTF8 + TestTranscode >(json); + + // UTF8 -> AutoUTF -> UTF8 + UTFType types[] = { kUTF8, kUTF16LE , kUTF16BE, kUTF32LE , kUTF32BE }; + for (size_t i = 0; i < 5; i++) { + StringStream s(json); + MemoryBuffer buffer; + AutoUTFOutputStream os(buffer, types[i], true); + Writer, UTF8<>, AutoUTF > writer(os); + Reader reader; + reader.Parse(s, writer); + + StringBuffer buffer2; + Writer writer2(buffer2); + GenericReader, UTF8<> > reader2; + MemoryStream s2(buffer.GetBuffer(), buffer.GetSize()); + AutoUTFInputStream is(s2); + reader2.Parse(is, writer2); + + EXPECT_STREQ(json, buffer2.GetString()); + } + +} + +#include + +class OStreamWrapper { +public: + typedef char Ch; + + OStreamWrapper(std::ostream& os) : os_(os) {} + + Ch Peek() const { assert(false); return '\0'; } + Ch Take() { assert(false); return '\0'; } + size_t Tell() const { return 0; } + + Ch* PutBegin() { assert(false); return 0; } + void Put(Ch c) { os_.put(c); } + void Flush() { os_.flush(); } + size_t PutEnd(Ch*) { assert(false); return 0; } + +private: + OStreamWrapper(const OStreamWrapper&); + OStreamWrapper& operator=(const OStreamWrapper&); + + std::ostream& os_; +}; + +TEST(Writer, OStreamWrapper) { + StringStream s("{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3], \"u64\": 1234567890123456789, \"i64\":-1234567890123456789 } "); + + std::stringstream ss; + OStreamWrapper os(ss); + + Writer writer(os); + + Reader reader; + reader.Parse<0>(s, writer); + + std::string actual = ss.str(); + EXPECT_STREQ("{\"hello\":\"world\",\"t\":true,\"f\":false,\"n\":null,\"i\":123,\"pi\":3.1416,\"a\":[1,2,3],\"u64\":1234567890123456789,\"i64\":-1234567890123456789}", actual.c_str()); +} + +TEST(Writer, AssertRootMayBeAnyValue) { +#define T(x)\ + {\ + StringBuffer buffer;\ + Writer writer(buffer);\ + EXPECT_TRUE(x);\ + } + T(writer.Bool(false)); + T(writer.Bool(true)); + T(writer.Null()); + T(writer.Int(0)); + T(writer.Uint(0)); + T(writer.Int64(0)); + T(writer.Uint64(0)); + T(writer.Double(0)); + T(writer.String("foo")); +#undef T +} + +TEST(Writer, AssertIncorrectObjectLevel) { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + writer.EndObject(); + ASSERT_THROW(writer.EndObject(), AssertException); +} + +TEST(Writer, AssertIncorrectArrayLevel) { + StringBuffer buffer; + Writer writer(buffer); + writer.StartArray(); + writer.EndArray(); + ASSERT_THROW(writer.EndArray(), AssertException); +} + +TEST(Writer, AssertIncorrectEndObject) { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + ASSERT_THROW(writer.EndArray(), AssertException); +} + +TEST(Writer, AssertIncorrectEndArray) { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + ASSERT_THROW(writer.EndArray(), AssertException); +} + +TEST(Writer, AssertObjectKeyNotString) { +#define T(x)\ + {\ + StringBuffer buffer;\ + Writer writer(buffer);\ + writer.StartObject();\ + ASSERT_THROW(x, AssertException); \ + } + T(writer.Bool(false)); + T(writer.Bool(true)); + T(writer.Null()); + T(writer.Int(0)); + T(writer.Uint(0)); + T(writer.Int64(0)); + T(writer.Uint64(0)); + T(writer.Double(0)); + T(writer.StartObject()); + T(writer.StartArray()); +#undef T +} + +TEST(Writer, AssertMultipleRoot) { + StringBuffer buffer; + Writer writer(buffer); + + writer.StartObject(); + writer.EndObject(); + ASSERT_THROW(writer.StartObject(), AssertException); + + writer.Reset(buffer); + writer.Null(); + ASSERT_THROW(writer.Int(0), AssertException); + + writer.Reset(buffer); + writer.String("foo"); + ASSERT_THROW(writer.StartArray(), AssertException); + + writer.Reset(buffer); + writer.StartArray(); + writer.EndArray(); + //ASSERT_THROW(writer.Double(3.14), AssertException); +} + +TEST(Writer, RootObjectIsComplete) { + StringBuffer buffer; + Writer writer(buffer); + EXPECT_FALSE(writer.IsComplete()); + writer.StartObject(); + EXPECT_FALSE(writer.IsComplete()); + writer.String("foo"); + EXPECT_FALSE(writer.IsComplete()); + writer.Int(1); + EXPECT_FALSE(writer.IsComplete()); + writer.EndObject(); + EXPECT_TRUE(writer.IsComplete()); +} + +TEST(Writer, RootArrayIsComplete) { + StringBuffer buffer; + Writer writer(buffer); + EXPECT_FALSE(writer.IsComplete()); + writer.StartArray(); + EXPECT_FALSE(writer.IsComplete()); + writer.String("foo"); + EXPECT_FALSE(writer.IsComplete()); + writer.Int(1); + EXPECT_FALSE(writer.IsComplete()); + writer.EndArray(); + EXPECT_TRUE(writer.IsComplete()); +} + +TEST(Writer, RootValueIsComplete) { +#define T(x)\ + {\ + StringBuffer buffer;\ + Writer writer(buffer);\ + EXPECT_FALSE(writer.IsComplete()); \ + x; \ + EXPECT_TRUE(writer.IsComplete()); \ + } + T(writer.Null()); + T(writer.Bool(true)); + T(writer.Bool(false)); + T(writer.Int(0)); + T(writer.Uint(0)); + T(writer.Int64(0)); + T(writer.Uint64(0)); + T(writer.Double(0)); + T(writer.String("")); +#undef T +} + +TEST(Writer, InvalidEncoding) { + // Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt + { + GenericStringBuffer > buffer; + Writer >, UTF8<>, UTF16<> > writer(buffer); + writer.StartArray(); + EXPECT_FALSE(writer.String("\xfe")); + EXPECT_FALSE(writer.String("\xff")); + EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff")); + writer.EndArray(); + } + + // Fail in encoding + { + StringBuffer buffer; + Writer > writer(buffer); + static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF + EXPECT_FALSE(writer.String(s)); + } + + // Fail in unicode escaping in ASCII output + { + StringBuffer buffer; + Writer, ASCII<> > writer(buffer); + static const UTF32<>::Ch s[] = { 0x110000, 0 }; // Out of U+0000 to U+10FFFF + EXPECT_FALSE(writer.String(s)); + } +} + +TEST(Writer, ValidateEncoding) { + { + StringBuffer buffer; + Writer, UTF8<>, CrtAllocator, kWriteValidateEncodingFlag> writer(buffer); + writer.StartArray(); + EXPECT_TRUE(writer.String("\x24")); // Dollar sign U+0024 + EXPECT_TRUE(writer.String("\xC2\xA2")); // Cents sign U+00A2 + EXPECT_TRUE(writer.String("\xE2\x82\xAC")); // Euro sign U+20AC + EXPECT_TRUE(writer.String("\xF0\x9D\x84\x9E")); // G clef sign U+1D11E + EXPECT_TRUE(writer.String("\x01")); // SOH control U+0001 + EXPECT_TRUE(writer.String("\x1B")); // Escape control U+001B + writer.EndArray(); + EXPECT_STREQ("[\"\x24\",\"\xC2\xA2\",\"\xE2\x82\xAC\",\"\xF0\x9D\x84\x9E\",\"\\u0001\",\"\\u001B\"]", buffer.GetString()); + } + + // Fail in decoding invalid UTF-8 sequence http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt + { + StringBuffer buffer; + Writer, UTF8<>, CrtAllocator, kWriteValidateEncodingFlag> writer(buffer); + writer.StartArray(); + EXPECT_FALSE(writer.String("\xfe")); + EXPECT_FALSE(writer.String("\xff")); + EXPECT_FALSE(writer.String("\xfe\xfe\xff\xff")); + writer.EndArray(); + } +} + +TEST(Writer, InvalidEventSequence) { + // {] + { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + EXPECT_THROW(writer.EndArray(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // [} + { + StringBuffer buffer; + Writer writer(buffer); + writer.StartArray(); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 1: + { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + EXPECT_THROW(writer.Int(1), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 'a' } + { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + writer.Key("a"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } + + // { 'a':'b','c' } + { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + writer.Key("a"); + writer.String("b"); + writer.Key("c"); + EXPECT_THROW(writer.EndObject(), AssertException); + EXPECT_FALSE(writer.IsComplete()); + } +} + +TEST(Writer, NaN) { + double nan = std::numeric_limits::quiet_NaN(); + + EXPECT_TRUE(internal::Double(nan).IsNan()); + StringBuffer buffer; + { + Writer writer(buffer); + EXPECT_FALSE(writer.Double(nan)); + } + { + Writer, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer); + EXPECT_TRUE(writer.Double(nan)); + EXPECT_STREQ("NaN", buffer.GetString()); + } + GenericStringBuffer > buffer2; + Writer > > writer2(buffer2); + EXPECT_FALSE(writer2.Double(nan)); +} + +TEST(Writer, Inf) { + double inf = std::numeric_limits::infinity(); + + EXPECT_TRUE(internal::Double(inf).IsInf()); + StringBuffer buffer; + { + Writer writer(buffer); + EXPECT_FALSE(writer.Double(inf)); + } + { + Writer writer(buffer); + EXPECT_FALSE(writer.Double(-inf)); + } + { + Writer, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer); + EXPECT_TRUE(writer.Double(inf)); + } + { + Writer, UTF8<>, CrtAllocator, kWriteNanAndInfFlag> writer(buffer); + EXPECT_TRUE(writer.Double(-inf)); + } + EXPECT_STREQ("Infinity-Infinity", buffer.GetString()); +} + +TEST(Writer, RawValue) { + StringBuffer buffer; + Writer writer(buffer); + writer.StartObject(); + writer.Key("a"); + writer.Int(1); + writer.Key("raw"); + const char json[] = "[\"Hello\\nWorld\", 123.456]"; + writer.RawValue(json, strlen(json), kArrayType); + writer.EndObject(); + EXPECT_TRUE(writer.IsComplete()); + EXPECT_STREQ("{\"a\":1,\"raw\":[\"Hello\\nWorld\", 123.456]}", buffer.GetString()); +} + +TEST(Write, RawValue_Issue1152) { + { + GenericStringBuffer > sb; + Writer >, UTF8<>, UTF32<> > writer(sb); + writer.RawValue("null", 4, kNullType); + EXPECT_TRUE(writer.IsComplete()); + const unsigned *out = sb.GetString(); + EXPECT_EQ(static_cast('n'), out[0]); + EXPECT_EQ(static_cast('u'), out[1]); + EXPECT_EQ(static_cast('l'), out[2]); + EXPECT_EQ(static_cast('l'), out[3]); + EXPECT_EQ(static_cast(0 ), out[4]); + } + + { + GenericStringBuffer > sb; + Writer >, UTF16<>, UTF8<> > writer(sb); + writer.RawValue(L"null", 4, kNullType); + EXPECT_TRUE(writer.IsComplete()); + EXPECT_STREQ("null", sb.GetString()); + } + + { + // Fail in transcoding + GenericStringBuffer > buffer; + Writer >, UTF8<>, UTF16<> > writer(buffer); + EXPECT_FALSE(writer.RawValue("\"\xfe\"", 3, kStringType)); + } + + { + // Fail in encoding validation + StringBuffer buffer; + Writer, UTF8<>, CrtAllocator, kWriteValidateEncodingFlag> writer(buffer); + EXPECT_FALSE(writer.RawValue("\"\xfe\"", 3, kStringType)); + } +} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS +static Writer WriterGen(StringBuffer &target) { + Writer writer(target); + writer.StartObject(); + writer.Key("a"); + writer.Int(1); + return writer; +} + +TEST(Writer, MoveCtor) { + StringBuffer buffer; + Writer writer(WriterGen(buffer)); + writer.EndObject(); + EXPECT_TRUE(writer.IsComplete()); + EXPECT_STREQ("{\"a\":1}", buffer.GetString()); +} +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif diff --git a/deps/rapidjson/test/valgrind.supp b/deps/rapidjson/test/valgrind.supp new file mode 100644 index 0000000..c9d3d22 --- /dev/null +++ b/deps/rapidjson/test/valgrind.supp @@ -0,0 +1,26 @@ +{ + Suppress wcslen valgrind report 1 + Memcheck:Cond + fun:__wcslen_sse2 +} + +{ + Suppress wcslen valgrind report 2 + Memcheck:Addr8 + fun:__wcslen_sse2 +} + +{ + Suppress wcslen valgrind report 3 + Memcheck:Value8 + fun:__wcslen_sse2 +} + +{ + Suppress wmemcmp valgrind report 4 + Memcheck:Addr32 + fun:__wmemcmp_avx2_movbe + ... + fun:*Uri*Parse_UTF16_Std* +} + diff --git a/deps/rapidjson/thirdparty/gtest/.gitignore b/deps/rapidjson/thirdparty/gtest/.gitignore new file mode 100644 index 0000000..b294d3b --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/.gitignore @@ -0,0 +1,40 @@ +# Ignore CI build directory +build/ +xcuserdata +cmake-build-debug/ +.idea/ +bazel-bin +bazel-genfiles +bazel-googletest +bazel-out +bazel-testlogs +# python +*.pyc + +# Visual Studio files +*.sdf +*.opensdf +*.VC.opendb +*.suo +*.user +_ReSharper.Caches/ +Win32-Debug/ +Win32-Release/ +x64-Debug/ +x64-Release/ + +# Ignore autoconf / automake files +Makefile.in +aclocal.m4 +configure +build-aux/ +autom4te.cache/ +googletest/m4/libtool.m4 +googletest/m4/ltoptions.m4 +googletest/m4/ltsugar.m4 +googletest/m4/ltversion.m4 +googletest/m4/lt~obsolete.m4 + +# Ignore generated directories. +googlemock/fused-src/ +googletest/fused-src/ diff --git a/deps/rapidjson/thirdparty/gtest/.travis.yml b/deps/rapidjson/thirdparty/gtest/.travis.yml new file mode 100644 index 0000000..1200c67 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/.travis.yml @@ -0,0 +1,81 @@ +# Build matrix / environment variable are explained on: +# http://about.travis-ci.org/docs/user/build-configuration/ +# This file can be validated on: +# http://lint.travis-ci.org/ + +sudo: false +language: cpp + +# Define the matrix explicitly, manually expanding the combinations of (os, compiler, env). +# It is more tedious, but grants us far more flexibility. +matrix: + include: + - os: linux + compiler: gcc + sudo : true + install: ./ci/install-linux.sh && ./ci/log-config.sh + script: ./ci/build-linux-bazel.sh + - os: linux + compiler: clang + sudo : true + install: ./ci/install-linux.sh && ./ci/log-config.sh + script: ./ci/build-linux-bazel.sh + - os: linux + group: deprecated-2017Q4 + compiler: gcc + install: ./ci/install-linux.sh && ./ci/log-config.sh + script: ./ci/build-linux-autotools.sh + - os: linux + group: deprecated-2017Q4 + compiler: gcc + env: BUILD_TYPE=Debug VERBOSE=1 CXX_FLAGS=-std=c++11 + - os: linux + group: deprecated-2017Q4 + compiler: clang + env: BUILD_TYPE=Debug VERBOSE=1 + - os: linux + group: deprecated-2017Q4 + compiler: clang + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 + - os: linux + compiler: clang + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 NO_EXCEPTION=ON NO_RTTI=ON COMPILER_IS_GNUCXX=ON + - os: osx + compiler: gcc + env: BUILD_TYPE=Debug VERBOSE=1 + - os: osx + compiler: gcc + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 + - os: osx + compiler: clang + env: BUILD_TYPE=Debug VERBOSE=1 + if: type != pull_request + - os: osx + env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 + if: type != pull_request + +# These are the install and build (script) phases for the most common entries in the matrix. They could be included +# in each entry in the matrix, but that is just repetitive. +install: + - ./ci/install-${TRAVIS_OS_NAME}.sh + - . ./ci/env-${TRAVIS_OS_NAME}.sh + - ./ci/log-config.sh + +script: ./ci/travis.sh + +# For sudo=false builds this section installs the necessary dependencies. +addons: + apt: + # List of whitelisted in travis packages for ubuntu-precise can be found here: + # https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise + # List of whitelisted in travis apt-sources: + # https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json + sources: + - ubuntu-toolchain-r-test + - llvm-toolchain-precise-3.7 + packages: + - g++-4.9 + - clang-3.7 + +notifications: + email: false diff --git a/deps/rapidjson/thirdparty/gtest/BUILD.bazel b/deps/rapidjson/thirdparty/gtest/BUILD.bazel new file mode 100644 index 0000000..6d82829 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/BUILD.bazel @@ -0,0 +1,175 @@ +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. +# +# Author: misterg@google.com (Gennadiy Civil) +# +# Bazel Build for Google C++ Testing Framework(Google Test) + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +config_setting( + name = "windows", + values = { "cpu": "x64_windows" }, +) + +config_setting( + name = "windows_msvc", + values = {"cpu": "x64_windows_msvc"}, +) + +config_setting( + name = "has_absl", + values = {"define": "absl=1"}, +) + + +# Google Test including Google Mock +cc_library( + name = "gtest", + srcs = glob( + include = [ + "googletest/src/*.cc", + "googletest/src/*.h", + "googletest/include/gtest/**/*.h", + "googlemock/src/*.cc", + "googlemock/include/gmock/**/*.h", + ], + exclude = [ + "googletest/src/gtest-all.cc", + "googletest/src/gtest_main.cc", + "googlemock/src/gmock-all.cc", + "googlemock/src/gmock_main.cc", + ], + ), + hdrs =glob([ + "googletest/include/gtest/*.h", + "googlemock/include/gmock/*.h", + ]), + copts = select( + { + ":windows": [], + ":windows_msvc": [], + "//conditions:default": ["-pthread"], + }, + ), + includes = [ + "googlemock", + "googlemock/include", + "googletest", + "googletest/include", + ], + linkopts = select({ + ":windows": [], + ":windows_msvc": [], + "//conditions:default": [ + "-pthread", + ], + }), + defines = select ({ + ":has_absl": [ + "GTEST_HAS_ABSL=1", + ], + "//conditions:default": [], + } + ), + deps = select ({ + ":has_absl": [ + "@com_google_absl//absl/types:optional", + "@com_google_absl//absl/strings" + ], + "//conditions:default": [], + } + ) +) + +cc_library( + name = "gtest_main", + srcs = [ + "googlemock/src/gmock_main.cc", + ], + deps = [":gtest"], +) + +# The following rules build samples of how to use gTest. +cc_library( + name = "gtest_sample_lib", + srcs = [ + "googletest/samples/sample1.cc", + "googletest/samples/sample2.cc", + "googletest/samples/sample4.cc", + ], + hdrs = [ + "googletest/samples/prime_tables.h", + "googletest/samples/sample1.h", + "googletest/samples/sample2.h", + "googletest/samples/sample3-inl.h", + "googletest/samples/sample4.h", + ], +) + +cc_test( + name = "gtest_samples", + size = "small", + #All Samples except: + #sample9 ( main ) + #sample10 (main and takes a command line option and needs to be separate) + srcs = [ + "googletest/samples/sample1_unittest.cc", + "googletest/samples/sample2_unittest.cc", + "googletest/samples/sample3_unittest.cc", + "googletest/samples/sample4_unittest.cc", + "googletest/samples/sample5_unittest.cc", + "googletest/samples/sample6_unittest.cc", + "googletest/samples/sample7_unittest.cc", + "googletest/samples/sample8_unittest.cc", + ], + deps = [ + "gtest_sample_lib", + ":gtest_main", + ], +) + +cc_test( + name = "sample9_unittest", + size = "small", + srcs = ["googletest/samples/sample9_unittest.cc"], + deps = [":gtest"], +) + +cc_test( + name = "sample10_unittest", + size = "small", + srcs = ["googletest/samples/sample10_unittest.cc"], + deps = [ + ":gtest", + ], +) diff --git a/deps/rapidjson/thirdparty/gtest/CMakeLists.txt b/deps/rapidjson/thirdparty/gtest/CMakeLists.txt new file mode 100644 index 0000000..f8a97fa --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 2.6.4) + +if (POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) +endif (POLICY CMP0048) + +project( googletest-distribution ) + +enable_testing() + +include(CMakeDependentOption) +if (CMAKE_VERSION VERSION_LESS 2.8.5) + set(CMAKE_INSTALL_BINDIR "bin" CACHE STRING "User executables (bin)") + set(CMAKE_INSTALL_LIBDIR "lib${LIB_SUFFIX}" CACHE STRING "Object code libraries (lib)") + set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "C header files (include)") + mark_as_advanced(CMAKE_INSTALL_BINDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR) +else() + include(GNUInstallDirs) +endif() + +option(BUILD_GTEST "Builds the googletest subproject" OFF) + +#Note that googlemock target already builds googletest +option(BUILD_GMOCK "Builds the googlemock subproject" ON) + +cmake_dependent_option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON "BUILD_GTEST OR BUILD_GMOCK" OFF) +cmake_dependent_option(INSTALL_GMOCK "Enable installation of googlemock. (Projects embedding googlemock may want to turn this OFF.)" ON "BUILD_GMOCK" OFF) + +if(BUILD_GMOCK) + add_subdirectory( googlemock ) +elseif(BUILD_GTEST) + add_subdirectory( googletest ) +endif() diff --git a/deps/rapidjson/thirdparty/gtest/CONTRIBUTING.md b/deps/rapidjson/thirdparty/gtest/CONTRIBUTING.md new file mode 100644 index 0000000..0ebdfcc --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/CONTRIBUTING.md @@ -0,0 +1,160 @@ +# How to become a contributor and submit your own code + +## Contributor License Agreements + +We'd love to accept your patches! Before we can take them, we +have to jump a couple of legal hurdles. + +Please fill out either the individual or corporate Contributor License Agreement +(CLA). + + * If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an + [individual CLA](https://developers.google.com/open-source/cla/individual). + * If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a + [corporate CLA](https://developers.google.com/open-source/cla/corporate). + +Follow either of the two links above to access the appropriate CLA and +instructions for how to sign and return it. Once we receive it, we'll be able to +accept your pull requests. + +## Contributing A Patch + +1. Submit an issue describing your proposed change to the + [issue tracker](https://github.com/google/googletest). +1. Please don't mix more than one logical change per submittal, + because it makes the history hard to follow. If you want to make a + change that doesn't have a corresponding issue in the issue + tracker, please create one. +1. Also, coordinate with team members that are listed on the issue in + question. This ensures that work isn't being duplicated and + communicating your plan early also generally leads to better + patches. +1. If your proposed change is accepted, and you haven't already done so, sign a + Contributor License Agreement (see details above). +1. Fork the desired repo, develop and test your code changes. +1. Ensure that your code adheres to the existing style in the sample to which + you are contributing. +1. Ensure that your code has an appropriate set of unit tests which all pass. +1. Submit a pull request. + +If you are a Googler, it is preferable to first create an internal change and +have it reviewed and submitted, and then create an upstreaming pull +request here. + +## The Google Test and Google Mock Communities ## + +The Google Test community exists primarily through the +[discussion group](http://groups.google.com/group/googletestframework) +and the GitHub repository. +Likewise, the Google Mock community exists primarily through their own +[discussion group](http://groups.google.com/group/googlemock). +You are definitely encouraged to contribute to the +discussion and you can also help us to keep the effectiveness of the +group high by following and promoting the guidelines listed here. + +### Please Be Friendly ### + +Showing courtesy and respect to others is a vital part of the Google +culture, and we strongly encourage everyone participating in Google +Test development to join us in accepting nothing less. Of course, +being courteous is not the same as failing to constructively disagree +with each other, but it does mean that we should be respectful of each +other when enumerating the 42 technical reasons that a particular +proposal may not be the best choice. There's never a reason to be +antagonistic or dismissive toward anyone who is sincerely trying to +contribute to a discussion. + +Sure, C++ testing is serious business and all that, but it's also +a lot of fun. Let's keep it that way. Let's strive to be one of the +friendliest communities in all of open source. + +As always, discuss Google Test in the official GoogleTest discussion group. +You don't have to actually submit code in order to sign up. Your participation +itself is a valuable contribution. + +## Style + +To keep the source consistent, readable, diffable and easy to merge, +we use a fairly rigid coding style, as defined by the [google-styleguide](https://github.com/google/styleguide) project. All patches will be expected +to conform to the style outlined [here](https://google.github.io/styleguide/cppguide.html). + +## Requirements for Contributors ### + +If you plan to contribute a patch, you need to build Google Test, +Google Mock, and their own tests from a git checkout, which has +further requirements: + + * [Python](https://www.python.org/) v2.3 or newer (for running some of + the tests and re-generating certain source files from templates) + * [CMake](https://cmake.org/) v2.6.4 or newer + * [GNU Build System](https://en.wikipedia.org/wiki/GNU_Build_System) + including automake (>= 1.9), autoconf (>= 2.59), and + libtool / libtoolize. + +## Developing Google Test ## + +This section discusses how to make your own changes to Google Test. + +### Testing Google Test Itself ### + +To make sure your changes work as intended and don't break existing +functionality, you'll want to compile and run Google Test's own tests. +For that you can use CMake: + + mkdir mybuild + cd mybuild + cmake -Dgtest_build_tests=ON ${GTEST_DIR} + +Make sure you have Python installed, as some of Google Test's tests +are written in Python. If the cmake command complains about not being +able to find Python (`Could NOT find PythonInterp (missing: +PYTHON_EXECUTABLE)`), try telling it explicitly where your Python +executable can be found: + + cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR} + +Next, you can build Google Test and all of its own tests. On \*nix, +this is usually done by 'make'. To run the tests, do + + make test + +All tests should pass. + +### Regenerating Source Files ## + +Some of Google Test's source files are generated from templates (not +in the C++ sense) using a script. +For example, the +file include/gtest/internal/gtest-type-util.h.pump is used to generate +gtest-type-util.h in the same directory. + +You don't need to worry about regenerating the source files +unless you need to modify them. You would then modify the +corresponding `.pump` files and run the '[pump.py](googletest/scripts/pump.py)' +generator script. See the [Pump Manual](googletest/docs/PumpManual.md). + +## Developing Google Mock ### + +This section discusses how to make your own changes to Google Mock. + +#### Testing Google Mock Itself #### + +To make sure your changes work as intended and don't break existing +functionality, you'll want to compile and run Google Test's own tests. +For that you'll need Autotools. First, make sure you have followed +the instructions above to configure Google Mock. +Then, create a build output directory and enter it. Next, + + ${GMOCK_DIR}/configure # try --help for more info + +Once you have successfully configured Google Mock, the build steps are +standard for GNU-style OSS packages. + + make # Standard makefile following GNU conventions + make check # Builds and runs all tests - all should pass. + +Note that when building your project against Google Mock, you are building +against Google Test as well. There is no need to configure Google Test +separately. diff --git a/deps/rapidjson/thirdparty/gtest/LICENSE b/deps/rapidjson/thirdparty/gtest/LICENSE new file mode 100644 index 0000000..1941a11 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/LICENSE @@ -0,0 +1,28 @@ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +OWNER 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. diff --git a/deps/rapidjson/thirdparty/gtest/Makefile.am b/deps/rapidjson/thirdparty/gtest/Makefile.am new file mode 100644 index 0000000..433eefe --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/Makefile.am @@ -0,0 +1,14 @@ +## Process this file with automake to produce Makefile.in +ACLOCAL_AMFLAGS = -I m4 + +AUTOMAKE_OPTIONS = foreign + +# Build . before src so that our all-local and clean-local hooks kicks in at +# the right time. +SUBDIRS = googletest googlemock + +EXTRA_DIST = \ + BUILD.bazel \ + CMakeLists.txt \ + README.md \ + WORKSPACE diff --git a/deps/rapidjson/thirdparty/gtest/README.md b/deps/rapidjson/thirdparty/gtest/README.md new file mode 100644 index 0000000..d87abce --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/README.md @@ -0,0 +1,122 @@ + +# Google Test # + +[![Build Status](https://travis-ci.org/google/googletest.svg?branch=master)](https://travis-ci.org/google/googletest) +[![Build status](https://ci.appveyor.com/api/projects/status/4o38plt0xbo1ubc8/branch/master?svg=true)](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master) + +Welcome to **Google Test**, Google's C++ test framework! + +This repository is a merger of the formerly separate GoogleTest and +GoogleMock projects. These were so closely related that it makes sense to +maintain and release them together. + +Please see the project page above for more information as well as the +mailing list for questions, discussions, and development. There is +also an IRC channel on [OFTC](https://webchat.oftc.net/) (irc.oftc.net) #gtest available. Please +join us! + +Getting started information for **Google Test** is available in the +[Google Test Primer](googletest/docs/primer.md) documentation. + +**Google Mock** is an extension to Google Test for writing and using C++ mock +classes. See the separate [Google Mock documentation](googlemock/README.md). + +More detailed documentation for googletest (including build instructions) are +in its interior [googletest/README.md](googletest/README.md) file. + +## Features ## + + * An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework. + * Test discovery. + * A rich set of assertions. + * User-defined assertions. + * Death tests. + * Fatal and non-fatal failures. + * Value-parameterized tests. + * Type-parameterized tests. + * Various options for running the tests. + * XML test report generation. + +## Platforms ## + +Google test has been used on a variety of platforms: + + * Linux + * Mac OS X + * Windows + * Cygwin + * MinGW + * Windows Mobile + * Symbian + +## Who Is Using Google Test? ## + +In addition to many internal projects at Google, Google Test is also used by +the following notable projects: + + * The [Chromium projects](http://www.chromium.org/) (behind the Chrome + browser and Chrome OS). + * The [LLVM](http://llvm.org/) compiler. + * [Protocol Buffers](https://github.com/google/protobuf), Google's data + interchange format. + * The [OpenCV](http://opencv.org/) computer vision library. + * [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only, dependency-free deep learning framework in C++11. + +## Related Open Source Projects ## + +[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based automated test-runner and Graphical User Interface with powerful features for Windows and Linux platforms. + +[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that runs +your test binary, allows you to track its progress via a progress bar, and +displays a list of test failures. Clicking on one shows failure text. Google +Test UI is written in C#. + +[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event +listener for Google Test that implements the +[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test +result output. If your test runner understands TAP, you may find it useful. + +[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that +runs tests from your binary in parallel to provide significant speed-up. + +## Requirements ## + +Google Test is designed to have fairly minimal requirements to build +and use with your projects, but there are some. Currently, we support +Linux, Windows, Mac OS X, and Cygwin. We will also make our best +effort to support other platforms (e.g. Solaris, AIX, and z/OS). +However, since core members of the Google Test project have no access +to these platforms, Google Test may have outstanding issues there. If +you notice any problems on your platform, please notify +[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework). Patches for fixing them are +even more welcome! + +### Linux Requirements ### + +These are the base requirements to build and use Google Test from a source +package (as described below): + + * GNU-compatible Make or gmake + * POSIX-standard shell + * POSIX(-2) Regular Expressions (regex.h) + * A C++98-standard-compliant compiler + +### Windows Requirements ### + + * Microsoft Visual C++ 2015 or newer + +### Cygwin Requirements ### + + * Cygwin v1.5.25-14 or newer + +### Mac OS X Requirements ### + + * Mac OS X v10.4 Tiger or newer + * Xcode Developer Tools + +## Contributing change + +Please read the [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on +how to contribute to this project. + +Happy testing! diff --git a/deps/rapidjson/thirdparty/gtest/WORKSPACE b/deps/rapidjson/thirdparty/gtest/WORKSPACE new file mode 100644 index 0000000..1d5d388 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/WORKSPACE @@ -0,0 +1,8 @@ +workspace(name = "com_google_googletest") + +# Abseil +http_archive( + name = "com_google_absl", + urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"], + strip_prefix = "abseil-cpp-master", +) diff --git a/deps/rapidjson/thirdparty/gtest/appveyor.yml b/deps/rapidjson/thirdparty/gtest/appveyor.yml new file mode 100644 index 0000000..b1da655 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/appveyor.yml @@ -0,0 +1,104 @@ +version: '{build}' + +os: Visual Studio 2015 + +environment: + matrix: + - compiler: msvc-15-seh + generator: "Visual Studio 15 2017" + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + + - compiler: msvc-15-seh + generator: "Visual Studio 15 2017 Win64" + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + enabled_on_pr: yes + + - compiler: msvc-14-seh + generator: "Visual Studio 14 2015" + enabled_on_pr: yes + + - compiler: msvc-14-seh + generator: "Visual Studio 14 2015 Win64" + + - compiler: gcc-5.3.0-posix + generator: "MinGW Makefiles" + cxx_path: 'C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin' + + - compiler: gcc-6.3.0-posix + generator: "MinGW Makefiles" + cxx_path: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin' + +configuration: + - Debug + +build: + verbosity: minimal + +install: +- ps: | + Write-Output "Compiler: $env:compiler" + Write-Output "Generator: $env:generator" + if (-not (Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER)) { + Write-Output "This is *NOT* a pull request build" + } else { + Write-Output "This is a pull request build" + if (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes") { + Write-Output "PR builds are *NOT* explicitly enabled" + } + } + + # git bash conflicts with MinGW makefiles + if ($env:generator -eq "MinGW Makefiles") { + $env:path = $env:path.replace("C:\Program Files\Git\usr\bin;", "") + if ($env:cxx_path -ne "") { + $env:path += ";$env:cxx_path" + } + } + +build_script: +- ps: | + # Only enable some builds for pull requests, the AppVeyor queue is too long. + if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) { + return + } + md _build -Force | Out-Null + cd _build + + $conf = if ($env:generator -eq "MinGW Makefiles") {"-DCMAKE_BUILD_TYPE=$env:configuration"} else {"-DCMAKE_CONFIGURATION_TYPES=Debug;Release"} + # Disable test for MinGW (gtest tests fail, gmock tests can not build) + $gtest_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgtest_build_tests=OFF"} else {"-Dgtest_build_tests=ON"} + $gmock_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgmock_build_tests=OFF"} else {"-Dgmock_build_tests=ON"} + & cmake -G "$env:generator" $conf -Dgtest_build_samples=ON $gtest_build_tests $gmock_build_tests .. + if ($LastExitCode -ne 0) { + throw "Exec: $ErrorMessage" + } + $cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"} + & cmake --build . --config $env:configuration -- $cmake_parallel + if ($LastExitCode -ne 0) { + throw "Exec: $ErrorMessage" + } + + +skip_commits: + files: + - '**/*.md' + +test_script: +- ps: | + # Only enable some builds for pull requests, the AppVeyor queue is too long. + if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) { + return + } + if ($env:generator -eq "MinGW Makefiles") { + return # No test available for MinGW + } + & ctest -C $env:configuration --timeout 600 --output-on-failure + if ($LastExitCode -ne 0) { + throw "Exec: $ErrorMessage" + } + +artifacts: + - path: '_build/CMakeFiles/*.log' + name: logs + - path: '_build/Testing/**/*.xml' + name: test_results diff --git a/deps/rapidjson/thirdparty/gtest/ci/build-linux-autotools.sh b/deps/rapidjson/thirdparty/gtest/ci/build-linux-autotools.sh new file mode 100644 index 0000000..cc404e9 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/build-linux-autotools.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +set -e + +. ci/get-nprocessors.sh + +# Create the configuration script +autoreconf -i + +# Run in a subdirectory to keep the sources clean +mkdir build || true +cd build +../configure + +make -j ${NPROCESSORS:-2} diff --git a/deps/rapidjson/thirdparty/gtest/ci/build-linux-bazel.sh b/deps/rapidjson/thirdparty/gtest/ci/build-linux-bazel.sh new file mode 100644 index 0000000..3f1c784 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/build-linux-bazel.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +set -e + +bazel build --curses=no //...:all +bazel test --curses=no //...:all +bazel test --curses=no //...:all --define absl=1 diff --git a/deps/rapidjson/thirdparty/gtest/ci/env-linux.sh b/deps/rapidjson/thirdparty/gtest/ci/env-linux.sh new file mode 100644 index 0000000..9086b1f --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/env-linux.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +# +# This file should be sourced, and not executed as a standalone script. +# + +# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}. + +if [ "${TRAVIS_OS_NAME}" = "linux" ]; then + if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi + if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi +fi diff --git a/deps/rapidjson/thirdparty/gtest/ci/env-osx.sh b/deps/rapidjson/thirdparty/gtest/ci/env-osx.sh new file mode 100644 index 0000000..31c8835 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/env-osx.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +# +# This file should be sourced, and not executed as a standalone script. +# + +# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}. + +if [ "${TRAVIS_OS_NAME}" = "linux" ]; then + if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi +fi diff --git a/deps/rapidjson/thirdparty/gtest/ci/get-nprocessors.sh b/deps/rapidjson/thirdparty/gtest/ci/get-nprocessors.sh new file mode 100644 index 0000000..43635e7 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/get-nprocessors.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +# This file is typically sourced by another script. +# if possible, ask for the precise number of processors, +# otherwise take 2 processors as reasonable default; see +# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization +if [ -x /usr/bin/getconf ]; then + NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN) +else + NPROCESSORS=2 +fi + +# as of 2017-09-04 Travis CI reports 32 processors, but GCC build +# crashes if parallelized too much (maybe memory consumption problem), +# so limit to 4 processors for the time being. +if [ $NPROCESSORS -gt 4 ] ; then + echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4." + NPROCESSORS=4 +fi diff --git a/deps/rapidjson/thirdparty/gtest/ci/install-linux.sh b/deps/rapidjson/thirdparty/gtest/ci/install-linux.sh new file mode 100644 index 0000000..02a1943 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/install-linux.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +set -eu + +if [ "${TRAVIS_OS_NAME}" != linux ]; then + echo "Not a Linux build; skipping installation" + exit 0 +fi + + +if [ "${TRAVIS_SUDO}" = "true" ]; then + echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | \ + sudo tee /etc/apt/sources.list.d/bazel.list + curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - + sudo apt-get update && sudo apt-get install -y bazel gcc-4.9 g++-4.9 clang-3.7 +elif [ "${CXX}" = "clang++" ]; then + # Use ccache, assuming $HOME/bin is in the path, which is true in the Travis build environment. + ln -sf /usr/bin/ccache $HOME/bin/${CXX}; + ln -sf /usr/bin/ccache $HOME/bin/${CC}; +fi diff --git a/deps/rapidjson/thirdparty/gtest/ci/install-osx.sh b/deps/rapidjson/thirdparty/gtest/ci/install-osx.sh new file mode 100644 index 0000000..6550ff5 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/install-osx.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +set -eu + +if [ "${TRAVIS_OS_NAME}" != "osx" ]; then + echo "Not a macOS build; skipping installation" + exit 0 +fi + +brew install ccache diff --git a/deps/rapidjson/thirdparty/gtest/ci/log-config.sh b/deps/rapidjson/thirdparty/gtest/ci/log-config.sh new file mode 100644 index 0000000..5fef119 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/log-config.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * 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. +# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +# OWNER 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. + +set -e + +# ccache on OS X needs installation first +# reset ccache statistics +ccache --zero-stats + +echo PATH=${PATH} + +echo "Compiler configuration:" +echo CXX=${CXX} +echo CC=${CC} +echo CXXFLAGS=${CXXFLAGS} + +echo "C++ compiler version:" +${CXX} --version || echo "${CXX} does not seem to support the --version flag" +${CXX} -v || echo "${CXX} does not seem to support the -v flag" + +echo "C compiler version:" +${CC} --version || echo "${CXX} does not seem to support the --version flag" +${CC} -v || echo "${CXX} does not seem to support the -v flag" diff --git a/deps/rapidjson/thirdparty/gtest/ci/travis.sh b/deps/rapidjson/thirdparty/gtest/ci/travis.sh new file mode 100644 index 0000000..9ff3bad --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/ci/travis.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env sh +set -evx + +. ci/get-nprocessors.sh + +# if possible, ask for the precise number of processors, +# otherwise take 2 processors as reasonable default; see +# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization +if [ -x /usr/bin/getconf ]; then + NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN) +else + NPROCESSORS=2 +fi +# as of 2017-09-04 Travis CI reports 32 processors, but GCC build +# crashes if parallelized too much (maybe memory consumption problem), +# so limit to 4 processors for the time being. +if [ $NPROCESSORS -gt 4 ] ; then + echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4." + NPROCESSORS=4 +fi +# Tell make to use the processors. No preceding '-' required. +MAKEFLAGS="j${NPROCESSORS}" +export MAKEFLAGS + +env | sort + +# Set default values to OFF for these variables if not specified. +: "${NO_EXCEPTION:=OFF}" +: "${NO_RTTI:=OFF}" +: "${COMPILER_IS_GNUCXX:=OFF}" + +mkdir build || true +cd build +cmake -Dgtest_build_samples=ON \ + -Dgtest_build_tests=ON \ + -Dgmock_build_tests=ON \ + -Dcxx_no_exception=$NO_EXCEPTION \ + -Dcxx_no_rtti=$NO_RTTI \ + -DCMAKE_COMPILER_IS_GNUCXX=$COMPILER_IS_GNUCXX \ + -DCMAKE_CXX_FLAGS=$CXX_FLAGS \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ + .. +make +CTEST_OUTPUT_ON_FAILURE=1 make test diff --git a/deps/rapidjson/thirdparty/gtest/configure.ac b/deps/rapidjson/thirdparty/gtest/configure.ac new file mode 100644 index 0000000..751b9ba --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/configure.ac @@ -0,0 +1,16 @@ +AC_INIT([Google C++ Mocking and Testing Frameworks], + [1.8.0], + [googlemock@googlegroups.com], + [googletest]) + +# Provide various options to initialize the Autoconf and configure processes. +AC_PREREQ([2.59]) +AC_CONFIG_SRCDIR([./README.md]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_SUBDIRS([googletest googlemock]) + +AM_INIT_AUTOMAKE + +# Output the generated files. No further autoconf macros may be used. +AC_OUTPUT diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/CHANGES b/deps/rapidjson/thirdparty/gtest/googlemock/CHANGES new file mode 100644 index 0000000..4328ece --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/CHANGES @@ -0,0 +1,126 @@ +Changes for 1.7.0: + +* All new improvements in Google Test 1.7.0. +* New feature: matchers DoubleNear(), FloatNear(), + NanSensitiveDoubleNear(), NanSensitiveFloatNear(), + UnorderedElementsAre(), UnorderedElementsAreArray(), WhenSorted(), + WhenSortedBy(), IsEmpty(), and SizeIs(). +* Improvement: Google Mock can now be built as a DLL. +* Improvement: when compiled by a C++11 compiler, matchers AllOf() + and AnyOf() can accept an arbitrary number of matchers. +* Improvement: when compiled by a C++11 compiler, matchers + ElementsAreArray() can accept an initializer list. +* Improvement: when exceptions are enabled, a mock method with no + default action now throws instead crashing the test. +* Improvement: added class testing::StringMatchResultListener to aid + definition of composite matchers. +* Improvement: function return types used in MOCK_METHOD*() macros can + now contain unprotected commas. +* Improvement (potentially breaking): EXPECT_THAT() and ASSERT_THAT() + are now more strict in ensuring that the value type and the matcher + type are compatible, catching potential bugs in tests. +* Improvement: Pointee() now works on an optional. +* Improvement: the ElementsAreArray() matcher can now take a vector or + iterator range as input, and makes a copy of its input elements + before the conversion to a Matcher. +* Improvement: the Google Mock Generator can now generate mocks for + some class templates. +* Bug fix: mock object destruction triggerred by another mock object's + destruction no longer hangs. +* Improvement: Google Mock Doctor works better with newer Clang and + GCC now. +* Compatibility fixes. +* Bug/warning fixes. + +Changes for 1.6.0: + +* Compilation is much faster and uses much less memory, especially + when the constructor and destructor of a mock class are moved out of + the class body. +* New matchers: Pointwise(), Each(). +* New actions: ReturnPointee() and ReturnRefOfCopy(). +* CMake support. +* Project files for Visual Studio 2010. +* AllOf() and AnyOf() can handle up-to 10 arguments now. +* Google Mock doctor understands Clang error messages now. +* SetArgPointee<> now accepts string literals. +* gmock_gen.py handles storage specifier macros and template return + types now. +* Compatibility fixes. +* Bug fixes and implementation clean-ups. +* Potentially incompatible changes: disables the harmful 'make install' + command in autotools. + +Potentially breaking changes: + +* The description string for MATCHER*() changes from Python-style + interpolation to an ordinary C++ string expression. +* SetArgumentPointee is deprecated in favor of SetArgPointee. +* Some non-essential project files for Visual Studio 2005 are removed. + +Changes for 1.5.0: + + * New feature: Google Mock can be safely used in multi-threaded tests + on platforms having pthreads. + * New feature: function for printing a value of arbitrary type. + * New feature: function ExplainMatchResult() for easy definition of + composite matchers. + * The new matcher API lets user-defined matchers generate custom + explanations more directly and efficiently. + * Better failure messages all around. + * NotNull() and IsNull() now work with smart pointers. + * Field() and Property() now work when the matcher argument is a pointer + passed by reference. + * Regular expression matchers on all platforms. + * Added GCC 4.0 support for Google Mock Doctor. + * Added gmock_all_test.cc for compiling most Google Mock tests + in a single file. + * Significantly cleaned up compiler warnings. + * Bug fixes, better test coverage, and implementation clean-ups. + + Potentially breaking changes: + + * Custom matchers defined using MatcherInterface or MakePolymorphicMatcher() + need to be updated after upgrading to Google Mock 1.5.0; matchers defined + using MATCHER or MATCHER_P* aren't affected. + * Dropped support for 'make install'. + +Changes for 1.4.0 (we skipped 1.2.* and 1.3.* to match the version of +Google Test): + + * Works in more environments: Symbian and minGW, Visual C++ 7.1. + * Lighter weight: comes with our own implementation of TR1 tuple (no + more dependency on Boost!). + * New feature: --gmock_catch_leaked_mocks for detecting leaked mocks. + * New feature: ACTION_TEMPLATE for defining templatized actions. + * New feature: the .After() clause for specifying expectation order. + * New feature: the .With() clause for specifying inter-argument + constraints. + * New feature: actions ReturnArg(), ReturnNew(...), and + DeleteArg(). + * New feature: matchers Key(), Pair(), Args<...>(), AllArgs(), IsNull(), + and Contains(). + * New feature: utility class MockFunction, useful for checkpoints, etc. + * New feature: functions Value(x, m) and SafeMatcherCast(m). + * New feature: copying a mock object is rejected at compile time. + * New feature: a script for fusing all Google Mock and Google Test + source files for easy deployment. + * Improved the Google Mock doctor to diagnose more diseases. + * Improved the Google Mock generator script. + * Compatibility fixes for Mac OS X and gcc. + * Bug fixes and implementation clean-ups. + +Changes for 1.1.0: + + * New feature: ability to use Google Mock with any testing framework. + * New feature: macros for easily defining new matchers + * New feature: macros for easily defining new actions. + * New feature: more container matchers. + * New feature: actions for accessing function arguments and throwing + exceptions. + * Improved the Google Mock doctor script for diagnosing compiler errors. + * Bug fixes and implementation clean-ups. + +Changes for 1.0.0: + + * Initial Open Source release of Google Mock diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/CMakeLists.txt b/deps/rapidjson/thirdparty/gtest/googlemock/CMakeLists.txt new file mode 100644 index 0000000..bac2e3b --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/CMakeLists.txt @@ -0,0 +1,242 @@ +######################################################################## +# CMake build script for Google Mock. +# +# To run the tests for Google Mock itself on Linux, use 'make test' or +# ctest. You can select which tests to run using 'ctest -R regex'. +# For more options, run 'ctest --help'. + +# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to +# make it prominent in the GUI. +option(BUILD_SHARED_LIBS "Build shared libraries (DLLs)." OFF) + +option(gmock_build_tests "Build all of Google Mock's own tests." OFF) + +# A directory to find Google Test sources. +if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/gtest/CMakeLists.txt") + set(gtest_dir gtest) +else() + set(gtest_dir ../googletest) +endif() + +# Defines pre_project_set_up_hermetic_build() and set_up_hermetic_build(). +include("${gtest_dir}/cmake/hermetic_build.cmake" OPTIONAL) + +if (COMMAND pre_project_set_up_hermetic_build) + # Google Test also calls hermetic setup functions from add_subdirectory, + # although its changes will not affect things at the current scope. + pre_project_set_up_hermetic_build() +endif() + +######################################################################## +# +# Project-wide settings + +# Name of the project. +# +# CMake files in this project can refer to the root source directory +# as ${gmock_SOURCE_DIR} and to the root binary directory as +# ${gmock_BINARY_DIR}. +# Language "C" is required for find_package(Threads). +if (CMAKE_VERSION VERSION_LESS 3.0) + project(gmock CXX C) +else() + cmake_policy(SET CMP0048 NEW) + project(gmock VERSION 1.9.0 LANGUAGES CXX C) +endif() +cmake_minimum_required(VERSION 2.6.4) + +if (COMMAND set_up_hermetic_build) + set_up_hermetic_build() +endif() + +# Instructs CMake to process Google Test's CMakeLists.txt and add its +# targets to the current scope. We are placing Google Test's binary +# directory in a subdirectory of our own as VC compilation may break +# if they are the same (the default). +add_subdirectory("${gtest_dir}" "${gmock_BINARY_DIR}/gtest") + +# Although Google Test's CMakeLists.txt calls this function, the +# changes there don't affect the current scope. Therefore we have to +# call it again here. +config_compiler_and_linker() # from ${gtest_dir}/cmake/internal_utils.cmake + +# Adds Google Mock's and Google Test's header directories to the search path. +include_directories("${gmock_SOURCE_DIR}/include" + "${gmock_SOURCE_DIR}" + "${gtest_SOURCE_DIR}/include" + # This directory is needed to build directly from Google + # Test sources. + "${gtest_SOURCE_DIR}") + +# Summary of tuple support for Microsoft Visual Studio: +# Compiler version(MS) version(cmake) Support +# ---------- ----------- -------------- ----------------------------- +# <= VS 2010 <= 10 <= 1600 Use Google Tests's own tuple. +# VS 2012 11 1700 std::tr1::tuple + _VARIADIC_MAX=10 +# VS 2013 12 1800 std::tr1::tuple +# VS 2015 14 1900 std::tuple +# VS 2017 15 >= 1910 std::tuple +if (MSVC AND MSVC_VERSION EQUAL 1700) + add_definitions(/D _VARIADIC_MAX=10) +endif() + +######################################################################## +# +# Defines the gmock & gmock_main libraries. User tests should link +# with one of them. + +# Google Mock libraries. We build them using more strict warnings than what +# are used for other targets, to ensure that Google Mock can be compiled by +# a user aggressive about warnings. +if (MSVC) + cxx_library(gmock + "${cxx_strict}" + "${gtest_dir}/src/gtest-all.cc" + src/gmock-all.cc) + + cxx_library(gmock_main + "${cxx_strict}" + "${gtest_dir}/src/gtest-all.cc" + src/gmock-all.cc + src/gmock_main.cc) +else() + cxx_library(gmock "${cxx_strict}" src/gmock-all.cc) + target_link_libraries(gmock gtest) + cxx_library(gmock_main "${cxx_strict}" src/gmock_main.cc) + target_link_libraries(gmock_main gmock) +endif() + +# If the CMake version supports it, attach header directory information +# to the targets for when we are part of a parent build (ie being pulled +# in via add_subdirectory() rather than being a standalone build). +if (DEFINED CMAKE_VERSION AND NOT "${CMAKE_VERSION}" VERSION_LESS "2.8.11") + target_include_directories(gmock SYSTEM INTERFACE "${gmock_SOURCE_DIR}/include") + target_include_directories(gmock_main SYSTEM INTERFACE "${gmock_SOURCE_DIR}/include") +endif() + +######################################################################## +# +# Install rules +if(INSTALL_GMOCK) + install(TARGETS gmock gmock_main + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") + install(DIRECTORY "${gmock_SOURCE_DIR}/include/gmock" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + + # configure and install pkgconfig files + configure_file( + cmake/gmock.pc.in + "${CMAKE_BINARY_DIR}/gmock.pc" + @ONLY) + configure_file( + cmake/gmock_main.pc.in + "${CMAKE_BINARY_DIR}/gmock_main.pc" + @ONLY) + install(FILES "${CMAKE_BINARY_DIR}/gmock.pc" "${CMAKE_BINARY_DIR}/gmock_main.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +endif() + +######################################################################## +# +# Google Mock's own tests. +# +# You can skip this section if you aren't interested in testing +# Google Mock itself. +# +# The tests are not built by default. To build them, set the +# gmock_build_tests option to ON. You can do it by running ccmake +# or specifying the -Dgmock_build_tests=ON flag when running cmake. + +if (gmock_build_tests) + # This must be set in the root directory for the tests to be run by + # 'make test' or ctest. + enable_testing() + + ############################################################ + # C++ tests built with standard compiler flags. + + cxx_test(gmock-actions_test gmock_main) + cxx_test(gmock-cardinalities_test gmock_main) + cxx_test(gmock_ex_test gmock_main) + cxx_test(gmock-generated-actions_test gmock_main) + cxx_test(gmock-generated-function-mockers_test gmock_main) + cxx_test(gmock-generated-internal-utils_test gmock_main) + cxx_test(gmock-generated-matchers_test gmock_main) + cxx_test(gmock-internal-utils_test gmock_main) + cxx_test(gmock-matchers_test gmock_main) + cxx_test(gmock-more-actions_test gmock_main) + cxx_test(gmock-nice-strict_test gmock_main) + cxx_test(gmock-port_test gmock_main) + cxx_test(gmock-spec-builders_test gmock_main) + cxx_test(gmock_link_test gmock_main test/gmock_link2_test.cc) + cxx_test(gmock_test gmock_main) + + if (DEFINED GTEST_HAS_PTHREAD) + cxx_test(gmock_stress_test gmock) + endif() + + # gmock_all_test is commented to save time building and running tests. + # Uncomment if necessary. + # cxx_test(gmock_all_test gmock_main) + + ############################################################ + # C++ tests built with non-standard compiler flags. + + if (MSVC) + cxx_library(gmock_main_no_exception "${cxx_no_exception}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + if (MSVC_VERSION LESS 1600) # 1600 is Visual Studio 2010. + # Visual Studio 2010, 2012, and 2013 define symbols in std::tr1 that + # conflict with our own definitions. Therefore using our own tuple does not + # work on those compilers. + cxx_library(gmock_main_use_own_tuple "${cxx_use_own_tuple}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + cxx_test_with_flags(gmock_use_own_tuple_test "${cxx_use_own_tuple}" + gmock_main_use_own_tuple test/gmock-spec-builders_test.cc) + endif() + else() + cxx_library(gmock_main_no_exception "${cxx_no_exception}" src/gmock_main.cc) + target_link_libraries(gmock_main_no_exception gmock) + + cxx_library(gmock_main_no_rtti "${cxx_no_rtti}" src/gmock_main.cc) + target_link_libraries(gmock_main_no_rtti gmock) + + cxx_library(gmock_main_use_own_tuple "${cxx_use_own_tuple}" src/gmock_main.cc) + target_link_libraries(gmock_main_use_own_tuple gmock) + endif() + cxx_test_with_flags(gmock-more-actions_no_exception_test "${cxx_no_exception}" + gmock_main_no_exception test/gmock-more-actions_test.cc) + + cxx_test_with_flags(gmock_no_rtti_test "${cxx_no_rtti}" + gmock_main_no_rtti test/gmock-spec-builders_test.cc) + + cxx_shared_library(shared_gmock_main "${cxx_default}" + "${gtest_dir}/src/gtest-all.cc" src/gmock-all.cc src/gmock_main.cc) + + # Tests that a binary can be built with Google Mock as a shared library. On + # some system configurations, it may not possible to run the binary without + # knowing more details about the system configurations. We do not try to run + # this binary. To get a more robust shared library coverage, configure with + # -DBUILD_SHARED_LIBS=ON. + cxx_executable_with_flags(shared_gmock_test_ "${cxx_default}" + shared_gmock_main test/gmock-spec-builders_test.cc) + set_target_properties(shared_gmock_test_ + PROPERTIES + COMPILE_DEFINITIONS "GTEST_LINKED_AS_SHARED_LIBRARY=1") + + ############################################################ + # Python tests. + + cxx_executable(gmock_leak_test_ test gmock_main) + py_test(gmock_leak_test) + + cxx_executable(gmock_output_test_ test gmock) + py_test(gmock_output_test) +endif() diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/CONTRIBUTORS b/deps/rapidjson/thirdparty/gtest/googlemock/CONTRIBUTORS new file mode 100644 index 0000000..6e9ae36 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/CONTRIBUTORS @@ -0,0 +1,40 @@ +# This file contains a list of people who've made non-trivial +# contribution to the Google C++ Mocking Framework project. People +# who commit code to the project are encouraged to add their names +# here. Please keep the list sorted by first names. + +Benoit Sigoure +Bogdan Piloca +Chandler Carruth +Dave MacLachlan +David Anderson +Dean Sturtevant +Gene Volovich +Hal Burch +Jeffrey Yasskin +Jim Keller +Joe Walnes +Jon Wray +Keir Mierle +Keith Ray +Kostya Serebryany +Lev Makhlis +Manuel Klimek +Mario Tanev +Mark Paskin +Markus Heule +Matthew Simmons +Mike Bland +Neal Norwitz +Nermin Ozkiranartli +Owen Carlsen +Paneendra Ba +Paul Menage +Piotr Kaminski +Russ Rufer +Sverre Sundsdal +Takeshi Yoshino +Vadim Berman +Vlad Losev +Wolfgang Klier +Zhanyong Wan diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/LICENSE b/deps/rapidjson/thirdparty/gtest/googlemock/LICENSE new file mode 100644 index 0000000..1941a11 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/LICENSE @@ -0,0 +1,28 @@ +Copyright 2008, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +OWNER 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. diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/Makefile.am b/deps/rapidjson/thirdparty/gtest/googlemock/Makefile.am new file mode 100644 index 0000000..9adbc51 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/Makefile.am @@ -0,0 +1,224 @@ +# Automake file + +# Nonstandard package files for distribution. +EXTRA_DIST = LICENSE + +# We may need to build our internally packaged gtest. If so, it will be +# included in the 'subdirs' variable. +SUBDIRS = $(subdirs) + +# This is generated by the configure script, so clean it for distribution. +DISTCLEANFILES = scripts/gmock-config + +# We define the global AM_CPPFLAGS as everything we compile includes from these +# directories. +AM_CPPFLAGS = $(GTEST_CPPFLAGS) -I$(srcdir)/include + +# Modifies compiler and linker flags for pthreads compatibility. +if HAVE_PTHREADS + AM_CXXFLAGS = @PTHREAD_CFLAGS@ -DGTEST_HAS_PTHREAD=1 + AM_LIBS = @PTHREAD_LIBS@ +endif + +# Build rules for libraries. +lib_LTLIBRARIES = lib/libgmock.la lib/libgmock_main.la + +lib_libgmock_la_SOURCES = src/gmock-all.cc + +pkginclude_HEADERS = \ + include/gmock/gmock-actions.h \ + include/gmock/gmock-cardinalities.h \ + include/gmock/gmock-generated-actions.h \ + include/gmock/gmock-generated-function-mockers.h \ + include/gmock/gmock-generated-matchers.h \ + include/gmock/gmock-generated-nice-strict.h \ + include/gmock/gmock-matchers.h \ + include/gmock/gmock-more-actions.h \ + include/gmock/gmock-more-matchers.h \ + include/gmock/gmock-spec-builders.h \ + include/gmock/gmock.h + +pkginclude_internaldir = $(pkgincludedir)/internal +pkginclude_internal_HEADERS = \ + include/gmock/internal/gmock-generated-internal-utils.h \ + include/gmock/internal/gmock-internal-utils.h \ + include/gmock/internal/gmock-port.h \ + include/gmock/internal/custom/gmock-generated-actions.h \ + include/gmock/internal/custom/gmock-matchers.h \ + include/gmock/internal/custom/gmock-port.h + +lib_libgmock_main_la_SOURCES = src/gmock_main.cc +lib_libgmock_main_la_LIBADD = lib/libgmock.la + +# Build rules for tests. Automake's naming for some of these variables isn't +# terribly obvious, so this is a brief reference: +# +# TESTS -- Programs run automatically by "make check" +# check_PROGRAMS -- Programs built by "make check" but not necessarily run + +TESTS= +check_PROGRAMS= +AM_LDFLAGS = $(GTEST_LDFLAGS) + +# This exercises all major components of Google Mock. It also +# verifies that libgmock works. +TESTS += test/gmock-spec-builders_test +check_PROGRAMS += test/gmock-spec-builders_test +test_gmock_spec_builders_test_SOURCES = test/gmock-spec-builders_test.cc +test_gmock_spec_builders_test_LDADD = $(GTEST_LIBS) lib/libgmock.la + +# This tests using Google Mock in multiple translation units. It also +# verifies that libgmock_main and libgmock work. +TESTS += test/gmock_link_test +check_PROGRAMS += test/gmock_link_test +test_gmock_link_test_SOURCES = \ + test/gmock_link2_test.cc \ + test/gmock_link_test.cc \ + test/gmock_link_test.h +test_gmock_link_test_LDADD = $(GTEST_LIBS) lib/libgmock_main.la lib/libgmock.la + +if HAVE_PYTHON + # Tests that fused gmock files compile and work. + TESTS += test/gmock_fused_test + check_PROGRAMS += test/gmock_fused_test + test_gmock_fused_test_SOURCES = \ + fused-src/gmock-gtest-all.cc \ + fused-src/gmock/gmock.h \ + fused-src/gmock_main.cc \ + fused-src/gtest/gtest.h \ + test/gmock_test.cc + test_gmock_fused_test_CPPFLAGS = -I"$(srcdir)/fused-src" +endif + +# Google Mock source files that we don't compile directly. +GMOCK_SOURCE_INGLUDES = \ + src/gmock-cardinalities.cc \ + src/gmock-internal-utils.cc \ + src/gmock-matchers.cc \ + src/gmock-spec-builders.cc \ + src/gmock.cc + +EXTRA_DIST += $(GMOCK_SOURCE_INGLUDES) + +# C++ tests that we don't compile using autotools. +EXTRA_DIST += \ + test/gmock-actions_test.cc \ + test/gmock_all_test.cc \ + test/gmock-cardinalities_test.cc \ + test/gmock_ex_test.cc \ + test/gmock-generated-actions_test.cc \ + test/gmock-generated-function-mockers_test.cc \ + test/gmock-generated-internal-utils_test.cc \ + test/gmock-generated-matchers_test.cc \ + test/gmock-internal-utils_test.cc \ + test/gmock-matchers_test.cc \ + test/gmock-more-actions_test.cc \ + test/gmock-nice-strict_test.cc \ + test/gmock-port_test.cc \ + test/gmock_stress_test.cc + +# Python tests, which we don't run using autotools. +EXTRA_DIST += \ + test/gmock_leak_test.py \ + test/gmock_leak_test_.cc \ + test/gmock_output_test.py \ + test/gmock_output_test_.cc \ + test/gmock_output_test_golden.txt \ + test/gmock_test_utils.py + +# Nonstandard package files for distribution. +EXTRA_DIST += \ + CHANGES \ + CONTRIBUTORS \ + make/Makefile + +# Pump scripts for generating Google Mock headers. +# TODO(chandlerc@google.com): automate the generation of *.h from *.h.pump. +EXTRA_DIST += \ + include/gmock/gmock-generated-actions.h.pump \ + include/gmock/gmock-generated-function-mockers.h.pump \ + include/gmock/gmock-generated-matchers.h.pump \ + include/gmock/gmock-generated-nice-strict.h.pump \ + include/gmock/internal/gmock-generated-internal-utils.h.pump \ + include/gmock/internal/custom/gmock-generated-actions.h.pump + +# Script for fusing Google Mock and Google Test source files. +EXTRA_DIST += scripts/fuse_gmock_files.py + +# The Google Mock Generator tool from the cppclean project. +EXTRA_DIST += \ + scripts/generator/LICENSE \ + scripts/generator/README \ + scripts/generator/README.cppclean \ + scripts/generator/cpp/__init__.py \ + scripts/generator/cpp/ast.py \ + scripts/generator/cpp/gmock_class.py \ + scripts/generator/cpp/keywords.py \ + scripts/generator/cpp/tokenize.py \ + scripts/generator/cpp/utils.py \ + scripts/generator/gmock_gen.py + +# Script for diagnosing compiler errors in programs that use Google +# Mock. +EXTRA_DIST += scripts/gmock_doctor.py + +# CMake scripts. +EXTRA_DIST += \ + CMakeLists.txt + +# Microsoft Visual Studio 2005 projects. +EXTRA_DIST += \ + msvc/2005/gmock.sln \ + msvc/2005/gmock.vcproj \ + msvc/2005/gmock_config.vsprops \ + msvc/2005/gmock_main.vcproj \ + msvc/2005/gmock_test.vcproj + +# Microsoft Visual Studio 2010 projects. +EXTRA_DIST += \ + msvc/2010/gmock.sln \ + msvc/2010/gmock.vcxproj \ + msvc/2010/gmock_config.props \ + msvc/2010/gmock_main.vcxproj \ + msvc/2010/gmock_test.vcxproj + +if HAVE_PYTHON +# gmock_test.cc does not really depend on files generated by the +# fused-gmock-internal rule. However, gmock_test.o does, and it is +# important to include test/gmock_test.cc as part of this rule in order to +# prevent compiling gmock_test.o until all dependent files have been +# generated. +$(test_gmock_fused_test_SOURCES): fused-gmock-internal + +# TODO(vladl@google.com): Find a way to add Google Tests's sources here. +fused-gmock-internal: $(pkginclude_HEADERS) $(pkginclude_internal_HEADERS) \ + $(lib_libgmock_la_SOURCES) $(GMOCK_SOURCE_INGLUDES) \ + $(lib_libgmock_main_la_SOURCES) \ + scripts/fuse_gmock_files.py + mkdir -p "$(srcdir)/fused-src" + chmod -R u+w "$(srcdir)/fused-src" + rm -f "$(srcdir)/fused-src/gtest/gtest.h" + rm -f "$(srcdir)/fused-src/gmock/gmock.h" + rm -f "$(srcdir)/fused-src/gmock-gtest-all.cc" + "$(srcdir)/scripts/fuse_gmock_files.py" "$(srcdir)/fused-src" + cp -f "$(srcdir)/src/gmock_main.cc" "$(srcdir)/fused-src" + +maintainer-clean-local: + rm -rf "$(srcdir)/fused-src" +endif + +# Death tests may produce core dumps in the build directory. In case +# this happens, clean them to keep distcleancheck happy. +CLEANFILES = core + +# Disables 'make install' as installing a compiled version of Google +# Mock can lead to undefined behavior due to violation of the +# One-Definition Rule. + +install-exec-local: + echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Mock into your build system." + false + +install-data-local: + echo "'make install' is dangerous and not supported. Instead, see README for how to integrate Google Mock into your build system." + false diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/README.md b/deps/rapidjson/thirdparty/gtest/googlemock/README.md new file mode 100644 index 0000000..ad374de --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/README.md @@ -0,0 +1,344 @@ +## Google Mock ## + +The Google C++ mocking framework. + +### Overview ### + +Google's framework for writing and using C++ mock classes. +It can help you derive better designs of your system and write better tests. + +It is inspired by: + + * [jMock](http://www.jmock.org/), + * [EasyMock](http://www.easymock.org/), and + * [Hamcrest](http://code.google.com/p/hamcrest/), + +and designed with C++'s specifics in mind. + +Google mock: + + * lets you create mock classes trivially using simple macros. + * supports a rich set of matchers and actions. + * handles unordered, partially ordered, or completely ordered expectations. + * is extensible by users. + +We hope you find it useful! + +### Features ### + + * Provides a declarative syntax for defining mocks. + * Can easily define partial (hybrid) mocks, which are a cross of real + and mock objects. + * Handles functions of arbitrary types and overloaded functions. + * Comes with a rich set of matchers for validating function arguments. + * Uses an intuitive syntax for controlling the behavior of a mock. + * Does automatic verification of expectations (no record-and-replay needed). + * Allows arbitrary (partial) ordering constraints on + function calls to be expressed,. + * Lets an user extend it by defining new matchers and actions. + * Does not use exceptions. + * Is easy to learn and use. + +Please see the project page above for more information as well as the +mailing list for questions, discussions, and development. There is +also an IRC channel on OFTC (irc.oftc.net) #gtest available. Please +join us! + +Please note that code under [scripts/generator](scripts/generator/) is +from [cppclean](http://code.google.com/p/cppclean/) and released under +the Apache License, which is different from Google Mock's license. + +## Getting Started ## + +If you are new to the project, we suggest that you read the user +documentation in the following order: + + * Learn the [basics](../../master/googletest/docs/primer.md) of + Google Test, if you choose to use Google Mock with it (recommended). + * Read [Google Mock for Dummies](../../master/googlemock/docs/ForDummies.md). + * Read the instructions below on how to build Google Mock. + +You can also watch Zhanyong's [talk](http://www.youtube.com/watch?v=sYpCyLI47rM) on Google Mock's usage and implementation. + +Once you understand the basics, check out the rest of the docs: + + * [CheatSheet](../../master/googlemock/docs/CheatSheet.md) - all the commonly used stuff + at a glance. + * [CookBook](../../master/googlemock/docs/CookBook.md) - recipes for getting things done, + including advanced techniques. + +If you need help, please check the +[KnownIssues](docs/KnownIssues.md) and +[FrequentlyAskedQuestions](docs/FrequentlyAskedQuestions.md) before +posting a question on the +[discussion group](http://groups.google.com/group/googlemock). + + +### Using Google Mock Without Google Test ### + +Google Mock is not a testing framework itself. Instead, it needs a +testing framework for writing tests. Google Mock works seamlessly +with [Google Test](https://github.com/google/googletest), but +you can also use it with [any C++ testing framework](../../master/googlemock/docs/ForDummies.md#using-google-mock-with-any-testing-framework). + +### Requirements for End Users ### + +Google Mock is implemented on top of [Google Test]( +http://github.com/google/googletest/), and depends on it. +You must use the bundled version of Google Test when using Google Mock. + +You can also easily configure Google Mock to work with another testing +framework, although it will still need Google Test. Please read +["Using_Google_Mock_with_Any_Testing_Framework"]( + ../../master/googlemock/docs/ForDummies.md#using-google-mock-with-any-testing-framework) +for instructions. + +Google Mock depends on advanced C++ features and thus requires a more +modern compiler. The following are needed to use Google Mock: + +#### Linux Requirements #### + + * GNU-compatible Make or "gmake" + * POSIX-standard shell + * POSIX(-2) Regular Expressions (regex.h) + * C++98-standard-compliant compiler (e.g. GCC 3.4 or newer) + +#### Windows Requirements #### + + * Microsoft Visual C++ 8.0 SP1 or newer + +#### Mac OS X Requirements #### + + * Mac OS X 10.4 Tiger or newer + * Developer Tools Installed + +### Requirements for Contributors ### + +We welcome patches. If you plan to contribute a patch, you need to +build Google Mock and its tests, which has further requirements: + + * Automake version 1.9 or newer + * Autoconf version 2.59 or newer + * Libtool / Libtoolize + * Python version 2.3 or newer (for running some of the tests and + re-generating certain source files from templates) + +### Building Google Mock ### + +#### Using CMake #### + +If you have CMake available, it is recommended that you follow the +[build instructions][gtest_cmakebuild] +as described for Google Test. + +If are using Google Mock with an +existing CMake project, the section +[Incorporating Into An Existing CMake Project][gtest_incorpcmake] +may be of particular interest. +To make it work for Google Mock you will need to change + + target_link_libraries(example gtest_main) + +to + + target_link_libraries(example gmock_main) + +This works because `gmock_main` library is compiled with Google Test. +However, it does not automatically add Google Test includes. +Therefore you will also have to change + + if (CMAKE_VERSION VERSION_LESS 2.8.11) + include_directories("${gtest_SOURCE_DIR}/include") + endif() + +to + + if (CMAKE_VERSION VERSION_LESS 2.8.11) + include_directories(BEFORE SYSTEM + "${gtest_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include") + else() + target_include_directories(gmock_main SYSTEM BEFORE INTERFACE + "${gtest_SOURCE_DIR}/include" "${gmock_SOURCE_DIR}/include") + endif() + +This will addtionally mark Google Mock includes as system, which will +silence compiler warnings when compiling your tests using clang with +`-Wpedantic -Wall -Wextra -Wconversion`. + + +#### Preparing to Build (Unix only) #### + +If you are using a Unix system and plan to use the GNU Autotools build +system to build Google Mock (described below), you'll need to +configure it now. + +To prepare the Autotools build system: + + cd googlemock + autoreconf -fvi + +To build Google Mock and your tests that use it, you need to tell your +build system where to find its headers and source files. The exact +way to do it depends on which build system you use, and is usually +straightforward. + +This section shows how you can integrate Google Mock into your +existing build system. + +Suppose you put Google Mock in directory `${GMOCK_DIR}` and Google Test +in `${GTEST_DIR}` (the latter is `${GMOCK_DIR}/gtest` by default). To +build Google Mock, create a library build target (or a project as +called by Visual Studio and Xcode) to compile + + ${GTEST_DIR}/src/gtest-all.cc and ${GMOCK_DIR}/src/gmock-all.cc + +with + + ${GTEST_DIR}/include and ${GMOCK_DIR}/include + +in the system header search path, and + + ${GTEST_DIR} and ${GMOCK_DIR} + +in the normal header search path. Assuming a Linux-like system and gcc, +something like the following will do: + + g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \ + -isystem ${GMOCK_DIR}/include -I${GMOCK_DIR} \ + -pthread -c ${GTEST_DIR}/src/gtest-all.cc + g++ -isystem ${GTEST_DIR}/include -I${GTEST_DIR} \ + -isystem ${GMOCK_DIR}/include -I${GMOCK_DIR} \ + -pthread -c ${GMOCK_DIR}/src/gmock-all.cc + ar -rv libgmock.a gtest-all.o gmock-all.o + +(We need -pthread as Google Test and Google Mock use threads.) + +Next, you should compile your test source file with +${GTEST\_DIR}/include and ${GMOCK\_DIR}/include in the header search +path, and link it with gmock and any other necessary libraries: + + g++ -isystem ${GTEST_DIR}/include -isystem ${GMOCK_DIR}/include \ + -pthread path/to/your_test.cc libgmock.a -o your_test + +As an example, the make/ directory contains a Makefile that you can +use to build Google Mock on systems where GNU make is available +(e.g. Linux, Mac OS X, and Cygwin). It doesn't try to build Google +Mock's own tests. Instead, it just builds the Google Mock library and +a sample test. You can use it as a starting point for your own build +script. + +If the default settings are correct for your environment, the +following commands should succeed: + + cd ${GMOCK_DIR}/make + make + ./gmock_test + +If you see errors, try to tweak the contents of +[make/Makefile](make/Makefile) to make them go away. + +### Windows ### + +The msvc/2005 directory contains VC++ 2005 projects and the msvc/2010 +directory contains VC++ 2010 projects for building Google Mock and +selected tests. + +Change to the appropriate directory and run "msbuild gmock.sln" to +build the library and tests (or open the gmock.sln in the MSVC IDE). +If you want to create your own project to use with Google Mock, you'll +have to configure it to use the `gmock_config` propety sheet. For that: + + * Open the Property Manager window (View | Other Windows | Property Manager) + * Right-click on your project and select "Add Existing Property Sheet..." + * Navigate to `gmock_config.vsprops` or `gmock_config.props` and select it. + * In Project Properties | Configuration Properties | General | Additional + Include Directories, type /include. + +### Tweaking Google Mock ### + +Google Mock can be used in diverse environments. The default +configuration may not work (or may not work well) out of the box in +some environments. However, you can easily tweak Google Mock by +defining control macros on the compiler command line. Generally, +these macros are named like `GTEST_XYZ` and you define them to either 1 +or 0 to enable or disable a certain feature. + +We list the most frequently used macros below. For a complete list, +see file [${GTEST\_DIR}/include/gtest/internal/gtest-port.h]( +../googletest/include/gtest/internal/gtest-port.h). + +### Choosing a TR1 Tuple Library ### + +Google Mock uses the C++ Technical Report 1 (TR1) tuple library +heavily. Unfortunately TR1 tuple is not yet widely available with all +compilers. The good news is that Google Test 1.4.0+ implements a +subset of TR1 tuple that's enough for Google Mock's need. Google Mock +will automatically use that implementation when the compiler doesn't +provide TR1 tuple. + +Usually you don't need to care about which tuple library Google Test +and Google Mock use. However, if your project already uses TR1 tuple, +you need to tell Google Test and Google Mock to use the same TR1 tuple +library the rest of your project uses, or the two tuple +implementations will clash. To do that, add + + -DGTEST_USE_OWN_TR1_TUPLE=0 + +to the compiler flags while compiling Google Test, Google Mock, and +your tests. If you want to force Google Test and Google Mock to use +their own tuple library, just add + + -DGTEST_USE_OWN_TR1_TUPLE=1 + +to the compiler flags instead. + +If you want to use Boost's TR1 tuple library with Google Mock, please +refer to the Boost website (http://www.boost.org/) for how to obtain +it and set it up. + +### As a Shared Library (DLL) ### + +Google Mock is compact, so most users can build and link it as a static +library for the simplicity. Google Mock can be used as a DLL, but the +same DLL must contain Google Test as well. See +[Google Test's README][gtest_readme] +for instructions on how to set up necessary compiler settings. + +### Tweaking Google Mock ### + +Most of Google Test's control macros apply to Google Mock as well. +Please see [Google Test's README][gtest_readme] for how to tweak them. + +### Upgrading from an Earlier Version ### + +We strive to keep Google Mock releases backward compatible. +Sometimes, though, we have to make some breaking changes for the +users' long-term benefits. This section describes what you'll need to +do if you are upgrading from an earlier version of Google Mock. + +#### Upgrading from 1.1.0 or Earlier #### + +You may need to explicitly enable or disable Google Test's own TR1 +tuple library. See the instructions in section "[Choosing a TR1 Tuple +Library](../googletest/#choosing-a-tr1-tuple-library)". + +#### Upgrading from 1.4.0 or Earlier #### + +On platforms where the pthread library is available, Google Test and +Google Mock use it in order to be thread-safe. For this to work, you +may need to tweak your compiler and/or linker flags. Please see the +"[Multi-threaded Tests](../googletest#multi-threaded-tests +)" section in file Google Test's README for what you may need to do. + +If you have custom matchers defined using `MatcherInterface` or +`MakePolymorphicMatcher()`, you'll need to update their definitions to +use the new matcher API ( +[monomorphic](./docs/CookBook.md#writing-new-monomorphic-matchers), +[polymorphic](./docs/CookBook.md#writing-new-polymorphic-matchers)). +Matchers defined using `MATCHER()` or `MATCHER_P*()` aren't affected. + +Happy testing! + +[gtest_readme]: ../googletest/README.md "googletest" +[gtest_cmakebuild]: ../googletest/README.md#using-cmake "Using CMake" +[gtest_incorpcmake]: ../googletest/README.md#incorporating-into-an-existing-cmake-project "Incorporating Into An Existing CMake Project" diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock.pc.in b/deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock.pc.in new file mode 100644 index 0000000..c441642 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock.pc.in @@ -0,0 +1,9 @@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: gmock +Description: GoogleMock (without main() function) +Version: @PROJECT_VERSION@ +URL: https://github.com/google/googletest +Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock_main.pc.in b/deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock_main.pc.in new file mode 100644 index 0000000..c377dba --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/cmake/gmock_main.pc.in @@ -0,0 +1,9 @@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ + +Name: gmock_main +Description: GoogleMock (with main() function) +Version: @PROJECT_VERSION@ +URL: https://github.com/google/googletest +Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/configure.ac b/deps/rapidjson/thirdparty/gtest/googlemock/configure.ac new file mode 100644 index 0000000..cb5e1a6 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/configure.ac @@ -0,0 +1,146 @@ +m4_include(../googletest/m4/acx_pthread.m4) + +AC_INIT([Google C++ Mocking Framework], + [1.8.0], + [googlemock@googlegroups.com], + [gmock]) + +# Provide various options to initialize the Autoconf and configure processes. +AC_PREREQ([2.59]) +AC_CONFIG_SRCDIR([./LICENSE]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_HEADERS([build-aux/config.h]) +AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([scripts/gmock-config], [chmod +x scripts/gmock-config]) + +# Initialize Automake with various options. We require at least v1.9, prevent +# pedantic complaints about package files, and enable various distribution +# targets. +AM_INIT_AUTOMAKE([1.9 dist-bzip2 dist-zip foreign subdir-objects]) + +# Check for programs used in building Google Test. +AC_PROG_CC +AC_PROG_CXX +AC_LANG([C++]) +AC_PROG_LIBTOOL + +# TODO(chandlerc@google.com): Currently we aren't running the Python tests +# against the interpreter detected by AM_PATH_PYTHON, and so we condition +# HAVE_PYTHON by requiring "python" to be in the PATH, and that interpreter's +# version to be >= 2.3. This will allow the scripts to use a "/usr/bin/env" +# hashbang. +PYTHON= # We *do not* allow the user to specify a python interpreter +AC_PATH_PROG([PYTHON],[python],[:]) +AS_IF([test "$PYTHON" != ":"], + [AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])]) +AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"]) + +# TODO(chandlerc@google.com) Check for the necessary system headers. + +# Configure pthreads. +AC_ARG_WITH([pthreads], + [AS_HELP_STRING([--with-pthreads], + [use pthreads (default is yes)])], + [with_pthreads=$withval], + [with_pthreads=check]) + +have_pthreads=no +AS_IF([test "x$with_pthreads" != "xno"], + [ACX_PTHREAD( + [], + [AS_IF([test "x$with_pthreads" != "xcheck"], + [AC_MSG_FAILURE( + [--with-pthreads was specified, but unable to be used])])]) + have_pthreads="$acx_pthread_ok"]) +AM_CONDITIONAL([HAVE_PTHREADS],[test "x$have_pthreads" == "xyes"]) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_LIBS) + +# GoogleMock currently has hard dependencies upon GoogleTest above and beyond +# running its own test suite, so we both provide our own version in +# a subdirectory and provide some logic to use a custom version or a system +# installed version. +AC_ARG_WITH([gtest], + [AS_HELP_STRING([--with-gtest], + [Specifies how to find the gtest package. If no + arguments are given, the default behavior, a + system installed gtest will be used if present, + and an internal version built otherwise. If a + path is provided, the gtest built or installed at + that prefix will be used.])], + [], + [with_gtest=yes]) +AC_ARG_ENABLE([external-gtest], + [AS_HELP_STRING([--disable-external-gtest], + [Disables any detection or use of a system + installed or user provided gtest. Any option to + '--with-gtest' is ignored. (Default is enabled.)]) + ], [], [enable_external_gtest=yes]) +AS_IF([test "x$with_gtest" == "xno"], + [AC_MSG_ERROR([dnl +Support for GoogleTest was explicitly disabled. Currently GoogleMock has a hard +dependency upon GoogleTest to build, please provide a version, or allow +GoogleMock to use any installed version and fall back upon its internal +version.])]) + +# Setup various GTEST variables. TODO(chandlerc@google.com): When these are +# used below, they should be used such that any pre-existing values always +# trump values we set them to, so that they can be used to selectively override +# details of the detection process. +AC_ARG_VAR([GTEST_CONFIG], + [The exact path of Google Test's 'gtest-config' script.]) +AC_ARG_VAR([GTEST_CPPFLAGS], + [C-like preprocessor flags for Google Test.]) +AC_ARG_VAR([GTEST_CXXFLAGS], + [C++ compile flags for Google Test.]) +AC_ARG_VAR([GTEST_LDFLAGS], + [Linker path and option flags for Google Test.]) +AC_ARG_VAR([GTEST_LIBS], + [Library linking flags for Google Test.]) +AC_ARG_VAR([GTEST_VERSION], + [The version of Google Test available.]) +HAVE_BUILT_GTEST="no" + +GTEST_MIN_VERSION="1.8.0" + +AS_IF([test "x${enable_external_gtest}" = "xyes"], + [# Begin filling in variables as we are able. + AS_IF([test "x${with_gtest}" != "xyes"], + [AS_IF([test -x "${with_gtest}/scripts/gtest-config"], + [GTEST_CONFIG="${with_gtest}/scripts/gtest-config"], + [GTEST_CONFIG="${with_gtest}/bin/gtest-config"]) + AS_IF([test -x "${GTEST_CONFIG}"], [], + [AC_MSG_ERROR([dnl +Unable to locate either a built or installed Google Test at '${with_gtest}'.]) + ])]) + + AS_IF([test -x "${GTEST_CONFIG}"], [], + [AC_PATH_PROG([GTEST_CONFIG], [gtest-config])]) + AS_IF([test -x "${GTEST_CONFIG}"], + [AC_MSG_CHECKING([for Google Test version >= ${GTEST_MIN_VERSION}]) + AS_IF([${GTEST_CONFIG} --min-version=${GTEST_MIN_VERSION}], + [AC_MSG_RESULT([yes]) + HAVE_BUILT_GTEST="yes"], + [AC_MSG_RESULT([no])])])]) + +AS_IF([test "x${HAVE_BUILT_GTEST}" = "xyes"], + [GTEST_CPPFLAGS=`${GTEST_CONFIG} --cppflags` + GTEST_CXXFLAGS=`${GTEST_CONFIG} --cxxflags` + GTEST_LDFLAGS=`${GTEST_CONFIG} --ldflags` + GTEST_LIBS=`${GTEST_CONFIG} --libs` + GTEST_VERSION=`${GTEST_CONFIG} --version`], + [ + # GTEST_CONFIG needs to be executable both in a Makefile environment and + # in a shell script environment, so resolve an absolute path for it here. + GTEST_CONFIG="`pwd -P`/../googletest/scripts/gtest-config" + GTEST_CPPFLAGS='-I$(top_srcdir)/../googletest/include' + GTEST_CXXFLAGS='-g' + GTEST_LDFLAGS='' + GTEST_LIBS='$(top_builddir)/../googletest/lib/libgtest.la' + GTEST_VERSION="${GTEST_MIN_VERSION}"]) + +# TODO(chandlerc@google.com) Check the types, structures, and other compiler +# and architecture characteristics. + +# Output the generated files. No further autoconf macros may be used. +AC_OUTPUT diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/docs/CheatSheet.md b/deps/rapidjson/thirdparty/gtest/googlemock/docs/CheatSheet.md new file mode 100644 index 0000000..d54dd16 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/docs/CheatSheet.md @@ -0,0 +1,564 @@ + + +# Defining a Mock Class # + +## Mocking a Normal Class ## + +Given +``` +class Foo { + ... + virtual ~Foo(); + virtual int GetSize() const = 0; + virtual string Describe(const char* name) = 0; + virtual string Describe(int type) = 0; + virtual bool Process(Bar elem, int count) = 0; +}; +``` +(note that `~Foo()` **must** be virtual) we can define its mock as +``` +#include "gmock/gmock.h" + +class MockFoo : public Foo { + MOCK_CONST_METHOD0(GetSize, int()); + MOCK_METHOD1(Describe, string(const char* name)); + MOCK_METHOD1(Describe, string(int type)); + MOCK_METHOD2(Process, bool(Bar elem, int count)); +}; +``` + +To create a "nice" mock object which ignores all uninteresting calls, +or a "strict" mock object, which treats them as failures: +``` +NiceMock nice_foo; // The type is a subclass of MockFoo. +StrictMock strict_foo; // The type is a subclass of MockFoo. +``` + +## Mocking a Class Template ## + +To mock +``` +template +class StackInterface { + public: + ... + virtual ~StackInterface(); + virtual int GetSize() const = 0; + virtual void Push(const Elem& x) = 0; +}; +``` +(note that `~StackInterface()` **must** be virtual) just append `_T` to the `MOCK_*` macros: +``` +template +class MockStack : public StackInterface { + public: + ... + MOCK_CONST_METHOD0_T(GetSize, int()); + MOCK_METHOD1_T(Push, void(const Elem& x)); +}; +``` + +## Specifying Calling Conventions for Mock Functions ## + +If your mock function doesn't use the default calling convention, you +can specify it by appending `_WITH_CALLTYPE` to any of the macros +described in the previous two sections and supplying the calling +convention as the first argument to the macro. For example, +``` + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Foo, bool(int n)); + MOCK_CONST_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, Bar, int(double x, double y)); +``` +where `STDMETHODCALLTYPE` is defined by `` on Windows. + +# Using Mocks in Tests # + +The typical flow is: + 1. Import the Google Mock names you need to use. All Google Mock names are in the `testing` namespace unless they are macros or otherwise noted. + 1. Create the mock objects. + 1. Optionally, set the default actions of the mock objects. + 1. Set your expectations on the mock objects (How will they be called? What wil they do?). + 1. Exercise code that uses the mock objects; if necessary, check the result using [Google Test](../../googletest/) assertions. + 1. When a mock objects is destructed, Google Mock automatically verifies that all expectations on it have been satisfied. + +Here is an example: +``` +using ::testing::Return; // #1 + +TEST(BarTest, DoesThis) { + MockFoo foo; // #2 + + ON_CALL(foo, GetSize()) // #3 + .WillByDefault(Return(1)); + // ... other default actions ... + + EXPECT_CALL(foo, Describe(5)) // #4 + .Times(3) + .WillRepeatedly(Return("Category 5")); + // ... other expectations ... + + EXPECT_EQ("good", MyProductionFunction(&foo)); // #5 +} // #6 +``` + +# Setting Default Actions # + +Google Mock has a **built-in default action** for any function that +returns `void`, `bool`, a numeric value, or a pointer. + +To customize the default action for functions with return type `T` globally: +``` +using ::testing::DefaultValue; + +// Sets the default value to be returned. T must be CopyConstructible. +DefaultValue::Set(value); +// Sets a factory. Will be invoked on demand. T must be MoveConstructible. +// T MakeT(); +DefaultValue::SetFactory(&MakeT); +// ... use the mocks ... +// Resets the default value. +DefaultValue::Clear(); +``` + +To customize the default action for a particular method, use `ON_CALL()`: +``` +ON_CALL(mock_object, method(matchers)) + .With(multi_argument_matcher) ? + .WillByDefault(action); +``` + +# Setting Expectations # + +`EXPECT_CALL()` sets **expectations** on a mock method (How will it be +called? What will it do?): +``` +EXPECT_CALL(mock_object, method(matchers)) + .With(multi_argument_matcher) ? + .Times(cardinality) ? + .InSequence(sequences) * + .After(expectations) * + .WillOnce(action) * + .WillRepeatedly(action) ? + .RetiresOnSaturation(); ? +``` + +If `Times()` is omitted, the cardinality is assumed to be: + + * `Times(1)` when there is neither `WillOnce()` nor `WillRepeatedly()`; + * `Times(n)` when there are `n WillOnce()`s but no `WillRepeatedly()`, where `n` >= 1; or + * `Times(AtLeast(n))` when there are `n WillOnce()`s and a `WillRepeatedly()`, where `n` >= 0. + +A method with no `EXPECT_CALL()` is free to be invoked _any number of times_, and the default action will be taken each time. + +# Matchers # + +A **matcher** matches a _single_ argument. You can use it inside +`ON_CALL()` or `EXPECT_CALL()`, or use it to validate a value +directly: + +| `EXPECT_THAT(value, matcher)` | Asserts that `value` matches `matcher`. | +|:------------------------------|:----------------------------------------| +| `ASSERT_THAT(value, matcher)` | The same as `EXPECT_THAT(value, matcher)`, except that it generates a **fatal** failure. | + +Built-in matchers (where `argument` is the function argument) are +divided into several categories: + +## Wildcard ## +|`_`|`argument` can be any value of the correct type.| +|:--|:-----------------------------------------------| +|`A()` or `An()`|`argument` can be any value of type `type`. | + +## Generic Comparison ## + +|`Eq(value)` or `value`|`argument == value`| +|:---------------------|:------------------| +|`Ge(value)` |`argument >= value`| +|`Gt(value)` |`argument > value` | +|`Le(value)` |`argument <= value`| +|`Lt(value)` |`argument < value` | +|`Ne(value)` |`argument != value`| +|`IsNull()` |`argument` is a `NULL` pointer (raw or smart).| +|`NotNull()` |`argument` is a non-null pointer (raw or smart).| +|`VariantWith(m)` |`argument` is `variant<>` that holds the alternative of +type T with a value matching `m`.| +|`Ref(variable)` |`argument` is a reference to `variable`.| +|`TypedEq(value)`|`argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded.| + +Except `Ref()`, these matchers make a _copy_ of `value` in case it's +modified or destructed later. If the compiler complains that `value` +doesn't have a public copy constructor, try wrap it in `ByRef()`, +e.g. `Eq(ByRef(non_copyable_value))`. If you do that, make sure +`non_copyable_value` is not changed afterwards, or the meaning of your +matcher will be changed. + +## Floating-Point Matchers ## + +|`DoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as unequal.| +|:-------------------|:----------------------------------------------------------------------------------------------| +|`FloatEq(a_float)` |`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal. | +|`NanSensitiveDoubleEq(a_double)`|`argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal. | +|`NanSensitiveFloatEq(a_float)`|`argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal. | + +The above matchers use ULP-based comparison (the same as used in +[Google Test](../../googletest/)). They +automatically pick a reasonable error bound based on the absolute +value of the expected value. `DoubleEq()` and `FloatEq()` conform to +the IEEE standard, which requires comparing two NaNs for equality to +return false. The `NanSensitive*` version instead treats two NaNs as +equal, which is often what a user wants. + +|`DoubleNear(a_double, max_abs_error)`|`argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as unequal.| +|:------------------------------------|:--------------------------------------------------------------------------------------------------------------------| +|`FloatNear(a_float, max_abs_error)` |`argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as unequal. | +|`NanSensitiveDoubleNear(a_double, max_abs_error)`|`argument` is a `double` value close to `a_double` (absolute error <= `max_abs_error`), treating two NaNs as equal. | +|`NanSensitiveFloatNear(a_float, max_abs_error)`|`argument` is a `float` value close to `a_float` (absolute error <= `max_abs_error`), treating two NaNs as equal. | + +## String Matchers ## + +The `argument` can be either a C string or a C++ string object: + +|`ContainsRegex(string)`|`argument` matches the given regular expression.| +|:----------------------|:-----------------------------------------------| +|`EndsWith(suffix)` |`argument` ends with string `suffix`. | +|`HasSubstr(string)` |`argument` contains `string` as a sub-string. | +|`MatchesRegex(string)` |`argument` matches the given regular expression with the match starting at the first character and ending at the last character.| +|`StartsWith(prefix)` |`argument` starts with string `prefix`. | +|`StrCaseEq(string)` |`argument` is equal to `string`, ignoring case. | +|`StrCaseNe(string)` |`argument` is not equal to `string`, ignoring case.| +|`StrEq(string)` |`argument` is equal to `string`. | +|`StrNe(string)` |`argument` is not equal to `string`. | + +`ContainsRegex()` and `MatchesRegex()` use the regular expression +syntax defined +[here](../../googletest/docs/advanced.md#regular-expression-syntax). +`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide +strings as well. + +## Container Matchers ## + +Most STL-style containers support `==`, so you can use +`Eq(expected_container)` or simply `expected_container` to match a +container exactly. If you want to write the elements in-line, +match them more flexibly, or get more informative messages, you can use: + +| `ContainerEq(container)` | The same as `Eq(container)` except that the failure message also includes which elements are in one container but not the other. | +|:-------------------------|:---------------------------------------------------------------------------------------------------------------------------------| +| `Contains(e)` | `argument` contains an element that matches `e`, which can be either a value or a matcher. | +| `Each(e)` | `argument` is a container where _every_ element matches `e`, which can be either a value or a matcher. | +| `ElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, where the i-th element matches `ei`, which can be a value or a matcher. 0 to 10 arguments are allowed. | +| `ElementsAreArray({ e0, e1, ..., en })`, `ElementsAreArray(array)`, or `ElementsAreArray(array, count)` | The same as `ElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, or C-style array. | +| `IsEmpty()` | `argument` is an empty container (`container.empty()`). | +| `Pointwise(m, container)` | `argument` contains the same number of elements as in `container`, and for all i, (the i-th element in `argument`, the i-th element in `container`) match `m`, which is a matcher on 2-tuples. E.g. `Pointwise(Le(), upper_bounds)` verifies that each element in `argument` doesn't exceed the corresponding element in `upper_bounds`. See more detail below. | +| `SizeIs(m)` | `argument` is a container whose size matches `m`. E.g. `SizeIs(2)` or `SizeIs(Lt(2))`. | +| `UnorderedElementsAre(e0, e1, ..., en)` | `argument` has `n + 1` elements, and under some permutation each element matches an `ei` (for a different `i`), which can be a value or a matcher. 0 to 10 arguments are allowed. | +| `UnorderedElementsAreArray({ e0, e1, ..., en })`, `UnorderedElementsAreArray(array)`, or `UnorderedElementsAreArray(array, count)` | The same as `UnorderedElementsAre()` except that the expected element values/matchers come from an initializer list, STL-style container, or C-style array. | +| `WhenSorted(m)` | When `argument` is sorted using the `<` operator, it matches container matcher `m`. E.g. `WhenSorted(ElementsAre(1, 2, 3))` verifies that `argument` contains elements `1`, `2`, and `3`, ignoring order. | +| `WhenSortedBy(comparator, m)` | The same as `WhenSorted(m)`, except that the given comparator instead of `<` is used to sort `argument`. E.g. `WhenSortedBy(std::greater(), ElementsAre(3, 2, 1))`. | + +Notes: + + * These matchers can also match: + 1. a native array passed by reference (e.g. in `Foo(const int (&a)[5])`), and + 1. an array passed as a pointer and a count (e.g. in `Bar(const T* buffer, int len)` -- see [Multi-argument Matchers](#Multiargument_Matchers.md)). + * The array being matched may be multi-dimensional (i.e. its elements can be arrays). + * `m` in `Pointwise(m, ...)` should be a matcher for `::testing::tuple` where `T` and `U` are the element type of the actual container and the expected container, respectively. For example, to compare two `Foo` containers where `Foo` doesn't support `operator==` but has an `Equals()` method, one might write: + +``` +using ::testing::get; +MATCHER(FooEq, "") { + return get<0>(arg).Equals(get<1>(arg)); +} +... +EXPECT_THAT(actual_foos, Pointwise(FooEq(), expected_foos)); +``` + +## Member Matchers ## + +|`Field(&class::field, m)`|`argument.field` (or `argument->field` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.| +|:------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------| +|`Key(e)` |`argument.first` matches `e`, which can be either a value or a matcher. E.g. `Contains(Key(Le(5)))` can verify that a `map` contains a key `<= 5`.| +|`Pair(m1, m2)` |`argument` is an `std::pair` whose `first` field matches `m1` and `second` field matches `m2`. | +|`Property(&class::property, m)`|`argument.property()` (or `argument->property()` when `argument` is a plain pointer) matches matcher `m`, where `argument` is an object of type _class_.| + +## Matching the Result of a Function or Functor ## + +|`ResultOf(f, m)`|`f(argument)` matches matcher `m`, where `f` is a function or functor.| +|:---------------|:---------------------------------------------------------------------| + +## Pointer Matchers ## + +|`Pointee(m)`|`argument` (either a smart pointer or a raw pointer) points to a value that matches matcher `m`.| +|:-----------|:-----------------------------------------------------------------------------------------------| +|`WhenDynamicCastTo(m)`| when `argument` is passed through `dynamic_cast()`, it matches matcher `m`. | + +## Multiargument Matchers ## + +Technically, all matchers match a _single_ value. A "multi-argument" +matcher is just one that matches a _tuple_. The following matchers can +be used to match a tuple `(x, y)`: + +|`Eq()`|`x == y`| +|:-----|:-------| +|`Ge()`|`x >= y`| +|`Gt()`|`x > y` | +|`Le()`|`x <= y`| +|`Lt()`|`x < y` | +|`Ne()`|`x != y`| + +You can use the following selectors to pick a subset of the arguments +(or reorder them) to participate in the matching: + +|`AllArgs(m)`|Equivalent to `m`. Useful as syntactic sugar in `.With(AllArgs(m))`.| +|:-----------|:-------------------------------------------------------------------| +|`Args(m)`|The tuple of the `k` selected (using 0-based indices) arguments matches `m`, e.g. `Args<1, 2>(Eq())`.| + +## Composite Matchers ## + +You can make a matcher from one or more other matchers: + +|`AllOf(m1, m2, ..., mn)`|`argument` matches all of the matchers `m1` to `mn`.| +|:-----------------------|:---------------------------------------------------| +|`AnyOf(m1, m2, ..., mn)`|`argument` matches at least one of the matchers `m1` to `mn`.| +|`Not(m)` |`argument` doesn't match matcher `m`. | + +## Adapters for Matchers ## + +|`MatcherCast(m)`|casts matcher `m` to type `Matcher`.| +|:------------------|:--------------------------------------| +|`SafeMatcherCast(m)`| [safely casts](CookBook.md#casting-matchers) matcher `m` to type `Matcher`. | +|`Truly(predicate)` |`predicate(argument)` returns something considered by C++ to be true, where `predicate` is a function or functor.| + +## Matchers as Predicates ## + +|`Matches(m)(value)`|evaluates to `true` if `value` matches `m`. You can use `Matches(m)` alone as a unary functor.| +|:------------------|:---------------------------------------------------------------------------------------------| +|`ExplainMatchResult(m, value, result_listener)`|evaluates to `true` if `value` matches `m`, explaining the result to `result_listener`. | +|`Value(value, m)` |evaluates to `true` if `value` matches `m`. | + +## Defining Matchers ## + +| `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. | +|:-------------------------------------------------|:------------------------------------------------------| +| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. | +| `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. | + +**Notes:** + + 1. The `MATCHER*` macros cannot be used inside a function or class. + 1. The matcher body must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters). + 1. You can use `PrintToString(x)` to convert a value `x` of any type to a string. + +## Matchers as Test Assertions ## + +|`ASSERT_THAT(expression, m)`|Generates a [fatal failure](../../googletest/docs/primer.md#assertions) if the value of `expression` doesn't match matcher `m`.| +|:---------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| +|`EXPECT_THAT(expression, m)`|Generates a non-fatal failure if the value of `expression` doesn't match matcher `m`. | + +# Actions # + +**Actions** specify what a mock function should do when invoked. + +## Returning a Value ## + +|`Return()`|Return from a `void` mock function.| +|:---------|:----------------------------------| +|`Return(value)`|Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type at the time the expectation is set, not when the action is executed.| +|`ReturnArg()`|Return the `N`-th (0-based) argument.| +|`ReturnNew(a1, ..., ak)`|Return `new T(a1, ..., ak)`; a different object is created each time.| +|`ReturnNull()`|Return a null pointer. | +|`ReturnPointee(ptr)`|Return the value pointed to by `ptr`.| +|`ReturnRef(variable)`|Return a reference to `variable`. | +|`ReturnRefOfCopy(value)`|Return a reference to a copy of `value`; the copy lives as long as the action.| + +## Side Effects ## + +|`Assign(&variable, value)`|Assign `value` to variable.| +|:-------------------------|:--------------------------| +| `DeleteArg()` | Delete the `N`-th (0-based) argument, which must be a pointer. | +| `SaveArg(pointer)` | Save the `N`-th (0-based) argument to `*pointer`. | +| `SaveArgPointee(pointer)` | Save the value pointed to by the `N`-th (0-based) argument to `*pointer`. | +| `SetArgReferee(value)` | Assign value to the variable referenced by the `N`-th (0-based) argument. | +|`SetArgPointee(value)` |Assign `value` to the variable pointed by the `N`-th (0-based) argument.| +|`SetArgumentPointee(value)`|Same as `SetArgPointee(value)`. Deprecated. Will be removed in v1.7.0.| +|`SetArrayArgument(first, last)`|Copies the elements in source range [`first`, `last`) to the array pointed to by the `N`-th (0-based) argument, which can be either a pointer or an iterator. The action does not take ownership of the elements in the source range.| +|`SetErrnoAndReturn(error, value)`|Set `errno` to `error` and return `value`.| +|`Throw(exception)` |Throws the given exception, which can be any copyable value. Available since v1.1.0.| + +## Using a Function or a Functor as an Action ## + +|`Invoke(f)`|Invoke `f` with the arguments passed to the mock function, where `f` can be a global/static function or a functor.| +|:----------|:-----------------------------------------------------------------------------------------------------------------| +|`Invoke(object_pointer, &class::method)`|Invoke the {method on the object with the arguments passed to the mock function. | +|`InvokeWithoutArgs(f)`|Invoke `f`, which can be a global/static function or a functor. `f` must take no arguments. | +|`InvokeWithoutArgs(object_pointer, &class::method)`|Invoke the method on the object, which takes no arguments. | +|`InvokeArgument(arg1, arg2, ..., argk)`|Invoke the mock function's `N`-th (0-based) argument, which must be a function or a functor, with the `k` arguments.| + +The return value of the invoked function is used as the return value +of the action. + +When defining a function or functor to be used with `Invoke*()`, you can declare any unused parameters as `Unused`: +``` + double Distance(Unused, double x, double y) { return sqrt(x*x + y*y); } + ... + EXPECT_CALL(mock, Foo("Hi", _, _)).WillOnce(Invoke(Distance)); +``` + +In `InvokeArgument(...)`, if an argument needs to be passed by reference, wrap it inside `ByRef()`. For example, +``` + InvokeArgument<2>(5, string("Hi"), ByRef(foo)) +``` +calls the mock function's #2 argument, passing to it `5` and `string("Hi")` by value, and `foo` by reference. + +## Default Action ## + +|`DoDefault()`|Do the default action (specified by `ON_CALL()` or the built-in one).| +|:------------|:--------------------------------------------------------------------| + +**Note:** due to technical reasons, `DoDefault()` cannot be used inside a composite action - trying to do so will result in a run-time error. + +## Composite Actions ## + +|`DoAll(a1, a2, ..., an)`|Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. | +|:-----------------------|:-----------------------------------------------------------------------------------------------------------------------------| +|`IgnoreResult(a)` |Perform action `a` and ignore its result. `a` must not return void. | +|`WithArg(a)` |Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. | +|`WithArgs(a)`|Pass the selected (0-based) arguments of the mock function to action `a` and perform it. | +|`WithoutArgs(a)` |Perform action `a` without any arguments. | + +## Defining Actions ## + +| `ACTION(Sum) { return arg0 + arg1; }` | Defines an action `Sum()` to return the sum of the mock function's argument #0 and #1. | +|:--------------------------------------|:---------------------------------------------------------------------------------------| +| `ACTION_P(Plus, n) { return arg0 + n; }` | Defines an action `Plus(n)` to return the sum of the mock function's argument #0 and `n`. | +| `ACTION_Pk(Foo, p1, ..., pk) { statements; }` | Defines a parameterized action `Foo(p1, ..., pk)` to execute the given `statements`. | + +The `ACTION*` macros cannot be used inside a function or class. + +# Cardinalities # + +These are used in `Times()` to specify how many times a mock function will be called: + +|`AnyNumber()`|The function can be called any number of times.| +|:------------|:----------------------------------------------| +|`AtLeast(n)` |The call is expected at least `n` times. | +|`AtMost(n)` |The call is expected at most `n` times. | +|`Between(m, n)`|The call is expected between `m` and `n` (inclusive) times.| +|`Exactly(n) or n`|The call is expected exactly `n` times. In particular, the call should never happen when `n` is 0.| + +# Expectation Order # + +By default, the expectations can be matched in _any_ order. If some +or all expectations must be matched in a given order, there are two +ways to specify it. They can be used either independently or +together. + +## The After Clause ## + +``` +using ::testing::Expectation; +... +Expectation init_x = EXPECT_CALL(foo, InitX()); +Expectation init_y = EXPECT_CALL(foo, InitY()); +EXPECT_CALL(foo, Bar()) + .After(init_x, init_y); +``` +says that `Bar()` can be called only after both `InitX()` and +`InitY()` have been called. + +If you don't know how many pre-requisites an expectation has when you +write it, you can use an `ExpectationSet` to collect them: + +``` +using ::testing::ExpectationSet; +... +ExpectationSet all_inits; +for (int i = 0; i < element_count; i++) { + all_inits += EXPECT_CALL(foo, InitElement(i)); +} +EXPECT_CALL(foo, Bar()) + .After(all_inits); +``` +says that `Bar()` can be called only after all elements have been +initialized (but we don't care about which elements get initialized +before the others). + +Modifying an `ExpectationSet` after using it in an `.After()` doesn't +affect the meaning of the `.After()`. + +## Sequences ## + +When you have a long chain of sequential expectations, it's easier to +specify the order using **sequences**, which don't require you to given +each expectation in the chain a different name. All expected
    +calls
    in the same sequence must occur in the order they are +specified. + +``` +using ::testing::Sequence; +Sequence s1, s2; +... +EXPECT_CALL(foo, Reset()) + .InSequence(s1, s2) + .WillOnce(Return(true)); +EXPECT_CALL(foo, GetSize()) + .InSequence(s1) + .WillOnce(Return(1)); +EXPECT_CALL(foo, Describe(A())) + .InSequence(s2) + .WillOnce(Return("dummy")); +``` +says that `Reset()` must be called before _both_ `GetSize()` _and_ +`Describe()`, and the latter two can occur in any order. + +To put many expectations in a sequence conveniently: +``` +using ::testing::InSequence; +{ + InSequence dummy; + + EXPECT_CALL(...)...; + EXPECT_CALL(...)...; + ... + EXPECT_CALL(...)...; +} +``` +says that all expected calls in the scope of `dummy` must occur in +strict order. The name `dummy` is irrelevant.) + +# Verifying and Resetting a Mock # + +Google Mock will verify the expectations on a mock object when it is destructed, or you can do it earlier: +``` +using ::testing::Mock; +... +// Verifies and removes the expectations on mock_obj; +// returns true iff successful. +Mock::VerifyAndClearExpectations(&mock_obj); +... +// Verifies and removes the expectations on mock_obj; +// also removes the default actions set by ON_CALL(); +// returns true iff successful. +Mock::VerifyAndClear(&mock_obj); +``` + +You can also tell Google Mock that a mock object can be leaked and doesn't +need to be verified: +``` +Mock::AllowLeak(&mock_obj); +``` + +# Mock Classes # + +Google Mock defines a convenient mock class template +``` +class MockFunction { + public: + MOCK_METHODn(Call, R(A1, ..., An)); +}; +``` +See this [recipe](CookBook.md#using-check-points) for one application of it. + +# Flags # + +| `--gmock_catch_leaked_mocks=0` | Don't report leaked mock objects as failures. | +|:-------------------------------|:----------------------------------------------| +| `--gmock_verbose=LEVEL` | Sets the default verbosity level (`info`, `warning`, or `error`) of Google Mock messages. | diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/docs/CookBook.md b/deps/rapidjson/thirdparty/gtest/googlemock/docs/CookBook.md new file mode 100644 index 0000000..bd9f026 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/docs/CookBook.md @@ -0,0 +1,3660 @@ + + +You can find recipes for using Google Mock here. If you haven't yet, +please read the [ForDummies](ForDummies.md) document first to make sure you understand +the basics. + +**Note:** Google Mock lives in the `testing` name space. For +readability, it is recommended to write `using ::testing::Foo;` once in +your file before using the name `Foo` defined by Google Mock. We omit +such `using` statements in this page for brevity, but you should do it +in your own code. + +# Creating Mock Classes # + +## Mocking Private or Protected Methods ## + +You must always put a mock method definition (`MOCK_METHOD*`) in a +`public:` section of the mock class, regardless of the method being +mocked being `public`, `protected`, or `private` in the base class. +This allows `ON_CALL` and `EXPECT_CALL` to reference the mock function +from outside of the mock class. (Yes, C++ allows a subclass to specify +a different access level than the base class on a virtual function.) +Example: + +``` +class Foo { + public: + ... + virtual bool Transform(Gadget* g) = 0; + + protected: + virtual void Resume(); + + private: + virtual int GetTimeOut(); +}; + +class MockFoo : public Foo { + public: + ... + MOCK_METHOD1(Transform, bool(Gadget* g)); + + // The following must be in the public section, even though the + // methods are protected or private in the base class. + MOCK_METHOD0(Resume, void()); + MOCK_METHOD0(GetTimeOut, int()); +}; +``` + +## Mocking Overloaded Methods ## + +You can mock overloaded functions as usual. No special attention is required: + +``` +class Foo { + ... + + // Must be virtual as we'll inherit from Foo. + virtual ~Foo(); + + // Overloaded on the types and/or numbers of arguments. + virtual int Add(Element x); + virtual int Add(int times, Element x); + + // Overloaded on the const-ness of this object. + virtual Bar& GetBar(); + virtual const Bar& GetBar() const; +}; + +class MockFoo : public Foo { + ... + MOCK_METHOD1(Add, int(Element x)); + MOCK_METHOD2(Add, int(int times, Element x); + + MOCK_METHOD0(GetBar, Bar&()); + MOCK_CONST_METHOD0(GetBar, const Bar&()); +}; +``` + +**Note:** if you don't mock all versions of the overloaded method, the +compiler will give you a warning about some methods in the base class +being hidden. To fix that, use `using` to bring them in scope: + +``` +class MockFoo : public Foo { + ... + using Foo::Add; + MOCK_METHOD1(Add, int(Element x)); + // We don't want to mock int Add(int times, Element x); + ... +}; +``` + +## Mocking Class Templates ## + +To mock a class template, append `_T` to the `MOCK_*` macros: + +``` +template +class StackInterface { + ... + // Must be virtual as we'll inherit from StackInterface. + virtual ~StackInterface(); + + virtual int GetSize() const = 0; + virtual void Push(const Elem& x) = 0; +}; + +template +class MockStack : public StackInterface { + ... + MOCK_CONST_METHOD0_T(GetSize, int()); + MOCK_METHOD1_T(Push, void(const Elem& x)); +}; +``` + +## Mocking Nonvirtual Methods ## + +Google Mock can mock non-virtual functions to be used in what we call _hi-perf +dependency injection_. + +In this case, instead of sharing a common base class with the real +class, your mock class will be _unrelated_ to the real class, but +contain methods with the same signatures. The syntax for mocking +non-virtual methods is the _same_ as mocking virtual methods: + +``` +// A simple packet stream class. None of its members is virtual. +class ConcretePacketStream { + public: + void AppendPacket(Packet* new_packet); + const Packet* GetPacket(size_t packet_number) const; + size_t NumberOfPackets() const; + ... +}; + +// A mock packet stream class. It inherits from no other, but defines +// GetPacket() and NumberOfPackets(). +class MockPacketStream { + public: + MOCK_CONST_METHOD1(GetPacket, const Packet*(size_t packet_number)); + MOCK_CONST_METHOD0(NumberOfPackets, size_t()); + ... +}; +``` + +Note that the mock class doesn't define `AppendPacket()`, unlike the +real class. That's fine as long as the test doesn't need to call it. + +Next, you need a way to say that you want to use +`ConcretePacketStream` in production code and to use `MockPacketStream` +in tests. Since the functions are not virtual and the two classes are +unrelated, you must specify your choice at _compile time_ (as opposed +to run time). + +One way to do it is to templatize your code that needs to use a packet +stream. More specifically, you will give your code a template type +argument for the type of the packet stream. In production, you will +instantiate your template with `ConcretePacketStream` as the type +argument. In tests, you will instantiate the same template with +`MockPacketStream`. For example, you may write: + +``` +template +void CreateConnection(PacketStream* stream) { ... } + +template +class PacketReader { + public: + void ReadPackets(PacketStream* stream, size_t packet_num); +}; +``` + +Then you can use `CreateConnection()` and +`PacketReader` in production code, and use +`CreateConnection()` and +`PacketReader` in tests. + +``` + MockPacketStream mock_stream; + EXPECT_CALL(mock_stream, ...)...; + .. set more expectations on mock_stream ... + PacketReader reader(&mock_stream); + ... exercise reader ... +``` + +## Mocking Free Functions ## + +It's possible to use Google Mock to mock a free function (i.e. a +C-style function or a static method). You just need to rewrite your +code to use an interface (abstract class). + +Instead of calling a free function (say, `OpenFile`) directly, +introduce an interface for it and have a concrete subclass that calls +the free function: + +``` +class FileInterface { + public: + ... + virtual bool Open(const char* path, const char* mode) = 0; +}; + +class File : public FileInterface { + public: + ... + virtual bool Open(const char* path, const char* mode) { + return OpenFile(path, mode); + } +}; +``` + +Your code should talk to `FileInterface` to open a file. Now it's +easy to mock out the function. + +This may seem much hassle, but in practice you often have multiple +related functions that you can put in the same interface, so the +per-function syntactic overhead will be much lower. + +If you are concerned about the performance overhead incurred by +virtual functions, and profiling confirms your concern, you can +combine this with the recipe for [mocking non-virtual methods](#mocking-nonvirtual-methods). + +## The Nice, the Strict, and the Naggy ## + +If a mock method has no `EXPECT_CALL` spec but is called, Google Mock +will print a warning about the "uninteresting call". The rationale is: + + * New methods may be added to an interface after a test is written. We shouldn't fail a test just because a method it doesn't know about is called. + * However, this may also mean there's a bug in the test, so Google Mock shouldn't be silent either. If the user believes these calls are harmless, they can add an `EXPECT_CALL()` to suppress the warning. + +However, sometimes you may want to suppress all "uninteresting call" +warnings, while sometimes you may want the opposite, i.e. to treat all +of them as errors. Google Mock lets you make the decision on a +per-mock-object basis. + +Suppose your test uses a mock class `MockFoo`: + +``` +TEST(...) { + MockFoo mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +If a method of `mock_foo` other than `DoThis()` is called, it will be +reported by Google Mock as a warning. However, if you rewrite your +test to use `NiceMock` instead, the warning will be gone, +resulting in a cleaner test output: + +``` +using ::testing::NiceMock; + +TEST(...) { + NiceMock mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +`NiceMock` is a subclass of `MockFoo`, so it can be used +wherever `MockFoo` is accepted. + +It also works if `MockFoo`'s constructor takes some arguments, as +`NiceMock` "inherits" `MockFoo`'s constructors: + +``` +using ::testing::NiceMock; + +TEST(...) { + NiceMock mock_foo(5, "hi"); // Calls MockFoo(5, "hi"). + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... +} +``` + +The usage of `StrictMock` is similar, except that it makes all +uninteresting calls failures: + +``` +using ::testing::StrictMock; + +TEST(...) { + StrictMock mock_foo; + EXPECT_CALL(mock_foo, DoThis()); + ... code that uses mock_foo ... + + // The test will fail if a method of mock_foo other than DoThis() + // is called. +} +``` + +There are some caveats though (I don't like them just as much as the +next guy, but sadly they are side effects of C++'s limitations): + + 1. `NiceMock` and `StrictMock` only work for mock methods defined using the `MOCK_METHOD*` family of macros **directly** in the `MockFoo` class. If a mock method is defined in a **base class** of `MockFoo`, the "nice" or "strict" modifier may not affect it, depending on the compiler. In particular, nesting `NiceMock` and `StrictMock` (e.g. `NiceMock >`) is **not** supported. + 1. The constructors of the base mock (`MockFoo`) cannot have arguments passed by non-const reference, which happens to be banned by the [Google C++ style guide](https://google.github.io/styleguide/cppguide.html). + 1. During the constructor or destructor of `MockFoo`, the mock object is _not_ nice or strict. This may cause surprises if the constructor or destructor calls a mock method on `this` object. (This behavior, however, is consistent with C++'s general rule: if a constructor or destructor calls a virtual method of `this` object, that method is treated as non-virtual. In other words, to the base class's constructor or destructor, `this` object behaves like an instance of the base class, not the derived class. This rule is required for safety. Otherwise a base constructor may use members of a derived class before they are initialized, or a base destructor may use members of a derived class after they have been destroyed.) + +Finally, you should be **very cautious** about when to use naggy or strict mocks, as they tend to make tests more brittle and harder to maintain. When you refactor your code without changing its externally visible behavior, ideally you should't need to update any tests. If your code interacts with a naggy mock, however, you may start to get spammed with warnings as the result of your change. Worse, if your code interacts with a strict mock, your tests may start to fail and you'll be forced to fix them. Our general recommendation is to use nice mocks (not yet the default) most of the time, use naggy mocks (the current default) when developing or debugging tests, and use strict mocks only as the last resort. + +## Simplifying the Interface without Breaking Existing Code ## + +Sometimes a method has a long list of arguments that is mostly +uninteresting. For example, + +``` +class LogSink { + public: + ... + virtual void send(LogSeverity severity, const char* full_filename, + const char* base_filename, int line, + const struct tm* tm_time, + const char* message, size_t message_len) = 0; +}; +``` + +This method's argument list is lengthy and hard to work with (let's +say that the `message` argument is not even 0-terminated). If we mock +it as is, using the mock will be awkward. If, however, we try to +simplify this interface, we'll need to fix all clients depending on +it, which is often infeasible. + +The trick is to re-dispatch the method in the mock class: + +``` +class ScopedMockLog : public LogSink { + public: + ... + virtual void send(LogSeverity severity, const char* full_filename, + const char* base_filename, int line, const tm* tm_time, + const char* message, size_t message_len) { + // We are only interested in the log severity, full file name, and + // log message. + Log(severity, full_filename, std::string(message, message_len)); + } + + // Implements the mock method: + // + // void Log(LogSeverity severity, + // const string& file_path, + // const string& message); + MOCK_METHOD3(Log, void(LogSeverity severity, const string& file_path, + const string& message)); +}; +``` + +By defining a new mock method with a trimmed argument list, we make +the mock class much more user-friendly. + +## Alternative to Mocking Concrete Classes ## + +Often you may find yourself using classes that don't implement +interfaces. In order to test your code that uses such a class (let's +call it `Concrete`), you may be tempted to make the methods of +`Concrete` virtual and then mock it. + +Try not to do that. + +Making a non-virtual function virtual is a big decision. It creates an +extension point where subclasses can tweak your class' behavior. This +weakens your control on the class because now it's harder to maintain +the class' invariants. You should make a function virtual only when +there is a valid reason for a subclass to override it. + +Mocking concrete classes directly is problematic as it creates a tight +coupling between the class and the tests - any small change in the +class may invalidate your tests and make test maintenance a pain. + +To avoid such problems, many programmers have been practicing "coding +to interfaces": instead of talking to the `Concrete` class, your code +would define an interface and talk to it. Then you implement that +interface as an adaptor on top of `Concrete`. In tests, you can easily +mock that interface to observe how your code is doing. + +This technique incurs some overhead: + + * You pay the cost of virtual function calls (usually not a problem). + * There is more abstraction for the programmers to learn. + +However, it can also bring significant benefits in addition to better +testability: + + * `Concrete`'s API may not fit your problem domain very well, as you may not be the only client it tries to serve. By designing your own interface, you have a chance to tailor it to your need - you may add higher-level functionalities, rename stuff, etc instead of just trimming the class. This allows you to write your code (user of the interface) in a more natural way, which means it will be more readable, more maintainable, and you'll be more productive. + * If `Concrete`'s implementation ever has to change, you don't have to rewrite everywhere it is used. Instead, you can absorb the change in your implementation of the interface, and your other code and tests will be insulated from this change. + +Some people worry that if everyone is practicing this technique, they +will end up writing lots of redundant code. This concern is totally +understandable. However, there are two reasons why it may not be the +case: + + * Different projects may need to use `Concrete` in different ways, so the best interfaces for them will be different. Therefore, each of them will have its own domain-specific interface on top of `Concrete`, and they will not be the same code. + * If enough projects want to use the same interface, they can always share it, just like they have been sharing `Concrete`. You can check in the interface and the adaptor somewhere near `Concrete` (perhaps in a `contrib` sub-directory) and let many projects use it. + +You need to weigh the pros and cons carefully for your particular +problem, but I'd like to assure you that the Java community has been +practicing this for a long time and it's a proven effective technique +applicable in a wide variety of situations. :-) + +## Delegating Calls to a Fake ## + +Some times you have a non-trivial fake implementation of an +interface. For example: + +``` +class Foo { + public: + virtual ~Foo() {} + virtual char DoThis(int n) = 0; + virtual void DoThat(const char* s, int* p) = 0; +}; + +class FakeFoo : public Foo { + public: + virtual char DoThis(int n) { + return (n > 0) ? '+' : + (n < 0) ? '-' : '0'; + } + + virtual void DoThat(const char* s, int* p) { + *p = strlen(s); + } +}; +``` + +Now you want to mock this interface such that you can set expectations +on it. However, you also want to use `FakeFoo` for the default +behavior, as duplicating it in the mock object is, well, a lot of +work. + +When you define the mock class using Google Mock, you can have it +delegate its default action to a fake class you already have, using +this pattern: + +``` +using ::testing::_; +using ::testing::Invoke; + +class MockFoo : public Foo { + public: + // Normal mock method definitions using Google Mock. + MOCK_METHOD1(DoThis, char(int n)); + MOCK_METHOD2(DoThat, void(const char* s, int* p)); + + // Delegates the default actions of the methods to a FakeFoo object. + // This must be called *before* the custom ON_CALL() statements. + void DelegateToFake() { + ON_CALL(*this, DoThis(_)) + .WillByDefault(Invoke(&fake_, &FakeFoo::DoThis)); + ON_CALL(*this, DoThat(_, _)) + .WillByDefault(Invoke(&fake_, &FakeFoo::DoThat)); + } + private: + FakeFoo fake_; // Keeps an instance of the fake in the mock. +}; +``` + +With that, you can use `MockFoo` in your tests as usual. Just remember +that if you don't explicitly set an action in an `ON_CALL()` or +`EXPECT_CALL()`, the fake will be called upon to do it: + +``` +using ::testing::_; + +TEST(AbcTest, Xyz) { + MockFoo foo; + foo.DelegateToFake(); // Enables the fake for delegation. + + // Put your ON_CALL(foo, ...)s here, if any. + + // No action specified, meaning to use the default action. + EXPECT_CALL(foo, DoThis(5)); + EXPECT_CALL(foo, DoThat(_, _)); + + int n = 0; + EXPECT_EQ('+', foo.DoThis(5)); // FakeFoo::DoThis() is invoked. + foo.DoThat("Hi", &n); // FakeFoo::DoThat() is invoked. + EXPECT_EQ(2, n); +} +``` + +**Some tips:** + + * If you want, you can still override the default action by providing your own `ON_CALL()` or using `.WillOnce()` / `.WillRepeatedly()` in `EXPECT_CALL()`. + * In `DelegateToFake()`, you only need to delegate the methods whose fake implementation you intend to use. + * The general technique discussed here works for overloaded methods, but you'll need to tell the compiler which version you mean. To disambiguate a mock function (the one you specify inside the parentheses of `ON_CALL()`), see the "Selecting Between Overloaded Functions" section on this page; to disambiguate a fake function (the one you place inside `Invoke()`), use a `static_cast` to specify the function's type. For instance, if class `Foo` has methods `char DoThis(int n)` and `bool DoThis(double x) const`, and you want to invoke the latter, you need to write `Invoke(&fake_, static_cast(&FakeFoo::DoThis))` instead of `Invoke(&fake_, &FakeFoo::DoThis)` (The strange-looking thing inside the angled brackets of `static_cast` is the type of a function pointer to the second `DoThis()` method.). + * Having to mix a mock and a fake is often a sign of something gone wrong. Perhaps you haven't got used to the interaction-based way of testing yet. Or perhaps your interface is taking on too many roles and should be split up. Therefore, **don't abuse this**. We would only recommend to do it as an intermediate step when you are refactoring your code. + +Regarding the tip on mixing a mock and a fake, here's an example on +why it may be a bad sign: Suppose you have a class `System` for +low-level system operations. In particular, it does file and I/O +operations. And suppose you want to test how your code uses `System` +to do I/O, and you just want the file operations to work normally. If +you mock out the entire `System` class, you'll have to provide a fake +implementation for the file operation part, which suggests that +`System` is taking on too many roles. + +Instead, you can define a `FileOps` interface and an `IOOps` interface +and split `System`'s functionalities into the two. Then you can mock +`IOOps` without mocking `FileOps`. + +## Delegating Calls to a Real Object ## + +When using testing doubles (mocks, fakes, stubs, and etc), sometimes +their behaviors will differ from those of the real objects. This +difference could be either intentional (as in simulating an error such +that you can test the error handling code) or unintentional. If your +mocks have different behaviors than the real objects by mistake, you +could end up with code that passes the tests but fails in production. + +You can use the _delegating-to-real_ technique to ensure that your +mock has the same behavior as the real object while retaining the +ability to validate calls. This technique is very similar to the +delegating-to-fake technique, the difference being that we use a real +object instead of a fake. Here's an example: + +``` +using ::testing::_; +using ::testing::AtLeast; +using ::testing::Invoke; + +class MockFoo : public Foo { + public: + MockFoo() { + // By default, all calls are delegated to the real object. + ON_CALL(*this, DoThis()) + .WillByDefault(Invoke(&real_, &Foo::DoThis)); + ON_CALL(*this, DoThat(_)) + .WillByDefault(Invoke(&real_, &Foo::DoThat)); + ... + } + MOCK_METHOD0(DoThis, ...); + MOCK_METHOD1(DoThat, ...); + ... + private: + Foo real_; +}; +... + + MockFoo mock; + + EXPECT_CALL(mock, DoThis()) + .Times(3); + EXPECT_CALL(mock, DoThat("Hi")) + .Times(AtLeast(1)); + ... use mock in test ... +``` + +With this, Google Mock will verify that your code made the right calls +(with the right arguments, in the right order, called the right number +of times, etc), and a real object will answer the calls (so the +behavior will be the same as in production). This gives you the best +of both worlds. + +## Delegating Calls to a Parent Class ## + +Ideally, you should code to interfaces, whose methods are all pure +virtual. In reality, sometimes you do need to mock a virtual method +that is not pure (i.e, it already has an implementation). For example: + +``` +class Foo { + public: + virtual ~Foo(); + + virtual void Pure(int n) = 0; + virtual int Concrete(const char* str) { ... } +}; + +class MockFoo : public Foo { + public: + // Mocking a pure method. + MOCK_METHOD1(Pure, void(int n)); + // Mocking a concrete method. Foo::Concrete() is shadowed. + MOCK_METHOD1(Concrete, int(const char* str)); +}; +``` + +Sometimes you may want to call `Foo::Concrete()` instead of +`MockFoo::Concrete()`. Perhaps you want to do it as part of a stub +action, or perhaps your test doesn't need to mock `Concrete()` at all +(but it would be oh-so painful to have to define a new mock class +whenever you don't need to mock one of its methods). + +The trick is to leave a back door in your mock class for accessing the +real methods in the base class: + +``` +class MockFoo : public Foo { + public: + // Mocking a pure method. + MOCK_METHOD1(Pure, void(int n)); + // Mocking a concrete method. Foo::Concrete() is shadowed. + MOCK_METHOD1(Concrete, int(const char* str)); + + // Use this to call Concrete() defined in Foo. + int FooConcrete(const char* str) { return Foo::Concrete(str); } +}; +``` + +Now, you can call `Foo::Concrete()` inside an action by: + +``` +using ::testing::_; +using ::testing::Invoke; +... + EXPECT_CALL(foo, Concrete(_)) + .WillOnce(Invoke(&foo, &MockFoo::FooConcrete)); +``` + +or tell the mock object that you don't want to mock `Concrete()`: + +``` +using ::testing::Invoke; +... + ON_CALL(foo, Concrete(_)) + .WillByDefault(Invoke(&foo, &MockFoo::FooConcrete)); +``` + +(Why don't we just write `Invoke(&foo, &Foo::Concrete)`? If you do +that, `MockFoo::Concrete()` will be called (and cause an infinite +recursion) since `Foo::Concrete()` is virtual. That's just how C++ +works.) + +# Using Matchers # + +## Matching Argument Values Exactly ## + +You can specify exactly which arguments a mock method is expecting: + +``` +using ::testing::Return; +... + EXPECT_CALL(foo, DoThis(5)) + .WillOnce(Return('a')); + EXPECT_CALL(foo, DoThat("Hello", bar)); +``` + +## Using Simple Matchers ## + +You can use matchers to match arguments that have a certain property: + +``` +using ::testing::Ge; +using ::testing::NotNull; +using ::testing::Return; +... + EXPECT_CALL(foo, DoThis(Ge(5))) // The argument must be >= 5. + .WillOnce(Return('a')); + EXPECT_CALL(foo, DoThat("Hello", NotNull())); + // The second argument must not be NULL. +``` + +A frequently used matcher is `_`, which matches anything: + +``` +using ::testing::_; +using ::testing::NotNull; +... + EXPECT_CALL(foo, DoThat(_, NotNull())); +``` + +## Combining Matchers ## + +You can build complex matchers from existing ones using `AllOf()`, +`AnyOf()`, and `Not()`: + +``` +using ::testing::AllOf; +using ::testing::Gt; +using ::testing::HasSubstr; +using ::testing::Ne; +using ::testing::Not; +... + // The argument must be > 5 and != 10. + EXPECT_CALL(foo, DoThis(AllOf(Gt(5), + Ne(10)))); + + // The first argument must not contain sub-string "blah". + EXPECT_CALL(foo, DoThat(Not(HasSubstr("blah")), + NULL)); +``` + +## Casting Matchers ## + +Google Mock matchers are statically typed, meaning that the compiler +can catch your mistake if you use a matcher of the wrong type (for +example, if you use `Eq(5)` to match a `string` argument). Good for +you! + +Sometimes, however, you know what you're doing and want the compiler +to give you some slack. One example is that you have a matcher for +`long` and the argument you want to match is `int`. While the two +types aren't exactly the same, there is nothing really wrong with +using a `Matcher` to match an `int` - after all, we can first +convert the `int` argument to a `long` before giving it to the +matcher. + +To support this need, Google Mock gives you the +`SafeMatcherCast(m)` function. It casts a matcher `m` to type +`Matcher`. To ensure safety, Google Mock checks that (let `U` be the +type `m` accepts): + + 1. Type `T` can be implicitly cast to type `U`; + 1. When both `T` and `U` are built-in arithmetic types (`bool`, integers, and floating-point numbers), the conversion from `T` to `U` is not lossy (in other words, any value representable by `T` can also be represented by `U`); and + 1. When `U` is a reference, `T` must also be a reference (as the underlying matcher may be interested in the address of the `U` value). + +The code won't compile if any of these conditions aren't met. + +Here's one example: + +``` +using ::testing::SafeMatcherCast; + +// A base class and a child class. +class Base { ... }; +class Derived : public Base { ... }; + +class MockFoo : public Foo { + public: + MOCK_METHOD1(DoThis, void(Derived* derived)); +}; +... + + MockFoo foo; + // m is a Matcher we got from somewhere. + EXPECT_CALL(foo, DoThis(SafeMatcherCast(m))); +``` + +If you find `SafeMatcherCast(m)` too limiting, you can use a similar +function `MatcherCast(m)`. The difference is that `MatcherCast` works +as long as you can `static_cast` type `T` to type `U`. + +`MatcherCast` essentially lets you bypass C++'s type system +(`static_cast` isn't always safe as it could throw away information, +for example), so be careful not to misuse/abuse it. + +## Selecting Between Overloaded Functions ## + +If you expect an overloaded function to be called, the compiler may +need some help on which overloaded version it is. + +To disambiguate functions overloaded on the const-ness of this object, +use the `Const()` argument wrapper. + +``` +using ::testing::ReturnRef; + +class MockFoo : public Foo { + ... + MOCK_METHOD0(GetBar, Bar&()); + MOCK_CONST_METHOD0(GetBar, const Bar&()); +}; +... + + MockFoo foo; + Bar bar1, bar2; + EXPECT_CALL(foo, GetBar()) // The non-const GetBar(). + .WillOnce(ReturnRef(bar1)); + EXPECT_CALL(Const(foo), GetBar()) // The const GetBar(). + .WillOnce(ReturnRef(bar2)); +``` + +(`Const()` is defined by Google Mock and returns a `const` reference +to its argument.) + +To disambiguate overloaded functions with the same number of arguments +but different argument types, you may need to specify the exact type +of a matcher, either by wrapping your matcher in `Matcher()`, or +using a matcher whose type is fixed (`TypedEq`, `An()`, +etc): + +``` +using ::testing::An; +using ::testing::Lt; +using ::testing::Matcher; +using ::testing::TypedEq; + +class MockPrinter : public Printer { + public: + MOCK_METHOD1(Print, void(int n)); + MOCK_METHOD1(Print, void(char c)); +}; + +TEST(PrinterTest, Print) { + MockPrinter printer; + + EXPECT_CALL(printer, Print(An())); // void Print(int); + EXPECT_CALL(printer, Print(Matcher(Lt(5)))); // void Print(int); + EXPECT_CALL(printer, Print(TypedEq('a'))); // void Print(char); + + printer.Print(3); + printer.Print(6); + printer.Print('a'); +} +``` + +## Performing Different Actions Based on the Arguments ## + +When a mock method is called, the _last_ matching expectation that's +still active will be selected (think "newer overrides older"). So, you +can make a method do different things depending on its argument values +like this: + +``` +using ::testing::_; +using ::testing::Lt; +using ::testing::Return; +... + // The default case. + EXPECT_CALL(foo, DoThis(_)) + .WillRepeatedly(Return('b')); + + // The more specific case. + EXPECT_CALL(foo, DoThis(Lt(5))) + .WillRepeatedly(Return('a')); +``` + +Now, if `foo.DoThis()` is called with a value less than 5, `'a'` will +be returned; otherwise `'b'` will be returned. + +## Matching Multiple Arguments as a Whole ## + +Sometimes it's not enough to match the arguments individually. For +example, we may want to say that the first argument must be less than +the second argument. The `With()` clause allows us to match +all arguments of a mock function as a whole. For example, + +``` +using ::testing::_; +using ::testing::Lt; +using ::testing::Ne; +... + EXPECT_CALL(foo, InRange(Ne(0), _)) + .With(Lt()); +``` + +says that the first argument of `InRange()` must not be 0, and must be +less than the second argument. + +The expression inside `With()` must be a matcher of type +`Matcher< ::testing::tuple >`, where `A1`, ..., `An` are the +types of the function arguments. + +You can also write `AllArgs(m)` instead of `m` inside `.With()`. The +two forms are equivalent, but `.With(AllArgs(Lt()))` is more readable +than `.With(Lt())`. + +You can use `Args(m)` to match the `n` selected arguments +(as a tuple) against `m`. For example, + +``` +using ::testing::_; +using ::testing::AllOf; +using ::testing::Args; +using ::testing::Lt; +... + EXPECT_CALL(foo, Blah(_, _, _)) + .With(AllOf(Args<0, 1>(Lt()), Args<1, 2>(Lt()))); +``` + +says that `Blah()` will be called with arguments `x`, `y`, and `z` where +`x < y < z`. + +As a convenience and example, Google Mock provides some matchers for +2-tuples, including the `Lt()` matcher above. See the [CheatSheet](CheatSheet.md) for +the complete list. + +Note that if you want to pass the arguments to a predicate of your own +(e.g. `.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be +written to take a `::testing::tuple` as its argument; Google Mock will pass the `n` selected arguments as _one_ single tuple to the predicate. + +## Using Matchers as Predicates ## + +Have you noticed that a matcher is just a fancy predicate that also +knows how to describe itself? Many existing algorithms take predicates +as arguments (e.g. those defined in STL's `` header), and +it would be a shame if Google Mock matchers are not allowed to +participate. + +Luckily, you can use a matcher where a unary predicate functor is +expected by wrapping it inside the `Matches()` function. For example, + +``` +#include +#include + +std::vector v; +... +// How many elements in v are >= 10? +const int count = count_if(v.begin(), v.end(), Matches(Ge(10))); +``` + +Since you can build complex matchers from simpler ones easily using +Google Mock, this gives you a way to conveniently construct composite +predicates (doing the same using STL's `` header is just +painful). For example, here's a predicate that's satisfied by any +number that is >= 0, <= 100, and != 50: + +``` +Matches(AllOf(Ge(0), Le(100), Ne(50))) +``` + +## Using Matchers in Google Test Assertions ## + +Since matchers are basically predicates that also know how to describe +themselves, there is a way to take advantage of them in +[Google Test](../../googletest/) assertions. It's +called `ASSERT_THAT` and `EXPECT_THAT`: + +``` + ASSERT_THAT(value, matcher); // Asserts that value matches matcher. + EXPECT_THAT(value, matcher); // The non-fatal version. +``` + +For example, in a Google Test test you can write: + +``` +#include "gmock/gmock.h" + +using ::testing::AllOf; +using ::testing::Ge; +using ::testing::Le; +using ::testing::MatchesRegex; +using ::testing::StartsWith; +... + + EXPECT_THAT(Foo(), StartsWith("Hello")); + EXPECT_THAT(Bar(), MatchesRegex("Line \\d+")); + ASSERT_THAT(Baz(), AllOf(Ge(5), Le(10))); +``` + +which (as you can probably guess) executes `Foo()`, `Bar()`, and +`Baz()`, and verifies that: + + * `Foo()` returns a string that starts with `"Hello"`. + * `Bar()` returns a string that matches regular expression `"Line \\d+"`. + * `Baz()` returns a number in the range [5, 10]. + +The nice thing about these macros is that _they read like +English_. They generate informative messages too. For example, if the +first `EXPECT_THAT()` above fails, the message will be something like: + +``` +Value of: Foo() + Actual: "Hi, world!" +Expected: starts with "Hello" +``` + +**Credit:** The idea of `(ASSERT|EXPECT)_THAT` was stolen from the +[Hamcrest](https://github.com/hamcrest/) project, which adds +`assertThat()` to JUnit. + +## Using Predicates as Matchers ## + +Google Mock provides a built-in set of matchers. In case you find them +lacking, you can use an arbitray unary predicate function or functor +as a matcher - as long as the predicate accepts a value of the type +you want. You do this by wrapping the predicate inside the `Truly()` +function, for example: + +``` +using ::testing::Truly; + +int IsEven(int n) { return (n % 2) == 0 ? 1 : 0; } +... + + // Bar() must be called with an even number. + EXPECT_CALL(foo, Bar(Truly(IsEven))); +``` + +Note that the predicate function / functor doesn't have to return +`bool`. It works as long as the return value can be used as the +condition in statement `if (condition) ...`. + +## Matching Arguments that Are Not Copyable ## + +When you do an `EXPECT_CALL(mock_obj, Foo(bar))`, Google Mock saves +away a copy of `bar`. When `Foo()` is called later, Google Mock +compares the argument to `Foo()` with the saved copy of `bar`. This +way, you don't need to worry about `bar` being modified or destroyed +after the `EXPECT_CALL()` is executed. The same is true when you use +matchers like `Eq(bar)`, `Le(bar)`, and so on. + +But what if `bar` cannot be copied (i.e. has no copy constructor)? You +could define your own matcher function and use it with `Truly()`, as +the previous couple of recipes have shown. Or, you may be able to get +away from it if you can guarantee that `bar` won't be changed after +the `EXPECT_CALL()` is executed. Just tell Google Mock that it should +save a reference to `bar`, instead of a copy of it. Here's how: + +``` +using ::testing::Eq; +using ::testing::ByRef; +using ::testing::Lt; +... + // Expects that Foo()'s argument == bar. + EXPECT_CALL(mock_obj, Foo(Eq(ByRef(bar)))); + + // Expects that Foo()'s argument < bar. + EXPECT_CALL(mock_obj, Foo(Lt(ByRef(bar)))); +``` + +Remember: if you do this, don't change `bar` after the +`EXPECT_CALL()`, or the result is undefined. + +## Validating a Member of an Object ## + +Often a mock function takes a reference to object as an argument. When +matching the argument, you may not want to compare the entire object +against a fixed object, as that may be over-specification. Instead, +you may need to validate a certain member variable or the result of a +certain getter method of the object. You can do this with `Field()` +and `Property()`. More specifically, + +``` +Field(&Foo::bar, m) +``` + +is a matcher that matches a `Foo` object whose `bar` member variable +satisfies matcher `m`. + +``` +Property(&Foo::baz, m) +``` + +is a matcher that matches a `Foo` object whose `baz()` method returns +a value that satisfies matcher `m`. + +For example: + +| Expression | Description | +|:-----------------------------|:-----------------------------------| +| `Field(&Foo::number, Ge(3))` | Matches `x` where `x.number >= 3`. | +| `Property(&Foo::name, StartsWith("John "))` | Matches `x` where `x.name()` starts with `"John "`. | + +Note that in `Property(&Foo::baz, ...)`, method `baz()` must take no +argument and be declared as `const`. + +BTW, `Field()` and `Property()` can also match plain pointers to +objects. For instance, + +``` +Field(&Foo::number, Ge(3)) +``` + +matches a plain pointer `p` where `p->number >= 3`. If `p` is `NULL`, +the match will always fail regardless of the inner matcher. + +What if you want to validate more than one members at the same time? +Remember that there is `AllOf()`. + +## Validating the Value Pointed to by a Pointer Argument ## + +C++ functions often take pointers as arguments. You can use matchers +like `IsNull()`, `NotNull()`, and other comparison matchers to match a +pointer, but what if you want to make sure the value _pointed to_ by +the pointer, instead of the pointer itself, has a certain property? +Well, you can use the `Pointee(m)` matcher. + +`Pointee(m)` matches a pointer iff `m` matches the value the pointer +points to. For example: + +``` +using ::testing::Ge; +using ::testing::Pointee; +... + EXPECT_CALL(foo, Bar(Pointee(Ge(3)))); +``` + +expects `foo.Bar()` to be called with a pointer that points to a value +greater than or equal to 3. + +One nice thing about `Pointee()` is that it treats a `NULL` pointer as +a match failure, so you can write `Pointee(m)` instead of + +``` + AllOf(NotNull(), Pointee(m)) +``` + +without worrying that a `NULL` pointer will crash your test. + +Also, did we tell you that `Pointee()` works with both raw pointers +**and** smart pointers (`linked_ptr`, `shared_ptr`, `scoped_ptr`, and +etc)? + +What if you have a pointer to pointer? You guessed it - you can use +nested `Pointee()` to probe deeper inside the value. For example, +`Pointee(Pointee(Lt(3)))` matches a pointer that points to a pointer +that points to a number less than 3 (what a mouthful...). + +## Testing a Certain Property of an Object ## + +Sometimes you want to specify that an object argument has a certain +property, but there is no existing matcher that does this. If you want +good error messages, you should define a matcher. If you want to do it +quick and dirty, you could get away with writing an ordinary function. + +Let's say you have a mock function that takes an object of type `Foo`, +which has an `int bar()` method and an `int baz()` method, and you +want to constrain that the argument's `bar()` value plus its `baz()` +value is a given number. Here's how you can define a matcher to do it: + +``` +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; + +class BarPlusBazEqMatcher : public MatcherInterface { + public: + explicit BarPlusBazEqMatcher(int expected_sum) + : expected_sum_(expected_sum) {} + + virtual bool MatchAndExplain(const Foo& foo, + MatchResultListener* listener) const { + return (foo.bar() + foo.baz()) == expected_sum_; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "bar() + baz() equals " << expected_sum_; + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "bar() + baz() does not equal " << expected_sum_; + } + private: + const int expected_sum_; +}; + +inline Matcher BarPlusBazEq(int expected_sum) { + return MakeMatcher(new BarPlusBazEqMatcher(expected_sum)); +} + +... + + EXPECT_CALL(..., DoThis(BarPlusBazEq(5)))...; +``` + +## Matching Containers ## + +Sometimes an STL container (e.g. list, vector, map, ...) is passed to +a mock function and you may want to validate it. Since most STL +containers support the `==` operator, you can write +`Eq(expected_container)` or simply `expected_container` to match a +container exactly. + +Sometimes, though, you may want to be more flexible (for example, the +first element must be an exact match, but the second element can be +any positive number, and so on). Also, containers used in tests often +have a small number of elements, and having to define the expected +container out-of-line is a bit of a hassle. + +You can use the `ElementsAre()` or `UnorderedElementsAre()` matcher in +such cases: + +``` +using ::testing::_; +using ::testing::ElementsAre; +using ::testing::Gt; +... + + MOCK_METHOD1(Foo, void(const vector& numbers)); +... + + EXPECT_CALL(mock, Foo(ElementsAre(1, Gt(0), _, 5))); +``` + +The above matcher says that the container must have 4 elements, which +must be 1, greater than 0, anything, and 5 respectively. + +If you instead write: + +``` +using ::testing::_; +using ::testing::Gt; +using ::testing::UnorderedElementsAre; +... + + MOCK_METHOD1(Foo, void(const vector& numbers)); +... + + EXPECT_CALL(mock, Foo(UnorderedElementsAre(1, Gt(0), _, 5))); +``` + +It means that the container must have 4 elements, which under some +permutation must be 1, greater than 0, anything, and 5 respectively. + +`ElementsAre()` and `UnorderedElementsAre()` are overloaded to take 0 +to 10 arguments. If more are needed, you can place them in a C-style +array and use `ElementsAreArray()` or `UnorderedElementsAreArray()` +instead: + +``` +using ::testing::ElementsAreArray; +... + + // ElementsAreArray accepts an array of element values. + const int expected_vector1[] = { 1, 5, 2, 4, ... }; + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector1))); + + // Or, an array of element matchers. + Matcher expected_vector2 = { 1, Gt(2), _, 3, ... }; + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector2))); +``` + +In case the array needs to be dynamically created (and therefore the +array size cannot be inferred by the compiler), you can give +`ElementsAreArray()` an additional argument to specify the array size: + +``` +using ::testing::ElementsAreArray; +... + int* const expected_vector3 = new int[count]; + ... fill expected_vector3 with values ... + EXPECT_CALL(mock, Foo(ElementsAreArray(expected_vector3, count))); +``` + +**Tips:** + + * `ElementsAre*()` can be used to match _any_ container that implements the STL iterator pattern (i.e. it has a `const_iterator` type and supports `begin()/end()`), not just the ones defined in STL. It will even work with container types yet to be written - as long as they follows the above pattern. + * You can use nested `ElementsAre*()` to match nested (multi-dimensional) containers. + * If the container is passed by pointer instead of by reference, just write `Pointee(ElementsAre*(...))`. + * The order of elements _matters_ for `ElementsAre*()`. Therefore don't use it with containers whose element order is undefined (e.g. `hash_map`). + +## Sharing Matchers ## + +Under the hood, a Google Mock matcher object consists of a pointer to +a ref-counted implementation object. Copying matchers is allowed and +very efficient, as only the pointer is copied. When the last matcher +that references the implementation object dies, the implementation +object will be deleted. + +Therefore, if you have some complex matcher that you want to use again +and again, there is no need to build it every time. Just assign it to a +matcher variable and use that variable repeatedly! For example, + +``` + Matcher in_range = AllOf(Gt(5), Le(10)); + ... use in_range as a matcher in multiple EXPECT_CALLs ... +``` + +# Setting Expectations # + +## Knowing When to Expect ## + +`ON_CALL` is likely the single most under-utilized construct in Google Mock. + +There are basically two constructs for defining the behavior of a mock object: `ON_CALL` and `EXPECT_CALL`. The difference? `ON_CALL` defines what happens when a mock method is called, but _doesn't imply any expectation on the method being called._ `EXPECT_CALL` not only defines the behavior, but also sets an expectation that _the method will be called with the given arguments, for the given number of times_ (and _in the given order_ when you specify the order too). + +Since `EXPECT_CALL` does more, isn't it better than `ON_CALL`? Not really. Every `EXPECT_CALL` adds a constraint on the behavior of the code under test. Having more constraints than necessary is _baaad_ - even worse than not having enough constraints. + +This may be counter-intuitive. How could tests that verify more be worse than tests that verify less? Isn't verification the whole point of tests? + +The answer, lies in _what_ a test should verify. **A good test verifies the contract of the code.** If a test over-specifies, it doesn't leave enough freedom to the implementation. As a result, changing the implementation without breaking the contract (e.g. refactoring and optimization), which should be perfectly fine to do, can break such tests. Then you have to spend time fixing them, only to see them broken again the next time the implementation is changed. + +Keep in mind that one doesn't have to verify more than one property in one test. In fact, **it's a good style to verify only one thing in one test.** If you do that, a bug will likely break only one or two tests instead of dozens (which case would you rather debug?). If you are also in the habit of giving tests descriptive names that tell what they verify, you can often easily guess what's wrong just from the test log itself. + +So use `ON_CALL` by default, and only use `EXPECT_CALL` when you actually intend to verify that the call is made. For example, you may have a bunch of `ON_CALL`s in your test fixture to set the common mock behavior shared by all tests in the same group, and write (scarcely) different `EXPECT_CALL`s in different `TEST_F`s to verify different aspects of the code's behavior. Compared with the style where each `TEST` has many `EXPECT_CALL`s, this leads to tests that are more resilient to implementational changes (and thus less likely to require maintenance) and makes the intent of the tests more obvious (so they are easier to maintain when you do need to maintain them). + +If you are bothered by the "Uninteresting mock function call" message printed when a mock method without an `EXPECT_CALL` is called, you may use a `NiceMock` instead to suppress all such messages for the mock object, or suppress the message for specific methods by adding `EXPECT_CALL(...).Times(AnyNumber())`. DO NOT suppress it by blindly adding an `EXPECT_CALL(...)`, or you'll have a test that's a pain to maintain. + +## Ignoring Uninteresting Calls ## + +If you are not interested in how a mock method is called, just don't +say anything about it. In this case, if the method is ever called, +Google Mock will perform its default action to allow the test program +to continue. If you are not happy with the default action taken by +Google Mock, you can override it using `DefaultValue::Set()` +(described later in this document) or `ON_CALL()`. + +Please note that once you expressed interest in a particular mock +method (via `EXPECT_CALL()`), all invocations to it must match some +expectation. If this function is called but the arguments don't match +any `EXPECT_CALL()` statement, it will be an error. + +## Disallowing Unexpected Calls ## + +If a mock method shouldn't be called at all, explicitly say so: + +``` +using ::testing::_; +... + EXPECT_CALL(foo, Bar(_)) + .Times(0); +``` + +If some calls to the method are allowed, but the rest are not, just +list all the expected calls: + +``` +using ::testing::AnyNumber; +using ::testing::Gt; +... + EXPECT_CALL(foo, Bar(5)); + EXPECT_CALL(foo, Bar(Gt(10))) + .Times(AnyNumber()); +``` + +A call to `foo.Bar()` that doesn't match any of the `EXPECT_CALL()` +statements will be an error. + +## Understanding Uninteresting vs Unexpected Calls ## + +_Uninteresting_ calls and _unexpected_ calls are different concepts in Google Mock. _Very_ different. + +A call `x.Y(...)` is **uninteresting** if there's _not even a single_ `EXPECT_CALL(x, Y(...))` set. In other words, the test isn't interested in the `x.Y()` method at all, as evident in that the test doesn't care to say anything about it. + +A call `x.Y(...)` is **unexpected** if there are some `EXPECT_CALL(x, Y(...))s` set, but none of them matches the call. Put another way, the test is interested in the `x.Y()` method (therefore it _explicitly_ sets some `EXPECT_CALL` to verify how it's called); however, the verification fails as the test doesn't expect this particular call to happen. + +**An unexpected call is always an error,** as the code under test doesn't behave the way the test expects it to behave. + +**By default, an uninteresting call is not an error,** as it violates no constraint specified by the test. (Google Mock's philosophy is that saying nothing means there is no constraint.) However, it leads to a warning, as it _might_ indicate a problem (e.g. the test author might have forgotten to specify a constraint). + +In Google Mock, `NiceMock` and `StrictMock` can be used to make a mock class "nice" or "strict". How does this affect uninteresting calls and unexpected calls? + +A **nice mock** suppresses uninteresting call warnings. It is less chatty than the default mock, but otherwise is the same. If a test fails with a default mock, it will also fail using a nice mock instead. And vice versa. Don't expect making a mock nice to change the test's result. + +A **strict mock** turns uninteresting call warnings into errors. So making a mock strict may change the test's result. + +Let's look at an example: + +``` +TEST(...) { + NiceMock mock_registry; + EXPECT_CALL(mock_registry, GetDomainOwner("google.com")) + .WillRepeatedly(Return("Larry Page")); + + // Use mock_registry in code under test. + ... &mock_registry ... +} +``` + +The sole `EXPECT_CALL` here says that all calls to `GetDomainOwner()` must have `"google.com"` as the argument. If `GetDomainOwner("yahoo.com")` is called, it will be an unexpected call, and thus an error. Having a nice mock doesn't change the severity of an unexpected call. + +So how do we tell Google Mock that `GetDomainOwner()` can be called with some other arguments as well? The standard technique is to add a "catch all" `EXPECT_CALL`: + +``` + EXPECT_CALL(mock_registry, GetDomainOwner(_)) + .Times(AnyNumber()); // catches all other calls to this method. + EXPECT_CALL(mock_registry, GetDomainOwner("google.com")) + .WillRepeatedly(Return("Larry Page")); +``` + +Remember that `_` is the wildcard matcher that matches anything. With this, if `GetDomainOwner("google.com")` is called, it will do what the second `EXPECT_CALL` says; if it is called with a different argument, it will do what the first `EXPECT_CALL` says. + +Note that the order of the two `EXPECT_CALLs` is important, as a newer `EXPECT_CALL` takes precedence over an older one. + +For more on uninteresting calls, nice mocks, and strict mocks, read ["The Nice, the Strict, and the Naggy"](#the-nice-the-strict-and-the-naggy). + +## Expecting Ordered Calls ## + +Although an `EXPECT_CALL()` statement defined earlier takes precedence +when Google Mock tries to match a function call with an expectation, +by default calls don't have to happen in the order `EXPECT_CALL()` +statements are written. For example, if the arguments match the +matchers in the third `EXPECT_CALL()`, but not those in the first two, +then the third expectation will be used. + +If you would rather have all calls occur in the order of the +expectations, put the `EXPECT_CALL()` statements in a block where you +define a variable of type `InSequence`: + +``` + using ::testing::_; + using ::testing::InSequence; + + { + InSequence s; + + EXPECT_CALL(foo, DoThis(5)); + EXPECT_CALL(bar, DoThat(_)) + .Times(2); + EXPECT_CALL(foo, DoThis(6)); + } +``` + +In this example, we expect a call to `foo.DoThis(5)`, followed by two +calls to `bar.DoThat()` where the argument can be anything, which are +in turn followed by a call to `foo.DoThis(6)`. If a call occurred +out-of-order, Google Mock will report an error. + +## Expecting Partially Ordered Calls ## + +Sometimes requiring everything to occur in a predetermined order can +lead to brittle tests. For example, we may care about `A` occurring +before both `B` and `C`, but aren't interested in the relative order +of `B` and `C`. In this case, the test should reflect our real intent, +instead of being overly constraining. + +Google Mock allows you to impose an arbitrary DAG (directed acyclic +graph) on the calls. One way to express the DAG is to use the +[After](CheatSheet.md#the-after-clause) clause of `EXPECT_CALL`. + +Another way is via the `InSequence()` clause (not the same as the +`InSequence` class), which we borrowed from jMock 2. It's less +flexible than `After()`, but more convenient when you have long chains +of sequential calls, as it doesn't require you to come up with +different names for the expectations in the chains. Here's how it +works: + +If we view `EXPECT_CALL()` statements as nodes in a graph, and add an +edge from node A to node B wherever A must occur before B, we can get +a DAG. We use the term "sequence" to mean a directed path in this +DAG. Now, if we decompose the DAG into sequences, we just need to know +which sequences each `EXPECT_CALL()` belongs to in order to be able to +reconstruct the original DAG. + +So, to specify the partial order on the expectations we need to do two +things: first to define some `Sequence` objects, and then for each +`EXPECT_CALL()` say which `Sequence` objects it is part +of. Expectations in the same sequence must occur in the order they are +written. For example, + +``` + using ::testing::Sequence; + + Sequence s1, s2; + + EXPECT_CALL(foo, A()) + .InSequence(s1, s2); + EXPECT_CALL(bar, B()) + .InSequence(s1); + EXPECT_CALL(bar, C()) + .InSequence(s2); + EXPECT_CALL(foo, D()) + .InSequence(s2); +``` + +specifies the following DAG (where `s1` is `A -> B`, and `s2` is `A -> +C -> D`): + +``` + +---> B + | + A ---| + | + +---> C ---> D +``` + +This means that A must occur before B and C, and C must occur before +D. There's no restriction about the order other than these. + +## Controlling When an Expectation Retires ## + +When a mock method is called, Google Mock only consider expectations +that are still active. An expectation is active when created, and +becomes inactive (aka _retires_) when a call that has to occur later +has occurred. For example, in + +``` + using ::testing::_; + using ::testing::Sequence; + + Sequence s1, s2; + + EXPECT_CALL(log, Log(WARNING, _, "File too large.")) // #1 + .Times(AnyNumber()) + .InSequence(s1, s2); + EXPECT_CALL(log, Log(WARNING, _, "Data set is empty.")) // #2 + .InSequence(s1); + EXPECT_CALL(log, Log(WARNING, _, "User not found.")) // #3 + .InSequence(s2); +``` + +as soon as either #2 or #3 is matched, #1 will retire. If a warning +`"File too large."` is logged after this, it will be an error. + +Note that an expectation doesn't retire automatically when it's +saturated. For example, + +``` +using ::testing::_; +... + EXPECT_CALL(log, Log(WARNING, _, _)); // #1 + EXPECT_CALL(log, Log(WARNING, _, "File too large.")); // #2 +``` + +says that there will be exactly one warning with the message `"File +too large."`. If the second warning contains this message too, #2 will +match again and result in an upper-bound-violated error. + +If this is not what you want, you can ask an expectation to retire as +soon as it becomes saturated: + +``` +using ::testing::_; +... + EXPECT_CALL(log, Log(WARNING, _, _)); // #1 + EXPECT_CALL(log, Log(WARNING, _, "File too large.")) // #2 + .RetiresOnSaturation(); +``` + +Here #2 can be used only once, so if you have two warnings with the +message `"File too large."`, the first will match #2 and the second +will match #1 - there will be no error. + +# Using Actions # + +## Returning References from Mock Methods ## + +If a mock function's return type is a reference, you need to use +`ReturnRef()` instead of `Return()` to return a result: + +``` +using ::testing::ReturnRef; + +class MockFoo : public Foo { + public: + MOCK_METHOD0(GetBar, Bar&()); +}; +... + + MockFoo foo; + Bar bar; + EXPECT_CALL(foo, GetBar()) + .WillOnce(ReturnRef(bar)); +``` + +## Returning Live Values from Mock Methods ## + +The `Return(x)` action saves a copy of `x` when the action is +_created_, and always returns the same value whenever it's +executed. Sometimes you may want to instead return the _live_ value of +`x` (i.e. its value at the time when the action is _executed_.). + +If the mock function's return type is a reference, you can do it using +`ReturnRef(x)`, as shown in the previous recipe ("Returning References +from Mock Methods"). However, Google Mock doesn't let you use +`ReturnRef()` in a mock function whose return type is not a reference, +as doing that usually indicates a user error. So, what shall you do? + +You may be tempted to try `ByRef()`: + +``` +using testing::ByRef; +using testing::Return; + +class MockFoo : public Foo { + public: + MOCK_METHOD0(GetValue, int()); +}; +... + int x = 0; + MockFoo foo; + EXPECT_CALL(foo, GetValue()) + .WillRepeatedly(Return(ByRef(x))); + x = 42; + EXPECT_EQ(42, foo.GetValue()); +``` + +Unfortunately, it doesn't work here. The above code will fail with error: + +``` +Value of: foo.GetValue() + Actual: 0 +Expected: 42 +``` + +The reason is that `Return(value)` converts `value` to the actual +return type of the mock function at the time when the action is +_created_, not when it is _executed_. (This behavior was chosen for +the action to be safe when `value` is a proxy object that references +some temporary objects.) As a result, `ByRef(x)` is converted to an +`int` value (instead of a `const int&`) when the expectation is set, +and `Return(ByRef(x))` will always return 0. + +`ReturnPointee(pointer)` was provided to solve this problem +specifically. It returns the value pointed to by `pointer` at the time +the action is _executed_: + +``` +using testing::ReturnPointee; +... + int x = 0; + MockFoo foo; + EXPECT_CALL(foo, GetValue()) + .WillRepeatedly(ReturnPointee(&x)); // Note the & here. + x = 42; + EXPECT_EQ(42, foo.GetValue()); // This will succeed now. +``` + +## Combining Actions ## + +Want to do more than one thing when a function is called? That's +fine. `DoAll()` allow you to do sequence of actions every time. Only +the return value of the last action in the sequence will be used. + +``` +using ::testing::DoAll; + +class MockFoo : public Foo { + public: + MOCK_METHOD1(Bar, bool(int n)); +}; +... + + EXPECT_CALL(foo, Bar(_)) + .WillOnce(DoAll(action_1, + action_2, + ... + action_n)); +``` + +## Mocking Side Effects ## + +Sometimes a method exhibits its effect not via returning a value but +via side effects. For example, it may change some global state or +modify an output argument. To mock side effects, in general you can +define your own action by implementing `::testing::ActionInterface`. + +If all you need to do is to change an output argument, the built-in +`SetArgPointee()` action is convenient: + +``` +using ::testing::SetArgPointee; + +class MockMutator : public Mutator { + public: + MOCK_METHOD2(Mutate, void(bool mutate, int* value)); + ... +}; +... + + MockMutator mutator; + EXPECT_CALL(mutator, Mutate(true, _)) + .WillOnce(SetArgPointee<1>(5)); +``` + +In this example, when `mutator.Mutate()` is called, we will assign 5 +to the `int` variable pointed to by argument #1 +(0-based). + +`SetArgPointee()` conveniently makes an internal copy of the +value you pass to it, removing the need to keep the value in scope and +alive. The implication however is that the value must have a copy +constructor and assignment operator. + +If the mock method also needs to return a value as well, you can chain +`SetArgPointee()` with `Return()` using `DoAll()`: + +``` +using ::testing::_; +using ::testing::Return; +using ::testing::SetArgPointee; + +class MockMutator : public Mutator { + public: + ... + MOCK_METHOD1(MutateInt, bool(int* value)); +}; +... + + MockMutator mutator; + EXPECT_CALL(mutator, MutateInt(_)) + .WillOnce(DoAll(SetArgPointee<0>(5), + Return(true))); +``` + +If the output argument is an array, use the +`SetArrayArgument(first, last)` action instead. It copies the +elements in source range `[first, last)` to the array pointed to by +the `N`-th (0-based) argument: + +``` +using ::testing::NotNull; +using ::testing::SetArrayArgument; + +class MockArrayMutator : public ArrayMutator { + public: + MOCK_METHOD2(Mutate, void(int* values, int num_values)); + ... +}; +... + + MockArrayMutator mutator; + int values[5] = { 1, 2, 3, 4, 5 }; + EXPECT_CALL(mutator, Mutate(NotNull(), 5)) + .WillOnce(SetArrayArgument<0>(values, values + 5)); +``` + +This also works when the argument is an output iterator: + +``` +using ::testing::_; +using ::testing::SetArrayArgument; + +class MockRolodex : public Rolodex { + public: + MOCK_METHOD1(GetNames, void(std::back_insert_iterator >)); + ... +}; +... + + MockRolodex rolodex; + vector names; + names.push_back("George"); + names.push_back("John"); + names.push_back("Thomas"); + EXPECT_CALL(rolodex, GetNames(_)) + .WillOnce(SetArrayArgument<0>(names.begin(), names.end())); +``` + +## Changing a Mock Object's Behavior Based on the State ## + +If you expect a call to change the behavior of a mock object, you can use `::testing::InSequence` to specify different behaviors before and after the call: + +``` +using ::testing::InSequence; +using ::testing::Return; + +... + { + InSequence seq; + EXPECT_CALL(my_mock, IsDirty()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(my_mock, Flush()); + EXPECT_CALL(my_mock, IsDirty()) + .WillRepeatedly(Return(false)); + } + my_mock.FlushIfDirty(); +``` + +This makes `my_mock.IsDirty()` return `true` before `my_mock.Flush()` is called and return `false` afterwards. + +If the behavior change is more complex, you can store the effects in a variable and make a mock method get its return value from that variable: + +``` +using ::testing::_; +using ::testing::SaveArg; +using ::testing::Return; + +ACTION_P(ReturnPointee, p) { return *p; } +... + int previous_value = 0; + EXPECT_CALL(my_mock, GetPrevValue()) + .WillRepeatedly(ReturnPointee(&previous_value)); + EXPECT_CALL(my_mock, UpdateValue(_)) + .WillRepeatedly(SaveArg<0>(&previous_value)); + my_mock.DoSomethingToUpdateValue(); +``` + +Here `my_mock.GetPrevValue()` will always return the argument of the last `UpdateValue()` call. + +## Setting the Default Value for a Return Type ## + +If a mock method's return type is a built-in C++ type or pointer, by +default it will return 0 when invoked. Also, in C++ 11 and above, a mock +method whose return type has a default constructor will return a default-constructed +value by default. You only need to specify an +action if this default value doesn't work for you. + +Sometimes, you may want to change this default value, or you may want +to specify a default value for types Google Mock doesn't know +about. You can do this using the `::testing::DefaultValue` class +template: + +``` +class MockFoo : public Foo { + public: + MOCK_METHOD0(CalculateBar, Bar()); +}; +... + + Bar default_bar; + // Sets the default return value for type Bar. + DefaultValue::Set(default_bar); + + MockFoo foo; + + // We don't need to specify an action here, as the default + // return value works for us. + EXPECT_CALL(foo, CalculateBar()); + + foo.CalculateBar(); // This should return default_bar. + + // Unsets the default return value. + DefaultValue::Clear(); +``` + +Please note that changing the default value for a type can make you +tests hard to understand. We recommend you to use this feature +judiciously. For example, you may want to make sure the `Set()` and +`Clear()` calls are right next to the code that uses your mock. + +## Setting the Default Actions for a Mock Method ## + +You've learned how to change the default value of a given +type. However, this may be too coarse for your purpose: perhaps you +have two mock methods with the same return type and you want them to +have different behaviors. The `ON_CALL()` macro allows you to +customize your mock's behavior at the method level: + +``` +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Gt; +using ::testing::Return; +... + ON_CALL(foo, Sign(_)) + .WillByDefault(Return(-1)); + ON_CALL(foo, Sign(0)) + .WillByDefault(Return(0)); + ON_CALL(foo, Sign(Gt(0))) + .WillByDefault(Return(1)); + + EXPECT_CALL(foo, Sign(_)) + .Times(AnyNumber()); + + foo.Sign(5); // This should return 1. + foo.Sign(-9); // This should return -1. + foo.Sign(0); // This should return 0. +``` + +As you may have guessed, when there are more than one `ON_CALL()` +statements, the news order take precedence over the older ones. In +other words, the **last** one that matches the function arguments will +be used. This matching order allows you to set up the common behavior +in a mock object's constructor or the test fixture's set-up phase and +specialize the mock's behavior later. + +## Using Functions/Methods/Functors as Actions ## + +If the built-in actions don't suit you, you can easily use an existing +function, method, or functor as an action: + +``` +using ::testing::_; +using ::testing::Invoke; + +class MockFoo : public Foo { + public: + MOCK_METHOD2(Sum, int(int x, int y)); + MOCK_METHOD1(ComplexJob, bool(int x)); +}; + +int CalculateSum(int x, int y) { return x + y; } + +class Helper { + public: + bool ComplexJob(int x); +}; +... + + MockFoo foo; + Helper helper; + EXPECT_CALL(foo, Sum(_, _)) + .WillOnce(Invoke(CalculateSum)); + EXPECT_CALL(foo, ComplexJob(_)) + .WillOnce(Invoke(&helper, &Helper::ComplexJob)); + + foo.Sum(5, 6); // Invokes CalculateSum(5, 6). + foo.ComplexJob(10); // Invokes helper.ComplexJob(10); +``` + +The only requirement is that the type of the function, etc must be +_compatible_ with the signature of the mock function, meaning that the +latter's arguments can be implicitly converted to the corresponding +arguments of the former, and the former's return type can be +implicitly converted to that of the latter. So, you can invoke +something whose type is _not_ exactly the same as the mock function, +as long as it's safe to do so - nice, huh? + +## Invoking a Function/Method/Functor Without Arguments ## + +`Invoke()` is very useful for doing actions that are more complex. It +passes the mock function's arguments to the function or functor being +invoked such that the callee has the full context of the call to work +with. If the invoked function is not interested in some or all of the +arguments, it can simply ignore them. + +Yet, a common pattern is that a test author wants to invoke a function +without the arguments of the mock function. `Invoke()` allows her to +do that using a wrapper function that throws away the arguments before +invoking an underlining nullary function. Needless to say, this can be +tedious and obscures the intent of the test. + +`InvokeWithoutArgs()` solves this problem. It's like `Invoke()` except +that it doesn't pass the mock function's arguments to the +callee. Here's an example: + +``` +using ::testing::_; +using ::testing::InvokeWithoutArgs; + +class MockFoo : public Foo { + public: + MOCK_METHOD1(ComplexJob, bool(int n)); +}; + +bool Job1() { ... } +... + + MockFoo foo; + EXPECT_CALL(foo, ComplexJob(_)) + .WillOnce(InvokeWithoutArgs(Job1)); + + foo.ComplexJob(10); // Invokes Job1(). +``` + +## Invoking an Argument of the Mock Function ## + +Sometimes a mock function will receive a function pointer or a functor +(in other words, a "callable") as an argument, e.g. + +``` +class MockFoo : public Foo { + public: + MOCK_METHOD2(DoThis, bool(int n, bool (*fp)(int))); +}; +``` + +and you may want to invoke this callable argument: + +``` +using ::testing::_; +... + MockFoo foo; + EXPECT_CALL(foo, DoThis(_, _)) + .WillOnce(...); + // Will execute (*fp)(5), where fp is the + // second argument DoThis() receives. +``` + +Arghh, you need to refer to a mock function argument but your version +of C++ has no lambdas, so you have to define your own action. :-( +Or do you really? + +Well, Google Mock has an action to solve _exactly_ this problem: + +``` + InvokeArgument(arg_1, arg_2, ..., arg_m) +``` + +will invoke the `N`-th (0-based) argument the mock function receives, +with `arg_1`, `arg_2`, ..., and `arg_m`. No matter if the argument is +a function pointer or a functor, Google Mock handles them both. + +With that, you could write: + +``` +using ::testing::_; +using ::testing::InvokeArgument; +... + EXPECT_CALL(foo, DoThis(_, _)) + .WillOnce(InvokeArgument<1>(5)); + // Will execute (*fp)(5), where fp is the + // second argument DoThis() receives. +``` + +What if the callable takes an argument by reference? No problem - just +wrap it inside `ByRef()`: + +``` +... + MOCK_METHOD1(Bar, bool(bool (*fp)(int, const Helper&))); +... +using ::testing::_; +using ::testing::ByRef; +using ::testing::InvokeArgument; +... + + MockFoo foo; + Helper helper; + ... + EXPECT_CALL(foo, Bar(_)) + .WillOnce(InvokeArgument<0>(5, ByRef(helper))); + // ByRef(helper) guarantees that a reference to helper, not a copy of it, + // will be passed to the callable. +``` + +What if the callable takes an argument by reference and we do **not** +wrap the argument in `ByRef()`? Then `InvokeArgument()` will _make a +copy_ of the argument, and pass a _reference to the copy_, instead of +a reference to the original value, to the callable. This is especially +handy when the argument is a temporary value: + +``` +... + MOCK_METHOD1(DoThat, bool(bool (*f)(const double& x, const string& s))); +... +using ::testing::_; +using ::testing::InvokeArgument; +... + + MockFoo foo; + ... + EXPECT_CALL(foo, DoThat(_)) + .WillOnce(InvokeArgument<0>(5.0, string("Hi"))); + // Will execute (*f)(5.0, string("Hi")), where f is the function pointer + // DoThat() receives. Note that the values 5.0 and string("Hi") are + // temporary and dead once the EXPECT_CALL() statement finishes. Yet + // it's fine to perform this action later, since a copy of the values + // are kept inside the InvokeArgument action. +``` + +## Ignoring an Action's Result ## + +Sometimes you have an action that returns _something_, but you need an +action that returns `void` (perhaps you want to use it in a mock +function that returns `void`, or perhaps it needs to be used in +`DoAll()` and it's not the last in the list). `IgnoreResult()` lets +you do that. For example: + +``` +using ::testing::_; +using ::testing::Invoke; +using ::testing::Return; + +int Process(const MyData& data); +string DoSomething(); + +class MockFoo : public Foo { + public: + MOCK_METHOD1(Abc, void(const MyData& data)); + MOCK_METHOD0(Xyz, bool()); +}; +... + + MockFoo foo; + EXPECT_CALL(foo, Abc(_)) + // .WillOnce(Invoke(Process)); + // The above line won't compile as Process() returns int but Abc() needs + // to return void. + .WillOnce(IgnoreResult(Invoke(Process))); + + EXPECT_CALL(foo, Xyz()) + .WillOnce(DoAll(IgnoreResult(Invoke(DoSomething)), + // Ignores the string DoSomething() returns. + Return(true))); +``` + +Note that you **cannot** use `IgnoreResult()` on an action that already +returns `void`. Doing so will lead to ugly compiler errors. + +## Selecting an Action's Arguments ## + +Say you have a mock function `Foo()` that takes seven arguments, and +you have a custom action that you want to invoke when `Foo()` is +called. Trouble is, the custom action only wants three arguments: + +``` +using ::testing::_; +using ::testing::Invoke; +... + MOCK_METHOD7(Foo, bool(bool visible, const string& name, int x, int y, + const map, double>& weight, + double min_weight, double max_wight)); +... + +bool IsVisibleInQuadrant1(bool visible, int x, int y) { + return visible && x >= 0 && y >= 0; +} +... + + EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _)) + .WillOnce(Invoke(IsVisibleInQuadrant1)); // Uh, won't compile. :-( +``` + +To please the compiler God, you can to define an "adaptor" that has +the same signature as `Foo()` and calls the custom action with the +right arguments: + +``` +using ::testing::_; +using ::testing::Invoke; + +bool MyIsVisibleInQuadrant1(bool visible, const string& name, int x, int y, + const map, double>& weight, + double min_weight, double max_wight) { + return IsVisibleInQuadrant1(visible, x, y); +} +... + + EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _)) + .WillOnce(Invoke(MyIsVisibleInQuadrant1)); // Now it works. +``` + +But isn't this awkward? + +Google Mock provides a generic _action adaptor_, so you can spend your +time minding more important business than writing your own +adaptors. Here's the syntax: + +``` + WithArgs(action) +``` + +creates an action that passes the arguments of the mock function at +the given indices (0-based) to the inner `action` and performs +it. Using `WithArgs`, our original example can be written as: + +``` +using ::testing::_; +using ::testing::Invoke; +using ::testing::WithArgs; +... + EXPECT_CALL(mock, Foo(_, _, _, _, _, _, _)) + .WillOnce(WithArgs<0, 2, 3>(Invoke(IsVisibleInQuadrant1))); + // No need to define your own adaptor. +``` + +For better readability, Google Mock also gives you: + + * `WithoutArgs(action)` when the inner `action` takes _no_ argument, and + * `WithArg(action)` (no `s` after `Arg`) when the inner `action` takes _one_ argument. + +As you may have realized, `InvokeWithoutArgs(...)` is just syntactic +sugar for `WithoutArgs(Invoke(...))`. + +Here are more tips: + + * The inner action used in `WithArgs` and friends does not have to be `Invoke()` -- it can be anything. + * You can repeat an argument in the argument list if necessary, e.g. `WithArgs<2, 3, 3, 5>(...)`. + * You can change the order of the arguments, e.g. `WithArgs<3, 2, 1>(...)`. + * The types of the selected arguments do _not_ have to match the signature of the inner action exactly. It works as long as they can be implicitly converted to the corresponding arguments of the inner action. For example, if the 4-th argument of the mock function is an `int` and `my_action` takes a `double`, `WithArg<4>(my_action)` will work. + +## Ignoring Arguments in Action Functions ## + +The selecting-an-action's-arguments recipe showed us one way to make a +mock function and an action with incompatible argument lists fit +together. The downside is that wrapping the action in +`WithArgs<...>()` can get tedious for people writing the tests. + +If you are defining a function, method, or functor to be used with +`Invoke*()`, and you are not interested in some of its arguments, an +alternative to `WithArgs` is to declare the uninteresting arguments as +`Unused`. This makes the definition less cluttered and less fragile in +case the types of the uninteresting arguments change. It could also +increase the chance the action function can be reused. For example, +given + +``` + MOCK_METHOD3(Foo, double(const string& label, double x, double y)); + MOCK_METHOD3(Bar, double(int index, double x, double y)); +``` + +instead of + +``` +using ::testing::_; +using ::testing::Invoke; + +double DistanceToOriginWithLabel(const string& label, double x, double y) { + return sqrt(x*x + y*y); +} + +double DistanceToOriginWithIndex(int index, double x, double y) { + return sqrt(x*x + y*y); +} +... + + EXEPCT_CALL(mock, Foo("abc", _, _)) + .WillOnce(Invoke(DistanceToOriginWithLabel)); + EXEPCT_CALL(mock, Bar(5, _, _)) + .WillOnce(Invoke(DistanceToOriginWithIndex)); +``` + +you could write + +``` +using ::testing::_; +using ::testing::Invoke; +using ::testing::Unused; + +double DistanceToOrigin(Unused, double x, double y) { + return sqrt(x*x + y*y); +} +... + + EXEPCT_CALL(mock, Foo("abc", _, _)) + .WillOnce(Invoke(DistanceToOrigin)); + EXEPCT_CALL(mock, Bar(5, _, _)) + .WillOnce(Invoke(DistanceToOrigin)); +``` + +## Sharing Actions ## + +Just like matchers, a Google Mock action object consists of a pointer +to a ref-counted implementation object. Therefore copying actions is +also allowed and very efficient. When the last action that references +the implementation object dies, the implementation object will be +deleted. + +If you have some complex action that you want to use again and again, +you may not have to build it from scratch every time. If the action +doesn't have an internal state (i.e. if it always does the same thing +no matter how many times it has been called), you can assign it to an +action variable and use that variable repeatedly. For example: + +``` + Action set_flag = DoAll(SetArgPointee<0>(5), + Return(true)); + ... use set_flag in .WillOnce() and .WillRepeatedly() ... +``` + +However, if the action has its own state, you may be surprised if you +share the action object. Suppose you have an action factory +`IncrementCounter(init)` which creates an action that increments and +returns a counter whose initial value is `init`, using two actions +created from the same expression and using a shared action will +exihibit different behaviors. Example: + +``` + EXPECT_CALL(foo, DoThis()) + .WillRepeatedly(IncrementCounter(0)); + EXPECT_CALL(foo, DoThat()) + .WillRepeatedly(IncrementCounter(0)); + foo.DoThis(); // Returns 1. + foo.DoThis(); // Returns 2. + foo.DoThat(); // Returns 1 - Blah() uses a different + // counter than Bar()'s. +``` + +versus + +``` + Action increment = IncrementCounter(0); + + EXPECT_CALL(foo, DoThis()) + .WillRepeatedly(increment); + EXPECT_CALL(foo, DoThat()) + .WillRepeatedly(increment); + foo.DoThis(); // Returns 1. + foo.DoThis(); // Returns 2. + foo.DoThat(); // Returns 3 - the counter is shared. +``` + +# Misc Recipes on Using Google Mock # + +## Mocking Methods That Use Move-Only Types ## + +C++11 introduced *move-only types*. A move-only-typed value can be moved from +one object to another, but cannot be copied. `std::unique_ptr` is +probably the most commonly used move-only type. + +Mocking a method that takes and/or returns move-only types presents some +challenges, but nothing insurmountable. This recipe shows you how you can do it. +Note that the support for move-only method arguments was only introduced to +gMock in April 2017; in older code, you may find more complex +[workarounds](#LegacyMoveOnly) for lack of this feature. + +Let’s say we are working on a fictional project that lets one post and share +snippets called “buzzesâ€. Your code uses these types: + +```cpp +enum class AccessLevel { kInternal, kPublic }; + +class Buzz { + public: + explicit Buzz(AccessLevel access) { … } + ... +}; + +class Buzzer { + public: + virtual ~Buzzer() {} + virtual std::unique_ptr MakeBuzz(StringPiece text) = 0; + virtual bool ShareBuzz(std::unique_ptr buzz, int64_t timestamp) = 0; + ... +}; +``` + +A `Buzz` object represents a snippet being posted. A class that implements the +`Buzzer` interface is capable of creating and sharing `Buzz`es. Methods in +`Buzzer` may return a `unique_ptr` or take a +`unique_ptr`. Now we need to mock `Buzzer` in our tests. + +To mock a method that accepts or returns move-only types, you just use the +familiar `MOCK_METHOD` syntax as usual: + +```cpp +class MockBuzzer : public Buzzer { + public: + MOCK_METHOD1(MakeBuzz, std::unique_ptr(StringPiece text)); + MOCK_METHOD2(ShareBuzz, bool(std::unique_ptr buzz, int64_t timestamp)); +}; +``` + +Now that we have the mock class defined, we can use it in tests. In the +following code examples, we assume that we have defined a `MockBuzzer` object +named `mock_buzzer_`: + +```cpp + MockBuzzer mock_buzzer_; +``` + +First let’s see how we can set expectations on the `MakeBuzz()` method, which +returns a `unique_ptr`. + +As usual, if you set an expectation without an action (i.e. the `.WillOnce()` or +`.WillRepeated()` clause), when that expectation fires, the default action for +that method will be taken. Since `unique_ptr<>` has a default constructor +that returns a null `unique_ptr`, that’s what you’ll get if you don’t specify an +action: + +```cpp + // Use the default action. + EXPECT_CALL(mock_buzzer_, MakeBuzz("hello")); + + // Triggers the previous EXPECT_CALL. + EXPECT_EQ(nullptr, mock_buzzer_.MakeBuzz("hello")); +``` + +If you are not happy with the default action, you can tweak it as usual; see +[Setting Default Actions](#OnCall). + +If you just need to return a pre-defined move-only value, you can use the +`Return(ByMove(...))` action: + +```cpp + // When this fires, the unique_ptr<> specified by ByMove(...) will + // be returned. + EXPECT_CALL(mock_buzzer_, MakeBuzz("world")) + .WillOnce(Return(ByMove(MakeUnique(AccessLevel::kInternal)))); + + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("world")); +``` + +Note that `ByMove()` is essential here - if you drop it, the code won’t compile. + +Quiz time! What do you think will happen if a `Return(ByMove(...))` action is +performed more than once (e.g. you write +`….WillRepeatedly(Return(ByMove(...)));`)? Come think of it, after the first +time the action runs, the source value will be consumed (since it’s a move-only +value), so the next time around, there’s no value to move from -- you’ll get a +run-time error that `Return(ByMove(...))` can only be run once. + +If you need your mock method to do more than just moving a pre-defined value, +remember that you can always use a lambda or a callable object, which can do +pretty much anything you want: + +```cpp + EXPECT_CALL(mock_buzzer_, MakeBuzz("x")) + .WillRepeatedly([](StringPiece text) { + return MakeUnique(AccessLevel::kInternal); + }); + + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); + EXPECT_NE(nullptr, mock_buzzer_.MakeBuzz("x")); +``` + +Every time this `EXPECT_CALL` fires, a new `unique_ptr` will be +created and returned. You cannot do this with `Return(ByMove(...))`. + +That covers returning move-only values; but how do we work with methods +accepting move-only arguments? The answer is that they work normally, although +some actions will not compile when any of method's arguments are move-only. You +can always use `Return`, or a [lambda or functor](#FunctionsAsActions): + +```cpp + using ::testing::Unused; + + EXPECT_CALL(mock_buzzer_, ShareBuzz(NotNull(), _)) .WillOnce(Return(true)); + EXPECT_TRUE(mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal)), + 0); + + EXPECT_CALL(mock_buzzer_, ShareBuzz(_, _)) .WillOnce( + [](std::unique_ptr buzz, Unused) { return buzz != nullptr; }); + EXPECT_FALSE(mock_buzzer_.ShareBuzz(nullptr, 0)); +``` + +Many built-in actions (`WithArgs`, `WithoutArgs`,`DeleteArg`, `SaveArg`, ...) +could in principle support move-only arguments, but the support for this is not +implemented yet. If this is blocking you, please file a bug. + +A few actions (e.g. `DoAll`) copy their arguments internally, so they can never +work with non-copyable objects; you'll have to use functors instead. + +##### Legacy workarounds for move-only types {#LegacyMoveOnly} + +Support for move-only function arguments was only introduced to gMock in April +2017. In older code, you may encounter the following workaround for the lack of +this feature (it is no longer necessary - we're including it just for +reference): + +```cpp +class MockBuzzer : public Buzzer { + public: + MOCK_METHOD2(DoShareBuzz, bool(Buzz* buzz, Time timestamp)); + bool ShareBuzz(std::unique_ptr buzz, Time timestamp) override { + return DoShareBuzz(buzz.get(), timestamp); + } +}; +``` + +The trick is to delegate the `ShareBuzz()` method to a mock method (let’s call +it `DoShareBuzz()`) that does not take move-only parameters. Then, instead of +setting expectations on `ShareBuzz()`, you set them on the `DoShareBuzz()` mock +method: + +```cpp + MockBuzzer mock_buzzer_; + EXPECT_CALL(mock_buzzer_, DoShareBuzz(NotNull(), _)); + + // When one calls ShareBuzz() on the MockBuzzer like this, the call is + // forwarded to DoShareBuzz(), which is mocked. Therefore this statement + // will trigger the above EXPECT_CALL. + mock_buzzer_.ShareBuzz(MakeUnique(AccessLevel::kInternal), 0); +``` + + + +## Making the Compilation Faster ## + +Believe it or not, the _vast majority_ of the time spent on compiling +a mock class is in generating its constructor and destructor, as they +perform non-trivial tasks (e.g. verification of the +expectations). What's more, mock methods with different signatures +have different types and thus their constructors/destructors need to +be generated by the compiler separately. As a result, if you mock many +different types of methods, compiling your mock class can get really +slow. + +If you are experiencing slow compilation, you can move the definition +of your mock class' constructor and destructor out of the class body +and into a `.cpp` file. This way, even if you `#include` your mock +class in N files, the compiler only needs to generate its constructor +and destructor once, resulting in a much faster compilation. + +Let's illustrate the idea using an example. Here's the definition of a +mock class before applying this recipe: + +``` +// File mock_foo.h. +... +class MockFoo : public Foo { + public: + // Since we don't declare the constructor or the destructor, + // the compiler will generate them in every translation unit + // where this mock class is used. + + MOCK_METHOD0(DoThis, int()); + MOCK_METHOD1(DoThat, bool(const char* str)); + ... more mock methods ... +}; +``` + +After the change, it would look like: + +``` +// File mock_foo.h. +... +class MockFoo : public Foo { + public: + // The constructor and destructor are declared, but not defined, here. + MockFoo(); + virtual ~MockFoo(); + + MOCK_METHOD0(DoThis, int()); + MOCK_METHOD1(DoThat, bool(const char* str)); + ... more mock methods ... +}; +``` +and +``` +// File mock_foo.cpp. +#include "path/to/mock_foo.h" + +// The definitions may appear trivial, but the functions actually do a +// lot of things through the constructors/destructors of the member +// variables used to implement the mock methods. +MockFoo::MockFoo() {} +MockFoo::~MockFoo() {} +``` + +## Forcing a Verification ## + +When it's being destroyed, your friendly mock object will automatically +verify that all expectations on it have been satisfied, and will +generate [Google Test](../../googletest/) failures +if not. This is convenient as it leaves you with one less thing to +worry about. That is, unless you are not sure if your mock object will +be destroyed. + +How could it be that your mock object won't eventually be destroyed? +Well, it might be created on the heap and owned by the code you are +testing. Suppose there's a bug in that code and it doesn't delete the +mock object properly - you could end up with a passing test when +there's actually a bug. + +Using a heap checker is a good idea and can alleviate the concern, but +its implementation may not be 100% reliable. So, sometimes you do want +to _force_ Google Mock to verify a mock object before it is +(hopefully) destructed. You can do this with +`Mock::VerifyAndClearExpectations(&mock_object)`: + +``` +TEST(MyServerTest, ProcessesRequest) { + using ::testing::Mock; + + MockFoo* const foo = new MockFoo; + EXPECT_CALL(*foo, ...)...; + // ... other expectations ... + + // server now owns foo. + MyServer server(foo); + server.ProcessRequest(...); + + // In case that server's destructor will forget to delete foo, + // this will verify the expectations anyway. + Mock::VerifyAndClearExpectations(foo); +} // server is destroyed when it goes out of scope here. +``` + +**Tip:** The `Mock::VerifyAndClearExpectations()` function returns a +`bool` to indicate whether the verification was successful (`true` for +yes), so you can wrap that function call inside a `ASSERT_TRUE()` if +there is no point going further when the verification has failed. + +## Using Check Points ## + +Sometimes you may want to "reset" a mock object at various check +points in your test: at each check point, you verify that all existing +expectations on the mock object have been satisfied, and then you set +some new expectations on it as if it's newly created. This allows you +to work with a mock object in "phases" whose sizes are each +manageable. + +One such scenario is that in your test's `SetUp()` function, you may +want to put the object you are testing into a certain state, with the +help from a mock object. Once in the desired state, you want to clear +all expectations on the mock, such that in the `TEST_F` body you can +set fresh expectations on it. + +As you may have figured out, the `Mock::VerifyAndClearExpectations()` +function we saw in the previous recipe can help you here. Or, if you +are using `ON_CALL()` to set default actions on the mock object and +want to clear the default actions as well, use +`Mock::VerifyAndClear(&mock_object)` instead. This function does what +`Mock::VerifyAndClearExpectations(&mock_object)` does and returns the +same `bool`, **plus** it clears the `ON_CALL()` statements on +`mock_object` too. + +Another trick you can use to achieve the same effect is to put the +expectations in sequences and insert calls to a dummy "check-point" +function at specific places. Then you can verify that the mock +function calls do happen at the right time. For example, if you are +exercising code: + +``` +Foo(1); +Foo(2); +Foo(3); +``` + +and want to verify that `Foo(1)` and `Foo(3)` both invoke +`mock.Bar("a")`, but `Foo(2)` doesn't invoke anything. You can write: + +``` +using ::testing::MockFunction; + +TEST(FooTest, InvokesBarCorrectly) { + MyMock mock; + // Class MockFunction has exactly one mock method. It is named + // Call() and has type F. + MockFunction check; + { + InSequence s; + + EXPECT_CALL(mock, Bar("a")); + EXPECT_CALL(check, Call("1")); + EXPECT_CALL(check, Call("2")); + EXPECT_CALL(mock, Bar("a")); + } + Foo(1); + check.Call("1"); + Foo(2); + check.Call("2"); + Foo(3); +} +``` + +The expectation spec says that the first `Bar("a")` must happen before +check point "1", the second `Bar("a")` must happen after check point "2", +and nothing should happen between the two check points. The explicit +check points make it easy to tell which `Bar("a")` is called by which +call to `Foo()`. + +## Mocking Destructors ## + +Sometimes you want to make sure a mock object is destructed at the +right time, e.g. after `bar->A()` is called but before `bar->B()` is +called. We already know that you can specify constraints on the order +of mock function calls, so all we need to do is to mock the destructor +of the mock function. + +This sounds simple, except for one problem: a destructor is a special +function with special syntax and special semantics, and the +`MOCK_METHOD0` macro doesn't work for it: + +``` + MOCK_METHOD0(~MockFoo, void()); // Won't compile! +``` + +The good news is that you can use a simple pattern to achieve the same +effect. First, add a mock function `Die()` to your mock class and call +it in the destructor, like this: + +``` +class MockFoo : public Foo { + ... + // Add the following two lines to the mock class. + MOCK_METHOD0(Die, void()); + virtual ~MockFoo() { Die(); } +}; +``` + +(If the name `Die()` clashes with an existing symbol, choose another +name.) Now, we have translated the problem of testing when a `MockFoo` +object dies to testing when its `Die()` method is called: + +``` + MockFoo* foo = new MockFoo; + MockBar* bar = new MockBar; + ... + { + InSequence s; + + // Expects *foo to die after bar->A() and before bar->B(). + EXPECT_CALL(*bar, A()); + EXPECT_CALL(*foo, Die()); + EXPECT_CALL(*bar, B()); + } +``` + +And that's that. + +## Using Google Mock and Threads ## + +**IMPORTANT NOTE:** What we describe in this recipe is **ONLY** true on +platforms where Google Mock is thread-safe. Currently these are only +platforms that support the pthreads library (this includes Linux and Mac). +To make it thread-safe on other platforms we only need to implement +some synchronization operations in `"gtest/internal/gtest-port.h"`. + +In a **unit** test, it's best if you could isolate and test a piece of +code in a single-threaded context. That avoids race conditions and +dead locks, and makes debugging your test much easier. + +Yet many programs are multi-threaded, and sometimes to test something +we need to pound on it from more than one thread. Google Mock works +for this purpose too. + +Remember the steps for using a mock: + + 1. Create a mock object `foo`. + 1. Set its default actions and expectations using `ON_CALL()` and `EXPECT_CALL()`. + 1. The code under test calls methods of `foo`. + 1. Optionally, verify and reset the mock. + 1. Destroy the mock yourself, or let the code under test destroy it. The destructor will automatically verify it. + +If you follow the following simple rules, your mocks and threads can +live happily together: + + * Execute your _test code_ (as opposed to the code being tested) in _one_ thread. This makes your test easy to follow. + * Obviously, you can do step #1 without locking. + * When doing step #2 and #5, make sure no other thread is accessing `foo`. Obvious too, huh? + * #3 and #4 can be done either in one thread or in multiple threads - anyway you want. Google Mock takes care of the locking, so you don't have to do any - unless required by your test logic. + +If you violate the rules (for example, if you set expectations on a +mock while another thread is calling its methods), you get undefined +behavior. That's not fun, so don't do it. + +Google Mock guarantees that the action for a mock function is done in +the same thread that called the mock function. For example, in + +``` + EXPECT_CALL(mock, Foo(1)) + .WillOnce(action1); + EXPECT_CALL(mock, Foo(2)) + .WillOnce(action2); +``` + +if `Foo(1)` is called in thread 1 and `Foo(2)` is called in thread 2, +Google Mock will execute `action1` in thread 1 and `action2` in thread +2. + +Google Mock does _not_ impose a sequence on actions performed in +different threads (doing so may create deadlocks as the actions may +need to cooperate). This means that the execution of `action1` and +`action2` in the above example _may_ interleave. If this is a problem, +you should add proper synchronization logic to `action1` and `action2` +to make the test thread-safe. + + +Also, remember that `DefaultValue` is a global resource that +potentially affects _all_ living mock objects in your +program. Naturally, you won't want to mess with it from multiple +threads or when there still are mocks in action. + +## Controlling How Much Information Google Mock Prints ## + +When Google Mock sees something that has the potential of being an +error (e.g. a mock function with no expectation is called, a.k.a. an +uninteresting call, which is allowed but perhaps you forgot to +explicitly ban the call), it prints some warning messages, including +the arguments of the function and the return value. Hopefully this +will remind you to take a look and see if there is indeed a problem. + +Sometimes you are confident that your tests are correct and may not +appreciate such friendly messages. Some other times, you are debugging +your tests or learning about the behavior of the code you are testing, +and wish you could observe every mock call that happens (including +argument values and the return value). Clearly, one size doesn't fit +all. + +You can control how much Google Mock tells you using the +`--gmock_verbose=LEVEL` command-line flag, where `LEVEL` is a string +with three possible values: + + * `info`: Google Mock will print all informational messages, warnings, and errors (most verbose). At this setting, Google Mock will also log any calls to the `ON_CALL/EXPECT_CALL` macros. + * `warning`: Google Mock will print both warnings and errors (less verbose). This is the default. + * `error`: Google Mock will print errors only (least verbose). + +Alternatively, you can adjust the value of that flag from within your +tests like so: + +``` + ::testing::FLAGS_gmock_verbose = "error"; +``` + +Now, judiciously use the right flag to enable Google Mock serve you better! + +## Gaining Super Vision into Mock Calls ## + +You have a test using Google Mock. It fails: Google Mock tells you +that some expectations aren't satisfied. However, you aren't sure why: +Is there a typo somewhere in the matchers? Did you mess up the order +of the `EXPECT_CALL`s? Or is the code under test doing something +wrong? How can you find out the cause? + +Won't it be nice if you have X-ray vision and can actually see the +trace of all `EXPECT_CALL`s and mock method calls as they are made? +For each call, would you like to see its actual argument values and +which `EXPECT_CALL` Google Mock thinks it matches? + +You can unlock this power by running your test with the +`--gmock_verbose=info` flag. For example, given the test program: + +``` +using testing::_; +using testing::HasSubstr; +using testing::Return; + +class MockFoo { + public: + MOCK_METHOD2(F, void(const string& x, const string& y)); +}; + +TEST(Foo, Bar) { + MockFoo mock; + EXPECT_CALL(mock, F(_, _)).WillRepeatedly(Return()); + EXPECT_CALL(mock, F("a", "b")); + EXPECT_CALL(mock, F("c", HasSubstr("d"))); + + mock.F("a", "good"); + mock.F("a", "b"); +} +``` + +if you run it with `--gmock_verbose=info`, you will see this output: + +``` +[ RUN ] Foo.Bar + +foo_test.cc:14: EXPECT_CALL(mock, F(_, _)) invoked +foo_test.cc:15: EXPECT_CALL(mock, F("a", "b")) invoked +foo_test.cc:16: EXPECT_CALL(mock, F("c", HasSubstr("d"))) invoked +foo_test.cc:14: Mock function call matches EXPECT_CALL(mock, F(_, _))... + Function call: F(@0x7fff7c8dad40"a", @0x7fff7c8dad10"good") +foo_test.cc:15: Mock function call matches EXPECT_CALL(mock, F("a", "b"))... + Function call: F(@0x7fff7c8dada0"a", @0x7fff7c8dad70"b") +foo_test.cc:16: Failure +Actual function call count doesn't match EXPECT_CALL(mock, F("c", HasSubstr("d")))... + Expected: to be called once + Actual: never called - unsatisfied and active +[ FAILED ] Foo.Bar +``` + +Suppose the bug is that the `"c"` in the third `EXPECT_CALL` is a typo +and should actually be `"a"`. With the above message, you should see +that the actual `F("a", "good")` call is matched by the first +`EXPECT_CALL`, not the third as you thought. From that it should be +obvious that the third `EXPECT_CALL` is written wrong. Case solved. + +## Running Tests in Emacs ## + +If you build and run your tests in Emacs, the source file locations of +Google Mock and [Google Test](../../googletest/) +errors will be highlighted. Just press `` on one of them and +you'll be taken to the offending line. Or, you can just type `C-x `` +to jump to the next error. + +To make it even easier, you can add the following lines to your +`~/.emacs` file: + +``` +(global-set-key "\M-m" 'compile) ; m is for make +(global-set-key [M-down] 'next-error) +(global-set-key [M-up] '(lambda () (interactive) (next-error -1))) +``` + +Then you can type `M-m` to start a build, or `M-up`/`M-down` to move +back and forth between errors. + +## Fusing Google Mock Source Files ## + +Google Mock's implementation consists of dozens of files (excluding +its own tests). Sometimes you may want them to be packaged up in +fewer files instead, such that you can easily copy them to a new +machine and start hacking there. For this we provide an experimental +Python script `fuse_gmock_files.py` in the `scripts/` directory +(starting with release 1.2.0). Assuming you have Python 2.4 or above +installed on your machine, just go to that directory and run +``` +python fuse_gmock_files.py OUTPUT_DIR +``` + +and you should see an `OUTPUT_DIR` directory being created with files +`gtest/gtest.h`, `gmock/gmock.h`, and `gmock-gtest-all.cc` in it. +These three files contain everything you need to use Google Mock (and +Google Test). Just copy them to anywhere you want and you are ready +to write tests and use mocks. You can use the +[scrpts/test/Makefile](../scripts/test/Makefile) file as an example on how to compile your tests +against them. + +# Extending Google Mock # + +## Writing New Matchers Quickly ## + +The `MATCHER*` family of macros can be used to define custom matchers +easily. The syntax: + +``` +MATCHER(name, description_string_expression) { statements; } +``` + +will define a matcher with the given name that executes the +statements, which must return a `bool` to indicate if the match +succeeds. Inside the statements, you can refer to the value being +matched by `arg`, and refer to its type by `arg_type`. + +The description string is a `string`-typed expression that documents +what the matcher does, and is used to generate the failure message +when the match fails. It can (and should) reference the special +`bool` variable `negation`, and should evaluate to the description of +the matcher when `negation` is `false`, or that of the matcher's +negation when `negation` is `true`. + +For convenience, we allow the description string to be empty (`""`), +in which case Google Mock will use the sequence of words in the +matcher name as the description. + +For example: +``` +MATCHER(IsDivisibleBy7, "") { return (arg % 7) == 0; } +``` +allows you to write +``` + // Expects mock_foo.Bar(n) to be called where n is divisible by 7. + EXPECT_CALL(mock_foo, Bar(IsDivisibleBy7())); +``` +or, +``` +using ::testing::Not; +... + EXPECT_THAT(some_expression, IsDivisibleBy7()); + EXPECT_THAT(some_other_expression, Not(IsDivisibleBy7())); +``` +If the above assertions fail, they will print something like: +``` + Value of: some_expression + Expected: is divisible by 7 + Actual: 27 +... + Value of: some_other_expression + Expected: not (is divisible by 7) + Actual: 21 +``` +where the descriptions `"is divisible by 7"` and `"not (is divisible +by 7)"` are automatically calculated from the matcher name +`IsDivisibleBy7`. + +As you may have noticed, the auto-generated descriptions (especially +those for the negation) may not be so great. You can always override +them with a string expression of your own: +``` +MATCHER(IsDivisibleBy7, std::string(negation ? "isn't" : "is") + + " divisible by 7") { + return (arg % 7) == 0; +} +``` + +Optionally, you can stream additional information to a hidden argument +named `result_listener` to explain the match result. For example, a +better definition of `IsDivisibleBy7` is: +``` +MATCHER(IsDivisibleBy7, "") { + if ((arg % 7) == 0) + return true; + + *result_listener << "the remainder is " << (arg % 7); + return false; +} +``` + +With this definition, the above assertion will give a better message: +``` + Value of: some_expression + Expected: is divisible by 7 + Actual: 27 (the remainder is 6) +``` + +You should let `MatchAndExplain()` print _any additional information_ +that can help a user understand the match result. Note that it should +explain why the match succeeds in case of a success (unless it's +obvious) - this is useful when the matcher is used inside +`Not()`. There is no need to print the argument value itself, as +Google Mock already prints it for you. + +**Notes:** + + 1. The type of the value being matched (`arg_type`) is determined by the context in which you use the matcher and is supplied to you by the compiler, so you don't need to worry about declaring it (nor can you). This allows the matcher to be polymorphic. For example, `IsDivisibleBy7()` can be used to match any type where the value of `(arg % 7) == 0` can be implicitly converted to a `bool`. In the `Bar(IsDivisibleBy7())` example above, if method `Bar()` takes an `int`, `arg_type` will be `int`; if it takes an `unsigned long`, `arg_type` will be `unsigned long`; and so on. + 1. Google Mock doesn't guarantee when or how many times a matcher will be invoked. Therefore the matcher logic must be _purely functional_ (i.e. it cannot have any side effect, and the result must not depend on anything other than the value being matched and the matcher parameters). This requirement must be satisfied no matter how you define the matcher (e.g. using one of the methods described in the following recipes). In particular, a matcher can never call a mock function, as that will affect the state of the mock object and Google Mock. + +## Writing New Parameterized Matchers Quickly ## + +Sometimes you'll want to define a matcher that has parameters. For that you +can use the macro: +``` +MATCHER_P(name, param_name, description_string) { statements; } +``` +where the description string can be either `""` or a string expression +that references `negation` and `param_name`. + +For example: +``` +MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +``` +will allow you to write: +``` + EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +``` +which may lead to this message (assuming `n` is 10): +``` + Value of: Blah("a") + Expected: has absolute value 10 + Actual: -9 +``` + +Note that both the matcher description and its parameter are +printed, making the message human-friendly. + +In the matcher definition body, you can write `foo_type` to +reference the type of a parameter named `foo`. For example, in the +body of `MATCHER_P(HasAbsoluteValue, value)` above, you can write +`value_type` to refer to the type of `value`. + +Google Mock also provides `MATCHER_P2`, `MATCHER_P3`, ..., up to +`MATCHER_P10` to support multi-parameter matchers: +``` +MATCHER_Pk(name, param_1, ..., param_k, description_string) { statements; } +``` + +Please note that the custom description string is for a particular +**instance** of the matcher, where the parameters have been bound to +actual values. Therefore usually you'll want the parameter values to +be part of the description. Google Mock lets you do that by +referencing the matcher parameters in the description string +expression. + +For example, +``` + using ::testing::PrintToString; + MATCHER_P2(InClosedRange, low, hi, + std::string(negation ? "isn't" : "is") + " in range [" + + PrintToString(low) + ", " + PrintToString(hi) + "]") { + return low <= arg && arg <= hi; + } + ... + EXPECT_THAT(3, InClosedRange(4, 6)); +``` +would generate a failure that contains the message: +``` + Expected: is in range [4, 6] +``` + +If you specify `""` as the description, the failure message will +contain the sequence of words in the matcher name followed by the +parameter values printed as a tuple. For example, +``` + MATCHER_P2(InClosedRange, low, hi, "") { ... } + ... + EXPECT_THAT(3, InClosedRange(4, 6)); +``` +would generate a failure that contains the text: +``` + Expected: in closed range (4, 6) +``` + +For the purpose of typing, you can view +``` +MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +``` +as shorthand for +``` +template +FooMatcherPk +Foo(p1_type p1, ..., pk_type pk) { ... } +``` + +When you write `Foo(v1, ..., vk)`, the compiler infers the types of +the parameters `v1`, ..., and `vk` for you. If you are not happy with +the result of the type inference, you can specify the types by +explicitly instantiating the template, as in `Foo(5, false)`. +As said earlier, you don't get to (or need to) specify +`arg_type` as that's determined by the context in which the matcher +is used. + +You can assign the result of expression `Foo(p1, ..., pk)` to a +variable of type `FooMatcherPk`. This can be +useful when composing matchers. Matchers that don't have a parameter +or have only one parameter have special types: you can assign `Foo()` +to a `FooMatcher`-typed variable, and assign `Foo(p)` to a +`FooMatcherP`-typed variable. + +While you can instantiate a matcher template with reference types, +passing the parameters by pointer usually makes your code more +readable. If, however, you still want to pass a parameter by +reference, be aware that in the failure message generated by the +matcher you will see the value of the referenced object but not its +address. + +You can overload matchers with different numbers of parameters: +``` +MATCHER_P(Blah, a, description_string_1) { ... } +MATCHER_P2(Blah, a, b, description_string_2) { ... } +``` + +While it's tempting to always use the `MATCHER*` macros when defining +a new matcher, you should also consider implementing +`MatcherInterface` or using `MakePolymorphicMatcher()` instead (see +the recipes that follow), especially if you need to use the matcher a +lot. While these approaches require more work, they give you more +control on the types of the value being matched and the matcher +parameters, which in general leads to better compiler error messages +that pay off in the long run. They also allow overloading matchers +based on parameter types (as opposed to just based on the number of +parameters). + +## Writing New Monomorphic Matchers ## + +A matcher of argument type `T` implements +`::testing::MatcherInterface` and does two things: it tests whether a +value of type `T` matches the matcher, and can describe what kind of +values it matches. The latter ability is used for generating readable +error messages when expectations are violated. + +The interface looks like this: + +``` +class MatchResultListener { + public: + ... + // Streams x to the underlying ostream; does nothing if the ostream + // is NULL. + template + MatchResultListener& operator<<(const T& x); + + // Returns the underlying ostream. + ::std::ostream* stream(); +}; + +template +class MatcherInterface { + public: + virtual ~MatcherInterface(); + + // Returns true iff the matcher matches x; also explains the match + // result to 'listener'. + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; + + // Describes this matcher to an ostream. + virtual void DescribeTo(::std::ostream* os) const = 0; + + // Describes the negation of this matcher to an ostream. + virtual void DescribeNegationTo(::std::ostream* os) const; +}; +``` + +If you need a custom matcher but `Truly()` is not a good option (for +example, you may not be happy with the way `Truly(predicate)` +describes itself, or you may want your matcher to be polymorphic as +`Eq(value)` is), you can define a matcher to do whatever you want in +two steps: first implement the matcher interface, and then define a +factory function to create a matcher instance. The second step is not +strictly needed but it makes the syntax of using the matcher nicer. + +For example, you can define a matcher to test whether an `int` is +divisible by 7 and then use it like this: +``` +using ::testing::MakeMatcher; +using ::testing::Matcher; +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; + +class DivisibleBy7Matcher : public MatcherInterface { + public: + virtual bool MatchAndExplain(int n, MatchResultListener* listener) const { + return (n % 7) == 0; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "is divisible by 7"; + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "is not divisible by 7"; + } +}; + +inline Matcher DivisibleBy7() { + return MakeMatcher(new DivisibleBy7Matcher); +} +... + + EXPECT_CALL(foo, Bar(DivisibleBy7())); +``` + +You may improve the matcher message by streaming additional +information to the `listener` argument in `MatchAndExplain()`: + +``` +class DivisibleBy7Matcher : public MatcherInterface { + public: + virtual bool MatchAndExplain(int n, + MatchResultListener* listener) const { + const int remainder = n % 7; + if (remainder != 0) { + *listener << "the remainder is " << remainder; + } + return remainder == 0; + } + ... +}; +``` + +Then, `EXPECT_THAT(x, DivisibleBy7());` may general a message like this: +``` +Value of: x +Expected: is divisible by 7 + Actual: 23 (the remainder is 2) +``` + +## Writing New Polymorphic Matchers ## + +You've learned how to write your own matchers in the previous +recipe. Just one problem: a matcher created using `MakeMatcher()` only +works for one particular type of arguments. If you want a +_polymorphic_ matcher that works with arguments of several types (for +instance, `Eq(x)` can be used to match a `value` as long as `value` == +`x` compiles -- `value` and `x` don't have to share the same type), +you can learn the trick from `"gmock/gmock-matchers.h"` but it's a bit +involved. + +Fortunately, most of the time you can define a polymorphic matcher +easily with the help of `MakePolymorphicMatcher()`. Here's how you can +define `NotNull()` as an example: + +``` +using ::testing::MakePolymorphicMatcher; +using ::testing::MatchResultListener; +using ::testing::NotNull; +using ::testing::PolymorphicMatcher; + +class NotNullMatcher { + public: + // To implement a polymorphic matcher, first define a COPYABLE class + // that has three members MatchAndExplain(), DescribeTo(), and + // DescribeNegationTo(), like the following. + + // In this example, we want to use NotNull() with any pointer, so + // MatchAndExplain() accepts a pointer of any type as its first argument. + // In general, you can define MatchAndExplain() as an ordinary method or + // a method template, or even overload it. + template + bool MatchAndExplain(T* p, + MatchResultListener* /* listener */) const { + return p != NULL; + } + + // Describes the property of a value matching this matcher. + void DescribeTo(::std::ostream* os) const { *os << "is not NULL"; } + + // Describes the property of a value NOT matching this matcher. + void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; } +}; + +// To construct a polymorphic matcher, pass an instance of the class +// to MakePolymorphicMatcher(). Note the return type. +inline PolymorphicMatcher NotNull() { + return MakePolymorphicMatcher(NotNullMatcher()); +} +... + + EXPECT_CALL(foo, Bar(NotNull())); // The argument must be a non-NULL pointer. +``` + +**Note:** Your polymorphic matcher class does **not** need to inherit from +`MatcherInterface` or any other class, and its methods do **not** need +to be virtual. + +Like in a monomorphic matcher, you may explain the match result by +streaming additional information to the `listener` argument in +`MatchAndExplain()`. + +## Writing New Cardinalities ## + +A cardinality is used in `Times()` to tell Google Mock how many times +you expect a call to occur. It doesn't have to be exact. For example, +you can say `AtLeast(5)` or `Between(2, 4)`. + +If the built-in set of cardinalities doesn't suit you, you are free to +define your own by implementing the following interface (in namespace +`testing`): + +``` +class CardinalityInterface { + public: + virtual ~CardinalityInterface(); + + // Returns true iff call_count calls will satisfy this cardinality. + virtual bool IsSatisfiedByCallCount(int call_count) const = 0; + + // Returns true iff call_count calls will saturate this cardinality. + virtual bool IsSaturatedByCallCount(int call_count) const = 0; + + // Describes self to an ostream. + virtual void DescribeTo(::std::ostream* os) const = 0; +}; +``` + +For example, to specify that a call must occur even number of times, +you can write + +``` +using ::testing::Cardinality; +using ::testing::CardinalityInterface; +using ::testing::MakeCardinality; + +class EvenNumberCardinality : public CardinalityInterface { + public: + virtual bool IsSatisfiedByCallCount(int call_count) const { + return (call_count % 2) == 0; + } + + virtual bool IsSaturatedByCallCount(int call_count) const { + return false; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "called even number of times"; + } +}; + +Cardinality EvenNumber() { + return MakeCardinality(new EvenNumberCardinality); +} +... + + EXPECT_CALL(foo, Bar(3)) + .Times(EvenNumber()); +``` + +## Writing New Actions Quickly ## + +If the built-in actions don't work for you, and you find it +inconvenient to use `Invoke()`, you can use a macro from the `ACTION*` +family to quickly define a new action that can be used in your code as +if it's a built-in action. + +By writing +``` +ACTION(name) { statements; } +``` +in a namespace scope (i.e. not inside a class or function), you will +define an action with the given name that executes the statements. +The value returned by `statements` will be used as the return value of +the action. Inside the statements, you can refer to the K-th +(0-based) argument of the mock function as `argK`. For example: +``` +ACTION(IncrementArg1) { return ++(*arg1); } +``` +allows you to write +``` +... WillOnce(IncrementArg1()); +``` + +Note that you don't need to specify the types of the mock function +arguments. Rest assured that your code is type-safe though: +you'll get a compiler error if `*arg1` doesn't support the `++` +operator, or if the type of `++(*arg1)` isn't compatible with the mock +function's return type. + +Another example: +``` +ACTION(Foo) { + (*arg2)(5); + Blah(); + *arg1 = 0; + return arg0; +} +``` +defines an action `Foo()` that invokes argument #2 (a function pointer) +with 5, calls function `Blah()`, sets the value pointed to by argument +#1 to 0, and returns argument #0. + +For more convenience and flexibility, you can also use the following +pre-defined symbols in the body of `ACTION`: + +| `argK_type` | The type of the K-th (0-based) argument of the mock function | +|:------------|:-------------------------------------------------------------| +| `args` | All arguments of the mock function as a tuple | +| `args_type` | The type of all arguments of the mock function as a tuple | +| `return_type` | The return type of the mock function | +| `function_type` | The type of the mock function | + +For example, when using an `ACTION` as a stub action for mock function: +``` +int DoSomething(bool flag, int* ptr); +``` +we have: + +| **Pre-defined Symbol** | **Is Bound To** | +|:-----------------------|:----------------| +| `arg0` | the value of `flag` | +| `arg0_type` | the type `bool` | +| `arg1` | the value of `ptr` | +| `arg1_type` | the type `int*` | +| `args` | the tuple `(flag, ptr)` | +| `args_type` | the type `::testing::tuple` | +| `return_type` | the type `int` | +| `function_type` | the type `int(bool, int*)` | + +## Writing New Parameterized Actions Quickly ## + +Sometimes you'll want to parameterize an action you define. For that +we have another macro +``` +ACTION_P(name, param) { statements; } +``` + +For example, +``` +ACTION_P(Add, n) { return arg0 + n; } +``` +will allow you to write +``` +// Returns argument #0 + 5. +... WillOnce(Add(5)); +``` + +For convenience, we use the term _arguments_ for the values used to +invoke the mock function, and the term _parameters_ for the values +used to instantiate an action. + +Note that you don't need to provide the type of the parameter either. +Suppose the parameter is named `param`, you can also use the +Google-Mock-defined symbol `param_type` to refer to the type of the +parameter as inferred by the compiler. For example, in the body of +`ACTION_P(Add, n)` above, you can write `n_type` for the type of `n`. + +Google Mock also provides `ACTION_P2`, `ACTION_P3`, and etc to support +multi-parameter actions. For example, +``` +ACTION_P2(ReturnDistanceTo, x, y) { + double dx = arg0 - x; + double dy = arg1 - y; + return sqrt(dx*dx + dy*dy); +} +``` +lets you write +``` +... WillOnce(ReturnDistanceTo(5.0, 26.5)); +``` + +You can view `ACTION` as a degenerated parameterized action where the +number of parameters is 0. + +You can also easily define actions overloaded on the number of parameters: +``` +ACTION_P(Plus, a) { ... } +ACTION_P2(Plus, a, b) { ... } +``` + +## Restricting the Type of an Argument or Parameter in an ACTION ## + +For maximum brevity and reusability, the `ACTION*` macros don't ask +you to provide the types of the mock function arguments and the action +parameters. Instead, we let the compiler infer the types for us. + +Sometimes, however, we may want to be more explicit about the types. +There are several tricks to do that. For example: +``` +ACTION(Foo) { + // Makes sure arg0 can be converted to int. + int n = arg0; + ... use n instead of arg0 here ... +} + +ACTION_P(Bar, param) { + // Makes sure the type of arg1 is const char*. + ::testing::StaticAssertTypeEq(); + + // Makes sure param can be converted to bool. + bool flag = param; +} +``` +where `StaticAssertTypeEq` is a compile-time assertion in Google Test +that verifies two types are the same. + +## Writing New Action Templates Quickly ## + +Sometimes you want to give an action explicit template parameters that +cannot be inferred from its value parameters. `ACTION_TEMPLATE()` +supports that and can be viewed as an extension to `ACTION()` and +`ACTION_P*()`. + +The syntax: +``` +ACTION_TEMPLATE(ActionName, + HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), + AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } +``` + +defines an action template that takes _m_ explicit template parameters +and _n_ value parameters, where _m_ is between 1 and 10, and _n_ is +between 0 and 10. `name_i` is the name of the i-th template +parameter, and `kind_i` specifies whether it's a `typename`, an +integral constant, or a template. `p_i` is the name of the i-th value +parameter. + +Example: +``` +// DuplicateArg(output) converts the k-th argument of the mock +// function to type T and copies it to *output. +ACTION_TEMPLATE(DuplicateArg, + // Note the comma between int and k: + HAS_2_TEMPLATE_PARAMS(int, k, typename, T), + AND_1_VALUE_PARAMS(output)) { + *output = T(::testing::get(args)); +} +``` + +To create an instance of an action template, write: +``` + ActionName(v1, ..., v_n) +``` +where the `t`s are the template arguments and the +`v`s are the value arguments. The value argument +types are inferred by the compiler. For example: +``` +using ::testing::_; +... + int n; + EXPECT_CALL(mock, Foo(_, _)) + .WillOnce(DuplicateArg<1, unsigned char>(&n)); +``` + +If you want to explicitly specify the value argument types, you can +provide additional template arguments: +``` + ActionName(v1, ..., v_n) +``` +where `u_i` is the desired type of `v_i`. + +`ACTION_TEMPLATE` and `ACTION`/`ACTION_P*` can be overloaded on the +number of value parameters, but not on the number of template +parameters. Without the restriction, the meaning of the following is +unclear: + +``` + OverloadedAction(x); +``` + +Are we using a single-template-parameter action where `bool` refers to +the type of `x`, or a two-template-parameter action where the compiler +is asked to infer the type of `x`? + +## Using the ACTION Object's Type ## + +If you are writing a function that returns an `ACTION` object, you'll +need to know its type. The type depends on the macro used to define +the action and the parameter types. The rule is relatively simple: + +| **Given Definition** | **Expression** | **Has Type** | +|:---------------------|:---------------|:-------------| +| `ACTION(Foo)` | `Foo()` | `FooAction` | +| `ACTION_TEMPLATE(Foo, HAS_m_TEMPLATE_PARAMS(...), AND_0_VALUE_PARAMS())` | `Foo()` | `FooAction` | +| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP` | +| `ACTION_TEMPLATE(Bar, HAS_m_TEMPLATE_PARAMS(...), AND_1_VALUE_PARAMS(p1))` | `Bar(int_value)` | `FooActionP` | +| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2` | +| `ACTION_TEMPLATE(Baz, HAS_m_TEMPLATE_PARAMS(...), AND_2_VALUE_PARAMS(p1, p2))`| `Baz(bool_value, int_value)` | `FooActionP2` | +| ... | ... | ... | + +Note that we have to pick different suffixes (`Action`, `ActionP`, +`ActionP2`, and etc) for actions with different numbers of value +parameters, or the action definitions cannot be overloaded on the +number of them. + +## Writing New Monomorphic Actions ## + +While the `ACTION*` macros are very convenient, sometimes they are +inappropriate. For example, despite the tricks shown in the previous +recipes, they don't let you directly specify the types of the mock +function arguments and the action parameters, which in general leads +to unoptimized compiler error messages that can baffle unfamiliar +users. They also don't allow overloading actions based on parameter +types without jumping through some hoops. + +An alternative to the `ACTION*` macros is to implement +`::testing::ActionInterface`, where `F` is the type of the mock +function in which the action will be used. For example: + +``` +template class ActionInterface { + public: + virtual ~ActionInterface(); + + // Performs the action. Result is the return type of function type + // F, and ArgumentTuple is the tuple of arguments of F. + // + // For example, if F is int(bool, const string&), then Result would + // be int, and ArgumentTuple would be ::testing::tuple. + virtual Result Perform(const ArgumentTuple& args) = 0; +}; + +using ::testing::_; +using ::testing::Action; +using ::testing::ActionInterface; +using ::testing::MakeAction; + +typedef int IncrementMethod(int*); + +class IncrementArgumentAction : public ActionInterface { + public: + virtual int Perform(const ::testing::tuple& args) { + int* p = ::testing::get<0>(args); // Grabs the first argument. + return *p++; + } +}; + +Action IncrementArgument() { + return MakeAction(new IncrementArgumentAction); +} +... + + EXPECT_CALL(foo, Baz(_)) + .WillOnce(IncrementArgument()); + + int n = 5; + foo.Baz(&n); // Should return 5 and change n to 6. +``` + +## Writing New Polymorphic Actions ## + +The previous recipe showed you how to define your own action. This is +all good, except that you need to know the type of the function in +which the action will be used. Sometimes that can be a problem. For +example, if you want to use the action in functions with _different_ +types (e.g. like `Return()` and `SetArgPointee()`). + +If an action can be used in several types of mock functions, we say +it's _polymorphic_. The `MakePolymorphicAction()` function template +makes it easy to define such an action: + +``` +namespace testing { + +template +PolymorphicAction MakePolymorphicAction(const Impl& impl); + +} // namespace testing +``` + +As an example, let's define an action that returns the second argument +in the mock function's argument list. The first step is to define an +implementation class: + +``` +class ReturnSecondArgumentAction { + public: + template + Result Perform(const ArgumentTuple& args) const { + // To get the i-th (0-based) argument, use ::testing::get(args). + return ::testing::get<1>(args); + } +}; +``` + +This implementation class does _not_ need to inherit from any +particular class. What matters is that it must have a `Perform()` +method template. This method template takes the mock function's +arguments as a tuple in a **single** argument, and returns the result of +the action. It can be either `const` or not, but must be invokable +with exactly one template argument, which is the result type. In other +words, you must be able to call `Perform(args)` where `R` is the +mock function's return type and `args` is its arguments in a tuple. + +Next, we use `MakePolymorphicAction()` to turn an instance of the +implementation class into the polymorphic action we need. It will be +convenient to have a wrapper for this: + +``` +using ::testing::MakePolymorphicAction; +using ::testing::PolymorphicAction; + +PolymorphicAction ReturnSecondArgument() { + return MakePolymorphicAction(ReturnSecondArgumentAction()); +} +``` + +Now, you can use this polymorphic action the same way you use the +built-in ones: + +``` +using ::testing::_; + +class MockFoo : public Foo { + public: + MOCK_METHOD2(DoThis, int(bool flag, int n)); + MOCK_METHOD3(DoThat, string(int x, const char* str1, const char* str2)); +}; +... + + MockFoo foo; + EXPECT_CALL(foo, DoThis(_, _)) + .WillOnce(ReturnSecondArgument()); + EXPECT_CALL(foo, DoThat(_, _, _)) + .WillOnce(ReturnSecondArgument()); + ... + foo.DoThis(true, 5); // Will return 5. + foo.DoThat(1, "Hi", "Bye"); // Will return "Hi". +``` + +## Teaching Google Mock How to Print Your Values ## + +When an uninteresting or unexpected call occurs, Google Mock prints the +argument values and the stack trace to help you debug. Assertion +macros like `EXPECT_THAT` and `EXPECT_EQ` also print the values in +question when the assertion fails. Google Mock and Google Test do this using +Google Test's user-extensible value printer. + +This printer knows how to print built-in C++ types, native arrays, STL +containers, and any type that supports the `<<` operator. For other +types, it prints the raw bytes in the value and hopes that you the +user can figure it out. +[Google Test's advanced guide](../../googletest/docs/advanced.md#teaching-google-test-how-to-print-your-values) +explains how to extend the printer to do a better job at +printing your particular type than to dump the bytes. diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/docs/DesignDoc.md b/deps/rapidjson/thirdparty/gtest/googlemock/docs/DesignDoc.md new file mode 100644 index 0000000..3f515c3 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/docs/DesignDoc.md @@ -0,0 +1,280 @@ +This page discusses the design of new Google Mock features. + + + +# Macros for Defining Actions # + +## Problem ## + +Due to the lack of closures in C++, it currently requires some +non-trivial effort to define a custom action in Google Mock. For +example, suppose you want to "increment the value pointed to by the +second argument of the mock function and return it", you could write: + +``` +int IncrementArg1(Unused, int* p, Unused) { + return ++(*p); +} + +... WillOnce(Invoke(IncrementArg1)); +``` + +There are several things unsatisfactory about this approach: + + * Even though the action only cares about the second argument of the mock function, its definition needs to list other arguments as dummies. This is tedious. + * The defined action is usable only in mock functions that takes exactly 3 arguments - an unnecessary restriction. + * To use the action, one has to say `Invoke(IncrementArg1)`, which isn't as nice as `IncrementArg1()`. + +The latter two problems can be overcome using `MakePolymorphicAction()`, +but it requires much more boilerplate code: + +``` +class IncrementArg1Action { + public: + template + Result Perform(const ArgumentTuple& args) const { + return ++(*tr1::get<1>(args)); + } +}; + +PolymorphicAction IncrementArg1() { + return MakePolymorphicAction(IncrementArg1Action()); +} + +... WillOnce(IncrementArg1()); +``` + +Our goal is to allow defining custom actions with the least amount of +boiler-plate C++ requires. + +## Solution ## + +We propose to introduce a new macro: +``` +ACTION(name) { statements; } +``` + +Using this in a namespace scope will define an action with the given +name that executes the statements. Inside the statements, you can +refer to the K-th (0-based) argument of the mock function as `argK`. +For example: +``` +ACTION(IncrementArg1) { return ++(*arg1); } +``` +allows you to write +``` +... WillOnce(IncrementArg1()); +``` + +Note that you don't need to specify the types of the mock function +arguments, as brevity is a top design goal here. Rest assured that +your code is still type-safe though: you'll get a compiler error if +`*arg1` doesn't support the `++` operator, or if the type of +`++(*arg1)` isn't compatible with the mock function's return type. + +Another example: +``` +ACTION(Foo) { + (*arg2)(5); + Blah(); + *arg1 = 0; + return arg0; +} +``` +defines an action `Foo()` that invokes argument #2 (a function pointer) +with 5, calls function `Blah()`, sets the value pointed to by argument +#1 to 0, and returns argument #0. + +For more convenience and flexibility, you can also use the following +pre-defined symbols in the body of `ACTION`: + +| `argK_type` | The type of the K-th (0-based) argument of the mock function | +|:------------|:-------------------------------------------------------------| +| `args` | All arguments of the mock function as a tuple | +| `args_type` | The type of all arguments of the mock function as a tuple | +| `return_type` | The return type of the mock function | +| `function_type` | The type of the mock function | + +For example, when using an `ACTION` as a stub action for mock function: +``` +int DoSomething(bool flag, int* ptr); +``` +we have: +| **Pre-defined Symbol** | **Is Bound To** | +|:-----------------------|:----------------| +| `arg0` | the value of `flag` | +| `arg0_type` | the type `bool` | +| `arg1` | the value of `ptr` | +| `arg1_type` | the type `int*` | +| `args` | the tuple `(flag, ptr)` | +| `args_type` | the type `std::tr1::tuple` | +| `return_type` | the type `int` | +| `function_type` | the type `int(bool, int*)` | + +## Parameterized actions ## + +Sometimes you'll want to parameterize the action. For that we propose +another macro +``` +ACTION_P(name, param) { statements; } +``` + +For example, +``` +ACTION_P(Add, n) { return arg0 + n; } +``` +will allow you to write +``` +// Returns argument #0 + 5. +... WillOnce(Add(5)); +``` + +For convenience, we use the term _arguments_ for the values used to +invoke the mock function, and the term _parameters_ for the values +used to instantiate an action. + +Note that you don't need to provide the type of the parameter either. +Suppose the parameter is named `param`, you can also use the +Google-Mock-defined symbol `param_type` to refer to the type of the +parameter as inferred by the compiler. + +We will also provide `ACTION_P2`, `ACTION_P3`, and etc to support +multi-parameter actions. For example, +``` +ACTION_P2(ReturnDistanceTo, x, y) { + double dx = arg0 - x; + double dy = arg1 - y; + return sqrt(dx*dx + dy*dy); +} +``` +lets you write +``` +... WillOnce(ReturnDistanceTo(5.0, 26.5)); +``` + +You can view `ACTION` as a degenerated parameterized action where the +number of parameters is 0. + +## Advanced Usages ## + +### Overloading Actions ### + +You can easily define actions overloaded on the number of parameters: +``` +ACTION_P(Plus, a) { ... } +ACTION_P2(Plus, a, b) { ... } +``` + +### Restricting the Type of an Argument or Parameter ### + +For maximum brevity and reusability, the `ACTION*` macros don't let +you specify the types of the mock function arguments and the action +parameters. Instead, we let the compiler infer the types for us. + +Sometimes, however, we may want to be more explicit about the types. +There are several tricks to do that. For example: +``` +ACTION(Foo) { + // Makes sure arg0 can be converted to int. + int n = arg0; + ... use n instead of arg0 here ... +} + +ACTION_P(Bar, param) { + // Makes sure the type of arg1 is const char*. + ::testing::StaticAssertTypeEq(); + + // Makes sure param can be converted to bool. + bool flag = param; +} +``` +where `StaticAssertTypeEq` is a compile-time assertion we plan to add to +Google Test (the name is chosen to match `static_assert` in C++0x). + +### Using the ACTION Object's Type ### + +If you are writing a function that returns an `ACTION` object, you'll +need to know its type. The type depends on the macro used to define +the action and the parameter types. The rule is relatively simple: +| **Given Definition** | **Expression** | **Has Type** | +|:---------------------|:---------------|:-------------| +| `ACTION(Foo)` | `Foo()` | `FooAction` | +| `ACTION_P(Bar, param)` | `Bar(int_value)` | `BarActionP` | +| `ACTION_P2(Baz, p1, p2)` | `Baz(bool_value, int_value)` | `BazActionP2` | +| ... | ... | ... | + +Note that we have to pick different suffixes (`Action`, `ActionP`, +`ActionP2`, and etc) for actions with different numbers of parameters, +or the action definitions cannot be overloaded on the number of +parameters. + +## When to Use ## + +While the new macros are very convenient, please also consider other +means of implementing actions (e.g. via `ActionInterface` or +`MakePolymorphicAction()`), especially if you need to use the defined +action a lot. While the other approaches require more work, they give +you more control on the types of the mock function arguments and the +action parameters, which in general leads to better compiler error +messages that pay off in the long run. They also allow overloading +actions based on parameter types, as opposed to just the number of +parameters. + +## Related Work ## + +As you may have realized, the `ACTION*` macros resemble closures (also +known as lambda expressions or anonymous functions). Indeed, both of +them seek to lower the syntactic overhead for defining a function. + +C++0x will support lambdas, but they are not part of C++ right now. +Some non-standard libraries (most notably BLL or Boost Lambda Library) +try to alleviate this problem. However, they are not a good choice +for defining actions as: + + * They are non-standard and not widely installed. Google Mock only depends on standard libraries and `tr1::tuple`, which is part of the new C++ standard and comes with gcc 4+. We want to keep it that way. + * They are not trivial to learn. + * They will become obsolete when C++0x's lambda feature is widely supported. We don't want to make our users use a dying library. + * Since they are based on operators, they are rather ad hoc: you cannot use statements, and you cannot pass the lambda arguments to a function, for example. + * They have subtle semantics that easily confuses new users. For example, in expression `_1++ + foo++`, `foo` will be incremented only once where the expression is evaluated, while `_1` will be incremented every time the unnamed function is invoked. This is far from intuitive. + +`ACTION*` avoid all these problems. + +## Future Improvements ## + +There may be a need for composing `ACTION*` definitions (i.e. invoking +another `ACTION` inside the definition of one `ACTION*`). We are not +sure we want it yet, as one can get a similar effect by putting +`ACTION` definitions in function templates and composing the function +templates. We'll revisit this based on user feedback. + +The reason we don't allow `ACTION*()` inside a function body is that +the current C++ standard doesn't allow function-local types to be used +to instantiate templates. The upcoming C++0x standard will lift this +restriction. Once this feature is widely supported by compilers, we +can revisit the implementation and add support for using `ACTION*()` +inside a function. + +C++0x will also support lambda expressions. When they become +available, we may want to support using lambdas as actions. + +# Macros for Defining Matchers # + +Once the macros for defining actions are implemented, we plan to do +the same for matchers: + +``` +MATCHER(name) { statements; } +``` + +where you can refer to the value being matched as `arg`. For example, +given: + +``` +MATCHER(IsPositive) { return arg > 0; } +``` + +you can use `IsPositive()` as a matcher that matches a value iff it is +greater than 0. + +We will also add `MATCHER_P`, `MATCHER_P2`, and etc for parameterized +matchers. \ No newline at end of file diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/docs/Documentation.md b/deps/rapidjson/thirdparty/gtest/googlemock/docs/Documentation.md new file mode 100644 index 0000000..16083e7 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/docs/Documentation.md @@ -0,0 +1,15 @@ +This page lists all documentation markdown files for Google Mock **(the +current git version)** +-- **if you use a former version of Google Mock, please read the +documentation for that specific version instead (e.g. by checking out +the respective git branch/tag).** + + * [ForDummies](ForDummies.md) -- start here if you are new to Google Mock. + * [CheatSheet](CheatSheet.md) -- a quick reference. + * [CookBook](CookBook.md) -- recipes for doing various tasks using Google Mock. + * [FrequentlyAskedQuestions](FrequentlyAskedQuestions.md) -- check here before asking a question on the mailing list. + +To contribute code to Google Mock, read: + + * [CONTRIBUTING](../CONTRIBUTING.md) -- read this _before_ writing your first patch. + * [Pump Manual](../../googletest/docs/PumpManual.md) -- how we generate some of Google Mock's source files. diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/docs/ForDummies.md b/deps/rapidjson/thirdparty/gtest/googlemock/docs/ForDummies.md new file mode 100644 index 0000000..1e0fd41 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/docs/ForDummies.md @@ -0,0 +1,447 @@ + + +(**Note:** If you get compiler errors that you don't understand, be sure to consult [Google Mock Doctor](FrequentlyAskedQuestions.md#how-am-i-supposed-to-make-sense-of-these-horrible-template-errors).) + +# What Is Google C++ Mocking Framework? # +When you write a prototype or test, often it's not feasible or wise to rely on real objects entirely. A **mock object** implements the same interface as a real object (so it can be used as one), but lets you specify at run time how it will be used and what it should do (which methods will be called? in which order? how many times? with what arguments? what will they return? etc). + +**Note:** It is easy to confuse the term _fake objects_ with mock objects. Fakes and mocks actually mean very different things in the Test-Driven Development (TDD) community: + + * **Fake** objects have working implementations, but usually take some shortcut (perhaps to make the operations less expensive), which makes them not suitable for production. An in-memory file system would be an example of a fake. + * **Mocks** are objects pre-programmed with _expectations_, which form a specification of the calls they are expected to receive. + +If all this seems too abstract for you, don't worry - the most important thing to remember is that a mock allows you to check the _interaction_ between itself and code that uses it. The difference between fakes and mocks will become much clearer once you start to use mocks. + +**Google C++ Mocking Framework** (or **Google Mock** for short) is a library (sometimes we also call it a "framework" to make it sound cool) for creating mock classes and using them. It does to C++ what [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/) do to Java. + +Using Google Mock involves three basic steps: + + 1. Use some simple macros to describe the interface you want to mock, and they will expand to the implementation of your mock class; + 1. Create some mock objects and specify its expectations and behavior using an intuitive syntax; + 1. Exercise code that uses the mock objects. Google Mock will catch any violation of the expectations as soon as it arises. + +# Why Google Mock? # +While mock objects help you remove unnecessary dependencies in tests and make them fast and reliable, using mocks manually in C++ is _hard_: + + * Someone has to implement the mocks. The job is usually tedious and error-prone. No wonder people go great distances to avoid it. + * The quality of those manually written mocks is a bit, uh, unpredictable. You may see some really polished ones, but you may also see some that were hacked up in a hurry and have all sorts of ad-hoc restrictions. + * The knowledge you gained from using one mock doesn't transfer to the next. + +In contrast, Java and Python programmers have some fine mock frameworks, which automate the creation of mocks. As a result, mocking is a proven effective technique and widely adopted practice in those communities. Having the right tool absolutely makes the difference. + +Google Mock was built to help C++ programmers. It was inspired by [jMock](http://www.jmock.org/) and [EasyMock](http://www.easymock.org/), but designed with C++'s specifics in mind. It is your friend if any of the following problems is bothering you: + + * You are stuck with a sub-optimal design and wish you had done more prototyping before it was too late, but prototyping in C++ is by no means "rapid". + * Your tests are slow as they depend on too many libraries or use expensive resources (e.g. a database). + * Your tests are brittle as some resources they use are unreliable (e.g. the network). + * You want to test how your code handles a failure (e.g. a file checksum error), but it's not easy to cause one. + * You need to make sure that your module interacts with other modules in the right way, but it's hard to observe the interaction; therefore you resort to observing the side effects at the end of the action, which is awkward at best. + * You want to "mock out" your dependencies, except that they don't have mock implementations yet; and, frankly, you aren't thrilled by some of those hand-written mocks. + +We encourage you to use Google Mock as: + + * a _design_ tool, for it lets you experiment with your interface design early and often. More iterations lead to better designs! + * a _testing_ tool to cut your tests' outbound dependencies and probe the interaction between your module and its collaborators. + +# Getting Started # +Using Google Mock is easy! Inside your C++ source file, just `#include` `"gtest/gtest.h"` and `"gmock/gmock.h"`, and you are ready to go. + +# A Case for Mock Turtles # +Let's look at an example. Suppose you are developing a graphics program that relies on a LOGO-like API for drawing. How would you test that it does the right thing? Well, you can run it and compare the screen with a golden screen snapshot, but let's admit it: tests like this are expensive to run and fragile (What if you just upgraded to a shiny new graphics card that has better anti-aliasing? Suddenly you have to update all your golden images.). It would be too painful if all your tests are like this. Fortunately, you learned about Dependency Injection and know the right thing to do: instead of having your application talk to the drawing API directly, wrap the API in an interface (say, `Turtle`) and code to that interface: + +``` +class Turtle { + ... + virtual ~Turtle() {} + virtual void PenUp() = 0; + virtual void PenDown() = 0; + virtual void Forward(int distance) = 0; + virtual void Turn(int degrees) = 0; + virtual void GoTo(int x, int y) = 0; + virtual int GetX() const = 0; + virtual int GetY() const = 0; +}; +``` + +(Note that the destructor of `Turtle` **must** be virtual, as is the case for **all** classes you intend to inherit from - otherwise the destructor of the derived class will not be called when you delete an object through a base pointer, and you'll get corrupted program states like memory leaks.) + +You can control whether the turtle's movement will leave a trace using `PenUp()` and `PenDown()`, and control its movement using `Forward()`, `Turn()`, and `GoTo()`. Finally, `GetX()` and `GetY()` tell you the current position of the turtle. + +Your program will normally use a real implementation of this interface. In tests, you can use a mock implementation instead. This allows you to easily check what drawing primitives your program is calling, with what arguments, and in which order. Tests written this way are much more robust (they won't break because your new machine does anti-aliasing differently), easier to read and maintain (the intent of a test is expressed in the code, not in some binary images), and run _much, much faster_. + +# Writing the Mock Class # +If you are lucky, the mocks you need to use have already been implemented by some nice people. If, however, you find yourself in the position to write a mock class, relax - Google Mock turns this task into a fun game! (Well, almost.) + +## How to Define It ## +Using the `Turtle` interface as example, here are the simple steps you need to follow: + + 1. Derive a class `MockTurtle` from `Turtle`. + 1. Take a _virtual_ function of `Turtle` (while it's possible to [mock non-virtual methods using templates](CookBook.md#mocking-nonvirtual-methods), it's much more involved). Count how many arguments it has. + 1. In the `public:` section of the child class, write `MOCK_METHODn();` (or `MOCK_CONST_METHODn();` if you are mocking a `const` method), where `n` is the number of the arguments; if you counted wrong, shame on you, and a compiler error will tell you so. + 1. Now comes the fun part: you take the function signature, cut-and-paste the _function name_ as the _first_ argument to the macro, and leave what's left as the _second_ argument (in case you're curious, this is the _type of the function_). + 1. Repeat until all virtual functions you want to mock are done. + +After the process, you should have something like: + +``` +#include "gmock/gmock.h" // Brings in Google Mock. +class MockTurtle : public Turtle { + public: + ... + MOCK_METHOD0(PenUp, void()); + MOCK_METHOD0(PenDown, void()); + MOCK_METHOD1(Forward, void(int distance)); + MOCK_METHOD1(Turn, void(int degrees)); + MOCK_METHOD2(GoTo, void(int x, int y)); + MOCK_CONST_METHOD0(GetX, int()); + MOCK_CONST_METHOD0(GetY, int()); +}; +``` + +You don't need to define these mock methods somewhere else - the `MOCK_METHOD*` macros will generate the definitions for you. It's that simple! Once you get the hang of it, you can pump out mock classes faster than your source-control system can handle your check-ins. + +**Tip:** If even this is too much work for you, you'll find the +`gmock_gen.py` tool in Google Mock's `scripts/generator/` directory (courtesy of the [cppclean](http://code.google.com/p/cppclean/) project) useful. This command-line +tool requires that you have Python 2.4 installed. You give it a C++ file and the name of an abstract class defined in it, +and it will print the definition of the mock class for you. Due to the +complexity of the C++ language, this script may not always work, but +it can be quite handy when it does. For more details, read the [user documentation](../scripts/generator/README). + +## Where to Put It ## +When you define a mock class, you need to decide where to put its definition. Some people put it in a `*_test.cc`. This is fine when the interface being mocked (say, `Foo`) is owned by the same person or team. Otherwise, when the owner of `Foo` changes it, your test could break. (You can't really expect `Foo`'s maintainer to fix every test that uses `Foo`, can you?) + +So, the rule of thumb is: if you need to mock `Foo` and it's owned by others, define the mock class in `Foo`'s package (better, in a `testing` sub-package such that you can clearly separate production code and testing utilities), and put it in a `mock_foo.h`. Then everyone can reference `mock_foo.h` from their tests. If `Foo` ever changes, there is only one copy of `MockFoo` to change, and only tests that depend on the changed methods need to be fixed. + +Another way to do it: you can introduce a thin layer `FooAdaptor` on top of `Foo` and code to this new interface. Since you own `FooAdaptor`, you can absorb changes in `Foo` much more easily. While this is more work initially, carefully choosing the adaptor interface can make your code easier to write and more readable (a net win in the long run), as you can choose `FooAdaptor` to fit your specific domain much better than `Foo` does. + +# Using Mocks in Tests # +Once you have a mock class, using it is easy. The typical work flow is: + + 1. Import the Google Mock names from the `testing` namespace such that you can use them unqualified (You only have to do it once per file. Remember that namespaces are a good idea and good for your health.). + 1. Create some mock objects. + 1. Specify your expectations on them (How many times will a method be called? With what arguments? What should it do? etc.). + 1. Exercise some code that uses the mocks; optionally, check the result using Google Test assertions. If a mock method is called more than expected or with wrong arguments, you'll get an error immediately. + 1. When a mock is destructed, Google Mock will automatically check whether all expectations on it have been satisfied. + +Here's an example: + +``` +#include "path/to/mock-turtle.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +using ::testing::AtLeast; // #1 + +TEST(PainterTest, CanDrawSomething) { + MockTurtle turtle; // #2 + EXPECT_CALL(turtle, PenDown()) // #3 + .Times(AtLeast(1)); + + Painter painter(&turtle); // #4 + + EXPECT_TRUE(painter.DrawCircle(0, 0, 10)); +} // #5 + +int main(int argc, char** argv) { + // The following line must be executed to initialize Google Mock + // (and Google Test) before running the tests. + ::testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} +``` + +As you might have guessed, this test checks that `PenDown()` is called at least once. If the `painter` object didn't call this method, your test will fail with a message like this: + +``` +path/to/my_test.cc:119: Failure +Actual function call count doesn't match this expectation: +Actually: never called; +Expected: called at least once. +``` + +**Tip 1:** If you run the test from an Emacs buffer, you can hit `` on the line number displayed in the error message to jump right to the failed expectation. + +**Tip 2:** If your mock objects are never deleted, the final verification won't happen. Therefore it's a good idea to use a heap leak checker in your tests when you allocate mocks on the heap. + +**Important note:** Google Mock requires expectations to be set **before** the mock functions are called, otherwise the behavior is **undefined**. In particular, you mustn't interleave `EXPECT_CALL()`s and calls to the mock functions. + +This means `EXPECT_CALL()` should be read as expecting that a call will occur _in the future_, not that a call has occurred. Why does Google Mock work like that? Well, specifying the expectation beforehand allows Google Mock to report a violation as soon as it arises, when the context (stack trace, etc) is still available. This makes debugging much easier. + +Admittedly, this test is contrived and doesn't do much. You can easily achieve the same effect without using Google Mock. However, as we shall reveal soon, Google Mock allows you to do _much more_ with the mocks. + +## Using Google Mock with Any Testing Framework ## +If you want to use something other than Google Test (e.g. [CppUnit](http://sourceforge.net/projects/cppunit/) or +[CxxTest](http://cxxtest.tigris.org/)) as your testing framework, just change the `main()` function in the previous section to: +``` +int main(int argc, char** argv) { + // The following line causes Google Mock to throw an exception on failure, + // which will be interpreted by your testing framework as a test failure. + ::testing::GTEST_FLAG(throw_on_failure) = true; + ::testing::InitGoogleMock(&argc, argv); + ... whatever your testing framework requires ... +} +``` + +This approach has a catch: it makes Google Mock throw an exception +from a mock object's destructor sometimes. With some compilers, this +sometimes causes the test program to crash. You'll still be able to +notice that the test has failed, but it's not a graceful failure. + +A better solution is to use Google Test's +[event listener API](../../googletest/docs/advanced.md#extending-google-test-by-handling-test-events) +to report a test failure to your testing framework properly. You'll need to +implement the `OnTestPartResult()` method of the event listener interface, but it +should be straightforward. + +If this turns out to be too much work, we suggest that you stick with +Google Test, which works with Google Mock seamlessly (in fact, it is +technically part of Google Mock.). If there is a reason that you +cannot use Google Test, please let us know. + +# Setting Expectations # +The key to using a mock object successfully is to set the _right expectations_ on it. If you set the expectations too strict, your test will fail as the result of unrelated changes. If you set them too loose, bugs can slip through. You want to do it just right such that your test can catch exactly the kind of bugs you intend it to catch. Google Mock provides the necessary means for you to do it "just right." + +## General Syntax ## +In Google Mock we use the `EXPECT_CALL()` macro to set an expectation on a mock method. The general syntax is: + +``` +EXPECT_CALL(mock_object, method(matchers)) + .Times(cardinality) + .WillOnce(action) + .WillRepeatedly(action); +``` + +The macro has two arguments: first the mock object, and then the method and its arguments. Note that the two are separated by a comma (`,`), not a period (`.`). (Why using a comma? The answer is that it was necessary for technical reasons.) + +The macro can be followed by some optional _clauses_ that provide more information about the expectation. We'll discuss how each clause works in the coming sections. + +This syntax is designed to make an expectation read like English. For example, you can probably guess that + +``` +using ::testing::Return; +... +EXPECT_CALL(turtle, GetX()) + .Times(5) + .WillOnce(Return(100)) + .WillOnce(Return(150)) + .WillRepeatedly(Return(200)); +``` + +says that the `turtle` object's `GetX()` method will be called five times, it will return 100 the first time, 150 the second time, and then 200 every time. Some people like to call this style of syntax a Domain-Specific Language (DSL). + +**Note:** Why do we use a macro to do this? It serves two purposes: first it makes expectations easily identifiable (either by `grep` or by a human reader), and second it allows Google Mock to include the source file location of a failed expectation in messages, making debugging easier. + +## Matchers: What Arguments Do We Expect? ## +When a mock function takes arguments, we must specify what arguments we are expecting; for example: + +``` +// Expects the turtle to move forward by 100 units. +EXPECT_CALL(turtle, Forward(100)); +``` + +Sometimes you may not want to be too specific (Remember that talk about tests being too rigid? Over specification leads to brittle tests and obscures the intent of tests. Therefore we encourage you to specify only what's necessary - no more, no less.). If you care to check that `Forward()` will be called but aren't interested in its actual argument, write `_` as the argument, which means "anything goes": + +``` +using ::testing::_; +... +// Expects the turtle to move forward. +EXPECT_CALL(turtle, Forward(_)); +``` + +`_` is an instance of what we call **matchers**. A matcher is like a predicate and can test whether an argument is what we'd expect. You can use a matcher inside `EXPECT_CALL()` wherever a function argument is expected. + +A list of built-in matchers can be found in the [CheatSheet](CheatSheet.md). For example, here's the `Ge` (greater than or equal) matcher: + +``` +using ::testing::Ge; +... +EXPECT_CALL(turtle, Forward(Ge(100))); +``` + +This checks that the turtle will be told to go forward by at least 100 units. + +## Cardinalities: How Many Times Will It Be Called? ## +The first clause we can specify following an `EXPECT_CALL()` is `Times()`. We call its argument a **cardinality** as it tells _how many times_ the call should occur. It allows us to repeat an expectation many times without actually writing it as many times. More importantly, a cardinality can be "fuzzy", just like a matcher can be. This allows a user to express the intent of a test exactly. + +An interesting special case is when we say `Times(0)`. You may have guessed - it means that the function shouldn't be called with the given arguments at all, and Google Mock will report a Google Test failure whenever the function is (wrongfully) called. + +We've seen `AtLeast(n)` as an example of fuzzy cardinalities earlier. For the list of built-in cardinalities you can use, see the [CheatSheet](CheatSheet.md). + +The `Times()` clause can be omitted. **If you omit `Times()`, Google Mock will infer the cardinality for you.** The rules are easy to remember: + + * If **neither** `WillOnce()` **nor** `WillRepeatedly()` is in the `EXPECT_CALL()`, the inferred cardinality is `Times(1)`. + * If there are `n WillOnce()`'s but **no** `WillRepeatedly()`, where `n` >= 1, the cardinality is `Times(n)`. + * If there are `n WillOnce()`'s and **one** `WillRepeatedly()`, where `n` >= 0, the cardinality is `Times(AtLeast(n))`. + +**Quick quiz:** what do you think will happen if a function is expected to be called twice but actually called four times? + +## Actions: What Should It Do? ## +Remember that a mock object doesn't really have a working implementation? We as users have to tell it what to do when a method is invoked. This is easy in Google Mock. + +First, if the return type of a mock function is a built-in type or a pointer, the function has a **default action** (a `void` function will just return, a `bool` function will return `false`, and other functions will return 0). In addition, in C++ 11 and above, a mock function whose return type is default-constructible (i.e. has a default constructor) has a default action of returning a default-constructed value. If you don't say anything, this behavior will be used. + +Second, if a mock function doesn't have a default action, or the default action doesn't suit you, you can specify the action to be taken each time the expectation matches using a series of `WillOnce()` clauses followed by an optional `WillRepeatedly()`. For example, + +``` +using ::testing::Return; +... +EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(100)) + .WillOnce(Return(200)) + .WillOnce(Return(300)); +``` + +This says that `turtle.GetX()` will be called _exactly three times_ (Google Mock inferred this from how many `WillOnce()` clauses we've written, since we didn't explicitly write `Times()`), and will return 100, 200, and 300 respectively. + +``` +using ::testing::Return; +... +EXPECT_CALL(turtle, GetY()) + .WillOnce(Return(100)) + .WillOnce(Return(200)) + .WillRepeatedly(Return(300)); +``` + +says that `turtle.GetY()` will be called _at least twice_ (Google Mock knows this as we've written two `WillOnce()` clauses and a `WillRepeatedly()` while having no explicit `Times()`), will return 100 the first time, 200 the second time, and 300 from the third time on. + +Of course, if you explicitly write a `Times()`, Google Mock will not try to infer the cardinality itself. What if the number you specified is larger than there are `WillOnce()` clauses? Well, after all `WillOnce()`s are used up, Google Mock will do the _default_ action for the function every time (unless, of course, you have a `WillRepeatedly()`.). + +What can we do inside `WillOnce()` besides `Return()`? You can return a reference using `ReturnRef(variable)`, or invoke a pre-defined function, among [others](CheatSheet.md#actions). + +**Important note:** The `EXPECT_CALL()` statement evaluates the action clause only once, even though the action may be performed many times. Therefore you must be careful about side effects. The following may not do what you want: + +``` +int n = 100; +EXPECT_CALL(turtle, GetX()) +.Times(4) +.WillRepeatedly(Return(n++)); +``` + +Instead of returning 100, 101, 102, ..., consecutively, this mock function will always return 100 as `n++` is only evaluated once. Similarly, `Return(new Foo)` will create a new `Foo` object when the `EXPECT_CALL()` is executed, and will return the same pointer every time. If you want the side effect to happen every time, you need to define a custom action, which we'll teach in the [CookBook](CookBook.md). + +Time for another quiz! What do you think the following means? + +``` +using ::testing::Return; +... +EXPECT_CALL(turtle, GetY()) +.Times(4) +.WillOnce(Return(100)); +``` + +Obviously `turtle.GetY()` is expected to be called four times. But if you think it will return 100 every time, think twice! Remember that one `WillOnce()` clause will be consumed each time the function is invoked and the default action will be taken afterwards. So the right answer is that `turtle.GetY()` will return 100 the first time, but **return 0 from the second time on**, as returning 0 is the default action for `int` functions. + +## Using Multiple Expectations ## +So far we've only shown examples where you have a single expectation. More realistically, you're going to specify expectations on multiple mock methods, which may be from multiple mock objects. + +By default, when a mock method is invoked, Google Mock will search the expectations in the **reverse order** they are defined, and stop when an active expectation that matches the arguments is found (you can think of it as "newer rules override older ones."). If the matching expectation cannot take any more calls, you will get an upper-bound-violated failure. Here's an example: + +``` +using ::testing::_; +... +EXPECT_CALL(turtle, Forward(_)); // #1 +EXPECT_CALL(turtle, Forward(10)) // #2 + .Times(2); +``` + +If `Forward(10)` is called three times in a row, the third time it will be an error, as the last matching expectation (#2) has been saturated. If, however, the third `Forward(10)` call is replaced by `Forward(20)`, then it would be OK, as now #1 will be the matching expectation. + +**Side note:** Why does Google Mock search for a match in the _reverse_ order of the expectations? The reason is that this allows a user to set up the default expectations in a mock object's constructor or the test fixture's set-up phase and then customize the mock by writing more specific expectations in the test body. So, if you have two expectations on the same method, you want to put the one with more specific matchers **after** the other, or the more specific rule would be shadowed by the more general one that comes after it. + +## Ordered vs Unordered Calls ## +By default, an expectation can match a call even though an earlier expectation hasn't been satisfied. In other words, the calls don't have to occur in the order the expectations are specified. + +Sometimes, you may want all the expected calls to occur in a strict order. To say this in Google Mock is easy: + +``` +using ::testing::InSequence; +... +TEST(FooTest, DrawsLineSegment) { + ... + { + InSequence dummy; + + EXPECT_CALL(turtle, PenDown()); + EXPECT_CALL(turtle, Forward(100)); + EXPECT_CALL(turtle, PenUp()); + } + Foo(); +} +``` + +By creating an object of type `InSequence`, all expectations in its scope are put into a _sequence_ and have to occur _sequentially_. Since we are just relying on the constructor and destructor of this object to do the actual work, its name is really irrelevant. + +In this example, we test that `Foo()` calls the three expected functions in the order as written. If a call is made out-of-order, it will be an error. + +(What if you care about the relative order of some of the calls, but not all of them? Can you specify an arbitrary partial order? The answer is ... yes! If you are impatient, the details can be found in the [CookBook](CookBook.md#expecting-partially-ordered-calls).) + +## All Expectations Are Sticky (Unless Said Otherwise) ## +Now let's do a quick quiz to see how well you can use this mock stuff already. How would you test that the turtle is asked to go to the origin _exactly twice_ (you want to ignore any other instructions it receives)? + +After you've come up with your answer, take a look at ours and compare notes (solve it yourself first - don't cheat!): + +``` +using ::testing::_; +... +EXPECT_CALL(turtle, GoTo(_, _)) // #1 + .Times(AnyNumber()); +EXPECT_CALL(turtle, GoTo(0, 0)) // #2 + .Times(2); +``` + +Suppose `turtle.GoTo(0, 0)` is called three times. In the third time, Google Mock will see that the arguments match expectation #2 (remember that we always pick the last matching expectation). Now, since we said that there should be only two such calls, Google Mock will report an error immediately. This is basically what we've told you in the "Using Multiple Expectations" section above. + +This example shows that **expectations in Google Mock are "sticky" by default**, in the sense that they remain active even after we have reached their invocation upper bounds. This is an important rule to remember, as it affects the meaning of the spec, and is **different** to how it's done in many other mocking frameworks (Why'd we do that? Because we think our rule makes the common cases easier to express and understand.). + +Simple? Let's see if you've really understood it: what does the following code say? + +``` +using ::testing::Return; +... +for (int i = n; i > 0; i--) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)); +} +``` + +If you think it says that `turtle.GetX()` will be called `n` times and will return 10, 20, 30, ..., consecutively, think twice! The problem is that, as we said, expectations are sticky. So, the second time `turtle.GetX()` is called, the last (latest) `EXPECT_CALL()` statement will match, and will immediately lead to an "upper bound exceeded" error - this piece of code is not very useful! + +One correct way of saying that `turtle.GetX()` will return 10, 20, 30, ..., is to explicitly say that the expectations are _not_ sticky. In other words, they should _retire_ as soon as they are saturated: + +``` +using ::testing::Return; +... +for (int i = n; i > 0; i--) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)) + .RetiresOnSaturation(); +} +``` + +And, there's a better way to do it: in this case, we expect the calls to occur in a specific order, and we line up the actions to match the order. Since the order is important here, we should make it explicit using a sequence: + +``` +using ::testing::InSequence; +using ::testing::Return; +... +{ + InSequence s; + + for (int i = 1; i <= n; i++) { + EXPECT_CALL(turtle, GetX()) + .WillOnce(Return(10*i)) + .RetiresOnSaturation(); + } +} +``` + +By the way, the other situation where an expectation may _not_ be sticky is when it's in a sequence - as soon as another expectation that comes after it in the sequence has been used, it automatically retires (and will never be used to match any call). + +## Uninteresting Calls ## +A mock object may have many methods, and not all of them are that interesting. For example, in some tests we may not care about how many times `GetX()` and `GetY()` get called. + +In Google Mock, if you are not interested in a method, just don't say anything about it. If a call to this method occurs, you'll see a warning in the test output, but it won't be a failure. + +# What Now? # +Congratulations! You've learned enough about Google Mock to start using it. Now, you might want to join the [googlemock](http://groups.google.com/group/googlemock) discussion group and actually write some tests using Google Mock - it will be fun. Hey, it may even be addictive - you've been warned. + +Then, if you feel like increasing your mock quotient, you should move on to the [CookBook](CookBook.md). You can learn many advanced features of Google Mock there -- and advance your level of enjoyment and testing bliss. diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/docs/FrequentlyAskedQuestions.md b/deps/rapidjson/thirdparty/gtest/googlemock/docs/FrequentlyAskedQuestions.md new file mode 100644 index 0000000..23f7da0 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/docs/FrequentlyAskedQuestions.md @@ -0,0 +1,627 @@ + + +Please send your questions to the +[googlemock](http://groups.google.com/group/googlemock) discussion +group. If you need help with compiler errors, make sure you have +tried [Google Mock Doctor](#How_am_I_supposed_to_make_sense_of_these_horrible_template_error.md) first. + +## When I call a method on my mock object, the method for the real object is invoked instead. What's the problem? ## + +In order for a method to be mocked, it must be _virtual_, unless you use the [high-perf dependency injection technique](CookBook.md#mocking-nonvirtual-methods). + +## I wrote some matchers. After I upgraded to a new version of Google Mock, they no longer compile. What's going on? ## + +After version 1.4.0 of Google Mock was released, we had an idea on how +to make it easier to write matchers that can generate informative +messages efficiently. We experimented with this idea and liked what +we saw. Therefore we decided to implement it. + +Unfortunately, this means that if you have defined your own matchers +by implementing `MatcherInterface` or using `MakePolymorphicMatcher()`, +your definitions will no longer compile. Matchers defined using the +`MATCHER*` family of macros are not affected. + +Sorry for the hassle if your matchers are affected. We believe it's +in everyone's long-term interest to make this change sooner than +later. Fortunately, it's usually not hard to migrate an existing +matcher to the new API. Here's what you need to do: + +If you wrote your matcher like this: +``` +// Old matcher definition that doesn't work with the latest +// Google Mock. +using ::testing::MatcherInterface; +... +class MyWonderfulMatcher : public MatcherInterface { + public: + ... + virtual bool Matches(MyType value) const { + // Returns true if value matches. + return value.GetFoo() > 5; + } + ... +}; +``` + +you'll need to change it to: +``` +// New matcher definition that works with the latest Google Mock. +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; +... +class MyWonderfulMatcher : public MatcherInterface { + public: + ... + virtual bool MatchAndExplain(MyType value, + MatchResultListener* listener) const { + // Returns true if value matches. + return value.GetFoo() > 5; + } + ... +}; +``` +(i.e. rename `Matches()` to `MatchAndExplain()` and give it a second +argument of type `MatchResultListener*`.) + +If you were also using `ExplainMatchResultTo()` to improve the matcher +message: +``` +// Old matcher definition that doesn't work with the lastest +// Google Mock. +using ::testing::MatcherInterface; +... +class MyWonderfulMatcher : public MatcherInterface { + public: + ... + virtual bool Matches(MyType value) const { + // Returns true if value matches. + return value.GetFoo() > 5; + } + + virtual void ExplainMatchResultTo(MyType value, + ::std::ostream* os) const { + // Prints some helpful information to os to help + // a user understand why value matches (or doesn't match). + *os << "the Foo property is " << value.GetFoo(); + } + ... +}; +``` + +you should move the logic of `ExplainMatchResultTo()` into +`MatchAndExplain()`, using the `MatchResultListener` argument where +the `::std::ostream` was used: +``` +// New matcher definition that works with the latest Google Mock. +using ::testing::MatcherInterface; +using ::testing::MatchResultListener; +... +class MyWonderfulMatcher : public MatcherInterface { + public: + ... + virtual bool MatchAndExplain(MyType value, + MatchResultListener* listener) const { + // Returns true if value matches. + *listener << "the Foo property is " << value.GetFoo(); + return value.GetFoo() > 5; + } + ... +}; +``` + +If your matcher is defined using `MakePolymorphicMatcher()`: +``` +// Old matcher definition that doesn't work with the latest +// Google Mock. +using ::testing::MakePolymorphicMatcher; +... +class MyGreatMatcher { + public: + ... + bool Matches(MyType value) const { + // Returns true if value matches. + return value.GetBar() < 42; + } + ... +}; +... MakePolymorphicMatcher(MyGreatMatcher()) ... +``` + +you should rename the `Matches()` method to `MatchAndExplain()` and +add a `MatchResultListener*` argument (the same as what you need to do +for matchers defined by implementing `MatcherInterface`): +``` +// New matcher definition that works with the latest Google Mock. +using ::testing::MakePolymorphicMatcher; +using ::testing::MatchResultListener; +... +class MyGreatMatcher { + public: + ... + bool MatchAndExplain(MyType value, + MatchResultListener* listener) const { + // Returns true if value matches. + return value.GetBar() < 42; + } + ... +}; +... MakePolymorphicMatcher(MyGreatMatcher()) ... +``` + +If your polymorphic matcher uses `ExplainMatchResultTo()` for better +failure messages: +``` +// Old matcher definition that doesn't work with the latest +// Google Mock. +using ::testing::MakePolymorphicMatcher; +... +class MyGreatMatcher { + public: + ... + bool Matches(MyType value) const { + // Returns true if value matches. + return value.GetBar() < 42; + } + ... +}; +void ExplainMatchResultTo(const MyGreatMatcher& matcher, + MyType value, + ::std::ostream* os) { + // Prints some helpful information to os to help + // a user understand why value matches (or doesn't match). + *os << "the Bar property is " << value.GetBar(); +} +... MakePolymorphicMatcher(MyGreatMatcher()) ... +``` + +you'll need to move the logic inside `ExplainMatchResultTo()` to +`MatchAndExplain()`: +``` +// New matcher definition that works with the latest Google Mock. +using ::testing::MakePolymorphicMatcher; +using ::testing::MatchResultListener; +... +class MyGreatMatcher { + public: + ... + bool MatchAndExplain(MyType value, + MatchResultListener* listener) const { + // Returns true if value matches. + *listener << "the Bar property is " << value.GetBar(); + return value.GetBar() < 42; + } + ... +}; +... MakePolymorphicMatcher(MyGreatMatcher()) ... +``` + +For more information, you can read these +[two](CookBook.md#writing-new-monomorphic-matchers) +[recipes](CookBook.md#writing-new-polymorphic-matchers) +from the cookbook. As always, you +are welcome to post questions on `googlemock@googlegroups.com` if you +need any help. + +## When using Google Mock, do I have to use Google Test as the testing framework? I have my favorite testing framework and don't want to switch. ## + +Google Mock works out of the box with Google Test. However, it's easy +to configure it to work with any testing framework of your choice. +[Here](ForDummies.md#using-google-mock-with-any-testing-framework) is how. + +## How am I supposed to make sense of these horrible template errors? ## + +If you are confused by the compiler errors gcc threw at you, +try consulting the _Google Mock Doctor_ tool first. What it does is to +scan stdin for gcc error messages, and spit out diagnoses on the +problems (we call them diseases) your code has. + +To "install", run command: +``` +alias gmd='/scripts/gmock_doctor.py' +``` + +To use it, do: +``` + 2>&1 | gmd +``` + +For example: +``` +make my_test 2>&1 | gmd +``` + +Or you can run `gmd` and copy-n-paste gcc's error messages to it. + +## Can I mock a variadic function? ## + +You cannot mock a variadic function (i.e. a function taking ellipsis +(`...`) arguments) directly in Google Mock. + +The problem is that in general, there is _no way_ for a mock object to +know how many arguments are passed to the variadic method, and what +the arguments' types are. Only the _author of the base class_ knows +the protocol, and we cannot look into their head. + +Therefore, to mock such a function, the _user_ must teach the mock +object how to figure out the number of arguments and their types. One +way to do it is to provide overloaded versions of the function. + +Ellipsis arguments are inherited from C and not really a C++ feature. +They are unsafe to use and don't work with arguments that have +constructors or destructors. Therefore we recommend to avoid them in +C++ as much as possible. + +## MSVC gives me warning C4301 or C4373 when I define a mock method with a const parameter. Why? ## + +If you compile this using Microsoft Visual C++ 2005 SP1: +``` +class Foo { + ... + virtual void Bar(const int i) = 0; +}; + +class MockFoo : public Foo { + ... + MOCK_METHOD1(Bar, void(const int i)); +}; +``` +You may get the following warning: +``` +warning C4301: 'MockFoo::Bar': overriding virtual function only differs from 'Foo::Bar' by const/volatile qualifier +``` + +This is a MSVC bug. The same code compiles fine with gcc ,for +example. If you use Visual C++ 2008 SP1, you would get the warning: +``` +warning C4373: 'MockFoo::Bar': virtual function overrides 'Foo::Bar', previous versions of the compiler did not override when parameters only differed by const/volatile qualifiers +``` + +In C++, if you _declare_ a function with a `const` parameter, the +`const` modifier is _ignored_. Therefore, the `Foo` base class above +is equivalent to: +``` +class Foo { + ... + virtual void Bar(int i) = 0; // int or const int? Makes no difference. +}; +``` + +In fact, you can _declare_ Bar() with an `int` parameter, and _define_ +it with a `const int` parameter. The compiler will still match them +up. + +Since making a parameter `const` is meaningless in the method +_declaration_, we recommend to remove it in both `Foo` and `MockFoo`. +That should workaround the VC bug. + +Note that we are talking about the _top-level_ `const` modifier here. +If the function parameter is passed by pointer or reference, declaring +the _pointee_ or _referee_ as `const` is still meaningful. For +example, the following two declarations are _not_ equivalent: +``` +void Bar(int* p); // Neither p nor *p is const. +void Bar(const int* p); // p is not const, but *p is. +``` + +## I have a huge mock class, and Microsoft Visual C++ runs out of memory when compiling it. What can I do? ## + +We've noticed that when the `/clr` compiler flag is used, Visual C++ +uses 5~6 times as much memory when compiling a mock class. We suggest +to avoid `/clr` when compiling native C++ mocks. + +## I can't figure out why Google Mock thinks my expectations are not satisfied. What should I do? ## + +You might want to run your test with +`--gmock_verbose=info`. This flag lets Google Mock print a trace +of every mock function call it receives. By studying the trace, +you'll gain insights on why the expectations you set are not met. + +## How can I assert that a function is NEVER called? ## + +``` +EXPECT_CALL(foo, Bar(_)) + .Times(0); +``` + +## I have a failed test where Google Mock tells me TWICE that a particular expectation is not satisfied. Isn't this redundant? ## + +When Google Mock detects a failure, it prints relevant information +(the mock function arguments, the state of relevant expectations, and +etc) to help the user debug. If another failure is detected, Google +Mock will do the same, including printing the state of relevant +expectations. + +Sometimes an expectation's state didn't change between two failures, +and you'll see the same description of the state twice. They are +however _not_ redundant, as they refer to _different points in time_. +The fact they are the same _is_ interesting information. + +## I get a heap check failure when using a mock object, but using a real object is fine. What can be wrong? ## + +Does the class (hopefully a pure interface) you are mocking have a +virtual destructor? + +Whenever you derive from a base class, make sure its destructor is +virtual. Otherwise Bad Things will happen. Consider the following +code: + +``` +class Base { + public: + // Not virtual, but should be. + ~Base() { ... } + ... +}; + +class Derived : public Base { + public: + ... + private: + std::string value_; +}; + +... + Base* p = new Derived; + ... + delete p; // Surprise! ~Base() will be called, but ~Derived() will not + // - value_ is leaked. +``` + +By changing `~Base()` to virtual, `~Derived()` will be correctly +called when `delete p` is executed, and the heap checker +will be happy. + +## The "newer expectations override older ones" rule makes writing expectations awkward. Why does Google Mock do that? ## + +When people complain about this, often they are referring to code like: + +``` +// foo.Bar() should be called twice, return 1 the first time, and return +// 2 the second time. However, I have to write the expectations in the +// reverse order. This sucks big time!!! +EXPECT_CALL(foo, Bar()) + .WillOnce(Return(2)) + .RetiresOnSaturation(); +EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .RetiresOnSaturation(); +``` + +The problem is that they didn't pick the **best** way to express the test's +intent. + +By default, expectations don't have to be matched in _any_ particular +order. If you want them to match in a certain order, you need to be +explicit. This is Google Mock's (and jMock's) fundamental philosophy: it's +easy to accidentally over-specify your tests, and we want to make it +harder to do so. + +There are two better ways to write the test spec. You could either +put the expectations in sequence: + +``` +// foo.Bar() should be called twice, return 1 the first time, and return +// 2 the second time. Using a sequence, we can write the expectations +// in their natural order. +{ + InSequence s; + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .RetiresOnSaturation(); + EXPECT_CALL(foo, Bar()) + .WillOnce(Return(2)) + .RetiresOnSaturation(); +} +``` + +or you can put the sequence of actions in the same expectation: + +``` +// foo.Bar() should be called twice, return 1 the first time, and return +// 2 the second time. +EXPECT_CALL(foo, Bar()) + .WillOnce(Return(1)) + .WillOnce(Return(2)) + .RetiresOnSaturation(); +``` + +Back to the original questions: why does Google Mock search the +expectations (and `ON_CALL`s) from back to front? Because this +allows a user to set up a mock's behavior for the common case early +(e.g. in the mock's constructor or the test fixture's set-up phase) +and customize it with more specific rules later. If Google Mock +searches from front to back, this very useful pattern won't be +possible. + +## Google Mock prints a warning when a function without EXPECT\_CALL is called, even if I have set its behavior using ON\_CALL. Would it be reasonable not to show the warning in this case? ## + +When choosing between being neat and being safe, we lean toward the +latter. So the answer is that we think it's better to show the +warning. + +Often people write `ON_CALL`s in the mock object's +constructor or `SetUp()`, as the default behavior rarely changes from +test to test. Then in the test body they set the expectations, which +are often different for each test. Having an `ON_CALL` in the set-up +part of a test doesn't mean that the calls are expected. If there's +no `EXPECT_CALL` and the method is called, it's possibly an error. If +we quietly let the call go through without notifying the user, bugs +may creep in unnoticed. + +If, however, you are sure that the calls are OK, you can write + +``` +EXPECT_CALL(foo, Bar(_)) + .WillRepeatedly(...); +``` + +instead of + +``` +ON_CALL(foo, Bar(_)) + .WillByDefault(...); +``` + +This tells Google Mock that you do expect the calls and no warning should be +printed. + +Also, you can control the verbosity using the `--gmock_verbose` flag. +If you find the output too noisy when debugging, just choose a less +verbose level. + +## How can I delete the mock function's argument in an action? ## + +If you find yourself needing to perform some action that's not +supported by Google Mock directly, remember that you can define your own +actions using +[MakeAction()](CookBook.md#writing-new-actions) or +[MakePolymorphicAction()](CookBook.md#writing_new_polymorphic_actions), +or you can write a stub function and invoke it using +[Invoke()](CookBook.md#using-functions_methods_functors). + +## MOCK\_METHODn()'s second argument looks funny. Why don't you use the MOCK\_METHODn(Method, return\_type, arg\_1, ..., arg\_n) syntax? ## + +What?! I think it's beautiful. :-) + +While which syntax looks more natural is a subjective matter to some +extent, Google Mock's syntax was chosen for several practical advantages it +has. + +Try to mock a function that takes a map as an argument: +``` +virtual int GetSize(const map& m); +``` + +Using the proposed syntax, it would be: +``` +MOCK_METHOD1(GetSize, int, const map& m); +``` + +Guess what? You'll get a compiler error as the compiler thinks that +`const map& m` are **two**, not one, arguments. To work +around this you can use `typedef` to give the map type a name, but +that gets in the way of your work. Google Mock's syntax avoids this +problem as the function's argument types are protected inside a pair +of parentheses: +``` +// This compiles fine. +MOCK_METHOD1(GetSize, int(const map& m)); +``` + +You still need a `typedef` if the return type contains an unprotected +comma, but that's much rarer. + +Other advantages include: + 1. `MOCK_METHOD1(Foo, int, bool)` can leave a reader wonder whether the method returns `int` or `bool`, while there won't be such confusion using Google Mock's syntax. + 1. The way Google Mock describes a function type is nothing new, although many people may not be familiar with it. The same syntax was used in C, and the `function` library in `tr1` uses this syntax extensively. Since `tr1` will become a part of the new version of STL, we feel very comfortable to be consistent with it. + 1. The function type syntax is also used in other parts of Google Mock's API (e.g. the action interface) in order to make the implementation tractable. A user needs to learn it anyway in order to utilize Google Mock's more advanced features. We'd as well stick to the same syntax in `MOCK_METHOD*`! + +## My code calls a static/global function. Can I mock it? ## + +You can, but you need to make some changes. + +In general, if you find yourself needing to mock a static function, +it's a sign that your modules are too tightly coupled (and less +flexible, less reusable, less testable, etc). You are probably better +off defining a small interface and call the function through that +interface, which then can be easily mocked. It's a bit of work +initially, but usually pays for itself quickly. + +This Google Testing Blog +[post](http://googletesting.blogspot.com/2008/06/defeat-static-cling.html) +says it excellently. Check it out. + +## My mock object needs to do complex stuff. It's a lot of pain to specify the actions. Google Mock sucks! ## + +I know it's not a question, but you get an answer for free any way. :-) + +With Google Mock, you can create mocks in C++ easily. And people might be +tempted to use them everywhere. Sometimes they work great, and +sometimes you may find them, well, a pain to use. So, what's wrong in +the latter case? + +When you write a test without using mocks, you exercise the code and +assert that it returns the correct value or that the system is in an +expected state. This is sometimes called "state-based testing". + +Mocks are great for what some call "interaction-based" testing: +instead of checking the system state at the very end, mock objects +verify that they are invoked the right way and report an error as soon +as it arises, giving you a handle on the precise context in which the +error was triggered. This is often more effective and economical to +do than state-based testing. + +If you are doing state-based testing and using a test double just to +simulate the real object, you are probably better off using a fake. +Using a mock in this case causes pain, as it's not a strong point for +mocks to perform complex actions. If you experience this and think +that mocks suck, you are just not using the right tool for your +problem. Or, you might be trying to solve the wrong problem. :-) + +## I got a warning "Uninteresting function call encountered - default action taken.." Should I panic? ## + +By all means, NO! It's just an FYI. + +What it means is that you have a mock function, you haven't set any +expectations on it (by Google Mock's rule this means that you are not +interested in calls to this function and therefore it can be called +any number of times), and it is called. That's OK - you didn't say +it's not OK to call the function! + +What if you actually meant to disallow this function to be called, but +forgot to write `EXPECT_CALL(foo, Bar()).Times(0)`? While +one can argue that it's the user's fault, Google Mock tries to be nice and +prints you a note. + +So, when you see the message and believe that there shouldn't be any +uninteresting calls, you should investigate what's going on. To make +your life easier, Google Mock prints the function name and arguments +when an uninteresting call is encountered. + +## I want to define a custom action. Should I use Invoke() or implement the action interface? ## + +Either way is fine - you want to choose the one that's more convenient +for your circumstance. + +Usually, if your action is for a particular function type, defining it +using `Invoke()` should be easier; if your action can be used in +functions of different types (e.g. if you are defining +`Return(value)`), `MakePolymorphicAction()` is +easiest. Sometimes you want precise control on what types of +functions the action can be used in, and implementing +`ActionInterface` is the way to go here. See the implementation of +`Return()` in `include/gmock/gmock-actions.h` for an example. + +## I'm using the set-argument-pointee action, and the compiler complains about "conflicting return type specified". What does it mean? ## + +You got this error as Google Mock has no idea what value it should return +when the mock method is called. `SetArgPointee()` says what the +side effect is, but doesn't say what the return value should be. You +need `DoAll()` to chain a `SetArgPointee()` with a `Return()`. + +See this [recipe](CookBook.md#mocking_side_effects) for more details and an example. + + +## My question is not in your FAQ! ## + +If you cannot find the answer to your question in this FAQ, there are +some other resources you can use: + + 1. search the mailing list [archive](http://groups.google.com/group/googlemock/topics), + 1. ask it on [googlemock@googlegroups.com](mailto:googlemock@googlegroups.com) and someone will answer it (to prevent spam, we require you to join the [discussion group](http://groups.google.com/group/googlemock) before you can post.). + +Please note that creating an issue in the +[issue tracker](https://github.com/google/googletest/issues) is _not_ +a good way to get your answer, as it is monitored infrequently by a +very small number of people. + +When asking a question, it's helpful to provide as much of the +following information as possible (people cannot help you if there's +not enough information in your question): + + * the version (or the revision number if you check out from SVN directly) of Google Mock you use (Google Mock is under active development, so it's possible that your problem has been solved in a later version), + * your operating system, + * the name and version of your compiler, + * the complete command line flags you give to your compiler, + * the complete compiler error messages (if the question is about compilation), + * the _actual_ code (ideally, a minimal but complete program) that has the problem you encounter. diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/docs/KnownIssues.md b/deps/rapidjson/thirdparty/gtest/googlemock/docs/KnownIssues.md new file mode 100644 index 0000000..adadf51 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/docs/KnownIssues.md @@ -0,0 +1,19 @@ +As any non-trivial software system, Google Mock has some known limitations and problems. We are working on improving it, and welcome your help! The follow is a list of issues we know about. + + + +## README contains outdated information on Google Mock's compatibility with other testing frameworks ## + +The `README` file in release 1.1.0 still says that Google Mock only works with Google Test. Actually, you can configure Google Mock to work with any testing framework you choose. + +## Tests failing on machines using Power PC CPUs (e.g. some Macs) ## + +`gmock_output_test` and `gmock-printers_test` are known to fail with Power PC CPUs. This is due to portability issues with these tests, and is not an indication of problems in Google Mock itself. You can safely ignore them. + +## Failed to resolve libgtest.so.0 in tests when built against installed Google Test ## + +This only applies if you manually built and installed Google Test, and then built a Google Mock against it (either explicitly, or because gtest-config was in your path post-install). In this situation, Libtool has a known issue with certain systems' ldconfig setup: + +http://article.gmane.org/gmane.comp.sysutils.automake.general/9025 + +This requires a manual run of "sudo ldconfig" after the "sudo make install" for Google Test before any binaries which link against it can be executed. This isn't a bug in our install, but we should at least have documented it or hacked a work-around into our install. We should have one of these solutions in our next release. \ No newline at end of file diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-actions.h b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-actions.h new file mode 100644 index 0000000..a2784f6 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-actions.h @@ -0,0 +1,1262 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used actions. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ + +#ifndef _WIN32_WCE +# include +#endif + +#include +#include + +#include "gmock/internal/gmock-internal-utils.h" +#include "gmock/internal/gmock-port.h" + +#if GTEST_LANG_CXX11 // Defined by gtest-port.h via gmock-port.h. +#include +#include +#endif // GTEST_LANG_CXX11 + +namespace testing { + +// To implement an action Foo, define: +// 1. a class FooAction that implements the ActionInterface interface, and +// 2. a factory function that creates an Action object from a +// const FooAction*. +// +// The two-level delegation design follows that of Matcher, providing +// consistency for extension developers. It also eases ownership +// management as Action objects can now be copied like plain values. + +namespace internal { + +template +class ActionAdaptor; + +// BuiltInDefaultValueGetter::Get() returns a +// default-constructed T value. BuiltInDefaultValueGetter::Get() crashes with an error. +// +// This primary template is used when kDefaultConstructible is true. +template +struct BuiltInDefaultValueGetter { + static T Get() { return T(); } +}; +template +struct BuiltInDefaultValueGetter { + static T Get() { + Assert(false, __FILE__, __LINE__, + "Default action undefined for the function return type."); + return internal::Invalid(); + // The above statement will never be reached, but is required in + // order for this function to compile. + } +}; + +// BuiltInDefaultValue::Get() returns the "built-in" default value +// for type T, which is NULL when T is a raw pointer type, 0 when T is +// a numeric type, false when T is bool, or "" when T is string or +// std::string. In addition, in C++11 and above, it turns a +// default-constructed T value if T is default constructible. For any +// other type T, the built-in default T value is undefined, and the +// function will abort the process. +template +class BuiltInDefaultValue { + public: +#if GTEST_LANG_CXX11 + // This function returns true iff type T has a built-in default value. + static bool Exists() { + return ::std::is_default_constructible::value; + } + + static T Get() { + return BuiltInDefaultValueGetter< + T, ::std::is_default_constructible::value>::Get(); + } + +#else // GTEST_LANG_CXX11 + // This function returns true iff type T has a built-in default value. + static bool Exists() { + return false; + } + + static T Get() { + return BuiltInDefaultValueGetter::Get(); + } + +#endif // GTEST_LANG_CXX11 +}; + +// This partial specialization says that we use the same built-in +// default value for T and const T. +template +class BuiltInDefaultValue { + public: + static bool Exists() { return BuiltInDefaultValue::Exists(); } + static T Get() { return BuiltInDefaultValue::Get(); } +}; + +// This partial specialization defines the default values for pointer +// types. +template +class BuiltInDefaultValue { + public: + static bool Exists() { return true; } + static T* Get() { return NULL; } +}; + +// The following specializations define the default values for +// specific types we care about. +#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \ + template <> \ + class BuiltInDefaultValue { \ + public: \ + static bool Exists() { return true; } \ + static type Get() { return value; } \ + } + +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT +#if GTEST_HAS_GLOBAL_STRING +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::string, ""); +#endif // GTEST_HAS_GLOBAL_STRING +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, ""); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0'); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0'); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0'); + +// There's no need for a default action for signed wchar_t, as that +// type is the same as wchar_t for gcc, and invalid for MSVC. +// +// There's also no need for a default action for unsigned wchar_t, as +// that type is the same as unsigned int for gcc, and invalid for +// MSVC. +#if GMOCK_WCHAR_T_IS_NATIVE_ +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U); // NOLINT +#endif + +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(UInt64, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(Int64, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0); + +#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_ + +} // namespace internal + +// When an unexpected function call is encountered, Google Mock will +// let it return a default value if the user has specified one for its +// return type, or if the return type has a built-in default value; +// otherwise Google Mock won't know what value to return and will have +// to abort the process. +// +// The DefaultValue class allows a user to specify the +// default value for a type T that is both copyable and publicly +// destructible (i.e. anything that can be used as a function return +// type). The usage is: +// +// // Sets the default value for type T to be foo. +// DefaultValue::Set(foo); +template +class DefaultValue { + public: + // Sets the default value for type T; requires T to be + // copy-constructable and have a public destructor. + static void Set(T x) { + delete producer_; + producer_ = new FixedValueProducer(x); + } + + // Provides a factory function to be called to generate the default value. + // This method can be used even if T is only move-constructible, but it is not + // limited to that case. + typedef T (*FactoryFunction)(); + static void SetFactory(FactoryFunction factory) { + delete producer_; + producer_ = new FactoryValueProducer(factory); + } + + // Unsets the default value for type T. + static void Clear() { + delete producer_; + producer_ = NULL; + } + + // Returns true iff the user has set the default value for type T. + static bool IsSet() { return producer_ != NULL; } + + // Returns true if T has a default return value set by the user or there + // exists a built-in default value. + static bool Exists() { + return IsSet() || internal::BuiltInDefaultValue::Exists(); + } + + // Returns the default value for type T if the user has set one; + // otherwise returns the built-in default value. Requires that Exists() + // is true, which ensures that the return value is well-defined. + static T Get() { + return producer_ == NULL ? + internal::BuiltInDefaultValue::Get() : producer_->Produce(); + } + + private: + class ValueProducer { + public: + virtual ~ValueProducer() {} + virtual T Produce() = 0; + }; + + class FixedValueProducer : public ValueProducer { + public: + explicit FixedValueProducer(T value) : value_(value) {} + virtual T Produce() { return value_; } + + private: + const T value_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(FixedValueProducer); + }; + + class FactoryValueProducer : public ValueProducer { + public: + explicit FactoryValueProducer(FactoryFunction factory) + : factory_(factory) {} + virtual T Produce() { return factory_(); } + + private: + const FactoryFunction factory_; + GTEST_DISALLOW_COPY_AND_ASSIGN_(FactoryValueProducer); + }; + + static ValueProducer* producer_; +}; + +// This partial specialization allows a user to set default values for +// reference types. +template +class DefaultValue { + public: + // Sets the default value for type T&. + static void Set(T& x) { // NOLINT + address_ = &x; + } + + // Unsets the default value for type T&. + static void Clear() { + address_ = NULL; + } + + // Returns true iff the user has set the default value for type T&. + static bool IsSet() { return address_ != NULL; } + + // Returns true if T has a default return value set by the user or there + // exists a built-in default value. + static bool Exists() { + return IsSet() || internal::BuiltInDefaultValue::Exists(); + } + + // Returns the default value for type T& if the user has set one; + // otherwise returns the built-in default value if there is one; + // otherwise aborts the process. + static T& Get() { + return address_ == NULL ? + internal::BuiltInDefaultValue::Get() : *address_; + } + + private: + static T* address_; +}; + +// This specialization allows DefaultValue::Get() to +// compile. +template <> +class DefaultValue { + public: + static bool Exists() { return true; } + static void Get() {} +}; + +// Points to the user-set default value for type T. +template +typename DefaultValue::ValueProducer* DefaultValue::producer_ = NULL; + +// Points to the user-set default value for type T&. +template +T* DefaultValue::address_ = NULL; + +// Implement this interface to define an action for function type F. +template +class ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + ActionInterface() {} + virtual ~ActionInterface() {} + + // Performs the action. This method is not const, as in general an + // action can have side effects and be stateful. For example, a + // get-the-next-element-from-the-collection action will need to + // remember the current element. + virtual Result Perform(const ArgumentTuple& args) = 0; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface); +}; + +// An Action is a copyable and IMMUTABLE (except by assignment) +// object that represents an action to be taken when a mock function +// of type F is called. The implementation of Action is just a +// linked_ptr to const ActionInterface, so copying is fairly cheap. +// Don't inherit from Action! +// +// You can view an object implementing ActionInterface as a +// concrete action (including its current state), and an Action +// object as a handle to it. +template +class Action { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + // Constructs a null Action. Needed for storing Action objects in + // STL containers. + Action() {} + +#if GTEST_LANG_CXX11 + // Construct an Action from a specified callable. + // This cannot take std::function directly, because then Action would not be + // directly constructible from lambda (it would require two conversions). + template , G>::value>::type> + Action(G&& fun) : fun_(::std::forward(fun)) {} // NOLINT +#endif + + // Constructs an Action from its implementation. + explicit Action(ActionInterface* impl) : impl_(impl) {} + + // This constructor allows us to turn an Action object into an + // Action, as long as F's arguments can be implicitly converted + // to Func's and Func's return type can be implicitly converted to + // F's. + template + explicit Action(const Action& action); + + // Returns true iff this is the DoDefault() action. + bool IsDoDefault() const { +#if GTEST_LANG_CXX11 + return impl_ == nullptr && fun_ == nullptr; +#else + return impl_ == NULL; +#endif + } + + // Performs the action. Note that this method is const even though + // the corresponding method in ActionInterface is not. The reason + // is that a const Action means that it cannot be re-bound to + // another concrete action, not that the concrete action it binds to + // cannot change state. (Think of the difference between a const + // pointer and a pointer to const.) + Result Perform(ArgumentTuple args) const { + if (IsDoDefault()) { + internal::IllegalDoDefault(__FILE__, __LINE__); + } +#if GTEST_LANG_CXX11 + if (fun_ != nullptr) { + return internal::Apply(fun_, ::std::move(args)); + } +#endif + return impl_->Perform(args); + } + + private: + template + friend class internal::ActionAdaptor; + + template + friend class Action; + + // In C++11, Action can be implemented either as a generic functor (through + // std::function), or legacy ActionInterface. In C++98, only ActionInterface + // is available. The invariants are as follows: + // * in C++98, impl_ is null iff this is the default action + // * in C++11, at most one of fun_ & impl_ may be nonnull; both are null iff + // this is the default action +#if GTEST_LANG_CXX11 + ::std::function fun_; +#endif + internal::linked_ptr > impl_; +}; + +// The PolymorphicAction class template makes it easy to implement a +// polymorphic action (i.e. an action that can be used in mock +// functions of than one type, e.g. Return()). +// +// To define a polymorphic action, a user first provides a COPYABLE +// implementation class that has a Perform() method template: +// +// class FooAction { +// public: +// template +// Result Perform(const ArgumentTuple& args) const { +// // Processes the arguments and returns a result, using +// // tr1::get(args) to get the N-th (0-based) argument in the tuple. +// } +// ... +// }; +// +// Then the user creates the polymorphic action using +// MakePolymorphicAction(object) where object has type FooAction. See +// the definition of Return(void) and SetArgumentPointee(value) for +// complete examples. +template +class PolymorphicAction { + public: + explicit PolymorphicAction(const Impl& impl) : impl_(impl) {} + + template + operator Action() const { + return Action(new MonomorphicImpl(impl_)); + } + + private: + template + class MonomorphicImpl : public ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} + + virtual Result Perform(const ArgumentTuple& args) { + return impl_.template Perform(args); + } + + private: + Impl impl_; + + GTEST_DISALLOW_ASSIGN_(MonomorphicImpl); + }; + + Impl impl_; + + GTEST_DISALLOW_ASSIGN_(PolymorphicAction); +}; + +// Creates an Action from its implementation and returns it. The +// created Action object owns the implementation. +template +Action MakeAction(ActionInterface* impl) { + return Action(impl); +} + +// Creates a polymorphic action from its implementation. This is +// easier to use than the PolymorphicAction constructor as it +// doesn't require you to explicitly write the template argument, e.g. +// +// MakePolymorphicAction(foo); +// vs +// PolymorphicAction(foo); +template +inline PolymorphicAction MakePolymorphicAction(const Impl& impl) { + return PolymorphicAction(impl); +} + +namespace internal { + +// Allows an Action object to pose as an Action, as long as F2 +// and F1 are compatible. +template +class ActionAdaptor : public ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + explicit ActionAdaptor(const Action& from) : impl_(from.impl_) {} + + virtual Result Perform(const ArgumentTuple& args) { + return impl_->Perform(args); + } + + private: + const internal::linked_ptr > impl_; + + GTEST_DISALLOW_ASSIGN_(ActionAdaptor); +}; + +// Helper struct to specialize ReturnAction to execute a move instead of a copy +// on return. Useful for move-only types, but could be used on any type. +template +struct ByMoveWrapper { + explicit ByMoveWrapper(T value) : payload(internal::move(value)) {} + T payload; +}; + +// Implements the polymorphic Return(x) action, which can be used in +// any function that returns the type of x, regardless of the argument +// types. +// +// Note: The value passed into Return must be converted into +// Function::Result when this action is cast to Action rather than +// when that action is performed. This is important in scenarios like +// +// MOCK_METHOD1(Method, T(U)); +// ... +// { +// Foo foo; +// X x(&foo); +// EXPECT_CALL(mock, Method(_)).WillOnce(Return(x)); +// } +// +// In the example above the variable x holds reference to foo which leaves +// scope and gets destroyed. If copying X just copies a reference to foo, +// that copy will be left with a hanging reference. If conversion to T +// makes a copy of foo, the above code is safe. To support that scenario, we +// need to make sure that the type conversion happens inside the EXPECT_CALL +// statement, and conversion of the result of Return to Action is a +// good place for that. +// +// The real life example of the above scenario happens when an invocation +// of gtl::Container() is passed into Return. +// +template +class ReturnAction { + public: + // Constructs a ReturnAction object from the value to be returned. + // 'value' is passed by value instead of by const reference in order + // to allow Return("string literal") to compile. + explicit ReturnAction(R value) : value_(new R(internal::move(value))) {} + + // This template type conversion operator allows Return(x) to be + // used in ANY function that returns x's type. + template + operator Action() const { + // Assert statement belongs here because this is the best place to verify + // conditions on F. It produces the clearest error messages + // in most compilers. + // Impl really belongs in this scope as a local class but can't + // because MSVC produces duplicate symbols in different translation units + // in this case. Until MS fixes that bug we put Impl into the class scope + // and put the typedef both here (for use in assert statement) and + // in the Impl class. But both definitions must be the same. + typedef typename Function::Result Result; + GTEST_COMPILE_ASSERT_( + !is_reference::value, + use_ReturnRef_instead_of_Return_to_return_a_reference); + return Action(new Impl(value_)); + } + + private: + // Implements the Return(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + // The implicit cast is necessary when Result has more than one + // single-argument constructor (e.g. Result is std::vector) and R + // has a type conversion operator template. In that case, value_(value) + // won't compile as the compiler doesn't known which constructor of + // Result to call. ImplicitCast_ forces the compiler to convert R to + // Result without considering explicit constructors, thus resolving the + // ambiguity. value_ is then initialized using its copy constructor. + explicit Impl(const linked_ptr& value) + : value_before_cast_(*value), + value_(ImplicitCast_(value_before_cast_)) {} + + virtual Result Perform(const ArgumentTuple&) { return value_; } + + private: + GTEST_COMPILE_ASSERT_(!is_reference::value, + Result_cannot_be_a_reference_type); + // We save the value before casting just in case it is being cast to a + // wrapper type. + R value_before_cast_; + Result value_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); + }; + + // Partially specialize for ByMoveWrapper. This version of ReturnAction will + // move its contents instead. + template + class Impl, F> : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const linked_ptr& wrapper) + : performed_(false), wrapper_(wrapper) {} + + virtual Result Perform(const ArgumentTuple&) { + GTEST_CHECK_(!performed_) + << "A ByMove() action should only be performed once."; + performed_ = true; + return internal::move(wrapper_->payload); + } + + private: + bool performed_; + const linked_ptr wrapper_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + const linked_ptr value_; + + GTEST_DISALLOW_ASSIGN_(ReturnAction); +}; + +// Implements the ReturnNull() action. +class ReturnNullAction { + public: + // Allows ReturnNull() to be used in any pointer-returning function. In C++11 + // this is enforced by returning nullptr, and in non-C++11 by asserting a + // pointer type on compile time. + template + static Result Perform(const ArgumentTuple&) { +#if GTEST_LANG_CXX11 + return nullptr; +#else + GTEST_COMPILE_ASSERT_(internal::is_pointer::value, + ReturnNull_can_be_used_to_return_a_pointer_only); + return NULL; +#endif // GTEST_LANG_CXX11 + } +}; + +// Implements the Return() action. +class ReturnVoidAction { + public: + // Allows Return() to be used in any void-returning function. + template + static void Perform(const ArgumentTuple&) { + CompileAssertTypesEqual(); + } +}; + +// Implements the polymorphic ReturnRef(x) action, which can be used +// in any function that returns a reference to the type of x, +// regardless of the argument types. +template +class ReturnRefAction { + public: + // Constructs a ReturnRefAction object from the reference to be returned. + explicit ReturnRefAction(T& ref) : ref_(ref) {} // NOLINT + + // This template type conversion operator allows ReturnRef(x) to be + // used in ANY function that returns a reference to x's type. + template + operator Action() const { + typedef typename Function::Result Result; + // Asserts that the function return type is a reference. This + // catches the user error of using ReturnRef(x) when Return(x) + // should be used, and generates some helpful error message. + GTEST_COMPILE_ASSERT_(internal::is_reference::value, + use_Return_instead_of_ReturnRef_to_return_a_value); + return Action(new Impl(ref_)); + } + + private: + // Implements the ReturnRef(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(T& ref) : ref_(ref) {} // NOLINT + + virtual Result Perform(const ArgumentTuple&) { + return ref_; + } + + private: + T& ref_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + T& ref_; + + GTEST_DISALLOW_ASSIGN_(ReturnRefAction); +}; + +// Implements the polymorphic ReturnRefOfCopy(x) action, which can be +// used in any function that returns a reference to the type of x, +// regardless of the argument types. +template +class ReturnRefOfCopyAction { + public: + // Constructs a ReturnRefOfCopyAction object from the reference to + // be returned. + explicit ReturnRefOfCopyAction(const T& value) : value_(value) {} // NOLINT + + // This template type conversion operator allows ReturnRefOfCopy(x) to be + // used in ANY function that returns a reference to x's type. + template + operator Action() const { + typedef typename Function::Result Result; + // Asserts that the function return type is a reference. This + // catches the user error of using ReturnRefOfCopy(x) when Return(x) + // should be used, and generates some helpful error message. + GTEST_COMPILE_ASSERT_( + internal::is_reference::value, + use_Return_instead_of_ReturnRefOfCopy_to_return_a_value); + return Action(new Impl(value_)); + } + + private: + // Implements the ReturnRefOfCopy(x) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const T& value) : value_(value) {} // NOLINT + + virtual Result Perform(const ArgumentTuple&) { + return value_; + } + + private: + T value_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + const T value_; + + GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction); +}; + +// Implements the polymorphic DoDefault() action. +class DoDefaultAction { + public: + // This template type conversion operator allows DoDefault() to be + // used in any function. + template + operator Action() const { return Action(); } // NOLINT +}; + +// Implements the Assign action to set a given pointer referent to a +// particular value. +template +class AssignAction { + public: + AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {} + + template + void Perform(const ArgumentTuple& /* args */) const { + *ptr_ = value_; + } + + private: + T1* const ptr_; + const T2 value_; + + GTEST_DISALLOW_ASSIGN_(AssignAction); +}; + +#if !GTEST_OS_WINDOWS_MOBILE + +// Implements the SetErrnoAndReturn action to simulate return from +// various system calls and libc functions. +template +class SetErrnoAndReturnAction { + public: + SetErrnoAndReturnAction(int errno_value, T result) + : errno_(errno_value), + result_(result) {} + template + Result Perform(const ArgumentTuple& /* args */) const { + errno = errno_; + return result_; + } + + private: + const int errno_; + const T result_; + + GTEST_DISALLOW_ASSIGN_(SetErrnoAndReturnAction); +}; + +#endif // !GTEST_OS_WINDOWS_MOBILE + +// Implements the SetArgumentPointee(x) action for any function +// whose N-th argument (0-based) is a pointer to x's type. The +// template parameter kIsProto is true iff type A is ProtocolMessage, +// proto2::Message, or a sub-class of those. +template +class SetArgumentPointeeAction { + public: + // Constructs an action that sets the variable pointed to by the + // N-th function argument to 'value'. + explicit SetArgumentPointeeAction(const A& value) : value_(value) {} + + template + void Perform(const ArgumentTuple& args) const { + CompileAssertTypesEqual(); + *::testing::get(args) = value_; + } + + private: + const A value_; + + GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction); +}; + +template +class SetArgumentPointeeAction { + public: + // Constructs an action that sets the variable pointed to by the + // N-th function argument to 'proto'. Both ProtocolMessage and + // proto2::Message have the CopyFrom() method, so the same + // implementation works for both. + explicit SetArgumentPointeeAction(const Proto& proto) : proto_(new Proto) { + proto_->CopyFrom(proto); + } + + template + void Perform(const ArgumentTuple& args) const { + CompileAssertTypesEqual(); + ::testing::get(args)->CopyFrom(*proto_); + } + + private: + const internal::linked_ptr proto_; + + GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction); +}; + +// Implements the InvokeWithoutArgs(f) action. The template argument +// FunctionImpl is the implementation type of f, which can be either a +// function pointer or a functor. InvokeWithoutArgs(f) can be used as an +// Action as long as f's type is compatible with F (i.e. f can be +// assigned to a tr1::function). +template +class InvokeWithoutArgsAction { + public: + // The c'tor makes a copy of function_impl (either a function + // pointer or a functor). + explicit InvokeWithoutArgsAction(FunctionImpl function_impl) + : function_impl_(function_impl) {} + + // Allows InvokeWithoutArgs(f) to be used as any action whose type is + // compatible with f. + template + Result Perform(const ArgumentTuple&) { return function_impl_(); } + + private: + FunctionImpl function_impl_; + + GTEST_DISALLOW_ASSIGN_(InvokeWithoutArgsAction); +}; + +// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action. +template +class InvokeMethodWithoutArgsAction { + public: + InvokeMethodWithoutArgsAction(Class* obj_ptr, MethodPtr method_ptr) + : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {} + + template + Result Perform(const ArgumentTuple&) const { + return (obj_ptr_->*method_ptr_)(); + } + + private: + Class* const obj_ptr_; + const MethodPtr method_ptr_; + + GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction); +}; + +// Implements the InvokeWithoutArgs(callback) action. +template +class InvokeCallbackWithoutArgsAction { + public: + // The c'tor takes ownership of the callback. + explicit InvokeCallbackWithoutArgsAction(CallbackType* callback) + : callback_(callback) { + callback->CheckIsRepeatable(); // Makes sure the callback is permanent. + } + + // This type conversion operator template allows Invoke(callback) to + // be used wherever the callback's return type can be implicitly + // converted to that of the mock function. + template + Result Perform(const ArgumentTuple&) const { return callback_->Run(); } + + private: + const internal::linked_ptr callback_; + + GTEST_DISALLOW_ASSIGN_(InvokeCallbackWithoutArgsAction); +}; + +// Implements the IgnoreResult(action) action. +template +class IgnoreResultAction { + public: + explicit IgnoreResultAction(const A& action) : action_(action) {} + + template + operator Action() const { + // Assert statement belongs here because this is the best place to verify + // conditions on F. It produces the clearest error messages + // in most compilers. + // Impl really belongs in this scope as a local class but can't + // because MSVC produces duplicate symbols in different translation units + // in this case. Until MS fixes that bug we put Impl into the class scope + // and put the typedef both here (for use in assert statement) and + // in the Impl class. But both definitions must be the same. + typedef typename internal::Function::Result Result; + + // Asserts at compile time that F returns void. + CompileAssertTypesEqual(); + + return Action(new Impl(action_)); + } + + private: + template + class Impl : public ActionInterface { + public: + typedef typename internal::Function::Result Result; + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const A& action) : action_(action) {} + + virtual void Perform(const ArgumentTuple& args) { + // Performs the action and ignores its result. + action_.Perform(args); + } + + private: + // Type OriginalFunction is the same as F except that its return + // type is IgnoredValue. + typedef typename internal::Function::MakeResultIgnoredValue + OriginalFunction; + + const Action action_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + const A action_; + + GTEST_DISALLOW_ASSIGN_(IgnoreResultAction); +}; + +// A ReferenceWrapper object represents a reference to type T, +// which can be either const or not. It can be explicitly converted +// from, and implicitly converted to, a T&. Unlike a reference, +// ReferenceWrapper can be copied and can survive template type +// inference. This is used to support by-reference arguments in the +// InvokeArgument(...) action. The idea was from "reference +// wrappers" in tr1, which we don't have in our source tree yet. +template +class ReferenceWrapper { + public: + // Constructs a ReferenceWrapper object from a T&. + explicit ReferenceWrapper(T& l_value) : pointer_(&l_value) {} // NOLINT + + // Allows a ReferenceWrapper object to be implicitly converted to + // a T&. + operator T&() const { return *pointer_; } + private: + T* pointer_; +}; + +// Allows the expression ByRef(x) to be printed as a reference to x. +template +void PrintTo(const ReferenceWrapper& ref, ::std::ostream* os) { + T& value = ref; + UniversalPrinter::Print(value, os); +} + +// Does two actions sequentially. Used for implementing the DoAll(a1, +// a2, ...) action. +template +class DoBothAction { + public: + DoBothAction(Action1 action1, Action2 action2) + : action1_(action1), action2_(action2) {} + + // This template type conversion operator allows DoAll(a1, ..., a_n) + // to be used in ANY function of compatible type. + template + operator Action() const { + return Action(new Impl(action1_, action2_)); + } + + private: + // Implements the DoAll(...) action for a particular function type F. + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + typedef typename Function::MakeResultVoid VoidResult; + + Impl(const Action& action1, const Action& action2) + : action1_(action1), action2_(action2) {} + + virtual Result Perform(const ArgumentTuple& args) { + action1_.Perform(args); + return action2_.Perform(args); + } + + private: + const Action action1_; + const Action action2_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + Action1 action1_; + Action2 action2_; + + GTEST_DISALLOW_ASSIGN_(DoBothAction); +}; + +} // namespace internal + +// An Unused object can be implicitly constructed from ANY value. +// This is handy when defining actions that ignore some or all of the +// mock function arguments. For example, given +// +// MOCK_METHOD3(Foo, double(const string& label, double x, double y)); +// MOCK_METHOD3(Bar, double(int index, double x, double y)); +// +// instead of +// +// double DistanceToOriginWithLabel(const string& label, double x, double y) { +// return sqrt(x*x + y*y); +// } +// double DistanceToOriginWithIndex(int index, double x, double y) { +// return sqrt(x*x + y*y); +// } +// ... +// EXPECT_CALL(mock, Foo("abc", _, _)) +// .WillOnce(Invoke(DistanceToOriginWithLabel)); +// EXPECT_CALL(mock, Bar(5, _, _)) +// .WillOnce(Invoke(DistanceToOriginWithIndex)); +// +// you could write +// +// // We can declare any uninteresting argument as Unused. +// double DistanceToOrigin(Unused, double x, double y) { +// return sqrt(x*x + y*y); +// } +// ... +// EXPECT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin)); +// EXPECT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin)); +typedef internal::IgnoredValue Unused; + +// This constructor allows us to turn an Action object into an +// Action, as long as To's arguments can be implicitly converted +// to From's and From's return type cann be implicitly converted to +// To's. +template +template +Action::Action(const Action& from) + : +#if GTEST_LANG_CXX11 + fun_(from.fun_), +#endif + impl_(from.impl_ == NULL ? NULL + : new internal::ActionAdaptor(from)) { +} + +// Creates an action that returns 'value'. 'value' is passed by value +// instead of const reference - otherwise Return("string literal") +// will trigger a compiler error about using array as initializer. +template +internal::ReturnAction Return(R value) { + return internal::ReturnAction(internal::move(value)); +} + +// Creates an action that returns NULL. +inline PolymorphicAction ReturnNull() { + return MakePolymorphicAction(internal::ReturnNullAction()); +} + +// Creates an action that returns from a void function. +inline PolymorphicAction Return() { + return MakePolymorphicAction(internal::ReturnVoidAction()); +} + +// Creates an action that returns the reference to a variable. +template +inline internal::ReturnRefAction ReturnRef(R& x) { // NOLINT + return internal::ReturnRefAction(x); +} + +// Creates an action that returns the reference to a copy of the +// argument. The copy is created when the action is constructed and +// lives as long as the action. +template +inline internal::ReturnRefOfCopyAction ReturnRefOfCopy(const R& x) { + return internal::ReturnRefOfCopyAction(x); +} + +// Modifies the parent action (a Return() action) to perform a move of the +// argument instead of a copy. +// Return(ByMove()) actions can only be executed once and will assert this +// invariant. +template +internal::ByMoveWrapper ByMove(R x) { + return internal::ByMoveWrapper(internal::move(x)); +} + +// Creates an action that does the default action for the give mock function. +inline internal::DoDefaultAction DoDefault() { + return internal::DoDefaultAction(); +} + +// Creates an action that sets the variable pointed by the N-th +// (0-based) function argument to 'value'. +template +PolymorphicAction< + internal::SetArgumentPointeeAction< + N, T, internal::IsAProtocolMessage::value> > +SetArgPointee(const T& x) { + return MakePolymorphicAction(internal::SetArgumentPointeeAction< + N, T, internal::IsAProtocolMessage::value>(x)); +} + +#if !((GTEST_GCC_VER_ && GTEST_GCC_VER_ < 40000) || GTEST_OS_SYMBIAN) +// This overload allows SetArgPointee() to accept a string literal. +// GCC prior to the version 4.0 and Symbian C++ compiler cannot distinguish +// this overload from the templated version and emit a compile error. +template +PolymorphicAction< + internal::SetArgumentPointeeAction > +SetArgPointee(const char* p) { + return MakePolymorphicAction(internal::SetArgumentPointeeAction< + N, const char*, false>(p)); +} + +template +PolymorphicAction< + internal::SetArgumentPointeeAction > +SetArgPointee(const wchar_t* p) { + return MakePolymorphicAction(internal::SetArgumentPointeeAction< + N, const wchar_t*, false>(p)); +} +#endif + +// The following version is DEPRECATED. +template +PolymorphicAction< + internal::SetArgumentPointeeAction< + N, T, internal::IsAProtocolMessage::value> > +SetArgumentPointee(const T& x) { + return MakePolymorphicAction(internal::SetArgumentPointeeAction< + N, T, internal::IsAProtocolMessage::value>(x)); +} + +// Creates an action that sets a pointer referent to a given value. +template +PolymorphicAction > Assign(T1* ptr, T2 val) { + return MakePolymorphicAction(internal::AssignAction(ptr, val)); +} + +#if !GTEST_OS_WINDOWS_MOBILE + +// Creates an action that sets errno and returns the appropriate error. +template +PolymorphicAction > +SetErrnoAndReturn(int errval, T result) { + return MakePolymorphicAction( + internal::SetErrnoAndReturnAction(errval, result)); +} + +#endif // !GTEST_OS_WINDOWS_MOBILE + +// Various overloads for InvokeWithoutArgs(). + +// Creates an action that invokes 'function_impl' with no argument. +template +PolymorphicAction > +InvokeWithoutArgs(FunctionImpl function_impl) { + return MakePolymorphicAction( + internal::InvokeWithoutArgsAction(function_impl)); +} + +// Creates an action that invokes the given method on the given object +// with no argument. +template +PolymorphicAction > +InvokeWithoutArgs(Class* obj_ptr, MethodPtr method_ptr) { + return MakePolymorphicAction( + internal::InvokeMethodWithoutArgsAction( + obj_ptr, method_ptr)); +} + +// Creates an action that performs an_action and throws away its +// result. In other words, it changes the return type of an_action to +// void. an_action MUST NOT return void, or the code won't compile. +template +inline internal::IgnoreResultAction IgnoreResult(const A& an_action) { + return internal::IgnoreResultAction(an_action); +} + +// Creates a reference wrapper for the given L-value. If necessary, +// you can explicitly specify the type of the reference. For example, +// suppose 'derived' is an object of type Derived, ByRef(derived) +// would wrap a Derived&. If you want to wrap a const Base& instead, +// where Base is a base class of Derived, just write: +// +// ByRef(derived) +template +inline internal::ReferenceWrapper ByRef(T& l_value) { // NOLINT + return internal::ReferenceWrapper(l_value); +} + +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-cardinalities.h b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-cardinalities.h new file mode 100644 index 0000000..fc315f9 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-cardinalities.h @@ -0,0 +1,147 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used cardinalities. More +// cardinalities can be defined by the user implementing the +// CardinalityInterface interface if necessary. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ + +#include +#include // NOLINT +#include "gmock/internal/gmock-port.h" +#include "gtest/gtest.h" + +namespace testing { + +// To implement a cardinality Foo, define: +// 1. a class FooCardinality that implements the +// CardinalityInterface interface, and +// 2. a factory function that creates a Cardinality object from a +// const FooCardinality*. +// +// The two-level delegation design follows that of Matcher, providing +// consistency for extension developers. It also eases ownership +// management as Cardinality objects can now be copied like plain values. + +// The implementation of a cardinality. +class CardinalityInterface { + public: + virtual ~CardinalityInterface() {} + + // Conservative estimate on the lower/upper bound of the number of + // calls allowed. + virtual int ConservativeLowerBound() const { return 0; } + virtual int ConservativeUpperBound() const { return INT_MAX; } + + // Returns true iff call_count calls will satisfy this cardinality. + virtual bool IsSatisfiedByCallCount(int call_count) const = 0; + + // Returns true iff call_count calls will saturate this cardinality. + virtual bool IsSaturatedByCallCount(int call_count) const = 0; + + // Describes self to an ostream. + virtual void DescribeTo(::std::ostream* os) const = 0; +}; + +// A Cardinality is a copyable and IMMUTABLE (except by assignment) +// object that specifies how many times a mock function is expected to +// be called. The implementation of Cardinality is just a linked_ptr +// to const CardinalityInterface, so copying is fairly cheap. +// Don't inherit from Cardinality! +class GTEST_API_ Cardinality { + public: + // Constructs a null cardinality. Needed for storing Cardinality + // objects in STL containers. + Cardinality() {} + + // Constructs a Cardinality from its implementation. + explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {} + + // Conservative estimate on the lower/upper bound of the number of + // calls allowed. + int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); } + int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); } + + // Returns true iff call_count calls will satisfy this cardinality. + bool IsSatisfiedByCallCount(int call_count) const { + return impl_->IsSatisfiedByCallCount(call_count); + } + + // Returns true iff call_count calls will saturate this cardinality. + bool IsSaturatedByCallCount(int call_count) const { + return impl_->IsSaturatedByCallCount(call_count); + } + + // Returns true iff call_count calls will over-saturate this + // cardinality, i.e. exceed the maximum number of allowed calls. + bool IsOverSaturatedByCallCount(int call_count) const { + return impl_->IsSaturatedByCallCount(call_count) && + !impl_->IsSatisfiedByCallCount(call_count); + } + + // Describes self to an ostream + void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + + // Describes the given actual call count to an ostream. + static void DescribeActualCallCountTo(int actual_call_count, + ::std::ostream* os); + + private: + internal::linked_ptr impl_; +}; + +// Creates a cardinality that allows at least n calls. +GTEST_API_ Cardinality AtLeast(int n); + +// Creates a cardinality that allows at most n calls. +GTEST_API_ Cardinality AtMost(int n); + +// Creates a cardinality that allows any number of calls. +GTEST_API_ Cardinality AnyNumber(); + +// Creates a cardinality that allows between min and max calls. +GTEST_API_ Cardinality Between(int min, int max); + +// Creates a cardinality that allows exactly n calls. +GTEST_API_ Cardinality Exactly(int n); + +// Creates a cardinality from its implementation. +inline Cardinality MakeCardinality(const CardinalityInterface* c) { + return Cardinality(c); +} + +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h new file mode 100644 index 0000000..7728d74 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h @@ -0,0 +1,2571 @@ +// This file was GENERATED by command: +// pump.py gmock-generated-actions.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic actions. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ + +#include "gmock/gmock-actions.h" +#include "gmock/internal/gmock-port.h" + +namespace testing { +namespace internal { + +// InvokeHelper knows how to unpack an N-tuple and invoke an N-ary +// function, method, or callback with the unpacked values, where F is +// a function type that takes N arguments. +template +class InvokeHelper; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple<>&) { + return function(); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple<>&) { + return (obj_ptr->*method_ptr)(); + } + + template + static R InvokeCallback(CallbackType* callback, + const ::testing::tuple<>&) { + return callback->Run(); + } +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args)); + } + + template + static R InvokeCallback(CallbackType* callback, + const ::testing::tuple& args) { + return callback->Run(get<0>(args)); + } +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args)); + } + + template + static R InvokeCallback(CallbackType* callback, + const ::testing::tuple& args) { + return callback->Run(get<0>(args), get<1>(args)); + } +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args)); + } + + template + static R InvokeCallback(CallbackType* callback, + const ::testing::tuple& args) { + return callback->Run(get<0>(args), get<1>(args), get<2>(args)); + } +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args), + get<3>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args), get<3>(args)); + } + + template + static R InvokeCallback(CallbackType* callback, + const ::testing::tuple& args) { + return callback->Run(get<0>(args), get<1>(args), get<2>(args), + get<3>(args)); + } +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args), + get<3>(args), get<4>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args), get<3>(args), get<4>(args)); + } + + template + static R InvokeCallback(CallbackType* callback, + const ::testing::tuple& args) { + return callback->Run(get<0>(args), get<1>(args), get<2>(args), + get<3>(args), get<4>(args)); + } +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args), + get<3>(args), get<4>(args), get<5>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args), get<3>(args), get<4>(args), get<5>(args)); + } + + // There is no InvokeCallback() for 6-tuples, as google3 callbacks + // support 5 arguments at most. +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args), + get<3>(args), get<4>(args), get<5>(args), get<6>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args), get<3>(args), get<4>(args), get<5>(args), + get<6>(args)); + } + + // There is no InvokeCallback() for 7-tuples, as google3 callbacks + // support 5 arguments at most. +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args), + get<3>(args), get<4>(args), get<5>(args), get<6>(args), + get<7>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args), get<3>(args), get<4>(args), get<5>(args), + get<6>(args), get<7>(args)); + } + + // There is no InvokeCallback() for 8-tuples, as google3 callbacks + // support 5 arguments at most. +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args), + get<3>(args), get<4>(args), get<5>(args), get<6>(args), + get<7>(args), get<8>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args), get<3>(args), get<4>(args), get<5>(args), + get<6>(args), get<7>(args), get<8>(args)); + } + + // There is no InvokeCallback() for 9-tuples, as google3 callbacks + // support 5 arguments at most. +}; + +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple& args) { + return function(get<0>(args), get<1>(args), get<2>(args), + get<3>(args), get<4>(args), get<5>(args), get<6>(args), + get<7>(args), get<8>(args), get<9>(args)); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple& args) { + return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), + get<2>(args), get<3>(args), get<4>(args), get<5>(args), + get<6>(args), get<7>(args), get<8>(args), get<9>(args)); + } + + // There is no InvokeCallback() for 10-tuples, as google3 callbacks + // support 5 arguments at most. +}; + +// Implements the Invoke(callback) action. +template +class InvokeCallbackAction { + public: + // The c'tor takes ownership of the callback. + explicit InvokeCallbackAction(CallbackType* callback) + : callback_(callback) { + callback->CheckIsRepeatable(); // Makes sure the callback is permanent. + } + + // This type conversion operator template allows Invoke(callback) to + // be used wherever the callback's type is compatible with that of + // the mock function, i.e. if the mock function's arguments can be + // implicitly converted to the callback's arguments and the + // callback's result can be implicitly converted to the mock + // function's result. + template + Result Perform(const ArgumentTuple& args) const { + return InvokeHelper::InvokeCallback( + callback_.get(), args); + } + private: + const linked_ptr callback_; +}; + +// An INTERNAL macro for extracting the type of a tuple field. It's +// subject to change without notice - DO NOT USE IN USER CODE! +#define GMOCK_FIELD_(Tuple, N) \ + typename ::testing::tuple_element::type + +// SelectArgs::type is the +// type of an n-ary function whose i-th (1-based) argument type is the +// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple +// type, and whose return type is Result. For example, +// SelectArgs, 0, 3>::type +// is int(bool, long). +// +// SelectArgs::Select(args) +// returns the selected fields (k1, k2, ..., k_n) of args as a tuple. +// For example, +// SelectArgs, 2, 0>::Select( +// ::testing::make_tuple(true, 'a', 2.5)) +// returns tuple (2.5, true). +// +// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be +// in the range [0, 10]. Duplicates are allowed and they don't have +// to be in an ascending or descending order. + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), + GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), + GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7), + GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9), + GMOCK_FIELD_(ArgumentTuple, k10)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args), + get(args), get(args), get(args), get(args), + get(args), get(args), get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& /* args */) { + return SelectedArgs(); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), + GMOCK_FIELD_(ArgumentTuple, k4)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args), + get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), + GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args), + get(args), get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), + GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), + GMOCK_FIELD_(ArgumentTuple, k6)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args), + get(args), get(args), get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), + GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), + GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args), + get(args), get(args), get(args), get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), + GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), + GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7), + GMOCK_FIELD_(ArgumentTuple, k8)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args), + get(args), get(args), get(args), get(args), + get(args)); + } +}; + +template +class SelectArgs { + public: + typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), + GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), + GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), + GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7), + GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9)); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs(get(args), get(args), get(args), + get(args), get(args), get(args), get(args), + get(args), get(args)); + } +}; + +#undef GMOCK_FIELD_ + +// Implements the WithArgs action. +template +class WithArgsAction { + public: + explicit WithArgsAction(const InnerAction& action) : action_(action) {} + + template + operator Action() const { return MakeAction(new Impl(action_)); } + + private: + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const InnerAction& action) : action_(action) {} + + virtual Result Perform(const ArgumentTuple& args) { + return action_.Perform(SelectArgs::Select(args)); + } + + private: + typedef typename SelectArgs::type InnerFunctionType; + + Action action_; + }; + + const InnerAction action_; + + GTEST_DISALLOW_ASSIGN_(WithArgsAction); +}; + +// A macro from the ACTION* family (defined later in this file) +// defines an action that can be used in a mock function. Typically, +// these actions only care about a subset of the arguments of the mock +// function. For example, if such an action only uses the second +// argument, it can be used in any mock function that takes >= 2 +// arguments where the type of the second argument is compatible. +// +// Therefore, the action implementation must be prepared to take more +// arguments than it needs. The ExcessiveArg type is used to +// represent those excessive arguments. In order to keep the compiler +// error messages tractable, we define it in the testing namespace +// instead of testing::internal. However, this is an INTERNAL TYPE +// and subject to change without notice, so a user MUST NOT USE THIS +// TYPE DIRECTLY. +struct ExcessiveArg {}; + +// A helper class needed for implementing the ACTION* macros. +template +class ActionHelper { + public: + static Result Perform(Impl* impl, const ::testing::tuple<>& args) { + return impl->template gmock_PerformImpl<>(args, ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, get<0>(args), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, get<0>(args), + get<1>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, get<0>(args), + get<1>(args), get<2>(args), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, get<0>(args), + get<1>(args), get<2>(args), get<3>(args), ExcessiveArg(), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, + get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args), + ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, + get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args), + get<5>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, + get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args), + get<5>(args), get<6>(args), ExcessiveArg(), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args), + get<4>(args), get<5>(args), get<6>(args), get<7>(args), ExcessiveArg(), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args), + get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args), + ExcessiveArg()); + } + + template + static Result Perform(Impl* impl, const ::testing::tuple& args) { + return impl->template gmock_PerformImpl(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args), + get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args), + get<9>(args)); + } +}; + +} // namespace internal + +// Various overloads for Invoke(). + +// WithArgs(an_action) creates an action that passes +// the selected arguments of the mock function to an_action and +// performs it. It serves as an adaptor between actions with +// different argument lists. C++ doesn't support default arguments for +// function templates, so we have to overload it. +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +template +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + +// Creates an action that does actions a1, a2, ..., sequentially in +// each invocation. +template +inline internal::DoBothAction +DoAll(Action1 a1, Action2 a2) { + return internal::DoBothAction(a1, a2); +} + +template +inline internal::DoBothAction > +DoAll(Action1 a1, Action2 a2, Action3 a3) { + return DoAll(a1, DoAll(a2, a3)); +} + +template +inline internal::DoBothAction > > +DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4) { + return DoAll(a1, DoAll(a2, a3, a4)); +} + +template +inline internal::DoBothAction > > > +DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5) { + return DoAll(a1, DoAll(a2, a3, a4, a5)); +} + +template +inline internal::DoBothAction > > > > +DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6) { + return DoAll(a1, DoAll(a2, a3, a4, a5, a6)); +} + +template +inline internal::DoBothAction > > > > > +DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, + Action7 a7) { + return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7)); +} + +template +inline internal::DoBothAction > > > > > > +DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, + Action7 a7, Action8 a8) { + return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8)); +} + +template +inline internal::DoBothAction > > > > > > > +DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, + Action7 a7, Action8 a8, Action9 a9) { + return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9)); +} + +template +inline internal::DoBothAction > > > > > > > > +DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, + Action7 a7, Action8 a8, Action9 a9, Action10 a10) { + return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9, a10)); +} + +} // namespace testing + +// The ACTION* family of macros can be used in a namespace scope to +// define custom actions easily. The syntax: +// +// ACTION(name) { statements; } +// +// will define an action with the given name that executes the +// statements. The value returned by the statements will be used as +// the return value of the action. Inside the statements, you can +// refer to the K-th (0-based) argument of the mock function by +// 'argK', and refer to its type by 'argK_type'. For example: +// +// ACTION(IncrementArg1) { +// arg1_type temp = arg1; +// return ++(*temp); +// } +// +// allows you to write +// +// ...WillOnce(IncrementArg1()); +// +// You can also refer to the entire argument tuple and its type by +// 'args' and 'args_type', and refer to the mock function type and its +// return type by 'function_type' and 'return_type'. +// +// Note that you don't need to specify the types of the mock function +// arguments. However rest assured that your code is still type-safe: +// you'll get a compiler error if *arg1 doesn't support the ++ +// operator, or if the type of ++(*arg1) isn't compatible with the +// mock function's return type, for example. +// +// Sometimes you'll want to parameterize the action. For that you can use +// another macro: +// +// ACTION_P(name, param_name) { statements; } +// +// For example: +// +// ACTION_P(Add, n) { return arg0 + n; } +// +// will allow you to write: +// +// ...WillOnce(Add(5)); +// +// Note that you don't need to provide the type of the parameter +// either. If you need to reference the type of a parameter named +// 'foo', you can write 'foo_type'. For example, in the body of +// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type +// of 'n'. +// +// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support +// multi-parameter actions. +// +// For the purpose of typing, you can view +// +// ACTION_Pk(Foo, p1, ..., pk) { ... } +// +// as shorthand for +// +// template +// FooActionPk Foo(p1_type p1, ..., pk_type pk) { ... } +// +// In particular, you can provide the template type arguments +// explicitly when invoking Foo(), as in Foo(5, false); +// although usually you can rely on the compiler to infer the types +// for you automatically. You can assign the result of expression +// Foo(p1, ..., pk) to a variable of type FooActionPk. This can be useful when composing actions. +// +// You can also overload actions with different numbers of parameters: +// +// ACTION_P(Plus, a) { ... } +// ACTION_P2(Plus, a, b) { ... } +// +// While it's tempting to always use the ACTION* macros when defining +// a new action, you should also consider implementing ActionInterface +// or using MakePolymorphicAction() instead, especially if you need to +// use the action a lot. While these approaches require more work, +// they give you more control on the types of the mock function +// arguments and the action parameters, which in general leads to +// better compiler error messages that pay off in the long run. They +// also allow overloading actions based on parameter types (as opposed +// to just based on the number of parameters). +// +// CAVEAT: +// +// ACTION*() can only be used in a namespace scope. The reason is +// that C++ doesn't yet allow function-local types to be used to +// instantiate templates. The up-coming C++0x standard will fix this. +// Once that's done, we'll consider supporting using ACTION*() inside +// a function. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'ACTION' +// on https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md + +// An internal macro needed for implementing ACTION*(). +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\ + const args_type& args GTEST_ATTRIBUTE_UNUSED_, \ + arg0_type arg0 GTEST_ATTRIBUTE_UNUSED_, \ + arg1_type arg1 GTEST_ATTRIBUTE_UNUSED_, \ + arg2_type arg2 GTEST_ATTRIBUTE_UNUSED_, \ + arg3_type arg3 GTEST_ATTRIBUTE_UNUSED_, \ + arg4_type arg4 GTEST_ATTRIBUTE_UNUSED_, \ + arg5_type arg5 GTEST_ATTRIBUTE_UNUSED_, \ + arg6_type arg6 GTEST_ATTRIBUTE_UNUSED_, \ + arg7_type arg7 GTEST_ATTRIBUTE_UNUSED_, \ + arg8_type arg8 GTEST_ATTRIBUTE_UNUSED_, \ + arg9_type arg9 GTEST_ATTRIBUTE_UNUSED_ + +// Sometimes you want to give an action explicit template parameters +// that cannot be inferred from its value parameters. ACTION() and +// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that +// and can be viewed as an extension to ACTION() and ACTION_P*(). +// +// The syntax: +// +// ACTION_TEMPLATE(ActionName, +// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), +// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } +// +// defines an action template that takes m explicit template +// parameters and n value parameters. name_i is the name of the i-th +// template parameter, and kind_i specifies whether it's a typename, +// an integral constant, or a template. p_i is the name of the i-th +// value parameter. +// +// Example: +// +// // DuplicateArg(output) converts the k-th argument of the mock +// // function to type T and copies it to *output. +// ACTION_TEMPLATE(DuplicateArg, +// HAS_2_TEMPLATE_PARAMS(int, k, typename, T), +// AND_1_VALUE_PARAMS(output)) { +// *output = T(::testing::get(args)); +// } +// ... +// int n; +// EXPECT_CALL(mock, Foo(_, _)) +// .WillOnce(DuplicateArg<1, unsigned char>(&n)); +// +// To create an instance of an action template, write: +// +// ActionName(v1, ..., v_n) +// +// where the ts are the template arguments and the vs are the value +// arguments. The value argument types are inferred by the compiler. +// If you want to explicitly specify the value argument types, you can +// provide additional template arguments: +// +// ActionName(v1, ..., v_n) +// +// where u_i is the desired type of v_i. +// +// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the +// number of value parameters, but not on the number of template +// parameters. Without the restriction, the meaning of the following +// is unclear: +// +// OverloadedAction(x); +// +// Are we using a single-template-parameter action where 'bool' refers +// to the type of x, or are we using a two-template-parameter action +// where the compiler is asked to infer the type of x? +// +// Implementation notes: +// +// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and +// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for +// implementing ACTION_TEMPLATE. The main trick we use is to create +// new macro invocations when expanding a macro. For example, we have +// +// #define ACTION_TEMPLATE(name, template_params, value_params) +// ... GMOCK_INTERNAL_DECL_##template_params ... +// +// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...) +// to expand to +// +// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ... +// +// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the +// preprocessor will continue to expand it to +// +// ... typename T ... +// +// This technique conforms to the C++ standard and is portable. It +// allows us to implement action templates using O(N) code, where N is +// the maximum number of template/value parameters supported. Without +// using it, we'd have to devote O(N^2) amount of code to implement all +// combinations of m and n. + +// Declares the template parameters. +#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0 +#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1) kind0 name0, kind1 name1 +#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2) kind0 name0, kind1 name1, kind2 name2 +#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3) kind0 name0, kind1 name1, kind2 name2, \ + kind3 name3 +#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4) kind0 name0, kind1 name1, \ + kind2 name2, kind3 name3, kind4 name4 +#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5) kind0 name0, \ + kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5 +#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6) kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \ + kind5 name5, kind6 name6 +#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7) kind0 name0, kind1 name1, kind2 name2, kind3 name3, \ + kind4 name4, kind5 name5, kind6 name6, kind7 name7 +#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7, kind8, name8) kind0 name0, kind1 name1, kind2 name2, \ + kind3 name3, kind4 name4, kind5 name5, kind6 name6, kind7 name7, \ + kind8 name8 +#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6, kind7, name7, kind8, name8, kind9, name9) kind0 name0, \ + kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5, \ + kind6 name6, kind7 name7, kind8 name8, kind9 name9 + +// Lists the template parameters. +#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0 +#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1) name0, name1 +#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2) name0, name1, name2 +#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3) name0, name1, name2, name3 +#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4) name0, name1, name2, name3, \ + name4 +#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5) name0, name1, \ + name2, name3, name4, name5 +#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6) name0, name1, name2, name3, name4, name5, name6 +#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7) name0, name1, name2, name3, name4, name5, name6, name7 +#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ + kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ + kind7, name7, kind8, name8) name0, name1, name2, name3, name4, name5, \ + name6, name7, name8 +#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \ + name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ + name6, kind7, name7, kind8, name8, kind9, name9) name0, name1, name2, \ + name3, name4, name5, name6, name7, name8, name9 + +// Declares the types of value parameters. +#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) , \ + typename p0##_type, typename p1##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , \ + typename p0##_type, typename p1##_type, typename p2##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \ + typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \ + typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \ + typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) , typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7) , typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8) , typename p0##_type, typename p1##_type, typename p2##_type, \ + typename p3##_type, typename p4##_type, typename p5##_type, \ + typename p6##_type, typename p7##_type, typename p8##_type +#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8, p9) , typename p0##_type, typename p1##_type, \ + typename p2##_type, typename p3##_type, typename p4##_type, \ + typename p5##_type, typename p6##_type, typename p7##_type, \ + typename p8##_type, typename p9##_type + +// Initializes the value parameters. +#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS()\ + () +#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0)\ + (p0##_type gmock_p0) : p0(::testing::internal::move(gmock_p0)) +#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1)\ + (p0##_type gmock_p0, \ + p1##_type gmock_p1) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)) +#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2)\ + (p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)) +#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)) +#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, \ + p4##_type gmock_p4) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)) +#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)) +#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)) +#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, \ + p7##_type gmock_p7) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)) +#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)), \ + p8(::testing::internal::move(gmock_p8)) +#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9)\ + (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ + p9##_type gmock_p9) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)), \ + p8(::testing::internal::move(gmock_p8)), \ + p9(::testing::internal::move(gmock_p9)) + +// Declares the fields for storing the value parameters. +#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0; +#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0; \ + p1##_type p1; +#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0; \ + p1##_type p1; p2##_type p2; +#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0; \ + p1##_type p1; p2##_type p2; p3##_type p3; +#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \ + p4) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; +#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \ + p5) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ + p5##_type p5; +#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ + p5##_type p5; p6##_type p6; +#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ + p5##_type p5; p6##_type p6; p7##_type p7; +#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \ + p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; +#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \ + p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; \ + p9##_type p9; + +// Lists the value parameters. +#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0 +#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1 +#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2 +#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3 +#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) p0, p1, \ + p2, p3, p4 +#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) p0, \ + p1, p2, p3, p4, p5 +#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) p0, p1, p2, p3, p4, p5, p6 +#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) p0, p1, p2, p3, p4, p5, p6, p7 +#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) p0, p1, p2, p3, p4, p5, p6, p7, p8 +#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) p0, p1, p2, p3, p4, p5, p6, p7, p8, p9 + +// Lists the value parameter types. +#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) , p0##_type, \ + p1##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , p0##_type, \ + p1##_type, p2##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \ + p0##_type, p1##_type, p2##_type, p3##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \ + p0##_type, p1##_type, p2##_type, p3##_type, p4##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \ + p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \ + p6##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type, p8##_type +#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8, p9) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ + p5##_type, p6##_type, p7##_type, p8##_type, p9##_type + +// Declares the value parameters. +#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0 +#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0, \ + p1##_type p1 +#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0, \ + p1##_type p1, p2##_type p2 +#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0, \ + p1##_type p1, p2##_type p2, p3##_type p3 +#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \ + p4) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4 +#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \ + p5) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ + p5##_type p5 +#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ + p6) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ + p5##_type p5, p6##_type p6 +#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ + p5##_type p5, p6##_type p6, p7##_type p7 +#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8 +#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ + p9##_type p9 + +// The suffix of the class template implementing the action template. +#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS() +#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P +#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2 +#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3 +#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4 +#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5 +#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6 +#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7 +#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7) P8 +#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8) P9 +#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ + p7, p8, p9) P10 + +// The name of the class template implementing the action template. +#define GMOCK_ACTION_CLASS_(name, value_params)\ + GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) + +#define ACTION_TEMPLATE(name, template_params, value_params)\ + template \ + class GMOCK_ACTION_CLASS_(name, value_params) {\ + public:\ + explicit GMOCK_ACTION_CLASS_(name, value_params)\ + GMOCK_INTERNAL_INIT_##value_params {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(\ + new gmock_Impl(GMOCK_INTERNAL_LIST_##value_params));\ + }\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\ + };\ + template \ + inline GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ + GMOCK_INTERNAL_DECL_##value_params) {\ + return GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ + GMOCK_INTERNAL_LIST_##value_params);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::\ + gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION(name)\ + class name##Action {\ + public:\ + name##Action() {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl() {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl());\ + }\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##Action);\ + };\ + inline name##Action name() {\ + return name##Action();\ + }\ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##Action::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P(name, p0)\ + template \ + class name##ActionP {\ + public:\ + explicit name##ActionP(p0##_type gmock_p0) : \ + p0(::testing::internal::forward(gmock_p0)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + explicit gmock_Impl(p0##_type gmock_p0) : \ + p0(::testing::internal::forward(gmock_p0)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0));\ + }\ + p0##_type p0;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP);\ + };\ + template \ + inline name##ActionP name(p0##_type p0) {\ + return name##ActionP(p0);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P2(name, p0, p1)\ + template \ + class name##ActionP2 {\ + public:\ + name##ActionP2(p0##_type gmock_p0, \ + p1##_type gmock_p1) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, \ + p1##_type gmock_p1) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP2);\ + };\ + template \ + inline name##ActionP2 name(p0##_type p0, \ + p1##_type p1) {\ + return name##ActionP2(p0, p1);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP2::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P3(name, p0, p1, p2)\ + template \ + class name##ActionP3 {\ + public:\ + name##ActionP3(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP3);\ + };\ + template \ + inline name##ActionP3 name(p0##_type p0, \ + p1##_type p1, p2##_type p2) {\ + return name##ActionP3(p0, p1, p2);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP3::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P4(name, p0, p1, p2, p3)\ + template \ + class name##ActionP4 {\ + public:\ + name##ActionP4(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, \ + p3##_type gmock_p3) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP4);\ + };\ + template \ + inline name##ActionP4 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3) {\ + return name##ActionP4(p0, p1, \ + p2, p3);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP4::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P5(name, p0, p1, p2, p3, p4)\ + template \ + class name##ActionP5 {\ + public:\ + name##ActionP5(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, \ + p4##_type gmock_p4) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, \ + p4##_type gmock_p4) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP5);\ + };\ + template \ + inline name##ActionP5 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4) {\ + return name##ActionP5(p0, p1, p2, p3, p4);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP5::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P6(name, p0, p1, p2, p3, p4, p5)\ + template \ + class name##ActionP6 {\ + public:\ + name##ActionP6(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP6);\ + };\ + template \ + inline name##ActionP6 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3, p4##_type p4, p5##_type p5) {\ + return name##ActionP6(p0, p1, p2, p3, p4, p5);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP6::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P7(name, p0, p1, p2, p3, p4, p5, p6)\ + template \ + class name##ActionP7 {\ + public:\ + name##ActionP7(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, \ + p6##_type gmock_p6) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP7);\ + };\ + template \ + inline name##ActionP7 name(p0##_type p0, p1##_type p1, \ + p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6) {\ + return name##ActionP7(p0, p1, p2, p3, p4, p5, p6);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP7::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P8(name, p0, p1, p2, p3, p4, p5, p6, p7)\ + template \ + class name##ActionP8 {\ + public:\ + name##ActionP8(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, \ + p7##_type gmock_p7) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)), \ + p7(::testing::internal::forward(gmock_p7)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, \ + p7##_type gmock_p7) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)), \ + p7(::testing::internal::forward(gmock_p7)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6, p7));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP8);\ + };\ + template \ + inline name##ActionP8 name(p0##_type p0, \ + p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6, p7##_type p7) {\ + return name##ActionP8(p0, p1, p2, p3, p4, p5, \ + p6, p7);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP8::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8)\ + template \ + class name##ActionP9 {\ + public:\ + name##ActionP9(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)), \ + p7(::testing::internal::forward(gmock_p7)), \ + p8(::testing::internal::forward(gmock_p8)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)), \ + p7(::testing::internal::forward(gmock_p7)), \ + p8(::testing::internal::forward(gmock_p8)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP9);\ + };\ + template \ + inline name##ActionP9 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ + p8##_type p8) {\ + return name##ActionP9(p0, p1, p2, \ + p3, p4, p5, p6, p7, p8);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP9::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)\ + template \ + class name##ActionP10 {\ + public:\ + name##ActionP10(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8, \ + p9##_type gmock_p9) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)), \ + p7(::testing::internal::forward(gmock_p7)), \ + p8(::testing::internal::forward(gmock_p8)), \ + p9(::testing::internal::forward(gmock_p9)) {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ + p9##_type gmock_p9) : p0(::testing::internal::forward(gmock_p0)), \ + p1(::testing::internal::forward(gmock_p1)), \ + p2(::testing::internal::forward(gmock_p2)), \ + p3(::testing::internal::forward(gmock_p3)), \ + p4(::testing::internal::forward(gmock_p4)), \ + p5(::testing::internal::forward(gmock_p5)), \ + p6(::testing::internal::forward(gmock_p6)), \ + p7(::testing::internal::forward(gmock_p7)), \ + p8(::testing::internal::forward(gmock_p8)), \ + p9(::testing::internal::forward(gmock_p9)) {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template \ + return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ + arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ + arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ + arg9_type arg9) const;\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + p9##_type p9;\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ + p6, p7, p8, p9));\ + }\ + p0##_type p0;\ + p1##_type p1;\ + p2##_type p2;\ + p3##_type p3;\ + p4##_type p4;\ + p5##_type p5;\ + p6##_type p6;\ + p7##_type p7;\ + p8##_type p8;\ + p9##_type p9;\ + private:\ + GTEST_DISALLOW_ASSIGN_(name##ActionP10);\ + };\ + template \ + inline name##ActionP10 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ + p9##_type p9) {\ + return name##ActionP10(p0, \ + p1, p2, p3, p4, p5, p6, p7, p8, p9);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + name##ActionP10::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +namespace testing { + + +// The ACTION*() macros trigger warning C4100 (unreferenced formal +// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in +// the macro definition, as the warnings are generated when the macro +// is expanded and macro expansion cannot contain #pragma. Therefore +// we suppress them here. +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4100) +#endif + +// Various overloads for InvokeArgument(). +// +// The InvokeArgument(a1, a2, ..., a_k) action invokes the N-th +// (0-based) argument, which must be a k-ary callable, of the mock +// function, with arguments a1, a2, ..., a_k. +// +// Notes: +// +// 1. The arguments are passed by value by default. If you need to +// pass an argument by reference, wrap it inside ByRef(). For +// example, +// +// InvokeArgument<1>(5, string("Hello"), ByRef(foo)) +// +// passes 5 and string("Hello") by value, and passes foo by +// reference. +// +// 2. If the callable takes an argument by reference but ByRef() is +// not used, it will receive the reference to a copy of the value, +// instead of the original value. For example, when the 0-th +// argument of the mock function takes a const string&, the action +// +// InvokeArgument<0>(string("Hello")) +// +// makes a copy of the temporary string("Hello") object and passes a +// reference of the copy, instead of the original temporary object, +// to the callable. This makes it easy for a user to define an +// InvokeArgument action from temporary values and have it performed +// later. + +namespace internal { +namespace invoke_argument { + +// Appears in InvokeArgumentAdl's argument list to help avoid +// accidental calls to user functions of the same name. +struct AdlTag {}; + +// InvokeArgumentAdl - a helper for InvokeArgument. +// The basic overloads are provided here for generic functors. +// Overloads for other custom-callables are provided in the +// internal/custom/callback-actions.h header. + +template +R InvokeArgumentAdl(AdlTag, F f) { + return f(); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1) { + return f(a1); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2) { + return f(a1, a2); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3) { + return f(a1, a2, a3); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4) { + return f(a1, a2, a3, a4); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + return f(a1, a2, a3, a4, a5); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { + return f(a1, a2, a3, a4, a5, a6); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7) { + return f(a1, a2, a3, a4, a5, a6, a7); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7, A8 a8) { + return f(a1, a2, a3, a4, a5, a6, a7, a8); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7, A8 a8, A9 a9) { + return f(a1, a2, a3, a4, a5, a6, a7, a8, a9); +} +template +R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, + A7 a7, A8 a8, A9 a9, A10 a10) { + return f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); +} +} // namespace invoke_argument +} // namespace internal + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_0_VALUE_PARAMS()) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args)); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_1_VALUE_PARAMS(p0)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_2_VALUE_PARAMS(p0, p1)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_3_VALUE_PARAMS(p0, p1, p2)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2, p3); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2, p3, p4); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2, p3, p4, p5); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2, p3, p4, p5, p6); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2, p3, p4, p5, p6, p7); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2, p3, p4, p5, p6, p7, p8); +} + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); +} + +// Various overloads for ReturnNew(). +// +// The ReturnNew(a1, a2, ..., a_k) action returns a pointer to a new +// instance of type T, constructed on the heap with constructor arguments +// a1, a2, ..., and a_k. The caller assumes ownership of the returned value. +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_0_VALUE_PARAMS()) { + return new T(); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_1_VALUE_PARAMS(p0)) { + return new T(p0); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_2_VALUE_PARAMS(p0, p1)) { + return new T(p0, p1); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_3_VALUE_PARAMS(p0, p1, p2)) { + return new T(p0, p1, p2); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { + return new T(p0, p1, p2, p3); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { + return new T(p0, p1, p2, p3, p4); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { + return new T(p0, p1, p2, p3, p4, p5); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { + return new T(p0, p1, p2, p3, p4, p5, p6); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8); +} + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { + return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); +} + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +} // namespace testing + +// Include any custom callback actions added by the local installation. +// We must include this header at the end to make sure it can use the +// declarations from this file. +#include "gmock/internal/custom/gmock-generated-actions.h" + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h.pump b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h.pump new file mode 100644 index 0000000..8bafa47 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-actions.h.pump @@ -0,0 +1,833 @@ +$$ -*- mode: c++; -*- +$$ This is a Pump source file. Please use Pump to convert it to +$$ gmock-generated-actions.h. +$$ +$var n = 10 $$ The maximum arity we support. +$$}} This meta comment fixes auto-indentation in editors. +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic actions. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ + +#include "gmock/gmock-actions.h" +#include "gmock/internal/gmock-port.h" + +namespace testing { +namespace internal { + +// InvokeHelper knows how to unpack an N-tuple and invoke an N-ary +// function, method, or callback with the unpacked values, where F is +// a function type that takes N arguments. +template +class InvokeHelper; + + +$var max_callback_arity = 5 +$range i 0..n +$for i [[ +$range j 1..i +$var types = [[$for j [[, typename A$j]]]] +$var as = [[$for j, [[A$j]]]] +$var args = [[$if i==0 [[]] $else [[ args]]]] +$var gets = [[$for j, [[get<$(j - 1)>(args)]]]] +template +class InvokeHelper > { + public: + template + static R Invoke(Function function, const ::testing::tuple<$as>&$args) { + return function($gets); + } + + template + static R InvokeMethod(Class* obj_ptr, + MethodPtr method_ptr, + const ::testing::tuple<$as>&$args) { + return (obj_ptr->*method_ptr)($gets); + } + + +$if i <= max_callback_arity [[ + template + static R InvokeCallback(CallbackType* callback, + const ::testing::tuple<$as>&$args) { + return callback->Run($gets); + } +]] $else [[ + // There is no InvokeCallback() for $i-tuples, as google3 callbacks + // support $max_callback_arity arguments at most. +]] + +}; + + +]] +// Implements the Invoke(callback) action. +template +class InvokeCallbackAction { + public: + // The c'tor takes ownership of the callback. + explicit InvokeCallbackAction(CallbackType* callback) + : callback_(callback) { + callback->CheckIsRepeatable(); // Makes sure the callback is permanent. + } + + // This type conversion operator template allows Invoke(callback) to + // be used wherever the callback's type is compatible with that of + // the mock function, i.e. if the mock function's arguments can be + // implicitly converted to the callback's arguments and the + // callback's result can be implicitly converted to the mock + // function's result. + template + Result Perform(const ArgumentTuple& args) const { + return InvokeHelper::InvokeCallback( + callback_.get(), args); + } + private: + const linked_ptr callback_; +}; + +// An INTERNAL macro for extracting the type of a tuple field. It's +// subject to change without notice - DO NOT USE IN USER CODE! +#define GMOCK_FIELD_(Tuple, N) \ + typename ::testing::tuple_element::type + +$range i 1..n + +// SelectArgs::type is the +// type of an n-ary function whose i-th (1-based) argument type is the +// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple +// type, and whose return type is Result. For example, +// SelectArgs, 0, 3>::type +// is int(bool, long). +// +// SelectArgs::Select(args) +// returns the selected fields (k1, k2, ..., k_n) of args as a tuple. +// For example, +// SelectArgs, 2, 0>::Select( +// ::testing::make_tuple(true, 'a', 2.5)) +// returns tuple (2.5, true). +// +// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be +// in the range [0, $n]. Duplicates are allowed and they don't have +// to be in an ascending or descending order. + +template +class SelectArgs { + public: + typedef Result type($for i, [[GMOCK_FIELD_(ArgumentTuple, k$i)]]); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& args) { + return SelectedArgs($for i, [[get(args)]]); + } +}; + + +$for i [[ +$range j 1..n +$range j1 1..i-1 +template +class SelectArgs { + public: + typedef Result type($for j1, [[GMOCK_FIELD_(ArgumentTuple, k$j1)]]); + typedef typename Function::ArgumentTuple SelectedArgs; + static SelectedArgs Select(const ArgumentTuple& [[]] +$if i == 1 [[/* args */]] $else [[args]]) { + return SelectedArgs($for j1, [[get(args)]]); + } +}; + + +]] +#undef GMOCK_FIELD_ + +$var ks = [[$for i, [[k$i]]]] + +// Implements the WithArgs action. +template +class WithArgsAction { + public: + explicit WithArgsAction(const InnerAction& action) : action_(action) {} + + template + operator Action() const { return MakeAction(new Impl(action_)); } + + private: + template + class Impl : public ActionInterface { + public: + typedef typename Function::Result Result; + typedef typename Function::ArgumentTuple ArgumentTuple; + + explicit Impl(const InnerAction& action) : action_(action) {} + + virtual Result Perform(const ArgumentTuple& args) { + return action_.Perform(SelectArgs::Select(args)); + } + + private: + typedef typename SelectArgs::type InnerFunctionType; + + Action action_; + }; + + const InnerAction action_; + + GTEST_DISALLOW_ASSIGN_(WithArgsAction); +}; + +// A macro from the ACTION* family (defined later in this file) +// defines an action that can be used in a mock function. Typically, +// these actions only care about a subset of the arguments of the mock +// function. For example, if such an action only uses the second +// argument, it can be used in any mock function that takes >= 2 +// arguments where the type of the second argument is compatible. +// +// Therefore, the action implementation must be prepared to take more +// arguments than it needs. The ExcessiveArg type is used to +// represent those excessive arguments. In order to keep the compiler +// error messages tractable, we define it in the testing namespace +// instead of testing::internal. However, this is an INTERNAL TYPE +// and subject to change without notice, so a user MUST NOT USE THIS +// TYPE DIRECTLY. +struct ExcessiveArg {}; + +// A helper class needed for implementing the ACTION* macros. +template +class ActionHelper { + public: +$range i 0..n +$for i + +[[ +$var template = [[$if i==0 [[]] $else [[ +$range j 0..i-1 + template <$for j, [[typename A$j]]> +]]]] +$range j 0..i-1 +$var As = [[$for j, [[A$j]]]] +$var as = [[$for j, [[get<$j>(args)]]]] +$range k 1..n-i +$var eas = [[$for k, [[ExcessiveArg()]]]] +$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]] +$template + static Result Perform(Impl* impl, const ::testing::tuple<$As>& args) { + return impl->template gmock_PerformImpl<$As>(args, $arg_list); + } + +]] +}; + +} // namespace internal + +// Various overloads for Invoke(). + +// WithArgs(an_action) creates an action that passes +// the selected arguments of the mock function to an_action and +// performs it. It serves as an adaptor between actions with +// different argument lists. C++ doesn't support default arguments for +// function templates, so we have to overload it. + +$range i 1..n +$for i [[ +$range j 1..i +template <$for j [[int k$j, ]]typename InnerAction> +inline internal::WithArgsAction +WithArgs(const InnerAction& action) { + return internal::WithArgsAction(action); +} + + +]] +// Creates an action that does actions a1, a2, ..., sequentially in +// each invocation. +$range i 2..n +$for i [[ +$range j 2..i +$var types = [[$for j, [[typename Action$j]]]] +$var Aas = [[$for j [[, Action$j a$j]]]] + +template +$range k 1..i-1 + +inline $for k [[internal::DoBothAction]] + +DoAll(Action1 a1$Aas) { +$if i==2 [[ + + return internal::DoBothAction(a1, a2); +]] $else [[ +$range j2 2..i + + return DoAll(a1, DoAll($for j2, [[a$j2]])); +]] + +} + +]] + +} // namespace testing + +// The ACTION* family of macros can be used in a namespace scope to +// define custom actions easily. The syntax: +// +// ACTION(name) { statements; } +// +// will define an action with the given name that executes the +// statements. The value returned by the statements will be used as +// the return value of the action. Inside the statements, you can +// refer to the K-th (0-based) argument of the mock function by +// 'argK', and refer to its type by 'argK_type'. For example: +// +// ACTION(IncrementArg1) { +// arg1_type temp = arg1; +// return ++(*temp); +// } +// +// allows you to write +// +// ...WillOnce(IncrementArg1()); +// +// You can also refer to the entire argument tuple and its type by +// 'args' and 'args_type', and refer to the mock function type and its +// return type by 'function_type' and 'return_type'. +// +// Note that you don't need to specify the types of the mock function +// arguments. However rest assured that your code is still type-safe: +// you'll get a compiler error if *arg1 doesn't support the ++ +// operator, or if the type of ++(*arg1) isn't compatible with the +// mock function's return type, for example. +// +// Sometimes you'll want to parameterize the action. For that you can use +// another macro: +// +// ACTION_P(name, param_name) { statements; } +// +// For example: +// +// ACTION_P(Add, n) { return arg0 + n; } +// +// will allow you to write: +// +// ...WillOnce(Add(5)); +// +// Note that you don't need to provide the type of the parameter +// either. If you need to reference the type of a parameter named +// 'foo', you can write 'foo_type'. For example, in the body of +// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type +// of 'n'. +// +// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support +// multi-parameter actions. +// +// For the purpose of typing, you can view +// +// ACTION_Pk(Foo, p1, ..., pk) { ... } +// +// as shorthand for +// +// template +// FooActionPk Foo(p1_type p1, ..., pk_type pk) { ... } +// +// In particular, you can provide the template type arguments +// explicitly when invoking Foo(), as in Foo(5, false); +// although usually you can rely on the compiler to infer the types +// for you automatically. You can assign the result of expression +// Foo(p1, ..., pk) to a variable of type FooActionPk. This can be useful when composing actions. +// +// You can also overload actions with different numbers of parameters: +// +// ACTION_P(Plus, a) { ... } +// ACTION_P2(Plus, a, b) { ... } +// +// While it's tempting to always use the ACTION* macros when defining +// a new action, you should also consider implementing ActionInterface +// or using MakePolymorphicAction() instead, especially if you need to +// use the action a lot. While these approaches require more work, +// they give you more control on the types of the mock function +// arguments and the action parameters, which in general leads to +// better compiler error messages that pay off in the long run. They +// also allow overloading actions based on parameter types (as opposed +// to just based on the number of parameters). +// +// CAVEAT: +// +// ACTION*() can only be used in a namespace scope. The reason is +// that C++ doesn't yet allow function-local types to be used to +// instantiate templates. The up-coming C++0x standard will fix this. +// Once that's done, we'll consider supporting using ACTION*() inside +// a function. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'ACTION' +// on https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md + +$range i 0..n +$range k 0..n-1 + +// An internal macro needed for implementing ACTION*(). +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\ + const args_type& args GTEST_ATTRIBUTE_UNUSED_ +$for k [[, \ + arg$k[[]]_type arg$k GTEST_ATTRIBUTE_UNUSED_]] + + +// Sometimes you want to give an action explicit template parameters +// that cannot be inferred from its value parameters. ACTION() and +// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that +// and can be viewed as an extension to ACTION() and ACTION_P*(). +// +// The syntax: +// +// ACTION_TEMPLATE(ActionName, +// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), +// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } +// +// defines an action template that takes m explicit template +// parameters and n value parameters. name_i is the name of the i-th +// template parameter, and kind_i specifies whether it's a typename, +// an integral constant, or a template. p_i is the name of the i-th +// value parameter. +// +// Example: +// +// // DuplicateArg(output) converts the k-th argument of the mock +// // function to type T and copies it to *output. +// ACTION_TEMPLATE(DuplicateArg, +// HAS_2_TEMPLATE_PARAMS(int, k, typename, T), +// AND_1_VALUE_PARAMS(output)) { +// *output = T(::testing::get(args)); +// } +// ... +// int n; +// EXPECT_CALL(mock, Foo(_, _)) +// .WillOnce(DuplicateArg<1, unsigned char>(&n)); +// +// To create an instance of an action template, write: +// +// ActionName(v1, ..., v_n) +// +// where the ts are the template arguments and the vs are the value +// arguments. The value argument types are inferred by the compiler. +// If you want to explicitly specify the value argument types, you can +// provide additional template arguments: +// +// ActionName(v1, ..., v_n) +// +// where u_i is the desired type of v_i. +// +// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the +// number of value parameters, but not on the number of template +// parameters. Without the restriction, the meaning of the following +// is unclear: +// +// OverloadedAction(x); +// +// Are we using a single-template-parameter action where 'bool' refers +// to the type of x, or are we using a two-template-parameter action +// where the compiler is asked to infer the type of x? +// +// Implementation notes: +// +// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and +// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for +// implementing ACTION_TEMPLATE. The main trick we use is to create +// new macro invocations when expanding a macro. For example, we have +// +// #define ACTION_TEMPLATE(name, template_params, value_params) +// ... GMOCK_INTERNAL_DECL_##template_params ... +// +// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...) +// to expand to +// +// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ... +// +// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the +// preprocessor will continue to expand it to +// +// ... typename T ... +// +// This technique conforms to the C++ standard and is portable. It +// allows us to implement action templates using O(N) code, where N is +// the maximum number of template/value parameters supported. Without +// using it, we'd have to devote O(N^2) amount of code to implement all +// combinations of m and n. + +// Declares the template parameters. + +$range j 1..n +$for j [[ +$range m 0..j-1 +#define GMOCK_INTERNAL_DECL_HAS_$j[[]] +_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[kind$m name$m]] + + +]] + +// Lists the template parameters. + +$for j [[ +$range m 0..j-1 +#define GMOCK_INTERNAL_LIST_HAS_$j[[]] +_TEMPLATE_PARAMS($for m, [[kind$m, name$m]]) $for m, [[name$m]] + + +]] + +// Declares the types of value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_DECL_TYPE_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j [[, typename p$j##_type]] + + +]] + +// Initializes the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_INIT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])\ + ($for j, [[p$j##_type gmock_p$j]])$if i>0 [[ : ]]$for j, [[p$j(::testing::internal::move(gmock_p$j))]] + + +]] + +// Declares the fields for storing the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_DEFN_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j [[p$j##_type p$j; ]] + + +]] + +// Lists the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_LIST_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j, [[p$j]] + + +]] + +// Lists the value parameter types. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_LIST_TYPE_AND_$i[[]] +_VALUE_PARAMS($for j, [[p$j]]) $for j [[, p$j##_type]] + + +]] + +// Declares the value parameters. + +$for i [[ +$range j 0..i-1 +#define GMOCK_INTERNAL_DECL_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]] +$for j, [[p$j##_type p$j]] + + +]] + +// The suffix of the class template implementing the action template. +$for i [[ + + +$range j 0..i-1 +#define GMOCK_INTERNAL_COUNT_AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]]) [[]] +$if i==1 [[P]] $elif i>=2 [[P$i]] +]] + + +// The name of the class template implementing the action template. +#define GMOCK_ACTION_CLASS_(name, value_params)\ + GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) + +$range k 0..n-1 + +#define ACTION_TEMPLATE(name, template_params, value_params)\ + template \ + class GMOCK_ACTION_CLASS_(name, value_params) {\ + public:\ + explicit GMOCK_ACTION_CLASS_(name, value_params)\ + GMOCK_INTERNAL_INIT_##value_params {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template <$for k, [[typename arg$k[[]]_type]]>\ + return_type gmock_PerformImpl(const args_type& args[[]] +$for k [[, arg$k[[]]_type arg$k]]) const;\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(\ + new gmock_Impl(GMOCK_INTERNAL_LIST_##value_params));\ + }\ + GMOCK_INTERNAL_DEFN_##value_params\ + private:\ + GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\ + };\ + template \ + inline GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ + GMOCK_INTERNAL_DECL_##value_params) {\ + return GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ + GMOCK_INTERNAL_LIST_##value_params);\ + }\ + template \ + template \ + template \ + typename ::testing::internal::Function::Result\ + GMOCK_ACTION_CLASS_(name, value_params)<\ + GMOCK_INTERNAL_LIST_##template_params\ + GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::\ + gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +$for i + +[[ +$var template = [[$if i==0 [[]] $else [[ +$range j 0..i-1 + + template <$for j, [[typename p$j##_type]]>\ +]]]] +$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]] + $else [[P$i]]]]]] +$range j 0..i-1 +$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] +$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::testing::internal::forward(gmock_p$j))]]]]]] +$var param_field_decls = [[$for j +[[ + + p$j##_type p$j;\ +]]]] +$var param_field_decls2 = [[$for j +[[ + + p$j##_type p$j;\ +]]]] +$var params = [[$for j, [[p$j]]]] +$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] +$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]] +$var arg_types_and_names = [[$for k, [[arg$k[[]]_type arg$k]]]] +$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]] + $else [[ACTION_P$i]]]] + +#define $macro_name(name$for j [[, p$j]])\$template + class $class_name {\ + public:\ + [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {}\ + template \ + class gmock_Impl : public ::testing::ActionInterface {\ + public:\ + typedef F function_type;\ + typedef typename ::testing::internal::Function::Result return_type;\ + typedef typename ::testing::internal::Function::ArgumentTuple\ + args_type;\ + [[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\ + virtual return_type Perform(const args_type& args) {\ + return ::testing::internal::ActionHelper::\ + Perform(this, args);\ + }\ + template <$typename_arg_types>\ + return_type gmock_PerformImpl(const args_type& args, [[]] +$arg_types_and_names) const;\$param_field_decls + private:\ + GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ + };\ + template operator ::testing::Action() const {\ + return ::testing::Action(new gmock_Impl($params));\ + }\$param_field_decls2 + private:\ + GTEST_DISALLOW_ASSIGN_($class_name);\ + };\$template + inline $class_name$param_types name($param_types_and_names) {\ + return $class_name$param_types($params);\ + }\$template + template \ + template <$typename_arg_types>\ + typename ::testing::internal::Function::Result\ + $class_name$param_types::gmock_Impl::gmock_PerformImpl(\ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const +]] +$$ } // This meta comment fixes auto-indentation in Emacs. It won't +$$ // show up in the generated code. + + +namespace testing { + + +// The ACTION*() macros trigger warning C4100 (unreferenced formal +// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in +// the macro definition, as the warnings are generated when the macro +// is expanded and macro expansion cannot contain #pragma. Therefore +// we suppress them here. +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4100) +#endif + +// Various overloads for InvokeArgument(). +// +// The InvokeArgument(a1, a2, ..., a_k) action invokes the N-th +// (0-based) argument, which must be a k-ary callable, of the mock +// function, with arguments a1, a2, ..., a_k. +// +// Notes: +// +// 1. The arguments are passed by value by default. If you need to +// pass an argument by reference, wrap it inside ByRef(). For +// example, +// +// InvokeArgument<1>(5, string("Hello"), ByRef(foo)) +// +// passes 5 and string("Hello") by value, and passes foo by +// reference. +// +// 2. If the callable takes an argument by reference but ByRef() is +// not used, it will receive the reference to a copy of the value, +// instead of the original value. For example, when the 0-th +// argument of the mock function takes a const string&, the action +// +// InvokeArgument<0>(string("Hello")) +// +// makes a copy of the temporary string("Hello") object and passes a +// reference of the copy, instead of the original temporary object, +// to the callable. This makes it easy for a user to define an +// InvokeArgument action from temporary values and have it performed +// later. + +namespace internal { +namespace invoke_argument { + +// Appears in InvokeArgumentAdl's argument list to help avoid +// accidental calls to user functions of the same name. +struct AdlTag {}; + +// InvokeArgumentAdl - a helper for InvokeArgument. +// The basic overloads are provided here for generic functors. +// Overloads for other custom-callables are provided in the +// internal/custom/callback-actions.h header. + +$range i 0..n +$for i +[[ +$range j 1..i + +template +R InvokeArgumentAdl(AdlTag, F f[[$for j [[, A$j a$j]]]]) { + return f([[$for j, [[a$j]]]]); +} +]] + +} // namespace invoke_argument +} // namespace internal + +$range i 0..n +$for i [[ +$range j 0..i-1 + +ACTION_TEMPLATE(InvokeArgument, + HAS_1_TEMPLATE_PARAMS(int, k), + AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) { + using internal::invoke_argument::InvokeArgumentAdl; + return InvokeArgumentAdl( + internal::invoke_argument::AdlTag(), + ::testing::get(args)$for j [[, p$j]]); +} + +]] + +// Various overloads for ReturnNew(). +// +// The ReturnNew(a1, a2, ..., a_k) action returns a pointer to a new +// instance of type T, constructed on the heap with constructor arguments +// a1, a2, ..., and a_k. The caller assumes ownership of the returned value. +$range i 0..n +$for i [[ +$range j 0..i-1 +$var ps = [[$for j, [[p$j]]]] + +ACTION_TEMPLATE(ReturnNew, + HAS_1_TEMPLATE_PARAMS(typename, T), + AND_$i[[]]_VALUE_PARAMS($ps)) { + return new T($ps); +} + +]] + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +} // namespace testing + +// Include any custom callback actions added by the local installation. +// We must include this header at the end to make sure it can use the +// declarations from this file. +#include "gmock/internal/custom/gmock-generated-actions.h" + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h new file mode 100644 index 0000000..126c48c --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h @@ -0,0 +1,1379 @@ +// This file was GENERATED by command: +// pump.py gmock-generated-function-mockers.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements function mockers of various arities. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-internal-utils.h" + +#if GTEST_HAS_STD_FUNCTION_ +# include +#endif + +namespace testing { +namespace internal { + +template +class FunctionMockerBase; + +// Note: class FunctionMocker really belongs to the ::testing +// namespace. However if we define it in ::testing, MSVC will +// complain when classes in ::testing::internal declare it as a +// friend class template. To workaround this compiler bug, we define +// FunctionMocker in ::testing::internal and import it into ::testing. +template +class FunctionMocker; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With() { + return MockSpec(this, ::testing::make_tuple()); + } + + R Invoke() { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple()); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1) { + return MockSpec(this, ::testing::make_tuple(m1)); + } + + R Invoke(A1 a1) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2) { + return MockSpec(this, ::testing::make_tuple(m1, m2)); + } + + R Invoke(A1 a1, A2 a2) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3)); + } + + R Invoke(A1 a1, A2 a2, A3 a3) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3, A4); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3, const Matcher& m4) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3, m4)); + } + + R Invoke(A1 a1, A2 a2, A3 a3, A4 a4) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3), + internal::forward(a4))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3, A4, A5); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3, const Matcher& m4, const Matcher& m5) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3, m4, m5)); + } + + R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3), + internal::forward(a4), internal::forward(a5))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3, A4, A5, A6); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3, const Matcher& m4, const Matcher& m5, + const Matcher& m6) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3, m4, m5, m6)); + } + + R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3), + internal::forward(a4), internal::forward(a5), + internal::forward(a6))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3, A4, A5, A6, A7); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3, const Matcher& m4, const Matcher& m5, + const Matcher& m6, const Matcher& m7) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3, m4, m5, m6, m7)); + } + + R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3), + internal::forward(a4), internal::forward(a5), + internal::forward(a6), internal::forward(a7))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3, A4, A5, A6, A7, A8); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3, const Matcher& m4, const Matcher& m5, + const Matcher& m6, const Matcher& m7, const Matcher& m8) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3, m4, m5, m6, m7, + m8)); + } + + R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3), + internal::forward(a4), internal::forward(a5), + internal::forward(a6), internal::forward(a7), + internal::forward(a8))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3, const Matcher& m4, const Matcher& m5, + const Matcher& m6, const Matcher& m7, const Matcher& m8, + const Matcher& m9) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3, m4, m5, m6, m7, + m8, m9)); + } + + R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3), + internal::forward(a4), internal::forward(a5), + internal::forward(a6), internal::forward(a7), + internal::forward(a8), internal::forward(a9))); + } +}; + +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With(const Matcher& m1, const Matcher& m2, + const Matcher& m3, const Matcher& m4, const Matcher& m5, + const Matcher& m6, const Matcher& m7, const Matcher& m8, + const Matcher& m9, const Matcher& m10) { + return MockSpec(this, ::testing::make_tuple(m1, m2, m3, m4, m5, m6, m7, + m8, m9, m10)); + } + + R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, + A10 a10) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple(internal::forward(a1), + internal::forward(a2), internal::forward(a3), + internal::forward(a4), internal::forward(a5), + internal::forward(a6), internal::forward(a7), + internal::forward(a8), internal::forward(a9), + internal::forward(a10))); + } +}; + +// Removes the given pointer; this is a helper for the expectation setter method +// for parameterless matchers. +// +// We want to make sure that the user cannot set a parameterless expectation on +// overloaded methods, including methods which are overloaded on const. Example: +// +// class MockClass { +// MOCK_METHOD0(GetName, string&()); +// MOCK_CONST_METHOD0(GetName, const string&()); +// }; +// +// TEST() { +// // This should be an error, as it's not clear which overload is expected. +// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value)); +// } +// +// Here are the generated expectation-setter methods: +// +// class MockClass { +// // Overload 1 +// MockSpec gmock_GetName() { … } +// // Overload 2. Declared const so that the compiler will generate an +// // error when trying to resolve between this and overload 4 in +// // 'gmock_GetName(WithoutMatchers(), nullptr)'. +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Removes const from this, calls overload 1 +// return AdjustConstness_(this)->gmock_GetName(); +// } +// +// // Overload 3 +// const string& gmock_GetName() const { … } +// // Overload 4 +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Does not remove const, calls overload 3 +// return AdjustConstness_const(this)->gmock_GetName(); +// } +// } +// +template +const MockType* AdjustConstness_const(const MockType* mock) { + return mock; +} + +// Removes const from and returns the given pointer; this is a helper for the +// expectation setter method for parameterless matchers. +template +MockType* AdjustConstness_(const MockType* mock) { + return const_cast(mock); +} + +} // namespace internal + +// The style guide prohibits "using" statements in a namespace scope +// inside a header file. However, the FunctionMocker class template +// is meant to be defined in the ::testing namespace. The following +// line is just a trick for working around a bug in MSVC 8.0, which +// cannot handle it if we define FunctionMocker in ::testing. +using internal::FunctionMocker; + +// GMOCK_RESULT_(tn, F) expands to the result type of function type F. +// We define this as a variadic macro in case F contains unprotected +// commas (the same reason that we use variadic macros in other places +// in this file). +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_RESULT_(tn, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::Result + +// The type of argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_ARG_(tn, N, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::Argument##N + +// The matcher type for argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MATCHER_(tn, N, ...) \ + const ::testing::Matcher& + +// The variable for mocking the given method. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MOCKER_(arity, constness, Method) \ + GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method() constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 0), \ + this_method_does_not_take_0_arguments); \ + GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(0, constness, Method).Invoke(); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method() constness { \ + GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(0, constness, Method).With(); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 1), \ + this_method_does_not_take_1_argument); \ + GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(1, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \ + GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 2), \ + this_method_does_not_take_2_arguments); \ + GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(2, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \ + GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 3), \ + this_method_does_not_take_3_arguments); \ + GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(3, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \ + GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(3, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 4), \ + this_method_does_not_take_4_arguments); \ + GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(4, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3), \ + ::testing::internal::forward( \ + gmock_a4)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \ + GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(4, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3, gmock_a4); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 5), \ + this_method_does_not_take_5_arguments); \ + GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(5, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3), \ + ::testing::internal::forward( \ + gmock_a4), \ + ::testing::internal::forward( \ + gmock_a5)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \ + GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(5, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3, gmock_a4, gmock_a5); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 6), \ + this_method_does_not_take_6_arguments); \ + GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(6, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3), \ + ::testing::internal::forward( \ + gmock_a4), \ + ::testing::internal::forward( \ + gmock_a5), \ + ::testing::internal::forward( \ + gmock_a6)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \ + GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(6, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3, gmock_a4, gmock_a5, gmock_a6); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 7), \ + this_method_does_not_take_7_arguments); \ + GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(7, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3), \ + ::testing::internal::forward( \ + gmock_a4), \ + ::testing::internal::forward( \ + gmock_a5), \ + ::testing::internal::forward( \ + gmock_a6), \ + ::testing::internal::forward( \ + gmock_a7)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \ + GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(7, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3, gmock_a4, gmock_a5, gmock_a6, \ + gmock_a7); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 8), \ + this_method_does_not_take_8_arguments); \ + GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(8, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3), \ + ::testing::internal::forward( \ + gmock_a4), \ + ::testing::internal::forward( \ + gmock_a5), \ + ::testing::internal::forward( \ + gmock_a6), \ + ::testing::internal::forward( \ + gmock_a7), \ + ::testing::internal::forward( \ + gmock_a8)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \ + GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(8, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3, gmock_a4, gmock_a5, gmock_a6, \ + gmock_a7, gmock_a8); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8, \ + GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 9), \ + this_method_does_not_take_9_arguments); \ + GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(9, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3), \ + ::testing::internal::forward( \ + gmock_a4), \ + ::testing::internal::forward( \ + gmock_a5), \ + ::testing::internal::forward( \ + gmock_a6), \ + ::testing::internal::forward( \ + gmock_a7), \ + ::testing::internal::forward( \ + gmock_a8), \ + ::testing::internal::forward( \ + gmock_a9)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \ + GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \ + GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(9, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3, gmock_a4, gmock_a5, gmock_a6, \ + gmock_a7, gmock_a8, gmock_a9); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \ + Method) + +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) \ + ct Method(GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_ARG_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_ARG_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_ARG_(tn, 8, __VA_ARGS__) gmock_a8, \ + GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \ + GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \ + GTEST_COMPILE_ASSERT_( \ + (::testing::tuple_size::ArgumentTuple>::value == 10), \ + this_method_does_not_take_10_arguments); \ + GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_(10, constness, Method) \ + .Invoke(::testing::internal::forward( \ + gmock_a1), \ + ::testing::internal::forward( \ + gmock_a2), \ + ::testing::internal::forward( \ + gmock_a3), \ + ::testing::internal::forward( \ + gmock_a4), \ + ::testing::internal::forward( \ + gmock_a5), \ + ::testing::internal::forward( \ + gmock_a6), \ + ::testing::internal::forward( \ + gmock_a7), \ + ::testing::internal::forward( \ + gmock_a8), \ + ::testing::internal::forward( \ + gmock_a9), \ + ::testing::internal::forward( \ + gmock_a10)); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ + GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ + GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ + GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ + GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ + GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ + GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ + GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \ + GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \ + GMOCK_MATCHER_(tn, 10, __VA_ARGS__) gmock_a10) constness { \ + GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_(10, constness, Method) \ + .With(gmock_a1, gmock_a2, gmock_a3, gmock_a4, gmock_a5, gmock_a6, \ + gmock_a7, gmock_a8, gmock_a9, gmock_a10); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>*) const { \ + return ::testing::internal::AdjustConstness_##constness(this) \ + ->gmock_##Method(::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A(), \ + ::testing::A()); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \ + Method) + +#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__) +#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__) +#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__) +#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__) +#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__) +#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__) +#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__) +#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__) +#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__) +#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__) +#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__) + +#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__) +#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T(m, ...) \ + GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T(m, ...) \ + GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T(m, ...) \ + GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T(m, ...) \ + GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T(m, ...) \ + GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T(m, ...) \ + GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T(m, ...) \ + GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T(m, ...) \ + GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T(m, ...) \ + GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T(m, ...) \ + GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T(m, ...) \ + GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__) + +#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(, , ct, m, __VA_ARGS__) +#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(, , ct, m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__) + +#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__) +#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__) + +// A MockFunction class has one mock method whose type is F. It is +// useful when you just want your test code to emit some messages and +// have Google Mock verify the right messages are sent (and perhaps at +// the right times). For example, if you are exercising code: +// +// Foo(1); +// Foo(2); +// Foo(3); +// +// and want to verify that Foo(1) and Foo(3) both invoke +// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write: +// +// TEST(FooTest, InvokesBarCorrectly) { +// MyMock mock; +// MockFunction check; +// { +// InSequence s; +// +// EXPECT_CALL(mock, Bar("a")); +// EXPECT_CALL(check, Call("1")); +// EXPECT_CALL(check, Call("2")); +// EXPECT_CALL(mock, Bar("a")); +// } +// Foo(1); +// check.Call("1"); +// Foo(2); +// check.Call("2"); +// Foo(3); +// } +// +// The expectation spec says that the first Bar("a") must happen +// before check point "1", the second Bar("a") must happen after check +// point "2", and nothing should happen between the two check +// points. The explicit check points make it easy to tell which +// Bar("a") is called by which call to Foo(). +// +// MockFunction can also be used to exercise code that accepts +// std::function callbacks. To do so, use AsStdFunction() method +// to create std::function proxy forwarding to original object's Call. +// Example: +// +// TEST(FooTest, RunsCallbackWithBarArgument) { +// MockFunction callback; +// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1)); +// Foo(callback.AsStdFunction()); +// } +template +class MockFunction; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD0_T(Call, R()); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this]() -> R { + return this->Call(); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD1_T(Call, R(A0)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0) -> R { + return this->Call(::std::move(a0)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD2_T(Call, R(A0, A1)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1) -> R { + return this->Call(::std::move(a0), ::std::move(a1)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD3_T(Call, R(A0, A1, A2)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD4_T(Call, R(A0, A1, A2, A3)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2, A3 a3) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2), + ::std::move(a3)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2), + ::std::move(a3), ::std::move(a4)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2), + ::std::move(a3), ::std::move(a4), ::std::move(a5)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2), + ::std::move(a3), ::std::move(a4), ::std::move(a5), ::std::move(a6)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2), + ::std::move(a3), ::std::move(a4), ::std::move(a5), ::std::move(a6), + ::std::move(a7)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, + A8 a8) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2), + ::std::move(a3), ::std::move(a4), ::std::move(a5), ::std::move(a6), + ::std::move(a7), ::std::move(a8)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this](A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, + A8 a8, A9 a9) -> R { + return this->Call(::std::move(a0), ::std::move(a1), ::std::move(a2), + ::std::move(a3), ::std::move(a4), ::std::move(a5), ::std::move(a6), + ::std::move(a7), ::std::move(a8), ::std::move(a9)); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump new file mode 100644 index 0000000..efcb3e8 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-function-mockers.h.pump @@ -0,0 +1,347 @@ +$$ -*- mode: c++; -*- +$$ This is a Pump source file. Please use Pump to convert +$$ it to gmock-generated-function-mockers.h. +$$ +$var n = 10 $$ The maximum arity we support. +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements function mockers of various arities. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-internal-utils.h" + +#if GTEST_HAS_STD_FUNCTION_ +# include +#endif + +namespace testing { +namespace internal { + +template +class FunctionMockerBase; + +// Note: class FunctionMocker really belongs to the ::testing +// namespace. However if we define it in ::testing, MSVC will +// complain when classes in ::testing::internal declare it as a +// friend class template. To workaround this compiler bug, we define +// FunctionMocker in ::testing::internal and import it into ::testing. +template +class FunctionMocker; + + +$range i 0..n +$for i [[ +$range j 1..i +$var typename_As = [[$for j [[, typename A$j]]]] +$var As = [[$for j, [[A$j]]]] +$var as = [[$for j, [[internal::forward(a$j)]]]] +$var Aas = [[$for j, [[A$j a$j]]]] +$var ms = [[$for j, [[m$j]]]] +$var matchers = [[$for j, [[const Matcher& m$j]]]] +template +class FunctionMocker : public + internal::FunctionMockerBase { + public: + typedef R F($As); + typedef typename internal::Function::ArgumentTuple ArgumentTuple; + + MockSpec With($matchers) { + return MockSpec(this, ::testing::make_tuple($ms)); + } + + R Invoke($Aas) { + // Even though gcc and MSVC don't enforce it, 'this->' is required + // by the C++ standard [14.6.4] here, as the base class type is + // dependent on the template argument (and thus shouldn't be + // looked into when resolving InvokeWith). + return this->InvokeWith(ArgumentTuple($as)); + } +}; + + +]] +// Removes the given pointer; this is a helper for the expectation setter method +// for parameterless matchers. +// +// We want to make sure that the user cannot set a parameterless expectation on +// overloaded methods, including methods which are overloaded on const. Example: +// +// class MockClass { +// MOCK_METHOD0(GetName, string&()); +// MOCK_CONST_METHOD0(GetName, const string&()); +// }; +// +// TEST() { +// // This should be an error, as it's not clear which overload is expected. +// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value)); +// } +// +// Here are the generated expectation-setter methods: +// +// class MockClass { +// // Overload 1 +// MockSpec gmock_GetName() { … } +// // Overload 2. Declared const so that the compiler will generate an +// // error when trying to resolve between this and overload 4 in +// // 'gmock_GetName(WithoutMatchers(), nullptr)'. +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Removes const from this, calls overload 1 +// return AdjustConstness_(this)->gmock_GetName(); +// } +// +// // Overload 3 +// const string& gmock_GetName() const { … } +// // Overload 4 +// MockSpec gmock_GetName( +// const WithoutMatchers&, const Function*) const { +// // Does not remove const, calls overload 3 +// return AdjustConstness_const(this)->gmock_GetName(); +// } +// } +// +template +const MockType* AdjustConstness_const(const MockType* mock) { + return mock; +} + +// Removes const from and returns the given pointer; this is a helper for the +// expectation setter method for parameterless matchers. +template +MockType* AdjustConstness_(const MockType* mock) { + return const_cast(mock); +} + +} // namespace internal + +// The style guide prohibits "using" statements in a namespace scope +// inside a header file. However, the FunctionMocker class template +// is meant to be defined in the ::testing namespace. The following +// line is just a trick for working around a bug in MSVC 8.0, which +// cannot handle it if we define FunctionMocker in ::testing. +using internal::FunctionMocker; + +// GMOCK_RESULT_(tn, F) expands to the result type of function type F. +// We define this as a variadic macro in case F contains unprotected +// commas (the same reason that we use variadic macros in other places +// in this file). +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_RESULT_(tn, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::Result + +// The type of argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_ARG_(tn, N, ...) \ + tn ::testing::internal::Function<__VA_ARGS__>::Argument##N + +// The matcher type for argument N of the given function type. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MATCHER_(tn, N, ...) \ + const ::testing::Matcher& + +// The variable for mocking the given method. +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_MOCKER_(arity, constness, Method) \ + GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) + + +$for i [[ +$range j 1..i +$var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]] +$var as = [[$for j, \ + [[::testing::internal::forward(gmock_a$j)]]]] +$var matcher_arg_as = [[$for j, \ + [[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]] +$var matcher_as = [[$for j, [[gmock_a$j]]]] +$var anything_matchers = [[$for j, \ + [[::testing::A()]]]] +// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! +#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \ + GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ + $arg_as) constness { \ + GTEST_COMPILE_ASSERT_((::testing::tuple_size< \ + tn ::testing::internal::Function<__VA_ARGS__>::ArgumentTuple>::value == $i), \ + this_method_does_not_take_$i[[]]_argument[[$if i != 1 [[s]]]]); \ + GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \ + return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \ + } \ + ::testing::MockSpec<__VA_ARGS__> \ + gmock_##Method($matcher_arg_as) constness { \ + GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \ + return GMOCK_MOCKER_($i, constness, Method).With($matcher_as); \ + } \ + ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ + const ::testing::internal::WithoutMatchers&, \ + constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ + return ::testing::internal::AdjustConstness_##constness(this)-> \ + gmock_##Method($anything_matchers); \ + } \ + mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method) + + +]] +$for i [[ +#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \ + GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__) + +]] + + +$for i [[ +#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__) + +]] + +// A MockFunction class has one mock method whose type is F. It is +// useful when you just want your test code to emit some messages and +// have Google Mock verify the right messages are sent (and perhaps at +// the right times). For example, if you are exercising code: +// +// Foo(1); +// Foo(2); +// Foo(3); +// +// and want to verify that Foo(1) and Foo(3) both invoke +// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write: +// +// TEST(FooTest, InvokesBarCorrectly) { +// MyMock mock; +// MockFunction check; +// { +// InSequence s; +// +// EXPECT_CALL(mock, Bar("a")); +// EXPECT_CALL(check, Call("1")); +// EXPECT_CALL(check, Call("2")); +// EXPECT_CALL(mock, Bar("a")); +// } +// Foo(1); +// check.Call("1"); +// Foo(2); +// check.Call("2"); +// Foo(3); +// } +// +// The expectation spec says that the first Bar("a") must happen +// before check point "1", the second Bar("a") must happen after check +// point "2", and nothing should happen between the two check +// points. The explicit check points make it easy to tell which +// Bar("a") is called by which call to Foo(). +// +// MockFunction can also be used to exercise code that accepts +// std::function callbacks. To do so, use AsStdFunction() method +// to create std::function proxy forwarding to original object's Call. +// Example: +// +// TEST(FooTest, RunsCallbackWithBarArgument) { +// MockFunction callback; +// EXPECT_CALL(callback, Call("bar")).WillOnce(Return(1)); +// Foo(callback.AsStdFunction()); +// } +template +class MockFunction; + + +$for i [[ +$range j 0..i-1 +$var ArgTypes = [[$for j, [[A$j]]]] +$var ArgValues = [[$for j, [[::std::move(a$j)]]]] +$var ArgDecls = [[$for j, [[A$j a$j]]]] +template +class MockFunction { + public: + MockFunction() {} + + MOCK_METHOD$i[[]]_T(Call, R($ArgTypes)); + +#if GTEST_HAS_STD_FUNCTION_ + ::std::function AsStdFunction() { + return [this]($ArgDecls) -> R { + return this->Call($ArgValues); + }; + } +#endif // GTEST_HAS_STD_FUNCTION_ + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction); +}; + + +]] +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h new file mode 100644 index 0000000..21af61b --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h @@ -0,0 +1,2258 @@ +// This file was GENERATED by command: +// pump.py gmock-generated-matchers.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic matchers. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ + +#include +#include +#include +#include +#include "gmock/gmock-matchers.h" + +namespace testing { +namespace internal { + +// The type of the i-th (0-based) field of Tuple. +#define GMOCK_FIELD_TYPE_(Tuple, i) \ + typename ::testing::tuple_element::type + +// TupleFields is for selecting fields from a +// tuple of type Tuple. It has two members: +// +// type: a tuple type whose i-th field is the ki-th field of Tuple. +// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple. +// +// For example, in class TupleFields, 2, 0>, we have: +// +// type is tuple, and +// GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true). + +template +class TupleFields; + +// This generic version is used when there are 10 selectors. +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t), get(t), get(t), + get(t), get(t), get(t), get(t), get(t)); + } +}; + +// The following specialization is used for 0 ~ 9 selectors. + +template +class TupleFields { + public: + typedef ::testing::tuple<> type; + static type GetSelectedFields(const Tuple& /* t */) { + return type(); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t), get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t), get(t), get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t), get(t), get(t), + get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t), get(t), get(t), + get(t), get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t), get(t), get(t), + get(t), get(t), get(t)); + } +}; + +template +class TupleFields { + public: + typedef ::testing::tuple type; + static type GetSelectedFields(const Tuple& t) { + return type(get(t), get(t), get(t), get(t), get(t), + get(t), get(t), get(t), get(t)); + } +}; + +#undef GMOCK_FIELD_TYPE_ + +// Implements the Args() matcher. +template +class ArgsMatcherImpl : public MatcherInterface { + public: + // ArgsTuple may have top-level const or reference modifiers. + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple; + typedef typename internal::TupleFields::type SelectedArgs; + typedef Matcher MonomorphicInnerMatcher; + + template + explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher) + : inner_matcher_(SafeMatcherCast(inner_matcher)) {} + + virtual bool MatchAndExplain(ArgsTuple args, + MatchResultListener* listener) const { + const SelectedArgs& selected_args = GetSelectedArgs(args); + if (!listener->IsInterested()) + return inner_matcher_.Matches(selected_args); + + PrintIndices(listener->stream()); + *listener << "are " << PrintToString(selected_args); + + StringMatchResultListener inner_listener; + const bool match = inner_matcher_.MatchAndExplain(selected_args, + &inner_listener); + PrintIfNotEmpty(inner_listener.str(), listener->stream()); + return match; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "are a tuple "; + PrintIndices(os); + inner_matcher_.DescribeTo(os); + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "are a tuple "; + PrintIndices(os); + inner_matcher_.DescribeNegationTo(os); + } + + private: + static SelectedArgs GetSelectedArgs(ArgsTuple args) { + return TupleFields::GetSelectedFields(args); + } + + // Prints the indices of the selected fields. + static void PrintIndices(::std::ostream* os) { + *os << "whose fields ("; + const int indices[10] = { k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 }; + for (int i = 0; i < 10; i++) { + if (indices[i] < 0) + break; + + if (i >= 1) + *os << ", "; + + *os << "#" << indices[i]; + } + *os << ") "; + } + + const MonomorphicInnerMatcher inner_matcher_; + + GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl); +}; + +template +class ArgsMatcher { + public: + explicit ArgsMatcher(const InnerMatcher& inner_matcher) + : inner_matcher_(inner_matcher) {} + + template + operator Matcher() const { + return MakeMatcher(new ArgsMatcherImpl(inner_matcher_)); + } + + private: + const InnerMatcher inner_matcher_; + + GTEST_DISALLOW_ASSIGN_(ArgsMatcher); +}; + +// A set of metafunctions for computing the result type of AllOf. +// AllOf(m1, ..., mN) returns +// AllOfResultN::type. + +// Although AllOf isn't defined for one argument, AllOfResult1 is defined +// to simplify the implementation. +template +struct AllOfResult1 { + typedef M1 type; +}; + +template +struct AllOfResult2 { + typedef BothOfMatcher< + typename AllOfResult1::type, + typename AllOfResult1::type + > type; +}; + +template +struct AllOfResult3 { + typedef BothOfMatcher< + typename AllOfResult1::type, + typename AllOfResult2::type + > type; +}; + +template +struct AllOfResult4 { + typedef BothOfMatcher< + typename AllOfResult2::type, + typename AllOfResult2::type + > type; +}; + +template +struct AllOfResult5 { + typedef BothOfMatcher< + typename AllOfResult2::type, + typename AllOfResult3::type + > type; +}; + +template +struct AllOfResult6 { + typedef BothOfMatcher< + typename AllOfResult3::type, + typename AllOfResult3::type + > type; +}; + +template +struct AllOfResult7 { + typedef BothOfMatcher< + typename AllOfResult3::type, + typename AllOfResult4::type + > type; +}; + +template +struct AllOfResult8 { + typedef BothOfMatcher< + typename AllOfResult4::type, + typename AllOfResult4::type + > type; +}; + +template +struct AllOfResult9 { + typedef BothOfMatcher< + typename AllOfResult4::type, + typename AllOfResult5::type + > type; +}; + +template +struct AllOfResult10 { + typedef BothOfMatcher< + typename AllOfResult5::type, + typename AllOfResult5::type + > type; +}; + +// A set of metafunctions for computing the result type of AnyOf. +// AnyOf(m1, ..., mN) returns +// AnyOfResultN::type. + +// Although AnyOf isn't defined for one argument, AnyOfResult1 is defined +// to simplify the implementation. +template +struct AnyOfResult1 { + typedef M1 type; +}; + +template +struct AnyOfResult2 { + typedef EitherOfMatcher< + typename AnyOfResult1::type, + typename AnyOfResult1::type + > type; +}; + +template +struct AnyOfResult3 { + typedef EitherOfMatcher< + typename AnyOfResult1::type, + typename AnyOfResult2::type + > type; +}; + +template +struct AnyOfResult4 { + typedef EitherOfMatcher< + typename AnyOfResult2::type, + typename AnyOfResult2::type + > type; +}; + +template +struct AnyOfResult5 { + typedef EitherOfMatcher< + typename AnyOfResult2::type, + typename AnyOfResult3::type + > type; +}; + +template +struct AnyOfResult6 { + typedef EitherOfMatcher< + typename AnyOfResult3::type, + typename AnyOfResult3::type + > type; +}; + +template +struct AnyOfResult7 { + typedef EitherOfMatcher< + typename AnyOfResult3::type, + typename AnyOfResult4::type + > type; +}; + +template +struct AnyOfResult8 { + typedef EitherOfMatcher< + typename AnyOfResult4::type, + typename AnyOfResult4::type + > type; +}; + +template +struct AnyOfResult9 { + typedef EitherOfMatcher< + typename AnyOfResult4::type, + typename AnyOfResult5::type + > type; +}; + +template +struct AnyOfResult10 { + typedef EitherOfMatcher< + typename AnyOfResult5::type, + typename AnyOfResult5::type + > type; +}; + +} // namespace internal + +// Args(a_matcher) matches a tuple if the selected +// fields of it matches a_matcher. C++ doesn't support default +// arguments for function templates, so we have to overload it. +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +template +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + +// ElementsAre(e_1, e_2, ... e_n) matches an STL-style container with +// n elements, where the i-th element in the container must +// match the i-th argument in the list. Each argument of +// ElementsAre() can be either a value or a matcher. We support up to +// 10 arguments. +// +// The use of DecayArray in the implementation allows ElementsAre() +// to accept string literals, whose type is const char[N], but we +// want to treat them as const char*. +// +// NOTE: Since ElementsAre() cares about the order of the elements, it +// must not be used with containers whose elements's order is +// undefined (e.g. hash_map). + +inline internal::ElementsAreMatcher< + ::testing::tuple<> > +ElementsAre() { + typedef ::testing::tuple<> Args; + return internal::ElementsAreMatcher(Args()); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type> > +ElementsAre(const T1& e1) { + typedef ::testing::tuple< + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3, e4)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3, e4, e5)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3, e4, e5, e6)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3, e4, e5, e6, e7)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7, const T8& e8) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3, e4, e5, e6, e7, + e8)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3, e4, e5, e6, e7, + e8, e9)); +} + +template +inline internal::ElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9, + const T10& e10) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::ElementsAreMatcher(Args(e1, e2, e3, e4, e5, e6, e7, + e8, e9, e10)); +} + +// UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension +// that matches n elements in any order. We support up to n=10 arguments. +// +// If you have >10 elements, consider UnorderedElementsAreArray() or +// UnorderedPointwise() instead. + +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple<> > +UnorderedElementsAre() { + typedef ::testing::tuple<> Args; + return internal::UnorderedElementsAreMatcher(Args()); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1) { + typedef ::testing::tuple< + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3, e4)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3, e4, e5)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3, e4, e5, + e6)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3, e4, e5, + e6, e7)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7, const T8& e8) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3, e4, e5, + e6, e7, e8)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3, e4, e5, + e6, e7, e8, e9)); +} + +template +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> > +UnorderedElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4, + const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9, + const T10& e10) { + typedef ::testing::tuple< + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type, + typename internal::DecayArray::type> Args; + return internal::UnorderedElementsAreMatcher(Args(e1, e2, e3, e4, e5, + e6, e7, e8, e9, e10)); +} + +// AllOf(m1, m2, ..., mk) matches any value that matches all of the given +// sub-matchers. AllOf is called fully qualified to prevent ADL from firing. + +template +inline typename internal::AllOfResult2::type +AllOf(M1 m1, M2 m2) { + return typename internal::AllOfResult2::type( + m1, + m2); +} + +template +inline typename internal::AllOfResult3::type +AllOf(M1 m1, M2 m2, M3 m3) { + return typename internal::AllOfResult3::type( + m1, + ::testing::AllOf(m2, m3)); +} + +template +inline typename internal::AllOfResult4::type +AllOf(M1 m1, M2 m2, M3 m3, M4 m4) { + return typename internal::AllOfResult4::type( + ::testing::AllOf(m1, m2), + ::testing::AllOf(m3, m4)); +} + +template +inline typename internal::AllOfResult5::type +AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5) { + return typename internal::AllOfResult5::type( + ::testing::AllOf(m1, m2), + ::testing::AllOf(m3, m4, m5)); +} + +template +inline typename internal::AllOfResult6::type +AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6) { + return typename internal::AllOfResult6::type( + ::testing::AllOf(m1, m2, m3), + ::testing::AllOf(m4, m5, m6)); +} + +template +inline typename internal::AllOfResult7::type +AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7) { + return typename internal::AllOfResult7::type( + ::testing::AllOf(m1, m2, m3), + ::testing::AllOf(m4, m5, m6, m7)); +} + +template +inline typename internal::AllOfResult8::type +AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8) { + return typename internal::AllOfResult8::type( + ::testing::AllOf(m1, m2, m3, m4), + ::testing::AllOf(m5, m6, m7, m8)); +} + +template +inline typename internal::AllOfResult9::type +AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9) { + return typename internal::AllOfResult9::type( + ::testing::AllOf(m1, m2, m3, m4), + ::testing::AllOf(m5, m6, m7, m8, m9)); +} + +template +inline typename internal::AllOfResult10::type +AllOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9, M10 m10) { + return typename internal::AllOfResult10::type( + ::testing::AllOf(m1, m2, m3, m4, m5), + ::testing::AllOf(m6, m7, m8, m9, m10)); +} + +// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given +// sub-matchers. AnyOf is called fully qualified to prevent ADL from firing. + +template +inline typename internal::AnyOfResult2::type +AnyOf(M1 m1, M2 m2) { + return typename internal::AnyOfResult2::type( + m1, + m2); +} + +template +inline typename internal::AnyOfResult3::type +AnyOf(M1 m1, M2 m2, M3 m3) { + return typename internal::AnyOfResult3::type( + m1, + ::testing::AnyOf(m2, m3)); +} + +template +inline typename internal::AnyOfResult4::type +AnyOf(M1 m1, M2 m2, M3 m3, M4 m4) { + return typename internal::AnyOfResult4::type( + ::testing::AnyOf(m1, m2), + ::testing::AnyOf(m3, m4)); +} + +template +inline typename internal::AnyOfResult5::type +AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5) { + return typename internal::AnyOfResult5::type( + ::testing::AnyOf(m1, m2), + ::testing::AnyOf(m3, m4, m5)); +} + +template +inline typename internal::AnyOfResult6::type +AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6) { + return typename internal::AnyOfResult6::type( + ::testing::AnyOf(m1, m2, m3), + ::testing::AnyOf(m4, m5, m6)); +} + +template +inline typename internal::AnyOfResult7::type +AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7) { + return typename internal::AnyOfResult7::type( + ::testing::AnyOf(m1, m2, m3), + ::testing::AnyOf(m4, m5, m6, m7)); +} + +template +inline typename internal::AnyOfResult8::type +AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8) { + return typename internal::AnyOfResult8::type( + ::testing::AnyOf(m1, m2, m3, m4), + ::testing::AnyOf(m5, m6, m7, m8)); +} + +template +inline typename internal::AnyOfResult9::type +AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9) { + return typename internal::AnyOfResult9::type( + ::testing::AnyOf(m1, m2, m3, m4), + ::testing::AnyOf(m5, m6, m7, m8, m9)); +} + +template +inline typename internal::AnyOfResult10::type +AnyOf(M1 m1, M2 m2, M3 m3, M4 m4, M5 m5, M6 m6, M7 m7, M8 m8, M9 m9, M10 m10) { + return typename internal::AnyOfResult10::type( + ::testing::AnyOf(m1, m2, m3, m4, m5), + ::testing::AnyOf(m6, m7, m8, m9, m10)); +} + +} // namespace testing + + +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax +// +// MATCHER(name, description_string) { statements; } +// +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. +// +// The description string documents what the matcher does, and is used +// to generate the failure message when the match fails. Since a +// MATCHER() is usually defined in a header file shared by multiple +// C++ source files, we require the description to be a C-string +// literal to avoid possible side effects. It can be empty, in which +// case we'll use the sequence of words in the matcher name as the +// description. +// +// For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Argument Type +// ============= +// +// Note that the type of the value being matched (arg_type) is +// determined by the context in which you use the matcher and is +// supplied to you by the compiler, so you don't need to worry about +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Parameterizing Matchers +// ======================= +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to +// support multi-parameter matchers. +// +// Describing Parameterized Matchers +// ================================= +// +// The last argument to MATCHER*() is a string-typed expression. The +// expression can reference all of the matcher's parameters and a +// special bool-typed variable named 'negation'. When 'negation' is +// false, the expression should evaluate to the matcher's description; +// otherwise it should evaluate to the description of the negation of +// the matcher. For example, +// +// using testing::PrintToString; +// +// MATCHER_P2(InClosedRange, low, hi, +// std::string(negation ? "is not" : "is") + " in range [" + +// PrintToString(low) + ", " + PrintToString(hi) + "]") { +// return low <= arg && arg <= hi; +// } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: is in range [4, 6] +// ... +// Expected: is not in range [2, 4] +// +// If you specify "" as the description, the failure message will +// contain the sequence of words in the matcher name followed by the +// parameter values printed as a tuple. For example, +// +// MATCHER_P2(InClosedRange, low, hi, "") { ... } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: in closed range (4, 6) +// ... +// Expected: not (in closed range (2, 4)) +// +// Types of Matcher Parameters +// =========================== +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template +// FooMatcherPk +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// Caveats +// ======= +// +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). +// +// MATCHER*() can only be used in a namespace scope. The reason is +// that C++ doesn't yet allow function-local types to be used to +// instantiate templates. The up-coming C++0x standard will fix this. +// Once that's done, we'll consider supporting using MATCHER*() inside +// a function. +// +// More Information +// ================ +// +// To learn more about using these macros, please search for 'MATCHER' +// on https://github.com/google/googletest/blob/master/googlemock/docs/ +// CookBook.md + +#define MATCHER(name, description)\ + class name##Matcher {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl()\ + {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple<>()));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl());\ + }\ + name##Matcher() {\ + }\ + private:\ + };\ + inline name##Matcher name() {\ + return name##Matcher();\ + }\ + template \ + bool name##Matcher::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P(name, p0, description)\ + template \ + class name##MatcherP {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + explicit gmock_Impl(p0##_type gmock_p0)\ + : p0(::testing::internal::move(gmock_p0)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0));\ + }\ + explicit name##MatcherP(p0##_type gmock_p0) : \ + p0(::testing::internal::move(gmock_p0)) {\ + }\ + p0##_type const p0;\ + private:\ + };\ + template \ + inline name##MatcherP name(p0##_type p0) {\ + return name##MatcherP(p0);\ + }\ + template \ + template \ + bool name##MatcherP::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P2(name, p0, p1, description)\ + template \ + class name##MatcherP2 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1));\ + }\ + name##MatcherP2(p0##_type gmock_p0, \ + p1##_type gmock_p1) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + private:\ + };\ + template \ + inline name##MatcherP2 name(p0##_type p0, \ + p1##_type p1) {\ + return name##MatcherP2(p0, p1);\ + }\ + template \ + template \ + bool name##MatcherP2::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P3(name, p0, p1, p2, description)\ + template \ + class name##MatcherP3 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, \ + p2)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2));\ + }\ + name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + private:\ + };\ + template \ + inline name##MatcherP3 name(p0##_type p0, \ + p1##_type p1, p2##_type p2) {\ + return name##MatcherP3(p0, p1, p2);\ + }\ + template \ + template \ + bool name##MatcherP3::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P4(name, p0, p1, p2, p3, description)\ + template \ + class name##MatcherP4 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, p2, p3)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3));\ + }\ + name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, \ + p3##_type gmock_p3) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + private:\ + };\ + template \ + inline name##MatcherP4 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3) {\ + return name##MatcherP4(p0, \ + p1, p2, p3);\ + }\ + template \ + template \ + bool name##MatcherP4::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\ + template \ + class name##MatcherP5 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, p2, p3, p4)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4));\ + }\ + name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, \ + p4##_type gmock_p4) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + private:\ + };\ + template \ + inline name##MatcherP5 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4) {\ + return name##MatcherP5(p0, p1, p2, p3, p4);\ + }\ + template \ + template \ + bool name##MatcherP5::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\ + template \ + class name##MatcherP6 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, p2, p3, p4, p5)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5));\ + }\ + name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + private:\ + };\ + template \ + inline name##MatcherP6 name(p0##_type p0, p1##_type p1, p2##_type p2, \ + p3##_type p3, p4##_type p4, p5##_type p5) {\ + return name##MatcherP6(p0, p1, p2, p3, p4, p5);\ + }\ + template \ + template \ + bool name##MatcherP6::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\ + template \ + class name##MatcherP7 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, p2, p3, p4, p5, \ + p6)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6));\ + }\ + name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, \ + p6##_type gmock_p6) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + private:\ + };\ + template \ + inline name##MatcherP7 name(p0##_type p0, p1##_type p1, \ + p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6) {\ + return name##MatcherP7(p0, p1, p2, p3, p4, p5, p6);\ + }\ + template \ + template \ + bool name##MatcherP7::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\ + template \ + class name##MatcherP8 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, p2, \ + p3, p4, p5, p6, p7)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7));\ + }\ + name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, \ + p7##_type gmock_p7) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + private:\ + };\ + template \ + inline name##MatcherP8 name(p0##_type p0, \ + p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ + p6##_type p6, p7##_type p7) {\ + return name##MatcherP8(p0, p1, p2, p3, p4, p5, \ + p6, p7);\ + }\ + template \ + template \ + bool name##MatcherP8::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\ + template \ + class name##MatcherP9 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)), \ + p8(::testing::internal::move(gmock_p8)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8));\ + }\ + name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)), \ + p8(::testing::internal::move(gmock_p8)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + private:\ + };\ + template \ + inline name##MatcherP9 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ + p8##_type p8) {\ + return name##MatcherP9(p0, p1, p2, \ + p3, p4, p5, p6, p7, p8);\ + }\ + template \ + template \ + bool name##MatcherP9::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\ + template \ + class name##MatcherP10 {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ + p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ + p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ + p9##_type gmock_p9)\ + : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)), \ + p8(::testing::internal::move(gmock_p8)), \ + p9(::testing::internal::move(gmock_p9)) {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + p9##_type const p9;\ + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\ + }\ + name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \ + p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ + p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ + p8##_type gmock_p8, \ + p9##_type gmock_p9) : p0(::testing::internal::move(gmock_p0)), \ + p1(::testing::internal::move(gmock_p1)), \ + p2(::testing::internal::move(gmock_p2)), \ + p3(::testing::internal::move(gmock_p3)), \ + p4(::testing::internal::move(gmock_p4)), \ + p5(::testing::internal::move(gmock_p5)), \ + p6(::testing::internal::move(gmock_p6)), \ + p7(::testing::internal::move(gmock_p7)), \ + p8(::testing::internal::move(gmock_p8)), \ + p9(::testing::internal::move(gmock_p9)) {\ + }\ + p0##_type const p0;\ + p1##_type const p1;\ + p2##_type const p2;\ + p3##_type const p3;\ + p4##_type const p4;\ + p5##_type const p5;\ + p6##_type const p6;\ + p7##_type const p7;\ + p8##_type const p8;\ + p9##_type const p9;\ + private:\ + };\ + template \ + inline name##MatcherP10 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ + p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ + p9##_type p9) {\ + return name##MatcherP10(p0, \ + p1, p2, p3, p4, p5, p6, p7, p8, p9);\ + }\ + template \ + template \ + bool name##MatcherP10::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h.pump b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h.pump new file mode 100644 index 0000000..4b62844 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-matchers.h.pump @@ -0,0 +1,675 @@ +$$ -*- mode: c++; -*- +$$ This is a Pump source file. Please use Pump to convert +$$ it to gmock-generated-matchers.h. +$$ +$var n = 10 $$ The maximum arity we support. +$$ }} This line fixes auto-indentation of the following code in Emacs. +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used variadic matchers. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ + +#include +#include +#include +#include +#include "gmock/gmock-matchers.h" + +namespace testing { +namespace internal { + +$range i 0..n-1 + +// The type of the i-th (0-based) field of Tuple. +#define GMOCK_FIELD_TYPE_(Tuple, i) \ + typename ::testing::tuple_element::type + +// TupleFields is for selecting fields from a +// tuple of type Tuple. It has two members: +// +// type: a tuple type whose i-th field is the ki-th field of Tuple. +// GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple. +// +// For example, in class TupleFields, 2, 0>, we have: +// +// type is tuple, and +// GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true). + +template +class TupleFields; + +// This generic version is used when there are $n selectors. +template +class TupleFields { + public: + typedef ::testing::tuple<$for i, [[GMOCK_FIELD_TYPE_(Tuple, k$i)]]> type; + static type GetSelectedFields(const Tuple& t) { + return type($for i, [[get(t)]]); + } +}; + +// The following specialization is used for 0 ~ $(n-1) selectors. + +$for i [[ +$$ }}} +$range j 0..i-1 +$range k 0..n-1 + +template +class TupleFields { + public: + typedef ::testing::tuple<$for j, [[GMOCK_FIELD_TYPE_(Tuple, k$j)]]> type; + static type GetSelectedFields(const Tuple& $if i==0 [[/* t */]] $else [[t]]) { + return type($for j, [[get(t)]]); + } +}; + +]] + +#undef GMOCK_FIELD_TYPE_ + +// Implements the Args() matcher. + +$var ks = [[$for i, [[k$i]]]] +template +class ArgsMatcherImpl : public MatcherInterface { + public: + // ArgsTuple may have top-level const or reference modifiers. + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple; + typedef typename internal::TupleFields::type SelectedArgs; + typedef Matcher MonomorphicInnerMatcher; + + template + explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher) + : inner_matcher_(SafeMatcherCast(inner_matcher)) {} + + virtual bool MatchAndExplain(ArgsTuple args, + MatchResultListener* listener) const { + const SelectedArgs& selected_args = GetSelectedArgs(args); + if (!listener->IsInterested()) + return inner_matcher_.Matches(selected_args); + + PrintIndices(listener->stream()); + *listener << "are " << PrintToString(selected_args); + + StringMatchResultListener inner_listener; + const bool match = inner_matcher_.MatchAndExplain(selected_args, + &inner_listener); + PrintIfNotEmpty(inner_listener.str(), listener->stream()); + return match; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "are a tuple "; + PrintIndices(os); + inner_matcher_.DescribeTo(os); + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "are a tuple "; + PrintIndices(os); + inner_matcher_.DescribeNegationTo(os); + } + + private: + static SelectedArgs GetSelectedArgs(ArgsTuple args) { + return TupleFields::GetSelectedFields(args); + } + + // Prints the indices of the selected fields. + static void PrintIndices(::std::ostream* os) { + *os << "whose fields ("; + const int indices[$n] = { $ks }; + for (int i = 0; i < $n; i++) { + if (indices[i] < 0) + break; + + if (i >= 1) + *os << ", "; + + *os << "#" << indices[i]; + } + *os << ") "; + } + + const MonomorphicInnerMatcher inner_matcher_; + + GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl); +}; + +template +class ArgsMatcher { + public: + explicit ArgsMatcher(const InnerMatcher& inner_matcher) + : inner_matcher_(inner_matcher) {} + + template + operator Matcher() const { + return MakeMatcher(new ArgsMatcherImpl(inner_matcher_)); + } + + private: + const InnerMatcher inner_matcher_; + + GTEST_DISALLOW_ASSIGN_(ArgsMatcher); +}; + +// A set of metafunctions for computing the result type of AllOf. +// AllOf(m1, ..., mN) returns +// AllOfResultN::type. + +// Although AllOf isn't defined for one argument, AllOfResult1 is defined +// to simplify the implementation. +template +struct AllOfResult1 { + typedef M1 type; +}; + +$range i 1..n + +$range i 2..n +$for i [[ +$range j 2..i +$var m = i/2 +$range k 1..m +$range t m+1..i + +template +struct AllOfResult$i { + typedef BothOfMatcher< + typename AllOfResult$m<$for k, [[M$k]]>::type, + typename AllOfResult$(i-m)<$for t, [[M$t]]>::type + > type; +}; + +]] + +// A set of metafunctions for computing the result type of AnyOf. +// AnyOf(m1, ..., mN) returns +// AnyOfResultN::type. + +// Although AnyOf isn't defined for one argument, AnyOfResult1 is defined +// to simplify the implementation. +template +struct AnyOfResult1 { + typedef M1 type; +}; + +$range i 1..n + +$range i 2..n +$for i [[ +$range j 2..i +$var m = i/2 +$range k 1..m +$range t m+1..i + +template +struct AnyOfResult$i { + typedef EitherOfMatcher< + typename AnyOfResult$m<$for k, [[M$k]]>::type, + typename AnyOfResult$(i-m)<$for t, [[M$t]]>::type + > type; +}; + +]] + +} // namespace internal + +// Args(a_matcher) matches a tuple if the selected +// fields of it matches a_matcher. C++ doesn't support default +// arguments for function templates, so we have to overload it. + +$range i 0..n +$for i [[ +$range j 1..i +template <$for j [[int k$j, ]]typename InnerMatcher> +inline internal::ArgsMatcher +Args(const InnerMatcher& matcher) { + return internal::ArgsMatcher(matcher); +} + + +]] +// ElementsAre(e_1, e_2, ... e_n) matches an STL-style container with +// n elements, where the i-th element in the container must +// match the i-th argument in the list. Each argument of +// ElementsAre() can be either a value or a matcher. We support up to +// $n arguments. +// +// The use of DecayArray in the implementation allows ElementsAre() +// to accept string literals, whose type is const char[N], but we +// want to treat them as const char*. +// +// NOTE: Since ElementsAre() cares about the order of the elements, it +// must not be used with containers whose elements's order is +// undefined (e.g. hash_map). + +$range i 0..n +$for i [[ + +$range j 1..i + +$if i>0 [[ + +template <$for j, [[typename T$j]]> +]] + +inline internal::ElementsAreMatcher< + ::testing::tuple< +$for j, [[ + + typename internal::DecayArray::type]]> > +ElementsAre($for j, [[const T$j& e$j]]) { + typedef ::testing::tuple< +$for j, [[ + + typename internal::DecayArray::type]]> Args; + return internal::ElementsAreMatcher(Args($for j, [[e$j]])); +} + +]] + +// UnorderedElementsAre(e_1, e_2, ..., e_n) is an ElementsAre extension +// that matches n elements in any order. We support up to n=$n arguments. +// +// If you have >$n elements, consider UnorderedElementsAreArray() or +// UnorderedPointwise() instead. + +$range i 0..n +$for i [[ + +$range j 1..i + +$if i>0 [[ + +template <$for j, [[typename T$j]]> +]] + +inline internal::UnorderedElementsAreMatcher< + ::testing::tuple< +$for j, [[ + + typename internal::DecayArray::type]]> > +UnorderedElementsAre($for j, [[const T$j& e$j]]) { + typedef ::testing::tuple< +$for j, [[ + + typename internal::DecayArray::type]]> Args; + return internal::UnorderedElementsAreMatcher(Args($for j, [[e$j]])); +} + +]] + +// AllOf(m1, m2, ..., mk) matches any value that matches all of the given +// sub-matchers. AllOf is called fully qualified to prevent ADL from firing. + +$range i 2..n +$for i [[ +$range j 1..i +$var m = i/2 +$range k 1..m +$range t m+1..i + +template <$for j, [[typename M$j]]> +inline typename internal::AllOfResult$i<$for j, [[M$j]]>::type +AllOf($for j, [[M$j m$j]]) { + return typename internal::AllOfResult$i<$for j, [[M$j]]>::type( + $if m == 1 [[m1]] $else [[::testing::AllOf($for k, [[m$k]])]], + $if m+1 == i [[m$i]] $else [[::testing::AllOf($for t, [[m$t]])]]); +} + +]] + +// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given +// sub-matchers. AnyOf is called fully qualified to prevent ADL from firing. + +$range i 2..n +$for i [[ +$range j 1..i +$var m = i/2 +$range k 1..m +$range t m+1..i + +template <$for j, [[typename M$j]]> +inline typename internal::AnyOfResult$i<$for j, [[M$j]]>::type +AnyOf($for j, [[M$j m$j]]) { + return typename internal::AnyOfResult$i<$for j, [[M$j]]>::type( + $if m == 1 [[m1]] $else [[::testing::AnyOf($for k, [[m$k]])]], + $if m+1 == i [[m$i]] $else [[::testing::AnyOf($for t, [[m$t]])]]); +} + +]] + +} // namespace testing +$$ } // This Pump meta comment fixes auto-indentation in Emacs. It will not +$$ // show up in the generated code. + + +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax +// +// MATCHER(name, description_string) { statements; } +// +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. +// +// The description string documents what the matcher does, and is used +// to generate the failure message when the match fails. Since a +// MATCHER() is usually defined in a header file shared by multiple +// C++ source files, we require the description to be a C-string +// literal to avoid possible side effects. It can be empty, in which +// case we'll use the sequence of words in the matcher name as the +// description. +// +// For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Argument Type +// ============= +// +// Note that the type of the value being matched (arg_type) is +// determined by the context in which you use the matcher and is +// supplied to you by the compiler, so you don't need to worry about +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Parameterizing Matchers +// ======================= +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to +// support multi-parameter matchers. +// +// Describing Parameterized Matchers +// ================================= +// +// The last argument to MATCHER*() is a string-typed expression. The +// expression can reference all of the matcher's parameters and a +// special bool-typed variable named 'negation'. When 'negation' is +// false, the expression should evaluate to the matcher's description; +// otherwise it should evaluate to the description of the negation of +// the matcher. For example, +// +// using testing::PrintToString; +// +// MATCHER_P2(InClosedRange, low, hi, +// std::string(negation ? "is not" : "is") + " in range [" + +// PrintToString(low) + ", " + PrintToString(hi) + "]") { +// return low <= arg && arg <= hi; +// } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: is in range [4, 6] +// ... +// Expected: is not in range [2, 4] +// +// If you specify "" as the description, the failure message will +// contain the sequence of words in the matcher name followed by the +// parameter values printed as a tuple. For example, +// +// MATCHER_P2(InClosedRange, low, hi, "") { ... } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: in closed range (4, 6) +// ... +// Expected: not (in closed range (2, 4)) +// +// Types of Matcher Parameters +// =========================== +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template +// FooMatcherPk +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// Caveats +// ======= +// +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). +// +// MATCHER*() can only be used in a namespace scope. The reason is +// that C++ doesn't yet allow function-local types to be used to +// instantiate templates. The up-coming C++0x standard will fix this. +// Once that's done, we'll consider supporting using MATCHER*() inside +// a function. +// +// More Information +// ================ +// +// To learn more about using these macros, please search for 'MATCHER' +// on https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md + +$range i 0..n +$for i + +[[ +$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]] + $else [[MATCHER_P$i]]]] +$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]] + $else [[P$i]]]]]] +$range j 0..i-1 +$var template = [[$if i==0 [[]] $else [[ + + template <$for j, [[typename p$j##_type]]>\ +]]]] +$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] +$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::testing::internal::move(gmock_p$j))]]]]]] +$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::testing::internal::move(gmock_p$j))]]]]]] +$var params = [[$for j, [[p$j]]]] +$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] +$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] +$var param_field_decls = [[$for j +[[ + + p$j##_type const p$j;\ +]]]] +$var param_field_decls2 = [[$for j +[[ + + p$j##_type const p$j;\ +]]]] + +#define $macro_name(name$for j [[, p$j]], description)\$template + class $class_name {\ + public:\ + template \ + class gmock_Impl : public ::testing::MatcherInterface<\ + GTEST_REFERENCE_TO_CONST_(arg_type)> {\ + public:\ + [[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\ + $impl_inits {}\ + virtual bool MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener) const;\ + virtual void DescribeTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(false);\ + }\ + virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ + *gmock_os << FormatDescription(true);\ + }\$param_field_decls + private:\ + ::std::string FormatDescription(bool negation) const {\ + ::std::string gmock_description = (description);\ + if (!gmock_description.empty())\ + return gmock_description;\ + return ::testing::internal::FormatMatcherDescription(\ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ + ::testing::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\ + }\ + };\ + template \ + operator ::testing::Matcher() const {\ + return ::testing::Matcher(\ + new gmock_Impl($params));\ + }\ + [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\ + }\$param_field_decls2 + private:\ + };\$template + inline $class_name$param_types name($param_types_and_names) {\ + return $class_name$param_types($params);\ + }\$template + template \ + bool $class_name$param_types::gmock_Impl::MatchAndExplain(\ + GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ + const +]] + + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h new file mode 100644 index 0000000..8e56873 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h @@ -0,0 +1,458 @@ +// This file was GENERATED by command: +// pump.py gmock-generated-nice-strict.h.pump +// DO NOT EDIT BY HAND!!! + +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Implements class templates NiceMock, NaggyMock, and StrictMock. +// +// Given a mock class MockFoo that is created using Google Mock, +// NiceMock is a subclass of MockFoo that allows +// uninteresting calls (i.e. calls to mock methods that have no +// EXPECT_CALL specs), NaggyMock is a subclass of MockFoo +// that prints a warning when an uninteresting call occurs, and +// StrictMock is a subclass of MockFoo that treats all +// uninteresting calls as errors. +// +// Currently a mock is naggy by default, so MockFoo and +// NaggyMock behave like the same. However, we will soon +// switch the default behavior of mocks to be nice, as that in general +// leads to more maintainable tests. When that happens, MockFoo will +// stop behaving like NaggyMock and start behaving like +// NiceMock. +// +// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of +// their respective base class. Therefore you can write +// NiceMock(5, "a") to construct a nice mock where MockFoo +// has a constructor that accepts (int, const char*), for example. +// +// A known limitation is that NiceMock, NaggyMock, +// and StrictMock only works for mock methods defined using +// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. +// If a mock method is defined in a base class of MockFoo, the "nice" +// or "strict" modifier may not affect it, depending on the compiler. +// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT +// supported. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-port.h" + +namespace testing { + +template +class NiceMock : public MockClass { + public: + NiceMock() : MockClass() { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + +#if GTEST_LANG_CXX11 + // Ideally, we would inherit base class's constructors through a using + // declaration, which would preserve their visibility. However, many existing + // tests rely on the fact that current implementation reexports protected + // constructors as public. These tests would need to be cleaned up first. + + // Single argument constructor is special-cased so that it can be + // made explicit. + template + explicit NiceMock(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(A1&& arg1, A2&& arg2, An&&... args) + : MockClass(std::forward(arg1), std::forward(arg2), + std::forward(args)...) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } +#else + // C++98 doesn't have variadic templates, so we have to define one + // for each arity. + template + explicit NiceMock(const A1& a1) : MockClass(a1) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + template + NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) : MockClass(a1, a2, a3, a4) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5) : MockClass(a1, a2, a3, a4, a5) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5, + a6, a7) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1, + a2, a3, a4, a5, a6, a7, a8) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, + const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, + const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { + ::testing::Mock::AllowUninterestingCalls( + internal::ImplicitCast_(this)); + } + +#endif // GTEST_LANG_CXX11 + + ~NiceMock() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock); +}; + +template +class NaggyMock : public MockClass { + public: + NaggyMock() : MockClass() { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + +#if GTEST_LANG_CXX11 + // Ideally, we would inherit base class's constructors through a using + // declaration, which would preserve their visibility. However, many existing + // tests rely on the fact that current implementation reexports protected + // constructors as public. These tests would need to be cleaned up first. + + // Single argument constructor is special-cased so that it can be + // made explicit. + template + explicit NaggyMock(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(A1&& arg1, A2&& arg2, An&&... args) + : MockClass(std::forward(arg1), std::forward(arg2), + std::forward(args)...) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } +#else + // C++98 doesn't have variadic templates, so we have to define one + // for each arity. + template + explicit NaggyMock(const A1& a1) : MockClass(a1) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + template + NaggyMock(const A1& a1, const A2& a2) : MockClass(a1, a2) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) : MockClass(a1, a2, a3, a4) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5) : MockClass(a1, a2, a3, a4, a5) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5, + a6, a7) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1, + a2, a3, a4, a5, a6, a7, a8) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, + const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + NaggyMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, + const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { + ::testing::Mock::WarnUninterestingCalls( + internal::ImplicitCast_(this)); + } + +#endif // GTEST_LANG_CXX11 + + ~NaggyMock() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(NaggyMock); +}; + +template +class StrictMock : public MockClass { + public: + StrictMock() : MockClass() { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + +#if GTEST_LANG_CXX11 + // Ideally, we would inherit base class's constructors through a using + // declaration, which would preserve their visibility. However, many existing + // tests rely on the fact that current implementation reexports protected + // constructors as public. These tests would need to be cleaned up first. + + // Single argument constructor is special-cased so that it can be + // made explicit. + template + explicit StrictMock(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(A1&& arg1, A2&& arg2, An&&... args) + : MockClass(std::forward(arg1), std::forward(arg2), + std::forward(args)...) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } +#else + // C++98 doesn't have variadic templates, so we have to define one + // for each arity. + template + explicit StrictMock(const A1& a1) : MockClass(a1) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + template + StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3, + const A4& a4) : MockClass(a1, a2, a3, a4) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5) : MockClass(a1, a2, a3, a4, a5) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5, + a6, a7) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1, + a2, a3, a4, a5, a6, a7, a8) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, + const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + + template + StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4, + const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9, + const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) { + ::testing::Mock::FailUninterestingCalls( + internal::ImplicitCast_(this)); + } + +#endif // GTEST_LANG_CXX11 + + ~StrictMock() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock); +}; + +// The following specializations catch some (relatively more common) +// user errors of nesting nice and strict mocks. They do NOT catch +// all possible errors. + +// These specializations are declared but not defined, as NiceMock, +// NaggyMock, and StrictMock cannot be nested. + +template +class NiceMock >; +template +class NiceMock >; +template +class NiceMock >; + +template +class NaggyMock >; +template +class NaggyMock >; +template +class NaggyMock >; + +template +class StrictMock >; +template +class StrictMock >; +template +class StrictMock >; + +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump new file mode 100644 index 0000000..2f443ae --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-generated-nice-strict.h.pump @@ -0,0 +1,178 @@ +$$ -*- mode: c++; -*- +$$ This is a Pump source file. Please use Pump to convert +$$ it to gmock-generated-nice-strict.h. +$$ +$var n = 10 $$ The maximum arity we support. +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Implements class templates NiceMock, NaggyMock, and StrictMock. +// +// Given a mock class MockFoo that is created using Google Mock, +// NiceMock is a subclass of MockFoo that allows +// uninteresting calls (i.e. calls to mock methods that have no +// EXPECT_CALL specs), NaggyMock is a subclass of MockFoo +// that prints a warning when an uninteresting call occurs, and +// StrictMock is a subclass of MockFoo that treats all +// uninteresting calls as errors. +// +// Currently a mock is naggy by default, so MockFoo and +// NaggyMock behave like the same. However, we will soon +// switch the default behavior of mocks to be nice, as that in general +// leads to more maintainable tests. When that happens, MockFoo will +// stop behaving like NaggyMock and start behaving like +// NiceMock. +// +// NiceMock, NaggyMock, and StrictMock "inherit" the constructors of +// their respective base class. Therefore you can write +// NiceMock(5, "a") to construct a nice mock where MockFoo +// has a constructor that accepts (int, const char*), for example. +// +// A known limitation is that NiceMock, NaggyMock, +// and StrictMock only works for mock methods defined using +// the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class. +// If a mock method is defined in a base class of MockFoo, the "nice" +// or "strict" modifier may not affect it, depending on the compiler. +// In particular, nesting NiceMock, NaggyMock, and StrictMock is NOT +// supported. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-port.h" + +namespace testing { + +$range kind 0..2 +$for kind [[ + +$var clazz=[[$if kind==0 [[NiceMock]] + $elif kind==1 [[NaggyMock]] + $else [[StrictMock]]]] + +$var method=[[$if kind==0 [[AllowUninterestingCalls]] + $elif kind==1 [[WarnUninterestingCalls]] + $else [[FailUninterestingCalls]]]] + +template +class $clazz : public MockClass { + public: + $clazz() : MockClass() { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } + +#if GTEST_LANG_CXX11 + // Ideally, we would inherit base class's constructors through a using + // declaration, which would preserve their visibility. However, many existing + // tests rely on the fact that current implementation reexports protected + // constructors as public. These tests would need to be cleaned up first. + + // Single argument constructor is special-cased so that it can be + // made explicit. + template + explicit $clazz(A&& arg) : MockClass(std::forward(arg)) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } + + template + $clazz(A1&& arg1, A2&& arg2, An&&... args) + : MockClass(std::forward(arg1), std::forward(arg2), + std::forward(args)...) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } +#else + // C++98 doesn't have variadic templates, so we have to define one + // for each arity. + template + explicit $clazz(const A1& a1) : MockClass(a1) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } + +$range i 2..n +$for i [[ +$range j 1..i + template <$for j, [[typename A$j]]> + $clazz($for j, [[const A$j& a$j]]) : MockClass($for j, [[a$j]]) { + ::testing::Mock::$method( + internal::ImplicitCast_(this)); + } + + +]] +#endif // GTEST_LANG_CXX11 + + ~$clazz() { + ::testing::Mock::UnregisterCallReaction( + internal::ImplicitCast_(this)); + } + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_($clazz); +}; + +]] + +// The following specializations catch some (relatively more common) +// user errors of nesting nice and strict mocks. They do NOT catch +// all possible errors. + +// These specializations are declared but not defined, as NiceMock, +// NaggyMock, and StrictMock cannot be nested. + +template +class NiceMock >; +template +class NiceMock >; +template +class NiceMock >; + +template +class NaggyMock >; +template +class NaggyMock >; +template +class NaggyMock >; + +template +class StrictMock >; +template +class StrictMock >; +template +class StrictMock >; + +} // namespace testing + +#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_ diff --git a/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-matchers.h b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-matchers.h new file mode 100644 index 0000000..c94f582 --- /dev/null +++ b/deps/rapidjson/thirdparty/gtest/googlemock/include/gmock/gmock-matchers.h @@ -0,0 +1,5255 @@ +// Copyright 2007, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * 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. +// * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT +// OWNER 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. +// +// Author: wan@google.com (Zhanyong Wan) + +// Google Mock - a framework for writing C++ mock classes. +// +// This file implements some commonly used argument matchers. More +// matchers can be defined by the user implementing the +// MatcherInterface interface if necessary. + +#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ +#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ + +#include +#include +#include +#include +#include // NOLINT +#include +#include +#include +#include +#include "gtest/gtest.h" +#include "gmock/internal/gmock-internal-utils.h" +#include "gmock/internal/gmock-port.h" + +#if GTEST_HAS_STD_INITIALIZER_LIST_ +# include // NOLINT -- must be after gtest.h +#endif + +namespace testing { + +// To implement a matcher Foo for type T, define: +// 1. a class FooMatcherImpl that implements the +// MatcherInterface interface, and +// 2. a factory function that creates a Matcher object from a +// FooMatcherImpl*. +// +// The two-level delegation design makes it possible to allow a user +// to write "v" instead of "Eq(v)" where a Matcher is expected, which +// is impossible if we pass matchers by pointers. It also eases +// ownership management as Matcher objects can now be copied like +// plain values. + +// MatchResultListener is an abstract class. Its << operator can be +// used by a matcher to explain why a value matches or doesn't match. +// +// TODO(wan@google.com): add method +// bool InterestedInWhy(bool result) const; +// to indicate whether the listener is interested in why the match +// result is 'result'. +class MatchResultListener { + public: + // Creates a listener object with the given underlying ostream. The + // listener does not own the ostream, and does not dereference it + // in the constructor or destructor. + explicit MatchResultListener(::std::ostream* os) : stream_(os) {} + virtual ~MatchResultListener() = 0; // Makes this class abstract. + + // Streams x to the underlying ostream; does nothing if the ostream + // is NULL. + template + MatchResultListener& operator<<(const T& x) { + if (stream_ != NULL) + *stream_ << x; + return *this; + } + + // Returns the underlying ostream. + ::std::ostream* stream() { return stream_; } + + // Returns true iff the listener is interested in an explanation of + // the match result. A matcher's MatchAndExplain() method can use + // this information to avoid generating the explanation when no one + // intends to hear it. + bool IsInterested() const { return stream_ != NULL; } + + private: + ::std::ostream* const stream_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); +}; + +inline MatchResultListener::~MatchResultListener() { +} + +// An instance of a subclass of this knows how to describe itself as a +// matcher. +class MatcherDescriberInterface { + public: + virtual ~MatcherDescriberInterface() {} + + // Describes this matcher to an ostream. The function should print + // a verb phrase that describes the property a value matching this + // matcher should have. The subject of the verb phrase is the value + // being matched. For example, the DescribeTo() method of the Gt(7) + // matcher prints "is greater than 7". + virtual void DescribeTo(::std::ostream* os) const = 0; + + // Describes the negation of this matcher to an ostream. For + // example, if the description of this matcher is "is greater than + // 7", the negated description could be "is not greater than 7". + // You are not required to override this when implementing + // MatcherInterface, but it is highly advised so that your matcher + // can produce good error messages. + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "not ("; + DescribeTo(os); + *os << ")"; + } +}; + +// The implementation of a matcher. +template +class MatcherInterface : public MatcherDescriberInterface { + public: + // Returns true iff the matcher matches x; also explains the match + // result to 'listener' if necessary (see the next paragraph), in + // the form of a non-restrictive relative clause ("which ...", + // "whose ...", etc) that describes x. For example, the + // MatchAndExplain() method of the Pointee(...) matcher should + // generate an explanation like "which points to ...". + // + // Implementations of MatchAndExplain() should add an explanation of + // the match result *if and only if* they can provide additional + // information that's not already present (or not obvious) in the + // print-out of x and the matcher's description. Whether the match + // succeeds is not a factor in deciding whether an explanation is + // needed, as sometimes the caller needs to print a failure message + // when the match succeeds (e.g. when the matcher is used inside + // Not()). + // + // For example, a "has at least 10 elements" matcher should explain + // what the actual element count is, regardless of the match result, + // as it is useful information to the reader; on the other hand, an + // "is empty" matcher probably only needs to explain what the actual + // size is when the match fails, as it's redundant to say that the + // size is 0 when the value is already known to be empty. + // + // You should override this method when defining a new matcher. + // + // It's the responsibility of the caller (Google Mock) to guarantee + // that 'listener' is not NULL. This helps to simplify a matcher's + // implementation when it doesn't care about the performance, as it + // can talk to 'listener' without checking its validity first. + // However, in order to implement dummy listeners efficiently, + // listener->stream() may be NULL. + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; + + // Inherits these methods from MatcherDescriberInterface: + // virtual void DescribeTo(::std::ostream* os) const = 0; + // virtual void DescribeNegationTo(::std::ostream* os) const; +}; + +namespace internal { + +// Converts a MatcherInterface to a MatcherInterface. +template +class MatcherInterfaceAdapter : public MatcherInterface { + public: + explicit MatcherInterfaceAdapter(const MatcherInterface* impl) + : impl_(impl) {} + virtual ~MatcherInterfaceAdapter() { delete impl_; } + + virtual void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + + virtual void DescribeNegationTo(::std::ostream* os) const { + impl_->DescribeNegationTo(os); + } + + virtual bool MatchAndExplain(const T& x, + MatchResultListener* listener) const { + return impl_->MatchAndExplain(x, listener); + } + + private: + const MatcherInterface* const impl_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter); +}; + +} // namespace internal + +// A match result listener that stores the explanation in a string. +class StringMatchResultListener : public MatchResultListener { + public: + StringMatchResultListener() : MatchResultListener(&ss_) {} + + // Returns the explanation accumulated so far. + std::string str() const { return ss_.str(); } + + // Clears the explanation accumulated so far. + void Clear() { ss_.str(""); } + + private: + ::std::stringstream ss_; + + GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener); +}; + +namespace internal { + +struct AnyEq { + template + bool operator()(const A& a, const B& b) const { return a == b; } +}; +struct AnyNe { + template + bool operator()(const A& a, const B& b) const { return a != b; } +}; +struct AnyLt { + template + bool operator()(const A& a, const B& b) const { return a < b; } +}; +struct AnyGt { + template + bool operator()(const A& a, const B& b) const { return a > b; } +}; +struct AnyLe { + template + bool operator()(const A& a, const B& b) const { return a <= b; } +}; +struct AnyGe { + template + bool operator()(const A& a, const B& b) const { return a >= b; } +}; + +// A match result listener that ignores the explanation. +class DummyMatchResultListener : public MatchResultListener { + public: + DummyMatchResultListener() : MatchResultListener(NULL) {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener); +}; + +// A match result listener that forwards the explanation to a given +// ostream. The difference between this and MatchResultListener is +// that the former is concrete. +class StreamMatchResultListener : public MatchResultListener { + public: + explicit StreamMatchResultListener(::std::ostream* os) + : MatchResultListener(os) {} + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); +}; + +// An internal class for implementing Matcher, which will derive +// from it. We put functionalities common to all Matcher +// specializations here to avoid code duplication. +template +class MatcherBase { + public: + // Returns true iff the matcher matches x; also explains the match + // result to 'listener'. + bool MatchAndExplain(GTEST_REFERENCE_TO_CONST_(T) x, + MatchResultListener* listener) const { + return impl_->MatchAndExplain(x, listener); + } + + // Returns true iff this matcher matches x. + bool Matches(GTEST_REFERENCE_TO_CONST_(T) x) const { + DummyMatchResultListener dummy; + return MatchAndExplain(x, &dummy); + } + + // Describes this matcher to an ostream. + void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + + // Describes the negation of this matcher to an ostream. + void DescribeNegationTo(::std::ostream* os) const { + impl_->DescribeNegationTo(os); + } + + // Explains why x matches, or doesn't match, the matcher. + void ExplainMatchResultTo(GTEST_REFERENCE_TO_CONST_(T) x, + ::std::ostream* os) const { + StreamMatchResultListener listener(os); + MatchAndExplain(x, &listener); + } + + // Returns the describer for this matcher object; retains ownership + // of the describer, which is only guaranteed to be alive when + // this matcher object is alive. + const MatcherDescriberInterface* GetDescriber() const { + return impl_.get(); + } + + protected: + MatcherBase() {} + + // Constructs a matcher from its implementation. + explicit MatcherBase( + const MatcherInterface* impl) + : impl_(impl) {} + + template + explicit MatcherBase( + const MatcherInterface* impl, + typename internal::EnableIf< + !internal::IsSame::value>::type* = + NULL) + : impl_(new internal::MatcherInterfaceAdapter(impl)) {} + + virtual ~MatcherBase() {} + + private: + // shared_ptr (util/gtl/shared_ptr.h) and linked_ptr have similar + // interfaces. The former dynamically allocates a chunk of memory + // to hold the reference count, while the latter tracks all + // references using a circular linked list without allocating + // memory. It has been observed that linked_ptr performs better in + // typical scenarios. However, shared_ptr can out-perform + // linked_ptr when there are many more uses of the copy constructor + // than the default constructor. + // + // If performance becomes a problem, we should see if using + // shared_ptr helps. + ::testing::internal::linked_ptr< + const MatcherInterface > + impl_; +}; + +} // namespace internal + +// A Matcher is a copyable and IMMUTABLE (except by assignment) +// object that can check whether a value of type T matches. The +// implementation of Matcher is just a linked_ptr to const +// MatcherInterface, so copying is fairly cheap. Don't inherit +// from Matcher! +template +class Matcher : public internal::MatcherBase { + public: + // Constructs a null matcher. Needed for storing Matcher objects in STL + // containers. A default-constructed matcher is not yet initialized. You + // cannot use it until a valid value has been assigned to it. + explicit Matcher() {} // NOLINT + + // Constructs a matcher from its implementation. + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + template + explicit Matcher(const MatcherInterface* impl, + typename internal::EnableIf::value>::type* = NULL) + : internal::MatcherBase(impl) {} + + // Implicit constructor here allows people to write + // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes + Matcher(T value); // NOLINT +}; + +// The following two specializations allow the user to write str +// instead of Eq(str) and "foo" instead of Eq("foo") when a std::string +// matcher is expected. +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a ::string object. + Matcher(const ::string& s); // NOLINT +#endif // GTEST_HAS_GLOBAL_STRING + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT +}; + +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a string object. + Matcher(const std::string& s); // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a ::string object. + Matcher(const ::string& s); // NOLINT +#endif // GTEST_HAS_GLOBAL_STRING + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT +}; + +#if GTEST_HAS_GLOBAL_STRING +// The following two specializations allow the user to write str +// instead of Eq(str) and "foo" instead of Eq("foo") when a ::string +// matcher is expected. +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a ::string object. + Matcher(const ::string& s); // NOLINT + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT +}; + +template <> +class GTEST_API_ Matcher< ::string> + : public internal::MatcherBase< ::string> { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase< ::string>(impl) {} + explicit Matcher(const MatcherInterface< ::string>* impl) + : internal::MatcherBase< ::string>(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a ::string object. + Matcher(const ::string& s); // NOLINT + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT +}; +#endif // GTEST_HAS_GLOBAL_STRING + +#if GTEST_HAS_ABSL +// The following two specializations allow the user to write str +// instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view +// matcher is expected. +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a ::string object. + Matcher(const ::string& s); // NOLINT +#endif // GTEST_HAS_GLOBAL_STRING + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT + + // Allows the user to pass absl::string_views directly. + Matcher(absl::string_view s); // NOLINT +}; + +template <> +class GTEST_API_ Matcher + : public internal::MatcherBase { + public: + Matcher() {} + + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a std::string object. + Matcher(const std::string& s); // NOLINT + +#if GTEST_HAS_GLOBAL_STRING + // Allows the user to write str instead of Eq(str) sometimes, where + // str is a ::string object. + Matcher(const ::string& s); // NOLINT +#endif // GTEST_HAS_GLOBAL_STRING + + // Allows the user to write "foo" instead of Eq("foo") sometimes. + Matcher(const char* s); // NOLINT + + // Allows the user to pass absl::string_views directly. + Matcher(absl::string_view s); // NOLINT +}; +#endif // GTEST_HAS_ABSL + +// Prints a matcher in a human-readable format. +template +std::ostream& operator<<(std::ostream& os, const Matcher& matcher) { + matcher.DescribeTo(&os); + return os; +} + +// The PolymorphicMatcher class template makes it easy to implement a +// polymorphic matcher (i.e. a matcher that can match values of more +// than one type, e.g. Eq(n) and NotNull()). +// +// To define a polymorphic matcher, a user should provide an Impl +// class that has a DescribeTo() method and a DescribeNegationTo() +// method, and define a member function (or member function template) +// +// bool MatchAndExplain(const Value& value, +// MatchResultListener* listener) const; +// +// See the definition of NotNull() for a complete example. +template +class PolymorphicMatcher { + public: + explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {} + + // Returns a mutable reference to the underlying matcher + // implementation object. + Impl& mutable_impl() { return impl_; } + + // Returns an immutable reference to the underlying matcher + // implementation object. + const Impl& impl() const { return impl_; } + + template + operator Matcher() const { + return Matcher(new MonomorphicImpl(impl_)); + } + + private: + template + class MonomorphicImpl : public MatcherInterface { + public: + explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} + + virtual void DescribeTo(::std::ostream* os) const { + impl_.DescribeTo(os); + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + impl_.DescribeNegationTo(os); + } + + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + return impl_.MatchAndExplain(x, listener); + } + + private: + const Impl impl_; + + GTEST_DISALLOW_ASSIGN_(MonomorphicImpl); + }; + + Impl impl_; + + GTEST_DISALLOW_ASSIGN_(PolymorphicMatcher); +}; + +// Creates a matcher from its implementation. This is easier to use +// than the Matcher constructor as it doesn't require you to +// explicitly write the template argument, e.g. +// +// MakeMatcher(foo); +// vs +// Matcher(foo); +template +inline Matcher MakeMatcher(const MatcherInterface* impl) { + return Matcher(impl); +} + +// Creates a polymorphic matcher from its implementation. This is +// easier to use than the PolymorphicMatcher constructor as it +// doesn't require you to explicitly write the template argument, e.g. +// +// MakePolymorphicMatcher(foo); +// vs +// PolymorphicMatcher(foo); +template +inline PolymorphicMatcher MakePolymorphicMatcher(const Impl& impl) { + return PolymorphicMatcher(impl); +} + +// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION +// and MUST NOT BE USED IN USER CODE!!! +namespace internal { + +// The MatcherCastImpl class template is a helper for implementing +// MatcherCast(). We need this helper in order to partially +// specialize the implementation of MatcherCast() (C++ allows +// class/struct templates to be partially specialized, but not +// function templates.). + +// This general version is used when MatcherCast()'s argument is a +// polymorphic matcher (i.e. something that can be converted to a +// Matcher but is not one yet; for example, Eq(value)) or a value (for +// example, "hello"). +template +class MatcherCastImpl { + public: + static Matcher Cast(const M& polymorphic_matcher_or_value) { + // M can be a polymorphic matcher, in which case we want to use + // its conversion operator to create Matcher. Or it can be a value + // that should be passed to the Matcher's constructor. + // + // We can't call Matcher(polymorphic_matcher_or_value) when M is a + // polymorphic matcher because it'll be ambiguous if T has an implicit + // constructor from M (this usually happens when T has an implicit + // constructor from any type). + // + // It won't work to unconditionally implict_cast + // polymorphic_matcher_or_value to Matcher because it won't trigger + // a user-defined conversion from M to T if one exists (assuming M is + // a value). + return CastImpl( + polymorphic_matcher_or_value, + BooleanConstant< + internal::ImplicitlyConvertible >::value>(), + BooleanConstant< + internal::ImplicitlyConvertible::value>()); + } + + private: + template + static Matcher CastImpl(const M& polymorphic_matcher_or_value, + BooleanConstant /* convertible_to_matcher */, + BooleanConstant) { + // M is implicitly convertible to Matcher, which means that either + // M is a polymorphic matcher or Matcher has an implicit constructor + // from M. In both cases using the implicit conversion will produce a + // matcher. + // + // Even if T has an implicit constructor from M, it won't be called because + // creating Matcher would require a chain of two user-defined conversions + // (first to create T from M and then to create Matcher from T). + return polymorphic_matcher_or_value; + } + + // M can't be implicitly converted to Matcher, so M isn't a polymorphic + // matcher. It's a value of a type implicitly convertible to T. Use direct + // initialization to create a matcher. + static Matcher CastImpl( + const M& value, BooleanConstant /* convertible_to_matcher */, + BooleanConstant /* convertible_to_T */) { + return Matcher(ImplicitCast_(value)); + } + + // M can't be implicitly converted to either Matcher or T. Attempt to use + // polymorphic matcher Eq(value) in this case. + // + // Note that we first attempt to perform an implicit cast on the value and + // only fall back to the polymorphic Eq() matcher afterwards because the + // latter calls bool operator==(const Lhs& lhs, const Rhs& rhs) in the end + // which might be undefined even when Rhs is implicitly convertible to Lhs + // (e.g. std::pair vs. std::pair). + // + // We don't define this method inline as we need the declaration of Eq(). + static Matcher CastImpl( + const M& value, BooleanConstant /* convertible_to_matcher */, + BooleanConstant /* convertible_to_T */); +}; + +// This more specialized version is used when MatcherCast()'s argument +// is already a Matcher. This only compiles when type T can be +// statically converted to type U. +template +class MatcherCastImpl > { + public: + static Matcher Cast(const Matcher& source_matcher) { + return Matcher(new Impl(source_matcher)); + } + + private: + class Impl : public MatcherInterface { + public: + explicit Impl(const Matcher& source_matcher) + : source_matcher_(source_matcher) {} + + // We delegate the matching logic to the source matcher. + virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { +#if GTEST_LANG_CXX11 + using FromType = typename std::remove_cv::type>::type>::type; + using ToType = typename std::remove_cv::type>::type>::type; + // Do not allow implicitly converting base*/& to derived*/&. + static_assert( + // Do not trigger if only one of them is a pointer. That implies a + // regular conversion and not a down_cast. + (std::is_pointer::type>::value != + std::is_pointer::type>::value) || + std::is_same::value || + !std::is_base_of::value, + "Can't implicitly convert from to "); +#endif // GTEST_LANG_CXX11 + + return source_matcher_.MatchAndExplain(static_cast(x), listener); + } + + virtual void DescribeTo(::std::ostream* os) const { + source_matcher_.DescribeTo(os); + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + source_matcher_.DescribeNegationTo(os); + } + + private: + const Matcher source_matcher_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; +}; + +// This even more specialized version is used for efficiently casting +// a matcher to its own type. +template +class MatcherCastImpl > { + public: + static Matcher Cast(const Matcher& matcher) { return matcher; } +}; + +} // namespace internal + +// In order to be safe and clear, casting between different matcher +// types is done explicitly via MatcherCast(m), which takes a +// matcher m and returns a Matcher. It compiles only when T can be +// statically converted to the argument type of m. +template +inline Matcher MatcherCast(const M& matcher) { + return internal::MatcherCastImpl::Cast(matcher); +} + +// Implements SafeMatcherCast(). +// +// We use an intermediate class to do the actual safe casting as Nokia's +// Symbian compiler cannot decide between +// template ... (M) and +// template ... (const Matcher&) +// for function templates but can for member function templates. +template +class SafeMatcherCastImpl { + public: + // This overload handles polymorphic matchers and values only since + // monomorphic matchers are handled by the next one. + template + static inline Matcher Cast(const M& polymorphic_matcher_or_value) { + return internal::MatcherCastImpl::Cast(polymorphic_matcher_or_value); + } + + // This overload handles monomorphic matchers. + // + // In general, if type T can be implicitly converted to type U, we can + // safely convert a Matcher to a Matcher (i.e. Matcher is + // contravariant): just keep a copy of the original Matcher, convert the + // argument from type T to U, and then pass it to the underlying Matcher. + // The only exception is when U is a reference and T is not, as the + // underlying Matcher may be interested in the argument's address, which + // is not preserved in the conversion from T to U. + template + static inline Matcher Cast(const Matcher& matcher) { + // Enforce that T can be implicitly converted to U. + GTEST_COMPILE_ASSERT_((internal::ImplicitlyConvertible::value), + T_must_be_implicitly_convertible_to_U); + // Enforce that we are not converting a non-reference type T to a reference + // type U. + GTEST_COMPILE_ASSERT_( + internal::is_reference::value || !internal::is_reference::value, + cannot_convert_non_reference_arg_to_reference); + // In case both T and U are arithmetic types, enforce that the + // conversion is not lossy. + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; + const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; + const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; + GTEST_COMPILE_ASSERT_( + kTIsOther || kUIsOther || + (internal::LosslessArithmeticConvertible::value), + conversion_of_arithmetic_types_must_be_lossless); + return MatcherCast(matcher); + } +}; + +template +inline Matcher SafeMatcherCast(const M& polymorphic_matcher) { + return SafeMatcherCastImpl::Cast(polymorphic_matcher); +} + +// A() returns a matcher that matches any value of type T. +template +Matcher A(); + +// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION +// and MUST NOT BE USED IN USER CODE!!! +namespace internal { + +// If the explanation is not empty, prints it to the ostream. +inline void PrintIfNotEmpty(const std::string& explanation, + ::std::ostream* os) { + if (explanation != "" && os != NULL) { + *os << ", " << explanation; + } +} + +// Returns true if the given type name is easy to read by a human. +// This is used to decide whether printing the type of a value might +// be helpful. +inline bool IsReadableTypeName(const std::string& type_name) { + // We consider a type name readable if it's short or doesn't contain + // a template or function type. + return (type_name.length() <= 20 || + type_name.find_first_of("<(") == std::string::npos); +} + +// Matches the value against the given matcher, prints the value and explains +// the match result to the listener. Returns the match result. +// 'listener' must not be NULL. +// Value cannot be passed by const reference, because some matchers take a +// non-const argument. +template +bool MatchPrintAndExplain(Value& value, const Matcher& matcher, + MatchResultListener* listener) { + if (!listener->IsInterested()) { + // If the listener is not interested, we do not need to construct the + // inner explanation. + return matcher.Matches(value); + } + + StringMatchResultListener inner_listener; + const bool match = matcher.MatchAndExplain(value, &inner_listener); + + UniversalPrint(value, listener->stream()); +#if GTEST_HAS_RTTI + const std::string& type_name = GetTypeName(); + if (IsReadableTypeName(type_name)) + *listener->stream() << " (of type " << type_name << ")"; +#endif + PrintIfNotEmpty(inner_listener.str(), listener->stream()); + + return match; +} + +// An internal helper class for doing compile-time loop on a tuple's +// fields. +template +class TuplePrefix { + public: + // TuplePrefix::Matches(matcher_tuple, value_tuple) returns true + // iff the first N fields of matcher_tuple matches the first N + // fields of value_tuple, respectively. + template + static bool Matches(const MatcherTuple& matcher_tuple, + const ValueTuple& value_tuple) { + return TuplePrefix::Matches(matcher_tuple, value_tuple) + && get(matcher_tuple).Matches(get(value_tuple)); + } + + // TuplePrefix::ExplainMatchFailuresTo(matchers, values, os) + // describes failures in matching the first N fields of matchers + // against the first N fields of values. If there is no failure, + // nothing will be streamed to os. + template + static void ExplainMatchFailuresTo(const MatcherTuple& matchers, + const ValueTuple& values, + ::std::ostream* os) { + // First, describes failures in the first N - 1 fields. + TuplePrefix::ExplainMatchFailuresTo(matchers, values, os); + + // Then describes the failure (if any) in the (N - 1)-th (0-based) + // field. + typename tuple_element::type matcher = + get(matchers); + typedef typename tuple_element::type Value; + GTEST_REFERENCE_TO_CONST_(Value) value = get(values); + StringMatchResultListener listener; + if (!matcher.MatchAndExplain(value, &listener)) { + // TODO(wan): include in the message the name of the parameter + // as used in MOCK_METHOD*() when possible. + *os << " Expected arg #" << N - 1 << ": "; + get(matchers).DescribeTo(os); + *os << "\n Actual: "; + // We remove the reference in type Value to prevent the + // universal printer from printing the address of value, which + // isn't interesting to the user most of the time. The + // matcher's MatchAndExplain() method handles the case when + // the address is interesting. + internal::UniversalPrint(value, os); + PrintIfNotEmpty(listener.str(), os); + *os << "\n"; + } + } +}; + +// The base case. +template <> +class TuplePrefix<0> { + public: + template + static bool Matches(const MatcherTuple& /* matcher_tuple */, + const ValueTuple& /* value_tuple */) { + return true; + } + + template + static void ExplainMatchFailuresTo(const MatcherTuple& /* matchers */, + const ValueTuple& /* values */, + ::std::ostream* /* os */) {} +}; + +// TupleMatches(matcher_tuple, value_tuple) returns true iff all +// matchers in matcher_tuple match the corresponding fields in +// value_tuple. It is a compiler error if matcher_tuple and +// value_tuple have different number of fields or incompatible field +// types. +template +bool TupleMatches(const MatcherTuple& matcher_tuple, + const ValueTuple& value_tuple) { + // Makes sure that matcher_tuple and value_tuple have the same + // number of fields. + GTEST_COMPILE_ASSERT_(tuple_size::value == + tuple_size::value, + matcher_and_value_have_different_numbers_of_fields); + return TuplePrefix::value>:: + Matches(matcher_tuple, value_tuple); +} + +// Describes failures in matching matchers against values. If there +// is no failure, nothing will be streamed to os. +template +void ExplainMatchFailureTupleTo(const MatcherTuple& matchers, + const ValueTuple& values, + ::std::ostream* os) { + TuplePrefix::value>::ExplainMatchFailuresTo( + matchers, values, os); +} + +// TransformTupleValues and its helper. +// +// TransformTupleValuesHelper hides the internal machinery that +// TransformTupleValues uses to implement a tuple traversal. +template +class TransformTupleValuesHelper { + private: + typedef ::testing::tuple_size TupleSize; + + public: + // For each member of tuple 't', taken in order, evaluates '*out++ = f(t)'. + // Returns the final value of 'out' in case the caller needs it. + static OutIter Run(Func f, const Tuple& t, OutIter out) { + return IterateOverTuple()(f, t, out); + } + + private: + template + struct IterateOverTuple { + OutIter operator() (Func f, const Tup& t, OutIter out) const { + *out++ = f(::testing::get(t)); + return IterateOverTuple()(f, t, out); + } + }; + template + struct IterateOverTuple { + OutIter operator() (Func /* f */, const Tup& /* t */, OutIter out) const { + return out; + } + }; +}; + +// Successively invokes 'f(element)' on each element of the tuple 't', +// appending each result to the 'out' iterator. Returns the final value +// of 'out'. +template +OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) { + return TransformTupleValuesHelper::Run(f, t, out); +} + +// Implements A(). +template +class AnyMatcherImpl : public MatcherInterface { + public: + virtual bool MatchAndExplain(GTEST_REFERENCE_TO_CONST_(T) /* x */, + MatchResultListener* /* listener */) const { + return true; + } + virtual void DescribeTo(::std::ostream* os) const { *os << "is anything"; } + virtual void DescribeNegationTo(::std::ostream* os) const { + // This is mostly for completeness' safe, as it's not very useful + // to write Not(A()). However we cannot completely rule out + // such a possibility, and it doesn't hurt to be prepared. + *os << "never matches"; + } +}; + +// Implements _, a matcher that matches any value of any +// type. This is a polymorphic matcher, so we need a template type +// conversion operator to make it appearing as a Matcher for any +// type T. +class AnythingMatcher { + public: + template + operator Matcher() const { return A(); } +}; + +// Implements a matcher that compares a given value with a +// pre-supplied value using one of the ==, <=, <, etc, operators. The +// two values being compared don't have to have the same type. +// +// The matcher defined here is polymorphic (for example, Eq(5) can be +// used to match an int, a short, a double, etc). Therefore we use +// a template type conversion operator in the implementation. +// +// The following template definition assumes that the Rhs parameter is +// a "bare" type (i.e. neither 'const T' nor 'T&'). +template +class ComparisonBase { + public: + explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} + template + operator Matcher() const { + return MakeMatcher(new Impl(rhs_)); + } + + private: + template + class Impl : public MatcherInterface { + public: + explicit Impl(const Rhs& rhs) : rhs_(rhs) {} + virtual bool MatchAndExplain( + Lhs lhs, MatchResultListener* /* listener */) const { + return Op()(lhs, rhs_); + } + virtual void DescribeTo(::std::ostream* os) const { + *os << D::Desc() << " "; + UniversalPrint(rhs_, os); + } + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << D::NegatedDesc() << " "; + UniversalPrint(rhs_, os); + } + private: + Rhs rhs_; + GTEST_DISALLOW_ASSIGN_(Impl); + }; + Rhs rhs_; + GTEST_DISALLOW_ASSIGN_(ComparisonBase); +}; + +template +class EqMatcher : public ComparisonBase, Rhs, AnyEq> { + public: + explicit EqMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyEq>(rhs) { } + static const char* Desc() { return "is equal to"; } + static const char* NegatedDesc() { return "isn't equal to"; } +}; +template +class NeMatcher : public ComparisonBase, Rhs, AnyNe> { + public: + explicit NeMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyNe>(rhs) { } + static const char* Desc() { return "isn't equal to"; } + static const char* NegatedDesc() { return "is equal to"; } +}; +template +class LtMatcher : public ComparisonBase, Rhs, AnyLt> { + public: + explicit LtMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyLt>(rhs) { } + static const char* Desc() { return "is <"; } + static const char* NegatedDesc() { return "isn't <"; } +}; +template +class GtMatcher : public ComparisonBase, Rhs, AnyGt> { + public: + explicit GtMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyGt>(rhs) { } + static const char* Desc() { return "is >"; } + static const char* NegatedDesc() { return "isn't >"; } +}; +template +class LeMatcher : public ComparisonBase, Rhs, AnyLe> { + public: + explicit LeMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyLe>(rhs) { } + static const char* Desc() { return "is <="; } + static const char* NegatedDesc() { return "isn't <="; } +}; +template +class GeMatcher : public ComparisonBase, Rhs, AnyGe> { + public: + explicit GeMatcher(const Rhs& rhs) + : ComparisonBase, Rhs, AnyGe>(rhs) { } + static const char* Desc() { return "is >="; } + static const char* NegatedDesc() { return "isn't >="; } +}; + +// Implements the polymorphic IsNull() matcher, which matches any raw or smart +// pointer that is NULL. +class IsNullMatcher { + public: + template + bool MatchAndExplain(const Pointer& p, + MatchResultListener* /* listener */) const { +#if GTEST_LANG_CXX11 + return p == nullptr; +#else // GTEST_LANG_CXX11 + return GetRawPointer(p) == NULL; +#endif // GTEST_LANG_CXX11 + } + + void DescribeTo(::std::ostream* os) const { *os << "is NULL"; } + void DescribeNegationTo(::std::ostream* os) const { + *os << "isn't NULL"; + } +}; + +// Implements the polymorphic NotNull() matcher, which matches any raw or smart +// pointer that is not NULL. +class NotNullMatcher { + public: + template + bool MatchAndExplain(const Pointer& p, + MatchResultListener* /* listener */) const { +#if GTEST_LANG_CXX11 + return p != nullptr; +#else // GTEST_LANG_CXX11 + return GetRawPointer(p) != NULL; +#endif // GTEST_LANG_CXX11 + } + + void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; } + void DescribeNegationTo(::std::ostream* os) const { + *os << "is NULL"; + } +}; + +// Ref(variable) matches any argument that is a reference to +// 'variable'. This matcher is polymorphic as it can match any +// super type of the type of 'variable'. +// +// The RefMatcher template class implements Ref(variable). It can +// only be instantiated with a reference type. This prevents a user +// from mistakenly using Ref(x) to match a non-reference function +// argument. For example, the following will righteously cause a +// compiler error: +// +// int n; +// Matcher m1 = Ref(n); // This won't compile. +// Matcher m2 = Ref(n); // This will compile. +template +class RefMatcher; + +template +class RefMatcher { + // Google Mock is a generic framework and thus needs to support + // mocking any function types, including those that take non-const + // reference arguments. Therefore the template parameter T (and + // Super below) can be instantiated to either a const type or a + // non-const type. + public: + // RefMatcher() takes a T& instead of const T&, as we want the + // compiler to catch using Ref(const_value) as a matcher for a + // non-const reference. + explicit RefMatcher(T& x) : object_(x) {} // NOLINT + + template + operator Matcher() const { + // By passing object_ (type T&) to Impl(), which expects a Super&, + // we make sure that Super is a super type of T. In particular, + // this catches using Ref(const_value) as a matcher for a + // non-const reference, as you cannot implicitly convert a const + // reference to a non-const reference. + return MakeMatcher(new Impl(object_)); + } + + private: + template + class Impl : public MatcherInterface { + public: + explicit Impl(Super& x) : object_(x) {} // NOLINT + + // MatchAndExplain() takes a Super& (as opposed to const Super&) + // in order to match the interface MatcherInterface. + virtual bool MatchAndExplain( + Super& x, MatchResultListener* listener) const { + *listener << "which is located @" << static_cast(&x); + return &x == &object_; + } + + virtual void DescribeTo(::std::ostream* os) const { + *os << "references the variable "; + UniversalPrinter::Print(object_, os); + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "does not reference the variable "; + UniversalPrinter::Print(object_, os); + } + + private: + const Super& object_; + + GTEST_DISALLOW_ASSIGN_(Impl); + }; + + T& object_; + + GTEST_DISALLOW_ASSIGN_(RefMatcher); +}; + +// Polymorphic helper functions for narrow and wide string matchers. +inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) { + return String::CaseInsensitiveCStringEquals(lhs, rhs); +} + +inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, + const wchar_t* rhs) { + return String::CaseInsensitiveWideCStringEquals(lhs, rhs); +} + +// String comparison for narrow or wide strings that can have embedded NUL +// characters. +template +bool CaseInsensitiveStringEquals(const StringType& s1, + const StringType& s2) { + // Are the heads equal? + if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) { + return false; + } + + // Skip the equal heads. + const typename StringType::value_type nul = 0; + const size_t i1 = s1.find(nul), i2 = s2.find(nul); + + // Are we at the end of either s1 or s2? + if (i1 == StringType::npos || i2 == StringType::npos) { + return i1 == i2; + } + + // Are the tails equal? + return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1)); +} + +// String matchers. + +// Implements equality-based string matchers like StrEq, StrCaseNe, and etc. +template +class StrEqualityMatcher { + public: + StrEqualityMatcher(const StringType& str, bool expect_eq, + bool case_sensitive) + : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + if (s.data() == NULL) { + return !expect_eq_; + } + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + if (s == NULL) { + return !expect_eq_; + } + return MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + const bool eq = case_sensitive_ ? s2 == string_ : + CaseInsensitiveStringEquals(s2, string_); + return expect_eq_ == eq; + } + + void DescribeTo(::std::ostream* os) const { + DescribeToHelper(expect_eq_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + DescribeToHelper(!expect_eq_, os); + } + + private: + void DescribeToHelper(bool expect_eq, ::std::ostream* os) const { + *os << (expect_eq ? "is " : "isn't "); + *os << "equal to "; + if (!case_sensitive_) { + *os << "(ignoring case) "; + } + UniversalPrint(string_, os); + } + + const StringType string_; + const bool expect_eq_; + const bool case_sensitive_; + + GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher); +}; + +// Implements the polymorphic HasSubstr(substring) matcher, which +// can be used as a Matcher as long as T can be converted to a +// string. +template +class HasSubstrMatcher { + public: + explicit HasSubstrMatcher(const StringType& substring) + : substring_(substring) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + if (s.data() == NULL) { + return false; + } + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + return s2.find(substring_) != StringType::npos; + } + + // Describes what this matcher matches. + void DescribeTo(::std::ostream* os) const { + *os << "has substring "; + UniversalPrint(substring_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "has no substring "; + UniversalPrint(substring_, os); + } + + private: + const StringType substring_; + + GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher); +}; + +// Implements the polymorphic StartsWith(substring) matcher, which +// can be used as a Matcher as long as T can be converted to a +// string. +template +class StartsWithMatcher { + public: + explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { + } + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + if (s.data() == NULL) { + return false; + } + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + return s2.length() >= prefix_.length() && + s2.substr(0, prefix_.length()) == prefix_; + } + + void DescribeTo(::std::ostream* os) const { + *os << "starts with "; + UniversalPrint(prefix_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't start with "; + UniversalPrint(prefix_, os); + } + + private: + const StringType prefix_; + + GTEST_DISALLOW_ASSIGN_(StartsWithMatcher); +}; + +// Implements the polymorphic EndsWith(substring) matcher, which +// can be used as a Matcher as long as T can be converted to a +// string. +template +class EndsWithMatcher { + public: + explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + if (s.data() == NULL) { + return false; + } + // This should fail to compile if absl::string_view is used with wide + // strings. + const StringType& str = string(s); + return MatchAndExplain(str, listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(StringType(s), listener); + } + + // Matches anything that can convert to StringType. + // + // This is a template, not just a plain function with const StringType&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const StringType& s2(s); + return s2.length() >= suffix_.length() && + s2.substr(s2.length() - suffix_.length()) == suffix_; + } + + void DescribeTo(::std::ostream* os) const { + *os << "ends with "; + UniversalPrint(suffix_, os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't end with "; + UniversalPrint(suffix_, os); + } + + private: + const StringType suffix_; + + GTEST_DISALLOW_ASSIGN_(EndsWithMatcher); +}; + +// Implements polymorphic matchers MatchesRegex(regex) and +// ContainsRegex(regex), which can be used as a Matcher as long as +// T can be converted to a string. +class MatchesRegexMatcher { + public: + MatchesRegexMatcher(const RE* regex, bool full_match) + : regex_(regex), full_match_(full_match) {} + +#if GTEST_HAS_ABSL + bool MatchAndExplain(const absl::string_view& s, + MatchResultListener* listener) const { + return s.data() && MatchAndExplain(string(s), listener); + } +#endif // GTEST_HAS_ABSL + + // Accepts pointer types, particularly: + // const char* + // char* + // const wchar_t* + // wchar_t* + template + bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { + return s != NULL && MatchAndExplain(std::string(s), listener); + } + + // Matches anything that can convert to std::string. + // + // This is a template, not just a plain function with const std::string&, + // because absl::string_view has some interfering non-explicit constructors. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* /* listener */) const { + const std::string& s2(s); + return full_match_ ? RE::FullMatch(s2, *regex_) : + RE::PartialMatch(s2, *regex_); + } + + void DescribeTo(::std::ostream* os) const { + *os << (full_match_ ? "matches" : "contains") + << " regular expression "; + UniversalPrinter::Print(regex_->pattern(), os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "doesn't " << (full_match_ ? "match" : "contain") + << " regular expression "; + UniversalPrinter::Print(regex_->pattern(), os); + } + + private: + const internal::linked_ptr regex_; + const bool full_match_; + + GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher); +}; + +// Implements a matcher that compares the two fields of a 2-tuple +// using one of the ==, <=, <, etc, operators. The two fields being +// compared don't have to have the same type. +// +// The matcher defined here is polymorphic (for example, Eq() can be +// used to match a tuple, a tuple, +// etc). Therefore we use a template type conversion operator in the +// implementation. +template +class PairMatchBase { + public: + template + operator Matcher< ::testing::tuple >() const { + return MakeMatcher(new Impl< ::testing::tuple >); + } + template + operator Matcher&>() const { + return MakeMatcher(new Impl&>); + } + + private: + static ::std::ostream& GetDesc(::std::ostream& os) { // NOLINT + return os << D::Desc(); + } + + template + class Impl : public MatcherInterface { + public: + virtual bool MatchAndExplain( + Tuple args, + MatchResultListener* /* listener */) const { + return Op()(::testing::get<0>(args), ::testing::get<1>(args)); + } + virtual void DescribeTo(::std::ostream* os) const { + *os << "are " << GetDesc; + } + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "aren't " << GetDesc; + } + }; +}; + +class Eq2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "an equal pair"; } +}; +class Ne2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "an unequal pair"; } +}; +class Lt2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first < the second"; } +}; +class Gt2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first > the second"; } +}; +class Le2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first <= the second"; } +}; +class Ge2Matcher : public PairMatchBase { + public: + static const char* Desc() { return "a pair where the first >= the second"; } +}; + +// Implements the Not(...) matcher for a particular argument type T. +// We do not nest it inside the NotMatcher class template, as that +// will prevent different instantiations of NotMatcher from sharing +// the same NotMatcherImpl class. +template +class NotMatcherImpl : public MatcherInterface { + public: + explicit NotMatcherImpl(const Matcher& matcher) + : matcher_(matcher) {} + + virtual bool MatchAndExplain(GTEST_REFERENCE_TO_CONST_(T) x, + MatchResultListener* listener) const { + return !matcher_.MatchAndExplain(x, listener); + } + + virtual void DescribeTo(::std::ostream* os) const { + matcher_.DescribeNegationTo(os); + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + matcher_.DescribeTo(os); + } + + private: + const Matcher matcher_; + + GTEST_DISALLOW_ASSIGN_(NotMatcherImpl); +}; + +// Implements the Not(m) matcher, which matches a value that doesn't +// match matcher m. +template +class NotMatcher { + public: + explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {} + + // This template type conversion operator allows Not(m) to be used + // to match any type m can match. + template + operator Matcher() const { + return Matcher(new NotMatcherImpl(SafeMatcherCast(matcher_))); + } + + private: + InnerMatcher matcher_; + + GTEST_DISALLOW_ASSIGN_(NotMatcher); +}; + +// Implements the AllOf(m1, m2) matcher for a particular argument type +// T. We do not nest it inside the BothOfMatcher class template, as +// that will prevent different instantiations of BothOfMatcher from +// sharing the same BothOfMatcherImpl class. +template +class AllOfMatcherImpl + : public MatcherInterface { + public: + explicit AllOfMatcherImpl(std::vector > matchers) + : matchers_(internal::move(matchers)) {} + + virtual void DescribeTo(::std::ostream* os) const { + *os << "("; + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") and ("; + matchers_[i].DescribeTo(os); + } + *os << ")"; + } + + virtual void DescribeNegationTo(::std::ostream* os) const { + *os << "("; + for (size_t i = 0; i < matchers_.size(); ++i) { + if (i != 0) *os << ") or ("; + matchers_[i].DescribeNegationTo(os); + } + *os << ")"; + } + + virtual bool MatchAndExplain(GTEST_REFERENCE_TO_CONST_(T) x, + MatchResultListener* listener) const { + // If either matcher1_ or matcher2_ doesn't match x, we only need + // to explain why one of them fails. + std::string all_match_result; + + for (size_t i = 0; i < matchers_.size(); ++i) { + StringMatchResultListener slistener; + if (matchers_[i].MatchAndExplain(x, &slistener)) { + if (all_match_result.empty()) { + all_match_result = slistener.str(); + } else { + std::string result = slistener.str(); + if (!result.empty()) { + all_match_result += ", and "; + all_match_result += result; + } + } + } else { + *listener << slistener.str(); + return false; + } + } + + // Otherwise we need to explain why *both* of them match. + *listener << all_match_result; + return true; + } + + private: + const std::vector > matchers_; + + GTEST_DISALLOW_ASSIGN_(AllOfMatcherImpl); +}; + +#if GTEST_LANG_CXX11 +// VariadicMatcher is used for the variadic implementation of +// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). +// CombiningMatcher is used to recursively combine the provided matchers +// (of type Args...). +template
  • T_rEt` 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 literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin new file mode 100644 index 0000000..309df12 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin @@ -0,0 +1,29 @@ +{ + "FileVersion": 3, + "Version": 1, + "VersionName": "1.0", + "FriendlyName": "Discord RPC", + "Description": "Wrap the Discord RPC library.", + "Category": "Messaging", + "CreatedBy": "Chris Marsh ", + "CreatedByURL": "https://discordapp.com/", + "DocsURL": "", + "MarketplaceURL": "", + "SupportURL": "", + "CanContainContent": true, + "IsBetaVersion": true, + "Installed": false, + "Modules": [ + { + "Name": "DiscordRpc", + "Type": "Runtime", + "LoadingPhase": "PreDefault", + "WhitelistPlatforms" : + [ + "Win64", + "Linux", + "Mac" + ] + } + ] +} \ No newline at end of file diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/Icon128.png b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/Icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..8b7f8e1c6a2c71c9e20d4e9e819455056c43d75e GIT binary patch literal 9834 zcmZu%c{o&G+`ltsVv;3$S%wN_iIQE6R7hEh$S!MHhLFMFT0*5np+ZC|J7r(SOqR($ zDofU}Yb0YI#+Y}0@ALlo{&DYl&N?x-Q+U2Ii@MLmvPtlR5WY;H*Bv-{?*t0C2bd_dtl~&u*;2V?kGJf^MNbf+*0;nsu4E%H_JeOe{<$al;={`$Qa4`y zxz1zUppCf42c0l@t9;#v20Ytd?t5|6&_1h{y&{=cg3g_qvD1ByXTl>=EwC6xnY?fB}?$tHsO>fVFrAyuOXs6+J`o@sin_Siv6zDlSnjcY;$*XTHFP0WRnS|w z^!Ludw?XIW{Ski-*UIURT zyNnz~N2}fKZnW6G&p{XCf@i37Z)A0jEd{MN8f|y1mD~rT?H7YP)~@`@u!dK(@H4E;io(klDH?scq!~?;A-K$w2L` z{_(2}V)y3kX77tXDrJ|)J7z!hD>Ps5+ul|+Hn=?z9Z|Bax*ghh&G{SiM{IJz{?@m_ z`Emu@2(nq=ZPv|fKS)!Ca?q{;c=Q`!J`y4lS@M6~6hJHoIMO2xkPZ2O3SUT2Sn_=E zRYc?tlGrziBbU*0nvc=#SLhE@@a$2jz2aIW$7b}7N%=~C{W*L{Fu?lQffJxr1_7ct z69AzX#;!a~hdI-10kaqmar`TMY&i_r_Y%hoBL zCQ1xVr|$ebcW;4*fT~Q)gwdp5$JsOSCyi@+obFVHms#xULPW41xO1l)JDC3B0QDm4 z*x$t@zwz?k1`Js1;?cL+ovG9DV1+pT1zrfC_Hu)pmdl%e#!Oaep$RRAINLw;!b#~a zGJ9#iO+wBNQVojq4)1$G<3yR&uoPHgFo*JVf++MGg0%&#Vl2uMBGNPgKM@RYfaHU! zGmoCWhI1ncmpATxh4XO#^jlK-I~et*F>l?hud5cu!RdtHEn_sos9Io5IlLkPG@|Bn zK~i8;tCj&s&vx>E_fV<|10uV;-stn!GS+rF1EV^wD+^SG3X=wz)o)B5mZ}gEVv)r_ z**4MwC}z9t&D2N4Ku1>evVaBJ>N0Q?=5>!f@iY)y3pYAeofdyx0sHa|)~fQJ3Z#kB zvP$5t?X`7Wd&3iUgteEG{_$*dYEKufcn7geAu})Sq2aGq?)bb$~Qt@-^lEP zQ*&SYM!L6s*m7u%PCmp!hy{P{bS4x-&9{tFn2l0^#>KAk;r{{yMNXWOWbJt17N8g% z$l**gGMoIT=H=_@5&QD8uN=^49CgvvW73kpj_cq7c?>!-h%99!ECZF#nJx)H zXr%AHVGku)hQ&TYkh?2@2R(!fGOdLwfo_W6=EXfWf=x4f*{Hd+)nBzTO;xI6aT1(Z z>-lhMX{D2iGbe8iLmu+2n&~y$k}m19B@e-_=v`+|)Hsl*;kfan{9quE8=x)lN|FOp z6MQ>8)YJpaKlq*iI)swW)wJPJXyScvorG!U%)|cP3*)5_;h<~}LT!yZlZAnG7s>7)S zYbZ?%FxaV%VvAIOzMgG41KwfSLK_*GP%p$QU}~nS5YU+2TNVR4m32}MG6ld%;d$}#XbzCc+2#ZwgW7=AIONB5UkIQ#R5=BUs{c<~$68E)Lr7CV zG?K*umXIV()XwIN2B&hP1}}61TK?WJ7Fo7l4GfTpav=JzC+(bdixh~M8a{aTA5i6N zHvcR1l~v4bemo!{PqQH}ckRIZt0SfHJ??^4ezyeO1+zbtHujMYTDPhqcHZ0;1gPo@ z5}#7Ps8rSG#vi;0&PvCHqOj!-3>UaES^X26{d=fS?^D?vU(6 zi(r5E;!QSp7ju4k=0sf0IO~x2b@A=ziaCwau*TGm>+);l#?cm*HpqX*R9atEkk`9% zeKppuSb>M)G^ivB3>Q~FuQy&ksbS?C5MY3<^Boy*~;6~BTvi6?hYoRmd# zl}1XVG+3&WOV9VM4?UJB{PRU6#CEO2QLbD^`Z8(YQWknI=|Szgyw0cFv|{9A(n0=V zJh}Wdq@z!+>*tG1w#hiO0gv^rx30!@E23xwDTVSjENror?SjX(6m~4;s&e6*-3#bH zXTw5%9v!IJxMpgx8~xQXI4{NYonKx(JOHtLyyczFd(Q;H% zXU>w;d5cRbIXY*8c;fnO#9Z-#2t4uE!3sAicqCoNgWnJ$az8NF5Q@I7yC6^y?j5>F zCm=6IK2I;bOZD2wdej~AGrcK4h_V?9`7R_qG(yU|Vlsd^xOG?{C)fIRdZ6L=yvcFF z+c+!z>fmQmdap$!n8}sOa$Bu$u#4mH*{R_(R5zsC6SV5v1(Z%rmiix%P8 z?~qq7FBdV$QWdyuG)L|la(W0MQF?|fAY@!ytDM}wl_0C z*m-mFn~w0f(Yg2R(}9?e$rPST1dP)ZWzdfp|3iqdT8OSQ5~MS-fgL5gTgJ^-1+NOB z2s<$6C9NnSsMnGVmdk;CFzPcUi^tTC7&qXk>G;!VB4L38;RE?gX_?VN?NymWfDyR( z8h%-Xnt=-?Aqq=pVg@7#Q|A}cCVoZOaBo@ijSQ|*fU~sDlTQmxn&AG?YO_$kt2sZX z>KB7JKGY;}UJal7_K35pc>jWQps>+xzBqn-Nu)I$Eeyee4hXi1o}_~CKl`C~xYiOm zFNedS_6?h73U0`y^7)5-6t4NqAUc769@SS~GQ7S-V9u?4+|o2OkgT?{=N(ny1$Mz? zfhu4ke&OcfQ_f2)>sz*003eCgY;z5$%yaMQ_>&Y$Hs$3rQ=3w8VQ@PsKAEiddLj;} zzx(V%(ks3?awBX>?Zklr$WpC7M0N*52YhAF3PiS~CXw?}c!vNGHD%Jh{hb>h2vIcP zNzV<1wpFqvIYX|0cX2scci*u5%ABC~?%4fHsOl^Bz^IB0HhVwy{=mV}--z|o2)?A# zn`Cc@J$38~$V<|aSR&=F6IHMuw*Q98RtzO^qQZ&Ns9Qg!DJgGd;Ue*>h9!Z8jj1dX zbplVu99Dh=2YzwjA$H}xxqBJq-gMWf;Xd?g9r+|}bS5oa8Y>tCo*F=`$HB@dXm!Ys zk8>uFJp53l(vX7J>^6FpCNFiC>H)nkVkFUF01)|6K8qITS%x)tIz-e$APQoi8+@IN zQ{E2<>{{A`16>Z4;u$B+kUYc{fGkyTeK0+X$C@&}jY z?)`mrf}(dmA>JM4)i;wpvjtI0OrP6)b0}=KIpV_o2S>M#zcYw1T=>!Ud#vq|#J0Or zSsf~Yv+U85>Uk%^;x%i&5o%)v@68w}MDHK;NccHD>)63ugXqlZ?fyX~#jZ4Dn@3w+ zw&ls8XMOzE3nwCey6t^%zqR_y=WV4k`(XB#Q_Vz{&y>{-#?OtoQT|Kp+OhQB0dI~M`EK9e&q--s zaI=SG7jiZ8jleb1o03Dp7^SfmNKRu6V#4RzP%vq4FO0elTyZ7$>EC8C&tGw#_AW+$;s{mW=JnwHX${nO8(*N@CmGVI#< z@JQ9KmQ}98BVLsu|H4Ii4wJqE@n=t>moeF3BOY&2Z#hL0Sl5_NwGO%t{_E5iUh1WW z7gPdbl?!7uty4w|elL0qppLb}zH4T9n*$Gxw3RT7S-p57 zIqVt85qb?86k|UC*B!?i?U!)g4~$v7_;7)H0A2+gk2H_Lvf@c7&X#Bey1ayHo+aTv zTa&veQ&-Ac`02Y*qKSGLZEZZhdNz#ncSWdtVuwlaA$e4#+j^7uk=Jk_NYH2JF16VP zs)*{hd?)z@R#%4pLwO)eN_YD+8X@5iaY!J9LohHt>dJG*tTxPurG448FU(lgsXQEr z7b!akAXNMenofPYc@GjaHav)oQ-T9{u`o{tWO4R4VJhWZb6oM1(-yF5)siByAHnN9 z{ba)QwPL3oQsO3bE}ZYX5e?b|_K#(mt_eAFz&O~(o?~{mHgC!m`#bIbiQzqi8EF43 z%n5fxOgXLT)3BEKXduD{Z2FepM+|hI{Bp5q#%ha`7D+uZ4!J1_ghX4dT57q}oYH=n zlL{4aK(*G&JIR(A05E?-&200*JNV}r!=1 zrKxs}mu-kz0GQI6I+$yX8#=i@t7l|;(myO%=2HMdP&9DjJyn}aKCuNjUWOPI#3Rp@ zS~h+ES^d>6m67ucL9&gJ#Q5z>V4m|i_jMQa5fQ>o+~?eS)S=Wf`@xF%&xO)6qyhL> z>3d#vD2I6JDH1>G8?oUlH#xkP^Rs~tTqNt50G{2hxi!9?3nJ6UbI}x+;@Wo!A z=QfV>0B;c*wDkSX;%ppe!>@)d_G1rUQx=U7%7~u)mB#y7l6J@U4_>9f^G4@&P}VKi z%|U32slk{&z~kTceP{Fz)%H=Kp_3_9@6jL58hI)oF0Slk!lTq5BRtF=`#S%W1tp@r zvUs&OD#hpP_%*3*8W!L&6Fw>jvp*`W*PPWAkwC$Gm6 z!zfKFRjbZR-Cr{^Z)jRwaQ4ATqrj^-QF_jK40es<5DHuQ|3ad(2i}eZ=Cn0TLVZ;tSL&sHtIcH$w5ot)ExUb<$gj30|(- zNB8E8viWVjWiV&K>8~*GEZjV;-&gN6Dk}j{L{*W+YkqwECm^g<_wa9yt9`}j3Hc#$ z=kJ8yEuZ(Mm!Q{xqoFVW@@`q!5OSyj*t;Qc@@iA@0{3WER8PGMb9@Fmc>50HK=#OO z1n7bXd6o#lQstcWY;9|o%@YBP-o<9M6O*@t*SQbB%JTnbZmqog?U9hIS+$=i`dJ;S zJ+;*;*mBC>QAcTb*dcT_)*z3qPTr|HvT{P=znDtMM+K*T+XHeqq)nHf_>%bAG4P8; z)ACSCey?_%_tO#oyIiLnzuZ@v7Z58rse|_FtBovDND1%a?CEFHq9Xt9-d{&t2Ggq=C(b>Xf)+fnrwbLoUVC z-n90%)PsrWeY!BGXw^CoWzX=RcK?al=`C_yT%rzy*>;sy5nm`=lW2P6nAQC3!Fuw| z2>Ex8HM21@hn;7dpLi-vUU6WbH(%7RzYsR6)}>VTaiw6;(lOu(w?xtWqJ?Z3Ql~RD zOYgZq%s?L`to!OHLLtX-_$|tRGGu%n7g0uGVj?|`yscGy^5iz z8el5$vTkYQj-;S(@kihBt*-5?SA+d8Q5K9N%*{WC0t(jdNXXdpk-cM8YJYIXvdzGf zB{nWnJL<}(Ly~F%h5}?$)-w(UC71qO^XQy4@#>^>y*`D1{=$K*lRYOMU;C`JGlMOG zf^jfo$x7Uh^PE=co*9C{Grln^KxH4sRwvn@x@~?3Q?^ z@*y{i#pvI^f|U(~r*G>;h?d$k<{TEm>aQWiTiV6u!OcF6d6OmG?I&uwe&2J_q{*rG_QUY{>B&Wm2qX!gUg z42v(;UqyvsWlAB_+0U5RJOYnIR2xidmb z{sSAp0KCH>hVQs?%?mYmaXzahK43slPTEW0BOM8^*@&=T)%5iTzCN?5 zzV?kuZg|yw1<2XSza7ycHYbfi?~X>ZZ$gCbYX8ET27A$E-9Niknzc`gnHqu{uUoR2 z+(9B$5r`Zfx(Lo;7f9}lm*P%%YBFR=J))bTMHS1NCF?+(n8m{-*joVC)Jp)m>B|Et z0jeVGh;$g2L5!nML`T)#vbWSlgbt$4Vd%Y8&OHI7P_$n~&e-nfGwqbU2yU~(?Z-2G zo<3FG+M@G9rs;9Klwg_-XI&x|E#Wi!#RrjzE*ADW#lw>rBzhJ-8-7z(@adX_VpRX+ zt(lf&jY++*619=-PbBli9sVLuyJqY7&SPaaP^hAJj+5G{Gr%7W;{|`dX>2?4E;g4E5IN&7 zXhy?${p82l^5A@S2X&H48Lj#h?S>bGz;=~=;Y0AI8l|F1h*NEZ^|GPXk>_85h^vck zY@bCR%%MR2nV%|>`j2HH+{>wU3X&>^06mpFV>+$uXF3U}{v(MCENM5Dx&#_{fU8pkmk491KGllGYW z{#|_XF1}Gz?|stmu|ij-7(zl&37IjF4>JM}91Rc!btYH9 z%0nY$EfFvSUjU4x8^-`*_SIu=JXbWt?CFz{w%sSl-(C9T-Cyati-tS_E)FZ%p;qyE zMl4T-eNuFF{`D%t8Luus^%7rlK={uc0ZNC<5_iFLFdjfF_W8zYv#T~5TtBQ_)y-Lz)&vI13TzqwMNy; z!LzQQ;Z65>mIq!O$rfo2K3n6@9saB!1#;f6!{oekH{@ZzZ?vTHQ5mE0iD$m;jI&@c zQYP4od9iIyNg&b)hDD6?I1(10q~l{1ojM>$7f6sWetAoqOK1zfw!Zw4UDSKIoVdEqGd>lt#9a)!i1c<{I{3j3jaAK=i30aO?ti*>7 zzcu7X8gQu1W`4aFHZ`_mVFRT=(jskzlYRK(-G&$X+ zBQ~wj36rpAQ;VY-;|T%H)@zPI^Rvq~@+7F*WQvIayK_k_xp7AKD8g~_QyxK{*0A3A zQAm?jj;LcLKy;{Aw>TktZDyby3)d2HS!WfNZ?@+;_+m2usU_W-{0O!LlfnEJ1V-b_ z%_!ejB(df5@<(H+5J!SAY0EZRsDg_oCzZB3@d;*5c8xE`XAYvRaeY761SF+>H)Lc< zMi$NyV^^<}IdpHBl&3i6OGd}=jNDa(b6nLI^4y&BMIgc6>d|fT?A-Gh1(Y4s-<+Yp zq|@ix>+e8q?h=OVI}e6a1!*?&dVKqy?3X~UfTQHAeN#cA4KCH}=Z}z#AU4f4`O%qc zx)vrzyoZq$aQ}$o!nHR@5*RiufRn0*737*o0!xRE413d|7i3}@Mq`(!K4CE@U^r>; z5K^9{p7Bu+oh8elf(LFfcIwTu9i5zd^j5-;4SV0MM;F>=o5Vp!>>fxU#Td zR^}S)s0nBROJu^l9-!ZH-YL&(TvNMO+lAlL*!By-5 z%W?-6tZy=B`Ic_LfzkD8>y%Az2+oDT^TNB}5G%MeGQ$23l zKq0@E09M%j)CLM0!!`7>0_+tn@XUJ?7MleqD8WgH!z@e`k*gF&cLKXEk^cA7uw(cv zGx9@g*A^6)()|c&202LG5bUc(<95SCwnW}Ub->G|AH(YoG*nge5tn9*9|mTgWafVY zXa8o83X!ea+1-_+Gd~5o$D}EZ;nW8V>be>?owU<-e(U*12KA~APi#@Yb`J-Or6QZx z(^v%+y@?$7(lI1tQ-_?HwW_!OE9q!6(JvVKOhDKtn|Dczo3u)?JsI?(6o+Y{6#Aqs40Ghcg8SLjO;GG2a(&PRi`_@qu*aGW~K1CS}wxy zG3>bK8`fD&LOr9?uXt$F1=Sm!1Qa=HyMi^*nFBdRh0-LdbWo@rE6zR?gexV`V>W0M zdtE>F=`oA*anZ?ZIK!|3&)SJ?&L9Bz7TLO;-4ceK?Cw|j?oV|s#Aag-gDybJoJ^nZ zu*1&0cFv!*Z4cm!RA#^>wN|~=Yp0eRuXY9@@3;Z#?s!o}5$NZl3~Cxc(LKW+YXzm* z;_7@$1hK*xE+l~=ek(m>p0PD$#OTYRmwrW9!_+g9~c z95wsccv3>=>%^^%W8%!pBbcrEbM$5&%b+|oe!J5;o3LRg7KQGkbODH5hPJHf5H?OgtUylh-G6JHO?De3p6rN~Y3 zOG@LQ&gZ0A^aw3RJy7m$jtv~H9-gFbAg37Egz%`By88!H9?u(@wfyH#&f^k@^cp4E z9o@L3?xr0=CI3Ihjrg9}u-=`EiRI6__v_y{!H1c9nMrF}JI)MmM`oCU;e>2W>!Onc zs>6MJW4Y%XbB{E4l)1?472iZBClMkcm>~0sD=l4+y445&>NX~$Bi{W@3pTcH7Q!Dw ze~Wsuak(pAY)d0R5M=_&##C}Ca!&vW+9E=c-}SBW{7l5+Cnr34*L5iQw_Zo2BCwsU zNbt?l_G2!-@-y2U$4c1`j!|K|LCyy7fIl0p>ENh|Uf= z(ElIoO3ZdL<5Bx~2<`axu~W29$jRS@v#uA_R7apRd?s|$OYcAIPAnb5oEH)DUjf{} zt=9~SL9WtWWizO=rS^6T;=44YZFgZI_tEkQ@$F<5C<vV}P|C(eiE)Co10 zOF|lCPvI*<=^=jM)D*);tp6`IG@*qLZls`S=Yvp2%s@Ks9F2+!0fgZj(g z+1JlMcC=?8AZ3*HSAc(jDcn<#xi;#JZlY%-D>2EHj+(ZBm?pVGg+)@07s6kH@QRGY zl+nzXJ8Oc)k;5ykKDcMx(Sh8oCBC(%1D-YkMdF{Hw}dlW`myQ58ncP{2`r-i+%*Bn zUUXW<`R4-uBZ==%u$F6j&F9=iEOg!1mhc`Q`jpAv{ohdT{4%qati~E*IZ&N2T3i>(=4 literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/discord.png b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Resources/discord.png new file mode 100644 index 0000000000000000000000000000000000000000..8b7f8e1c6a2c71c9e20d4e9e819455056c43d75e GIT binary patch literal 9834 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 literal 0 HcmV?d00001 diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/DiscordRpc.Build.cs b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/DiscordRpc.Build.cs new file mode 100644 index 0000000..3678f98 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/DiscordRpc.Build.cs @@ -0,0 +1,57 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.IO; + +public class DiscordRpc : ModuleRules +{ +#if WITH_FORWARDED_MODULE_RULES_CTOR + public DiscordRpc(ReadOnlyTargetRules Target) : base(Target) +#else + public DiscordRpc(TargetInfo Target) +#endif + { + Definitions.Add("DISCORD_DYNAMIC_LIB=1"); + + PublicIncludePaths.AddRange( + new string[] { + "DiscordRpc/Public" + } + ); + + PrivateIncludePaths.AddRange( + new string[] { + "DiscordRpc/Private" + } + ); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "DiscordRpcLibrary" + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "Projects" + } + ); + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + + string BaseDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "Source", "ThirdParty", "DiscordRpcLibrary")); + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + } +} \ No newline at end of file diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpc.cpp b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpc.cpp new file mode 100644 index 0000000..d539dab --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpc.cpp @@ -0,0 +1,76 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "DiscordRpcPrivatePCH.h" +#include "IPluginManager.h" +#include "ModuleManager.h" + +#define LOCTEXT_NAMESPACE "FDiscordRpcModule" + +void FDiscordRpcModule::StartupModule() +{ +#if !PLATFORM_LINUX +#if defined(DISCORD_DYNAMIC_LIB) + // Get the base directory of this plugin + FString BaseDir = IPluginManager::Get().FindPlugin("DiscordRpc")->GetBaseDir(); + const FString SDKDir = + FPaths::Combine(*BaseDir, TEXT("Source"), TEXT("ThirdParty"), TEXT("DiscordRpcLibrary")); +#if PLATFORM_WINDOWS + const FString LibName = TEXT("discord-rpc"); + const FString LibDir = FPaths::Combine(*SDKDir, TEXT("Win64")); + if (!LoadDependency(LibDir, LibName, DiscordRpcLibraryHandle)) { + FMessageDialog::Open( + EAppMsgType::Ok, + LOCTEXT(LOCTEXT_NAMESPACE, + "Failed to load DiscordRpc plugin. Plug-in will not be functional.")); + FreeDependency(DiscordRpcLibraryHandle); + } +#elif PLATFORM_MAC + const FString LibName = TEXT("libdiscord-rpc"); + const FString LibDir = FPaths::Combine(*SDKDir, TEXT("Mac")); + if (!LoadDependency(LibDir, LibName, DiscordRpcLibraryHandle)) { + FMessageDialog::Open( + EAppMsgType::Ok, + LOCTEXT(LOCTEXT_NAMESPACE, + "Failed to load DiscordRpc plugin. Plug-in will not be functional.")); + FreeDependency(DiscordRpcLibraryHandle); + } +#endif +#endif +#endif +} + +void FDiscordRpcModule::ShutdownModule() +{ + // Free the dll handle +#if !PLATFORM_LINUX +#if defined(DISCORD_DYNAMIC_LIB) + FreeDependency(DiscordRpcLibraryHandle); +#endif +#endif +} + +bool FDiscordRpcModule::LoadDependency(const FString& Dir, const FString& Name, void*& Handle) +{ + FString Lib = Name + TEXT(".") + FPlatformProcess::GetModuleExtension(); + FString Path = Dir.IsEmpty() ? *Lib : FPaths::Combine(*Dir, *Lib); + + Handle = FPlatformProcess::GetDllHandle(*Path); + + if (Handle == nullptr) { + return false; + } + + return true; +} + +void FDiscordRpcModule::FreeDependency(void*& Handle) +{ + if (Handle != nullptr) { + FPlatformProcess::FreeDllHandle(Handle); + Handle = nullptr; + } +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FDiscordRpcModule, DiscordRpc) \ No newline at end of file diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp new file mode 100644 index 0000000..8925d8e --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp @@ -0,0 +1,172 @@ +#include "DiscordRpcPrivatePCH.h" +#include "DiscordRpcBlueprint.h" +#include "discord_rpc.h" + +DEFINE_LOG_CATEGORY(Discord) + +static UDiscordRpc* self = nullptr; + +static void ReadyHandler(const DiscordUser* connectedUser) +{ + FDiscordUserData ud; + ud.userId = ANSI_TO_TCHAR(connectedUser->userId); + ud.username = ANSI_TO_TCHAR(connectedUser->username); + ud.discriminator = ANSI_TO_TCHAR(connectedUser->discriminator); + ud.avatar = ANSI_TO_TCHAR(connectedUser->avatar); + UE_LOG(Discord, + Log, + TEXT("Discord connected to %s - %s#%s"), + *ud.userId, + *ud.username, + *ud.discriminator); + if (self) { + self->IsConnected = true; + self->OnConnected.Broadcast(ud); + } +} + +static void DisconnectHandler(int errorCode, const char* message) +{ + auto msg = FString(message); + UE_LOG(Discord, Log, TEXT("Discord disconnected (%d): %s"), errorCode, *msg); + if (self) { + self->IsConnected = false; + self->OnDisconnected.Broadcast(errorCode, msg); + } +} + +static void ErroredHandler(int errorCode, const char* message) +{ + auto msg = FString(message); + UE_LOG(Discord, Log, TEXT("Discord error (%d): %s"), errorCode, *msg); + if (self) { + self->OnErrored.Broadcast(errorCode, msg); + } +} + +static void JoinGameHandler(const char* joinSecret) +{ + auto secret = FString(joinSecret); + UE_LOG(Discord, Log, TEXT("Discord join %s"), *secret); + if (self) { + self->OnJoin.Broadcast(secret); + } +} + +static void SpectateGameHandler(const char* spectateSecret) +{ + auto secret = FString(spectateSecret); + UE_LOG(Discord, Log, TEXT("Discord spectate %s"), *secret); + if (self) { + self->OnSpectate.Broadcast(secret); + } +} + +static void JoinRequestHandler(const DiscordUser* request) +{ + FDiscordUserData ud; + ud.userId = ANSI_TO_TCHAR(request->userId); + ud.username = ANSI_TO_TCHAR(request->username); + ud.discriminator = ANSI_TO_TCHAR(request->discriminator); + ud.avatar = ANSI_TO_TCHAR(request->avatar); + UE_LOG(Discord, + Log, + TEXT("Discord join request from %s - %s#%s"), + *ud.userId, + *ud.username, + *ud.discriminator); + if (self) { + self->OnJoinRequest.Broadcast(ud); + } +} + +void UDiscordRpc::Initialize(const FString& applicationId, + bool autoRegister, + const FString& optionalSteamId) +{ + self = this; + IsConnected = false; + DiscordEventHandlers handlers{}; + handlers.ready = ReadyHandler; + handlers.disconnected = DisconnectHandler; + handlers.errored = ErroredHandler; + if (OnJoin.IsBound()) { + handlers.joinGame = JoinGameHandler; + } + if (OnSpectate.IsBound()) { + handlers.spectateGame = SpectateGameHandler; + } + if (OnJoinRequest.IsBound()) { + handlers.joinRequest = JoinRequestHandler; + } + auto appId = StringCast(*applicationId); + auto steamId = StringCast(*optionalSteamId); + Discord_Initialize( + (const char*)appId.Get(), &handlers, autoRegister, (const char*)steamId.Get()); +} + +void UDiscordRpc::Shutdown() +{ + Discord_Shutdown(); + self = nullptr; +} + +void UDiscordRpc::RunCallbacks() +{ + Discord_RunCallbacks(); +} + +void UDiscordRpc::UpdatePresence() +{ + DiscordRichPresence rp{}; + + auto state = StringCast(*RichPresence.state); + rp.state = state.Get(); + + auto details = StringCast(*RichPresence.details); + rp.details = details.Get(); + + auto largeImageKey = StringCast(*RichPresence.largeImageKey); + rp.largeImageKey = largeImageKey.Get(); + + auto largeImageText = StringCast(*RichPresence.largeImageText); + rp.largeImageText = largeImageText.Get(); + + auto smallImageKey = StringCast(*RichPresence.smallImageKey); + rp.smallImageKey = smallImageKey.Get(); + + auto smallImageText = StringCast(*RichPresence.smallImageText); + rp.smallImageText = smallImageText.Get(); + + auto partyId = StringCast(*RichPresence.partyId); + rp.partyId = partyId.Get(); + + auto matchSecret = StringCast(*RichPresence.matchSecret); + rp.matchSecret = matchSecret.Get(); + + auto joinSecret = StringCast(*RichPresence.joinSecret); + rp.joinSecret = joinSecret.Get(); + + auto spectateSecret = StringCast(*RichPresence.spectateSecret); + rp.spectateSecret = spectateSecret.Get(); + rp.startTimestamp = RichPresence.startTimestamp; + rp.endTimestamp = RichPresence.endTimestamp; + rp.partySize = RichPresence.partySize; + rp.partyMax = RichPresence.partyMax; + rp.partyPrivacy = (int)RichPresence.partyPrivacy; + rp.instance = RichPresence.instance; + + Discord_UpdatePresence(&rp); +} + +void UDiscordRpc::ClearPresence() +{ + Discord_ClearPresence(); +} + +void UDiscordRpc::Respond(const FString& userId, int reply) +{ + UE_LOG(Discord, Log, TEXT("Responding %d to join request from %s"), reply, *userId); + FTCHARToUTF8 utf8_userid(*userId); + Discord_Respond(utf8_userid.Get(), reply); +} diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcPrivatePCH.h b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcPrivatePCH.h new file mode 100644 index 0000000..1166801 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcPrivatePCH.h @@ -0,0 +1,2 @@ +#include "Core.h" +#include "DiscordRpc.h" \ No newline at end of file diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpc.h b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpc.h new file mode 100644 index 0000000..727833b --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpc.h @@ -0,0 +1,20 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "ModuleManager.h" + +class FDiscordRpcModule : public IModuleInterface { +public: + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + +private: + /** Handle to the test dll we will load */ + void* DiscordRpcLibraryHandle; + + /** StartupModule is covered with defines, these functions are the place to put breakpoints */ + static bool LoadDependency(const FString& Dir, const FString& Name, void*& Handle); + static void FreeDependency(void*& Handle); +}; \ No newline at end of file diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h new file mode 100644 index 0000000..409eee0 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h @@ -0,0 +1,181 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Engine.h" +#include "DiscordRpcBlueprint.generated.h" + +// unreal's header tool hates clang-format +// clang-format off + +/** +* Ask to join callback data +*/ +USTRUCT(BlueprintType) +struct FDiscordUserData { + GENERATED_USTRUCT_BODY() + + UPROPERTY(BlueprintReadOnly) + FString userId; + UPROPERTY(BlueprintReadOnly) + FString username; + UPROPERTY(BlueprintReadOnly) + FString discriminator; + UPROPERTY(BlueprintReadOnly) + FString avatar; +}; + +/** +* Valid response codes for Respond function +*/ +UENUM(BlueprintType) +enum class EDiscordJoinResponseCodes : uint8 +{ + DISCORD_REPLY_NO UMETA(DisplayName="No"), + DISCORD_REPLY_YES UMETA(DisplayName="Yes"), + DISCORD_REPLY_IGNORE UMETA(DisplayName="Ignore") +}; + +/** +* Valid party privacy values +*/ +UENUM(BlueprintType) +enum class EDiscordPartyPrivacy: uint8 +{ + DISCORD_PARTY_PRIVATE UMETA(DisplayName="Private"), + DISCORD_PARTY_PUBLIC UMETA(DisplayName="Public") +}; + +DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All); + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordConnected, const FDiscordUserData&, joinRequest); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordDisconnected, int, errorCode, const FString&, errorMessage); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordErrored, int, errorCode, const FString&, errorMessage); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoin, const FString&, joinSecret); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordSpectate, const FString&, spectateSecret); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoinRequest, const FDiscordUserData&, joinRequest); + +// clang-format on + +/** + * Rich presence data + */ +USTRUCT(BlueprintType) +struct FDiscordRichPresence { + GENERATED_USTRUCT_BODY() + + UPROPERTY(BlueprintReadWrite) + FString state; + UPROPERTY(BlueprintReadWrite) + FString details; + // todo, timestamps are 64bit, does that even matter? + UPROPERTY(BlueprintReadWrite) + int startTimestamp; + UPROPERTY(BlueprintReadWrite) + int endTimestamp; + UPROPERTY(BlueprintReadWrite) + FString largeImageKey; + UPROPERTY(BlueprintReadWrite) + FString largeImageText; + UPROPERTY(BlueprintReadWrite) + FString smallImageKey; + UPROPERTY(BlueprintReadWrite) + FString smallImageText; + UPROPERTY(BlueprintReadWrite) + FString partyId; + UPROPERTY(BlueprintReadWrite) + int partySize; + UPROPERTY(BlueprintReadWrite) + int partyMax; + UPROPERTY(BlueprintReadWrite) + EDiscordPartyPrivacy partyPrivacy; + UPROPERTY(BlueprintReadWrite) + FString matchSecret; + UPROPERTY(BlueprintReadWrite) + FString joinSecret; + UPROPERTY(BlueprintReadWrite) + FString spectateSecret; + UPROPERTY(BlueprintReadWrite) + bool instance; +}; + +/** + * + */ +UCLASS(BlueprintType, meta = (DisplayName = "Discord RPC"), Category = "Discord") +class DISCORDRPC_API UDiscordRpc : public UObject { + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, + meta = (DisplayName = "Initialize connection", Keywords = "Discord rpc"), + Category = "Discord") + void Initialize(const FString& applicationId, + bool autoRegister, + const FString& optionalSteamId); + + UFUNCTION(BlueprintCallable, + meta = (DisplayName = "Shut down connection", Keywords = "Discord rpc"), + Category = "Discord") + void Shutdown(); + + UFUNCTION(BlueprintCallable, + meta = (DisplayName = "Check for callbacks", Keywords = "Discord rpc"), + Category = "Discord") + void RunCallbacks(); + + UFUNCTION(BlueprintCallable, + meta = (DisplayName = "Send presence", Keywords = "Discord rpc"), + Category = "Discord") + void UpdatePresence(); + + UFUNCTION(BlueprintCallable, + meta = (DisplayName = "Clear presence", Keywords = "Discord rpc"), + Category = "Discord") + void ClearPresence(); + + UFUNCTION(BlueprintCallable, + meta = (DisplayName = "Respond to join request", Keywords = "Discord rpc"), + Category = "Discord") + void Respond(const FString& userId, int reply); + + UPROPERTY(BlueprintReadOnly, + meta = (DisplayName = "Is Discord connected", Keywords = "Discord rpc"), + Category = "Discord") + bool IsConnected; + + UPROPERTY(BlueprintAssignable, + meta = (DisplayName = "On connection", Keywords = "Discord rpc"), + Category = "Discord") + FDiscordConnected OnConnected; + + UPROPERTY(BlueprintAssignable, + meta = (DisplayName = "On disconnection", Keywords = "Discord rpc"), + Category = "Discord") + FDiscordDisconnected OnDisconnected; + + UPROPERTY(BlueprintAssignable, + meta = (DisplayName = "On error message", Keywords = "Discord rpc"), + Category = "Discord") + FDiscordErrored OnErrored; + + UPROPERTY(BlueprintAssignable, + meta = (DisplayName = "When Discord user presses join", Keywords = "Discord rpc"), + Category = "Discord") + FDiscordJoin OnJoin; + + UPROPERTY(BlueprintAssignable, + meta = (DisplayName = "When Discord user presses spectate", Keywords = "Discord rpc"), + Category = "Discord") + FDiscordSpectate OnSpectate; + + UPROPERTY(BlueprintAssignable, + meta = (DisplayName = "When Discord another user sends a join request", + Keywords = "Discord rpc"), + Category = "Discord") + FDiscordJoinRequest OnJoinRequest; + + UPROPERTY(BlueprintReadWrite, + meta = (DisplayName = "Rich presence info", Keywords = "Discord rpc"), + Category = "Discord") + FDiscordRichPresence RichPresence; +}; diff --git a/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/DiscordRpcLibrary/DiscordRpcLibrary.Build.cs b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/DiscordRpcLibrary/DiscordRpcLibrary.Build.cs new file mode 100644 index 0000000..8591b15 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/DiscordRpcLibrary/DiscordRpcLibrary.Build.cs @@ -0,0 +1,59 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using System.IO; +using UnrealBuildTool; + +public class DiscordRpcLibrary : ModuleRules +{ +#if WITH_FORWARDED_MODULE_RULES_CTOR + public DiscordRpcLibrary(ReadOnlyTargetRules Target) : base(Target) +#else + public DiscordRpcLibrary(TargetInfo Target) +#endif + { + Type = ModuleType.External; + Definitions.Add("DISCORD_DYNAMIC_LIB=1"); + + string BaseDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "DiscordRpcLibrary")); + + if (Target.Platform == UnrealTargetPlatform.Win64) + { + string lib = Path.Combine(BaseDirectory, "Win64"); + + // Include headers + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + + // Add the import library + PublicLibraryPaths.Add(lib); + PublicAdditionalLibraries.Add(Path.Combine(lib, "discord-rpc.lib")); + + // Dynamic + RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "discord-rpc.dll"))); + PublicDelayLoadDLLs.Add("discord-rpc.dll"); + } + else if (Target.Platform == UnrealTargetPlatform.Linux) + { + string lib = Path.Combine(BaseDirectory, "Linux", "x86_64-unknown-linux-gnu"); + + // Include headers + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + + // Add the import library + PublicLibraryPaths.Add(lib); + PublicAdditionalLibraries.Add(Path.Combine(lib, "libdiscord-rpc.so")); + RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "libdiscord-rpc.so"))); + } + else if (Target.Platform == UnrealTargetPlatform.Mac) + { + string lib = Path.Combine(BaseDirectory, "Mac"); + + // Include headers + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + + // Add the import library + PublicLibraryPaths.Add(lib); + PublicAdditionalLibraries.Add(Path.Combine(lib, "libdiscord-rpc.dylib")); + RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "libdiscord-rpc.dylib"))); + } + } +} \ No newline at end of file diff --git a/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus.Target.cs b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus.Target.cs new file mode 100644 index 0000000..0c7c3c8 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus.Target.cs @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class unrealstatusTarget : TargetRules +{ + public unrealstatusTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Game; + + ExtraModuleNames.AddRange( new string[] { "unrealstatus" } ); + } +} diff --git a/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.Build.cs b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.Build.cs new file mode 100644 index 0000000..9560370 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.Build.cs @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; + +public class unrealstatus : ModuleRules +{ + public unrealstatus(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); + + PrivateDependencyModuleNames.AddRange(new string[] { }); + + // Uncomment if you are using Slate UI + // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); + + // Uncomment if you are using online features + // PrivateDependencyModuleNames.Add("OnlineSubsystem"); + + // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true + } +} diff --git a/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.cpp b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.cpp new file mode 100644 index 0000000..9dd5388 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "unrealstatus.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE(FDefaultGameModuleImpl, unrealstatus, "unrealstatus"); diff --git a/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.h b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.h new file mode 100644 index 0000000..73407dd --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatus.h @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" diff --git a/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.cpp b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.cpp new file mode 100644 index 0000000..1af3094 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.cpp @@ -0,0 +1,3 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "unrealstatusGameModeBase.h" diff --git a/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.h b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.h new file mode 100644 index 0000000..8dd9bd4 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatus/unrealstatusGameModeBase.h @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameModeBase.h" +#include "unrealstatusGameModeBase.generated.h" + +/** + * + */ +UCLASS() +class UNREALSTATUS_API AunrealstatusGameModeBase : public AGameModeBase { + GENERATED_BODY() +}; diff --git a/deps/discord-rpc/examples/unrealstatus/Source/unrealstatusEditor.Target.cs b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatusEditor.Target.cs new file mode 100644 index 0000000..2e8ad02 --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/Source/unrealstatusEditor.Target.cs @@ -0,0 +1,14 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class unrealstatusEditorTarget : TargetRules +{ + public unrealstatusEditorTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + + ExtraModuleNames.AddRange( new string[] { "unrealstatus" } ); + } +} diff --git a/deps/discord-rpc/examples/unrealstatus/unrealstatus.uproject b/deps/discord-rpc/examples/unrealstatus/unrealstatus.uproject new file mode 100644 index 0000000..8a4a40b --- /dev/null +++ b/deps/discord-rpc/examples/unrealstatus/unrealstatus.uproject @@ -0,0 +1,19 @@ +{ + "FileVersion": 3, + "EngineAssociation": "4.18", + "Category": "", + "Description": "", + "Modules": [ + { + "Name": "unrealstatus", + "Type": "Runtime", + "LoadingPhase": "Default" + } + ], + "TargetPlatforms": [ + "LinuxNoEditor", + "MacNoEditor", + "WindowsNoEditor", + "AllDesktop" + ] +} \ No newline at end of file diff --git a/deps/discord-rpc/include/discord_register.h b/deps/discord-rpc/include/discord_register.h new file mode 100644 index 0000000..16fb42f --- /dev/null +++ b/deps/discord-rpc/include/discord_register.h @@ -0,0 +1,26 @@ +#pragma once + +#if defined(DISCORD_DYNAMIC_LIB) +#if defined(_WIN32) +#if defined(DISCORD_BUILDING_SDK) +#define DISCORD_EXPORT __declspec(dllexport) +#else +#define DISCORD_EXPORT __declspec(dllimport) +#endif +#else +#define DISCORD_EXPORT __attribute__((visibility("default"))) +#endif +#else +#define DISCORD_EXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command); +DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId); + +#ifdef __cplusplus +} +#endif diff --git a/deps/discord-rpc/include/discord_rpc.h b/deps/discord-rpc/include/discord_rpc.h new file mode 100644 index 0000000..9470434 --- /dev/null +++ b/deps/discord-rpc/include/discord_rpc.h @@ -0,0 +1,90 @@ +#pragma once +#include + +// clang-format off + +#if defined(DISCORD_DYNAMIC_LIB) +# if defined(_WIN32) +# if defined(DISCORD_BUILDING_SDK) +# define DISCORD_EXPORT __declspec(dllexport) +# else +# define DISCORD_EXPORT __declspec(dllimport) +# endif +# else +# define DISCORD_EXPORT __attribute__((visibility("default"))) +# endif +#else +# define DISCORD_EXPORT +#endif + +// clang-format on + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct DiscordRichPresence { + const char* state; /* max 128 bytes */ + const char* details; /* max 128 bytes */ + int64_t startTimestamp; + int64_t endTimestamp; + const char* largeImageKey; /* max 32 bytes */ + const char* largeImageText; /* max 128 bytes */ + const char* smallImageKey; /* max 32 bytes */ + const char* smallImageText; /* max 128 bytes */ + const char* partyId; /* max 128 bytes */ + int partySize; + int partyMax; + int partyPrivacy; + const char* matchSecret; /* max 128 bytes */ + const char* joinSecret; /* max 128 bytes */ + const char* spectateSecret; /* max 128 bytes */ + int8_t instance; +} DiscordRichPresence; + +typedef struct DiscordUser { + const char* userId; + const char* username; + const char* discriminator; + const char* avatar; +} DiscordUser; + +typedef struct DiscordEventHandlers { + void (*ready)(const DiscordUser* request); + void (*disconnected)(int errorCode, const char* message); + void (*errored)(int errorCode, const char* message); + void (*joinGame)(const char* joinSecret); + void (*spectateGame)(const char* spectateSecret); + void (*joinRequest)(const DiscordUser* request); +} DiscordEventHandlers; + +#define DISCORD_REPLY_NO 0 +#define DISCORD_REPLY_YES 1 +#define DISCORD_REPLY_IGNORE 2 +#define DISCORD_PARTY_PRIVATE 0 +#define DISCORD_PARTY_PUBLIC 1 + +DISCORD_EXPORT void Discord_Initialize(const char* applicationId, + DiscordEventHandlers* handlers, + int autoRegister, + const char* optionalSteamId); +DISCORD_EXPORT void Discord_Shutdown(void); + +/* checks for incoming messages, dispatches callbacks */ +DISCORD_EXPORT void Discord_RunCallbacks(void); + +/* If you disable the lib starting its own io thread, you'll need to call this from your own */ +#ifdef DISCORD_DISABLE_IO_THREAD +DISCORD_EXPORT void Discord_UpdateConnection(void); +#endif + +DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence); +DISCORD_EXPORT void Discord_ClearPresence(void); + +DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply); + +DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers); + +#ifdef __cplusplus +} /* extern "C" */ +#endif diff --git a/deps/discord-rpc/src/CMakeLists.txt b/deps/discord-rpc/src/CMakeLists.txt new file mode 100644 index 0000000..290d761 --- /dev/null +++ b/deps/discord-rpc/src/CMakeLists.txt @@ -0,0 +1,147 @@ +include_directories(${PROJECT_SOURCE_DIR}/include) + +option(ENABLE_IO_THREAD "Start up a separate I/O thread, otherwise I'd need to call an update function" ON) +option(USE_STATIC_CRT "Use /MT[d] for dynamic library" OFF) +option(WARNINGS_AS_ERRORS "When enabled, compiles with `-Werror` (on *nix platforms)." OFF) + +set(CMAKE_CXX_STANDARD 14) + +set(BASE_RPC_SRC + ${PROJECT_SOURCE_DIR}/include/discord_rpc.h + discord_rpc.cpp + ${PROJECT_SOURCE_DIR}/include/discord_register.h + rpc_connection.h + rpc_connection.cpp + serialization.h + serialization.cpp + connection.h + backoff.h + msg_queue.h +) + +if (${BUILD_SHARED_LIBS}) + if(WIN32) + set(BASE_RPC_SRC ${BASE_RPC_SRC} dllmain.cpp) + endif(WIN32) +endif(${BUILD_SHARED_LIBS}) + +if(WIN32) + add_definitions(-DDISCORD_WINDOWS) + set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_win.cpp discord_register_win.cpp) + add_library(discord-rpc ${BASE_RPC_SRC}) + if (MSVC) + if(USE_STATIC_CRT) + foreach(CompilerFlag + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + endforeach() + endif(USE_STATIC_CRT) + target_compile_options(discord-rpc PRIVATE /EHsc + /Wall + /wd4100 # unreferenced formal parameter + /wd4514 # unreferenced inline + /wd4625 # copy constructor deleted + /wd5026 # move constructor deleted + /wd4626 # move assignment operator deleted + /wd4668 # not defined preprocessor macro + /wd4710 # function not inlined + /wd4711 # function was inlined + /wd4820 # structure padding + /wd4946 # reinterpret_cast used between related classes + /wd5027 # move assignment operator was implicitly defined as deleted + ) + endif(MSVC) + target_link_libraries(discord-rpc PRIVATE psapi advapi32) +endif(WIN32) + +if(UNIX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_unix.cpp) + + if (APPLE) + add_definitions(-DDISCORD_OSX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_osx.m) + else (APPLE) + add_definitions(-DDISCORD_LINUX) + set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_linux.cpp) + endif(APPLE) + + add_library(discord-rpc ${BASE_RPC_SRC}) + target_link_libraries(discord-rpc PUBLIC pthread) + + if (APPLE) + target_link_libraries(discord-rpc PRIVATE "-framework AppKit, -mmacosx-version-min=10.10") + endif (APPLE) + + target_compile_options(discord-rpc PRIVATE + -g + -Wall + -Wextra + -Wpedantic + ) + + if (${WARNINGS_AS_ERRORS}) + target_compile_options(discord-rpc PRIVATE -Werror) + endif (${WARNINGS_AS_ERRORS}) + + target_compile_options(discord-rpc PRIVATE + -Wno-unknown-pragmas # pragma push thing doesn't work on clang + -Wno-old-style-cast # it's fine + -Wno-c++98-compat # that was almost 2 decades ago + -Wno-c++98-compat-pedantic + -Wno-missing-noreturn + -Wno-padded # structure padding + -Wno-covered-switch-default + -Wno-exit-time-destructors # not sure about these + -Wno-global-constructors + ) + + if (${BUILD_SHARED_LIBS}) + target_compile_options(discord-rpc PRIVATE -fPIC) + endif (${BUILD_SHARED_LIBS}) + + if (APPLE) + target_link_libraries(discord-rpc PRIVATE "-framework AppKit") + endif (APPLE) +endif(UNIX) + +target_include_directories(discord-rpc PRIVATE ${RAPIDJSON}/include) + +if (NOT ${ENABLE_IO_THREAD}) + target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DISABLE_IO_THREAD) +endif (NOT ${ENABLE_IO_THREAD}) + +if (${BUILD_SHARED_LIBS}) + target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DYNAMIC_LIB) + target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK) +endif(${BUILD_SHARED_LIBS}) + +if (CLANG_FORMAT_CMD) + add_dependencies(discord-rpc clangformat) +endif(CLANG_FORMAT_CMD) + +# install + +install( + TARGETS discord-rpc + EXPORT "discord-rpc" + RUNTIME + DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY + DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE + DESTINATION "${CMAKE_INSTALL_LIBDIR}" + INCLUDES + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +install( + FILES + "../include/discord_rpc.h" + "../include/discord_register.h" + DESTINATION "include" +) diff --git a/deps/discord-rpc/src/backoff.h b/deps/discord-rpc/src/backoff.h new file mode 100644 index 0000000..a3e736f --- /dev/null +++ b/deps/discord-rpc/src/backoff.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include +#include +#include + +struct Backoff { + int64_t minAmount; + int64_t maxAmount; + int64_t current; + int fails; + std::mt19937_64 randGenerator; + std::uniform_real_distribution<> randDistribution; + + double rand01() { return randDistribution(randGenerator); } + + Backoff(int64_t min, int64_t max) + : minAmount(min) + , maxAmount(max) + , current(min) + , fails(0) + , randGenerator((uint64_t)time(0)) + { + } + + void reset() + { + fails = 0; + current = minAmount; + } + + int64_t nextDelay() + { + ++fails; + int64_t delay = (int64_t)((double)current * 2.0 * rand01()); + current = std::min(current + delay, maxAmount); + return current; + } +}; diff --git a/deps/discord-rpc/src/connection.h b/deps/discord-rpc/src/connection.h new file mode 100644 index 0000000..a8f99b9 --- /dev/null +++ b/deps/discord-rpc/src/connection.h @@ -0,0 +1,19 @@ +#pragma once + +// This is to wrap the platform specific kinds of connect/read/write. + +#include +#include + +// not really connectiony, but need per-platform +int GetProcessId(); + +struct BaseConnection { + static BaseConnection* Create(); + static void Destroy(BaseConnection*&); + bool isOpen{false}; + bool Open(); + bool Close(); + bool Write(const void* data, size_t length); + bool Read(void* data, size_t length); +}; diff --git a/deps/discord-rpc/src/connection_unix.cpp b/deps/discord-rpc/src/connection_unix.cpp new file mode 100644 index 0000000..85dace3 --- /dev/null +++ b/deps/discord-rpc/src/connection_unix.cpp @@ -0,0 +1,125 @@ +#include "connection.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +int GetProcessId() +{ + return ::getpid(); +} + +struct BaseConnectionUnix : public BaseConnection { + int sock{-1}; +}; + +static BaseConnectionUnix Connection; +static sockaddr_un PipeAddr{}; +#ifdef MSG_NOSIGNAL +static int MsgFlags = MSG_NOSIGNAL; +#else +static int MsgFlags = 0; +#endif + +static const char* GetTempPath() +{ + const char* temp = getenv("XDG_RUNTIME_DIR"); + temp = temp ? temp : getenv("TMPDIR"); + temp = temp ? temp : getenv("TMP"); + temp = temp ? temp : getenv("TEMP"); + temp = temp ? temp : "/tmp"; + return temp; +} + +/*static*/ BaseConnection* BaseConnection::Create() +{ + PipeAddr.sun_family = AF_UNIX; + return &Connection; +} + +/*static*/ void BaseConnection::Destroy(BaseConnection*& c) +{ + auto self = reinterpret_cast(c); + self->Close(); + c = nullptr; +} + +bool BaseConnection::Open() +{ + const char* tempPath = GetTempPath(); + auto self = reinterpret_cast(this); + self->sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (self->sock == -1) { + return false; + } + fcntl(self->sock, F_SETFL, O_NONBLOCK); +#ifdef SO_NOSIGPIPE + int optval = 1; + setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)); +#endif + + for (int pipeNum = 0; pipeNum < 10; ++pipeNum) { + snprintf( + PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum); + int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr)); + if (err == 0) { + self->isOpen = true; + return true; + } + } + self->Close(); + return false; +} + +bool BaseConnection::Close() +{ + auto self = reinterpret_cast(this); + if (self->sock == -1) { + return false; + } + close(self->sock); + self->sock = -1; + self->isOpen = false; + return true; +} + +bool BaseConnection::Write(const void* data, size_t length) +{ + auto self = reinterpret_cast(this); + + if (self->sock == -1) { + return false; + } + + ssize_t sentBytes = send(self->sock, data, length, MsgFlags); + if (sentBytes < 0) { + Close(); + } + return sentBytes == (ssize_t)length; +} + +bool BaseConnection::Read(void* data, size_t length) +{ + auto self = reinterpret_cast(this); + + if (self->sock == -1) { + return false; + } + + int res = (int)recv(self->sock, data, length, MsgFlags); + if (res < 0) { + if (errno == EAGAIN) { + return false; + } + Close(); + } + else if (res == 0) { + Close(); + } + return res == (int)length; +} diff --git a/deps/discord-rpc/src/connection_win.cpp b/deps/discord-rpc/src/connection_win.cpp new file mode 100644 index 0000000..2dd2750 --- /dev/null +++ b/deps/discord-rpc/src/connection_win.cpp @@ -0,0 +1,128 @@ +#include "connection.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMCX +#define NOSERVICE +#define NOIME +#include +#include + +int GetProcessId() +{ + return (int)::GetCurrentProcessId(); +} + +struct BaseConnectionWin : public BaseConnection { + HANDLE pipe{INVALID_HANDLE_VALUE}; +}; + +static BaseConnectionWin Connection; + +/*static*/ BaseConnection* BaseConnection::Create() +{ + return &Connection; +} + +/*static*/ void BaseConnection::Destroy(BaseConnection*& c) +{ + auto self = reinterpret_cast(c); + self->Close(); + c = nullptr; +} + +bool BaseConnection::Open() +{ + wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"}; + const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2; + pipeName[pipeDigit] = L'0'; + auto self = reinterpret_cast(this); + for (;;) { + self->pipe = ::CreateFileW( + pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); + if (self->pipe != INVALID_HANDLE_VALUE) { + self->isOpen = true; + return true; + } + + auto lastError = GetLastError(); + if (lastError == ERROR_FILE_NOT_FOUND) { + if (pipeName[pipeDigit] < L'9') { + pipeName[pipeDigit]++; + continue; + } + } + else if (lastError == ERROR_PIPE_BUSY) { + if (!WaitNamedPipeW(pipeName, 10000)) { + return false; + } + continue; + } + return false; + } +} + +bool BaseConnection::Close() +{ + auto self = reinterpret_cast(this); + ::CloseHandle(self->pipe); + self->pipe = INVALID_HANDLE_VALUE; + self->isOpen = false; + return true; +} + +bool BaseConnection::Write(const void* data, size_t length) +{ + if (length == 0) { + return true; + } + auto self = reinterpret_cast(this); + assert(self); + if (!self) { + return false; + } + if (self->pipe == INVALID_HANDLE_VALUE) { + return false; + } + assert(data); + if (!data) { + return false; + } + const DWORD bytesLength = (DWORD)length; + DWORD bytesWritten = 0; + return ::WriteFile(self->pipe, data, bytesLength, &bytesWritten, nullptr) == TRUE && + bytesWritten == bytesLength; +} + +bool BaseConnection::Read(void* data, size_t length) +{ + assert(data); + if (!data) { + return false; + } + auto self = reinterpret_cast(this); + assert(self); + if (!self) { + return false; + } + if (self->pipe == INVALID_HANDLE_VALUE) { + return false; + } + DWORD bytesAvailable = 0; + if (::PeekNamedPipe(self->pipe, nullptr, 0, nullptr, &bytesAvailable, nullptr)) { + if (bytesAvailable >= length) { + DWORD bytesToRead = (DWORD)length; + DWORD bytesRead = 0; + if (::ReadFile(self->pipe, data, bytesToRead, &bytesRead, nullptr) == TRUE) { + assert(bytesToRead == bytesRead); + return true; + } + else { + Close(); + } + } + } + else { + Close(); + } + return false; +} diff --git a/deps/discord-rpc/src/discord_register_linux.cpp b/deps/discord-rpc/src/discord_register_linux.cpp new file mode 100644 index 0000000..dd92eea --- /dev/null +++ b/deps/discord-rpc/src/discord_register_linux.cpp @@ -0,0 +1,102 @@ +#include "discord_rpc.h" +#include "discord_register.h" +#include + +#include +#include +#include +#include +#include +#include + +static bool Mkdir(const char* path) +{ + int result = mkdir(path, 0755); + if (result == 0) { + return true; + } + if (errno == EEXIST) { + return true; + } + return false; +} + +// we want to register games so we can run them from Discord client as discord-:// +extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) +{ + // Add a desktop file and update some mime handlers so that xdg-open does the right thing. + + const char* home = getenv("HOME"); + if (!home) { + return; + } + + char exePath[1024]; + if (!command || !command[0]) { + ssize_t size = readlink("/proc/self/exe", exePath, sizeof(exePath)); + if (size <= 0 || size >= (ssize_t)sizeof(exePath)) { + return; + } + exePath[size] = '\0'; + command = exePath; + } + + const char* desktopFileFormat = "[Desktop Entry]\n" + "Name=Game %s\n" + "Exec=%s %%u\n" // note: it really wants that %u in there + "Type=Application\n" + "NoDisplay=true\n" + "Categories=Discord;Games;\n" + "MimeType=x-scheme-handler/discord-%s;\n"; + char desktopFile[2048]; + int fileLen = snprintf( + desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId); + if (fileLen <= 0) { + return; + } + + char desktopFilename[256]; + snprintf(desktopFilename, sizeof(desktopFilename), "/discord-%s.desktop", applicationId); + + char desktopFilePath[1024]; + snprintf(desktopFilePath, sizeof(desktopFilePath), "%s/.local", home); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, "/share"); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, "/applications"); + if (!Mkdir(desktopFilePath)) { + return; + } + strcat(desktopFilePath, desktopFilename); + + FILE* fp = fopen(desktopFilePath, "w"); + if (fp) { + fwrite(desktopFile, 1, fileLen, fp); + fclose(fp); + } + else { + return; + } + + char xdgMimeCommand[1024]; + snprintf(xdgMimeCommand, + sizeof(xdgMimeCommand), + "xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s", + applicationId, + applicationId); + if (system(xdgMimeCommand) < 0) { + fprintf(stderr, "Failed to register mime handler\n"); + } +} + +extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, + const char* steamId) +{ + char command[256]; + sprintf(command, "xdg-open steam://rungameid/%s", steamId); + Discord_Register(applicationId, command); +} diff --git a/deps/discord-rpc/src/discord_register_osx.m b/deps/discord-rpc/src/discord_register_osx.m new file mode 100644 index 0000000..d710102 --- /dev/null +++ b/deps/discord-rpc/src/discord_register_osx.m @@ -0,0 +1,80 @@ +#include +#include + +#import + +#include "discord_register.h" + +static void RegisterCommand(const char* applicationId, const char* command) +{ + // There does not appear to be a way to register arbitrary commands on OSX, so instead we'll save the command + // to a file in the Discord config path, and when it is needed, Discord can try to load the file there, open + // the command therein (will pass to js's window.open, so requires a url-like thing) + + // Note: will not work for sandboxed apps + NSString *home = NSHomeDirectory(); + if (!home) { + return; + } + + NSString *path = [[[[[[home stringByAppendingPathComponent:@"Library"] + stringByAppendingPathComponent:@"Application Support"] + stringByAppendingPathComponent:@"discord"] + stringByAppendingPathComponent:@"games"] + stringByAppendingPathComponent:[NSString stringWithUTF8String:applicationId]] + stringByAppendingPathExtension:@"json"]; + [[NSFileManager defaultManager] createDirectoryAtPath:[path stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; + + NSString *jsonBuffer = [NSString stringWithFormat:@"{\"command\": \"%s\"}", command]; + [jsonBuffer writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:nil]; +} + +static void RegisterURL(const char* applicationId) +{ + char url[256]; + snprintf(url, sizeof(url), "discord-%s", applicationId); + CFStringRef cfURL = CFStringCreateWithCString(NULL, url, kCFStringEncodingUTF8); + + NSString* myBundleId = [[NSBundle mainBundle] bundleIdentifier]; + if (!myBundleId) { + fprintf(stderr, "No bundle id found\n"); + return; + } + + NSURL* myURL = [[NSBundle mainBundle] bundleURL]; + if (!myURL) { + fprintf(stderr, "No bundle url found\n"); + return; + } + + OSStatus status = LSSetDefaultHandlerForURLScheme(cfURL, (__bridge CFStringRef)myBundleId); + if (status != noErr) { + fprintf(stderr, "Error in LSSetDefaultHandlerForURLScheme: %d\n", (int)status); + return; + } + + status = LSRegisterURL((__bridge CFURLRef)myURL, true); + if (status != noErr) { + fprintf(stderr, "Error in LSRegisterURL: %d\n", (int)status); + } +} + +void Discord_Register(const char* applicationId, const char* command) +{ + if (command) { + RegisterCommand(applicationId, command); + } + else { + // raii lite + @autoreleasepool { + RegisterURL(applicationId); + } + } +} + +void Discord_RegisterSteamGame(const char* applicationId, const char* steamId) +{ + char command[256]; + snprintf(command, 256, "steam://rungameid/%s", steamId); + Discord_Register(applicationId, command); +} diff --git a/deps/discord-rpc/src/discord_register_win.cpp b/deps/discord-rpc/src/discord_register_win.cpp new file mode 100644 index 0000000..0b1c4a1 --- /dev/null +++ b/deps/discord-rpc/src/discord_register_win.cpp @@ -0,0 +1,186 @@ +#include "discord_rpc.h" +#include "discord_register.h" + +#define WIN32_LEAN_AND_MEAN +#define NOMCX +#define NOSERVICE +#define NOIME +#include +#include +#include + +/** + * Updated fixes for MinGW and WinXP + * This block is written the way it does not involve changing the rest of the code + * Checked to be compiling + * 1) strsafe.h belongs to Windows SDK and cannot be added to MinGW + * #include guarded, functions redirected to substitutes + * 2) RegSetKeyValueW and LSTATUS are not declared in + * The entire function is rewritten + */ +#ifdef __MINGW32__ +#include +/// strsafe.h fixes +static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...) +{ + HRESULT ret; + va_list va; + va_start(va, pszFormat); + cbDest /= 2; // Size is divided by 2 to convert from bytes to wide characters - causes segfault + // othervise + ret = vsnwprintf(pszDest, cbDest, pszFormat, va); + pszDest[cbDest - 1] = 0; // Terminate the string in case a buffer overflow; -1 will be returned + va_end(va); + return ret; +} +#else +#include +#include +#endif // __MINGW32__ + +/// winreg.h fixes +#ifndef LSTATUS +#define LSTATUS LONG +#endif +#ifdef RegSetKeyValueW +#undefine RegSetKeyValueW +#endif +#define RegSetKeyValueW regset +static LSTATUS regset(HKEY hkey, + LPCWSTR subkey, + LPCWSTR name, + DWORD type, + const void* data, + DWORD len) +{ + HKEY htkey = hkey, hsubkey = nullptr; + LSTATUS ret; + if (subkey && subkey[0]) { + if ((ret = RegCreateKeyExW(hkey, subkey, 0, 0, 0, KEY_ALL_ACCESS, 0, &hsubkey, 0)) != + ERROR_SUCCESS) + return ret; + htkey = hsubkey; + } + ret = RegSetValueExW(htkey, name, 0, type, (const BYTE*)data, len); + if (hsubkey && hsubkey != hkey) + RegCloseKey(hsubkey); + return ret; +} + +static void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command) +{ + // https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx + // we want to register games so we can run them as discord-:// + // Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions. + + wchar_t exeFilePath[MAX_PATH]; + DWORD exeLen = GetModuleFileNameW(nullptr, exeFilePath, MAX_PATH); + wchar_t openCommand[1024]; + + if (command && command[0]) { + StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", command); + } + else { + // StringCbCopyW(openCommand, sizeof(openCommand), exeFilePath); + StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", exeFilePath); + } + + wchar_t protocolName[64]; + StringCbPrintfW(protocolName, sizeof(protocolName), L"discord-%s", applicationId); + wchar_t protocolDescription[128]; + StringCbPrintfW( + protocolDescription, sizeof(protocolDescription), L"URL:Run game %s protocol", applicationId); + wchar_t urlProtocol = 0; + + wchar_t keyName[256]; + StringCbPrintfW(keyName, sizeof(keyName), L"Software\\Classes\\%s", protocolName); + HKEY key; + auto status = + RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, nullptr, 0, KEY_WRITE, nullptr, &key, nullptr); + if (status != ERROR_SUCCESS) { + fprintf(stderr, "Error creating key\n"); + return; + } + DWORD len; + LSTATUS result; + len = (DWORD)lstrlenW(protocolDescription) + 1; + result = + RegSetKeyValueW(key, nullptr, nullptr, REG_SZ, protocolDescription, len * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing description\n"); + } + + len = (DWORD)lstrlenW(protocolDescription) + 1; + result = RegSetKeyValueW(key, nullptr, L"URL Protocol", REG_SZ, &urlProtocol, sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing description\n"); + } + + result = RegSetKeyValueW( + key, L"DefaultIcon", nullptr, REG_SZ, exeFilePath, (exeLen + 1) * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing icon\n"); + } + + len = (DWORD)lstrlenW(openCommand) + 1; + result = RegSetKeyValueW( + key, L"shell\\open\\command", nullptr, REG_SZ, openCommand, len * sizeof(wchar_t)); + if (FAILED(result)) { + fprintf(stderr, "Error writing command\n"); + } + RegCloseKey(key); +} + +extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command) +{ + wchar_t appId[32]; + MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); + + wchar_t openCommand[1024]; + const wchar_t* wcommand = nullptr; + if (command && command[0]) { + const auto commandBufferLen = sizeof(openCommand) / sizeof(*openCommand); + MultiByteToWideChar(CP_UTF8, 0, command, -1, openCommand, commandBufferLen); + wcommand = openCommand; + } + + Discord_RegisterW(appId, wcommand); +} + +extern "C" DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, + const char* steamId) +{ + wchar_t appId[32]; + MultiByteToWideChar(CP_UTF8, 0, applicationId, -1, appId, 32); + + wchar_t wSteamId[32]; + MultiByteToWideChar(CP_UTF8, 0, steamId, -1, wSteamId, 32); + + HKEY key; + auto status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", 0, KEY_READ, &key); + if (status != ERROR_SUCCESS) { + fprintf(stderr, "Error opening Steam key\n"); + return; + } + + wchar_t steamPath[MAX_PATH]; + DWORD pathBytes = sizeof(steamPath); + status = RegQueryValueExW(key, L"SteamExe", nullptr, nullptr, (BYTE*)steamPath, &pathBytes); + RegCloseKey(key); + if (status != ERROR_SUCCESS || pathBytes < 1) { + fprintf(stderr, "Error reading SteamExe key\n"); + return; + } + + DWORD pathChars = pathBytes / sizeof(wchar_t); + for (DWORD i = 0; i < pathChars; ++i) { + if (steamPath[i] == L'/') { + steamPath[i] = L'\\'; + } + } + + wchar_t command[1024]; + StringCbPrintfW(command, sizeof(command), L"\"%s\" steam://rungameid/%s", steamPath, wSteamId); + + Discord_RegisterW(appId, command); +} diff --git a/deps/discord-rpc/src/discord_rpc.cpp b/deps/discord-rpc/src/discord_rpc.cpp new file mode 100644 index 0000000..0392453 --- /dev/null +++ b/deps/discord-rpc/src/discord_rpc.cpp @@ -0,0 +1,504 @@ +#include "discord_rpc.h" + +#include "backoff.h" +#include "discord_register.h" +#include "msg_queue.h" +#include "rpc_connection.h" +#include "serialization.h" + +#include +#include +#include + +#ifndef DISCORD_DISABLE_IO_THREAD +#include +#include +#endif + +constexpr size_t MaxMessageSize{16 * 1024}; +constexpr size_t MessageQueueSize{8}; +constexpr size_t JoinQueueSize{8}; + +struct QueuedMessage { + size_t length; + char buffer[MaxMessageSize]; + + void Copy(const QueuedMessage& other) + { + length = other.length; + if (length) { + memcpy(buffer, other.buffer, length); + } + } +}; + +struct User { + // snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null + // terminator = 21 + char userId[32]; + // 32 unicode glyphs is max name size => 4 bytes per glyph in the worst case, +1 for null + // terminator = 129 + char username[344]; + // 4 decimal digits + 1 null terminator = 5 + char discriminator[8]; + // optional 'a_' + md5 hex digest (32 bytes) + null terminator = 35 + char avatar[128]; + // Rounded way up because I'm paranoid about games breaking from future changes in these sizes +}; + +static RpcConnection* Connection{nullptr}; +static DiscordEventHandlers QueuedHandlers{}; +static DiscordEventHandlers Handlers{}; +static std::atomic_bool WasJustConnected{false}; +static std::atomic_bool WasJustDisconnected{false}; +static std::atomic_bool GotErrorMessage{false}; +static std::atomic_bool WasJoinGame{false}; +static std::atomic_bool WasSpectateGame{false}; +static std::atomic_bool UpdatePresence{false}; +static char JoinGameSecret[256]; +static char SpectateGameSecret[256]; +static int LastErrorCode{0}; +static char LastErrorMessage[256]; +static int LastDisconnectErrorCode{0}; +static char LastDisconnectErrorMessage[256]; +static std::mutex PresenceMutex; +static std::mutex HandlerMutex; +static QueuedMessage QueuedPresence{}; +static MsgQueue SendQueue; +static MsgQueue JoinAskQueue; +static User connectedUser; + +// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential +// backoff from 0.5 seconds to 1 minute +static Backoff ReconnectTimeMs(500, 60 * 1000); +static auto NextConnect = std::chrono::system_clock::now(); +static int Pid{0}; +static int Nonce{1}; + +#ifndef DISCORD_DISABLE_IO_THREAD +static void Discord_UpdateConnection(void); +class IoThreadHolder { +private: + std::atomic_bool keepRunning{true}; + std::mutex waitForIOMutex; + std::condition_variable waitForIOActivity; + std::thread ioThread; + +public: + void Start() + { + keepRunning.store(true); + ioThread = std::thread([&]() { + const std::chrono::duration maxWait{500LL}; + Discord_UpdateConnection(); + while (keepRunning.load()) { + std::unique_lock lock(waitForIOMutex); + waitForIOActivity.wait_for(lock, maxWait); + Discord_UpdateConnection(); + } + }); + } + + void Notify() { waitForIOActivity.notify_all(); } + + void Stop() + { + keepRunning.exchange(false); + Notify(); + if (ioThread.joinable()) { + ioThread.join(); + } + } + + ~IoThreadHolder() { Stop(); } +}; +#else +class IoThreadHolder { +public: + void Start() {} + void Stop() {} + void Notify() {} +}; +#endif // DISCORD_DISABLE_IO_THREAD +static IoThreadHolder* IoThread{nullptr}; + +static void UpdateReconnectTime() +{ + NextConnect = std::chrono::system_clock::now() + + std::chrono::duration{ReconnectTimeMs.nextDelay()}; +} + +#ifdef DISCORD_DISABLE_IO_THREAD +extern "C" DISCORD_EXPORT void Discord_UpdateConnection(void) +#else +static void Discord_UpdateConnection(void) +#endif +{ + if (!Connection) { + return; + } + + if (!Connection->IsOpen()) { + if (std::chrono::system_clock::now() >= NextConnect) { + UpdateReconnectTime(); + Connection->Open(); + } + } + else { + // reads + + for (;;) { + JsonDocument message; + + if (!Connection->Read(message)) { + break; + } + + const char* evtName = GetStrMember(&message, "evt"); + const char* nonce = GetStrMember(&message, "nonce"); + + if (nonce) { + // in responses only -- should use to match up response when needed. + + if (evtName && strcmp(evtName, "ERROR") == 0) { + auto data = GetObjMember(&message, "data"); + LastErrorCode = GetIntMember(data, "code"); + StringCopy(LastErrorMessage, GetStrMember(data, "message", "")); + GotErrorMessage.store(true); + } + } + else { + // should have evt == name of event, optional data + if (evtName == nullptr) { + continue; + } + + auto data = GetObjMember(&message, "data"); + + if (strcmp(evtName, "ACTIVITY_JOIN") == 0) { + auto secret = GetStrMember(data, "secret"); + if (secret) { + StringCopy(JoinGameSecret, secret); + WasJoinGame.store(true); + } + } + else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0) { + auto secret = GetStrMember(data, "secret"); + if (secret) { + StringCopy(SpectateGameSecret, secret); + WasSpectateGame.store(true); + } + } + else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0) { + auto user = GetObjMember(data, "user"); + auto userId = GetStrMember(user, "id"); + auto username = GetStrMember(user, "username"); + auto avatar = GetStrMember(user, "avatar"); + auto joinReq = JoinAskQueue.GetNextAddMessage(); + if (userId && username && joinReq) { + StringCopy(joinReq->userId, userId); + StringCopy(joinReq->username, username); + auto discriminator = GetStrMember(user, "discriminator"); + if (discriminator) { + StringCopy(joinReq->discriminator, discriminator); + } + if (avatar) { + StringCopy(joinReq->avatar, avatar); + } + else { + joinReq->avatar[0] = 0; + } + JoinAskQueue.CommitAdd(); + } + } + } + } + + // writes + if (UpdatePresence.exchange(false) && QueuedPresence.length) { + QueuedMessage local; + { + std::lock_guard guard(PresenceMutex); + local.Copy(QueuedPresence); + } + if (!Connection->Write(local.buffer, local.length)) { + // if we fail to send, requeue + std::lock_guard guard(PresenceMutex); + QueuedPresence.Copy(local); + UpdatePresence.exchange(true); + } + } + + while (SendQueue.HavePendingSends()) { + auto qmessage = SendQueue.GetNextSendMessage(); + Connection->Write(qmessage->buffer, qmessage->length); + SendQueue.CommitSend(); + } + } +} + +static void SignalIOActivity() +{ + if (IoThread != nullptr) { + IoThread->Notify(); + } +} + +static bool RegisterForEvent(const char* evtName) +{ + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); + SendQueue.CommitAdd(); + SignalIOActivity(); + return true; + } + return false; +} + +static bool DeregisterForEvent(const char* evtName) +{ + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName); + SendQueue.CommitAdd(); + SignalIOActivity(); + return true; + } + return false; +} + +extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, + DiscordEventHandlers* handlers, + int autoRegister, + const char* optionalSteamId) +{ + IoThread = new (std::nothrow) IoThreadHolder(); + if (IoThread == nullptr) { + return; + } + + if (autoRegister) { + if (optionalSteamId && optionalSteamId[0]) { + Discord_RegisterSteamGame(applicationId, optionalSteamId); + } + else { + Discord_Register(applicationId, nullptr); + } + } + + Pid = GetProcessId(); + + { + std::lock_guard guard(HandlerMutex); + + if (handlers) { + QueuedHandlers = *handlers; + } + else { + QueuedHandlers = {}; + } + + Handlers = {}; + } + + if (Connection) { + return; + } + + Connection = RpcConnection::Create(applicationId); + Connection->onConnect = [](JsonDocument& readyMessage) { + Discord_UpdateHandlers(&QueuedHandlers); + if (QueuedPresence.length > 0) { + UpdatePresence.exchange(true); + SignalIOActivity(); + } + auto data = GetObjMember(&readyMessage, "data"); + auto user = GetObjMember(data, "user"); + auto userId = GetStrMember(user, "id"); + auto username = GetStrMember(user, "username"); + auto avatar = GetStrMember(user, "avatar"); + if (userId && username) { + StringCopy(connectedUser.userId, userId); + StringCopy(connectedUser.username, username); + auto discriminator = GetStrMember(user, "discriminator"); + if (discriminator) { + StringCopy(connectedUser.discriminator, discriminator); + } + if (avatar) { + StringCopy(connectedUser.avatar, avatar); + } + else { + connectedUser.avatar[0] = 0; + } + } + WasJustConnected.exchange(true); + ReconnectTimeMs.reset(); + }; + Connection->onDisconnect = [](int err, const char* message) { + LastDisconnectErrorCode = err; + StringCopy(LastDisconnectErrorMessage, message); + WasJustDisconnected.exchange(true); + UpdateReconnectTime(); + }; + + IoThread->Start(); +} + +extern "C" DISCORD_EXPORT void Discord_Shutdown(void) +{ + if (!Connection) { + return; + } + Connection->onConnect = nullptr; + Connection->onDisconnect = nullptr; + Handlers = {}; + QueuedPresence.length = 0; + UpdatePresence.exchange(false); + if (IoThread != nullptr) { + IoThread->Stop(); + delete IoThread; + IoThread = nullptr; + } + + RpcConnection::Destroy(Connection); +} + +extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence) +{ + { + std::lock_guard guard(PresenceMutex); + QueuedPresence.length = JsonWriteRichPresenceObj( + QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); + UpdatePresence.exchange(true); + } + SignalIOActivity(); +} + +extern "C" DISCORD_EXPORT void Discord_ClearPresence(void) +{ + Discord_UpdatePresence(nullptr); +} + +extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply) +{ + // if we are not connected, let's not batch up stale messages for later + if (!Connection || !Connection->IsOpen()) { + return; + } + auto qmessage = SendQueue.GetNextAddMessage(); + if (qmessage) { + qmessage->length = + JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++); + SendQueue.CommitAdd(); + SignalIOActivity(); + } +} + +extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) +{ + // Note on some weirdness: internally we might connect, get other signals, disconnect any number + // of times inbetween calls here. Externally, we want the sequence to seem sane, so any other + // signals are book-ended by calls to ready and disconnect. + + if (!Connection) { + return; + } + + bool wasDisconnected = WasJustDisconnected.exchange(false); + bool isConnected = Connection->IsOpen(); + + if (isConnected) { + // if we are connected, disconnect cb first + std::lock_guard guard(HandlerMutex); + if (wasDisconnected && Handlers.disconnected) { + Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage); + } + } + + if (WasJustConnected.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.ready) { + DiscordUser du{connectedUser.userId, + connectedUser.username, + connectedUser.discriminator, + connectedUser.avatar}; + Handlers.ready(&du); + } + } + + if (GotErrorMessage.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.errored) { + Handlers.errored(LastErrorCode, LastErrorMessage); + } + } + + if (WasJoinGame.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.joinGame) { + Handlers.joinGame(JoinGameSecret); + } + } + + if (WasSpectateGame.exchange(false)) { + std::lock_guard guard(HandlerMutex); + if (Handlers.spectateGame) { + Handlers.spectateGame(SpectateGameSecret); + } + } + + // Right now this batches up any requests and sends them all in a burst; I could imagine a world + // where the implementer would rather sequentially accept/reject each one before the next invite + // is sent. I left it this way because I could also imagine wanting to process these all and + // maybe show them in one common dialog and/or start fetching the avatars in parallel, and if + // not it should be trivial for the implementer to make a queue themselves. + while (JoinAskQueue.HavePendingSends()) { + auto req = JoinAskQueue.GetNextSendMessage(); + { + std::lock_guard guard(HandlerMutex); + if (Handlers.joinRequest) { + DiscordUser du{req->userId, req->username, req->discriminator, req->avatar}; + Handlers.joinRequest(&du); + } + } + JoinAskQueue.CommitSend(); + } + + if (!isConnected) { + // if we are not connected, disconnect message last + std::lock_guard guard(HandlerMutex); + if (wasDisconnected && Handlers.disconnected) { + Handlers.disconnected(LastDisconnectErrorCode, LastDisconnectErrorMessage); + } + } +} + +extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) +{ + if (newHandlers) { +#define HANDLE_EVENT_REGISTRATION(handler_name, event) \ + if (!Handlers.handler_name && newHandlers->handler_name) { \ + RegisterForEvent(event); \ + } \ + else if (Handlers.handler_name && !newHandlers->handler_name) { \ + DeregisterForEvent(event); \ + } + + std::lock_guard guard(HandlerMutex); + HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN") + HANDLE_EVENT_REGISTRATION(spectateGame, "ACTIVITY_SPECTATE") + HANDLE_EVENT_REGISTRATION(joinRequest, "ACTIVITY_JOIN_REQUEST") + +#undef HANDLE_EVENT_REGISTRATION + + Handlers = *newHandlers; + } + else { + std::lock_guard guard(HandlerMutex); + Handlers = {}; + } + return; +} diff --git a/deps/discord-rpc/src/dllmain.cpp b/deps/discord-rpc/src/dllmain.cpp new file mode 100644 index 0000000..fbfc295 --- /dev/null +++ b/deps/discord-rpc/src/dllmain.cpp @@ -0,0 +1,8 @@ +#include + +// outsmart GCC's missing-declarations warning +BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID); +BOOL WINAPI DllMain(HMODULE, DWORD, LPVOID) +{ + return TRUE; +} diff --git a/deps/discord-rpc/src/msg_queue.h b/deps/discord-rpc/src/msg_queue.h new file mode 100644 index 0000000..77f380e --- /dev/null +++ b/deps/discord-rpc/src/msg_queue.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +// A simple queue. No locks, but only works with a single thread as producer and a single thread as +// a consumer. Mutex up as needed. + +template +class MsgQueue { + ElementType queue_[QueueSize]; + std::atomic_uint nextAdd_{0}; + std::atomic_uint nextSend_{0}; + std::atomic_uint pendingSends_{0}; + +public: + MsgQueue() {} + + ElementType* GetNextAddMessage() + { + // if we are falling behind, bail + if (pendingSends_.load() >= QueueSize) { + return nullptr; + } + auto index = (nextAdd_++) % QueueSize; + return &queue_[index]; + } + void CommitAdd() { ++pendingSends_; } + + bool HavePendingSends() const { return pendingSends_.load() != 0; } + ElementType* GetNextSendMessage() + { + auto index = (nextSend_++) % QueueSize; + return &queue_[index]; + } + void CommitSend() { --pendingSends_; } +}; diff --git a/deps/discord-rpc/src/rpc_connection.cpp b/deps/discord-rpc/src/rpc_connection.cpp new file mode 100644 index 0000000..0933162 --- /dev/null +++ b/deps/discord-rpc/src/rpc_connection.cpp @@ -0,0 +1,137 @@ +#include "rpc_connection.h" +#include "serialization.h" + +#include + +static const int RpcVersion = 1; +static RpcConnection Instance; + +/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId) +{ + Instance.connection = BaseConnection::Create(); + StringCopy(Instance.appId, applicationId); + return &Instance; +} + +/*static*/ void RpcConnection::Destroy(RpcConnection*& c) +{ + c->Close(); + BaseConnection::Destroy(c->connection); + c = nullptr; +} + +void RpcConnection::Open() +{ + if (state == State::Connected) { + return; + } + + if (state == State::Disconnected && !connection->Open()) { + return; + } + + if (state == State::SentHandshake) { + JsonDocument message; + if (Read(message)) { + auto cmd = GetStrMember(&message, "cmd"); + auto evt = GetStrMember(&message, "evt"); + if (cmd && evt && !strcmp(cmd, "DISPATCH") && !strcmp(evt, "READY")) { + state = State::Connected; + if (onConnect) { + onConnect(message); + } + } + } + } + else { + sendFrame.opcode = Opcode::Handshake; + sendFrame.length = (uint32_t)JsonWriteHandshakeObj( + sendFrame.message, sizeof(sendFrame.message), RpcVersion, appId); + + if (connection->Write(&sendFrame, sizeof(MessageFrameHeader) + sendFrame.length)) { + state = State::SentHandshake; + } + else { + Close(); + } + } +} + +void RpcConnection::Close() +{ + if (onDisconnect && (state == State::Connected || state == State::SentHandshake)) { + onDisconnect(lastErrorCode, lastErrorMessage); + } + connection->Close(); + state = State::Disconnected; +} + +bool RpcConnection::Write(const void* data, size_t length) +{ + sendFrame.opcode = Opcode::Frame; + memcpy(sendFrame.message, data, length); + sendFrame.length = (uint32_t)length; + if (!connection->Write(&sendFrame, sizeof(MessageFrameHeader) + length)) { + Close(); + return false; + } + return true; +} + +bool RpcConnection::Read(JsonDocument& message) +{ + if (state != State::Connected && state != State::SentHandshake) { + return false; + } + MessageFrame readFrame; + for (;;) { + bool didRead = connection->Read(&readFrame, sizeof(MessageFrameHeader)); + if (!didRead) { + if (!connection->isOpen) { + lastErrorCode = (int)ErrorCode::PipeClosed; + StringCopy(lastErrorMessage, "Pipe closed"); + Close(); + } + return false; + } + + if (readFrame.length > 0) { + didRead = connection->Read(readFrame.message, readFrame.length); + if (!didRead) { + lastErrorCode = (int)ErrorCode::ReadCorrupt; + StringCopy(lastErrorMessage, "Partial data in frame"); + Close(); + return false; + } + readFrame.message[readFrame.length] = 0; + } + + switch (readFrame.opcode) { + case Opcode::Close: { + message.ParseInsitu(readFrame.message); + lastErrorCode = GetIntMember(&message, "code"); + StringCopy(lastErrorMessage, GetStrMember(&message, "message", "")); + Close(); + return false; + } + case Opcode::Frame: + message.ParseInsitu(readFrame.message); + return true; + case Opcode::Ping: + readFrame.opcode = Opcode::Pong; + if (!connection->Write(&readFrame, sizeof(MessageFrameHeader) + readFrame.length)) { + Close(); + } + break; + case Opcode::Pong: + break; + case Opcode::Handshake: + default: + // something bad happened + lastErrorCode = (int)ErrorCode::ReadCorrupt; + StringCopy(lastErrorMessage, "Bad ipc frame"); + Close(); + return false; + } + } +} diff --git a/deps/discord-rpc/src/rpc_connection.h b/deps/discord-rpc/src/rpc_connection.h new file mode 100644 index 0000000..bbdd05c --- /dev/null +++ b/deps/discord-rpc/src/rpc_connection.h @@ -0,0 +1,59 @@ +#pragma once + +#include "connection.h" +#include "serialization.h" + +// I took this from the buffer size libuv uses for named pipes; I suspect ours would usually be much +// smaller. +constexpr size_t MaxRpcFrameSize = 64 * 1024; + +struct RpcConnection { + enum class ErrorCode : int { + Success = 0, + PipeClosed = 1, + ReadCorrupt = 2, + }; + + enum class Opcode : uint32_t { + Handshake = 0, + Frame = 1, + Close = 2, + Ping = 3, + Pong = 4, + }; + + struct MessageFrameHeader { + Opcode opcode; + uint32_t length; + }; + + struct MessageFrame : public MessageFrameHeader { + char message[MaxRpcFrameSize - sizeof(MessageFrameHeader)]; + }; + + enum class State : uint32_t { + Disconnected, + SentHandshake, + AwaitingResponse, + Connected, + }; + + BaseConnection* connection{nullptr}; + State state{State::Disconnected}; + void (*onConnect)(JsonDocument& message){nullptr}; + void (*onDisconnect)(int errorCode, const char* message){nullptr}; + char appId[64]{}; + int lastErrorCode{0}; + char lastErrorMessage[256]{}; + RpcConnection::MessageFrame sendFrame; + + static RpcConnection* Create(const char* applicationId); + static void Destroy(RpcConnection*&); + + inline bool IsOpen() const { return state == State::Connected; } + + void Open(); + void Close(); + bool Write(const void* data, size_t length); + bool Read(JsonDocument& message); +}; diff --git a/deps/discord-rpc/src/serialization.cpp b/deps/discord-rpc/src/serialization.cpp new file mode 100644 index 0000000..70efa63 --- /dev/null +++ b/deps/discord-rpc/src/serialization.cpp @@ -0,0 +1,250 @@ +#include "serialization.h" +#include "connection.h" +#include "discord_rpc.h" + +template +void NumberToString(char* dest, T number) +{ + if (!number) { + *dest++ = '0'; + *dest++ = 0; + return; + } + if (number < 0) { + *dest++ = '-'; + number = -number; + } + char temp[32]; + int place = 0; + while (number) { + auto digit = number % 10; + number = number / 10; + temp[place++] = '0' + (char)digit; + } + for (--place; place >= 0; --place) { + *dest++ = temp[place]; + } + *dest = 0; +} + +// it's ever so slightly faster to not have to strlen the key +template +void WriteKey(JsonWriter& w, T& k) +{ + w.Key(k, sizeof(T) - 1); +} + +struct WriteObject { + JsonWriter& writer; + WriteObject(JsonWriter& w) + : writer(w) + { + writer.StartObject(); + } + template + WriteObject(JsonWriter& w, T& name) + : writer(w) + { + WriteKey(writer, name); + writer.StartObject(); + } + ~WriteObject() { writer.EndObject(); } +}; + +struct WriteArray { + JsonWriter& writer; + template + WriteArray(JsonWriter& w, T& name) + : writer(w) + { + WriteKey(writer, name); + writer.StartArray(); + } + ~WriteArray() { writer.EndArray(); } +}; + +template +void WriteOptionalString(JsonWriter& w, T& k, const char* value) +{ + if (value && value[0]) { + w.Key(k, sizeof(T) - 1); + w.String(value); + } +} + +static void JsonWriteNonce(JsonWriter& writer, int nonce) +{ + WriteKey(writer, "nonce"); + char nonceBuffer[32]; + NumberToString(nonceBuffer, nonce); + writer.String(nonceBuffer); +} + +size_t JsonWriteRichPresenceObj(char* dest, + size_t maxLen, + int nonce, + int pid, + const DiscordRichPresence* presence) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject top(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("SET_ACTIVITY"); + + { + WriteObject args(writer, "args"); + + WriteKey(writer, "pid"); + writer.Int(pid); + + if (presence != nullptr) { + WriteObject activity(writer, "activity"); + + WriteOptionalString(writer, "state", presence->state); + WriteOptionalString(writer, "details", presence->details); + + if (presence->startTimestamp || presence->endTimestamp) { + WriteObject timestamps(writer, "timestamps"); + + if (presence->startTimestamp) { + WriteKey(writer, "start"); + writer.Int64(presence->startTimestamp); + } + + if (presence->endTimestamp) { + WriteKey(writer, "end"); + writer.Int64(presence->endTimestamp); + } + } + + if ((presence->largeImageKey && presence->largeImageKey[0]) || + (presence->largeImageText && presence->largeImageText[0]) || + (presence->smallImageKey && presence->smallImageKey[0]) || + (presence->smallImageText && presence->smallImageText[0])) { + WriteObject assets(writer, "assets"); + WriteOptionalString(writer, "large_image", presence->largeImageKey); + WriteOptionalString(writer, "large_text", presence->largeImageText); + WriteOptionalString(writer, "small_image", presence->smallImageKey); + WriteOptionalString(writer, "small_text", presence->smallImageText); + } + + if ((presence->partyId && presence->partyId[0]) || presence->partySize || + presence->partyMax || presence->partyPrivacy) { + WriteObject party(writer, "party"); + WriteOptionalString(writer, "id", presence->partyId); + if (presence->partySize && presence->partyMax) { + WriteArray size(writer, "size"); + writer.Int(presence->partySize); + writer.Int(presence->partyMax); + } + + if (presence->partyPrivacy) { + WriteKey(writer, "privacy"); + writer.Int(presence->partyPrivacy); + } + } + + if ((presence->matchSecret && presence->matchSecret[0]) || + (presence->joinSecret && presence->joinSecret[0]) || + (presence->spectateSecret && presence->spectateSecret[0])) { + WriteObject secrets(writer, "secrets"); + WriteOptionalString(writer, "match", presence->matchSecret); + WriteOptionalString(writer, "join", presence->joinSecret); + WriteOptionalString(writer, "spectate", presence->spectateSecret); + } + + writer.Key("instance"); + writer.Bool(presence->instance != 0); + } + } + } + + return writer.Size(); +} + +size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + WriteKey(writer, "v"); + writer.Int(version); + WriteKey(writer, "client_id"); + writer.String(applicationId); + } + + return writer.Size(); +} + +size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("SUBSCRIBE"); + + WriteKey(writer, "evt"); + writer.String(evtName); + } + + return writer.Size(); +} + +size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + JsonWriteNonce(writer, nonce); + + WriteKey(writer, "cmd"); + writer.String("UNSUBSCRIBE"); + + WriteKey(writer, "evt"); + writer.String(evtName); + } + + return writer.Size(); +} + +size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce) +{ + JsonWriter writer(dest, maxLen); + + { + WriteObject obj(writer); + + WriteKey(writer, "cmd"); + if (reply == DISCORD_REPLY_YES) { + writer.String("SEND_ACTIVITY_JOIN_INVITE"); + } + else { + writer.String("CLOSE_ACTIVITY_JOIN_REQUEST"); + } + + WriteKey(writer, "args"); + { + WriteObject args(writer); + + WriteKey(writer, "user_id"); + writer.String(userId); + } + + JsonWriteNonce(writer, nonce); + } + + return writer.Size(); +} diff --git a/deps/discord-rpc/src/serialization.h b/deps/discord-rpc/src/serialization.h new file mode 100644 index 0000000..9c462dc --- /dev/null +++ b/deps/discord-rpc/src/serialization.h @@ -0,0 +1,215 @@ +#pragma once + +#include + +#ifndef __MINGW32__ +#pragma warning(push) + +#pragma warning(disable : 4061) // enum is not explicitly handled by a case label +#pragma warning(disable : 4365) // signed/unsigned mismatch +#pragma warning(disable : 4464) // relative include path contains +#pragma warning(disable : 4668) // is not defined as a preprocessor macro +#pragma warning(disable : 6313) // Incorrect operator +#endif // __MINGW32__ + +#include "rapidjson/document.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" + +#ifndef __MINGW32__ +#pragma warning(pop) +#endif // __MINGW32__ + +// if only there was a standard library function for this +template +inline size_t StringCopy(char (&dest)[Len], const char* src) +{ + if (!src || !Len) { + return 0; + } + size_t copied; + char* out = dest; + for (copied = 1; *src && copied < Len; ++copied) { + *out++ = *src++; + } + *out = 0; + return copied - 1; +} + +size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId); + +// Commands +struct DiscordRichPresence; +size_t JsonWriteRichPresenceObj(char* dest, + size_t maxLen, + int nonce, + int pid, + const DiscordRichPresence* presence); +size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName); + +size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName); + +size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce); + +// I want to use as few allocations as I can get away with, and to do that with RapidJson, you need +// to supply some of your own allocators for stuff rather than use the defaults + +class LinearAllocator { +public: + char* buffer_; + char* end_; + LinearAllocator() + { + assert(0); // needed for some default case in rapidjson, should not use + } + LinearAllocator(char* buffer, size_t size) + : buffer_(buffer) + , end_(buffer + size) + { + } + static const bool kNeedFree = false; + void* Malloc(size_t size) + { + char* res = buffer_; + buffer_ += size; + if (buffer_ > end_) { + buffer_ = res; + return nullptr; + } + return res; + } + void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) + { + if (newSize == 0) { + return nullptr; + } + // allocate how much you need in the first place + assert(!originalPtr && !originalSize); + // unused parameter warning + (void)(originalPtr); + (void)(originalSize); + return Malloc(newSize); + } + static void Free(void* ptr) + { + /* shrug */ + (void)ptr; + } +}; + +template +class FixedLinearAllocator : public LinearAllocator { +public: + char fixedBuffer_[Size]; + FixedLinearAllocator() + : LinearAllocator(fixedBuffer_, Size) + { + } + static const bool kNeedFree = false; +}; + +// wonder why this isn't a thing already, maybe I missed it +class DirectStringBuffer { +public: + using Ch = char; + char* buffer_; + char* end_; + char* current_; + + DirectStringBuffer(char* buffer, size_t maxLen) + : buffer_(buffer) + , end_(buffer + maxLen) + , current_(buffer) + { + } + + void Put(char c) + { + if (current_ < end_) { + *current_++ = c; + } + } + void Flush() {} + size_t GetSize() const { return (size_t)(current_ - buffer_); } +}; + +using MallocAllocator = rapidjson::CrtAllocator; +using PoolAllocator = rapidjson::MemoryPoolAllocator; +using UTF8 = rapidjson::UTF8; +// Writer appears to need about 16 bytes per nested object level (with 64bit size_t) +using StackAllocator = FixedLinearAllocator<2048>; +constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t)); +using JsonWriterBase = + rapidjson::Writer; +class JsonWriter : public JsonWriterBase { +public: + DirectStringBuffer stringBuffer_; + StackAllocator stackAlloc_; + + JsonWriter(char* dest, size_t maxLen) + : JsonWriterBase(stringBuffer_, &stackAlloc_, WriterNestingLevels) + , stringBuffer_(dest, maxLen) + , stackAlloc_() + { + } + + size_t Size() const { return stringBuffer_.GetSize(); } +}; + +using JsonDocumentBase = rapidjson::GenericDocument; +class JsonDocument : public JsonDocumentBase { +public: + static const int kDefaultChunkCapacity = 32 * 1024; + // json parser will use this buffer first, then allocate more if needed; I seriously doubt we + // send any messages that would use all of this, though. + char parseBuffer_[32 * 1024]; + MallocAllocator mallocAllocator_; + PoolAllocator poolAllocator_; + StackAllocator stackAllocator_; + JsonDocument() + : JsonDocumentBase(rapidjson::kObjectType, + &poolAllocator_, + sizeof(stackAllocator_.fixedBuffer_), + &stackAllocator_) + , poolAllocator_(parseBuffer_, sizeof(parseBuffer_), kDefaultChunkCapacity, &mallocAllocator_) + , stackAllocator_() + { + } +}; + +using JsonValue = rapidjson::GenericValue; + +inline JsonValue* GetObjMember(JsonValue* obj, const char* name) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsObject()) { + return &member->value; + } + } + return nullptr; +} + +inline int GetIntMember(JsonValue* obj, const char* name, int notFoundDefault = 0) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsInt()) { + return member->value.GetInt(); + } + } + return notFoundDefault; +} + +inline const char* GetStrMember(JsonValue* obj, + const char* name, + const char* notFoundDefault = nullptr) +{ + if (obj) { + auto member = obj->FindMember(name); + if (member != obj->MemberEnd() && member->value.IsString()) { + return member->value.GetString(); + } + } + return notFoundDefault; +} diff --git a/deps/libtomcrypt b/deps/libtomcrypt deleted file mode 160000 index fae62af..0000000 --- a/deps/libtomcrypt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fae62af0ab16f469c2512ec04575dd60ca018657 diff --git a/deps/libtomcrypt/.ci/build.sh b/deps/libtomcrypt/.ci/build.sh new file mode 100644 index 0000000..c36df46 --- /dev/null +++ b/deps/libtomcrypt/.ci/build.sh @@ -0,0 +1,75 @@ +#!/bin/bash +echo "$1 ($2, $3)..." + +make clean 1>/dev/null 2>/dev/null + +echo -n "building..." + +if [ -f /proc/cpuinfo ] +then + MAKE_JOBS=$(( ($(cat /proc/cpuinfo | grep -E '^processor[[:space:]]*:' | tail -n -1 | cut -d':' -f2) + 1) * 2 + 1 )) +else + MAKE_JOBS=8 +fi + +CFLAGS="$2 $CFLAGS $4" EXTRALIBS="$5" make -j$MAKE_JOBS -f $3 all_test 1>gcc_1.txt 2>gcc_2.txt +mret=$? +cnt=$(wc -l < gcc_2.txt) +# ignore 1 line since ar prints to stderr instead of stdout and ar is called for +# $(LIBNAME) +if [[ $mret -ne 0 ]] || [[ $cnt -gt 1 ]]; then + echo "build $1 failed! printing gcc_2.txt now for convenience" + cat gcc_2.txt + exit 1 +fi + +# remove the standard arguments from the make options +opts=${3//makefile.shared/} +opts=${opts//makefile/} +opts=${opts//V=1/} +opts=${opts//COVERAGE=1/} +opts=$(echo $opts | tr -d '[:space:]') + +# if there's something else than the standard arguments we check if we're currently +# building a Travis PR and if it's like that, we skip those tests +if [ ! -z "$opts" ]; then + if [ ! -z "$TRAVIS_PULL_REQUEST" ] && [ "$TRAVIS_PULL_REQUEST" != "false" ]; then + echo "PR Tests skipped" | tee testok.txt + exit 0 + fi +fi + +echo -n "testing..." + +if [ -a test ] && [ -f test ] && [ -x test ]; then + ((./test >test_std.txt 2>test_err.txt && ./tv_gen > tv.txt) && echo "$1 test passed." && echo "y" > testok.txt) || (echo "$1 test failed, look at test_err.txt or tv.txt" && exit 1) + if find *_tv.txt -type f 1>/dev/null 2>/dev/null ; then + for f in *_tv.txt; do + # check for lines starting with '<' ($f might be a subset of notes/$f) + difftroubles=$(diff -i -w -B $f notes/$f | grep '^<') + if [ -n "$difftroubles" ]; then + echo "FAILURE: $f" + diff -i -w -B $f notes/$f + echo "tv_gen $f failed" && rm -f testok.txt && exit 1 + else + true + fi + done + fi +fi + + +if [ -a testok.txt ] && [ -f testok.txt ]; then + if [ "$LTC_COVERAGE" != "" ]; then + bash .ci/coverage_more.sh > test_coverage_more.txt || exit 1 + lcov_opts="--capture --no-external --directory src -q" + lcov_out=$(echo coverage_$1_$2_$3 | tr ' -=+' '_')".info" + lcov $lcov_opts --output-file $lcov_out + fi + exit 0 +fi +exit 1 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/check_source.sh b/deps/libtomcrypt/.ci/check_source.sh new file mode 100644 index 0000000..3a2731f --- /dev/null +++ b/deps/libtomcrypt/.ci/check_source.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# output version +bash .ci/printinfo.sh + +make clean > /dev/null + +echo "checking..." +./helper.pl --check-all || exit 1 + +exit 0 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/clang-tidy.sh b/deps/libtomcrypt/.ci/clang-tidy.sh new file mode 100644 index 0000000..c58a676 --- /dev/null +++ b/deps/libtomcrypt/.ci/clang-tidy.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# output version +bash .ci/printinfo.sh + +# tested with clang-tidy from llvm-6.0.0 +# not tested with Travis-CI + +#### we use the main test sets: +# readability +# misc +# clang-analyzer +# google +# performance +# modernize +# cert +# bugprone +# portability + +#### the following checks are skipped +# google-readability-function-size +# readability-function-size +# google-readability-casting +# readability-braces-around-statements +# misc-macro-parentheses +# clang-analyzer-valist.Uninitialized + +echo "Run clang-tidy version" + +clang-tidy --version || exit 1 + +echo "Run clang-tidy..." + +clang-tidy src/*/*.c src/*/*/*.c src/*/*/*/*.c src/*/*/*/*/*.c -warnings-as-errors='*' --quiet --checks=-*,\ +readability-*,-readability-function-size,-readability-braces-around-statements,\ +misc-*,-misc-macro-parentheses,\ +clang-analyzer-*,-clang-analyzer-valist.Uninitialized,\ +google-*,-google-readability-function-size,-google-readability-casting,\ +performance-*,\ +modernize-*,\ +cert-*,\ +bugprone-*,\ +portability-* -- -DUSE_LTM -DLTM_DESC -Isrc/headers -I../libtommath || { echo "clang-tidy FAILED!"; exit 1; } + +echo "clang-tidy ok" + +exit 0 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/coverage.sh b/deps/libtomcrypt/.ci/coverage.sh new file mode 100644 index 0000000..e8808f9 --- /dev/null +++ b/deps/libtomcrypt/.ci/coverage.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -e + +if [ "$TRAVIS_CI" == "private" ]; then + exit 0 +fi + +if [ "$#" != "5" ]; then + echo "Usage is: ${0} \"coverage\" \"\" \"\" \"\" " + echo "CC=gcc ${0} \"coverage\" \" \" \"makefile\" \"-DUSE_LTM -DLTM_DESC -I../libtommath\" ../libtommath/libtommath.a" + exit -1 +fi + +if [ -z "$(echo $CC | grep "gcc")" ]; then + echo "no gcc detected, early exit success" + exit 0 +fi + +if [ "$(echo $3 | grep -v 'makefile[.]')" == "" ]; then + echo "only run $0 for the regular makefile, early exit success" + exit 0 +fi + +# output version +bash .ci/printinfo.sh + +bash .ci/build.sh " $1" " $2" " $3 COVERAGE=1" "$4" "$5" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +bash .ci/coverage_more.sh "$5" > test_coverage_more.txt || { rm -f testok.txt && exit 1 ; } + +make lcov-single +# if this isn't run on CI create coverage locally +if [ "$CI" == "" ]; then + make lcov-html +else + coveralls-lcov coverage.info --service-job-id="$GITHUB_RUN_ID" --service-name="github" --repo-token="$REPO_TOKEN" --branch="$GITHUB_REF_NAME" --service-pull-request="$PR_NUMBER" +fi + +exit 0 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/coverage_more.sh b/deps/libtomcrypt/.ci/coverage_more.sh new file mode 100644 index 0000000..37c73f7 --- /dev/null +++ b/deps/libtomcrypt/.ci/coverage_more.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +if [ "$#" = "1" -a "$(echo $1 | grep 'gmp')" != "" ]; then + ./test t gmp +fi + +./sizes +./constants + +for i in $(for j in $(echo $(./hashsum -h | awk '/Algorithms/,EOF' | tail -n +2)); do echo $j; done | sort); do echo -n "$i: " && ./hashsum -a $i tests/test.key ; done > hashsum_tv.txt +difftroubles=$(diff -i -w -B hashsum_tv.txt notes/hashsum_tv.txt | grep '^<') || true +if [ -n "$difftroubles" ]; then + echo "FAILURE: hashsum_tv.tx" + diff -i -w -B hashsum_tv.txt notes/hashsum_tv.txt + echo "hashsum failed" + exit 1 +else + echo "hashsum okay" +fi + + +exit 0 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/meta_builds.sh b/deps/libtomcrypt/.ci/meta_builds.sh new file mode 100644 index 0000000..2ba99a9 --- /dev/null +++ b/deps/libtomcrypt/.ci/meta_builds.sh @@ -0,0 +1,108 @@ +#!/bin/bash +# +# This builds different stuff depending on the compiler: +# gcc - valgrind, coverage +# clang - asan, ubsan, scan-build +# both - the two testbuild's NOTEST and NOFILE + +set -e + +if [ "$#" = "5" -a "$(echo $3 | grep -v 'makefile[.]')" = "" ]; then + echo "only run $0 for the regular makefile, early exit success" + exit 0 +fi + +if [ -f /proc/cpuinfo ] +then + MAKE_JOBS=$(( ($(cat /proc/cpuinfo | grep -E '^processor[[:space:]]*:' | tail -n -1 | cut -d':' -f2) + 1) * 2 + 1 )) +else + MAKE_JOBS=8 +fi + +function run_gcc() { + bash .ci/check_source.sh "CHECK_SOURCES" "$2" "$3" "$4" "$5" + + make clean &>/dev/null + + echo + echo "Build for ASAN..." + + make -j$MAKE_JOBS CFLAGS="-fsanitize=address -fno-omit-frame-pointer -static-libasan $2 $CFLAGS $4" EXTRALIBS="-lasan $5" test LTC_DEBUG=1 V=1 1>gcc_1.txt 2>gcc_2.txt + + echo + echo "Run ASAN tests with LTM..." + + ASAN_OPTIONS=verbosity=1 ./test t ltm 1>test_std.txt 2> test_err.txt || exit 1 + + if echo $* | grep -q GMP ; then + echo + echo "Run ASAN tests with GMP..." + + ASAN_OPTIONS=verbosity=1 ./test t gmp 1>test_std.txt 2> test_err.txt || exit 1 + fi + + make clean &>/dev/null + + echo + echo "Create code coverage" + + bash .ci/coverage.sh "COVERAGE" "$2" "$3" "$4" "$5" +} + +function run_clang() { + # output version + bash .ci/printinfo.sh + + scan_build=$(which scan-build) || true + [ -z "$scan_build" ] && scan_build=$(find /usr/bin/ -name 'scan-build-[0-9]*' | sort -nr | head -n1) || true + [ -z "$scan_build" ] && { echo "couldn't find clang scan-build"; exit 1; } || echo "run $scan_build" + $scan_build --status-bugs make -j$MAKE_JOBS all CFLAGS="$2 $CFLAGS $4" EXTRALIBS="$5" + + make clean &>/dev/null + + echo + echo "Build for UBSAN..." + + make -j$MAKE_JOBS LDFLAGS="-fsanitize=undefined" CFLAGS="$2 $CFLAGS $4" EXTRALIBS="$5" all LTC_DEBUG=1 V=1 1>gcc_1.txt 2>gcc_2.txt + + echo "Run UBSAN tests with LTM..." + UBSAN_OPTIONS=verbosity=1 ./test t ltm 1>test_std.txt 2> test_err.txt || exit 1 + + if echo $* | grep -q GMP ; then + echo + echo "Run UBSAN tests with GMP..." + + UBSAN_OPTIONS=verbosity=1 ./test t gmp 1>test_std.txt 2> test_err.txt || exit 1 + fi +} + +make clean &>/dev/null + +EXTRALIBS="$5" + +echo $* | grep -q GMP && EXTRALIBS="$EXTRALIBS -lgmp" + +if [ -z "$(echo $CC | grep "clang")" ]; then + run_gcc "$1" "$2" "$3" "$4" "$EXTRALIBS" +else + run_clang "$1" "$2" "$3" "$4" "$EXTRALIBS" +fi + +make clean &>/dev/null + +bash .ci/testbuild.sh "NOTEST" "-DLTC_NO_TEST" "$3" "$4" "$EXTRALIBS" + +make clean &>/dev/null + +bash .ci/testbuild.sh "NOFILE" "-DLTC_NO_FILE" "$3" "$4" "$EXTRALIBS" + +make clean &>/dev/null + +echo +echo "Build full debug..." + +make -j$MAKE_JOBS CFLAGS="$2 $CFLAGS $4" EXTRALIBS="$EXTRALIBS" all_test LTC_DEBUG=2 V=1 1>gcc_1.txt 2>gcc_2.txt + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/printinfo.sh b/deps/libtomcrypt/.ci/printinfo.sh new file mode 100644 index 0000000..21e1fec --- /dev/null +++ b/deps/libtomcrypt/.ci/printinfo.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +version=$(git describe --tags --always --dirty 2>/dev/null) +if [ ! -e ".git" ] || [ -z $version ] +then + version=$(grep "^VERSION=" makefile_include.mk | sed "s/.*=//") +fi +echo "Testing version:" $version +#grep "VERSION=" makefile | perl -e "@a = split('=', <>); print @a[1];"` + +# get uname +echo "uname="`uname -a` + +# get gcc name +if [ -z ${CC} ] +then + CC="gcc" +fi +echo "${CC}="`${CC} -dumpversion` +echo + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/run.sh b/deps/libtomcrypt/.ci/run.sh new file mode 100644 index 0000000..3109171 --- /dev/null +++ b/deps/libtomcrypt/.ci/run.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# output version +bash .ci/printinfo.sh + +bash .ci/build.sh " $1" "$2" "$3" "$4" "$5" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +rm -f testok.txt +bash .ci/build.sh " $1" "$2" "$3 LTC_DEBUG=1" "$4" "$5" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +rm -f testok.txt +bash .ci/build.sh " $1" "$2 -O2" "$3 IGNORE_SPEED=1" "$4" "$5" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +rm -f testok.txt +bash .ci/build.sh " $1" "$2" "$3 IGNORE_SPEED=1 LTC_SMALL=1" "$4" "$5" +if [ -a testok.txt ] && [ -f testok.txt ]; then + echo +else + echo + echo "Test failed" + exit 1 +fi + +exit 0 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/testbuild.sh b/deps/libtomcrypt/.ci/testbuild.sh new file mode 100644 index 0000000..0159774 --- /dev/null +++ b/deps/libtomcrypt/.ci/testbuild.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# output version +bash .ci/printinfo.sh + +if [ -f /proc/cpuinfo ] +then + MAKE_JOBS=$(( ($(cat /proc/cpuinfo | grep -E '^processor[[:space:]]*:' | tail -n -1 | cut -d':' -f2) + 1) * 2 + 1 )) +else + MAKE_JOBS=8 +fi + +echo "$1 (Build Only, $2, $3)..." +make clean 1>/dev/null 2>/dev/null +echo -n "building..." +touch testok.txt +make -j$MAKE_JOBS -f $3 test tv_gen CFLAGS="$2 $CFLAGS $4" EXTRALIBS="$5" 1>gcc_1.txt 2>gcc_2.txt || (echo "build $1 failed see gcc_2.txt for more information" && cat gcc_2.txt && rm -f testok.txt && exit 1) +if find testok.txt -type f 1>/dev/null 2>/dev/null ; then + echo "successful" + exit 0 +fi +exit 1 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.ci/valgrind.sh b/deps/libtomcrypt/.ci/valgrind.sh new file mode 100644 index 0000000..87ad884 --- /dev/null +++ b/deps/libtomcrypt/.ci/valgrind.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -e + +if [ "$#" = "5" -a "$(echo $3 | grep -v 'makefile[.]')" = "" ]; then + echo "only run $0 for the regular makefile, early exit success" + exit 0 +fi + +if [ -f /proc/cpuinfo ] +then + MAKE_JOBS=$(( ($(cat /proc/cpuinfo | grep -E '^processor[[:space:]]*:' | tail -n -1 | cut -d':' -f2) + 1) * 2 + 1 )) +else + MAKE_JOBS=8 +fi + +# output version +bash .ci/printinfo.sh + +make clean &>/dev/null + +echo "Build for valgrind..." + +make -j$MAKE_JOBS CFLAGS="$2 $CFLAGS $4" EXTRALIBS="$5" test LTC_DEBUG=1 1>gcc_1.txt 2>gcc_2.txt + +echo "Run tests with valgrind..." + +for i in `seq 1 10` ; do sleep 300 && echo "Valgrind tests in Progress..."; done & +alive_pid=$! + +valgrind --error-exitcode=666 --leak-check=full --show-leak-kinds=all --errors-for-leak-kinds=all ./test >test_std.txt 2> >(tee -a test_err.txt >&2) || { kill $alive_pid; echo "Valgrind failed"; exit 1; } + +kill $alive_pid + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/.clang-format b/deps/libtomcrypt/.clang-format new file mode 100644 index 0000000..686711f --- /dev/null +++ b/deps/libtomcrypt/.clang-format @@ -0,0 +1,42 @@ +--- +AccessModifierOffset: -2 +ConstructorInitializerIndentWidth: 4 +AlignEscapedNewlinesLeft: false +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakTemplateDeclarations: false +AlwaysBreakBeforeMultilineStrings: false +BreakBeforeBinaryOperators: false +BreakConstructorInitializersBeforeComma: false +BinPackParameters: true +ColumnLimit: 120 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +DerivePointerBinding: true +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCSpaceBeforeProtocolList: false +PenaltyBreakComment: 60 +PenaltyBreakString: 1000 +PenaltyBreakFirstLessLess: 120 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerBindsToType: false +SpacesBeforeTrailingComments: 1 +Cpp11BracedListStyle: false +Standard: Cpp03 +IndentWidth: 3 +TabWidth: 8 +UseTab: Never +BreakBeforeBraces: Linux +IndentFunctionDeclarationAfterType: false +SpacesInParentheses: false +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpaceAfterControlStatementKeyword: true +SpaceBeforeAssignmentOperators: true +... + diff --git a/deps/libtomcrypt/.gitattributes b/deps/libtomcrypt/.gitattributes new file mode 100644 index 0000000..5a182b9 --- /dev/null +++ b/deps/libtomcrypt/.gitattributes @@ -0,0 +1,7 @@ +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore + +/** export-subst + +/tests/test.key -text diff --git a/deps/libtomcrypt/.github/ISSUE_TEMPLATE.md b/deps/libtomcrypt/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..e7c66af --- /dev/null +++ b/deps/libtomcrypt/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,30 @@ + + +### Prerequisites + +* [ ] Checked the developer manual +* [ ] Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=repo%3Alibtom%2Flibtomcrypt +* [ ] Checked that your issue isn't due to the fact that you're using asymmetric cryptography and you forgot linking in and/or setting an MPI provider (usually this causes either random crashes or runtime errors like `LTC_ARGCHK 'ltc_mp.name != NULL' failure ...`). c.f. Ch. "Math Descriptors" of the developer manual. +* [ ] Checked that your issue isn't related to TomsFastMath's limitation that PK operations can by default only be done with max. 2048bit keys + +### Description + +[Description of the issue] + +### Steps to Reproduce + + +### Version + +You can get this information from the define `SCRYPT` in `src/include/tomcrypt.h` or your local git repository by running `git describe --always --tags --dirty`. +Also, please include the compiler, the compiler version, the architecture and (if applicable) the MPI provider, the OS and what version of the OS you're experiencing the issue. + +### Additional Information + +Any additional information, configuration or data that might be necessary to reproduce the issue. diff --git a/deps/libtomcrypt/.github/PULL_REQUEST_TEMPLATE.md b/deps/libtomcrypt/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..8cd4614 --- /dev/null +++ b/deps/libtomcrypt/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ + + +### Checklist + + +* [ ] documentation is added or updated +* [ ] tests are added or updated diff --git a/deps/libtomcrypt/.github/workflows/main.yml b/deps/libtomcrypt/.github/workflows/main.yml new file mode 100644 index 0000000..fbd68ee --- /dev/null +++ b/deps/libtomcrypt/.github/workflows/main.yml @@ -0,0 +1,92 @@ +name: CI + +on: + push: + branches: + - master + - develop + - /^release\/.*$/ + pull_request: + branches: + - master + - develop + - /^release\/.*$/ + +jobs: + Docs: + runs-on: ubuntu-20.04 + container: texlive/texlive:latest-medium + steps: + - uses: actions/checkout@v2 + - name: generate PDF + run: | + make docs + cp doc/crypt.pdf crypt-${{ github.run_id }}.pdf + - name: upload PDF + uses: actions/upload-artifact@v3 + with: + name: crypt-${{ github.run_id }}.pdf + path: crypt-${{ github.run_id }}.pdf + Build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + cc: [ gcc, clang ] + os: [ ubuntu-18.04 ] + config: + - { BUILDNAME: 'META_BUILDS', BUILDOPTIONS: '-DGMP_DESC', BUILDSCRIPT: '.ci/meta_builds.sh' } + - { BUILDNAME: 'VALGRIND', BUILDOPTIONS: '', BUILDSCRIPT: '.ci/valgrind.sh' } + - { BUILDNAME: 'STOCK', BUILDOPTIONS: '', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK-MPI', BUILDOPTIONS: '-ULTM_DESC -UTFM_DESC -UUSE_LTM -UUSE_TFM', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'EASY', BUILDOPTIONS: '-DLTC_EASY', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'SMALL', BUILDOPTIONS: '-DLTC_SMALL_CODE', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NOTABLES', BUILDOPTIONS: '-DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'SMALL+NOTABLES', BUILDOPTIONS: '-DLTC_SMALL_CODE -DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_FAST', BUILDOPTIONS: '-DLTC_NO_FAST', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_FAST+NOTABLES', BUILDOPTIONS: '-DLTC_NO_FAST -DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_ASM', BUILDOPTIONS: '-DLTC_NO_ASM', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_TIMING_RESISTANCE', BUILDOPTIONS: '-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'PTHREAD', BUILDOPTIONS: '-DLTC_PTHREAD', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=1', BUILDOPTIONS: '-DARGTYPE=1', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=2', BUILDOPTIONS: '-DARGTYPE=2', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=3', BUILDOPTIONS: '-DARGTYPE=3', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'STOCK+ARGTYPE=4', BUILDOPTIONS: '-DARGTYPE=4', BUILDSCRIPT: '.ci/run.sh' } + steps: + - uses: actions/checkout@v2 + - name: install dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y libtommath-dev libgmp-dev libtfm-dev valgrind libtool-bin clang-tools lcov + sudo gem install coveralls-lcov + curl -s https://packagecloud.io/install/repositories/libtom/packages/script.deb.sh | sudo bash + sudo apt-get install libtfm1=0.13-5ubuntu1 + - name: run tests + env: + CC: "${{ matrix.cc }}" + PR_NUMBER: ${{ github.event.number }} + REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + bash "${{ matrix.config.BUILDSCRIPT }}" "${{ matrix.config.BUILDNAME }}" "-DUSE_LTM -DLTM_DESC" "makefile V=1" "${{ matrix.config.BUILDOPTIONS }}" "-ltommath" + bash "${{ matrix.config.BUILDSCRIPT }}" "${{ matrix.config.BUILDNAME }}" "-DUSE_TFM -DTFM_DESC" "makefile.shared V=1" "${{ matrix.config.BUILDOPTIONS }}" "-ltfm" + - name: regular logs + if: ${{ !failure() }} + run: | + cat gcc_1.txt + cat gcc_2.txt + - name: error logs + if: ${{ failure() }} + run: | + cat test_std.txt + cat test_err.txt + cat tv.txt + - name: pack build directory + if: ${{ failure() }} + run: | + tar cJf build-${{ github.run_id }}.tar.xz --exclude ./build-${{ github.run_id }}.tar.xz . + - name: upload Artifact + if: ${{ failure() }} + uses: actions/upload-artifact@v3 + with: + name: build-${{ github.run_id }}.tar.xz + path: build-${{ github.run_id }}.tar.xz + retention-days: 1 diff --git a/deps/libtomcrypt/.gitignore b/deps/libtomcrypt/.gitignore new file mode 100644 index 0000000..be757fa --- /dev/null +++ b/deps/libtomcrypt/.gitignore @@ -0,0 +1,111 @@ +# suppress compiler/linker output +*.[oa] +*.obj +*.l[oa] +[Dd]ebug/ +[Rr]elease/ +/MSVC_* +.libs/ + +# release files +/libtomcrypt-* +/crypt-* + +# suppress output of build process +gcc_[12].txt +testok.txt +test_*.txt +tv.txt +*_tv.txt +doxygen/ +doc/crypt.pdf +doc/refman.pdf + +# *nix/windows test executables +aesgcm +aesgcm.exe +constants +constants.exe +ltcrypt +ltcrypt.exe +hashsum +hashsum.exe +multi +multi.exe +openssl-enc +openssl-enc.exe +sizes +sizes.exe +small +small.exe +test +test.exe +tv_gen +tv_gen.exe +timing +timing.exe + +# Visual Studio special files +# ignore user specific settings +*.user +*.suo +# ignore non-compressed browse file (holds information for ClassView, IntelliSense and WizardBar) +*.ncb +# ignore VS intermediate and program database files +*.idb +*.pdb + +# Eclipse special files +.project +.cproject +.settings/ + +# KDevelop special files +*.kdev4 + + +# macOS special files +.DS_Store + +# other special files +showlibs # symlink to .libs + +# oops ;) but we don't want them to appear in the repository... +*.stackdump +*.core + +# misc +*.rej +*.patch +*.diff +*.orig +*.out +*.ll +*.gcda +*.gcno +*.gcov +libtomcrypt.pc + +# output from doc generation +doxygen/ +*.dvi +*.log +*.aux +*.toc +*.idx +*.ilg +*.ind +*.out +*.lof +*.bak + +coverage/ +coverage*.info + +# coverity intermediate directory etc. +cov-int/ +.coverity_* +libtomcrypt.lzma + +# cmake build directories +build*/ diff --git a/deps/libtomcrypt/CMakeLists.txt b/deps/libtomcrypt/CMakeLists.txt new file mode 100644 index 0000000..ba48f9f --- /dev/null +++ b/deps/libtomcrypt/CMakeLists.txt @@ -0,0 +1,304 @@ +# SPDX-License-Identifier: Unlicense +# +# LibTomCrypt, modular cryptographic library -- Tom St Denis +# + +cmake_minimum_required(VERSION 3.10) + +project(libtomcrypt + VERSION 1.18.2 + DESCRIPTION "A modular cryptographic library." + HOMEPAGE_URL "https://www.libtom.net/LibTomCrypt" + LANGUAGES C) + +# package release version +# bump if re-releasing the same VERSION + patches +# set to 1 if releasing a new VERSION +set(PACKAGE_RELEASE_VERSION 1) + +#----------------------------------------------------------------------------- +# Include CMake modules +#----------------------------------------------------------------------------- +include(GNUInstallDirs) +include(CheckIPOSupported) +include(CMakePackageConfigHelpers) +# for potential builds against gnump +include(FindPkgConfig) +# default is "No tests" +option(BUILD_TESTING "" OFF) +include(CTest) +include(sources.cmake) + +#----------------------------------------------------------------------------- +# Options +#----------------------------------------------------------------------------- +option(WITH_LTM "Build with support for libtommath" TRUE) +option(WITH_GMP "Build with support for GNU Multi Precision Arithmetic Library" FALSE) +set(MPI_PROVIDER "LTM" CACHE STRING "Build tests and demos against 'LTM', 'TFM' or 'GMP', default is LTM") +option(BUILD_SHARED_LIBS "Build shared library and only the shared library if \"ON\", default is static" OFF) + +#----------------------------------------------------------------------------- +# Compose CFLAGS +#----------------------------------------------------------------------------- + +# Some information ported from makefile_include.mk + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE "Release") +endif() + +# We differentiate between MSVC, WATCOM and GCC-compatible compilers +if(MSVC) + set(LTC_C_FLAGS -W3) +elseif(WATCOM) + set(LTC_C_FLAGS -fo=.obj -oaxt -3r -w3) +else() + set(LTC_C_FLAGS -Wall -Wsign-compare -Wextra -Wshadow + -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align + -Wstrict-prototypes -Wpointer-arith -Wsystem-headers) + set(CMAKE_C_FLAGS_DEBUG "-g3") + set(CMAKE_C_FLAGS_RELEASE "-O3 -funroll-loops -fomit-frame-pointer") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g3 -O2") + set(CMAKE_C_FLAGS_MINSIZEREL "-Os") +endif() + +# What compiler do we have and what are their...uhm... peculiarities +if(CMAKE_C_COMPILER_ID MATCHES "(C|c?)lang") + list(APPEND LTC_C_FLAGS -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header) + # Clang requires at least '-O1' for dead code eliminiation + set(CMAKE_C_FLAGS_DEBUG "-O1 ${CMAKE_C_FLAGS_DEBUG}") +endif() +if(CMAKE_C_COMPILER MATCHES "mingw") + list(APPEND LTC_C_FLAGS -Wno-shadow -Wno-expansion-to-defined -Wno-declaration-after-statement -Wno-bad-function-cast) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + list(APPEND LTC_C_FLAGS -Wno-nullability-completeness) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") + list(APPEND LTC_C_FLAGS -no-undefined) +endif() + +# If the user set the environment variables at generate-time, append them +# in order to allow overriding our defaults. +# ${LTC_CFLAGS} means the user passed it via sth like: +# $ cmake -DLTC_CFLAGS="foo" +list(APPEND LTC_C_FLAGS ${LTC_CFLAGS}) +list(APPEND LTC_LD_FLAGS ${LTC_LDFLAGS}) + +#----------------------------------------------------------------------------- +# Library targets +#----------------------------------------------------------------------------- +add_library(${PROJECT_NAME} + ${SOURCES} + ${PUBLIC_HEADERS} + ${PRIVATE_HEADERS} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ +) + +target_compile_options(${PROJECT_NAME} BEFORE PRIVATE + ${LTC_C_FLAGS} +) +target_link_options(${PROJECT_NAME} BEFORE PRIVATE + ${LTC_LD_FLAGS} +) + +set_target_properties(${PROJECT_NAME} PROPERTIES + OUTPUT_NAME tomcrypt + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + PUBLIC_HEADER "${PUBLIC_HEADERS}" +) + +option(COMPILE_LTO "Build with LTO enabled") +if(COMPILE_LTO) + check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) + if(COMPILER_SUPPORTS_LTO) + set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(SEND_ERROR "This compiler does not support LTO. Reconfigure ${PROJECT_NAME} with -DCOMPILE_LTO=OFF.") + endif() +endif() + +#----------------------------------------------------------------------------- +# MPI provider +#----------------------------------------------------------------------------- +# libtommath +if(WITH_LTM) + find_package(libtommath 1.2.0 REQUIRED) + + target_compile_definitions(${PROJECT_NAME} PUBLIC LTM_DESC) + if(MPI_PROVIDER MATCHES "LTM") + target_compile_definitions(${PROJECT_NAME} PUBLIC USE_LTM) + endif() + target_link_libraries(${PROJECT_NAME} PUBLIC libtommath) +endif() +# GNU MP +if(WITH_GMP) + pkg_check_modules(GMP REQUIRED gmp>=6.1.2) + + target_compile_definitions(${PROJECT_NAME} PUBLIC GMP_DESC) + if(MPI_PROVIDER MATCHES "GMP") + target_compile_definitions(${PROJECT_NAME} PUBLIC USE_GMP) + endif() + target_link_libraries(${PROJECT_NAME} PUBLIC ${GMP_LIBRARIES}) +endif() + + +#----------------------------------------------------------------------------- +# demos&test targets +#----------------------------------------------------------------------------- + +add_subdirectory(demos) +if(BUILD_TESTING) + enable_testing() + add_subdirectory(tests) +endif() + +#--------------------------------------------------------------------------------------- +# Install/export targets and files +#--------------------------------------------------------------------------------------- +set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +set(PROJECT_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake") +set(PROJECT_CONFIG_FILE "${PROJECT_NAME}-config.cmake") +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") + +# install targets +install(TARGETS ${PROJECT_NAME} + EXPORT ${TARGETS_EXPORT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} +) + +# Install libtomcrypt.pc for pkg-config if we build a shared library +if(BUILD_SHARED_LIBS) + # Let the user override the default directory of the pkg-config file (usually this shouldn't be required to be changed) + set(CMAKE_INSTALL_PKGCONFIGDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Folder where to install .pc files") + + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR} + ) +endif() + +# generate package version file +write_basic_package_version_file( + ${PROJECT_VERSION_FILE} + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + +# install version file +install(FILES ${PROJECT_VERSION_FILE} + DESTINATION ${CONFIG_INSTALL_DIR} +) + +# build directory package config +export(EXPORT ${TARGETS_EXPORT_NAME} + FILE ${PROJECT_CONFIG_FILE} +) + +# installed package config +install(EXPORT ${TARGETS_EXPORT_NAME} + DESTINATION ${CONFIG_INSTALL_DIR} + FILE ${PROJECT_CONFIG_FILE} +) + +# add to CMake registry +export(PACKAGE ${PROJECT_NAME}) + +#--------------------------------------------------------------------------------------- +# Create release packages +#--------------------------------------------------------------------------------------- + +# determine distribution and architecture +find_program(LSB_RELEASE lsb_release) +find_program(SYSCTL sysctl) +find_program(UNAME uname) + +if(UNAME) + execute_process(COMMAND uname -m OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +elseif(SYSCTL) + execute_process(COMMAND sysctl -b hw.machine_arch OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +else() + string(TOLOWER ${CMAKE_SYSTEM_NAME} MACHINE_ARCH) +endif() + +if(LSB_RELEASE) + execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE LINUX_DISTRO OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND lsb_release -sc OUTPUT_VARIABLE LINUX_DISTRO_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE LINUX_DISTRO_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + + string(TOLOWER ${LINUX_DISTRO} LINUX_DISTRO) + if(LINUX_DISTRO_CODENAME STREQUAL "n/a") + set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_VERSION}/) + else() + set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_CODENAME}/) + endif() +else() + set(DISTRO_PACK_PATH ${CMAKE_SYSTEM_NAME}/) +endif() + +# default CPack generators +set(CPACK_GENERATOR TGZ STGZ) + +# extra CPack generators +if(LINUX_DISTRO STREQUAL "debian" OR LINUX_DISTRO STREQUAL "ubuntu" OR LINUX_DISTRO STREQUAL "linuxmint") + list(APPEND CPACK_GENERATOR DEB) +elseif(LINUX_DISTRO STREQUAL "fedora" OR LINUX_DISTRO STREQUAL "opensuse" OR LINUX_DISTRO STREQUAL "centos") + list(APPEND CPACK_GENERATOR RPM) +elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + list(APPEND CPACK_GENERATOR FREEBSD) +endif() + +# general CPack config +set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages/${DISTRO_PACK_PATH}) +message(STATUS "CPack: packages will be generated under ${CPACK_PACKAGE_DIRECTORY}") +if(BUILD_SHARED_LIBS) + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}") +else() + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}-devel") +endif() +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LibTomCrypt") +set(CPACK_PACKAGE_VENDOR "libtom projects") +set(CPACK_PACKAGE_CONTACT "libtom@googlegroups.com") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(PACKAGE_NAME_TRAILER ${CPACK_PACKAGE_VERSION}-${PACKAGE_RELEASE_VERSION}_${MACHINE_ARCH}) +set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${PACKAGE_NAME_TRAILER}) +set(CPACK_STRIP_FILES ON) + +# deb specific CPack config +set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION}) +if(BUILD_SHARED_LIBS) + set(CPACK_DEBIAN_PACKAGE_SECTION "libs") +else() + set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}-dev") + set(CPACK_DEBIAN_PACKAGE_SECTION "devel") +endif() + +# rpm specific CPack config +set(CPACK_RPM_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION}) +set(CPACK_RPM_PACKAGE_ARCHITECTURE ${MACHINE_ARCH}) +set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}") +set(CPACK_RPM_PACKAGE_LICENSE "The Unlicense") + +# FreeBSD specific CPack config +set(CPACK_FREEBSD_PACKAGE_MAINTAINER "gahr@FreeBSD.org") +set(CPACK_FREEBSD_PACKAGE_ORIGIN "security/libtomcrypt") +set(CPACK_FREEBSD_PACKAGE_CATEGORIES "security") + +include(CPack) diff --git a/deps/libtomcrypt/LICENSE b/deps/libtomcrypt/LICENSE new file mode 100644 index 0000000..b23b3c8 --- /dev/null +++ b/deps/libtomcrypt/LICENSE @@ -0,0 +1,26 @@ + The LibTom license + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/deps/libtomcrypt/README.md b/deps/libtomcrypt/README.md new file mode 100644 index 0000000..3088bdc --- /dev/null +++ b/deps/libtomcrypt/README.md @@ -0,0 +1,200 @@ +# libtomcrypt + +Previously the git repository contained `doc/crypt.pdf` for detailed documentation. +This was changed and the file is now only available from the tarball of the appropriate version +or from the page https://github.com/libtom/libtomcrypt/releases . + +## Project Status + +### Travis CI + +master: [![Build Status](https://github.com/libtom/libtomcrypt/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/libtom/libtomcrypt/actions/workflows/main.yml?query=branch%3Amaster+++) [![Coverage Status](https://coveralls.io/repos/libtom/libtomcrypt/badge.png?branch=master)](https://coveralls.io/r/libtom/libtomcrypt) + +develop: [![Build Status](https://github.com/libtom/libtomcrypt/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/libtom/libtomcrypt/actions/workflows/main.yml?query=branch%3Adevelop+++) [![Coverage Status](https://coveralls.io/repos/libtom/libtomcrypt/badge.png?branch=develop)](https://coveralls.io/r/libtom/libtomcrypt) + +### AppVeyor + +master: [![Build status](https://ci.appveyor.com/api/projects/status/xyl2nbdsyp1tj9ye/branch/master?svg=true)](https://ci.appveyor.com/project/libtom/libtomcrypt/branch/master) + +develop: [![Build status](https://ci.appveyor.com/api/projects/status/xyl2nbdsyp1tj9ye/branch/develop?svg=true)](https://ci.appveyor.com/project/libtom/libtomcrypt/branch/develop) + +### Coverity + +[![Coverity Scan Build Status](https://scan.coverity.com/projects/487/badge.svg)](https://scan.coverity.com/projects/487) + +### ABI Laboratory + +API/ABI changes: [check here](https://abi-laboratory.pro/tracker/timeline/libtomcrypt/) + +## Submitting patches + +Please branch off from develop if you want to submit a patch. + +Patch integration will be faster if tests and documentation are included. + +Please update the makefiles in a separate commit. To update them simply run the `updatemakes.sh` script. + +If you have something bigger to submit, feel free to contact us beforehand. +Then we can give you write access to this repo, so you can open your PR based on this repo +and we can easier follow the rebase-before-merge approach we're using (or even do the rebase ourself). + +### Reviews + +We're using Pull Request reviews to make sure that the code is in line with the existing code base. + +Please have a look [here](https://help.github.com/articles/approving-a-pull-request-with-required-reviews/) to get an idea of the approach. + +## Branches + +Please be aware, that all branches besides _master_ and _develop_ __can__ and __will be__ force-pushed, rebased and/or removed! + +If you want to rely on such an _unstable_ branch, create your own fork of this repository to make sure nothing breaks for you. + +## Configuration options + +By default the library builds its entire feature set (besides `katja`) in a (depending on your needs more or less) optimal way. + +There are numerous configuration options available if you want to trim down the functionality of the library. + +Please have a look at `src/headers/tomcrypt_custom.h` for all available configuration options. + +The following list is a small part of the available, but the most often required, configuration switches. + +| Flag | Behavior | +| ---- | -------- | +| `LTC_NO_TEST` | Remove all algorithm self-tests from the library | +| `LTC_NO_FILE` | Remove all API functions requiring a pre-defined `FILE` data-type (mostly useful for embedded targets) | +| `GMP_DESC` | enable [gmp](https://gmplib.org/) as MPI provider *\*1* | +| `LTM_DESC` | enable [libtommath](http://www.libtom.net/) as MPI provider *\*1* | +| `TFM_DESC` | enable [tomsfastmath](http://www.libtom.net/) as MPI provider *\*1* *\*2* | +| `USE_GMP` | use `gmp` as MPI provider when building the binaries *\*3* | +| `USE_LTM` | use `libtommath` as MPI provider when building the binaries *\*3* | +| `USE_TFM` | use `tomsfastmath` as MPI provider when building the binaries *\*3* | + +*\*1* It is possible to build the library against all MPI providers in parallel and choose at startup-time which math library should be used. + +*\*2* Please be aware that `tomsfastmath` has the limitation of a fixed max size of MPI's. + +*\*3* Only one is supported at the time & this is only required when building the binaries, not when building the library itself. + +## Building the library + +There are several `makefile`s provided. Please choose the one that fits best for you. + +| makefile | use-case | +| -------- | -------- | +| `makefile` | builds a static library (GNU Make required) | +| `makefile.shared` | builds a shared (and static) library (GNU Make required) | +| `makefile.unix` | for unusual UNIX platforms, or if you do not have GNU Make | +| `makefile.mingw` | for usage with the mingw compiler on MS Windows | +| `makefile.msvc` | for usage with the MSVC compiler on MS Windows | +| `libtomcrypt_VS2008.sln` | A VisualStudio 2008 project for MS Windows | + +### Make targets + +The `makefile`s provide several targets to build (VS project excluded). +The following list does not claim to be complete resp. to be available across all `makefile` variants. + +| target | application | +| ------ | ----------- | +| *empty target*/none given | c.f. `library` +| `library` | builds only the library | +| `hashsum` | builds the `hashsum` binary, similar to [`shasum`](https://linux.die.net/man/1/shasum), but with support for all hash-algorithms included in the library *\*4* | +| `ltcrypt` | builds the `ltcrypt` binary, implementing something similar to [`crypt`](https://linux.die.net/man/3/crypt) *\*4* | +| `sizes` | builds the `sizes` binary, printing all internal data sizes on invocation *\*4* | +| `constants` | builds the `constants` binary, printing all internal constants on invocation *\*4* | +| `openssl-enc` | builds the `openssl-enc` binary, which is more or less compatible to [`openssl enc`](https://linux.die.net/man/1/enc) *\*4* *\*5* | +| `test` | builds the `test` binary, which runs all algorithm self-tests + some extended tests *\*4* | +| `timing` | builds the `timing` binary, which can be used to measure timings for algorithms and modes *\*4* | +| `bins` | builds `hashsum` *\*4* | +| `all_test` | builds `test`, `hashsum`, `ltcrypt`, `small`, `tv_gen`, `sizes` & `constants` *\*4* | +| `docs` | builds the developer documentation `doc/crypt.pdf` | +| `install` | installs the `library` and header files *\*7* *\*8* | +| `install_bins` | installs the binaries created by the `bins` target *\*7* *\*8* | +| `install_docs` | installs the documentation created by the `docs` target *\*7* *\*8* | +| `install_test` | installs the test-app created by the `test` target *\*7* *\*8* | +| `install_all` | installs everything (i.e. `library`, `bins`, `docs` and `test`) *\*8* | +| `uninstall` | uninstalls the `library` and header files | + +*\*4* also builds `library` + +*\*5* broken build in some configurations, therefore not built by default + +*\*7* also builds the necessary artifact(s) before installing it + +*\*8* also have a look at the 'Installation' section of this file + +### Examples + +You want to build the library as static library + + make + +You want to build the library as shared library + + make -f makefile.shared + +You have `libtommath` installed on your system and want to build a static library and the `test` binary to run the self-tests. + + make CFLAGS="-DUSE_LTM -DLTM_DESC" EXTRALIBS="-ltommath" test + +You have `tomsfastmath` installed on your system and want to build a shared library and all binaries + + make -f makefile.shared CFLAGS="-DUSE_TFM -DTFM_DESC" EXTRALIBS="-ltfm" all demos + +You have `gmp`, `libtommath` and `tomsfastmath` installed on your system and want to build a static library and the `timing` binary to measure timings against `gmp`. + + make CFLAGS="-DUSE_GMP -DGMP_DESC -DLTM_DESC -DTFM_DESC" EXTRALIBS="-lgmp" timing + +If you have `libtommath` in a non-standard location: + + make CFLAGS="-DUSE_LTM -DLTM_DESC -I/opt/devel/ltm" EXTRALIBS="/opt/devel/ltm/libtommath.a" all + +## Installation + +There exist several _install_ make-targets which are described in the table above. + +These targets support the standard ways (c.f. [[GNU]], [[FreeBSD]]) +to modify the installation path via the following set of variables: + + DESTDIR + PREFIX + LIBPATH + INCPATH + DATAPATH + BINPATH + +The entire set of the variables is only supported in `makefile`, `makefile.shared` and `makefile.unix`. + +In case you have to use one of the other makefiles, check in the file which variables are supported. + +### Examples + +You want to install the static library to the default paths + + make install + +You want to install the shared library to a special path and use it from this path + + make -f makefile.shared PREFIX=/opt/special/path + +Have a look at the developer documentation, [[GNU]] or [[FreeBSD]] to get a detailed explanation of all the variables. + +## CMake support + +The project provides support for the CMake build system. + +``` +git clone https://github.com/libtom/libtomcrypt.git +mkdir -p libtomcrypt/build +cd libtomcrypt/build +cmake .. +make -j$(nproc) +``` + +More details around building with CMake can be found in the developer documentation. + + +[GNU]: https://www.gnu.org/prep/standards/html_node/DESTDIR.html + +[FreeBSD]: https://www.freebsd.org/doc/en/books/porters-handbook/porting-prefix.html diff --git a/deps/libtomcrypt/appveyor.yml b/deps/libtomcrypt/appveyor.yml new file mode 100644 index 0000000..474d222 --- /dev/null +++ b/deps/libtomcrypt/appveyor.yml @@ -0,0 +1,29 @@ +version: 1.18.2-develop+{build} +branches: + only: + - master + - develop + - /^release/ + - /^appveyor/ + - /^build-ci/ +image: +- Visual Studio 2022 +- Visual Studio 2019 +- Visual Studio 2017 +- Visual Studio 2015 +build_script: +- cmd: >- + if "Visual Studio 2022"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2019"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2017"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 + cd.. + git clone https://github.com/libtom/libtommath.git --branch=master + cd libtommath + nmake -f makefile.msvc + cd.. + cd libtomcrypt + nmake -f makefile.msvc all +test_script: +- cmd: test.exe diff --git a/deps/libtomcrypt/changes b/deps/libtomcrypt/changes new file mode 100644 index 0000000..dc56d08 --- /dev/null +++ b/deps/libtomcrypt/changes @@ -0,0 +1,1648 @@ +July 1st, 2018 +v1.18.2 + -- Fix Side Channel Based ECDSA Key Extraction (CVE-2018-12437) (PR #408) + -- Fix potential stack overflow when DER flexi-decoding (CVE-2018-0739) (PR #373) + -- Fix two-key 3DES (PR #390) + -- Fix accelerated CTR mode (PR #359) + -- Fix Fortuna PRNG (PR #363) + -- Fix compilation on platforms where cc doesn't point to gcc (PR #382) + -- Fix using the wrong environment variable LT instead of LIBTOOL (PR #392) + -- Fix build on platforms where the compiler provides __WCHAR_MAX__ but wchar.h is not available (PR #390) + -- Fix & re-factor crypt_list_all_sizes() and crypt_list_all_constants() (PR #414) + -- Minor fixes (PR's #350 #351 #375 #377 #378 #379) + +January 22nd, 2018 +v1.18.1 + -- Fix wrong SHA3 blocksizes, thanks to Claus Fischer for reporting this via Mail (PR #329) + -- Fix NULL-pointer dereference in `ccm_memory()` with LTC_CLEAN_STACK enabled (PR #327) + -- Fix `ccm_process()` being unable to process input buffers longer than 256 bytes (PR #326) + -- Fix the `register_all_{ciphers,hashes,prngs}()` return values (PR #316) + -- Fix some typos, warnings and duplicate prototypes in code & doc (PR's #310 #320 #321 #335) + -- Fix possible undefined behavior with LTC_PTHREAD (PR #337) + -- Fix some DER bugs (PR #339) + -- Fix CTR-mode when accelerator is used (OP-TEE/optee_os #2086) + -- Fix installation procedure (Issue #340) + +October 10th, 2017 +v1.18.0 + -- Bugfix multi2 + -- Bugfix Noekeon + -- Bugfix XTEA + -- Bugfix rng_get_bytes() on windows where we could read from c:\dev\random + -- Fixed the Bleichbacher Signature attack in PKCS#1 v1.5 EMSA, thanks to Alex Dent + -- Fixed a potential cache-based timing attack in CCM, thanks to Sebastian Verschoor + -- Fix GCM counter reuse and potential timing attacks in EAX, OCB and OCBv3, + thanks to Raphaël Jamet + -- Implement hardened RSA operations when CRT is used + -- Enabled timing resistant calculations of ECC and RSA operations per default + -- Applied some patches from the OLPC project regarding PKCS#1 and preventing + the hash algorithms from overflowing + -- Larry Bugbee contributed the necessary stuff to more easily call libtomcrypt + from a dynamic language like Python, as shown in his pyTomCrypt + -- Nikos Mavrogiannopoulos contributed RSA blinding and export of RSA and DSA keys + in OpenSSL/GnuTLS compatible format + -- Patrick Pelletier contributed a smart volley of patches + -- Christopher Brown contributed some patches and additions to ASN.1/DER + -- Pascal Brand of STMicroelectronics contributed patches regarding CCM, the + XTS mode and RSA private key operations with keys without CRT parameters + -- RC2 now also works with smaller key-sizes + -- Improved/extended several tests & demos + -- Hardened DSA and RSA by testing (through Karel's perl-CryptX) + against Google's "Wycheproof" and Kudelski Security's "CDF" + -- Fixed all compiler warnings + -- Fixed several build issues on FreeBSD, NetBSD, Linux x32 ABI, HP-UX/IA64, + Mac OS X, Windows (32&64bit, Cygwin, MingW & MSVC) ... + -- Re-worked all makefiles + -- Re-worked most PRNG's + -- The code is now verified by a linter, thanks to Francois Perrad + -- Documentation (crypt.pdf) is now built deterministically, thanks to Michael Stapelberg + -- Add Adler32 and CRC32 checksum algorithms + -- Add Base64-URL de-/encoding and some strict variants + -- Add Blake2b & Blake2s (hash & mac), thanks to Kelvin Sherlock + -- Add Camellia block cipher + -- Add ChaCha (stream cipher), Poly1305 (mac), ChaCha20Poly1305 (encauth) + -- Add constant-time mem-compare mem_neq() + -- Add DER GeneralizedTime de-/encoding + -- Add DSA and ECC key generation FIPS-186-4 compliance + -- Add HKDF, thanks to RyanC (especially for also providing documentation :-) ) + -- Add OCBv3 + -- Add PKCS#1 v1.5 mode of SSL3.0 + -- Add PKCS#1 testvectors from RSA + -- Add PKCS#8 & X.509 import for RSA keys + -- Add stream cipher API + -- Add SHA3 & SHAKE + -- Add SHA512/256 and SHA512/224 + -- Add Triple-DES 2-key mode, thanks to Paul Howarth + -- Brought back Diffie-Hellman + +May 12th, 2007 +v1.17 -- Cryptography Research Inc. contributed another small volley of patches, one to fix __WCHAR_DEFINED__ for BSD platforms, + another to silence MSVC warnings. + -- Added LTC_XCBC_PURE to XCBC mode which lets you use it in three-key mode. + -- [CRI] Added libtomcrypt.dsp for Visual C++ users. + -- [CRI] Added more functions for manipulating the ECC fixed point cache (including saving and loading) + -- [CRI] Modified ecc_make_key() to always produce keys smaller than base point order, for standards-compliance + -- Elliptic Semiconductor contributed XTS chaining mode to the cipher suite (subsequently optimized it) + -- Fixed xcbc_init() keylen when using single key mode. + -- Bruce Fortune pointed out a typo in the hmac_process() description in the manual. Fixed. + -- Added variable width counter support to CTR mode + -- Fixed CMAC (aka OMAC) when using 64-bit block ciphers and LTC_FAST ... my bad. + -- Fixed bug in ecc_is_valid() that would basically always return true + -- renamed a lot of macros to add the LTC_ prefix [e.g. RIJNDAEL => LTC_RIJNDAEL] + +December 16th, 2006 +v1.16 -- Brian Gladman pointed out that a recent change to GCM broke how the IV was handled. Currently the code complies against his test vectors + so the code should be considered frozen now. + -- Trevor from Cryptography Research Inc. submitted patches to convert the ECC code to be generic allowing curve parameters to be submitted + at runtime. + -- Fixed various doxygen comments + -- Added UTF8 support to the ASN1 code + -- Fixed STOREXXH macros for x86 platforms (Fix found at Elliptic Inc.) + -- Added makefile.unix which is BSD compatible, you have to manually tweak it since well I don't use it normally + -- removed a few lingering memcpy's + -- Fixed memory free errors in ecc_sign_hash() that can arise if the mp_init_multi() fails + -- Fixed incorrect return value in pkcs_1_pss_decode() which would correctly set res to 0 (indicating an incorrect signature) but + would return CRYPT_OK to the caller + -- ltc_ecc_mulmod() could leak memory if mp_init(&mu) failed, fixed. Would you believe that ltc_ecc_mulmod_timing() had the same + bug? Also fixed. :-) + -- Added Shamir's trick to the ECC side (defined as LTC_ECC_SHAMIR, enabled by default), gets ~1.34x to ~1.40x faster ECC verifications + -- Added Brian's vector #46 to the GCM code. It catches the ctr counter error from v1.15. Originally I was going to add all of his vectors, + but they're not as easy to parse and I got a lot of other things to do. Regression! + -- Various other small fixes to the ECC code to clean up error handling (I think most of that was from the move in 1.06 to the plugins) + All of the errors were in cleaning up from heap failures. So they were not likely to be triggered in normal usage + Made similar fixes to the RSA and DSA code (my bad) + -- Cryptography Research Inc. contributed a bunch of fixes to silence warnings (with MSVC) w.r.t. assigned data to unsigned char types. + -- Martin Marko suggested some fixes to make the RNG build with WinCE. + -- Updates to the manual for print (some fixes thanks to Martin Marko) + + +November 17th, 2006 +v1.15 -- Andreas Lange found that if sha256_init DID fail in fortuna it wouldn't clean up the state correctly. Thanks. + Fortunately sha256_init cannot fail (as of v1.14) :-) + -- Andreas Lange contributed RMD-256 and RMD-320 code. + -- Removed mutex locks from fortuna_import as they create a deadlock and aren't required anyways [Avi Zelmanovich] + -- Added LTC_NO_PROTOTYPES to avoid prototyping functions like memset/memcpy. Required for fans of GCC 3.3.x + -- David Eder caught a off by one overrun bug in pmac_done() which can be exploited if your output tag buffer is + smaller than the block size of the cipher, e.g. if you have a 4-byte buffer and you tell pmac_done that you want + a 4-byte TAG it will store 4 bytes but return an outlen of 5. + -- Added signatures to the ECC and RSA benchmarks + -- Added LTC_PROFILE to run the PK tests only once in the timing demo (so you can capture events properly) + -- Andreas contributed PKCS #1 v1.5 code that merged cleanly with the existing PKCS code. w00t. + (update: I had to fix it to include the digestInfo and what not. Bad Andreas, bad! hehehe) + -- Fixed a signed variable error in gcm_process() (hard to trigger bug fortunately) + -- Removed all memcmp/memset/memcpy from the source (replaced with X macros) + -- Renamed macros HMAC/OMAC/PMAC to have a LTC_ prefix. If you pass these on the command line please update your makefiles + -- Added XCBC-MAC support [RFC 3566] + -- fixed LOAD32H and LOAD64H to stop putting out that darn warning :-) + -- Added the Korean SEED block cipher [RFC 4269] + -- Added LTC_VALGRIND define which makes SOBER-128 and RC4 a pure PRNG (and not a stream cipher). Useful if you use + Valgrind to debug your code (reported by Andreas Lange) + -- Made SOBER-128 more portable by removing the ASCII key in the test function (my bad, sorry). + -- Martin Mocko pointed out that if you have no PRNGs defined the lib won't build. Fixed, also fixed for if you have no + hashes defined. + -- Sped up F8 mode with LTC_FAST + -- Made CTR mode RFC 3686 compliant (increment counter first), to enable, OR the value LTC_CTR_RFC3686 to the "mode" + parameter you pass to ctr_start(), otherwise it will be LTC compliant (e.g. encrypt then increment) + -- Added ctr_test() to test CTR mode against RFC 3686 + -- Added crypt_fsa() ... O_o + -- Fixed LTC_ECC_TIMING_RESISTANT so it once again builds properly (pt add/dbl are through the plugin now) + -- Added ANSI X9.63 (sec 4.3.6) import/export of public keys (cannot export to compressed formats but will import + hybrid compressed) + -- Added SECP curves for 112, 128, and 160 bits (only the 'r1' curves) + -- Added 3GPP-F9 MAC (thanks to Greg Rose for the test vectors) + -- Added the KASUMI block cipher + -- Added F9/XCBC/OMAC callbacks to the cipher plugin + -- Added RSA PKCS #1 v1.5 signature/encrypt tests to rsa_test.c + -- Fix to yarrow_test() to not call yarrow_done() which is invalid in that context (thanks Valgrind) + -- Christophe Devine pointed out that Anubis would fail on various 64-bit UNIX boxes when "x>>24" was used as an index, we needed + to mask it with 0xFF. Thanks. Fixed. + +August 0x1E, 0x07D6 +v1.14 -- Renamed the chaining mode macros from XXX to LTC_XXX_MODE. Should help avoid polluting the macro name space. + -- clean up of SHA-256 + -- Chris Colman pointed out that der_decode_sequence_* allows LTC_ASN1_SETOF to accept SEQUENCEs and vice versa. + Decoder [non-flexi decoder that is] is more strict now and requires a match. + -- Steffen Jaeckel pointed out a typo in the user manual (re: rsa_exptmod). Fixed. This disproves the notion that + nobody reads it. :-) + -- Made GCM a bit more portable w.r.t. handling the CTR IV (e.g. & with 255) + -- Add LTC_VERBOSE if you really want to see what test is doing :-) + -- Added SSE2 support to GCM [use GCM_TABLES_SSE2 to enable], shaves 2 cycles per byte on Opteron processors + Shaved 4 cycles on a Prescott (Intel P4) + Requires you align your gcm_state on a 16 byte boundary, see gcm_memory() for more info + -- Added missing prototype for f8_test_mode() + -- two fixes to CCM for corner cases [L+noncelen > 15] and fixing the CTR pad to encrypt the CBC-MAC tag + -- Franz Glasner pointed out the ARGTYPE=4 is not actually valid. Fixed. + -- Fixed bug in f8_start() if your key < saltkey unspecified behaviour occurs. :-( + -- Documented F8 mode. Yeah, because you read the manual. + -- Minor updates to the technotes. + + +June 17th, 2006 +v1.13 -- Fixed to fortuna_start() to clean up state if an error occurs. Not really useful at this stage (sha256 can't fail) but useful + if I ever make fortuna pluggable + -- Mike Marin submitted a whole bunch of patches for fixing up the libs on traditional UNIX platforms. Go AIX! Thanks! + -- One of bugs found in the multi demo highlights that at least with gcc you need to pass integers with a UL prefix to ensure + they're unsigned long + -- Updated the FP ECC code to use affine points. It's teh fast. + -- Made it so many functions which return CRYPT_BUFFER_OVERFLOW now also indicate the required buffer size, note that not all functions + do this (most do though). + -- Added F8 chaining mode. It's super neato. + +May 29th, 2006 +v1.12 -- Fixed OID encoder/decoder/length to properly handle the first two parts of an OID, matches 2002 X.690 now. + -- [Wesley Shields] Allows both GMP/LTM and TFM to be defined now. + -- [Wesley Shields] GMP pluggin is cleaner now and doesn't use deprecated symbols. Yipee + -- Added count_lsb_bits to get the number of leading LSB zero bits there are. + -- Fixed a bug in the INTEGER encoders for values of -(256**k)/2 + -- Added BOOLEAN type to ASN.1 thingy-ma-do-hicky + -- Testprof doesn't strictly require GMP ... oops [Nils Durner] + -- Added LTC_CALL and LTC_EXPORT macros in tomcrypt_cfg.h to support various calling and linker conventions + (Thanks to John Kirk from Demonware) + -- In what has to be the best thing since sliced bread I bring you MECC_FP which is the fixed point + ECC point multiplier. It's fast, it's sexy and what's more it's hella fast [did I mention it's fast?] + You can tune it somewhat with FP_LUT (default to 8) for look-up width. + Read section 8.2 of the manual for more info. + It is disabled by default, you'll have to build LTC with it defined to get it. + -- Fixed bug in ecc_test.c (from testprof) to include the 521 [not 512] bit curve. :-) + +April 4th, 2006 +v1.11 -- Removed printf's from lrw_test ... whoops + -- lrw_process now checks the return of the cipher ecb encrypt/decrypt calls + -- lrw_start was not using num_rounds ... + -- Adam Miller reported a bug in the flexi decoder with elements past the end of a sequence. Fixed. + -- Bruce Guenter suggested I use --tag=CC for libtool builds where the compiler may think it's C++. (I applied this to LTM and TFM) + -- Optimized the ECC for TFM a bit by removing the useless "if" statements (most TFM functions don't return error codes) + Actually shaved a good chunk of time off and made the code smaller. By default with TFM the stock LTC point add/dbl functions + will be totally omitted (ECC-256 make key times on a Prescott for old vs. new are 11.03M vs. 9.59M cycles) + -- added missing CVS tags to ltc_ecc_mulmod.c + -- corrected typo in tomcrypt_cfg.h about what the file has been called + -- corrected my address in the user manual. A "bit" out of date. + -- added lrw_gen to tv_gen + -- added GMP plugin, only tested on a AMD64 and x86_32 Gentoo Linux box so be aware + -- made testme.sh runs diff case insensitivityly [whatever...] cuz GMP outputs lowercase satan text + -- added LDFLAGS to the makefile to allow cross porting linking options + -- added lrw_test() to the header file ... whoops + -- changed libtomcrypt.org to libtomcrypt.com .... mumble mumble + -- Updates to detect __STRICT_ANSI__ which is defined in --std=c99 modes (note -ansi is not supported as it lacks long long) so you can + build LTC out of the box with c99 (note: it'll be slower as there is no asm in this case) + -- Updated pelican.c and aes_tab.c to undef tables not-required. The tables are static so both AES and Pelican MAC would have copies. Save a few KB in the final binary. + -- Added LTC_NO_FAST to the makefile.icc to compensate for the fact ICC v9 can't handle it (Pelican MAC fails for instance) + +February 11th, 2006 +v1.10 -- Free ecb/cbc/ctr/lrw structures in timing code by calling the "done" function + -- fixed bug in lrw_process() which would always use the slow update ... + -- vastly sped up gcm_gf_mult() when LTC_FAST is defined. This speeds up LRW and GCM state creation, useful for servers with GCM + -- Removed NLS since there are some attacks against it. + -- fixed memory leak in rsa_import reported by John Kuhns + ++ re-released as the rsa fix was incorrect (bad John bad ... hehehe) and I missed some NULLs in the static descriptor entry for ciphers + +January 26th, 2006 +v1.09 -- Added missing doxygen comments to some of the ASN.1 routines + -- Added "easy button" define LTC_EASY and LTC will build with a subset of all the algos. Reduces build times for typical + configurations. Tunable [see tomcrypt_custom.h] + -- Added some error detection to reg_algs() of the testprof.a library to detect when the PRNG is not setup correctly (took me 10 mins to figure out, PITA!) + -- Similar fixes to timing demo (MD5 not defined when EASY is defined) + -- Added the NLS enc+mac stream cipher from QUALCOMM, disabled for this release, waiting on test vectors + -- Finally added an auto-update script for the makefiles. So when I add new files/dirs it can automatically fix up the makefiles [all four of them...] + -- Added LRW to the list of cipher modes supported + -- cleaned up ciphers definitions to remove cbc/cfb/ofb/ctr/etc from the namespace when not used. + +November 24th, 2005 +v1.08 -- Added SET and SET OF support to the ASN.1 side + -- Fixed up X macros, added QSORT to the mix [thanks SET/SETOF] + -- Added XMEMCMP to the list of X macros + -- In der_decode_sequence() the SHORT_INTEGER type was not being handled correctly [oddly enough it worked just enough to make RSA work ... go figure!] + -- Fixed bug in math descriptors where if you hadn't defined MECC (ECC support) you would get linker errors + -- Added RSA accelerators to the math descriptors to make it possible to not include the stock routines if you supply your own. + -- dsa_decrypt_key() was erroneously dependent on MECC not MDSA ... whoops + -- Moved DSA size limits to tomcrypt_pk.h so they're defined with LTC_NO_PK+MDSA + -- cleaned up tomcrypt_custom.h to make customizable PK easier (and also cleaned up the error traps so they're correctly reported) + +November 18th, 2005 +v1.07 -- Craig Schlenter pointed out the "encrypt" demo doesn't call ctr_start() correctly. That's because as of a few releases ago + I added support to set the mode of the counter at init time + -- Fixed some "testprof" make issues + -- Added RSA keygen to the math descriptors + -- Fixed install_test target ... oops + -- made the "ranlib" program renamable useful for cross-compiling + -- Made the cipher accelerators return error codes. :-) + -- Made CCM accept a pre-scheduled key to speed it up if you use the same key for multiple packets + -- Added "Katja" public key crypto. It's based on the recent N = p^2q work by Katja. I added OAEP padding + to it. Note this code has been disabled not because it doesn't work but because it hasn't been thoroughly + analyzed. It does carry some advantages over RSA (slightly smaller public key, faster decrypt) but also + some annoying "setup" issues like the primes are smaller which makes ECM factoring more plausible. + -- Made makefile accept a NODOCS flag to disable the requirement of tetex to install LTC for you no tetex people... all 3 of ya :-) + -- Cleaned up rsa_export() since "zero" was handled with a SHORT_INTEGER + -- Cleaned up the LIBTEST_S definitions in both GNU makefiles. A few minor touchups as well. + -- Made the cipher ecb encrypt/decrypt return an int as well, changed ALL dependent code to check for this. + -- der_decode_choice() would fail to mark a NULL as "used" when decoding. Fixed + -- ecc_decrypt_key() now uses find_hash_oid() to clean up the code ;-) + -- Added mp_neg() to the math descriptors. + -- Swapped arguments for the pkcs_1_mgf1() function so the hash_idx is the first param (to be more consistent) + -- Made the math descriptors buildable when RSA has been undefined + -- ECC timing demo now capable of detecting which curves have been defined + -- Refactored the ECC code so it's easier to maintain. (note: the form of this code hasn't really changed since I first added ECC ... :-/) + -- Updated the documentation w.r.t. ECC and the accelerators to keep it current + -- Fixed bug in ltc_init_multi() which would fail to free all allocated memory on error. + -- Fixed bug in ecc_decrypt_key() which could possibly lead to overflows (if MAXBLOCKSIZE > ECC_BUF_SIZE and you have a hash that emits MAXBLOCKSIZE bytes) + -- Added encrypt/decrypt to the DSA side (basically DH with DSA parameters) + -- Updated makefiles to remove references to the old DH object files and the ecc_sys.o crap ... clean code ahead! + -- ecc_import() now checks if the point it reads in lies on the curve (to prevent degenerative points from being used) + -- ECC code now ALWAYS uses the accelerator interface. This allows people who use the accelerators to not have the stock + ECC point add/dbl/mul code linked in. Yeah space savings! Rah Rah Rah. + -- Added LTC_MUTEX_* support to Yarrow and Fortuna allowing you to use respective prng_state as a global PRNG state [e.g. thread-safe] if you define one of the LTC_* defines at + build time (e.g. LTC_PTHREAD == pthreads) + -- Added PPC32 support to the rotate macros (tested on an IBM PPC 405) and LTC_FAST macros (it aint fast but it's faster than stock) + -- Added ltc_mp checks in all *_make_key() and *_import() which will help catch newbs who don't register their bignum first :-) + -- the UTCTIME type was missing from der_length_sequence() [oops, oh like you've never done that] + -- the main makefile allows you to rename the make command [e.g. MAKE=gmake gmake install] so you can build LTC on platforms where the default make command sucks [e.g. BSD] + -- Added DER flexi decoder which allows the decoding of arbitrary DER encoded packets without knowing + their structure in advance (thanks to MSVC for finding 3 bugs in it just prior to release! ... don't ask) + +August 1st, 2005 +v1.06 -- Fixed rand_prime() to accept negative inputs as a signal for BBS primes. [Fredrik Olsson] + -- Added fourth ARGCHK type which outputs to stderr and continues. Useful if you trap sigsegv. [Valient Gough] + -- Removed the DH code from the tree + -- Made the ECC code fully public (you can access ecc_mulmod directly now) useful for debuging + -- Added ecc test to tv_gen + -- Added hmac callback to hash descriptors. + -- Fixed two doxy comment errors in the UTCTIME functions + -- rsa_import() can now read OpenSSL format DER public keys as well as the PKCS #1 RSAPublicKey format. + Note that rsa_export() **ONLY** writes PKCS #1 formats + -- Changed MIN/MAX to only define if not already present. -- Kirk J from Demonware ... + -- Ported tv_gen to new framework (and yes, I made ecc vectors BEFORE changing the API and YES they match now :-)) + -- ported testing scripts to support pluggable math. yipee! + -- Wrote a TFM descriptor ... yipee + -- Cleaned up LTC_FAST in CBC mode a bit + -- Merged in patches from Michael Brown for the sparc/sparc64 targets + -- Added find_hash_oid() to search for a hash by its OID + -- Cleaned up a few stray CLEAN_STACKs that should have been LTC_CLEAN_STACK + -- Added timing resistant ECC, enable by defining LTC_ECC_TIMING_RESISTANT then use ECC API as normal + -- Updated the ECC documentation as it was a bit out of date + +June 27th, 2005 +v1.05 + -- Added Technote #6 which covers the current PK compliance. + -- Fixed buffer overflow in OAEP decoder + -- Added CHOICE to the list of ASN.1 types + -- Added UTCTIME to the list of ASN.1 types + -- Added MUTEX locks around descriptor table functions [but not on the functions that are dependent on them] + All functions call *_is_valid() before using a descriptor index which means the respective table must be unlocked before + it can be accessed. However, during the operation [e.g. CCM] if the descriptor has been altered the results will be + undefined. + -- Minor updates to the manual to reflect recent changes + -- Added a catch to for an error that should never come up in rsa_exptmod(). Just being thorough. + +June 15th, 2005 +v1.04 + -- Fixed off by one [bit] error in dsa_make_key() it was too high by one bit [not a security problem just inconsistent] + -- ECC-224 curve was wrong [it was an ok curve just not NIST, so no security flaw just interoperability]. + -- Removed point compression since it slows down ECC ops to save a measly couple bytes. + This makes the ecc export format incompatible with 1.03 [it shouldn't change in the future] + -- Removed ECC-160 from timing and added the other curves + +June 9th, 2005 +v1.03 + -- Users may want to note that on a P4/GCC3.4 platform "-fno-regmove" greatly accelerates the ciphers/hashes. + -------------------------------------------------------------------------------------------------------------- + -- Made it install the testing library in the icc/static makefiles + -- Found bug in ccm_memory.c which would fail to compile when LTC_CLEAN_STACK was enabled + -- Simon Johnson proposed I do a fully automated test suite. Hence "testme.sh" was born + -- Added LTC_NO_TEST which forces test vectors off (regardless of what tomcrypt_custom.h has) + -- Added LTC_NO_TABLES which disables large tables (where possible, regardless of what tomcrypt_custom.h has) + -- New test script found a bug in twofish.c when TABLES was disabled. Yeah testing! + -- Added a LTC_FAST specific test to the testing software. + -- Updated test driver to actually halt on errors and just print them out (useful for say... automated testing...) + -- Added bounds checking to Pelican MAC + -- Added BIT and OCTET STRING to the ASN.1 side of things. + -- Pekka Riikonen pointed out that my ctr_start() function should accept the counter mode. + -- Cleaned up warnings in testprof + -- Removed redundant mu and point mapping in ecc_verify_hash() so it should be a bit faster now + -- Pekka pointed out that the AES key structure was using 32 bytes more than it ought to. + -- Added quick defines to remove entire classes of algorithms. This makes it easier if you want to build with just + one algorithm (say AES or SHA-256). Defines are LTC_NO_CIPHERS, LTC_NO_MODES, LTC_NO_HASHES, LTC_NO_MACS, + LTC_NO_PRNGS, LTC_NO_PK, LTC_NO_PKCS + -- As part of the move for ECC to X9.62 I've changed the signature algorithm to EC DSA. No API changes. + -- Pekka helped me clean up the PKCS #1 v2.1 [OAEP/PSS] code + -- Wrote new DER SEQUENCE coder/decoder + -- RSA, DSA and ECDSA now use the DER SEQUENCE code (saves a lot of code!) + -- DSA output is now a DER SEQUENCE (so not compatible with previous releases). + -- Added Technote #5 which shows how to build LTC on an AMD64 to have a variety of algorithms in only ~80KB of code. + -- Changed temp variable in LOAD/STORE macros to "ulong32" for 32-bit ops. Makes it safer on Big endian platforms + -- Added INSTALL_GROUP and INSTALL_USER which you can specify on the build to override the default USER/GROUP the library + is to be installed as + -- Removed "testprof" from the default build. + -- Added IA5, NULL and Object Identifier to the list of ASN.1 DER supported types + -- The "no_oops" target (part of zipup) now scans for non-cvs files. This helps prevent temp/scratch files from appearing in releases ;-) + -- Added DERs for missing hashes, but just the OID not the PKCS #1 v1.5 additions. + -- Removed PKCS #1 v1.5 from the tree since it's taking up space and you ought to use v2.1 anyways + -- Kevin Kenny pointed out a few stray // comments + -- INTEGER code properly supports negatives and zero padding [Pekka!] + -- Sorted asn1/der/ directory ... less of a mess now ;-) + -- Added PRINTABLE STRING type + -- Removed ECC-160 as it wasn't a standard curve + -- Made ecc_shared_secret() ANSI X9.63 compliant + -- Changed "printf" to "fprintf(stderr, " in the testbench... ;-) + -- Optimized the GCM table creation. On 1KB packets [with key switching] the new GCM is 12.7x faster than before. + -- Changed OID representation for hashes to be just a list of unsigned longs (so you can compare against them nicely after decoding a sequence) + -- ECC code now uses Montgomery reduction ... it's even faster [ECC-256 make key down from 37.4M to 4.6M cycles on an Athlon64] + -- Added SHORT_INTEGER so users can easily store DER encoded INTEGER types without using the bignum math library + -- Fixed OMAC code so that with LTC_FAST it doesn't require that LTC_FAST_TYPE divides 16 [it has to divide the block size instead] + -- ECC key export is now a simple [and documented] SEQUENCE, the "encrypt_key" also uses a new SEQUENCE format. + -- Thanks goes to the following testers + Michael Brown - Solaris 10/uSPARCII + Richard Outerbridge - MacOS + Martin Carpenter - Solaris 8/uSPARCII [Thanks for cleaning up the scripts] + Greg Rose - ... SunOS 5.8/SPARC [... what's with the SPARCS?] + Matt Johnston - MacOS X [Thanks for pointing out GCC 4 problems with -Os] + +April 19th, 2005 +v1.02 + -- Added LTC_TEST support to gcm_test() + -- "pt/ct" can now be NULL in gcm_process() if you are processing zero bytes + -- Optimized GCM by removing the "double copy" handling of the plaintext/aad + -- Richard Outerbridge pointed out that x86_prof won't build on MACOS and that the manual + erroneously refers to "mycrypt" all over the place. Fixed. + +April 17th, 2005 +v1.01 + ** Secure Science Corporation has supported this release cycle by sponsoring the development time taken. Their + continuing support of this project has helped me maintain a steady pace in order to keep LibTomCrypt up to date, + stable and more efficient. + ----------------------------------------------------------------------------------------------------- + -- Updated base64_decode.c so if there are more than 3 '=' signs it would stop parsing + -- Merged in latest mpi that fixed a few bugs here and there + -- Updated OAEP encoder/decoder to catch when the hash output is too large + Cleaned up PSS code too + -- Andy Bontoft fixed a bug in my demos/tests/makefile.msvc ... seems "dsa_test.c" isn't an object + afterall. Thanks. + -- Made invalid ECC key sizes (configuration) not hard fault the program (it returns an error code now) + -- SAFER has been re-enabled after I was pointed to http://www.ciphersbyritter.com/NEWS2/95032301.HTM + [Mark Kotiaho] + -- Added CCM mode to the encauth list (now has EAX, OCB and CCM, c'est un treo magnifique!) + -- Added missing ASN.1 header to the RSA keys ... oops... now the rsa_export/import are FULLY compatible + with other libs like OpenSSL (comment: Test vectors would go a long way RSA...) + -- Manually merged in fix to the prime_random_ex() LTM function that ensures the 2nd MSB is set properly. Now + When you say "I want a 1024/8 byte RSA key" the MSB bit of the modulus is set as expected. Note I generally + don't view this as a "huge issue" but it's just one less nit to worry about. [Bryan Klisch] + -- A new CVS has been setup on my Athlon64 box... if you want developer access send me an email (and at this point the email would have to be awesome). + -- Updated API for ECB and CBC shell code. Now can process N whole blocks in one call (like $DEITY intended) + -- Introduced a new "hardware accel" framework that can be used to speed up cipher ECB, CBC and CTR mode + calls. Later on dependent code (e.g. OMAC, CCM) will be re-written to use the generic cbc/ctr functions. But now + if you [say] call ctr_encrypt() with a cipher descriptor that has hardware CTR it will automatically + be used (e.g. no code rewrites) + -- Now ships with 20% more love. + -- x86_prof now uses ECB shell code (hint: accelerators) and outputs cycles per BLOCK not byte. This will make it a bit + easier to compare hardware vs. software cipher implementations. It also emits timings for CBC and CTR modes + -- [Peter LaDow] fixed a typo w.r.t. XREALLOC macro (spelling counts kids!) + -- Fixed bug with __x86_64__ where ROL64/ROR64 with LTC_NO_ROLC would be the 32-bit versions instead... + -- Shipping with preliminary GCM code (disabled). It's buggy (stack overflow hidden somewhere). If anyone can spot it let me know. + -- Added Pelican MAC [it's an AES based fast MAC] to the list of supported MACs + -- Added LTC_FAST [and you can disable by defining LTC_NO_FAST] so that CBC and CTR mode XOR whole words [e.g. 32 or 64 bits] at a time + instead of one byte. On my AMD64 this reduced the overhead for AES-128-CBC from 4.56 cycles/byte to around 1 cycle/byte. This requires + that you either allow unaligned read/writes [e.g. x86_32/x86_64] or align all your data. It won't go out of it's way to ensure + aligned access. Only enabled for x86_* platforms by default since they allow unaligned read/writes. + -- Added LTC_FAST support to PMAC (drops the cycle/byte by about 9 cycles on my AMD64) [note: I later rewrote this prior to release] + -- Updated "profiled" target to work with the new directory layout + -- Added [demo only] optimized RC5-CTR code to x86_prof demo to show off how to make an accelerator + [This has been removed prior to release... It may re-appear later] + -- Added CCM acelerator callbacks to the list [now supports ECB, CTR, CBC and now CCM]. + -- Added chapter to manual about accelerators (you know you want it) + -- Added "bswap" optimizations to x86 LOAD/STORE with big endian. Can be disabled by defining LTC_NO_BSWAP + -- LTC_NO_ASM is now the official "disable all non-portable stuff" macro. When defined it will make the code endian-neutral, + disable any form of ASM and disable LTC_FAST load/stores. Essentially build the library with this defined if you're having + trouble building the library (old GCCs for instance dislike the ROLc macro) + -- Added tomcrypt_mac.h and moved MAC/encMAC functions from tomcrypt_hash.h into it + -- Added "done" function to ciphers and the five chaining modes [and things like omac/pmac/etc] + -- Changed install group to "wheel" from "root". + -- Replaced // comments with /**/ so it will build on older UNIX-like platforms + -- x86_prof builds and runs with IntelCC fine now + -- Added "stest" build to intel CC to test static linked from within the dir (so you don't have to install to test) + -- Moved testing/benchmark into testprof directory and build it as part of the build. Now you can link against libtomcrypt_prof.a to get + testing info (hint: hardware developers ;-) ) + -- Added CCM to tv_gen + -- Added demos to MSVC makefile + -- Removed -funroll-all-loops from GCC makefile and replaced with -funroll-loops which is a bit more sane (P4 ain't got much cache for the IDATA) + -- Fixed GCM prior to release and re-enabled it. It has not been optimized but it does conform when compiled with optimizations. + -- I've since optimized GCM and CCM. They're close in speed but GCM is more flexible imho (though EAX is more flexible than both) + -- For kicks I optimized the ECC code to use projective points. Gets between 3.21x (Prescott P4) to 4.53x (AMD64) times faster than before at 160-bit keys and the + speedup grows as the keysize grows. Basically removing most practical reasons to "not use the ECC code". Enjoy. + -- Added LTC_FAST support to OMAC/PMAC and doubled it's speed on my amd64 [faster on the P4 too I guess] + -- Added GCM to tv_gen + -- Removed "makefile.cygwin_dll" as it's not really used by anyone and not worth the effort (hell I hardly maintain the MSVC makefiles ...) + -- Updated a few files in the "misc" directory to have correct @file comments for doxygen + -- Removed "profile" target since it was slower anyways (go figure...) + +December 31st, 2004 +v1.00 + -- Added "r,s == 0" check to dsa_verify_hash() + -- Added "multi block" helpers for hash, hmac, pmac and omac routines so you can process multiple non-adjacent + blocks of data with one call (added demos/multi.c to make sure they work) + -- Note these are not documented but they do have doxygen comments inside them + -- Also I don't use them in other functions (like pkcs_5_2()) because I didn't have the time. Job for the new LTC maintainer ;-) + -- Added tweaked Anubis test vectors and made it default (undefined ANUBIS_TWEAK to get original Anubis) + -- Merged in fix for mp_prime_random_ex() to deal with MSB and LSB "bugs" + -- Removed tim_exptmod() completely, updated several RSA functions (notably v15 and the decrypt/verify) so they + don't require a prng now + -- This release brought to you by the fine tunes of Macy Gray. We miss you. + +December 23rd, 2004 +v1.00rc1 + -- Renamed "mycrypt_*" to "tomcrypt_*" to be more specific and professional + Now just include "tomcrypt.h" instead of "mycrypt.h" to get LTC ;-) + -- Cleaned up makefiles to ensure all headers are correctly installed + -- Added "rotate by constant" macros for portable, x86-32 and x86-64 + You can disable this new code with LTC_NO_ROLC which is useful for older GCCs + -- Cleaned up detection of x86-64 so it works for ROL/ROR macros + -- Fixed rsa_import() so that it would detect multi-prime RSA keys and error appropriately + -- Sorted the source files by category and updated the makefiles appropriately + -- Added LTC_DER define so you can trim out DER code if not required + -- Fixed up RSA's decrypt functions changing "res" to "stat" to be more in sync + with the signature variables nomenclature. (no code change just renamed the arguments) + -- Removed all labels starting with __ and replaced with LBL_ to avoid namespace conflicts (Randy Howard) + -- Merged in LTM fix to mp_prime_random_ex() which zap'ed the most significant byte if the bit size + requested was a multiple of eight. + -- Made RSA_TIMING off by default as it's not terribly useful [and likely to be deprecated] + -- Renamed SMALL_CODE, CLEAN_STACK and NO_FILE to have a LTC_ prefix to avoid namespace collisions + with other programs. e.g. SMALL_CODE => LTC_SMALL_CODE + -- Zed Shaw pointed out that on certain systems installing libs as "root" isn't possible as the super-user + is not root. Now the makefiles allow this to be changed easily. + -- Renamed "struct _*_descriptor" to "struct ltc_*_descriptor" to avoid using a leading _ + Also renamed _ARGCHK to LTC_ARGCHK + -- Zed Shaw pointed out that I still defined the prng structs in tomcrypt_prng.h even if they + weren't defined. This made undef'ing FORTUNA break the build. + -- Added LTC_NO_ASM to disable inline asm macros [ROL/ROR/etc] + -- Changed RSA decrypt functions to change the output length variable name from "keylen" to "outlen" to make + it more consistent. + -- Added the 64-bit Khazad block cipher [NESSIE] + -- Added the 128-bit Anubis block cipher [with key support for 128...320 bit keys] [NESSIE] + -- Changes to several MAC functions to rename input arguments to more sensible names + -- Removed FAST_PK support from dh_sys.c + -- Declared deskey() from des.c as static instead of a global + -- Added pretty much all practical GCC warning tests to the GCC [related] makefiles. These additional + warnings can easily be disabled for those with older copies of GCC [or even non GNU cc's] + -- Added doxygen @ tags to the code... phew that was a hell of a lot of [repetitive] work + -- Also added pre-configured Doxygen script. + -- Cleaned up quite a few functions [ciphers, pk, etc] to make the parameters naming style consistent + E.g. ciphers keys are called "skey" consistently now. The input to PK encryption is called "in", etc. + These changes require no code changes on the behalf of developers fortunately + -- Started a SAFER+ optimizer [does encrypt only] which shaves a good 30 or so cycles/byte on my AMD64 + at an expense of huge code. It's in notes/etc/saferp_optimizer.c + -- DSA sign/verify now uses DER encoded output/inputs and no LTC style headers. + -- Matt Johnston found a missing semi-colon in mp_exptmod(). Fix has been merged in. + +October 29th, 2004 +v0.99 -- Merged in the latest version of LTM which includes all of the recent bug fixes + -- Deprecated LTMSSE and removed it (to be replaced with TFM later on) + -- Stefan Arentz pointed out that mp_s_rmap should be extern + -- Kristian Gj?steen pointed out that there are typos in the + "test" makefile and minor issues in Yarrow and Sober [just cosmetics really] + -- Matthew P. Cashdollar pointed out that "export" is a C++ keyword + so changed the PRNG api to use "pexport" and "pimport" + -- Updated "hashsum" demo so it builds ;-) + -- Added automatic support for x86-64 (will configure for 64-bit little endian automagically) + -- Zhi Chen pointed out a bug in rsa_exptmod which would leak memory on error. + -- Made hash functions "init" return an int. slight change to API ;-( + -- Added "CHC" mode which turns any cipher into a hash the other LTC functions can use + -- Added CHC mode stuff to demos such as tv_gen and hashsum + -- Added "makefile.shared" which builds and installs shared/static object copies + of the library. + -- Added DER for bignum support + -- RSA is now fully joy. rsa_export/rsa_import use PKCS #1 encodings and should be + compatible with other crypto libs that use the format. + -- Added support for x86-64 for the ROL/ROR macros + -- Changed the DLL and SO makefiles to optimize for speed, commented SMALL_CODE in + mycrypt_custom.h and added -DSMALL_CODE to the default makefile + -- Updated primality testing code so it does a minimum of 5 tests [of Miller-Rabin] + (AFAIK not a security fix, just warm fuzzies) + -- Minor updates to the OMAC code (additional __ARGCHK and removed printf from omac_test... oops!) + -- Update build and configuration info which was really really really out of date. (Chapter 14) + ++ Minor update, switch RSA to use the PKCS style CRT + +August 6th, 2004 +v0.98 -- Update to hmac_init to free all allocated memory on error + -- Update to PRNG API to fix import/export functions of Fortuna and Yarrow + -- Added test functions to PRNG api, RC4 now conforms ;-) [was a minor issue] + -- Added the SOBER-128 PRNG based off of code donated by Greg Rose. + -- Added Tech Note #4 [notes/tech0004.txt] + -- Changed RC4 back [due to request]. It will now XOR the output so you can use it like + a stream cipher easily. + -- Update Fortuna's export() to emit a hash of each pool. This means that the accumulated + entropy that was spread over all the pools isn't entirely lost when you export/import. + -- Zhi Chen suggested a comment for rsa_encrypt_key() to let users know [easily] that it was + PKCS #1 v2.0 padding. (updated other rsa_* functions) + -- Cleaned up Noekeon to remove unrolling [wasn't required, was messy and actually slower with GCC/ICC] + -- Updated RC4 so that when you feed it >256 bytes of entropy it quietly ignores additional + bytes. Also removed the % from the key setup to speed it up a bit. + -- Added cipher/hash/prng tests to x86_prof to help catch bugs while testing + -- Made the PRNG "done" return int, fixed sprng_done to not require prng* to be non-null + -- Spruced up mycrypt_custom.h to trap more errors and also help prevent LTMSSE from being defined + on non-i386 platforms by accident. + -- Added RSA/ECC/DH speed tests to x86_prof and cleaned it up to build with zero warnings + -- Changed Fortuna to count only entropy [not the 2 byte header] added to pool[0] into the + reseed mechanism. + -- Added "export_size" member to prng_descriptor tables so you can know in advance the size of + the exported state for any given PRNG. + -- Ported over patch on LTM 0.30 [not ready to release LTM 0.31] that fixes bug in mp_mul()/mp_div() + that used to result in negative zeroes when you multiplied zero by a negative integer. + (patch due to "Wolfgang Ehrhardt" ) + -- Fixed rsa_*decrypt_key() and rsa_*verify_hash() to default to invalid "stat" or "res". This way + if any of the higher level functions fail [before you get to the padding] the result will be in + a known state]. Applied to both v2 and v1.5 padding helpers. + -- Added MACs to x86_prof + -- Fixed up "warnings" in x86_prof and tv_gen + -- Added a "profiled" target back [for GCC 3.4 and ICC v8]. Doesn't seem to help but might be worth + tinkering with. + -- Beefed up load/store test in demos/test + + ++ New note, in order to use the optimized LOAD/STORE macros your platform + must support unaligned 32/64 bit load/stores. The x86s support this + but some [ARM for instance] do not. If your platform cannot perform + unaligned operations you must use the endian neutral code which is safe for + any sort of platform. + +July 23rd, 2004 +v0.97b -- Added PKCS #1 v1.5 RSA encrypt/sign helpers (like rsa_sign_hash, etc...) + -- Added missing prng check to rsa_decrypt_key() [not critical as I don't use + descriptors directly in that function] + -- Merged in LTM-SSE, define LTMSSE before you build and you will get SSE2 optimized math ;-) + (roughly 3x faster on a P4 Northwood). By default it will compile as ISO C portable + code (when LTMSSE is undefined). + -- Fixed bug in ltc_tommath.h where I had the kara/toom cutoffs not marked as ``extern'' + Thanks to "Stefan Arentz" + -- Steven Dake and Richard Amacker submitted patches to + fix pkcs_5_2(). It now matches the output of another crypto library. Whoops... hehehe + -- Updated PRNG api. Added Fortuna PRNG to the list of supported PRNGs + -- Fixed up the descriptor tables since globals are automatically zero'ed on startup. + -- Changed RC4 to store it's output. If you want to encrypt with RC4 + you'll have to do the XOR yourself. + -- Fixed buffer overflows/overruns in the HMAC code. + + ++ API change for the PRNGs there now is a done() function per PRNG. You + should call it when you are done with a prng state. So far it's + not absolutely required (won't cause problems) but is a good idea to + start. + + +June 23rd, 2004 +v0.97a ++ Fixed several potentially crippling bugs... [read on] + -- Fixed bug in OAEP decoder that would incorrectly report + buffer overflows. [Zhi Chen] + -- Fixed headers which had various C++ missing [extern "C"]'s + -- Added "extern" to sha384_desc descriptor which I removed by mistake + -- Fixed bugs in ENDIAN_BIG macros using the wrong byte order [Matt Johnston] + -- Updated tiger.c and des.c to not shadow "round" which is intrinsic on + some C compilers. + -- Updated demos/test/rsa_test.c to test the RSA functionality better + ++ This update has been tested with GCC [v3.3.3], ICC [v8] and MSVC [v6+SP6] + all on a x86 P4 [GCC/ICC tested in Gentoo Linux, MSVC in WinXP] + ++ Outcome: The bug Zhi Chen pointed out has been fixed. So have the bugs + that Matt Johnston found. + +June 19th, 2004 +v0.97 -- Removed spurious unused files [arrg!] + -- Patched buffer overflow in tim_exptmod() + -- Fixed buffer overrun bug in pkcs_1_v15_es_decode() + -- Reduced stack usage in PKCS #1 v2.0 padding functions (by several KBs) + -- Removed useless extern's that were an artifact from the project start... ;-) + -- Replaced memcpy/memset with XMEMCPY and XMEMSET for greater flexibility + -- fixed bugs in hmac_done()/hmac_init()/[various others()] where I didn't trap errors + -- Reduced stack usage in OMAC/PMAC/HMAC/EAX/OCB/PKCS#5 by mallocing any significant sized + arrays (e.g. > 100 bytes or so). Only in non-critical functions (e.g. eax_init()) + -- "Zhi Chen" pointed out that rsa_decrypt_key() requires + an incorrect output size (too large). Fixed. + -- Added a "pretty" target to the GCC makefile. Requires PERL. It is NEAT! + -- Minor updates to ch1 of the manual. + -- Cleaned up the indentation and added comments to rsa_make_key(), rsa_exptmod() and + rsa_verify_hash() + -- Updated makefile.icc so the "install" target would work ;-) + -- Removed demos/test.c [deprecated from demos/test/test.c] + -- Changed MAXBLOCKSIZE from 128 to 64 to reflect the true size... + +May 30th, 2004 +v0.96 -- Removed GF and Keyring code + -- Extended OAEP decoder to distinguish better [and use a more uniform API] + -- Changed PSS/OAEP API slightly to be more consistent with other PK functions (order of arguments) + -- rsa_exptmod() now pads with leading zeroes as per I2OSP. + -- added error checking to yarrow code + -- pointed out that tommath.h from this distro will overwrite tommath.h + from libtommath. I changed this to ltc_tommath.h to avoid any such problems. + -- Fixed bug in PSS encoder/decoder that didn't handle the MSB properly + -- refactored AES, now sports an "encrypt only" descriptor which uses half as much code space. + -- modded Yarrow to try and use refactored AES code and added WHIRLPOOL support (d'oh) ;-) + -- updated ECB, OCB and CBC decrypt functions to detect when "encrypt only" descriptor is used. + -- replaced old RSA code with new code that uses PKCS #1 v2.0 padding + -- replaced old test harness with new over-engineer'ed one in /demos/test/ + -- updated cbc/cfb/ofb/ctr code with setiv/getiv functions to change/read the IV without re-keying. + -- Added PKCS #1 v1.5 RSA encryption and signature padding routines + -- Added DER OID's to most hash descriptors (as many as I could find) + -- modded rsa_exptmod() to use timing-resilient tim_exptmod() when doing private key operations + added #define RSA_TIMING which can turn on/off this feature. + -- No more config.pl so please just read mycrypt_custom.h for build-time tweaks + -- Small update to rand_prime() + -- Updated sha1, md5 and sha256 so they are smaller when SMALL_CODE is defined. If you want speed though, + you're going to have to undefine SMALL_CODE ;-) + -- Worked over AES so that it's even smaller now [in both modes]. + +May 12th, 2004 +v0.95 -- Optimized AES and WHIRLPOOL for SMALL_CODE by taking advantage of the fact + the transforms are circulant. AES dropped 5KB and WHIRLPOOL dropped 13KB + using the default build options on the x86. + -- Updated eax so the eax_done() would clear the state [like hmac,pmac,ocb] when + CLEAN_STACK has been defined. + -- added LTC_TEST support to rmd160 + -- updates to mycrypt_pk.h + -- updated rand_prime() to faciliate making RSA composites + -- DSA/RSA now makes composites of the exact size desired. + -- Refactored quite a bit of the code, fewer functions per C file + -- cleaned up the makefiles to organize the objects logically + -- added ICC makefile along with "profiled" targets for both GNU and ICC compilers + -- Marked functions for removal before v1.00 see PLAN for more information + -- GCC 3.4.0 tested and seems to work + -- Added PKCS #5 support + -- Fixed typo in comment header of .C files ;-) + -- Added PKCS #1 OAEP and PSS support. + +Feb 20th, 2004 +v0.94 -- removed unused variables from ocb.c and fixed it to match known test vectors. + -- Added PMAC support, minor changes to OMAC/EAX code [I think....] + -- Teamed up with Brian Gladman. His code verifies against my vectors and my code + verifies against his test vectors. Hazaa for co-operation! + -- Various small changes (added missing ARGCHKs and cleaned up indentation) + -- Optimization to base64, removed unused variable "c" + -- Added base64 gen to demos/tv_gen.c + -- Fix to demos/x86_prof.c to correctly identify the i386 architecture... weird... + -- Fixed up all of the PK code by adding missing error checking, removed "res" variables, + shrunk some stack variables, removed non-required stack variables and added proper + error conversion from MPI to LTC codes. I also spotted a few "off by one" error + checking which could have been used to force the code to read past the end of + the buffer (in theory, haven't checked if it would work) by a few bytes. + -- Added checks to OUTPUT_BIGNUM so the *_export() functions cannot overflow the output and I + also modded it so it stores in the output provided to the function (that is not on + the local stack) which saves memory and time. + -- Made SAFER default to disabled for now (plans are to cleanhouse write an implementation later) + -- Added the 512-bit one-way hash WHIRLPOOL which clocks in at 138 cycles per byte on my + Athlon XP [for comparison, SHA-512 clocks in at 77 cycles per byte]. This code uses the + teams new sbox design (not the original NESSIE one). + + +Jan 25th, 2004 +v0.93 -- [note: deleted v0.93 changes by accident... recreating from memory...] + -- Fix to RC2 to not deference pointer before ARGCHK + -- Fix to NOEKEON to match published test vectors as well as cleaned up the code a bit + -- Optimized Twofish [down to 28 cycles/byte on my box] and Blowfish + -- Fix to OMAC to test cipher block size first [prevents wasting any time] + -- Added more OMAC test vectors + -- Added EAX Encrypt+Authenticate support + -- Fix to DSA to check return of a few LTM functions I forgot [mp_to_unsigned_bin] + -- Added common headers to all C files + -- CTR mode supports big and little [default] endian counters now. + -- fix to find_cipher_any() so that it can handle a fragmented cipher_descriptor table. + -- added find_hash_any() akin to find_cipher_any(). + -- Added EAX code to demos/tv_gen.c Hazaa! + -- Removed SONY defines and files from codebase. + -- Added OCB support [patents be damned] and to demos/tv_gen.c + -- Merge all of the INPUT/OUTPUT BIGNUM macros (less toc) into mycrypt_pk.h + -- Made appropriate changes to the debug string in crypt.c + +Dec 24th, 2003 +v0.92 -- Updated the config.pl script so the options have more details. + -- Updated demos/tv_gen to include RIPEMD hashes + -- Updated Twofish so when TWOFISH_ALL_TABLES is defined a pre-computed RS table + is included [speedup: slight, about 4k cycles on my Athlon]. + -- Re-wrote the twofish large key generation [the four 8x32 key dependent tables]. Now about twice as fast. + With both optimizations [e.g. TWOFISH_ALL_TABLES defined] a 128-bit Twofish key can now be scheduled + in 26,000 cycles on my Athlon XP [as opposed to 49,000 before] when optimized for size. + -- config.pl has been updated so rmd128.o and rmd160.o are objects included in the build [oops] + -- Andrew Mann found a bug in rsa_exptmod() which wouldn't indicate if the wrong type of key was specified + (e.g. not PK_PRIVATE or PK_PUBLIC) + -- Fixed up demos/x86_prof so it sorts the output now :-) + -- The project is now powered by radioactive rubber pants. + -- Fixed dh_encrypt_key() so if you pass it a hash with a smaller output than the input key it + will return CRYPT_INVALID_HASH [to match what ecc_encrypt_key() will do] + -- Merge the store/encrypt key part of ecc_encrypt_key() as per dh_encrypt_key() [can you guess what I'm upto?] + -- Massive updates to the prime generation code. I use the LTM random prime functions [and provide a nice + interface between the LTC PRNG's and the LTM generic prng prototype]. I also use a variable number of tests + depending on the input size. This nicely speeds up most prime generation/testing within the library. + -- Added SHA-224 to the list of hashes. + -- Made HMAC test vectors constant and static [takes ROM space instead of RAM] + -- This release was brought to you by the letter P which stands for Patent Infringement. + -- Added generic HASH_PROCESS macro to mycrypt_hash.h which simplifies the hash "process" functions + I also optimized the compression functions of all but MD2 to not perform input copies when avoidable. + -- Removed the division from the Blowfish setup function [dropped 3k cycles on my Athlon] + -- Added stack cleaning to rijndael, cast5 so now all ciphers have CLEAN_STACK code. + -- Added Skipjack to the list of ciphers [made appropriate changes to demos/test.c, demos/tv_gen.c and + demos/x86_prof.c] + -- Added mechanical testing to cipher test vector routines. Now it encrypts 1000 times, then decrypts and + compares. Any fault (e.g. bug in code, compiler) in the routines is likely to show through. Doesn't + stress test the key gen though... + -- Matt Johnson found a bug in the blowfish.c apparently I was out of my mind and put twofish defines in there + The code now builds with any config. Thanks. + -- Added OMAC1 Message Authentication Code support to the library. + -- Re-prototyped the hash "process" and "done" to prevent buffer overflows [which don't seem easy to exploit]. + Updated HMAC code to use them too. Hazaa! + -- Fixed bug in ECC code which wouldn't do an _ARGCHK on stat in ecc_verify_hash(). + -- Fixed [temp fix] bug in all PK where the OUTPUT_BIGNUM macros would not trap errors on the to_unsigned_bin + conversion [now returns CRYPT_MEM, will fix it up better later] + -- Added DSA to the list of supported PK algorithms. + -- Fixed up various ciphers to &255 the input key bytes where required [e.g. where used to index a table] to prevent + problems on platforms where CHAR_BIT != 8 + -- Merged in LibTomMath v0.28 + -- Updated demos/x86_prof.c to use Yarrow during the key sched testing [was horribly slow on platforms with blockable + /dev/random]. + -- Added OMAC/HMAC tests to demos/tv_gen and I now store the output of this in notes/ + -- Fixed a bug in config.pl that wouldn't have TWOFISH_TABLES defined by default (too many commas on the line) + -- Fixed bug in hmac_done(). Apparently FIPS-198 [HMAC] specifies that the output can be truncated. My code + would not support that (does now just like the new OMAC code). + -- Removed "hashsize" from hmac_state as it wasn't being used. + -- Made demos/test.c stop if OMAC or HMAC tests fail (instead of just printing a failed message and keep going). + -- Updated notes/tech0003.txt to take into account the existence of Skipjack [also I fixed a few typos]. + -- Slight changes to Noekeon, with SMALL_CODE undefined it uses a fully unrolled version. Dropped +10 cycles/byte + on my Athlon (35 cycles per byte or 410.4Mbit/sec at 1795Mhz) + -- Added _ARGCHK() calls to is_prime() for the two input pointers. + +Sept 25th, 2003 +v0.91 -- HMAC fix of 0.90 was incorrect for keys larger than the block size of the hash. + -- Added error CRYPT_FILE_NOTFOUND for the file [hmac/hash] routines. + -- Added RIPEMD hashes to the hashsum demo. + -- Added hashsum demo to MSVC makefile. + -- Added RMD160 to the x86_prof demo [oops] + -- Merged in LibTomMath-0.27 with a patch to mp_shrink() that will be in LibTomMath-0.28 + Fixes another potential memory leak. + +Sept 7th, 2003 +v0.90 -- new ROL/ROR for x86 GCC + -- Jochen Katz submitted a patch to the makefile to prevent "make" from making the .a library + when not required. + == By default the KR code is not enabled [it's only a demo anyways!] + -- changed the "buf" in ecc_make_key from 4KB to 128 bytes [since the largest key is 65 bytes] + -- hmac_done() now requires you pass it the size of the destination buffer to prevent + buffer overflows. (API CHANGE) + -- hmac/hash filebased routines now return CRYPT_NOP if NO_FILE is defined. + -- I've removed the primes from dh.c and replaced them with DR safe primes suitable for the default + configuration of LibTomMath. Check out these comparisons on a 1.3Ghz Athlon XP, optimized for size, + +768-bit, 4 vs. 10 +1024-bit, 8 vs. 18 +1280-bit, 12 vs. 34 +1536-bit, 20 vs. 56 +1792-bit 28 vs. 88 +2048-bit, 40 vs. 124 +2560-bit, 71 vs. 234 +3072-bit, 113 vs. 386 +4096-bit, 283 vs. 916 + + Times are all in milliseconds for key generation. New primes times on the left. This makes the code binary + incompatible with previous releases. However, this addition is long overdue as LibTomMath has supported DR + reductions for quite some time. + -- Added RIPE-MD 128 and 160 to the list of supported hashes [10 in total]. + -- The project has been released as public domain. TDCAL no longer applies. + +July 15th, 2003 +v0.89 -- Fix a bug in bits.c which would prevent it from building with msvc + -- Merged in LibTomMath v0.24 [and I used the alloc/free macros this time!] + -- Removed the LTC version of next_prime() and replaced it with a call to the + mp_prime_next_prime() from LibTomMath + -- reverted bits.c to the 0.86 copy since the new one doesn't build in MSVC + or cygwin. + +Jul 10th, 2003 +v0.88 -- Sped up CAST5 key schedule for MSVC + -- added "ulong32" which allows people on 64-bit platforms to force the 32-bit tables in + ciphers like blowfish and AES to be 32-bits. E.g. when unsigned long is 64-bits. + -- Optimized the SAFER-SK64, SAFER-SK128, SAFER+, RC5 and RC6 key schedule [big time!] + -- Optimized SHA-1 and SHA-256 quite a bit too. + -- Fixed up the makefile to use -fomit-frame-pointer more liberally + -- Added tv_gen program which makes test vectors for ciphers/hashes + -- Merged in LibTomMath v0.22 + +Jun 19th, 2003 +v0.87 -- Many MSVC optimizations to the code base + -- Improved the AES and Twofish key schedule [faster, more constant time] + -- Tons of optimizations here and there. + +Jun 15th, 2003 +v0.86 -- Fixed up AES to workaround MSVC optimizer bug + -- Merged in fresh LTM base [based on v0.20] so there are no warnings with MSVC + -- Wrote x86_prof which will time the hashes and ciphers downto cycles per byte. + -- Fixed up demos/encrypt to remove serpent_desc from the list + -- Re-enabled MSVC optimizations w00t w00t + -- Replaced "errno" with "err" in all functions that had it so it wouldn't clash + with the global "errno" + -- Removed a set of unused variables from certain functions + -- Removed {#line 0 "..."} stuff from mpi.c to comply with ISO C :-) + +Jun 11th, 2003 +v0.85 -- Swapped in a new AES routine + -- Removed Serpent + -- Added TDCAL policy document + +Jun 1st, 2003 +v0.84 -- Removed a 4KB buffer from rsa_decrypt_key that wasn't being used no more + -- Fixed another potential buffer problem. Not an overflow but could cause the + PK import routines to read past the end of the buffer. + -- Optimized the ECC mulmod more by removing a if condition that will always be false + -- Optimized prime.c to not include a 2nd prime table, removed code from is_prime calls prime + test from LibTomMath now + -- Added LTC_TEST define which when defined will enable the test vector routines [see mycrypt_custom.h] + -- Removed ampi.o from the depends cuz it ain't no not working in *nix with it [routines are in mpi.c now]. + + +Mar 29th, 2003 +v0.83 -- Optimized the ecc_mulmod, it's faster and takes less heap/stack space + -- Fixed a free memory error in ecc_mulmod and del_point which would try to free NULL + -- Fixed two serious bugs in rsa_decrypt_key and rsa_verify_hash that would allow a trivialy + buffer overflow. + -- Fixed a bug in the hmac testing code if you don't register all the hashes it won't return + errors now. + +Mar 15th, 2003 +v0.82 -- Manual updated + -- Added MSVC makefile [back, actually its written from scratch to work with NMAKE] + -- Change to HMAC helper functions API to avoid buffer overflow [source changes] + -- the rsa_encrypt_key was supposed to reject key sizes out of bounds ... + same fix to the rsa_sign_hash + -- Added code to ensure that that chaining mode code (cfb/ofb/ctr/cbc) have valid + structures when being called. E.g. the indexes to the pad/ivs are not out of bounds + -- Cleaned up the DES code and simplified the core desfunc routine. + -- Simplified one of the boolean functions in MD4 + +Jan 16th, 2003 +v0.81 -- Merged in new makefile from Clay Culver and Mike Frysinger + -- Sped up the ECC mulmod() routine by making the word size adapt to the input. Saves a whopping 9 point + operations on 521-bit keys now (translates to about 8ms on my Athlon XP). I also now use barrett reduction + as much as possible. This sped the routine up quite a bit. + -- Fixed a huge flaw in ecc_verify_hash() where it would return CRYPT_OK on error... Now fixed. + -- Fixed up config.pl by fixing an invalid query and the file is saved in non-windows [e.g. not CR/LF] format + (fix due to Mika Bostr?m) + -- Merged in LibTomMath for kicks + -- Changed the build process so that by default "mycrypt_custom.h" is included and provided + The makefile doesn't include any build options anymore + -- Removed the PS2 and VC makefiles. + +Dec 16th, 2002 +v0.80 -- Found a change I made to the MPI that is questionable. Not quite a bug but definately not desired. Had todo + with the digit shifting. In v0.79 I simply truncated without zeroing. It didn't cause problems during my + testing but I fixed it up none the less. + -- Optimized s_mp_mul_dig() from MPI to do a minimal number of passes. + -- Fixed in rsa_exptmod() where I was getting the size of the result. Basically it accomplishes the same thing + but the fixed code is more readable. + -- Fixed slight bug in dh_sign_hash() where the random "k" value was 1 byte shorter than it should have been. I've + also made the #define FAST_PK speed up signatures as well. Essentially FAST_PK tells the DH sub-system to + limit any private exponent to 256-bits. Note that when FAST_PK is defined does not make the library + binary or source incompatible with a copy of the library with it undefined. + -- Removed the DSA code. If you want fast diffie-hellman just define FAST_PK :-) + -- Updated dh_sign_hash()/dh_verify_hash() to export "unsigned" bignums. Saves two bytes but is not binary + compatible with the previous release... sorry! I've performed the same fix to the ecc code as well. + -- Fixed up the PK code to remove all use of mp_toraw() and mp_read_raw() [get all the changes out of the way now] + -- Fixed a bug in the DH code where it missed trapping a few errors if they occurred. + -- Fixed a slight "its-not-a-bug-but-could-be-done-better" bug in the next_prime() function. Essentially it was + testing to ensure that in the loop that searches for the next candidate that the step never grows beyond + 65000. Should have been testing for MP_DIGIT_MAX + -- Spruced up the config.pl script. It now makes a header file "mycrypt_custom.h" which can be included *before* + you include mycrypt.h. This allows you to add libtomcrypt to a project without completely changing your make + system around. Note that you should use the makefile it writes to at least build the library initially. + -- Used splint to check alot of the code out. Tons of minor fixes and explicit casts added. + -- Also made all the internal functions of MPI are now static to avoid poluting the namespace + -- **Notice**: There are no planned future releases for at least a month from the this release date. + +Dec 14th, 2002 +v0.79 -- Change to PK code [binary and source]. I made it so you have to pass the buffer size to the *_decrypt_key and + *_verify_hash functions. This prevents malformed packets from performing buffer overflows. I've also trimmed + the packet header size [by 4 bytes]. + -- Made the test program halt on the first error it occurs. Also made it trap more errors than before. + -- Wrote the first chapter of my new book [DRAFT!], not in this package but check my website! + -- Included a perl script "config.pl" that will make "makefile.out" according to the users needs. + -- Added shell script to look for latest release + -- Merge DH and ECC key defines from mycrypt_cfg.h into the makefiles + -- updated the makefile to use BSD friendly archiving invokations + -- Changed the DH and ECC code to use base64 static key settings [e.g. the primes]. Dropped the code size by 3KB + and is ever-so-slightly faster than before. + -- added "mp_shrink" function to shrink the size of bignums. Specially useful for PK code :-) + -- Added new exptmod function that calculates a^b mod c with fewer multiplies then before [~20% for crypto + sized numbers]. Also added a "low mem" variant that doesn't use more than 20KB [upto 4096 bit nums] of + heap todo the calculation. Both are #define'able controlled + -- Added XREALLOC macro to provide realloc() functionality. + -- Added fix where in rsa_import() if you imported a public key or a non-optimized key it would free the mp_int's + not being used. + -- Fixed potential bug in the ECC code. Only would occur on platforms where char is not eight bits [which isn't + often!] + -- Fixed up the ECC point multiplication, its about 15% faster now + -- While I was at it [since the lib isn't binary backwards compatible anyways] I've fixed the PK export routines + so they export as "unsigned" types saving 1 byte per bignum outputted. Not a lot but heck why not. + +Nov 28th, 2002 +v0.78 -- Made the default ARGCHK macro a function call instead which reduced the code size from 264KB to 239KB. + -- Fixed a bug in the XTEA keysize function which called ARGCHK incorrectly. + -- Added Noekeon block cipher at 2,800 bytes of object code and 345Mbit/sec it is a welcome addition. + -- Made the KR code check if the other PK systems are included [provides error when building otherwise]. + -- Made "aes" an alias for Rijndael via a pre-processor macro. Now you can use "aes_ecb_encrypt", etc... :-) + Thanks to Jean-Luc Cooke for the "buzzword conformance" suggestion. + -- Removed the old PK code entirely (e.g. rsa_sign, dh_encrypt). The *_sign_hash and *_encrypt_key functions + are all that is to remain. + -- **NOTE** Changed the PK *_import (including the keyring) routine to accept a "inlen" parameter. This fixes a + bug where improperly made key packets could result in reading passed the end of the buffer. This means + the code is no longer source compatible but still binary compatible. + -- Fixed a few other minor bugs in the PK import code while I was at it. + +Nov 26th, 2002 +v0.77 -- Updated the XTEA code to use pre-computed keys. With optimizations for speed it achieves 222Mbit/sec + compared to the 121Mbit/sec before. It is 288 bytes bigger than before. + -- Cleaned up some of the ciphers and hashes (coding style, cosmetic changes) + -- Optimized AES slightly for 256-bit keys [only one if statement now, still two for 192-bit keys] + -- Removed most test cases from Blowfish, left three of them there. Makes it smaller and faster to test. + -- Changed the primality routines around. I now use 8 rounds of Rabin-Miller, I use 256 primes in the sieve + step and the "rand_prime" function uses a modified sieve that avoids alot of un-needed bignum work. + -- Fixed a bug in the ECC/DH signatures where the keys "setting" value was not checked for validity. This means + that a invalid value could have caused segfaults, etc... + -- **NOTE** Changed the way the ECC/DH export/import functions work. They are source but not binary compatible + with v0.76. Essentially insteading of exporting the setting index like before I export the key size. Now + if you ever re-configure which key settings are supported the lib will still be able to make use of your + keys. + -- Optimized Blowfish by inlining the round function, unrolling it for four rounds then using a for loop for the + rest. It achieves a rate of 425Mbit/sec with the new code compared to 314Mbit/sec before. The new blowfish + object file is 7,813 bytes compared to 8,663 before and is 850 bytes smaller. So the code is both smaller and + faster! + -- Optimized Twofish as well by inlining the round function. Gets ~400Mbit/sec compared to 280Mbit/sec before + and the code is only 78 bytes larger than the previous copy. + -- Removed SMALL_PRIME_TAB build option. I use the smaller table always. + -- Fixed some mistakes concerning prime generation in the manual. + -- [Note: sizes/speeds are for GCC 3.2 on an x86 Athlon XP @ 1.53Ghz] + +Nov 25th, 2002 +v0.76 -- Updated makefiles a bit more, use "-Os" instead of "-O2" to optimize for size. Got the lib + downto 265KB using GCC 3.2 on my x86 box. + -- Updated the SAFER+, Twofish and Rijndael test vector routine to use the table driven design. + -- Updated all other test vector routines to return as soon as an error is found + -- fixed a bug in the test program where errors in the hash test routines would not be reported + correctly. I found this by temporarily changing one of the bytes of the test vectors. All the + hashes check out [the demos/test.c would still have reported an error, just the wrong one]. + + +Nov 24th, 2002 +v0.75 -- Fixed a flaw in hash_filehandle, it should ARGCHK that the filehandle is not NULL + -- Fixed a bug where in hash_file if the call to hash_filehandle failed the open file would + not be closed. + -- Added more strict rules to build process, starting to weed out "oh this works in GCC" style code + In the next release "-Wconversion" will be enabled which will deal with all implicit casts. + +Nov 22nd, 2002 [later in the day] +v0.74 -- Wrote a small variant of SAFER+ which shaved 50KB off the size of the library on x86 platforms + -- Wrote a build option to remove the PK packet functions [keeps the encrypt_key/sign_hash functions] + -- Wrote a small variant of Rijndael (trimmed 13KB) + -- Trimmed the TIGER/192 hash function a bit + -- Overall the entire lib compiled is 295KB [down from 400KB before] + -- Fixed a few minor oversights in the MSVC makefile + +Nov 22nd, 2002 +v0.73 -- Fixed bug in RC4 code where it could only use 255 byte keys. + -- Fixed bug in yarrow code where it would allow cast5 or md2 to be used with it... + -- Removed the ecc compress/expand points from the global scope. Reduces namespace polution + -- Fixed bug where if you used the SPRNG you couldn't pass NULL as your prng_state which you should be + able todo since the SPRNG has no state... + -- Corrected some oversights in the manual and the examples... + -- By default the GF(2^W) math library is excluded from the build. The source is maintained because I wrote it + and like it :-). This way the built library is a tad smaller + -- the MSVC makefile will now build for a SPACE optimized library rather than TIME optimized. + +Nov 21th, 2002 +v0.72 -- Fixed bug in the prime testing. In the Miller-Rabin test I was raising the base to "N-1" not "r". + The math still worked out fine because in effect it was performing a Fermat test. Tested the new code and it + works properly + -- Fixed some of the code where it was still using the old error syntax + -- Sped up the RSA decrypt/sign routines + -- Optimized the ecc_shared_secret routine to not use so much stack + -- Fixed up the makefile to make releases where the version # is in the file name and directory it will unzip + to + +Nov 19th, 2002 +v0.71 -- HELP TOM. I need tuition for the January semester. Now I don't want to force donations [nor will I ever] + but I really need the help! See my website http://tom.iahu.ca/help_tom.html for more details. Please help + if you can! + -------------------------------------------------------------------------------------------------------------- + -- Officially the library is no longer supported in GCC 3.2 in windows [cygwin]. + In windows you can either use GCC 2.95.3 or try your luck with 3.2 It seems that + "-fomit-frame-pointer" is broken in the windows build [but not the linux x86 build???] + If you simply must use 3.2 then I suggest you limit the optimizations to simply "-O2" + -- Started new error handling API. Similar to the previous except there are more error codes than just + CRYPT_ERROR + -- Added my implementation of the MD2 hash function [despite the errors in the RFC I managed to get it right!] + -- Merged in more changes from Sky Schulz. I have to make mention here that he has been a tremendous help in + getting me motivated to make some much needed updates to the library! + -- Fixed one of the many mistakes in the manual as pointed out by Daniel Richards + -- Fixed a bug in the RC4 code [wasn't setting up the key correctly] + -- Added my implementation of the CAST5 [aka CAST-128] block cipher (conforms...) + -- Fixed numerous bugs in the PK code. Essentially I was "freeing" keys when the import failed. This is neither + required nor a good a idea [double free]. + -- Tom needs a job. + -- Fixed up the test harness as requested by Sky Schulz. Also modifed the timing routines to run for X seconds + and count # of ops performed. This is more suitable than say encrypting 10 million blocks on a slow processor + where it could take minutes! + -- Modified test programs hashsum/encrypt to use the new algorithms and error handling syntax + -- Removed the PKCS code since it was incomplete. In the future I plan on writing a "add-on" library that + provides PKCS support... + -- updated the config system so the #defines are in the makefiles instead of mycrypt_cfg.h + -- Willing to work on an hourly basis for 15$ CDN per hour. + -- updated the test program to not test ciphers not included + -- updated the makefile to make "rsa_sys.c" a dependency of rsa.o [helps develop the code...] + -- fixed numerous failures to detect buffer overflows [minor] in the PK code. + -- fixed the safer [64-bit block version] test routines which didn't check the returns of the setup + function + -- check out my CV at http://tom.iahu.ca/cv.html + -- removed the GBA makefile and code from demos/test.c [not a particularly useful demo...] + -- merged in rudimentary [for testing] PS2 RNG from Sky Schulz + -- merged in PS2 timer code [only shell included due to NDA reasons...] + -- updated HMAC code to return errors where possible + -- Thanks go to Sky Schulz who bought me a RegCode for TextPad [the official editor of libtomcrypt] + +Nov 12th, 2002 +v0.70 -- Updated so you can swap out the default malloc/calloc/free routines at build time with others. (Sky Schulz) + -- Sky Schulz contributed some code towards autodetecting the PS2 in mycrypt_cfg.h + -- Added PS2 makefile contributed by Sky Schulz [see a pattern forming?] + -- Added ability to have no FILE I/O functions at all (see makefile), Sky Schulz.... + -- Added support for substituting out the clock() function (Sky Schulz) + -- Fixed up makefile to include new headers in the HEADERS variable + -- Removed "coin.c" as its not really useful anyways + -- Removed many "debug" printfs that would show up on failures. Basically I wanted to ensure the only output + would be from the developer themselves. + -- Added "rc4.c" a RC4 implementation with a PRNG interface. Since RC4 isn't a block cipher it wouldn't work + too well as a block cipher. + -- Fixed ARGCHK macro usage when ARGTYPE=1 throughout the code + -- updated makefile to make subdirectory properly (Sku Schulz) + -- Started towards new API setup. Instead of checking for "== CRYPT_ERROR" you should check "!= CRYPT_OK" + In future releases functions will return things other than CRYPT_ERROR on error to give more useful + thread safe error reporting. The manual will be updated to reflect this. For this release all + errors are returned as CRYPT_ERROR (except as noted) but in future releases this will change. + -- Removed the zlib branch since its not really required anyways. Makes the package smaller + +Nov 11th, 2002 +v0.69 -- Added ARGCHK (see mycrypt_argchk.h) "arguement checking" to all functions that accept pointers + -- Note I forgot to change the CRYPT version tag in v0.68... fixed now. + +Nov 8th, 2002 +v0.68 -- Fixed flaw in kr_import/kr_export that wasted 4 bytes. Source but not binary compatible with v0.67 + -- Fixed bug in kr_find_name that used memcmp to match strings. Uses strncmp now. + -- kr_clear now sets the pointer to NULL to facilate debugging [e.g. using the keyring after clearing] + -- static functions in _write/_read in keyring.c now check the return of ctr_encrypt/ctr_decrypt. + -- Updated blowfish/rc2/rc5/rc6 keysize() function to not reject keys larger than the biggest key the + respective ciphers can use. + -- Fixed a bug in hashsum demo that would report the hash for files that don't exist! + +Oct 16th, 2002 +v0.67 -- Moved the function prototypes into files mycrypt_*.h. To "install" the lib just copy all the + header files "*.h" from the base of this project into your global include path. + -- Made the OFB/CFB/CTR functions use "unsigned long" for the length instead of "int" + -- Added keyring support for the PK functions + -- ***API CHANGE*** changed the ecc_make_key and dh_make_key to act more like rsa_make_key. Basically + move the first argument to the next to last. + -- Fixed bug in dh_test() that wouldn't test the primality of the order of the sub-group + -- replaced the primes in the DH code with new ones that are larger than the size they are + associated with. That is a 1024-bit DH key will have a 1025-bit prime as the modulus + -- cleaned up all the PK code, changed a bit of the API around [not source compatible with v0.66] + -- major editing of the manual, started Docer program + -- added 160 and 224 bit key settings for ECC. This makes the DH and ECC binary wise incompatible with v0.66 + -- Added an additional check for memory errors in is_prime() and cleaned up prime.c a bit + -- Removed ID_TAG from all files [meh, not a big fan...] + -- Removed unused variable from yarrow state and made AES/SHA256 the default cipher/hash combo + -- Fixed a bug in the Yarrow code that called prng_is_valid instead of cipher_is_valid from yarrow_start() + -- The ECB/CBC/OFB/CFB/CTR wrappers now check that the cipher is valid in the encrypt/decrypt calls + Returns int now instead of void. + +Sept 24th, 2002 +v0.66 -- Updated the /demos/test.c program to time the hashes correctly. Also it uses the yarrow PRNG for all of the + tests meaning its possible to run on RNG less platforms + -- Updated the /demos/hashsum.c program to hash from the standard input + -- Updated the RSA code to make keys a bit quicker [update by Wayne Scott] by not making both primes at the same + time. + -- Dan Kaminsky suggested some cleanups for the code and the MPI config + Code ships in unix LF format by default now too... will still build in MSVC and all... but if you want + to read the stuff you'll have to convert it + -- Changes to the manual to reflect new API [e.g. hash_memory/file have v0.65 prototypes]and some typos fixed + +Sept 20th, 2002 +v0.65 -- Wayne Scott (wscott@bitmover.com) made a few of suggestions to improve the library. Most + importantly he pointed out the math lib is not really required. He's also tested the lib on 18 + different platforms. According to him with only a few troubles [lack of /dev/random, etc] the + library worked as it was supposed to. You can find the list at + http://www.bitkeeper.com/Products.BitKeeper.Platforms.html + -- Updated the hash_file and hash_memory functions to keep track of the size of the output + -- Wayne Scott updated the demos/test.c file to use the SPRNG less and Yarrow more + -- Modified the mycrypt_cfg.h to autodetect x86-32 machines + +Sept 19th, 2002 +v0.64 -- wrote makefile for the GBA device [and hacked the demos/test.c file to support it conditionally] + -- Fixed error in PK (e.g. ECC, RSA, DH) import functions where I was clobbering the packet error messages + -- fixed more typos in the manual + -- removed all unused variables from the core library (ignore the ID_TAG stuff) + -- added "const char *crypt_build_settings" string which is a build time constant that gives a listing + of all the build time options. Useful for debugging since you can send that to me and I will know what + exactly you had set for the mycrypt_cfg.h file. + -- Added control over endianess. Out of the box it defaults to endianess neutral but you can trivially + configure the library for your platform. Using this I boosted RC5 from 660Mbit/sec to 785Mbit/sec on my + Athlon box. See "mycrypt_cfg.h" for more information. + +Sept 11th, 2002 +v0.63 -- Made hashsum demo output like the original md5sum program + -- Made additions to the examples in the manual (fixed them up a bunch) + -- Merged in the base64 code from Wayne Scott (wscott@bitmover.com) + +Aug 29th, 2002 +v0.62 -- Added the CLEAN_STACK functionality to several of the hashes I forgot to update. + +Aug 9th, 2002 +v0.61 -- Fixed a bug in the DES code [oops I read something wrong]. + +Aug 8th, 2002 +v0.60 -- Merged in DES code [and wrote 3DES-EDE code based on it] from Dobes V. + +Aug 7th, 2002 +v0.59 -- Fixed a "unsigned long long" bug that caused v0.58 not to build in MSVC. + -- Cleaned up a little in the makefile + -- added code that times the hash functions too in the test program + +Aug 3rd, 2002 +v0.58 -- Added more stack cleaning conditionals throughout the code. + -- corrected some CLEAR_STACK conditionals... should have been CLEAN_STACK + -- Simplified the RSA, DH and ECC encrypt() routines where they use CTR to encode the message + now they only make one call to ctr_encrypt()/ctr_decrypt(). + +Aug 2nd, 2002 +v0.57 -- Fixed a few errors messages in the SAFER code to actually report the correct cipher name. + -- rsa_encrypt() uses the "keysize()" method of the cipher being used to more accurately pick a + key size. By default rsa_encrypt() will choose to use a 256-bit key but the cipher can turn that + down if required. + -- The rsa_exptmod() function will now more reliably detect invalid inputs (e.g. greater than the modulus). + -- The padding method for RSA is more clearly documented. Namely if you want to encrypt/sign something of length + N then your modulus must be of length 1+3N. So to sign a message with say SHA-384 [48 bytes] you need a + 145 byte (1160 bits) modulus. This is all in the manual now. + -- Added build option CLEAN_STACK which will allow you to choose whether you want to clean the stack or not after every + cipher/hash call + -- Sped up the hash "process()" functions by not copying one byte at a time. + ++ (added just after I uploaded...) + MD4 process() now handles input buffers > 64 bytes + +Aug 1st, 2002 +v0.56 -- Cleaned up the comments in the Blowfish code. + -- Oh yeah, in v0.55 I made all of the descriptor elements constant. I just forgot to mention it. + -- fixed a couple of places where descriptor indexes were tested wrong. Not a huge bug but now its harder + to mess up. + -- Added the SAFER [64-bit block] ciphers K64, SK64, K128 and SK128 to the library. + -- Added the RC2 block cipher to the library. + -- Changed the SAFER define for the SAFER+ cipher to SAFERP so that the new SAFER [64-bit] ciphers + can use them with less confusion. + +July 29th, 2002 +v0.55 -- My god stupid Blowfish has yet again been fixed. I swear I hate that cipher. Next bug in it and boom its out of the + library. Use AES or something else cuz I really hate Blowfish at this stage.... + -- Partial PKCS support [hint DONT USE IT YET CUZ ITS UNTESTED!] + +July 19th, 2002 +v0.54 -- Blowfish now conforms to known test vectors. Silly bad coding tom! + -- RC5/RC6/Serpent all have more test vectors now [and they seemed to have been working before] + +July 18th, 2002 +v0.53 -- Added more test vectors to the blowfish code just for kicks [and they are const now too :-)] + -- added prng/hash/cipher is_valid functions and used them in all of the PK code so you can't enter the code + with an invalid index ever now. + -- Simplified the Yarrow code once again :-) + +July 12th, 2002 +v0.52 -- Fixed a bug in MD4 where the hash descriptor ID was the same as SHA-512. Now MD4 will work with + all the routines... + -- Fixed the comments in SHA-512 to be a bit more meaningful + -- In md4 I made the PADDING array const [again to store it in ROM] + -- in hash_file I switched the constant "512" to "sizeof(buf)" to be a bit safer + -- in SHA-1's test routine I fixed the string literal to say SHA-1 not sha1 + -- Fixed a logical error in the CTR code which would make it skip the first IV value. This means + the CTR code from v0.52 will be incompatible [binary wise] with previous releases but it makes more + sense this way. + -- Added {} braces for as many if/for/blocks of code I could find. My rule is that every for/if/while/do block + must have {} braces around it. + -- made the rounds table in saferp_setup const [again for the ROM think about the ROM!] + -- fixed RC5 since it no longer requires rc5 to be registered in the lib. It used to since the descriptors used to + be part of the table... + -- the packet.c code now makes crypt_error literal string errors when an error occurs + -- cleaned up the SAFER+ key schedule to be a bit easier to read. + -- fixed a huge bug in Twofish with the TWOFISH_SMALL define. Because I clean the stack now I had + changed the "g_func()" to be called indirectly. I forgot to actually return the return of the Twofish + g_func() function which caused it not to work... [does now :-)] + +July 11th, 2002 +v0.51 -- Fixed a bug in SHA512/384 code for multi-block messages. + -- Added more test vectors to the SHA384/512 and TIGER hash functions + -- cleaned up the hash done routines to make more sense + +July 10th, 2002 +v0.50 -- Fixed yarrow.c so that the cipher/hash used would be registered. Also fixed + a bug where the SAFER+ name was "safer" but should have been "safer+". + -- Added an element to the hash descriptors that gives the size of a block [sent into the compressor] + -- Cleaned up the support for HMAC's + -- Cleaned up the test vector routines to make the test vector data const. This means on some platforms it will be + placed in ROM not RAM now. + -- Added MD4 code submited by Dobes Vandermeer (dobes@smartt.com) + -- Added "burn_stack" function [idea taken from another source of crypto code]. The idea is if a function has + alot of variables it will clean up better. Functions like the ecb serpent and twofish code will now have their + stacks cleaned and the rest of the code is getting much more straightforward. + -- Added a hashing demo by Daniel Richards (kyhwana@world-net.co.nz) + -- I (Tom) modified some of the test vector routines to use more vectors ala Dobes style. + For example, the MD5/SHA1 code now uses all of the test vectors from the RFC/FIPS spec. + -- Fixed the register/unregister functions to properly report errors in crypt_error + -- Correctly updated yarrow code to remove a few unused variables. + -- Updated manual to fix a few erroneous examples. + -- Added section on Hash based Message Authentication Codes (HMAC) to the manual + +June 19th, 2002 +v0.46 -- Added in HMAC code from Dobes Vandermeer (dobes@smartt.com) + +June 8th, 2002 +v0.45 -- Fixed bug in rc5.c where if you called rc5_setup() before registering RC5 it would cause + undefined behaviour. + -- Fixed mycrypt_cfg.h to eliminate the 224 bit ECC key. + -- made the "default" makefile target have depends on mycrypt.h and mycrypt_cfg.h + +Apr 4th, 2002 +v0.44 -- Fixed bug in ecc.c::new_point() where if the initial malloc fails it would not catch it. + +Mar 22nd, 2002 +v0.43 -- Changed the ZLIB code over to the 1.1.4 code base to avoid the "double free" bug. + -- Updated the GCC makefile not to use -O3 or -funroll-loops + -- Version tag in mycrypt.h has been updated :-) + +Mar 10th, 2002 +v0.42 -- The RNG code can now use /dev/urandom before trying /dev/random (J. Klapste) + +Mar 3rd, 2002 +v0.41 -- Added support to link and use ciphers at compile time. This can greatly reduce the code size! + -- Added a demo to show off how small an application can get... 46kb! + -- Disastry pointed out that Blowfish is supposed to be high endian. + -- Made registry code for the PRNGs as well [now the smallest useable link is 43kb] + +Feb 11th, 2002 +v0.40 -- RSA signatures use [and check for] fixed padding scheme. + -- I'm developing in Linux now :-) + -- No more warnings from GCC 2.96 + +Feb 5th, 2002 +v0.39 -- Updated the XTEA code to work in accordance with the XTEA design + +January 24th, 2002 +v0.38 -- CFB and OFB modes can now handle blocks of variable size like the CTR code + -- Wrote a wrapper around the memory compress functions in Zlib that act like the functions + in the rest of my crypto lib + +January 23rd, 2002 +v0.37 -- Added support code so that if a hash size and key size for a cipher don't match up they will + use the next lower key supported. (mainly for the PK code). So you can now use SHA-1 with + Twofish, etc... + -- Added more options for Twofish. You can now tell it to use precomputed sboxes and MDS multiplications + This will speed up the TWOFISH_SMALL implementation by increasing the code size by 1024 bytes. + -- Fixed a bug in prime.c that would not use the correct table if you undefined SMALL_PRIME_TAB + -- Fixed all of the PK packet code to use the same header format [see packet.c]. This makes the PK code + binary wise incompatible with previous releases while the API has not changed at all. + +January 22nd, 2002 +v0.36 -- Corrections to the manual + -- Made a modification to Twofish which lets you build a "small ram" variant. It requires + about 190 bytes of ram for the key storage compared to the 4,200 bytes the normal + variant requires. + -- Reduced the stack space used in all of the PK routines. + +January 19th, 2002 +v0.35 -- If you removed the first hash or cipher from the library it wouldn't return an error if + you used an ID=0 [i.e blowfish or sha256] in any routine. Now it checks for that and will + return an error like it should + -- Merged in new routines from Clay Culver. These routines are for the PK code so you can easily + encode a symmetric key for multiple recipients. + -- Made the ecc and DH make_key() routines make secret keys of the same size as the keysize listed. + Originally I wanted to ensure that the keys were smaller than the order of the field used + However, the bias is so insignifcant using full sizes. For example, with a ECC-192 key the order + is about 2^191.99, so instead I rounded down and used a 184-bit secret key. Now I simply use a full 192-bit + key the code will work just the same except that some 192-bit keys will be duplicates which is not a big + deal since 1/2^192 is a very small bias! + -- Made the configuration a bit simpler and more exacting. You can for example now select which DH or ECC + key settings you wish to support without including the data for all other key settings. I put the #defines + in a new file called "mycrypt_cfg.h" + -- Configured "mpi-config.h" so its a bit more conservative with the memory required and code space used + -- Jason Klapste submitted bug fixes to the yarrow, hash and various other issues. The yarrow code will now + use what ever remaining hash/cipher combo is left [after you #undef them] at build time. He also suggested + a fix to remove unused structures from the symmetric_key and hash_state unions. + -- Made the CTR code handle variable length blocks better. It will buffer the encryption pad so you can + encrypt messages any size block at a time. + -- Simplified the yarrow code to take advantage of the new CTR code. + -- Added a 4096-bit DH key setting. That took me about 36 hours to find! + -- Changed the base64 routines to use a real base64 encoding scheme. + -- Added in DH and ECC "encrypt_key()" functions. They are still rather "beta"ish. + -- Added **Twofish** to the list of ciphers! + +January 18th, 2002 +v0.34 -- Added "sha512" to the list of hashes. Produces a 512-bit message digest. Note that with the current + padding with the rsa_sign() function you cannot use sha512 with a key less than 1536 bits for signatures. + -- Cleaned up the other hash functions to use the LOAD and STORE macros... + +January 17th, 2002 +v0.33 -- Made the lower limit on keysizes for RSA 1024 bits again because I realized that 768 bit keys wouldn't + work with the padding scheme and large symmetric keys. + -- Added information concerning the Zlib license to the manual + -- Added a 3072-bit key setting for the DH code. + -- Made the "find_xyz()" routines take "const char *" as per Clay Culver's suggestion. + -- Fixed an embarassing typo in the manual concerning the hashes. Thank's Clay for finding it! + -- Fixed rand_prime() so that it makes primes bigger than the setting you give. For example, + if you want a 1024-bit prime it would make a 1023-bit one. Now it ensures that the prime + it makes is always greater than 2^(8n) (n == bytes in prime). This doesn't have a huge + impact on security but I corrected it just the same. + -- Fixed the CTR routine to work on platforms where char != 8-bits + -- Fixed sha1/sha256/md5/blowfish to not assume "unsigned long == 32-bits", Basically any operation with carries + I "AND" with 0xFFFFFFFF. That forces only the lower 32-bits to have information in it. On x86 platforms + most compilers optimize out the AND operation since its a nop. + +January 16th, 2002 +v0.32 -- Made Rijndael's setup function fully static so it is thread safe + -- Svante Seleborg suggested a cosmetic style fixup for aes.c, + basically to remove some of the #defines to clean it up + -- Made the PK routines not export the ASCII version of the names of ciphers/hashes which makes + the PK message formats *incompatible* with previous releases. + -- Merge in Zlib :-) + + +January 15th, 2002 +v0.31 -- The RSA routines can now use CRT to speed up decryption/signatures. The routines are backwards + compatible with previous releases. + -- Fixed another bug that Svante Seleborg found. Basically you could buffer-overrun the + rsa_exptmod() function itself if you're not careful. That's fixed now. Fixed another bug in + rsa_exptmod() where if it knows the buffer you passed is too small it wouldn't free all used + memory. + -- improved the readability of the PK import/export functions + -- Added a fix to RSA.C by Clay Culver + -- Changed the CONST64 macro for MSVC to use the "unsigned __int64" type, e.g. "ui64" instead of "i64". + +January 14th, 2002 +v0.30 -- Major change to the Yarrow PRNG code, fixed a bug that Eugene Starokoltsev found. + Basically if you added entropy to the pool in small increments it could in fact + cancel out. Now I hash the pool with the new data which is way smarter. + +January 12th, 2002 +v0.29 -- Added MPI code written by Svante Seleborg to the library. This will make the PK code much + easier to follow and debug. Actually I've already fixed a memory leak in dh_shared_secret(). + -- Memory leaks found and correct in all three PK routines. The leaks would occur when a bignum + operation fails so it wouldn't normally turn up in the course of a program + -- Fixed bugs in dh_key_size and ecc_key_size which would return garbage for invalid key idx'es + +January 11th, 2002 +v0.28 -- Cleaned up some code so that it doesn't assume "char == 8bits". Mainly SAFER+ has been + changed. + -- ***HUGE*** changes in the PK code. I check all return values in the bignum code so if there + are errors [insufficient memory, etc..] it will be reported. This makes the code fairly more + robust and likely to catch any errors. + -- Updated the is_prime() function to use a new prototype [it can return errors now] and it also + does trial divisions against more primes before the Rabin Miller steps + -- Added OFB, CFB and ECB generic wrappers for the symmetric ciphers to round out the implementations. + -- Added Xtea to the list of ciphers, to the best of my ability I have verified this implementation. + I should note that there is not alot of concrete information about the cipher. "Ansi C" versions + I found did not address endianess and were not even portable!. This code is portable and to the + best of my knowledge implements the Xtea algorithm as per the [short] X-Tea paper. + -- Reformated the manual to include the **FULL** source code optimized to be pritable. + +January 9th, 2002 +v0.27 -- Changed the char constants to numerical values. It is backwards compatible and should work on + platforms where 'd' != 100 [for example]. + -- Made a change to rand_prime() which takes the input length as a signed type so you can pass + a negative len to get a "3 mod 4" style prime... oops + -- changed the MSVC makefile to build with a warning level of three, no warnings! + +January 8th, 2002 +v0.26 -- updated SHA-256 to use ROR() for a rotate so 64-bit machines won't corrupt + the output + -- Changed #include <> to #include "" for local .h files as per Richard Heathfields' suggestions. + -- Fixed bug in MPI [well bug in MSVC] that compiled code incorrectly in mp_set_int() + I added a work around that catches the error and continues normally. + +January 8th, 2002 +v0.25 -- Added a stupid define so MSVC 6.00 can build the library. + -- Big thanks to sci.crypt and "Ajay K. Agrawal" for helping me port this to MSVC + +January 7th, 2002 +v0.24 -- Sped up Blowfish by unrolling and removing the swaps. + -- Made the code comply with more traditional ANSI C standards + Should compile with MSVC with less errors + -- moved the demos and documentation into their own directories + so you can easily build the library with other tool chains + by compiling the files in the root + -- converted functions with length of outputs to use + "unsigned long" so 16-bit platforms will like this library more. + +January 5th, 2002 +v0.23 -- Fixed a small error in the MPI config it should build fine anywhere. + +January 4th, 2002 +v0.22 -- faster gf_mul() code + -- gf_shl() and gf_shr() are safe on 64-bit platforms now + -- Fixed an error in the hashes that Brian Gladman found. + Basically if the message has exactly 56 bytes left to be + compressed I handled them incorrectly. + +January 4th, 2002 +v0.21 -- sped up the ECC code by removing redundant divisions in the + point add and double routines. I also extract the bits more + efficiently in "ecc_mulmod()" now. + -- sped up [and documented] the rand_prime() function. Now it just + makes a random integer and increments by two until a prime is found + This is faster since it doesn't require alot of calls to the PRNG and + it doesn't require loading huge integers over and over. rand_prime() + can also make primes congruent to 3 mod 4 [i.e for a blum integer] + -- added a gf_sqrt() function that finds square roots in a GF(2^w) field + -- fixed a bug in gf_div() that would return the wrong results if the divisor had a greator + divisor than the dividend. + +January 4th, 2002 +v0.20 -- Added the fixed MPI back in so RSA and DH are much faster again + +v0.19 -- Updated the manual to reflect the fact that Brian Gladman wrote the AES and Serpent code. + -- DH, ECC and RSA signature/decryption functions check if the key is private + -- new DH signature/verification code works just like the RSA/ECC versions + +January 3rd, 2002 +v0.18 -- Added way more comments to each .C file + -- fixed a bug in cbc_decrypt(pt, ct, key) where pt == ct [i.e same buffer] + -- fixed RC5 so it reads the default rounds out of the cipher_descriptor table + -- cleaned up ecc_export() + -- Cleaned up dh_import() and ecc_import() which also perform more + error checking now + -- Fixed a serious flaw in rsa_import() with private keys. + +January 2nd, 2002 +v0.17 -- Fixed a bug in the random prime generator that fixes the wrong bits to one + -- ECC and DH code verify that the moduli and orders are in fact prime. That + slows down the test routines alot but what are you gonna do? + -- Fixed a huge bug in the mp_exptmod() function which incorrectly calculates g^x mod p for some + values of p. I replaced it with a slow function. Once the author of MPI fixes his faster routine + I will switch back. + +January 1st, 2002 [whoa new year!] +v0.16 -- Improved GF division code that is faster. + -- documented the GF code + +December 31st, 2001 +v0.15 -- A 1792-bit and 2048-bit DH setting was added. Took me all night to + find a 1792 and 2048-bit strong prime but what the heck + -- Library now has polynomial-basis GF(2^w) routines I wrote myself. Can be used to perform + ECC over GF(2^w) later on.... + -- Fixed a bug with the defines that allows it to build in windows + +December 30th, 2001 +v0.14 -- Fixed the xxx_encrypt() packet routines to make an IV of appropriate size + for the cipher used. It was defaulting to making a 256-bit IV... + -- base64_encode() now appends a NULL byte, um "duh" stupid mistake now fixed... + -- spell checked the manual again... :-) + +December 30th, 2001 +v0.13 -- Switching back to older copy of MPI since it works! arrg.. + -- Added sign/verify functions for ECC + -- all signature verification routines default to invalid signatures. + -- Changed all calls to memset to zeromem. Fixed up some buffer problems + in other routines. All calls to zeromem let the compiler determine the size + of the data to wipe. + +December 29th, 2001 +v0.12 -- Imported a new version of MPI [the bignum library] that should + be a bit more stable [if you want to write your own bignum + routines with the library that is...] + -- Manual has way more info + -- hash_file() clears stack now [like it should] + -- The artificial cap on the hash input size of 2^32 bits has been + removed. Basically I was too lazy todo 64-bit math before + [don't ask why... I can't remember]. Anyways the hashes + support the size of 2^64 bits [if you ever use that many bits in a message + that's just wierd...] + -- The hashes now wipe the "hash_state" after the digest is computed. This helps + prevent the internal state of the hash being leaked accidently [i.e stack problems] + +December 29th, 2001 +v0.11 -- Made #define's so you can trim the library down by removing + ciphers, hashs, modes of operation, prngs, and even PK algorithms + For example, the library with rijndael+ctr+sha1+ECC is 91KB compared + to the 246kb the full library takes. + -- Added ECC packet routines for encrypt/decrypt/sign/verify much akin to + the RSA packet routines. + -- ECC now compresses the public key, a ECC-192 public key takes 33 bytes + for example.... + +December 28th, 2001 +v0.10 -- going to restart the manual from scratch to make it more + clear and professional + -- Added ECC over Z/pZ. Basically provides as much as DH + except its faster since the numbers are smaller. For example, + A comparable 256-bit ECC key provides as much security as expected + from a DH key over 1024-bits. + -- Cleaned up the DH code to not export the symbol "sets[]" + -- Fixed a bug in the DH code that would not make the correct size + random string if you made the key short. For instance if you wanted + a 512-bit DH key it would make a 768-bit one but only make up 512-bits + for the exponent... now it makes the full 768 bits [or whatever the case + is] + -- Fixed another ***SERIOUS*** bug in the DH code that would default to 768-bit + keys by mistake. + +December 25th, 2001 +v0.09 -- Includes a demo program called file_crypt which shows off + how to use the library to make a command line tool which + allows the user to encode/decode a file with any + hash (on the passphrase) and cipher in CTR mode. + -- Switched everything to use typedef's now to clear up the code. + -- Added AES (128/192 and 256 bit key modes) + +December 24th, 2001 +v0.08 -- fixed a typo in the manual. MPI stores its bignums in + BIG endian not little. + -- Started adding a RNG to the library. Right now it tries + to open /dev/random and if that fails it uses either the + MS CSP or the clock drift RNG. It also allows callbacks + since the drift RNG is slow (about 3.5 bytes/sec) + -- the RNG can also automatically setup a PRNG as well now + +v0.07 -- Added basic DH routines sufficient to + negotiate shared secrets + [see the manual for a complete example!] + -- Fixed rsa_import to detect when the input + could be corrupt. + -- added more to the manual. + +December 22nd, 2001 +v0.06 -- Fixed some formatting errors in + the hash functions [just source code cleaning] + -- Fixed a typo in the error message for sha256 :-) + -- Fixed an error in base64_encode() that + would fail to catch all buffer overruns + -- Test program times the RSA and symmetric cipher + routines for kicks... + -- Added the "const" modifier to alot of routines to + clear up the purpose of each function. + -- Changed the name of the library to "TomCrypt" + following a suggestion from a sci.crypt reader.... + +v0.05 -- Fixed the ROL/ROR macro to be safe on platforms + where unsigned long is not 32-bits + -- I have added a bit more to the documentation + manual "crypt.pdf" provided. + -- I have added a makefile for LCC-Win32. It should be + easy to port to other LCC platforms by changing a few lines. + -- Ran a spell checker over the manual. + -- Changed the header and library from "crypt" to "mycrypt" to not + clash with the *nix package "crypt". + +v0.04 -- Fixed a bug in the RC5,RC6,Blowfish key schedules + where if the key was not a multiple of 4 bytes it would + not get loaded correctly. + +December 21st, 2001 + +v0.03 -- Added Serpent to the list of ciphers. + +v0.02 -- Changed RC5 to only allow 12 to 24 rounds + -- Added more to the manual. + +v0.01 -- We will call this the first version. + +/* $Source: /cvs/libtom/libtomcrypt/changes,v $ */ +/* $Revision: 1.288 $ */ +/* $Date: 2007/05/12 14:37:41 $ */ + diff --git a/deps/libtomcrypt/coverity.sh b/deps/libtomcrypt/coverity.sh new file mode 100644 index 0000000..5f40097 --- /dev/null +++ b/deps/libtomcrypt/coverity.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +if [ $# -lt 2 ] +then + echo "usage is: ${0##*/} " + echo "e.g. \"${0##*/} \"/usr/local/bin/coverity\" \"-DLTM_DESC -I/path/to/libtommath/\"\"" + exit -1 +fi + +PATH=$PATH:$1/bin + +make clean +rm -r cov-int/ + +myCflags="" +myCflags="$myCflags -O2 ${2}" +myCflags="$myCflags -pipe -Werror -Wpointer-arith -Winit-self -Wextra -Wall -Wformat -Wformat-security" + +CFLAGS="$myCflags" cov-build --dir cov-int make -f makefile.unix $MAKE_OPTS IGNORE_SPEED=1 1>gcc_1.txt + +if [ $? -ne 0 ] +then + echo "make failed" + exit -1 +fi + +# zipup everything +tar caf libtomcrypt.lzma cov-int + +mytoken=$(cat .coverity_token) +mymail=$(cat .coverity_mail) +myversion=$(git describe --dirty) + +curl -k --form project=libtomcrypt \ + --form token=${mytoken} \ + --form email=${mymail} \ + --form file=@libtomcrypt.lzma \ + --form version=\"${myversion}\" \ + --form description="\"libtomcrypt version ${myversion}\"" \ + https://scan.coverity.com/builds?project=libtom%2Flibtomcrypt + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/demos/CMakeLists.txt b/deps/libtomcrypt/demos/CMakeLists.txt new file mode 100644 index 0000000..114c779 --- /dev/null +++ b/deps/libtomcrypt/demos/CMakeLists.txt @@ -0,0 +1,70 @@ +#----------------------------------------------------------------------------- +# Options +#----------------------------------------------------------------------------- +option(BUILD_USEFUL_DEMOS "Build useful demos (hashsum)" FALSE) +option(BUILD_USABLE_DEMOS "Build usable demos (ltcrypt sizes constants)" FALSE) + +#----------------------------------------------------------------------------- +# Useful demos +#----------------------------------------------------------------------------- + +if(BUILD_USEFUL_DEMOS) + + list(APPEND ALL_DEMOS_TARGETS hashsum) + + # hashsum + add_executable(hashsum + ${CMAKE_CURRENT_SOURCE_DIR}/hashsum.c + ) + + target_link_libraries(hashsum PRIVATE + ${PROJECT_NAME} + ) + +endif() + +#----------------------------------------------------------------------------- +# Usable demos +#----------------------------------------------------------------------------- + +if(BUILD_USABLE_DEMOS) + + list(APPEND ALL_DEMOS_TARGETS ltcrypt sizes constants) + + # ltcrypt + add_executable(ltcrypt + ${CMAKE_CURRENT_SOURCE_DIR}/ltcrypt.c + ) + + target_link_libraries(ltcrypt PRIVATE + ${PROJECT_NAME} + ) + + # sizes + add_executable(sizes + ${CMAKE_CURRENT_SOURCE_DIR}/sizes.c + ) + + target_link_libraries(sizes PRIVATE + ${PROJECT_NAME} + ) + + # constants + add_executable(constants + ${CMAKE_CURRENT_SOURCE_DIR}/constants.c + ) + + target_link_libraries(constants PRIVATE + ${PROJECT_NAME} + ) + +endif() + +#----------------------------------------------------------------------------- +# Install targets +#----------------------------------------------------------------------------- +install(TARGETS ${ALL_DEMOS_TARGETS} + COMPONENT "runtime" + EXPORT ${TARGETS_EXPORT_NAME} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/deps/libtomcrypt/demos/aesgcm.c b/deps/libtomcrypt/demos/aesgcm.c new file mode 100644 index 0000000..fa0e2d3 --- /dev/null +++ b/deps/libtomcrypt/demos/aesgcm.c @@ -0,0 +1,150 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file aesgcm.c + AES128-GCM demo - file en-&decryption, Steffen Jaeckel + Uses the format: |ciphertext|tag-16-bytes| +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gcm-file/gcm_filehandle.c" +#include "gcm-file/gcm_file.c" + + +static off_t fsize(const char *filename) +{ + struct stat st; + + if (stat(filename, &st) == 0) return st.st_size; + + return -1; +} + +#if defined(__linux__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 14) +#define HAS_SYNCFS +#endif +#endif + +static int mv(const char *old_name, const char *new_name) +{ + int fd; + if (rename(old_name, new_name) == -1) return -1; + fd = open(new_name, 0); + if (fd == -1) return -1; +#if !defined(_WIN32) + if (fsync(fd) != 0) goto OUT; +#if defined(HAS_SYNCFS) + syncfs(fd); +#else + sync(); +#endif +OUT: +#endif + close(fd); + return 0; +} + +/* https://stackoverflow.com/a/23898449 */ +static void scan_hex(const char* str, uint8_t* bytes, size_t blen) +{ + uint8_t pos; + uint8_t idx0; + uint8_t idx1; + + const uint8_t hashmap[] = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ + 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */ + 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* @ABCDEFG */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* HIJKLMNO */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* PQRSTUVW */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* XYZ[\]^_ */ + 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, /* `abcdefg */ + }; + + for (pos = 0; ((pos < (blen*2)) && (pos < XSTRLEN(str))); pos += 2) + { + idx0 = (uint8_t)(str[pos+0] & 0x1F) ^ 0x10; + idx1 = (uint8_t)(str[pos+1] & 0x1F) ^ 0x10; + bytes[pos/2] = (uint8_t)(hashmap[idx0] << 4) | hashmap[idx1]; + } +} + +static void die(int ret) +{ + fprintf(stderr, "Usage: aesgcm <-e|-d> <88|96 char hex-string 'IV | key'>\n"); + exit(ret); +} + +int main(int argc, char **argv) +{ + int ret = 0, err, arg, direction, res, tmp; + size_t keylen; + uint8_t keybuf[48] = {0}; + char *out = NULL; + const char *mode, *in_file, *out_file, *key_string; + unsigned long ivlen; + + if (argc < 5) die(__LINE__); + + arg = 1; + mode = argv[arg++]; + in_file = argv[arg++]; + out_file = argv[arg++]; + key_string = argv[arg++]; + + if(strcmp(mode, "-d") == 0) direction = GCM_DECRYPT; + else if(strcmp(mode, "-e") == 0) direction = GCM_ENCRYPT; + else die(__LINE__); + + if (fsize(in_file) <= 0) die(__LINE__); + + keylen = XSTRLEN(key_string); + if (keylen != 88 && keylen != 96) die(__LINE__); + + scan_hex(key_string, keybuf, keylen/2); + + register_all_ciphers(); + + if(asprintf(&out, "%s-XXXXXX", out_file) < 0) die(__LINE__); + if((tmp = mkstemp(out)) == -1) { + ret = __LINE__; + goto cleanup; + } + close(tmp); + ivlen = keylen/2 - 32; + if((err = gcm_file(find_cipher("aes"), &keybuf[ivlen], 32, keybuf, ivlen, NULL, 0, in_file, out, 16, direction, &res)) != CRYPT_OK) { + fprintf(stderr, "boooh %s\n", error_to_string(err)); + ret = __LINE__; + goto cleanup; + } + + if(res != 1) { + ret = __LINE__; + } + else + { + if (mv(out, out_file) != 0) ret = __LINE__; + } + +cleanup: + if(ret != 0) unlink(out); + free(out); + + + return ret; +} diff --git a/deps/libtomcrypt/demos/constants.c b/deps/libtomcrypt/demos/constants.c new file mode 100644 index 0000000..8f8f4aa --- /dev/null +++ b/deps/libtomcrypt/demos/constants.c @@ -0,0 +1,77 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt.h" + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L +#include +#else +#define basename(x) x +#endif + +/** + @file demo_crypt_constants.c + + Demo how to get various constants to dynamic languages + like Python + + Larry Bugbee, February 2013 +*/ + +static void s_print_line(const char* cmd, const char* desc) +{ + printf(" %-16s - %s\n", cmd, desc); +} + +int main(int argc, char **argv) +{ + if (argc == 1) { + /* given a specific constant name, get and print its value */ + char name[] = "CTR_COUNTER_BIG_ENDIAN"; + int value; + char *names_list; + unsigned int names_list_len; + + if (crypt_get_constant(name, &value) != 0) exit(EXIT_FAILURE); + printf("\n %s is %d \n\n", name, value); + + /* get and print the length of the names (and values) list */ + + if (crypt_list_all_constants(NULL, &names_list_len) != 0) exit(EXIT_FAILURE); + printf(" need to allocate %u bytes \n\n", names_list_len); + + /* get and print the names (and values) list */ + if ((names_list = malloc(names_list_len)) == NULL) exit(EXIT_FAILURE); + if (crypt_list_all_constants(names_list, &names_list_len) != 0) exit(EXIT_FAILURE); + printf(" supported constants:\n\n%s\n\n", names_list); + free(names_list); + } else if (argc == 2) { + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { + char* base = strdup(basename(argv[0])); + printf("Usage: %s [-a] [-s name]\n\n", base); + s_print_line("", "The old behavior of the demo"); + s_print_line("-a", "Only lists all constants"); + s_print_line("-s name", "List a single constant given as argument"); + s_print_line("-h", "The help you're looking at"); + free(base); + } else if (strcmp(argv[1], "-a") == 0) { + char *names_list; + unsigned int names_list_len; + /* get and print the length of the names (and values) list */ + if (crypt_list_all_constants(NULL, &names_list_len) != 0) exit(EXIT_FAILURE); + /* get and print the names (and values) list */ + if ((names_list = malloc(names_list_len)) == NULL) exit(EXIT_FAILURE); + if (crypt_list_all_constants(names_list, &names_list_len) != 0) exit(EXIT_FAILURE); + printf("%s\n", names_list); + free(names_list); + } + } else if (argc == 3) { + if (strcmp(argv[1], "-s") == 0) { + int value; + if (crypt_get_constant(argv[2], &value) != 0) exit(EXIT_FAILURE); + printf("%s,%u\n", argv[2], value); + } + } + + return 0; +} + diff --git a/deps/libtomcrypt/demos/demo_dynamic.py b/deps/libtomcrypt/demos/demo_dynamic.py new file mode 100644 index 0000000..50301c1 --- /dev/null +++ b/deps/libtomcrypt/demos/demo_dynamic.py @@ -0,0 +1,309 @@ + + +""" + demo_dynamic.py v2b + + This program demonstrates Python's use of the dynamic + language support additions to LTC, namely access to LTC + constants, struct and union sizes, and the binding of a + math package to LTC. Also provided are simple code + fragments to illustrate how one might write a Python + wrapper for LTC and how an app might call the wrapper. + This or a similar model should work for Ruby and other + dynamic languages. + + This instance uses Python's ctypes and requires a single + .dylib linking together LTC and a math library. Building + a single .dylib is needed because LTC wants a fairly tight + relationship between itself and the mathlib. (ctypes can + load multiple .dylibs, but it does not support this level + of tight coupling between otherwise independent libraries.) + + My .dylib was created on OSX/macOS with the following: + sudo make -j5 -f makefile.shared \ + CFLAGS="-DUSE_TFM -DTFM_DESC -I/usr/local/include" \ + EXTRALIBS=/usr/local/lib/libtfm.a install + + For python 2.7.12 on Ubuntu Xenial the following worked for + me (without MPI support): + sudo make -f makefile.shared install PREFIX="/usr" + + Reminder: you don't need to bind in a math library unless + you are going to use LTC functions that need a + mathlib. For example, public key crypto requires + a mathlib; hashing and symmetric encryption do not. + + ------ + + This code was originally written for Python 2.7 with the + ctypes standard library. This version is modified to run + under both Python 2.7 and 3.6. + + Arguably the biggest change for Python3 has to do with + strings. Under Python2, native strings are ASCII bytes and + passing them to LTC is natural and requires no conversion. + Under Python3 all native strings are Unicode which requires + they be converted to bytes before use by LTC. + + Note the following for Python3. + - ASCII keys, IVs and other string arguments must be + 'bytes'. Define them with a 'b' prefix or convert + via the 'bytes()' function. + - "strings" returned from LTC are bytes and conversion + to Unicode might be necessary for proper printing. + If so, use .decode('utf-8'). + - The Python2 'print' statement becomes a function in + Python3 which requires parenthesis, eg. 'print()'. + + NB: Unicode is achieved under Python2 by either defining + a Unicode string with a 'u' prefix or passing ASCII + strings thru the 'unicode()' function. + + Larry Bugbee + March 2014 v1 + August 2017 v2b + +""" + + +import sys +from ctypes import * +from ctypes.util import find_library + +# switches to enable/disable selected output +SHOW_ALL_CONSTANTS = True +SHOW_ALL_SIZES = True +SHOW_SELECTED_CONSTANTS = True +SHOW_SELECTED_SIZES = True +SHOW_BUILD_OPTIONS_ALGS = True +SHOW_SHA256_EXAMPLE = True +SHOW_CHACHA_EXAMPLE = True + +print(' ') +print(' demo_dynamic.py') + +def inprint(s, indent=0): + "prints strings indented, including multline strings" + for line in s.split('\n'): + print(' '*indent + line) + +#------------------------------------------------------------------------------- +# load the .dylib + +libname = 'tomcrypt' +libpath = find_library(libname) +print(' ') +print(' path to library %s: %s' % (libname, libpath)) + +LTC = cdll.LoadLibrary(libpath) +print(' loaded: %s' % LTC) +print(' ') + + +#------------------------------------------------------------------------------- +# get list of all supported constants followed by a list of all +# supported sizes. One alternative: these lists may be parsed +# and used as needed. + +if SHOW_ALL_CONSTANTS: + print('-'*60) + print(' all supported constants and their values:') + + # get size to allocate for constants output list + str_len = c_int(0) + ret = LTC.crypt_list_all_constants(None, byref(str_len)) + print(' need to allocate %d bytes to build list \n' % str_len.value) + + # allocate that size and get (name, size) pairs, each pair + # separated by a newline char. + names_sizes = c_buffer(str_len.value) + ret = LTC.crypt_list_all_constants(names_sizes, byref(str_len)) + print(names_sizes.value.decode("utf-8")) + print(' ') + + +if SHOW_ALL_SIZES: + print('-'*60) + print(' all supported sizes:') + + # get size to allocate for sizes output list + str_len = c_int(0) + ret = LTC.crypt_list_all_sizes(None, byref(str_len)) + print(' need to allocate %d bytes to build list \n' % str_len.value) + + # allocate that size and get (name, size) pairs, each pair + # separated by a newline char. + names_sizes = c_buffer(str_len.value) + ret = LTC.crypt_list_all_sizes(names_sizes, byref(str_len)) + print(names_sizes.value.decode("utf-8")) + print(' ') + + +#------------------------------------------------------------------------------- +# get individually named constants and sizes + +if SHOW_SELECTED_CONSTANTS: + print('-'*60) + print('\n selected constants:') + + names = [ + b'ENDIAN_LITTLE', + b'ENDIAN_64BITWORD', + b'PK_PUBLIC', + b'LTC_MILLER_RABIN_REPS', + b'CTR_COUNTER_BIG_ENDIAN', + ] + for name in names: + const_value = c_int(0) + rc = LTC.crypt_get_constant(name, byref(const_value)) + value = const_value.value + print(' %-25s %d' % (name.decode("utf-8"), value)) + print(' ') + +if SHOW_SELECTED_SIZES: + print('-'*60) + print('\n selected sizes:') + + names = [ + b'rijndael_key', + b'rsa_key', + b'symmetric_CTR', + b'twofish_key', + b'ecc_point', + b'gcm_state', + b'sha512_state', + ] + for name in names: + size_value = c_int(0) + rc = LTC.crypt_get_size(name, byref(size_value)) + value = size_value.value + print(' %-25s %d' % (name.decode("utf-8"), value)) + print(' ') + + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +# LibTomCrypt exposes one interesting string that can be accessed +# via Python's ctypes module, "crypt_build_settings", which +# provides a list of this build's compiler switches and supported +# algorithms. If someday LTC exposes other interesting strings, +# they can be found with: +# nm /usr/local/lib/libtomcrypt.dylib | grep " D " + +def get_named_string(lib, name): + return c_char_p.in_dll(lib, name).value.decode("utf-8") + +if SHOW_BUILD_OPTIONS_ALGS: + print('-'*60) + print('This is a string compiled into LTC showing compile') + print('options and algorithms supported by this build \n') +# print(get_named_string(LTC, 'crypt_build_settings')) + inprint(get_named_string(LTC, 'crypt_build_settings'), 4) + + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +# here is an example of how Python code can be written to access +# LTC's implementation of SHA256 and ChaCha, + +# - - - - - - - - - - - - - +# definitions + +from binascii import hexlify, unhexlify + +def _err2str(err): + # define return type + errstr = LTC.error_to_string + errstr.restype = c_char_p + # get and return err string + return errstr(err) + +def _get_size(name): + size = c_int(0) + rc = LTC.crypt_get_size(bytes(name), byref(size)) + if rc != 0: + raise Exception('LTC.crypt_get_size(%s) rc = %d' % (name, rc)) + return size.value + +def _get_constant(name): + constant = c_int(0) + rc = LTC.crypt_get_constant(bytes(name), byref(constant)) + if rc != 0: + raise Exception('LTC.crypt_get_constant(%s) rc = %d' % (name, rc)) + return constant.value + +CRYPT_OK = _get_constant(b'CRYPT_OK') + +class SHA256(object): + def __init__(self): + self.state = c_buffer(_get_size(b'sha256_state')) + LTC.sha256_init(byref(self.state)) + def update(self, data): + LTC.sha256_process(byref(self.state), data, len(data)) + def digest(self): + md = c_buffer(32) + LTC.sha256_done(byref(self.state), byref(md)) + return md.raw + +# - - - - - - - - - - - - - +# a SHA256 app fragment + +if SHOW_SHA256_EXAMPLE: + print('-'*60) + data = b'hello world' # we want bytes, not Unicode + + sha256 = SHA256() + sha256.update(data) + md = sha256.digest() + + template = '\n the SHA256 digest for "%s" is %s \n' + print(template % (data, hexlify(md))) + +class ChaCha(object): + def __init__(self, key, rounds): + self.state = c_buffer(_get_size(b'chacha_state')) + self.counter = c_uint(1) + err = LTC.chacha_setup(byref(self.state), key, len(key), rounds) + if err != CRYPT_OK: + raise Exception('LTC.chacha_setup(), err = %d, "%s"' % (err, _err2str(err))) + def set_iv32(self, iv): + err = LTC.chacha_ivctr32(byref(self.state), iv, len(iv), self.counter) + if err != CRYPT_OK: + raise Exception('LTC.chacha_ivctr32(), err = %d, "%s"' % (err, _err2str(err))) + def crypt(self, datain): + dataout = c_buffer(len(datain)) + err = LTC.chacha_crypt(byref(self.state), datain, len(datain), byref(dataout)) + if err != CRYPT_OK: + raise Exception('LTC.chacha_crypt(), err = %d, "%s"' % (err, _err2str(err))) + return dataout.raw + +# - - - - - - - - - - - - - +# a ChaCha app fragment + +if SHOW_CHACHA_EXAMPLE: + print('-'*60) + key = b'hownowbrowncow\x00\x00' # exactly 16 or 32 bytes + rounds = 12 # common values: 8, 12, 20 + iv = b'123456789012' # exactly 12 bytes + plain = b'Kilroy was here, there, and everywhere!' + + cha = ChaCha(key, rounds) + cha.set_iv32(iv) + cipher = cha.crypt(plain) + + template = '\n ChaCha%d ciphertext for "%s" is "%s"' + print(template % (rounds, plain, hexlify(cipher))) + + cha.set_iv32(iv) # reset to decrypt + decrypted = cha.crypt(cipher) + + template = ' ChaCha%d decoded text for "%s" is "%s" \n' + print(template % (rounds, plain, decrypted.decode("utf-8"))) + +# Footnote: Keys should be erased fm memory as soon as possible after use, +# and that includes Python. For a tip on how to do that in Python, see +# http://buggywhip.blogspot.com/2010/12/erase-keys-and-credit-card-numbers-in.html + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- diff --git a/deps/libtomcrypt/demos/gcm-file/gcm_file.c b/deps/libtomcrypt/demos/gcm-file/gcm_file.c new file mode 100644 index 0000000..21fd495 --- /dev/null +++ b/deps/libtomcrypt/demos/gcm-file/gcm_file.c @@ -0,0 +1,84 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt.h" + +/** + @file gcm_file.c + GCM process a file, Steffen Jaeckel +*/ + +#ifdef LTC_GCM_MODE +#ifndef LTC_NO_FILE + +/** + Process a file. + + c.f. gcm_filehandle() for basic documentation. + + It is possible, that in error-cases the 'out' file + will be created and after the error occurred it will + be removed again. + + @param cipher Index of cipher to use + @param key The secret key + @param keylen The length of the secret key + @param IV The initial vector + @param IVlen The length of the initial vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param in The input file + @param out The output file + @param taglen The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @param res [out] Result of the operation, 1==valid, 0==invalid + @return CRYPT_OK on success + */ +int gcm_file( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + const char *in, + const char *out, + unsigned long taglen, + int direction, + int *res) +{ + int err; + FILE *f_in = NULL, *f_out = NULL; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(res != NULL); + + *res = 0; + + f_in = fopen(in, "rb"); + if (f_in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + f_out = fopen(out, "w+b"); + if (f_out == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + err = gcm_filehandle(cipher, key, keylen, IV, IVlen, adata, adatalen, f_in, f_out, taglen, direction, res); + +LBL_ERR: + if (f_out != NULL && fclose(f_out) != 0) { + err = CRYPT_ERROR; + } + if (*res != 1) { + remove(out); + } + if (f_in != NULL && fclose(f_in) != 0) { + err = CRYPT_ERROR; + } + + return err; +} +#endif +#endif + diff --git a/deps/libtomcrypt/demos/gcm-file/gcm_filehandle.c b/deps/libtomcrypt/demos/gcm-file/gcm_filehandle.c new file mode 100644 index 0000000..11c55a6 --- /dev/null +++ b/deps/libtomcrypt/demos/gcm-file/gcm_filehandle.c @@ -0,0 +1,192 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt.h" + +/** + @file gcm_filehandle.c + GCM process a filehandle, Steffen Jaeckel +*/ + +#ifdef LTC_GCM_MODE +#ifndef LTC_NO_FILE + +#if defined(_MSC_VER) +#define ftruncate _chsize +#else +#include +#endif + +/** + Process a filehandle. + + This uses the widely established scheme where the tag is appended + to the ciphertext. + + encrypted_file = aesgcm(plain_file) | aesgcm_tag(plain_file) + + Depending on 'direction' this function does: + + Encrypt file 'in' to 'out' and append the tag of length 'taglen' + to 'out'. + + or + + Decrypt file 'in' to 'out' and check the tag of length 'taglen' + and strip the tag from 'in'. + + In error-cases 'out' will be zeroed out first and then truncated to + a length of 0. + + @param cipher Index of cipher to use + @param key The secret key + @param keylen The length of the secret key + @param IV The initial vector + @param IVlen The length of the initial vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param in The input file + @param out The output file + @param taglen The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @param res [out] Result of the operation, 1==valid, 0==invalid + @return CRYPT_OK on success + */ +int gcm_filehandle( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + FILE *in, + FILE *out, + unsigned long taglen, + int direction, + int *res) +{ + void *orig; + gcm_state *gcm; + int err; + unsigned char *buf, tag[16]; + size_t x, tot_data; + unsigned long tag_len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(res != NULL); + + *res = 0; + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifndef LTC_GCM_TABLES_SSE2 + orig = gcm = XMALLOC(sizeof(*gcm)); +#else + orig = gcm = XMALLOC(sizeof(*gcm) + 16); +#endif + if (gcm == NULL) { + return CRYPT_MEM; + } + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + XFREE(gcm); + return CRYPT_MEM; + } + + /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations + * note that we only modify gcm and keep orig intact. This code is not portable + * but again it's only for SSE2 anyways, so who cares? + */ +#ifdef LTC_GCM_TABLES_SSE2 + if ((unsigned long)gcm & 15) { + gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15))); + } +#endif + + if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) { + goto LBL_ERR; + } + + fseek(in, 0, SEEK_END); + tot_data = ftell(in); + if (direction == GCM_DECRYPT) { + tot_data -= taglen; + } + rewind(in); + do { + x = MIN(tot_data, LTC_FILE_READ_BUFSIZE); + x = fread(buf, 1, x, in); + tot_data -= x; + if ((err = gcm_process(gcm, buf, (unsigned long)x, buf, direction)) != CRYPT_OK) { + goto LBL_CLEANBUF; + } + if(fwrite(buf, 1, x, out) != x) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + tag_len = taglen; + if ((err = gcm_done(gcm, tag, &tag_len)) != CRYPT_OK) { + goto LBL_CLEANBUF; + } + if (tag_len != taglen) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + if (direction == GCM_DECRYPT) { + x = fread(buf, 1, taglen, in); + if (x != taglen) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + if (XMEM_NEQ(buf, tag, taglen) == 0) { + *res = 1; + } + } else { + if(fwrite(tag, 1, taglen, out) != taglen) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + *res = 1; + } + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); + zeromem(tag, sizeof(tag)); +LBL_ERR: +#ifdef LTC_CLEAN_STACK +#ifndef LTC_GCM_TABLES_SSE2 + zeromem(orig, sizeof(*gcm)); +#else + zeromem(orig, sizeof(*gcm) + 16); +#endif +#endif + if(*res == 0) { + x = ftell(out); + rewind(out); + while((size_t)ftell(out) < x) { + fwrite(buf, 1, LTC_FILE_READ_BUFSIZE, out); + } + if(ftruncate(fileno(out), 0)) { + /* well, what shall we do here... */ + } + } + fflush(out); + + XFREE(buf); + XFREE(orig); + + return err; +} +#endif +#endif + diff --git a/deps/libtomcrypt/demos/hashsum.c b/deps/libtomcrypt/demos/hashsum.c new file mode 100644 index 0000000..ebf4c4a --- /dev/null +++ b/deps/libtomcrypt/demos/hashsum.c @@ -0,0 +1,290 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * Written by Daniel Richards 6/7/2002 + * hash.c: This app uses libtomcrypt to hash either stdin or a file + * This file is Public Domain. No rights are reserved. + * Compile with 'gcc hashsum.c -o hashsum -ltomcrypt' + * This example isn't really big enough to warrent splitting into + * more functions ;) +*/ + +#include + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L +#include +#else +#define basename(x) x +#endif + +#if !defined(PATH_MAX) && defined(_MSC_VER) +#include +#define PATH_MAX MAX_PATH +#endif + +/* thanks http://stackoverflow.com/a/8198009 */ +#define s_base(x) ((x >= '0' && x <= '9') ? '0' : \ + (x >= 'a' && x <= 'f') ? 'a' - 10 : \ + (x >= 'A' && x <= 'F') ? 'A' - 10 : \ + '\255') +#define HEXOF(x) (x - s_base(x)) + +static char* hashsum; + +static void cleanup(void) +{ + free(hashsum); +} + +static void die(int status) +{ + unsigned long w, x; + FILE* o = status == EXIT_SUCCESS ? stdout : stderr; + fprintf(o, "usage: %s -a algorithm [-c] [file...]\n\n", hashsum); + fprintf(o, "\t-c\tCheck the hash(es) of the file(s) written in [file].\n"); + fprintf(o, "\t\t(-a not required)\n"); + fprintf(o, "\nAlgorithms:\n\t"); + w = 0; + for (x = 0; hash_descriptor[x].name != NULL; x++) { + w += fprintf(o, "%-14s", hash_descriptor[x].name); + if (w >= 70) { + fprintf(o, "\n\t"); + w = 0; + } + } + if (w != 0) fprintf(o, "\n"); + exit(status); +} + +static void printf_hex(unsigned char* hash_buffer, unsigned long w) +{ + unsigned long x; + for (x = 0; x < w; x++) { + printf("%02x",hash_buffer[x]); + } +} + +static void check_file(int argn, int argc, char **argv) +{ + int err, failed, invalid; + unsigned char is_buffer[MAXBLOCKSIZE], should_buffer[MAXBLOCKSIZE]; + char buf[PATH_MAX + (MAXBLOCKSIZE * 3)]; + /* iterate through all files */ + while(argn < argc) { + char* s; + FILE* f = fopen(argv[argn], "rb"); + if(f == NULL) { + int n = snprintf(buf, sizeof(buf), "%s: %s", hashsum, argv[argn]); + if (n > 0 && n < (int)sizeof(buf)) + perror(buf); + else + perror(argv[argn]); + exit(EXIT_FAILURE); + } + failed = 0; + invalid = 0; + /* read the file line by line */ + while((s = fgets(buf, sizeof(buf), f)) != NULL) + { + int tries, n; + unsigned long hash_len, w, x; + char* space = strstr(s, " "); + + /* skip lines with comments */ + if (buf[0] == '#') continue; + + if (space == NULL) { + fprintf(stderr, "%s: no properly formatted checksum lines found\n", hashsum); + goto ERR; + } + + hash_len = space - s; + hash_len /= 2; + + if (hash_len > sizeof(should_buffer)) { + fprintf(stderr, "%s: hash too long\n", hashsum); + goto ERR; + } + + /* convert the hex-string back to binary */ + for (x = 0; x < hash_len; ++x) { + should_buffer[x] = HEXOF(s[x*2]) << 4 | HEXOF(s[x*2 + 1]); + } + + space++; + if (*space != '*') { + fprintf(stderr, "%s: unsupported input mode '%c'\n", hashsum, *space); + goto ERR; + } + space++; + + for (n = 0; n < (buf + sizeof(buf)) - space; ++n) { + if(iscntrl((int)space[n])) { + space[n] = '\0'; + break; + } + } + + /* try all hash algorithms that have the appropriate hash size */ + tries = 0; + for (x = 0; hash_descriptor[x].name != NULL; ++x) { + if (hash_descriptor[x].hashsize == hash_len) { + tries++; + w = sizeof(is_buffer); + if ((err = hash_file(x, space, is_buffer, &w)) != CRYPT_OK) { + fprintf(stderr, "%s: File hash error: %s: %s\n", hashsum, space, error_to_string(err)); +ERR: + fclose(f); + exit(EXIT_FAILURE); + } + if(XMEMCMP(should_buffer, is_buffer, w) == 0) { + printf("%s: OK\n", space); + break; + } + } + } /* for */ + if (hash_descriptor[x].name == NULL) { + if(tries > 0) { + printf("%s: FAILED\n", space); + failed++; + } + else { + invalid++; + } + } + } /* while */ + fclose(f); + if(invalid) { + fprintf(stderr, "%s: WARNING: %d %s is improperly formatted\n", hashsum, invalid, invalid > 1?"lines":"line"); + } + if(failed) { + fprintf(stderr, "%s: WARNING: %d computed %s did NOT match\n", hashsum, failed, failed > 1?"checksums":"checksum"); + } + argn++; + } + exit(EXIT_SUCCESS); +} + +int main(int argc, char **argv) +{ + int idxs[TAB_SIZE], idx, check, y, z, err, argn; + unsigned long w, x; + unsigned char hash_buffer[MAXBLOCKSIZE]; + + hashsum = strdup(basename(argv[0])); + atexit(cleanup); + + /* You need to register algorithms before using them */ + register_all_ciphers(); + register_all_hashes(); + if (argc > 1 && (strcmp("-h", argv[1]) == 0 || strcmp("--help", argv[1]) == 0)) { + die(EXIT_SUCCESS); + } + if (argc < 3) { + die(EXIT_FAILURE); + } + + for (x = 0; x < sizeof(idxs)/sizeof(idxs[0]); ++x) { + idxs[x] = -2; + } + argn = 1; + check = 0; + idx = 0; + + while(argn < argc){ + if(strcmp("-a", argv[argn]) == 0) { + argn++; + if(argn < argc) { + idxs[idx] = find_hash(argv[argn]); + if (idxs[idx] == -1) { + struct { + const char* is; + const char* should; + } shasum_compat[] = + { +#ifdef LTC_SHA1 + { "1", sha1_desc.name }, +#endif +#ifdef LTC_SHA224 + { "224", sha224_desc.name }, +#endif +#ifdef LTC_SHA256 + { "256", sha256_desc.name }, +#endif +#ifdef LTC_SHA384 + { "384", sha384_desc.name }, +#endif +#ifdef LTC_SHA512 + { "512", sha512_desc.name }, +#endif +#ifdef LTC_SHA512_224 + { "512224", sha512_224_desc.name }, +#endif +#ifdef LTC_SHA512_256 + { "512256", sha512_256_desc.name }, +#endif + { NULL, NULL } + }; + for (x = 0; shasum_compat[x].is != NULL; ++x) { + if(XSTRCMP(shasum_compat[x].is, argv[argn]) == 0) { + idxs[idx] = find_hash(shasum_compat[x].should); + break; + } + } + } + if (idxs[idx] == -1) { + fprintf(stderr, "%s: Unrecognized algorithm\n", hashsum); + die(EXIT_FAILURE); + } + idx++; + if ((size_t)idx >= sizeof(idxs)/sizeof(idxs[0])) { + fprintf(stderr, "%s: Too many '-a' options chosen\n", hashsum); + die(EXIT_FAILURE); + } + argn++; + continue; + } + else { + die(EXIT_FAILURE); + } + } + if(strcmp("-c", argv[argn]) == 0) { + check = 1; + argn++; + continue; + } + break; + } + + if (check == 1) { + check_file(argn, argc, argv); + } + + if (argc == argn) { + w = sizeof(hash_buffer); + if ((err = hash_filehandle(idxs[0], stdin, hash_buffer, &w)) != CRYPT_OK) { + fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err)); + return EXIT_FAILURE; + } else { + for (x = 0; x < w; x++) { + printf("%02x",hash_buffer[x]); + } + printf(" *-\n"); + } + } else { + for (z = argn; z < argc; z++) { + for (y = 0; y < idx; ++y) { + w = sizeof(hash_buffer); + if ((err = hash_file(idxs[y],argv[z],hash_buffer,&w)) != CRYPT_OK) { + fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err)); + return EXIT_FAILURE; + } else { + printf_hex(hash_buffer, w); + printf(" *%s\n", argv[z]); + } + } + } + } + return EXIT_SUCCESS; +} diff --git a/deps/libtomcrypt/demos/ltcrypt.c b/deps/libtomcrypt/demos/ltcrypt.c new file mode 100644 index 0000000..a4be30e --- /dev/null +++ b/deps/libtomcrypt/demos/ltcrypt.c @@ -0,0 +1,195 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* encrypt V1.1 Fri Oct 18 04:28:03 NZDT 2002 */ +/* File de/encryption, using libtomcrypt */ +/* Written by Daniel Richards */ +/* Help from Tom St Denis with various bits */ +/* This code is public domain, no rights reserved. */ +/* Encrypts by default, -d flag enables decryption */ +/* ie: ./encrypt blowfish story.txt story.ct */ +/* ./encrypt -d blowfish story.ct story.pt */ + +#include + +static int LTC_NORETURN usage(char *name) +{ + int x; + + printf("Usage encrypt: %s cipher infile outfile\n", name); + printf("Usage decrypt: %s -d cipher infile outfile\n", name); + printf("Usage test: %s -t cipher\nCiphers:\n", name); + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + printf("%s\n",cipher_descriptor[x].name); + } + exit(1); +} + +int main(int argc, char *argv[]) +{ + unsigned char plaintext[512],ciphertext[512]; + unsigned char tmpkey[512], key[MAXBLOCKSIZE], IV[MAXBLOCKSIZE]; + unsigned char inbuf[512]; /* i/o block size */ + unsigned long outlen, y, ivsize, x, decrypt; + symmetric_CTR ctr; + int cipher_idx, hash_idx, ks; + char *infile, *outfile, *cipher; + prng_state prng; + FILE *fdin, *fdout; + int err; + + /* register algs, so they can be printed */ + register_all_ciphers(); + register_all_hashes(); + register_all_prngs(); + + if (argc < 4) { + if ((argc > 2) && (!strcmp(argv[1], "-t"))) { + cipher = argv[2]; + cipher_idx = find_cipher(cipher); + if (cipher_idx == -1) { + printf("Invalid cipher %s entered on command line.\n", cipher); + exit(-1); + } /* if */ + if (cipher_descriptor[cipher_idx].test) + { + if (cipher_descriptor[cipher_idx].test() != CRYPT_OK) + { + printf("Error when testing cipher %s.\n", cipher); + exit(-1); + } + else + { + printf("Testing cipher %s succeeded.\n", cipher); + exit(0); + } /* if ... else */ + } /* if */ + } + return usage(argv[0]); + } + + if (!strcmp(argv[1], "-d")) { + decrypt = 1; + cipher = argv[2]; + infile = argv[3]; + outfile = argv[4]; + } else { + decrypt = 0; + cipher = argv[1]; + infile = argv[2]; + outfile = argv[3]; + } + + /* file handles setup */ + fdin = fopen(infile,"rb"); + if (fdin == NULL) { + perror("Can't open input for reading"); + exit(-1); + } + + fdout = fopen(outfile,"wb"); + if (fdout == NULL) { + perror("Can't open output for writing"); + exit(-1); + } + + cipher_idx = find_cipher(cipher); + if (cipher_idx == -1) { + printf("Invalid cipher entered on command line.\n"); + exit(-1); + } + + hash_idx = find_hash("sha256"); + if (hash_idx == -1) { + printf("LTC_SHA256 not found...?\n"); + exit(-1); + } + + ivsize = cipher_descriptor[cipher_idx].block_length; + ks = hash_descriptor[hash_idx].hashsize; + if (cipher_descriptor[cipher_idx].keysize(&ks) != CRYPT_OK) { + printf("Invalid keysize???\n"); + exit(-1); + } + + printf("\nEnter key: "); + if(fgets((char *)tmpkey,sizeof(tmpkey), stdin) == NULL) + exit(-1); + outlen = sizeof(key); + if ((err = hash_memory(hash_idx,tmpkey,XSTRLEN((char *)tmpkey),key,&outlen)) != CRYPT_OK) { + printf("Error hashing key: %s\n", error_to_string(err)); + exit(-1); + } + + if (decrypt) { + /* Need to read in IV */ + if (fread(IV,1,ivsize,fdin) != ivsize) { + printf("Error reading IV from input.\n"); + exit(-1); + } + + if ((err = ctr_start(cipher_idx,IV,key,ks,0,CTR_COUNTER_LITTLE_ENDIAN,&ctr)) != CRYPT_OK) { + printf("ctr_start error: %s\n",error_to_string(err)); + exit(-1); + } + + /* IV done */ + do { + y = fread(inbuf,1,sizeof(inbuf),fdin); + + if ((err = ctr_decrypt(inbuf,plaintext,y,&ctr)) != CRYPT_OK) { + printf("ctr_decrypt error: %s\n", error_to_string(err)); + exit(-1); + } + + if (fwrite(plaintext,1,y,fdout) != y) { + printf("Error writing to file.\n"); + exit(-1); + } + } while (y == sizeof(inbuf)); + fclose(fdin); + fclose(fdout); + + } else { /* encrypt */ + /* Setup yarrow for random bytes for IV */ + + if ((err = rng_make_prng(128, find_prng("yarrow"), &prng, NULL)) != CRYPT_OK) { + printf("Error setting up PRNG, %s\n", error_to_string(err)); + } + + /* You can use rng_get_bytes on platforms that support it */ + /* x = rng_get_bytes(IV,ivsize,NULL);*/ + x = yarrow_read(IV,ivsize,&prng); + if (x != ivsize) { + printf("Error reading PRNG for IV required.\n"); + exit(-1); + } + + if (fwrite(IV,1,ivsize,fdout) != ivsize) { + printf("Error writing IV to output.\n"); + exit(-1); + } + + if ((err = ctr_start(cipher_idx,IV,key,ks,0,CTR_COUNTER_LITTLE_ENDIAN,&ctr)) != CRYPT_OK) { + printf("ctr_start error: %s\n",error_to_string(err)); + exit(-1); + } + + do { + y = fread(inbuf,1,sizeof(inbuf),fdin); + + if ((err = ctr_encrypt(inbuf,ciphertext,y,&ctr)) != CRYPT_OK) { + printf("ctr_encrypt error: %s\n", error_to_string(err)); + exit(-1); + } + + if (fwrite(ciphertext,1,y,fdout) != y) { + printf("Error writing to output.\n"); + exit(-1); + } + } while (y == sizeof(inbuf)); + fclose(fdout); + fclose(fdin); + } + return 0; +} diff --git a/deps/libtomcrypt/demos/openssl-enc.c b/deps/libtomcrypt/demos/openssl-enc.c new file mode 100644 index 0000000..b4f7778 --- /dev/null +++ b/deps/libtomcrypt/demos/openssl-enc.c @@ -0,0 +1,358 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * Demo to do the rough equivalent of: + * + * openssl enc -aes-256-cbc -pass pass:foobar -in infile -out outfile -p + * + * Compilation: + * + * $(CC) -I /path/to/headers -L .../libs \ + * -o openssl-enc \ + * openssl-enc.c -ltomcrypt + * + * Usage: + * + * ./openssl-enc infile outfile "passphrase" [salt] + * + * If provided, the salt must be EXACTLY a 16-char hex string. + * + * Demo is an example of: + * + * - (When decrypting) yanking salt out of the OpenSSL "Salted__..." header + * - OpenSSL-compatible key derivation (in OpenSSL's modified PKCS#5v1 approach) + * - Grabbing an Initialization Vector from the key generator + * - Performing simple block encryption using AES + * - PKCS#7-type padding (which hopefully can get ripped out of this demo and + * made a libtomcrypt thing someday). + * + * This program is free for all purposes without any express guarantee it + * works. If you really want to see a license here, assume the WTFPL :-) + * + * BJ Black, bblack@barracuda.com, https://wjblack.com + * + * BUGS: + * Passing a password on a command line is a HORRIBLE idea. Don't use + * this program for serious work! + */ + +#include + +#ifndef LTC_RIJNDAEL +#error Cannot compile this demo; Rijndael (AES) required +#endif +#ifndef LTC_CBC_MODE +#error Cannot compile this demo; CBC mode required +#endif +#ifndef LTC_PKCS_5 +#error Cannot compile this demo; PKCS5 required +#endif +#ifndef LTC_RNG_GET_BYTES +#error Cannot compile this demo; random generator required +#endif +#ifndef LTC_MD5 +#error Cannot compile this demo; MD5 required +#endif + +/* OpenSSL by default only runs one hash round */ +#define OPENSSL_ITERATIONS 1 +/* Use aes-256-cbc, so 256 bits of key, 128 of IV */ +#define KEY_LENGTH (256>>3) +#define IV_LENGTH (128>>3) +/* PKCS#5v1 requires exactly an 8-byte salt */ +#define SALT_LENGTH 8 +/* The header OpenSSL puts on an encrypted file */ +static char salt_header[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' }; + +#include +#include +#include + +/* A simple way to handle the possibility that a block may increase in size + after padding. */ +union paddable { + unsigned char unpad[1024]; + unsigned char pad[1024+MAXBLOCKSIZE]; +}; + +/* + * Print usage and exit with a bad status (and perror() if any errno). + * + * Input: argv[0] and the error string + * Output: + * Side Effects: print messages and barf (does exit(3)) + */ +void barf(const char *pname, const char *err) +{ + printf("Usage: %s infile outfile passphrase [salt]\n", pname); + printf("\n"); + printf(" # encrypts infile->outfile, random salt\n"); + printf(" %s enc infile outfile \"passphrase\"\n", pname); + printf("\n"); + printf(" # encrypts infile->outfile, salt from cmdline\n"); + printf(" %s enc infile outfile pass 0123456789abcdef\n", pname); + printf("\n"); + printf(" # decrypts infile->outfile, pulls salt from infile\n"); + printf(" %s dec infile outfile pass\n", pname); + printf("\n"); + printf(" # decrypts infile->outfile, salt specified\n"); + printf(" # (don't try to read the salt from infile)\n"); + printf(" %s dec infile outfile pass 0123456789abcdef" + "\n", pname); + printf("\n"); + printf("Application Error: %s\n", err); + if(errno) + perror(" System Error"); + exit(-1); +} + +/* + * Parse a salt value passed in on the cmdline. + * + * Input: string passed in and a buf to put it in (exactly 8 bytes!) + * Output: CRYPT_OK if parsed OK, CRYPT_ERROR if not + * Side Effects: none + */ +int parse_hex_salt(unsigned char *in, unsigned char *out) +{ + int idx; + for(idx=0; idxpad); + if (padding_pad(buf->pad, nb, &length, block_length) != CRYPT_OK) + return 0; + return length; + } else { + length = nb; + if (padding_depad(buf->pad, &length, 0) != CRYPT_OK) + return 0; + return length; + } +} + +/* + * Perform an encrypt/decrypt operation to/from files using AES+CBC+PKCS7 pad. + * Set encrypt to 1 to encrypt, 0 to decrypt. + * + * Input: in/out files, key, iv, and mode + * Output: CRYPT_OK if no error + * Side Effects: bytes slurped from infile, pushed to outfile, fds updated. + */ +int do_crypt(FILE *infd, FILE *outfd, unsigned char *key, unsigned char *iv, + int encrypt) +{ + union paddable inbuf, outbuf; + int cipher, ret; + symmetric_CBC cbc; + size_t nb; + + /* Register your cipher! */ + cipher = register_cipher(&aes_desc); + if(cipher == -1) + return CRYPT_INVALID_CIPHER; + + /* Start a CBC session with cipher/key/val params */ + ret = cbc_start(cipher, iv, key, KEY_LENGTH, 0, &cbc); + if( ret != CRYPT_OK ) + return -1; + + do { + /* Get bytes from the source */ + nb = fread(inbuf.unpad, 1, sizeof(inbuf.unpad), infd); + if(!nb) + return encrypt ? CRYPT_OK : CRYPT_ERROR; + + /* Barf if we got a read error */ + if(ferror(infd)) + return CRYPT_ERROR; + + if(encrypt) { + /* We're encrypting, so pad first (if at EOF) and then + crypt */ + if(feof(infd)) + nb = s_pkcs7_pad(&inbuf, nb, + aes_desc.block_length, 1); + + ret = cbc_encrypt(inbuf.pad, outbuf.pad, nb, &cbc); + if(ret != CRYPT_OK) + return ret; + + } else { + /* We're decrypting, so decrypt and then unpad if at + EOF */ + ret = cbc_decrypt(inbuf.unpad, outbuf.unpad, nb, &cbc); + if( ret != CRYPT_OK ) + return ret; + + if(feof(infd)) + nb = s_pkcs7_pad(&outbuf, nb, + aes_desc.block_length, 0); + if(nb == 0) + /* The file didn't decrypt correctly */ + return CRYPT_ERROR; + + } + + /* Push bytes to outfile */ + if(fwrite(outbuf.unpad, 1, nb, outfd) != nb) + return CRYPT_ERROR; + + } while(!feof(infd)); + + /* Close up */ + cbc_done(&cbc); + + return CRYPT_OK; +} + +/* Convenience macro for the various barfable places below */ +#define BARF(a) { \ + if(infd) fclose(infd); \ + if(outfd) { fclose(outfd); remove(argv[3]); } \ + barf(argv[0], a); \ +} +/* + * The main routine. Mostly validate cmdline params, open files, run the KDF, + * and do the crypt. + */ +int main(int argc, char *argv[]) { + unsigned char salt[SALT_LENGTH]; + FILE *infd = NULL, *outfd = NULL; + int encrypt = -1; + int hash = -1; + int ret; + unsigned char keyiv[KEY_LENGTH + IV_LENGTH]; + unsigned long keyivlen = (KEY_LENGTH + IV_LENGTH); + unsigned char *key, *iv; + + /* Check proper number of cmdline args */ + if(argc < 5 || argc > 6) + BARF("Invalid number of arguments"); + + /* Check proper mode of operation */ + if (!strncmp(argv[1], "enc", 3)) + encrypt = 1; + else if(!strncmp(argv[1], "dec", 3)) + encrypt = 0; + else + BARF("Bad command name"); + + /* Check we can open infile/outfile */ + infd = fopen(argv[2], "rb"); + if(infd == NULL) + BARF("Could not open infile"); + outfd = fopen(argv[3], "wb"); + if(outfd == NULL) + BARF("Could not open outfile"); + + /* Get the salt from wherever */ + if(argc == 6) { + /* User-provided */ + if(parse_hex_salt((unsigned char*) argv[5], salt) != CRYPT_OK) + BARF("Bad user-specified salt"); + } else if(!strncmp(argv[1], "enc", 3)) { + /* Encrypting; get from RNG */ + if(rng_get_bytes(salt, sizeof(salt), NULL) != sizeof(salt)) + BARF("Not enough random data"); + } else { + /* Parse from infile (decrypt only) */ + if(parse_openssl_header(infd, salt) != CRYPT_OK) + BARF("Invalid OpenSSL header in infile"); + } + + /* Fetch the MD5 hasher for PKCS#5 */ + hash = register_hash(&md5_desc); + if(hash == -1) + BARF("Could not register MD5 hash"); + + /* Set things to a sane initial state */ + zeromem(keyiv, sizeof(keyiv)); + key = keyiv + 0; /* key comes first */ + iv = keyiv + KEY_LENGTH; /* iv comes next */ + + /* Run the key derivation from the provided passphrase. This gets us + the key and iv. */ + ret = pkcs_5_alg1_openssl((unsigned char*)argv[4], XSTRLEN(argv[4]), salt, + OPENSSL_ITERATIONS, hash, keyiv, &keyivlen ); + if(ret != CRYPT_OK) + BARF("Could not derive key/iv from passphrase"); + + /* Display the salt/key/iv like OpenSSL cmdline does when -p */ + printf("salt="); dump_bytes(salt, sizeof(salt)); printf("\n"); + printf("key="); dump_bytes(key, KEY_LENGTH); printf("\n"); + printf("iv ="); dump_bytes(iv, IV_LENGTH ); printf("\n"); + + /* If we're encrypting, write the salt header as OpenSSL does */ + if(!strncmp(argv[1], "enc", 3)) { + if(fwrite(salt_header, 1, sizeof(salt_header), outfd) != + sizeof(salt_header) ) + BARF("Error writing salt header to outfile"); + if(fwrite(salt, 1, sizeof(salt), outfd) != sizeof(salt)) + BARF("Error writing salt to outfile"); + } + + /* At this point, the files are open, the salt has been figured out, + and we're ready to pump data through crypt. */ + + /* Do the crypt operation */ + if(do_crypt(infd, outfd, key, iv, encrypt) != CRYPT_OK) + BARF("Error during crypt operation"); + + /* Clean up */ + fclose(infd); fclose(outfd); + return 0; +} diff --git a/deps/libtomcrypt/demos/sizes.c b/deps/libtomcrypt/demos/sizes.c new file mode 100644 index 0000000..9d4bee5 --- /dev/null +++ b/deps/libtomcrypt/demos/sizes.c @@ -0,0 +1,71 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt.h" + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L +#include +#else +#define basename(x) x +#endif +/** + @file demo_crypt_sizes.c + + Demo how to get various sizes to dynamic languages + like Python - Larry Bugbee, February 2013 +*/ + +static void s_print_line(const char* cmd, const char* desc) +{ + printf(" %-16s - %s\n", cmd, desc); +} + +int main(int argc, char **argv) +{ + if (argc == 1) { + /* given a specific size name, get and print its size */ + char name[] = "ltc_hash_descriptor"; + unsigned int size; + char *sizes_list; + unsigned int sizes_list_len; + if (crypt_get_size(name, &size) != 0) exit(EXIT_FAILURE); + printf("\n size of '%s' is %u \n\n", name, size); + + /* get and print the length of the names (and sizes) list */ + if (crypt_list_all_sizes(NULL, &sizes_list_len) != 0) exit(EXIT_FAILURE); + printf(" need to allocate %u bytes \n\n", sizes_list_len); + + /* get and print the names (and sizes) list */ + if ((sizes_list = malloc(sizes_list_len)) == NULL) exit(EXIT_FAILURE); + if (crypt_list_all_sizes(sizes_list, &sizes_list_len) != 0) exit(EXIT_FAILURE); + printf(" supported sizes:\n\n%s\n\n", sizes_list); + free(sizes_list); + } else if (argc == 2) { + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { + char* base = strdup(basename(argv[0])); + printf("Usage: %s [-a] [-s name]\n\n", base); + s_print_line("", "The old behavior of the demo"); + s_print_line("-a", "Only lists all sizes"); + s_print_line("-s name", "List a single size given as argument"); + s_print_line("-h", "The help you're looking at"); + free(base); + } else if (strcmp(argv[1], "-a") == 0) { + char *sizes_list; + unsigned int sizes_list_len; + /* get and print the length of the names (and sizes) list */ + if (crypt_list_all_sizes(NULL, &sizes_list_len) != 0) exit(EXIT_FAILURE); + /* get and print the names (and sizes) list */ + if ((sizes_list = malloc(sizes_list_len)) == NULL) exit(EXIT_FAILURE); + if (crypt_list_all_sizes(sizes_list, &sizes_list_len) != 0) exit(EXIT_FAILURE); + printf("%s\n", sizes_list); + free(sizes_list); + } + } else if (argc == 3) { + if (strcmp(argv[1], "-s") == 0) { + unsigned int size; + if (crypt_get_size(argv[2], &size) != 0) exit(EXIT_FAILURE); + printf("%s,%u\n", argv[2], size); + } + } + return 0; +} diff --git a/deps/libtomcrypt/demos/small.c b/deps/libtomcrypt/demos/small.c new file mode 100644 index 0000000..aa8902c --- /dev/null +++ b/deps/libtomcrypt/demos/small.c @@ -0,0 +1,12 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* small demo app that just includes a cipher/hash/prng */ +#include + +int main(void) +{ + register_cipher(&rijndael_enc_desc); + register_prng(&yarrow_desc); + register_hash(&sha256_desc); + return 0; +} diff --git a/deps/libtomcrypt/demos/timing.c b/deps/libtomcrypt/demos/timing.c new file mode 100644 index 0000000..7dc430c --- /dev/null +++ b/deps/libtomcrypt/demos/timing.c @@ -0,0 +1,1396 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#if defined(_WIN32) + #define PRI64 "I64d" +#else + #define PRI64 "ll" +#endif + +static prng_state yarrow_prng; + +/* timing */ +#define KTIMES 25 +#define TIMES 100000 + +static struct list { + int id; + ulong64 spd1, spd2, avg; +} results[100]; +static int no_results; + +static int sorter(const void *a, const void *b) +{ + const struct list *A, *B; + A = a; + B = b; + if (A->avg < B->avg) return -1; + if (A->avg > B->avg) return 1; + return 0; +} + +static void tally_results(int type) +{ + int x; + + /* qsort the results */ + qsort(results, no_results, sizeof(struct list), &sorter); + + fprintf(stderr, "\n"); + if (type == 0) { + for (x = 0; x < no_results; x++) { + fprintf(stderr, "%-20s: Schedule at %6lu\n", cipher_descriptor[results[x].id].name, (unsigned long)results[x].spd1); + } + } else if (type == 1) { + for (x = 0; x < no_results; x++) { + printf + ("%-20s[%3d]: Encrypt at %5"PRI64"u, Decrypt at %5"PRI64"u\n", cipher_descriptor[results[x].id].name, cipher_descriptor[results[x].id].ID, results[x].spd1, results[x].spd2); + } + } else { + for (x = 0; x < no_results; x++) { + printf + ("%-20s: Process at %5"PRI64"u\n", hash_descriptor[results[x].id].name, results[x].spd1 / 1000); + } + } +} + +/* RDTSC from Scott Duplichan */ +static ulong64 rdtsc (void) + { + #if defined __GNUC__ && !defined(LTC_NO_ASM) + #if defined(__i386__) || defined(__x86_64__) + /* version from http://www.mcs.anl.gov/~kazutomo/rdtsc.html + * the old code always got a warning issued by gcc, clang did not complain... + */ + unsigned hi, lo; + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + return ((ulong64)lo)|( ((ulong64)hi)<<32); + #elif defined(LTC_PPC32) || defined(TFM_PPC32) + unsigned long a, b; + __asm__ __volatile__ ("mftbu %1 \nmftb %0\n":"=r"(a), "=r"(b)); + return (((ulong64)b) << 32ULL) | ((ulong64)a); + #elif defined(__ia64__) /* gcc-IA64 version */ + unsigned long result; + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + while (__builtin_expect ((int) result == -1, 0)) + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + return result; + #elif defined(__sparc__) + #if defined(__arch64__) + ulong64 a; + asm volatile("rd %%tick,%0" : "=r" (a)); + return a; + #else + register unsigned long x, y; + __asm__ __volatile__ ("rd %%tick, %0; clruw %0, %1; srlx %0, 32, %0" : "=r" (x), "=r" (y) : "0" (x), "1" (y)); + return ((unsigned long long) x << 32) | y; + #endif + #elif defined(__aarch64__) + ulong64 CNTVCT_EL0; + __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r"(CNTVCT_EL0)); + return CNTVCT_EL0; + #else + return XCLOCK(); + #endif + + /* Microsoft and Intel Windows compilers */ + #elif defined _M_IX86 && !defined(LTC_NO_ASM) + __asm rdtsc + #elif defined _M_AMD64 && !defined(LTC_NO_ASM) + return __rdtsc (); + #elif defined _M_IA64 && !defined(LTC_NO_ASM) + #if defined __INTEL_COMPILER + #include + #endif + return __getReg (3116); + #else + return XCLOCK(); + #endif + } + +static ulong64 timer, skew = 0; + +static void t_start(void) +{ + timer = rdtsc(); +} + +static ulong64 t_read(void) +{ + return rdtsc() - timer; +} + +static void init_timer(void) +{ + ulong64 c1, c2, t1, t2; + unsigned long y1; + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < TIMES*100; y1++) { + t_start(); + t1 = t_read(); + t2 = (t_read() - t1)>>1; + + c1 = (t1 > c1) ? t1 : c1; + c2 = (t2 > c2) ? t2 : c2; + } + skew = c2 - c1; + fprintf(stderr, "Clock Skew: %lu\n", (unsigned long)skew); +} + +static void time_keysched(void) +{ + unsigned long x, y1; + ulong64 t1, c1; + symmetric_key skey; + int kl; + int (*func) (const unsigned char *, int , int , symmetric_key *); + unsigned char key[MAXBLOCKSIZE]; + + fprintf(stderr, "\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { +#define DO1(k) func(k, kl, 0, &skey); + + func = cipher_descriptor[x].setup; + kl = cipher_descriptor[x].min_key_length; + c1 = (ulong64)-1; + for (y1 = 0; y1 < KTIMES; y1++) { + yarrow_read(key, kl, &yarrow_prng); + t_start(); + DO1(key); + t1 = t_read(); + c1 = (t1 > c1) ? c1 : t1; + } + t1 = c1 - skew; + results[no_results].spd1 = results[no_results].avg = t1; + results[no_results++].id = x; + fprintf(stderr, "."); fflush(stdout); + +#undef DO1 + } + tally_results(0); +} + +#ifdef LTC_ECB_MODE +static void time_cipher_ecb(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_ECB ecb; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nECB Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + ecb_start(x, key, cipher_descriptor[x].min_key_length, 0, &ecb); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 ecb_encrypt(pt, pt, sizeof(pt), &ecb); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 ecb_decrypt(pt, pt, sizeof(pt), &ecb); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + ecb_done(&ecb); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_ecb(void) { fprintf(stderr, "NO ECB\n"); return 0; } +#endif + +#ifdef LTC_CBC_MODE +static void time_cipher_cbc(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_CBC cbc; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nCBC Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + cbc_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, &cbc); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 cbc_encrypt(pt, pt, sizeof(pt), &cbc); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 cbc_decrypt(pt, pt, sizeof(pt), &cbc); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + cbc_done(&cbc); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_cbc(void) { fprintf(stderr, "NO CBC\n"); return 0; } +#endif + +#ifdef LTC_CTR_MODE +static void time_cipher_ctr(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_CTR ctr; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nCTR Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + ctr_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, CTR_COUNTER_LITTLE_ENDIAN, &ctr); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 ctr_encrypt(pt, pt, sizeof(pt), &ctr); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 ctr_decrypt(pt, pt, sizeof(pt), &ctr); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + ctr_done(&ctr); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_ctr(void) { fprintf(stderr, "NO CTR\n"); return 0; } +#endif + +#ifdef LTC_LRW_MODE +static void time_cipher_lrw(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_LRW lrw; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nLRW Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + if (cipher_descriptor[x].block_length != 16) continue; + lrw_start(x, pt, key, cipher_descriptor[x].min_key_length, key, 0, &lrw); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 lrw_encrypt(pt, pt, sizeof(pt), &lrw); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 lrw_decrypt(pt, pt, sizeof(pt), &lrw); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + + lrw_done(&lrw); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_lrw(void) { fprintf(stderr, "NO LRW\n"); } +#endif + + +static void time_hash(void) +{ + unsigned long x, y1, len; + ulong64 t1, t2, c1, c2; + hash_state md; + int (*func)(hash_state *, const unsigned char *, unsigned long), err; + unsigned char pt[MAXBLOCKSIZE] = { 0 }; + + + fprintf(stderr, "\n\nHASH Time Trials for:\n"); + no_results = 0; + for (x = 0; hash_descriptor[x].name != NULL; x++) { + + /* sanity check on hash */ + if ((err = hash_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Hash %s failed self-test %s\n", hash_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + + hash_descriptor[x].init(&md); + +#define DO1 func(&md,pt,len); +#define DO2 DO1 DO1 + + func = hash_descriptor[x].process; + len = hash_descriptor[x].blocksize; + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < TIMES; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read() - t1; + c1 = (t1 > c1) ? c1 : t1; + c2 = (t2 > c2) ? c2 : t2; + } + t1 = c2 - c1 - skew; + t1 = ((t1 * CONST64(1000))) / ((ulong64)hash_descriptor[x].blocksize); + results[no_results].id = x; + results[no_results].spd1 = results[no_results].avg = t1; + ++no_results; + fprintf(stderr, "."); fflush(stdout); +#undef DO2 +#undef DO1 + } + tally_results(2); +} + +/*#warning you need an mp_rand!!!*/ + +static void time_mult(void) +{ + ulong64 t1, t2; + unsigned long x, y; + void *a, *b, *c; + + if (ltc_mp.name == NULL) return; + + fprintf(stderr, "Timing Multiplying:\n"); + mp_init_multi(&a,&b,&c,NULL); + for (x = 128/MP_DIGIT_BIT; x <= (unsigned long)1536/MP_DIGIT_BIT; x += 128/MP_DIGIT_BIT) { + mp_rand(a, x); + mp_rand(b, x); + +#define DO1 mp_mul(a, b, c); +#define DO2 DO1; DO1; + + t2 = -1; + for (y = 0; y < TIMES; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%4lu bits: %9"PRI64"u cycles\n", x*MP_DIGIT_BIT, t2); + } + mp_clear_multi(a,b,c,NULL); + +#undef DO1 +#undef DO2 +} + +static void time_sqr(void) +{ + ulong64 t1, t2; + unsigned long x, y; + void *a, *b; + + if (ltc_mp.name == NULL) return; + + fprintf(stderr, "Timing Squaring:\n"); + mp_init_multi(&a,&b,NULL); + for (x = 128/MP_DIGIT_BIT; x <= (unsigned long)1536/MP_DIGIT_BIT; x += 128/MP_DIGIT_BIT) { + mp_rand(a, x); + +#define DO1 mp_sqr(a, b); +#define DO2 DO1; DO1; + + t2 = -1; + for (y = 0; y < TIMES; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%4lu bits: %9"PRI64"u cycles\n", x*MP_DIGIT_BIT, t2); + } + mp_clear_multi(a,b,NULL); + +#undef DO1 +#undef DO2 +} + +static void time_prng(void) +{ + ulong64 t1, t2; + unsigned char buf[4096]; + prng_state tprng; + unsigned long x, y; + int err; + + fprintf(stderr, "Timing PRNGs (cycles/byte output, cycles add_entropy (32 bytes) :\n"); + for (x = 0; prng_descriptor[x].name != NULL; x++) { + + /* sanity check on prng */ + if ((err = prng_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: PRNG %s failed self-test %s\n", prng_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + + prng_descriptor[x].start(&tprng); + zeromem(buf, 256); + prng_descriptor[x].add_entropy(buf, 256, &tprng); + prng_descriptor[x].ready(&tprng); + t2 = -1; + +#define DO1 if (prng_descriptor[x].read(buf, 4096, &tprng) != 4096) { fprintf(stderr, "\n\nERROR READ != 4096\n\n"); exit(EXIT_FAILURE); } +#define DO2 DO1 DO1 + for (y = 0; y < 10000; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%20s: %5"PRI64"u ", prng_descriptor[x].name, t2>>12); +#undef DO2 +#undef DO1 + +#define DO1 prng_descriptor[x].start(&tprng); prng_descriptor[x].add_entropy(buf, 32, &tprng); prng_descriptor[x].ready(&tprng); prng_descriptor[x].done(&tprng); +#define DO2 DO1 DO1 + for (y = 0; y < 10000; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%5"PRI64"u\n", t2); +#undef DO2 +#undef DO1 + + } +} + +#if defined(LTC_MDSA) +/* time various DSA operations */ +static void time_dsa(void) +{ + dsa_key key; + ulong64 t1, t2; + unsigned long x, y; + int err; +static const struct { + int group, modulus; +} groups[] = { +{ 20, 96 }, +{ 20, 128 }, +{ 24, 192 }, +{ 28, 256 }, +#ifndef TFM_DESC +{ 32, 512 }, +#endif +}; + + if (ltc_mp.name == NULL) return; + + for (x = 0; x < (sizeof(groups)/sizeof(groups[0])); x++) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = dsa_generate_pqg(&yarrow_prng, find_prng("yarrow"), groups[x].group, groups[x].modulus, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndsa_generate_pqg says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if ((err = dsa_generate_key(&yarrow_prng, find_prng("yarrow"), &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 2; + break; +#endif + if (y < 3) { + dsa_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "DSA-(%lu, %lu) make_key took %15"PRI64"u cycles\n", (unsigned long)groups[x].group*8, (unsigned long)groups[x].modulus*8, t2); + dsa_free(&key); + } + fprintf(stderr, "\n\n"); +} +#else +static void time_dsa(void) { fprintf(stderr, "NO DSA\n"); } +#endif + + +#if defined(LTC_MRSA) +/* time various RSA operations */ +static void time_rsa(void) +{ + rsa_key key; + ulong64 t1, t2; + unsigned char buf[2][2048] = { 0 }; + unsigned long x, y, z, zzz; + int err, zz, stat; + + if (ltc_mp.name == NULL) return; + + for (x = 2048; x <= 8192; x <<= 1) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = rsa_make_key(&yarrow_prng, find_prng("yarrow"), x/8, 65537, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 2; + break; +#endif + + if (y < 3) { + rsa_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "RSA-%lu make_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 16; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = rsa_encrypt_key(buf[0], 32, buf[1], &z, (const unsigned char *)"testprog", 8, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 4; + break; +#endif + } + t2 >>= 4; + fprintf(stderr, "RSA-%lu encrypt_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + zzz = sizeof(buf[0]); + if ((err = rsa_decrypt_key(buf[1], z, buf[0], &zzz, (const unsigned char *)"testprog", 8, find_hash("sha1"), + &zz, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 11; + break; +#endif + } + t2 >>= 11; + fprintf(stderr, "RSA-%lu decrypt_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = rsa_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), 8, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "RSA-%lu sign_hash took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + if ((err = rsa_verify_hash(buf[1], z, buf[0], 20, find_hash("sha1"), 8, &stat, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if (stat == 0) { + fprintf(stderr, "\n\nrsa_verify_hash for RSA-%lu failed to verify signature(%lu)\n", x, y); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 11; + break; +#endif + } + t2 >>= 11; + fprintf(stderr, "RSA-%lu verify_hash took %15"PRI64"u cycles\n", x, t2); + fprintf(stderr, "\n\n"); + rsa_free(&key); + } +} +#else +static void time_rsa(void) { fprintf(stderr, "NO RSA\n"); } +#endif + +#if defined(LTC_MDH) +/* time various DH operations */ +static void time_dh(void) +{ + dh_key key; + ulong64 t1, t2; + unsigned long i, x, y; + int err; + static unsigned long sizes[] = {768/8, 1024/8, 1536/8, 2048/8, +#ifndef TFM_DESC + 3072/8, 4096/8, 6144/8, 8192/8, +#endif + 100000 + }; + + if (ltc_mp.name == NULL) return; + + for (x = sizes[i=0]; x < 100000; x = sizes[++i]) { + t2 = 0; + for (y = 0; y < 16; y++) { + if((err = dh_set_pg_groupsize(x, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndh_set_pg_groupsize says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + + t_start(); + t1 = t_read(); + if ((err = dh_generate_key(&yarrow_prng, find_prng("yarrow"), &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndh_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + + dh_free(&key); + } + t2 >>= 4; + fprintf(stderr, "DH-%4lu make_key took %15"PRI64"u cycles\n", x*8, t2); + } +} +#else +static void time_dh(void) { fprintf(stderr, "NO DH\n"); } +#endif + +#if defined(LTC_MECC) +/* time various ECC operations */ +static void time_ecc(void) +{ + ecc_key key; + ulong64 t1, t2; + unsigned char buf[2][256] = { 0 }; + unsigned long i, w, x, y, z; + int err, stat; + static unsigned long sizes[] = { +#ifdef LTC_ECC_SECP112R1 +112/8, +#endif +#ifdef LTC_ECC_SECP128R1 +128/8, +#endif +#ifdef LTC_ECC_SECP160R1 +160/8, +#endif +#ifdef LTC_ECC_SECP192R1 +192/8, +#endif +#ifdef LTC_ECC_SECP224R1 +224/8, +#endif +#ifdef LTC_ECC_SECP256R1 +256/8, +#endif +#ifdef LTC_ECC_SECP384R1 +384/8, +#endif +#ifdef LTC_ECC_SECP512R1 +521/8, +#endif +100000}; + + if (ltc_mp.name == NULL) return; + + for (x = sizes[i=0]; x < 100000; x = sizes[++i]) { + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + if ((err = ecc_make_key(&yarrow_prng, find_prng("yarrow"), x, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + + if (y < 255) { + ecc_free(&key); + } + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu make_key took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = ecc_encrypt_key(buf[0], 20, buf[1], &z, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu encrypt_key took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + w = 20; + if ((err = ecc_decrypt_key(buf[1], z, buf[0], &w, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu decrypt_key took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = ecc_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng, + find_prng("yarrow"), &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu sign_hash took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + if ((err = ecc_verify_hash(buf[1], z, buf[0], 20, &stat, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if (stat == 0) { + fprintf(stderr, "\n\necc_verify_hash for ECC-%lu failed to verify signature(%lu)\n", x*8, y); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu verify_hash took %15"PRI64"u cycles\n", x*8, t2); + + fprintf(stderr, "\n\n"); + ecc_free(&key); + } +} +#else +static void time_ecc(void) { fprintf(stderr, "NO ECC\n"); } +#endif + +static void time_macs_(unsigned long MAC_SIZE) +{ +#if defined(LTC_OMAC) || defined(LTC_XCBC) || defined(LTC_F9_MODE) || defined(LTC_PMAC) || defined(LTC_PELICAN) || defined(LTC_HMAC) + unsigned char *buf, key[16], tag[16]; + ulong64 t1, t2; + unsigned long x, z; + int err, cipher_idx, hash_idx; + + fprintf(stderr, "\nMAC Timings (cycles/byte on %luKB blocks):\n", MAC_SIZE); + + buf = XMALLOC(MAC_SIZE*1024); + if (buf == NULL) { + fprintf(stderr, "\n\nout of heap yo\n\n"); + exit(EXIT_FAILURE); + } + + cipher_idx = find_cipher("aes"); + hash_idx = find_hash("sha1"); + + if (cipher_idx == -1 || hash_idx == -1) { + fprintf(stderr, "Warning the MAC tests requires AES and SHA1 to operate... so sorry\n"); + exit(EXIT_FAILURE); + } + + yarrow_read(buf, MAC_SIZE*1024, &yarrow_prng); + yarrow_read(key, 16, &yarrow_prng); + +#ifdef LTC_OMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = omac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nomac-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "OMAC-%s\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_XCBC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = xcbc_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nxcbc-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "XCBC-%s\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_F9_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = f9_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nF9-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "F9-%s\t\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_PMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = pmac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\npmac-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "PMAC-%s\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_PELICAN + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = pelican_memory(key, 16, buf, MAC_SIZE*1024, tag)) != CRYPT_OK) { + fprintf(stderr, "\n\npelican error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "PELICAN \t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_HMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = hmac_memory(hash_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nhmac-%s error... %s\n", hash_descriptor[hash_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "HMAC-%s\t\t%9"PRI64"u\n", hash_descriptor[hash_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + + XFREE(buf); +#else + LTC_UNUSED_PARAM(MAC_SIZE); + fprintf(stderr, "NO MACs\n"); +#endif +} + +static void time_macs(void) +{ + time_macs_(1); + time_macs_(4); + time_macs_(32); +} + +static void time_encmacs_(unsigned long MAC_SIZE) +{ +#if defined(LTC_EAX_MODE) || defined(LTC_OCB_MODE) || defined(LTC_OCB3_MODE) || defined(LTC_CCM_MODE) || defined(LTC_GCM_MODE) + unsigned char *buf, IV[16], key[16], tag[16]; + ulong64 t1, t2; + unsigned long x, z; + int err, cipher_idx; + symmetric_key skey; + + fprintf(stderr, "\nENC+MAC Timings (zero byte AAD, 16 byte IV, cycles/byte on %luKB blocks):\n", MAC_SIZE); + + buf = XMALLOC(MAC_SIZE*1024); + if (buf == NULL) { + fprintf(stderr, "\n\nout of heap yo\n\n"); + exit(EXIT_FAILURE); + } + + cipher_idx = find_cipher("aes"); + + yarrow_read(buf, MAC_SIZE*1024, &yarrow_prng); + yarrow_read(key, 16, &yarrow_prng); + yarrow_read(IV, 16, &yarrow_prng); + +#ifdef LTC_EAX_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = eax_encrypt_authenticate_memory(cipher_idx, key, 16, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nEAX error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "EAX \t\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_OCB_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ocb_encrypt_authenticate_memory(cipher_idx, key, 16, IV, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nOCB error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "OCB \t\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_OCB3_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ocb3_encrypt_authenticate_memory(cipher_idx, key, 16, IV, 15, (unsigned char*)"", 0, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nOCB3 error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "OCB3 \t\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_CCM_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ccm_memory(cipher_idx, key, 16, NULL, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "CCM (no-precomp) \t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + + cipher_descriptor[cipher_idx].setup(key, 16, 0, &skey); + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ccm_memory(cipher_idx, key, 16, &skey, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "CCM (precomp) \t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + cipher_descriptor[cipher_idx].done(&skey); +#endif + +#ifdef LTC_GCM_MODE + t2 = -1; + for (x = 0; x < 100; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = gcm_memory(cipher_idx, key, 16, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, GCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "GCM (no-precomp)\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + + { + gcm_state gcm +#ifdef LTC_GCM_TABLES_SSE2 +__attribute__ ((aligned (16))) +#endif +; + + if ((err = gcm_init(&gcm, cipher_idx, key, 16)) != CRYPT_OK) { fprintf(stderr, "gcm_init: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = gcm_reset(&gcm)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_add_iv(&gcm, IV, 16)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_add_aad(&gcm, NULL, 0)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_process(&gcm, buf, MAC_SIZE*1024, buf, GCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + + if ((err = gcm_done(&gcm, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "GCM (precomp)\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + } + +#endif + XFREE(buf); +#else + LTC_UNUSED_PARAM(MAC_SIZE); + fprintf(stderr, "NO ENCMACs\n"); +#endif + +} + +static void time_encmacs(void) +{ + time_encmacs_(1); + time_encmacs_(4); + time_encmacs_(32); +} + +#define LTC_TEST_FN(f) { f, #f } +int main(int argc, char **argv) +{ +int err; + +const struct +{ + void (*fn)(void); + const char* name; +} test_functions[] = { + LTC_TEST_FN(time_keysched), + LTC_TEST_FN(time_cipher_ecb), + LTC_TEST_FN(time_cipher_cbc), + LTC_TEST_FN(time_cipher_ctr), + LTC_TEST_FN(time_cipher_lrw), + LTC_TEST_FN(time_hash), + LTC_TEST_FN(time_macs), + LTC_TEST_FN(time_encmacs), + LTC_TEST_FN(time_prng), + LTC_TEST_FN(time_mult), + LTC_TEST_FN(time_sqr), + LTC_TEST_FN(time_rsa), + LTC_TEST_FN(time_dsa), + LTC_TEST_FN(time_ecc), + LTC_TEST_FN(time_dh), +}; +char *single_test = NULL; +unsigned int i; +const char* mpi_provider = NULL; + +init_timer(); +register_all_ciphers(); +register_all_hashes(); +register_all_prngs(); + +#ifdef USE_LTM + mpi_provider = "ltm"; +#elif defined(USE_TFM) + mpi_provider = "tfm"; +#elif defined(USE_GMP) + mpi_provider = "gmp"; +#elif defined(EXT_MATH_LIB) + mpi_provider = "ext"; +#endif + + if (argc > 2) { + mpi_provider = argv[2]; + } + + crypt_mp_init(mpi_provider); + +if ((err = rng_make_prng(128, find_prng("yarrow"), &yarrow_prng, NULL)) != CRYPT_OK) { + fprintf(stderr, "rng_make_prng failed: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); +} + +/* single test name from commandline */ +if (argc > 1) single_test = argv[1]; + +for (i = 0; i < sizeof(test_functions)/sizeof(test_functions[0]); ++i) { + if (single_test && strstr(test_functions[i].name, single_test) == NULL) { + continue; + } + test_functions[i].fn(); +} + +return EXIT_SUCCESS; + +} diff --git a/deps/libtomcrypt/demos/tv_gen.c b/deps/libtomcrypt/demos/tv_gen.c new file mode 100644 index 0000000..ef9f919 --- /dev/null +++ b/deps/libtomcrypt/demos/tv_gen.c @@ -0,0 +1,818 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +static void hash_gen(void) +{ + unsigned char md[MAXBLOCKSIZE], *buf; + unsigned long outlen, x, y, z; + FILE *out; + int err; + + out = fopen("hash_tv.txt", "w"); + if (out == NULL) { + perror("can't open hash_tv"); + } + + fprintf(out, "Hash Test Vectors:\n\nThese are the hashes of nn bytes '00 01 02 03 .. (nn-1)'\n\n"); + for (x = 0; hash_descriptor[x].name != NULL; x++) { + buf = XMALLOC(2 * hash_descriptor[x].blocksize + 1); + if (buf == NULL) { + perror("can't alloc mem"); + exit(EXIT_FAILURE); + } + fprintf(out, "Hash: %s\n", hash_descriptor[x].name); + for (y = 0; y <= (hash_descriptor[x].blocksize * 2); y++) { + for (z = 0; z < y; z++) { + buf[z] = (unsigned char)(z & 255); + } + outlen = sizeof(md); + if ((err = hash_memory(x, buf, y, md, &outlen)) != CRYPT_OK) { + printf("hash_memory error: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + fprintf(out, "%3lu: ", y); + for (z = 0; z < outlen; z++) { + fprintf(out, "%02X", md[z]); + } + fprintf(out, "\n"); + } + fprintf(out, "\n"); + XFREE(buf); + } + fclose(out); +} + +static void cipher_gen(void) +{ + unsigned char *key, pt[MAXBLOCKSIZE]; + unsigned long x, y, z, w; + int err, kl, lastkl; + FILE *out; + symmetric_key skey; + + out = fopen("cipher_tv.txt", "w"); + + fprintf(out, +"Cipher Test Vectors\n\nThese are test encryptions with key of nn bytes '00 01 02 03 .. (nn-1)' and original PT of the same style.\n" +"The output of step N is used as the key and plaintext for step N+1 (key bytes repeated as required to fill the key)\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + fprintf(out, "Cipher: %s\n", cipher_descriptor[x].name); + + /* three modes, smallest, medium, large keys */ + lastkl = 10000; + for (y = 0; y < 3; y++) { + switch (y) { + case 0: kl = cipher_descriptor[x].min_key_length; break; + case 1: kl = (cipher_descriptor[x].min_key_length + cipher_descriptor[x].max_key_length)/2; break; + case 2: kl = cipher_descriptor[x].max_key_length; break; + } + if ((err = cipher_descriptor[x].keysize(&kl)) != CRYPT_OK) { + printf("keysize error: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (kl == lastkl) continue; + lastkl = kl; + fprintf(out, "Key Size: %d bytes\n", kl); + + key = XMALLOC(kl); + if (key == NULL) { + perror("can't malloc memory"); + exit(EXIT_FAILURE); + } + + for (z = 0; (int)z < kl; z++) { + key[z] = (unsigned char)z; + } + if ((err = cipher_descriptor[x].setup(key, kl, 0, &skey)) != CRYPT_OK) { + printf("setup error: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) { + pt[z] = (unsigned char)z; + } + for (w = 0; w < 50; w++) { + cipher_descriptor[x].ecb_encrypt(pt, pt, &skey); + fprintf(out, "%2lu: ", w); + for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) { + fprintf(out, "%02X", pt[z]); + } + fprintf(out, "\n"); + + /* reschedule a new key */ + for (z = 0; z < (unsigned long)kl; z++) { + key[z] = pt[z % cipher_descriptor[x].block_length]; + } + if ((err = cipher_descriptor[x].setup(key, kl, 0, &skey)) != CRYPT_OK) { + printf("cipher setup2 error: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + } + fprintf(out, "\n"); + XFREE(key); + } + fprintf(out, "\n"); + } + fclose(out); +} + +static void hmac_gen(void) +{ + unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], *input; + int x, y, z, err; + FILE *out; + unsigned long len; + + out = fopen("hmac_tv.txt", "w"); + + fprintf(out, +"HMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are HMACed. The initial key is\n" +"of the same format (the same length as the HASH output size). The HMAC key in step N+1 is the HMAC output of\n" +"step N.\n\n"); + + for (x = 0; hash_descriptor[x].name != NULL; x++) { + fprintf(out, "HMAC-%s\n", hash_descriptor[x].name); + + /* initial key */ + for (y = 0; y < (int)hash_descriptor[x].hashsize; y++) { + key[y] = (y&255); + } + + input = XMALLOC(hash_descriptor[x].blocksize * 2 + 1); + if (input == NULL) { + perror("Can't malloc memory"); + exit(EXIT_FAILURE); + } + + for (y = 0; y <= (int)(hash_descriptor[x].blocksize * 2); y++) { + for (z = 0; z < y; z++) { + input[z] = (unsigned char)(z & 255); + } + len = sizeof(output); + if ((err = hmac_memory(x, key, hash_descriptor[x].hashsize, input, y, output, &len)) != CRYPT_OK) { + printf("Error hmacing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y); + for (z = 0; z <(int) len; z++) { + fprintf(out, "%02X", output[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + memcpy(key, output, hash_descriptor[x].hashsize); + } + XFREE(input); + fprintf(out, "\n"); + } + fclose(out); +} + +#ifdef LTC_OMAC +static void omac_gen(void) +{ + unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2]; + int err, x, y, z, kl; + FILE *out; + unsigned long len; + + out = fopen("omac_tv.txt", "w"); + + fprintf(out, +"OMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are OMAC'ed. The initial key is\n" +"of the same format (length specified per cipher). The OMAC key in step N+1 is the OMAC output of\n" +"step N (repeated as required to fill the array).\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 64 or 128 bit block sizes */ + if (kl != 8 && kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "OMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* initial key/block */ + for (y = 0; y < kl; y++) { + key[y] = (y & 255); + } + + for (y = 0; y <= (int)(cipher_descriptor[x].block_length*2); y++) { + for (z = 0; z < y; z++) { + input[z] = (unsigned char)(z & 255); + } + len = sizeof(output); + if ((err = omac_memory(x, key, kl, input, y, output, &len)) != CRYPT_OK) { + printf("Error OMAC'ing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (len == 0) { + printf("Error OMAC'ing: zero length\n"); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", output[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = output[z % len]; + } + } + fprintf(out, "\n"); + } + fclose(out); +} +#endif + +#ifdef LTC_PMAC +static void pmac_gen(void) +{ + unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2]; + int err, x, y, z, kl; + FILE *out; + unsigned long len; + + out = fopen("pmac_tv.txt", "w"); + + fprintf(out, +"PMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are PMAC'ed. The initial key is\n" +"of the same format (length specified per cipher). The PMAC key in step N+1 is the PMAC output of\n" +"step N (repeated as required to fill the array).\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 64 or 128 bit block sizes */ + if (kl != 8 && kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "PMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* initial key/block */ + for (y = 0; y < kl; y++) { + key[y] = (y & 255); + } + + for (y = 0; y <= (int)(cipher_descriptor[x].block_length*2); y++) { + for (z = 0; z < y; z++) { + input[z] = (unsigned char)(z & 255); + } + len = sizeof(output); + if ((err = pmac_memory(x, key, kl, input, y, output, &len)) != CRYPT_OK) { + printf("Error PMACing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (len == 0) { + printf("Error PMAC'ing: zero length\n"); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", output[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = output[z % len]; + } + } + fprintf(out, "\n"); + } + fclose(out); +} +#endif + +#ifdef LTC_EAX_MODE +static void eax_gen(void) +{ + int err, kl, x, y1, z; + FILE *out; + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], header[MAXBLOCKSIZE*2], + plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; + unsigned long len; + + out = fopen("eax_tv.txt", "w"); + fprintf(out, "EAX Test Vectors. Uses the 00010203...NN-1 pattern for header/nonce/plaintext/key. The outputs\n" + "are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n" + "step repeated sufficiently.\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 64 or 128 bit block sizes */ + if (kl != 8 && kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "EAX-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* the key */ + for (z = 0; z < kl; z++) { + key[z] = (z & 255); + } + + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ + for (z = 0; z < y1; z++) { + plaintext[z] = (unsigned char)(z & 255); + nonce[z] = (unsigned char)(z & 255); + header[z] = (unsigned char)(z & 255); + } + len = sizeof(tag); + if ((err = eax_encrypt_authenticate_memory(x, key, kl, nonce, y1, header, y1, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) { + printf("Error EAX'ing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (len == 0) { + printf("Error EAX'ing: zero length\n"); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y1); + for (z = 0; z < y1; z++) { + fprintf(out, "%02X", plaintext[z]); + } + fprintf(out, ", "); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", tag[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = tag[z % len]; + } + } + fprintf(out, "\n"); + } + fclose(out); +} +#endif + +#ifdef LTC_OCB_MODE +static void ocb_gen(void) +{ + int err, kl, x, y1, z; + FILE *out; + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], + plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; + unsigned long len; + + out = fopen("ocb_tv.txt", "w"); + fprintf(out, "OCB Test Vectors. Uses the 00010203...NN-1 pattern for nonce/plaintext/key. The outputs\n" + "are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n" + "step repeated sufficiently. The nonce is fixed throughout.\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 64 or 128 bit block sizes */ + if (kl != 8 && kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "OCB-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* the key */ + for (z = 0; z < kl; z++) { + key[z] = (z & 255); + } + + /* fixed nonce */ + for (z = 0; z < cipher_descriptor[x].block_length; z++) { + nonce[z] = z; + } + + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ + for (z = 0; z < y1; z++) { + plaintext[z] = (unsigned char)(z & 255); + } + len = sizeof(tag); + if ((err = ocb_encrypt_authenticate_memory(x, key, kl, nonce, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) { + printf("Error OCB'ing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (len == 0) { + printf("Error OCB'ing: zero length\n"); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y1); + for (z = 0; z < y1; z++) { + fprintf(out, "%02X", plaintext[z]); + } + fprintf(out, ", "); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", tag[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = tag[z % len]; + } + } + fprintf(out, "\n"); + } + fclose(out); +} +#endif + +#ifdef LTC_OCB3_MODE +static void ocb3_gen(void) +{ + int err, kl, x, y1, z, noncelen; + FILE *out; + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], + plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; + unsigned long len; + + out = fopen("ocb3_tv.txt", "w"); + fprintf(out, "OCB3 Test Vectors. Uses the 00010203...NN-1 pattern for nonce/plaintext/key. The outputs\n" + "are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n" + "step repeated sufficiently. The nonce is fixed throughout. AAD is fixed to 3 bytes (ASCII) 'AAD'.\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 64 or 128 bit block sizes */ + if (kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "OCB3-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* the key */ + for (z = 0; z < kl; z++) { + key[z] = (z & 255); + } + + /* fixed nonce */ + noncelen = MIN(15, cipher_descriptor[x].block_length); + for (z = 0; z < noncelen; z++) { + nonce[z] = z; + } + + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ + for (z = 0; z < y1; z++) { + plaintext[z] = (unsigned char)(z & 255); + } + len = 16; + if ((err = ocb3_encrypt_authenticate_memory(x, key, kl, nonce, noncelen, (unsigned char*)"AAD", 3, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) { + printf("Error OCB3'ing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (len == 0) { + printf("Error OCB3'ing: zero length\n"); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y1); + for (z = 0; z < y1; z++) { + fprintf(out, "%02X", plaintext[z]); + } + fprintf(out, ", "); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", tag[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = tag[z % len]; + } + } + fprintf(out, "\n"); + } + fclose(out); +} +#endif + +#ifdef LTC_CCM_MODE +static void ccm_gen(void) +{ + int err, kl, x, y1, z; + unsigned int t; + FILE *out; + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], + plaintext[MAXBLOCKSIZE*2], tag[16]; + unsigned long len; + const unsigned int taglen[] = {4, 6, 8, 10, 12, 14, 16}; + + out = fopen("ccm_tv.txt", "w"); + fprintf(out, "CCM Test Vectors. Uses the 00010203...NN-1 pattern for nonce/header/plaintext/key. The outputs\n" + "are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n" + "step repeated sufficiently. The nonce is fixed throughout at 13 bytes 000102...\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 128 bit block sizes */ + if (kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "CCM-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* the key */ + for (z = 0; z < kl; z++) { + key[z] = (z & 255); + } + + /* fixed nonce */ + for (z = 0; z < cipher_descriptor[x].block_length; z++) { + nonce[z] = z; + } + + for (t = 0; t < sizeof(taglen)/sizeof(taglen[0]); ++t) { + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ + for (z = 0; z < y1; z++) { + plaintext[z] = (unsigned char)(z & 255); + } + len = taglen[t]; + if ((err = ccm_memory(x, key, kl, NULL, nonce, 13, plaintext, y1, plaintext, y1, plaintext, tag, &len, CCM_ENCRYPT)) != CRYPT_OK) { + printf("Error CCM'ing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (len == 0) { + printf("Error CCM'ing: zero length\n"); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y1); + for (z = 0; z < y1; z++) { + fprintf(out, "%02X", plaintext[z]); + } + fprintf(out, ", "); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", tag[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = tag[z % len]; + } + } + } + fprintf(out, "\n"); + } + fclose(out); +} +#endif + +#ifdef LTC_GCM_MODE +static void gcm_gen(void) +{ + int err, kl, x, y1, z; + FILE *out; + unsigned char key[MAXBLOCKSIZE], plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; + unsigned long len; + + out = fopen("gcm_tv.txt", "w"); + fprintf(out, "GCM Test Vectors. Uses the 00010203...NN-1 pattern for nonce/header/plaintext/key. The outputs\n" + "are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n" + "step repeated sufficiently. The nonce is fixed throughout at 13 bytes 000102...\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 128 bit block sizes */ + if (kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "GCM-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* the key */ + for (z = 0; z < kl; z++) { + key[z] = (z & 255); + } + + for (y1 = 1; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ + for (z = 0; z < y1; z++) { + plaintext[z] = (unsigned char)(z & 255); + } + len = sizeof(tag); + if ((err = gcm_memory(x, key, kl, plaintext, y1, plaintext, y1, plaintext, y1, plaintext, tag, &len, GCM_ENCRYPT)) != CRYPT_OK) { + printf("Error GCM'ing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if (len == 0) { + printf("Error GCM'ing: zero length\n"); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y1); + for (z = 0; z < y1; z++) { + fprintf(out, "%02X", plaintext[z]); + } + fprintf(out, ", "); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", tag[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = tag[z % len]; + } + } + fprintf(out, "\n"); + } + fclose(out); +} +#endif + +static void base64_gen(void) +{ + FILE *out; + unsigned char src[32], ch; + char dst[256]; + unsigned long x, len; + + out = fopen("base64_tv.txt", "w"); + fprintf(out, "Base64 vectors. These are the base64 encodings of the strings 00,01,02...NN-1\n\n"); + for (x = 0; x <= 32; x++) { + for (ch = 0; ch < x; ch++) { + src[ch] = ch; + } + len = sizeof(dst); + base64_encode(src, x, dst, &len); + fprintf(out, "%2lu: %s\n", x, dst); + } + fclose(out); +} + +static void math_gen(void) +{ +} + +static void ecc_gen(void) +{ + FILE *out; + unsigned char str[512]; + void *k, *order, *modulus, *a; + ecc_point *G, *R; + int x; + + out = fopen("ecc_tv.txt", "w"); + fprintf(out, "ecc vectors. These are for kG for k=1,3,9,27,...,3**n until k > order of the curve outputs are triplets\n\n"); + G = ltc_ecc_new_point(); + R = ltc_ecc_new_point(); + mp_init(&k); + mp_init(&order); + mp_init(&modulus); + mp_init(&a); + + for (x = 0; ltc_ecc_curves[x].prime != NULL; x++) { + fprintf(out, "%s\n", ltc_ecc_curves[x].OID); + mp_set(k, 1); + + mp_read_radix(order, (char *)ltc_ecc_curves[x].order, 16); + mp_read_radix(modulus, (char *)ltc_ecc_curves[x].prime, 16); + mp_read_radix(a, (char *)ltc_ecc_curves[x].A, 16); + mp_read_radix(G->x, (char *)ltc_ecc_curves[x].Gx, 16); + mp_read_radix(G->y, (char *)ltc_ecc_curves[x].Gy, 16); + mp_set(G->z, 1); + + while (mp_cmp(k, order) == LTC_MP_LT) { + ltc_mp.ecc_ptmul(k, G, R, a, modulus, 1); + mp_tohex(k, (char*)str); fprintf(out, "%s, ", (char*)str); + mp_tohex(R->x, (char*)str); fprintf(out, "%s, ", (char*)str); + mp_tohex(R->y, (char*)str); fprintf(out, "%s\n", (char*)str); + mp_mul_d(k, 3, k); + } + } + mp_clear_multi(k, order, modulus, a, LTC_NULL); + ltc_ecc_del_point(G); + ltc_ecc_del_point(R); + fclose(out); +} + +#ifdef LTC_LRW_MODE +static void lrw_gen(void) +{ + FILE *out; + unsigned char tweak[16], key[16], iv[16], buf[1024]; + int x, y, err; + symmetric_LRW lrw; + + /* initialize default key and tweak */ + for (x = 0; x < 16; x++) { + tweak[x] = key[x] = iv[x] = x; + } + + out = fopen("lrw_tv.txt", "w"); + for (x = 16; x < (int)(sizeof(buf)); x += 16) { + if ((err = lrw_start(find_cipher("aes"), iv, key, 16, tweak, 0, &lrw)) != CRYPT_OK) { + fprintf(stderr, "Error starting LRW-AES: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + /* encrypt incremental */ + for (y = 0; y < x; y++) { + buf[y] = y & 255; + } + + if ((err = lrw_encrypt(buf, buf, x, &lrw)) != CRYPT_OK) { + fprintf(stderr, "Error encrypting with LRW-AES: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + /* display it */ + fprintf(out, "%d:", x); + for (y = 0; y < x; y++) { + fprintf(out, "%02x", buf[y]); + } + fprintf(out, "\n"); + + /* reset IV */ + if ((err = lrw_setiv(iv, 16, &lrw)) != CRYPT_OK) { + fprintf(stderr, "Error setting IV: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + /* copy new tweak, iv and key */ + for (y = 0; y < 16; y++) { + key[y] = buf[y]; + iv[y] = buf[(y+16)%x]; + tweak[y] = buf[(y+32)%x]; + } + + if ((err = lrw_decrypt(buf, buf, x, &lrw)) != CRYPT_OK) { + fprintf(stderr, "Error decrypting with LRW-AES: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + /* display it */ + fprintf(out, "%d:", x); + for (y = 0; y < x; y++) { + fprintf(out, "%02x", buf[y]); + } + fprintf(out, "\n"); + lrw_done(&lrw); + } + fclose(out); +} +#endif + +int main(void) +{ + register_all_ciphers(); + register_all_hashes(); + register_all_prngs(); +#ifdef USE_LTM + ltc_mp = ltm_desc; +#elif defined(USE_TFM) + ltc_mp = tfm_desc; +#elif defined(USE_GMP) + ltc_mp = gmp_desc; +#elif defined(EXT_MATH_LIB) + extern ltc_math_descriptor EXT_MATH_LIB; + ltc_mp = EXT_MATH_LIB; +#endif + + printf("Generating hash vectors..."); fflush(stdout); hash_gen(); printf("done\n"); + printf("Generating cipher vectors..."); fflush(stdout); cipher_gen(); printf("done\n"); + printf("Generating HMAC vectors..."); fflush(stdout); hmac_gen(); printf("done\n"); +#ifdef LTC_OMAC + printf("Generating OMAC vectors..."); fflush(stdout); omac_gen(); printf("done\n"); +#endif +#ifdef LTC_PMAC + printf("Generating PMAC vectors..."); fflush(stdout); pmac_gen(); printf("done\n"); +#endif +#ifdef LTC_EAX_MODE + printf("Generating EAX vectors..."); fflush(stdout); eax_gen(); printf("done\n"); +#endif +#ifdef LTC_OCB_MODE + printf("Generating OCB vectors..."); fflush(stdout); ocb_gen(); printf("done\n"); +#endif +#ifdef LTC_OCB3_MODE + printf("Generating OCB3 vectors..."); fflush(stdout); ocb3_gen(); printf("done\n"); +#endif +#ifdef LTC_CCM_MODE + printf("Generating CCM vectors..."); fflush(stdout); ccm_gen(); printf("done\n"); +#endif +#ifdef LTC_GCM_MODE + printf("Generating GCM vectors..."); fflush(stdout); gcm_gen(); printf("done\n"); +#endif + printf("Generating BASE64 vectors..."); fflush(stdout); base64_gen(); printf("done\n"); + if (ltc_mp.name != NULL) { + printf("Generating MATH vectors..."); fflush(stdout); math_gen(); printf("done\n"); + printf("Generating ECC vectors..."); fflush(stdout); ecc_gen(); printf("done\n"); + } +#ifdef LTC_LRW_MODE + printf("Generating LRW vectors..."); fflush(stdout); lrw_gen(); printf("done\n"); +#endif + return 0; +} diff --git a/deps/libtomcrypt/doc/Doxyfile b/deps/libtomcrypt/doc/Doxyfile new file mode 100644 index 0000000..829961d --- /dev/null +++ b/deps/libtomcrypt/doc/Doxyfile @@ -0,0 +1,2429 @@ +# Doxyfile 1.8.11 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = LibTomCrypt + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER=1.18.2-develop + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = libtomsm.png + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = doxygen + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = src + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = ../src/headers + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = YES + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../src/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, +# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 1 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /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%0AS(R2*D-YlX|+Qs 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 YAAULDfvG86)Bpeg07*qoM6N<$f?L33r2qf` literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/doc/makefile b/deps/libtomcrypt/doc/makefile new file mode 100644 index 0000000..f9b75e5 --- /dev/null +++ b/deps/libtomcrypt/doc/makefile @@ -0,0 +1,63 @@ +ifeq ($V,1) +silent= +silent_stdout= +else +silent=@ +silent_stdout= > /dev/null +endif + +#Files left over from making the crypt.pdf. +LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out *.lof + +#build the doxy files (requires Doxygen, tetex and patience) +.PHONY: doxygen +doxygen: + doxygen $(silent_stdout) + +patched_doxygen: + (cat Doxyfile && echo "HAVE_DOT=no") | doxygen - $(silent_stdout) + +doxy: patched_doxygen + ${MAKE} -C doxygen/latex $(silent_stdout) && mv -f doxygen/latex/refman.pdf . + @echo The huge doxygen PDF should be available as doc/refman.pdf + +#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed +#from the clean command! This is because most people would like to keep the +#nice pre-compiled crypt.pdf that comes with libtomcrypt! We only need to +#delete it if we are rebuilding it. +docs crypt.pdf: crypt.tex + rm -f crypt.pdf $(LEFTOVERS) + cp crypt.tex crypt.bak + touch -r crypt.tex crypt.bak + (printf "%s" "\def\fixedpdfdate{"; date +'D:%Y%m%d%H%M%S%:z' -d @$$(stat --format=%Y crypt.tex) | sed "s/:\([0-9][0-9]\)$$/'\1'}/g") > crypt-deterministic.tex + printf "%s\n" "\pdfinfo{" >> crypt-deterministic.tex + printf "%s\n" " /CreationDate (\fixedpdfdate)" >> crypt-deterministic.tex + printf "%s\n}\n" " /ModDate (\fixedpdfdate)" >> crypt-deterministic.tex + cat crypt.tex >> crypt-deterministic.tex + mv crypt-deterministic.tex crypt.tex + touch -r crypt.bak crypt.tex + echo "hello" > crypt.ind + latex crypt $(silent_stdout) + latex crypt $(silent_stdout) + makeindex crypt.idx $(silent_stdout) + perl ../helper.pl --fixupind crypt.ind + pdflatex crypt $(silent_stdout) + sed -b -i 's,^/ID \[.*\]$$,/ID [<0> <0>],g' crypt.pdf + mv crypt.bak crypt.tex + rm -f $(LEFTOVERS) + +docdvi: crypt.tex + echo hello > crypt.ind + latex crypt $(silent_stdout) + latex crypt $(silent_stdout) + makeindex crypt.idx + perl ../helper.pl --fixupind crypt.ind + latex crypt $(silent_stdout) + latex crypt $(silent_stdout) + +termdoc: docdvi + dvi2tty crypt.dvi -w120 + +clean: + rm -f $(LEFTOVERS) + rm -rf doxygen/ diff --git a/deps/libtomcrypt/helper.pl b/deps/libtomcrypt/helper.pl new file mode 100644 index 0000000..a65df1e --- /dev/null +++ b/deps/libtomcrypt/helper.pl @@ -0,0 +1,411 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Getopt::Long; +use File::Find 'find'; +use File::Basename 'basename'; +use File::Glob 'bsd_glob'; + +sub read_file { + my $f = shift; + open my $fh, "<", $f or die "FATAL: read_rawfile() cannot open file '$f': $!"; + binmode $fh; + return do { local $/; <$fh> }; +} + +sub write_file { + my ($f, $data) = @_; + die "FATAL: write_file() no data" unless defined $data; + open my $fh, ">", $f or die "FATAL: write_file() cannot open file '$f': $!"; + binmode $fh; + print $fh $data or die "FATAL: write_file() cannot write to '$f': $!"; + close $fh or die "FATAL: write_file() cannot close '$f': $!"; + return; +} + +sub check_source { + my @all_files = (bsd_glob("makefile*"), bsd_glob("*.sh"), bsd_glob("*.pl")); + find({ wanted=>sub { push @all_files, $_ if -f $_ }, no_chdir=>1 }, qw/src tests demos/); + + my $fails = 0; + for my $file (sort @all_files) { + next unless $file =~ /\.(c|h|pl|py|sh)$/ || basename($file) =~ /^makefile/i; + my $troubles = {}; + my $lineno = 1; + my $content = read_file($file); + push @{$troubles->{crlf_line_end}}, '?' if $content =~ /\r/; + for my $l (split /\n/, $content) { + push @{$troubles->{merge_conflict}}, $lineno if $l =~ /^(<<<<<<<|=======|>>>>>>>)([^<=>]|$)/; + push @{$troubles->{trailing_space}}, $lineno if $l =~ / $/; + push @{$troubles->{tab}}, $lineno if $l =~ /\t/ && basename($file) !~ /^makefile/i; + push @{$troubles->{non_ascii_char}}, $lineno if $l =~ /[^[:ascii:]]/; + push @{$troubles->{cpp_comment}}, $lineno if $file =~ /\.(c|h)$/ && ($l =~ /\s\/\// || $l =~ /\/\/\s/); + # in ./src we prefer using XMEMCPY, XMALLOC, XFREE ... + push @{$troubles->{unwanted_memcpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemcpy\s*\(/; + push @{$troubles->{unwanted_malloc}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmalloc\s*\(/; + push @{$troubles->{unwanted_realloc}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\brealloc\s*\(/; + push @{$troubles->{unwanted_calloc}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bcalloc\s*\(/; + push @{$troubles->{unwanted_free}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bfree\s*\(/; + push @{$troubles->{unwanted_memset}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemset\s*\(/; + push @{$troubles->{unwanted_memcpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemcpy\s*\(/; + push @{$troubles->{unwanted_memmove}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemmove\s*\(/; + push @{$troubles->{unwanted_memcmp}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bmemcmp\s*\(/; + push @{$troubles->{unwanted_strcmp}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrcmp\s*\(/; + push @{$troubles->{unwanted_strcpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrcpy\s*\(/; + push @{$troubles->{unwanted_strlen}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrlen\s*\(/; + push @{$troubles->{unwanted_strncpy}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bstrncpy\s*\(/; + push @{$troubles->{unwanted_clock}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bclock\s*\(/; + push @{$troubles->{unwanted_qsort}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bqsort\s*\(/; + push @{$troubles->{sizeof_no_brackets}}, $lineno if $file =~ /^src\/.*\.c$/ && $l =~ /\bsizeof\s*[^\(]/; + if ($file =~ m|src/.*\.c$| && + $file !~ m|src/ciphers/.*\.c$| && + $file !~ m|src/math/.+_desc.c$| && + $file !~ m|src/pk/ec25519/tweetnacl.c$| && + $file !~ m|src/stream/sober128/sober128_stream.c$| && + $l =~ /^static(\s+[a-zA-Z0-9_]+)+\s++([^s][a-zA-Z0-9_]+)\s*\(/) { + push @{$troubles->{staticfunc_name}}, "$2"; + } + if ($file =~ m|src/.*\.[ch]$| && $l =~ /^\s*#\s*define\s+(_[A-Z_][a-zA-Z0-9_]*)\b/) { + my $n = $1; + push @{$troubles->{invalid_macro_name}}, "$lineno($n)" + unless ($file eq 'src/headers/tomcrypt_cfg.h' && $n eq '__has_builtin') || + ($file eq 'src/prngs/rng_get_bytes.c' && $n eq '_WIN32_WINNT'); + } + $lineno++; + } + for my $k (sort keys %$troubles) { + warn "[$k] $file line:" . join(",", @{$troubles->{$k}}) . "\n"; + $fails++; + } + } + + warn( $fails > 0 ? "check-source: FAIL $fails\n" : "check-source: PASS\n" ); + return $fails; +} + +sub check_defines { + my $fails = 0; + my $cust_h = read_file("src/headers/tomcrypt_custom.h"); + my $cryp_c = read_file("src/misc/crypt/crypt.c"); + $cust_h =~ s|/\*.*?\*/||sg; # remove comments + $cryp_c =~ s|/\*.*?\*/||sg; # remove comments + my %def = map { $_ => 1 } map { my $x = $_; $x =~ s/^\s*#define\s+(LTC_\S+).*$/$1/; $x } grep { /^\s*#define\s+LTC_\S+/ } split /\n/, $cust_h; + for my $d (sort keys %def) { + next if $d =~ /^LTC_(DH\d+|ECC\d+|ECC_\S+|MPI|MUTEX_\S+\(x\)|NO_\S+)$/; + warn "$d missing in src/misc/crypt/crypt.c\n" and $fails++ if $cryp_c !~ /\Q$d\E/; + } + warn( $fails > 0 ? "check-defines: FAIL $fails\n" : "check-defines: PASS\n" ); + return $fails; +} + +sub check_descriptor { + my $which = shift; + my $what = shift; + my @src; + my @descriptors; + find({ wanted => sub { push @src, $_ if $_ =~ /\.c$/ }, no_chdir=>1 }, "./src/${which}/"); + for my $f (@src) { + my @n = map { my $x = $_; $x =~ s/^.*?ltc_${what}_descriptor\s+(\S+).*$/$1/; $x } grep { $_ =~ /ltc_${what}_descriptor/ } split /\n/, read_file($f); + push @descriptors, @n if @n; + } + my $fails = 0; + for my $d (@descriptors) { + for my $f ("./src/misc/crypt/crypt_register_all_${which}.c") { + my $txt = read_file($f); + warn "$d missing in $f\n" and $fails++ if $txt !~ /\Q$d\E/; + } + } + for my $d (@descriptors) { + for my $f ("./tests/test.c") { + my $txt = read_file($f); + warn "$d missing in $f\n" and $fails++ if $txt !~ /\Q$d\E/; + } + } + my $name = sprintf("%-17s", "check-${which}:"); + warn( $fails > 0 ? "${name}FAIL $fails\n" : "${name}PASS\n" ); + return $fails; +} + +sub check_descriptors { + my $fails = 0; + $fails = $fails + check_descriptor("ciphers", "cipher"); + $fails = $fails + check_descriptor("hashes", "hash"); + $fails = $fails + check_descriptor("prngs", "prng"); + return $fails; +} + +sub check_comments { + my $fails = 0; + my $first_comment = <<'MARKER'; +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +MARKER + my @all_files; + find({ wanted=> sub { push @all_files, $_ if $_ =~ /\.(c|h)$/ }, no_chdir=>1 }, 'demos', 'src', 'tests'); + for my $f (@all_files) { + my $txt = read_file($f); + if ($txt !~ /^\Q$first_comment\E/s) { + warn "[first_comment] $f\n"; + $fails++; + } + } + warn( $fails > 0 ? "check-comments: FAIL $fails\n" : "check-comments: PASS\n" ); + return $fails; +} + +sub prepare_variable { + my ($varname, @list) = @_; + my $output = "$varname="; + my $len = length($output); + foreach my $obj (sort @list) { + $len = $len + length $obj; + $obj =~ s/\*/\$/; + if ($len > 100) { + $output .= "\\\n"; + $len = length $obj; + } + $output .= $obj . ' '; + } + $output =~ s/ $//; + return $output; +} + +sub prepare_msvc_files_xml { + my ($all, $exclude_re, $targets) = @_; + my $last = []; + my $depth = 2; + + # sort files in the same order as visual studio (ugly, I know) + my @parts = (); + for my $orig (@$all) { + my $p = $orig; + $p =~ s|/|/~|g; + $p =~ s|/~([^/]+)$|/$1|g; + # now we have: 'src/pk/rsa/rsa_verify_hash.c' > 'src/~pk/~rsa/rsa_verify_hash.c' + my @l = map { sprintf "% -99s", $_ } split /\//, $p; + push @parts, [ $orig, join(':', @l) ]; + } + my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } @parts; + + my $files = "\r\n"; + for my $full (@sorted) { + my @items = split /\//, $full; # split by '/' + $full =~ s|/|\\|g; # replace '/' bt '\' + shift @items; # drop first one (src) + pop @items; # drop last one (filename.ext) + my $current = \@items; + if (join(':', @$current) ne join(':', @$last)) { + my $common = 0; + $common++ while ($last->[$common] && $current->[$common] && $last->[$common] eq $current->[$common]); + my $back = @$last - $common; + if ($back > 0) { + $files .= ("\t" x --$depth) . "\r\n" for (1..$back); + } + my $fwd = [ @$current ]; splice(@$fwd, 0, $common); + for my $i (0..scalar(@$fwd) - 1) { + $files .= ("\t" x $depth) . "[$i]\"\r\n"; + $files .= ("\t" x $depth) . "\t>\r\n"; + $depth++; + } + $last = $current; + } + $files .= ("\t" x $depth) . "\r\n"; + if ($full =~ $exclude_re) { + for (@$targets) { + $files .= ("\t" x $depth) . "\t\r\n"; + $files .= ("\t" x $depth) . "\t\t\r\n"; + $files .= ("\t" x $depth) . "\t\r\n"; + } + } +########### aes_enc "hack" disabled - discussion: https://github.com/libtom/libtomcrypt/pull/158 +# if ($full eq 'src\ciphers\aes\aes.c') { #hack +# my %cmd = ( +# 'Debug|Win32' => [ 'Debug/aes.obj;Debug/aes_enc.obj', 'cl /nologo /MLd /W3 /Gm /GX /ZI /Od /I "src\headers" /I "..\libtommath" /D "_DEBUG" /D "LTM_DESC" /D "WIN32" /D "_MBCS" /D "_LIB" /D "LTC_SOURCE" /D "USE_LTM" /Fp"Debug/libtomcrypt.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c $(InputPath) cl /nologo /DENCRYPT_ONLY /MLd /W3 /Gm /GX /ZI /Od /I "src\headers" /I "..\libtommath" /D "_DEBUG" /D "LTM_DESC" /D "WIN32" /D "_MBCS" /D "_LIB" /D "LTC_SOURCE" /D "USE_LTM" /Fp"Debug/libtomcrypt.pch" /YX /Fo"Debug/aes_enc.obj" /Fd"Debug/" /FD /GZ /c $(InputPath) ' ], +# 'Release|Win32' => [ 'Release/aes.obj;Release/aes_enc.obj', 'cl /nologo /MLd /W3 /Gm /GX /ZI /Od /I "src\headers" /I "..\libtommath" /D "_DEBUG" /D "LTM_DESC" /D "WIN32" /D "_MBCS" /D "_LIB" /D "LTC_SOURCE" /D "USE_LTM" /Fp"Release/libtomcrypt.pch" /YX /Fo"Release/" /Fd"Release/" /FD /GZ /c $(InputPath) cl /nologo /DENCRYPT_ONLY /MLd /W3 /Gm /GX /ZI /Od /I "src\headers" /I "..\libtommath" /D "_DEBUG" /D "LTM_DESC" /D "WIN32" /D "_MBCS" /D "_LIB" /D "LTC_SOURCE" /D "USE_LTM" /Fp"Release/libtomcrypt.pch" /YX /Fo"Release/aes_enc.obj" /Fd"Release/" /FD /GZ /c $(InputPath) ' ], +# ); +# for (@$targets) { +# next unless $cmd{$_}; +# $files .= ("\t" x $depth) . "\t\r\n"; +# $files .= ("\t" x $depth) . "\t\t\r\n"; +# $files .= ("\t" x $depth) . "\t\r\n"; +# } +# } + $files .= ("\t" x $depth) . "\r\n"; + } + $files .= ("\t" x --$depth) . "\r\n" for (@$last); + $files .= "\t"; + return $files; +} + +sub patch_file { + my ($content, @variables) = @_; + for my $v (@variables) { + if ($v =~ /^([A-Z0-9_]+)\s*=.*$/si) { + my $name = $1; + $content =~ s/\n\Q$name\E\b.*?[^\\]\n/\n$v\n/s; + } + else { + die "patch_file failed: " . substr($v, 0, 30) . ".."; + } + } + return $content; +} + +sub version_from_tomcrypt_h { + my $h = read_file(shift); + if ($h =~ /\n#define\s*SCRYPT\s*"([0-9]+)\.([0-9]+)\.([0-9]+)(\S*)"/s) { + return "VERSION_PC=$1.$2.$3", "VERSION_LT=1:1", "VERSION=$1.$2.$3$4", "PROJECT_NUMBER=$1.$2.$3$4"; + } + else { + die "#define SCRYPT not found in tomcrypt.h"; + } +} + +sub make_sources_cmake { + my ($list, $pub_headers) = @_; + my $output = "set(SOURCES\n"; + + foreach my $obj (sort @$list) { + $output .= $obj . "\n"; + } + $output .= ")\n\n"; + + if ($pub_headers eq "") { + return $output; + } + + $output .= "set(PUBLIC_HEADERS\n"; + + foreach my $obj (sort @$pub_headers) { + $output .= $obj . "\n"; + } + + $output .= ")\n\nset(PRIVATE_HEADERS src/headers/tomcrypt_private.h)\n"; + $output .= "set_property(GLOBAL PROPERTY PUBLIC_HEADERS \$\{PUBLIC_HEADERS\}\)\n\n"; + + return $output; +} + +sub process_makefiles { + my $write = shift; + my $changed_count = 0; + my @c = (); + find({ no_chdir => 1, wanted => sub { push @c, $_ if -f $_ && $_ =~ /\.c$/ && $_ !~ /tab.c$/ } }, 'src'); + my @h = (); + find({ no_chdir => 1, wanted => sub { push @h, $_ if -f $_ && $_ =~ /\.h$/ && $_ !~ /dh_static.h$/ && $_ !~ /tomcrypt_private.h$/ } }, 'src'); + my @all = (); + find({ no_chdir => 1, wanted => sub { push @all, $_ if -f $_ && $_ =~ /\.(c|h)$/ } }, 'src'); + my @t = qw(); + find({ no_chdir => 1, wanted => sub { push @t, $_ if $_ =~ /(common|no_prng|_tests?|test).c$/ } }, 'tests'); + + my @o = sort ('src/ciphers/aes/aes_enc.o', map { my $x = $_; $x =~ s/\.c$/.o/; $x } @c); + my $var_o = prepare_variable("OBJECTS", @o); + my $var_h = prepare_variable("HEADERS_PUB", (sort @h)); + (my $var_obj = $var_o) =~ s/\.o\b/.obj/sg; + + my @t_srcs = sort (map { my $x = $_; $x =~ s/^tests\///; $x } @t); + my $var_to = prepare_variable("TOBJECTS", sort map { my $x = $_; $x =~ s/\.c$/.o/; $x } @t); + (my $var_tobj = $var_to) =~ s/\.o\b/.obj/sg; + + my @ver_version = version_from_tomcrypt_h("src/headers/tomcrypt.h"); + + # update MSVC project files + my $msvc_files = prepare_msvc_files_xml(\@all, qr/tab\.c$/, ['Debug|Win32', 'Release|Win32', 'Debug|x64', 'Release|x64']); + for my $m (qw/libtomcrypt_VS2008.vcproj/) { + my $old = read_file($m); + my $new = $old; + $new =~ s|.*|$msvc_files|s; + if ($old ne $new) { + write_file($m, $new) if $write; + warn "changed: $m\n"; + $changed_count++; + } + } + + # update OBJECTS + HEADERS in makefile* + for my $m (qw/ makefile makefile.shared makefile.unix makefile.mingw makefile.msvc makefile_include.mk doc\/Doxyfile sources.cmake tests\/sources.cmake /) { + my $old = read_file($m); + my $new = $m eq 'makefile.msvc' ? patch_file($old, $var_obj, $var_h, $var_tobj, @ver_version) + : $m eq 'sources.cmake' ? make_sources_cmake(\@all, \@h) + : $m eq 'tests/sources.cmake' ? make_sources_cmake(\@t_srcs, "") + : patch_file($old, $var_o, $var_h, $var_to, @ver_version); + + if ($old ne $new) { + write_file($m, $new) if $write; + warn "changed: $m\n"; + $changed_count++; + } + } + + if ($write) { + return 0; # no failures + } + else { + warn( $changed_count > 0 ? "check-makefiles: FAIL $changed_count\n" : "check-makefiles: PASS\n" ); + return $changed_count; + } +} + +sub die_usage { + die <<"MARKER"; +usage: $0 -s OR $0 --check-source + $0 -c OR $0 --check-descriptors + $0 -d OR $0 --check-defines + $0 -o OR $0 --check-comments + $0 -m OR $0 --check-makefiles + $0 -a OR $0 --check-all + $0 -u OR $0 --update-makefiles + $0 --fixupind crypt.ind +MARKER +} + +GetOptions( "s|check-source" => \my $check_source, + "c|check-descriptors" => \my $check_descriptors, + "d|check-defines" => \my $check_defines, + "o|check-comments" => \my $check_comments, + "m|check-makefiles" => \my $check_makefiles, + "a|check-all" => \my $check_all, + "u|update-makefiles" => \my $update_makefiles, + "f|fixupind=s" => \my $fixupind, + "h|help" => \my $help + ) or die_usage; + +if ($fixupind) { + my $txt = read_file($fixupind); + $txt =~ s/^([^\n]*\n)/$1\n\\addcontentsline{toc}{chapter}{Index}\n/s; + write_file($fixupind, $txt); + exit 0; +} + +my $failure; +$failure ||= check_source() if $check_all || $check_source; +$failure ||= check_defines() if $check_all || $check_defines; +$failure ||= check_descriptors() if $check_all || $check_descriptors; +$failure ||= check_comments() if $check_all || $check_comments; +$failure ||= process_makefiles(0) if $check_all || $check_makefiles; +$failure ||= process_makefiles(1) if $update_makefiles; + +die_usage unless defined $failure; +exit $failure ? 1 : 0; + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/hooks/pre-commit b/deps/libtomcrypt/hooks/pre-commit new file mode 100644 index 0000000..8a82f12 --- /dev/null +++ b/deps/libtomcrypt/hooks/pre-commit @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +fi + +# If you want to allow non-ascii filenames set this variable to true. +allownonascii=$(git config hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ascii filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + echo "Error: Attempt to add a non-ascii file name." + echo + echo "This can cause problems if you want to work" + echo "with people on other platforms." + echo + echo "To be portable it is advisable to rename the file ..." + echo + echo "If you know what you are doing you can disable this" + echo "check using:" + echo + echo " git config hooks.allownonascii true" + echo + exit 1 +fi + +exec perl helper.pl --check-all diff --git a/deps/libtomcrypt/libtomcrypt.pc.in b/deps/libtomcrypt/libtomcrypt.pc.in new file mode 100644 index 0000000..b97cb0d --- /dev/null +++ b/deps/libtomcrypt/libtomcrypt.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@ + +Name: LibTomCrypt +Description: public domain open source cryptographic toolkit +Version: @PROJECT_VERSION@ +Libs: -L${libdir} -ltomcrypt +Cflags: -I${includedir} diff --git a/deps/libtomcrypt/libtomcrypt_VS2008.sln b/deps/libtomcrypt/libtomcrypt_VS2008.sln new file mode 100644 index 0000000..73fe67f --- /dev/null +++ b/deps/libtomcrypt/libtomcrypt_VS2008.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtomcrypt", "libtomcrypt_VS2008.vcproj", "{E3802982-DCB6-4D85-A2BD-6B08F0657E79}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|Win32.ActiveCfg = Debug|Win32 + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|Win32.Build.0 = Debug|Win32 + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|x64.ActiveCfg = Debug|x64 + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Debug|x64.Build.0 = Debug|x64 + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|Win32.ActiveCfg = Release|Win32 + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|Win32.Build.0 = Release|Win32 + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|x64.ActiveCfg = Release|x64 + {E3802982-DCB6-4D85-A2BD-6B08F0657E79}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/deps/libtomcrypt/libtomcrypt_VS2008.vcproj b/deps/libtomcrypt/libtomcrypt_VS2008.vcproj new file mode 100644 index 0000000..0b46da1 --- /dev/null +++ b/deps/libtomcrypt/libtomcrypt_VS2008.vcproj @@ -0,0 +1,2898 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deps/libtomcrypt/makefile b/deps/libtomcrypt/makefile new file mode 100644 index 0000000..32e8072 --- /dev/null +++ b/deps/libtomcrypt/makefile @@ -0,0 +1,142 @@ +# MAKEFILE for linux GCC +# +# Tom St Denis +# Modified by Clay Culver +# +# (GNU make only) + +ifeq ($V,0) +silent_echo= > /dev/null +else +silent_echo= +endif +ifeq ($V,1) +silent= +silent_stdout= +else +silent=@ +silent_stdout= > /dev/null +endif + +PLATFORM := $(shell uname | sed -e 's/_.*//') + +# ranlib tools +ifndef RANLIB +RANLIB:=$(CROSS_COMPILE)ranlib +endif +INSTALL_CMD = install +UNINSTALL_CMD = rm + +#Output filenames for various targets. +ifndef LIBNAME + LIBNAME=libtomcrypt.a +endif + + +include makefile_include.mk + +ifeq ($(COVERAGE),1) +all_test: LIB_PRE = -Wl,--whole-archive +all_test: LIB_POST = -Wl,--no-whole-archive +LTC_CFLAGS += -fprofile-arcs -ftest-coverage +LTC_EXTRALIBS += -lgcov +endif + +LTC_EXTRALIBS += $(EXTRALIBS) + +#AES comes in two flavours... enc+dec and enc +src/ciphers/aes/aes_enc.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c +ifneq ($V,1) + @echo " * ${CC} $@" ${silent_echo} +endif + ${silent} ${CC} ${LTC_CFLAGS} -DENCRYPT_ONLY -c $< -o $@ + +.c.o: +ifneq ($V,1) + @echo " * ${CC} $@" ${silent_echo} +endif + ${silent} ${CC} ${LTC_CFLAGS} -c $< -o $@ + +$(LIBNAME): $(OBJECTS) +ifneq ($V,1) + @echo " * ${AR} $@" ${silent_echo} +endif + ${silent} $(AR) $(ARFLAGS) $@ $(OBJECTS) +ifneq ($V,1) + @echo " * ${RANLIB} $@" ${silent_echo} +endif + ${silent} $(RANLIB) $@ + +test: $(call print-help,test,Builds the library and the 'test' application to run all self-tests) $(LIBNAME) $(TOBJECTS) +ifneq ($V,1) + @echo " * ${CC} $@" ${silent_echo} +endif + ${silent} $(CC) $(LTC_LDFLAGS) $(TOBJECTS) $(LIB_PRE) $(LIBNAME) $(LIB_POST) $(LTC_EXTRALIBS) -o $(TEST) + +# build the demos from a template +define DEMO_template +$(1): $(call print-help,$(1),Builds the library and the '$(1)' demo) demos/$(1).o $$(LIBNAME) +ifneq ($V,1) + @echo " * $${CC} $$@" ${silent_echo} +endif + $${silent} $$(CC) $$(LTC_LDFLAGS) $$< $$(LIB_PRE) $$(LIBNAME) $$(LIB_POST) $$(LTC_EXTRALIBS) -o $(1) +endef + +$(foreach demo, $(strip $(DEMOS)), $(eval $(call DEMO_template,$(demo)))) + + +#This rule installs the library and the header files. This must be run +#as root in order to have a high enough permission to write to the correct +#directories and to set the owner and group to root. +install: $(call print-help,install,Installs the library and headers) .common_install + +install_bins: $(call print-help,install_bins,Installs the useful demos ($(USEFUL_DEMOS))) .common_install_bins + +uninstall: $(call print-help,uninstall,Uninstalls the library and headers) .common_uninstall + +profile: + LTC_CFLAGS="$(LTC_CFLAGS) -fprofile-generate" $(MAKE) timing EXTRALIBS="$(LTC_EXTRALIBS) -lgcov" + ./timing + rm -f timing `find . -type f | grep [.][ao] | xargs` + LTC_CFLAGS="$(LTC_CFLAGS) -fprofile-use" $(MAKE) timing EXTRALIBS="$(LTC_EXTRALIBS) -lgcov" + +# target that pre-processes all coverage data +lcov-single-create: + lcov --capture --no-external --directory src -q --output-file coverage_std.info + +# target that removes all coverage output +cleancov-clean: + rm -f `find . -type f -name "*.info" | xargs` + rm -rf coverage/ + +# merges all coverage_*.info files into coverage.info +coverage.info: + lcov `find -name 'coverage_*.info' -exec echo -n " -a {}" \;` -o coverage.info + +# generates html output from all coverage_*.info files +lcov-html: coverage.info + genhtml coverage.info --output-directory coverage -q + +# combines all necessary steps to create the coverage from a single testrun with e.g. +# CFLAGS="-DUSE_LTM -DLTM_DESC -I../libtommath" EXTRALIBS="../libtommath/libtommath.a" make coverage -j9 +lcov-single: + $(MAKE) cleancov-clean + $(MAKE) lcov-single-create + $(MAKE) coverage.info + + +#make the code coverage of the library +coverage: LTC_CFLAGS += -fprofile-arcs -ftest-coverage +coverage: LTC_EXTRALIBS += -lgcov +coverage: LIB_PRE = -Wl,--whole-archive +coverage: LIB_POST = -Wl,--no-whole-archive + +coverage: $(call print-help,coverage,Create code-coverage of the library - but better use coverage.sh) test + ./test + +# cleans everything - coverage output and standard 'clean' +cleancov: cleancov-clean clean + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/makefile.mingw b/deps/libtomcrypt/makefile.mingw new file mode 100644 index 0000000..7a691f0 --- /dev/null +++ b/deps/libtomcrypt/makefile.mingw @@ -0,0 +1,328 @@ +# MAKEFILE for MS Windows (mingw + gcc + gmake) +# +# BEWARE: variables OBJECTS, TOBJECTS, HEADERS, VERSION are updated via ./updatemakes.sh + +### USAGE: +# Open a command prompt with gcc + gmake in PATH and start: +# +# gmake -f makefile.mingw all +# test.exe +# gmake -f makefile.mingw PREFIX=c:\devel\libtom install +# +#Or: +# +# gmake -f makefile.mingw CFLAGS="-O3 -DUSE_LTM -DLTM_DESC -Ic:/path/to/libtommath" EXTRALIBS="-Lc:/path/to/libtommath -ltommath" all +# + +#The following can be overridden from command line e.g. make -f makefile.mingw CC=gcc ARFLAGS=rcs +PREFIX = c:\mingw +CC = gcc +AR = ar +ARFLAGS = r +RANLIB = ranlib +STRIP = strip +CFLAGS = -O2 -DUSE_LTM -DLTM_DESC -I../libtommath +EXTRALIBS = -L../libtommath -ltommath + +#Compilation flags +LTC_CFLAGS = -Isrc/headers -Itests -DLTC_SOURCE $(CFLAGS) +LTC_LDFLAGS = $(LDFLAGS) $(EXTRALIBS) +VERSION=1.18.2-develop + +#Libraries to be created +LIBMAIN_S =libtomcrypt.a +LIBMAIN_I =libtomcrypt.dll.a +LIBMAIN_D =libtomcrypt.dll + +#List of objects to compile (all goes to libtomcrypt.a) +OBJECTS=src/ciphers/aes/aes.o src/ciphers/aes/aes_enc.o src/ciphers/anubis.o src/ciphers/blowfish.o \ +src/ciphers/camellia.o src/ciphers/cast5.o src/ciphers/des.o src/ciphers/idea.o src/ciphers/kasumi.o \ +src/ciphers/khazad.o src/ciphers/kseed.o src/ciphers/multi2.o src/ciphers/noekeon.o src/ciphers/rc2.o \ +src/ciphers/rc5.o src/ciphers/rc6.o src/ciphers/safer/safer.o src/ciphers/safer/saferp.o \ +src/ciphers/serpent.o src/ciphers/skipjack.o src/ciphers/tea.o src/ciphers/twofish/twofish.o \ +src/ciphers/xtea.o src/encauth/ccm/ccm_add_aad.o src/encauth/ccm/ccm_add_nonce.o \ +src/encauth/ccm/ccm_done.o src/encauth/ccm/ccm_init.o src/encauth/ccm/ccm_memory.o \ +src/encauth/ccm/ccm_process.o src/encauth/ccm/ccm_reset.o src/encauth/ccm/ccm_test.o \ +src/encauth/chachapoly/chacha20poly1305_add_aad.o src/encauth/chachapoly/chacha20poly1305_decrypt.o \ +src/encauth/chachapoly/chacha20poly1305_done.o src/encauth/chachapoly/chacha20poly1305_encrypt.o \ +src/encauth/chachapoly/chacha20poly1305_init.o src/encauth/chachapoly/chacha20poly1305_memory.o \ +src/encauth/chachapoly/chacha20poly1305_setiv.o \ +src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.o \ +src/encauth/chachapoly/chacha20poly1305_test.o src/encauth/eax/eax_addheader.o \ +src/encauth/eax/eax_decrypt.o src/encauth/eax/eax_decrypt_verify_memory.o src/encauth/eax/eax_done.o \ +src/encauth/eax/eax_encrypt.o src/encauth/eax/eax_encrypt_authenticate_memory.o \ +src/encauth/eax/eax_init.o src/encauth/eax/eax_test.o src/encauth/gcm/gcm_add_aad.o \ +src/encauth/gcm/gcm_add_iv.o src/encauth/gcm/gcm_done.o src/encauth/gcm/gcm_gf_mult.o \ +src/encauth/gcm/gcm_init.o src/encauth/gcm/gcm_memory.o src/encauth/gcm/gcm_mult_h.o \ +src/encauth/gcm/gcm_process.o src/encauth/gcm/gcm_reset.o src/encauth/gcm/gcm_test.o \ +src/encauth/ocb/ocb_decrypt.o src/encauth/ocb/ocb_decrypt_verify_memory.o \ +src/encauth/ocb/ocb_done_decrypt.o src/encauth/ocb/ocb_done_encrypt.o src/encauth/ocb/ocb_encrypt.o \ +src/encauth/ocb/ocb_encrypt_authenticate_memory.o src/encauth/ocb/ocb_init.o src/encauth/ocb/ocb_ntz.o \ +src/encauth/ocb/ocb_shift_xor.o src/encauth/ocb/ocb_test.o src/encauth/ocb/s_ocb_done.o \ +src/encauth/ocb3/ocb3_add_aad.o src/encauth/ocb3/ocb3_decrypt.o src/encauth/ocb3/ocb3_decrypt_last.o \ +src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \ +src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \ +src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \ +src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/hashes/blake2b.o \ +src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \ +src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ +src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \ +src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \ +src/hashes/sha2/sha224.o src/hashes/sha2/sha256.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \ +src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \ +src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ +src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \ +src/mac/blake2/blake2bmac_memory_multi.o src/mac/blake2/blake2bmac_test.o src/mac/blake2/blake2smac.o \ +src/mac/blake2/blake2smac_file.o src/mac/blake2/blake2smac_memory.o \ +src/mac/blake2/blake2smac_memory_multi.o src/mac/blake2/blake2smac_test.o src/mac/f9/f9_done.o \ +src/mac/f9/f9_file.o src/mac/f9/f9_init.o src/mac/f9/f9_memory.o src/mac/f9/f9_memory_multi.o \ +src/mac/f9/f9_process.o src/mac/f9/f9_test.o src/mac/hmac/hmac_done.o src/mac/hmac/hmac_file.o \ +src/mac/hmac/hmac_init.o src/mac/hmac/hmac_memory.o src/mac/hmac/hmac_memory_multi.o \ +src/mac/hmac/hmac_process.o src/mac/hmac/hmac_test.o src/mac/omac/omac_done.o src/mac/omac/omac_file.o \ +src/mac/omac/omac_init.o src/mac/omac/omac_memory.o src/mac/omac/omac_memory_multi.o \ +src/mac/omac/omac_process.o src/mac/omac/omac_test.o src/mac/pelican/pelican.o \ +src/mac/pelican/pelican_memory.o src/mac/pelican/pelican_test.o src/mac/pmac/pmac_done.o \ +src/mac/pmac/pmac_file.o src/mac/pmac/pmac_init.o src/mac/pmac/pmac_memory.o \ +src/mac/pmac/pmac_memory_multi.o src/mac/pmac/pmac_ntz.o src/mac/pmac/pmac_process.o \ +src/mac/pmac/pmac_shift_xor.o src/mac/pmac/pmac_test.o src/mac/poly1305/poly1305.o \ +src/mac/poly1305/poly1305_file.o src/mac/poly1305/poly1305_memory.o \ +src/mac/poly1305/poly1305_memory_multi.o src/mac/poly1305/poly1305_test.o src/mac/xcbc/xcbc_done.o \ +src/mac/xcbc/xcbc_file.o src/mac/xcbc/xcbc_init.o src/mac/xcbc/xcbc_memory.o \ +src/mac/xcbc/xcbc_memory_multi.o src/mac/xcbc/xcbc_process.o src/mac/xcbc/xcbc_test.o \ +src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math/multi.o \ +src/math/radix_to_bin.o src/math/rand_bn.o src/math/rand_prime.o src/math/tfm_desc.o src/misc/adler32.o \ +src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \ +src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \ +src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \ +src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \ +src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \ +src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \ +src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \ +src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \ +src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \ +src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \ +src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \ +src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \ +src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \ +src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \ +src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ +src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ +src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ +src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ +src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ +src/misc/padding/padding_pad.o src/misc/pbes/pbes.o src/misc/pbes/pbes1.o src/misc/pbes/pbes2.o \ +src/misc/pkcs12/pkcs12_kdf.o src/misc/pkcs12/pkcs12_utf8_to_utf16.o src/misc/pkcs5/pkcs_5_1.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/pkcs5/pkcs_5_test.o src/misc/ssh/ssh_decode_sequence_multi.o \ +src/misc/ssh/ssh_encode_sequence_multi.o src/misc/zeromem.o src/modes/cbc/cbc_decrypt.o \ +src/modes/cbc/cbc_done.o src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o \ +src/modes/cbc/cbc_setiv.o src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o \ +src/modes/cfb/cfb_done.o src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o \ +src/modes/cfb/cfb_setiv.o src/modes/cfb/cfb_start.o src/modes/ctr/ctr_decrypt.o \ +src/modes/ctr/ctr_done.o src/modes/ctr/ctr_encrypt.o src/modes/ctr/ctr_getiv.o \ +src/modes/ctr/ctr_setiv.o src/modes/ctr/ctr_start.o src/modes/ctr/ctr_test.o \ +src/modes/ecb/ecb_decrypt.o src/modes/ecb/ecb_done.o src/modes/ecb/ecb_encrypt.o \ +src/modes/ecb/ecb_start.o src/modes/f8/f8_decrypt.o src/modes/f8/f8_done.o src/modes/f8/f8_encrypt.o \ +src/modes/f8/f8_getiv.o src/modes/f8/f8_setiv.o src/modes/f8/f8_start.o src/modes/f8/f8_test_mode.o \ +src/modes/lrw/lrw_decrypt.o src/modes/lrw/lrw_done.o src/modes/lrw/lrw_encrypt.o \ +src/modes/lrw/lrw_getiv.o src/modes/lrw/lrw_process.o src/modes/lrw/lrw_setiv.o \ +src/modes/lrw/lrw_start.o src/modes/lrw/lrw_test.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \ +src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \ +src/modes/ofb/ofb_start.o src/modes/xts/xts_decrypt.o src/modes/xts/xts_done.o \ +src/modes/xts/xts_encrypt.o src/modes/xts/xts_init.o src/modes/xts/xts_mult_x.o \ +src/modes/xts/xts_test.o src/pk/asn1/der/bit/der_decode_bit_string.o \ +src/pk/asn1/der/bit/der_decode_raw_bit_string.o src/pk/asn1/der/bit/der_encode_bit_string.o \ +src/pk/asn1/der/bit/der_encode_raw_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \ +src/pk/asn1/der/boolean/der_decode_boolean.o src/pk/asn1/der/boolean/der_encode_boolean.o \ +src/pk/asn1/der/boolean/der_length_boolean.o src/pk/asn1/der/choice/der_decode_choice.o \ +src/pk/asn1/der/custom_type/der_decode_custom_type.o \ +src/pk/asn1/der/custom_type/der_encode_custom_type.o \ +src/pk/asn1/der/custom_type/der_length_custom_type.o src/pk/asn1/der/general/der_asn1_maps.o \ +src/pk/asn1/der/general/der_decode_asn1_identifier.o src/pk/asn1/der/general/der_decode_asn1_length.o \ +src/pk/asn1/der/general/der_encode_asn1_identifier.o src/pk/asn1/der/general/der_encode_asn1_length.o \ +src/pk/asn1/der/general/der_length_asn1_identifier.o src/pk/asn1/der/general/der_length_asn1_length.o \ +src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \ +src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.o \ +src/pk/asn1/der/generalizedtime/der_length_generalizedtime.o \ +src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \ +src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \ +src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.o \ +src/pk/asn1/der/octet/der_decode_octet_string.o src/pk/asn1/der/octet/der_encode_octet_string.o \ +src/pk/asn1/der/octet/der_length_octet_string.o \ +src/pk/asn1/der/printable_string/der_decode_printable_string.o \ +src/pk/asn1/der/printable_string/der_encode_printable_string.o \ +src/pk/asn1/der/printable_string/der_length_printable_string.o \ +src/pk/asn1/der/sequence/der_decode_sequence_ex.o \ +src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \ +src/pk/asn1/der/sequence/der_decode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_encode_sequence_ex.o \ +src/pk/asn1/der/sequence/der_encode_sequence_multi.o src/pk/asn1/der/sequence/der_length_sequence.o \ +src/pk/asn1/der/sequence/der_sequence_free.o src/pk/asn1/der/sequence/der_sequence_shrink.o \ +src/pk/asn1/der/set/der_encode_set.o src/pk/asn1/der/set/der_encode_setof.o \ +src/pk/asn1/der/short_integer/der_decode_short_integer.o \ +src/pk/asn1/der/short_integer/der_encode_short_integer.o \ +src/pk/asn1/der/short_integer/der_length_short_integer.o \ +src/pk/asn1/der/teletex_string/der_decode_teletex_string.o \ +src/pk/asn1/der/teletex_string/der_length_teletex_string.o \ +src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \ +src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \ +src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \ +src/pk/asn1/oid/pk_get_oid.o src/pk/asn1/oid/pk_oid_cmp.o src/pk/asn1/oid/pk_oid_str.o \ +src/pk/asn1/pkcs8/pkcs8_decode_flexi.o src/pk/asn1/x509/x509_decode_public_key_from_certificate.o \ +src/pk/asn1/x509/x509_decode_subject_public_key_info.o \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \ +src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \ +src/pk/dh/dh_import.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o \ +src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \ +src/pk/dsa/dsa_generate_key.o src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o \ +src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_set.o src/pk/dsa/dsa_set_pqg_dsaparam.o \ +src/pk/dsa/dsa_shared_secret.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \ +src/pk/dsa/dsa_verify_key.o src/pk/ec25519/ec25519_crypto_ctx.o src/pk/ec25519/ec25519_export.o \ +src/pk/ec25519/ec25519_import_pkcs8.o src/pk/ec25519/tweetnacl.o src/pk/ecc/ecc.o \ +src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \ +src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_export_openssl.o \ +src/pk/ecc/ecc_find_curve.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_key.o src/pk/ecc/ecc_get_oid_str.o \ +src/pk/ecc/ecc_get_size.o src/pk/ecc/ecc_import.o src/pk/ecc/ecc_import_openssl.o \ +src/pk/ecc/ecc_import_pkcs8.o src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_key.o \ +src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o \ +src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ +src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ +src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ +src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ +src/pk/ecc/ltc_ecc_verify_key.o src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o \ +src/pk/ed25519/ed25519_import_pkcs8.o src/pk/ed25519/ed25519_import_raw.o \ +src/pk/ed25519/ed25519_import_x509.o src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o \ +src/pk/ed25519/ed25519_verify.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ +src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ +src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \ +src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ +src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_get_size.o src/pk/rsa/rsa_import.o \ +src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o src/pk/rsa/rsa_key.o \ +src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \ +src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \ +src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_raw.o \ +src/pk/x25519/x25519_import_x509.o src/pk/x25519/x25519_make_key.o \ +src/pk/x25519/x25519_shared_secret.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ +src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o \ +src/prngs/yarrow.o src/stream/chacha/chacha_crypt.o src/stream/chacha/chacha_done.o \ +src/stream/chacha/chacha_ivctr32.o src/stream/chacha/chacha_ivctr64.o \ +src/stream/chacha/chacha_keystream.o src/stream/chacha/chacha_memory.o \ +src/stream/chacha/chacha_setup.o src/stream/chacha/chacha_test.o src/stream/rabbit/rabbit.o \ +src/stream/rabbit/rabbit_memory.o src/stream/rc4/rc4_stream.o src/stream/rc4/rc4_stream_memory.o \ +src/stream/rc4/rc4_test.o src/stream/salsa20/salsa20_crypt.o src/stream/salsa20/salsa20_done.o \ +src/stream/salsa20/salsa20_ivctr64.o src/stream/salsa20/salsa20_keystream.o \ +src/stream/salsa20/salsa20_memory.o src/stream/salsa20/salsa20_setup.o \ +src/stream/salsa20/salsa20_test.o src/stream/salsa20/xsalsa20_memory.o \ +src/stream/salsa20/xsalsa20_setup.o src/stream/salsa20/xsalsa20_test.o \ +src/stream/sober128/sober128_stream.o src/stream/sober128/sober128_stream_memory.o \ +src/stream/sober128/sober128_test.o src/stream/sosemanuk/sosemanuk.o \ +src/stream/sosemanuk/sosemanuk_memory.o src/stream/sosemanuk/sosemanuk_test.o + +#List of test objects to compile +TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ +tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ +tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ +tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_null_termination_check_test.o \ +tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ +tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ +tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o + +#The following headers will be installed by "make install" +HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ +src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ +src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ +src/headers/tomcrypt_prng.h + +HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h + +#The default rule for make builds the libtomcrypt.a library (static) +default: $(LIBMAIN_S) + +#SPECIAL: AES comes in two flavours - enc+dec and enc-only +src/ciphers/aes/aes_enc.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c + $(CC) $(LTC_CFLAGS) -DENCRYPT_ONLY -c src/ciphers/aes/aes.c -o src/ciphers/aes/aes_enc.o + +#SPECIAL: these are the rules to make certain object files +src/ciphers/aes/aes.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c +src/ciphers/twofish/twofish.o: src/ciphers/twofish/twofish.c src/ciphers/twofish/twofish_tab.c +src/hashes/sha2/sha256.o: src/hashes/sha2/sha256.c src/hashes/sha2/sha224.c +src/hashes/sha2/sha384.o: src/hashes/sha2/sha384.c src/hashes/sha2/sha512.c +src/hashes/sha2/sha512.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha384.c +src/hashes/sha2/sha512_224.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_224.c +src/hashes/sha2/sha512_256.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_256.c +src/hashes/whirl/whirl.o: src/hashes/whirl/whirl.c src/hashes/whirl/whirltab.c + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) +$(TOBJECTS): $(HEADERS) tests/tomcrypt_test.h + +.c.o: + $(CC) $(LTC_CFLAGS) -c $< -o $@ + +#Create libtomcrypt.a +$(LIBMAIN_S): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + $(RANLIB) $@ + +#Create DLL + import library libtomcrypt.dll.a +$(LIBMAIN_D) $(LIBMAIN_I): $(OBJECTS) + $(CC) -s -shared -o $(LIBMAIN_D) $^ -Wl,--enable-auto-import,--export-all -Wl,--out-implib=$(LIBMAIN_I) $(LTC_LDFLAGS) + $(STRIP) -S $(LIBMAIN_D) + +#Demo tools/utilities +hashsum.exe: demos/hashsum.o $(LIBMAIN_S) + $(CC) demos/hashsum.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +ltcrypt.exe: demos/ltcrypt.o $(LIBMAIN_S) + $(CC) demos/ltcrypt.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +small.exe: demos/small.o $(LIBMAIN_S) + $(CC) demos/small.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +tv_gen.exe: demos/tv_gen.o $(LIBMAIN_S) + $(CC) demos/tv_gen.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +sizes.exe: demos/sizes.o $(LIBMAIN_S) + $(CC) demos/sizes.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +constants.exe: demos/constants.o $(LIBMAIN_S) + $(CC) demos/constants.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +timing.exe: demos/timing.o $(LIBMAIN_S) + $(CC) demos/timing.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ + +#Tests +test.exe: $(TOBJECTS) $(LIBMAIN_S) + $(CC) $(TOBJECTS) $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ + @echo NOTICE: start the tests by launching test.exe + +all: $(LIBMAIN_S) $(LIBMAIN_I) $(LIBMAIN_D) hashsum.exe ltcrypt.exe small.exe tv_gen.exe sizes.exe constants.exe timing.exe test.exe + +test: test.exe + +clean: + @-cmd /c del /Q *_tv.txt 2>nul + @-cmd /c del /Q /S *.o *.a *.exe *.dll 2>nul + +#Install the library + headers +install: $(LIBMAIN_S) $(LIBMAIN_I) $(LIBMAIN_D) + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + cmd /c if not exist "$(PREFIX)\lib" mkdir "$(PREFIX)\lib" + cmd /c if not exist "$(PREFIX)\include" mkdir "$(PREFIX)\include" + copy /Y $(LIBMAIN_S) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_I) "$(PREFIX)\lib" + copy /Y $(LIBMAIN_D) "$(PREFIX)\bin" + copy /Y src\headers\tomcrypt*.h "$(PREFIX)\include" + +#Install useful tools +install_bins: hashsum + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + copy /Y hashsum.exe "$(PREFIX)\bin" + +#Install documentation +install_docs: doc/crypt.pdf + cmd /c if not exist "$(PREFIX)\doc" mkdir "$(PREFIX)\doc" + copy /Y doc\crypt.pdf "$(PREFIX)\doc" + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/makefile.msvc b/deps/libtomcrypt/makefile.msvc new file mode 100644 index 0000000..1a04721 --- /dev/null +++ b/deps/libtomcrypt/makefile.msvc @@ -0,0 +1,313 @@ +# MAKEFILE for MS Windows (nmake + Windows SDK) +# +# BEWARE: variables OBJECTS, TOBJECTS, HEADERS, VERSION are updated via ./updatemakes.sh + +### USAGE: +# Open a command prompt with WinSDK variables set and start: +# +# nmake -f makefile.msvc all +# test.exe +# nmake -f makefile.msvc PREFIX=c:\devel\libtom install +# +#Or: +# +# nmake -f makefile.msvc CFLAGS="/DUSE_LTM /DLTM_DESC /Ic:\path\to\libtommath" EXTRALIBS=c:\path\to\libtommath\tommath.lib all +# + +#The following can be overridden from command line e.g. make -f makefile.msvc CC=gcc ARFLAGS=rcs +PREFIX = c:\devel +CFLAGS = /Ox /DUSE_LTM /DLTM_DESC /I../libtommath +EXTRALIBS = ../libtommath/tommath.lib + +#Compilation flags +LTC_CFLAGS = /nologo /Isrc/headers/ /Itests/ /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_DEPRECATE /DLTC_SOURCE /W3 $(CFLAGS) +LTC_LDFLAGS = advapi32.lib $(EXTRALIBS) +VERSION=1.18.2-develop + +#Libraries to be created (this makefile builds only static libraries) +LIBMAIN_S =tomcrypt.lib + +#List of objects to compile (all goes to tomcrypt.lib) +OBJECTS=src/ciphers/aes/aes.obj src/ciphers/aes/aes_enc.obj src/ciphers/anubis.obj src/ciphers/blowfish.obj \ +src/ciphers/camellia.obj src/ciphers/cast5.obj src/ciphers/des.obj src/ciphers/idea.obj src/ciphers/kasumi.obj \ +src/ciphers/khazad.obj src/ciphers/kseed.obj src/ciphers/multi2.obj src/ciphers/noekeon.obj src/ciphers/rc2.obj \ +src/ciphers/rc5.obj src/ciphers/rc6.obj src/ciphers/safer/safer.obj src/ciphers/safer/saferp.obj \ +src/ciphers/serpent.obj src/ciphers/skipjack.obj src/ciphers/tea.obj src/ciphers/twofish/twofish.obj \ +src/ciphers/xtea.obj src/encauth/ccm/ccm_add_aad.obj src/encauth/ccm/ccm_add_nonce.obj \ +src/encauth/ccm/ccm_done.obj src/encauth/ccm/ccm_init.obj src/encauth/ccm/ccm_memory.obj \ +src/encauth/ccm/ccm_process.obj src/encauth/ccm/ccm_reset.obj src/encauth/ccm/ccm_test.obj \ +src/encauth/chachapoly/chacha20poly1305_add_aad.obj src/encauth/chachapoly/chacha20poly1305_decrypt.obj \ +src/encauth/chachapoly/chacha20poly1305_done.obj src/encauth/chachapoly/chacha20poly1305_encrypt.obj \ +src/encauth/chachapoly/chacha20poly1305_init.obj src/encauth/chachapoly/chacha20poly1305_memory.obj \ +src/encauth/chachapoly/chacha20poly1305_setiv.obj \ +src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.obj \ +src/encauth/chachapoly/chacha20poly1305_test.obj src/encauth/eax/eax_addheader.obj \ +src/encauth/eax/eax_decrypt.obj src/encauth/eax/eax_decrypt_verify_memory.obj src/encauth/eax/eax_done.obj \ +src/encauth/eax/eax_encrypt.obj src/encauth/eax/eax_encrypt_authenticate_memory.obj \ +src/encauth/eax/eax_init.obj src/encauth/eax/eax_test.obj src/encauth/gcm/gcm_add_aad.obj \ +src/encauth/gcm/gcm_add_iv.obj src/encauth/gcm/gcm_done.obj src/encauth/gcm/gcm_gf_mult.obj \ +src/encauth/gcm/gcm_init.obj src/encauth/gcm/gcm_memory.obj src/encauth/gcm/gcm_mult_h.obj \ +src/encauth/gcm/gcm_process.obj src/encauth/gcm/gcm_reset.obj src/encauth/gcm/gcm_test.obj \ +src/encauth/ocb/ocb_decrypt.obj src/encauth/ocb/ocb_decrypt_verify_memory.obj \ +src/encauth/ocb/ocb_done_decrypt.obj src/encauth/ocb/ocb_done_encrypt.obj src/encauth/ocb/ocb_encrypt.obj \ +src/encauth/ocb/ocb_encrypt_authenticate_memory.obj src/encauth/ocb/ocb_init.obj src/encauth/ocb/ocb_ntz.obj \ +src/encauth/ocb/ocb_shift_xor.obj src/encauth/ocb/ocb_test.obj src/encauth/ocb/s_ocb_done.obj \ +src/encauth/ocb3/ocb3_add_aad.obj src/encauth/ocb3/ocb3_decrypt.obj src/encauth/ocb3/ocb3_decrypt_last.obj \ +src/encauth/ocb3/ocb3_decrypt_verify_memory.obj src/encauth/ocb3/ocb3_done.obj \ +src/encauth/ocb3/ocb3_encrypt.obj src/encauth/ocb3/ocb3_encrypt_authenticate_memory.obj \ +src/encauth/ocb3/ocb3_encrypt_last.obj src/encauth/ocb3/ocb3_init.obj src/encauth/ocb3/ocb3_int_ntz.obj \ +src/encauth/ocb3/ocb3_int_xor_blocks.obj src/encauth/ocb3/ocb3_test.obj src/hashes/blake2b.obj \ +src/hashes/blake2s.obj src/hashes/chc/chc.obj src/hashes/helper/hash_file.obj \ +src/hashes/helper/hash_filehandle.obj src/hashes/helper/hash_memory.obj \ +src/hashes/helper/hash_memory_multi.obj src/hashes/md2.obj src/hashes/md4.obj src/hashes/md5.obj \ +src/hashes/rmd128.obj src/hashes/rmd160.obj src/hashes/rmd256.obj src/hashes/rmd320.obj src/hashes/sha1.obj \ +src/hashes/sha2/sha224.obj src/hashes/sha2/sha256.obj src/hashes/sha2/sha384.obj src/hashes/sha2/sha512.obj \ +src/hashes/sha2/sha512_224.obj src/hashes/sha2/sha512_256.obj src/hashes/sha3.obj src/hashes/sha3_test.obj \ +src/hashes/tiger.obj src/hashes/whirl/whirl.obj src/mac/blake2/blake2bmac.obj \ +src/mac/blake2/blake2bmac_file.obj src/mac/blake2/blake2bmac_memory.obj \ +src/mac/blake2/blake2bmac_memory_multi.obj src/mac/blake2/blake2bmac_test.obj src/mac/blake2/blake2smac.obj \ +src/mac/blake2/blake2smac_file.obj src/mac/blake2/blake2smac_memory.obj \ +src/mac/blake2/blake2smac_memory_multi.obj src/mac/blake2/blake2smac_test.obj src/mac/f9/f9_done.obj \ +src/mac/f9/f9_file.obj src/mac/f9/f9_init.obj src/mac/f9/f9_memory.obj src/mac/f9/f9_memory_multi.obj \ +src/mac/f9/f9_process.obj src/mac/f9/f9_test.obj src/mac/hmac/hmac_done.obj src/mac/hmac/hmac_file.obj \ +src/mac/hmac/hmac_init.obj src/mac/hmac/hmac_memory.obj src/mac/hmac/hmac_memory_multi.obj \ +src/mac/hmac/hmac_process.obj src/mac/hmac/hmac_test.obj src/mac/omac/omac_done.obj src/mac/omac/omac_file.obj \ +src/mac/omac/omac_init.obj src/mac/omac/omac_memory.obj src/mac/omac/omac_memory_multi.obj \ +src/mac/omac/omac_process.obj src/mac/omac/omac_test.obj src/mac/pelican/pelican.obj \ +src/mac/pelican/pelican_memory.obj src/mac/pelican/pelican_test.obj src/mac/pmac/pmac_done.obj \ +src/mac/pmac/pmac_file.obj src/mac/pmac/pmac_init.obj src/mac/pmac/pmac_memory.obj \ +src/mac/pmac/pmac_memory_multi.obj src/mac/pmac/pmac_ntz.obj src/mac/pmac/pmac_process.obj \ +src/mac/pmac/pmac_shift_xor.obj src/mac/pmac/pmac_test.obj src/mac/poly1305/poly1305.obj \ +src/mac/poly1305/poly1305_file.obj src/mac/poly1305/poly1305_memory.obj \ +src/mac/poly1305/poly1305_memory_multi.obj src/mac/poly1305/poly1305_test.obj src/mac/xcbc/xcbc_done.obj \ +src/mac/xcbc/xcbc_file.obj src/mac/xcbc/xcbc_init.obj src/mac/xcbc/xcbc_memory.obj \ +src/mac/xcbc/xcbc_memory_multi.obj src/mac/xcbc/xcbc_process.obj src/mac/xcbc/xcbc_test.obj \ +src/math/fp/ltc_ecc_fp_mulmod.obj src/math/gmp_desc.obj src/math/ltm_desc.obj src/math/multi.obj \ +src/math/radix_to_bin.obj src/math/rand_bn.obj src/math/rand_prime.obj src/math/tfm_desc.obj src/misc/adler32.obj \ +src/misc/base16/base16_decode.obj src/misc/base16/base16_encode.obj src/misc/base32/base32_decode.obj \ +src/misc/base32/base32_encode.obj src/misc/base64/base64_decode.obj src/misc/base64/base64_encode.obj \ +src/misc/bcrypt/bcrypt.obj src/misc/burn_stack.obj src/misc/compare_testvector.obj src/misc/copy_or_zeromem.obj \ +src/misc/crc32.obj src/misc/crypt/crypt.obj src/misc/crypt/crypt_argchk.obj \ +src/misc/crypt/crypt_cipher_descriptor.obj src/misc/crypt/crypt_cipher_is_valid.obj \ +src/misc/crypt/crypt_constants.obj src/misc/crypt/crypt_find_cipher.obj \ +src/misc/crypt/crypt_find_cipher_any.obj src/misc/crypt/crypt_find_cipher_id.obj \ +src/misc/crypt/crypt_find_hash.obj src/misc/crypt/crypt_find_hash_any.obj \ +src/misc/crypt/crypt_find_hash_id.obj src/misc/crypt/crypt_find_hash_oid.obj \ +src/misc/crypt/crypt_find_prng.obj src/misc/crypt/crypt_fsa.obj src/misc/crypt/crypt_hash_descriptor.obj \ +src/misc/crypt/crypt_hash_is_valid.obj src/misc/crypt/crypt_inits.obj \ +src/misc/crypt/crypt_ltc_mp_descriptor.obj src/misc/crypt/crypt_prng_descriptor.obj \ +src/misc/crypt/crypt_prng_is_valid.obj src/misc/crypt/crypt_prng_rng_descriptor.obj \ +src/misc/crypt/crypt_register_all_ciphers.obj src/misc/crypt/crypt_register_all_hashes.obj \ +src/misc/crypt/crypt_register_all_prngs.obj src/misc/crypt/crypt_register_cipher.obj \ +src/misc/crypt/crypt_register_hash.obj src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \ +src/misc/crypt/crypt_unregister_cipher.obj src/misc/crypt/crypt_unregister_hash.obj \ +src/misc/crypt/crypt_unregister_prng.obj src/misc/error_to_string.obj src/misc/hkdf/hkdf.obj \ +src/misc/hkdf/hkdf_test.obj src/misc/mem_neq.obj src/misc/padding/padding_depad.obj \ +src/misc/padding/padding_pad.obj src/misc/pbes/pbes.obj src/misc/pbes/pbes1.obj src/misc/pbes/pbes2.obj \ +src/misc/pkcs12/pkcs12_kdf.obj src/misc/pkcs12/pkcs12_utf8_to_utf16.obj src/misc/pkcs5/pkcs_5_1.obj \ +src/misc/pkcs5/pkcs_5_2.obj src/misc/pkcs5/pkcs_5_test.obj src/misc/ssh/ssh_decode_sequence_multi.obj \ +src/misc/ssh/ssh_encode_sequence_multi.obj src/misc/zeromem.obj src/modes/cbc/cbc_decrypt.obj \ +src/modes/cbc/cbc_done.obj src/modes/cbc/cbc_encrypt.obj src/modes/cbc/cbc_getiv.obj \ +src/modes/cbc/cbc_setiv.obj src/modes/cbc/cbc_start.obj src/modes/cfb/cfb_decrypt.obj \ +src/modes/cfb/cfb_done.obj src/modes/cfb/cfb_encrypt.obj src/modes/cfb/cfb_getiv.obj \ +src/modes/cfb/cfb_setiv.obj src/modes/cfb/cfb_start.obj src/modes/ctr/ctr_decrypt.obj \ +src/modes/ctr/ctr_done.obj src/modes/ctr/ctr_encrypt.obj src/modes/ctr/ctr_getiv.obj \ +src/modes/ctr/ctr_setiv.obj src/modes/ctr/ctr_start.obj src/modes/ctr/ctr_test.obj \ +src/modes/ecb/ecb_decrypt.obj src/modes/ecb/ecb_done.obj src/modes/ecb/ecb_encrypt.obj \ +src/modes/ecb/ecb_start.obj src/modes/f8/f8_decrypt.obj src/modes/f8/f8_done.obj src/modes/f8/f8_encrypt.obj \ +src/modes/f8/f8_getiv.obj src/modes/f8/f8_setiv.obj src/modes/f8/f8_start.obj src/modes/f8/f8_test_mode.obj \ +src/modes/lrw/lrw_decrypt.obj src/modes/lrw/lrw_done.obj src/modes/lrw/lrw_encrypt.obj \ +src/modes/lrw/lrw_getiv.obj src/modes/lrw/lrw_process.obj src/modes/lrw/lrw_setiv.obj \ +src/modes/lrw/lrw_start.obj src/modes/lrw/lrw_test.obj src/modes/ofb/ofb_decrypt.obj src/modes/ofb/ofb_done.obj \ +src/modes/ofb/ofb_encrypt.obj src/modes/ofb/ofb_getiv.obj src/modes/ofb/ofb_setiv.obj \ +src/modes/ofb/ofb_start.obj src/modes/xts/xts_decrypt.obj src/modes/xts/xts_done.obj \ +src/modes/xts/xts_encrypt.obj src/modes/xts/xts_init.obj src/modes/xts/xts_mult_x.obj \ +src/modes/xts/xts_test.obj src/pk/asn1/der/bit/der_decode_bit_string.obj \ +src/pk/asn1/der/bit/der_decode_raw_bit_string.obj src/pk/asn1/der/bit/der_encode_bit_string.obj \ +src/pk/asn1/der/bit/der_encode_raw_bit_string.obj src/pk/asn1/der/bit/der_length_bit_string.obj \ +src/pk/asn1/der/boolean/der_decode_boolean.obj src/pk/asn1/der/boolean/der_encode_boolean.obj \ +src/pk/asn1/der/boolean/der_length_boolean.obj src/pk/asn1/der/choice/der_decode_choice.obj \ +src/pk/asn1/der/custom_type/der_decode_custom_type.obj \ +src/pk/asn1/der/custom_type/der_encode_custom_type.obj \ +src/pk/asn1/der/custom_type/der_length_custom_type.obj src/pk/asn1/der/general/der_asn1_maps.obj \ +src/pk/asn1/der/general/der_decode_asn1_identifier.obj src/pk/asn1/der/general/der_decode_asn1_length.obj \ +src/pk/asn1/der/general/der_encode_asn1_identifier.obj src/pk/asn1/der/general/der_encode_asn1_length.obj \ +src/pk/asn1/der/general/der_length_asn1_identifier.obj src/pk/asn1/der/general/der_length_asn1_length.obj \ +src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.obj \ +src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.obj \ +src/pk/asn1/der/generalizedtime/der_length_generalizedtime.obj \ +src/pk/asn1/der/ia5/der_decode_ia5_string.obj src/pk/asn1/der/ia5/der_encode_ia5_string.obj \ +src/pk/asn1/der/ia5/der_length_ia5_string.obj src/pk/asn1/der/integer/der_decode_integer.obj \ +src/pk/asn1/der/integer/der_encode_integer.obj src/pk/asn1/der/integer/der_length_integer.obj \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.obj \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.obj \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.obj \ +src/pk/asn1/der/octet/der_decode_octet_string.obj src/pk/asn1/der/octet/der_encode_octet_string.obj \ +src/pk/asn1/der/octet/der_length_octet_string.obj \ +src/pk/asn1/der/printable_string/der_decode_printable_string.obj \ +src/pk/asn1/der/printable_string/der_encode_printable_string.obj \ +src/pk/asn1/der/printable_string/der_length_printable_string.obj \ +src/pk/asn1/der/sequence/der_decode_sequence_ex.obj \ +src/pk/asn1/der/sequence/der_decode_sequence_flexi.obj \ +src/pk/asn1/der/sequence/der_decode_sequence_multi.obj \ +src/pk/asn1/der/sequence/der_encode_sequence_ex.obj \ +src/pk/asn1/der/sequence/der_encode_sequence_multi.obj src/pk/asn1/der/sequence/der_length_sequence.obj \ +src/pk/asn1/der/sequence/der_sequence_free.obj src/pk/asn1/der/sequence/der_sequence_shrink.obj \ +src/pk/asn1/der/set/der_encode_set.obj src/pk/asn1/der/set/der_encode_setof.obj \ +src/pk/asn1/der/short_integer/der_decode_short_integer.obj \ +src/pk/asn1/der/short_integer/der_encode_short_integer.obj \ +src/pk/asn1/der/short_integer/der_length_short_integer.obj \ +src/pk/asn1/der/teletex_string/der_decode_teletex_string.obj \ +src/pk/asn1/der/teletex_string/der_length_teletex_string.obj \ +src/pk/asn1/der/utctime/der_decode_utctime.obj src/pk/asn1/der/utctime/der_encode_utctime.obj \ +src/pk/asn1/der/utctime/der_length_utctime.obj src/pk/asn1/der/utf8/der_decode_utf8_string.obj \ +src/pk/asn1/der/utf8/der_encode_utf8_string.obj src/pk/asn1/der/utf8/der_length_utf8_string.obj \ +src/pk/asn1/oid/pk_get_oid.obj src/pk/asn1/oid/pk_oid_cmp.obj src/pk/asn1/oid/pk_oid_str.obj \ +src/pk/asn1/pkcs8/pkcs8_decode_flexi.obj src/pk/asn1/x509/x509_decode_public_key_from_certificate.obj \ +src/pk/asn1/x509/x509_decode_subject_public_key_info.obj \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.obj src/pk/dh/dh.obj src/pk/dh/dh_check_pubkey.obj \ +src/pk/dh/dh_export.obj src/pk/dh/dh_export_key.obj src/pk/dh/dh_free.obj src/pk/dh/dh_generate_key.obj \ +src/pk/dh/dh_import.obj src/pk/dh/dh_set.obj src/pk/dh/dh_set_pg_dhparam.obj src/pk/dh/dh_shared_secret.obj \ +src/pk/dsa/dsa_decrypt_key.obj src/pk/dsa/dsa_encrypt_key.obj src/pk/dsa/dsa_export.obj src/pk/dsa/dsa_free.obj \ +src/pk/dsa/dsa_generate_key.obj src/pk/dsa/dsa_generate_pqg.obj src/pk/dsa/dsa_import.obj \ +src/pk/dsa/dsa_make_key.obj src/pk/dsa/dsa_set.obj src/pk/dsa/dsa_set_pqg_dsaparam.obj \ +src/pk/dsa/dsa_shared_secret.obj src/pk/dsa/dsa_sign_hash.obj src/pk/dsa/dsa_verify_hash.obj \ +src/pk/dsa/dsa_verify_key.obj src/pk/ec25519/ec25519_crypto_ctx.obj src/pk/ec25519/ec25519_export.obj \ +src/pk/ec25519/ec25519_import_pkcs8.obj src/pk/ec25519/tweetnacl.obj src/pk/ecc/ecc.obj \ +src/pk/ecc/ecc_ansi_x963_export.obj src/pk/ecc/ecc_ansi_x963_import.obj src/pk/ecc/ecc_decrypt_key.obj \ +src/pk/ecc/ecc_encrypt_key.obj src/pk/ecc/ecc_export.obj src/pk/ecc/ecc_export_openssl.obj \ +src/pk/ecc/ecc_find_curve.obj src/pk/ecc/ecc_free.obj src/pk/ecc/ecc_get_key.obj src/pk/ecc/ecc_get_oid_str.obj \ +src/pk/ecc/ecc_get_size.obj src/pk/ecc/ecc_import.obj src/pk/ecc/ecc_import_openssl.obj \ +src/pk/ecc/ecc_import_pkcs8.obj src/pk/ecc/ecc_import_x509.obj src/pk/ecc/ecc_make_key.obj \ +src/pk/ecc/ecc_recover_key.obj src/pk/ecc/ecc_set_curve.obj src/pk/ecc/ecc_set_curve_internal.obj \ +src/pk/ecc/ecc_set_key.obj src/pk/ecc/ecc_shared_secret.obj src/pk/ecc/ecc_sign_hash.obj \ +src/pk/ecc/ecc_sizes.obj src/pk/ecc/ecc_ssh_ecdsa_encode_name.obj src/pk/ecc/ecc_verify_hash.obj \ +src/pk/ecc/ltc_ecc_export_point.obj src/pk/ecc/ltc_ecc_import_point.obj src/pk/ecc/ltc_ecc_is_point.obj \ +src/pk/ecc/ltc_ecc_is_point_at_infinity.obj src/pk/ecc/ltc_ecc_map.obj src/pk/ecc/ltc_ecc_mul2add.obj \ +src/pk/ecc/ltc_ecc_mulmod.obj src/pk/ecc/ltc_ecc_mulmod_timing.obj src/pk/ecc/ltc_ecc_points.obj \ +src/pk/ecc/ltc_ecc_projective_add_point.obj src/pk/ecc/ltc_ecc_projective_dbl_point.obj \ +src/pk/ecc/ltc_ecc_verify_key.obj src/pk/ed25519/ed25519_export.obj src/pk/ed25519/ed25519_import.obj \ +src/pk/ed25519/ed25519_import_pkcs8.obj src/pk/ed25519/ed25519_import_raw.obj \ +src/pk/ed25519/ed25519_import_x509.obj src/pk/ed25519/ed25519_make_key.obj src/pk/ed25519/ed25519_sign.obj \ +src/pk/ed25519/ed25519_verify.obj src/pk/pkcs1/pkcs_1_i2osp.obj src/pk/pkcs1/pkcs_1_mgf1.obj \ +src/pk/pkcs1/pkcs_1_oaep_decode.obj src/pk/pkcs1/pkcs_1_oaep_encode.obj src/pk/pkcs1/pkcs_1_os2ip.obj \ +src/pk/pkcs1/pkcs_1_pss_decode.obj src/pk/pkcs1/pkcs_1_pss_encode.obj src/pk/pkcs1/pkcs_1_v1_5_decode.obj \ +src/pk/pkcs1/pkcs_1_v1_5_encode.obj src/pk/rsa/rsa_decrypt_key.obj src/pk/rsa/rsa_encrypt_key.obj \ +src/pk/rsa/rsa_export.obj src/pk/rsa/rsa_exptmod.obj src/pk/rsa/rsa_get_size.obj src/pk/rsa/rsa_import.obj \ +src/pk/rsa/rsa_import_pkcs8.obj src/pk/rsa/rsa_import_x509.obj src/pk/rsa/rsa_key.obj \ +src/pk/rsa/rsa_make_key.obj src/pk/rsa/rsa_set.obj src/pk/rsa/rsa_sign_hash.obj \ +src/pk/rsa/rsa_sign_saltlen_get.obj src/pk/rsa/rsa_verify_hash.obj src/pk/x25519/x25519_export.obj \ +src/pk/x25519/x25519_import.obj src/pk/x25519/x25519_import_pkcs8.obj src/pk/x25519/x25519_import_raw.obj \ +src/pk/x25519/x25519_import_x509.obj src/pk/x25519/x25519_make_key.obj \ +src/pk/x25519/x25519_shared_secret.obj src/prngs/chacha20.obj src/prngs/fortuna.obj src/prngs/rc4.obj \ +src/prngs/rng_get_bytes.obj src/prngs/rng_make_prng.obj src/prngs/sober128.obj src/prngs/sprng.obj \ +src/prngs/yarrow.obj src/stream/chacha/chacha_crypt.obj src/stream/chacha/chacha_done.obj \ +src/stream/chacha/chacha_ivctr32.obj src/stream/chacha/chacha_ivctr64.obj \ +src/stream/chacha/chacha_keystream.obj src/stream/chacha/chacha_memory.obj \ +src/stream/chacha/chacha_setup.obj src/stream/chacha/chacha_test.obj src/stream/rabbit/rabbit.obj \ +src/stream/rabbit/rabbit_memory.obj src/stream/rc4/rc4_stream.obj src/stream/rc4/rc4_stream_memory.obj \ +src/stream/rc4/rc4_test.obj src/stream/salsa20/salsa20_crypt.obj src/stream/salsa20/salsa20_done.obj \ +src/stream/salsa20/salsa20_ivctr64.obj src/stream/salsa20/salsa20_keystream.obj \ +src/stream/salsa20/salsa20_memory.obj src/stream/salsa20/salsa20_setup.obj \ +src/stream/salsa20/salsa20_test.obj src/stream/salsa20/xsalsa20_memory.obj \ +src/stream/salsa20/xsalsa20_setup.obj src/stream/salsa20/xsalsa20_test.obj \ +src/stream/sober128/sober128_stream.obj src/stream/sober128/sober128_stream_memory.obj \ +src/stream/sober128/sober128_test.obj src/stream/sosemanuk/sosemanuk.obj \ +src/stream/sosemanuk/sosemanuk_memory.obj src/stream/sosemanuk/sosemanuk_test.obj + +#List of test objects to compile +TOBJECTS=tests/base16_test.obj tests/base32_test.obj tests/base64_test.obj tests/bcrypt_test.obj \ +tests/cipher_hash_test.obj tests/common.obj tests/der_test.obj tests/dh_test.obj tests/dsa_test.obj \ +tests/ecc_test.obj tests/ed25519_test.obj tests/file_test.obj tests/mac_test.obj tests/misc_test.obj \ +tests/modes_test.obj tests/mpi_test.obj tests/multi_test.obj tests/no_null_termination_check_test.obj \ +tests/no_prng.obj tests/padding_test.obj tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj \ +tests/pkcs_1_oaep_test.obj tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/prng_test.obj \ +tests/rotate_test.obj tests/rsa_test.obj tests/ssh_test.obj tests/store_test.obj tests/test.obj tests/x25519_test.obj + +#The following headers will be installed by "make install" +HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ +src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ +src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ +src/headers/tomcrypt_prng.h + +HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h + +#The default rule for make builds the tomcrypt.lib library (static) +default: $(LIBMAIN_S) + +#SPECIAL: AES comes in two flavours - enc+dec and enc-only +src/ciphers/aes/aes_enc.obj: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c + $(CC) $(LTC_CFLAGS) /DENCRYPT_ONLY /c src/ciphers/aes/aes.c /Fosrc/ciphers/aes/aes_enc.obj + +#SPECIAL: these are the rules to make certain object files +src/ciphers/aes/aes.obj: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c +src/ciphers/twofish/twofish.obj: src/ciphers/twofish/twofish.c src/ciphers/twofish/twofish_tab.c +src/hashes/sha2/sha256.obj: src/hashes/sha2/sha256.c src/hashes/sha2/sha224.c +src/hashes/sha2/sha384.obj: src/hashes/sha2/sha384.c src/hashes/sha2/sha512.c +src/hashes/sha2/sha512.obj: src/hashes/sha2/sha512.c src/hashes/sha2/sha384.c +src/hashes/sha2/sha512_224.obj: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_224.c +src/hashes/sha2/sha512_256.obj: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_256.c +src/hashes/whirl/whirl.obj: src/hashes/whirl/whirl.c src/hashes/whirl/whirltab.c + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) +$(TOBJECTS): $(HEADERS) tests/tomcrypt_test.h + +.c.obj: + $(CC) $(LTC_CFLAGS) /c $< /Fo$@ + +#Create tomcrypt.lib +$(LIBMAIN_S): $(OBJECTS) + lib /out:$(LIBMAIN_S) $(OBJECTS) + +#Demo tools/utilities +hashsum.exe: demos/hashsum.c tests/common.c $(LIBMAIN_S) + cl $(LTC_CFLAGS) demos/hashsum.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ +ltcrypt.exe: demos/ltcrypt.c $(LIBMAIN_S) + cl $(LTC_CFLAGS) demos/ltcrypt.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ +small.exe: demos/small.c $(LIBMAIN_S) + cl $(LTC_CFLAGS) demos/small.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ +tv_gen.exe: demos/tv_gen.c $(LIBMAIN_S) + cl $(LTC_CFLAGS) demos/tv_gen.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ +sizes.exe: demos/sizes.c $(LIBMAIN_S) + cl $(LTC_CFLAGS) demos/sizes.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ +constants.exe: demos/constants.c $(LIBMAIN_S) + cl $(LTC_CFLAGS) demos/constants.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ +timing.exe: demos/timing.c $(LIBMAIN_S) + cl $(LTC_CFLAGS) demos/timing.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ + +#Tests +test.exe: $(LIBMAIN_S) $(TOBJECTS) + cl $(LTC_CFLAGS) $(TOBJECTS) $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@ + @echo NOTICE: start the tests by launching test.exe + +all: $(LIBMAIN_S) hashsum.exe ltcrypt.exe small.exe tv_gen.exe sizes.exe constants.exe timing.exe test.exe + +test: test.exe + +clean: + @-cmd /c del /Q *_tv.txt 2>nul + @-cmd /c del /Q /S *.OBJ *.LIB *.EXE *.DLL 2>nul + +#Install the library + headers +install: $(LIBMAIN_S) + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + cmd /c if not exist "$(PREFIX)\lib" mkdir "$(PREFIX)\lib" + cmd /c if not exist "$(PREFIX)\include" mkdir "$(PREFIX)\include" + copy /Y $(LIBMAIN_S) "$(PREFIX)\lib" + copy /Y src\headers\tomcrypt*.h "$(PREFIX)\include" + +#Install useful tools +install_bins: hashsum + cmd /c if not exist "$(PREFIX)\bin" mkdir "$(PREFIX)\bin" + copy /Y hashsum.exe "$(PREFIX)\bin" + +#Install documentation +install_docs: doc/crypt.pdf + cmd /c if not exist "$(PREFIX)\doc" mkdir "$(PREFIX)\doc" + copy /Y doc\crypt.pdf "$(PREFIX)\doc" + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/makefile.shared b/deps/libtomcrypt/makefile.shared new file mode 100644 index 0000000..0194a39 --- /dev/null +++ b/deps/libtomcrypt/makefile.shared @@ -0,0 +1,94 @@ +# MAKEFILE for linux GCC +# +# This makefile produces a shared object and requires libtool to be installed. +# +# Thanks to Zed Shaw for helping debug this on BSD/OSX. +# Tom St Denis +# +# (GNU make only) + +### USAGE: +# +# CFLAGS="-DUSE_LTM -DLTM_DESC -I/path/to/libtommath" make -f makefile.shared all EXTRALIBS=/path/to/libtommath/libtommath.a +# ./test +# make -f makefile.shared PREFIX=/opt/libtom install +# + +PLATFORM := $(shell uname | sed -e 's/_.*//') +### Observed uname outputs: +# MINGW32_NT-6.2 (on MSYS/MINGW old) +# MINGW64_NT-10.0-14393 (on MSYS new) +# MSYS_NT-10.0-19042 (on MSYS2) +# CYGWIN_NT-10.0 (on Cygwin 64bit) +# CYGWIN_NT-6.2-WOW64 (on Cygwin 32bit) +# Linux (on all Linux distros) +# Darwin (on macOS, OS X) + +ifeq ($(LIBTOOL),rlibtool) + TGTLIBTOOL:=slibtool-shared +else + ifndef LIBTOOL + ifeq ($(PLATFORM), Darwin) + TGTLIBTOOL:=glibtool + else + TGTLIBTOOL:=libtool + endif + else + TGTLIBTOOL=$(LIBTOOL) + endif +endif + +ifneq ($(findstring $(PLATFORM),CYGWIN MINGW32 MINGW64 MSYS),) + NO_UNDEFINED:=-no-undefined +endif + +LTCOMPILE = $(TGTLIBTOOL) --mode=compile --tag=CC $(CC) +INSTALL_CMD = $(TGTLIBTOOL) --mode=install install +UNINSTALL_CMD = $(TGTLIBTOOL) --mode=uninstall rm + +#Output filenames for various targets. +ifndef LIBNAME + LIBNAME=libtomcrypt.la +endif + + +include makefile_include.mk + + +#ciphers come in two flavours... enc+dec and enc +src/ciphers/aes/aes_enc.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c + $(LTCOMPILE) $(LTC_CFLAGS) $(CPPFLAGS) $(LTC_LDFLAGS) -DENCRYPT_ONLY -c src/ciphers/aes/aes.c -o src/ciphers/aes/aes_enc.o + +.c.o: + $(LTCOMPILE) $(LTC_CFLAGS) $(CPPFLAGS) $(LTC_LDFLAGS) -o $@ -c $< + +LOBJECTS = $(OBJECTS:.o=.lo) + +$(LIBNAME): $(OBJECTS) + $(TGTLIBTOOL) --mode=link --tag=CC $(CC) $(LTC_LDFLAGS) $(LOBJECTS) $(EXTRALIBS) -o $@ -rpath $(LIBPATH) -version-info $(VERSION_LT) $(NO_UNDEFINED) + +test: $(call print-help,test,Builds the library and the 'test' application to run all self-tests) $(LIBNAME) $(TOBJECTS) + $(TGTLIBTOOL) --mode=link --tag=CC $(CC) $(LTC_LDFLAGS) -o $(TEST) $(TOBJECTS) $(LIBNAME) $(EXTRALIBS) + +# build the demos from a template +define DEMO_template +$(1): $(call print-help,$(1),Builds the library and the '$(1)' demo) demos/$(1).o $$(LIBNAME) + $$(TGTLIBTOOL) --mode=link --tag=CC $$(CC) $$(LTC_LDFLAGS) $$^ $$(EXTRALIBS) -o $(1) +endef + +$(foreach demo, $(strip $(DEMOS)), $(eval $(call DEMO_template,$(demo)))) + +install: $(call print-help,install,Installs the library + headers + pkg-config file) .common_install + sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION_PC),' -e 's,@CMAKE_INSTALL_LIBDIR@,lib,' \ + -e 's,@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@,include/tomcrypt,' libtomcrypt.pc.in > libtomcrypt.pc + install -p -d $(DESTDIR)$(LIBPATH)/pkgconfig + install -p -m 644 libtomcrypt.pc $(DESTDIR)$(LIBPATH)/pkgconfig/ + +install_bins: $(call print-help,install_bins,Installs the useful demos ($(USEFUL_DEMOS))) .common_install_bins + +uninstall: $(call print-help,uninstall,Uninstalls the library + headers + pkg-config file) .common_uninstall + rm $(DESTDIR)$(LIBPATH)/pkgconfig/libtomcrypt.pc + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/makefile.unix b/deps/libtomcrypt/makefile.unix new file mode 100644 index 0000000..c25b286 --- /dev/null +++ b/deps/libtomcrypt/makefile.unix @@ -0,0 +1,334 @@ +# MAKEFILE that is intended to be compatible with any kind of make (GNU make, BSD make, ...) +# works on: Linux, *BSD, Cygwin, AIX, HP-UX and hopefully other UNIX systems +# +# Please do not use here neither any special make syntax nor any unusual tools/utilities! +# +# BEWARE: variables OBJECTS, TOBJECTS, HEADERS, VERSION are updated via ./updatemakes.sh + +### USAGE: +# +# make -f makefile.unix all +# ./test +# make -f makefile.unix install +# +#Or: +# +# make -f makefile.unix CFLAGS="-O3 -DUSE_LTM -DLTM_DESC -I/path/to/libtommath" EXTRALIBS=/path/to/libtommath/libtommath.a all +# ./test +# make -f makefile.unix PREFIX=/opt/libtom install +# +#Or if you are using Intel C compiler you might need something like: +# +# make -f makefile.unix CC=icc AR=xiar CFLAGS="-fast -DUSE_LTM -DLTM_DESC -I/path/to/libtommath" EXTRALIBS=/path/to/libtommath/libtommath.a all +# + +#The following can be overridden from command line e.g. "make -f makefile.unix CC=gcc ARFLAGS=rcs" +DESTDIR = +PREFIX = /usr/local +LIBPATH = $(PREFIX)/lib +INCPATH = $(PREFIX)/include +DATAPATH = $(PREFIX)/share/doc/libtomcrypt/pdf +BINPATH = $(PREFIX)/bin +CC = cc +AR = ar +ARFLAGS = r +RANLIB = ranlib +CFLAGS = -O2 -DUSE_LTM -DLTM_DESC -I../libtommath +EXTRALIBS = ../libtommath/libtommath.a + +#Compilation flags +LTC_CFLAGS = -Isrc/headers -Itests -DLTC_SOURCE $(CFLAGS) +LTC_LDFLAGS = $(LDFLAGS) $(EXTRALIBS) +VERSION=1.18.2-develop + +#Libraries to be created (this makefile builds only static libraries) +LIBMAIN_S =libtomcrypt.a + +#List of objects to compile (all goes to libtomcrypt.a) +OBJECTS=src/ciphers/aes/aes.o src/ciphers/aes/aes_enc.o src/ciphers/anubis.o src/ciphers/blowfish.o \ +src/ciphers/camellia.o src/ciphers/cast5.o src/ciphers/des.o src/ciphers/idea.o src/ciphers/kasumi.o \ +src/ciphers/khazad.o src/ciphers/kseed.o src/ciphers/multi2.o src/ciphers/noekeon.o src/ciphers/rc2.o \ +src/ciphers/rc5.o src/ciphers/rc6.o src/ciphers/safer/safer.o src/ciphers/safer/saferp.o \ +src/ciphers/serpent.o src/ciphers/skipjack.o src/ciphers/tea.o src/ciphers/twofish/twofish.o \ +src/ciphers/xtea.o src/encauth/ccm/ccm_add_aad.o src/encauth/ccm/ccm_add_nonce.o \ +src/encauth/ccm/ccm_done.o src/encauth/ccm/ccm_init.o src/encauth/ccm/ccm_memory.o \ +src/encauth/ccm/ccm_process.o src/encauth/ccm/ccm_reset.o src/encauth/ccm/ccm_test.o \ +src/encauth/chachapoly/chacha20poly1305_add_aad.o src/encauth/chachapoly/chacha20poly1305_decrypt.o \ +src/encauth/chachapoly/chacha20poly1305_done.o src/encauth/chachapoly/chacha20poly1305_encrypt.o \ +src/encauth/chachapoly/chacha20poly1305_init.o src/encauth/chachapoly/chacha20poly1305_memory.o \ +src/encauth/chachapoly/chacha20poly1305_setiv.o \ +src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.o \ +src/encauth/chachapoly/chacha20poly1305_test.o src/encauth/eax/eax_addheader.o \ +src/encauth/eax/eax_decrypt.o src/encauth/eax/eax_decrypt_verify_memory.o src/encauth/eax/eax_done.o \ +src/encauth/eax/eax_encrypt.o src/encauth/eax/eax_encrypt_authenticate_memory.o \ +src/encauth/eax/eax_init.o src/encauth/eax/eax_test.o src/encauth/gcm/gcm_add_aad.o \ +src/encauth/gcm/gcm_add_iv.o src/encauth/gcm/gcm_done.o src/encauth/gcm/gcm_gf_mult.o \ +src/encauth/gcm/gcm_init.o src/encauth/gcm/gcm_memory.o src/encauth/gcm/gcm_mult_h.o \ +src/encauth/gcm/gcm_process.o src/encauth/gcm/gcm_reset.o src/encauth/gcm/gcm_test.o \ +src/encauth/ocb/ocb_decrypt.o src/encauth/ocb/ocb_decrypt_verify_memory.o \ +src/encauth/ocb/ocb_done_decrypt.o src/encauth/ocb/ocb_done_encrypt.o src/encauth/ocb/ocb_encrypt.o \ +src/encauth/ocb/ocb_encrypt_authenticate_memory.o src/encauth/ocb/ocb_init.o src/encauth/ocb/ocb_ntz.o \ +src/encauth/ocb/ocb_shift_xor.o src/encauth/ocb/ocb_test.o src/encauth/ocb/s_ocb_done.o \ +src/encauth/ocb3/ocb3_add_aad.o src/encauth/ocb3/ocb3_decrypt.o src/encauth/ocb3/ocb3_decrypt_last.o \ +src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \ +src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \ +src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \ +src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/hashes/blake2b.o \ +src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \ +src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ +src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \ +src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \ +src/hashes/sha2/sha224.o src/hashes/sha2/sha256.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \ +src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \ +src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ +src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \ +src/mac/blake2/blake2bmac_memory_multi.o src/mac/blake2/blake2bmac_test.o src/mac/blake2/blake2smac.o \ +src/mac/blake2/blake2smac_file.o src/mac/blake2/blake2smac_memory.o \ +src/mac/blake2/blake2smac_memory_multi.o src/mac/blake2/blake2smac_test.o src/mac/f9/f9_done.o \ +src/mac/f9/f9_file.o src/mac/f9/f9_init.o src/mac/f9/f9_memory.o src/mac/f9/f9_memory_multi.o \ +src/mac/f9/f9_process.o src/mac/f9/f9_test.o src/mac/hmac/hmac_done.o src/mac/hmac/hmac_file.o \ +src/mac/hmac/hmac_init.o src/mac/hmac/hmac_memory.o src/mac/hmac/hmac_memory_multi.o \ +src/mac/hmac/hmac_process.o src/mac/hmac/hmac_test.o src/mac/omac/omac_done.o src/mac/omac/omac_file.o \ +src/mac/omac/omac_init.o src/mac/omac/omac_memory.o src/mac/omac/omac_memory_multi.o \ +src/mac/omac/omac_process.o src/mac/omac/omac_test.o src/mac/pelican/pelican.o \ +src/mac/pelican/pelican_memory.o src/mac/pelican/pelican_test.o src/mac/pmac/pmac_done.o \ +src/mac/pmac/pmac_file.o src/mac/pmac/pmac_init.o src/mac/pmac/pmac_memory.o \ +src/mac/pmac/pmac_memory_multi.o src/mac/pmac/pmac_ntz.o src/mac/pmac/pmac_process.o \ +src/mac/pmac/pmac_shift_xor.o src/mac/pmac/pmac_test.o src/mac/poly1305/poly1305.o \ +src/mac/poly1305/poly1305_file.o src/mac/poly1305/poly1305_memory.o \ +src/mac/poly1305/poly1305_memory_multi.o src/mac/poly1305/poly1305_test.o src/mac/xcbc/xcbc_done.o \ +src/mac/xcbc/xcbc_file.o src/mac/xcbc/xcbc_init.o src/mac/xcbc/xcbc_memory.o \ +src/mac/xcbc/xcbc_memory_multi.o src/mac/xcbc/xcbc_process.o src/mac/xcbc/xcbc_test.o \ +src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math/multi.o \ +src/math/radix_to_bin.o src/math/rand_bn.o src/math/rand_prime.o src/math/tfm_desc.o src/misc/adler32.o \ +src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \ +src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \ +src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \ +src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \ +src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \ +src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \ +src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \ +src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \ +src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \ +src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \ +src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \ +src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \ +src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \ +src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \ +src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ +src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ +src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ +src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ +src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ +src/misc/padding/padding_pad.o src/misc/pbes/pbes.o src/misc/pbes/pbes1.o src/misc/pbes/pbes2.o \ +src/misc/pkcs12/pkcs12_kdf.o src/misc/pkcs12/pkcs12_utf8_to_utf16.o src/misc/pkcs5/pkcs_5_1.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/pkcs5/pkcs_5_test.o src/misc/ssh/ssh_decode_sequence_multi.o \ +src/misc/ssh/ssh_encode_sequence_multi.o src/misc/zeromem.o src/modes/cbc/cbc_decrypt.o \ +src/modes/cbc/cbc_done.o src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o \ +src/modes/cbc/cbc_setiv.o src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o \ +src/modes/cfb/cfb_done.o src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o \ +src/modes/cfb/cfb_setiv.o src/modes/cfb/cfb_start.o src/modes/ctr/ctr_decrypt.o \ +src/modes/ctr/ctr_done.o src/modes/ctr/ctr_encrypt.o src/modes/ctr/ctr_getiv.o \ +src/modes/ctr/ctr_setiv.o src/modes/ctr/ctr_start.o src/modes/ctr/ctr_test.o \ +src/modes/ecb/ecb_decrypt.o src/modes/ecb/ecb_done.o src/modes/ecb/ecb_encrypt.o \ +src/modes/ecb/ecb_start.o src/modes/f8/f8_decrypt.o src/modes/f8/f8_done.o src/modes/f8/f8_encrypt.o \ +src/modes/f8/f8_getiv.o src/modes/f8/f8_setiv.o src/modes/f8/f8_start.o src/modes/f8/f8_test_mode.o \ +src/modes/lrw/lrw_decrypt.o src/modes/lrw/lrw_done.o src/modes/lrw/lrw_encrypt.o \ +src/modes/lrw/lrw_getiv.o src/modes/lrw/lrw_process.o src/modes/lrw/lrw_setiv.o \ +src/modes/lrw/lrw_start.o src/modes/lrw/lrw_test.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \ +src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \ +src/modes/ofb/ofb_start.o src/modes/xts/xts_decrypt.o src/modes/xts/xts_done.o \ +src/modes/xts/xts_encrypt.o src/modes/xts/xts_init.o src/modes/xts/xts_mult_x.o \ +src/modes/xts/xts_test.o src/pk/asn1/der/bit/der_decode_bit_string.o \ +src/pk/asn1/der/bit/der_decode_raw_bit_string.o src/pk/asn1/der/bit/der_encode_bit_string.o \ +src/pk/asn1/der/bit/der_encode_raw_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \ +src/pk/asn1/der/boolean/der_decode_boolean.o src/pk/asn1/der/boolean/der_encode_boolean.o \ +src/pk/asn1/der/boolean/der_length_boolean.o src/pk/asn1/der/choice/der_decode_choice.o \ +src/pk/asn1/der/custom_type/der_decode_custom_type.o \ +src/pk/asn1/der/custom_type/der_encode_custom_type.o \ +src/pk/asn1/der/custom_type/der_length_custom_type.o src/pk/asn1/der/general/der_asn1_maps.o \ +src/pk/asn1/der/general/der_decode_asn1_identifier.o src/pk/asn1/der/general/der_decode_asn1_length.o \ +src/pk/asn1/der/general/der_encode_asn1_identifier.o src/pk/asn1/der/general/der_encode_asn1_length.o \ +src/pk/asn1/der/general/der_length_asn1_identifier.o src/pk/asn1/der/general/der_length_asn1_length.o \ +src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \ +src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.o \ +src/pk/asn1/der/generalizedtime/der_length_generalizedtime.o \ +src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \ +src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \ +src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.o \ +src/pk/asn1/der/octet/der_decode_octet_string.o src/pk/asn1/der/octet/der_encode_octet_string.o \ +src/pk/asn1/der/octet/der_length_octet_string.o \ +src/pk/asn1/der/printable_string/der_decode_printable_string.o \ +src/pk/asn1/der/printable_string/der_encode_printable_string.o \ +src/pk/asn1/der/printable_string/der_length_printable_string.o \ +src/pk/asn1/der/sequence/der_decode_sequence_ex.o \ +src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \ +src/pk/asn1/der/sequence/der_decode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_encode_sequence_ex.o \ +src/pk/asn1/der/sequence/der_encode_sequence_multi.o src/pk/asn1/der/sequence/der_length_sequence.o \ +src/pk/asn1/der/sequence/der_sequence_free.o src/pk/asn1/der/sequence/der_sequence_shrink.o \ +src/pk/asn1/der/set/der_encode_set.o src/pk/asn1/der/set/der_encode_setof.o \ +src/pk/asn1/der/short_integer/der_decode_short_integer.o \ +src/pk/asn1/der/short_integer/der_encode_short_integer.o \ +src/pk/asn1/der/short_integer/der_length_short_integer.o \ +src/pk/asn1/der/teletex_string/der_decode_teletex_string.o \ +src/pk/asn1/der/teletex_string/der_length_teletex_string.o \ +src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \ +src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \ +src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \ +src/pk/asn1/oid/pk_get_oid.o src/pk/asn1/oid/pk_oid_cmp.o src/pk/asn1/oid/pk_oid_str.o \ +src/pk/asn1/pkcs8/pkcs8_decode_flexi.o src/pk/asn1/x509/x509_decode_public_key_from_certificate.o \ +src/pk/asn1/x509/x509_decode_subject_public_key_info.o \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \ +src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \ +src/pk/dh/dh_import.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o \ +src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \ +src/pk/dsa/dsa_generate_key.o src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o \ +src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_set.o src/pk/dsa/dsa_set_pqg_dsaparam.o \ +src/pk/dsa/dsa_shared_secret.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \ +src/pk/dsa/dsa_verify_key.o src/pk/ec25519/ec25519_crypto_ctx.o src/pk/ec25519/ec25519_export.o \ +src/pk/ec25519/ec25519_import_pkcs8.o src/pk/ec25519/tweetnacl.o src/pk/ecc/ecc.o \ +src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \ +src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_export_openssl.o \ +src/pk/ecc/ecc_find_curve.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_key.o src/pk/ecc/ecc_get_oid_str.o \ +src/pk/ecc/ecc_get_size.o src/pk/ecc/ecc_import.o src/pk/ecc/ecc_import_openssl.o \ +src/pk/ecc/ecc_import_pkcs8.o src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_key.o \ +src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o \ +src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ +src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ +src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ +src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ +src/pk/ecc/ltc_ecc_verify_key.o src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o \ +src/pk/ed25519/ed25519_import_pkcs8.o src/pk/ed25519/ed25519_import_raw.o \ +src/pk/ed25519/ed25519_import_x509.o src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o \ +src/pk/ed25519/ed25519_verify.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ +src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ +src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \ +src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ +src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_get_size.o src/pk/rsa/rsa_import.o \ +src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o src/pk/rsa/rsa_key.o \ +src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \ +src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \ +src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_raw.o \ +src/pk/x25519/x25519_import_x509.o src/pk/x25519/x25519_make_key.o \ +src/pk/x25519/x25519_shared_secret.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ +src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o \ +src/prngs/yarrow.o src/stream/chacha/chacha_crypt.o src/stream/chacha/chacha_done.o \ +src/stream/chacha/chacha_ivctr32.o src/stream/chacha/chacha_ivctr64.o \ +src/stream/chacha/chacha_keystream.o src/stream/chacha/chacha_memory.o \ +src/stream/chacha/chacha_setup.o src/stream/chacha/chacha_test.o src/stream/rabbit/rabbit.o \ +src/stream/rabbit/rabbit_memory.o src/stream/rc4/rc4_stream.o src/stream/rc4/rc4_stream_memory.o \ +src/stream/rc4/rc4_test.o src/stream/salsa20/salsa20_crypt.o src/stream/salsa20/salsa20_done.o \ +src/stream/salsa20/salsa20_ivctr64.o src/stream/salsa20/salsa20_keystream.o \ +src/stream/salsa20/salsa20_memory.o src/stream/salsa20/salsa20_setup.o \ +src/stream/salsa20/salsa20_test.o src/stream/salsa20/xsalsa20_memory.o \ +src/stream/salsa20/xsalsa20_setup.o src/stream/salsa20/xsalsa20_test.o \ +src/stream/sober128/sober128_stream.o src/stream/sober128/sober128_stream_memory.o \ +src/stream/sober128/sober128_test.o src/stream/sosemanuk/sosemanuk.o \ +src/stream/sosemanuk/sosemanuk_memory.o src/stream/sosemanuk/sosemanuk_test.o + +#List of test objects to compile (all goes to libtomcrypt_prof.a) +TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ +tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ +tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ +tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_null_termination_check_test.o \ +tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ +tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ +tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o + +#The following headers will be installed by "make install" +HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ +src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ +src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ +src/headers/tomcrypt_prng.h + +HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h + +#The default rule for make builds the libtomcrypt.a library (static) +default: $(LIBMAIN_S) + +#SPECIAL: AES comes in two flavours - enc+dec and enc-only +src/ciphers/aes/aes_enc.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c + $(CC) $(LTC_CFLAGS) -DENCRYPT_ONLY -c src/ciphers/aes/aes.c -o src/ciphers/aes/aes_enc.o + +#SPECIAL: these are the rules to make certain object files +src/ciphers/aes/aes.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c +src/ciphers/twofish/twofish.o: src/ciphers/twofish/twofish.c src/ciphers/twofish/twofish_tab.c +src/hashes/sha2/sha256.o: src/hashes/sha2/sha256.c src/hashes/sha2/sha224.c +src/hashes/sha2/sha384.o: src/hashes/sha2/sha384.c src/hashes/sha2/sha512.c +src/hashes/sha2/sha512.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha384.c +src/hashes/sha2/sha512_224.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_224.c +src/hashes/sha2/sha512_256.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_256.c +src/hashes/whirl/whirl.o: src/hashes/whirl/whirl.c src/hashes/whirl/whirltab.c + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) +$(TOBJECTS): $(HEADERS) tests/tomcrypt_test.h + +#This is necessary for compatibility with BSD make (namely on OpenBSD) +.SUFFIXES: .o .c +.c.o: + $(CC) $(LTC_CFLAGS) -c $< -o $@ + +#Create libtomcrypt.a +$(LIBMAIN_S): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + $(RANLIB) $@ + +#Demo tools/utilities +hashsum: demos/hashsum.o $(LIBMAIN_S) + $(CC) demos/hashsum.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +ltcrypt: demos/ltcrypt.o $(LIBMAIN_S) + $(CC) demos/ltcrypt.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +small: demos/small.o $(LIBMAIN_S) + $(CC) demos/small.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +tv_gen: demos/tv_gen.o $(LIBMAIN_S) + $(CC) demos/tv_gen.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +sizes: demos/sizes.o $(LIBMAIN_S) + $(CC) demos/sizes.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +constants: demos/constants.o $(LIBMAIN_S) + $(CC) demos/constants.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ +timing: demos/timing.o $(LIBMAIN_S) + $(CC) demos/timing.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ + +#Tests +test: $(TOBJECTS) $(LIBMAIN_S) + $(CC) $(TOBJECTS) $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@ + @echo "NOTICE: start the tests by: ./test" + +all: $(LIBMAIN_S) hashsum ltcrypt small tv_gen sizes constants timing test + +#NOTE: this makefile works also on cygwin, thus we need to delete *.exe +clean: + -@rm -f $(OBJECTS) $(TOBJECTS) + -@rm -f $(LIBMAIN_S) + -@rm -f demos/*.o *_tv.txt + -@rm -f test constants sizes tv_gen hashsum ltcrypt small timing + -@rm -f test.exe constants.exe sizes.exe tv_gen.exe hashsum.exe ltcrypt.exe small.exe timing.exe + +#Install the library + headers +install: $(LIBMAIN_S) + @mkdir -p $(DESTDIR)$(INCPATH) $(DESTDIR)$(LIBPATH)/pkgconfig + @cp $(LIBMAIN_S) $(DESTDIR)$(LIBPATH)/ + @cp $(HEADERS_PUB) $(DESTDIR)$(INCPATH)/ + @sed -e 's,^prefix=.*,prefix=$(PREFIX),' -e 's,^Version:.*,Version: $(VERSION),' libtomcrypt.pc.in > $(DESTDIR)$(LIBPATH)/pkgconfig/libtomcrypt.pc + +#Install useful tools +install_bins: hashsum + @mkdir -p $(DESTDIR)$(BINPATH) + @cp hashsum $(DESTDIR)$(BINPATH)/ + +#Install documentation +install_docs: doc/crypt.pdf + @mkdir -p $(DESTDIR)$(DATAPATH) + @cp doc/crypt.pdf $(DESTDIR)$(DATAPATH)/ + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/makefile_include.mk b/deps/libtomcrypt/makefile_include.mk new file mode 100644 index 0000000..9564fac --- /dev/null +++ b/deps/libtomcrypt/makefile_include.mk @@ -0,0 +1,535 @@ +# +# Include makefile used by makefile + makefile.shared +# (GNU make only) + +# The version - BEWARE: VERSION, VERSION_PC and VERSION_LT are updated via ./updatemakes.sh +VERSION=1.18.2-develop +VERSION_PC=1.18.2 +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +VERSION_LT=1:1 + +# Compiler and Linker Names +ifndef CROSS_COMPILE + CROSS_COMPILE:= +endif + +# We only need to go through this dance of determining the right compiler if we're using +# cross compilation, otherwise $(CC) is fine as-is. +ifneq (,$(CROSS_COMPILE)) +ifeq ($(origin CC),default) +CSTR := "\#ifdef __clang__\nCLANG\n\#endif\n" +ifeq ($(PLATFORM),FreeBSD) + # XXX: FreeBSD needs extra escaping for some reason + CSTR := $$$(CSTR) +endif +ifneq (,$(shell echo $(CSTR) | $(CC) -E - | grep CLANG)) + CC := $(CROSS_COMPILE)clang +else + CC := $(CROSS_COMPILE)gcc +endif # Clang +endif # cc is Make's default +endif # CROSS_COMPILE non-empty + +LD:=$(CROSS_COMPILE)ld +AR:=$(CROSS_COMPILE)ar + +# Archiver [makes .a files] +#AR=ar +ARFLAGS:=r + +ifndef MAKE +# BSDs refer to GNU Make as gmake +ifneq (,$(findstring $(PLATFORM),FreeBSD OpenBSD DragonFly NetBSD)) + MAKE=gmake +else + MAKE=make +endif +endif + +ifndef INSTALL_CMD +$(error your makefile must define INSTALL_CMD) +endif +ifndef UNINSTALL_CMD +$(error your makefile must define UNINSTALL_CMD) +endif + +ifndef EXTRALIBS +ifneq ($(shell echo $(CFLAGS) | grep USE_LTM),) +EXTRALIBS=$(shell PKG_CONFIG_PATH=$(LIBPATH)/pkgconfig pkg-config libtommath --libs) +else +ifneq ($(shell echo $(CFLAGS) | grep USE_TFM),) +EXTRALIBS=$(shell PKG_CONFIG_PATH=$(LIBPATH)/pkgconfig pkg-config tomsfastmath --libs) +endif +endif +endif + +need-help := $(filter help,$(MAKECMDGOALS)) +define print-help +$(if $(need-help),$(info $1 -- $2)) +endef + +# +# Compilation flags. Note the += does not write over the user's CFLAGS! +# +# Also note that we're extending the environments' CFLAGS. +# If you think that our CFLAGS are not nice you can easily override them +# by giving them as a parameter to make: +# make CFLAGS="-I./src/headers/ -DLTC_SOURCE ..." ... +# +LTC_CFLAGS += -I./src/headers/ -DLTC_SOURCE -Wall -Wsign-compare -Wshadow + +ifdef OLD_GCC +LTC_CFLAGS += -W +# older GCCs can't handle the "rotate with immediate" ROLc/RORc/etc macros +# define this to help +LTC_CFLAGS += -DLTC_NO_ROLC +else +LTC_CFLAGS += -Wextra +# additional warnings +LTC_CFLAGS += -Wsystem-headers -Wbad-function-cast -Wcast-align +LTC_CFLAGS += -Wstrict-prototypes -Wpointer-arith +LTC_CFLAGS += -Wdeclaration-after-statement +LTC_CFLAGS += -Wwrite-strings +endif + +ifdef LTC_DEBUG +$(info Debug build) +# compile for DEBUGGING (required for ccmalloc checking!!!) +LTC_CFLAGS += -g3 -DLTC_NO_ASM + +ifneq (,$(strip $(LTC_DEBUG))) +LTC_CFLAGS += -DLTC_TEST_DBG=$(LTC_DEBUG) +else +LTC_CFLAGS += -DLTC_TEST_DBG +endif +endif # LTC_DEBUG + +ifndef IGNORE_SPEED +# optimize for SPEED +LTC_CFLAGS += -O3 -funroll-loops + +# add -fomit-frame-pointer. hinders debugging! +LTC_CFLAGS += -fomit-frame-pointer +endif # IGNORE_SPEED + +ifdef LTC_SMALL +# optimize for SIZE +LTC_CFLAGS += -Os -DLTC_SMALL_CODE +endif # LTC_SMALL + + +ifneq ($(findstring clang,$(CC)),) +LTC_CFLAGS += -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header +LTC_CFLAGS += -Wno-missing-field-initializers -Wno-missing-braces -Wno-incomplete-setjmp-declaration +endif +ifneq ($(findstring mingw,$(CC)),) +LTC_CFLAGS += -Wno-shadow -Wno-attributes +endif +ifeq ($(PLATFORM), Darwin) +LTC_CFLAGS += -Wno-nullability-completeness +endif + + +GIT_VERSION := $(shell { [ -e .git ] && which git 2>/dev/null 1>&2 ; } && { printf git- ; git describe --tags --always --dirty ; } || echo $(VERSION)) +ifneq ($(GIT_VERSION),) +LTC_CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" +endif + +LTC_CFLAGS := $(LTC_CFLAGS) $(CFLAGS) + +ifneq ($(findstring -DLTC_PTHREAD,$(LTC_CFLAGS)),) +LTC_LDFLAGS += -pthread +endif + +LTC_LDFLAGS := $(LTC_LDFLAGS) $(LDFLAGS) + +ifeq ($(V)$(filter clean,$(MAKECMDGOALS)),0) +$(warning CFLAGS=$(LTC_CFLAGS)) +$(warning LDFLAGS=$(LTC_LDFLAGS)) +endif + +#List of demo objects +DSOURCES = $(wildcard demos/*.c) +DOBJECTS = $(DSOURCES:.c=.o) + +#List of tests headers +THEADERS = $(wildcard tests/*.h) + +TEST=test + +# Demos that are even somehow useful and could be installed as a system-tool +USEFUL_DEMOS = hashsum + +# Demos that are usable but only rarely make sense to be installed +USEABLE_DEMOS = ltcrypt sizes constants + +# Demos that are used for testing or measuring +TEST_DEMOS = small tv_gen + +# Demos that are in one config broken +# aesgcm - can't be built with LTC_EASY +# openssl-enc - can't be built with LTC_EASY +# timing - not really broken, but older gcc builds spit warnings +BROKEN_DEMOS = aesgcm openssl-enc timing + +# Combine demos in groups +UNBROKEN_DEMOS = $(TEST_DEMOS) $(USEABLE_DEMOS) $(USEFUL_DEMOS) +DEMOS = $(UNBROKEN_DEMOS) $(BROKEN_DEMOS) + +#LIBPATH The directory for libtomcrypt to be installed to. +#INCPATH The directory to install the header files for libtomcrypt. +#DATAPATH The directory to install the pdf docs. +#BINPATH The directory to install the binaries provided. +DESTDIR ?= +PREFIX ?= /usr/local +LIBPATH ?= $(PREFIX)/lib +INCPATH ?= $(PREFIX)/include +DATAPATH ?= $(PREFIX)/share/doc/libtomcrypt/pdf +BINPATH ?= $(PREFIX)/bin + +#Who do we install as? +ifdef INSTALL_USER +USER=$(INSTALL_USER) +else +USER=root +endif + +ifdef INSTALL_GROUP +GROUP=$(INSTALL_GROUP) +else +GROUP=wheel +endif + + +#The first rule is also the default rule and builds the libtomcrypt library. +library: $(call print-help,library,Builds the library) $(LIBNAME) + + +# List of objects to compile (all goes to libtomcrypt.a) +OBJECTS=src/ciphers/aes/aes.o src/ciphers/aes/aes_enc.o src/ciphers/anubis.o src/ciphers/blowfish.o \ +src/ciphers/camellia.o src/ciphers/cast5.o src/ciphers/des.o src/ciphers/idea.o src/ciphers/kasumi.o \ +src/ciphers/khazad.o src/ciphers/kseed.o src/ciphers/multi2.o src/ciphers/noekeon.o src/ciphers/rc2.o \ +src/ciphers/rc5.o src/ciphers/rc6.o src/ciphers/safer/safer.o src/ciphers/safer/saferp.o \ +src/ciphers/serpent.o src/ciphers/skipjack.o src/ciphers/tea.o src/ciphers/twofish/twofish.o \ +src/ciphers/xtea.o src/encauth/ccm/ccm_add_aad.o src/encauth/ccm/ccm_add_nonce.o \ +src/encauth/ccm/ccm_done.o src/encauth/ccm/ccm_init.o src/encauth/ccm/ccm_memory.o \ +src/encauth/ccm/ccm_process.o src/encauth/ccm/ccm_reset.o src/encauth/ccm/ccm_test.o \ +src/encauth/chachapoly/chacha20poly1305_add_aad.o src/encauth/chachapoly/chacha20poly1305_decrypt.o \ +src/encauth/chachapoly/chacha20poly1305_done.o src/encauth/chachapoly/chacha20poly1305_encrypt.o \ +src/encauth/chachapoly/chacha20poly1305_init.o src/encauth/chachapoly/chacha20poly1305_memory.o \ +src/encauth/chachapoly/chacha20poly1305_setiv.o \ +src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.o \ +src/encauth/chachapoly/chacha20poly1305_test.o src/encauth/eax/eax_addheader.o \ +src/encauth/eax/eax_decrypt.o src/encauth/eax/eax_decrypt_verify_memory.o src/encauth/eax/eax_done.o \ +src/encauth/eax/eax_encrypt.o src/encauth/eax/eax_encrypt_authenticate_memory.o \ +src/encauth/eax/eax_init.o src/encauth/eax/eax_test.o src/encauth/gcm/gcm_add_aad.o \ +src/encauth/gcm/gcm_add_iv.o src/encauth/gcm/gcm_done.o src/encauth/gcm/gcm_gf_mult.o \ +src/encauth/gcm/gcm_init.o src/encauth/gcm/gcm_memory.o src/encauth/gcm/gcm_mult_h.o \ +src/encauth/gcm/gcm_process.o src/encauth/gcm/gcm_reset.o src/encauth/gcm/gcm_test.o \ +src/encauth/ocb/ocb_decrypt.o src/encauth/ocb/ocb_decrypt_verify_memory.o \ +src/encauth/ocb/ocb_done_decrypt.o src/encauth/ocb/ocb_done_encrypt.o src/encauth/ocb/ocb_encrypt.o \ +src/encauth/ocb/ocb_encrypt_authenticate_memory.o src/encauth/ocb/ocb_init.o src/encauth/ocb/ocb_ntz.o \ +src/encauth/ocb/ocb_shift_xor.o src/encauth/ocb/ocb_test.o src/encauth/ocb/s_ocb_done.o \ +src/encauth/ocb3/ocb3_add_aad.o src/encauth/ocb3/ocb3_decrypt.o src/encauth/ocb3/ocb3_decrypt_last.o \ +src/encauth/ocb3/ocb3_decrypt_verify_memory.o src/encauth/ocb3/ocb3_done.o \ +src/encauth/ocb3/ocb3_encrypt.o src/encauth/ocb3/ocb3_encrypt_authenticate_memory.o \ +src/encauth/ocb3/ocb3_encrypt_last.o src/encauth/ocb3/ocb3_init.o src/encauth/ocb3/ocb3_int_ntz.o \ +src/encauth/ocb3/ocb3_int_xor_blocks.o src/encauth/ocb3/ocb3_test.o src/hashes/blake2b.o \ +src/hashes/blake2s.o src/hashes/chc/chc.o src/hashes/helper/hash_file.o \ +src/hashes/helper/hash_filehandle.o src/hashes/helper/hash_memory.o \ +src/hashes/helper/hash_memory_multi.o src/hashes/md2.o src/hashes/md4.o src/hashes/md5.o \ +src/hashes/rmd128.o src/hashes/rmd160.o src/hashes/rmd256.o src/hashes/rmd320.o src/hashes/sha1.o \ +src/hashes/sha2/sha224.o src/hashes/sha2/sha256.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \ +src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \ +src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ +src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \ +src/mac/blake2/blake2bmac_memory_multi.o src/mac/blake2/blake2bmac_test.o src/mac/blake2/blake2smac.o \ +src/mac/blake2/blake2smac_file.o src/mac/blake2/blake2smac_memory.o \ +src/mac/blake2/blake2smac_memory_multi.o src/mac/blake2/blake2smac_test.o src/mac/f9/f9_done.o \ +src/mac/f9/f9_file.o src/mac/f9/f9_init.o src/mac/f9/f9_memory.o src/mac/f9/f9_memory_multi.o \ +src/mac/f9/f9_process.o src/mac/f9/f9_test.o src/mac/hmac/hmac_done.o src/mac/hmac/hmac_file.o \ +src/mac/hmac/hmac_init.o src/mac/hmac/hmac_memory.o src/mac/hmac/hmac_memory_multi.o \ +src/mac/hmac/hmac_process.o src/mac/hmac/hmac_test.o src/mac/omac/omac_done.o src/mac/omac/omac_file.o \ +src/mac/omac/omac_init.o src/mac/omac/omac_memory.o src/mac/omac/omac_memory_multi.o \ +src/mac/omac/omac_process.o src/mac/omac/omac_test.o src/mac/pelican/pelican.o \ +src/mac/pelican/pelican_memory.o src/mac/pelican/pelican_test.o src/mac/pmac/pmac_done.o \ +src/mac/pmac/pmac_file.o src/mac/pmac/pmac_init.o src/mac/pmac/pmac_memory.o \ +src/mac/pmac/pmac_memory_multi.o src/mac/pmac/pmac_ntz.o src/mac/pmac/pmac_process.o \ +src/mac/pmac/pmac_shift_xor.o src/mac/pmac/pmac_test.o src/mac/poly1305/poly1305.o \ +src/mac/poly1305/poly1305_file.o src/mac/poly1305/poly1305_memory.o \ +src/mac/poly1305/poly1305_memory_multi.o src/mac/poly1305/poly1305_test.o src/mac/xcbc/xcbc_done.o \ +src/mac/xcbc/xcbc_file.o src/mac/xcbc/xcbc_init.o src/mac/xcbc/xcbc_memory.o \ +src/mac/xcbc/xcbc_memory_multi.o src/mac/xcbc/xcbc_process.o src/mac/xcbc/xcbc_test.o \ +src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math/multi.o \ +src/math/radix_to_bin.o src/math/rand_bn.o src/math/rand_prime.o src/math/tfm_desc.o src/misc/adler32.o \ +src/misc/base16/base16_decode.o src/misc/base16/base16_encode.o src/misc/base32/base32_decode.o \ +src/misc/base32/base32_encode.o src/misc/base64/base64_decode.o src/misc/base64/base64_encode.o \ +src/misc/bcrypt/bcrypt.o src/misc/burn_stack.o src/misc/compare_testvector.o src/misc/copy_or_zeromem.o \ +src/misc/crc32.o src/misc/crypt/crypt.o src/misc/crypt/crypt_argchk.o \ +src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \ +src/misc/crypt/crypt_constants.o src/misc/crypt/crypt_find_cipher.o \ +src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher_id.o \ +src/misc/crypt/crypt_find_hash.o src/misc/crypt/crypt_find_hash_any.o \ +src/misc/crypt/crypt_find_hash_id.o src/misc/crypt/crypt_find_hash_oid.o \ +src/misc/crypt/crypt_find_prng.o src/misc/crypt/crypt_fsa.o src/misc/crypt/crypt_hash_descriptor.o \ +src/misc/crypt/crypt_hash_is_valid.o src/misc/crypt/crypt_inits.o \ +src/misc/crypt/crypt_ltc_mp_descriptor.o src/misc/crypt/crypt_prng_descriptor.o \ +src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_prng_rng_descriptor.o \ +src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_hashes.o \ +src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ +src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ +src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ +src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ +src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ +src/misc/padding/padding_pad.o src/misc/pbes/pbes.o src/misc/pbes/pbes1.o src/misc/pbes/pbes2.o \ +src/misc/pkcs12/pkcs12_kdf.o src/misc/pkcs12/pkcs12_utf8_to_utf16.o src/misc/pkcs5/pkcs_5_1.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/pkcs5/pkcs_5_test.o src/misc/ssh/ssh_decode_sequence_multi.o \ +src/misc/ssh/ssh_encode_sequence_multi.o src/misc/zeromem.o src/modes/cbc/cbc_decrypt.o \ +src/modes/cbc/cbc_done.o src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o \ +src/modes/cbc/cbc_setiv.o src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o \ +src/modes/cfb/cfb_done.o src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o \ +src/modes/cfb/cfb_setiv.o src/modes/cfb/cfb_start.o src/modes/ctr/ctr_decrypt.o \ +src/modes/ctr/ctr_done.o src/modes/ctr/ctr_encrypt.o src/modes/ctr/ctr_getiv.o \ +src/modes/ctr/ctr_setiv.o src/modes/ctr/ctr_start.o src/modes/ctr/ctr_test.o \ +src/modes/ecb/ecb_decrypt.o src/modes/ecb/ecb_done.o src/modes/ecb/ecb_encrypt.o \ +src/modes/ecb/ecb_start.o src/modes/f8/f8_decrypt.o src/modes/f8/f8_done.o src/modes/f8/f8_encrypt.o \ +src/modes/f8/f8_getiv.o src/modes/f8/f8_setiv.o src/modes/f8/f8_start.o src/modes/f8/f8_test_mode.o \ +src/modes/lrw/lrw_decrypt.o src/modes/lrw/lrw_done.o src/modes/lrw/lrw_encrypt.o \ +src/modes/lrw/lrw_getiv.o src/modes/lrw/lrw_process.o src/modes/lrw/lrw_setiv.o \ +src/modes/lrw/lrw_start.o src/modes/lrw/lrw_test.o src/modes/ofb/ofb_decrypt.o src/modes/ofb/ofb_done.o \ +src/modes/ofb/ofb_encrypt.o src/modes/ofb/ofb_getiv.o src/modes/ofb/ofb_setiv.o \ +src/modes/ofb/ofb_start.o src/modes/xts/xts_decrypt.o src/modes/xts/xts_done.o \ +src/modes/xts/xts_encrypt.o src/modes/xts/xts_init.o src/modes/xts/xts_mult_x.o \ +src/modes/xts/xts_test.o src/pk/asn1/der/bit/der_decode_bit_string.o \ +src/pk/asn1/der/bit/der_decode_raw_bit_string.o src/pk/asn1/der/bit/der_encode_bit_string.o \ +src/pk/asn1/der/bit/der_encode_raw_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \ +src/pk/asn1/der/boolean/der_decode_boolean.o src/pk/asn1/der/boolean/der_encode_boolean.o \ +src/pk/asn1/der/boolean/der_length_boolean.o src/pk/asn1/der/choice/der_decode_choice.o \ +src/pk/asn1/der/custom_type/der_decode_custom_type.o \ +src/pk/asn1/der/custom_type/der_encode_custom_type.o \ +src/pk/asn1/der/custom_type/der_length_custom_type.o src/pk/asn1/der/general/der_asn1_maps.o \ +src/pk/asn1/der/general/der_decode_asn1_identifier.o src/pk/asn1/der/general/der_decode_asn1_length.o \ +src/pk/asn1/der/general/der_encode_asn1_identifier.o src/pk/asn1/der/general/der_encode_asn1_length.o \ +src/pk/asn1/der/general/der_length_asn1_identifier.o src/pk/asn1/der/general/der_length_asn1_length.o \ +src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \ +src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.o \ +src/pk/asn1/der/generalizedtime/der_length_generalizedtime.o \ +src/pk/asn1/der/ia5/der_decode_ia5_string.o src/pk/asn1/der/ia5/der_encode_ia5_string.o \ +src/pk/asn1/der/ia5/der_length_ia5_string.o src/pk/asn1/der/integer/der_decode_integer.o \ +src/pk/asn1/der/integer/der_encode_integer.o src/pk/asn1/der/integer/der_length_integer.o \ +src/pk/asn1/der/object_identifier/der_decode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_encode_object_identifier.o \ +src/pk/asn1/der/object_identifier/der_length_object_identifier.o \ +src/pk/asn1/der/octet/der_decode_octet_string.o src/pk/asn1/der/octet/der_encode_octet_string.o \ +src/pk/asn1/der/octet/der_length_octet_string.o \ +src/pk/asn1/der/printable_string/der_decode_printable_string.o \ +src/pk/asn1/der/printable_string/der_encode_printable_string.o \ +src/pk/asn1/der/printable_string/der_length_printable_string.o \ +src/pk/asn1/der/sequence/der_decode_sequence_ex.o \ +src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \ +src/pk/asn1/der/sequence/der_decode_sequence_multi.o \ +src/pk/asn1/der/sequence/der_encode_sequence_ex.o \ +src/pk/asn1/der/sequence/der_encode_sequence_multi.o src/pk/asn1/der/sequence/der_length_sequence.o \ +src/pk/asn1/der/sequence/der_sequence_free.o src/pk/asn1/der/sequence/der_sequence_shrink.o \ +src/pk/asn1/der/set/der_encode_set.o src/pk/asn1/der/set/der_encode_setof.o \ +src/pk/asn1/der/short_integer/der_decode_short_integer.o \ +src/pk/asn1/der/short_integer/der_encode_short_integer.o \ +src/pk/asn1/der/short_integer/der_length_short_integer.o \ +src/pk/asn1/der/teletex_string/der_decode_teletex_string.o \ +src/pk/asn1/der/teletex_string/der_length_teletex_string.o \ +src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \ +src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \ +src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \ +src/pk/asn1/oid/pk_get_oid.o src/pk/asn1/oid/pk_oid_cmp.o src/pk/asn1/oid/pk_oid_str.o \ +src/pk/asn1/pkcs8/pkcs8_decode_flexi.o src/pk/asn1/x509/x509_decode_public_key_from_certificate.o \ +src/pk/asn1/x509/x509_decode_subject_public_key_info.o \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \ +src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \ +src/pk/dh/dh_import.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o \ +src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \ +src/pk/dsa/dsa_generate_key.o src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o \ +src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_set.o src/pk/dsa/dsa_set_pqg_dsaparam.o \ +src/pk/dsa/dsa_shared_secret.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \ +src/pk/dsa/dsa_verify_key.o src/pk/ec25519/ec25519_crypto_ctx.o src/pk/ec25519/ec25519_export.o \ +src/pk/ec25519/ec25519_import_pkcs8.o src/pk/ec25519/tweetnacl.o src/pk/ecc/ecc.o \ +src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \ +src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_export_openssl.o \ +src/pk/ecc/ecc_find_curve.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_key.o src/pk/ecc/ecc_get_oid_str.o \ +src/pk/ecc/ecc_get_size.o src/pk/ecc/ecc_import.o src/pk/ecc/ecc_import_openssl.o \ +src/pk/ecc/ecc_import_pkcs8.o src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_key.o \ +src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_set_curve.o src/pk/ecc/ecc_set_curve_internal.o \ +src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o src/pk/ecc/ecc_sign_hash.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ +src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ +src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ +src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ +src/pk/ecc/ltc_ecc_verify_key.o src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o \ +src/pk/ed25519/ed25519_import_pkcs8.o src/pk/ed25519/ed25519_import_raw.o \ +src/pk/ed25519/ed25519_import_x509.o src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o \ +src/pk/ed25519/ed25519_verify.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ +src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ +src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \ +src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ +src/pk/rsa/rsa_export.o src/pk/rsa/rsa_exptmod.o src/pk/rsa/rsa_get_size.o src/pk/rsa/rsa_import.o \ +src/pk/rsa/rsa_import_pkcs8.o src/pk/rsa/rsa_import_x509.o src/pk/rsa/rsa_key.o \ +src/pk/rsa/rsa_make_key.o src/pk/rsa/rsa_set.o src/pk/rsa/rsa_sign_hash.o \ +src/pk/rsa/rsa_sign_saltlen_get.o src/pk/rsa/rsa_verify_hash.o src/pk/x25519/x25519_export.o \ +src/pk/x25519/x25519_import.o src/pk/x25519/x25519_import_pkcs8.o src/pk/x25519/x25519_import_raw.o \ +src/pk/x25519/x25519_import_x509.o src/pk/x25519/x25519_make_key.o \ +src/pk/x25519/x25519_shared_secret.o src/prngs/chacha20.o src/prngs/fortuna.o src/prngs/rc4.o \ +src/prngs/rng_get_bytes.o src/prngs/rng_make_prng.o src/prngs/sober128.o src/prngs/sprng.o \ +src/prngs/yarrow.o src/stream/chacha/chacha_crypt.o src/stream/chacha/chacha_done.o \ +src/stream/chacha/chacha_ivctr32.o src/stream/chacha/chacha_ivctr64.o \ +src/stream/chacha/chacha_keystream.o src/stream/chacha/chacha_memory.o \ +src/stream/chacha/chacha_setup.o src/stream/chacha/chacha_test.o src/stream/rabbit/rabbit.o \ +src/stream/rabbit/rabbit_memory.o src/stream/rc4/rc4_stream.o src/stream/rc4/rc4_stream_memory.o \ +src/stream/rc4/rc4_test.o src/stream/salsa20/salsa20_crypt.o src/stream/salsa20/salsa20_done.o \ +src/stream/salsa20/salsa20_ivctr64.o src/stream/salsa20/salsa20_keystream.o \ +src/stream/salsa20/salsa20_memory.o src/stream/salsa20/salsa20_setup.o \ +src/stream/salsa20/salsa20_test.o src/stream/salsa20/xsalsa20_memory.o \ +src/stream/salsa20/xsalsa20_setup.o src/stream/salsa20/xsalsa20_test.o \ +src/stream/sober128/sober128_stream.o src/stream/sober128/sober128_stream_memory.o \ +src/stream/sober128/sober128_test.o src/stream/sosemanuk/sosemanuk.o \ +src/stream/sosemanuk/sosemanuk_memory.o src/stream/sosemanuk/sosemanuk_test.o + +# List of test objects to compile (all goes to libtomcrypt_prof.a) +TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ +tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ +tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ +tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_null_termination_check_test.o \ +tests/no_prng.o tests/padding_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ +tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ +tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o + +# The following headers will be installed by "make install" +HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ +src/headers/tomcrypt_cipher.h src/headers/tomcrypt_custom.h src/headers/tomcrypt_hash.h \ +src/headers/tomcrypt_mac.h src/headers/tomcrypt_macros.h src/headers/tomcrypt_math.h \ +src/headers/tomcrypt_misc.h src/headers/tomcrypt_pk.h src/headers/tomcrypt_pkcs.h \ +src/headers/tomcrypt_prng.h + +HEADERS=$(HEADERS_PUB) src/headers/tomcrypt_private.h + +#These are the rules to make certain object files. +src/ciphers/aes/aes.o: src/ciphers/aes/aes.c src/ciphers/aes/aes_tab.c +src/ciphers/twofish/twofish.o: src/ciphers/twofish/twofish.c src/ciphers/twofish/twofish_tab.c +src/hashes/sha2/sha224.o: src/hashes/sha2/sha224.c src/hashes/sha2/sha256.c +src/hashes/sha2/sha384.o: src/hashes/sha2/sha384.c src/hashes/sha2/sha512.c +src/hashes/sha2/sha512_224.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_224.c +src/hashes/sha2/sha512_256.o: src/hashes/sha2/sha512.c src/hashes/sha2/sha512_256.c +src/hashes/whirl/whirl.o: src/hashes/whirl/whirl.c src/hashes/whirl/whirltab.c + +$(DOBJECTS): LTC_CFLAGS := -Itests $(LTC_CFLAGS) +$(TOBJECTS): LTC_CFLAGS := -Itests $(LTC_CFLAGS) + +#Dependencies on *.h +$(OBJECTS): $(HEADERS) +$(DOBJECTS): $(HEADERS) $(THEADERS) +$(TOBJECTS): $(HEADERS) $(THEADERS) + +all: $(call print-help,all,Builds the library and all demos and test utils (test $(UNBROKEN_DEMOS) $(BROKEN_DEMOS))) all_test $(BROKEN_DEMOS) + +all_test: $(call print-help,all_test,Builds the library and all unbroken demos and test utils (test $(UNBROKEN_DEMOS))) test $(UNBROKEN_DEMOS) + +bins: $(call print-help,bins,Builds the library and all useful demos) $(USEFUL_DEMOS) + +check: test + ./test + +#build the doxy files (requires Doxygen, tetex and patience) +doxygen: $(call print-help,doxygen,Builds the doxygen html documentation) + $(MAKE) -C doc/ $@ V=$(V) +doxy: $(call print-help,doxy,Builds the complete doxygen documentation including refman.pdf (takes long to generate)) + $(MAKE) -C doc/ $@ V=$(V) +docs: $(call print-help,docs,Builds the Developer Manual) + $(MAKE) -C doc/ $@ V=$(V) + +doc/crypt.pdf: $(call print-help,doc/crypt.pdf,Builds the Developer Manual) + $(MAKE) -C doc/ crypt.pdf V=$(V) + + +install_all: $(call print-help,install_all,Install everything - library bins docs tests) install install_bins install_docs + +INSTALL_OPTS ?= -m 644 + +.common_install: $(LIBNAME) + install -p -d $(DESTDIR)$(INCPATH) + install -p -d $(DESTDIR)$(LIBPATH) + $(INSTALL_CMD) -p $(INSTALL_OPTS) $(LIBNAME) $(DESTDIR)$(LIBPATH)/$(LIBNAME) + install -p -m 644 $(HEADERS_PUB) $(DESTDIR)$(INCPATH) + +$(DESTDIR)$(BINPATH): + install -p -d $(DESTDIR)$(BINPATH) + +.common_install_bins: $(USEFUL_DEMOS) $(DESTDIR)$(BINPATH) + $(INSTALL_CMD) -p -m 775 $(USEFUL_DEMOS) $(DESTDIR)$(BINPATH) + +install_docs: $(call print-help,install_docs,Installs the Developer Manual) doc/crypt.pdf + install -p -d $(DESTDIR)$(DATAPATH) + install -p -m 644 doc/crypt.pdf $(DESTDIR)$(DATAPATH) + +install_test: $(call print-help,install_test,Installs the self-test binary) test $(DESTDIR)$(BINPATH) + $(INSTALL_CMD) -p -m 775 $< $(DESTDIR)$(BINPATH) + +install_hooks: $(call print-help,install_hooks,Installs the git hooks) + for s in `ls hooks/`; do ln -s ../../hooks/$$s .git/hooks/$$s; done + +HEADER_FILES=$(notdir $(HEADERS_PUB)) +.common_uninstall: + $(UNINSTALL_CMD) $(DESTDIR)$(LIBPATH)/$(LIBNAME) + rm $(HEADER_FILES:%=$(DESTDIR)$(INCPATH)/%) + +#This rule cleans the source tree of all compiled code, not including the pdf +#documentation. +clean: $(call print-help,clean,Clean everything besides the pdf documentation) + find . -type f -name "*.o" \ + -o -name "*.lo" \ + -o -name "*.a" \ + -o -name "*.la" \ + -o -name "*.obj" \ + -o -name "*.lib" \ + -o -name "*.exe" \ + -o -name "*.dll" \ + -o -name "*.so" \ + -o -name "*.gcov"\ + -o -name "*.gcda"\ + -o -name "*.gcno"\ + -o -name "*.il" \ + -o -name "*.dyn" \ + -o -name "*.dpi" | xargs rm -f + rm -f $(TIMING) $(TEST) $(DEMOS) + rm -f *_tv.txt + rm -f *.pc + rm -rf `find . -type d -name "*.libs" | xargs` + $(MAKE) -C doc/ clean + +zipup: $(call print-help,zipup,Prepare the archives for a release) doc/crypt.pdf + @# Update the index, so diff-index won't fail in case the pdf has been created. + @# As the pdf creation modifies crypt.tex, git sometimes detects the + @# modified file, but misses that it's put back to its original version. + @git update-index --refresh + @git diff-index --quiet HEAD -- || ( echo "FAILURE: uncommited changes or not a git" && exit 1 ) + @perl helper.pl --check-all || ( echo "FAILURE: helper.pl --check-all errors" && exit 1 ) + rm -rf libtomcrypt-$(VERSION) crypt-$(VERSION).* + @# files/dirs excluded from "git archive" are defined in .gitattributes + git archive --format=tar --prefix=libtomcrypt-$(VERSION)/ HEAD | tar x + @echo 'fixme check' + -@(find libtomcrypt-$(VERSION)/ -type f | xargs grep 'FIXM[E]') && echo '############## BEWARE: the "fixme" marker was found !!! ##############' || true + mkdir -p libtomcrypt-$(VERSION)/doc + cp doc/crypt.pdf libtomcrypt-$(VERSION)/doc/crypt.pdf + tar -c libtomcrypt-$(VERSION)/ | xz -6e -c - > crypt-$(VERSION).tar.xz + zip -9rq crypt-$(VERSION).zip libtomcrypt-$(VERSION) + rm -rf libtomcrypt-$(VERSION) + gpg -b -a crypt-$(VERSION).tar.xz + gpg -b -a crypt-$(VERSION).zip + +codecheck: $(call print-help,codecheck,Check the code of the library) + perl helper.pl -a + perlcritic *.pl + +help: $(call print-help,help,That's what you're currently looking at) + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/notes/etc/NoekeonVects.java b/deps/libtomcrypt/notes/etc/NoekeonVects.java new file mode 100644 index 0000000..8ec542a --- /dev/null +++ b/deps/libtomcrypt/notes/etc/NoekeonVects.java @@ -0,0 +1,249 @@ +/* + NoekeonVects.java - Generate Noekeon test vectors using BouncyCastle. + + Written in 2011 by Patrick Pelletier + + To the extent possible under law, the author(s) have dedicated all + copyright and related and neighboring rights to this software to + the public domain worldwide. This software is distributed without + any warranty. + + This file is dedicated to the public domain with the CC0 Public Domain + Dedication: http://creativecommons.org/publicdomain/zero/1.0/legalcode.txt + + You may also consider this file to be covered by the WTFPL, as contained + in the LibTomCrypt LICENSE file, if that makes you happier for some reason. + + ---------------------------------------------------------------------- + + This program was inspired by the comment in Botan 1.10.1's + doc/examples/eax_test.cpp: + + // Noekeon: unknown cause, though LTC's lone test vector does not + // match Botan + + So, I investigated the discrepancy by comparing them with a third + implementation, BouncyCastle: http://www.bouncycastle.org/java.html + + I determined that there are two reasons why LibTomCrypt's Noekeon does + not match Botan: + + 1) Botan uses "indirect Noekeon" (with a key schedule), while + LibTomCrypt and BouncyCastle both use "direct Noekeon" (without + a key schedule). See slide 14 of + http://gro.noekeon.org/Noekeon-slides.pdf + + 2) However, LibTomCrypt's direct Noekeon still does not match + BouncyCastle's direct Noekeon. This is because of a bug in + LibTomCrypt's PI1 and PI2 functions: + https://github.com/libtom/libtomcrypt/issues/5 + + This program uses BouncyCastle to produce test vectors which are + suitable for Botan (by explicitly scheduling the key, thus + building indirect Noekeon out of BouncyCastle's direct Noekeon), + and also produces test vectors which would be suitable for + LibTomCrypt (direct Noekeon) once its PI1 and PI2 functions are + fixed to match the Noekeon specification. + + Although this program uses a PRNG from BouncyCastle to generate + data for the test vectors, it uses a fixed seed and thus will + produce the same output every time it is run. +*/ + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Locale; +import org.bouncycastle.crypto.digests.RIPEMD128Digest; +import org.bouncycastle.crypto.engines.NoekeonEngine; +import org.bouncycastle.crypto.modes.EAXBlockCipher; +import org.bouncycastle.crypto.params.AEADParameters; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.crypto.prng.DigestRandomGenerator; +import org.bouncycastle.util.encoders.HexEncoder; + +public class NoekeonVects +{ + private final DigestRandomGenerator r = + new DigestRandomGenerator(new RIPEMD128Digest()); + + private final HexEncoder h = new HexEncoder(); + + private final NoekeonEngine noekeon = new NoekeonEngine(); + + private final KeyParameter null_key = new KeyParameter(new byte[16]); + + private final boolean schedule_key; + + private final boolean botan_format; + + private byte[] randomBytes(int n) + { + byte[] b = new byte[n]; + r.nextBytes(b); + return b; + } + + private void hexOut(byte[] b) throws IOException + { + // HexEncoder uses lowercase, and Botan's test vectors must + // be in uppercase, so... + ByteArrayOutputStream os = new ByteArrayOutputStream(); + h.encode(b, 0, b.length, os); + String s = os.toString("US-ASCII"); + System.out.print(s.toUpperCase(Locale.US)); + } + + private void printCArray(byte[] a) throws IOException + { + byte[] b = new byte[1]; + for (int i = 0; i < a.length; i++) + { + if (i > 0) + System.out.print(", "); + System.out.print("0x"); + b[0] = a[i]; + hexOut(b); + } + } + + private void printVector(byte[] key, byte[] plaintext, byte[] ciphertext) + throws IOException + { + if (botan_format) + { + hexOut(plaintext); + System.out.print(":"); + hexOut(ciphertext); + System.out.println(":\\"); + hexOut(key); + System.out.println(); + } + else + { + System.out.println(" {"); + System.out.println(" 16,"); + System.out.print(" { "); + printCArray (key); + System.out.println(" },"); + System.out.print(" { "); + printCArray (plaintext); + System.out.println(" },"); + System.out.print(" { "); + printCArray (ciphertext); + System.out.println(" }"); + System.out.println(" },"); + } + } + + private KeyParameter maybe_schedule_key(byte[] key) + { + if (schedule_key) + { + noekeon.init(true, null_key); + byte[] scheduled = new byte[16]; + noekeon.processBlock(key, 0, scheduled, 0); + return new KeyParameter(scheduled); + } + else + return new KeyParameter(key); + } + + private byte[] encrypt(byte[] plaintext, byte[] key) + { + KeyParameter kp = maybe_schedule_key(key); + noekeon.init(true, kp); + byte[] ciphertext = new byte[16]; + noekeon.processBlock(plaintext, 0, ciphertext, 0); + return ciphertext; + } + + public NoekeonVects(long seed, boolean schedule_key, boolean botan_format) + { + this.schedule_key = schedule_key; + this.botan_format = botan_format; + r.addSeedMaterial(seed); + } + + public void ecb_vectors() throws IOException + { + for (int i = 0; i < 8; i++) + { + byte[] key = randomBytes(16); + byte[] plaintext = randomBytes(16); + byte[] ciphertext = encrypt(plaintext, key); + printVector(key, plaintext, ciphertext); + } + } + + public void eax_vectors() throws Exception + { + System.out.println("EAX-noekeon (16 byte key)"); + EAXBlockCipher eax = new EAXBlockCipher(new NoekeonEngine()); + byte[] output = new byte[48]; + byte[] tag = new byte[16]; + + for (int j = 0; j < 16; j++) + tag[j] = (byte) j; + + for (int i = 0; i <= 32; i++) + { + byte[] header_nonce_plaintext = new byte[i]; + for (int j = 0; j < i; j++) + header_nonce_plaintext[j] = (byte) j; + AEADParameters params = + new AEADParameters(maybe_schedule_key(tag), + 128, + header_nonce_plaintext, + header_nonce_plaintext); + eax.init(true, params); + int off = eax.processBytes(header_nonce_plaintext, 0, i, + output, 0); + off += eax.doFinal(output, off); + if (off != i + 16) + throw new RuntimeException("didn't expect that"); + byte[] ciphertext = new byte[i]; + for (int j = 0; j < i; j++) + ciphertext[j] = output[j]; + for (int j = 0; j < 16; j++) + tag[j] = output[i + j]; + System.out.print(i < 10 ? " " : " "); + System.out.print(i); + System.out.print(": "); + hexOut(ciphertext); + System.out.print(", "); + hexOut(tag); + System.out.println(); + } + } + + public static void main(String[] argv) throws Exception + { + NoekeonVects bot = new NoekeonVects(0xdefacedbadfacadeL, true, true); + NoekeonVects tom = new NoekeonVects(0xdefacedbadfacadeL, false, false); + System.out.println("# ECB vectors for indirect Noekeon, in Botan's"); + System.out.println("# test vector format, suitable for insertion"); + System.out.println("# into Botan's file checks/validate.dat"); + System.out.println("# Block cipher format is plaintext:ciphertext:key"); + bot.ecb_vectors(); + System.out.println(); + System.out.println("/* ECB vectors for direct Noekeon, as C arrays"); + System.out.println(" * suitable for insertion into LibTomCrypt's"); + System.out.println(" * noekeon_test() in src/ciphers/noekeon.c,"); + System.out.println(" * once LTC's PI1/PI2 bug is fixed. */"); + tom.ecb_vectors(); + System.out.println(); + System.out.println("# EAX vectors for indirect Noekeon, in the format"); + System.out.println("# generated by LTC's demos/tv_gen.c and consumed"); + System.out.println("# by Botan's doc/examples/eax_test.cpp, suitable"); + System.out.println("# for insertion in Botan's doc/examples/eax.vec"); + bot.eax_vectors(); + System.out.println(); + System.out.println("# EAX vectors for direct Noekeon, in the format"); + System.out.println("# generated by LTC's demos/tv_gen.c and consumed"); + System.out.println("# by Botan's doc/examples/eax_test.cpp, which"); + System.out.println("# should match LTC's notes/eax_tv.txt, once"); + System.out.println("# LTC's PI1/PI2 bug is fixed."); + tom.eax_vectors(); + System.out.flush(); + } +} diff --git a/deps/libtomcrypt/notes/etc/saferp_optimizer.c b/deps/libtomcrypt/notes/etc/saferp_optimizer.c new file mode 100644 index 0000000..4a66d63 --- /dev/null +++ b/deps/libtomcrypt/notes/etc/saferp_optimizer.c @@ -0,0 +1,177 @@ +/* emits an optimized version of LTC_SAFER+ ... only does encrypt so far... */ + +#include +#include + +/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */ +#define SHUF\ + b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \ + b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \ + b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \ + b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; memcpy(b, b2, sizeof(b)); + +/* This is the inverse shuffle. It takes from b and gives to b2 */ +#define iSHUF(b, b2) \ + b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \ + b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \ + b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \ + b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; memcpy(b, b2, sizeof(b)); + +#define ROUND(b, i) \ + b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \ + b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \ + b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \ + b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \ + b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \ + b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \ + b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \ + b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \ + b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \ + b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \ + b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \ + b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \ + b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \ + b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \ + b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \ + b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; + +int main(void) +{ + int b[16], b2[16], x, y, z; + +/* -- ENCRYPT --- */ + for (x = 0; x < 16; x++) b[x] = x; + /* emit encrypt preabmle */ +printf( +"void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)\n" +"{\n" +" int x;\n" +" unsigned char b[16];\n" +"\n" +" LTC_ARGCHK(pt != NULL);\n" +" LTC_ARGCHK(ct != NULL);\n" +" LTC_ARGCHK(skey != NULL);\n" +"\n" +" /* do eight rounds */\n" +" for (x = 0; x < 16; x++) {\n" +" b[x] = pt[x];\n" +" }\n"); + + /* do 8 rounds of ROUND; LT; */ + for (x = 0; x < 8; x++) { + /* ROUND(..., x*2) */ + for (y = 0; y < 16; y++) { +printf("b[%d] = (safer_%cbox[(b[%d] %c skey->saferp.K[%d][%d]) & 255] %c skey->saferp.K[%d][%d]) & 255;\n", + b[y], "elle"[y&3], b[y], "^++^"[y&3], x*2, y, "+^^+"[y&3], x*2+1, y); + } + + /* LT */ + for (y = 0; y < 4; y++) { +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[0], b[0], b[1], b[0], b[1]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[2], b[2], b[3], b[3], b[2]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[4], b[4], b[5], b[5], b[4]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[6], b[6], b[7], b[7], b[6]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[8], b[8], b[9], b[9], b[8]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[10], b[10], b[11], b[11], b[10]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[12], b[12], b[13], b[13], b[12]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[14], b[14], b[15], b[15], b[14]); + if (y < 3) { + SHUF; + } + } + } + +printf( +" if (skey->saferp.rounds <= 8) {\n"); +/* finish */ + for (x = 0; x < 16; x++) { + printf( +" ct[%d] = (b[%d] %c skey->saferp.K[skey->saferp.rounds*2][%d]) & 255;\n", + x, b[x], "^++^"[x&3], x); + } + printf(" return;\n }\n"); + + /* 192-bit keys */ +printf( +" /* 192-bit key? */\n" +" if (skey->saferp.rounds > 8) {\n"); + + /* do 4 rounds of ROUND; LT; */ + for (x = 8; x < 12; x++) { + /* ROUND(..., x*2) */ + for (y = 0; y < 16; y++) { +printf("b[%d] = (safer_%cbox[(b[%d] %c skey->saferp.K[%d][%d]) & 255] %c skey->saferp.K[%d][%d]) & 255;\n", + b[y], "elle"[y&3], b[y], "^++^"[y&3], x*2, y, "+^^+"[y&3], x*2+1, y); + } + + /* LT */ + for (y = 0; y < 4; y++) { +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[0], b[0], b[1], b[0], b[1]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[2], b[2], b[3], b[3], b[2]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[4], b[4], b[5], b[5], b[4]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[6], b[6], b[7], b[7], b[6]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[8], b[8], b[9], b[9], b[8]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[10], b[10], b[11], b[11], b[10]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[12], b[12], b[13], b[13], b[12]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[14], b[14], b[15], b[15], b[14]); + if (y < 3) { + SHUF; + } + } + } +printf("}\n"); + +printf( +" if (skey->saferp.rounds <= 12) {\n"); +/* finish */ + for (x = 0; x < 16; x++) { + printf( +" ct[%d] = (b[%d] %c skey->saferp.K[skey->saferp.rounds*2][%d]) & 255;\n", + x, b[x], "^++^"[x&3], x); + } + printf(" return;\n }\n"); + + /* 256-bit keys */ +printf( +" /* 256-bit key? */\n" +" if (skey->saferp.rounds > 12) {\n"); + + /* do 4 rounds of ROUND; LT; */ + for (x = 12; x < 16; x++) { + /* ROUND(..., x*2) */ + for (y = 0; y < 16; y++) { +printf("b[%d] = (safer_%cbox[(b[%d] %c skey->saferp.K[%d][%d]) & 255] %c skey->saferp.K[%d][%d]) & 255;\n", + b[y], "elle"[y&3], b[y], "^++^"[y&3], x*2, y, "+^^+"[y&3], x*2+1, y); + } + + /* LT */ + for (y = 0; y < 4; y++) { +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[0], b[0], b[1], b[0], b[1]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[2], b[2], b[3], b[3], b[2]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[4], b[4], b[5], b[5], b[4]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[6], b[6], b[7], b[7], b[6]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[8], b[8], b[9], b[9], b[8]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[10], b[10], b[11], b[11], b[10]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[12], b[12], b[13], b[13], b[12]); +printf(" b[%d] = (b[%d] + (b[%d] = (b[%d] + b[%d]) & 255)) & 255;\n", b[14], b[14], b[15], b[15], b[14]); + if (y < 3) { + SHUF; + } + } + } +/* finish */ + for (x = 0; x < 16; x++) { + printf( +" ct[%d] = (b[%d] %c skey->saferp.K[skey->saferp.rounds*2][%d]) & 255;\n", + x, b[x], "^++^"[x&3], x); + } + printf(" return;\n"); +printf(" }\n}\n\n"); + + return 0; +} + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/deps/libtomcrypt/notes/etc/whirlgen.c b/deps/libtomcrypt/notes/etc/whirlgen.c new file mode 100644 index 0000000..d537cef --- /dev/null +++ b/deps/libtomcrypt/notes/etc/whirlgen.c @@ -0,0 +1,95 @@ +#include + +unsigned E[16] = { 1, 0xb, 9, 0xc, 0xd, 6, 0xf, 3, 0xe, 8, 7, 4, 0xa, 2, 5, 0 }; +unsigned Ei[16]; +unsigned R[16] = { 7, 0xc, 0xb, 0xd, 0xe, 4, 9, 0xf, 6, 3, 8, 0xa, 2, 5, 1, 0 }; +unsigned cir[8][8] = { + {1, 1, 4, 1, 8, 5, 2, 9 }, +}; + + +unsigned gf_mul(unsigned a, unsigned b) +{ + unsigned r; + + r = 0; + while (a) { + if (a & 1) r ^= b; + a >>= 1; + b = (b << 1) ^ (b & 0x80 ? 0x11d : 0x00); + } + return r; +} + +unsigned sbox(unsigned x) +{ + unsigned a, b, w; + + a = x >> 4; + b = x & 15; + + a = E[a]; b = Ei[b]; + w = a ^ b; w = R[w]; + a = E[a ^ w]; b = Ei[b ^ w]; + + + return (a << 4) | b; +} + +int main(void) +{ + unsigned x, y; + + for (x = 0; x < 16; x++) Ei[E[x]] = x; + +// for (x = 0; x < 16; x++) printf("%2x ", sbox(x)); + for (y = 1; y < 8; y++) { + for (x = 0; x < 8; x++) { + cir[y][x] = cir[y-1][(x-1)&7]; + } + } + +/* + printf("\n"); + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) printf("%2d ", cir[y][x]); + printf("\n"); + } +*/ + + for (y = 0; y < 8; y++) { + printf("static const ulong64 sbox%d[] = {\n", y); + for (x = 0; x < 256; ) { + printf("CONST64(0x%02x%02x%02x%02x%02x%02x%02x%02x)", + gf_mul(sbox(x), cir[y][0]), + gf_mul(sbox(x), cir[y][1]), + gf_mul(sbox(x), cir[y][2]), + gf_mul(sbox(x), cir[y][3]), + gf_mul(sbox(x), cir[y][4]), + gf_mul(sbox(x), cir[y][5]), + gf_mul(sbox(x), cir[y][6]), + gf_mul(sbox(x), cir[y][7])); + if (x < 255) printf(", "); + if (!(++x & 3)) printf("\n"); + } + printf("};\n\n"); + } + + printf("static const ulong64 cont[] = {\n"); + for (y = 0; y <= 10; y++) { + printf("CONST64(0x"); + for (x = 0; x < 8; x++) { + printf("%02x", sbox((8*y + x)&255)); + } + printf("),\n"); + } + printf("};\n\n"); + return 0; + +} + + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/deps/libtomcrypt/notes/etc/whirltest.c b/deps/libtomcrypt/notes/etc/whirltest.c new file mode 100644 index 0000000..d8c24e8 --- /dev/null +++ b/deps/libtomcrypt/notes/etc/whirltest.c @@ -0,0 +1,19 @@ +#include + +int main(void) +{ + char buf[4096]; + int x; + + while (fgets(buf, sizeof(buf)-2, stdin) != NULL) { + for (x = 0; x < 128; ) { + printf("0x%c%c, ", buf[x], buf[x+1]); + if (!((x += 2) & 31)) printf("\n"); + } + } +} + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/deps/libtomcrypt/notes/rsa-testvectors/makefile b/deps/libtomcrypt/notes/rsa-testvectors/makefile new file mode 100644 index 0000000..dd84f47 --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/makefile @@ -0,0 +1,11 @@ +default: regen + +clean: + rm -f *.c + +regen: + python rt.py pss-vect.txt pss > pss-vect.c + python rt.py oaep-vect.txt oaep > oaep-vect.c + python rt.py pkcs1v15sign-vectors.txt emsa > pkcs1v15sign-vectors.c + python rt.py pkcs1v15crypt-vectors.txt eme > pkcs1v15crypt-vectors.c + diff --git a/deps/libtomcrypt/notes/rsa-testvectors/oaep-int.txt b/deps/libtomcrypt/notes/rsa-testvectors/oaep-int.txt new file mode 100644 index 0000000..aea559f --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/oaep-int.txt @@ -0,0 +1,369 @@ +# ================================= +# WORKED-OUT EXAMPLE FOR RSAES-OAEP +# ================================= +# +# This file gives an example of the process of +# encrypting and decrypting a message with +# RSAES-OAEP as specified in PKCS #1 v2.1. +# +# The message is a bit string of length 128, +# while the size of the modulus in the public +# key is 1024 bits. The second representation +# of the private key is used, which means that +# CRT is applied in the decryption process. +# +# The underlying hash function is SHA-1; the +# mask generation function is MGF1 with SHA-1 +# as specified in PKCS #1 v2.1. +# +# This file also contains a demonstration of +# the RSADP decryption primitive with CRT. +# Finally, DER encodings of the RSA keys are +# given at the end of the file. +# +# +# Integers are represented by strings of octets +# with the leftmost octet being the most +# significant octet. For example, +# +# 9,202,000 = (0x)8c 69 50. +# +# ============================================= + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +bb f8 2f 09 06 82 ce 9c 23 38 ac 2b 9d a8 71 f7 +36 8d 07 ee d4 10 43 a4 40 d6 b6 f0 74 54 f5 1f +b8 df ba af 03 5c 02 ab 61 ea 48 ce eb 6f cd 48 +76 ed 52 0d 60 e1 ec 46 19 71 9d 8a 5b 8b 80 7f +af b8 e0 a3 df c7 37 72 3e e6 b4 b7 d9 3a 25 84 +ee 6a 64 9d 06 09 53 74 88 34 b2 45 45 98 39 4e +e0 aa b1 2d 7b 61 a5 1f 52 7a 9a 41 f6 c1 68 7f +e2 53 72 98 ca 2a 8f 59 46 f8 e5 fd 09 1d bd cb + +# RSA public exponent e: +(0x)11 + +# Prime p: +ee cf ae 81 b1 b9 b3 c9 08 81 0b 10 a1 b5 60 01 +99 eb 9f 44 ae f4 fd a4 93 b8 1a 9e 3d 84 f6 32 +12 4e f0 23 6e 5d 1e 3b 7e 28 fa e7 aa 04 0a 2d +5b 25 21 76 45 9d 1f 39 75 41 ba 2a 58 fb 65 99 + +# Prime q: +c9 7f b1 f0 27 f4 53 f6 34 12 33 ea aa d1 d9 35 +3f 6c 42 d0 88 66 b1 d0 5a 0f 20 35 02 8b 9d 86 +98 40 b4 16 66 b4 2e 92 ea 0d a3 b4 32 04 b5 cf +ce 33 52 52 4d 04 16 a5 a4 41 e7 00 af 46 15 03 + +# p's CRT exponent dP: +54 49 4c a6 3e ba 03 37 e4 e2 40 23 fc d6 9a 5a +eb 07 dd dc 01 83 a4 d0 ac 9b 54 b0 51 f2 b1 3e +d9 49 09 75 ea b7 74 14 ff 59 c1 f7 69 2e 9a 2e +20 2b 38 fc 91 0a 47 41 74 ad c9 3c 1f 67 c9 81 + +# q's CRT exponent dQ: +47 1e 02 90 ff 0a f0 75 03 51 b7 f8 78 86 4c a9 +61 ad bd 3a 8a 7e 99 1c 5c 05 56 a9 4c 31 46 a7 +f9 80 3f 8f 6f 8a e3 42 e9 31 fd 8a e4 7a 22 0d +1b 99 a4 95 84 98 07 fe 39 f9 24 5a 98 36 da 3d + +# CRT coefficient qInv: +b0 6c 4f da bb 63 01 19 8d 26 5b db ae 94 23 b3 +80 f2 71 f7 34 53 88 50 93 07 7f cd 39 e2 11 9f +c9 86 32 15 4f 58 83 b1 67 a9 67 bf 40 2b 4e 9e +2e 0f 96 56 e6 98 ea 36 66 ed fb 25 79 80 39 f7 + +# ---------------------------------- +# Step-by-step RSAES-OAEP Encryption +# ---------------------------------- + +# Message M to be encrypted: +d4 36 e9 95 69 fd 32 a7 c8 a0 5b bc 90 d3 2c 49 + +# Label L: +(the empty string) + +# lHash = Hash(L) +# DB = lHash || Padding || M +# seed = random string of octets +# dbMask = MGF(seed, length(DB)) +# maskedDB = DB xor dbMask +# seedMask = MGF(maskedDB, length(seed)) +# maskedSeed = seed xor seedMask +# EM = 0x00 || maskedSeed || maskedDB + +# lHash: +da 39 a3 ee 5e 6b 4b 0d 32 55 bf ef 95 60 18 90 +af d8 07 09 + +# DB: +da 39 a3 ee 5e 6b 4b 0d 32 55 bf ef 95 60 18 90 +af d8 07 09 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 01 d4 36 e9 95 69 +fd 32 a7 c8 a0 5b bc 90 d3 2c 49 + +# seed: +aa fd 12 f6 59 ca e6 34 89 b4 79 e5 07 6d de c2 +f0 6c b5 8f + +# dbMask: +06 e1 de b2 36 9a a5 a5 c7 07 d8 2c 8e 4e 93 24 +8a c7 83 de e0 b2 c0 46 26 f5 af f9 3e dc fb 25 +c9 c2 b3 ff 8a e1 0e 83 9a 2d db 4c dc fe 4f f4 +77 28 b4 a1 b7 c1 36 2b aa d2 9a b4 8d 28 69 d5 +02 41 21 43 58 11 59 1b e3 92 f9 82 fb 3e 87 d0 +95 ae b4 04 48 db 97 2f 3a c1 4e af f4 9c 8c 3b +7c fc 95 1a 51 ec d1 dd e6 12 64 + +# maskedDB: +dc d8 7d 5c 68 f1 ee a8 f5 52 67 c3 1b 2e 8b b4 +25 1f 84 d7 e0 b2 c0 46 26 f5 af f9 3e dc fb 25 +c9 c2 b3 ff 8a e1 0e 83 9a 2d db 4c dc fe 4f f4 +77 28 b4 a1 b7 c1 36 2b aa d2 9a b4 8d 28 69 d5 +02 41 21 43 58 11 59 1b e3 92 f9 82 fb 3e 87 d0 +95 ae b4 04 48 db 97 2f 3a c1 4f 7b c2 75 19 52 +81 ce 32 d2 f1 b7 6d 4d 35 3e 2d + +# seedMask: +41 87 0b 5a b0 29 e6 57 d9 57 50 b5 4c 28 3c 08 +72 5d be a9 + +# maskedSeed: +eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2 ca +82 31 0b 26 + +# EM = 00 || maskedSeed || maskedDB: +00 eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2 +ca 82 31 0b 26 dc d8 7d 5c 68 f1 ee a8 f5 52 67 +c3 1b 2e 8b b4 25 1f 84 d7 e0 b2 c0 46 26 f5 af +f9 3e dc fb 25 c9 c2 b3 ff 8a e1 0e 83 9a 2d db +4c dc fe 4f f4 77 28 b4 a1 b7 c1 36 2b aa d2 9a +b4 8d 28 69 d5 02 41 21 43 58 11 59 1b e3 92 f9 +82 fb 3e 87 d0 95 ae b4 04 48 db 97 2f 3a c1 4f +7b c2 75 19 52 81 ce 32 d2 f1 b7 6d 4d 35 3e 2d + +# Ciphertext, the RSA encryption of EM: +12 53 e0 4d c0 a5 39 7b b4 4a 7a b8 7e 9b f2 a0 +39 a3 3d 1e 99 6f c8 2a 94 cc d3 00 74 c9 5d f7 +63 72 20 17 06 9e 52 68 da 5d 1c 0b 4f 87 2c f6 +53 c1 1d f8 23 14 a6 79 68 df ea e2 8d ef 04 bb +6d 84 b1 c3 1d 65 4a 19 70 e5 78 3b d6 eb 96 a0 +24 c2 ca 2f 4a 90 fe 9f 2e f5 c9 c1 40 e5 bb 48 +da 95 36 ad 87 00 c8 4f c9 13 0a de a7 4e 55 8d +51 a7 4d df 85 d8 b5 0d e9 68 38 d6 06 3e 09 55 + +# -------------------------------------------- +# Step-by-step RSAES-OAEP Decryption Using CRT +# -------------------------------------------- + +# c = the integer value of C above +# m1 = c^dP mod p = (c mod p)^dP mod p +# m2 = c^dQ mod q = (c mod q)^dQ mod q +# h = (m1-m2)*qInv mod p +# m = m2 + q*h = the integer value of EM above + +# c mod p: +de 63 d4 72 35 66 fa a7 59 bf e4 08 82 1d d5 25 +72 ec 92 85 4d df 87 a2 b6 64 d4 4d aa 37 ca 34 +6a 05 20 3d 82 ff 2d e8 e3 6c ec 1d 34 f9 8e b6 +05 e2 a7 d2 6d e7 af 36 9c e4 ec ae 14 e3 56 33 + +# c mod q: +a2 d9 24 de d9 c3 6d 62 3e d9 a6 5b 5d 86 2c fb +ec 8b 19 9c 64 27 9c 54 14 e6 41 19 6e f1 c9 3c +50 7a 9b 52 13 88 1a ad 05 b4 cc fa 02 8a c1 ec +61 42 09 74 bf 16 25 83 6b 0b 7d 05 fb b7 53 36 + +# m1: +89 6c a2 6c d7 e4 87 1c 7f c9 68 a8 ed ea 11 e2 +71 82 4f 0e 03 65 52 17 94 f1 e9 e9 43 b4 a4 4b +57 c9 e3 95 a1 46 74 78 f5 26 49 6b 4b b9 1f 1c +ba ea 90 0f fc 60 2c f0 c6 63 6e ba 84 fc 9f f7 + +# m2: +4e bb 22 75 85 f0 c1 31 2d ca 19 e0 b5 41 db 14 +99 fb f1 4e 27 0e 69 8e 23 9a 8c 27 a9 6c da 9a +74 09 74 de 93 7b 5c 9c 93 ea d9 46 2c 65 75 02 +1a 23 d4 64 99 dc 9f 6b 35 89 75 59 60 8f 19 be + +# h: +01 2b 2b 24 15 0e 76 e1 59 bd 8d db 42 76 e0 7b +fa c1 88 e0 8d 60 47 cf 0e fb 8a e2 ae bd f2 51 +c4 0e bc 23 dc fd 4a 34 42 43 94 ad a9 2c fc be +1b 2e ff bb 60 fd fb 03 35 9a 95 36 8d 98 09 25 + +# m: +00 eb 7a 19 ac e9 e3 00 63 50 e3 29 50 4b 45 e2 +ca 82 31 0b 26 dc d8 7d 5c 68 f1 ee a8 f5 52 67 +c3 1b 2e 8b b4 25 1f 84 d7 e0 b2 c0 46 26 f5 af +f9 3e dc fb 25 c9 c2 b3 ff 8a e1 0e 83 9a 2d db +4c dc fe 4f f4 77 28 b4 a1 b7 c1 36 2b aa d2 9a +b4 8d 28 69 d5 02 41 21 43 58 11 59 1b e3 92 f9 +82 fb 3e 87 d0 95 ae b4 04 48 db 97 2f 3a c1 4f +7b c2 75 19 52 81 ce 32 d2 f1 b7 6d 4d 35 3e 2d + +# The intermediate values in the remaining +# decryption process are the same as during +# RSAES-OAEP encryption of M. + +# ============================================= + +# ======================== +# DER Encoding of RSA Keys +# ======================== + +# ------------ +# RSAPublicKey +# ------------ +30 81 87 +# modulus + 02 81 81 + 00 bb f8 2f 09 06 82 ce + 9c 23 38 ac 2b 9d a8 71 + f7 36 8d 07 ee d4 10 43 + a4 40 d6 b6 f0 74 54 f5 + 1f b8 df ba af 03 5c 02 + ab 61 ea 48 ce eb 6f cd + 48 76 ed 52 0d 60 e1 ec + 46 19 71 9d 8a 5b 8b 80 + 7f af b8 e0 a3 df c7 37 + 72 3e e6 b4 b7 d9 3a 25 + 84 ee 6a 64 9d 06 09 53 + 74 88 34 b2 45 45 98 39 + 4e e0 aa b1 2d 7b 61 a5 + 1f 52 7a 9a 41 f6 c1 68 + 7f e2 53 72 98 ca 2a 8f + 59 46 f8 e5 fd 09 1d bd + cb +# publicExponent + 02 01 + 11 + +# ------------- +# RSAPrivateKey +# ------------- +30 82 02 5b +# version + 02 01 + 00 +# modulus + 02 81 81 + 00 bb f8 2f 09 06 82 ce + 9c 23 38 ac 2b 9d a8 71 + f7 36 8d 07 ee d4 10 43 + a4 40 d6 b6 f0 74 54 f5 + 1f b8 df ba af 03 5c 02 + ab 61 ea 48 ce eb 6f cd + 48 76 ed 52 0d 60 e1 ec + 46 19 71 9d 8a 5b 8b 80 + 7f af b8 e0 a3 df c7 37 + 72 3e e6 b4 b7 d9 3a 25 + 84 ee 6a 64 9d 06 09 53 + 74 88 34 b2 45 45 98 39 + 4e e0 aa b1 2d 7b 61 a5 + 1f 52 7a 9a 41 f6 c1 68 + 7f e2 53 72 98 ca 2a 8f + 59 46 f8 e5 fd 09 1d bd + cb +# publicExponent + 02 01 + 11 +# privateExponent + 02 81 81 + 00 a5 da fc 53 41 fa f2 + 89 c4 b9 88 db 30 c1 cd + f8 3f 31 25 1e 06 68 b4 + 27 84 81 38 01 57 96 41 + b2 94 10 b3 c7 99 8d 6b + c4 65 74 5e 5c 39 26 69 + d6 87 0d a2 c0 82 a9 39 + e3 7f dc b8 2e c9 3e da + c9 7f f3 ad 59 50 ac cf + bc 11 1c 76 f1 a9 52 94 + 44 e5 6a af 68 c5 6c 09 + 2c d3 8d c3 be f5 d2 0a + 93 99 26 ed 4f 74 a1 3e + dd fb e1 a1 ce cc 48 94 + af 94 28 c2 b7 b8 88 3f + e4 46 3a 4b c8 5b 1c b3 + c1 +# prime1 + 02 41 + 00 ee cf ae 81 b1 b9 b3 + c9 08 81 0b 10 a1 b5 60 + 01 99 eb 9f 44 ae f4 fd + a4 93 b8 1a 9e 3d 84 f6 + 32 12 4e f0 23 6e 5d 1e + 3b 7e 28 fa e7 aa 04 0a + 2d 5b 25 21 76 45 9d 1f + 39 75 41 ba 2a 58 fb 65 + 99 +# prime2 + 02 41 + 00 c9 7f b1 f0 27 f4 53 + f6 34 12 33 ea aa d1 d9 + 35 3f 6c 42 d0 88 66 b1 + d0 5a 0f 20 35 02 8b 9d + 86 98 40 b4 16 66 b4 2e + 92 ea 0d a3 b4 32 04 b5 + cf ce 33 52 52 4d 04 16 + a5 a4 41 e7 00 af 46 15 + 03 +# exponent1 + 02 40 + 54 49 4c a6 3e ba 03 37 + e4 e2 40 23 fc d6 9a 5a + eb 07 dd dc 01 83 a4 d0 + ac 9b 54 b0 51 f2 b1 3e + d9 49 09 75 ea b7 74 14 + ff 59 c1 f7 69 2e 9a 2e + 20 2b 38 fc 91 0a 47 41 + 74 ad c9 3c 1f 67 c9 81 +# exponent2 + 02 40 + 47 1e 02 90 ff 0a f0 75 + 03 51 b7 f8 78 86 4c a9 + 61 ad bd 3a 8a 7e 99 1c + 5c 05 56 a9 4c 31 46 a7 + f9 80 3f 8f 6f 8a e3 42 + e9 31 fd 8a e4 7a 22 0d + 1b 99 a4 95 84 98 07 fe + 39 f9 24 5a 98 36 da 3d +# coefficient + 02 41 + 00 b0 6c 4f da bb 63 01 + 19 8d 26 5b db ae 94 23 + b3 80 f2 71 f7 34 53 88 + 50 93 07 7f cd 39 e2 11 + 9f c9 86 32 15 4f 58 83 + b1 67 a9 67 bf 40 2b 4e + 9e 2e 0f 96 56 e6 98 ea + 36 66 ed fb 25 79 80 39 + f7 + +# ------------------------ +# PrivateKeyInfo (PKCS #8) +# ------------------------ +30 82 02 75 +# version + 02 01 + 00 +# privateKeyAlgorithmIdentifier + 30 0d + 06 09 + 2a 86 48 86 f7 0d 01 01 01 +# parameters + 05 00 +# privateKey = RSAPrivateKey encoding + 04 82 02 5f +# DER encoding of RSAPrivateKey structure + 30 82 02 5b ... 79 80 39 f7 + +# ============================================= diff --git a/deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.c b/deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.c new file mode 100644 index 0000000..dcbdbb0 --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.c @@ -0,0 +1,1418 @@ +/* Generated from file: oaep-vect.txt + * with md5 hash: 9c79a5465c35222512ed3e7ac1ad3190 + */ + + +typedef struct rsaKey { + int n_l; + unsigned char n[256]; + int e_l; + unsigned char e[256]; + int d_l; + unsigned char d[256]; + int p_l; + unsigned char p[256]; + int q_l; + unsigned char q[256]; + int dP_l; + unsigned char dP[256]; + int dQ_l; + unsigned char dQ[256]; + int qInv_l; + unsigned char qInv[256]; +} rsaKey_t; + +typedef struct rsaData { + const char* name; + int o1_l; + unsigned char o1[256]; + int o2_l; + unsigned char o2[256]; + int o3_l; + unsigned char o3[256]; +} rsaData_t; + +typedef struct testcase { + const char* name; + rsaKey_t rsa; +#ifdef LTC_TEST_EXT + rsaData_t data[6]; +#else + rsaData_t data[1]; +#endif /* LTC_TEST_EXT */ +} testcase_t; + +testcase_t testcases_oaep[] = + { +{ + "Example 1: A 1024-bit RSA Key Pair", +{ + /* RSA modulus n */ + 128, + { 0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8, 0x60, 0xf1, 0x46, 0xc4, 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55, 0x98, 0xc8, 0xae, 0x48, 0x11, 0xa1, 0xe0, 0xab, 0xc4, 0xc7, 0xe0, 0xb0, 0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc, 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85, 0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42, 0xc6, 0xc6, 0x30, 0xf5, 0x33, 0xc8, 0xcc, 0x72, 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b, 0xf2, 0x58, 0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97, 0xc0, 0x10, 0x7d, 0x55, 0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14, 0x8e, 0xf7, 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66, 0x7b, 0xb3, 0xd4, 0x24, 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf, 0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f, 0x16, 0xfb } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x53, 0x33, 0x9c, 0xfd, 0xb7, 0x9f, 0xc8, 0x46, 0x6a, 0x65, 0x5c, 0x73, 0x16, 0xac, 0xa8, 0x5c, 0x55, 0xfd, 0x8f, 0x6d, 0xd8, 0x98, 0xfd, 0xaf, 0x11, 0x95, 0x17, 0xef, 0x4f, 0x52, 0xe8, 0xfd, 0x8e, 0x25, 0x8d, 0xf9, 0x3f, 0xee, 0x18, 0x0f, 0xa0, 0xe4, 0xab, 0x29, 0x69, 0x3c, 0xd8, 0x3b, 0x15, 0x2a, 0x55, 0x3d, 0x4a, 0xc4, 0xd1, 0x81, 0x2b, 0x8b, 0x9f, 0xa5, 0xaf, 0x0e, 0x7f, 0x55, 0xfe, 0x73, 0x04, 0xdf, 0x41, 0x57, 0x09, 0x26, 0xf3, 0x31, 0x1f, 0x15, 0xc4, 0xd6, 0x5a, 0x73, 0x2c, 0x48, 0x31, 0x16, 0xee, 0x3d, 0x3d, 0x2d, 0x0a, 0xf3, 0x54, 0x9a, 0xd9, 0xbf, 0x7c, 0xbf, 0xb7, 0x8a, 0xd8, 0x84, 0xf8, 0x4d, 0x5b, 0xeb, 0x04, 0x72, 0x4d, 0xc7, 0x36, 0x9b, 0x31, 0xde, 0xf3, 0x7d, 0x0c, 0xf5, 0x39, 0xe9, 0xcf, 0xcd, 0xd3, 0xde, 0x65, 0x37, 0x29, 0xea, 0xd5, 0xd1 } +, + /* Prime p */ + 64, + { 0xd3, 0x27, 0x37, 0xe7, 0x26, 0x7f, 0xfe, 0x13, 0x41, 0xb2, 0xd5, 0xc0, 0xd1, 0x50, 0xa8, 0x1b, 0x58, 0x6f, 0xb3, 0x13, 0x2b, 0xed, 0x2f, 0x8d, 0x52, 0x62, 0x86, 0x4a, 0x9c, 0xb9, 0xf3, 0x0a, 0xf3, 0x8b, 0xe4, 0x48, 0x59, 0x8d, 0x41, 0x3a, 0x17, 0x2e, 0xfb, 0x80, 0x2c, 0x21, 0xac, 0xf1, 0xc1, 0x1c, 0x52, 0x0c, 0x2f, 0x26, 0xa4, 0x71, 0xdc, 0xad, 0x21, 0x2e, 0xac, 0x7c, 0xa3, 0x9d } +, + /* Prime q */ + 64, + { 0xcc, 0x88, 0x53, 0xd1, 0xd5, 0x4d, 0xa6, 0x30, 0xfa, 0xc0, 0x04, 0xf4, 0x71, 0xf2, 0x81, 0xc7, 0xb8, 0x98, 0x2d, 0x82, 0x24, 0xa4, 0x90, 0xed, 0xbe, 0xb3, 0x3d, 0x3e, 0x3d, 0x5c, 0xc9, 0x3c, 0x47, 0x65, 0x70, 0x3d, 0x1d, 0xd7, 0x91, 0x64, 0x2f, 0x1f, 0x11, 0x6a, 0x0d, 0xd8, 0x52, 0xbe, 0x24, 0x19, 0xb2, 0xaf, 0x72, 0xbf, 0xe9, 0xa0, 0x30, 0xe8, 0x60, 0xb0, 0x28, 0x8b, 0x5d, 0x77 } +, + /* p's CRT exponent dP */ + 64, + { 0x0e, 0x12, 0xbf, 0x17, 0x18, 0xe9, 0xce, 0xf5, 0x59, 0x9b, 0xa1, 0xc3, 0x88, 0x2f, 0xe8, 0x04, 0x6a, 0x90, 0x87, 0x4e, 0xef, 0xce, 0x8f, 0x2c, 0xcc, 0x20, 0xe4, 0xf2, 0x74, 0x1f, 0xb0, 0xa3, 0x3a, 0x38, 0x48, 0xae, 0xc9, 0xc9, 0x30, 0x5f, 0xbe, 0xcb, 0xd2, 0xd7, 0x68, 0x19, 0x96, 0x7d, 0x46, 0x71, 0xac, 0xc6, 0x43, 0x1e, 0x40, 0x37, 0x96, 0x8d, 0xb3, 0x78, 0x78, 0xe6, 0x95, 0xc1 } +, + /* q's CRT exponent dQ */ + 64, + { 0x95, 0x29, 0x7b, 0x0f, 0x95, 0xa2, 0xfa, 0x67, 0xd0, 0x07, 0x07, 0xd6, 0x09, 0xdf, 0xd4, 0xfc, 0x05, 0xc8, 0x9d, 0xaf, 0xc2, 0xef, 0x6d, 0x6e, 0xa5, 0x5b, 0xec, 0x77, 0x1e, 0xa3, 0x33, 0x73, 0x4d, 0x92, 0x51, 0xe7, 0x90, 0x82, 0xec, 0xda, 0x86, 0x6e, 0xfe, 0xf1, 0x3c, 0x45, 0x9e, 0x1a, 0x63, 0x13, 0x86, 0xb7, 0xe3, 0x54, 0xc8, 0x99, 0xf5, 0xf1, 0x12, 0xca, 0x85, 0xd7, 0x15, 0x83 } +, + /* CRT coefficient qInv */ + 64, + { 0x4f, 0x45, 0x6c, 0x50, 0x24, 0x93, 0xbd, 0xc0, 0xed, 0x2a, 0xb7, 0x56, 0xa3, 0xa6, 0xed, 0x4d, 0x67, 0x35, 0x2a, 0x69, 0x7d, 0x42, 0x16, 0xe9, 0x32, 0x12, 0xb1, 0x27, 0xa6, 0x3d, 0x54, 0x11, 0xce, 0x6f, 0xa9, 0x8d, 0x5d, 0xbe, 0xfd, 0x73, 0x26, 0x3e, 0x37, 0x28, 0x14, 0x27, 0x43, 0x81, 0x81, 0x66, 0xed, 0x7d, 0xd6, 0x36, 0x87, 0xdd, 0x2a, 0x8c, 0xa1, 0xd2, 0xf4, 0xfb, 0xd8, 0xe1 } + +} +, +{{ + "RSAES-OAEP Encryption Example 1.1", + /* Message to be encrypted */ + 28, + { 0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda, 0x9e, 0xf9, 0x53, 0x23, 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, 0x4a, 0xfe, 0xfe, 0x34 } +, + /* Seed */ + 20, + { 0x18, 0xb7, 0x76, 0xea, 0x21, 0x06, 0x9d, 0x69, 0x77, 0x6a, 0x33, 0xe9, 0x6b, 0xad, 0x48, 0xe1, 0xdd, 0xa0, 0xa5, 0xef } +, + /* Encryption */ + 128, + { 0x35, 0x4f, 0xe6, 0x7b, 0x4a, 0x12, 0x6d, 0x5d, 0x35, 0xfe, 0x36, 0xc7, 0x77, 0x79, 0x1a, 0x3f, 0x7b, 0xa1, 0x3d, 0xef, 0x48, 0x4e, 0x2d, 0x39, 0x08, 0xaf, 0xf7, 0x22, 0xfa, 0xd4, 0x68, 0xfb, 0x21, 0x69, 0x6d, 0xe9, 0x5d, 0x0b, 0xe9, 0x11, 0xc2, 0xd3, 0x17, 0x4f, 0x8a, 0xfc, 0xc2, 0x01, 0x03, 0x5f, 0x7b, 0x6d, 0x8e, 0x69, 0x40, 0x2d, 0xe5, 0x45, 0x16, 0x18, 0xc2, 0x1a, 0x53, 0x5f, 0xa9, 0xd7, 0xbf, 0xc5, 0xb8, 0xdd, 0x9f, 0xc2, 0x43, 0xf8, 0xcf, 0x92, 0x7d, 0xb3, 0x13, 0x22, 0xd6, 0xe8, 0x81, 0xea, 0xa9, 0x1a, 0x99, 0x61, 0x70, 0xe6, 0x57, 0xa0, 0x5a, 0x26, 0x64, 0x26, 0xd9, 0x8c, 0x88, 0x00, 0x3f, 0x84, 0x77, 0xc1, 0x22, 0x70, 0x94, 0xa0, 0xd9, 0xfa, 0x1e, 0x8c, 0x40, 0x24, 0x30, 0x9c, 0xe1, 0xec, 0xcc, 0xb5, 0x21, 0x00, 0x35, 0xd4, 0x7a, 0xc7, 0x2e, 0x8a } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 1.2", + /* Message to be encrypted */ + 28, + { 0x75, 0x0c, 0x40, 0x47, 0xf5, 0x47, 0xe8, 0xe4, 0x14, 0x11, 0x85, 0x65, 0x23, 0x29, 0x8a, 0xc9, 0xba, 0xe2, 0x45, 0xef, 0xaf, 0x13, 0x97, 0xfb, 0xe5, 0x6f, 0x9d, 0xd5 } +, + /* Seed */ + 20, + { 0x0c, 0xc7, 0x42, 0xce, 0x4a, 0x9b, 0x7f, 0x32, 0xf9, 0x51, 0xbc, 0xb2, 0x51, 0xef, 0xd9, 0x25, 0xfe, 0x4f, 0xe3, 0x5f } +, + /* Encryption */ + 128, + { 0x64, 0x0d, 0xb1, 0xac, 0xc5, 0x8e, 0x05, 0x68, 0xfe, 0x54, 0x07, 0xe5, 0xf9, 0xb7, 0x01, 0xdf, 0xf8, 0xc3, 0xc9, 0x1e, 0x71, 0x6c, 0x53, 0x6f, 0xc7, 0xfc, 0xec, 0x6c, 0xb5, 0xb7, 0x1c, 0x11, 0x65, 0x98, 0x8d, 0x4a, 0x27, 0x9e, 0x15, 0x77, 0xd7, 0x30, 0xfc, 0x7a, 0x29, 0x93, 0x2e, 0x3f, 0x00, 0xc8, 0x15, 0x15, 0x23, 0x6d, 0x8d, 0x8e, 0x31, 0x01, 0x7a, 0x7a, 0x09, 0xdf, 0x43, 0x52, 0xd9, 0x04, 0xcd, 0xeb, 0x79, 0xaa, 0x58, 0x3a, 0xdc, 0xc3, 0x1e, 0xa6, 0x98, 0xa4, 0xc0, 0x52, 0x83, 0xda, 0xba, 0x90, 0x89, 0xbe, 0x54, 0x91, 0xf6, 0x7c, 0x1a, 0x4e, 0xe4, 0x8d, 0xc7, 0x4b, 0xbb, 0xe6, 0x64, 0x3a, 0xef, 0x84, 0x66, 0x79, 0xb4, 0xcb, 0x39, 0x5a, 0x35, 0x2d, 0x5e, 0xd1, 0x15, 0x91, 0x2d, 0xf6, 0x96, 0xff, 0xe0, 0x70, 0x29, 0x32, 0x94, 0x6d, 0x71, 0x49, 0x2b, 0x44 } + +} +, +{ + "RSAES-OAEP Encryption Example 1.3", + /* Message to be encrypted */ + 55, + { 0xd9, 0x4a, 0xe0, 0x83, 0x2e, 0x64, 0x45, 0xce, 0x42, 0x33, 0x1c, 0xb0, 0x6d, 0x53, 0x1a, 0x82, 0xb1, 0xdb, 0x4b, 0xaa, 0xd3, 0x0f, 0x74, 0x6d, 0xc9, 0x16, 0xdf, 0x24, 0xd4, 0xe3, 0xc2, 0x45, 0x1f, 0xff, 0x59, 0xa6, 0x42, 0x3e, 0xb0, 0xe1, 0xd0, 0x2d, 0x4f, 0xe6, 0x46, 0xcf, 0x69, 0x9d, 0xfd, 0x81, 0x8c, 0x6e, 0x97, 0xb0, 0x51 } +, + /* Seed */ + 20, + { 0x25, 0x14, 0xdf, 0x46, 0x95, 0x75, 0x5a, 0x67, 0xb2, 0x88, 0xea, 0xf4, 0x90, 0x5c, 0x36, 0xee, 0xc6, 0x6f, 0xd2, 0xfd } +, + /* Encryption */ + 128, + { 0x42, 0x37, 0x36, 0xed, 0x03, 0x5f, 0x60, 0x26, 0xaf, 0x27, 0x6c, 0x35, 0xc0, 0xb3, 0x74, 0x1b, 0x36, 0x5e, 0x5f, 0x76, 0xca, 0x09, 0x1b, 0x4e, 0x8c, 0x29, 0xe2, 0xf0, 0xbe, 0xfe, 0xe6, 0x03, 0x59, 0x5a, 0xa8, 0x32, 0x2d, 0x60, 0x2d, 0x2e, 0x62, 0x5e, 0x95, 0xeb, 0x81, 0xb2, 0xf1, 0xc9, 0x72, 0x4e, 0x82, 0x2e, 0xca, 0x76, 0xdb, 0x86, 0x18, 0xcf, 0x09, 0xc5, 0x34, 0x35, 0x03, 0xa4, 0x36, 0x08, 0x35, 0xb5, 0x90, 0x3b, 0xc6, 0x37, 0xe3, 0x87, 0x9f, 0xb0, 0x5e, 0x0e, 0xf3, 0x26, 0x85, 0xd5, 0xae, 0xc5, 0x06, 0x7c, 0xd7, 0xcc, 0x96, 0xfe, 0x4b, 0x26, 0x70, 0xb6, 0xea, 0xc3, 0x06, 0x6b, 0x1f, 0xcf, 0x56, 0x86, 0xb6, 0x85, 0x89, 0xaa, 0xfb, 0x7d, 0x62, 0x9b, 0x02, 0xd8, 0xf8, 0x62, 0x5c, 0xa3, 0x83, 0x36, 0x24, 0xd4, 0x80, 0x0f, 0xb0, 0x81, 0xb1, 0xcf, 0x94, 0xeb } + +} +, +{ + "RSAES-OAEP Encryption Example 1.4", + /* Message to be encrypted */ + 26, + { 0x52, 0xe6, 0x50, 0xd9, 0x8e, 0x7f, 0x2a, 0x04, 0x8b, 0x4f, 0x86, 0x85, 0x21, 0x53, 0xb9, 0x7e, 0x01, 0xdd, 0x31, 0x6f, 0x34, 0x6a, 0x19, 0xf6, 0x7a, 0x85 } +, + /* Seed */ + 20, + { 0xc4, 0x43, 0x5a, 0x3e, 0x1a, 0x18, 0xa6, 0x8b, 0x68, 0x20, 0x43, 0x62, 0x90, 0xa3, 0x7c, 0xef, 0xb8, 0x5d, 0xb3, 0xfb } +, + /* Encryption */ + 128, + { 0x45, 0xea, 0xd4, 0xca, 0x55, 0x1e, 0x66, 0x2c, 0x98, 0x00, 0xf1, 0xac, 0xa8, 0x28, 0x3b, 0x05, 0x25, 0xe6, 0xab, 0xae, 0x30, 0xbe, 0x4b, 0x4a, 0xba, 0x76, 0x2f, 0xa4, 0x0f, 0xd3, 0xd3, 0x8e, 0x22, 0xab, 0xef, 0xc6, 0x97, 0x94, 0xf6, 0xeb, 0xbb, 0xc0, 0x5d, 0xdb, 0xb1, 0x12, 0x16, 0x24, 0x7d, 0x2f, 0x41, 0x2f, 0xd0, 0xfb, 0xa8, 0x7c, 0x6e, 0x3a, 0xcd, 0x88, 0x88, 0x13, 0x64, 0x6f, 0xd0, 0xe4, 0x8e, 0x78, 0x52, 0x04, 0xf9, 0xc3, 0xf7, 0x3d, 0x6d, 0x82, 0x39, 0x56, 0x27, 0x22, 0xdd, 0xdd, 0x87, 0x71, 0xfe, 0xc4, 0x8b, 0x83, 0xa3, 0x1e, 0xe6, 0xf5, 0x92, 0xc4, 0xcf, 0xd4, 0xbc, 0x88, 0x17, 0x4f, 0x3b, 0x13, 0xa1, 0x12, 0xaa, 0xe3, 0xb9, 0xf7, 0xb8, 0x0e, 0x0f, 0xc6, 0xf7, 0x25, 0x5b, 0xa8, 0x80, 0xdc, 0x7d, 0x80, 0x21, 0xe2, 0x2a, 0xd6, 0xa8, 0x5f, 0x07, 0x55 } + +} +, +{ + "RSAES-OAEP Encryption Example 1.5", + /* Message to be encrypted */ + 20, + { 0x8d, 0xa8, 0x9f, 0xd9, 0xe5, 0xf9, 0x74, 0xa2, 0x9f, 0xef, 0xfb, 0x46, 0x2b, 0x49, 0x18, 0x0f, 0x6c, 0xf9, 0xe8, 0x02 } +, + /* Seed */ + 20, + { 0xb3, 0x18, 0xc4, 0x2d, 0xf3, 0xbe, 0x0f, 0x83, 0xfe, 0xa8, 0x23, 0xf5, 0xa7, 0xb4, 0x7e, 0xd5, 0xe4, 0x25, 0xa3, 0xb5 } +, + /* Encryption */ + 128, + { 0x36, 0xf6, 0xe3, 0x4d, 0x94, 0xa8, 0xd3, 0x4d, 0xaa, 0xcb, 0xa3, 0x3a, 0x21, 0x39, 0xd0, 0x0a, 0xd8, 0x5a, 0x93, 0x45, 0xa8, 0x60, 0x51, 0xe7, 0x30, 0x71, 0x62, 0x00, 0x56, 0xb9, 0x20, 0xe2, 0x19, 0x00, 0x58, 0x55, 0xa2, 0x13, 0xa0, 0xf2, 0x38, 0x97, 0xcd, 0xcd, 0x73, 0x1b, 0x45, 0x25, 0x7c, 0x77, 0x7f, 0xe9, 0x08, 0x20, 0x2b, 0xef, 0xdd, 0x0b, 0x58, 0x38, 0x6b, 0x12, 0x44, 0xea, 0x0c, 0xf5, 0x39, 0xa0, 0x5d, 0x5d, 0x10, 0x32, 0x9d, 0xa4, 0x4e, 0x13, 0x03, 0x0f, 0xd7, 0x60, 0xdc, 0xd6, 0x44, 0xcf, 0xef, 0x20, 0x94, 0xd1, 0x91, 0x0d, 0x3f, 0x43, 0x3e, 0x1c, 0x7c, 0x6d, 0xd1, 0x8b, 0xc1, 0xf2, 0xdf, 0x7f, 0x64, 0x3d, 0x66, 0x2f, 0xb9, 0xdd, 0x37, 0xea, 0xd9, 0x05, 0x91, 0x90, 0xf4, 0xfa, 0x66, 0xca, 0x39, 0xe8, 0x69, 0xc4, 0xeb, 0x44, 0x9c, 0xbd, 0xc4, 0x39 } + +} +, +{ + "RSAES-OAEP Encryption Example 1.6", + /* Message to be encrypted */ + 7, + { 0x26, 0x52, 0x10, 0x50, 0x84, 0x42, 0x71 } +, + /* Seed */ + 20, + { 0xe4, 0xec, 0x09, 0x82, 0xc2, 0x33, 0x6f, 0x3a, 0x67, 0x7f, 0x6a, 0x35, 0x61, 0x74, 0xeb, 0x0c, 0xe8, 0x87, 0xab, 0xc2 } +, + /* Encryption */ + 128, + { 0x42, 0xce, 0xe2, 0x61, 0x7b, 0x1e, 0xce, 0xa4, 0xdb, 0x3f, 0x48, 0x29, 0x38, 0x6f, 0xbd, 0x61, 0xda, 0xfb, 0xf0, 0x38, 0xe1, 0x80, 0xd8, 0x37, 0xc9, 0x63, 0x66, 0xdf, 0x24, 0xc0, 0x97, 0xb4, 0xab, 0x0f, 0xac, 0x6b, 0xdf, 0x59, 0x0d, 0x82, 0x1c, 0x9f, 0x10, 0x64, 0x2e, 0x68, 0x1a, 0xd0, 0x5b, 0x8d, 0x78, 0xb3, 0x78, 0xc0, 0xf4, 0x6c, 0xe2, 0xfa, 0xd6, 0x3f, 0x74, 0xe0, 0xad, 0x3d, 0xf0, 0x6b, 0x07, 0x5d, 0x7e, 0xb5, 0xf5, 0x63, 0x6f, 0x8d, 0x40, 0x3b, 0x90, 0x59, 0xca, 0x76, 0x1b, 0x5c, 0x62, 0xbb, 0x52, 0xaa, 0x45, 0x00, 0x2e, 0xa7, 0x0b, 0xaa, 0xce, 0x08, 0xde, 0xd2, 0x43, 0xb9, 0xd8, 0xcb, 0xd6, 0x2a, 0x68, 0xad, 0xe2, 0x65, 0x83, 0x2b, 0x56, 0x56, 0x4e, 0x43, 0xa6, 0xfa, 0x42, 0xed, 0x19, 0x9a, 0x09, 0x97, 0x69, 0x74, 0x2d, 0xf1, 0x53, 0x9e, 0x82, 0x55 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 2: A 1025-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x01, 0x94, 0x7c, 0x7f, 0xce, 0x90, 0x42, 0x5f, 0x47, 0x27, 0x9e, 0x70, 0x85, 0x1f, 0x25, 0xd5, 0xe6, 0x23, 0x16, 0xfe, 0x8a, 0x1d, 0xf1, 0x93, 0x71, 0xe3, 0xe6, 0x28, 0xe2, 0x60, 0x54, 0x3e, 0x49, 0x01, 0xef, 0x60, 0x81, 0xf6, 0x8c, 0x0b, 0x81, 0x41, 0x19, 0x0d, 0x2a, 0xe8, 0xda, 0xba, 0x7d, 0x12, 0x50, 0xec, 0x6d, 0xb6, 0x36, 0xe9, 0x44, 0xec, 0x37, 0x22, 0x87, 0x7c, 0x7c, 0x1d, 0x0a, 0x67, 0xf1, 0x4b, 0x16, 0x94, 0xc5, 0xf0, 0x37, 0x94, 0x51, 0xa4, 0x3e, 0x49, 0xa3, 0x2d, 0xde, 0x83, 0x67, 0x0b, 0x73, 0xda, 0x91, 0xa1, 0xc9, 0x9b, 0xc2, 0x3b, 0x43, 0x6a, 0x60, 0x05, 0x5c, 0x61, 0x0f, 0x0b, 0xaf, 0x99, 0xc1, 0xa0, 0x79, 0x56, 0x5b, 0x95, 0xa3, 0xf1, 0x52, 0x66, 0x32, 0xd1, 0xd4, 0xda, 0x60, 0xf2, 0x0e, 0xda, 0x25, 0xe6, 0x53, 0xc4, 0xf0, 0x02, 0x76, 0x6f, 0x45 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x08, 0x23, 0xf2, 0x0f, 0xad, 0xb5, 0xda, 0x89, 0x08, 0x8a, 0x9d, 0x00, 0x89, 0x3e, 0x21, 0xfa, 0x4a, 0x1b, 0x11, 0xfb, 0xc9, 0x3c, 0x64, 0xa3, 0xbe, 0x0b, 0xaa, 0xea, 0x97, 0xfb, 0x3b, 0x93, 0xc3, 0xff, 0x71, 0x37, 0x04, 0xc1, 0x9c, 0x96, 0x3c, 0x1d, 0x10, 0x7a, 0xae, 0x99, 0x05, 0x47, 0x39, 0xf7, 0x9e, 0x02, 0xe1, 0x86, 0xde, 0x86, 0xf8, 0x7a, 0x6d, 0xde, 0xfe, 0xa6, 0xd8, 0xcc, 0xd1, 0xd3, 0xc8, 0x1a, 0x47, 0xbf, 0xa7, 0x25, 0x5b, 0xe2, 0x06, 0x01, 0xa4, 0xa4, 0xb2, 0xf0, 0x8a, 0x16, 0x7b, 0x5e, 0x27, 0x9d, 0x71, 0x5b, 0x1b, 0x45, 0x5b, 0xdd, 0x7e, 0xab, 0x24, 0x59, 0x41, 0xd9, 0x76, 0x8b, 0x9a, 0xce, 0xfb, 0x3c, 0xcd, 0xa5, 0x95, 0x2d, 0xa3, 0xce, 0xe7, 0x25, 0x25, 0xb4, 0x50, 0x16, 0x63, 0xa8, 0xee, 0x15, 0xc9, 0xe9, 0x92, 0xd9, 0x24, 0x62, 0xfe, 0x39 } +, + /* Prime p */ + 65, + { 0x01, 0x59, 0xdb, 0xde, 0x04, 0xa3, 0x3e, 0xf0, 0x6f, 0xb6, 0x08, 0xb8, 0x0b, 0x19, 0x0f, 0x4d, 0x3e, 0x22, 0xbc, 0xc1, 0x3a, 0xc8, 0xe4, 0xa0, 0x81, 0x03, 0x3a, 0xbf, 0xa4, 0x16, 0xed, 0xb0, 0xb3, 0x38, 0xaa, 0x08, 0xb5, 0x73, 0x09, 0xea, 0x5a, 0x52, 0x40, 0xe7, 0xdc, 0x6e, 0x54, 0x37, 0x8c, 0x69, 0x41, 0x4c, 0x31, 0xd9, 0x7d, 0xdb, 0x1f, 0x40, 0x6d, 0xb3, 0x76, 0x9c, 0xc4, 0x1a, 0x43 } +, + /* Prime q */ + 65, + { 0x01, 0x2b, 0x65, 0x2f, 0x30, 0x40, 0x3b, 0x38, 0xb4, 0x09, 0x95, 0xfd, 0x6f, 0xf4, 0x1a, 0x1a, 0xcc, 0x8a, 0xda, 0x70, 0x37, 0x32, 0x36, 0xb7, 0x20, 0x2d, 0x39, 0xb2, 0xee, 0x30, 0xcf, 0xb4, 0x6d, 0xb0, 0x95, 0x11, 0xf6, 0xf3, 0x07, 0xcc, 0x61, 0xcc, 0x21, 0x60, 0x6c, 0x18, 0xa7, 0x5b, 0x8a, 0x62, 0xf8, 0x22, 0xdf, 0x03, 0x1b, 0xa0, 0xdf, 0x0d, 0xaf, 0xd5, 0x50, 0x6f, 0x56, 0x8b, 0xd7 } +, + /* p's CRT exponent dP */ + 64, + { 0x43, 0x6e, 0xf5, 0x08, 0xde, 0x73, 0x65, 0x19, 0xc2, 0xda, 0x4c, 0x58, 0x0d, 0x98, 0xc8, 0x2c, 0xb7, 0x45, 0x2a, 0x3f, 0xb5, 0xef, 0xad, 0xc3, 0xb9, 0xc7, 0x78, 0x9a, 0x1b, 0xc6, 0x58, 0x4f, 0x79, 0x5a, 0xdd, 0xbb, 0xd3, 0x24, 0x39, 0xc7, 0x46, 0x86, 0x55, 0x2e, 0xcb, 0x6c, 0x2c, 0x30, 0x7a, 0x4d, 0x3a, 0xf7, 0xf5, 0x39, 0xee, 0xc1, 0x57, 0x24, 0x8c, 0x7b, 0x31, 0xf1, 0xa2, 0x55 } +, + /* q's CRT exponent dQ */ + 65, + { 0x01, 0x2b, 0x15, 0xa8, 0x9f, 0x3d, 0xfb, 0x2b, 0x39, 0x07, 0x3e, 0x73, 0xf0, 0x2b, 0xdd, 0x0c, 0x1a, 0x7b, 0x37, 0x9d, 0xd4, 0x35, 0xf0, 0x5c, 0xdd, 0xe2, 0xef, 0xf9, 0xe4, 0x62, 0x94, 0x8b, 0x7c, 0xec, 0x62, 0xee, 0x90, 0x50, 0xd5, 0xe0, 0x81, 0x6e, 0x07, 0x85, 0xa8, 0x56, 0xb4, 0x91, 0x08, 0xdc, 0xb7, 0x5f, 0x36, 0x83, 0x87, 0x4d, 0x1c, 0xa6, 0x32, 0x9a, 0x19, 0x01, 0x30, 0x66, 0xff } +, + /* CRT coefficient qInv */ + 64, + { 0x02, 0x70, 0xdb, 0x17, 0xd5, 0x91, 0x4b, 0x01, 0x8d, 0x76, 0x11, 0x8b, 0x24, 0x38, 0x9a, 0x73, 0x50, 0xec, 0x83, 0x6b, 0x00, 0x63, 0xa2, 0x17, 0x21, 0x23, 0x6f, 0xd8, 0xed, 0xb6, 0xd8, 0x9b, 0x51, 0xe7, 0xee, 0xb8, 0x7b, 0x61, 0x1b, 0x71, 0x32, 0xcb, 0x7e, 0xa7, 0x35, 0x6c, 0x23, 0x15, 0x1c, 0x1e, 0x77, 0x51, 0x50, 0x7c, 0x78, 0x6d, 0x9e, 0xe1, 0x79, 0x41, 0x70, 0xa8, 0xc8, 0xe8 } + +} +, +{{ + "RSAES-OAEP Encryption Example 2.1", + /* Message to be encrypted */ + 27, + { 0x8f, 0xf0, 0x0c, 0xaa, 0x60, 0x5c, 0x70, 0x28, 0x30, 0x63, 0x4d, 0x9a, 0x6c, 0x3d, 0x42, 0xc6, 0x52, 0xb5, 0x8c, 0xf1, 0xd9, 0x2f, 0xec, 0x57, 0x0b, 0xee, 0xe7 } +, + /* Seed */ + 20, + { 0x8c, 0x40, 0x7b, 0x5e, 0xc2, 0x89, 0x9e, 0x50, 0x99, 0xc5, 0x3e, 0x8c, 0xe7, 0x93, 0xbf, 0x94, 0xe7, 0x1b, 0x17, 0x82 } +, + /* Encryption */ + 129, + { 0x01, 0x81, 0xaf, 0x89, 0x22, 0xb9, 0xfc, 0xb4, 0xd7, 0x9d, 0x92, 0xeb, 0xe1, 0x98, 0x15, 0x99, 0x2f, 0xc0, 0xc1, 0x43, 0x9d, 0x8b, 0xcd, 0x49, 0x13, 0x98, 0xa0, 0xf4, 0xad, 0x3a, 0x32, 0x9a, 0x5b, 0xd9, 0x38, 0x55, 0x60, 0xdb, 0x53, 0x26, 0x83, 0xc8, 0xb7, 0xda, 0x04, 0xe4, 0xb1, 0x2a, 0xed, 0x6a, 0xac, 0xdf, 0x47, 0x1c, 0x34, 0xc9, 0xcd, 0xa8, 0x91, 0xad, 0xdc, 0xc2, 0xdf, 0x34, 0x56, 0x65, 0x3a, 0xa6, 0x38, 0x2e, 0x9a, 0xe5, 0x9b, 0x54, 0x45, 0x52, 0x57, 0xeb, 0x09, 0x9d, 0x56, 0x2b, 0xbe, 0x10, 0x45, 0x3f, 0x2b, 0x6d, 0x13, 0xc5, 0x9c, 0x02, 0xe1, 0x0f, 0x1f, 0x8a, 0xbb, 0x5d, 0xa0, 0xd0, 0x57, 0x09, 0x32, 0xda, 0xcf, 0x2d, 0x09, 0x01, 0xdb, 0x72, 0x9d, 0x0f, 0xef, 0xcc, 0x05, 0x4e, 0x70, 0x96, 0x8e, 0xa5, 0x40, 0xc8, 0x1b, 0x04, 0xbc, 0xae, 0xfe, 0x72, 0x0e } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 2.2", + /* Message to be encrypted */ + 1, + { 0x2d } +, + /* Seed */ + 20, + { 0xb6, 0x00, 0xcf, 0x3c, 0x2e, 0x50, 0x6d, 0x7f, 0x16, 0x77, 0x8c, 0x91, 0x0d, 0x3a, 0x8b, 0x00, 0x3e, 0xee, 0x61, 0xd5 } +, + /* Encryption */ + 129, + { 0x01, 0x87, 0x59, 0xff, 0x1d, 0xf6, 0x3b, 0x27, 0x92, 0x41, 0x05, 0x62, 0x31, 0x44, 0x16, 0xa8, 0xae, 0xaf, 0x2a, 0xc6, 0x34, 0xb4, 0x6f, 0x94, 0x0a, 0xb8, 0x2d, 0x64, 0xdb, 0xf1, 0x65, 0xee, 0xe3, 0x30, 0x11, 0xda, 0x74, 0x9d, 0x4b, 0xab, 0x6e, 0x2f, 0xcd, 0x18, 0x12, 0x9c, 0x9e, 0x49, 0x27, 0x7d, 0x84, 0x53, 0x11, 0x2b, 0x42, 0x9a, 0x22, 0x2a, 0x84, 0x71, 0xb0, 0x70, 0x99, 0x39, 0x98, 0xe7, 0x58, 0x86, 0x1c, 0x4d, 0x3f, 0x6d, 0x74, 0x9d, 0x91, 0xc4, 0x29, 0x0d, 0x33, 0x2c, 0x7a, 0x4a, 0xb3, 0xf7, 0xea, 0x35, 0xff, 0x3a, 0x07, 0xd4, 0x97, 0xc9, 0x55, 0xff, 0x0f, 0xfc, 0x95, 0x00, 0x6b, 0x62, 0xc6, 0xd2, 0x96, 0x81, 0x0d, 0x9b, 0xfa, 0xb0, 0x24, 0x19, 0x6c, 0x79, 0x34, 0x01, 0x2c, 0x2d, 0xf9, 0x78, 0xef, 0x29, 0x9a, 0xba, 0x23, 0x99, 0x40, 0xcb, 0xa1, 0x02, 0x45 } + +} +, +{ + "RSAES-OAEP Encryption Example 2.3", + /* Message to be encrypted */ + 26, + { 0x74, 0xfc, 0x88, 0xc5, 0x1b, 0xc9, 0x0f, 0x77, 0xaf, 0x9d, 0x5e, 0x9a, 0x4a, 0x70, 0x13, 0x3d, 0x4b, 0x4e, 0x0b, 0x34, 0xda, 0x3c, 0x37, 0xc7, 0xef, 0x8e } +, + /* Seed */ + 20, + { 0xa7, 0x37, 0x68, 0xae, 0xea, 0xa9, 0x1f, 0x9d, 0x8c, 0x1e, 0xd6, 0xf9, 0xd2, 0xb6, 0x34, 0x67, 0xf0, 0x7c, 0xca, 0xe3 } +, + /* Encryption */ + 129, + { 0x01, 0x88, 0x02, 0xba, 0xb0, 0x4c, 0x60, 0x32, 0x5e, 0x81, 0xc4, 0x96, 0x23, 0x11, 0xf2, 0xbe, 0x7c, 0x2a, 0xdc, 0xe9, 0x30, 0x41, 0xa0, 0x07, 0x19, 0xc8, 0x8f, 0x95, 0x75, 0x75, 0xf2, 0xc7, 0x9f, 0x1b, 0x7b, 0xc8, 0xce, 0xd1, 0x15, 0xc7, 0x06, 0xb3, 0x11, 0xc0, 0x8a, 0x2d, 0x98, 0x6c, 0xa3, 0xb6, 0xa9, 0x33, 0x6b, 0x14, 0x7c, 0x29, 0xc6, 0xf2, 0x29, 0x40, 0x9d, 0xde, 0xc6, 0x51, 0xbd, 0x1f, 0xdd, 0x5a, 0x0b, 0x7f, 0x61, 0x0c, 0x99, 0x37, 0xfd, 0xb4, 0xa3, 0xa7, 0x62, 0x36, 0x4b, 0x8b, 0x32, 0x06, 0xb4, 0xea, 0x48, 0x5f, 0xd0, 0x98, 0xd0, 0x8f, 0x63, 0xd4, 0xaa, 0x8b, 0xb2, 0x69, 0x7d, 0x02, 0x7b, 0x75, 0x0c, 0x32, 0xd7, 0xf7, 0x4e, 0xaf, 0x51, 0x80, 0xd2, 0xe9, 0xb6, 0x6b, 0x17, 0xcb, 0x2f, 0xa5, 0x55, 0x23, 0xbc, 0x28, 0x0d, 0xa1, 0x0d, 0x14, 0xbe, 0x20, 0x53 } + +} +, +{ + "RSAES-OAEP Encryption Example 2.4", + /* Message to be encrypted */ + 53, + { 0xa7, 0xeb, 0x2a, 0x50, 0x36, 0x93, 0x1d, 0x27, 0xd4, 0xe8, 0x91, 0x32, 0x6d, 0x99, 0x69, 0x2f, 0xfa, 0xdd, 0xa9, 0xbf, 0x7e, 0xfd, 0x3e, 0x34, 0xe6, 0x22, 0xc4, 0xad, 0xc0, 0x85, 0xf7, 0x21, 0xdf, 0xe8, 0x85, 0x07, 0x2c, 0x78, 0xa2, 0x03, 0xb1, 0x51, 0x73, 0x9b, 0xe5, 0x40, 0xfa, 0x8c, 0x15, 0x3a, 0x10, 0xf0, 0x0a } +, + /* Seed */ + 20, + { 0x9a, 0x7b, 0x3b, 0x0e, 0x70, 0x8b, 0xd9, 0x6f, 0x81, 0x90, 0xec, 0xab, 0x4f, 0xb9, 0xb2, 0xb3, 0x80, 0x5a, 0x81, 0x56 } +, + /* Encryption */ + 129, + { 0x00, 0xa4, 0x57, 0x8c, 0xbc, 0x17, 0x63, 0x18, 0xa6, 0x38, 0xfb, 0xa7, 0xd0, 0x1d, 0xf1, 0x57, 0x46, 0xaf, 0x44, 0xd4, 0xf6, 0xcd, 0x96, 0xd7, 0xe7, 0xc4, 0x95, 0xcb, 0xf4, 0x25, 0xb0, 0x9c, 0x64, 0x9d, 0x32, 0xbf, 0x88, 0x6d, 0xa4, 0x8f, 0xba, 0xf9, 0x89, 0xa2, 0x11, 0x71, 0x87, 0xca, 0xfb, 0x1f, 0xb5, 0x80, 0x31, 0x76, 0x90, 0xe3, 0xcc, 0xd4, 0x46, 0x92, 0x0b, 0x7a, 0xf8, 0x2b, 0x31, 0xdb, 0x58, 0x04, 0xd8, 0x7d, 0x01, 0x51, 0x4a, 0xcb, 0xfa, 0x91, 0x56, 0xe7, 0x82, 0xf8, 0x67, 0xf6, 0xbe, 0xd9, 0x44, 0x9e, 0x0e, 0x9a, 0x2c, 0x09, 0xbc, 0xec, 0xc6, 0xaa, 0x08, 0x76, 0x36, 0x96, 0x5e, 0x34, 0xb3, 0xec, 0x76, 0x6f, 0x2f, 0xe2, 0xe4, 0x30, 0x18, 0xa2, 0xfd, 0xde, 0xb1, 0x40, 0x61, 0x6a, 0x0e, 0x9d, 0x82, 0xe5, 0x33, 0x10, 0x24, 0xee, 0x06, 0x52, 0xfc, 0x76, 0x41 } + +} +, +{ + "RSAES-OAEP Encryption Example 2.5", + /* Message to be encrypted */ + 19, + { 0x2e, 0xf2, 0xb0, 0x66, 0xf8, 0x54, 0xc3, 0x3f, 0x3b, 0xdc, 0xbb, 0x59, 0x94, 0xa4, 0x35, 0xe7, 0x3d, 0x6c, 0x6c } +, + /* Seed */ + 20, + { 0xeb, 0x3c, 0xeb, 0xbc, 0x4a, 0xdc, 0x16, 0xbb, 0x48, 0xe8, 0x8c, 0x8a, 0xec, 0x0e, 0x34, 0xaf, 0x7f, 0x42, 0x7f, 0xd3 } +, + /* Encryption */ + 129, + { 0x00, 0xeb, 0xc5, 0xf5, 0xfd, 0xa7, 0x7c, 0xfd, 0xad, 0x3c, 0x83, 0x64, 0x1a, 0x90, 0x25, 0xe7, 0x7d, 0x72, 0xd8, 0xa6, 0xfb, 0x33, 0xa8, 0x10, 0xf5, 0x95, 0x0f, 0x8d, 0x74, 0xc7, 0x3e, 0x8d, 0x93, 0x1e, 0x86, 0x34, 0xd8, 0x6a, 0xb1, 0x24, 0x62, 0x56, 0xae, 0x07, 0xb6, 0x00, 0x5b, 0x71, 0xb7, 0xf2, 0xfb, 0x98, 0x35, 0x12, 0x18, 0x33, 0x1c, 0xe6, 0x9b, 0x8f, 0xfb, 0xdc, 0x9d, 0xa0, 0x8b, 0xbc, 0x9c, 0x70, 0x4f, 0x87, 0x6d, 0xeb, 0x9d, 0xf9, 0xfc, 0x2e, 0xc0, 0x65, 0xca, 0xd8, 0x7f, 0x90, 0x90, 0xb0, 0x7a, 0xcc, 0x17, 0xaa, 0x7f, 0x99, 0x7b, 0x27, 0xac, 0xa4, 0x88, 0x06, 0xe8, 0x97, 0xf7, 0x71, 0xd9, 0x51, 0x41, 0xfe, 0x45, 0x26, 0xd8, 0xa5, 0x30, 0x1b, 0x67, 0x86, 0x27, 0xef, 0xab, 0x70, 0x7f, 0xd4, 0x0f, 0xbe, 0xbd, 0x6e, 0x79, 0x2a, 0x25, 0x61, 0x3e, 0x7a, 0xec } + +} +, +{ + "RSAES-OAEP Encryption Example 2.6", + /* Message to be encrypted */ + 22, + { 0x8a, 0x7f, 0xb3, 0x44, 0xc8, 0xb6, 0xcb, 0x2c, 0xf2, 0xef, 0x1f, 0x64, 0x3f, 0x9a, 0x32, 0x18, 0xf6, 0xe1, 0x9b, 0xba, 0x89, 0xc0 } +, + /* Seed */ + 20, + { 0x4c, 0x45, 0xcf, 0x4d, 0x57, 0xc9, 0x8e, 0x3d, 0x6d, 0x20, 0x95, 0xad, 0xc5, 0x1c, 0x48, 0x9e, 0xb5, 0x0d, 0xff, 0x84 } +, + /* Encryption */ + 129, + { 0x01, 0x08, 0x39, 0xec, 0x20, 0xc2, 0x7b, 0x90, 0x52, 0xe5, 0x5b, 0xef, 0xb9, 0xb7, 0x7e, 0x6f, 0xc2, 0x6e, 0x90, 0x75, 0xd7, 0xa5, 0x43, 0x78, 0xc6, 0x46, 0xab, 0xdf, 0x51, 0xe4, 0x45, 0xbd, 0x57, 0x15, 0xde, 0x81, 0x78, 0x9f, 0x56, 0xf1, 0x80, 0x3d, 0x91, 0x70, 0x76, 0x4a, 0x9e, 0x93, 0xcb, 0x78, 0x79, 0x86, 0x94, 0x02, 0x3e, 0xe7, 0x39, 0x3c, 0xe0, 0x4b, 0xc5, 0xd8, 0xf8, 0xc5, 0xa5, 0x2c, 0x17, 0x1d, 0x43, 0x83, 0x7e, 0x3a, 0xca, 0x62, 0xf6, 0x09, 0xeb, 0x0a, 0xa5, 0xff, 0xb0, 0x96, 0x0e, 0xf0, 0x41, 0x98, 0xdd, 0x75, 0x4f, 0x57, 0xf7, 0xfb, 0xe6, 0xab, 0xf7, 0x65, 0xcf, 0x11, 0x8b, 0x4c, 0xa4, 0x43, 0xb2, 0x3b, 0x5a, 0xab, 0x26, 0x6f, 0x95, 0x23, 0x26, 0xac, 0x45, 0x81, 0x10, 0x06, 0x44, 0x32, 0x5f, 0x8b, 0x72, 0x1a, 0xcd, 0x5d, 0x04, 0xff, 0x14, 0xef, 0x3a } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 3: A 1026-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x02, 0xb5, 0x8f, 0xec, 0x03, 0x9a, 0x86, 0x07, 0x00, 0xa4, 0xd7, 0xb6, 0x46, 0x2f, 0x93, 0xe6, 0xcd, 0xd4, 0x91, 0x16, 0x1d, 0xdd, 0x74, 0xf4, 0xe8, 0x10, 0xb4, 0x0e, 0x3c, 0x16, 0x52, 0x00, 0x6a, 0x5c, 0x27, 0x7b, 0x27, 0x74, 0xc1, 0x13, 0x05, 0xa4, 0xcb, 0xab, 0x5a, 0x78, 0xef, 0xa5, 0x7e, 0x17, 0xa8, 0x6d, 0xf7, 0xa3, 0xfa, 0x36, 0xfc, 0x4b, 0x1d, 0x22, 0x49, 0xf2, 0x2e, 0xc7, 0xc2, 0xdd, 0x6a, 0x46, 0x32, 0x32, 0xac, 0xce, 0xa9, 0x06, 0xd6, 0x6e, 0xbe, 0x80, 0xb5, 0x70, 0x4b, 0x10, 0x72, 0x9d, 0xa6, 0xf8, 0x33, 0x23, 0x4a, 0xbb, 0x5e, 0xfd, 0xd4, 0xa2, 0x92, 0xcb, 0xfa, 0xd3, 0x3b, 0x4d, 0x33, 0xfa, 0x7a, 0x14, 0xb8, 0xc3, 0x97, 0xb5, 0x6e, 0x3a, 0xcd, 0x21, 0x20, 0x34, 0x28, 0xb7, 0x7c, 0xdf, 0xa3, 0x3a, 0x6d, 0xa7, 0x06, 0xb3, 0xd8, 0xb0, 0xfc, 0x43, 0xe9 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x15, 0xb4, 0x8a, 0x5b, 0x56, 0x83, 0xa9, 0x46, 0x70, 0xe2, 0x3b, 0x57, 0x18, 0xf8, 0x14, 0xfa, 0x0e, 0x13, 0xf8, 0x50, 0x38, 0xf5, 0x07, 0x11, 0x18, 0x2c, 0xba, 0x61, 0x51, 0x05, 0x81, 0xf3, 0xd2, 0x2c, 0x7e, 0x23, 0x2e, 0xf9, 0x37, 0xe2, 0x2e, 0x55, 0x1d, 0x68, 0xb8, 0x6e, 0x2f, 0x8c, 0xb1, 0xaa, 0xd8, 0xbe, 0x2e, 0x48, 0x8f, 0x5d, 0xf7, 0xef, 0xd2, 0x79, 0xe3, 0xf5, 0x68, 0xd4, 0xea, 0xf3, 0x6f, 0x80, 0xcf, 0x71, 0x41, 0xac, 0xe6, 0x0f, 0xcc, 0x91, 0x13, 0xfb, 0x6c, 0x4a, 0x84, 0x1f, 0xd5, 0x0b, 0xbc, 0x7c, 0x51, 0x2f, 0xfc, 0xbe, 0xff, 0x21, 0x48, 0x7a, 0xa8, 0x11, 0xeb, 0x3c, 0xa8, 0xc6, 0x20, 0x05, 0x34, 0x6a, 0x86, 0xde, 0x86, 0xbf, 0xa1, 0xd8, 0xa9, 0x48, 0xfd, 0x3f, 0x34, 0x8c, 0x22, 0xea, 0xad, 0xf3, 0x33, 0xc3, 0xce, 0x6c, 0xe1, 0x32, 0x08, 0xfd } +, + /* Prime p */ + 65, + { 0x01, 0xbf, 0x01, 0xd2, 0x16, 0xd7, 0x35, 0x95, 0xcf, 0x02, 0x70, 0xc2, 0xbe, 0xb7, 0x8d, 0x40, 0xa0, 0xd8, 0x44, 0x7d, 0x31, 0xda, 0x91, 0x9a, 0x98, 0x3f, 0x7e, 0xea, 0x78, 0x1b, 0x77, 0xd8, 0x5f, 0xe3, 0x71, 0xb3, 0xe9, 0x37, 0x3e, 0x7b, 0x69, 0x21, 0x7d, 0x31, 0x50, 0xa0, 0x2d, 0x89, 0x58, 0xde, 0x7f, 0xad, 0x9d, 0x55, 0x51, 0x60, 0x95, 0x8b, 0x44, 0x54, 0x12, 0x7e, 0x0e, 0x7e, 0xaf } +, + /* Prime q */ + 65, + { 0x01, 0x8d, 0x33, 0x99, 0x65, 0x81, 0x66, 0xdb, 0x38, 0x29, 0x81, 0x6d, 0x7b, 0x29, 0x54, 0x16, 0x75, 0x9e, 0x9c, 0x91, 0x98, 0x7f, 0x5b, 0x2d, 0x8a, 0xec, 0xd6, 0x3b, 0x04, 0xb4, 0x8b, 0xd7, 0xb2, 0xfc, 0xf2, 0x29, 0xbb, 0x7f, 0x8a, 0x6d, 0xc8, 0x8b, 0xa1, 0x3d, 0xd2, 0xe3, 0x9a, 0xd5, 0x5b, 0x6d, 0x1a, 0x06, 0x16, 0x07, 0x08, 0xf9, 0x70, 0x0b, 0xe8, 0x0b, 0x8f, 0xd3, 0x74, 0x4c, 0xe7 } +, + /* p's CRT exponent dP */ + 64, + { 0x06, 0xc0, 0xa2, 0x49, 0xd2, 0x0a, 0x6f, 0x2e, 0xe7, 0x5c, 0x88, 0xb4, 0x94, 0xd5, 0x3f, 0x6a, 0xae, 0x99, 0xaa, 0x42, 0x7c, 0x88, 0xc2, 0x8b, 0x16, 0x3a, 0x76, 0x94, 0x45, 0xe5, 0xf3, 0x90, 0xcf, 0x40, 0xc2, 0x74, 0xfd, 0x6e, 0xa6, 0x32, 0x9a, 0x5c, 0xe7, 0xc7, 0xce, 0x03, 0xa2, 0x15, 0x83, 0x96, 0xee, 0x2a, 0x78, 0x45, 0x78, 0x6e, 0x09, 0xe2, 0x88, 0x5a, 0x97, 0x28, 0xe4, 0xe5 } +, + /* q's CRT exponent dQ */ + 64, + { 0xd1, 0xd2, 0x7c, 0x29, 0xfe, 0xdd, 0x92, 0xd8, 0x6c, 0x34, 0x8e, 0xdd, 0x0c, 0xcb, 0xfa, 0xc1, 0x4f, 0x74, 0x6e, 0x05, 0x1c, 0xe1, 0xd1, 0x81, 0x1d, 0xf3, 0x5d, 0x61, 0xf2, 0xee, 0x1c, 0x97, 0xd4, 0xbf, 0x28, 0x04, 0x80, 0x2f, 0x64, 0x27, 0x18, 0x7b, 0xa8, 0xe9, 0x0a, 0x8a, 0xf4, 0x42, 0x43, 0xb4, 0x07, 0x9b, 0x03, 0x44, 0x5e, 0x60, 0x2e, 0x29, 0xfa, 0x51, 0x93, 0xe6, 0x4f, 0xe9 } +, + /* CRT coefficient qInv */ + 64, + { 0x8c, 0xb2, 0xf7, 0x56, 0xbd, 0x89, 0x41, 0xb1, 0xd3, 0xb7, 0x70, 0xe5, 0xad, 0x31, 0xee, 0x37, 0x3b, 0x28, 0xac, 0xda, 0x69, 0xff, 0x9b, 0x6f, 0x40, 0xfe, 0x57, 0x8b, 0x9f, 0x1a, 0xfb, 0x85, 0x83, 0x6f, 0x96, 0x27, 0xd3, 0x7a, 0xcf, 0xf7, 0x3c, 0x27, 0x79, 0xe6, 0x34, 0xbb, 0x26, 0x01, 0x1c, 0x2c, 0x8f, 0x7f, 0x33, 0x61, 0xae, 0x2a, 0x9e, 0xa6, 0x5e, 0xd6, 0x89, 0xe3, 0x63, 0x9a } + +} +, +{{ + "RSAES-OAEP Encryption Example 3.1", + /* Message to be encrypted */ + 8, + { 0x08, 0x78, 0x20, 0xb5, 0x69, 0xe8, 0xfa, 0x8d } +, + /* Seed */ + 20, + { 0x8c, 0xed, 0x6b, 0x19, 0x62, 0x90, 0x80, 0x57, 0x90, 0xe9, 0x09, 0x07, 0x40, 0x15, 0xe6, 0xa2, 0x0b, 0x0c, 0x48, 0x94 } +, + /* Encryption */ + 129, + { 0x02, 0x6a, 0x04, 0x85, 0xd9, 0x6a, 0xeb, 0xd9, 0x6b, 0x43, 0x82, 0x08, 0x50, 0x99, 0xb9, 0x62, 0xe6, 0xa2, 0xbd, 0xec, 0x3d, 0x90, 0xc8, 0xdb, 0x62, 0x5e, 0x14, 0x37, 0x2d, 0xe8, 0x5e, 0x2d, 0x5b, 0x7b, 0xaa, 0xb6, 0x5c, 0x8f, 0xaf, 0x91, 0xbb, 0x55, 0x04, 0xfb, 0x49, 0x5a, 0xfc, 0xe5, 0xc9, 0x88, 0xb3, 0xf6, 0xa5, 0x2e, 0x20, 0xe1, 0xd6, 0xcb, 0xd3, 0x56, 0x6c, 0x5c, 0xd1, 0xf2, 0xb8, 0x31, 0x8b, 0xb5, 0x42, 0xcc, 0x0e, 0xa2, 0x5c, 0x4a, 0xab, 0x99, 0x32, 0xaf, 0xa2, 0x07, 0x60, 0xea, 0xdd, 0xec, 0x78, 0x43, 0x96, 0xa0, 0x7e, 0xa0, 0xef, 0x24, 0xd4, 0xe6, 0xf4, 0xd3, 0x7e, 0x50, 0x52, 0xa7, 0xa3, 0x1e, 0x14, 0x6a, 0xa4, 0x80, 0xa1, 0x11, 0xbb, 0xe9, 0x26, 0x40, 0x13, 0x07, 0xe0, 0x0f, 0x41, 0x00, 0x33, 0x84, 0x2b, 0x6d, 0x82, 0xfe, 0x5c, 0xe4, 0xdf, 0xae, 0x80 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 3.2", + /* Message to be encrypted */ + 28, + { 0x46, 0x53, 0xac, 0xaf, 0x17, 0x19, 0x60, 0xb0, 0x1f, 0x52, 0xa7, 0xbe, 0x63, 0xa3, 0xab, 0x21, 0xdc, 0x36, 0x8e, 0xc4, 0x3b, 0x50, 0xd8, 0x2e, 0xc3, 0x78, 0x1e, 0x04 } +, + /* Seed */ + 20, + { 0xb4, 0x29, 0x1d, 0x65, 0x67, 0x55, 0x08, 0x48, 0xcc, 0x15, 0x69, 0x67, 0xc8, 0x09, 0xba, 0xab, 0x6c, 0xa5, 0x07, 0xf0 } +, + /* Encryption */ + 129, + { 0x02, 0x4d, 0xb8, 0x9c, 0x78, 0x02, 0x98, 0x9b, 0xe0, 0x78, 0x38, 0x47, 0x86, 0x30, 0x84, 0x94, 0x1b, 0xf2, 0x09, 0xd7, 0x61, 0x98, 0x7e, 0x38, 0xf9, 0x7c, 0xb5, 0xf6, 0xf1, 0xbc, 0x88, 0xda, 0x72, 0xa5, 0x0b, 0x73, 0xeb, 0xaf, 0x11, 0xc8, 0x79, 0xc4, 0xf9, 0x5d, 0xf3, 0x7b, 0x85, 0x0b, 0x8f, 0x65, 0xd7, 0x62, 0x2e, 0x25, 0xb1, 0xb8, 0x89, 0xe8, 0x0f, 0xe8, 0x0b, 0xac, 0xa2, 0x06, 0x9d, 0x6e, 0x0e, 0x1d, 0x82, 0x99, 0x53, 0xfc, 0x45, 0x90, 0x69, 0xde, 0x98, 0xea, 0x97, 0x98, 0xb4, 0x51, 0xe5, 0x57, 0xe9, 0x9a, 0xbf, 0x8f, 0xe3, 0xd9, 0xcc, 0xf9, 0x09, 0x6e, 0xbb, 0xf3, 0xe5, 0x25, 0x5d, 0x3b, 0x4e, 0x1c, 0x6d, 0x2e, 0xca, 0xdf, 0x06, 0x7a, 0x35, 0x9e, 0xea, 0x86, 0x40, 0x5a, 0xcd, 0x47, 0xd5, 0xe1, 0x65, 0x51, 0x7c, 0xca, 0xfd, 0x47, 0xd6, 0xdb, 0xee, 0x4b, 0xf5 } + +} +, +{ + "RSAES-OAEP Encryption Example 3.3", + /* Message to be encrypted */ + 9, + { 0xd9, 0x4c, 0xd0, 0xe0, 0x8f, 0xa4, 0x04, 0xed, 0x89 } +, + /* Seed */ + 20, + { 0xce, 0x89, 0x28, 0xf6, 0x05, 0x95, 0x58, 0x25, 0x40, 0x08, 0xba, 0xdd, 0x97, 0x94, 0xfa, 0xdc, 0xd2, 0xfd, 0x1f, 0x65 } +, + /* Encryption */ + 129, + { 0x02, 0x39, 0xbc, 0xe6, 0x81, 0x03, 0x24, 0x41, 0x52, 0x88, 0x77, 0xd6, 0xd1, 0xc8, 0xbb, 0x28, 0xaa, 0x3b, 0xc9, 0x7f, 0x1d, 0xf5, 0x84, 0x56, 0x36, 0x18, 0x99, 0x57, 0x97, 0x68, 0x38, 0x44, 0xca, 0x86, 0x66, 0x47, 0x32, 0xf4, 0xbe, 0xd7, 0xa0, 0xaa, 0xb0, 0x83, 0xaa, 0xab, 0xfb, 0x72, 0x38, 0xf5, 0x82, 0xe3, 0x09, 0x58, 0xc2, 0x02, 0x4e, 0x44, 0xe5, 0x70, 0x43, 0xb9, 0x79, 0x50, 0xfd, 0x54, 0x3d, 0xa9, 0x77, 0xc9, 0x0c, 0xdd, 0xe5, 0x33, 0x7d, 0x61, 0x84, 0x42, 0xf9, 0x9e, 0x60, 0xd7, 0x78, 0x3a, 0xb5, 0x9c, 0xe6, 0xdd, 0x9d, 0x69, 0xc4, 0x7a, 0xd1, 0xe9, 0x62, 0xbe, 0xc2, 0x2d, 0x05, 0x89, 0x5c, 0xff, 0x8d, 0x3f, 0x64, 0xed, 0x52, 0x61, 0xd9, 0x2b, 0x26, 0x78, 0x51, 0x03, 0x93, 0x48, 0x49, 0x90, 0xba, 0x3f, 0x7f, 0x06, 0x81, 0x8a, 0xe6, 0xff, 0xce, 0x8a, 0x3a } + +} +, +{ + "RSAES-OAEP Encryption Example 3.4", + /* Message to be encrypted */ + 18, + { 0x6c, 0xc6, 0x41, 0xb6, 0xb6, 0x1e, 0x6f, 0x96, 0x39, 0x74, 0xda, 0xd2, 0x3a, 0x90, 0x13, 0x28, 0x4e, 0xf1 } +, + /* Seed */ + 20, + { 0x6e, 0x29, 0x79, 0xf5, 0x2d, 0x68, 0x14, 0xa5, 0x7d, 0x83, 0xb0, 0x90, 0x05, 0x48, 0x88, 0xf1, 0x19, 0xa5, 0xb9, 0xa3 } +, + /* Encryption */ + 129, + { 0x02, 0x99, 0x4c, 0x62, 0xaf, 0xd7, 0x6f, 0x49, 0x8b, 0xa1, 0xfd, 0x2c, 0xf6, 0x42, 0x85, 0x7f, 0xca, 0x81, 0xf4, 0x37, 0x3c, 0xb0, 0x8f, 0x1c, 0xba, 0xee, 0x6f, 0x02, 0x5c, 0x3b, 0x51, 0x2b, 0x42, 0xc3, 0xe8, 0x77, 0x91, 0x13, 0x47, 0x66, 0x48, 0x03, 0x9d, 0xbe, 0x04, 0x93, 0xf9, 0x24, 0x62, 0x92, 0xfa, 0xc2, 0x89, 0x50, 0x60, 0x0e, 0x7c, 0x0f, 0x32, 0xed, 0xf9, 0xc8, 0x1b, 0x9d, 0xec, 0x45, 0xc3, 0xbd, 0xe0, 0xcc, 0x8d, 0x88, 0x47, 0x59, 0x01, 0x69, 0x90, 0x7b, 0x7d, 0xc5, 0x99, 0x1c, 0xeb, 0x29, 0xbb, 0x07, 0x14, 0xd6, 0x13, 0xd9, 0x6d, 0xf0, 0xf1, 0x2e, 0xc5, 0xd8, 0xd3, 0x50, 0x7c, 0x8e, 0xe7, 0xae, 0x78, 0xdd, 0x83, 0xf2, 0x16, 0xfa, 0x61, 0xde, 0x10, 0x03, 0x63, 0xac, 0xa4, 0x8a, 0x7e, 0x91, 0x4a, 0xe9, 0xf4, 0x2d, 0xdf, 0xbe, 0x94, 0x3b, 0x09, 0xd9, 0xa0 } + +} +, +{ + "RSAES-OAEP Encryption Example 3.5", + /* Message to be encrypted */ + 46, + { 0xdf, 0x51, 0x51, 0x83, 0x2b, 0x61, 0xf4, 0xf2, 0x58, 0x91, 0xfb, 0x41, 0x72, 0xf3, 0x28, 0xd2, 0xed, 0xdf, 0x83, 0x71, 0xff, 0xcf, 0xdb, 0xe9, 0x97, 0x93, 0x92, 0x95, 0xf3, 0x0e, 0xca, 0x69, 0x18, 0x01, 0x7c, 0xfd, 0xa1, 0x15, 0x3b, 0xf7, 0xa6, 0xaf, 0x87, 0x59, 0x32, 0x23 } +, + /* Seed */ + 20, + { 0x2d, 0x76, 0x0b, 0xfe, 0x38, 0xc5, 0x9d, 0xe3, 0x4c, 0xdc, 0x8b, 0x8c, 0x78, 0xa3, 0x8e, 0x66, 0x28, 0x4a, 0x2d, 0x27 } +, + /* Encryption */ + 129, + { 0x01, 0x62, 0x04, 0x2f, 0xf6, 0x96, 0x95, 0x92, 0xa6, 0x16, 0x70, 0x31, 0x81, 0x1a, 0x23, 0x98, 0x34, 0xce, 0x63, 0x8a, 0xbf, 0x54, 0xfe, 0xc8, 0xb9, 0x94, 0x78, 0x12, 0x2a, 0xfe, 0x2e, 0xe6, 0x7f, 0x8c, 0x5b, 0x18, 0xb0, 0x33, 0x98, 0x05, 0xbf, 0xdb, 0xc5, 0xa4, 0xe6, 0x72, 0x0b, 0x37, 0xc5, 0x9c, 0xfb, 0xa9, 0x42, 0x46, 0x4c, 0x59, 0x7f, 0xf5, 0x32, 0xa1, 0x19, 0x82, 0x15, 0x45, 0xfd, 0x2e, 0x59, 0xb1, 0x14, 0xe6, 0x1d, 0xaf, 0x71, 0x82, 0x05, 0x29, 0xf5, 0x02, 0x9c, 0xf5, 0x24, 0x95, 0x43, 0x27, 0xc3, 0x4e, 0xc5, 0xe6, 0xf5, 0xba, 0x7e, 0xfc, 0xc4, 0xde, 0x94, 0x3a, 0xb8, 0xad, 0x4e, 0xd7, 0x87, 0xb1, 0x45, 0x43, 0x29, 0xf7, 0x0d, 0xb7, 0x98, 0xa3, 0xa8, 0xf4, 0xd9, 0x2f, 0x82, 0x74, 0xe2, 0xb2, 0x94, 0x8a, 0xde, 0x62, 0x7c, 0xe8, 0xee, 0x33, 0xe4, 0x3c, 0x60 } + +} +, +{ + "RSAES-OAEP Encryption Example 3.6", + /* Message to be encrypted */ + 56, + { 0x3c, 0x3b, 0xad, 0x89, 0x3c, 0x54, 0x4a, 0x6d, 0x52, 0x0a, 0xb0, 0x22, 0x31, 0x91, 0x88, 0xc8, 0xd5, 0x04, 0xb7, 0xa7, 0x88, 0xb8, 0x50, 0x90, 0x3b, 0x85, 0x97, 0x2e, 0xaa, 0x18, 0x55, 0x2e, 0x11, 0x34, 0xa7, 0xad, 0x60, 0x98, 0x82, 0x62, 0x54, 0xff, 0x7a, 0xb6, 0x72, 0xb3, 0xd8, 0xeb, 0x31, 0x58, 0xfa, 0xc6, 0xd4, 0xcb, 0xae, 0xf1 } +, + /* Seed */ + 20, + { 0xf1, 0x74, 0x77, 0x9c, 0x5f, 0xd3, 0xcf, 0xe0, 0x07, 0xba, 0xdc, 0xb7, 0xa3, 0x6c, 0x9b, 0x55, 0xbf, 0xcf, 0xbf, 0x0e } +, + /* Encryption */ + 129, + { 0x00, 0x11, 0x20, 0x51, 0xe7, 0x5d, 0x06, 0x49, 0x43, 0xbc, 0x44, 0x78, 0x07, 0x5e, 0x43, 0x48, 0x2f, 0xd5, 0x9c, 0xee, 0x06, 0x79, 0xde, 0x68, 0x93, 0xee, 0xc3, 0xa9, 0x43, 0xda, 0xa4, 0x90, 0xb9, 0x69, 0x1c, 0x93, 0xdf, 0xc0, 0x46, 0x4b, 0x66, 0x23, 0xb9, 0xf3, 0xdb, 0xd3, 0xe7, 0x00, 0x83, 0x26, 0x4f, 0x03, 0x4b, 0x37, 0x4f, 0x74, 0x16, 0x4e, 0x1a, 0x00, 0x76, 0x37, 0x25, 0xe5, 0x74, 0x74, 0x4b, 0xa0, 0xb9, 0xdb, 0x83, 0x43, 0x4f, 0x31, 0xdf, 0x96, 0xf6, 0xe2, 0xa2, 0x6f, 0x6d, 0x8e, 0xba, 0x34, 0x8b, 0xd4, 0x68, 0x6c, 0x22, 0x38, 0xac, 0x07, 0xc3, 0x7a, 0xac, 0x37, 0x85, 0xd1, 0xc7, 0xee, 0xa2, 0xf8, 0x19, 0xfd, 0x91, 0x49, 0x17, 0x98, 0xed, 0x8e, 0x9c, 0xef, 0x5e, 0x43, 0xb7, 0x81, 0xb0, 0xe0, 0x27, 0x6e, 0x37, 0xc4, 0x3f, 0xf9, 0x49, 0x2d, 0x00, 0x57, 0x30 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 4: A 1027-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x05, 0x12, 0x40, 0xb6, 0xcc, 0x00, 0x04, 0xfa, 0x48, 0xd0, 0x13, 0x46, 0x71, 0xc0, 0x78, 0xc7, 0xc8, 0xde, 0xc3, 0xb3, 0xe2, 0xf2, 0x5b, 0xc2, 0x56, 0x44, 0x67, 0x33, 0x9d, 0xb3, 0x88, 0x53, 0xd0, 0x6b, 0x85, 0xee, 0xa5, 0xb2, 0xde, 0x35, 0x3b, 0xff, 0x42, 0xac, 0x2e, 0x46, 0xbc, 0x97, 0xfa, 0xe6, 0xac, 0x96, 0x18, 0xda, 0x95, 0x37, 0xa5, 0xc8, 0xf5, 0x53, 0xc1, 0xe3, 0x57, 0x62, 0x59, 0x91, 0xd6, 0x10, 0x8d, 0xcd, 0x78, 0x85, 0xfb, 0x3a, 0x25, 0x41, 0x3f, 0x53, 0xef, 0xca, 0xd9, 0x48, 0xcb, 0x35, 0xcd, 0x9b, 0x9a, 0xe9, 0xc1, 0xc6, 0x76, 0x26, 0xd1, 0x13, 0xd5, 0x7d, 0xde, 0x4c, 0x5b, 0xea, 0x76, 0xbb, 0x5b, 0xb7, 0xde, 0x96, 0xc0, 0x0d, 0x07, 0x37, 0x2e, 0x96, 0x85, 0xa6, 0xd7, 0x5c, 0xf9, 0xd2, 0x39, 0xfa, 0x14, 0x8d, 0x70, 0x93, 0x1b, 0x5f, 0x3f, 0xb0, 0x39 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x04, 0x11, 0xff, 0xca, 0x3b, 0x7c, 0xa5, 0xe9, 0xe9, 0xbe, 0x7f, 0xe3, 0x8a, 0x85, 0x10, 0x5e, 0x35, 0x38, 0x96, 0xdb, 0x05, 0xc5, 0x79, 0x6a, 0xec, 0xd2, 0xa7, 0x25, 0x16, 0x1e, 0xb3, 0x65, 0x1c, 0x86, 0x29, 0xa9, 0xb8, 0x62, 0xb9, 0x04, 0xd7, 0xb0, 0xc7, 0xb3, 0x7f, 0x8c, 0xb5, 0xa1, 0xc2, 0xb5, 0x40, 0x01, 0x01, 0x8a, 0x00, 0xa1, 0xeb, 0x2c, 0xaf, 0xe4, 0xee, 0x4e, 0x94, 0x92, 0xc3, 0x48, 0xbc, 0x2b, 0xed, 0xab, 0x4b, 0x9e, 0xbb, 0xf0, 0x64, 0xe8, 0xef, 0xf3, 0x22, 0xb9, 0x00, 0x9f, 0x8e, 0xec, 0x65, 0x39, 0x05, 0xf4, 0x0d, 0xf8, 0x8a, 0x3c, 0xdc, 0x49, 0xd4, 0x56, 0x7f, 0x75, 0x62, 0x7d, 0x41, 0xac, 0xa6, 0x24, 0x12, 0x9b, 0x46, 0xa0, 0xb7, 0xc6, 0x98, 0xe5, 0xe6, 0x5f, 0x2b, 0x7b, 0xa1, 0x02, 0xc7, 0x49, 0xa1, 0x01, 0x35, 0xb6, 0x54, 0x0d, 0x04, 0x01 } +, + /* Prime p */ + 65, + { 0x02, 0x74, 0x58, 0xc1, 0x9e, 0xc1, 0x63, 0x69, 0x19, 0xe7, 0x36, 0xc9, 0xaf, 0x25, 0xd6, 0x09, 0xa5, 0x1b, 0x8f, 0x56, 0x1d, 0x19, 0xc6, 0xbf, 0x69, 0x43, 0xdd, 0x1e, 0xe1, 0xab, 0x8a, 0x4a, 0x3f, 0x23, 0x21, 0x00, 0xbd, 0x40, 0xb8, 0x8d, 0xec, 0xc6, 0xba, 0x23, 0x55, 0x48, 0xb6, 0xef, 0x79, 0x2a, 0x11, 0xc9, 0xde, 0x82, 0x3d, 0x0a, 0x79, 0x22, 0xc7, 0x09, 0x5b, 0x6e, 0xba, 0x57, 0x01 } +, + /* Prime q */ + 65, + { 0x02, 0x10, 0xee, 0x9b, 0x33, 0xab, 0x61, 0x71, 0x6e, 0x27, 0xd2, 0x51, 0xbd, 0x46, 0x5f, 0x4b, 0x35, 0xa1, 0xa2, 0x32, 0xe2, 0xda, 0x00, 0x90, 0x1c, 0x29, 0x4b, 0xf2, 0x23, 0x50, 0xce, 0x49, 0x0d, 0x09, 0x9f, 0x64, 0x2b, 0x53, 0x75, 0x61, 0x2d, 0xb6, 0x3b, 0xa1, 0xf2, 0x03, 0x86, 0x49, 0x2b, 0xf0, 0x4d, 0x34, 0xb3, 0xc2, 0x2b, 0xce, 0xb9, 0x09, 0xd1, 0x34, 0x41, 0xb5, 0x3b, 0x51, 0x39 } +, + /* p's CRT exponent dP */ + 64, + { 0x39, 0xfa, 0x02, 0x8b, 0x82, 0x6e, 0x88, 0xc1, 0x12, 0x1b, 0x75, 0x0a, 0x8b, 0x24, 0x2f, 0xa9, 0xa3, 0x5c, 0x5b, 0x66, 0xbd, 0xfd, 0x1f, 0xa6, 0x37, 0xd3, 0xcc, 0x48, 0xa8, 0x4a, 0x4f, 0x45, 0x7a, 0x19, 0x4e, 0x77, 0x27, 0xe4, 0x9f, 0x7b, 0xcc, 0x6e, 0x5a, 0x5a, 0x41, 0x26, 0x57, 0xfc, 0x47, 0x0c, 0x73, 0x22, 0xeb, 0xc3, 0x74, 0x16, 0xef, 0x45, 0x8c, 0x30, 0x7a, 0x8c, 0x09, 0x01 } +, + /* q's CRT exponent dQ */ + 65, + { 0x01, 0x5d, 0x99, 0xa8, 0x41, 0x95, 0x94, 0x39, 0x79, 0xfa, 0x9e, 0x1b, 0xe2, 0xc3, 0xc1, 0xb6, 0x9f, 0x43, 0x2f, 0x46, 0xfd, 0x03, 0xe4, 0x7d, 0x5b, 0xef, 0xbb, 0xbf, 0xd6, 0xb1, 0xd1, 0x37, 0x1d, 0x83, 0xef, 0xb3, 0x30, 0xa3, 0xe0, 0x20, 0x94, 0x2b, 0x2f, 0xed, 0x11, 0x5e, 0x5d, 0x02, 0xbe, 0x24, 0xfd, 0x92, 0xc9, 0x01, 0x9d, 0x1c, 0xec, 0xd6, 0xdd, 0x4c, 0xf1, 0xe5, 0x4c, 0xc8, 0x99 } +, + /* CRT coefficient qInv */ + 65, + { 0x01, 0xf0, 0xb7, 0x01, 0x51, 0x70, 0xb3, 0xf5, 0xe4, 0x22, 0x23, 0xba, 0x30, 0x30, 0x1c, 0x41, 0xa6, 0xd8, 0x7c, 0xbb, 0x70, 0xe3, 0x0c, 0xb7, 0xd3, 0xc6, 0x7d, 0x25, 0x47, 0x3d, 0xb1, 0xf6, 0xcb, 0xf0, 0x3e, 0x3f, 0x91, 0x26, 0xe3, 0xe9, 0x79, 0x68, 0x27, 0x9a, 0x86, 0x5b, 0x2c, 0x2b, 0x42, 0x65, 0x24, 0xcf, 0xc5, 0x2a, 0x68, 0x3d, 0x31, 0xed, 0x30, 0xeb, 0x98, 0x4b, 0xe4, 0x12, 0xba } + +} +, +{{ + "RSAES-OAEP Encryption Example 4.1", + /* Message to be encrypted */ + 56, + { 0x4a, 0x86, 0x60, 0x95, 0x34, 0xee, 0x43, 0x4a, 0x6c, 0xbc, 0xa3, 0xf7, 0xe9, 0x62, 0xe7, 0x6d, 0x45, 0x5e, 0x32, 0x64, 0xc1, 0x9f, 0x60, 0x5f, 0x6e, 0x5f, 0xf6, 0x13, 0x7c, 0x65, 0xc5, 0x6d, 0x7f, 0xb3, 0x44, 0xcd, 0x52, 0xbc, 0x93, 0x37, 0x4f, 0x3d, 0x16, 0x6c, 0x9f, 0x0c, 0x6f, 0x9c, 0x50, 0x6b, 0xad, 0x19, 0x33, 0x09, 0x72, 0xd2 } +, + /* Seed */ + 20, + { 0x1c, 0xac, 0x19, 0xce, 0x99, 0x3d, 0xef, 0x55, 0xf9, 0x82, 0x03, 0xf6, 0x85, 0x28, 0x96, 0xc9, 0x5c, 0xcc, 0xa1, 0xf3 } +, + /* Encryption */ + 129, + { 0x04, 0xcc, 0xe1, 0x96, 0x14, 0x84, 0x5e, 0x09, 0x41, 0x52, 0xa3, 0xfe, 0x18, 0xe5, 0x4e, 0x33, 0x30, 0xc4, 0x4e, 0x5e, 0xfb, 0xc6, 0x4a, 0xe1, 0x68, 0x86, 0xcb, 0x18, 0x69, 0x01, 0x4c, 0xc5, 0x78, 0x1b, 0x1f, 0x8f, 0x9e, 0x04, 0x53, 0x84, 0xd0, 0x11, 0x2a, 0x13, 0x5c, 0xa0, 0xd1, 0x2e, 0x9c, 0x88, 0xa8, 0xe4, 0x06, 0x34, 0x16, 0xde, 0xaa, 0xe3, 0x84, 0x4f, 0x60, 0xd6, 0xe9, 0x6f, 0xe1, 0x55, 0x14, 0x5f, 0x45, 0x25, 0xb9, 0xa3, 0x44, 0x31, 0xca, 0x37, 0x66, 0x18, 0x0f, 0x70, 0xe1, 0x5a, 0x5e, 0x5d, 0x8e, 0x8b, 0x1a, 0x51, 0x6f, 0xf8, 0x70, 0x60, 0x9f, 0x13, 0xf8, 0x96, 0x93, 0x5c, 0xed, 0x18, 0x82, 0x79, 0xa5, 0x8e, 0xd1, 0x3d, 0x07, 0x11, 0x42, 0x77, 0xd7, 0x5c, 0x65, 0x68, 0x60, 0x7e, 0x0a, 0xb0, 0x92, 0xfd, 0x80, 0x3a, 0x22, 0x3e, 0x4a, 0x8e, 0xe0, 0xb1, 0xa8 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 4.2", + /* Message to be encrypted */ + 64, + { 0xb0, 0xad, 0xc4, 0xf3, 0xfe, 0x11, 0xda, 0x59, 0xce, 0x99, 0x27, 0x73, 0xd9, 0x05, 0x99, 0x43, 0xc0, 0x30, 0x46, 0x49, 0x7e, 0xe9, 0xd9, 0xf9, 0xa0, 0x6d, 0xf1, 0x16, 0x6d, 0xb4, 0x6d, 0x98, 0xf5, 0x8d, 0x27, 0xec, 0x07, 0x4c, 0x02, 0xee, 0xe6, 0xcb, 0xe2, 0x44, 0x9c, 0x8b, 0x9f, 0xc5, 0x08, 0x0c, 0x5c, 0x3f, 0x44, 0x33, 0x09, 0x25, 0x12, 0xec, 0x46, 0xaa, 0x79, 0x37, 0x43, 0xc8 } +, + /* Seed */ + 20, + { 0xf5, 0x45, 0xd5, 0x89, 0x75, 0x85, 0xe3, 0xdb, 0x71, 0xaa, 0x0c, 0xb8, 0xda, 0x76, 0xc5, 0x1d, 0x03, 0x2a, 0xe9, 0x63 } +, + /* Encryption */ + 129, + { 0x00, 0x97, 0xb6, 0x98, 0xc6, 0x16, 0x56, 0x45, 0xb3, 0x03, 0x48, 0x6f, 0xbf, 0x5a, 0x2a, 0x44, 0x79, 0xc0, 0xee, 0x85, 0x88, 0x9b, 0x54, 0x1a, 0x6f, 0x0b, 0x85, 0x8d, 0x6b, 0x65, 0x97, 0xb1, 0x3b, 0x85, 0x4e, 0xb4, 0xf8, 0x39, 0xaf, 0x03, 0x39, 0x9a, 0x80, 0xd7, 0x9b, 0xda, 0x65, 0x78, 0xc8, 0x41, 0xf9, 0x0d, 0x64, 0x57, 0x15, 0xb2, 0x80, 0xd3, 0x71, 0x43, 0x99, 0x2d, 0xd1, 0x86, 0xc8, 0x0b, 0x94, 0x9b, 0x77, 0x5c, 0xae, 0x97, 0x37, 0x0e, 0x4e, 0xc9, 0x74, 0x43, 0x13, 0x6c, 0x6d, 0xa4, 0x84, 0xe9, 0x70, 0xff, 0xdb, 0x13, 0x23, 0xa2, 0x08, 0x47, 0x82, 0x1d, 0x3b, 0x18, 0x38, 0x1d, 0xe1, 0x3b, 0xb4, 0x9a, 0xae, 0xa6, 0x65, 0x30, 0xc4, 0xa4, 0xb8, 0x27, 0x1f, 0x3e, 0xae, 0x17, 0x2c, 0xd3, 0x66, 0xe0, 0x7e, 0x66, 0x36, 0xf1, 0x01, 0x9d, 0x2a, 0x28, 0xae, 0xd1, 0x5e } + +} +, +{ + "RSAES-OAEP Encryption Example 4.3", + /* Message to be encrypted */ + 62, + { 0xbf, 0x6d, 0x42, 0xe7, 0x01, 0x70, 0x7b, 0x1d, 0x02, 0x06, 0xb0, 0xc8, 0xb4, 0x5a, 0x1c, 0x72, 0x64, 0x1f, 0xf1, 0x28, 0x89, 0x21, 0x9a, 0x82, 0xbd, 0xea, 0x96, 0x5b, 0x5e, 0x79, 0xa9, 0x6b, 0x0d, 0x01, 0x63, 0xed, 0x9d, 0x57, 0x8e, 0xc9, 0xad, 0xa2, 0x0f, 0x2f, 0xbc, 0xf1, 0xea, 0x3c, 0x40, 0x89, 0xd8, 0x34, 0x19, 0xba, 0x81, 0xb0, 0xc6, 0x0f, 0x36, 0x06, 0xda, 0x99 } +, + /* Seed */ + 20, + { 0xad, 0x99, 0x7f, 0xee, 0xf7, 0x30, 0xd6, 0xea, 0x7b, 0xe6, 0x0d, 0x0d, 0xc5, 0x2e, 0x72, 0xea, 0xcb, 0xfd, 0xd2, 0x75 } +, + /* Encryption */ + 129, + { 0x03, 0x01, 0xf9, 0x35, 0xe9, 0xc4, 0x7a, 0xbc, 0xb4, 0x8a, 0xcb, 0xbe, 0x09, 0x89, 0x5d, 0x9f, 0x59, 0x71, 0xaf, 0x14, 0x83, 0x9d, 0xa4, 0xff, 0x95, 0x41, 0x7e, 0xe4, 0x53, 0xd1, 0xfd, 0x77, 0x31, 0x90, 0x72, 0xbb, 0x72, 0x97, 0xe1, 0xb5, 0x5d, 0x75, 0x61, 0xcd, 0x9d, 0x1b, 0xb2, 0x4c, 0x1a, 0x9a, 0x37, 0xc6, 0x19, 0x86, 0x43, 0x08, 0x24, 0x28, 0x04, 0x87, 0x9d, 0x86, 0xeb, 0xd0, 0x01, 0xdc, 0xe5, 0x18, 0x39, 0x75, 0xe1, 0x50, 0x69, 0x89, 0xb7, 0x0e, 0x5a, 0x83, 0x43, 0x41, 0x54, 0xd5, 0xcb, 0xfd, 0x6a, 0x24, 0x78, 0x7e, 0x60, 0xeb, 0x0c, 0x65, 0x8d, 0x2a, 0xc1, 0x93, 0x30, 0x2d, 0x11, 0x92, 0xc6, 0xe6, 0x22, 0xd4, 0xa1, 0x2a, 0xd4, 0xb5, 0x39, 0x23, 0xbc, 0xa2, 0x46, 0xdf, 0x31, 0xc6, 0x39, 0x5e, 0x37, 0x70, 0x2c, 0x6a, 0x78, 0xae, 0x08, 0x1f, 0xb9, 0xd0, 0x65 } + +} +, +{ + "RSAES-OAEP Encryption Example 4.4", + /* Message to be encrypted */ + 22, + { 0xfb, 0x2e, 0xf1, 0x12, 0xf5, 0xe7, 0x66, 0xeb, 0x94, 0x01, 0x92, 0x97, 0x93, 0x47, 0x94, 0xf7, 0xbe, 0x2f, 0x6f, 0xc1, 0xc5, 0x8e } +, + /* Seed */ + 20, + { 0x13, 0x64, 0x54, 0xdf, 0x57, 0x30, 0xf7, 0x3c, 0x80, 0x7a, 0x7e, 0x40, 0xd8, 0xc1, 0xa3, 0x12, 0xac, 0x5b, 0x9d, 0xd3 } +, + /* Encryption */ + 129, + { 0x02, 0xd1, 0x10, 0xad, 0x30, 0xaf, 0xb7, 0x27, 0xbe, 0xb6, 0x91, 0xdd, 0x0c, 0xf1, 0x7d, 0x0a, 0xf1, 0xa1, 0xe7, 0xfa, 0x0c, 0xc0, 0x40, 0xec, 0x1a, 0x4b, 0xa2, 0x6a, 0x42, 0xc5, 0x9d, 0x0a, 0x79, 0x6a, 0x2e, 0x22, 0xc8, 0xf3, 0x57, 0xcc, 0xc9, 0x8b, 0x65, 0x19, 0xac, 0xeb, 0x68, 0x2e, 0x94, 0x5e, 0x62, 0xcb, 0x73, 0x46, 0x14, 0xa5, 0x29, 0x40, 0x7c, 0xd4, 0x52, 0xbe, 0xe3, 0xe4, 0x4f, 0xec, 0xe8, 0x42, 0x3c, 0xc1, 0x9e, 0x55, 0x54, 0x8b, 0x8b, 0x99, 0x4b, 0x84, 0x9c, 0x7e, 0xcd, 0xe4, 0x93, 0x3e, 0x76, 0x03, 0x7e, 0x1d, 0x0c, 0xe4, 0x42, 0x75, 0xb0, 0x87, 0x10, 0xc6, 0x8e, 0x43, 0x01, 0x30, 0xb9, 0x29, 0x73, 0x0e, 0xd7, 0x7e, 0x09, 0xb0, 0x15, 0x64, 0x2c, 0x55, 0x93, 0xf0, 0x4e, 0x4f, 0xfb, 0x94, 0x10, 0x79, 0x81, 0x02, 0xa8, 0xe9, 0x6f, 0xfd, 0xfe, 0x11, 0xe4 } + +} +, +{ + "RSAES-OAEP Encryption Example 4.5", + /* Message to be encrypted */ + 34, + { 0x28, 0xcc, 0xd4, 0x47, 0xbb, 0x9e, 0x85, 0x16, 0x6d, 0xab, 0xb9, 0xe5, 0xb7, 0xd1, 0xad, 0xad, 0xc4, 0xb9, 0xd3, 0x9f, 0x20, 0x4e, 0x96, 0xd5, 0xe4, 0x40, 0xce, 0x9a, 0xd9, 0x28, 0xbc, 0x1c, 0x22, 0x84 } +, + /* Seed */ + 20, + { 0xbc, 0xa8, 0x05, 0x7f, 0x82, 0x4b, 0x2e, 0xa2, 0x57, 0xf2, 0x86, 0x14, 0x07, 0xee, 0xf6, 0x3d, 0x33, 0x20, 0x86, 0x81 } +, + /* Encryption */ + 129, + { 0x00, 0xdb, 0xb8, 0xa7, 0x43, 0x9d, 0x90, 0xef, 0xd9, 0x19, 0xa3, 0x77, 0xc5, 0x4f, 0xae, 0x8f, 0xe1, 0x1e, 0xc5, 0x8c, 0x3b, 0x85, 0x83, 0x62, 0xe2, 0x3a, 0xd1, 0xb8, 0xa4, 0x43, 0x10, 0x79, 0x90, 0x66, 0xb9, 0x93, 0x47, 0xaa, 0x52, 0x56, 0x91, 0xd2, 0xad, 0xc5, 0x8d, 0x9b, 0x06, 0xe3, 0x4f, 0x28, 0x8c, 0x17, 0x03, 0x90, 0xc5, 0xf0, 0xe1, 0x1c, 0x0a, 0xa3, 0x64, 0x59, 0x59, 0xf1, 0x8e, 0xe7, 0x9e, 0x8f, 0x2b, 0xe8, 0xd7, 0xac, 0x5c, 0x23, 0xd0, 0x61, 0xf1, 0x8d, 0xd7, 0x4b, 0x8c, 0x5f, 0x2a, 0x58, 0xfc, 0xb5, 0xeb, 0x0c, 0x54, 0xf9, 0x9f, 0x01, 0xa8, 0x32, 0x47, 0x56, 0x82, 0x92, 0x53, 0x65, 0x83, 0x34, 0x09, 0x48, 0xd7, 0xa8, 0xc9, 0x7c, 0x4a, 0xcd, 0x1e, 0x98, 0xd1, 0xe2, 0x9d, 0xc3, 0x20, 0xe9, 0x7a, 0x26, 0x05, 0x32, 0xa8, 0xaa, 0x7a, 0x75, 0x8a, 0x1e, 0xc2 } + +} +, +{ + "RSAES-OAEP Encryption Example 4.6", + /* Message to be encrypted */ + 7, + { 0xf2, 0x22, 0x42, 0x75, 0x1e, 0xc6, 0xb1 } +, + /* Seed */ + 20, + { 0x2e, 0x7e, 0x1e, 0x17, 0xf6, 0x47, 0xb5, 0xdd, 0xd0, 0x33, 0xe1, 0x54, 0x72, 0xf9, 0x0f, 0x68, 0x12, 0xf3, 0xac, 0x4e } +, + /* Encryption */ + 129, + { 0x00, 0xa5, 0xff, 0xa4, 0x76, 0x8c, 0x8b, 0xbe, 0xca, 0xee, 0x2d, 0xb7, 0x7e, 0x8f, 0x2e, 0xec, 0x99, 0x59, 0x59, 0x33, 0x54, 0x55, 0x20, 0x83, 0x5e, 0x5b, 0xa7, 0xdb, 0x94, 0x93, 0xd3, 0xe1, 0x7c, 0xdd, 0xef, 0xe6, 0xa5, 0xf5, 0x67, 0x62, 0x44, 0x71, 0x90, 0x8d, 0xb4, 0xe2, 0xd8, 0x3a, 0x0f, 0xbe, 0xe6, 0x06, 0x08, 0xfc, 0x84, 0x04, 0x95, 0x03, 0xb2, 0x23, 0x4a, 0x07, 0xdc, 0x83, 0xb2, 0x7b, 0x22, 0x84, 0x7a, 0xd8, 0x92, 0x0f, 0xf4, 0x2f, 0x67, 0x4e, 0xf7, 0x9b, 0x76, 0x28, 0x0b, 0x00, 0x23, 0x3d, 0x2b, 0x51, 0xb8, 0xcb, 0x27, 0x03, 0xa9, 0xd4, 0x2b, 0xfb, 0xc8, 0x25, 0x0c, 0x96, 0xec, 0x32, 0xc0, 0x51, 0xe5, 0x7f, 0x1b, 0x4b, 0xa5, 0x28, 0xdb, 0x89, 0xc3, 0x7e, 0x4c, 0x54, 0xe2, 0x7e, 0x6e, 0x64, 0xac, 0x69, 0x63, 0x5a, 0xe8, 0x87, 0xd9, 0x54, 0x16, 0x19, 0xa9 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 5: A 1028-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x0a, 0xad, 0xf3, 0xf9, 0xc1, 0x25, 0xe5, 0xd8, 0x91, 0xf3, 0x1a, 0xc4, 0x48, 0xe9, 0x93, 0xde, 0xfe, 0x58, 0x0f, 0x80, 0x2b, 0x45, 0xf9, 0xd7, 0xf2, 0x2b, 0xa5, 0x02, 0x1e, 0x9c, 0x47, 0x57, 0x6b, 0x5a, 0x1e, 0x68, 0x03, 0x1b, 0xa9, 0xdb, 0x4e, 0x6d, 0xab, 0xe4, 0xd9, 0x6a, 0x1d, 0x6f, 0x3d, 0x26, 0x72, 0x68, 0xcf, 0xf4, 0x08, 0x00, 0x5f, 0x11, 0x8e, 0xfc, 0xad, 0xb9, 0x98, 0x88, 0xd1, 0xc2, 0x34, 0x46, 0x71, 0x66, 0xb2, 0xa2, 0xb8, 0x49, 0xa0, 0x5a, 0x88, 0x9c, 0x06, 0x0a, 0xc0, 0xda, 0x0c, 0x5f, 0xae, 0x8b, 0x55, 0xf3, 0x09, 0xba, 0x62, 0xe7, 0x03, 0x74, 0x2f, 0xa0, 0x32, 0x6f, 0x2d, 0x10, 0xb0, 0x11, 0x02, 0x14, 0x89, 0xff, 0x49, 0x77, 0x70, 0x19, 0x0d, 0x89, 0x5f, 0xd3, 0x9f, 0x52, 0x29, 0x3c, 0x39, 0xef, 0xd7, 0x3a, 0x69, 0x8b, 0xda, 0xb9, 0xf1, 0x0e, 0xd9 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 129, + { 0x02, 0x56, 0xeb, 0x4c, 0xba, 0x70, 0x67, 0xf2, 0xd2, 0xbe, 0x54, 0x0d, 0xcd, 0xff, 0x45, 0x82, 0xa3, 0x6b, 0x7d, 0x31, 0xd1, 0xc9, 0x09, 0x9b, 0xb2, 0x14, 0xb7, 0x98, 0x48, 0x46, 0x6a, 0x26, 0x8f, 0x80, 0xf5, 0x8a, 0x49, 0xac, 0x04, 0xc0, 0xe3, 0x64, 0x89, 0x34, 0xa0, 0x20, 0x6c, 0x04, 0x53, 0x7c, 0x19, 0xb2, 0x36, 0x64, 0x3a, 0x60, 0x82, 0x73, 0x21, 0x44, 0xdf, 0x75, 0xfa, 0x21, 0x75, 0x88, 0xf7, 0x94, 0x68, 0x2b, 0xe8, 0x91, 0x68, 0x27, 0x6d, 0xc7, 0x26, 0xc5, 0xc0, 0xcb, 0xdb, 0x84, 0xd3, 0x1b, 0xbf, 0x26, 0xd0, 0xa4, 0x3a, 0xf4, 0x95, 0x71, 0x7f, 0x7d, 0x52, 0x8a, 0xcf, 0xee, 0x34, 0x15, 0x61, 0xf6, 0xff, 0x3c, 0xae, 0x05, 0xc5, 0x78, 0xf8, 0x47, 0x0d, 0x96, 0x82, 0xf9, 0xc0, 0xd0, 0x72, 0xf9, 0xf6, 0x06, 0x8b, 0x56, 0xd5, 0x88, 0x0f, 0x68, 0x2b, 0xe2, 0xc5 } +, + /* Prime p */ + 65, + { 0x03, 0xb0, 0xd3, 0x96, 0x2f, 0x6d, 0x17, 0x54, 0x9c, 0xbf, 0xca, 0x11, 0x29, 0x43, 0x48, 0xdc, 0xf0, 0xe7, 0xe3, 0x9f, 0x8c, 0x2b, 0xc6, 0x82, 0x4f, 0x21, 0x64, 0xb6, 0x06, 0xd6, 0x87, 0x86, 0x0d, 0xae, 0x1e, 0x63, 0x23, 0x93, 0xcf, 0xed, 0xf5, 0x13, 0x22, 0x82, 0x29, 0x06, 0x9e, 0x2f, 0x60, 0xe4, 0xac, 0xd7, 0xe6, 0x33, 0xa4, 0x36, 0x06, 0x3f, 0x82, 0x38, 0x5f, 0x48, 0x99, 0x37, 0x07 } +, + /* Prime q */ + 65, + { 0x02, 0xe4, 0xc3, 0x2e, 0x2f, 0x51, 0x72, 0x69, 0xb7, 0x07, 0x23, 0x09, 0xf0, 0x0c, 0x0e, 0x31, 0x36, 0x5f, 0x7c, 0xe2, 0x8b, 0x23, 0x6b, 0x82, 0x91, 0x2d, 0xf2, 0x39, 0xab, 0xf3, 0x95, 0x72, 0xcf, 0x0e, 0xd6, 0x04, 0xb0, 0x29, 0x82, 0xe5, 0x35, 0x64, 0xc5, 0x2d, 0x6a, 0x05, 0x39, 0x7d, 0xe5, 0xc0, 0x52, 0xa2, 0xfd, 0xdc, 0x14, 0x1e, 0xf7, 0x18, 0x98, 0x36, 0x34, 0x6a, 0xeb, 0x33, 0x1f } +, + /* p's CRT exponent dP */ + 65, + { 0x01, 0xe8, 0x4b, 0x11, 0x9d, 0x25, 0x16, 0x1f, 0xa6, 0x7b, 0x00, 0x25, 0x6a, 0x5b, 0xd9, 0xb6, 0x45, 0xd2, 0xb2, 0x32, 0xec, 0xb0, 0x5b, 0x01, 0x51, 0x80, 0x02, 0x9a, 0x88, 0x62, 0x2a, 0xdc, 0x3f, 0x09, 0xb3, 0xae, 0xac, 0xde, 0x61, 0x61, 0xab, 0x7c, 0xde, 0x22, 0xc2, 0xad, 0x26, 0xe7, 0x79, 0x7d, 0xf5, 0x4e, 0x07, 0x2c, 0xbd, 0x3b, 0x26, 0x73, 0x80, 0x0b, 0x3e, 0x43, 0x38, 0xdb, 0xd5 } +, + /* q's CRT exponent dQ */ + 64, + { 0xeb, 0x90, 0xaa, 0x1a, 0x40, 0x13, 0x5b, 0x4c, 0xea, 0x07, 0x19, 0x7c, 0xed, 0xc8, 0x81, 0x9b, 0xe1, 0xe7, 0xcb, 0xff, 0x25, 0x47, 0x66, 0x21, 0x16, 0xf4, 0x65, 0xa4, 0xa9, 0xf4, 0x87, 0xab, 0x12, 0xf3, 0xba, 0x4f, 0xef, 0x13, 0x82, 0x22, 0x65, 0xa6, 0x52, 0x97, 0xd9, 0x8b, 0x7b, 0xde, 0xd9, 0x37, 0x2e, 0x3f, 0xfe, 0x81, 0xa3, 0x8b, 0x3e, 0x96, 0x00, 0xfe, 0xd0, 0x55, 0x75, 0x4f } +, + /* CRT coefficient qInv */ + 65, + { 0x01, 0x2f, 0x7f, 0x81, 0x38, 0xf9, 0x40, 0x40, 0x62, 0xeb, 0x85, 0xa4, 0x29, 0x24, 0x52, 0x0b, 0x38, 0xf5, 0xbb, 0x88, 0x6a, 0x01, 0x96, 0xf4, 0x8b, 0xb8, 0xdc, 0xea, 0x60, 0xfd, 0x92, 0xcc, 0x02, 0x7f, 0x18, 0xe7, 0x81, 0x58, 0xa3, 0x4a, 0x5c, 0x5d, 0x5f, 0x86, 0x0a, 0x0f, 0x6c, 0x04, 0x07, 0x1a, 0x7d, 0x01, 0x31, 0x2c, 0x06, 0x50, 0x62, 0xf1, 0xeb, 0x48, 0xb7, 0x9d, 0x1c, 0x83, 0xcb } + +} +, +{{ + "RSAES-OAEP Encryption Example 5.1", + /* Message to be encrypted */ + 31, + { 0xaf, 0x71, 0xa9, 0x01, 0xe3, 0xa6, 0x1d, 0x31, 0x32, 0xf0, 0xfc, 0x1f, 0xdb, 0x47, 0x4f, 0x9e, 0xa6, 0x57, 0x92, 0x57, 0xff, 0xc2, 0x4d, 0x16, 0x41, 0x70, 0x14, 0x5b, 0x3d, 0xbd, 0xe8 } +, + /* Seed */ + 20, + { 0x44, 0xc9, 0x2e, 0x28, 0x3f, 0x77, 0xb9, 0x49, 0x9c, 0x60, 0x3d, 0x96, 0x36, 0x60, 0xc8, 0x7d, 0x2f, 0x93, 0x94, 0x61 } +, + /* Encryption */ + 129, + { 0x03, 0x60, 0x46, 0xa4, 0xa4, 0x7d, 0x9e, 0xd3, 0xba, 0x9a, 0x89, 0x13, 0x9c, 0x10, 0x50, 0x38, 0xeb, 0x74, 0x92, 0xb0, 0x5a, 0x5d, 0x68, 0xbf, 0xd5, 0x3a, 0xcc, 0xff, 0x45, 0x97, 0xf7, 0xa6, 0x86, 0x51, 0xb4, 0x7b, 0x4a, 0x46, 0x27, 0xd9, 0x27, 0xe4, 0x85, 0xee, 0xd7, 0xb4, 0x56, 0x64, 0x20, 0xe8, 0xb4, 0x09, 0x87, 0x9e, 0x5d, 0x60, 0x6e, 0xae, 0x25, 0x1d, 0x22, 0xa5, 0xdf, 0x79, 0x9f, 0x79, 0x20, 0xbf, 0xc1, 0x17, 0xb9, 0x92, 0x57, 0x2a, 0x53, 0xb1, 0x26, 0x31, 0x46, 0xbc, 0xea, 0x03, 0x38, 0x5c, 0xc5, 0xe8, 0x53, 0xc9, 0xa1, 0x01, 0xc8, 0xc3, 0xe1, 0xbd, 0xa3, 0x1a, 0x51, 0x98, 0x07, 0x49, 0x6c, 0x6c, 0xb5, 0xe5, 0xef, 0xb4, 0x08, 0x82, 0x3a, 0x35, 0x2b, 0x8f, 0xa0, 0x66, 0x1f, 0xb6, 0x64, 0xef, 0xad, 0xd5, 0x93, 0xde, 0xb9, 0x9f, 0xff, 0x5e, 0xd0, 0x00, 0xe5 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 5.2", + /* Message to be encrypted */ + 44, + { 0xa3, 0xb8, 0x44, 0xa0, 0x82, 0x39, 0xa8, 0xac, 0x41, 0x60, 0x5a, 0xf1, 0x7a, 0x6c, 0xfd, 0xa4, 0xd3, 0x50, 0x13, 0x65, 0x85, 0x90, 0x3a, 0x41, 0x7a, 0x79, 0x26, 0x87, 0x60, 0x51, 0x9a, 0x4b, 0x4a, 0xc3, 0x30, 0x3e, 0xc7, 0x3f, 0x0f, 0x87, 0xcf, 0xb3, 0x23, 0x99 } +, + /* Seed */ + 20, + { 0xcb, 0x28, 0xf5, 0x86, 0x06, 0x59, 0xfc, 0xee, 0xe4, 0x9c, 0x3e, 0xea, 0xfc, 0xe6, 0x25, 0xa7, 0x08, 0x03, 0xbd, 0x32 } +, + /* Encryption */ + 129, + { 0x03, 0xd6, 0xeb, 0x65, 0x4e, 0xdc, 0xe6, 0x15, 0xbc, 0x59, 0xf4, 0x55, 0x26, 0x5e, 0xd4, 0xe5, 0xa1, 0x82, 0x23, 0xcb, 0xb9, 0xbe, 0x4e, 0x40, 0x69, 0xb4, 0x73, 0x80, 0x4d, 0x5d, 0xe9, 0x6f, 0x54, 0xdc, 0xaa, 0xa6, 0x03, 0xd0, 0x49, 0xc5, 0xd9, 0x4a, 0xa1, 0x47, 0x0d, 0xfc, 0xd2, 0x25, 0x40, 0x66, 0xb7, 0xc7, 0xb6, 0x1f, 0xf1, 0xf6, 0xf6, 0x77, 0x0e, 0x32, 0x15, 0xc5, 0x13, 0x99, 0xfd, 0x4e, 0x34, 0xec, 0x50, 0x82, 0xbc, 0x48, 0xf0, 0x89, 0x84, 0x0a, 0xd0, 0x43, 0x54, 0xae, 0x66, 0xdc, 0x0f, 0x1b, 0xd1, 0x8e, 0x46, 0x1a, 0x33, 0xcc, 0x12, 0x58, 0xb4, 0x43, 0xa2, 0x83, 0x7a, 0x6d, 0xf2, 0x67, 0x59, 0xaa, 0x23, 0x02, 0x33, 0x49, 0x86, 0xf8, 0x73, 0x80, 0xc9, 0xcc, 0x9d, 0x53, 0xbe, 0x9f, 0x99, 0x60, 0x5d, 0x2c, 0x9a, 0x97, 0xda, 0x7b, 0x09, 0x15, 0xa4, 0xa7, 0xad } + +} +, +{ + "RSAES-OAEP Encryption Example 5.3", + /* Message to be encrypted */ + 63, + { 0x30, 0x8b, 0x0e, 0xcb, 0xd2, 0xc7, 0x6c, 0xb7, 0x7f, 0xc6, 0xf7, 0x0c, 0x5e, 0xdd, 0x23, 0x3f, 0xd2, 0xf2, 0x09, 0x29, 0xd6, 0x29, 0xf0, 0x26, 0x95, 0x3b, 0xb6, 0x2a, 0x8f, 0x4a, 0x3a, 0x31, 0x4b, 0xde, 0x19, 0x5d, 0xe8, 0x5b, 0x5f, 0x81, 0x6d, 0xa2, 0xaa, 0xb0, 0x74, 0xd2, 0x6c, 0xb6, 0xac, 0xdd, 0xf3, 0x23, 0xae, 0x3b, 0x9c, 0x67, 0x8a, 0xc3, 0xcf, 0x12, 0xfb, 0xdd, 0xe7 } +, + /* Seed */ + 20, + { 0x22, 0x85, 0xf4, 0x0d, 0x77, 0x04, 0x82, 0xf9, 0xa9, 0xef, 0xa2, 0xc7, 0x2c, 0xb3, 0xac, 0x55, 0x71, 0x6d, 0xc0, 0xca } +, + /* Encryption */ + 129, + { 0x07, 0x70, 0x95, 0x21, 0x81, 0x64, 0x9f, 0x9f, 0x9f, 0x07, 0xff, 0x62, 0x6f, 0xf3, 0xa2, 0x2c, 0x35, 0xc4, 0x62, 0x44, 0x3d, 0x90, 0x5d, 0x45, 0x6a, 0x9f, 0xd0, 0xbf, 0xf4, 0x3c, 0xac, 0x2c, 0xa7, 0xa9, 0xf5, 0x54, 0xe9, 0x47, 0x8b, 0x9a, 0xcc, 0x3a, 0xc8, 0x38, 0xb0, 0x20, 0x40, 0xff, 0xd3, 0xe1, 0x84, 0x7d, 0xe2, 0xe4, 0x25, 0x39, 0x29, 0xf9, 0xdd, 0x9e, 0xe4, 0x04, 0x43, 0x25, 0xa9, 0xb0, 0x5c, 0xab, 0xb8, 0x08, 0xb2, 0xee, 0x84, 0x0d, 0x34, 0xe1, 0x5d, 0x10, 0x5a, 0x3f, 0x1f, 0x7b, 0x27, 0x69, 0x5a, 0x1a, 0x07, 0xa2, 0xd7, 0x3f, 0xe0, 0x8e, 0xca, 0xaa, 0x3c, 0x9c, 0x9d, 0x4d, 0x5a, 0x89, 0xff, 0x89, 0x0d, 0x54, 0x72, 0x7d, 0x7a, 0xe4, 0x0c, 0x0e, 0xc1, 0xa8, 0xdd, 0x86, 0x16, 0x5d, 0x8e, 0xe2, 0xc6, 0x36, 0x81, 0x41, 0x01, 0x6a, 0x48, 0xb5, 0x5b, 0x69, 0x67 } + +} +, +{ + "RSAES-OAEP Encryption Example 5.4", + /* Message to be encrypted */ + 6, + { 0x15, 0xc5, 0xb9, 0xee, 0x11, 0x85 } +, + /* Seed */ + 20, + { 0x49, 0xfa, 0x45, 0xd3, 0xa7, 0x8d, 0xd1, 0x0d, 0xfd, 0x57, 0x73, 0x99, 0xd1, 0xeb, 0x00, 0xaf, 0x7e, 0xed, 0x55, 0x13 } +, + /* Encryption */ + 129, + { 0x08, 0x12, 0xb7, 0x67, 0x68, 0xeb, 0xcb, 0x64, 0x2d, 0x04, 0x02, 0x58, 0xe5, 0xf4, 0x44, 0x1a, 0x01, 0x85, 0x21, 0xbd, 0x96, 0x68, 0x7e, 0x6c, 0x5e, 0x89, 0x9f, 0xcd, 0x6c, 0x17, 0x58, 0x8f, 0xf5, 0x9a, 0x82, 0xcc, 0x8a, 0xe0, 0x3a, 0x4b, 0x45, 0xb3, 0x12, 0x99, 0xaf, 0x17, 0x88, 0xc3, 0x29, 0xf7, 0xdc, 0xd2, 0x85, 0xf8, 0xcf, 0x4c, 0xed, 0x82, 0x60, 0x6b, 0x97, 0x61, 0x26, 0x71, 0xa4, 0x5b, 0xed, 0xca, 0x13, 0x34, 0x42, 0x14, 0x4d, 0x16, 0x17, 0xd1, 0x14, 0xf8, 0x02, 0x85, 0x7f, 0x0f, 0x9d, 0x73, 0x97, 0x51, 0xc5, 0x7a, 0x3f, 0x9e, 0xe4, 0x00, 0x91, 0x2c, 0x61, 0xe2, 0xe6, 0x99, 0x2b, 0xe0, 0x31, 0xa4, 0x3d, 0xd4, 0x8f, 0xa6, 0xba, 0x14, 0xee, 0xf7, 0xc4, 0x22, 0xb5, 0xed, 0xc4, 0xe7, 0xaf, 0xa0, 0x4f, 0xdd, 0x38, 0xf4, 0x02, 0xd1, 0xc8, 0xbb, 0x71, 0x9a, 0xbf } + +} +, +{ + "RSAES-OAEP Encryption Example 5.5", + /* Message to be encrypted */ + 45, + { 0x21, 0x02, 0x6e, 0x68, 0x00, 0xc7, 0xfa, 0x72, 0x8f, 0xca, 0xab, 0xa0, 0xd1, 0x96, 0xae, 0x28, 0xd7, 0xa2, 0xac, 0x4f, 0xfd, 0x8a, 0xbc, 0xe7, 0x94, 0xf0, 0x98, 0x5f, 0x60, 0xc8, 0xa6, 0x73, 0x72, 0x77, 0x36, 0x5d, 0x3f, 0xea, 0x11, 0xdb, 0x89, 0x23, 0xa2, 0x02, 0x9a } +, + /* Seed */ + 20, + { 0xf0, 0x28, 0x74, 0x13, 0x23, 0x4c, 0xc5, 0x03, 0x47, 0x24, 0xa0, 0x94, 0xc4, 0x58, 0x6b, 0x87, 0xaf, 0xf1, 0x33, 0xfc } +, + /* Encryption */ + 129, + { 0x07, 0xb6, 0x0e, 0x14, 0xec, 0x95, 0x4b, 0xfd, 0x29, 0xe6, 0x0d, 0x00, 0x47, 0xe7, 0x89, 0xf5, 0x1d, 0x57, 0x18, 0x6c, 0x63, 0x58, 0x99, 0x03, 0x30, 0x67, 0x93, 0xce, 0xd3, 0xf6, 0x82, 0x41, 0xc7, 0x43, 0x52, 0x9a, 0xba, 0x6a, 0x63, 0x74, 0xf9, 0x2e, 0x19, 0xe0, 0x16, 0x3e, 0xfa, 0x33, 0x69, 0x7e, 0x19, 0x6f, 0x76, 0x61, 0xdf, 0xaa, 0xa4, 0x7a, 0xac, 0x6b, 0xde, 0x5e, 0x51, 0xde, 0xb5, 0x07, 0xc7, 0x2c, 0x58, 0x9a, 0x2c, 0xa1, 0x69, 0x3d, 0x96, 0xb1, 0x46, 0x03, 0x81, 0x24, 0x9b, 0x2c, 0xdb, 0x9e, 0xac, 0x44, 0x76, 0x9f, 0x24, 0x89, 0xc5, 0xd3, 0xd2, 0xf9, 0x9f, 0x0e, 0xe3, 0xc7, 0xee, 0x5b, 0xf6, 0x4a, 0x5a, 0xc7, 0x9c, 0x42, 0xbd, 0x43, 0x3f, 0x14, 0x9b, 0xe8, 0xcb, 0x59, 0x54, 0x83, 0x61, 0x64, 0x05, 0x95, 0x51, 0x3c, 0x97, 0xaf, 0x7b, 0xc2, 0x50, 0x97, 0x23 } + +} +, +{ + "RSAES-OAEP Encryption Example 5.6", + /* Message to be encrypted */ + 11, + { 0x54, 0x1e, 0x37, 0xb6, 0x8b, 0x6c, 0x88, 0x72, 0xb8, 0x4c, 0x02 } +, + /* Seed */ + 20, + { 0xd9, 0xfb, 0xa4, 0x5c, 0x96, 0xf2, 0x1e, 0x6e, 0x26, 0xd2, 0x9e, 0xb2, 0xcd, 0xcb, 0x65, 0x85, 0xbe, 0x9c, 0xb3, 0x41 } +, + /* Encryption */ + 129, + { 0x08, 0xc3, 0x6d, 0x4d, 0xda, 0x33, 0x42, 0x3b, 0x2e, 0xd6, 0x83, 0x0d, 0x85, 0xf6, 0x41, 0x1b, 0xa1, 0xdc, 0xf4, 0x70, 0xa1, 0xfa, 0xe0, 0xeb, 0xef, 0xee, 0x7c, 0x08, 0x9f, 0x25, 0x6c, 0xef, 0x74, 0xcb, 0x96, 0xea, 0x69, 0xc3, 0x8f, 0x60, 0xf3, 0x9a, 0xbe, 0xe4, 0x41, 0x29, 0xbc, 0xb4, 0xc9, 0x2d, 0xe7, 0xf7, 0x97, 0x62, 0x3b, 0x20, 0x07, 0x4e, 0x3d, 0x9c, 0x28, 0x99, 0x70, 0x1e, 0xd9, 0x07, 0x1e, 0x1e, 0xfa, 0x0b, 0xdd, 0x84, 0xd4, 0xc3, 0xe5, 0x13, 0x03, 0x02, 0xd8, 0xf0, 0x24, 0x0b, 0xab, 0xa4, 0xb8, 0x4a, 0x71, 0xcc, 0x03, 0x2f, 0x22, 0x35, 0xa5, 0xff, 0x0f, 0xae, 0x27, 0x7c, 0x3e, 0x8f, 0x91, 0x12, 0xbe, 0xf4, 0x4c, 0x9a, 0xe2, 0x0d, 0x17, 0x5f, 0xc9, 0xa4, 0x05, 0x8b, 0xfc, 0x93, 0x0b, 0xa3, 0x1b, 0x02, 0xe2, 0xe4, 0xf4, 0x44, 0x48, 0x37, 0x10, 0xf2, 0x4a } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 6: A 1029-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x12, 0xb1, 0x7f, 0x6d, 0xad, 0x2e, 0xcd, 0x19, 0xff, 0x46, 0xdc, 0x13, 0xf7, 0x86, 0x0f, 0x09, 0xe0, 0xe0, 0xcf, 0xb6, 0x77, 0xb3, 0x8a, 0x52, 0x59, 0x23, 0x05, 0xce, 0xaf, 0x02, 0x2c, 0x16, 0x6d, 0xb9, 0x0d, 0x04, 0xac, 0x29, 0xe3, 0x3f, 0x7d, 0xd1, 0x2d, 0x9f, 0xaf, 0x66, 0xe0, 0x81, 0x6b, 0xb6, 0x3e, 0xad, 0x26, 0x7c, 0xc7, 0xd4, 0x6c, 0x17, 0xc3, 0x7b, 0xe2, 0x14, 0xbc, 0xa2, 0xa2, 0x2d, 0x72, 0x3a, 0x64, 0xe4, 0x44, 0x07, 0x43, 0x6b, 0x6f, 0xc9, 0x65, 0x72, 0x9a, 0xef, 0xc2, 0x55, 0x4f, 0x37, 0x6c, 0xd5, 0xdc, 0xea, 0x68, 0x29, 0x37, 0x80, 0xa6, 0x2b, 0xf3, 0x9d, 0x00, 0x29, 0x48, 0x5a, 0x16, 0x0b, 0xbb, 0x9e, 0x5d, 0xc0, 0x97, 0x2d, 0x21, 0xa5, 0x04, 0xf5, 0x2e, 0x5e, 0xe0, 0x28, 0xaa, 0x41, 0x63, 0x32, 0xf5, 0x10, 0xb2, 0xe9, 0xcf, 0xf5, 0xf7, 0x22, 0xaf } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 129, + { 0x02, 0x95, 0xec, 0xa3, 0x56, 0x06, 0x18, 0x36, 0x95, 0x59, 0xce, 0xcd, 0x30, 0x3a, 0xa9, 0xcf, 0xda, 0xfc, 0x1d, 0x9f, 0x06, 0x95, 0x9d, 0xf7, 0x5f, 0xfe, 0xf9, 0x29, 0xaa, 0x89, 0x69, 0x61, 0xbc, 0xd1, 0x90, 0xdc, 0x69, 0x97, 0xed, 0xa7, 0xf5, 0x96, 0x3e, 0x72, 0x4d, 0x07, 0xb4, 0xdc, 0x11, 0xf3, 0x06, 0x5e, 0x5a, 0xe9, 0x7d, 0x96, 0x83, 0x51, 0x12, 0x28, 0x0b, 0x90, 0x84, 0xbb, 0x14, 0xf2, 0xa2, 0x1e, 0xbd, 0x4e, 0x88, 0x9d, 0x41, 0xb9, 0xc4, 0x13, 0x2e, 0xc1, 0x95, 0x6f, 0xca, 0xb8, 0xbb, 0x2f, 0xed, 0x05, 0x75, 0x88, 0x49, 0x36, 0x52, 0x2c, 0x5f, 0xf7, 0xd3, 0x32, 0x61, 0x90, 0x48, 0x24, 0xe7, 0xca, 0xde, 0xe4, 0xe0, 0xbb, 0x37, 0x2d, 0x24, 0x57, 0xcf, 0x78, 0xe2, 0xbd, 0x12, 0x86, 0x22, 0x8f, 0xf8, 0x3f, 0x10, 0x73, 0x1c, 0xe6, 0x3c, 0x90, 0xcf, 0xf3, 0xf9 } +, + /* Prime p */ + 65, + { 0x04, 0xa6, 0xce, 0x8b, 0x73, 0x58, 0xdf, 0xa6, 0x9b, 0xdc, 0xf7, 0x42, 0x61, 0x70, 0x05, 0xaf, 0xb5, 0x38, 0x5f, 0x5f, 0x3a, 0x58, 0xa2, 0x4e, 0xf7, 0x4a, 0x22, 0xa8, 0xc0, 0x5c, 0xb7, 0xcc, 0x38, 0xeb, 0xd4, 0xcc, 0x9d, 0x9a, 0x9d, 0x78, 0x9a, 0x62, 0xcd, 0x0f, 0x60, 0xf0, 0xcb, 0x94, 0x1d, 0x34, 0x23, 0xc9, 0x69, 0x2e, 0xfa, 0x4f, 0xe3, 0xad, 0xff, 0x29, 0x0c, 0x47, 0x49, 0xa3, 0x8b } +, + /* Prime q */ + 65, + { 0x04, 0x04, 0xc9, 0xa8, 0x03, 0x37, 0x1f, 0xed, 0xb4, 0xc5, 0xbe, 0x39, 0xf3, 0xc0, 0x0b, 0x00, 0x9e, 0x5e, 0x08, 0xa6, 0x3b, 0xe1, 0xe4, 0x00, 0x35, 0xcd, 0xac, 0xa5, 0x01, 0x1c, 0xc7, 0x01, 0xcf, 0x7e, 0xeb, 0xcb, 0x99, 0xf0, 0xff, 0xe1, 0x7c, 0xfd, 0x0a, 0x4b, 0xf7, 0xbe, 0xfd, 0x2d, 0xd5, 0x36, 0xac, 0x94, 0x6d, 0xb7, 0x97, 0xfd, 0xbc, 0x4a, 0xbe, 0x8f, 0x29, 0x34, 0x9b, 0x91, 0xed } +, + /* p's CRT exponent dP */ + 65, + { 0x03, 0x96, 0x1c, 0x8f, 0x76, 0x0a, 0xa2, 0xbd, 0x51, 0x54, 0xc7, 0xaa, 0xfd, 0x77, 0x22, 0x5b, 0x3b, 0xac, 0xd0, 0x13, 0x9a, 0xe7, 0xb5, 0x94, 0x8e, 0xa3, 0x31, 0x1f, 0xcc, 0xd8, 0x6f, 0xb9, 0x5c, 0x75, 0xaf, 0xa7, 0x67, 0x28, 0x4b, 0x9b, 0x2d, 0xe5, 0x59, 0x57, 0x2f, 0x15, 0xd8, 0xd0, 0x44, 0xc7, 0xeb, 0x83, 0xa1, 0xbe, 0x5f, 0xad, 0xf2, 0xcc, 0x37, 0x7c, 0x0d, 0x84, 0x75, 0x29, 0x4b } +, + /* q's CRT exponent dQ */ + 65, + { 0x02, 0x21, 0x97, 0xe0, 0x66, 0x74, 0x21, 0x96, 0xaa, 0xbc, 0x03, 0xfa, 0x2f, 0xee, 0xb4, 0xe7, 0x0b, 0x15, 0xcb, 0x78, 0x7d, 0x61, 0x7a, 0xcd, 0x31, 0xbb, 0x75, 0xc7, 0xbc, 0x23, 0x4a, 0xd7, 0x06, 0xf7, 0xc4, 0x8d, 0x21, 0x82, 0xd1, 0xf0, 0xff, 0x9c, 0x22, 0x8d, 0xcf, 0x41, 0x96, 0x7b, 0x6c, 0x0b, 0xa6, 0xd2, 0xc0, 0xad, 0x11, 0x0a, 0x1b, 0x85, 0x78, 0x31, 0xec, 0x24, 0x5e, 0x2c, 0xb1 } +, + /* CRT coefficient qInv */ + 65, + { 0x04, 0x01, 0xc4, 0xc0, 0xc5, 0x3d, 0x45, 0xdb, 0xdb, 0x5e, 0x9d, 0x96, 0xd0, 0xfe, 0xcf, 0x42, 0x75, 0xdf, 0x09, 0x74, 0xbc, 0x4a, 0x07, 0x36, 0xb4, 0xa7, 0x4c, 0x32, 0x69, 0x05, 0x3e, 0xfb, 0x68, 0x6a, 0xce, 0x24, 0x06, 0xe2, 0x2c, 0x9e, 0x05, 0x8d, 0xdb, 0x4a, 0xe5, 0x40, 0x62, 0x7a, 0xe2, 0xfd, 0xb0, 0x82, 0x61, 0xe8, 0xe7, 0xe4, 0xbc, 0xbc, 0x99, 0x4d, 0xaa, 0xfa, 0x30, 0x5c, 0x45 } + +} +, +{{ + "RSAES-OAEP Encryption Example 6.1", + /* Message to be encrypted */ + 22, + { 0x40, 0x46, 0xca, 0x8b, 0xaa, 0x33, 0x47, 0xca, 0x27, 0xf4, 0x9e, 0x0d, 0x81, 0xf9, 0xcc, 0x1d, 0x71, 0xbe, 0x9b, 0xa5, 0x17, 0xd4 } +, + /* Seed */ + 20, + { 0xdd, 0x0f, 0x6c, 0xfe, 0x41, 0x5e, 0x88, 0xe5, 0xa4, 0x69, 0xa5, 0x1f, 0xbb, 0xa6, 0xdf, 0xd4, 0x0a, 0xdb, 0x43, 0x84 } +, + /* Encryption */ + 129, + { 0x06, 0x30, 0xee, 0xbc, 0xd2, 0x85, 0x6c, 0x24, 0xf7, 0x98, 0x80, 0x6e, 0x41, 0xf9, 0xe6, 0x73, 0x45, 0xed, 0xa9, 0xce, 0xda, 0x38, 0x6a, 0xcc, 0x9f, 0xac, 0xae, 0xa1, 0xee, 0xed, 0x06, 0xac, 0xe5, 0x83, 0x70, 0x97, 0x18, 0xd9, 0xd1, 0x69, 0xfa, 0xdf, 0x41, 0x4d, 0x5c, 0x76, 0xf9, 0x29, 0x96, 0x83, 0x3e, 0xf3, 0x05, 0xb7, 0x5b, 0x1e, 0x4b, 0x95, 0xf6, 0x62, 0xa2, 0x0f, 0xae, 0xdc, 0x3b, 0xae, 0x0c, 0x48, 0x27, 0xa8, 0xbf, 0x8a, 0x88, 0xed, 0xbd, 0x57, 0xec, 0x20, 0x3a, 0x27, 0xa8, 0x41, 0xf0, 0x2e, 0x43, 0xa6, 0x15, 0xba, 0xb1, 0xa8, 0xca, 0xc0, 0x70, 0x1d, 0xe3, 0x4d, 0xeb, 0xde, 0xf6, 0x2a, 0x08, 0x80, 0x89, 0xb5, 0x5e, 0xc3, 0x6e, 0xa7, 0x52, 0x2f, 0xd3, 0xec, 0x8d, 0x06, 0xb6, 0xa0, 0x73, 0xe6, 0xdf, 0x83, 0x31, 0x53, 0xbc, 0x0a, 0xef, 0xd9, 0x3b, 0xd1, 0xa3 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 6.2", + /* Message to be encrypted */ + 50, + { 0x5c, 0xc7, 0x2c, 0x60, 0x23, 0x1d, 0xf0, 0x3b, 0x3d, 0x40, 0xf9, 0xb5, 0x79, 0x31, 0xbc, 0x31, 0x10, 0x9f, 0x97, 0x25, 0x27, 0xf2, 0x8b, 0x19, 0xe7, 0x48, 0x0c, 0x72, 0x88, 0xcb, 0x3c, 0x92, 0xb2, 0x25, 0x12, 0x21, 0x4e, 0x4b, 0xe6, 0xc9, 0x14, 0x79, 0x2d, 0xda, 0xbd, 0xf5, 0x7f, 0xaa, 0x8a, 0xa7 } +, + /* Seed */ + 20, + { 0x8d, 0x14, 0xbd, 0x94, 0x6a, 0x13, 0x51, 0x14, 0x8f, 0x5c, 0xae, 0x2e, 0xd9, 0xa0, 0xc6, 0x53, 0xe8, 0x5e, 0xbd, 0x85 } +, + /* Encryption */ + 129, + { 0x0e, 0xbc, 0x37, 0x37, 0x61, 0x73, 0xa4, 0xfd, 0x2f, 0x89, 0xcc, 0x55, 0xc2, 0xca, 0x62, 0xb2, 0x6b, 0x11, 0xd5, 0x1c, 0x3c, 0x7c, 0xe4, 0x9e, 0x88, 0x45, 0xf7, 0x4e, 0x76, 0x07, 0x31, 0x7c, 0x43, 0x6b, 0xc8, 0xd2, 0x3b, 0x96, 0x67, 0xdf, 0xeb, 0x9d, 0x08, 0x72, 0x34, 0xb4, 0x7b, 0xc6, 0x83, 0x71, 0x75, 0xae, 0x5c, 0x05, 0x59, 0xf6, 0xb8, 0x1d, 0x7d, 0x22, 0x41, 0x6d, 0x3e, 0x50, 0xf4, 0xac, 0x53, 0x3d, 0x8f, 0x08, 0x12, 0xf2, 0xdb, 0x9e, 0x79, 0x1f, 0xe9, 0xc7, 0x75, 0xac, 0x8b, 0x6a, 0xd0, 0xf5, 0x35, 0xad, 0x9c, 0xeb, 0x23, 0xa4, 0xa0, 0x20, 0x14, 0xc5, 0x8a, 0xb3, 0xf8, 0xd3, 0x16, 0x14, 0x99, 0xa2, 0x60, 0xf3, 0x93, 0x48, 0xe7, 0x14, 0xae, 0x2a, 0x1d, 0x34, 0x43, 0x20, 0x8f, 0xd8, 0xb7, 0x22, 0xcc, 0xfd, 0xfb, 0x39, 0x3e, 0x98, 0x01, 0x1f, 0x99, 0xe6, 0x3f } + +} +, +{ + "RSAES-OAEP Encryption Example 6.3", + /* Message to be encrypted */ + 54, + { 0xb2, 0x0e, 0x65, 0x13, 0x03, 0x09, 0x2f, 0x4b, 0xcc, 0xb4, 0x30, 0x70, 0xc0, 0xf8, 0x6d, 0x23, 0x04, 0x93, 0x62, 0xed, 0x96, 0x64, 0x2f, 0xc5, 0x63, 0x2c, 0x27, 0xdb, 0x4a, 0x52, 0xe3, 0xd8, 0x31, 0xf2, 0xab, 0x06, 0x8b, 0x23, 0xb1, 0x49, 0x87, 0x9c, 0x00, 0x2f, 0x6b, 0xf3, 0xfe, 0xee, 0x97, 0x59, 0x11, 0x12, 0x56, 0x2c } +, + /* Seed */ + 20, + { 0x6c, 0x07, 0x5b, 0xc4, 0x55, 0x20, 0xf1, 0x65, 0xc0, 0xbf, 0x5e, 0xa4, 0xc5, 0xdf, 0x19, 0x1b, 0xc9, 0xef, 0x0e, 0x44 } +, + /* Encryption */ + 129, + { 0x0a, 0x98, 0xbf, 0x10, 0x93, 0x61, 0x93, 0x94, 0x43, 0x6c, 0xf6, 0x8d, 0x8f, 0x38, 0xe2, 0xf1, 0x58, 0xfd, 0xe8, 0xea, 0x54, 0xf3, 0x43, 0x5f, 0x23, 0x9b, 0x8d, 0x06, 0xb8, 0x32, 0x18, 0x44, 0x20, 0x24, 0x76, 0xae, 0xed, 0x96, 0x00, 0x94, 0x92, 0x48, 0x0c, 0xe3, 0xa8, 0xd7, 0x05, 0x49, 0x8c, 0x4c, 0x8c, 0x68, 0xf0, 0x15, 0x01, 0xdc, 0x81, 0xdb, 0x60, 0x8f, 0x60, 0x08, 0x73, 0x50, 0xc8, 0xc3, 0xb0, 0xbd, 0x2e, 0x9e, 0xf6, 0xa8, 0x14, 0x58, 0xb7, 0xc8, 0x01, 0xb8, 0x9f, 0x2e, 0x4f, 0xe9, 0x9d, 0x49, 0x00, 0xba, 0x6a, 0x4b, 0x5e, 0x5a, 0x96, 0xd8, 0x65, 0xdc, 0x67, 0x6c, 0x77, 0x55, 0x92, 0x87, 0x94, 0x13, 0x0d, 0x62, 0x80, 0xa8, 0x16, 0x0a, 0x19, 0x0f, 0x2d, 0xf3, 0xea, 0x7c, 0xf9, 0xaa, 0x02, 0x71, 0xd8, 0x8e, 0x9e, 0x69, 0x05, 0xec, 0xf1, 0xc5, 0x15, 0x2d, 0x65 } + +} +, +{ + "RSAES-OAEP Encryption Example 6.4", + /* Message to be encrypted */ + 8, + { 0x68, 0x4e, 0x30, 0x38, 0xc5, 0xc0, 0x41, 0xf7 } +, + /* Seed */ + 20, + { 0x3b, 0xbc, 0x3b, 0xd6, 0x63, 0x7d, 0xfe, 0x12, 0x84, 0x69, 0x01, 0x02, 0x9b, 0xf5, 0xb0, 0xc0, 0x71, 0x03, 0x43, 0x9c } +, + /* Encryption */ + 129, + { 0x00, 0x8e, 0x7a, 0x67, 0xca, 0xcf, 0xb5, 0xc4, 0xe2, 0x4b, 0xec, 0x7d, 0xee, 0x14, 0x91, 0x17, 0xf1, 0x95, 0x98, 0xce, 0x8c, 0x45, 0x80, 0x8f, 0xef, 0x88, 0xc6, 0x08, 0xff, 0x9c, 0xd6, 0xe6, 0x95, 0x26, 0x3b, 0x9a, 0x3c, 0x0a, 0xd4, 0xb8, 0xba, 0x4c, 0x95, 0x23, 0x8e, 0x96, 0xa8, 0x42, 0x2b, 0x85, 0x35, 0x62, 0x9c, 0x8d, 0x53, 0x82, 0x37, 0x44, 0x79, 0xad, 0x13, 0xfa, 0x39, 0x97, 0x4b, 0x24, 0x2f, 0x9a, 0x75, 0x9e, 0xea, 0xf9, 0xc8, 0x3a, 0xd5, 0xa8, 0xca, 0x18, 0x94, 0x0a, 0x01, 0x62, 0xba, 0x75, 0x58, 0x76, 0xdf, 0x26, 0x3f, 0x4b, 0xd5, 0x0c, 0x65, 0x25, 0xc5, 0x60, 0x90, 0x26, 0x7c, 0x1f, 0x0e, 0x09, 0xce, 0x08, 0x99, 0xa0, 0xcf, 0x35, 0x9e, 0x88, 0x12, 0x0a, 0xbd, 0x9b, 0xf8, 0x93, 0x44, 0x5b, 0x3c, 0xae, 0x77, 0xd3, 0x60, 0x73, 0x59, 0xae, 0x9a, 0x52, 0xf8 } + +} +, +{ + "RSAES-OAEP Encryption Example 6.5", + /* Message to be encrypted */ + 25, + { 0x32, 0x48, 0x8c, 0xb2, 0x62, 0xd0, 0x41, 0xd6, 0xe4, 0xdd, 0x35, 0xf9, 0x87, 0xbf, 0x3c, 0xa6, 0x96, 0xdb, 0x1f, 0x06, 0xac, 0x29, 0xa4, 0x46, 0x93 } +, + /* Seed */ + 20, + { 0xb4, 0x6b, 0x41, 0x89, 0x3e, 0x8b, 0xef, 0x32, 0x6f, 0x67, 0x59, 0x38, 0x3a, 0x83, 0x07, 0x1d, 0xae, 0x7f, 0xca, 0xbc } +, + /* Encryption */ + 129, + { 0x00, 0x00, 0x34, 0x74, 0x41, 0x6c, 0x7b, 0x68, 0xbd, 0xf9, 0x61, 0xc3, 0x85, 0x73, 0x79, 0x44, 0xd7, 0xf1, 0xf4, 0x0c, 0xb3, 0x95, 0x34, 0x3c, 0x69, 0x3c, 0xc0, 0xb4, 0xfe, 0x63, 0xb3, 0x1f, 0xed, 0xf1, 0xea, 0xee, 0xac, 0x9c, 0xcc, 0x06, 0x78, 0xb3, 0x1d, 0xc3, 0x2e, 0x09, 0x77, 0x48, 0x95, 0x14, 0xc4, 0xf0, 0x90, 0x85, 0xf6, 0x29, 0x8a, 0x96, 0x53, 0xf0, 0x1a, 0xea, 0x40, 0x45, 0xff, 0x58, 0x2e, 0xe8, 0x87, 0xbe, 0x26, 0xae, 0x57, 0x5b, 0x73, 0xee, 0xf7, 0xf3, 0x77, 0x49, 0x21, 0xe3, 0x75, 0xa3, 0xd1, 0x9a, 0xdd, 0xa0, 0xca, 0x31, 0xaa, 0x18, 0x49, 0x88, 0x7c, 0x1f, 0x42, 0xca, 0xc9, 0x67, 0x7f, 0x7a, 0x2f, 0x4e, 0x92, 0x3f, 0x6e, 0x5a, 0x86, 0x8b, 0x38, 0xc0, 0x84, 0xef, 0x18, 0x75, 0x94, 0xdc, 0x9f, 0x7f, 0x04, 0x8f, 0xea, 0x2e, 0x02, 0x95, 0x53, 0x84, 0xab } + +} +, +{ + "RSAES-OAEP Encryption Example 6.6", + /* Message to be encrypted */ + 12, + { 0x50, 0xba, 0x14, 0xbe, 0x84, 0x62, 0x72, 0x02, 0x79, 0xc3, 0x06, 0xba } +, + /* Seed */ + 20, + { 0x0a, 0x24, 0x03, 0x31, 0x2a, 0x41, 0xe3, 0xd5, 0x2f, 0x06, 0x0f, 0xbc, 0x13, 0xa6, 0x7d, 0xe5, 0xcf, 0x76, 0x09, 0xa7 } +, + /* Encryption */ + 129, + { 0x0a, 0x02, 0x6d, 0xda, 0x5f, 0xc8, 0x78, 0x5f, 0x7b, 0xd9, 0xbf, 0x75, 0x32, 0x7b, 0x63, 0xe8, 0x5e, 0x2c, 0x0f, 0xde, 0xe5, 0xda, 0xdb, 0x65, 0xeb, 0xdc, 0xac, 0x9a, 0xe1, 0xde, 0x95, 0xc9, 0x2c, 0x67, 0x2a, 0xb4, 0x33, 0xaa, 0x7a, 0x8e, 0x69, 0xce, 0x6a, 0x6d, 0x88, 0x97, 0xfa, 0xc4, 0xac, 0x4a, 0x54, 0xde, 0x84, 0x1a, 0xe5, 0xe5, 0xbb, 0xce, 0x76, 0x87, 0x87, 0x9d, 0x79, 0x63, 0x4c, 0xea, 0x7a, 0x30, 0x68, 0x40, 0x65, 0xc7, 0x14, 0xd5, 0x24, 0x09, 0xb9, 0x28, 0x25, 0x6b, 0xbf, 0x53, 0xea, 0xbc, 0xd5, 0x23, 0x1e, 0xb7, 0x25, 0x95, 0x04, 0x53, 0x73, 0x99, 0xbd, 0x29, 0x16, 0x4b, 0x72, 0x6d, 0x33, 0xa4, 0x6d, 0xa7, 0x01, 0x36, 0x0a, 0x41, 0x68, 0xa0, 0x91, 0xcc, 0xab, 0x72, 0xd4, 0x4a, 0x62, 0xfe, 0xd2, 0x46, 0xc0, 0xff, 0xea, 0x5b, 0x13, 0x48, 0xab, 0x54, 0x70 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 7: A 1030-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x31, 0x11, 0x79, 0xf0, 0xbc, 0xfc, 0x9b, 0x9d, 0x3c, 0xa3, 0x15, 0xd0, 0x0e, 0xf3, 0x0d, 0x7b, 0xdd, 0x3a, 0x2c, 0xfa, 0xe9, 0x91, 0x1b, 0xfe, 0xdc, 0xb9, 0x48, 0xb3, 0xa4, 0x78, 0x2d, 0x07, 0x32, 0xb6, 0xab, 0x44, 0xaa, 0x4b, 0xf0, 0x37, 0x41, 0xa6, 0x44, 0xdc, 0x01, 0xbe, 0xc3, 0xe6, 0x9b, 0x01, 0xa0, 0x33, 0xe6, 0x75, 0xd8, 0xac, 0xd7, 0xc4, 0x92, 0x5c, 0x6b, 0x1a, 0xec, 0x31, 0x19, 0x05, 0x1d, 0xfd, 0x89, 0x76, 0x2d, 0x21, 0x5d, 0x45, 0x47, 0x5f, 0xfc, 0xb5, 0x9f, 0x90, 0x81, 0x48, 0x62, 0x3f, 0x37, 0x17, 0x71, 0x56, 0xf6, 0xae, 0x86, 0xdd, 0x7a, 0x7c, 0x5f, 0x43, 0xdc, 0x1e, 0x1f, 0x90, 0x82, 0x54, 0x05, 0x8a, 0x28, 0x4a, 0x5f, 0x06, 0xc0, 0x02, 0x17, 0x93, 0xa8, 0x7f, 0x1a, 0xc5, 0xfe, 0xff, 0x7d, 0xca, 0xee, 0x69, 0xc5, 0xe5, 0x1a, 0x37, 0x89, 0xe3, 0x73 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 129, + { 0x07, 0x0c, 0xfc, 0xff, 0x2f, 0xeb, 0x82, 0x76, 0xe2, 0x74, 0x32, 0xc4, 0x5d, 0xfe, 0xe4, 0x8f, 0x49, 0xb7, 0x91, 0x7d, 0x65, 0x30, 0xe1, 0xf0, 0xca, 0x34, 0x60, 0xf3, 0x2e, 0x02, 0x76, 0x17, 0x44, 0x87, 0xc5, 0x6e, 0x22, 0xa4, 0x5d, 0x25, 0x00, 0xd7, 0x77, 0x54, 0x95, 0x21, 0x9d, 0x7d, 0x16, 0x5a, 0x9c, 0xf3, 0xbd, 0x92, 0xc3, 0x2a, 0xf9, 0xa9, 0x8d, 0x8d, 0xc9, 0xcc, 0x29, 0x68, 0x00, 0xad, 0xc9, 0x4a, 0x0a, 0x54, 0xfb, 0x40, 0xf3, 0x42, 0x91, 0xbf, 0x84, 0xee, 0x8e, 0xa1, 0x2b, 0x6f, 0x10, 0x93, 0x59, 0xc6, 0xd3, 0x54, 0x2a, 0x50, 0xf9, 0xc7, 0x67, 0xf5, 0xcf, 0xff, 0x05, 0xa6, 0x81, 0xc2, 0xe6, 0x56, 0xfb, 0x77, 0xca, 0xaa, 0xdb, 0x4b, 0xe9, 0x46, 0x8d, 0x8a, 0xbc, 0xd4, 0xdf, 0x98, 0xf5, 0x8e, 0x86, 0xd2, 0x05, 0x3f, 0xa1, 0x34, 0x9f, 0x74, 0x8e, 0x21, 0xb1 } +, + /* Prime p */ + 65, + { 0x07, 0x49, 0x26, 0x2c, 0x11, 0x1c, 0xd4, 0x70, 0xec, 0x25, 0x66, 0xe6, 0xb3, 0x73, 0x2f, 0xc0, 0x93, 0x29, 0x46, 0x9a, 0xa1, 0x90, 0x71, 0xd3, 0xb9, 0xc0, 0x19, 0x06, 0x51, 0x4c, 0x6f, 0x1d, 0x26, 0xba, 0xa1, 0x4b, 0xea, 0xb0, 0x97, 0x1c, 0x8b, 0x7e, 0x61, 0x1a, 0x4f, 0x79, 0x00, 0x9d, 0x6f, 0xea, 0x77, 0x69, 0x28, 0xca, 0x25, 0x28, 0x5b, 0x0d, 0xe3, 0x64, 0x3d, 0x1a, 0x3f, 0x8c, 0x71 } +, + /* Prime q */ + 65, + { 0x06, 0xbc, 0x1e, 0x50, 0xe9, 0x6c, 0x02, 0xbf, 0x63, 0x6e, 0x9e, 0xea, 0x8b, 0x89, 0x9b, 0xbe, 0xbf, 0x76, 0x51, 0xde, 0x77, 0xdd, 0x47, 0x4c, 0x3e, 0x9b, 0xc2, 0x3b, 0xad, 0x81, 0x82, 0xb6, 0x19, 0x04, 0xc7, 0xd9, 0x7d, 0xfb, 0xeb, 0xfb, 0x1e, 0x00, 0x10, 0x88, 0x78, 0xb6, 0xe6, 0x7e, 0x41, 0x53, 0x91, 0xd6, 0x79, 0x42, 0xc2, 0xb2, 0xbf, 0x9b, 0x44, 0x35, 0xf8, 0x8b, 0x0c, 0xb0, 0x23 } +, + /* p's CRT exponent dP */ + 65, + { 0x03, 0xbc, 0x7e, 0xa7, 0xf0, 0xaa, 0xb1, 0x43, 0xab, 0xc6, 0xce, 0x8b, 0x97, 0x11, 0x86, 0x36, 0xa3, 0x01, 0x72, 0xe4, 0xcf, 0xe0, 0x2c, 0x8f, 0xa0, 0xdd, 0xa3, 0xb7, 0xba, 0xaf, 0x90, 0xf8, 0x09, 0x29, 0x82, 0x98, 0x55, 0x25, 0xf4, 0x88, 0xbd, 0xfc, 0xb4, 0xbd, 0x72, 0x6e, 0x22, 0x63, 0x9a, 0xc6, 0x4a, 0x30, 0x92, 0xab, 0x7f, 0xfc, 0xbf, 0x1d, 0x53, 0x34, 0xcf, 0xa5, 0x0b, 0x5b, 0xf1 } +, + /* q's CRT exponent dQ */ + 65, + { 0x02, 0x62, 0xa6, 0xaa, 0x29, 0xc2, 0xa3, 0xc6, 0x7d, 0xc5, 0x34, 0x6c, 0x06, 0x38, 0x1a, 0xfd, 0x98, 0x7a, 0xa3, 0xcc, 0x93, 0xcf, 0xbf, 0xec, 0xf5, 0x4f, 0xdd, 0x9f, 0x9d, 0x78, 0x7d, 0x7f, 0x59, 0xa5, 0x23, 0xd3, 0x98, 0x97, 0x9d, 0xa1, 0x37, 0xa2, 0xf6, 0x38, 0x1f, 0xe9, 0x48, 0x01, 0xf7, 0xc9, 0x4d, 0xa2, 0x15, 0x18, 0xdc, 0x34, 0xcb, 0x40, 0x87, 0x0c, 0x46, 0x97, 0x99, 0x4a, 0xd9 } +, + /* CRT coefficient qInv */ + 64, + { 0x64, 0x9d, 0x4c, 0x17, 0xb6, 0xee, 0x17, 0x21, 0xe7, 0x72, 0xd0, 0x38, 0x9a, 0x55, 0x9c, 0x3d, 0x3c, 0xdf, 0x95, 0x50, 0xd4, 0x57, 0xc4, 0x6b, 0x03, 0x7b, 0x74, 0x64, 0x1b, 0x1d, 0x52, 0x16, 0x6a, 0xf8, 0xa2, 0x13, 0xc8, 0x39, 0x62, 0x06, 0xcd, 0xfb, 0xa4, 0x42, 0x2f, 0x18, 0xd6, 0xf6, 0x1d, 0xbc, 0xb5, 0xd2, 0x14, 0xc9, 0x71, 0xbf, 0x48, 0x2a, 0xeb, 0x97, 0x6a, 0x73, 0x70, 0xc2 } + +} +, +{{ + "RSAES-OAEP Encryption Example 7.1", + /* Message to be encrypted */ + 4, + { 0x47, 0xaa, 0xe9, 0x09 } +, + /* Seed */ + 20, + { 0x43, 0xdd, 0x09, 0xa0, 0x7f, 0xf4, 0xca, 0xc7, 0x1c, 0xaa, 0x46, 0x32, 0xee, 0x5e, 0x1c, 0x1d, 0xae, 0xe4, 0xcd, 0x8f } +, + /* Encryption */ + 129, + { 0x16, 0x88, 0xe4, 0xce, 0x77, 0x94, 0xbb, 0xa6, 0xcb, 0x70, 0x14, 0x16, 0x9e, 0xcd, 0x55, 0x9c, 0xed, 0xe2, 0xa3, 0x0b, 0x56, 0xa5, 0x2b, 0x68, 0xd9, 0xfe, 0x18, 0xcf, 0x19, 0x73, 0xef, 0x97, 0xb2, 0xa0, 0x31, 0x53, 0x95, 0x1c, 0x75, 0x5f, 0x62, 0x94, 0xaa, 0x49, 0xad, 0xbd, 0xb5, 0x58, 0x45, 0xab, 0x68, 0x75, 0xfb, 0x39, 0x86, 0xc9, 0x3e, 0xcf, 0x92, 0x79, 0x62, 0x84, 0x0d, 0x28, 0x2f, 0x9e, 0x54, 0xce, 0x8b, 0x69, 0x0f, 0x7c, 0x0c, 0xb8, 0xbb, 0xd7, 0x34, 0x40, 0xd9, 0x57, 0x1d, 0x1b, 0x16, 0xcd, 0x92, 0x60, 0xf9, 0xea, 0xb4, 0x78, 0x3c, 0xc4, 0x82, 0xe5, 0x22, 0x3d, 0xc6, 0x09, 0x73, 0x87, 0x17, 0x83, 0xec, 0x27, 0xb0, 0xae, 0x0f, 0xd4, 0x77, 0x32, 0xcb, 0xc2, 0x86, 0xa1, 0x73, 0xfc, 0x92, 0xb0, 0x0f, 0xb4, 0xba, 0x68, 0x24, 0x64, 0x7c, 0xd9, 0x3c, 0x85, 0xc1 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 7.2", + /* Message to be encrypted */ + 31, + { 0x1d, 0x9b, 0x2e, 0x22, 0x23, 0xd9, 0xbc, 0x13, 0xbf, 0xb9, 0xf1, 0x62, 0xce, 0x73, 0x5d, 0xb4, 0x8b, 0xa7, 0xc6, 0x8f, 0x68, 0x22, 0xa0, 0xa1, 0xa7, 0xb6, 0xae, 0x16, 0x58, 0x34, 0xe7 } +, + /* Seed */ + 20, + { 0x3a, 0x9c, 0x3c, 0xec, 0x7b, 0x84, 0xf9, 0xbd, 0x3a, 0xde, 0xcb, 0xc6, 0x73, 0xec, 0x99, 0xd5, 0x4b, 0x22, 0xbc, 0x9b } +, + /* Encryption */ + 129, + { 0x10, 0x52, 0xed, 0x39, 0x7b, 0x2e, 0x01, 0xe1, 0xd0, 0xee, 0x1c, 0x50, 0xbf, 0x24, 0x36, 0x3f, 0x95, 0xe5, 0x04, 0xf4, 0xa0, 0x34, 0x34, 0xa0, 0x8f, 0xd8, 0x22, 0x57, 0x4e, 0xd6, 0xb9, 0x73, 0x6e, 0xdb, 0xb5, 0xf3, 0x90, 0xdb, 0x10, 0x32, 0x14, 0x79, 0xa8, 0xa1, 0x39, 0x35, 0x0e, 0x2b, 0xd4, 0x97, 0x7c, 0x37, 0x78, 0xef, 0x33, 0x1f, 0x3e, 0x78, 0xae, 0x11, 0x8b, 0x26, 0x84, 0x51, 0xf2, 0x0a, 0x2f, 0x01, 0xd4, 0x71, 0xf5, 0xd5, 0x3c, 0x56, 0x69, 0x37, 0x17, 0x1b, 0x2d, 0xbc, 0x2d, 0x4b, 0xde, 0x45, 0x9a, 0x57, 0x99, 0xf0, 0x37, 0x2d, 0x65, 0x74, 0x23, 0x9b, 0x23, 0x23, 0xd2, 0x45, 0xd0, 0xbb, 0x81, 0xc2, 0x86, 0xb6, 0x3c, 0x89, 0xa3, 0x61, 0x01, 0x73, 0x37, 0xe4, 0x90, 0x2f, 0x88, 0xa4, 0x67, 0xf4, 0xc7, 0xf2, 0x44, 0xbf, 0xd5, 0xab, 0x46, 0x43, 0x7f, 0xf3, 0xb6 } + +} +, +{ + "RSAES-OAEP Encryption Example 7.3", + /* Message to be encrypted */ + 3, + { 0xd9, 0x76, 0xfc } +, + /* Seed */ + 20, + { 0x76, 0xa7, 0x5e, 0x5b, 0x61, 0x57, 0xa5, 0x56, 0xcf, 0x88, 0x84, 0xbb, 0x2e, 0x45, 0xc2, 0x93, 0xdd, 0x54, 0x5c, 0xf5 } +, + /* Encryption */ + 129, + { 0x21, 0x55, 0xcd, 0x84, 0x3f, 0xf2, 0x4a, 0x4e, 0xe8, 0xba, 0xdb, 0x76, 0x94, 0x26, 0x00, 0x28, 0xa4, 0x90, 0x81, 0x3b, 0xa8, 0xb3, 0x69, 0xa4, 0xcb, 0xf1, 0x06, 0xec, 0x14, 0x8e, 0x52, 0x98, 0x70, 0x7f, 0x59, 0x65, 0xbe, 0x7d, 0x10, 0x1c, 0x10, 0x49, 0xea, 0x85, 0x84, 0xc2, 0x4c, 0xd6, 0x34, 0x55, 0xad, 0x9c, 0x10, 0x4d, 0x68, 0x62, 0x82, 0xd3, 0xfb, 0x80, 0x3a, 0x4c, 0x11, 0xc1, 0xc2, 0xe9, 0xb9, 0x1c, 0x71, 0x78, 0x80, 0x1d, 0x1b, 0x66, 0x40, 0xf0, 0x03, 0xf5, 0x72, 0x8d, 0xf0, 0x07, 0xb8, 0xa4, 0xcc, 0xc9, 0x2b, 0xce, 0x05, 0xe4, 0x1a, 0x27, 0x27, 0x8d, 0x7c, 0x85, 0x01, 0x8c, 0x52, 0x41, 0x43, 0x13, 0xa5, 0x07, 0x77, 0x89, 0x00, 0x1d, 0x4f, 0x01, 0x91, 0x0b, 0x72, 0xaa, 0xd0, 0x5d, 0x22, 0x0a, 0xa1, 0x4a, 0x58, 0x73, 0x3a, 0x74, 0x89, 0xbc, 0x54, 0x55, 0x6b } + +} +, +{ + "RSAES-OAEP Encryption Example 7.4", + /* Message to be encrypted */ + 62, + { 0xd4, 0x73, 0x86, 0x23, 0xdf, 0x22, 0x3a, 0xa4, 0x38, 0x43, 0xdf, 0x84, 0x67, 0x53, 0x4c, 0x41, 0xd0, 0x13, 0xe0, 0xc8, 0x03, 0xc6, 0x24, 0xe2, 0x63, 0x66, 0x6b, 0x23, 0x9b, 0xde, 0x40, 0xa5, 0xf2, 0x9a, 0xeb, 0x8d, 0xe7, 0x9e, 0x3d, 0xaa, 0x61, 0xdd, 0x03, 0x70, 0xf4, 0x9b, 0xd4, 0xb0, 0x13, 0x83, 0x4b, 0x98, 0x21, 0x2a, 0xef, 0x6b, 0x1c, 0x5e, 0xe3, 0x73, 0xb3, 0xcb } +, + /* Seed */ + 20, + { 0x78, 0x66, 0x31, 0x4a, 0x6a, 0xd6, 0xf2, 0xb2, 0x50, 0xa3, 0x59, 0x41, 0xdb, 0x28, 0xf5, 0x86, 0x4b, 0x58, 0x58, 0x59 } +, + /* Encryption */ + 129, + { 0x0a, 0xb1, 0x4c, 0x37, 0x3a, 0xeb, 0x7d, 0x43, 0x28, 0xd0, 0xaa, 0xad, 0x8c, 0x09, 0x4d, 0x88, 0xb9, 0xeb, 0x09, 0x8b, 0x95, 0xf2, 0x10, 0x54, 0xa2, 0x90, 0x82, 0x52, 0x2b, 0xe7, 0xc2, 0x7a, 0x31, 0x28, 0x78, 0xb6, 0x37, 0x91, 0x7e, 0x3d, 0x81, 0x9e, 0x6c, 0x3c, 0x56, 0x8d, 0xb5, 0xd8, 0x43, 0x80, 0x2b, 0x06, 0xd5, 0x1d, 0x9e, 0x98, 0xa2, 0xbe, 0x0b, 0xf4, 0x0c, 0x03, 0x14, 0x23, 0xb0, 0x0e, 0xdf, 0xbf, 0xf8, 0x32, 0x0e, 0xfb, 0x91, 0x71, 0xbd, 0x20, 0x44, 0x65, 0x3a, 0x4c, 0xb9, 0xc5, 0x12, 0x2f, 0x6c, 0x65, 0xe8, 0x3c, 0xda, 0x2e, 0xc3, 0xc1, 0x26, 0x02, 0x7a, 0x9c, 0x1a, 0x56, 0xba, 0x87, 0x4d, 0x0f, 0xea, 0x23, 0xf3, 0x80, 0xb8, 0x2c, 0xf2, 0x40, 0xb8, 0xcf, 0x54, 0x00, 0x04, 0x75, 0x8c, 0x4c, 0x77, 0xd9, 0x34, 0x15, 0x7a, 0x74, 0xf3, 0xfc, 0x12, 0xbf, 0xac } + +} +, +{ + "RSAES-OAEP Encryption Example 7.5", + /* Message to be encrypted */ + 16, + { 0xbb, 0x47, 0x23, 0x1c, 0xa5, 0xea, 0x1d, 0x3a, 0xd4, 0x6c, 0x99, 0x34, 0x5d, 0x9a, 0x8a, 0x61 } +, + /* Seed */ + 20, + { 0xb2, 0x16, 0x6e, 0xd4, 0x72, 0xd5, 0x8d, 0xb1, 0x0c, 0xab, 0x2c, 0x6b, 0x00, 0x0c, 0xcc, 0xf1, 0x0a, 0x7d, 0xc5, 0x09 } +, + /* Encryption */ + 129, + { 0x02, 0x83, 0x87, 0xa3, 0x18, 0x27, 0x74, 0x34, 0x79, 0x8b, 0x4d, 0x97, 0xf4, 0x60, 0x06, 0x8d, 0xf5, 0x29, 0x8f, 0xab, 0xa5, 0x04, 0x1b, 0xa1, 0x17, 0x61, 0xa1, 0xcb, 0x73, 0x16, 0xb2, 0x41, 0x84, 0x11, 0x4e, 0xc5, 0x00, 0x25, 0x7e, 0x25, 0x89, 0xed, 0x3b, 0x60, 0x7a, 0x1e, 0xbb, 0xe9, 0x7a, 0x6c, 0xc2, 0xe0, 0x2b, 0xf1, 0xb6, 0x81, 0xf4, 0x23, 0x12, 0xa3, 0x3b, 0x7a, 0x77, 0xd8, 0xe7, 0x85, 0x5c, 0x4a, 0x6d, 0xe0, 0x3e, 0x3c, 0x04, 0x64, 0x3f, 0x78, 0x6b, 0x91, 0xa2, 0x64, 0xa0, 0xd6, 0x80, 0x5e, 0x2c, 0xea, 0x91, 0xe6, 0x81, 0x77, 0xeb, 0x7a, 0x64, 0xd9, 0x25, 0x5e, 0x4f, 0x27, 0xe7, 0x13, 0xb7, 0xcc, 0xec, 0x00, 0xdc, 0x20, 0x0e, 0xbd, 0x21, 0xc2, 0xea, 0x2b, 0xb8, 0x90, 0xfe, 0xae, 0x49, 0x42, 0xdf, 0x94, 0x1d, 0xc3, 0xf9, 0x78, 0x90, 0xed, 0x34, 0x74, 0x78 } + +} +, +{ + "RSAES-OAEP Encryption Example 7.6", + /* Message to be encrypted */ + 18, + { 0x21, 0x84, 0x82, 0x70, 0x95, 0xd3, 0x5c, 0x3f, 0x86, 0xf6, 0x00, 0xe8, 0xe5, 0x97, 0x54, 0x01, 0x32, 0x96 } +, + /* Seed */ + 20, + { 0x52, 0x67, 0x3b, 0xde, 0x2c, 0xa1, 0x66, 0xc2, 0xaa, 0x46, 0x13, 0x1a, 0xc1, 0xdc, 0x80, 0x8d, 0x67, 0xd7, 0xd3, 0xb1 } +, + /* Encryption */ + 129, + { 0x14, 0xc6, 0x78, 0xa9, 0x4a, 0xd6, 0x05, 0x25, 0xef, 0x39, 0xe9, 0x59, 0xb2, 0xf3, 0xba, 0x5c, 0x09, 0x7a, 0x94, 0xff, 0x91, 0x2b, 0x67, 0xdb, 0xac, 0xe8, 0x05, 0x35, 0xc1, 0x87, 0xab, 0xd4, 0x7d, 0x07, 0x54, 0x20, 0xb1, 0x87, 0x21, 0x52, 0xbb, 0xa0, 0x8f, 0x7f, 0xc3, 0x1f, 0x31, 0x3b, 0xbf, 0x92, 0x73, 0xc9, 0x12, 0xfc, 0x4c, 0x01, 0x49, 0xa9, 0xb0, 0xcf, 0xb7, 0x98, 0x07, 0xe3, 0x46, 0xeb, 0x33, 0x20, 0x69, 0x61, 0x1b, 0xec, 0x0f, 0xf9, 0xbc, 0xd1, 0x68, 0xf1, 0xf7, 0xc3, 0x3e, 0x77, 0x31, 0x3c, 0xea, 0x45, 0x4b, 0x94, 0xe2, 0x54, 0x9e, 0xec, 0xf0, 0x02, 0xe2, 0xac, 0xf7, 0xf6, 0xf2, 0xd2, 0x84, 0x5d, 0x4f, 0xe0, 0xaa, 0xb2, 0xe5, 0xa9, 0x2d, 0xdf, 0x68, 0xc4, 0x80, 0xae, 0x11, 0x24, 0x79, 0x35, 0xd1, 0xf6, 0x25, 0x74, 0x84, 0x22, 0x16, 0xae, 0x67, 0x41, 0x15 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 8: A 1031-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x5b, 0xdf, 0x0e, 0x30, 0xd3, 0x21, 0xdd, 0xa5, 0x14, 0x7f, 0x88, 0x24, 0x08, 0xfa, 0x69, 0x19, 0x54, 0x80, 0xdf, 0x8f, 0x80, 0xd3, 0xf6, 0xe8, 0xbf, 0x58, 0x18, 0x50, 0x4f, 0x36, 0x42, 0x7c, 0xa9, 0xb1, 0xf5, 0x54, 0x0b, 0x9c, 0x65, 0xa8, 0xf6, 0x97, 0x4c, 0xf8, 0x44, 0x7a, 0x24, 0x4d, 0x92, 0x80, 0x20, 0x1b, 0xb4, 0x9f, 0xcb, 0xbe, 0x63, 0x78, 0xd1, 0x94, 0x4c, 0xd2, 0x27, 0xe2, 0x30, 0xf9, 0x6e, 0x3d, 0x10, 0xf8, 0x19, 0xdc, 0xef, 0x27, 0x6c, 0x64, 0xa0, 0x0b, 0x2a, 0x4b, 0x67, 0x01, 0xe7, 0xd0, 0x1d, 0xe5, 0xfa, 0xbd, 0xe3, 0xb1, 0xe9, 0xa0, 0xdf, 0x82, 0xf4, 0x63, 0x13, 0x59, 0xcd, 0x22, 0x66, 0x96, 0x47, 0xfb, 0xb1, 0x71, 0x72, 0x46, 0x13, 0x4e, 0xd7, 0xb4, 0x97, 0xcf, 0xff, 0xbd, 0xc4, 0x2b, 0x59, 0xc7, 0x3a, 0x96, 0xed, 0x90, 0x16, 0x62, 0x12, 0xdf, 0xf7 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 129, + { 0x0f, 0x7d, 0x1e, 0x9e, 0x5a, 0xaa, 0x25, 0xfd, 0x13, 0xe4, 0xa0, 0x66, 0x3a, 0xe1, 0x44, 0xe0, 0xd1, 0x5f, 0x5c, 0xd1, 0x8b, 0xcd, 0xb0, 0x9d, 0xf2, 0xcc, 0x7e, 0x64, 0xe3, 0xc5, 0xe9, 0x15, 0xad, 0x62, 0x64, 0x53, 0x04, 0x16, 0x1d, 0x09, 0x8c, 0x71, 0x5b, 0xb7, 0xab, 0x8b, 0xd0, 0x1d, 0x07, 0xea, 0xf3, 0xfe, 0xd7, 0xc7, 0xed, 0x08, 0xaf, 0x2a, 0x8a, 0x62, 0xef, 0x44, 0xab, 0x16, 0xb3, 0x20, 0xe1, 0x4a, 0xf7, 0x2a, 0x48, 0xf9, 0x6a, 0xfe, 0x26, 0x2a, 0x0a, 0xe4, 0xcf, 0x65, 0xe6, 0x35, 0xe9, 0x10, 0x79, 0x0c, 0xd4, 0xee, 0x5c, 0xea, 0x76, 0x8a, 0x4b, 0x26, 0x39, 0xf7, 0xe6, 0xf6, 0x77, 0xb3, 0xf0, 0xbb, 0x6b, 0xe3, 0x2b, 0x75, 0x74, 0x7d, 0x89, 0x09, 0x03, 0x6f, 0x02, 0x64, 0xf5, 0x8d, 0x40, 0x1c, 0xdb, 0xa1, 0x31, 0x71, 0x61, 0x57, 0xa7, 0x5e, 0xcf, 0x63, 0x31 } +, + /* Prime p */ + 65, + { 0x0a, 0x02, 0xef, 0x84, 0x48, 0xd9, 0xfa, 0xd8, 0xbb, 0xd0, 0xd0, 0x04, 0xc8, 0xc2, 0xaa, 0x97, 0x51, 0xef, 0x97, 0x21, 0xc1, 0xb0, 0xd0, 0x32, 0x36, 0xa5, 0x4b, 0x0d, 0xf9, 0x47, 0xcb, 0xae, 0xd5, 0xa2, 0x55, 0xee, 0x9e, 0x8e, 0x20, 0xd4, 0x91, 0xea, 0x17, 0x23, 0xfe, 0x09, 0x47, 0x04, 0xa9, 0x76, 0x2e, 0x88, 0xaf, 0xd1, 0x6e, 0xbb, 0x59, 0x94, 0x41, 0x2c, 0xa9, 0x66, 0xdc, 0x4f, 0x9f } +, + /* Prime q */ + 65, + { 0x09, 0x2d, 0x36, 0x2e, 0x7e, 0xd3, 0xa0, 0xbf, 0xd9, 0xe9, 0xfd, 0x0e, 0x6c, 0x03, 0x01, 0xb6, 0xdf, 0x29, 0x15, 0x9c, 0xf5, 0x0c, 0xc8, 0x3b, 0x9b, 0x0c, 0xf4, 0xd6, 0xee, 0xa7, 0x1a, 0x61, 0xe0, 0x02, 0xb4, 0x6e, 0x0a, 0xe9, 0xf2, 0xde, 0x62, 0xd2, 0x5b, 0x5d, 0x74, 0x52, 0xd4, 0x98, 0xb8, 0x1c, 0x9a, 0xc6, 0xfc, 0x58, 0x59, 0x3d, 0x4c, 0x3f, 0xb4, 0xf5, 0xd7, 0x2d, 0xfb, 0xb0, 0xa9 } +, + /* p's CRT exponent dP */ + 65, + { 0x07, 0xc7, 0x14, 0x10, 0xaf, 0x10, 0x39, 0x62, 0xdb, 0x36, 0x74, 0x04, 0xe3, 0x7a, 0xe8, 0x50, 0xba, 0xa4, 0xe9, 0xc2, 0x9d, 0xd9, 0x21, 0x45, 0x81, 0x52, 0x94, 0xa6, 0x7c, 0x7d, 0x1c, 0x6d, 0xed, 0x26, 0x3a, 0xa0, 0x30, 0xa9, 0xb6, 0x33, 0xae, 0x50, 0x30, 0x3e, 0x14, 0x03, 0x5d, 0x1a, 0xf0, 0x14, 0x12, 0x3e, 0xba, 0x68, 0x78, 0x20, 0x30, 0x8d, 0x8e, 0xbc, 0x85, 0xb6, 0x95, 0x7d, 0x7d } +, + /* q's CRT exponent dQ */ + 64, + { 0xae, 0x2c, 0x75, 0x38, 0x0c, 0x02, 0xc0, 0x16, 0xad, 0x05, 0x89, 0x1b, 0x33, 0x01, 0xde, 0x88, 0x1f, 0x28, 0xae, 0x11, 0x71, 0x18, 0x2b, 0x6b, 0x2c, 0x83, 0xbe, 0xa7, 0xc5, 0x15, 0xec, 0xa9, 0xca, 0x29, 0x8c, 0x7b, 0x1c, 0xab, 0x58, 0x17, 0xa5, 0x97, 0x06, 0x8f, 0xc8, 0x50, 0x60, 0xde, 0x4d, 0xa8, 0xa0, 0x16, 0x37, 0x8a, 0xae, 0x43, 0xc7, 0xf9, 0x67, 0xbc, 0xc3, 0x79, 0x04, 0xb9 } +, + /* CRT coefficient qInv */ + 65, + { 0x05, 0x98, 0xd1, 0x05, 0x9e, 0x3a, 0xda, 0x4f, 0x63, 0x20, 0x75, 0x2c, 0x09, 0xd8, 0x05, 0xff, 0x7d, 0x1f, 0x1a, 0xe0, 0xd0, 0x17, 0xae, 0xee, 0xe9, 0xce, 0xfa, 0x0d, 0x7d, 0xd7, 0xff, 0x77, 0x5e, 0x44, 0xb5, 0x78, 0x32, 0x2f, 0x64, 0x05, 0xd6, 0x21, 0x1d, 0xa1, 0x95, 0x19, 0x66, 0x6a, 0xa8, 0x7f, 0xdc, 0x4c, 0xd8, 0xc8, 0x8f, 0x6b, 0x6e, 0x3d, 0x67, 0xe9, 0x61, 0xdc, 0xbb, 0xa3, 0xd0 } + +} +, +{{ + "RSAES-OAEP Encryption Example 8.1", + /* Message to be encrypted */ + 54, + { 0x05, 0x0b, 0x75, 0x5e, 0x5e, 0x68, 0x80, 0xf7, 0xb9, 0xe9, 0xd6, 0x92, 0xa7, 0x4c, 0x37, 0xaa, 0xe4, 0x49, 0xb3, 0x1b, 0xfe, 0xa6, 0xde, 0xff, 0x83, 0x74, 0x7a, 0x89, 0x7f, 0x6c, 0x2c, 0x82, 0x5b, 0xb1, 0xad, 0xbf, 0x85, 0x0a, 0x3c, 0x96, 0x99, 0x4b, 0x5d, 0xe5, 0xb3, 0x3c, 0xbc, 0x7d, 0x4a, 0x17, 0x91, 0x3a, 0x79, 0x67 } +, + /* Seed */ + 20, + { 0x77, 0x06, 0xff, 0xca, 0x1e, 0xcf, 0xb1, 0xeb, 0xee, 0x2a, 0x55, 0xe5, 0xc6, 0xe2, 0x4c, 0xd2, 0x79, 0x7a, 0x41, 0x25 } +, + /* Encryption */ + 129, + { 0x09, 0xb3, 0x68, 0x3d, 0x8a, 0x2e, 0xb0, 0xfb, 0x29, 0x5b, 0x62, 0xed, 0x1f, 0xb9, 0x29, 0x0b, 0x71, 0x44, 0x57, 0xb7, 0x82, 0x53, 0x19, 0xf4, 0x64, 0x78, 0x72, 0xaf, 0x88, 0x9b, 0x30, 0x40, 0x94, 0x72, 0x02, 0x0a, 0xd1, 0x29, 0x12, 0xbf, 0x19, 0xb1, 0x1d, 0x48, 0x19, 0xf4, 0x96, 0x14, 0x82, 0x4f, 0xfd, 0x84, 0xd0, 0x9c, 0x0a, 0x17, 0xe7, 0xd1, 0x73, 0x09, 0xd1, 0x29, 0x19, 0x79, 0x04, 0x10, 0xaa, 0x29, 0x95, 0x69, 0x9f, 0x6a, 0x86, 0xdb, 0xe3, 0x24, 0x2b, 0x5a, 0xcc, 0x23, 0xaf, 0x45, 0x69, 0x10, 0x80, 0xd6, 0xb1, 0xae, 0x81, 0x0f, 0xb3, 0xe3, 0x05, 0x70, 0x87, 0xf0, 0x97, 0x00, 0x92, 0xce, 0x00, 0xbe, 0x95, 0x62, 0xff, 0x40, 0x53, 0xb6, 0x26, 0x2c, 0xe0, 0xca, 0xa9, 0x3e, 0x13, 0x72, 0x3d, 0x2e, 0x3a, 0x5b, 0xa0, 0x75, 0xd4, 0x5f, 0x0d, 0x61, 0xb5, 0x4b, 0x61 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 8.2", + /* Message to be encrypted */ + 63, + { 0x4e, 0xb6, 0x8d, 0xcd, 0x93, 0xca, 0x9b, 0x19, 0xdf, 0x11, 0x1b, 0xd4, 0x36, 0x08, 0xf5, 0x57, 0x02, 0x6f, 0xe4, 0xaa, 0x1d, 0x5c, 0xfa, 0xc2, 0x27, 0xa3, 0xeb, 0x5a, 0xb9, 0x54, 0x8c, 0x18, 0xa0, 0x6d, 0xde, 0xd2, 0x3f, 0x81, 0x82, 0x59, 0x86, 0xb2, 0xfc, 0xd7, 0x11, 0x09, 0xec, 0xef, 0x7e, 0xff, 0x88, 0x87, 0x3f, 0x07, 0x5c, 0x2a, 0xa0, 0xc4, 0x69, 0xf6, 0x9c, 0x92, 0xbc } +, + /* Seed */ + 20, + { 0xa3, 0x71, 0x7d, 0xa1, 0x43, 0xb4, 0xdc, 0xff, 0xbc, 0x74, 0x26, 0x65, 0xa8, 0xfa, 0x95, 0x05, 0x85, 0x54, 0x83, 0x43 } +, + /* Encryption */ + 129, + { 0x2e, 0xcf, 0x15, 0xc9, 0x7c, 0x5a, 0x15, 0xb1, 0x47, 0x6a, 0xe9, 0x86, 0xb3, 0x71, 0xb5, 0x7a, 0x24, 0x28, 0x4f, 0x4a, 0x16, 0x2a, 0x8d, 0x0c, 0x81, 0x82, 0xe7, 0x90, 0x5e, 0x79, 0x22, 0x56, 0xf1, 0x81, 0x2b, 0xa5, 0xf8, 0x3f, 0x1f, 0x7a, 0x13, 0x0e, 0x42, 0xdc, 0xc0, 0x22, 0x32, 0x84, 0x4e, 0xdc, 0x14, 0xa3, 0x1a, 0x68, 0xee, 0x97, 0xae, 0x56, 0x4a, 0x38, 0x3a, 0x34, 0x11, 0x65, 0x64, 0x24, 0xc5, 0xf6, 0x2d, 0xdb, 0x64, 0x60, 0x93, 0xc3, 0x67, 0xbe, 0x1f, 0xcd, 0xa4, 0x26, 0xcf, 0x00, 0xa0, 0x6d, 0x8a, 0xcb, 0x7e, 0x57, 0x77, 0x6f, 0xbb, 0xd8, 0x55, 0xac, 0x3d, 0xf5, 0x06, 0xfc, 0x16, 0xb1, 0xd7, 0xc3, 0xf2, 0x11, 0x0f, 0x3d, 0x80, 0x68, 0xe9, 0x1e, 0x18, 0x63, 0x63, 0x83, 0x1c, 0x84, 0x09, 0x68, 0x0d, 0x8d, 0xa9, 0xec, 0xd8, 0xcf, 0x1f, 0xa2, 0x0e, 0xe3, 0x9d } + +} +, +{ + "RSAES-OAEP Encryption Example 8.3", + /* Message to be encrypted */ + 12, + { 0x86, 0x04, 0xac, 0x56, 0x32, 0x8c, 0x1a, 0xb5, 0xad, 0x91, 0x78, 0x61 } +, + /* Seed */ + 20, + { 0xee, 0x06, 0x20, 0x90, 0x73, 0xcc, 0xa0, 0x26, 0xbb, 0x26, 0x4e, 0x51, 0x85, 0xbf, 0x8c, 0x68, 0xb7, 0x73, 0x9f, 0x86 } +, + /* Encryption */ + 129, + { 0x4b, 0xc8, 0x91, 0x30, 0xa5, 0xb2, 0xda, 0xbb, 0x7c, 0x2f, 0xcf, 0x90, 0xeb, 0x5d, 0x0e, 0xaf, 0x9e, 0x68, 0x1b, 0x71, 0x46, 0xa3, 0x8f, 0x31, 0x73, 0xa3, 0xd9, 0xcf, 0xec, 0x52, 0xea, 0x9e, 0x0a, 0x41, 0x93, 0x2e, 0x64, 0x8a, 0x9d, 0x69, 0x34, 0x4c, 0x50, 0xda, 0x76, 0x3f, 0x51, 0xa0, 0x3c, 0x95, 0x76, 0x21, 0x31, 0xe8, 0x05, 0x22, 0x54, 0xdc, 0xd2, 0x24, 0x8c, 0xba, 0x40, 0xfd, 0x31, 0x66, 0x77, 0x86, 0xce, 0x05, 0xa2, 0xb7, 0xb5, 0x31, 0xac, 0x9d, 0xac, 0x9e, 0xd5, 0x84, 0xa5, 0x9b, 0x67, 0x7c, 0x1a, 0x8a, 0xed, 0x8c, 0x5d, 0x15, 0xd6, 0x8c, 0x05, 0x56, 0x9e, 0x2b, 0xe7, 0x80, 0xbf, 0x7d, 0xb6, 0x38, 0xfd, 0x2b, 0xfd, 0x2a, 0x85, 0xab, 0x27, 0x68, 0x60, 0xf3, 0x77, 0x73, 0x38, 0xfc, 0xa9, 0x89, 0xff, 0xd7, 0x43, 0xd1, 0x3e, 0xe0, 0x8e, 0x0c, 0xa9, 0x89, 0x3f } + +} +, +{ + "RSAES-OAEP Encryption Example 8.4", + /* Message to be encrypted */ + 34, + { 0xfd, 0xda, 0x5f, 0xbf, 0x6e, 0xc3, 0x61, 0xa9, 0xd9, 0xa4, 0xac, 0x68, 0xaf, 0x21, 0x6a, 0x06, 0x86, 0xf4, 0x38, 0xb1, 0xe0, 0xe5, 0xc3, 0x6b, 0x95, 0x5f, 0x74, 0xe1, 0x07, 0xf3, 0x9c, 0x0d, 0xdd, 0xcc } +, + /* Seed */ + 20, + { 0x99, 0x0a, 0xd5, 0x73, 0xdc, 0x48, 0xa9, 0x73, 0x23, 0x5b, 0x6d, 0x82, 0x54, 0x36, 0x18, 0xf2, 0xe9, 0x55, 0x10, 0x5d } +, + /* Encryption */ + 129, + { 0x2e, 0x45, 0x68, 0x47, 0xd8, 0xfc, 0x36, 0xff, 0x01, 0x47, 0xd6, 0x99, 0x35, 0x94, 0xb9, 0x39, 0x72, 0x27, 0xd5, 0x77, 0x75, 0x2c, 0x79, 0xd0, 0xf9, 0x04, 0xfc, 0xb0, 0x39, 0xd4, 0xd8, 0x12, 0xfe, 0xa6, 0x05, 0xa7, 0xb5, 0x74, 0xdd, 0x82, 0xca, 0x78, 0x6f, 0x93, 0x75, 0x23, 0x48, 0x43, 0x8e, 0xe9, 0xf5, 0xb5, 0x45, 0x49, 0x85, 0xd5, 0xf0, 0xe1, 0x69, 0x9e, 0x3e, 0x7a, 0xd1, 0x75, 0xa3, 0x2e, 0x15, 0xf0, 0x3d, 0xeb, 0x04, 0x2a, 0xb9, 0xfe, 0x1d, 0xd9, 0xdb, 0x1b, 0xb8, 0x6f, 0x8c, 0x08, 0x9c, 0xcb, 0x45, 0xe7, 0xef, 0x0c, 0x5e, 0xe7, 0xca, 0x9b, 0x72, 0x90, 0xca, 0x6b, 0x15, 0xbe, 0xd4, 0x70, 0x39, 0x78, 0x8a, 0x8a, 0x93, 0xff, 0x83, 0xe0, 0xe8, 0xd6, 0x24, 0x4c, 0x71, 0x00, 0x63, 0x62, 0xde, 0xef, 0x69, 0xb6, 0xf4, 0x16, 0xfb, 0x3c, 0x68, 0x43, 0x83, 0xfb, 0xd0 } + +} +, +{ + "RSAES-OAEP Encryption Example 8.5", + /* Message to be encrypted */ + 13, + { 0x4a, 0x5f, 0x49, 0x14, 0xbe, 0xe2, 0x5d, 0xe3, 0xc6, 0x93, 0x41, 0xde, 0x07 } +, + /* Seed */ + 20, + { 0xec, 0xc6, 0x3b, 0x28, 0xf0, 0x75, 0x6f, 0x22, 0xf5, 0x2a, 0xc8, 0xe6, 0xec, 0x12, 0x51, 0xa6, 0xec, 0x30, 0x47, 0x18 } +, + /* Encryption */ + 129, + { 0x1f, 0xb9, 0x35, 0x6f, 0xd5, 0xc4, 0xb1, 0x79, 0x6d, 0xb2, 0xeb, 0xf7, 0xd0, 0xd3, 0x93, 0xcc, 0x81, 0x0a, 0xdf, 0x61, 0x45, 0xde, 0xfc, 0x2f, 0xce, 0x71, 0x4f, 0x79, 0xd9, 0x38, 0x00, 0xd5, 0xe2, 0xac, 0x21, 0x1e, 0xa8, 0xbb, 0xec, 0xca, 0x4b, 0x65, 0x4b, 0x94, 0xc3, 0xb1, 0x8b, 0x30, 0xdd, 0x57, 0x6c, 0xe3, 0x4d, 0xc9, 0x54, 0x36, 0xef, 0x57, 0xa0, 0x94, 0x15, 0x64, 0x59, 0x23, 0x35, 0x9a, 0x5d, 0x7b, 0x41, 0x71, 0xef, 0x22, 0xc2, 0x46, 0x70, 0xf1, 0xb2, 0x29, 0xd3, 0x60, 0x3e, 0x91, 0xf7, 0x66, 0x71, 0xb7, 0xdf, 0x97, 0xe7, 0x31, 0x7c, 0x97, 0x73, 0x44, 0x76, 0xd5, 0xf3, 0xd1, 0x7d, 0x21, 0xcf, 0x82, 0xb5, 0xba, 0x9f, 0x83, 0xdf, 0x2e, 0x58, 0x8d, 0x36, 0x98, 0x4f, 0xd1, 0xb5, 0x84, 0x46, 0x8b, 0xd2, 0x3b, 0x2e, 0x87, 0x5f, 0x32, 0xf6, 0x89, 0x53, 0xf7, 0xb2 } + +} +, +{ + "RSAES-OAEP Encryption Example 8.6", + /* Message to be encrypted */ + 25, + { 0x8e, 0x07, 0xd6, 0x6f, 0x7b, 0x88, 0x0a, 0x72, 0x56, 0x3a, 0xbc, 0xd3, 0xf3, 0x50, 0x92, 0xbc, 0x33, 0x40, 0x9f, 0xb7, 0xf8, 0x8f, 0x24, 0x72, 0xbe } +, + /* Seed */ + 20, + { 0x39, 0x25, 0xc7, 0x1b, 0x36, 0x2d, 0x40, 0xa0, 0xa6, 0xde, 0x42, 0x14, 0x55, 0x79, 0xba, 0x1e, 0x7d, 0xd4, 0x59, 0xfc } +, + /* Encryption */ + 129, + { 0x3a, 0xfd, 0x9c, 0x66, 0x00, 0x14, 0x7b, 0x21, 0x79, 0x8d, 0x81, 0x8c, 0x65, 0x5a, 0x0f, 0x4c, 0x92, 0x12, 0xdb, 0x26, 0xd0, 0xb0, 0xdf, 0xdc, 0x2a, 0x75, 0x94, 0xcc, 0xb3, 0xd2, 0x2f, 0x5b, 0xf1, 0xd7, 0xc3, 0xe1, 0x12, 0xcd, 0x73, 0xfc, 0x7d, 0x50, 0x9c, 0x7a, 0x8b, 0xaf, 0xdd, 0x3c, 0x27, 0x4d, 0x13, 0x99, 0x00, 0x9f, 0x96, 0x09, 0xec, 0x4b, 0xe6, 0x47, 0x7e, 0x45, 0x3f, 0x07, 0x5a, 0xa3, 0x3d, 0xb3, 0x82, 0x87, 0x0c, 0x1c, 0x34, 0x09, 0xae, 0xf3, 0x92, 0xd7, 0x38, 0x6a, 0xe3, 0xa6, 0x96, 0xb9, 0x9a, 0x94, 0xb4, 0xda, 0x05, 0x89, 0x44, 0x7e, 0x95, 0x5d, 0x16, 0xc9, 0x8b, 0x17, 0x60, 0x2a, 0x59, 0xbd, 0x73, 0x62, 0x79, 0xfc, 0xd8, 0xfb, 0x28, 0x0c, 0x44, 0x62, 0xd5, 0x90, 0xbf, 0xa9, 0xbf, 0x13, 0xfe, 0xd5, 0x70, 0xea, 0xfd, 0xe9, 0x73, 0x30, 0xa2, 0xc2, 0x10 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 9: A 1536-bit RSA Key Pair", +{ + /* RSA modulus n */ + 192, + { 0xcf, 0x2c, 0xd4, 0x1e, 0x34, 0xca, 0x3a, 0x72, 0x8e, 0xa5, 0xcb, 0x8a, 0xff, 0x64, 0xc3, 0x6d, 0x27, 0xbd, 0xef, 0x53, 0x64, 0xe3, 0x36, 0xfd, 0x68, 0xd3, 0x12, 0x3c, 0x5a, 0x19, 0x6a, 0x8c, 0x28, 0x70, 0x13, 0xe8, 0x53, 0xd5, 0x15, 0x6d, 0x58, 0xd1, 0x51, 0x95, 0x45, 0x20, 0xfb, 0x4f, 0x6d, 0x7b, 0x17, 0xab, 0xb6, 0x81, 0x77, 0x65, 0x90, 0x9c, 0x57, 0x61, 0x19, 0x65, 0x9d, 0x90, 0x2b, 0x19, 0x06, 0xed, 0x8a, 0x2b, 0x10, 0xc1, 0x55, 0xc2, 0x4d, 0x12, 0x45, 0x28, 0xda, 0xb9, 0xee, 0xae, 0x37, 0x9b, 0xea, 0xc6, 0x6e, 0x4a, 0x41, 0x17, 0x86, 0xdc, 0xb8, 0xfd, 0x00, 0x62, 0xeb, 0xc0, 0x30, 0xde, 0x12, 0x19, 0xa0, 0x4c, 0x2a, 0x8c, 0x1b, 0x7d, 0xd3, 0x13, 0x1e, 0x4d, 0x6b, 0x6c, 0xae, 0xe2, 0xe3, 0x1a, 0x5e, 0xd4, 0x1a, 0xc1, 0x50, 0x9b, 0x2e, 0xf1, 0xee, 0x2a, 0xb1, 0x83, 0x64, 0xbe, 0x56, 0x8c, 0xa9, 0x41, 0xc2, 0x5e, 0xcc, 0x84, 0xff, 0x9d, 0x64, 0x3b, 0x5e, 0xc1, 0xaa, 0xae, 0x10, 0x2a, 0x20, 0xd7, 0x3f, 0x47, 0x9b, 0x78, 0x0f, 0xd6, 0xda, 0x91, 0x07, 0x52, 0x12, 0xd9, 0xea, 0xc0, 0x3a, 0x06, 0x74, 0xd8, 0x99, 0xeb, 0xa2, 0xe4, 0x31, 0xf4, 0xc4, 0x4b, 0x61, 0x5b, 0x6b, 0xa2, 0x23, 0x2b, 0xd4, 0xb3, 0x3b, 0xae, 0xd7, 0x3d, 0x62, 0x5d } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 192, + { 0x19, 0x8c, 0x14, 0x1e, 0x23, 0x71, 0x5a, 0x92, 0xbc, 0xcf, 0x6a, 0x11, 0x9a, 0x5b, 0xc1, 0x13, 0x89, 0x46, 0x8d, 0x28, 0x11, 0xf5, 0x48, 0xd7, 0x27, 0xe1, 0x7b, 0x4a, 0xb0, 0xeb, 0x98, 0x6d, 0x6f, 0x21, 0x1e, 0xfb, 0x53, 0xb7, 0x1f, 0x7c, 0xcb, 0xea, 0x87, 0xee, 0x69, 0xc7, 0x5e, 0xe6, 0x15, 0x00, 0x8c, 0x53, 0x32, 0xde, 0xb5, 0x2b, 0xf3, 0x90, 0xab, 0xdf, 0xbf, 0xe3, 0x7d, 0x72, 0x05, 0x36, 0x81, 0x59, 0xb2, 0x63, 0x8c, 0x1d, 0xe3, 0x26, 0xe2, 0x1d, 0x22, 0x25, 0x1f, 0x0f, 0xb5, 0x84, 0x8b, 0x3b, 0xf1, 0x50, 0x05, 0xd2, 0xa7, 0x43, 0x30, 0xf0, 0xaf, 0xe9, 0x16, 0xee, 0x62, 0xcc, 0xc1, 0x34, 0x4d, 0x1d, 0x83, 0xa7, 0x09, 0xe6, 0x06, 0x76, 0x27, 0x38, 0x40, 0xf7, 0xf3, 0x77, 0x42, 0x4a, 0x5e, 0x0a, 0x4d, 0xa7, 0x5f, 0x01, 0xb3, 0x1f, 0xf7, 0x68, 0x19, 0xcf, 0x9c, 0xbf, 0xdd, 0x21, 0x52, 0x43, 0xc3, 0x91, 0x7c, 0x03, 0xef, 0x38, 0x19, 0x93, 0x12, 0xe5, 0x67, 0xb3, 0xbf, 0x7a, 0xed, 0x3a, 0xb4, 0x57, 0xf3, 0x71, 0xef, 0x8a, 0x14, 0x23, 0xf4, 0x5b, 0x68, 0xc6, 0xe2, 0x82, 0xec, 0x11, 0x1b, 0xba, 0x28, 0x33, 0xb9, 0x87, 0xfd, 0x69, 0xfa, 0xd8, 0x3b, 0xc1, 0xb8, 0xc6, 0x13, 0xc5, 0xe1, 0xea, 0x16, 0xc1, 0x1e, 0xd1, 0x25, 0xea, 0x7e, 0xc1 } +, + /* Prime p */ + 96, + { 0xfc, 0x8d, 0x6c, 0x04, 0xbe, 0xc4, 0xeb, 0x9a, 0x81, 0x92, 0xca, 0x79, 0x00, 0xcb, 0xe5, 0x36, 0xe2, 0xe8, 0xb5, 0x19, 0xde, 0xcf, 0x33, 0xb2, 0x45, 0x97, 0x98, 0xc6, 0x90, 0x9d, 0xf4, 0xf1, 0x76, 0xdb, 0x7d, 0x23, 0x19, 0x0f, 0xc7, 0x2b, 0x88, 0x65, 0xa7, 0x18, 0xaf, 0x89, 0x5f, 0x1b, 0xcd, 0x91, 0x45, 0x29, 0x80, 0x27, 0x42, 0x3b, 0x60, 0x5e, 0x70, 0xa4, 0x7c, 0xf5, 0x83, 0x90, 0xa8, 0xc3, 0xe8, 0x8f, 0xc8, 0xc4, 0x8e, 0x8b, 0x32, 0xe3, 0xda, 0x21, 0x0d, 0xfb, 0xe3, 0xe8, 0x81, 0xea, 0x56, 0x74, 0xb6, 0xa3, 0x48, 0xc2, 0x1e, 0x93, 0xf9, 0xe5, 0x5e, 0xa6, 0x5e, 0xfd } +, + /* Prime q */ + 96, + { 0xd2, 0x00, 0xd4, 0x5e, 0x78, 0x8a, 0xac, 0xea, 0x60, 0x6a, 0x40, 0x1d, 0x04, 0x60, 0xf8, 0x7d, 0xd5, 0xc1, 0x02, 0x7e, 0x12, 0xdc, 0x1a, 0x0d, 0x75, 0x86, 0xe8, 0x93, 0x9d, 0x9c, 0xf7, 0x89, 0xb4, 0x0f, 0x51, 0xac, 0x04, 0x42, 0x96, 0x1d, 0xe7, 0xd2, 0x1c, 0xc2, 0x1e, 0x05, 0xc8, 0x31, 0x55, 0xc1, 0xf2, 0xaa, 0x91, 0x93, 0x38, 0x7c, 0xfd, 0xf9, 0x56, 0xcb, 0x48, 0xd1, 0x53, 0xba, 0x27, 0x04, 0x06, 0xf9, 0xbb, 0xba, 0x53, 0x7d, 0x49, 0x87, 0xd9, 0xe2, 0xf9, 0x94, 0x2d, 0x7a, 0x14, 0xcb, 0xff, 0xfe, 0xa7, 0x4f, 0xec, 0xdd, 0xa9, 0x28, 0xd2, 0x3e, 0x25, 0x9f, 0x5e, 0xe1 } +, + /* p's CRT exponent dP */ + 96, + { 0xdb, 0x16, 0x80, 0x2f, 0x79, 0xa2, 0xf0, 0xd4, 0x5f, 0x35, 0x8d, 0x69, 0xfd, 0x33, 0xe4, 0x4b, 0x81, 0xfa, 0xe8, 0x28, 0x62, 0x2e, 0x93, 0xa5, 0x42, 0x53, 0xe9, 0x97, 0xd0, 0x1b, 0x07, 0x43, 0x75, 0x9d, 0xa0, 0xe8, 0x12, 0xb4, 0xaa, 0x4e, 0x6c, 0x8b, 0xea, 0xb2, 0x32, 0x8d, 0x54, 0x31, 0x95, 0x5a, 0x41, 0x8a, 0x67, 0xff, 0x26, 0xa8, 0xc5, 0xc8, 0x07, 0xa5, 0xda, 0x35, 0x4e, 0x05, 0xef, 0x31, 0xcc, 0x8c, 0xf7, 0x58, 0xf4, 0x63, 0x73, 0x29, 0x50, 0xb0, 0x3e, 0x26, 0x57, 0x26, 0xfb, 0x94, 0xe3, 0x9d, 0x6a, 0x57, 0x2a, 0x26, 0x24, 0x4a, 0xb0, 0x8d, 0xb7, 0x57, 0x52, 0xad } +, + /* q's CRT exponent dQ */ + 96, + { 0xa0, 0xa3, 0x17, 0xcf, 0xe7, 0xdf, 0x14, 0x23, 0xf8, 0x7a, 0x6d, 0xee, 0x84, 0x51, 0xf4, 0xe2, 0xb4, 0xa6, 0x7e, 0x54, 0x97, 0xf2, 0x9b, 0x4f, 0x1e, 0x4e, 0x83, 0x0b, 0x9f, 0xad, 0xd9, 0x40, 0x11, 0x67, 0x02, 0x6f, 0x55, 0x96, 0xe5, 0xa3, 0x9c, 0x97, 0x81, 0x7e, 0x0f, 0x5f, 0x16, 0xe2, 0x7e, 0x19, 0xec, 0x99, 0x02, 0xe0, 0x1d, 0x7e, 0xa6, 0xfb, 0x9a, 0xa3, 0xc7, 0x60, 0xaf, 0xee, 0x1e, 0x38, 0x1b, 0x69, 0xde, 0x6a, 0xc9, 0xc0, 0x75, 0x85, 0xa0, 0x6a, 0xd9, 0xc4, 0xba, 0x00, 0xbf, 0x75, 0xc8, 0xad, 0x2f, 0xa8, 0x98, 0xa4, 0x79, 0xe8, 0x0a, 0xe2, 0x94, 0xfe, 0xd2, 0xa1 } +, + /* CRT coefficient qInv */ + 96, + { 0x0b, 0x21, 0xf3, 0x35, 0xc3, 0x53, 0x34, 0x2e, 0xb4, 0x4c, 0x3a, 0xa2, 0x44, 0x45, 0x78, 0x0c, 0x2d, 0x65, 0x5b, 0x94, 0x01, 0x74, 0xca, 0xe3, 0x8c, 0x7c, 0x8a, 0x4e, 0x64, 0x93, 0xc0, 0xba, 0x9f, 0xd3, 0x03, 0x74, 0x82, 0x67, 0xb0, 0x83, 0xb9, 0xa7, 0xa6, 0xcb, 0x61, 0xe4, 0x2d, 0xb3, 0x62, 0xb8, 0xc9, 0x89, 0x6d, 0xb7, 0x06, 0x4e, 0x02, 0xad, 0x5a, 0xe6, 0x15, 0x87, 0xda, 0x15, 0xb4, 0x64, 0x9c, 0x90, 0x59, 0x49, 0x09, 0xfe, 0xb3, 0x7d, 0xbc, 0xb6, 0x54, 0xbe, 0xb7, 0x26, 0x8e, 0xc8, 0x01, 0xe5, 0xa8, 0xb4, 0xaa, 0x39, 0x11, 0xbe, 0xbd, 0x88, 0x54, 0x2f, 0x05, 0xbe } + +} +, +{{ + "RSAES-OAEP Encryption Example 9.1", + /* Message to be encrypted */ + 61, + { 0xf7, 0x35, 0xfd, 0x55, 0xba, 0x92, 0x59, 0x2c, 0x3b, 0x52, 0xb8, 0xf9, 0xc4, 0xf6, 0x9a, 0xaa, 0x1c, 0xbe, 0xf8, 0xfe, 0x88, 0xad, 0xd0, 0x95, 0x59, 0x54, 0x12, 0x46, 0x7f, 0x9c, 0xf4, 0xec, 0x0b, 0x89, 0x6c, 0x59, 0xed, 0xa1, 0x62, 0x10, 0xe7, 0x54, 0x9c, 0x8a, 0xbb, 0x10, 0xcd, 0xbc, 0x21, 0xa1, 0x2e, 0xc9, 0xb6, 0xb5, 0xb8, 0xfd, 0x2f, 0x10, 0x39, 0x9e, 0xb6 } +, + /* Seed */ + 20, + { 0x8e, 0xc9, 0x65, 0xf1, 0x34, 0xa3, 0xec, 0x99, 0x31, 0xe9, 0x2a, 0x1c, 0xa0, 0xdc, 0x81, 0x69, 0xd5, 0xea, 0x70, 0x5c } +, + /* Encryption */ + 192, + { 0x26, 0x7b, 0xcd, 0x11, 0x8a, 0xca, 0xb1, 0xfc, 0x8b, 0xa8, 0x1c, 0x85, 0xd7, 0x30, 0x03, 0xcb, 0x86, 0x10, 0xfa, 0x55, 0xc1, 0xd9, 0x7d, 0xa8, 0xd4, 0x8a, 0x7c, 0x7f, 0x06, 0x89, 0x6a, 0x4d, 0xb7, 0x51, 0xaa, 0x28, 0x42, 0x55, 0xb9, 0xd3, 0x6a, 0xd6, 0x5f, 0x37, 0x65, 0x3d, 0x82, 0x9f, 0x1b, 0x37, 0xf9, 0x7b, 0x80, 0x01, 0x94, 0x25, 0x45, 0xb2, 0xfc, 0x2c, 0x55, 0xa7, 0x37, 0x6c, 0xa7, 0xa1, 0xbe, 0x4b, 0x17, 0x60, 0xc8, 0xe0, 0x5a, 0x33, 0xe5, 0xaa, 0x25, 0x26, 0xb8, 0xd9, 0x8e, 0x31, 0x70, 0x88, 0xe7, 0x83, 0x4c, 0x75, 0x5b, 0x2a, 0x59, 0xb1, 0x26, 0x31, 0xa1, 0x82, 0xc0, 0x5d, 0x5d, 0x43, 0xab, 0x17, 0x79, 0x26, 0x4f, 0x84, 0x56, 0xf5, 0x15, 0xce, 0x57, 0xdf, 0xdf, 0x51, 0x2d, 0x54, 0x93, 0xda, 0xb7, 0xb7, 0x33, 0x8d, 0xc4, 0xb7, 0xd7, 0x8d, 0xb9, 0xc0, 0x91, 0xac, 0x3b, 0xaf, 0x53, 0x7a, 0x69, 0xfc, 0x7f, 0x54, 0x9d, 0x97, 0x9f, 0x0e, 0xff, 0x9a, 0x94, 0xfd, 0xa4, 0x16, 0x9b, 0xd4, 0xd1, 0xd1, 0x9a, 0x69, 0xc9, 0x9e, 0x33, 0xc3, 0xb5, 0x54, 0x90, 0xd5, 0x01, 0xb3, 0x9b, 0x1e, 0xda, 0xe1, 0x18, 0xff, 0x67, 0x93, 0xa1, 0x53, 0x26, 0x15, 0x84, 0xd3, 0xa5, 0xf3, 0x9f, 0x6e, 0x68, 0x2e, 0x3d, 0x17, 0xc8, 0xcd, 0x12, 0x61, 0xfa, 0x72 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 9.2", + /* Message to be encrypted */ + 39, + { 0x81, 0xb9, 0x06, 0x60, 0x50, 0x15, 0xa6, 0x3a, 0xab, 0xe4, 0x2d, 0xdf, 0x11, 0xe1, 0x97, 0x89, 0x12, 0xf5, 0x40, 0x4c, 0x74, 0x74, 0xb2, 0x6d, 0xce, 0x3e, 0xd4, 0x82, 0xbf, 0x96, 0x1e, 0xcc, 0x81, 0x8b, 0xf4, 0x20, 0xc5, 0x46, 0x59 } +, + /* Seed */ + 20, + { 0xec, 0xb1, 0xb8, 0xb2, 0x5f, 0xa5, 0x0c, 0xda, 0xb0, 0x8e, 0x56, 0x04, 0x28, 0x67, 0xf4, 0xaf, 0x58, 0x26, 0xd1, 0x6c } +, + /* Encryption */ + 192, + { 0x93, 0xac, 0x9f, 0x06, 0x71, 0xec, 0x29, 0xac, 0xbb, 0x44, 0x4e, 0xff, 0xc1, 0xa5, 0x74, 0x13, 0x51, 0xd6, 0x0f, 0xdb, 0x0e, 0x39, 0x3f, 0xbf, 0x75, 0x4a, 0xcf, 0x0d, 0xe4, 0x97, 0x61, 0xa1, 0x48, 0x41, 0xdf, 0x77, 0x72, 0xe9, 0xbc, 0x82, 0x77, 0x39, 0x66, 0xa1, 0x58, 0x4c, 0x4d, 0x72, 0xba, 0xea, 0x00, 0x11, 0x8f, 0x83, 0xf3, 0x5c, 0xca, 0x6e, 0x53, 0x7c, 0xbd, 0x4d, 0x81, 0x1f, 0x55, 0x83, 0xb2, 0x97, 0x83, 0xd8, 0xa6, 0xd9, 0x4c, 0xd3, 0x1b, 0xe7, 0x0d, 0x6f, 0x52, 0x6c, 0x10, 0xff, 0x09, 0xc6, 0xfa, 0x7c, 0xe0, 0x69, 0x79, 0x5a, 0x3f, 0xcd, 0x05, 0x11, 0xfd, 0x5f, 0xcb, 0x56, 0x4b, 0xcc, 0x80, 0xea, 0x9c, 0x78, 0xf3, 0x8b, 0x80, 0x01, 0x25, 0x39, 0xd8, 0xa4, 0xdd, 0xf6, 0xfe, 0x81, 0xe9, 0xcd, 0xdb, 0x7f, 0x50, 0xdb, 0xbb, 0xbc, 0xc7, 0xe5, 0xd8, 0x60, 0x97, 0xcc, 0xf4, 0xec, 0x49, 0x18, 0x9f, 0xb8, 0xbf, 0x31, 0x8b, 0xe6, 0xd5, 0xa0, 0x71, 0x5d, 0x51, 0x6b, 0x49, 0xaf, 0x19, 0x12, 0x58, 0xcd, 0x32, 0xdc, 0x83, 0x3c, 0xe6, 0xeb, 0x46, 0x73, 0xc0, 0x3a, 0x19, 0xbb, 0xac, 0xe8, 0x8c, 0xc5, 0x48, 0x95, 0xf6, 0x36, 0xcc, 0x0c, 0x1e, 0xc8, 0x90, 0x96, 0xd1, 0x1c, 0xe2, 0x35, 0xa2, 0x65, 0xca, 0x17, 0x64, 0x23, 0x2a, 0x68, 0x9a, 0xe8 } + +} +, +{ + "RSAES-OAEP Encryption Example 9.3", + /* Message to be encrypted */ + 17, + { 0xfd, 0x32, 0x64, 0x29, 0xdf, 0x9b, 0x89, 0x0e, 0x09, 0xb5, 0x4b, 0x18, 0xb8, 0xf3, 0x4f, 0x1e, 0x24 } +, + /* Seed */ + 20, + { 0xe8, 0x9b, 0xb0, 0x32, 0xc6, 0xce, 0x62, 0x2c, 0xbd, 0xb5, 0x3b, 0xc9, 0x46, 0x60, 0x14, 0xea, 0x77, 0xf7, 0x77, 0xc0 } +, + /* Encryption */ + 192, + { 0x81, 0xeb, 0xdd, 0x95, 0x05, 0x4b, 0x0c, 0x82, 0x2e, 0xf9, 0xad, 0x76, 0x93, 0xf5, 0xa8, 0x7a, 0xdf, 0xb4, 0xb4, 0xc4, 0xce, 0x70, 0xdf, 0x2d, 0xf8, 0x4e, 0xd4, 0x9c, 0x04, 0xda, 0x58, 0xba, 0x5f, 0xc2, 0x0a, 0x19, 0xe1, 0xa6, 0xe8, 0xb7, 0xa3, 0x90, 0x0b, 0x22, 0x79, 0x6d, 0xc4, 0xe8, 0x69, 0xee, 0x6b, 0x42, 0x79, 0x2d, 0x15, 0xa8, 0xec, 0xeb, 0x56, 0xc0, 0x9c, 0x69, 0x91, 0x4e, 0x81, 0x3c, 0xea, 0x8f, 0x69, 0x31, 0xe4, 0xb8, 0xed, 0x6f, 0x42, 0x1a, 0xf2, 0x98, 0xd5, 0x95, 0xc9, 0x7f, 0x47, 0x89, 0xc7, 0xca, 0xa6, 0x12, 0xc7, 0xef, 0x36, 0x09, 0x84, 0xc2, 0x1b, 0x93, 0xed, 0xc5, 0x40, 0x10, 0x68, 0xb5, 0xaf, 0x4c, 0x78, 0xa8, 0x77, 0x1b, 0x98, 0x4d, 0x53, 0xb8, 0xea, 0x8a, 0xdf, 0x2f, 0x6a, 0x7d, 0x4a, 0x0b, 0xa7, 0x6c, 0x75, 0xe1, 0xdd, 0x9f, 0x65, 0x8f, 0x20, 0xde, 0xd4, 0xa4, 0x60, 0x71, 0xd4, 0x6d, 0x77, 0x91, 0xb5, 0x68, 0x03, 0xd8, 0xfe, 0xa7, 0xf0, 0xb0, 0xf8, 0xe4, 0x1a, 0xe3, 0xf0, 0x93, 0x83, 0xa6, 0xf9, 0x58, 0x5f, 0xe7, 0x75, 0x3e, 0xaa, 0xff, 0xd2, 0xbf, 0x94, 0x56, 0x31, 0x08, 0xbe, 0xec, 0xc2, 0x07, 0xbb, 0xb5, 0x35, 0xf5, 0xfc, 0xc7, 0x05, 0xf0, 0xdd, 0xe9, 0xf7, 0x08, 0xc6, 0x2f, 0x49, 0xa9, 0xc9, 0x03, 0x71, 0xd3 } + +} +, +{ + "RSAES-OAEP Encryption Example 9.4", + /* Message to be encrypted */ + 62, + { 0xf1, 0x45, 0x9b, 0x5f, 0x0c, 0x92, 0xf0, 0x1a, 0x0f, 0x72, 0x3a, 0x2e, 0x56, 0x62, 0x48, 0x4d, 0x8f, 0x8c, 0x0a, 0x20, 0xfc, 0x29, 0xda, 0xd6, 0xac, 0xd4, 0x3b, 0xb5, 0xf3, 0xef, 0xfd, 0xf4, 0xe1, 0xb6, 0x3e, 0x07, 0xfd, 0xfe, 0x66, 0x28, 0xd0, 0xd7, 0x4c, 0xa1, 0x9b, 0xf2, 0xd6, 0x9e, 0x4a, 0x0a, 0xbf, 0x86, 0xd2, 0x93, 0x92, 0x5a, 0x79, 0x67, 0x72, 0xf8, 0x08, 0x8e } +, + /* Seed */ + 20, + { 0x60, 0x6f, 0x3b, 0x99, 0xc0, 0xb9, 0xcc, 0xd7, 0x71, 0xea, 0xa2, 0x9e, 0xa0, 0xe4, 0xc8, 0x84, 0xf3, 0x18, 0x9c, 0xcc } +, + /* Encryption */ + 192, + { 0xbc, 0xc3, 0x5f, 0x94, 0xcd, 0xe6, 0x6c, 0xb1, 0x13, 0x66, 0x25, 0xd6, 0x25, 0xb9, 0x44, 0x32, 0xa3, 0x5b, 0x22, 0xf3, 0xd2, 0xfa, 0x11, 0xa6, 0x13, 0xff, 0x0f, 0xca, 0x5b, 0xd5, 0x7f, 0x87, 0xb9, 0x02, 0xcc, 0xdc, 0x1c, 0xd0, 0xae, 0xbc, 0xb0, 0x71, 0x5e, 0xe8, 0x69, 0xd1, 0xd1, 0xfe, 0x39, 0x5f, 0x67, 0x93, 0x00, 0x3f, 0x5e, 0xca, 0x46, 0x50, 0x59, 0xc8, 0x86, 0x60, 0xd4, 0x46, 0xff, 0x5f, 0x08, 0x18, 0x55, 0x20, 0x22, 0x55, 0x7e, 0x38, 0xc0, 0x8a, 0x67, 0xea, 0xd9, 0x91, 0x26, 0x22, 0x54, 0xf1, 0x06, 0x82, 0x97, 0x5e, 0xc5, 0x63, 0x97, 0x76, 0x85, 0x37, 0xf4, 0x97, 0x7a, 0xf6, 0xd5, 0xf6, 0xaa, 0xce, 0xb7, 0xfb, 0x25, 0xde, 0xc5, 0x93, 0x72, 0x30, 0x23, 0x1f, 0xd8, 0x97, 0x8a, 0xf4, 0x91, 0x19, 0xa2, 0x9f, 0x29, 0xe4, 0x24, 0xab, 0x82, 0x72, 0xb4, 0x75, 0x62, 0x79, 0x2d, 0x5c, 0x94, 0xf7, 0x74, 0xb8, 0x82, 0x9d, 0x0b, 0x0d, 0x9f, 0x1a, 0x8c, 0x9e, 0xdd, 0xf3, 0x75, 0x74, 0xd5, 0xfa, 0x24, 0x8e, 0xef, 0xa9, 0xc5, 0x27, 0x1f, 0xc5, 0xec, 0x25, 0x79, 0xc8, 0x1b, 0xdd, 0x61, 0xb4, 0x10, 0xfa, 0x61, 0xfe, 0x36, 0xe4, 0x24, 0x22, 0x1c, 0x11, 0x3a, 0xdd, 0xb2, 0x75, 0x66, 0x4c, 0x80, 0x1d, 0x34, 0xca, 0x8c, 0x63, 0x51, 0xe4, 0xa8, 0x58 } + +} +, +{ + "RSAES-OAEP Encryption Example 9.5", + /* Message to be encrypted */ + 53, + { 0x53, 0xe6, 0xe8, 0xc7, 0x29, 0xd6, 0xf9, 0xc3, 0x19, 0xdd, 0x31, 0x7e, 0x74, 0xb0, 0xdb, 0x8e, 0x4c, 0xcc, 0xa2, 0x5f, 0x3c, 0x83, 0x05, 0x74, 0x6e, 0x13, 0x7a, 0xc6, 0x3a, 0x63, 0xef, 0x37, 0x39, 0xe7, 0xb5, 0x95, 0xab, 0xb9, 0x6e, 0x8d, 0x55, 0xe5, 0x4f, 0x7b, 0xd4, 0x1a, 0xb4, 0x33, 0x37, 0x8f, 0xfb, 0x91, 0x1d } +, + /* Seed */ + 20, + { 0xfc, 0xbc, 0x42, 0x14, 0x02, 0xe9, 0xec, 0xab, 0xc6, 0x08, 0x2a, 0xfa, 0x40, 0xba, 0x5f, 0x26, 0x52, 0x2c, 0x84, 0x0e } +, + /* Encryption */ + 192, + { 0x23, 0x2a, 0xfb, 0xc9, 0x27, 0xfa, 0x08, 0xc2, 0xf6, 0xa2, 0x7b, 0x87, 0xd4, 0xa5, 0xcb, 0x09, 0xc0, 0x7d, 0xc2, 0x6f, 0xae, 0x73, 0xd7, 0x3a, 0x90, 0x55, 0x88, 0x39, 0xf4, 0xfd, 0x66, 0xd2, 0x81, 0xb8, 0x7e, 0xc7, 0x34, 0xbc, 0xe2, 0x37, 0xba, 0x16, 0x66, 0x98, 0xed, 0x82, 0x91, 0x06, 0xa7, 0xde, 0x69, 0x42, 0xcd, 0x6c, 0xdc, 0xe7, 0x8f, 0xed, 0x8d, 0x2e, 0x4d, 0x81, 0x42, 0x8e, 0x66, 0x49, 0x0d, 0x03, 0x62, 0x64, 0xce, 0xf9, 0x2a, 0xf9, 0x41, 0xd3, 0xe3, 0x50, 0x55, 0xfe, 0x39, 0x81, 0xe1, 0x4d, 0x29, 0xcb, 0xb9, 0xa4, 0xf6, 0x74, 0x73, 0x06, 0x3b, 0xae, 0xc7, 0x9a, 0x11, 0x79, 0xf5, 0xa1, 0x7c, 0x9c, 0x18, 0x32, 0xf2, 0x83, 0x8f, 0xd7, 0xd5, 0xe5, 0x9b, 0xb9, 0x65, 0x9d, 0x56, 0xdc, 0xe8, 0xa0, 0x19, 0xed, 0xef, 0x1b, 0xb3, 0xac, 0xcc, 0x69, 0x7c, 0xc6, 0xcc, 0x7a, 0x77, 0x8f, 0x60, 0xa0, 0x64, 0xc7, 0xf6, 0xf5, 0xd5, 0x29, 0xc6, 0x21, 0x02, 0x62, 0xe0, 0x03, 0xde, 0x58, 0x3e, 0x81, 0xe3, 0x16, 0x7b, 0x89, 0x97, 0x1f, 0xb8, 0xc0, 0xe1, 0x5d, 0x44, 0xff, 0xfe, 0xf8, 0x9b, 0x53, 0xd8, 0xd6, 0x4d, 0xd7, 0x97, 0xd1, 0x59, 0xb5, 0x6d, 0x2b, 0x08, 0xea, 0x53, 0x07, 0xea, 0x12, 0xc2, 0x41, 0xbd, 0x58, 0xd4, 0xee, 0x27, 0x8a, 0x1f, 0x2e } + +} +, +{ + "RSAES-OAEP Encryption Example 9.6", + /* Message to be encrypted */ + 11, + { 0xb6, 0xb2, 0x8e, 0xa2, 0x19, 0x8d, 0x0c, 0x10, 0x08, 0xbc, 0x64 } +, + /* Seed */ + 20, + { 0x23, 0xaa, 0xde, 0x0e, 0x1e, 0x08, 0xbb, 0x9b, 0x9a, 0x78, 0xd2, 0x30, 0x2a, 0x52, 0xf9, 0xc2, 0x1b, 0x2e, 0x1b, 0xa2 } +, + /* Encryption */ + 192, + { 0x43, 0x8c, 0xc7, 0xdc, 0x08, 0xa6, 0x8d, 0xa2, 0x49, 0xe4, 0x25, 0x05, 0xf8, 0x57, 0x3b, 0xa6, 0x0e, 0x2c, 0x27, 0x73, 0xd5, 0xb2, 0x90, 0xf4, 0xcf, 0x9d, 0xff, 0x71, 0x8e, 0x84, 0x20, 0x81, 0xc3, 0x83, 0xe6, 0x70, 0x24, 0xa0, 0xf2, 0x95, 0x94, 0xea, 0x98, 0x7b, 0x9d, 0x25, 0xe4, 0xb7, 0x38, 0xf2, 0x85, 0x97, 0x0d, 0x19, 0x5a, 0xbb, 0x3a, 0x8c, 0x80, 0x54, 0xe3, 0xd7, 0x9d, 0x6b, 0x9c, 0x9a, 0x83, 0x27, 0xba, 0x59, 0x6f, 0x12, 0x59, 0xe2, 0x71, 0x26, 0x67, 0x47, 0x66, 0x90, 0x7d, 0x8d, 0x58, 0x2f, 0xf3, 0xa8, 0x47, 0x61, 0x54, 0x92, 0x9a, 0xdb, 0x1e, 0x6d, 0x12, 0x35, 0xb2, 0xcc, 0xb4, 0xec, 0x8f, 0x66, 0x3b, 0xa9, 0xcc, 0x67, 0x0a, 0x92, 0xbe, 0xbd, 0x85, 0x3c, 0x8d, 0xbf, 0x69, 0xc6, 0x43, 0x6d, 0x01, 0x6f, 0x61, 0xad, 0xd8, 0x36, 0xe9, 0x47, 0x32, 0x45, 0x04, 0x34, 0x20, 0x7f, 0x9f, 0xd4, 0xc4, 0x3d, 0xec, 0x2a, 0x12, 0xa9, 0x58, 0xef, 0xa0, 0x1e, 0xfe, 0x26, 0x69, 0x89, 0x9b, 0x5e, 0x60, 0x4c, 0x25, 0x5c, 0x55, 0xfb, 0x71, 0x66, 0xde, 0x55, 0x89, 0xe3, 0x69, 0x59, 0x7b, 0xb0, 0x91, 0x68, 0xc0, 0x6d, 0xd5, 0xdb, 0x17, 0x7e, 0x06, 0xa1, 0x74, 0x0e, 0xb2, 0xd5, 0xc8, 0x2f, 0xae, 0xca, 0x6d, 0x92, 0xfc, 0xee, 0x99, 0x31, 0xba, 0x9f } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 10: A 2048-bit RSA Key Pair", +{ + /* RSA modulus n */ + 256, + { 0xae, 0x45, 0xed, 0x56, 0x01, 0xce, 0xc6, 0xb8, 0xcc, 0x05, 0xf8, 0x03, 0x93, 0x5c, 0x67, 0x4d, 0xdb, 0xe0, 0xd7, 0x5c, 0x4c, 0x09, 0xfd, 0x79, 0x51, 0xfc, 0x6b, 0x0c, 0xae, 0xc3, 0x13, 0xa8, 0xdf, 0x39, 0x97, 0x0c, 0x51, 0x8b, 0xff, 0xba, 0x5e, 0xd6, 0x8f, 0x3f, 0x0d, 0x7f, 0x22, 0xa4, 0x02, 0x9d, 0x41, 0x3f, 0x1a, 0xe0, 0x7e, 0x4e, 0xbe, 0x9e, 0x41, 0x77, 0xce, 0x23, 0xe7, 0xf5, 0x40, 0x4b, 0x56, 0x9e, 0x4e, 0xe1, 0xbd, 0xcf, 0x3c, 0x1f, 0xb0, 0x3e, 0xf1, 0x13, 0x80, 0x2d, 0x4f, 0x85, 0x5e, 0xb9, 0xb5, 0x13, 0x4b, 0x5a, 0x7c, 0x80, 0x85, 0xad, 0xca, 0xe6, 0xfa, 0x2f, 0xa1, 0x41, 0x7e, 0xc3, 0x76, 0x3b, 0xe1, 0x71, 0xb0, 0xc6, 0x2b, 0x76, 0x0e, 0xde, 0x23, 0xc1, 0x2a, 0xd9, 0x2b, 0x98, 0x08, 0x84, 0xc6, 0x41, 0xf5, 0xa8, 0xfa, 0xc2, 0x6b, 0xda, 0xd4, 0xa0, 0x33, 0x81, 0xa2, 0x2f, 0xe1, 0xb7, 0x54, 0x88, 0x50, 0x94, 0xc8, 0x25, 0x06, 0xd4, 0x01, 0x9a, 0x53, 0x5a, 0x28, 0x6a, 0xfe, 0xb2, 0x71, 0xbb, 0x9b, 0xa5, 0x92, 0xde, 0x18, 0xdc, 0xf6, 0x00, 0xc2, 0xae, 0xea, 0xe5, 0x6e, 0x02, 0xf7, 0xcf, 0x79, 0xfc, 0x14, 0xcf, 0x3b, 0xdc, 0x7c, 0xd8, 0x4f, 0xeb, 0xbb, 0xf9, 0x50, 0xca, 0x90, 0x30, 0x4b, 0x22, 0x19, 0xa7, 0xaa, 0x06, 0x3a, 0xef, 0xa2, 0xc3, 0xc1, 0x98, 0x0e, 0x56, 0x0c, 0xd6, 0x4a, 0xfe, 0x77, 0x95, 0x85, 0xb6, 0x10, 0x76, 0x57, 0xb9, 0x57, 0x85, 0x7e, 0xfd, 0xe6, 0x01, 0x09, 0x88, 0xab, 0x7d, 0xe4, 0x17, 0xfc, 0x88, 0xd8, 0xf3, 0x84, 0xc4, 0xe6, 0xe7, 0x2c, 0x3f, 0x94, 0x3e, 0x0c, 0x31, 0xc0, 0xc4, 0xa5, 0xcc, 0x36, 0xf8, 0x79, 0xd8, 0xa3, 0xac, 0x9d, 0x7d, 0x59, 0x86, 0x0e, 0xaa, 0xda, 0x6b, 0x83, 0xbb } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 256, + { 0x05, 0x6b, 0x04, 0x21, 0x6f, 0xe5, 0xf3, 0x54, 0xac, 0x77, 0x25, 0x0a, 0x4b, 0x6b, 0x0c, 0x85, 0x25, 0xa8, 0x5c, 0x59, 0xb0, 0xbd, 0x80, 0xc5, 0x64, 0x50, 0xa2, 0x2d, 0x5f, 0x43, 0x8e, 0x59, 0x6a, 0x33, 0x3a, 0xa8, 0x75, 0xe2, 0x91, 0xdd, 0x43, 0xf4, 0x8c, 0xb8, 0x8b, 0x9d, 0x5f, 0xc0, 0xd4, 0x99, 0xf9, 0xfc, 0xd1, 0xc3, 0x97, 0xf9, 0xaf, 0xc0, 0x70, 0xcd, 0x9e, 0x39, 0x8c, 0x8d, 0x19, 0xe6, 0x1d, 0xb7, 0xc7, 0x41, 0x0a, 0x6b, 0x26, 0x75, 0xdf, 0xbf, 0x5d, 0x34, 0x5b, 0x80, 0x4d, 0x20, 0x1a, 0xdd, 0x50, 0x2d, 0x5c, 0xe2, 0xdf, 0xcb, 0x09, 0x1c, 0xe9, 0x99, 0x7b, 0xbe, 0xbe, 0x57, 0x30, 0x6f, 0x38, 0x3e, 0x4d, 0x58, 0x81, 0x03, 0xf0, 0x36, 0xf7, 0xe8, 0x5d, 0x19, 0x34, 0xd1, 0x52, 0xa3, 0x23, 0xe4, 0xa8, 0xdb, 0x45, 0x1d, 0x6f, 0x4a, 0x5b, 0x1b, 0x0f, 0x10, 0x2c, 0xc1, 0x50, 0xe0, 0x2f, 0xee, 0xe2, 0xb8, 0x8d, 0xea, 0x4a, 0xd4, 0xc1, 0xba, 0xcc, 0xb2, 0x4d, 0x84, 0x07, 0x2d, 0x14, 0xe1, 0xd2, 0x4a, 0x67, 0x71, 0xf7, 0x40, 0x8e, 0xe3, 0x05, 0x64, 0xfb, 0x86, 0xd4, 0x39, 0x3a, 0x34, 0xbc, 0xf0, 0xb7, 0x88, 0x50, 0x1d, 0x19, 0x33, 0x03, 0xf1, 0x3a, 0x22, 0x84, 0xb0, 0x01, 0xf0, 0xf6, 0x49, 0xea, 0xf7, 0x93, 0x28, 0xd4, 0xac, 0x5c, 0x43, 0x0a, 0xb4, 0x41, 0x49, 0x20, 0xa9, 0x46, 0x0e, 0xd1, 0xb7, 0xbc, 0x40, 0xec, 0x65, 0x3e, 0x87, 0x6d, 0x09, 0xab, 0xc5, 0x09, 0xae, 0x45, 0xb5, 0x25, 0x19, 0x01, 0x16, 0xa0, 0xc2, 0x61, 0x01, 0x84, 0x82, 0x98, 0x50, 0x9c, 0x1c, 0x3b, 0xf3, 0xa4, 0x83, 0xe7, 0x27, 0x40, 0x54, 0xe1, 0x5e, 0x97, 0x07, 0x50, 0x36, 0xe9, 0x89, 0xf6, 0x09, 0x32, 0x80, 0x7b, 0x52, 0x57, 0x75, 0x1e, 0x79 } +, + /* Prime p */ + 128, + { 0xec, 0xf5, 0xae, 0xcd, 0x1e, 0x55, 0x15, 0xff, 0xfa, 0xcb, 0xd7, 0x5a, 0x28, 0x16, 0xc6, 0xeb, 0xf4, 0x90, 0x18, 0xcd, 0xfb, 0x46, 0x38, 0xe1, 0x85, 0xd6, 0x6a, 0x73, 0x96, 0xb6, 0xf8, 0x09, 0x0f, 0x80, 0x18, 0xc7, 0xfd, 0x95, 0xcc, 0x34, 0xb8, 0x57, 0xdc, 0x17, 0xf0, 0xcc, 0x65, 0x16, 0xbb, 0x13, 0x46, 0xab, 0x4d, 0x58, 0x2c, 0xad, 0xad, 0x7b, 0x41, 0x03, 0x35, 0x23, 0x87, 0xb7, 0x03, 0x38, 0xd0, 0x84, 0x04, 0x7c, 0x9d, 0x95, 0x39, 0xb6, 0x49, 0x62, 0x04, 0xb3, 0xdd, 0x6e, 0xa4, 0x42, 0x49, 0x92, 0x07, 0xbe, 0xc0, 0x1f, 0x96, 0x42, 0x87, 0xff, 0x63, 0x36, 0xc3, 0x98, 0x46, 0x58, 0x33, 0x68, 0x46, 0xf5, 0x6e, 0x46, 0x86, 0x18, 0x81, 0xc1, 0x02, 0x33, 0xd2, 0x17, 0x6b, 0xf1, 0x5a, 0x5e, 0x96, 0xdd, 0xc7, 0x80, 0xbc, 0x86, 0x8a, 0xa7, 0x7d, 0x3c, 0xe7, 0x69 } +, + /* Prime q */ + 128, + { 0xbc, 0x46, 0xc4, 0x64, 0xfc, 0x6a, 0xc4, 0xca, 0x78, 0x3b, 0x0e, 0xb0, 0x8a, 0x3c, 0x84, 0x1b, 0x77, 0x2f, 0x7e, 0x9b, 0x2f, 0x28, 0xba, 0xbd, 0x58, 0x8a, 0xe8, 0x85, 0xe1, 0xa0, 0xc6, 0x1e, 0x48, 0x58, 0xa0, 0xfb, 0x25, 0xac, 0x29, 0x99, 0x90, 0xf3, 0x5b, 0xe8, 0x51, 0x64, 0xc2, 0x59, 0xba, 0x11, 0x75, 0xcd, 0xd7, 0x19, 0x27, 0x07, 0x13, 0x51, 0x84, 0x99, 0x2b, 0x6c, 0x29, 0xb7, 0x46, 0xdd, 0x0d, 0x2c, 0xab, 0xe1, 0x42, 0x83, 0x5f, 0x7d, 0x14, 0x8c, 0xc1, 0x61, 0x52, 0x4b, 0x4a, 0x09, 0x94, 0x6d, 0x48, 0xb8, 0x28, 0x47, 0x3f, 0x1c, 0xe7, 0x6b, 0x6c, 0xb6, 0x88, 0x6c, 0x34, 0x5c, 0x03, 0xe0, 0x5f, 0x41, 0xd5, 0x1b, 0x5c, 0x3a, 0x90, 0xa3, 0xf2, 0x40, 0x73, 0xc7, 0xd7, 0x4a, 0x4f, 0xe2, 0x5d, 0x9c, 0xf2, 0x1c, 0x75, 0x96, 0x0f, 0x3f, 0xc3, 0x86, 0x31, 0x83 } +, + /* p's CRT exponent dP */ + 128, + { 0xc7, 0x35, 0x64, 0x57, 0x1d, 0x00, 0xfb, 0x15, 0xd0, 0x8a, 0x3d, 0xe9, 0x95, 0x7a, 0x50, 0x91, 0x5d, 0x71, 0x26, 0xe9, 0x44, 0x2d, 0xac, 0xf4, 0x2b, 0xc8, 0x2e, 0x86, 0x2e, 0x56, 0x73, 0xff, 0x6a, 0x00, 0x8e, 0xd4, 0xd2, 0xe3, 0x74, 0x61, 0x7d, 0xf8, 0x9f, 0x17, 0xa1, 0x60, 0xb4, 0x3b, 0x7f, 0xda, 0x9c, 0xb6, 0xb6, 0xb7, 0x42, 0x18, 0x60, 0x98, 0x15, 0xf7, 0xd4, 0x5c, 0xa2, 0x63, 0xc1, 0x59, 0xaa, 0x32, 0xd2, 0x72, 0xd1, 0x27, 0xfa, 0xf4, 0xbc, 0x8c, 0xa2, 0xd7, 0x73, 0x78, 0xe8, 0xae, 0xb1, 0x9b, 0x0a, 0xd7, 0xda, 0x3c, 0xb3, 0xde, 0x0a, 0xe7, 0x31, 0x49, 0x80, 0xf6, 0x2b, 0x6d, 0x4b, 0x0a, 0x87, 0x5d, 0x1d, 0xf0, 0x3c, 0x1b, 0xae, 0x39, 0xcc, 0xd8, 0x33, 0xef, 0x6c, 0xd7, 0xe2, 0xd9, 0x52, 0x8b, 0xf0, 0x84, 0xd1, 0xf9, 0x69, 0xe7, 0x94, 0xe9, 0xf6, 0xc1 } +, + /* q's CRT exponent dQ */ + 128, + { 0x26, 0x58, 0xb3, 0x7f, 0x6d, 0xf9, 0xc1, 0x03, 0x0b, 0xe1, 0xdb, 0x68, 0x11, 0x7f, 0xa9, 0xd8, 0x7e, 0x39, 0xea, 0x2b, 0x69, 0x3b, 0x7e, 0x6d, 0x3a, 0x2f, 0x70, 0x94, 0x74, 0x13, 0xee, 0xc6, 0x14, 0x2e, 0x18, 0xfb, 0x8d, 0xfc, 0xb6, 0xac, 0x54, 0x5d, 0x7c, 0x86, 0xa0, 0xad, 0x48, 0xf8, 0x45, 0x71, 0x70, 0xf0, 0xef, 0xb2, 0x6b, 0xc4, 0x81, 0x26, 0xc5, 0x3e, 0xfd, 0x1d, 0x16, 0x92, 0x01, 0x98, 0xdc, 0x2a, 0x11, 0x07, 0xdc, 0x28, 0x2d, 0xb6, 0xa8, 0x0c, 0xd3, 0x06, 0x23, 0x60, 0xba, 0x3f, 0xa1, 0x3f, 0x70, 0xe4, 0x31, 0x2f, 0xf1, 0xa6, 0xcd, 0x6b, 0x8f, 0xc4, 0xcd, 0x9c, 0x5c, 0x3d, 0xb1, 0x7c, 0x6d, 0x6a, 0x57, 0x21, 0x2f, 0x73, 0xae, 0x29, 0xf6, 0x19, 0x32, 0x7b, 0xad, 0x59, 0xb1, 0x53, 0x85, 0x85, 0x85, 0xba, 0x4e, 0x28, 0xb6, 0x0a, 0x62, 0xa4, 0x5e, 0x49 } +, + /* CRT coefficient qInv */ + 128, + { 0x6f, 0x38, 0x52, 0x6b, 0x39, 0x25, 0x08, 0x55, 0x34, 0xef, 0x3e, 0x41, 0x5a, 0x83, 0x6e, 0xde, 0x8b, 0x86, 0x15, 0x8a, 0x2c, 0x7c, 0xbf, 0xec, 0xcb, 0x0b, 0xd8, 0x34, 0x30, 0x4f, 0xec, 0x68, 0x3b, 0xa8, 0xd4, 0xf4, 0x79, 0xc4, 0x33, 0xd4, 0x34, 0x16, 0xe6, 0x32, 0x69, 0x62, 0x3c, 0xea, 0x10, 0x07, 0x76, 0xd8, 0x5a, 0xff, 0x40, 0x1d, 0x3f, 0xff, 0x61, 0x0e, 0xe6, 0x54, 0x11, 0xce, 0x3b, 0x13, 0x63, 0xd6, 0x3a, 0x97, 0x09, 0xee, 0xde, 0x42, 0x64, 0x7c, 0xea, 0x56, 0x14, 0x93, 0xd5, 0x45, 0x70, 0xa8, 0x79, 0xc1, 0x86, 0x82, 0xcd, 0x97, 0x71, 0x0b, 0x96, 0x20, 0x5e, 0xc3, 0x11, 0x17, 0xd7, 0x3b, 0x5f, 0x36, 0x22, 0x3f, 0xad, 0xd6, 0xe8, 0xba, 0x90, 0xdd, 0x7c, 0x0e, 0xe6, 0x1d, 0x44, 0xe1, 0x63, 0x25, 0x1e, 0x20, 0xc7, 0xf6, 0x6e, 0xb3, 0x05, 0x11, 0x7c, 0xb8 } + +} +, +{{ + "RSAES-OAEP Encryption Example 10.1", + /* Message to be encrypted */ + 28, + { 0x8b, 0xba, 0x6b, 0xf8, 0x2a, 0x6c, 0x0f, 0x86, 0xd5, 0xf1, 0x75, 0x6e, 0x97, 0x95, 0x68, 0x70, 0xb0, 0x89, 0x53, 0xb0, 0x6b, 0x4e, 0xb2, 0x05, 0xbc, 0x16, 0x94, 0xee } +, + /* Seed */ + 20, + { 0x47, 0xe1, 0xab, 0x71, 0x19, 0xfe, 0xe5, 0x6c, 0x95, 0xee, 0x5e, 0xaa, 0xd8, 0x6f, 0x40, 0xd0, 0xaa, 0x63, 0xbd, 0x33 } +, + /* Encryption */ + 256, + { 0x53, 0xea, 0x5d, 0xc0, 0x8c, 0xd2, 0x60, 0xfb, 0x3b, 0x85, 0x85, 0x67, 0x28, 0x7f, 0xa9, 0x15, 0x52, 0xc3, 0x0b, 0x2f, 0xeb, 0xfb, 0xa2, 0x13, 0xf0, 0xae, 0x87, 0x70, 0x2d, 0x06, 0x8d, 0x19, 0xba, 0xb0, 0x7f, 0xe5, 0x74, 0x52, 0x3d, 0xfb, 0x42, 0x13, 0x9d, 0x68, 0xc3, 0xc5, 0xaf, 0xee, 0xe0, 0xbf, 0xe4, 0xcb, 0x79, 0x69, 0xcb, 0xf3, 0x82, 0xb8, 0x04, 0xd6, 0xe6, 0x13, 0x96, 0x14, 0x4e, 0x2d, 0x0e, 0x60, 0x74, 0x1f, 0x89, 0x93, 0xc3, 0x01, 0x4b, 0x58, 0xb9, 0xb1, 0x95, 0x7a, 0x8b, 0xab, 0xcd, 0x23, 0xaf, 0x85, 0x4f, 0x4c, 0x35, 0x6f, 0xb1, 0x66, 0x2a, 0xa7, 0x2b, 0xfc, 0xc7, 0xe5, 0x86, 0x55, 0x9d, 0xc4, 0x28, 0x0d, 0x16, 0x0c, 0x12, 0x67, 0x85, 0xa7, 0x23, 0xeb, 0xee, 0xbe, 0xff, 0x71, 0xf1, 0x15, 0x94, 0x44, 0x0a, 0xae, 0xf8, 0x7d, 0x10, 0x79, 0x3a, 0x87, 0x74, 0xa2, 0x39, 0xd4, 0xa0, 0x4c, 0x87, 0xfe, 0x14, 0x67, 0xb9, 0xda, 0xf8, 0x52, 0x08, 0xec, 0x6c, 0x72, 0x55, 0x79, 0x4a, 0x96, 0xcc, 0x29, 0x14, 0x2f, 0x9a, 0x8b, 0xd4, 0x18, 0xe3, 0xc1, 0xfd, 0x67, 0x34, 0x4b, 0x0c, 0xd0, 0x82, 0x9d, 0xf3, 0xb2, 0xbe, 0xc6, 0x02, 0x53, 0x19, 0x62, 0x93, 0xc6, 0xb3, 0x4d, 0x3f, 0x75, 0xd3, 0x2f, 0x21, 0x3d, 0xd4, 0x5c, 0x62, 0x73, 0xd5, 0x05, 0xad, 0xf4, 0xcc, 0xed, 0x10, 0x57, 0xcb, 0x75, 0x8f, 0xc2, 0x6a, 0xee, 0xfa, 0x44, 0x12, 0x55, 0xed, 0x4e, 0x64, 0xc1, 0x99, 0xee, 0x07, 0x5e, 0x7f, 0x16, 0x64, 0x61, 0x82, 0xfd, 0xb4, 0x64, 0x73, 0x9b, 0x68, 0xab, 0x5d, 0xaf, 0xf0, 0xe6, 0x3e, 0x95, 0x52, 0x01, 0x68, 0x24, 0xf0, 0x54, 0xbf, 0x4d, 0x3c, 0x8c, 0x90, 0xa9, 0x7b, 0xb6, 0xb6, 0x55, 0x32, 0x84, 0xeb, 0x42, 0x9f, 0xcc } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSAES-OAEP Encryption Example 10.2", + /* Message to be encrypted */ + 16, + { 0xe6, 0xad, 0x18, 0x1f, 0x05, 0x3b, 0x58, 0xa9, 0x04, 0xf2, 0x45, 0x75, 0x10, 0x37, 0x3e, 0x57 } +, + /* Seed */ + 20, + { 0x6d, 0x17, 0xf5, 0xb4, 0xc1, 0xff, 0xac, 0x35, 0x1d, 0x19, 0x5b, 0xf7, 0xb0, 0x9d, 0x09, 0xf0, 0x9a, 0x40, 0x79, 0xcf } +, + /* Encryption */ + 256, + { 0xa2, 0xb1, 0xa4, 0x30, 0xa9, 0xd6, 0x57, 0xe2, 0xfa, 0x1c, 0x2b, 0xb5, 0xed, 0x43, 0xff, 0xb2, 0x5c, 0x05, 0xa3, 0x08, 0xfe, 0x90, 0x93, 0xc0, 0x10, 0x31, 0x79, 0x5f, 0x58, 0x74, 0x40, 0x01, 0x10, 0x82, 0x8a, 0xe5, 0x8f, 0xb9, 0xb5, 0x81, 0xce, 0x9d, 0xdd, 0xd3, 0xe5, 0x49, 0xae, 0x04, 0xa0, 0x98, 0x54, 0x59, 0xbd, 0xe6, 0xc6, 0x26, 0x59, 0x4e, 0x7b, 0x05, 0xdc, 0x42, 0x78, 0xb2, 0xa1, 0x46, 0x5c, 0x13, 0x68, 0x40, 0x88, 0x23, 0xc8, 0x5e, 0x96, 0xdc, 0x66, 0xc3, 0xa3, 0x09, 0x83, 0xc6, 0x39, 0x66, 0x4f, 0xc4, 0x56, 0x9a, 0x37, 0xfe, 0x21, 0xe5, 0xa1, 0x95, 0xb5, 0x77, 0x6e, 0xed, 0x2d, 0xf8, 0xd8, 0xd3, 0x61, 0xaf, 0x68, 0x6e, 0x75, 0x02, 0x29, 0xbb, 0xd6, 0x63, 0xf1, 0x61, 0x86, 0x8a, 0x50, 0x61, 0x5e, 0x0c, 0x33, 0x7b, 0xec, 0x0c, 0xa3, 0x5f, 0xec, 0x0b, 0xb1, 0x9c, 0x36, 0xeb, 0x2e, 0x0b, 0xbc, 0xc0, 0x58, 0x2f, 0xa1, 0xd9, 0x3a, 0xac, 0xdb, 0x06, 0x10, 0x63, 0xf5, 0x9f, 0x2c, 0xe1, 0xee, 0x43, 0x60, 0x5e, 0x5d, 0x89, 0xec, 0xa1, 0x83, 0xd2, 0xac, 0xdf, 0xe9, 0xf8, 0x10, 0x11, 0x02, 0x2a, 0xd3, 0xb4, 0x3a, 0x3d, 0xd4, 0x17, 0xda, 0xc9, 0x4b, 0x4e, 0x11, 0xea, 0x81, 0xb1, 0x92, 0x96, 0x6e, 0x96, 0x6b, 0x18, 0x20, 0x82, 0xe7, 0x19, 0x64, 0x60, 0x7b, 0x4f, 0x80, 0x02, 0xf3, 0x62, 0x99, 0x84, 0x4a, 0x11, 0xf2, 0xae, 0x0f, 0xae, 0xac, 0x2e, 0xae, 0x70, 0xf8, 0xf4, 0xf9, 0x80, 0x88, 0xac, 0xdc, 0xd0, 0xac, 0x55, 0x6e, 0x9f, 0xcc, 0xc5, 0x11, 0x52, 0x19, 0x08, 0xfa, 0xd2, 0x6f, 0x04, 0xc6, 0x42, 0x01, 0x45, 0x03, 0x05, 0x77, 0x87, 0x58, 0xb0, 0x53, 0x8b, 0xf8, 0xb5, 0xbb, 0x14, 0x4a, 0x82, 0x8e, 0x62, 0x97, 0x95 } + +} +, +{ + "RSAES-OAEP Encryption Example 10.3", + /* Message to be encrypted */ + 26, + { 0x51, 0x0a, 0x2c, 0xf6, 0x0e, 0x86, 0x6f, 0xa2, 0x34, 0x05, 0x53, 0xc9, 0x4e, 0xa3, 0x9f, 0xbc, 0x25, 0x63, 0x11, 0xe8, 0x3e, 0x94, 0x45, 0x4b, 0x41, 0x24 } +, + /* Seed */ + 20, + { 0x38, 0x53, 0x87, 0x51, 0x4d, 0xec, 0xcc, 0x7c, 0x74, 0x0d, 0xd8, 0xcd, 0xf9, 0xda, 0xee, 0x49, 0xa1, 0xcb, 0xfd, 0x54 } +, + /* Encryption */ + 256, + { 0x98, 0x86, 0xc3, 0xe6, 0x76, 0x4a, 0x8b, 0x9a, 0x84, 0xe8, 0x41, 0x48, 0xeb, 0xd8, 0xc3, 0xb1, 0xaa, 0x80, 0x50, 0x38, 0x1a, 0x78, 0xf6, 0x68, 0x71, 0x4c, 0x16, 0xd9, 0xcf, 0xd2, 0xa6, 0xed, 0xc5, 0x69, 0x79, 0xc5, 0x35, 0xd9, 0xde, 0xe3, 0xb4, 0x4b, 0x85, 0xc1, 0x8b, 0xe8, 0x92, 0x89, 0x92, 0x37, 0x17, 0x11, 0x47, 0x22, 0x16, 0xd9, 0x5d, 0xda, 0x98, 0xd2, 0xee, 0x83, 0x47, 0xc9, 0xb1, 0x4d, 0xff, 0xdf, 0xf8, 0x4a, 0xa4, 0x8d, 0x25, 0xac, 0x06, 0xf7, 0xd7, 0xe6, 0x53, 0x98, 0xac, 0x96, 0x7b, 0x1c, 0xe9, 0x09, 0x25, 0xf6, 0x7d, 0xce, 0x04, 0x9b, 0x7f, 0x81, 0x2d, 0xb0, 0x74, 0x29, 0x97, 0xa7, 0x4d, 0x44, 0xfe, 0x81, 0xdb, 0xe0, 0xe7, 0xa3, 0xfe, 0xaf, 0x2e, 0x5c, 0x40, 0xaf, 0x88, 0x8d, 0x55, 0x0d, 0xdb, 0xbe, 0x3b, 0xc2, 0x06, 0x57, 0xa2, 0x95, 0x43, 0xf8, 0xfc, 0x29, 0x13, 0xb9, 0xbd, 0x1a, 0x61, 0xb2, 0xab, 0x22, 0x56, 0xec, 0x40, 0x9b, 0xbd, 0x7d, 0xc0, 0xd1, 0x77, 0x17, 0xea, 0x25, 0xc4, 0x3f, 0x42, 0xed, 0x27, 0xdf, 0x87, 0x38, 0xbf, 0x4a, 0xfc, 0x67, 0x66, 0xff, 0x7a, 0xff, 0x08, 0x59, 0x55, 0x5e, 0xe2, 0x83, 0x92, 0x0f, 0x4c, 0x8a, 0x63, 0xc4, 0xa7, 0x34, 0x0c, 0xba, 0xfd, 0xdc, 0x33, 0x9e, 0xcd, 0xb4, 0xb0, 0x51, 0x50, 0x02, 0xf9, 0x6c, 0x93, 0x2b, 0x5b, 0x79, 0x16, 0x7a, 0xf6, 0x99, 0xc0, 0xad, 0x3f, 0xcc, 0xfd, 0xf0, 0xf4, 0x4e, 0x85, 0xa7, 0x02, 0x62, 0xbf, 0x2e, 0x18, 0xfe, 0x34, 0xb8, 0x50, 0x58, 0x99, 0x75, 0xe8, 0x67, 0xff, 0x96, 0x9d, 0x48, 0xea, 0xbf, 0x21, 0x22, 0x71, 0x54, 0x6c, 0xdc, 0x05, 0xa6, 0x9e, 0xcb, 0x52, 0x6e, 0x52, 0x87, 0x0c, 0x83, 0x6f, 0x30, 0x7b, 0xd7, 0x98, 0x78, 0x0e, 0xde } + +} +, +{ + "RSAES-OAEP Encryption Example 10.4", + /* Message to be encrypted */ + 36, + { 0xbc, 0xdd, 0x19, 0x0d, 0xa3, 0xb7, 0xd3, 0x00, 0xdf, 0x9a, 0x06, 0xe2, 0x2c, 0xaa, 0xe2, 0xa7, 0x5f, 0x10, 0xc9, 0x1f, 0xf6, 0x67, 0xb7, 0xc1, 0x6b, 0xde, 0x8b, 0x53, 0x06, 0x4a, 0x26, 0x49, 0xa9, 0x40, 0x45, 0xc9 } +, + /* Seed */ + 20, + { 0x5c, 0xac, 0xa6, 0xa0, 0xf7, 0x64, 0x16, 0x1a, 0x96, 0x84, 0xf8, 0x5d, 0x92, 0xb6, 0xe0, 0xef, 0x37, 0xca, 0x8b, 0x65 } +, + /* Encryption */ + 256, + { 0x63, 0x18, 0xe9, 0xfb, 0x5c, 0x0d, 0x05, 0xe5, 0x30, 0x7e, 0x16, 0x83, 0x43, 0x6e, 0x90, 0x32, 0x93, 0xac, 0x46, 0x42, 0x35, 0x8a, 0xaa, 0x22, 0x3d, 0x71, 0x63, 0x01, 0x3a, 0xba, 0x87, 0xe2, 0xdf, 0xda, 0x8e, 0x60, 0xc6, 0x86, 0x0e, 0x29, 0xa1, 0xe9, 0x26, 0x86, 0x16, 0x3e, 0xa0, 0xb9, 0x17, 0x5f, 0x32, 0x9c, 0xa3, 0xb1, 0x31, 0xa1, 0xed, 0xd3, 0xa7, 0x77, 0x59, 0xa8, 0xb9, 0x7b, 0xad, 0x6a, 0x4f, 0x8f, 0x43, 0x96, 0xf2, 0x8c, 0xf6, 0xf3, 0x9c, 0xa5, 0x81, 0x12, 0xe4, 0x81, 0x60, 0xd6, 0xe2, 0x03, 0xda, 0xa5, 0x85, 0x6f, 0x3a, 0xca, 0x5f, 0xfe, 0xd5, 0x77, 0xaf, 0x49, 0x94, 0x08, 0xe3, 0xdf, 0xd2, 0x33, 0xe3, 0xe6, 0x04, 0xdb, 0xe3, 0x4a, 0x9c, 0x4c, 0x90, 0x82, 0xde, 0x65, 0x52, 0x7c, 0xac, 0x63, 0x31, 0xd2, 0x9d, 0xc8, 0x0e, 0x05, 0x08, 0xa0, 0xfa, 0x71, 0x22, 0xe7, 0xf3, 0x29, 0xf6, 0xcc, 0xa5, 0xcf, 0xa3, 0x4d, 0x4d, 0x1d, 0xa4, 0x17, 0x80, 0x54, 0x57, 0xe0, 0x08, 0xbe, 0xc5, 0x49, 0xe4, 0x78, 0xff, 0x9e, 0x12, 0xa7, 0x63, 0xc4, 0x77, 0xd1, 0x5b, 0xbb, 0x78, 0xf5, 0xb6, 0x9b, 0xd5, 0x78, 0x30, 0xfc, 0x2c, 0x4e, 0xd6, 0x86, 0xd7, 0x9b, 0xc7, 0x2a, 0x95, 0xd8, 0x5f, 0x88, 0x13, 0x4c, 0x6b, 0x0a, 0xfe, 0x56, 0xa8, 0xcc, 0xfb, 0xc8, 0x55, 0x82, 0x8b, 0xb3, 0x39, 0xbd, 0x17, 0x90, 0x9c, 0xf1, 0xd7, 0x0d, 0xe3, 0x33, 0x5a, 0xe0, 0x70, 0x39, 0x09, 0x3e, 0x60, 0x6d, 0x65, 0x53, 0x65, 0xde, 0x65, 0x50, 0xb8, 0x72, 0xcd, 0x6d, 0xe1, 0xd4, 0x40, 0xee, 0x03, 0x1b, 0x61, 0x94, 0x5f, 0x62, 0x9a, 0xd8, 0xa3, 0x53, 0xb0, 0xd4, 0x09, 0x39, 0xe9, 0x6a, 0x3c, 0x45, 0x0d, 0x2a, 0x8d, 0x5e, 0xee, 0x9f, 0x67, 0x80, 0x93, 0xc8 } + +} +, +{ + "RSAES-OAEP Encryption Example 10.5", + /* Message to be encrypted */ + 23, + { 0xa7, 0xdd, 0x6c, 0x7d, 0xc2, 0x4b, 0x46, 0xf9, 0xdd, 0x5f, 0x1e, 0x91, 0xad, 0xa4, 0xc3, 0xb3, 0xdf, 0x94, 0x7e, 0x87, 0x72, 0x32, 0xa9 } +, + /* Seed */ + 20, + { 0x95, 0xbc, 0xa9, 0xe3, 0x85, 0x98, 0x94, 0xb3, 0xdd, 0x86, 0x9f, 0xa7, 0xec, 0xd5, 0xbb, 0xc6, 0x40, 0x1b, 0xf3, 0xe4 } +, + /* Encryption */ + 256, + { 0x75, 0x29, 0x08, 0x72, 0xcc, 0xfd, 0x4a, 0x45, 0x05, 0x66, 0x0d, 0x65, 0x1f, 0x56, 0xda, 0x6d, 0xaa, 0x09, 0xca, 0x13, 0x01, 0xd8, 0x90, 0x63, 0x2f, 0x6a, 0x99, 0x2f, 0x3d, 0x56, 0x5c, 0xee, 0x46, 0x4a, 0xfd, 0xed, 0x40, 0xed, 0x3b, 0x5b, 0xe9, 0x35, 0x67, 0x14, 0xea, 0x5a, 0xa7, 0x65, 0x5f, 0x4a, 0x13, 0x66, 0xc2, 0xf1, 0x7c, 0x72, 0x8f, 0x6f, 0x2c, 0x5a, 0x5d, 0x1f, 0x8e, 0x28, 0x42, 0x9b, 0xc4, 0xe6, 0xf8, 0xf2, 0xcf, 0xf8, 0xda, 0x8d, 0xc0, 0xe0, 0xa9, 0x80, 0x8e, 0x45, 0xfd, 0x09, 0xea, 0x2f, 0xa4, 0x0c, 0xb2, 0xb6, 0xce, 0x6f, 0xff, 0xf5, 0xc0, 0xe1, 0x59, 0xd1, 0x1b, 0x68, 0xd9, 0x0a, 0x85, 0xf7, 0xb8, 0x4e, 0x10, 0x3b, 0x09, 0xe6, 0x82, 0x66, 0x64, 0x80, 0xc6, 0x57, 0x50, 0x5c, 0x09, 0x29, 0x25, 0x94, 0x68, 0xa3, 0x14, 0x78, 0x6d, 0x74, 0xea, 0xb1, 0x31, 0x57, 0x3c, 0xf2, 0x34, 0xbf, 0x57, 0xdb, 0x7d, 0x9e, 0x66, 0xcc, 0x67, 0x48, 0x19, 0x2e, 0x00, 0x2d, 0xc0, 0xde, 0xea, 0x93, 0x05, 0x85, 0xf0, 0x83, 0x1f, 0xdc, 0xd9, 0xbc, 0x33, 0xd5, 0x1f, 0x79, 0xed, 0x2f, 0xfc, 0x16, 0xbc, 0xf4, 0xd5, 0x98, 0x12, 0xfc, 0xeb, 0xca, 0xa3, 0xf9, 0x06, 0x9b, 0x0e, 0x44, 0x56, 0x86, 0xd6, 0x44, 0xc2, 0x5c, 0xcf, 0x63, 0xb4, 0x56, 0xee, 0x5f, 0xa6, 0xff, 0xe9, 0x6f, 0x19, 0xcd, 0xf7, 0x51, 0xfe, 0xd9, 0xea, 0xf3, 0x59, 0x57, 0x75, 0x4d, 0xbf, 0x4b, 0xfe, 0xa5, 0x21, 0x6a, 0xa1, 0x84, 0x4d, 0xc5, 0x07, 0xcb, 0x2d, 0x08, 0x0e, 0x72, 0x2e, 0xba, 0x15, 0x03, 0x08, 0xc2, 0xb5, 0xff, 0x11, 0x93, 0x62, 0x0f, 0x17, 0x66, 0xec, 0xf4, 0x48, 0x1b, 0xaf, 0xb9, 0x43, 0xbd, 0x29, 0x28, 0x77, 0xf2, 0x13, 0x6c, 0xa4, 0x94, 0xab, 0xa0 } + +} +, +{ + "RSAES-OAEP Encryption Example 10.6", + /* Message to be encrypted */ + 45, + { 0xea, 0xf1, 0xa7, 0x3a, 0x1b, 0x0c, 0x46, 0x09, 0x53, 0x7d, 0xe6, 0x9c, 0xd9, 0x22, 0x8b, 0xbc, 0xfb, 0x9a, 0x8c, 0xa8, 0xc6, 0xc3, 0xef, 0xaf, 0x05, 0x6f, 0xe4, 0xa7, 0xf4, 0x63, 0x4e, 0xd0, 0x0b, 0x7c, 0x39, 0xec, 0x69, 0x22, 0xd7, 0xb8, 0xea, 0x2c, 0x04, 0xeb, 0xac } +, + /* Seed */ + 20, + { 0x9f, 0x47, 0xdd, 0xf4, 0x2e, 0x97, 0xee, 0xa8, 0x56, 0xa9, 0xbd, 0xbc, 0x71, 0x4e, 0xb3, 0xac, 0x22, 0xf6, 0xeb, 0x32 } +, + /* Encryption */ + 256, + { 0x2d, 0x20, 0x7a, 0x73, 0x43, 0x2a, 0x8f, 0xb4, 0xc0, 0x30, 0x51, 0xb3, 0xf7, 0x3b, 0x28, 0xa6, 0x17, 0x64, 0x09, 0x8d, 0xfa, 0x34, 0xc4, 0x7a, 0x20, 0x99, 0x5f, 0x81, 0x15, 0xaa, 0x68, 0x16, 0x67, 0x9b, 0x55, 0x7e, 0x82, 0xdb, 0xee, 0x58, 0x49, 0x08, 0xc6, 0xe6, 0x97, 0x82, 0xd7, 0xde, 0xb3, 0x4d, 0xbd, 0x65, 0xaf, 0x06, 0x3d, 0x57, 0xfc, 0xa7, 0x6a, 0x5f, 0xd0, 0x69, 0x49, 0x2f, 0xd6, 0x06, 0x8d, 0x99, 0x84, 0xd2, 0x09, 0x35, 0x05, 0x65, 0xa6, 0x2e, 0x5c, 0x77, 0xf2, 0x30, 0x38, 0xc1, 0x2c, 0xb1, 0x0c, 0x66, 0x34, 0x70, 0x9b, 0x54, 0x7c, 0x46, 0xf6, 0xb4, 0xa7, 0x09, 0xbd, 0x85, 0xca, 0x12, 0x2d, 0x74, 0x46, 0x5e, 0xf9, 0x77, 0x62, 0xc2, 0x97, 0x63, 0xe0, 0x6d, 0xbc, 0x7a, 0x9e, 0x73, 0x8c, 0x78, 0xbf, 0xca, 0x01, 0x02, 0xdc, 0x5e, 0x79, 0xd6, 0x5b, 0x97, 0x3f, 0x28, 0x24, 0x0c, 0xaa, 0xb2, 0xe1, 0x61, 0xa7, 0x8b, 0x57, 0xd2, 0x62, 0x45, 0x7e, 0xd8, 0x19, 0x5d, 0x53, 0xe3, 0xc7, 0xae, 0x9d, 0xa0, 0x21, 0x88, 0x3c, 0x6d, 0xb7, 0xc2, 0x4a, 0xfd, 0xd2, 0x32, 0x2e, 0xac, 0x97, 0x2a, 0xd3, 0xc3, 0x54, 0xc5, 0xfc, 0xef, 0x1e, 0x14, 0x6c, 0x3a, 0x02, 0x90, 0xfb, 0x67, 0xad, 0xf0, 0x07, 0x06, 0x6e, 0x00, 0x42, 0x8d, 0x2c, 0xec, 0x18, 0xce, 0x58, 0xf9, 0x32, 0x86, 0x98, 0xde, 0xfe, 0xf4, 0xb2, 0xeb, 0x5e, 0xc7, 0x69, 0x18, 0xfd, 0xe1, 0xc1, 0x98, 0xcb, 0xb3, 0x8b, 0x7a, 0xfc, 0x67, 0x62, 0x6a, 0x9a, 0xef, 0xec, 0x43, 0x22, 0xbf, 0xd9, 0x0d, 0x25, 0x63, 0x48, 0x1c, 0x9a, 0x22, 0x1f, 0x78, 0xc8, 0x27, 0x2c, 0x82, 0xd1, 0xb6, 0x2a, 0xb9, 0x14, 0xe1, 0xc6, 0x9f, 0x6a, 0xf6, 0xef, 0x30, 0xca, 0x52, 0x60, 0xdb, 0x4a, 0x46 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +}; + diff --git a/deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.txt b/deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.txt new file mode 100644 index 0000000..3df59e9 --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/oaep-vect.txt @@ -0,0 +1,2212 @@ +========================= +TEST VECTORS FOR RSA-OAEP +========================= + +# This file contains test vectors for the +# RSAES-OAEP encryption scheme as defined in +# PKCS #1 v2.1. 10 RSA keys of different sizes +# have been generated. For each key, 6 random +# messages of length between 1 and 64 octets +# have been RSAES-OAEP encrypted via a random +# seed of length 20 octets. +# +# The underlying hash function is SHA-1; the +# mask generation function is MGF1 with SHA-1 +# as specified in PKCS #1 v2.1. +# +# Integers are represented by strings of octets +# with the leftmost octet being the most +# significant octet. For example, +# +# 9,202,000 = (0x)8c 69 50. +# +# Key lengths: +# +# Key 1: 1024 bits +# Key 2: 1025 bits +# Key 3: 1026 bits +# Key 4: 1027 bits +# Key 5: 1028 bits +# Key 6: 1029 bits +# Key 7: 1030 bits +# Key 8: 1031 bits +# Key 9: 1536 bits +# Key 10: 2048 bits +# ============================================= + +# ================================== +# Example 1: A 1024-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 +91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab +c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 +12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 +f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 +c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 +8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 +76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c +55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd +8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b +15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 +fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 +2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf +b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de +f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 + +# Prime p: +d3 27 37 e7 26 7f fe 13 41 b2 d5 c0 d1 50 a8 1b +58 6f b3 13 2b ed 2f 8d 52 62 86 4a 9c b9 f3 0a +f3 8b e4 48 59 8d 41 3a 17 2e fb 80 2c 21 ac f1 +c1 1c 52 0c 2f 26 a4 71 dc ad 21 2e ac 7c a3 9d + +# Prime q: +cc 88 53 d1 d5 4d a6 30 fa c0 04 f4 71 f2 81 c7 +b8 98 2d 82 24 a4 90 ed be b3 3d 3e 3d 5c c9 3c +47 65 70 3d 1d d7 91 64 2f 1f 11 6a 0d d8 52 be +24 19 b2 af 72 bf e9 a0 30 e8 60 b0 28 8b 5d 77 + +# p's CRT exponent dP: +0e 12 bf 17 18 e9 ce f5 59 9b a1 c3 88 2f e8 04 +6a 90 87 4e ef ce 8f 2c cc 20 e4 f2 74 1f b0 a3 +3a 38 48 ae c9 c9 30 5f be cb d2 d7 68 19 96 7d +46 71 ac c6 43 1e 40 37 96 8d b3 78 78 e6 95 c1 + +# q's CRT exponent dQ: +95 29 7b 0f 95 a2 fa 67 d0 07 07 d6 09 df d4 fc +05 c8 9d af c2 ef 6d 6e a5 5b ec 77 1e a3 33 73 +4d 92 51 e7 90 82 ec da 86 6e fe f1 3c 45 9e 1a +63 13 86 b7 e3 54 c8 99 f5 f1 12 ca 85 d7 15 83 + +# CRT coefficient qInv: +4f 45 6c 50 24 93 bd c0 ed 2a b7 56 a3 a6 ed 4d +67 35 2a 69 7d 42 16 e9 32 12 b1 27 a6 3d 54 11 +ce 6f a9 8d 5d be fd 73 26 3e 37 28 14 27 43 81 +81 66 ed 7d d6 36 87 dd 2a 8c a1 d2 f4 fb d8 e1 + +# --------------------------------- +# RSAES-OAEP Encryption Example 1.1 +# --------------------------------- + +# Message to be encrypted: +66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 +97 d5 0d ba 79 b9 87 00 4a fe fe 34 + +# Seed: +18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1 +dd a0 a5 ef + +# Encryption: +35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f +7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb +21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01 +03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f +a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22 +d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26 +d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c +40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a + +# --------------------------------- +# RSAES-OAEP Encryption Example 1.2 +# --------------------------------- + +# Message to be encrypted: +75 0c 40 47 f5 47 e8 e4 14 11 85 65 23 29 8a c9 +ba e2 45 ef af 13 97 fb e5 6f 9d d5 + +# Seed: +0c c7 42 ce 4a 9b 7f 32 f9 51 bc b2 51 ef d9 25 +fe 4f e3 5f + +# Encryption: +64 0d b1 ac c5 8e 05 68 fe 54 07 e5 f9 b7 01 df +f8 c3 c9 1e 71 6c 53 6f c7 fc ec 6c b5 b7 1c 11 +65 98 8d 4a 27 9e 15 77 d7 30 fc 7a 29 93 2e 3f +00 c8 15 15 23 6d 8d 8e 31 01 7a 7a 09 df 43 52 +d9 04 cd eb 79 aa 58 3a dc c3 1e a6 98 a4 c0 52 +83 da ba 90 89 be 54 91 f6 7c 1a 4e e4 8d c7 4b +bb e6 64 3a ef 84 66 79 b4 cb 39 5a 35 2d 5e d1 +15 91 2d f6 96 ff e0 70 29 32 94 6d 71 49 2b 44 + +# --------------------------------- +# RSAES-OAEP Encryption Example 1.3 +# --------------------------------- + +# Message to be encrypted: +d9 4a e0 83 2e 64 45 ce 42 33 1c b0 6d 53 1a 82 +b1 db 4b aa d3 0f 74 6d c9 16 df 24 d4 e3 c2 45 +1f ff 59 a6 42 3e b0 e1 d0 2d 4f e6 46 cf 69 9d +fd 81 8c 6e 97 b0 51 + +# Seed: +25 14 df 46 95 75 5a 67 b2 88 ea f4 90 5c 36 ee +c6 6f d2 fd + +# Encryption: +42 37 36 ed 03 5f 60 26 af 27 6c 35 c0 b3 74 1b +36 5e 5f 76 ca 09 1b 4e 8c 29 e2 f0 be fe e6 03 +59 5a a8 32 2d 60 2d 2e 62 5e 95 eb 81 b2 f1 c9 +72 4e 82 2e ca 76 db 86 18 cf 09 c5 34 35 03 a4 +36 08 35 b5 90 3b c6 37 e3 87 9f b0 5e 0e f3 26 +85 d5 ae c5 06 7c d7 cc 96 fe 4b 26 70 b6 ea c3 +06 6b 1f cf 56 86 b6 85 89 aa fb 7d 62 9b 02 d8 +f8 62 5c a3 83 36 24 d4 80 0f b0 81 b1 cf 94 eb + +# --------------------------------- +# RSAES-OAEP Encryption Example 1.4 +# --------------------------------- + +# Message to be encrypted: +52 e6 50 d9 8e 7f 2a 04 8b 4f 86 85 21 53 b9 7e +01 dd 31 6f 34 6a 19 f6 7a 85 + +# Seed: +c4 43 5a 3e 1a 18 a6 8b 68 20 43 62 90 a3 7c ef +b8 5d b3 fb + +# Encryption: +45 ea d4 ca 55 1e 66 2c 98 00 f1 ac a8 28 3b 05 +25 e6 ab ae 30 be 4b 4a ba 76 2f a4 0f d3 d3 8e +22 ab ef c6 97 94 f6 eb bb c0 5d db b1 12 16 24 +7d 2f 41 2f d0 fb a8 7c 6e 3a cd 88 88 13 64 6f +d0 e4 8e 78 52 04 f9 c3 f7 3d 6d 82 39 56 27 22 +dd dd 87 71 fe c4 8b 83 a3 1e e6 f5 92 c4 cf d4 +bc 88 17 4f 3b 13 a1 12 aa e3 b9 f7 b8 0e 0f c6 +f7 25 5b a8 80 dc 7d 80 21 e2 2a d6 a8 5f 07 55 + +# --------------------------------- +# RSAES-OAEP Encryption Example 1.5 +# --------------------------------- + +# Message to be encrypted: +8d a8 9f d9 e5 f9 74 a2 9f ef fb 46 2b 49 18 0f +6c f9 e8 02 + +# Seed: +b3 18 c4 2d f3 be 0f 83 fe a8 23 f5 a7 b4 7e d5 +e4 25 a3 b5 + +# Encryption: +36 f6 e3 4d 94 a8 d3 4d aa cb a3 3a 21 39 d0 0a +d8 5a 93 45 a8 60 51 e7 30 71 62 00 56 b9 20 e2 +19 00 58 55 a2 13 a0 f2 38 97 cd cd 73 1b 45 25 +7c 77 7f e9 08 20 2b ef dd 0b 58 38 6b 12 44 ea +0c f5 39 a0 5d 5d 10 32 9d a4 4e 13 03 0f d7 60 +dc d6 44 cf ef 20 94 d1 91 0d 3f 43 3e 1c 7c 6d +d1 8b c1 f2 df 7f 64 3d 66 2f b9 dd 37 ea d9 05 +91 90 f4 fa 66 ca 39 e8 69 c4 eb 44 9c bd c4 39 + +# --------------------------------- +# RSAES-OAEP Encryption Example 1.6 +# --------------------------------- + +# Message to be encrypted: +26 52 10 50 84 42 71 + +# Seed: +e4 ec 09 82 c2 33 6f 3a 67 7f 6a 35 61 74 eb 0c +e8 87 ab c2 + +# Encryption: +42 ce e2 61 7b 1e ce a4 db 3f 48 29 38 6f bd 61 +da fb f0 38 e1 80 d8 37 c9 63 66 df 24 c0 97 b4 +ab 0f ac 6b df 59 0d 82 1c 9f 10 64 2e 68 1a d0 +5b 8d 78 b3 78 c0 f4 6c e2 fa d6 3f 74 e0 ad 3d +f0 6b 07 5d 7e b5 f5 63 6f 8d 40 3b 90 59 ca 76 +1b 5c 62 bb 52 aa 45 00 2e a7 0b aa ce 08 de d2 +43 b9 d8 cb d6 2a 68 ad e2 65 83 2b 56 56 4e 43 +a6 fa 42 ed 19 9a 09 97 69 74 2d f1 53 9e 82 55 + +# ============================================= + +# ================================== +# Example 2: A 1025-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5 +e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e +49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba +7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d +0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d +de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05 +5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66 +32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f +45 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa +4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93 +c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47 +39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc +d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0 +8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59 +41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25 +25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39 + +# Prime p: +01 59 db de 04 a3 3e f0 6f b6 08 b8 0b 19 0f 4d +3e 22 bc c1 3a c8 e4 a0 81 03 3a bf a4 16 ed b0 +b3 38 aa 08 b5 73 09 ea 5a 52 40 e7 dc 6e 54 37 +8c 69 41 4c 31 d9 7d db 1f 40 6d b3 76 9c c4 1a +43 + +# Prime q: +01 2b 65 2f 30 40 3b 38 b4 09 95 fd 6f f4 1a 1a +cc 8a da 70 37 32 36 b7 20 2d 39 b2 ee 30 cf b4 +6d b0 95 11 f6 f3 07 cc 61 cc 21 60 6c 18 a7 5b +8a 62 f8 22 df 03 1b a0 df 0d af d5 50 6f 56 8b +d7 + +# p's CRT exponent dP: +43 6e f5 08 de 73 65 19 c2 da 4c 58 0d 98 c8 2c +b7 45 2a 3f b5 ef ad c3 b9 c7 78 9a 1b c6 58 4f +79 5a dd bb d3 24 39 c7 46 86 55 2e cb 6c 2c 30 +7a 4d 3a f7 f5 39 ee c1 57 24 8c 7b 31 f1 a2 55 + +# q's CRT exponent dQ: +01 2b 15 a8 9f 3d fb 2b 39 07 3e 73 f0 2b dd 0c +1a 7b 37 9d d4 35 f0 5c dd e2 ef f9 e4 62 94 8b +7c ec 62 ee 90 50 d5 e0 81 6e 07 85 a8 56 b4 91 +08 dc b7 5f 36 83 87 4d 1c a6 32 9a 19 01 30 66 +ff + +# CRT coefficient qInv: +02 70 db 17 d5 91 4b 01 8d 76 11 8b 24 38 9a 73 +50 ec 83 6b 00 63 a2 17 21 23 6f d8 ed b6 d8 9b +51 e7 ee b8 7b 61 1b 71 32 cb 7e a7 35 6c 23 15 +1c 1e 77 51 50 7c 78 6d 9e e1 79 41 70 a8 c8 e8 + +# --------------------------------- +# RSAES-OAEP Encryption Example 2.1 +# --------------------------------- + +# Message to be encrypted: +8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6 +52 b5 8c f1 d9 2f ec 57 0b ee e7 + +# Seed: +8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94 +e7 1b 17 82 + +# Encryption: +01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99 +2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a +5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a +ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34 +56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d +56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a +bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f +ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72 +0e + +# --------------------------------- +# RSAES-OAEP Encryption Example 2.2 +# --------------------------------- + +# Message to be encrypted: +2d + +# Seed: +b6 00 cf 3c 2e 50 6d 7f 16 77 8c 91 0d 3a 8b 00 +3e ee 61 d5 + +# Encryption: +01 87 59 ff 1d f6 3b 27 92 41 05 62 31 44 16 a8 +ae af 2a c6 34 b4 6f 94 0a b8 2d 64 db f1 65 ee +e3 30 11 da 74 9d 4b ab 6e 2f cd 18 12 9c 9e 49 +27 7d 84 53 11 2b 42 9a 22 2a 84 71 b0 70 99 39 +98 e7 58 86 1c 4d 3f 6d 74 9d 91 c4 29 0d 33 2c +7a 4a b3 f7 ea 35 ff 3a 07 d4 97 c9 55 ff 0f fc +95 00 6b 62 c6 d2 96 81 0d 9b fa b0 24 19 6c 79 +34 01 2c 2d f9 78 ef 29 9a ba 23 99 40 cb a1 02 +45 + +# --------------------------------- +# RSAES-OAEP Encryption Example 2.3 +# --------------------------------- + +# Message to be encrypted: +74 fc 88 c5 1b c9 0f 77 af 9d 5e 9a 4a 70 13 3d +4b 4e 0b 34 da 3c 37 c7 ef 8e + +# Seed: +a7 37 68 ae ea a9 1f 9d 8c 1e d6 f9 d2 b6 34 67 +f0 7c ca e3 + +# Encryption: +01 88 02 ba b0 4c 60 32 5e 81 c4 96 23 11 f2 be +7c 2a dc e9 30 41 a0 07 19 c8 8f 95 75 75 f2 c7 +9f 1b 7b c8 ce d1 15 c7 06 b3 11 c0 8a 2d 98 6c +a3 b6 a9 33 6b 14 7c 29 c6 f2 29 40 9d de c6 51 +bd 1f dd 5a 0b 7f 61 0c 99 37 fd b4 a3 a7 62 36 +4b 8b 32 06 b4 ea 48 5f d0 98 d0 8f 63 d4 aa 8b +b2 69 7d 02 7b 75 0c 32 d7 f7 4e af 51 80 d2 e9 +b6 6b 17 cb 2f a5 55 23 bc 28 0d a1 0d 14 be 20 +53 + +# --------------------------------- +# RSAES-OAEP Encryption Example 2.4 +# --------------------------------- + +# Message to be encrypted: +a7 eb 2a 50 36 93 1d 27 d4 e8 91 32 6d 99 69 2f +fa dd a9 bf 7e fd 3e 34 e6 22 c4 ad c0 85 f7 21 +df e8 85 07 2c 78 a2 03 b1 51 73 9b e5 40 fa 8c +15 3a 10 f0 0a + +# Seed: +9a 7b 3b 0e 70 8b d9 6f 81 90 ec ab 4f b9 b2 b3 +80 5a 81 56 + +# Encryption: +00 a4 57 8c bc 17 63 18 a6 38 fb a7 d0 1d f1 57 +46 af 44 d4 f6 cd 96 d7 e7 c4 95 cb f4 25 b0 9c +64 9d 32 bf 88 6d a4 8f ba f9 89 a2 11 71 87 ca +fb 1f b5 80 31 76 90 e3 cc d4 46 92 0b 7a f8 2b +31 db 58 04 d8 7d 01 51 4a cb fa 91 56 e7 82 f8 +67 f6 be d9 44 9e 0e 9a 2c 09 bc ec c6 aa 08 76 +36 96 5e 34 b3 ec 76 6f 2f e2 e4 30 18 a2 fd de +b1 40 61 6a 0e 9d 82 e5 33 10 24 ee 06 52 fc 76 +41 + +# --------------------------------- +# RSAES-OAEP Encryption Example 2.5 +# --------------------------------- + +# Message to be encrypted: +2e f2 b0 66 f8 54 c3 3f 3b dc bb 59 94 a4 35 e7 +3d 6c 6c + +# Seed: +eb 3c eb bc 4a dc 16 bb 48 e8 8c 8a ec 0e 34 af +7f 42 7f d3 + +# Encryption: +00 eb c5 f5 fd a7 7c fd ad 3c 83 64 1a 90 25 e7 +7d 72 d8 a6 fb 33 a8 10 f5 95 0f 8d 74 c7 3e 8d +93 1e 86 34 d8 6a b1 24 62 56 ae 07 b6 00 5b 71 +b7 f2 fb 98 35 12 18 33 1c e6 9b 8f fb dc 9d a0 +8b bc 9c 70 4f 87 6d eb 9d f9 fc 2e c0 65 ca d8 +7f 90 90 b0 7a cc 17 aa 7f 99 7b 27 ac a4 88 06 +e8 97 f7 71 d9 51 41 fe 45 26 d8 a5 30 1b 67 86 +27 ef ab 70 7f d4 0f be bd 6e 79 2a 25 61 3e 7a +ec + +# --------------------------------- +# RSAES-OAEP Encryption Example 2.6 +# --------------------------------- + +# Message to be encrypted: +8a 7f b3 44 c8 b6 cb 2c f2 ef 1f 64 3f 9a 32 18 +f6 e1 9b ba 89 c0 + +# Seed: +4c 45 cf 4d 57 c9 8e 3d 6d 20 95 ad c5 1c 48 9e +b5 0d ff 84 + +# Encryption: +01 08 39 ec 20 c2 7b 90 52 e5 5b ef b9 b7 7e 6f +c2 6e 90 75 d7 a5 43 78 c6 46 ab df 51 e4 45 bd +57 15 de 81 78 9f 56 f1 80 3d 91 70 76 4a 9e 93 +cb 78 79 86 94 02 3e e7 39 3c e0 4b c5 d8 f8 c5 +a5 2c 17 1d 43 83 7e 3a ca 62 f6 09 eb 0a a5 ff +b0 96 0e f0 41 98 dd 75 4f 57 f7 fb e6 ab f7 65 +cf 11 8b 4c a4 43 b2 3b 5a ab 26 6f 95 23 26 ac +45 81 10 06 44 32 5f 8b 72 1a cd 5d 04 ff 14 ef +3a + +# ============================================= + +# ================================== +# Example 3: A 1026-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +02 b5 8f ec 03 9a 86 07 00 a4 d7 b6 46 2f 93 e6 +cd d4 91 16 1d dd 74 f4 e8 10 b4 0e 3c 16 52 00 +6a 5c 27 7b 27 74 c1 13 05 a4 cb ab 5a 78 ef a5 +7e 17 a8 6d f7 a3 fa 36 fc 4b 1d 22 49 f2 2e c7 +c2 dd 6a 46 32 32 ac ce a9 06 d6 6e be 80 b5 70 +4b 10 72 9d a6 f8 33 23 4a bb 5e fd d4 a2 92 cb +fa d3 3b 4d 33 fa 7a 14 b8 c3 97 b5 6e 3a cd 21 +20 34 28 b7 7c df a3 3a 6d a7 06 b3 d8 b0 fc 43 +e9 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +15 b4 8a 5b 56 83 a9 46 70 e2 3b 57 18 f8 14 fa +0e 13 f8 50 38 f5 07 11 18 2c ba 61 51 05 81 f3 +d2 2c 7e 23 2e f9 37 e2 2e 55 1d 68 b8 6e 2f 8c +b1 aa d8 be 2e 48 8f 5d f7 ef d2 79 e3 f5 68 d4 +ea f3 6f 80 cf 71 41 ac e6 0f cc 91 13 fb 6c 4a +84 1f d5 0b bc 7c 51 2f fc be ff 21 48 7a a8 11 +eb 3c a8 c6 20 05 34 6a 86 de 86 bf a1 d8 a9 48 +fd 3f 34 8c 22 ea ad f3 33 c3 ce 6c e1 32 08 fd + +# Prime p: +01 bf 01 d2 16 d7 35 95 cf 02 70 c2 be b7 8d 40 +a0 d8 44 7d 31 da 91 9a 98 3f 7e ea 78 1b 77 d8 +5f e3 71 b3 e9 37 3e 7b 69 21 7d 31 50 a0 2d 89 +58 de 7f ad 9d 55 51 60 95 8b 44 54 12 7e 0e 7e +af + +# Prime q: +01 8d 33 99 65 81 66 db 38 29 81 6d 7b 29 54 16 +75 9e 9c 91 98 7f 5b 2d 8a ec d6 3b 04 b4 8b d7 +b2 fc f2 29 bb 7f 8a 6d c8 8b a1 3d d2 e3 9a d5 +5b 6d 1a 06 16 07 08 f9 70 0b e8 0b 8f d3 74 4c +e7 + +# p's CRT exponent dP: +06 c0 a2 49 d2 0a 6f 2e e7 5c 88 b4 94 d5 3f 6a +ae 99 aa 42 7c 88 c2 8b 16 3a 76 94 45 e5 f3 90 +cf 40 c2 74 fd 6e a6 32 9a 5c e7 c7 ce 03 a2 15 +83 96 ee 2a 78 45 78 6e 09 e2 88 5a 97 28 e4 e5 + +# q's CRT exponent dQ: +d1 d2 7c 29 fe dd 92 d8 6c 34 8e dd 0c cb fa c1 +4f 74 6e 05 1c e1 d1 81 1d f3 5d 61 f2 ee 1c 97 +d4 bf 28 04 80 2f 64 27 18 7b a8 e9 0a 8a f4 42 +43 b4 07 9b 03 44 5e 60 2e 29 fa 51 93 e6 4f e9 + +# CRT coefficient qInv: +8c b2 f7 56 bd 89 41 b1 d3 b7 70 e5 ad 31 ee 37 +3b 28 ac da 69 ff 9b 6f 40 fe 57 8b 9f 1a fb 85 +83 6f 96 27 d3 7a cf f7 3c 27 79 e6 34 bb 26 01 +1c 2c 8f 7f 33 61 ae 2a 9e a6 5e d6 89 e3 63 9a + +# --------------------------------- +# RSAES-OAEP Encryption Example 3.1 +# --------------------------------- + +# Message to be encrypted: +08 78 20 b5 69 e8 fa 8d + +# Seed: +8c ed 6b 19 62 90 80 57 90 e9 09 07 40 15 e6 a2 +0b 0c 48 94 + +# Encryption: +02 6a 04 85 d9 6a eb d9 6b 43 82 08 50 99 b9 62 +e6 a2 bd ec 3d 90 c8 db 62 5e 14 37 2d e8 5e 2d +5b 7b aa b6 5c 8f af 91 bb 55 04 fb 49 5a fc e5 +c9 88 b3 f6 a5 2e 20 e1 d6 cb d3 56 6c 5c d1 f2 +b8 31 8b b5 42 cc 0e a2 5c 4a ab 99 32 af a2 07 +60 ea dd ec 78 43 96 a0 7e a0 ef 24 d4 e6 f4 d3 +7e 50 52 a7 a3 1e 14 6a a4 80 a1 11 bb e9 26 40 +13 07 e0 0f 41 00 33 84 2b 6d 82 fe 5c e4 df ae +80 + +# --------------------------------- +# RSAES-OAEP Encryption Example 3.2 +# --------------------------------- + +# Message to be encrypted: +46 53 ac af 17 19 60 b0 1f 52 a7 be 63 a3 ab 21 +dc 36 8e c4 3b 50 d8 2e c3 78 1e 04 + +# Seed: +b4 29 1d 65 67 55 08 48 cc 15 69 67 c8 09 ba ab +6c a5 07 f0 + +# Encryption: +02 4d b8 9c 78 02 98 9b e0 78 38 47 86 30 84 94 +1b f2 09 d7 61 98 7e 38 f9 7c b5 f6 f1 bc 88 da +72 a5 0b 73 eb af 11 c8 79 c4 f9 5d f3 7b 85 0b +8f 65 d7 62 2e 25 b1 b8 89 e8 0f e8 0b ac a2 06 +9d 6e 0e 1d 82 99 53 fc 45 90 69 de 98 ea 97 98 +b4 51 e5 57 e9 9a bf 8f e3 d9 cc f9 09 6e bb f3 +e5 25 5d 3b 4e 1c 6d 2e ca df 06 7a 35 9e ea 86 +40 5a cd 47 d5 e1 65 51 7c ca fd 47 d6 db ee 4b +f5 + +# --------------------------------- +# RSAES-OAEP Encryption Example 3.3 +# --------------------------------- + +# Message to be encrypted: +d9 4c d0 e0 8f a4 04 ed 89 + +# Seed: +ce 89 28 f6 05 95 58 25 40 08 ba dd 97 94 fa dc +d2 fd 1f 65 + +# Encryption: +02 39 bc e6 81 03 24 41 52 88 77 d6 d1 c8 bb 28 +aa 3b c9 7f 1d f5 84 56 36 18 99 57 97 68 38 44 +ca 86 66 47 32 f4 be d7 a0 aa b0 83 aa ab fb 72 +38 f5 82 e3 09 58 c2 02 4e 44 e5 70 43 b9 79 50 +fd 54 3d a9 77 c9 0c dd e5 33 7d 61 84 42 f9 9e +60 d7 78 3a b5 9c e6 dd 9d 69 c4 7a d1 e9 62 be +c2 2d 05 89 5c ff 8d 3f 64 ed 52 61 d9 2b 26 78 +51 03 93 48 49 90 ba 3f 7f 06 81 8a e6 ff ce 8a +3a + +# --------------------------------- +# RSAES-OAEP Encryption Example 3.4 +# --------------------------------- + +# Message to be encrypted: +6c c6 41 b6 b6 1e 6f 96 39 74 da d2 3a 90 13 28 +4e f1 + +# Seed: +6e 29 79 f5 2d 68 14 a5 7d 83 b0 90 05 48 88 f1 +19 a5 b9 a3 + +# Encryption: +02 99 4c 62 af d7 6f 49 8b a1 fd 2c f6 42 85 7f +ca 81 f4 37 3c b0 8f 1c ba ee 6f 02 5c 3b 51 2b +42 c3 e8 77 91 13 47 66 48 03 9d be 04 93 f9 24 +62 92 fa c2 89 50 60 0e 7c 0f 32 ed f9 c8 1b 9d +ec 45 c3 bd e0 cc 8d 88 47 59 01 69 90 7b 7d c5 +99 1c eb 29 bb 07 14 d6 13 d9 6d f0 f1 2e c5 d8 +d3 50 7c 8e e7 ae 78 dd 83 f2 16 fa 61 de 10 03 +63 ac a4 8a 7e 91 4a e9 f4 2d df be 94 3b 09 d9 +a0 + +# --------------------------------- +# RSAES-OAEP Encryption Example 3.5 +# --------------------------------- + +# Message to be encrypted: +df 51 51 83 2b 61 f4 f2 58 91 fb 41 72 f3 28 d2 +ed df 83 71 ff cf db e9 97 93 92 95 f3 0e ca 69 +18 01 7c fd a1 15 3b f7 a6 af 87 59 32 23 + +# Seed: +2d 76 0b fe 38 c5 9d e3 4c dc 8b 8c 78 a3 8e 66 +28 4a 2d 27 + +# Encryption: +01 62 04 2f f6 96 95 92 a6 16 70 31 81 1a 23 98 +34 ce 63 8a bf 54 fe c8 b9 94 78 12 2a fe 2e e6 +7f 8c 5b 18 b0 33 98 05 bf db c5 a4 e6 72 0b 37 +c5 9c fb a9 42 46 4c 59 7f f5 32 a1 19 82 15 45 +fd 2e 59 b1 14 e6 1d af 71 82 05 29 f5 02 9c f5 +24 95 43 27 c3 4e c5 e6 f5 ba 7e fc c4 de 94 3a +b8 ad 4e d7 87 b1 45 43 29 f7 0d b7 98 a3 a8 f4 +d9 2f 82 74 e2 b2 94 8a de 62 7c e8 ee 33 e4 3c +60 + +# --------------------------------- +# RSAES-OAEP Encryption Example 3.6 +# --------------------------------- + +# Message to be encrypted: +3c 3b ad 89 3c 54 4a 6d 52 0a b0 22 31 91 88 c8 +d5 04 b7 a7 88 b8 50 90 3b 85 97 2e aa 18 55 2e +11 34 a7 ad 60 98 82 62 54 ff 7a b6 72 b3 d8 eb +31 58 fa c6 d4 cb ae f1 + +# Seed: +f1 74 77 9c 5f d3 cf e0 07 ba dc b7 a3 6c 9b 55 +bf cf bf 0e + +# Encryption: +00 11 20 51 e7 5d 06 49 43 bc 44 78 07 5e 43 48 +2f d5 9c ee 06 79 de 68 93 ee c3 a9 43 da a4 90 +b9 69 1c 93 df c0 46 4b 66 23 b9 f3 db d3 e7 00 +83 26 4f 03 4b 37 4f 74 16 4e 1a 00 76 37 25 e5 +74 74 4b a0 b9 db 83 43 4f 31 df 96 f6 e2 a2 6f +6d 8e ba 34 8b d4 68 6c 22 38 ac 07 c3 7a ac 37 +85 d1 c7 ee a2 f8 19 fd 91 49 17 98 ed 8e 9c ef +5e 43 b7 81 b0 e0 27 6e 37 c4 3f f9 49 2d 00 57 +30 + +# ============================================= + +# ================================== +# Example 4: A 1027-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +05 12 40 b6 cc 00 04 fa 48 d0 13 46 71 c0 78 c7 +c8 de c3 b3 e2 f2 5b c2 56 44 67 33 9d b3 88 53 +d0 6b 85 ee a5 b2 de 35 3b ff 42 ac 2e 46 bc 97 +fa e6 ac 96 18 da 95 37 a5 c8 f5 53 c1 e3 57 62 +59 91 d6 10 8d cd 78 85 fb 3a 25 41 3f 53 ef ca +d9 48 cb 35 cd 9b 9a e9 c1 c6 76 26 d1 13 d5 7d +de 4c 5b ea 76 bb 5b b7 de 96 c0 0d 07 37 2e 96 +85 a6 d7 5c f9 d2 39 fa 14 8d 70 93 1b 5f 3f b0 +39 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +04 11 ff ca 3b 7c a5 e9 e9 be 7f e3 8a 85 10 5e +35 38 96 db 05 c5 79 6a ec d2 a7 25 16 1e b3 65 +1c 86 29 a9 b8 62 b9 04 d7 b0 c7 b3 7f 8c b5 a1 +c2 b5 40 01 01 8a 00 a1 eb 2c af e4 ee 4e 94 92 +c3 48 bc 2b ed ab 4b 9e bb f0 64 e8 ef f3 22 b9 +00 9f 8e ec 65 39 05 f4 0d f8 8a 3c dc 49 d4 56 +7f 75 62 7d 41 ac a6 24 12 9b 46 a0 b7 c6 98 e5 +e6 5f 2b 7b a1 02 c7 49 a1 01 35 b6 54 0d 04 01 + +# Prime p: +02 74 58 c1 9e c1 63 69 19 e7 36 c9 af 25 d6 09 +a5 1b 8f 56 1d 19 c6 bf 69 43 dd 1e e1 ab 8a 4a +3f 23 21 00 bd 40 b8 8d ec c6 ba 23 55 48 b6 ef +79 2a 11 c9 de 82 3d 0a 79 22 c7 09 5b 6e ba 57 +01 + +# Prime q: +02 10 ee 9b 33 ab 61 71 6e 27 d2 51 bd 46 5f 4b +35 a1 a2 32 e2 da 00 90 1c 29 4b f2 23 50 ce 49 +0d 09 9f 64 2b 53 75 61 2d b6 3b a1 f2 03 86 49 +2b f0 4d 34 b3 c2 2b ce b9 09 d1 34 41 b5 3b 51 +39 + +# p's CRT exponent dP: +39 fa 02 8b 82 6e 88 c1 12 1b 75 0a 8b 24 2f a9 +a3 5c 5b 66 bd fd 1f a6 37 d3 cc 48 a8 4a 4f 45 +7a 19 4e 77 27 e4 9f 7b cc 6e 5a 5a 41 26 57 fc +47 0c 73 22 eb c3 74 16 ef 45 8c 30 7a 8c 09 01 + +# q's CRT exponent dQ: +01 5d 99 a8 41 95 94 39 79 fa 9e 1b e2 c3 c1 b6 +9f 43 2f 46 fd 03 e4 7d 5b ef bb bf d6 b1 d1 37 +1d 83 ef b3 30 a3 e0 20 94 2b 2f ed 11 5e 5d 02 +be 24 fd 92 c9 01 9d 1c ec d6 dd 4c f1 e5 4c c8 +99 + +# CRT coefficient qInv: +01 f0 b7 01 51 70 b3 f5 e4 22 23 ba 30 30 1c 41 +a6 d8 7c bb 70 e3 0c b7 d3 c6 7d 25 47 3d b1 f6 +cb f0 3e 3f 91 26 e3 e9 79 68 27 9a 86 5b 2c 2b +42 65 24 cf c5 2a 68 3d 31 ed 30 eb 98 4b e4 12 +ba + +# --------------------------------- +# RSAES-OAEP Encryption Example 4.1 +# --------------------------------- + +# Message to be encrypted: +4a 86 60 95 34 ee 43 4a 6c bc a3 f7 e9 62 e7 6d +45 5e 32 64 c1 9f 60 5f 6e 5f f6 13 7c 65 c5 6d +7f b3 44 cd 52 bc 93 37 4f 3d 16 6c 9f 0c 6f 9c +50 6b ad 19 33 09 72 d2 + +# Seed: +1c ac 19 ce 99 3d ef 55 f9 82 03 f6 85 28 96 c9 +5c cc a1 f3 + +# Encryption: +04 cc e1 96 14 84 5e 09 41 52 a3 fe 18 e5 4e 33 +30 c4 4e 5e fb c6 4a e1 68 86 cb 18 69 01 4c c5 +78 1b 1f 8f 9e 04 53 84 d0 11 2a 13 5c a0 d1 2e +9c 88 a8 e4 06 34 16 de aa e3 84 4f 60 d6 e9 6f +e1 55 14 5f 45 25 b9 a3 44 31 ca 37 66 18 0f 70 +e1 5a 5e 5d 8e 8b 1a 51 6f f8 70 60 9f 13 f8 96 +93 5c ed 18 82 79 a5 8e d1 3d 07 11 42 77 d7 5c +65 68 60 7e 0a b0 92 fd 80 3a 22 3e 4a 8e e0 b1 +a8 + +# --------------------------------- +# RSAES-OAEP Encryption Example 4.2 +# --------------------------------- + +# Message to be encrypted: +b0 ad c4 f3 fe 11 da 59 ce 99 27 73 d9 05 99 43 +c0 30 46 49 7e e9 d9 f9 a0 6d f1 16 6d b4 6d 98 +f5 8d 27 ec 07 4c 02 ee e6 cb e2 44 9c 8b 9f c5 +08 0c 5c 3f 44 33 09 25 12 ec 46 aa 79 37 43 c8 + +# Seed: +f5 45 d5 89 75 85 e3 db 71 aa 0c b8 da 76 c5 1d +03 2a e9 63 + +# Encryption: +00 97 b6 98 c6 16 56 45 b3 03 48 6f bf 5a 2a 44 +79 c0 ee 85 88 9b 54 1a 6f 0b 85 8d 6b 65 97 b1 +3b 85 4e b4 f8 39 af 03 39 9a 80 d7 9b da 65 78 +c8 41 f9 0d 64 57 15 b2 80 d3 71 43 99 2d d1 86 +c8 0b 94 9b 77 5c ae 97 37 0e 4e c9 74 43 13 6c +6d a4 84 e9 70 ff db 13 23 a2 08 47 82 1d 3b 18 +38 1d e1 3b b4 9a ae a6 65 30 c4 a4 b8 27 1f 3e +ae 17 2c d3 66 e0 7e 66 36 f1 01 9d 2a 28 ae d1 +5e + +# --------------------------------- +# RSAES-OAEP Encryption Example 4.3 +# --------------------------------- + +# Message to be encrypted: +bf 6d 42 e7 01 70 7b 1d 02 06 b0 c8 b4 5a 1c 72 +64 1f f1 28 89 21 9a 82 bd ea 96 5b 5e 79 a9 6b +0d 01 63 ed 9d 57 8e c9 ad a2 0f 2f bc f1 ea 3c +40 89 d8 34 19 ba 81 b0 c6 0f 36 06 da 99 + +# Seed: +ad 99 7f ee f7 30 d6 ea 7b e6 0d 0d c5 2e 72 ea +cb fd d2 75 + +# Encryption: +03 01 f9 35 e9 c4 7a bc b4 8a cb be 09 89 5d 9f +59 71 af 14 83 9d a4 ff 95 41 7e e4 53 d1 fd 77 +31 90 72 bb 72 97 e1 b5 5d 75 61 cd 9d 1b b2 4c +1a 9a 37 c6 19 86 43 08 24 28 04 87 9d 86 eb d0 +01 dc e5 18 39 75 e1 50 69 89 b7 0e 5a 83 43 41 +54 d5 cb fd 6a 24 78 7e 60 eb 0c 65 8d 2a c1 93 +30 2d 11 92 c6 e6 22 d4 a1 2a d4 b5 39 23 bc a2 +46 df 31 c6 39 5e 37 70 2c 6a 78 ae 08 1f b9 d0 +65 + +# --------------------------------- +# RSAES-OAEP Encryption Example 4.4 +# --------------------------------- + +# Message to be encrypted: +fb 2e f1 12 f5 e7 66 eb 94 01 92 97 93 47 94 f7 +be 2f 6f c1 c5 8e + +# Seed: +13 64 54 df 57 30 f7 3c 80 7a 7e 40 d8 c1 a3 12 +ac 5b 9d d3 + +# Encryption: +02 d1 10 ad 30 af b7 27 be b6 91 dd 0c f1 7d 0a +f1 a1 e7 fa 0c c0 40 ec 1a 4b a2 6a 42 c5 9d 0a +79 6a 2e 22 c8 f3 57 cc c9 8b 65 19 ac eb 68 2e +94 5e 62 cb 73 46 14 a5 29 40 7c d4 52 be e3 e4 +4f ec e8 42 3c c1 9e 55 54 8b 8b 99 4b 84 9c 7e +cd e4 93 3e 76 03 7e 1d 0c e4 42 75 b0 87 10 c6 +8e 43 01 30 b9 29 73 0e d7 7e 09 b0 15 64 2c 55 +93 f0 4e 4f fb 94 10 79 81 02 a8 e9 6f fd fe 11 +e4 + +# --------------------------------- +# RSAES-OAEP Encryption Example 4.5 +# --------------------------------- + +# Message to be encrypted: +28 cc d4 47 bb 9e 85 16 6d ab b9 e5 b7 d1 ad ad +c4 b9 d3 9f 20 4e 96 d5 e4 40 ce 9a d9 28 bc 1c +22 84 + +# Seed: +bc a8 05 7f 82 4b 2e a2 57 f2 86 14 07 ee f6 3d +33 20 86 81 + +# Encryption: +00 db b8 a7 43 9d 90 ef d9 19 a3 77 c5 4f ae 8f +e1 1e c5 8c 3b 85 83 62 e2 3a d1 b8 a4 43 10 79 +90 66 b9 93 47 aa 52 56 91 d2 ad c5 8d 9b 06 e3 +4f 28 8c 17 03 90 c5 f0 e1 1c 0a a3 64 59 59 f1 +8e e7 9e 8f 2b e8 d7 ac 5c 23 d0 61 f1 8d d7 4b +8c 5f 2a 58 fc b5 eb 0c 54 f9 9f 01 a8 32 47 56 +82 92 53 65 83 34 09 48 d7 a8 c9 7c 4a cd 1e 98 +d1 e2 9d c3 20 e9 7a 26 05 32 a8 aa 7a 75 8a 1e +c2 + +# --------------------------------- +# RSAES-OAEP Encryption Example 4.6 +# --------------------------------- + +# Message to be encrypted: +f2 22 42 75 1e c6 b1 + +# Seed: +2e 7e 1e 17 f6 47 b5 dd d0 33 e1 54 72 f9 0f 68 +12 f3 ac 4e + +# Encryption: +00 a5 ff a4 76 8c 8b be ca ee 2d b7 7e 8f 2e ec +99 59 59 33 54 55 20 83 5e 5b a7 db 94 93 d3 e1 +7c dd ef e6 a5 f5 67 62 44 71 90 8d b4 e2 d8 3a +0f be e6 06 08 fc 84 04 95 03 b2 23 4a 07 dc 83 +b2 7b 22 84 7a d8 92 0f f4 2f 67 4e f7 9b 76 28 +0b 00 23 3d 2b 51 b8 cb 27 03 a9 d4 2b fb c8 25 +0c 96 ec 32 c0 51 e5 7f 1b 4b a5 28 db 89 c3 7e +4c 54 e2 7e 6e 64 ac 69 63 5a e8 87 d9 54 16 19 +a9 + +# ============================================= + +# ================================== +# Example 5: A 1028-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +0a ad f3 f9 c1 25 e5 d8 91 f3 1a c4 48 e9 93 de +fe 58 0f 80 2b 45 f9 d7 f2 2b a5 02 1e 9c 47 57 +6b 5a 1e 68 03 1b a9 db 4e 6d ab e4 d9 6a 1d 6f +3d 26 72 68 cf f4 08 00 5f 11 8e fc ad b9 98 88 +d1 c2 34 46 71 66 b2 a2 b8 49 a0 5a 88 9c 06 0a +c0 da 0c 5f ae 8b 55 f3 09 ba 62 e7 03 74 2f a0 +32 6f 2d 10 b0 11 02 14 89 ff 49 77 70 19 0d 89 +5f d3 9f 52 29 3c 39 ef d7 3a 69 8b da b9 f1 0e +d9 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +02 56 eb 4c ba 70 67 f2 d2 be 54 0d cd ff 45 82 +a3 6b 7d 31 d1 c9 09 9b b2 14 b7 98 48 46 6a 26 +8f 80 f5 8a 49 ac 04 c0 e3 64 89 34 a0 20 6c 04 +53 7c 19 b2 36 64 3a 60 82 73 21 44 df 75 fa 21 +75 88 f7 94 68 2b e8 91 68 27 6d c7 26 c5 c0 cb +db 84 d3 1b bf 26 d0 a4 3a f4 95 71 7f 7d 52 8a +cf ee 34 15 61 f6 ff 3c ae 05 c5 78 f8 47 0d 96 +82 f9 c0 d0 72 f9 f6 06 8b 56 d5 88 0f 68 2b e2 +c5 + +# Prime p: +03 b0 d3 96 2f 6d 17 54 9c bf ca 11 29 43 48 dc +f0 e7 e3 9f 8c 2b c6 82 4f 21 64 b6 06 d6 87 86 +0d ae 1e 63 23 93 cf ed f5 13 22 82 29 06 9e 2f +60 e4 ac d7 e6 33 a4 36 06 3f 82 38 5f 48 99 37 +07 + +# Prime q: +02 e4 c3 2e 2f 51 72 69 b7 07 23 09 f0 0c 0e 31 +36 5f 7c e2 8b 23 6b 82 91 2d f2 39 ab f3 95 72 +cf 0e d6 04 b0 29 82 e5 35 64 c5 2d 6a 05 39 7d +e5 c0 52 a2 fd dc 14 1e f7 18 98 36 34 6a eb 33 +1f + +# p's CRT exponent dP: +01 e8 4b 11 9d 25 16 1f a6 7b 00 25 6a 5b d9 b6 +45 d2 b2 32 ec b0 5b 01 51 80 02 9a 88 62 2a dc +3f 09 b3 ae ac de 61 61 ab 7c de 22 c2 ad 26 e7 +79 7d f5 4e 07 2c bd 3b 26 73 80 0b 3e 43 38 db +d5 + +# q's CRT exponent dQ: +eb 90 aa 1a 40 13 5b 4c ea 07 19 7c ed c8 81 9b +e1 e7 cb ff 25 47 66 21 16 f4 65 a4 a9 f4 87 ab +12 f3 ba 4f ef 13 82 22 65 a6 52 97 d9 8b 7b de +d9 37 2e 3f fe 81 a3 8b 3e 96 00 fe d0 55 75 4f + +# CRT coefficient qInv: +01 2f 7f 81 38 f9 40 40 62 eb 85 a4 29 24 52 0b +38 f5 bb 88 6a 01 96 f4 8b b8 dc ea 60 fd 92 cc +02 7f 18 e7 81 58 a3 4a 5c 5d 5f 86 0a 0f 6c 04 +07 1a 7d 01 31 2c 06 50 62 f1 eb 48 b7 9d 1c 83 +cb + +# --------------------------------- +# RSAES-OAEP Encryption Example 5.1 +# --------------------------------- + +# Message to be encrypted: +af 71 a9 01 e3 a6 1d 31 32 f0 fc 1f db 47 4f 9e +a6 57 92 57 ff c2 4d 16 41 70 14 5b 3d bd e8 + +# Seed: +44 c9 2e 28 3f 77 b9 49 9c 60 3d 96 36 60 c8 7d +2f 93 94 61 + +# Encryption: +03 60 46 a4 a4 7d 9e d3 ba 9a 89 13 9c 10 50 38 +eb 74 92 b0 5a 5d 68 bf d5 3a cc ff 45 97 f7 a6 +86 51 b4 7b 4a 46 27 d9 27 e4 85 ee d7 b4 56 64 +20 e8 b4 09 87 9e 5d 60 6e ae 25 1d 22 a5 df 79 +9f 79 20 bf c1 17 b9 92 57 2a 53 b1 26 31 46 bc +ea 03 38 5c c5 e8 53 c9 a1 01 c8 c3 e1 bd a3 1a +51 98 07 49 6c 6c b5 e5 ef b4 08 82 3a 35 2b 8f +a0 66 1f b6 64 ef ad d5 93 de b9 9f ff 5e d0 00 +e5 + +# --------------------------------- +# RSAES-OAEP Encryption Example 5.2 +# --------------------------------- + +# Message to be encrypted: +a3 b8 44 a0 82 39 a8 ac 41 60 5a f1 7a 6c fd a4 +d3 50 13 65 85 90 3a 41 7a 79 26 87 60 51 9a 4b +4a c3 30 3e c7 3f 0f 87 cf b3 23 99 + +# Seed: +cb 28 f5 86 06 59 fc ee e4 9c 3e ea fc e6 25 a7 +08 03 bd 32 + +# Encryption: +03 d6 eb 65 4e dc e6 15 bc 59 f4 55 26 5e d4 e5 +a1 82 23 cb b9 be 4e 40 69 b4 73 80 4d 5d e9 6f +54 dc aa a6 03 d0 49 c5 d9 4a a1 47 0d fc d2 25 +40 66 b7 c7 b6 1f f1 f6 f6 77 0e 32 15 c5 13 99 +fd 4e 34 ec 50 82 bc 48 f0 89 84 0a d0 43 54 ae +66 dc 0f 1b d1 8e 46 1a 33 cc 12 58 b4 43 a2 83 +7a 6d f2 67 59 aa 23 02 33 49 86 f8 73 80 c9 cc +9d 53 be 9f 99 60 5d 2c 9a 97 da 7b 09 15 a4 a7 +ad + +# --------------------------------- +# RSAES-OAEP Encryption Example 5.3 +# --------------------------------- + +# Message to be encrypted: +30 8b 0e cb d2 c7 6c b7 7f c6 f7 0c 5e dd 23 3f +d2 f2 09 29 d6 29 f0 26 95 3b b6 2a 8f 4a 3a 31 +4b de 19 5d e8 5b 5f 81 6d a2 aa b0 74 d2 6c b6 +ac dd f3 23 ae 3b 9c 67 8a c3 cf 12 fb dd e7 + +# Seed: +22 85 f4 0d 77 04 82 f9 a9 ef a2 c7 2c b3 ac 55 +71 6d c0 ca + +# Encryption: +07 70 95 21 81 64 9f 9f 9f 07 ff 62 6f f3 a2 2c +35 c4 62 44 3d 90 5d 45 6a 9f d0 bf f4 3c ac 2c +a7 a9 f5 54 e9 47 8b 9a cc 3a c8 38 b0 20 40 ff +d3 e1 84 7d e2 e4 25 39 29 f9 dd 9e e4 04 43 25 +a9 b0 5c ab b8 08 b2 ee 84 0d 34 e1 5d 10 5a 3f +1f 7b 27 69 5a 1a 07 a2 d7 3f e0 8e ca aa 3c 9c +9d 4d 5a 89 ff 89 0d 54 72 7d 7a e4 0c 0e c1 a8 +dd 86 16 5d 8e e2 c6 36 81 41 01 6a 48 b5 5b 69 +67 + +# --------------------------------- +# RSAES-OAEP Encryption Example 5.4 +# --------------------------------- + +# Message to be encrypted: +15 c5 b9 ee 11 85 + +# Seed: +49 fa 45 d3 a7 8d d1 0d fd 57 73 99 d1 eb 00 af +7e ed 55 13 + +# Encryption: +08 12 b7 67 68 eb cb 64 2d 04 02 58 e5 f4 44 1a +01 85 21 bd 96 68 7e 6c 5e 89 9f cd 6c 17 58 8f +f5 9a 82 cc 8a e0 3a 4b 45 b3 12 99 af 17 88 c3 +29 f7 dc d2 85 f8 cf 4c ed 82 60 6b 97 61 26 71 +a4 5b ed ca 13 34 42 14 4d 16 17 d1 14 f8 02 85 +7f 0f 9d 73 97 51 c5 7a 3f 9e e4 00 91 2c 61 e2 +e6 99 2b e0 31 a4 3d d4 8f a6 ba 14 ee f7 c4 22 +b5 ed c4 e7 af a0 4f dd 38 f4 02 d1 c8 bb 71 9a +bf + +# --------------------------------- +# RSAES-OAEP Encryption Example 5.5 +# --------------------------------- + +# Message to be encrypted: +21 02 6e 68 00 c7 fa 72 8f ca ab a0 d1 96 ae 28 +d7 a2 ac 4f fd 8a bc e7 94 f0 98 5f 60 c8 a6 73 +72 77 36 5d 3f ea 11 db 89 23 a2 02 9a + +# Seed: +f0 28 74 13 23 4c c5 03 47 24 a0 94 c4 58 6b 87 +af f1 33 fc + +# Encryption: +07 b6 0e 14 ec 95 4b fd 29 e6 0d 00 47 e7 89 f5 +1d 57 18 6c 63 58 99 03 30 67 93 ce d3 f6 82 41 +c7 43 52 9a ba 6a 63 74 f9 2e 19 e0 16 3e fa 33 +69 7e 19 6f 76 61 df aa a4 7a ac 6b de 5e 51 de +b5 07 c7 2c 58 9a 2c a1 69 3d 96 b1 46 03 81 24 +9b 2c db 9e ac 44 76 9f 24 89 c5 d3 d2 f9 9f 0e +e3 c7 ee 5b f6 4a 5a c7 9c 42 bd 43 3f 14 9b e8 +cb 59 54 83 61 64 05 95 51 3c 97 af 7b c2 50 97 +23 + +# --------------------------------- +# RSAES-OAEP Encryption Example 5.6 +# --------------------------------- + +# Message to be encrypted: +54 1e 37 b6 8b 6c 88 72 b8 4c 02 + +# Seed: +d9 fb a4 5c 96 f2 1e 6e 26 d2 9e b2 cd cb 65 85 +be 9c b3 41 + +# Encryption: +08 c3 6d 4d da 33 42 3b 2e d6 83 0d 85 f6 41 1b +a1 dc f4 70 a1 fa e0 eb ef ee 7c 08 9f 25 6c ef +74 cb 96 ea 69 c3 8f 60 f3 9a be e4 41 29 bc b4 +c9 2d e7 f7 97 62 3b 20 07 4e 3d 9c 28 99 70 1e +d9 07 1e 1e fa 0b dd 84 d4 c3 e5 13 03 02 d8 f0 +24 0b ab a4 b8 4a 71 cc 03 2f 22 35 a5 ff 0f ae +27 7c 3e 8f 91 12 be f4 4c 9a e2 0d 17 5f c9 a4 +05 8b fc 93 0b a3 1b 02 e2 e4 f4 44 48 37 10 f2 +4a + +# ============================================= + +# ================================== +# Example 6: A 1029-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +12 b1 7f 6d ad 2e cd 19 ff 46 dc 13 f7 86 0f 09 +e0 e0 cf b6 77 b3 8a 52 59 23 05 ce af 02 2c 16 +6d b9 0d 04 ac 29 e3 3f 7d d1 2d 9f af 66 e0 81 +6b b6 3e ad 26 7c c7 d4 6c 17 c3 7b e2 14 bc a2 +a2 2d 72 3a 64 e4 44 07 43 6b 6f c9 65 72 9a ef +c2 55 4f 37 6c d5 dc ea 68 29 37 80 a6 2b f3 9d +00 29 48 5a 16 0b bb 9e 5d c0 97 2d 21 a5 04 f5 +2e 5e e0 28 aa 41 63 32 f5 10 b2 e9 cf f5 f7 22 +af + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +02 95 ec a3 56 06 18 36 95 59 ce cd 30 3a a9 cf +da fc 1d 9f 06 95 9d f7 5f fe f9 29 aa 89 69 61 +bc d1 90 dc 69 97 ed a7 f5 96 3e 72 4d 07 b4 dc +11 f3 06 5e 5a e9 7d 96 83 51 12 28 0b 90 84 bb +14 f2 a2 1e bd 4e 88 9d 41 b9 c4 13 2e c1 95 6f +ca b8 bb 2f ed 05 75 88 49 36 52 2c 5f f7 d3 32 +61 90 48 24 e7 ca de e4 e0 bb 37 2d 24 57 cf 78 +e2 bd 12 86 22 8f f8 3f 10 73 1c e6 3c 90 cf f3 +f9 + +# Prime p: +04 a6 ce 8b 73 58 df a6 9b dc f7 42 61 70 05 af +b5 38 5f 5f 3a 58 a2 4e f7 4a 22 a8 c0 5c b7 cc +38 eb d4 cc 9d 9a 9d 78 9a 62 cd 0f 60 f0 cb 94 +1d 34 23 c9 69 2e fa 4f e3 ad ff 29 0c 47 49 a3 +8b + +# Prime q: +04 04 c9 a8 03 37 1f ed b4 c5 be 39 f3 c0 0b 00 +9e 5e 08 a6 3b e1 e4 00 35 cd ac a5 01 1c c7 01 +cf 7e eb cb 99 f0 ff e1 7c fd 0a 4b f7 be fd 2d +d5 36 ac 94 6d b7 97 fd bc 4a be 8f 29 34 9b 91 +ed + +# p's CRT exponent dP: +03 96 1c 8f 76 0a a2 bd 51 54 c7 aa fd 77 22 5b +3b ac d0 13 9a e7 b5 94 8e a3 31 1f cc d8 6f b9 +5c 75 af a7 67 28 4b 9b 2d e5 59 57 2f 15 d8 d0 +44 c7 eb 83 a1 be 5f ad f2 cc 37 7c 0d 84 75 29 +4b + +# q's CRT exponent dQ: +02 21 97 e0 66 74 21 96 aa bc 03 fa 2f ee b4 e7 +0b 15 cb 78 7d 61 7a cd 31 bb 75 c7 bc 23 4a d7 +06 f7 c4 8d 21 82 d1 f0 ff 9c 22 8d cf 41 96 7b +6c 0b a6 d2 c0 ad 11 0a 1b 85 78 31 ec 24 5e 2c +b1 + +# CRT coefficient qInv: +04 01 c4 c0 c5 3d 45 db db 5e 9d 96 d0 fe cf 42 +75 df 09 74 bc 4a 07 36 b4 a7 4c 32 69 05 3e fb +68 6a ce 24 06 e2 2c 9e 05 8d db 4a e5 40 62 7a +e2 fd b0 82 61 e8 e7 e4 bc bc 99 4d aa fa 30 5c +45 + +# --------------------------------- +# RSAES-OAEP Encryption Example 6.1 +# --------------------------------- + +# Message to be encrypted: +40 46 ca 8b aa 33 47 ca 27 f4 9e 0d 81 f9 cc 1d +71 be 9b a5 17 d4 + +# Seed: +dd 0f 6c fe 41 5e 88 e5 a4 69 a5 1f bb a6 df d4 +0a db 43 84 + +# Encryption: +06 30 ee bc d2 85 6c 24 f7 98 80 6e 41 f9 e6 73 +45 ed a9 ce da 38 6a cc 9f ac ae a1 ee ed 06 ac +e5 83 70 97 18 d9 d1 69 fa df 41 4d 5c 76 f9 29 +96 83 3e f3 05 b7 5b 1e 4b 95 f6 62 a2 0f ae dc +3b ae 0c 48 27 a8 bf 8a 88 ed bd 57 ec 20 3a 27 +a8 41 f0 2e 43 a6 15 ba b1 a8 ca c0 70 1d e3 4d +eb de f6 2a 08 80 89 b5 5e c3 6e a7 52 2f d3 ec +8d 06 b6 a0 73 e6 df 83 31 53 bc 0a ef d9 3b d1 +a3 + +# --------------------------------- +# RSAES-OAEP Encryption Example 6.2 +# --------------------------------- + +# Message to be encrypted: +5c c7 2c 60 23 1d f0 3b 3d 40 f9 b5 79 31 bc 31 +10 9f 97 25 27 f2 8b 19 e7 48 0c 72 88 cb 3c 92 +b2 25 12 21 4e 4b e6 c9 14 79 2d da bd f5 7f aa +8a a7 + +# Seed: +8d 14 bd 94 6a 13 51 14 8f 5c ae 2e d9 a0 c6 53 +e8 5e bd 85 + +# Encryption: +0e bc 37 37 61 73 a4 fd 2f 89 cc 55 c2 ca 62 b2 +6b 11 d5 1c 3c 7c e4 9e 88 45 f7 4e 76 07 31 7c +43 6b c8 d2 3b 96 67 df eb 9d 08 72 34 b4 7b c6 +83 71 75 ae 5c 05 59 f6 b8 1d 7d 22 41 6d 3e 50 +f4 ac 53 3d 8f 08 12 f2 db 9e 79 1f e9 c7 75 ac +8b 6a d0 f5 35 ad 9c eb 23 a4 a0 20 14 c5 8a b3 +f8 d3 16 14 99 a2 60 f3 93 48 e7 14 ae 2a 1d 34 +43 20 8f d8 b7 22 cc fd fb 39 3e 98 01 1f 99 e6 +3f + +# --------------------------------- +# RSAES-OAEP Encryption Example 6.3 +# --------------------------------- + +# Message to be encrypted: +b2 0e 65 13 03 09 2f 4b cc b4 30 70 c0 f8 6d 23 +04 93 62 ed 96 64 2f c5 63 2c 27 db 4a 52 e3 d8 +31 f2 ab 06 8b 23 b1 49 87 9c 00 2f 6b f3 fe ee +97 59 11 12 56 2c + +# Seed: +6c 07 5b c4 55 20 f1 65 c0 bf 5e a4 c5 df 19 1b +c9 ef 0e 44 + +# Encryption: +0a 98 bf 10 93 61 93 94 43 6c f6 8d 8f 38 e2 f1 +58 fd e8 ea 54 f3 43 5f 23 9b 8d 06 b8 32 18 44 +20 24 76 ae ed 96 00 94 92 48 0c e3 a8 d7 05 49 +8c 4c 8c 68 f0 15 01 dc 81 db 60 8f 60 08 73 50 +c8 c3 b0 bd 2e 9e f6 a8 14 58 b7 c8 01 b8 9f 2e +4f e9 9d 49 00 ba 6a 4b 5e 5a 96 d8 65 dc 67 6c +77 55 92 87 94 13 0d 62 80 a8 16 0a 19 0f 2d f3 +ea 7c f9 aa 02 71 d8 8e 9e 69 05 ec f1 c5 15 2d +65 + +# --------------------------------- +# RSAES-OAEP Encryption Example 6.4 +# --------------------------------- + +# Message to be encrypted: +68 4e 30 38 c5 c0 41 f7 + +# Seed: +3b bc 3b d6 63 7d fe 12 84 69 01 02 9b f5 b0 c0 +71 03 43 9c + +# Encryption: +00 8e 7a 67 ca cf b5 c4 e2 4b ec 7d ee 14 91 17 +f1 95 98 ce 8c 45 80 8f ef 88 c6 08 ff 9c d6 e6 +95 26 3b 9a 3c 0a d4 b8 ba 4c 95 23 8e 96 a8 42 +2b 85 35 62 9c 8d 53 82 37 44 79 ad 13 fa 39 97 +4b 24 2f 9a 75 9e ea f9 c8 3a d5 a8 ca 18 94 0a +01 62 ba 75 58 76 df 26 3f 4b d5 0c 65 25 c5 60 +90 26 7c 1f 0e 09 ce 08 99 a0 cf 35 9e 88 12 0a +bd 9b f8 93 44 5b 3c ae 77 d3 60 73 59 ae 9a 52 +f8 + +# --------------------------------- +# RSAES-OAEP Encryption Example 6.5 +# --------------------------------- + +# Message to be encrypted: +32 48 8c b2 62 d0 41 d6 e4 dd 35 f9 87 bf 3c a6 +96 db 1f 06 ac 29 a4 46 93 + +# Seed: +b4 6b 41 89 3e 8b ef 32 6f 67 59 38 3a 83 07 1d +ae 7f ca bc + +# Encryption: +00 00 34 74 41 6c 7b 68 bd f9 61 c3 85 73 79 44 +d7 f1 f4 0c b3 95 34 3c 69 3c c0 b4 fe 63 b3 1f +ed f1 ea ee ac 9c cc 06 78 b3 1d c3 2e 09 77 48 +95 14 c4 f0 90 85 f6 29 8a 96 53 f0 1a ea 40 45 +ff 58 2e e8 87 be 26 ae 57 5b 73 ee f7 f3 77 49 +21 e3 75 a3 d1 9a dd a0 ca 31 aa 18 49 88 7c 1f +42 ca c9 67 7f 7a 2f 4e 92 3f 6e 5a 86 8b 38 c0 +84 ef 18 75 94 dc 9f 7f 04 8f ea 2e 02 95 53 84 +ab + +# --------------------------------- +# RSAES-OAEP Encryption Example 6.6 +# --------------------------------- + +# Message to be encrypted: +50 ba 14 be 84 62 72 02 79 c3 06 ba + +# Seed: +0a 24 03 31 2a 41 e3 d5 2f 06 0f bc 13 a6 7d e5 +cf 76 09 a7 + +# Encryption: +0a 02 6d da 5f c8 78 5f 7b d9 bf 75 32 7b 63 e8 +5e 2c 0f de e5 da db 65 eb dc ac 9a e1 de 95 c9 +2c 67 2a b4 33 aa 7a 8e 69 ce 6a 6d 88 97 fa c4 +ac 4a 54 de 84 1a e5 e5 bb ce 76 87 87 9d 79 63 +4c ea 7a 30 68 40 65 c7 14 d5 24 09 b9 28 25 6b +bf 53 ea bc d5 23 1e b7 25 95 04 53 73 99 bd 29 +16 4b 72 6d 33 a4 6d a7 01 36 0a 41 68 a0 91 cc +ab 72 d4 4a 62 fe d2 46 c0 ff ea 5b 13 48 ab 54 +70 + +# ============================================= + +# ================================== +# Example 7: A 1030-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +31 11 79 f0 bc fc 9b 9d 3c a3 15 d0 0e f3 0d 7b +dd 3a 2c fa e9 91 1b fe dc b9 48 b3 a4 78 2d 07 +32 b6 ab 44 aa 4b f0 37 41 a6 44 dc 01 be c3 e6 +9b 01 a0 33 e6 75 d8 ac d7 c4 92 5c 6b 1a ec 31 +19 05 1d fd 89 76 2d 21 5d 45 47 5f fc b5 9f 90 +81 48 62 3f 37 17 71 56 f6 ae 86 dd 7a 7c 5f 43 +dc 1e 1f 90 82 54 05 8a 28 4a 5f 06 c0 02 17 93 +a8 7f 1a c5 fe ff 7d ca ee 69 c5 e5 1a 37 89 e3 +73 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +07 0c fc ff 2f eb 82 76 e2 74 32 c4 5d fe e4 8f +49 b7 91 7d 65 30 e1 f0 ca 34 60 f3 2e 02 76 17 +44 87 c5 6e 22 a4 5d 25 00 d7 77 54 95 21 9d 7d +16 5a 9c f3 bd 92 c3 2a f9 a9 8d 8d c9 cc 29 68 +00 ad c9 4a 0a 54 fb 40 f3 42 91 bf 84 ee 8e a1 +2b 6f 10 93 59 c6 d3 54 2a 50 f9 c7 67 f5 cf ff +05 a6 81 c2 e6 56 fb 77 ca aa db 4b e9 46 8d 8a +bc d4 df 98 f5 8e 86 d2 05 3f a1 34 9f 74 8e 21 +b1 + +# Prime p: +07 49 26 2c 11 1c d4 70 ec 25 66 e6 b3 73 2f c0 +93 29 46 9a a1 90 71 d3 b9 c0 19 06 51 4c 6f 1d +26 ba a1 4b ea b0 97 1c 8b 7e 61 1a 4f 79 00 9d +6f ea 77 69 28 ca 25 28 5b 0d e3 64 3d 1a 3f 8c +71 + +# Prime q: +06 bc 1e 50 e9 6c 02 bf 63 6e 9e ea 8b 89 9b be +bf 76 51 de 77 dd 47 4c 3e 9b c2 3b ad 81 82 b6 +19 04 c7 d9 7d fb eb fb 1e 00 10 88 78 b6 e6 7e +41 53 91 d6 79 42 c2 b2 bf 9b 44 35 f8 8b 0c b0 +23 + +# p's CRT exponent dP: +03 bc 7e a7 f0 aa b1 43 ab c6 ce 8b 97 11 86 36 +a3 01 72 e4 cf e0 2c 8f a0 dd a3 b7 ba af 90 f8 +09 29 82 98 55 25 f4 88 bd fc b4 bd 72 6e 22 63 +9a c6 4a 30 92 ab 7f fc bf 1d 53 34 cf a5 0b 5b +f1 + +# q's CRT exponent dQ: +02 62 a6 aa 29 c2 a3 c6 7d c5 34 6c 06 38 1a fd +98 7a a3 cc 93 cf bf ec f5 4f dd 9f 9d 78 7d 7f +59 a5 23 d3 98 97 9d a1 37 a2 f6 38 1f e9 48 01 +f7 c9 4d a2 15 18 dc 34 cb 40 87 0c 46 97 99 4a +d9 + +# CRT coefficient qInv: +64 9d 4c 17 b6 ee 17 21 e7 72 d0 38 9a 55 9c 3d +3c df 95 50 d4 57 c4 6b 03 7b 74 64 1b 1d 52 16 +6a f8 a2 13 c8 39 62 06 cd fb a4 42 2f 18 d6 f6 +1d bc b5 d2 14 c9 71 bf 48 2a eb 97 6a 73 70 c2 + +# --------------------------------- +# RSAES-OAEP Encryption Example 7.1 +# --------------------------------- + +# Message to be encrypted: +47 aa e9 09 + +# Seed: +43 dd 09 a0 7f f4 ca c7 1c aa 46 32 ee 5e 1c 1d +ae e4 cd 8f + +# Encryption: +16 88 e4 ce 77 94 bb a6 cb 70 14 16 9e cd 55 9c +ed e2 a3 0b 56 a5 2b 68 d9 fe 18 cf 19 73 ef 97 +b2 a0 31 53 95 1c 75 5f 62 94 aa 49 ad bd b5 58 +45 ab 68 75 fb 39 86 c9 3e cf 92 79 62 84 0d 28 +2f 9e 54 ce 8b 69 0f 7c 0c b8 bb d7 34 40 d9 57 +1d 1b 16 cd 92 60 f9 ea b4 78 3c c4 82 e5 22 3d +c6 09 73 87 17 83 ec 27 b0 ae 0f d4 77 32 cb c2 +86 a1 73 fc 92 b0 0f b4 ba 68 24 64 7c d9 3c 85 +c1 + +# --------------------------------- +# RSAES-OAEP Encryption Example 7.2 +# --------------------------------- + +# Message to be encrypted: +1d 9b 2e 22 23 d9 bc 13 bf b9 f1 62 ce 73 5d b4 +8b a7 c6 8f 68 22 a0 a1 a7 b6 ae 16 58 34 e7 + +# Seed: +3a 9c 3c ec 7b 84 f9 bd 3a de cb c6 73 ec 99 d5 +4b 22 bc 9b + +# Encryption: +10 52 ed 39 7b 2e 01 e1 d0 ee 1c 50 bf 24 36 3f +95 e5 04 f4 a0 34 34 a0 8f d8 22 57 4e d6 b9 73 +6e db b5 f3 90 db 10 32 14 79 a8 a1 39 35 0e 2b +d4 97 7c 37 78 ef 33 1f 3e 78 ae 11 8b 26 84 51 +f2 0a 2f 01 d4 71 f5 d5 3c 56 69 37 17 1b 2d bc +2d 4b de 45 9a 57 99 f0 37 2d 65 74 23 9b 23 23 +d2 45 d0 bb 81 c2 86 b6 3c 89 a3 61 01 73 37 e4 +90 2f 88 a4 67 f4 c7 f2 44 bf d5 ab 46 43 7f f3 +b6 + +# --------------------------------- +# RSAES-OAEP Encryption Example 7.3 +# --------------------------------- + +# Message to be encrypted: +d9 76 fc + +# Seed: +76 a7 5e 5b 61 57 a5 56 cf 88 84 bb 2e 45 c2 93 +dd 54 5c f5 + +# Encryption: +21 55 cd 84 3f f2 4a 4e e8 ba db 76 94 26 00 28 +a4 90 81 3b a8 b3 69 a4 cb f1 06 ec 14 8e 52 98 +70 7f 59 65 be 7d 10 1c 10 49 ea 85 84 c2 4c d6 +34 55 ad 9c 10 4d 68 62 82 d3 fb 80 3a 4c 11 c1 +c2 e9 b9 1c 71 78 80 1d 1b 66 40 f0 03 f5 72 8d +f0 07 b8 a4 cc c9 2b ce 05 e4 1a 27 27 8d 7c 85 +01 8c 52 41 43 13 a5 07 77 89 00 1d 4f 01 91 0b +72 aa d0 5d 22 0a a1 4a 58 73 3a 74 89 bc 54 55 +6b + +# --------------------------------- +# RSAES-OAEP Encryption Example 7.4 +# --------------------------------- + +# Message to be encrypted: +d4 73 86 23 df 22 3a a4 38 43 df 84 67 53 4c 41 +d0 13 e0 c8 03 c6 24 e2 63 66 6b 23 9b de 40 a5 +f2 9a eb 8d e7 9e 3d aa 61 dd 03 70 f4 9b d4 b0 +13 83 4b 98 21 2a ef 6b 1c 5e e3 73 b3 cb + +# Seed: +78 66 31 4a 6a d6 f2 b2 50 a3 59 41 db 28 f5 86 +4b 58 58 59 + +# Encryption: +0a b1 4c 37 3a eb 7d 43 28 d0 aa ad 8c 09 4d 88 +b9 eb 09 8b 95 f2 10 54 a2 90 82 52 2b e7 c2 7a +31 28 78 b6 37 91 7e 3d 81 9e 6c 3c 56 8d b5 d8 +43 80 2b 06 d5 1d 9e 98 a2 be 0b f4 0c 03 14 23 +b0 0e df bf f8 32 0e fb 91 71 bd 20 44 65 3a 4c +b9 c5 12 2f 6c 65 e8 3c da 2e c3 c1 26 02 7a 9c +1a 56 ba 87 4d 0f ea 23 f3 80 b8 2c f2 40 b8 cf +54 00 04 75 8c 4c 77 d9 34 15 7a 74 f3 fc 12 bf +ac + +# --------------------------------- +# RSAES-OAEP Encryption Example 7.5 +# --------------------------------- + +# Message to be encrypted: +bb 47 23 1c a5 ea 1d 3a d4 6c 99 34 5d 9a 8a 61 + +# Seed: +b2 16 6e d4 72 d5 8d b1 0c ab 2c 6b 00 0c cc f1 +0a 7d c5 09 + +# Encryption: +02 83 87 a3 18 27 74 34 79 8b 4d 97 f4 60 06 8d +f5 29 8f ab a5 04 1b a1 17 61 a1 cb 73 16 b2 41 +84 11 4e c5 00 25 7e 25 89 ed 3b 60 7a 1e bb e9 +7a 6c c2 e0 2b f1 b6 81 f4 23 12 a3 3b 7a 77 d8 +e7 85 5c 4a 6d e0 3e 3c 04 64 3f 78 6b 91 a2 64 +a0 d6 80 5e 2c ea 91 e6 81 77 eb 7a 64 d9 25 5e +4f 27 e7 13 b7 cc ec 00 dc 20 0e bd 21 c2 ea 2b +b8 90 fe ae 49 42 df 94 1d c3 f9 78 90 ed 34 74 +78 + +# --------------------------------- +# RSAES-OAEP Encryption Example 7.6 +# --------------------------------- + +# Message to be encrypted: +21 84 82 70 95 d3 5c 3f 86 f6 00 e8 e5 97 54 01 +32 96 + +# Seed: +52 67 3b de 2c a1 66 c2 aa 46 13 1a c1 dc 80 8d +67 d7 d3 b1 + +# Encryption: +14 c6 78 a9 4a d6 05 25 ef 39 e9 59 b2 f3 ba 5c +09 7a 94 ff 91 2b 67 db ac e8 05 35 c1 87 ab d4 +7d 07 54 20 b1 87 21 52 bb a0 8f 7f c3 1f 31 3b +bf 92 73 c9 12 fc 4c 01 49 a9 b0 cf b7 98 07 e3 +46 eb 33 20 69 61 1b ec 0f f9 bc d1 68 f1 f7 c3 +3e 77 31 3c ea 45 4b 94 e2 54 9e ec f0 02 e2 ac +f7 f6 f2 d2 84 5d 4f e0 aa b2 e5 a9 2d df 68 c4 +80 ae 11 24 79 35 d1 f6 25 74 84 22 16 ae 67 41 +15 + +# ============================================= + +# ================================== +# Example 8: A 1031-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +5b df 0e 30 d3 21 dd a5 14 7f 88 24 08 fa 69 19 +54 80 df 8f 80 d3 f6 e8 bf 58 18 50 4f 36 42 7c +a9 b1 f5 54 0b 9c 65 a8 f6 97 4c f8 44 7a 24 4d +92 80 20 1b b4 9f cb be 63 78 d1 94 4c d2 27 e2 +30 f9 6e 3d 10 f8 19 dc ef 27 6c 64 a0 0b 2a 4b +67 01 e7 d0 1d e5 fa bd e3 b1 e9 a0 df 82 f4 63 +13 59 cd 22 66 96 47 fb b1 71 72 46 13 4e d7 b4 +97 cf ff bd c4 2b 59 c7 3a 96 ed 90 16 62 12 df +f7 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +0f 7d 1e 9e 5a aa 25 fd 13 e4 a0 66 3a e1 44 e0 +d1 5f 5c d1 8b cd b0 9d f2 cc 7e 64 e3 c5 e9 15 +ad 62 64 53 04 16 1d 09 8c 71 5b b7 ab 8b d0 1d +07 ea f3 fe d7 c7 ed 08 af 2a 8a 62 ef 44 ab 16 +b3 20 e1 4a f7 2a 48 f9 6a fe 26 2a 0a e4 cf 65 +e6 35 e9 10 79 0c d4 ee 5c ea 76 8a 4b 26 39 f7 +e6 f6 77 b3 f0 bb 6b e3 2b 75 74 7d 89 09 03 6f +02 64 f5 8d 40 1c db a1 31 71 61 57 a7 5e cf 63 +31 + +# Prime p: +0a 02 ef 84 48 d9 fa d8 bb d0 d0 04 c8 c2 aa 97 +51 ef 97 21 c1 b0 d0 32 36 a5 4b 0d f9 47 cb ae +d5 a2 55 ee 9e 8e 20 d4 91 ea 17 23 fe 09 47 04 +a9 76 2e 88 af d1 6e bb 59 94 41 2c a9 66 dc 4f +9f + +# Prime q: +09 2d 36 2e 7e d3 a0 bf d9 e9 fd 0e 6c 03 01 b6 +df 29 15 9c f5 0c c8 3b 9b 0c f4 d6 ee a7 1a 61 +e0 02 b4 6e 0a e9 f2 de 62 d2 5b 5d 74 52 d4 98 +b8 1c 9a c6 fc 58 59 3d 4c 3f b4 f5 d7 2d fb b0 +a9 + +# p's CRT exponent dP: +07 c7 14 10 af 10 39 62 db 36 74 04 e3 7a e8 50 +ba a4 e9 c2 9d d9 21 45 81 52 94 a6 7c 7d 1c 6d +ed 26 3a a0 30 a9 b6 33 ae 50 30 3e 14 03 5d 1a +f0 14 12 3e ba 68 78 20 30 8d 8e bc 85 b6 95 7d +7d + +# q's CRT exponent dQ: +ae 2c 75 38 0c 02 c0 16 ad 05 89 1b 33 01 de 88 +1f 28 ae 11 71 18 2b 6b 2c 83 be a7 c5 15 ec a9 +ca 29 8c 7b 1c ab 58 17 a5 97 06 8f c8 50 60 de +4d a8 a0 16 37 8a ae 43 c7 f9 67 bc c3 79 04 b9 + +# CRT coefficient qInv: +05 98 d1 05 9e 3a da 4f 63 20 75 2c 09 d8 05 ff +7d 1f 1a e0 d0 17 ae ee e9 ce fa 0d 7d d7 ff 77 +5e 44 b5 78 32 2f 64 05 d6 21 1d a1 95 19 66 6a +a8 7f dc 4c d8 c8 8f 6b 6e 3d 67 e9 61 dc bb a3 +d0 + +# --------------------------------- +# RSAES-OAEP Encryption Example 8.1 +# --------------------------------- + +# Message to be encrypted: +05 0b 75 5e 5e 68 80 f7 b9 e9 d6 92 a7 4c 37 aa +e4 49 b3 1b fe a6 de ff 83 74 7a 89 7f 6c 2c 82 +5b b1 ad bf 85 0a 3c 96 99 4b 5d e5 b3 3c bc 7d +4a 17 91 3a 79 67 + +# Seed: +77 06 ff ca 1e cf b1 eb ee 2a 55 e5 c6 e2 4c d2 +79 7a 41 25 + +# Encryption: +09 b3 68 3d 8a 2e b0 fb 29 5b 62 ed 1f b9 29 0b +71 44 57 b7 82 53 19 f4 64 78 72 af 88 9b 30 40 +94 72 02 0a d1 29 12 bf 19 b1 1d 48 19 f4 96 14 +82 4f fd 84 d0 9c 0a 17 e7 d1 73 09 d1 29 19 79 +04 10 aa 29 95 69 9f 6a 86 db e3 24 2b 5a cc 23 +af 45 69 10 80 d6 b1 ae 81 0f b3 e3 05 70 87 f0 +97 00 92 ce 00 be 95 62 ff 40 53 b6 26 2c e0 ca +a9 3e 13 72 3d 2e 3a 5b a0 75 d4 5f 0d 61 b5 4b +61 + +# --------------------------------- +# RSAES-OAEP Encryption Example 8.2 +# --------------------------------- + +# Message to be encrypted: +4e b6 8d cd 93 ca 9b 19 df 11 1b d4 36 08 f5 57 +02 6f e4 aa 1d 5c fa c2 27 a3 eb 5a b9 54 8c 18 +a0 6d de d2 3f 81 82 59 86 b2 fc d7 11 09 ec ef +7e ff 88 87 3f 07 5c 2a a0 c4 69 f6 9c 92 bc + +# Seed: +a3 71 7d a1 43 b4 dc ff bc 74 26 65 a8 fa 95 05 +85 54 83 43 + +# Encryption: +2e cf 15 c9 7c 5a 15 b1 47 6a e9 86 b3 71 b5 7a +24 28 4f 4a 16 2a 8d 0c 81 82 e7 90 5e 79 22 56 +f1 81 2b a5 f8 3f 1f 7a 13 0e 42 dc c0 22 32 84 +4e dc 14 a3 1a 68 ee 97 ae 56 4a 38 3a 34 11 65 +64 24 c5 f6 2d db 64 60 93 c3 67 be 1f cd a4 26 +cf 00 a0 6d 8a cb 7e 57 77 6f bb d8 55 ac 3d f5 +06 fc 16 b1 d7 c3 f2 11 0f 3d 80 68 e9 1e 18 63 +63 83 1c 84 09 68 0d 8d a9 ec d8 cf 1f a2 0e e3 +9d + +# --------------------------------- +# RSAES-OAEP Encryption Example 8.3 +# --------------------------------- + +# Message to be encrypted: +86 04 ac 56 32 8c 1a b5 ad 91 78 61 + +# Seed: +ee 06 20 90 73 cc a0 26 bb 26 4e 51 85 bf 8c 68 +b7 73 9f 86 + +# Encryption: +4b c8 91 30 a5 b2 da bb 7c 2f cf 90 eb 5d 0e af +9e 68 1b 71 46 a3 8f 31 73 a3 d9 cf ec 52 ea 9e +0a 41 93 2e 64 8a 9d 69 34 4c 50 da 76 3f 51 a0 +3c 95 76 21 31 e8 05 22 54 dc d2 24 8c ba 40 fd +31 66 77 86 ce 05 a2 b7 b5 31 ac 9d ac 9e d5 84 +a5 9b 67 7c 1a 8a ed 8c 5d 15 d6 8c 05 56 9e 2b +e7 80 bf 7d b6 38 fd 2b fd 2a 85 ab 27 68 60 f3 +77 73 38 fc a9 89 ff d7 43 d1 3e e0 8e 0c a9 89 +3f + +# --------------------------------- +# RSAES-OAEP Encryption Example 8.4 +# --------------------------------- + +# Message to be encrypted: +fd da 5f bf 6e c3 61 a9 d9 a4 ac 68 af 21 6a 06 +86 f4 38 b1 e0 e5 c3 6b 95 5f 74 e1 07 f3 9c 0d +dd cc + +# Seed: +99 0a d5 73 dc 48 a9 73 23 5b 6d 82 54 36 18 f2 +e9 55 10 5d + +# Encryption: +2e 45 68 47 d8 fc 36 ff 01 47 d6 99 35 94 b9 39 +72 27 d5 77 75 2c 79 d0 f9 04 fc b0 39 d4 d8 12 +fe a6 05 a7 b5 74 dd 82 ca 78 6f 93 75 23 48 43 +8e e9 f5 b5 45 49 85 d5 f0 e1 69 9e 3e 7a d1 75 +a3 2e 15 f0 3d eb 04 2a b9 fe 1d d9 db 1b b8 6f +8c 08 9c cb 45 e7 ef 0c 5e e7 ca 9b 72 90 ca 6b +15 be d4 70 39 78 8a 8a 93 ff 83 e0 e8 d6 24 4c +71 00 63 62 de ef 69 b6 f4 16 fb 3c 68 43 83 fb +d0 + +# --------------------------------- +# RSAES-OAEP Encryption Example 8.5 +# --------------------------------- + +# Message to be encrypted: +4a 5f 49 14 be e2 5d e3 c6 93 41 de 07 + +# Seed: +ec c6 3b 28 f0 75 6f 22 f5 2a c8 e6 ec 12 51 a6 +ec 30 47 18 + +# Encryption: +1f b9 35 6f d5 c4 b1 79 6d b2 eb f7 d0 d3 93 cc +81 0a df 61 45 de fc 2f ce 71 4f 79 d9 38 00 d5 +e2 ac 21 1e a8 bb ec ca 4b 65 4b 94 c3 b1 8b 30 +dd 57 6c e3 4d c9 54 36 ef 57 a0 94 15 64 59 23 +35 9a 5d 7b 41 71 ef 22 c2 46 70 f1 b2 29 d3 60 +3e 91 f7 66 71 b7 df 97 e7 31 7c 97 73 44 76 d5 +f3 d1 7d 21 cf 82 b5 ba 9f 83 df 2e 58 8d 36 98 +4f d1 b5 84 46 8b d2 3b 2e 87 5f 32 f6 89 53 f7 +b2 + +# --------------------------------- +# RSAES-OAEP Encryption Example 8.6 +# --------------------------------- + +# Message to be encrypted: +8e 07 d6 6f 7b 88 0a 72 56 3a bc d3 f3 50 92 bc +33 40 9f b7 f8 8f 24 72 be + +# Seed: +39 25 c7 1b 36 2d 40 a0 a6 de 42 14 55 79 ba 1e +7d d4 59 fc + +# Encryption: +3a fd 9c 66 00 14 7b 21 79 8d 81 8c 65 5a 0f 4c +92 12 db 26 d0 b0 df dc 2a 75 94 cc b3 d2 2f 5b +f1 d7 c3 e1 12 cd 73 fc 7d 50 9c 7a 8b af dd 3c +27 4d 13 99 00 9f 96 09 ec 4b e6 47 7e 45 3f 07 +5a a3 3d b3 82 87 0c 1c 34 09 ae f3 92 d7 38 6a +e3 a6 96 b9 9a 94 b4 da 05 89 44 7e 95 5d 16 c9 +8b 17 60 2a 59 bd 73 62 79 fc d8 fb 28 0c 44 62 +d5 90 bf a9 bf 13 fe d5 70 ea fd e9 73 30 a2 c2 +10 + +# ============================================= + +# ================================== +# Example 9: A 1536-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +cf 2c d4 1e 34 ca 3a 72 8e a5 cb 8a ff 64 c3 6d +27 bd ef 53 64 e3 36 fd 68 d3 12 3c 5a 19 6a 8c +28 70 13 e8 53 d5 15 6d 58 d1 51 95 45 20 fb 4f +6d 7b 17 ab b6 81 77 65 90 9c 57 61 19 65 9d 90 +2b 19 06 ed 8a 2b 10 c1 55 c2 4d 12 45 28 da b9 +ee ae 37 9b ea c6 6e 4a 41 17 86 dc b8 fd 00 62 +eb c0 30 de 12 19 a0 4c 2a 8c 1b 7d d3 13 1e 4d +6b 6c ae e2 e3 1a 5e d4 1a c1 50 9b 2e f1 ee 2a +b1 83 64 be 56 8c a9 41 c2 5e cc 84 ff 9d 64 3b +5e c1 aa ae 10 2a 20 d7 3f 47 9b 78 0f d6 da 91 +07 52 12 d9 ea c0 3a 06 74 d8 99 eb a2 e4 31 f4 +c4 4b 61 5b 6b a2 23 2b d4 b3 3b ae d7 3d 62 5d + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +19 8c 14 1e 23 71 5a 92 bc cf 6a 11 9a 5b c1 13 +89 46 8d 28 11 f5 48 d7 27 e1 7b 4a b0 eb 98 6d +6f 21 1e fb 53 b7 1f 7c cb ea 87 ee 69 c7 5e e6 +15 00 8c 53 32 de b5 2b f3 90 ab df bf e3 7d 72 +05 36 81 59 b2 63 8c 1d e3 26 e2 1d 22 25 1f 0f +b5 84 8b 3b f1 50 05 d2 a7 43 30 f0 af e9 16 ee +62 cc c1 34 4d 1d 83 a7 09 e6 06 76 27 38 40 f7 +f3 77 42 4a 5e 0a 4d a7 5f 01 b3 1f f7 68 19 cf +9c bf dd 21 52 43 c3 91 7c 03 ef 38 19 93 12 e5 +67 b3 bf 7a ed 3a b4 57 f3 71 ef 8a 14 23 f4 5b +68 c6 e2 82 ec 11 1b ba 28 33 b9 87 fd 69 fa d8 +3b c1 b8 c6 13 c5 e1 ea 16 c1 1e d1 25 ea 7e c1 + +# Prime p: +fc 8d 6c 04 be c4 eb 9a 81 92 ca 79 00 cb e5 36 +e2 e8 b5 19 de cf 33 b2 45 97 98 c6 90 9d f4 f1 +76 db 7d 23 19 0f c7 2b 88 65 a7 18 af 89 5f 1b +cd 91 45 29 80 27 42 3b 60 5e 70 a4 7c f5 83 90 +a8 c3 e8 8f c8 c4 8e 8b 32 e3 da 21 0d fb e3 e8 +81 ea 56 74 b6 a3 48 c2 1e 93 f9 e5 5e a6 5e fd + +# Prime q: +d2 00 d4 5e 78 8a ac ea 60 6a 40 1d 04 60 f8 7d +d5 c1 02 7e 12 dc 1a 0d 75 86 e8 93 9d 9c f7 89 +b4 0f 51 ac 04 42 96 1d e7 d2 1c c2 1e 05 c8 31 +55 c1 f2 aa 91 93 38 7c fd f9 56 cb 48 d1 53 ba +27 04 06 f9 bb ba 53 7d 49 87 d9 e2 f9 94 2d 7a +14 cb ff fe a7 4f ec dd a9 28 d2 3e 25 9f 5e e1 + +# p's CRT exponent dP: +db 16 80 2f 79 a2 f0 d4 5f 35 8d 69 fd 33 e4 4b +81 fa e8 28 62 2e 93 a5 42 53 e9 97 d0 1b 07 43 +75 9d a0 e8 12 b4 aa 4e 6c 8b ea b2 32 8d 54 31 +95 5a 41 8a 67 ff 26 a8 c5 c8 07 a5 da 35 4e 05 +ef 31 cc 8c f7 58 f4 63 73 29 50 b0 3e 26 57 26 +fb 94 e3 9d 6a 57 2a 26 24 4a b0 8d b7 57 52 ad + +# q's CRT exponent dQ: +a0 a3 17 cf e7 df 14 23 f8 7a 6d ee 84 51 f4 e2 +b4 a6 7e 54 97 f2 9b 4f 1e 4e 83 0b 9f ad d9 40 +11 67 02 6f 55 96 e5 a3 9c 97 81 7e 0f 5f 16 e2 +7e 19 ec 99 02 e0 1d 7e a6 fb 9a a3 c7 60 af ee +1e 38 1b 69 de 6a c9 c0 75 85 a0 6a d9 c4 ba 00 +bf 75 c8 ad 2f a8 98 a4 79 e8 0a e2 94 fe d2 a1 + +# CRT coefficient qInv: +0b 21 f3 35 c3 53 34 2e b4 4c 3a a2 44 45 78 0c +2d 65 5b 94 01 74 ca e3 8c 7c 8a 4e 64 93 c0 ba +9f d3 03 74 82 67 b0 83 b9 a7 a6 cb 61 e4 2d b3 +62 b8 c9 89 6d b7 06 4e 02 ad 5a e6 15 87 da 15 +b4 64 9c 90 59 49 09 fe b3 7d bc b6 54 be b7 26 +8e c8 01 e5 a8 b4 aa 39 11 be bd 88 54 2f 05 be + +# --------------------------------- +# RSAES-OAEP Encryption Example 9.1 +# --------------------------------- + +# Message to be encrypted: +f7 35 fd 55 ba 92 59 2c 3b 52 b8 f9 c4 f6 9a aa +1c be f8 fe 88 ad d0 95 59 54 12 46 7f 9c f4 ec +0b 89 6c 59 ed a1 62 10 e7 54 9c 8a bb 10 cd bc +21 a1 2e c9 b6 b5 b8 fd 2f 10 39 9e b6 + +# Seed: +8e c9 65 f1 34 a3 ec 99 31 e9 2a 1c a0 dc 81 69 +d5 ea 70 5c + +# Encryption: +26 7b cd 11 8a ca b1 fc 8b a8 1c 85 d7 30 03 cb +86 10 fa 55 c1 d9 7d a8 d4 8a 7c 7f 06 89 6a 4d +b7 51 aa 28 42 55 b9 d3 6a d6 5f 37 65 3d 82 9f +1b 37 f9 7b 80 01 94 25 45 b2 fc 2c 55 a7 37 6c +a7 a1 be 4b 17 60 c8 e0 5a 33 e5 aa 25 26 b8 d9 +8e 31 70 88 e7 83 4c 75 5b 2a 59 b1 26 31 a1 82 +c0 5d 5d 43 ab 17 79 26 4f 84 56 f5 15 ce 57 df +df 51 2d 54 93 da b7 b7 33 8d c4 b7 d7 8d b9 c0 +91 ac 3b af 53 7a 69 fc 7f 54 9d 97 9f 0e ff 9a +94 fd a4 16 9b d4 d1 d1 9a 69 c9 9e 33 c3 b5 54 +90 d5 01 b3 9b 1e da e1 18 ff 67 93 a1 53 26 15 +84 d3 a5 f3 9f 6e 68 2e 3d 17 c8 cd 12 61 fa 72 + +# --------------------------------- +# RSAES-OAEP Encryption Example 9.2 +# --------------------------------- + +# Message to be encrypted: +81 b9 06 60 50 15 a6 3a ab e4 2d df 11 e1 97 89 +12 f5 40 4c 74 74 b2 6d ce 3e d4 82 bf 96 1e cc +81 8b f4 20 c5 46 59 + +# Seed: +ec b1 b8 b2 5f a5 0c da b0 8e 56 04 28 67 f4 af +58 26 d1 6c + +# Encryption: +93 ac 9f 06 71 ec 29 ac bb 44 4e ff c1 a5 74 13 +51 d6 0f db 0e 39 3f bf 75 4a cf 0d e4 97 61 a1 +48 41 df 77 72 e9 bc 82 77 39 66 a1 58 4c 4d 72 +ba ea 00 11 8f 83 f3 5c ca 6e 53 7c bd 4d 81 1f +55 83 b2 97 83 d8 a6 d9 4c d3 1b e7 0d 6f 52 6c +10 ff 09 c6 fa 7c e0 69 79 5a 3f cd 05 11 fd 5f +cb 56 4b cc 80 ea 9c 78 f3 8b 80 01 25 39 d8 a4 +dd f6 fe 81 e9 cd db 7f 50 db bb bc c7 e5 d8 60 +97 cc f4 ec 49 18 9f b8 bf 31 8b e6 d5 a0 71 5d +51 6b 49 af 19 12 58 cd 32 dc 83 3c e6 eb 46 73 +c0 3a 19 bb ac e8 8c c5 48 95 f6 36 cc 0c 1e c8 +90 96 d1 1c e2 35 a2 65 ca 17 64 23 2a 68 9a e8 + +# --------------------------------- +# RSAES-OAEP Encryption Example 9.3 +# --------------------------------- + +# Message to be encrypted: +fd 32 64 29 df 9b 89 0e 09 b5 4b 18 b8 f3 4f 1e +24 + +# Seed: +e8 9b b0 32 c6 ce 62 2c bd b5 3b c9 46 60 14 ea +77 f7 77 c0 + +# Encryption: +81 eb dd 95 05 4b 0c 82 2e f9 ad 76 93 f5 a8 7a +df b4 b4 c4 ce 70 df 2d f8 4e d4 9c 04 da 58 ba +5f c2 0a 19 e1 a6 e8 b7 a3 90 0b 22 79 6d c4 e8 +69 ee 6b 42 79 2d 15 a8 ec eb 56 c0 9c 69 91 4e +81 3c ea 8f 69 31 e4 b8 ed 6f 42 1a f2 98 d5 95 +c9 7f 47 89 c7 ca a6 12 c7 ef 36 09 84 c2 1b 93 +ed c5 40 10 68 b5 af 4c 78 a8 77 1b 98 4d 53 b8 +ea 8a df 2f 6a 7d 4a 0b a7 6c 75 e1 dd 9f 65 8f +20 de d4 a4 60 71 d4 6d 77 91 b5 68 03 d8 fe a7 +f0 b0 f8 e4 1a e3 f0 93 83 a6 f9 58 5f e7 75 3e +aa ff d2 bf 94 56 31 08 be ec c2 07 bb b5 35 f5 +fc c7 05 f0 dd e9 f7 08 c6 2f 49 a9 c9 03 71 d3 + +# --------------------------------- +# RSAES-OAEP Encryption Example 9.4 +# --------------------------------- + +# Message to be encrypted: +f1 45 9b 5f 0c 92 f0 1a 0f 72 3a 2e 56 62 48 4d +8f 8c 0a 20 fc 29 da d6 ac d4 3b b5 f3 ef fd f4 +e1 b6 3e 07 fd fe 66 28 d0 d7 4c a1 9b f2 d6 9e +4a 0a bf 86 d2 93 92 5a 79 67 72 f8 08 8e + +# Seed: +60 6f 3b 99 c0 b9 cc d7 71 ea a2 9e a0 e4 c8 84 +f3 18 9c cc + +# Encryption: +bc c3 5f 94 cd e6 6c b1 13 66 25 d6 25 b9 44 32 +a3 5b 22 f3 d2 fa 11 a6 13 ff 0f ca 5b d5 7f 87 +b9 02 cc dc 1c d0 ae bc b0 71 5e e8 69 d1 d1 fe +39 5f 67 93 00 3f 5e ca 46 50 59 c8 86 60 d4 46 +ff 5f 08 18 55 20 22 55 7e 38 c0 8a 67 ea d9 91 +26 22 54 f1 06 82 97 5e c5 63 97 76 85 37 f4 97 +7a f6 d5 f6 aa ce b7 fb 25 de c5 93 72 30 23 1f +d8 97 8a f4 91 19 a2 9f 29 e4 24 ab 82 72 b4 75 +62 79 2d 5c 94 f7 74 b8 82 9d 0b 0d 9f 1a 8c 9e +dd f3 75 74 d5 fa 24 8e ef a9 c5 27 1f c5 ec 25 +79 c8 1b dd 61 b4 10 fa 61 fe 36 e4 24 22 1c 11 +3a dd b2 75 66 4c 80 1d 34 ca 8c 63 51 e4 a8 58 + +# --------------------------------- +# RSAES-OAEP Encryption Example 9.5 +# --------------------------------- + +# Message to be encrypted: +53 e6 e8 c7 29 d6 f9 c3 19 dd 31 7e 74 b0 db 8e +4c cc a2 5f 3c 83 05 74 6e 13 7a c6 3a 63 ef 37 +39 e7 b5 95 ab b9 6e 8d 55 e5 4f 7b d4 1a b4 33 +37 8f fb 91 1d + +# Seed: +fc bc 42 14 02 e9 ec ab c6 08 2a fa 40 ba 5f 26 +52 2c 84 0e + +# Encryption: +23 2a fb c9 27 fa 08 c2 f6 a2 7b 87 d4 a5 cb 09 +c0 7d c2 6f ae 73 d7 3a 90 55 88 39 f4 fd 66 d2 +81 b8 7e c7 34 bc e2 37 ba 16 66 98 ed 82 91 06 +a7 de 69 42 cd 6c dc e7 8f ed 8d 2e 4d 81 42 8e +66 49 0d 03 62 64 ce f9 2a f9 41 d3 e3 50 55 fe +39 81 e1 4d 29 cb b9 a4 f6 74 73 06 3b ae c7 9a +11 79 f5 a1 7c 9c 18 32 f2 83 8f d7 d5 e5 9b b9 +65 9d 56 dc e8 a0 19 ed ef 1b b3 ac cc 69 7c c6 +cc 7a 77 8f 60 a0 64 c7 f6 f5 d5 29 c6 21 02 62 +e0 03 de 58 3e 81 e3 16 7b 89 97 1f b8 c0 e1 5d +44 ff fe f8 9b 53 d8 d6 4d d7 97 d1 59 b5 6d 2b +08 ea 53 07 ea 12 c2 41 bd 58 d4 ee 27 8a 1f 2e + +# --------------------------------- +# RSAES-OAEP Encryption Example 9.6 +# --------------------------------- + +# Message to be encrypted: +b6 b2 8e a2 19 8d 0c 10 08 bc 64 + +# Seed: +23 aa de 0e 1e 08 bb 9b 9a 78 d2 30 2a 52 f9 c2 +1b 2e 1b a2 + +# Encryption: +43 8c c7 dc 08 a6 8d a2 49 e4 25 05 f8 57 3b a6 +0e 2c 27 73 d5 b2 90 f4 cf 9d ff 71 8e 84 20 81 +c3 83 e6 70 24 a0 f2 95 94 ea 98 7b 9d 25 e4 b7 +38 f2 85 97 0d 19 5a bb 3a 8c 80 54 e3 d7 9d 6b +9c 9a 83 27 ba 59 6f 12 59 e2 71 26 67 47 66 90 +7d 8d 58 2f f3 a8 47 61 54 92 9a db 1e 6d 12 35 +b2 cc b4 ec 8f 66 3b a9 cc 67 0a 92 be bd 85 3c +8d bf 69 c6 43 6d 01 6f 61 ad d8 36 e9 47 32 45 +04 34 20 7f 9f d4 c4 3d ec 2a 12 a9 58 ef a0 1e +fe 26 69 89 9b 5e 60 4c 25 5c 55 fb 71 66 de 55 +89 e3 69 59 7b b0 91 68 c0 6d d5 db 17 7e 06 a1 +74 0e b2 d5 c8 2f ae ca 6d 92 fc ee 99 31 ba 9f + +# ============================================= + +# =================================== +# Example 10: A 2048-bit RSA Key Pair +# =================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d +db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8 +df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4 +02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5 +40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d +4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f +a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1 +2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0 +33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a +53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00 +c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8 +4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef +a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76 +57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88 +d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc +36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85 +25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59 +6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0 +d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d +19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80 +4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be +be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19 +34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10 +2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2 +4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64 +fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1 +3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43 +0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87 +6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01 +84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e +97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79 + +# Prime p: +ec f5 ae cd 1e 55 15 ff fa cb d7 5a 28 16 c6 eb +f4 90 18 cd fb 46 38 e1 85 d6 6a 73 96 b6 f8 09 +0f 80 18 c7 fd 95 cc 34 b8 57 dc 17 f0 cc 65 16 +bb 13 46 ab 4d 58 2c ad ad 7b 41 03 35 23 87 b7 +03 38 d0 84 04 7c 9d 95 39 b6 49 62 04 b3 dd 6e +a4 42 49 92 07 be c0 1f 96 42 87 ff 63 36 c3 98 +46 58 33 68 46 f5 6e 46 86 18 81 c1 02 33 d2 17 +6b f1 5a 5e 96 dd c7 80 bc 86 8a a7 7d 3c e7 69 + +# Prime q: +bc 46 c4 64 fc 6a c4 ca 78 3b 0e b0 8a 3c 84 1b +77 2f 7e 9b 2f 28 ba bd 58 8a e8 85 e1 a0 c6 1e +48 58 a0 fb 25 ac 29 99 90 f3 5b e8 51 64 c2 59 +ba 11 75 cd d7 19 27 07 13 51 84 99 2b 6c 29 b7 +46 dd 0d 2c ab e1 42 83 5f 7d 14 8c c1 61 52 4b +4a 09 94 6d 48 b8 28 47 3f 1c e7 6b 6c b6 88 6c +34 5c 03 e0 5f 41 d5 1b 5c 3a 90 a3 f2 40 73 c7 +d7 4a 4f e2 5d 9c f2 1c 75 96 0f 3f c3 86 31 83 + +# p's CRT exponent dP: +c7 35 64 57 1d 00 fb 15 d0 8a 3d e9 95 7a 50 91 +5d 71 26 e9 44 2d ac f4 2b c8 2e 86 2e 56 73 ff +6a 00 8e d4 d2 e3 74 61 7d f8 9f 17 a1 60 b4 3b +7f da 9c b6 b6 b7 42 18 60 98 15 f7 d4 5c a2 63 +c1 59 aa 32 d2 72 d1 27 fa f4 bc 8c a2 d7 73 78 +e8 ae b1 9b 0a d7 da 3c b3 de 0a e7 31 49 80 f6 +2b 6d 4b 0a 87 5d 1d f0 3c 1b ae 39 cc d8 33 ef +6c d7 e2 d9 52 8b f0 84 d1 f9 69 e7 94 e9 f6 c1 + +# q's CRT exponent dQ: +26 58 b3 7f 6d f9 c1 03 0b e1 db 68 11 7f a9 d8 +7e 39 ea 2b 69 3b 7e 6d 3a 2f 70 94 74 13 ee c6 +14 2e 18 fb 8d fc b6 ac 54 5d 7c 86 a0 ad 48 f8 +45 71 70 f0 ef b2 6b c4 81 26 c5 3e fd 1d 16 92 +01 98 dc 2a 11 07 dc 28 2d b6 a8 0c d3 06 23 60 +ba 3f a1 3f 70 e4 31 2f f1 a6 cd 6b 8f c4 cd 9c +5c 3d b1 7c 6d 6a 57 21 2f 73 ae 29 f6 19 32 7b +ad 59 b1 53 85 85 85 ba 4e 28 b6 0a 62 a4 5e 49 + +# CRT coefficient qInv: +6f 38 52 6b 39 25 08 55 34 ef 3e 41 5a 83 6e de +8b 86 15 8a 2c 7c bf ec cb 0b d8 34 30 4f ec 68 +3b a8 d4 f4 79 c4 33 d4 34 16 e6 32 69 62 3c ea +10 07 76 d8 5a ff 40 1d 3f ff 61 0e e6 54 11 ce +3b 13 63 d6 3a 97 09 ee de 42 64 7c ea 56 14 93 +d5 45 70 a8 79 c1 86 82 cd 97 71 0b 96 20 5e c3 +11 17 d7 3b 5f 36 22 3f ad d6 e8 ba 90 dd 7c 0e +e6 1d 44 e1 63 25 1e 20 c7 f6 6e b3 05 11 7c b8 + +# ---------------------------------- +# RSAES-OAEP Encryption Example 10.1 +# ---------------------------------- + +# Message to be encrypted: +8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70 +b0 89 53 b0 6b 4e b2 05 bc 16 94 ee + +# Seed: +47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0 +aa 63 bd 33 + +# Encryption: +53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15 +52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19 +ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee +e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14 +4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a +8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc +c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb +ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87 +74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec +6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1 +fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62 +93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05 +ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55 +ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64 +73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54 +bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc + +# ---------------------------------- +# RSAES-OAEP Encryption Example 10.2 +# ---------------------------------- + +# Message to be encrypted: +e6 ad 18 1f 05 3b 58 a9 04 f2 45 75 10 37 3e 57 + +# Seed: +6d 17 f5 b4 c1 ff ac 35 1d 19 5b f7 b0 9d 09 f0 +9a 40 79 cf + +# Encryption: +a2 b1 a4 30 a9 d6 57 e2 fa 1c 2b b5 ed 43 ff b2 +5c 05 a3 08 fe 90 93 c0 10 31 79 5f 58 74 40 01 +10 82 8a e5 8f b9 b5 81 ce 9d dd d3 e5 49 ae 04 +a0 98 54 59 bd e6 c6 26 59 4e 7b 05 dc 42 78 b2 +a1 46 5c 13 68 40 88 23 c8 5e 96 dc 66 c3 a3 09 +83 c6 39 66 4f c4 56 9a 37 fe 21 e5 a1 95 b5 77 +6e ed 2d f8 d8 d3 61 af 68 6e 75 02 29 bb d6 63 +f1 61 86 8a 50 61 5e 0c 33 7b ec 0c a3 5f ec 0b +b1 9c 36 eb 2e 0b bc c0 58 2f a1 d9 3a ac db 06 +10 63 f5 9f 2c e1 ee 43 60 5e 5d 89 ec a1 83 d2 +ac df e9 f8 10 11 02 2a d3 b4 3a 3d d4 17 da c9 +4b 4e 11 ea 81 b1 92 96 6e 96 6b 18 20 82 e7 19 +64 60 7b 4f 80 02 f3 62 99 84 4a 11 f2 ae 0f ae +ac 2e ae 70 f8 f4 f9 80 88 ac dc d0 ac 55 6e 9f +cc c5 11 52 19 08 fa d2 6f 04 c6 42 01 45 03 05 +77 87 58 b0 53 8b f8 b5 bb 14 4a 82 8e 62 97 95 + +# ---------------------------------- +# RSAES-OAEP Encryption Example 10.3 +# ---------------------------------- + +# Message to be encrypted: +51 0a 2c f6 0e 86 6f a2 34 05 53 c9 4e a3 9f bc +25 63 11 e8 3e 94 45 4b 41 24 + +# Seed: +38 53 87 51 4d ec cc 7c 74 0d d8 cd f9 da ee 49 +a1 cb fd 54 + +# Encryption: +98 86 c3 e6 76 4a 8b 9a 84 e8 41 48 eb d8 c3 b1 +aa 80 50 38 1a 78 f6 68 71 4c 16 d9 cf d2 a6 ed +c5 69 79 c5 35 d9 de e3 b4 4b 85 c1 8b e8 92 89 +92 37 17 11 47 22 16 d9 5d da 98 d2 ee 83 47 c9 +b1 4d ff df f8 4a a4 8d 25 ac 06 f7 d7 e6 53 98 +ac 96 7b 1c e9 09 25 f6 7d ce 04 9b 7f 81 2d b0 +74 29 97 a7 4d 44 fe 81 db e0 e7 a3 fe af 2e 5c +40 af 88 8d 55 0d db be 3b c2 06 57 a2 95 43 f8 +fc 29 13 b9 bd 1a 61 b2 ab 22 56 ec 40 9b bd 7d +c0 d1 77 17 ea 25 c4 3f 42 ed 27 df 87 38 bf 4a +fc 67 66 ff 7a ff 08 59 55 5e e2 83 92 0f 4c 8a +63 c4 a7 34 0c ba fd dc 33 9e cd b4 b0 51 50 02 +f9 6c 93 2b 5b 79 16 7a f6 99 c0 ad 3f cc fd f0 +f4 4e 85 a7 02 62 bf 2e 18 fe 34 b8 50 58 99 75 +e8 67 ff 96 9d 48 ea bf 21 22 71 54 6c dc 05 a6 +9e cb 52 6e 52 87 0c 83 6f 30 7b d7 98 78 0e de + +# ---------------------------------- +# RSAES-OAEP Encryption Example 10.4 +# ---------------------------------- + +# Message to be encrypted: +bc dd 19 0d a3 b7 d3 00 df 9a 06 e2 2c aa e2 a7 +5f 10 c9 1f f6 67 b7 c1 6b de 8b 53 06 4a 26 49 +a9 40 45 c9 + +# Seed: +5c ac a6 a0 f7 64 16 1a 96 84 f8 5d 92 b6 e0 ef +37 ca 8b 65 + +# Encryption: +63 18 e9 fb 5c 0d 05 e5 30 7e 16 83 43 6e 90 32 +93 ac 46 42 35 8a aa 22 3d 71 63 01 3a ba 87 e2 +df da 8e 60 c6 86 0e 29 a1 e9 26 86 16 3e a0 b9 +17 5f 32 9c a3 b1 31 a1 ed d3 a7 77 59 a8 b9 7b +ad 6a 4f 8f 43 96 f2 8c f6 f3 9c a5 81 12 e4 81 +60 d6 e2 03 da a5 85 6f 3a ca 5f fe d5 77 af 49 +94 08 e3 df d2 33 e3 e6 04 db e3 4a 9c 4c 90 82 +de 65 52 7c ac 63 31 d2 9d c8 0e 05 08 a0 fa 71 +22 e7 f3 29 f6 cc a5 cf a3 4d 4d 1d a4 17 80 54 +57 e0 08 be c5 49 e4 78 ff 9e 12 a7 63 c4 77 d1 +5b bb 78 f5 b6 9b d5 78 30 fc 2c 4e d6 86 d7 9b +c7 2a 95 d8 5f 88 13 4c 6b 0a fe 56 a8 cc fb c8 +55 82 8b b3 39 bd 17 90 9c f1 d7 0d e3 33 5a e0 +70 39 09 3e 60 6d 65 53 65 de 65 50 b8 72 cd 6d +e1 d4 40 ee 03 1b 61 94 5f 62 9a d8 a3 53 b0 d4 +09 39 e9 6a 3c 45 0d 2a 8d 5e ee 9f 67 80 93 c8 + +# ---------------------------------- +# RSAES-OAEP Encryption Example 10.5 +# ---------------------------------- + +# Message to be encrypted: +a7 dd 6c 7d c2 4b 46 f9 dd 5f 1e 91 ad a4 c3 b3 +df 94 7e 87 72 32 a9 + +# Seed: +95 bc a9 e3 85 98 94 b3 dd 86 9f a7 ec d5 bb c6 +40 1b f3 e4 + +# Encryption: +75 29 08 72 cc fd 4a 45 05 66 0d 65 1f 56 da 6d +aa 09 ca 13 01 d8 90 63 2f 6a 99 2f 3d 56 5c ee +46 4a fd ed 40 ed 3b 5b e9 35 67 14 ea 5a a7 65 +5f 4a 13 66 c2 f1 7c 72 8f 6f 2c 5a 5d 1f 8e 28 +42 9b c4 e6 f8 f2 cf f8 da 8d c0 e0 a9 80 8e 45 +fd 09 ea 2f a4 0c b2 b6 ce 6f ff f5 c0 e1 59 d1 +1b 68 d9 0a 85 f7 b8 4e 10 3b 09 e6 82 66 64 80 +c6 57 50 5c 09 29 25 94 68 a3 14 78 6d 74 ea b1 +31 57 3c f2 34 bf 57 db 7d 9e 66 cc 67 48 19 2e +00 2d c0 de ea 93 05 85 f0 83 1f dc d9 bc 33 d5 +1f 79 ed 2f fc 16 bc f4 d5 98 12 fc eb ca a3 f9 +06 9b 0e 44 56 86 d6 44 c2 5c cf 63 b4 56 ee 5f +a6 ff e9 6f 19 cd f7 51 fe d9 ea f3 59 57 75 4d +bf 4b fe a5 21 6a a1 84 4d c5 07 cb 2d 08 0e 72 +2e ba 15 03 08 c2 b5 ff 11 93 62 0f 17 66 ec f4 +48 1b af b9 43 bd 29 28 77 f2 13 6c a4 94 ab a0 + +# ---------------------------------- +# RSAES-OAEP Encryption Example 10.6 +# ---------------------------------- + +# Message to be encrypted: +ea f1 a7 3a 1b 0c 46 09 53 7d e6 9c d9 22 8b bc +fb 9a 8c a8 c6 c3 ef af 05 6f e4 a7 f4 63 4e d0 +0b 7c 39 ec 69 22 d7 b8 ea 2c 04 eb ac + +# Seed: +9f 47 dd f4 2e 97 ee a8 56 a9 bd bc 71 4e b3 ac +22 f6 eb 32 + +# Encryption: +2d 20 7a 73 43 2a 8f b4 c0 30 51 b3 f7 3b 28 a6 +17 64 09 8d fa 34 c4 7a 20 99 5f 81 15 aa 68 16 +67 9b 55 7e 82 db ee 58 49 08 c6 e6 97 82 d7 de +b3 4d bd 65 af 06 3d 57 fc a7 6a 5f d0 69 49 2f +d6 06 8d 99 84 d2 09 35 05 65 a6 2e 5c 77 f2 30 +38 c1 2c b1 0c 66 34 70 9b 54 7c 46 f6 b4 a7 09 +bd 85 ca 12 2d 74 46 5e f9 77 62 c2 97 63 e0 6d +bc 7a 9e 73 8c 78 bf ca 01 02 dc 5e 79 d6 5b 97 +3f 28 24 0c aa b2 e1 61 a7 8b 57 d2 62 45 7e d8 +19 5d 53 e3 c7 ae 9d a0 21 88 3c 6d b7 c2 4a fd +d2 32 2e ac 97 2a d3 c3 54 c5 fc ef 1e 14 6c 3a +02 90 fb 67 ad f0 07 06 6e 00 42 8d 2c ec 18 ce +58 f9 32 86 98 de fe f4 b2 eb 5e c7 69 18 fd e1 +c1 98 cb b3 8b 7a fc 67 62 6a 9a ef ec 43 22 bf +d9 0d 25 63 48 1c 9a 22 1f 78 c8 27 2c 82 d1 b6 +2a b9 14 e1 c6 9f 6a f6 ef 30 ca 52 60 db 4a 46 + +# ============================================= diff --git a/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.c b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.c new file mode 100644 index 0000000..ce96cf2 --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.c @@ -0,0 +1,5463 @@ +/* Generated from file: pkcs1v15crypt-vectors.txt + * with md5 hash: 120f611de26e7eb0f0e16da16639539c + */ + + +typedef struct rsaKey { + int n_l; + unsigned char n[256]; + int e_l; + unsigned char e[256]; + int d_l; + unsigned char d[256]; + int p_l; + unsigned char p[256]; + int q_l; + unsigned char q[256]; + int dP_l; + unsigned char dP[256]; + int dQ_l; + unsigned char dQ[256]; + int qInv_l; + unsigned char qInv[256]; +} rsaKey_t; + +typedef struct rsaData { + const char* name; + int o1_l; + unsigned char o1[256]; + int o2_l; + unsigned char o2[256]; + int o3_l; + unsigned char o3[256]; +} rsaData_t; + +typedef struct testcase { + const char* name; + rsaKey_t rsa; +#ifdef LTC_TEST_EXT + rsaData_t data[20]; +#else + rsaData_t data[1]; +#endif /* LTC_TEST_EXT */ +} testcase_t; + +testcase_t testcases_eme[] = + { +{ + "Example 1: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xa8, 0xb3, 0xb2, 0x84, 0xaf, 0x8e, 0xb5, 0x0b, 0x38, 0x70, 0x34, 0xa8, 0x60, 0xf1, 0x46, 0xc4, 0x91, 0x9f, 0x31, 0x87, 0x63, 0xcd, 0x6c, 0x55, 0x98, 0xc8, 0xae, 0x48, 0x11, 0xa1, 0xe0, 0xab, 0xc4, 0xc7, 0xe0, 0xb0, 0x82, 0xd6, 0x93, 0xa5, 0xe7, 0xfc, 0xed, 0x67, 0x5c, 0xf4, 0x66, 0x85, 0x12, 0x77, 0x2c, 0x0c, 0xbc, 0x64, 0xa7, 0x42, 0xc6, 0xc6, 0x30, 0xf5, 0x33, 0xc8, 0xcc, 0x72, 0xf6, 0x2a, 0xe8, 0x33, 0xc4, 0x0b, 0xf2, 0x58, 0x42, 0xe9, 0x84, 0xbb, 0x78, 0xbd, 0xbf, 0x97, 0xc0, 0x10, 0x7d, 0x55, 0xbd, 0xb6, 0x62, 0xf5, 0xc4, 0xe0, 0xfa, 0xb9, 0x84, 0x5c, 0xb5, 0x14, 0x8e, 0xf7, 0x39, 0x2d, 0xd3, 0xaa, 0xff, 0x93, 0xae, 0x1e, 0x6b, 0x66, 0x7b, 0xb3, 0xd4, 0x24, 0x76, 0x16, 0xd4, 0xf5, 0xba, 0x10, 0xd4, 0xcf, 0xd2, 0x26, 0xde, 0x88, 0xd3, 0x9f, 0x16, 0xfb } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x53, 0x33, 0x9c, 0xfd, 0xb7, 0x9f, 0xc8, 0x46, 0x6a, 0x65, 0x5c, 0x73, 0x16, 0xac, 0xa8, 0x5c, 0x55, 0xfd, 0x8f, 0x6d, 0xd8, 0x98, 0xfd, 0xaf, 0x11, 0x95, 0x17, 0xef, 0x4f, 0x52, 0xe8, 0xfd, 0x8e, 0x25, 0x8d, 0xf9, 0x3f, 0xee, 0x18, 0x0f, 0xa0, 0xe4, 0xab, 0x29, 0x69, 0x3c, 0xd8, 0x3b, 0x15, 0x2a, 0x55, 0x3d, 0x4a, 0xc4, 0xd1, 0x81, 0x2b, 0x8b, 0x9f, 0xa5, 0xaf, 0x0e, 0x7f, 0x55, 0xfe, 0x73, 0x04, 0xdf, 0x41, 0x57, 0x09, 0x26, 0xf3, 0x31, 0x1f, 0x15, 0xc4, 0xd6, 0x5a, 0x73, 0x2c, 0x48, 0x31, 0x16, 0xee, 0x3d, 0x3d, 0x2d, 0x0a, 0xf3, 0x54, 0x9a, 0xd9, 0xbf, 0x7c, 0xbf, 0xb7, 0x8a, 0xd8, 0x84, 0xf8, 0x4d, 0x5b, 0xeb, 0x04, 0x72, 0x4d, 0xc7, 0x36, 0x9b, 0x31, 0xde, 0xf3, 0x7d, 0x0c, 0xf5, 0x39, 0xe9, 0xcf, 0xcd, 0xd3, 0xde, 0x65, 0x37, 0x29, 0xea, 0xd5, 0xd1 } +, + /* Prime 1 */ + 64, + { 0xd3, 0x27, 0x37, 0xe7, 0x26, 0x7f, 0xfe, 0x13, 0x41, 0xb2, 0xd5, 0xc0, 0xd1, 0x50, 0xa8, 0x1b, 0x58, 0x6f, 0xb3, 0x13, 0x2b, 0xed, 0x2f, 0x8d, 0x52, 0x62, 0x86, 0x4a, 0x9c, 0xb9, 0xf3, 0x0a, 0xf3, 0x8b, 0xe4, 0x48, 0x59, 0x8d, 0x41, 0x3a, 0x17, 0x2e, 0xfb, 0x80, 0x2c, 0x21, 0xac, 0xf1, 0xc1, 0x1c, 0x52, 0x0c, 0x2f, 0x26, 0xa4, 0x71, 0xdc, 0xad, 0x21, 0x2e, 0xac, 0x7c, 0xa3, 0x9d } +, + /* Prime 2 */ + 64, + { 0xcc, 0x88, 0x53, 0xd1, 0xd5, 0x4d, 0xa6, 0x30, 0xfa, 0xc0, 0x04, 0xf4, 0x71, 0xf2, 0x81, 0xc7, 0xb8, 0x98, 0x2d, 0x82, 0x24, 0xa4, 0x90, 0xed, 0xbe, 0xb3, 0x3d, 0x3e, 0x3d, 0x5c, 0xc9, 0x3c, 0x47, 0x65, 0x70, 0x3d, 0x1d, 0xd7, 0x91, 0x64, 0x2f, 0x1f, 0x11, 0x6a, 0x0d, 0xd8, 0x52, 0xbe, 0x24, 0x19, 0xb2, 0xaf, 0x72, 0xbf, 0xe9, 0xa0, 0x30, 0xe8, 0x60, 0xb0, 0x28, 0x8b, 0x5d, 0x77 } +, + /* Prime exponent 1 */ + 64, + { 0x0e, 0x12, 0xbf, 0x17, 0x18, 0xe9, 0xce, 0xf5, 0x59, 0x9b, 0xa1, 0xc3, 0x88, 0x2f, 0xe8, 0x04, 0x6a, 0x90, 0x87, 0x4e, 0xef, 0xce, 0x8f, 0x2c, 0xcc, 0x20, 0xe4, 0xf2, 0x74, 0x1f, 0xb0, 0xa3, 0x3a, 0x38, 0x48, 0xae, 0xc9, 0xc9, 0x30, 0x5f, 0xbe, 0xcb, 0xd2, 0xd7, 0x68, 0x19, 0x96, 0x7d, 0x46, 0x71, 0xac, 0xc6, 0x43, 0x1e, 0x40, 0x37, 0x96, 0x8d, 0xb3, 0x78, 0x78, 0xe6, 0x95, 0xc1 } +, + /* Prime exponent 2 */ + 64, + { 0x95, 0x29, 0x7b, 0x0f, 0x95, 0xa2, 0xfa, 0x67, 0xd0, 0x07, 0x07, 0xd6, 0x09, 0xdf, 0xd4, 0xfc, 0x05, 0xc8, 0x9d, 0xaf, 0xc2, 0xef, 0x6d, 0x6e, 0xa5, 0x5b, 0xec, 0x77, 0x1e, 0xa3, 0x33, 0x73, 0x4d, 0x92, 0x51, 0xe7, 0x90, 0x82, 0xec, 0xda, 0x86, 0x6e, 0xfe, 0xf1, 0x3c, 0x45, 0x9e, 0x1a, 0x63, 0x13, 0x86, 0xb7, 0xe3, 0x54, 0xc8, 0x99, 0xf5, 0xf1, 0x12, 0xca, 0x85, 0xd7, 0x15, 0x83 } +, + /* Coefficient */ + 64, + { 0x4f, 0x45, 0x6c, 0x50, 0x24, 0x93, 0xbd, 0xc0, 0xed, 0x2a, 0xb7, 0x56, 0xa3, 0xa6, 0xed, 0x4d, 0x67, 0x35, 0x2a, 0x69, 0x7d, 0x42, 0x16, 0xe9, 0x32, 0x12, 0xb1, 0x27, 0xa6, 0x3d, 0x54, 0x11, 0xce, 0x6f, 0xa9, 0x8d, 0x5d, 0xbe, 0xfd, 0x73, 0x26, 0x3e, 0x37, 0x28, 0x14, 0x27, 0x43, 0x81, 0x81, 0x66, 0xed, 0x7d, 0xd6, 0x36, 0x87, 0xdd, 0x2a, 0x8c, 0xa1, 0xd2, 0xf4, 0xfb, 0xd8, 0xe1 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 1.1", + /* Message */ + 28, + { 0x66, 0x28, 0x19, 0x4e, 0x12, 0x07, 0x3d, 0xb0, 0x3b, 0xa9, 0x4c, 0xda, 0x9e, 0xf9, 0x53, 0x23, 0x97, 0xd5, 0x0d, 0xba, 0x79, 0xb9, 0x87, 0x00, 0x4a, 0xfe, 0xfe, 0x34 } +, + /* Seed */ + 97, + { 0x01, 0x73, 0x41, 0xae, 0x38, 0x75, 0xd5, 0xf8, 0x71, 0x01, 0xf8, 0xcc, 0x4f, 0xa9, 0xb9, 0xbc, 0x15, 0x6b, 0xb0, 0x46, 0x28, 0xfc, 0xcd, 0xb2, 0xf4, 0xf1, 0x1e, 0x90, 0x5b, 0xd3, 0xa1, 0x55, 0xd3, 0x76, 0xf5, 0x93, 0xbd, 0x73, 0x04, 0x21, 0x08, 0x74, 0xeb, 0xa0, 0x8a, 0x5e, 0x22, 0xbc, 0xcc, 0xb4, 0xc9, 0xd3, 0x88, 0x2a, 0x93, 0xa5, 0x4d, 0xb0, 0x22, 0xf5, 0x03, 0xd1, 0x63, 0x38, 0xb6, 0xb7, 0xce, 0x16, 0xdc, 0x7f, 0x4b, 0xbf, 0x9a, 0x96, 0xb5, 0x97, 0x72, 0xd6, 0x60, 0x6e, 0x97, 0x47, 0xc7, 0x64, 0x9b, 0xf9, 0xe0, 0x83, 0xdb, 0x98, 0x18, 0x84, 0xa9, 0x54, 0xab, 0x3c, 0x6f } +, + /* Encryption */ + 128, + { 0x50, 0xb4, 0xc1, 0x41, 0x36, 0xbd, 0x19, 0x8c, 0x2f, 0x3c, 0x3e, 0xd2, 0x43, 0xfc, 0xe0, 0x36, 0xe1, 0x68, 0xd5, 0x65, 0x17, 0x98, 0x4a, 0x26, 0x3c, 0xd6, 0x64, 0x92, 0xb8, 0x08, 0x04, 0xf1, 0x69, 0xd2, 0x10, 0xf2, 0xb9, 0xbd, 0xfb, 0x48, 0xb1, 0x2f, 0x9e, 0xa0, 0x50, 0x09, 0xc7, 0x7d, 0xa2, 0x57, 0xcc, 0x60, 0x0c, 0xce, 0xfe, 0x3a, 0x62, 0x83, 0x78, 0x9d, 0x8e, 0xa0, 0xe6, 0x07, 0xac, 0x58, 0xe2, 0x69, 0x0e, 0xc4, 0xeb, 0xc1, 0x01, 0x46, 0xe8, 0xcb, 0xaa, 0x5e, 0xd4, 0xd5, 0xcc, 0xe6, 0xfe, 0x7b, 0x0f, 0xf9, 0xef, 0xc1, 0xea, 0xbb, 0x56, 0x4d, 0xbf, 0x49, 0x82, 0x85, 0xf4, 0x49, 0xee, 0x61, 0xdd, 0x7b, 0x42, 0xee, 0x5b, 0x58, 0x92, 0xcb, 0x90, 0x60, 0x1f, 0x30, 0xcd, 0xa0, 0x7b, 0xf2, 0x64, 0x89, 0x31, 0x0b, 0xcd, 0x23, 0xb5, 0x28, 0xce, 0xab, 0x3c, 0x31 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 1.2", + /* Message */ + 28, + { 0x75, 0x0c, 0x40, 0x47, 0xf5, 0x47, 0xe8, 0xe4, 0x14, 0x11, 0x85, 0x65, 0x23, 0x29, 0x8a, 0xc9, 0xba, 0xe2, 0x45, 0xef, 0xaf, 0x13, 0x97, 0xfb, 0xe5, 0x6f, 0x9d, 0xd5 } +, + /* Seed */ + 97, + { 0xac, 0x47, 0x28, 0xa8, 0x42, 0x8c, 0x1e, 0x52, 0x24, 0x71, 0xa8, 0xdf, 0x73, 0x5a, 0x8e, 0x92, 0x92, 0xaf, 0x0d, 0x55, 0xbc, 0xb7, 0x3a, 0x12, 0xac, 0x32, 0xc2, 0x64, 0xf3, 0x88, 0x1c, 0x7c, 0x8a, 0x71, 0x0f, 0x70, 0xfe, 0xb1, 0x04, 0x85, 0xc8, 0x37, 0x0f, 0x78, 0x1f, 0xff, 0xd0, 0x21, 0x81, 0x6f, 0x05, 0x87, 0x39, 0x76, 0x6d, 0xa0, 0xa9, 0xc9, 0xdb, 0x0e, 0xae, 0x7e, 0x9a, 0x25, 0xb6, 0xc4, 0x33, 0x18, 0xd0, 0xca, 0xac, 0x23, 0x65, 0x22, 0xca, 0x31, 0x0f, 0x17, 0xfc, 0x52, 0xad, 0x42, 0x29, 0xc8, 0x3a, 0x24, 0xe9, 0xe5, 0x45, 0xeb, 0x35, 0xe9, 0x82, 0x6d, 0x55, 0x9f, 0x57 } +, + /* Encryption */ + 128, + { 0x68, 0x42, 0xe5, 0xe2, 0xcc, 0x00, 0x41, 0xd6, 0xb0, 0xc8, 0x1a, 0x56, 0x2c, 0x39, 0xa6, 0x17, 0x37, 0x9a, 0x51, 0x5c, 0xab, 0x74, 0xab, 0xcb, 0x26, 0x19, 0xc7, 0x74, 0x0a, 0x54, 0x1d, 0x95, 0x55, 0xdd, 0x91, 0x65, 0x97, 0x5b, 0xf8, 0xa3, 0xeb, 0xd0, 0xd0, 0x45, 0x66, 0x61, 0xdf, 0xb1, 0xa6, 0x86, 0x1b, 0xa2, 0x33, 0x22, 0x69, 0x93, 0x0e, 0x0d, 0xb5, 0x14, 0xfc, 0xa0, 0x73, 0x3e, 0xeb, 0x9c, 0x40, 0x57, 0x13, 0xeb, 0x1f, 0x9d, 0x76, 0x80, 0x33, 0xed, 0x29, 0x3e, 0x1e, 0x08, 0x1a, 0x12, 0x5f, 0x32, 0xdd, 0xb9, 0xea, 0x52, 0xed, 0xbe, 0x27, 0x5c, 0x4a, 0xf6, 0x0f, 0x8a, 0x7b, 0xf8, 0x32, 0xbd, 0x22, 0x75, 0x61, 0xc2, 0x08, 0xdc, 0x00, 0x31, 0xa8, 0x4b, 0x50, 0x12, 0xc9, 0xdd, 0x9f, 0x74, 0x45, 0x9d, 0xcb, 0x07, 0x0b, 0xdb, 0xe1, 0x3c, 0xfa, 0x8c, 0x2d, 0x50 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.3", + /* Message */ + 55, + { 0xd9, 0x4a, 0xe0, 0x83, 0x2e, 0x64, 0x45, 0xce, 0x42, 0x33, 0x1c, 0xb0, 0x6d, 0x53, 0x1a, 0x82, 0xb1, 0xdb, 0x4b, 0xaa, 0xd3, 0x0f, 0x74, 0x6d, 0xc9, 0x16, 0xdf, 0x24, 0xd4, 0xe3, 0xc2, 0x45, 0x1f, 0xff, 0x59, 0xa6, 0x42, 0x3e, 0xb0, 0xe1, 0xd0, 0x2d, 0x4f, 0xe6, 0x46, 0xcf, 0x69, 0x9d, 0xfd, 0x81, 0x8c, 0x6e, 0x97, 0xb0, 0x51 } +, + /* Seed */ + 70, + { 0xdd, 0x2d, 0x60, 0xa5, 0xe0, 0x08, 0xeb, 0xe1, 0xd0, 0xbe, 0x6f, 0x60, 0xdb, 0xc4, 0x3f, 0x29, 0x62, 0xef, 0x50, 0xbf, 0xde, 0x54, 0x2b, 0xbb, 0xe9, 0x8f, 0xed, 0xd1, 0xfe, 0xac, 0x05, 0x7e, 0x77, 0x1c, 0xf1, 0x5f, 0xc6, 0x32, 0xc8, 0xdb, 0x27, 0x2e, 0x28, 0xd2, 0x9b, 0x57, 0x93, 0xea, 0x6a, 0xb8, 0x06, 0x21, 0x8c, 0x53, 0x82, 0x39, 0xb9, 0x3a, 0x93, 0x5e, 0x65, 0xd2, 0x44, 0x16, 0xec, 0x6c, 0x6e, 0x99, 0xae, 0x04 } +, + /* Encryption */ + 128, + { 0x70, 0x9c, 0x7d, 0x2d, 0x45, 0x98, 0xc9, 0x60, 0x65, 0xb6, 0x58, 0x8d, 0xa2, 0xf8, 0x9f, 0xa8, 0x7f, 0x06, 0x2d, 0x72, 0x41, 0xef, 0x65, 0x95, 0x89, 0x8f, 0x63, 0x7a, 0xda, 0x57, 0xea, 0xe9, 0x01, 0x73, 0xf0, 0xfb, 0x4b, 0xf6, 0xa9, 0x1e, 0xbd, 0x96, 0x50, 0x69, 0x07, 0xc8, 0x53, 0xda, 0xcf, 0x20, 0x84, 0x94, 0xbe, 0x94, 0xd3, 0x13, 0xa0, 0x41, 0x85, 0xd4, 0x74, 0xa9, 0x07, 0x41, 0x2e, 0xff, 0xc3, 0xe0, 0x24, 0xd0, 0x7e, 0x4d, 0x09, 0xaa, 0x24, 0x5f, 0xbc, 0xb1, 0x30, 0x21, 0x9b, 0xfa, 0x5d, 0xe0, 0x2d, 0x4f, 0x7e, 0x2e, 0xc9, 0xe6, 0x2e, 0x8a, 0xd3, 0x2d, 0xee, 0x5f, 0xf4, 0xd8, 0xe4, 0xcf, 0xec, 0xbc, 0x50, 0x33, 0xa1, 0xc2, 0xc6, 0x1c, 0x52, 0x33, 0xae, 0x16, 0x19, 0x2a, 0x48, 0x1d, 0x00, 0x75, 0xbf, 0xc7, 0xce, 0x02, 0x82, 0x12, 0xcd, 0x27, 0xbe, 0xbe } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.4", + /* Message */ + 26, + { 0x52, 0xe6, 0x50, 0xd9, 0x8e, 0x7f, 0x2a, 0x04, 0x8b, 0x4f, 0x86, 0x85, 0x21, 0x53, 0xb9, 0x7e, 0x01, 0xdd, 0x31, 0x6f, 0x34, 0x6a, 0x19, 0xf6, 0x7a, 0x85 } +, + /* Seed */ + 99, + { 0x26, 0x29, 0xa7, 0xaa, 0xc0, 0xc3, 0x90, 0x5e, 0x83, 0x1e, 0xb6, 0x02, 0x38, 0x8c, 0x54, 0x5a, 0xf5, 0x54, 0xb9, 0x6b, 0x2a, 0xe5, 0x15, 0x32, 0xe9, 0xcc, 0xdb, 0x89, 0x72, 0xef, 0x30, 0xb6, 0x4a, 0x2f, 0x98, 0xc6, 0x95, 0x29, 0x7a, 0x01, 0xc5, 0x81, 0x2a, 0x2c, 0x40, 0x15, 0x82, 0xf3, 0x7b, 0x14, 0x4a, 0x3e, 0x90, 0xe5, 0x9d, 0x81, 0xb6, 0x90, 0x39, 0xc6, 0x4b, 0x84, 0x4b, 0x02, 0x8c, 0x10, 0x5c, 0x8e, 0x68, 0x36, 0x15, 0xaf, 0xb6, 0x58, 0xb6, 0xc4, 0xd9, 0xf3, 0x82, 0x38, 0xa7, 0x63, 0x01, 0xbb, 0x14, 0x44, 0x91, 0x13, 0xb6, 0x9d, 0xe1, 0x26, 0x04, 0x5e, 0x26, 0xf1, 0x3e, 0xe6, 0xd7 } +, + /* Encryption */ + 128, + { 0x54, 0xdd, 0xb7, 0x84, 0x26, 0x8e, 0xad, 0xb3, 0x95, 0x5b, 0xd9, 0xf9, 0x49, 0x88, 0x42, 0x59, 0x5a, 0xd2, 0x9f, 0xf8, 0xa6, 0x67, 0xfe, 0xb4, 0x1f, 0x6f, 0x53, 0x0c, 0xb6, 0x0b, 0xc9, 0x26, 0xac, 0x6c, 0x71, 0xc7, 0x72, 0xf8, 0x03, 0xd0, 0x22, 0xb4, 0x1c, 0xa5, 0x72, 0x04, 0x22, 0x3b, 0x27, 0xca, 0x79, 0xec, 0x5b, 0x72, 0x65, 0x2c, 0xa9, 0xaf, 0xbf, 0x40, 0xdc, 0x2f, 0x6a, 0x0e, 0x13, 0xbc, 0xd6, 0x0d, 0x37, 0xf7, 0x95, 0x04, 0xb0, 0xff, 0xcc, 0x01, 0xcf, 0x53, 0x42, 0xd6, 0xd3, 0x4a, 0xc6, 0xf1, 0xf2, 0xf9, 0xf2, 0xf4, 0x87, 0x46, 0x25, 0xb9, 0xfd, 0xbb, 0x7d, 0xda, 0x2e, 0xc8, 0x7d, 0xf0, 0xcf, 0x87, 0x25, 0x97, 0x98, 0xdf, 0x86, 0xa0, 0x6b, 0xd5, 0xae, 0xf7, 0x35, 0x4b, 0x8c, 0xb1, 0xcb, 0x13, 0x75, 0x75, 0xf4, 0xcf, 0xbc, 0x46, 0x28, 0x1b, 0xb3, 0x31 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.5", + /* Message */ + 20, + { 0x8d, 0xa8, 0x9f, 0xd9, 0xe5, 0xf9, 0x74, 0xa2, 0x9f, 0xef, 0xfb, 0x46, 0x2b, 0x49, 0x18, 0x0f, 0x6c, 0xf9, 0xe8, 0x02 } +, + /* Seed */ + 105, + { 0xc3, 0xca, 0x84, 0x60, 0x0f, 0x35, 0xc8, 0x65, 0x5f, 0xc7, 0xc6, 0x4c, 0x75, 0xc5, 0x87, 0x38, 0x53, 0xd3, 0xaa, 0x8a, 0x94, 0x26, 0xa5, 0x1b, 0x63, 0xd7, 0xe7, 0x5d, 0xcf, 0x6c, 0xae, 0x97, 0xa4, 0x25, 0x3f, 0xba, 0x87, 0x1d, 0x6f, 0x96, 0x89, 0x97, 0x19, 0x9b, 0xf0, 0x1b, 0x6a, 0x4d, 0x34, 0x28, 0xce, 0x4c, 0x96, 0xd1, 0xc4, 0x87, 0xb2, 0x83, 0x0c, 0xb9, 0xe3, 0x5d, 0x64, 0x05, 0x56, 0x23, 0x69, 0x9a, 0xb4, 0x97, 0x9a, 0x02, 0x58, 0x4b, 0x92, 0xe6, 0xba, 0x39, 0xe7, 0x57, 0x28, 0x40, 0x79, 0xab, 0xf1, 0x33, 0xa7, 0xda, 0x54, 0xe5, 0x42, 0x52, 0x17, 0xa2, 0x10, 0xf6, 0x7c, 0x18, 0x26, 0x9b, 0x51, 0x1f, 0x61, 0xf8, 0xc5 } +, + /* Encryption */ + 128, + { 0xa8, 0x55, 0x48, 0x01, 0x3b, 0xd0, 0xe2, 0x0e, 0xe0, 0xeb, 0xd3, 0x6f, 0xb7, 0x48, 0x97, 0x7f, 0x98, 0x58, 0x46, 0xd7, 0x61, 0x0e, 0xed, 0x24, 0xc3, 0x6c, 0xd8, 0x30, 0x33, 0xdd, 0x2a, 0xa4, 0x58, 0x0b, 0xd1, 0x53, 0x35, 0x20, 0x9d, 0xcf, 0x78, 0x2e, 0xe2, 0x6c, 0x48, 0xc3, 0x06, 0x44, 0xb0, 0xb5, 0xcc, 0x86, 0xc8, 0xcd, 0x16, 0x5a, 0xe2, 0x1e, 0xad, 0xf5, 0x78, 0x04, 0x18, 0x67, 0x76, 0x07, 0x03, 0x18, 0x75, 0xe2, 0x21, 0xec, 0xdf, 0x3b, 0x10, 0x57, 0x31, 0x6f, 0x3f, 0x12, 0xa4, 0x7d, 0x5d, 0xa4, 0x0c, 0x41, 0x53, 0x9b, 0x63, 0x64, 0x30, 0xda, 0x2e, 0x54, 0x21, 0x90, 0x11, 0x9e, 0x42, 0x9c, 0x53, 0xc2, 0x22, 0x6f, 0x95, 0x9b, 0x19, 0xcc, 0xf4, 0x8a, 0x3d, 0x24, 0x02, 0x17, 0xc4, 0xde, 0x70, 0xd7, 0x07, 0x2a, 0x7e, 0x0d, 0x95, 0xb6, 0x16, 0xd1, 0x15, 0xa8 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.6", + /* Message */ + 7, + { 0x26, 0x52, 0x10, 0x50, 0x84, 0x42, 0x71 } +, + /* Seed */ + 118, + { 0x3c, 0x6a, 0x04, 0x71, 0xda, 0xf0, 0x0b, 0x7c, 0x2e, 0xfc, 0x9e, 0xe8, 0x80, 0x41, 0x65, 0x4f, 0x87, 0x62, 0x90, 0x07, 0xc1, 0x24, 0x32, 0x22, 0x11, 0xa5, 0xf4, 0xea, 0x3c, 0x58, 0x23, 0x85, 0x7b, 0xc8, 0xfc, 0x7e, 0x21, 0xc9, 0x45, 0x48, 0xb0, 0xee, 0xbd, 0xcf, 0xf7, 0x91, 0x60, 0xe1, 0x12, 0x46, 0x1e, 0x40, 0x50, 0x91, 0x10, 0xcf, 0xdc, 0x4f, 0x0f, 0x13, 0xc7, 0xfb, 0x92, 0x1a, 0xba, 0xc8, 0xdf, 0xaa, 0xc2, 0x1a, 0xcb, 0x0f, 0x7b, 0x8a, 0x13, 0xa4, 0xb5, 0xcc, 0xa5, 0x23, 0xd5, 0xc7, 0xdd, 0xf7, 0x05, 0x23, 0xeb, 0x57, 0x0c, 0x59, 0xb6, 0xc7, 0xae, 0x97, 0x67, 0xe4, 0xec, 0x9a, 0x63, 0xd1, 0x13, 0x6d, 0x10, 0x23, 0x1b, 0x40, 0x1e, 0x20, 0xe7, 0x41, 0x02, 0x84, 0x83, 0x48, 0x01, 0x7a, 0x16, 0x16 } +, + /* Encryption */ + 128, + { 0x5e, 0x51, 0x43, 0x63, 0x28, 0x7d, 0xe9, 0xb3, 0x80, 0x04, 0x8c, 0xc4, 0x43, 0x5d, 0x53, 0x29, 0x4a, 0xd5, 0x94, 0x1c, 0x55, 0x1a, 0x97, 0xe1, 0x3c, 0x16, 0xdc, 0x13, 0x98, 0xde, 0x61, 0x0d, 0xc7, 0x33, 0x7b, 0xc6, 0xbd, 0xe5, 0x78, 0xe9, 0xe9, 0xf5, 0x6a, 0xf1, 0x44, 0x54, 0xf2, 0xe8, 0x31, 0xbe, 0xef, 0x32, 0x31, 0xa8, 0x50, 0x68, 0xe8, 0xfe, 0xf7, 0x2c, 0x89, 0xe1, 0xdf, 0x1c, 0x99, 0x43, 0x0a, 0x60, 0xf6, 0xd9, 0x42, 0x89, 0xcf, 0xba, 0x87, 0xb2, 0xb4, 0x32, 0xa4, 0x0b, 0x88, 0xdb, 0x61, 0xda, 0xe0, 0x88, 0xf9, 0xed, 0x4e, 0x28, 0x4a, 0x21, 0x63, 0xaf, 0x65, 0xbf, 0x2b, 0x43, 0x55, 0x9a, 0x5d, 0xa2, 0xae, 0xc5, 0xbb, 0x8f, 0x43, 0xf9, 0x2c, 0x1b, 0x04, 0xa5, 0x14, 0x6a, 0x65, 0xb6, 0xe0, 0x19, 0xb4, 0xcd, 0xd2, 0x94, 0x0c, 0x35, 0xd9, 0x64, 0x5b, 0x2d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.7", + /* Message */ + 5, + { 0x8a, 0x84, 0x7d, 0xd9, 0xe2 } +, + /* Seed */ + 120, + { 0xa1, 0x3d, 0xff, 0x8a, 0x48, 0xe8, 0x04, 0x94, 0xae, 0x66, 0xe6, 0xba, 0x9f, 0x17, 0x9a, 0x01, 0x0d, 0x9e, 0x6d, 0x40, 0x31, 0x87, 0x96, 0x7f, 0x99, 0xfd, 0xd9, 0x0e, 0xf9, 0x0e, 0x0a, 0x94, 0x07, 0x3f, 0xf0, 0xe4, 0xd0, 0xe6, 0x66, 0x4f, 0xf3, 0x73, 0xb5, 0x09, 0x95, 0x3e, 0x04, 0xef, 0x77, 0x83, 0xbe, 0x0f, 0xb4, 0x6c, 0x8a, 0x9f, 0xc0, 0xed, 0x8c, 0x1f, 0x33, 0xcb, 0x4d, 0x0d, 0x2f, 0x1d, 0x0d, 0x5c, 0xdb, 0xa1, 0x4d, 0xca, 0x50, 0x8c, 0xa1, 0xd7, 0x3d, 0x20, 0x80, 0x18, 0x63, 0x9b, 0xc8, 0xe1, 0x65, 0x86, 0x23, 0xde, 0x1e, 0x5b, 0xa3, 0xf0, 0x5e, 0xd0, 0x91, 0x4d, 0x2f, 0x96, 0x90, 0x2f, 0x25, 0x20, 0x33, 0x2d, 0x84, 0x92, 0xd3, 0x73, 0x4a, 0xcd, 0xeb, 0xbd, 0xf4, 0x3e, 0x50, 0xa4, 0x3e, 0x7a, 0xa8, 0x72 } +, + /* Encryption */ + 128, + { 0x82, 0x7a, 0x67, 0xe8, 0x15, 0x78, 0x1c, 0x4d, 0x4e, 0x2b, 0x2e, 0x16, 0x9d, 0x80, 0xca, 0xe9, 0x36, 0x68, 0x72, 0xa7, 0x92, 0xaf, 0xbf, 0x3c, 0x0c, 0xd5, 0x1c, 0xe2, 0x8c, 0x70, 0xe8, 0x6d, 0x41, 0xeb, 0xb9, 0x75, 0x2f, 0x3f, 0x92, 0xdb, 0xa5, 0x1a, 0xdb, 0xb6, 0x85, 0x1b, 0x1f, 0x78, 0x45, 0x61, 0xa8, 0xf1, 0x97, 0x20, 0x8f, 0xde, 0x02, 0x97, 0x0b, 0x38, 0xf2, 0xa9, 0x74, 0x22, 0xec, 0x7f, 0x4f, 0xc8, 0xa1, 0x06, 0x75, 0xa9, 0xdb, 0xde, 0x10, 0x9e, 0xed, 0x0c, 0xe0, 0x65, 0x27, 0x70, 0x3e, 0xe0, 0x5b, 0x65, 0x7d, 0x34, 0x08, 0xf7, 0xfd, 0xdb, 0x1e, 0xec, 0xcf, 0xfa, 0xe1, 0x6b, 0x1d, 0xa1, 0x07, 0x30, 0x7a, 0x2c, 0xf2, 0x56, 0xfa, 0x60, 0xe8, 0x15, 0x21, 0x72, 0xde, 0x9f, 0x95, 0x27, 0xfe, 0x92, 0x0a, 0x90, 0x1d, 0x93, 0xc4, 0xf4, 0xd5, 0x7e, 0x54, 0x6e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.8", + /* Message */ + 49, + { 0x37, 0x32, 0x36, 0xb7, 0x20, 0x2d, 0x39, 0xb2, 0xee, 0x30, 0xcf, 0xb4, 0x6d, 0xb0, 0x95, 0x11, 0xf6, 0xf3, 0x07, 0xcc, 0x61, 0xcc, 0x21, 0x60, 0x6c, 0x18, 0xa7, 0x5b, 0x8a, 0x62, 0xf8, 0x22, 0xdf, 0x03, 0x1b, 0xa0, 0xe0, 0xe8, 0x2d, 0xd2, 0xf3, 0xe5, 0xd3, 0x1e, 0x4e, 0xa2, 0x57, 0xb1, 0x5b } +, + /* Seed */ + 76, + { 0x21, 0x99, 0x74, 0xa0, 0x87, 0xf0, 0xa2, 0x81, 0x93, 0xe6, 0x49, 0xa0, 0x4a, 0xe9, 0xd8, 0x4c, 0xf2, 0xc8, 0xa9, 0xa4, 0x6c, 0xdf, 0xd8, 0xf1, 0xac, 0x62, 0xc7, 0xe0, 0xf2, 0x0f, 0x4e, 0x27, 0x03, 0x0c, 0x72, 0xb2, 0x0a, 0x5d, 0xb7, 0x25, 0xb4, 0xa8, 0x68, 0x3d, 0xf5, 0x55, 0x6e, 0xe7, 0x94, 0x7f, 0xa0, 0xa7, 0x66, 0x1b, 0x6d, 0x99, 0xdc, 0xb7, 0x9e, 0x49, 0x4f, 0x46, 0x73, 0xf0, 0x73, 0xa0, 0x41, 0xdd, 0x90, 0x7c, 0x87, 0x32, 0x4e, 0x86, 0x25, 0xdd } +, + /* Encryption */ + 128, + { 0x1a, 0x6d, 0xf5, 0x75, 0x99, 0x84, 0xf2, 0xc4, 0x11, 0x93, 0x55, 0xc5, 0xdb, 0x35, 0xc8, 0xa4, 0x78, 0x16, 0x4d, 0x5e, 0x5e, 0xe7, 0x7b, 0x49, 0x91, 0xf1, 0x04, 0xba, 0x91, 0xb9, 0x87, 0x0f, 0x15, 0x91, 0xbe, 0x1f, 0x19, 0xf5, 0x5a, 0x80, 0x51, 0xa6, 0x2c, 0x0e, 0x59, 0x49, 0x3d, 0xf6, 0xf0, 0x0f, 0xe5, 0x0e, 0xf7, 0x3a, 0x6c, 0xf0, 0xc4, 0x35, 0x41, 0xf5, 0x32, 0x0d, 0xab, 0x7b, 0x2f, 0xc6, 0x7c, 0x93, 0x22, 0x5c, 0xcc, 0xd6, 0xd5, 0x03, 0x47, 0xaa, 0x96, 0x9a, 0xd8, 0x7b, 0xd3, 0xd8, 0x20, 0x81, 0x45, 0x4f, 0xea, 0xd8, 0x10, 0xdc, 0x1a, 0xb8, 0xc2, 0x17, 0x81, 0xf7, 0x61, 0x2e, 0x64, 0x06, 0x72, 0x9b, 0x32, 0x2e, 0x04, 0xb1, 0x62, 0x4f, 0x85, 0x38, 0x98, 0x56, 0x59, 0xae, 0x34, 0xd9, 0x93, 0x1e, 0x01, 0x9f, 0x76, 0x2c, 0x79, 0x7d, 0x5c, 0xbf, 0xa3, 0x2d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.9", + /* Message */ + 33, + { 0x97, 0xe0, 0xb6, 0x36, 0xbf, 0xdd, 0xb8, 0xe1, 0xc8, 0xa9, 0xcf, 0x5b, 0x30, 0x5c, 0xef, 0x3a, 0x8f, 0x47, 0xf9, 0xa8, 0xb3, 0x34, 0x4f, 0x13, 0x55, 0xfa, 0x3d, 0xba, 0xb6, 0x7b, 0xb9, 0x72, 0x10 } +, + /* Seed */ + 92, + { 0xc1, 0xf8, 0x9b, 0xcd, 0xc5, 0x60, 0x40, 0xd5, 0xe6, 0x63, 0xb7, 0x4b, 0xfd, 0xe2, 0x39, 0x7b, 0x58, 0x46, 0x08, 0xcd, 0xf3, 0x2d, 0x5a, 0x58, 0x44, 0x72, 0x4a, 0xc7, 0xe5, 0x98, 0xa8, 0x6e, 0xf7, 0x11, 0x4b, 0x1b, 0xe0, 0x87, 0x30, 0xcb, 0x10, 0xf6, 0x61, 0xfb, 0xfb, 0x86, 0x09, 0xf7, 0xc6, 0xc3, 0x74, 0x42, 0xa1, 0xb1, 0x1e, 0x04, 0xa6, 0x11, 0xff, 0x8c, 0xa5, 0xce, 0x9a, 0xfc, 0x1e, 0xb3, 0xaa, 0xa9, 0x2c, 0x9f, 0x28, 0xba, 0xe2, 0x20, 0x44, 0x05, 0x78, 0x99, 0x02, 0x26, 0x07, 0x83, 0x78, 0xc4, 0x93, 0x41, 0x13, 0x74, 0xc5, 0x3e, 0x3d, 0xdc } +, + /* Encryption */ + 128, + { 0x87, 0x3c, 0xc4, 0xdc, 0xa4, 0x27, 0x97, 0x2b, 0x63, 0xc6, 0xcc, 0x8a, 0xc1, 0x1c, 0xcc, 0x33, 0xc9, 0x59, 0xf7, 0xfc, 0xfe, 0x4b, 0x45, 0xbb, 0xd4, 0x7b, 0x29, 0xd9, 0xc9, 0x88, 0xc0, 0x1a, 0x96, 0xbc, 0x1e, 0xae, 0x0e, 0xf9, 0xb1, 0x94, 0x8d, 0xce, 0x2c, 0xc9, 0xf0, 0xaa, 0x91, 0x7e, 0x86, 0xa6, 0xc1, 0x1f, 0x8d, 0xa3, 0xda, 0x29, 0xdf, 0x90, 0x59, 0x01, 0xf1, 0x91, 0x8a, 0x76, 0x16, 0x8d, 0xe1, 0x17, 0x5e, 0x27, 0x35, 0x12, 0x8c, 0x09, 0x72, 0x99, 0xd6, 0x6e, 0xa5, 0xcc, 0xf9, 0xb9, 0x5b, 0x36, 0x92, 0xee, 0xbf, 0xc6, 0xea, 0x11, 0xbc, 0x37, 0x09, 0x1b, 0x79, 0x5f, 0x18, 0x80, 0x3d, 0x70, 0xe7, 0x95, 0x58, 0xe1, 0x25, 0x16, 0x23, 0x0f, 0xed, 0x55, 0x15, 0xe5, 0x1b, 0x45, 0xae, 0x86, 0xce, 0xfe, 0x47, 0xb9, 0x37, 0x90, 0xe4, 0x99, 0x4d, 0xc4, 0x1e, 0x05 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.10", + /* Message */ + 55, + { 0x82, 0xb5, 0x07, 0x5b, 0xfc, 0x88, 0xf4, 0x00, 0x65, 0x76, 0xaa, 0x80, 0xa0, 0x00, 0x7a, 0x74, 0x51, 0x18, 0x4d, 0x4f, 0x76, 0x0c, 0xf9, 0x24, 0x28, 0x04, 0x22, 0x2b, 0x0e, 0x07, 0x26, 0xf5, 0x55, 0x03, 0x0e, 0x4e, 0x6b, 0x01, 0xf7, 0x93, 0xb0, 0x97, 0x01, 0x81, 0x27, 0x82, 0x4a, 0x3e, 0x40, 0x24, 0x57, 0xd8, 0x49, 0x5f, 0xc0 } +, + /* Seed */ + 70, + { 0xd5, 0x5e, 0x3d, 0x48, 0x97, 0xe9, 0xd8, 0x65, 0x01, 0x4c, 0xb1, 0x5d, 0x3e, 0xe3, 0xf9, 0xfb, 0xd2, 0x9c, 0x92, 0xe5, 0xc2, 0x37, 0xdc, 0xae, 0x46, 0x67, 0x2a, 0x46, 0x3e, 0xaa, 0xa4, 0xf7, 0xdd, 0x09, 0x86, 0x1e, 0x94, 0x6a, 0xc6, 0x5b, 0x85, 0x62, 0x50, 0x63, 0x93, 0xb8, 0x51, 0x92, 0xad, 0x41, 0xfb, 0x0c, 0x48, 0xc8, 0xc0, 0x52, 0x98, 0x1b, 0xdd, 0xcd, 0x5f, 0x1f, 0xc8, 0xb1, 0x39, 0xcd, 0x47, 0xca, 0xcf, 0xfc } +, + /* Encryption */ + 128, + { 0x2e, 0x83, 0xc3, 0xd2, 0x88, 0x01, 0x5a, 0x5f, 0x50, 0x3d, 0x3e, 0x5d, 0xe7, 0xd2, 0xad, 0x91, 0x06, 0x54, 0x5e, 0xf9, 0x7d, 0x63, 0xe4, 0xd0, 0x6a, 0x5a, 0x0d, 0x9d, 0xbc, 0x29, 0xf6, 0xba, 0xfb, 0x93, 0xa5, 0x17, 0x3f, 0xa5, 0x06, 0x3a, 0x69, 0x39, 0xdb, 0xa6, 0xc7, 0xa4, 0x28, 0xc3, 0x5e, 0x7d, 0xbe, 0x6a, 0x95, 0x93, 0xfe, 0x5e, 0xc4, 0xc1, 0x98, 0x78, 0x89, 0x3f, 0x31, 0x37, 0x09, 0xc8, 0x76, 0x02, 0x72, 0x6c, 0xb3, 0x25, 0x5b, 0xe7, 0x5a, 0xdc, 0x7f, 0x2f, 0x27, 0xe6, 0xdb, 0x91, 0xc3, 0xa3, 0x43, 0xea, 0xff, 0x1c, 0x28, 0xd9, 0xd5, 0xf7, 0xcb, 0x65, 0x74, 0xe6, 0x31, 0x06, 0x90, 0x03, 0xcd, 0xcf, 0xa0, 0x77, 0x43, 0xa7, 0x34, 0x0d, 0x58, 0x83, 0x9e, 0x70, 0x8b, 0xf3, 0x6a, 0xf6, 0x34, 0x2d, 0xb8, 0xdf, 0xa4, 0x1f, 0xea, 0xda, 0xfc, 0x69, 0x53, 0xac } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.11", + /* Message */ + 34, + { 0x36, 0x48, 0xc3, 0x6f, 0x85, 0x1f, 0x52, 0xf2, 0x32, 0x87, 0x79, 0x09, 0x19, 0x85, 0xa3, 0xc8, 0x12, 0xe1, 0x8a, 0x70, 0x55, 0xd0, 0x90, 0xbb, 0xf0, 0x32, 0x4c, 0x13, 0x79, 0x3b, 0xb8, 0x22, 0x1a, 0x57 } +, + /* Seed */ + 91, + { 0xc1, 0x27, 0x71, 0x85, 0xc3, 0x59, 0x55, 0xca, 0xed, 0xfd, 0xf9, 0xde, 0x55, 0xd5, 0xd9, 0x5a, 0x39, 0x8d, 0x58, 0xf5, 0xf3, 0x33, 0x19, 0x1f, 0xc0, 0x29, 0x45, 0xef, 0xdf, 0xad, 0xfb, 0x6d, 0xb0, 0x5e, 0xe2, 0xa2, 0xd3, 0x41, 0x83, 0xed, 0xf8, 0x9a, 0x1a, 0x4d, 0xcc, 0xc4, 0x65, 0x91, 0xb3, 0x53, 0x2b, 0xa7, 0x03, 0x93, 0x62, 0xc7, 0x5d, 0xf1, 0x94, 0xec, 0x10, 0x64, 0x48, 0xaf, 0xb7, 0xf6, 0xbf, 0xb2, 0x80, 0x7e, 0x38, 0x3e, 0x15, 0x99, 0x54, 0x25, 0x5e, 0x82, 0x7c, 0xb9, 0xda, 0xdc, 0x8d, 0x9b, 0x7e, 0x68, 0xa1, 0xaa, 0x09, 0x76, 0x35 } +, + /* Encryption */ + 128, + { 0x88, 0x62, 0xf1, 0x97, 0x3f, 0xef, 0xe0, 0xaf, 0x02, 0xd9, 0x6c, 0xc4, 0x58, 0x33, 0x4d, 0xed, 0x6c, 0x02, 0xd8, 0xd7, 0xea, 0xf5, 0x93, 0x77, 0x9c, 0x5d, 0x38, 0x6c, 0x4e, 0x49, 0xf7, 0x68, 0xf1, 0x30, 0xb4, 0x87, 0xb3, 0xc9, 0x1e, 0x32, 0x3a, 0x47, 0x7e, 0x4c, 0x11, 0x0a, 0x33, 0x41, 0xff, 0x46, 0xee, 0xe3, 0x7c, 0x77, 0x3e, 0x5c, 0x0a, 0xc8, 0x39, 0xbc, 0x55, 0xcc, 0x0c, 0x07, 0x0c, 0xac, 0x01, 0xcd, 0x45, 0x18, 0x3c, 0xfe, 0xe6, 0xb8, 0x8b, 0xfb, 0x82, 0x36, 0x1d, 0x35, 0x60, 0x19, 0x7c, 0xde, 0xab, 0x42, 0xe5, 0xc7, 0x55, 0xd2, 0x37, 0x97, 0x1a, 0x88, 0xda, 0xf6, 0x10, 0xcb, 0x39, 0x52, 0x61, 0x4b, 0x36, 0x40, 0x56, 0xcd, 0x49, 0x14, 0x20, 0xef, 0xfe, 0x3a, 0x0b, 0x8c, 0xe3, 0x1f, 0x2e, 0x3e, 0x49, 0xca, 0xd6, 0xf3, 0xb0, 0x64, 0x0f, 0x44, 0x91, 0xde } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.12", + /* Message */ + 20, + { 0x94, 0xf7, 0x8c, 0xf4, 0x5c, 0x53, 0xfc, 0x46, 0xe7, 0xeb, 0x1b, 0x26, 0x61, 0x8a, 0x29, 0xe9, 0x48, 0x50, 0x12, 0xc1 } +, + /* Seed */ + 105, + { 0xe6, 0xde, 0x9e, 0x9b, 0x90, 0x22, 0xa5, 0x5f, 0x56, 0x12, 0x1d, 0x5a, 0xc0, 0x0a, 0xa6, 0xdf, 0x29, 0x9c, 0x8a, 0x36, 0x94, 0x22, 0xe7, 0x54, 0x29, 0x56, 0xb6, 0xda, 0x2e, 0x0d, 0xcd, 0xee, 0x96, 0x8d, 0xb0, 0x7d, 0x99, 0x5a, 0x7b, 0xb8, 0x76, 0xf7, 0xf8, 0xcd, 0x66, 0xb2, 0xf5, 0x42, 0xc0, 0x53, 0x08, 0xf7, 0x49, 0x83, 0xa3, 0xf8, 0x36, 0x0c, 0x6b, 0x89, 0x47, 0xf8, 0x7d, 0x60, 0x8b, 0x03, 0x1a, 0x2c, 0x68, 0xdd, 0xe1, 0x47, 0x1a, 0xe4, 0x96, 0xae, 0x9b, 0x16, 0xe2, 0xa8, 0x11, 0x81, 0xeb, 0x6f, 0xc2, 0xf6, 0x5b, 0xaa, 0xad, 0xda, 0x64, 0x22, 0xa9, 0x34, 0x31, 0xf6, 0xf3, 0xb0, 0x7b, 0x5b, 0x46, 0xa3, 0xcf, 0x89, 0x48 } +, + /* Encryption */ + 128, + { 0x3c, 0x6d, 0x3b, 0x43, 0xd2, 0x3a, 0xdb, 0x79, 0xd6, 0x97, 0x23, 0x38, 0x08, 0xb0, 0x74, 0x48, 0x76, 0x97, 0xf3, 0x35, 0xfd, 0x99, 0xcd, 0xe8, 0x65, 0x41, 0x1f, 0xb1, 0x82, 0x28, 0x92, 0x56, 0x1f, 0xdc, 0x24, 0xa8, 0xb8, 0xbb, 0x2c, 0x4f, 0x65, 0x3c, 0x4d, 0x15, 0x6c, 0x77, 0xa7, 0x5d, 0xe3, 0x16, 0x00, 0xb5, 0x70, 0x9e, 0x8d, 0x50, 0x6e, 0x98, 0xe1, 0xd3, 0x73, 0xcb, 0xda, 0x01, 0xf4, 0xd9, 0xfe, 0xb0, 0x29, 0x71, 0x98, 0xca, 0xd0, 0xca, 0x2a, 0x7e, 0x3b, 0x1e, 0x63, 0x90, 0x3b, 0x10, 0x43, 0xce, 0x79, 0x49, 0x4c, 0x57, 0x54, 0xf7, 0xf9, 0x0f, 0xc1, 0xf0, 0x73, 0xa6, 0x19, 0x92, 0x9e, 0xf1, 0x26, 0x39, 0x4b, 0x06, 0x24, 0xf3, 0xb8, 0xba, 0x6d, 0x56, 0x45, 0xe9, 0x90, 0xe7, 0xc0, 0x13, 0x2c, 0xe2, 0x12, 0x31, 0x46, 0xfd, 0x9c, 0xad, 0xf7, 0x45, 0xec, 0x61 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.13", + /* Message */ + 35, + { 0x77, 0x9d, 0x1e, 0xb8, 0x4f, 0xa2, 0x84, 0xc3, 0x7d, 0x29, 0xd5, 0xe1, 0x79, 0xd0, 0x03, 0x06, 0xb4, 0x13, 0xc4, 0x4a, 0x80, 0x0a, 0x07, 0x7e, 0x59, 0x85, 0x3f, 0x63, 0x05, 0xf9, 0x2e, 0x59, 0xfb, 0x7f, 0x81 } +, + /* Seed */ + 90, + { 0xc3, 0xe6, 0xd1, 0x8b, 0xda, 0x97, 0x78, 0x2c, 0xa7, 0x81, 0xfa, 0x76, 0xd9, 0x7a, 0x6c, 0x94, 0xd8, 0x54, 0xd1, 0x41, 0x99, 0xb4, 0xea, 0x7d, 0x82, 0xc5, 0xbc, 0xbb, 0xe6, 0xcd, 0xaa, 0xb5, 0x25, 0x57, 0x47, 0x44, 0x3c, 0x59, 0xbf, 0x8c, 0x77, 0xec, 0xda, 0xa6, 0x4a, 0xe7, 0xce, 0x61, 0xe2, 0xc7, 0x30, 0x01, 0x32, 0xb7, 0x54, 0xe9, 0x16, 0x2f, 0x7c, 0xde, 0x75, 0x8f, 0x48, 0x0a, 0xe5, 0x88, 0xcf, 0xd4, 0x4a, 0x94, 0x6d, 0x64, 0xe2, 0x72, 0x0a, 0x2d, 0x17, 0x52, 0x55, 0x45, 0x22, 0x04, 0x84, 0x83, 0x81, 0x18, 0xad, 0x6e, 0x6b, 0x54 } +, + /* Encryption */ + 128, + { 0x72, 0x2c, 0xa9, 0x25, 0x66, 0xc7, 0x3c, 0xc8, 0x5d, 0x19, 0xce, 0x3f, 0xaa, 0x14, 0xcb, 0x2e, 0x79, 0x84, 0x9f, 0x20, 0x50, 0x92, 0xd1, 0x58, 0x92, 0x82, 0x31, 0x3c, 0x04, 0x27, 0xf0, 0x67, 0x79, 0x8a, 0xfa, 0xe3, 0xe3, 0xf0, 0xa5, 0x61, 0xf3, 0x99, 0x34, 0x6e, 0x9d, 0x10, 0x7d, 0xa0, 0x4a, 0xf4, 0x4b, 0x0c, 0x6f, 0x04, 0x4a, 0xde, 0xfe, 0x09, 0x7a, 0x0c, 0xd1, 0x4a, 0x47, 0xa9, 0x9c, 0xd9, 0x81, 0x9a, 0x98, 0x41, 0x37, 0x06, 0x30, 0x7c, 0xbd, 0x0d, 0xa0, 0x16, 0x97, 0x46, 0x9e, 0xff, 0x71, 0xd3, 0x14, 0x41, 0x63, 0x94, 0x93, 0xfb, 0xed, 0x8e, 0xee, 0x1b, 0xa3, 0x9f, 0xdd, 0x07, 0xfc, 0x0e, 0xa0, 0x82, 0x30, 0x18, 0x61, 0x79, 0xf9, 0x0e, 0x7e, 0xf1, 0x3c, 0x61, 0xee, 0x56, 0xf1, 0x67, 0xfc, 0x2f, 0x6b, 0x15, 0x79, 0x3e, 0x1a, 0x32, 0x24, 0xff, 0xa2, 0x9e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.14", + /* Message */ + 1, + { 0x88 } +, + /* Seed */ + 124, + { 0xc0, 0x16, 0x9d, 0x76, 0xe4, 0xea, 0x45, 0x45, 0x41, 0x0d, 0xdf, 0x66, 0x46, 0xc1, 0xba, 0x7d, 0xd2, 0x72, 0xd7, 0xc3, 0x49, 0x8b, 0xa6, 0xb0, 0x80, 0x4b, 0x42, 0x61, 0x30, 0xa8, 0x0f, 0xbf, 0xff, 0x4b, 0xb7, 0xb5, 0xf5, 0x59, 0xb0, 0xa9, 0x09, 0x0e, 0x4a, 0xd9, 0xb9, 0xf4, 0x16, 0xa6, 0xdf, 0xdc, 0x15, 0x01, 0xb1, 0xba, 0x46, 0x87, 0x7b, 0x1a, 0x96, 0xfa, 0x84, 0x91, 0xdc, 0xfd, 0xde, 0x50, 0xeb, 0xee, 0xd2, 0x4d, 0x3f, 0x98, 0x96, 0x24, 0x13, 0x34, 0x6e, 0xd4, 0xa3, 0x39, 0x3e, 0x23, 0x5b, 0x77, 0xbc, 0x1e, 0xd6, 0x74, 0x68, 0xec, 0xe2, 0x79, 0x2a, 0x2f, 0xd3, 0xa8, 0x34, 0x8f, 0xc5, 0x50, 0x9b, 0x59, 0x06, 0xf2, 0x88, 0x56, 0x15, 0xdf, 0x8c, 0x14, 0x61, 0x37, 0x7a, 0x74, 0x1d, 0x59, 0x52, 0xfb, 0x36, 0xea, 0xc0, 0x20, 0x1e, 0x27 } +, + /* Encryption */ + 128, + { 0x4e, 0xd7, 0xd1, 0x29, 0x1a, 0x03, 0x36, 0x65, 0x4d, 0x5c, 0xa2, 0xb1, 0xf9, 0xd2, 0x0c, 0xb2, 0xda, 0x72, 0x26, 0xf7, 0x11, 0x6b, 0x93, 0x09, 0x88, 0x43, 0x9b, 0x44, 0x63, 0x98, 0x11, 0x04, 0xbd, 0x63, 0xc2, 0xce, 0x2b, 0x77, 0xd6, 0x26, 0xb3, 0x10, 0x9c, 0x93, 0x14, 0x03, 0xac, 0x5b, 0x49, 0xb4, 0x24, 0x7c, 0x4f, 0x69, 0x67, 0xb8, 0xc0, 0xdb, 0x06, 0x3c, 0x99, 0x95, 0xaf, 0x9d, 0x36, 0x54, 0x06, 0x50, 0x93, 0x8b, 0x01, 0xf9, 0x39, 0x06, 0xf9, 0x83, 0x89, 0x07, 0xed, 0x59, 0x36, 0xab, 0xb3, 0x43, 0xb0, 0xe2, 0x55, 0x09, 0xa1, 0xd2, 0xd4, 0xc5, 0xc8, 0xb9, 0x58, 0x06, 0x50, 0xda, 0x2c, 0xe1, 0x1f, 0xa3, 0xcf, 0x3e, 0x64, 0x07, 0x23, 0xea, 0xcb, 0xee, 0x87, 0xfa, 0xd3, 0xee, 0x35, 0x95, 0x8b, 0x45, 0x07, 0x5d, 0xf7, 0x81, 0xc4, 0x13, 0x46, 0x6a, 0xf1, 0x39 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.15", + /* Message */ + 51, + { 0xa2, 0xdc, 0x08, 0x77, 0x78, 0xd5, 0x43, 0x40, 0x8e, 0x89, 0x73, 0xf1, 0x36, 0x31, 0x59, 0xed, 0xb8, 0xf0, 0x78, 0x3c, 0x45, 0x70, 0x89, 0x07, 0x2d, 0xce, 0x66, 0xd3, 0x10, 0x2b, 0xb4, 0xfa, 0xe6, 0x0a, 0xa6, 0x0e, 0x41, 0x93, 0x3c, 0x48, 0xa1, 0xbe, 0x39, 0x53, 0xec, 0x2f, 0x80, 0x4c, 0x0c, 0xc9, 0x6c } +, + /* Seed */ + 74, + { 0x18, 0x11, 0x20, 0x14, 0x06, 0x53, 0x29, 0xd0, 0x4b, 0xfb, 0x0c, 0xf5, 0x44, 0xdd, 0x38, 0xd7, 0xbe, 0xf1, 0x54, 0x9b, 0x4a, 0x49, 0xa1, 0x67, 0x76, 0xdd, 0xa7, 0x4d, 0x0a, 0x7e, 0xdc, 0x49, 0x67, 0xb4, 0x24, 0x0c, 0x37, 0x14, 0x2f, 0xa3, 0xf6, 0x63, 0x9c, 0x26, 0x96, 0xcd, 0x7d, 0x4b, 0x18, 0xa1, 0x1e, 0x2f, 0xb5, 0x40, 0x81, 0xf2, 0xde, 0x5b, 0xd7, 0xbd, 0x15, 0xcd, 0xda, 0x92, 0xc9, 0x4c, 0x3a, 0x47, 0x18, 0x7b, 0x5f, 0xf4, 0x3b, 0x53 } +, + /* Encryption */ + 128, + { 0x71, 0x15, 0x19, 0x0a, 0x21, 0x04, 0x88, 0xf0, 0x4f, 0xa0, 0xc0, 0x0c, 0x93, 0xa4, 0x68, 0xa8, 0x03, 0x0b, 0x7b, 0x9f, 0xc1, 0x00, 0x20, 0xd8, 0x31, 0x0b, 0xcb, 0x01, 0xa5, 0xc8, 0xdd, 0xa1, 0xd0, 0x6c, 0xe2, 0x41, 0xdc, 0x77, 0x5b, 0x43, 0xe6, 0xf1, 0x3b, 0x19, 0xab, 0xfc, 0xbf, 0x36, 0x16, 0xe8, 0x4f, 0x10, 0x7c, 0x9e, 0xd8, 0x0d, 0x1b, 0x86, 0xbf, 0x87, 0xc9, 0x8c, 0x2b, 0x62, 0x9f, 0xfa, 0xda, 0xa6, 0xec, 0x01, 0xf4, 0xe6, 0x75, 0x55, 0x8e, 0xf5, 0x26, 0x06, 0xea, 0xf1, 0x26, 0x06, 0x8f, 0xa7, 0x53, 0x4d, 0xd1, 0x3b, 0x92, 0x0d, 0x23, 0x81, 0x69, 0x5a, 0xd7, 0x75, 0xff, 0xf0, 0xbb, 0x7c, 0xec, 0x46, 0x90, 0x90, 0x1d, 0x6f, 0x1e, 0x17, 0x36, 0xb8, 0x2c, 0xfe, 0x3a, 0x0c, 0x22, 0x4d, 0x18, 0xf1, 0x29, 0x15, 0xfd, 0xc9, 0x5c, 0x18, 0x39, 0x7c, 0x35, 0x70 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.16", + /* Message */ + 36, + { 0x11, 0x0b, 0xf2, 0xb1, 0xd0, 0xdd, 0x81, 0x2f, 0x2a, 0x5a, 0x21, 0xf3, 0x40, 0x4f, 0xa2, 0xf2, 0xc4, 0x54, 0xc4, 0x43, 0x2f, 0xdf, 0xa7, 0x0f, 0x1b, 0x0f, 0x23, 0xec, 0x69, 0xc1, 0x02, 0x37, 0x73, 0xa7, 0x3a, 0xba } +, + /* Seed */ + 89, + { 0x17, 0xb8, 0x5f, 0x76, 0x53, 0xff, 0x0e, 0xf5, 0xde, 0x7f, 0x25, 0x69, 0x6c, 0xd4, 0x90, 0x23, 0xad, 0x8e, 0xac, 0x94, 0x8a, 0x83, 0xe2, 0x24, 0x58, 0xec, 0xd5, 0xd1, 0x0a, 0x43, 0x86, 0x6d, 0xc7, 0x91, 0x55, 0x5e, 0x64, 0xf0, 0x78, 0xc3, 0x8c, 0x75, 0x2b, 0x6e, 0x9c, 0x6e, 0xee, 0xb3, 0x39, 0xee, 0xc9, 0x10, 0x16, 0xd2, 0x58, 0x88, 0x6d, 0x01, 0x27, 0x75, 0xad, 0x64, 0x36, 0x02, 0xa0, 0xf0, 0xd1, 0x79, 0x34, 0x54, 0xa0, 0x60, 0x94, 0x71, 0x16, 0x22, 0x88, 0x22, 0x39, 0x50, 0x82, 0x6e, 0xd8, 0xe2, 0x02, 0x5d, 0xa9, 0xa4, 0xe9 } +, + /* Encryption */ + 128, + { 0x5d, 0x0f, 0x2f, 0xd8, 0x5e, 0x6f, 0x9d, 0x9e, 0x43, 0x2f, 0xad, 0x86, 0x0f, 0xdc, 0x49, 0x96, 0x96, 0x24, 0xff, 0x4f, 0xa0, 0x71, 0x5d, 0x36, 0x1e, 0x9f, 0x00, 0xb0, 0x5b, 0x3a, 0xa0, 0xba, 0x9e, 0xb2, 0x7b, 0xae, 0x61, 0x0e, 0xfd, 0xe1, 0x14, 0x3c, 0xbc, 0x93, 0x3b, 0x52, 0xde, 0xa7, 0x01, 0x87, 0x60, 0xbb, 0x25, 0x1b, 0xe0, 0xe1, 0xe3, 0x0c, 0xd1, 0xc5, 0x99, 0x1a, 0xef, 0x74, 0x4d, 0xb8, 0x2f, 0x16, 0x6b, 0x90, 0x63, 0xef, 0xb7, 0xe3, 0x38, 0x40, 0xa2, 0x56, 0x90, 0x05, 0x65, 0x4b, 0x14, 0x0e, 0x11, 0x5f, 0xa5, 0x6c, 0x30, 0x40, 0x6e, 0x45, 0x65, 0x6e, 0x81, 0x99, 0xaf, 0x39, 0x4f, 0x63, 0x86, 0x34, 0x6d, 0x5f, 0x1a, 0x30, 0x0b, 0x95, 0xba, 0x48, 0xfc, 0x08, 0x73, 0xd6, 0x18, 0xd6, 0x92, 0xbb, 0x02, 0x5b, 0xf1, 0x5e, 0x9d, 0x23, 0x2c, 0x64, 0x1a, 0xda } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.17", + /* Message */ + 60, + { 0xd9, 0xd9, 0x37, 0x13, 0x1f, 0xf1, 0x94, 0x0a, 0x86, 0xbf, 0x71, 0x39, 0xb4, 0x81, 0x14, 0x36, 0x41, 0x95, 0xb4, 0x00, 0x52, 0x22, 0xa8, 0xbb, 0xbc, 0x26, 0x1a, 0x7f, 0x2e, 0x21, 0x2b, 0x8d, 0xd0, 0x35, 0xe5, 0x3f, 0x91, 0x44, 0xf5, 0x61, 0x0b, 0x4c, 0xec, 0x32, 0xea, 0x01, 0xbd, 0xa9, 0xd3, 0xc8, 0x0c, 0xf2, 0x94, 0x64, 0xf8, 0x0f, 0x5f, 0x56, 0x56, 0xc8 } +, + /* Seed */ + 65, + { 0x33, 0x05, 0xe1, 0xda, 0x60, 0xe5, 0x86, 0x73, 0xfc, 0x46, 0xcd, 0x33, 0xbe, 0x2a, 0x66, 0xd3, 0xa1, 0x02, 0xc3, 0xdb, 0x16, 0x1e, 0xf4, 0x8c, 0x0d, 0x60, 0xef, 0x25, 0x03, 0x1b, 0x40, 0x14, 0x16, 0x78, 0x26, 0x24, 0x6a, 0xa5, 0x28, 0xa3, 0xa3, 0xe5, 0xb0, 0xab, 0x95, 0x07, 0x8d, 0x84, 0x01, 0xd9, 0x29, 0x03, 0x59, 0x5a, 0xfc, 0x1a, 0xa8, 0x54, 0xe6, 0x04, 0x4e, 0x5e, 0xb5, 0xf5, 0xbe } +, + /* Encryption */ + 128, + { 0x0e, 0x12, 0x16, 0x74, 0x89, 0xf0, 0xba, 0xef, 0xca, 0xd6, 0x39, 0x34, 0xbc, 0x15, 0x9f, 0x1b, 0xbd, 0x9e, 0x9b, 0x28, 0x7e, 0x50, 0x0f, 0x49, 0x09, 0x23, 0xc1, 0x6a, 0x85, 0x56, 0x4a, 0x1d, 0xa6, 0x36, 0x59, 0x37, 0x5f, 0x22, 0xaf, 0x7b, 0xa4, 0x97, 0x98, 0xe1, 0x57, 0x8c, 0xf3, 0x15, 0xfa, 0xe3, 0xe9, 0xed, 0x56, 0x99, 0xc6, 0x91, 0xe3, 0xc1, 0xd0, 0xbb, 0x46, 0xda, 0x49, 0x2d, 0x01, 0x34, 0x9e, 0x93, 0x29, 0x59, 0x3d, 0x43, 0x81, 0xd0, 0x74, 0xa0, 0xa5, 0x31, 0xdf, 0x92, 0x1b, 0x31, 0x31, 0x6f, 0x7e, 0x2b, 0x4f, 0xe9, 0x15, 0x34, 0x72, 0x83, 0x24, 0x23, 0x35, 0xf0, 0xb0, 0xb2, 0x31, 0x92, 0xc7, 0x21, 0x02, 0xf2, 0xc6, 0x36, 0x24, 0xb1, 0xe7, 0x89, 0x65, 0x45, 0x0e, 0x82, 0x30, 0xd4, 0x87, 0x7e, 0x46, 0x17, 0xb0, 0x3d, 0x44, 0x83, 0x13, 0x98, 0xdd, 0xbf } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.18", + /* Message */ + 8, + { 0x81, 0xb3, 0x4a, 0xeb, 0x8a, 0xfb, 0x8a, 0x3f } +, + /* Seed */ + 117, + { 0x02, 0xf7, 0x48, 0x34, 0x2d, 0x01, 0x0f, 0xb5, 0x6a, 0x6f, 0x69, 0xf2, 0x1f, 0x8c, 0x6a, 0x63, 0x16, 0x79, 0xc8, 0xc4, 0xb8, 0xf6, 0xfe, 0xb5, 0x25, 0xcf, 0x8e, 0x72, 0xfd, 0xa8, 0xef, 0x8d, 0xf6, 0x62, 0x31, 0x28, 0xc0, 0xfe, 0x74, 0xbc, 0x59, 0x0c, 0xaa, 0x34, 0xf1, 0xee, 0xd1, 0xad, 0x2d, 0x61, 0x42, 0xdc, 0xc5, 0xbc, 0xae, 0x84, 0xef, 0x31, 0x37, 0x62, 0xf2, 0xe4, 0xe7, 0x03, 0x03, 0xd2, 0x09, 0xc8, 0xd9, 0x57, 0x7a, 0x7c, 0x84, 0x3d, 0x2b, 0x91, 0x72, 0xed, 0x4e, 0xfe, 0x2a, 0xd6, 0x29, 0x61, 0x4b, 0x99, 0xa9, 0x1a, 0x4c, 0xc8, 0x32, 0x5b, 0xa3, 0x24, 0x11, 0x6e, 0xcf, 0x0c, 0x5e, 0x29, 0x09, 0x49, 0x38, 0xae, 0x49, 0x89, 0x84, 0xf4, 0xf4, 0xcb, 0xb1, 0x62, 0x38, 0x86, 0xe0, 0x39, 0x73 } +, + /* Encryption */ + 128, + { 0x43, 0xb2, 0x76, 0xc7, 0xd3, 0x68, 0xea, 0x21, 0xc6, 0x80, 0x71, 0x16, 0xcd, 0xe8, 0x60, 0x82, 0x98, 0xf2, 0x40, 0x02, 0x07, 0x2d, 0x77, 0x6e, 0x56, 0xe6, 0x2c, 0x35, 0x72, 0xbf, 0xb9, 0x9d, 0xa4, 0xc5, 0x6e, 0x93, 0x8a, 0x47, 0xdc, 0x07, 0x5f, 0xa1, 0xff, 0x7a, 0x61, 0x8f, 0xb5, 0xfa, 0xed, 0x3e, 0xe3, 0x7b, 0x91, 0xdf, 0xc3, 0x91, 0x53, 0x49, 0x5a, 0xeb, 0xa9, 0xdf, 0x6d, 0x45, 0xdf, 0x94, 0xb0, 0xe8, 0xa8, 0xad, 0x2d, 0xb3, 0x7a, 0x9f, 0xe4, 0x6d, 0x0f, 0xdf, 0x15, 0x42, 0x31, 0xfd, 0x6f, 0x32, 0x21, 0x47, 0x4e, 0x8f, 0x5c, 0x19, 0x1f, 0xdb, 0x85, 0x38, 0xe1, 0xa6, 0x03, 0xe5, 0x98, 0x97, 0xe1, 0x50, 0xfa, 0xf9, 0x5b, 0x65, 0xda, 0x14, 0x06, 0x67, 0xed, 0xb1, 0x98, 0x09, 0xeb, 0x4a, 0x16, 0xac, 0xd0, 0x1e, 0xcc, 0x60, 0x4b, 0xda, 0x57, 0xf2, 0x0e, 0xf2 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.19", + /* Message */ + 10, + { 0x7b, 0xf9, 0xfa, 0xd8, 0x89, 0xde, 0x73, 0xed, 0x87, 0x3d } +, + /* Seed */ + 115, + { 0xfa, 0x5d, 0xad, 0x45, 0xa4, 0xbb, 0x5e, 0x74, 0xc4, 0xcf, 0x2e, 0x21, 0x3e, 0xd4, 0x0a, 0xa9, 0x61, 0x75, 0x98, 0xd1, 0x1d, 0x49, 0xae, 0x1c, 0x32, 0xd7, 0x94, 0xe0, 0x9c, 0xd0, 0xe5, 0xc7, 0xaa, 0xae, 0x81, 0xb9, 0x55, 0x4d, 0xde, 0x31, 0x08, 0xd6, 0x0a, 0x9a, 0x82, 0xf4, 0x2c, 0xc6, 0xc2, 0xa6, 0x89, 0xf4, 0x60, 0xff, 0x1d, 0x53, 0xad, 0x85, 0xbf, 0x83, 0x83, 0x11, 0xe7, 0x58, 0x9e, 0x19, 0x67, 0x95, 0x7b, 0x51, 0x56, 0x7a, 0xa0, 0xd3, 0x3a, 0xfa, 0x37, 0x52, 0xcd, 0xe6, 0xc5, 0x66, 0x1d, 0x4f, 0x27, 0xae, 0xd3, 0xdf, 0x52, 0x90, 0x5f, 0x1c, 0xf2, 0x25, 0x33, 0x04, 0x61, 0x8e, 0x07, 0x86, 0x04, 0x1e, 0x70, 0xb4, 0xdc, 0xba, 0xc8, 0xc1, 0x08, 0xba, 0x34, 0xac, 0x39, 0x39, 0xf4 } +, + /* Encryption */ + 128, + { 0x61, 0xc2, 0x55, 0x0e, 0x0b, 0x36, 0xa6, 0x79, 0x7f, 0xf8, 0x64, 0x93, 0x80, 0x1b, 0x11, 0x46, 0xd8, 0x90, 0x59, 0x49, 0x83, 0x52, 0xe4, 0xc2, 0x62, 0x27, 0x5b, 0x14, 0x04, 0xb1, 0x33, 0x15, 0xe9, 0x56, 0xbb, 0x3d, 0x31, 0x21, 0x85, 0xb5, 0x21, 0xb3, 0xc7, 0x08, 0xe9, 0xd9, 0x54, 0x02, 0x17, 0x19, 0xa0, 0x59, 0xd9, 0x84, 0x72, 0x4c, 0x53, 0xc0, 0x4f, 0x5a, 0xd2, 0x74, 0xbe, 0xf9, 0xff, 0x0a, 0x79, 0x50, 0xb2, 0xfd, 0xec, 0xc5, 0x29, 0x0c, 0xd5, 0xf3, 0xbc, 0x26, 0x52, 0x4c, 0xd1, 0x34, 0x20, 0x48, 0x18, 0x4b, 0x0e, 0x2c, 0xdf, 0x94, 0x06, 0xa4, 0x53, 0xa2, 0xef, 0x9f, 0x3b, 0xb2, 0x3c, 0x4e, 0x7c, 0x1c, 0x8b, 0x29, 0x52, 0xa0, 0x20, 0x2b, 0xcc, 0x23, 0x82, 0x47, 0xea, 0x32, 0x7b, 0x8c, 0x07, 0x00, 0xc8, 0x00, 0x3f, 0xd6, 0x34, 0xec, 0x1e, 0xd9, 0xbf, 0x30 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 1.20", + /* Message */ + 31, + { 0xb6, 0xa3, 0x50, 0x9b, 0xb3, 0xb9, 0xb0, 0xb5, 0x7c, 0xd5, 0x8d, 0xe4, 0x09, 0xd9, 0x53, 0x20, 0x1a, 0x04, 0x2f, 0x94, 0x92, 0xdc, 0x1d, 0x7e, 0x34, 0xa7, 0xd0, 0x94, 0x1a, 0x1a, 0x1b } +, + /* Seed */ + 94, + { 0x3a, 0x9e, 0x15, 0x06, 0x57, 0x86, 0xb3, 0xe0, 0x1d, 0x82, 0x6b, 0x86, 0x2a, 0x8f, 0x70, 0x2b, 0x5c, 0xac, 0x8c, 0x16, 0x62, 0xee, 0x7d, 0x15, 0xff, 0x32, 0x3c, 0xdf, 0xe7, 0x1e, 0xbf, 0x4a, 0xd1, 0xb1, 0xf3, 0xa6, 0xbc, 0xbd, 0xd4, 0xb0, 0x01, 0x08, 0x77, 0xec, 0xac, 0x09, 0x1f, 0x61, 0x59, 0x08, 0xe2, 0xbe, 0x40, 0x0b, 0xb0, 0xc4, 0x98, 0xe3, 0x55, 0xd5, 0x71, 0xfd, 0x10, 0x89, 0x5b, 0x8e, 0xe9, 0xc3, 0xa9, 0xc3, 0x1e, 0x4b, 0x11, 0x03, 0x89, 0xc3, 0xd5, 0xc4, 0x6e, 0xbf, 0x76, 0xb3, 0xb3, 0x5a, 0xd1, 0xf4, 0x79, 0x1b, 0x6d, 0x20, 0x97, 0xf1, 0x09, 0xf2 } +, + /* Encryption */ + 128, + { 0x6b, 0x4b, 0x6d, 0x7b, 0xab, 0xfe, 0x4d, 0x64, 0x17, 0xac, 0xad, 0xfb, 0x78, 0x57, 0x2e, 0x7c, 0x87, 0xe3, 0xfe, 0x1b, 0xd5, 0x8e, 0xef, 0xb0, 0xd4, 0xb1, 0x27, 0x9c, 0x7b, 0x7c, 0x83, 0x26, 0xa6, 0x8b, 0xb2, 0x87, 0x95, 0xe0, 0x9f, 0x9b, 0x1c, 0xe2, 0xe2, 0x4a, 0x53, 0x9f, 0x4b, 0x0d, 0x93, 0xb2, 0x92, 0x74, 0xce, 0xcf, 0x7c, 0xd9, 0xf0, 0xb7, 0x32, 0xae, 0xbe, 0xda, 0x91, 0x11, 0xbd, 0xfe, 0x25, 0xe2, 0x68, 0xa8, 0x8e, 0x34, 0x22, 0xe2, 0x9b, 0x52, 0xbd, 0x4b, 0x7a, 0x05, 0x47, 0xdb, 0x8f, 0xe1, 0x2a, 0x6f, 0xcf, 0x1a, 0x3c, 0x06, 0xa0, 0x02, 0xbf, 0x87, 0x0a, 0x2f, 0xab, 0xb7, 0xc4, 0x57, 0xe4, 0xbb, 0xce, 0x3e, 0x31, 0x6f, 0x72, 0x32, 0x44, 0x9f, 0x87, 0xa9, 0xd7, 0x02, 0xb1, 0x2d, 0x19, 0xbd, 0xe7, 0xf9, 0x59, 0x0f, 0x94, 0x67, 0xb0, 0x6b, 0xd5, 0x8a } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 2: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0x98, 0xb7, 0x05, 0x82, 0xca, 0x80, 0x8f, 0xd1, 0xd3, 0x50, 0x95, 0x62, 0xa0, 0xef, 0x30, 0x5a, 0xf6, 0xd9, 0x87, 0x54, 0x43, 0xb3, 0x5b, 0xdf, 0x24, 0xd5, 0x36, 0x35, 0x3e, 0x3f, 0x12, 0x28, 0xdc, 0xd1, 0x2a, 0x78, 0x56, 0x83, 0x56, 0xc6, 0xff, 0x32, 0x3a, 0xbf, 0x72, 0xac, 0x1c, 0xdb, 0xfe, 0x71, 0x2f, 0xb4, 0x9f, 0xe5, 0x94, 0xa5, 0xa2, 0x17, 0x5d, 0x48, 0xb6, 0x73, 0x25, 0x38, 0xd8, 0xdf, 0x37, 0xcb, 0x97, 0x0b, 0xe4, 0xa5, 0xb5, 0x62, 0xc3, 0xf2, 0x98, 0xdb, 0x9d, 0xdf, 0x75, 0x60, 0x78, 0x77, 0x91, 0x8c, 0xce, 0xd1, 0xd0, 0xd1, 0xf3, 0x77, 0x33, 0x8c, 0x0d, 0x3d, 0x32, 0x07, 0x79, 0x7e, 0x86, 0x2c, 0x65, 0xd1, 0x14, 0x39, 0xe5, 0x88, 0x17, 0x75, 0x27, 0xa7, 0xde, 0xd9, 0x19, 0x71, 0xad, 0xcf, 0x91, 0xe2, 0xe8, 0x34, 0xe3, 0x7f, 0x05, 0xa7, 0x36, 0x55 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x06, 0x14, 0xa7, 0x86, 0x05, 0x2d, 0x28, 0x4c, 0xd9, 0x06, 0xa8, 0xe4, 0x13, 0xf7, 0x62, 0x2c, 0x05, 0x0f, 0x35, 0x49, 0xc0, 0x26, 0x58, 0x9e, 0xa2, 0x77, 0x50, 0xe0, 0xbe, 0xd9, 0x41, 0x0e, 0x5a, 0x78, 0x83, 0xa1, 0xe6, 0x03, 0xf5, 0xc5, 0x17, 0xad, 0x36, 0xd4, 0x9f, 0xaa, 0xc5, 0xbd, 0x66, 0xbc, 0xb8, 0x03, 0x0f, 0xa8, 0xd3, 0x09, 0xe3, 0x51, 0xdd, 0xd7, 0x82, 0xd8, 0x43, 0xdf, 0x97, 0x56, 0x80, 0xae, 0x73, 0xee, 0xa9, 0xaa, 0xb2, 0x89, 0xb7, 0x57, 0x20, 0x5d, 0xad, 0xb8, 0xfd, 0xfb, 0x98, 0x9e, 0xc8, 0xdb, 0x8e, 0x70, 0x95, 0xf5, 0x1f, 0x24, 0x52, 0x9f, 0x56, 0x37, 0xaa, 0x66, 0x93, 0x31, 0xe2, 0x56, 0x9f, 0x8b, 0x85, 0x4a, 0xbe, 0xce, 0xc9, 0x9a, 0xa2, 0x64, 0xc3, 0xda, 0x7c, 0xc6, 0x86, 0x6f, 0x0c, 0x0e, 0x1f, 0xb8, 0x46, 0x98, 0x48, 0x58, 0x1c, 0x73 } +, + /* Prime 1 */ + 64, + { 0xcb, 0x61, 0xa8, 0x8c, 0x8c, 0x30, 0x5a, 0xd9, 0xa8, 0xfb, 0xec, 0x2b, 0xa4, 0xc8, 0x6c, 0xcc, 0xc2, 0x02, 0x80, 0x24, 0xaa, 0x16, 0x90, 0xc2, 0x9b, 0xc8, 0x26, 0x4d, 0x2f, 0xeb, 0xe8, 0x7e, 0x4f, 0x86, 0xe9, 0x12, 0xef, 0x0f, 0x5c, 0x18, 0x53, 0xd7, 0x1c, 0xbc, 0x9b, 0x14, 0xba, 0xed, 0x3c, 0x37, 0xce, 0xf6, 0xc7, 0xa3, 0x59, 0x8b, 0x6f, 0xbe, 0x06, 0x48, 0x10, 0x90, 0x5b, 0x57 } +, + /* Prime 2 */ + 64, + { 0xc0, 0x39, 0x9f, 0x0b, 0x93, 0x80, 0xfa, 0xba, 0x38, 0xff, 0x80, 0xd2, 0xff, 0xf6, 0xed, 0xe7, 0x9c, 0xfd, 0xab, 0xf6, 0x58, 0x97, 0x20, 0x77, 0xa5, 0xe2, 0xb2, 0x95, 0x69, 0x3e, 0xa5, 0x10, 0x72, 0x26, 0x8b, 0x91, 0x74, 0x6e, 0xea, 0x9b, 0xe0, 0x4a, 0xd6, 0x61, 0x00, 0xeb, 0xed, 0x73, 0x3d, 0xb4, 0xcd, 0x01, 0x47, 0xa1, 0x8d, 0x6d, 0xe8, 0xc0, 0xcd, 0x8f, 0xbf, 0x24, 0x9c, 0x33 } +, + /* Prime exponent 1 */ + 64, + { 0x94, 0x4c, 0x3a, 0x65, 0x79, 0x57, 0x4c, 0xf7, 0x87, 0x33, 0x62, 0xab, 0x14, 0x35, 0x9c, 0xb7, 0xd5, 0x03, 0x93, 0xc2, 0xa8, 0x4f, 0x59, 0xf0, 0xbd, 0x3c, 0xbd, 0x48, 0xed, 0x17, 0x7c, 0x68, 0x95, 0xbe, 0x8e, 0xb6, 0xe2, 0x9f, 0xf5, 0x8c, 0x3b, 0x9e, 0x0f, 0xf3, 0x2a, 0xb5, 0x7b, 0xf3, 0xbe, 0x44, 0x07, 0x62, 0x84, 0x81, 0x84, 0xaa, 0x9a, 0xa9, 0x19, 0xd5, 0x74, 0x56, 0x7e, 0x73 } +, + /* Prime exponent 2 */ + 64, + { 0x45, 0xeb, 0xef, 0xd5, 0x87, 0x27, 0x30, 0x8c, 0xd2, 0xb4, 0xe6, 0x08, 0x5a, 0x81, 0x58, 0xd2, 0x9a, 0x41, 0x8f, 0xee, 0xc1, 0x14, 0xe0, 0x03, 0x85, 0xbc, 0xeb, 0x96, 0xfb, 0xbc, 0x84, 0xd0, 0x71, 0xa5, 0x61, 0xb9, 0x5c, 0x30, 0x08, 0x79, 0x00, 0xe2, 0x58, 0x0e, 0xdb, 0x05, 0xf6, 0xce, 0xa7, 0x90, 0x7f, 0xcd, 0xca, 0x5f, 0x92, 0x91, 0x7b, 0x4b, 0xbe, 0xba, 0x5e, 0x1e, 0x14, 0x0f } +, + /* Coefficient */ + 64, + { 0xc5, 0x24, 0x68, 0xc8, 0xfd, 0x15, 0xe5, 0xda, 0x2f, 0x6c, 0x8e, 0xba, 0x4e, 0x97, 0xba, 0xeb, 0xe9, 0x95, 0xb6, 0x7a, 0x1a, 0x7a, 0xd7, 0x19, 0xdd, 0x9f, 0xff, 0x36, 0x6b, 0x18, 0x4d, 0x5a, 0xb4, 0x55, 0x07, 0x59, 0x09, 0x29, 0x20, 0x44, 0xec, 0xb3, 0x45, 0xcf, 0x2c, 0xdd, 0x26, 0x22, 0x8e, 0x21, 0xf8, 0x51, 0x83, 0x25, 0x5f, 0x4a, 0x9e, 0x69, 0xf4, 0xc7, 0x15, 0x2e, 0xbb, 0x0f } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 2.1", + /* Message */ + 17, + { 0xe9, 0xa7, 0x71, 0xe0, 0xa6, 0x5f, 0x28, 0x70, 0x8e, 0x83, 0xd5, 0xe6, 0xcc, 0x89, 0x8a, 0x41, 0xd7 } +, + /* Seed */ + 108, + { 0x16, 0x8e, 0x3e, 0xb5, 0x80, 0x9b, 0x08, 0x70, 0xe1, 0xf2, 0x48, 0x7e, 0x1b, 0xe7, 0x7a, 0x17, 0x6b, 0x34, 0x71, 0x6d, 0xe1, 0x41, 0xba, 0x4c, 0x90, 0x59, 0xda, 0x90, 0xe5, 0xe5, 0x1a, 0x36, 0x94, 0xe8, 0x58, 0xfe, 0xd1, 0x0b, 0x92, 0x6c, 0x02, 0x52, 0x39, 0x80, 0xa8, 0x90, 0x9d, 0xa9, 0x96, 0xc6, 0x43, 0x33, 0xea, 0x67, 0x67, 0x87, 0xbc, 0xe6, 0x77, 0xf1, 0x1f, 0xda, 0x77, 0xdb, 0xb1, 0xa9, 0x51, 0x6e, 0xdd, 0xa9, 0xb1, 0x29, 0x4f, 0xc2, 0xe4, 0x50, 0x52, 0x22, 0x88, 0xe9, 0x30, 0xbe, 0x7f, 0xa7, 0x29, 0xb2, 0x50, 0xe3, 0xaa, 0xc5, 0x20, 0x51, 0x1e, 0x95, 0x16, 0xaa, 0x86, 0x3a, 0xf6, 0xbc, 0x07, 0x5c, 0xbd, 0xbf, 0xf4, 0x30, 0x46, 0x70 } +, + /* Encryption */ + 128, + { 0x71, 0xc2, 0xb8, 0xfb, 0x38, 0x19, 0xf1, 0x34, 0xc2, 0x24, 0x7c, 0x6b, 0xab, 0xb4, 0xcf, 0xbe, 0x17, 0xd7, 0xb2, 0x64, 0x3f, 0x87, 0xac, 0xe5, 0xc5, 0x71, 0x27, 0x7b, 0xe1, 0x90, 0x8e, 0xf3, 0xa5, 0x28, 0x8e, 0x34, 0x38, 0x4e, 0x46, 0x0a, 0x70, 0x38, 0x6e, 0x7e, 0xa1, 0xd1, 0x9d, 0x3d, 0xca, 0x1c, 0xe1, 0x5b, 0xa9, 0x32, 0x39, 0xa8, 0xcd, 0xda, 0x18, 0xe3, 0x17, 0xfe, 0x07, 0x96, 0x80, 0xce, 0x7e, 0x6a, 0xc6, 0xd9, 0xbd, 0xaf, 0x86, 0xcb, 0x9a, 0xeb, 0xf1, 0xcf, 0x46, 0xcd, 0x10, 0xef, 0x6a, 0x68, 0x8b, 0x0c, 0xb2, 0xce, 0x76, 0x5d, 0xd0, 0xb3, 0x25, 0x20, 0x42, 0x39, 0x66, 0xee, 0xe1, 0xaa, 0x05, 0xc6, 0xc2, 0x8c, 0x6f, 0x35, 0x24, 0xfb, 0x68, 0x6b, 0x5f, 0xb1, 0x58, 0x53, 0x65, 0x9e, 0x58, 0x3a, 0xc4, 0x37, 0x21, 0x9d, 0xef, 0x8e, 0xdc, 0x58, 0xbe, 0x2d } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 2.2", + /* Message */ + 47, + { 0x66, 0x4b, 0xf0, 0x5d, 0x61, 0x2b, 0xaf, 0x61, 0x52, 0x4c, 0x60, 0x8e, 0xda, 0x36, 0xfc, 0x6e, 0xa2, 0xc9, 0x3c, 0x14, 0x31, 0x53, 0x22, 0x1b, 0xcf, 0xd6, 0xba, 0x0c, 0xfb, 0xbd, 0x6b, 0x64, 0x14, 0x47, 0xe4, 0x78, 0x8b, 0x0a, 0x46, 0x2c, 0xb5, 0xb3, 0xf9, 0xfa, 0xfc, 0x9a, 0x75 } +, + /* Seed */ + 78, + { 0xe7, 0xf0, 0xa2, 0x79, 0x18, 0xca, 0xd9, 0x15, 0xda, 0x28, 0x11, 0x36, 0x59, 0xff, 0xb5, 0xdf, 0xa0, 0xb5, 0x1b, 0x24, 0xd5, 0xa7, 0x1c, 0x20, 0x27, 0xf8, 0xe4, 0xd9, 0x40, 0x9e, 0x8c, 0x64, 0x72, 0xf0, 0xc5, 0x4b, 0x5c, 0x08, 0x85, 0x8d, 0xa6, 0x3d, 0x4b, 0x81, 0x72, 0xb0, 0x7d, 0xcf, 0x8c, 0x5a, 0x7e, 0x8f, 0x9e, 0x90, 0xf0, 0x17, 0xc2, 0x4b, 0x44, 0xd1, 0x6b, 0x67, 0x0b, 0xdc, 0x96, 0x03, 0x0c, 0x83, 0x53, 0xa2, 0x83, 0x9b, 0xa4, 0xc0, 0x75, 0xd2, 0x4c, 0x20 } +, + /* Encryption */ + 128, + { 0x06, 0x86, 0x90, 0x18, 0x13, 0xdb, 0x05, 0x3a, 0xc7, 0x08, 0xe3, 0xfc, 0xec, 0x6b, 0xae, 0x03, 0x60, 0x08, 0x8f, 0xd3, 0x44, 0xe9, 0xd7, 0xea, 0x11, 0x8b, 0xb3, 0xf5, 0x37, 0x53, 0x14, 0x25, 0x1e, 0x60, 0x67, 0x37, 0xf5, 0x82, 0x4b, 0x36, 0x28, 0xf6, 0x65, 0x03, 0x48, 0xf6, 0xab, 0x55, 0x3b, 0x27, 0x7d, 0xa0, 0x15, 0x44, 0xd0, 0x56, 0x73, 0xba, 0xed, 0xf4, 0x55, 0xcc, 0x03, 0x32, 0xf6, 0x13, 0xf6, 0x54, 0x78, 0xfc, 0xfe, 0x06, 0x67, 0x34, 0xc4, 0x65, 0x58, 0xbc, 0x23, 0x3b, 0x4b, 0x6f, 0x52, 0x41, 0xe4, 0xf4, 0xac, 0x53, 0xfc, 0x18, 0xc5, 0x53, 0x84, 0xc8, 0xfd, 0x96, 0x18, 0x3f, 0x0b, 0xb5, 0x51, 0x5e, 0x89, 0x31, 0x14, 0xf9, 0xc6, 0x1c, 0xcc, 0x11, 0xfc, 0x19, 0x83, 0xde, 0x74, 0x46, 0x92, 0x64, 0xdb, 0xdb, 0xb0, 0xc7, 0x49, 0x17, 0x4e, 0xcd, 0xfb, 0xe3 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.3", + /* Message */ + 52, + { 0x5e, 0x76, 0xe6, 0x6e, 0xd5, 0x75, 0x41, 0xfc, 0x23, 0xd3, 0x59, 0xf4, 0xad, 0xbf, 0x3f, 0x56, 0x82, 0x01, 0xd3, 0xc6, 0xf0, 0xe0, 0x26, 0xaa, 0xa5, 0x67, 0x63, 0x56, 0xcc, 0x98, 0x66, 0xf1, 0x75, 0x5d, 0xe9, 0x8c, 0xb3, 0x9f, 0x23, 0x6d, 0xaf, 0xa9, 0xe6, 0xbc, 0x79, 0x4b, 0x74, 0x43, 0xb5, 0x3a, 0x2d, 0x85 } +, + /* Seed */ + 73, + { 0x5c, 0x65, 0x68, 0xb6, 0xe3, 0x3b, 0xc1, 0x3a, 0xd2, 0xdc, 0xd6, 0x01, 0x2d, 0x17, 0xda, 0x81, 0xb1, 0x3d, 0xbd, 0x62, 0xaa, 0xe4, 0x0a, 0x64, 0xaf, 0x97, 0xe2, 0x19, 0xe7, 0x5d, 0xc1, 0x81, 0x12, 0x60, 0x77, 0xd1, 0x20, 0xdd, 0xa1, 0x9d, 0x63, 0x12, 0xcf, 0x1e, 0x98, 0x71, 0xc1, 0x15, 0xf0, 0x86, 0x7f, 0xe6, 0x62, 0xd7, 0x8a, 0x40, 0x31, 0x97, 0x6b, 0xdd, 0xef, 0x68, 0xf5, 0x2b, 0x68, 0x99, 0x58, 0x67, 0xcd, 0x80, 0x95, 0x05, 0xdd } +, + /* Encryption */ + 128, + { 0x19, 0xe7, 0x99, 0x66, 0xff, 0x1f, 0xbc, 0x10, 0x07, 0x3d, 0xe7, 0x3d, 0xf3, 0xa5, 0x31, 0x63, 0x78, 0x74, 0xe4, 0x7d, 0xf6, 0x39, 0x25, 0x6c, 0x51, 0xd0, 0xbb, 0xa9, 0x35, 0x61, 0x0b, 0x46, 0x34, 0xf9, 0xe5, 0xb4, 0x68, 0x9b, 0xd9, 0x21, 0x73, 0x5b, 0x32, 0x23, 0x6e, 0xfc, 0xc6, 0xe7, 0xcc, 0x49, 0xa9, 0xe0, 0x6a, 0x25, 0xac, 0x96, 0x59, 0xb7, 0xfe, 0x82, 0x9c, 0xb3, 0xe8, 0xb0, 0x1f, 0x10, 0x31, 0x79, 0x42, 0x23, 0x65, 0x74, 0x1b, 0x76, 0xc8, 0x34, 0x21, 0x49, 0xce, 0xdc, 0x76, 0xeb, 0x0a, 0xd0, 0x18, 0xed, 0x42, 0x35, 0xfb, 0xd5, 0x24, 0xfd, 0x87, 0xc9, 0x54, 0x9a, 0xb3, 0x3f, 0xf2, 0x3e, 0xe4, 0xf8, 0x20, 0x0e, 0xfa, 0x33, 0x02, 0x7e, 0x9d, 0xee, 0xc6, 0x0f, 0xac, 0x01, 0x3d, 0x1e, 0x56, 0xe6, 0xe3, 0x33, 0xd4, 0x93, 0xa4, 0xa9, 0x46, 0x0f, 0xe5, 0x8a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.4", + /* Message */ + 9, + { 0x5b, 0x19, 0x50, 0x48, 0xeb, 0x90, 0xeb, 0x47, 0x93 } +, + /* Seed */ + 116, + { 0xbb, 0xbd, 0x49, 0x55, 0x0e, 0xd1, 0xea, 0x1b, 0x6b, 0xc7, 0x20, 0x6c, 0xe0, 0xb0, 0x03, 0xa6, 0x32, 0xa5, 0x2b, 0x0b, 0xac, 0x5f, 0x32, 0x71, 0x0b, 0x39, 0xfa, 0x64, 0xb3, 0x55, 0x6a, 0xd6, 0xf6, 0xc8, 0x2b, 0xd9, 0xd5, 0x31, 0xb3, 0x07, 0x46, 0x9e, 0x86, 0x3f, 0x54, 0xb5, 0xfe, 0x21, 0x83, 0x05, 0x69, 0x54, 0xf2, 0xa9, 0x67, 0xe4, 0xdc, 0x2b, 0x32, 0x6e, 0x41, 0xdd, 0xdf, 0x74, 0x3a, 0x76, 0x4f, 0x7e, 0x82, 0x88, 0x68, 0x29, 0xa8, 0xfa, 0xb2, 0x77, 0x2a, 0x34, 0x97, 0x70, 0x6b, 0x95, 0x38, 0xa9, 0xf8, 0x42, 0x96, 0xc8, 0x2d, 0x9b, 0xaf, 0xc2, 0x9c, 0x39, 0xd4, 0x68, 0x4f, 0x75, 0xff, 0x6b, 0xb1, 0xc1, 0x2e, 0x39, 0xbb, 0x80, 0x56, 0xaf, 0x2d, 0x24, 0x34, 0x4b, 0x2c, 0xae, 0x46, 0x29 } +, + /* Encryption */ + 128, + { 0x42, 0xc9, 0xcb, 0x68, 0x21, 0xb5, 0x5d, 0xae, 0x30, 0xd9, 0x00, 0x25, 0x75, 0x31, 0x12, 0xe6, 0xee, 0x02, 0xf4, 0xad, 0x6f, 0x0f, 0x5b, 0x3c, 0xc4, 0x95, 0x2a, 0x12, 0x7c, 0x8a, 0x16, 0xf6, 0x64, 0x79, 0xb8, 0x14, 0x4f, 0x3c, 0xf2, 0x9d, 0x84, 0xe4, 0x3d, 0x67, 0xd6, 0x77, 0x12, 0xc7, 0xf5, 0xb7, 0x6d, 0xa2, 0xc6, 0x6b, 0xa0, 0xe9, 0x0c, 0xd4, 0xb1, 0xfc, 0x1c, 0x1b, 0x3f, 0x17, 0xa3, 0x92, 0xe7, 0x04, 0x08, 0x28, 0x8a, 0xf6, 0x9b, 0x50, 0xfe, 0x8a, 0x50, 0xb3, 0x29, 0x6a, 0x0d, 0xab, 0xd7, 0xc8, 0xdc, 0x39, 0x84, 0xa1, 0x94, 0x06, 0x88, 0xbe, 0x70, 0x98, 0x25, 0x16, 0x20, 0x25, 0x6c, 0xc2, 0x1b, 0x7c, 0x76, 0xed, 0x29, 0xd8, 0x6f, 0xf7, 0xc0, 0x1e, 0xc2, 0x87, 0xdf, 0x47, 0x38, 0xbe, 0x34, 0x69, 0xb3, 0x0a, 0x3f, 0x8f, 0xb7, 0xbe, 0x83, 0xd9, 0x36, 0x1a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.5", + /* Message */ + 61, + { 0x66, 0x0b, 0xbd, 0x40, 0x06, 0x9c, 0xc6, 0x7b, 0xad, 0xe4, 0x1a, 0x09, 0xec, 0xf4, 0x3c, 0xc4, 0x51, 0x3f, 0x7c, 0x7c, 0xc0, 0x2d, 0xde, 0x97, 0x2d, 0x2b, 0x1f, 0x29, 0x29, 0x5e, 0x09, 0xb9, 0x91, 0x0c, 0x59, 0xed, 0xba, 0x0e, 0xd2, 0xdd, 0xf1, 0x1a, 0x6d, 0x41, 0x69, 0x35, 0x1f, 0x97, 0x24, 0x07, 0x33, 0x52, 0x8f, 0x91, 0xb2, 0x68, 0xfa, 0xa7, 0xaf, 0x90, 0x6e } +, + /* Seed */ + 64, + { 0x30, 0x7f, 0x61, 0xb1, 0x83, 0xa8, 0xdc, 0xf9, 0x15, 0x5a, 0xb2, 0x35, 0xe6, 0x1f, 0xb5, 0x6b, 0xa2, 0xb8, 0x79, 0x5d, 0xc4, 0x23, 0x53, 0x85, 0xe8, 0xac, 0xf3, 0x66, 0xd2, 0x52, 0x33, 0xb4, 0x70, 0xe0, 0x5d, 0x70, 0x11, 0xb6, 0xfc, 0x53, 0x2f, 0x0a, 0x65, 0x8a, 0xd1, 0x3a, 0xfd, 0x29, 0x0c, 0x6f, 0x30, 0xe2, 0x79, 0x5e, 0xe3, 0xd3, 0x9d, 0xbd, 0xc8, 0x0f, 0x56, 0x0e, 0xce, 0x2f } +, + /* Encryption */ + 128, + { 0x04, 0x9b, 0x26, 0x05, 0x0a, 0x3a, 0xbe, 0xf8, 0x3e, 0xc2, 0x77, 0x61, 0x11, 0xe3, 0xb7, 0x2f, 0xb9, 0xa2, 0xd6, 0xa8, 0x01, 0x05, 0x5d, 0x6b, 0x5e, 0x0d, 0xa4, 0xe9, 0x5c, 0xcf, 0x2e, 0xbd, 0x0a, 0x78, 0x6a, 0x97, 0x21, 0xaa, 0x79, 0x25, 0xbf, 0x15, 0xbe, 0xb6, 0x27, 0x13, 0xa3, 0x13, 0x87, 0x7d, 0xd8, 0x5d, 0x26, 0x58, 0xb2, 0x08, 0xe8, 0x8e, 0x64, 0x45, 0xfc, 0x35, 0x01, 0x9b, 0x0c, 0xad, 0x6b, 0xf4, 0xd0, 0x6e, 0x2c, 0xa5, 0xf1, 0x19, 0x49, 0xee, 0xee, 0x7e, 0xe4, 0x7f, 0x1d, 0x5b, 0x4c, 0x88, 0x24, 0x1f, 0x50, 0xe4, 0xd6, 0xed, 0xf0, 0x18, 0x3d, 0x4f, 0xa3, 0x5a, 0x37, 0x1f, 0xc4, 0x07, 0x36, 0x4f, 0x2d, 0xca, 0xa4, 0xcd, 0xae, 0xce, 0xfc, 0xea, 0x6d, 0xfa, 0xc1, 0xd5, 0x13, 0xf9, 0x05, 0xe7, 0x47, 0x94, 0x47, 0x44, 0xbb, 0x64, 0x57, 0x6b, 0xa1, 0xc8 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.6", + /* Message */ + 11, + { 0x81, 0xcb, 0x0a, 0x97, 0x69, 0x8f, 0x82, 0x3b, 0x56, 0xb4, 0x5f } +, + /* Seed */ + 114, + { 0x93, 0x8c, 0x8d, 0xfd, 0xa0, 0x8b, 0x89, 0x05, 0x5b, 0x68, 0xaf, 0x01, 0x1f, 0x24, 0x6c, 0xec, 0x1f, 0x93, 0xa2, 0x77, 0x1d, 0xa9, 0x7d, 0xba, 0x20, 0x95, 0x4c, 0x90, 0x09, 0x12, 0x28, 0x5e, 0x5d, 0xb1, 0x87, 0xb2, 0x9e, 0x32, 0x72, 0xe9, 0x9e, 0x69, 0x4e, 0x12, 0x14, 0x17, 0x25, 0x28, 0x45, 0x30, 0x84, 0x06, 0x4e, 0x5c, 0x60, 0xf0, 0x1e, 0x78, 0x6f, 0xc5, 0xd0, 0xd9, 0xaf, 0x06, 0x39, 0xa4, 0x98, 0xc5, 0x7a, 0xde, 0x93, 0x77, 0x60, 0xae, 0x51, 0x74, 0x84, 0xaf, 0xd7, 0x02, 0x5e, 0xa0, 0xd5, 0x5a, 0x62, 0xb1, 0x1f, 0x9a, 0xab, 0x7f, 0xa5, 0xdd, 0xd0, 0x93, 0xe5, 0xea, 0xba, 0xd6, 0x1b, 0x67, 0xa2, 0x95, 0xa7, 0x75, 0xbe, 0x96, 0xc6, 0xb7, 0x6e, 0xc3, 0xfe, 0x47, 0x29, 0x50 } +, + /* Encryption */ + 128, + { 0x7f, 0xb8, 0xf3, 0x35, 0xee, 0xdc, 0x4a, 0xf6, 0xaf, 0x44, 0x07, 0x3d, 0xa1, 0x96, 0x45, 0x7d, 0x04, 0x61, 0x45, 0x03, 0x01, 0x47, 0xf8, 0x42, 0x0f, 0xc7, 0x9b, 0xd5, 0x89, 0x77, 0x4a, 0x73, 0x0a, 0x6d, 0x94, 0xfb, 0x7e, 0xfa, 0xdc, 0x5a, 0xee, 0xa7, 0xc0, 0x70, 0xf1, 0x89, 0x24, 0x91, 0x25, 0xe1, 0x66, 0xc6, 0xd3, 0x01, 0x29, 0xec, 0xf2, 0xc4, 0x82, 0x2a, 0x50, 0x49, 0x6b, 0xc2, 0xf2, 0x1e, 0x79, 0xac, 0x57, 0xdb, 0xfb, 0xdd, 0x71, 0xa6, 0x8b, 0x58, 0xd9, 0x05, 0x1b, 0x48, 0x0b, 0xf4, 0x77, 0x48, 0xa1, 0x3d, 0xfb, 0x67, 0x3e, 0xae, 0xd7, 0x71, 0x0a, 0x46, 0x8f, 0xe7, 0x2f, 0x7d, 0x74, 0xe6, 0xf4, 0xa2, 0x89, 0x44, 0x04, 0x3a, 0x52, 0xd9, 0x30, 0xde, 0x68, 0xdb, 0xcb, 0x6e, 0xe7, 0xfb, 0x8b, 0x69, 0x64, 0x05, 0x41, 0xe3, 0xed, 0x5b, 0x75, 0x4e, 0x65, 0xfe } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.7", + /* Message */ + 45, + { 0x05, 0xf7, 0x83, 0x56, 0x23, 0xc8, 0xcf, 0xaa, 0xe4, 0x82, 0xa9, 0x10, 0x85, 0xb9, 0x7f, 0x6b, 0x95, 0x92, 0x8b, 0xb9, 0x74, 0xac, 0xad, 0x02, 0x36, 0x4a, 0xaf, 0x13, 0x17, 0xed, 0x53, 0xc9, 0xdb, 0x2f, 0xfb, 0xc8, 0xa3, 0xcb, 0x3a, 0x00, 0xf4, 0x4d, 0xac, 0xef, 0x78 } +, + /* Seed */ + 80, + { 0x80, 0xc8, 0x3d, 0x25, 0x47, 0xbe, 0x41, 0xba, 0xf2, 0x32, 0x1b, 0xd3, 0x0a, 0x9a, 0xb7, 0x74, 0x9c, 0x5e, 0xeb, 0xb5, 0xa1, 0xff, 0xf0, 0xb3, 0x1d, 0x6b, 0xdb, 0x0a, 0xd1, 0x6d, 0xd0, 0xc0, 0xfb, 0x3e, 0xc1, 0x57, 0xe7, 0x8b, 0x09, 0x86, 0x60, 0x20, 0x41, 0xcd, 0xe8, 0x89, 0x57, 0xa5, 0x53, 0x29, 0xe3, 0xe2, 0xcf, 0xe8, 0x5a, 0x59, 0x44, 0x74, 0x94, 0x5e, 0xfa, 0x33, 0x35, 0x85, 0xff, 0xfd, 0x41, 0xeb, 0xb8, 0xe7, 0xc5, 0x18, 0xc3, 0xc9, 0x25, 0x9a, 0xea, 0x8d, 0xe6, 0x35 } +, + /* Encryption */ + 128, + { 0x87, 0xf9, 0xce, 0x05, 0xf0, 0xac, 0x9c, 0x05, 0xe4, 0x5f, 0xb7, 0xbb, 0x55, 0x5a, 0x7a, 0x18, 0xa9, 0xcd, 0xc5, 0x5f, 0x54, 0x4a, 0x54, 0x21, 0x01, 0xe9, 0xa7, 0x1c, 0xd2, 0x03, 0x66, 0x82, 0x0e, 0x7f, 0xf6, 0xdc, 0xa3, 0x46, 0x75, 0x22, 0x9d, 0x86, 0xe4, 0xfb, 0x58, 0x71, 0xf9, 0x31, 0x0b, 0x12, 0xbb, 0x74, 0xe2, 0x86, 0x18, 0xd6, 0xd6, 0x58, 0x65, 0x87, 0xf6, 0x6a, 0xcc, 0x89, 0x68, 0xa8, 0x3c, 0xd8, 0x07, 0xf4, 0xd2, 0x12, 0x97, 0x73, 0x1d, 0x7c, 0x22, 0xc1, 0x45, 0x99, 0xe7, 0x57, 0x19, 0xfd, 0x23, 0x05, 0x2b, 0x8a, 0xa6, 0x5b, 0x7e, 0x9c, 0x5c, 0x02, 0x00, 0x38, 0x2d, 0x35, 0xd5, 0x60, 0xf2, 0xd3, 0x3d, 0xd0, 0x49, 0xe0, 0x6a, 0xc8, 0x27, 0xcb, 0xdd, 0x9a, 0xf5, 0x81, 0xa6, 0xb2, 0x6d, 0xb6, 0x1d, 0x43, 0xd7, 0x12, 0x4b, 0x34, 0x72, 0x1d, 0xf1, 0x42 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.8", + /* Message */ + 59, + { 0xe2, 0xe0, 0xf6, 0xb3, 0x28, 0xd9, 0xbb, 0xe9, 0xfd, 0x66, 0xcd, 0x87, 0x98, 0x7c, 0x11, 0x60, 0xed, 0x23, 0x7b, 0x1c, 0x7c, 0x65, 0x6a, 0x89, 0xfb, 0x1f, 0x21, 0xd7, 0x09, 0x40, 0x3b, 0x04, 0x10, 0xf8, 0xe4, 0xe1, 0x2e, 0xb9, 0x69, 0x0a, 0xeb, 0xeb, 0x38, 0x07, 0x31, 0x9a, 0x93, 0x65, 0x64, 0xf6, 0x67, 0x17, 0xa7, 0x1c, 0x48, 0x62, 0xcc, 0xc5, 0x6e } +, + /* Seed */ + 66, + { 0xcf, 0x18, 0xe6, 0x08, 0xb1, 0x56, 0x14, 0x5c, 0x44, 0xde, 0x31, 0x49, 0x66, 0xcb, 0xcc, 0x66, 0x74, 0xa4, 0x5a, 0xe0, 0xdf, 0x90, 0x04, 0x06, 0xe4, 0x0d, 0x3d, 0xfc, 0x32, 0x2f, 0x39, 0x40, 0x4c, 0xee, 0xb6, 0xdc, 0x58, 0xf8, 0x01, 0xbb, 0xf2, 0xac, 0x4f, 0x47, 0x84, 0x1a, 0xbd, 0x79, 0x61, 0x79, 0xd0, 0x82, 0x4f, 0x3b, 0xf5, 0x51, 0x8d, 0x78, 0xcc, 0x66, 0xad, 0x8d, 0xfb, 0xed, 0xb1, 0x17 } +, + /* Encryption */ + 128, + { 0x14, 0x01, 0xaa, 0x21, 0xec, 0x6e, 0xba, 0xa7, 0xe3, 0xa9, 0xf7, 0x13, 0xc8, 0x6b, 0x50, 0x8e, 0x37, 0x5f, 0x6c, 0x12, 0x5b, 0x29, 0x62, 0x6e, 0xbd, 0x34, 0x9f, 0x64, 0xe2, 0x0f, 0xa4, 0x8a, 0x1b, 0x06, 0x84, 0x79, 0xff, 0xf3, 0x30, 0x22, 0xf6, 0x6f, 0x86, 0xe9, 0x7d, 0x9c, 0x5e, 0xdd, 0x90, 0x26, 0xe3, 0x18, 0x3c, 0xe0, 0x86, 0x41, 0x57, 0x06, 0x59, 0x35, 0x2f, 0x87, 0xa6, 0x18, 0x91, 0xf3, 0xd8, 0x6a, 0x3d, 0x24, 0x5f, 0x02, 0x45, 0xe3, 0x9d, 0x99, 0x89, 0x2c, 0x67, 0xfa, 0x2b, 0xed, 0x8e, 0x37, 0x54, 0x8d, 0xe2, 0x3d, 0xef, 0xdd, 0x1e, 0x43, 0xd5, 0xd7, 0xe3, 0xd9, 0xa3, 0xc2, 0x2c, 0xe6, 0xa3, 0x68, 0xd8, 0x4c, 0x5a, 0xfa, 0x1c, 0xc5, 0xbf, 0x49, 0xb6, 0x8f, 0xe5, 0xc2, 0x5a, 0x32, 0x6b, 0x0e, 0xec, 0x5e, 0x44, 0xc5, 0xe2, 0xff, 0x5a, 0x35, 0x9d, 0xd1 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.9", + /* Message */ + 17, + { 0xc6, 0x95, 0x78, 0xea, 0x03, 0xe2, 0x69, 0xb1, 0xb9, 0x16, 0x33, 0xa7, 0x2f, 0x9f, 0xb4, 0xd1, 0x0c } +, + /* Seed */ + 108, + { 0xe0, 0xa1, 0xa9, 0xba, 0xe3, 0x0a, 0x7a, 0xc6, 0x6c, 0xab, 0x3d, 0x86, 0x43, 0x3c, 0x1c, 0xa5, 0xe8, 0xac, 0x2b, 0x74, 0xe4, 0x83, 0xca, 0x7f, 0x34, 0x59, 0x77, 0x16, 0xee, 0x16, 0x18, 0x90, 0x6c, 0x97, 0x77, 0x2f, 0x28, 0x86, 0xf4, 0x6d, 0x78, 0x31, 0x21, 0xb7, 0xfe, 0x1b, 0x8f, 0xa5, 0xfb, 0xec, 0x09, 0xc0, 0x68, 0xe5, 0x63, 0x5c, 0x89, 0xe6, 0xa0, 0xa9, 0xac, 0xcf, 0x2b, 0x12, 0xc6, 0x47, 0x06, 0xb6, 0xae, 0x9a, 0x5a, 0x74, 0xab, 0xb8, 0x3f, 0x64, 0xe1, 0x3a, 0x8c, 0x53, 0xf9, 0x26, 0x76, 0x04, 0x66, 0xb6, 0x45, 0xe2, 0x8e, 0x9a, 0xd6, 0x46, 0x1a, 0xe7, 0xb8, 0x9d, 0x5e, 0xfc, 0xcf, 0x7d, 0x89, 0x14, 0x9a, 0xa2, 0xe6, 0x9f, 0x0d, 0x25 } +, + /* Encryption */ + 128, + { 0x78, 0xf8, 0x7d, 0x6b, 0x06, 0x76, 0x1b, 0xd7, 0xe7, 0x17, 0xe0, 0xc5, 0xeb, 0x40, 0xe1, 0xfb, 0x80, 0x89, 0x9c, 0x7b, 0xe4, 0x01, 0x7c, 0x2e, 0xfb, 0x07, 0x59, 0x78, 0xee, 0x38, 0xd0, 0xf9, 0x5e, 0x98, 0x03, 0xdc, 0xd4, 0x0f, 0xee, 0x97, 0x92, 0xc6, 0x1d, 0x4a, 0x2d, 0x85, 0xda, 0xbd, 0xea, 0x96, 0xca, 0x29, 0xf3, 0xca, 0x1e, 0x8b, 0xcf, 0x81, 0x76, 0x55, 0xd0, 0xc0, 0x94, 0x74, 0xd9, 0x80, 0x94, 0xeb, 0x6a, 0x7e, 0xf0, 0x33, 0x3d, 0x69, 0x71, 0xc9, 0x38, 0x36, 0xfe, 0x02, 0x32, 0xf7, 0x18, 0x46, 0x3d, 0xc9, 0x54, 0x18, 0x53, 0x46, 0x3b, 0xc1, 0xcf, 0x03, 0x67, 0x7e, 0x78, 0x6e, 0xe5, 0x2e, 0x72, 0x71, 0xc3, 0xc1, 0x1a, 0xc0, 0x05, 0x53, 0xc6, 0x75, 0x27, 0x07, 0xe0, 0xdf, 0x92, 0x80, 0xc4, 0xf2, 0xb7, 0xd1, 0x9f, 0xd6, 0xf3, 0xd8, 0xbb, 0xcc, 0x7b, 0xe6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.10", + /* Message */ + 20, + { 0x76, 0x72, 0xcf, 0xc2, 0x7a, 0x41, 0xd5, 0x01, 0xaa, 0x4c, 0x41, 0xba, 0xab, 0xf4, 0x52, 0x5a, 0x7c, 0x45, 0x5f, 0xc8 } +, + /* Seed */ + 105, + { 0x4c, 0xee, 0xa1, 0xa8, 0x94, 0x64, 0xa5, 0xd2, 0xf8, 0x9e, 0x07, 0x89, 0x53, 0xca, 0xf7, 0x76, 0x36, 0x58, 0x98, 0xa5, 0xbd, 0x5e, 0x8e, 0x44, 0x8c, 0x65, 0xda, 0x26, 0xff, 0x98, 0x90, 0x0c, 0xd0, 0x80, 0x61, 0xef, 0x44, 0x6c, 0x69, 0xb4, 0x8d, 0xc4, 0x60, 0x9e, 0xd8, 0x65, 0x4a, 0x64, 0x6d, 0x70, 0x82, 0x62, 0xcb, 0x84, 0x09, 0xac, 0x27, 0xc4, 0xa4, 0x9a, 0xdf, 0xed, 0x47, 0xa8, 0x5a, 0xd4, 0x29, 0xed, 0x75, 0x07, 0x75, 0x78, 0xe4, 0xc2, 0x73, 0xc6, 0x1e, 0x2c, 0x3b, 0x46, 0xbe, 0xb4, 0x72, 0xf0, 0xa3, 0x45, 0xa0, 0x5d, 0x61, 0xa7, 0xea, 0xaa, 0xd8, 0xa6, 0x3e, 0x0b, 0x3d, 0x49, 0x52, 0xf2, 0x7c, 0x40, 0x81, 0x32, 0x9e } +, + /* Encryption */ + 128, + { 0x25, 0x2b, 0x14, 0x13, 0x3f, 0x1d, 0xb2, 0x50, 0x13, 0x29, 0x35, 0x01, 0xe3, 0x56, 0x53, 0x4f, 0x26, 0xaf, 0xe3, 0x34, 0x68, 0x8e, 0x68, 0xd7, 0x91, 0x83, 0x3a, 0x0d, 0x82, 0x56, 0x05, 0x70, 0xbb, 0xb3, 0xce, 0x2b, 0x16, 0xd8, 0xb5, 0xf7, 0xf8, 0x9e, 0x7e, 0xbc, 0x7c, 0xf9, 0xc2, 0x94, 0xab, 0x34, 0x16, 0xb7, 0xc2, 0x11, 0x87, 0x70, 0x7f, 0xe5, 0xe7, 0x99, 0x2e, 0x72, 0x0f, 0xf9, 0x58, 0xda, 0xa4, 0x0f, 0x5a, 0xd4, 0x5b, 0xc7, 0x47, 0x47, 0x96, 0x39, 0xa5, 0x37, 0xfe, 0x0a, 0x4a, 0x75, 0xfc, 0xfb, 0x45, 0xa5, 0x3f, 0x01, 0x73, 0xaf, 0xc0, 0xf3, 0xcc, 0x91, 0x0b, 0x86, 0xae, 0x31, 0x37, 0x62, 0x8d, 0x90, 0xff, 0x67, 0x5a, 0xe1, 0xae, 0x31, 0xe1, 0x64, 0x05, 0x37, 0xea, 0x1a, 0x7c, 0xcc, 0xfb, 0x73, 0xf8, 0xbe, 0x5a, 0xec, 0xa0, 0x3b, 0xab, 0x19, 0x3b, 0xb0 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.11", + /* Message */ + 32, + { 0xa1, 0x6a, 0xd8, 0xf2, 0xe0, 0x93, 0x23, 0x42, 0xed, 0x21, 0xe1, 0x37, 0x77, 0xf4, 0x65, 0x2a, 0x35, 0x50, 0xdd, 0xb4, 0x36, 0x8b, 0x5e, 0xa7, 0x1c, 0x66, 0xdb, 0xc3, 0xbb, 0xfe, 0xb7, 0xdb } +, + /* Seed */ + 93, + { 0x55, 0x88, 0x4c, 0x83, 0x0d, 0x4a, 0x80, 0xb7, 0x9f, 0x08, 0x9d, 0xa7, 0x4d, 0xc2, 0x5a, 0xe0, 0xc4, 0x82, 0x46, 0x21, 0x45, 0xe1, 0xd0, 0x95, 0x23, 0xda, 0x3c, 0x93, 0x44, 0xbb, 0x97, 0xb0, 0x52, 0xfb, 0xdc, 0x15, 0x43, 0xdf, 0xb5, 0x3c, 0xf2, 0x37, 0x82, 0x59, 0x68, 0x7c, 0x7b, 0x1b, 0x35, 0xca, 0xf2, 0xf9, 0x19, 0x99, 0xed, 0x4a, 0xce, 0x39, 0xaf, 0x10, 0xd6, 0xbe, 0xd0, 0xfa, 0x22, 0x44, 0x4c, 0x12, 0x9d, 0x90, 0x74, 0x1c, 0xfc, 0xda, 0x90, 0x19, 0x8e, 0x27, 0x82, 0xfb, 0x03, 0xbd, 0xcc, 0x7c, 0xfa, 0xfd, 0x89, 0xdb, 0x6f, 0xb0, 0xfe, 0xd2, 0x24 } +, + /* Encryption */ + 128, + { 0x08, 0x32, 0x6a, 0xff, 0x6d, 0x03, 0xcc, 0x4e, 0x26, 0x10, 0xdd, 0x53, 0x6a, 0xf7, 0xf2, 0x1d, 0x76, 0x22, 0x7d, 0x82, 0x7d, 0x52, 0x80, 0xd8, 0xb8, 0x3a, 0xb9, 0xeb, 0x30, 0xe0, 0x76, 0x9c, 0xfa, 0x02, 0xb5, 0xc1, 0x35, 0x2b, 0xf4, 0xd1, 0x70, 0xce, 0xb6, 0x6f, 0x8b, 0xe6, 0x98, 0x78, 0x4e, 0x1a, 0x6c, 0x20, 0x3f, 0xa5, 0xab, 0x90, 0x07, 0xa6, 0xf7, 0xfc, 0x20, 0x65, 0x20, 0x4b, 0x98, 0x2f, 0xa5, 0x61, 0xfb, 0xb3, 0x61, 0xaf, 0x2b, 0x8e, 0xea, 0x42, 0xab, 0x3f, 0xec, 0x0e, 0xd0, 0x86, 0x22, 0xe5, 0xf2, 0x89, 0x80, 0x52, 0x75, 0x38, 0x0b, 0x69, 0x34, 0x2a, 0x96, 0xf7, 0x6a, 0x99, 0x04, 0x87, 0x68, 0x90, 0xd9, 0x2f, 0x24, 0x00, 0x20, 0x32, 0x35, 0x1d, 0x8a, 0x1c, 0xbc, 0x3d, 0x27, 0xb2, 0x46, 0x48, 0x21, 0xbb, 0xfb, 0xfb, 0xb9, 0xa6, 0x78, 0x51, 0x96, 0x10 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.12", + /* Message */ + 1, + { 0x4a } +, + /* Seed */ + 124, + { 0x8a, 0xa0, 0xce, 0xd1, 0x7f, 0x09, 0xad, 0xae, 0x61, 0x0a, 0x46, 0x03, 0x0d, 0xad, 0x40, 0x31, 0x1b, 0xf1, 0x46, 0x9c, 0x27, 0x37, 0x41, 0x1e, 0x40, 0xf9, 0x23, 0x96, 0x75, 0x1d, 0xd5, 0x66, 0x37, 0xc9, 0x58, 0xdb, 0xc5, 0x8a, 0x17, 0xfd, 0xbd, 0xdd, 0xdb, 0xbf, 0x79, 0x75, 0x18, 0x78, 0x98, 0xbe, 0x1a, 0xa6, 0x3c, 0x5e, 0xee, 0x5f, 0x9a, 0x19, 0x02, 0x98, 0x0f, 0x59, 0x51, 0x84, 0xb9, 0xb5, 0xb4, 0x65, 0xb9, 0x2e, 0x20, 0xf7, 0xae, 0x8b, 0x5a, 0x5c, 0xee, 0x7f, 0x3b, 0x57, 0xd9, 0x97, 0xa0, 0x6a, 0x70, 0x2d, 0x23, 0x83, 0x50, 0xa9, 0x26, 0x98, 0xef, 0x27, 0x5d, 0xff, 0x52, 0x77, 0xbd, 0x2c, 0x99, 0x96, 0x47, 0x40, 0x5a, 0xdb, 0xe4, 0xfb, 0x3f, 0x1b, 0xe7, 0x5e, 0x15, 0x9a, 0x4c, 0x43, 0x83, 0x13, 0xb7, 0xfd, 0x8a, 0xca, 0x9d, 0xea } +, + /* Encryption */ + 128, + { 0x4c, 0x4e, 0x5a, 0xb6, 0x2d, 0x0c, 0x96, 0x7a, 0xb8, 0x29, 0x21, 0x42, 0x9f, 0xfe, 0x50, 0xd2, 0x24, 0x0e, 0x7e, 0x0a, 0x18, 0x75, 0x48, 0x87, 0x55, 0xbb, 0x7f, 0xf6, 0x15, 0xa8, 0xc9, 0x9a, 0xbc, 0x37, 0xb2, 0xe4, 0x71, 0x47, 0xa9, 0x27, 0xd7, 0xb9, 0x8c, 0x30, 0xdb, 0x24, 0xda, 0x8c, 0xd3, 0x5e, 0x13, 0xd7, 0xb7, 0x14, 0x14, 0xd0, 0x32, 0xbd, 0x0c, 0x3c, 0xe3, 0x8b, 0x89, 0xb1, 0x1b, 0x2c, 0x3f, 0x9d, 0x83, 0x08, 0x16, 0x71, 0x6a, 0x2e, 0x8c, 0xcd, 0x8c, 0x79, 0xe9, 0xc7, 0x49, 0x31, 0xa7, 0xb8, 0xa8, 0xdb, 0x13, 0x12, 0x8c, 0xe4, 0x0b, 0x21, 0x59, 0xe4, 0x98, 0xda, 0x98, 0xf2, 0xaa, 0x35, 0x2f, 0x23, 0x85, 0x31, 0x06, 0xb6, 0x61, 0xd8, 0x8e, 0xd0, 0x6f, 0xf6, 0x6a, 0x56, 0xe7, 0x56, 0x59, 0x72, 0x20, 0xbd, 0x10, 0x15, 0x81, 0x53, 0xce, 0x5c, 0x02, 0x63 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.13", + /* Message */ + 11, + { 0xbf, 0xfc, 0x42, 0x08, 0x73, 0xf5, 0xaf, 0x5d, 0xd2, 0x3b, 0xb0 } +, + /* Seed */ + 114, + { 0xdd, 0x31, 0xcc, 0xd4, 0x7d, 0x4e, 0x31, 0x02, 0xdf, 0x0f, 0xc5, 0x9b, 0x1b, 0x84, 0x77, 0xaf, 0x3a, 0x78, 0xc2, 0xfa, 0x9c, 0x8e, 0xcb, 0x4f, 0x0b, 0x3b, 0xde, 0x23, 0x50, 0x04, 0x36, 0x55, 0x03, 0x64, 0x66, 0x5f, 0x81, 0xc0, 0x35, 0x6a, 0xbc, 0x0b, 0x78, 0xe9, 0x73, 0x19, 0x11, 0x14, 0x02, 0x75, 0xc8, 0x66, 0xf7, 0x5a, 0xd0, 0xcb, 0xbc, 0x88, 0xad, 0x6b, 0x5d, 0x4d, 0xa5, 0x2d, 0x08, 0xe2, 0x2e, 0xe5, 0x39, 0xb5, 0x8e, 0x92, 0xc6, 0x19, 0x63, 0x87, 0xe2, 0x21, 0xa0, 0x87, 0x39, 0x6c, 0xbe, 0x57, 0xec, 0x56, 0x03, 0xf6, 0x16, 0x26, 0x27, 0x98, 0x3e, 0xff, 0x82, 0xde, 0x04, 0x8b, 0xdc, 0x1b, 0x5e, 0xdb, 0xb5, 0xd4, 0xea, 0x84, 0xf5, 0x02, 0x24, 0xbd, 0x88, 0xa9, 0x05, 0xda } +, + /* Encryption */ + 128, + { 0x0d, 0xa2, 0xd6, 0xf7, 0xbc, 0xb5, 0x0a, 0x47, 0x2e, 0xda, 0x24, 0x60, 0x9d, 0xa6, 0x77, 0x28, 0xe5, 0x3c, 0x98, 0x80, 0xaa, 0x5f, 0xb6, 0xfb, 0xe6, 0x0d, 0x83, 0xc1, 0x1e, 0x6b, 0xb3, 0xcf, 0xdb, 0x17, 0xd1, 0x4d, 0xbc, 0xe8, 0xec, 0x55, 0xc7, 0x3a, 0xb0, 0x14, 0x3e, 0x9b, 0x27, 0x56, 0xbb, 0x69, 0x68, 0xe5, 0xaf, 0x1a, 0xed, 0xcf, 0x6a, 0x80, 0xc2, 0x6d, 0x49, 0x0e, 0x47, 0x18, 0x7e, 0xa5, 0xd8, 0xcd, 0x2f, 0xac, 0xb8, 0x1c, 0xe6, 0x4a, 0x72, 0x3c, 0x40, 0xf0, 0xba, 0x4c, 0x69, 0x3e, 0x1b, 0x11, 0x43, 0xdf, 0x15, 0xa4, 0x20, 0x91, 0x70, 0x9a, 0xb4, 0xc7, 0xcd, 0x9d, 0x47, 0x07, 0x9e, 0xcd, 0x68, 0xf6, 0xa1, 0x96, 0x44, 0x8a, 0x44, 0x67, 0x9a, 0x04, 0x14, 0x10, 0x41, 0x8f, 0x11, 0xa1, 0xe1, 0xbc, 0xe7, 0x8e, 0x77, 0x26, 0x04, 0xa2, 0xf2, 0x77, 0x81, 0x95 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.14", + /* Message */ + 40, + { 0x1a, 0x9b, 0x87, 0x29, 0x21, 0x0a, 0x84, 0x71, 0xfc, 0x5c, 0xd7, 0x09, 0xf2, 0xed, 0xd3, 0x24, 0x01, 0x50, 0x24, 0x4b, 0xec, 0x96, 0xa9, 0x2f, 0xf8, 0x07, 0xe3, 0xb3, 0x0d, 0x29, 0x5d, 0x3c, 0x34, 0x5c, 0x04, 0x4f, 0x2e, 0x95, 0x60, 0x37 } +, + /* Seed */ + 85, + { 0x58, 0x78, 0xc9, 0x1b, 0x16, 0x6e, 0x90, 0xc3, 0x4e, 0x6e, 0x66, 0x56, 0x8c, 0x15, 0x1f, 0x4d, 0x44, 0x43, 0x40, 0xb5, 0xf1, 0xd7, 0x30, 0x52, 0xcc, 0x56, 0x33, 0xea, 0x2e, 0x47, 0xac, 0xed, 0x7b, 0x17, 0x8a, 0x64, 0xfb, 0x09, 0xa5, 0xad, 0x08, 0x46, 0xae, 0xe4, 0x11, 0x6d, 0x67, 0x80, 0xee, 0x75, 0xeb, 0x20, 0x85, 0x16, 0x68, 0x82, 0x0c, 0xde, 0xc0, 0xf2, 0xc4, 0x96, 0xe4, 0xc2, 0x88, 0xd8, 0x27, 0x9c, 0x1c, 0x5d, 0x4e, 0xc0, 0x0d, 0x98, 0x0c, 0x27, 0x2e, 0x87, 0x05, 0x18, 0x48, 0x6d, 0xca, 0xea, 0x85 } +, + /* Encryption */ + 128, + { 0x37, 0x00, 0xac, 0x36, 0x2c, 0xf6, 0x0e, 0x16, 0x39, 0x47, 0xa1, 0x98, 0xd0, 0x0f, 0x3b, 0x3b, 0x26, 0xe0, 0x3e, 0xe2, 0xfb, 0x78, 0x2b, 0x42, 0x88, 0xb8, 0xc1, 0xde, 0x76, 0xe9, 0xe8, 0x99, 0x46, 0xc9, 0x80, 0x7c, 0x56, 0xe0, 0x9c, 0x7b, 0x52, 0xbe, 0x00, 0x78, 0xac, 0xf6, 0x92, 0x96, 0x4a, 0xcb, 0x97, 0xd1, 0xfa, 0x5c, 0xeb, 0x57, 0x76, 0xa1, 0xd5, 0x56, 0xb4, 0xbc, 0x9d, 0xb0, 0x0b, 0xda, 0x25, 0x23, 0x7a, 0x75, 0x1b, 0x7c, 0x22, 0x9b, 0x6b, 0x57, 0xf7, 0xff, 0x75, 0x1c, 0x12, 0xd1, 0xf2, 0x2a, 0x4f, 0xb0, 0xe9, 0x0b, 0x63, 0xd0, 0x42, 0xd9, 0x49, 0x9e, 0x0f, 0x7e, 0xfe, 0xad, 0xd3, 0xc5, 0x88, 0xf2, 0xc7, 0x43, 0xa1, 0x2c, 0x56, 0x7c, 0x81, 0x57, 0x8d, 0xbe, 0xeb, 0xfd, 0x37, 0x74, 0xda, 0x34, 0xad, 0x09, 0xee, 0xbe, 0x90, 0x17, 0x89, 0x02, 0x14, 0xb5 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.15", + /* Message */ + 64, + { 0xa6, 0xd0, 0xe8, 0xc1, 0xea, 0x4a, 0xb4, 0xec, 0xc8, 0x95, 0x7d, 0x62, 0x28, 0x15, 0x79, 0x67, 0x5a, 0x64, 0x8d, 0x62, 0xb7, 0xf2, 0x2b, 0x2b, 0x08, 0xd1, 0x31, 0x3f, 0x40, 0x6f, 0x13, 0x7e, 0x99, 0x42, 0x67, 0x35, 0xcd, 0xb9, 0x37, 0x2f, 0xec, 0xa1, 0xee, 0x78, 0x46, 0x3f, 0xa5, 0xde, 0x9c, 0xdd, 0x84, 0x75, 0x6c, 0x68, 0xbd, 0x1d, 0x92, 0xba, 0x96, 0x5f, 0x50, 0x64, 0x10, 0xb1 } +, + /* Seed */ + 61, + { 0x1c, 0x25, 0xc9, 0xb8, 0x32, 0x16, 0x9a, 0x1f, 0xdb, 0x6c, 0x14, 0x8e, 0x47, 0xe6, 0x6c, 0x3c, 0xc8, 0x21, 0x41, 0xe6, 0x11, 0xa6, 0xf3, 0x0c, 0xc9, 0x0c, 0x50, 0x49, 0xe8, 0xc5, 0x02, 0xb3, 0x1c, 0xad, 0xc7, 0x62, 0x39, 0xb7, 0xbd, 0xaf, 0x93, 0xfa, 0x97, 0x34, 0x3e, 0x7e, 0xe5, 0x51, 0xbc, 0x52, 0xfd, 0xb5, 0xec, 0x9e, 0x40, 0x0a, 0xf0, 0x5d, 0xbe, 0xac, 0xda } +, + /* Encryption */ + 128, + { 0x00, 0xe8, 0xb2, 0xfc, 0x76, 0xdf, 0xb4, 0xa6, 0xcc, 0x43, 0x64, 0xde, 0x8f, 0x68, 0x3c, 0x3f, 0xcd, 0x0a, 0x9e, 0xcf, 0xbd, 0x4a, 0x5a, 0x72, 0x24, 0xf4, 0x9a, 0xe9, 0xb4, 0xf3, 0xb5, 0xcd, 0xc7, 0x1c, 0xbb, 0x8c, 0x66, 0xfd, 0x35, 0xf3, 0xd1, 0x8e, 0xca, 0x98, 0x96, 0x7b, 0xd4, 0x00, 0x5d, 0xf7, 0x91, 0x52, 0x41, 0x6f, 0xd4, 0x7e, 0x56, 0x2c, 0x55, 0xed, 0xc6, 0xd6, 0x12, 0x12, 0x28, 0x6e, 0xf9, 0x75, 0xbc, 0xc8, 0x02, 0x69, 0x25, 0x92, 0x65, 0x39, 0x00, 0x97, 0x3c, 0x72, 0xe0, 0x1a, 0x69, 0x3b, 0x05, 0xfc, 0x2d, 0x58, 0x56, 0xea, 0xef, 0x7a, 0xc0, 0x8f, 0xf5, 0xec, 0xd5, 0x31, 0xe2, 0xc2, 0xce, 0x92, 0x77, 0x45, 0xa1, 0x16, 0x5a, 0x51, 0xaa, 0x66, 0x98, 0xa1, 0xff, 0xcb, 0x87, 0xf8, 0x1e, 0xf6, 0x51, 0x0b, 0xca, 0xf9, 0xcb, 0x76, 0x1e, 0x9e, 0x1f, 0x0f } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.16", + /* Message */ + 63, + { 0xf3, 0x40, 0x5b, 0x21, 0x8f, 0x3e, 0xc6, 0x03, 0xa9, 0x80, 0x69, 0x00, 0x99, 0xc2, 0xcf, 0x5c, 0xbe, 0x0b, 0x2b, 0x05, 0x96, 0x79, 0xc4, 0x6b, 0x7e, 0x48, 0xf6, 0xfd, 0xc4, 0xda, 0x40, 0x92, 0xd8, 0x31, 0xc8, 0xb5, 0x2b, 0x2c, 0xc7, 0x9b, 0xd2, 0xbb, 0xf6, 0xe9, 0xf5, 0x7b, 0x4e, 0x8c, 0xaa, 0x94, 0xb5, 0x81, 0xf9, 0xf2, 0x31, 0x26, 0x1f, 0x0e, 0x2b, 0xbb, 0xf5, 0x3d, 0xbb } +, + /* Seed */ + 62, + { 0xf4, 0x70, 0x7f, 0x58, 0x64, 0x2b, 0x54, 0xcb, 0xf8, 0x0a, 0x9b, 0x50, 0x48, 0xa6, 0xec, 0x0b, 0xd3, 0x5d, 0x09, 0x57, 0x16, 0xdb, 0x12, 0x06, 0x0c, 0xbf, 0x50, 0x58, 0x5f, 0xb9, 0x23, 0x79, 0x81, 0x05, 0x2f, 0x7b, 0xb1, 0x58, 0x3c, 0xd8, 0x7b, 0xc8, 0xbf, 0xb5, 0x5b, 0x73, 0x3e, 0x89, 0x0e, 0xb9, 0xc0, 0x8e, 0xf0, 0xe8, 0x80, 0xe9, 0xba, 0x0d, 0x50, 0xec, 0x95, 0x41 } +, + /* Encryption */ + 128, + { 0x6d, 0x9d, 0x39, 0x19, 0x8b, 0x5f, 0xcb, 0x13, 0x2d, 0x93, 0x15, 0x11, 0x49, 0xd7, 0x59, 0x91, 0x02, 0x4a, 0xc2, 0x2e, 0xb6, 0xeb, 0x2d, 0xc7, 0xc6, 0x05, 0x8f, 0x64, 0x87, 0x56, 0x45, 0x10, 0x2b, 0x95, 0x25, 0x4e, 0x25, 0xe9, 0xf0, 0xae, 0x45, 0x06, 0xd4, 0x3c, 0x60, 0x1c, 0x18, 0x8a, 0x31, 0x4f, 0x4b, 0xb4, 0xe0, 0x38, 0xc8, 0x15, 0x39, 0x41, 0x6e, 0x10, 0x5e, 0x80, 0x97, 0xfb, 0x69, 0x5a, 0xab, 0x36, 0xfe, 0xf5, 0x16, 0xe6, 0xa3, 0x3f, 0x36, 0xf7, 0xf9, 0x5a, 0xd1, 0xff, 0x15, 0x88, 0x90, 0x25, 0xb1, 0xb2, 0xe8, 0x1e, 0x1b, 0xf3, 0xb2, 0xde, 0x5b, 0xa9, 0x18, 0x7c, 0xa9, 0x6c, 0xeb, 0xa9, 0xfc, 0xec, 0xef, 0x9c, 0x53, 0xe4, 0x94, 0x34, 0x86, 0x18, 0x59, 0x67, 0xcf, 0x7a, 0x64, 0x77, 0xc3, 0x29, 0xf0, 0x0e, 0xa6, 0x95, 0x52, 0x5b, 0xca, 0x99, 0xf2, 0xc7 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.17", + /* Message */ + 52, + { 0x6a, 0xfa, 0xdb, 0xe3, 0xda, 0x68, 0xd9, 0x02, 0x85, 0xbb, 0x8f, 0x1e, 0x21, 0x29, 0xff, 0xeb, 0xb1, 0xc6, 0x5b, 0x95, 0x88, 0xd6, 0xc2, 0xc0, 0x40, 0x24, 0xc2, 0x38, 0xb2, 0x0c, 0x65, 0xd2, 0xac, 0xa5, 0xe3, 0x82, 0x76, 0x00, 0x0a, 0x0e, 0x6a, 0x0d, 0x05, 0x37, 0xef, 0xee, 0xf6, 0xd3, 0xe3, 0xd9, 0x4f, 0xb9 } +, + /* Seed */ + 73, + { 0xee, 0x17, 0x6e, 0xa3, 0xcf, 0xd4, 0x90, 0xb6, 0xc0, 0x49, 0xd2, 0xe7, 0x4c, 0x90, 0xc0, 0xee, 0x74, 0x68, 0x52, 0x03, 0x49, 0xb8, 0x51, 0x65, 0x3d, 0xb0, 0x58, 0xa1, 0xc3, 0xe9, 0x56, 0xe0, 0x88, 0x5f, 0x26, 0x1b, 0x6e, 0x71, 0xcf, 0x1e, 0x62, 0x3d, 0x3b, 0x9d, 0x1d, 0x56, 0xfa, 0x13, 0x67, 0xe4, 0x7f, 0xf3, 0x74, 0xad, 0x39, 0x30, 0x9f, 0xfa, 0x2e, 0x67, 0x11, 0x28, 0xd5, 0xab, 0xb4, 0xa6, 0x1a, 0x5b, 0x0d, 0xc2, 0xdb, 0x2c, 0x08 } +, + /* Encryption */ + 128, + { 0x67, 0x2f, 0xe9, 0x51, 0x59, 0xa9, 0x89, 0x3f, 0x34, 0x98, 0xb6, 0x16, 0xc1, 0x7b, 0x59, 0xda, 0x71, 0xda, 0x80, 0x2f, 0xeb, 0xf7, 0xcd, 0x38, 0x11, 0x06, 0x14, 0xa1, 0xb2, 0x5d, 0x96, 0xaa, 0x8a, 0x74, 0xaa, 0xaa, 0x2a, 0x0f, 0x00, 0x0e, 0xf8, 0xac, 0xa3, 0xb4, 0x1a, 0xd1, 0x61, 0xb6, 0x26, 0x33, 0xf2, 0x41, 0x31, 0x9c, 0x33, 0xe4, 0xec, 0xb7, 0x70, 0x6a, 0xb3, 0xad, 0xc6, 0xa3, 0xef, 0xea, 0x22, 0x43, 0x0f, 0x3f, 0x5c, 0x9c, 0x4c, 0xe5, 0x40, 0x4e, 0xb8, 0xe7, 0x5a, 0x10, 0x93, 0x69, 0xc0, 0xaa, 0x0b, 0x7d, 0xd7, 0x13, 0xbd, 0x8b, 0x77, 0xcc, 0xa5, 0xf7, 0x4b, 0xca, 0x5b, 0xc5, 0x55, 0x69, 0x6b, 0x68, 0xe1, 0x17, 0x2d, 0xb4, 0x02, 0x50, 0x1d, 0xcd, 0x26, 0x49, 0x68, 0x5d, 0xb0, 0xfd, 0x88, 0xc8, 0x83, 0x60, 0xda, 0xcc, 0x65, 0x09, 0xff, 0xa8, 0xdf, 0xc2 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.18", + /* Message */ + 48, + { 0x6d, 0x9f, 0x9b, 0x4b, 0xb1, 0x23, 0xba, 0x90, 0x95, 0x53, 0xa7, 0x57, 0x3a, 0x97, 0x1f, 0x64, 0xb7, 0x25, 0x24, 0xcf, 0xeb, 0x04, 0x2d, 0xe3, 0x92, 0x15, 0xf6, 0x50, 0xdb, 0x61, 0x2d, 0x66, 0xd7, 0xae, 0x86, 0x05, 0xd0, 0x44, 0x19, 0x54, 0x62, 0x5f, 0xa9, 0x81, 0x22, 0x33, 0x0e, 0x92 } +, + /* Seed */ + 77, + { 0x7f, 0xf8, 0x68, 0x5a, 0xec, 0xf3, 0x40, 0x26, 0x13, 0x90, 0xad, 0x07, 0x42, 0x73, 0x0c, 0xb6, 0x39, 0x28, 0x30, 0x14, 0xab, 0x37, 0x73, 0x55, 0x6c, 0x69, 0x7f, 0x97, 0xef, 0x62, 0x1a, 0x4d, 0xcb, 0xf8, 0xec, 0x6e, 0xde, 0xc5, 0x0d, 0x8e, 0xc9, 0x59, 0x0a, 0xdb, 0xaf, 0x23, 0x51, 0xdd, 0xfa, 0x0e, 0x52, 0xea, 0x6e, 0xd1, 0x8e, 0xb6, 0xc3, 0x78, 0xf3, 0x80, 0x85, 0xae, 0x5e, 0xe4, 0xcc, 0x48, 0xc1, 0x89, 0x1b, 0xa4, 0x7b, 0x20, 0x10, 0xd5, 0xd4, 0x35, 0x39 } +, + /* Encryption */ + 128, + { 0x8d, 0x30, 0x65, 0x5c, 0xf1, 0x5b, 0xf1, 0x0a, 0x46, 0x97, 0x87, 0xc6, 0xa1, 0x0e, 0x79, 0x25, 0x4f, 0xf0, 0xbd, 0x11, 0x93, 0x8b, 0xc6, 0x0a, 0x81, 0xa7, 0x58, 0xd9, 0x3c, 0xf2, 0xa0, 0x30, 0x24, 0x59, 0xfc, 0x2f, 0x0d, 0x77, 0x00, 0xb8, 0x6d, 0xd6, 0xed, 0x61, 0x83, 0x83, 0xb4, 0x4b, 0x45, 0x87, 0x04, 0xca, 0x11, 0x92, 0x8e, 0x50, 0x4f, 0x02, 0x8e, 0xfe, 0x50, 0x37, 0x17, 0x2c, 0x3e, 0x51, 0xb8, 0x37, 0xbe, 0x61, 0x56, 0xde, 0x6a, 0x09, 0xc5, 0x55, 0x97, 0xbe, 0x74, 0xc9, 0x7c, 0xaa, 0x1d, 0xeb, 0xf3, 0x14, 0xcd, 0x94, 0xb9, 0x1b, 0x9f, 0x94, 0xcb, 0xf7, 0x64, 0x0f, 0x86, 0xc2, 0x6d, 0x1d, 0x6a, 0x0b, 0x10, 0x46, 0x28, 0xb5, 0x87, 0x11, 0x4a, 0xa3, 0x1d, 0x99, 0xf6, 0x9c, 0xf9, 0x57, 0x37, 0x93, 0x2c, 0x0c, 0xb5, 0x33, 0x33, 0x74, 0xde, 0xa0, 0x7f, 0xac } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.19", + /* Message */ + 23, + { 0x33, 0xcc, 0xcb, 0x59, 0x7d, 0xe9, 0x5c, 0xed, 0xb8, 0xb6, 0x57, 0xfc, 0xd8, 0xf8, 0x88, 0x86, 0xda, 0x04, 0xc7, 0x57, 0x93, 0x53, 0x14 } +, + /* Seed */ + 102, + { 0x53, 0x42, 0xf4, 0x68, 0x43, 0x91, 0xcd, 0x74, 0xf5, 0x28, 0x2d, 0xb8, 0x31, 0x41, 0xff, 0xf6, 0x78, 0xf2, 0x3a, 0x3e, 0xa6, 0x52, 0xe0, 0xd4, 0x27, 0xfb, 0x6a, 0xd9, 0x76, 0xc5, 0xa7, 0x10, 0xa6, 0x37, 0x95, 0x77, 0x71, 0x89, 0x47, 0xac, 0x72, 0x7b, 0x4d, 0x58, 0xa0, 0xb0, 0xbd, 0x20, 0x7a, 0xe3, 0x73, 0xa8, 0xb9, 0x9a, 0xc8, 0xe2, 0x51, 0xeb, 0x02, 0x45, 0x8a, 0x9e, 0xdc, 0x39, 0x52, 0xfb, 0x28, 0x42, 0x6d, 0x18, 0xfd, 0xa1, 0x8a, 0x80, 0x2b, 0xbf, 0x0a, 0x0b, 0x8b, 0x2c, 0xf2, 0x5c, 0xa3, 0xa0, 0x22, 0xf7, 0x78, 0xc7, 0xf4, 0x7f, 0xc5, 0x30, 0xd0, 0xb7, 0xa5, 0xbc, 0x84, 0x6e, 0xea, 0x91, 0x80, 0xf2 } +, + /* Encryption */ + 128, + { 0x8c, 0x4a, 0x63, 0xd0, 0x73, 0x1e, 0x2e, 0x71, 0xeb, 0x46, 0x15, 0x18, 0x9a, 0x96, 0x8b, 0x3e, 0x4a, 0x24, 0x28, 0x56, 0xb2, 0x09, 0x02, 0x45, 0x23, 0x8b, 0x66, 0x45, 0x97, 0x8f, 0x1e, 0xe8, 0xd7, 0x98, 0x11, 0x06, 0x2e, 0xbd, 0x2d, 0x1f, 0x3d, 0x52, 0x3a, 0xe6, 0x00, 0xe0, 0xe5, 0xa6, 0xe4, 0x05, 0xc4, 0xe4, 0xb5, 0xa1, 0x6e, 0x8d, 0xfb, 0x49, 0x24, 0x30, 0x4b, 0x0d, 0x1f, 0xf4, 0xd6, 0x41, 0xbf, 0x98, 0x7f, 0xc6, 0xd4, 0x1d, 0x3e, 0xb7, 0xcd, 0xc5, 0x31, 0x34, 0xd0, 0x06, 0x9c, 0xdb, 0x5a, 0xfe, 0xf7, 0xf8, 0xf9, 0xca, 0xc0, 0xee, 0x52, 0x30, 0xb6, 0xf8, 0x86, 0x22, 0xa8, 0x4d, 0xe5, 0x2a, 0xd6, 0xf7, 0x50, 0x47, 0x84, 0x37, 0x06, 0xca, 0x96, 0x97, 0x42, 0xc5, 0x8d, 0xa7, 0x72, 0x62, 0xff, 0x1f, 0x12, 0x8a, 0x66, 0x4e, 0x51, 0xcd, 0x63, 0x5e, 0x71, 0x15 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 2.20", + /* Message */ + 2, + { 0x19, 0xd6 } +, + /* Seed */ + 123, + { 0xea, 0xac, 0xb5, 0x78, 0xae, 0xab, 0xf6, 0x9d, 0x4e, 0xae, 0xeb, 0x36, 0xd0, 0x4c, 0xd8, 0xa2, 0x2e, 0x8f, 0xd7, 0xa2, 0x5f, 0x04, 0x43, 0xa1, 0x1e, 0x4e, 0x08, 0xb3, 0xff, 0xac, 0x1e, 0x05, 0x42, 0x1a, 0x87, 0x6c, 0xca, 0x91, 0x31, 0x82, 0x50, 0xbe, 0xfa, 0xff, 0xef, 0x9b, 0x27, 0x49, 0xdc, 0x40, 0x2f, 0xad, 0x4f, 0xdb, 0x7c, 0x1b, 0x66, 0xaa, 0x5e, 0x08, 0x9f, 0xf9, 0x9f, 0x8b, 0x30, 0x0c, 0xdc, 0x46, 0xf4, 0x8f, 0x56, 0x48, 0xc9, 0x40, 0x8b, 0x5f, 0x8b, 0x3f, 0x5a, 0x12, 0xe6, 0x50, 0x50, 0xdc, 0xbc, 0x0d, 0x53, 0x43, 0xd6, 0x3d, 0x58, 0x08, 0x19, 0x21, 0x65, 0x2d, 0x5b, 0xc8, 0x2d, 0xd3, 0xd7, 0x0e, 0x07, 0x5d, 0x32, 0xd8, 0x02, 0xc2, 0x97, 0x64, 0x78, 0xfc, 0x9f, 0x09, 0x93, 0xdd, 0x08, 0x59, 0xc9, 0x0e, 0x22, 0x8e, 0x87 } +, + /* Encryption */ + 128, + { 0x61, 0x3b, 0xba, 0x5c, 0x19, 0x0a, 0xd7, 0x72, 0xe0, 0x8c, 0x29, 0x07, 0x6e, 0x2e, 0x9e, 0x5f, 0x12, 0xef, 0xc9, 0x29, 0x2e, 0x3b, 0x5c, 0xee, 0x52, 0xc2, 0x69, 0x7f, 0xb7, 0xb6, 0x07, 0xdc, 0x72, 0xe8, 0x25, 0x78, 0xe8, 0xb7, 0x53, 0xba, 0xca, 0xdf, 0x23, 0xb4, 0x77, 0x25, 0x21, 0x3d, 0xb8, 0x9f, 0x88, 0x73, 0xfa, 0x79, 0xb9, 0x14, 0xa4, 0xb5, 0x16, 0x1e, 0xfd, 0x9e, 0x15, 0xcf, 0xa8, 0xdd, 0x1e, 0xff, 0xe8, 0x9f, 0x89, 0x47, 0xa6, 0xf3, 0x82, 0x6d, 0xc6, 0xbf, 0x53, 0xbe, 0xca, 0x36, 0x5b, 0x93, 0x81, 0x18, 0x45, 0x62, 0xa7, 0x9e, 0x21, 0xca, 0x0e, 0x68, 0xeb, 0xf0, 0xab, 0x82, 0xae, 0x76, 0x2b, 0x28, 0xc1, 0x43, 0x65, 0x15, 0x2a, 0xe0, 0xf5, 0x4f, 0x2e, 0x9d, 0x14, 0x43, 0x9a, 0x84, 0x6b, 0x38, 0x3f, 0x5e, 0x2c, 0x55, 0xef, 0xa7, 0x00, 0x85, 0x97, 0xb5 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 3: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xb9, 0x30, 0x96, 0xd0, 0x26, 0x1e, 0xfe, 0x00, 0x0b, 0x3d, 0x17, 0x04, 0xf5, 0x04, 0x31, 0x60, 0xab, 0xd3, 0xeb, 0x56, 0x6c, 0x61, 0xe5, 0x3c, 0x76, 0xc4, 0x01, 0xe2, 0xb6, 0x55, 0x21, 0xbc, 0x12, 0xd4, 0x81, 0x21, 0x51, 0x83, 0xe8, 0xf4, 0x6c, 0x2c, 0xa8, 0xd0, 0x0a, 0xda, 0x5d, 0xfd, 0x04, 0xdc, 0xf7, 0xcf, 0x36, 0xcc, 0x58, 0x11, 0x05, 0xd9, 0x9d, 0x2a, 0x7d, 0xd9, 0x4b, 0x56, 0x76, 0x0a, 0x65, 0x64, 0xfe, 0xe5, 0xe8, 0xaa, 0xeb, 0x06, 0x07, 0xe1, 0x45, 0x19, 0x62, 0x10, 0xa3, 0x1b, 0x7e, 0xd8, 0xdd, 0x2a, 0xf3, 0x2d, 0x29, 0xd2, 0xba, 0xd6, 0xf1, 0x5f, 0xfa, 0x5a, 0x11, 0xdc, 0x73, 0x5c, 0xc3, 0x62, 0x19, 0x02, 0x1e, 0xe8, 0xd1, 0xee, 0xed, 0x34, 0x63, 0x9b, 0x5a, 0x91, 0xac, 0x6a, 0x92, 0x67, 0x4e, 0x18, 0x39, 0x70, 0xc5, 0x9d, 0x5b, 0x19, 0x6d, 0x4b } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x01, 0x07, 0xea, 0x61, 0xad, 0xec, 0xa5, 0xe9, 0x00, 0x7c, 0x59, 0x13, 0x4a, 0x7d, 0x38, 0xfc, 0x7a, 0xf3, 0x10, 0x3a, 0xd2, 0xc4, 0xa2, 0xbe, 0xe3, 0x97, 0x08, 0xbe, 0xfc, 0x83, 0xdc, 0x79, 0xb7, 0x0d, 0xc9, 0x75, 0x92, 0xdb, 0x6d, 0xf7, 0x0f, 0xb3, 0xc4, 0x9c, 0x25, 0x35, 0xfc, 0xfd, 0x9f, 0xc2, 0xce, 0x7b, 0x05, 0x53, 0x92, 0xe3, 0xee, 0xb3, 0xe7, 0x97, 0x93, 0xcc, 0x1b, 0x60, 0x15, 0x3f, 0x4a, 0x0b, 0xff, 0x26, 0xbe, 0x66, 0x7b, 0xbc, 0xdb, 0xbf, 0x6e, 0x32, 0xaf, 0xa6, 0xfd, 0x14, 0x83, 0x7f, 0x3c, 0x79, 0xbe, 0x44, 0xcb, 0x1c, 0x63, 0x8f, 0xfa, 0x5c, 0x6b, 0x17, 0x70, 0x9a, 0x96, 0xe1, 0x27, 0x03, 0x0b, 0xb1, 0x11, 0x6d, 0xec, 0xfd, 0xe5, 0x2b, 0xb0, 0x40, 0x84, 0x2a, 0x94, 0xd2, 0xe6, 0x74, 0xf1, 0x17, 0x51, 0xec, 0xb9, 0x03, 0xee, 0x10, 0x48, 0x45 } +, + /* Prime 1 */ + 64, + { 0xe7, 0xfe, 0xc4, 0x74, 0xe0, 0xeb, 0x31, 0x2d, 0x1d, 0x76, 0xcb, 0xb2, 0x72, 0x2e, 0xfa, 0x42, 0x10, 0x68, 0xb1, 0x91, 0xe2, 0x33, 0xb6, 0x4e, 0x46, 0x08, 0x7f, 0xdd, 0x45, 0x76, 0xd3, 0x85, 0x55, 0x07, 0x19, 0x35, 0x2e, 0x10, 0x9f, 0xe4, 0x33, 0xac, 0x4e, 0x35, 0x8e, 0x7c, 0x28, 0x59, 0xeb, 0xa7, 0xe4, 0x3a, 0x04, 0xee, 0x85, 0x9a, 0x46, 0x35, 0x2c, 0x12, 0x43, 0xa1, 0xcc, 0x6f } +, + /* Prime 2 */ + 64, + { 0xcc, 0x5a, 0x02, 0xf9, 0x55, 0x7a, 0x63, 0x5c, 0xf5, 0xe6, 0x9b, 0x0f, 0x2b, 0x3f, 0x2e, 0x61, 0x2e, 0x1f, 0x0a, 0xbb, 0xd4, 0xbc, 0xf1, 0x69, 0xca, 0xc0, 0x84, 0xdc, 0xf4, 0xb9, 0xb4, 0x34, 0x43, 0xa7, 0x85, 0x23, 0x90, 0xf8, 0x19, 0x41, 0x9e, 0xc1, 0xa8, 0x38, 0x7e, 0xf0, 0x4d, 0xd2, 0xdb, 0x7d, 0x60, 0xb4, 0x0a, 0x21, 0xf9, 0x4f, 0x46, 0xd2, 0x27, 0x87, 0x4b, 0x3e, 0x52, 0xe5 } +, + /* Prime exponent 1 */ + 64, + { 0xab, 0x92, 0x8b, 0x10, 0x35, 0x57, 0x3b, 0x23, 0x36, 0x6b, 0x28, 0xf2, 0x6b, 0xe7, 0xba, 0x45, 0x29, 0x85, 0x83, 0xed, 0x73, 0xf0, 0xf2, 0x9e, 0xa8, 0xc4, 0x98, 0x6b, 0xb8, 0x77, 0xcc, 0xaf, 0x0a, 0xd7, 0x19, 0x19, 0x6f, 0x5b, 0xf4, 0x23, 0xfc, 0xe3, 0x2d, 0x64, 0x06, 0x60, 0x64, 0x27, 0x3c, 0x55, 0x0a, 0x40, 0xae, 0x6d, 0x08, 0x79, 0xb3, 0xfa, 0x97, 0x01, 0x5a, 0xeb, 0x4a, 0x19 } +, + /* Prime exponent 2 */ + 63, + { 0x8c, 0x7d, 0x55, 0x8e, 0x15, 0x36, 0x0f, 0x19, 0xd9, 0xf4, 0xb0, 0xa5, 0xbd, 0x15, 0xb2, 0xcd, 0x1c, 0xe8, 0x3a, 0x78, 0xe7, 0xc8, 0xfe, 0x2f, 0xbd, 0x34, 0x9e, 0x23, 0x4a, 0x1c, 0x61, 0xc7, 0x8c, 0xbb, 0x9e, 0xcc, 0xd4, 0xdd, 0xbc, 0x7f, 0x60, 0xa5, 0xc3, 0x01, 0x14, 0x44, 0x21, 0x3c, 0xd5, 0xa9, 0x5c, 0xd2, 0x6a, 0x24, 0xf1, 0x41, 0x8f, 0x6e, 0xeb, 0xbe, 0x17, 0xfc, 0xc1 } +, + /* Coefficient */ + 64, + { 0xb0, 0xb1, 0xb9, 0xcb, 0x23, 0xac, 0x2a, 0x8a, 0x56, 0x36, 0x66, 0x69, 0x9a, 0x52, 0x40, 0x54, 0xbe, 0xf3, 0x81, 0xaa, 0xbd, 0x75, 0x55, 0x31, 0xa1, 0xdf, 0xa8, 0x85, 0xdc, 0x8f, 0x98, 0x86, 0xa5, 0x5a, 0xf0, 0xe3, 0x68, 0x63, 0x91, 0xc7, 0x97, 0x68, 0x1a, 0x8f, 0xef, 0xcf, 0x24, 0xdb, 0xd8, 0x1e, 0x03, 0x13, 0x16, 0x99, 0x8f, 0x5d, 0x81, 0x8d, 0x24, 0x76, 0xda, 0xd0, 0x6d, 0xe8 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 3.1", + /* Message */ + 17, + { 0x44, 0xe5, 0x6a, 0xa7, 0x7b, 0xd9, 0x35, 0xac, 0x59, 0xa9, 0xbd, 0x32, 0x37, 0x83, 0xe1, 0x27, 0x42 } +, + /* Seed */ + 108, + { 0x92, 0xee, 0xf6, 0x19, 0xf0, 0x4f, 0x52, 0x02, 0x8f, 0x4c, 0xc3, 0xe5, 0x24, 0x1f, 0x0a, 0xa0, 0x92, 0x1b, 0x4d, 0x18, 0x3c, 0x1f, 0x5b, 0xd6, 0x8d, 0x86, 0xfb, 0xe9, 0xe7, 0xb7, 0xd0, 0xbb, 0x10, 0x4e, 0xd1, 0xca, 0xe0, 0x7a, 0xc7, 0xd8, 0x0b, 0xfd, 0x9c, 0x1c, 0xef, 0xf8, 0xdc, 0xda, 0x1d, 0xcc, 0x69, 0x30, 0xf4, 0xc5, 0x51, 0x37, 0x34, 0x6b, 0xfd, 0x68, 0xc1, 0x9d, 0x87, 0x97, 0x2f, 0x7f, 0x34, 0xcb, 0xae, 0x56, 0x63, 0x26, 0x0f, 0xeb, 0x79, 0xf7, 0x60, 0x22, 0x1c, 0xd6, 0x7b, 0xe0, 0x66, 0xd5, 0xaf, 0x0f, 0x07, 0x3c, 0x0f, 0x2c, 0x43, 0x9e, 0x8b, 0xcb, 0x74, 0x63, 0xed, 0xe4, 0x4c, 0x8b, 0x15, 0x0e, 0xba, 0xf3, 0x29, 0x87, 0x26, 0xc3 } +, + /* Encryption */ + 128, + { 0x15, 0x91, 0xd1, 0xce, 0x0f, 0xad, 0x66, 0xd8, 0x6f, 0xd4, 0x2e, 0xfd, 0xb3, 0x1e, 0x9a, 0x02, 0x8a, 0x31, 0x57, 0xfb, 0x09, 0x14, 0xb2, 0x47, 0xeb, 0x3d, 0x22, 0xd7, 0x6f, 0x97, 0x69, 0xb0, 0xe1, 0x9f, 0x6c, 0x06, 0x4c, 0xa1, 0xb9, 0x89, 0x06, 0x39, 0xee, 0x6e, 0x37, 0xb7, 0x09, 0x22, 0x4d, 0x6b, 0x58, 0xeb, 0xb6, 0x55, 0xae, 0x4b, 0x69, 0xed, 0x4c, 0xd7, 0x5d, 0x81, 0x29, 0x21, 0x17, 0xc0, 0x69, 0x30, 0xd4, 0x2a, 0xc4, 0xd4, 0x2e, 0xa7, 0x35, 0x14, 0x21, 0x8f, 0x49, 0xea, 0x07, 0xca, 0x97, 0x43, 0x67, 0x09, 0x68, 0x3d, 0x67, 0xa8, 0xe9, 0xe8, 0x08, 0xda, 0x69, 0xa5, 0x0b, 0x73, 0x9c, 0x42, 0xeb, 0x0d, 0xeb, 0x94, 0xa3, 0x49, 0x8f, 0xc5, 0x45, 0x0e, 0xb6, 0x9a, 0xce, 0x23, 0x76, 0x76, 0x61, 0xfe, 0xdf, 0x34, 0x18, 0x3a, 0x1b, 0x6f, 0x42, 0x5d, 0xd6, 0xa0 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 3.2", + /* Message */ + 18, + { 0xa7, 0x57, 0x38, 0x29, 0x1f, 0xad, 0x54, 0x13, 0x95, 0x7f, 0xa3, 0xb9, 0xf3, 0xb2, 0xca, 0xac, 0x9f, 0x5a } +, + /* Seed */ + 107, + { 0x3a, 0x19, 0x1a, 0xaf, 0x45, 0xed, 0x4c, 0x25, 0x89, 0x20, 0x5d, 0x9c, 0xf6, 0xa3, 0x0f, 0x07, 0x70, 0x0e, 0x38, 0xbe, 0x06, 0x25, 0x62, 0x43, 0x01, 0x8d, 0x23, 0xc6, 0x84, 0xda, 0xec, 0xe7, 0xe8, 0x67, 0xe3, 0x9d, 0x76, 0xc6, 0xb6, 0xf0, 0x35, 0x43, 0xfc, 0x15, 0xaf, 0x81, 0xbf, 0x84, 0xf9, 0x64, 0xea, 0xf3, 0xa9, 0x5a, 0x4b, 0x80, 0x86, 0x28, 0xfd, 0x51, 0x55, 0x38, 0x99, 0xf8, 0x11, 0xc0, 0x8c, 0x62, 0x60, 0x9c, 0x51, 0x4c, 0xfa, 0x1d, 0xbb, 0x78, 0xd5, 0xa5, 0xb3, 0x3c, 0xc0, 0xb8, 0x57, 0xfc, 0xb1, 0xee, 0xcc, 0x53, 0x1b, 0x13, 0x26, 0x34, 0x43, 0x90, 0x59, 0xf5, 0x5a, 0x73, 0x3e, 0x14, 0x6e, 0x1c, 0xa1, 0xeb, 0x5a, 0x97, 0xf4 } +, + /* Encryption */ + 128, + { 0x70, 0xaa, 0xf7, 0x24, 0x39, 0x6c, 0x1a, 0xc5, 0x0e, 0xdb, 0xbf, 0xe8, 0x34, 0x1b, 0x08, 0x7b, 0xa0, 0xff, 0xe2, 0x87, 0x60, 0x5a, 0x8c, 0x3a, 0x8c, 0xcf, 0x85, 0xab, 0x2e, 0xd2, 0xfe, 0x22, 0x15, 0x9d, 0x62, 0xaa, 0x02, 0x74, 0x76, 0xeb, 0xbf, 0x07, 0x70, 0x02, 0x6d, 0x2d, 0x3b, 0x0c, 0x0d, 0x77, 0x34, 0xfa, 0xaa, 0xa8, 0xd1, 0x5e, 0x2c, 0xe5, 0x1c, 0x85, 0x53, 0x5c, 0x26, 0xb4, 0x15, 0x0a, 0xd6, 0x34, 0x6e, 0x3b, 0xfd, 0x38, 0xdb, 0x5d, 0xac, 0xf7, 0x52, 0xe7, 0x5d, 0x75, 0x31, 0x40, 0x54, 0xd1, 0x67, 0xa9, 0x6d, 0x81, 0x9f, 0x34, 0x38, 0xa7, 0xbe, 0xc4, 0x46, 0x7f, 0xc5, 0x60, 0xa6, 0x94, 0x46, 0x94, 0x85, 0xe8, 0xe7, 0x8e, 0x47, 0xe4, 0xe8, 0x27, 0x7c, 0xa7, 0xd3, 0xfd, 0x2a, 0xd9, 0x4a, 0x30, 0x46, 0x4c, 0x24, 0x57, 0x85, 0x47, 0x25, 0xc6, 0x16, 0x15 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.3", + /* Message */ + 14, + { 0x87, 0x31, 0x2f, 0x78, 0x7d, 0xe0, 0x65, 0x97, 0x50, 0xd6, 0x02, 0xac, 0x11, 0x02 } +, + /* Seed */ + 111, + { 0xa2, 0x29, 0xe3, 0xe8, 0xef, 0x1c, 0xaa, 0x66, 0xca, 0xf0, 0xd8, 0xac, 0xd8, 0xd6, 0x6b, 0x9e, 0x41, 0xcc, 0x77, 0x1f, 0x26, 0xe2, 0x0f, 0x12, 0xec, 0xc6, 0xe2, 0xaa, 0x38, 0x45, 0x51, 0x3d, 0xd1, 0x34, 0xf7, 0xc6, 0xe5, 0x74, 0xf4, 0x1b, 0x21, 0x5d, 0x1d, 0x11, 0x17, 0x56, 0xda, 0xf9, 0x71, 0xcc, 0xf3, 0x9c, 0xcd, 0xce, 0x78, 0x16, 0x19, 0xd7, 0x97, 0x20, 0xdf, 0x91, 0x8d, 0x33, 0x9c, 0x82, 0x6d, 0xc0, 0x49, 0xb3, 0x90, 0x91, 0x7c, 0x17, 0xba, 0x0f, 0xb1, 0x30, 0x2f, 0xff, 0x11, 0x0a, 0x14, 0xdd, 0x23, 0x84, 0x90, 0x27, 0x41, 0xf9, 0x12, 0xb2, 0x6a, 0x1a, 0xdb, 0xe0, 0xed, 0x1e, 0x8f, 0xd9, 0x89, 0x71, 0x0b, 0x40, 0x3d, 0x27, 0xc4, 0xe0, 0x18, 0xfb, 0x9b } +, + /* Encryption */ + 128, + { 0x03, 0x38, 0x46, 0xd7, 0x66, 0x4c, 0x8f, 0x92, 0x62, 0x57, 0xc7, 0xfd, 0x32, 0x64, 0x48, 0x47, 0x92, 0xac, 0x7f, 0x9b, 0xc8, 0x75, 0x8a, 0x7a, 0x16, 0xab, 0xb8, 0x9f, 0xa3, 0xcc, 0xc4, 0xd1, 0x3a, 0x1e, 0xed, 0x88, 0xaf, 0x73, 0x23, 0xbc, 0x3c, 0x74, 0xe2, 0x3f, 0xda, 0xb5, 0x03, 0x81, 0x89, 0x4c, 0x86, 0x26, 0xdf, 0xd0, 0xac, 0x85, 0x89, 0xd4, 0x62, 0x34, 0xd3, 0xc3, 0x5f, 0x18, 0x99, 0x81, 0x79, 0x44, 0x84, 0x31, 0xdc, 0x81, 0x6f, 0xb6, 0x3e, 0x55, 0xcf, 0x26, 0xd7, 0x4a, 0x9d, 0x2a, 0x09, 0x32, 0x67, 0x3c, 0xb4, 0xbe, 0xb8, 0x29, 0xcd, 0x7d, 0x49, 0x50, 0x88, 0x48, 0xc6, 0xd0, 0xc0, 0x0d, 0x5c, 0x70, 0xf7, 0xfb, 0x47, 0x67, 0x70, 0xe4, 0x03, 0x19, 0x23, 0x7c, 0x78, 0x6b, 0xf4, 0xe2, 0x6c, 0x48, 0xd2, 0xcf, 0xd9, 0x6e, 0xe3, 0x62, 0xbf, 0x29, 0x28, 0x25 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.4", + /* Message */ + 54, + { 0x9a, 0x2b, 0xca, 0x75, 0xe3, 0x26, 0x49, 0x77, 0x7b, 0x9f, 0x13, 0xec, 0x30, 0xfe, 0x16, 0xbb, 0x8a, 0xb4, 0x6d, 0x6d, 0x5e, 0x0c, 0x64, 0x63, 0xa7, 0x3d, 0x8c, 0x36, 0x63, 0xad, 0xab, 0xc7, 0x23, 0xbd, 0xe7, 0x2a, 0x50, 0x76, 0x5e, 0x7b, 0x30, 0x0e, 0xf6, 0xb5, 0x61, 0xde, 0xe8, 0x84, 0x84, 0x88, 0x0e, 0x4d, 0x61, 0x2c } +, + /* Seed */ + 71, + { 0x8b, 0xfa, 0xe9, 0x22, 0x2f, 0x75, 0xa0, 0x69, 0x98, 0xed, 0x6d, 0x9b, 0x14, 0x9e, 0x89, 0x05, 0xcf, 0xc8, 0xdb, 0x05, 0x5a, 0x0e, 0x32, 0xac, 0xed, 0xf8, 0x24, 0xd2, 0xf6, 0xb5, 0xb4, 0x2b, 0x3a, 0xea, 0xc6, 0xa7, 0x10, 0x4e, 0x14, 0x4d, 0x5e, 0x48, 0x34, 0x28, 0x0e, 0x36, 0x44, 0x5a, 0xb8, 0x50, 0xf3, 0xa6, 0xde, 0x16, 0x4c, 0x2c, 0x79, 0x0f, 0xe7, 0xd9, 0xd7, 0xbc, 0x7f, 0x9b, 0xdb, 0xe2, 0x52, 0x17, 0xda, 0x2d, 0xed } +, + /* Encryption */ + 128, + { 0x6e, 0xc5, 0xf5, 0x59, 0xc8, 0xa3, 0x20, 0xd9, 0x0d, 0x1e, 0xb5, 0xef, 0x09, 0x1c, 0x4d, 0x12, 0x55, 0xa2, 0x4a, 0x69, 0x19, 0x41, 0x0e, 0xb1, 0xdf, 0x65, 0xa9, 0x7b, 0x30, 0xcd, 0xd7, 0xfa, 0xe1, 0x8e, 0x65, 0x12, 0xa0, 0x27, 0xe9, 0x76, 0x70, 0x4b, 0x4f, 0xa0, 0x44, 0x37, 0x43, 0x93, 0xd5, 0x01, 0xe2, 0xba, 0x46, 0x18, 0x62, 0x00, 0xef, 0x0d, 0xdd, 0xf1, 0x9c, 0x75, 0x77, 0x58, 0xe4, 0x67, 0x94, 0x30, 0xbc, 0xd9, 0xfd, 0x11, 0x9e, 0xa2, 0x43, 0xb3, 0x49, 0xdc, 0xf8, 0x1c, 0x34, 0x32, 0xd3, 0x1f, 0xba, 0x91, 0x1e, 0xc6, 0xfc, 0x68, 0x6e, 0xaa, 0xdf, 0xf6, 0xb9, 0xfd, 0xf5, 0x3a, 0xa4, 0xc8, 0x5a, 0x49, 0xa2, 0x2a, 0x05, 0x1c, 0x5f, 0x18, 0x07, 0xf3, 0x08, 0x3b, 0x1b, 0x3e, 0x61, 0x17, 0xb4, 0xef, 0x12, 0x08, 0xde, 0x0a, 0x80, 0x01, 0xdc, 0x29, 0x1c, 0x4e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.5", + /* Message */ + 48, + { 0xdf, 0xd6, 0x3e, 0x6e, 0xc6, 0x1e, 0x07, 0x27, 0x5b, 0x8e, 0x37, 0xcc, 0x63, 0x69, 0xe1, 0xf3, 0xec, 0x0b, 0xfc, 0x57, 0xa2, 0x98, 0xb9, 0x05, 0xae, 0x5d, 0x07, 0x74, 0xe0, 0xf5, 0x22, 0xe6, 0x75, 0x9c, 0x7d, 0x11, 0x6f, 0x8e, 0x8e, 0xfe, 0x69, 0x45, 0x0f, 0xa7, 0xa8, 0x38, 0x9f, 0x81 } +, + /* Seed */ + 77, + { 0xc4, 0x22, 0x37, 0x7b, 0x89, 0x86, 0x4b, 0x0d, 0xf3, 0x8b, 0x4f, 0x9c, 0x15, 0xf9, 0x8a, 0x05, 0x96, 0x55, 0xe1, 0xc9, 0xb0, 0xc7, 0x09, 0x63, 0x5c, 0xa6, 0x06, 0x49, 0xd8, 0xd2, 0x47, 0x5e, 0xe1, 0x6c, 0xb1, 0x27, 0xf6, 0x76, 0x39, 0x12, 0x96, 0x4e, 0x19, 0x84, 0xd6, 0xda, 0xad, 0x4d, 0x6a, 0xbd, 0x04, 0xb0, 0x46, 0x18, 0xb3, 0x2e, 0x53, 0x25, 0xba, 0x95, 0xeb, 0x5e, 0x76, 0xdb, 0xd4, 0x6d, 0x9f, 0xb5, 0x9d, 0xf0, 0x7a, 0x08, 0x1e, 0x95, 0x6c, 0xb0, 0x73 } +, + /* Encryption */ + 128, + { 0x9e, 0x06, 0xcd, 0x91, 0xa4, 0x4a, 0x9a, 0xde, 0xa6, 0xa7, 0x98, 0x03, 0xd3, 0xe6, 0xbb, 0xab, 0x17, 0xdb, 0x10, 0x62, 0xb6, 0x51, 0x0b, 0xed, 0x40, 0x07, 0x55, 0x66, 0x74, 0x95, 0x44, 0xc0, 0x3d, 0x7a, 0x78, 0xb1, 0x37, 0xb0, 0xdc, 0x1e, 0x66, 0x26, 0x32, 0x1f, 0xed, 0xaf, 0xc2, 0x0d, 0xcd, 0xbf, 0x70, 0x80, 0xf7, 0xf5, 0xbd, 0xd5, 0x67, 0x44, 0xce, 0x99, 0x9f, 0x76, 0x70, 0x5c, 0x4f, 0x5e, 0x6f, 0xa1, 0x5f, 0x46, 0xc5, 0xae, 0x50, 0x80, 0x90, 0xdb, 0xbc, 0x85, 0xfb, 0x86, 0x89, 0x9c, 0x95, 0x78, 0x60, 0x8d, 0xfd, 0x77, 0x8a, 0xa4, 0xa7, 0x9d, 0x3d, 0x73, 0x63, 0x54, 0xcc, 0xfb, 0xfa, 0x2c, 0x86, 0xf2, 0x9a, 0x7a, 0x58, 0x45, 0x3d, 0x75, 0x7f, 0xd5, 0x22, 0xf7, 0x84, 0x08, 0xd9, 0x91, 0x6b, 0x1b, 0xd0, 0x65, 0x4b, 0xff, 0xe6, 0xe0, 0x66, 0xba, 0xeb, 0x50 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.6", + /* Message */ + 35, + { 0x5d, 0x91, 0xfb, 0xc1, 0xa7, 0xba, 0x79, 0x93, 0x9b, 0x89, 0xa2, 0x40, 0x8c, 0xce, 0x8e, 0xd4, 0xbb, 0x26, 0x66, 0xdd, 0xfe, 0x09, 0xd9, 0x19, 0x21, 0xa0, 0xaa, 0x69, 0x09, 0x6a, 0x95, 0x69, 0x92, 0xc2, 0x1c } +, + /* Seed */ + 90, + { 0xaf, 0x07, 0xfe, 0xa3, 0x21, 0xea, 0xa2, 0x67, 0xaf, 0x7f, 0x09, 0x80, 0x6f, 0x9e, 0xa8, 0xb4, 0xcf, 0x13, 0x5e, 0xd6, 0xf1, 0x43, 0x2d, 0x51, 0xb2, 0x8f, 0x92, 0x44, 0x87, 0x09, 0xc2, 0xee, 0x8a, 0xed, 0x7f, 0x73, 0xb6, 0x28, 0x2c, 0xbf, 0xd3, 0x7f, 0x82, 0xdb, 0xa8, 0x72, 0x3e, 0x5e, 0x5e, 0x0a, 0x81, 0xf5, 0x90, 0xf8, 0x2e, 0x2f, 0xa8, 0x4c, 0x3b, 0xc0, 0x0c, 0x9b, 0x9f, 0x91, 0xaa, 0x55, 0x3b, 0x8b, 0x2c, 0x07, 0x4b, 0xfe, 0xca, 0xc2, 0xf5, 0x52, 0x37, 0xf4, 0xcb, 0x70, 0x54, 0x3a, 0xba, 0x49, 0x94, 0x68, 0xcf, 0x68, 0x44, 0xc3 } +, + /* Encryption */ + 128, + { 0x76, 0x05, 0x0e, 0x22, 0x64, 0x22, 0x0e, 0x10, 0x05, 0x2c, 0x49, 0xb9, 0x6c, 0xc8, 0x41, 0x1e, 0x39, 0x6a, 0x7a, 0x6e, 0x4a, 0xed, 0xb0, 0x6b, 0x48, 0xfd, 0xb0, 0x71, 0xde, 0x83, 0x9b, 0x40, 0x1c, 0xac, 0x0c, 0x46, 0x8d, 0xe8, 0xd1, 0xed, 0x0b, 0x56, 0x8c, 0xe6, 0x90, 0xe8, 0x03, 0x7a, 0xf5, 0xde, 0xf6, 0xb3, 0xd2, 0xdb, 0xc7, 0xb5, 0xf2, 0xfa, 0xde, 0x35, 0x6c, 0x26, 0xcf, 0xfc, 0xdd, 0x33, 0x40, 0x33, 0xea, 0x2c, 0x99, 0x77, 0x92, 0xd9, 0x30, 0xa7, 0x26, 0x46, 0x12, 0x5c, 0x0e, 0xe8, 0x6a, 0x4d, 0xd8, 0x43, 0xc8, 0x24, 0xc7, 0xa5, 0x2a, 0xc9, 0x88, 0xc9, 0x2e, 0x6c, 0x69, 0xb5, 0x80, 0x76, 0x1c, 0x49, 0x88, 0x1f, 0x29, 0xdd, 0x8a, 0x76, 0xda, 0x79, 0x3f, 0x43, 0x2e, 0x7d, 0x5d, 0xc7, 0x31, 0xa2, 0x5e, 0x5b, 0xb5, 0x02, 0x58, 0xd0, 0x27, 0x39, 0x5f, 0xbd } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.7", + /* Message */ + 8, + { 0x04, 0xed, 0xd8, 0x3c, 0x65, 0x65, 0x6a, 0x01 } +, + /* Seed */ + 117, + { 0x88, 0xf9, 0xa2, 0x71, 0x97, 0xf9, 0xf2, 0x57, 0xfa, 0x81, 0xc0, 0xe3, 0x05, 0x90, 0xb7, 0x3e, 0x9e, 0x11, 0xc7, 0x6b, 0xc8, 0x9e, 0x08, 0x53, 0x6b, 0x4b, 0x64, 0xa2, 0x50, 0x6a, 0xeb, 0x33, 0xb4, 0x50, 0x74, 0x73, 0x08, 0x09, 0xa0, 0x5c, 0x45, 0xb9, 0xbc, 0x95, 0x71, 0x73, 0x69, 0xcf, 0x92, 0xc1, 0xbf, 0x98, 0x6e, 0x53, 0xba, 0x11, 0x23, 0x83, 0x30, 0xfd, 0xc4, 0xe0, 0x5e, 0xa1, 0x07, 0x33, 0x4a, 0xb3, 0x11, 0x06, 0xae, 0xbd, 0x9c, 0x6c, 0x29, 0xe5, 0x01, 0xa5, 0x7d, 0x99, 0x7c, 0x01, 0xbb, 0xc1, 0x01, 0x0b, 0xd5, 0x2f, 0x05, 0x38, 0xb9, 0x51, 0x59, 0xf3, 0x91, 0x32, 0x0d, 0xe6, 0xdb, 0x23, 0xd8, 0x16, 0x2c, 0xf1, 0x46, 0x58, 0x4c, 0x6e, 0x07, 0x6c, 0x4e, 0xae, 0x86, 0x20, 0x72, 0xeb, 0x5b } +, + /* Encryption */ + 128, + { 0x79, 0x1b, 0x37, 0x91, 0x48, 0xa8, 0x3a, 0x03, 0x4d, 0x31, 0x2a, 0x82, 0xbb, 0xb3, 0x7b, 0x11, 0x1b, 0x40, 0xbc, 0xf6, 0xa3, 0x37, 0xfd, 0xe2, 0x89, 0xb0, 0x8e, 0x07, 0x2e, 0x44, 0x03, 0x19, 0x73, 0xff, 0x9d, 0x0c, 0x27, 0xf7, 0x0d, 0x64, 0xa8, 0xea, 0xfc, 0x6e, 0xb5, 0xf8, 0xeb, 0x4e, 0x52, 0xe2, 0xc4, 0x19, 0x7e, 0xcf, 0xa5, 0x45, 0xed, 0x63, 0xae, 0x9a, 0x12, 0x83, 0x79, 0xd3, 0xf5, 0x62, 0xa1, 0x8f, 0xe3, 0xad, 0x14, 0x05, 0x27, 0x67, 0xf0, 0x54, 0x1b, 0x90, 0x16, 0x81, 0x85, 0xcb, 0xb7, 0x8d, 0xb6, 0x03, 0x81, 0xc0, 0x92, 0xbc, 0x23, 0xe1, 0xaa, 0x05, 0xb4, 0x08, 0x92, 0xf9, 0xa1, 0x16, 0xe6, 0x25, 0xcb, 0x14, 0x8b, 0x56, 0x07, 0x42, 0xcc, 0x12, 0x78, 0xc4, 0xd2, 0x1a, 0x4a, 0x7d, 0x37, 0xf6, 0x98, 0x2a, 0xee, 0x27, 0xf2, 0xa4, 0xc0, 0xc5, 0x73, 0xd2 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.8", + /* Message */ + 25, + { 0x3f, 0x7e, 0xea, 0x78, 0x1b, 0x77, 0xd8, 0x5f, 0xe3, 0x71, 0xb3, 0xe9, 0x37, 0x3e, 0x7b, 0x69, 0x21, 0x7d, 0x31, 0x50, 0xa0, 0x2d, 0x89, 0x58, 0xde } +, + /* Seed */ + 100, + { 0x49, 0x99, 0xc6, 0x4c, 0xbf, 0xa3, 0x85, 0x24, 0xad, 0xca, 0xb6, 0x6f, 0x64, 0x45, 0x4d, 0x36, 0xfb, 0xfc, 0xb2, 0x98, 0x6e, 0x1f, 0xa4, 0x75, 0x3a, 0x0e, 0x03, 0x88, 0x9f, 0xf0, 0x6e, 0xe1, 0x60, 0x0e, 0xee, 0x23, 0xbe, 0x53, 0xa9, 0x74, 0x42, 0xb4, 0x2c, 0x69, 0x62, 0x18, 0x66, 0x63, 0x2e, 0x4a, 0x6b, 0x6a, 0x1c, 0x71, 0x05, 0x73, 0x26, 0x1d, 0x71, 0xf3, 0x8a, 0xbf, 0x9e, 0x52, 0x49, 0xdd, 0xc8, 0xe1, 0xb7, 0x7b, 0x3f, 0x12, 0x6b, 0xa0, 0x88, 0x15, 0xc4, 0xfe, 0x63, 0x31, 0x4f, 0x9b, 0x9e, 0x8e, 0x7a, 0x40, 0xc7, 0xfc, 0x72, 0x86, 0x25, 0x20, 0xed, 0x49, 0xd4, 0x12, 0x59, 0xab, 0x2e, 0x0c } +, + /* Encryption */ + 128, + { 0x74, 0xfd, 0x8b, 0x98, 0x56, 0xd7, 0x57, 0x6e, 0x0f, 0x12, 0x87, 0xe0, 0xe9, 0x08, 0x5a, 0x38, 0x01, 0xe6, 0xb6, 0x77, 0x4d, 0xb7, 0x33, 0x54, 0x1d, 0xeb, 0xd3, 0x9e, 0x72, 0xcf, 0xa8, 0x29, 0x1f, 0xec, 0x27, 0x01, 0x8c, 0x9f, 0x53, 0x05, 0xa4, 0x4c, 0xcb, 0x5a, 0x3c, 0xb5, 0x91, 0xfe, 0xd2, 0xe6, 0xa1, 0xd1, 0xd8, 0x5c, 0xaa, 0xa7, 0x4d, 0xc2, 0x37, 0x59, 0xd6, 0x66, 0x5a, 0x45, 0x70, 0xa6, 0x37, 0xf3, 0xab, 0x30, 0x4b, 0x76, 0x61, 0x31, 0x3b, 0x96, 0x71, 0x3c, 0x7b, 0x7e, 0x49, 0x77, 0x31, 0x33, 0xdd, 0x5d, 0x4e, 0xf9, 0xd2, 0x9a, 0x1a, 0xf7, 0x12, 0x00, 0x15, 0x02, 0x8d, 0xaa, 0xb3, 0xdf, 0x04, 0x2c, 0x56, 0x26, 0x20, 0xaa, 0x49, 0xd2, 0xc0, 0x14, 0x41, 0x4d, 0xfb, 0x15, 0x77, 0xd7, 0x19, 0xa9, 0x58, 0x82, 0x64, 0x71, 0x2d, 0xe3, 0xbf, 0x4a, 0x76, 0x79 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.9", + /* Message */ + 47, + { 0xa3, 0x85, 0x08, 0xd9, 0x46, 0x0c, 0x63, 0xf4, 0x15, 0x81, 0xa8, 0x86, 0x9a, 0x75, 0x82, 0x4b, 0x14, 0xf5, 0xc6, 0x50, 0x32, 0x29, 0x99, 0xdc, 0x41, 0x13, 0x50, 0xd0, 0xd4, 0xe8, 0x62, 0x4f, 0xf0, 0x9c, 0xeb, 0x00, 0xd3, 0xbe, 0xdc, 0x5d, 0x76, 0x2a, 0x40, 0xc9, 0x39, 0x80, 0x04 } +, + /* Seed */ + 78, + { 0x6a, 0x0a, 0x28, 0x8a, 0x1e, 0x67, 0x43, 0x0c, 0x66, 0x6a, 0xeb, 0xea, 0x44, 0xb5, 0x82, 0xa9, 0x09, 0x69, 0xcc, 0x01, 0xe9, 0x0a, 0xae, 0x10, 0x53, 0xce, 0x55, 0xee, 0xb9, 0x87, 0x9b, 0xcc, 0x62, 0x25, 0x39, 0x15, 0xe9, 0x22, 0xf1, 0x09, 0x66, 0x67, 0xbd, 0xa0, 0x2a, 0x14, 0xe7, 0x07, 0x47, 0xb3, 0x59, 0x35, 0x24, 0xc2, 0x84, 0x85, 0x47, 0xd2, 0x11, 0x4d, 0x1d, 0x0c, 0xdc, 0xb9, 0x7e, 0xb4, 0xdf, 0x45, 0x5b, 0xba, 0xc9, 0xb0, 0xcc, 0x29, 0x08, 0x39, 0xb7, 0x3a } +, + /* Encryption */ + 128, + { 0xa6, 0x77, 0x57, 0x80, 0x8f, 0x5a, 0xbd, 0xc8, 0x1e, 0xdb, 0x7f, 0x69, 0x2f, 0x9f, 0xb8, 0x52, 0xf1, 0xa1, 0x66, 0x1c, 0x4a, 0x00, 0x98, 0x05, 0xc4, 0x4b, 0x21, 0x6c, 0xd3, 0xb1, 0x32, 0x2b, 0xbb, 0x25, 0xd1, 0x45, 0x8e, 0x31, 0xb0, 0xf0, 0x7d, 0x65, 0x50, 0x57, 0x59, 0xc4, 0xb4, 0x14, 0x7f, 0x23, 0xcb, 0xee, 0x2a, 0xf4, 0xa1, 0xa5, 0x93, 0x8a, 0x06, 0x8c, 0xe9, 0xc5, 0x32, 0x3f, 0xf5, 0x3f, 0x4b, 0x39, 0x2e, 0x12, 0x50, 0xd0, 0x37, 0xb3, 0x1e, 0x62, 0x81, 0xdc, 0xdf, 0xb9, 0x6b, 0xf4, 0xbf, 0xea, 0xa1, 0x47, 0xf0, 0x96, 0xc7, 0x84, 0xc9, 0x2f, 0x4a, 0xc5, 0x70, 0x91, 0x12, 0x28, 0x02, 0x50, 0x29, 0xc3, 0xb5, 0x23, 0x30, 0x3f, 0xe8, 0x22, 0x7e, 0x8b, 0x2c, 0xc0, 0xef, 0x15, 0x70, 0x14, 0xcb, 0x67, 0x31, 0xaa, 0xc0, 0x9b, 0xfe, 0x6f, 0xfa, 0x18, 0xea, 0xf6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.10", + /* Message */ + 28, + { 0xf7, 0x84, 0x05, 0x23, 0x6a, 0x9e, 0xb5, 0x57, 0xaa, 0xce, 0xc6, 0x00, 0x7d, 0xbc, 0x4c, 0x0e, 0xde, 0x78, 0xed, 0x12, 0xb0, 0x4c, 0x82, 0x88, 0x8a, 0x82, 0xc2, 0x13 } +, + /* Seed */ + 97, + { 0x86, 0xf0, 0x72, 0x3b, 0x31, 0x68, 0xe2, 0xae, 0xac, 0xe9, 0xec, 0x2e, 0x95, 0xfd, 0xa6, 0xe6, 0xd6, 0xfc, 0x8d, 0x62, 0x94, 0x55, 0x65, 0x66, 0x39, 0x9d, 0x73, 0x11, 0xe7, 0x99, 0xfa, 0xa9, 0xb1, 0xee, 0x1f, 0x03, 0x2a, 0xb2, 0xe5, 0x34, 0xa9, 0x1f, 0xbc, 0xd0, 0x7c, 0x8a, 0x7d, 0x04, 0xa9, 0xb4, 0x85, 0xf3, 0x1e, 0x07, 0x23, 0xfd, 0x29, 0xeb, 0x21, 0x88, 0x06, 0x9d, 0x9b, 0xbd, 0x76, 0x29, 0xdc, 0x6e, 0x3f, 0xc8, 0x9b, 0xe6, 0x04, 0xbc, 0xf0, 0x0c, 0x52, 0xfa, 0x8e, 0x1d, 0x6c, 0x62, 0x55, 0x5f, 0xd1, 0xf6, 0x0c, 0xec, 0x02, 0xd4, 0xd9, 0x61, 0xd8, 0x28, 0xda, 0xbc, 0x4a } +, + /* Encryption */ + 128, + { 0x6e, 0x8d, 0x2f, 0xb0, 0xb2, 0xee, 0xf8, 0x2f, 0xc1, 0x10, 0xce, 0xe0, 0xa9, 0xd3, 0x84, 0x2f, 0x2a, 0x05, 0x8a, 0x24, 0x40, 0x7f, 0xa1, 0x1b, 0xa9, 0x05, 0xd1, 0xaa, 0x50, 0xe8, 0xcc, 0x12, 0xde, 0xcc, 0x07, 0x3d, 0xbd, 0x08, 0xa8, 0xc7, 0x05, 0x18, 0xef, 0x25, 0xdb, 0x96, 0xfd, 0xa2, 0x41, 0x1c, 0xca, 0x08, 0x72, 0x87, 0x88, 0x95, 0x6f, 0x73, 0xdf, 0xa1, 0x20, 0xe0, 0xea, 0x60, 0x5b, 0xff, 0xc9, 0x3b, 0x43, 0xa4, 0x41, 0xa4, 0x3d, 0x0e, 0xaa, 0x3f, 0xf0, 0x73, 0xe6, 0x98, 0x2e, 0xef, 0x52, 0x96, 0x39, 0x06, 0x07, 0xe2, 0x5a, 0x58, 0x8a, 0x39, 0x82, 0x55, 0xba, 0x00, 0x5a, 0x48, 0x5e, 0x6e, 0x73, 0x2e, 0x3a, 0x19, 0x20, 0xcd, 0x43, 0xa3, 0x90, 0xfb, 0x66, 0xd5, 0x42, 0x8d, 0xfd, 0x62, 0x89, 0x74, 0xb8, 0xaf, 0xf2, 0xf0, 0x60, 0x2d, 0xa5, 0x78, 0xd6, 0x25 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.11", + /* Message */ + 40, + { 0x56, 0x1d, 0x27, 0xc1, 0xd3, 0xf6, 0xd5, 0xd1, 0xa6, 0x43, 0xaa, 0x47, 0xe5, 0x5d, 0x78, 0xeb, 0x00, 0xf3, 0x2d, 0x42, 0x89, 0x6a, 0x34, 0xe0, 0xc1, 0xd7, 0x1b, 0xc3, 0xa5, 0x45, 0x7c, 0x92, 0x05, 0xbe, 0xd1, 0x3b, 0x98, 0x4c, 0x52, 0x59 } +, + /* Seed */ + 85, + { 0x98, 0x17, 0x6e, 0x1d, 0x67, 0xa2, 0x46, 0x2f, 0x5d, 0xc1, 0xbf, 0xa6, 0xe0, 0x75, 0x95, 0x42, 0x10, 0x4a, 0xc1, 0x48, 0x11, 0xd3, 0x18, 0x79, 0x38, 0x25, 0x04, 0x55, 0xc6, 0x5e, 0x4a, 0xaa, 0x76, 0x32, 0xbd, 0x2d, 0x1d, 0x75, 0x2e, 0x1f, 0x34, 0xc5, 0x3c, 0xab, 0x26, 0x76, 0x76, 0xa7, 0x8c, 0x10, 0xc9, 0x98, 0xe7, 0x73, 0xfd, 0x8f, 0xfe, 0x35, 0xc8, 0x67, 0xc4, 0x43, 0xbe, 0xf7, 0x98, 0x65, 0xaa, 0x2d, 0xa2, 0x91, 0x5a, 0x85, 0xc7, 0x02, 0x63, 0x23, 0x69, 0x3e, 0x45, 0x4d, 0x8a, 0xb3, 0x2a, 0x77, 0x15 } +, + /* Encryption */ + 128, + { 0x0b, 0xc0, 0x47, 0x83, 0xc6, 0x92, 0x44, 0x7a, 0x3d, 0xe6, 0x1f, 0x53, 0xb7, 0x2f, 0x7a, 0xa4, 0x10, 0x31, 0x6d, 0xd5, 0x09, 0xa6, 0xf4, 0x9e, 0x3a, 0xba, 0x56, 0xad, 0x1f, 0xf8, 0x6e, 0xbe, 0x9e, 0x63, 0x66, 0xe1, 0x7e, 0x51, 0x45, 0x00, 0x76, 0xbe, 0xa3, 0x71, 0xd4, 0xc6, 0x89, 0xcd, 0x61, 0x49, 0x5c, 0xd8, 0xfa, 0x29, 0xc0, 0xe8, 0x7b, 0x6d, 0xbf, 0xa8, 0xe3, 0x86, 0xc2, 0xe8, 0x20, 0xe4, 0xc7, 0x42, 0xa4, 0x87, 0xe8, 0x9b, 0x27, 0x5a, 0x21, 0x86, 0xe2, 0x38, 0x40, 0xbe, 0x9c, 0x02, 0x52, 0x7b, 0xa7, 0x17, 0xe9, 0xe6, 0x0b, 0x5b, 0xf4, 0x17, 0x71, 0x1d, 0xf3, 0x4d, 0x7b, 0x8e, 0x2d, 0x12, 0xbc, 0xeb, 0x85, 0x93, 0x85, 0xfa, 0x00, 0x1d, 0x4b, 0x4b, 0xff, 0xbb, 0xc0, 0xed, 0xef, 0xbd, 0x40, 0x02, 0x41, 0x84, 0x68, 0xc5, 0x66, 0xfd, 0xf6, 0xb8, 0x35, 0x09 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.12", + /* Message */ + 45, + { 0xeb, 0x5f, 0x8c, 0x0d, 0xc9, 0xd9, 0x01, 0x06, 0x1b, 0x82, 0xae, 0xff, 0x8d, 0x67, 0xd8, 0xbf, 0xfc, 0x0c, 0x04, 0x7e, 0xcc, 0x4a, 0xa3, 0x46, 0xb2, 0x3b, 0xdb, 0xa6, 0x2a, 0x87, 0xe9, 0xdc, 0x77, 0x0b, 0x11, 0x69, 0x5f, 0xbf, 0x19, 0x02, 0xf2, 0x4b, 0x66, 0xce, 0xab } +, + /* Seed */ + 80, + { 0x74, 0x82, 0x77, 0x0f, 0x3c, 0xf5, 0x7e, 0xdb, 0x81, 0x40, 0xeb, 0xc3, 0x3a, 0x02, 0x82, 0x45, 0xee, 0x06, 0x48, 0x52, 0x06, 0x89, 0xa5, 0x0e, 0x33, 0xf5, 0xf4, 0x67, 0xf6, 0xd1, 0xe4, 0x32, 0x4e, 0x1c, 0x50, 0xc8, 0x99, 0xe5, 0xad, 0x2c, 0x46, 0xc9, 0x7f, 0x81, 0x20, 0xd1, 0xc7, 0x22, 0x39, 0xd6, 0xa8, 0x2d, 0x8f, 0x8e, 0xbc, 0x80, 0xb9, 0x73, 0xee, 0xa8, 0xc5, 0x45, 0x69, 0x29, 0x50, 0x45, 0x14, 0xb4, 0xb1, 0x56, 0x62, 0x84, 0x4f, 0x29, 0x50, 0x62, 0xf2, 0x1e, 0xbd, 0x92 } +, + /* Encryption */ + 128, + { 0xb8, 0x40, 0x43, 0x54, 0xa3, 0x81, 0xb7, 0xc2, 0xab, 0xe5, 0xf7, 0x28, 0x25, 0xf3, 0xd3, 0x15, 0xbd, 0xac, 0xe6, 0xc3, 0xcf, 0xbd, 0x88, 0xb8, 0x97, 0x68, 0x61, 0x20, 0x05, 0x19, 0x7c, 0x61, 0x66, 0x38, 0x83, 0xf2, 0xc2, 0x57, 0x4f, 0x99, 0x5e, 0xa6, 0xf9, 0x4e, 0xb3, 0x4f, 0x27, 0x68, 0x62, 0xb3, 0x3f, 0x58, 0xa8, 0x83, 0x92, 0x23, 0x70, 0x6b, 0xe1, 0xc1, 0xff, 0x47, 0x23, 0x05, 0xf1, 0x1b, 0xa9, 0x56, 0x2a, 0x0e, 0xb0, 0x12, 0xf1, 0xaa, 0xf8, 0x5c, 0x22, 0xe8, 0x8f, 0x2f, 0xdf, 0xea, 0xff, 0x86, 0x33, 0xd3, 0xcf, 0xeb, 0x5f, 0x76, 0x4f, 0x42, 0x28, 0x92, 0x0d, 0xe3, 0x0c, 0x6b, 0xde, 0x2c, 0xb4, 0xe8, 0xf0, 0x3d, 0x90, 0xed, 0x54, 0x8f, 0x64, 0x85, 0x00, 0x35, 0x1a, 0x5f, 0x41, 0xdf, 0x74, 0xad, 0x65, 0xe8, 0xc3, 0xbe, 0xe9, 0x50, 0x5a, 0x7d, 0x70, 0xe1 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.13", + /* Message */ + 48, + { 0x5a, 0x7f, 0x0e, 0xae, 0xba, 0xe4, 0x9c, 0xf5, 0x7c, 0x47, 0x5a, 0x6d, 0xa6, 0x79, 0x43, 0xa7, 0xd3, 0x04, 0x6e, 0x3f, 0x7c, 0x7d, 0x50, 0xb0, 0x9a, 0x80, 0x98, 0xb5, 0x44, 0x69, 0x39, 0x68, 0x93, 0xcf, 0xc0, 0xb2, 0xf0, 0x8f, 0x6c, 0x2b, 0xff, 0x23, 0x50, 0x51, 0x57, 0x5e, 0x6e, 0x56 } +, + /* Seed */ + 77, + { 0xfb, 0x08, 0x48, 0x86, 0xdb, 0x37, 0x98, 0xd2, 0xb5, 0xbb, 0x35, 0xa3, 0xb1, 0xd3, 0xaf, 0x4f, 0xdf, 0xc0, 0x45, 0x6c, 0xbc, 0x79, 0x7b, 0x96, 0x40, 0xd8, 0xc4, 0x4a, 0x0e, 0x03, 0x4e, 0x40, 0x37, 0x2b, 0x34, 0xfc, 0x7c, 0x1e, 0x8b, 0x66, 0x01, 0x1b, 0x4e, 0xcd, 0xfa, 0xec, 0x6e, 0xe4, 0xcd, 0xc8, 0x28, 0xcb, 0x1a, 0xb4, 0x91, 0x27, 0x4a, 0xc1, 0xe3, 0x9f, 0x67, 0x58, 0x7a, 0x55, 0x47, 0x67, 0x09, 0xb4, 0x02, 0x3f, 0xc5, 0x69, 0xcb, 0xe8, 0xb4, 0xfd, 0x4b } +, + /* Encryption */ + 128, + { 0x07, 0x78, 0x4e, 0xcb, 0x8c, 0xc5, 0xba, 0x02, 0xd2, 0x07, 0xba, 0xb0, 0x55, 0xc0, 0xe5, 0x5d, 0x10, 0xa9, 0xb9, 0x42, 0x70, 0xcc, 0xa2, 0x50, 0xee, 0x75, 0xfa, 0x1b, 0x5a, 0xe1, 0x90, 0xb3, 0x3b, 0x96, 0x96, 0xeb, 0x2e, 0xc9, 0x72, 0xb2, 0x6a, 0x0e, 0x94, 0x23, 0xaf, 0x16, 0xaa, 0x37, 0x89, 0x17, 0x62, 0x76, 0x06, 0x0a, 0x76, 0x40, 0x03, 0x21, 0x11, 0x74, 0x82, 0x96, 0x34, 0x03, 0x4f, 0x97, 0x12, 0xc9, 0x17, 0x10, 0x17, 0xf2, 0xfb, 0x21, 0x3f, 0x25, 0xc1, 0x46, 0xc2, 0x65, 0x1f, 0x89, 0x44, 0x0c, 0xa5, 0x36, 0xe5, 0x33, 0xe3, 0x05, 0xcc, 0x6b, 0x01, 0x13, 0x39, 0x8f, 0x61, 0xb4, 0x63, 0xb0, 0x73, 0xe1, 0xbe, 0x05, 0x07, 0x3e, 0x9d, 0x64, 0xbc, 0xae, 0xea, 0x54, 0x44, 0xb8, 0x20, 0xc6, 0xab, 0xf3, 0x46, 0x54, 0x30, 0xff, 0x4d, 0xe4, 0xa8, 0xbc, 0x0e, 0x75 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.14", + /* Message */ + 47, + { 0xf9, 0x1c, 0x71, 0xaf, 0x5a, 0xea, 0xca, 0xe1, 0x79, 0xe1, 0x6e, 0x87, 0xc9, 0x02, 0x3b, 0xa9, 0x4d, 0x84, 0xd7, 0x51, 0x6c, 0xec, 0x6c, 0x39, 0x89, 0x80, 0x1f, 0xb3, 0xe7, 0xad, 0xd0, 0x64, 0xbd, 0xdf, 0x92, 0x8b, 0x50, 0x00, 0x94, 0x0b, 0xbd, 0xe5, 0x39, 0xd6, 0x23, 0x37, 0x9c } +, + /* Seed */ + 78, + { 0xde, 0xb2, 0x60, 0x25, 0x8b, 0xe2, 0xc8, 0x53, 0x35, 0x21, 0x57, 0xb0, 0x65, 0x26, 0xb1, 0x43, 0xba, 0x13, 0x3c, 0x4f, 0x49, 0xbf, 0x3d, 0xf2, 0xc0, 0x50, 0xec, 0xb2, 0xc9, 0xca, 0x32, 0x53, 0x11, 0xb3, 0xc3, 0xe3, 0xd8, 0x8d, 0xf6, 0xc2, 0x4a, 0x89, 0x4e, 0xab, 0x63, 0x74, 0x5b, 0x62, 0x53, 0xe3, 0xc4, 0x6b, 0xca, 0x17, 0x1a, 0x26, 0xa4, 0xf2, 0xfc, 0x0a, 0xb6, 0x2b, 0x8a, 0x2e, 0x63, 0xa0, 0x18, 0xeb, 0x47, 0x01, 0x8c, 0xab, 0x95, 0x1f, 0x59, 0xf0, 0x20, 0x3a } +, + /* Encryption */ + 128, + { 0x0d, 0xff, 0xff, 0x51, 0x97, 0x10, 0xc9, 0xea, 0xdc, 0x53, 0x3b, 0x10, 0x8a, 0x4c, 0x29, 0x74, 0xfe, 0x53, 0x18, 0x91, 0xa3, 0x41, 0x07, 0xa6, 0x74, 0x27, 0x93, 0x5b, 0xa7, 0x20, 0xcd, 0xc6, 0xf6, 0xee, 0x02, 0x9a, 0x1b, 0x03, 0x68, 0x61, 0xdb, 0x14, 0x04, 0xc5, 0x86, 0x49, 0x90, 0x54, 0x1f, 0xa2, 0x42, 0x13, 0x01, 0xa7, 0xb2, 0x48, 0xcb, 0x11, 0xf3, 0x65, 0xb6, 0xa4, 0xaa, 0x94, 0x6f, 0x22, 0x31, 0xcb, 0xb1, 0x47, 0x32, 0xb0, 0x1a, 0xa4, 0xa6, 0x0b, 0xcb, 0xe5, 0x20, 0xec, 0x6c, 0x38, 0x53, 0xa6, 0x95, 0x8a, 0x93, 0xc5, 0xb6, 0x8b, 0x85, 0xd4, 0xbc, 0x3d, 0x84, 0x15, 0xef, 0x8b, 0x1d, 0x4f, 0x63, 0x03, 0x8f, 0x4d, 0x94, 0x2c, 0xa6, 0xbc, 0x7a, 0x38, 0x25, 0x1f, 0x15, 0xa4, 0xe3, 0x3b, 0x18, 0x9c, 0x25, 0x0b, 0xcf, 0xbc, 0x03, 0x15, 0x6e, 0x4f, 0x92, 0x11 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.15", + /* Message */ + 28, + { 0x07, 0x90, 0xc0, 0x81, 0xf3, 0x61, 0xc9, 0x5b, 0x59, 0xd5, 0x27, 0xd3, 0xcb, 0x50, 0x71, 0x0e, 0x66, 0xe2, 0x72, 0x59, 0x50, 0x10, 0x25, 0xed, 0x3f, 0x20, 0xf3, 0x0c } +, + /* Seed */ + 97, + { 0xfc, 0xfc, 0x2d, 0x56, 0xcb, 0x92, 0x6d, 0x90, 0x5d, 0xb3, 0x6e, 0x1e, 0x2e, 0xff, 0x1f, 0xbb, 0x75, 0xd6, 0x53, 0x51, 0x7f, 0x59, 0xe8, 0x6f, 0x71, 0xbc, 0x4b, 0xc5, 0x57, 0x26, 0xf0, 0x88, 0xb8, 0x21, 0x62, 0x44, 0x83, 0xb3, 0xe2, 0x9a, 0xc2, 0x1a, 0x49, 0xbd, 0x85, 0x91, 0x34, 0x90, 0x8e, 0x6c, 0x0e, 0xc1, 0xa0, 0xdc, 0x80, 0x79, 0x93, 0x01, 0x44, 0x12, 0x0d, 0x1f, 0x6b, 0xf9, 0x3b, 0xc6, 0x27, 0xb9, 0x99, 0x69, 0xb2, 0xaf, 0xe2, 0x1a, 0x7d, 0xe1, 0x0d, 0x96, 0xf6, 0xef, 0x43, 0xc5, 0x67, 0xb5, 0xe2, 0x38, 0x38, 0x5c, 0xc1, 0x1a, 0x5a, 0x2a, 0x13, 0xe1, 0x78, 0x55, 0x8b } +, + /* Encryption */ + 128, + { 0x7f, 0x0e, 0x6b, 0x34, 0x2d, 0x6a, 0x13, 0x54, 0x66, 0xbe, 0x41, 0x73, 0x38, 0x1a, 0xc0, 0x4a, 0xba, 0xab, 0x7e, 0x14, 0xfd, 0xcf, 0x51, 0x01, 0x89, 0x87, 0xe9, 0x69, 0x67, 0x16, 0x9a, 0xea, 0x97, 0x78, 0x03, 0xeb, 0xb3, 0x24, 0x2a, 0xe9, 0xad, 0xb4, 0x6f, 0xf5, 0x11, 0x20, 0x93, 0x4b, 0x39, 0x21, 0x46, 0x31, 0xb0, 0x3f, 0x5a, 0xf5, 0xbd, 0xea, 0x1c, 0xac, 0xd3, 0x28, 0xad, 0xdc, 0xd4, 0x0a, 0x3a, 0x29, 0x96, 0x6b, 0xf9, 0x8b, 0xd7, 0xc8, 0xc6, 0xfd, 0x0f, 0x4e, 0x8b, 0x97, 0x2e, 0x2d, 0xa1, 0x0c, 0x6c, 0xc5, 0x52, 0x05, 0x86, 0x7f, 0x39, 0x04, 0xed, 0x60, 0xf5, 0xb5, 0xbe, 0xdf, 0x7c, 0x3b, 0x3c, 0x7d, 0xd5, 0xf3, 0x87, 0x54, 0x8f, 0x40, 0x05, 0x67, 0x02, 0xea, 0x72, 0x01, 0x76, 0xdc, 0xe2, 0x06, 0xd4, 0x13, 0xd7, 0x42, 0x3f, 0x94, 0x3f, 0xcd, 0xf6, 0x39 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.16", + /* Message */ + 64, + { 0x93, 0xc4, 0x1a, 0x1a, 0xdd, 0xa8, 0xf6, 0x93, 0x60, 0xf4, 0x1a, 0x58, 0xec, 0xa0, 0xb5, 0x5e, 0xcb, 0x37, 0xa6, 0xa9, 0x00, 0xfb, 0xc7, 0xda, 0xcd, 0x9c, 0xa3, 0x99, 0xc2, 0x3d, 0x31, 0x72, 0x61, 0x53, 0x77, 0xac, 0x0c, 0xc6, 0xb0, 0xed, 0x43, 0xbf, 0x59, 0x7f, 0x21, 0xcd, 0x25, 0x9d, 0x8f, 0x80, 0x88, 0x7b, 0x15, 0x9d, 0x96, 0xd6, 0x61, 0x61, 0xd5, 0x58, 0x9b, 0x95, 0xf1, 0xfe } +, + /* Seed */ + 61, + { 0x99, 0x1a, 0x2a, 0x7c, 0x06, 0x1c, 0x23, 0xa8, 0xeb, 0xc9, 0x48, 0x9a, 0xbc, 0x1b, 0x4a, 0x64, 0xa5, 0xd4, 0xe8, 0x38, 0xd9, 0xfc, 0xba, 0x42, 0x88, 0xc0, 0x1f, 0xea, 0xd6, 0x6d, 0x59, 0xf4, 0x96, 0x36, 0xe4, 0xa8, 0xd7, 0x52, 0x4c, 0xb8, 0x9d, 0x7a, 0xdc, 0x7a, 0xf3, 0xf6, 0x1a, 0xe6, 0xb3, 0x9b, 0x58, 0x8f, 0xb7, 0x7e, 0xb7, 0x02, 0x23, 0x62, 0xff, 0xd2, 0x6b } +, + /* Encryption */ + 128, + { 0x7e, 0x54, 0xa4, 0x32, 0xf5, 0x25, 0xc5, 0x23, 0x33, 0xab, 0xe3, 0xbb, 0x45, 0x48, 0x7e, 0x03, 0x9a, 0xf9, 0x4d, 0xd3, 0xef, 0xc3, 0x58, 0x44, 0xdd, 0x8e, 0x83, 0x5e, 0xe1, 0x00, 0x61, 0x78, 0xe2, 0x4d, 0xcd, 0x19, 0xfc, 0x07, 0x66, 0x7b, 0x4a, 0x34, 0xf3, 0xbd, 0x77, 0x1d, 0x09, 0xa7, 0xe2, 0x9f, 0x8c, 0xa1, 0x7e, 0x88, 0xd0, 0x29, 0xb9, 0x0d, 0xdb, 0x5f, 0x28, 0x13, 0xbe, 0x99, 0x00, 0x0d, 0x59, 0xf5, 0x43, 0x2c, 0x46, 0x6a, 0x84, 0x28, 0x75, 0x77, 0x20, 0x4b, 0xf7, 0x65, 0x97, 0x39, 0x27, 0x69, 0x98, 0x30, 0x57, 0x47, 0x66, 0x7f, 0xaf, 0xd8, 0x02, 0x9c, 0xdc, 0xbb, 0x59, 0x18, 0x39, 0x3c, 0x2c, 0xfc, 0xe4, 0xd8, 0x4a, 0x92, 0x20, 0xea, 0x3e, 0x38, 0x19, 0x72, 0x53, 0x36, 0xf2, 0x5f, 0xee, 0x8e, 0x08, 0x5d, 0xeb, 0xed, 0x33, 0x32, 0xd5, 0xdd, 0xf1, 0xee } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.17", + /* Message */ + 60, + { 0x9e, 0x2a, 0x7b, 0x37, 0x74, 0xb1, 0x1e, 0x62, 0xb6, 0x49, 0x0b, 0x56, 0x51, 0xa0, 0xc1, 0x8e, 0x09, 0x2e, 0x9f, 0xab, 0x8b, 0x22, 0x84, 0xae, 0x46, 0x43, 0xbe, 0xc3, 0x6b, 0x26, 0x5e, 0x5b, 0xa3, 0xc5, 0x1a, 0xc3, 0x85, 0xb2, 0xc7, 0x3d, 0x22, 0x0b, 0x2d, 0xc2, 0xe1, 0x0b, 0x0d, 0x69, 0x0f, 0x67, 0x94, 0x5a, 0x0c, 0x42, 0xb3, 0xbd, 0x09, 0xd0, 0xa8, 0xa7 } +, + /* Seed */ + 65, + { 0xa1, 0x8b, 0xfb, 0x74, 0xf6, 0xde, 0xbc, 0xed, 0xcf, 0xb4, 0x7c, 0x7d, 0x5d, 0xbf, 0x10, 0x6e, 0x77, 0x4d, 0x7e, 0xf6, 0x63, 0x8e, 0xc3, 0x82, 0x18, 0x69, 0xcd, 0x2e, 0xd6, 0x2d, 0xd5, 0x32, 0x5f, 0x4e, 0x57, 0x33, 0xb8, 0xbf, 0xd5, 0xfa, 0xfc, 0x43, 0xe4, 0x16, 0x4e, 0x78, 0xd4, 0x38, 0x99, 0x4d, 0x85, 0x33, 0x7d, 0x7f, 0x0d, 0x38, 0xf0, 0xea, 0x3b, 0xa3, 0x7f, 0x4f, 0x41, 0xb6, 0xa7 } +, + /* Encryption */ + 128, + { 0x18, 0xc8, 0x8a, 0xee, 0x25, 0x36, 0xd9, 0x42, 0xf7, 0x62, 0x2a, 0x64, 0x4f, 0xad, 0x6f, 0xec, 0xd3, 0x32, 0x28, 0xc7, 0xae, 0xa0, 0xca, 0xda, 0x0e, 0x53, 0x1f, 0x4c, 0xcb, 0xf1, 0xc1, 0xf2, 0x69, 0xcc, 0x95, 0x86, 0x29, 0xa4, 0x3b, 0x97, 0x52, 0xfc, 0xaf, 0x2b, 0xf9, 0x53, 0xec, 0x9f, 0x7e, 0xf4, 0xbb, 0x0e, 0x62, 0xd1, 0x28, 0xe0, 0xcf, 0x4b, 0xab, 0xe9, 0x2c, 0x6d, 0x92, 0x84, 0x9e, 0x98, 0x38, 0xdd, 0x88, 0xe2, 0xb4, 0x68, 0xbd, 0xce, 0xfc, 0x04, 0xa9, 0xe4, 0xcb, 0x55, 0xe2, 0xa5, 0x18, 0xca, 0x25, 0x9f, 0x9e, 0x81, 0xa4, 0x9f, 0x28, 0xdf, 0x34, 0x76, 0x1f, 0x9d, 0xea, 0x2e, 0x70, 0x59, 0x56, 0x62, 0x62, 0x6c, 0xf9, 0x6a, 0xc0, 0x5a, 0x7c, 0x8b, 0x10, 0x33, 0x33, 0xe9, 0x06, 0xe1, 0x32, 0x63, 0x9b, 0x65, 0xa7, 0x66, 0xf4, 0x09, 0x2c, 0x8c, 0xa0, 0x78 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.18", + /* Message */ + 61, + { 0x0a, 0xc5, 0x2d, 0x40, 0x01, 0xf2, 0x5c, 0x2c, 0x9d, 0xb9, 0x1c, 0xe5, 0x0b, 0xdd, 0xf0, 0xd5, 0x91, 0x9e, 0x19, 0x96, 0x2e, 0x83, 0xb0, 0x7c, 0xb7, 0x9a, 0xdb, 0x00, 0x43, 0x6e, 0x13, 0x66, 0xb0, 0xaa, 0x8f, 0x3f, 0xd1, 0xee, 0x79, 0x6b, 0x23, 0xc8, 0xbc, 0x56, 0x0c, 0xcf, 0xa4, 0xbc, 0xbd, 0xb1, 0xf8, 0x40, 0x4d, 0xd6, 0xf7, 0x55, 0x15, 0x20, 0xd7, 0xd9, 0xe2 } +, + /* Seed */ + 64, + { 0x22, 0xff, 0xdc, 0xfe, 0xc6, 0xf0, 0x6b, 0x1b, 0xbd, 0x14, 0x53, 0x97, 0x70, 0x43, 0xa3, 0x4e, 0xdd, 0xf8, 0x59, 0x4d, 0xa0, 0x22, 0x13, 0x09, 0x14, 0x97, 0x55, 0x42, 0xf2, 0xf0, 0x0e, 0x98, 0xf3, 0x1e, 0x0d, 0xd0, 0xc4, 0x8f, 0x7e, 0xe5, 0xf0, 0x9d, 0x6a, 0x52, 0x71, 0x21, 0xad, 0x23, 0x37, 0x1c, 0x6c, 0xd0, 0xe0, 0x79, 0x0e, 0xb7, 0x30, 0x8b, 0xbb, 0x08, 0x96, 0xdd, 0x59, 0x0d } +, + /* Encryption */ + 128, + { 0xb2, 0x69, 0x57, 0xc5, 0x62, 0x29, 0x4d, 0xe1, 0xf3, 0x93, 0x24, 0xb1, 0xcd, 0x80, 0x3c, 0xfc, 0x39, 0xfc, 0xee, 0x2d, 0x3c, 0x9d, 0x13, 0x79, 0xf8, 0xa1, 0x12, 0x07, 0x9d, 0x69, 0x43, 0x68, 0xf5, 0x55, 0x03, 0xc2, 0x09, 0x4d, 0x98, 0x8a, 0x8a, 0x5b, 0x5a, 0xc5, 0x49, 0xbe, 0x1c, 0xf5, 0x53, 0x16, 0x04, 0x5d, 0xf5, 0xb6, 0xf6, 0x33, 0xa4, 0xef, 0x1e, 0x1f, 0x01, 0x9b, 0xa1, 0xb5, 0x42, 0xbf, 0x0a, 0x87, 0xfa, 0x3e, 0x5c, 0xa3, 0xf6, 0xb6, 0x1c, 0xc8, 0x56, 0x61, 0x28, 0xa0, 0xfa, 0x41, 0x8b, 0x08, 0x25, 0xc9, 0x0e, 0xc2, 0xf1, 0xec, 0x74, 0xe5, 0x87, 0xcd, 0x80, 0x57, 0xd9, 0x52, 0x96, 0x7a, 0xc4, 0x52, 0x1c, 0xcd, 0xbf, 0x63, 0x26, 0xf3, 0x50, 0x93, 0x00, 0x93, 0x82, 0x6d, 0x2e, 0xfa, 0x05, 0x8e, 0xd6, 0x44, 0x15, 0x37, 0x4d, 0xb3, 0x20, 0x48, 0x85, 0xca } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.19", + /* Message */ + 13, + { 0xa8, 0x00, 0x34, 0x62, 0xf8, 0x06, 0xb7, 0xf6, 0x61, 0xfb, 0x66, 0x46, 0x32 } +, + /* Seed */ + 112, + { 0xc7, 0x43, 0xf4, 0xa6, 0xda, 0x03, 0xab, 0x2d, 0xe5, 0xa7, 0x31, 0xcb, 0x88, 0xd8, 0xca, 0x9b, 0x61, 0xc7, 0x31, 0x9a, 0x5f, 0x8b, 0xf9, 0xd2, 0x37, 0x87, 0x7a, 0x05, 0xd0, 0xf3, 0x68, 0xc3, 0x60, 0x8a, 0x05, 0x2a, 0xc6, 0xce, 0x13, 0x73, 0x17, 0x95, 0x47, 0x55, 0x42, 0xea, 0x16, 0xa8, 0x62, 0x91, 0x3d, 0x04, 0x32, 0xf0, 0x8b, 0xd8, 0xc8, 0xb6, 0xff, 0x81, 0x95, 0x69, 0x1f, 0xee, 0x5e, 0xd1, 0x42, 0xfb, 0x9e, 0xca, 0x94, 0x67, 0x52, 0x4b, 0xd3, 0xb5, 0xfa, 0x5a, 0x4a, 0xc6, 0x14, 0x3b, 0x0d, 0x38, 0x25, 0x0a, 0xe6, 0x21, 0xd4, 0x39, 0x90, 0x9c, 0xbe, 0x3a, 0x6b, 0x5c, 0x01, 0xfb, 0xea, 0x2d, 0x7a, 0x3f, 0x1a, 0xe4, 0x1d, 0x61, 0xfd, 0xd6, 0x47, 0x64, 0x14, 0x9f } +, + /* Encryption */ + 128, + { 0xb7, 0x38, 0xe1, 0xc4, 0x29, 0xf8, 0xfc, 0x06, 0x82, 0xfa, 0xad, 0xc8, 0xca, 0x87, 0xed, 0x8f, 0x16, 0xdf, 0x93, 0x0f, 0xaf, 0x43, 0xb1, 0x99, 0x1a, 0xac, 0x71, 0xd8, 0x8f, 0x26, 0x4c, 0x0d, 0x82, 0x9a, 0xc0, 0x3d, 0x23, 0xc2, 0x5f, 0xc5, 0xf3, 0xe8, 0x5d, 0xd3, 0x02, 0xcb, 0x7b, 0x15, 0x33, 0xe6, 0x8c, 0x24, 0x16, 0xc5, 0x1a, 0x79, 0xbb, 0xcc, 0x7c, 0x29, 0xb0, 0x7e, 0x2e, 0x0e, 0x23, 0xc6, 0xf2, 0xdf, 0x0d, 0x07, 0x81, 0x91, 0x7e, 0xba, 0x1a, 0x57, 0x08, 0x62, 0x8e, 0xed, 0x8a, 0x15, 0xb3, 0xb1, 0x84, 0xaf, 0x70, 0x0d, 0x0d, 0xab, 0xb1, 0x4d, 0xf6, 0x0b, 0x09, 0xba, 0xd2, 0x12, 0x7d, 0xf1, 0x80, 0xf4, 0xd6, 0xf7, 0x29, 0x65, 0x87, 0x60, 0xd6, 0x33, 0xc7, 0x77, 0x5a, 0x7b, 0x59, 0x6d, 0x09, 0xd9, 0x03, 0x49, 0x1f, 0x21, 0x09, 0x6c, 0x34, 0xc3, 0x95, 0x3b } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 3.20", + /* Message */ + 2, + { 0xef, 0x32 } +, + /* Seed */ + 123, + { 0x43, 0x99, 0xcb, 0x04, 0x4a, 0x60, 0x07, 0x6d, 0x18, 0xcc, 0xb3, 0x4e, 0x8b, 0x07, 0x8c, 0x81, 0x8e, 0xa7, 0x7f, 0x63, 0xb0, 0xa4, 0x3a, 0xbd, 0xec, 0xc5, 0x77, 0x81, 0x93, 0xa8, 0xbb, 0xba, 0x5d, 0x56, 0xd0, 0xfc, 0x4e, 0x82, 0xa2, 0x11, 0x51, 0x6b, 0xbd, 0xef, 0x44, 0xe7, 0xf4, 0xe7, 0xfe, 0xbb, 0xe1, 0xe1, 0x92, 0x3c, 0x99, 0x9a, 0x7e, 0x96, 0x1c, 0xd6, 0xee, 0x1c, 0x41, 0x6a, 0x85, 0x96, 0xe2, 0x4b, 0x63, 0x83, 0xa4, 0x69, 0x93, 0x5f, 0x33, 0xd1, 0x56, 0xfd, 0x5b, 0xcf, 0xdb, 0xd4, 0x27, 0x46, 0x0d, 0x48, 0x66, 0x83, 0x06, 0x1e, 0x41, 0x05, 0xf3, 0x5b, 0x5e, 0x75, 0x23, 0x20, 0x15, 0x5c, 0x7f, 0x69, 0xad, 0x8e, 0xb4, 0x02, 0xcc, 0x11, 0x06, 0xe0, 0x28, 0x9a, 0x9b, 0x49, 0x65, 0x82, 0x3e, 0x7a, 0x51, 0xcf, 0xe4, 0xd2, 0x6d } +, + /* Encryption */ + 128, + { 0x13, 0x1b, 0x62, 0x5e, 0x86, 0xe6, 0xcd, 0x1e, 0x08, 0xac, 0xf1, 0x95, 0xd9, 0x3c, 0xd3, 0xa0, 0xdc, 0x8b, 0xa9, 0xe2, 0xdc, 0xd6, 0xfc, 0x99, 0x6b, 0xe2, 0x17, 0x24, 0xaf, 0x17, 0x90, 0xb6, 0x88, 0xd7, 0x9d, 0x3e, 0xa9, 0xa9, 0x50, 0x98, 0xca, 0xbb, 0xe8, 0xa5, 0xd4, 0x85, 0x92, 0xe4, 0x74, 0x6b, 0x0e, 0xd2, 0xaf, 0x7c, 0xaf, 0x89, 0xb7, 0xb6, 0x15, 0x2e, 0x38, 0x24, 0xd9, 0x15, 0x89, 0xee, 0xec, 0x33, 0x75, 0xc7, 0x1a, 0x89, 0x97, 0x48, 0x70, 0x3a, 0xcc, 0x1e, 0x8d, 0x1d, 0xe4, 0x71, 0xea, 0x75, 0x28, 0x04, 0x0b, 0x79, 0x5f, 0x29, 0x9e, 0x66, 0x8c, 0xec, 0x9f, 0x5a, 0xf3, 0xeb, 0x48, 0xf9, 0x8c, 0x0d, 0x85, 0x20, 0x67, 0x77, 0x3e, 0x10, 0x1f, 0xa2, 0x4a, 0xeb, 0x6b, 0x40, 0x4d, 0xaf, 0xb4, 0x2e, 0x7a, 0x63, 0xb0, 0x4a, 0x66, 0xbd, 0x0e, 0x9f, 0x9c, 0x94 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 4: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xe9, 0xf2, 0x5e, 0x48, 0x14, 0x0b, 0x5d, 0xcf, 0x46, 0x99, 0xe3, 0x03, 0x7f, 0xa8, 0x34, 0xf0, 0xc7, 0x8b, 0x16, 0x73, 0x5f, 0xf7, 0x9f, 0x6b, 0x18, 0xae, 0x60, 0xb5, 0x18, 0x48, 0xd3, 0x06, 0x99, 0xec, 0x64, 0x6d, 0x85, 0x7f, 0x15, 0x77, 0x0e, 0x2c, 0x7a, 0x0c, 0x0c, 0x90, 0x0f, 0xb6, 0x04, 0x0b, 0x5f, 0x34, 0x48, 0x4e, 0x9c, 0xf5, 0xce, 0xda, 0x23, 0xd5, 0xb2, 0x50, 0xef, 0x93, 0x28, 0x6f, 0x01, 0x1e, 0x9a, 0x5b, 0xf9, 0xe5, 0x42, 0xe5, 0xc9, 0xf4, 0x42, 0xde, 0x54, 0x58, 0xe2, 0x3e, 0x41, 0xd1, 0xd9, 0xcd, 0x9f, 0x0c, 0xe1, 0xcf, 0x20, 0x08, 0xd3, 0xea, 0x4d, 0x80, 0x32, 0xe8, 0x54, 0xcf, 0xfc, 0xdf, 0x5f, 0x69, 0x8d, 0x13, 0x16, 0xe0, 0x29, 0xc4, 0x88, 0xfc, 0xbb, 0x2b, 0xe2, 0x9a, 0x4e, 0x7b, 0xfb, 0x8e, 0x6e, 0x81, 0xd3, 0x42, 0x12, 0x3e, 0xe7, 0x5b } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x45, 0x45, 0x88, 0x68, 0x44, 0x53, 0x27, 0x48, 0x60, 0x49, 0xe1, 0xbf, 0xdf, 0xf5, 0x61, 0x13, 0xa8, 0xaa, 0x45, 0x10, 0x0d, 0xab, 0x07, 0x4f, 0xd1, 0x63, 0x94, 0xec, 0x1a, 0x90, 0x39, 0xb8, 0x1b, 0x2c, 0xb5, 0x81, 0xfe, 0x84, 0xe6, 0x48, 0xb5, 0xf0, 0x32, 0x85, 0x4d, 0xd4, 0xfc, 0x69, 0xf3, 0x61, 0xa0, 0xa3, 0x9d, 0x03, 0x76, 0x13, 0x8c, 0xd7, 0xe7, 0xc3, 0x77, 0x84, 0xe2, 0xa2, 0xf9, 0xd4, 0xf2, 0x66, 0x84, 0xcc, 0x5c, 0xc9, 0xf5, 0x12, 0xba, 0x62, 0x15, 0xeb, 0xd2, 0x32, 0xf9, 0xaa, 0x3d, 0xa4, 0x69, 0xdb, 0x43, 0xda, 0x1c, 0x06, 0x46, 0xe7, 0x5b, 0x33, 0xaa, 0xc5, 0x70, 0x08, 0x1b, 0x5b, 0x2e, 0x96, 0xea, 0xb7, 0x54, 0x6a, 0xcf, 0x93, 0x17, 0x85, 0xaa, 0x2f, 0xd1, 0x82, 0x4c, 0xbe, 0x2c, 0x5f, 0x9b, 0xf5, 0x63, 0x34, 0xec, 0x15, 0x66, 0xd1, 0xcf, 0x45 } +, + /* Prime 1 */ + 64, + { 0xfc, 0xdf, 0x1c, 0x49, 0x35, 0x8a, 0x1a, 0xac, 0x93, 0x88, 0xc4, 0x6c, 0xaa, 0x04, 0x72, 0xfa, 0x35, 0xb2, 0x1b, 0xdf, 0x99, 0xa2, 0x7b, 0xc2, 0xac, 0x65, 0x46, 0x7b, 0x88, 0xd0, 0x16, 0x1f, 0xbc, 0x70, 0xf3, 0xf4, 0xfa, 0x13, 0xa5, 0xf3, 0xa9, 0x8b, 0x59, 0xc0, 0x67, 0xea, 0xbf, 0x19, 0x62, 0x16, 0xa1, 0xb8, 0x9e, 0x20, 0xaf, 0xb2, 0xe5, 0xe5, 0xed, 0xde, 0xae, 0x8e, 0xe1, 0xef } +, + /* Prime 2 */ + 64, + { 0xec, 0xd7, 0x51, 0xd3, 0xd3, 0xf3, 0xb2, 0x08, 0xbd, 0x71, 0x8a, 0xe4, 0x35, 0x5d, 0x23, 0xf9, 0x16, 0xfa, 0x8f, 0xf6, 0x7d, 0xf0, 0x36, 0x61, 0x6b, 0xfd, 0xa7, 0xcb, 0xc8, 0x7a, 0xeb, 0xef, 0xaa, 0x7e, 0xda, 0x69, 0x1f, 0xb9, 0x8f, 0xbb, 0x03, 0x8a, 0x02, 0x07, 0x22, 0x01, 0x3c, 0xa8, 0xee, 0x3d, 0x04, 0x8f, 0x97, 0xba, 0xd2, 0xa2, 0x93, 0x0b, 0xe4, 0xb9, 0x6f, 0xb7, 0x4d, 0x55 } +, + /* Prime exponent 1 */ + 64, + { 0x1d, 0x2f, 0x73, 0x08, 0x50, 0x11, 0x9c, 0x7a, 0x86, 0x9c, 0xa6, 0x6f, 0x14, 0x40, 0x67, 0x34, 0xd1, 0xb5, 0xb8, 0xd9, 0xd9, 0xd5, 0x93, 0x0b, 0x28, 0xf2, 0x97, 0x6b, 0xf2, 0xa2, 0x71, 0xab, 0x40, 0x08, 0x99, 0x5f, 0x90, 0xed, 0x6b, 0x9d, 0xef, 0xd7, 0x91, 0x88, 0x4f, 0x76, 0x1c, 0x90, 0x45, 0x6d, 0xef, 0x44, 0x6b, 0x9b, 0xc2, 0x2b, 0x97, 0xb5, 0x2d, 0xfb, 0x21, 0x92, 0x84, 0x29 } +, + /* Prime exponent 2 */ + 64, + { 0x4d, 0x50, 0x95, 0x03, 0xc3, 0x83, 0x20, 0x31, 0x3e, 0x36, 0x9c, 0x92, 0x96, 0xe1, 0x0a, 0xe7, 0x3b, 0x9b, 0x1b, 0xf7, 0xe9, 0x70, 0xcb, 0x2f, 0xce, 0x63, 0x05, 0xad, 0xbe, 0x8a, 0x72, 0x0e, 0xd0, 0xe7, 0x8c, 0x41, 0x18, 0xfc, 0x28, 0x71, 0x72, 0x5c, 0x51, 0x01, 0x27, 0x16, 0xa4, 0x48, 0xb9, 0x4c, 0xed, 0xfa, 0x3a, 0x1b, 0xe0, 0xba, 0xf5, 0xa9, 0xc2, 0x46, 0xce, 0xb3, 0x55, 0xe9 } +, + /* Coefficient */ + 64, + { 0xbc, 0x15, 0xf4, 0x7c, 0x0b, 0xb6, 0xde, 0x6a, 0x7a, 0x3a, 0x1f, 0xe9, 0x28, 0x89, 0x80, 0x9b, 0x4a, 0x3c, 0x0c, 0xfa, 0x65, 0x0c, 0x2f, 0xec, 0x36, 0xb8, 0x92, 0x85, 0x14, 0x65, 0x47, 0xa5, 0x7d, 0x2b, 0x15, 0x71, 0xac, 0xb9, 0xd3, 0x0a, 0xa7, 0x91, 0xec, 0x97, 0xfd, 0x51, 0xfd, 0xe1, 0xec, 0x26, 0xf5, 0x6b, 0x32, 0x63, 0xda, 0xec, 0x9e, 0x29, 0x2e, 0x9c, 0x17, 0x37, 0x36, 0x4b } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 4.1", + /* Message */ + 29, + { 0xca, 0x24, 0x72, 0x1c, 0x88, 0xe0, 0x47, 0x74, 0xf4, 0x15, 0xb4, 0xc4, 0x6c, 0xa0, 0xfc, 0x26, 0xd5, 0xbb, 0x53, 0xaa, 0xfb, 0x19, 0x92, 0xf6, 0xde, 0x78, 0x5c, 0x76, 0x3a } +, + /* Seed */ + 96, + { 0xfc, 0x7f, 0x85, 0xc1, 0x38, 0x6d, 0xc4, 0x3c, 0x3a, 0x28, 0x46, 0xe4, 0xda, 0xe4, 0xd9, 0x54, 0x80, 0x54, 0x45, 0x9d, 0xa2, 0x31, 0x82, 0xf9, 0x84, 0x07, 0x9b, 0x07, 0x1f, 0xdb, 0x5e, 0x6d, 0x9d, 0x0f, 0xa0, 0xb2, 0x2e, 0x3d, 0xe6, 0x36, 0xee, 0x5b, 0x25, 0x3a, 0x42, 0xf9, 0x5e, 0xed, 0x44, 0x22, 0x95, 0x6c, 0x70, 0xf4, 0x8d, 0xfe, 0xcf, 0x0e, 0x55, 0x5b, 0x05, 0x15, 0x7b, 0x15, 0x6a, 0x55, 0xc8, 0xbc, 0x65, 0x8c, 0xd3, 0xb5, 0x39, 0x7f, 0xab, 0x78, 0xd7, 0x11, 0x56, 0x4e, 0x89, 0xc7, 0xe6, 0x24, 0x8a, 0xa0, 0x6a, 0xd1, 0x05, 0xc4, 0x0c, 0x31, 0xc4, 0xb1, 0x99, 0x7d } +, + /* Encryption */ + 128, + { 0xe3, 0x95, 0xff, 0x1f, 0xa5, 0x52, 0xfc, 0x2e, 0x79, 0xc4, 0xa5, 0x35, 0x58, 0xdf, 0x14, 0x00, 0xf8, 0x70, 0x4e, 0xb3, 0x6c, 0xf7, 0xcb, 0x05, 0x1b, 0xab, 0x93, 0x15, 0x0a, 0xc6, 0x39, 0x6a, 0xdd, 0x63, 0x66, 0x9b, 0x04, 0x24, 0x8b, 0x9d, 0xb3, 0x6a, 0x9c, 0x94, 0xf5, 0x19, 0x8c, 0x6e, 0x5d, 0x9a, 0x17, 0xd4, 0x74, 0xed, 0xb2, 0x03, 0x45, 0xfd, 0x6a, 0x78, 0xb5, 0x1d, 0xe8, 0x16, 0x6e, 0x98, 0xca, 0xb5, 0xb6, 0xd1, 0x65, 0x68, 0xb4, 0x1a, 0x8e, 0x93, 0xe4, 0x83, 0x88, 0x65, 0xd4, 0xbd, 0x9c, 0x51, 0xcd, 0xe8, 0xdf, 0xbe, 0xee, 0xa5, 0x88, 0x2b, 0x09, 0xdc, 0x70, 0xbc, 0x9f, 0xe7, 0x49, 0xb5, 0xd2, 0x4b, 0xb7, 0xca, 0x51, 0x1d, 0xb2, 0xc2, 0xb8, 0x29, 0xa7, 0xc9, 0x14, 0x6c, 0x77, 0x4e, 0xb0, 0xbd, 0x7a, 0xaf, 0xdc, 0x5c, 0x38, 0xd3, 0xd7, 0xcd, 0x58, 0x27 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 4.2", + /* Message */ + 40, + { 0x25, 0xc7, 0xbc, 0x4c, 0xb2, 0x43, 0xac, 0x1f, 0x07, 0x40, 0x86, 0x9c, 0xd2, 0x6b, 0xa8, 0x26, 0xf3, 0x55, 0xd4, 0x77, 0xc4, 0xaa, 0x6c, 0xbe, 0x54, 0x3a, 0xdd, 0xea, 0x84, 0x44, 0x44, 0xf4, 0x1c, 0x35, 0x92, 0xbb, 0x3d, 0xa7, 0xd4, 0x21 } +, + /* Seed */ + 85, + { 0x27, 0x2b, 0xe3, 0xfb, 0xcc, 0x76, 0x14, 0x99, 0x6f, 0x1a, 0xc0, 0xe0, 0xa5, 0xe2, 0x69, 0x06, 0x23, 0xbb, 0x0b, 0x69, 0x70, 0xfc, 0xde, 0x0b, 0x6f, 0x45, 0x58, 0xee, 0x62, 0x34, 0x26, 0xfa, 0x60, 0xad, 0xd6, 0xc5, 0xa8, 0xa1, 0x0d, 0x4a, 0x37, 0x51, 0x50, 0x15, 0x36, 0xfe, 0x8a, 0x45, 0xc5, 0x42, 0xf6, 0x27, 0xf4, 0x22, 0x9f, 0xa1, 0x24, 0x57, 0xc1, 0x13, 0x31, 0x13, 0x72, 0x05, 0x55, 0x2b, 0x01, 0x4c, 0x91, 0xb1, 0xc4, 0xe0, 0x9e, 0x45, 0x96, 0x78, 0x34, 0x0a, 0x74, 0xc2, 0x85, 0xe2, 0x6a, 0xef, 0xb9 } +, + /* Encryption */ + 128, + { 0x76, 0x50, 0xd6, 0xf8, 0x1a, 0xef, 0x5c, 0x0e, 0x32, 0x0e, 0xc7, 0x7f, 0xc8, 0x9b, 0x7c, 0x3e, 0x61, 0x83, 0x85, 0x0d, 0x10, 0xc9, 0x8a, 0xd7, 0xe9, 0xfe, 0xea, 0x47, 0xe3, 0x8c, 0xfb, 0x37, 0xa0, 0x25, 0xdb, 0x42, 0x1f, 0xb6, 0xd0, 0x05, 0x80, 0x9e, 0x38, 0xbb, 0x3c, 0x51, 0x95, 0x1d, 0xa9, 0xd9, 0x43, 0x3b, 0xa7, 0xef, 0xb1, 0x7d, 0xe7, 0xd8, 0xfe, 0x3e, 0x9b, 0x9c, 0xe4, 0x55, 0x53, 0x74, 0xea, 0x66, 0x3a, 0x1b, 0x5d, 0xa4, 0xa0, 0x92, 0x29, 0x4c, 0xe9, 0x66, 0x98, 0x56, 0x55, 0xe2, 0xdd, 0xd2, 0x0d, 0x7d, 0xe3, 0xaa, 0x35, 0x37, 0x05, 0x8c, 0xfd, 0x7e, 0x7a, 0x7b, 0x97, 0xfc, 0xdd, 0x98, 0x53, 0x79, 0x2b, 0xa8, 0x3f, 0xcc, 0x89, 0x07, 0x4a, 0x8d, 0x0f, 0x3c, 0xef, 0xdf, 0x98, 0x5b, 0x9e, 0x78, 0xae, 0xbf, 0xb0, 0x59, 0x67, 0x36, 0x4f, 0x24, 0x11, 0xcd } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.3", + /* Message */ + 20, + { 0xcf, 0x00, 0x7e, 0xbd, 0x23, 0xda, 0x06, 0x97, 0x1a, 0xf7, 0x9a, 0xa6, 0x34, 0xd5, 0xd2, 0x55, 0x05, 0xbd, 0x52, 0x29 } +, + /* Seed */ + 105, + { 0x9c, 0xf7, 0x23, 0x7e, 0x28, 0xa8, 0x6e, 0x41, 0x8d, 0x66, 0x4f, 0xe3, 0xbe, 0x7a, 0xe3, 0x0e, 0xeb, 0x95, 0x5a, 0x3f, 0x71, 0x02, 0xb2, 0x7d, 0x5f, 0xa0, 0x96, 0x74, 0x9c, 0x7f, 0xc2, 0x06, 0x4c, 0x88, 0x0b, 0xf3, 0xd3, 0x0e, 0xaa, 0x98, 0x1f, 0xce, 0x39, 0x86, 0xa9, 0x10, 0xfe, 0xea, 0xe1, 0x84, 0xc0, 0x10, 0x25, 0x04, 0x8b, 0xa6, 0x79, 0x48, 0x96, 0xfc, 0xcf, 0xf7, 0x4a, 0x59, 0x42, 0xf9, 0x62, 0xf3, 0xe3, 0x63, 0x71, 0xf6, 0xb3, 0x55, 0x18, 0x29, 0x43, 0x4a, 0xd8, 0xd0, 0x0a, 0x2c, 0x59, 0x7c, 0xf6, 0xd4, 0x51, 0xea, 0xce, 0x88, 0x86, 0x85, 0x38, 0xa4, 0x80, 0xf6, 0x8c, 0xe6, 0x8f, 0xc6, 0x85, 0x6e, 0xbb, 0x57, 0xdc } +, + /* Encryption */ + 128, + { 0xb6, 0x32, 0x52, 0xaf, 0x2e, 0x8e, 0xa2, 0x71, 0xe7, 0x06, 0xfd, 0x68, 0x3d, 0x0f, 0x8c, 0x10, 0xb3, 0xf4, 0xa3, 0x45, 0xc4, 0xf5, 0xb6, 0x78, 0x5b, 0xa9, 0x32, 0x9f, 0x44, 0x62, 0x43, 0xc6, 0xf3, 0x69, 0xe3, 0x0e, 0xa8, 0xfb, 0x11, 0x08, 0x4d, 0xb9, 0x79, 0x88, 0xe9, 0xc3, 0x87, 0x4b, 0x34, 0xd6, 0xfd, 0x08, 0x71, 0x7d, 0x9e, 0x81, 0x0e, 0x9c, 0x22, 0x43, 0x60, 0x34, 0x6b, 0xec, 0xcd, 0x3e, 0x0e, 0x53, 0xd1, 0x0b, 0x1e, 0xd4, 0x58, 0xe6, 0x4f, 0x3f, 0xb0, 0x92, 0xf4, 0x8c, 0xb6, 0x6a, 0xe0, 0x3b, 0x64, 0xf6, 0xaa, 0x9c, 0x63, 0xbd, 0x27, 0x9f, 0xae, 0x4c, 0x33, 0xf4, 0x2a, 0x9d, 0x73, 0xbb, 0x39, 0x11, 0x8e, 0xb8, 0x7d, 0x25, 0x12, 0xb9, 0xd9, 0x36, 0xa2, 0x7e, 0xd2, 0xe4, 0x49, 0x60, 0x7d, 0xbf, 0x0e, 0x3e, 0x22, 0x3a, 0x53, 0x95, 0x26, 0x35, 0x59, 0x9c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.4", + /* Message */ + 34, + { 0xef, 0xda, 0x79, 0xe9, 0xc3, 0x36, 0xc2, 0x34, 0xff, 0x37, 0xb4, 0xf5, 0x8f, 0xdb, 0xd3, 0x1a, 0xf3, 0x67, 0x5b, 0x3d, 0x2b, 0x10, 0x5e, 0xaf, 0xbe, 0xad, 0x4b, 0xbb, 0xff, 0xf5, 0x4e, 0x68, 0x6a, 0xb5 } +, + /* Seed */ + 91, + { 0x30, 0xc2, 0x09, 0x43, 0xf1, 0xbf, 0xc4, 0x23, 0x61, 0xd4, 0xd2, 0x2f, 0x51, 0xa8, 0xd7, 0x86, 0xcb, 0x2d, 0x0d, 0xd5, 0xff, 0x7d, 0x70, 0x5b, 0x30, 0x28, 0x60, 0x18, 0x11, 0x29, 0x3d, 0xbe, 0x5d, 0x72, 0xc3, 0x55, 0x97, 0x10, 0xce, 0x0a, 0xe9, 0x5d, 0x2f, 0x16, 0xb2, 0x39, 0xa4, 0xac, 0x84, 0x45, 0x53, 0x7d, 0x48, 0x8e, 0x3e, 0x6d, 0x2c, 0xf5, 0xb7, 0xa6, 0x4c, 0x06, 0xc3, 0x75, 0x6e, 0x11, 0x60, 0x67, 0x63, 0x63, 0x3e, 0xdb, 0xdd, 0xbf, 0x26, 0xbe, 0xe6, 0x51, 0x18, 0x42, 0xd2, 0x75, 0x2d, 0xcd, 0x88, 0x89, 0x6c, 0xb8, 0x55, 0x8a, 0x87 } +, + /* Encryption */ + 128, + { 0xbb, 0x91, 0xb2, 0xf6, 0xf4, 0x33, 0x1d, 0x64, 0xd0, 0x73, 0x6a, 0x2e, 0xa6, 0x03, 0x29, 0xaa, 0x16, 0xc2, 0xed, 0x7a, 0x4d, 0x5c, 0xa8, 0xd7, 0x84, 0xe6, 0x30, 0x4c, 0xe4, 0x84, 0x4c, 0x71, 0x58, 0xf8, 0x22, 0xd2, 0xaf, 0x29, 0xc8, 0x90, 0x97, 0x7d, 0x75, 0xa9, 0x35, 0xe4, 0x3d, 0x93, 0xb5, 0xbe, 0x10, 0xc1, 0xd4, 0x4f, 0xa0, 0x0c, 0xe2, 0x8e, 0x75, 0xf5, 0x27, 0xbd, 0x84, 0xa3, 0xbe, 0x5a, 0xf5, 0xbe, 0xe9, 0x45, 0x67, 0xc5, 0x5e, 0x15, 0xee, 0x3e, 0x93, 0x42, 0x6a, 0xd8, 0xd5, 0x0f, 0x06, 0x4c, 0x57, 0x93, 0xca, 0x38, 0xc4, 0x3a, 0x70, 0xc5, 0xf5, 0x60, 0x74, 0x0b, 0x16, 0xee, 0xa1, 0x6b, 0x7f, 0x13, 0x41, 0x5f, 0x75, 0x1b, 0x3f, 0xdb, 0x87, 0x7a, 0x88, 0x29, 0x33, 0x21, 0xf5, 0x0f, 0xff, 0xa6, 0xf1, 0x24, 0x94, 0x96, 0xc2, 0xb0, 0x27, 0xa2, 0x18, 0xed } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.5", + /* Message */ + 52, + { 0x4a, 0x01, 0xfc, 0x13, 0xc1, 0xd8, 0x6f, 0xe7, 0xb2, 0xfd, 0xc7, 0x92, 0xf5, 0x28, 0x0f, 0x87, 0x5a, 0xdc, 0x5a, 0xe9, 0x9f, 0xf9, 0x11, 0xd0, 0x2c, 0x8c, 0x00, 0x3d, 0x39, 0xbb, 0xee, 0x54, 0xb8, 0x51, 0xef, 0xa3, 0x4b, 0x41, 0x31, 0xbe, 0x52, 0x0d, 0x81, 0x00, 0xef, 0x62, 0xc2, 0x5a, 0x4b, 0x51, 0x7e, 0x9b } +, + /* Seed */ + 73, + { 0xbe, 0x6b, 0xa5, 0xd1, 0x1d, 0xf1, 0xbf, 0xcb, 0x2b, 0x84, 0x67, 0x71, 0xb6, 0xc9, 0xdf, 0xc9, 0x33, 0x4d, 0xa8, 0x6c, 0x4b, 0x7c, 0x25, 0x43, 0x93, 0x18, 0xe8, 0xba, 0x8e, 0x47, 0x49, 0x2b, 0xcd, 0x51, 0x1b, 0xd4, 0xca, 0xe1, 0x67, 0x7d, 0x31, 0x2c, 0xa2, 0x2a, 0x94, 0x57, 0xcc, 0x81, 0xd9, 0x0e, 0x4d, 0x52, 0x4b, 0xa2, 0x26, 0x5f, 0x0f, 0xbc, 0xa1, 0x8e, 0x3c, 0x3f, 0x48, 0x2d, 0xca, 0xa7, 0x88, 0x33, 0x22, 0x39, 0x34, 0x6d, 0x6f } +, + /* Encryption */ + 128, + { 0x16, 0xbf, 0xcf, 0xb4, 0x2d, 0x28, 0xb9, 0xd1, 0x62, 0x70, 0xcd, 0x13, 0x8d, 0xc3, 0xca, 0x64, 0x42, 0x95, 0x6a, 0x41, 0x82, 0x5e, 0xd0, 0x23, 0x0b, 0x71, 0x09, 0x16, 0x13, 0x33, 0x3a, 0x9e, 0x7c, 0x52, 0xce, 0x8c, 0xc4, 0xb0, 0xbf, 0x29, 0x10, 0x79, 0x41, 0xa0, 0xd7, 0x2c, 0xc3, 0x4a, 0xfd, 0x00, 0x48, 0xbb, 0xf4, 0xc7, 0x16, 0xc7, 0x3a, 0xa9, 0xb0, 0xc7, 0x8d, 0x37, 0xc1, 0x93, 0x71, 0x9e, 0xbe, 0x03, 0xa9, 0x31, 0x74, 0x53, 0xb5, 0x53, 0xd4, 0xf5, 0xb3, 0x85, 0xd1, 0x41, 0xfc, 0x3b, 0x0e, 0xd1, 0x9b, 0x96, 0xdc, 0x35, 0x0d, 0xfd, 0x4d, 0x12, 0xe3, 0xdd, 0x03, 0xff, 0x18, 0x39, 0xd4, 0x78, 0x2c, 0x6d, 0xfd, 0x5f, 0xdf, 0x59, 0x71, 0xf3, 0xdd, 0xb0, 0xe3, 0x12, 0xa9, 0x16, 0x06, 0xf3, 0x13, 0x73, 0x02, 0x0d, 0xb3, 0xa7, 0x6d, 0x04, 0xfd, 0x6d, 0x65, 0xd6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.6", + /* Message */ + 7, + { 0x7a, 0xb0, 0x6e, 0x19, 0x69, 0x22, 0xc0 } +, + /* Seed */ + 118, + { 0xde, 0x0d, 0x60, 0x33, 0xc1, 0xe9, 0x6b, 0x5f, 0xd8, 0x31, 0x21, 0x4f, 0x30, 0xd8, 0x1b, 0x8f, 0xd9, 0xa2, 0x69, 0x3e, 0x5e, 0x8a, 0x36, 0xea, 0xff, 0xd0, 0x39, 0xe7, 0x47, 0x3c, 0x28, 0xee, 0x43, 0xa3, 0x91, 0x6c, 0x78, 0xc9, 0xa1, 0x12, 0x95, 0x8a, 0x94, 0xce, 0x67, 0x1c, 0xcc, 0x40, 0xd9, 0x7e, 0xd4, 0x18, 0x7a, 0x3f, 0xff, 0xa0, 0xdc, 0x12, 0x9d, 0x88, 0xa8, 0xb8, 0xc4, 0x96, 0x6e, 0xa3, 0x94, 0xa9, 0x10, 0x89, 0x61, 0x25, 0xf5, 0x4d, 0xaf, 0xbb, 0x3b, 0x17, 0xb9, 0xfa, 0x10, 0xc4, 0x82, 0x20, 0x09, 0x64, 0x90, 0xc6, 0xf7, 0x5b, 0xe2, 0x51, 0x83, 0xe9, 0x98, 0x4d, 0xf5, 0xe4, 0xd7, 0xeb, 0xf9, 0x47, 0x5d, 0x11, 0xea, 0x39, 0x33, 0x5a, 0xc7, 0x2f, 0x93, 0xd3, 0x33, 0xbd, 0x74, 0x22, 0x19, 0x42 } +, + /* Encryption */ + 128, + { 0x54, 0x18, 0x23, 0xf9, 0x05, 0x57, 0x6d, 0xa1, 0x42, 0xe2, 0x65, 0xd8, 0x90, 0x45, 0xab, 0x66, 0x20, 0xfd, 0x1a, 0x74, 0xc9, 0x53, 0x3a, 0xda, 0x4b, 0xc7, 0xb4, 0x3d, 0x95, 0x62, 0x9a, 0x31, 0x18, 0x6f, 0x4e, 0x89, 0x89, 0x20, 0x83, 0xd2, 0x54, 0x9b, 0x0e, 0x63, 0x8b, 0xdf, 0xc0, 0xd2, 0x7e, 0x14, 0xec, 0x18, 0xc4, 0x5c, 0xa3, 0x58, 0x61, 0xdf, 0xe6, 0x12, 0xa3, 0xa1, 0xed, 0xaa, 0xfc, 0x72, 0xfb, 0x46, 0x81, 0xa9, 0x9e, 0xa6, 0xe6, 0x48, 0xbe, 0x89, 0x62, 0xf1, 0x56, 0x1e, 0x75, 0x0d, 0x14, 0x49, 0xf2, 0x3f, 0x43, 0x0a, 0xf9, 0x30, 0x72, 0x25, 0x54, 0x4d, 0x8a, 0x8b, 0x89, 0x65, 0xaf, 0x5d, 0xd1, 0x8c, 0xb7, 0x89, 0x53, 0xce, 0x6d, 0x16, 0xd8, 0x5e, 0xb2, 0x11, 0xaf, 0x0c, 0x64, 0x68, 0xa2, 0xaf, 0x9f, 0x72, 0xe7, 0x86, 0x61, 0xb0, 0xfc, 0xaa, 0x48, 0x15 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.7", + /* Message */ + 7, + { 0x9a, 0xda, 0x9c, 0x10, 0xb8, 0xae, 0x22 } +, + /* Seed */ + 118, + { 0xcc, 0x23, 0x43, 0x72, 0x4a, 0xc5, 0x0e, 0xe5, 0x47, 0x08, 0xfc, 0x5f, 0xd0, 0x3f, 0x09, 0xa1, 0xcc, 0x12, 0x22, 0xa4, 0x4b, 0xcd, 0x44, 0x03, 0x87, 0x7c, 0x6b, 0xde, 0x86, 0xbf, 0x43, 0xe4, 0x2c, 0x10, 0x84, 0xf6, 0xef, 0xff, 0x20, 0xfa, 0xc0, 0xac, 0xc3, 0x1e, 0xca, 0x17, 0xc7, 0x38, 0xd4, 0x68, 0x68, 0x73, 0x65, 0x52, 0xfd, 0x2f, 0x7e, 0x93, 0xb8, 0x22, 0x25, 0x61, 0x05, 0x4e, 0x6d, 0xad, 0xc3, 0x15, 0x60, 0x4e, 0xaf, 0x8f, 0x77, 0xf0, 0x5d, 0xd8, 0x58, 0x3a, 0x93, 0xbf, 0x03, 0xcb, 0x9c, 0xc2, 0x13, 0x9b, 0xc4, 0x19, 0xbb, 0x10, 0xe9, 0xb2, 0x01, 0xb2, 0xa7, 0xe1, 0x8b, 0x03, 0x79, 0x0c, 0xc8, 0x3e, 0xd6, 0x05, 0xd6, 0xd5, 0x66, 0x33, 0x05, 0x34, 0x71, 0x39, 0xc7, 0x5e, 0x1a, 0xe2, 0xa5, 0x6a } +, + /* Encryption */ + 128, + { 0x9f, 0x54, 0xd0, 0xde, 0xa0, 0x5a, 0x5d, 0x00, 0x72, 0x23, 0x5b, 0xc4, 0x67, 0x93, 0xcf, 0xc4, 0x7b, 0x00, 0x6d, 0xaa, 0xac, 0x02, 0x41, 0xc7, 0xe6, 0x6d, 0x33, 0x3e, 0x23, 0xc3, 0xcf, 0x97, 0x63, 0xb6, 0x1d, 0x9e, 0xea, 0xdd, 0xd8, 0x3f, 0x5d, 0x7f, 0x0a, 0xa9, 0x7d, 0x16, 0xc7, 0x69, 0x92, 0x55, 0xcf, 0x7e, 0x48, 0x72, 0xb6, 0xa0, 0x07, 0x95, 0x62, 0xd2, 0x60, 0x7d, 0x64, 0x40, 0xd7, 0xed, 0x37, 0xc6, 0x71, 0x3c, 0xe9, 0x66, 0x43, 0xa4, 0x41, 0xf8, 0x39, 0x55, 0x64, 0xd2, 0x6a, 0xde, 0xa5, 0x82, 0x3a, 0x49, 0x42, 0xda, 0x4a, 0xb8, 0xe4, 0x7b, 0xed, 0x58, 0x81, 0xb9, 0xd1, 0x84, 0x05, 0x79, 0x57, 0xdf, 0x65, 0x39, 0xe4, 0x36, 0xda, 0x35, 0xe3, 0x0a, 0x25, 0x3a, 0xf1, 0x2d, 0x54, 0x1d, 0x4b, 0x0e, 0xf8, 0x3c, 0x5e, 0xf3, 0xc1, 0x35, 0xab, 0x95, 0x94, 0x9a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.8", + /* Message */ + 19, + { 0xd8, 0x12, 0x6f, 0x4a, 0x88, 0x78, 0x97, 0x82, 0x93, 0x11, 0x76, 0x51, 0xb3, 0x0e, 0x79, 0x22, 0xd1, 0x4a, 0xcf } +, + /* Seed */ + 106, + { 0xad, 0xf9, 0xb0, 0xa9, 0x15, 0x2f, 0x0e, 0x6e, 0xc6, 0xf4, 0x39, 0x59, 0x71, 0xad, 0x40, 0x3f, 0x02, 0xe7, 0xfa, 0x98, 0xf8, 0x15, 0x56, 0x0a, 0xfa, 0xff, 0xa7, 0xca, 0xd5, 0xb4, 0x47, 0x4b, 0x6e, 0xce, 0x65, 0xed, 0xab, 0xe2, 0x7e, 0xc2, 0x4a, 0x0a, 0xa4, 0x73, 0xed, 0x75, 0xa6, 0x1f, 0x5c, 0x24, 0x90, 0xa5, 0x36, 0xb1, 0xa4, 0xdf, 0x7b, 0x03, 0x41, 0x77, 0x37, 0xc5, 0x34, 0xe1, 0xd4, 0x5b, 0xf7, 0x26, 0x94, 0x38, 0x6b, 0xee, 0x82, 0x0c, 0x48, 0xdb, 0xd1, 0x83, 0x17, 0xbd, 0x61, 0x7c, 0x04, 0xb6, 0xa4, 0x17, 0xe3, 0x0e, 0xed, 0x79, 0x58, 0x8d, 0xc2, 0x3f, 0xd4, 0xdb, 0xa1, 0x37, 0x44, 0xb4, 0xb2, 0xaa, 0x5a, 0xf8, 0x0a, 0x8a } +, + /* Encryption */ + 128, + { 0x3b, 0x2b, 0x85, 0xed, 0xfc, 0xd7, 0xc7, 0xc2, 0x7b, 0xde, 0xde, 0xe1, 0xc2, 0x8a, 0xb6, 0x18, 0x7a, 0xbf, 0x1c, 0x96, 0xd9, 0x45, 0x30, 0x07, 0x92, 0xcf, 0x8a, 0xf1, 0x97, 0xc2, 0xf9, 0xa3, 0x91, 0xb4, 0x8b, 0x83, 0x32, 0xcf, 0xde, 0x7e, 0x4c, 0x7d, 0xc3, 0x4c, 0x42, 0x30, 0x29, 0x56, 0x92, 0xce, 0xfd, 0xa5, 0xef, 0xb2, 0x57, 0x35, 0x49, 0x2b, 0x9f, 0xf7, 0x84, 0xc7, 0xba, 0xe7, 0x35, 0x11, 0xc6, 0x18, 0xe3, 0xaa, 0x7b, 0xc8, 0x7b, 0xc3, 0x13, 0xf2, 0x67, 0x09, 0xa8, 0xea, 0x4a, 0xd7, 0x3a, 0x34, 0x9a, 0xb9, 0xe5, 0xad, 0x82, 0x6c, 0x96, 0xad, 0x0e, 0xca, 0x97, 0xe3, 0x13, 0x28, 0x6b, 0xcc, 0xbf, 0x8e, 0x33, 0xc9, 0x1f, 0x03, 0x68, 0x39, 0xb9, 0x94, 0x8b, 0x4e, 0xb0, 0xc3, 0x8e, 0x21, 0x3e, 0xf4, 0x7f, 0x77, 0x66, 0x1a, 0x27, 0xf8, 0xcf, 0xe4, 0x99, 0x03 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.9", + /* Message */ + 58, + { 0xf5, 0xdf, 0x01, 0xaf, 0xe6, 0xa9, 0x22, 0x51, 0x8b, 0x3f, 0x4b, 0x80, 0xcd, 0x4f, 0xca, 0x73, 0xb9, 0x7b, 0xab, 0x61, 0x71, 0x6e, 0x27, 0xd2, 0x51, 0xbd, 0x46, 0x5f, 0x4b, 0x35, 0xa1, 0xa2, 0x32, 0xe2, 0xda, 0x00, 0x90, 0x1c, 0x29, 0x4b, 0xf2, 0x23, 0x50, 0xce, 0x49, 0x0d, 0x09, 0x9f, 0x64, 0x2b, 0x53, 0x75, 0x61, 0x2d, 0xb6, 0x3b, 0xa1, 0xf2 } +, + /* Seed */ + 67, + { 0x6b, 0xf2, 0x81, 0x0d, 0xb8, 0xfb, 0x26, 0x93, 0x98, 0x41, 0x2d, 0xbb, 0x88, 0x06, 0x02, 0x82, 0xd4, 0x5f, 0xbe, 0x96, 0x27, 0x33, 0x7e, 0x54, 0x34, 0x26, 0x1a, 0x5d, 0xbc, 0x19, 0x3a, 0xd6, 0x18, 0xc1, 0x1f, 0x7b, 0xde, 0xc1, 0xde, 0x25, 0x05, 0xf8, 0x60, 0x37, 0xfc, 0x18, 0x51, 0xbf, 0x6f, 0xb4, 0x9d, 0x23, 0x60, 0x62, 0x73, 0x47, 0x49, 0x9e, 0xfc, 0x98, 0xe2, 0x92, 0x05, 0xda, 0x90, 0x6d, 0x32 } +, + /* Encryption */ + 128, + { 0x40, 0x12, 0xfc, 0xc5, 0xcf, 0xb9, 0x78, 0xde, 0xf8, 0x8f, 0xb8, 0xf8, 0x17, 0x4a, 0xa5, 0xb4, 0xa3, 0x07, 0x75, 0xac, 0x45, 0x59, 0xf0, 0xb2, 0xf3, 0xd3, 0xb4, 0x38, 0x9b, 0x82, 0x8a, 0x79, 0xd1, 0x40, 0x25, 0x10, 0xc9, 0xa0, 0x33, 0x7d, 0x48, 0x9d, 0x11, 0x82, 0xab, 0x31, 0xc8, 0x38, 0xac, 0x7c, 0x80, 0xb7, 0x48, 0x60, 0x9a, 0x2a, 0xa5, 0x37, 0xda, 0x7a, 0xcc, 0x3a, 0x4a, 0x7a, 0x31, 0xd2, 0xad, 0x25, 0x2b, 0xfd, 0x59, 0x28, 0x0b, 0x3d, 0x18, 0x13, 0xa2, 0x6f, 0x93, 0xc5, 0x9e, 0xe8, 0xc5, 0xee, 0x68, 0x87, 0x18, 0xf4, 0x27, 0x83, 0x93, 0xfe, 0xce, 0x32, 0x3a, 0x9d, 0xff, 0x83, 0x37, 0x55, 0xe8, 0x9a, 0xc8, 0xee, 0x1f, 0xa2, 0x90, 0x4b, 0xf2, 0x4c, 0xdf, 0x4f, 0x01, 0xe6, 0xea, 0xed, 0xb6, 0xa8, 0xef, 0x01, 0xf4, 0x07, 0xbe, 0xf3, 0x30, 0x9f, 0x03, 0x39 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.10", + /* Message */ + 4, + { 0xa3, 0x82, 0x3f, 0xaf } +, + /* Seed */ + 121, + { 0x94, 0xf6, 0x70, 0xfd, 0x82, 0xf6, 0x91, 0x32, 0x75, 0xee, 0xa4, 0xc6, 0x71, 0x16, 0xca, 0xaa, 0xbd, 0x33, 0x57, 0x8c, 0xf8, 0x4d, 0x22, 0x63, 0x64, 0x38, 0xa6, 0xfd, 0x7e, 0xcf, 0xee, 0xfc, 0x0b, 0x18, 0x7d, 0xec, 0xf7, 0x93, 0x89, 0x1c, 0x6e, 0x4c, 0xfc, 0x52, 0xb5, 0x67, 0xd8, 0x72, 0xbf, 0xfb, 0xee, 0x0a, 0x67, 0x47, 0x2a, 0x1a, 0x48, 0xc0, 0xf1, 0xba, 0x59, 0x8a, 0xd8, 0x25, 0x89, 0x01, 0xc5, 0x6a, 0x55, 0x92, 0xf1, 0x41, 0x14, 0x7e, 0x81, 0x33, 0x9d, 0x74, 0x7e, 0x06, 0x32, 0xde, 0xf0, 0x0d, 0x3d, 0xbe, 0xe9, 0x5c, 0x4e, 0x43, 0x21, 0xcc, 0x25, 0xb5, 0x31, 0x14, 0x47, 0xa3, 0x02, 0xc5, 0x34, 0x92, 0x9c, 0xf7, 0xe5, 0x34, 0xf9, 0xae, 0x67, 0xf4, 0x1e, 0x01, 0xe2, 0x2a, 0x3d, 0x7c, 0xe4, 0x1b, 0x3b, 0x31, 0x35 } +, + /* Encryption */ + 128, + { 0x7b, 0x60, 0x25, 0x42, 0xb6, 0x4f, 0x0a, 0x1e, 0x0e, 0xc2, 0xaa, 0x01, 0xcb, 0xed, 0x37, 0x7e, 0x33, 0x1e, 0xa3, 0xff, 0x86, 0xf3, 0x56, 0xfb, 0x7a, 0x58, 0x83, 0x76, 0x4b, 0xe4, 0xcb, 0xf7, 0xd0, 0x75, 0x4c, 0x58, 0x29, 0x64, 0x31, 0x36, 0xf2, 0x57, 0x23, 0x36, 0xa2, 0x3f, 0x15, 0x41, 0x1d, 0x83, 0x85, 0x14, 0xa1, 0x43, 0x87, 0x24, 0xad, 0x74, 0x09, 0xe8, 0xec, 0x8f, 0xe2, 0x63, 0x41, 0xae, 0xea, 0x56, 0x68, 0x34, 0x5d, 0x0d, 0x82, 0x3f, 0xb5, 0xc2, 0x1d, 0xf4, 0x59, 0xe8, 0xbf, 0x7c, 0x15, 0xb8, 0x0b, 0x07, 0x2e, 0x5f, 0x8a, 0x84, 0x65, 0xa4, 0x4a, 0xa9, 0xd0, 0x9d, 0x82, 0x5c, 0x03, 0x15, 0xa0, 0xec, 0xd2, 0xd6, 0x49, 0x70, 0x2b, 0x10, 0x9b, 0xe8, 0xfe, 0x35, 0xeb, 0x22, 0x84, 0x3a, 0x20, 0xe7, 0xfd, 0x87, 0x4f, 0x1c, 0x6b, 0x46, 0xa8, 0x0b, 0x68, 0xdf } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.11", + /* Message */ + 62, + { 0x75, 0xb9, 0xa4, 0xa0, 0xbb, 0x2d, 0x46, 0x43, 0xe4, 0x78, 0xf6, 0x54, 0xf2, 0xcc, 0x1a, 0x8c, 0x1b, 0xb4, 0x67, 0x19, 0x76, 0x0d, 0x45, 0x41, 0xa8, 0xa7, 0x33, 0xf3, 0x3b, 0x71, 0x3d, 0x32, 0xc6, 0x0b, 0xfd, 0x35, 0xf1, 0x61, 0x74, 0x83, 0x48, 0x47, 0xe8, 0x81, 0x2c, 0xbd, 0x7f, 0x06, 0xce, 0x72, 0x89, 0xf3, 0x72, 0xc5, 0x82, 0x30, 0xf2, 0xb0, 0x01, 0x45, 0x9b, 0x5d } +, + /* Seed */ + 63, + { 0x49, 0xa7, 0x3d, 0xeb, 0x93, 0xe3, 0xf1, 0xbe, 0xaa, 0xad, 0x3a, 0x19, 0x9a, 0x70, 0x56, 0x9e, 0x09, 0x9a, 0xfa, 0xca, 0xf7, 0xa7, 0x5f, 0xc4, 0xce, 0x64, 0x8f, 0xa8, 0x2e, 0xaf, 0x2a, 0x0f, 0xe4, 0x11, 0xd2, 0x64, 0xfe, 0x45, 0xf7, 0x45, 0x25, 0xc9, 0x1f, 0x3c, 0x75, 0x10, 0x17, 0xf8, 0x0a, 0x02, 0xba, 0xbf, 0xf3, 0x57, 0x99, 0x62, 0x6f, 0x2b, 0x8d, 0xdb, 0x9f, 0x36, 0x91 } +, + /* Encryption */ + 128, + { 0xe5, 0xae, 0xe7, 0x0d, 0xe8, 0x62, 0x72, 0x3c, 0x51, 0x73, 0xdf, 0xfb, 0xf6, 0x92, 0x6c, 0x3d, 0x33, 0x16, 0xd5, 0x90, 0x9c, 0xf5, 0xa1, 0xd6, 0x63, 0xe6, 0x80, 0xab, 0x2b, 0xb5, 0x76, 0xe3, 0x5b, 0x93, 0xfd, 0x43, 0x27, 0x43, 0xa1, 0x8e, 0x8d, 0xb4, 0xfa, 0xa3, 0x32, 0xf4, 0x46, 0x68, 0xa3, 0xd1, 0x9e, 0x5e, 0x69, 0x57, 0x32, 0xf8, 0x4b, 0xbd, 0x86, 0xd0, 0xdd, 0xed, 0x76, 0x65, 0xb7, 0x0b, 0x97, 0x63, 0x2e, 0xab, 0xe2, 0x36, 0x4c, 0xaf, 0xef, 0x7b, 0x74, 0xdc, 0xd1, 0xbf, 0xbd, 0x62, 0x5e, 0x2b, 0xbb, 0xf6, 0x65, 0x4c, 0xc0, 0x26, 0x61, 0x81, 0xac, 0x0a, 0x75, 0x7c, 0x3f, 0xba, 0xbd, 0x43, 0x0a, 0xe8, 0x63, 0x71, 0xeb, 0x56, 0xaf, 0x61, 0x0f, 0x77, 0xcf, 0x2f, 0xff, 0x6e, 0x24, 0x8f, 0x8c, 0x57, 0x91, 0x60, 0xb9, 0x1d, 0xce, 0xcc, 0x0d, 0x20, 0x2b, 0x50 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.12", + /* Message */ + 52, + { 0x15, 0x06, 0xeb, 0x34, 0x91, 0x78, 0x5a, 0xa7, 0x21, 0x06, 0xbf, 0x6c, 0x85, 0xd0, 0x10, 0x02, 0x04, 0x6d, 0x1c, 0x16, 0xd4, 0x35, 0xdd, 0x4e, 0x7c, 0x4b, 0x7e, 0x8e, 0x90, 0xdd, 0xdf, 0x16, 0x33, 0x2f, 0x94, 0xf4, 0xb8, 0x35, 0xd0, 0xe4, 0xad, 0x55, 0xd8, 0x3a, 0x81, 0xb3, 0x5c, 0x54, 0xb6, 0x79, 0xd3, 0xcf } +, + /* Seed */ + 73, + { 0xf6, 0x6e, 0x6a, 0x84, 0x75, 0x84, 0x40, 0x86, 0xe2, 0x84, 0x77, 0x22, 0x97, 0x46, 0x80, 0x1d, 0x43, 0x50, 0xd9, 0xad, 0x07, 0x68, 0xf3, 0xc3, 0xd8, 0xfa, 0xa8, 0x10, 0x7d, 0x95, 0xfb, 0x20, 0x5e, 0x4b, 0xa8, 0xc6, 0x4b, 0x73, 0x8e, 0x54, 0xe5, 0xac, 0x0d, 0xfe, 0xab, 0x99, 0x6d, 0x61, 0x12, 0x5c, 0x26, 0x79, 0x80, 0x72, 0x59, 0xbc, 0x9e, 0x47, 0xd8, 0xbd, 0xd2, 0xc0, 0x40, 0x95, 0x05, 0x44, 0x8b, 0xbf, 0x87, 0x2b, 0xf6, 0x64, 0x7a } +, + /* Encryption */ + 128, + { 0xd1, 0xfa, 0x39, 0x52, 0xcc, 0x61, 0x45, 0xff, 0x77, 0x1b, 0x6c, 0x5a, 0x68, 0x27, 0x5b, 0xbc, 0x22, 0xd0, 0x03, 0x92, 0x03, 0x66, 0x17, 0x37, 0x5f, 0x0c, 0x2b, 0xec, 0x3e, 0x28, 0x85, 0x83, 0xec, 0xfd, 0xc6, 0xdf, 0x6a, 0x82, 0x8d, 0xe3, 0x7f, 0x77, 0xc5, 0x56, 0xa8, 0xcb, 0xc4, 0xd4, 0x43, 0x36, 0xe8, 0xd2, 0xe3, 0x05, 0x87, 0xe3, 0x31, 0x58, 0x73, 0x17, 0xe9, 0x7b, 0x05, 0xa3, 0xfd, 0x78, 0x02, 0x5b, 0x2d, 0x49, 0x6b, 0x3b, 0xbe, 0xeb, 0x6c, 0x72, 0x5d, 0x9e, 0xa5, 0x61, 0xa7, 0x32, 0x28, 0x82, 0x33, 0xd6, 0x8b, 0x79, 0x49, 0x7f, 0xb0, 0xb6, 0xfe, 0xe0, 0xa6, 0xb6, 0x8a, 0xc3, 0x13, 0x66, 0x1b, 0x4b, 0x65, 0x47, 0x39, 0xf9, 0x18, 0xf6, 0xfd, 0x3b, 0xff, 0xc1, 0x7c, 0x1d, 0xf4, 0x1f, 0x01, 0x44, 0x95, 0xd5, 0x5f, 0x95, 0x90, 0x14, 0x7b, 0x82, 0xd1, 0x5d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.13", + /* Message */ + 2, + { 0x9e, 0x3e } +, + /* Seed */ + 123, + { 0x9b, 0x3d, 0xdf, 0x17, 0xcd, 0x74, 0xe7, 0x6c, 0x69, 0xb5, 0xca, 0x3a, 0x01, 0x0a, 0x0e, 0x0f, 0xbd, 0x17, 0x05, 0xd6, 0x9c, 0x30, 0x74, 0x35, 0x3b, 0xe7, 0xd3, 0xc0, 0xc2, 0x05, 0xf0, 0x99, 0xc7, 0xa8, 0x10, 0xb7, 0xa1, 0xad, 0xe0, 0x9f, 0x5a, 0x03, 0x6b, 0xb7, 0x69, 0xef, 0xf5, 0x3a, 0x53, 0xd4, 0xc6, 0xf8, 0x71, 0x52, 0x92, 0x2d, 0x9a, 0x7b, 0x86, 0xed, 0xeb, 0xa3, 0x72, 0x37, 0xd7, 0xf1, 0x73, 0x4d, 0x9d, 0x97, 0x39, 0x38, 0x3f, 0x48, 0x80, 0xaf, 0x3a, 0xd6, 0x88, 0x87, 0xe0, 0xfe, 0x7c, 0x87, 0xa1, 0x74, 0xfb, 0x32, 0x38, 0xb1, 0xe5, 0x1e, 0xad, 0x2a, 0x84, 0x34, 0x40, 0xc2, 0xb2, 0x7f, 0x22, 0xdd, 0xa4, 0x22, 0x8d, 0xce, 0x70, 0xf9, 0x1c, 0x98, 0xd4, 0x71, 0xa8, 0x74, 0x4d, 0x27, 0x65, 0x55, 0x79, 0x58, 0x81, 0x02, 0x44 } +, + /* Encryption */ + 128, + { 0x42, 0x12, 0x6b, 0x49, 0x2a, 0x1e, 0x7c, 0xc0, 0x33, 0x95, 0xb2, 0xac, 0x70, 0x33, 0xcf, 0x6a, 0x67, 0x36, 0xb1, 0x2e, 0x76, 0x82, 0x5a, 0x17, 0x3b, 0x9e, 0x01, 0x1a, 0xe8, 0xbf, 0xed, 0x44, 0xfe, 0xcb, 0x8d, 0x9f, 0x58, 0xcc, 0xe1, 0x99, 0x11, 0xfe, 0x42, 0xd4, 0x55, 0xe2, 0x49, 0x20, 0x09, 0x32, 0xa9, 0xb6, 0x8f, 0xe2, 0xe4, 0x19, 0xbc, 0x63, 0x9c, 0x11, 0x78, 0xd1, 0x1f, 0xfb, 0xdb, 0xd9, 0x95, 0x5d, 0x45, 0x9f, 0x5e, 0xcf, 0xe0, 0x90, 0x20, 0x09, 0x8e, 0x29, 0x7b, 0x8e, 0x91, 0x48, 0x5e, 0x94, 0xbf, 0x11, 0xe7, 0xbf, 0x77, 0xed, 0xf5, 0xa2, 0x70, 0x11, 0xc8, 0x2b, 0x92, 0x73, 0x65, 0xa1, 0x2c, 0x9c, 0x77, 0xc7, 0xe4, 0x9b, 0xb7, 0xfe, 0x2f, 0x61, 0x33, 0x39, 0xde, 0x3f, 0x51, 0x20, 0x87, 0x79, 0x53, 0x86, 0xca, 0x58, 0x5a, 0x70, 0x24, 0x78, 0x27, 0x90 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.14", + /* Message */ + 28, + { 0x70, 0xaa, 0x78, 0xa4, 0xd3, 0x7f, 0x74, 0xc1, 0x81, 0xaa, 0x27, 0x40, 0x7f, 0x2f, 0x9f, 0xe6, 0x63, 0xa9, 0x1b, 0x16, 0xbe, 0x9b, 0xea, 0x6f, 0xc6, 0x12, 0x88, 0x7f } +, + /* Seed */ + 97, + { 0xd0, 0xfd, 0x16, 0xc0, 0xf0, 0xd7, 0x90, 0x9a, 0x38, 0x86, 0x17, 0x08, 0x11, 0xe4, 0x4f, 0x24, 0xfa, 0xdf, 0x94, 0xff, 0x17, 0x03, 0x9a, 0x56, 0x84, 0xa0, 0x9b, 0x24, 0xe1, 0x93, 0x3f, 0xa0, 0xc4, 0x71, 0x51, 0x63, 0x5d, 0x75, 0x7b, 0x73, 0xc2, 0x3f, 0xf3, 0x91, 0x01, 0xcb, 0xe2, 0x52, 0x9a, 0x63, 0xa7, 0xf3, 0xa0, 0x19, 0x5b, 0x6e, 0x47, 0x51, 0x07, 0x11, 0xde, 0x17, 0x1a, 0x16, 0x56, 0xc9, 0xea, 0xb3, 0xcf, 0x82, 0xd1, 0xc6, 0x52, 0x26, 0xb5, 0x8f, 0xd0, 0xfe, 0x58, 0xec, 0x31, 0x96, 0x24, 0x7f, 0x34, 0xb1, 0xa0, 0x55, 0x27, 0x02, 0xdc, 0x03, 0x75, 0x12, 0xc6, 0x81, 0x04 } +, + /* Encryption */ + 128, + { 0x95, 0x36, 0xd4, 0x7e, 0x1d, 0x68, 0x7f, 0x1f, 0x24, 0x99, 0x6c, 0xb4, 0x6c, 0xe9, 0x46, 0xae, 0x54, 0xd4, 0xa1, 0x49, 0xb3, 0x4b, 0x5b, 0xc3, 0x44, 0x43, 0xa2, 0x01, 0x51, 0x83, 0x87, 0xf4, 0xb6, 0x38, 0x18, 0x37, 0xcb, 0x7e, 0x4b, 0x0a, 0x44, 0x75, 0x13, 0x70, 0x42, 0xf1, 0x44, 0x8c, 0x1e, 0xa4, 0x15, 0x15, 0xef, 0x31, 0xc2, 0xfc, 0xbf, 0x62, 0xe7, 0xe9, 0x58, 0x67, 0xb6, 0x74, 0xac, 0x23, 0x0a, 0xed, 0x9c, 0x7d, 0x8d, 0x61, 0xc5, 0x27, 0x52, 0xb2, 0xfc, 0x2a, 0x0b, 0xba, 0xfc, 0x77, 0xb3, 0x1c, 0x51, 0x49, 0x30, 0xde, 0x98, 0x23, 0xb4, 0x38, 0xb6, 0xfa, 0xaa, 0x40, 0xd2, 0x55, 0x31, 0x03, 0x3c, 0x66, 0x48, 0x3f, 0xa0, 0x02, 0x3a, 0xf2, 0x1d, 0xa6, 0x4f, 0xcc, 0x8b, 0xb8, 0xc5, 0xd5, 0x2d, 0x3f, 0x6c, 0x43, 0x80, 0xf1, 0xd6, 0x08, 0xd8, 0xc0, 0x11, 0x8f } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.15", + /* Message */ + 59, + { 0x01, 0x16, 0xa4, 0x61, 0x77, 0x73, 0xb6, 0xdd, 0xb2, 0x19, 0x16, 0x1c, 0x4f, 0xd0, 0x71, 0x93, 0x7b, 0xbb, 0x07, 0x15, 0xcc, 0x62, 0x7c, 0x17, 0xb8, 0xe7, 0x52, 0x80, 0xd9, 0x9c, 0xdd, 0x41, 0x6e, 0xa5, 0xcd, 0xfa, 0x09, 0x06, 0xb9, 0xaf, 0x0a, 0x20, 0xcd, 0x47, 0x7f, 0xdc, 0xad, 0x14, 0x15, 0xa1, 0x9a, 0x9d, 0x1b, 0x96, 0xfd, 0xc3, 0xc0, 0xed, 0xb9 } +, + /* Seed */ + 66, + { 0x86, 0xb1, 0x58, 0x60, 0x9b, 0xfa, 0x08, 0xa8, 0xed, 0xe4, 0xef, 0x3f, 0x23, 0xe1, 0x2e, 0xb5, 0x0d, 0x24, 0x55, 0x74, 0x26, 0x4d, 0x76, 0x4d, 0x87, 0x12, 0x67, 0xdb, 0x8a, 0x95, 0x24, 0xea, 0x3f, 0xa2, 0xe3, 0x84, 0x5f, 0xfc, 0x29, 0x1b, 0xda, 0x98, 0x99, 0x89, 0xbf, 0x71, 0x5a, 0xa2, 0xb0, 0x8c, 0x49, 0x79, 0x8a, 0x81, 0x9f, 0x68, 0x58, 0xd9, 0xfa, 0x35, 0xf9, 0x4d, 0xf3, 0xc7, 0xe0, 0x86 } +, + /* Encryption */ + 128, + { 0x74, 0xa3, 0xdf, 0x38, 0x5d, 0x20, 0x87, 0x7b, 0xca, 0x9d, 0xbc, 0xeb, 0xca, 0x2e, 0x53, 0x2c, 0x6a, 0xbe, 0x95, 0x62, 0xd6, 0x81, 0x7b, 0xe1, 0x6e, 0x11, 0x8a, 0x60, 0xf4, 0xab, 0x0a, 0x1a, 0xc0, 0xa8, 0x46, 0x66, 0x53, 0xa8, 0xf8, 0x17, 0x0e, 0x35, 0xfc, 0xe1, 0x4b, 0x44, 0x9c, 0xd5, 0x9f, 0x55, 0x8e, 0x02, 0x0a, 0x89, 0x88, 0x94, 0xbd, 0x2a, 0x71, 0x75, 0x58, 0xe6, 0x65, 0x0f, 0x3a, 0x12, 0x85, 0x70, 0xd8, 0xc1, 0x69, 0xa7, 0x74, 0x66, 0x63, 0xc1, 0xd7, 0xef, 0x62, 0x14, 0x5f, 0x4b, 0x75, 0xc5, 0xfe, 0xb6, 0x38, 0x6f, 0xdb, 0x85, 0x33, 0x94, 0xc6, 0x59, 0xa9, 0x1a, 0xa2, 0xaa, 0xe0, 0x3b, 0xef, 0x91, 0x13, 0xdd, 0x49, 0x28, 0xff, 0x28, 0xb3, 0x80, 0x92, 0x7a, 0xd1, 0xba, 0x4e, 0x8a, 0x37, 0xed, 0xd1, 0x72, 0xef, 0xe8, 0xe9, 0xea, 0xbb, 0x61, 0x4d, 0x83 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.16", + /* Message */ + 63, + { 0x15, 0xc5, 0xfc, 0xc7, 0x54, 0x7d, 0x63, 0x76, 0x1f, 0x6a, 0xf1, 0xf2, 0x6e, 0xed, 0x9b, 0xe8, 0x13, 0x4f, 0x9f, 0x92, 0x12, 0x7e, 0x76, 0xb0, 0x3a, 0x33, 0xa9, 0x7b, 0x9b, 0xe3, 0xf7, 0x8b, 0x2e, 0x22, 0xfc, 0x7c, 0x85, 0x06, 0x99, 0xa1, 0x5c, 0x0e, 0x0e, 0xce, 0xbe, 0x2a, 0x71, 0x80, 0x5f, 0x02, 0x4b, 0x93, 0x88, 0xa3, 0xbd, 0xb2, 0xb3, 0x60, 0xd6, 0x9c, 0x5c, 0x0c, 0x46 } +, + /* Seed */ + 62, + { 0x5b, 0x4f, 0x17, 0xa9, 0xde, 0x91, 0x73, 0x7a, 0x7f, 0xe8, 0x54, 0xe8, 0xa1, 0x76, 0xbe, 0x5a, 0x0a, 0x16, 0xfc, 0x10, 0x42, 0xcb, 0x87, 0x0c, 0xc0, 0x18, 0x92, 0xfc, 0xd3, 0x8e, 0xa7, 0x5b, 0x07, 0x3c, 0x0f, 0xfa, 0x01, 0x4f, 0x96, 0xa3, 0x58, 0xe3, 0xaa, 0x5e, 0x73, 0xea, 0xf8, 0xa9, 0x1f, 0xce, 0x75, 0x47, 0x0b, 0xde, 0x64, 0xe8, 0x7a, 0xb8, 0x91, 0xba, 0x3b, 0xf2 } +, + /* Encryption */ + 128, + { 0x73, 0x62, 0xd7, 0x39, 0x8d, 0x0c, 0x25, 0x1f, 0x83, 0x58, 0x17, 0xe4, 0x79, 0x37, 0xa9, 0x25, 0x58, 0x36, 0xca, 0x02, 0x30, 0x45, 0x7f, 0xf6, 0x08, 0xb0, 0x78, 0xd5, 0x09, 0x31, 0xa8, 0x80, 0x33, 0xea, 0x76, 0x50, 0x81, 0x12, 0x65, 0xf8, 0xe2, 0x68, 0xb5, 0x33, 0x15, 0xd8, 0x43, 0x8e, 0x52, 0xa6, 0xa4, 0xb1, 0xb3, 0x89, 0x5d, 0x30, 0xc3, 0xda, 0xe1, 0x1a, 0x3b, 0x8e, 0xa8, 0xc3, 0x0f, 0x05, 0xe9, 0xd7, 0x1d, 0xef, 0x46, 0xd4, 0x51, 0x11, 0x92, 0xa1, 0x0f, 0x54, 0x21, 0x8d, 0x39, 0x36, 0xcb, 0x17, 0x98, 0x3a, 0x1e, 0x7a, 0xff, 0x18, 0x18, 0x89, 0x39, 0xb9, 0x46, 0x92, 0x76, 0x49, 0xb0, 0xfc, 0x4f, 0x7b, 0xbf, 0xcb, 0xfc, 0x14, 0xe1, 0xc0, 0xec, 0xa0, 0x7d, 0x00, 0xc9, 0x03, 0xdb, 0x78, 0x16, 0x9c, 0x50, 0xef, 0x0a, 0x38, 0xf1, 0xda, 0x19, 0xae, 0x44, 0x59 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.17", + /* Message */ + 29, + { 0x7c, 0xad, 0x18, 0xf1, 0x75, 0x13, 0x87, 0x42, 0x28, 0x5e, 0x90, 0x35, 0xd1, 0x3a, 0xd4, 0x1f, 0xc3, 0xa8, 0x52, 0x10, 0xe1, 0x54, 0x4e, 0x24, 0xde, 0xa3, 0xfc, 0xfe, 0x66 } +, + /* Seed */ + 96, + { 0x9a, 0x06, 0xca, 0x10, 0xfc, 0xc6, 0x61, 0x0e, 0x77, 0xdf, 0xf9, 0x0d, 0xd1, 0x76, 0xf8, 0x2e, 0x3f, 0x96, 0xe4, 0xa9, 0xd7, 0xab, 0x87, 0x2c, 0x74, 0x8e, 0xd4, 0x22, 0xf3, 0x4b, 0x33, 0x48, 0x61, 0x94, 0x40, 0xf0, 0xaa, 0xa2, 0x2a, 0x66, 0x98, 0x51, 0xda, 0xc8, 0x89, 0x4a, 0x8e, 0xfa, 0x34, 0xea, 0x2c, 0x2d, 0xa5, 0xe9, 0x58, 0x69, 0xe0, 0xad, 0xc0, 0x05, 0xa4, 0x9b, 0xa4, 0x58, 0x18, 0xca, 0xa4, 0x74, 0x11, 0x5c, 0x34, 0x49, 0x96, 0x6a, 0x85, 0xc4, 0x18, 0xfc, 0xaa, 0x8f, 0x45, 0x63, 0x0e, 0xfe, 0x0b, 0x1b, 0x4d, 0x3d, 0x69, 0xbe, 0x1b, 0xc0, 0x06, 0x8a, 0xa7, 0x99 } +, + /* Encryption */ + 128, + { 0x1e, 0xfa, 0xd4, 0x14, 0x46, 0xb9, 0x1f, 0xda, 0xdd, 0x8b, 0x80, 0x61, 0x9f, 0x68, 0x27, 0x36, 0x68, 0xb7, 0x58, 0x5f, 0xd9, 0x1f, 0x34, 0x49, 0xec, 0x85, 0xc2, 0x42, 0xd0, 0x84, 0x9e, 0x4a, 0x53, 0xa5, 0x97, 0x7b, 0x61, 0xaa, 0x40, 0xd1, 0x2c, 0xc4, 0x85, 0xec, 0x7e, 0x4f, 0xf2, 0x0f, 0x98, 0x86, 0x91, 0xcb, 0x9d, 0x73, 0xaf, 0x46, 0xea, 0x37, 0x6a, 0xfc, 0x69, 0xba, 0x22, 0x33, 0x86, 0xe9, 0xf1, 0x5d, 0x03, 0x26, 0x97, 0xda, 0x75, 0xe2, 0xf9, 0x52, 0xbe, 0x2a, 0xf0, 0x62, 0xe8, 0x24, 0x6c, 0xf7, 0x49, 0xb8, 0x9c, 0x4c, 0xbc, 0xd6, 0x4e, 0x23, 0xf8, 0x82, 0xbb, 0x55, 0x3c, 0x3c, 0xe3, 0x05, 0x20, 0x36, 0x22, 0xb5, 0xa7, 0x39, 0x77, 0x35, 0xa6, 0x34, 0xaa, 0xb0, 0xd1, 0x7e, 0xf9, 0xb5, 0x55, 0x9d, 0xdd, 0x34, 0xf4, 0x87, 0x2b, 0x56, 0xe7, 0x98, 0x6e, 0xfc } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.18", + /* Message */ + 18, + { 0xfd, 0x98, 0xc3, 0x8b, 0xe3, 0x19, 0x30, 0x70, 0xb5, 0xc4, 0x33, 0x4b, 0x11, 0xc2, 0x5b, 0x33, 0x4a, 0x44 } +, + /* Seed */ + 107, + { 0xf3, 0x57, 0x91, 0x11, 0x03, 0xe9, 0x87, 0xd1, 0xa9, 0xf1, 0x5c, 0xc2, 0xe5, 0x2f, 0x42, 0x39, 0x0e, 0x0f, 0xaa, 0x50, 0x02, 0xc4, 0xf1, 0x7d, 0x40, 0xa4, 0xaf, 0x50, 0xf3, 0x1a, 0x23, 0x17, 0x50, 0xe7, 0xaf, 0x61, 0xd9, 0xaf, 0xdf, 0x9c, 0xaa, 0x38, 0x61, 0xa2, 0x0d, 0xc7, 0x21, 0x89, 0x58, 0x61, 0xfb, 0x11, 0x8e, 0x08, 0x8d, 0x32, 0x18, 0xe6, 0xfb, 0x35, 0x56, 0xb1, 0x62, 0xd6, 0xbd, 0x67, 0x91, 0x1d, 0xbc, 0x94, 0x21, 0x98, 0x42, 0x65, 0x82, 0x72, 0xa5, 0xd4, 0x9b, 0xf5, 0xab, 0xb4, 0xa0, 0x87, 0x94, 0x95, 0xc5, 0xe6, 0xe6, 0x86, 0x28, 0x59, 0x29, 0xa5, 0x5a, 0x36, 0x8f, 0x52, 0x4c, 0x14, 0xa4, 0x0b, 0x0c, 0x61, 0x38, 0x0d, 0x0e } +, + /* Encryption */ + 128, + { 0xde, 0xae, 0x18, 0x3b, 0x56, 0xc3, 0xfb, 0x38, 0x41, 0xea, 0x57, 0x42, 0x34, 0xac, 0xd3, 0x0a, 0xff, 0x00, 0xd0, 0x05, 0x1f, 0x57, 0x80, 0x37, 0x58, 0xa4, 0x71, 0x4a, 0xbc, 0xbe, 0xdc, 0xda, 0x8b, 0xd1, 0xa4, 0x8a, 0x98, 0x01, 0x53, 0xdf, 0x89, 0x6b, 0x13, 0x76, 0xaa, 0x4b, 0x45, 0x95, 0x80, 0x13, 0xd6, 0x19, 0xbe, 0x7e, 0xaf, 0xf6, 0xc1, 0xa6, 0x75, 0xe2, 0x92, 0xef, 0xc3, 0xf4, 0x39, 0x3d, 0xdb, 0xde, 0xab, 0x47, 0xe8, 0x90, 0xa7, 0x8c, 0xef, 0x69, 0x00, 0x24, 0x49, 0x57, 0x87, 0x48, 0x90, 0x6c, 0x10, 0x21, 0xb8, 0x91, 0xb9, 0x43, 0xd8, 0x18, 0xd3, 0xa6, 0x1e, 0x67, 0xa3, 0x15, 0x61, 0x2d, 0x4c, 0xb1, 0xcf, 0x19, 0x7c, 0xe5, 0xdf, 0xab, 0xef, 0xda, 0xeb, 0x59, 0x0b, 0x8e, 0x8c, 0x73, 0x68, 0x5e, 0x74, 0x7e, 0x59, 0xa3, 0x95, 0xc8, 0x45, 0xc5, 0xd0, 0xc3 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.19", + /* Message */ + 54, + { 0x96, 0x53, 0xd7, 0x94, 0x69, 0xf0, 0x5d, 0x40, 0x19, 0x65, 0xa9, 0x5c, 0xe8, 0x74, 0xfa, 0x22, 0x5e, 0xc4, 0x79, 0x74, 0xe8, 0xd0, 0x68, 0x41, 0xc1, 0x3b, 0x47, 0x85, 0xe0, 0x0d, 0x54, 0x7f, 0x9d, 0x31, 0x44, 0xc3, 0x87, 0x9e, 0x6c, 0xcd, 0xaf, 0x78, 0x7a, 0xef, 0xc2, 0xf8, 0x45, 0x2a, 0x4a, 0x3c, 0x88, 0x4e, 0x38, 0xee } +, + /* Seed */ + 71, + { 0x85, 0x5d, 0x6d, 0x15, 0x12, 0xe5, 0x43, 0xa4, 0x5d, 0x3a, 0x9a, 0xa9, 0x68, 0x5d, 0x5d, 0xfd, 0xa7, 0x04, 0x79, 0xba, 0x39, 0x52, 0x63, 0x64, 0x14, 0x1b, 0xb6, 0x36, 0x27, 0x45, 0x89, 0x85, 0x71, 0x20, 0x01, 0x22, 0xf4, 0xbc, 0x82, 0xc6, 0x22, 0x43, 0x45, 0xc6, 0x9d, 0x3e, 0xf5, 0x42, 0xf1, 0x23, 0xbd, 0xe3, 0x01, 0x5b, 0x60, 0xc4, 0xc0, 0xff, 0xb9, 0x8d, 0x63, 0x01, 0x31, 0xae, 0xe8, 0x1f, 0xe4, 0xa0, 0xb0, 0x15, 0x38 } +, + /* Encryption */ + 128, + { 0x69, 0xca, 0x62, 0xe2, 0x9a, 0x5b, 0xdb, 0x4b, 0x04, 0xe2, 0x40, 0x16, 0x21, 0x2c, 0x25, 0x91, 0x40, 0xa6, 0x0c, 0xfa, 0x81, 0xeb, 0x66, 0x93, 0xbf, 0xfa, 0xfc, 0x9f, 0x60, 0x0d, 0xce, 0x10, 0x82, 0x2a, 0x00, 0x7b, 0x6a, 0xde, 0x93, 0xfa, 0xcd, 0xa1, 0xb2, 0xb1, 0x65, 0xb5, 0x57, 0x76, 0x0f, 0x0a, 0x67, 0x5a, 0xc9, 0xbc, 0xb2, 0x06, 0xb9, 0x64, 0xfb, 0x90, 0xcf, 0x6a, 0x2c, 0xf9, 0x9f, 0x18, 0x6b, 0x36, 0xd2, 0xeb, 0x99, 0x1d, 0x82, 0x53, 0xa0, 0x75, 0x4f, 0x9c, 0xc2, 0xd7, 0x2d, 0xe5, 0x49, 0xab, 0xae, 0x90, 0x94, 0xf5, 0xa8, 0x6c, 0xe1, 0xdb, 0x49, 0x4d, 0xbb, 0x6e, 0x51, 0x62, 0x86, 0x71, 0x5b, 0x3d, 0xd4, 0x05, 0x59, 0xb3, 0x10, 0x7b, 0x95, 0x24, 0xb7, 0x29, 0xac, 0x65, 0x4c, 0xfb, 0x40, 0xf9, 0xab, 0x35, 0xd0, 0x34, 0xe0, 0x27, 0x19, 0x7c, 0xbc, 0x36 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 4.20", + /* Message */ + 41, + { 0x0b, 0xdf, 0x3f, 0xce, 0x8e, 0x48, 0x7d, 0xb2, 0x2d, 0x07, 0x60, 0xab, 0x71, 0x15, 0x86, 0xca, 0x8e, 0x45, 0x9c, 0x39, 0x4f, 0xf8, 0xb1, 0xa1, 0x86, 0x70, 0x67, 0xa9, 0x31, 0x51, 0x99, 0xa8, 0x01, 0x24, 0x74, 0xb0, 0xf9, 0x0d, 0xcc, 0x87, 0xcb } +, + /* Seed */ + 84, + { 0xc9, 0xb7, 0x8d, 0xce, 0x9d, 0xfd, 0x7f, 0x04, 0x04, 0xff, 0x98, 0x2e, 0x06, 0xb5, 0x96, 0x50, 0xba, 0xfe, 0x31, 0xea, 0x19, 0xbc, 0x1f, 0x2e, 0x1f, 0x39, 0x89, 0xf4, 0xce, 0xfc, 0xe4, 0x6f, 0xc6, 0x52, 0x42, 0x3d, 0xb3, 0xc9, 0x9d, 0x92, 0xa8, 0xfb, 0x58, 0xf3, 0xee, 0x39, 0x3d, 0x55, 0x5b, 0x76, 0x84, 0x88, 0x9a, 0x4b, 0xf8, 0x15, 0xa1, 0x3e, 0x3b, 0x9b, 0xf2, 0x43, 0x71, 0x40, 0x66, 0xb9, 0x07, 0x58, 0x90, 0x67, 0x50, 0x47, 0xf1, 0x7e, 0x93, 0x5b, 0xdc, 0xf0, 0xe6, 0x6f, 0xcf, 0xe3, 0x9b, 0xcf } +, + /* Encryption */ + 128, + { 0x43, 0xad, 0x3e, 0x62, 0x5f, 0xb1, 0x72, 0x15, 0x57, 0x8b, 0xef, 0x2f, 0x46, 0x5f, 0xaa, 0x72, 0xae, 0x69, 0x43, 0x83, 0x36, 0x9f, 0xf7, 0xaa, 0x15, 0x12, 0x01, 0xa3, 0xf2, 0x59, 0xc8, 0xd8, 0xce, 0x8c, 0x16, 0xbd, 0x25, 0x52, 0x21, 0x49, 0xf6, 0x66, 0xe8, 0xd6, 0x92, 0xa0, 0x79, 0x5e, 0xa7, 0x15, 0x69, 0xd2, 0x88, 0x1f, 0x97, 0x07, 0x08, 0x5d, 0x3f, 0x59, 0xbd, 0xfa, 0x28, 0x73, 0x66, 0xd7, 0xf5, 0xa3, 0xf7, 0x6e, 0xa5, 0xdc, 0x10, 0x9f, 0xcb, 0x03, 0x30, 0x2d, 0xa0, 0xb7, 0x86, 0x99, 0x71, 0x3e, 0x0d, 0x30, 0x09, 0x58, 0x4f, 0x97, 0x17, 0x6c, 0x1b, 0x9b, 0xa6, 0x3e, 0x80, 0xcf, 0xa8, 0xfd, 0x4c, 0x01, 0x3d, 0x74, 0xb5, 0xfa, 0xde, 0x84, 0x72, 0xd5, 0x2c, 0x11, 0xe2, 0xe9, 0x36, 0x81, 0xba, 0x19, 0xd3, 0x53, 0xd3, 0x1c, 0xe6, 0xfa, 0x3c, 0x0a, 0xb6, 0x0d } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 5: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xab, 0x29, 0xd4, 0x9c, 0xdc, 0x92, 0x5c, 0x69, 0xca, 0xe7, 0x52, 0x92, 0xfc, 0x03, 0x62, 0x03, 0x73, 0xc6, 0xfb, 0x36, 0xd3, 0xc2, 0x49, 0xdd, 0x5b, 0xb5, 0x0f, 0x88, 0x1a, 0x4c, 0x93, 0x89, 0xaf, 0xe7, 0x3e, 0x8c, 0x56, 0xb8, 0xd6, 0x67, 0xa5, 0xea, 0xf2, 0xb5, 0x71, 0x4a, 0xda, 0xf4, 0xca, 0xa0, 0x06, 0xa4, 0x9a, 0xc4, 0xbd, 0x4b, 0x91, 0xd5, 0x45, 0xcf, 0x3c, 0x10, 0x00, 0x9d, 0x31, 0x8a, 0x9d, 0xe0, 0xf3, 0xbb, 0xd8, 0x38, 0x4e, 0x8c, 0x7e, 0x96, 0xca, 0x15, 0x95, 0xe3, 0x2a, 0x70, 0x41, 0xd1, 0x68, 0xca, 0xa7, 0x34, 0x43, 0xb8, 0x85, 0xbf, 0x7f, 0x61, 0x4a, 0xe1, 0x21, 0x2e, 0x3b, 0x5a, 0xdd, 0xa2, 0x9d, 0xfa, 0xd5, 0x01, 0xb8, 0xb1, 0xa8, 0x1c, 0x3f, 0x48, 0xa4, 0x56, 0xe1, 0x33, 0xad, 0x52, 0xda, 0x2a, 0xbc, 0xe5, 0xd6, 0xe7, 0x82, 0xf2, 0x75, 0xc9 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x07, 0x7b, 0xb2, 0x73, 0x32, 0x34, 0x86, 0xec, 0x4c, 0x25, 0xed, 0x67, 0x06, 0x34, 0x1a, 0xa8, 0xa6, 0x7a, 0xec, 0x58, 0x43, 0x0d, 0x53, 0x3f, 0xe5, 0x86, 0xc6, 0xb9, 0x4f, 0x57, 0x0a, 0x3b, 0x42, 0x90, 0xc4, 0x5c, 0x0b, 0xdd, 0x94, 0x68, 0x1f, 0x29, 0xa4, 0xb7, 0x58, 0x8e, 0xea, 0x80, 0x39, 0xcc, 0xa1, 0xc5, 0xb8, 0x0b, 0x82, 0x70, 0x27, 0x9d, 0xd0, 0xa9, 0xc5, 0x09, 0x39, 0x11, 0x93, 0xe3, 0xd5, 0xc2, 0x5c, 0x10, 0x75, 0xc4, 0xa1, 0xd3, 0xdc, 0x32, 0x74, 0x06, 0x6d, 0xab, 0x81, 0x7f, 0xb5, 0x1b, 0x16, 0xbc, 0x26, 0x7e, 0xd9, 0xa9, 0x98, 0x0f, 0xfb, 0xc0, 0x92, 0x85, 0xd9, 0x7f, 0x11, 0x2f, 0x15, 0x26, 0x95, 0xe6, 0xe0, 0x9c, 0xae, 0x72, 0xbb, 0x55, 0x06, 0x6c, 0xb9, 0xdb, 0xd0, 0x98, 0xa7, 0x5c, 0xeb, 0x47, 0xb4, 0x62, 0x72, 0x00, 0x5c, 0x6b, 0xd2, 0x15 } +, + /* Prime 1 */ + 64, + { 0xe9, 0x4e, 0xa6, 0xb6, 0x19, 0xbe, 0xc3, 0xe4, 0x78, 0x87, 0x8e, 0x87, 0x8c, 0xf1, 0x23, 0xb7, 0xa9, 0xf1, 0x2c, 0xab, 0xb1, 0x95, 0xe0, 0xaa, 0xe0, 0x22, 0xf3, 0x17, 0x73, 0x46, 0x69, 0x31, 0x38, 0xb1, 0x1a, 0x86, 0xfa, 0x5c, 0xb7, 0x55, 0x5a, 0x10, 0xb8, 0xe4, 0x62, 0x2c, 0xe9, 0x52, 0x0c, 0x57, 0x2b, 0xef, 0x29, 0x1d, 0xf7, 0x0a, 0x16, 0xd8, 0x85, 0xf5, 0x97, 0xe5, 0x90, 0x4d } +, + /* Prime 2 */ + 64, + { 0xbb, 0xcf, 0xcc, 0x5a, 0x60, 0x95, 0x34, 0xee, 0x43, 0x4a, 0x6c, 0xbc, 0xa3, 0xf7, 0xe9, 0x62, 0xe7, 0x6d, 0x45, 0x5e, 0x32, 0x64, 0xc1, 0x9f, 0x60, 0x5f, 0x6e, 0x5f, 0xf6, 0x13, 0x7c, 0x65, 0xc5, 0x6d, 0x7f, 0xb3, 0x44, 0xcd, 0x52, 0xbc, 0x93, 0x37, 0x4f, 0x3d, 0x16, 0x6c, 0x9f, 0x0c, 0x6f, 0x9c, 0x50, 0x6b, 0xad, 0x19, 0x33, 0x09, 0x72, 0xd2, 0x1c, 0xac, 0x19, 0xce, 0x99, 0x6d } +, + /* Prime exponent 1 */ + 64, + { 0xe8, 0xa6, 0x0d, 0x88, 0x39, 0x54, 0x09, 0x73, 0xa2, 0xdd, 0x4a, 0x3b, 0xd1, 0x48, 0x05, 0x1d, 0xf8, 0xd1, 0x0e, 0x82, 0x87, 0xab, 0xb5, 0x45, 0xb0, 0x0c, 0x29, 0xec, 0x90, 0x7e, 0xfe, 0x16, 0x9f, 0x39, 0xbc, 0x02, 0x2d, 0x56, 0x97, 0x5a, 0xfd, 0x5c, 0xff, 0x82, 0x7e, 0x83, 0xda, 0x86, 0x7e, 0xd7, 0xce, 0x6f, 0xc6, 0xc8, 0xa2, 0xb7, 0xe4, 0xe0, 0x35, 0x75, 0x19, 0xeb, 0x49, 0x61 } +, + /* Prime exponent 2 */ + 64, + { 0x8f, 0xf2, 0xe2, 0x27, 0x37, 0x35, 0xc5, 0x5f, 0x05, 0x56, 0x6a, 0xe7, 0x5f, 0x29, 0xa9, 0xc9, 0x33, 0xa6, 0x2d, 0xef, 0xd7, 0xe2, 0x20, 0x01, 0x7f, 0x05, 0x45, 0xfc, 0xe9, 0x07, 0xe0, 0x65, 0xc4, 0x9f, 0x7b, 0xac, 0x34, 0x84, 0xc6, 0xf0, 0x60, 0x49, 0x99, 0x43, 0x32, 0x07, 0xc9, 0x13, 0xe8, 0x0b, 0xc0, 0x1b, 0xf7, 0x8d, 0x83, 0xef, 0xaf, 0x00, 0xda, 0x17, 0x12, 0xa4, 0xa6, 0x35 } +, + /* Coefficient */ + 64, + { 0x5f, 0x1f, 0xf9, 0x6a, 0x8a, 0x90, 0x19, 0x78, 0x4f, 0x92, 0x26, 0xe2, 0x5c, 0x9b, 0xfe, 0x25, 0x08, 0x02, 0x39, 0x43, 0x73, 0x90, 0x25, 0xdd, 0x6b, 0xab, 0x03, 0x7f, 0xf4, 0x7d, 0xc6, 0x42, 0x49, 0x85, 0x15, 0xc2, 0xf9, 0xe6, 0xff, 0x60, 0x60, 0xc5, 0xb7, 0xd2, 0x34, 0x30, 0xd8, 0xd5, 0x0f, 0x1c, 0x0f, 0x6d, 0x50, 0xc1, 0x80, 0xb4, 0xae, 0xa8, 0xa4, 0xa8, 0x2f, 0xcd, 0x2b, 0x74 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 5.1", + /* Message */ + 53, + { 0x5d, 0xc9, 0xf8, 0xb1, 0x2d, 0xc8, 0x12, 0xa0, 0x9a, 0xa4, 0xb0, 0x6d, 0xfc, 0xb5, 0x7e, 0x1d, 0x2e, 0x8d, 0x1c, 0x7d, 0x2c, 0x07, 0x6b, 0x25, 0xd5, 0xc1, 0x8e, 0xdb, 0xc0, 0x46, 0xbd, 0x63, 0xc7, 0xca, 0x4a, 0x59, 0x9f, 0x18, 0xde, 0x26, 0xf3, 0xbe, 0x73, 0x8c, 0xc2, 0x8d, 0x16, 0x67, 0x2c, 0x00, 0x6e, 0x4d, 0x9c } +, + /* Seed */ + 72, + { 0x43, 0xd6, 0x05, 0xa5, 0x74, 0x0a, 0x97, 0x0b, 0x32, 0x37, 0x27, 0xaf, 0x35, 0x2a, 0x1b, 0xd4, 0x8d, 0xe6, 0x9d, 0x95, 0x05, 0xe2, 0x2c, 0x2f, 0xad, 0x03, 0x0c, 0x3b, 0x84, 0xb6, 0xde, 0xa2, 0xd2, 0x2f, 0x91, 0x64, 0x06, 0xa7, 0x69, 0x3c, 0xf5, 0x06, 0xc2, 0xd2, 0x51, 0x88, 0x6f, 0x02, 0x20, 0x3e, 0x3f, 0x76, 0x55, 0xa3, 0x0a, 0x68, 0x37, 0xaf, 0x8a, 0x8c, 0xbe, 0xc7, 0xb5, 0xc9, 0x2f, 0xc0, 0x4c, 0x8c, 0x18, 0xdf, 0xe9, 0xd3 } +, + /* Encryption */ + 128, + { 0x21, 0x5a, 0x35, 0xf4, 0xc0, 0x43, 0x5b, 0x07, 0xed, 0x5d, 0x2c, 0x4b, 0x68, 0x65, 0xbc, 0x28, 0x1c, 0xea, 0x70, 0x50, 0xcf, 0xea, 0x7a, 0x7e, 0x86, 0xe0, 0x3f, 0x8a, 0xcb, 0x28, 0xb5, 0x8d, 0xbe, 0xe6, 0x54, 0x58, 0x91, 0x9c, 0xea, 0xa5, 0xa3, 0x3e, 0xdd, 0x98, 0x20, 0x1e, 0xa6, 0xe7, 0x63, 0x2d, 0x76, 0x22, 0xd5, 0xa5, 0x1d, 0x35, 0xa3, 0x5f, 0xed, 0xe8, 0x6e, 0xf2, 0x03, 0xee, 0xf6, 0xeb, 0x34, 0x75, 0xec, 0x8f, 0x19, 0xe6, 0x9c, 0x0e, 0xd5, 0x2c, 0x05, 0xdd, 0x7d, 0x59, 0xe3, 0x53, 0xf5, 0x2b, 0x67, 0x10, 0xaf, 0x40, 0x26, 0x65, 0x55, 0x04, 0x10, 0x7d, 0xdb, 0x86, 0xf9, 0x57, 0xe6, 0xc0, 0x6b, 0xa6, 0x7b, 0x1f, 0x4f, 0xc9, 0xf1, 0x21, 0xe1, 0x5f, 0x82, 0x73, 0x67, 0x09, 0xd2, 0xde, 0x8d, 0x77, 0x43, 0x2d, 0xf0, 0x8d, 0xcc, 0xd2, 0xa0, 0xcc, 0x77, 0x04 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 5.2", + /* Message */ + 16, + { 0xd7, 0x74, 0x07, 0xd8, 0xf6, 0x9f, 0x80, 0xdc, 0x08, 0xeb, 0xa5, 0xf4, 0x26, 0x28, 0x2d, 0xe7 } +, + /* Seed */ + 109, + { 0xb8, 0x29, 0xc7, 0x89, 0xbe, 0x38, 0x1c, 0xd5, 0x9d, 0xe2, 0x14, 0x89, 0xdb, 0xa1, 0x41, 0xe0, 0xbd, 0x1f, 0xa8, 0xa3, 0xc3, 0x82, 0x6d, 0x59, 0xc6, 0xd1, 0x10, 0xe7, 0xdf, 0x72, 0x42, 0xba, 0x98, 0xc4, 0x7a, 0x43, 0x92, 0xc7, 0xf2, 0xac, 0x1c, 0x6e, 0x9d, 0xae, 0x22, 0xb9, 0xeb, 0x74, 0xa7, 0x64, 0x36, 0x08, 0x8b, 0xd0, 0xba, 0x6e, 0x19, 0x91, 0xe1, 0x9e, 0x3a, 0xf7, 0x9c, 0xf3, 0xf7, 0xde, 0xfb, 0x6a, 0x11, 0x61, 0x80, 0x25, 0x34, 0xba, 0x0e, 0x7e, 0xd1, 0x65, 0x34, 0x93, 0x88, 0x72, 0xec, 0xa6, 0x77, 0x05, 0x8a, 0xc7, 0x34, 0x67, 0xd4, 0x9e, 0xd1, 0x12, 0x5b, 0x50, 0xdf, 0xe5, 0xd6, 0xd6, 0x5a, 0x5d, 0x24, 0x53, 0x99, 0xb6, 0xbf, 0x1b, 0xf1 } +, + /* Encryption */ + 128, + { 0x2d, 0x48, 0x06, 0xcf, 0xaf, 0xe4, 0xaf, 0x36, 0xbd, 0x02, 0xf6, 0x2d, 0x6a, 0x43, 0xb0, 0x0b, 0x41, 0x6f, 0x70, 0x8e, 0x96, 0x85, 0xb1, 0x7a, 0xc8, 0xe3, 0xa4, 0xd8, 0xc2, 0x91, 0x80, 0x93, 0x05, 0x76, 0x9d, 0x78, 0x98, 0xf6, 0xfc, 0x85, 0x91, 0x7b, 0xa2, 0xfd, 0x8e, 0x58, 0x9f, 0xf7, 0xa8, 0xbb, 0x84, 0xbb, 0x7c, 0x12, 0x20, 0x2e, 0xd2, 0x79, 0xe0, 0x64, 0x09, 0xa5, 0xc0, 0xa7, 0xd3, 0x24, 0xbc, 0x46, 0xae, 0x4f, 0x92, 0x82, 0xc9, 0x02, 0x3d, 0x3d, 0xfb, 0x3a, 0x79, 0x15, 0xde, 0xfc, 0x16, 0x4b, 0x3f, 0x08, 0x26, 0x6a, 0xcf, 0x12, 0x41, 0xf8, 0x26, 0x24, 0x98, 0x15, 0x07, 0x41, 0x4e, 0x56, 0x29, 0x78, 0x35, 0x1d, 0xc8, 0xb7, 0xa7, 0x9e, 0xf5, 0x31, 0x40, 0x21, 0x01, 0xa8, 0xd3, 0xd3, 0xea, 0xa3, 0x53, 0x9b, 0xbf, 0x62, 0xaa, 0xd9, 0x9a, 0x3b, 0xb1, 0x1e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.3", + /* Message */ + 2, + { 0x23, 0x8a } +, + /* Seed */ + 123, + { 0xa5, 0x88, 0x1a, 0xcf, 0xf3, 0x52, 0x9f, 0x25, 0x1b, 0x1b, 0x9c, 0x61, 0x9c, 0xe9, 0xf9, 0xdf, 0x91, 0xe0, 0xa0, 0x3d, 0xd8, 0x89, 0x16, 0x36, 0x46, 0x87, 0x1a, 0x62, 0x72, 0x07, 0xee, 0xf1, 0x47, 0x68, 0x0c, 0x32, 0xf4, 0x50, 0xa7, 0x76, 0xe1, 0x9f, 0x54, 0xec, 0x05, 0x5d, 0xc6, 0x8b, 0x04, 0xbd, 0x4d, 0x89, 0x37, 0x6d, 0xf3, 0xea, 0xfa, 0x6f, 0xca, 0xf6, 0x0e, 0xb8, 0x31, 0x84, 0x39, 0x10, 0xb6, 0x25, 0xb6, 0x4f, 0x25, 0xd9, 0x29, 0x9a, 0xfc, 0x30, 0x6a, 0x23, 0x76, 0x53, 0x80, 0x45, 0x51, 0x94, 0xb7, 0x5d, 0xc0, 0x13, 0x5d, 0x27, 0xc3, 0xb7, 0xd7, 0x2d, 0xf9, 0x08, 0x77, 0x5c, 0x7e, 0x90, 0xbe, 0xfc, 0x0c, 0x5a, 0xdf, 0x74, 0xa1, 0x69, 0xed, 0x58, 0x68, 0xf3, 0xd6, 0x34, 0x32, 0x7a, 0x05, 0x78, 0x18, 0x92, 0x54, 0x45, 0x43 } +, + /* Encryption */ + 128, + { 0x77, 0x10, 0xee, 0xa8, 0x65, 0x7d, 0xfd, 0x15, 0x65, 0x16, 0x65, 0x62, 0xdf, 0x0e, 0x2e, 0x84, 0x0e, 0xc3, 0xe3, 0xde, 0xdc, 0x0b, 0x80, 0x2b, 0xb0, 0x21, 0x3e, 0x47, 0xa5, 0xce, 0x97, 0xf4, 0xb8, 0x5b, 0xa9, 0xba, 0x14, 0x19, 0x77, 0x36, 0x3d, 0x8f, 0x54, 0xb0, 0x6d, 0x57, 0x8d, 0x5b, 0x2a, 0x96, 0xe9, 0x69, 0xcf, 0xa9, 0x15, 0xdf, 0x21, 0x9f, 0x00, 0x2a, 0x85, 0xd0, 0x32, 0x57, 0x04, 0x7b, 0x31, 0x16, 0xa1, 0xc4, 0xdd, 0xaf, 0x79, 0x1d, 0x93, 0x98, 0x2d, 0x1b, 0x9f, 0xfa, 0x24, 0x31, 0x86, 0xe9, 0xe2, 0xb1, 0x9e, 0xf0, 0x74, 0x1c, 0xe9, 0x8d, 0xe2, 0xa4, 0xa1, 0x58, 0x6e, 0x50, 0x12, 0xc4, 0x81, 0xde, 0x23, 0xa0, 0xef, 0xf8, 0x82, 0xfd, 0x62, 0x38, 0x38, 0xd2, 0x01, 0x1f, 0x4f, 0x63, 0x73, 0x8a, 0xff, 0xd7, 0xef, 0xb8, 0xc5, 0x0f, 0x46, 0xa6, 0xc2, 0x0e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.4", + /* Message */ + 33, + { 0x25, 0xa2, 0x7e, 0xb1, 0xb2, 0x1f, 0x10, 0xcf, 0x9d, 0x57, 0x1c, 0x33, 0x05, 0x61, 0x0b, 0x97, 0xf0, 0xda, 0xee, 0x39, 0x90, 0x5c, 0x65, 0x94, 0xbf, 0xbf, 0x45, 0x2a, 0x9a, 0x00, 0xd9, 0xe8, 0x2b } +, + /* Seed */ + 92, + { 0x25, 0x04, 0x61, 0x80, 0x11, 0xc6, 0x73, 0xdb, 0x3c, 0x41, 0x22, 0x79, 0xdc, 0x8a, 0xd1, 0x65, 0xab, 0x7b, 0x64, 0x73, 0xae, 0x19, 0x5e, 0x8d, 0x6d, 0x41, 0x21, 0x49, 0x18, 0x19, 0x8b, 0x34, 0x51, 0xa6, 0x50, 0x8d, 0x61, 0x38, 0xce, 0xdc, 0x51, 0x8d, 0x80, 0x12, 0xba, 0x0e, 0xc7, 0x9b, 0x38, 0x6a, 0xf8, 0xfa, 0x40, 0xb0, 0x34, 0x78, 0xbb, 0xf2, 0xba, 0x06, 0x5e, 0x58, 0x2d, 0x61, 0x95, 0xcc, 0xbe, 0x15, 0x8f, 0x11, 0x78, 0x1e, 0xae, 0xb1, 0xb1, 0x72, 0x0b, 0x72, 0xd9, 0xb5, 0x21, 0x27, 0xde, 0xb9, 0x55, 0x17, 0x11, 0xe8, 0x87, 0xdb, 0xd0, 0xb8 } +, + /* Encryption */ + 128, + { 0x35, 0x72, 0xbd, 0xea, 0x23, 0x05, 0xe1, 0x78, 0x5c, 0x75, 0x4d, 0xe7, 0x44, 0xc4, 0xfa, 0x3f, 0xa2, 0xcb, 0x75, 0x71, 0x60, 0xe5, 0xcb, 0x39, 0xa3, 0x14, 0x97, 0xe1, 0x48, 0x5b, 0xbd, 0x7c, 0x08, 0x99, 0xc5, 0x35, 0x85, 0xb2, 0xbb, 0xbb, 0xd9, 0x90, 0x81, 0xb4, 0x16, 0xef, 0xc6, 0x85, 0x78, 0xdb, 0x78, 0xe0, 0xec, 0xd0, 0x8d, 0xa7, 0xa3, 0x95, 0x3e, 0x38, 0x6b, 0xb2, 0x5c, 0x12, 0xbb, 0xb8, 0x7c, 0x78, 0x94, 0x42, 0x83, 0xa8, 0xc8, 0x01, 0x87, 0xb4, 0x50, 0x8d, 0xab, 0xbc, 0x76, 0x97, 0xf4, 0x3a, 0x8a, 0xe7, 0x8a, 0x33, 0xfe, 0xbb, 0x15, 0xf3, 0xcd, 0x58, 0x1c, 0x80, 0xd4, 0x9b, 0x97, 0x1b, 0xcb, 0xd4, 0x8e, 0x44, 0x14, 0x2f, 0x58, 0xc2, 0xc9, 0x1a, 0xdb, 0x1a, 0xe1, 0x45, 0xaa, 0x9a, 0x83, 0xb3, 0xc5, 0x81, 0x5a, 0xa1, 0xa8, 0xff, 0x8d, 0xd2, 0x31, 0xfe } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.5", + /* Message */ + 6, + { 0x59, 0xcf, 0x0b, 0x6b, 0x50, 0xea } +, + /* Seed */ + 119, + { 0x2b, 0xf1, 0x91, 0x60, 0xdf, 0x69, 0x88, 0x93, 0x5b, 0xd2, 0x46, 0x10, 0x6b, 0x89, 0x09, 0xdd, 0x7b, 0xb3, 0xe5, 0x16, 0x90, 0xdf, 0x84, 0xd7, 0x6e, 0x4d, 0x31, 0xac, 0x82, 0x10, 0x44, 0x56, 0x34, 0x6b, 0x4c, 0x3c, 0x9b, 0xa7, 0xb5, 0xe9, 0xe6, 0x8e, 0xe2, 0x08, 0x6c, 0x84, 0x73, 0xc6, 0x83, 0x02, 0xe2, 0x59, 0x9a, 0xbf, 0x6b, 0x31, 0xce, 0xb3, 0xf7, 0x81, 0xad, 0x6b, 0x56, 0x89, 0x86, 0xf2, 0x1c, 0xd6, 0xd7, 0x55, 0x32, 0x8f, 0xb8, 0x3a, 0xfd, 0x55, 0x48, 0x50, 0x1d, 0x07, 0x0a, 0xc2, 0xdd, 0x8f, 0x5c, 0xdf, 0xb6, 0x2c, 0xef, 0x54, 0x5e, 0x81, 0x5f, 0xe3, 0x82, 0xbc, 0x0c, 0x67, 0xb6, 0x76, 0xe5, 0x45, 0x6e, 0xbb, 0x9a, 0xb6, 0x7d, 0xf4, 0x77, 0x40, 0xc6, 0xa4, 0x3d, 0xe3, 0xf9, 0xa2, 0x47, 0x7a, 0x9b } +, + /* Encryption */ + 128, + { 0x2e, 0xd5, 0x91, 0xfd, 0x4b, 0x35, 0x7e, 0x94, 0xf4, 0x81, 0xba, 0x84, 0xff, 0x4e, 0xbe, 0x7a, 0xe4, 0x31, 0x05, 0x4e, 0x5c, 0xd9, 0x8a, 0x99, 0x58, 0x96, 0x48, 0xe6, 0x16, 0xcd, 0x68, 0xe0, 0xd4, 0x72, 0x4f, 0xa8, 0xa6, 0xc5, 0x99, 0x68, 0x6b, 0xfe, 0xe1, 0x74, 0x7a, 0xd0, 0x77, 0xdb, 0xed, 0xad, 0x45, 0xf1, 0x24, 0x4d, 0x7f, 0x8e, 0x00, 0xda, 0x3a, 0x3a, 0x06, 0xd2, 0x31, 0x32, 0xd3, 0x17, 0x1d, 0x74, 0x4e, 0xf1, 0x4e, 0x1e, 0x97, 0xcd, 0xda, 0x10, 0x9b, 0xd2, 0xe5, 0x56, 0xa5, 0xfc, 0x7b, 0xbc, 0x60, 0x9a, 0x7f, 0xf2, 0x4c, 0xfa, 0xbe, 0xf4, 0xb5, 0x6c, 0xbb, 0xb7, 0x0e, 0x05, 0x06, 0x53, 0xb6, 0x98, 0x48, 0xd7, 0x11, 0x30, 0x75, 0xa5, 0xde, 0xbe, 0x7a, 0x46, 0x82, 0x15, 0xf8, 0xdc, 0x08, 0xe7, 0xef, 0x84, 0xfd, 0x55, 0x77, 0x8c, 0xd5, 0xb5, 0x96, 0xe5 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.6", + /* Message */ + 57, + { 0xe9, 0x44, 0x52, 0xf5, 0x0a, 0x5e, 0xdb, 0xe6, 0x75, 0x73, 0xab, 0x22, 0x30, 0x9f, 0xa2, 0x1b, 0xab, 0xc6, 0xd2, 0x25, 0x20, 0xe6, 0xe8, 0x3b, 0xf7, 0x2e, 0x7a, 0xfa, 0x6d, 0x71, 0xe2, 0x02, 0x96, 0xda, 0xea, 0xf5, 0x4a, 0x60, 0xc8, 0x03, 0x63, 0x04, 0x87, 0x9a, 0x21, 0x31, 0xd1, 0x78, 0x78, 0x0e, 0x34, 0x8e, 0xe0, 0x12, 0x0b, 0x99, 0x7c } +, + /* Seed */ + 68, + { 0xc5, 0x30, 0x44, 0x3a, 0x16, 0xef, 0xd8, 0xd6, 0xd7, 0x2a, 0xb4, 0x44, 0x3f, 0x8d, 0xb2, 0x44, 0x91, 0xde, 0x99, 0xd5, 0xaa, 0xbe, 0x51, 0x88, 0xb3, 0xf6, 0x1d, 0xc0, 0x48, 0x3b, 0x7e, 0xe0, 0x0b, 0x1c, 0x13, 0x25, 0x9b, 0x8a, 0xe2, 0x40, 0x9f, 0x1a, 0xe6, 0x2d, 0x99, 0x30, 0xc1, 0x1a, 0x4d, 0xde, 0xf3, 0xe8, 0x35, 0x82, 0x93, 0x88, 0x93, 0xf9, 0xac, 0x66, 0x8f, 0x79, 0xc6, 0x4c, 0x7f, 0x5d, 0x79, 0x6d } +, + /* Encryption */ + 128, + { 0x0e, 0xee, 0x90, 0xc7, 0x08, 0x18, 0x22, 0x1a, 0xe2, 0x70, 0x4b, 0xbe, 0x38, 0xd6, 0x8f, 0x8e, 0x15, 0x4c, 0x6e, 0xe7, 0xad, 0xe5, 0x3e, 0x2a, 0x1f, 0x4d, 0x1d, 0xba, 0xac, 0x98, 0xc5, 0x75, 0x91, 0xeb, 0xb6, 0xc6, 0x38, 0xbc, 0xb6, 0x8e, 0x18, 0x14, 0x35, 0xb7, 0x00, 0x01, 0xba, 0xd1, 0x80, 0x19, 0x2b, 0xfd, 0xa0, 0x57, 0x32, 0xc0, 0x5e, 0x7f, 0xb5, 0xaf, 0x22, 0xaa, 0x89, 0xd2, 0xa8, 0xff, 0x80, 0xcf, 0x9f, 0x08, 0x62, 0xf0, 0x4c, 0x05, 0xca, 0xca, 0x3d, 0x2a, 0x3a, 0x5b, 0x07, 0x79, 0x94, 0x6c, 0x6d, 0xdf, 0xa0, 0x4c, 0xd7, 0x9f, 0xa1, 0x64, 0xd6, 0x02, 0xf1, 0xb7, 0xde, 0x5c, 0x95, 0xbe, 0x85, 0xe9, 0x60, 0x84, 0x67, 0xe2, 0x5c, 0x29, 0xd0, 0x35, 0xc4, 0x66, 0x09, 0x06, 0x26, 0x9f, 0x6d, 0xc0, 0x0a, 0x47, 0x2b, 0x04, 0x46, 0xea, 0x56, 0xe7, 0x2a, 0x59 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.7", + /* Message */ + 44, + { 0x1c, 0xbf, 0xa0, 0xe7, 0xb1, 0xa1, 0x0c, 0x13, 0xd7, 0x50, 0x77, 0xb1, 0xcb, 0xd8, 0x03, 0x10, 0xcd, 0x24, 0x10, 0x34, 0x0d, 0x5f, 0x53, 0x72, 0x93, 0x46, 0x4a, 0x67, 0x81, 0xa9, 0xcc, 0x30, 0x2c, 0xb5, 0x38, 0x0e, 0xd9, 0x26, 0x7b, 0x3e, 0xb2, 0x3c, 0xdb, 0x13 } +, + /* Seed */ + 81, + { 0xd3, 0x6b, 0x7e, 0x17, 0x99, 0x05, 0x9d, 0x1e, 0xd1, 0x34, 0x7b, 0x0b, 0xf8, 0x24, 0x7c, 0x6b, 0xe5, 0x18, 0x7d, 0x8f, 0x15, 0x21, 0x9e, 0x3c, 0xb6, 0x6e, 0xc6, 0x2e, 0x1a, 0xc4, 0x1f, 0xf7, 0xed, 0x35, 0x7e, 0xd7, 0xca, 0x03, 0x84, 0xe3, 0x1d, 0x39, 0x94, 0x85, 0x61, 0xfc, 0x16, 0xcb, 0xd9, 0x6b, 0x7e, 0x70, 0x42, 0x79, 0xe5, 0x72, 0xbf, 0x56, 0x4e, 0x06, 0xc3, 0xa3, 0x40, 0x1a, 0x27, 0x14, 0xdd, 0x51, 0xd7, 0x21, 0x5b, 0xeb, 0xa1, 0xc6, 0x61, 0x54, 0xf6, 0x0d, 0xd0, 0xcd, 0x4d } +, + /* Encryption */ + 128, + { 0x9c, 0x03, 0xdc, 0x01, 0x33, 0xa6, 0xe6, 0xaa, 0xba, 0x92, 0x05, 0x9b, 0xdf, 0x5a, 0x6c, 0xc1, 0xb1, 0x44, 0xb9, 0x0d, 0x2a, 0x94, 0xa4, 0x8e, 0x7b, 0x3c, 0xb9, 0x0b, 0x0b, 0xb6, 0xf6, 0x24, 0xc7, 0xb1, 0xd1, 0x72, 0x33, 0x1e, 0x43, 0x23, 0xd0, 0x8d, 0x2e, 0x8e, 0x09, 0x95, 0x32, 0xdc, 0xb3, 0xb2, 0xa8, 0x7c, 0xa4, 0x20, 0x74, 0x9f, 0xc6, 0x34, 0x5c, 0x0d, 0x86, 0xe9, 0xab, 0xca, 0x71, 0xaf, 0x09, 0xa0, 0x92, 0x9e, 0xde, 0xee, 0xde, 0x83, 0xe7, 0x22, 0x44, 0x20, 0x3b, 0x2b, 0xf4, 0x5c, 0xeb, 0x18, 0x7e, 0x9d, 0xb3, 0xc7, 0xd3, 0xad, 0x05, 0xb2, 0x3b, 0x59, 0x62, 0x4c, 0x24, 0x66, 0x96, 0xcf, 0xc7, 0x58, 0x06, 0x39, 0x14, 0x02, 0xe4, 0x44, 0xe3, 0x97, 0x49, 0x69, 0x88, 0xe1, 0xe1, 0xf4, 0x2c, 0x6a, 0xde, 0xd3, 0x0c, 0xdc, 0x93, 0x79, 0x37, 0xf3, 0x00, 0x54 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.8", + /* Message */ + 64, + { 0xe1, 0x72, 0xa6, 0xb8, 0xb4, 0x96, 0xf0, 0x77, 0x73, 0x8b, 0x74, 0xf6, 0xd8, 0xb2, 0x92, 0xdd, 0xa6, 0x07, 0xf2, 0xad, 0xbf, 0xb3, 0x72, 0xbe, 0x37, 0xee, 0x00, 0x08, 0x88, 0xbe, 0xa3, 0x1f, 0x99, 0xcb, 0xa1, 0xcf, 0x39, 0x32, 0xe4, 0xbe, 0x37, 0x17, 0xc9, 0xe1, 0x68, 0x90, 0x1a, 0x32, 0xd1, 0xb8, 0x20, 0xbe, 0x4f, 0xb0, 0x13, 0x75, 0x27, 0xa2, 0x48, 0x18, 0x77, 0xfe, 0x01, 0xee } +, + /* Seed */ + 61, + { 0x84, 0x0c, 0xe1, 0x3b, 0xbc, 0x96, 0x17, 0xdc, 0x9f, 0x3f, 0x26, 0xb1, 0x47, 0x30, 0x1a, 0x6f, 0x46, 0x30, 0x0d, 0x77, 0x81, 0xa5, 0xd9, 0x81, 0x16, 0x2f, 0x86, 0x92, 0x87, 0x37, 0x1f, 0x1d, 0x59, 0x58, 0x76, 0x4f, 0xb0, 0x0b, 0x05, 0x53, 0x70, 0xec, 0x71, 0x1b, 0xba, 0x52, 0x83, 0xfc, 0xb0, 0x0b, 0x83, 0xbc, 0x02, 0x17, 0x5e, 0xa1, 0x01, 0x7b, 0xcc, 0x83, 0x53 } +, + /* Encryption */ + 128, + { 0x99, 0x3e, 0x39, 0x6f, 0xb5, 0x7b, 0x2e, 0xa6, 0xa1, 0xa3, 0xfc, 0xed, 0x9a, 0x69, 0xd3, 0x61, 0xcb, 0xb6, 0x26, 0x5b, 0x26, 0x50, 0x3c, 0x17, 0x5f, 0x84, 0xc6, 0x1a, 0x41, 0xea, 0x3e, 0x1c, 0xe4, 0xfb, 0xb6, 0x2e, 0x01, 0xd6, 0x42, 0x0e, 0x22, 0xfe, 0xf1, 0xd9, 0xe2, 0x8a, 0x58, 0x83, 0xe2, 0xea, 0xc8, 0x2e, 0x05, 0xf3, 0x58, 0xea, 0x75, 0xf7, 0x7d, 0xa4, 0x89, 0x7b, 0x6b, 0x64, 0x9a, 0xa4, 0x74, 0x28, 0x39, 0x41, 0x93, 0xdd, 0xec, 0x64, 0x8c, 0x3a, 0x7f, 0xb8, 0x1c, 0xfc, 0xf4, 0xb5, 0x1c, 0xe3, 0xeb, 0xba, 0x78, 0xae, 0xdc, 0xa7, 0xbb, 0x91, 0x7b, 0x35, 0xb3, 0xe2, 0x2a, 0xeb, 0x20, 0x1c, 0xea, 0x96, 0x59, 0x2e, 0x50, 0xe0, 0xd2, 0x84, 0x1e, 0x7d, 0x2c, 0xe0, 0xd6, 0x9f, 0xf3, 0x03, 0x9d, 0xc0, 0x1e, 0x96, 0x4a, 0x97, 0x7a, 0x01, 0x76, 0x83, 0xb3, 0x87 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.9", + /* Message */ + 55, + { 0xc8, 0xf0, 0xea, 0x23, 0xe0, 0x66, 0x11, 0xe4, 0xfd, 0x27, 0xb6, 0x1d, 0xb7, 0x92, 0x0c, 0x55, 0xf3, 0xc0, 0xa2, 0x22, 0x12, 0x88, 0x38, 0xe4, 0xcd, 0xb0, 0x62, 0xe1, 0x76, 0xb2, 0x1f, 0xc2, 0x32, 0x53, 0x55, 0x8c, 0x5d, 0x40, 0xde, 0x2d, 0xfd, 0x62, 0x0f, 0xb7, 0xcd, 0xf1, 0x39, 0x9c, 0x2a, 0xf8, 0xfc, 0x77, 0xca, 0x33, 0x35 } +, + /* Seed */ + 70, + { 0x16, 0x4d, 0x77, 0xb5, 0xd2, 0x6a, 0xe6, 0xd7, 0xab, 0xe7, 0xca, 0xed, 0x62, 0x5d, 0x87, 0xc2, 0x11, 0xcc, 0x50, 0x9a, 0xd0, 0x17, 0x2c, 0x20, 0x83, 0x3d, 0x8f, 0x98, 0xca, 0xe3, 0x8a, 0x2c, 0x37, 0x0e, 0xf2, 0x1d, 0x40, 0x96, 0xda, 0x84, 0x1d, 0xbe, 0xee, 0x94, 0x8e, 0xc6, 0x34, 0x03, 0xca, 0xbd, 0x4a, 0x5f, 0x71, 0xac, 0xe4, 0x93, 0x64, 0xaa, 0x7d, 0xe2, 0x0f, 0x32, 0xc9, 0x88, 0x33, 0x7a, 0x11, 0x5f, 0x83, 0x46 } +, + /* Encryption */ + 128, + { 0x7a, 0x8f, 0x15, 0xee, 0xf5, 0x10, 0xad, 0xe8, 0xd5, 0xc3, 0x17, 0xf9, 0x06, 0x4a, 0xd7, 0xda, 0xe6, 0xc9, 0x3e, 0x7c, 0xf1, 0x56, 0xa7, 0x37, 0x22, 0x02, 0x32, 0x58, 0xf8, 0xb5, 0x74, 0x47, 0x34, 0x70, 0x00, 0x34, 0xa3, 0xde, 0x6f, 0x13, 0x7a, 0xf6, 0xe9, 0x00, 0x46, 0xd8, 0x6e, 0x9b, 0x90, 0x59, 0x0f, 0xa5, 0xa6, 0x50, 0xce, 0xf4, 0xfd, 0xb4, 0xd3, 0x36, 0x02, 0x33, 0xaf, 0x86, 0xf4, 0xa7, 0xa2, 0x3c, 0x24, 0x3d, 0x19, 0x51, 0xc6, 0x66, 0xb6, 0x73, 0xc3, 0x3c, 0x7d, 0xec, 0x4f, 0x51, 0xac, 0xe3, 0x4b, 0x80, 0x5c, 0x0a, 0x9e, 0x67, 0xe2, 0x09, 0xcc, 0x7f, 0x9e, 0xd6, 0x9b, 0x8f, 0x5e, 0xb5, 0xc5, 0x53, 0xe0, 0xf1, 0x5c, 0x10, 0x30, 0x4b, 0xf5, 0x6d, 0x7b, 0xe1, 0x71, 0xf3, 0x1c, 0xce, 0x88, 0xf3, 0x7d, 0x1f, 0xb4, 0xa2, 0xa0, 0x04, 0x18, 0x89, 0x75, 0x76 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.10", + /* Message */ + 49, + { 0x19, 0xdb, 0x24, 0x22, 0x05, 0xc0, 0x3d, 0x7f, 0xa9, 0x93, 0x5d, 0x9e, 0x04, 0xfa, 0x6e, 0xcf, 0x38, 0xa5, 0x1e, 0xa9, 0x98, 0xac, 0x8e, 0x4b, 0xac, 0xa6, 0xcd, 0xfd, 0x6a, 0x0a, 0xce, 0x1d, 0xf3, 0x67, 0xe7, 0x3d, 0x23, 0xc2, 0x40, 0xaf, 0x76, 0xb6, 0x2e, 0x9f, 0xe9, 0x21, 0x5f, 0xe9, 0x43 } +, + /* Seed */ + 76, + { 0xbe, 0x49, 0x52, 0x05, 0x55, 0x69, 0x56, 0xfa, 0xe2, 0xa2, 0x2e, 0xa7, 0x0c, 0xe1, 0x02, 0xde, 0x06, 0x6c, 0x9e, 0x58, 0x95, 0x96, 0x06, 0x21, 0x74, 0x84, 0xa5, 0xb1, 0x50, 0x36, 0xff, 0xa1, 0xd4, 0x61, 0x23, 0x9d, 0xd4, 0x7b, 0x4f, 0x38, 0x1c, 0xea, 0x71, 0x51, 0x6e, 0x2d, 0xb0, 0xfc, 0x36, 0x9d, 0x72, 0xb4, 0x40, 0x69, 0x65, 0x12, 0xa9, 0x72, 0x88, 0xf0, 0x6f, 0xc0, 0xbc, 0xeb, 0x96, 0x82, 0x86, 0xe9, 0x95, 0xe0, 0x2d, 0x21, 0x8d, 0x9c, 0x26, 0x62 } +, + /* Encryption */ + 128, + { 0x55, 0x12, 0xb3, 0x99, 0x9b, 0x30, 0xc9, 0xc1, 0x44, 0x0e, 0x59, 0x75, 0x93, 0x1d, 0x55, 0xf2, 0x1e, 0x9e, 0xb4, 0x22, 0xb6, 0x2d, 0xaf, 0xcd, 0xab, 0x5d, 0x50, 0x03, 0xa7, 0x5e, 0xb1, 0x24, 0x81, 0x99, 0x86, 0x36, 0x19, 0x13, 0x36, 0x1d, 0xfc, 0x46, 0xac, 0x29, 0xaa, 0xba, 0x8e, 0x1a, 0xa0, 0x2e, 0x1b, 0xa4, 0x44, 0x67, 0x16, 0x2d, 0x20, 0xf6, 0x3a, 0xd1, 0x70, 0xfe, 0x0d, 0x87, 0xa5, 0x3d, 0x93, 0xc6, 0x4e, 0x02, 0x6b, 0x12, 0xbe, 0x6b, 0xc2, 0xb8, 0xeb, 0x0e, 0x57, 0xc0, 0x39, 0xeb, 0x60, 0xf3, 0x2c, 0x4b, 0x52, 0x70, 0x35, 0xf7, 0x03, 0xa7, 0xa8, 0x37, 0x4b, 0xd7, 0xfa, 0xa7, 0xb5, 0x40, 0x4a, 0x3c, 0x5a, 0xad, 0xb7, 0x92, 0xe2, 0x5f, 0xf9, 0x28, 0x76, 0xb2, 0x3d, 0xd3, 0xa7, 0x42, 0x2c, 0x45, 0x26, 0x6c, 0x6d, 0x98, 0x6e, 0xec, 0x53, 0x34, 0xb9, 0xba } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.11", + /* Message */ + 35, + { 0x49, 0xa7, 0x61, 0xf8, 0xc1, 0x8e, 0xf9, 0x23, 0x62, 0xd6, 0xab, 0xb2, 0x4c, 0x07, 0xfc, 0x72, 0x82, 0x55, 0x84, 0x24, 0x53, 0x69, 0x4e, 0x17, 0x60, 0x58, 0x99, 0xf4, 0x37, 0xb3, 0x1a, 0xc9, 0x8d, 0xb5, 0x16 } +, + /* Seed */ + 90, + { 0xd8, 0xcd, 0x85, 0xed, 0xfa, 0x0a, 0x84, 0xd0, 0x76, 0xa9, 0xf8, 0xb2, 0xf9, 0x3d, 0xaa, 0xeb, 0xa9, 0xae, 0x37, 0x43, 0x81, 0xea, 0x4f, 0x8c, 0xea, 0xbc, 0x14, 0xf6, 0x2a, 0x4e, 0xd7, 0x63, 0x8c, 0x1e, 0x39, 0x67, 0x57, 0xde, 0x3a, 0xe2, 0xb7, 0xef, 0xa3, 0xa1, 0x7c, 0x9a, 0x55, 0x86, 0xda, 0x84, 0xa5, 0xe5, 0x0e, 0xcd, 0xed, 0x61, 0x08, 0x7f, 0xa6, 0xf0, 0xce, 0x93, 0x82, 0x87, 0x99, 0x8a, 0xc1, 0xb9, 0xbc, 0x33, 0x21, 0xa7, 0xed, 0x16, 0x0d, 0x28, 0x67, 0x04, 0xe0, 0x52, 0x6e, 0xce, 0x7b, 0x30, 0xb4, 0x68, 0x14, 0x64, 0x9f, 0xec } +, + /* Encryption */ + 128, + { 0x9b, 0x47, 0x82, 0x68, 0x40, 0x62, 0x12, 0xca, 0x05, 0x30, 0xf4, 0x31, 0xbd, 0xb2, 0x63, 0x72, 0x61, 0x50, 0x84, 0xca, 0x48, 0x8d, 0xa4, 0x34, 0x51, 0xd2, 0x5a, 0x22, 0xb3, 0x5a, 0xc6, 0xfc, 0x61, 0xe3, 0x70, 0x74, 0xa5, 0xc2, 0x2b, 0xc1, 0xc7, 0x01, 0xdb, 0x19, 0x32, 0xb8, 0xc5, 0x57, 0xb8, 0x48, 0x7c, 0xea, 0x56, 0x60, 0x50, 0xe4, 0x8a, 0xd6, 0xe0, 0x37, 0x6f, 0x8d, 0xb4, 0x19, 0x8c, 0x4d, 0x27, 0xdb, 0x2e, 0x6b, 0x28, 0xc2, 0x5a, 0xed, 0x83, 0x7e, 0xf4, 0x77, 0x42, 0xd5, 0xeb, 0x8e, 0xb1, 0xd8, 0xb4, 0x32, 0xc9, 0xd5, 0x73, 0xcd, 0x4b, 0x86, 0xfd, 0xf3, 0x2c, 0x52, 0xa3, 0xd0, 0xf6, 0xcf, 0x92, 0xcf, 0x3c, 0xd9, 0x51, 0x96, 0x77, 0xa5, 0x8b, 0x1d, 0x1d, 0x99, 0x4f, 0xc1, 0xc9, 0x05, 0x7a, 0xc1, 0x06, 0xe8, 0x16, 0x04, 0x59, 0x26, 0xb4, 0x5b, 0x00, 0xe5 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.12", + /* Message */ + 10, + { 0x84, 0xe8, 0x28, 0xf7, 0x15, 0xf2, 0x28, 0xa6, 0x02, 0x65 } +, + /* Seed */ + 115, + { 0xf7, 0xf2, 0x75, 0xa8, 0x53, 0xd4, 0xe1, 0x26, 0xd7, 0xd0, 0xc3, 0x8e, 0xf7, 0x03, 0xf3, 0xfb, 0xda, 0x7a, 0x95, 0x20, 0x78, 0x8d, 0x7a, 0x81, 0xa3, 0x1b, 0x05, 0x30, 0xd4, 0x3f, 0xe6, 0xc9, 0x4b, 0x1b, 0x1b, 0xb1, 0x08, 0x51, 0x20, 0x9d, 0xb2, 0x6a, 0xc4, 0xb8, 0x88, 0xae, 0xce, 0xea, 0x77, 0x13, 0x82, 0x4c, 0x29, 0x38, 0xb4, 0xc6, 0x43, 0x1b, 0x2b, 0x03, 0xc6, 0x93, 0xab, 0x7b, 0x54, 0x63, 0x15, 0x41, 0x54, 0x6a, 0xc4, 0x03, 0x94, 0x79, 0x85, 0x48, 0xfb, 0xba, 0x95, 0x88, 0x2d, 0x91, 0xa1, 0x7c, 0x27, 0xe7, 0xdd, 0x53, 0x02, 0x6c, 0x96, 0x79, 0x1e, 0xe5, 0x5f, 0x24, 0x7d, 0x7f, 0x89, 0x8f, 0xea, 0xb3, 0x70, 0x9a, 0x13, 0x2a, 0x78, 0x26, 0x66, 0xa1, 0x4d, 0x0d, 0xf1, 0xa8, 0x4e } +, + /* Encryption */ + 128, + { 0x4e, 0x3f, 0xe9, 0x6e, 0x8f, 0x96, 0xe5, 0xb3, 0xc6, 0x11, 0xca, 0xdb, 0x96, 0xed, 0x51, 0x04, 0x20, 0x98, 0xec, 0xc5, 0x47, 0xbe, 0x7b, 0x88, 0xf8, 0xde, 0xa7, 0x65, 0xae, 0x14, 0xe8, 0x35, 0x0c, 0xfe, 0x39, 0xdc, 0xb1, 0xc1, 0xd6, 0xe4, 0x17, 0x9c, 0xa4, 0x04, 0xd5, 0x38, 0x4d, 0x87, 0xb0, 0x66, 0x50, 0x75, 0xee, 0xd7, 0xda, 0x7a, 0xaf, 0x71, 0x00, 0x8e, 0x24, 0x67, 0xd7, 0x0b, 0xff, 0xf6, 0x23, 0xb4, 0x59, 0x4b, 0x6d, 0xff, 0xf9, 0x0e, 0x3d, 0x84, 0x85, 0xf9, 0x41, 0x89, 0x48, 0x6c, 0xa0, 0xca, 0x9e, 0x72, 0x2b, 0x2a, 0x77, 0x7e, 0x25, 0xb5, 0x82, 0xf7, 0xad, 0x4e, 0xc5, 0x10, 0x3a, 0xd7, 0x67, 0x85, 0x9a, 0xc5, 0x9a, 0x1b, 0x8c, 0x5c, 0x19, 0x71, 0x30, 0x17, 0x48, 0xfc, 0xc2, 0x64, 0xf6, 0xc9, 0x29, 0x36, 0x4a, 0x8d, 0x9a, 0xf4, 0x22, 0x55, 0xc0, 0xf6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.13", + /* Message */ + 51, + { 0xc4, 0x79, 0x7e, 0x8a, 0x6f, 0x26, 0x9b, 0xf2, 0x5d, 0x4c, 0xb4, 0xec, 0x3f, 0xa4, 0x6f, 0x8f, 0x11, 0xe6, 0xb3, 0x69, 0xfb, 0xda, 0xec, 0x1e, 0x51, 0x97, 0x83, 0x58, 0xd4, 0x6f, 0x3c, 0xf3, 0xb8, 0x42, 0x91, 0x7d, 0x96, 0x7a, 0xa9, 0xd3, 0x0b, 0x18, 0x34, 0x53, 0x93, 0x7a, 0x68, 0x26, 0x56, 0xb2, 0x7b } +, + /* Seed */ + 74, + { 0x17, 0x77, 0x42, 0x19, 0x7f, 0x04, 0x11, 0x44, 0x3b, 0xd8, 0x7e, 0x28, 0xea, 0x88, 0xd5, 0x4b, 0x4f, 0x2c, 0x7a, 0xb1, 0xdc, 0xae, 0xd8, 0x1a, 0x56, 0xf8, 0xd7, 0x87, 0x91, 0x12, 0x44, 0x54, 0x02, 0x85, 0x04, 0xd3, 0x22, 0xe1, 0xde, 0x34, 0x60, 0x47, 0xa4, 0x93, 0x93, 0x3e, 0x87, 0x62, 0x8c, 0xe0, 0x8b, 0x06, 0xc0, 0x17, 0x08, 0x2d, 0xcc, 0xd3, 0x8b, 0x48, 0x94, 0x65, 0x14, 0xea, 0x37, 0x7c, 0x2d, 0xfc, 0x75, 0x2a, 0xdc, 0x24, 0xfb, 0x57 } +, + /* Encryption */ + 128, + { 0x79, 0x84, 0xc3, 0xba, 0xd8, 0x6a, 0x54, 0x79, 0x90, 0xe0, 0x47, 0x5a, 0x48, 0x4f, 0x8d, 0xba, 0x5d, 0x4d, 0xce, 0xb0, 0xd3, 0xe3, 0xfc, 0xe0, 0x71, 0xd6, 0xf8, 0x71, 0x76, 0xb7, 0xcb, 0xe6, 0xf8, 0x11, 0x2d, 0x81, 0xd7, 0xcd, 0xaa, 0xd7, 0x7e, 0xd0, 0xd5, 0x78, 0x8e, 0x65, 0xf8, 0xbf, 0x5f, 0x0c, 0x2a, 0xd0, 0xdf, 0x07, 0xcc, 0xdf, 0x54, 0xb2, 0xda, 0xce, 0xfc, 0x19, 0xba, 0x65, 0x20, 0x1c, 0xcf, 0xd3, 0x61, 0xd1, 0x86, 0xb7, 0xd9, 0xe2, 0x69, 0xaa, 0x1e, 0x6a, 0xd2, 0xc7, 0x2b, 0xd2, 0x3f, 0x58, 0x08, 0x4f, 0xdb, 0xc3, 0xbc, 0x60, 0xe1, 0x7a, 0x33, 0xe3, 0xc5, 0x5a, 0x95, 0xeb, 0x0c, 0x38, 0xa0, 0x81, 0xbc, 0x0d, 0x39, 0x81, 0xdb, 0x26, 0xa7, 0x21, 0x2d, 0x6f, 0x69, 0x1b, 0x33, 0x6d, 0xac, 0x46, 0xb6, 0x4a, 0xe2, 0x25, 0x38, 0xa7, 0xb0, 0x08, 0x7f, 0x25 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.14", + /* Message */ + 20, + { 0xa5, 0xe9, 0xde, 0xb1, 0xc2, 0x0f, 0x98, 0x2d, 0x5b, 0x7d, 0x4b, 0x87, 0xd7, 0x99, 0x46, 0x1f, 0x05, 0x3d, 0x91, 0x9e } +, + /* Seed */ + 105, + { 0x59, 0x75, 0x9c, 0xf5, 0xf8, 0x38, 0xd9, 0x52, 0x49, 0x3d, 0x0f, 0x42, 0x81, 0xe3, 0xea, 0x0f, 0xe2, 0x16, 0x97, 0x1c, 0x0a, 0x2e, 0x24, 0x54, 0xb9, 0x6c, 0x8a, 0x11, 0xb4, 0xc6, 0x91, 0x27, 0x15, 0x90, 0x24, 0xdb, 0x6e, 0xc5, 0xc3, 0x36, 0x40, 0xd1, 0x20, 0x29, 0x58, 0x99, 0xf6, 0x66, 0x6c, 0x94, 0x17, 0xb2, 0x02, 0xa8, 0x6c, 0x26, 0xef, 0xd7, 0xc6, 0x13, 0x4c, 0x92, 0xfd, 0x86, 0xb8, 0x32, 0x3d, 0x17, 0x4a, 0x62, 0x53, 0x48, 0x81, 0x38, 0x2d, 0x7c, 0x6c, 0x9e, 0x1b, 0x8c, 0x1e, 0x95, 0xda, 0xf2, 0x10, 0xc3, 0xe9, 0xba, 0x43, 0xe5, 0x88, 0x79, 0xf3, 0x4f, 0x2f, 0xa7, 0x1e, 0xf6, 0xae, 0x4b, 0x68, 0xd6, 0x41, 0x47, 0xbe } +, + /* Encryption */ + 128, + { 0x70, 0xac, 0x10, 0x2d, 0x07, 0x1e, 0x3d, 0x90, 0x22, 0x81, 0x83, 0x62, 0x16, 0xe0, 0x81, 0x29, 0x0b, 0xb5, 0xdf, 0xcd, 0x56, 0x68, 0xd1, 0x1d, 0xae, 0xfa, 0x0a, 0xb0, 0x64, 0x59, 0x9d, 0x0f, 0x91, 0x4b, 0x47, 0x29, 0x61, 0x37, 0x5b, 0xbf, 0x5f, 0x2a, 0x66, 0x6f, 0xae, 0x0f, 0x6a, 0x25, 0xba, 0xfd, 0x44, 0xf6, 0x65, 0xc1, 0x7c, 0x14, 0x4d, 0xc4, 0xd4, 0xcc, 0x0a, 0x5d, 0x5b, 0xa5, 0x5c, 0x47, 0xa4, 0xcd, 0xe9, 0x59, 0xb3, 0x2b, 0xaa, 0x52, 0x32, 0xa0, 0x7f, 0xbf, 0x93, 0x78, 0xc9, 0xc5, 0x3c, 0xa2, 0xb3, 0x77, 0x81, 0xc9, 0x3a, 0x1c, 0xc8, 0xd6, 0x52, 0x94, 0x78, 0xa1, 0xc6, 0x73, 0x03, 0x4d, 0xda, 0x7f, 0xf3, 0x35, 0x60, 0x78, 0x6a, 0x46, 0x4f, 0x5b, 0x4a, 0x55, 0x9c, 0x62, 0x6a, 0xe2, 0x95, 0xbc, 0x91, 0xd0, 0xee, 0xd9, 0x37, 0x5f, 0x49, 0xe3, 0xe4, 0xaa } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.15", + /* Message */ + 63, + { 0x73, 0x9f, 0xa7, 0x6d, 0xbd, 0x12, 0x73, 0x03, 0xb7, 0xab, 0xf9, 0x3e, 0x1d, 0x7b, 0xa7, 0x29, 0x75, 0x5d, 0x6c, 0x81, 0x1b, 0x5e, 0x93, 0x35, 0x5e, 0x0c, 0x01, 0x1f, 0x74, 0x46, 0x4c, 0x7d, 0xb4, 0x79, 0x19, 0x3c, 0x3f, 0xb7, 0x38, 0x0a, 0x62, 0xa0, 0xc0, 0x06, 0xa2, 0xd1, 0xdc, 0x49, 0xa7, 0x66, 0xaf, 0x63, 0xfb, 0xa4, 0x52, 0x7c, 0xd1, 0x57, 0x50, 0x6d, 0x62, 0xc2, 0x1a } +, + /* Seed */ + 62, + { 0xa0, 0xb4, 0xda, 0xff, 0x3e, 0x26, 0xce, 0xbb, 0x3e, 0x4e, 0x3a, 0x43, 0xdb, 0x36, 0xc4, 0x66, 0xfb, 0x8c, 0xe6, 0x05, 0xb2, 0x5a, 0xf4, 0xc9, 0xda, 0x74, 0x4b, 0x62, 0xd4, 0x1f, 0x9e, 0x62, 0xc2, 0x28, 0x5c, 0x39, 0x0d, 0x60, 0xd1, 0x8e, 0x3d, 0x7e, 0x67, 0x5b, 0x4a, 0xc3, 0x19, 0x67, 0x24, 0x45, 0x19, 0x46, 0xbc, 0x1c, 0xcf, 0x2a, 0x9b, 0x56, 0x2c, 0x45, 0x33, 0xc9 } +, + /* Encryption */ + 128, + { 0x2b, 0x79, 0x80, 0x91, 0xb3, 0xa3, 0x91, 0x53, 0x3d, 0x62, 0xdc, 0x0e, 0x41, 0x7b, 0xa6, 0xde, 0xda, 0x00, 0x5b, 0xfc, 0x30, 0xab, 0x7d, 0xc8, 0x2e, 0x8f, 0x9b, 0xcc, 0x74, 0x17, 0xbc, 0xb0, 0x04, 0x34, 0x8c, 0x6d, 0x00, 0xe5, 0x37, 0xd2, 0x72, 0x2b, 0x84, 0x38, 0x61, 0x48, 0x92, 0x45, 0xab, 0x0d, 0x51, 0xf2, 0x11, 0x44, 0x7d, 0xac, 0x33, 0xa3, 0xf9, 0xdd, 0x6f, 0x3c, 0xa6, 0x6b, 0xbf, 0xa0, 0xd1, 0xad, 0xf9, 0x8b, 0xc9, 0x09, 0x95, 0x15, 0x92, 0x69, 0x76, 0xb9, 0x25, 0x8a, 0xab, 0x63, 0x20, 0x4a, 0xd8, 0x91, 0x65, 0xc8, 0x7b, 0xbe, 0xfd, 0x8d, 0x98, 0x85, 0x34, 0xb3, 0x74, 0x07, 0xdf, 0x7d, 0x43, 0xad, 0x39, 0x1e, 0xed, 0x99, 0x82, 0x47, 0x28, 0xef, 0xc3, 0xa5, 0x33, 0xb7, 0x89, 0xb4, 0x7e, 0x8a, 0xa7, 0x12, 0x16, 0x17, 0x47, 0x4f, 0x33, 0x25, 0xc5, 0x1a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.16", + /* Message */ + 21, + { 0x5a, 0x44, 0xb5, 0x47, 0xbd, 0xa1, 0x9e, 0xcc, 0xa1, 0xdc, 0x7b, 0xc0, 0x45, 0x50, 0x20, 0x5f, 0x66, 0xc5, 0xde, 0x0a, 0xcb } +, + /* Seed */ + 104, + { 0x2f, 0x54, 0x85, 0xd2, 0x5f, 0xe5, 0xce, 0x40, 0xae, 0x62, 0xa1, 0x12, 0x97, 0x6c, 0xb4, 0xa5, 0x39, 0xb7, 0x4d, 0x96, 0xef, 0x8b, 0xe8, 0x73, 0x32, 0x5e, 0x20, 0x4b, 0xb3, 0xf8, 0x66, 0x07, 0xa1, 0x6a, 0x2c, 0x2a, 0xb5, 0x0f, 0x69, 0x78, 0x09, 0xed, 0x03, 0x01, 0x72, 0x70, 0xef, 0x20, 0xa1, 0x02, 0xc4, 0x3a, 0x2c, 0x4c, 0x3b, 0xe6, 0xab, 0x7a, 0x8a, 0xe2, 0xdc, 0xb5, 0x69, 0x84, 0xd5, 0xe0, 0x65, 0x52, 0x45, 0x93, 0xeb, 0x70, 0x70, 0x83, 0x4c, 0xe5, 0x53, 0xf1, 0x75, 0x69, 0x20, 0xbb, 0xcb, 0xbe, 0x4f, 0xb2, 0x6d, 0x35, 0xd4, 0xad, 0xcb, 0x59, 0xdf, 0x52, 0x46, 0x35, 0x6f, 0xf1, 0x2e, 0x7a, 0xa9, 0xee, 0x6d, 0xef } +, + /* Encryption */ + 128, + { 0x62, 0xd1, 0x48, 0x9a, 0x40, 0x3a, 0x90, 0xfa, 0xac, 0x67, 0x7a, 0xbc, 0x17, 0x4a, 0xa7, 0x24, 0x3b, 0xc7, 0x51, 0xa9, 0x64, 0x69, 0x5f, 0x6c, 0x32, 0xb3, 0x9d, 0xe0, 0x18, 0xfe, 0x46, 0x43, 0x44, 0x20, 0xea, 0x76, 0x59, 0xbe, 0x2c, 0x41, 0x0b, 0xc5, 0x6c, 0x4e, 0x3e, 0x7a, 0x1b, 0x16, 0x77, 0xfd, 0xf4, 0xad, 0xfb, 0x23, 0x24, 0xf0, 0x41, 0xed, 0xd5, 0x79, 0x0c, 0x4c, 0xdf, 0xab, 0x36, 0x55, 0xe0, 0x7e, 0x41, 0xfe, 0x9d, 0x73, 0x29, 0x21, 0x51, 0xb0, 0xdd, 0x5b, 0x96, 0xfc, 0x84, 0xa6, 0xb2, 0x0f, 0x6f, 0x3b, 0xc0, 0xf6, 0x0e, 0xae, 0xa8, 0xd8, 0x29, 0x17, 0xb2, 0x10, 0x83, 0x05, 0x59, 0x40, 0xfc, 0x02, 0xee, 0x3e, 0x17, 0xc3, 0x78, 0xbd, 0x4d, 0x85, 0x06, 0xd0, 0x8e, 0xc4, 0x5f, 0x33, 0xde, 0x57, 0x80, 0xf0, 0x1b, 0xd3, 0x18, 0xa9, 0xa1, 0x67, 0x87, 0xad } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.17", + /* Message */ + 5, + { 0x16, 0x80, 0x2d, 0x80, 0x3c } +, + /* Seed */ + 120, + { 0x02, 0xf0, 0xe7, 0x62, 0xc3, 0x39, 0x17, 0xbf, 0x6a, 0x4d, 0xf1, 0x1f, 0xa2, 0x84, 0x73, 0x54, 0x7a, 0x5a, 0xb0, 0x76, 0x7d, 0xd3, 0xa6, 0x1a, 0x8d, 0x05, 0xcc, 0x1e, 0x6f, 0x98, 0x34, 0x5a, 0xf1, 0xa0, 0x0e, 0x42, 0xf6, 0x2b, 0xd8, 0xec, 0xca, 0xcb, 0xd3, 0x7f, 0x4c, 0xcb, 0x80, 0x9e, 0x9e, 0x05, 0x5f, 0x73, 0xd3, 0x37, 0x5a, 0x60, 0x41, 0xd9, 0x78, 0x2c, 0xcd, 0x85, 0xd5, 0x9d, 0x14, 0xf4, 0x3e, 0x5c, 0x94, 0x10, 0x25, 0x7b, 0x90, 0x6e, 0x41, 0xcc, 0x8b, 0x97, 0x35, 0x47, 0xd0, 0x62, 0x2b, 0xd2, 0x1d, 0xb2, 0x9a, 0x91, 0x38, 0xd3, 0xb1, 0xbe, 0xde, 0x38, 0xce, 0x5c, 0x94, 0xc4, 0xe1, 0xd2, 0xa0, 0xa8, 0x40, 0x0b, 0x45, 0xba, 0xcd, 0x42, 0x69, 0x79, 0x7c, 0x38, 0x5a, 0xa3, 0x06, 0x6e, 0x65, 0x80, 0x72, 0x99 } +, + /* Encryption */ + 128, + { 0x75, 0x3b, 0x9c, 0xee, 0x70, 0xd4, 0x18, 0x1f, 0x95, 0x63, 0x87, 0x80, 0xdb, 0x7a, 0x04, 0xf9, 0xb1, 0x2e, 0xa3, 0x8e, 0x5d, 0xae, 0xe4, 0xf2, 0x89, 0x4c, 0x02, 0x67, 0x3a, 0x53, 0xf4, 0x85, 0x30, 0x74, 0x6f, 0xf2, 0x85, 0x8b, 0x78, 0x7e, 0xfc, 0xb4, 0x2d, 0x45, 0xe5, 0x31, 0xbe, 0xa1, 0xc8, 0xda, 0xe9, 0x48, 0x77, 0x15, 0x3b, 0x95, 0x6a, 0xc7, 0xb2, 0x87, 0x46, 0xee, 0x21, 0xc6, 0x31, 0xbf, 0x9a, 0x3b, 0xa7, 0x9d, 0x2b, 0xa8, 0x13, 0x21, 0xb7, 0x96, 0x03, 0xb1, 0xd0, 0x1a, 0x4e, 0x90, 0x9e, 0xd5, 0xa2, 0x7c, 0xbf, 0x27, 0xc9, 0x57, 0x78, 0x3d, 0x3f, 0x79, 0x50, 0xe0, 0x1d, 0xd8, 0xf4, 0x47, 0xf1, 0x0e, 0xce, 0xd3, 0x6f, 0x2d, 0x19, 0x35, 0x86, 0xf5, 0xcc, 0x17, 0xfb, 0x62, 0x2a, 0x05, 0xfa, 0xa1, 0xfb, 0x5c, 0xd2, 0xaa, 0x06, 0x4c, 0x08, 0x67, 0xb1, 0xca } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.18", + /* Message */ + 48, + { 0xd6, 0xd0, 0xf6, 0x03, 0x85, 0x97, 0x9c, 0xa5, 0x06, 0xfc, 0x83, 0x34, 0x21, 0xbc, 0xd2, 0x2d, 0xa6, 0xa0, 0x6a, 0x8f, 0x37, 0x0a, 0x7f, 0x02, 0xfe, 0xf4, 0x7c, 0x1c, 0xb2, 0x19, 0x9f, 0x26, 0x45, 0xc7, 0x54, 0x90, 0xfb, 0xf7, 0x89, 0xad, 0x52, 0x47, 0x04, 0xda, 0x8a, 0x27, 0x66, 0xc6 } +, + /* Seed */ + 77, + { 0xa0, 0x3c, 0x05, 0x67, 0x2e, 0xfe, 0x23, 0xb4, 0x4b, 0x26, 0xc7, 0x93, 0xe7, 0x05, 0x3a, 0x77, 0x04, 0x8b, 0xa2, 0xdb, 0xb4, 0xb5, 0x3a, 0xe9, 0x75, 0x18, 0x54, 0xe7, 0xad, 0xd7, 0xd6, 0x7c, 0x12, 0xcb, 0xd1, 0x6c, 0x0b, 0x19, 0x34, 0xd2, 0xc2, 0x3e, 0x77, 0xcd, 0xcc, 0x89, 0xce, 0x1d, 0x45, 0xc7, 0x61, 0x15, 0x8a, 0xa8, 0x61, 0x31, 0x71, 0xa7, 0x39, 0x01, 0xac, 0x1f, 0x61, 0xc6, 0x57, 0x05, 0x53, 0x3d, 0x3e, 0x63, 0x9b, 0x57, 0xa2, 0x48, 0x92, 0x91, 0x79 } +, + /* Encryption */ + 128, + { 0x00, 0x78, 0xdc, 0x48, 0xa6, 0x61, 0x58, 0x99, 0x2a, 0xaa, 0x68, 0xfc, 0x3c, 0xcc, 0x62, 0x8f, 0x92, 0xa7, 0x08, 0xd0, 0xb1, 0xd4, 0x38, 0x37, 0x20, 0x8d, 0x53, 0x4b, 0xc3, 0xf9, 0xbe, 0x1c, 0x14, 0x12, 0xed, 0x0f, 0x9f, 0x7b, 0xef, 0x49, 0x43, 0x0d, 0xc9, 0xe9, 0x98, 0xf7, 0x52, 0xe0, 0x74, 0x77, 0x68, 0xb4, 0xae, 0x38, 0x14, 0x46, 0x96, 0xc0, 0x03, 0xd6, 0xd2, 0x5e, 0xa1, 0xa6, 0xca, 0x6a, 0xec, 0x92, 0x4a, 0x9f, 0x4d, 0x9b, 0x57, 0x5a, 0x8f, 0x13, 0x6b, 0xba, 0x29, 0xbf, 0x31, 0xc1, 0x3b, 0x70, 0x50, 0xbd, 0x55, 0xd1, 0x00, 0x0d, 0x43, 0x3d, 0xaa, 0x6c, 0xf1, 0x0b, 0x49, 0x11, 0x6c, 0x80, 0x63, 0x10, 0x7f, 0xd3, 0xa5, 0xbd, 0xf6, 0x15, 0x45, 0xc5, 0xd8, 0x63, 0xf6, 0xa7, 0x88, 0x81, 0x78, 0x6c, 0xc8, 0xdc, 0x37, 0x6d, 0x36, 0xc9, 0x11, 0x36, 0x82, 0x25 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.19", + /* Message */ + 34, + { 0xb0, 0x38, 0x1c, 0xac, 0x04, 0xf3, 0x10, 0x15, 0x04, 0x96, 0x8f, 0x26, 0xd6, 0x55, 0x47, 0x45, 0x38, 0x3b, 0xd1, 0x71, 0xd3, 0x61, 0x56, 0xdd, 0x36, 0x80, 0xb3, 0xdb, 0x6f, 0xad, 0x7f, 0x77, 0x1f, 0x7d } +, + /* Seed */ + 91, + { 0xcc, 0x54, 0x8a, 0x67, 0x77, 0xcd, 0xe9, 0x53, 0xc1, 0x5a, 0x71, 0xfc, 0x49, 0x7c, 0x0c, 0x36, 0x17, 0xb1, 0xbb, 0x05, 0x6b, 0x03, 0x28, 0x8d, 0x9a, 0x54, 0x8b, 0x69, 0x3b, 0xb4, 0x30, 0x8b, 0x67, 0xc1, 0xda, 0xc3, 0x8b, 0xb9, 0xb8, 0xc9, 0xcc, 0x89, 0x6a, 0xc2, 0x44, 0xa9, 0xe3, 0x0d, 0x13, 0x24, 0x30, 0xf4, 0xce, 0xae, 0x57, 0x90, 0x34, 0x3d, 0xbc, 0xe3, 0x8d, 0x05, 0x6f, 0x27, 0xb8, 0x6b, 0xdd, 0x9d, 0x32, 0xa8, 0x17, 0x1f, 0x3b, 0x3c, 0xc2, 0xfd, 0x14, 0x22, 0x65, 0xac, 0x9a, 0x68, 0xdc, 0x35, 0x36, 0x27, 0x33, 0x9c, 0xd8, 0x83, 0x03 } +, + /* Encryption */ + 128, + { 0x45, 0x6f, 0x7c, 0x3e, 0x3b, 0xe8, 0x5f, 0xf7, 0xbd, 0xd6, 0xb5, 0xb2, 0x50, 0xbf, 0xb8, 0x1c, 0xd6, 0xfb, 0xb1, 0x86, 0xd2, 0x5e, 0x0c, 0x1c, 0x52, 0x59, 0xd6, 0x78, 0x87, 0x93, 0xc5, 0x41, 0xed, 0xac, 0xb4, 0xec, 0xde, 0xdb, 0x8a, 0x89, 0x29, 0x01, 0x34, 0xa6, 0x06, 0xf4, 0x6a, 0x81, 0x99, 0x1c, 0x13, 0xb1, 0x20, 0xe3, 0x30, 0x56, 0xbc, 0x0f, 0xc7, 0xe9, 0x7b, 0x34, 0x2d, 0x0f, 0x20, 0x05, 0x18, 0x13, 0xdd, 0xe4, 0x5e, 0x0b, 0x59, 0x6a, 0x7d, 0xcd, 0x69, 0x04, 0x90, 0x3b, 0x8f, 0xc0, 0x76, 0xa6, 0xe2, 0x4b, 0x3a, 0xd8, 0x01, 0x34, 0x16, 0xd9, 0xfd, 0x18, 0x48, 0x30, 0x55, 0x4a, 0xd5, 0x4d, 0x55, 0x48, 0xbc, 0xad, 0xda, 0xf5, 0x92, 0x0a, 0x02, 0x49, 0x55, 0x88, 0x78, 0x25, 0xdd, 0x37, 0x1a, 0xe4, 0xef, 0x90, 0x06, 0x9a, 0x4f, 0x31, 0x1c, 0x5a, 0x17, 0x29 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 5.20", + /* Message */ + 1, + { 0xe5 } +, + /* Seed */ + 124, + { 0xfe, 0x0b, 0xc7, 0xac, 0xb5, 0x6c, 0xe1, 0x4b, 0x4e, 0x2f, 0x55, 0xfb, 0xa0, 0xe2, 0xb1, 0x71, 0x54, 0x90, 0x7b, 0xe9, 0x4c, 0xe4, 0x85, 0xc6, 0x98, 0x4d, 0x61, 0xf6, 0x7c, 0x04, 0xa7, 0x40, 0xa2, 0x8d, 0x60, 0x94, 0xae, 0xae, 0x33, 0xb3, 0xea, 0x0d, 0x58, 0x18, 0x3e, 0x1e, 0xc7, 0xf6, 0x01, 0xb2, 0xab, 0x82, 0x0f, 0xb8, 0xa7, 0xff, 0xac, 0x0b, 0x4f, 0x96, 0x0e, 0x1b, 0x4a, 0xcb, 0xe5, 0x7c, 0xdc, 0x35, 0xb2, 0x25, 0xc4, 0x97, 0xfc, 0xac, 0xa0, 0x30, 0x19, 0xa2, 0x95, 0xb3, 0xe6, 0x6d, 0xa9, 0x6f, 0x53, 0x79, 0xcc, 0xd1, 0xda, 0x44, 0x47, 0x9a, 0x4f, 0x21, 0x35, 0xe1, 0x06, 0x3d, 0x71, 0xa2, 0x82, 0xc1, 0xe6, 0x6f, 0xdb, 0xd5, 0xd9, 0x53, 0xf5, 0x71, 0x8c, 0x25, 0x39, 0xd0, 0x0c, 0xe4, 0x9b, 0x45, 0x18, 0x20, 0x45, 0x4d, 0x2d, 0x49 } +, + /* Encryption */ + 128, + { 0x5c, 0x53, 0x36, 0x77, 0xa1, 0xdc, 0xb3, 0x63, 0x95, 0xda, 0x9a, 0x6d, 0x34, 0x77, 0xbf, 0xbf, 0x71, 0x51, 0x2c, 0x6a, 0x93, 0x3d, 0x04, 0x1c, 0xa3, 0x13, 0x44, 0xe1, 0xcb, 0xe1, 0xe5, 0x55, 0x88, 0xa1, 0x14, 0x6e, 0x3d, 0xec, 0x46, 0x10, 0xef, 0xac, 0x41, 0xb5, 0xf8, 0x02, 0x66, 0x02, 0x66, 0x52, 0xb3, 0xd7, 0xaa, 0x59, 0x42, 0x74, 0xd9, 0xd9, 0x20, 0xd3, 0x3a, 0xa0, 0xad, 0x9b, 0x4e, 0xc5, 0x9a, 0xa8, 0x80, 0x71, 0x2a, 0x1d, 0x1c, 0x36, 0x8a, 0x45, 0x7f, 0x35, 0xc7, 0x43, 0x88, 0xb0, 0x42, 0xf2, 0x49, 0x8e, 0x9f, 0x4b, 0xd4, 0x5a, 0x26, 0xf3, 0x21, 0xdd, 0x9e, 0xb3, 0x33, 0xef, 0x80, 0xaf, 0xe3, 0xaf, 0x9f, 0x72, 0x9c, 0xa1, 0x8f, 0x42, 0xc8, 0x8a, 0x71, 0x73, 0x85, 0x8c, 0x54, 0x20, 0x66, 0xf8, 0xa2, 0x52, 0xcc, 0xf0, 0xfe, 0xaf, 0xe6, 0xb5, 0xa9, 0x24 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 6: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xdd, 0xca, 0xd6, 0xa3, 0x8b, 0x37, 0x04, 0xcb, 0xe0, 0x6b, 0xb1, 0xb5, 0x1d, 0x11, 0x62, 0x58, 0x49, 0x78, 0xa4, 0x29, 0x1f, 0xb6, 0x73, 0xb4, 0xea, 0x30, 0xed, 0x8b, 0x51, 0xa4, 0xbf, 0x26, 0x1d, 0xc9, 0xf0, 0xf4, 0x69, 0xce, 0x99, 0x88, 0xa0, 0x89, 0xf0, 0x84, 0x36, 0x64, 0x64, 0xa1, 0x80, 0xcf, 0xd7, 0x17, 0x10, 0x69, 0xa6, 0xf6, 0x36, 0xd7, 0x5f, 0x23, 0x40, 0x1b, 0x30, 0xcf, 0x43, 0xad, 0xcf, 0x87, 0x0e, 0xcd, 0x24, 0x58, 0x2f, 0x4d, 0xa2, 0x95, 0x22, 0x91, 0x51, 0xdd, 0xcf, 0xc7, 0xc9, 0x91, 0x86, 0xb2, 0x45, 0x88, 0x5c, 0xb6, 0x31, 0x96, 0xc4, 0xa5, 0x72, 0x6f, 0x20, 0x7e, 0xe3, 0x60, 0xaf, 0x3a, 0xd8, 0xc4, 0x83, 0x85, 0xa4, 0xe0, 0x84, 0x1d, 0x7d, 0x85, 0x1d, 0x54, 0x54, 0x5d, 0xe7, 0x67, 0xd8, 0xf9, 0x99, 0xdc, 0x17, 0xeb, 0x0c, 0x57, 0x11, 0x89 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x5e, 0x48, 0xe0, 0x3d, 0xdd, 0xec, 0xa1, 0xa9, 0x59, 0xd9, 0xee, 0x4d, 0xa3, 0xf1, 0xc3, 0xf0, 0xec, 0x2a, 0xd0, 0xfe, 0x7a, 0x70, 0xc1, 0x77, 0x63, 0x27, 0x31, 0x94, 0x4c, 0x3c, 0xd0, 0xd5, 0x8f, 0x4c, 0x4d, 0x96, 0x59, 0x74, 0x6e, 0x68, 0x5a, 0x76, 0xc9, 0x3c, 0x2b, 0x33, 0x3a, 0x64, 0x3d, 0xb2, 0x1d, 0x29, 0xbc, 0xdc, 0x6d, 0x11, 0xb5, 0xf6, 0x90, 0x87, 0x17, 0xb5, 0x77, 0x65, 0x99, 0xff, 0x30, 0x88, 0xb2, 0x01, 0x4f, 0xfc, 0x51, 0xf1, 0x8d, 0x93, 0x22, 0x24, 0xf1, 0x05, 0x9b, 0x22, 0x39, 0xea, 0x56, 0x44, 0xe8, 0x06, 0x9a, 0x5c, 0xc4, 0x31, 0xae, 0xf6, 0x07, 0x38, 0x0a, 0xa9, 0x24, 0xc1, 0x58, 0xab, 0xcb, 0xdd, 0x97, 0x51, 0xf5, 0x4e, 0x67, 0x79, 0xc4, 0xec, 0x23, 0x21, 0x68, 0xb0, 0x01, 0x4f, 0x4c, 0x8b, 0x49, 0x7b, 0xe9, 0x49, 0xae, 0xe6, 0x57, 0x51 } +, + /* Prime 1 */ + 64, + { 0xf9, 0x47, 0x1f, 0x2d, 0x22, 0x13, 0xa9, 0x2c, 0xf0, 0xa7, 0xc3, 0x84, 0x04, 0xd4, 0x0e, 0x32, 0x2f, 0x14, 0xf4, 0x39, 0x61, 0xf0, 0x1e, 0x92, 0x33, 0x63, 0xcf, 0x66, 0x53, 0xe8, 0x98, 0x4f, 0xb6, 0xe6, 0x8d, 0x66, 0xe6, 0xf1, 0x59, 0x80, 0x3a, 0x44, 0xbc, 0xdd, 0x09, 0xe0, 0x56, 0x19, 0x6d, 0xa4, 0x00, 0x7a, 0xe2, 0xa3, 0x7f, 0x40, 0x57, 0xbf, 0x7e, 0x3b, 0x5e, 0x4a, 0x80, 0x23 } +, + /* Prime 2 */ + 64, + { 0xe3, 0xc5, 0xf8, 0xcb, 0xfd, 0x51, 0xc6, 0xc2, 0x66, 0xb1, 0xa3, 0x2f, 0xb2, 0xf6, 0xfa, 0x48, 0x9b, 0x97, 0x54, 0xb2, 0x27, 0xc7, 0x7f, 0x53, 0x59, 0xc5, 0x5d, 0xfa, 0x03, 0x80, 0xfe, 0x9a, 0x02, 0xb4, 0xd3, 0x95, 0x05, 0xf3, 0xab, 0x36, 0x95, 0x7c, 0xeb, 0xfa, 0xd5, 0x34, 0xd7, 0xf9, 0xa2, 0x67, 0xeb, 0xee, 0x19, 0xaf, 0xe5, 0xc6, 0x24, 0x04, 0x3e, 0x30, 0x19, 0xd0, 0xac, 0x63 } +, + /* Prime exponent 1 */ + 64, + { 0x2c, 0xf4, 0x79, 0x97, 0xdf, 0x1c, 0x62, 0x97, 0x1b, 0x33, 0x76, 0x1c, 0x19, 0xee, 0xd0, 0x3c, 0x96, 0xa7, 0x15, 0xc0, 0x3f, 0x7c, 0x59, 0x57, 0x0e, 0x73, 0x82, 0x94, 0xb6, 0xaf, 0x2c, 0xc0, 0xbb, 0x80, 0x6a, 0xa1, 0xd3, 0x26, 0x55, 0x78, 0xbd, 0x89, 0x65, 0xf2, 0x0a, 0xf4, 0xed, 0x32, 0x1a, 0xc6, 0xc7, 0xdb, 0x61, 0x82, 0x10, 0xd1, 0xde, 0xc1, 0x47, 0x17, 0x97, 0xd2, 0xa1, 0xb7 } +, + /* Prime exponent 2 */ + 64, + { 0xa6, 0xc0, 0x29, 0xbb, 0xd5, 0x91, 0xc7, 0xcc, 0x4c, 0x78, 0x61, 0xfa, 0xaa, 0xaf, 0x8b, 0x5e, 0x1a, 0xa2, 0x78, 0x7c, 0x11, 0x09, 0x49, 0x5a, 0xd1, 0x0e, 0xe0, 0x15, 0x07, 0xf9, 0xa8, 0xeb, 0x41, 0x6d, 0xf6, 0xb4, 0x53, 0xee, 0x26, 0xfb, 0x48, 0x07, 0x73, 0x8f, 0x68, 0x05, 0x4e, 0xd4, 0x50, 0x24, 0x7a, 0xa2, 0x0e, 0xa6, 0x2a, 0xb6, 0x9b, 0x69, 0x8b, 0xc9, 0x95, 0x2c, 0xa2, 0xf7 } +, + /* Coefficient */ + 64, + { 0xaa, 0xd0, 0x60, 0xde, 0x5e, 0xdb, 0x35, 0x81, 0x8b, 0xd6, 0x3e, 0x85, 0xd4, 0x2e, 0xee, 0x55, 0xe4, 0xcf, 0x8f, 0xa4, 0x2d, 0x4e, 0xa5, 0x92, 0x83, 0xce, 0xf9, 0x6a, 0xca, 0xad, 0x55, 0x5d, 0x47, 0x8d, 0x2f, 0xd7, 0xc3, 0x8f, 0xa9, 0x31, 0xfa, 0x1a, 0xeb, 0x6d, 0xe5, 0x66, 0x55, 0x3d, 0x08, 0xf1, 0xcb, 0xc0, 0x6a, 0x51, 0x0f, 0xc2, 0xe5, 0x69, 0xb5, 0xa8, 0x22, 0x67, 0xac, 0x91 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 6.1", + /* Message */ + 19, + { 0xa3, 0xe1, 0x52, 0x75, 0xfb, 0x33, 0xae, 0xc3, 0x7b, 0xd3, 0xdd, 0x58, 0x2e, 0x19, 0xf5, 0xd3, 0x8b, 0x9d, 0x0d } +, + /* Seed */ + 106, + { 0x78, 0xda, 0xa6, 0x1c, 0x07, 0xf9, 0x41, 0xb4, 0xb4, 0x40, 0xe7, 0x38, 0x33, 0x8d, 0x06, 0xcc, 0x15, 0x7a, 0x01, 0x57, 0x4a, 0x72, 0xfa, 0x78, 0xd3, 0x63, 0xdc, 0xe9, 0x94, 0x09, 0x04, 0x22, 0x0a, 0x71, 0x32, 0x35, 0x69, 0x96, 0xf0, 0x7c, 0x01, 0xd5, 0x4e, 0xe5, 0x4f, 0xa3, 0x2c, 0x5f, 0xaa, 0x1b, 0x90, 0xd2, 0x43, 0x0c, 0x80, 0xa2, 0x32, 0x17, 0xe0, 0x6b, 0xb1, 0xc8, 0x04, 0x3d, 0x61, 0xff, 0xa1, 0x8a, 0xa1, 0xd1, 0x8e, 0x15, 0xe4, 0x30, 0xaa, 0x12, 0x1c, 0xdf, 0xf4, 0x3f, 0xab, 0x2b, 0xb0, 0xde, 0xbf, 0x73, 0xe3, 0xd5, 0xa7, 0x5b, 0x46, 0xf9, 0x0d, 0xf7, 0x3d, 0x65, 0x6b, 0xb0, 0x66, 0xac, 0x1c, 0x76, 0x8f, 0xa3, 0x83, 0xe4 } +, + /* Encryption */ + 128, + { 0x9b, 0xf1, 0xdc, 0xfc, 0x65, 0x4c, 0xa7, 0xa2, 0x3d, 0x80, 0xa1, 0x2c, 0x09, 0xc2, 0x59, 0xd0, 0x4b, 0xae, 0x07, 0xe8, 0x31, 0xf6, 0x09, 0xe9, 0xf0, 0x35, 0xd3, 0x56, 0x41, 0x4e, 0xd1, 0x06, 0xf9, 0xb4, 0x62, 0x35, 0xfa, 0x3d, 0xa9, 0x1a, 0x32, 0xb8, 0xfd, 0xc8, 0xfb, 0x88, 0x30, 0xc9, 0x65, 0x23, 0xdc, 0xaa, 0x9b, 0x25, 0x38, 0xfc, 0x01, 0x02, 0xdc, 0x0f, 0x7a, 0x5f, 0xae, 0x86, 0x35, 0xb3, 0xb1, 0x23, 0x14, 0xc3, 0x90, 0x55, 0xfa, 0xac, 0xfb, 0xe0, 0x0a, 0x15, 0x16, 0x34, 0x24, 0x14, 0x8c, 0xc9, 0xe0, 0xf0, 0xab, 0x42, 0xdf, 0x09, 0x02, 0x3c, 0x05, 0x2a, 0x46, 0xae, 0x3f, 0x86, 0xa1, 0x8d, 0xcc, 0x53, 0x80, 0xce, 0x39, 0x06, 0x2e, 0x36, 0x23, 0x75, 0xd3, 0xa5, 0xf9, 0xe3, 0xb3, 0x4a, 0x5d, 0xa2, 0x5c, 0xf0, 0xde, 0x9c, 0xc1, 0x9c, 0x4d, 0x04, 0xf6, 0x3f } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 6.2", + /* Message */ + 50, + { 0x44, 0x3a, 0xb0, 0x3c, 0x46, 0x04, 0xdb, 0xd8, 0xbf, 0x80, 0x06, 0xae, 0xcc, 0x2a, 0xa8, 0xde, 0x64, 0xa1, 0x55, 0xb4, 0xf9, 0x0c, 0xdb, 0x08, 0x59, 0x98, 0x6d, 0x5c, 0xa3, 0x60, 0x66, 0x03, 0x59, 0x80, 0x8c, 0x59, 0xbd, 0x9c, 0x2d, 0xe7, 0x75, 0xfc, 0x18, 0x52, 0x02, 0x24, 0xb6, 0x69, 0xc3, 0x25 } +, + /* Seed */ + 75, + { 0x3a, 0x6a, 0x60, 0x89, 0xf7, 0x27, 0xdd, 0x16, 0x92, 0x97, 0xa5, 0x79, 0xfc, 0xaf, 0x8e, 0xa7, 0xf8, 0xe1, 0x2d, 0x54, 0x27, 0xf1, 0xf7, 0x90, 0x1a, 0x90, 0x22, 0xa2, 0x1e, 0x2d, 0x82, 0xd2, 0xf0, 0x8e, 0x63, 0xba, 0xca, 0x26, 0x7b, 0x65, 0x3a, 0xaf, 0x89, 0xde, 0x23, 0x2b, 0xa3, 0xd3, 0x92, 0xd1, 0xcb, 0x49, 0xdd, 0x76, 0xb3, 0x88, 0xb2, 0xda, 0xdf, 0xb0, 0x09, 0x4f, 0xda, 0x97, 0x18, 0xf1, 0x78, 0x37, 0x38, 0xd1, 0x8f, 0xa7, 0xaa, 0xa6, 0x29 } +, + /* Encryption */ + 128, + { 0x5a, 0x0a, 0xe0, 0xde, 0x28, 0xfd, 0x33, 0xcc, 0x98, 0x01, 0xbf, 0x4d, 0xd3, 0x06, 0x71, 0x23, 0x74, 0x53, 0x63, 0xca, 0xce, 0x4d, 0xd8, 0xb7, 0xb8, 0xb8, 0x11, 0xd6, 0x48, 0x2f, 0x59, 0x12, 0x0c, 0x0d, 0x65, 0x3e, 0xee, 0x86, 0xa6, 0x1a, 0x01, 0x2a, 0x18, 0x0e, 0xc5, 0xd1, 0x7e, 0x99, 0x14, 0x6d, 0x0c, 0xca, 0x0a, 0x58, 0x7c, 0x85, 0xcf, 0x01, 0xdc, 0x7a, 0xdd, 0x84, 0x23, 0x0d, 0x91, 0x80, 0xbd, 0xdf, 0x5a, 0x77, 0x19, 0xf6, 0x9d, 0x1f, 0xc4, 0x81, 0xaf, 0x6f, 0x47, 0xdb, 0x8c, 0xbd, 0x4e, 0xe1, 0x87, 0x1a, 0x57, 0x3f, 0xc8, 0x76, 0x7c, 0xe8, 0xbe, 0xed, 0xb5, 0xc7, 0x3f, 0xa9, 0x3f, 0x0c, 0x53, 0x80, 0x4a, 0xfe, 0x2e, 0x76, 0xcc, 0xeb, 0xb8, 0x7c, 0xba, 0x00, 0xcd, 0xac, 0x94, 0xde, 0x40, 0xe2, 0xb0, 0xbe, 0xaa, 0x8e, 0x2e, 0x41, 0x58, 0xc7, 0x78, 0x50 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.3", + /* Message */ + 57, + { 0xd1, 0xba, 0x30, 0xe8, 0x8c, 0xdd, 0xa3, 0x3d, 0x2b, 0x41, 0x89, 0x6f, 0x43, 0xdf, 0x08, 0x1e, 0xef, 0x20, 0xca, 0xf7, 0x8d, 0x7c, 0x1b, 0x97, 0x0c, 0x6a, 0x61, 0x72, 0xe8, 0x38, 0x39, 0xdc, 0x43, 0xd4, 0xbe, 0x29, 0xf9, 0xa7, 0x72, 0xba, 0x41, 0x59, 0x73, 0x8b, 0xc6, 0x13, 0x29, 0x68, 0x61, 0x8d, 0xc7, 0x19, 0x7c, 0x0e, 0xdc, 0x57, 0xa1 } +, + /* Seed */ + 68, + { 0x9b, 0xb6, 0x2b, 0xf9, 0xa7, 0x51, 0xfe, 0x41, 0x81, 0x66, 0x43, 0x68, 0x98, 0xed, 0xe8, 0x35, 0xcf, 0xae, 0xe2, 0xf5, 0x0e, 0xfc, 0xad, 0x60, 0x94, 0x2f, 0x2f, 0xb2, 0xda, 0x1a, 0x20, 0x38, 0x03, 0xf0, 0xbe, 0x80, 0xbe, 0xb1, 0x7f, 0xfa, 0xd0, 0xda, 0xb2, 0x18, 0xb1, 0x28, 0x02, 0x7f, 0x34, 0x97, 0xa4, 0xf8, 0xd4, 0x1a, 0xb9, 0xa1, 0xbe, 0x26, 0x4e, 0x96, 0xb4, 0x45, 0x48, 0x76, 0x7b, 0xe8, 0xd4, 0xa7 } +, + /* Encryption */ + 128, + { 0x81, 0x19, 0x1c, 0x54, 0x75, 0x27, 0x3d, 0xe6, 0x6a, 0x41, 0xbf, 0x56, 0x04, 0xf3, 0x2b, 0x58, 0xb7, 0x59, 0xa1, 0x4e, 0x74, 0x26, 0xc7, 0x46, 0xde, 0x4b, 0x53, 0xba, 0xf7, 0x80, 0xbb, 0xa4, 0x2b, 0x42, 0xe9, 0x27, 0x8a, 0xa9, 0x45, 0x27, 0xf0, 0xee, 0xbf, 0x85, 0x5f, 0x46, 0x2d, 0x6f, 0xbb, 0x29, 0x78, 0xa4, 0x65, 0x30, 0x37, 0xd8, 0xb4, 0x48, 0xe1, 0xb8, 0x07, 0xa1, 0x83, 0x1d, 0xbc, 0x53, 0x22, 0xd0, 0x66, 0x98, 0x4e, 0xec, 0x28, 0x11, 0x4f, 0xb7, 0x20, 0x1c, 0x79, 0x6b, 0x57, 0x3a, 0xdc, 0xc5, 0xcc, 0x92, 0x7f, 0x3a, 0x58, 0x97, 0xb2, 0x00, 0x55, 0x64, 0xef, 0x1a, 0x2c, 0x01, 0x67, 0xf5, 0x43, 0x65, 0x51, 0x18, 0x34, 0xac, 0x6f, 0x49, 0x58, 0xb8, 0x31, 0x8d, 0x09, 0xe6, 0x78, 0x54, 0xd6, 0x31, 0xca, 0x52, 0x80, 0x76, 0x86, 0xab, 0x70, 0x5d, 0x71, 0xa3 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.4", + /* Message */ + 47, + { 0xa5, 0x4b, 0xc2, 0x27, 0x8b, 0x56, 0x76, 0x85, 0xc9, 0xb5, 0x68, 0x54, 0xe4, 0xc1, 0xc4, 0x06, 0xd9, 0x16, 0x17, 0x47, 0xc6, 0x81, 0x34, 0x80, 0x16, 0x3e, 0xe3, 0xaf, 0x23, 0xb2, 0x1e, 0xd1, 0x99, 0x83, 0xe0, 0xf4, 0x2b, 0xfc, 0x93, 0x25, 0xcb, 0x5c, 0x82, 0xe1, 0xa4, 0x7b, 0x8f } +, + /* Seed */ + 78, + { 0xcc, 0xba, 0x5f, 0xa5, 0xc9, 0x4e, 0x79, 0x83, 0x2a, 0xb0, 0x46, 0xc9, 0x77, 0x74, 0x95, 0xb1, 0x63, 0xbd, 0x3a, 0xf2, 0x17, 0x59, 0x0f, 0xec, 0x5a, 0xc4, 0x8c, 0x62, 0x78, 0x6a, 0x27, 0xf3, 0x70, 0xd2, 0x85, 0x99, 0x55, 0xe4, 0x5a, 0xfb, 0x2b, 0x79, 0xf1, 0x2d, 0xe4, 0x16, 0x11, 0x45, 0xbe, 0x62, 0xac, 0x13, 0xa0, 0x3b, 0xf4, 0x81, 0x95, 0xfb, 0x9e, 0x5a, 0x18, 0xb8, 0x2d, 0xeb, 0xbf, 0x3d, 0xdf, 0xc8, 0x08, 0x25, 0xd5, 0x93, 0xfc, 0xd4, 0x02, 0xe7, 0x4e, 0xef } +, + /* Encryption */ + 128, + { 0x3d, 0xe4, 0xc3, 0xe0, 0x59, 0x35, 0x7b, 0x8a, 0x54, 0x83, 0x7e, 0xa1, 0x59, 0x62, 0xcf, 0xe2, 0x00, 0x7c, 0x5e, 0xa8, 0x98, 0x5c, 0x93, 0x51, 0x91, 0x64, 0xa6, 0x89, 0xb7, 0x55, 0xb6, 0x1c, 0x8b, 0xd2, 0x73, 0x96, 0x9d, 0x33, 0x3c, 0x4b, 0xcd, 0x9b, 0x06, 0x03, 0x53, 0xc3, 0x7b, 0xaf, 0x13, 0xeb, 0x42, 0x2f, 0x1c, 0xb9, 0x77, 0x56, 0xe6, 0xb4, 0x94, 0x6a, 0xdf, 0xe1, 0xaf, 0x75, 0xe9, 0xfe, 0x2d, 0x95, 0xb4, 0xb1, 0x3d, 0xa1, 0x73, 0x2b, 0xd8, 0xb8, 0xbe, 0x11, 0x97, 0x02, 0x79, 0x19, 0x53, 0x0c, 0x34, 0x7f, 0x3d, 0xd1, 0x03, 0x9e, 0x34, 0x8a, 0x53, 0xb1, 0x16, 0xf9, 0xf8, 0xfe, 0x89, 0x36, 0xa8, 0x4a, 0xcc, 0x39, 0xf2, 0xe0, 0x69, 0x56, 0xb6, 0x78, 0xd2, 0x0f, 0xdf, 0x95, 0x17, 0x07, 0x2e, 0x02, 0xf5, 0x70, 0x78, 0xfd, 0xc0, 0x46, 0x59, 0x40, 0x0c, 0x5c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.5", + /* Message */ + 58, + { 0xf3, 0xc0, 0x0b, 0x00, 0x9e, 0x5e, 0x08, 0xa6, 0x3b, 0xe1, 0xe4, 0x00, 0x35, 0xcd, 0xac, 0xa5, 0x01, 0x1c, 0xc7, 0x01, 0xcf, 0x7e, 0xeb, 0xcb, 0x99, 0xf0, 0xff, 0xe1, 0x7c, 0xfd, 0x0a, 0x4b, 0xf7, 0xbe, 0xfd, 0x2d, 0xd5, 0x36, 0xac, 0x94, 0x6d, 0xb7, 0x97, 0xfd, 0xbc, 0x67, 0x9c, 0xbe, 0x68, 0xf1, 0xa2, 0xf3, 0x62, 0x59, 0xc5, 0x58, 0xf0, 0x4d } +, + /* Seed */ + 67, + { 0xe2, 0x2d, 0x5e, 0x43, 0xb1, 0xeb, 0xa1, 0xac, 0x0c, 0xe6, 0x5c, 0x32, 0x70, 0x51, 0x0e, 0x0f, 0x13, 0xc9, 0x4e, 0x96, 0x24, 0xee, 0x52, 0x56, 0x59, 0xef, 0x4d, 0x57, 0x37, 0x88, 0x20, 0xc9, 0x35, 0x22, 0x9b, 0x30, 0x99, 0xaa, 0x2b, 0x23, 0x50, 0x61, 0x4f, 0x8c, 0xc4, 0x29, 0x58, 0x15, 0xa2, 0xc9, 0xed, 0xb2, 0xd9, 0xc5, 0x9c, 0x73, 0xd1, 0xaa, 0x90, 0x0c, 0x21, 0x34, 0xc0, 0xa7, 0xd0, 0x90, 0x9c } +, + /* Encryption */ + 128, + { 0x53, 0x3e, 0x67, 0xa2, 0xbc, 0x5b, 0x3f, 0x01, 0x34, 0x2d, 0x8c, 0xb8, 0xd9, 0x25, 0xd7, 0x3b, 0x4d, 0xb3, 0x4c, 0xb6, 0x75, 0xda, 0x90, 0x39, 0x22, 0x6a, 0x98, 0xe4, 0xd8, 0x13, 0xc6, 0x20, 0x11, 0x09, 0x90, 0xa8, 0xe6, 0xac, 0xba, 0x50, 0xfd, 0x04, 0xf3, 0x30, 0x7d, 0xeb, 0xaf, 0x20, 0xd4, 0xf3, 0x74, 0xcf, 0x6d, 0xe0, 0xd9, 0xb2, 0x1d, 0x86, 0xe2, 0x66, 0x07, 0x9c, 0xf2, 0xf1, 0x8b, 0x45, 0x03, 0x20, 0x8a, 0x21, 0x5d, 0xe2, 0xb1, 0x1c, 0xca, 0x9e, 0x34, 0x64, 0xfc, 0x5a, 0xc1, 0xdd, 0x7e, 0x96, 0xb2, 0xfc, 0x04, 0x09, 0xe4, 0x2f, 0x46, 0xa5, 0x06, 0x12, 0xa6, 0xb2, 0x06, 0x1e, 0xd1, 0x61, 0x9a, 0x7f, 0xe4, 0x67, 0x96, 0xed, 0x8f, 0x52, 0x06, 0x9a, 0x5b, 0xfc, 0x84, 0x08, 0xd5, 0x58, 0xf5, 0x2a, 0x03, 0x33, 0x2e, 0xe8, 0xed, 0xde, 0xf8, 0xf7, 0x45, 0xd9 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.6", + /* Message */ + 53, + { 0xaa, 0xfe, 0x5b, 0x27, 0x11, 0x11, 0xef, 0xb8, 0x79, 0x2f, 0x5a, 0xa9, 0x23, 0x83, 0x07, 0x29, 0x76, 0xb7, 0x2a, 0x0a, 0x27, 0x2f, 0x90, 0xc5, 0x24, 0x61, 0xf8, 0x8a, 0xfb, 0x1b, 0xb6, 0xb7, 0xec, 0x26, 0x38, 0x1c, 0x65, 0x76, 0xa4, 0x10, 0x87, 0xa0, 0x39, 0x80, 0x9d, 0x14, 0xf6, 0x11, 0x60, 0x67, 0x59, 0x4e, 0xbb } +, + /* Seed */ + 72, + { 0x75, 0x0e, 0xf0, 0x86, 0x9f, 0x8c, 0x75, 0x7e, 0xf4, 0x31, 0x57, 0x8b, 0x45, 0xa6, 0xe7, 0x41, 0xbd, 0x1d, 0x96, 0x0e, 0xfc, 0x37, 0x89, 0xb1, 0x0d, 0x2b, 0xde, 0x27, 0x38, 0x18, 0x07, 0x4e, 0xbf, 0xe5, 0xfa, 0xae, 0x10, 0xac, 0x24, 0x4f, 0x89, 0xf6, 0xc0, 0x2d, 0xe5, 0xd1, 0xad, 0xae, 0xfc, 0x7a, 0x8f, 0xd2, 0x4d, 0x7b, 0xc3, 0x76, 0xfd, 0x65, 0xd3, 0x5e, 0x39, 0x50, 0x8c, 0x42, 0x36, 0xac, 0xbe, 0x2d, 0x5c, 0xa7, 0x69, 0x4b } +, + /* Encryption */ + 128, + { 0x34, 0x4d, 0x43, 0x37, 0x61, 0x2b, 0x22, 0xdd, 0x40, 0x2b, 0xe3, 0x79, 0xe6, 0xb2, 0x65, 0x0b, 0x51, 0x9e, 0xf3, 0x7b, 0x7a, 0xb4, 0x85, 0x81, 0x94, 0x52, 0xd1, 0x67, 0xc1, 0xb2, 0x15, 0xdb, 0xd3, 0xfb, 0x24, 0xf9, 0xb2, 0xf9, 0x29, 0x86, 0x69, 0xcb, 0x1a, 0xee, 0x14, 0x1a, 0x7d, 0x89, 0x01, 0x64, 0x20, 0x43, 0x11, 0x1f, 0xc3, 0x8b, 0x3f, 0x40, 0xef, 0x0b, 0x7f, 0xfd, 0x7d, 0xf7, 0x6c, 0x2d, 0x92, 0xe3, 0x29, 0x41, 0x1c, 0x75, 0xe0, 0xf1, 0x72, 0x85, 0xbb, 0x6b, 0xb8, 0x26, 0x88, 0x12, 0x8e, 0xd9, 0xbb, 0x95, 0x1c, 0xae, 0xdd, 0x7d, 0x06, 0x7e, 0xdd, 0x0b, 0x13, 0xe8, 0x27, 0x5a, 0xc8, 0x86, 0x25, 0xd9, 0x7c, 0xe8, 0xd2, 0x0b, 0x69, 0xb3, 0x57, 0x38, 0xb2, 0xf4, 0x72, 0x6e, 0x29, 0x84, 0xb8, 0xdf, 0xa8, 0x66, 0x95, 0xaa, 0xe8, 0x8d, 0x9e, 0x17, 0x6d, 0xf6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.7", + /* Message */ + 37, + { 0xa1, 0x22, 0x4d, 0xf9, 0xaa, 0xb6, 0x58, 0x78, 0x45, 0xb2, 0xa3, 0x93, 0xa5, 0xa8, 0x76, 0xc1, 0x7d, 0x95, 0x9d, 0x53, 0x5b, 0x54, 0x19, 0xd4, 0x12, 0xa9, 0xa5, 0x31, 0xbb, 0x43, 0x7e, 0x1d, 0xac, 0x1b, 0x54, 0x6d, 0x62 } +, + /* Seed */ + 88, + { 0x76, 0x1d, 0xc4, 0xf5, 0x1b, 0xc8, 0x51, 0x8d, 0x62, 0x7c, 0x45, 0xb3, 0xe9, 0x81, 0x8b, 0x85, 0x42, 0xa0, 0x6f, 0xfe, 0x17, 0x2b, 0xe3, 0xaf, 0x5c, 0xe7, 0xa9, 0x05, 0x3f, 0xe5, 0x4e, 0x69, 0x70, 0x12, 0x49, 0x73, 0x37, 0x4d, 0xfc, 0xc1, 0xf4, 0x9f, 0xcf, 0xfe, 0x95, 0x7a, 0xae, 0x8c, 0x9c, 0x3b, 0x13, 0x0f, 0x46, 0x05, 0xd2, 0xc3, 0xef, 0xa2, 0x93, 0x2a, 0xd0, 0x83, 0xde, 0xc5, 0x8e, 0x70, 0xd4, 0xf6, 0x92, 0x6c, 0x80, 0xb5, 0xd4, 0x89, 0x1a, 0x1a, 0x55, 0x9e, 0xdb, 0x0c, 0xaf, 0xfa, 0xca, 0xd7, 0x5e, 0xb2, 0x64, 0x83 } +, + /* Encryption */ + 128, + { 0x78, 0x5f, 0x6a, 0xaa, 0xb4, 0xd2, 0xf3, 0x18, 0xd4, 0xaf, 0x37, 0xb6, 0xe0, 0x07, 0x4e, 0xd5, 0xa4, 0x19, 0x4f, 0xa6, 0x05, 0xa7, 0xec, 0x87, 0xd0, 0x5a, 0x07, 0xf3, 0x34, 0x9b, 0x5b, 0x92, 0xf5, 0xfc, 0x47, 0x90, 0xea, 0xb1, 0x37, 0x86, 0xcb, 0xf0, 0x35, 0xc7, 0x8f, 0xfc, 0xf1, 0x34, 0x4d, 0x1f, 0x3e, 0xcd, 0xaa, 0xe0, 0x16, 0x72, 0x22, 0x2e, 0x6d, 0x4a, 0x96, 0x55, 0x59, 0xe2, 0xc0, 0x82, 0x91, 0xcb, 0x1d, 0x4c, 0x2d, 0x4e, 0x68, 0xff, 0x8e, 0xe7, 0x15, 0x23, 0xf6, 0xdd, 0xae, 0xc5, 0x0a, 0x4a, 0xb2, 0x2e, 0xdc, 0xa2, 0x47, 0x36, 0x4c, 0x92, 0xd8, 0x73, 0x99, 0xe8, 0xa7, 0x1d, 0xf7, 0x43, 0x6b, 0x62, 0xd8, 0xba, 0x8a, 0xd2, 0x02, 0x94, 0xcb, 0xc6, 0x0d, 0xca, 0xe0, 0x30, 0x5c, 0x79, 0x73, 0xf7, 0xfc, 0xb4, 0xa5, 0xcb, 0xed, 0x15, 0x71, 0x3a, 0x7a, 0x16 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.8", + /* Message */ + 48, + { 0x1e, 0x0e, 0x3f, 0x65, 0x0c, 0x32, 0xdb, 0xb2, 0xf6, 0x91, 0x6f, 0x36, 0xf1, 0x35, 0xbc, 0xae, 0x88, 0x1d, 0x54, 0x55, 0x07, 0x40, 0x2d, 0x6a, 0xfd, 0x3d, 0x5b, 0x3b, 0xd8, 0x38, 0x5a, 0x50, 0xb4, 0xfa, 0xd6, 0xf7, 0x89, 0x49, 0xfd, 0xe6, 0x21, 0x64, 0xed, 0x76, 0x89, 0xe5, 0xf9, 0xa4 } +, + /* Seed */ + 77, + { 0xee, 0xa9, 0x0a, 0x54, 0xd0, 0x16, 0xda, 0x7e, 0x8f, 0x08, 0x76, 0xa7, 0x33, 0xb0, 0xf2, 0xa0, 0x6f, 0x90, 0xa7, 0x3c, 0x1a, 0x3c, 0xd6, 0x39, 0xb6, 0xcf, 0xa9, 0x06, 0xce, 0x08, 0xef, 0x78, 0x8b, 0xb6, 0xfe, 0xa7, 0x4f, 0x22, 0xeb, 0x91, 0xa6, 0xab, 0x32, 0x84, 0xcd, 0xfc, 0x1e, 0x72, 0xe6, 0x3e, 0x78, 0xd1, 0x8a, 0x64, 0xd6, 0x7f, 0x9d, 0x1a, 0x29, 0x19, 0x49, 0xed, 0x2e, 0x32, 0x3e, 0x91, 0xdc, 0x03, 0x38, 0x76, 0xee, 0xeb, 0x09, 0xff, 0xa7, 0x1f, 0x59 } +, + /* Encryption */ + 128, + { 0x6b, 0xbd, 0xae, 0x20, 0xf9, 0x89, 0xbf, 0xaa, 0x5d, 0x65, 0xda, 0xdc, 0xd6, 0x1a, 0x86, 0xb6, 0x63, 0x07, 0xa0, 0x60, 0x2f, 0xb5, 0x51, 0xa7, 0x38, 0x06, 0x12, 0x2d, 0xb1, 0x88, 0xec, 0x1d, 0x41, 0xe8, 0x4d, 0xaa, 0x2c, 0xc7, 0xd6, 0xbe, 0x54, 0x1e, 0x12, 0x28, 0x88, 0x09, 0xa1, 0x7e, 0x08, 0x5f, 0x2c, 0xaf, 0xa8, 0xae, 0x13, 0x67, 0x0e, 0x0f, 0x33, 0x65, 0xa1, 0x47, 0x1c, 0xb3, 0x15, 0x7c, 0x06, 0xe0, 0xf6, 0x3b, 0x82, 0x00, 0xf3, 0x16, 0x0c, 0x16, 0x3f, 0xde, 0x7c, 0x90, 0x1e, 0xf3, 0x26, 0xe5, 0x70, 0x0c, 0x9f, 0x5e, 0x07, 0xfe, 0x01, 0x98, 0x81, 0x0f, 0xa8, 0x0c, 0x8c, 0x5d, 0xc5, 0x3a, 0x50, 0xbc, 0xe2, 0x54, 0xf7, 0xd1, 0x99, 0x01, 0xcf, 0x6c, 0xbb, 0x60, 0x34, 0x13, 0xe4, 0x1f, 0x90, 0x30, 0xe7, 0x39, 0xc8, 0xba, 0x96, 0x49, 0x97, 0x84, 0x74, 0x99 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.9", + /* Message */ + 32, + { 0x73, 0xdd, 0xf0, 0xa1, 0x4d, 0x57, 0xba, 0x65, 0xb4, 0xf6, 0x93, 0xac, 0x76, 0x1e, 0x20, 0x2b, 0x1e, 0x5b, 0x85, 0x7c, 0x8b, 0x34, 0x04, 0xe1, 0x41, 0x85, 0xdf, 0xa8, 0xaa, 0xf0, 0x49, 0x89 } +, + /* Seed */ + 93, + { 0xfd, 0x43, 0x3d, 0x7b, 0x01, 0x76, 0xb7, 0x31, 0xd7, 0x80, 0xdd, 0x6c, 0x58, 0x51, 0xb8, 0x2f, 0x17, 0x6d, 0x62, 0xb8, 0x0d, 0x96, 0xae, 0xb6, 0x31, 0xd7, 0xfb, 0x8a, 0xc5, 0xbe, 0x55, 0xac, 0x21, 0x7f, 0x4e, 0x08, 0xbc, 0x7e, 0xcf, 0x81, 0xf8, 0xe3, 0xf5, 0xdd, 0xaa, 0xcd, 0xc6, 0xc2, 0x17, 0x8d, 0xf7, 0x81, 0x88, 0x23, 0x97, 0x53, 0x3a, 0x63, 0x8e, 0x62, 0xf0, 0x74, 0xac, 0x48, 0x8f, 0x4c, 0x12, 0xaa, 0x57, 0xbe, 0x2e, 0xce, 0x5b, 0xb6, 0xe9, 0x09, 0x6c, 0xd9, 0x22, 0x59, 0xa4, 0x5b, 0x0b, 0x03, 0x2f, 0x10, 0x14, 0x31, 0xa2, 0x8b, 0x86, 0x40, 0xfb } +, + /* Encryption */ + 128, + { 0xae, 0x97, 0xff, 0x43, 0x4e, 0x9a, 0x5e, 0xe4, 0x87, 0x76, 0x1d, 0xb3, 0x56, 0x90, 0x0b, 0x06, 0x37, 0x37, 0x46, 0x5b, 0xe5, 0x05, 0x8d, 0xc0, 0x3a, 0x28, 0xa3, 0x22, 0xe5, 0xc0, 0xe0, 0x91, 0xb7, 0x99, 0xbf, 0x65, 0x94, 0x55, 0xcf, 0xbe, 0x05, 0x42, 0x7a, 0xc4, 0xd0, 0x44, 0x05, 0xe5, 0x6e, 0xe0, 0x4e, 0x06, 0x3a, 0x23, 0x73, 0xdb, 0xcb, 0x9b, 0x4f, 0xa1, 0x6e, 0x43, 0x07, 0x94, 0x6a, 0x49, 0xb3, 0x56, 0x34, 0x52, 0x0d, 0x41, 0x6f, 0x65, 0xc3, 0xc3, 0x22, 0xed, 0xc5, 0x46, 0x71, 0x56, 0x91, 0x28, 0xa2, 0xa1, 0x52, 0xa7, 0x6f, 0xe4, 0x44, 0xc4, 0x30, 0xaa, 0x6f, 0x03, 0xc4, 0x12, 0x9c, 0x6e, 0x21, 0x31, 0x75, 0x5d, 0x76, 0x4c, 0xec, 0x4a, 0x14, 0x86, 0xa8, 0x1b, 0xa8, 0xa3, 0x16, 0x8d, 0x16, 0xe7, 0x4d, 0xca, 0x8e, 0x77, 0xbb, 0xfd, 0x67, 0xea, 0x37, 0x2b } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.10", + /* Message */ + 29, + { 0xef, 0x3e, 0x76, 0x98, 0xe7, 0xd9, 0xcc, 0x86, 0x3b, 0x46, 0x6b, 0xb2, 0x88, 0x55, 0x6e, 0x4a, 0xc2, 0x52, 0x82, 0xe0, 0x94, 0xfb, 0x5b, 0x57, 0xc1, 0x76, 0x17, 0xbb, 0x98 } +, + /* Seed */ + 96, + { 0xdb, 0x90, 0xa7, 0x58, 0x0d, 0x8d, 0x42, 0x9e, 0x22, 0xbd, 0x7e, 0xa5, 0xc7, 0xb4, 0xcd, 0x0c, 0x65, 0xad, 0x0e, 0x2e, 0x27, 0xf5, 0x33, 0x41, 0xbc, 0x23, 0xa8, 0xb1, 0x35, 0x8a, 0x76, 0xa0, 0xb5, 0xe9, 0x4f, 0xc5, 0xb4, 0x2a, 0x9f, 0x75, 0x6c, 0xc6, 0x3b, 0x9d, 0x62, 0x3f, 0x55, 0x17, 0x67, 0xfb, 0xc6, 0xf7, 0x11, 0x4e, 0x40, 0xba, 0x73, 0x61, 0xfd, 0x32, 0xd6, 0xf8, 0xd7, 0x72, 0x34, 0x37, 0x43, 0x6d, 0xf7, 0x24, 0xb1, 0x32, 0x7a, 0xae, 0xf7, 0xb9, 0x57, 0x56, 0x27, 0x68, 0xf8, 0xfa, 0xdd, 0x57, 0x86, 0x2b, 0xa0, 0xb3, 0x14, 0x09, 0x6a, 0x3b, 0x38, 0x77, 0x0e, 0x31 } +, + /* Encryption */ + 128, + { 0x43, 0xf8, 0xcc, 0xce, 0xa8, 0x12, 0xd3, 0x38, 0x5f, 0x43, 0xfa, 0x83, 0x7c, 0xb5, 0xe6, 0xfa, 0x59, 0x0f, 0x1a, 0xff, 0xb8, 0x62, 0xd2, 0xca, 0xcc, 0xc6, 0xd8, 0xe8, 0xbb, 0x5d, 0x5c, 0x0d, 0x50, 0xff, 0xb9, 0xf8, 0xf8, 0x09, 0x89, 0x00, 0xc1, 0x2e, 0x77, 0x2a, 0x84, 0x7b, 0x37, 0x81, 0x57, 0x78, 0x2b, 0x0a, 0x90, 0x40, 0xf7, 0xa6, 0x16, 0xc2, 0xeb, 0x05, 0x8e, 0x44, 0xd4, 0xa7, 0xe2, 0x0b, 0x48, 0x5a, 0xc2, 0x9f, 0x40, 0xd6, 0x8e, 0x03, 0xc3, 0x9d, 0xdc, 0x8d, 0xae, 0x7e, 0x7e, 0x09, 0xe2, 0x8f, 0x9d, 0xd2, 0x19, 0x0f, 0x3a, 0x9f, 0x35, 0x74, 0xb2, 0xf6, 0x34, 0x00, 0x15, 0x44, 0x36, 0x3c, 0x86, 0x1f, 0xe2, 0x7f, 0x7a, 0x39, 0x23, 0x66, 0x92, 0xfe, 0x35, 0x82, 0x14, 0x0b, 0x21, 0x72, 0xce, 0x64, 0x7e, 0xed, 0x41, 0x76, 0x85, 0xc6, 0xe1, 0xdb, 0x85, 0x6c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.11", + /* Message */ + 31, + { 0xf8, 0x69, 0x18, 0x47, 0x4f, 0x88, 0x16, 0x97, 0x11, 0x1b, 0xdd, 0xdc, 0x1f, 0x00, 0x61, 0x3e, 0xb2, 0xc3, 0xd9, 0xc1, 0x78, 0x76, 0x68, 0x35, 0x3e, 0xbb, 0x02, 0xb3, 0x20, 0xa3, 0x26 } +, + /* Seed */ + 94, + { 0xcb, 0x7d, 0x99, 0xda, 0x9b, 0x11, 0xea, 0x57, 0xf6, 0x40, 0x55, 0x43, 0x44, 0x7d, 0xd1, 0x5f, 0xb5, 0xcc, 0xa0, 0xa1, 0x0f, 0x3b, 0x69, 0xb4, 0xd2, 0x33, 0x09, 0xef, 0xf2, 0x75, 0x0c, 0x48, 0x6c, 0xa6, 0x55, 0x32, 0x5b, 0x55, 0xa3, 0x27, 0xff, 0xe8, 0xbd, 0x6d, 0xca, 0x99, 0xbc, 0x8e, 0xfb, 0x5b, 0xc2, 0x94, 0x2e, 0xc0, 0x39, 0xe2, 0x84, 0x25, 0xe4, 0xa5, 0x6a, 0x07, 0xd3, 0x80, 0x12, 0xf1, 0x0d, 0x21, 0x5a, 0x22, 0xd6, 0x37, 0x68, 0x59, 0x43, 0xd3, 0x64, 0x72, 0x53, 0x01, 0xdd, 0x40, 0xe2, 0x17, 0x22, 0x8a, 0xb7, 0x91, 0x59, 0x89, 0x98, 0x83, 0x6b, 0xbf } +, + /* Encryption */ + 128, + { 0x2a, 0x40, 0x87, 0x80, 0xad, 0x51, 0x4e, 0x56, 0x71, 0xfe, 0x1d, 0xfc, 0x36, 0x7d, 0x7a, 0xa4, 0x65, 0xfc, 0x34, 0x69, 0xf1, 0xc1, 0x52, 0xae, 0xe1, 0x81, 0x45, 0xe0, 0xf5, 0xf0, 0x75, 0x9f, 0x44, 0x69, 0xb4, 0x3d, 0x55, 0x12, 0x3f, 0x5d, 0xc9, 0xff, 0xc6, 0x17, 0xf2, 0x3f, 0xa4, 0x9b, 0x78, 0x96, 0x02, 0x19, 0x66, 0x0e, 0xc6, 0x22, 0x74, 0xd6, 0xc5, 0x9b, 0xa3, 0x14, 0x60, 0xbd, 0x10, 0x94, 0x1e, 0xbb, 0x5e, 0x05, 0x69, 0x41, 0x51, 0xc5, 0x7b, 0x5b, 0x95, 0x88, 0xca, 0xf0, 0x9f, 0x45, 0x50, 0x20, 0xa5, 0x4e, 0x97, 0x7c, 0x3c, 0xc0, 0x27, 0xda, 0xe3, 0x1f, 0x2c, 0xe4, 0x42, 0x17, 0x02, 0x3e, 0x10, 0xad, 0xb6, 0xf2, 0xd8, 0xaa, 0x0f, 0x80, 0x84, 0xfc, 0x45, 0x86, 0x05, 0x80, 0x3f, 0xd4, 0x4b, 0x21, 0xab, 0xc2, 0x7b, 0xdb, 0x8d, 0x4c, 0x56, 0x17, 0x84, 0xcf } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.12", + /* Message */ + 22, + { 0x6a, 0x40, 0xbb, 0x60, 0x70, 0x8c, 0x5a, 0x99, 0x2e, 0xcf, 0xdc, 0x7e, 0xe5, 0x3f, 0x54, 0x08, 0x4d, 0x19, 0xaf, 0xfd, 0x4d, 0x21 } +, + /* Seed */ + 103, + { 0xc3, 0xf4, 0xfa, 0xca, 0x56, 0xc1, 0xff, 0x07, 0xd1, 0xad, 0x10, 0x37, 0x07, 0xd1, 0xb6, 0x68, 0x20, 0x47, 0xb4, 0xd9, 0xd6, 0x24, 0x6c, 0x2e, 0x5c, 0x4b, 0x0c, 0xe6, 0x55, 0x3d, 0x55, 0x31, 0x3f, 0x8f, 0x38, 0xae, 0xe5, 0xe4, 0xd8, 0x07, 0x3a, 0x55, 0xd2, 0x4a, 0xd7, 0x96, 0xc4, 0xb7, 0x61, 0x26, 0xc8, 0xaa, 0x61, 0xc4, 0x6a, 0x4e, 0xe8, 0x5f, 0xa9, 0x05, 0x7a, 0x52, 0x6c, 0xd0, 0xaa, 0x24, 0x5e, 0x58, 0x28, 0xf2, 0x18, 0x1b, 0x4a, 0x64, 0x79, 0x86, 0x87, 0x48, 0xe7, 0x47, 0x9f, 0x40, 0x34, 0x53, 0x3c, 0x0f, 0x3e, 0x1e, 0xb4, 0x35, 0xfa, 0x47, 0xd5, 0x3b, 0x58, 0xe4, 0x2c, 0x96, 0x17, 0xbf, 0x7e, 0x77, 0x7e } +, + /* Encryption */ + 128, + { 0xc4, 0x64, 0x11, 0xc7, 0x11, 0x6f, 0xe6, 0xf4, 0x6f, 0x1c, 0xa0, 0xf7, 0x4c, 0x60, 0x81, 0xa5, 0x5d, 0xf4, 0x1d, 0x2c, 0x0b, 0x8f, 0xc5, 0xd3, 0x8f, 0xaa, 0x34, 0x0b, 0x5e, 0xcf, 0x71, 0x83, 0xf8, 0x5f, 0x88, 0xc4, 0xfb, 0x28, 0xac, 0x5f, 0xb1, 0xf1, 0x8a, 0xeb, 0xfc, 0xfc, 0x10, 0xbf, 0xdd, 0x3a, 0x19, 0x00, 0x2c, 0x6b, 0x52, 0x24, 0x14, 0x92, 0x70, 0x4b, 0x6f, 0xe6, 0x3d, 0x61, 0xa7, 0x30, 0x10, 0xc1, 0x49, 0xff, 0x63, 0x03, 0x28, 0x3e, 0x99, 0x78, 0xcd, 0x84, 0x54, 0x04, 0xfa, 0x06, 0xb8, 0xc6, 0x98, 0xaa, 0xea, 0x8f, 0x86, 0x13, 0x61, 0xd8, 0x86, 0xb2, 0xc0, 0xf0, 0x1b, 0x47, 0xa1, 0xa9, 0xa3, 0xdd, 0x90, 0x3f, 0x8a, 0x58, 0xae, 0xd6, 0x6a, 0xfc, 0x85, 0xe9, 0xb7, 0x1e, 0xfc, 0x3f, 0x55, 0xa1, 0x21, 0x66, 0x74, 0x16, 0xa3, 0x00, 0x00, 0x13, 0x13, 0xe8 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.13", + /* Message */ + 13, + { 0x32, 0x52, 0xfe, 0x99, 0x62, 0x09, 0x74, 0xe0, 0x77, 0xd6, 0xeb, 0x55, 0x75 } +, + /* Seed */ + 112, + { 0xbf, 0x06, 0x9b, 0x4b, 0xcf, 0x15, 0x44, 0x8b, 0xc3, 0x9e, 0x45, 0xf4, 0x42, 0x6a, 0xad, 0x0d, 0x5d, 0x82, 0xb7, 0x4e, 0x93, 0xae, 0x1c, 0xdd, 0x71, 0xf7, 0x1b, 0xb9, 0xbe, 0xb9, 0xb2, 0x3d, 0x59, 0x73, 0x2f, 0x9c, 0x8b, 0xc6, 0x34, 0x3d, 0x13, 0x02, 0x31, 0xde, 0x18, 0xf7, 0xc8, 0x9f, 0xc2, 0xf4, 0x22, 0x18, 0x9c, 0xd9, 0x27, 0xe5, 0x09, 0xb1, 0x31, 0x97, 0xaa, 0x56, 0xd8, 0x1a, 0x73, 0x76, 0xf8, 0x33, 0x3e, 0x47, 0x42, 0x44, 0x8c, 0xc8, 0x92, 0xde, 0x40, 0x44, 0x97, 0x2c, 0x7f, 0x67, 0xdc, 0xbe, 0x85, 0x44, 0xa9, 0x0e, 0xec, 0x59, 0xe7, 0x95, 0xae, 0x59, 0x64, 0x08, 0x39, 0x2a, 0xf5, 0x77, 0x6d, 0xa0, 0xd6, 0xcb, 0x29, 0xc7, 0xe0, 0xa7, 0x86, 0x81, 0x30, 0xa7 } +, + /* Encryption */ + 128, + { 0x76, 0x53, 0xcb, 0xff, 0x58, 0x68, 0x92, 0xcd, 0xd2, 0x58, 0xbf, 0xe6, 0xba, 0xeb, 0xd9, 0x91, 0x45, 0xeb, 0x1b, 0x22, 0x89, 0x4e, 0x1a, 0x76, 0x4d, 0x02, 0xb2, 0xba, 0x99, 0x59, 0x52, 0xa0, 0x12, 0x58, 0x20, 0x8d, 0xe1, 0xa0, 0x1d, 0x8e, 0x8c, 0xbb, 0x5c, 0xda, 0xf0, 0xd6, 0x03, 0x69, 0x4f, 0x88, 0x25, 0x5e, 0x80, 0x90, 0x97, 0xb7, 0x0e, 0x9d, 0x79, 0xe6, 0x2b, 0xd5, 0xc0, 0xd8, 0x36, 0xdc, 0xc2, 0x9d, 0xd1, 0x9b, 0x05, 0xa1, 0x60, 0x26, 0x90, 0x42, 0x05, 0xb6, 0x0c, 0x45, 0x03, 0xd4, 0xfb, 0xe9, 0x93, 0x38, 0x55, 0xe8, 0x68, 0x02, 0xc7, 0x54, 0x28, 0xd9, 0xa6, 0x34, 0x73, 0x03, 0x16, 0x76, 0x32, 0xd3, 0x3c, 0x5d, 0x9e, 0xcc, 0x8a, 0xe2, 0x49, 0x3b, 0x58, 0xc3, 0x6b, 0x2a, 0x65, 0x53, 0xa7, 0xb9, 0xe2, 0xb1, 0x35, 0x8a, 0xe2, 0x8d, 0xad, 0x50, 0x28, 0x0d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.14", + /* Message */ + 2, + { 0xdc, 0x94 } +, + /* Seed */ + 123, + { 0x05, 0xe8, 0x05, 0xbf, 0xfb, 0xd1, 0xb7, 0x4d, 0x1a, 0x5a, 0x83, 0x8d, 0x85, 0x71, 0x67, 0xb4, 0xc7, 0xd4, 0x0a, 0x6c, 0xd3, 0xe6, 0x8f, 0x31, 0xbe, 0x46, 0x93, 0xb9, 0x8c, 0xec, 0x6d, 0x75, 0x89, 0x49, 0x19, 0xab, 0x18, 0x57, 0x2c, 0x75, 0x82, 0x2e, 0x75, 0xe9, 0xde, 0xd7, 0x2d, 0xa0, 0x67, 0x97, 0x83, 0xa7, 0x72, 0x18, 0x14, 0xe1, 0x99, 0x16, 0x0b, 0x75, 0x07, 0xf6, 0x7f, 0x4e, 0xde, 0x58, 0x7c, 0x88, 0xbe, 0x76, 0x81, 0x5c, 0x50, 0xb2, 0x61, 0xdf, 0x30, 0x8b, 0x31, 0x43, 0x23, 0x73, 0x0c, 0x1e, 0x07, 0x3a, 0xa7, 0x29, 0x98, 0xcc, 0x2f, 0x8e, 0x0a, 0x8a, 0x5b, 0xd6, 0x5b, 0xf9, 0x34, 0xac, 0xa8, 0xa6, 0x48, 0x59, 0xe2, 0x5f, 0x02, 0xc5, 0xa2, 0x71, 0x39, 0x41, 0xc8, 0xc8, 0xe6, 0x27, 0x20, 0x84, 0x6d, 0xfb, 0x51, 0xc2, 0xff } +, + /* Encryption */ + 128, + { 0x6a, 0xdd, 0xe2, 0x44, 0xf0, 0x63, 0x8c, 0x5a, 0xb7, 0x45, 0xff, 0xba, 0xb5, 0xab, 0xe1, 0xfe, 0x80, 0x0b, 0x0e, 0xee, 0x15, 0x35, 0x50, 0xc4, 0x8c, 0x36, 0xf4, 0x24, 0x9f, 0x9d, 0x5d, 0x36, 0xb4, 0x7b, 0x28, 0xcc, 0xda, 0x71, 0xa7, 0xdd, 0x83, 0x2e, 0x64, 0x35, 0xad, 0x0e, 0xb8, 0x5e, 0xf7, 0x55, 0x6b, 0xb8, 0x4b, 0xf9, 0x5a, 0x59, 0xcc, 0xc9, 0xc2, 0x07, 0x51, 0xed, 0x3e, 0x1a, 0xd0, 0xde, 0x10, 0x29, 0x94, 0xa7, 0x12, 0xc5, 0x14, 0x01, 0x46, 0x92, 0xa6, 0x7f, 0x1d, 0x87, 0xca, 0x2e, 0x4f, 0xef, 0x29, 0xec, 0x83, 0xe0, 0x1e, 0x29, 0xad, 0x0c, 0x97, 0x8a, 0xcc, 0xa4, 0xd5, 0xc5, 0x02, 0x74, 0x5a, 0x6c, 0x50, 0x0d, 0xf2, 0x00, 0x04, 0xbc, 0x9b, 0xf1, 0x6f, 0x5f, 0xcc, 0x69, 0xbf, 0x52, 0x70, 0x9e, 0x31, 0xcf, 0x6a, 0x2b, 0x9f, 0xe6, 0x24, 0xd9, 0xa3, 0x64 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.15", + /* Message */ + 8, + { 0x4f, 0xae, 0x6c, 0xf3, 0x7e, 0x9d, 0x5f, 0x59 } +, + /* Seed */ + 117, + { 0xe7, 0xf9, 0xed, 0x4a, 0x0c, 0x3a, 0x64, 0x66, 0x69, 0x03, 0x9b, 0xd0, 0x1f, 0x24, 0x9f, 0x32, 0xbe, 0xa1, 0xe6, 0x57, 0x6c, 0x21, 0xd4, 0x51, 0x89, 0xd0, 0xf8, 0x91, 0xcf, 0x4a, 0xfd, 0x62, 0x32, 0x08, 0x3a, 0x32, 0x1e, 0xd2, 0xd3, 0x4d, 0x07, 0x09, 0x84, 0xf5, 0xe9, 0x45, 0x78, 0x39, 0xb2, 0xeb, 0xc1, 0xe0, 0x3a, 0x2c, 0x0d, 0x8d, 0xd7, 0x09, 0x73, 0x1e, 0x95, 0xb2, 0xe6, 0x94, 0x1c, 0xa0, 0x90, 0x71, 0x87, 0xaf, 0xfd, 0xcf, 0x5a, 0x87, 0xf5, 0xcb, 0xea, 0xd2, 0xf9, 0x05, 0x2c, 0x38, 0xd0, 0xee, 0x54, 0xe1, 0xf1, 0x28, 0xff, 0xc3, 0x37, 0xde, 0x45, 0x66, 0xa5, 0x92, 0x5e, 0x1e, 0x94, 0x7a, 0xef, 0x50, 0x88, 0x1c, 0xbd, 0xae, 0xd9, 0x9b, 0x1b, 0xbc, 0x1a, 0xf5, 0x13, 0x23, 0x2c, 0x0f, 0xf4 } +, + /* Encryption */ + 128, + { 0x46, 0xe6, 0x70, 0x5e, 0xb1, 0x25, 0x2d, 0xeb, 0xf8, 0xec, 0x67, 0x2c, 0x4f, 0xde, 0xaf, 0x69, 0x88, 0x26, 0x84, 0x59, 0xf9, 0x95, 0x89, 0xbb, 0xd3, 0x05, 0x41, 0x33, 0xd4, 0x83, 0xab, 0xe1, 0xe2, 0x7c, 0xaa, 0xb0, 0xa7, 0xf0, 0x22, 0x1b, 0x1b, 0x67, 0xa1, 0x4e, 0xbf, 0x45, 0x12, 0x6e, 0x60, 0x13, 0x48, 0xb0, 0x43, 0x44, 0x06, 0xda, 0x3a, 0x8c, 0x76, 0xd4, 0xf1, 0xe3, 0xf1, 0xa0, 0xe0, 0x6d, 0x0d, 0xb8, 0x23, 0xda, 0x51, 0x17, 0xb9, 0x2a, 0x40, 0xb6, 0xf3, 0x9f, 0x57, 0xe4, 0x83, 0xa7, 0xda, 0x36, 0xe9, 0x9b, 0x67, 0x7b, 0xb3, 0xf7, 0x6e, 0x6c, 0x5d, 0xb0, 0x3f, 0x3c, 0xe4, 0x45, 0x04, 0xeb, 0xd4, 0x5e, 0x9f, 0x14, 0xfe, 0x0f, 0x61, 0x3a, 0x2e, 0xb7, 0x95, 0x47, 0xab, 0x57, 0x8c, 0x58, 0x6d, 0x3b, 0x65, 0x4a, 0x06, 0xfe, 0x1e, 0xf3, 0x7a, 0x22, 0x10, 0x66 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.16", + /* Message */ + 14, + { 0xcd, 0xfd, 0xfd, 0xaa, 0xbc, 0xa3, 0x76, 0x7e, 0x70, 0xbb, 0xc5, 0xe9, 0xab, 0xf6 } +, + /* Seed */ + 111, + { 0xac, 0x77, 0x7f, 0x67, 0x29, 0x9d, 0xe4, 0xc1, 0xc4, 0xc5, 0x74, 0xf3, 0x1f, 0x67, 0x4f, 0x6f, 0xaa, 0xbd, 0xe0, 0x31, 0xf8, 0xec, 0x33, 0xe8, 0x26, 0x76, 0xeb, 0x32, 0xa9, 0x3f, 0x65, 0x79, 0xaa, 0xc3, 0xe9, 0x59, 0x35, 0x9f, 0xc5, 0x73, 0xee, 0x5c, 0x0e, 0x3e, 0x07, 0x76, 0x53, 0xef, 0xf9, 0xd5, 0xf8, 0xdb, 0x4b, 0x1e, 0x7a, 0xca, 0xdb, 0x05, 0x99, 0x71, 0x53, 0x1f, 0x49, 0xb0, 0x7c, 0x93, 0xeb, 0x9f, 0xde, 0xdc, 0xf0, 0x90, 0x3a, 0x7d, 0x50, 0xb4, 0x79, 0x67, 0x6f, 0xcd, 0xe8, 0x74, 0x0a, 0xfb, 0xd7, 0xd3, 0x7c, 0x3a, 0x21, 0x02, 0x41, 0x2b, 0xde, 0x1d, 0x3a, 0x82, 0x44, 0x15, 0x6a, 0xd8, 0x08, 0x9d, 0x45, 0xdf, 0xdc, 0x91, 0xcd, 0xe6, 0xc3, 0xa1, 0x59 } +, + /* Encryption */ + 128, + { 0x51, 0x3c, 0x76, 0x1e, 0xb1, 0x92, 0x9a, 0xff, 0x79, 0x77, 0xa9, 0xff, 0x0e, 0x61, 0xb7, 0xa1, 0xd5, 0x11, 0xc8, 0xcb, 0x25, 0x39, 0x24, 0x33, 0x24, 0x25, 0x56, 0x9a, 0x07, 0xe2, 0x29, 0xcb, 0x39, 0x01, 0x71, 0x53, 0x90, 0xf7, 0xde, 0x37, 0xbd, 0x36, 0x2c, 0x96, 0xfc, 0x0b, 0x0d, 0x79, 0x81, 0x0c, 0x1e, 0x8b, 0x15, 0xe1, 0x3b, 0x00, 0x32, 0x73, 0x47, 0x78, 0xcf, 0x96, 0x4e, 0x6f, 0x6d, 0x17, 0xfc, 0x41, 0xc7, 0x86, 0x76, 0x72, 0xb2, 0x54, 0x0f, 0x56, 0x9d, 0x0a, 0x46, 0x0a, 0x80, 0xfa, 0xd5, 0x6b, 0x5f, 0x05, 0x4a, 0xb8, 0xe4, 0x9e, 0x40, 0x9e, 0x9e, 0x0b, 0x86, 0x13, 0xcb, 0x3d, 0xa2, 0x0c, 0x35, 0xc3, 0xe1, 0xbb, 0x99, 0xb7, 0xec, 0xab, 0x7a, 0x00, 0xfc, 0x1f, 0xc2, 0x37, 0x0f, 0x9c, 0x80, 0x85, 0x67, 0xdf, 0x89, 0xbe, 0x2e, 0xdd, 0xbd, 0xb6, 0xb1, 0x10 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.17", + /* Message */ + 18, + { 0xb8, 0x20, 0xc3, 0x2e, 0x73, 0x7d, 0xaa, 0x23, 0x4f, 0x29, 0xba, 0x90, 0x64, 0x7f, 0xc3, 0xbf, 0x0a, 0x8e } +, + /* Seed */ + 107, + { 0xf5, 0xca, 0xf8, 0xfe, 0xb4, 0x2d, 0xf7, 0xb6, 0xb3, 0x89, 0xf5, 0x05, 0x99, 0xa4, 0xec, 0x20, 0xe6, 0x19, 0xca, 0x22, 0xd2, 0xbf, 0xc9, 0x1b, 0xc7, 0xf1, 0x4a, 0xe9, 0xf1, 0x22, 0x9e, 0x07, 0xc8, 0x88, 0xed, 0x57, 0xaa, 0x6a, 0xd3, 0xc1, 0x04, 0x10, 0x44, 0xc5, 0x1a, 0xfb, 0x55, 0x21, 0x7b, 0x0c, 0xaa, 0x23, 0x34, 0xad, 0x79, 0xf4, 0x7a, 0xbb, 0xf9, 0xb4, 0x20, 0x83, 0x33, 0xb7, 0x2b, 0x4b, 0xa4, 0xbb, 0x5f, 0xd0, 0x37, 0x98, 0x1d, 0xd8, 0x01, 0x70, 0xc8, 0x03, 0x60, 0xc1, 0x4d, 0x5a, 0xf5, 0x1e, 0x5f, 0x82, 0xab, 0xf5, 0x1f, 0xd3, 0x6f, 0x02, 0x18, 0x67, 0xa6, 0xec, 0x09, 0x7b, 0xc3, 0x39, 0x22, 0xac, 0xea, 0xd9, 0xe3, 0x35, 0x58 } +, + /* Encryption */ + 128, + { 0x3e, 0x23, 0x25, 0x18, 0x41, 0xdb, 0x2e, 0x20, 0x7a, 0x27, 0x10, 0x1f, 0x13, 0x29, 0x19, 0x1a, 0xb7, 0xfa, 0x6a, 0x70, 0x1a, 0x52, 0x62, 0x61, 0x48, 0x23, 0x53, 0xa1, 0xa2, 0x21, 0xef, 0xa9, 0xd3, 0xa9, 0xd4, 0x59, 0xcd, 0x2a, 0x2d, 0x86, 0x68, 0x90, 0x8b, 0x78, 0x3b, 0xb0, 0x9c, 0x87, 0x9a, 0x21, 0x7f, 0x1e, 0x40, 0x0f, 0x95, 0xb2, 0x17, 0xb0, 0x40, 0xa5, 0x3e, 0x34, 0x1c, 0x17, 0xb9, 0x3d, 0x3c, 0x3d, 0x65, 0x46, 0x0c, 0x5c, 0x7f, 0x2b, 0x4d, 0x79, 0xa3, 0x4b, 0x5a, 0x96, 0x11, 0x7a, 0xa3, 0x67, 0x51, 0xd9, 0xea, 0xf2, 0x33, 0xb0, 0x3f, 0x68, 0xdb, 0xa6, 0xa4, 0x57, 0x1b, 0x90, 0x71, 0x77, 0xf8, 0x28, 0x33, 0x6e, 0x82, 0x5a, 0x92, 0x26, 0x1b, 0x62, 0x36, 0x39, 0xbe, 0xc9, 0x8d, 0x3a, 0x09, 0xf8, 0x72, 0xc2, 0xec, 0x59, 0x1b, 0x4c, 0x38, 0x3a, 0x69, 0xc7 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.18", + /* Message */ + 43, + { 0x60, 0x6b, 0xbd, 0x61, 0x37, 0x15, 0xdd, 0xcd, 0x92, 0xc7, 0xb6, 0xdf, 0x04, 0xb3, 0x60, 0x72, 0xf0, 0x11, 0x62, 0xd0, 0x08, 0x76, 0x63, 0x12, 0xca, 0x69, 0x77, 0xdd, 0x3a, 0x06, 0xeb, 0x95, 0xe1, 0xba, 0xc7, 0xbc, 0x1b, 0xc6, 0x60, 0x2c, 0x9e, 0xe6, 0x44 } +, + /* Seed */ + 82, + { 0x51, 0x3a, 0x5c, 0x95, 0x68, 0xe8, 0x9b, 0x9a, 0x53, 0xd5, 0xaf, 0x71, 0x6e, 0x55, 0xfb, 0x34, 0x0f, 0x8a, 0x39, 0x23, 0x70, 0xe8, 0x88, 0xa8, 0x0c, 0xae, 0xda, 0x50, 0x2e, 0x7f, 0x9d, 0xfc, 0x17, 0x51, 0x95, 0xa5, 0x0e, 0x47, 0x07, 0x13, 0x96, 0xd6, 0xec, 0x55, 0x4e, 0xb7, 0x2f, 0x18, 0x3b, 0xe1, 0x8f, 0x3b, 0xf4, 0xec, 0x73, 0xb3, 0x05, 0x92, 0xfa, 0xef, 0x2f, 0xb5, 0x14, 0xde, 0xbe, 0xfc, 0xc6, 0x5c, 0x8d, 0x23, 0xc4, 0xad, 0x25, 0x94, 0x56, 0xc1, 0xe8, 0x0b, 0x36, 0x0a, 0xd4, 0x59 } +, + /* Encryption */ + 128, + { 0x47, 0x21, 0xa2, 0x39, 0x40, 0x18, 0x87, 0x30, 0xf5, 0xde, 0xac, 0x85, 0x00, 0x2e, 0x38, 0x31, 0xb1, 0x49, 0xae, 0x57, 0xaf, 0xc6, 0x97, 0x35, 0xa0, 0x45, 0xee, 0x3f, 0xc3, 0x53, 0x64, 0x72, 0xfc, 0x83, 0x3c, 0x27, 0xc8, 0x7e, 0xab, 0x6f, 0xc9, 0x05, 0xe3, 0x67, 0x96, 0x1b, 0x31, 0x24, 0x98, 0x63, 0x6b, 0xe6, 0xc7, 0x7a, 0xa8, 0x0b, 0x8d, 0xa2, 0xf5, 0xd9, 0x48, 0xaa, 0xa7, 0x7b, 0x5f, 0xab, 0x72, 0x4b, 0xbf, 0x64, 0xee, 0x89, 0xd2, 0x81, 0xee, 0xd4, 0x7b, 0x21, 0x2c, 0x32, 0x95, 0x26, 0x65, 0x77, 0xf4, 0xfd, 0x93, 0xa2, 0x22, 0x39, 0xde, 0xe5, 0x40, 0xc9, 0x40, 0x0f, 0xe5, 0x6d, 0x7a, 0xef, 0x51, 0xdf, 0x36, 0xa8, 0x9a, 0xe9, 0x2f, 0x92, 0x6f, 0x55, 0x83, 0x31, 0xe4, 0x1b, 0xfd, 0xfe, 0xfe, 0x35, 0x75, 0x8b, 0x93, 0xce, 0x11, 0x40, 0xac, 0x9b, 0x6a, 0x54 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.19", + /* Message */ + 36, + { 0x1d, 0x82, 0xde, 0xf8, 0xc5, 0x92, 0x87, 0x50, 0x08, 0xa5, 0xf8, 0x9e, 0x7e, 0xb6, 0x4e, 0x25, 0x2e, 0xdd, 0xe9, 0xdd, 0xb8, 0x81, 0xd3, 0x73, 0x62, 0x31, 0x7f, 0x6e, 0x6e, 0x6e, 0x99, 0x3c, 0x60, 0x23, 0x3b, 0x0f } +, + /* Seed */ + 89, + { 0x87, 0x5e, 0x07, 0x5e, 0xf1, 0xb0, 0x54, 0xb5, 0x84, 0x1e, 0x08, 0x45, 0x0d, 0x78, 0xeb, 0x54, 0xa5, 0x5c, 0x88, 0xb6, 0xd0, 0x18, 0x13, 0xc1, 0x07, 0xa0, 0x9b, 0x74, 0x54, 0x3b, 0x3f, 0x9f, 0xe1, 0xb7, 0xc9, 0x02, 0x11, 0xc6, 0x2e, 0xa7, 0x33, 0x81, 0x20, 0xd4, 0xae, 0x0f, 0x73, 0xba, 0x82, 0xc0, 0x1d, 0x28, 0xf8, 0x19, 0x4b, 0x3a, 0x39, 0x6b, 0xdf, 0x50, 0xf9, 0x41, 0x3a, 0x7f, 0xb0, 0x3b, 0xe2, 0x25, 0xfe, 0x05, 0x45, 0xdb, 0x80, 0xcd, 0xf0, 0xf6, 0x10, 0xa9, 0x5f, 0xd9, 0x03, 0x76, 0xe0, 0x39, 0xe3, 0x83, 0x1f, 0xf9, 0x9e } +, + /* Encryption */ + 128, + { 0x8f, 0xb5, 0x46, 0x26, 0x3c, 0x1d, 0x18, 0x75, 0xc7, 0x43, 0xf5, 0x2f, 0x02, 0x67, 0xb2, 0xf2, 0xfe, 0x68, 0x8d, 0x25, 0x42, 0x02, 0x10, 0x49, 0xf5, 0x34, 0x89, 0xce, 0x7c, 0x35, 0x91, 0x30, 0xf8, 0xe1, 0x1e, 0x3c, 0x46, 0x1c, 0x5e, 0x86, 0x3e, 0x4d, 0xc1, 0x9f, 0x07, 0xa1, 0x3a, 0x4c, 0x1a, 0x88, 0x22, 0x4b, 0x26, 0xc5, 0xc0, 0xcb, 0xe2, 0x02, 0x02, 0x45, 0xd9, 0x1e, 0x1b, 0x83, 0x42, 0x42, 0x52, 0x52, 0xf5, 0x3f, 0xc4, 0x0e, 0x4b, 0x14, 0xfa, 0x02, 0xbb, 0xd7, 0x47, 0x37, 0xd4, 0x02, 0x2c, 0xc5, 0x4f, 0xe3, 0x8f, 0x0d, 0x27, 0xd8, 0xfe, 0xa5, 0x0f, 0x2f, 0xdd, 0x84, 0x65, 0xd4, 0xf3, 0x2f, 0x8a, 0xc0, 0x3e, 0xe0, 0x06, 0xbe, 0x62, 0x33, 0xe4, 0xd1, 0xa3, 0xc1, 0x6e, 0xb1, 0x44, 0xb5, 0xd8, 0xbe, 0x72, 0x9a, 0xd3, 0x04, 0xf8, 0x23, 0x61, 0xe0, 0x7c, 0xfb } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 6.20", + /* Message */ + 28, + { 0x8a, 0x8a, 0x3e, 0xab, 0xdc, 0xa7, 0xca, 0xb0, 0xcc, 0x29, 0x6a, 0x29, 0x1e, 0xa8, 0xa9, 0x3d, 0xa4, 0xd2, 0xd2, 0xa1, 0x96, 0xff, 0x2f, 0x8d, 0x18, 0x1f, 0xee, 0x1f } +, + /* Seed */ + 97, + { 0x2e, 0x47, 0x36, 0xe4, 0x29, 0x6a, 0xb4, 0x66, 0x18, 0xb1, 0xef, 0x34, 0xda, 0x26, 0x77, 0x6e, 0x92, 0xef, 0x66, 0xf7, 0xcd, 0x17, 0x4e, 0xf9, 0x47, 0x69, 0x72, 0x42, 0x23, 0xa7, 0x65, 0xb4, 0xeb, 0xef, 0x08, 0xa8, 0x8f, 0xed, 0xbe, 0x27, 0x05, 0x60, 0xe5, 0xf6, 0x74, 0x37, 0xcf, 0x49, 0xd5, 0x7e, 0xa6, 0x62, 0x0a, 0xca, 0x59, 0x89, 0x8a, 0xfd, 0x52, 0xcd, 0xef, 0x30, 0xa8, 0xb0, 0xd9, 0x85, 0x5e, 0x5d, 0xfb, 0xe3, 0x47, 0xde, 0x77, 0xc4, 0xc0, 0x28, 0x0b, 0x0f, 0x1f, 0xd4, 0x4d, 0x4f, 0xe6, 0x89, 0x06, 0xbe, 0x8a, 0x4f, 0x12, 0xc5, 0x33, 0x08, 0x7b, 0xf5, 0xbc, 0xea, 0xfb } +, + /* Encryption */ + 128, + { 0x03, 0xf3, 0xe4, 0xba, 0x03, 0x48, 0x31, 0xa0, 0xe3, 0x0a, 0x4a, 0x33, 0x44, 0xce, 0xad, 0x61, 0xb2, 0x8b, 0x43, 0xbe, 0x31, 0x53, 0x2c, 0x2d, 0x76, 0x37, 0x53, 0x9b, 0x90, 0x13, 0x83, 0x7e, 0xdc, 0xb1, 0xf2, 0x16, 0xd3, 0x2f, 0xdf, 0xae, 0x73, 0x32, 0x36, 0x74, 0xa2, 0x81, 0x45, 0x65, 0xdb, 0xf2, 0x9e, 0x71, 0x2d, 0x18, 0xc4, 0x37, 0x39, 0x64, 0xdf, 0x60, 0xc9, 0x39, 0x9f, 0xda, 0x54, 0x14, 0xa0, 0xeb, 0x45, 0xbd, 0xe8, 0x66, 0x1a, 0x89, 0x09, 0x12, 0x95, 0xa1, 0xef, 0x71, 0x61, 0x6a, 0x3c, 0xd1, 0x45, 0xe9, 0xb3, 0x18, 0xb6, 0x51, 0xaf, 0x17, 0x5d, 0x4e, 0xc3, 0x50, 0x1d, 0x5e, 0xb7, 0x63, 0xe8, 0xd3, 0x5a, 0x2b, 0x72, 0x74, 0x6e, 0x02, 0x0b, 0x4b, 0xa5, 0x99, 0x73, 0x83, 0x4b, 0x21, 0x50, 0x02, 0x6b, 0x43, 0x2b, 0x17, 0x9a, 0x9a, 0xe8, 0x17, 0x2b, 0x7b } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 7: A 1025-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x01, 0x70, 0x93, 0x41, 0xd2, 0xec, 0x08, 0x04, 0xa7, 0x40, 0x34, 0xe8, 0xfa, 0x72, 0x86, 0x42, 0x98, 0x3d, 0x16, 0x50, 0xd7, 0x46, 0xe4, 0x49, 0xc9, 0xee, 0x40, 0x79, 0xaa, 0x15, 0xe5, 0x1f, 0x1f, 0xc1, 0x34, 0x24, 0x2e, 0x52, 0x4b, 0x0d, 0x3d, 0x0d, 0xbf, 0x5a, 0x51, 0x21, 0x93, 0x9b, 0x12, 0x5f, 0xcc, 0x86, 0x3e, 0x51, 0x41, 0x60, 0xb6, 0x34, 0xe3, 0x7a, 0xa6, 0x98, 0x94, 0x77, 0x6c, 0x7d, 0x33, 0xe1, 0xe7, 0xc6, 0x19, 0x52, 0x1d, 0xe4, 0x82, 0xa0, 0xae, 0xa4, 0x5c, 0x3c, 0x6a, 0xbc, 0x3f, 0x33, 0xe2, 0x5d, 0x86, 0xff, 0xa1, 0x39, 0x33, 0x25, 0x65, 0x9b, 0xf2, 0xd4, 0x09, 0x8d, 0xf1, 0x69, 0xb4, 0x07, 0x21, 0x87, 0x66, 0x0e, 0x27, 0x77, 0x00, 0x19, 0x9b, 0x7a, 0x3e, 0x34, 0x84, 0xb3, 0x84, 0x5f, 0x6f, 0xbf, 0x31, 0x98, 0x65, 0x7d, 0xf8, 0xcb, 0xf3, 0xa8, 0x1b } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x6f, 0xeb, 0xf7, 0x98, 0x12, 0x1e, 0x99, 0x33, 0x24, 0x97, 0x2c, 0x8c, 0x28, 0xcc, 0xc6, 0x5a, 0x2e, 0x6a, 0xa1, 0x5f, 0xcd, 0xe2, 0x32, 0xda, 0x03, 0xe4, 0x46, 0x4d, 0xb4, 0xda, 0x5f, 0xaa, 0x27, 0xe4, 0x2a, 0x7c, 0x7a, 0x76, 0xd9, 0xed, 0x49, 0x48, 0x6b, 0x27, 0xa9, 0xd7, 0x85, 0xc6, 0x7d, 0x9a, 0xc0, 0xc5, 0x19, 0xad, 0x8d, 0xad, 0xa6, 0xbf, 0xd1, 0x15, 0xd7, 0xcd, 0x75, 0xb9, 0x9c, 0x4b, 0x59, 0xc7, 0x69, 0x83, 0xa7, 0x01, 0x5b, 0x0d, 0xa6, 0x97, 0x3c, 0x69, 0xfa, 0x95, 0x08, 0x10, 0xae, 0x27, 0x68, 0xd9, 0x75, 0x88, 0x90, 0x05, 0x62, 0xe8, 0x6a, 0x6d, 0xf7, 0xc7, 0x14, 0xb8, 0x44, 0xb1, 0xe0, 0x46, 0x68, 0x6a, 0x5a, 0xfc, 0x66, 0x7b, 0x13, 0x57, 0x3a, 0x55, 0xbe, 0x9b, 0x5b, 0x38, 0xb9, 0x9b, 0xd3, 0xcf, 0x54, 0xe4, 0x34, 0x4a, 0x2f, 0x2d, 0x0e, 0x21 } +, + /* Prime 1 */ + 65, + { 0x01, 0x40, 0xef, 0x5b, 0x50, 0x70, 0x54, 0xd5, 0xa6, 0x94, 0x46, 0x4e, 0xf4, 0x7e, 0x49, 0x86, 0x8c, 0xb3, 0x3c, 0x97, 0xe0, 0xe3, 0xed, 0xd7, 0x7b, 0xf4, 0x5a, 0x52, 0x5e, 0x60, 0x8d, 0x7e, 0x21, 0x5f, 0x91, 0x33, 0x48, 0xa9, 0xb8, 0x27, 0xc8, 0x39, 0x73, 0x7a, 0x42, 0xb6, 0xad, 0xfb, 0xb2, 0xbb, 0x49, 0x7e, 0x14, 0x78, 0x92, 0x2f, 0x71, 0x88, 0x97, 0xd9, 0xfe, 0xed, 0x27, 0x7a, 0x6b } +, + /* Prime 2 */ + 65, + { 0x01, 0x26, 0x00, 0x4b, 0xbe, 0x2d, 0xf7, 0x6b, 0x6f, 0x38, 0xae, 0xa1, 0x64, 0xb1, 0xfd, 0x0f, 0x97, 0x61, 0x2b, 0x2d, 0xb9, 0x6c, 0xed, 0xe2, 0x8a, 0x3a, 0x91, 0xce, 0x0d, 0x74, 0x25, 0x3b, 0xb3, 0xf9, 0x55, 0x9b, 0x89, 0xf4, 0x81, 0x33, 0x75, 0x65, 0x2a, 0x50, 0x70, 0x06, 0xce, 0x99, 0x95, 0xa9, 0x8f, 0x0e, 0x6e, 0xf3, 0xbc, 0x22, 0xe5, 0x51, 0x9b, 0x61, 0x3b, 0xfb, 0xcd, 0x55, 0x11 } +, + /* Prime exponent 1 */ + 64, + { 0x98, 0x14, 0xd4, 0xe0, 0xb9, 0x5a, 0x7a, 0x24, 0x05, 0xff, 0x8b, 0x4a, 0xb0, 0xcd, 0x86, 0xc5, 0x05, 0xea, 0xa0, 0xce, 0x21, 0x34, 0x83, 0xf8, 0x69, 0x42, 0xa3, 0xe5, 0xb5, 0x3b, 0x57, 0x99, 0xd8, 0xff, 0xa5, 0x9d, 0xb9, 0x4f, 0x5b, 0x0a, 0xb6, 0xae, 0xd2, 0x30, 0xeb, 0x00, 0x67, 0x55, 0xbb, 0x0a, 0x88, 0x84, 0x8a, 0xde, 0x3b, 0x3d, 0x41, 0xcd, 0x33, 0xb0, 0x6a, 0x11, 0x5b, 0x21 } +, + /* Prime exponent 2 */ + 64, + { 0x1c, 0x4b, 0x1c, 0xfe, 0xf1, 0x67, 0x85, 0x34, 0x4f, 0xed, 0x26, 0x65, 0x0d, 0x68, 0x00, 0x2f, 0x1e, 0x4f, 0xcc, 0x77, 0xb2, 0xce, 0xf5, 0xe5, 0x3d, 0x9b, 0xb8, 0x8b, 0xbc, 0xe8, 0xb4, 0x65, 0x2e, 0x92, 0x99, 0x84, 0x5e, 0x3e, 0x6c, 0xd8, 0x58, 0x63, 0x09, 0x18, 0xae, 0xdf, 0x05, 0x12, 0xcd, 0x1d, 0x92, 0x53, 0x05, 0x2b, 0xce, 0xe3, 0xe8, 0xc5, 0x9e, 0x46, 0xea, 0x85, 0xa9, 0x31 } +, + /* Coefficient */ + 64, + { 0xfd, 0xc5, 0x10, 0xc4, 0xd9, 0x79, 0x07, 0x30, 0xb0, 0xfd, 0x47, 0xd3, 0x13, 0xab, 0xd4, 0x08, 0x58, 0xc7, 0xdf, 0xd5, 0x8f, 0x4b, 0x37, 0x91, 0x5f, 0x7a, 0x4b, 0x1d, 0xb3, 0xd7, 0xd8, 0xab, 0xd0, 0x6d, 0x3d, 0xa0, 0x02, 0xde, 0x98, 0x4a, 0x76, 0x09, 0xcc, 0x18, 0xa9, 0x44, 0x86, 0x46, 0x0a, 0x61, 0x74, 0x6c, 0x7e, 0xa6, 0x31, 0x17, 0xa6, 0x8a, 0xa2, 0x82, 0x59, 0x74, 0x4f, 0x49 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 7.1", + /* Message */ + 58, + { 0xda, 0x50, 0x9d, 0xce, 0x45, 0xe2, 0x47, 0x00, 0x37, 0x9b, 0xfe, 0x5a, 0xa1, 0xa8, 0x1c, 0x24, 0x70, 0x6c, 0x18, 0x42, 0xd9, 0xb1, 0x3e, 0x7a, 0x2e, 0x0a, 0x15, 0xd3, 0xa4, 0xaf, 0x8e, 0x6d, 0x08, 0x61, 0x2d, 0xca, 0xa1, 0x5d, 0x46, 0x0e, 0xce, 0x87, 0x29, 0x88, 0xe3, 0xe9, 0x0f, 0xb2, 0x7e, 0x5c, 0xa5, 0xc1, 0x0f, 0xa1, 0xfa, 0xcd, 0xcb, 0x0e } +, + /* Seed */ + 68, + { 0x80, 0x8c, 0x20, 0x46, 0xfb, 0x50, 0x5c, 0x37, 0x69, 0x5c, 0x8d, 0xc3, 0x5c, 0x38, 0xf9, 0xf9, 0x90, 0x5a, 0xb4, 0x8a, 0x2b, 0x8a, 0x14, 0x6e, 0x8e, 0x8e, 0xda, 0x33, 0x85, 0xce, 0xd9, 0x5a, 0x31, 0x3b, 0x2d, 0xc6, 0xeb, 0x41, 0x83, 0x67, 0xfe, 0xef, 0xf7, 0x9a, 0x02, 0xad, 0x74, 0x64, 0x6d, 0xf7, 0xa5, 0xd8, 0x70, 0x54, 0xac, 0xdd, 0xaf, 0x34, 0xea, 0xfd, 0x5c, 0x1d, 0xb5, 0x8e, 0x5d, 0xec, 0x04, 0x81 } +, + /* Encryption */ + 129, + { 0x00, 0xfc, 0x3d, 0x0a, 0xaa, 0xf2, 0x6c, 0xdf, 0x25, 0xa1, 0xa8, 0xdf, 0xcb, 0x71, 0x70, 0x0f, 0xb6, 0x5e, 0x2a, 0xb5, 0x55, 0x1a, 0xe5, 0xf4, 0x19, 0xb2, 0xd2, 0xf9, 0x4c, 0xef, 0x01, 0x73, 0x02, 0xb0, 0x0a, 0xbd, 0x9e, 0x6c, 0x6e, 0xfa, 0xe9, 0x44, 0x74, 0xd1, 0x8e, 0x68, 0xda, 0x0a, 0x7c, 0x17, 0xef, 0x2c, 0x5f, 0xcc, 0x89, 0x07, 0x1d, 0x3b, 0x07, 0x12, 0x1b, 0x9c, 0x01, 0xe3, 0x0f, 0xf0, 0x53, 0x66, 0x3f, 0x61, 0xf8, 0x9f, 0xdb, 0xc4, 0x9b, 0xdc, 0xf8, 0xe6, 0x71, 0x66, 0x94, 0x43, 0x91, 0x9d, 0x41, 0x34, 0x28, 0x45, 0xe3, 0xe9, 0x9e, 0x46, 0xa8, 0xa3, 0xb4, 0x8e, 0x23, 0x98, 0xa8, 0x8e, 0x5b, 0x45, 0xd9, 0x9a, 0x17, 0xdd, 0x1f, 0x21, 0x2e, 0xda, 0xbc, 0xbc, 0xd3, 0x00, 0xa8, 0x4d, 0x39, 0x8e, 0xf5, 0x79, 0x35, 0xbd, 0xae, 0x95, 0x9e, 0x60, 0x54, 0xe7, 0x3a } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 7.2", + /* Message */ + 12, + { 0xce, 0x0a, 0x79, 0x47, 0x49, 0x87, 0x41, 0x60, 0xe5, 0xd2, 0xe4, 0xff } +, + /* Seed */ + 114, + { 0xf4, 0xb2, 0xc9, 0xf3, 0x11, 0xc1, 0xfd, 0x41, 0xd4, 0x79, 0x44, 0xb5, 0x0e, 0x17, 0x55, 0xd4, 0xea, 0xc5, 0xee, 0x65, 0x08, 0x7c, 0x9f, 0xc6, 0xd2, 0xf0, 0x75, 0xb7, 0x38, 0xc6, 0x49, 0x26, 0xea, 0xf7, 0xd4, 0x31, 0x6b, 0xcd, 0xb6, 0x36, 0x54, 0xd5, 0x42, 0x0d, 0xa6, 0x1e, 0x02, 0x45, 0xf1, 0x95, 0xb9, 0xe8, 0x24, 0xaa, 0x0b, 0x06, 0xc8, 0x87, 0x99, 0xb1, 0x27, 0xfe, 0x9b, 0x03, 0x6d, 0xf3, 0x61, 0x75, 0xc0, 0xa6, 0xbd, 0x80, 0xe4, 0xe0, 0xaf, 0x6e, 0xbc, 0x2f, 0x42, 0x70, 0xb0, 0x4c, 0xe3, 0x0b, 0x9f, 0xa2, 0x7f, 0x04, 0x35, 0x86, 0x0f, 0xcc, 0xf4, 0x0b, 0x3d, 0xc7, 0xea, 0xef, 0xfd, 0xba, 0xb9, 0xe1, 0x76, 0x66, 0x19, 0xbb, 0x01, 0x6c, 0x17, 0x90, 0x26, 0x63, 0xcb, 0x24 } +, + /* Encryption */ + 129, + { 0x01, 0x0c, 0xf7, 0x4b, 0xeb, 0xc2, 0x63, 0x6d, 0x2c, 0x49, 0xd9, 0xc6, 0x22, 0xbd, 0x76, 0xcc, 0x0b, 0x1d, 0x02, 0xeb, 0xb5, 0x2f, 0xdf, 0xae, 0xc0, 0x1c, 0x4a, 0xc1, 0xe7, 0x56, 0x07, 0x1a, 0x8e, 0xf7, 0x6e, 0x12, 0x2a, 0x4c, 0x62, 0xc6, 0xba, 0x32, 0x65, 0xfa, 0x4c, 0x90, 0x56, 0x26, 0xd1, 0x13, 0xd5, 0x9d, 0xb7, 0x9a, 0xd6, 0x5f, 0x86, 0x40, 0xb3, 0xc4, 0x34, 0x4d, 0x73, 0x40, 0xc1, 0x6e, 0x38, 0xde, 0xb1, 0x89, 0xe3, 0xa1, 0xb1, 0x1e, 0xaa, 0xb0, 0xb2, 0x60, 0x6a, 0x7f, 0x82, 0xf5, 0x94, 0x6d, 0x41, 0x9a, 0xce, 0xbb, 0xbb, 0x3a, 0x93, 0x7d, 0x41, 0xe2, 0x9b, 0x33, 0xed, 0xd3, 0xad, 0x15, 0xf1, 0xe7, 0x77, 0x0f, 0xcf, 0xc3, 0x0a, 0xe0, 0x6a, 0xa0, 0x1b, 0xcd, 0x03, 0xd5, 0xdf, 0xb1, 0x62, 0xf8, 0x7a, 0x18, 0x39, 0x67, 0x55, 0x3c, 0x25, 0x02, 0xcb, 0x5f, 0xfe } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.3", + /* Message */ + 2, + { 0x41, 0xd6 } +, + /* Seed */ + 124, + { 0x55, 0x6e, 0x59, 0xb2, 0xc1, 0x89, 0x58, 0x75, 0x08, 0xe2, 0x08, 0x92, 0xfa, 0x56, 0x02, 0xd2, 0x49, 0xfb, 0xfb, 0x71, 0xa1, 0x09, 0x05, 0xed, 0x5a, 0xf7, 0xb7, 0x9b, 0xe8, 0x71, 0x11, 0xa0, 0xc6, 0x9a, 0xdd, 0xb1, 0x9e, 0xef, 0x31, 0x6d, 0x7c, 0x0b, 0x21, 0x81, 0x79, 0x90, 0xdc, 0x3e, 0xd8, 0xc7, 0x6c, 0xb2, 0x3e, 0x83, 0x0e, 0x17, 0xc0, 0xf4, 0x38, 0x73, 0x15, 0x9f, 0xab, 0x7c, 0x5c, 0x4a, 0x6c, 0xf2, 0x19, 0xcb, 0x1d, 0xc5, 0xc5, 0xda, 0x45, 0x53, 0xa3, 0xe0, 0xbf, 0x18, 0x3b, 0x8e, 0x11, 0x2b, 0x61, 0xf6, 0x92, 0xa7, 0xdd, 0xf0, 0x04, 0xbd, 0xbf, 0xdc, 0xc8, 0xd6, 0x65, 0x9c, 0x3d, 0xd8, 0x0c, 0xb2, 0x3a, 0xab, 0xe8, 0xc6, 0xfd, 0xf2, 0x67, 0x5d, 0x07, 0x3b, 0x66, 0x23, 0x12, 0xe4, 0xac, 0xcd, 0xe9, 0x1c, 0x12, 0x25, 0xe6, 0xd1 } +, + /* Encryption */ + 129, + { 0x00, 0x2a, 0x10, 0x04, 0x95, 0x59, 0x66, 0x55, 0x30, 0x4b, 0xdd, 0xf9, 0x09, 0x7f, 0x78, 0xd9, 0xdd, 0xb5, 0xeb, 0x42, 0x9b, 0x66, 0x63, 0x5a, 0x58, 0xa2, 0x98, 0xf1, 0x92, 0x8e, 0xed, 0x61, 0x53, 0x4f, 0x80, 0xb4, 0xea, 0x05, 0xee, 0x39, 0xb0, 0x2a, 0x64, 0x56, 0x6f, 0x6c, 0x45, 0x6e, 0x3b, 0x58, 0x6e, 0x7c, 0xb4, 0x3a, 0x88, 0x94, 0x0e, 0xe1, 0x29, 0x34, 0x0f, 0x57, 0x8e, 0x56, 0xe7, 0x2d, 0x8b, 0x27, 0x83, 0x36, 0x10, 0x06, 0xd9, 0x71, 0x29, 0xab, 0xef, 0x02, 0xcf, 0x1c, 0x19, 0x12, 0xe1, 0x7f, 0x0c, 0xd1, 0xd7, 0x1c, 0x0b, 0x32, 0x8d, 0x0b, 0x48, 0xa4, 0xac, 0x7a, 0xec, 0xe3, 0xc0, 0x05, 0xa6, 0x19, 0x0e, 0xac, 0x22, 0xc1, 0x99, 0x10, 0x41, 0x15, 0x9a, 0x2a, 0xd1, 0xdb, 0x08, 0x96, 0x01, 0x5c, 0x4f, 0xf1, 0xd7, 0xb3, 0x54, 0x47, 0xcf, 0xc1, 0x0a, 0x24, 0xbe } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.4", + /* Message */ + 62, + { 0x0b, 0xb4, 0xab, 0xc7, 0xdc, 0x6c, 0xa4, 0x23, 0x5c, 0x29, 0xed, 0x0a, 0x2c, 0xb6, 0x3f, 0xd1, 0x41, 0x34, 0x1e, 0x2c, 0x4c, 0x90, 0x1e, 0x6d, 0xc9, 0x5d, 0xa9, 0xf0, 0x01, 0x0f, 0xa2, 0xe0, 0x22, 0xcc, 0xfe, 0x8a, 0xdf, 0xdb, 0x6e, 0xcf, 0x4d, 0x89, 0xf5, 0x79, 0xa1, 0x0a, 0x51, 0x70, 0xbe, 0x18, 0xc4, 0x6a, 0x24, 0x1c, 0xa7, 0xee, 0xd1, 0x07, 0xca, 0xfe, 0x4a, 0x9d } +, + /* Seed */ + 64, + { 0xbb, 0x80, 0xbe, 0x78, 0x02, 0xdd, 0x8b, 0xf5, 0xfb, 0x5b, 0x1b, 0x86, 0x39, 0x66, 0x54, 0xf4, 0x73, 0x9f, 0x5d, 0x43, 0x51, 0xf1, 0x9c, 0xe3, 0x1b, 0x72, 0xc2, 0x10, 0xae, 0xa1, 0xa2, 0xed, 0x21, 0x42, 0xd8, 0xd6, 0xf7, 0xae, 0x37, 0x4f, 0x06, 0x13, 0x3a, 0x31, 0x5c, 0x62, 0x64, 0xda, 0x65, 0xce, 0xf2, 0x33, 0xed, 0x3d, 0xcc, 0x81, 0x59, 0xd7, 0x6c, 0x3a, 0x17, 0xf3, 0x6d, 0x0c } +, + /* Encryption */ + 129, + { 0x00, 0x6f, 0x1b, 0x6c, 0x1f, 0xb3, 0x7a, 0xe5, 0xc8, 0xc0, 0x24, 0x44, 0x9a, 0xbc, 0x38, 0x40, 0xe8, 0xe5, 0x09, 0x71, 0x43, 0xee, 0xd1, 0x6b, 0xea, 0xf6, 0x7b, 0x6c, 0x7a, 0x48, 0x24, 0xac, 0x38, 0xb6, 0xf8, 0xc3, 0x53, 0xb6, 0x45, 0xc8, 0xce, 0xa4, 0xfa, 0xb0, 0x9c, 0x02, 0xfa, 0x6c, 0x32, 0x5a, 0x50, 0x74, 0x38, 0xb9, 0x64, 0x5e, 0xc8, 0x23, 0x00, 0x86, 0xb3, 0x15, 0xe3, 0x4e, 0x7a, 0x56, 0xad, 0xb0, 0xec, 0xd8, 0x9f, 0xd0, 0x7b, 0x98, 0x73, 0x9c, 0x24, 0xdb, 0x6f, 0xe1, 0x1f, 0xf2, 0xe5, 0xad, 0x38, 0x31, 0x8e, 0xc3, 0x1d, 0xf2, 0xed, 0x25, 0x08, 0xde, 0xbc, 0xa7, 0xa6, 0x7e, 0x24, 0x01, 0x96, 0xaa, 0x9a, 0xcd, 0x80, 0x32, 0x9f, 0x4c, 0x43, 0x43, 0xc1, 0x0b, 0x72, 0x69, 0x9f, 0x9d, 0x6b, 0x5b, 0xc2, 0x43, 0x99, 0x5b, 0x09, 0xc4, 0x6d, 0xd3, 0xd8, 0x03, 0xce } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.5", + /* Message */ + 15, + { 0xed, 0x26, 0xec, 0x20, 0x2d, 0x5e, 0x69, 0x74, 0x0d, 0xa3, 0x48, 0x84, 0x06, 0xbb, 0xbd } +, + /* Seed */ + 111, + { 0xf2, 0xfd, 0x08, 0xcc, 0x0d, 0xb9, 0xa5, 0x5a, 0xbf, 0xeb, 0xd9, 0x2e, 0x2a, 0x9d, 0x75, 0x87, 0x2a, 0xb7, 0xdf, 0xfb, 0x0b, 0x4d, 0xa1, 0x36, 0x06, 0xe1, 0x52, 0x75, 0x9f, 0x86, 0x6f, 0x22, 0xeb, 0x87, 0x29, 0xfb, 0x8c, 0x9a, 0x5c, 0x45, 0xba, 0x2f, 0x4a, 0xca, 0xe4, 0x31, 0x59, 0xa7, 0xad, 0x3c, 0xf7, 0x8e, 0x81, 0xfd, 0x09, 0x54, 0x90, 0x9b, 0x1f, 0x0e, 0x70, 0x89, 0xca, 0x86, 0xa4, 0x58, 0x8d, 0x8c, 0x87, 0xa1, 0xa6, 0x1f, 0x1a, 0x48, 0x39, 0x82, 0x36, 0xde, 0xf9, 0xb4, 0x97, 0x5e, 0x25, 0x49, 0x57, 0x3f, 0x60, 0xad, 0xb5, 0xe8, 0x61, 0xb7, 0xc3, 0xb2, 0xdf, 0xeb, 0x81, 0x0d, 0x13, 0xe2, 0x97, 0xa6, 0xcd, 0x3f, 0x2a, 0xfe, 0xcb, 0x0e, 0x4f, 0x14, 0x7c } +, + /* Encryption */ + 129, + { 0x00, 0x93, 0x3c, 0x58, 0xa5, 0x0c, 0x70, 0x15, 0x0d, 0xa0, 0x82, 0x3a, 0x7c, 0x1e, 0x36, 0x7d, 0x36, 0xe5, 0x21, 0x3f, 0x66, 0xa3, 0x00, 0x50, 0xfd, 0xed, 0x72, 0xd5, 0x75, 0x5b, 0x5f, 0x9c, 0x24, 0x05, 0x0b, 0x41, 0x14, 0xf5, 0x35, 0x09, 0x98, 0x8b, 0x62, 0x54, 0x20, 0xcf, 0xd0, 0x0a, 0xc1, 0xc8, 0xcd, 0x84, 0x48, 0x9c, 0xa2, 0x6b, 0x74, 0x3f, 0xb4, 0x7d, 0x1b, 0x64, 0xd0, 0xa8, 0x80, 0x8e, 0xe3, 0x21, 0x27, 0xc7, 0x71, 0x22, 0x4a, 0x0d, 0xd5, 0xa5, 0x64, 0xe6, 0x36, 0xad, 0xd7, 0x3b, 0xcf, 0xf7, 0xb4, 0x73, 0xe9, 0xa1, 0x2b, 0x7d, 0x46, 0x4d, 0x7d, 0xd4, 0xa7, 0x52, 0x04, 0x86, 0x61, 0xa8, 0xb0, 0x74, 0xb9, 0xfa, 0x15, 0x06, 0xfe, 0xf6, 0x03, 0xdd, 0x96, 0xd1, 0x19, 0x96, 0xa7, 0xd9, 0xe7, 0x48, 0x79, 0xf9, 0x9b, 0xb2, 0xd9, 0x1c, 0x37, 0xaa, 0xb1, 0x35, 0x72 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.6", + /* Message */ + 33, + { 0xdc, 0x28, 0x5a, 0x26, 0x39, 0x59, 0x39, 0xe7, 0x99, 0x72, 0x04, 0xc7, 0x1a, 0x93, 0x2f, 0x79, 0x5b, 0x4d, 0xe4, 0x01, 0xe9, 0x6f, 0x34, 0xe1, 0x89, 0x36, 0x32, 0x37, 0xe9, 0xcf, 0xda, 0xdc, 0x61 } +, + /* Seed */ + 93, + { 0xd8, 0x0b, 0xfc, 0xc2, 0x91, 0xce, 0x51, 0x8c, 0xe0, 0xbb, 0x6a, 0xe9, 0x34, 0xdf, 0xd8, 0x56, 0x58, 0xb2, 0x39, 0xfb, 0x45, 0x39, 0xcb, 0xe0, 0x5d, 0xa1, 0x26, 0xa8, 0x98, 0xb7, 0xf3, 0x64, 0x88, 0x7c, 0x0d, 0xdf, 0xb1, 0xea, 0xea, 0x1d, 0x5a, 0x90, 0xde, 0x76, 0x95, 0x66, 0x5c, 0x55, 0x82, 0x2a, 0x11, 0x72, 0xcb, 0x5b, 0xe8, 0xa1, 0x12, 0xd2, 0x8c, 0x86, 0x02, 0xc5, 0x13, 0xbe, 0x48, 0xc2, 0x92, 0xf0, 0x59, 0x72, 0xe6, 0x71, 0x1a, 0x44, 0xcb, 0xc7, 0x28, 0x17, 0x15, 0x09, 0x4b, 0x49, 0x0f, 0xde, 0x29, 0x16, 0x5a, 0x6b, 0x6b, 0x7d, 0x99, 0xdb, 0xed } +, + /* Encryption */ + 129, + { 0x01, 0x57, 0xe7, 0xb5, 0x4a, 0x34, 0x1b, 0x8d, 0xf8, 0xbd, 0x9b, 0x99, 0xfc, 0x2e, 0x6c, 0x58, 0xd8, 0x86, 0xfc, 0x79, 0xe7, 0x44, 0x2a, 0x9e, 0x76, 0xd0, 0xd6, 0x7e, 0x48, 0x58, 0xc4, 0xab, 0xf0, 0xed, 0x25, 0xc3, 0x3d, 0xf6, 0x2e, 0x2a, 0xad, 0xa3, 0x99, 0xdf, 0xea, 0xdc, 0x7f, 0xf6, 0x89, 0x28, 0xe6, 0xb9, 0x00, 0x71, 0x02, 0xdd, 0xf8, 0x09, 0xf5, 0x90, 0x8e, 0xef, 0xc1, 0x0f, 0x2a, 0x73, 0x71, 0x06, 0x09, 0x23, 0x1f, 0x5d, 0x45, 0xe0, 0x0a, 0xdd, 0xa1, 0x34, 0xb6, 0x02, 0xdd, 0x0e, 0xee, 0x0f, 0x67, 0x22, 0x49, 0x4b, 0x7e, 0x4f, 0x7b, 0x40, 0x57, 0x72, 0xc8, 0x31, 0xb6, 0x37, 0x29, 0xbe, 0x0f, 0x1c, 0x4b, 0x6d, 0x2a, 0x54, 0x2c, 0x15, 0x65, 0xc7, 0xdf, 0x23, 0x1d, 0x9e, 0x89, 0x2e, 0x58, 0x6a, 0x18, 0xec, 0x54, 0x37, 0x73, 0x76, 0xdb, 0x77, 0xf8, 0x13, 0x84 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.7", + /* Message */ + 55, + { 0x46, 0x47, 0xd8, 0x41, 0xc5, 0xa0, 0xb9, 0x97, 0x3a, 0x91, 0x45, 0x4d, 0xd1, 0xa0, 0x5e, 0xc0, 0xe5, 0x75, 0x03, 0xed, 0x99, 0x67, 0x2a, 0xc0, 0x02, 0xdf, 0xee, 0x77, 0x7f, 0x7f, 0xa5, 0x06, 0xfb, 0x41, 0xb2, 0xec, 0x8b, 0x8d, 0x2c, 0xdb, 0x9b, 0xef, 0x01, 0x33, 0xbd, 0x5e, 0x3a, 0x7d, 0x0c, 0x43, 0x44, 0xb2, 0x8f, 0xa8, 0xdb } +, + /* Seed */ + 71, + { 0xf5, 0x27, 0xa1, 0x4e, 0x2e, 0x06, 0xe7, 0x3f, 0x1c, 0x24, 0x5d, 0x19, 0x0d, 0x02, 0xcc, 0xed, 0x01, 0x1e, 0x46, 0x84, 0x87, 0xac, 0xfa, 0x5e, 0x0b, 0xce, 0x39, 0x78, 0x6b, 0x46, 0xa9, 0xa8, 0xc7, 0x51, 0xa8, 0xb4, 0x40, 0x6c, 0xcf, 0xa1, 0xfc, 0x5b, 0x7a, 0xb9, 0xba, 0xda, 0x7b, 0x4a, 0xd4, 0x52, 0x46, 0x7e, 0x50, 0xb7, 0xfc, 0x41, 0x31, 0x8e, 0xdc, 0x73, 0xdc, 0x2d, 0x84, 0xa2, 0x8a, 0x08, 0x1f, 0xa1, 0x79, 0x05, 0xbc } +, + /* Encryption */ + 129, + { 0x00, 0x4e, 0x03, 0xca, 0xa9, 0x48, 0x1d, 0x7f, 0x96, 0x78, 0x20, 0x7c, 0x17, 0xb6, 0x82, 0x2a, 0x5f, 0x69, 0x17, 0xed, 0x01, 0xeb, 0x40, 0x2e, 0x7f, 0x23, 0x01, 0x35, 0xa1, 0x23, 0xcd, 0x9b, 0x6d, 0xe3, 0xbe, 0xc3, 0xb9, 0xbf, 0x33, 0x8a, 0xde, 0xf8, 0x07, 0x6f, 0xb7, 0x65, 0x2f, 0xc7, 0xe3, 0xa3, 0x73, 0xfc, 0x16, 0x22, 0xf1, 0xdc, 0x67, 0x9d, 0x41, 0x5c, 0x32, 0x00, 0x02, 0x6d, 0x8a, 0x8a, 0x50, 0xf8, 0xdb, 0x6a, 0x58, 0x3f, 0x66, 0x69, 0x29, 0xd0, 0x31, 0x8e, 0xbf, 0x91, 0xd9, 0x59, 0x12, 0xfc, 0x06, 0x10, 0x2d, 0x9b, 0xe8, 0x75, 0x25, 0xa7, 0x36, 0xb5, 0xaf, 0x21, 0xe1, 0x6d, 0xe3, 0xef, 0xaa, 0x66, 0xe9, 0xcf, 0x41, 0xca, 0x73, 0x48, 0x23, 0x23, 0xdd, 0xe8, 0x0e, 0xec, 0x30, 0x85, 0x81, 0xa4, 0x4c, 0xa3, 0xaa, 0xbf, 0x76, 0xdd, 0x48, 0x1d, 0xe6, 0x52, 0x9a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.8", + /* Message */ + 8, + { 0xba, 0x10, 0xd4, 0x7a, 0x9f, 0x62, 0x42, 0x81 } +, + /* Seed */ + 118, + { 0x37, 0x9f, 0xdc, 0xfa, 0x5d, 0x8c, 0x61, 0x37, 0xc3, 0x6b, 0xad, 0x14, 0x3f, 0xd9, 0xb1, 0xf7, 0xe8, 0x94, 0xfa, 0x0e, 0x9a, 0xc0, 0xfb, 0x9c, 0xec, 0x60, 0xe8, 0x6c, 0x82, 0x53, 0x97, 0x5d, 0x8e, 0x78, 0x74, 0x21, 0x08, 0x49, 0x5e, 0x59, 0x4a, 0xd0, 0x89, 0x8f, 0xd0, 0x4c, 0x91, 0xe4, 0x01, 0xe7, 0xc8, 0x80, 0x89, 0xa8, 0x7b, 0x4a, 0x4a, 0x82, 0xe8, 0x34, 0xcd, 0x37, 0x77, 0xa7, 0xd3, 0xf8, 0x0e, 0x64, 0x86, 0x81, 0x2d, 0x4a, 0xb0, 0xd3, 0x37, 0x23, 0x16, 0x2b, 0xcb, 0xc7, 0xe0, 0x81, 0xa9, 0x9d, 0x3f, 0x9b, 0x5c, 0x3b, 0xa4, 0x4b, 0x19, 0xbd, 0xf8, 0x84, 0xa4, 0x62, 0x6f, 0xd7, 0xde, 0xf7, 0x67, 0x40, 0x57, 0xbe, 0xa0, 0x82, 0xe0, 0x0d, 0xb4, 0xb7, 0x61, 0xad, 0x75, 0x3a, 0xb5, 0x98, 0x5a, 0x94 } +, + /* Encryption */ + 129, + { 0x00, 0xc4, 0x96, 0x5e, 0x29, 0x63, 0xd7, 0xbc, 0x5b, 0x10, 0x44, 0xd8, 0xfc, 0x75, 0xeb, 0x33, 0x82, 0xce, 0xdd, 0x99, 0x07, 0x41, 0x97, 0x92, 0xef, 0xc8, 0x8c, 0x92, 0xb1, 0xd5, 0xc3, 0x90, 0xfa, 0xb1, 0x90, 0x01, 0x1c, 0x51, 0x8a, 0xc9, 0xce, 0x45, 0xc1, 0xb8, 0xe7, 0x27, 0x6b, 0xff, 0xc7, 0xc7, 0xe0, 0x5c, 0x25, 0x37, 0x08, 0x91, 0x37, 0xa9, 0x8d, 0xf6, 0xe0, 0xc6, 0x92, 0x02, 0x0e, 0xd6, 0x54, 0xaf, 0x83, 0x33, 0x9b, 0xab, 0x11, 0x92, 0x71, 0x77, 0xf2, 0xf5, 0x23, 0x22, 0x6b, 0x4f, 0xe6, 0x4b, 0x99, 0xc1, 0x72, 0x9f, 0x6c, 0x92, 0x29, 0x06, 0xbc, 0x16, 0xd3, 0x1f, 0x0c, 0x94, 0xdc, 0x2e, 0xa4, 0x13, 0x81, 0x0d, 0x55, 0x94, 0x0c, 0x97, 0xaf, 0xdd, 0x48, 0x29, 0xfb, 0xf1, 0x61, 0x8a, 0x8c, 0x9d, 0xe8, 0x9d, 0xc2, 0x40, 0x06, 0xe7, 0xe4, 0x21, 0xa5, 0x8d, 0x38 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.9", + /* Message */ + 38, + { 0xef, 0xc7, 0x48, 0x9f, 0xec, 0x77, 0x9e, 0x05, 0x2e, 0x37, 0x9c, 0x1a, 0xd9, 0x04, 0x59, 0x03, 0xb6, 0x84, 0x2a, 0x9c, 0xa4, 0x1b, 0x48, 0xbd, 0xdc, 0xe5, 0x80, 0x80, 0xa5, 0xed, 0xec, 0x63, 0xf3, 0x6e, 0xe1, 0x15, 0x60, 0xfd } +, + /* Seed */ + 88, + { 0xc8, 0xec, 0xba, 0x62, 0x72, 0x14, 0xc4, 0x14, 0xd7, 0xc3, 0xfd, 0xd3, 0x16, 0xc2, 0xd8, 0x2a, 0x98, 0x53, 0x57, 0x28, 0xb9, 0xa9, 0x37, 0x6f, 0x69, 0xa9, 0x53, 0xd7, 0xcd, 0x1c, 0xea, 0xd7, 0x10, 0x53, 0xdb, 0xe0, 0x14, 0x0c, 0x7f, 0x02, 0xbd, 0x71, 0xe0, 0x13, 0x7f, 0xea, 0x29, 0xcd, 0x4c, 0x21, 0xa5, 0x8b, 0xde, 0xc6, 0x66, 0x40, 0x99, 0x0d, 0x28, 0xc1, 0x0b, 0x70, 0x17, 0x59, 0x3c, 0x1d, 0x11, 0xfe, 0x9a, 0xbe, 0xbd, 0x71, 0x24, 0xe1, 0xd9, 0x85, 0x63, 0x1e, 0x94, 0xe9, 0xe5, 0x12, 0x41, 0x26, 0x0f, 0x9e, 0xf1, 0xf1 } +, + /* Encryption */ + 129, + { 0x00, 0x32, 0x18, 0x4e, 0xf2, 0x88, 0xfa, 0x0a, 0xaa, 0x0c, 0x2c, 0x1a, 0x19, 0xe7, 0xc2, 0x9f, 0x81, 0xc7, 0x01, 0x2f, 0x45, 0x29, 0xeb, 0x9e, 0xeb, 0x53, 0x68, 0x1f, 0x62, 0x47, 0xf8, 0xd4, 0x35, 0x69, 0x13, 0x45, 0xa5, 0x14, 0x8a, 0x2c, 0x87, 0x7b, 0x2b, 0x18, 0x92, 0x6b, 0xae, 0x9d, 0xe5, 0xb3, 0x17, 0xba, 0xc0, 0xe9, 0x02, 0xc9, 0x60, 0x25, 0xee, 0xc2, 0xf9, 0xea, 0xbd, 0x0f, 0x9e, 0x88, 0x86, 0xef, 0x95, 0x19, 0xc8, 0x24, 0x9f, 0xeb, 0x83, 0x46, 0x65, 0xc1, 0x01, 0x0d, 0xb7, 0x62, 0x4f, 0x48, 0x7e, 0x16, 0x1f, 0x89, 0xf6, 0xae, 0x00, 0x18, 0xc1, 0xf4, 0xe0, 0xab, 0x54, 0x72, 0xf7, 0xf0, 0x99, 0x35, 0x61, 0xcd, 0x59, 0x85, 0xf3, 0x83, 0xd0, 0x49, 0xdd, 0x83, 0x2b, 0x82, 0xc8, 0x37, 0x48, 0xb2, 0x28, 0x1b, 0xfb, 0x99, 0xd9, 0xd5, 0x00, 0x8d, 0xc8, 0x07, 0xde } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.10", + /* Message */ + 19, + { 0x5b, 0x26, 0x4f, 0xf8, 0x8d, 0xef, 0xd3, 0xc2, 0x99, 0x99, 0x3d, 0x81, 0x12, 0x9a, 0x6e, 0x5d, 0xd2, 0xb5, 0x7b } +, + /* Seed */ + 107, + { 0x0b, 0xe7, 0xab, 0x5b, 0x29, 0x70, 0x48, 0x43, 0xc1, 0xc0, 0xd7, 0xe4, 0xef, 0x5e, 0x93, 0xf3, 0xba, 0x71, 0x7d, 0xb7, 0x81, 0x5a, 0xf5, 0x72, 0xe3, 0xa9, 0xab, 0x3f, 0x99, 0xb1, 0xac, 0x9a, 0x22, 0xb9, 0x2d, 0x9b, 0x43, 0xda, 0x2b, 0x99, 0x65, 0xc7, 0x97, 0x70, 0x57, 0x17, 0x3c, 0x03, 0x57, 0x3f, 0x32, 0x48, 0x0a, 0x92, 0x70, 0x19, 0xaf, 0xff, 0x0e, 0x0e, 0x34, 0xe4, 0x09, 0x5e, 0x4a, 0x4d, 0x39, 0x2d, 0xcd, 0x1b, 0xd9, 0xf2, 0x7d, 0x32, 0xfd, 0xe7, 0x15, 0x9f, 0x02, 0x3c, 0x83, 0x08, 0x9e, 0x88, 0xa7, 0x1f, 0x24, 0x33, 0x64, 0x8e, 0xf8, 0xc8, 0x40, 0x45, 0xb9, 0xc3, 0x6d, 0x8e, 0x5f, 0x6e, 0xff, 0x03, 0x4b, 0x91, 0xb7, 0x02, 0x34 } +, + /* Encryption */ + 129, + { 0x00, 0x4c, 0x65, 0x29, 0x35, 0x56, 0xf2, 0xfd, 0x15, 0xab, 0x90, 0xeb, 0x22, 0xe0, 0x75, 0x33, 0xb3, 0xdc, 0x17, 0x33, 0x4f, 0x5e, 0xed, 0x27, 0xa3, 0x99, 0x31, 0x80, 0xc5, 0x6c, 0x8e, 0x3d, 0x8f, 0x51, 0xee, 0xb2, 0x75, 0x95, 0xf8, 0x78, 0xd2, 0x36, 0x65, 0xba, 0x3a, 0xb0, 0xe7, 0x28, 0xa5, 0xae, 0xf7, 0x23, 0x4f, 0x60, 0x36, 0xb0, 0x23, 0xf8, 0x71, 0xc2, 0xd6, 0x55, 0x2a, 0x18, 0xad, 0x5a, 0x25, 0xbe, 0xc5, 0x5b, 0xc7, 0x6b, 0xee, 0x63, 0x83, 0x46, 0x12, 0x81, 0xd3, 0x9a, 0x30, 0xf6, 0xd6, 0x60, 0x92, 0xe0, 0xcf, 0xf6, 0x92, 0x32, 0x68, 0xfc, 0x04, 0x3c, 0xdf, 0x74, 0x7e, 0x8d, 0x54, 0x89, 0x50, 0x4e, 0x7d, 0xb3, 0x0a, 0x7b, 0xd9, 0x1a, 0x2b, 0xfc, 0x6c, 0x1b, 0x34, 0x14, 0x40, 0x57, 0x01, 0x75, 0x3d, 0x5b, 0x85, 0xff, 0x73, 0x52, 0x01, 0x2d, 0x55, 0xe9, 0x23 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.11", + /* Message */ + 37, + { 0x72, 0xe2, 0x09, 0x00, 0xe5, 0xbc, 0xc2, 0x3c, 0xf8, 0x79, 0xed, 0x35, 0x31, 0x88, 0x9a, 0x1e, 0xd5, 0xaa, 0x3d, 0x5c, 0x79, 0x2e, 0x34, 0xe3, 0xb1, 0x26, 0x90, 0xd9, 0xac, 0x24, 0x03, 0xd0, 0xf6, 0xf7, 0x8f, 0x59, 0x23 } +, + /* Seed */ + 89, + { 0x11, 0x62, 0x75, 0xe9, 0xbe, 0x1b, 0xd4, 0xe6, 0xf2, 0x03, 0xff, 0xe4, 0xf0, 0xab, 0x9a, 0x32, 0x73, 0x84, 0x10, 0xe9, 0x23, 0xe8, 0x39, 0x71, 0xee, 0x9a, 0x6b, 0x99, 0x2c, 0x65, 0x0a, 0x03, 0x1f, 0x94, 0x0f, 0x6e, 0xf3, 0x3d, 0x61, 0x50, 0xdf, 0xf8, 0xb3, 0x9d, 0xcf, 0x22, 0x50, 0xd5, 0x66, 0x5c, 0x04, 0x27, 0x3b, 0x2b, 0xe2, 0xde, 0xc9, 0x97, 0x12, 0xbb, 0xc0, 0x12, 0xf7, 0x5a, 0x31, 0xb3, 0x0b, 0xa0, 0x6f, 0xf9, 0xeb, 0xe3, 0xb8, 0x9f, 0x58, 0xa6, 0x8f, 0x26, 0x85, 0xe3, 0x38, 0xff, 0x6c, 0xb8, 0xd4, 0x18, 0x1a, 0x8a, 0x14 } +, + /* Encryption */ + 129, + { 0x00, 0x21, 0x4a, 0x83, 0xbe, 0x45, 0x3a, 0x75, 0xbc, 0xda, 0x94, 0x33, 0xa7, 0xb9, 0x51, 0x43, 0x34, 0x39, 0x98, 0x30, 0x72, 0x07, 0x1c, 0xc8, 0x21, 0x12, 0xb7, 0x77, 0x42, 0xbe, 0x0c, 0x38, 0x22, 0x6c, 0xa3, 0xc6, 0xf3, 0x8d, 0x55, 0xb9, 0xca, 0x3f, 0x08, 0xc8, 0x79, 0x37, 0x89, 0x79, 0x6e, 0x6c, 0xde, 0x67, 0x37, 0x6d, 0x67, 0x3f, 0x5e, 0xc5, 0x7d, 0xac, 0xc3, 0x74, 0xc4, 0xc3, 0x17, 0x34, 0x44, 0xdd, 0x8a, 0x63, 0x76, 0xde, 0x8f, 0x9d, 0xdc, 0x31, 0xa4, 0xc0, 0x60, 0xd7, 0x72, 0xf0, 0x2e, 0xb7, 0x49, 0x51, 0x2d, 0xcd, 0x04, 0x02, 0x31, 0x17, 0x5d, 0x0b, 0x69, 0x42, 0xa9, 0x47, 0xb2, 0xc8, 0x2f, 0x7c, 0x19, 0xe2, 0xce, 0x87, 0x50, 0x00, 0xaf, 0x84, 0x27, 0x4c, 0xbe, 0x2a, 0xdb, 0xf2, 0xfb, 0xfb, 0x53, 0x7c, 0xcb, 0xe2, 0xfb, 0xd0, 0x72, 0x87, 0x13, 0x78, 0x75 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.12", + /* Message */ + 21, + { 0x16, 0xb1, 0x10, 0xe2, 0x90, 0x9b, 0x11, 0xb0, 0xcf, 0x36, 0xb0, 0x52, 0xc6, 0xf3, 0x93, 0x6a, 0x2c, 0xa1, 0x3f, 0xc3, 0xa5 } +, + /* Seed */ + 105, + { 0xc2, 0xbf, 0x9e, 0x4f, 0xb1, 0xed, 0x70, 0xca, 0x21, 0x2d, 0x15, 0xee, 0x8e, 0xb3, 0xcd, 0x66, 0x0e, 0xb6, 0x5c, 0x52, 0x78, 0xe0, 0x3a, 0x3b, 0x10, 0xeb, 0x12, 0xb2, 0x53, 0x34, 0xa4, 0x72, 0x8b, 0x94, 0x99, 0x20, 0x12, 0x2f, 0xb9, 0x92, 0xbf, 0x2c, 0xe4, 0x30, 0x10, 0x3d, 0x74, 0xab, 0x74, 0xe6, 0xd6, 0xe7, 0x62, 0xb8, 0x5d, 0x6e, 0xf9, 0xbe, 0xb7, 0xd7, 0x25, 0x98, 0xf2, 0x93, 0xa4, 0x35, 0x62, 0xe9, 0x06, 0x89, 0x54, 0x11, 0x11, 0x51, 0x1d, 0x31, 0x4a, 0x9c, 0x46, 0x02, 0x23, 0x76, 0xad, 0x05, 0x5d, 0x54, 0xce, 0xd6, 0xac, 0x1f, 0x36, 0xe9, 0x8c, 0x2b, 0x25, 0xa0, 0xac, 0xde, 0x64, 0xdc, 0xf6, 0x52, 0x2c, 0x3d, 0x22 } +, + /* Encryption */ + 129, + { 0x01, 0x6a, 0xa9, 0x5a, 0x08, 0x23, 0x82, 0xc1, 0x0c, 0x04, 0x53, 0x10, 0xfe, 0xfe, 0xcc, 0x8d, 0x17, 0xdb, 0xf2, 0x16, 0xd8, 0xed, 0xc0, 0x4b, 0xda, 0xcd, 0x4f, 0x52, 0x4d, 0xe4, 0x85, 0xb7, 0xfe, 0x8a, 0x26, 0xf1, 0x4c, 0xab, 0xd2, 0x97, 0xe7, 0xf0, 0x3b, 0x3c, 0x85, 0x08, 0x6a, 0x16, 0x14, 0x7d, 0x5f, 0x61, 0x93, 0x91, 0x9b, 0xb9, 0x5a, 0x53, 0xc1, 0x46, 0xc7, 0x84, 0xc0, 0x0b, 0x53, 0x32, 0xe0, 0x18, 0xf6, 0x43, 0xcf, 0x95, 0x87, 0x24, 0xcd, 0x08, 0x07, 0x5e, 0xb6, 0x4c, 0xa5, 0x68, 0x0c, 0x27, 0xc7, 0x05, 0xd4, 0x0d, 0x88, 0xb9, 0xd7, 0xf4, 0x26, 0xb7, 0x36, 0xe3, 0xc5, 0xf6, 0x39, 0x4e, 0xa6, 0x83, 0xb6, 0x5c, 0x23, 0x73, 0xa6, 0xfc, 0xeb, 0x14, 0xf2, 0xea, 0x85, 0x1c, 0xa8, 0xe0, 0x00, 0xe2, 0x4d, 0xc8, 0xf7, 0xe7, 0xc8, 0x1b, 0x1d, 0x4e, 0x72, 0x0c, 0x36 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.13", + /* Message */ + 17, + { 0x3c, 0x86, 0x0a, 0x28, 0xfa, 0xe8, 0xda, 0x2a, 0xc0, 0xd9, 0xa3, 0x39, 0x89, 0x97, 0x7f, 0xfa, 0x04 } +, + /* Seed */ + 109, + { 0x7c, 0x96, 0x99, 0x90, 0x6c, 0x9f, 0x16, 0x65, 0x12, 0x5c, 0x0b, 0x10, 0x67, 0x3f, 0x3d, 0xad, 0x98, 0xc9, 0x1a, 0x4f, 0xf0, 0xfa, 0xaa, 0x64, 0x7d, 0xb5, 0x54, 0xfd, 0x62, 0x27, 0xef, 0x50, 0x90, 0x9c, 0x97, 0xb7, 0x06, 0x09, 0x2b, 0xe2, 0x10, 0xdb, 0x2c, 0x24, 0xba, 0x9e, 0x8e, 0x6a, 0x87, 0xf9, 0xdd, 0xd9, 0xf3, 0xf4, 0x91, 0x29, 0x10, 0x29, 0xac, 0x6e, 0xe4, 0x6e, 0x08, 0xd0, 0xd7, 0xa5, 0x3c, 0x46, 0x2d, 0xb4, 0xf0, 0xfd, 0x1c, 0xc2, 0x3e, 0xc8, 0xf5, 0x5e, 0xda, 0x07, 0xf4, 0xca, 0x0d, 0x3e, 0x3c, 0xd3, 0x76, 0x22, 0x85, 0x5b, 0x4d, 0xb0, 0x8f, 0x64, 0xbe, 0x3e, 0x26, 0xc3, 0xe9, 0x78, 0x75, 0x17, 0x12, 0x94, 0xea, 0xdf, 0x86, 0xfc, 0xd6 } +, + /* Encryption */ + 129, + { 0x01, 0x0c, 0x1e, 0x04, 0xa8, 0x58, 0xc6, 0x15, 0xee, 0x96, 0x95, 0xf6, 0x4a, 0xb2, 0xdb, 0x99, 0x80, 0x6d, 0xa4, 0x82, 0xd2, 0xb4, 0x60, 0x29, 0x3c, 0x46, 0xdc, 0x7b, 0x71, 0x7a, 0x59, 0x76, 0xa3, 0xc7, 0xe3, 0x6d, 0x8d, 0x47, 0xa8, 0x4a, 0x34, 0xd6, 0x3c, 0xdf, 0xca, 0x2c, 0x1e, 0x38, 0x45, 0x25, 0x73, 0xed, 0x44, 0xc3, 0xa0, 0x40, 0x40, 0x5e, 0xcf, 0x3f, 0xbf, 0x36, 0x83, 0x41, 0xc4, 0xa1, 0xfc, 0x90, 0x83, 0xa8, 0xf5, 0x52, 0x93, 0x67, 0xb9, 0x9c, 0xb8, 0x9f, 0xc5, 0xa0, 0x8b, 0x8f, 0x34, 0x75, 0xa0, 0xd5, 0x5e, 0x3e, 0x42, 0xcc, 0xcb, 0xeb, 0x20, 0xd0, 0x4a, 0x19, 0x97, 0xee, 0xda, 0x4e, 0x3c, 0xc9, 0xe9, 0x92, 0xd2, 0x37, 0xec, 0x7d, 0x32, 0xfe, 0x25, 0x84, 0x5a, 0xb0, 0x24, 0xd5, 0x88, 0x28, 0x05, 0xed, 0x52, 0xf1, 0x0e, 0xd7, 0xd2, 0x5d, 0x62, 0xd0, 0xaf } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.14", + /* Message */ + 30, + { 0x4e, 0xdf, 0x4a, 0xd3, 0x44, 0x0f, 0x17, 0xb1, 0x0d, 0x26, 0xaf, 0xcd, 0xf4, 0xe4, 0x44, 0xd2, 0xaa, 0x61, 0xa1, 0x97, 0x55, 0xa6, 0x21, 0x07, 0x98, 0x3f, 0x01, 0x22, 0xfb, 0x2a } +, + /* Seed */ + 96, + { 0xe0, 0x20, 0x09, 0x39, 0x39, 0xb4, 0x18, 0x9e, 0x93, 0x4c, 0xb6, 0x2d, 0x27, 0xca, 0x5e, 0x97, 0x19, 0x65, 0x2c, 0x13, 0x7f, 0xc4, 0x9e, 0x72, 0x1c, 0x4a, 0xb9, 0xe9, 0xf3, 0x98, 0xb0, 0xa6, 0x12, 0xde, 0x8a, 0x8a, 0x89, 0x99, 0xaf, 0x0d, 0xbc, 0x1c, 0xea, 0x0b, 0x61, 0x63, 0xda, 0x42, 0x61, 0x23, 0x28, 0x14, 0xed, 0x92, 0xeb, 0x21, 0x60, 0xcf, 0x4b, 0x26, 0xd0, 0x55, 0x1b, 0x1b, 0xdd, 0x91, 0x9d, 0x49, 0x47, 0x93, 0x78, 0x6e, 0x1b, 0x86, 0xf7, 0x9d, 0x64, 0x16, 0x61, 0x2a, 0x28, 0x22, 0x61, 0x36, 0x3d, 0x6c, 0x9b, 0x7a, 0x0d, 0x92, 0xad, 0x17, 0x58, 0xea, 0xad, 0x51 } +, + /* Encryption */ + 129, + { 0x00, 0x8c, 0xf9, 0xb3, 0xf3, 0xe7, 0x60, 0x90, 0xd1, 0x01, 0x17, 0x4e, 0xcd, 0x97, 0xd1, 0x0b, 0xff, 0x6d, 0xe4, 0xd4, 0x64, 0x40, 0x00, 0x3f, 0xc0, 0xd4, 0x28, 0xf1, 0x9b, 0x85, 0x58, 0xf3, 0x13, 0x74, 0xa5, 0xfa, 0x28, 0x3d, 0x03, 0xd4, 0xdd, 0x43, 0xf9, 0x3a, 0x4d, 0x9f, 0x14, 0xca, 0x00, 0x68, 0xdc, 0x2c, 0xf3, 0xe2, 0x54, 0x37, 0xb0, 0x5a, 0xb1, 0xd4, 0x06, 0x21, 0xee, 0xbd, 0x84, 0x16, 0xf5, 0x82, 0x8a, 0xe7, 0xc6, 0xcf, 0xd2, 0x97, 0xb4, 0x51, 0x8f, 0x79, 0x94, 0x2b, 0x91, 0x43, 0x23, 0x28, 0x4e, 0x29, 0x76, 0xa5, 0x4d, 0x3c, 0xd9, 0x11, 0x63, 0x3a, 0x30, 0x7e, 0xda, 0xf1, 0xed, 0xb6, 0x74, 0x98, 0x46, 0x6b, 0x3e, 0x98, 0x91, 0x6f, 0x99, 0x04, 0xf4, 0xa0, 0xea, 0x9b, 0x87, 0xa9, 0x83, 0x44, 0xf0, 0x73, 0x83, 0x3e, 0xdf, 0x9b, 0x2b, 0x53, 0x94, 0xcf, 0xd7 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.15", + /* Message */ + 22, + { 0x8a, 0x6d, 0x53, 0xb0, 0xad, 0xa1, 0x85, 0x4e, 0x23, 0x13, 0x69, 0x1a, 0xab, 0x23, 0x06, 0x3d, 0xe1, 0x31, 0xbc, 0x36, 0xc7, 0x64 } +, + /* Seed */ + 104, + { 0x26, 0x85, 0x45, 0x8a, 0xeb, 0xfb, 0xd6, 0x07, 0x4e, 0xbe, 0xb0, 0xfc, 0x0c, 0xc4, 0x92, 0x1c, 0x27, 0x3e, 0x8c, 0x0a, 0x88, 0x15, 0x51, 0x50, 0x2e, 0x4c, 0x29, 0x9f, 0x33, 0x4d, 0xd5, 0x67, 0xf5, 0x16, 0x75, 0xb0, 0xff, 0x30, 0xf2, 0xc4, 0x82, 0x63, 0x20, 0x03, 0x64, 0x99, 0x66, 0x99, 0xf9, 0xb1, 0x72, 0xaf, 0xfe, 0xc0, 0xe7, 0x9e, 0x5c, 0x52, 0x3d, 0x1e, 0x77, 0x9e, 0xc0, 0x6d, 0xec, 0xd4, 0x76, 0xa5, 0x74, 0x30, 0x78, 0x1e, 0x2d, 0xc8, 0x1f, 0x25, 0xd6, 0x0d, 0x3a, 0x73, 0x97, 0x65, 0x79, 0xa2, 0xf0, 0x1f, 0x07, 0x58, 0x4c, 0xf8, 0xe5, 0xfb, 0x3e, 0xbd, 0x8d, 0x5a, 0x93, 0x2d, 0x57, 0xaa, 0x8a, 0x18, 0x0a, 0xaa } +, + /* Encryption */ + 129, + { 0x01, 0x3a, 0x3d, 0x32, 0xee, 0xc7, 0x35, 0xeb, 0xda, 0x13, 0xf8, 0xbe, 0x76, 0x02, 0xa0, 0x47, 0x5c, 0xf3, 0xcf, 0x28, 0x5b, 0x42, 0x86, 0xad, 0x93, 0xd6, 0x12, 0xc3, 0xad, 0x91, 0x72, 0x48, 0x80, 0x9d, 0x1c, 0x4c, 0x18, 0x0b, 0x36, 0x70, 0x15, 0xcc, 0x66, 0xc4, 0xd8, 0xe7, 0x86, 0x73, 0x84, 0x16, 0x8c, 0xf4, 0xcb, 0x71, 0x9b, 0xd5, 0x93, 0x35, 0x53, 0x55, 0xcd, 0xd7, 0xd7, 0x53, 0x0c, 0x80, 0xc8, 0x67, 0x74, 0x5f, 0x96, 0x61, 0xc6, 0xc3, 0x3b, 0xcb, 0x97, 0xf2, 0xcf, 0x75, 0xa4, 0xc2, 0x7c, 0x3c, 0xbb, 0xdb, 0xbe, 0x7e, 0xaf, 0x4f, 0x82, 0x34, 0xf2, 0x12, 0xe3, 0x05, 0x82, 0x56, 0xd4, 0x43, 0x9a, 0x9f, 0x97, 0x81, 0xdf, 0x48, 0xef, 0xdb, 0x02, 0x35, 0x68, 0xf9, 0x4a, 0xe4, 0x59, 0x46, 0x54, 0xa0, 0xf9, 0xba, 0xf6, 0xea, 0x30, 0xb7, 0xd8, 0xd9, 0x48, 0x0a, 0xd3 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.16", + /* Message */ + 17, + { 0x20, 0xf0, 0x20, 0x44, 0xe6, 0x3a, 0xc9, 0x2e, 0xb9, 0xfa, 0xf1, 0xa0, 0xce, 0x35, 0xba, 0x72, 0x09 } +, + /* Seed */ + 109, + { 0x2d, 0xe1, 0xfc, 0xc1, 0x17, 0xf8, 0x21, 0xf1, 0xde, 0xa7, 0x94, 0xb5, 0xee, 0xb3, 0x13, 0xf4, 0x29, 0xe0, 0x0b, 0x97, 0x6b, 0x53, 0x41, 0x9d, 0x3d, 0x03, 0xec, 0xaa, 0x1b, 0x50, 0x76, 0x88, 0x77, 0xe8, 0xb7, 0xfb, 0xd6, 0xc3, 0x63, 0x04, 0x7e, 0x15, 0xc2, 0x55, 0x79, 0x3b, 0x3c, 0xbe, 0x0f, 0x58, 0x84, 0xf0, 0xa5, 0x11, 0x25, 0x4d, 0x31, 0xbf, 0xb2, 0x37, 0x41, 0x02, 0x3c, 0x1f, 0x88, 0x1f, 0xe0, 0x16, 0xa1, 0x2e, 0xef, 0x1b, 0x8a, 0xf2, 0x2b, 0x93, 0x68, 0x20, 0x7e, 0x7b, 0x16, 0x39, 0xf7, 0x27, 0x1d, 0xeb, 0xe3, 0xc8, 0xdf, 0x52, 0x93, 0xee, 0xc3, 0xa0, 0x32, 0xf1, 0xce, 0x55, 0x9c, 0x0a, 0x04, 0x77, 0x1b, 0xbf, 0x88, 0x98, 0x94, 0x7c, 0xa4 } +, + /* Encryption */ + 129, + { 0x01, 0x70, 0x06, 0xe8, 0x6f, 0x6c, 0x58, 0x58, 0xfe, 0x5a, 0xde, 0x0d, 0xcb, 0xfa, 0x9c, 0xcd, 0x11, 0xc0, 0x2d, 0x4e, 0x7d, 0x0d, 0xe6, 0xc1, 0x58, 0xad, 0xf9, 0xee, 0xf1, 0x01, 0x07, 0xe7, 0xa4, 0xc3, 0x6b, 0xd3, 0xd9, 0x29, 0xea, 0x6a, 0x47, 0x6e, 0xcf, 0xa0, 0xb6, 0xec, 0xd0, 0x51, 0x49, 0xb5, 0x12, 0x15, 0x95, 0x48, 0x93, 0xa1, 0xab, 0x26, 0x69, 0xc0, 0x42, 0xda, 0x83, 0xe8, 0xc8, 0x18, 0xb0, 0x0a, 0xe7, 0x34, 0xde, 0x5f, 0x9e, 0x0b, 0x97, 0xba, 0x1f, 0xe3, 0xe9, 0xc4, 0x6a, 0xe9, 0x81, 0x6b, 0x63, 0xb1, 0x5c, 0x2d, 0xcc, 0x61, 0xcb, 0x3b, 0x8b, 0x2c, 0x23, 0xdd, 0xb9, 0x9f, 0xcd, 0x54, 0xe9, 0x55, 0x60, 0x91, 0x8b, 0x9a, 0x0f, 0xa3, 0xc4, 0xb6, 0x27, 0x3d, 0x1b, 0x28, 0xa2, 0x13, 0xe1, 0x20, 0xb4, 0xf2, 0x42, 0x86, 0x96, 0x5e, 0xbe, 0xe9, 0x4f, 0xf8, 0x96 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.17", + /* Message */ + 3, + { 0xd3, 0x88, 0x3b } +, + /* Seed */ + 123, + { 0x5c, 0xa3, 0xbb, 0xf9, 0x92, 0xd7, 0xae, 0x35, 0x94, 0xc6, 0x05, 0xc3, 0x9c, 0x3e, 0x97, 0x90, 0x25, 0xcc, 0xb0, 0xa3, 0x5c, 0x6e, 0xf0, 0xfa, 0x57, 0x4a, 0x98, 0xbe, 0x05, 0xef, 0x7c, 0x32, 0x8a, 0x19, 0xa2, 0x77, 0x5b, 0xa0, 0x6f, 0x2d, 0xd1, 0xe0, 0xff, 0x6f, 0x0f, 0x1f, 0x6a, 0x3b, 0x20, 0xfb, 0xda, 0x21, 0x62, 0xd0, 0x92, 0x4f, 0xf5, 0x5b, 0x70, 0xeb, 0xfe, 0x2b, 0x16, 0xd4, 0xff, 0x6a, 0xef, 0x8d, 0x47, 0xeb, 0xe5, 0x96, 0x38, 0xe5, 0x81, 0x0f, 0xfd, 0xb5, 0x8d, 0xb0, 0x5f, 0x4d, 0x9b, 0x4a, 0x3a, 0x42, 0x3f, 0x96, 0x7f, 0xe5, 0x79, 0xf8, 0x73, 0x78, 0x36, 0x9d, 0x5c, 0x5c, 0x07, 0xe5, 0xe3, 0xcb, 0x5d, 0xdd, 0xf3, 0x89, 0x62, 0x11, 0x80, 0x27, 0x0a, 0x21, 0xe0, 0x10, 0x78, 0xc8, 0x9a, 0xfb, 0xab, 0x18, 0x9e, 0x87, 0xf7 } +, + /* Encryption */ + 129, + { 0x01, 0x6f, 0x55, 0x05, 0xf7, 0x4f, 0xf1, 0x10, 0x4d, 0xa1, 0xf8, 0xa5, 0x2e, 0x50, 0xbf, 0xe2, 0x9c, 0x99, 0x87, 0x10, 0xc5, 0x7d, 0xe4, 0x40, 0x98, 0xa9, 0x57, 0x9e, 0x7a, 0x33, 0x13, 0xb6, 0x29, 0x60, 0x31, 0x02, 0xf0, 0x8d, 0x2d, 0x91, 0x1f, 0x91, 0x7a, 0x9c, 0x96, 0x62, 0x60, 0x8c, 0x97, 0xa1, 0xea, 0x37, 0x17, 0x34, 0xf6, 0x7c, 0xbf, 0x70, 0x03, 0xd9, 0x3c, 0x4c, 0x31, 0x4c, 0x3a, 0x0e, 0x77, 0xf3, 0x65, 0x8f, 0xa4, 0xd0, 0x72, 0x25, 0x62, 0xc4, 0xe1, 0x3e, 0x85, 0xa7, 0xc8, 0xd0, 0xd9, 0xd4, 0xfb, 0xf7, 0x12, 0x58, 0x84, 0xba, 0x62, 0xad, 0x28, 0x59, 0xb4, 0xd9, 0x61, 0x36, 0xf7, 0xa2, 0x45, 0x54, 0x69, 0xce, 0xb6, 0x0b, 0x63, 0xba, 0x84, 0x74, 0xe6, 0x16, 0x0c, 0x83, 0x17, 0x92, 0x1a, 0x07, 0xb4, 0xb6, 0x43, 0x6f, 0x37, 0x6c, 0x5f, 0x98, 0x25, 0x7b, 0x17 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.18", + /* Message */ + 11, + { 0x06, 0xa2, 0xae, 0x82, 0xa4, 0x85, 0x32, 0x07, 0xc9, 0xf9, 0x75 } +, + /* Seed */ + 115, + { 0xe2, 0xc3, 0x36, 0x33, 0xd5, 0x47, 0x54, 0xad, 0xdd, 0x24, 0xc8, 0x5c, 0x32, 0xd2, 0x8a, 0xd8, 0x70, 0xf1, 0x60, 0x3d, 0x44, 0x44, 0x60, 0xa0, 0x3a, 0xac, 0xad, 0x7d, 0xcb, 0x80, 0x96, 0x01, 0x56, 0xbb, 0xb2, 0x59, 0xca, 0xd3, 0x46, 0xbe, 0x90, 0xc0, 0xd4, 0xf3, 0xfb, 0x18, 0xac, 0x6e, 0x9d, 0x5a, 0x9a, 0xe2, 0xa5, 0xab, 0x98, 0xa1, 0xf8, 0x4b, 0x8e, 0x70, 0xc7, 0x1d, 0x0c, 0xcc, 0x0a, 0x1a, 0x2a, 0xa3, 0x99, 0x70, 0xd9, 0xc8, 0x3b, 0x4b, 0x0c, 0x25, 0xae, 0xa4, 0x3a, 0x5a, 0x5d, 0xea, 0xdf, 0x9d, 0xc6, 0x11, 0xb9, 0x6d, 0x11, 0x33, 0x4e, 0xf9, 0x43, 0x09, 0x03, 0x89, 0xa8, 0xd3, 0xc6, 0x6c, 0xf3, 0x18, 0x77, 0xaa, 0x2c, 0xdf, 0xf1, 0x11, 0x99, 0x43, 0x27, 0x8a, 0xdd, 0xff, 0x5e } +, + /* Encryption */ + 129, + { 0x01, 0x22, 0x41, 0x0e, 0x76, 0x5b, 0x2c, 0x9e, 0x90, 0xbd, 0xac, 0xbc, 0xff, 0x1b, 0xca, 0x8a, 0xe6, 0x4b, 0xe9, 0x9c, 0xf0, 0x13, 0x29, 0x74, 0x85, 0x72, 0x17, 0x68, 0x37, 0x0c, 0x36, 0xf8, 0xc0, 0xd9, 0xdb, 0x8d, 0x79, 0x37, 0x62, 0x54, 0xb9, 0xc6, 0x91, 0x52, 0x72, 0x0e, 0x05, 0xca, 0xef, 0xd4, 0xce, 0x7e, 0xae, 0x08, 0xb3, 0xdf, 0xe3, 0xea, 0xa9, 0x1c, 0x46, 0x02, 0xef, 0xf3, 0x8e, 0x4d, 0x81, 0xbc, 0xd3, 0x78, 0x7a, 0x14, 0xd6, 0x22, 0xdb, 0xb7, 0x9c, 0xe8, 0x64, 0x4c, 0x4f, 0xd1, 0xd2, 0xe4, 0x1f, 0x7c, 0x1c, 0x97, 0x27, 0x96, 0x11, 0x74, 0x0f, 0xc5, 0x00, 0x00, 0x31, 0x78, 0xb3, 0x7b, 0xbd, 0x81, 0xc5, 0xa5, 0x82, 0x9b, 0x5c, 0x14, 0xbf, 0x45, 0x9c, 0x42, 0x38, 0xb0, 0x3b, 0xee, 0xf7, 0x3e, 0x49, 0x8f, 0x86, 0x5f, 0x6c, 0xa7, 0x9a, 0x9e, 0xd6, 0x0f, 0x65 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.19", + /* Message */ + 6, + { 0xad, 0x8b, 0x11, 0xa9, 0x27, 0xde } +, + /* Seed */ + 120, + { 0x5e, 0xca, 0xcf, 0xf6, 0x3a, 0x79, 0x38, 0xe9, 0x98, 0x06, 0x8a, 0x2f, 0x4b, 0xa6, 0xbc, 0xc1, 0x02, 0x0e, 0x1f, 0x28, 0xc7, 0x34, 0xe4, 0x34, 0xe8, 0x86, 0x3c, 0x48, 0xe6, 0xdf, 0xfa, 0xe2, 0x8d, 0x18, 0x52, 0x72, 0x7f, 0xfa, 0x7f, 0x2e, 0xfa, 0x3d, 0xe7, 0x01, 0x3b, 0x81, 0x2a, 0x02, 0xb2, 0x17, 0x1a, 0x0f, 0x94, 0x0b, 0x36, 0xd9, 0x28, 0xdb, 0xdb, 0x96, 0x0a, 0x6b, 0x22, 0x03, 0x0c, 0x89, 0x37, 0x89, 0xcb, 0xfd, 0xea, 0x97, 0x35, 0xe9, 0xad, 0x10, 0x94, 0xa6, 0x84, 0x61, 0xc2, 0xeb, 0x6f, 0x71, 0x8b, 0xe4, 0x74, 0xd9, 0x3a, 0x51, 0x93, 0x0e, 0x3c, 0xda, 0x02, 0xc2, 0x1f, 0x63, 0x63, 0x91, 0x4e, 0x7e, 0xda, 0x54, 0x84, 0x03, 0x7a, 0x76, 0xad, 0xc5, 0x33, 0x12, 0xeb, 0x9d, 0xbb, 0xe4, 0x5e, 0x23, 0xa1, 0x4b } +, + /* Encryption */ + 129, + { 0x01, 0x1f, 0xa4, 0x3f, 0x5f, 0x4f, 0xbb, 0x98, 0x30, 0x11, 0x81, 0x4d, 0x4a, 0xf5, 0x45, 0x52, 0x1d, 0xf0, 0xb5, 0x9e, 0x9b, 0x6f, 0xfd, 0x71, 0x33, 0x3b, 0x8f, 0x9b, 0xba, 0xaa, 0x0f, 0xcd, 0xc1, 0x42, 0x1c, 0xe4, 0xbf, 0x31, 0xbf, 0x99, 0x59, 0xfd, 0xc6, 0xb0, 0x9b, 0x4f, 0x42, 0x51, 0xdd, 0xee, 0xe8, 0x21, 0x0f, 0xc3, 0xa5, 0x2f, 0xe7, 0xc7, 0x1a, 0x87, 0x6e, 0x6d, 0xde, 0x1d, 0xfb, 0x59, 0xa4, 0xda, 0xb2, 0x7d, 0x34, 0xfd, 0xce, 0x5b, 0xbf, 0xc6, 0xed, 0x62, 0x3e, 0x89, 0x96, 0x7f, 0xb6, 0xfe, 0x73, 0x16, 0x20, 0x15, 0x28, 0x2c, 0x5f, 0x45, 0x01, 0x38, 0xf2, 0x50, 0x4a, 0xb6, 0x1c, 0x1f, 0x12, 0xd2, 0x64, 0x9d, 0x81, 0x5d, 0x6e, 0x81, 0x38, 0x43, 0x8f, 0x8a, 0x80, 0x46, 0xc4, 0xe8, 0x40, 0xcb, 0x71, 0x85, 0x98, 0xe1, 0xe4, 0xa9, 0xfc, 0x25, 0xa9, 0x45, 0x64 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 7.20", + /* Message */ + 44, + { 0xbe, 0xe2, 0x94, 0x36, 0xc2, 0xa0, 0xde, 0x16, 0xf6, 0x60, 0x42, 0x91, 0x70, 0x07, 0xfb, 0x51, 0x30, 0xf3, 0xc1, 0xaa, 0x7d, 0xf2, 0xc7, 0xc3, 0xbd, 0x99, 0xfb, 0xc1, 0xb4, 0x13, 0xaf, 0x4f, 0x96, 0xa6, 0x5b, 0x0e, 0x54, 0x3e, 0xc6, 0xa5, 0x0b, 0xe8, 0x3a, 0x9f } +, + /* Seed */ + 82, + { 0x23, 0x91, 0xa6, 0x84, 0x25, 0xdd, 0x8f, 0x0b, 0x83, 0xc9, 0xb3, 0x61, 0x24, 0x67, 0xa7, 0x79, 0xcf, 0x92, 0xf5, 0xff, 0x96, 0x11, 0xc0, 0x14, 0x93, 0xbc, 0xbe, 0xf8, 0x65, 0xe1, 0x5b, 0xba, 0x5e, 0x8f, 0xcf, 0x74, 0xbe, 0xb9, 0xea, 0x25, 0x73, 0xa9, 0xfc, 0xe5, 0x41, 0x64, 0xd0, 0x6b, 0xaa, 0x8b, 0x6d, 0xf3, 0x67, 0xcc, 0x4c, 0x6a, 0x11, 0x4a, 0xa0, 0x34, 0x6c, 0x45, 0x4a, 0x2a, 0x9e, 0x60, 0x53, 0x59, 0x18, 0xd3, 0x66, 0x0c, 0x66, 0x48, 0x4e, 0xd9, 0x53, 0x72, 0x7a, 0x9c, 0x9a, 0x25 } +, + /* Encryption */ + 129, + { 0x00, 0x98, 0x9d, 0xdb, 0xd2, 0x8d, 0x60, 0x95, 0xad, 0xa6, 0x88, 0x1e, 0x28, 0x34, 0x1c, 0xe7, 0xa0, 0xa1, 0xca, 0x6b, 0xf7, 0xf3, 0x1f, 0x77, 0x2f, 0x91, 0x04, 0x93, 0xaf, 0xdb, 0xa2, 0xd6, 0x35, 0x9d, 0x50, 0xb9, 0x83, 0x3f, 0x83, 0xd0, 0xab, 0x87, 0x13, 0xab, 0xe8, 0xe2, 0x10, 0x2a, 0x27, 0xab, 0x2a, 0x60, 0x1f, 0xb7, 0x7b, 0x9a, 0x25, 0xd6, 0xa0, 0xaf, 0xf4, 0x0c, 0xfd, 0xcf, 0x9e, 0x12, 0xc4, 0x28, 0x43, 0xeb, 0xad, 0x32, 0x83, 0x24, 0xa7, 0x19, 0xf2, 0x9e, 0x8d, 0x79, 0xea, 0x9e, 0x5d, 0x0d, 0x98, 0x86, 0x95, 0x73, 0x60, 0x34, 0xdb, 0x5f, 0xea, 0x73, 0xdd, 0x36, 0x00, 0x13, 0x6f, 0x57, 0xa3, 0x98, 0xfe, 0x35, 0x2b, 0x27, 0x8c, 0x60, 0xcb, 0x74, 0xec, 0x98, 0xad, 0x57, 0xa3, 0xe1, 0xd8, 0xc4, 0x47, 0x8c, 0xa6, 0x17, 0x9f, 0x4d, 0x04, 0x26, 0xf0, 0xf4, 0x20 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 8: A 1026-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x02, 0x52, 0xe9, 0x5b, 0xb1, 0x1b, 0xa1, 0xe1, 0xc7, 0xc9, 0x5b, 0x68, 0x53, 0xf8, 0xde, 0x0b, 0xfe, 0x2b, 0x64, 0x03, 0xac, 0x1b, 0xde, 0x81, 0x9d, 0x91, 0x89, 0x07, 0x74, 0x7b, 0x01, 0x99, 0xfa, 0xdb, 0x80, 0x59, 0xc2, 0x5a, 0xaf, 0x1a, 0xc5, 0x65, 0xa7, 0x49, 0x29, 0xd0, 0x15, 0xa2, 0x01, 0xf8, 0x97, 0xa9, 0xba, 0xfe, 0x75, 0x41, 0x68, 0x95, 0x5b, 0x35, 0x5b, 0xb0, 0x09, 0xce, 0x16, 0x14, 0x93, 0x12, 0x28, 0x3c, 0x39, 0xce, 0xe2, 0x20, 0xd0, 0xf0, 0x85, 0x8b, 0x13, 0x81, 0x2e, 0x86, 0xa7, 0xd4, 0xe5, 0x38, 0x8b, 0x7e, 0xae, 0x5a, 0xca, 0x7c, 0x88, 0x6a, 0x76, 0xd3, 0xb1, 0xe6, 0xdd, 0x67, 0x92, 0x68, 0xa8, 0x23, 0x11, 0xe2, 0x82, 0x03, 0x18, 0xcb, 0x8f, 0x0f, 0x7e, 0x85, 0xf0, 0xe6, 0x69, 0x2e, 0xb0, 0xde, 0xdf, 0x30, 0x88, 0x1c, 0xaf, 0x73, 0x15, 0xd2, 0x7d } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x01, 0x04, 0xc8, 0x5f, 0xd5, 0xd8, 0xd7, 0x93, 0x2a, 0x29, 0x85, 0xc4, 0xcb, 0x7e, 0x9e, 0x13, 0xa2, 0xc4, 0xf1, 0x90, 0x3c, 0x8b, 0x70, 0xf3, 0xdf, 0x97, 0x12, 0xfa, 0xee, 0x20, 0x17, 0xb9, 0x20, 0x82, 0xc5, 0x16, 0x53, 0xc0, 0xbd, 0xde, 0x9d, 0xe6, 0x6c, 0x39, 0x01, 0xb7, 0xc2, 0x2b, 0xe4, 0xf2, 0x4c, 0xc5, 0x6d, 0xff, 0xaa, 0x75, 0xd4, 0x3b, 0x18, 0xa2, 0xe0, 0xc0, 0xdf, 0xe3, 0x72, 0x6b, 0x19, 0x8c, 0xaa, 0x0c, 0x96, 0x65, 0x26, 0x3a, 0x93, 0x79, 0x6a, 0x27, 0xd3, 0x29, 0x84, 0x46, 0x5f, 0x4b, 0x4a, 0xff, 0xca, 0x0d, 0x92, 0xf4, 0xe5, 0x1a, 0x37, 0xe4, 0x1a, 0xb1, 0x55, 0x07, 0x66, 0xd5, 0xca, 0x7e, 0x90, 0xd4, 0xde, 0x90, 0x9b, 0xbd, 0x79, 0x4e, 0x8b, 0xc5, 0x2b, 0x74, 0x99, 0xa7, 0x3e, 0x46, 0x8a, 0xb4, 0x42, 0x13, 0xcb, 0x3a, 0x3b, 0x54, 0x52, 0xd2, 0xff } +, + /* Prime 1 */ + 65, + { 0x01, 0x93, 0x3f, 0x8f, 0x85, 0x82, 0xb8, 0xff, 0xf3, 0xe6, 0xbd, 0x30, 0x42, 0x81, 0x97, 0xf0, 0xac, 0xec, 0x63, 0xe6, 0x91, 0xf7, 0x9b, 0x91, 0xfb, 0xd4, 0xd4, 0xc4, 0x94, 0x2b, 0x8a, 0xe9, 0x13, 0xa4, 0x01, 0xf0, 0xe1, 0x7b, 0xa7, 0x66, 0xd0, 0xa8, 0xee, 0xec, 0x4c, 0xb0, 0xe3, 0xda, 0x17, 0xb6, 0xd9, 0x1f, 0x1a, 0x74, 0x24, 0x88, 0x09, 0x20, 0x1e, 0x37, 0x30, 0x15, 0x18, 0x61, 0x8f } +, + /* Prime 2 */ + 65, + { 0x01, 0x79, 0xad, 0x28, 0x3c, 0xac, 0x68, 0xaf, 0x21, 0x6a, 0x06, 0x86, 0xf4, 0x38, 0xb1, 0xe0, 0xe5, 0xc3, 0x6b, 0x95, 0x5f, 0x74, 0xe1, 0x07, 0xf3, 0x9c, 0x0d, 0xdd, 0xcc, 0x99, 0x0a, 0xd5, 0x73, 0xdc, 0x48, 0xa9, 0x73, 0x23, 0x5b, 0x6d, 0x82, 0x54, 0x36, 0x18, 0xf2, 0xe9, 0x55, 0x10, 0x5d, 0x8c, 0x4a, 0x5f, 0x49, 0x14, 0xbe, 0xe2, 0x5d, 0xe3, 0xc6, 0x93, 0x41, 0xde, 0x07, 0xed, 0x33 } +, + /* Prime exponent 1 */ + 65, + { 0x01, 0x6e, 0xf5, 0x3d, 0x6f, 0x3a, 0xd9, 0x8d, 0x9a, 0x6f, 0xd4, 0xa4, 0x71, 0x31, 0x2b, 0x8a, 0x8a, 0x62, 0x88, 0x3a, 0xcf, 0x84, 0x6b, 0x5e, 0xfa, 0xb3, 0xe0, 0x77, 0x8f, 0x7a, 0xdc, 0x6b, 0x64, 0x43, 0x30, 0xbc, 0xfb, 0x04, 0xa2, 0xff, 0x0e, 0x4d, 0x5d, 0x37, 0x4e, 0x46, 0xfe, 0xe2, 0x7e, 0x08, 0x18, 0x27, 0x94, 0xd4, 0x32, 0x56, 0x55, 0x2f, 0x94, 0x2f, 0x96, 0xa2, 0xeb, 0xd0, 0x03 } +, + /* Prime exponent 2 */ + 64, + { 0xe6, 0xc6, 0xe6, 0x25, 0x5c, 0xfc, 0x82, 0xb7, 0x1a, 0x40, 0x6e, 0xca, 0x60, 0xb2, 0x60, 0xc8, 0x45, 0x07, 0x42, 0x39, 0x18, 0x04, 0x41, 0x85, 0x9c, 0x3f, 0xe4, 0xde, 0x16, 0x4e, 0x46, 0x6c, 0x0b, 0x98, 0xe2, 0xe2, 0x16, 0x22, 0xd1, 0xe1, 0xa7, 0x6f, 0x7f, 0x03, 0x3f, 0x8c, 0xd8, 0xf9, 0x30, 0xb6, 0x69, 0x4f, 0x10, 0xbc, 0x2b, 0x3a, 0x4f, 0xea, 0x91, 0x24, 0xd8, 0x75, 0x63, 0x7d } +, + /* Coefficient */ + 64, + { 0x35, 0x42, 0x45, 0x2e, 0x83, 0x2c, 0x16, 0xac, 0xf9, 0xc3, 0xf4, 0x13, 0x49, 0x23, 0x5e, 0xdd, 0xd2, 0x75, 0xc7, 0x05, 0x3c, 0x55, 0x3b, 0xf8, 0x9e, 0x1a, 0x84, 0x57, 0x12, 0x48, 0x33, 0x3a, 0xad, 0x52, 0x0e, 0x3a, 0x34, 0x46, 0xc4, 0xc5, 0xe3, 0xfd, 0xd9, 0xba, 0xec, 0xd9, 0x29, 0x48, 0x0e, 0xb5, 0xb8, 0xfb, 0xef, 0x8e, 0x03, 0xad, 0xe9, 0xe3, 0x9a, 0x28, 0xfd, 0x8e, 0x75, 0x6c } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 8.1", + /* Message */ + 34, + { 0xf7, 0x26, 0x37, 0xae, 0xc2, 0x8d, 0x2b, 0x6e, 0xbf, 0x8f, 0x73, 0xd7, 0x48, 0x75, 0xdf, 0x01, 0xcd, 0x12, 0x24, 0x8f, 0x00, 0x20, 0x60, 0x8e, 0x61, 0xc7, 0x3d, 0x1a, 0x01, 0xf9, 0x72, 0xf7, 0x4d, 0xee } +, + /* Seed */ + 92, + { 0xcc, 0x20, 0x77, 0xa2, 0x40, 0x01, 0xf3, 0xe3, 0x86, 0x96, 0x94, 0xe4, 0xfe, 0x27, 0x72, 0xbf, 0x93, 0x8f, 0x76, 0x27, 0x66, 0x7b, 0x62, 0xd5, 0x90, 0xf9, 0xee, 0x4f, 0xcf, 0xff, 0xbb, 0xb4, 0x7a, 0xfd, 0x5f, 0xed, 0x6a, 0x18, 0x08, 0x44, 0xa9, 0x12, 0x1a, 0x32, 0xed, 0x7c, 0xbc, 0x56, 0xcd, 0x28, 0x70, 0xa2, 0xd6, 0x96, 0xb9, 0x43, 0xd6, 0xfd, 0xe9, 0x76, 0x7c, 0x1b, 0x96, 0x48, 0x61, 0x6c, 0x32, 0xed, 0x6c, 0x40, 0x0d, 0x42, 0x3d, 0xd4, 0xab, 0x72, 0x16, 0xaf, 0xad, 0xa0, 0x28, 0x40, 0x2e, 0xb2, 0xa1, 0xc3, 0xeb, 0xcc, 0x24, 0x5a, 0xfc, 0x7f } +, + /* Encryption */ + 129, + { 0x00, 0x72, 0x57, 0x5d, 0x3b, 0x11, 0xc5, 0xff, 0xd6, 0xae, 0x24, 0xf3, 0x53, 0xff, 0x74, 0x99, 0x27, 0xb4, 0xae, 0x5d, 0xf4, 0x63, 0xf7, 0x0c, 0x5f, 0x3e, 0xf5, 0x49, 0x6b, 0x0d, 0x14, 0x5e, 0xb2, 0xb8, 0xa5, 0x3c, 0x28, 0xd5, 0x3e, 0xfe, 0x8b, 0xf9, 0xf2, 0x7b, 0x2e, 0xf4, 0xce, 0xea, 0x48, 0x31, 0x05, 0x77, 0xc3, 0xd2, 0xb4, 0xb9, 0x49, 0xa1, 0x2e, 0x3d, 0xf3, 0xf5, 0x67, 0x76, 0x82, 0x88, 0x18, 0x45, 0x2d, 0x81, 0xbd, 0x45, 0xaf, 0x15, 0x8c, 0x87, 0xbb, 0x57, 0x74, 0x5b, 0x8a, 0x10, 0xfc, 0x1a, 0x92, 0xa0, 0xea, 0x55, 0xc8, 0x51, 0x39, 0xf8, 0x42, 0xf7, 0x3f, 0x1d, 0x61, 0x3b, 0x9a, 0x96, 0x4a, 0xf8, 0xed, 0x72, 0x0d, 0x0e, 0x08, 0x47, 0xf7, 0xae, 0x5b, 0x30, 0x5c, 0x05, 0xf1, 0x2c, 0xbc, 0x4c, 0x9c, 0x16, 0x84, 0xac, 0xf9, 0x02, 0x97, 0x0d, 0x82, 0x09, 0x49 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 8.2", + /* Message */ + 60, + { 0x2a, 0x8e, 0x3e, 0xe7, 0xea, 0xc6, 0xb2, 0x2e, 0xc6, 0x58, 0xad, 0x44, 0xd6, 0x66, 0xc8, 0xcd, 0x3f, 0x57, 0xec, 0xea, 0x29, 0x9b, 0x5c, 0xb7, 0xbf, 0x9a, 0x37, 0x3d, 0xfa, 0x66, 0x97, 0x2f, 0x13, 0xe5, 0xf3, 0xa3, 0x00, 0xe8, 0x0e, 0x6d, 0xbf, 0x74, 0x15, 0x68, 0x0d, 0x0d, 0x24, 0x90, 0x1a, 0xd6, 0xb1, 0x40, 0xb0, 0x00, 0xaa, 0xb8, 0x53, 0x51, 0xf9, 0x2f } +, + /* Seed */ + 66, + { 0xfb, 0x19, 0x20, 0x9d, 0x8a, 0x29, 0xaf, 0xaf, 0xbc, 0x05, 0x3a, 0xc1, 0xf3, 0x20, 0xba, 0x60, 0xfc, 0x1f, 0xe1, 0x04, 0xaa, 0x78, 0x39, 0xc8, 0x4c, 0x9b, 0x3e, 0xaa, 0x18, 0xa8, 0xf9, 0x43, 0xbb, 0x21, 0x9f, 0x59, 0xcc, 0x16, 0x7a, 0x38, 0x4b, 0xac, 0x7b, 0xd3, 0x65, 0x82, 0x4e, 0x10, 0x36, 0x31, 0xb9, 0x7b, 0xb9, 0xa6, 0xd1, 0x18, 0xf4, 0xf0, 0xa9, 0x51, 0xfa, 0x47, 0x8a, 0x05, 0xea, 0x09 } +, + /* Encryption */ + 129, + { 0x02, 0x1b, 0x54, 0x64, 0x65, 0x71, 0xa9, 0xa9, 0x3f, 0x0b, 0x0a, 0x03, 0x82, 0xe5, 0x40, 0xa8, 0xc3, 0x97, 0x4c, 0xb3, 0x1c, 0x87, 0xeb, 0xf1, 0x7b, 0x3b, 0xa6, 0x2a, 0x1c, 0x95, 0x21, 0xc5, 0x0d, 0x7f, 0x90, 0x70, 0x2e, 0x13, 0xae, 0x0e, 0x22, 0x26, 0x38, 0x34, 0xe7, 0x64, 0x60, 0x35, 0x15, 0x94, 0x45, 0xa0, 0x87, 0x7d, 0x9a, 0x4f, 0x5b, 0x16, 0x17, 0x7f, 0x7f, 0xe0, 0x52, 0xbb, 0xd0, 0x23, 0xd0, 0x81, 0x89, 0x4f, 0x2d, 0x97, 0xca, 0xc2, 0x45, 0x20, 0x76, 0xca, 0x11, 0x91, 0xa1, 0x71, 0xa4, 0x8f, 0xa1, 0xcb, 0xbb, 0xc3, 0xf0, 0xf6, 0xf3, 0xbc, 0x1a, 0x44, 0x78, 0x40, 0x3a, 0x5a, 0x48, 0x8f, 0xeb, 0xb3, 0xa4, 0x13, 0x80, 0x16, 0x3d, 0x94, 0x2c, 0x97, 0x7b, 0xb8, 0xec, 0xd2, 0x86, 0x6c, 0x5f, 0x5d, 0x91, 0x9e, 0xd2, 0x0c, 0x0d, 0xb3, 0xee, 0x31, 0xef, 0x2f, 0x51 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.3", + /* Message */ + 24, + { 0xd9, 0x9b, 0x4f, 0x10, 0xd9, 0xf3, 0x2e, 0x12, 0xec, 0xfa, 0xe2, 0x63, 0x0b, 0x22, 0xac, 0x02, 0x6a, 0xf9, 0x64, 0xb9, 0xc7, 0x15, 0xd2, 0x07 } +, + /* Seed */ + 102, + { 0xe0, 0xaf, 0x8b, 0x7e, 0xab, 0x36, 0xa6, 0xee, 0x31, 0x6d, 0x78, 0x13, 0x67, 0xf0, 0x9e, 0xa1, 0x1e, 0x31, 0xfd, 0xc1, 0xef, 0x2c, 0xf9, 0xc9, 0x7c, 0x37, 0x9e, 0xaa, 0xcf, 0x68, 0x72, 0xa8, 0x21, 0x3c, 0xbe, 0x4c, 0xe2, 0xe2, 0x9c, 0x77, 0x8b, 0x35, 0x95, 0x40, 0x10, 0x06, 0x3f, 0x17, 0x76, 0xab, 0x5b, 0x17, 0x2d, 0xa6, 0x24, 0xb4, 0x06, 0xa1, 0xc5, 0x8e, 0x0b, 0x57, 0x4a, 0x03, 0xb1, 0xb1, 0xb2, 0xcd, 0x7d, 0x3a, 0x9e, 0x50, 0x35, 0xa9, 0xa9, 0x73, 0x05, 0x8f, 0x04, 0x97, 0x65, 0x2d, 0x2f, 0x73, 0xb1, 0xdc, 0x8f, 0x48, 0x7c, 0x09, 0xcf, 0xe7, 0x1d, 0x8f, 0xf8, 0xf1, 0x45, 0x8c, 0x79, 0x0e, 0xe0, 0xc5 } +, + /* Encryption */ + 129, + { 0x01, 0x02, 0x3b, 0xbe, 0x85, 0x57, 0xc2, 0x63, 0x0a, 0x26, 0x22, 0x46, 0xdb, 0x7a, 0xbc, 0x54, 0x03, 0x43, 0x88, 0x70, 0x38, 0xf6, 0x4c, 0x64, 0x1f, 0xd7, 0x4e, 0xe8, 0x74, 0xae, 0x96, 0x70, 0xfb, 0x28, 0x62, 0xd4, 0x24, 0x70, 0x3d, 0xa2, 0x0b, 0xe4, 0xf4, 0x8b, 0x23, 0x9c, 0xd0, 0x60, 0x43, 0x81, 0x9d, 0x8f, 0x61, 0x51, 0x44, 0xe2, 0xb1, 0xf0, 0x0c, 0x8f, 0x88, 0x49, 0x2e, 0x62, 0xf6, 0xe0, 0x73, 0x16, 0xf8, 0x49, 0x05, 0x35, 0x3b, 0x0b, 0x18, 0x80, 0xed, 0x77, 0xda, 0x2b, 0x62, 0xd3, 0xa9, 0x3b, 0xb7, 0x0f, 0xf6, 0xa5, 0x00, 0x79, 0x38, 0xb9, 0x73, 0xb4, 0xcd, 0x5a, 0xbf, 0xee, 0x0c, 0xf1, 0x3f, 0x5d, 0x4a, 0xb2, 0x16, 0x01, 0x02, 0x68, 0x5c, 0xac, 0x80, 0x81, 0x83, 0x4f, 0x95, 0x55, 0x80, 0x6b, 0xb3, 0x22, 0xd0, 0xdc, 0x5b, 0x8a, 0x2b, 0xf1, 0x28, 0x45, 0x62 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.4", + /* Message */ + 25, + { 0xca, 0xec, 0xa8, 0xe5, 0x9b, 0x81, 0x0c, 0xf7, 0x51, 0x12, 0xf7, 0xed, 0x04, 0x7a, 0x46, 0x69, 0x2c, 0xa0, 0xb7, 0xa8, 0x6e, 0x18, 0x41, 0xd7, 0x19 } +, + /* Seed */ + 101, + { 0x76, 0x1f, 0x68, 0x64, 0xdc, 0xeb, 0xc9, 0x5a, 0x77, 0x9b, 0xc0, 0xb1, 0x6a, 0x95, 0x86, 0x6c, 0x33, 0xdc, 0x8d, 0xca, 0xce, 0x61, 0xcd, 0x7b, 0xf9, 0x01, 0x72, 0xd9, 0x9a, 0xa4, 0x57, 0xdb, 0x6d, 0x90, 0x88, 0x7d, 0x84, 0xc4, 0x73, 0x8d, 0x25, 0xcd, 0xf0, 0xe8, 0x95, 0x69, 0xae, 0x47, 0xd3, 0x07, 0x3e, 0xc4, 0x46, 0xee, 0xed, 0xd5, 0x2d, 0x57, 0x20, 0x8b, 0xdb, 0x69, 0x45, 0x57, 0x03, 0x46, 0x57, 0xa7, 0x03, 0x78, 0x49, 0x37, 0xba, 0x69, 0x4d, 0x42, 0x51, 0x21, 0x38, 0x53, 0x2b, 0x8a, 0xd1, 0xd9, 0x86, 0xfe, 0x47, 0x31, 0x8b, 0x28, 0x23, 0xde, 0x82, 0xce, 0x27, 0x6f, 0xa6, 0xf0, 0xd3, 0xc8, 0xef } +, + /* Encryption */ + 129, + { 0x01, 0x1c, 0x0c, 0x03, 0xf7, 0xb6, 0xe1, 0xc1, 0xa8, 0x41, 0x17, 0x40, 0xa6, 0xe5, 0xb4, 0x73, 0xc2, 0x8d, 0x62, 0x21, 0x17, 0x6c, 0x9d, 0x4f, 0x68, 0x02, 0x4c, 0xa5, 0x7c, 0xda, 0x27, 0x3a, 0xf5, 0x54, 0x74, 0x03, 0x60, 0x99, 0x0a, 0x1b, 0x74, 0xde, 0x34, 0xbc, 0xea, 0x10, 0x3c, 0x2d, 0x0c, 0x36, 0x57, 0x60, 0x02, 0x08, 0x0b, 0x30, 0xbd, 0x28, 0xf0, 0x76, 0xfb, 0x75, 0xfc, 0x9b, 0xeb, 0x9e, 0x05, 0xd1, 0x98, 0x9a, 0x31, 0x1d, 0x12, 0xc1, 0xf2, 0x8f, 0xd6, 0x93, 0x92, 0xad, 0x4b, 0xe5, 0x2c, 0xe3, 0x89, 0xde, 0xc1, 0x1e, 0xba, 0x94, 0x6b, 0xe0, 0x59, 0x91, 0xda, 0x7f, 0xd8, 0x87, 0xa8, 0xd8, 0x76, 0x8d, 0xe7, 0x36, 0xb9, 0x05, 0xbf, 0x4b, 0xdb, 0xe8, 0x8b, 0x85, 0xdf, 0xc3, 0xb2, 0x5a, 0xea, 0x30, 0xfe, 0x90, 0xdf, 0x1d, 0x22, 0xd8, 0xa8, 0xd6, 0x15, 0x65, 0x1c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.5", + /* Message */ + 39, + { 0x10, 0x12, 0x12, 0x85, 0x6e, 0x60, 0xcd, 0x27, 0x2f, 0xb1, 0x69, 0xcf, 0x62, 0xcf, 0x47, 0xf1, 0xbc, 0x50, 0xef, 0x9f, 0x1f, 0xcf, 0xd2, 0x14, 0x81, 0x6c, 0x80, 0x7f, 0x18, 0x4a, 0x90, 0x3f, 0x16, 0xf0, 0xe8, 0x09, 0xac, 0xf5, 0xe0 } +, + /* Seed */ + 87, + { 0x60, 0x43, 0xc8, 0xdf, 0x6a, 0x7f, 0x4a, 0xb8, 0x3e, 0x31, 0x97, 0xe8, 0xcd, 0x02, 0x25, 0xdc, 0x38, 0x66, 0xb5, 0xd8, 0xe6, 0x99, 0x3c, 0x2c, 0xc5, 0xb8, 0x76, 0x35, 0x1e, 0xe3, 0x3c, 0x71, 0xc1, 0xa4, 0xcc, 0xdc, 0xe4, 0x5f, 0x3e, 0x9d, 0xc7, 0xb7, 0xe5, 0x1b, 0x52, 0xee, 0xbe, 0x0e, 0x27, 0x0e, 0x71, 0x62, 0x07, 0xca, 0x14, 0x03, 0xe1, 0x3e, 0x72, 0x3c, 0xe7, 0x3f, 0x10, 0x45, 0x5e, 0xdb, 0xde, 0x85, 0xb0, 0x82, 0x90, 0x52, 0xed, 0xaf, 0xe5, 0x6e, 0x9a, 0x22, 0x02, 0x4d, 0x40, 0x68, 0x37, 0x1d, 0x36, 0xc9, 0x1f } +, + /* Encryption */ + 129, + { 0x00, 0x05, 0xc5, 0xcf, 0xf8, 0x9b, 0x93, 0x3d, 0x8b, 0x65, 0x23, 0xb3, 0x59, 0x06, 0xbb, 0x3a, 0x71, 0x1a, 0x0f, 0x7f, 0x50, 0x3f, 0x92, 0x14, 0x74, 0x66, 0x59, 0x85, 0x03, 0x91, 0x27, 0x30, 0x3b, 0x00, 0x11, 0xe7, 0xa4, 0x2b, 0x41, 0xc3, 0x3b, 0xd2, 0x0d, 0xb3, 0x1b, 0x15, 0x60, 0xc9, 0xb5, 0x22, 0x20, 0x89, 0xcd, 0xcf, 0x53, 0xb8, 0x2c, 0x95, 0xf8, 0xc1, 0xad, 0xcd, 0x8b, 0x78, 0x3f, 0xd4, 0xb4, 0x8a, 0x45, 0x40, 0x20, 0x66, 0x8e, 0x0b, 0x62, 0x52, 0x0e, 0x52, 0x58, 0x52, 0x09, 0xdb, 0x52, 0x9f, 0x38, 0x70, 0x86, 0x49, 0xd8, 0xe0, 0x64, 0x89, 0x0b, 0x22, 0x8f, 0xb3, 0xc1, 0x98, 0x1b, 0x2a, 0xef, 0x3a, 0x54, 0x65, 0xce, 0xb1, 0x30, 0x21, 0xeb, 0xe0, 0x8d, 0x02, 0xe3, 0x3a, 0xa2, 0xdc, 0x3c, 0x39, 0x28, 0x4e, 0xf7, 0xa8, 0x58, 0xdc, 0xce, 0xb2, 0x8f, 0xfa, 0x28 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.6", + /* Message */ + 17, + { 0x6f, 0x03, 0xb5, 0x72, 0x52, 0x30, 0xde, 0x7f, 0x99, 0x63, 0x69, 0x8e, 0xdb, 0x79, 0x75, 0xec, 0xe8 } +, + /* Seed */ + 109, + { 0xa3, 0x0e, 0xe5, 0xae, 0xab, 0x59, 0x31, 0x03, 0x3e, 0xfb, 0x70, 0xaf, 0xbc, 0x2d, 0x3d, 0x11, 0xa6, 0x33, 0x84, 0xcb, 0x8c, 0xb3, 0x3a, 0x8f, 0xca, 0xe6, 0x14, 0x66, 0x84, 0xe6, 0x3f, 0x0c, 0xc3, 0x2e, 0x89, 0xa7, 0xe4, 0xea, 0x43, 0x32, 0x7b, 0xf0, 0x35, 0x66, 0x95, 0x43, 0x19, 0x28, 0x86, 0xde, 0xc3, 0xfb, 0x4e, 0x2d, 0x08, 0x11, 0xef, 0xa9, 0xae, 0xc5, 0x10, 0x9e, 0x31, 0xb6, 0xa0, 0x56, 0xe5, 0x3e, 0x31, 0x7f, 0x6a, 0x90, 0x4b, 0x13, 0xa7, 0x35, 0x6f, 0x5e, 0x7a, 0xe6, 0x0b, 0x97, 0x21, 0x5e, 0xd1, 0x48, 0x17, 0xd2, 0x8f, 0x74, 0xb1, 0x64, 0x0b, 0x1f, 0x2e, 0x42, 0xef, 0x0d, 0x38, 0xca, 0x35, 0xa3, 0x54, 0xa0, 0xaf, 0xef, 0xa8, 0x03, 0xa4 } +, + /* Encryption */ + 129, + { 0x00, 0x10, 0xbd, 0x2b, 0x35, 0x6f, 0x9e, 0xab, 0xc2, 0x2f, 0x7e, 0x68, 0xf7, 0x2f, 0x61, 0x75, 0xf9, 0xab, 0x9d, 0xed, 0xa9, 0x64, 0x23, 0xb7, 0x4b, 0x11, 0xde, 0x82, 0xc6, 0x07, 0xa1, 0x38, 0x86, 0x3e, 0x17, 0x96, 0x6c, 0x07, 0xf5, 0x6c, 0xde, 0x9e, 0xd6, 0xbc, 0x42, 0x2e, 0xd9, 0xfe, 0xaa, 0x1f, 0x65, 0x36, 0x7c, 0xcf, 0x91, 0xcd, 0x4c, 0x91, 0x58, 0xa7, 0x49, 0x57, 0x1a, 0x0e, 0x9f, 0x96, 0x07, 0xcb, 0x48, 0xcd, 0x00, 0xa4, 0x48, 0xde, 0x03, 0x64, 0x91, 0x06, 0xce, 0x0c, 0x24, 0x06, 0xaa, 0x50, 0xaa, 0x12, 0x17, 0x17, 0x8c, 0xdb, 0x06, 0x80, 0x1c, 0x70, 0xa8, 0x9a, 0x7a, 0x1a, 0x83, 0x06, 0x8e, 0x68, 0xdb, 0x95, 0xd2, 0x4c, 0xa3, 0xdb, 0x33, 0xa7, 0xe5, 0xe4, 0x3a, 0x68, 0x15, 0x22, 0x74, 0xbb, 0xbf, 0x40, 0x06, 0xd9, 0xfb, 0x69, 0xf0, 0x51, 0x4c, 0xc9, 0xe2 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.7", + /* Message */ + 9, + { 0x87, 0x99, 0x13, 0x04, 0x54, 0x61, 0xbc, 0x0e, 0xac } +, + /* Seed */ + 117, + { 0xc3, 0xc6, 0xa2, 0x4a, 0xc3, 0x40, 0xa4, 0xa3, 0xff, 0x3b, 0x2c, 0x30, 0x2b, 0x56, 0xeb, 0x83, 0x91, 0xbb, 0xd9, 0x5f, 0xaf, 0xb6, 0x64, 0x78, 0x38, 0x44, 0x38, 0xab, 0xd8, 0xb4, 0x5d, 0x13, 0x2b, 0x26, 0x99, 0x09, 0xb1, 0x87, 0x84, 0x0a, 0x68, 0x44, 0xad, 0x39, 0x9f, 0xa8, 0x13, 0x72, 0x05, 0xe0, 0x2c, 0xca, 0xe7, 0x77, 0x5c, 0xe6, 0x66, 0x21, 0x20, 0xe1, 0x54, 0xb7, 0xbf, 0xd3, 0x0e, 0x8e, 0xa4, 0xd3, 0x4a, 0x7d, 0xb6, 0xa2, 0x34, 0x88, 0xa5, 0xda, 0xea, 0x38, 0x08, 0x5b, 0xed, 0x56, 0x78, 0x0c, 0xff, 0x87, 0x27, 0x12, 0x5f, 0x1a, 0xd5, 0xf9, 0xd5, 0xa0, 0xbc, 0x3b, 0xe5, 0x80, 0xbc, 0x4f, 0xa0, 0x68, 0x26, 0x7b, 0x27, 0xde, 0x38, 0x3c, 0x55, 0xc7, 0xfc, 0x17, 0x64, 0xc8, 0x6a, 0xc2, 0x1a } +, + /* Encryption */ + 129, + { 0x01, 0xd2, 0x1e, 0xce, 0x33, 0xf4, 0x40, 0xc7, 0x2a, 0x11, 0x1d, 0x62, 0xef, 0x48, 0x6c, 0x77, 0xc6, 0xc8, 0x90, 0xcd, 0x81, 0xa4, 0xeb, 0x05, 0x32, 0xad, 0x2c, 0x0e, 0xc7, 0x68, 0xdd, 0x1d, 0xe5, 0xb2, 0x11, 0x2f, 0xdf, 0x04, 0xe2, 0x87, 0xa9, 0x5b, 0x95, 0x0b, 0x1f, 0xca, 0x5a, 0xe6, 0x93, 0xcf, 0x0e, 0x8a, 0xcc, 0x93, 0x6f, 0x37, 0x47, 0x14, 0xde, 0x74, 0x95, 0x90, 0x8c, 0x29, 0x15, 0xa7, 0x07, 0x21, 0x3a, 0xc3, 0xdb, 0xda, 0xba, 0xd8, 0x1b, 0x4b, 0xa1, 0xcb, 0x50, 0xb9, 0x5f, 0x93, 0x14, 0x53, 0x1f, 0xec, 0x83, 0x3f, 0x08, 0x21, 0xc0, 0x4b, 0x57, 0x40, 0xd7, 0x3b, 0x8c, 0xf1, 0xf9, 0xe3, 0xd7, 0xab, 0xc9, 0x74, 0x49, 0x26, 0x13, 0x8f, 0xb0, 0x15, 0xc0, 0xf0, 0x56, 0xcc, 0x4b, 0xa2, 0xf3, 0x16, 0x37, 0x34, 0xdb, 0x44, 0x3e, 0xbd, 0x68, 0x85, 0x8c, 0x4f, 0xa6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.8", + /* Message */ + 1, + { 0x5b } +, + /* Seed */ + 125, + { 0x42, 0xb9, 0x99, 0xfb, 0x16, 0x3a, 0x6f, 0xfa, 0x67, 0xa9, 0xbc, 0x4e, 0x6b, 0xa1, 0x2f, 0x81, 0xb1, 0xd5, 0x6e, 0x54, 0xbf, 0x08, 0x66, 0x39, 0x7f, 0xd3, 0x14, 0xeb, 0x0c, 0xf9, 0x7f, 0x13, 0xb7, 0x80, 0x4f, 0x76, 0x8f, 0xba, 0x54, 0x06, 0x21, 0xf0, 0x5c, 0xd3, 0x72, 0x64, 0xd8, 0xe8, 0xf5, 0x82, 0x28, 0xfb, 0x6a, 0xb3, 0x0e, 0xf5, 0x4e, 0x30, 0xfa, 0x8c, 0xfc, 0xb5, 0xa8, 0x7e, 0x14, 0x8f, 0xba, 0xbf, 0x85, 0x88, 0x6a, 0xb1, 0xf0, 0xd5, 0x25, 0x49, 0x2f, 0x56, 0xc6, 0x47, 0xf7, 0x22, 0x9b, 0x2b, 0xf3, 0x94, 0xa0, 0xce, 0xab, 0xbd, 0x37, 0xc9, 0x3e, 0x6d, 0xa8, 0x09, 0x7e, 0x82, 0x72, 0x7b, 0x3d, 0x53, 0xe8, 0xc2, 0xad, 0x1f, 0x77, 0x13, 0xe3, 0x4e, 0xd1, 0x3b, 0xa5, 0x9e, 0x0a, 0x91, 0x4d, 0xb0, 0x6f, 0xaa, 0xe4, 0x9c, 0xb3, 0x79, 0x96 } +, + /* Encryption */ + 129, + { 0x00, 0x90, 0xe5, 0x35, 0x59, 0x47, 0x90, 0x2b, 0xc3, 0xfb, 0x58, 0x0a, 0x84, 0x77, 0x09, 0x03, 0xa3, 0x95, 0x5b, 0x3d, 0xd7, 0x19, 0x1c, 0x92, 0x8f, 0x74, 0x07, 0xba, 0x74, 0x72, 0x65, 0xdc, 0x8c, 0xbc, 0x1d, 0x22, 0xf9, 0x37, 0x72, 0x72, 0xb1, 0xa8, 0xc3, 0x5c, 0x23, 0x8f, 0x04, 0xa1, 0x19, 0x37, 0xd1, 0xb4, 0x35, 0x4f, 0x64, 0x37, 0x95, 0xe9, 0x86, 0xde, 0xe2, 0xe4, 0x0a, 0x40, 0x67, 0x41, 0xb0, 0x21, 0xfd, 0xf0, 0x5c, 0x4b, 0xa1, 0x15, 0x62, 0xe8, 0x3e, 0x9f, 0x28, 0x59, 0x2e, 0x0a, 0x79, 0x14, 0xfe, 0x88, 0xb2, 0xc0, 0xfe, 0x7a, 0x5e, 0xea, 0xf5, 0x00, 0xf7, 0xe9, 0x8a, 0x5b, 0xa9, 0x54, 0xf7, 0x50, 0x77, 0xbc, 0x8f, 0x65, 0x9f, 0x21, 0xbb, 0x22, 0x03, 0x31, 0x4b, 0xe0, 0xd6, 0xd2, 0x1e, 0x63, 0x20, 0xc0, 0x5e, 0x6e, 0x2d, 0x55, 0x79, 0x79, 0x22, 0x6b, 0x80 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.9", + /* Message */ + 50, + { 0xf6, 0x35, 0x29, 0x90, 0x13, 0x24, 0xa2, 0x0f, 0xe5, 0xe9, 0x25, 0x8a, 0xda, 0x2f, 0x95, 0x37, 0xb0, 0x1f, 0x58, 0x39, 0xb4, 0x45, 0x97, 0xe3, 0x29, 0x3a, 0x12, 0x25, 0xca, 0x3a, 0x2a, 0xdf, 0x68, 0x4a, 0x72, 0xa7, 0x93, 0xc6, 0x9c, 0x56, 0xaf, 0x2d, 0x34, 0x98, 0xd3, 0x2a, 0x09, 0x2e, 0x91, 0x4b } +, + /* Seed */ + 76, + { 0x7b, 0xfa, 0x85, 0x97, 0xa4, 0x34, 0xcd, 0xad, 0xfe, 0x15, 0x63, 0x14, 0x44, 0x95, 0x13, 0xd7, 0x6c, 0x10, 0x5d, 0xf1, 0xbf, 0xc4, 0x8c, 0x4d, 0x07, 0x6a, 0xbf, 0xc0, 0x5b, 0x5d, 0xda, 0x72, 0xe0, 0xdd, 0x15, 0xf9, 0xfe, 0x82, 0xa9, 0x95, 0x5b, 0xd5, 0x6d, 0x33, 0x43, 0xe7, 0xc6, 0xf2, 0x5a, 0x60, 0x74, 0x12, 0x07, 0xe7, 0x3a, 0x2d, 0x10, 0xbb, 0x95, 0xd1, 0xd7, 0x29, 0xa2, 0x27, 0x93, 0xe6, 0xc4, 0x55, 0xe9, 0x16, 0x23, 0x5a, 0x81, 0x16, 0x94, 0xdb } +, + /* Encryption */ + 129, + { 0x00, 0xad, 0xf4, 0x78, 0x74, 0x67, 0xea, 0xc2, 0xea, 0x61, 0xfe, 0x7e, 0xf8, 0x2f, 0xd8, 0x7c, 0x2d, 0xa5, 0x89, 0x9f, 0x30, 0x30, 0x2b, 0xbc, 0x11, 0x27, 0x86, 0xd2, 0xfb, 0x11, 0xc1, 0x42, 0xf3, 0xf1, 0xd8, 0xcf, 0x37, 0x16, 0x0d, 0x2e, 0x4a, 0x43, 0x98, 0x3f, 0xfb, 0xd3, 0x93, 0xa4, 0x1b, 0x59, 0x9e, 0xe6, 0xa2, 0x7e, 0x24, 0x64, 0x25, 0x50, 0x2d, 0x46, 0x90, 0x20, 0x2f, 0xe5, 0xf8, 0xee, 0x1b, 0xc6, 0xc1, 0xd5, 0xd1, 0x6b, 0xe2, 0x3b, 0x97, 0x3a, 0xed, 0xf7, 0xf9, 0x11, 0x1b, 0xd8, 0xb1, 0x42, 0x84, 0x42, 0x65, 0xfd, 0x93, 0x57, 0x7a, 0x43, 0xc3, 0xac, 0xc6, 0xe2, 0xaf, 0x20, 0x89, 0xd9, 0xd2, 0xf3, 0xf3, 0x1a, 0x5c, 0x24, 0x7a, 0x7b, 0x68, 0x31, 0x5b, 0xae, 0x25, 0xd5, 0xae, 0x81, 0x40, 0xa5, 0x1f, 0xfc, 0x00, 0x97, 0x10, 0x7e, 0xc1, 0x62, 0x0a, 0xb3, 0xb5 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.10", + /* Message */ + 32, + { 0xc6, 0xd1, 0x4b, 0x04, 0x71, 0x45, 0xf3, 0x17, 0x78, 0x1d, 0xd7, 0x38, 0x2d, 0xc0, 0xa9, 0x72, 0x57, 0xd5, 0x54, 0xbb, 0x53, 0x53, 0x9e, 0xe9, 0xa2, 0x92, 0xe7, 0xda, 0x5c, 0xb6, 0x42, 0x6f } +, + /* Seed */ + 94, + { 0x01, 0xff, 0x38, 0xd5, 0xde, 0xd6, 0xc4, 0x3d, 0xc1, 0xdc, 0x5c, 0x27, 0xa7, 0xe4, 0x81, 0x3f, 0x44, 0x8f, 0x45, 0xc9, 0x6e, 0xdf, 0x4b, 0xd9, 0x3e, 0x96, 0xfa, 0xda, 0x9b, 0xc8, 0xec, 0x5b, 0x43, 0x4f, 0x06, 0x19, 0xa3, 0x8e, 0x04, 0x35, 0x6e, 0x06, 0x27, 0x85, 0x51, 0x40, 0x7b, 0x7f, 0x37, 0xe4, 0x2d, 0x91, 0x45, 0x62, 0x0a, 0x81, 0x98, 0x18, 0x50, 0xa4, 0x9e, 0x28, 0x51, 0x17, 0x2d, 0x23, 0x0b, 0x37, 0x82, 0x41, 0x10, 0xf8, 0xff, 0xdb, 0x84, 0x77, 0x94, 0x63, 0x9d, 0x26, 0x50, 0xcb, 0xed, 0x36, 0x26, 0x01, 0x05, 0xf1, 0xf1, 0x29, 0x6e, 0x52, 0xa7, 0xd4 } +, + /* Encryption */ + 129, + { 0x00, 0x5e, 0xdc, 0x93, 0x97, 0x89, 0xcf, 0xbf, 0xaa, 0xff, 0x28, 0x2b, 0xaf, 0x97, 0x01, 0xd6, 0x1f, 0x9d, 0xbe, 0xe6, 0xf2, 0xd2, 0x06, 0xcf, 0xab, 0x77, 0x57, 0x61, 0xf4, 0x2c, 0xb2, 0x74, 0xec, 0xba, 0x31, 0xc7, 0xcd, 0x2f, 0xe6, 0x03, 0x1a, 0xba, 0x0b, 0x84, 0xd4, 0x62, 0x7d, 0x30, 0x37, 0xe3, 0x1c, 0xe7, 0xe1, 0x56, 0x23, 0xba, 0x7c, 0xb7, 0x69, 0x02, 0x51, 0xc0, 0x63, 0x27, 0xa4, 0x31, 0x37, 0x12, 0x98, 0xdf, 0x29, 0x21, 0x95, 0xb6, 0x45, 0x11, 0x62, 0xd2, 0xda, 0x92, 0xa7, 0x07, 0x8e, 0x2d, 0x07, 0xc9, 0xf5, 0x6a, 0x07, 0x06, 0x8a, 0x9a, 0x3e, 0x17, 0x3e, 0x4a, 0xae, 0x25, 0xa5, 0xd1, 0xc6, 0x8e, 0x68, 0x20, 0x8c, 0xb5, 0x25, 0x3a, 0x0a, 0x53, 0xaa, 0x6e, 0x2e, 0xf6, 0xc2, 0x95, 0xd1, 0x51, 0x65, 0x69, 0xb8, 0x62, 0xcb, 0x92, 0xca, 0x82, 0x3c, 0xcb, 0xab } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.11", + /* Message */ + 63, + { 0xc1, 0x16, 0x53, 0xe8, 0x10, 0xb5, 0x3e, 0x65, 0x11, 0xf1, 0x33, 0x23, 0xfe, 0x52, 0x26, 0xa1, 0x70, 0xc2, 0x1f, 0x6d, 0xaa, 0x44, 0x29, 0xd9, 0x68, 0xef, 0xda, 0x05, 0x29, 0xd7, 0xb6, 0xe1, 0x0d, 0xce, 0xd8, 0x0c, 0x6b, 0x63, 0x01, 0xde, 0xd2, 0x2f, 0x52, 0x91, 0x1c, 0x0f, 0x7f, 0xf4, 0x53, 0x5b, 0xd5, 0xe2, 0x0f, 0xf5, 0x35, 0x88, 0xcd, 0x3d, 0xe6, 0x64, 0x8a, 0xc0, 0x2d } +, + /* Seed */ + 63, + { 0x85, 0xfa, 0x7c, 0x6c, 0xe9, 0x6d, 0x0a, 0x8a, 0x1f, 0xba, 0x75, 0x04, 0x71, 0x7c, 0xcb, 0xe1, 0x37, 0x13, 0x80, 0x93, 0x95, 0x6e, 0xff, 0x06, 0x3f, 0xc2, 0xef, 0xd4, 0xa4, 0x6d, 0x7d, 0xc7, 0x4e, 0x90, 0xf1, 0xda, 0x9e, 0x43, 0xdb, 0xa9, 0x12, 0x9f, 0x14, 0xec, 0x55, 0x9a, 0x4d, 0x2d, 0x6c, 0x5a, 0x19, 0xcb, 0xf3, 0xa6, 0x8c, 0x62, 0xd0, 0x98, 0x34, 0x52, 0xa9, 0xee, 0x0c } +, + /* Encryption */ + 129, + { 0x01, 0xb0, 0x8d, 0x49, 0x83, 0x13, 0xa7, 0xd7, 0x4a, 0x05, 0x53, 0x14, 0xeb, 0x43, 0x15, 0xba, 0x02, 0x87, 0x60, 0xda, 0xd4, 0x11, 0x14, 0xd5, 0x94, 0x2d, 0x63, 0xbf, 0x8d, 0x27, 0xbe, 0x3f, 0x49, 0xcc, 0xd9, 0x4a, 0xcf, 0x9d, 0x3a, 0xa2, 0x2d, 0x09, 0xb9, 0x9b, 0xf9, 0x74, 0x09, 0xbc, 0xf3, 0x32, 0x13, 0xc0, 0x99, 0x67, 0x07, 0x86, 0x82, 0x03, 0xa9, 0xab, 0x27, 0x70, 0x8d, 0x3f, 0xff, 0x69, 0xb8, 0x9d, 0x02, 0xe3, 0x6e, 0x01, 0x21, 0xa1, 0x19, 0xb8, 0xd4, 0xd9, 0xbf, 0xd4, 0xfe, 0x8b, 0x16, 0x8f, 0xd7, 0xc1, 0x2a, 0x24, 0x3f, 0x7a, 0x00, 0x0b, 0x39, 0xbf, 0x8d, 0x56, 0x48, 0x17, 0x24, 0x20, 0x80, 0x23, 0xbb, 0x60, 0x7b, 0x30, 0x50, 0x5d, 0xd1, 0x74, 0x2f, 0x87, 0x9f, 0x16, 0xc1, 0x0c, 0xe4, 0x90, 0xd3, 0x4a, 0x68, 0x0d, 0x27, 0xac, 0x39, 0x60, 0x7d, 0xa2, 0x4e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.12", + /* Message */ + 50, + { 0x09, 0x5b, 0x77, 0xc9, 0x4d, 0xc1, 0xb1, 0x87, 0x88, 0xe4, 0x00, 0xe6, 0x91, 0x6a, 0x4b, 0x4c, 0xfd, 0x73, 0xac, 0xe0, 0xdf, 0x9a, 0x3a, 0xc1, 0x31, 0xbd, 0xf9, 0xad, 0x0a, 0x12, 0xdb, 0x76, 0x6d, 0xeb, 0x22, 0x53, 0x59, 0xd9, 0x01, 0xcd, 0x56, 0xed, 0x88, 0xcd, 0xa3, 0xd3, 0x28, 0x56, 0x54, 0x02 } +, + /* Seed */ + 76, + { 0xa3, 0x4a, 0x68, 0x05, 0x55, 0x71, 0x09, 0xc2, 0x61, 0xdd, 0xdf, 0x5f, 0x85, 0xd3, 0x71, 0xae, 0x65, 0x20, 0xf4, 0x5a, 0xdf, 0x46, 0x96, 0x01, 0xb5, 0xc3, 0x59, 0xfe, 0xc7, 0x44, 0xcb, 0x2a, 0xae, 0x80, 0x98, 0x3c, 0x73, 0x2d, 0xb6, 0xc5, 0x45, 0xdf, 0x55, 0xe0, 0x20, 0x8a, 0xcf, 0xbb, 0xf1, 0xc2, 0xc5, 0xe7, 0x99, 0x88, 0xf3, 0x4e, 0xcd, 0x6e, 0x5b, 0xb4, 0xb5, 0x25, 0xc1, 0xb8, 0xbc, 0xb0, 0x70, 0xd0, 0xd8, 0x42, 0x48, 0xb1, 0xf8, 0xe7, 0x48, 0x0e } +, + /* Encryption */ + 129, + { 0x00, 0x39, 0x56, 0x36, 0xa8, 0x26, 0x67, 0xdc, 0xf0, 0x0d, 0x5d, 0xbd, 0xd8, 0x54, 0x12, 0x06, 0x94, 0x8d, 0x49, 0x36, 0x89, 0x17, 0xec, 0x0e, 0x00, 0xfd, 0x7a, 0xc5, 0xca, 0x8b, 0xf4, 0x4e, 0xc5, 0x83, 0x78, 0x38, 0x6e, 0x59, 0x4b, 0xc0, 0x65, 0xa9, 0xa6, 0x3c, 0xf2, 0xa3, 0x55, 0xa6, 0x08, 0xb6, 0xf0, 0xba, 0xcb, 0xa5, 0x60, 0x08, 0xbb, 0xa4, 0x72, 0x2a, 0x7c, 0x47, 0x05, 0x45, 0xa2, 0x0f, 0x38, 0x78, 0x53, 0xd4, 0x60, 0x31, 0x3b, 0x2e, 0x86, 0x4e, 0x17, 0xb2, 0x33, 0xe5, 0x96, 0x35, 0x41, 0x32, 0xaf, 0x17, 0x3b, 0x4d, 0x04, 0x49, 0x26, 0x47, 0x79, 0x02, 0x62, 0xd3, 0xa4, 0x3f, 0x84, 0x27, 0x37, 0x88, 0x37, 0x46, 0x6b, 0x06, 0x73, 0xa8, 0x15, 0x27, 0xe6, 0xbe, 0x10, 0x45, 0x80, 0x32, 0x6f, 0xec, 0x84, 0xba, 0x37, 0x1e, 0xa6, 0x10, 0x91, 0xfa, 0x40, 0x33, 0xa4 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.13", + /* Message */ + 1, + { 0x38 } +, + /* Seed */ + 125, + { 0x54, 0x7c, 0x91, 0x75, 0x19, 0x05, 0xd5, 0xa2, 0x84, 0xac, 0x3f, 0xe4, 0x32, 0xcb, 0xe0, 0x30, 0x55, 0xb2, 0x85, 0x06, 0x58, 0x96, 0x11, 0x0e, 0xa3, 0x6d, 0x05, 0xa1, 0x40, 0x08, 0x3c, 0xe3, 0x95, 0x5f, 0xa8, 0x28, 0x41, 0xea, 0xf6, 0xdb, 0x4a, 0x50, 0xd1, 0x2c, 0x07, 0x4f, 0x45, 0xa6, 0x88, 0xb5, 0x57, 0x6d, 0x6e, 0x61, 0x68, 0x07, 0x54, 0x0a, 0xc1, 0x17, 0x58, 0x5c, 0x5b, 0xc3, 0xbe, 0x52, 0x60, 0x72, 0x7c, 0xdf, 0x12, 0x3c, 0x77, 0x4d, 0xb4, 0x0c, 0xff, 0x29, 0x70, 0x88, 0x62, 0x48, 0x53, 0xe4, 0x69, 0x51, 0x36, 0xb9, 0x31, 0x16, 0x15, 0x17, 0xa7, 0xb9, 0xb5, 0xdd, 0xcd, 0x9d, 0x32, 0xde, 0x3d, 0xfe, 0x3e, 0xe2, 0xea, 0x68, 0x8c, 0xf7, 0xbf, 0x88, 0x2c, 0xcf, 0x7b, 0x9c, 0x48, 0xd5, 0xe1, 0x9e, 0xff, 0xa6, 0x50, 0x4a, 0x42, 0x62, 0x0b } +, + /* Encryption */ + 129, + { 0x00, 0x89, 0xe3, 0x9d, 0xcf, 0xdf, 0x91, 0x69, 0x3d, 0xef, 0xe3, 0x9d, 0x12, 0xbb, 0x25, 0xf8, 0x0a, 0x76, 0x8d, 0x44, 0x1b, 0x48, 0x1d, 0x6a, 0x75, 0x48, 0x69, 0x50, 0x42, 0x48, 0x0c, 0xd4, 0xa0, 0xba, 0x97, 0x83, 0xd5, 0xc5, 0xbd, 0x38, 0x89, 0x6d, 0xce, 0x06, 0xac, 0xb1, 0x77, 0xa4, 0xac, 0x59, 0x68, 0xe6, 0x55, 0xa7, 0xaa, 0xf5, 0x0d, 0x69, 0x4a, 0x64, 0x97, 0x13, 0xb7, 0xa4, 0xbd, 0xd1, 0x4c, 0x81, 0x9f, 0x83, 0xb2, 0x04, 0x7d, 0xe2, 0x19, 0x5f, 0x73, 0x03, 0x66, 0x54, 0x53, 0xa8, 0xa1, 0x11, 0x5e, 0x5b, 0x48, 0xac, 0x0e, 0x9a, 0x65, 0xed, 0xdb, 0x31, 0x89, 0x51, 0x7b, 0x04, 0x6f, 0xcb, 0xc2, 0xd1, 0x43, 0x81, 0x77, 0x6a, 0x77, 0xfb, 0x46, 0x8e, 0x11, 0x29, 0x3c, 0x78, 0xc8, 0x37, 0x4c, 0x8f, 0x46, 0x60, 0x35, 0x1a, 0xc2, 0xb2, 0xc7, 0x84, 0x5a, 0x25, 0xfe } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.14", + /* Message */ + 42, + { 0x80, 0x64, 0x6b, 0x3c, 0x4d, 0xf0, 0xeb, 0x79, 0x1b, 0xda, 0x0c, 0xcc, 0x4d, 0x97, 0xd8, 0x1e, 0xa8, 0xf6, 0xf7, 0x4e, 0xb2, 0x45, 0xe2, 0xc7, 0xc3, 0x48, 0xfd, 0x7f, 0xb9, 0x90, 0x16, 0xa9, 0xd4, 0x0a, 0x60, 0x5a, 0xc7, 0x42, 0xb2, 0x7a, 0xd2, 0x48 } +, + /* Seed */ + 84, + { 0x11, 0xb8, 0xe7, 0x98, 0xd7, 0xa1, 0x42, 0xd0, 0x82, 0xe0, 0x59, 0x8a, 0x8c, 0xb4, 0xf8, 0xc2, 0xaa, 0x87, 0x5d, 0x5b, 0x65, 0x17, 0x8c, 0x4e, 0xe6, 0x7a, 0x5c, 0xb8, 0x41, 0xd1, 0xcd, 0xa3, 0x04, 0x31, 0xd0, 0x20, 0xdf, 0x28, 0x80, 0xd7, 0x93, 0x58, 0x15, 0xd5, 0x9d, 0x91, 0xb9, 0x99, 0x3e, 0x53, 0xac, 0x34, 0x1c, 0x97, 0x28, 0x61, 0xea, 0xa2, 0x66, 0x97, 0xcf, 0x10, 0xca, 0x8b, 0x27, 0x94, 0xb4, 0x53, 0x03, 0xbe, 0x03, 0x48, 0x9e, 0xbe, 0x07, 0x4d, 0x8f, 0x23, 0x98, 0x54, 0xc3, 0xa6, 0x06, 0xfb } +, + /* Encryption */ + 129, + { 0x01, 0xf1, 0xe5, 0xa3, 0xdb, 0xd8, 0x24, 0x75, 0x2d, 0x2f, 0xba, 0x3c, 0x32, 0x42, 0xe9, 0xd9, 0x96, 0xe6, 0x27, 0x43, 0x0d, 0x49, 0x3e, 0x1b, 0x44, 0x6a, 0x2d, 0xbc, 0xd8, 0x6a, 0x48, 0x09, 0x3e, 0x37, 0xa2, 0xe1, 0x28, 0xb2, 0x8c, 0x49, 0xd2, 0xd1, 0x72, 0xbf, 0x5a, 0x97, 0x7c, 0x36, 0x9b, 0xaa, 0x9f, 0xfb, 0x83, 0x9b, 0xd2, 0xfd, 0xf0, 0x0b, 0xd3, 0x0f, 0xf5, 0x22, 0x8b, 0x57, 0x6b, 0x94, 0xe6, 0xd8, 0xec, 0xf9, 0x44, 0x24, 0x7a, 0xda, 0xd0, 0x19, 0xf2, 0x1d, 0x06, 0xfb, 0xe4, 0x18, 0xd3, 0xa6, 0xd5, 0x4c, 0xdf, 0x11, 0x3e, 0x8d, 0x14, 0xf6, 0xea, 0x06, 0xd8, 0xdb, 0x79, 0x64, 0x93, 0xbc, 0xb1, 0x89, 0x6f, 0xc4, 0xf3, 0xf3, 0x03, 0x86, 0xc5, 0xc8, 0xba, 0xb7, 0x03, 0x7c, 0x87, 0x9a, 0xfe, 0xa4, 0x7c, 0x8f, 0xb7, 0xa3, 0xc5, 0xb5, 0x0b, 0x29, 0x18, 0x66, 0xb9 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.15", + /* Message */ + 9, + { 0x6b, 0x63, 0x1c, 0x7c, 0x35, 0xea, 0x75, 0xa1, 0xb0 } +, + /* Seed */ + 117, + { 0x3e, 0x42, 0x40, 0xc3, 0xe0, 0x9e, 0xa7, 0x83, 0x55, 0x35, 0x8c, 0xda, 0x61, 0x29, 0x53, 0x47, 0x30, 0xf4, 0x8a, 0x9c, 0x9a, 0x1a, 0x52, 0x13, 0x28, 0x4b, 0xfd, 0x07, 0x71, 0x21, 0x6a, 0xd4, 0xca, 0x23, 0x3d, 0x99, 0x3e, 0xe6, 0x35, 0x7f, 0x4b, 0x1b, 0x12, 0xa6, 0xba, 0xa1, 0x77, 0x43, 0x13, 0x4a, 0x85, 0x7f, 0xd7, 0x69, 0xa8, 0xbc, 0x78, 0xd6, 0x1f, 0xb1, 0x4f, 0xea, 0x05, 0x22, 0x1d, 0xcf, 0x5a, 0xeb, 0x1a, 0xff, 0xd4, 0x0d, 0x8b, 0xc6, 0x94, 0x5c, 0x30, 0x10, 0x45, 0xb6, 0x86, 0xc6, 0x11, 0xfa, 0x43, 0x7e, 0x30, 0xca, 0x0f, 0xab, 0x5a, 0x4c, 0xde, 0xf5, 0x20, 0x5b, 0xaf, 0x99, 0x26, 0xc6, 0x07, 0xbe, 0x96, 0x37, 0xb1, 0x50, 0x7f, 0x50, 0x83, 0xe9, 0x40, 0xcc, 0xfa, 0x2f, 0xb3, 0x86, 0x19 } +, + /* Encryption */ + 129, + { 0x00, 0x47, 0xcb, 0x9a, 0x91, 0x98, 0xd9, 0x83, 0xb3, 0x22, 0x24, 0xcf, 0x27, 0xfc, 0x72, 0x99, 0xbb, 0xd4, 0xae, 0x07, 0x78, 0xa8, 0x3f, 0xc5, 0x9c, 0x47, 0x45, 0xfa, 0x99, 0xe9, 0x17, 0xbb, 0x74, 0xf8, 0xbd, 0x4e, 0xf1, 0x3f, 0x14, 0x0c, 0xa9, 0xb7, 0x2e, 0x2a, 0xa1, 0x74, 0xce, 0xea, 0x26, 0x48, 0x94, 0xe2, 0x15, 0xf4, 0x1c, 0x36, 0xd4, 0xe6, 0xf3, 0x46, 0xf6, 0x9b, 0x4f, 0x85, 0x50, 0x5c, 0x54, 0xcd, 0x46, 0x25, 0x9c, 0x71, 0x2e, 0x30, 0xc4, 0x92, 0x94, 0xba, 0xdb, 0x1c, 0x47, 0x16, 0x85, 0x1f, 0x2b, 0x75, 0xe3, 0x96, 0x12, 0xcd, 0x54, 0x66, 0xba, 0x56, 0xe3, 0xf3, 0x15, 0x99, 0xc2, 0xdc, 0xe2, 0x3d, 0x04, 0xc9, 0x3a, 0x64, 0x40, 0x22, 0x27, 0xdf, 0x40, 0xb5, 0x14, 0xc7, 0x4d, 0x0a, 0xa3, 0x6e, 0x1e, 0x86, 0x58, 0xe2, 0x92, 0x77, 0xb3, 0x05, 0xaf, 0x35, 0x15 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.16", + /* Message */ + 53, + { 0x40, 0x08, 0x55, 0xda, 0x54, 0xa6, 0xd1, 0xfe, 0x5f, 0xb5, 0x8a, 0x73, 0xd2, 0xa5, 0xe5, 0x58, 0x38, 0x70, 0xfb, 0xd5, 0x25, 0xd2, 0xf5, 0x72, 0xad, 0xb5, 0x96, 0x30, 0x06, 0xd0, 0xa1, 0x33, 0x9b, 0xea, 0x88, 0x9d, 0x6d, 0x46, 0xa4, 0x37, 0x62, 0xf5, 0x13, 0xbb, 0x7c, 0xc0, 0x36, 0x22, 0xbf, 0x85, 0x92, 0x44, 0xd6 } +, + /* Seed */ + 73, + { 0x49, 0x6e, 0x50, 0xba, 0xb5, 0xef, 0x18, 0xf2, 0x2c, 0x3f, 0x62, 0xb9, 0x21, 0x14, 0x8d, 0x36, 0xc1, 0x01, 0xad, 0x0a, 0x9a, 0x20, 0x38, 0x67, 0x58, 0x08, 0xce, 0x8b, 0x62, 0xf8, 0xa6, 0xa0, 0xba, 0x8d, 0x91, 0x05, 0xf9, 0x2e, 0xd8, 0xa0, 0x2b, 0x31, 0x2f, 0x32, 0x4f, 0x3f, 0xd3, 0x91, 0x92, 0xbd, 0x41, 0x53, 0x78, 0x4f, 0xb5, 0x59, 0x05, 0xc3, 0xb6, 0x69, 0x30, 0x7b, 0xad, 0xa8, 0x27, 0xaf, 0xa1, 0xb5, 0xcb, 0x3d, 0xc1, 0x1d, 0xc4 } +, + /* Encryption */ + 129, + { 0x00, 0xd3, 0xa8, 0x5d, 0xec, 0x97, 0xd3, 0x44, 0x88, 0xee, 0x33, 0xc6, 0x58, 0xba, 0x18, 0x8e, 0x64, 0xcb, 0x57, 0x83, 0x7d, 0x2e, 0xdd, 0xbc, 0xba, 0x8e, 0xe5, 0x2f, 0x13, 0xf1, 0xe4, 0xfe, 0x9b, 0xec, 0x2f, 0x92, 0xe7, 0x21, 0x09, 0x87, 0xe1, 0xc3, 0xfe, 0x34, 0x5d, 0x40, 0x19, 0x77, 0x0b, 0x07, 0x74, 0x94, 0x51, 0xb0, 0x4d, 0x67, 0x30, 0xd5, 0x3a, 0x91, 0x01, 0x5b, 0x25, 0x7e, 0x81, 0x0d, 0xae, 0x0a, 0x0c, 0x11, 0x6a, 0x4f, 0x22, 0x45, 0x14, 0xed, 0xbd, 0x39, 0xb2, 0xc6, 0x5e, 0x15, 0x2d, 0x3b, 0x97, 0x89, 0xdd, 0xa4, 0xf0, 0xd4, 0x5b, 0xf9, 0x83, 0x2d, 0x27, 0x9d, 0x34, 0x31, 0x06, 0x2b, 0x4d, 0xe1, 0xb0, 0x67, 0x7e, 0xf5, 0x9c, 0x6c, 0x33, 0x27, 0x68, 0xec, 0xda, 0x3a, 0xa6, 0xbc, 0xd1, 0x0f, 0x70, 0xbd, 0x06, 0x03, 0x0a, 0x76, 0x65, 0xed, 0x3f, 0x20, 0x79 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.17", + /* Message */ + 48, + { 0xb8, 0x7e, 0xdb, 0x45, 0x5a, 0x7e, 0x85, 0x53, 0x9f, 0x92, 0x8e, 0xda, 0xe9, 0x09, 0xfb, 0xf8, 0xf7, 0xa1, 0x99, 0xc0, 0x3a, 0x94, 0xa9, 0xa4, 0x5a, 0xca, 0xb2, 0x5e, 0xfa, 0xee, 0xcc, 0x26, 0x29, 0x74, 0xca, 0xe0, 0xbb, 0x72, 0x24, 0x3a, 0x99, 0xc6, 0x47, 0x20, 0x79, 0xf1, 0x97, 0x38 } +, + /* Seed */ + 78, + { 0x03, 0x5e, 0x31, 0x59, 0x4a, 0x56, 0x65, 0x60, 0x5b, 0x84, 0xfe, 0xc9, 0x3a, 0xdf, 0x92, 0x58, 0x50, 0x85, 0x1d, 0xf7, 0xb3, 0x94, 0xe9, 0xbb, 0xec, 0xbe, 0x4d, 0x72, 0xc9, 0x2f, 0x27, 0x03, 0xb6, 0xd6, 0x08, 0x96, 0xe0, 0x05, 0x4c, 0x59, 0xca, 0xfa, 0x5e, 0x0d, 0x28, 0x6c, 0x81, 0x2b, 0x23, 0xe5, 0x37, 0x88, 0x5e, 0x4c, 0x34, 0x38, 0xa7, 0x72, 0xa1, 0x61, 0x0a, 0xe9, 0xfa, 0xe9, 0x18, 0xe3, 0x4d, 0x49, 0x92, 0xc7, 0xf2, 0x63, 0xf3, 0xe8, 0xe2, 0xf9, 0x80, 0xb8 } +, + /* Encryption */ + 129, + { 0x02, 0x1c, 0x8c, 0x95, 0x9a, 0xec, 0x47, 0x29, 0x68, 0x87, 0x68, 0x93, 0x0d, 0x67, 0xe2, 0x02, 0x99, 0xdd, 0x47, 0x90, 0x2d, 0xb0, 0x79, 0xf2, 0x39, 0xb8, 0xc2, 0x88, 0xb0, 0xa7, 0x04, 0x47, 0xc7, 0x19, 0x6b, 0x84, 0x91, 0x2e, 0xaa, 0x5b, 0xc3, 0xaf, 0xf6, 0xba, 0x63, 0x0c, 0x2e, 0xaa, 0x3f, 0xcb, 0xb2, 0x4b, 0xe4, 0x63, 0x83, 0x65, 0x31, 0x25, 0x0b, 0xd4, 0xc4, 0xf2, 0xa1, 0xda, 0x68, 0xc8, 0xbf, 0x4f, 0x40, 0xcf, 0x5c, 0x98, 0xb6, 0x85, 0xeb, 0xec, 0xa4, 0xd0, 0x3e, 0x76, 0xb3, 0x34, 0xaf, 0x0b, 0x1b, 0x34, 0x48, 0x8b, 0x58, 0x2e, 0x29, 0x35, 0x25, 0x35, 0x72, 0xf7, 0xfc, 0xfa, 0xa8, 0x35, 0x44, 0xe7, 0xfd, 0x52, 0xef, 0x45, 0x8a, 0xcc, 0xcb, 0x19, 0x30, 0x1a, 0x4d, 0xdd, 0x50, 0x51, 0x6f, 0x16, 0xa5, 0xfb, 0x78, 0xf3, 0x95, 0x99, 0x00, 0xdb, 0xcc, 0xa1, 0xf2 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.18", + /* Message */ + 38, + { 0x30, 0x2a, 0xc8, 0x0e, 0x30, 0xc6, 0x55, 0x3e, 0x93, 0x59, 0xdf, 0x85, 0xb1, 0xe2, 0x4a, 0x16, 0xc8, 0x62, 0xa2, 0x0f, 0xf4, 0xfd, 0x9d, 0x5f, 0x14, 0x6b, 0xe2, 0x81, 0xdc, 0x30, 0x66, 0xae, 0xb8, 0xfa, 0x00, 0xb5, 0x2a, 0x99 } +, + /* Seed */ + 88, + { 0x32, 0x6c, 0x99, 0x35, 0x8c, 0x4e, 0x5f, 0xa4, 0xd2, 0xc0, 0x43, 0xf0, 0x2f, 0x92, 0x70, 0x5f, 0x79, 0x1c, 0xf7, 0x12, 0xbc, 0x01, 0x04, 0x5b, 0x4c, 0xf3, 0x49, 0xb4, 0x2a, 0xe5, 0xac, 0xfa, 0xc3, 0x78, 0x38, 0x11, 0xbb, 0xf0, 0x7f, 0x34, 0xbd, 0x6c, 0x85, 0x19, 0x55, 0xcb, 0xa4, 0xa8, 0xb2, 0xa7, 0xd1, 0x39, 0xa7, 0x8b, 0xc4, 0xd8, 0x8e, 0x3a, 0x88, 0xe6, 0xc4, 0xcf, 0x49, 0x4e, 0x6a, 0x4a, 0x52, 0x35, 0x41, 0x45, 0xe1, 0x18, 0x83, 0xcb, 0x5c, 0x78, 0xb5, 0x72, 0xf3, 0x0a, 0x51, 0xed, 0x23, 0xf2, 0x56, 0x4b, 0x69, 0x60 } +, + /* Encryption */ + 129, + { 0x02, 0x03, 0x29, 0x87, 0xcc, 0xf7, 0x5a, 0x63, 0x86, 0x24, 0x17, 0x80, 0x64, 0xdb, 0xa4, 0xb7, 0x2b, 0xe5, 0x39, 0xe0, 0x7e, 0xcd, 0xf5, 0x30, 0x03, 0x56, 0xcc, 0x43, 0xd7, 0x29, 0xfe, 0x34, 0xfb, 0x35, 0xbb, 0xbf, 0x5a, 0x32, 0x17, 0x2c, 0xe3, 0x9e, 0xa1, 0xfb, 0x47, 0xd3, 0x8e, 0x49, 0x7a, 0x03, 0xb6, 0x01, 0xee, 0xaf, 0xda, 0xaf, 0x99, 0xa3, 0x4f, 0xd7, 0x21, 0x18, 0x4a, 0xf2, 0xe1, 0x8e, 0x83, 0xd0, 0x50, 0xa4, 0x10, 0x8b, 0x15, 0xe5, 0xe3, 0xa2, 0x7e, 0x0e, 0x63, 0x6d, 0xf8, 0xd9, 0x4f, 0x98, 0x16, 0x58, 0xeb, 0xde, 0xcd, 0xab, 0x0d, 0xef, 0xcc, 0x0d, 0xaf, 0x3a, 0xc9, 0xa2, 0x7b, 0x3f, 0x22, 0xa0, 0x54, 0x1d, 0x35, 0x00, 0x27, 0x52, 0xe9, 0xcc, 0x4f, 0xb2, 0x58, 0x2f, 0xae, 0x25, 0x11, 0xa1, 0x32, 0xec, 0x5c, 0x22, 0x8a, 0x88, 0x72, 0xbd, 0xba, 0xd6, 0x87 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.19", + /* Message */ + 43, + { 0x00, 0xb3, 0x82, 0x01, 0x74, 0x6d, 0xca, 0xf4, 0x03, 0x48, 0xaf, 0x57, 0xba, 0xd7, 0x25, 0x70, 0xca, 0xf5, 0xa2, 0x85, 0x5f, 0xec, 0x6c, 0x42, 0xee, 0x22, 0xdc, 0xfe, 0x64, 0xc9, 0x97, 0xec, 0x62, 0xa5, 0xc9, 0x75, 0x62, 0x4b, 0xbd, 0x1f, 0x8e, 0xc9, 0x16 } +, + /* Seed */ + 83, + { 0x93, 0x91, 0x05, 0xc0, 0x04, 0xc0, 0x1a, 0xa9, 0xf4, 0x74, 0x46, 0xd3, 0xcc, 0xf5, 0x30, 0xe9, 0xb2, 0x17, 0x4c, 0x50, 0xae, 0xbc, 0xa0, 0xa9, 0x5c, 0xb7, 0xa4, 0xd8, 0x39, 0x54, 0xef, 0xb8, 0x03, 0x9e, 0x59, 0x1c, 0x19, 0x71, 0xd7, 0x76, 0xce, 0xc7, 0x61, 0x12, 0x92, 0x06, 0xdb, 0x7a, 0xd3, 0xdd, 0x87, 0x16, 0x68, 0x25, 0x5a, 0x55, 0x50, 0xac, 0x4e, 0x94, 0x8b, 0xe0, 0x5c, 0x16, 0x22, 0x20, 0xdc, 0xef, 0xec, 0x13, 0xff, 0x1f, 0xd8, 0xa5, 0xa7, 0xf7, 0x8b, 0xf7, 0x15, 0xb4, 0x9d, 0x03, 0xba } +, + /* Encryption */ + 129, + { 0x01, 0x2b, 0xa8, 0x7d, 0xc0, 0x3a, 0x1a, 0x38, 0xbf, 0xed, 0xf1, 0x21, 0xed, 0x87, 0x22, 0x82, 0x7b, 0xd9, 0x7d, 0xd6, 0x3f, 0xdd, 0xfd, 0xd5, 0x90, 0x50, 0xc5, 0x3c, 0x5e, 0x7b, 0x49, 0xfb, 0x7a, 0xe6, 0x03, 0x84, 0x87, 0x82, 0x0e, 0xfd, 0x5f, 0xb9, 0x71, 0x43, 0x81, 0xce, 0x8d, 0xae, 0xb5, 0x6d, 0x13, 0x50, 0xbf, 0xc6, 0x7d, 0xf0, 0x91, 0xbe, 0xa2, 0xac, 0xdf, 0xfd, 0xe9, 0x29, 0x2a, 0xb1, 0x29, 0x1c, 0xc9, 0x75, 0x1d, 0x9e, 0x39, 0xa8, 0x26, 0xf0, 0x54, 0xad, 0x1f, 0x33, 0xa2, 0xb7, 0x94, 0xda, 0x50, 0xef, 0x80, 0x67, 0x29, 0x17, 0xe0, 0xb3, 0x81, 0x40, 0x45, 0xd2, 0x3d, 0xf4, 0x5d, 0xba, 0x3f, 0xdc, 0x6f, 0x09, 0xab, 0x0a, 0x01, 0x8b, 0x06, 0x0a, 0xa9, 0xfa, 0xfc, 0x3a, 0x5d, 0x19, 0xd5, 0xeb, 0x64, 0x31, 0x0b, 0xd6, 0x02, 0xa9, 0x91, 0x1d, 0xcb, 0x7f, 0x24 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 8.20", + /* Message */ + 26, + { 0xba, 0x28, 0x33, 0x66, 0x04, 0x76, 0xd8, 0x73, 0x15, 0x07, 0x66, 0x9f, 0x50, 0x29, 0x8c, 0x2c, 0x68, 0xd4, 0x4c, 0x53, 0xe3, 0xd0, 0xa8, 0x03, 0x78, 0x6e } +, + /* Seed */ + 100, + { 0x86, 0xce, 0x8e, 0x92, 0xad, 0x88, 0xb1, 0x46, 0x2a, 0x17, 0x1a, 0xf2, 0x8b, 0x4e, 0x99, 0x08, 0x8c, 0x04, 0x98, 0xa2, 0x9b, 0x4c, 0xa5, 0xe6, 0x6f, 0x64, 0xf8, 0x6a, 0xde, 0xc7, 0xf9, 0x64, 0xe8, 0xeb, 0x82, 0x57, 0xc5, 0xc0, 0x1c, 0xda, 0x16, 0x5e, 0x0f, 0x75, 0x11, 0xdb, 0x14, 0x7c, 0x10, 0xbc, 0x07, 0x51, 0x5f, 0x04, 0xf0, 0x5f, 0x52, 0xd2, 0xbc, 0x89, 0x22, 0x83, 0x57, 0xc6, 0x61, 0xb4, 0x3f, 0x43, 0xd5, 0x42, 0xdb, 0xe7, 0x78, 0x34, 0x09, 0x1c, 0x7c, 0xe7, 0x0b, 0x18, 0x2e, 0x19, 0xbc, 0x93, 0x6c, 0x30, 0x68, 0x4a, 0x83, 0x1e, 0x2c, 0x3b, 0x8a, 0x4a, 0x74, 0x46, 0x3f, 0x0c, 0x9f, 0x1b } +, + /* Encryption */ + 129, + { 0x01, 0x12, 0xac, 0x28, 0x98, 0xa2, 0x5c, 0x13, 0x28, 0x79, 0x1f, 0xc9, 0x6a, 0x82, 0xb7, 0x29, 0x18, 0xb5, 0x1a, 0x66, 0x8c, 0x54, 0x0b, 0xcf, 0xfc, 0x8e, 0x0b, 0x3a, 0xaf, 0xe2, 0x05, 0xee, 0x87, 0x1f, 0x5e, 0xb7, 0x6a, 0xd1, 0x16, 0xd3, 0x04, 0xcc, 0x04, 0x42, 0xbd, 0xb1, 0xaf, 0x5b, 0x9a, 0x63, 0x45, 0x82, 0x7e, 0x67, 0x8e, 0x40, 0xe3, 0x3f, 0xc8, 0x58, 0xef, 0x6c, 0x45, 0x6b, 0xe4, 0x36, 0x52, 0xbb, 0x2e, 0xbc, 0x39, 0x64, 0xb4, 0xbf, 0x4a, 0x93, 0xa8, 0xee, 0xef, 0x84, 0x04, 0xae, 0xf1, 0xa0, 0x44, 0x41, 0x5a, 0x15, 0x6f, 0x7c, 0xfd, 0x79, 0x95, 0xac, 0x25, 0xe7, 0xb0, 0x30, 0x26, 0x69, 0x8e, 0x14, 0x48, 0x9e, 0xfc, 0xc1, 0xae, 0x92, 0x96, 0x58, 0xbb, 0x66, 0x3d, 0xe0, 0xac, 0x44, 0xa7, 0xa5, 0x5c, 0xaa, 0x0b, 0x0b, 0x20, 0x34, 0xc2, 0xaa, 0xec, 0x13, 0x4e } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 9: A 1027-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x06, 0x8e, 0xf0, 0xb2, 0x74, 0x15, 0x7d, 0x7b, 0x5e, 0xc7, 0x29, 0x03, 0x86, 0x59, 0x56, 0x18, 0x3e, 0x0e, 0x34, 0x62, 0xec, 0xd2, 0x21, 0x14, 0xca, 0xd4, 0xc7, 0xba, 0xac, 0x94, 0xc7, 0xc2, 0xc5, 0xe6, 0xcb, 0xdf, 0xa2, 0xab, 0xfe, 0xaf, 0x8d, 0x23, 0x18, 0x2e, 0x9c, 0x08, 0x81, 0x5d, 0x10, 0x0d, 0x8e, 0x8f, 0x62, 0x1d, 0x3c, 0xd4, 0xaf, 0xbb, 0x99, 0x85, 0x96, 0x6f, 0xd6, 0xa4, 0x18, 0x2b, 0x59, 0x90, 0x88, 0xa3, 0x5d, 0x77, 0xfe, 0x01, 0x78, 0xac, 0xf7, 0x53, 0x1c, 0x70, 0xd8, 0x96, 0xff, 0x78, 0x8e, 0xdc, 0x82, 0x06, 0x05, 0x40, 0xef, 0xef, 0xd9, 0xf3, 0xc2, 0x4d, 0x5b, 0xe6, 0x9a, 0xf7, 0xf2, 0xf4, 0x44, 0x85, 0xb1, 0x91, 0x18, 0xa4, 0x68, 0x81, 0x4f, 0xc5, 0x13, 0xe3, 0xa1, 0xce, 0xd6, 0x77, 0x91, 0xf9, 0x03, 0x6e, 0xee, 0x56, 0xfa, 0x9e, 0x20, 0x60, 0x2b } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x71, 0x94, 0x0b, 0xe6, 0x79, 0x7b, 0xb3, 0x28, 0x5e, 0xbd, 0xc2, 0x0c, 0xc9, 0x27, 0x5f, 0x5d, 0x77, 0x55, 0x88, 0xe9, 0xaf, 0x6f, 0x68, 0x7a, 0x2e, 0x39, 0xd2, 0xc1, 0x91, 0x11, 0x10, 0x76, 0x95, 0xdd, 0xed, 0xe3, 0x91, 0xd2, 0x19, 0x6b, 0x29, 0x58, 0x1d, 0xf3, 0x15, 0x4a, 0x37, 0x12, 0xfa, 0x6f, 0xcd, 0xf8, 0x5b, 0xb4, 0xfd, 0x48, 0x64, 0x1f, 0x07, 0x1f, 0xfd, 0xb1, 0xde, 0x08, 0xa1, 0xd5, 0x92, 0x1c, 0xa1, 0x0e, 0x68, 0xdc, 0x04, 0x13, 0x13, 0xc9, 0xbb, 0xcb, 0x80, 0x81, 0xbd, 0xb5, 0xd4, 0x60, 0x42, 0x27, 0xcb, 0xe5, 0x78, 0x07, 0x41, 0x65, 0x74, 0xd1, 0xa3, 0x8d, 0xa0, 0xb2, 0x34, 0x4b, 0xb2, 0x15, 0xb4, 0x18, 0x2b, 0x10, 0x6b, 0x2b, 0x53, 0x4a, 0x8d, 0x32, 0x06, 0xf2, 0xd7, 0xd3, 0x03, 0xb8, 0xdd, 0x5b, 0xce, 0x29, 0x2a, 0xbf, 0x75, 0xcd, 0x76, 0x49 } +, + /* Prime 1 */ + 65, + { 0x02, 0x95, 0x10, 0xb9, 0x33, 0xb7, 0xc8, 0x4e, 0x41, 0xff, 0xcc, 0x72, 0x2e, 0x32, 0x38, 0x60, 0xc9, 0xb2, 0xd0, 0x88, 0x3c, 0x68, 0x33, 0x62, 0x4b, 0xa5, 0xbb, 0xb8, 0x97, 0x53, 0xd7, 0x60, 0x3a, 0x7d, 0xcf, 0x26, 0x6c, 0xc8, 0xf4, 0xbb, 0x07, 0x48, 0x48, 0x26, 0x0f, 0x68, 0xdd, 0x82, 0x6b, 0x63, 0x8a, 0x8d, 0xd2, 0xef, 0xaf, 0x68, 0xaa, 0xee, 0x26, 0x5a, 0xe8, 0x98, 0x39, 0xb1, 0x63 } +, + /* Prime 2 */ + 65, + { 0x02, 0x8a, 0x2d, 0x03, 0x34, 0x49, 0x44, 0x62, 0xf6, 0x11, 0xf3, 0x60, 0x3e, 0x0d, 0x37, 0x4f, 0x3e, 0x32, 0xd2, 0xfa, 0xb5, 0xe9, 0xd6, 0x97, 0x2d, 0xfd, 0x70, 0x79, 0x64, 0x46, 0xa4, 0x8b, 0xc3, 0x03, 0xee, 0x25, 0x8b, 0x75, 0xa1, 0xb7, 0xac, 0xe7, 0x0d, 0x48, 0x58, 0x51, 0x79, 0x4e, 0x42, 0x84, 0xf2, 0xdc, 0x51, 0xd3, 0x97, 0x8d, 0x55, 0x53, 0x7b, 0xea, 0x22, 0x55, 0x11, 0xf4, 0x99 } +, + /* Prime exponent 1 */ + 65, + { 0x01, 0xb9, 0x55, 0x0d, 0xdf, 0xda, 0x3d, 0x6f, 0x09, 0x9e, 0xe5, 0xf6, 0x00, 0xa3, 0x64, 0x82, 0x31, 0x86, 0x20, 0xb4, 0x23, 0x68, 0x09, 0x8e, 0x01, 0x24, 0xe7, 0x5b, 0x88, 0x23, 0xe0, 0x31, 0x0d, 0x3b, 0xba, 0xd5, 0x53, 0x61, 0x22, 0x09, 0xcf, 0x05, 0xd1, 0xad, 0x1f, 0x32, 0x8a, 0x57, 0xac, 0xac, 0x2a, 0xef, 0x1e, 0x39, 0x08, 0x69, 0x1f, 0x5c, 0x98, 0xdc, 0xae, 0x56, 0x1a, 0x86, 0x33 } +, + /* Prime exponent 2 */ + 64, + { 0xe8, 0xff, 0xa4, 0x8c, 0x52, 0x4d, 0x5d, 0xa1, 0x8d, 0x61, 0x48, 0x76, 0x34, 0x4a, 0x43, 0xed, 0xa8, 0x4d, 0x0f, 0x67, 0xad, 0xbb, 0x27, 0x46, 0x65, 0xf2, 0xae, 0xae, 0x0e, 0xda, 0xdc, 0xf3, 0x30, 0x2f, 0x61, 0xe9, 0x0e, 0x68, 0xbb, 0xe8, 0x0c, 0x8d, 0x28, 0x05, 0xee, 0x7c, 0xa8, 0x5d, 0x12, 0x43, 0xee, 0x4c, 0xac, 0xa5, 0x3d, 0x12, 0xfc, 0xee, 0x05, 0x43, 0xf4, 0x74, 0x90, 0xd1 } +, + /* Coefficient */ + 65, + { 0x01, 0x98, 0x4a, 0x81, 0x5c, 0xdb, 0x46, 0xad, 0x81, 0xcd, 0x82, 0x10, 0xaa, 0x07, 0x22, 0x70, 0x0c, 0x59, 0x90, 0x9d, 0xdc, 0x9c, 0x4a, 0x49, 0xf1, 0x9b, 0xe1, 0x5d, 0xa6, 0x04, 0x47, 0x8c, 0x21, 0x88, 0x81, 0xd5, 0x43, 0xa7, 0x54, 0x6b, 0xf7, 0x75, 0x69, 0x4c, 0x2b, 0xd1, 0x3d, 0xda, 0x69, 0x2c, 0xd0, 0xbc, 0x24, 0x39, 0xef, 0x22, 0xef, 0xb6, 0x7f, 0xfc, 0x5d, 0x46, 0x95, 0x21, 0xb2 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 9.1", + /* Message */ + 61, + { 0x96, 0xad, 0x3b, 0xa4, 0xd2, 0x9b, 0xdd, 0x35, 0x25, 0xbb, 0xc5, 0xd0, 0x2e, 0x88, 0xc0, 0x13, 0x3f, 0xfd, 0xea, 0x40, 0x94, 0x74, 0xdb, 0x34, 0xdf, 0x73, 0x3c, 0xa5, 0x9c, 0x3a, 0x23, 0x2f, 0x6a, 0x64, 0xc2, 0x14, 0x3c, 0xa1, 0x31, 0xa7, 0xf1, 0x8d, 0x00, 0x5b, 0xb3, 0xaa, 0x6c, 0xa1, 0xea, 0xbe, 0xaa, 0x13, 0x6b, 0xec, 0x37, 0xdb, 0x11, 0x1d, 0x4d, 0x8f, 0x61 } +, + /* Seed */ + 65, + { 0x10, 0xe9, 0xf5, 0x09, 0x3c, 0xec, 0x87, 0x2e, 0xdb, 0x16, 0x16, 0x2b, 0x6b, 0xbd, 0x52, 0x12, 0xf6, 0x10, 0x1a, 0x71, 0xd5, 0x1d, 0xc1, 0x42, 0x0c, 0xad, 0xd1, 0xd5, 0x50, 0xfa, 0xf9, 0xaf, 0x40, 0xf5, 0x73, 0xd3, 0xe3, 0xab, 0x68, 0x91, 0xd8, 0xa8, 0x82, 0xef, 0x06, 0x56, 0xbc, 0x30, 0x06, 0x2a, 0x05, 0xb1, 0xcc, 0x27, 0x7a, 0x11, 0xc9, 0xba, 0x2e, 0xfd, 0x51, 0x03, 0xc5, 0x6e, 0x23 } +, + /* Encryption */ + 129, + { 0x04, 0xde, 0xc0, 0x1b, 0xbf, 0x8e, 0x0c, 0x22, 0x96, 0xd9, 0xf5, 0xbc, 0x2d, 0x2b, 0xa8, 0x95, 0x34, 0x3e, 0xc3, 0x0e, 0xc5, 0x44, 0x13, 0x57, 0x6d, 0x80, 0x84, 0xb9, 0x31, 0x43, 0xcf, 0xa2, 0xd2, 0x03, 0x3b, 0xf4, 0xc2, 0xc2, 0xe0, 0x3f, 0x5b, 0x02, 0x59, 0xed, 0xf1, 0x4a, 0x8f, 0x3e, 0x11, 0x69, 0x85, 0x77, 0x65, 0x2a, 0x2a, 0xb9, 0xf5, 0x1a, 0xb0, 0x18, 0x7c, 0xc7, 0x51, 0x75, 0xc8, 0x6d, 0xfc, 0x9a, 0x45, 0xb1, 0xe4, 0xeb, 0x8b, 0x54, 0x47, 0xa9, 0x4a, 0xb9, 0xb5, 0x17, 0x7a, 0x04, 0x04, 0xba, 0x49, 0xe5, 0x7f, 0x83, 0xc9, 0x3f, 0x7f, 0xe2, 0xde, 0x24, 0x18, 0x45, 0xf5, 0x81, 0xf6, 0x42, 0x12, 0x43, 0x7e, 0x0c, 0x04, 0xff, 0x34, 0xea, 0x1d, 0xee, 0x6d, 0xd2, 0x8f, 0x6f, 0xf3, 0x36, 0x72, 0x35, 0x44, 0x13, 0x74, 0xf0, 0xf2, 0xef, 0x71, 0xa9, 0xcd, 0xae, 0x9e } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 9.2", + /* Message */ + 37, + { 0x7f, 0x92, 0xab, 0xb6, 0xe5, 0x2e, 0xd5, 0xd4, 0x20, 0x84, 0x9e, 0xd6, 0xcc, 0xab, 0x36, 0xc3, 0xd0, 0x84, 0x92, 0x55, 0x43, 0x1e, 0x19, 0x3d, 0x67, 0xbd, 0x94, 0x4b, 0x6c, 0x0f, 0xce, 0xfb, 0x77, 0x29, 0xcf, 0x5a, 0x31 } +, + /* Seed */ + 89, + { 0xce, 0xa9, 0x68, 0xbe, 0x78, 0xab, 0x5f, 0xaa, 0xc2, 0x27, 0xdc, 0x3c, 0x6f, 0xc9, 0xce, 0xd4, 0x9f, 0x85, 0x1e, 0xd5, 0x8b, 0x08, 0xd5, 0xca, 0x37, 0x54, 0x28, 0x48, 0x9a, 0xfb, 0xef, 0x3b, 0xf5, 0xed, 0x83, 0x74, 0x6d, 0x95, 0x9a, 0x0a, 0x56, 0xe9, 0xac, 0x66, 0xff, 0x2e, 0x7c, 0x8b, 0x8c, 0x3a, 0xda, 0x97, 0xfa, 0x15, 0xdd, 0x7f, 0x99, 0x13, 0x41, 0x74, 0x70, 0x70, 0xcc, 0xad, 0x65, 0x42, 0xbd, 0x7f, 0x4b, 0x33, 0xf5, 0x56, 0x04, 0x45, 0x8b, 0x91, 0x03, 0xae, 0x13, 0xdc, 0x89, 0xb4, 0xe6, 0x2c, 0xcb, 0xf8, 0x4f, 0xf7, 0x3b } +, + /* Encryption */ + 129, + { 0x02, 0x5a, 0x1e, 0x65, 0xeb, 0x37, 0xf4, 0xb3, 0x28, 0xcc, 0x31, 0xb0, 0x17, 0x24, 0xf8, 0x3c, 0x26, 0xed, 0x8d, 0x18, 0xa6, 0x51, 0x65, 0x21, 0x3b, 0xa0, 0xef, 0xf7, 0xae, 0x76, 0x7e, 0xe6, 0x0b, 0x99, 0x27, 0x76, 0x1a, 0x06, 0x94, 0xb5, 0xc3, 0xbb, 0x64, 0xb7, 0xe0, 0x39, 0x96, 0xa3, 0x56, 0x8d, 0x6f, 0xd1, 0xac, 0x6b, 0x7a, 0x8b, 0x71, 0x97, 0x5b, 0xb0, 0x71, 0x6d, 0x94, 0x5c, 0x02, 0xd4, 0x73, 0x68, 0x96, 0x6f, 0xff, 0xb1, 0xd4, 0x49, 0xfc, 0x6e, 0xd7, 0x3e, 0x2d, 0x19, 0x83, 0x1b, 0x86, 0xd1, 0x87, 0x67, 0x51, 0x29, 0x36, 0x69, 0xe7, 0x7d, 0x6e, 0x12, 0xa0, 0xf0, 0xc9, 0x62, 0xdf, 0xcd, 0x40, 0x0f, 0xb8, 0x3c, 0xe8, 0x26, 0x07, 0x16, 0x31, 0x7a, 0xd5, 0xfd, 0xe2, 0x18, 0x49, 0xaa, 0x6f, 0x68, 0xe7, 0x0c, 0xe0, 0xb5, 0xb3, 0x11, 0x42, 0x89, 0x8a, 0xd1, 0xa2 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.3", + /* Message */ + 61, + { 0xf5, 0xb5, 0x35, 0xb6, 0x3d, 0x53, 0x5e, 0x21, 0x37, 0x73, 0x2c, 0x30, 0x13, 0x37, 0xc9, 0x53, 0xea, 0x2e, 0xdd, 0x58, 0xa7, 0x8c, 0x20, 0x25, 0x83, 0x2d, 0xca, 0x9d, 0x6b, 0xcd, 0xad, 0x87, 0xc9, 0x97, 0xc9, 0x06, 0x83, 0x6b, 0x2b, 0xf9, 0x5c, 0x83, 0xf0, 0x3f, 0x7a, 0xfa, 0x29, 0x01, 0x34, 0x6d, 0x67, 0x4a, 0xa6, 0x9a, 0x1b, 0x47, 0xf6, 0xb9, 0x16, 0xfd, 0x4b } +, + /* Seed */ + 65, + { 0xc8, 0x9e, 0xfd, 0xb2, 0x34, 0xe0, 0x1a, 0x2f, 0x07, 0x76, 0x29, 0x57, 0xe8, 0xc0, 0xa4, 0xf9, 0x1a, 0xba, 0xe6, 0xd4, 0xf3, 0x60, 0xe8, 0x9a, 0x7c, 0x48, 0x6c, 0x55, 0x49, 0xf3, 0xd0, 0xad, 0x75, 0x77, 0x7f, 0x0c, 0xcd, 0x97, 0xa0, 0x97, 0x5e, 0x98, 0x44, 0xd9, 0x86, 0x87, 0x02, 0x76, 0xc9, 0x82, 0x5f, 0x5d, 0x1e, 0xef, 0x3d, 0x1b, 0x48, 0x7a, 0xbc, 0xd1, 0x9b, 0x51, 0x2d, 0x08, 0xbe } +, + /* Encryption */ + 129, + { 0x03, 0x9a, 0x1c, 0xe8, 0xc0, 0x91, 0x62, 0x51, 0xa0, 0x1e, 0x5f, 0xb6, 0x61, 0x5d, 0x2e, 0x11, 0x98, 0x2f, 0x4f, 0xae, 0x7d, 0x46, 0xdf, 0x21, 0xda, 0xa2, 0x98, 0xf2, 0xc7, 0x46, 0x11, 0xb5, 0x58, 0x16, 0xcc, 0x27, 0xfa, 0x37, 0x27, 0x9a, 0xaf, 0x59, 0x02, 0xec, 0xb6, 0xc8, 0x39, 0xfa, 0x90, 0x0c, 0xf3, 0xaf, 0x86, 0xff, 0x40, 0xa4, 0x47, 0xdc, 0x40, 0x22, 0x35, 0xf9, 0x06, 0x67, 0x91, 0x23, 0xf3, 0xcd, 0x38, 0x19, 0x04, 0xf3, 0x3e, 0xee, 0x35, 0x3a, 0xc9, 0x0d, 0x5f, 0x7f, 0x20, 0x3a, 0x6e, 0xa8, 0x91, 0x35, 0x1a, 0xdb, 0x11, 0x60, 0x1b, 0xd9, 0xd6, 0xb0, 0xa0, 0x24, 0x33, 0x3a, 0x24, 0x55, 0xbe, 0x1c, 0xa6, 0x2e, 0xd8, 0x2c, 0xf3, 0x7c, 0xf8, 0xde, 0x4e, 0x23, 0x92, 0xdd, 0x54, 0xe7, 0x75, 0x03, 0x3c, 0x56, 0x99, 0x0b, 0xae, 0x5c, 0x43, 0x91, 0xb6, 0x65, 0x3a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.4", + /* Message */ + 47, + { 0xa7, 0xcf, 0x29, 0x82, 0x03, 0x47, 0xa5, 0x2a, 0xb9, 0xcc, 0x42, 0x04, 0xbb, 0x6a, 0xc1, 0xbd, 0x7f, 0xd9, 0x0a, 0x75, 0x8a, 0x15, 0x6d, 0xfa, 0x9c, 0xe7, 0x19, 0x27, 0xe7, 0x4e, 0xe2, 0x15, 0x98, 0x70, 0x8c, 0xf6, 0x9c, 0xfd, 0x79, 0x85, 0x74, 0x2f, 0x50, 0x27, 0xff, 0xa7, 0x10 } +, + /* Seed */ + 79, + { 0x10, 0x9f, 0x0d, 0x6c, 0xa0, 0xe1, 0x3f, 0x50, 0x4c, 0x07, 0xd8, 0x4a, 0x5b, 0xbe, 0x43, 0xed, 0x6a, 0x94, 0xac, 0xba, 0xfa, 0xb0, 0x48, 0x89, 0x36, 0x05, 0xd3, 0x41, 0xc5, 0xd2, 0x8d, 0x85, 0x44, 0xc3, 0xfd, 0x28, 0x43, 0x50, 0xf2, 0xc2, 0x2d, 0x1f, 0x36, 0x7d, 0xfb, 0x9b, 0x6a, 0x67, 0x51, 0xd0, 0x6a, 0xae, 0xb1, 0x7c, 0x3c, 0x0a, 0x10, 0x11, 0xae, 0x38, 0xfb, 0xa4, 0xe4, 0x6d, 0x4e, 0x44, 0xc4, 0x82, 0x87, 0x9e, 0xba, 0x06, 0x44, 0x37, 0x48, 0x71, 0xb5, 0xc5, 0x3b } +, + /* Encryption */ + 129, + { 0x04, 0x48, 0xc3, 0x9c, 0xc4, 0x57, 0xd6, 0xcc, 0xc3, 0x0b, 0x0d, 0x76, 0xff, 0x5a, 0x13, 0x2e, 0x00, 0xc7, 0x5d, 0x53, 0x36, 0x46, 0xb8, 0x44, 0x0b, 0x13, 0xce, 0x73, 0x0e, 0x1b, 0x7a, 0xd8, 0x3b, 0xb2, 0xba, 0x4a, 0x08, 0x2b, 0xb5, 0xa3, 0x3c, 0xf4, 0x14, 0x66, 0xe0, 0x67, 0xfc, 0xf1, 0x6c, 0x6a, 0x29, 0xf1, 0x87, 0x9f, 0x77, 0xe9, 0xb0, 0xdb, 0xf3, 0xec, 0x08, 0x05, 0x75, 0xbe, 0xba, 0xc0, 0xc5, 0x67, 0x6b, 0xae, 0xe0, 0x02, 0xd5, 0x73, 0xd1, 0xbc, 0xc8, 0xa7, 0x0f, 0xed, 0x2a, 0xb6, 0x79, 0x43, 0xef, 0xc9, 0xbc, 0x13, 0x13, 0x9e, 0x5d, 0x8d, 0xde, 0x2c, 0xb3, 0x0e, 0x1b, 0x93, 0x4f, 0x50, 0xcf, 0x6c, 0x45, 0x73, 0x92, 0x3f, 0x73, 0x98, 0xde, 0x66, 0x70, 0xcc, 0x26, 0x34, 0x1f, 0x3e, 0x35, 0xa4, 0x19, 0x36, 0x1e, 0x59, 0xf6, 0x08, 0x98, 0xf2, 0x69, 0x2b, 0x94 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.5", + /* Message */ + 10, + { 0xb8, 0x03, 0xc7, 0xef, 0x5f, 0x9a, 0x9b, 0xd5, 0x84, 0x01 } +, + /* Seed */ + 116, + { 0x8e, 0x77, 0x58, 0xed, 0x4d, 0x1b, 0xa4, 0xdc, 0xe0, 0x88, 0x92, 0x6c, 0x10, 0xb2, 0xf3, 0xd4, 0xc1, 0xe2, 0x67, 0x1a, 0xe7, 0x2e, 0x65, 0x9f, 0x72, 0x1f, 0xf7, 0xbe, 0x6f, 0xc0, 0x35, 0xe3, 0x85, 0xd5, 0x12, 0xd0, 0x7a, 0x38, 0xdc, 0xca, 0x1e, 0xb8, 0x31, 0xfe, 0xf9, 0x06, 0x10, 0x04, 0x44, 0xee, 0x99, 0x5c, 0xb0, 0x7b, 0xc2, 0x6a, 0x5d, 0xc9, 0x2b, 0x27, 0x2a, 0x74, 0xa9, 0x2d, 0x21, 0x49, 0x73, 0x25, 0x22, 0xd5, 0x39, 0x43, 0x4f, 0xa4, 0xd0, 0x3b, 0x07, 0xcf, 0x96, 0x99, 0x95, 0x8c, 0x19, 0x89, 0x1d, 0x1d, 0x59, 0x06, 0xaa, 0x36, 0xd0, 0xa8, 0xd0, 0x6c, 0x6f, 0xc8, 0x7a, 0x45, 0x51, 0xbf, 0x18, 0x58, 0xbd, 0xfe, 0xd5, 0xf8, 0x86, 0xcc, 0x8d, 0x31, 0xee, 0x4c, 0x16, 0x4e, 0x98, 0x1d } +, + /* Encryption */ + 129, + { 0x04, 0xb6, 0x2d, 0x4d, 0x4b, 0x9c, 0x1c, 0x3e, 0x05, 0x13, 0x09, 0x79, 0x5c, 0x69, 0x24, 0x8a, 0xed, 0x38, 0x9d, 0xe2, 0x4a, 0x6c, 0x79, 0x53, 0x8a, 0x2d, 0x51, 0xd5, 0xd0, 0x37, 0x19, 0xa8, 0xa5, 0x28, 0x75, 0x0d, 0x5d, 0x25, 0x4a, 0x1b, 0x91, 0x40, 0x96, 0xdb, 0x96, 0xd8, 0x3d, 0x2d, 0x9a, 0xaa, 0x2a, 0x16, 0x5b, 0xb1, 0x34, 0x6e, 0x44, 0xc3, 0x57, 0x27, 0x56, 0xc3, 0x8d, 0x52, 0xf8, 0xd3, 0x07, 0xc0, 0x4e, 0x1e, 0xfe, 0xe5, 0x84, 0x78, 0x22, 0x31, 0x7a, 0xb4, 0x69, 0x34, 0x5b, 0x86, 0xc7, 0xb8, 0x5b, 0x54, 0x15, 0x41, 0xc9, 0x92, 0xab, 0xea, 0x98, 0xd1, 0x08, 0xa7, 0xdf, 0xc7, 0x09, 0x1c, 0x30, 0xc6, 0x68, 0x5a, 0xf0, 0xe3, 0x3d, 0x04, 0x66, 0xac, 0xe4, 0xcc, 0xcc, 0xb3, 0x4e, 0x5b, 0x26, 0x6d, 0x3d, 0x6b, 0x94, 0x7b, 0xc7, 0xc0, 0xae, 0x34, 0xd5, 0xe2, 0x64 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.6", + /* Message */ + 49, + { 0x61, 0x7e, 0xa9, 0xe4, 0xa5, 0x6c, 0x4e, 0xc1, 0xd3, 0xd7, 0xfd, 0x7f, 0x32, 0x81, 0xae, 0x7f, 0xa9, 0x32, 0xb2, 0xa0, 0xa6, 0xcf, 0x55, 0xeb, 0x60, 0x48, 0x14, 0x56, 0x81, 0xb3, 0x58, 0x8e, 0xdf, 0x70, 0x12, 0x69, 0xf8, 0x9f, 0xe6, 0x4a, 0xa1, 0x4a, 0xd8, 0xdf, 0x0d, 0x46, 0x79, 0x61, 0x31 } +, + /* Seed */ + 77, + { 0x64, 0xd7, 0xeb, 0xd0, 0x48, 0x50, 0xeb, 0x6f, 0x7a, 0xe1, 0xaf, 0x48, 0x12, 0x0a, 0x80, 0x13, 0x0f, 0x32, 0xed, 0xb5, 0x03, 0x69, 0x64, 0x0b, 0x22, 0x2b, 0x8d, 0x63, 0xef, 0xf6, 0x57, 0x12, 0x70, 0xdc, 0xab, 0x31, 0x76, 0xd0, 0x24, 0x72, 0x28, 0xdc, 0xd1, 0xc3, 0xf3, 0xcf, 0xd5, 0x13, 0x31, 0xb7, 0x56, 0xa8, 0x65, 0x2a, 0x14, 0xdd, 0xaa, 0xb9, 0x93, 0x96, 0xb9, 0x19, 0x9a, 0x73, 0x87, 0x50, 0xd6, 0x9e, 0xfc, 0xd3, 0x77, 0xf1, 0x84, 0xae, 0x19, 0xb5, 0xa9 } +, + /* Encryption */ + 129, + { 0x02, 0xdf, 0xe7, 0x29, 0x58, 0x59, 0x58, 0x81, 0xd8, 0x07, 0x56, 0x6d, 0x3e, 0x36, 0x07, 0xc0, 0x22, 0xe4, 0x61, 0xfe, 0x1d, 0xbe, 0xd3, 0xcc, 0x6d, 0x63, 0xde, 0xdc, 0xb7, 0x19, 0x0f, 0x06, 0xc7, 0xd2, 0x4b, 0x4f, 0x03, 0x26, 0x4c, 0xaf, 0xbb, 0x74, 0x82, 0xec, 0x28, 0xb9, 0xba, 0x48, 0x9d, 0x03, 0x11, 0x5a, 0xf5, 0x8f, 0xde, 0x47, 0x5e, 0xda, 0x58, 0xbf, 0x01, 0x55, 0xcd, 0xf1, 0xaf, 0x16, 0xdf, 0x20, 0x6b, 0xcd, 0x12, 0x57, 0x04, 0xc3, 0xe3, 0x15, 0xad, 0x3d, 0x95, 0x44, 0xb9, 0xe2, 0xc2, 0xfe, 0xa8, 0x10, 0xce, 0x48, 0x45, 0x56, 0xd2, 0x9e, 0x07, 0xad, 0xbf, 0x0f, 0xf4, 0x61, 0xcc, 0xbc, 0xf6, 0x62, 0xbd, 0x74, 0x95, 0x9a, 0x43, 0x7d, 0x4c, 0x80, 0x11, 0xce, 0xad, 0xa5, 0x50, 0x2a, 0xf7, 0x67, 0x6d, 0x9a, 0x15, 0x21, 0xe3, 0x18, 0x9d, 0xaf, 0xde, 0x00, 0xdd } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.7", + /* Message */ + 60, + { 0xc9, 0x1f, 0x2c, 0x98, 0xc7, 0x5b, 0x2f, 0xd4, 0xcd, 0x8d, 0x5c, 0x7f, 0xf2, 0xe7, 0x69, 0xb1, 0x2f, 0x28, 0xf3, 0x13, 0xfb, 0xac, 0xb5, 0x1b, 0x5e, 0x50, 0x14, 0xdf, 0xce, 0x9d, 0x63, 0x5e, 0x7c, 0x6b, 0x2d, 0x88, 0xaf, 0x5e, 0xac, 0x30, 0xd1, 0x62, 0xb8, 0xdd, 0xc2, 0x2e, 0xd8, 0xbc, 0x7b, 0xee, 0x50, 0x6b, 0xfb, 0xf3, 0x1e, 0x51, 0xba, 0x48, 0xf4, 0x26 } +, + /* Seed */ + 66, + { 0x6c, 0x44, 0x59, 0x61, 0xf8, 0x6f, 0xa2, 0x98, 0xd7, 0x64, 0x7c, 0x22, 0x24, 0xd9, 0x5b, 0xc1, 0x27, 0xda, 0xfc, 0xbd, 0x5b, 0x90, 0x21, 0xec, 0x7e, 0x9e, 0xbd, 0xe9, 0x6f, 0x5d, 0x7a, 0x76, 0xf4, 0xee, 0xd0, 0xac, 0x92, 0x2a, 0x6e, 0x93, 0xeb, 0x3b, 0x4c, 0x3c, 0x43, 0xf8, 0xa5, 0x7e, 0x18, 0x29, 0x4e, 0x1a, 0x51, 0x73, 0xb0, 0xf7, 0xe2, 0xdd, 0x2c, 0x4e, 0x57, 0x7a, 0x4b, 0xec, 0xe7, 0x14 } +, + /* Encryption */ + 129, + { 0x03, 0xa8, 0x85, 0xaa, 0xf7, 0xb7, 0xd9, 0x4f, 0xda, 0xe3, 0x4b, 0x41, 0xc3, 0x74, 0x17, 0x66, 0xa4, 0x09, 0xc1, 0xee, 0x02, 0x32, 0xb1, 0xc5, 0x3e, 0x5f, 0x6c, 0x5a, 0xa5, 0x4a, 0xc1, 0xef, 0x0e, 0x5b, 0xf9, 0x9b, 0x9f, 0x7d, 0xf3, 0xe9, 0xb0, 0x0c, 0xed, 0x94, 0x76, 0xee, 0x1a, 0xdb, 0x8f, 0xc5, 0x71, 0x68, 0x91, 0xf5, 0x4d, 0x45, 0xce, 0xda, 0x70, 0xb9, 0xdb, 0x3b, 0x8f, 0xad, 0x25, 0xe7, 0x77, 0x95, 0xaf, 0x14, 0x81, 0xec, 0x49, 0x21, 0x84, 0xc4, 0x9e, 0x9d, 0xf8, 0x23, 0xee, 0x64, 0x66, 0x41, 0x0f, 0x65, 0x01, 0x3c, 0xe3, 0xc5, 0x79, 0x16, 0x63, 0x5d, 0xa8, 0x30, 0x67, 0x7f, 0x93, 0x2b, 0xda, 0xba, 0xb5, 0xc0, 0xa2, 0x08, 0xd7, 0xf4, 0x36, 0x7a, 0x7e, 0xab, 0xa7, 0x5b, 0x04, 0x5d, 0x25, 0xac, 0xfd, 0xb4, 0x15, 0xfe, 0xe0, 0x52, 0x19, 0xa5, 0x84, 0x23, 0x7a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.8", + /* Message */ + 51, + { 0x7b, 0x1c, 0x31, 0x51, 0xa3, 0x8d, 0x32, 0xec, 0x7b, 0x82, 0xc4, 0x8c, 0x00, 0x0a, 0xa4, 0x81, 0xde, 0x41, 0x8e, 0x80, 0x3b, 0x67, 0x3d, 0x2e, 0x9a, 0x0f, 0xc3, 0xd5, 0xe9, 0x74, 0xad, 0xcd, 0xce, 0xbd, 0x3c, 0x2a, 0x8f, 0x41, 0x14, 0x21, 0x18, 0xa5, 0x5e, 0x87, 0xd0, 0x4b, 0xba, 0xd5, 0xb3, 0x64, 0x25 } +, + /* Seed */ + 75, + { 0xb0, 0xf5, 0xbe, 0x9b, 0x3f, 0x23, 0x7c, 0xc5, 0xaf, 0xca, 0x5a, 0x99, 0xfc, 0xcb, 0x77, 0xb6, 0xef, 0xd8, 0x68, 0x94, 0x7f, 0x98, 0x55, 0x4f, 0xbe, 0xce, 0xac, 0xfa, 0x88, 0x4c, 0x15, 0x15, 0x39, 0xd7, 0xcf, 0x42, 0x3e, 0x72, 0x60, 0x31, 0xbf, 0xeb, 0x8d, 0xd2, 0xd4, 0xf3, 0x01, 0xda, 0x6b, 0xdf, 0xca, 0xd6, 0xe5, 0x81, 0x65, 0x82, 0xad, 0xdc, 0xe1, 0x0d, 0x85, 0xd5, 0xee, 0x1d, 0x04, 0x46, 0xf3, 0x73, 0xb9, 0x5e, 0xe1, 0x60, 0xbc, 0xf0, 0x35 } +, + /* Encryption */ + 129, + { 0x06, 0x6c, 0x30, 0x09, 0xdc, 0x6c, 0xba, 0xc7, 0xb8, 0xbd, 0x51, 0x41, 0xc5, 0x5c, 0xf8, 0x6a, 0x3d, 0x79, 0x69, 0xd5, 0x85, 0x45, 0x2e, 0x3a, 0x66, 0x54, 0x0f, 0x94, 0x02, 0xdb, 0xa2, 0x15, 0xe3, 0xfb, 0x3a, 0x27, 0x7f, 0x0d, 0x33, 0x96, 0xc8, 0xc0, 0x08, 0xaf, 0x19, 0x91, 0x3e, 0x3d, 0x91, 0xe4, 0x0f, 0x86, 0x76, 0x06, 0xb5, 0xbf, 0x54, 0x30, 0x4c, 0x04, 0x71, 0xda, 0xdd, 0x64, 0x04, 0xb6, 0x7a, 0x48, 0x57, 0xbf, 0x52, 0x24, 0x6c, 0x0d, 0x60, 0x18, 0x23, 0xdd, 0x03, 0x80, 0xc6, 0x60, 0x9d, 0xac, 0xb9, 0x2d, 0xb6, 0x02, 0xe5, 0x57, 0x64, 0xae, 0x46, 0x50, 0xdf, 0x1a, 0xdb, 0xb4, 0xb9, 0x5f, 0xa5, 0xaf, 0x4b, 0xcd, 0x11, 0x21, 0xf1, 0x3c, 0x0a, 0x73, 0x23, 0xad, 0xa8, 0xc6, 0x0d, 0xe3, 0xd0, 0x81, 0x72, 0x9d, 0x19, 0x7f, 0x9c, 0xf8, 0xe2, 0x7c, 0xde, 0x80, 0xb1 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.9", + /* Message */ + 58, + { 0xb2, 0x93, 0xc6, 0xf6, 0xd0, 0x5d, 0x1f, 0x38, 0xb5, 0x61, 0xea, 0x3d, 0x0d, 0x0a, 0xd6, 0xa2, 0xaf, 0x83, 0x09, 0xbb, 0x9a, 0xde, 0xfa, 0x77, 0x8f, 0xd6, 0xbb, 0x9f, 0xff, 0x3e, 0x01, 0x0c, 0x40, 0x4c, 0x53, 0x39, 0x97, 0xcc, 0xfe, 0xd7, 0xe1, 0x91, 0x7a, 0x66, 0x92, 0x61, 0xcf, 0xcc, 0xa4, 0xe3, 0x70, 0x29, 0x99, 0x1d, 0x2d, 0xe9, 0xb2, 0x99 } +, + /* Seed */ + 68, + { 0x87, 0xbd, 0x2f, 0x6b, 0xb4, 0x82, 0x45, 0x59, 0x1d, 0x65, 0xf0, 0x23, 0xa6, 0x5b, 0x63, 0xbb, 0xba, 0x84, 0x19, 0x79, 0x2c, 0x01, 0x41, 0x09, 0x2b, 0x1d, 0xb1, 0xbe, 0x53, 0xe8, 0xc9, 0xb4, 0xdf, 0x95, 0xf0, 0xad, 0x55, 0xb9, 0x6e, 0x5e, 0x57, 0x61, 0x5d, 0x21, 0x4b, 0x49, 0x77, 0x87, 0x0a, 0x27, 0x2f, 0x72, 0x31, 0x66, 0xc6, 0x20, 0x45, 0x76, 0x5e, 0x6b, 0x4a, 0x73, 0xa7, 0xc9, 0xeb, 0xe1, 0x1d, 0x24 } +, + /* Encryption */ + 129, + { 0x03, 0x10, 0x4e, 0xc6, 0xc4, 0xab, 0x9d, 0xac, 0xae, 0x42, 0x7f, 0xb1, 0x06, 0x99, 0xbc, 0xae, 0x00, 0x3d, 0xa5, 0x6f, 0x6d, 0x07, 0x50, 0x95, 0x87, 0x14, 0x5b, 0x73, 0x3e, 0xdb, 0x53, 0x23, 0x9a, 0x6f, 0x42, 0x22, 0x86, 0x83, 0x9c, 0xac, 0x06, 0x4a, 0xdf, 0xee, 0xe5, 0xdc, 0x89, 0x78, 0x0c, 0xdd, 0xad, 0xcc, 0x80, 0x72, 0x19, 0xd6, 0xa9, 0x7b, 0x85, 0xc1, 0x3f, 0x27, 0x93, 0x7d, 0x70, 0x32, 0x7f, 0x82, 0xcc, 0x36, 0xa5, 0xda, 0x8e, 0x45, 0x63, 0x77, 0xfc, 0xa2, 0x3a, 0xee, 0x51, 0x4e, 0x04, 0x4a, 0xbf, 0x1f, 0x66, 0xc3, 0xe7, 0xbd, 0xeb, 0xc2, 0xcf, 0xf6, 0x28, 0xbd, 0x52, 0x4a, 0x09, 0x66, 0xe2, 0x63, 0x8d, 0x28, 0x33, 0xbf, 0xa3, 0x43, 0xeb, 0xc7, 0x41, 0xf7, 0x6b, 0x5b, 0x70, 0xa1, 0x13, 0x6f, 0x4a, 0xbc, 0x60, 0x28, 0x64, 0xa2, 0xad, 0x43, 0xa7, 0x91, 0xbd } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.10", + /* Message */ + 5, + { 0x08, 0x38, 0xf4, 0xa5, 0x92 } +, + /* Seed */ + 121, + { 0x89, 0xc5, 0x89, 0x8c, 0x6c, 0x3d, 0xc6, 0xcb, 0xdb, 0x1a, 0xcb, 0x28, 0x05, 0xdf, 0x53, 0x98, 0xf0, 0xb3, 0x35, 0x8a, 0x18, 0xe5, 0xe6, 0x3c, 0x14, 0xd2, 0x0c, 0x98, 0xd2, 0x1d, 0x9f, 0xd8, 0xb2, 0xec, 0xc9, 0xa0, 0xe8, 0x3d, 0xaf, 0x0c, 0x06, 0x92, 0x68, 0xbb, 0xe8, 0x6f, 0xee, 0xa5, 0x1c, 0x93, 0x79, 0x1b, 0x68, 0xe5, 0xd9, 0x3b, 0x74, 0x5f, 0xea, 0xf6, 0xad, 0xc4, 0x2b, 0x83, 0xc3, 0x09, 0xc9, 0xcd, 0x3d, 0xfe, 0x1c, 0x06, 0x15, 0x3a, 0xb8, 0x80, 0x85, 0x56, 0x18, 0x98, 0x90, 0xbe, 0x05, 0x3a, 0x92, 0x54, 0x88, 0xd0, 0x29, 0xfe, 0x50, 0x40, 0xe3, 0xe7, 0xd5, 0xd5, 0x31, 0xb3, 0x2e, 0xb9, 0xd2, 0xf4, 0xee, 0xa2, 0x21, 0x11, 0xb3, 0x8a, 0x65, 0x53, 0xf0, 0x0e, 0xdd, 0x23, 0x65, 0x57, 0x5b, 0xb9, 0x49, 0xf3, 0x63 } +, + /* Encryption */ + 129, + { 0x01, 0x4f, 0x27, 0x97, 0xdd, 0xe8, 0xd4, 0x60, 0x18, 0xff, 0x23, 0xd8, 0x9b, 0xe2, 0xe3, 0xae, 0x04, 0x6e, 0xed, 0x31, 0x97, 0xc8, 0x79, 0xc6, 0x0e, 0x26, 0xf3, 0xd2, 0x40, 0x08, 0x66, 0xeb, 0x50, 0xd7, 0xb4, 0x5f, 0x6b, 0x01, 0xae, 0x9c, 0xa0, 0x06, 0x84, 0x7e, 0xfb, 0xe9, 0xab, 0xcc, 0x9b, 0xc3, 0xe3, 0x56, 0x90, 0x07, 0x2b, 0x68, 0xdb, 0x9e, 0xcd, 0x92, 0x6d, 0x94, 0x5f, 0x78, 0x7b, 0x27, 0xc3, 0x75, 0x3b, 0xf9, 0x6b, 0x2d, 0x49, 0x98, 0x30, 0x84, 0x14, 0x2c, 0x42, 0xa1, 0x26, 0x1a, 0xff, 0x7b, 0x17, 0xff, 0x4b, 0x20, 0xde, 0x9b, 0xff, 0xa5, 0x86, 0x24, 0xab, 0x37, 0x1d, 0x4c, 0xe2, 0xf9, 0x64, 0x69, 0xa8, 0xe1, 0x03, 0x8d, 0x57, 0x20, 0xb8, 0x1c, 0xf0, 0x42, 0xdc, 0x78, 0xbf, 0xda, 0x9a, 0x3c, 0xcb, 0x61, 0x60, 0x81, 0x2d, 0xde, 0xa1, 0x58, 0xbd, 0x2f, 0x5c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.11", + /* Message */ + 60, + { 0x12, 0x38, 0x0c, 0x5e, 0x80, 0xbb, 0x95, 0xbb, 0xc8, 0x85, 0x73, 0x57, 0xfe, 0xfd, 0x17, 0xbf, 0x9e, 0x50, 0x96, 0x27, 0xd2, 0x8c, 0xdf, 0xcd, 0x12, 0xbb, 0x13, 0x16, 0x61, 0xb3, 0x42, 0xdf, 0xa6, 0xca, 0x67, 0x2e, 0x13, 0xa8, 0x85, 0x1f, 0xce, 0x19, 0xb1, 0xa8, 0xca, 0xf0, 0xe3, 0x3c, 0xd6, 0xef, 0x53, 0x8a, 0x05, 0xfa, 0x54, 0x26, 0x9a, 0x13, 0x78, 0xe7 } +, + /* Seed */ + 66, + { 0x88, 0x03, 0x31, 0xeb, 0xe9, 0x1a, 0xb6, 0xce, 0x16, 0x84, 0xd9, 0xaf, 0x5d, 0x97, 0x7e, 0xb4, 0x26, 0xca, 0x71, 0x56, 0xe0, 0xb6, 0xf4, 0x33, 0x6c, 0x6e, 0x09, 0x33, 0xd6, 0xfa, 0x48, 0x78, 0x2c, 0x0a, 0xc9, 0x69, 0xf3, 0xdd, 0xe6, 0x1d, 0x8f, 0xd7, 0x4c, 0x47, 0xfe, 0x9e, 0x30, 0x61, 0x71, 0x0d, 0x24, 0x5b, 0x1d, 0x38, 0x11, 0x04, 0x28, 0x60, 0xc1, 0xf4, 0x8d, 0x2b, 0x8f, 0xfd, 0x80, 0x9e } +, + /* Encryption */ + 129, + { 0x04, 0x6c, 0x54, 0x5f, 0xf4, 0x96, 0xc2, 0x1f, 0x69, 0x01, 0x27, 0x24, 0x54, 0x18, 0xcc, 0x5f, 0xb1, 0x8f, 0x09, 0x10, 0x2e, 0x7a, 0xca, 0x87, 0xe2, 0x6e, 0x20, 0x82, 0xfc, 0x16, 0xf6, 0x2f, 0xe9, 0xf4, 0x2a, 0x72, 0x22, 0x71, 0xa7, 0x9e, 0xae, 0xe9, 0x62, 0x5a, 0x7e, 0x63, 0x2c, 0x19, 0x36, 0x40, 0x4c, 0xec, 0x62, 0x11, 0xd8, 0x23, 0x86, 0x3b, 0xa0, 0x2c, 0x6b, 0x0a, 0x83, 0x19, 0x58, 0xb4, 0xed, 0x8f, 0xc6, 0x25, 0xa2, 0xe5, 0x2a, 0x05, 0x4f, 0x8f, 0x18, 0x1f, 0x13, 0x0f, 0x8b, 0xc4, 0xb1, 0xdf, 0xbd, 0x44, 0xb7, 0x0a, 0x35, 0xb3, 0x5e, 0x9c, 0x7f, 0x4a, 0xc5, 0x5e, 0xe5, 0xe2, 0xcb, 0x06, 0x8b, 0x75, 0x86, 0x39, 0xb2, 0xcd, 0x64, 0x3d, 0xbf, 0xa8, 0x2e, 0x2d, 0x97, 0x20, 0xe4, 0x89, 0xf5, 0xc8, 0x21, 0xd8, 0xeb, 0xdc, 0x13, 0x68, 0xa9, 0xd3, 0x46, 0x8a, 0x37 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.12", + /* Message */ + 40, + { 0xee, 0xe1, 0xe4, 0x5d, 0x18, 0xb1, 0x47, 0xc2, 0x69, 0xa6, 0x0a, 0x9c, 0x64, 0x20, 0x18, 0xed, 0x6c, 0xd1, 0x15, 0x7c, 0xd0, 0xce, 0x2b, 0x29, 0x68, 0xdf, 0xa4, 0xb4, 0x97, 0xfc, 0x40, 0xb2, 0x24, 0xbd, 0x86, 0x1e, 0x25, 0x35, 0x12, 0x2b } +, + /* Seed */ + 86, + { 0x5c, 0x51, 0x3e, 0x51, 0x44, 0x52, 0xb1, 0x4a, 0xee, 0x33, 0xb6, 0x17, 0x60, 0xb8, 0x58, 0xc5, 0x35, 0x7c, 0x7d, 0x7f, 0x20, 0xe4, 0xa3, 0x7c, 0x7e, 0xef, 0xe4, 0x19, 0xca, 0xe3, 0xfd, 0x16, 0xf9, 0xd8, 0x3e, 0x5e, 0xcd, 0xe1, 0x9e, 0xe6, 0x32, 0x85, 0xdd, 0xce, 0x66, 0x80, 0xee, 0x94, 0x64, 0xfe, 0x83, 0x75, 0x6e, 0x90, 0x31, 0xd6, 0x37, 0x9e, 0x6a, 0x6b, 0x38, 0x4c, 0xe2, 0x77, 0xbc, 0x64, 0x2c, 0xed, 0x83, 0xb2, 0x9c, 0xf7, 0x4b, 0x72, 0xce, 0xff, 0xf5, 0x30, 0x71, 0x04, 0xe1, 0x83, 0xde, 0x2c, 0xe6, 0xa1 } +, + /* Encryption */ + 129, + { 0x03, 0xa8, 0x64, 0x83, 0xcb, 0xb7, 0x2c, 0x15, 0xf5, 0xa6, 0x93, 0x2b, 0x01, 0x2f, 0x40, 0xc4, 0xb1, 0x73, 0x33, 0x3b, 0x26, 0x86, 0xf4, 0x98, 0x4b, 0xa6, 0x6e, 0x24, 0xc7, 0xcf, 0x44, 0x41, 0x23, 0xba, 0x2e, 0xa6, 0x66, 0xa1, 0x75, 0x5d, 0x09, 0x35, 0x7b, 0xee, 0xa4, 0x37, 0x9c, 0xe3, 0xcd, 0xb0, 0xa7, 0x7a, 0x6e, 0xe3, 0xb7, 0xca, 0x60, 0xdb, 0x68, 0x24, 0x17, 0xf7, 0x16, 0x3d, 0x7d, 0x3a, 0xc7, 0x35, 0x28, 0x11, 0xbb, 0x94, 0xc5, 0xb7, 0x71, 0xf3, 0xd3, 0xfd, 0xa7, 0x73, 0xe5, 0xce, 0xbc, 0x8b, 0xc6, 0x60, 0x11, 0x55, 0xb3, 0xf4, 0xe4, 0xb4, 0xca, 0x85, 0xd9, 0xba, 0xb8, 0xec, 0x25, 0x8c, 0xec, 0xff, 0x44, 0x33, 0xc9, 0x2e, 0x8f, 0x86, 0x3d, 0x96, 0xfc, 0xc7, 0x94, 0x29, 0x49, 0x8a, 0x9e, 0x17, 0x90, 0x33, 0x0b, 0xc4, 0x87, 0xc0, 0x10, 0xd7, 0x99, 0x24, 0x5d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.13", + /* Message */ + 28, + { 0x55, 0x09, 0xa5, 0xc1, 0xac, 0x54, 0x89, 0xdc, 0xb7, 0x65, 0xf3, 0x7c, 0xeb, 0xbe, 0x7d, 0x81, 0xcf, 0x02, 0x76, 0xb1, 0xf2, 0xcf, 0xf9, 0x5d, 0x27, 0x4b, 0xbd, 0x04 } +, + /* Seed */ + 98, + { 0x76, 0xe8, 0x1a, 0x51, 0x37, 0x1f, 0xb5, 0x07, 0x41, 0x14, 0x1d, 0xcb, 0x31, 0xd5, 0x1d, 0x1c, 0x46, 0x1f, 0xcc, 0x02, 0x6a, 0xea, 0x85, 0x20, 0x15, 0xd4, 0x68, 0x74, 0x0b, 0x45, 0x23, 0x40, 0x5f, 0x95, 0xba, 0x87, 0x9b, 0x08, 0x69, 0xbf, 0x03, 0x1a, 0x60, 0x65, 0x4f, 0xc4, 0xe5, 0x68, 0xc1, 0x95, 0x7c, 0xe4, 0xe4, 0x2a, 0x35, 0x0a, 0x95, 0xbf, 0x8c, 0xb2, 0xa8, 0xb5, 0xfd, 0xe6, 0xdc, 0xfd, 0x25, 0x05, 0xc0, 0x37, 0xa2, 0x9e, 0xde, 0x68, 0x9c, 0x53, 0xd8, 0x32, 0x19, 0xe7, 0x3e, 0x64, 0x08, 0x17, 0xbf, 0x8a, 0xfc, 0x9a, 0xb0, 0x04, 0xec, 0xae, 0xc8, 0x43, 0xe4, 0xfe, 0x4e, 0x38 } +, + /* Encryption */ + 129, + { 0x02, 0x55, 0xde, 0x28, 0x0b, 0x71, 0xaf, 0xef, 0xaf, 0xa2, 0x0f, 0x24, 0x1e, 0x08, 0x1b, 0x7e, 0xc6, 0xc1, 0x62, 0xdd, 0xda, 0x18, 0x84, 0xfa, 0x9f, 0x82, 0x5c, 0x4c, 0xe7, 0x63, 0x6e, 0xfb, 0xc1, 0x1b, 0x84, 0xa6, 0xeb, 0xea, 0x35, 0x89, 0x25, 0x71, 0xac, 0x9e, 0x6b, 0x1a, 0xd8, 0x47, 0x3f, 0xa5, 0x73, 0xc8, 0x83, 0xc9, 0xf2, 0x15, 0xa1, 0x95, 0x80, 0xc3, 0xea, 0x30, 0x2f, 0x88, 0xf4, 0x4f, 0x48, 0xe4, 0xd9, 0x5c, 0x34, 0x40, 0xd4, 0x93, 0x1f, 0x17, 0x66, 0xa1, 0xfe, 0x7e, 0x79, 0x0e, 0x5d, 0x38, 0xe8, 0x5d, 0x1f, 0x63, 0x85, 0x0a, 0x3c, 0x70, 0x7a, 0xd8, 0x97, 0x7b, 0x88, 0xc3, 0x8c, 0xb9, 0xed, 0x98, 0x34, 0x5c, 0xd3, 0x50, 0xc3, 0xdd, 0x45, 0x30, 0x9f, 0xc8, 0x1c, 0xb4, 0x62, 0x76, 0xe4, 0xad, 0x64, 0x7f, 0xa8, 0x4c, 0x14, 0x12, 0x5e, 0xfd, 0x67, 0xd8, 0xba } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.14", + /* Message */ + 58, + { 0x02, 0x53, 0x81, 0xa5, 0x5c, 0x8e, 0x48, 0x7d, 0x7f, 0x4f, 0xf7, 0xc3, 0x6c, 0xfb, 0x37, 0x50, 0x07, 0xd1, 0x9f, 0x93, 0x71, 0x13, 0x6e, 0x2b, 0x3d, 0xf4, 0x42, 0x5e, 0xee, 0xee, 0x5d, 0x79, 0xc3, 0x52, 0x61, 0xfb, 0xb4, 0xea, 0x68, 0xbd, 0x91, 0xe8, 0xed, 0xab, 0xa2, 0x32, 0x9e, 0x29, 0x31, 0x53, 0x06, 0xc7, 0xd7, 0x18, 0x33, 0x15, 0x5b, 0x88 } +, + /* Seed */ + 68, + { 0xaa, 0x31, 0x0f, 0x62, 0xda, 0x90, 0xda, 0x4a, 0x20, 0x28, 0xb3, 0x81, 0x39, 0x9c, 0xb7, 0xe0, 0xed, 0x3b, 0xb5, 0x10, 0x57, 0x5c, 0x9b, 0xd0, 0xf6, 0x38, 0x21, 0x5b, 0xaf, 0x78, 0x08, 0xe3, 0x24, 0x5e, 0xaf, 0x38, 0xb7, 0x6e, 0x26, 0x52, 0x29, 0x0b, 0x7c, 0xc6, 0x20, 0x90, 0x7c, 0xda, 0x0c, 0xb7, 0xaf, 0x07, 0x3c, 0x12, 0x2f, 0xf8, 0x3d, 0xaa, 0xe1, 0x98, 0x6b, 0x43, 0xec, 0x1a, 0x14, 0x82, 0xdb, 0xa6 } +, + /* Encryption */ + 129, + { 0x04, 0x9b, 0xfa, 0xc6, 0x41, 0x0b, 0x77, 0x80, 0x39, 0x7a, 0x49, 0xfb, 0x88, 0x93, 0xb2, 0x4d, 0x90, 0x3b, 0x36, 0x00, 0xf3, 0x3c, 0x78, 0x2c, 0x14, 0x75, 0xb5, 0xd2, 0x4b, 0x4f, 0x4e, 0x88, 0xfd, 0x11, 0x24, 0xef, 0x06, 0x45, 0xf3, 0xd3, 0x91, 0xed, 0x31, 0x00, 0x6d, 0xd1, 0xb7, 0xc2, 0x64, 0x12, 0x8d, 0x0d, 0xb9, 0xaa, 0x0d, 0x65, 0xa0, 0x9f, 0xfb, 0xe2, 0x9a, 0x94, 0xcc, 0xa3, 0x58, 0xda, 0x64, 0xbd, 0x1b, 0x72, 0xff, 0x55, 0x88, 0x88, 0x08, 0x10, 0x5b, 0xe0, 0x91, 0xae, 0x23, 0xea, 0x3f, 0x34, 0x75, 0x05, 0x17, 0x9e, 0xcc, 0xb2, 0x41, 0x0d, 0x89, 0xde, 0xcb, 0x62, 0x33, 0x0f, 0x36, 0xc7, 0x44, 0x26, 0x2e, 0xb2, 0xb0, 0x78, 0xb4, 0x25, 0x4b, 0xcd, 0xce, 0xce, 0x21, 0x1c, 0xf0, 0x57, 0x4a, 0x24, 0x68, 0xe2, 0xa1, 0xe0, 0x18, 0xbc, 0x31, 0xf5, 0x02, 0x22, 0x35 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.15", + /* Message */ + 38, + { 0x07, 0x3c, 0x43, 0x67, 0xba, 0xfd, 0x48, 0x10, 0xd7, 0x70, 0x44, 0x60, 0xc7, 0x83, 0xd3, 0x50, 0xf7, 0xcc, 0xd0, 0x99, 0x47, 0x2f, 0x79, 0xf7, 0xfd, 0xf2, 0x3e, 0xf0, 0xcf, 0xaa, 0xcc, 0xab, 0x95, 0x71, 0xdf, 0x53, 0xfd, 0xe4 } +, + /* Seed */ + 88, + { 0xf9, 0x5a, 0x39, 0x96, 0xde, 0xf1, 0xca, 0xfc, 0x1a, 0x4a, 0x0b, 0x34, 0x14, 0x6b, 0x73, 0xde, 0x6b, 0x5a, 0x92, 0xcb, 0x81, 0x2e, 0x20, 0xb2, 0x0c, 0x12, 0x2a, 0x25, 0x1e, 0x6b, 0x22, 0xe0, 0x46, 0x9c, 0x98, 0xdb, 0x12, 0x8d, 0x43, 0xce, 0xfc, 0xdd, 0x80, 0xc7, 0xff, 0x36, 0x99, 0x80, 0x16, 0xa8, 0x92, 0xa8, 0xb6, 0x34, 0xb3, 0x6b, 0x9b, 0x0c, 0xe8, 0x7e, 0xa8, 0x0b, 0x5d, 0xd9, 0xfd, 0x7a, 0x08, 0x29, 0x14, 0xe7, 0x3b, 0x83, 0xa3, 0x84, 0x1d, 0xe5, 0x1b, 0x71, 0xb1, 0xa6, 0xb7, 0xef, 0x7d, 0xe4, 0xe4, 0xb8, 0x8e, 0xdc } +, + /* Encryption */ + 129, + { 0x02, 0xde, 0xe4, 0x8b, 0x0f, 0x99, 0x53, 0xee, 0x12, 0xc7, 0x18, 0xb3, 0x03, 0xb0, 0xc8, 0x9d, 0x61, 0x50, 0xeb, 0xbe, 0x83, 0xad, 0x62, 0x4e, 0x11, 0x7e, 0x3f, 0x27, 0x04, 0xa0, 0xb1, 0x7a, 0x2e, 0xbe, 0xe8, 0x38, 0x52, 0x56, 0xf0, 0xe6, 0x42, 0x80, 0xfb, 0x06, 0xc3, 0xb1, 0x46, 0xc0, 0x99, 0xaf, 0x23, 0xa9, 0xf2, 0x47, 0x93, 0x39, 0x37, 0x81, 0xa5, 0x55, 0xac, 0x4e, 0xa2, 0xd8, 0x8d, 0x78, 0x5d, 0x8c, 0xdb, 0x6e, 0x7a, 0x2f, 0x89, 0x52, 0xd2, 0x50, 0x3c, 0xcf, 0x90, 0x1f, 0x12, 0x39, 0xf6, 0xf7, 0xb1, 0xac, 0xd4, 0x41, 0x21, 0xc3, 0x65, 0xfd, 0xae, 0x37, 0x07, 0x46, 0xde, 0x45, 0x26, 0xe7, 0xc6, 0x56, 0x0f, 0x87, 0x54, 0x6e, 0xd5, 0x77, 0xcf, 0x97, 0x98, 0xbe, 0xf4, 0x7e, 0x49, 0x20, 0x65, 0x50, 0x9c, 0x49, 0x21, 0x2d, 0x37, 0x0d, 0xea, 0x05, 0x22, 0xd7, 0x94 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.16", + /* Message */ + 42, + { 0xba, 0xb2, 0x0b, 0x9a, 0x6a, 0x53, 0x2e, 0x6f, 0x8a, 0xf0, 0x78, 0xb3, 0xa1, 0x85, 0xe0, 0xaa, 0x86, 0xe6, 0x16, 0x81, 0xbd, 0x1b, 0xd7, 0x75, 0x04, 0x4a, 0x2c, 0x95, 0x8d, 0x61, 0xed, 0xc2, 0x51, 0x60, 0x7c, 0xd9, 0xf3, 0x11, 0x48, 0xf5, 0xa9, 0x11 } +, + /* Seed */ + 84, + { 0x37, 0x6c, 0xf0, 0x18, 0x14, 0x3b, 0x0c, 0xe6, 0x70, 0x21, 0x68, 0x4c, 0xbb, 0x36, 0xe4, 0xaf, 0xe2, 0xff, 0x9d, 0xe1, 0x8b, 0xc7, 0xf0, 0x2b, 0xed, 0x86, 0x3b, 0xf1, 0xbc, 0x34, 0x66, 0x31, 0x9e, 0x72, 0x0f, 0xee, 0xf1, 0x9d, 0x38, 0xe2, 0x6b, 0xca, 0x7e, 0x99, 0xd4, 0x09, 0x6a, 0x9e, 0xed, 0x8d, 0xe5, 0xbf, 0x20, 0x3f, 0xc7, 0xdd, 0x9c, 0x84, 0x85, 0xdf, 0xa5, 0xb6, 0x90, 0x75, 0xef, 0x0c, 0xc0, 0x37, 0xfc, 0xdf, 0xb5, 0x5a, 0x0c, 0x92, 0x8c, 0xda, 0xc0, 0xcb, 0xa0, 0x49, 0x7e, 0xb6, 0x0e, 0x3f } +, + /* Encryption */ + 129, + { 0x04, 0x8d, 0xd7, 0x50, 0x99, 0x18, 0x43, 0x0e, 0xda, 0xbc, 0x01, 0x46, 0x8d, 0xb7, 0xe2, 0x87, 0xa7, 0x38, 0x1e, 0x42, 0x8b, 0x5f, 0xc9, 0x3c, 0xe8, 0xde, 0xfd, 0x7f, 0x49, 0xd5, 0xe9, 0x34, 0x15, 0x30, 0x43, 0xd1, 0x37, 0xac, 0xa9, 0xf7, 0xb9, 0x75, 0x77, 0xb7, 0x0d, 0xc0, 0x16, 0x80, 0xf2, 0xdb, 0xa9, 0x1e, 0x93, 0x2b, 0x53, 0xac, 0xf2, 0xa7, 0xf3, 0x34, 0x8f, 0x56, 0x54, 0xb2, 0xcf, 0xcf, 0xe7, 0x5d, 0x48, 0xf0, 0xfa, 0x45, 0x00, 0xd1, 0xba, 0x5d, 0x29, 0x24, 0x7f, 0xf1, 0x42, 0xd6, 0xb9, 0x80, 0xe1, 0x1b, 0x9d, 0xba, 0x68, 0x83, 0xf7, 0x3b, 0xb8, 0x55, 0xa2, 0x4c, 0xc4, 0xeb, 0x90, 0x68, 0x23, 0x6d, 0xaa, 0x0f, 0x2f, 0x93, 0x45, 0x8d, 0x72, 0x72, 0x6c, 0x2d, 0x8e, 0x31, 0x25, 0x9a, 0xcd, 0x3a, 0x7f, 0xde, 0xb6, 0xfe, 0xb5, 0xc6, 0xd2, 0xed, 0x17, 0x8d, 0xdb } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.17", + /* Message */ + 63, + { 0x19, 0xb1, 0xf4, 0xcd, 0x3d, 0xbd, 0xf0, 0x5b, 0x3d, 0x5f, 0x16, 0x80, 0x85, 0x6c, 0x5a, 0x74, 0x4f, 0x51, 0x62, 0xb5, 0x20, 0xbf, 0xcd, 0xfc, 0x98, 0x87, 0xdd, 0x92, 0xbe, 0x9d, 0x8c, 0xb6, 0x25, 0xc7, 0x25, 0xad, 0x75, 0xf4, 0xf2, 0xca, 0xa5, 0xef, 0x51, 0xfa, 0xca, 0x71, 0xb5, 0xe6, 0x6f, 0x84, 0xf2, 0xfc, 0x6f, 0x67, 0x8a, 0xce, 0x80, 0x9d, 0x76, 0xb8, 0x42, 0xea, 0xfe } +, + /* Seed */ + 63, + { 0x78, 0xa7, 0x18, 0x82, 0x85, 0x3d, 0x85, 0xaf, 0x16, 0x5c, 0xc0, 0xb2, 0x2f, 0xfd, 0xc8, 0x87, 0x3d, 0xf4, 0x9e, 0x2d, 0x6c, 0xc0, 0xad, 0x0b, 0x0a, 0x99, 0x5b, 0x4a, 0x25, 0x9c, 0x86, 0x7d, 0xc1, 0xaa, 0xb6, 0x42, 0x8a, 0x5b, 0x8e, 0x9f, 0x3b, 0xe8, 0x7d, 0x87, 0xf9, 0xe6, 0xea, 0xc5, 0x50, 0xf4, 0xdf, 0x11, 0x36, 0x8e, 0x7f, 0x6c, 0xfd, 0x7d, 0x0e, 0x47, 0x6a, 0x45, 0x9b } +, + /* Encryption */ + 129, + { 0x06, 0x2a, 0x78, 0xdb, 0x5c, 0xa6, 0x9a, 0x30, 0x48, 0x10, 0x78, 0x94, 0x93, 0xdb, 0x8c, 0xd6, 0x44, 0xfb, 0x29, 0x4e, 0x17, 0xfd, 0x36, 0x45, 0x32, 0xb8, 0xec, 0x17, 0xce, 0x3f, 0xda, 0x70, 0x47, 0x64, 0x65, 0x62, 0x4a, 0x60, 0xa6, 0xec, 0xdb, 0xd5, 0xd9, 0x72, 0x40, 0xc8, 0xd8, 0x9d, 0xea, 0xc1, 0x1d, 0xc3, 0x0d, 0x7b, 0x85, 0x14, 0x41, 0x40, 0x8e, 0xdd, 0x64, 0x28, 0x81, 0xa0, 0x11, 0x2b, 0x62, 0xf8, 0xcf, 0xde, 0x34, 0xd9, 0xc1, 0x13, 0x85, 0xc2, 0x91, 0x89, 0xbf, 0x38, 0x93, 0xa6, 0xab, 0xac, 0xe0, 0x4a, 0x10, 0xaa, 0x68, 0x0c, 0xd3, 0xa6, 0xee, 0x00, 0x2c, 0x30, 0x70, 0x35, 0xd2, 0x39, 0x9a, 0x2a, 0x60, 0xb5, 0xa7, 0xf1, 0xca, 0xaf, 0x05, 0x84, 0xd1, 0x0f, 0xd0, 0x6d, 0x6e, 0xfd, 0x56, 0x11, 0x4c, 0x05, 0xe4, 0x3d, 0x42, 0xd8, 0x34, 0xf0, 0x3e, 0x3f, 0xe9 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.18", + /* Message */ + 32, + { 0x8c, 0xb7, 0x3b, 0xc4, 0x78, 0x50, 0xc1, 0x7f, 0xeb, 0xd3, 0x4f, 0xf4, 0xb7, 0x32, 0x3b, 0x50, 0x53, 0x03, 0x0b, 0x96, 0x22, 0x14, 0x03, 0xcd, 0xef, 0x45, 0xde, 0xc6, 0x5b, 0xa6, 0x0e, 0xa3 } +, + /* Seed */ + 94, + { 0xed, 0x64, 0x78, 0x61, 0x48, 0x81, 0xeb, 0xe3, 0xfd, 0xd6, 0xd9, 0xee, 0x05, 0xf2, 0x76, 0x5f, 0xc8, 0xa3, 0xea, 0xa5, 0x80, 0x31, 0x23, 0x5a, 0xf9, 0x6f, 0x86, 0xe7, 0xf2, 0xc8, 0x13, 0xec, 0x04, 0x80, 0x66, 0x1d, 0x1c, 0x2b, 0x4d, 0xef, 0x74, 0x2b, 0x2e, 0x41, 0x41, 0x9d, 0xf2, 0x88, 0x3e, 0xd5, 0x86, 0x79, 0xcb, 0x9a, 0xda, 0xe4, 0xde, 0xc4, 0xcf, 0x77, 0xf8, 0xbc, 0x29, 0x41, 0xd0, 0x33, 0xf8, 0x87, 0x7a, 0x90, 0x6d, 0xdc, 0x88, 0xd6, 0xdd, 0x3c, 0x53, 0x96, 0xad, 0xaa, 0xc0, 0x3e, 0xb2, 0xa7, 0x09, 0x4c, 0x0f, 0xdf, 0x0a, 0x44, 0xa6, 0xb9, 0x23, 0xab } +, + /* Encryption */ + 129, + { 0x03, 0x97, 0x8d, 0x4e, 0xff, 0xc6, 0xd6, 0x2f, 0x23, 0x2b, 0xf4, 0x6b, 0x42, 0x90, 0xc5, 0x01, 0x1d, 0x73, 0x28, 0x0a, 0xb0, 0xe8, 0x0a, 0xb9, 0xd6, 0x05, 0x0a, 0x85, 0x2a, 0x66, 0x79, 0xe0, 0x17, 0xe1, 0x70, 0xd9, 0xe7, 0x15, 0x6c, 0x8d, 0xcb, 0xd4, 0x6c, 0xde, 0xda, 0x70, 0xff, 0x9a, 0x55, 0x16, 0x8b, 0x9f, 0xdc, 0x03, 0x65, 0xb8, 0xaa, 0xbb, 0x90, 0x9a, 0xad, 0x40, 0xd5, 0x95, 0xc9, 0x0b, 0x9f, 0x00, 0xc1, 0xe0, 0x0a, 0xd6, 0xf0, 0x1d, 0x54, 0x43, 0x07, 0xb2, 0x54, 0xea, 0xf4, 0x25, 0x5d, 0xe6, 0x2b, 0xfd, 0x8a, 0x5f, 0x7e, 0x79, 0xdc, 0xfc, 0x74, 0x45, 0xce, 0xc6, 0x3d, 0xf0, 0xc2, 0xbd, 0x0a, 0xd9, 0x6c, 0xb7, 0x02, 0x42, 0xb3, 0x0b, 0x32, 0x42, 0x07, 0x88, 0x16, 0xb5, 0x8b, 0x0a, 0x9f, 0xfa, 0x16, 0xf1, 0xd8, 0x63, 0x15, 0xf8, 0xa1, 0xcb, 0x2f, 0x8f, 0x6b } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.19", + /* Message */ + 56, + { 0x8e, 0xa5, 0x56, 0x43, 0xdf, 0xe7, 0xcb, 0xe0, 0x75, 0xc1, 0x7b, 0x93, 0xc6, 0xba, 0x6b, 0x5a, 0x74, 0xea, 0x8d, 0x1a, 0xba, 0xb9, 0xc7, 0x28, 0xae, 0x5b, 0x00, 0x86, 0x6c, 0x62, 0x88, 0x0d, 0x3c, 0x00, 0x05, 0x20, 0x37, 0xcf, 0x80, 0x2d, 0x2c, 0xf2, 0xa8, 0xe1, 0xbe, 0xa5, 0x8c, 0x7b, 0xa6, 0x04, 0x77, 0x4d, 0x4f, 0x80, 0xbc, 0x04 } +, + /* Seed */ + 70, + { 0xaf, 0x9d, 0x9d, 0x31, 0x2e, 0x22, 0x57, 0x0f, 0xbc, 0x4b, 0xc8, 0x5a, 0x44, 0x5e, 0xd8, 0xd8, 0x99, 0x66, 0x0e, 0xd2, 0x4c, 0xf0, 0x30, 0x15, 0x33, 0x94, 0x6e, 0x5c, 0xb9, 0x47, 0x1a, 0x27, 0xc5, 0x10, 0xcd, 0x17, 0x55, 0x91, 0xd2, 0x3d, 0x36, 0x3d, 0xc4, 0xe3, 0xe6, 0x9c, 0x7b, 0xb4, 0x65, 0x51, 0x7a, 0x4c, 0xd1, 0xd1, 0xce, 0x41, 0x3e, 0x10, 0x16, 0xae, 0xaf, 0xd5, 0x5d, 0x2c, 0xb9, 0xde, 0xbc, 0xfe, 0x4b, 0x1d } +, + /* Encryption */ + 129, + { 0x05, 0x87, 0x11, 0x19, 0x16, 0xbb, 0x42, 0xf8, 0x47, 0x57, 0x69, 0x1e, 0xfe, 0xde, 0x7e, 0xb7, 0x79, 0x6a, 0x5c, 0xf8, 0x87, 0xc3, 0x7c, 0xa9, 0xf6, 0x1b, 0x45, 0x1f, 0xb1, 0xba, 0xde, 0x38, 0x9c, 0xfc, 0x5f, 0xdc, 0x21, 0x98, 0x41, 0xbb, 0x41, 0xda, 0x82, 0x74, 0x52, 0x72, 0x5f, 0xc8, 0x2b, 0x4d, 0x1a, 0xde, 0x56, 0x9c, 0xee, 0xc8, 0x05, 0x79, 0xed, 0xb1, 0xb4, 0xb1, 0x5b, 0x46, 0xad, 0x7d, 0x45, 0xb2, 0x45, 0x98, 0x80, 0x23, 0xea, 0x0d, 0xfc, 0xb3, 0x74, 0x4a, 0x69, 0x2e, 0xb9, 0xac, 0xa8, 0x5f, 0x21, 0x10, 0x10, 0xaf, 0xb1, 0xe9, 0x89, 0x4f, 0x85, 0x4a, 0x5e, 0x34, 0xfe, 0x89, 0xaa, 0x05, 0x19, 0x68, 0xa3, 0xb2, 0x36, 0x2c, 0x15, 0x0c, 0x6d, 0x97, 0x0e, 0xdd, 0x82, 0xb9, 0xe2, 0xd1, 0x3b, 0x38, 0xc3, 0xc2, 0x95, 0x6d, 0x91, 0x50, 0x08, 0x86, 0x41, 0xd5, 0x30 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 9.20", + /* Message */ + 4, + { 0x52, 0x5c, 0xff, 0xa3 } +, + /* Seed */ + 122, + { 0x0c, 0x99, 0x30, 0x4c, 0xc6, 0x26, 0x3d, 0x1e, 0xe2, 0x44, 0x6e, 0x24, 0x8c, 0x27, 0x11, 0x2c, 0x8f, 0x96, 0xda, 0x82, 0x51, 0x5f, 0x06, 0xf8, 0x12, 0x39, 0x8a, 0x88, 0x81, 0x1f, 0x39, 0xfb, 0x05, 0x62, 0x05, 0xc4, 0x4d, 0x6b, 0xd4, 0x85, 0x5a, 0x62, 0xc2, 0x1c, 0x60, 0x1b, 0x88, 0xf8, 0x02, 0x34, 0xe2, 0x32, 0x41, 0xf7, 0x16, 0x32, 0x2d, 0x80, 0x54, 0xa8, 0x4a, 0x1f, 0xc3, 0xc8, 0x46, 0xde, 0xfb, 0x61, 0x76, 0x7c, 0xc4, 0xd8, 0x16, 0xfa, 0x7b, 0x37, 0x47, 0xf8, 0x72, 0x9b, 0xf3, 0x37, 0x2a, 0xc2, 0xc2, 0x29, 0xd0, 0x52, 0xf4, 0x5b, 0xc4, 0x2f, 0xc3, 0x80, 0x50, 0xdc, 0xa3, 0xf2, 0x63, 0x2e, 0x60, 0x07, 0xb6, 0x08, 0x53, 0xb7, 0xe0, 0xcc, 0xb3, 0xda, 0xa4, 0x94, 0xe5, 0x53, 0x35, 0xfd, 0x04, 0xf1, 0x3d, 0x5f, 0xad, 0xa7 } +, + /* Encryption */ + 129, + { 0x06, 0x3e, 0x45, 0x08, 0xe5, 0x31, 0x2b, 0x5c, 0x38, 0x69, 0x4d, 0xe8, 0x2a, 0x71, 0xed, 0xa3, 0x12, 0xe9, 0xae, 0xd0, 0x5b, 0xc1, 0x43, 0xd3, 0x38, 0xf7, 0xf2, 0x28, 0x12, 0xd9, 0x3c, 0x28, 0x65, 0x12, 0x6a, 0x9b, 0x3a, 0x42, 0xc3, 0xca, 0x19, 0xed, 0xb3, 0x46, 0x01, 0xc0, 0xb2, 0x8a, 0x75, 0x66, 0x3b, 0x18, 0xf2, 0x39, 0xf5, 0xad, 0xca, 0xa4, 0xe9, 0xfa, 0x9f, 0x61, 0x18, 0x04, 0x72, 0x6f, 0xa1, 0x29, 0x62, 0xbb, 0xa3, 0x23, 0x0c, 0xb8, 0x86, 0xd6, 0x67, 0x82, 0xa4, 0x7e, 0xa9, 0x50, 0x2a, 0x83, 0x71, 0xe7, 0x57, 0x3b, 0xb6, 0xb0, 0x26, 0x6c, 0x33, 0x64, 0x6b, 0xdf, 0x53, 0xf8, 0xde, 0x36, 0x8e, 0xf2, 0x05, 0xb1, 0x1a, 0x85, 0xba, 0xf2, 0x1d, 0xaf, 0x3c, 0xe7, 0xa2, 0x59, 0x9f, 0x00, 0x8b, 0x99, 0x45, 0xee, 0xb1, 0x86, 0xec, 0x19, 0x2c, 0x54, 0x0a, 0xc2, 0x3c } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 10: A 1028-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x0b, 0x52, 0xcb, 0x6b, 0x5c, 0x3b, 0x9e, 0xc5, 0xaa, 0xad, 0x89, 0x4e, 0x51, 0x77, 0xf7, 0xf4, 0x5b, 0x8d, 0x33, 0xdc, 0xbb, 0xe9, 0x6a, 0x5b, 0x26, 0xf3, 0x00, 0x72, 0xbf, 0x15, 0x73, 0xa6, 0xc4, 0x1f, 0xb0, 0xa9, 0x7a, 0xe1, 0xe5, 0x2e, 0xd8, 0xc2, 0x5c, 0x62, 0xb9, 0x8b, 0xf5, 0x9d, 0xe7, 0xb6, 0x8a, 0xb9, 0x8c, 0x2d, 0x8b, 0x93, 0xc4, 0x94, 0x27, 0x23, 0xcc, 0x4b, 0xae, 0xd2, 0xb3, 0x93, 0xc0, 0x7b, 0x2b, 0x11, 0x90, 0x9c, 0x73, 0x2d, 0xf7, 0xc1, 0xdc, 0xbb, 0x43, 0x3a, 0x83, 0x9d, 0x46, 0xf4, 0x28, 0xe9, 0xdd, 0xc8, 0xd3, 0x5f, 0xd3, 0x3e, 0xed, 0x29, 0x81, 0x80, 0xf7, 0x5f, 0x2d, 0x5c, 0x9f, 0xe8, 0x53, 0x4f, 0x03, 0x47, 0xf8, 0x68, 0x5c, 0x28, 0xc4, 0x37, 0xea, 0x5b, 0x81, 0x1a, 0x28, 0x6e, 0x81, 0x0c, 0x69, 0x7a, 0x88, 0xcd, 0x7e, 0x45, 0x36, 0x4c, 0x1f } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x45, 0xcc, 0x14, 0x17, 0xb2, 0x6f, 0xce, 0x3e, 0x9f, 0xd3, 0x10, 0x89, 0xb1, 0xa3, 0xcc, 0xc4, 0x6f, 0x8f, 0xf2, 0x1e, 0xac, 0x2e, 0x1d, 0x67, 0xc0, 0xae, 0x20, 0x15, 0x2d, 0xc5, 0x0d, 0x1c, 0xe7, 0xce, 0x6f, 0x26, 0x40, 0x4e, 0x2e, 0x64, 0x95, 0xb9, 0x77, 0xbf, 0x13, 0xf9, 0xa4, 0x05, 0xb2, 0x45, 0x80, 0xd6, 0x39, 0x3a, 0x85, 0x22, 0x54, 0x96, 0xe4, 0xab, 0xc4, 0x9e, 0xbe, 0xff, 0xde, 0x70, 0xcf, 0x26, 0x76, 0x68, 0x66, 0xf2, 0x76, 0xe1, 0x5b, 0x49, 0x2a, 0xf8, 0x03, 0x3f, 0x1b, 0xac, 0x7f, 0x66, 0xb7, 0x1a, 0x3b, 0xaf, 0x57, 0x1f, 0xfc, 0xcc, 0x03, 0x8a, 0x48, 0x86, 0x93, 0x94, 0xcc, 0xa3, 0xfa, 0x00, 0x49, 0x85, 0xb4, 0x34, 0xa5, 0x15, 0x17, 0x87, 0x7e, 0xae, 0x97, 0xa3, 0x84, 0x94, 0x7f, 0x01, 0xa7, 0x2c, 0xf4, 0xb2, 0x01, 0x93, 0xdd, 0x27, 0x64, 0x81 } +, + /* Prime 1 */ + 65, + { 0x03, 0x5f, 0xed, 0xee, 0x7e, 0x64, 0xfd, 0x68, 0x65, 0x79, 0x31, 0xa9, 0xdf, 0x9d, 0x55, 0x62, 0x28, 0xdf, 0xc6, 0x33, 0xa7, 0x50, 0x02, 0x76, 0x8f, 0x65, 0xd7, 0x15, 0xf0, 0x44, 0xf2, 0x3b, 0x3f, 0xe7, 0x88, 0xbb, 0x17, 0x86, 0x4d, 0x61, 0xdf, 0x57, 0x9e, 0x68, 0xdf, 0x80, 0xde, 0xa3, 0xa6, 0x31, 0x90, 0x62, 0x9d, 0xac, 0x7d, 0xe6, 0x29, 0xef, 0x9a, 0xb8, 0xf4, 0xdf, 0x0b, 0x27, 0x7f } +, + /* Prime 2 */ + 65, + { 0x03, 0x5a, 0xf8, 0xe6, 0xfe, 0x2f, 0x84, 0x61, 0xfc, 0x89, 0xa6, 0x45, 0x00, 0xf8, 0x19, 0x9c, 0xcb, 0xd3, 0xf4, 0x69, 0x07, 0x85, 0x96, 0x15, 0x56, 0x03, 0xd3, 0xf0, 0x88, 0x08, 0x33, 0xc3, 0x77, 0xdb, 0x07, 0x8e, 0x43, 0x7e, 0x35, 0x60, 0x00, 0x4a, 0xd1, 0xd6, 0xf8, 0xd3, 0x47, 0x88, 0x3f, 0x3e, 0xb0, 0x1d, 0x18, 0x9d, 0x52, 0xef, 0xf6, 0xe2, 0x60, 0xe5, 0x2f, 0xba, 0xa6, 0x2b, 0x61 } +, + /* Prime exponent 1 */ + 64, + { 0xb2, 0x43, 0xb3, 0x49, 0x8b, 0x67, 0x2a, 0xaa, 0x7d, 0x96, 0x7c, 0xd9, 0xf2, 0x6a, 0x12, 0xe6, 0x22, 0x3e, 0x90, 0x9b, 0xfe, 0x8b, 0x73, 0x91, 0x65, 0x4f, 0x3b, 0x6c, 0xa7, 0x9d, 0x60, 0x12, 0x70, 0xa1, 0x2b, 0x11, 0xd0, 0x99, 0x99, 0x0f, 0x6f, 0xd1, 0xf5, 0x0b, 0xe1, 0x58, 0x8f, 0x66, 0x14, 0xa6, 0x19, 0x63, 0x35, 0x9b, 0x88, 0xe9, 0xb0, 0x52, 0x39, 0xc5, 0xf5, 0x5c, 0x24, 0xdb } +, + /* Prime exponent 2 */ + 65, + { 0x01, 0x35, 0x25, 0xad, 0xe5, 0x3f, 0xee, 0xd2, 0x61, 0x54, 0x9d, 0x3d, 0xea, 0x8a, 0x60, 0x95, 0x79, 0x1a, 0x90, 0xb5, 0x98, 0x5a, 0x70, 0xd8, 0xbe, 0xfb, 0x63, 0xb5, 0x07, 0x10, 0x84, 0xa8, 0xce, 0x23, 0x4b, 0x85, 0xdd, 0x2e, 0xb8, 0x41, 0x13, 0xf9, 0xd9, 0xaa, 0x18, 0x25, 0xda, 0x71, 0xe3, 0xe9, 0x48, 0xf3, 0x3f, 0xdf, 0xa7, 0x70, 0xec, 0x17, 0x2f, 0xae, 0x6c, 0xce, 0x2d, 0x6e, 0x21 } +, + /* Coefficient */ + 64, + { 0x1c, 0x52, 0x92, 0x93, 0x3c, 0x58, 0xd0, 0x22, 0x59, 0x2f, 0xc0, 0x03, 0x38, 0xbf, 0x22, 0xed, 0xfc, 0xba, 0x33, 0x16, 0x16, 0xb7, 0x9f, 0x8d, 0x2e, 0xfd, 0x1f, 0xa2, 0x4c, 0x64, 0xf5, 0xdc, 0xfa, 0xd9, 0xaa, 0x52, 0xba, 0xa4, 0x6e, 0x86, 0x59, 0xdd, 0xa9, 0xea, 0xb3, 0xa7, 0x86, 0x3e, 0x61, 0x37, 0x4a, 0xc0, 0xda, 0xe0, 0x18, 0x5f, 0xb5, 0x8e, 0xcb, 0x0b, 0x74, 0x65, 0xee, 0x07 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 10.1", + /* Message */ + 46, + { 0x59, 0x22, 0xd0, 0x9f, 0xdf, 0x65, 0x22, 0x80, 0x2f, 0xbc, 0xf7, 0xa2, 0x8e, 0xc3, 0xd9, 0xfa, 0xdf, 0x60, 0x72, 0x03, 0xa3, 0x1b, 0xd0, 0xda, 0x96, 0x3a, 0xa0, 0x31, 0x5f, 0x35, 0xe1, 0xa0, 0xa3, 0x74, 0xd4, 0x87, 0xdd, 0x08, 0x62, 0xa6, 0xf6, 0xbe, 0xc9, 0x32, 0xb7, 0xdb } +, + /* Seed */ + 80, + { 0x61, 0x39, 0x5a, 0x0f, 0xa1, 0x2e, 0x1e, 0xc2, 0xff, 0xea, 0x2a, 0x88, 0x90, 0x65, 0x3e, 0x8f, 0x37, 0x8d, 0xc4, 0x6c, 0xe2, 0xb8, 0xaa, 0x4a, 0x0a, 0x1c, 0x56, 0x7b, 0x30, 0xe5, 0x9c, 0x3a, 0x33, 0xa6, 0x68, 0x98, 0x97, 0x14, 0xfc, 0x3d, 0x45, 0xac, 0x88, 0x63, 0x27, 0xe3, 0x6c, 0x34, 0x5d, 0xa8, 0x58, 0xf9, 0x03, 0xd1, 0xe6, 0x06, 0x74, 0x03, 0x14, 0xcb, 0x80, 0x8d, 0x86, 0xab, 0xc3, 0x1b, 0x49, 0xb3, 0x5b, 0x3f, 0x20, 0xe3, 0x79, 0x29, 0xdc, 0xc8, 0x59, 0xd5, 0x91, 0x41 } +, + /* Encryption */ + 129, + { 0x04, 0x39, 0xe7, 0xdd, 0x09, 0xaf, 0x61, 0xc0, 0xee, 0x25, 0xf3, 0xe5, 0xc2, 0x95, 0x1d, 0xa4, 0x9d, 0x3f, 0xd7, 0x08, 0xb2, 0x97, 0xa3, 0x05, 0x5f, 0xf9, 0x98, 0x3a, 0x9e, 0xa5, 0x38, 0xb8, 0x3d, 0x59, 0xda, 0xbd, 0xb8, 0x5d, 0xaf, 0x82, 0xae, 0x7b, 0xb1, 0x97, 0x8e, 0x7d, 0xa2, 0xa6, 0xdc, 0x05, 0x87, 0xef, 0x9c, 0x73, 0x2e, 0xe6, 0x88, 0x37, 0x3f, 0xbc, 0xbf, 0xa2, 0xda, 0xcf, 0xf9, 0xb3, 0xc1, 0x2f, 0x70, 0x4e, 0xe1, 0x4f, 0x83, 0x24, 0xbd, 0x4c, 0xc6, 0xbf, 0x9d, 0xcd, 0x3f, 0x05, 0x33, 0xc3, 0xb1, 0x1a, 0x0d, 0x38, 0xdb, 0xcc, 0x7b, 0xb7, 0xef, 0x9a, 0x72, 0x29, 0x6b, 0x6c, 0x13, 0xdc, 0x42, 0xd7, 0xec, 0x17, 0xf8, 0x51, 0xa5, 0x16, 0x12, 0xc7, 0x49, 0x4c, 0x63, 0x68, 0xa7, 0xfb, 0xec, 0x93, 0xd2, 0x2e, 0x8f, 0x9b, 0x72, 0xbd, 0xc0, 0x44, 0x9f, 0xb4, 0x30 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 10.2", + /* Message */ + 62, + { 0x5f, 0xba, 0xd4, 0x3a, 0x91, 0x0a, 0x29, 0x0e, 0x50, 0x55, 0xd5, 0x14, 0xe7, 0x1c, 0x8e, 0xab, 0xf1, 0xf9, 0x33, 0x20, 0xeb, 0xd0, 0xda, 0x8f, 0x90, 0xd1, 0x46, 0xa8, 0xf3, 0xdd, 0x5c, 0x1a, 0x2c, 0x72, 0x0b, 0x93, 0x21, 0x1e, 0x48, 0x29, 0x34, 0x14, 0x9f, 0x1d, 0x21, 0xb9, 0x78, 0xf4, 0x8a, 0x0b, 0xb8, 0xe4, 0xcc, 0xa3, 0xf5, 0xd4, 0x5d, 0x3f, 0x3e, 0x3b, 0xa8, 0xe1 } +, + /* Seed */ + 64, + { 0x21, 0x04, 0x52, 0x61, 0x80, 0x4b, 0xf7, 0x54, 0xbc, 0xb8, 0xbf, 0x34, 0x98, 0xb1, 0xad, 0x10, 0xaf, 0xf3, 0x3d, 0xa1, 0xf2, 0x25, 0xed, 0xa5, 0x64, 0x65, 0x90, 0x45, 0x8b, 0x20, 0x70, 0x9f, 0xc8, 0xd0, 0xb4, 0x98, 0x90, 0x7a, 0x83, 0x64, 0xce, 0x1c, 0x43, 0x6b, 0x6b, 0x1e, 0x73, 0x18, 0x1c, 0x86, 0xc6, 0x77, 0xaf, 0x45, 0xc1, 0x7f, 0x9e, 0x4a, 0xf3, 0x75, 0x9c, 0xad, 0x24, 0x87 } +, + /* Encryption */ + 129, + { 0x02, 0x9f, 0x64, 0xac, 0x33, 0x01, 0x34, 0x00, 0x7f, 0x77, 0xf7, 0x2c, 0x37, 0xf4, 0x17, 0x7c, 0x24, 0xd6, 0x60, 0xbe, 0x4e, 0xba, 0xc1, 0x86, 0x8a, 0xd1, 0x1f, 0x9e, 0x30, 0x51, 0xb8, 0xcd, 0x77, 0xc4, 0x69, 0x11, 0x99, 0xac, 0x49, 0x19, 0xdb, 0x2e, 0xd3, 0x63, 0x74, 0x0d, 0x2d, 0xde, 0x32, 0x91, 0xf1, 0x0d, 0x92, 0x68, 0xe7, 0xc7, 0xde, 0x37, 0xea, 0x42, 0x1e, 0xbb, 0x1f, 0xad, 0x65, 0x29, 0xf2, 0x92, 0x19, 0x2a, 0x96, 0x80, 0xba, 0x96, 0x3e, 0xda, 0x93, 0x74, 0x03, 0x7a, 0xb9, 0x52, 0x9a, 0x48, 0x6f, 0x35, 0xcb, 0xd2, 0x9e, 0x09, 0xea, 0x98, 0xa5, 0x04, 0x5d, 0x9e, 0x16, 0xbb, 0x87, 0x70, 0x15, 0x5d, 0x70, 0xaf, 0xd2, 0x17, 0xa1, 0x46, 0x86, 0x27, 0x49, 0xec, 0x1a, 0xd1, 0x59, 0xcf, 0x6e, 0x6a, 0x63, 0xdf, 0x14, 0x2b, 0x82, 0x46, 0xd8, 0x44, 0xa7, 0x37, 0x2d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.3", + /* Message */ + 62, + { 0x22, 0xbb, 0xc6, 0x16, 0xec, 0x6e, 0xf3, 0x57, 0x31, 0x56, 0xb4, 0x17, 0x61, 0xac, 0x3b, 0xdb, 0x57, 0xbd, 0x9b, 0x70, 0x36, 0xed, 0xc9, 0xa6, 0x97, 0x88, 0x75, 0xe2, 0xa6, 0x14, 0xcd, 0xe3, 0xef, 0xed, 0xaf, 0xd3, 0x88, 0x9a, 0x5d, 0xbd, 0xcc, 0x5f, 0xad, 0x9e, 0x9b, 0xec, 0xf8, 0xa8, 0xbb, 0x80, 0x33, 0xff, 0x91, 0xdf, 0xed, 0x60, 0x4b, 0xf8, 0xc6, 0xe9, 0xbb, 0xc7 } +, + /* Seed */ + 64, + { 0x3b, 0x47, 0xd2, 0xca, 0x95, 0x54, 0xb3, 0x4f, 0x94, 0x29, 0x57, 0x8d, 0x4f, 0xde, 0xc5, 0xd9, 0x6e, 0xca, 0x89, 0xb6, 0x81, 0x72, 0xd1, 0xdb, 0x13, 0x56, 0xb3, 0xda, 0x7a, 0x69, 0xf1, 0x58, 0x4d, 0x4c, 0x84, 0x6b, 0x18, 0x43, 0x2f, 0x02, 0xf2, 0x59, 0xca, 0xdc, 0x24, 0xe1, 0x54, 0xff, 0x15, 0xf8, 0x06, 0xf2, 0x53, 0x43, 0x50, 0x0e, 0x13, 0xb5, 0xbe, 0x43, 0xc7, 0xb5, 0xae, 0x7e } +, + /* Encryption */ + 129, + { 0x00, 0xc4, 0xe6, 0xc1, 0x0c, 0x25, 0x5e, 0x4b, 0xeb, 0x2b, 0x31, 0xc1, 0x65, 0x68, 0x46, 0xb9, 0x7c, 0xa2, 0x3a, 0x3b, 0xa3, 0x2a, 0xb1, 0x9c, 0x64, 0x85, 0x20, 0x11, 0x3d, 0x70, 0x34, 0xdf, 0xa4, 0x6b, 0x0c, 0xd2, 0x3d, 0x73, 0x99, 0xa9, 0x3c, 0xb0, 0x2f, 0x1e, 0xba, 0x94, 0x83, 0x18, 0xe3, 0x79, 0x1c, 0x30, 0x6a, 0x2e, 0xb9, 0xc0, 0xc5, 0x6d, 0x8f, 0x7e, 0x83, 0x25, 0x0f, 0x83, 0xad, 0x49, 0x2f, 0xad, 0xf7, 0x83, 0x17, 0x69, 0xf0, 0x2e, 0x18, 0x24, 0x34, 0x74, 0x45, 0xd0, 0x41, 0x9b, 0x98, 0xb8, 0xe7, 0x95, 0x45, 0x65, 0x32, 0x30, 0x0b, 0x92, 0xd6, 0xe4, 0x55, 0xb5, 0xa4, 0xeb, 0xa8, 0x53, 0xd6, 0xf7, 0x45, 0x92, 0x90, 0xab, 0x02, 0x31, 0x99, 0x48, 0x53, 0xa8, 0xc0, 0x7e, 0x54, 0xf5, 0x9c, 0x62, 0x45, 0x37, 0x08, 0x02, 0x89, 0xf9, 0x31, 0x43, 0xeb, 0xc6, 0x61 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.4", + /* Message */ + 50, + { 0x31, 0x6c, 0xc4, 0x45, 0x0a, 0x53, 0x70, 0x3c, 0x05, 0x8c, 0x90, 0x1f, 0x50, 0x7d, 0x7a, 0xd0, 0xcb, 0x63, 0x96, 0xc5, 0x51, 0xd4, 0xf0, 0x61, 0x82, 0xab, 0xd3, 0xa4, 0x3a, 0xac, 0xba, 0xbb, 0x31, 0x59, 0xc0, 0x26, 0xb3, 0xe7, 0xdb, 0xc1, 0x60, 0xf4, 0x19, 0x53, 0x31, 0x7e, 0x0f, 0x20, 0x80, 0x8c } +, + /* Seed */ + 76, + { 0xc1, 0xec, 0xb1, 0x16, 0x4b, 0x3e, 0x66, 0x23, 0xf0, 0xd9, 0xb9, 0xc5, 0xeb, 0xf9, 0x9e, 0x78, 0x8b, 0x7b, 0xd9, 0x4e, 0xb7, 0x43, 0x74, 0xf6, 0x1e, 0xd3, 0x14, 0x30, 0x4c, 0xaf, 0x46, 0xf8, 0x4a, 0x3f, 0xea, 0x1b, 0xa0, 0xe4, 0x7f, 0xc8, 0xbe, 0x41, 0x97, 0xd1, 0xd2, 0xcd, 0x41, 0x41, 0xcb, 0x9a, 0x61, 0x5d, 0x89, 0xc4, 0xbd, 0x91, 0x10, 0xca, 0x6a, 0xc9, 0xa5, 0x60, 0xf0, 0x76, 0xeb, 0xe6, 0x9b, 0x74, 0xa1, 0x0f, 0xe9, 0xcc, 0xdb, 0x76, 0xda, 0xbd } +, + /* Encryption */ + 129, + { 0x06, 0x16, 0xb8, 0xbc, 0x77, 0x2c, 0x55, 0x64, 0xd4, 0x51, 0xb1, 0x28, 0xd9, 0xb1, 0x36, 0x4c, 0x9e, 0x33, 0xb6, 0xe5, 0x58, 0xec, 0x67, 0xf2, 0x10, 0x5c, 0x98, 0x00, 0x11, 0x7d, 0x0b, 0x73, 0xcc, 0xab, 0x9d, 0xb5, 0x1d, 0x96, 0x7a, 0x9d, 0x66, 0x32, 0x2c, 0xbc, 0x5a, 0x01, 0x74, 0x6e, 0x47, 0x31, 0xdd, 0x7d, 0x04, 0xe6, 0x36, 0xe6, 0x4d, 0x35, 0xf2, 0xc8, 0x6c, 0xa3, 0x9d, 0x26, 0x14, 0x92, 0x17, 0x6b, 0x8d, 0xab, 0xdb, 0x13, 0x4b, 0xe9, 0x4b, 0xe5, 0x1b, 0x6c, 0x02, 0x3a, 0x0d, 0x55, 0xfc, 0xc1, 0xf0, 0x4c, 0x94, 0xc8, 0x6d, 0x47, 0x7d, 0xb4, 0x03, 0xb0, 0x4f, 0xb6, 0xc0, 0x28, 0x50, 0x57, 0x24, 0x79, 0x38, 0x40, 0xcb, 0xf4, 0x68, 0xaa, 0xaa, 0x91, 0xbc, 0x54, 0xe0, 0xd6, 0x47, 0x7c, 0xe6, 0x48, 0xce, 0xdd, 0x12, 0x76, 0xf2, 0xad, 0x2d, 0x4d, 0x42, 0x3b, 0x6c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.5", + /* Message */ + 51, + { 0xd5, 0x4e, 0xa3, 0x7c, 0xbf, 0xbd, 0xb8, 0x18, 0x3b, 0x3b, 0x54, 0x7f, 0x6d, 0xf2, 0xd5, 0xd6, 0x3c, 0x41, 0x5b, 0x1c, 0x44, 0xed, 0x63, 0x93, 0xc6, 0x97, 0xb4, 0xd9, 0x3a, 0x97, 0xfa, 0x0d, 0x2f, 0x4d, 0x30, 0x0a, 0x68, 0xe9, 0x8f, 0x7f, 0xd0, 0x46, 0x07, 0x01, 0xd1, 0x57, 0x9d, 0x96, 0x83, 0x61, 0x2b } +, + /* Seed */ + 75, + { 0xd1, 0xce, 0xb0, 0xc0, 0x72, 0xd6, 0x88, 0x8f, 0xa9, 0x1a, 0x75, 0x7c, 0xbf, 0x50, 0xd6, 0x69, 0x76, 0xbb, 0xb7, 0x2e, 0x61, 0x94, 0x62, 0x61, 0x4d, 0x5d, 0xec, 0x0f, 0xc0, 0xbb, 0xca, 0xbb, 0x07, 0x07, 0x89, 0xc2, 0xb0, 0x89, 0x50, 0x91, 0xb8, 0xfa, 0x9c, 0x7e, 0x75, 0xab, 0x20, 0xb8, 0x97, 0x58, 0xf9, 0x7f, 0xd0, 0x47, 0xbc, 0x44, 0xa5, 0x68, 0xa2, 0x61, 0x2d, 0x0d, 0x50, 0x1d, 0x15, 0xd4, 0xfb, 0x82, 0xe7, 0x75, 0x28, 0x79, 0x69, 0x49, 0xf3 } +, + /* Encryption */ + 129, + { 0x03, 0xc1, 0x38, 0xc7, 0x91, 0x99, 0xb0, 0xb1, 0x70, 0x0b, 0xab, 0x2e, 0x63, 0xe1, 0xd2, 0xa0, 0x03, 0x1e, 0xf6, 0x02, 0xf7, 0xdd, 0xf1, 0xed, 0x3a, 0x16, 0x1a, 0x5e, 0x70, 0xf1, 0x64, 0x51, 0xda, 0xa1, 0x01, 0xf7, 0x4c, 0xdd, 0x65, 0x47, 0xa7, 0xc6, 0x52, 0xc7, 0x32, 0x9b, 0xb1, 0x73, 0x7f, 0xb1, 0x4c, 0x1c, 0xc0, 0xc0, 0xc3, 0xe7, 0x61, 0x2a, 0xe2, 0x0e, 0xe0, 0x21, 0xab, 0x21, 0xd7, 0x0b, 0xf9, 0x51, 0x7b, 0x4d, 0x33, 0xa9, 0xd8, 0x09, 0x61, 0x2e, 0x7f, 0x42, 0x68, 0x85, 0xb7, 0x9b, 0x31, 0x2e, 0x26, 0x6e, 0x42, 0xb2, 0x02, 0xb5, 0x71, 0xc6, 0x6f, 0x9a, 0x10, 0x7b, 0x8f, 0xd7, 0xc5, 0x6c, 0x05, 0x0a, 0x8e, 0x1e, 0xb1, 0x89, 0x56, 0xdb, 0x06, 0xa0, 0x20, 0x9d, 0xd1, 0x6e, 0xf2, 0xd9, 0x05, 0x24, 0xdb, 0x87, 0x91, 0x7f, 0x34, 0x00, 0x6b, 0xe6, 0xb1, 0x5a, 0x13 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.6", + /* Message */ + 9, + { 0xf6, 0x4b, 0x25, 0x11, 0xcb, 0xe3, 0xcc, 0x65, 0x81 } +, + /* Seed */ + 117, + { 0xda, 0xca, 0x19, 0x63, 0xcb, 0x3d, 0xe5, 0x24, 0x57, 0x79, 0xe9, 0x64, 0x77, 0xff, 0xda, 0x27, 0x7f, 0x4b, 0x92, 0x3f, 0xa9, 0xa8, 0xd9, 0x38, 0x5d, 0x52, 0x31, 0x69, 0x23, 0x3f, 0x58, 0x79, 0xa3, 0xc9, 0xfc, 0x7a, 0x38, 0xe1, 0xb2, 0x08, 0xc3, 0x2d, 0xe4, 0x0b, 0xbe, 0x1d, 0xa0, 0x77, 0x47, 0x1e, 0x61, 0xc8, 0xb9, 0xb7, 0x09, 0x3c, 0x41, 0xb0, 0xa6, 0x5c, 0x99, 0x64, 0x32, 0xd6, 0x45, 0x52, 0x11, 0x84, 0xa6, 0x6a, 0xfc, 0xb9, 0x6f, 0x07, 0xa8, 0xf8, 0xee, 0xbb, 0x6e, 0xf8, 0x17, 0xe0, 0x27, 0xee, 0x2f, 0x37, 0x95, 0x45, 0x23, 0x9e, 0xf6, 0xf9, 0xc1, 0xd0, 0xd8, 0x60, 0xe8, 0x21, 0x44, 0xec, 0x71, 0x59, 0x7f, 0x24, 0x6a, 0x83, 0xcc, 0xf6, 0x60, 0xea, 0x4c, 0x70, 0xee, 0x1d, 0xf0, 0x14, 0xef } +, + /* Encryption */ + 129, + { 0x05, 0x08, 0xed, 0x84, 0x5c, 0x96, 0x23, 0x8e, 0x3a, 0x07, 0xe8, 0xec, 0x02, 0x7f, 0x7b, 0x09, 0x8a, 0x83, 0xf0, 0x3e, 0xac, 0x1f, 0xec, 0x42, 0x6f, 0x4d, 0x60, 0x05, 0xb6, 0x0d, 0x07, 0x35, 0xdb, 0x05, 0x37, 0x08, 0x2f, 0x23, 0xb7, 0x50, 0xf6, 0xdb, 0x54, 0x88, 0x21, 0x41, 0x81, 0xe1, 0x14, 0xcf, 0x1f, 0x72, 0x07, 0x41, 0x9c, 0xa2, 0x93, 0x75, 0x0a, 0xa7, 0x66, 0xfa, 0x7a, 0x5b, 0x9b, 0xe0, 0x0e, 0x37, 0x29, 0x2c, 0x23, 0x23, 0x1c, 0x6a, 0xb3, 0xbe, 0x2d, 0xed, 0xee, 0xd3, 0x21, 0xb0, 0xf9, 0xcd, 0x83, 0x2c, 0x5e, 0xdb, 0x41, 0x67, 0x7c, 0x1a, 0xb9, 0x83, 0xe7, 0xe3, 0xeb, 0xc8, 0xb5, 0x19, 0x93, 0x82, 0x1d, 0x76, 0xdf, 0x2a, 0xc2, 0x29, 0x8d, 0x8b, 0x80, 0xab, 0x17, 0xc3, 0x8b, 0x38, 0x53, 0xf1, 0x8f, 0xe3, 0x09, 0xcc, 0x7b, 0xf7, 0xc4, 0xa2, 0xc2, 0x7d, 0x63 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.7", + /* Message */ + 16, + { 0x85, 0x26, 0x49, 0x01, 0x52, 0x06, 0xe2, 0xa4, 0x09, 0x78, 0x76, 0xf8, 0xab, 0xb9, 0xb8, 0x46 } +, + /* Seed */ + 110, + { 0x03, 0x4f, 0xe3, 0x4e, 0x20, 0xe6, 0x06, 0xa8, 0xdc, 0x7c, 0xbc, 0xd0, 0xd6, 0xab, 0x3e, 0x07, 0x97, 0xc5, 0xdc, 0x4e, 0xd7, 0x86, 0x8e, 0xdc, 0x79, 0x59, 0x89, 0x3e, 0x58, 0x13, 0x7d, 0x26, 0x32, 0xb2, 0xc5, 0xa2, 0x9a, 0x81, 0x35, 0xc2, 0x4a, 0xf6, 0x99, 0xb5, 0x9d, 0x68, 0x10, 0x3a, 0x1f, 0x42, 0x33, 0x93, 0xe3, 0x88, 0x6e, 0x3f, 0xa8, 0x54, 0xe3, 0x97, 0x21, 0x50, 0x19, 0x41, 0x3a, 0xf0, 0xb0, 0xd4, 0xfb, 0x1b, 0xd6, 0x9b, 0xd4, 0x93, 0x4d, 0x4d, 0x1e, 0x2e, 0x9f, 0x3b, 0x9e, 0x7c, 0x46, 0xd4, 0x98, 0x4f, 0xe9, 0xe7, 0xa3, 0x7a, 0xb2, 0xf1, 0xc7, 0x8b, 0x0b, 0x8d, 0x9c, 0xd8, 0xfa, 0xbb, 0x3d, 0x18, 0xd4, 0xc5, 0x06, 0xe2, 0xfd, 0x3f, 0x85, 0xae } +, + /* Encryption */ + 129, + { 0x01, 0x6f, 0xbf, 0x2a, 0x7d, 0x36, 0x80, 0x71, 0xcc, 0x7b, 0xe5, 0x94, 0x49, 0x35, 0x4b, 0x9d, 0xe0, 0x5a, 0x85, 0xe1, 0xbb, 0x97, 0xb2, 0x51, 0x4b, 0x52, 0xb8, 0xd1, 0xf3, 0xe2, 0x69, 0x94, 0xe1, 0x2c, 0xfe, 0xda, 0x59, 0xe0, 0x58, 0xa2, 0xf3, 0xc8, 0x79, 0x23, 0x50, 0xc0, 0x68, 0x41, 0x7f, 0x99, 0x44, 0x1b, 0xfe, 0x74, 0x17, 0xe0, 0xb5, 0x31, 0x6e, 0x16, 0x3b, 0xa8, 0xd1, 0xf9, 0xe3, 0x2c, 0x59, 0xa4, 0x44, 0x98, 0x82, 0xf4, 0x7a, 0xd9, 0xb2, 0x4f, 0x68, 0x76, 0xd4, 0x78, 0xd3, 0xf5, 0xb7, 0xd2, 0x75, 0x35, 0x73, 0xe3, 0xf6, 0x97, 0xbf, 0x64, 0xc7, 0xb3, 0xac, 0x22, 0x28, 0xce, 0x69, 0xe7, 0x5e, 0x8e, 0x14, 0xab, 0x93, 0xf2, 0x19, 0x78, 0x05, 0x9a, 0x14, 0x3b, 0x87, 0x7c, 0x6d, 0xd4, 0x21, 0xb6, 0xe2, 0x0b, 0x07, 0x35, 0xa5, 0x36, 0x05, 0x55, 0x2a, 0xb0, 0xa8 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.8", + /* Message */ + 58, + { 0xf4, 0xfb, 0x50, 0xbe, 0xab, 0xec, 0xba, 0x77, 0xe7, 0x1d, 0xd8, 0xd1, 0x6c, 0x97, 0x5a, 0x86, 0xf6, 0x19, 0xea, 0x7d, 0xbf, 0x41, 0x96, 0x9a, 0x24, 0xba, 0xe2, 0xb8, 0x42, 0xc2, 0x69, 0xe0, 0xb4, 0xd6, 0xa2, 0x9e, 0x82, 0x9d, 0xbe, 0x2e, 0x49, 0x79, 0x9c, 0x9e, 0xd9, 0x71, 0xa3, 0x03, 0x35, 0xe6, 0xed, 0x9b, 0xf3, 0x9d, 0x12, 0x4b, 0xe0, 0xf8 } +, + /* Seed */ + 68, + { 0x9d, 0xbd, 0x92, 0xda, 0xee, 0xb8, 0x2b, 0xde, 0x81, 0x6c, 0x59, 0x3f, 0x70, 0x6b, 0x15, 0x92, 0x56, 0x85, 0x22, 0xbc, 0xa0, 0x79, 0x7f, 0x9e, 0x81, 0x1d, 0xd9, 0xdc, 0x0e, 0x89, 0x6e, 0x98, 0x4a, 0x4a, 0x9a, 0xce, 0x77, 0xde, 0xf5, 0xa9, 0x25, 0x0d, 0xb7, 0x95, 0x81, 0xaf, 0x33, 0xfb, 0x6d, 0xe2, 0x42, 0x7d, 0x1a, 0xf6, 0xa5, 0xf6, 0x92, 0x9f, 0xa8, 0xb6, 0x7b, 0xad, 0x02, 0x3f, 0x04, 0xb3, 0xff, 0xd2 } +, + /* Encryption */ + 129, + { 0x02, 0x92, 0xed, 0xfb, 0xac, 0x38, 0xe2, 0x22, 0x45, 0x45, 0xaf, 0x82, 0x86, 0x23, 0x27, 0x63, 0xbc, 0xb1, 0x8b, 0xae, 0x13, 0x70, 0x97, 0x99, 0xe3, 0x50, 0x77, 0x58, 0xd0, 0x14, 0x1a, 0xc2, 0x97, 0x6f, 0x30, 0xb8, 0x54, 0x67, 0xd7, 0x83, 0xab, 0xf6, 0xfc, 0x71, 0xdf, 0x61, 0x9e, 0x1a, 0x59, 0xe6, 0x23, 0x4f, 0x27, 0xb6, 0x32, 0xfe, 0xaa, 0xbf, 0xd9, 0x85, 0x33, 0x77, 0x35, 0x4d, 0x93, 0x3e, 0xf4, 0xec, 0x59, 0x94, 0xc0, 0xd5, 0x0d, 0x95, 0x2e, 0x0e, 0xce, 0x0b, 0xe1, 0xbe, 0x4d, 0x38, 0xf1, 0x1f, 0x66, 0xe7, 0xc3, 0xda, 0x88, 0xc8, 0x3b, 0x4b, 0xed, 0xcc, 0x06, 0x2e, 0x09, 0xf9, 0xaf, 0x95, 0xea, 0xca, 0xc0, 0x09, 0x9c, 0x52, 0x5f, 0x24, 0x1e, 0xa7, 0xd5, 0x65, 0xe1, 0xb7, 0x68, 0xcb, 0x97, 0x08, 0xf3, 0xbc, 0xd5, 0x91, 0x77, 0xb6, 0x76, 0x6a, 0x37, 0x34, 0x88 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.9", + /* Message */ + 56, + { 0x76, 0x91, 0x3e, 0x84, 0x8f, 0xb7, 0xb9, 0xfa, 0xca, 0x91, 0xba, 0xf4, 0xf4, 0x42, 0x01, 0x06, 0xa9, 0x4d, 0x6c, 0xe2, 0x5d, 0x14, 0x97, 0xfc, 0x4e, 0x7f, 0x85, 0x96, 0x54, 0x79, 0x5d, 0x7f, 0x24, 0x39, 0x9f, 0x3a, 0x12, 0x08, 0xaf, 0x02, 0x8e, 0x61, 0x67, 0x8a, 0x6d, 0x19, 0xa1, 0x86, 0x40, 0xb4, 0xd5, 0x0f, 0x75, 0x55, 0x86, 0x00 } +, + /* Seed */ + 70, + { 0x9c, 0xee, 0xaa, 0x26, 0x09, 0xba, 0x90, 0xeb, 0x61, 0xe4, 0xf7, 0x49, 0xc4, 0xcd, 0xa0, 0x1a, 0xea, 0x23, 0x68, 0x81, 0x76, 0x2d, 0xfc, 0x15, 0x0d, 0x97, 0xc1, 0x1e, 0xb6, 0x44, 0x0c, 0xb0, 0x57, 0xe5, 0x3c, 0x3f, 0xd9, 0xb3, 0x9e, 0x56, 0x0a, 0x46, 0xe9, 0xd3, 0xfa, 0x3a, 0xf3, 0xfe, 0xe5, 0xee, 0x2d, 0x02, 0xfa, 0x42, 0x49, 0xaf, 0x99, 0x98, 0xf5, 0x3e, 0xd0, 0x4d, 0xb0, 0x10, 0xe9, 0x6d, 0x8a, 0x01, 0xff, 0x6b } +, + /* Encryption */ + 129, + { 0x01, 0x96, 0x30, 0x89, 0xc3, 0x43, 0xed, 0x88, 0xb5, 0x6d, 0x6a, 0xcf, 0xef, 0xbc, 0x65, 0x5a, 0x37, 0xcc, 0xfd, 0x96, 0x20, 0x3f, 0x21, 0x87, 0x64, 0x69, 0x5a, 0xd3, 0x10, 0xc0, 0xb2, 0x66, 0x65, 0xee, 0x74, 0x5e, 0xb0, 0x10, 0xfc, 0x83, 0xbe, 0x8c, 0x20, 0x64, 0x5c, 0x43, 0x47, 0xdc, 0xd9, 0x44, 0x65, 0x5d, 0x9f, 0xe6, 0xcd, 0x98, 0x77, 0xdc, 0x70, 0xe5, 0xc1, 0x88, 0xcf, 0xc9, 0xa6, 0x6e, 0x71, 0xda, 0x74, 0x5c, 0xd3, 0xe1, 0xa7, 0xb7, 0xf5, 0xa1, 0xb2, 0x5b, 0x4f, 0xc1, 0x47, 0x0a, 0xdf, 0xbf, 0x7d, 0x8e, 0x45, 0xfb, 0x10, 0x7c, 0x5a, 0xeb, 0x50, 0xea, 0x8b, 0x56, 0xe0, 0x4c, 0xa5, 0x5b, 0x9b, 0x65, 0x2a, 0xd8, 0x34, 0xd9, 0xc9, 0x65, 0x77, 0xb6, 0x42, 0xef, 0x33, 0xf1, 0x64, 0xd4, 0x93, 0x1f, 0xb8, 0x9e, 0x0c, 0x8c, 0x6b, 0xf9, 0x17, 0x08, 0xfd, 0xa6, 0xdb } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.10", + /* Message */ + 44, + { 0xc3, 0x39, 0xf8, 0x57, 0xe4, 0xd0, 0x23, 0x1f, 0xa3, 0x7c, 0x06, 0xf0, 0x95, 0x6b, 0x4d, 0x53, 0xa6, 0xc5, 0x8e, 0x06, 0x10, 0xd8, 0xda, 0x43, 0x17, 0xdc, 0x84, 0x11, 0xd3, 0xa0, 0xf8, 0x98, 0x49, 0xb9, 0x4e, 0x8d, 0x7c, 0xcd, 0xb0, 0xc7, 0xd5, 0x33, 0x0c, 0x25 } +, + /* Seed */ + 82, + { 0x24, 0x90, 0x81, 0x6a, 0xc9, 0x69, 0x76, 0xca, 0x72, 0x5e, 0xb4, 0x98, 0xe2, 0xff, 0x04, 0x0a, 0xfe, 0x3d, 0x64, 0x17, 0xd3, 0x2e, 0x4f, 0xfb, 0xd9, 0xfc, 0x9e, 0x3f, 0xa6, 0x8c, 0xe8, 0x49, 0xc8, 0x81, 0xbe, 0x37, 0x9f, 0x17, 0x50, 0x4b, 0x97, 0xe1, 0xe0, 0xd2, 0x2d, 0x32, 0xff, 0x8d, 0xfe, 0x76, 0xbb, 0x45, 0x49, 0xf7, 0x13, 0xb5, 0xb8, 0xd8, 0x70, 0xed, 0x36, 0x59, 0xdd, 0xd3, 0x98, 0x4b, 0x6f, 0xb3, 0x9f, 0x6e, 0xbd, 0xdc, 0x11, 0x77, 0xad, 0x69, 0x8d, 0x90, 0x44, 0x39, 0x68, 0xab } +, + /* Encryption */ + 129, + { 0x00, 0xb5, 0xfb, 0x7b, 0x1e, 0x9d, 0x71, 0xdf, 0x8b, 0x16, 0xc6, 0x3a, 0x1a, 0x49, 0x6e, 0x6f, 0x7b, 0xf7, 0x72, 0x86, 0x4c, 0xb4, 0x11, 0x55, 0x2b, 0x50, 0xe0, 0xb7, 0xf1, 0x5e, 0x45, 0x97, 0x16, 0xf5, 0x64, 0x62, 0x43, 0x68, 0x76, 0x33, 0xa9, 0x10, 0x6c, 0x34, 0x6c, 0x8c, 0x6b, 0x7c, 0xfa, 0xc7, 0x50, 0xb4, 0x56, 0x6b, 0x1b, 0x88, 0xaa, 0xc0, 0xac, 0xb9, 0x16, 0xc0, 0x7a, 0x78, 0x0b, 0xe0, 0x6d, 0xf7, 0x97, 0x5c, 0xcd, 0x8b, 0x72, 0x60, 0x78, 0x68, 0x7a, 0x8e, 0xa5, 0xd3, 0x90, 0x3e, 0x04, 0xab, 0x1d, 0x23, 0xdc, 0x9b, 0x1e, 0xd3, 0x60, 0x00, 0xc9, 0xbb, 0xc3, 0xdc, 0x81, 0x61, 0xe9, 0x48, 0x3a, 0x18, 0xab, 0xb8, 0x64, 0x1e, 0xbb, 0x1f, 0xdd, 0x02, 0x66, 0xc0, 0x84, 0xbf, 0x0b, 0xd0, 0x9c, 0xc9, 0x4e, 0xeb, 0xb9, 0x28, 0x3c, 0x5a, 0x5f, 0x74, 0xe3, 0x60, 0x13 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.11", + /* Message */ + 30, + { 0x47, 0x58, 0x65, 0xa5, 0x7b, 0xdb, 0x91, 0xad, 0xdf, 0x77, 0x7c, 0xc9, 0xd0, 0xa1, 0x7a, 0x71, 0xa9, 0xf9, 0x71, 0x0a, 0x93, 0x1b, 0xd0, 0xc3, 0x14, 0x9b, 0x23, 0x91, 0xa3, 0x53 } +, + /* Seed */ + 96, + { 0x56, 0x2f, 0x79, 0x70, 0x94, 0x6a, 0xc4, 0xcf, 0x05, 0xed, 0xfb, 0x26, 0x34, 0x16, 0x7e, 0x14, 0xd6, 0x65, 0x8d, 0x24, 0xcd, 0xae, 0xf7, 0x5b, 0x40, 0x7c, 0x90, 0x04, 0x81, 0x8e, 0xfa, 0x75, 0xd1, 0x64, 0x5e, 0x81, 0x52, 0xd1, 0xfc, 0x80, 0xd6, 0x99, 0xdf, 0xe9, 0x9a, 0x27, 0xa7, 0xdf, 0x99, 0x7a, 0x8a, 0x66, 0x47, 0x5a, 0xaf, 0xce, 0x41, 0x95, 0x98, 0xe2, 0xa1, 0x91, 0x99, 0xfc, 0x20, 0x53, 0xe3, 0xac, 0xdd, 0x07, 0xfe, 0xc8, 0xba, 0x61, 0xf2, 0xb0, 0x3e, 0xfc, 0x7d, 0xee, 0xd8, 0x15, 0xcd, 0xa8, 0x95, 0x2e, 0x21, 0xe3, 0xc0, 0xb9, 0xa9, 0x35, 0x2a, 0xb3, 0x6f, 0x5e } +, + /* Encryption */ + 129, + { 0x03, 0xe2, 0x68, 0xd7, 0xd1, 0x80, 0xd0, 0x3c, 0x7c, 0xbc, 0x85, 0x07, 0xed, 0x1f, 0x83, 0x0e, 0xd3, 0x7a, 0x79, 0x95, 0x71, 0x2d, 0x7d, 0x91, 0x57, 0x32, 0x24, 0x3d, 0xe6, 0x85, 0xd5, 0xbd, 0x99, 0xa1, 0x4a, 0x8e, 0x86, 0xa6, 0x7c, 0xdd, 0x60, 0xdc, 0xd9, 0x0c, 0x33, 0x92, 0x10, 0x83, 0x5a, 0x46, 0xce, 0xac, 0x19, 0x36, 0xab, 0x3a, 0xa9, 0xc3, 0x81, 0x88, 0x2d, 0x76, 0x94, 0xa8, 0x38, 0x3d, 0x68, 0x98, 0xe2, 0x73, 0x44, 0xbd, 0x15, 0x6f, 0xe9, 0x28, 0x2c, 0x71, 0x32, 0x26, 0x25, 0xd6, 0x8d, 0x30, 0x70, 0xef, 0xf0, 0x1a, 0xc8, 0xd5, 0x95, 0xf6, 0x48, 0x6d, 0x79, 0xb7, 0x88, 0xe3, 0x69, 0x12, 0xfd, 0x3c, 0xcf, 0x28, 0x4e, 0xdd, 0x5f, 0xce, 0xe2, 0x40, 0x9d, 0xca, 0x7d, 0x4f, 0x29, 0xcc, 0x18, 0x2a, 0x78, 0x47, 0x8b, 0xd3, 0xea, 0x23, 0x62, 0x11, 0x25, 0x10, 0xa5 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.12", + /* Message */ + 26, + { 0x9e, 0x1e, 0x53, 0xf9, 0x86, 0x59, 0x9d, 0xa8, 0x98, 0xd5, 0x6d, 0xc1, 0xc7, 0x55, 0x6f, 0xef, 0xca, 0xa3, 0x39, 0x5d, 0x84, 0x50, 0xd5, 0x2b, 0x3b, 0xa7 } +, + /* Seed */ + 100, + { 0x0b, 0x17, 0x63, 0xcc, 0x34, 0x0e, 0x6e, 0x39, 0x78, 0x62, 0x6a, 0x06, 0xd6, 0xef, 0xc4, 0x0d, 0xed, 0x73, 0xdb, 0x53, 0x5a, 0x82, 0x2e, 0xc0, 0x4c, 0x99, 0x24, 0xd9, 0xec, 0x40, 0xd3, 0x85, 0x20, 0x15, 0xd7, 0xe1, 0x02, 0x9c, 0x13, 0x93, 0xad, 0xcf, 0x01, 0x50, 0x30, 0x8a, 0xcb, 0x27, 0x3c, 0x36, 0x35, 0x68, 0x28, 0xa4, 0x77, 0xfc, 0xf9, 0xa2, 0x9a, 0xca, 0xb9, 0x09, 0x35, 0x70, 0x42, 0x50, 0x26, 0xda, 0xc1, 0x4d, 0xa6, 0xcd, 0x30, 0x4c, 0xda, 0xa5, 0x4c, 0x9a, 0x4c, 0x5a, 0x99, 0x4e, 0xd6, 0x8a, 0x5c, 0xea, 0xc7, 0xe0, 0x81, 0xde, 0xc4, 0x64, 0x6e, 0x23, 0x7e, 0x47, 0x1e, 0x52, 0x5e, 0xf8 } +, + /* Encryption */ + 129, + { 0x06, 0xd5, 0x19, 0xa7, 0x30, 0xea, 0x5f, 0x54, 0x9f, 0xe1, 0x9e, 0x30, 0x1b, 0xa5, 0x15, 0x2d, 0x10, 0x3a, 0x3e, 0xad, 0x3f, 0x89, 0xab, 0x35, 0x16, 0xff, 0x7b, 0x34, 0x4c, 0x4f, 0x72, 0xa1, 0xc2, 0x6a, 0xa9, 0x0d, 0x5a, 0x01, 0xa2, 0xa6, 0x51, 0x93, 0xd3, 0xcf, 0x63, 0x41, 0xe5, 0x9a, 0x31, 0xfd, 0x2d, 0x7d, 0xfe, 0x43, 0x5c, 0x09, 0x84, 0xd1, 0xbb, 0xe8, 0x11, 0x32, 0x01, 0x0f, 0x43, 0x58, 0xee, 0xbf, 0xe8, 0x3f, 0xaf, 0x24, 0x1e, 0x7f, 0x35, 0xaf, 0x98, 0xb7, 0xc7, 0xab, 0x91, 0xe4, 0xf0, 0xe8, 0xa3, 0x2a, 0x2f, 0x57, 0xf0, 0x7f, 0x49, 0xd5, 0xc2, 0x1f, 0x1e, 0x13, 0x80, 0xba, 0x0e, 0x17, 0x9a, 0x38, 0xd3, 0xa2, 0xca, 0x46, 0x4f, 0xc1, 0x4d, 0x2b, 0x74, 0xa0, 0x3a, 0x88, 0x84, 0xaa, 0x85, 0x7b, 0x66, 0x01, 0x47, 0x02, 0xb1, 0xbc, 0x4e, 0x7c, 0xc5, 0xe1, 0xeb } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.13", + /* Message */ + 25, + { 0x1a, 0xe3, 0x1e, 0x0c, 0xbe, 0x44, 0x97, 0xba, 0x43, 0xc5, 0xd1, 0x5f, 0x53, 0x5f, 0xe0, 0x18, 0x84, 0x1c, 0x73, 0x14, 0x57, 0x67, 0xa6, 0xa4, 0xc8 } +, + /* Seed */ + 101, + { 0x8f, 0xf0, 0xfa, 0xa7, 0xa2, 0xb4, 0xff, 0x55, 0x3c, 0xcb, 0xb2, 0x0f, 0xf3, 0x10, 0xac, 0x5e, 0x0e, 0xa9, 0x28, 0x18, 0x56, 0x2e, 0xc9, 0xa0, 0x60, 0x64, 0xf5, 0xde, 0x79, 0x86, 0xb4, 0xf6, 0xc9, 0xae, 0xa2, 0xb9, 0xf0, 0x11, 0x42, 0x38, 0xe5, 0xa4, 0x99, 0xa8, 0xae, 0x20, 0xea, 0xe4, 0x02, 0x1f, 0xcd, 0xd8, 0xf0, 0x60, 0xc9, 0x93, 0xa9, 0xbf, 0x64, 0x2d, 0xa0, 0x25, 0x67, 0x39, 0x33, 0x48, 0x08, 0xe3, 0x88, 0xe1, 0xda, 0x82, 0x37, 0x27, 0x8b, 0xf4, 0xf4, 0x7e, 0x05, 0x01, 0x5a, 0x8b, 0x88, 0xc5, 0x42, 0x0c, 0xeb, 0xc8, 0xbb, 0x37, 0xee, 0x43, 0x52, 0x83, 0x7a, 0xf7, 0x64, 0x70, 0x18, 0x41, 0x97 } +, + /* Encryption */ + 129, + { 0x04, 0xa2, 0x10, 0xf7, 0x6c, 0x0f, 0x84, 0x93, 0x99, 0x09, 0x53, 0x58, 0x98, 0x86, 0xf6, 0x2c, 0x1c, 0x48, 0x25, 0x01, 0x2a, 0xf4, 0x4b, 0xdc, 0xf2, 0xc9, 0x9b, 0x32, 0xa7, 0x0a, 0x17, 0xf7, 0x64, 0xa3, 0xa9, 0x7b, 0x2b, 0x04, 0x7e, 0x39, 0xd8, 0x0c, 0xde, 0x15, 0x4e, 0xbe, 0xd5, 0xd2, 0x81, 0x3e, 0xe8, 0x4a, 0xc9, 0xc8, 0xd6, 0xec, 0x6a, 0x96, 0xf4, 0x02, 0xdb, 0xb3, 0x26, 0xd5, 0xa6, 0xe9, 0xc0, 0xf7, 0x87, 0xc1, 0x5e, 0x98, 0x23, 0xc5, 0x08, 0xb3, 0x23, 0x5f, 0x3a, 0x00, 0x8d, 0xdd, 0xcd, 0xdb, 0x07, 0x9e, 0x80, 0xff, 0x50, 0xfe, 0x37, 0x25, 0x4a, 0x0c, 0xc4, 0x68, 0x29, 0x7e, 0xe3, 0x32, 0x53, 0xa7, 0x4c, 0x1e, 0x03, 0x70, 0x26, 0x05, 0x69, 0x58, 0xad, 0x07, 0x78, 0xe0, 0xaa, 0x12, 0x50, 0xdf, 0x1c, 0x14, 0x85, 0x7c, 0xb0, 0xd7, 0x1a, 0xa6, 0x93, 0x7e, 0x31 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.14", + /* Message */ + 17, + { 0xa6, 0xe3, 0xd1, 0x07, 0x03, 0x21, 0xd8, 0xff, 0x76, 0xb8, 0x5c, 0x70, 0x93, 0xfa, 0xa0, 0x42, 0x83 } +, + /* Seed */ + 109, + { 0xd1, 0x60, 0xb1, 0x2c, 0x76, 0x62, 0x2c, 0x3d, 0x34, 0xd8, 0x55, 0x87, 0xe6, 0xe8, 0x1c, 0xf0, 0x54, 0x61, 0x8a, 0x34, 0x6b, 0x67, 0x52, 0xd5, 0x36, 0x9a, 0x71, 0xc4, 0x92, 0x35, 0x7a, 0x13, 0x4b, 0x7f, 0x67, 0xf3, 0x34, 0xa4, 0xf3, 0xb3, 0x28, 0xba, 0xa9, 0xf0, 0x07, 0x18, 0x47, 0xd0, 0xda, 0xfd, 0xac, 0x22, 0x5d, 0x7b, 0x7f, 0x07, 0x16, 0x18, 0xea, 0x86, 0x81, 0xfc, 0xd2, 0xd2, 0x30, 0x5c, 0x2f, 0x64, 0x63, 0x1e, 0x62, 0x31, 0x85, 0xfc, 0x09, 0x96, 0xe6, 0x1c, 0x84, 0xf4, 0x18, 0x0c, 0x63, 0x7b, 0xf6, 0xea, 0x2d, 0x06, 0x03, 0x75, 0xf1, 0x6a, 0x65, 0xe5, 0xb1, 0xe2, 0xb8, 0x65, 0x28, 0x5d, 0xa3, 0xd8, 0xfb, 0x1b, 0x6a, 0x60, 0xea, 0x36, 0xe1 } +, + /* Encryption */ + 129, + { 0x0a, 0x70, 0x03, 0xb5, 0x86, 0x1a, 0x85, 0xa8, 0xf7, 0x2f, 0x19, 0x9d, 0xc6, 0x5c, 0x17, 0xfc, 0x58, 0xa9, 0x24, 0xbc, 0xc4, 0x08, 0x19, 0xe2, 0x8c, 0x95, 0x83, 0xe8, 0x21, 0x03, 0x8c, 0x00, 0x05, 0x36, 0x5e, 0x90, 0x9e, 0xee, 0x4f, 0x32, 0x66, 0xf5, 0x9a, 0x84, 0xe3, 0x25, 0xb1, 0xbe, 0xa9, 0xd2, 0x81, 0xb4, 0x82, 0x3f, 0x2f, 0xce, 0x44, 0x15, 0x3f, 0x03, 0x17, 0x0f, 0xad, 0xcb, 0x16, 0xa2, 0x79, 0xb2, 0xc9, 0x58, 0x7f, 0x6b, 0x79, 0xef, 0xfc, 0x55, 0xa3, 0xc4, 0x34, 0xe0, 0xbc, 0x5d, 0xaf, 0xe9, 0xd4, 0x03, 0x26, 0x48, 0xaa, 0xe7, 0xe4, 0xed, 0x1d, 0x7f, 0x14, 0x1b, 0xfe, 0x72, 0x26, 0x83, 0xfa, 0x32, 0xc8, 0x9d, 0xdd, 0x67, 0x3c, 0x3f, 0x0c, 0x03, 0xc8, 0x54, 0x59, 0x89, 0x0a, 0xb7, 0xfb, 0xc1, 0xd9, 0xa8, 0x14, 0xbf, 0xe9, 0xb0, 0xd1, 0x2a, 0xb1, 0x7f, 0x51 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.15", + /* Message */ + 40, + { 0xd0, 0xbc, 0x89, 0x03, 0x9b, 0xa1, 0x9e, 0xe5, 0x0a, 0x73, 0x82, 0x98, 0x4e, 0x42, 0x8a, 0xed, 0x88, 0x61, 0x4f, 0x78, 0x98, 0x13, 0x01, 0x89, 0x16, 0xe2, 0xe7, 0xeb, 0x0d, 0xb8, 0x3d, 0xa2, 0x8e, 0xc2, 0x3c, 0x04, 0xa0, 0xc2, 0xf7, 0x6a } +, + /* Seed */ + 86, + { 0xc6, 0x4d, 0x10, 0xa4, 0xb5, 0x2f, 0x49, 0x0a, 0xb6, 0x2a, 0x60, 0x38, 0xb3, 0x2b, 0x23, 0xc6, 0x3a, 0x1c, 0x85, 0x97, 0x0d, 0x93, 0x45, 0x14, 0x83, 0x94, 0xcd, 0x35, 0xcf, 0xd6, 0xf6, 0xb1, 0x59, 0x0f, 0xce, 0x8c, 0x67, 0x5b, 0xee, 0xf8, 0x7c, 0xd0, 0x34, 0x5e, 0x5c, 0xad, 0xe8, 0x95, 0x09, 0x45, 0x56, 0x54, 0x26, 0xb6, 0xb2, 0x83, 0x03, 0xb0, 0xb0, 0x39, 0x32, 0x98, 0xcd, 0xd9, 0x5c, 0x88, 0x1f, 0xa0, 0x65, 0x33, 0xca, 0x9d, 0x2d, 0x27, 0x14, 0xd0, 0xf1, 0x37, 0x85, 0xa6, 0x1b, 0x3a, 0x17, 0xa7, 0x81, 0x40 } +, + /* Encryption */ + 129, + { 0x00, 0x8b, 0x19, 0x75, 0x58, 0xca, 0x4c, 0xe5, 0x90, 0x14, 0x58, 0xab, 0xd8, 0xe8, 0xfd, 0x52, 0xd9, 0x89, 0x96, 0x0f, 0x01, 0xc2, 0x16, 0xef, 0xb5, 0x81, 0xf8, 0x61, 0x14, 0x8d, 0x1a, 0x2b, 0x44, 0xeb, 0x0b, 0x7c, 0x15, 0xdd, 0xc3, 0x45, 0xdc, 0x83, 0xf9, 0x03, 0x7d, 0xdb, 0x8f, 0xe2, 0xea, 0xa2, 0xcb, 0xed, 0x9b, 0x1c, 0x1e, 0xee, 0xae, 0xb8, 0x65, 0xbd, 0x29, 0xf4, 0x4e, 0xe1, 0x47, 0x8c, 0x95, 0xe9, 0xfb, 0xf4, 0x44, 0x82, 0x8e, 0xed, 0xcb, 0xc0, 0x17, 0x02, 0x00, 0xde, 0x35, 0x49, 0xb2, 0x2c, 0x11, 0xe4, 0xb4, 0x33, 0x79, 0x8b, 0x9d, 0x63, 0xbb, 0x49, 0xf0, 0xb0, 0x2d, 0xaf, 0x56, 0x58, 0xce, 0xed, 0xea, 0xa9, 0x3c, 0x0f, 0xae, 0xb9, 0x44, 0x65, 0x38, 0xba, 0x92, 0xeb, 0x17, 0xc8, 0x5d, 0xb5, 0xee, 0xa2, 0x04, 0xba, 0x2f, 0x49, 0xc3, 0xce, 0x65, 0xbf, 0x13 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.16", + /* Message */ + 43, + { 0xce, 0x0a, 0x4a, 0x59, 0x39, 0xf6, 0xaa, 0x26, 0x3b, 0xbf, 0x8e, 0x1e, 0x5e, 0x94, 0x31, 0x03, 0x56, 0xab, 0xa5, 0x75, 0x59, 0xc4, 0x1b, 0x39, 0x44, 0x27, 0x70, 0xb6, 0x1f, 0x6b, 0x3c, 0x9b, 0x5f, 0xe7, 0x27, 0xf3, 0x19, 0x52, 0x28, 0x08, 0xd5, 0x80, 0x19 } +, + /* Seed */ + 83, + { 0x27, 0xcc, 0xe2, 0xd4, 0x3c, 0x71, 0x31, 0x8e, 0xd4, 0xfc, 0x8c, 0x0b, 0xdb, 0x9b, 0x79, 0x13, 0x53, 0x19, 0x9f, 0x3d, 0x89, 0xfc, 0x12, 0xac, 0x47, 0xfd, 0xb6, 0xd8, 0x8b, 0x44, 0xc6, 0x54, 0x5e, 0x9e, 0xee, 0xd9, 0xf4, 0xc6, 0x85, 0x15, 0xd4, 0xf5, 0x30, 0xb8, 0x13, 0x7d, 0x77, 0x45, 0x71, 0x3b, 0xad, 0x0e, 0xbb, 0x70, 0x52, 0x23, 0x1f, 0x6b, 0x4c, 0xed, 0x18, 0x7a, 0xec, 0xd1, 0xe7, 0xa1, 0x69, 0xd8, 0x6c, 0xbd, 0x13, 0xd5, 0x0b, 0x78, 0xbe, 0x27, 0xc6, 0x54, 0x5d, 0x81, 0x92, 0xe0, 0xec } +, + /* Encryption */ + 129, + { 0x0a, 0xd3, 0xae, 0x7e, 0x5a, 0x98, 0x65, 0x2c, 0x1b, 0xf3, 0x45, 0xc4, 0x91, 0x90, 0x3f, 0x55, 0x17, 0xc6, 0x11, 0xac, 0x31, 0x00, 0x05, 0x87, 0x7f, 0xa9, 0x1a, 0xbc, 0xee, 0x64, 0x85, 0xf2, 0x77, 0x8a, 0xbf, 0x0a, 0x6c, 0x73, 0x87, 0x87, 0x37, 0x63, 0x9b, 0x26, 0x72, 0xfd, 0xd0, 0x0a, 0x39, 0x65, 0xd7, 0xd3, 0xd8, 0xd7, 0x68, 0x8e, 0x77, 0xb5, 0x45, 0x9e, 0x14, 0x5e, 0xce, 0x64, 0xa9, 0xa5, 0x2c, 0x37, 0x97, 0xf3, 0x61, 0x07, 0xc9, 0x36, 0x8b, 0xdf, 0x79, 0x90, 0xf3, 0xfb, 0x6c, 0x5c, 0xff, 0x59, 0xf4, 0xf8, 0xa3, 0xd4, 0x90, 0x93, 0xdf, 0xfe, 0x74, 0x06, 0xc9, 0x10, 0xaa, 0x57, 0x23, 0x22, 0x8d, 0xae, 0x5a, 0x9b, 0x29, 0xa4, 0xcc, 0x47, 0x69, 0xaf, 0x8b, 0xd5, 0xfd, 0x6e, 0xce, 0x88, 0x58, 0xa2, 0x9d, 0xb1, 0xb1, 0x9c, 0x08, 0x1b, 0xf0, 0xd6, 0xb0, 0xdc, 0x78 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.17", + /* Message */ + 40, + { 0x03, 0xbf, 0xb2, 0x59, 0xbd, 0x92, 0x46, 0xde, 0x3f, 0x71, 0xc3, 0x13, 0x9c, 0x72, 0x85, 0x74, 0xb4, 0x4d, 0x97, 0xad, 0x57, 0xbb, 0xdd, 0x67, 0x01, 0x94, 0x95, 0xc2, 0xa2, 0x00, 0x41, 0x39, 0x26, 0x34, 0xe3, 0x1a, 0xad, 0x63, 0xf6, 0x3b } +, + /* Seed */ + 86, + { 0x5f, 0xa4, 0xbb, 0xb7, 0x0e, 0x1f, 0x9e, 0xcb, 0x5e, 0xb2, 0x14, 0x7b, 0xf4, 0x59, 0xd1, 0xd0, 0x64, 0x43, 0xf0, 0x25, 0xc0, 0x8e, 0x36, 0x4c, 0xcc, 0x1b, 0x16, 0x0c, 0x16, 0x41, 0x6f, 0xb1, 0x74, 0xb4, 0x4b, 0x95, 0x36, 0x38, 0xa9, 0x68, 0x8c, 0x5e, 0xa2, 0xd0, 0x60, 0x17, 0x1f, 0x30, 0x54, 0xf3, 0xca, 0x3f, 0xe0, 0x13, 0xb9, 0xe3, 0x18, 0x8e, 0xe3, 0x9d, 0xa9, 0x1f, 0x80, 0x16, 0xd4, 0xb7, 0x33, 0x18, 0x79, 0x35, 0x1f, 0x32, 0x2a, 0xe5, 0x29, 0x86, 0x4d, 0x90, 0x74, 0x09, 0x8a, 0xa2, 0x51, 0x6b, 0x44, 0xca } +, + /* Encryption */ + 129, + { 0x01, 0x78, 0xe3, 0xa0, 0x17, 0xed, 0x2f, 0xc1, 0x18, 0xbb, 0x2e, 0x03, 0x28, 0xbe, 0xb2, 0x8a, 0x98, 0xc8, 0x53, 0xb9, 0xe5, 0xa5, 0xf8, 0x30, 0x80, 0xc0, 0xf1, 0x01, 0x7f, 0xdc, 0xa8, 0x37, 0x92, 0x07, 0x72, 0x2c, 0x25, 0x73, 0x7a, 0x89, 0x15, 0xe0, 0xeb, 0x72, 0xc5, 0x22, 0x85, 0xe8, 0x8f, 0x61, 0x30, 0xa1, 0xcf, 0x56, 0xad, 0x1d, 0x96, 0xca, 0x2c, 0xe4, 0xb7, 0x1e, 0xc3, 0x68, 0x94, 0x7b, 0xd0, 0x71, 0xf8, 0x36, 0x59, 0x10, 0xc7, 0x92, 0x57, 0x5b, 0x8c, 0xd6, 0xfd, 0x27, 0xe5, 0x23, 0xe8, 0x59, 0x65, 0xdd, 0xa9, 0x22, 0x82, 0xd5, 0xdf, 0xd1, 0xc0, 0x64, 0xea, 0xab, 0x6a, 0xbe, 0xac, 0x65, 0xe1, 0x6a, 0xe0, 0x4f, 0x0d, 0x40, 0xb3, 0xbb, 0x68, 0x41, 0x0b, 0x92, 0x74, 0xdf, 0xee, 0xa3, 0x2a, 0x43, 0xf9, 0x40, 0x83, 0xc1, 0x07, 0x80, 0x35, 0x3f, 0x43, 0xe4, 0x3c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.18", + /* Message */ + 37, + { 0x16, 0x2c, 0xca, 0x9e, 0xd4, 0x70, 0x8d, 0xd1, 0x03, 0x40, 0xe1, 0x94, 0xc3, 0x5c, 0x0a, 0x5f, 0xa4, 0x9a, 0x5c, 0x3b, 0x5b, 0x24, 0x71, 0x71, 0x20, 0x3c, 0xa4, 0x8a, 0x79, 0xe5, 0x2d, 0xff, 0x40, 0xf2, 0xbc, 0xa9, 0x9a } +, + /* Seed */ + 89, + { 0x4d, 0x73, 0xff, 0xcd, 0xc2, 0x69, 0x43, 0xa8, 0x70, 0x78, 0x23, 0x47, 0x8d, 0xa3, 0x1a, 0xac, 0x01, 0x27, 0x4b, 0x17, 0x17, 0xc5, 0x0c, 0x6a, 0xd0, 0xc6, 0x2e, 0xe2, 0xbc, 0xd5, 0x57, 0x95, 0x2e, 0xf1, 0x3f, 0x15, 0xff, 0xaf, 0x66, 0xbb, 0x4f, 0x45, 0x39, 0x99, 0x11, 0xc6, 0xd6, 0x5a, 0xd1, 0x87, 0x57, 0x2b, 0xc1, 0xeb, 0xa0, 0xd2, 0x86, 0xcc, 0x45, 0xaa, 0x49, 0x32, 0xe7, 0x3e, 0x47, 0x0c, 0x5d, 0xc8, 0x29, 0x39, 0x04, 0x02, 0x5c, 0x86, 0x3f, 0xbc, 0x96, 0x22, 0x37, 0x04, 0x90, 0xc9, 0x1c, 0x87, 0x40, 0xb0, 0x94, 0xd8, 0xf0 } +, + /* Encryption */ + 129, + { 0x04, 0x2b, 0xce, 0x0d, 0xfc, 0xec, 0xa9, 0xff, 0x05, 0xa6, 0xe3, 0xf7, 0x4a, 0x6a, 0x70, 0xcd, 0xcb, 0xe0, 0xde, 0xc8, 0x1e, 0xdd, 0xc8, 0x8e, 0x46, 0x7f, 0x47, 0xbb, 0x76, 0x0d, 0xa4, 0x4c, 0x79, 0x4d, 0x3c, 0xdc, 0xab, 0x93, 0x92, 0x49, 0xf8, 0x49, 0xd1, 0xd4, 0x39, 0x56, 0x64, 0x1b, 0x0b, 0x79, 0xc6, 0x86, 0x1c, 0x5f, 0x71, 0x5b, 0x9d, 0x8d, 0x8b, 0xe9, 0xf0, 0x76, 0x6a, 0xdb, 0x3f, 0x18, 0xaf, 0x7d, 0xb3, 0x6a, 0xd9, 0x5f, 0xfc, 0xd7, 0xe0, 0xfa, 0xc1, 0x62, 0x85, 0x23, 0xe8, 0xf6, 0x9a, 0xde, 0xb7, 0xff, 0x50, 0x94, 0xa2, 0xb5, 0xbf, 0x92, 0xb9, 0xd0, 0xef, 0xb1, 0x11, 0x8b, 0x85, 0x39, 0x26, 0x25, 0xfd, 0x56, 0xf8, 0x8f, 0xaa, 0x0a, 0x16, 0xd5, 0x47, 0x30, 0xfb, 0xc5, 0xca, 0xf1, 0x66, 0x82, 0xe9, 0xe4, 0x1b, 0x7e, 0x79, 0xd2, 0x02, 0x2f, 0x7c, 0xcf, 0x96 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.19", + /* Message */ + 58, + { 0x8e, 0x1b, 0x52, 0xcb, 0x4e, 0x00, 0x77, 0x27, 0xc4, 0xb5, 0xf6, 0x5d, 0x78, 0x47, 0xf3, 0x49, 0x16, 0x89, 0x1e, 0xf9, 0xc7, 0x3a, 0xd1, 0x8c, 0xf2, 0x71, 0xf8, 0x9f, 0x18, 0x2c, 0x69, 0x3e, 0x52, 0x89, 0xdc, 0x31, 0xda, 0xbc, 0x34, 0xcf, 0x7f, 0x44, 0xfb, 0xde, 0x57, 0x9e, 0x64, 0x51, 0x69, 0xec, 0xba, 0x6e, 0x4e, 0x87, 0x7f, 0x7d, 0xef, 0x44 } +, + /* Seed */ + 68, + { 0xba, 0x14, 0x74, 0x8e, 0x6d, 0xa7, 0xb6, 0xac, 0x18, 0x33, 0x32, 0x32, 0x95, 0xad, 0xb5, 0x42, 0x2d, 0xbd, 0x19, 0xe2, 0xec, 0x72, 0xdf, 0xd0, 0xaa, 0xfd, 0x7b, 0xd0, 0x7b, 0xfb, 0x97, 0xe7, 0xdb, 0x10, 0x8a, 0x3e, 0xaa, 0xdc, 0xff, 0x67, 0xb6, 0x7e, 0xc7, 0xe4, 0xc6, 0x70, 0x04, 0xc1, 0x78, 0x34, 0x6a, 0x12, 0x5d, 0xd3, 0xb6, 0xca, 0x55, 0x23, 0x70, 0x59, 0x4f, 0x7f, 0x42, 0xcb, 0x33, 0x4b, 0x44, 0x85 } +, + /* Encryption */ + 129, + { 0x09, 0x4b, 0x40, 0x30, 0xe3, 0x0c, 0x8b, 0x46, 0x2e, 0xca, 0x00, 0xf1, 0x6b, 0xb1, 0x70, 0x19, 0xd1, 0xea, 0x31, 0x25, 0xf1, 0xc6, 0x4c, 0x67, 0x1c, 0xb0, 0x0d, 0x46, 0xe3, 0xad, 0x87, 0x84, 0x28, 0x52, 0xb2, 0x01, 0x49, 0x6e, 0xe2, 0xb3, 0xd5, 0x42, 0x28, 0x93, 0xa8, 0x0c, 0x66, 0xa3, 0x0d, 0xa2, 0xc9, 0xf1, 0xa3, 0x2a, 0xd4, 0xd4, 0xe7, 0x73, 0x77, 0x43, 0xca, 0x1b, 0x78, 0xef, 0x7d, 0x4a, 0x63, 0xc5, 0xe1, 0xe0, 0xbe, 0x7e, 0x51, 0x88, 0xcc, 0xe9, 0x42, 0x95, 0x69, 0x74, 0xff, 0xd4, 0x81, 0xe6, 0x47, 0x83, 0x44, 0x23, 0x0c, 0x37, 0xda, 0x5b, 0x25, 0xf6, 0xb5, 0x99, 0xa5, 0x9a, 0x05, 0x80, 0xf1, 0xa0, 0x00, 0xc2, 0x59, 0x54, 0xf3, 0xa4, 0x63, 0xf2, 0x89, 0x5f, 0x32, 0xb0, 0x5c, 0xc0, 0x88, 0x21, 0xb1, 0xa0, 0x23, 0x60, 0x9f, 0x18, 0xca, 0x7d, 0x44, 0x9c, 0xb4 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 10.20", + /* Message */ + 12, + { 0x82, 0xff, 0x62, 0xaf, 0xfa, 0xd8, 0x00, 0x30, 0x94, 0xcc, 0x65, 0x35 } +, + /* Seed */ + 114, + { 0x1c, 0x7f, 0x21, 0xfd, 0x02, 0x09, 0x79, 0x07, 0x40, 0x5e, 0xaa, 0x77, 0xae, 0x72, 0x88, 0x65, 0x72, 0x1d, 0x93, 0x86, 0xf5, 0xaa, 0xbc, 0x2e, 0x0a, 0x95, 0xf3, 0xed, 0xb0, 0x5d, 0x46, 0xe2, 0x33, 0x79, 0x3b, 0xa1, 0xa3, 0x88, 0xe4, 0xb0, 0xdd, 0xa0, 0x0c, 0xc3, 0x2b, 0x94, 0x8a, 0xc2, 0x65, 0xae, 0x6a, 0x2b, 0xf2, 0xc3, 0x90, 0xa4, 0xdc, 0xce, 0x11, 0x0d, 0x5e, 0x86, 0x64, 0x47, 0x28, 0xf5, 0x37, 0x81, 0x36, 0x47, 0x6c, 0xf7, 0x1d, 0xc7, 0xba, 0xac, 0x50, 0xcc, 0x41, 0xc2, 0x01, 0x48, 0xdd, 0x37, 0xd5, 0xf7, 0x0a, 0x81, 0x2a, 0x29, 0x4e, 0x24, 0x2d, 0xe8, 0x03, 0xb4, 0x8b, 0x63, 0x40, 0xf4, 0x28, 0xd3, 0xc9, 0xbc, 0xa9, 0x6f, 0x76, 0x6f, 0xc4, 0xf4, 0x41, 0x67, 0xe0, 0x4a } +, + /* Encryption */ + 129, + { 0x00, 0x30, 0x3c, 0x35, 0x2e, 0x1f, 0xdd, 0x2a, 0xf8, 0xa8, 0xe3, 0xa1, 0x69, 0xb5, 0xda, 0xc5, 0x43, 0x45, 0xca, 0xa3, 0x35, 0xa7, 0x1a, 0x37, 0xe9, 0x38, 0xbf, 0x98, 0x47, 0x08, 0x86, 0x56, 0x84, 0x18, 0xae, 0x98, 0xd0, 0xaa, 0xdf, 0xe7, 0x9d, 0x0c, 0x65, 0x1b, 0x3f, 0x51, 0x6e, 0x70, 0xf1, 0x01, 0x74, 0xfe, 0x63, 0x22, 0xcd, 0x37, 0x6d, 0xa0, 0x2f, 0x22, 0x6d, 0x15, 0xb3, 0x6a, 0xbf, 0x6d, 0x1c, 0xbd, 0xab, 0x6d, 0xd5, 0x65, 0x4d, 0x99, 0x25, 0xf7, 0x25, 0x3c, 0xe9, 0x91, 0x51, 0x2a, 0x44, 0xe9, 0xfa, 0x15, 0x27, 0x12, 0xd7, 0xb8, 0xdb, 0x7f, 0x18, 0x33, 0x75, 0x80, 0xfe, 0x51, 0xdc, 0x32, 0xa0, 0x58, 0x2c, 0xe2, 0x60, 0x53, 0xf1, 0xb9, 0x49, 0x28, 0x69, 0xb9, 0xc4, 0x7d, 0xf9, 0x28, 0x39, 0xc0, 0x50, 0x2f, 0x2d, 0xb4, 0xcc, 0x4d, 0x0b, 0x20, 0x4f, 0x6f, 0xd1 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 11: A 1029-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x11, 0x65, 0x47, 0x94, 0xf4, 0x64, 0x9a, 0x97, 0xac, 0x87, 0xef, 0x67, 0x94, 0xf6, 0xa6, 0xff, 0xb5, 0xcd, 0xab, 0x87, 0x02, 0xc2, 0x32, 0x54, 0xfd, 0xe0, 0x34, 0xf3, 0x12, 0x9a, 0xad, 0x82, 0x5c, 0xf3, 0xc0, 0xcc, 0x38, 0x80, 0xa9, 0x6f, 0xb6, 0x4e, 0x48, 0xd7, 0x59, 0x5e, 0xde, 0x06, 0xc3, 0x1d, 0x0a, 0xcb, 0xd1, 0xf8, 0xef, 0x9c, 0xd1, 0xf9, 0xf6, 0xf0, 0x0b, 0x24, 0xba, 0x53, 0x45, 0xab, 0xa1, 0x46, 0xd4, 0x1c, 0x56, 0x3b, 0xae, 0xce, 0x3b, 0x25, 0x23, 0xdf, 0x6a, 0x9f, 0x43, 0x01, 0x8a, 0x5f, 0x08, 0x69, 0xb6, 0xec, 0x99, 0x34, 0x69, 0x88, 0x6b, 0x5d, 0x23, 0x17, 0xd5, 0x9c, 0xff, 0xd4, 0xed, 0xe9, 0x46, 0x6a, 0x03, 0xf6, 0xdf, 0xec, 0x17, 0x5c, 0xad, 0x5a, 0x85, 0x44, 0x30, 0x95, 0xc7, 0x30, 0xb9, 0x8b, 0xbf, 0xa0, 0x48, 0x9b, 0x91, 0xbb, 0x27, 0x39, 0x9d } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x1d, 0x4c, 0x4c, 0x6e, 0x13, 0xda, 0xb2, 0x84, 0x6c, 0xe6, 0x85, 0xd0, 0xc4, 0x93, 0x52, 0x5b, 0xb0, 0xad, 0x35, 0x62, 0x59, 0x6d, 0xb9, 0xad, 0x16, 0x94, 0x5d, 0x44, 0x5c, 0xe6, 0x7c, 0x54, 0xe9, 0x38, 0xf6, 0x54, 0x54, 0x2b, 0x09, 0x34, 0x48, 0x02, 0x91, 0xac, 0x21, 0xae, 0xd0, 0x98, 0xe8, 0x5a, 0xd6, 0xfe, 0xc6, 0xd0, 0xfe, 0x15, 0x4c, 0x3c, 0x34, 0x2b, 0x16, 0x99, 0x9a, 0x8c, 0xec, 0xe7, 0xfa, 0xf9, 0x90, 0xb7, 0xc8, 0xce, 0x87, 0xb6, 0x6f, 0xe3, 0x27, 0xfb, 0x35, 0x2e, 0xd0, 0x11, 0x32, 0x3d, 0x2b, 0x81, 0x9a, 0x36, 0xca, 0xbe, 0xcc, 0x5a, 0xae, 0x72, 0x30, 0xd3, 0xf8, 0xe0, 0x02, 0x45, 0xaf, 0x35, 0xaf, 0x80, 0x88, 0x62, 0xe5, 0x4d, 0x92, 0x56, 0x07, 0xee, 0x8b, 0x58, 0xe6, 0xa9, 0xf3, 0xad, 0x8f, 0xa7, 0x28, 0xfc, 0xe2, 0x68, 0x56, 0xc3, 0x67, 0xb1 } +, + /* Prime 1 */ + 65, + { 0x04, 0x41, 0x0a, 0xb5, 0x54, 0x60, 0x2d, 0x7e, 0xfb, 0x0c, 0xce, 0x92, 0x71, 0xa5, 0x22, 0x20, 0xf2, 0x52, 0x50, 0x02, 0x34, 0xb3, 0x82, 0x02, 0xfa, 0xfc, 0x94, 0xaa, 0x26, 0xb4, 0xfb, 0x04, 0xe5, 0xf5, 0x08, 0x74, 0x9a, 0x44, 0xef, 0xb8, 0x9b, 0x75, 0x78, 0xdb, 0x00, 0x7e, 0x03, 0x06, 0x23, 0x89, 0x48, 0x69, 0x12, 0x80, 0xf7, 0x3c, 0x12, 0x7a, 0x49, 0x30, 0xb4, 0x63, 0x39, 0xba, 0xd9 } +, + /* Prime 2 */ + 65, + { 0x04, 0x16, 0xd3, 0xfd, 0xed, 0x8f, 0x9e, 0x7b, 0x01, 0x9f, 0x67, 0x12, 0x32, 0x0e, 0xec, 0x11, 0xd8, 0xcc, 0x83, 0x81, 0xea, 0x86, 0x26, 0x6e, 0xe0, 0x3f, 0x00, 0x72, 0xe9, 0xa2, 0xfc, 0xdd, 0x80, 0x81, 0xae, 0x74, 0xfe, 0x27, 0x88, 0x70, 0xf4, 0xfd, 0xa2, 0xa0, 0x00, 0x6c, 0x4f, 0x54, 0x23, 0x9e, 0x24, 0xa1, 0x5d, 0x1a, 0xeb, 0xc6, 0x7d, 0x90, 0xd8, 0x18, 0x4d, 0x29, 0x5f, 0x52, 0x65 } +, + /* Prime exponent 1 */ + 65, + { 0x04, 0x06, 0x7b, 0x98, 0x7b, 0x5f, 0x8a, 0x8d, 0x56, 0x06, 0x97, 0x4d, 0x11, 0x06, 0x1d, 0x96, 0x29, 0x55, 0x63, 0xe9, 0xc2, 0x6e, 0x7d, 0x3e, 0x4e, 0xba, 0x43, 0xfe, 0x01, 0x24, 0x4d, 0x46, 0x24, 0x46, 0x49, 0x1a, 0xf4, 0x82, 0xf8, 0x86, 0xa9, 0x6b, 0x6d, 0xd1, 0x64, 0xd4, 0xd8, 0x0d, 0xae, 0x00, 0x90, 0x29, 0x04, 0x5e, 0x4e, 0x13, 0x64, 0xb4, 0x9b, 0x9e, 0xdf, 0x81, 0xe8, 0xb5, 0x79 } +, + /* Prime exponent 2 */ + 64, + { 0xe1, 0x38, 0x72, 0xe5, 0x6d, 0x84, 0xd7, 0x4a, 0x1e, 0x15, 0x7a, 0xe0, 0xb2, 0x3d, 0x30, 0x09, 0xc8, 0xd6, 0x72, 0x59, 0x16, 0xcb, 0xa6, 0x07, 0x31, 0x06, 0xd3, 0xb2, 0x58, 0x92, 0xb6, 0xc5, 0x33, 0x21, 0x69, 0xa2, 0x54, 0xb7, 0x12, 0x36, 0x63, 0x6b, 0x5d, 0xa9, 0x39, 0xa4, 0x47, 0xa1, 0xf2, 0x20, 0x47, 0x67, 0x54, 0xa7, 0x6d, 0x69, 0x0e, 0x84, 0xaf, 0x95, 0xca, 0x54, 0xeb, 0xd1 } +, + /* Coefficient */ + 65, + { 0x02, 0x51, 0x37, 0xae, 0x5d, 0x25, 0xfe, 0x1d, 0xaf, 0x9b, 0x38, 0x32, 0xf8, 0x07, 0x56, 0xb8, 0x6d, 0xb5, 0xca, 0x0e, 0x37, 0x2e, 0x51, 0x63, 0x03, 0x4e, 0xa3, 0x39, 0x1f, 0x5e, 0x54, 0x58, 0x2a, 0x1d, 0xd0, 0x47, 0x58, 0xb9, 0x92, 0xa5, 0xa8, 0xe4, 0x6e, 0xe1, 0x6f, 0x8a, 0xd3, 0x8c, 0xa6, 0x52, 0x27, 0x45, 0xaa, 0x7d, 0xf5, 0x1d, 0xf8, 0x9f, 0xc2, 0x21, 0x08, 0x01, 0x0e, 0x00, 0x4e } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 11.1", + /* Message */ + 15, + { 0x4e, 0xa8, 0xdf, 0xda, 0x3a, 0x9c, 0x26, 0x70, 0xca, 0x9b, 0x80, 0xfa, 0x89, 0x71, 0x0a } +, + /* Seed */ + 111, + { 0x96, 0x06, 0x42, 0x1b, 0x97, 0x3a, 0xb4, 0xba, 0x2a, 0xe2, 0x2f, 0xf5, 0x38, 0x70, 0x7d, 0x7d, 0x4e, 0x56, 0x3e, 0x8f, 0x05, 0xf2, 0x0b, 0xc3, 0x38, 0x1f, 0xf4, 0x5b, 0x0c, 0x29, 0x19, 0xa1, 0xb3, 0x46, 0xb0, 0x76, 0x03, 0x5a, 0xe7, 0x74, 0xb3, 0x2a, 0xf8, 0xee, 0x56, 0x6c, 0x73, 0xe2, 0x09, 0x49, 0x68, 0x4e, 0x44, 0x74, 0x80, 0xdf, 0xa3, 0x4d, 0xbb, 0x0c, 0x22, 0x66, 0x61, 0x50, 0x90, 0x9a, 0x59, 0xe1, 0xbb, 0x22, 0xd0, 0x95, 0xab, 0xe5, 0x02, 0x5a, 0x76, 0xd6, 0x0e, 0xc1, 0x01, 0xc7, 0x80, 0xe8, 0x3a, 0x0f, 0xf1, 0x59, 0x46, 0x5c, 0x3e, 0x7a, 0xc0, 0x21, 0x2b, 0xb3, 0x8b, 0x2f, 0x1e, 0x0e, 0x6e, 0x0b, 0x54, 0xd3, 0x5f, 0x4c, 0x76, 0x04, 0xc2, 0xd0, 0x93 } +, + /* Encryption */ + 129, + { 0x09, 0xbb, 0xcd, 0x8b, 0x63, 0xb2, 0x9c, 0xe9, 0x52, 0x26, 0xec, 0x1d, 0x51, 0x91, 0x2a, 0xf3, 0x97, 0x89, 0xfc, 0xe5, 0xe7, 0x7e, 0x7b, 0xe6, 0x78, 0x96, 0xc2, 0xc4, 0xe4, 0xc4, 0x37, 0x6f, 0xa4, 0x28, 0xec, 0x5d, 0x8a, 0x49, 0x7a, 0xcc, 0xa9, 0xe0, 0x82, 0x1e, 0x1f, 0x6d, 0xe1, 0x06, 0x78, 0x19, 0xc4, 0x8a, 0x51, 0x6f, 0x06, 0x91, 0xcb, 0xea, 0xcb, 0xb1, 0x9d, 0x1b, 0xa5, 0x09, 0xf0, 0x4f, 0xc0, 0x13, 0x36, 0xd9, 0x0f, 0x73, 0x96, 0xb4, 0x3a, 0xa2, 0xf2, 0xb5, 0x15, 0x0c, 0x28, 0xa4, 0x5f, 0x35, 0xa9, 0xde, 0x1a, 0x29, 0x73, 0xea, 0x10, 0x28, 0x67, 0x94, 0x94, 0x0a, 0xb7, 0x9f, 0x12, 0x9e, 0x31, 0x8c, 0xf9, 0x7a, 0x5f, 0xd7, 0x2b, 0x04, 0x5b, 0x46, 0x6d, 0x66, 0x6e, 0x5d, 0xe0, 0xb7, 0x14, 0xf2, 0x12, 0xa0, 0xb9, 0x05, 0x2a, 0x0c, 0x91, 0x44, 0x8e, 0x52, 0x0d } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 11.2", + /* Message */ + 27, + { 0xc6, 0xe2, 0x57, 0xf3, 0xa1, 0xb3, 0x5b, 0xbd, 0xc5, 0xcf, 0x42, 0x0b, 0xd7, 0x65, 0x4c, 0x52, 0xb2, 0x52, 0xdf, 0x32, 0xc5, 0x70, 0xd4, 0x28, 0xe6, 0x3e, 0xa2 } +, + /* Seed */ + 99, + { 0x77, 0xbb, 0xd7, 0x2b, 0x7b, 0x8f, 0xd2, 0x85, 0x02, 0xec, 0xf7, 0x9f, 0xd1, 0xc8, 0xaf, 0x8e, 0xbf, 0xe2, 0x44, 0x32, 0x70, 0x93, 0xb8, 0x24, 0x79, 0x5e, 0x95, 0xc0, 0xb4, 0x36, 0xeb, 0x41, 0xe5, 0xf0, 0xf2, 0xae, 0xc4, 0x33, 0x63, 0xaa, 0x2c, 0x08, 0xfc, 0x33, 0xf2, 0x87, 0xe6, 0x53, 0x80, 0x40, 0xe4, 0x28, 0x0d, 0xba, 0x47, 0x23, 0xe5, 0x32, 0x92, 0xe0, 0xa6, 0x7b, 0x21, 0xef, 0x77, 0x70, 0x79, 0x85, 0xb7, 0x2b, 0x2e, 0xca, 0xde, 0x28, 0x0a, 0x61, 0xfa, 0x73, 0xd7, 0x3d, 0xbb, 0x2f, 0xdb, 0x17, 0xf7, 0x75, 0xf4, 0x5f, 0xa1, 0x75, 0xb7, 0x7c, 0xb1, 0x06, 0x7d, 0x6f, 0x93, 0xa4, 0x37 } +, + /* Encryption */ + 129, + { 0x0d, 0x21, 0x49, 0x5c, 0x49, 0x28, 0xc2, 0x6a, 0x92, 0xc1, 0x6a, 0x90, 0x7f, 0x08, 0x33, 0x35, 0xad, 0xe8, 0xeb, 0x0c, 0x20, 0xb0, 0xb4, 0x5f, 0xe0, 0xe0, 0x8e, 0xf3, 0x9a, 0xe2, 0x4e, 0xc0, 0xb5, 0x05, 0x7e, 0x60, 0x78, 0xdd, 0x7a, 0x1b, 0x9d, 0x10, 0x2c, 0x24, 0x81, 0x85, 0x57, 0xe9, 0x0b, 0x83, 0xff, 0xda, 0x14, 0xf3, 0xcc, 0x37, 0x3c, 0x84, 0xc1, 0x05, 0xce, 0xee, 0x71, 0xbc, 0x73, 0x1a, 0x7f, 0x35, 0x71, 0xbd, 0x7b, 0xbb, 0xa1, 0xd4, 0xf2, 0x3f, 0xf4, 0xdf, 0x0a, 0x84, 0xf3, 0x12, 0x99, 0x0f, 0xf7, 0x71, 0xff, 0x11, 0x8f, 0x05, 0xbc, 0xfa, 0x22, 0x2f, 0x11, 0xc1, 0xea, 0x01, 0xf6, 0xa4, 0x68, 0xca, 0x5a, 0x87, 0x50, 0x80, 0x40, 0x98, 0xf8, 0x46, 0xa8, 0x64, 0x30, 0xea, 0x23, 0xe9, 0xf0, 0x7e, 0x23, 0x48, 0x46, 0x1e, 0xf0, 0x0b, 0xa6, 0x25, 0x34, 0xfc, 0xe7 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.3", + /* Message */ + 41, + { 0x2d, 0x30, 0x7f, 0x44, 0xdd, 0xff, 0x9c, 0x45, 0x35, 0xa0, 0x6e, 0xda, 0x01, 0x4a, 0x19, 0x13, 0x04, 0xfb, 0x3f, 0xa8, 0xe3, 0xa2, 0xbe, 0x88, 0xbb, 0x3b, 0x7b, 0xe9, 0x9f, 0x94, 0xd1, 0x33, 0x9c, 0x21, 0x9a, 0x51, 0xff, 0x5c, 0xad, 0xda, 0x93 } +, + /* Seed */ + 85, + { 0x5f, 0xab, 0x24, 0x2d, 0xd9, 0xf2, 0x92, 0x4b, 0x20, 0xd3, 0x78, 0xa8, 0x87, 0xb5, 0xde, 0x21, 0xd1, 0x95, 0x76, 0x9c, 0x3b, 0x53, 0x71, 0xc0, 0x0f, 0x4c, 0x3f, 0x1b, 0x63, 0x26, 0x8b, 0x01, 0x0c, 0x31, 0xf3, 0x2b, 0xb8, 0x7c, 0x9a, 0x52, 0x29, 0xe0, 0xd9, 0x30, 0x5f, 0x5f, 0xc8, 0x3b, 0x89, 0x34, 0xb9, 0x98, 0xd8, 0xce, 0xdf, 0x91, 0x6f, 0x7a, 0x4d, 0x72, 0x68, 0xfe, 0x3b, 0xe5, 0x12, 0x35, 0xf8, 0xbe, 0xac, 0x80, 0x0d, 0x4f, 0xff, 0xca, 0x6f, 0xfd, 0xdb, 0x29, 0xda, 0x4f, 0xa1, 0xc7, 0x76, 0x9d, 0x51 } +, + /* Encryption */ + 129, + { 0x0f, 0xaf, 0xb6, 0x1c, 0x37, 0x16, 0xc7, 0x96, 0x69, 0xfc, 0xd1, 0x64, 0x52, 0x46, 0xa0, 0xd3, 0xb0, 0x75, 0xb2, 0x8b, 0x73, 0x82, 0x20, 0x15, 0xa8, 0xca, 0xdc, 0x88, 0xa2, 0x2b, 0x7d, 0xa5, 0x39, 0x43, 0xe2, 0x54, 0x4d, 0xe3, 0x96, 0xbe, 0xee, 0xd3, 0xb0, 0xa9, 0x89, 0xad, 0x20, 0xa7, 0x3d, 0xdc, 0xd1, 0x91, 0xe8, 0xaa, 0x5c, 0xae, 0xb6, 0xe9, 0x08, 0x8a, 0x4a, 0x3a, 0xe8, 0x40, 0x67, 0xf9, 0x19, 0x8e, 0x92, 0x4a, 0x9c, 0xfe, 0x14, 0x50, 0xb0, 0x18, 0xa6, 0xb6, 0x9d, 0xd2, 0x37, 0x58, 0xe9, 0x25, 0x1c, 0x76, 0xcc, 0xea, 0xe8, 0x40, 0xda, 0x2c, 0xc6, 0x25, 0x17, 0x39, 0xe2, 0x3b, 0x9a, 0x42, 0xb6, 0x34, 0x46, 0xec, 0xa0, 0xd6, 0x15, 0x99, 0xa1, 0x46, 0xb7, 0x41, 0xfd, 0x43, 0x51, 0x1c, 0x73, 0x66, 0x3a, 0x92, 0x3e, 0x37, 0x57, 0xf1, 0x8a, 0x17, 0x1c, 0x3b, 0x12 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.4", + /* Message */ + 10, + { 0x1f, 0x03, 0x33, 0x88, 0x55, 0x4b, 0xeb, 0xfa, 0xa0, 0x1c } +, + /* Seed */ + 116, + { 0x9d, 0x81, 0x57, 0x56, 0x74, 0x66, 0x3b, 0x3d, 0x87, 0x7d, 0x4b, 0x0a, 0xa4, 0xfd, 0xc6, 0x05, 0x47, 0x0a, 0xbc, 0x55, 0x0b, 0x53, 0x52, 0x72, 0xc8, 0x23, 0x70, 0x18, 0x86, 0x7c, 0x50, 0x22, 0xca, 0xfe, 0x6a, 0x4a, 0xc8, 0x37, 0x37, 0xe9, 0x9c, 0x6e, 0xba, 0xfe, 0x69, 0xca, 0xa7, 0xfd, 0xca, 0x70, 0x27, 0xc8, 0xfb, 0xc4, 0x37, 0xec, 0x52, 0x32, 0xce, 0x2e, 0x25, 0x29, 0xa0, 0xf7, 0x03, 0xe2, 0x01, 0xf7, 0xe5, 0x10, 0x32, 0x35, 0xba, 0x65, 0xa6, 0x47, 0x94, 0xf1, 0x90, 0xef, 0x42, 0x54, 0x93, 0xb6, 0x48, 0xed, 0x24, 0xa2, 0x19, 0x7d, 0x0a, 0xb0, 0x4d, 0x81, 0xc7, 0xb3, 0x35, 0xa2, 0xda, 0xfd, 0x6b, 0x59, 0xc9, 0x43, 0xa0, 0x9b, 0x48, 0xea, 0xc3, 0x5e, 0x35, 0x59, 0x62, 0x91, 0xf5, 0xf7 } +, + /* Encryption */ + 129, + { 0x00, 0x1b, 0xdf, 0x33, 0x93, 0x34, 0x2c, 0x38, 0x13, 0xee, 0x3b, 0x87, 0x07, 0xea, 0xf5, 0x46, 0x47, 0xba, 0xde, 0x4c, 0x71, 0x8a, 0x4b, 0x64, 0x54, 0x78, 0x12, 0xe0, 0x10, 0xc2, 0xb7, 0x46, 0xc8, 0x8c, 0xda, 0xfd, 0xc3, 0x16, 0xf0, 0x36, 0x9a, 0x6c, 0x43, 0x0a, 0xe7, 0xe6, 0xc5, 0x0f, 0x05, 0xd5, 0x45, 0xc3, 0xf7, 0x98, 0xde, 0xb1, 0xd9, 0xa5, 0xbb, 0x69, 0xc5, 0x91, 0x39, 0x33, 0xc2, 0xd7, 0x79, 0x2f, 0xae, 0x9d, 0x42, 0xad, 0x76, 0x49, 0x4d, 0xc9, 0xa3, 0xe2, 0x7c, 0x21, 0x1d, 0xb4, 0xef, 0x19, 0x85, 0x18, 0x7a, 0x6c, 0x4d, 0x28, 0x1c, 0x47, 0x72, 0x17, 0x74, 0xa7, 0xa1, 0x1c, 0x12, 0x18, 0xd4, 0xdd, 0x26, 0x7b, 0x57, 0x48, 0x58, 0x77, 0xaa, 0x75, 0x1f, 0x6c, 0x28, 0x19, 0xf8, 0x1b, 0x50, 0x54, 0xa2, 0x8a, 0x26, 0xa5, 0x3d, 0xf3, 0xea, 0x34, 0x82, 0xb3, 0x40 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.5", + /* Message */ + 43, + { 0xf7, 0x1b, 0xc7, 0x37, 0x4b, 0xd5, 0x9c, 0x37, 0x77, 0x59, 0x76, 0xf3, 0x35, 0x24, 0x4a, 0x36, 0x84, 0x3c, 0x59, 0xe7, 0x48, 0x9a, 0xd2, 0x8b, 0x1a, 0x82, 0x2d, 0x2d, 0x7d, 0x0b, 0x9a, 0x6f, 0xe9, 0xac, 0x5b, 0xf4, 0x36, 0x82, 0xd6, 0x3d, 0x63, 0x6e, 0xf6 } +, + /* Seed */ + 83, + { 0xa1, 0xff, 0x98, 0x44, 0xa7, 0x3e, 0xc4, 0xb3, 0xbe, 0xfb, 0x1a, 0x86, 0x03, 0x52, 0xcf, 0x9b, 0x75, 0xfc, 0x66, 0xff, 0x47, 0x9a, 0x2d, 0xed, 0x59, 0x98, 0x84, 0x5a, 0x79, 0x77, 0x3a, 0x8c, 0x62, 0x06, 0xa3, 0x64, 0x36, 0xc8, 0x80, 0xa5, 0x5e, 0x18, 0x71, 0x18, 0x35, 0x45, 0x6d, 0x91, 0x45, 0x4b, 0x5b, 0xa1, 0x32, 0x07, 0x8f, 0x20, 0x37, 0xfb, 0xda, 0x72, 0x86, 0x25, 0x1b, 0xad, 0xd1, 0x2d, 0x0a, 0x97, 0x81, 0xaf, 0x3f, 0x58, 0x97, 0xcd, 0x94, 0x7b, 0x1e, 0x14, 0x25, 0xf9, 0x70, 0x55, 0x09 } +, + /* Encryption */ + 129, + { 0x09, 0x3f, 0xb6, 0x85, 0x26, 0xce, 0xad, 0x01, 0x0a, 0x54, 0xd1, 0x16, 0xcd, 0x7d, 0x60, 0x35, 0x09, 0x9b, 0xf1, 0xab, 0xff, 0xe9, 0x33, 0x1d, 0xe3, 0x64, 0x86, 0xf0, 0x53, 0xa8, 0x02, 0x98, 0xe4, 0xab, 0xfa, 0xb4, 0x0d, 0x3b, 0x03, 0xa3, 0xe7, 0xe9, 0x25, 0x59, 0x73, 0x38, 0xf1, 0x70, 0x3b, 0x04, 0x53, 0x5a, 0x9c, 0x87, 0xc6, 0x58, 0x36, 0xf1, 0x61, 0x11, 0xaa, 0xe8, 0x89, 0xe6, 0xc8, 0xd9, 0x0a, 0x24, 0x07, 0xd4, 0x41, 0xa1, 0xc2, 0xa3, 0x11, 0xcb, 0xd9, 0x46, 0x11, 0xa4, 0x2e, 0x93, 0xc7, 0x3a, 0x3d, 0x21, 0x48, 0x3f, 0xad, 0xb8, 0xf4, 0xe2, 0x46, 0xd0, 0x89, 0xf1, 0xcf, 0xd7, 0x08, 0x52, 0xb4, 0xdc, 0x77, 0x8a, 0x60, 0xd1, 0x52, 0xd3, 0xfc, 0xa7, 0x5f, 0xd6, 0x06, 0x67, 0x04, 0xe9, 0x33, 0xbf, 0x99, 0xf5, 0xbb, 0x77, 0xaf, 0xc9, 0xa9, 0xcb, 0x3b, 0x8c, 0xb5 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.6", + /* Message */ + 25, + { 0x46, 0x87, 0x83, 0xd4, 0xea, 0xc8, 0x81, 0x34, 0x32, 0x04, 0x85, 0x47, 0xce, 0x24, 0x1f, 0x72, 0xdb, 0x1c, 0x85, 0xce, 0x4a, 0xdb, 0xe3, 0xee, 0x2c } +, + /* Seed */ + 101, + { 0xc6, 0xe3, 0x26, 0x30, 0xed, 0x90, 0xd0, 0xaf, 0xb1, 0x68, 0xc0, 0x8b, 0x75, 0x22, 0x59, 0xef, 0x4b, 0x9e, 0x81, 0x17, 0x62, 0xf7, 0xcf, 0x4c, 0x53, 0x5c, 0xb4, 0xa0, 0xa0, 0x4b, 0x1d, 0x43, 0x65, 0x4e, 0xd4, 0xfa, 0xdf, 0xc7, 0xdd, 0xbc, 0x3a, 0xad, 0x03, 0x14, 0x07, 0x8b, 0x22, 0x6c, 0x4f, 0x3e, 0x97, 0x84, 0x45, 0x7c, 0x91, 0xc7, 0x76, 0x8c, 0x5c, 0x37, 0xb7, 0x60, 0x08, 0x93, 0x2e, 0x8d, 0x04, 0x57, 0x85, 0x05, 0x73, 0xce, 0x6b, 0x41, 0xa4, 0x3c, 0xdd, 0xa9, 0x70, 0x03, 0x18, 0x36, 0x84, 0x0e, 0x4e, 0x60, 0xa3, 0x48, 0x7b, 0x47, 0xa1, 0x85, 0xc8, 0x6f, 0x8a, 0x16, 0xf6, 0xf2, 0x21, 0xd0, 0xa0 } +, + /* Encryption */ + 129, + { 0x01, 0x71, 0xa1, 0x2b, 0x00, 0xcf, 0xd1, 0x09, 0x67, 0x4e, 0x5b, 0xf7, 0xf8, 0x43, 0x47, 0xfd, 0xa3, 0xfe, 0x4a, 0x8e, 0xa2, 0xf4, 0x8e, 0x0d, 0x6b, 0x6d, 0x94, 0xb4, 0x9f, 0xd7, 0xbd, 0xfb, 0x26, 0xe3, 0x24, 0x00, 0xa7, 0x12, 0x51, 0xab, 0x84, 0x22, 0x06, 0x92, 0x1d, 0x83, 0x72, 0x3a, 0x89, 0xea, 0x09, 0x93, 0x00, 0x25, 0x92, 0x0e, 0x3e, 0xf8, 0xa8, 0x87, 0xd2, 0xbc, 0x24, 0x15, 0xa7, 0xf1, 0xed, 0x37, 0xba, 0x8a, 0x5d, 0x03, 0xef, 0x92, 0x6a, 0xce, 0xf6, 0x11, 0x90, 0x00, 0x1c, 0x5e, 0xa0, 0xf8, 0xcd, 0x92, 0x02, 0x0c, 0xd8, 0x96, 0x67, 0xe9, 0xea, 0x5f, 0x7f, 0x2b, 0x15, 0x37, 0x8a, 0x21, 0x0b, 0x8a, 0xe9, 0x14, 0x81, 0x90, 0x98, 0xda, 0x1c, 0xbe, 0xc9, 0xc5, 0x43, 0xa2, 0x63, 0x30, 0x0f, 0x99, 0x4f, 0xb0, 0xb4, 0x92, 0x85, 0x71, 0x40, 0x1c, 0x20, 0x2b, 0xd6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.7", + /* Message */ + 26, + { 0xaf, 0x63, 0x1d, 0x76, 0xc9, 0x7f, 0xd9, 0x95, 0xe4, 0x94, 0xaa, 0x9b, 0x4b, 0xd7, 0x58, 0xc5, 0xc6, 0x72, 0xc5, 0xe4, 0x15, 0x8f, 0x3a, 0xaf, 0x87, 0x4b } +, + /* Seed */ + 100, + { 0x40, 0x6e, 0x1e, 0x23, 0xf9, 0x92, 0xbb, 0x07, 0x62, 0x12, 0x5c, 0xa4, 0x63, 0xbd, 0x0f, 0x2e, 0xfd, 0xf1, 0xbf, 0xcb, 0x08, 0x2a, 0x8d, 0xf5, 0x06, 0xaf, 0x5f, 0x72, 0x70, 0xc3, 0x9f, 0xde, 0x01, 0xd9, 0xee, 0xd3, 0x22, 0x66, 0x61, 0xdb, 0x22, 0xa9, 0xc4, 0x04, 0xb7, 0xd7, 0x65, 0xfa, 0x38, 0x4f, 0x9a, 0xd4, 0xf5, 0x1b, 0x93, 0x69, 0xd7, 0x4b, 0x0e, 0x37, 0x70, 0x66, 0x31, 0xbc, 0x65, 0x36, 0xf6, 0x55, 0x5e, 0xc7, 0xfd, 0xeb, 0xd3, 0x48, 0xef, 0x3c, 0xf5, 0xf8, 0xa8, 0x77, 0xf6, 0x06, 0x43, 0x7c, 0x27, 0x8c, 0xb8, 0x16, 0x3a, 0xd3, 0x49, 0x38, 0x4b, 0xaa, 0xe3, 0x2f, 0x31, 0xb6, 0x86, 0xe0 } +, + /* Encryption */ + 129, + { 0x01, 0xff, 0x8f, 0xe7, 0x9a, 0xf3, 0x18, 0xd7, 0x56, 0xf2, 0x84, 0x08, 0x3b, 0x51, 0xb4, 0x3b, 0x66, 0xaa, 0xe8, 0x3c, 0x6a, 0xa9, 0x1a, 0x99, 0x93, 0x4b, 0x4d, 0xe8, 0x4b, 0xd5, 0xfd, 0x24, 0xfa, 0x8d, 0x07, 0xc7, 0x55, 0x14, 0x74, 0x66, 0x5e, 0x62, 0x36, 0x0a, 0x65, 0x98, 0x4e, 0x67, 0xa4, 0x85, 0x6c, 0x3d, 0xbd, 0x2c, 0x75, 0xf2, 0x46, 0xe2, 0x22, 0x22, 0xe9, 0xf4, 0xb9, 0x69, 0x51, 0x67, 0x26, 0xed, 0x28, 0x7f, 0x42, 0x3a, 0x67, 0x47, 0x82, 0x1f, 0xbb, 0xb7, 0xfa, 0x17, 0x62, 0x35, 0xc8, 0x50, 0xa8, 0x61, 0xf2, 0x99, 0xf7, 0x39, 0x4c, 0x2c, 0x43, 0x07, 0xb1, 0x02, 0x59, 0x09, 0x40, 0xfe, 0xd1, 0x20, 0x6a, 0xd5, 0x9b, 0x9d, 0xd6, 0x44, 0x4e, 0x1e, 0x19, 0x6e, 0x94, 0x73, 0x25, 0x22, 0x4f, 0xfa, 0xca, 0x06, 0x9e, 0x9c, 0xdf, 0x8c, 0x62, 0x02, 0x69, 0x07, 0x7d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.8", + /* Message */ + 56, + { 0x73, 0xcb, 0x53, 0x90, 0x82, 0xfb, 0x06, 0xdc, 0xae, 0x3c, 0x20, 0x68, 0xe9, 0x89, 0xe7, 0xc0, 0xd8, 0xff, 0xf0, 0xfb, 0x34, 0x0b, 0x6d, 0xe8, 0x0d, 0x0b, 0xa5, 0xd1, 0xe0, 0x06, 0x4f, 0x22, 0x13, 0x92, 0x8a, 0x4b, 0xaf, 0x20, 0xa8, 0x03, 0x48, 0xaf, 0x3c, 0xde, 0x9d, 0xe6, 0x3f, 0x88, 0x6d, 0x63, 0xe5, 0x6a, 0x3e, 0x32, 0xcd, 0x8e } +, + /* Seed */ + 70, + { 0x28, 0xe2, 0xa9, 0x7c, 0x7e, 0x9e, 0x03, 0x3b, 0x49, 0xaa, 0xdc, 0xee, 0x8f, 0xdc, 0x07, 0xed, 0xfd, 0xfd, 0xb9, 0x50, 0x35, 0x4b, 0x70, 0x8c, 0xe5, 0xdf, 0x84, 0x8d, 0x1b, 0x51, 0xaa, 0x2f, 0x4a, 0xff, 0x99, 0x74, 0x16, 0x01, 0x81, 0x42, 0x29, 0x47, 0xb1, 0x33, 0x76, 0x4c, 0x5a, 0x40, 0x06, 0x57, 0x04, 0x6a, 0x49, 0x36, 0x3f, 0xfd, 0xf1, 0xf9, 0x3c, 0xa4, 0x8b, 0x3e, 0x52, 0x93, 0x7e, 0x1f, 0x38, 0xfb, 0x50, 0xfb } +, + /* Encryption */ + 129, + { 0x0c, 0x72, 0xe6, 0x95, 0x48, 0xc3, 0x4e, 0xca, 0xf2, 0x48, 0xb2, 0xdc, 0x6b, 0xb6, 0x43, 0x87, 0xf4, 0xf3, 0x35, 0x0f, 0x66, 0x8e, 0x59, 0x01, 0x35, 0x60, 0x80, 0x8c, 0x41, 0x3f, 0xa8, 0x35, 0xfd, 0x36, 0x0e, 0x04, 0xe4, 0x74, 0x7a, 0x00, 0x31, 0xc8, 0xa6, 0x4a, 0x9d, 0x7a, 0x07, 0xb3, 0x63, 0xfa, 0xd2, 0x93, 0xb7, 0x03, 0xa7, 0xdc, 0x99, 0x0f, 0x80, 0x6f, 0xb9, 0x0e, 0x39, 0x12, 0x21, 0xa1, 0x16, 0xdf, 0x10, 0x8f, 0x54, 0x6e, 0xae, 0x51, 0x71, 0x6b, 0xa0, 0x45, 0x01, 0xab, 0x77, 0x7b, 0x0c, 0x2a, 0x17, 0x71, 0x2f, 0x71, 0xe4, 0x06, 0x27, 0x5f, 0x01, 0x73, 0x77, 0xcf, 0x24, 0x88, 0xc4, 0x35, 0xef, 0x6c, 0x6e, 0x7c, 0x45, 0xcd, 0xb9, 0x8f, 0x24, 0x47, 0x7c, 0xed, 0x18, 0x0e, 0xb3, 0xef, 0xc8, 0x70, 0x3e, 0x96, 0x38, 0x26, 0xbf, 0xb3, 0x44, 0xf1, 0x6e, 0xb4, 0xa1 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.9", + /* Message */ + 38, + { 0xf2, 0xf9, 0x85, 0xb8, 0x03, 0x12, 0x73, 0xcb, 0x5f, 0xc8, 0x9a, 0x31, 0xdd, 0xeb, 0x4c, 0x67, 0xa4, 0xe4, 0xf3, 0x8c, 0x09, 0xd3, 0x02, 0x87, 0x42, 0x09, 0xb3, 0x9c, 0x69, 0xb7, 0x1f, 0x84, 0x95, 0x88, 0x86, 0x8f, 0xa5, 0xf8 } +, + /* Seed */ + 88, + { 0xc1, 0x20, 0x44, 0x6f, 0x5b, 0xdd, 0xa0, 0x6c, 0x63, 0x73, 0x8f, 0x18, 0x15, 0x55, 0x95, 0xf6, 0x2b, 0xc2, 0x65, 0x67, 0x28, 0x4c, 0x35, 0x03, 0x65, 0x91, 0xcd, 0x5d, 0x75, 0x3e, 0x4e, 0xf7, 0x90, 0x0d, 0xff, 0x33, 0xbf, 0xdd, 0x3b, 0x10, 0x8c, 0x10, 0x2d, 0x08, 0x98, 0x80, 0xc7, 0xb6, 0x9d, 0x86, 0xe9, 0xce, 0x3d, 0x68, 0x8c, 0xda, 0x15, 0x6f, 0xd6, 0xa9, 0x92, 0x31, 0x05, 0x8c, 0xc3, 0x18, 0x33, 0x96, 0x38, 0x09, 0x46, 0xe8, 0xa9, 0x69, 0xa7, 0xfc, 0xbe, 0x9e, 0xdc, 0x95, 0x9a, 0x0e, 0x50, 0x45, 0x32, 0xba, 0xb8, 0xea } +, + /* Encryption */ + 129, + { 0x10, 0xe0, 0xbc, 0x14, 0xba, 0x16, 0x01, 0x26, 0x98, 0xcc, 0x76, 0xcb, 0x82, 0x04, 0x5e, 0x2b, 0xfd, 0xbc, 0xb2, 0xb1, 0x18, 0xf1, 0x83, 0x06, 0x79, 0x59, 0xd7, 0x13, 0x7f, 0xd5, 0x0f, 0xa8, 0x8f, 0xe4, 0xf9, 0xce, 0xcf, 0x66, 0x31, 0xa9, 0x9c, 0xcc, 0xab, 0x76, 0xcd, 0xb7, 0x74, 0x4b, 0xab, 0xd0, 0x6b, 0x2b, 0xed, 0xfb, 0xca, 0x77, 0x24, 0xda, 0xfd, 0x91, 0xe6, 0xdf, 0xa8, 0x8b, 0xea, 0x2b, 0x44, 0xa8, 0xcb, 0xb0, 0x62, 0x19, 0xb1, 0x5c, 0x2a, 0xe7, 0x68, 0x72, 0xfa, 0xd2, 0x88, 0xe8, 0x43, 0x8a, 0xcd, 0x39, 0x5c, 0xe5, 0xcb, 0xe2, 0x8a, 0x71, 0x2b, 0x67, 0xf5, 0x61, 0xa1, 0x78, 0x6d, 0x75, 0x34, 0x3e, 0xd9, 0xad, 0x0d, 0x0a, 0x5e, 0xb6, 0xfa, 0xed, 0x07, 0xb0, 0x6a, 0xef, 0x03, 0x31, 0x8f, 0xf1, 0xaf, 0xe4, 0x72, 0xdb, 0x4e, 0xe3, 0xe2, 0x1e, 0xc1, 0x29, 0x33 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.10", + /* Message */ + 36, + { 0x39, 0x87, 0x2c, 0xfd, 0x6c, 0xf7, 0x4b, 0x4c, 0xcc, 0x1a, 0x70, 0xd9, 0x73, 0xb3, 0x18, 0x99, 0xa6, 0x7a, 0xee, 0xde, 0xe5, 0xd6, 0x71, 0xe0, 0x5b, 0xd6, 0x01, 0x12, 0xe6, 0x45, 0x12, 0xbb, 0xe4, 0x3b, 0xb8, 0x40 } +, + /* Seed */ + 90, + { 0x68, 0xac, 0x3f, 0x96, 0x97, 0xb7, 0x50, 0x75, 0x4f, 0xa7, 0x53, 0x2e, 0x41, 0x61, 0xc1, 0x20, 0x18, 0xe0, 0x33, 0xa6, 0x02, 0x51, 0xc8, 0xdc, 0xa8, 0x38, 0x78, 0x16, 0xf4, 0x23, 0x79, 0xab, 0x97, 0x8e, 0x15, 0x57, 0x8a, 0xe2, 0xe9, 0x4c, 0x17, 0x76, 0x48, 0x8b, 0x0c, 0xfd, 0xff, 0x18, 0x6f, 0xa6, 0xd7, 0x98, 0x88, 0xf8, 0x16, 0x9e, 0xe4, 0x49, 0xea, 0xdd, 0xc8, 0xe7, 0xf5, 0xa6, 0x58, 0xd0, 0x99, 0x7a, 0x93, 0x4f, 0x58, 0x6e, 0x31, 0xf7, 0x47, 0x30, 0xbe, 0x60, 0x3f, 0x1e, 0xe6, 0x2f, 0xa6, 0xc0, 0x8b, 0x0b, 0xff, 0xae, 0x6b, 0x88 } +, + /* Encryption */ + 129, + { 0x09, 0xb7, 0x70, 0x07, 0xf1, 0x5d, 0x65, 0x9e, 0xfc, 0xca, 0xca, 0x66, 0xc1, 0xe7, 0xd9, 0x62, 0xe0, 0x47, 0xa1, 0xe1, 0x49, 0xe5, 0x2d, 0xcc, 0x0e, 0x1a, 0xdc, 0x9e, 0x18, 0x3b, 0xf7, 0x3b, 0x5f, 0x23, 0x48, 0xd3, 0x43, 0x28, 0x24, 0x1b, 0x40, 0x7f, 0x61, 0x82, 0x2f, 0x6d, 0x57, 0xe1, 0xab, 0xb3, 0x22, 0xd3, 0x02, 0xf4, 0x53, 0x0d, 0x2c, 0xb9, 0xa4, 0x1a, 0x27, 0x70, 0x23, 0x8a, 0x1b, 0xdf, 0x87, 0x5e, 0xdd, 0x79, 0x78, 0x10, 0xd9, 0x04, 0xe9, 0x7a, 0x4d, 0x7c, 0x51, 0x51, 0x32, 0xd6, 0xab, 0xbf, 0x3a, 0x4a, 0x40, 0x74, 0x86, 0xdd, 0x00, 0x4e, 0xa3, 0x8a, 0xff, 0x8d, 0x4e, 0xd3, 0x82, 0x5f, 0xe1, 0x31, 0x42, 0xf1, 0x36, 0xfd, 0x1d, 0x71, 0x3e, 0x80, 0xe0, 0xcf, 0x22, 0x57, 0x69, 0xb4, 0x19, 0xcc, 0xa5, 0x4c, 0x15, 0x6e, 0x54, 0x66, 0x8b, 0x30, 0x6b, 0x5f, 0x2a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.11", + /* Message */ + 14, + { 0x74, 0xd5, 0x6b, 0xf8, 0xd9, 0xc1, 0x80, 0xdc, 0x09, 0x93, 0x71, 0xa5, 0xaf, 0x72 } +, + /* Seed */ + 112, + { 0x33, 0x78, 0x70, 0xf0, 0x47, 0x9c, 0xf1, 0x28, 0x3a, 0x0c, 0x87, 0xc9, 0xc4, 0xaf, 0x54, 0xba, 0x8f, 0x85, 0x06, 0x44, 0xd5, 0x9a, 0x20, 0x25, 0x26, 0x3d, 0x2b, 0xdc, 0x49, 0xbf, 0xa6, 0x63, 0x6e, 0x75, 0x18, 0xf9, 0x4b, 0x6a, 0xb1, 0x8f, 0x85, 0xb1, 0x93, 0x21, 0x20, 0x9b, 0x76, 0x9f, 0x0c, 0x19, 0x75, 0xd1, 0xd5, 0xad, 0xa0, 0x6f, 0xd2, 0xa7, 0x6c, 0x82, 0x45, 0x0e, 0x4e, 0x09, 0xcd, 0xad, 0xb7, 0x83, 0x2f, 0xfb, 0x8a, 0xe7, 0xdc, 0xb4, 0x74, 0x10, 0xb2, 0x87, 0x80, 0x4d, 0xdd, 0xc7, 0x49, 0x3d, 0x61, 0x0a, 0x81, 0x39, 0x9b, 0x6d, 0xf6, 0xdf, 0x5e, 0xf1, 0x52, 0x09, 0x29, 0x84, 0xfe, 0x27, 0x76, 0xa4, 0xf9, 0x30, 0x54, 0x6b, 0xe1, 0xdc, 0x18, 0x31, 0x3c, 0x14 } +, + /* Encryption */ + 129, + { 0x07, 0x61, 0xeb, 0xaa, 0xd8, 0xff, 0x1c, 0x3d, 0xbe, 0x71, 0x0f, 0x60, 0xe3, 0xbe, 0x9f, 0x28, 0x9f, 0xb2, 0x7a, 0x6b, 0x53, 0x77, 0x75, 0x5b, 0x71, 0xfb, 0x38, 0x4c, 0x5f, 0xac, 0xb1, 0x60, 0x3c, 0x95, 0x3e, 0x1e, 0x2c, 0xa1, 0x1e, 0x78, 0x43, 0x25, 0xae, 0x42, 0xf3, 0x21, 0xae, 0x5c, 0x58, 0x64, 0x8c, 0x84, 0xf5, 0x24, 0xdf, 0x9d, 0xe9, 0xf9, 0x3f, 0xb4, 0xb0, 0xc2, 0xe0, 0x97, 0x97, 0xff, 0x2d, 0x11, 0x40, 0x70, 0x73, 0xb9, 0x5a, 0x78, 0x6d, 0xf5, 0x1a, 0x43, 0xf7, 0x99, 0x82, 0xd8, 0x6c, 0x49, 0xfb, 0x9e, 0x50, 0x14, 0xb1, 0xb7, 0x68, 0x76, 0x0a, 0x51, 0x30, 0x26, 0x6d, 0x06, 0x99, 0x30, 0x6a, 0x90, 0x4e, 0xd2, 0xdf, 0xe2, 0x01, 0x38, 0xd5, 0x31, 0xc5, 0xdc, 0x4b, 0xbf, 0x4d, 0xcc, 0xf1, 0x02, 0x49, 0xa6, 0xe2, 0xb3, 0x55, 0xf7, 0xcc, 0xb3, 0x26, 0xa4, 0x8a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.12", + /* Message */ + 35, + { 0x61, 0x10, 0x63, 0xb5, 0xda, 0x12, 0x3c, 0xe2, 0x12, 0x96, 0x17, 0xdf, 0x38, 0x59, 0x95, 0x57, 0xb9, 0x5d, 0x1b, 0x05, 0xe6, 0xb6, 0x6b, 0xcd, 0x49, 0xaf, 0xe9, 0x83, 0x1a, 0x04, 0x21, 0xa5, 0xbe, 0x4e, 0x48 } +, + /* Seed */ + 91, + { 0x10, 0xf9, 0xdf, 0x30, 0xec, 0x97, 0x77, 0xfc, 0xab, 0x5a, 0x92, 0x4d, 0xed, 0x36, 0xfd, 0xfd, 0x6e, 0x1f, 0x38, 0x14, 0x49, 0xad, 0x99, 0xd2, 0x0a, 0xea, 0x0e, 0x39, 0x72, 0xea, 0x60, 0x4e, 0xa2, 0x27, 0x50, 0xd0, 0x60, 0x1d, 0x10, 0xa3, 0x77, 0xda, 0xd1, 0xa9, 0x4f, 0x9b, 0x02, 0x73, 0x40, 0x94, 0x81, 0x23, 0x82, 0x73, 0x98, 0xbb, 0x22, 0xb1, 0x44, 0x5f, 0x71, 0xc5, 0x05, 0xc6, 0x23, 0xaa, 0xf5, 0x16, 0xcd, 0x9f, 0xb3, 0xe9, 0x77, 0xf7, 0x78, 0xcf, 0xdd, 0x3a, 0x5d, 0x28, 0xc2, 0x29, 0x9e, 0x4b, 0x2a, 0xbd, 0x9f, 0x98, 0xc4, 0x35, 0x5a } +, + /* Encryption */ + 129, + { 0x07, 0xf2, 0xd5, 0x8b, 0xc4, 0x16, 0x39, 0x94, 0xd7, 0x6f, 0x49, 0x1e, 0xdd, 0x69, 0x74, 0x3c, 0x45, 0xdd, 0xa0, 0xc3, 0x8c, 0xcb, 0x07, 0x69, 0xde, 0x9c, 0xf9, 0xf4, 0xfd, 0x00, 0x55, 0xd3, 0x0a, 0x0c, 0xf0, 0x02, 0x80, 0x0d, 0x76, 0xed, 0x8c, 0x12, 0xcb, 0xd3, 0x6a, 0xf0, 0x51, 0xa9, 0xd7, 0x33, 0x7b, 0x29, 0xbc, 0x77, 0x4d, 0xc3, 0xc4, 0x01, 0x2b, 0xf5, 0xc2, 0x8a, 0xea, 0xd8, 0xc3, 0xe0, 0x36, 0xaa, 0x41, 0x39, 0x8a, 0x8b, 0x0f, 0xe9, 0x91, 0xc0, 0xbf, 0x66, 0xb5, 0x34, 0x1c, 0x99, 0xd9, 0x37, 0x7d, 0x94, 0x70, 0x4a, 0xd4, 0x90, 0xa9, 0xf8, 0x74, 0x6f, 0xc5, 0xce, 0xf7, 0x26, 0xe1, 0x96, 0xf3, 0x41, 0xf9, 0x3a, 0x1f, 0x1e, 0xae, 0x2c, 0x13, 0xe0, 0x0c, 0xfd, 0x22, 0x06, 0x2f, 0x8e, 0xb3, 0xda, 0x9d, 0xaf, 0xb9, 0x5a, 0x1e, 0x7b, 0x81, 0xb1, 0xfd, 0xb6, 0x56 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.13", + /* Message */ + 36, + { 0x80, 0x76, 0x4f, 0x78, 0x5f, 0xd4, 0x17, 0x6e, 0x16, 0x41, 0xe1, 0x29, 0xa3, 0x5a, 0x9b, 0x31, 0xb3, 0xa8, 0x9a, 0x75, 0x67, 0xad, 0x6c, 0x1f, 0x0d, 0x65, 0xec, 0x8a, 0xf9, 0x5f, 0xc1, 0x6e, 0x15, 0x28, 0x14, 0x09 } +, + /* Seed */ + 90, + { 0x20, 0x36, 0xd0, 0x98, 0xa6, 0xe9, 0x35, 0xf9, 0xa4, 0x11, 0x20, 0x1d, 0x2b, 0xcb, 0x62, 0x9f, 0x79, 0x0a, 0x94, 0xdb, 0x2e, 0xc6, 0x98, 0x67, 0x43, 0x3b, 0x17, 0x61, 0xd7, 0xc6, 0x95, 0x4b, 0xe9, 0x1a, 0x9f, 0xc7, 0x19, 0x19, 0x0e, 0x10, 0x86, 0x13, 0xcd, 0x58, 0x4c, 0xbb, 0x97, 0x76, 0x87, 0x04, 0x69, 0x24, 0xbc, 0xa6, 0xb2, 0xfe, 0x1a, 0x54, 0xbf, 0x76, 0xac, 0xf7, 0x7b, 0x36, 0x8c, 0x39, 0x65, 0x0f, 0x6d, 0x0a, 0x49, 0x8d, 0xbd, 0xed, 0xae, 0x3f, 0x4c, 0x21, 0x04, 0x0a, 0x8a, 0xed, 0x63, 0x4d, 0xe4, 0xed, 0x8a, 0xf1, 0x34, 0x6e } +, + /* Encryption */ + 129, + { 0x04, 0x9c, 0x61, 0x44, 0x4e, 0x92, 0x47, 0x72, 0xf9, 0x4a, 0x79, 0x5c, 0xcd, 0x99, 0xeb, 0x2f, 0xe4, 0x30, 0x99, 0x7b, 0x91, 0xb4, 0x2d, 0xe6, 0x16, 0x36, 0x29, 0xab, 0x98, 0xd2, 0x5a, 0x71, 0xe7, 0xf9, 0x68, 0x86, 0xa5, 0x7e, 0x97, 0x9d, 0x9c, 0x94, 0xc9, 0x62, 0x20, 0x9c, 0x1f, 0x71, 0x2c, 0x70, 0x57, 0x1a, 0x81, 0xf3, 0x77, 0xea, 0xf7, 0x4e, 0x80, 0xe7, 0x07, 0x22, 0xe1, 0xbe, 0x3d, 0x13, 0x37, 0xc5, 0x04, 0x5f, 0x79, 0x7b, 0xd5, 0x7d, 0xf2, 0xf5, 0xae, 0x5e, 0xf3, 0x3a, 0xe5, 0x79, 0xe9, 0x3b, 0x38, 0xfb, 0x25, 0x0d, 0xf0, 0xc2, 0xbc, 0x59, 0xb3, 0x3a, 0x74, 0x86, 0x7b, 0x8f, 0x3d, 0xfe, 0x5b, 0xa7, 0x85, 0xd7, 0x28, 0xb8, 0x9d, 0x96, 0xb3, 0x00, 0x2b, 0xc0, 0x05, 0x4d, 0xb5, 0xbb, 0x0d, 0x84, 0xfd, 0xa4, 0x5d, 0xb4, 0xa1, 0xf2, 0x62, 0x8a, 0xb1, 0x12, 0x30 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.14", + /* Message */ + 18, + { 0x0a, 0xbc, 0x2b, 0xc5, 0xfc, 0xd0, 0x40, 0x18, 0x9f, 0x84, 0x22, 0xf1, 0xca, 0x04, 0x50, 0x21, 0xda, 0x95 } +, + /* Seed */ + 108, + { 0xe4, 0x73, 0x2e, 0x49, 0x90, 0x69, 0x9f, 0xd7, 0x47, 0x40, 0xc8, 0x52, 0xae, 0x8d, 0x4d, 0x70, 0x7f, 0xbd, 0x79, 0x46, 0x0f, 0x88, 0x74, 0x09, 0x84, 0xae, 0x53, 0xff, 0xb9, 0xfc, 0x39, 0x62, 0x68, 0x3e, 0xad, 0x0d, 0x14, 0x04, 0xf5, 0x31, 0x51, 0xd1, 0xae, 0xe8, 0x0f, 0xcd, 0x6a, 0x1f, 0xf6, 0x5f, 0xc8, 0x8e, 0xf0, 0x8f, 0xd7, 0x6d, 0x9f, 0xdc, 0xa8, 0xf9, 0xe3, 0xac, 0x7d, 0x8d, 0x82, 0xb8, 0x2e, 0xce, 0x78, 0x9c, 0x66, 0xc5, 0x40, 0x22, 0x80, 0xb3, 0xe5, 0x68, 0x10, 0x1c, 0xe2, 0xa2, 0xa7, 0xb2, 0xb2, 0xf1, 0xe9, 0x65, 0x19, 0xcf, 0xb4, 0x1e, 0x60, 0x49, 0x3d, 0x76, 0x8e, 0xb5, 0xb9, 0x6c, 0xcc, 0x49, 0xbb, 0x0f, 0x6e, 0xc7, 0x11, 0xfd } +, + /* Encryption */ + 129, + { 0x03, 0xd8, 0xae, 0x60, 0x4f, 0x92, 0x95, 0x31, 0x73, 0xc7, 0x7a, 0x01, 0xff, 0xa0, 0x90, 0xaa, 0x0e, 0x37, 0xa3, 0x8a, 0x47, 0xc9, 0x72, 0x19, 0xc0, 0xb9, 0xf8, 0x64, 0xd3, 0x48, 0x74, 0x6a, 0xf7, 0xf4, 0xa6, 0x32, 0x11, 0x29, 0xc6, 0x04, 0x6a, 0x99, 0x4c, 0xed, 0x1c, 0xcf, 0x33, 0x24, 0xda, 0x93, 0x71, 0x53, 0x88, 0x8d, 0xd6, 0xc6, 0x70, 0x19, 0xa7, 0xca, 0xa7, 0x65, 0x5a, 0x36, 0x42, 0x83, 0x8e, 0xdf, 0xa0, 0xe2, 0xed, 0x8d, 0xc2, 0x5c, 0x14, 0xbf, 0xf8, 0xbf, 0xf5, 0x65, 0xc7, 0x18, 0xf8, 0xb6, 0xc9, 0x20, 0x56, 0xc9, 0xbb, 0xe8, 0xd9, 0x30, 0x83, 0x70, 0xc7, 0xcd, 0x75, 0xa0, 0x4e, 0x11, 0xb6, 0xe2, 0x5a, 0xa6, 0xc3, 0xc2, 0xcd, 0xdd, 0x17, 0x2a, 0x4b, 0x6a, 0xee, 0xf0, 0x4f, 0xb8, 0x35, 0xb6, 0x86, 0x37, 0xcf, 0x0c, 0xa0, 0xb9, 0xa9, 0x11, 0xb8, 0xb8, 0x74 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.15", + /* Message */ + 24, + { 0x8f, 0x98, 0x35, 0xef, 0xb6, 0x9c, 0xca, 0x8c, 0x07, 0xbf, 0xef, 0x4d, 0x8f, 0x53, 0x5d, 0x0c, 0xbd, 0xa5, 0x36, 0x7b, 0xbd, 0x41, 0x08, 0x0a } +, + /* Seed */ + 102, + { 0x32, 0xd4, 0xbe, 0x07, 0xe6, 0xc7, 0xfb, 0x81, 0xd5, 0x20, 0x8c, 0x25, 0x01, 0xc5, 0xdf, 0x7c, 0x56, 0xd1, 0x98, 0x6d, 0xc6, 0xd6, 0x31, 0x10, 0xad, 0x21, 0xd8, 0x1e, 0x57, 0xce, 0x11, 0x3f, 0x3d, 0xbb, 0xfe, 0xbe, 0x0f, 0x80, 0xc0, 0x16, 0xb7, 0x19, 0xe9, 0xd5, 0xc3, 0xd9, 0xa3, 0xbb, 0xbb, 0x2f, 0x35, 0xbe, 0x95, 0xd4, 0x56, 0x22, 0x2b, 0x51, 0xc3, 0xd6, 0x5b, 0x38, 0x8e, 0x7a, 0xda, 0xf6, 0xb9, 0xce, 0xae, 0x1f, 0xd4, 0x6a, 0x6e, 0x05, 0xca, 0x1b, 0xb1, 0x99, 0xc2, 0x7b, 0xac, 0xdc, 0x8b, 0x5f, 0xd1, 0x4f, 0x03, 0x51, 0xae, 0xb3, 0xfd, 0xd6, 0xdc, 0x1d, 0x93, 0xf3, 0xb5, 0x31, 0x56, 0xef, 0xa3, 0xc6 } +, + /* Encryption */ + 129, + { 0x0e, 0x47, 0xad, 0x4d, 0x92, 0xd1, 0x9a, 0x1e, 0xbc, 0xac, 0xbf, 0x87, 0x5d, 0x80, 0x19, 0x27, 0xd4, 0xfe, 0x5a, 0xfa, 0xf6, 0x6e, 0xd8, 0x01, 0x5c, 0x55, 0x9b, 0x56, 0x6a, 0x9f, 0x3c, 0xbf, 0x0a, 0xbe, 0x8a, 0x76, 0xfe, 0x73, 0x24, 0xf6, 0x28, 0xc2, 0xe4, 0xf3, 0x45, 0x84, 0xa5, 0x0f, 0xf7, 0x7e, 0x82, 0x2a, 0x54, 0x11, 0x8e, 0xfa, 0x9b, 0xae, 0x9d, 0x0f, 0xa5, 0x02, 0x94, 0xc6, 0x18, 0x0b, 0xaf, 0x3a, 0x8b, 0x0c, 0x7e, 0x45, 0x3a, 0x74, 0x37, 0xab, 0x1a, 0x19, 0xcc, 0x00, 0x30, 0x7a, 0x8c, 0x6a, 0xed, 0x95, 0xc3, 0x15, 0xb2, 0x4b, 0x47, 0x90, 0x07, 0x24, 0x56, 0xc9, 0x44, 0x60, 0x99, 0x5d, 0xbb, 0x1f, 0xe5, 0xa1, 0x2b, 0x4c, 0xf4, 0x45, 0x42, 0x96, 0xf7, 0x40, 0x02, 0x83, 0xce, 0xfd, 0xce, 0x6b, 0x00, 0xcc, 0x80, 0x49, 0xdd, 0x5d, 0xd8, 0xcb, 0x2a, 0xf3, 0x6f } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.16", + /* Message */ + 47, + { 0x6d, 0xfb, 0xd9, 0x3b, 0x00, 0x78, 0xd4, 0x9a, 0xe4, 0xfe, 0x1e, 0x24, 0xcc, 0xa9, 0x7d, 0x0a, 0x9a, 0xff, 0xd7, 0xbe, 0xe0, 0x62, 0xae, 0xd2, 0x9d, 0xef, 0x0b, 0x1c, 0x0b, 0x3a, 0xef, 0xad, 0x81, 0x1d, 0x6e, 0x7a, 0xce, 0x8b, 0x49, 0xd7, 0x24, 0x2a, 0x9f, 0xe6, 0xe2, 0x3c, 0x22 } +, + /* Seed */ + 79, + { 0x31, 0x9f, 0x9c, 0xda, 0x2c, 0x93, 0x38, 0x8e, 0xbe, 0x1a, 0x50, 0xe7, 0x6c, 0x93, 0x97, 0x55, 0x9d, 0xca, 0xf1, 0x4f, 0xe1, 0x03, 0x52, 0xaa, 0x51, 0x1d, 0xc5, 0xba, 0xa6, 0x4d, 0xc1, 0x52, 0xfc, 0xc7, 0x9c, 0xbb, 0x23, 0xd4, 0xe6, 0x9b, 0x12, 0xb9, 0xf2, 0x7a, 0x79, 0x09, 0x15, 0x98, 0x87, 0xbb, 0x04, 0x12, 0x9a, 0xd6, 0x35, 0x16, 0x81, 0x33, 0x86, 0x37, 0x4f, 0x31, 0x89, 0x2d, 0x4c, 0xdc, 0x4f, 0xe6, 0x39, 0x69, 0xb5, 0xbf, 0xdd, 0xc6, 0x67, 0xf9, 0x46, 0x89, 0x7d } +, + /* Encryption */ + 129, + { 0x01, 0xc5, 0xce, 0x83, 0x6b, 0xe2, 0x20, 0x8a, 0x3d, 0x81, 0x4e, 0x7e, 0x60, 0xc2, 0x76, 0x74, 0xac, 0xb7, 0xcd, 0x3e, 0x31, 0xc0, 0x24, 0xd9, 0xd3, 0x8f, 0xc2, 0x29, 0x53, 0xaa, 0xfe, 0x73, 0xaf, 0x52, 0x40, 0x43, 0x4d, 0xcf, 0x54, 0xa3, 0x88, 0x99, 0x2e, 0xac, 0x36, 0xec, 0x84, 0x64, 0xd9, 0xa0, 0x42, 0xac, 0x58, 0xd1, 0x8a, 0x70, 0x39, 0x8b, 0x8a, 0x77, 0x3e, 0x66, 0x69, 0xbb, 0x3d, 0x76, 0xee, 0xac, 0xdf, 0x1f, 0xd1, 0x52, 0x47, 0x40, 0x99, 0xbf, 0xa6, 0x62, 0xa4, 0x81, 0xdb, 0xab, 0x4c, 0xa4, 0x67, 0x14, 0x95, 0x87, 0x45, 0xe2, 0xb7, 0x83, 0x2a, 0x59, 0xcc, 0xb0, 0x05, 0x36, 0x49, 0xb7, 0xe0, 0x95, 0x07, 0x43, 0x33, 0x3f, 0x5f, 0xcd, 0x6f, 0x65, 0x19, 0x7d, 0xdc, 0xb4, 0xe1, 0xbc, 0x12, 0xa6, 0x6e, 0x8e, 0x92, 0xa8, 0x65, 0x9f, 0xae, 0xe5, 0x71, 0x31, 0xe2 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.17", + /* Message */ + 31, + { 0xe5, 0x87, 0x9f, 0xfc, 0xe0, 0xb6, 0x29, 0xb8, 0x85, 0x7c, 0x19, 0x5c, 0xf5, 0xd0, 0x9f, 0x7b, 0x93, 0xbf, 0xf1, 0xf7, 0xa9, 0xf2, 0xd8, 0xa4, 0x5a, 0x56, 0x3b, 0xbb, 0xe9, 0xe6, 0x2d } +, + /* Seed */ + 95, + { 0xba, 0xce, 0x2c, 0xea, 0x0b, 0xfe, 0xc2, 0x5a, 0x2d, 0x34, 0xd7, 0x29, 0x92, 0xc2, 0xb8, 0xea, 0x0a, 0xea, 0x17, 0xb7, 0xa3, 0xa8, 0xbe, 0xd6, 0x0d, 0x1b, 0xb5, 0x10, 0x13, 0x34, 0x7b, 0x2d, 0x03, 0x6a, 0x75, 0xa4, 0xec, 0x3e, 0xb2, 0xc1, 0x78, 0x8d, 0x44, 0xa9, 0xe1, 0xc5, 0xc8, 0x8d, 0x04, 0x1e, 0x82, 0xaf, 0x87, 0x81, 0x55, 0xdd, 0xc7, 0xd8, 0x1b, 0x3e, 0x27, 0xcd, 0xdd, 0x20, 0x40, 0x9d, 0xbd, 0xda, 0x4a, 0x64, 0xbf, 0x83, 0x11, 0xa7, 0xb7, 0xeb, 0x77, 0x29, 0x93, 0x12, 0x66, 0x1a, 0x6e, 0x37, 0xdf, 0x35, 0x02, 0xf8, 0x6a, 0x22, 0x49, 0x2b, 0xef, 0xac, 0xf4 } +, + /* Encryption */ + 129, + { 0x01, 0xe4, 0xfa, 0xeb, 0xca, 0xb8, 0x9d, 0x7b, 0xaa, 0x3e, 0x03, 0x93, 0xf7, 0x16, 0x84, 0xb0, 0xae, 0x53, 0xdf, 0x8e, 0xb9, 0x87, 0x3e, 0x65, 0xa7, 0x16, 0xec, 0x2f, 0x41, 0x74, 0x1f, 0x8b, 0x78, 0x16, 0xd2, 0xe1, 0x97, 0xd9, 0x76, 0xfd, 0x53, 0xa8, 0xee, 0x7f, 0x92, 0x4b, 0xf4, 0xbf, 0xd4, 0x10, 0x42, 0xe1, 0x64, 0x45, 0xe9, 0x06, 0x0b, 0x55, 0xa0, 0xb6, 0xdc, 0x16, 0xaa, 0xf3, 0x06, 0x44, 0x91, 0xd1, 0x89, 0x28, 0x22, 0x39, 0x50, 0x39, 0x33, 0x28, 0xc1, 0x47, 0xdb, 0xd0, 0x35, 0x31, 0xec, 0x01, 0x2d, 0x8c, 0x52, 0x75, 0x02, 0xe7, 0xeb, 0x3d, 0xca, 0x50, 0x9b, 0x7d, 0xe1, 0x69, 0x95, 0x92, 0x46, 0x07, 0xc8, 0xb2, 0x8a, 0x2b, 0xda, 0x9b, 0xcb, 0x2c, 0x77, 0x81, 0x46, 0x1c, 0x76, 0x66, 0x3b, 0x88, 0x7b, 0x96, 0x43, 0xe2, 0x31, 0x7f, 0x0e, 0xa1, 0xd1, 0xbb, 0x14 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.18", + /* Message */ + 62, + { 0x0a, 0x2e, 0x24, 0x13, 0x0e, 0x8a, 0x9d, 0x28, 0xdf, 0xcb, 0x9d, 0xf9, 0x76, 0x5f, 0x46, 0x83, 0xe9, 0xda, 0x78, 0x42, 0x5a, 0x28, 0x19, 0x98, 0x06, 0xa9, 0x3b, 0x32, 0x2e, 0xfa, 0x88, 0x49, 0x3a, 0xc3, 0x72, 0x52, 0xc2, 0x9a, 0x26, 0x4f, 0x3e, 0x85, 0xae, 0x56, 0x53, 0x8e, 0x80, 0x8d, 0xc5, 0x56, 0x42, 0xa4, 0x88, 0x5f, 0x05, 0x46, 0x40, 0xf6, 0x9c, 0x89, 0x81, 0xfe } +, + /* Seed */ + 64, + { 0x20, 0x43, 0x1e, 0xf3, 0x1f, 0xce, 0x19, 0x93, 0x9d, 0xa5, 0x45, 0xa0, 0x85, 0x30, 0x11, 0x2d, 0xb0, 0xfa, 0x07, 0x13, 0x8d, 0xd8, 0x6d, 0xb1, 0xcc, 0x65, 0xe2, 0xb0, 0x3f, 0xc2, 0xbe, 0x60, 0x7c, 0x3e, 0x60, 0x38, 0xeb, 0xb7, 0x89, 0x17, 0x55, 0xb2, 0x31, 0x29, 0xfb, 0x96, 0x9a, 0x7f, 0xe1, 0x06, 0x10, 0xf2, 0xeb, 0xc3, 0xf0, 0x77, 0xb2, 0xc8, 0xf4, 0x60, 0x1e, 0x09, 0xab, 0x4c } +, + /* Encryption */ + 129, + { 0x0c, 0x14, 0xb7, 0xd3, 0x2d, 0x3d, 0x4c, 0xe2, 0xb0, 0x8e, 0xe4, 0x4f, 0x51, 0x6a, 0xee, 0x29, 0x90, 0xb6, 0x30, 0x52, 0x40, 0xb2, 0x5d, 0x23, 0x34, 0xaa, 0x31, 0x75, 0x2a, 0xef, 0x28, 0x02, 0x16, 0x39, 0xf7, 0x6a, 0x4c, 0x47, 0x19, 0x56, 0x9b, 0x30, 0x05, 0x2d, 0x4b, 0xd0, 0x8b, 0x3a, 0x07, 0xf2, 0x3b, 0xe6, 0x86, 0x23, 0x7e, 0x48, 0x1e, 0x67, 0xbf, 0x3f, 0x5a, 0x01, 0xad, 0xd7, 0x56, 0xda, 0x77, 0x2c, 0x7d, 0xc1, 0x3d, 0x32, 0x29, 0x8b, 0x9b, 0xbc, 0x3d, 0x33, 0xe6, 0xdf, 0x82, 0xd8, 0x5c, 0x08, 0x9d, 0x34, 0x76, 0x00, 0x49, 0x7a, 0x8b, 0x8e, 0xa4, 0xde, 0x68, 0xab, 0xb9, 0x0e, 0x5c, 0x6a, 0xeb, 0x26, 0x9a, 0x97, 0xbe, 0x42, 0x6c, 0xef, 0xac, 0xde, 0xbb, 0xcc, 0x0c, 0x1f, 0x2c, 0x40, 0x9b, 0xbc, 0x7c, 0x72, 0xd9, 0x0b, 0xdb, 0x42, 0x6b, 0x13, 0xcc, 0xc1, 0x9a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.19", + /* Message */ + 63, + { 0x7e, 0xfc, 0x62, 0x7b, 0xa5, 0xfa, 0x28, 0x25, 0xaa, 0xe0, 0xca, 0x94, 0x03, 0x0e, 0x70, 0x47, 0x08, 0xd3, 0x5f, 0x92, 0x23, 0x98, 0x26, 0xb4, 0x2e, 0x2d, 0x4d, 0xbb, 0xe4, 0x02, 0xab, 0x7d, 0x19, 0x6a, 0x7f, 0x54, 0x88, 0x0c, 0xf2, 0xc5, 0xa4, 0xd0, 0xfc, 0xe5, 0x3a, 0x20, 0xa3, 0x2b, 0x68, 0x30, 0xe6, 0x2d, 0xcd, 0x00, 0xdb, 0xcb, 0xf3, 0x3b, 0x5c, 0x0c, 0x70, 0x44, 0x01 } +, + /* Seed */ + 63, + { 0xf0, 0x49, 0x79, 0x19, 0xc1, 0x42, 0xf3, 0xa9, 0x8e, 0xf5, 0x5b, 0xcd, 0x59, 0x88, 0x23, 0x4f, 0xdc, 0x8a, 0xeb, 0xf7, 0x36, 0xd4, 0x7a, 0xf9, 0x70, 0x90, 0xa7, 0xa9, 0xdd, 0xe0, 0xa7, 0x35, 0x09, 0xf9, 0xcd, 0x41, 0x36, 0x26, 0xbb, 0x8b, 0xa7, 0x67, 0xc9, 0xd6, 0x38, 0x49, 0x1c, 0x28, 0x6e, 0x67, 0xbf, 0x22, 0xd6, 0x70, 0xd5, 0x6b, 0x24, 0xc1, 0x5b, 0xad, 0x70, 0x35, 0x1e } +, + /* Encryption */ + 129, + { 0x01, 0xdb, 0xce, 0x3b, 0x3f, 0x84, 0xb2, 0xda, 0x06, 0xb1, 0x67, 0xe2, 0x06, 0x64, 0x9d, 0x42, 0x4a, 0x42, 0xb8, 0xe9, 0xea, 0x54, 0x53, 0xa1, 0x6b, 0x5f, 0xc6, 0xc2, 0xe9, 0xcb, 0x17, 0xed, 0xa1, 0xef, 0xfe, 0x4e, 0x78, 0x36, 0xa5, 0xe5, 0x8f, 0x99, 0xe5, 0x31, 0x53, 0x0b, 0x40, 0x17, 0x1e, 0x4b, 0x51, 0xfc, 0x0b, 0x92, 0xde, 0x30, 0x31, 0x30, 0x09, 0x36, 0xd2, 0x59, 0x5e, 0x39, 0x10, 0x09, 0xe2, 0xe5, 0x3c, 0x32, 0xf7, 0x59, 0x60, 0x4a, 0x6d, 0xba, 0xd9, 0xc9, 0x70, 0x90, 0x0f, 0xa6, 0xe4, 0x1a, 0x35, 0x08, 0x3f, 0x78, 0x7b, 0x9b, 0xf3, 0xbe, 0xbc, 0xea, 0xa1, 0xa7, 0x71, 0x84, 0x1b, 0x5e, 0x6e, 0x4c, 0x8b, 0x50, 0x96, 0x29, 0x00, 0x7b, 0x46, 0x7e, 0x3c, 0xec, 0x8a, 0x1d, 0x03, 0x23, 0xc3, 0xc5, 0xdb, 0xc3, 0x4d, 0x8d, 0x41, 0x25, 0xa3, 0x98, 0xc9, 0xd5, 0x3d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 11.20", + /* Message */ + 15, + { 0x59, 0x3d, 0x3f, 0xcd, 0x05, 0xac, 0xee, 0x30, 0x29, 0x81, 0x5e, 0x1e, 0x76, 0xa8, 0x90 } +, + /* Seed */ + 111, + { 0x12, 0x35, 0xee, 0x3e, 0x7a, 0x9d, 0xf5, 0x96, 0x7f, 0xe9, 0x8d, 0x97, 0x10, 0xff, 0xdd, 0x5f, 0x7e, 0xb2, 0x2d, 0xc0, 0x71, 0x47, 0xaf, 0x43, 0x6f, 0xe2, 0x0a, 0xa5, 0x26, 0xbf, 0x0b, 0x94, 0x19, 0x0c, 0xab, 0xb5, 0x21, 0x3d, 0xe9, 0x8a, 0x23, 0xf5, 0xef, 0x27, 0x50, 0x22, 0xa2, 0xf7, 0x3e, 0x60, 0xe9, 0xef, 0xe2, 0xc0, 0x34, 0xc5, 0x5c, 0xeb, 0x26, 0xaa, 0x80, 0x6c, 0xde, 0xd6, 0x73, 0x9d, 0xdb, 0x2c, 0xbd, 0x3e, 0xc3, 0xb5, 0x55, 0x20, 0x4a, 0x79, 0x84, 0x65, 0xc3, 0x7c, 0x67, 0x57, 0x19, 0x56, 0x86, 0xa3, 0xea, 0x3c, 0x56, 0x57, 0xc3, 0x60, 0xa0, 0x15, 0x8d, 0x99, 0x2d, 0x4f, 0xeb, 0xfa, 0x04, 0x29, 0xee, 0xb7, 0xc9, 0x2a, 0x46, 0x84, 0x34, 0xc5, 0xb7 } +, + /* Encryption */ + 129, + { 0x0f, 0x69, 0x98, 0x81, 0xa1, 0x52, 0x46, 0x18, 0xbc, 0x25, 0xd4, 0xe5, 0x14, 0xe2, 0x07, 0x30, 0x68, 0xea, 0x7d, 0x35, 0x38, 0x4b, 0xaf, 0xd4, 0x6f, 0xc2, 0x82, 0xe1, 0xd8, 0x55, 0x11, 0x9e, 0xe9, 0x69, 0xf2, 0x11, 0xc7, 0x18, 0x4a, 0x07, 0x03, 0x06, 0x47, 0xfc, 0x40, 0x99, 0x0e, 0xcf, 0x2e, 0xa4, 0x05, 0x22, 0x86, 0x5d, 0x91, 0x77, 0x8a, 0x62, 0x7e, 0xca, 0x8e, 0x50, 0xc2, 0xbb, 0x97, 0x60, 0xb0, 0x45, 0xda, 0xaf, 0x12, 0x77, 0xa4, 0xfa, 0x98, 0x35, 0x76, 0xca, 0x8c, 0xfa, 0xd7, 0x60, 0x83, 0x29, 0xc1, 0x88, 0x15, 0x88, 0x01, 0x7d, 0x63, 0x72, 0x2b, 0x70, 0xe9, 0x8b, 0xe5, 0x24, 0xe0, 0x03, 0x39, 0x95, 0x98, 0x25, 0x73, 0xd3, 0x38, 0x70, 0x78, 0xc8, 0xb7, 0xc1, 0xc5, 0xf9, 0xae, 0xf2, 0x64, 0xa0, 0x48, 0x46, 0x84, 0xb3, 0x42, 0x66, 0x43, 0x73, 0x7d, 0x34, 0xbb } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 12: A 1030-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x26, 0x1f, 0xe0, 0x28, 0x44, 0x59, 0xc2, 0xfa, 0x6f, 0x05, 0x54, 0x6b, 0xed, 0x58, 0x5e, 0x1e, 0xe0, 0xa1, 0x30, 0xb7, 0x1c, 0x2b, 0x8a, 0x6f, 0xbb, 0x3b, 0xdc, 0x75, 0x78, 0x7b, 0x26, 0x55, 0xd0, 0xed, 0x4e, 0x32, 0x5b, 0x54, 0xc7, 0xb3, 0x71, 0xa6, 0xfc, 0xf2, 0xb6, 0x78, 0x82, 0x77, 0xa5, 0x0d, 0x47, 0x05, 0xba, 0x23, 0xc5, 0x96, 0x28, 0x5d, 0xa7, 0xe3, 0xc9, 0x30, 0x4a, 0x41, 0xe7, 0xcc, 0x48, 0x8b, 0x44, 0x92, 0x2f, 0x7b, 0xe2, 0xb4, 0x7c, 0x16, 0x31, 0x9e, 0x33, 0x74, 0x51, 0x17, 0x3d, 0x40, 0xb1, 0xea, 0x48, 0x1d, 0x1a, 0x9c, 0x11, 0x29, 0xb1, 0xfe, 0xb7, 0xd0, 0x9f, 0x67, 0x49, 0x7a, 0xeb, 0x98, 0x94, 0x8f, 0x1a, 0xbf, 0x3b, 0x77, 0x86, 0xbd, 0x3b, 0x87, 0x04, 0x71, 0x87, 0xc8, 0xf3, 0x70, 0x15, 0x68, 0x2b, 0x3f, 0x2d, 0xe5, 0x0e, 0x07, 0x8e, 0x8d, 0x0f } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x05, 0xdf, 0x76, 0x83, 0x72, 0xcc, 0x0a, 0x64, 0xd3, 0xc2, 0x14, 0x18, 0x30, 0x24, 0x23, 0x13, 0x9f, 0x47, 0x95, 0x73, 0xe5, 0x0b, 0x5c, 0x09, 0xb6, 0xe3, 0xbe, 0x23, 0xfb, 0xc9, 0xaa, 0x1a, 0x76, 0xd3, 0x27, 0x99, 0xa0, 0x47, 0x76, 0x1f, 0xfc, 0x21, 0x07, 0x94, 0x48, 0x17, 0x01, 0x04, 0xcc, 0xa5, 0xe2, 0xa1, 0x4c, 0xe4, 0x57, 0xd0, 0x0d, 0x80, 0x7d, 0x42, 0xc7, 0x6a, 0x55, 0xf6, 0x16, 0x87, 0x4b, 0xa7, 0xf7, 0xea, 0xa1, 0xce, 0x63, 0xcb, 0xf1, 0x32, 0xde, 0xb0, 0x81, 0xaa, 0xd2, 0xfd, 0x80, 0xd1, 0x24, 0xc4, 0xda, 0x86, 0xec, 0x6c, 0x02, 0x0e, 0x8c, 0xa8, 0x2d, 0xcd, 0xcd, 0x35, 0x54, 0xe6, 0x9b, 0xb1, 0x98, 0x72, 0x26, 0x2a, 0x50, 0x31, 0xab, 0x5d, 0xb7, 0xcc, 0x8c, 0x92, 0x59, 0xa1, 0x46, 0xd5, 0x8b, 0x1d, 0xb9, 0x4c, 0xc7, 0xe7, 0x56, 0x25, 0x3d, 0x5a, 0xa1 } +, + /* Prime 1 */ + 65, + { 0x06, 0x77, 0x25, 0xab, 0x55, 0x34, 0x18, 0xe1, 0xeb, 0x8a, 0x41, 0xf4, 0xfd, 0x92, 0xd2, 0x80, 0xb6, 0x9f, 0x85, 0xb0, 0x8c, 0xb4, 0x02, 0xf0, 0x1a, 0xa4, 0x96, 0x92, 0xc7, 0x20, 0x9b, 0x36, 0x42, 0x98, 0xee, 0xf4, 0xe3, 0x3d, 0xc4, 0x22, 0xbb, 0xa3, 0x35, 0x03, 0xd1, 0x1a, 0x12, 0x7d, 0xd2, 0x86, 0x43, 0xf7, 0xe7, 0x75, 0x58, 0x97, 0xe2, 0xeb, 0x96, 0xc4, 0xdd, 0xbb, 0x91, 0x12, 0xf1 } +, + /* Prime 2 */ + 65, + { 0x05, 0xe5, 0x8c, 0xeb, 0xd4, 0x7d, 0x87, 0xb1, 0xe7, 0x8d, 0xa2, 0xfe, 0xee, 0x6d, 0xc5, 0xf9, 0xbf, 0xa2, 0x20, 0xc3, 0x55, 0xe8, 0x20, 0xc8, 0xfb, 0xaa, 0x88, 0x46, 0xdf, 0x11, 0x00, 0x36, 0x2c, 0xd1, 0x69, 0x1f, 0x5c, 0xbf, 0x5c, 0x78, 0x68, 0xc4, 0x72, 0xd0, 0x28, 0x2a, 0xbe, 0x01, 0x03, 0x16, 0x1f, 0x4d, 0x8c, 0x62, 0xaf, 0xf3, 0x5b, 0xb1, 0xfb, 0x7c, 0xc6, 0x99, 0xd9, 0x9f, 0xff } +, + /* Prime exponent 1 */ + 65, + { 0x01, 0x6c, 0xc9, 0x14, 0x95, 0xd6, 0xc1, 0x95, 0x29, 0x40, 0x73, 0x80, 0xf7, 0x52, 0x20, 0xaa, 0xd5, 0x95, 0x1a, 0xf5, 0xea, 0x4c, 0xd2, 0x48, 0xf0, 0xd6, 0x4d, 0x89, 0x53, 0xf1, 0xcf, 0xc3, 0x89, 0xb2, 0x03, 0x18, 0x5d, 0xed, 0x03, 0x09, 0x54, 0xa9, 0x87, 0xc9, 0xab, 0x90, 0x3f, 0x7b, 0x13, 0xa7, 0x1b, 0xdb, 0xcb, 0x5b, 0x85, 0x87, 0x14, 0x30, 0x30, 0x2e, 0x7b, 0x60, 0x17, 0x7d, 0x41 } +, + /* Prime exponent 2 */ + 64, + { 0xf9, 0xcc, 0x89, 0x15, 0xff, 0xb3, 0xdd, 0xc7, 0xc0, 0x93, 0x71, 0x76, 0x49, 0x2a, 0x12, 0xbb, 0x18, 0x7c, 0x2d, 0x76, 0xe0, 0xd3, 0xd4, 0x0e, 0x79, 0x58, 0xd5, 0xc9, 0x82, 0x09, 0xb3, 0xed, 0x54, 0xb5, 0xfd, 0x9f, 0x9e, 0x77, 0x11, 0xe1, 0xdc, 0x68, 0x57, 0x73, 0xde, 0x26, 0xd5, 0x0a, 0x0a, 0xb6, 0x21, 0x62, 0x12, 0xce, 0xa5, 0x09, 0xce, 0x79, 0x1c, 0x5b, 0xcd, 0x07, 0xcb, 0x47 } +, + /* Coefficient */ + 65, + { 0x05, 0xfe, 0x93, 0x3b, 0x87, 0x3f, 0x1d, 0x68, 0xf6, 0xbe, 0x2d, 0x4d, 0x5a, 0xa2, 0x2d, 0x96, 0x8f, 0x2b, 0x7a, 0xf5, 0x41, 0xa2, 0xdc, 0xd6, 0x4e, 0x09, 0xc0, 0x30, 0xb1, 0x50, 0x35, 0x8a, 0x98, 0x02, 0xae, 0x86, 0x59, 0x95, 0xd7, 0x6a, 0x50, 0x03, 0x7d, 0x19, 0x8d, 0x7e, 0x70, 0x4d, 0x26, 0x84, 0x7a, 0xda, 0x8a, 0xe3, 0xd3, 0x85, 0xc2, 0x96, 0x5f, 0xb1, 0x7f, 0xcf, 0x15, 0x2f, 0x77 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 12.1", + /* Message */ + 20, + { 0x7d, 0xe6, 0x9c, 0xd9, 0x22, 0x8b, 0xbc, 0xfb, 0x9a, 0x8c, 0xa8, 0xc6, 0xc3, 0xef, 0xaf, 0x05, 0x6f, 0xe4, 0xa7, 0xf4 } +, + /* Seed */ + 106, + { 0x33, 0xd6, 0x2c, 0xd6, 0x67, 0x82, 0x3f, 0xbf, 0x13, 0xd5, 0x92, 0xae, 0x4d, 0x02, 0xa2, 0x37, 0x0d, 0x1d, 0x99, 0xdb, 0x06, 0xc7, 0x25, 0x42, 0x5e, 0x0d, 0x12, 0xfc, 0xb4, 0x83, 0x4e, 0xf9, 0xe5, 0x49, 0x9d, 0x60, 0x7e, 0x8a, 0xae, 0xfe, 0xba, 0x81, 0x96, 0x49, 0xfb, 0x3d, 0x61, 0xc7, 0x05, 0xf5, 0xe9, 0xa3, 0xa2, 0xf8, 0x96, 0x27, 0x61, 0x89, 0xa3, 0x20, 0x0d, 0x2f, 0xaf, 0xf7, 0x76, 0x79, 0xe0, 0x56, 0x34, 0x9a, 0x5b, 0x9b, 0x7b, 0x44, 0x49, 0xb6, 0x75, 0xcd, 0x48, 0xb6, 0x98, 0x09, 0x32, 0xc2, 0xcf, 0xc4, 0x6b, 0xf8, 0x9a, 0x77, 0x34, 0xf6, 0x8d, 0xd9, 0xf4, 0xfe, 0x77, 0xe1, 0xd9, 0xcf, 0x1f, 0x31, 0xb2, 0x1c, 0x4c, 0x61 } +, + /* Encryption */ + 129, + { 0x04, 0xca, 0xef, 0xfc, 0xd5, 0x1c, 0x3f, 0xc9, 0x23, 0x63, 0x46, 0x77, 0x4d, 0xa0, 0xcf, 0xa7, 0x7e, 0x9e, 0x64, 0x65, 0xf6, 0x43, 0x7f, 0xf4, 0x6d, 0x9f, 0xa4, 0x58, 0xb3, 0x62, 0x34, 0x12, 0xc3, 0x10, 0x30, 0x09, 0xfb, 0xfe, 0x20, 0x31, 0x96, 0xdf, 0x72, 0x96, 0x26, 0xe0, 0xee, 0x3a, 0xfb, 0x6b, 0x10, 0xa5, 0xac, 0xd7, 0x2e, 0x84, 0x28, 0x1d, 0x9d, 0x9b, 0xcb, 0xa3, 0xe0, 0xef, 0x77, 0xdd, 0x84, 0xf3, 0xdb, 0x19, 0x2d, 0x31, 0xb5, 0xb6, 0x66, 0xf7, 0x6c, 0x93, 0x81, 0x06, 0x81, 0x37, 0x3b, 0xaa, 0x58, 0xe6, 0xda, 0xdb, 0x01, 0xfa, 0x5c, 0x65, 0xec, 0x89, 0xfa, 0x51, 0xcc, 0x24, 0x74, 0x61, 0x1b, 0x9a, 0x7c, 0xb0, 0x0e, 0x86, 0x2f, 0xd3, 0xd4, 0x9b, 0x1c, 0xd3, 0x1a, 0xfc, 0x2d, 0xb4, 0x49, 0xe0, 0x9d, 0xae, 0x2d, 0x0a, 0x7d, 0x4d, 0xf0, 0xbc, 0x32, 0x0b, 0x5a } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 12.2", + /* Message */ + 47, + { 0x97, 0xee, 0xa8, 0x56, 0xa9, 0xbd, 0xbc, 0x71, 0x4e, 0xb3, 0xac, 0x22, 0xf6, 0xeb, 0x32, 0x71, 0x96, 0x69, 0xc4, 0x2f, 0x94, 0x30, 0xc5, 0x89, 0x50, 0xc6, 0x4c, 0x0d, 0xab, 0xff, 0x3a, 0x9e, 0x20, 0x43, 0x41, 0x6c, 0x67, 0xca, 0xaa, 0xab, 0x7c, 0x68, 0xcc, 0xb3, 0xca, 0x99, 0xa3 } +, + /* Seed */ + 79, + { 0x9f, 0x14, 0x12, 0x61, 0xce, 0xc4, 0xf2, 0xc5, 0x2f, 0x96, 0x91, 0x25, 0xa3, 0x6f, 0x14, 0x10, 0x27, 0x08, 0x82, 0x50, 0xd3, 0x6b, 0x17, 0x42, 0x1c, 0xd0, 0x96, 0x14, 0x76, 0x19, 0x06, 0x46, 0x8a, 0xfa, 0xb7, 0x62, 0x2c, 0x0d, 0x02, 0x19, 0x36, 0x91, 0x74, 0x47, 0x91, 0xe0, 0xd3, 0x5b, 0x6b, 0xc9, 0xf3, 0x37, 0x7e, 0x10, 0xb2, 0x85, 0x6c, 0x8e, 0xd9, 0x19, 0x9c, 0x89, 0xf4, 0xa4, 0x16, 0x13, 0xd3, 0xc4, 0x0c, 0xca, 0x37, 0x3a, 0x7c, 0xc6, 0x3c, 0x52, 0x60, 0xfe, 0x5a } +, + /* Encryption */ + 129, + { 0x0d, 0x26, 0xa0, 0x5d, 0xe9, 0x3b, 0x70, 0x7b, 0x85, 0x40, 0xfd, 0xc1, 0x98, 0x89, 0xd2, 0xd1, 0xe7, 0x93, 0x71, 0x57, 0xd3, 0x2d, 0x30, 0x3c, 0x52, 0x8d, 0xe3, 0x5e, 0x55, 0x3f, 0x94, 0x20, 0x28, 0x74, 0x4a, 0xf6, 0xa0, 0x40, 0x2e, 0xca, 0x0f, 0xcf, 0x5a, 0x85, 0x26, 0x1a, 0xd4, 0x75, 0xd8, 0x71, 0x0c, 0xc9, 0xf8, 0xb1, 0x1b, 0xa2, 0xc6, 0xda, 0xf1, 0xd6, 0x72, 0x69, 0x0c, 0x68, 0xed, 0x11, 0xe0, 0x35, 0xe9, 0xc6, 0x60, 0xec, 0xe1, 0xd8, 0x0c, 0xda, 0xb8, 0x00, 0xea, 0xd3, 0xc6, 0xe0, 0x78, 0x61, 0x7a, 0x1b, 0x0d, 0x27, 0x3d, 0xed, 0xd8, 0xd6, 0x57, 0x49, 0x16, 0x6b, 0xd0, 0x77, 0x74, 0xfb, 0x4c, 0x14, 0x86, 0xaa, 0x8a, 0x0a, 0xdf, 0x59, 0x5d, 0xbc, 0x3d, 0x10, 0xff, 0xae, 0xf1, 0x83, 0x84, 0x98, 0xa6, 0x75, 0x55, 0xc7, 0x7b, 0x6e, 0xd9, 0x83, 0xd5, 0xb9, 0xde } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.3", + /* Message */ + 5, + { 0x8e, 0x3e, 0x77, 0x2f, 0x39 } +, + /* Seed */ + 121, + { 0x9e, 0xb7, 0x31, 0xfa, 0x6d, 0x8d, 0x5b, 0x75, 0x81, 0xf8, 0xfa, 0xd2, 0xc8, 0x22, 0x5b, 0xc9, 0x68, 0x34, 0xaf, 0x61, 0xdb, 0x3d, 0x40, 0x9d, 0xd5, 0x63, 0x04, 0xae, 0x23, 0xea, 0x62, 0x69, 0x63, 0xa4, 0xd8, 0x04, 0x40, 0xc2, 0x4e, 0x43, 0x1e, 0x41, 0x97, 0x60, 0x90, 0x3a, 0xc4, 0x4b, 0xfe, 0x41, 0xa7, 0x50, 0x81, 0xa5, 0x46, 0x2b, 0xae, 0x65, 0x47, 0xc0, 0xe7, 0xa0, 0x6e, 0x91, 0x60, 0xdf, 0x9c, 0x01, 0xfa, 0x6c, 0x53, 0x54, 0xc8, 0x33, 0x18, 0xdb, 0x65, 0x6d, 0xee, 0x0a, 0x43, 0x77, 0x87, 0xfa, 0x46, 0x39, 0x4e, 0x55, 0x2e, 0xa5, 0x33, 0x15, 0x59, 0xb4, 0x01, 0x7b, 0xb6, 0xa0, 0xe1, 0xd6, 0xfc, 0x8a, 0x65, 0xb4, 0x5d, 0xa0, 0xc4, 0x5d, 0x88, 0x95, 0x48, 0x61, 0xcd, 0x6e, 0x7a, 0x41, 0x7e, 0x03, 0x7b, 0x1b, 0x05 } +, + /* Encryption */ + 129, + { 0x24, 0x4a, 0x86, 0x34, 0x51, 0x9a, 0xf4, 0x9f, 0x56, 0x9b, 0x69, 0x86, 0xab, 0x47, 0x79, 0x64, 0xa6, 0xb2, 0x92, 0x0d, 0x84, 0x3a, 0x1d, 0x97, 0xef, 0xd7, 0xfe, 0xf8, 0x3e, 0x81, 0xba, 0xda, 0x4c, 0x4b, 0x56, 0x29, 0x61, 0xef, 0x4e, 0x1f, 0xc3, 0x33, 0x46, 0x4b, 0x92, 0x6b, 0xd7, 0x4b, 0x07, 0xad, 0x50, 0xc6, 0x5b, 0x68, 0x16, 0x83, 0xd3, 0x89, 0xfe, 0x41, 0xd6, 0xd2, 0x13, 0xb6, 0x46, 0x9f, 0x18, 0x2b, 0x14, 0xb4, 0x62, 0xd7, 0x2c, 0x1c, 0xe3, 0x92, 0x8c, 0xa8, 0x06, 0xd9, 0x66, 0xb5, 0x2d, 0x42, 0xd0, 0xbf, 0xd6, 0x0c, 0x9d, 0x04, 0x91, 0x4d, 0x50, 0x83, 0x7c, 0xda, 0xe0, 0x9b, 0x33, 0x0e, 0x37, 0x27, 0x44, 0xdc, 0xe1, 0x7f, 0x18, 0xe9, 0x4d, 0x71, 0x1c, 0x8b, 0x58, 0xea, 0x44, 0x9f, 0x14, 0x49, 0xd3, 0x69, 0xfa, 0xef, 0x51, 0x46, 0x83, 0xd3, 0x01, 0x60, 0x79 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.4", + /* Message */ + 20, + { 0xdc, 0xfa, 0xe7, 0x71, 0x8c, 0x24, 0x7c, 0x40, 0xf9, 0xa2, 0xa3, 0xc3, 0x53, 0x5c, 0x50, 0x92, 0x80, 0xc8, 0x73, 0xc3 } +, + /* Seed */ + 106, + { 0xb9, 0x3b, 0xbe, 0xa6, 0xc1, 0x85, 0x3f, 0x15, 0x3b, 0x5e, 0x01, 0xe7, 0xe4, 0xe5, 0xd0, 0xc6, 0x3d, 0x9d, 0xfb, 0x24, 0x5f, 0xc6, 0xcf, 0x64, 0x04, 0x3d, 0x7a, 0x92, 0x20, 0xb0, 0xb8, 0x1a, 0xc2, 0xaf, 0x65, 0x6b, 0x99, 0x71, 0x4b, 0xa4, 0x30, 0xe0, 0xa3, 0x96, 0x95, 0xd2, 0x5f, 0xf2, 0x69, 0xb0, 0xb9, 0xb8, 0x65, 0xfc, 0x4d, 0x4e, 0xee, 0x5e, 0x07, 0xa5, 0xb5, 0xbe, 0x35, 0x43, 0x82, 0xaa, 0xa4, 0x14, 0xbc, 0x62, 0x08, 0x54, 0x5c, 0x86, 0xce, 0x02, 0x38, 0x8c, 0x07, 0xb3, 0x76, 0xfb, 0x02, 0x98, 0xc3, 0x7d, 0x1a, 0xc3, 0x9e, 0xa1, 0x89, 0xb0, 0xad, 0xf7, 0x80, 0xf6, 0xe8, 0x30, 0xbc, 0xe9, 0x17, 0xb5, 0x0a, 0xdb, 0x7a, 0x31 } +, + /* Encryption */ + 129, + { 0x0c, 0x41, 0x20, 0x52, 0xd4, 0xef, 0x4a, 0xb5, 0x1b, 0x2f, 0x62, 0x37, 0x05, 0xf0, 0x7f, 0x41, 0xfa, 0xd6, 0x4d, 0xaf, 0xfd, 0xba, 0x62, 0x44, 0xef, 0xd4, 0x7f, 0x51, 0x9d, 0xe2, 0xe7, 0x1a, 0x01, 0xa6, 0xc5, 0x7d, 0x1f, 0x28, 0xb6, 0xbf, 0x7b, 0x5c, 0x8d, 0xbb, 0x9f, 0xe7, 0xb1, 0x49, 0xb0, 0xeb, 0xaa, 0x53, 0x59, 0x61, 0x99, 0x37, 0x6d, 0xf4, 0x90, 0x32, 0x3d, 0x25, 0xc2, 0x17, 0xbc, 0x71, 0xbe, 0x37, 0xf1, 0x81, 0x03, 0x5c, 0xf4, 0x57, 0xeb, 0x5c, 0x06, 0xd6, 0xa3, 0xde, 0xd3, 0xd6, 0x6d, 0x5b, 0x35, 0xf0, 0x61, 0x81, 0xbf, 0x94, 0xd0, 0xec, 0x13, 0xec, 0x44, 0x7c, 0x70, 0x82, 0x33, 0x49, 0x1c, 0x55, 0x4f, 0x9e, 0x99, 0x1f, 0x6b, 0xcb, 0x8b, 0x78, 0xd3, 0x3c, 0x9c, 0x36, 0x95, 0x5b, 0x8d, 0xce, 0x51, 0x79, 0xff, 0x8b, 0xc5, 0x92, 0x44, 0xf6, 0x67, 0x90, 0x87 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.5", + /* Message */ + 42, + { 0xd7, 0x1d, 0xd8, 0x7a, 0x13, 0x99, 0x1a, 0x0d, 0xa2, 0xc7, 0x4a, 0x58, 0xb0, 0x48, 0x56, 0x34, 0xb3, 0xe0, 0x4f, 0xec, 0x9e, 0x3f, 0x1c, 0xf2, 0x60, 0x4a, 0x93, 0xbe, 0xd7, 0x96, 0x96, 0xfa, 0x63, 0x78, 0xeb, 0x1b, 0xa0, 0xe5, 0xd2, 0x04, 0x70, 0xa4 } +, + /* Seed */ + 84, + { 0x09, 0x90, 0x59, 0x92, 0x58, 0xe9, 0x7a, 0x2e, 0xbf, 0xbe, 0x10, 0x97, 0x72, 0x25, 0xc4, 0x16, 0x76, 0x2e, 0x95, 0xd2, 0x55, 0x3a, 0x80, 0x1f, 0x72, 0x6c, 0xc2, 0x49, 0xbc, 0xdf, 0x32, 0x21, 0x32, 0x58, 0x57, 0x19, 0xfc, 0x12, 0x39, 0x9a, 0xcd, 0x72, 0x54, 0xae, 0x77, 0xda, 0x34, 0x3f, 0xe2, 0xa9, 0xa3, 0xac, 0xb1, 0x1c, 0x14, 0xe2, 0x14, 0xe2, 0xd8, 0x5a, 0x76, 0x70, 0x8c, 0x3e, 0x72, 0x17, 0x3d, 0xa5, 0xd9, 0x90, 0x58, 0xe0, 0xc8, 0x70, 0x9e, 0xdf, 0x28, 0xc3, 0x69, 0x38, 0x76, 0x9f, 0x1f, 0x22 } +, + /* Encryption */ + 129, + { 0x0f, 0xf9, 0xcc, 0xe7, 0xb6, 0x9d, 0x7f, 0xca, 0x48, 0xd7, 0xc4, 0xf6, 0xcc, 0xff, 0x24, 0x8c, 0x3d, 0xb8, 0x8b, 0xf1, 0xb7, 0x85, 0x2c, 0xd9, 0xd8, 0x52, 0x5c, 0x3b, 0x41, 0xe4, 0x4a, 0x9b, 0x54, 0x0f, 0x20, 0x8f, 0xfb, 0xb8, 0xc8, 0x5b, 0xfa, 0x89, 0x0a, 0xc0, 0x2e, 0x99, 0x49, 0x59, 0xd6, 0xb0, 0x7f, 0x64, 0x81, 0x40, 0x78, 0x55, 0x6f, 0x8e, 0xc6, 0x0d, 0xb3, 0x57, 0xac, 0xea, 0xf8, 0x39, 0x11, 0x5f, 0xad, 0x41, 0xf8, 0x91, 0x8d, 0x69, 0xc2, 0x1a, 0x3a, 0xff, 0xef, 0x6e, 0xb1, 0x4a, 0x5d, 0x2c, 0xd0, 0x64, 0x5c, 0xd7, 0x06, 0xb5, 0x81, 0x43, 0x39, 0x4a, 0x27, 0x35, 0x36, 0x82, 0xe3, 0xba, 0xa1, 0x98, 0x00, 0x2e, 0x16, 0x80, 0xf2, 0x8f, 0x34, 0xbe, 0x08, 0x9a, 0x57, 0x84, 0xac, 0xe5, 0xca, 0x6b, 0x11, 0x08, 0x99, 0xdf, 0xb9, 0x58, 0x2f, 0x2e, 0x4b, 0x2a, 0x40 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.6", + /* Message */ + 58, + { 0x5e, 0x4b, 0x15, 0x8f, 0x8d, 0xcb, 0xcd, 0xd7, 0xe3, 0x08, 0x38, 0x5b, 0x40, 0x19, 0x0f, 0x5d, 0xef, 0x8c, 0xf3, 0x30, 0x5f, 0xc4, 0x9d, 0xe6, 0x3c, 0x9e, 0x35, 0xb4, 0x02, 0x36, 0xae, 0xe1, 0xf4, 0x56, 0x20, 0x5a, 0x52, 0x67, 0xa2, 0xaa, 0x7d, 0x88, 0xcb, 0x2c, 0x11, 0xaf, 0x7f, 0x28, 0x99, 0xd0, 0x1d, 0xa1, 0xb2, 0xc7, 0x46, 0x6f, 0xfe, 0xf7 } +, + /* Seed */ + 68, + { 0xa5, 0x22, 0xf9, 0x80, 0x8d, 0x9c, 0x01, 0xd8, 0xff, 0x79, 0x77, 0x5f, 0x7b, 0x22, 0x09, 0x8f, 0xc5, 0xfe, 0x32, 0x54, 0xe1, 0xb0, 0x4e, 0xb1, 0xcb, 0x85, 0x0e, 0x10, 0xe2, 0xc5, 0x06, 0x5e, 0x23, 0x27, 0x4d, 0xc0, 0xa0, 0x55, 0x87, 0x43, 0x6d, 0xa3, 0x75, 0x59, 0x33, 0x5f, 0xe7, 0x09, 0x3f, 0xa5, 0xe7, 0xa2, 0xa9, 0xc9, 0xa4, 0xdc, 0xaf, 0x23, 0x51, 0x79, 0xd0, 0xe9, 0x8f, 0xa3, 0x3e, 0x34, 0xb6, 0x16 } +, + /* Encryption */ + 129, + { 0x1c, 0x0e, 0x86, 0xa6, 0x36, 0x6b, 0xeb, 0x1e, 0x12, 0xd6, 0xbc, 0xfa, 0x6a, 0xd4, 0x94, 0x06, 0xc8, 0xb7, 0xe4, 0x8d, 0x1d, 0x5b, 0xe4, 0x5c, 0xbd, 0x83, 0x19, 0x49, 0x87, 0x49, 0x6f, 0xaa, 0x3e, 0x21, 0x92, 0x7e, 0xc6, 0x62, 0xf5, 0x02, 0xac, 0x3f, 0x91, 0xa4, 0xb4, 0xb9, 0x1d, 0x16, 0x0c, 0x19, 0x86, 0xa5, 0xed, 0x09, 0x27, 0x66, 0x88, 0x3b, 0x85, 0x55, 0xe3, 0xc9, 0x31, 0x4b, 0x44, 0xba, 0x33, 0x83, 0xdb, 0x28, 0x74, 0x23, 0xaf, 0x91, 0xb4, 0x13, 0x91, 0x8c, 0x08, 0x02, 0xc7, 0x77, 0x8e, 0x46, 0xc2, 0x96, 0xdc, 0x9f, 0x04, 0xcd, 0xb8, 0xb0, 0x6a, 0xdc, 0x7c, 0x53, 0xd8, 0x59, 0xf4, 0x42, 0xcc, 0xbd, 0x5f, 0xfa, 0xb5, 0xaf, 0x75, 0x2b, 0x97, 0x9b, 0xf5, 0x23, 0xa4, 0x0a, 0x1d, 0x08, 0xd7, 0x60, 0x63, 0xff, 0xb3, 0xd5, 0xcf, 0xc8, 0x2f, 0x15, 0xeb, 0xd6, 0xd4 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.7", + /* Message */ + 58, + { 0x35, 0x9b, 0xa5, 0x07, 0x56, 0xa8, 0x03, 0x30, 0x40, 0x9d, 0x3f, 0x23, 0x6a, 0x34, 0x0b, 0x90, 0xf4, 0x2f, 0x73, 0x2a, 0x87, 0x71, 0x1f, 0xe2, 0x23, 0x52, 0xd4, 0xc8, 0x25, 0x0d, 0x45, 0x47, 0x5e, 0x32, 0xb9, 0x58, 0x83, 0xe1, 0x60, 0x97, 0x55, 0xa1, 0x3c, 0xdf, 0xc1, 0xbf, 0x39, 0x4c, 0x5c, 0x67, 0x36, 0x9e, 0xca, 0x1f, 0x9a, 0x33, 0xe8, 0xba } +, + /* Seed */ + 68, + { 0xf9, 0xeb, 0xdd, 0xac, 0x9d, 0xe1, 0x70, 0x9a, 0x06, 0xbf, 0x6b, 0xbd, 0xdf, 0x58, 0x94, 0xe2, 0x3b, 0x96, 0x2b, 0xa0, 0xc0, 0x64, 0xbf, 0xcd, 0x7c, 0xc5, 0x76, 0x60, 0x3b, 0x0a, 0x1a, 0x1f, 0xf3, 0x5d, 0x64, 0x5e, 0xe8, 0x7a, 0xc6, 0xf8, 0x21, 0xa6, 0xa1, 0x51, 0xe6, 0xbb, 0xb0, 0x5b, 0xf3, 0xe0, 0x5c, 0xd9, 0xa6, 0xe2, 0xcd, 0x9c, 0x6c, 0xf5, 0x53, 0xbf, 0xb0, 0x7b, 0xd2, 0xfd, 0xa0, 0x40, 0xdf, 0xb6 } +, + /* Encryption */ + 129, + { 0x08, 0x33, 0x60, 0xe6, 0x49, 0x05, 0x9d, 0x00, 0x65, 0x8d, 0xba, 0x21, 0xf2, 0xdf, 0x28, 0xa2, 0x76, 0x4c, 0x45, 0x89, 0xf7, 0xa7, 0x7d, 0x5a, 0xf9, 0x95, 0x79, 0xa8, 0xab, 0x44, 0x80, 0xc8, 0x26, 0xa7, 0x7c, 0x2f, 0xb7, 0x95, 0x4f, 0x4f, 0x31, 0xfe, 0x1d, 0x9e, 0xb1, 0xbf, 0x40, 0xe8, 0x09, 0x57, 0x7f, 0x39, 0x30, 0x1a, 0xd3, 0xab, 0x95, 0xb3, 0x81, 0x6c, 0x90, 0xec, 0x3f, 0x1c, 0xd6, 0x29, 0xc4, 0x39, 0x61, 0x74, 0xbe, 0xd9, 0xfe, 0x1e, 0x0f, 0x47, 0x68, 0x23, 0xe5, 0x3b, 0x41, 0xd1, 0x35, 0xb4, 0x9a, 0x02, 0xb0, 0x0e, 0xff, 0xc7, 0x61, 0xec, 0x90, 0x94, 0x23, 0xaf, 0x15, 0x85, 0x52, 0x37, 0xb7, 0x7e, 0xe0, 0x7d, 0xf2, 0x5a, 0xb4, 0xe8, 0x58, 0x46, 0x7d, 0x4c, 0xcf, 0xe8, 0x08, 0x43, 0x24, 0x1b, 0xbf, 0x88, 0xeb, 0x4f, 0x85, 0x3e, 0xf4, 0xb4, 0x3b, 0xa3, 0xac } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.8", + /* Message */ + 25, + { 0xa9, 0xf3, 0x9f, 0x8b, 0xa0, 0x64, 0x66, 0x25, 0x0c, 0x26, 0x5d, 0xf0, 0xca, 0x46, 0x57, 0x0a, 0x16, 0x01, 0x12, 0xcf, 0x38, 0xfd, 0x74, 0x59, 0x99 } +, + /* Seed */ + 101, + { 0x88, 0xb3, 0xc2, 0x8b, 0xd3, 0x99, 0x9a, 0x86, 0x0b, 0x8d, 0xe7, 0x75, 0x93, 0x5b, 0x8e, 0xd7, 0x8f, 0xa2, 0xf2, 0x7c, 0x26, 0x8b, 0x24, 0x3a, 0x02, 0x45, 0xaf, 0x86, 0x72, 0x25, 0x47, 0x19, 0xf2, 0x3a, 0x4b, 0x7f, 0xed, 0xc0, 0x0d, 0x54, 0xe1, 0x2e, 0x9d, 0x70, 0x1f, 0x64, 0x69, 0x94, 0x24, 0xb6, 0xb8, 0x7d, 0x14, 0xd9, 0x67, 0x6e, 0xfa, 0x95, 0x9b, 0xe2, 0x1a, 0x04, 0xb6, 0x43, 0x5d, 0x25, 0x10, 0x03, 0xdd, 0x15, 0x3d, 0x7d, 0x08, 0xff, 0x28, 0xd9, 0x3a, 0x93, 0x20, 0xdc, 0x1b, 0xbc, 0x3d, 0xb3, 0x97, 0xa5, 0x48, 0x94, 0xf2, 0x05, 0x79, 0xf9, 0x3e, 0x4e, 0xad, 0x65, 0xc3, 0x1a, 0x40, 0x7e, 0xb4 } +, + /* Encryption */ + 129, + { 0x19, 0x83, 0x96, 0x50, 0xb9, 0x25, 0xf1, 0xf9, 0x6d, 0x61, 0x1e, 0x4d, 0xbb, 0x91, 0x49, 0x93, 0x54, 0x5c, 0x67, 0x39, 0x0c, 0x32, 0x93, 0x5f, 0xbf, 0x82, 0x25, 0x9d, 0xad, 0x10, 0xf2, 0x37, 0x30, 0xeb, 0x48, 0xf3, 0x42, 0x00, 0x46, 0x5a, 0x20, 0x38, 0x72, 0x77, 0xe2, 0xb9, 0x61, 0xe0, 0x83, 0x18, 0xd2, 0x07, 0x74, 0x47, 0xc9, 0x10, 0x92, 0x71, 0xe4, 0xde, 0xd8, 0xff, 0x3d, 0xc4, 0xf3, 0x79, 0xee, 0xe4, 0x55, 0xae, 0x96, 0x08, 0x1a, 0x1a, 0xe2, 0x4b, 0x96, 0xca, 0x73, 0x0a, 0x62, 0xf7, 0xac, 0xc5, 0xa5, 0xea, 0x52, 0x28, 0xe3, 0xa4, 0x8e, 0xa6, 0x74, 0x1c, 0xb3, 0x0e, 0x82, 0x9d, 0x55, 0x09, 0xcc, 0xc6, 0xc2, 0x87, 0xc7, 0x29, 0x1f, 0x3a, 0x1d, 0x89, 0xd6, 0x26, 0xbc, 0x98, 0x15, 0x77, 0xde, 0x52, 0xa1, 0x1f, 0x12, 0xae, 0x21, 0x43, 0xd3, 0xb0, 0xb5, 0x2f, 0x86 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.9", + /* Message */ + 1, + { 0x68 } +, + /* Seed */ + 125, + { 0x53, 0x8b, 0x09, 0x5e, 0x4f, 0x2a, 0xd6, 0x77, 0x30, 0x68, 0x74, 0x21, 0x91, 0x52, 0x42, 0x25, 0x1d, 0x07, 0xf6, 0x61, 0xed, 0xac, 0x7f, 0xe7, 0x9e, 0x31, 0xd6, 0xc3, 0x45, 0xaf, 0xf5, 0x9d, 0xf3, 0x88, 0xc7, 0x18, 0x2f, 0xff, 0x0c, 0x04, 0x27, 0xb5, 0x99, 0x35, 0xc6, 0x91, 0xda, 0xb8, 0xbc, 0x42, 0xbe, 0x47, 0xd7, 0x69, 0x11, 0x88, 0x0d, 0x91, 0x7b, 0x86, 0x27, 0x18, 0xb4, 0xc1, 0xc1, 0x88, 0x8d, 0x42, 0x20, 0xb9, 0xf8, 0x23, 0x1a, 0xcd, 0xf1, 0x2d, 0x9b, 0x85, 0x18, 0x6b, 0xe0, 0x95, 0x0c, 0x1a, 0xff, 0x84, 0xcd, 0x0f, 0xe3, 0x65, 0x86, 0xa5, 0x0e, 0x7e, 0x04, 0xb1, 0x72, 0xca, 0x9c, 0x85, 0x9e, 0x2d, 0xed, 0x6b, 0x8e, 0xa5, 0x79, 0xdd, 0x5e, 0x6e, 0xee, 0x77, 0x2c, 0xca, 0xa6, 0xb4, 0xa5, 0xd8, 0xab, 0x17, 0x31, 0xa8, 0x35, 0xd6, 0xa8 } +, + /* Encryption */ + 129, + { 0x1e, 0x86, 0x8a, 0xdb, 0x0e, 0x65, 0x32, 0x80, 0x60, 0x4e, 0x8d, 0x3b, 0xc4, 0xd9, 0x69, 0x84, 0xa2, 0x0a, 0xa0, 0x9d, 0x48, 0x0b, 0x4d, 0xff, 0xac, 0x62, 0xba, 0x78, 0xcb, 0xb7, 0xee, 0xd0, 0x64, 0x5a, 0x6d, 0x94, 0xd9, 0xd2, 0xf2, 0xd1, 0xe9, 0x17, 0xc1, 0x46, 0xb4, 0x1f, 0xaa, 0x3d, 0x1d, 0x2c, 0x19, 0x01, 0x05, 0x36, 0x8f, 0xb4, 0x84, 0x06, 0xa1, 0xd2, 0x42, 0x6a, 0xf3, 0xdc, 0xc8, 0x5b, 0xd0, 0x2d, 0x5c, 0x26, 0xc8, 0x97, 0xcc, 0xb2, 0x2e, 0x57, 0x59, 0x12, 0x64, 0x1a, 0x18, 0x8e, 0xf4, 0xac, 0x47, 0xa0, 0xa9, 0xfe, 0x9a, 0xa2, 0x70, 0x6d, 0x8e, 0x10, 0x61, 0xf5, 0xd9, 0x30, 0x63, 0xf4, 0x90, 0x17, 0x00, 0x3b, 0x23, 0x09, 0xca, 0x7d, 0x8d, 0x36, 0x70, 0x3b, 0xfd, 0xda, 0x3f, 0x7f, 0x43, 0xdf, 0x15, 0x8a, 0x15, 0xbb, 0x22, 0x13, 0x9a, 0xae, 0x15, 0x10, 0x77 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.10", + /* Message */ + 23, + { 0x35, 0x65, 0x87, 0xe6, 0xc6, 0xc0, 0xb4, 0x6c, 0x24, 0x45, 0xe0, 0x18, 0x63, 0x52, 0x76, 0xab, 0x84, 0x5f, 0xd1, 0x07, 0x6d, 0x10, 0x7f } +, + /* Seed */ + 103, + { 0xe5, 0xd3, 0x3e, 0x4d, 0x93, 0xc7, 0x08, 0x44, 0xee, 0x4a, 0x01, 0x65, 0x56, 0x24, 0x2d, 0x08, 0xe8, 0xe6, 0x2f, 0x1a, 0x7f, 0x79, 0x47, 0x79, 0xe2, 0x23, 0xee, 0x9d, 0xfb, 0x23, 0x1c, 0x3a, 0x52, 0x0f, 0x29, 0x7e, 0x50, 0x73, 0xe4, 0xf9, 0x2f, 0x53, 0x5c, 0xf1, 0x44, 0x55, 0x7f, 0x94, 0xee, 0x1e, 0x1e, 0x5c, 0xc6, 0xbf, 0x4c, 0x0c, 0x0c, 0x8e, 0x5e, 0xd4, 0x0d, 0x06, 0x63, 0x56, 0x06, 0xf7, 0x54, 0xcc, 0x2d, 0xd8, 0x3f, 0xe0, 0x2c, 0x57, 0x6c, 0xcd, 0x2b, 0x83, 0x5f, 0xd0, 0xf5, 0x3a, 0x99, 0x08, 0x3f, 0x4d, 0x15, 0xbf, 0xe9, 0x26, 0x88, 0x99, 0xef, 0x09, 0xff, 0x5f, 0x2f, 0x3c, 0xec, 0x9f, 0x9b, 0x8a, 0x7e } +, + /* Encryption */ + 129, + { 0x15, 0xd3, 0x64, 0xa4, 0x49, 0x9b, 0x30, 0xa5, 0xf7, 0x8b, 0x6d, 0x7d, 0x4f, 0x66, 0x7a, 0x1f, 0x76, 0xd7, 0x15, 0x15, 0x8f, 0x28, 0x01, 0x19, 0xb0, 0x55, 0xe1, 0xf2, 0x66, 0x3f, 0xc7, 0x96, 0xe3, 0x3c, 0x0e, 0xb6, 0x4e, 0x34, 0xa8, 0xda, 0xda, 0x5c, 0x81, 0x75, 0x42, 0x57, 0xa8, 0xbd, 0xf0, 0xed, 0x81, 0x15, 0xf6, 0x07, 0xb7, 0xc9, 0xcc, 0xa4, 0x81, 0xf7, 0x45, 0x20, 0xb6, 0xd9, 0xac, 0x98, 0xf5, 0xe7, 0x2c, 0x2b, 0xaf, 0x3c, 0xbb, 0x6b, 0xd9, 0xba, 0xea, 0x5d, 0x75, 0x86, 0x0c, 0xbd, 0xae, 0x34, 0x03, 0xfd, 0x5c, 0x37, 0x96, 0x4a, 0xae, 0x64, 0x36, 0x6a, 0xb0, 0x9b, 0xc9, 0xc6, 0x72, 0x76, 0x95, 0x14, 0x48, 0x19, 0x3b, 0xb4, 0xb1, 0xaf, 0xa2, 0x70, 0x79, 0xc3, 0x41, 0x70, 0xa2, 0x69, 0x56, 0x51, 0x0d, 0x44, 0x27, 0x64, 0x22, 0x99, 0x08, 0x42, 0x0f, 0xe8, 0x0a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.11", + /* Message */ + 64, + { 0xe1, 0x53, 0x27, 0x6a, 0x68, 0x79, 0x67, 0x8f, 0xee, 0x19, 0x89, 0x48, 0x28, 0xd6, 0x26, 0x2e, 0xa3, 0x9a, 0xd0, 0x54, 0xc8, 0x9e, 0xdc, 0xb2, 0x3f, 0x72, 0xdc, 0xda, 0x1b, 0x00, 0x73, 0xc2, 0x87, 0x62, 0x02, 0x18, 0xd9, 0x2d, 0x0e, 0xb3, 0x0c, 0x62, 0xaf, 0xbf, 0x2b, 0x45, 0xdf, 0x62, 0xd0, 0x66, 0x65, 0xf8, 0x05, 0x25, 0xb6, 0x72, 0x7f, 0x95, 0xe3, 0x42, 0x29, 0xe6, 0x82, 0xa8 } +, + /* Seed */ + 62, + { 0x2a, 0xd7, 0x14, 0x2f, 0xcf, 0xa3, 0xbd, 0xbe, 0xb7, 0x55, 0xb2, 0xc5, 0xb5, 0xcf, 0x13, 0xe6, 0x96, 0x9e, 0xb7, 0x3b, 0x7a, 0x06, 0xbc, 0x29, 0xbc, 0xad, 0x7e, 0x75, 0x30, 0xa5, 0x90, 0x23, 0x0f, 0x6a, 0x43, 0xfc, 0x03, 0xd6, 0xc3, 0xa9, 0xc6, 0x41, 0xe5, 0x3a, 0x41, 0x77, 0xd5, 0x75, 0x02, 0x91, 0xec, 0x6d, 0x4b, 0x33, 0xf8, 0x71, 0x66, 0x8a, 0xd8, 0x56, 0x90, 0x77 } +, + /* Encryption */ + 129, + { 0x17, 0x8e, 0x49, 0x77, 0x0a, 0x4c, 0x8f, 0xfb, 0x7f, 0x65, 0xf3, 0x82, 0xcd, 0xb5, 0x76, 0xe6, 0x08, 0xe9, 0x75, 0xc4, 0x37, 0x13, 0x39, 0x10, 0x2b, 0x95, 0x2a, 0x1e, 0x71, 0xcb, 0xcb, 0x91, 0xfd, 0xcd, 0x0c, 0x0e, 0xd5, 0xa8, 0x5f, 0xbd, 0x26, 0x3d, 0xa6, 0xa7, 0x4e, 0x49, 0x1f, 0xb0, 0x4b, 0x60, 0xa5, 0x96, 0x1d, 0x8e, 0x6a, 0xc7, 0x24, 0xec, 0x8a, 0x81, 0x61, 0xc2, 0x2a, 0xe3, 0x10, 0x40, 0x7f, 0x59, 0xf7, 0xe6, 0x02, 0xda, 0x48, 0xaa, 0x2d, 0xad, 0x68, 0x3e, 0x88, 0xdb, 0x1d, 0x84, 0x29, 0x5e, 0x0f, 0xba, 0x5f, 0xf2, 0xf6, 0x73, 0xdf, 0x32, 0x85, 0x4d, 0x01, 0xb7, 0x1a, 0x89, 0x46, 0x0f, 0xf0, 0xe6, 0xe1, 0xbe, 0x98, 0xae, 0xbf, 0xa2, 0x27, 0xe3, 0x97, 0xea, 0xcc, 0x8b, 0x23, 0x17, 0x41, 0x47, 0xc4, 0x4e, 0x16, 0x20, 0x1e, 0xc6, 0xba, 0xbd, 0x16, 0x5b, 0xa4 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.12", + /* Message */ + 15, + { 0xfa, 0x4e, 0xb9, 0x31, 0xa7, 0xe2, 0x09, 0x0f, 0x31, 0xed, 0xb1, 0xff, 0x7d, 0x83, 0x61 } +, + /* Seed */ + 111, + { 0x43, 0x7f, 0xa1, 0x51, 0xf4, 0x34, 0x05, 0xdb, 0x22, 0x42, 0x2c, 0xb3, 0x5d, 0x1c, 0x57, 0x61, 0x16, 0x1c, 0xb9, 0xa7, 0x8a, 0xbc, 0xb6, 0xf0, 0x6d, 0xc4, 0xe7, 0xa8, 0x69, 0x48, 0x1f, 0x40, 0xb2, 0x1a, 0xe1, 0xd3, 0x3e, 0x07, 0x5c, 0x48, 0x5c, 0xd8, 0x50, 0x1a, 0x3c, 0xaa, 0x60, 0x18, 0x32, 0x5b, 0x7f, 0x85, 0x0d, 0x4d, 0x8f, 0x6d, 0xcf, 0xd2, 0xaf, 0xfe, 0x19, 0xd3, 0xe6, 0xc7, 0x08, 0x74, 0xe7, 0x10, 0x11, 0x14, 0xf0, 0xfb, 0xb9, 0x82, 0x25, 0x81, 0xba, 0xe6, 0xba, 0x2b, 0xa1, 0xe7, 0x49, 0x88, 0x81, 0xa5, 0xdc, 0x5b, 0xb8, 0x85, 0x27, 0x38, 0xa8, 0x2f, 0xb0, 0x6d, 0x15, 0x27, 0xb4, 0x33, 0x44, 0x87, 0xb3, 0x24, 0x01, 0x3e, 0x32, 0xbc, 0xf1, 0x7b, 0xab } +, + /* Encryption */ + 129, + { 0x22, 0x6d, 0x77, 0x67, 0x00, 0xc5, 0xe1, 0xdd, 0xb9, 0x99, 0x4b, 0x32, 0x91, 0xf1, 0xd3, 0x34, 0xb6, 0x9d, 0xd8, 0x63, 0x06, 0x5f, 0xa8, 0x34, 0x21, 0xe0, 0x1d, 0x52, 0x06, 0xec, 0x2c, 0xdb, 0x89, 0x90, 0xcf, 0x78, 0x97, 0x31, 0x09, 0xdc, 0x9f, 0x12, 0x6b, 0x60, 0x33, 0xd6, 0xd5, 0xd6, 0x91, 0x8e, 0xc8, 0x50, 0xd6, 0x9c, 0x71, 0x3c, 0xb5, 0xbb, 0xe3, 0x2e, 0xe5, 0x9e, 0x44, 0x5b, 0xcb, 0x4e, 0x50, 0xc6, 0xf1, 0x64, 0x43, 0x4d, 0x2a, 0x6c, 0xa6, 0x39, 0x69, 0xa2, 0x9b, 0x25, 0x03, 0x64, 0x15, 0xb0, 0xf7, 0xcb, 0x21, 0xb4, 0xf8, 0xb3, 0x4a, 0x8d, 0x9b, 0x74, 0x65, 0x3f, 0xff, 0x4f, 0x5d, 0xb9, 0xd1, 0xa6, 0xb5, 0x15, 0x2a, 0x64, 0x48, 0x36, 0xb6, 0x8b, 0x8e, 0xde, 0x9d, 0xc5, 0xa1, 0x69, 0xdc, 0x60, 0xdc, 0x5f, 0xac, 0x46, 0x8f, 0x24, 0x27, 0x84, 0x58, 0x10, 0x62 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.13", + /* Message */ + 49, + { 0x58, 0x81, 0x15, 0xe5, 0x37, 0x09, 0xeb, 0x15, 0xa3, 0x37, 0x4c, 0x25, 0x32, 0x9e, 0x88, 0x38, 0x26, 0xe3, 0x21, 0x3f, 0x37, 0xa1, 0xb7, 0xa6, 0x5d, 0xe1, 0x2d, 0xf2, 0x31, 0x72, 0xf1, 0x7f, 0xa4, 0x96, 0xff, 0x49, 0x2b, 0x09, 0x17, 0x3b, 0xa0, 0xc6, 0xf5, 0x8c, 0x29, 0x3d, 0x47, 0xf1, 0x48 } +, + /* Seed */ + 77, + { 0x07, 0x81, 0x85, 0xe0, 0x83, 0xcb, 0xb0, 0x6f, 0xe1, 0xa7, 0x49, 0x74, 0x35, 0x15, 0xf3, 0xa0, 0xb4, 0xb2, 0x6f, 0x85, 0x3b, 0x10, 0xe5, 0x68, 0xe8, 0x70, 0x82, 0xce, 0x44, 0x41, 0x2c, 0xa6, 0x7e, 0x59, 0x88, 0x8c, 0xcc, 0x0f, 0x50, 0x31, 0x01, 0x52, 0x1a, 0xca, 0xbf, 0xd9, 0x8f, 0xb7, 0xb5, 0xc1, 0x1d, 0x8a, 0x94, 0x1b, 0xa0, 0x3c, 0x49, 0x5a, 0xa0, 0x3e, 0x13, 0x52, 0x2f, 0x48, 0x7f, 0x6e, 0x16, 0x16, 0xbe, 0xc2, 0x07, 0x2b, 0x39, 0x96, 0xfa, 0xee, 0x29 } +, + /* Encryption */ + 129, + { 0x0e, 0x7e, 0x50, 0xa7, 0xb2, 0x47, 0xb0, 0x29, 0x7d, 0xec, 0x65, 0xc9, 0x52, 0x3f, 0x67, 0xca, 0xb6, 0xb5, 0x2a, 0x02, 0x5f, 0x53, 0x32, 0x0e, 0x94, 0x86, 0xcd, 0x20, 0x74, 0x10, 0xca, 0xdc, 0x74, 0xe4, 0xb0, 0x3f, 0xc0, 0x6b, 0xbe, 0xd5, 0x98, 0xb0, 0x22, 0xb6, 0x3b, 0x37, 0x76, 0x2a, 0x65, 0xfd, 0x35, 0x1c, 0xb2, 0x72, 0x7f, 0x3d, 0x80, 0x35, 0xa4, 0xcd, 0xba, 0x9c, 0x6a, 0x31, 0xe4, 0xed, 0x6b, 0xeb, 0x4f, 0xed, 0x31, 0x34, 0xeb, 0x63, 0xdf, 0xce, 0xab, 0x4f, 0x5f, 0x24, 0x59, 0xe5, 0x9f, 0xca, 0x01, 0x74, 0x75, 0x8a, 0xab, 0x37, 0x53, 0xb5, 0xc1, 0x93, 0xc8, 0x1e, 0x11, 0x49, 0x0f, 0x97, 0xb6, 0x22, 0xb7, 0x3f, 0xa7, 0x3f, 0x8e, 0xae, 0x7d, 0xa8, 0x39, 0x34, 0x84, 0xb8, 0x29, 0x79, 0x71, 0xa3, 0xe9, 0x23, 0x12, 0x9c, 0xe4, 0x35, 0x7b, 0x64, 0x5c, 0xc6, 0x38 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.14", + /* Message */ + 11, + { 0x20, 0xf1, 0xcf, 0xaa, 0x63, 0x67, 0xc7, 0xc3, 0x9b, 0x54, 0xa0 } +, + /* Seed */ + 115, + { 0x4a, 0x1c, 0x7b, 0x70, 0xf7, 0x83, 0xba, 0x0d, 0x5a, 0x26, 0xd4, 0x64, 0x5c, 0xf0, 0x5f, 0xa6, 0x10, 0xf5, 0xbe, 0x01, 0x77, 0xfd, 0xde, 0x9f, 0x2c, 0x34, 0x50, 0x57, 0xdb, 0x42, 0x44, 0x57, 0xfa, 0xa4, 0x30, 0xc9, 0x42, 0x4a, 0x54, 0xf7, 0xe5, 0x5f, 0xcf, 0xee, 0x6f, 0xae, 0xa4, 0x24, 0x4c, 0x03, 0x97, 0x74, 0x81, 0xed, 0xfc, 0xbb, 0x28, 0x88, 0x37, 0xc6, 0xa4, 0x8d, 0xbd, 0x72, 0x96, 0x67, 0x7a, 0x24, 0xe0, 0x6c, 0xc9, 0xd8, 0x5e, 0x68, 0x8c, 0x14, 0x09, 0x0f, 0xa2, 0x83, 0x0f, 0xf4, 0x96, 0x79, 0x33, 0xea, 0xf0, 0xdb, 0x69, 0x4b, 0x6a, 0xe4, 0x02, 0xca, 0xf9, 0xc2, 0xbe, 0xff, 0x04, 0xa5, 0x2a, 0x2f, 0x84, 0x7f, 0xe4, 0x0f, 0x4f, 0xfb, 0xdf, 0x3d, 0x58, 0xb7, 0xc4, 0xfd, 0xa8 } +, + /* Encryption */ + 129, + { 0x1e, 0x52, 0x84, 0x20, 0xbc, 0xbb, 0xa7, 0xd5, 0x9c, 0x6c, 0x40, 0xd4, 0x46, 0xd1, 0xaa, 0x95, 0x6a, 0xff, 0x03, 0x05, 0x36, 0x5b, 0x4d, 0x7c, 0xe9, 0x81, 0x0f, 0x22, 0xc3, 0x4f, 0x09, 0xa5, 0x55, 0xe5, 0xff, 0xbe, 0x51, 0x75, 0x03, 0x7f, 0x90, 0x3e, 0xaa, 0x6c, 0x40, 0x56, 0x36, 0x36, 0xd3, 0x81, 0xf4, 0x53, 0x25, 0xb5, 0xe6, 0x1a, 0x2c, 0x70, 0x51, 0x12, 0x55, 0x64, 0x02, 0xa7, 0xdc, 0xbe, 0x86, 0xcf, 0xa5, 0x4a, 0x6e, 0x6a, 0x50, 0x37, 0x8d, 0x05, 0xe2, 0x1c, 0x95, 0xcc, 0x6c, 0x45, 0xff, 0xdd, 0x05, 0x17, 0xf7, 0x7a, 0x36, 0xb2, 0x24, 0xd1, 0x70, 0x0a, 0x1f, 0x3e, 0xbb, 0x81, 0xd3, 0x67, 0x8a, 0x66, 0xe1, 0x45, 0x34, 0xa8, 0x0a, 0x59, 0x8b, 0xd7, 0x17, 0x26, 0xfe, 0x32, 0x2e, 0x73, 0x9c, 0x17, 0xeb, 0xa5, 0x08, 0xda, 0x8a, 0x03, 0x1a, 0x27, 0xf6, 0xbb, 0x28 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.15", + /* Message */ + 33, + { 0x73, 0x60, 0xcd, 0xb6, 0xc1, 0x59, 0x96, 0xb0, 0x60, 0x33, 0x1e, 0x9f, 0x2a, 0x36, 0x89, 0x95, 0xc0, 0x64, 0xad, 0xda, 0x56, 0x55, 0x95, 0x27, 0x78, 0x2c, 0x17, 0x0c, 0x69, 0x1b, 0xb3, 0xbd, 0x3b } +, + /* Seed */ + 93, + { 0x58, 0xdd, 0x80, 0xf4, 0xfd, 0xc5, 0xc9, 0x5d, 0xd9, 0xeb, 0x56, 0xac, 0x80, 0xa0, 0x2d, 0x53, 0xe8, 0xcc, 0x2e, 0xfb, 0x3c, 0xba, 0xc6, 0x72, 0x7d, 0x75, 0xb1, 0xe7, 0xb3, 0x5e, 0x05, 0x42, 0x19, 0x43, 0x3a, 0xf5, 0xaa, 0xe1, 0x98, 0xfd, 0x62, 0xf2, 0xec, 0xd2, 0xab, 0x8e, 0x26, 0x38, 0x77, 0xb5, 0xc9, 0x1e, 0xd5, 0x13, 0xe2, 0x35, 0x49, 0x7a, 0x63, 0x19, 0x2d, 0xb9, 0xa9, 0xbc, 0xb3, 0xbc, 0xa9, 0x7a, 0xe9, 0xbf, 0xce, 0xdf, 0x93, 0x56, 0x44, 0xb2, 0xd3, 0xbc, 0x20, 0xe0, 0x2a, 0xe5, 0xe7, 0x42, 0x4e, 0x81, 0x2a, 0x29, 0x49, 0x61, 0x6b, 0x82, 0x01 } +, + /* Encryption */ + 129, + { 0x20, 0x3b, 0xcd, 0xe1, 0xb4, 0x12, 0xe3, 0xce, 0xa2, 0x5b, 0x86, 0x30, 0xb2, 0x08, 0xf9, 0x78, 0xab, 0x22, 0xc1, 0xda, 0x81, 0x25, 0x07, 0x6e, 0x10, 0xff, 0x91, 0xd7, 0xbc, 0xfa, 0xef, 0xd7, 0xdc, 0xd8, 0x39, 0x16, 0x55, 0xc8, 0x86, 0xe8, 0xa9, 0x45, 0xa7, 0xf5, 0x7a, 0x74, 0xce, 0x2d, 0xc0, 0xe8, 0xec, 0x7f, 0xdb, 0x17, 0xcf, 0x19, 0x57, 0x80, 0xd3, 0xce, 0x80, 0xe0, 0xdd, 0xe7, 0x63, 0x9c, 0x67, 0x72, 0x05, 0xb8, 0xf9, 0xec, 0xea, 0x11, 0x54, 0x68, 0x97, 0x7b, 0xde, 0xa3, 0x50, 0x0b, 0x23, 0x9f, 0xce, 0x0d, 0x7a, 0x94, 0xbe, 0x6d, 0xe3, 0x33, 0xea, 0x7e, 0xcc, 0x22, 0xc0, 0x7e, 0x65, 0xd0, 0xeb, 0xd6, 0x5a, 0x39, 0x0a, 0x18, 0x5f, 0x18, 0x17, 0x89, 0xe7, 0xca, 0x8c, 0x1a, 0xc2, 0xfc, 0xa8, 0x28, 0xbb, 0x8d, 0x28, 0x22, 0x7e, 0x38, 0xc9, 0x88, 0x9c, 0xe0, 0x08 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.16", + /* Message */ + 29, + { 0x31, 0x9b, 0x82, 0x94, 0xbd, 0xf0, 0x7c, 0xd4, 0x06, 0x85, 0xe8, 0x80, 0x09, 0xfa, 0x7b, 0x3f, 0x12, 0x90, 0x16, 0x0e, 0xf3, 0x30, 0x67, 0xad, 0xd5, 0xef, 0x4d, 0x80, 0xfd } +, + /* Seed */ + 97, + { 0x4e, 0x07, 0xd7, 0xf9, 0x63, 0xbe, 0x24, 0xee, 0x6d, 0x8b, 0xd4, 0xdd, 0x95, 0xe9, 0xe3, 0x33, 0x49, 0x30, 0xe0, 0x3e, 0x65, 0x8d, 0x29, 0x6b, 0xb7, 0x95, 0x48, 0x6d, 0x72, 0x4e, 0x07, 0x41, 0xdd, 0x50, 0x73, 0x47, 0xa5, 0xb5, 0x7b, 0x79, 0xc9, 0x0d, 0x3c, 0x90, 0xc1, 0xae, 0xa7, 0x16, 0x19, 0x09, 0x1a, 0xcc, 0x81, 0x98, 0xb5, 0x51, 0x22, 0xda, 0x50, 0x99, 0x58, 0x2e, 0x0d, 0xb7, 0xda, 0x3c, 0xbd, 0x3c, 0xfd, 0x85, 0x29, 0x8f, 0x31, 0x55, 0x4e, 0x29, 0xcb, 0xcb, 0xa1, 0x19, 0x9c, 0xe4, 0x70, 0x16, 0x3c, 0xa0, 0x33, 0x7c, 0xc4, 0x14, 0xad, 0x32, 0x76, 0x70, 0x81, 0x11, 0xd6 } +, + /* Encryption */ + 129, + { 0x04, 0xfc, 0x7b, 0xb6, 0xfb, 0x64, 0x19, 0x61, 0x2b, 0x6e, 0xf5, 0x4b, 0x3c, 0xa0, 0x0a, 0x87, 0x46, 0x51, 0x95, 0xc3, 0x7f, 0x7f, 0x94, 0x0c, 0x23, 0x3e, 0xcb, 0x1d, 0x4a, 0x50, 0x5d, 0x3c, 0x56, 0xed, 0x23, 0xe0, 0x9e, 0x03, 0xf1, 0x45, 0x4f, 0x04, 0xb5, 0x6f, 0x6d, 0xa2, 0x5d, 0x0a, 0x6f, 0xca, 0xb0, 0xc4, 0x00, 0x87, 0x4a, 0xe9, 0x80, 0x6e, 0xe1, 0x87, 0x80, 0xb7, 0x5c, 0x6c, 0xa5, 0x66, 0x29, 0xe5, 0x77, 0xe8, 0xe7, 0xb5, 0xd2, 0xfc, 0x2c, 0x44, 0x0b, 0x98, 0x00, 0x19, 0x5b, 0x58, 0x51, 0x1b, 0xc3, 0xa7, 0x95, 0x44, 0x12, 0xc8, 0xf2, 0x73, 0xcc, 0x0e, 0x9d, 0x97, 0x1a, 0xbb, 0xdd, 0xd7, 0x02, 0x8e, 0x6f, 0x84, 0x87, 0x6a, 0x30, 0x58, 0xa4, 0x54, 0xfe, 0x2f, 0x33, 0xc7, 0x5e, 0x3d, 0xd0, 0x62, 0xf1, 0x19, 0xcd, 0x3e, 0xca, 0x81, 0x06, 0xb6, 0xbf, 0xbe, 0xa4 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.17", + /* Message */ + 26, + { 0x79, 0xc6, 0x82, 0xa2, 0xb9, 0x79, 0xfe, 0x5c, 0x96, 0x32, 0xaf, 0x18, 0x31, 0xc2, 0xaa, 0xcf, 0x0c, 0x6b, 0xf5, 0x66, 0x88, 0x5b, 0xf5, 0x25, 0x62, 0x50 } +, + /* Seed */ + 100, + { 0x5c, 0x2a, 0x95, 0x6d, 0x4b, 0x5f, 0x06, 0xf7, 0x50, 0x83, 0x5a, 0xb8, 0xb2, 0x9c, 0xf7, 0xc6, 0x41, 0xd7, 0x93, 0xc5, 0x56, 0xe1, 0x2a, 0xab, 0xa9, 0x56, 0xdf, 0xde, 0x46, 0x32, 0xd5, 0xe5, 0x02, 0xd5, 0x90, 0x41, 0x78, 0x3a, 0xfd, 0x1d, 0xa7, 0xb2, 0xe2, 0xd2, 0x4e, 0x22, 0xd6, 0x44, 0x78, 0x35, 0xbf, 0x6d, 0x77, 0xc6, 0xee, 0xbc, 0x0d, 0x2d, 0x64, 0xe7, 0xed, 0x2c, 0x14, 0x17, 0x18, 0xad, 0x86, 0x87, 0xc5, 0x97, 0xb7, 0x71, 0x8f, 0x38, 0xbf, 0x1a, 0x33, 0x16, 0xed, 0xef, 0xf6, 0xb7, 0x2e, 0x28, 0x51, 0x82, 0x88, 0x07, 0xbc, 0xff, 0xa9, 0xb8, 0xe1, 0xa8, 0x52, 0xf3, 0xfa, 0xa8, 0x07, 0xf6 } +, + /* Encryption */ + 129, + { 0x25, 0x1d, 0x48, 0x56, 0xb7, 0xa7, 0x58, 0x0d, 0x53, 0x88, 0x01, 0x62, 0x28, 0x1b, 0xb4, 0xe4, 0x1b, 0xde, 0xb2, 0xa8, 0x7d, 0xdb, 0xd5, 0xae, 0x1b, 0x30, 0x7d, 0x44, 0x48, 0xbe, 0x1f, 0x11, 0x69, 0x5f, 0xf7, 0x22, 0xc4, 0x32, 0x41, 0x5d, 0x0c, 0x74, 0xba, 0xa3, 0xfc, 0x0d, 0xd5, 0x11, 0x66, 0xac, 0x86, 0x5b, 0x31, 0x0c, 0x4f, 0x5c, 0x87, 0x07, 0x98, 0x62, 0x54, 0xc8, 0x96, 0x04, 0xcc, 0xda, 0xbc, 0xe6, 0xc6, 0x92, 0x44, 0x66, 0x21, 0x89, 0x8b, 0x4f, 0x5a, 0x08, 0xbc, 0xdf, 0x64, 0x62, 0xe5, 0x18, 0xee, 0x3a, 0xeb, 0x75, 0xe2, 0x6d, 0x8f, 0x63, 0xa0, 0x6f, 0xcb, 0xb3, 0xdf, 0x09, 0x8c, 0xee, 0xbb, 0x0f, 0xd2, 0xf6, 0x37, 0xe3, 0xa7, 0x93, 0x7f, 0x4d, 0x19, 0xe3, 0xa1, 0x92, 0x4c, 0x16, 0x08, 0x2e, 0xdc, 0x33, 0x3c, 0xb6, 0xde, 0x37, 0x63, 0x72, 0x46, 0xe4, 0x98 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.18", + /* Message */ + 63, + { 0x1e, 0x0d, 0x18, 0x07, 0xa2, 0xbd, 0x49, 0x6b, 0xb0, 0xcb, 0xa8, 0x41, 0xc7, 0x71, 0x58, 0xbf, 0xa5, 0xf8, 0xaa, 0x77, 0xd0, 0x56, 0x75, 0xc6, 0x4a, 0x5e, 0xb1, 0x85, 0x65, 0x91, 0xd3, 0x48, 0x54, 0xf8, 0x65, 0x92, 0x5b, 0x37, 0x1b, 0x68, 0x6a, 0xaa, 0xb4, 0x45, 0x98, 0xb4, 0xa1, 0x6a, 0xb6, 0xb7, 0x93, 0x44, 0xd3, 0xc2, 0x3f, 0x7d, 0x5b, 0xf1, 0x73, 0xb8, 0x42, 0xd7, 0x8c } +, + /* Seed */ + 63, + { 0xdb, 0xaf, 0xa5, 0x33, 0x2f, 0x0b, 0x55, 0x27, 0x96, 0x63, 0x6d, 0x8a, 0x09, 0x28, 0xb7, 0xd8, 0x7d, 0x9c, 0xee, 0x3d, 0x4b, 0xe6, 0xa3, 0x1c, 0x77, 0xe1, 0x4e, 0x0e, 0x5d, 0xfd, 0xd4, 0x03, 0xef, 0xb9, 0x8f, 0xa3, 0x38, 0x81, 0x6e, 0x12, 0x62, 0xc0, 0x64, 0x96, 0xfd, 0xe9, 0xd5, 0x57, 0xc0, 0x0c, 0xc0, 0xdd, 0x35, 0xfc, 0x33, 0xac, 0xcd, 0x79, 0xa3, 0x15, 0x06, 0x90, 0xeb } +, + /* Encryption */ + 129, + { 0x1b, 0x2e, 0xce, 0xa5, 0xfa, 0x90, 0x03, 0xfa, 0xb6, 0x55, 0x98, 0x57, 0xc6, 0xd9, 0x4f, 0x95, 0x70, 0x03, 0xf4, 0xe4, 0x1c, 0x09, 0x45, 0x64, 0x80, 0x4f, 0xe6, 0x96, 0x39, 0xe5, 0x40, 0xb6, 0x8f, 0x26, 0x3f, 0xaa, 0xec, 0xa1, 0x99, 0x69, 0x7a, 0x48, 0x85, 0x8b, 0x8a, 0x0f, 0xce, 0xa4, 0x91, 0x05, 0x7d, 0xf2, 0xfb, 0x8b, 0x35, 0xd0, 0x93, 0xd8, 0x94, 0xae, 0xc1, 0x7c, 0x5c, 0xde, 0x5d, 0xfd, 0x8f, 0x33, 0x51, 0x2b, 0xcc, 0x66, 0xcd, 0xe7, 0x6d, 0xa0, 0x73, 0x36, 0x98, 0x5a, 0x97, 0x43, 0x5b, 0x6e, 0xfe, 0xe4, 0xee, 0x09, 0xd3, 0xa2, 0x8a, 0xff, 0x34, 0xce, 0x6a, 0xe8, 0x75, 0x0d, 0xa4, 0x1e, 0x16, 0xca, 0x47, 0xe9, 0x38, 0x81, 0x8e, 0x44, 0xa9, 0xb4, 0x1f, 0xe9, 0x1a, 0x6a, 0x80, 0x1d, 0x35, 0x5e, 0xe8, 0xd6, 0x60, 0xe2, 0x7e, 0x4f, 0xe2, 0xce, 0x7f, 0x32, 0x5b } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.19", + /* Message */ + 15, + { 0x1c, 0x10, 0x5d, 0x5e, 0xbe, 0xa3, 0x66, 0x46, 0xa9, 0x72, 0x84, 0xc1, 0x7a, 0x86, 0xc4 } +, + /* Seed */ + 111, + { 0xc6, 0xf8, 0x03, 0x40, 0xa6, 0x55, 0x7e, 0x07, 0x53, 0xa9, 0x57, 0x3f, 0xe4, 0xf5, 0x21, 0x49, 0x77, 0xef, 0xdb, 0x08, 0x2a, 0x50, 0xeb, 0x5d, 0x5c, 0x51, 0x7d, 0x46, 0x72, 0x9f, 0xd2, 0xa3, 0x4a, 0xf7, 0xce, 0xe1, 0xaa, 0x46, 0xb7, 0x9d, 0x47, 0xe2, 0x5d, 0x83, 0x09, 0x0a, 0xeb, 0x4f, 0x50, 0x22, 0x98, 0xc0, 0x31, 0x37, 0x24, 0xfa, 0xb5, 0x4e, 0x54, 0xbe, 0xbb, 0x48, 0xd6, 0xcd, 0x9b, 0xeb, 0xdd, 0xcb, 0xee, 0x0f, 0x07, 0x53, 0x77, 0x27, 0xd6, 0x5c, 0x50, 0xe7, 0xd4, 0xcc, 0x0c, 0x6d, 0x19, 0xfc, 0x48, 0x0b, 0xa5, 0x78, 0x67, 0x26, 0x2c, 0xf2, 0xee, 0xdd, 0x9c, 0xfa, 0xba, 0x60, 0x7d, 0x65, 0x82, 0x87, 0xeb, 0xa4, 0x2b, 0x46, 0x99, 0x44, 0xcc, 0xb6, 0x12 } +, + /* Encryption */ + 129, + { 0x05, 0xb2, 0x3d, 0xc0, 0xc6, 0x2d, 0x90, 0xc1, 0x77, 0x1e, 0xba, 0x37, 0x8e, 0x43, 0x17, 0x9d, 0x7c, 0xa6, 0xaf, 0x51, 0x5e, 0x26, 0x19, 0xae, 0x4d, 0x7c, 0x8f, 0xc8, 0xbd, 0xa3, 0x78, 0xcb, 0xf7, 0xa1, 0xdb, 0xba, 0x1a, 0x14, 0xf4, 0x94, 0xc4, 0xe0, 0xd7, 0x13, 0x38, 0x79, 0x7c, 0x7e, 0xe0, 0x6e, 0x1a, 0x79, 0xe9, 0xff, 0x28, 0x56, 0xfb, 0xf7, 0x4f, 0xe6, 0xf1, 0xa7, 0xca, 0x6e, 0x5b, 0x9c, 0xa2, 0x83, 0xc4, 0xc9, 0x7e, 0x61, 0xcf, 0x9f, 0x40, 0x73, 0xe0, 0x32, 0xca, 0x27, 0xd6, 0x9b, 0x1b, 0x4e, 0xeb, 0xea, 0x77, 0xcc, 0x95, 0xa9, 0x28, 0x1f, 0x26, 0xb6, 0x4a, 0x05, 0xa9, 0x39, 0x44, 0xc8, 0x2c, 0x5a, 0x13, 0x42, 0x8e, 0xce, 0x21, 0xfb, 0x44, 0x01, 0xad, 0x42, 0x6e, 0x7a, 0xc1, 0xf0, 0x5b, 0xff, 0x84, 0xb3, 0x47, 0xcd, 0xc4, 0xdb, 0xe5, 0x2e, 0x67, 0x8a, 0xed } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 12.20", + /* Message */ + 12, + { 0xf1, 0x04, 0x02, 0xf0, 0x02, 0x05, 0xc5, 0x27, 0x57, 0xed, 0x6e, 0x9d } +, + /* Seed */ + 114, + { 0xe2, 0xae, 0xe7, 0xfc, 0xf4, 0x3c, 0xed, 0xe0, 0x75, 0x52, 0xa2, 0xdf, 0xe5, 0xb5, 0xa9, 0xef, 0x80, 0x82, 0x76, 0xd8, 0xf1, 0x0e, 0xb3, 0xf9, 0xbc, 0x50, 0xf1, 0xbd, 0x94, 0x0a, 0xaa, 0xe6, 0x34, 0xc9, 0xd8, 0xa0, 0x78, 0x8d, 0x44, 0xd4, 0x1e, 0x8a, 0x5c, 0x60, 0x36, 0x49, 0xef, 0xea, 0x83, 0x03, 0x32, 0x31, 0x51, 0x6c, 0x69, 0xd3, 0x3e, 0x12, 0xf1, 0xf5, 0xd3, 0xf0, 0xac, 0x1f, 0xc2, 0x3a, 0x9b, 0x3f, 0x5d, 0xa4, 0xe0, 0xef, 0x6e, 0x45, 0x50, 0xcb, 0x43, 0xfd, 0xff, 0x02, 0xb2, 0x5d, 0xac, 0x86, 0x27, 0x2d, 0x66, 0xdb, 0x59, 0xcd, 0xd6, 0x35, 0xf9, 0xc0, 0xdd, 0x0d, 0xaa, 0x08, 0x57, 0x91, 0x0c, 0x15, 0x88, 0x1b, 0x16, 0x0d, 0x70, 0xea, 0x53, 0x40, 0x5a, 0xa9, 0x59, 0xf4 } +, + /* Encryption */ + 129, + { 0x0b, 0x96, 0x56, 0x31, 0x78, 0x32, 0xa9, 0x40, 0xc7, 0x95, 0xbb, 0xa5, 0x8d, 0xaa, 0x15, 0x9a, 0x4f, 0x73, 0x3e, 0x82, 0x6c, 0xe5, 0x5a, 0x4e, 0xc5, 0x64, 0x33, 0xc5, 0x16, 0x84, 0x44, 0x4c, 0x78, 0xe2, 0xe2, 0xfc, 0xb3, 0x7f, 0x85, 0xad, 0x87, 0x79, 0x16, 0x52, 0x2d, 0x8a, 0x35, 0xa4, 0x3f, 0x53, 0xc5, 0x95, 0x17, 0xa8, 0x18, 0xe5, 0x21, 0xe1, 0x98, 0x2a, 0x50, 0x91, 0xbf, 0x2c, 0x68, 0xb0, 0x0e, 0xe4, 0x9a, 0xbd, 0x90, 0xdd, 0x77, 0x6c, 0x02, 0xf6, 0x4f, 0x34, 0xf6, 0x80, 0xa8, 0x8e, 0xee, 0x05, 0xec, 0x08, 0x88, 0x92, 0xbc, 0x0a, 0x95, 0x55, 0xb3, 0xf2, 0x0c, 0x8b, 0xee, 0x57, 0x9c, 0x0d, 0xdd, 0xe1, 0x51, 0x1a, 0x18, 0xaf, 0x98, 0xbc, 0x1d, 0x9c, 0xf9, 0x0b, 0x81, 0xbf, 0x13, 0x2a, 0xbd, 0x58, 0x97, 0x0b, 0x3e, 0x84, 0xd8, 0x14, 0xe2, 0x7d, 0x02, 0x5b, 0x73 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 13: A 1031-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x55, 0x5d, 0xc2, 0xba, 0xf0, 0x41, 0xb7, 0xf0, 0x9a, 0x04, 0x78, 0x42, 0x3a, 0xeb, 0xcb, 0x5f, 0x49, 0xb9, 0x5d, 0xbe, 0x15, 0x70, 0xe9, 0xa5, 0x42, 0x12, 0x8d, 0x33, 0x22, 0x87, 0x86, 0x6a, 0xc4, 0xcc, 0x63, 0xe7, 0x6f, 0x8e, 0x3a, 0xef, 0x22, 0xc9, 0x75, 0x3a, 0x54, 0x51, 0x99, 0x94, 0x24, 0x52, 0x41, 0x8a, 0x67, 0xd1, 0xa2, 0x23, 0x0d, 0xdb, 0x6f, 0x42, 0x22, 0xc6, 0x63, 0xd3, 0x8e, 0x80, 0x05, 0x0e, 0xeb, 0x67, 0x95, 0x6e, 0xc5, 0xf5, 0x49, 0x94, 0xa0, 0xbe, 0xa6, 0x95, 0xfa, 0x59, 0xfa, 0xdf, 0x2d, 0xcf, 0xe7, 0xac, 0xb5, 0x4e, 0xd9, 0xda, 0x3d, 0x0b, 0xeb, 0x12, 0x2c, 0x8a, 0x69, 0x1b, 0x0b, 0xb5, 0x1a, 0xe6, 0x5a, 0x77, 0x4d, 0x75, 0xb1, 0xb3, 0x49, 0xcb, 0x68, 0xc5, 0x17, 0xcb, 0xd3, 0x86, 0xae, 0x48, 0x2f, 0x05, 0xee, 0x46, 0x03, 0xec, 0xf2, 0x95, 0x5d } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x05, 0x97, 0x87, 0xbb, 0x01, 0x23, 0xfc, 0xed, 0x98, 0xd9, 0x34, 0x1b, 0x7a, 0x8a, 0x99, 0x9e, 0xdb, 0x50, 0x76, 0x30, 0x8e, 0x6d, 0x00, 0x11, 0x20, 0x3b, 0xe0, 0xdd, 0xf9, 0xa4, 0x11, 0x0d, 0x0b, 0x69, 0x2c, 0x1e, 0x2b, 0xf3, 0x90, 0x2e, 0xbc, 0x03, 0xa0, 0x57, 0x3a, 0xd0, 0xc1, 0x93, 0xaf, 0xb1, 0x67, 0xb3, 0xae, 0x4b, 0x50, 0x28, 0xa5, 0xae, 0xbb, 0x22, 0x04, 0xef, 0x23, 0xf8, 0xe5, 0x83, 0x60, 0xbe, 0x94, 0x84, 0x95, 0x1e, 0x34, 0x71, 0x11, 0x76, 0x06, 0x2e, 0x53, 0xe3, 0xf6, 0x38, 0x74, 0xfc, 0x9e, 0x35, 0x91, 0xa9, 0xd9, 0x06, 0x8a, 0xa5, 0xe6, 0xc8, 0xc7, 0xa9, 0xab, 0x08, 0xe9, 0x79, 0x24, 0x70, 0x06, 0x6d, 0x71, 0xa0, 0x7c, 0x34, 0x33, 0xdd, 0x70, 0x3a, 0x42, 0xa6, 0xb3, 0xa9, 0xb1, 0xbf, 0xfb, 0x31, 0x49, 0x49, 0x8d, 0xcf, 0xf8, 0xb3, 0x57, 0x56, 0xed } +, + /* Prime 1 */ + 65, + { 0x0a, 0x7d, 0xbd, 0x7e, 0xe6, 0xde, 0xf3, 0x87, 0x5b, 0x4c, 0x55, 0x9f, 0x56, 0x69, 0x30, 0x7d, 0x17, 0x6b, 0xc1, 0x25, 0xb0, 0x9f, 0x5e, 0xb8, 0x26, 0x01, 0xb8, 0x13, 0x48, 0x57, 0x6c, 0x1c, 0xa7, 0xdc, 0xf4, 0xc2, 0xbd, 0x7f, 0x2b, 0x42, 0xa2, 0xc5, 0x46, 0x00, 0x02, 0xfc, 0xe0, 0xa9, 0xa2, 0x1d, 0xac, 0x5a, 0x97, 0x97, 0xdb, 0x23, 0x3d, 0x9d, 0x4a, 0x92, 0x93, 0xad, 0xd3, 0xdf, 0x73 } +, + /* Prime 2 */ + 65, + { 0x08, 0x23, 0x0f, 0xcf, 0x26, 0xfd, 0xc5, 0x75, 0x11, 0x9c, 0xf9, 0x05, 0x78, 0xd3, 0x66, 0x56, 0x4c, 0xfd, 0xa8, 0x65, 0xa2, 0x82, 0x0f, 0x38, 0xbc, 0xd6, 0x3e, 0xca, 0xa0, 0x95, 0x57, 0x65, 0x77, 0x2a, 0x88, 0x32, 0xfb, 0x31, 0x69, 0x7f, 0xd0, 0xdd, 0x45, 0xbb, 0xec, 0xc0, 0x4d, 0xd6, 0xa5, 0x9e, 0xc1, 0x1c, 0x1d, 0x5c, 0x6e, 0x87, 0x7c, 0x6b, 0x9d, 0x77, 0xc6, 0xa2, 0x76, 0xe3, 0xef } +, + /* Prime exponent 1 */ + 65, + { 0x08, 0xd1, 0xc7, 0xd9, 0xc4, 0xd0, 0x2c, 0xbd, 0xdf, 0x7c, 0x7e, 0x86, 0x62, 0xa8, 0x2f, 0x41, 0x19, 0xcd, 0x56, 0x24, 0x0f, 0x25, 0x0b, 0x05, 0x97, 0xbd, 0xde, 0x37, 0x27, 0x9b, 0x86, 0xa1, 0x58, 0x64, 0xa1, 0xc6, 0x8c, 0x73, 0x39, 0xb4, 0xdd, 0x0d, 0x26, 0x59, 0xa0, 0x29, 0x61, 0xdc, 0x79, 0x12, 0xa4, 0xef, 0xcb, 0x7c, 0xb7, 0x96, 0x1a, 0x97, 0xfe, 0x36, 0xd6, 0xbb, 0x4c, 0xe0, 0x0d } +, + /* Prime exponent 2 */ + 65, + { 0x01, 0xd4, 0x91, 0x3b, 0xd1, 0xd3, 0x87, 0xd5, 0x3b, 0xaf, 0x09, 0xbd, 0x17, 0x5e, 0xc6, 0x48, 0x67, 0x6d, 0x2f, 0xb2, 0x1d, 0x0a, 0x10, 0x8e, 0x7c, 0xbb, 0xdc, 0xc8, 0x0b, 0xb3, 0x4c, 0x43, 0x80, 0xb8, 0xca, 0x86, 0x5d, 0x46, 0xd2, 0x2a, 0x74, 0x3b, 0x31, 0xf2, 0x81, 0xe1, 0x08, 0x21, 0x5e, 0x84, 0x05, 0x80, 0x63, 0x82, 0x65, 0x42, 0x88, 0xd4, 0x54, 0x49, 0x9b, 0x1e, 0xf4, 0x8b, 0x75 } +, + /* Coefficient */ + 65, + { 0x08, 0x7b, 0x2e, 0xf2, 0x11, 0x44, 0x8e, 0x5c, 0x96, 0x1c, 0x9f, 0x6d, 0xfe, 0xe6, 0xaa, 0x26, 0x8e, 0xe8, 0x97, 0x7e, 0x31, 0x1c, 0x07, 0xcc, 0x8d, 0xb4, 0x72, 0xda, 0x6c, 0x49, 0x86, 0x3f, 0xaa, 0xf3, 0x3b, 0xf5, 0x05, 0xdc, 0xfd, 0x81, 0xf5, 0x3a, 0x53, 0xbe, 0x12, 0x1e, 0x44, 0x5e, 0x89, 0xd7, 0xe0, 0x38, 0xef, 0x27, 0xf3, 0x72, 0x7b, 0x51, 0x2a, 0x2b, 0x80, 0x94, 0x41, 0x20, 0xea } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 13.1", + /* Message */ + 7, + { 0x7b, 0xc8, 0x1d, 0x81, 0x46, 0xe3, 0x59 } +, + /* Seed */ + 119, + { 0x76, 0x65, 0x5e, 0x4a, 0xd8, 0xfb, 0x99, 0x34, 0xd1, 0x84, 0x7c, 0xc9, 0x0c, 0x02, 0x47, 0x3c, 0x57, 0x2b, 0x5f, 0xdf, 0xd1, 0x64, 0xa9, 0x70, 0xa3, 0xcd, 0x96, 0xbc, 0x8c, 0xd7, 0x96, 0xac, 0x80, 0x2c, 0x50, 0x28, 0x22, 0x90, 0xea, 0xd4, 0xc7, 0x7a, 0xa5, 0xcc, 0x2a, 0x7e, 0x34, 0x34, 0x18, 0xc9, 0xdf, 0x47, 0xef, 0xb8, 0x87, 0x86, 0xaf, 0x4c, 0xc8, 0xd1, 0x82, 0x1c, 0x50, 0x07, 0x39, 0x09, 0xe8, 0x4f, 0x7b, 0x45, 0x1a, 0xf4, 0xa3, 0x2a, 0xee, 0x6c, 0x7c, 0xc8, 0x97, 0xee, 0xf7, 0x66, 0x0e, 0x1c, 0x4c, 0x53, 0x5d, 0x10, 0x03, 0x9d, 0x3a, 0xa2, 0x03, 0x5c, 0x98, 0x51, 0x01, 0x25, 0xec, 0x5f, 0x2a, 0x2e, 0x9d, 0xac, 0x63, 0x95, 0x89, 0xff, 0x8b, 0xb3, 0x9f, 0x07, 0x43, 0x8d, 0xef, 0xb7, 0xd1, 0x33, 0x77 } +, + /* Encryption */ + 129, + { 0x14, 0x6d, 0x65, 0x12, 0xdf, 0xdf, 0xfb, 0xc0, 0x2d, 0x5d, 0x54, 0xbf, 0xf3, 0xe0, 0x36, 0xa3, 0x5b, 0x4c, 0x2a, 0xa9, 0x44, 0xd6, 0xf6, 0x72, 0x47, 0x93, 0x30, 0x65, 0x37, 0x08, 0x1b, 0xd1, 0x1e, 0xe5, 0x68, 0xa4, 0xe9, 0x71, 0x9f, 0x1e, 0x31, 0xf2, 0xd1, 0x4e, 0x18, 0xc2, 0xda, 0x62, 0x44, 0x70, 0xc5, 0xb0, 0xff, 0xab, 0x39, 0x7f, 0x92, 0x31, 0xb6, 0xef, 0x46, 0x34, 0xf6, 0x3a, 0x18, 0x28, 0x5d, 0xf3, 0x41, 0x45, 0x17, 0xa5, 0x1f, 0x93, 0x58, 0x6d, 0x66, 0xb0, 0x3c, 0xab, 0x1e, 0x78, 0xa4, 0xeb, 0x94, 0x1b, 0x9d, 0x3d, 0x7f, 0x92, 0x03, 0xb5, 0x9e, 0x1c, 0xb3, 0xbb, 0x48, 0x64, 0xb6, 0x46, 0xdc, 0x17, 0xa0, 0x64, 0x11, 0xeb, 0xd5, 0xff, 0x03, 0x37, 0x20, 0x58, 0x88, 0x1b, 0x4a, 0x24, 0xb2, 0x4f, 0x4c, 0x2d, 0xcd, 0x5c, 0xb4, 0x4c, 0x2e, 0xea, 0xbe, 0x6f, 0x72 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 13.2", + /* Message */ + 52, + { 0x68, 0x6a, 0x81, 0x0a, 0x03, 0x1d, 0x80, 0x61, 0xe4, 0x1a, 0x77, 0x6a, 0x7d, 0xfb, 0xdb, 0x3a, 0xf6, 0x26, 0xfe, 0x97, 0x69, 0xde, 0xee, 0xa4, 0x60, 0xba, 0x28, 0x67, 0xac, 0xf0, 0x3d, 0x9f, 0x92, 0x4d, 0x32, 0x1e, 0x8a, 0x8f, 0x42, 0x5c, 0x28, 0x51, 0x92, 0x98, 0x67, 0xa3, 0x26, 0xae, 0x27, 0x5b, 0x49, 0xd2 } +, + /* Seed */ + 74, + { 0xf7, 0x9b, 0x49, 0xf6, 0xa6, 0xbe, 0x3e, 0x68, 0x88, 0x4c, 0x80, 0xdf, 0xe1, 0xe8, 0x50, 0x1e, 0x54, 0x4c, 0xa7, 0x82, 0x23, 0x88, 0x43, 0xd4, 0x19, 0x76, 0x41, 0x12, 0x25, 0x0e, 0xdc, 0x1b, 0x69, 0xc7, 0xd1, 0xc3, 0x58, 0x7f, 0xdc, 0x75, 0x98, 0x7c, 0x62, 0xcb, 0x4c, 0x33, 0xbb, 0x81, 0x20, 0x2f, 0x72, 0xdb, 0xa7, 0xee, 0xe2, 0x4b, 0xfc, 0xf8, 0x9d, 0x4d, 0xae, 0x15, 0x0c, 0x07, 0x27, 0x24, 0x58, 0xfb, 0x01, 0xb6, 0xcd, 0x27, 0x09, 0x25 } +, + /* Encryption */ + 129, + { 0x08, 0x8a, 0x47, 0xf1, 0x1c, 0xb1, 0x34, 0xde, 0xc4, 0xb5, 0x08, 0x77, 0x25, 0xe8, 0xa5, 0xbd, 0x04, 0xf7, 0xfe, 0x58, 0x2a, 0x69, 0x91, 0x4f, 0x68, 0x3e, 0xe6, 0xde, 0x7c, 0x32, 0x4f, 0xed, 0x7e, 0x07, 0xf5, 0x70, 0x05, 0xc0, 0xe0, 0xdf, 0x75, 0x00, 0xe3, 0x70, 0xa4, 0x2e, 0xfd, 0x6f, 0xe5, 0xb2, 0x90, 0x19, 0x95, 0x19, 0xb1, 0x98, 0x06, 0xb6, 0xe6, 0x91, 0x69, 0x8a, 0xfd, 0x95, 0x17, 0xd7, 0x80, 0xda, 0x0b, 0xeb, 0xf7, 0x0a, 0x26, 0xd6, 0x5c, 0x5b, 0x64, 0xe3, 0x40, 0xa6, 0x40, 0x5e, 0x88, 0x95, 0x55, 0xdf, 0xa0, 0xa9, 0x2c, 0x42, 0x9a, 0xe9, 0xc3, 0xec, 0x88, 0xe8, 0x88, 0xee, 0xda, 0x04, 0x5e, 0x41, 0x0e, 0x3a, 0x9e, 0x61, 0x99, 0xab, 0x39, 0xeb, 0x1a, 0xc8, 0x64, 0xe2, 0x28, 0xc2, 0xcc, 0x1b, 0x64, 0xe3, 0x36, 0x16, 0x95, 0xb5, 0xaa, 0x11, 0x3d, 0xc5, 0xa7 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.3", + /* Message */ + 9, + { 0x18, 0x54, 0x4a, 0xad, 0x24, 0xab, 0x07, 0x5d, 0x3a } +, + /* Seed */ + 117, + { 0x23, 0x20, 0x4b, 0x8a, 0xd9, 0x45, 0x75, 0xf6, 0xe2, 0xf4, 0x6c, 0x79, 0x7b, 0xb8, 0x73, 0xaa, 0x3f, 0x46, 0x1a, 0xcd, 0x05, 0xe7, 0xdb, 0x78, 0x46, 0xa2, 0x31, 0x57, 0x59, 0x2d, 0x52, 0xe9, 0xa9, 0xa7, 0x04, 0x38, 0x19, 0xc4, 0x88, 0x96, 0x27, 0x5e, 0xd9, 0xdf, 0x0b, 0x1e, 0x54, 0x04, 0x93, 0xc0, 0x77, 0xea, 0x15, 0x41, 0x9a, 0xfa, 0x87, 0xdc, 0x35, 0xf9, 0xfd, 0xf7, 0xab, 0x8a, 0xaf, 0x47, 0xee, 0xe1, 0xd3, 0x3e, 0xcc, 0x28, 0x95, 0x06, 0x45, 0xf1, 0xb6, 0x91, 0x38, 0x2d, 0x87, 0x54, 0x1e, 0xd0, 0x64, 0x06, 0x93, 0x0c, 0x7e, 0xe1, 0x10, 0x9a, 0xa5, 0xca, 0x75, 0xa4, 0x90, 0x93, 0x4e, 0xa8, 0xd3, 0xb2, 0xa0, 0x4b, 0xa1, 0x52, 0x1b, 0xe0, 0x92, 0xc8, 0x68, 0xf7, 0xea, 0x5b, 0xe3, 0x78, 0xea } +, + /* Encryption */ + 129, + { 0x34, 0xd6, 0xe5, 0x46, 0xd6, 0x9e, 0x27, 0x06, 0xcd, 0xfc, 0x6d, 0x9e, 0x74, 0x18, 0xf8, 0xbe, 0x03, 0xe4, 0x57, 0x56, 0xa8, 0xb1, 0x9b, 0x60, 0xc2, 0x1d, 0x27, 0x34, 0x20, 0xaa, 0x7d, 0x5e, 0xbb, 0xbf, 0x46, 0x0e, 0xf4, 0xc8, 0x4f, 0x6d, 0x47, 0x77, 0xe6, 0xbf, 0x20, 0x3f, 0xf9, 0x18, 0x5f, 0xd5, 0x7d, 0xc7, 0x23, 0xb5, 0x8f, 0x35, 0xc1, 0xe9, 0xb5, 0xff, 0xf4, 0x7c, 0xf9, 0x5a, 0xe5, 0x69, 0xa5, 0xcb, 0x64, 0xdd, 0x9c, 0xb8, 0xd6, 0x40, 0x7c, 0x0b, 0xa5, 0xef, 0xd1, 0x48, 0xf1, 0x8b, 0x56, 0x96, 0xb0, 0x47, 0xda, 0xaa, 0xa2, 0x77, 0xed, 0x8d, 0x45, 0x28, 0x61, 0x4e, 0xe3, 0xda, 0x52, 0x38, 0x71, 0x32, 0xb7, 0xa9, 0xcc, 0xfe, 0x07, 0x3b, 0xe5, 0x03, 0x32, 0xc9, 0xe2, 0x83, 0x73, 0x53, 0xc6, 0x7d, 0xaa, 0x0f, 0xdf, 0xef, 0xc3, 0xb6, 0x52, 0xcf, 0x7d, 0x79, 0xfd } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.4", + /* Message */ + 4, + { 0xd9, 0x0f, 0xa3, 0x8f } +, + /* Seed */ + 122, + { 0x3e, 0x09, 0xf6, 0x50, 0x6f, 0x7f, 0x71, 0x91, 0x47, 0xae, 0x21, 0xe3, 0x94, 0x53, 0xae, 0x0b, 0x41, 0x60, 0x98, 0xda, 0x10, 0x3a, 0xf8, 0x4c, 0x0f, 0x7c, 0xef, 0xae, 0x50, 0x01, 0x99, 0xc9, 0x85, 0x59, 0x67, 0xa8, 0x30, 0x0a, 0x1a, 0x7f, 0x8d, 0x2c, 0xc1, 0x3b, 0x91, 0x72, 0x7e, 0xeb, 0xd9, 0x3c, 0xf7, 0x7d, 0x3f, 0xac, 0xb1, 0x9e, 0x83, 0xa8, 0x40, 0xeb, 0x58, 0x3b, 0xce, 0xa6, 0xc6, 0x11, 0x3a, 0x9c, 0x6f, 0x6f, 0x1f, 0xb5, 0xa0, 0xb3, 0x32, 0x55, 0x9a, 0x6b, 0x43, 0x15, 0x47, 0x45, 0x7c, 0xda, 0x1d, 0x3d, 0xce, 0xe3, 0x41, 0xd1, 0x71, 0xc6, 0x2e, 0x95, 0xe7, 0xea, 0xae, 0x16, 0xae, 0x0e, 0xaf, 0x1c, 0x1f, 0xe8, 0x10, 0xfb, 0xb0, 0xb7, 0x13, 0x8c, 0xfa, 0x3d, 0x66, 0xc6, 0x38, 0x50, 0xf3, 0x81, 0xe4, 0x9a, 0x2d, 0xad } +, + /* Encryption */ + 129, + { 0x27, 0x13, 0x3f, 0x43, 0x79, 0x1b, 0x39, 0x22, 0x7c, 0x8e, 0x95, 0x4e, 0x1c, 0xaa, 0x83, 0x0f, 0xa6, 0x59, 0x95, 0xf8, 0xa9, 0xf8, 0x8e, 0x0d, 0x1f, 0x75, 0x67, 0x85, 0xed, 0x5c, 0x8c, 0x78, 0x54, 0xfb, 0x1a, 0x9d, 0xc4, 0xa9, 0x5f, 0xa4, 0x4d, 0xbd, 0xf0, 0xf2, 0x85, 0x99, 0xc4, 0x72, 0x84, 0x93, 0x79, 0x75, 0x0a, 0x6a, 0x1b, 0xcb, 0x42, 0xca, 0xfb, 0x5b, 0xbf, 0xe0, 0x8c, 0x65, 0x10, 0x6d, 0xc8, 0x40, 0xcb, 0xec, 0x8e, 0xe2, 0xcb, 0x5a, 0x20, 0x6c, 0x81, 0x18, 0xaa, 0x06, 0x1d, 0xa4, 0xd2, 0x1d, 0x1b, 0x5c, 0x46, 0x11, 0x7f, 0x77, 0xc8, 0x96, 0xbc, 0x71, 0xce, 0xe2, 0xf8, 0x75, 0x7a, 0xff, 0x5c, 0xb2, 0xb3, 0xc3, 0x47, 0x74, 0x55, 0x8e, 0x8b, 0x82, 0xed, 0xb4, 0xef, 0x9b, 0xf2, 0xd4, 0xf2, 0xca, 0x4f, 0xc5, 0x97, 0xfa, 0xb4, 0x0a, 0x2d, 0x74, 0xe5, 0x23, 0x3a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.5", + /* Message */ + 47, + { 0xfc, 0xbd, 0xd0, 0x24, 0x8d, 0xf8, 0x57, 0xaf, 0x17, 0x5b, 0x43, 0x96, 0x87, 0x5c, 0x00, 0x6d, 0x51, 0x14, 0xcc, 0x11, 0x16, 0x42, 0x80, 0x04, 0x38, 0x08, 0xaa, 0x79, 0x88, 0x6c, 0x4c, 0xaa, 0x29, 0x11, 0x7b, 0xf3, 0xce, 0x45, 0xa9, 0xbe, 0x55, 0x07, 0xc6, 0xb8, 0xbf, 0x0d, 0x30 } +, + /* Seed */ + 79, + { 0x2c, 0x9d, 0x14, 0x57, 0xba, 0x44, 0x50, 0xdf, 0x40, 0x21, 0xe4, 0xe5, 0x11, 0x83, 0xf7, 0x95, 0xd0, 0x91, 0xc0, 0x7f, 0x6a, 0xe0, 0xdd, 0x96, 0x2d, 0x57, 0x28, 0xc5, 0x4b, 0x7f, 0xc3, 0xc7, 0x72, 0xd7, 0x9d, 0x7b, 0xec, 0xe1, 0xbb, 0x0c, 0x99, 0x6c, 0x9a, 0xc0, 0x7f, 0x99, 0x54, 0xdd, 0xa7, 0x68, 0x7b, 0xec, 0x86, 0xbc, 0xdb, 0x31, 0x40, 0xb2, 0x45, 0xbb, 0x5e, 0x01, 0x27, 0x5b, 0x38, 0xd1, 0xf2, 0x52, 0x33, 0x5e, 0x36, 0xc6, 0x8c, 0x0e, 0x58, 0xf4, 0xce, 0x11, 0x7e } +, + /* Encryption */ + 129, + { 0x2c, 0xed, 0xde, 0xf2, 0x02, 0x69, 0x1a, 0xae, 0x42, 0x71, 0x85, 0x2a, 0x89, 0x83, 0xde, 0x7c, 0x21, 0x4c, 0xee, 0x00, 0xdb, 0xe1, 0xa1, 0x58, 0x84, 0xf4, 0xc3, 0xc1, 0xde, 0x7a, 0x3e, 0xa0, 0x1e, 0xcc, 0xf4, 0x7a, 0xe8, 0x6c, 0x26, 0x93, 0x24, 0xae, 0x52, 0x37, 0x73, 0x37, 0xb6, 0xca, 0x82, 0xe8, 0x5d, 0x55, 0x3f, 0xbb, 0x2e, 0xe5, 0xf9, 0x77, 0xdc, 0x66, 0x4e, 0x14, 0x2f, 0x1b, 0x54, 0x53, 0x8f, 0xaf, 0x85, 0xca, 0xc2, 0x7c, 0x29, 0xf2, 0xed, 0x0c, 0x40, 0x42, 0x67, 0x33, 0x5d, 0x48, 0xea, 0x40, 0xe8, 0xa3, 0xdd, 0xd8, 0x96, 0xbb, 0xb3, 0xe0, 0xed, 0xf0, 0xe1, 0x6f, 0x9e, 0x89, 0x44, 0x68, 0x3b, 0x8c, 0xfb, 0xaa, 0xb5, 0xea, 0xf2, 0x25, 0x30, 0xf1, 0x58, 0xc4, 0x88, 0x0b, 0xc3, 0xe4, 0x60, 0xc0, 0x6a, 0x24, 0x03, 0x42, 0x21, 0x0a, 0xa8, 0x7b, 0x79, 0x09, 0x68 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.6", + /* Message */ + 34, + { 0x25, 0xf2, 0xa3, 0x06, 0xea, 0xbe, 0x6e, 0x3a, 0x18, 0x30, 0xdc, 0x93, 0x6b, 0xfa, 0x41, 0xcd, 0xeb, 0xb8, 0x80, 0x05, 0x17, 0x5d, 0xf4, 0xa3, 0xc9, 0xc4, 0x64, 0x23, 0x01, 0x45, 0x61, 0x11, 0x5a, 0xa8 } +, + /* Seed */ + 92, + { 0xcb, 0x8e, 0x0f, 0xf4, 0x1b, 0xab, 0x01, 0xa1, 0x42, 0xf9, 0x6e, 0x7d, 0x7c, 0xd3, 0x92, 0x82, 0x0a, 0x82, 0xa1, 0x73, 0x66, 0x74, 0xb9, 0x21, 0x35, 0xef, 0x33, 0x08, 0x96, 0x88, 0xdd, 0x30, 0xb2, 0xc2, 0xf7, 0xba, 0x11, 0x1a, 0xf7, 0x8d, 0x3f, 0x76, 0xa3, 0x7f, 0x66, 0x7d, 0xb3, 0x97, 0x5f, 0xce, 0x64, 0xec, 0x9a, 0xfb, 0x09, 0x68, 0x50, 0x7f, 0x7b, 0x31, 0x09, 0x7e, 0xaa, 0xe4, 0x88, 0x1b, 0x36, 0x24, 0x06, 0x56, 0x16, 0xca, 0x09, 0x0c, 0x20, 0x4c, 0x1f, 0xa4, 0xbe, 0x13, 0x48, 0x50, 0xea, 0x5e, 0x90, 0xfe, 0xcd, 0xc8, 0x45, 0xb9, 0xd8, 0x39 } +, + /* Encryption */ + 129, + { 0x4c, 0x7a, 0xc8, 0x12, 0x45, 0xe7, 0xd4, 0xde, 0x3c, 0x4d, 0xbf, 0xb3, 0x15, 0xc4, 0x68, 0x34, 0x1c, 0xbf, 0x22, 0x87, 0x57, 0x35, 0xc5, 0xf8, 0x05, 0x90, 0x50, 0x58, 0x53, 0x06, 0x8d, 0x6b, 0xe7, 0x03, 0x9b, 0x1c, 0xee, 0x6d, 0x07, 0xec, 0xb7, 0x66, 0x9c, 0x42, 0xf6, 0xb9, 0x2f, 0x2a, 0x71, 0xf6, 0x45, 0xf7, 0x2c, 0xba, 0xff, 0x76, 0x34, 0x16, 0x37, 0xd2, 0xf1, 0xd6, 0xb1, 0xfe, 0xce, 0xb0, 0x7f, 0x21, 0xe1, 0x4c, 0x70, 0xfb, 0x77, 0xbc, 0x7f, 0x87, 0xb0, 0x31, 0xc2, 0xc8, 0xf2, 0xad, 0xa4, 0xec, 0x43, 0xe9, 0x12, 0x68, 0x2c, 0x2f, 0x49, 0x63, 0x9e, 0x75, 0x71, 0x57, 0x18, 0x77, 0xfc, 0x48, 0x1c, 0xbf, 0x26, 0x98, 0xb3, 0x73, 0x15, 0xbd, 0x4b, 0x93, 0x07, 0x83, 0xf4, 0x79, 0x45, 0x64, 0x2b, 0x7d, 0x81, 0x5e, 0x04, 0x32, 0xd4, 0x5d, 0xd1, 0xd0, 0xd3, 0xb2, 0xa5 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.7", + /* Message */ + 51, + { 0xa0, 0xda, 0xab, 0x4f, 0x9f, 0xe0, 0x4a, 0x2a, 0x51, 0xbf, 0x08, 0x32, 0x70, 0x11, 0x5d, 0x0d, 0x06, 0xdc, 0x29, 0x21, 0xcf, 0x8d, 0xd1, 0x3f, 0x5c, 0xff, 0x26, 0x04, 0xbc, 0x55, 0x1e, 0xfd, 0x98, 0x3d, 0x9b, 0x25, 0xb7, 0x27, 0x4f, 0x3c, 0xcb, 0x0a, 0xdc, 0xc1, 0x1b, 0x1a, 0x39, 0x54, 0xab, 0x9d, 0xb4 } +, + /* Seed */ + 75, + { 0xc8, 0x1d, 0x1c, 0x02, 0xf0, 0x6e, 0x7f, 0xfd, 0x6e, 0x03, 0xb8, 0x1b, 0x71, 0x93, 0xaa, 0xbd, 0xac, 0x56, 0x63, 0xab, 0x14, 0x25, 0xa6, 0x7d, 0x1a, 0x29, 0x50, 0x88, 0x5f, 0x5d, 0x1c, 0x4b, 0x72, 0x5e, 0x20, 0x9d, 0xcb, 0xce, 0x9f, 0x7b, 0xf2, 0x96, 0x75, 0x23, 0x42, 0xf1, 0x84, 0xfe, 0xa0, 0x6a, 0x7d, 0x6c, 0xb2, 0xbd, 0x39, 0xb2, 0xa3, 0x18, 0x07, 0x51, 0x64, 0xa2, 0xe7, 0x61, 0xb7, 0x02, 0x70, 0x2b, 0x01, 0x92, 0x46, 0xc1, 0xe5, 0x0e, 0x6e } +, + /* Encryption */ + 129, + { 0x06, 0xc0, 0x6c, 0x97, 0x5f, 0xc6, 0xb9, 0xc2, 0x60, 0xd3, 0xd8, 0x81, 0x3b, 0x57, 0x14, 0x24, 0x8b, 0xeb, 0x39, 0x9b, 0x7d, 0x68, 0xfc, 0xac, 0x25, 0x03, 0x38, 0xca, 0xc5, 0x4c, 0x40, 0x72, 0x95, 0x9f, 0x62, 0x03, 0x84, 0x44, 0xe9, 0xe6, 0x66, 0xba, 0xb5, 0xf9, 0x36, 0x06, 0x70, 0x47, 0xbc, 0xaf, 0x4b, 0xa4, 0xed, 0x68, 0xc6, 0xc8, 0x18, 0x57, 0x46, 0x29, 0x32, 0x56, 0xe7, 0xc7, 0x24, 0x16, 0x65, 0x81, 0x54, 0xde, 0xc0, 0x67, 0xf4, 0x25, 0x0d, 0xc6, 0xb2, 0x9b, 0xba, 0xc1, 0x8e, 0x82, 0x1e, 0x49, 0xa4, 0xc9, 0xb1, 0x63, 0x83, 0x1f, 0x7b, 0xb3, 0x83, 0x92, 0x32, 0x6c, 0x6b, 0x46, 0x85, 0x46, 0x4f, 0xe4, 0xf0, 0x26, 0xc9, 0xae, 0x4d, 0xbc, 0x58, 0x49, 0x47, 0x7b, 0x4c, 0x26, 0x0a, 0xa4, 0xac, 0x02, 0xd2, 0x1a, 0x26, 0x40, 0x20, 0xf1, 0x0c, 0xa1, 0x1b, 0x4b, 0x0e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.8", + /* Message */ + 51, + { 0x74, 0x3c, 0xdd, 0xb3, 0x61, 0xc0, 0xbb, 0x32, 0x47, 0x64, 0x95, 0xad, 0x5d, 0xc6, 0x3a, 0x2b, 0xce, 0x5f, 0xba, 0xc1, 0xc8, 0xc2, 0x03, 0x93, 0x69, 0x32, 0x67, 0xd8, 0x43, 0xf2, 0x8b, 0x8c, 0xf3, 0xea, 0x13, 0xe3, 0x74, 0xe0, 0x9d, 0x0a, 0xa3, 0xf7, 0xae, 0x5d, 0x8f, 0x72, 0xd8, 0xe6, 0xcb, 0x9d, 0xbd } +, + /* Seed */ + 75, + { 0xf7, 0x2e, 0xd2, 0xd0, 0x69, 0xb8, 0xae, 0x50, 0x27, 0x04, 0x6e, 0x03, 0x27, 0xb9, 0x87, 0x84, 0x58, 0x09, 0xb4, 0xe8, 0x16, 0xc8, 0x86, 0x58, 0x24, 0xfc, 0x4a, 0x23, 0x01, 0xb4, 0x56, 0x80, 0x2b, 0x18, 0x9c, 0xbb, 0x43, 0xf0, 0x48, 0x32, 0xac, 0x25, 0xc8, 0x48, 0xd7, 0x4f, 0xbe, 0x1d, 0x62, 0x5a, 0xa9, 0x8a, 0xe0, 0x5e, 0xb6, 0x25, 0x47, 0x76, 0x1c, 0x78, 0xb8, 0x17, 0x61, 0xc3, 0x03, 0xf9, 0x3d, 0xf3, 0xfc, 0x0f, 0xea, 0x3c, 0x5a, 0x7b, 0xb1 } +, + /* Encryption */ + 129, + { 0x38, 0x3e, 0xbb, 0xf1, 0x59, 0xe1, 0xd0, 0xa2, 0x1c, 0x74, 0xeb, 0x61, 0xe3, 0x64, 0x3c, 0xb6, 0x31, 0xbe, 0x18, 0xc7, 0xa2, 0xa5, 0x4e, 0x24, 0x89, 0x33, 0x58, 0x7d, 0x34, 0x5e, 0x99, 0x52, 0x72, 0x46, 0x6d, 0xc1, 0xbd, 0x61, 0x3a, 0xdd, 0xb4, 0xcd, 0x7b, 0xa5, 0x01, 0x92, 0xfc, 0x2d, 0x89, 0x4d, 0x7f, 0xda, 0xf7, 0x83, 0x63, 0xb0, 0x79, 0xd9, 0x98, 0x01, 0x9f, 0x16, 0x42, 0x31, 0xcc, 0x2d, 0x75, 0x2d, 0xb7, 0x6a, 0x9f, 0x9d, 0x0c, 0x52, 0x04, 0xbf, 0xb0, 0xf9, 0x93, 0x05, 0x53, 0x09, 0x6b, 0x5b, 0x76, 0x80, 0xb0, 0x89, 0x4f, 0xb9, 0x9c, 0x11, 0x42, 0x5c, 0x67, 0xd6, 0x5d, 0x96, 0x5e, 0x35, 0x12, 0x8e, 0x15, 0x47, 0x46, 0xb3, 0xfe, 0xd8, 0xd0, 0x16, 0x99, 0x30, 0x70, 0xa7, 0x0e, 0x07, 0xeb, 0xeb, 0xe0, 0x6f, 0x2f, 0x4e, 0x97, 0x6c, 0x9a, 0x63, 0xfb, 0xe3, 0x20 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.9", + /* Message */ + 58, + { 0xe5, 0x31, 0x92, 0xfe, 0xbc, 0xd3, 0x69, 0x58, 0xbd, 0x08, 0x03, 0xf2, 0xea, 0x0a, 0xfd, 0xbf, 0xdf, 0x99, 0x3b, 0x58, 0xa9, 0xe4, 0xee, 0x70, 0xdf, 0x95, 0xb0, 0x6d, 0x4e, 0x7d, 0x74, 0xb6, 0x74, 0x5b, 0x87, 0xf5, 0x81, 0xf3, 0x42, 0xf8, 0xae, 0xf9, 0xae, 0x4c, 0x31, 0x82, 0xc4, 0x19, 0x9b, 0x65, 0x51, 0xfe, 0x18, 0xf8, 0xd3, 0xb9, 0xff, 0xe4 } +, + /* Seed */ + 68, + { 0xad, 0x98, 0x2f, 0xa7, 0x29, 0xf2, 0x7f, 0xce, 0x8a, 0x67, 0x49, 0x03, 0xec, 0xac, 0x69, 0x4d, 0xd3, 0x34, 0x13, 0xc7, 0x8e, 0x34, 0x28, 0xae, 0xed, 0x46, 0x9f, 0x84, 0xd9, 0x57, 0x5c, 0x6d, 0xa2, 0x75, 0x29, 0xf2, 0xc1, 0x4b, 0x53, 0xb7, 0x58, 0xd2, 0x0f, 0xb6, 0xb2, 0x47, 0xc8, 0x29, 0xc5, 0xfb, 0x1a, 0x16, 0xaf, 0x55, 0x07, 0x9a, 0x70, 0x73, 0xcc, 0xa0, 0x56, 0x25, 0x96, 0x2b, 0x6d, 0x1a, 0x6b, 0xef } +, + /* Encryption */ + 129, + { 0x22, 0x1d, 0x88, 0xa8, 0x6c, 0x9e, 0xd3, 0x7a, 0xa0, 0x9c, 0xf5, 0x72, 0x54, 0x97, 0x82, 0xe5, 0x8c, 0xa8, 0xd4, 0x85, 0x1f, 0x01, 0x6a, 0xcf, 0x28, 0x9e, 0xe8, 0xbf, 0x23, 0x79, 0x0b, 0x1a, 0x8f, 0x14, 0x8c, 0x16, 0x55, 0x08, 0xbc, 0x3f, 0xdb, 0x1e, 0xf9, 0xc9, 0x01, 0x16, 0x27, 0x42, 0x7c, 0x5f, 0x32, 0xe5, 0xca, 0xb8, 0x50, 0xcb, 0x6b, 0xc0, 0xbc, 0x04, 0xa1, 0x1d, 0xa2, 0xf0, 0x18, 0x13, 0xf3, 0x41, 0x41, 0x7b, 0x3e, 0x63, 0x2b, 0xca, 0xe0, 0x02, 0x97, 0x7d, 0x64, 0xff, 0xc9, 0x62, 0xc7, 0xfa, 0x75, 0x72, 0xf5, 0x6d, 0x26, 0x17, 0xe2, 0xa5, 0x2d, 0x3e, 0xf9, 0x17, 0xc4, 0x4a, 0x33, 0xb7, 0x15, 0x82, 0xaf, 0xf1, 0x39, 0x0b, 0x7c, 0x77, 0x4d, 0x60, 0x7c, 0x8d, 0x57, 0x8f, 0x7b, 0xc9, 0x0b, 0x35, 0x80, 0xd7, 0x7b, 0x03, 0x73, 0x19, 0x14, 0x77, 0xbc, 0x14, 0x26 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.10", + /* Message */ + 25, + { 0xd0, 0xeb, 0x48, 0x0e, 0x27, 0x45, 0x77, 0x9c, 0x8a, 0x30, 0xfe, 0x82, 0x0a, 0xef, 0x56, 0xd4, 0xce, 0x39, 0xef, 0x84, 0xea, 0x40, 0xc7, 0xdf, 0x0c } +, + /* Seed */ + 101, + { 0x46, 0x5f, 0x91, 0xe3, 0xf0, 0x7c, 0xb7, 0x22, 0x83, 0xbc, 0x2b, 0xbe, 0x52, 0x8b, 0x9a, 0xb3, 0x68, 0x16, 0x54, 0xfe, 0x20, 0xb6, 0x1a, 0x33, 0xf1, 0x23, 0xad, 0xe5, 0x2e, 0x83, 0x2f, 0xfa, 0x8a, 0x1b, 0x74, 0xa4, 0x44, 0x3c, 0xc8, 0x92, 0x95, 0xa2, 0x1a, 0x2a, 0xac, 0x98, 0x74, 0xda, 0x0a, 0x56, 0x79, 0xd1, 0x8c, 0xb5, 0xc4, 0xcd, 0x69, 0x0b, 0xd0, 0xa2, 0x0c, 0xbd, 0x9e, 0x9a, 0xa0, 0x72, 0xaa, 0x87, 0x13, 0x44, 0x8f, 0x95, 0xe5, 0xd6, 0xa6, 0xe6, 0x24, 0xd5, 0xb9, 0x08, 0x5c, 0xfc, 0xec, 0xb7, 0x99, 0x2f, 0x10, 0xea, 0x2d, 0xa6, 0xd6, 0x26, 0xeb, 0xe5, 0x43, 0xd8, 0x70, 0x22, 0x36, 0xee, 0x6c } +, + /* Encryption */ + 129, + { 0x06, 0xf3, 0xf8, 0xc7, 0x0d, 0x0f, 0xc4, 0xe7, 0x44, 0x73, 0xe6, 0x8f, 0xd2, 0x3c, 0xc9, 0xdf, 0x1e, 0xdd, 0x42, 0x35, 0xb4, 0x28, 0xb7, 0x72, 0xa0, 0x83, 0xb4, 0x1c, 0x34, 0x51, 0x62, 0x5a, 0x6f, 0x15, 0xde, 0xa4, 0xbf, 0x31, 0x3b, 0xf4, 0xf0, 0x3f, 0xdc, 0x4f, 0xe9, 0xf6, 0xa2, 0x07, 0x1a, 0xc6, 0x9a, 0xa3, 0xf0, 0xfc, 0x41, 0x57, 0xef, 0xc6, 0x21, 0xf9, 0x59, 0x40, 0x61, 0xf6, 0xc1, 0x98, 0x06, 0xbd, 0x5d, 0x75, 0x9a, 0xd0, 0x23, 0xca, 0xd1, 0x48, 0xe4, 0x47, 0xd2, 0x59, 0xb6, 0x2b, 0xf7, 0x34, 0x25, 0x91, 0xbe, 0x83, 0xba, 0xec, 0x77, 0x71, 0x4c, 0xfe, 0x2b, 0x90, 0x1f, 0x36, 0x9a, 0xea, 0x68, 0x02, 0x48, 0xba, 0xbf, 0x06, 0x87, 0x10, 0xcb, 0xb9, 0x70, 0x48, 0x4f, 0x32, 0x4a, 0x23, 0x52, 0x53, 0xa3, 0x1e, 0x02, 0x25, 0x34, 0xab, 0xec, 0x7b, 0x39, 0x96, 0x06 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.11", + /* Message */ + 27, + { 0x1c, 0x42, 0x97, 0xf6, 0xdf, 0xc0, 0x7f, 0xfe, 0x57, 0x59, 0xaa, 0x1e, 0xaa, 0x5b, 0x79, 0x37, 0x8a, 0xfc, 0xdd, 0x1a, 0x9a, 0x33, 0xa2, 0x13, 0x3a, 0x39, 0xac } +, + /* Seed */ + 99, + { 0xa7, 0xaf, 0x2a, 0x86, 0x01, 0xe4, 0x08, 0xc3, 0x18, 0xfd, 0x1e, 0x0f, 0x82, 0x44, 0x5b, 0x50, 0x95, 0x44, 0xd5, 0xec, 0x97, 0xa7, 0x95, 0x8f, 0x59, 0x4b, 0x20, 0x54, 0xc5, 0x09, 0xf7, 0xef, 0xfd, 0xd4, 0x16, 0x30, 0x6b, 0x2b, 0x2c, 0x91, 0xb5, 0xa6, 0x37, 0xa1, 0x56, 0x82, 0x0d, 0x60, 0x1a, 0x23, 0xff, 0xdb, 0x31, 0xfb, 0x35, 0xd3, 0x05, 0xaa, 0x93, 0x74, 0x57, 0x8e, 0xef, 0xb8, 0x10, 0x2e, 0x8b, 0x72, 0x44, 0x19, 0x1f, 0x4e, 0xc7, 0x4a, 0xa2, 0x6a, 0x0b, 0x7d, 0xb3, 0x6c, 0xab, 0x44, 0x99, 0x9c, 0x81, 0xb3, 0x61, 0x57, 0x01, 0x6b, 0x55, 0x89, 0x06, 0xe5, 0xd7, 0x08, 0x8d, 0x51, 0x32 } +, + /* Encryption */ + 129, + { 0x3c, 0xdf, 0x2d, 0xc6, 0x7a, 0x4a, 0xa5, 0x31, 0xcf, 0xa1, 0x42, 0x80, 0x08, 0xbd, 0x05, 0x44, 0xab, 0xbd, 0x03, 0x29, 0x22, 0xdc, 0xc2, 0x43, 0x6d, 0xa0, 0xb5, 0xd7, 0xef, 0x9a, 0x70, 0x17, 0xe6, 0x19, 0x3a, 0x8b, 0xaf, 0x38, 0xc5, 0x8e, 0x91, 0x96, 0x2d, 0x65, 0xa3, 0x75, 0xf0, 0x8c, 0x1d, 0x55, 0x57, 0x9c, 0xf9, 0x4a, 0x79, 0x5c, 0x9c, 0x70, 0xb6, 0xe4, 0x2e, 0x16, 0x43, 0xce, 0xf5, 0x40, 0xdc, 0xe1, 0xe9, 0x86, 0xdd, 0x99, 0x88, 0x87, 0xb6, 0x95, 0x52, 0x44, 0x4b, 0x6d, 0xe9, 0x3b, 0xa7, 0xd5, 0xf7, 0x64, 0x83, 0x54, 0xbf, 0xcb, 0x70, 0x21, 0x39, 0xed, 0x39, 0x54, 0x94, 0x7d, 0x7b, 0x18, 0x0b, 0x6c, 0x02, 0xbc, 0xad, 0x82, 0x43, 0xa0, 0xab, 0x27, 0xca, 0x66, 0x52, 0x76, 0x29, 0x1b, 0x46, 0xcc, 0x31, 0x8d, 0xa9, 0xb5, 0xf6, 0x0a, 0x04, 0xaf, 0xfe, 0xbc, 0xb0 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.12", + /* Message */ + 16, + { 0x00, 0x92, 0x7f, 0xca, 0x7f, 0x5e, 0xc7, 0x6f, 0x54, 0x8d, 0xd4, 0x82, 0x63, 0xe3, 0x39, 0xbe } +, + /* Seed */ + 110, + { 0xde, 0xbc, 0x2c, 0x1f, 0x22, 0xd9, 0x32, 0xff, 0xcb, 0x89, 0x7c, 0xf1, 0x0a, 0xe6, 0x2c, 0x3e, 0x05, 0x1e, 0x3f, 0x78, 0x46, 0x3a, 0xe6, 0x7d, 0x95, 0x61, 0xcf, 0x1a, 0x73, 0xd5, 0x5c, 0x4b, 0x14, 0xac, 0xa6, 0xc2, 0x1d, 0x83, 0xba, 0xf9, 0x76, 0xcd, 0x8b, 0xf2, 0x46, 0xc2, 0x29, 0x78, 0x61, 0xa6, 0xb1, 0xe9, 0xc9, 0xef, 0x30, 0x81, 0xc5, 0x1c, 0x4b, 0x68, 0x7c, 0x67, 0xb5, 0xdd, 0x0f, 0xe0, 0xf7, 0x55, 0x3f, 0x73, 0x8c, 0x2c, 0x8a, 0x5f, 0x81, 0xd1, 0x26, 0x8a, 0x0c, 0x2d, 0x4a, 0x46, 0x1d, 0x63, 0x5b, 0x0e, 0x59, 0xd2, 0x3b, 0xa4, 0x17, 0xab, 0xb8, 0x04, 0x5e, 0x9c, 0x10, 0xd6, 0x6b, 0x0e, 0xc8, 0x92, 0xf9, 0x53, 0xc6, 0xf2, 0x11, 0xf0, 0x2f, 0xf0 } +, + /* Encryption */ + 129, + { 0x49, 0xb9, 0x20, 0x89, 0xb5, 0x2a, 0xb7, 0x8c, 0x33, 0xb5, 0xbb, 0x30, 0x32, 0xcf, 0x70, 0x24, 0x94, 0x4a, 0xc6, 0x8e, 0x13, 0x9d, 0x2d, 0x56, 0x06, 0x8c, 0x7a, 0x26, 0x2a, 0x53, 0xe7, 0x80, 0x9f, 0xb5, 0xb0, 0x15, 0x65, 0xcc, 0x65, 0x61, 0xd7, 0x13, 0x30, 0x46, 0x87, 0x52, 0x30, 0xac, 0x21, 0x75, 0x64, 0x72, 0x96, 0xcf, 0x2b, 0x48, 0x47, 0xe1, 0x2b, 0x73, 0x63, 0x19, 0x72, 0x53, 0x21, 0xbe, 0xa2, 0x64, 0x75, 0x7d, 0xe0, 0xeb, 0x49, 0x88, 0x72, 0xd8, 0x9a, 0x4d, 0x7c, 0xe4, 0xa1, 0xbd, 0xb7, 0x33, 0x5d, 0xae, 0xa7, 0x8b, 0xa1, 0x96, 0xfd, 0x50, 0xd9, 0x03, 0x82, 0xe6, 0xd6, 0x2f, 0x8d, 0xf7, 0xae, 0x68, 0x5a, 0x1d, 0xfc, 0x84, 0x9e, 0x11, 0x99, 0x7d, 0xee, 0x88, 0x60, 0xd1, 0x0f, 0x70, 0x7b, 0x0d, 0x35, 0x36, 0x5a, 0x81, 0x24, 0x30, 0x73, 0x1e, 0x7a, 0x50, 0x8d } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.13", + /* Message */ + 26, + { 0x8b, 0x6d, 0xf2, 0xd6, 0xda, 0x63, 0x1a, 0xc8, 0xd5, 0x55, 0x6a, 0x26, 0x97, 0x54, 0x28, 0xfc, 0x4d, 0x20, 0xef, 0x5b, 0x4a, 0x1f, 0x06, 0x8e, 0xd2, 0xe5 } +, + /* Seed */ + 100, + { 0xff, 0x2c, 0x06, 0x98, 0x85, 0x2d, 0x1b, 0x0a, 0xe3, 0xc5, 0xc5, 0xc9, 0xbe, 0x26, 0xe8, 0x3c, 0x90, 0x44, 0x84, 0x2c, 0x16, 0x07, 0xf5, 0xf4, 0x08, 0x6a, 0x6d, 0x6c, 0xf1, 0x08, 0xad, 0xca, 0x61, 0xea, 0xf6, 0x65, 0x40, 0x0d, 0x7c, 0xff, 0x2a, 0x3a, 0xda, 0xdf, 0xaf, 0xd8, 0x0c, 0x64, 0x95, 0x6d, 0xa2, 0xd7, 0xd7, 0xc1, 0x35, 0xab, 0xf5, 0xa0, 0xd1, 0x76, 0x06, 0x25, 0x56, 0xeb, 0x4d, 0x8b, 0x75, 0xb9, 0x5c, 0xd1, 0x1e, 0xa9, 0xc0, 0x44, 0x2f, 0x84, 0x6f, 0x03, 0x7d, 0xa8, 0x77, 0x29, 0x02, 0xbf, 0xfc, 0xde, 0x65, 0x59, 0xe1, 0xb5, 0x9e, 0x60, 0xc6, 0xd0, 0xf9, 0x89, 0x6b, 0xa5, 0xc3, 0xc4 } +, + /* Encryption */ + 129, + { 0x41, 0x52, 0x76, 0x69, 0x80, 0x33, 0x39, 0xeb, 0xd8, 0xf2, 0xd1, 0xcc, 0x18, 0x6c, 0x7e, 0x8e, 0xbb, 0x80, 0xcf, 0x4b, 0x94, 0x9d, 0x8a, 0x28, 0x43, 0x65, 0x32, 0x9f, 0x3c, 0xe4, 0x6e, 0xbd, 0xac, 0x0a, 0x96, 0x9f, 0x67, 0x61, 0x90, 0x0c, 0xfe, 0x34, 0x2b, 0xc8, 0x4c, 0x7d, 0x69, 0x51, 0xac, 0xcf, 0x45, 0x28, 0x0b, 0xaf, 0x24, 0xa0, 0xcb, 0xb2, 0x42, 0xa9, 0x42, 0x18, 0xef, 0x9f, 0xd3, 0x71, 0xb1, 0xe0, 0x08, 0x24, 0x62, 0x62, 0x07, 0x0b, 0xf5, 0x54, 0xed, 0x57, 0x00, 0x7b, 0x97, 0x39, 0x79, 0x16, 0x35, 0x86, 0x1d, 0x86, 0xc6, 0x5b, 0x1a, 0x82, 0x56, 0xf4, 0x25, 0xf9, 0xf3, 0xae, 0x51, 0x9e, 0x1b, 0x1b, 0xdc, 0x58, 0x75, 0xb8, 0x78, 0xdd, 0xcf, 0xc1, 0x47, 0x0f, 0xee, 0xf2, 0xae, 0xeb, 0x01, 0x4b, 0x7e, 0x33, 0xef, 0xb9, 0xf4, 0xdd, 0x07, 0x83, 0xd1, 0x71, 0x23 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.14", + /* Message */ + 44, + { 0xea, 0x03, 0x96, 0x69, 0xbc, 0xd7, 0xa8, 0xcd, 0xce, 0xab, 0x58, 0x55, 0x91, 0xb5, 0x63, 0x61, 0xe9, 0x0b, 0xda, 0x0e, 0xa4, 0x40, 0x10, 0x49, 0x64, 0xe8, 0x89, 0xec, 0xe1, 0x8a, 0xeb, 0x04, 0xce, 0x0a, 0xb5, 0xb1, 0xcc, 0xb2, 0x30, 0xae, 0x03, 0x25, 0x5a, 0x39 } +, + /* Seed */ + 82, + { 0x20, 0x4f, 0xae, 0xb3, 0x13, 0x96, 0x5c, 0xc1, 0xa1, 0x8f, 0xaf, 0x10, 0x39, 0xfd, 0xde, 0x68, 0x1b, 0xc4, 0x3b, 0x22, 0x3e, 0x28, 0xbc, 0x47, 0x1c, 0x50, 0x42, 0x3d, 0xa0, 0xbd, 0x79, 0x7d, 0x6a, 0x8c, 0x73, 0x8c, 0x54, 0x03, 0x3c, 0x8e, 0x55, 0x9e, 0xa2, 0xd1, 0x0c, 0x3b, 0x79, 0xb8, 0x0e, 0x2e, 0xfd, 0xec, 0xfe, 0x89, 0x1c, 0xea, 0x2e, 0xcb, 0x34, 0x51, 0xa1, 0xa8, 0xe2, 0xec, 0x2f, 0x44, 0x7b, 0x79, 0x8d, 0x7d, 0xe5, 0x64, 0x1b, 0xda, 0x4a, 0xa9, 0x90, 0xb3, 0x01, 0xe1, 0xdd, 0xe7 } +, + /* Encryption */ + 129, + { 0x4c, 0xa1, 0xc8, 0x5c, 0xe3, 0xc6, 0x20, 0xd4, 0x29, 0x91, 0xcf, 0x41, 0x73, 0x3e, 0xad, 0x26, 0xa0, 0x93, 0x11, 0x18, 0x5f, 0xff, 0xe5, 0x8f, 0x41, 0x28, 0x8f, 0x6d, 0x0b, 0xb6, 0x84, 0x5b, 0x2d, 0x5a, 0xcf, 0x1a, 0xa0, 0x6c, 0x78, 0xd7, 0x1f, 0x76, 0x93, 0x96, 0xa9, 0x43, 0x42, 0x03, 0xe3, 0x8b, 0xb0, 0x1f, 0xd8, 0x8e, 0xb2, 0x3e, 0x6b, 0xc5, 0x1b, 0xa0, 0xc5, 0xf3, 0xee, 0xb3, 0x27, 0x13, 0xca, 0xd4, 0xd0, 0x87, 0x80, 0x50, 0x61, 0xab, 0x47, 0x3a, 0x15, 0x67, 0xe7, 0x9b, 0xbf, 0x4e, 0xae, 0x49, 0x36, 0xf1, 0x8d, 0x02, 0x05, 0xb3, 0x74, 0x6a, 0x17, 0xe0, 0x64, 0x8c, 0x52, 0x22, 0x3d, 0xd9, 0xf9, 0x99, 0x72, 0x81, 0xb5, 0x35, 0xab, 0x2f, 0xb3, 0xcf, 0xf0, 0x3c, 0xa8, 0x90, 0xf7, 0x10, 0xaa, 0x88, 0xfd, 0x2d, 0x0f, 0x39, 0x2f, 0xf4, 0xa8, 0x8d, 0x31, 0x1a, 0xa1 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.15", + /* Message */ + 5, + { 0x0f, 0x46, 0x2b, 0xeb, 0xc6 } +, + /* Seed */ + 121, + { 0x4e, 0xae, 0x5d, 0x54, 0x92, 0xd9, 0x44, 0xff, 0xdb, 0x04, 0x2a, 0xd9, 0x50, 0x16, 0x81, 0xad, 0xb3, 0xeb, 0x6a, 0xb5, 0x28, 0xb6, 0xe8, 0x13, 0x53, 0x55, 0xb6, 0x23, 0xab, 0x55, 0xa7, 0x40, 0x87, 0xb1, 0x9f, 0xc5, 0x9b, 0x85, 0x34, 0xda, 0x9a, 0x88, 0xda, 0x29, 0xf6, 0x6f, 0x71, 0xf9, 0x45, 0x2a, 0xed, 0xe0, 0xe3, 0xe9, 0x39, 0x07, 0x70, 0x9c, 0x34, 0x49, 0x56, 0x72, 0x85, 0x74, 0xb6, 0x6f, 0xb9, 0xa6, 0xf3, 0x38, 0x3d, 0x58, 0xa0, 0x13, 0x6f, 0x94, 0xc4, 0xed, 0x86, 0xca, 0x9d, 0xd3, 0x8b, 0xff, 0x07, 0x0f, 0xcc, 0x2d, 0xef, 0x29, 0xbd, 0xd6, 0xfc, 0x98, 0x59, 0x70, 0x96, 0x7f, 0x02, 0xfd, 0x6f, 0x93, 0x01, 0xcd, 0x56, 0xd0, 0x48, 0xa4, 0x42, 0xd7, 0x02, 0x40, 0x9a, 0x98, 0xa1, 0x32, 0xab, 0x6b, 0xed, 0xd4, 0xfe } +, + /* Encryption */ + 129, + { 0x29, 0x36, 0x9e, 0xb0, 0x0a, 0x3f, 0x87, 0x84, 0x38, 0xc9, 0x38, 0xf9, 0xd7, 0xbd, 0xa3, 0x85, 0x6c, 0x45, 0xa6, 0xd7, 0x7c, 0x17, 0x88, 0x51, 0x1b, 0x98, 0x2c, 0x58, 0xf6, 0x3d, 0xbe, 0xa3, 0x3e, 0x63, 0xae, 0x1d, 0x45, 0xc2, 0xdf, 0x6b, 0xa8, 0x0f, 0x0d, 0xe9, 0x97, 0x59, 0x2e, 0x1f, 0x8a, 0x3b, 0x3a, 0x09, 0xed, 0x76, 0x06, 0x51, 0x45, 0x3e, 0x10, 0x99, 0x78, 0xcf, 0xde, 0x3a, 0x60, 0x0a, 0x74, 0xfa, 0xa8, 0xa9, 0x1b, 0x7c, 0x72, 0x4f, 0x97, 0x3c, 0xb8, 0x0b, 0x96, 0x83, 0x5f, 0x05, 0x0b, 0x7d, 0xc0, 0x9d, 0x2f, 0x15, 0x74, 0x76, 0xc5, 0xb7, 0x05, 0x1f, 0x94, 0xd9, 0xc0, 0xf3, 0x17, 0xe1, 0xf1, 0x88, 0xe3, 0x09, 0x80, 0x79, 0x5b, 0x09, 0x6c, 0xf9, 0xbb, 0xce, 0xb5, 0x63, 0x6b, 0x3d, 0xb9, 0x87, 0x05, 0x4a, 0x56, 0x08, 0x75, 0x22, 0x75, 0x96, 0x29, 0x97, 0xe7 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.16", + /* Message */ + 45, + { 0x51, 0x4d, 0x3b, 0x38, 0x00, 0x22, 0xb3, 0x78, 0x2e, 0x8a, 0x77, 0xd7, 0x7b, 0xf2, 0x4a, 0xfd, 0xf9, 0x2f, 0x33, 0x97, 0x47, 0x4d, 0xae, 0x0d, 0x4b, 0xd6, 0xe4, 0xfa, 0x31, 0xca, 0x60, 0x83, 0xdf, 0x49, 0x6b, 0x36, 0x62, 0x6e, 0x7f, 0x8e, 0x1c, 0x91, 0x9f, 0x9f, 0x2e } +, + /* Seed */ + 81, + { 0xd4, 0xd3, 0xa9, 0xe8, 0xfb, 0xeb, 0x1d, 0xc6, 0x07, 0xb4, 0xdd, 0x78, 0x87, 0xba, 0x25, 0xc3, 0xd0, 0xbd, 0x81, 0x34, 0x84, 0xbd, 0x53, 0x76, 0xdc, 0x83, 0xef, 0xb5, 0x8e, 0xc5, 0xb2, 0x56, 0x2c, 0xb4, 0x4f, 0x98, 0x5e, 0x59, 0xf5, 0x0b, 0x9a, 0xde, 0x3c, 0x66, 0x71, 0x6c, 0xc6, 0xf4, 0x2e, 0x51, 0xc6, 0x0a, 0x2f, 0x4d, 0x8d, 0x75, 0xbf, 0xb9, 0xb8, 0x24, 0x10, 0x5d, 0x1e, 0xe1, 0x58, 0x35, 0xf5, 0xf5, 0xf2, 0x54, 0xfc, 0x6f, 0x68, 0x0e, 0xee, 0x0b, 0x85, 0xaf, 0x54, 0x7c, 0x17 } +, + /* Encryption */ + 129, + { 0x19, 0xfb, 0x39, 0x1a, 0x31, 0x00, 0x87, 0xbc, 0x3d, 0x08, 0x79, 0x1f, 0xd5, 0x99, 0x94, 0xbe, 0x80, 0x12, 0xdf, 0xfd, 0x76, 0xa0, 0x2a, 0xdb, 0xd4, 0x79, 0xcc, 0x0c, 0x15, 0x56, 0x60, 0x5d, 0x4d, 0xa2, 0xa3, 0x46, 0x1c, 0x7c, 0x71, 0xa8, 0x5e, 0xd8, 0xcf, 0x85, 0xe0, 0x8f, 0x45, 0xda, 0xde, 0x51, 0x8c, 0x00, 0xaf, 0x09, 0xf4, 0x93, 0xee, 0x8a, 0x55, 0x46, 0xff, 0xbe, 0xfb, 0x05, 0x3c, 0xca, 0x2e, 0xef, 0x06, 0x84, 0x76, 0x3c, 0xf7, 0x80, 0xf2, 0xe0, 0x97, 0xbd, 0x8e, 0x5c, 0x2e, 0xa8, 0x4c, 0xb1, 0xa8, 0xb8, 0xf8, 0x49, 0x6c, 0xc9, 0x18, 0x16, 0x7f, 0x65, 0x6c, 0xdc, 0x9e, 0x1d, 0x3b, 0x2a, 0x23, 0x38, 0xb6, 0x4c, 0x61, 0xe9, 0x0e, 0xcc, 0x27, 0x4a, 0x12, 0x10, 0xe3, 0xdb, 0x57, 0x83, 0xae, 0x3c, 0x00, 0xab, 0xd3, 0x74, 0x8a, 0x81, 0x0f, 0xd9, 0x14, 0x91, 0x14 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.17", + /* Message */ + 55, + { 0xfb, 0xa1, 0x63, 0x17, 0xb0, 0x93, 0x08, 0x3e, 0x37, 0x20, 0xaa, 0x06, 0x48, 0x17, 0xe7, 0x4c, 0xa7, 0x51, 0xa5, 0x17, 0x87, 0x4b, 0x69, 0x26, 0x50, 0xc4, 0x14, 0x7f, 0x11, 0x9f, 0x68, 0x90, 0x70, 0x2c, 0xf8, 0xb1, 0x4f, 0x0c, 0x18, 0x82, 0x21, 0x2d, 0x72, 0x40, 0x6c, 0x3a, 0x45, 0xd7, 0xd9, 0xff, 0xa4, 0x31, 0x24, 0x10, 0xa6 } +, + /* Seed */ + 71, + { 0x9c, 0xc9, 0xa4, 0xbf, 0x8c, 0xc2, 0x75, 0xa6, 0xb9, 0xb1, 0x35, 0x10, 0x31, 0x91, 0x10, 0x91, 0x7a, 0xd8, 0x53, 0x24, 0xc5, 0xa4, 0x34, 0x5e, 0x58, 0xf1, 0xfa, 0x47, 0x27, 0x5e, 0xe5, 0x92, 0x15, 0x69, 0xdc, 0xbc, 0xbd, 0x72, 0x36, 0x70, 0xcf, 0x4a, 0x24, 0xeb, 0xcd, 0x57, 0xf5, 0x7e, 0x99, 0x8c, 0x4b, 0xbd, 0x4a, 0x95, 0x67, 0x9d, 0x60, 0xba, 0xa0, 0xab, 0xe8, 0x79, 0x66, 0x8a, 0x2c, 0xb6, 0xed, 0x0f, 0xb9, 0x4e, 0x4a } +, + /* Encryption */ + 129, + { 0x4c, 0x41, 0xb9, 0xcb, 0xcc, 0x6f, 0xa8, 0x7f, 0x23, 0xf1, 0x7a, 0x36, 0xd0, 0x51, 0xe7, 0x78, 0x0a, 0x07, 0x06, 0x56, 0xca, 0xe7, 0xbe, 0xba, 0x14, 0xfa, 0x91, 0xc5, 0x55, 0xb8, 0x58, 0x8e, 0x88, 0x09, 0xe7, 0xd3, 0x35, 0x4e, 0x7e, 0xf5, 0xe0, 0xfa, 0xef, 0xe1, 0xcf, 0x39, 0x2e, 0x6f, 0xda, 0xd4, 0x04, 0x4a, 0xef, 0x08, 0xe3, 0x3e, 0x6f, 0xc2, 0x01, 0xc5, 0x47, 0xfd, 0xbd, 0xf7, 0xc7, 0x3d, 0x3b, 0xe0, 0x96, 0xed, 0x25, 0x3f, 0x9d, 0xf4, 0xaf, 0x52, 0xe1, 0x3b, 0x9a, 0x19, 0x25, 0xaa, 0x73, 0x93, 0xa6, 0x42, 0x95, 0x30, 0x20, 0x92, 0x01, 0xe5, 0x5b, 0x20, 0xe5, 0x1d, 0x50, 0x05, 0xd0, 0x6b, 0x58, 0x35, 0x3b, 0xfa, 0xfc, 0xee, 0xc3, 0x7d, 0x60, 0xe1, 0xca, 0x0d, 0x9d, 0xdd, 0xd8, 0x68, 0x0b, 0xd0, 0xa5, 0xd6, 0x92, 0xe7, 0x4f, 0x2d, 0xbd, 0xfc, 0xe2, 0x66, 0x02 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.18", + /* Message */ + 53, + { 0x5f, 0xfe, 0x82, 0xe0, 0x33, 0x54, 0x42, 0x45, 0xb8, 0x49, 0x62, 0xd3, 0x92, 0x7c, 0x2f, 0xa5, 0x99, 0x72, 0xef, 0x59, 0xc2, 0x37, 0xa3, 0x86, 0xa5, 0x1b, 0xd0, 0xba, 0x1f, 0x2c, 0x1f, 0x8e, 0x45, 0xb4, 0x6a, 0x05, 0xad, 0x97, 0xdb, 0x49, 0xd3, 0xac, 0xc6, 0x34, 0x4f, 0x1e, 0xda, 0xdf, 0x65, 0x64, 0xc2, 0x8c, 0xe1 } +, + /* Seed */ + 73, + { 0xcc, 0x23, 0x59, 0xbf, 0xd0, 0xd5, 0x7b, 0xce, 0xbf, 0x07, 0x5b, 0x87, 0xa5, 0x85, 0xa9, 0xbd, 0xe6, 0x59, 0x3e, 0xb2, 0x49, 0x61, 0xef, 0xf1, 0x98, 0x7e, 0x73, 0x56, 0x05, 0xd4, 0xe3, 0x0e, 0x97, 0x19, 0x37, 0xf6, 0xf3, 0xf5, 0xbe, 0x52, 0x78, 0xfd, 0x47, 0x6d, 0xc6, 0x60, 0xee, 0x07, 0x30, 0xcd, 0x07, 0xe5, 0xd1, 0xf4, 0x20, 0x09, 0xa3, 0x33, 0x31, 0x2d, 0x93, 0x28, 0xf3, 0xb0, 0x08, 0x5c, 0x40, 0x75, 0xbc, 0x70, 0x9a, 0x10, 0xf1 } +, + /* Encryption */ + 129, + { 0x05, 0x8b, 0x50, 0xe0, 0xbc, 0xa6, 0xb9, 0x34, 0xc0, 0x1b, 0xf7, 0xc3, 0x3b, 0xb6, 0x15, 0xb7, 0x22, 0xea, 0x41, 0x80, 0x7a, 0x7d, 0x2c, 0x7c, 0xb3, 0xd4, 0x38, 0xe2, 0x8d, 0xbe, 0x33, 0x3e, 0xd6, 0xd8, 0x37, 0x47, 0x7a, 0xf8, 0x4b, 0xb0, 0x06, 0xbb, 0xb1, 0x0b, 0x36, 0x94, 0x4f, 0x15, 0xd4, 0xf6, 0xd2, 0x8b, 0x5e, 0xd2, 0x49, 0xd5, 0x69, 0x0c, 0x08, 0x37, 0xa1, 0x6e, 0x15, 0x7b, 0xa8, 0x80, 0x22, 0x74, 0x10, 0x1c, 0xd4, 0x4e, 0x7f, 0xed, 0x72, 0xa7, 0x59, 0x81, 0xc9, 0x75, 0x66, 0xbc, 0x70, 0xe5, 0x55, 0x97, 0x02, 0xbf, 0x5b, 0x62, 0xfb, 0x09, 0xb2, 0x13, 0x60, 0x56, 0x73, 0xaa, 0xeb, 0xb7, 0xfe, 0x9b, 0x1a, 0xe6, 0xd8, 0x04, 0x03, 0xa2, 0x01, 0x33, 0x80, 0x3e, 0x1e, 0xd2, 0x35, 0x0b, 0x8e, 0x15, 0xff, 0x01, 0x9a, 0x70, 0x0f, 0x2a, 0xbe, 0x87, 0xd6, 0xe7, 0x33 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.19", + /* Message */ + 49, + { 0x22, 0x63, 0x3c, 0xc3, 0xfe, 0x7a, 0x7b, 0x4f, 0x00, 0xfa, 0x99, 0x9c, 0x4f, 0xe0, 0xd8, 0x82, 0xc3, 0x1b, 0xdc, 0x0d, 0x67, 0x0c, 0x0c, 0xc3, 0xd2, 0x88, 0x96, 0x1f, 0xbe, 0x63, 0x72, 0xe0, 0xe5, 0x32, 0x46, 0x42, 0xc7, 0xb1, 0xfa, 0x85, 0x2e, 0x1b, 0x4f, 0x69, 0x6f, 0x12, 0xf5, 0x58, 0x66 } +, + /* Seed */ + 77, + { 0x3e, 0xdf, 0xca, 0xf4, 0x88, 0x71, 0xd2, 0x91, 0xd5, 0xb7, 0xf7, 0x72, 0x3d, 0x92, 0xd9, 0x51, 0x51, 0x52, 0xb6, 0xbf, 0x52, 0xb8, 0x23, 0x69, 0x9c, 0x58, 0x8f, 0x75, 0xf3, 0x4e, 0x37, 0x95, 0x55, 0x0d, 0x07, 0x81, 0x18, 0xe2, 0x86, 0xc9, 0x6e, 0x90, 0x07, 0xae, 0xe1, 0x54, 0xf5, 0x7c, 0xe7, 0xf1, 0xd4, 0x60, 0x39, 0x47, 0x3a, 0x4a, 0x37, 0xa9, 0xb5, 0x90, 0xa3, 0x7e, 0xea, 0x59, 0x94, 0x7f, 0xe8, 0x58, 0x7c, 0x95, 0x69, 0x88, 0xbc, 0xb1, 0x74, 0xe9, 0x7c } +, + /* Encryption */ + 129, + { 0x3d, 0xeb, 0xbc, 0x6c, 0xfb, 0x0e, 0xed, 0x87, 0x16, 0x6b, 0xcc, 0xd5, 0x4c, 0x75, 0x97, 0xad, 0x36, 0xca, 0x0a, 0xc9, 0x6c, 0xf1, 0x66, 0x76, 0xe1, 0x87, 0x4b, 0xf5, 0xf1, 0x0a, 0x0e, 0xc6, 0x9c, 0x3b, 0xe2, 0x25, 0x96, 0x78, 0xee, 0xa6, 0x3a, 0x18, 0x08, 0xd9, 0x06, 0x65, 0xff, 0xce, 0x9a, 0xf0, 0x82, 0x7e, 0xe6, 0x29, 0xed, 0xd6, 0x59, 0x43, 0x43, 0x7f, 0x8c, 0xa0, 0xa6, 0x71, 0x17, 0x2c, 0x52, 0x1c, 0xc0, 0xd1, 0xdd, 0x01, 0xe2, 0x2f, 0x20, 0xa6, 0xc7, 0x9c, 0x42, 0x7a, 0xda, 0x88, 0x56, 0x00, 0x0c, 0x4e, 0x03, 0x5d, 0x9c, 0x5e, 0xf2, 0xe1, 0x05, 0xf2, 0xc9, 0xf6, 0x45, 0x7d, 0x9e, 0xe9, 0x5b, 0x43, 0xbc, 0x4b, 0xe3, 0x29, 0x4a, 0x0e, 0xe1, 0xd5, 0xc8, 0x33, 0xae, 0x91, 0x07, 0x8a, 0xed, 0x09, 0xe7, 0x92, 0xbb, 0x42, 0xc2, 0x5e, 0x00, 0xb0, 0x87, 0xe5, 0x61 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 13.20", + /* Message */ + 63, + { 0x55, 0x2b, 0x38, 0x4c, 0x5e, 0x51, 0x74, 0xf5, 0x1f, 0x38, 0x0d, 0x8b, 0x53, 0xe3, 0xc8, 0x97, 0xb4, 0x8c, 0x66, 0x9a, 0x9c, 0x2d, 0x11, 0x98, 0x5b, 0x86, 0x54, 0xde, 0x7f, 0x76, 0xd9, 0x62, 0x39, 0x6a, 0x37, 0xb9, 0x53, 0x41, 0xf9, 0x9d, 0xec, 0xe4, 0xaf, 0xd7, 0x1d, 0x3c, 0x84, 0xe1, 0x28, 0x7b, 0x0f, 0x0f, 0x86, 0xee, 0xff, 0xcf, 0xd9, 0x7b, 0xa1, 0x88, 0xe3, 0x79, 0x9e } +, + /* Seed */ + 63, + { 0x2e, 0x2f, 0x3e, 0x3f, 0x46, 0xd4, 0x74, 0x0c, 0xb2, 0x6c, 0xbc, 0x65, 0xaa, 0xe2, 0xaf, 0xe4, 0x9d, 0x0b, 0xe6, 0x66, 0x39, 0xd0, 0xdb, 0x10, 0xdf, 0xd6, 0xaf, 0x60, 0x64, 0x46, 0xf3, 0xb7, 0xde, 0x98, 0x21, 0x2f, 0x86, 0x17, 0x4b, 0xdf, 0xa5, 0xb2, 0xe2, 0x35, 0x85, 0x07, 0x45, 0x3c, 0x20, 0xad, 0xa6, 0x9a, 0x4f, 0xfe, 0x0a, 0x35, 0xe1, 0x2e, 0xfb, 0xab, 0x3b, 0xb4, 0x4c } +, + /* Encryption */ + 129, + { 0x14, 0x92, 0x91, 0xee, 0xb5, 0x36, 0xfc, 0x07, 0x03, 0xf7, 0xbd, 0xf1, 0xf0, 0x31, 0xa4, 0x30, 0xcc, 0x83, 0xad, 0xc4, 0x3e, 0x09, 0x68, 0x64, 0x91, 0x26, 0x69, 0x34, 0xef, 0x37, 0xea, 0xea, 0xb1, 0x1b, 0xc7, 0xf3, 0x91, 0x49, 0xab, 0x33, 0x43, 0x66, 0x94, 0x59, 0x36, 0x73, 0xcc, 0xc6, 0x39, 0x0b, 0x52, 0x9e, 0x64, 0xd3, 0x42, 0xe9, 0xf2, 0x1d, 0x17, 0x6d, 0xa2, 0x1f, 0xa6, 0x5a, 0xbd, 0x57, 0xee, 0xc6, 0x0d, 0xde, 0xc7, 0xd1, 0xa0, 0x93, 0xdb, 0xa3, 0x76, 0x44, 0x5f, 0x1b, 0xcf, 0xe5, 0xa6, 0xaa, 0xce, 0x9f, 0x13, 0x42, 0xaf, 0x39, 0xdb, 0x8a, 0xd4, 0x85, 0xba, 0x22, 0x2d, 0x39, 0x12, 0x62, 0x28, 0xfa, 0xee, 0xb4, 0x9b, 0xb3, 0xb2, 0x71, 0xfd, 0x38, 0xe1, 0x15, 0x25, 0xd8, 0x03, 0x15, 0x4e, 0x74, 0x08, 0x4b, 0x75, 0xc3, 0xdb, 0xcd, 0xff, 0x2e, 0x3d, 0x10, 0x42 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 14: A 1536-bit RSA key pair", +{ + /* Modulus */ + 192, + { 0xbe, 0x0c, 0xa0, 0x1f, 0x9c, 0x17, 0x21, 0x66, 0xf9, 0x12, 0x39, 0x1e, 0x5d, 0x58, 0xdd, 0xc3, 0x0d, 0x5d, 0xd0, 0x27, 0x9a, 0x49, 0xbb, 0x31, 0x2a, 0x31, 0xe4, 0xc8, 0xa6, 0x6a, 0x52, 0xfb, 0x4e, 0x8b, 0x67, 0x42, 0xfa, 0xac, 0xb2, 0x24, 0xc3, 0x03, 0x9f, 0x1e, 0x19, 0x8f, 0x33, 0x23, 0xb8, 0x88, 0xba, 0x0e, 0x35, 0xbb, 0x94, 0xc5, 0x11, 0xbd, 0x22, 0xb8, 0x86, 0x40, 0x5a, 0x71, 0x5e, 0x40, 0x9d, 0xe3, 0xbc, 0xeb, 0x4f, 0xc9, 0x91, 0x1b, 0x0e, 0x9c, 0x3b, 0x1e, 0x42, 0xe2, 0x57, 0xd5, 0xbb, 0xea, 0x07, 0x22, 0xb5, 0xd5, 0xdd, 0x35, 0x37, 0x56, 0x9d, 0xc7, 0x56, 0x06, 0x46, 0xa7, 0x50, 0xb8, 0x7e, 0xaa, 0x6f, 0x3a, 0x40, 0x5a, 0x94, 0xbf, 0x2a, 0xda, 0x72, 0xb5, 0x0a, 0x4b, 0x01, 0x87, 0xbb, 0x9d, 0x00, 0xec, 0x45, 0x1d, 0x50, 0xa6, 0xa9, 0x1a, 0x1e, 0x2a, 0x91, 0x19, 0x2a, 0x7f, 0xd7, 0x56, 0xb9, 0x00, 0x14, 0x1f, 0xe8, 0x8f, 0x96, 0xe2, 0x08, 0x0d, 0xfd, 0xd8, 0x01, 0x66, 0xa7, 0xbf, 0x67, 0xe3, 0x71, 0x44, 0xd0, 0x9e, 0x3a, 0xf8, 0x99, 0x74, 0xe5, 0x7c, 0x72, 0xb0, 0x3a, 0x2b, 0x88, 0xfd, 0x29, 0x95, 0x25, 0x2a, 0xce, 0x4f, 0x30, 0xe2, 0xe4, 0x7c, 0x28, 0x18, 0x05, 0x72, 0x40, 0x53, 0x6b, 0x58, 0xdb, 0x42, 0x07, 0x50, 0x9e, 0x59 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 191, + { 0xf3, 0x7d, 0x28, 0xd6, 0x1f, 0x28, 0x99, 0xa5, 0xc0, 0xe0, 0xa0, 0x74, 0x9d, 0x13, 0x89, 0x38, 0x7c, 0x64, 0xc8, 0xc3, 0x58, 0xa9, 0x71, 0xda, 0xd1, 0x3c, 0xff, 0x85, 0xc5, 0x9a, 0x62, 0xdd, 0xa7, 0xbb, 0xc0, 0xf7, 0xe5, 0xbd, 0xc6, 0x5d, 0xff, 0x9d, 0xe9, 0xc7, 0x45, 0x40, 0x46, 0x31, 0x75, 0x81, 0x48, 0x16, 0x8d, 0xfe, 0x6a, 0xc0, 0xa2, 0x87, 0x6a, 0x56, 0x05, 0x3b, 0xab, 0x2a, 0x2a, 0x9f, 0xf2, 0x72, 0x79, 0x4d, 0xd5, 0xd8, 0x13, 0x9e, 0xed, 0x10, 0xbc, 0xfb, 0x4d, 0xf3, 0x30, 0x20, 0xd5, 0x9e, 0x30, 0x48, 0xfd, 0x2f, 0x0c, 0x43, 0x14, 0x26, 0x14, 0x5e, 0x36, 0xa1, 0xd0, 0xa6, 0xbf, 0xce, 0x44, 0x43, 0xef, 0x3c, 0x7e, 0x31, 0xd4, 0xa9, 0x2f, 0xb8, 0x51, 0x7a, 0x49, 0xf7, 0x88, 0xc3, 0xb4, 0xe1, 0x37, 0x39, 0x5a, 0x4b, 0xee, 0xea, 0x63, 0xe0, 0xe0, 0xad, 0xc3, 0x22, 0x4f, 0x98, 0x09, 0x25, 0x03, 0x7d, 0xf6, 0xf5, 0xb2, 0x6c, 0x00, 0x72, 0x39, 0xb4, 0xf0, 0x1f, 0x8a, 0x9a, 0x61, 0xea, 0x0b, 0x51, 0x19, 0xbc, 0x9d, 0x54, 0x96, 0xa9, 0x5b, 0x60, 0xea, 0x76, 0x6c, 0xcb, 0xad, 0xe0, 0x37, 0xe3, 0x40, 0x32, 0x4f, 0x25, 0xf0, 0x2e, 0x72, 0x45, 0xc2, 0x36, 0xea, 0xe4, 0x36, 0x7a, 0x64, 0x68, 0xa7, 0xa0, 0x93, 0x8d, 0x85, 0xc0, 0xa1 } +, + /* Prime 1 */ + 96, + { 0xdf, 0xcc, 0x92, 0x74, 0x2c, 0x48, 0xd3, 0x34, 0xc6, 0x6f, 0xca, 0xa6, 0xd8, 0xa7, 0xe4, 0x22, 0x54, 0x43, 0x0f, 0x80, 0xa8, 0x35, 0x9e, 0xa2, 0x3b, 0x9a, 0x83, 0xb2, 0x41, 0xe4, 0x7f, 0x39, 0x9b, 0x3f, 0xfe, 0x3d, 0xab, 0x3f, 0x15, 0xbe, 0x8f, 0xa5, 0xc9, 0xe6, 0x46, 0xdf, 0xf9, 0x7c, 0xcf, 0x9b, 0x43, 0x17, 0x61, 0x07, 0x80, 0xad, 0x44, 0xcb, 0x1f, 0xbc, 0xef, 0xbd, 0x6e, 0xba, 0x05, 0x5d, 0x96, 0x94, 0x3c, 0x02, 0x47, 0xe0, 0xc8, 0x76, 0x78, 0xeb, 0x0b, 0xf7, 0x6c, 0x88, 0x76, 0xc3, 0xab, 0xb9, 0xef, 0x72, 0xcf, 0x01, 0x8f, 0x58, 0x11, 0xa6, 0xbe, 0xe0, 0x4f, 0x09 } +, + /* Prime 2 */ + 96, + { 0xd9, 0x64, 0xe9, 0x6e, 0xa6, 0xfa, 0x43, 0x70, 0xb5, 0x91, 0xee, 0x79, 0xe7, 0xe7, 0x2e, 0xcc, 0x21, 0x81, 0x53, 0x78, 0x7a, 0x60, 0xe2, 0xf7, 0xae, 0x94, 0xfa, 0x95, 0xb9, 0xbd, 0x68, 0x69, 0xd2, 0x81, 0xac, 0x3c, 0xcf, 0xb6, 0x57, 0x24, 0x7c, 0x58, 0x3e, 0xaf, 0xdc, 0x13, 0xd4, 0xd7, 0xa7, 0xd7, 0x76, 0x5e, 0x44, 0x67, 0xdf, 0x76, 0xb5, 0x28, 0xbf, 0x94, 0xbd, 0x03, 0xa3, 0xea, 0x73, 0xb8, 0x1b, 0xe2, 0x6c, 0xca, 0xd9, 0x89, 0xb9, 0xf0, 0x77, 0x28, 0xda, 0xd5, 0x3b, 0x38, 0xef, 0x7f, 0xe9, 0xeb, 0xe9, 0x11, 0x40, 0xcb, 0xad, 0x17, 0xdc, 0x7e, 0xcb, 0x1d, 0x58, 0xd1 } +, + /* Prime exponent 1 */ + 96, + { 0x9e, 0x79, 0xf6, 0x9b, 0x5d, 0x60, 0x94, 0x6f, 0x22, 0xb5, 0xb7, 0x03, 0x3f, 0x18, 0x64, 0x6c, 0x0a, 0xcf, 0x12, 0x03, 0x41, 0x19, 0xf7, 0x23, 0x5a, 0xa1, 0xa7, 0xf0, 0x6a, 0xc8, 0xab, 0x6e, 0xd7, 0x89, 0x11, 0x38, 0x0a, 0x33, 0xb9, 0xea, 0x1f, 0x3e, 0x7f, 0x22, 0x19, 0xbe, 0x30, 0xa5, 0x39, 0x3d, 0xf0, 0xdc, 0x75, 0x51, 0x22, 0xc5, 0x8f, 0x99, 0x66, 0xf8, 0x1b, 0xac, 0x40, 0xe4, 0x69, 0x38, 0x44, 0x90, 0xe3, 0x8d, 0x99, 0xe8, 0x8b, 0x0b, 0x99, 0xc4, 0x97, 0xcc, 0xb5, 0x86, 0x4c, 0xd3, 0x72, 0x9f, 0x4f, 0xf8, 0x34, 0xae, 0x1e, 0x1b, 0x77, 0x24, 0x64, 0xb5, 0xe2, 0x41 } +, + /* Prime exponent 2 */ + 96, + { 0x3a, 0x05, 0xe9, 0x18, 0x13, 0x91, 0x30, 0x76, 0xe0, 0xbf, 0x76, 0x7b, 0x2b, 0x1e, 0x55, 0x2b, 0x3e, 0xb6, 0x19, 0xe5, 0x4a, 0x24, 0x99, 0xef, 0xa9, 0xb5, 0x31, 0xbc, 0xcc, 0xba, 0x75, 0x27, 0xe9, 0x7b, 0x9a, 0xd1, 0x10, 0x4f, 0x86, 0xaa, 0xc2, 0x55, 0x7b, 0x45, 0xcc, 0xe3, 0xae, 0x27, 0x71, 0x30, 0xdc, 0xf3, 0x04, 0x27, 0x05, 0x49, 0xd5, 0xc8, 0x6e, 0x79, 0xf0, 0x89, 0x0c, 0x33, 0x03, 0x77, 0xdc, 0x59, 0x6e, 0xd8, 0x25, 0x7f, 0xd1, 0x15, 0x11, 0x78, 0xe2, 0x0f, 0x8f, 0xa2, 0xfe, 0xa9, 0x91, 0x71, 0xd9, 0xdf, 0x35, 0x00, 0x27, 0xce, 0xfa, 0x97, 0x0c, 0xf7, 0x64, 0x41 } +, + /* Coefficient */ + 96, + { 0x18, 0xb1, 0x0d, 0xd7, 0x3b, 0x14, 0x7d, 0x86, 0xb6, 0x0c, 0xf7, 0xfe, 0xbf, 0x46, 0x35, 0x93, 0xc0, 0xbd, 0xd6, 0xbc, 0x83, 0xa8, 0x39, 0x57, 0x3b, 0x4b, 0x3f, 0xe6, 0x5c, 0x0b, 0x13, 0xe7, 0xb6, 0x94, 0xb8, 0x1a, 0x56, 0x57, 0x21, 0x0b, 0xe9, 0x47, 0x01, 0x1d, 0x8d, 0x49, 0x29, 0xc1, 0x27, 0xfd, 0x2f, 0x3e, 0x31, 0x06, 0xc2, 0x53, 0x38, 0x3b, 0xe6, 0x35, 0x41, 0xd1, 0x23, 0x5b, 0xd7, 0x9c, 0x57, 0x2e, 0x92, 0xe2, 0x36, 0x34, 0x28, 0x20, 0x98, 0xbe, 0xe9, 0x4d, 0x48, 0xbd, 0x62, 0x8a, 0x0e, 0xb2, 0x1e, 0xd2, 0x61, 0xcf, 0xa3, 0x5b, 0x69, 0xb9, 0x77, 0x70, 0xe2, 0x93 } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 14.1", + /* Message */ + 9, + { 0x2b, 0xd6, 0xe3, 0xc1, 0xde, 0xfd, 0xdd, 0x5a, 0x43 } +, + /* Seed */ + 180, + { 0xe7, 0x84, 0xd5, 0x25, 0x03, 0xe6, 0x29, 0x1f, 0x25, 0x8e, 0x44, 0x2d, 0xb5, 0x77, 0xf9, 0x91, 0x63, 0x82, 0xa0, 0xd1, 0x4c, 0x7b, 0x9d, 0xcc, 0xbd, 0xb6, 0x07, 0xaf, 0x01, 0xf0, 0x25, 0x8f, 0xdc, 0x97, 0x23, 0x97, 0xda, 0x12, 0x39, 0xd4, 0x44, 0x9a, 0x58, 0x28, 0x6e, 0xce, 0x20, 0x08, 0xf7, 0x18, 0xf6, 0x90, 0xce, 0xe7, 0x3a, 0x02, 0x7f, 0xab, 0xf8, 0x4b, 0xdf, 0x7a, 0xce, 0x45, 0xf7, 0xed, 0x2d, 0x77, 0x32, 0x4c, 0xbe, 0xe9, 0x0e, 0xcc, 0x6f, 0x1e, 0x7b, 0x86, 0xcc, 0x29, 0x35, 0xa4, 0x7b, 0xa1, 0x56, 0x65, 0x0b, 0x42, 0xfc, 0x71, 0xaa, 0xd0, 0x70, 0x99, 0xa2, 0x7e, 0x97, 0xfe, 0x5a, 0x3f, 0x25, 0xfe, 0x13, 0x48, 0xe4, 0x42, 0x39, 0x12, 0x12, 0xa5, 0xcf, 0x1b, 0x44, 0x5a, 0x1e, 0x70, 0x19, 0x1f, 0xfa, 0x8f, 0xca, 0xde, 0x63, 0x5d, 0x2e, 0x44, 0x65, 0xf5, 0xf9, 0x13, 0xc5, 0x3e, 0x33, 0xb5, 0x91, 0x52, 0xcd, 0x8a, 0x14, 0x97, 0x84, 0xf2, 0x7d, 0x83, 0x18, 0x28, 0xaf, 0x2d, 0x66, 0x6a, 0x5c, 0x30, 0x9b, 0x56, 0xd0, 0x71, 0x9c, 0xfd, 0x80, 0x73, 0x40, 0x69, 0xa2, 0x3e, 0x09, 0x2d, 0x83, 0x15, 0x39, 0x9f, 0x95, 0xc4, 0x0a, 0xd7, 0xfd, 0x0b, 0xb5, 0xf9, 0x43, 0x77 } +, + /* Encryption */ + 192, + { 0x85, 0xef, 0x3e, 0x47, 0x76, 0x77, 0xbf, 0x76, 0x07, 0x1a, 0x27, 0xbb, 0xc7, 0x39, 0x57, 0x15, 0xcb, 0x35, 0x07, 0x96, 0xe4, 0x4f, 0x1b, 0x52, 0xa0, 0x8e, 0x90, 0x5e, 0x08, 0xff, 0x12, 0x56, 0x70, 0x5a, 0x9b, 0xf0, 0x15, 0x2e, 0x87, 0x2b, 0xdc, 0x74, 0xbb, 0x1f, 0x2f, 0xc8, 0x63, 0x1e, 0xf8, 0x81, 0x2d, 0x16, 0x94, 0x6a, 0x30, 0xb5, 0x8f, 0x44, 0x64, 0xd6, 0xe7, 0xb2, 0x45, 0x0b, 0xe4, 0x5b, 0x48, 0xcc, 0xff, 0x5d, 0x8e, 0xcf, 0x7a, 0x00, 0xb1, 0xb7, 0x8f, 0xc8, 0xfa, 0x54, 0x71, 0x3d, 0xd6, 0x96, 0xa1, 0x4a, 0xcb, 0x68, 0x00, 0xc0, 0xd3, 0xb6, 0x9a, 0x0b, 0x44, 0x43, 0x77, 0xfa, 0x30, 0x3a, 0x7d, 0x66, 0xdb, 0x49, 0x27, 0x91, 0x8a, 0x4b, 0xfb, 0x0f, 0xd4, 0x93, 0xbf, 0xaa, 0x01, 0x6a, 0xeb, 0xff, 0x99, 0x53, 0x30, 0xa6, 0xdc, 0xb6, 0x21, 0x5d, 0xd3, 0xbd, 0xb3, 0x5d, 0x7c, 0xd6, 0x1c, 0xcf, 0x0e, 0x9c, 0xcc, 0xbf, 0x51, 0xe9, 0xea, 0x65, 0x8e, 0xa3, 0x1d, 0x12, 0x43, 0x44, 0x4c, 0x4b, 0x72, 0xff, 0xf0, 0x1a, 0xc9, 0x3f, 0x28, 0xeb, 0x7f, 0x67, 0xc1, 0x83, 0x2e, 0x56, 0x8e, 0xd7, 0x2f, 0xd9, 0x57, 0xd5, 0xb4, 0xfd, 0x2f, 0x00, 0xb6, 0x02, 0x31, 0x71, 0xb8, 0x5a, 0xb0, 0xca, 0xa1, 0x03, 0x0e, 0xd3, 0xe3, 0xed, 0xc9, 0x50, 0x31, 0x45 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 14.2", + /* Message */ + 43, + { 0x10, 0x47, 0x35, 0xd9, 0xad, 0x72, 0x60, 0x46, 0x47, 0x3d, 0xf4, 0xb1, 0x3b, 0x2f, 0x5f, 0xa2, 0x85, 0xc3, 0xd2, 0x33, 0xec, 0xd4, 0x61, 0x70, 0x58, 0x2d, 0xd2, 0x28, 0xcd, 0xee, 0x46, 0x4d, 0xa5, 0x09, 0x5e, 0x20, 0x8c, 0xf8, 0xfb, 0xca, 0x05, 0x38, 0x8b } +, + /* Seed */ + 146, + { 0xdc, 0x6a, 0x63, 0x1e, 0x29, 0x75, 0x45, 0xd2, 0xf6, 0xfe, 0x9c, 0x69, 0xa5, 0xd3, 0x06, 0xa1, 0x09, 0x16, 0xd7, 0xe7, 0xef, 0x0d, 0xc9, 0x53, 0xf2, 0x1b, 0x6a, 0x04, 0x14, 0x31, 0xec, 0x8b, 0xa5, 0xce, 0x1c, 0x13, 0x87, 0x43, 0xfa, 0xac, 0x54, 0x97, 0xd6, 0x99, 0xf2, 0xff, 0x1d, 0x4a, 0x44, 0xa3, 0xe0, 0x63, 0x7c, 0xc5, 0xe5, 0xe6, 0x38, 0xcd, 0x73, 0x67, 0x7d, 0x09, 0xaf, 0xee, 0x3e, 0xc9, 0xfe, 0x80, 0x52, 0x94, 0x7a, 0x73, 0x33, 0x4c, 0x32, 0x70, 0x47, 0x28, 0x56, 0xf3, 0x07, 0x24, 0x3a, 0xc5, 0x8b, 0xf8, 0x63, 0x80, 0x74, 0x66, 0x7d, 0x7f, 0x7c, 0x18, 0xe3, 0xab, 0x32, 0x7e, 0xa3, 0xfc, 0x78, 0x91, 0xf1, 0xc5, 0x8a, 0xb4, 0x7e, 0x4f, 0xfa, 0x6e, 0x7d, 0x90, 0x11, 0xa3, 0x3d, 0x9b, 0x40, 0xa2, 0xd7, 0x89, 0xee, 0x42, 0x21, 0x25, 0x62, 0x30, 0xca, 0x8a, 0x61, 0x81, 0x1b, 0x09, 0x72, 0xcf, 0xd9, 0x86, 0x01, 0x75, 0x26, 0x18, 0x1d, 0x24, 0xee, 0xbb, 0x32, 0xcc } +, + /* Encryption */ + 192, + { 0x92, 0x1d, 0x2b, 0x02, 0x6d, 0x6b, 0x7e, 0x22, 0x20, 0x1d, 0xe7, 0x7f, 0xbf, 0x67, 0x99, 0x90, 0xf9, 0xaf, 0xf4, 0xea, 0x7f, 0xe7, 0xce, 0x45, 0x02, 0x21, 0x5f, 0x9e, 0x7a, 0xa4, 0x18, 0xb8, 0x5f, 0x72, 0xea, 0xdb, 0x6b, 0x69, 0x42, 0xbb, 0x08, 0xa0, 0x8b, 0xe7, 0xda, 0x66, 0x19, 0xaa, 0x5f, 0x1d, 0x2f, 0xf9, 0x61, 0xc9, 0xdc, 0x2c, 0x34, 0x1a, 0xe3, 0x2a, 0x25, 0x4f, 0xde, 0xab, 0xa2, 0xf6, 0x45, 0x0a, 0xc4, 0x47, 0x4b, 0x62, 0x74, 0xf0, 0xc3, 0x46, 0xf2, 0x6d, 0xa4, 0xed, 0x55, 0x5a, 0x8c, 0x95, 0x11, 0x89, 0xdc, 0x83, 0x69, 0xf3, 0x4d, 0x76, 0xd8, 0x37, 0xd6, 0xf3, 0x8a, 0x95, 0x18, 0xa6, 0x27, 0x1c, 0x5b, 0x56, 0x34, 0x62, 0x25, 0xa5, 0xab, 0x8d, 0xa6, 0x03, 0x2a, 0x59, 0x30, 0xfd, 0x5b, 0x77, 0x72, 0x9d, 0xe6, 0x32, 0xe1, 0x75, 0x2f, 0xc7, 0x2a, 0x0c, 0x34, 0xae, 0xce, 0x25, 0x65, 0x7b, 0x28, 0x1b, 0xe8, 0x93, 0x2c, 0x56, 0x50, 0xc9, 0x82, 0xfa, 0x14, 0x5f, 0xde, 0x0b, 0xcd, 0xd4, 0x8a, 0x73, 0xaa, 0x02, 0x88, 0xb4, 0xde, 0x46, 0x11, 0x33, 0xf2, 0x7d, 0x51, 0xe3, 0x86, 0x01, 0x6a, 0x72, 0x72, 0x6a, 0x9e, 0xde, 0x1d, 0x32, 0xdf, 0xc7, 0xe6, 0xf9, 0x78, 0x0c, 0x04, 0xeb, 0x70, 0xff, 0xff, 0xc2, 0x68, 0x82, 0x95, 0x66, 0x73, 0x33 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.3", + /* Message */ + 25, + { 0x31, 0x7e, 0x6f, 0x5e, 0x17, 0x50, 0x0f, 0xe9, 0x4f, 0xdf, 0xf2, 0x84, 0xbb, 0xe5, 0x03, 0x01, 0x04, 0x4d, 0x14, 0x22, 0xd3, 0xca, 0x70, 0x05, 0x98 } +, + /* Seed */ + 164, + { 0x46, 0x6d, 0x53, 0xc8, 0xd0, 0xbb, 0x9e, 0xd4, 0x60, 0xca, 0xa6, 0x3d, 0x79, 0xbf, 0xb8, 0x77, 0xbc, 0x4e, 0xa3, 0x45, 0xca, 0xb4, 0x35, 0x7e, 0x63, 0x9a, 0x95, 0xdc, 0xae, 0x37, 0x9d, 0xdc, 0xea, 0x5d, 0x64, 0xfe, 0xe9, 0x9f, 0xb6, 0xf7, 0x5f, 0xf2, 0x4e, 0xb7, 0x4d, 0x44, 0x03, 0x44, 0xd1, 0x47, 0xe4, 0x33, 0x14, 0xa0, 0xf8, 0x9f, 0x8b, 0x96, 0x14, 0x82, 0x15, 0x36, 0x8e, 0xb8, 0x65, 0x1f, 0x6d, 0x3c, 0xa0, 0xd0, 0x8d, 0x0b, 0x4c, 0x73, 0xe6, 0xd1, 0xa7, 0x68, 0x40, 0x98, 0x26, 0xd4, 0x3c, 0x2f, 0x81, 0xf3, 0x08, 0x40, 0x60, 0x5c, 0x43, 0xd0, 0xfe, 0x67, 0x1d, 0x3f, 0x02, 0x4c, 0x70, 0xd0, 0xb8, 0x99, 0x23, 0xcf, 0x90, 0x4e, 0x39, 0x97, 0x99, 0x62, 0xcd, 0x51, 0x5c, 0x16, 0x74, 0x29, 0x2a, 0xa3, 0x0d, 0xac, 0x70, 0x0d, 0xb4, 0xeb, 0x7e, 0x63, 0xd5, 0x6f, 0xdf, 0x08, 0xc2, 0x24, 0x70, 0xf2, 0x43, 0x86, 0x19, 0x45, 0xd0, 0x0f, 0xa4, 0xe2, 0x79, 0x90, 0x21, 0x2c, 0xfe, 0xd4, 0x28, 0x5d, 0xf1, 0xed, 0xda, 0x4b, 0x0a, 0xec, 0x91, 0x35, 0x59, 0xf5, 0x9d, 0x12, 0x55, 0x90 } +, + /* Encryption */ + 192, + { 0x14, 0x1f, 0xca, 0x68, 0xdd, 0x2e, 0x4d, 0x1d, 0xe5, 0x08, 0x6d, 0xbb, 0x78, 0x5f, 0xf4, 0x7d, 0x81, 0xe3, 0x9c, 0x31, 0x1d, 0x91, 0x7a, 0x99, 0x39, 0xa6, 0xff, 0x5b, 0x13, 0x43, 0x9c, 0xa9, 0x56, 0xc9, 0x74, 0x2b, 0xcf, 0xe4, 0x50, 0xb5, 0xbd, 0x03, 0x5b, 0x54, 0x1f, 0xab, 0x30, 0x7f, 0x24, 0xfb, 0xfb, 0x3f, 0x8b, 0x90, 0x21, 0x5b, 0x56, 0x04, 0x67, 0x6e, 0x56, 0x96, 0xf3, 0xba, 0x95, 0xfd, 0xb8, 0xd0, 0x90, 0xa6, 0xc2, 0x4a, 0x29, 0xd9, 0x90, 0xfb, 0xff, 0x1d, 0xa2, 0x02, 0x81, 0x42, 0x55, 0x8f, 0x0a, 0xd7, 0x53, 0x43, 0xc7, 0x2f, 0x38, 0x82, 0x3d, 0xb7, 0x66, 0x7b, 0x05, 0xe1, 0x6b, 0x51, 0x92, 0xb9, 0x33, 0x60, 0x07, 0xf7, 0x58, 0x10, 0x6c, 0x32, 0x8b, 0xd4, 0x76, 0x11, 0x8d, 0xf8, 0x2a, 0xd0, 0x75, 0x48, 0xa7, 0x26, 0x92, 0x1f, 0xb2, 0xe1, 0x92, 0xb4, 0x3c, 0x8c, 0x30, 0xcc, 0x9b, 0x84, 0x34, 0x63, 0x0e, 0x27, 0xfd, 0x8b, 0x23, 0xef, 0x8d, 0x8f, 0x22, 0xbe, 0x7f, 0x73, 0xae, 0xcd, 0xcb, 0x2b, 0x1e, 0xc5, 0x53, 0x9d, 0x5f, 0xbb, 0x2c, 0xff, 0x9e, 0xd5, 0xe7, 0xf1, 0x9b, 0x49, 0x18, 0x3d, 0x22, 0x1d, 0xfd, 0x53, 0x7d, 0x4f, 0x37, 0x03, 0x2e, 0xf3, 0x2f, 0x63, 0xb6, 0xff, 0x74, 0xee, 0x24, 0xa0, 0x96, 0xcf, 0x45, 0x59, 0x27, 0x09 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.4", + /* Message */ + 29, + { 0x90, 0x96, 0x3d, 0xda, 0xb3, 0x78, 0x91, 0xe7, 0x28, 0x8b, 0x53, 0xbe, 0x5d, 0x9d, 0xc5, 0x67, 0xb1, 0xa0, 0x7a, 0x15, 0x66, 0xc2, 0xaf, 0xdd, 0xd7, 0x72, 0x73, 0x24, 0xba } +, + /* Seed */ + 160, + { 0xa4, 0x9f, 0x12, 0x15, 0x17, 0x5b, 0xa0, 0x4c, 0x27, 0x4a, 0xbc, 0x05, 0x1f, 0x0c, 0x17, 0xa0, 0x8a, 0x63, 0x64, 0x89, 0x43, 0xdb, 0x2e, 0x8c, 0x76, 0x22, 0xbc, 0xbb, 0x1d, 0xcc, 0x56, 0x7e, 0xbe, 0x6a, 0xdd, 0x8c, 0x44, 0x48, 0x16, 0xc9, 0xd4, 0x36, 0xee, 0x93, 0xce, 0xfe, 0x23, 0xec, 0x41, 0xdd, 0xfc, 0xb0, 0xa4, 0x03, 0xbb, 0x6d, 0xbf, 0xf0, 0xae, 0x5d, 0x6f, 0xcd, 0xd7, 0x64, 0xda, 0xc1, 0xa7, 0x2a, 0x48, 0x4f, 0x36, 0x47, 0x1f, 0x4f, 0x3b, 0xd7, 0x25, 0xb2, 0xdb, 0x5a, 0xfa, 0x6a, 0xcf, 0x53, 0x0e, 0x4e, 0x4e, 0x86, 0xb4, 0xfd, 0xa8, 0x78, 0x20, 0x47, 0x87, 0x1c, 0xb0, 0x55, 0xad, 0x68, 0xc8, 0x41, 0xde, 0x54, 0x5a, 0x55, 0x40, 0xc8, 0xcc, 0x12, 0xe7, 0xe3, 0xf1, 0x58, 0x14, 0xa0, 0x03, 0x9a, 0x81, 0x03, 0x4b, 0xde, 0x9c, 0x68, 0xae, 0x22, 0x85, 0xe6, 0x16, 0xb7, 0xb5, 0x55, 0x5f, 0x98, 0xc6, 0x13, 0xce, 0x2e, 0xf6, 0x66, 0xa0, 0x22, 0x46, 0x5c, 0x63, 0x67, 0xd0, 0xbd, 0xa4, 0x0c, 0x12, 0xe9, 0x41, 0xf6, 0x99, 0x8a, 0x14, 0xa2, 0xb5, 0xe3 } +, + /* Encryption */ + 192, + { 0x8a, 0xd5, 0xbf, 0x78, 0x23, 0x2a, 0xa3, 0x6f, 0xb7, 0x83, 0x58, 0x3e, 0x71, 0xbc, 0x13, 0x93, 0x03, 0x7d, 0x13, 0xe7, 0x74, 0x54, 0xa9, 0xdc, 0x11, 0x11, 0x43, 0x4e, 0x75, 0xdd, 0x80, 0x20, 0x46, 0xba, 0xb4, 0x20, 0x25, 0x42, 0x0c, 0x63, 0x96, 0x1e, 0xa0, 0x06, 0x26, 0x57, 0xca, 0x50, 0x65, 0xde, 0xb6, 0x53, 0xac, 0x78, 0xeb, 0x64, 0x98, 0xcf, 0x14, 0xd1, 0x70, 0x4c, 0xec, 0x59, 0x11, 0x69, 0x60, 0x8d, 0xb0, 0x1f, 0xc9, 0x3d, 0x0d, 0x68, 0xe6, 0x28, 0x01, 0xb4, 0x65, 0xa3, 0x87, 0xa9, 0xc7, 0x2f, 0x7e, 0xb3, 0x5b, 0x0b, 0xa5, 0x3a, 0x5e, 0xfa, 0x98, 0xc9, 0xf0, 0xcb, 0x7c, 0x7c, 0xba, 0x18, 0x04, 0xcd, 0x70, 0x1d, 0x02, 0x97, 0xb6, 0x60, 0x05, 0xae, 0x25, 0xec, 0x3b, 0x6c, 0xd4, 0xcf, 0x31, 0x94, 0xa3, 0xfa, 0x65, 0xd9, 0x8c, 0x4b, 0x95, 0x33, 0x30, 0x79, 0x0e, 0xfd, 0xe7, 0x4f, 0xa2, 0x75, 0xd2, 0xa7, 0x9d, 0x33, 0x10, 0xa5, 0xbc, 0xc2, 0xc8, 0x1c, 0x91, 0xfc, 0x25, 0x56, 0x2c, 0xa9, 0x39, 0xf8, 0xd9, 0xc1, 0x75, 0xed, 0xf4, 0xb0, 0x76, 0x73, 0xd5, 0x39, 0x24, 0xe2, 0x7b, 0x15, 0x52, 0x88, 0x1c, 0x10, 0x83, 0x19, 0x23, 0x71, 0x5d, 0x14, 0x9f, 0x1f, 0x31, 0x9e, 0x38, 0xe9, 0x1d, 0xfa, 0x56, 0x6c, 0x54, 0x53, 0xba, 0xcc, 0x14, 0x8b } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.5", + /* Message */ + 11, + { 0x3d, 0x81, 0x02, 0x1f, 0xf6, 0x47, 0x33, 0x37, 0xe0, 0x4b, 0x92 } +, + /* Seed */ + 178, + { 0x9b, 0x70, 0x29, 0x73, 0x13, 0x77, 0xe8, 0x26, 0x97, 0xfa, 0x56, 0xb0, 0x86, 0xce, 0x49, 0xd3, 0xc4, 0xb1, 0x54, 0x9d, 0xe8, 0x1e, 0x3e, 0x99, 0xe1, 0x6c, 0xd9, 0x72, 0x29, 0x7a, 0x56, 0x0f, 0xf4, 0x83, 0xf2, 0xef, 0x5b, 0x71, 0xb0, 0x0f, 0xc6, 0x84, 0x74, 0x4f, 0x22, 0x4e, 0x85, 0x7e, 0x6d, 0x72, 0x39, 0xf1, 0x56, 0xd7, 0xb6, 0x10, 0x2f, 0x23, 0x04, 0xf8, 0xa5, 0x50, 0x50, 0xb3, 0x75, 0x6c, 0x54, 0x8f, 0x6e, 0xa2, 0x6e, 0xa6, 0xf7, 0x39, 0x4d, 0x2b, 0xb3, 0x79, 0x33, 0x35, 0x84, 0xe3, 0xb4, 0x81, 0xd0, 0x73, 0xc0, 0xa5, 0x8a, 0x0a, 0xd7, 0x87, 0xad, 0xb4, 0x80, 0xe1, 0xf2, 0x0a, 0x1a, 0x59, 0x0e, 0x03, 0x1e, 0x6b, 0x2b, 0xb7, 0xf3, 0x6a, 0x93, 0x61, 0x0d, 0xdf, 0x70, 0x83, 0xa5, 0x07, 0x68, 0xc9, 0x98, 0x62, 0x3f, 0x6e, 0x64, 0x37, 0x6a, 0x29, 0xb4, 0xa4, 0x18, 0x03, 0x2d, 0x27, 0x39, 0xbd, 0x4e, 0x74, 0x7d, 0xdf, 0xc7, 0x7f, 0xe3, 0xcf, 0x27, 0x93, 0xa2, 0x9b, 0xc7, 0x67, 0xbf, 0xac, 0xc7, 0x13, 0xe5, 0xf1, 0x0e, 0x53, 0x1b, 0x4c, 0x71, 0x89, 0x97, 0xb9, 0xbb, 0x6b, 0x65, 0x15, 0xe0, 0x71, 0x13, 0x28, 0x89, 0x74, 0x7e, 0x54, 0x6b, 0x13, 0x46, 0x8d } +, + /* Encryption */ + 192, + { 0x1b, 0x88, 0x4b, 0x06, 0x7d, 0x0b, 0xb1, 0x59, 0x7f, 0x5f, 0xab, 0x93, 0x30, 0x95, 0x75, 0x5a, 0x53, 0x0d, 0x9d, 0x04, 0xe2, 0x75, 0x4a, 0x57, 0x97, 0xff, 0xff, 0x5e, 0xf9, 0xce, 0xf1, 0x89, 0x54, 0x99, 0x98, 0x23, 0x00, 0x50, 0x3b, 0x3f, 0xeb, 0xcb, 0xaa, 0x09, 0xd3, 0x6b, 0x7d, 0xac, 0xc3, 0x0d, 0xf3, 0xc8, 0x68, 0xf0, 0x1a, 0x5f, 0x17, 0xed, 0x4a, 0x72, 0xa8, 0x5b, 0x6a, 0xdc, 0x80, 0xa2, 0x6a, 0x1b, 0x81, 0x97, 0x6b, 0x39, 0x3c, 0xba, 0x9b, 0x0c, 0x82, 0xcb, 0x1e, 0x2c, 0x58, 0x3a, 0xb6, 0xf3, 0x14, 0xed, 0xa2, 0x9a, 0x43, 0x32, 0x21, 0xb6, 0xe3, 0xed, 0x53, 0x51, 0x53, 0x74, 0xbb, 0xcd, 0x2b, 0x96, 0xf5, 0xcb, 0x5b, 0xd5, 0x81, 0x5d, 0x1a, 0x5d, 0xcb, 0xf0, 0x80, 0xd2, 0xd3, 0x7c, 0xb9, 0x6c, 0x4d, 0x96, 0x1d, 0xc4, 0x7e, 0x13, 0x0d, 0xb7, 0xb8, 0xd0, 0x18, 0x2e, 0x33, 0x69, 0xde, 0xf4, 0xc0, 0xf6, 0xc4, 0x2c, 0x6c, 0x20, 0x53, 0x1a, 0xf1, 0xa1, 0x90, 0x36, 0xde, 0xf0, 0x8d, 0x4b, 0xac, 0xa7, 0x1b, 0x99, 0xaf, 0x3c, 0x4e, 0x1e, 0xd5, 0x27, 0xd5, 0x1f, 0x37, 0xd0, 0xee, 0x1e, 0xa2, 0xc8, 0xb8, 0xeb, 0xf4, 0xfd, 0x52, 0x79, 0x85, 0x1d, 0xc3, 0x20, 0xe7, 0x42, 0x00, 0x8e, 0x04, 0x04, 0x4d, 0x0d, 0xa0, 0x64, 0x36, 0x61, 0x3d, 0x1b } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.6", + /* Message */ + 20, + { 0x5c, 0x74, 0x5d, 0xd4, 0xa8, 0xc5, 0x92, 0x93, 0x4e, 0xd1, 0x5e, 0x22, 0xfa, 0x9d, 0xec, 0x4a, 0x4d, 0xc2, 0x0a, 0x9f } +, + /* Seed */ + 169, + { 0x0e, 0x6a, 0xbb, 0x82, 0x9a, 0x3b, 0x16, 0xd0, 0x8b, 0x0b, 0xd4, 0x3e, 0xb9, 0x5c, 0x79, 0x1a, 0xf2, 0xa3, 0x39, 0x12, 0xea, 0x83, 0x3e, 0xe6, 0x89, 0x3e, 0xd5, 0xad, 0x3e, 0xe7, 0x44, 0xc8, 0xb2, 0xdd, 0x28, 0xfc, 0xee, 0x80, 0x8d, 0x3f, 0x01, 0x49, 0x58, 0x25, 0xbe, 0x0f, 0xe6, 0x37, 0x32, 0x07, 0xa8, 0x78, 0xd4, 0xa5, 0x25, 0xea, 0x72, 0xcf, 0xb0, 0xbb, 0x58, 0xa2, 0x67, 0x76, 0xfb, 0x39, 0xee, 0xbd, 0x33, 0x5f, 0x04, 0xcf, 0x71, 0x86, 0xbe, 0x61, 0xc5, 0x63, 0x5d, 0x95, 0xe5, 0x60, 0xed, 0xdf, 0xd4, 0x5d, 0xd8, 0x6a, 0x4e, 0x67, 0x0d, 0x33, 0x56, 0x8d, 0x83, 0xd2, 0xca, 0x20, 0x3e, 0xd2, 0x8d, 0x90, 0xe4, 0x8b, 0x06, 0x4d, 0x09, 0xa7, 0x5f, 0x82, 0x8d, 0xea, 0xcd, 0x5b, 0x37, 0xef, 0xcf, 0x78, 0x4f, 0xb1, 0x1b, 0x17, 0xd6, 0xd9, 0xf2, 0x31, 0x52, 0x24, 0xf8, 0xe7, 0x63, 0x79, 0x1b, 0xac, 0x6c, 0xf4, 0x6e, 0x1c, 0x23, 0xb0, 0xb0, 0x25, 0x2c, 0x19, 0xed, 0xf0, 0x40, 0xd3, 0x5f, 0x59, 0x25, 0x53, 0x26, 0x5b, 0x88, 0x6b, 0x29, 0xca, 0x56, 0xeb, 0xc5, 0x38, 0x63, 0x71, 0x41, 0x4d, 0x82, 0xa3, 0x40 } +, + /* Encryption */ + 192, + { 0x2b, 0x0a, 0x43, 0xb3, 0xcd, 0xc9, 0x9d, 0x6c, 0xfc, 0x74, 0xda, 0x2a, 0x86, 0xec, 0xd7, 0xd5, 0x76, 0x24, 0x75, 0xd1, 0x43, 0xe5, 0x48, 0x6f, 0xa9, 0xcb, 0xeb, 0xbf, 0x27, 0xd8, 0xe4, 0x14, 0x1e, 0xf7, 0x2b, 0x6d, 0x4f, 0x13, 0xf6, 0x64, 0xb3, 0xd2, 0xe9, 0xec, 0x32, 0x22, 0x7c, 0x1a, 0xd5, 0xb7, 0x6c, 0x0d, 0x1b, 0xef, 0xbd, 0x65, 0x89, 0x68, 0xc7, 0xdb, 0x14, 0x95, 0x23, 0x82, 0x49, 0xbc, 0xd9, 0x5e, 0x75, 0x40, 0x25, 0x4e, 0x65, 0x74, 0x98, 0x23, 0xb8, 0xa3, 0x4b, 0xf6, 0xa1, 0x41, 0x07, 0x21, 0xdf, 0x34, 0xf3, 0xc8, 0xd5, 0x79, 0xf3, 0x6a, 0xed, 0x9e, 0x0b, 0xac, 0x23, 0x1e, 0x54, 0xc2, 0x7f, 0x76, 0x73, 0x19, 0x7d, 0x19, 0xf5, 0x1c, 0xe6, 0xac, 0xbb, 0xcb, 0x7b, 0x1a, 0x55, 0xe3, 0x8e, 0xde, 0xbe, 0xed, 0x34, 0x61, 0x07, 0x3e, 0x80, 0xc7, 0x9a, 0x4f, 0xc3, 0x09, 0x31, 0x30, 0x69, 0x6b, 0xff, 0xf2, 0xbb, 0xcb, 0x74, 0x90, 0x5f, 0x2d, 0x34, 0x44, 0x33, 0x80, 0x57, 0xfd, 0xfa, 0xcb, 0xc4, 0xdb, 0x81, 0x93, 0x5b, 0x29, 0xe9, 0x9e, 0x55, 0xcc, 0xc1, 0xd4, 0x8d, 0x89, 0xe9, 0xdc, 0x4a, 0x63, 0xa0, 0x11, 0xa6, 0x23, 0x32, 0xcf, 0x57, 0x02, 0x62, 0xa0, 0x63, 0x59, 0xcc, 0x36, 0xc0, 0x5a, 0x6f, 0xe1, 0x8a, 0xfb, 0x78, 0x32, 0xb3, 0x2e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.7", + /* Message */ + 45, + { 0xb0, 0xe7, 0x7f, 0x42, 0xc1, 0xa1, 0xe3, 0xf4, 0x15, 0x57, 0x23, 0xa9, 0x0d, 0xb8, 0x8e, 0xb1, 0x53, 0xcb, 0x3d, 0x3a, 0x28, 0xed, 0xdf, 0x25, 0x9c, 0x47, 0x05, 0x6a, 0x47, 0x0c, 0x91, 0x5e, 0xc9, 0x55, 0xf8, 0x31, 0x89, 0xf7, 0x1a, 0xea, 0xcd, 0xd5, 0x5c, 0x33, 0x5f } +, + /* Seed */ + 144, + { 0xfb, 0x36, 0x01, 0x10, 0x5c, 0xaa, 0x9a, 0x2f, 0xdd, 0x6d, 0xd6, 0xc5, 0x74, 0x6f, 0x4f, 0xca, 0xfe, 0xf4, 0x41, 0xbc, 0xb0, 0xfb, 0x8a, 0x2c, 0xc0, 0x3d, 0x0b, 0x57, 0x34, 0x9f, 0x93, 0x21, 0xaf, 0x9d, 0x99, 0x84, 0xe6, 0x4e, 0x2e, 0xc4, 0x85, 0xc9, 0xad, 0x75, 0x5f, 0x14, 0x0c, 0x0b, 0x66, 0xdb, 0x1c, 0xfc, 0x26, 0x69, 0x1c, 0x26, 0x77, 0x31, 0xd1, 0xa3, 0xaf, 0xe6, 0x87, 0x20, 0x2a, 0x96, 0x77, 0xe4, 0x2e, 0x84, 0x4d, 0x47, 0x7b, 0x75, 0xbc, 0xbb, 0x8c, 0x97, 0xd9, 0x9f, 0xcf, 0x72, 0xb3, 0xfb, 0x6d, 0x34, 0x9f, 0xa9, 0xc4, 0x76, 0x61, 0x91, 0x47, 0x21, 0x7a, 0x04, 0xdc, 0x06, 0xaa, 0x3c, 0x3c, 0x17, 0x64, 0x95, 0x38, 0x0c, 0xb9, 0x2c, 0x0a, 0x7e, 0x09, 0x7b, 0x4b, 0x4c, 0x5f, 0xfe, 0x04, 0x63, 0x1a, 0xb1, 0xd1, 0xbf, 0xea, 0x03, 0x67, 0x86, 0x50, 0xc8, 0x5c, 0x17, 0x0f, 0xa4, 0xa1, 0xd6, 0x4a, 0x4c, 0x13, 0x5e, 0x61, 0x48, 0x14, 0x90, 0xb6, 0x2b } +, + /* Encryption */ + 192, + { 0xa4, 0xbd, 0xd4, 0x92, 0xfe, 0xc7, 0x9c, 0x3a, 0x79, 0x09, 0x3a, 0x44, 0x33, 0x42, 0x72, 0xd9, 0xd1, 0x7f, 0x54, 0x3d, 0x02, 0x02, 0xc3, 0x9e, 0x40, 0x8b, 0xfb, 0x39, 0x36, 0x6b, 0xe2, 0xde, 0x61, 0xdf, 0x50, 0xac, 0x45, 0x8c, 0xae, 0xdd, 0xef, 0xfb, 0x69, 0xe2, 0x13, 0xca, 0x92, 0xb7, 0x49, 0x53, 0x66, 0x34, 0x7e, 0xde, 0x73, 0x3f, 0xf3, 0x99, 0xae, 0xc7, 0x96, 0xc3, 0xc3, 0xb1, 0xdf, 0x34, 0x9f, 0x01, 0x1d, 0xa0, 0x1f, 0xee, 0x7d, 0x21, 0xc1, 0xc2, 0x61, 0x84, 0x3d, 0xe8, 0x82, 0x08, 0x56, 0x0c, 0x0e, 0x89, 0x84, 0xb9, 0x52, 0x23, 0xea, 0x37, 0x31, 0xdb, 0x91, 0xc5, 0x93, 0x7a, 0x79, 0xb0, 0xdb, 0x93, 0x87, 0x59, 0x1c, 0xe3, 0x2e, 0xc7, 0xf5, 0x83, 0xe6, 0x00, 0xf5, 0x24, 0x44, 0xdf, 0xa7, 0x67, 0x1c, 0xe8, 0x27, 0x38, 0x98, 0xfb, 0xbc, 0xa3, 0xa4, 0xaa, 0x68, 0x32, 0xcb, 0xb3, 0x54, 0x3a, 0xbe, 0x96, 0x47, 0xe5, 0xf8, 0xc1, 0x37, 0x72, 0x82, 0x52, 0xce, 0x54, 0x40, 0xfc, 0xe1, 0x0e, 0x4d, 0x4e, 0xf7, 0x5d, 0x56, 0xb8, 0x14, 0xd5, 0x19, 0x64, 0x44, 0x41, 0x41, 0x1c, 0x10, 0xa2, 0xa1, 0x4c, 0x35, 0x04, 0x72, 0x82, 0x7c, 0x99, 0xea, 0x3e, 0xe5, 0xfd, 0xa3, 0x88, 0x0f, 0x34, 0x1d, 0xca, 0x8d, 0x3d, 0x3a, 0x4e, 0x5e, 0x05, 0xba, 0x42 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.8", + /* Message */ + 44, + { 0xb8, 0x7f, 0x04, 0xb3, 0x35, 0x0e, 0x12, 0x63, 0xda, 0xa3, 0xf9, 0x40, 0x5e, 0x6f, 0xd3, 0xd2, 0x5d, 0x8e, 0xfa, 0x13, 0x25, 0x56, 0xa4, 0x95, 0x71, 0xf5, 0x70, 0x8a, 0x42, 0x52, 0x7a, 0xf3, 0x1d, 0xb0, 0x1e, 0xdf, 0x79, 0x82, 0x0f, 0x93, 0x26, 0x64, 0x5f, 0xb1 } +, + /* Seed */ + 145, + { 0xec, 0x8d, 0x01, 0x4d, 0x6e, 0xb8, 0xd0, 0x23, 0x9a, 0x97, 0x73, 0xbd, 0xd3, 0x20, 0xbf, 0xb3, 0xf2, 0xee, 0x8f, 0xc2, 0x7d, 0x5f, 0xdd, 0x91, 0xf3, 0xf3, 0x90, 0x5d, 0xc8, 0xa4, 0xc5, 0xff, 0x13, 0x52, 0x9a, 0xee, 0xe4, 0x61, 0x85, 0x4c, 0xcc, 0xd4, 0xe0, 0x9b, 0x62, 0x4a, 0xfa, 0x64, 0x7a, 0x7c, 0x04, 0x81, 0x4e, 0xb1, 0xe5, 0x7b, 0xa1, 0x4d, 0xf4, 0xc7, 0x95, 0xb4, 0x2e, 0x84, 0xc4, 0xd0, 0x86, 0x29, 0x24, 0x5d, 0xac, 0xbb, 0xed, 0x27, 0x39, 0x9a, 0x72, 0x5a, 0x94, 0x8f, 0x3b, 0xa2, 0xf8, 0xb6, 0x4d, 0x26, 0x02, 0xdd, 0x0d, 0x5f, 0x55, 0xcb, 0x23, 0xea, 0xaf, 0xfb, 0x3a, 0x66, 0x50, 0x8e, 0x4a, 0x68, 0x9a, 0xd9, 0xee, 0xe6, 0x44, 0xe6, 0xa2, 0x6d, 0x43, 0x8f, 0x36, 0x63, 0xfe, 0xa9, 0xbd, 0x03, 0x12, 0xbb, 0x0e, 0x7e, 0x5a, 0x6d, 0xee, 0x04, 0xbb, 0xe8, 0xa0, 0x74, 0x5a, 0x73, 0xd5, 0xac, 0x89, 0xfa, 0xa0, 0x96, 0xa5, 0x2e, 0xd3, 0x04, 0x6d, 0x77, 0xde } +, + /* Encryption */ + 192, + { 0x77, 0x5d, 0xc3, 0x24, 0xfe, 0x9d, 0x5e, 0x05, 0xad, 0x01, 0x50, 0x13, 0xd6, 0x5f, 0x0e, 0xba, 0x0d, 0xcd, 0x52, 0xff, 0x9d, 0xfc, 0x17, 0x95, 0xea, 0x93, 0xd0, 0xf4, 0x33, 0x57, 0x98, 0x96, 0x86, 0xfe, 0x3f, 0x8b, 0x04, 0x62, 0x23, 0xbb, 0xa5, 0xc7, 0x84, 0x9a, 0xca, 0xc3, 0x12, 0x35, 0x43, 0x43, 0x26, 0x16, 0xc3, 0x10, 0x3a, 0xc2, 0xba, 0x8d, 0xb0, 0xa1, 0xd2, 0x99, 0x40, 0xbb, 0xa2, 0x62, 0x47, 0x0e, 0x5e, 0x53, 0xbe, 0x60, 0xe0, 0xeb, 0x72, 0x4d, 0x07, 0xcd, 0x91, 0x2a, 0xef, 0xbb, 0x87, 0xfb, 0x51, 0x98, 0x0e, 0x9e, 0x1a, 0xc1, 0x94, 0xda, 0x31, 0x92, 0x95, 0x41, 0xca, 0x43, 0x22, 0x4b, 0x15, 0x2b, 0xe6, 0xf2, 0xdf, 0x6c, 0x5f, 0x04, 0x42, 0xb4, 0xf4, 0xd2, 0xcc, 0x2f, 0xb0, 0x27, 0x39, 0xd4, 0x85, 0xa0, 0x11, 0x62, 0xbc, 0x8d, 0xbb, 0xad, 0x14, 0x76, 0xeb, 0x06, 0xe2, 0x45, 0xab, 0x36, 0xc4, 0xc7, 0x2d, 0x3f, 0x36, 0x07, 0xd0, 0x50, 0x84, 0xa0, 0xf6, 0xb7, 0x2d, 0xc8, 0xba, 0xc3, 0x46, 0xbd, 0x19, 0x09, 0x1b, 0x02, 0xf5, 0x98, 0x2c, 0x91, 0x45, 0x7c, 0x7b, 0x10, 0xf4, 0x47, 0x2b, 0x57, 0x18, 0x45, 0x24, 0x21, 0x4b, 0x23, 0x82, 0x5b, 0x59, 0xf4, 0x34, 0xcc, 0x48, 0xa2, 0xb8, 0x54, 0xca, 0xb5, 0x0f, 0xf7, 0x9e, 0x59, 0x09, 0x1c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.9", + /* Message */ + 33, + { 0xe1, 0x95, 0xa0, 0x36, 0xa5, 0x30, 0xe1, 0xc2, 0xa9, 0xd7, 0xa1, 0x03, 0x35, 0x8d, 0xc2, 0xbd, 0x25, 0xb1, 0x01, 0xbf, 0x70, 0x44, 0x50, 0xab, 0x8e, 0x50, 0x62, 0xcb, 0x63, 0xdf, 0x56, 0x10, 0x35 } +, + /* Seed */ + 156, + { 0x0e, 0xf8, 0x81, 0xde, 0xfc, 0x45, 0xad, 0x3f, 0x3e, 0x58, 0xb1, 0x10, 0x5e, 0x49, 0xb4, 0x23, 0xab, 0x89, 0x12, 0x4a, 0x65, 0xb5, 0x2c, 0xfd, 0x81, 0xcf, 0xd5, 0x42, 0xb9, 0x1e, 0x7c, 0x4c, 0x1a, 0x60, 0x71, 0xa2, 0xcf, 0x12, 0xb4, 0x82, 0x7e, 0xd5, 0xd1, 0x9c, 0xba, 0xf8, 0xfe, 0xea, 0x54, 0xbb, 0x3d, 0x73, 0x85, 0x7e, 0xe8, 0x7c, 0x71, 0x5c, 0x71, 0xb9, 0xed, 0x1c, 0x07, 0xc3, 0xaf, 0xd9, 0x0f, 0xce, 0x40, 0x44, 0x8b, 0xb5, 0x7e, 0x35, 0x24, 0xd0, 0x38, 0x80, 0x98, 0x39, 0xe3, 0x6a, 0x4f, 0x55, 0x44, 0xc3, 0xe1, 0x81, 0xe8, 0xc2, 0xe2, 0x93, 0xcd, 0x57, 0x54, 0xc8, 0x65, 0x74, 0xad, 0xe6, 0xdf, 0xce, 0x0a, 0xb3, 0x4a, 0x80, 0xb4, 0xd4, 0x8a, 0x9d, 0x42, 0xe7, 0x11, 0x5d, 0x8c, 0xbc, 0xb1, 0xfa, 0x28, 0xc8, 0xa2, 0x65, 0x01, 0xdb, 0x7d, 0x0b, 0xb4, 0x96, 0xd0, 0x1d, 0xd6, 0x92, 0x65, 0xa0, 0x26, 0xe1, 0xa9, 0x7e, 0x9d, 0x3a, 0x1a, 0x65, 0xa8, 0xaa, 0x8e, 0xc2, 0xdf, 0x06, 0x34, 0xe6, 0xf2, 0x65, 0x1e, 0xf4, 0x35, 0x40 } +, + /* Encryption */ + 192, + { 0x1a, 0xd7, 0x7a, 0x00, 0x7c, 0xa4, 0x37, 0xab, 0xd0, 0x15, 0x9e, 0xd4, 0xb0, 0xb6, 0x81, 0x54, 0x16, 0xf9, 0xf0, 0x9d, 0x1b, 0x12, 0x15, 0xfb, 0x7c, 0xff, 0x11, 0x52, 0x97, 0x60, 0x1a, 0x88, 0x30, 0xf2, 0x09, 0x17, 0x86, 0x35, 0x63, 0x85, 0x3e, 0xd7, 0x8e, 0x9c, 0x3d, 0x7b, 0xa4, 0xc9, 0x7a, 0x05, 0xcf, 0x19, 0xdd, 0x32, 0x92, 0x48, 0x47, 0x1a, 0x47, 0x03, 0xa4, 0x65, 0x17, 0x8b, 0x85, 0xd4, 0xec, 0xd5, 0x42, 0x24, 0x12, 0x98, 0xc2, 0xfe, 0xcd, 0x41, 0x3e, 0x23, 0xa7, 0x0c, 0x8a, 0x5d, 0x47, 0xc2, 0x0e, 0x31, 0xc2, 0xda, 0xbe, 0x3c, 0x82, 0xa9, 0x54, 0x50, 0x27, 0x27, 0x49, 0xae, 0x2e, 0xbb, 0x89, 0x98, 0x5d, 0x00, 0xb6, 0x3d, 0xed, 0xd9, 0x59, 0x6d, 0x05, 0x16, 0xd1, 0x2a, 0x78, 0xc3, 0x74, 0xb7, 0xed, 0xdc, 0x7d, 0xce, 0xe8, 0xe4, 0xfd, 0xd1, 0x6c, 0x1d, 0xfa, 0xbf, 0xf7, 0xff, 0xd4, 0xc1, 0xfd, 0x61, 0xce, 0x04, 0xbe, 0x8e, 0x49, 0x75, 0xc5, 0xcd, 0x71, 0xe2, 0xcb, 0x0e, 0x54, 0x1b, 0x84, 0x61, 0xbb, 0x81, 0xfb, 0x28, 0xcc, 0xe7, 0x73, 0x65, 0x3e, 0x8b, 0x16, 0xb2, 0x8a, 0x8c, 0x20, 0x74, 0x28, 0x89, 0x5f, 0x28, 0x53, 0x55, 0x87, 0xa5, 0xc9, 0x9d, 0x46, 0xba, 0x4d, 0xf9, 0xae, 0x08, 0x50, 0x18, 0x51, 0x3d, 0x69, 0xab, 0xa3, 0xf6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.10", + /* Message */ + 25, + { 0x04, 0x2a, 0x39, 0x22, 0xaa, 0x87, 0x1e, 0xea, 0x0d, 0x78, 0x42, 0x2c, 0xe7, 0x85, 0x66, 0xab, 0xbb, 0x5b, 0x08, 0xc2, 0xdd, 0xf1, 0xee, 0x30, 0xcf } +, + /* Seed */ + 164, + { 0x5a, 0xe8, 0x51, 0x14, 0xb0, 0x02, 0x7a, 0x23, 0xc7, 0x2b, 0xdb, 0x46, 0xae, 0x7b, 0xb8, 0x87, 0xbe, 0xc5, 0xba, 0xd7, 0xa9, 0x88, 0x4e, 0x93, 0xf6, 0xf4, 0xfd, 0x0b, 0xc9, 0x38, 0xbc, 0x72, 0x41, 0x0c, 0xce, 0x96, 0xa1, 0x4f, 0x4d, 0xe1, 0x99, 0x19, 0x77, 0x35, 0x05, 0x1e, 0xfc, 0xdc, 0xc1, 0x96, 0xf3, 0xad, 0xbf, 0xaa, 0x06, 0x3c, 0xb3, 0xf7, 0xa2, 0x34, 0xc6, 0xcf, 0x99, 0xd7, 0x0f, 0xbb, 0x7e, 0x35, 0xb6, 0xae, 0xc6, 0x64, 0x14, 0x66, 0x93, 0x91, 0xe3, 0xcb, 0xe7, 0x21, 0xec, 0x99, 0x1a, 0x1e, 0x5d, 0xfb, 0xb0, 0x38, 0xf2, 0x70, 0x36, 0x85, 0x93, 0x74, 0x9b, 0x20, 0x8d, 0x08, 0x9a, 0xae, 0xe2, 0xef, 0x35, 0xc3, 0xda, 0xf6, 0x23, 0x8b, 0x5f, 0xe4, 0x2d, 0x13, 0xdd, 0xe4, 0x07, 0xdf, 0x14, 0xf2, 0xd6, 0x18, 0xc9, 0x79, 0xc9, 0x7d, 0x2d, 0xe0, 0x29, 0x33, 0xb5, 0x7f, 0xe8, 0x81, 0x22, 0x04, 0x86, 0x2b, 0x2f, 0x1d, 0xee, 0x98, 0x3f, 0x24, 0xc2, 0xc5, 0x96, 0xea, 0x66, 0x8e, 0x63, 0x7d, 0x0a, 0x6a, 0xe6, 0xdc, 0x52, 0x65, 0x27, 0x69, 0x94, 0xe7, 0xe4, 0xf0, 0x2b, 0x6e } +, + /* Encryption */ + 192, + { 0x12, 0x44, 0xde, 0x88, 0x0e, 0x0f, 0x78, 0x52, 0xe9, 0x96, 0x95, 0x9d, 0x76, 0x2f, 0xca, 0xd9, 0x15, 0x65, 0xa4, 0xd0, 0xad, 0x3b, 0xc5, 0x27, 0x50, 0xd4, 0xa0, 0x44, 0x0f, 0x0b, 0x5c, 0x65, 0x1a, 0xa0, 0xe6, 0xf4, 0x92, 0x06, 0x1b, 0x2c, 0x86, 0x24, 0xc5, 0x2e, 0xde, 0x68, 0x58, 0xfa, 0x25, 0x18, 0xae, 0x8e, 0x8b, 0x11, 0x65, 0x58, 0xb2, 0xc8, 0x07, 0x6c, 0x17, 0xae, 0x78, 0x3d, 0x8d, 0xb2, 0x5f, 0x0d, 0x8f, 0xb1, 0xf2, 0x75, 0x8a, 0x82, 0xab, 0x97, 0x1f, 0xa7, 0x28, 0x3e, 0xf0, 0x74, 0x9a, 0x37, 0xbe, 0x28, 0x93, 0xf8, 0x94, 0x37, 0xfb, 0x8e, 0xa9, 0x00, 0x72, 0xb5, 0x85, 0x5a, 0x26, 0x08, 0xfc, 0x54, 0x2f, 0x5d, 0x2e, 0x0c, 0xb5, 0x43, 0xf4, 0xfa, 0xc5, 0x28, 0xf9, 0x43, 0x52, 0xd0, 0x16, 0x40, 0xfc, 0x2c, 0x53, 0x1b, 0x79, 0x81, 0x0c, 0x00, 0x77, 0x7b, 0xc9, 0xe1, 0x0d, 0xd9, 0xea, 0x99, 0x96, 0xe7, 0x40, 0x87, 0xfa, 0xdc, 0xb7, 0x1a, 0xa1, 0x43, 0x00, 0x67, 0x65, 0x71, 0x61, 0x48, 0x82, 0x94, 0x3f, 0x4a, 0x56, 0x14, 0x12, 0xc0, 0x54, 0x67, 0xdc, 0xa6, 0x6c, 0xa4, 0x9f, 0x82, 0x29, 0x35, 0x18, 0x23, 0xdb, 0x8a, 0x6b, 0x9f, 0x80, 0x3d, 0x70, 0x9c, 0x11, 0x87, 0xed, 0x74, 0x10, 0xcf, 0x91, 0x00, 0x15, 0x59, 0x5c, 0xea, 0xb6, 0x3e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.11", + /* Message */ + 52, + { 0xf3, 0x1d, 0x3d, 0x0c, 0x30, 0xfd, 0x65, 0xd7, 0xb9, 0x8b, 0x70, 0x99, 0x44, 0x78, 0x2e, 0x20, 0x52, 0x5c, 0xa7, 0xc1, 0xf4, 0x2d, 0x5d, 0x03, 0xa0, 0xf6, 0xd2, 0x75, 0x9d, 0xf1, 0x91, 0x9e, 0xea, 0x82, 0xf8, 0x0f, 0x10, 0x00, 0xfd, 0x5c, 0xf8, 0x59, 0xdf, 0x59, 0x87, 0x1b, 0xac, 0x82, 0xdd, 0x90, 0x76, 0xcf } +, + /* Seed */ + 137, + { 0x04, 0x4b, 0xc3, 0x77, 0xe8, 0x58, 0x9f, 0xa5, 0xaf, 0x1c, 0x17, 0x34, 0x7d, 0x50, 0xe0, 0xcb, 0xbf, 0x90, 0x15, 0x76, 0xf2, 0x41, 0xde, 0x69, 0x0c, 0x88, 0x16, 0xc1, 0x29, 0xcd, 0x9f, 0x2f, 0xb0, 0x83, 0x1a, 0x01, 0x7b, 0xec, 0x30, 0xb8, 0x2b, 0x68, 0xf6, 0x98, 0x31, 0x1a, 0xf6, 0xe0, 0x77, 0x72, 0xbc, 0xd8, 0x98, 0xfa, 0x0c, 0x27, 0xf6, 0x2a, 0xfd, 0xe8, 0x95, 0x89, 0x77, 0x84, 0x46, 0x25, 0x55, 0x2d, 0x9b, 0xcb, 0x5a, 0x81, 0xaa, 0x3d, 0x74, 0x15, 0xb2, 0x42, 0xa0, 0x3b, 0x12, 0xfc, 0x1d, 0x3f, 0xe2, 0xd2, 0xce, 0x6e, 0x5f, 0x71, 0xc4, 0xa4, 0xa4, 0xc7, 0xca, 0x83, 0xe0, 0x65, 0x6f, 0x50, 0x02, 0xac, 0x36, 0xd8, 0xd0, 0x2b, 0x69, 0xae, 0x65, 0x73, 0x44, 0x98, 0xf1, 0x31, 0x95, 0x2c, 0xea, 0x48, 0x1f, 0xa2, 0xc2, 0x96, 0x5b, 0x6e, 0xf0, 0x51, 0x7e, 0xde, 0x50, 0xdd, 0xb0, 0x9b, 0x3e, 0xa7, 0x02, 0x6d, 0x06 } +, + /* Encryption */ + 192, + { 0x86, 0xf6, 0x6f, 0x0c, 0x25, 0x05, 0x85, 0x06, 0x59, 0x43, 0xde, 0x2f, 0x71, 0x1f, 0xae, 0x4f, 0xf2, 0x62, 0x70, 0x0e, 0x0d, 0x33, 0x06, 0xa2, 0x4c, 0x94, 0x30, 0xf8, 0x7c, 0xfd, 0x93, 0xde, 0xf4, 0xc3, 0x44, 0x7c, 0xc7, 0x21, 0x0f, 0xd9, 0x4a, 0x14, 0x33, 0x62, 0xf4, 0xf9, 0x45, 0xc6, 0xdb, 0xe2, 0x80, 0xbd, 0xef, 0x5d, 0x14, 0xf7, 0x5e, 0xb7, 0xbb, 0x31, 0x32, 0x0b, 0xcb, 0xd0, 0xd8, 0x8f, 0x0c, 0xcf, 0x2c, 0x95, 0xa7, 0x4c, 0xb4, 0x58, 0xc6, 0x27, 0x2b, 0x58, 0xbf, 0x74, 0x30, 0x93, 0xc4, 0xbb, 0xa2, 0xd7, 0xbe, 0xe9, 0xea, 0x2d, 0xd3, 0x0c, 0xf7, 0x2f, 0xe2, 0x93, 0xc9, 0x0c, 0x97, 0x43, 0x0a, 0x04, 0x7b, 0x17, 0x26, 0x63, 0x91, 0xc5, 0x1f, 0x5c, 0x39, 0x8b, 0xa3, 0xdf, 0x8c, 0xb7, 0x4b, 0xa3, 0xe3, 0x72, 0xf9, 0x55, 0x5c, 0xcc, 0x97, 0xd6, 0xdb, 0x76, 0x14, 0xea, 0x06, 0xd5, 0xc4, 0x8c, 0x1c, 0x60, 0x06, 0x13, 0x3d, 0x0e, 0x9d, 0x69, 0x95, 0x79, 0x93, 0x85, 0x92, 0x0a, 0xd8, 0xaf, 0xc3, 0xde, 0xad, 0xf6, 0x31, 0xce, 0xcc, 0x55, 0x9c, 0xaf, 0xf4, 0x95, 0xb0, 0x8d, 0x68, 0x3f, 0xb2, 0x2a, 0xa6, 0x97, 0xd7, 0x1c, 0x69, 0x6e, 0x46, 0xb1, 0xbf, 0x4f, 0xd7, 0x6b, 0x8d, 0x0b, 0x39, 0xf1, 0x79, 0xbf, 0x66, 0x84, 0x1b, 0xbb, 0x97, 0x07 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.12", + /* Message */ + 29, + { 0x6a, 0x35, 0x55, 0x57, 0x9d, 0xad, 0x03, 0x94, 0x35, 0x43, 0xff, 0x74, 0xe1, 0x74, 0x7c, 0x25, 0x7a, 0x83, 0xd3, 0x52, 0x94, 0xc2, 0x53, 0x93, 0x83, 0xe2, 0x35, 0xde, 0x69 } +, + /* Seed */ + 160, + { 0x5d, 0x92, 0x43, 0x4e, 0xdb, 0xd4, 0xf5, 0xbd, 0x27, 0x19, 0x71, 0x71, 0xf8, 0x53, 0xce, 0xb7, 0x26, 0x30, 0x30, 0x83, 0xad, 0x45, 0x67, 0xa1, 0xd7, 0xc6, 0x10, 0x4d, 0x19, 0x2b, 0x9b, 0xcc, 0xdf, 0xd0, 0xda, 0xed, 0xa2, 0x74, 0xe5, 0xcd, 0xfb, 0x3d, 0x0c, 0x5d, 0x19, 0xc9, 0x68, 0x25, 0x81, 0xec, 0x7a, 0xdc, 0x1a, 0x87, 0xe0, 0x81, 0x51, 0x41, 0x5d, 0x5a, 0x9a, 0xdc, 0x1a, 0xf4, 0x50, 0xb1, 0xba, 0x88, 0xd0, 0xef, 0x32, 0xac, 0x2d, 0x1f, 0x8a, 0xe3, 0x45, 0x95, 0x28, 0x14, 0x75, 0x3a, 0xf3, 0x8e, 0x12, 0x63, 0x5c, 0xff, 0x8c, 0x09, 0x21, 0x59, 0xb4, 0xe7, 0x5d, 0xee, 0xa1, 0x98, 0x3e, 0xd3, 0xd2, 0xd9, 0xec, 0x2f, 0xe7, 0xb9, 0xa2, 0xe1, 0x6a, 0x14, 0x1e, 0x81, 0x8b, 0x84, 0xcd, 0x9b, 0x71, 0xc1, 0x29, 0xa8, 0xb3, 0xc6, 0xdb, 0x62, 0x02, 0x32, 0xdc, 0x03, 0xa2, 0x40, 0x1f, 0x73, 0x1f, 0xf8, 0xa6, 0x3d, 0xa4, 0x58, 0xa7, 0xd8, 0x78, 0x90, 0x56, 0x25, 0xae, 0xe1, 0xfc, 0x09, 0x4d, 0xfb, 0x07, 0xb4, 0x57, 0x5a, 0x7f, 0x0a, 0xad, 0x23, 0x3e, 0x82 } +, + /* Encryption */ + 192, + { 0x93, 0x10, 0x27, 0x2d, 0x12, 0x4b, 0xc5, 0xcd, 0xb7, 0x21, 0x88, 0x98, 0x40, 0xaa, 0x77, 0x15, 0xe7, 0x67, 0x32, 0x17, 0x00, 0xcb, 0x39, 0xb2, 0xb8, 0xa5, 0xa8, 0x2a, 0xe3, 0xf0, 0x2e, 0xb9, 0x67, 0xe8, 0xdb, 0x46, 0x84, 0x3b, 0xc1, 0xbf, 0x62, 0xed, 0x8b, 0xd2, 0xab, 0xe8, 0x14, 0x34, 0x49, 0x7f, 0x99, 0x00, 0x64, 0x02, 0x53, 0x98, 0x2d, 0x37, 0x2b, 0x2b, 0xf7, 0xc1, 0xb0, 0x9b, 0xd5, 0x01, 0x96, 0x74, 0xa8, 0x34, 0xfb, 0xbd, 0xff, 0x35, 0x68, 0xa2, 0x82, 0x4a, 0xed, 0x4a, 0x80, 0x48, 0xd2, 0xb8, 0x61, 0x36, 0x27, 0x75, 0xbd, 0x5f, 0x0d, 0x63, 0xb3, 0x48, 0x36, 0x3d, 0x13, 0x78, 0x69, 0x1f, 0x5d, 0xd1, 0xd7, 0x96, 0x10, 0x74, 0xed, 0x95, 0xfc, 0x90, 0x07, 0xbd, 0x5f, 0x5c, 0x29, 0x23, 0xc1, 0x7c, 0x42, 0x90, 0x4e, 0x2b, 0xf9, 0xd2, 0x48, 0x77, 0x9f, 0xdf, 0xb2, 0x03, 0x97, 0x38, 0x41, 0xa1, 0x12, 0x90, 0xc7, 0xe9, 0xe9, 0x35, 0x6d, 0x4e, 0xab, 0x17, 0x0e, 0x43, 0x1b, 0xfe, 0x45, 0x4a, 0x88, 0x01, 0x0d, 0x9a, 0xff, 0x33, 0x70, 0x0c, 0xee, 0x55, 0xc7, 0x04, 0xc8, 0x2a, 0x7f, 0xfb, 0x15, 0xe2, 0x53, 0xef, 0x84, 0xf4, 0x01, 0x9e, 0x12, 0x43, 0x8f, 0x7c, 0x73, 0x86, 0xdc, 0x53, 0x5b, 0x19, 0xca, 0x86, 0xaf, 0x71, 0xd4, 0x77, 0x60, 0x8e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.13", + /* Message */ + 47, + { 0xcb, 0x79, 0xaf, 0x5a, 0xea, 0xfd, 0xf2, 0xba, 0xd2, 0x1d, 0xfe, 0x62, 0x92, 0x66, 0x42, 0xcb, 0xa8, 0x04, 0xec, 0x7f, 0xd0, 0xea, 0x5d, 0x54, 0x08, 0xac, 0xe9, 0xed, 0xff, 0x28, 0xe7, 0xe8, 0xdf, 0xff, 0x6d, 0xf3, 0x83, 0xaf, 0x14, 0x40, 0x21, 0x46, 0x04, 0x76, 0xc0, 0xc8, 0x2c } +, + /* Seed */ + 142, + { 0x5f, 0xce, 0xa2, 0x57, 0xcf, 0xa9, 0x2c, 0x84, 0xf0, 0xb8, 0x93, 0x7d, 0x17, 0x3f, 0xae, 0xcf, 0x75, 0x03, 0xab, 0x16, 0x2e, 0x0b, 0xae, 0xef, 0x7e, 0x4c, 0x51, 0x1f, 0x3e, 0x32, 0xa3, 0x24, 0xed, 0x40, 0xe2, 0x42, 0xa8, 0x52, 0xba, 0x57, 0x89, 0x5b, 0x7c, 0xfe, 0x4d, 0x61, 0x79, 0x61, 0xe0, 0x36, 0xf6, 0x63, 0xe0, 0x22, 0x8a, 0x29, 0xcd, 0x1a, 0x95, 0xac, 0xac, 0x08, 0xa2, 0x55, 0x26, 0xd1, 0xeb, 0xff, 0x0a, 0xb3, 0xf0, 0x33, 0xed, 0xbf, 0x1a, 0xe2, 0x76, 0xa8, 0xd2, 0x36, 0x73, 0x6c, 0xc7, 0xaf, 0x51, 0xb5, 0xd2, 0xbd, 0xc8, 0x3d, 0xcc, 0x7d, 0x7d, 0x3b, 0xf5, 0xb8, 0x22, 0xaf, 0x2e, 0xff, 0xed, 0x7e, 0xfc, 0xb6, 0x17, 0xe0, 0x83, 0xe5, 0x1b, 0xe9, 0x94, 0xae, 0xd6, 0x56, 0x9b, 0x23, 0x83, 0xb9, 0x41, 0xae, 0xe5, 0x94, 0xc7, 0xb0, 0x12, 0xe6, 0x75, 0x1c, 0x37, 0xb7, 0xa5, 0x4e, 0x2a, 0x19, 0x18, 0x24, 0xa1, 0x30, 0xd5, 0x5c, 0xf8, 0x45 } +, + /* Encryption */ + 192, + { 0x11, 0xfa, 0x81, 0x9d, 0x3a, 0x63, 0x88, 0x04, 0xee, 0xf1, 0xd9, 0x56, 0x0a, 0x11, 0xf5, 0x23, 0x0a, 0x0b, 0xad, 0xfd, 0x66, 0xeb, 0x68, 0x4e, 0x7d, 0x69, 0xdf, 0xa2, 0x89, 0x8c, 0x8e, 0x0b, 0x6e, 0x04, 0xaf, 0x8e, 0xfc, 0x70, 0x61, 0x08, 0x1e, 0xc5, 0x9e, 0x45, 0x85, 0x76, 0x42, 0xe8, 0xb2, 0x00, 0x41, 0xaf, 0x50, 0x8d, 0x9d, 0x4e, 0x28, 0x82, 0x20, 0xf9, 0xfd, 0x38, 0x9d, 0xe8, 0xb2, 0x91, 0x24, 0xce, 0x74, 0x7e, 0xb6, 0x8e, 0x2e, 0xaa, 0x8c, 0x8f, 0x6f, 0xb4, 0x93, 0xf6, 0x11, 0xac, 0x09, 0xb7, 0x23, 0x09, 0x5d, 0x07, 0xee, 0xd9, 0x24, 0xf6, 0xab, 0x8e, 0x09, 0xff, 0x93, 0xc5, 0x51, 0x6d, 0x1f, 0x0e, 0xbf, 0x62, 0xc5, 0xf0, 0x22, 0xf5, 0xbb, 0x4f, 0x4c, 0xb5, 0xb8, 0xf5, 0xd4, 0x87, 0xa1, 0x7d, 0xf7, 0xd0, 0x12, 0xd7, 0x04, 0x35, 0x7a, 0xbf, 0x17, 0x48, 0x67, 0xce, 0x40, 0xcd, 0xc5, 0x50, 0x11, 0xb0, 0x71, 0x39, 0xbe, 0xa4, 0x5c, 0xa0, 0xe5, 0x81, 0x78, 0x0d, 0xe6, 0x54, 0x17, 0xcc, 0x83, 0x5f, 0xf2, 0x69, 0x84, 0xfd, 0x0f, 0xeb, 0xa1, 0x87, 0x69, 0xc3, 0x94, 0xa2, 0xe4, 0x85, 0x02, 0x3e, 0x31, 0xd3, 0xb0, 0xa8, 0x88, 0xa7, 0xb1, 0x4c, 0x78, 0x1d, 0xd8, 0x5b, 0xab, 0x40, 0x86, 0x74, 0xf5, 0xf5, 0x7e, 0x4b, 0x76, 0x3d, 0x84, 0x35 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.14", + /* Message */ + 19, + { 0xd1, 0x62, 0x33, 0xfc, 0x77, 0x5c, 0x31, 0x9f, 0x15, 0x7a, 0xa2, 0x00, 0x47, 0x6c, 0xd6, 0xed, 0x64, 0xa1, 0xea } +, + /* Seed */ + 170, + { 0xbb, 0x33, 0xb2, 0x2b, 0x5f, 0x46, 0x79, 0x4b, 0xe8, 0x3e, 0x6a, 0xff, 0x34, 0xa0, 0xe4, 0x11, 0xd1, 0xf3, 0xf4, 0xb8, 0xda, 0xf9, 0xb5, 0x85, 0x87, 0x24, 0xef, 0xfd, 0xb9, 0x69, 0xc9, 0x55, 0x25, 0xc6, 0x2d, 0xc4, 0x4b, 0xb2, 0xb0, 0x83, 0x38, 0x60, 0x03, 0x05, 0x4b, 0xbd, 0x36, 0x66, 0xb7, 0x82, 0x82, 0x60, 0x6f, 0xe6, 0xea, 0x17, 0x27, 0x31, 0xbe, 0xe1, 0x16, 0x72, 0xd6, 0x01, 0xde, 0x32, 0x42, 0x3d, 0x83, 0xf4, 0x63, 0xcc, 0x29, 0x30, 0xf5, 0xfb, 0x79, 0xda, 0x15, 0x34, 0xc4, 0x15, 0xc9, 0x65, 0x82, 0x75, 0x65, 0x94, 0xa9, 0x99, 0xb2, 0x26, 0x35, 0x42, 0x48, 0xa0, 0x9f, 0x14, 0x1c, 0xae, 0xcf, 0x88, 0x83, 0x90, 0x78, 0xf7, 0x7f, 0x40, 0xbd, 0x48, 0x51, 0x34, 0x9c, 0x1f, 0xc7, 0x5e, 0x1e, 0xce, 0x6f, 0xd6, 0x96, 0x6b, 0xc9, 0xc9, 0xd5, 0xec, 0x12, 0x09, 0x6e, 0xd5, 0x04, 0x35, 0x46, 0x85, 0x9e, 0x4f, 0x95, 0x7d, 0x31, 0x88, 0xe1, 0xd9, 0x06, 0x0b, 0x59, 0xc1, 0xf7, 0xf6, 0x2e, 0xfb, 0xfe, 0x82, 0x5d, 0xda, 0x45, 0x35, 0x3e, 0x6f, 0xd4, 0xfa, 0xba, 0xc9, 0x83, 0xf9, 0x44, 0xf4, 0xc2, 0xc7, 0x9c, 0xbb } +, + /* Encryption */ + 192, + { 0x10, 0xc2, 0x0c, 0x0c, 0x71, 0xb1, 0x1b, 0xbe, 0xce, 0x14, 0xc8, 0x14, 0x83, 0xdc, 0xfa, 0x73, 0x0c, 0x23, 0xd4, 0xdd, 0x61, 0xb8, 0x75, 0x5b, 0x39, 0x94, 0x9d, 0xfd, 0x4a, 0x3c, 0x50, 0x33, 0x21, 0x60, 0xee, 0xc6, 0xf7, 0x71, 0x0e, 0x09, 0xc7, 0xa9, 0x7a, 0xf9, 0x3f, 0x70, 0x44, 0xb9, 0x2f, 0x41, 0xd0, 0x9f, 0xa3, 0xe6, 0xc6, 0xce, 0x1f, 0x64, 0x11, 0x48, 0x4e, 0xd4, 0x75, 0x40, 0xa1, 0xb5, 0x9e, 0x23, 0xc1, 0x93, 0x34, 0xb6, 0x6d, 0x68, 0x20, 0xc2, 0xd4, 0x4d, 0xb0, 0xf6, 0xaa, 0xf8, 0x5a, 0xa2, 0x7f, 0x53, 0xa4, 0x1f, 0x85, 0x6b, 0xf6, 0xa5, 0x91, 0x36, 0x59, 0x86, 0x9b, 0xa4, 0xab, 0xdd, 0xec, 0xbe, 0x87, 0x41, 0x3a, 0xc9, 0x5b, 0xe6, 0x40, 0x09, 0x59, 0x3b, 0x5c, 0xa2, 0xd0, 0x78, 0x3a, 0x16, 0xf6, 0x08, 0x66, 0x57, 0x55, 0x24, 0x53, 0x93, 0xfc, 0x14, 0x4f, 0xe3, 0xea, 0x5e, 0x9a, 0xac, 0x9f, 0x1f, 0x99, 0x1a, 0x92, 0x85, 0x38, 0xb4, 0x69, 0x97, 0xd3, 0x06, 0x3c, 0xc1, 0xa6, 0x9a, 0xdc, 0x19, 0x2a, 0x40, 0xc7, 0x6f, 0x92, 0xd4, 0x7a, 0x05, 0x80, 0xe3, 0xc0, 0x21, 0x20, 0x02, 0x3e, 0xce, 0x70, 0x32, 0x80, 0x7b, 0x7c, 0x09, 0x13, 0x43, 0xaa, 0x87, 0x3f, 0x6a, 0x4d, 0xdd, 0xe4, 0x3f, 0xb2, 0xdc, 0xc3, 0x79, 0xae, 0xee, 0xf6, 0x54 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.15", + /* Message */ + 17, + { 0xd2, 0xf3, 0xc2, 0xe6, 0xf4, 0x3b, 0x0f, 0xc9, 0xfc, 0x22, 0x93, 0xb8, 0x45, 0x88, 0xe6, 0x61, 0x15 } +, + /* Seed */ + 172, + { 0xb9, 0x81, 0x64, 0x89, 0x52, 0x5c, 0xd0, 0x26, 0x15, 0x6f, 0xb4, 0xe8, 0xa4, 0xa8, 0xf3, 0x4a, 0xea, 0x8a, 0x3a, 0xa1, 0xa6, 0x34, 0xcc, 0xcb, 0x32, 0x58, 0x91, 0x8f, 0xe8, 0x5c, 0xb8, 0xd4, 0xaa, 0x02, 0xa5, 0x28, 0x52, 0xa8, 0x94, 0x1d, 0x3e, 0xa6, 0xc0, 0x48, 0xb5, 0x8c, 0xc6, 0xc7, 0x56, 0x85, 0x67, 0x56, 0x25, 0xe5, 0xe4, 0xdd, 0x7d, 0xf9, 0x3b, 0x8a, 0xce, 0xc0, 0x79, 0x67, 0x0b, 0x49, 0xf3, 0xdc, 0x6e, 0x07, 0x63, 0xed, 0x4c, 0x8e, 0x2d, 0x0e, 0xe9, 0xb5, 0xca, 0x5b, 0xb6, 0x2d, 0xe0, 0x06, 0x91, 0x98, 0x38, 0xe4, 0xb6, 0x9b, 0xa1, 0x05, 0xd4, 0xc5, 0xa4, 0xcc, 0x6d, 0xca, 0x67, 0xb1, 0x21, 0x93, 0xa0, 0x32, 0xb6, 0x92, 0x73, 0x96, 0x44, 0xcc, 0xcf, 0x72, 0x3f, 0x9f, 0x69, 0xe4, 0x8b, 0x94, 0xc0, 0xbd, 0xce, 0x5a, 0xa3, 0x5f, 0x75, 0xdc, 0x53, 0x92, 0x7b, 0x81, 0xe3, 0x42, 0xce, 0x72, 0xc6, 0xb6, 0x5c, 0xf7, 0x5e, 0xae, 0xca, 0xc5, 0xfe, 0x0d, 0xea, 0x93, 0x88, 0x5b, 0xa4, 0x20, 0xaf, 0x99, 0x32, 0xd8, 0x4c, 0xa4, 0xb5, 0x0e, 0x07, 0xe3, 0x28, 0xec, 0x5f, 0x81, 0x6d, 0x2d, 0x86, 0x96, 0xb2, 0x0d, 0xf7, 0x5f } +, + /* Encryption */ + 192, + { 0x80, 0xf1, 0xdf, 0x25, 0xf3, 0x6f, 0x31, 0x4b, 0x98, 0x2c, 0x9c, 0x8a, 0xaf, 0xc0, 0xb8, 0xa1, 0xa2, 0xf1, 0x74, 0xab, 0xb2, 0x98, 0x08, 0x69, 0xc2, 0x9d, 0x19, 0xbe, 0x1d, 0x2d, 0x93, 0xb4, 0xfb, 0x42, 0x99, 0x90, 0x6c, 0x35, 0x7f, 0xdd, 0x40, 0xe8, 0x9a, 0x19, 0x54, 0x92, 0xa9, 0x79, 0x76, 0x61, 0xf0, 0x5d, 0x38, 0x71, 0xd1, 0xbd, 0x0a, 0x5c, 0x45, 0xd8, 0xf9, 0xb0, 0xfe, 0xe5, 0x65, 0xb0, 0x00, 0x4f, 0xf5, 0xaf, 0xc5, 0xa6, 0xf8, 0x9a, 0xd6, 0x03, 0xe8, 0x22, 0x83, 0x57, 0x0b, 0xdb, 0x4c, 0x6e, 0x0c, 0xfc, 0x31, 0x3e, 0x4e, 0x66, 0x5a, 0x94, 0x34, 0xb3, 0x2f, 0xcc, 0x77, 0x3d, 0x6e, 0xda, 0xbc, 0xe8, 0x5f, 0xe7, 0xc8, 0x0f, 0x03, 0x30, 0x2a, 0x84, 0xe2, 0x08, 0xb5, 0xbd, 0x0a, 0xad, 0x91, 0xce, 0x62, 0xfb, 0x8c, 0x2b, 0xf5, 0x4b, 0xa6, 0x6f, 0x7e, 0x8d, 0x00, 0x21, 0x92, 0x16, 0x29, 0x20, 0xa4, 0x6e, 0x36, 0xde, 0xa5, 0x66, 0x1f, 0xdd, 0x75, 0x81, 0x53, 0x56, 0x40, 0x74, 0xb8, 0x55, 0x9f, 0x88, 0x93, 0x62, 0x42, 0xfc, 0x09, 0x98, 0x14, 0x8f, 0x19, 0xeb, 0x50, 0xfc, 0x11, 0xfb, 0x24, 0xa7, 0xed, 0x8c, 0x83, 0x49, 0x65, 0x8f, 0xe9, 0xd3, 0x1e, 0x62, 0x74, 0xd4, 0x5d, 0x6f, 0x2b, 0x60, 0x9b, 0xb5, 0xcc, 0xd1, 0x7e, 0x28, 0x4c, 0x99 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.16", + /* Message */ + 50, + { 0x21, 0xee, 0x58, 0x12, 0xe3, 0x24, 0x6d, 0xab, 0x9c, 0x3c, 0x25, 0x9b, 0x21, 0x37, 0xd6, 0x5f, 0x98, 0xa0, 0x5e, 0x57, 0x40, 0x46, 0x5c, 0xa2, 0x2c, 0x69, 0x34, 0x97, 0x00, 0xa4, 0x2c, 0xbe, 0x4f, 0xfb, 0x39, 0x3f, 0xe2, 0x81, 0x99, 0x33, 0x9c, 0x51, 0x03, 0x1c, 0xd3, 0xb2, 0x2f, 0x2f, 0x0a, 0x83 } +, + /* Seed */ + 139, + { 0xe9, 0xde, 0x5b, 0xd3, 0x55, 0xe6, 0xaf, 0xf1, 0x9f, 0xa1, 0x1a, 0x2d, 0x0d, 0x3e, 0xdc, 0x3f, 0x64, 0x69, 0xbd, 0x3c, 0x75, 0x72, 0x06, 0xd6, 0x6b, 0x3f, 0x09, 0x90, 0x8f, 0xf6, 0x18, 0xaf, 0x48, 0x01, 0xac, 0x77, 0xb5, 0x2c, 0xde, 0x03, 0xd4, 0xae, 0x74, 0x9d, 0x02, 0x15, 0x5e, 0x5c, 0x70, 0xfc, 0x99, 0x5f, 0x48, 0x76, 0x72, 0xd2, 0x80, 0x63, 0x58, 0x55, 0xdb, 0x4b, 0x64, 0xa2, 0x26, 0x09, 0xb0, 0xc1, 0x60, 0x67, 0x16, 0x3c, 0x51, 0x90, 0x42, 0x05, 0x7c, 0xb3, 0x67, 0x12, 0xc7, 0xc2, 0xfe, 0xfe, 0xd1, 0x1f, 0x73, 0xc2, 0x8b, 0xdb, 0x9d, 0x25, 0xf0, 0x63, 0x6a, 0x4c, 0xaa, 0x11, 0x26, 0x9e, 0x5f, 0xe6, 0x5a, 0x2b, 0x17, 0x56, 0x86, 0xa1, 0x5f, 0x1e, 0x48, 0xd2, 0x8d, 0x34, 0x5d, 0xd9, 0xa1, 0xb2, 0x90, 0x0a, 0x24, 0xf9, 0xdd, 0xda, 0x3d, 0xf3, 0xa6, 0x9f, 0xfb, 0x9c, 0xf5, 0x04, 0x5a, 0xc4, 0xa1, 0x93, 0xae, 0x90, 0x2f } +, + /* Encryption */ + 192, + { 0x7d, 0x8c, 0x53, 0x1d, 0x4d, 0x35, 0x49, 0xe0, 0xbd, 0x2e, 0xe1, 0x62, 0xb6, 0x82, 0x53, 0x9d, 0xa6, 0x17, 0x22, 0xb8, 0x8e, 0xcf, 0x8c, 0x7d, 0xf6, 0xd6, 0xb8, 0x1f, 0xef, 0x50, 0x18, 0xbc, 0x4e, 0xa1, 0x0a, 0x7e, 0x1a, 0x4e, 0xaa, 0x02, 0x15, 0xd9, 0xb3, 0xcd, 0xf4, 0x13, 0x47, 0x92, 0x9e, 0xac, 0x27, 0x48, 0xeb, 0xd7, 0x79, 0x94, 0x5c, 0x9b, 0xc4, 0x61, 0xdc, 0x51, 0xf4, 0x8d, 0xf6, 0x52, 0x75, 0x53, 0xf0, 0x70, 0x37, 0xe5, 0x33, 0xce, 0xb1, 0x34, 0x8a, 0x46, 0xa7, 0xea, 0x79, 0x7d, 0x85, 0xa2, 0x6a, 0x9f, 0x44, 0xc5, 0x88, 0x69, 0x99, 0x6e, 0xf1, 0x14, 0x69, 0xbc, 0xc1, 0x0b, 0x75, 0x6c, 0x02, 0xd5, 0xc0, 0xe6, 0x18, 0x83, 0x68, 0x5c, 0xc3, 0x7d, 0x75, 0x8d, 0xfd, 0xe4, 0xc9, 0xb7, 0x35, 0x4e, 0x3b, 0x4f, 0x31, 0x6c, 0xa7, 0xf7, 0xfd, 0xe6, 0x59, 0xc3, 0xfd, 0x5e, 0x33, 0x2e, 0x1b, 0x63, 0x92, 0xa2, 0x92, 0x9e, 0x13, 0x17, 0x66, 0xce, 0x9b, 0xa1, 0xd9, 0x71, 0xad, 0x24, 0x6f, 0x3d, 0xf0, 0x22, 0x43, 0x38, 0x63, 0x8b, 0xb6, 0x53, 0x45, 0x8c, 0xd4, 0xb5, 0x26, 0xd9, 0x61, 0x74, 0x4d, 0xaf, 0xec, 0xd5, 0x99, 0x8a, 0xd7, 0x2a, 0xed, 0x3c, 0x34, 0x59, 0x9f, 0x7a, 0x40, 0x98, 0xe3, 0xd2, 0xdf, 0x9d, 0x13, 0xa2, 0x1c, 0xe2, 0x37, 0x0c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.17", + /* Message */ + 56, + { 0xa0, 0x34, 0xa6, 0xc1, 0x66, 0xcf, 0x0b, 0x25, 0xd2, 0xdd, 0xe5, 0x3a, 0xf4, 0xb8, 0x33, 0xb4, 0x78, 0xc6, 0xb0, 0xd2, 0xfb, 0x0c, 0xef, 0x13, 0x7f, 0xbf, 0x5c, 0x27, 0x12, 0x70, 0x64, 0x91, 0x23, 0x7f, 0x7b, 0x28, 0x6d, 0x12, 0x11, 0xd5, 0x73, 0x10, 0xf8, 0xa7, 0x62, 0xb1, 0xb3, 0xbf, 0xe1, 0x9c, 0x9a, 0x4b, 0x16, 0xd3, 0xe0, 0xa8 } +, + /* Seed */ + 133, + { 0xd8, 0x44, 0x17, 0x97, 0x22, 0x87, 0x13, 0x0a, 0x24, 0xa6, 0x06, 0xf5, 0x83, 0x29, 0x7a, 0xc9, 0x11, 0x52, 0x8a, 0xdc, 0xdb, 0xbd, 0x7d, 0xe1, 0x4a, 0x5b, 0x48, 0x9b, 0x67, 0x86, 0xf9, 0xf6, 0xf7, 0xe0, 0xb7, 0x3b, 0xab, 0x53, 0x8e, 0xb6, 0xc4, 0x5f, 0xf3, 0x4b, 0xd5, 0xdc, 0x43, 0xea, 0xe8, 0xd8, 0xc4, 0x3f, 0x71, 0x65, 0x16, 0xa6, 0x0d, 0xa2, 0x47, 0x53, 0x6f, 0x63, 0x4b, 0xe0, 0x65, 0xd9, 0x4e, 0x7f, 0x92, 0xad, 0xf5, 0x2a, 0x96, 0x7e, 0xe0, 0x5f, 0xd9, 0xaf, 0xd7, 0x32, 0x33, 0x3f, 0x99, 0xad, 0x05, 0x82, 0x97, 0xb2, 0x8f, 0x8e, 0xc6, 0xfe, 0xff, 0x80, 0x28, 0x44, 0xa0, 0x09, 0x7d, 0xf9, 0x1a, 0x97, 0x70, 0x2c, 0x48, 0x3a, 0xa1, 0xc7, 0x89, 0x2c, 0x7d, 0x43, 0xb6, 0xb9, 0x1c, 0xd4, 0xd8, 0x5d, 0x3e, 0xd2, 0xf1, 0xe9, 0x55, 0x39, 0x57, 0x06, 0xc3, 0xb3, 0x39, 0xba, 0xf2, 0xa0, 0xe0 } +, + /* Encryption */ + 192, + { 0x90, 0x4e, 0x04, 0x07, 0x23, 0xab, 0x97, 0x88, 0xa5, 0xed, 0x03, 0x52, 0xeb, 0x96, 0xc7, 0xf3, 0xd7, 0x07, 0xcf, 0x0d, 0xbc, 0x25, 0x8c, 0x51, 0xdc, 0xf6, 0x24, 0x34, 0x06, 0xf0, 0xc7, 0x42, 0xc6, 0xcd, 0xf2, 0x07, 0x67, 0x13, 0x2c, 0x09, 0x5e, 0x6c, 0x82, 0xa5, 0x02, 0x5b, 0xe7, 0xb4, 0x13, 0x4d, 0x8f, 0xa4, 0xde, 0x18, 0x7f, 0x8e, 0xcf, 0x12, 0xfd, 0xd3, 0xbe, 0xab, 0xdb, 0x06, 0x15, 0x8a, 0xef, 0x46, 0xc3, 0xfe, 0xd2, 0xd1, 0x83, 0x34, 0x06, 0xec, 0xa7, 0xa6, 0x9e, 0xb2, 0xd2, 0x08, 0xa2, 0xf6, 0xf4, 0x40, 0xd5, 0x4f, 0x6b, 0xe5, 0xdd, 0x56, 0x47, 0x09, 0xed, 0xa8, 0x12, 0xac, 0x06, 0x29, 0xa9, 0x4c, 0x7f, 0x8a, 0xee, 0x78, 0xbe, 0xaf, 0x9e, 0x93, 0x78, 0xc8, 0xdd, 0x9c, 0x62, 0x03, 0x74, 0xbb, 0xac, 0xa3, 0x94, 0x18, 0x59, 0xdd, 0x70, 0x2f, 0x6f, 0x7b, 0x25, 0xa2, 0x38, 0x45, 0x9e, 0xe8, 0x97, 0x59, 0xde, 0x94, 0x22, 0xb5, 0xbb, 0x6d, 0x28, 0x57, 0x16, 0x6c, 0xa2, 0x12, 0x0e, 0x63, 0x47, 0x74, 0xa0, 0xd1, 0xd4, 0x2e, 0xb8, 0xd9, 0x48, 0x15, 0xa1, 0x04, 0x4b, 0xea, 0x8b, 0xfb, 0x02, 0xda, 0x58, 0x62, 0xcd, 0x9a, 0x74, 0x5f, 0x15, 0x92, 0x47, 0x8c, 0x6f, 0x57, 0xbf, 0xd1, 0x3a, 0x5f, 0xdf, 0x4b, 0x8f, 0xaa, 0xe8, 0xa4, 0xbf, 0xc4 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.18", + /* Message */ + 35, + { 0x8f, 0xc6, 0x39, 0x4c, 0xd6, 0xe1, 0x75, 0x33, 0xd1, 0xff, 0x8e, 0xbb, 0xf3, 0xe1, 0xae, 0xae, 0xa3, 0x30, 0xed, 0x9f, 0x5a, 0x6e, 0x1e, 0xfb, 0x83, 0x45, 0x42, 0x94, 0xc6, 0xce, 0x24, 0xf6, 0x90, 0x4a, 0x0e } +, + /* Seed */ + 154, + { 0xbe, 0x1c, 0x18, 0x02, 0xdb, 0x44, 0x68, 0x2e, 0x58, 0xc6, 0x1f, 0xe3, 0x87, 0x57, 0xea, 0x0e, 0x38, 0x4e, 0xba, 0xdd, 0x79, 0x59, 0x48, 0x4b, 0x38, 0xbb, 0x23, 0x57, 0x55, 0xc4, 0x61, 0x77, 0xe6, 0x71, 0x76, 0x9f, 0x36, 0x57, 0x3d, 0x7c, 0xb0, 0xee, 0x7e, 0x82, 0x08, 0x7b, 0x58, 0x4b, 0x58, 0xbb, 0x30, 0x05, 0x30, 0x33, 0x68, 0xc6, 0x59, 0x0a, 0xd9, 0xf2, 0x88, 0x2c, 0xfa, 0x74, 0x0d, 0x51, 0xdc, 0x55, 0xeb, 0x0c, 0x79, 0x0f, 0x5b, 0xb6, 0xb6, 0xa3, 0xbd, 0x71, 0xf8, 0xb2, 0x14, 0x6b, 0xb9, 0xe8, 0x03, 0x4c, 0x35, 0xb7, 0xca, 0xbc, 0xbe, 0x10, 0x93, 0x6f, 0xfc, 0x5f, 0x0a, 0x8d, 0x7b, 0x30, 0x47, 0x6a, 0xb9, 0x16, 0x85, 0xae, 0xd8, 0xfa, 0x95, 0x8e, 0x73, 0xc1, 0xee, 0xa3, 0x04, 0x4c, 0x56, 0xb4, 0xb8, 0x70, 0xda, 0x89, 0x37, 0x1a, 0x93, 0xb8, 0x96, 0x52, 0x79, 0xb5, 0x5b, 0xb9, 0x2c, 0xc3, 0x16, 0xc2, 0x3e, 0xf0, 0x97, 0x53, 0x51, 0xc7, 0x49, 0x81, 0x7d, 0xb5, 0xdc, 0xd8, 0x6b, 0x94, 0xad, 0xf6, 0x03, 0xbd } +, + /* Encryption */ + 192, + { 0xb8, 0x3c, 0x71, 0x8c, 0xe5, 0xc6, 0xab, 0x1e, 0x40, 0xff, 0xa5, 0x67, 0x0a, 0xc1, 0x66, 0x66, 0x4d, 0x3a, 0x68, 0x33, 0xcb, 0x3b, 0xde, 0xf4, 0x62, 0x79, 0x4a, 0x25, 0xd5, 0x3e, 0x17, 0x04, 0x60, 0x06, 0x85, 0x8e, 0x63, 0xf8, 0x8a, 0xb9, 0x5d, 0x04, 0xf4, 0xfb, 0x67, 0x74, 0xf7, 0x00, 0x5d, 0xbb, 0x2e, 0x22, 0xd5, 0x19, 0x36, 0x0d, 0x5e, 0x13, 0x38, 0xad, 0x15, 0x30, 0x8f, 0x6c, 0x64, 0x12, 0x54, 0x95, 0x67, 0x00, 0x7e, 0x02, 0x1c, 0xb2, 0x37, 0xed, 0x4a, 0xf5, 0xee, 0xf3, 0xbc, 0xf9, 0xb7, 0x31, 0x59, 0x9f, 0x72, 0x53, 0xce, 0xba, 0x83, 0x04, 0xf4, 0xee, 0x8c, 0x34, 0x33, 0x39, 0xd0, 0xa0, 0x64, 0xeb, 0x77, 0xf1, 0xe9, 0x3f, 0xd1, 0xcc, 0x7b, 0xa5, 0xfc, 0x3b, 0xb8, 0x18, 0x4c, 0xed, 0x0e, 0x86, 0x97, 0xac, 0x47, 0xb7, 0x46, 0x20, 0xc4, 0x94, 0xea, 0xb5, 0x86, 0xed, 0x9f, 0xe7, 0x6e, 0x07, 0xe4, 0xbd, 0x2a, 0x2d, 0x1b, 0x95, 0x59, 0x5b, 0x69, 0xc6, 0x46, 0x77, 0xa8, 0x83, 0x5d, 0x56, 0xac, 0x63, 0x9d, 0xf8, 0xf6, 0x43, 0x24, 0x1b, 0x3e, 0x2c, 0x46, 0x88, 0xd2, 0xad, 0xf2, 0x28, 0xde, 0x2d, 0xa9, 0xbb, 0x0a, 0x36, 0x34, 0x38, 0xe7, 0x51, 0xb5, 0x25, 0x0d, 0xea, 0xe3, 0x05, 0xa3, 0x90, 0x5e, 0x7e, 0x07, 0x7a, 0x4e, 0x8c, 0x74, 0x66 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.19", + /* Message */ + 33, + { 0x89, 0xa1, 0x2d, 0x22, 0xbf, 0x87, 0x7d, 0x44, 0x0a, 0x2e, 0x03, 0xae, 0xa9, 0x32, 0xeb, 0x51, 0x83, 0x37, 0x9b, 0x3c, 0x8b, 0x90, 0xbe, 0xe8, 0xfe, 0xd6, 0xfc, 0x6d, 0xaf, 0xb0, 0xcf, 0x05, 0x27 } +, + /* Seed */ + 156, + { 0x60, 0x72, 0x89, 0x5e, 0x47, 0x80, 0xc8, 0xf7, 0x7e, 0x0b, 0x19, 0x5f, 0xc9, 0xf5, 0xdb, 0x78, 0x33, 0xf7, 0xb6, 0xf5, 0xc8, 0x1c, 0x1d, 0x30, 0xcb, 0xe9, 0xe8, 0x0c, 0xcb, 0x38, 0x66, 0x06, 0x9f, 0x8d, 0xb6, 0x96, 0x3a, 0xd4, 0x6d, 0x52, 0x94, 0x2a, 0x5a, 0x73, 0xf6, 0xa3, 0x27, 0xa9, 0x4e, 0xd1, 0x19, 0xdf, 0xce, 0x4c, 0x37, 0x65, 0x84, 0x37, 0x13, 0xb6, 0x19, 0xf9, 0xc4, 0x38, 0x32, 0x03, 0xd5, 0x5e, 0x2a, 0xb6, 0x1d, 0xa8, 0x96, 0x1a, 0x81, 0x03, 0x7f, 0x11, 0x18, 0xa7, 0x82, 0x97, 0xeb, 0x36, 0x6a, 0x1c, 0x51, 0xd9, 0xf9, 0x46, 0x6b, 0x71, 0x5b, 0xb6, 0x29, 0x99, 0xe0, 0xa9, 0xd6, 0xe0, 0x25, 0x01, 0xd4, 0x7f, 0x97, 0xdb, 0x40, 0x9e, 0x38, 0x86, 0xe1, 0x36, 0x6c, 0x3e, 0xff, 0x2b, 0xa7, 0x90, 0xe2, 0x62, 0x43, 0x22, 0x7a, 0xa1, 0x58, 0x80, 0x82, 0xbc, 0xe6, 0xd5, 0xcd, 0xe3, 0xea, 0x7e, 0xfb, 0xf1, 0x5c, 0x6c, 0x7d, 0xfa, 0x54, 0x54, 0x72, 0xfa, 0x9e, 0x93, 0x95, 0x6a, 0x45, 0x51, 0xd5, 0xa7, 0x7c, 0xa0, 0x0e, 0x26 } +, + /* Encryption */ + 192, + { 0xb7, 0xac, 0xbb, 0xcf, 0xf0, 0xfa, 0x9f, 0xca, 0x6f, 0x0b, 0xbd, 0xe5, 0xa2, 0xf0, 0xa1, 0xe6, 0xa0, 0xab, 0xad, 0xb3, 0x2c, 0x89, 0xe3, 0x17, 0x25, 0x5b, 0xd1, 0x8d, 0x12, 0xe1, 0xa6, 0x0b, 0x3e, 0x00, 0x2c, 0x1d, 0x69, 0x35, 0x64, 0x48, 0x32, 0x9a, 0x49, 0xb5, 0xbd, 0x24, 0x19, 0x10, 0xfa, 0x0c, 0xe0, 0x3b, 0x3e, 0x68, 0xa5, 0x90, 0x50, 0x75, 0x99, 0x39, 0x1e, 0xd1, 0x53, 0x97, 0x92, 0x29, 0x3f, 0xef, 0x13, 0x17, 0x4d, 0xac, 0xea, 0x6d, 0x2a, 0x05, 0xb3, 0x9f, 0x68, 0x48, 0x28, 0xa5, 0xd6, 0xd2, 0x17, 0xf8, 0x4b, 0x78, 0x2c, 0x8f, 0xc9, 0x84, 0x3c, 0xaf, 0x6a, 0xeb, 0x17, 0x8f, 0x0e, 0x2c, 0x6b, 0xd2, 0xa0, 0xe6, 0xf7, 0xb8, 0x09, 0x29, 0x61, 0x17, 0xcc, 0x8a, 0x6b, 0xf7, 0x37, 0x35, 0x84, 0x64, 0x24, 0xad, 0xeb, 0xa1, 0xab, 0x31, 0x14, 0x5f, 0xca, 0x3b, 0x8a, 0xf7, 0x68, 0xc9, 0xd0, 0xa2, 0x8e, 0x09, 0xd5, 0x8a, 0xd4, 0x96, 0x42, 0x31, 0x08, 0xf0, 0x8c, 0xaa, 0xc1, 0x74, 0xac, 0xd1, 0xf3, 0xac, 0x43, 0x48, 0x69, 0x61, 0xc5, 0xc9, 0x0e, 0x1e, 0xfb, 0x89, 0xbd, 0xdb, 0x7b, 0xb3, 0x9f, 0x4c, 0xa3, 0xaf, 0x57, 0x12, 0xf5, 0x53, 0xaf, 0x59, 0x4c, 0xd5, 0xd3, 0x64, 0x13, 0x29, 0x14, 0x26, 0x10, 0x07, 0xaa, 0x1d, 0x5f, 0x21, 0x6b, 0x8e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 14.20", + /* Message */ + 54, + { 0x09, 0xd6, 0x94, 0x8c, 0xe1, 0xc1, 0xf2, 0x4c, 0x6d, 0x52, 0x9c, 0xbc, 0x5d, 0x6d, 0x6c, 0x1b, 0xea, 0xab, 0x56, 0x95, 0xb3, 0x0c, 0xaa, 0xb7, 0x44, 0x96, 0x9b, 0xf7, 0xf9, 0xdb, 0xd2, 0x83, 0x33, 0x5e, 0x98, 0xa9, 0xbc, 0xd6, 0x5d, 0xad, 0x2b, 0x4f, 0x0e, 0x3c, 0xec, 0x89, 0x0b, 0x05, 0xe6, 0x7f, 0xe9, 0x78, 0x23, 0xd4 } +, + /* Seed */ + 135, + { 0xed, 0xed, 0x62, 0xa6, 0x50, 0xf7, 0xde, 0x3b, 0x12, 0x80, 0x22, 0x9d, 0x5f, 0xb1, 0xc4, 0x40, 0x8e, 0x82, 0xdf, 0xe0, 0x31, 0x7e, 0x64, 0x30, 0xfc, 0xf4, 0x71, 0xb1, 0xe2, 0x8d, 0xa8, 0xcf, 0x6b, 0x4b, 0xf4, 0xc5, 0xd0, 0x31, 0xe3, 0xee, 0x68, 0x8b, 0x64, 0x07, 0x72, 0xaa, 0x50, 0x08, 0xe5, 0x86, 0x3c, 0x70, 0x7a, 0x40, 0x22, 0xc3, 0x29, 0xa6, 0x66, 0x4e, 0x71, 0x10, 0x12, 0x06, 0xb5, 0x4d, 0xb5, 0x40, 0x6e, 0x7f, 0xa9, 0xc8, 0x22, 0x6f, 0x42, 0x93, 0x11, 0x19, 0x62, 0x0c, 0xa3, 0x0d, 0xe7, 0xd0, 0x3b, 0xe1, 0x43, 0x94, 0x0c, 0xbb, 0x4d, 0x1a, 0x9c, 0x86, 0xe9, 0x86, 0x3c, 0x98, 0x7b, 0xff, 0x07, 0x02, 0x3d, 0xe1, 0x98, 0x64, 0xf7, 0x33, 0xda, 0x0c, 0x89, 0xbd, 0x03, 0x9f, 0x19, 0xf4, 0xd8, 0xed, 0x61, 0x6f, 0x7c, 0x6e, 0x94, 0x94, 0x18, 0x5b, 0x60, 0x4a, 0x1a, 0x7b, 0xf7, 0x49, 0x0f, 0xd0, 0xd8 } +, + /* Encryption */ + 192, + { 0x7a, 0xdd, 0xb0, 0x5c, 0xbf, 0x0b, 0x17, 0xaa, 0x50, 0x8a, 0x0b, 0x17, 0x0c, 0x4c, 0x5a, 0xee, 0x84, 0xce, 0x06, 0x65, 0x0d, 0x08, 0xc9, 0x96, 0x6d, 0x95, 0xd3, 0x07, 0x1a, 0x9a, 0x8f, 0x3a, 0x93, 0xf9, 0x6a, 0x87, 0x53, 0x99, 0xb4, 0x78, 0xc2, 0x56, 0xd0, 0x41, 0x5e, 0x74, 0x84, 0x95, 0x98, 0x21, 0x1f, 0x9f, 0x9d, 0x0b, 0x89, 0x36, 0x7b, 0xaa, 0xaf, 0x17, 0x4b, 0x7f, 0x13, 0xd8, 0x49, 0x0b, 0xaa, 0xa7, 0x40, 0x96, 0x1f, 0x52, 0xd7, 0xe3, 0x53, 0xc5, 0x04, 0x81, 0x8a, 0x00, 0x0b, 0x03, 0x67, 0x4d, 0x9c, 0xe4, 0x93, 0xdc, 0x3a, 0x4e, 0xe9, 0x16, 0x13, 0x01, 0xf6, 0x1d, 0xe5, 0x21, 0xae, 0xf3, 0xf6, 0xd4, 0x1d, 0x82, 0xe1, 0xc5, 0xdc, 0xe0, 0x2e, 0x63, 0x6e, 0x77, 0x40, 0xa1, 0x83, 0xf8, 0x02, 0x3a, 0xd2, 0x61, 0x49, 0x41, 0xd9, 0xb1, 0x61, 0xcd, 0xbd, 0xf4, 0x8f, 0x8a, 0x56, 0x2c, 0x8f, 0xfe, 0x44, 0xf5, 0x7a, 0x74, 0x6f, 0x26, 0x39, 0xe5, 0xe8, 0x3b, 0xcf, 0xd3, 0x92, 0xd2, 0x3e, 0x1f, 0xb4, 0xa8, 0xd8, 0x5e, 0x3b, 0xa5, 0xe1, 0xcb, 0x9c, 0x0e, 0x53, 0xf0, 0xd9, 0x1b, 0x01, 0xce, 0xc0, 0xf0, 0xef, 0x9d, 0xfe, 0x3f, 0x2b, 0x30, 0x65, 0xbd, 0x55, 0xb7, 0x2f, 0xb1, 0x70, 0x60, 0xab, 0xe8, 0x83, 0x0a, 0xca, 0x00, 0x44, 0x64, 0xfe, 0x7d } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 15: A 2048-bit RSA key pair", +{ + /* Modulus */ + 256, + { 0xdc, 0xfa, 0x10, 0xff, 0xa7, 0x46, 0x65, 0xae, 0xef, 0x87, 0x09, 0x74, 0xea, 0x99, 0xb2, 0xce, 0x54, 0x54, 0x7c, 0x67, 0xf4, 0x2a, 0xaa, 0x6d, 0xd0, 0x1a, 0x2e, 0xd3, 0x1f, 0xd2, 0xc2, 0x42, 0xaf, 0x5d, 0x96, 0x0b, 0x1f, 0x89, 0x6e, 0xfb, 0xa3, 0x54, 0x3d, 0x65, 0x54, 0xb7, 0xb1, 0x26, 0x87, 0xa5, 0xc6, 0x88, 0x56, 0x8f, 0x32, 0xe0, 0x26, 0xc5, 0x32, 0xd2, 0x59, 0x93, 0xb9, 0x7a, 0x7c, 0x28, 0x42, 0xec, 0x2b, 0x8e, 0x12, 0x35, 0xee, 0xe2, 0x41, 0x4d, 0x25, 0x80, 0x6c, 0x6f, 0xba, 0xe4, 0x38, 0x95, 0x4e, 0xba, 0x9d, 0x27, 0x55, 0xdf, 0xfe, 0xeb, 0x1b, 0x47, 0x70, 0x09, 0x57, 0x81, 0x5a, 0x8a, 0x23, 0x3f, 0x97, 0xb1, 0xa2, 0xc7, 0x14, 0xb3, 0xe2, 0xbe, 0x2e, 0x42, 0xd8, 0xbe, 0x30, 0xb1, 0x96, 0x15, 0x82, 0xea, 0x99, 0x48, 0x91, 0x0e, 0x0c, 0x79, 0x7c, 0x50, 0xfc, 0x4b, 0xb4, 0x55, 0xf0, 0xfc, 0x45, 0xe5, 0xe3, 0x4e, 0x63, 0x96, 0xac, 0x5b, 0x2d, 0x46, 0x23, 0x93, 0x65, 0xc7, 0xf3, 0xda, 0xaf, 0x09, 0x09, 0x40, 0x0d, 0x61, 0xcf, 0x9e, 0x0c, 0xa8, 0x08, 0x3e, 0xaf, 0x33, 0x5a, 0x6f, 0xce, 0xb6, 0x86, 0x3c, 0x1c, 0xc0, 0xcf, 0x5a, 0x17, 0x1a, 0xff, 0x35, 0xd9, 0x7e, 0xcb, 0x60, 0xef, 0x25, 0x1c, 0x7e, 0xc2, 0xc8, 0xa5, 0x88, 0x36, 0x1d, 0xc4, 0x12, 0x66, 0xa4, 0xb7, 0xed, 0x38, 0xb0, 0x26, 0xce, 0x0d, 0x53, 0x78, 0x64, 0x49, 0xdb, 0xb1, 0x1a, 0x06, 0xea, 0x33, 0xcc, 0xf1, 0xec, 0xa5, 0x75, 0x20, 0x1e, 0xd1, 0xaa, 0x47, 0x3e, 0xd1, 0x18, 0x7e, 0xc1, 0xd8, 0xa7, 0x44, 0xea, 0x34, 0x5b, 0xed, 0x7e, 0xa0, 0x0e, 0xe4, 0xe8, 0x1b, 0xba, 0x46, 0x48, 0x60, 0x1d, 0xd5, 0x37, 0xdc, 0x91, 0x01, 0x5d, 0x31, 0xf0, 0xc2, 0xc1 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 256, + { 0x21, 0x95, 0x08, 0x51, 0xcd, 0xf2, 0x53, 0x20, 0x31, 0x8b, 0x30, 0x5a, 0xfa, 0x0f, 0x37, 0x1f, 0x07, 0xae, 0x5a, 0x44, 0xb3, 0x14, 0xeb, 0xd7, 0x29, 0xf5, 0xdc, 0xb1, 0x5d, 0xa7, 0xfa, 0x39, 0x47, 0xac, 0xdd, 0x91, 0x5d, 0xae, 0xd5, 0x74, 0xbd, 0x16, 0xdf, 0x88, 0xbf, 0x85, 0xf6, 0x10, 0x60, 0xb3, 0x87, 0x17, 0x2f, 0xae, 0x6e, 0x01, 0x26, 0x2b, 0x38, 0x64, 0xc2, 0xd3, 0xc2, 0x2f, 0x94, 0xe0, 0x4a, 0x81, 0x59, 0x42, 0x2b, 0x4e, 0xd2, 0x79, 0xc4, 0x8a, 0x4c, 0x9d, 0x76, 0x7d, 0x49, 0x66, 0x07, 0x1a, 0x5b, 0xbf, 0x5d, 0x04, 0x3e, 0x16, 0xff, 0x46, 0xec, 0x1b, 0xa0, 0x71, 0x6f, 0x00, 0xbb, 0xc9, 0x7b, 0xff, 0x5d, 0x56, 0x93, 0xe2, 0x14, 0xe9, 0x9c, 0x97, 0x21, 0xf1, 0x2b, 0x3e, 0xc6, 0x28, 0x2a, 0xe2, 0xa4, 0x85, 0x72, 0x1b, 0x96, 0xdd, 0xcf, 0x74, 0x03, 0xfa, 0x03, 0x7d, 0x0c, 0x57, 0xab, 0x46, 0x3c, 0x44, 0x8d, 0xe5, 0xcc, 0x12, 0x26, 0x5a, 0xdd, 0x88, 0x6d, 0x31, 0x1e, 0xa8, 0xd8, 0xa5, 0x90, 0x3f, 0xa5, 0x6c, 0x5f, 0x1c, 0x9c, 0xf2, 0xeb, 0x11, 0xcb, 0x65, 0x7a, 0x1a, 0x7d, 0x3e, 0x41, 0x35, 0x2d, 0xc3, 0xe6, 0x86, 0x89, 0x8c, 0x4c, 0xe4, 0x30, 0x5e, 0x8b, 0x63, 0x8e, 0x1b, 0x08, 0xa2, 0xa8, 0x6c, 0xc9, 0xeb, 0x98, 0x66, 0xf3, 0x49, 0x9a, 0xc7, 0x7b, 0x61, 0x36, 0xb8, 0x1c, 0xb2, 0x76, 0xd6, 0x14, 0xcf, 0xeb, 0x7b, 0x6e, 0xd3, 0xf3, 0xbc, 0x77, 0x5e, 0x46, 0xc0, 0x00, 0x66, 0xeb, 0xee, 0xe2, 0xcf, 0xf7, 0x16, 0x6b, 0x57, 0x52, 0x05, 0x98, 0x94, 0x7f, 0xf6, 0x21, 0x03, 0x20, 0xb2, 0x88, 0xfb, 0x4f, 0x2c, 0x3f, 0x8f, 0xe9, 0x7b, 0x27, 0x94, 0x14, 0xeb, 0xf7, 0x20, 0x30, 0x00, 0xa1, 0x9f, 0xc0, 0x42, 0x48, 0x75 } +, + /* Prime 1 */ + 128, + { 0xf1, 0x23, 0xbf, 0xe5, 0x3d, 0xe9, 0x7a, 0x56, 0x9d, 0x91, 0xad, 0xcf, 0x55, 0x6f, 0xa6, 0x25, 0xad, 0x30, 0xf3, 0xfd, 0x3d, 0x81, 0x1f, 0x9e, 0x91, 0xe6, 0xaf, 0x44, 0xb6, 0xe7, 0x80, 0xcb, 0x0f, 0x32, 0x78, 0x29, 0xfb, 0x21, 0x19, 0x0a, 0xe2, 0x80, 0x66, 0x46, 0xd7, 0x28, 0xcd, 0x9b, 0x65, 0x31, 0x13, 0x2b, 0x1e, 0xbf, 0xef, 0x12, 0x72, 0x99, 0x30, 0x60, 0xf1, 0xce, 0x70, 0xb1, 0x24, 0x39, 0x30, 0x91, 0xee, 0x85, 0x93, 0xb7, 0x27, 0x36, 0x7e, 0xdb, 0xba, 0x00, 0x9e, 0xc5, 0xbe, 0x17, 0xc4, 0xac, 0xee, 0x12, 0x0c, 0x84, 0x12, 0x67, 0xd4, 0x76, 0x31, 0xa1, 0x6c, 0x36, 0xa6, 0xd1, 0xc9, 0x99, 0x73, 0xc1, 0xb0, 0xb5, 0xa8, 0x35, 0xbf, 0x39, 0xfe, 0xaf, 0xe8, 0xf6, 0x42, 0x1f, 0xd9, 0xc2, 0xa9, 0x0b, 0xc2, 0x79, 0x76, 0x65, 0x9e, 0x67, 0xbc, 0x83, 0x12, 0x4d } +, + /* Prime 2 */ + 128, + { 0xea, 0x98, 0x39, 0xb7, 0xe3, 0x7e, 0xa8, 0x9b, 0xbd, 0xa2, 0x7e, 0x4c, 0x93, 0x47, 0x1c, 0xb4, 0xfd, 0x92, 0x18, 0x9a, 0x0a, 0x96, 0xbc, 0xb4, 0xd7, 0x56, 0x93, 0xf1, 0x8a, 0x5c, 0x2f, 0x74, 0x2a, 0xf9, 0xe3, 0x6f, 0xde, 0x67, 0x9f, 0xbd, 0x9e, 0xae, 0x34, 0x5f, 0xa2, 0x69, 0x52, 0x7b, 0x69, 0x65, 0x02, 0x1c, 0x4b, 0xdf, 0x54, 0xd6, 0x85, 0xbf, 0x08, 0x96, 0x0c, 0xc9, 0x76, 0xf6, 0x8d, 0xca, 0x21, 0xce, 0xbf, 0x44, 0xf2, 0x68, 0xa5, 0x9d, 0xab, 0x8d, 0x1a, 0x25, 0xe5, 0x19, 0xf5, 0x14, 0x7e, 0x1f, 0x45, 0xfe, 0x28, 0x7d, 0x74, 0xcf, 0x72, 0x5b, 0xec, 0x13, 0x26, 0xd3, 0x42, 0x12, 0xc5, 0x6c, 0xf4, 0xff, 0xfa, 0x20, 0x2f, 0x57, 0xb6, 0x8e, 0xe8, 0xcc, 0xa9, 0x43, 0xf3, 0xc1, 0x38, 0xc4, 0xcd, 0xe3, 0x3b, 0xdf, 0x2c, 0x94, 0x40, 0xdf, 0x65, 0x32, 0x24, 0x45 } +, + /* Prime exponent 1 */ + 128, + { 0xca, 0x0c, 0x9b, 0x60, 0xb8, 0xe4, 0xa6, 0x06, 0x67, 0x56, 0xc6, 0x5d, 0x20, 0x88, 0x41, 0x9d, 0xf6, 0x25, 0x3b, 0x7b, 0x68, 0x8a, 0x85, 0xf4, 0xf6, 0xe9, 0x64, 0xd8, 0x5d, 0xad, 0x52, 0xa4, 0x52, 0x62, 0x86, 0x7f, 0x1e, 0x96, 0x18, 0x06, 0x9f, 0xcc, 0xd8, 0x65, 0xe9, 0x28, 0x9e, 0x46, 0xe3, 0x9e, 0x20, 0x22, 0x94, 0x4c, 0x5c, 0x44, 0x87, 0xd3, 0x45, 0xcf, 0x25, 0x2d, 0x46, 0x0d, 0x97, 0x7d, 0x77, 0xed, 0xfe, 0xfe, 0xdb, 0xcb, 0xae, 0x46, 0xa2, 0x3a, 0xf7, 0xfa, 0x47, 0x0f, 0x07, 0x7d, 0xa0, 0xe5, 0x09, 0x42, 0x04, 0x4c, 0xb1, 0xa3, 0x60, 0x49, 0x7c, 0xc2, 0x76, 0x0a, 0xc0, 0xf2, 0xad, 0x4a, 0x2f, 0xcd, 0x0e, 0x84, 0xd7, 0xa1, 0xd9, 0x4d, 0xfd, 0xd2, 0x65, 0x8f, 0xd9, 0xce, 0x18, 0x47, 0x5c, 0x1f, 0xa7, 0x5e, 0xe0, 0xce, 0xba, 0xd0, 0xcf, 0x0a, 0xc0, 0x4d } +, + /* Prime exponent 2 */ + 128, + { 0x52, 0x81, 0x71, 0x23, 0x3c, 0x4e, 0x4a, 0x6c, 0x63, 0xb8, 0x67, 0x64, 0xf5, 0x13, 0x38, 0x84, 0x6a, 0xfd, 0xdb, 0xcb, 0x29, 0x58, 0x34, 0x4c, 0x01, 0xc4, 0x00, 0x4a, 0x1d, 0xd8, 0x28, 0x14, 0x5a, 0x1d, 0x02, 0xa1, 0x50, 0x7d, 0xef, 0x4f, 0x58, 0x24, 0x7a, 0x64, 0xfc, 0x10, 0xc0, 0xa2, 0x88, 0xc1, 0xae, 0x89, 0x57, 0x21, 0xd7, 0x8b, 0x8f, 0x04, 0x4d, 0xb7, 0xc0, 0x0d, 0x86, 0xda, 0x55, 0xa9, 0xb6, 0x54, 0x29, 0x2e, 0xcd, 0x76, 0x82, 0x70, 0xbe, 0x69, 0xe4, 0xbd, 0x59, 0x22, 0xd4, 0xef, 0xfd, 0x1f, 0x70, 0x95, 0x5f, 0x96, 0x27, 0xe3, 0xe1, 0x9b, 0x74, 0x9e, 0x93, 0xb4, 0x0e, 0xf3, 0xdd, 0x1d, 0x61, 0xd9, 0x39, 0x15, 0xe2, 0xb0, 0x9d, 0x93, 0x0b, 0x4b, 0x17, 0x68, 0xbf, 0xac, 0xc0, 0x13, 0x6f, 0x39, 0xb0, 0xcf, 0xdf, 0xb4, 0xd0, 0x50, 0x01, 0x1e, 0x2e, 0x65 } +, + /* Coefficient */ + 128, + { 0xdf, 0x2e, 0xb2, 0x32, 0x2c, 0xc2, 0xda, 0xab, 0xf4, 0xd1, 0x46, 0x55, 0x08, 0xf4, 0x15, 0x21, 0xcd, 0xa7, 0xce, 0xff, 0x23, 0xeb, 0xe6, 0x1d, 0x00, 0xd4, 0x41, 0xee, 0x72, 0x8d, 0xda, 0x5d, 0x16, 0xc7, 0xbf, 0x92, 0x0c, 0xd9, 0x5f, 0x34, 0xbe, 0xb4, 0xfe, 0x32, 0xee, 0x81, 0x7e, 0xf3, 0x36, 0x2e, 0x0b, 0xcd, 0x1d, 0x12, 0x45, 0xf7, 0xb0, 0x77, 0x93, 0xea, 0xa1, 0x90, 0xdc, 0x5a, 0x37, 0xfd, 0xaf, 0x4c, 0x68, 0xe2, 0xca, 0x13, 0x97, 0x2d, 0x7f, 0x51, 0x48, 0xb7, 0x96, 0xb6, 0xfb, 0x6d, 0x7a, 0xdd, 0xa0, 0x7b, 0xd2, 0xcd, 0x13, 0xbe, 0x98, 0xce, 0xbe, 0xd1, 0xed, 0xc6, 0xca, 0x41, 0x2e, 0x39, 0x53, 0x50, 0xc5, 0x9a, 0x1d, 0x84, 0x2b, 0xc4, 0xaa, 0x2f, 0x3c, 0x0b, 0x24, 0x3f, 0xde, 0x7d, 0xfd, 0x95, 0x35, 0x6f, 0x24, 0x39, 0x25, 0x1a, 0x11, 0x72, 0xc4, 0x5e } + +} +, +{{ + "PKCS#1 v1.5 Encryption Example 15.1", + /* Message */ + 19, + { 0x2a, 0xac, 0xec, 0x86, 0xf4, 0x23, 0xdd, 0x92, 0x5e, 0xc1, 0x58, 0x82, 0x2a, 0x74, 0x8c, 0xbe, 0x6c, 0x31, 0xa0 } +, + /* Seed */ + 234, + { 0xcc, 0x4b, 0x87, 0xf6, 0x74, 0x49, 0x7b, 0xb0, 0xe3, 0x3d, 0x9e, 0x2a, 0x4a, 0x80, 0x70, 0xb7, 0xd7, 0x8b, 0x5f, 0xd2, 0xc4, 0xb4, 0xf6, 0xeb, 0xac, 0xcd, 0x4e, 0xe5, 0x05, 0xb7, 0x1f, 0xca, 0xfe, 0x21, 0x56, 0x33, 0x7d, 0xdf, 0x27, 0xb4, 0x75, 0xaf, 0x33, 0xf6, 0xc3, 0x40, 0x5b, 0x8e, 0x3c, 0x0c, 0x20, 0x6e, 0xc2, 0x81, 0x29, 0x22, 0xfc, 0xd8, 0xa3, 0x66, 0x1b, 0x86, 0x19, 0xbb, 0xc1, 0x82, 0xf8, 0x07, 0xf3, 0xa1, 0x07, 0x2e, 0x62, 0xca, 0x2b, 0xf1, 0xfa, 0x8b, 0x94, 0x4e, 0x58, 0xa0, 0xe2, 0x03, 0xdb, 0xb7, 0x53, 0xf9, 0xf1, 0xb6, 0xef, 0x62, 0x7e, 0xbe, 0xe5, 0x98, 0x96, 0x7b, 0x38, 0x7a, 0x5f, 0x96, 0x36, 0xd8, 0xb6, 0x41, 0xb3, 0x89, 0x84, 0xb1, 0xca, 0x03, 0x7e, 0x3a, 0xae, 0xaa, 0x17, 0x10, 0xf5, 0x16, 0x25, 0xea, 0x85, 0xf8, 0xfb, 0x9a, 0x6e, 0x02, 0x9e, 0x64, 0x57, 0x58, 0x14, 0xd5, 0x30, 0xfc, 0x14, 0x6b, 0x34, 0x45, 0xac, 0x42, 0x01, 0xb4, 0xe4, 0x08, 0xad, 0xf6, 0x55, 0xf6, 0x78, 0x43, 0xd8, 0x87, 0x1c, 0xac, 0xe5, 0xd9, 0x06, 0xd7, 0xfc, 0x03, 0x8f, 0xea, 0x88, 0x5b, 0x96, 0xfb, 0x8e, 0xb1, 0xa7, 0x21, 0xc6, 0xc1, 0x4a, 0xbb, 0xeb, 0x78, 0xfb, 0x4c, 0x79, 0x8a, 0x19, 0x58, 0x99, 0x59, 0x89, 0x84, 0x55, 0xa3, 0x16, 0x84, 0x3c, 0x6c, 0xd9, 0x9e, 0xf5, 0x8c, 0x2b, 0x0b, 0x49, 0xb8, 0xab, 0x41, 0x91, 0xb4, 0x02, 0xa5, 0x4c, 0x92, 0x97, 0x31, 0x0c, 0xd2, 0x24, 0xb1, 0x7f, 0x21, 0x41, 0x67, 0x72, 0x5c, 0x48, 0xfc, 0xc6, 0x1b, 0xc4, 0x7c, 0xfa, 0xcc, 0xf1, 0x5e, 0xb3, 0xb0 } +, + /* Encryption */ + 256, + { 0x60, 0x42, 0xe7, 0x45, 0x58, 0x9a, 0xf0, 0x3a, 0xf8, 0x75, 0x20, 0xf9, 0x3c, 0x45, 0xd8, 0xc3, 0x59, 0x85, 0xad, 0xa1, 0x16, 0x1a, 0x37, 0xd8, 0x22, 0xe9, 0xf9, 0x46, 0x0f, 0xc7, 0x5f, 0xcf, 0x01, 0x79, 0xd8, 0x49, 0x1b, 0x8f, 0x5d, 0x1e, 0x4d, 0xe8, 0xce, 0xb3, 0x1e, 0x07, 0xc4, 0x86, 0x5c, 0x5a, 0x3e, 0xfd, 0xbb, 0xb6, 0x9a, 0x88, 0x03, 0xb8, 0x9e, 0xe6, 0x5a, 0x43, 0x0a, 0x58, 0x09, 0xc7, 0x07, 0x56, 0x91, 0x50, 0xb5, 0x80, 0xbb, 0x68, 0x6a, 0x94, 0xc5, 0x54, 0x1c, 0x46, 0xad, 0xcd, 0x82, 0x79, 0x60, 0xce, 0x24, 0x4f, 0xf6, 0x88, 0x38, 0x7d, 0x16, 0x16, 0xe8, 0x5b, 0x4d, 0x17, 0x80, 0xc6, 0x48, 0x36, 0x06, 0xcf, 0x92, 0x4b, 0x54, 0xf0, 0x80, 0xcf, 0x41, 0x54, 0xe6, 0x68, 0x29, 0xbf, 0x6e, 0x53, 0x24, 0x81, 0x04, 0x8e, 0xc4, 0x1f, 0xad, 0xc0, 0x7d, 0x75, 0x5b, 0xb3, 0x4b, 0xb2, 0x81, 0x45, 0x21, 0x9c, 0xb3, 0x0d, 0x47, 0xd0, 0xd6, 0x18, 0x70, 0x91, 0x80, 0xe9, 0x03, 0x03, 0xff, 0x9e, 0xf0, 0x90, 0x18, 0xbe, 0xd3, 0xda, 0x75, 0x76, 0x1d, 0xa7, 0x94, 0x81, 0x1f, 0x96, 0xbc, 0x9e, 0x8d, 0x7c, 0x4b, 0xa1, 0xb5, 0x94, 0x6b, 0xda, 0x0b, 0xd3, 0x13, 0xfa, 0xec, 0x4c, 0x99, 0x3e, 0xd2, 0x74, 0x8e, 0xed, 0x8c, 0xce, 0x4b, 0xdb, 0x52, 0x0b, 0xa7, 0xdb, 0x16, 0x5f, 0x9f, 0xe5, 0x6a, 0xa8, 0x45, 0x4d, 0x6f, 0xf3, 0x38, 0x74, 0xfe, 0xee, 0xbf, 0x29, 0xde, 0x2d, 0xf5, 0xb7, 0xf0, 0x0a, 0xa1, 0xd9, 0xfb, 0x07, 0x3f, 0xc4, 0x06, 0x7b, 0x58, 0xdc, 0x50, 0x62, 0x4e, 0x12, 0x7f, 0x71, 0x1d, 0xde, 0x2c, 0xc2, 0xcf, 0xda, 0xb4, 0x91, 0x9c, 0xcf, 0x28, 0xc8, 0x36, 0x60, 0xdf, 0xc2, 0x27, 0xb0, 0xf5, 0x00, 0xec, 0x1f, 0x90, 0x4f } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Encryption Example 15.2", + /* Message */ + 21, + { 0x5c, 0x8b, 0xf2, 0xac, 0xab, 0x08, 0xbf, 0xfe, 0xfa, 0x64, 0x80, 0x95, 0x2b, 0x24, 0xda, 0xa5, 0x01, 0x9d, 0x12, 0x5f, 0xee } +, + /* Seed */ + 232, + { 0x5e, 0x16, 0x30, 0x70, 0xef, 0xdd, 0xb7, 0x9f, 0x47, 0x64, 0xf8, 0xa8, 0x1d, 0x44, 0x46, 0x0b, 0x5c, 0x40, 0x0b, 0xec, 0x70, 0x37, 0x52, 0x29, 0x20, 0xf7, 0x72, 0x95, 0x9f, 0xd4, 0xcf, 0x3a, 0xef, 0x2f, 0x14, 0x45, 0x4d, 0xcd, 0x9e, 0x86, 0x25, 0x12, 0xca, 0x69, 0xdb, 0x83, 0x68, 0xa4, 0xcd, 0x8d, 0x1a, 0x44, 0xda, 0x59, 0x5d, 0x6b, 0x43, 0x93, 0x91, 0xc9, 0x31, 0x46, 0xb1, 0x23, 0xf1, 0x86, 0x08, 0x3c, 0x4b, 0x64, 0x47, 0xbf, 0x7e, 0x20, 0x81, 0x51, 0x46, 0xac, 0x75, 0x49, 0xef, 0xb6, 0x74, 0x60, 0xe8, 0xff, 0x1b, 0x2b, 0xba, 0x5c, 0x95, 0xa5, 0x1e, 0xf8, 0x13, 0xd5, 0xdc, 0x4e, 0x6c, 0x38, 0x92, 0xbc, 0x4f, 0x43, 0x9c, 0x99, 0x11, 0x7e, 0xd0, 0x6c, 0x14, 0xa6, 0xc5, 0x40, 0xfd, 0x4c, 0x65, 0xd1, 0x95, 0xd8, 0xc6, 0x1e, 0xa7, 0x79, 0x68, 0x38, 0xe5, 0xa5, 0xdf, 0xaf, 0x11, 0xd0, 0x71, 0x3c, 0x19, 0x1e, 0x8a, 0x0b, 0x80, 0x80, 0xf7, 0xa7, 0x7e, 0x70, 0x3a, 0xb3, 0x66, 0x22, 0xf1, 0xc6, 0x48, 0xb7, 0x65, 0x43, 0x5b, 0x90, 0x27, 0x97, 0x18, 0x11, 0xb1, 0x15, 0x2d, 0x97, 0x2f, 0xb7, 0x6a, 0xa8, 0x92, 0x05, 0x03, 0x3d, 0x95, 0x78, 0x18, 0x7a, 0xe6, 0x34, 0x88, 0xfd, 0xa3, 0xc8, 0x6b, 0x2f, 0x28, 0xe7, 0x79, 0xac, 0x4c, 0x89, 0xcd, 0x25, 0x20, 0x17, 0xd1, 0xa9, 0x95, 0x8a, 0x52, 0xc5, 0xb8, 0x7e, 0xc1, 0xbf, 0x9c, 0xbd, 0xf7, 0xde, 0x0e, 0x97, 0xc5, 0x8b, 0xa1, 0x1b, 0xa3, 0xa3, 0x37, 0x05, 0xf3, 0xf4, 0x99, 0x58, 0x9a, 0x3a, 0x72, 0xe2, 0xc0, 0xfc, 0x5b, 0x16, 0xfc, 0xa2 } +, + /* Encryption */ + 256, + { 0x44, 0xe6, 0x71, 0xe0, 0x3b, 0xb6, 0x67, 0x80, 0xec, 0x05, 0x86, 0xd5, 0x6f, 0x8f, 0x6a, 0x49, 0x41, 0x5a, 0xd4, 0xbb, 0xce, 0x22, 0x6d, 0x75, 0xd7, 0x0f, 0x06, 0xce, 0x29, 0xde, 0xea, 0x7d, 0xa1, 0xaf, 0xa8, 0x28, 0x7e, 0x44, 0x36, 0x3c, 0x51, 0x0f, 0x34, 0xeb, 0x8b, 0xf3, 0x1c, 0xa2, 0x47, 0x29, 0x59, 0x26, 0x9c, 0x18, 0xdf, 0x09, 0x36, 0xff, 0x12, 0xc6, 0x16, 0x6f, 0x4f, 0x45, 0x96, 0xcb, 0x1c, 0xae, 0xc4, 0x1d, 0xed, 0xa8, 0xc5, 0x09, 0x99, 0xbf, 0x4c, 0x94, 0x4d, 0x21, 0x37, 0x5b, 0x36, 0x75, 0x31, 0x91, 0xb4, 0xcb, 0x7c, 0xaa, 0x1b, 0x43, 0xe9, 0x11, 0x6c, 0xbf, 0x1d, 0xa8, 0xb2, 0x01, 0xd2, 0x97, 0xa4, 0xd0, 0x8b, 0xb0, 0xe5, 0xbd, 0xc8, 0x95, 0x32, 0x70, 0xf7, 0xc2, 0x80, 0x96, 0x78, 0xc4, 0x4b, 0xea, 0x75, 0xe8, 0x1f, 0xac, 0x22, 0xd2, 0x71, 0x06, 0x30, 0x2b, 0xb6, 0x9d, 0xa0, 0x74, 0xb6, 0xef, 0xa6, 0x68, 0x8c, 0xf8, 0x35, 0xc8, 0x0b, 0xf5, 0xe4, 0x55, 0x35, 0x28, 0xec, 0xe0, 0xb7, 0xc1, 0xb7, 0x7b, 0x66, 0x6e, 0xa3, 0x45, 0x23, 0xec, 0x1f, 0xcb, 0x3e, 0x25, 0x05, 0x4e, 0x0b, 0xb8, 0xe4, 0xba, 0x02, 0x7e, 0x5c, 0x21, 0xbf, 0x7a, 0x51, 0x43, 0xbf, 0x04, 0x1c, 0xe9, 0xcc, 0xbc, 0xfa, 0xfa, 0x87, 0x80, 0x82, 0xfe, 0x41, 0xf7, 0x8c, 0x70, 0xbf, 0x4e, 0x53, 0xcf, 0x48, 0x7c, 0x1a, 0xad, 0xb0, 0x19, 0x15, 0xce, 0xdd, 0xe8, 0xcd, 0x9f, 0xb8, 0x4e, 0xfd, 0x98, 0x1a, 0xc9, 0x8c, 0xd5, 0x7a, 0x82, 0x56, 0xd4, 0xe9, 0xe2, 0xd0, 0x86, 0x2d, 0xab, 0x04, 0x54, 0xd3, 0xff, 0x4f, 0xb9, 0x85, 0x26, 0x4a, 0x46, 0x99, 0x5a, 0xb0, 0x68, 0xa7, 0x4e, 0xdc, 0x7e, 0xd8, 0xae, 0xff, 0x5f, 0xa3, 0x0f, 0x3a, 0x7d, 0x75, 0x94 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.3", + /* Message */ + 13, + { 0xe2, 0x00, 0x4b, 0x31, 0x07, 0x39, 0x98, 0x2c, 0xfa, 0x9e, 0x95, 0x45, 0x3a } +, + /* Seed */ + 240, + { 0xe9, 0x3e, 0x64, 0x12, 0x33, 0x7a, 0xb7, 0xb0, 0xf1, 0xb5, 0x69, 0x80, 0x1a, 0x3c, 0x16, 0x4a, 0x6f, 0x23, 0xe3, 0xc2, 0x7c, 0x7c, 0x55, 0xa8, 0xc5, 0xac, 0x9e, 0xaf, 0x31, 0x88, 0x55, 0xf8, 0x32, 0x8b, 0x5d, 0x7a, 0xb4, 0xcb, 0x86, 0x19, 0xa0, 0x0e, 0x99, 0x41, 0xcc, 0xaa, 0x94, 0x85, 0x70, 0x52, 0x71, 0x82, 0x61, 0x74, 0x43, 0xc1, 0xd2, 0x1e, 0x4a, 0x6e, 0x21, 0xb3, 0xf6, 0xd4, 0xf6, 0x98, 0xa6, 0x1a, 0xe0, 0x29, 0x17, 0x2c, 0xf4, 0xda, 0x03, 0x9d, 0x91, 0x58, 0x5a, 0x87, 0xda, 0xd1, 0x28, 0xc2, 0xfa, 0xc5, 0x53, 0x1b, 0x2f, 0x45, 0xdc, 0xef, 0x9b, 0x9f, 0xc3, 0x31, 0xc8, 0x04, 0x48, 0x85, 0x28, 0x84, 0x7c, 0x90, 0x87, 0x5d, 0x19, 0x07, 0x5f, 0xff, 0xb0, 0x05, 0x76, 0x3d, 0x88, 0xe0, 0x81, 0x47, 0x66, 0x92, 0x28, 0xa9, 0xaa, 0xd0, 0x16, 0x25, 0xbc, 0x61, 0x11, 0x2c, 0xc7, 0xb7, 0x72, 0xf3, 0x21, 0xd4, 0x33, 0xd4, 0xf2, 0x69, 0x78, 0x20, 0x9d, 0x0e, 0x79, 0x67, 0x6a, 0xf3, 0xb8, 0xa7, 0x4b, 0x97, 0x3f, 0x52, 0xab, 0x91, 0x90, 0x85, 0xf3, 0x52, 0x35, 0x5f, 0x85, 0x6a, 0xa4, 0x0f, 0xfa, 0xbc, 0xe5, 0x43, 0xd4, 0xe7, 0x6d, 0x45, 0x48, 0x92, 0x98, 0x9c, 0xb3, 0x83, 0xf3, 0xe6, 0x6b, 0xbb, 0x0e, 0x8f, 0xee, 0xbf, 0xf7, 0xc6, 0xa5, 0x4e, 0xf2, 0x62, 0x5f, 0xc4, 0x05, 0x0e, 0x6f, 0x87, 0xa3, 0x23, 0x13, 0x2a, 0x4e, 0x67, 0x12, 0x68, 0xfb, 0x83, 0xcf, 0xf2, 0xd8, 0x22, 0x51, 0xb7, 0x9c, 0xbe, 0x32, 0xda, 0xa8, 0xe5, 0x53, 0x20, 0x2f, 0xe8, 0x87, 0x22, 0x61, 0xf6, 0x0d, 0x5b, 0xb5, 0x11, 0xf2, 0xfa, 0x2f, 0x14, 0x21, 0xa3 } +, + /* Encryption */ + 256, + { 0x2b, 0xbf, 0x6b, 0x0c, 0x5c, 0xf2, 0x0e, 0xf2, 0xf6, 0xc5, 0xa0, 0xaa, 0x48, 0x45, 0x4f, 0x85, 0x0a, 0xa5, 0xf6, 0xbb, 0xeb, 0x03, 0x0d, 0xb4, 0xe2, 0xbe, 0xc1, 0x1f, 0xb2, 0x00, 0xf0, 0x1e, 0x4e, 0xae, 0xf0, 0x44, 0xd8, 0x14, 0x33, 0x33, 0x33, 0x8e, 0x5e, 0x66, 0x38, 0x00, 0x87, 0x66, 0x0e, 0xd0, 0x17, 0x3a, 0x76, 0x82, 0x12, 0x85, 0x67, 0x7e, 0x37, 0x1f, 0x28, 0xec, 0x45, 0x00, 0xf4, 0xd5, 0x9f, 0xab, 0xab, 0x20, 0x73, 0xe7, 0x34, 0x36, 0x5f, 0xc6, 0xb0, 0x94, 0xee, 0x0a, 0xdb, 0xce, 0xac, 0xcf, 0xe2, 0x49, 0x88, 0xce, 0x61, 0x5d, 0x60, 0x5f, 0xc3, 0x40, 0x8c, 0x03, 0xbe, 0x22, 0x1c, 0x99, 0x3f, 0x61, 0xaa, 0x72, 0x4f, 0xc8, 0x71, 0x4a, 0x8a, 0x4a, 0x18, 0x15, 0xf9, 0xe9, 0xa9, 0x98, 0x82, 0xaa, 0x46, 0x88, 0x3e, 0x70, 0x47, 0x4e, 0x33, 0x29, 0xb9, 0x91, 0xe6, 0xd5, 0x3d, 0xc6, 0xb5, 0x00, 0x86, 0x19, 0x92, 0x34, 0x3a, 0x6d, 0xa8, 0x9a, 0x8b, 0xd6, 0xf3, 0x7f, 0x34, 0xe5, 0xde, 0xee, 0xf8, 0x0e, 0x7d, 0x56, 0xb9, 0x3a, 0x45, 0x17, 0x60, 0x66, 0x36, 0x50, 0xfa, 0x45, 0x5d, 0x55, 0x41, 0x89, 0x9a, 0x76, 0xaa, 0xd1, 0xc6, 0x27, 0x5e, 0xc8, 0x2c, 0x46, 0x07, 0x12, 0x26, 0x59, 0xb5, 0x08, 0xcb, 0x5d, 0xc0, 0x26, 0xac, 0xf9, 0x3f, 0xa0, 0x1a, 0x5f, 0xca, 0x3d, 0x81, 0xc1, 0xbb, 0x20, 0xa5, 0xa5, 0xcf, 0x35, 0x7a, 0x23, 0xc9, 0x56, 0x88, 0xea, 0x42, 0xeb, 0x1e, 0xf2, 0xc9, 0xd4, 0x6a, 0xe3, 0x7f, 0x8c, 0xbe, 0x61, 0x5c, 0x20, 0x84, 0xd9, 0x89, 0xb8, 0x92, 0xf0, 0x16, 0x7b, 0x23, 0xbe, 0x33, 0x62, 0xfa, 0xce, 0x80, 0x8d, 0x6a, 0x5e, 0xb8, 0x96, 0x19, 0x44, 0x08, 0xdb, 0x7c, 0x01, 0x63, 0x9c, 0x58, 0x62, 0x30, 0x4c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.4", + /* Message */ + 53, + { 0xdb, 0x6a, 0xf1, 0x29, 0x23, 0x05, 0x27, 0x8c, 0x5b, 0x33, 0x83, 0xf8, 0xa4, 0x1d, 0x6c, 0x83, 0x52, 0x21, 0x14, 0xc9, 0x88, 0x85, 0x50, 0x74, 0x06, 0x5b, 0x23, 0xf9, 0xfe, 0xae, 0x8e, 0xa4, 0x31, 0xfd, 0x5d, 0xa3, 0x6f, 0x9b, 0xab, 0xf9, 0xdc, 0x61, 0xdf, 0x2e, 0x39, 0x23, 0x47, 0x83, 0x04, 0x73, 0x38, 0xec, 0x4f } +, + /* Seed */ + 200, + { 0xcb, 0x85, 0x1f, 0xb2, 0x76, 0xa7, 0x49, 0x1c, 0xd3, 0xef, 0xe4, 0xd3, 0x39, 0x50, 0x16, 0xc1, 0xec, 0x2b, 0x15, 0x09, 0x4a, 0x1e, 0xc6, 0xd9, 0x30, 0xd4, 0xca, 0x21, 0xb4, 0x20, 0xf8, 0x47, 0xff, 0x68, 0x68, 0xf0, 0x14, 0xd2, 0x09, 0xff, 0x80, 0x7e, 0x8b, 0x1f, 0x71, 0x67, 0x0b, 0x32, 0x50, 0x94, 0xc0, 0xf6, 0xe3, 0x2f, 0x84, 0xf7, 0x68, 0x22, 0x22, 0x02, 0xb2, 0x1b, 0xe3, 0x6a, 0x28, 0x6b, 0x30, 0xe0, 0x82, 0xef, 0x3b, 0xba, 0x64, 0x7c, 0xeb, 0xee, 0xaf, 0xe3, 0x10, 0x69, 0x44, 0x18, 0xd7, 0x0a, 0x67, 0x9e, 0xb2, 0x01, 0x07, 0x80, 0xdd, 0x0e, 0x96, 0x55, 0x3c, 0x43, 0xcb, 0xc6, 0xd0, 0x0e, 0xac, 0x22, 0xaa, 0x71, 0xf2, 0x48, 0x21, 0xc4, 0xd6, 0xc1, 0x77, 0x8e, 0x78, 0x6c, 0xd8, 0xc7, 0xbf, 0x2c, 0xbb, 0xf2, 0x14, 0xe2, 0x03, 0xe2, 0xef, 0x2f, 0x33, 0x35, 0x78, 0xcf, 0x1a, 0x94, 0x7e, 0x27, 0xe5, 0x99, 0x96, 0x29, 0x0c, 0xbc, 0xd6, 0xca, 0x3f, 0x8f, 0x96, 0xba, 0x67, 0xe0, 0xe3, 0x41, 0x30, 0xcf, 0xdf, 0x86, 0xef, 0x48, 0xe6, 0x7c, 0x90, 0xb8, 0xb7, 0x2e, 0x6f, 0x42, 0x55, 0x01, 0x7d, 0xa2, 0xd1, 0xf3, 0xae, 0xdd, 0x7f, 0xb1, 0xd9, 0xde, 0x42, 0xef, 0xc0, 0x37, 0xab, 0xe6, 0x61, 0x6e, 0xbd, 0xa8, 0xd0, 0xb4, 0x0b, 0xd7, 0x80, 0xcb, 0xdb, 0x68, 0xce, 0x54, 0x31, 0x8f, 0xda, 0xfd } +, + /* Encryption */ + 256, + { 0xc9, 0x9a, 0x9a, 0xb6, 0x7c, 0xad, 0x0c, 0x41, 0xec, 0x84, 0x7b, 0xc2, 0x74, 0x67, 0xfd, 0xf5, 0xbf, 0x61, 0xed, 0x6d, 0x04, 0xc6, 0x5f, 0x7d, 0x9d, 0xd8, 0xbb, 0x70, 0x07, 0xa8, 0xa9, 0xb8, 0x3a, 0x3c, 0x38, 0xa9, 0xcb, 0x92, 0x5e, 0x3e, 0x7b, 0x3c, 0x40, 0x7d, 0x64, 0x66, 0x93, 0x15, 0xb3, 0x54, 0x49, 0xe7, 0x54, 0x28, 0xae, 0x96, 0x19, 0x14, 0xb0, 0xb9, 0x10, 0x23, 0xe7, 0x83, 0x19, 0x1f, 0x95, 0x41, 0xb6, 0x78, 0x65, 0x97, 0x1c, 0x95, 0xb0, 0xbe, 0x18, 0x93, 0x1e, 0xb1, 0xc8, 0x47, 0xc2, 0x6a, 0x29, 0x83, 0xc0, 0x58, 0x4e, 0xb2, 0x17, 0xc9, 0x9c, 0x70, 0x5f, 0x5a, 0xd8, 0xcb, 0xb0, 0x9f, 0x99, 0xb0, 0x6b, 0xdf, 0x7b, 0xd1, 0x26, 0x28, 0xae, 0x36, 0x67, 0xc1, 0x2c, 0x72, 0x27, 0xd9, 0x6f, 0xf9, 0xc1, 0x08, 0xdc, 0xe3, 0x22, 0x51, 0x06, 0xf6, 0x2f, 0x9a, 0x4a, 0x3a, 0x81, 0x17, 0xa9, 0x92, 0xf2, 0x88, 0xc3, 0xb5, 0x97, 0x91, 0x09, 0x87, 0x8f, 0xcd, 0x59, 0xc6, 0x79, 0x6b, 0x19, 0x98, 0x48, 0x2e, 0xa8, 0x2f, 0x30, 0x1c, 0x93, 0x91, 0x83, 0xb2, 0xdd, 0x47, 0x88, 0x04, 0x48, 0x67, 0x8a, 0xcb, 0xa1, 0x2d, 0x7b, 0xc8, 0xa5, 0x52, 0xeb, 0x32, 0x76, 0x34, 0xe9, 0x2d, 0x0c, 0xdc, 0xf7, 0x1e, 0xff, 0xb6, 0x66, 0xad, 0x90, 0x2d, 0x9e, 0x26, 0xad, 0x18, 0x60, 0xe2, 0x92, 0x81, 0xd0, 0x2f, 0xb0, 0xc5, 0x49, 0x3b, 0xf7, 0x4a, 0xc0, 0x2c, 0x94, 0x40, 0x43, 0x6e, 0x0d, 0x75, 0x32, 0x28, 0x92, 0x77, 0x7d, 0x32, 0x5e, 0xc8, 0x45, 0x2d, 0xe7, 0x58, 0xcc, 0x6a, 0x5c, 0xbb, 0x02, 0xd3, 0x41, 0xf4, 0x5c, 0x9a, 0xc8, 0xed, 0xf1, 0x50, 0xda, 0xd7, 0x15, 0x82, 0xdc, 0x77, 0x95, 0x8a, 0x85, 0x44, 0xb0, 0xb5, 0x58, 0xee, 0x2a, 0x0b } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.5", + /* Message */ + 11, + { 0xe7, 0x99, 0xe4, 0xeb, 0xc8, 0x69, 0x31, 0x9e, 0xe2, 0x25, 0x80 } +, + /* Seed */ + 242, + { 0x3a, 0x07, 0x57, 0xcb, 0x49, 0xa3, 0xfe, 0x6a, 0xe8, 0x0d, 0x37, 0x42, 0x06, 0x8b, 0x5c, 0x80, 0x68, 0xb8, 0xc5, 0x88, 0x54, 0x20, 0x01, 0x10, 0x93, 0xc2, 0x20, 0x99, 0xed, 0xaa, 0xdb, 0x49, 0x1f, 0x22, 0x6f, 0x85, 0x60, 0x66, 0x16, 0x3a, 0xb5, 0x10, 0x5e, 0x78, 0x79, 0xc7, 0x49, 0x1c, 0x18, 0x35, 0x98, 0x5d, 0xc4, 0x94, 0x21, 0x0e, 0xf7, 0x8b, 0xad, 0x48, 0x16, 0xd9, 0xb6, 0x94, 0xc9, 0xc8, 0xbe, 0x46, 0x6a, 0x4d, 0x17, 0x8a, 0x7d, 0xde, 0xcb, 0xce, 0x53, 0x65, 0x40, 0x0d, 0x68, 0x21, 0xb6, 0xe9, 0xae, 0x0e, 0x03, 0xbb, 0x69, 0xad, 0xc4, 0xec, 0x73, 0x4a, 0xfd, 0xcd, 0xea, 0x6d, 0xc0, 0xc4, 0x85, 0x96, 0xc4, 0x8b, 0x27, 0x35, 0xef, 0x70, 0xf3, 0x73, 0x4c, 0x18, 0x6d, 0x03, 0x18, 0x37, 0x8d, 0x2b, 0xf8, 0x09, 0x96, 0x88, 0x67, 0x2f, 0xa3, 0x85, 0x91, 0xda, 0x4a, 0xe6, 0xfc, 0x11, 0x2b, 0x72, 0x7e, 0xc8, 0x19, 0x84, 0xdf, 0x7b, 0x56, 0xc9, 0x84, 0x4e, 0x25, 0xb0, 0xfc, 0xd8, 0x1d, 0x2b, 0xe7, 0xd1, 0x8d, 0x01, 0x64, 0x6a, 0x6d, 0x9f, 0xe2, 0x25, 0xd3, 0x69, 0x7c, 0x34, 0xed, 0x2e, 0x33, 0x6c, 0xc0, 0x37, 0x3d, 0xaa, 0x28, 0xd8, 0x82, 0xe4, 0x97, 0x75, 0x7b, 0x0a, 0x65, 0x10, 0x86, 0x2e, 0xac, 0x10, 0xd3, 0xb2, 0x4a, 0xdb, 0x25, 0x2f, 0x30, 0xd4, 0x34, 0xe3, 0x0a, 0x63, 0x76, 0x46, 0x9d, 0x80, 0xb9, 0x57, 0x11, 0x16, 0x17, 0x78, 0xdf, 0x35, 0x88, 0x9b, 0x3a, 0xcf, 0xb1, 0xf6, 0x53, 0xea, 0x63, 0x07, 0x2f, 0x35, 0xa3, 0xc8, 0x9f, 0x6b, 0xa5, 0x2a, 0xfb, 0xbd, 0xc2, 0x8f, 0x23, 0xd3, 0x8f, 0x4d, 0x4e, 0x79, 0xfc, 0x39, 0x7c, 0x10 } +, + /* Encryption */ + 256, + { 0x3a, 0x3e, 0x72, 0x5c, 0x6e, 0x4b, 0xb0, 0x06, 0x12, 0x69, 0x61, 0x8c, 0xbb, 0x8a, 0x62, 0x67, 0xd9, 0x55, 0x83, 0xab, 0xaa, 0x03, 0xd8, 0xdf, 0x85, 0xa4, 0xf6, 0xa5, 0xcc, 0x35, 0x9b, 0xf1, 0x15, 0x26, 0x0d, 0xdb, 0x70, 0xae, 0x7c, 0x66, 0xbb, 0x8d, 0x87, 0xd6, 0x33, 0x1f, 0xf1, 0xb0, 0xb5, 0x4b, 0xe5, 0x64, 0x8e, 0x83, 0xe8, 0x3a, 0x91, 0xc5, 0x4c, 0xf3, 0x71, 0x49, 0x6e, 0xe5, 0xca, 0x02, 0x73, 0xb1, 0x9f, 0x70, 0x03, 0x70, 0xc2, 0xc8, 0xcd, 0xf4, 0x28, 0x13, 0x38, 0xa6, 0xe7, 0x2f, 0x66, 0x32, 0x41, 0x68, 0xea, 0x8c, 0xdb, 0xc6, 0x4c, 0x60, 0x9b, 0xa9, 0x67, 0x91, 0xc7, 0x91, 0xb5, 0xac, 0x84, 0x00, 0x99, 0x2a, 0x8c, 0x66, 0xfb, 0x09, 0xf4, 0xe3, 0x13, 0x07, 0x49, 0x12, 0xaf, 0x0c, 0xb7, 0x41, 0x5f, 0xb2, 0x15, 0xeb, 0x97, 0xfa, 0xeb, 0xbe, 0xf1, 0xa4, 0x47, 0x23, 0x9a, 0x91, 0xdb, 0x4a, 0x34, 0xfc, 0xa4, 0xd8, 0x43, 0x46, 0x25, 0x9e, 0xe0, 0xa1, 0xda, 0xdd, 0x10, 0xb7, 0xf0, 0x1f, 0xc8, 0xc5, 0x3e, 0x42, 0x0f, 0x88, 0xcd, 0xfa, 0x0c, 0xbc, 0xf6, 0x2b, 0xe4, 0x4b, 0x8a, 0x79, 0x40, 0x86, 0x4f, 0xf8, 0x13, 0x7e, 0xdb, 0x12, 0x2a, 0xc2, 0xda, 0xe5, 0x41, 0x0a, 0x47, 0xcf, 0x07, 0x62, 0xe2, 0x0f, 0x20, 0x86, 0xcb, 0xf6, 0x6f, 0xf4, 0xd1, 0xa9, 0xf7, 0x27, 0x0f, 0x00, 0x9c, 0xb2, 0xe0, 0x7d, 0x90, 0x20, 0xb4, 0x8a, 0x76, 0xd2, 0x41, 0x08, 0xe9, 0x98, 0x9b, 0xf9, 0x04, 0xe4, 0xa7, 0x1d, 0xdb, 0x91, 0x74, 0x0a, 0xd7, 0xe5, 0xd1, 0xb6, 0x8e, 0xc6, 0x4e, 0x3e, 0x66, 0xcd, 0x0e, 0x89, 0x7d, 0xcc, 0x66, 0x57, 0x39, 0xeb, 0xac, 0x45, 0x19, 0x93, 0xf0, 0x2c, 0xc5, 0xbf, 0xc6, 0x3a, 0x60, 0x2f, 0x55, 0x83, 0x81, 0xda } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.6", + /* Message */ + 55, + { 0x09, 0x97, 0x12, 0xb8, 0x26, 0xba, 0x67, 0xcf, 0x92, 0x92, 0x25, 0xbd, 0x61, 0x2e, 0xc0, 0x65, 0xd4, 0x51, 0xed, 0xe2, 0x31, 0xc8, 0xd5, 0xc2, 0x04, 0x04, 0xd4, 0x70, 0xe7, 0x9a, 0x7a, 0x1f, 0x24, 0x6e, 0x3e, 0xec, 0xdc, 0xc7, 0x5f, 0x08, 0x53, 0x29, 0xf8, 0xf1, 0x7b, 0x81, 0xd1, 0x30, 0x30, 0x0f, 0xc3, 0xb9, 0xf0, 0x93, 0xa2 } +, + /* Seed */ + 198, + { 0x81, 0xcd, 0x64, 0xc8, 0x4d, 0x77, 0x65, 0xfc, 0x60, 0xe4, 0xde, 0x3b, 0xa9, 0xb4, 0xdd, 0x21, 0xdd, 0xfb, 0x74, 0xfe, 0x2d, 0xfb, 0x7c, 0xf6, 0x19, 0xdb, 0xa4, 0xcb, 0xcc, 0x17, 0x6e, 0xd9, 0x4e, 0x6f, 0x37, 0xed, 0x1a, 0x97, 0xe3, 0xbf, 0xd3, 0x63, 0x65, 0xd2, 0x64, 0x4d, 0x3b, 0x6e, 0xe6, 0xc7, 0x71, 0x09, 0xfa, 0x18, 0x41, 0x2e, 0xe7, 0xcd, 0xdd, 0x3b, 0xe8, 0xd4, 0xbd, 0xee, 0x94, 0xc0, 0x96, 0xf0, 0x72, 0xca, 0xb6, 0xf1, 0x88, 0x6e, 0x3a, 0x84, 0xa7, 0xfd, 0xb5, 0xaf, 0xf3, 0xdd, 0x83, 0xf7, 0xe5, 0xc5, 0xb4, 0x9b, 0xb1, 0xb3, 0x8f, 0x8f, 0xaa, 0x75, 0x25, 0x31, 0xd8, 0x9c, 0x88, 0x39, 0x3e, 0x9e, 0xb8, 0xf5, 0x7e, 0xdc, 0x5b, 0x9f, 0xe6, 0xed, 0x2b, 0xc9, 0x5d, 0x27, 0x2c, 0xa9, 0x95, 0xf7, 0xe2, 0x59, 0xb0, 0x08, 0x32, 0xd9, 0x8b, 0x87, 0x23, 0x12, 0xcb, 0xef, 0x8a, 0x04, 0x8f, 0x6e, 0xb7, 0x91, 0x97, 0x84, 0xae, 0xd3, 0xd3, 0x1e, 0xb4, 0xb1, 0x2f, 0xd8, 0x07, 0x60, 0xa1, 0x34, 0xc9, 0xd6, 0xc3, 0x34, 0xc2, 0xdd, 0x3d, 0xfd, 0xf4, 0x97, 0x5c, 0xf1, 0xb5, 0x1e, 0x87, 0x12, 0x2b, 0x97, 0x33, 0x33, 0x44, 0x96, 0x08, 0xff, 0xbb, 0x2c, 0xf3, 0x0a, 0x02, 0xbc, 0x46, 0xea, 0x24, 0x7b, 0x45, 0x39, 0xb1, 0x86, 0x07, 0xbd, 0x47, 0xd3, 0xcd, 0xf0, 0x87, 0x72, 0x14, 0xba } +, + /* Encryption */ + 256, + { 0x78, 0x6b, 0x3f, 0x59, 0x9d, 0x1b, 0x74, 0x3e, 0x23, 0x58, 0x26, 0x24, 0xfa, 0x2c, 0x94, 0xa3, 0x6f, 0xb6, 0xbd, 0x33, 0xfd, 0xdd, 0x57, 0x64, 0x08, 0xcc, 0x85, 0x4a, 0xd7, 0xcf, 0x66, 0x7f, 0x17, 0x38, 0x0a, 0xf2, 0x0b, 0x0b, 0x73, 0x0c, 0x6b, 0xe9, 0x8c, 0x01, 0x80, 0x76, 0xb9, 0xb5, 0x04, 0x1d, 0xaf, 0x2e, 0xeb, 0x02, 0x54, 0x69, 0x30, 0x0a, 0xa4, 0x36, 0x43, 0x35, 0xbe, 0x26, 0x7d, 0x33, 0xb0, 0x6b, 0x4a, 0x7a, 0x79, 0x7a, 0x3c, 0x0a, 0xa5, 0xfd, 0x3f, 0x91, 0x6a, 0x55, 0xdc, 0x27, 0x4c, 0x0a, 0x24, 0x87, 0xf1, 0x25, 0xf9, 0xda, 0x82, 0x59, 0x6f, 0x43, 0x4c, 0x7f, 0xba, 0xc7, 0xec, 0xe2, 0xef, 0x6c, 0x83, 0xe0, 0x34, 0x8b, 0xf4, 0xf2, 0xc0, 0x83, 0x05, 0x07, 0x55, 0xb5, 0x6a, 0x9c, 0x63, 0x47, 0xf3, 0x9c, 0x76, 0xb0, 0xe0, 0xee, 0xdc, 0x61, 0x54, 0x10, 0x25, 0xc2, 0x3a, 0xa1, 0x85, 0x5c, 0x0b, 0x22, 0xb4, 0x46, 0xfe, 0x1e, 0xc5, 0xf1, 0x11, 0x2c, 0x5a, 0x7f, 0xc2, 0x85, 0xef, 0xdc, 0x84, 0x20, 0xec, 0x01, 0xa3, 0xa7, 0xc3, 0x3f, 0x73, 0x5b, 0x45, 0x55, 0x09, 0x2a, 0x9e, 0x8d, 0xe1, 0x6f, 0x3f, 0x7d, 0x46, 0x9f, 0x88, 0xcd, 0x75, 0xc0, 0x1c, 0x7f, 0x2e, 0x7d, 0x54, 0x6a, 0x1b, 0x9e, 0x7f, 0x49, 0x84, 0xfa, 0x29, 0xa2, 0xcc, 0x80, 0xd3, 0x10, 0xf9, 0xd7, 0x81, 0x8d, 0xf6, 0xd9, 0xad, 0x6c, 0xc2, 0x05, 0x37, 0x4d, 0x52, 0xe8, 0xe1, 0x73, 0x90, 0xbd, 0xe7, 0x2f, 0x25, 0xb7, 0x12, 0xa4, 0x26, 0x9f, 0x23, 0xae, 0xb2, 0x41, 0xa6, 0x66, 0xe9, 0x64, 0x96, 0xcd, 0x84, 0xb8, 0x33, 0xfb, 0x53, 0xd0, 0x57, 0x1f, 0x7a, 0xc2, 0xd1, 0x96, 0x4b, 0x8f, 0x2a, 0x7e, 0x13, 0x33, 0x6d, 0x9a, 0x7e, 0x03, 0x04, 0x1d, 0xcf, 0xcb } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.7", + /* Message */ + 41, + { 0x5f, 0x2a, 0x5c, 0x7f, 0x93, 0xe7, 0x14, 0xee, 0xca, 0xb3, 0xa5, 0x5a, 0x69, 0xc7, 0x9a, 0x3c, 0xbc, 0x15, 0xbd, 0x19, 0xdf, 0x27, 0x98, 0x9a, 0x9b, 0xab, 0x59, 0xfb, 0xbe, 0xa9, 0xff, 0xcc, 0x66, 0x3b, 0xf8, 0xe1, 0xe7, 0x40, 0x7d, 0xc2, 0x73 } +, + /* Seed */ + 212, + { 0xe0, 0x19, 0x60, 0x82, 0x6d, 0x1a, 0x69, 0xf6, 0x84, 0xc9, 0xc0, 0xb8, 0x5d, 0x84, 0xdc, 0xa5, 0x81, 0x1c, 0x89, 0xa2, 0xc0, 0x74, 0x2f, 0x33, 0xa2, 0xad, 0x19, 0x9f, 0xb6, 0x57, 0xa1, 0xaa, 0x98, 0x13, 0x60, 0x1d, 0x29, 0x93, 0x6a, 0x43, 0xd9, 0xb9, 0xeb, 0x4d, 0x32, 0x89, 0xcd, 0x7d, 0x37, 0x06, 0xab, 0x86, 0xb4, 0xd6, 0x6a, 0xda, 0xa7, 0xe0, 0xa1, 0x34, 0x51, 0xb2, 0xed, 0xb2, 0xbc, 0x77, 0x10, 0x91, 0x11, 0x0c, 0xda, 0xdd, 0x7e, 0xe2, 0xe6, 0xaa, 0xea, 0x2b, 0x35, 0xcf, 0xae, 0x4c, 0xe3, 0xb1, 0xda, 0x18, 0x16, 0x68, 0x4c, 0x89, 0xc0, 0xb3, 0xfb, 0x2f, 0x87, 0x79, 0xb2, 0x5c, 0xe0, 0xc1, 0x2d, 0x42, 0xb1, 0xd3, 0xd3, 0x0b, 0x8f, 0x20, 0xbe, 0xb8, 0x99, 0x91, 0x6e, 0x4f, 0xd0, 0xa1, 0x58, 0x86, 0x37, 0x19, 0x2e, 0x05, 0x28, 0xce, 0x6e, 0xa5, 0x4c, 0x8e, 0xb7, 0x54, 0xfd, 0x7f, 0xf0, 0x03, 0x25, 0x81, 0xa9, 0x50, 0x59, 0x98, 0xe6, 0x9e, 0x14, 0xf0, 0x72, 0xbf, 0x95, 0xdf, 0xef, 0xf0, 0x14, 0xdf, 0x99, 0xed, 0x78, 0x53, 0xb9, 0x82, 0xe8, 0x89, 0x41, 0x29, 0xa1, 0xd2, 0x7c, 0x53, 0xea, 0xaa, 0x23, 0x4c, 0x8d, 0x14, 0xa7, 0xff, 0xc5, 0xf5, 0xe2, 0x18, 0x7c, 0xef, 0x79, 0xeb, 0xf5, 0x2b, 0x3d, 0x6c, 0x06, 0x65, 0x89, 0x5b, 0xfb, 0x87, 0xe4, 0xbd, 0x61, 0x0e, 0x35, 0x8f, 0x35, 0x26, 0xda, 0x05, 0x92, 0xc9, 0xe5, 0x02, 0xb7, 0x2b, 0x76, 0xe4, 0x65, 0x66 } +, + /* Encryption */ + 256, + { 0x77, 0xd9, 0x07, 0x18, 0x1c, 0xc3, 0xb1, 0xbb, 0x19, 0x81, 0xe8, 0xcb, 0x22, 0xf7, 0xad, 0x75, 0xf8, 0x82, 0xe2, 0x6a, 0xfd, 0x28, 0x1b, 0x64, 0xdb, 0x70, 0xc8, 0x4c, 0x6a, 0x50, 0xfe, 0x74, 0x24, 0x9e, 0x22, 0xfb, 0xee, 0x90, 0xe3, 0x0d, 0x0b, 0x70, 0xae, 0x2f, 0x7e, 0x12, 0xac, 0xdd, 0xf6, 0x78, 0xf0, 0x0d, 0x22, 0x7e, 0x53, 0x61, 0x54, 0x26, 0x62, 0x43, 0x02, 0x69, 0xfe, 0xea, 0x34, 0x12, 0x47, 0x92, 0xaf, 0xb3, 0xf8, 0x7b, 0x30, 0xf9, 0x50, 0xf4, 0xed, 0xf2, 0x2c, 0x44, 0x04, 0xc9, 0x68, 0x8d, 0xec, 0x38, 0xea, 0x0b, 0x99, 0xcb, 0x3d, 0xc3, 0x84, 0xbd, 0x88, 0xfa, 0x31, 0x83, 0xd7, 0xe0, 0x7a, 0x20, 0x54, 0xd7, 0x3e, 0xa5, 0x1d, 0x42, 0x86, 0xbb, 0x39, 0xda, 0xe3, 0xae, 0x6d, 0x0b, 0x96, 0x51, 0xf1, 0xea, 0x48, 0x8f, 0x80, 0x5f, 0x2a, 0x21, 0x6e, 0xa2, 0x1a, 0x56, 0x76, 0xb9, 0x7d, 0x1b, 0x11, 0xd3, 0xb4, 0x03, 0x6c, 0xe1, 0x67, 0xfe, 0xf6, 0x4e, 0x0e, 0xba, 0x41, 0x9a, 0xf6, 0x73, 0x98, 0x3f, 0xc6, 0xee, 0x01, 0xc6, 0x37, 0xb1, 0x64, 0xe5, 0xaa, 0xac, 0xc9, 0x9a, 0xde, 0xe9, 0xf4, 0x7d, 0x21, 0x92, 0x54, 0x69, 0x6c, 0x8f, 0xce, 0xec, 0x6c, 0x74, 0xac, 0x4e, 0x39, 0x05, 0x1e, 0x15, 0x26, 0x94, 0x01, 0x73, 0x82, 0x64, 0xf0, 0xca, 0x5b, 0xf1, 0x22, 0xc5, 0x5c, 0x9e, 0x5d, 0xd8, 0x47, 0xb1, 0xd5, 0x77, 0x4e, 0x74, 0x08, 0xc3, 0x68, 0x4a, 0xa9, 0x74, 0xb0, 0xba, 0xaf, 0x40, 0xed, 0xc2, 0x2a, 0x03, 0x57, 0xaf, 0x72, 0xc8, 0x16, 0xcf, 0x73, 0x1f, 0xcb, 0x63, 0x96, 0x53, 0x60, 0x69, 0x9f, 0x26, 0x99, 0x97, 0xb8, 0x48, 0x0f, 0x30, 0xa6, 0xb5, 0xd5, 0x7e, 0x12, 0xa5, 0xcc, 0x54, 0xec, 0x0c, 0x80, 0x5f, 0xdc, 0xf6 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.8", + /* Message */ + 9, + { 0x55, 0x61, 0x39, 0x59, 0x3e, 0xee, 0x8b, 0x6e, 0x87 } +, + /* Seed */ + 244, + { 0x2d, 0xe2, 0xa5, 0x72, 0x24, 0xf5, 0xf5, 0xb1, 0x2e, 0x22, 0x3e, 0xb5, 0xf8, 0x2b, 0x9f, 0x47, 0x24, 0x9d, 0x25, 0x55, 0x93, 0x79, 0x13, 0x6e, 0xaf, 0x18, 0xe2, 0xf6, 0xc8, 0x33, 0xe3, 0xf0, 0x1b, 0xde, 0xea, 0x9c, 0x30, 0x3b, 0xd9, 0x67, 0x7c, 0x2a, 0x85, 0x71, 0x7d, 0x59, 0x3a, 0x28, 0x02, 0xae, 0xcb, 0xc6, 0xb3, 0xb7, 0x1f, 0x2c, 0x79, 0x03, 0xff, 0x69, 0x0e, 0x3f, 0x3c, 0x49, 0x57, 0xdd, 0x74, 0xcc, 0x9c, 0x2a, 0x68, 0xdc, 0x1d, 0x31, 0x9c, 0x1e, 0x17, 0x87, 0xbb, 0xb7, 0xf0, 0xe6, 0xe5, 0x1e, 0x39, 0xa5, 0xba, 0xdb, 0xba, 0x9f, 0xd4, 0x67, 0x66, 0x19, 0x74, 0x31, 0x2b, 0x55, 0x7a, 0xf1, 0x89, 0x52, 0x54, 0x9f, 0x6e, 0xba, 0x9d, 0xf4, 0x9f, 0x70, 0xea, 0xb3, 0x68, 0x9f, 0x9f, 0xa8, 0xfb, 0xea, 0x1c, 0x97, 0xe1, 0xbb, 0x2f, 0x09, 0x3e, 0x6a, 0xca, 0x9c, 0x38, 0x0e, 0xdc, 0x54, 0x6a, 0x19, 0xc4, 0x4f, 0x91, 0xf6, 0xdc, 0xaa, 0x28, 0x9b, 0xd1, 0x14, 0xfe, 0xa1, 0xb0, 0x36, 0xf9, 0x9b, 0x1a, 0x57, 0xf8, 0x61, 0x43, 0xd8, 0x67, 0x5b, 0xd0, 0x7d, 0x4d, 0xea, 0xbc, 0x9d, 0x51, 0x0c, 0x61, 0x70, 0x99, 0x44, 0x9c, 0xcc, 0xed, 0x5c, 0x45, 0x07, 0xb7, 0x9e, 0x85, 0x1e, 0xfe, 0xb1, 0x8d, 0x06, 0xb1, 0x99, 0x81, 0x0b, 0xb6, 0xb3, 0xcb, 0xe4, 0x12, 0x73, 0xba, 0xa7, 0x35, 0x16, 0x02, 0xe5, 0xf9, 0x52, 0x13, 0xf9, 0x69, 0x55, 0xad, 0x5f, 0xdd, 0x3a, 0x20, 0x52, 0xdb, 0xc7, 0x5f, 0xcf, 0x60, 0xaa, 0x22, 0x47, 0xf2, 0xd4, 0xe6, 0x03, 0xda, 0x45, 0x37, 0x0d, 0xe1, 0xc1, 0xda, 0x68, 0x7e, 0x26, 0x8e, 0xe4, 0x46, 0x67, 0xf9, 0x4d, 0xad, 0x13, 0xbc, 0x9b } +, + /* Encryption */ + 256, + { 0x4a, 0xce, 0x54, 0xa7, 0x52, 0xf5, 0x56, 0xe3, 0x6e, 0xab, 0xb1, 0x19, 0x48, 0x95, 0x84, 0x12, 0x14, 0x0c, 0x80, 0xc3, 0x1b, 0x61, 0xdc, 0x40, 0xf8, 0x1a, 0x6b, 0x12, 0x17, 0xa0, 0x1c, 0xe0, 0x67, 0xab, 0x37, 0xf5, 0x3d, 0xf4, 0xc7, 0x7d, 0x9e, 0xa9, 0xc2, 0xd7, 0x95, 0x0c, 0x8c, 0xd4, 0x97, 0x00, 0xb8, 0xcd, 0x24, 0xd4, 0xe7, 0x8f, 0x7f, 0xa3, 0x46, 0x29, 0x62, 0xcb, 0xfd, 0xe6, 0xd0, 0x2f, 0xb0, 0xe5, 0x03, 0x65, 0x64, 0x93, 0x25, 0x05, 0xae, 0x1c, 0x85, 0x1a, 0xa6, 0xd1, 0xd8, 0x4e, 0xfd, 0x04, 0xd5, 0x78, 0xad, 0x68, 0x27, 0x3a, 0x36, 0xa8, 0xae, 0x23, 0xd1, 0x45, 0x2f, 0x94, 0xa9, 0x37, 0x88, 0x17, 0x71, 0x3e, 0x76, 0x4a, 0x09, 0x17, 0x45, 0x26, 0x29, 0xb5, 0xdc, 0x75, 0xb5, 0x7b, 0x0d, 0x5e, 0x6a, 0x72, 0x8c, 0x83, 0x69, 0x11, 0x72, 0xd2, 0xcd, 0x95, 0xf8, 0xba, 0xd0, 0x7d, 0xb4, 0x68, 0xeb, 0xf5, 0x45, 0xb7, 0xf3, 0xf2, 0xc8, 0x63, 0xb6, 0xe2, 0x0c, 0x67, 0xc4, 0x76, 0x9d, 0xed, 0x03, 0x91, 0xa3, 0x36, 0xf3, 0xa5, 0xd8, 0x7e, 0x24, 0xfc, 0xf9, 0x1a, 0xaf, 0x77, 0x4b, 0xee, 0x77, 0xa7, 0x89, 0xa5, 0x90, 0x80, 0x09, 0xc7, 0xa5, 0x5e, 0xac, 0x92, 0xaf, 0x4c, 0x3d, 0x46, 0x1e, 0x7b, 0x40, 0x61, 0x6c, 0xe8, 0x06, 0x19, 0x4b, 0xfc, 0x20, 0x74, 0xc3, 0xf4, 0xf1, 0x35, 0x59, 0x70, 0x0b, 0x27, 0x08, 0xa0, 0xb7, 0x55, 0x78, 0x96, 0x70, 0xa3, 0x62, 0x6a, 0x14, 0x63, 0x88, 0x11, 0xbb, 0x18, 0xe1, 0x5b, 0x10, 0x25, 0xc3, 0xb9, 0xbe, 0xf1, 0x11, 0x17, 0x6b, 0xc1, 0xf2, 0x46, 0x9e, 0xa9, 0x9a, 0xad, 0x20, 0x86, 0x05, 0x73, 0xd6, 0xc6, 0xa1, 0xfe, 0x40, 0xdb, 0x51, 0xe3, 0x6f, 0xe3, 0x38, 0x00, 0x10, 0x1b, 0xda, 0x20 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.9", + /* Message */ + 49, + { 0x9a, 0x13, 0x96, 0x62, 0x2d, 0x06, 0x6c, 0x10, 0x56, 0x08, 0x58, 0xc2, 0xc4, 0xcd, 0x5c, 0x04, 0x44, 0x9e, 0x2b, 0x95, 0x50, 0xc5, 0xbc, 0x92, 0x93, 0x76, 0x1a, 0x91, 0x04, 0x41, 0x1d, 0xa1, 0x8a, 0x57, 0xd9, 0xb6, 0xa9, 0x97, 0x33, 0x3c, 0xdb, 0xce, 0x77, 0xe9, 0xfd, 0xbe, 0x6b, 0xb8, 0x31 } +, + /* Seed */ + 204, + { 0xf1, 0x78, 0x61, 0xac, 0xff, 0xb2, 0x4c, 0xac, 0xed, 0x90, 0xba, 0x38, 0xaa, 0x7e, 0xa0, 0xf2, 0xe5, 0x4e, 0xea, 0xa6, 0x2a, 0xe6, 0x64, 0x98, 0xf3, 0xc2, 0x8f, 0x99, 0x6b, 0xce, 0xe2, 0x53, 0xbe, 0xe8, 0x19, 0x9e, 0x3e, 0xb8, 0x0d, 0x62, 0x7f, 0xee, 0xb6, 0xe0, 0xb3, 0x94, 0x90, 0xed, 0xf7, 0x6d, 0x16, 0xa2, 0xa0, 0xbc, 0x20, 0x09, 0x32, 0x52, 0xa9, 0xd7, 0xf1, 0xf9, 0x38, 0x8b, 0x06, 0x19, 0x44, 0x85, 0x2a, 0xfb, 0xe7, 0x3c, 0xe4, 0x13, 0xa3, 0xfc, 0xa5, 0x21, 0xb9, 0x47, 0x4e, 0x67, 0x81, 0x29, 0x46, 0x4d, 0x91, 0xb8, 0x2b, 0xca, 0xa5, 0x9f, 0x56, 0xec, 0xfb, 0x12, 0x4f, 0x61, 0xf5, 0x04, 0x67, 0x13, 0x01, 0x05, 0xb2, 0xcb, 0xc6, 0x94, 0x3b, 0x95, 0x36, 0x95, 0xcf, 0xcd, 0x20, 0xc9, 0xb6, 0xef, 0x53, 0xf3, 0xf2, 0x10, 0x33, 0x1d, 0x39, 0x32, 0xdc, 0x01, 0x0c, 0x73, 0x59, 0x29, 0x09, 0x6b, 0x2e, 0x68, 0xff, 0x16, 0x66, 0x4b, 0x0b, 0x90, 0xa0, 0xfa, 0x1b, 0xe4, 0x60, 0x57, 0x85, 0x92, 0xb0, 0xcb, 0x4d, 0x6c, 0xa4, 0x5e, 0xa0, 0x6b, 0xde, 0x3e, 0x8a, 0x1e, 0xbf, 0xef, 0x70, 0xd8, 0x3e, 0xf7, 0x9b, 0x3a, 0x74, 0xdb, 0x06, 0x0f, 0xc0, 0x20, 0x3b, 0x74, 0x80, 0x7f, 0x40, 0x70, 0x01, 0xf4, 0xb4, 0xd9, 0x9e, 0xc5, 0x15, 0x8e, 0x8e, 0x7e, 0x4b, 0x10, 0x2a, 0x51, 0x5d, 0xe9, 0x5d, 0x2b, 0x70, 0xfe, 0x1f, 0xb4 } +, + /* Encryption */ + 256, + { 0x10, 0x0e, 0xce, 0x63, 0x45, 0x25, 0xd4, 0x67, 0xf6, 0xd4, 0xa6, 0xb6, 0x6e, 0xde, 0x1c, 0xc2, 0x37, 0xf6, 0x1f, 0xb2, 0xb6, 0x70, 0x23, 0xa8, 0x3d, 0xc4, 0x56, 0xb9, 0x2c, 0xda, 0x18, 0x3e, 0xd6, 0x62, 0x0f, 0xe5, 0x7d, 0x5a, 0x67, 0x33, 0x2c, 0x77, 0x23, 0x3a, 0xc1, 0xe8, 0x72, 0x5b, 0x36, 0xf8, 0xe1, 0xb1, 0x08, 0x41, 0x2c, 0xa6, 0xfb, 0x35, 0xdc, 0xd4, 0xd8, 0x16, 0x77, 0xa2, 0xb3, 0x0d, 0x5e, 0xaf, 0x25, 0xe0, 0xb9, 0x19, 0x1b, 0x38, 0xf7, 0xee, 0xf8, 0x3f, 0x91, 0x21, 0xa8, 0x08, 0x43, 0x8c, 0x92, 0xab, 0x03, 0xf5, 0x20, 0x80, 0x7b, 0xc9, 0xa8, 0x94, 0x70, 0x5e, 0xaf, 0x4e, 0xed, 0x06, 0x68, 0x23, 0xa6, 0x7a, 0xa2, 0xa5, 0x59, 0x9c, 0xd9, 0x5e, 0x58, 0xda, 0x7c, 0x09, 0x48, 0x36, 0xd2, 0xaf, 0xeb, 0xa3, 0x9d, 0xd0, 0x09, 0xa6, 0x4a, 0xde, 0x03, 0x05, 0x33, 0x76, 0xf0, 0x29, 0x36, 0xcf, 0x3f, 0x56, 0xbf, 0x64, 0xc1, 0xf3, 0xbd, 0xc0, 0x7c, 0x45, 0xa9, 0x5b, 0x9f, 0xcd, 0x93, 0x96, 0xcd, 0x9a, 0x8d, 0x41, 0xbc, 0xc5, 0x64, 0x24, 0x93, 0x7a, 0x13, 0x71, 0xb3, 0x84, 0x7c, 0x90, 0x5b, 0x9a, 0xb5, 0x84, 0x02, 0x39, 0x3d, 0x40, 0x46, 0xe4, 0xa0, 0x15, 0xc1, 0x47, 0x08, 0xf7, 0x4c, 0xe7, 0x79, 0x0e, 0xba, 0x8a, 0xf7, 0x92, 0x07, 0x24, 0x40, 0xbc, 0xaf, 0xb1, 0x4c, 0x0f, 0x81, 0x08, 0x97, 0x11, 0x87, 0xc8, 0x0f, 0x46, 0x3a, 0x1f, 0xff, 0x25, 0x86, 0x46, 0xea, 0x16, 0xe5, 0x1c, 0x6e, 0xe3, 0x61, 0xb6, 0x61, 0xa1, 0x4f, 0x07, 0xcd, 0x4f, 0x5a, 0x82, 0xc7, 0x09, 0xf4, 0x94, 0xf1, 0xdf, 0x0f, 0x80, 0x3b, 0x6f, 0x64, 0xa7, 0x2f, 0xb9, 0xc4, 0x50, 0xff, 0xe2, 0x68, 0xfc, 0xab, 0x48, 0x7d, 0x4d, 0x63, 0x01, 0x3e, 0x41 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.10", + /* Message */ + 53, + { 0xb3, 0x82, 0x4f, 0xb5, 0x45, 0xa8, 0x3f, 0x82, 0xef, 0x82, 0x23, 0x11, 0x82, 0x84, 0xc5, 0x45, 0x6b, 0xab, 0x60, 0x0a, 0xdf, 0x79, 0xf5, 0x07, 0x33, 0xb6, 0x66, 0x8f, 0xbc, 0x51, 0x5d, 0xa5, 0x96, 0x31, 0x62, 0xa6, 0xd7, 0xd7, 0xe9, 0x6f, 0xf9, 0x1a, 0xff, 0x12, 0xeb, 0x3e, 0x93, 0x11, 0xe2, 0x21, 0xe7, 0x0b, 0xc0 } +, + /* Seed */ + 200, + { 0xb8, 0x26, 0x8e, 0x4b, 0xce, 0x7e, 0x53, 0xf2, 0xe8, 0xbe, 0x98, 0xb1, 0x92, 0xd6, 0x3a, 0xd0, 0x65, 0x44, 0xa8, 0x0d, 0x6e, 0x62, 0xd6, 0x32, 0x48, 0x6e, 0x15, 0xe5, 0x75, 0xba, 0x70, 0x6e, 0x3e, 0x76, 0x89, 0x30, 0xdc, 0x8e, 0x41, 0x1f, 0x8e, 0xeb, 0x0b, 0x6e, 0x8f, 0x06, 0x06, 0x29, 0xda, 0x8a, 0x24, 0x23, 0x68, 0xe4, 0x79, 0xcc, 0xb3, 0x31, 0x69, 0x70, 0x70, 0xb4, 0xb3, 0x52, 0x4e, 0x69, 0x16, 0x92, 0x76, 0xba, 0xb0, 0xa9, 0x45, 0x14, 0xcc, 0xd6, 0x60, 0x70, 0x25, 0x28, 0xed, 0x20, 0xb5, 0xd1, 0xdf, 0x07, 0x77, 0x9a, 0x62, 0xc6, 0x56, 0x86, 0xe7, 0xd6, 0x68, 0x46, 0x6f, 0xfc, 0x74, 0x8e, 0xb3, 0x43, 0x44, 0xca, 0x6f, 0x30, 0x5c, 0xda, 0x3d, 0xc3, 0xe8, 0xf0, 0x1c, 0x43, 0xea, 0x91, 0x79, 0xda, 0x46, 0x21, 0x47, 0xf4, 0xd3, 0xec, 0x92, 0xf8, 0x88, 0xb7, 0xee, 0xaa, 0x41, 0x0e, 0x12, 0xc8, 0x6d, 0x89, 0x42, 0xc7, 0xd0, 0x12, 0xf4, 0x5c, 0x61, 0xff, 0xa6, 0xe2, 0xb7, 0x8f, 0x84, 0x3e, 0x9a, 0x75, 0xd9, 0x67, 0x32, 0x14, 0xd5, 0x58, 0xca, 0xf0, 0x1b, 0x45, 0xf9, 0x36, 0x86, 0xee, 0xda, 0x54, 0x79, 0xdb, 0x80, 0x52, 0x79, 0x25, 0x59, 0xcc, 0x23, 0x6a, 0x4a, 0x1e, 0xe6, 0x5d, 0x3c, 0xa6, 0x0e, 0x09, 0xa3, 0xc1, 0x84, 0xd4, 0xb3, 0x95, 0xd7, 0x0b, 0x8e, 0xf8, 0x8d, 0x78, 0x09, 0x1a } +, + /* Encryption */ + 256, + { 0xc0, 0xe9, 0x8d, 0x50, 0x89, 0x4a, 0xda, 0x84, 0x9f, 0xce, 0x89, 0x83, 0xf6, 0xf8, 0x95, 0x74, 0x03, 0x4d, 0x6c, 0xf3, 0xb8, 0x35, 0x2b, 0xfc, 0x50, 0x72, 0x4a, 0x70, 0x3d, 0xd4, 0xf4, 0x2f, 0x40, 0x06, 0xae, 0x00, 0x8a, 0xd9, 0x72, 0x33, 0xce, 0xf6, 0xf1, 0x6c, 0xe1, 0xb4, 0x23, 0xf5, 0x2c, 0x6b, 0x67, 0x7e, 0xf0, 0x05, 0x13, 0x1b, 0xa9, 0x87, 0xf9, 0x8c, 0x72, 0x2f, 0xaa, 0x49, 0x42, 0xec, 0xce, 0x2c, 0x99, 0x66, 0x37, 0x40, 0xa1, 0xa1, 0xe9, 0x81, 0x20, 0xfa, 0xed, 0x97, 0xfd, 0x03, 0xff, 0x36, 0xfe, 0x73, 0x75, 0x8e, 0x70, 0xdf, 0x17, 0xf3, 0x1f, 0x1f, 0x39, 0x41, 0x81, 0x2d, 0x34, 0xca, 0xe6, 0xc3, 0x9d, 0xe7, 0x87, 0xef, 0x57, 0x04, 0xbc, 0x39, 0xc9, 0x20, 0xea, 0x5b, 0x0e, 0xb1, 0x83, 0x3e, 0x83, 0xb4, 0x57, 0x94, 0xfd, 0xe0, 0xff, 0x00, 0x05, 0xc6, 0x27, 0x33, 0xc7, 0x0a, 0x29, 0x6c, 0xa0, 0xbd, 0x47, 0xf0, 0x65, 0x50, 0x3d, 0xdc, 0xe2, 0xd6, 0x49, 0xde, 0x1c, 0x32, 0x8d, 0xdf, 0x60, 0x32, 0xa3, 0x3f, 0xad, 0x46, 0xba, 0x04, 0x1d, 0xc0, 0xa9, 0x94, 0xbf, 0x0f, 0x56, 0xa4, 0x65, 0xf1, 0x62, 0x5f, 0xcb, 0x81, 0xce, 0x01, 0xfa, 0x29, 0x9f, 0xc2, 0xb3, 0xc8, 0x09, 0x39, 0xeb, 0xe6, 0xa6, 0x73, 0x82, 0x6e, 0x2b, 0x2f, 0x12, 0xec, 0xdd, 0xa5, 0x03, 0x5c, 0x95, 0x09, 0x31, 0x2d, 0xd1, 0x9f, 0x10, 0xc3, 0x5c, 0x8a, 0x8b, 0x0d, 0xa6, 0x3c, 0x08, 0x51, 0x97, 0x00, 0x6a, 0x9b, 0xe2, 0x36, 0x10, 0x8e, 0xb9, 0x87, 0x91, 0xb2, 0x6e, 0x28, 0x08, 0xb5, 0xcc, 0xd5, 0xac, 0xec, 0x73, 0x8b, 0xca, 0x02, 0x5b, 0x24, 0x18, 0x2e, 0xf4, 0xab, 0x9c, 0xcc, 0xb1, 0x71, 0xa6, 0x9f, 0xb4, 0x23, 0xa4, 0x6e, 0x03, 0x7a, 0x4d, 0x0a } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.11", + /* Message */ + 43, + { 0xa3, 0xa7, 0xda, 0x1b, 0xed, 0xb2, 0xca, 0x99, 0xfc, 0xde, 0xb7, 0xa4, 0x6d, 0x63, 0x3e, 0xca, 0x35, 0x06, 0x2d, 0xf2, 0x89, 0x6b, 0x69, 0x59, 0x07, 0xa7, 0xf9, 0x71, 0xd2, 0xcc, 0x50, 0xb6, 0xe3, 0xd2, 0xa3, 0x67, 0xd1, 0x6e, 0x72, 0x7f, 0x56, 0x97, 0xc0 } +, + /* Seed */ + 210, + { 0xf0, 0x18, 0xa9, 0xb1, 0x3f, 0xbe, 0x56, 0x0b, 0xfe, 0x95, 0x52, 0xed, 0x8a, 0x86, 0x06, 0xbe, 0xea, 0x90, 0x05, 0x5e, 0xd3, 0xf6, 0x2b, 0xb2, 0xaf, 0x07, 0xf6, 0x92, 0xcb, 0x60, 0xac, 0xfb, 0x6d, 0x59, 0x07, 0xd6, 0x0e, 0x0a, 0x59, 0x7a, 0x54, 0xca, 0xea, 0xf8, 0x44, 0x91, 0x1c, 0xdc, 0x87, 0x4f, 0xaf, 0x95, 0x69, 0x53, 0xa2, 0x7d, 0x30, 0x0e, 0x9b, 0x71, 0x5b, 0x10, 0x4d, 0xf3, 0xc2, 0x32, 0xc3, 0xc9, 0x63, 0x82, 0xcf, 0x5b, 0x5f, 0x3d, 0x07, 0xb2, 0x30, 0xb5, 0x25, 0xbb, 0x33, 0x0e, 0x31, 0x9d, 0x1a, 0x7c, 0x82, 0xd1, 0x53, 0xaf, 0x81, 0x7e, 0xf1, 0x1c, 0xf7, 0x2e, 0x76, 0xdd, 0x50, 0xb0, 0xd7, 0xe5, 0x56, 0x22, 0x65, 0xc8, 0x34, 0x5d, 0xa8, 0x29, 0xf5, 0x60, 0xd6, 0xa5, 0x4e, 0x6f, 0x1e, 0x28, 0x8a, 0x3d, 0xc2, 0x17, 0x6d, 0x19, 0xa6, 0x8a, 0x0b, 0x1c, 0x5c, 0x92, 0xb1, 0x6b, 0x8b, 0xb2, 0x9e, 0x4d, 0x01, 0xdf, 0xbd, 0x0b, 0x18, 0x07, 0x9b, 0xd4, 0x0c, 0xfc, 0xd5, 0x23, 0x35, 0xb3, 0xa1, 0x8b, 0xc4, 0xee, 0x92, 0x44, 0x76, 0x0e, 0xb4, 0x94, 0xf5, 0xbe, 0x5b, 0x19, 0x71, 0x88, 0x6c, 0xa2, 0xbe, 0xec, 0xe0, 0xa3, 0x94, 0x4f, 0xff, 0x8b, 0xe6, 0xb4, 0x2d, 0x96, 0xe1, 0xc2, 0xc7, 0x2e, 0x4e, 0x90, 0xf8, 0x7e, 0xd1, 0x36, 0x15, 0x46, 0x7c, 0xfc, 0x91, 0xc2, 0x6e, 0xb3, 0x8a, 0x7a, 0xf9, 0xf5, 0x66, 0x86, 0x93, 0x1a, 0x47, 0x26, 0xda, 0x04 } +, + /* Encryption */ + 256, + { 0x25, 0x17, 0x7b, 0xfe, 0x12, 0x61, 0x9b, 0x44, 0xf4, 0xa4, 0xfe, 0x7c, 0xb7, 0x6d, 0xe9, 0x3d, 0x4e, 0xd4, 0xa0, 0x5a, 0x31, 0xe5, 0xbe, 0x8c, 0xc4, 0xe5, 0x60, 0x66, 0x1d, 0xe9, 0xa3, 0x4a, 0xe3, 0x17, 0xcc, 0x02, 0xff, 0x63, 0x10, 0x67, 0x08, 0x32, 0x8b, 0xd3, 0xf7, 0x87, 0x63, 0xab, 0x3e, 0x57, 0x65, 0x2c, 0x63, 0xf1, 0x05, 0xf7, 0x97, 0x1d, 0x2d, 0x8d, 0x70, 0x1e, 0x62, 0x97, 0xa7, 0x9c, 0x78, 0x7b, 0x7c, 0xcd, 0x62, 0xa5, 0x3b, 0x39, 0xd9, 0xc0, 0x39, 0x46, 0xe6, 0x6f, 0x48, 0x8a, 0x92, 0xe8, 0xe1, 0x7d, 0xc6, 0xec, 0xb0, 0xf6, 0x5b, 0xf0, 0x1e, 0x3a, 0xff, 0xee, 0x99, 0x76, 0x87, 0x31, 0x1b, 0xe0, 0xe9, 0x45, 0xad, 0xd6, 0x3f, 0xa3, 0xf4, 0x00, 0x38, 0x2c, 0xb8, 0xff, 0xd8, 0x91, 0x57, 0x54, 0x01, 0x8c, 0xc7, 0x5e, 0x82, 0x82, 0x26, 0xb5, 0x03, 0x9c, 0xd9, 0xc5, 0x7f, 0xc6, 0xd9, 0x9c, 0xbe, 0x8e, 0xa4, 0xa3, 0xd2, 0x9c, 0xbd, 0x09, 0xd5, 0x4d, 0x95, 0xcc, 0x07, 0x34, 0xc2, 0x35, 0x44, 0xf8, 0xe1, 0xfb, 0xc7, 0x49, 0x3e, 0x06, 0xd1, 0x6c, 0x0a, 0x0a, 0xc1, 0x53, 0x0d, 0x21, 0xf0, 0x33, 0x7e, 0x26, 0x2f, 0xd9, 0xd2, 0x7f, 0xcc, 0x4a, 0xfe, 0xb5, 0x74, 0xd6, 0x68, 0x66, 0xd4, 0xca, 0x84, 0xcf, 0xd6, 0xe0, 0xaf, 0x2b, 0xb9, 0x77, 0xa5, 0xd9, 0x9a, 0x5b, 0x0b, 0x37, 0x44, 0x04, 0x2d, 0x33, 0x2b, 0x93, 0x6b, 0xbd, 0xd8, 0x69, 0xe5, 0xf2, 0xc8, 0x83, 0xb4, 0x00, 0xac, 0x8b, 0xc0, 0x68, 0x3e, 0x67, 0x90, 0x63, 0x42, 0x9d, 0x98, 0xd4, 0x94, 0xf3, 0x18, 0x04, 0xd6, 0x5b, 0xb3, 0xc9, 0x74, 0xaa, 0x72, 0xe6, 0x65, 0x7d, 0x4c, 0x16, 0x38, 0xc6, 0x79, 0xc8, 0x1a, 0x16, 0x45, 0x3f, 0x6b, 0x0b, 0xaa, 0x3f, 0x05, 0x17 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.12", + /* Message */ + 28, + { 0x49, 0xf6, 0xf8, 0xa4, 0xa8, 0x6a, 0x8a, 0xa0, 0x97, 0x63, 0xaa, 0xc8, 0x55, 0x72, 0xb0, 0xe7, 0xee, 0x77, 0x6a, 0xef, 0xf8, 0xa8, 0x29, 0x00, 0x07, 0x76, 0xff, 0xa6 } +, + /* Seed */ + 225, + { 0x6d, 0xb6, 0xa8, 0x27, 0xac, 0x2a, 0x5e, 0x06, 0x16, 0xc0, 0xf4, 0x43, 0xb2, 0x34, 0x58, 0xe1, 0x75, 0xac, 0xf9, 0xa3, 0xb2, 0x55, 0xf5, 0xc8, 0x52, 0x5e, 0x72, 0x53, 0x42, 0x4f, 0xaa, 0x91, 0x38, 0x05, 0x4c, 0x3d, 0xba, 0xa4, 0x71, 0xf2, 0x7f, 0xe8, 0x55, 0xc1, 0xc0, 0xce, 0xc3, 0x62, 0x59, 0x7a, 0x1a, 0x1e, 0x6e, 0xb4, 0xf2, 0x98, 0xac, 0x3e, 0xb7, 0x34, 0xd3, 0x1f, 0xf0, 0xef, 0x10, 0x08, 0xc0, 0xe0, 0x2b, 0x9b, 0x06, 0xe2, 0x93, 0x15, 0xfc, 0x09, 0x4a, 0x7e, 0xd2, 0x6b, 0x11, 0xea, 0x55, 0x27, 0x0a, 0x3d, 0xcb, 0x67, 0x06, 0xf4, 0x6a, 0x94, 0x50, 0xbf, 0x83, 0x12, 0x88, 0x10, 0x65, 0x13, 0x02, 0x48, 0xd2, 0x64, 0x47, 0x66, 0xa7, 0x99, 0x66, 0xef, 0xda, 0xdb, 0xaa, 0xf5, 0x75, 0xef, 0x4d, 0xd3, 0x5a, 0x93, 0x7f, 0xf0, 0xbf, 0xbf, 0x3d, 0x95, 0x61, 0xc7, 0x54, 0x40, 0x9b, 0xe7, 0xb8, 0x84, 0x7a, 0x60, 0x8d, 0x79, 0x1f, 0xb9, 0x87, 0xee, 0xd4, 0x6a, 0xfe, 0xb0, 0xdb, 0x1c, 0xa9, 0x75, 0xc0, 0x5f, 0x61, 0x57, 0x0d, 0xd0, 0x70, 0x98, 0x5f, 0x13, 0xe4, 0xe0, 0xed, 0x7a, 0x8c, 0xb3, 0x91, 0xce, 0x4d, 0x42, 0x08, 0x32, 0xb4, 0x5a, 0x8b, 0x7e, 0x9f, 0x90, 0x88, 0x4e, 0x61, 0x18, 0x98, 0xf4, 0x72, 0xa0, 0xac, 0x46, 0xc5, 0x7a, 0xa7, 0xf8, 0x46, 0x8a, 0xa1, 0x9d, 0x9c, 0x7b, 0x31, 0x2f, 0x13, 0x43, 0x22, 0x99, 0x03, 0x93, 0x88, 0x1d, 0x32, 0xaa, 0x14, 0x68, 0xf6, 0xe5, 0xf8, 0xeb, 0x85, 0xa2, 0xc3, 0xc2, 0xda, 0xed, 0x92, 0xb9, 0x3c } +, + /* Encryption */ + 256, + { 0x0f, 0xf9, 0x5f, 0x4a, 0x2a, 0x07, 0x18, 0xd6, 0x73, 0xf9, 0x20, 0x2c, 0x80, 0x9f, 0x10, 0x45, 0x10, 0x1f, 0x52, 0xb9, 0xdb, 0xa7, 0x72, 0x88, 0xfe, 0x28, 0x8c, 0xb2, 0x77, 0xc4, 0xdb, 0xaa, 0x35, 0xdb, 0x93, 0x27, 0xec, 0xee, 0xc3, 0x76, 0x5a, 0xe0, 0x33, 0xe0, 0xb6, 0xb7, 0x77, 0xb2, 0x2c, 0xa6, 0xbe, 0x66, 0x20, 0x03, 0xea, 0xfa, 0x2b, 0xfb, 0xda, 0x60, 0x6f, 0xd8, 0xce, 0xe7, 0xee, 0xe0, 0x6c, 0x6a, 0x00, 0xc9, 0x45, 0xa6, 0x55, 0x6c, 0x60, 0xb0, 0x08, 0x69, 0xf9, 0x99, 0x97, 0x1a, 0x8c, 0x57, 0xaf, 0xe1, 0xdd, 0xee, 0x7a, 0x75, 0x77, 0x04, 0x7a, 0x0d, 0xb9, 0x0f, 0x62, 0xcd, 0x24, 0x7a, 0x88, 0x7f, 0x32, 0x27, 0xef, 0x6d, 0xa9, 0x07, 0xa7, 0x5b, 0xcf, 0xf1, 0x9a, 0xa3, 0x0c, 0x90, 0x8f, 0x58, 0x35, 0xef, 0x10, 0x10, 0x0a, 0xdc, 0x7f, 0x6a, 0xd6, 0xfb, 0x31, 0x99, 0x79, 0x0b, 0x3f, 0x4d, 0x6a, 0xd1, 0x9a, 0x0d, 0xf5, 0x02, 0x7f, 0xdb, 0x8f, 0x84, 0x66, 0x04, 0xe0, 0x2d, 0xaf, 0x33, 0x55, 0xd9, 0x56, 0x40, 0x77, 0x79, 0xaf, 0x15, 0x5a, 0xcf, 0xa5, 0xa3, 0x2e, 0x6d, 0x61, 0x74, 0xdc, 0x90, 0x13, 0x1d, 0xbd, 0x7a, 0xbe, 0x58, 0x5d, 0xd7, 0x59, 0xfa, 0x3c, 0xb7, 0xe9, 0xf7, 0x21, 0x45, 0x3f, 0x3e, 0x35, 0x4f, 0xe7, 0xbe, 0x0b, 0x11, 0x8e, 0xf5, 0xb8, 0x79, 0x42, 0xb5, 0xfe, 0xd4, 0xc3, 0x0d, 0x7a, 0x08, 0xfe, 0x24, 0x64, 0xeb, 0x79, 0xa3, 0xde, 0xba, 0xb3, 0x7b, 0x6d, 0x3a, 0x0a, 0xb3, 0x15, 0x77, 0xde, 0x7e, 0x93, 0x22, 0x9b, 0x49, 0xd1, 0xe8, 0xfd, 0x56, 0x32, 0xd0, 0x26, 0xd8, 0x3e, 0xe0, 0x6a, 0xa7, 0x85, 0x34, 0xce, 0xe3, 0x08, 0x1b, 0x22, 0x2e, 0xc4, 0xcd, 0x94, 0x88, 0xcc, 0xde, 0x4e, 0x15, 0x29, 0x05 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.13", + /* Message */ + 5, + { 0x12, 0x97, 0x5d, 0xb7, 0x3d } +, + /* Seed */ + 248, + { 0x6a, 0x4b, 0x4f, 0xb8, 0x05, 0x80, 0x72, 0x72, 0x96, 0x5b, 0xff, 0x2f, 0x4c, 0x80, 0x0f, 0x96, 0x4f, 0xa3, 0xae, 0xb9, 0xfb, 0x43, 0x3b, 0x40, 0xc8, 0xac, 0xc5, 0x98, 0xb4, 0x84, 0x02, 0x98, 0x93, 0xa2, 0x19, 0xc9, 0x53, 0x21, 0x34, 0xc0, 0x6a, 0xc8, 0x42, 0x5c, 0x28, 0xa5, 0xf0, 0x63, 0xc2, 0x84, 0x20, 0x0a, 0x04, 0x56, 0x43, 0x48, 0x97, 0x16, 0x51, 0x6a, 0x98, 0x7b, 0xf8, 0x1b, 0xa1, 0x86, 0xf4, 0xce, 0xb8, 0xd8, 0xd9, 0xdc, 0x1d, 0x73, 0xf2, 0x26, 0x7f, 0xd1, 0x98, 0x8d, 0x6a, 0x2f, 0xfd, 0x68, 0xcd, 0x36, 0x69, 0xde, 0x2b, 0x04, 0x70, 0x09, 0x43, 0xd0, 0xd4, 0x44, 0xae, 0x3d, 0xa8, 0xf0, 0x59, 0x4e, 0x62, 0x61, 0xe5, 0xff, 0xf6, 0x07, 0xf0, 0x4d, 0xf3, 0x1e, 0x3d, 0x9c, 0x91, 0x22, 0xd7, 0x6f, 0xb9, 0x0f, 0x3f, 0x82, 0xc3, 0x93, 0x25, 0x3b, 0x75, 0x20, 0x16, 0x5b, 0xd1, 0xf3, 0x19, 0xab, 0x3b, 0x87, 0x5e, 0xcc, 0x6a, 0xb3, 0xed, 0x02, 0x47, 0xd0, 0x37, 0x70, 0xf8, 0xd6, 0x47, 0x1d, 0x69, 0xcd, 0x13, 0xee, 0x25, 0x7c, 0x1f, 0xc8, 0xb3, 0x0f, 0x19, 0xb9, 0x3f, 0xe4, 0xf2, 0xfc, 0x9c, 0x21, 0x49, 0x28, 0x13, 0xd1, 0xfc, 0x85, 0x2a, 0xf7, 0x0c, 0xdc, 0x63, 0x84, 0xd2, 0xae, 0x55, 0xb9, 0x1e, 0x39, 0xae, 0x6c, 0x3b, 0x19, 0xfd, 0x1a, 0x7d, 0xea, 0xf7, 0x18, 0xc0, 0x5d, 0x57, 0x80, 0x95, 0x96, 0xa2, 0x88, 0xfc, 0x9a, 0xef, 0xb8, 0x15, 0xae, 0xa2, 0x9f, 0xaf, 0x67, 0x83, 0xc0, 0x05, 0x35, 0xfd, 0x71, 0xd6, 0x25, 0x49, 0x40, 0xb7, 0x62, 0xf5, 0x07, 0x26, 0x1f, 0x20, 0x9b, 0xc8, 0xba, 0x94, 0x79, 0xbb, 0x3f, 0x5d, 0x64, 0x64, 0x23, 0x19, 0xcc, 0x31, 0x86, 0x85, 0x9c } +, + /* Encryption */ + 256, + { 0x27, 0x15, 0xd6, 0xeb, 0x53, 0xae, 0xe6, 0xd4, 0xbd, 0xdd, 0x3b, 0xe9, 0xb6, 0x63, 0x14, 0x4a, 0x41, 0x0d, 0x03, 0x81, 0x77, 0x9f, 0x79, 0x9d, 0xca, 0x88, 0x07, 0x92, 0xab, 0x43, 0x1a, 0xf9, 0x98, 0x9d, 0xeb, 0x17, 0x36, 0x9d, 0xc6, 0x74, 0x38, 0xad, 0xd8, 0x2b, 0xdf, 0x0a, 0x59, 0xdd, 0x3b, 0xc2, 0x78, 0x01, 0x02, 0x58, 0xc7, 0xdf, 0x87, 0x69, 0x84, 0xff, 0x52, 0x76, 0x78, 0xbf, 0x9b, 0x34, 0xc0, 0x77, 0x43, 0xb5, 0xd2, 0x2f, 0x4f, 0x30, 0xcb, 0x5d, 0x7d, 0x8a, 0x6c, 0xfd, 0x50, 0x58, 0x24, 0xf2, 0xe0, 0x94, 0x02, 0x4f, 0xb0, 0x43, 0x30, 0xf6, 0x6d, 0xa7, 0xcb, 0xc0, 0x1d, 0x5e, 0xcc, 0x8d, 0xfc, 0xa1, 0xca, 0x9e, 0x50, 0x91, 0xb9, 0xd9, 0xc8, 0xe3, 0x8d, 0x0a, 0xc3, 0x93, 0x1d, 0xe5, 0xd1, 0xfd, 0xc8, 0x33, 0x73, 0x84, 0x82, 0xa7, 0xfd, 0x15, 0x2c, 0x1d, 0x24, 0xe6, 0x9e, 0xa0, 0x1d, 0xd3, 0xe1, 0xfa, 0x77, 0x23, 0x54, 0xa6, 0x07, 0xd6, 0x2c, 0x60, 0xb5, 0x61, 0xdc, 0x5c, 0xcb, 0x01, 0x2b, 0x71, 0x2f, 0x5c, 0x2d, 0xa1, 0x89, 0x2c, 0x31, 0x20, 0xef, 0x99, 0x0d, 0x74, 0x61, 0x1d, 0xdd, 0x35, 0x66, 0xaf, 0x1a, 0xcd, 0x8b, 0x48, 0x50, 0x06, 0x1c, 0x91, 0x28, 0xf8, 0x2a, 0xd1, 0x12, 0xda, 0x9f, 0x68, 0xac, 0x88, 0x39, 0x3f, 0x9a, 0x5c, 0x2c, 0x10, 0x20, 0xaa, 0x77, 0xe9, 0xb6, 0x2e, 0x2d, 0x1e, 0x98, 0x5f, 0xef, 0x86, 0x4c, 0xc1, 0xae, 0xb4, 0x51, 0xac, 0x83, 0x9c, 0x72, 0x0c, 0xb9, 0x73, 0xe7, 0xb5, 0xdf, 0x24, 0xa9, 0x8c, 0xcb, 0x6e, 0x67, 0x72, 0x66, 0x29, 0xa3, 0x66, 0xfe, 0xa3, 0xf9, 0xa9, 0x52, 0x1d, 0xaa, 0x19, 0xb0, 0x44, 0x30, 0xe8, 0x10, 0xf2, 0xc4, 0x5a, 0x57, 0xd4, 0x25, 0x3b, 0xed, 0xb9, 0x1d, 0xa0 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.14", + /* Message */ + 46, + { 0x8d, 0xe0, 0xf5, 0xa4, 0x13, 0xa7, 0xf7, 0x86, 0x39, 0x6f, 0x09, 0xa4, 0x5e, 0x5e, 0x77, 0x4f, 0x3c, 0x60, 0x9c, 0xe6, 0xf1, 0xb4, 0x90, 0xdd, 0xe2, 0x22, 0xb3, 0x22, 0xd5, 0x34, 0x0e, 0x9b, 0x10, 0x55, 0x81, 0xf4, 0xc5, 0xbe, 0x44, 0xea, 0xbb, 0x3d, 0x1b, 0x23, 0xf8, 0x45 } +, + /* Seed */ + 207, + { 0xf8, 0x71, 0xa8, 0x97, 0xae, 0xe8, 0x45, 0xc3, 0xbb, 0x82, 0x69, 0x90, 0xb7, 0x31, 0xd2, 0x77, 0x7c, 0xf4, 0x76, 0xb5, 0xcf, 0xc5, 0x59, 0x6d, 0xf3, 0xa5, 0x23, 0xba, 0x69, 0x79, 0xc7, 0xa4, 0x51, 0x79, 0xda, 0x5f, 0xd6, 0x0f, 0x81, 0x0b, 0xf4, 0x14, 0xc5, 0x4e, 0x18, 0x2f, 0x26, 0x01, 0x72, 0x0f, 0xfe, 0x8a, 0x50, 0xd7, 0xd9, 0xd1, 0x1e, 0x56, 0x43, 0x18, 0xe9, 0x02, 0x6f, 0x07, 0xc5, 0xaa, 0xa1, 0x3e, 0xf8, 0x91, 0x28, 0x3a, 0x96, 0x63, 0xc1, 0xe3, 0xd2, 0x7b, 0x93, 0x81, 0x7d, 0x01, 0xa5, 0x6f, 0xce, 0x33, 0xd5, 0x16, 0x9b, 0xfe, 0xa6, 0x2a, 0x8e, 0xe6, 0xc3, 0x70, 0xa3, 0xaa, 0x8c, 0x71, 0x94, 0xd9, 0xd3, 0x53, 0xd0, 0x98, 0x16, 0x61, 0xfe, 0x85, 0x81, 0x62, 0x50, 0xe0, 0x32, 0x4e, 0xae, 0x1b, 0x84, 0x7f, 0xc7, 0x32, 0x91, 0x91, 0x60, 0xd0, 0x1e, 0x11, 0x92, 0xac, 0x16, 0xbe, 0x0e, 0xb8, 0xe9, 0x95, 0xe4, 0x86, 0x40, 0x27, 0x6a, 0x2d, 0xb7, 0xb8, 0x7f, 0x84, 0xb3, 0xfa, 0xc0, 0x4c, 0xe8, 0x62, 0xf0, 0x22, 0x38, 0x62, 0x3f, 0x62, 0xb9, 0x2a, 0x2e, 0x32, 0x7b, 0x01, 0xb8, 0xc7, 0xb9, 0xe5, 0xec, 0x87, 0x05, 0x5c, 0x6c, 0xb7, 0xb5, 0x56, 0x51, 0xab, 0x5a, 0xc9, 0x89, 0x83, 0x3b, 0x03, 0x4f, 0x8b, 0xe0, 0x11, 0x6f, 0x28, 0xb1, 0xe8, 0x86, 0xa2, 0xce, 0xd1, 0x23, 0x29, 0x8e, 0xb0, 0x04, 0x07, 0x5a, 0x6b, 0x5b, 0x71, 0xb1 } +, + /* Encryption */ + 256, + { 0xd3, 0x67, 0xac, 0xa8, 0xd4, 0xf1, 0x74, 0x14, 0xe9, 0xbf, 0x09, 0xad, 0x81, 0x1d, 0x78, 0xdb, 0x0e, 0x85, 0x0c, 0x45, 0xc8, 0xf9, 0xd7, 0x02, 0x44, 0x75, 0xd3, 0xe5, 0x6e, 0x3c, 0xbf, 0xbe, 0x6e, 0xe8, 0xab, 0xbf, 0xd7, 0x74, 0x58, 0x26, 0x41, 0x7c, 0xc8, 0xed, 0x52, 0xf5, 0x4e, 0x00, 0xa9, 0x2f, 0x81, 0x7e, 0xf9, 0x83, 0xe9, 0x8d, 0x10, 0x0a, 0x1f, 0x99, 0x0d, 0xb1, 0xe2, 0x90, 0xa8, 0x51, 0x6d, 0x60, 0x9b, 0xb3, 0x2e, 0x50, 0x2a, 0x77, 0xe1, 0x1f, 0x76, 0x20, 0x0b, 0x00, 0x25, 0x76, 0x5e, 0x9b, 0xd2, 0x85, 0x9b, 0xa9, 0x4a, 0x69, 0x63, 0x33, 0xa5, 0xeb, 0xe2, 0xeb, 0x25, 0xba, 0x9d, 0x19, 0x00, 0x7f, 0x64, 0x36, 0x0c, 0xc0, 0x75, 0xca, 0xd7, 0xf0, 0x99, 0x50, 0xe4, 0xb7, 0xaf, 0xcb, 0xac, 0x36, 0xe6, 0xec, 0xb0, 0x17, 0xcf, 0x4a, 0x1f, 0x25, 0xa4, 0xd2, 0xb9, 0x51, 0xbb, 0x85, 0xe8, 0x1c, 0xb2, 0xb4, 0xeb, 0x6f, 0x45, 0xcd, 0xd4, 0x00, 0xd2, 0xac, 0x4e, 0x21, 0x69, 0x89, 0x6d, 0x94, 0x15, 0x82, 0x44, 0x9c, 0xe3, 0x0f, 0x69, 0xc1, 0x7c, 0xb4, 0x49, 0x32, 0x1f, 0x65, 0xe4, 0x4d, 0xf3, 0x03, 0x87, 0x86, 0x27, 0x62, 0x13, 0x51, 0xf5, 0x2e, 0x5a, 0x07, 0x52, 0xe3, 0xb5, 0xeb, 0x12, 0x63, 0x61, 0x69, 0x7f, 0x53, 0xcf, 0x24, 0x66, 0x16, 0x5c, 0x3f, 0xbd, 0x66, 0x2b, 0x83, 0x75, 0x80, 0xb7, 0x6d, 0x45, 0x9f, 0xf0, 0x44, 0x97, 0xe5, 0xfe, 0x1b, 0x3c, 0xd1, 0x8c, 0x4d, 0x58, 0xff, 0xed, 0xab, 0xdd, 0x04, 0xa8, 0xc1, 0x08, 0xd8, 0x59, 0xb6, 0x52, 0x98, 0x63, 0x9c, 0x3a, 0xf8, 0x0c, 0xd9, 0x4e, 0x23, 0x87, 0xa8, 0x69, 0x44, 0x09, 0xef, 0x9e, 0x0b, 0x78, 0xb6, 0xf4, 0x67, 0x39, 0x0b, 0xe1, 0x08, 0x57, 0x9c, 0x9b, 0x2c } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.15", + /* Message */ + 32, + { 0x9e, 0x78, 0xc8, 0x2b, 0xfd, 0x0f, 0x23, 0xd3, 0x91, 0xe7, 0x60, 0x01, 0x64, 0x01, 0x9a, 0xad, 0x28, 0xf5, 0x9b, 0x14, 0x15, 0x44, 0x04, 0xd9, 0xe9, 0x66, 0x13, 0x3c, 0x10, 0x3f, 0xc3, 0x7c } +, + /* Seed */ + 221, + { 0xbb, 0x42, 0x24, 0x7d, 0xb2, 0x40, 0xba, 0xca, 0xcb, 0xcb, 0xe8, 0xc6, 0x8c, 0xb0, 0xf7, 0x0e, 0x46, 0x0a, 0x49, 0x73, 0xda, 0xe6, 0x56, 0x99, 0x35, 0x8f, 0xef, 0x82, 0x70, 0xd6, 0x5c, 0x3d, 0x0c, 0x45, 0x5a, 0x37, 0x9c, 0x56, 0x3c, 0x59, 0x7b, 0x28, 0xf4, 0xff, 0xa0, 0x70, 0xe0, 0xec, 0x1e, 0xbb, 0x9e, 0xd4, 0x27, 0xfe, 0x89, 0xab, 0xcd, 0x47, 0x93, 0xc4, 0x22, 0xc3, 0x38, 0x87, 0x8c, 0x8b, 0x14, 0x5b, 0x46, 0xc4, 0xf7, 0x13, 0x78, 0xa0, 0xfd, 0x7d, 0x50, 0x53, 0xb8, 0x67, 0x98, 0xbc, 0x02, 0xd9, 0x32, 0x93, 0xfe, 0xd8, 0x47, 0xf1, 0x8f, 0xe0, 0x61, 0x59, 0x07, 0x4a, 0xc1, 0x89, 0xd9, 0x56, 0x23, 0x20, 0x74, 0xdb, 0x6d, 0xdc, 0xf9, 0x94, 0x1a, 0x70, 0xf2, 0x8b, 0x60, 0xe4, 0x83, 0x39, 0x5a, 0x2d, 0x21, 0x01, 0x54, 0xb6, 0x2a, 0xba, 0xb8, 0x75, 0x0f, 0x5a, 0xeb, 0xf1, 0xac, 0xef, 0xe2, 0x05, 0x6f, 0x5a, 0xbd, 0x2f, 0x0e, 0x0e, 0xc4, 0x94, 0xaf, 0xa8, 0x2f, 0xc5, 0x9b, 0xb3, 0x57, 0xf1, 0x16, 0xa9, 0x4e, 0xc1, 0xcd, 0x06, 0x03, 0xb5, 0x2f, 0xe5, 0x6d, 0x31, 0xa4, 0x3b, 0x87, 0xaa, 0x63, 0x77, 0x88, 0xc7, 0x24, 0xcb, 0x6f, 0x88, 0x37, 0x3c, 0x92, 0xf6, 0x07, 0x11, 0xbf, 0x3f, 0x35, 0x94, 0xe2, 0x3d, 0xee, 0x2f, 0xec, 0xed, 0xfe, 0x6f, 0x5f, 0xc8, 0x86, 0xe9, 0x6a, 0xee, 0x7c, 0x74, 0x68, 0x22, 0xe5, 0x6c, 0xba, 0x7e, 0xbd, 0xaa, 0x2a, 0x92, 0x10, 0xea, 0x81, 0x98, 0xe4, 0xc2, 0x2d, 0xe9, 0x29, 0x89, 0x45 } +, + /* Encryption */ + 256, + { 0x81, 0x8d, 0xcb, 0xba, 0x98, 0xc3, 0x46, 0x79, 0x3c, 0x79, 0xd4, 0xbb, 0x78, 0x5a, 0xa6, 0x40, 0x19, 0x1b, 0x05, 0xf8, 0x83, 0x5f, 0xf7, 0x39, 0x74, 0x44, 0x3b, 0xce, 0x35, 0x7a, 0x26, 0x9d, 0x44, 0x64, 0x6e, 0x8c, 0x79, 0x10, 0x2d, 0xce, 0x22, 0x92, 0x39, 0x78, 0xa3, 0x94, 0x1e, 0xbc, 0xb9, 0x90, 0x4f, 0xc1, 0xbb, 0x1f, 0xb4, 0x3f, 0x11, 0x27, 0x5e, 0x71, 0xeb, 0x7a, 0x84, 0xd2, 0x74, 0xbe, 0x10, 0x4b, 0x00, 0xaf, 0x92, 0x25, 0xe2, 0xa4, 0xf7, 0xf5, 0xa0, 0x48, 0xab, 0xb6, 0x6c, 0xba, 0xb6, 0x52, 0x5d, 0x1b, 0x11, 0x5d, 0xa8, 0xc0, 0xbb, 0x08, 0xde, 0xea, 0xec, 0x7f, 0x80, 0xeb, 0x6c, 0x39, 0x50, 0x4d, 0xc4, 0xeb, 0x38, 0x15, 0x4c, 0xe4, 0xb6, 0x91, 0xb4, 0x06, 0x93, 0x19, 0xb2, 0x93, 0xc2, 0x5d, 0xc3, 0x0b, 0x8f, 0xb3, 0x8b, 0xca, 0x15, 0x3e, 0x2f, 0xa6, 0x1b, 0x33, 0x76, 0xdd, 0xc3, 0xc5, 0x3a, 0x57, 0x93, 0x21, 0xd9, 0x10, 0xa1, 0x71, 0xfc, 0x42, 0xaa, 0xf1, 0x70, 0x50, 0xed, 0x6d, 0x31, 0x1a, 0x7d, 0xf5, 0xb9, 0xa5, 0xcf, 0x3a, 0x98, 0xfd, 0x69, 0xaa, 0x85, 0xac, 0x23, 0x46, 0xc1, 0x6f, 0xa0, 0x3b, 0x1e, 0x53, 0xd1, 0x03, 0xd6, 0xf5, 0xa0, 0x4b, 0x0d, 0x9d, 0x3f, 0x18, 0x83, 0x53, 0x1e, 0x2f, 0x63, 0x41, 0xfd, 0x91, 0xbd, 0x63, 0xa5, 0xaa, 0x99, 0x3b, 0x6e, 0xdb, 0x99, 0x92, 0xe5, 0xdb, 0x17, 0xa7, 0xbe, 0x55, 0x5e, 0xaf, 0xa3, 0xbb, 0xab, 0x32, 0x08, 0x6e, 0x92, 0xb8, 0xb7, 0x91, 0x06, 0x69, 0x68, 0xe0, 0x0f, 0x8a, 0x17, 0x71, 0x61, 0x44, 0x0c, 0xe5, 0x38, 0x57, 0x97, 0x89, 0xc2, 0x91, 0x2e, 0xbd, 0x7a, 0xd0, 0x19, 0xbe, 0x29, 0x37, 0x6c, 0xad, 0xee, 0xc2, 0x99, 0x21, 0x07, 0xc9, 0xdb, 0x07, 0x60, 0x49 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.16", + /* Message */ + 47, + { 0x6d, 0x72, 0x08, 0xb2, 0xff, 0xb0, 0x1a, 0xd2, 0x36, 0x0c, 0x46, 0x09, 0xf3, 0xba, 0xd3, 0x15, 0x79, 0xc8, 0xd4, 0x00, 0x5c, 0xc9, 0x60, 0x14, 0x2e, 0x2b, 0x69, 0x6b, 0x26, 0xe9, 0x4f, 0x2d, 0x99, 0x98, 0x0b, 0xad, 0x38, 0x41, 0x05, 0xb1, 0x89, 0x95, 0x57, 0xaf, 0x89, 0x05, 0x25 } +, + /* Seed */ + 206, + { 0x72, 0xae, 0x49, 0x97, 0x18, 0x28, 0xba, 0x54, 0x23, 0xab, 0x96, 0x3c, 0xdb, 0x18, 0xf4, 0xbd, 0xfd, 0xbc, 0x74, 0x73, 0xcf, 0x70, 0xfb, 0x77, 0x21, 0x34, 0x41, 0xf1, 0xd4, 0x46, 0xae, 0x48, 0x10, 0x93, 0x03, 0xa2, 0x60, 0xc0, 0x91, 0xab, 0x51, 0x99, 0xd9, 0x64, 0xe6, 0x21, 0x63, 0xc2, 0x46, 0x57, 0x24, 0x71, 0x73, 0xcb, 0x05, 0x11, 0xb9, 0xcb, 0xb1, 0x63, 0x45, 0x9c, 0x95, 0x6f, 0x9c, 0x0b, 0x18, 0x83, 0xb6, 0x91, 0xb5, 0xe4, 0xea, 0xe0, 0x4f, 0x0a, 0xf2, 0x4e, 0xa3, 0x28, 0xc6, 0xde, 0x88, 0x2c, 0xeb, 0xc4, 0xf8, 0x9a, 0x56, 0x37, 0x32, 0x82, 0xd6, 0x0a, 0xf2, 0xba, 0x96, 0x7e, 0x25, 0x7a, 0xc4, 0x01, 0xa3, 0x7f, 0x94, 0x41, 0xc1, 0x1f, 0x2e, 0x0e, 0x42, 0x1b, 0x2d, 0x15, 0x1e, 0xb2, 0x43, 0xa9, 0x7e, 0xae, 0x5a, 0xaa, 0x86, 0xcd, 0x38, 0xdf, 0x43, 0xc2, 0x6a, 0x1d, 0x6e, 0x3b, 0x12, 0xc1, 0x3f, 0xa3, 0x59, 0x7b, 0x85, 0xbb, 0xaa, 0x13, 0x09, 0x45, 0x2c, 0x7e, 0x9b, 0x32, 0x5d, 0x8c, 0x73, 0xfa, 0x79, 0x9c, 0x57, 0x56, 0x52, 0x73, 0x7b, 0x92, 0xa2, 0x47, 0xd2, 0x3c, 0x4c, 0x70, 0x12, 0x40, 0xc5, 0x3d, 0xcf, 0xe2, 0xea, 0x69, 0x7a, 0xf6, 0x1c, 0x07, 0x2f, 0xa7, 0x6b, 0xdb, 0x05, 0x2a, 0x58, 0xc9, 0x19, 0xe6, 0x9e, 0xc5, 0x7b, 0x39, 0xa2, 0xa6, 0xc4, 0x7d, 0x77, 0x0e, 0xde, 0x67, 0x10, 0xfc, 0x7b, 0xdd, 0xe6, 0x01 } +, + /* Encryption */ + 256, + { 0x4b, 0x56, 0xdc, 0xd3, 0x04, 0xbd, 0xc7, 0xf0, 0xcc, 0xb7, 0x0d, 0x2c, 0x58, 0x6f, 0x52, 0x74, 0x60, 0x1e, 0xe6, 0x05, 0x36, 0xbb, 0x21, 0x80, 0x61, 0x67, 0x13, 0x50, 0xd6, 0xd3, 0xae, 0x2e, 0x28, 0x4f, 0x07, 0xb5, 0xed, 0x63, 0x01, 0x79, 0x26, 0x94, 0x13, 0x12, 0x2b, 0x98, 0x37, 0x60, 0x90, 0xf7, 0xa4, 0xa4, 0xf6, 0x43, 0x4a, 0xf7, 0x3a, 0xc4, 0x0c, 0x7a, 0xf4, 0xb6, 0xd7, 0xa3, 0xe3, 0x14, 0x70, 0x2a, 0xb9, 0xb8, 0x5e, 0x08, 0x73, 0x1d, 0xa0, 0xd1, 0x2e, 0xd3, 0xf0, 0x07, 0x0b, 0x0d, 0x20, 0x95, 0x05, 0x3b, 0x3f, 0x0d, 0x09, 0xd6, 0xc2, 0xcd, 0x8f, 0x98, 0xba, 0xde, 0xd9, 0x11, 0x48, 0xc3, 0x5b, 0x7b, 0x33, 0xc5, 0x43, 0x65, 0x3c, 0xcc, 0x32, 0xd8, 0x36, 0xf5, 0xf7, 0xf2, 0xee, 0x39, 0xca, 0xbd, 0x0b, 0xd8, 0x9d, 0xd9, 0xa4, 0xa9, 0x4e, 0x91, 0x2b, 0x4c, 0xa9, 0x7f, 0x18, 0x51, 0xd0, 0x17, 0x45, 0x1f, 0x60, 0x96, 0xac, 0xbf, 0x20, 0xa6, 0x5e, 0xc5, 0xa2, 0x9f, 0x08, 0xf8, 0x13, 0x5c, 0x73, 0x18, 0xa2, 0x21, 0x6d, 0x1b, 0x7d, 0x10, 0x37, 0x95, 0xc7, 0xec, 0x8e, 0xe5, 0x7a, 0x79, 0x28, 0x0f, 0x9a, 0x84, 0x4b, 0xd6, 0xab, 0x71, 0x28, 0x82, 0x0e, 0x1f, 0xb5, 0xe8, 0x25, 0x54, 0xfe, 0xc0, 0x2a, 0x78, 0xaa, 0x8d, 0x3f, 0xd6, 0xa1, 0x3e, 0x0f, 0xad, 0x0e, 0xce, 0xe7, 0xab, 0x61, 0x1d, 0xe4, 0xb0, 0xa0, 0x48, 0x1f, 0x42, 0xb8, 0xd0, 0xb5, 0x5c, 0xb8, 0x81, 0x3d, 0x1c, 0xa6, 0xe2, 0x61, 0x5c, 0xf5, 0xae, 0x8a, 0xe8, 0x6d, 0x0b, 0x5d, 0x46, 0x95, 0x50, 0x75, 0x49, 0xf7, 0xa3, 0x73, 0x66, 0xa4, 0x45, 0xfb, 0x55, 0xb7, 0xc4, 0xb6, 0xb5, 0x8e, 0xa6, 0x99, 0xdb, 0xe5, 0xdd, 0xc8, 0x19, 0x3e, 0x2b, 0xf3, 0xd5, 0xb8, 0x40 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.17", + /* Message */ + 15, + { 0x7d, 0xeb, 0x6d, 0x40, 0x41, 0x48, 0x23, 0x2c, 0x48, 0x21, 0x63, 0x4d, 0x3d, 0xf9, 0xbc } +, + /* Seed */ + 238, + { 0xe6, 0xf8, 0x3c, 0x8c, 0x99, 0x3e, 0x60, 0x15, 0xaf, 0x43, 0x04, 0x09, 0x68, 0x4e, 0x62, 0x7f, 0x3d, 0x9b, 0x84, 0xad, 0x05, 0x55, 0xc6, 0xa6, 0xc0, 0x91, 0x13, 0xa7, 0x12, 0x47, 0x2a, 0xbb, 0x36, 0xf6, 0x11, 0x92, 0x32, 0x6c, 0xf8, 0x40, 0x82, 0xaa, 0xbd, 0x1e, 0xc9, 0x5f, 0x4d, 0x1a, 0x92, 0xd9, 0x10, 0x7e, 0x30, 0x61, 0x0c, 0x8d, 0x27, 0x59, 0x55, 0x6d, 0x5d, 0x61, 0x47, 0x5c, 0xa3, 0xf3, 0xcb, 0xd9, 0x49, 0xfa, 0xc2, 0x20, 0x3c, 0x42, 0x3d, 0x56, 0xc2, 0x75, 0x58, 0xe6, 0x11, 0x8f, 0xaa, 0x0f, 0x6f, 0x68, 0x4a, 0xda, 0x13, 0xc3, 0x15, 0x3f, 0x6d, 0x25, 0x53, 0x38, 0xbf, 0xf7, 0x34, 0xe9, 0x5f, 0x60, 0xad, 0x29, 0x19, 0xab, 0xf2, 0x88, 0x15, 0xd3, 0xcc, 0x0b, 0x1e, 0xfd, 0x38, 0x5d, 0x0d, 0x45, 0x81, 0xb0, 0xee, 0x84, 0x94, 0xf2, 0xbb, 0xe2, 0x99, 0x59, 0x91, 0xac, 0x1e, 0xa8, 0x15, 0x40, 0xcb, 0x7e, 0x88, 0x56, 0x68, 0xe5, 0xa5, 0x2e, 0xca, 0x90, 0x57, 0xed, 0x9a, 0x1f, 0xb2, 0x3f, 0xdf, 0x83, 0xb5, 0x75, 0x51, 0x35, 0x8c, 0x23, 0xcd, 0x43, 0xce, 0x0e, 0x7a, 0x33, 0xc7, 0x25, 0x66, 0xb8, 0x8f, 0xe5, 0x93, 0x43, 0xf1, 0x87, 0x24, 0x46, 0xd3, 0x2c, 0x44, 0xb3, 0x99, 0x0a, 0xa4, 0xdb, 0x3e, 0xe5, 0x93, 0x42, 0x4c, 0x8e, 0x09, 0x46, 0xd2, 0x61, 0xe3, 0x27, 0x0e, 0xf4, 0x07, 0x6b, 0xb3, 0x5d, 0xf3, 0xc3, 0xc6, 0xda, 0x4b, 0xbe, 0x42, 0x3f, 0x59, 0x1b, 0x5c, 0x93, 0xba, 0x56, 0xc5, 0xcf, 0x01, 0xd4, 0xf0, 0xa9, 0x40, 0x96, 0x71, 0x09, 0xd3, 0x9b, 0x93, 0x9d, 0xf2, 0x82, 0x53, 0x2e, 0x54, 0x83, 0x10, 0x8b } +, + /* Encryption */ + 256, + { 0xaa, 0x6e, 0x6e, 0x4a, 0xf6, 0x89, 0x26, 0x4d, 0x61, 0xbf, 0xa8, 0xf5, 0x08, 0x6d, 0x82, 0x79, 0xdd, 0xc2, 0x28, 0x9c, 0x55, 0x41, 0xaf, 0x45, 0x35, 0x19, 0xc4, 0x4b, 0x95, 0xea, 0xe6, 0xa1, 0x5e, 0x7e, 0x7b, 0xd1, 0x5f, 0xd3, 0x1a, 0x4f, 0xad, 0x5f, 0x7c, 0x85, 0x90, 0x5e, 0xfc, 0xa2, 0x26, 0x93, 0x0d, 0x67, 0xda, 0xf5, 0x58, 0xb7, 0x15, 0xb2, 0x1f, 0x36, 0x28, 0xf6, 0x1a, 0x3b, 0x04, 0x2c, 0x1a, 0x38, 0xf9, 0xaf, 0x3a, 0xda, 0x82, 0xec, 0x44, 0x88, 0xc8, 0xad, 0xe5, 0xf1, 0xda, 0x81, 0xe1, 0xa8, 0xab, 0x90, 0xe1, 0xb3, 0x12, 0xdc, 0xda, 0x83, 0x5f, 0x9e, 0x92, 0x5f, 0x2e, 0x72, 0x46, 0x3f, 0xa8, 0x33, 0xa0, 0x8b, 0x93, 0x25, 0x3f, 0xdf, 0xe8, 0xcf, 0x4e, 0x5f, 0x3c, 0xfa, 0x91, 0x10, 0x77, 0x19, 0xa6, 0xa9, 0x46, 0x9a, 0xcd, 0x71, 0x25, 0xae, 0x67, 0xb2, 0xbd, 0x75, 0x85, 0x7c, 0x59, 0xbe, 0x0a, 0xbe, 0x98, 0x40, 0x74, 0xe2, 0x95, 0x47, 0x8a, 0xf2, 0x74, 0x0e, 0x25, 0x89, 0x4e, 0x56, 0xa6, 0x25, 0x0e, 0xf7, 0x36, 0x21, 0x94, 0x13, 0x81, 0x03, 0x74, 0x3c, 0xa9, 0x54, 0x47, 0x33, 0xd2, 0x50, 0x55, 0x71, 0xbe, 0xe0, 0x0f, 0x17, 0x8a, 0x2c, 0xfa, 0x38, 0xe1, 0xf8, 0xf2, 0x2f, 0xb2, 0x39, 0x30, 0xd6, 0xa7, 0x5d, 0xd1, 0x7c, 0x68, 0x9a, 0x47, 0x6d, 0x87, 0x15, 0x31, 0x85, 0x95, 0x10, 0x8f, 0xcc, 0xe8, 0x95, 0xe3, 0x44, 0x9e, 0xca, 0x97, 0xa7, 0xdd, 0xba, 0xe3, 0xe6, 0xd6, 0xf0, 0xe3, 0x5e, 0x66, 0x6d, 0x6f, 0xbd, 0x78, 0x78, 0x48, 0xf8, 0x68, 0x13, 0x37, 0xb1, 0xd4, 0xc5, 0x23, 0x8b, 0x1c, 0x24, 0xde, 0x77, 0xa7, 0xe6, 0x75, 0xe7, 0xae, 0xd8, 0xdc, 0x13, 0xdd, 0x9e, 0xb1, 0x06, 0x87, 0x98, 0x51, 0x7c, 0x0b, 0x6e } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.18", + /* Message */ + 30, + { 0x03, 0x1f, 0xc3, 0xa3, 0xea, 0xa4, 0x2b, 0x0d, 0x9f, 0x6d, 0x7d, 0xd5, 0x99, 0x3d, 0x61, 0x89, 0xcb, 0xb2, 0xe0, 0xe9, 0x6f, 0xaa, 0x33, 0xd6, 0x1f, 0x31, 0x7b, 0x6b, 0x3c, 0x00 } +, + /* Seed */ + 223, + { 0x16, 0xab, 0x64, 0x85, 0xca, 0xc0, 0x39, 0x71, 0x14, 0x88, 0x0e, 0x6f, 0x72, 0xbc, 0x1f, 0x1e, 0xf3, 0x4b, 0xa2, 0x7d, 0x1c, 0x43, 0x3d, 0x77, 0xf3, 0x37, 0x2b, 0x1f, 0xd5, 0xb2, 0x1b, 0xa5, 0x7a, 0x50, 0x5c, 0xd8, 0xf3, 0x5b, 0x75, 0x24, 0x2c, 0xf1, 0xb7, 0x6d, 0x38, 0x1c, 0x68, 0x34, 0x24, 0x01, 0xee, 0xef, 0xc8, 0x42, 0x53, 0xa2, 0xde, 0x1a, 0x19, 0x13, 0xe4, 0x38, 0x77, 0x3b, 0x7b, 0xcb, 0x31, 0xcb, 0xab, 0x25, 0x8f, 0x72, 0x6a, 0xc9, 0x34, 0xa8, 0x71, 0x26, 0x96, 0x9a, 0xdb, 0x7f, 0x76, 0x8c, 0x1b, 0xab, 0x87, 0x54, 0xa1, 0x3a, 0x3c, 0xcb, 0xba, 0x6f, 0x3d, 0xd8, 0xd0, 0xec, 0x6a, 0x7c, 0x6d, 0x68, 0x7d, 0x04, 0x95, 0xb6, 0xe2, 0x2c, 0x9a, 0xe7, 0x67, 0xaf, 0xc9, 0xd9, 0x4f, 0x2e, 0x45, 0xa1, 0x06, 0x13, 0x3c, 0x42, 0xc7, 0x9b, 0x52, 0xc2, 0x6a, 0xd4, 0xb6, 0x7b, 0xd8, 0xec, 0xe5, 0x5e, 0x84, 0x32, 0x5c, 0xa6, 0xf4, 0x9c, 0x8e, 0x95, 0x31, 0xf5, 0xf6, 0xb9, 0xca, 0xc3, 0x5c, 0x93, 0x3e, 0xeb, 0xe3, 0xb9, 0xa1, 0x1b, 0x9b, 0xb1, 0xc9, 0xea, 0x8c, 0xe6, 0xd2, 0x28, 0x5d, 0xa9, 0x08, 0xe5, 0x91, 0x97, 0x82, 0xb5, 0xb3, 0x08, 0xfe, 0x47, 0x8d, 0x98, 0xe4, 0x9a, 0xea, 0x54, 0x3b, 0xf8, 0xca, 0x1b, 0x22, 0xed, 0xf4, 0x3f, 0xdb, 0xf6, 0xaf, 0x31, 0xcc, 0x8c, 0xd4, 0xfb, 0x7d, 0xe2, 0xd8, 0x19, 0xaf, 0xa5, 0x48, 0x3e, 0xac, 0xdd, 0x56, 0xd7, 0x78, 0x7b, 0xc8, 0xbb, 0x16, 0x22, 0x38, 0x40, 0x49, 0xbc, 0x30, 0x9a, 0x66 } +, + /* Encryption */ + 256, + { 0x61, 0xc7, 0x54, 0x76, 0x30, 0x43, 0xb5, 0x84, 0xe4, 0xa8, 0x54, 0x6b, 0x79, 0xf0, 0xa3, 0xe2, 0xe0, 0xf3, 0xb3, 0xe2, 0xdb, 0x6c, 0x94, 0xad, 0x81, 0x7e, 0x92, 0x81, 0xf4, 0x85, 0xc0, 0x82, 0x08, 0xfe, 0xd4, 0xf4, 0xd7, 0xd0, 0xa7, 0x8c, 0x6c, 0x31, 0x1a, 0x07, 0xc7, 0x5b, 0x9b, 0xbe, 0x85, 0x04, 0xf4, 0xb7, 0xa6, 0x92, 0x99, 0x02, 0x16, 0xde, 0x12, 0x58, 0x5c, 0x00, 0x9a, 0xe5, 0x8c, 0x26, 0xf0, 0x85, 0x07, 0x1f, 0x39, 0x5e, 0x5a, 0xf8, 0x92, 0x5f, 0x39, 0x33, 0xf6, 0xd9, 0xf4, 0x12, 0xd4, 0x25, 0x54, 0x64, 0x54, 0xe8, 0x00, 0xb7, 0xe3, 0xaa, 0xc7, 0x8b, 0x7a, 0x08, 0xb9, 0x2e, 0x79, 0x8b, 0xb8, 0x34, 0xeb, 0xea, 0xdc, 0x4b, 0x4a, 0x63, 0x56, 0xaf, 0x1c, 0xa0, 0x9b, 0xf5, 0x86, 0x74, 0x5f, 0x61, 0x6d, 0x51, 0x74, 0x8c, 0xc7, 0xa3, 0x7b, 0x48, 0xcb, 0x10, 0x97, 0x7e, 0x30, 0x3b, 0xbe, 0x10, 0xbf, 0x27, 0xc6, 0x9b, 0xdf, 0xf0, 0xba, 0x5c, 0xab, 0x8f, 0x62, 0xd0, 0x58, 0x7a, 0x09, 0xd6, 0xe0, 0x22, 0x82, 0x32, 0x33, 0xc8, 0xc7, 0xaa, 0x41, 0x87, 0x22, 0x23, 0xed, 0x15, 0xa7, 0x4a, 0xcc, 0xb0, 0xf1, 0xf8, 0x22, 0xf2, 0x4d, 0x75, 0x94, 0xed, 0x99, 0x25, 0xa1, 0xc6, 0xc0, 0xc0, 0xf9, 0xad, 0x0e, 0x07, 0x1e, 0xb6, 0xb5, 0xeb, 0xe1, 0xba, 0xb6, 0xba, 0x3b, 0x6d, 0x99, 0xa3, 0x16, 0x52, 0x04, 0x7f, 0x46, 0x92, 0x60, 0xbe, 0xe8, 0x71, 0x0e, 0x37, 0x0f, 0x04, 0xed, 0x70, 0x75, 0x93, 0x93, 0x7a, 0x08, 0xdd, 0x82, 0x26, 0x49, 0x92, 0x31, 0x1f, 0x4a, 0xf9, 0x88, 0x4c, 0xf8, 0xad, 0x34, 0xaf, 0xb9, 0xf6, 0x75, 0x99, 0x3c, 0x8a, 0xbf, 0x41, 0x51, 0x98, 0x39, 0xf7, 0x6f, 0xa1, 0xe9, 0x31, 0xbd, 0xae, 0x1d, 0x08, 0xa6, 0x34 } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.19", + /* Message */ + 43, + { 0xc9, 0xc9, 0x3a, 0xfe, 0xa9, 0x97, 0xb1, 0xee, 0x36, 0xfa, 0x72, 0x72, 0x03, 0x54, 0xc7, 0x04, 0x64, 0x9b, 0xc6, 0xef, 0x44, 0xf5, 0x18, 0x7c, 0x6c, 0x28, 0x54, 0x2b, 0x9a, 0xe9, 0x55, 0xa7, 0x19, 0x3f, 0xff, 0xec, 0x86, 0x7b, 0xb6, 0x2e, 0x21, 0x9e, 0x68 } +, + /* Seed */ + 210, + { 0x52, 0xd4, 0xc3, 0xbf, 0x0c, 0x77, 0x2c, 0x02, 0xd3, 0xbb, 0x71, 0x1d, 0x7f, 0x14, 0x6d, 0x8c, 0x49, 0x76, 0xf8, 0x30, 0x81, 0xbe, 0x49, 0x53, 0xd4, 0xaf, 0xeb, 0x07, 0x8e, 0x54, 0x12, 0xa3, 0x2c, 0x3d, 0xc7, 0x37, 0xb5, 0x9b, 0xc4, 0x54, 0xc3, 0xde, 0x93, 0xa1, 0xae, 0xd0, 0x7c, 0x1b, 0xa6, 0x4d, 0x1d, 0xe4, 0x36, 0x80, 0x14, 0xd0, 0x4f, 0x64, 0x40, 0x55, 0x6a, 0x4a, 0x16, 0x97, 0x9d, 0x08, 0x03, 0xcc, 0x29, 0x22, 0xda, 0x97, 0xed, 0x67, 0x61, 0x90, 0x12, 0xf8, 0xf7, 0xd3, 0xb1, 0xa4, 0x55, 0x84, 0xb0, 0x94, 0x6a, 0xf6, 0xdb, 0xd4, 0xa0, 0x85, 0x7d, 0x4c, 0x2d, 0xb9, 0x9a, 0x17, 0xbb, 0xd2, 0x7a, 0xcd, 0x9a, 0x62, 0xe6, 0x7f, 0x88, 0x79, 0xdb, 0xef, 0x27, 0xf1, 0x04, 0x6a, 0x86, 0x7e, 0x69, 0x95, 0x16, 0x2b, 0x2a, 0x1a, 0x1c, 0xcc, 0xdc, 0xea, 0xf4, 0x5b, 0xe1, 0x33, 0x7e, 0x5f, 0xa8, 0xf8, 0x5e, 0xda, 0xad, 0xf7, 0x50, 0x8d, 0x58, 0xf3, 0x26, 0xaa, 0x7c, 0xf3, 0x01, 0xf4, 0x41, 0xba, 0x55, 0x8b, 0x60, 0xe0, 0xfa, 0xc6, 0xe0, 0xd1, 0x99, 0x20, 0x61, 0xa0, 0xa4, 0x69, 0xbe, 0x02, 0x16, 0x26, 0x89, 0x0e, 0xe8, 0x7e, 0x68, 0x13, 0x9b, 0xd5, 0x19, 0xae, 0x77, 0x3e, 0x3e, 0xc4, 0x81, 0xb7, 0xf2, 0xb3, 0x77, 0x33, 0x1f, 0x52, 0xf2, 0xe3, 0x86, 0x88, 0x4f, 0x76, 0x57, 0x23, 0xe2, 0x6c, 0xd4, 0xa8, 0xd9, 0x68, 0x61, 0x4c, 0x9c, 0x33, 0xdc, 0xdb } +, + /* Encryption */ + 256, + { 0xd0, 0x68, 0x67, 0x02, 0x2a, 0x0f, 0xaf, 0x57, 0x3d, 0x62, 0xcc, 0x24, 0xa6, 0xe0, 0x6a, 0x44, 0xcd, 0x3d, 0x83, 0xea, 0xc5, 0xd0, 0x80, 0x9e, 0xbf, 0x91, 0x30, 0x45, 0x68, 0xcb, 0x1b, 0x27, 0x56, 0x1b, 0xb2, 0x92, 0xe8, 0x77, 0x6e, 0x21, 0x6d, 0x1d, 0x02, 0x3e, 0x75, 0x3c, 0x12, 0x4b, 0x51, 0x86, 0x7b, 0x94, 0xdc, 0x60, 0x89, 0x4d, 0x62, 0xc7, 0xda, 0xe5, 0xfa, 0x1a, 0x9f, 0xaf, 0x03, 0x76, 0xe1, 0x75, 0x8c, 0xb6, 0xad, 0xc7, 0x14, 0x17, 0xe8, 0x31, 0x02, 0x52, 0x8f, 0x23, 0xf4, 0xc5, 0xe5, 0xb5, 0x03, 0x62, 0xa3, 0x9e, 0x2a, 0xa9, 0x76, 0x8b, 0x10, 0x62, 0x08, 0x6f, 0xa8, 0xc5, 0x3f, 0xf1, 0xc3, 0x9a, 0x0e, 0xe0, 0x3d, 0x38, 0x3d, 0x24, 0xbf, 0x49, 0x07, 0x22, 0xb7, 0x86, 0xda, 0xec, 0x90, 0x8c, 0xd7, 0x15, 0x1e, 0x18, 0x5d, 0xdd, 0x17, 0x88, 0x26, 0x78, 0x02, 0x7e, 0x36, 0x8b, 0x05, 0x12, 0xcf, 0x98, 0x41, 0x3f, 0x3e, 0x59, 0x6f, 0xa3, 0xdb, 0x4e, 0xc1, 0x96, 0xae, 0x5f, 0xf5, 0x24, 0xa8, 0x26, 0x6d, 0x76, 0x0e, 0x00, 0x51, 0x43, 0x3d, 0x18, 0x98, 0xff, 0xc2, 0x30, 0xe9, 0x6a, 0x2f, 0x0b, 0xfd, 0xf2, 0xb2, 0x44, 0x29, 0xad, 0xfa, 0x91, 0x8a, 0xba, 0x1a, 0x45, 0x0f, 0x76, 0x78, 0x34, 0x72, 0x30, 0x12, 0x93, 0x84, 0x8b, 0xd8, 0x2d, 0x5a, 0x33, 0x84, 0x31, 0xd6, 0xcb, 0x1c, 0x10, 0x6d, 0xc7, 0x41, 0xd2, 0x34, 0xbf, 0x5a, 0x80, 0xdb, 0xd3, 0x25, 0xda, 0x64, 0xa3, 0x94, 0xa0, 0x06, 0x5f, 0x22, 0x02, 0x8d, 0x0f, 0xdc, 0x5a, 0xdf, 0x0d, 0x0d, 0xe2, 0x9f, 0x22, 0xfb, 0x8c, 0x2a, 0x41, 0x33, 0x1f, 0xe1, 0xfc, 0xb6, 0x15, 0x89, 0xe0, 0xec, 0x75, 0x00, 0xed, 0x84, 0x42, 0xd6, 0x18, 0x46, 0xdf, 0x6c, 0xca, 0x46, 0xcc } + +} +, +{ + "PKCS#1 v1.5 Encryption Example 15.20", + /* Message */ + 22, + { 0x69, 0xb7, 0x64, 0x48, 0x55, 0xf9, 0x1d, 0x1c, 0x61, 0xc8, 0x49, 0x8e, 0x4b, 0xa1, 0xba, 0x4d, 0x84, 0x5b, 0xa8, 0x82, 0xb1, 0x73 } +, + /* Seed */ + 231, + { 0xb2, 0x2f, 0xc7, 0xde, 0x85, 0xc5, 0xf7, 0x5a, 0x2f, 0x32, 0xaf, 0x1b, 0xfb, 0xcd, 0x57, 0x89, 0x71, 0x56, 0x87, 0xde, 0x06, 0xe6, 0x6d, 0x06, 0x4a, 0xe3, 0xeb, 0x8d, 0xfb, 0x07, 0xa2, 0x57, 0x5b, 0xe0, 0xe9, 0xe6, 0xf2, 0x9f, 0x50, 0xd7, 0x39, 0x6d, 0x07, 0x8b, 0x36, 0xef, 0x80, 0x2f, 0x75, 0x1a, 0x77, 0xcc, 0x92, 0xd7, 0x61, 0x4c, 0x91, 0xdd, 0x27, 0x99, 0x31, 0xfc, 0xe0, 0x07, 0xeb, 0xf9, 0x15, 0xa0, 0xf1, 0x4e, 0x31, 0x2c, 0xe9, 0x1f, 0xe5, 0xaa, 0x6f, 0xb3, 0x74, 0x51, 0x61, 0x4f, 0xe3, 0x7c, 0x73, 0xfc, 0x6f, 0x6d, 0x6f, 0x8e, 0x52, 0x78, 0x9b, 0x5d, 0x88, 0xe8, 0x6b, 0xeb, 0x16, 0x33, 0xf5, 0xdd, 0xd5, 0xc0, 0x70, 0xf1, 0x4f, 0xd3, 0xcf, 0xee, 0x97, 0xdd, 0x4a, 0x64, 0x3d, 0x35, 0xd4, 0x5d, 0xd9, 0xbf, 0x34, 0xdf, 0x8c, 0x31, 0x0b, 0x48, 0x59, 0x2e, 0x94, 0x68, 0x31, 0xb3, 0x4e, 0xf3, 0xc0, 0xb9, 0x16, 0xf1, 0x7c, 0xb0, 0xac, 0xb2, 0xcf, 0xc1, 0xc2, 0x5d, 0x03, 0x09, 0xac, 0xc1, 0x12, 0x4f, 0x26, 0x5c, 0x1a, 0x83, 0xed, 0x88, 0x5c, 0x87, 0xfa, 0x82, 0x6f, 0xda, 0x57, 0x10, 0xb5, 0x4e, 0x16, 0xec, 0x0f, 0x44, 0x8c, 0xdb, 0x7e, 0xe0, 0x58, 0x0f, 0xf7, 0x38, 0x65, 0x30, 0xea, 0x46, 0x1e, 0x04, 0x2a, 0x0b, 0x77, 0x42, 0xc4, 0x61, 0x97, 0x6b, 0xb5, 0xa3, 0x80, 0xad, 0xbc, 0xb0, 0x01, 0x06, 0xf2, 0x67, 0x1b, 0x6c, 0xce, 0x4f, 0x72, 0x67, 0x75, 0x2f, 0x80, 0x66, 0x80, 0x42, 0x78, 0x35, 0x0b, 0x01, 0x75, 0x3e, 0x31, 0xb3, 0x8e, 0xcc, 0xfb, 0xe9, 0x05, 0x69, 0xf6 } +, + /* Encryption */ + 256, + { 0xab, 0x42, 0x67, 0x97, 0x2c, 0x77, 0x96, 0x83, 0x93, 0x88, 0xd4, 0xad, 0x87, 0xde, 0xd7, 0x4b, 0xb6, 0x53, 0xe9, 0xa7, 0x05, 0x0e, 0x28, 0x2e, 0x82, 0x19, 0x28, 0x75, 0x68, 0x9f, 0x70, 0xee, 0x1d, 0xa1, 0x8a, 0x1f, 0x73, 0x22, 0x09, 0x2c, 0xd2, 0x9f, 0xd0, 0x01, 0x19, 0x92, 0x2a, 0x6d, 0xe1, 0x26, 0x01, 0x98, 0x0a, 0xa9, 0xfa, 0x6e, 0x61, 0x9e, 0x27, 0x75, 0xe8, 0x7a, 0xda, 0xe3, 0x16, 0x95, 0xc1, 0x30, 0x4e, 0x77, 0xf5, 0x2c, 0xce, 0x01, 0x66, 0x65, 0xf2, 0x26, 0x7c, 0x20, 0x76, 0x26, 0x43, 0xc6, 0x00, 0x3c, 0x01, 0x6d, 0x84, 0x80, 0x44, 0x3c, 0x70, 0x1d, 0xf6, 0xc1, 0xd8, 0xd6, 0x55, 0x54, 0x96, 0x00, 0xee, 0x45, 0x5b, 0x70, 0xe4, 0x73, 0x31, 0x9b, 0x0d, 0x44, 0x45, 0xe0, 0xb7, 0x55, 0x2a, 0x1f, 0x80, 0x8e, 0x88, 0xf3, 0x26, 0x48, 0x42, 0x73, 0x5a, 0xe6, 0x1d, 0xf0, 0x32, 0x5e, 0xd0, 0x36, 0x90, 0xd6, 0xd5, 0xd6, 0x93, 0xad, 0x1f, 0xed, 0x22, 0x66, 0x84, 0x50, 0x37, 0x9d, 0xb5, 0x32, 0x3d, 0xc0, 0x1c, 0x89, 0xaf, 0xfa, 0xe3, 0x69, 0xb9, 0xc3, 0x01, 0xc3, 0x19, 0xc3, 0x7d, 0xdf, 0x51, 0xed, 0xf4, 0x6e, 0x09, 0xb2, 0x1e, 0x5d, 0xe9, 0x14, 0x83, 0xe8, 0xe3, 0xcb, 0x21, 0xee, 0xb7, 0x05, 0x7b, 0xc2, 0xeb, 0xdc, 0x3a, 0xaa, 0x3d, 0x65, 0x00, 0xc9, 0x2f, 0x99, 0xb1, 0x7b, 0x31, 0x80, 0xbb, 0xa0, 0x47, 0xd7, 0x60, 0x73, 0x77, 0x63, 0x36, 0xb1, 0x5d, 0x05, 0x4d, 0x79, 0xa4, 0x40, 0xcc, 0x5e, 0x98, 0x5e, 0xa5, 0x43, 0xfc, 0xaa, 0x25, 0xdb, 0x1d, 0xd8, 0x92, 0xb7, 0x1b, 0xb7, 0x4a, 0x5c, 0xf6, 0x82, 0x63, 0xd8, 0xfd, 0x58, 0xf1, 0xa4, 0x8e, 0x6c, 0x2f, 0xcb, 0x8c, 0x0b, 0x71, 0xa2, 0x51, 0xcf, 0xc1, 0xa2, 0x01, 0x57 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +}; + diff --git a/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.txt b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.txt new file mode 100644 index 0000000..cec22a2 --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15crypt-vectors.txt @@ -0,0 +1,9709 @@ +Test vectors for RSA PKCS#1 v1.5 Encryption +=========================================== + +This file contains test vectors for the PKCS#1 v1.5 +encryption scheme. 15 RSA keys of different sizes have +been generated. For each key, 20 random messages of length +between 1 and 64 octets have been PKCS#1 v1.5 encrypted. +As specified in PKCS#1, the block type for this operation is 2. +The seed value of each example provides the pseudo random bytes +to be used for padding. This makes the result predictable. +Note that each example can be used to test encryption and +decryption. + +Key lengths: + +Key 1: 1024 bits +Key 2: 1024 bits +Key 3: 1024 bits +Key 4: 1024 bits +Key 5: 1024 bits +Key 6: 1024 bits +Key 7: 1025 bits +Key 8: 1026 bits +Key 9: 1027 bits +Key 10: 1028 bits +Key 11: 1029 bits +Key 12: 1030 bits +Key 13: 1031 bits +Key 14: 1536 bits +Key 15: 2048 bits + +These test vectors have been derived from the OAEP test vectors. +============================================================================ +# Thirteen RSA keys with bit sizes between 1024 and 1031, one 1536-bit key, +# and one 2048-bit key are generated. + +# For each key, 20 random messages are PKCS#1 v1.5 encrypted with random seeds. + +# Example 1: A 1024-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 +91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab +c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 +12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 +f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 +c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 +8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 +76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4 +91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab +c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85 +12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72 +f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97 +c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14 +8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24 +76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb + +# Public exponent: +01 00 01 + +# Exponent: +53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c +55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd +8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b +15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55 +fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73 +2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf +b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de +f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1 + +# Prime 1: +d3 27 37 e7 26 7f fe 13 41 b2 d5 c0 d1 50 a8 1b +58 6f b3 13 2b ed 2f 8d 52 62 86 4a 9c b9 f3 0a +f3 8b e4 48 59 8d 41 3a 17 2e fb 80 2c 21 ac f1 +c1 1c 52 0c 2f 26 a4 71 dc ad 21 2e ac 7c a3 9d + +# Prime 2: +cc 88 53 d1 d5 4d a6 30 fa c0 04 f4 71 f2 81 c7 +b8 98 2d 82 24 a4 90 ed be b3 3d 3e 3d 5c c9 3c +47 65 70 3d 1d d7 91 64 2f 1f 11 6a 0d d8 52 be +24 19 b2 af 72 bf e9 a0 30 e8 60 b0 28 8b 5d 77 + +# Prime exponent 1: +0e 12 bf 17 18 e9 ce f5 59 9b a1 c3 88 2f e8 04 +6a 90 87 4e ef ce 8f 2c cc 20 e4 f2 74 1f b0 a3 +3a 38 48 ae c9 c9 30 5f be cb d2 d7 68 19 96 7d +46 71 ac c6 43 1e 40 37 96 8d b3 78 78 e6 95 c1 + +# Prime exponent 2: +95 29 7b 0f 95 a2 fa 67 d0 07 07 d6 09 df d4 fc +05 c8 9d af c2 ef 6d 6e a5 5b ec 77 1e a3 33 73 +4d 92 51 e7 90 82 ec da 86 6e fe f1 3c 45 9e 1a +63 13 86 b7 e3 54 c8 99 f5 f1 12 ca 85 d7 15 83 + +# Coefficient: +4f 45 6c 50 24 93 bd c0 ed 2a b7 56 a3 a6 ed 4d +67 35 2a 69 7d 42 16 e9 32 12 b1 27 a6 3d 54 11 +ce 6f a9 8d 5d be fd 73 26 3e 37 28 14 27 43 81 +81 66 ed 7d d6 36 87 dd 2a 8c a1 d2 f4 fb d8 e1 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 1.1 +# ---------------------------------- + +# Message: +66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23 +97 d5 0d ba 79 b9 87 00 4a fe fe 34 + +# Seed: +01 73 41 ae 38 75 d5 f8 71 01 f8 cc 4f a9 b9 bc +15 6b b0 46 28 fc cd b2 f4 f1 1e 90 5b d3 a1 55 +d3 76 f5 93 bd 73 04 21 08 74 eb a0 8a 5e 22 bc +cc b4 c9 d3 88 2a 93 a5 4d b0 22 f5 03 d1 63 38 +b6 b7 ce 16 dc 7f 4b bf 9a 96 b5 97 72 d6 60 6e +97 47 c7 64 9b f9 e0 83 db 98 18 84 a9 54 ab 3c +6f + +# Encryption: +50 b4 c1 41 36 bd 19 8c 2f 3c 3e d2 43 fc e0 36 +e1 68 d5 65 17 98 4a 26 3c d6 64 92 b8 08 04 f1 +69 d2 10 f2 b9 bd fb 48 b1 2f 9e a0 50 09 c7 7d +a2 57 cc 60 0c ce fe 3a 62 83 78 9d 8e a0 e6 07 +ac 58 e2 69 0e c4 eb c1 01 46 e8 cb aa 5e d4 d5 +cc e6 fe 7b 0f f9 ef c1 ea bb 56 4d bf 49 82 85 +f4 49 ee 61 dd 7b 42 ee 5b 58 92 cb 90 60 1f 30 +cd a0 7b f2 64 89 31 0b cd 23 b5 28 ce ab 3c 31 + +# PKCS#1 v1.5 Encryption Example 1.2 +# ---------------------------------- + +# Message: +75 0c 40 47 f5 47 e8 e4 14 11 85 65 23 29 8a c9 +ba e2 45 ef af 13 97 fb e5 6f 9d d5 + +# Seed: +ac 47 28 a8 42 8c 1e 52 24 71 a8 df 73 5a 8e 92 +92 af 0d 55 bc b7 3a 12 ac 32 c2 64 f3 88 1c 7c +8a 71 0f 70 fe b1 04 85 c8 37 0f 78 1f ff d0 21 +81 6f 05 87 39 76 6d a0 a9 c9 db 0e ae 7e 9a 25 +b6 c4 33 18 d0 ca ac 23 65 22 ca 31 0f 17 fc 52 +ad 42 29 c8 3a 24 e9 e5 45 eb 35 e9 82 6d 55 9f +57 + +# Encryption: +68 42 e5 e2 cc 00 41 d6 b0 c8 1a 56 2c 39 a6 17 +37 9a 51 5c ab 74 ab cb 26 19 c7 74 0a 54 1d 95 +55 dd 91 65 97 5b f8 a3 eb d0 d0 45 66 61 df b1 +a6 86 1b a2 33 22 69 93 0e 0d b5 14 fc a0 73 3e +eb 9c 40 57 13 eb 1f 9d 76 80 33 ed 29 3e 1e 08 +1a 12 5f 32 dd b9 ea 52 ed be 27 5c 4a f6 0f 8a +7b f8 32 bd 22 75 61 c2 08 dc 00 31 a8 4b 50 12 +c9 dd 9f 74 45 9d cb 07 0b db e1 3c fa 8c 2d 50 + +# PKCS#1 v1.5 Encryption Example 1.3 +# ---------------------------------- + +# Message: +d9 4a e0 83 2e 64 45 ce 42 33 1c b0 6d 53 1a 82 +b1 db 4b aa d3 0f 74 6d c9 16 df 24 d4 e3 c2 45 +1f ff 59 a6 42 3e b0 e1 d0 2d 4f e6 46 cf 69 9d +fd 81 8c 6e 97 b0 51 + +# Seed: +dd 2d 60 a5 e0 08 eb e1 d0 be 6f 60 db c4 3f 29 +62 ef 50 bf de 54 2b bb e9 8f ed d1 fe ac 05 7e +77 1c f1 5f c6 32 c8 db 27 2e 28 d2 9b 57 93 ea +6a b8 06 21 8c 53 82 39 b9 3a 93 5e 65 d2 44 16 +ec 6c 6e 99 ae 04 + +# Encryption: +70 9c 7d 2d 45 98 c9 60 65 b6 58 8d a2 f8 9f a8 +7f 06 2d 72 41 ef 65 95 89 8f 63 7a da 57 ea e9 +01 73 f0 fb 4b f6 a9 1e bd 96 50 69 07 c8 53 da +cf 20 84 94 be 94 d3 13 a0 41 85 d4 74 a9 07 41 +2e ff c3 e0 24 d0 7e 4d 09 aa 24 5f bc b1 30 21 +9b fa 5d e0 2d 4f 7e 2e c9 e6 2e 8a d3 2d ee 5f +f4 d8 e4 cf ec bc 50 33 a1 c2 c6 1c 52 33 ae 16 +19 2a 48 1d 00 75 bf c7 ce 02 82 12 cd 27 be be + +# PKCS#1 v1.5 Encryption Example 1.4 +# ---------------------------------- + +# Message: +52 e6 50 d9 8e 7f 2a 04 8b 4f 86 85 21 53 b9 7e +01 dd 31 6f 34 6a 19 f6 7a 85 + +# Seed: +26 29 a7 aa c0 c3 90 5e 83 1e b6 02 38 8c 54 5a +f5 54 b9 6b 2a e5 15 32 e9 cc db 89 72 ef 30 b6 +4a 2f 98 c6 95 29 7a 01 c5 81 2a 2c 40 15 82 f3 +7b 14 4a 3e 90 e5 9d 81 b6 90 39 c6 4b 84 4b 02 +8c 10 5c 8e 68 36 15 af b6 58 b6 c4 d9 f3 82 38 +a7 63 01 bb 14 44 91 13 b6 9d e1 26 04 5e 26 f1 +3e e6 d7 + +# Encryption: +54 dd b7 84 26 8e ad b3 95 5b d9 f9 49 88 42 59 +5a d2 9f f8 a6 67 fe b4 1f 6f 53 0c b6 0b c9 26 +ac 6c 71 c7 72 f8 03 d0 22 b4 1c a5 72 04 22 3b +27 ca 79 ec 5b 72 65 2c a9 af bf 40 dc 2f 6a 0e +13 bc d6 0d 37 f7 95 04 b0 ff cc 01 cf 53 42 d6 +d3 4a c6 f1 f2 f9 f2 f4 87 46 25 b9 fd bb 7d da +2e c8 7d f0 cf 87 25 97 98 df 86 a0 6b d5 ae f7 +35 4b 8c b1 cb 13 75 75 f4 cf bc 46 28 1b b3 31 + +# PKCS#1 v1.5 Encryption Example 1.5 +# ---------------------------------- + +# Message: +8d a8 9f d9 e5 f9 74 a2 9f ef fb 46 2b 49 18 0f +6c f9 e8 02 + +# Seed: +c3 ca 84 60 0f 35 c8 65 5f c7 c6 4c 75 c5 87 38 +53 d3 aa 8a 94 26 a5 1b 63 d7 e7 5d cf 6c ae 97 +a4 25 3f ba 87 1d 6f 96 89 97 19 9b f0 1b 6a 4d +34 28 ce 4c 96 d1 c4 87 b2 83 0c b9 e3 5d 64 05 +56 23 69 9a b4 97 9a 02 58 4b 92 e6 ba 39 e7 57 +28 40 79 ab f1 33 a7 da 54 e5 42 52 17 a2 10 f6 +7c 18 26 9b 51 1f 61 f8 c5 + +# Encryption: +a8 55 48 01 3b d0 e2 0e e0 eb d3 6f b7 48 97 7f +98 58 46 d7 61 0e ed 24 c3 6c d8 30 33 dd 2a a4 +58 0b d1 53 35 20 9d cf 78 2e e2 6c 48 c3 06 44 +b0 b5 cc 86 c8 cd 16 5a e2 1e ad f5 78 04 18 67 +76 07 03 18 75 e2 21 ec df 3b 10 57 31 6f 3f 12 +a4 7d 5d a4 0c 41 53 9b 63 64 30 da 2e 54 21 90 +11 9e 42 9c 53 c2 22 6f 95 9b 19 cc f4 8a 3d 24 +02 17 c4 de 70 d7 07 2a 7e 0d 95 b6 16 d1 15 a8 + +# PKCS#1 v1.5 Encryption Example 1.6 +# ---------------------------------- + +# Message: +26 52 10 50 84 42 71 + +# Seed: +3c 6a 04 71 da f0 0b 7c 2e fc 9e e8 80 41 65 4f +87 62 90 07 c1 24 32 22 11 a5 f4 ea 3c 58 23 85 +7b c8 fc 7e 21 c9 45 48 b0 ee bd cf f7 91 60 e1 +12 46 1e 40 50 91 10 cf dc 4f 0f 13 c7 fb 92 1a +ba c8 df aa c2 1a cb 0f 7b 8a 13 a4 b5 cc a5 23 +d5 c7 dd f7 05 23 eb 57 0c 59 b6 c7 ae 97 67 e4 +ec 9a 63 d1 13 6d 10 23 1b 40 1e 20 e7 41 02 84 +83 48 01 7a 16 16 + +# Encryption: +5e 51 43 63 28 7d e9 b3 80 04 8c c4 43 5d 53 29 +4a d5 94 1c 55 1a 97 e1 3c 16 dc 13 98 de 61 0d +c7 33 7b c6 bd e5 78 e9 e9 f5 6a f1 44 54 f2 e8 +31 be ef 32 31 a8 50 68 e8 fe f7 2c 89 e1 df 1c +99 43 0a 60 f6 d9 42 89 cf ba 87 b2 b4 32 a4 0b +88 db 61 da e0 88 f9 ed 4e 28 4a 21 63 af 65 bf +2b 43 55 9a 5d a2 ae c5 bb 8f 43 f9 2c 1b 04 a5 +14 6a 65 b6 e0 19 b4 cd d2 94 0c 35 d9 64 5b 2d + +# PKCS#1 v1.5 Encryption Example 1.7 +# ---------------------------------- + +# Message: +8a 84 7d d9 e2 + +# Seed: +a1 3d ff 8a 48 e8 04 94 ae 66 e6 ba 9f 17 9a 01 +0d 9e 6d 40 31 87 96 7f 99 fd d9 0e f9 0e 0a 94 +07 3f f0 e4 d0 e6 66 4f f3 73 b5 09 95 3e 04 ef +77 83 be 0f b4 6c 8a 9f c0 ed 8c 1f 33 cb 4d 0d +2f 1d 0d 5c db a1 4d ca 50 8c a1 d7 3d 20 80 18 +63 9b c8 e1 65 86 23 de 1e 5b a3 f0 5e d0 91 4d +2f 96 90 2f 25 20 33 2d 84 92 d3 73 4a cd eb bd +f4 3e 50 a4 3e 7a a8 72 + +# Encryption: +82 7a 67 e8 15 78 1c 4d 4e 2b 2e 16 9d 80 ca e9 +36 68 72 a7 92 af bf 3c 0c d5 1c e2 8c 70 e8 6d +41 eb b9 75 2f 3f 92 db a5 1a db b6 85 1b 1f 78 +45 61 a8 f1 97 20 8f de 02 97 0b 38 f2 a9 74 22 +ec 7f 4f c8 a1 06 75 a9 db de 10 9e ed 0c e0 65 +27 70 3e e0 5b 65 7d 34 08 f7 fd db 1e ec cf fa +e1 6b 1d a1 07 30 7a 2c f2 56 fa 60 e8 15 21 72 +de 9f 95 27 fe 92 0a 90 1d 93 c4 f4 d5 7e 54 6e + +# PKCS#1 v1.5 Encryption Example 1.8 +# ---------------------------------- + +# Message: +37 32 36 b7 20 2d 39 b2 ee 30 cf b4 6d b0 95 11 +f6 f3 07 cc 61 cc 21 60 6c 18 a7 5b 8a 62 f8 22 +df 03 1b a0 e0 e8 2d d2 f3 e5 d3 1e 4e a2 57 b1 +5b + +# Seed: +21 99 74 a0 87 f0 a2 81 93 e6 49 a0 4a e9 d8 4c +f2 c8 a9 a4 6c df d8 f1 ac 62 c7 e0 f2 0f 4e 27 +03 0c 72 b2 0a 5d b7 25 b4 a8 68 3d f5 55 6e e7 +94 7f a0 a7 66 1b 6d 99 dc b7 9e 49 4f 46 73 f0 +73 a0 41 dd 90 7c 87 32 4e 86 25 dd + +# Encryption: +1a 6d f5 75 99 84 f2 c4 11 93 55 c5 db 35 c8 a4 +78 16 4d 5e 5e e7 7b 49 91 f1 04 ba 91 b9 87 0f +15 91 be 1f 19 f5 5a 80 51 a6 2c 0e 59 49 3d f6 +f0 0f e5 0e f7 3a 6c f0 c4 35 41 f5 32 0d ab 7b +2f c6 7c 93 22 5c cc d6 d5 03 47 aa 96 9a d8 7b +d3 d8 20 81 45 4f ea d8 10 dc 1a b8 c2 17 81 f7 +61 2e 64 06 72 9b 32 2e 04 b1 62 4f 85 38 98 56 +59 ae 34 d9 93 1e 01 9f 76 2c 79 7d 5c bf a3 2d + +# PKCS#1 v1.5 Encryption Example 1.9 +# ---------------------------------- + +# Message: +97 e0 b6 36 bf dd b8 e1 c8 a9 cf 5b 30 5c ef 3a +8f 47 f9 a8 b3 34 4f 13 55 fa 3d ba b6 7b b9 72 +10 + +# Seed: +c1 f8 9b cd c5 60 40 d5 e6 63 b7 4b fd e2 39 7b +58 46 08 cd f3 2d 5a 58 44 72 4a c7 e5 98 a8 6e +f7 11 4b 1b e0 87 30 cb 10 f6 61 fb fb 86 09 f7 +c6 c3 74 42 a1 b1 1e 04 a6 11 ff 8c a5 ce 9a fc +1e b3 aa a9 2c 9f 28 ba e2 20 44 05 78 99 02 26 +07 83 78 c4 93 41 13 74 c5 3e 3d dc + +# Encryption: +87 3c c4 dc a4 27 97 2b 63 c6 cc 8a c1 1c cc 33 +c9 59 f7 fc fe 4b 45 bb d4 7b 29 d9 c9 88 c0 1a +96 bc 1e ae 0e f9 b1 94 8d ce 2c c9 f0 aa 91 7e +86 a6 c1 1f 8d a3 da 29 df 90 59 01 f1 91 8a 76 +16 8d e1 17 5e 27 35 12 8c 09 72 99 d6 6e a5 cc +f9 b9 5b 36 92 ee bf c6 ea 11 bc 37 09 1b 79 5f +18 80 3d 70 e7 95 58 e1 25 16 23 0f ed 55 15 e5 +1b 45 ae 86 ce fe 47 b9 37 90 e4 99 4d c4 1e 05 + +# PKCS#1 v1.5 Encryption Example 1.10 +# ---------------------------------- + +# Message: +82 b5 07 5b fc 88 f4 00 65 76 aa 80 a0 00 7a 74 +51 18 4d 4f 76 0c f9 24 28 04 22 2b 0e 07 26 f5 +55 03 0e 4e 6b 01 f7 93 b0 97 01 81 27 82 4a 3e +40 24 57 d8 49 5f c0 + +# Seed: +d5 5e 3d 48 97 e9 d8 65 01 4c b1 5d 3e e3 f9 fb +d2 9c 92 e5 c2 37 dc ae 46 67 2a 46 3e aa a4 f7 +dd 09 86 1e 94 6a c6 5b 85 62 50 63 93 b8 51 92 +ad 41 fb 0c 48 c8 c0 52 98 1b dd cd 5f 1f c8 b1 +39 cd 47 ca cf fc + +# Encryption: +2e 83 c3 d2 88 01 5a 5f 50 3d 3e 5d e7 d2 ad 91 +06 54 5e f9 7d 63 e4 d0 6a 5a 0d 9d bc 29 f6 ba +fb 93 a5 17 3f a5 06 3a 69 39 db a6 c7 a4 28 c3 +5e 7d be 6a 95 93 fe 5e c4 c1 98 78 89 3f 31 37 +09 c8 76 02 72 6c b3 25 5b e7 5a dc 7f 2f 27 e6 +db 91 c3 a3 43 ea ff 1c 28 d9 d5 f7 cb 65 74 e6 +31 06 90 03 cd cf a0 77 43 a7 34 0d 58 83 9e 70 +8b f3 6a f6 34 2d b8 df a4 1f ea da fc 69 53 ac + +# PKCS#1 v1.5 Encryption Example 1.11 +# ---------------------------------- + +# Message: +36 48 c3 6f 85 1f 52 f2 32 87 79 09 19 85 a3 c8 +12 e1 8a 70 55 d0 90 bb f0 32 4c 13 79 3b b8 22 +1a 57 + +# Seed: +c1 27 71 85 c3 59 55 ca ed fd f9 de 55 d5 d9 5a +39 8d 58 f5 f3 33 19 1f c0 29 45 ef df ad fb 6d +b0 5e e2 a2 d3 41 83 ed f8 9a 1a 4d cc c4 65 91 +b3 53 2b a7 03 93 62 c7 5d f1 94 ec 10 64 48 af +b7 f6 bf b2 80 7e 38 3e 15 99 54 25 5e 82 7c b9 +da dc 8d 9b 7e 68 a1 aa 09 76 35 + +# Encryption: +88 62 f1 97 3f ef e0 af 02 d9 6c c4 58 33 4d ed +6c 02 d8 d7 ea f5 93 77 9c 5d 38 6c 4e 49 f7 68 +f1 30 b4 87 b3 c9 1e 32 3a 47 7e 4c 11 0a 33 41 +ff 46 ee e3 7c 77 3e 5c 0a c8 39 bc 55 cc 0c 07 +0c ac 01 cd 45 18 3c fe e6 b8 8b fb 82 36 1d 35 +60 19 7c de ab 42 e5 c7 55 d2 37 97 1a 88 da f6 +10 cb 39 52 61 4b 36 40 56 cd 49 14 20 ef fe 3a +0b 8c e3 1f 2e 3e 49 ca d6 f3 b0 64 0f 44 91 de + +# PKCS#1 v1.5 Encryption Example 1.12 +# ---------------------------------- + +# Message: +94 f7 8c f4 5c 53 fc 46 e7 eb 1b 26 61 8a 29 e9 +48 50 12 c1 + +# Seed: +e6 de 9e 9b 90 22 a5 5f 56 12 1d 5a c0 0a a6 df +29 9c 8a 36 94 22 e7 54 29 56 b6 da 2e 0d cd ee +96 8d b0 7d 99 5a 7b b8 76 f7 f8 cd 66 b2 f5 42 +c0 53 08 f7 49 83 a3 f8 36 0c 6b 89 47 f8 7d 60 +8b 03 1a 2c 68 dd e1 47 1a e4 96 ae 9b 16 e2 a8 +11 81 eb 6f c2 f6 5b aa ad da 64 22 a9 34 31 f6 +f3 b0 7b 5b 46 a3 cf 89 48 + +# Encryption: +3c 6d 3b 43 d2 3a db 79 d6 97 23 38 08 b0 74 48 +76 97 f3 35 fd 99 cd e8 65 41 1f b1 82 28 92 56 +1f dc 24 a8 b8 bb 2c 4f 65 3c 4d 15 6c 77 a7 5d +e3 16 00 b5 70 9e 8d 50 6e 98 e1 d3 73 cb da 01 +f4 d9 fe b0 29 71 98 ca d0 ca 2a 7e 3b 1e 63 90 +3b 10 43 ce 79 49 4c 57 54 f7 f9 0f c1 f0 73 a6 +19 92 9e f1 26 39 4b 06 24 f3 b8 ba 6d 56 45 e9 +90 e7 c0 13 2c e2 12 31 46 fd 9c ad f7 45 ec 61 + +# PKCS#1 v1.5 Encryption Example 1.13 +# ---------------------------------- + +# Message: +77 9d 1e b8 4f a2 84 c3 7d 29 d5 e1 79 d0 03 06 +b4 13 c4 4a 80 0a 07 7e 59 85 3f 63 05 f9 2e 59 +fb 7f 81 + +# Seed: +c3 e6 d1 8b da 97 78 2c a7 81 fa 76 d9 7a 6c 94 +d8 54 d1 41 99 b4 ea 7d 82 c5 bc bb e6 cd aa b5 +25 57 47 44 3c 59 bf 8c 77 ec da a6 4a e7 ce 61 +e2 c7 30 01 32 b7 54 e9 16 2f 7c de 75 8f 48 0a +e5 88 cf d4 4a 94 6d 64 e2 72 0a 2d 17 52 55 45 +22 04 84 83 81 18 ad 6e 6b 54 + +# Encryption: +72 2c a9 25 66 c7 3c c8 5d 19 ce 3f aa 14 cb 2e +79 84 9f 20 50 92 d1 58 92 82 31 3c 04 27 f0 67 +79 8a fa e3 e3 f0 a5 61 f3 99 34 6e 9d 10 7d a0 +4a f4 4b 0c 6f 04 4a de fe 09 7a 0c d1 4a 47 a9 +9c d9 81 9a 98 41 37 06 30 7c bd 0d a0 16 97 46 +9e ff 71 d3 14 41 63 94 93 fb ed 8e ee 1b a3 9f +dd 07 fc 0e a0 82 30 18 61 79 f9 0e 7e f1 3c 61 +ee 56 f1 67 fc 2f 6b 15 79 3e 1a 32 24 ff a2 9e + +# PKCS#1 v1.5 Encryption Example 1.14 +# ---------------------------------- + +# Message: +88 + +# Seed: +c0 16 9d 76 e4 ea 45 45 41 0d df 66 46 c1 ba 7d +d2 72 d7 c3 49 8b a6 b0 80 4b 42 61 30 a8 0f bf +ff 4b b7 b5 f5 59 b0 a9 09 0e 4a d9 b9 f4 16 a6 +df dc 15 01 b1 ba 46 87 7b 1a 96 fa 84 91 dc fd +de 50 eb ee d2 4d 3f 98 96 24 13 34 6e d4 a3 39 +3e 23 5b 77 bc 1e d6 74 68 ec e2 79 2a 2f d3 a8 +34 8f c5 50 9b 59 06 f2 88 56 15 df 8c 14 61 37 +7a 74 1d 59 52 fb 36 ea c0 20 1e 27 + +# Encryption: +4e d7 d1 29 1a 03 36 65 4d 5c a2 b1 f9 d2 0c b2 +da 72 26 f7 11 6b 93 09 88 43 9b 44 63 98 11 04 +bd 63 c2 ce 2b 77 d6 26 b3 10 9c 93 14 03 ac 5b +49 b4 24 7c 4f 69 67 b8 c0 db 06 3c 99 95 af 9d +36 54 06 50 93 8b 01 f9 39 06 f9 83 89 07 ed 59 +36 ab b3 43 b0 e2 55 09 a1 d2 d4 c5 c8 b9 58 06 +50 da 2c e1 1f a3 cf 3e 64 07 23 ea cb ee 87 fa +d3 ee 35 95 8b 45 07 5d f7 81 c4 13 46 6a f1 39 + +# PKCS#1 v1.5 Encryption Example 1.15 +# ---------------------------------- + +# Message: +a2 dc 08 77 78 d5 43 40 8e 89 73 f1 36 31 59 ed +b8 f0 78 3c 45 70 89 07 2d ce 66 d3 10 2b b4 fa +e6 0a a6 0e 41 93 3c 48 a1 be 39 53 ec 2f 80 4c +0c c9 6c + +# Seed: +18 11 20 14 06 53 29 d0 4b fb 0c f5 44 dd 38 d7 +be f1 54 9b 4a 49 a1 67 76 dd a7 4d 0a 7e dc 49 +67 b4 24 0c 37 14 2f a3 f6 63 9c 26 96 cd 7d 4b +18 a1 1e 2f b5 40 81 f2 de 5b d7 bd 15 cd da 92 +c9 4c 3a 47 18 7b 5f f4 3b 53 + +# Encryption: +71 15 19 0a 21 04 88 f0 4f a0 c0 0c 93 a4 68 a8 +03 0b 7b 9f c1 00 20 d8 31 0b cb 01 a5 c8 dd a1 +d0 6c e2 41 dc 77 5b 43 e6 f1 3b 19 ab fc bf 36 +16 e8 4f 10 7c 9e d8 0d 1b 86 bf 87 c9 8c 2b 62 +9f fa da a6 ec 01 f4 e6 75 55 8e f5 26 06 ea f1 +26 06 8f a7 53 4d d1 3b 92 0d 23 81 69 5a d7 75 +ff f0 bb 7c ec 46 90 90 1d 6f 1e 17 36 b8 2c fe +3a 0c 22 4d 18 f1 29 15 fd c9 5c 18 39 7c 35 70 + +# PKCS#1 v1.5 Encryption Example 1.16 +# ---------------------------------- + +# Message: +11 0b f2 b1 d0 dd 81 2f 2a 5a 21 f3 40 4f a2 f2 +c4 54 c4 43 2f df a7 0f 1b 0f 23 ec 69 c1 02 37 +73 a7 3a ba + +# Seed: +17 b8 5f 76 53 ff 0e f5 de 7f 25 69 6c d4 90 23 +ad 8e ac 94 8a 83 e2 24 58 ec d5 d1 0a 43 86 6d +c7 91 55 5e 64 f0 78 c3 8c 75 2b 6e 9c 6e ee b3 +39 ee c9 10 16 d2 58 88 6d 01 27 75 ad 64 36 02 +a0 f0 d1 79 34 54 a0 60 94 71 16 22 88 22 39 50 +82 6e d8 e2 02 5d a9 a4 e9 + +# Encryption: +5d 0f 2f d8 5e 6f 9d 9e 43 2f ad 86 0f dc 49 96 +96 24 ff 4f a0 71 5d 36 1e 9f 00 b0 5b 3a a0 ba +9e b2 7b ae 61 0e fd e1 14 3c bc 93 3b 52 de a7 +01 87 60 bb 25 1b e0 e1 e3 0c d1 c5 99 1a ef 74 +4d b8 2f 16 6b 90 63 ef b7 e3 38 40 a2 56 90 05 +65 4b 14 0e 11 5f a5 6c 30 40 6e 45 65 6e 81 99 +af 39 4f 63 86 34 6d 5f 1a 30 0b 95 ba 48 fc 08 +73 d6 18 d6 92 bb 02 5b f1 5e 9d 23 2c 64 1a da + +# PKCS#1 v1.5 Encryption Example 1.17 +# ---------------------------------- + +# Message: +d9 d9 37 13 1f f1 94 0a 86 bf 71 39 b4 81 14 36 +41 95 b4 00 52 22 a8 bb bc 26 1a 7f 2e 21 2b 8d +d0 35 e5 3f 91 44 f5 61 0b 4c ec 32 ea 01 bd a9 +d3 c8 0c f2 94 64 f8 0f 5f 56 56 c8 + +# Seed: +33 05 e1 da 60 e5 86 73 fc 46 cd 33 be 2a 66 d3 +a1 02 c3 db 16 1e f4 8c 0d 60 ef 25 03 1b 40 14 +16 78 26 24 6a a5 28 a3 a3 e5 b0 ab 95 07 8d 84 +01 d9 29 03 59 5a fc 1a a8 54 e6 04 4e 5e b5 f5 +be + +# Encryption: +0e 12 16 74 89 f0 ba ef ca d6 39 34 bc 15 9f 1b +bd 9e 9b 28 7e 50 0f 49 09 23 c1 6a 85 56 4a 1d +a6 36 59 37 5f 22 af 7b a4 97 98 e1 57 8c f3 15 +fa e3 e9 ed 56 99 c6 91 e3 c1 d0 bb 46 da 49 2d +01 34 9e 93 29 59 3d 43 81 d0 74 a0 a5 31 df 92 +1b 31 31 6f 7e 2b 4f e9 15 34 72 83 24 23 35 f0 +b0 b2 31 92 c7 21 02 f2 c6 36 24 b1 e7 89 65 45 +0e 82 30 d4 87 7e 46 17 b0 3d 44 83 13 98 dd bf + +# PKCS#1 v1.5 Encryption Example 1.18 +# ---------------------------------- + +# Message: +81 b3 4a eb 8a fb 8a 3f + +# Seed: +02 f7 48 34 2d 01 0f b5 6a 6f 69 f2 1f 8c 6a 63 +16 79 c8 c4 b8 f6 fe b5 25 cf 8e 72 fd a8 ef 8d +f6 62 31 28 c0 fe 74 bc 59 0c aa 34 f1 ee d1 ad +2d 61 42 dc c5 bc ae 84 ef 31 37 62 f2 e4 e7 03 +03 d2 09 c8 d9 57 7a 7c 84 3d 2b 91 72 ed 4e fe +2a d6 29 61 4b 99 a9 1a 4c c8 32 5b a3 24 11 6e +cf 0c 5e 29 09 49 38 ae 49 89 84 f4 f4 cb b1 62 +38 86 e0 39 73 + +# Encryption: +43 b2 76 c7 d3 68 ea 21 c6 80 71 16 cd e8 60 82 +98 f2 40 02 07 2d 77 6e 56 e6 2c 35 72 bf b9 9d +a4 c5 6e 93 8a 47 dc 07 5f a1 ff 7a 61 8f b5 fa +ed 3e e3 7b 91 df c3 91 53 49 5a eb a9 df 6d 45 +df 94 b0 e8 a8 ad 2d b3 7a 9f e4 6d 0f df 15 42 +31 fd 6f 32 21 47 4e 8f 5c 19 1f db 85 38 e1 a6 +03 e5 98 97 e1 50 fa f9 5b 65 da 14 06 67 ed b1 +98 09 eb 4a 16 ac d0 1e cc 60 4b da 57 f2 0e f2 + +# PKCS#1 v1.5 Encryption Example 1.19 +# ---------------------------------- + +# Message: +7b f9 fa d8 89 de 73 ed 87 3d + +# Seed: +fa 5d ad 45 a4 bb 5e 74 c4 cf 2e 21 3e d4 0a a9 +61 75 98 d1 1d 49 ae 1c 32 d7 94 e0 9c d0 e5 c7 +aa ae 81 b9 55 4d de 31 08 d6 0a 9a 82 f4 2c c6 +c2 a6 89 f4 60 ff 1d 53 ad 85 bf 83 83 11 e7 58 +9e 19 67 95 7b 51 56 7a a0 d3 3a fa 37 52 cd e6 +c5 66 1d 4f 27 ae d3 df 52 90 5f 1c f2 25 33 04 +61 8e 07 86 04 1e 70 b4 dc ba c8 c1 08 ba 34 ac +39 39 f4 + +# Encryption: +61 c2 55 0e 0b 36 a6 79 7f f8 64 93 80 1b 11 46 +d8 90 59 49 83 52 e4 c2 62 27 5b 14 04 b1 33 15 +e9 56 bb 3d 31 21 85 b5 21 b3 c7 08 e9 d9 54 02 +17 19 a0 59 d9 84 72 4c 53 c0 4f 5a d2 74 be f9 +ff 0a 79 50 b2 fd ec c5 29 0c d5 f3 bc 26 52 4c +d1 34 20 48 18 4b 0e 2c df 94 06 a4 53 a2 ef 9f +3b b2 3c 4e 7c 1c 8b 29 52 a0 20 2b cc 23 82 47 +ea 32 7b 8c 07 00 c8 00 3f d6 34 ec 1e d9 bf 30 + +# PKCS#1 v1.5 Encryption Example 1.20 +# ---------------------------------- + +# Message: +b6 a3 50 9b b3 b9 b0 b5 7c d5 8d e4 09 d9 53 20 +1a 04 2f 94 92 dc 1d 7e 34 a7 d0 94 1a 1a 1b + +# Seed: +3a 9e 15 06 57 86 b3 e0 1d 82 6b 86 2a 8f 70 2b +5c ac 8c 16 62 ee 7d 15 ff 32 3c df e7 1e bf 4a +d1 b1 f3 a6 bc bd d4 b0 01 08 77 ec ac 09 1f 61 +59 08 e2 be 40 0b b0 c4 98 e3 55 d5 71 fd 10 89 +5b 8e e9 c3 a9 c3 1e 4b 11 03 89 c3 d5 c4 6e bf +76 b3 b3 5a d1 f4 79 1b 6d 20 97 f1 09 f2 + +# Encryption: +6b 4b 6d 7b ab fe 4d 64 17 ac ad fb 78 57 2e 7c +87 e3 fe 1b d5 8e ef b0 d4 b1 27 9c 7b 7c 83 26 +a6 8b b2 87 95 e0 9f 9b 1c e2 e2 4a 53 9f 4b 0d +93 b2 92 74 ce cf 7c d9 f0 b7 32 ae be da 91 11 +bd fe 25 e2 68 a8 8e 34 22 e2 9b 52 bd 4b 7a 05 +47 db 8f e1 2a 6f cf 1a 3c 06 a0 02 bf 87 0a 2f +ab b7 c4 57 e4 bb ce 3e 31 6f 72 32 44 9f 87 a9 +d7 02 b1 2d 19 bd e7 f9 59 0f 94 67 b0 6b d5 8a + +# ============================================= + +# Example 2: A 1024-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +98 b7 05 82 ca 80 8f d1 d3 50 95 62 a0 ef 30 5a +f6 d9 87 54 43 b3 5b df 24 d5 36 35 3e 3f 12 28 +dc d1 2a 78 56 83 56 c6 ff 32 3a bf 72 ac 1c db +fe 71 2f b4 9f e5 94 a5 a2 17 5d 48 b6 73 25 38 +d8 df 37 cb 97 0b e4 a5 b5 62 c3 f2 98 db 9d df +75 60 78 77 91 8c ce d1 d0 d1 f3 77 33 8c 0d 3d +32 07 79 7e 86 2c 65 d1 14 39 e5 88 17 75 27 a7 +de d9 19 71 ad cf 91 e2 e8 34 e3 7f 05 a7 36 55 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +98 b7 05 82 ca 80 8f d1 d3 50 95 62 a0 ef 30 5a +f6 d9 87 54 43 b3 5b df 24 d5 36 35 3e 3f 12 28 +dc d1 2a 78 56 83 56 c6 ff 32 3a bf 72 ac 1c db +fe 71 2f b4 9f e5 94 a5 a2 17 5d 48 b6 73 25 38 +d8 df 37 cb 97 0b e4 a5 b5 62 c3 f2 98 db 9d df +75 60 78 77 91 8c ce d1 d0 d1 f3 77 33 8c 0d 3d +32 07 79 7e 86 2c 65 d1 14 39 e5 88 17 75 27 a7 +de d9 19 71 ad cf 91 e2 e8 34 e3 7f 05 a7 36 55 + +# Public exponent: +01 00 01 + +# Exponent: +06 14 a7 86 05 2d 28 4c d9 06 a8 e4 13 f7 62 2c +05 0f 35 49 c0 26 58 9e a2 77 50 e0 be d9 41 0e +5a 78 83 a1 e6 03 f5 c5 17 ad 36 d4 9f aa c5 bd +66 bc b8 03 0f a8 d3 09 e3 51 dd d7 82 d8 43 df +97 56 80 ae 73 ee a9 aa b2 89 b7 57 20 5d ad b8 +fd fb 98 9e c8 db 8e 70 95 f5 1f 24 52 9f 56 37 +aa 66 93 31 e2 56 9f 8b 85 4a be ce c9 9a a2 64 +c3 da 7c c6 86 6f 0c 0e 1f b8 46 98 48 58 1c 73 + +# Prime 1: +cb 61 a8 8c 8c 30 5a d9 a8 fb ec 2b a4 c8 6c cc +c2 02 80 24 aa 16 90 c2 9b c8 26 4d 2f eb e8 7e +4f 86 e9 12 ef 0f 5c 18 53 d7 1c bc 9b 14 ba ed +3c 37 ce f6 c7 a3 59 8b 6f be 06 48 10 90 5b 57 + +# Prime 2: +c0 39 9f 0b 93 80 fa ba 38 ff 80 d2 ff f6 ed e7 +9c fd ab f6 58 97 20 77 a5 e2 b2 95 69 3e a5 10 +72 26 8b 91 74 6e ea 9b e0 4a d6 61 00 eb ed 73 +3d b4 cd 01 47 a1 8d 6d e8 c0 cd 8f bf 24 9c 33 + +# Prime exponent 1: +94 4c 3a 65 79 57 4c f7 87 33 62 ab 14 35 9c b7 +d5 03 93 c2 a8 4f 59 f0 bd 3c bd 48 ed 17 7c 68 +95 be 8e b6 e2 9f f5 8c 3b 9e 0f f3 2a b5 7b f3 +be 44 07 62 84 81 84 aa 9a a9 19 d5 74 56 7e 73 + +# Prime exponent 2: +45 eb ef d5 87 27 30 8c d2 b4 e6 08 5a 81 58 d2 +9a 41 8f ee c1 14 e0 03 85 bc eb 96 fb bc 84 d0 +71 a5 61 b9 5c 30 08 79 00 e2 58 0e db 05 f6 ce +a7 90 7f cd ca 5f 92 91 7b 4b be ba 5e 1e 14 0f + +# Coefficient: +c5 24 68 c8 fd 15 e5 da 2f 6c 8e ba 4e 97 ba eb +e9 95 b6 7a 1a 7a d7 19 dd 9f ff 36 6b 18 4d 5a +b4 55 07 59 09 29 20 44 ec b3 45 cf 2c dd 26 22 +8e 21 f8 51 83 25 5f 4a 9e 69 f4 c7 15 2e bb 0f + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 2.1 +# ---------------------------------- + +# Message: +e9 a7 71 e0 a6 5f 28 70 8e 83 d5 e6 cc 89 8a 41 +d7 + +# Seed: +16 8e 3e b5 80 9b 08 70 e1 f2 48 7e 1b e7 7a 17 +6b 34 71 6d e1 41 ba 4c 90 59 da 90 e5 e5 1a 36 +94 e8 58 fe d1 0b 92 6c 02 52 39 80 a8 90 9d a9 +96 c6 43 33 ea 67 67 87 bc e6 77 f1 1f da 77 db +b1 a9 51 6e dd a9 b1 29 4f c2 e4 50 52 22 88 e9 +30 be 7f a7 29 b2 50 e3 aa c5 20 51 1e 95 16 aa +86 3a f6 bc 07 5c bd bf f4 30 46 70 + +# Encryption: +71 c2 b8 fb 38 19 f1 34 c2 24 7c 6b ab b4 cf be +17 d7 b2 64 3f 87 ac e5 c5 71 27 7b e1 90 8e f3 +a5 28 8e 34 38 4e 46 0a 70 38 6e 7e a1 d1 9d 3d +ca 1c e1 5b a9 32 39 a8 cd da 18 e3 17 fe 07 96 +80 ce 7e 6a c6 d9 bd af 86 cb 9a eb f1 cf 46 cd +10 ef 6a 68 8b 0c b2 ce 76 5d d0 b3 25 20 42 39 +66 ee e1 aa 05 c6 c2 8c 6f 35 24 fb 68 6b 5f b1 +58 53 65 9e 58 3a c4 37 21 9d ef 8e dc 58 be 2d + +# PKCS#1 v1.5 Encryption Example 2.2 +# ---------------------------------- + +# Message: +66 4b f0 5d 61 2b af 61 52 4c 60 8e da 36 fc 6e +a2 c9 3c 14 31 53 22 1b cf d6 ba 0c fb bd 6b 64 +14 47 e4 78 8b 0a 46 2c b5 b3 f9 fa fc 9a 75 + +# Seed: +e7 f0 a2 79 18 ca d9 15 da 28 11 36 59 ff b5 df +a0 b5 1b 24 d5 a7 1c 20 27 f8 e4 d9 40 9e 8c 64 +72 f0 c5 4b 5c 08 85 8d a6 3d 4b 81 72 b0 7d cf +8c 5a 7e 8f 9e 90 f0 17 c2 4b 44 d1 6b 67 0b dc +96 03 0c 83 53 a2 83 9b a4 c0 75 d2 4c 20 + +# Encryption: +06 86 90 18 13 db 05 3a c7 08 e3 fc ec 6b ae 03 +60 08 8f d3 44 e9 d7 ea 11 8b b3 f5 37 53 14 25 +1e 60 67 37 f5 82 4b 36 28 f6 65 03 48 f6 ab 55 +3b 27 7d a0 15 44 d0 56 73 ba ed f4 55 cc 03 32 +f6 13 f6 54 78 fc fe 06 67 34 c4 65 58 bc 23 3b +4b 6f 52 41 e4 f4 ac 53 fc 18 c5 53 84 c8 fd 96 +18 3f 0b b5 51 5e 89 31 14 f9 c6 1c cc 11 fc 19 +83 de 74 46 92 64 db db b0 c7 49 17 4e cd fb e3 + +# PKCS#1 v1.5 Encryption Example 2.3 +# ---------------------------------- + +# Message: +5e 76 e6 6e d5 75 41 fc 23 d3 59 f4 ad bf 3f 56 +82 01 d3 c6 f0 e0 26 aa a5 67 63 56 cc 98 66 f1 +75 5d e9 8c b3 9f 23 6d af a9 e6 bc 79 4b 74 43 +b5 3a 2d 85 + +# Seed: +5c 65 68 b6 e3 3b c1 3a d2 dc d6 01 2d 17 da 81 +b1 3d bd 62 aa e4 0a 64 af 97 e2 19 e7 5d c1 81 +12 60 77 d1 20 dd a1 9d 63 12 cf 1e 98 71 c1 15 +f0 86 7f e6 62 d7 8a 40 31 97 6b dd ef 68 f5 2b +68 99 58 67 cd 80 95 05 dd + +# Encryption: +19 e7 99 66 ff 1f bc 10 07 3d e7 3d f3 a5 31 63 +78 74 e4 7d f6 39 25 6c 51 d0 bb a9 35 61 0b 46 +34 f9 e5 b4 68 9b d9 21 73 5b 32 23 6e fc c6 e7 +cc 49 a9 e0 6a 25 ac 96 59 b7 fe 82 9c b3 e8 b0 +1f 10 31 79 42 23 65 74 1b 76 c8 34 21 49 ce dc +76 eb 0a d0 18 ed 42 35 fb d5 24 fd 87 c9 54 9a +b3 3f f2 3e e4 f8 20 0e fa 33 02 7e 9d ee c6 0f +ac 01 3d 1e 56 e6 e3 33 d4 93 a4 a9 46 0f e5 8a + +# PKCS#1 v1.5 Encryption Example 2.4 +# ---------------------------------- + +# Message: +5b 19 50 48 eb 90 eb 47 93 + +# Seed: +bb bd 49 55 0e d1 ea 1b 6b c7 20 6c e0 b0 03 a6 +32 a5 2b 0b ac 5f 32 71 0b 39 fa 64 b3 55 6a d6 +f6 c8 2b d9 d5 31 b3 07 46 9e 86 3f 54 b5 fe 21 +83 05 69 54 f2 a9 67 e4 dc 2b 32 6e 41 dd df 74 +3a 76 4f 7e 82 88 68 29 a8 fa b2 77 2a 34 97 70 +6b 95 38 a9 f8 42 96 c8 2d 9b af c2 9c 39 d4 68 +4f 75 ff 6b b1 c1 2e 39 bb 80 56 af 2d 24 34 4b +2c ae 46 29 + +# Encryption: +42 c9 cb 68 21 b5 5d ae 30 d9 00 25 75 31 12 e6 +ee 02 f4 ad 6f 0f 5b 3c c4 95 2a 12 7c 8a 16 f6 +64 79 b8 14 4f 3c f2 9d 84 e4 3d 67 d6 77 12 c7 +f5 b7 6d a2 c6 6b a0 e9 0c d4 b1 fc 1c 1b 3f 17 +a3 92 e7 04 08 28 8a f6 9b 50 fe 8a 50 b3 29 6a +0d ab d7 c8 dc 39 84 a1 94 06 88 be 70 98 25 16 +20 25 6c c2 1b 7c 76 ed 29 d8 6f f7 c0 1e c2 87 +df 47 38 be 34 69 b3 0a 3f 8f b7 be 83 d9 36 1a + +# PKCS#1 v1.5 Encryption Example 2.5 +# ---------------------------------- + +# Message: +66 0b bd 40 06 9c c6 7b ad e4 1a 09 ec f4 3c c4 +51 3f 7c 7c c0 2d de 97 2d 2b 1f 29 29 5e 09 b9 +91 0c 59 ed ba 0e d2 dd f1 1a 6d 41 69 35 1f 97 +24 07 33 52 8f 91 b2 68 fa a7 af 90 6e + +# Seed: +30 7f 61 b1 83 a8 dc f9 15 5a b2 35 e6 1f b5 6b +a2 b8 79 5d c4 23 53 85 e8 ac f3 66 d2 52 33 b4 +70 e0 5d 70 11 b6 fc 53 2f 0a 65 8a d1 3a fd 29 +0c 6f 30 e2 79 5e e3 d3 9d bd c8 0f 56 0e ce 2f + +# Encryption: +04 9b 26 05 0a 3a be f8 3e c2 77 61 11 e3 b7 2f +b9 a2 d6 a8 01 05 5d 6b 5e 0d a4 e9 5c cf 2e bd +0a 78 6a 97 21 aa 79 25 bf 15 be b6 27 13 a3 13 +87 7d d8 5d 26 58 b2 08 e8 8e 64 45 fc 35 01 9b +0c ad 6b f4 d0 6e 2c a5 f1 19 49 ee ee 7e e4 7f +1d 5b 4c 88 24 1f 50 e4 d6 ed f0 18 3d 4f a3 5a +37 1f c4 07 36 4f 2d ca a4 cd ae ce fc ea 6d fa +c1 d5 13 f9 05 e7 47 94 47 44 bb 64 57 6b a1 c8 + +# PKCS#1 v1.5 Encryption Example 2.6 +# ---------------------------------- + +# Message: +81 cb 0a 97 69 8f 82 3b 56 b4 5f + +# Seed: +93 8c 8d fd a0 8b 89 05 5b 68 af 01 1f 24 6c ec +1f 93 a2 77 1d a9 7d ba 20 95 4c 90 09 12 28 5e +5d b1 87 b2 9e 32 72 e9 9e 69 4e 12 14 17 25 28 +45 30 84 06 4e 5c 60 f0 1e 78 6f c5 d0 d9 af 06 +39 a4 98 c5 7a de 93 77 60 ae 51 74 84 af d7 02 +5e a0 d5 5a 62 b1 1f 9a ab 7f a5 dd d0 93 e5 ea +ba d6 1b 67 a2 95 a7 75 be 96 c6 b7 6e c3 fe 47 +29 50 + +# Encryption: +7f b8 f3 35 ee dc 4a f6 af 44 07 3d a1 96 45 7d +04 61 45 03 01 47 f8 42 0f c7 9b d5 89 77 4a 73 +0a 6d 94 fb 7e fa dc 5a ee a7 c0 70 f1 89 24 91 +25 e1 66 c6 d3 01 29 ec f2 c4 82 2a 50 49 6b c2 +f2 1e 79 ac 57 db fb dd 71 a6 8b 58 d9 05 1b 48 +0b f4 77 48 a1 3d fb 67 3e ae d7 71 0a 46 8f e7 +2f 7d 74 e6 f4 a2 89 44 04 3a 52 d9 30 de 68 db +cb 6e e7 fb 8b 69 64 05 41 e3 ed 5b 75 4e 65 fe + +# PKCS#1 v1.5 Encryption Example 2.7 +# ---------------------------------- + +# Message: +05 f7 83 56 23 c8 cf aa e4 82 a9 10 85 b9 7f 6b +95 92 8b b9 74 ac ad 02 36 4a af 13 17 ed 53 c9 +db 2f fb c8 a3 cb 3a 00 f4 4d ac ef 78 + +# Seed: +80 c8 3d 25 47 be 41 ba f2 32 1b d3 0a 9a b7 74 +9c 5e eb b5 a1 ff f0 b3 1d 6b db 0a d1 6d d0 c0 +fb 3e c1 57 e7 8b 09 86 60 20 41 cd e8 89 57 a5 +53 29 e3 e2 cf e8 5a 59 44 74 94 5e fa 33 35 85 +ff fd 41 eb b8 e7 c5 18 c3 c9 25 9a ea 8d e6 35 + +# Encryption: +87 f9 ce 05 f0 ac 9c 05 e4 5f b7 bb 55 5a 7a 18 +a9 cd c5 5f 54 4a 54 21 01 e9 a7 1c d2 03 66 82 +0e 7f f6 dc a3 46 75 22 9d 86 e4 fb 58 71 f9 31 +0b 12 bb 74 e2 86 18 d6 d6 58 65 87 f6 6a cc 89 +68 a8 3c d8 07 f4 d2 12 97 73 1d 7c 22 c1 45 99 +e7 57 19 fd 23 05 2b 8a a6 5b 7e 9c 5c 02 00 38 +2d 35 d5 60 f2 d3 3d d0 49 e0 6a c8 27 cb dd 9a +f5 81 a6 b2 6d b6 1d 43 d7 12 4b 34 72 1d f1 42 + +# PKCS#1 v1.5 Encryption Example 2.8 +# ---------------------------------- + +# Message: +e2 e0 f6 b3 28 d9 bb e9 fd 66 cd 87 98 7c 11 60 +ed 23 7b 1c 7c 65 6a 89 fb 1f 21 d7 09 40 3b 04 +10 f8 e4 e1 2e b9 69 0a eb eb 38 07 31 9a 93 65 +64 f6 67 17 a7 1c 48 62 cc c5 6e + +# Seed: +cf 18 e6 08 b1 56 14 5c 44 de 31 49 66 cb cc 66 +74 a4 5a e0 df 90 04 06 e4 0d 3d fc 32 2f 39 40 +4c ee b6 dc 58 f8 01 bb f2 ac 4f 47 84 1a bd 79 +61 79 d0 82 4f 3b f5 51 8d 78 cc 66 ad 8d fb ed +b1 17 + +# Encryption: +14 01 aa 21 ec 6e ba a7 e3 a9 f7 13 c8 6b 50 8e +37 5f 6c 12 5b 29 62 6e bd 34 9f 64 e2 0f a4 8a +1b 06 84 79 ff f3 30 22 f6 6f 86 e9 7d 9c 5e dd +90 26 e3 18 3c e0 86 41 57 06 59 35 2f 87 a6 18 +91 f3 d8 6a 3d 24 5f 02 45 e3 9d 99 89 2c 67 fa +2b ed 8e 37 54 8d e2 3d ef dd 1e 43 d5 d7 e3 d9 +a3 c2 2c e6 a3 68 d8 4c 5a fa 1c c5 bf 49 b6 8f +e5 c2 5a 32 6b 0e ec 5e 44 c5 e2 ff 5a 35 9d d1 + +# PKCS#1 v1.5 Encryption Example 2.9 +# ---------------------------------- + +# Message: +c6 95 78 ea 03 e2 69 b1 b9 16 33 a7 2f 9f b4 d1 +0c + +# Seed: +e0 a1 a9 ba e3 0a 7a c6 6c ab 3d 86 43 3c 1c a5 +e8 ac 2b 74 e4 83 ca 7f 34 59 77 16 ee 16 18 90 +6c 97 77 2f 28 86 f4 6d 78 31 21 b7 fe 1b 8f a5 +fb ec 09 c0 68 e5 63 5c 89 e6 a0 a9 ac cf 2b 12 +c6 47 06 b6 ae 9a 5a 74 ab b8 3f 64 e1 3a 8c 53 +f9 26 76 04 66 b6 45 e2 8e 9a d6 46 1a e7 b8 9d +5e fc cf 7d 89 14 9a a2 e6 9f 0d 25 + +# Encryption: +78 f8 7d 6b 06 76 1b d7 e7 17 e0 c5 eb 40 e1 fb +80 89 9c 7b e4 01 7c 2e fb 07 59 78 ee 38 d0 f9 +5e 98 03 dc d4 0f ee 97 92 c6 1d 4a 2d 85 da bd +ea 96 ca 29 f3 ca 1e 8b cf 81 76 55 d0 c0 94 74 +d9 80 94 eb 6a 7e f0 33 3d 69 71 c9 38 36 fe 02 +32 f7 18 46 3d c9 54 18 53 46 3b c1 cf 03 67 7e +78 6e e5 2e 72 71 c3 c1 1a c0 05 53 c6 75 27 07 +e0 df 92 80 c4 f2 b7 d1 9f d6 f3 d8 bb cc 7b e6 + +# PKCS#1 v1.5 Encryption Example 2.10 +# ---------------------------------- + +# Message: +76 72 cf c2 7a 41 d5 01 aa 4c 41 ba ab f4 52 5a +7c 45 5f c8 + +# Seed: +4c ee a1 a8 94 64 a5 d2 f8 9e 07 89 53 ca f7 76 +36 58 98 a5 bd 5e 8e 44 8c 65 da 26 ff 98 90 0c +d0 80 61 ef 44 6c 69 b4 8d c4 60 9e d8 65 4a 64 +6d 70 82 62 cb 84 09 ac 27 c4 a4 9a df ed 47 a8 +5a d4 29 ed 75 07 75 78 e4 c2 73 c6 1e 2c 3b 46 +be b4 72 f0 a3 45 a0 5d 61 a7 ea aa d8 a6 3e 0b +3d 49 52 f2 7c 40 81 32 9e + +# Encryption: +25 2b 14 13 3f 1d b2 50 13 29 35 01 e3 56 53 4f +26 af e3 34 68 8e 68 d7 91 83 3a 0d 82 56 05 70 +bb b3 ce 2b 16 d8 b5 f7 f8 9e 7e bc 7c f9 c2 94 +ab 34 16 b7 c2 11 87 70 7f e5 e7 99 2e 72 0f f9 +58 da a4 0f 5a d4 5b c7 47 47 96 39 a5 37 fe 0a +4a 75 fc fb 45 a5 3f 01 73 af c0 f3 cc 91 0b 86 +ae 31 37 62 8d 90 ff 67 5a e1 ae 31 e1 64 05 37 +ea 1a 7c cc fb 73 f8 be 5a ec a0 3b ab 19 3b b0 + +# PKCS#1 v1.5 Encryption Example 2.11 +# ---------------------------------- + +# Message: +a1 6a d8 f2 e0 93 23 42 ed 21 e1 37 77 f4 65 2a +35 50 dd b4 36 8b 5e a7 1c 66 db c3 bb fe b7 db + +# Seed: +55 88 4c 83 0d 4a 80 b7 9f 08 9d a7 4d c2 5a e0 +c4 82 46 21 45 e1 d0 95 23 da 3c 93 44 bb 97 b0 +52 fb dc 15 43 df b5 3c f2 37 82 59 68 7c 7b 1b +35 ca f2 f9 19 99 ed 4a ce 39 af 10 d6 be d0 fa +22 44 4c 12 9d 90 74 1c fc da 90 19 8e 27 82 fb +03 bd cc 7c fa fd 89 db 6f b0 fe d2 24 + +# Encryption: +08 32 6a ff 6d 03 cc 4e 26 10 dd 53 6a f7 f2 1d +76 22 7d 82 7d 52 80 d8 b8 3a b9 eb 30 e0 76 9c +fa 02 b5 c1 35 2b f4 d1 70 ce b6 6f 8b e6 98 78 +4e 1a 6c 20 3f a5 ab 90 07 a6 f7 fc 20 65 20 4b +98 2f a5 61 fb b3 61 af 2b 8e ea 42 ab 3f ec 0e +d0 86 22 e5 f2 89 80 52 75 38 0b 69 34 2a 96 f7 +6a 99 04 87 68 90 d9 2f 24 00 20 32 35 1d 8a 1c +bc 3d 27 b2 46 48 21 bb fb fb b9 a6 78 51 96 10 + +# PKCS#1 v1.5 Encryption Example 2.12 +# ---------------------------------- + +# Message: +4a + +# Seed: +8a a0 ce d1 7f 09 ad ae 61 0a 46 03 0d ad 40 31 +1b f1 46 9c 27 37 41 1e 40 f9 23 96 75 1d d5 66 +37 c9 58 db c5 8a 17 fd bd dd db bf 79 75 18 78 +98 be 1a a6 3c 5e ee 5f 9a 19 02 98 0f 59 51 84 +b9 b5 b4 65 b9 2e 20 f7 ae 8b 5a 5c ee 7f 3b 57 +d9 97 a0 6a 70 2d 23 83 50 a9 26 98 ef 27 5d ff +52 77 bd 2c 99 96 47 40 5a db e4 fb 3f 1b e7 5e +15 9a 4c 43 83 13 b7 fd 8a ca 9d ea + +# Encryption: +4c 4e 5a b6 2d 0c 96 7a b8 29 21 42 9f fe 50 d2 +24 0e 7e 0a 18 75 48 87 55 bb 7f f6 15 a8 c9 9a +bc 37 b2 e4 71 47 a9 27 d7 b9 8c 30 db 24 da 8c +d3 5e 13 d7 b7 14 14 d0 32 bd 0c 3c e3 8b 89 b1 +1b 2c 3f 9d 83 08 16 71 6a 2e 8c cd 8c 79 e9 c7 +49 31 a7 b8 a8 db 13 12 8c e4 0b 21 59 e4 98 da +98 f2 aa 35 2f 23 85 31 06 b6 61 d8 8e d0 6f f6 +6a 56 e7 56 59 72 20 bd 10 15 81 53 ce 5c 02 63 + +# PKCS#1 v1.5 Encryption Example 2.13 +# ---------------------------------- + +# Message: +bf fc 42 08 73 f5 af 5d d2 3b b0 + +# Seed: +dd 31 cc d4 7d 4e 31 02 df 0f c5 9b 1b 84 77 af +3a 78 c2 fa 9c 8e cb 4f 0b 3b de 23 50 04 36 55 +03 64 66 5f 81 c0 35 6a bc 0b 78 e9 73 19 11 14 +02 75 c8 66 f7 5a d0 cb bc 88 ad 6b 5d 4d a5 2d +08 e2 2e e5 39 b5 8e 92 c6 19 63 87 e2 21 a0 87 +39 6c be 57 ec 56 03 f6 16 26 27 98 3e ff 82 de +04 8b dc 1b 5e db b5 d4 ea 84 f5 02 24 bd 88 a9 +05 da + +# Encryption: +0d a2 d6 f7 bc b5 0a 47 2e da 24 60 9d a6 77 28 +e5 3c 98 80 aa 5f b6 fb e6 0d 83 c1 1e 6b b3 cf +db 17 d1 4d bc e8 ec 55 c7 3a b0 14 3e 9b 27 56 +bb 69 68 e5 af 1a ed cf 6a 80 c2 6d 49 0e 47 18 +7e a5 d8 cd 2f ac b8 1c e6 4a 72 3c 40 f0 ba 4c +69 3e 1b 11 43 df 15 a4 20 91 70 9a b4 c7 cd 9d +47 07 9e cd 68 f6 a1 96 44 8a 44 67 9a 04 14 10 +41 8f 11 a1 e1 bc e7 8e 77 26 04 a2 f2 77 81 95 + +# PKCS#1 v1.5 Encryption Example 2.14 +# ---------------------------------- + +# Message: +1a 9b 87 29 21 0a 84 71 fc 5c d7 09 f2 ed d3 24 +01 50 24 4b ec 96 a9 2f f8 07 e3 b3 0d 29 5d 3c +34 5c 04 4f 2e 95 60 37 + +# Seed: +58 78 c9 1b 16 6e 90 c3 4e 6e 66 56 8c 15 1f 4d +44 43 40 b5 f1 d7 30 52 cc 56 33 ea 2e 47 ac ed +7b 17 8a 64 fb 09 a5 ad 08 46 ae e4 11 6d 67 80 +ee 75 eb 20 85 16 68 82 0c de c0 f2 c4 96 e4 c2 +88 d8 27 9c 1c 5d 4e c0 0d 98 0c 27 2e 87 05 18 +48 6d ca ea 85 + +# Encryption: +37 00 ac 36 2c f6 0e 16 39 47 a1 98 d0 0f 3b 3b +26 e0 3e e2 fb 78 2b 42 88 b8 c1 de 76 e9 e8 99 +46 c9 80 7c 56 e0 9c 7b 52 be 00 78 ac f6 92 96 +4a cb 97 d1 fa 5c eb 57 76 a1 d5 56 b4 bc 9d b0 +0b da 25 23 7a 75 1b 7c 22 9b 6b 57 f7 ff 75 1c +12 d1 f2 2a 4f b0 e9 0b 63 d0 42 d9 49 9e 0f 7e +fe ad d3 c5 88 f2 c7 43 a1 2c 56 7c 81 57 8d be +eb fd 37 74 da 34 ad 09 ee be 90 17 89 02 14 b5 + +# PKCS#1 v1.5 Encryption Example 2.15 +# ---------------------------------- + +# Message: +a6 d0 e8 c1 ea 4a b4 ec c8 95 7d 62 28 15 79 67 +5a 64 8d 62 b7 f2 2b 2b 08 d1 31 3f 40 6f 13 7e +99 42 67 35 cd b9 37 2f ec a1 ee 78 46 3f a5 de +9c dd 84 75 6c 68 bd 1d 92 ba 96 5f 50 64 10 b1 + +# Seed: +1c 25 c9 b8 32 16 9a 1f db 6c 14 8e 47 e6 6c 3c +c8 21 41 e6 11 a6 f3 0c c9 0c 50 49 e8 c5 02 b3 +1c ad c7 62 39 b7 bd af 93 fa 97 34 3e 7e e5 51 +bc 52 fd b5 ec 9e 40 0a f0 5d be ac da + +# Encryption: +00 e8 b2 fc 76 df b4 a6 cc 43 64 de 8f 68 3c 3f +cd 0a 9e cf bd 4a 5a 72 24 f4 9a e9 b4 f3 b5 cd +c7 1c bb 8c 66 fd 35 f3 d1 8e ca 98 96 7b d4 00 +5d f7 91 52 41 6f d4 7e 56 2c 55 ed c6 d6 12 12 +28 6e f9 75 bc c8 02 69 25 92 65 39 00 97 3c 72 +e0 1a 69 3b 05 fc 2d 58 56 ea ef 7a c0 8f f5 ec +d5 31 e2 c2 ce 92 77 45 a1 16 5a 51 aa 66 98 a1 +ff cb 87 f8 1e f6 51 0b ca f9 cb 76 1e 9e 1f 0f + +# PKCS#1 v1.5 Encryption Example 2.16 +# ---------------------------------- + +# Message: +f3 40 5b 21 8f 3e c6 03 a9 80 69 00 99 c2 cf 5c +be 0b 2b 05 96 79 c4 6b 7e 48 f6 fd c4 da 40 92 +d8 31 c8 b5 2b 2c c7 9b d2 bb f6 e9 f5 7b 4e 8c +aa 94 b5 81 f9 f2 31 26 1f 0e 2b bb f5 3d bb + +# Seed: +f4 70 7f 58 64 2b 54 cb f8 0a 9b 50 48 a6 ec 0b +d3 5d 09 57 16 db 12 06 0c bf 50 58 5f b9 23 79 +81 05 2f 7b b1 58 3c d8 7b c8 bf b5 5b 73 3e 89 +0e b9 c0 8e f0 e8 80 e9 ba 0d 50 ec 95 41 + +# Encryption: +6d 9d 39 19 8b 5f cb 13 2d 93 15 11 49 d7 59 91 +02 4a c2 2e b6 eb 2d c7 c6 05 8f 64 87 56 45 10 +2b 95 25 4e 25 e9 f0 ae 45 06 d4 3c 60 1c 18 8a +31 4f 4b b4 e0 38 c8 15 39 41 6e 10 5e 80 97 fb +69 5a ab 36 fe f5 16 e6 a3 3f 36 f7 f9 5a d1 ff +15 88 90 25 b1 b2 e8 1e 1b f3 b2 de 5b a9 18 7c +a9 6c eb a9 fc ec ef 9c 53 e4 94 34 86 18 59 67 +cf 7a 64 77 c3 29 f0 0e a6 95 52 5b ca 99 f2 c7 + +# PKCS#1 v1.5 Encryption Example 2.17 +# ---------------------------------- + +# Message: +6a fa db e3 da 68 d9 02 85 bb 8f 1e 21 29 ff eb +b1 c6 5b 95 88 d6 c2 c0 40 24 c2 38 b2 0c 65 d2 +ac a5 e3 82 76 00 0a 0e 6a 0d 05 37 ef ee f6 d3 +e3 d9 4f b9 + +# Seed: +ee 17 6e a3 cf d4 90 b6 c0 49 d2 e7 4c 90 c0 ee +74 68 52 03 49 b8 51 65 3d b0 58 a1 c3 e9 56 e0 +88 5f 26 1b 6e 71 cf 1e 62 3d 3b 9d 1d 56 fa 13 +67 e4 7f f3 74 ad 39 30 9f fa 2e 67 11 28 d5 ab +b4 a6 1a 5b 0d c2 db 2c 08 + +# Encryption: +67 2f e9 51 59 a9 89 3f 34 98 b6 16 c1 7b 59 da +71 da 80 2f eb f7 cd 38 11 06 14 a1 b2 5d 96 aa +8a 74 aa aa 2a 0f 00 0e f8 ac a3 b4 1a d1 61 b6 +26 33 f2 41 31 9c 33 e4 ec b7 70 6a b3 ad c6 a3 +ef ea 22 43 0f 3f 5c 9c 4c e5 40 4e b8 e7 5a 10 +93 69 c0 aa 0b 7d d7 13 bd 8b 77 cc a5 f7 4b ca +5b c5 55 69 6b 68 e1 17 2d b4 02 50 1d cd 26 49 +68 5d b0 fd 88 c8 83 60 da cc 65 09 ff a8 df c2 + +# PKCS#1 v1.5 Encryption Example 2.18 +# ---------------------------------- + +# Message: +6d 9f 9b 4b b1 23 ba 90 95 53 a7 57 3a 97 1f 64 +b7 25 24 cf eb 04 2d e3 92 15 f6 50 db 61 2d 66 +d7 ae 86 05 d0 44 19 54 62 5f a9 81 22 33 0e 92 + +# Seed: +7f f8 68 5a ec f3 40 26 13 90 ad 07 42 73 0c b6 +39 28 30 14 ab 37 73 55 6c 69 7f 97 ef 62 1a 4d +cb f8 ec 6e de c5 0d 8e c9 59 0a db af 23 51 dd +fa 0e 52 ea 6e d1 8e b6 c3 78 f3 80 85 ae 5e e4 +cc 48 c1 89 1b a4 7b 20 10 d5 d4 35 39 + +# Encryption: +8d 30 65 5c f1 5b f1 0a 46 97 87 c6 a1 0e 79 25 +4f f0 bd 11 93 8b c6 0a 81 a7 58 d9 3c f2 a0 30 +24 59 fc 2f 0d 77 00 b8 6d d6 ed 61 83 83 b4 4b +45 87 04 ca 11 92 8e 50 4f 02 8e fe 50 37 17 2c +3e 51 b8 37 be 61 56 de 6a 09 c5 55 97 be 74 c9 +7c aa 1d eb f3 14 cd 94 b9 1b 9f 94 cb f7 64 0f +86 c2 6d 1d 6a 0b 10 46 28 b5 87 11 4a a3 1d 99 +f6 9c f9 57 37 93 2c 0c b5 33 33 74 de a0 7f ac + +# PKCS#1 v1.5 Encryption Example 2.19 +# ---------------------------------- + +# Message: +33 cc cb 59 7d e9 5c ed b8 b6 57 fc d8 f8 88 86 +da 04 c7 57 93 53 14 + +# Seed: +53 42 f4 68 43 91 cd 74 f5 28 2d b8 31 41 ff f6 +78 f2 3a 3e a6 52 e0 d4 27 fb 6a d9 76 c5 a7 10 +a6 37 95 77 71 89 47 ac 72 7b 4d 58 a0 b0 bd 20 +7a e3 73 a8 b9 9a c8 e2 51 eb 02 45 8a 9e dc 39 +52 fb 28 42 6d 18 fd a1 8a 80 2b bf 0a 0b 8b 2c +f2 5c a3 a0 22 f7 78 c7 f4 7f c5 30 d0 b7 a5 bc +84 6e ea 91 80 f2 + +# Encryption: +8c 4a 63 d0 73 1e 2e 71 eb 46 15 18 9a 96 8b 3e +4a 24 28 56 b2 09 02 45 23 8b 66 45 97 8f 1e e8 +d7 98 11 06 2e bd 2d 1f 3d 52 3a e6 00 e0 e5 a6 +e4 05 c4 e4 b5 a1 6e 8d fb 49 24 30 4b 0d 1f f4 +d6 41 bf 98 7f c6 d4 1d 3e b7 cd c5 31 34 d0 06 +9c db 5a fe f7 f8 f9 ca c0 ee 52 30 b6 f8 86 22 +a8 4d e5 2a d6 f7 50 47 84 37 06 ca 96 97 42 c5 +8d a7 72 62 ff 1f 12 8a 66 4e 51 cd 63 5e 71 15 + +# PKCS#1 v1.5 Encryption Example 2.20 +# ---------------------------------- + +# Message: +19 d6 + +# Seed: +ea ac b5 78 ae ab f6 9d 4e ae eb 36 d0 4c d8 a2 +2e 8f d7 a2 5f 04 43 a1 1e 4e 08 b3 ff ac 1e 05 +42 1a 87 6c ca 91 31 82 50 be fa ff ef 9b 27 49 +dc 40 2f ad 4f db 7c 1b 66 aa 5e 08 9f f9 9f 8b +30 0c dc 46 f4 8f 56 48 c9 40 8b 5f 8b 3f 5a 12 +e6 50 50 dc bc 0d 53 43 d6 3d 58 08 19 21 65 2d +5b c8 2d d3 d7 0e 07 5d 32 d8 02 c2 97 64 78 fc +9f 09 93 dd 08 59 c9 0e 22 8e 87 + +# Encryption: +61 3b ba 5c 19 0a d7 72 e0 8c 29 07 6e 2e 9e 5f +12 ef c9 29 2e 3b 5c ee 52 c2 69 7f b7 b6 07 dc +72 e8 25 78 e8 b7 53 ba ca df 23 b4 77 25 21 3d +b8 9f 88 73 fa 79 b9 14 a4 b5 16 1e fd 9e 15 cf +a8 dd 1e ff e8 9f 89 47 a6 f3 82 6d c6 bf 53 be +ca 36 5b 93 81 18 45 62 a7 9e 21 ca 0e 68 eb f0 +ab 82 ae 76 2b 28 c1 43 65 15 2a e0 f5 4f 2e 9d +14 43 9a 84 6b 38 3f 5e 2c 55 ef a7 00 85 97 b5 + +# ============================================= + +# Example 3: A 1024-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +b9 30 96 d0 26 1e fe 00 0b 3d 17 04 f5 04 31 60 +ab d3 eb 56 6c 61 e5 3c 76 c4 01 e2 b6 55 21 bc +12 d4 81 21 51 83 e8 f4 6c 2c a8 d0 0a da 5d fd +04 dc f7 cf 36 cc 58 11 05 d9 9d 2a 7d d9 4b 56 +76 0a 65 64 fe e5 e8 aa eb 06 07 e1 45 19 62 10 +a3 1b 7e d8 dd 2a f3 2d 29 d2 ba d6 f1 5f fa 5a +11 dc 73 5c c3 62 19 02 1e e8 d1 ee ed 34 63 9b +5a 91 ac 6a 92 67 4e 18 39 70 c5 9d 5b 19 6d 4b + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +b9 30 96 d0 26 1e fe 00 0b 3d 17 04 f5 04 31 60 +ab d3 eb 56 6c 61 e5 3c 76 c4 01 e2 b6 55 21 bc +12 d4 81 21 51 83 e8 f4 6c 2c a8 d0 0a da 5d fd +04 dc f7 cf 36 cc 58 11 05 d9 9d 2a 7d d9 4b 56 +76 0a 65 64 fe e5 e8 aa eb 06 07 e1 45 19 62 10 +a3 1b 7e d8 dd 2a f3 2d 29 d2 ba d6 f1 5f fa 5a +11 dc 73 5c c3 62 19 02 1e e8 d1 ee ed 34 63 9b +5a 91 ac 6a 92 67 4e 18 39 70 c5 9d 5b 19 6d 4b + +# Public exponent: +01 00 01 + +# Exponent: +01 07 ea 61 ad ec a5 e9 00 7c 59 13 4a 7d 38 fc +7a f3 10 3a d2 c4 a2 be e3 97 08 be fc 83 dc 79 +b7 0d c9 75 92 db 6d f7 0f b3 c4 9c 25 35 fc fd +9f c2 ce 7b 05 53 92 e3 ee b3 e7 97 93 cc 1b 60 +15 3f 4a 0b ff 26 be 66 7b bc db bf 6e 32 af a6 +fd 14 83 7f 3c 79 be 44 cb 1c 63 8f fa 5c 6b 17 +70 9a 96 e1 27 03 0b b1 11 6d ec fd e5 2b b0 40 +84 2a 94 d2 e6 74 f1 17 51 ec b9 03 ee 10 48 45 + +# Prime 1: +e7 fe c4 74 e0 eb 31 2d 1d 76 cb b2 72 2e fa 42 +10 68 b1 91 e2 33 b6 4e 46 08 7f dd 45 76 d3 85 +55 07 19 35 2e 10 9f e4 33 ac 4e 35 8e 7c 28 59 +eb a7 e4 3a 04 ee 85 9a 46 35 2c 12 43 a1 cc 6f + +# Prime 2: +cc 5a 02 f9 55 7a 63 5c f5 e6 9b 0f 2b 3f 2e 61 +2e 1f 0a bb d4 bc f1 69 ca c0 84 dc f4 b9 b4 34 +43 a7 85 23 90 f8 19 41 9e c1 a8 38 7e f0 4d d2 +db 7d 60 b4 0a 21 f9 4f 46 d2 27 87 4b 3e 52 e5 + +# Prime exponent 1: +ab 92 8b 10 35 57 3b 23 36 6b 28 f2 6b e7 ba 45 +29 85 83 ed 73 f0 f2 9e a8 c4 98 6b b8 77 cc af +0a d7 19 19 6f 5b f4 23 fc e3 2d 64 06 60 64 27 +3c 55 0a 40 ae 6d 08 79 b3 fa 97 01 5a eb 4a 19 + +# Prime exponent 2: +8c 7d 55 8e 15 36 0f 19 d9 f4 b0 a5 bd 15 b2 cd +1c e8 3a 78 e7 c8 fe 2f bd 34 9e 23 4a 1c 61 c7 +8c bb 9e cc d4 dd bc 7f 60 a5 c3 01 14 44 21 3c +d5 a9 5c d2 6a 24 f1 41 8f 6e eb be 17 fc c1 + +# Coefficient: +b0 b1 b9 cb 23 ac 2a 8a 56 36 66 69 9a 52 40 54 +be f3 81 aa bd 75 55 31 a1 df a8 85 dc 8f 98 86 +a5 5a f0 e3 68 63 91 c7 97 68 1a 8f ef cf 24 db +d8 1e 03 13 16 99 8f 5d 81 8d 24 76 da d0 6d e8 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 3.1 +# ---------------------------------- + +# Message: +44 e5 6a a7 7b d9 35 ac 59 a9 bd 32 37 83 e1 27 +42 + +# Seed: +92 ee f6 19 f0 4f 52 02 8f 4c c3 e5 24 1f 0a a0 +92 1b 4d 18 3c 1f 5b d6 8d 86 fb e9 e7 b7 d0 bb +10 4e d1 ca e0 7a c7 d8 0b fd 9c 1c ef f8 dc da +1d cc 69 30 f4 c5 51 37 34 6b fd 68 c1 9d 87 97 +2f 7f 34 cb ae 56 63 26 0f eb 79 f7 60 22 1c d6 +7b e0 66 d5 af 0f 07 3c 0f 2c 43 9e 8b cb 74 63 +ed e4 4c 8b 15 0e ba f3 29 87 26 c3 + +# Encryption: +15 91 d1 ce 0f ad 66 d8 6f d4 2e fd b3 1e 9a 02 +8a 31 57 fb 09 14 b2 47 eb 3d 22 d7 6f 97 69 b0 +e1 9f 6c 06 4c a1 b9 89 06 39 ee 6e 37 b7 09 22 +4d 6b 58 eb b6 55 ae 4b 69 ed 4c d7 5d 81 29 21 +17 c0 69 30 d4 2a c4 d4 2e a7 35 14 21 8f 49 ea +07 ca 97 43 67 09 68 3d 67 a8 e9 e8 08 da 69 a5 +0b 73 9c 42 eb 0d eb 94 a3 49 8f c5 45 0e b6 9a +ce 23 76 76 61 fe df 34 18 3a 1b 6f 42 5d d6 a0 + +# PKCS#1 v1.5 Encryption Example 3.2 +# ---------------------------------- + +# Message: +a7 57 38 29 1f ad 54 13 95 7f a3 b9 f3 b2 ca ac +9f 5a + +# Seed: +3a 19 1a af 45 ed 4c 25 89 20 5d 9c f6 a3 0f 07 +70 0e 38 be 06 25 62 43 01 8d 23 c6 84 da ec e7 +e8 67 e3 9d 76 c6 b6 f0 35 43 fc 15 af 81 bf 84 +f9 64 ea f3 a9 5a 4b 80 86 28 fd 51 55 38 99 f8 +11 c0 8c 62 60 9c 51 4c fa 1d bb 78 d5 a5 b3 3c +c0 b8 57 fc b1 ee cc 53 1b 13 26 34 43 90 59 f5 +5a 73 3e 14 6e 1c a1 eb 5a 97 f4 + +# Encryption: +70 aa f7 24 39 6c 1a c5 0e db bf e8 34 1b 08 7b +a0 ff e2 87 60 5a 8c 3a 8c cf 85 ab 2e d2 fe 22 +15 9d 62 aa 02 74 76 eb bf 07 70 02 6d 2d 3b 0c +0d 77 34 fa aa a8 d1 5e 2c e5 1c 85 53 5c 26 b4 +15 0a d6 34 6e 3b fd 38 db 5d ac f7 52 e7 5d 75 +31 40 54 d1 67 a9 6d 81 9f 34 38 a7 be c4 46 7f +c5 60 a6 94 46 94 85 e8 e7 8e 47 e4 e8 27 7c a7 +d3 fd 2a d9 4a 30 46 4c 24 57 85 47 25 c6 16 15 + +# PKCS#1 v1.5 Encryption Example 3.3 +# ---------------------------------- + +# Message: +87 31 2f 78 7d e0 65 97 50 d6 02 ac 11 02 + +# Seed: +a2 29 e3 e8 ef 1c aa 66 ca f0 d8 ac d8 d6 6b 9e +41 cc 77 1f 26 e2 0f 12 ec c6 e2 aa 38 45 51 3d +d1 34 f7 c6 e5 74 f4 1b 21 5d 1d 11 17 56 da f9 +71 cc f3 9c cd ce 78 16 19 d7 97 20 df 91 8d 33 +9c 82 6d c0 49 b3 90 91 7c 17 ba 0f b1 30 2f ff +11 0a 14 dd 23 84 90 27 41 f9 12 b2 6a 1a db e0 +ed 1e 8f d9 89 71 0b 40 3d 27 c4 e0 18 fb 9b + +# Encryption: +03 38 46 d7 66 4c 8f 92 62 57 c7 fd 32 64 48 47 +92 ac 7f 9b c8 75 8a 7a 16 ab b8 9f a3 cc c4 d1 +3a 1e ed 88 af 73 23 bc 3c 74 e2 3f da b5 03 81 +89 4c 86 26 df d0 ac 85 89 d4 62 34 d3 c3 5f 18 +99 81 79 44 84 31 dc 81 6f b6 3e 55 cf 26 d7 4a +9d 2a 09 32 67 3c b4 be b8 29 cd 7d 49 50 88 48 +c6 d0 c0 0d 5c 70 f7 fb 47 67 70 e4 03 19 23 7c +78 6b f4 e2 6c 48 d2 cf d9 6e e3 62 bf 29 28 25 + +# PKCS#1 v1.5 Encryption Example 3.4 +# ---------------------------------- + +# Message: +9a 2b ca 75 e3 26 49 77 7b 9f 13 ec 30 fe 16 bb +8a b4 6d 6d 5e 0c 64 63 a7 3d 8c 36 63 ad ab c7 +23 bd e7 2a 50 76 5e 7b 30 0e f6 b5 61 de e8 84 +84 88 0e 4d 61 2c + +# Seed: +8b fa e9 22 2f 75 a0 69 98 ed 6d 9b 14 9e 89 05 +cf c8 db 05 5a 0e 32 ac ed f8 24 d2 f6 b5 b4 2b +3a ea c6 a7 10 4e 14 4d 5e 48 34 28 0e 36 44 5a +b8 50 f3 a6 de 16 4c 2c 79 0f e7 d9 d7 bc 7f 9b +db e2 52 17 da 2d ed + +# Encryption: +6e c5 f5 59 c8 a3 20 d9 0d 1e b5 ef 09 1c 4d 12 +55 a2 4a 69 19 41 0e b1 df 65 a9 7b 30 cd d7 fa +e1 8e 65 12 a0 27 e9 76 70 4b 4f a0 44 37 43 93 +d5 01 e2 ba 46 18 62 00 ef 0d dd f1 9c 75 77 58 +e4 67 94 30 bc d9 fd 11 9e a2 43 b3 49 dc f8 1c +34 32 d3 1f ba 91 1e c6 fc 68 6e aa df f6 b9 fd +f5 3a a4 c8 5a 49 a2 2a 05 1c 5f 18 07 f3 08 3b +1b 3e 61 17 b4 ef 12 08 de 0a 80 01 dc 29 1c 4e + +# PKCS#1 v1.5 Encryption Example 3.5 +# ---------------------------------- + +# Message: +df d6 3e 6e c6 1e 07 27 5b 8e 37 cc 63 69 e1 f3 +ec 0b fc 57 a2 98 b9 05 ae 5d 07 74 e0 f5 22 e6 +75 9c 7d 11 6f 8e 8e fe 69 45 0f a7 a8 38 9f 81 + +# Seed: +c4 22 37 7b 89 86 4b 0d f3 8b 4f 9c 15 f9 8a 05 +96 55 e1 c9 b0 c7 09 63 5c a6 06 49 d8 d2 47 5e +e1 6c b1 27 f6 76 39 12 96 4e 19 84 d6 da ad 4d +6a bd 04 b0 46 18 b3 2e 53 25 ba 95 eb 5e 76 db +d4 6d 9f b5 9d f0 7a 08 1e 95 6c b0 73 + +# Encryption: +9e 06 cd 91 a4 4a 9a de a6 a7 98 03 d3 e6 bb ab +17 db 10 62 b6 51 0b ed 40 07 55 66 74 95 44 c0 +3d 7a 78 b1 37 b0 dc 1e 66 26 32 1f ed af c2 0d +cd bf 70 80 f7 f5 bd d5 67 44 ce 99 9f 76 70 5c +4f 5e 6f a1 5f 46 c5 ae 50 80 90 db bc 85 fb 86 +89 9c 95 78 60 8d fd 77 8a a4 a7 9d 3d 73 63 54 +cc fb fa 2c 86 f2 9a 7a 58 45 3d 75 7f d5 22 f7 +84 08 d9 91 6b 1b d0 65 4b ff e6 e0 66 ba eb 50 + +# PKCS#1 v1.5 Encryption Example 3.6 +# ---------------------------------- + +# Message: +5d 91 fb c1 a7 ba 79 93 9b 89 a2 40 8c ce 8e d4 +bb 26 66 dd fe 09 d9 19 21 a0 aa 69 09 6a 95 69 +92 c2 1c + +# Seed: +af 07 fe a3 21 ea a2 67 af 7f 09 80 6f 9e a8 b4 +cf 13 5e d6 f1 43 2d 51 b2 8f 92 44 87 09 c2 ee +8a ed 7f 73 b6 28 2c bf d3 7f 82 db a8 72 3e 5e +5e 0a 81 f5 90 f8 2e 2f a8 4c 3b c0 0c 9b 9f 91 +aa 55 3b 8b 2c 07 4b fe ca c2 f5 52 37 f4 cb 70 +54 3a ba 49 94 68 cf 68 44 c3 + +# Encryption: +76 05 0e 22 64 22 0e 10 05 2c 49 b9 6c c8 41 1e +39 6a 7a 6e 4a ed b0 6b 48 fd b0 71 de 83 9b 40 +1c ac 0c 46 8d e8 d1 ed 0b 56 8c e6 90 e8 03 7a +f5 de f6 b3 d2 db c7 b5 f2 fa de 35 6c 26 cf fc +dd 33 40 33 ea 2c 99 77 92 d9 30 a7 26 46 12 5c +0e e8 6a 4d d8 43 c8 24 c7 a5 2a c9 88 c9 2e 6c +69 b5 80 76 1c 49 88 1f 29 dd 8a 76 da 79 3f 43 +2e 7d 5d c7 31 a2 5e 5b b5 02 58 d0 27 39 5f bd + +# PKCS#1 v1.5 Encryption Example 3.7 +# ---------------------------------- + +# Message: +04 ed d8 3c 65 65 6a 01 + +# Seed: +88 f9 a2 71 97 f9 f2 57 fa 81 c0 e3 05 90 b7 3e +9e 11 c7 6b c8 9e 08 53 6b 4b 64 a2 50 6a eb 33 +b4 50 74 73 08 09 a0 5c 45 b9 bc 95 71 73 69 cf +92 c1 bf 98 6e 53 ba 11 23 83 30 fd c4 e0 5e a1 +07 33 4a b3 11 06 ae bd 9c 6c 29 e5 01 a5 7d 99 +7c 01 bb c1 01 0b d5 2f 05 38 b9 51 59 f3 91 32 +0d e6 db 23 d8 16 2c f1 46 58 4c 6e 07 6c 4e ae +86 20 72 eb 5b + +# Encryption: +79 1b 37 91 48 a8 3a 03 4d 31 2a 82 bb b3 7b 11 +1b 40 bc f6 a3 37 fd e2 89 b0 8e 07 2e 44 03 19 +73 ff 9d 0c 27 f7 0d 64 a8 ea fc 6e b5 f8 eb 4e +52 e2 c4 19 7e cf a5 45 ed 63 ae 9a 12 83 79 d3 +f5 62 a1 8f e3 ad 14 05 27 67 f0 54 1b 90 16 81 +85 cb b7 8d b6 03 81 c0 92 bc 23 e1 aa 05 b4 08 +92 f9 a1 16 e6 25 cb 14 8b 56 07 42 cc 12 78 c4 +d2 1a 4a 7d 37 f6 98 2a ee 27 f2 a4 c0 c5 73 d2 + +# PKCS#1 v1.5 Encryption Example 3.8 +# ---------------------------------- + +# Message: +3f 7e ea 78 1b 77 d8 5f e3 71 b3 e9 37 3e 7b 69 +21 7d 31 50 a0 2d 89 58 de + +# Seed: +49 99 c6 4c bf a3 85 24 ad ca b6 6f 64 45 4d 36 +fb fc b2 98 6e 1f a4 75 3a 0e 03 88 9f f0 6e e1 +60 0e ee 23 be 53 a9 74 42 b4 2c 69 62 18 66 63 +2e 4a 6b 6a 1c 71 05 73 26 1d 71 f3 8a bf 9e 52 +49 dd c8 e1 b7 7b 3f 12 6b a0 88 15 c4 fe 63 31 +4f 9b 9e 8e 7a 40 c7 fc 72 86 25 20 ed 49 d4 12 +59 ab 2e 0c + +# Encryption: +74 fd 8b 98 56 d7 57 6e 0f 12 87 e0 e9 08 5a 38 +01 e6 b6 77 4d b7 33 54 1d eb d3 9e 72 cf a8 29 +1f ec 27 01 8c 9f 53 05 a4 4c cb 5a 3c b5 91 fe +d2 e6 a1 d1 d8 5c aa a7 4d c2 37 59 d6 66 5a 45 +70 a6 37 f3 ab 30 4b 76 61 31 3b 96 71 3c 7b 7e +49 77 31 33 dd 5d 4e f9 d2 9a 1a f7 12 00 15 02 +8d aa b3 df 04 2c 56 26 20 aa 49 d2 c0 14 41 4d +fb 15 77 d7 19 a9 58 82 64 71 2d e3 bf 4a 76 79 + +# PKCS#1 v1.5 Encryption Example 3.9 +# ---------------------------------- + +# Message: +a3 85 08 d9 46 0c 63 f4 15 81 a8 86 9a 75 82 4b +14 f5 c6 50 32 29 99 dc 41 13 50 d0 d4 e8 62 4f +f0 9c eb 00 d3 be dc 5d 76 2a 40 c9 39 80 04 + +# Seed: +6a 0a 28 8a 1e 67 43 0c 66 6a eb ea 44 b5 82 a9 +09 69 cc 01 e9 0a ae 10 53 ce 55 ee b9 87 9b cc +62 25 39 15 e9 22 f1 09 66 67 bd a0 2a 14 e7 07 +47 b3 59 35 24 c2 84 85 47 d2 11 4d 1d 0c dc b9 +7e b4 df 45 5b ba c9 b0 cc 29 08 39 b7 3a + +# Encryption: +a6 77 57 80 8f 5a bd c8 1e db 7f 69 2f 9f b8 52 +f1 a1 66 1c 4a 00 98 05 c4 4b 21 6c d3 b1 32 2b +bb 25 d1 45 8e 31 b0 f0 7d 65 50 57 59 c4 b4 14 +7f 23 cb ee 2a f4 a1 a5 93 8a 06 8c e9 c5 32 3f +f5 3f 4b 39 2e 12 50 d0 37 b3 1e 62 81 dc df b9 +6b f4 bf ea a1 47 f0 96 c7 84 c9 2f 4a c5 70 91 +12 28 02 50 29 c3 b5 23 30 3f e8 22 7e 8b 2c c0 +ef 15 70 14 cb 67 31 aa c0 9b fe 6f fa 18 ea f6 + +# PKCS#1 v1.5 Encryption Example 3.10 +# ---------------------------------- + +# Message: +f7 84 05 23 6a 9e b5 57 aa ce c6 00 7d bc 4c 0e +de 78 ed 12 b0 4c 82 88 8a 82 c2 13 + +# Seed: +86 f0 72 3b 31 68 e2 ae ac e9 ec 2e 95 fd a6 e6 +d6 fc 8d 62 94 55 65 66 39 9d 73 11 e7 99 fa a9 +b1 ee 1f 03 2a b2 e5 34 a9 1f bc d0 7c 8a 7d 04 +a9 b4 85 f3 1e 07 23 fd 29 eb 21 88 06 9d 9b bd +76 29 dc 6e 3f c8 9b e6 04 bc f0 0c 52 fa 8e 1d +6c 62 55 5f d1 f6 0c ec 02 d4 d9 61 d8 28 da bc +4a + +# Encryption: +6e 8d 2f b0 b2 ee f8 2f c1 10 ce e0 a9 d3 84 2f +2a 05 8a 24 40 7f a1 1b a9 05 d1 aa 50 e8 cc 12 +de cc 07 3d bd 08 a8 c7 05 18 ef 25 db 96 fd a2 +41 1c ca 08 72 87 88 95 6f 73 df a1 20 e0 ea 60 +5b ff c9 3b 43 a4 41 a4 3d 0e aa 3f f0 73 e6 98 +2e ef 52 96 39 06 07 e2 5a 58 8a 39 82 55 ba 00 +5a 48 5e 6e 73 2e 3a 19 20 cd 43 a3 90 fb 66 d5 +42 8d fd 62 89 74 b8 af f2 f0 60 2d a5 78 d6 25 + +# PKCS#1 v1.5 Encryption Example 3.11 +# ---------------------------------- + +# Message: +56 1d 27 c1 d3 f6 d5 d1 a6 43 aa 47 e5 5d 78 eb +00 f3 2d 42 89 6a 34 e0 c1 d7 1b c3 a5 45 7c 92 +05 be d1 3b 98 4c 52 59 + +# Seed: +98 17 6e 1d 67 a2 46 2f 5d c1 bf a6 e0 75 95 42 +10 4a c1 48 11 d3 18 79 38 25 04 55 c6 5e 4a aa +76 32 bd 2d 1d 75 2e 1f 34 c5 3c ab 26 76 76 a7 +8c 10 c9 98 e7 73 fd 8f fe 35 c8 67 c4 43 be f7 +98 65 aa 2d a2 91 5a 85 c7 02 63 23 69 3e 45 4d +8a b3 2a 77 15 + +# Encryption: +0b c0 47 83 c6 92 44 7a 3d e6 1f 53 b7 2f 7a a4 +10 31 6d d5 09 a6 f4 9e 3a ba 56 ad 1f f8 6e be +9e 63 66 e1 7e 51 45 00 76 be a3 71 d4 c6 89 cd +61 49 5c d8 fa 29 c0 e8 7b 6d bf a8 e3 86 c2 e8 +20 e4 c7 42 a4 87 e8 9b 27 5a 21 86 e2 38 40 be +9c 02 52 7b a7 17 e9 e6 0b 5b f4 17 71 1d f3 4d +7b 8e 2d 12 bc eb 85 93 85 fa 00 1d 4b 4b ff bb +c0 ed ef bd 40 02 41 84 68 c5 66 fd f6 b8 35 09 + +# PKCS#1 v1.5 Encryption Example 3.12 +# ---------------------------------- + +# Message: +eb 5f 8c 0d c9 d9 01 06 1b 82 ae ff 8d 67 d8 bf +fc 0c 04 7e cc 4a a3 46 b2 3b db a6 2a 87 e9 dc +77 0b 11 69 5f bf 19 02 f2 4b 66 ce ab + +# Seed: +74 82 77 0f 3c f5 7e db 81 40 eb c3 3a 02 82 45 +ee 06 48 52 06 89 a5 0e 33 f5 f4 67 f6 d1 e4 32 +4e 1c 50 c8 99 e5 ad 2c 46 c9 7f 81 20 d1 c7 22 +39 d6 a8 2d 8f 8e bc 80 b9 73 ee a8 c5 45 69 29 +50 45 14 b4 b1 56 62 84 4f 29 50 62 f2 1e bd 92 + +# Encryption: +b8 40 43 54 a3 81 b7 c2 ab e5 f7 28 25 f3 d3 15 +bd ac e6 c3 cf bd 88 b8 97 68 61 20 05 19 7c 61 +66 38 83 f2 c2 57 4f 99 5e a6 f9 4e b3 4f 27 68 +62 b3 3f 58 a8 83 92 23 70 6b e1 c1 ff 47 23 05 +f1 1b a9 56 2a 0e b0 12 f1 aa f8 5c 22 e8 8f 2f +df ea ff 86 33 d3 cf eb 5f 76 4f 42 28 92 0d e3 +0c 6b de 2c b4 e8 f0 3d 90 ed 54 8f 64 85 00 35 +1a 5f 41 df 74 ad 65 e8 c3 be e9 50 5a 7d 70 e1 + +# PKCS#1 v1.5 Encryption Example 3.13 +# ---------------------------------- + +# Message: +5a 7f 0e ae ba e4 9c f5 7c 47 5a 6d a6 79 43 a7 +d3 04 6e 3f 7c 7d 50 b0 9a 80 98 b5 44 69 39 68 +93 cf c0 b2 f0 8f 6c 2b ff 23 50 51 57 5e 6e 56 + +# Seed: +fb 08 48 86 db 37 98 d2 b5 bb 35 a3 b1 d3 af 4f +df c0 45 6c bc 79 7b 96 40 d8 c4 4a 0e 03 4e 40 +37 2b 34 fc 7c 1e 8b 66 01 1b 4e cd fa ec 6e e4 +cd c8 28 cb 1a b4 91 27 4a c1 e3 9f 67 58 7a 55 +47 67 09 b4 02 3f c5 69 cb e8 b4 fd 4b + +# Encryption: +07 78 4e cb 8c c5 ba 02 d2 07 ba b0 55 c0 e5 5d +10 a9 b9 42 70 cc a2 50 ee 75 fa 1b 5a e1 90 b3 +3b 96 96 eb 2e c9 72 b2 6a 0e 94 23 af 16 aa 37 +89 17 62 76 06 0a 76 40 03 21 11 74 82 96 34 03 +4f 97 12 c9 17 10 17 f2 fb 21 3f 25 c1 46 c2 65 +1f 89 44 0c a5 36 e5 33 e3 05 cc 6b 01 13 39 8f +61 b4 63 b0 73 e1 be 05 07 3e 9d 64 bc ae ea 54 +44 b8 20 c6 ab f3 46 54 30 ff 4d e4 a8 bc 0e 75 + +# PKCS#1 v1.5 Encryption Example 3.14 +# ---------------------------------- + +# Message: +f9 1c 71 af 5a ea ca e1 79 e1 6e 87 c9 02 3b a9 +4d 84 d7 51 6c ec 6c 39 89 80 1f b3 e7 ad d0 64 +bd df 92 8b 50 00 94 0b bd e5 39 d6 23 37 9c + +# Seed: +de b2 60 25 8b e2 c8 53 35 21 57 b0 65 26 b1 43 +ba 13 3c 4f 49 bf 3d f2 c0 50 ec b2 c9 ca 32 53 +11 b3 c3 e3 d8 8d f6 c2 4a 89 4e ab 63 74 5b 62 +53 e3 c4 6b ca 17 1a 26 a4 f2 fc 0a b6 2b 8a 2e +63 a0 18 eb 47 01 8c ab 95 1f 59 f0 20 3a + +# Encryption: +0d ff ff 51 97 10 c9 ea dc 53 3b 10 8a 4c 29 74 +fe 53 18 91 a3 41 07 a6 74 27 93 5b a7 20 cd c6 +f6 ee 02 9a 1b 03 68 61 db 14 04 c5 86 49 90 54 +1f a2 42 13 01 a7 b2 48 cb 11 f3 65 b6 a4 aa 94 +6f 22 31 cb b1 47 32 b0 1a a4 a6 0b cb e5 20 ec +6c 38 53 a6 95 8a 93 c5 b6 8b 85 d4 bc 3d 84 15 +ef 8b 1d 4f 63 03 8f 4d 94 2c a6 bc 7a 38 25 1f +15 a4 e3 3b 18 9c 25 0b cf bc 03 15 6e 4f 92 11 + +# PKCS#1 v1.5 Encryption Example 3.15 +# ---------------------------------- + +# Message: +07 90 c0 81 f3 61 c9 5b 59 d5 27 d3 cb 50 71 0e +66 e2 72 59 50 10 25 ed 3f 20 f3 0c + +# Seed: +fc fc 2d 56 cb 92 6d 90 5d b3 6e 1e 2e ff 1f bb +75 d6 53 51 7f 59 e8 6f 71 bc 4b c5 57 26 f0 88 +b8 21 62 44 83 b3 e2 9a c2 1a 49 bd 85 91 34 90 +8e 6c 0e c1 a0 dc 80 79 93 01 44 12 0d 1f 6b f9 +3b c6 27 b9 99 69 b2 af e2 1a 7d e1 0d 96 f6 ef +43 c5 67 b5 e2 38 38 5c c1 1a 5a 2a 13 e1 78 55 +8b + +# Encryption: +7f 0e 6b 34 2d 6a 13 54 66 be 41 73 38 1a c0 4a +ba ab 7e 14 fd cf 51 01 89 87 e9 69 67 16 9a ea +97 78 03 eb b3 24 2a e9 ad b4 6f f5 11 20 93 4b +39 21 46 31 b0 3f 5a f5 bd ea 1c ac d3 28 ad dc +d4 0a 3a 29 96 6b f9 8b d7 c8 c6 fd 0f 4e 8b 97 +2e 2d a1 0c 6c c5 52 05 86 7f 39 04 ed 60 f5 b5 +be df 7c 3b 3c 7d d5 f3 87 54 8f 40 05 67 02 ea +72 01 76 dc e2 06 d4 13 d7 42 3f 94 3f cd f6 39 + +# PKCS#1 v1.5 Encryption Example 3.16 +# ---------------------------------- + +# Message: +93 c4 1a 1a dd a8 f6 93 60 f4 1a 58 ec a0 b5 5e +cb 37 a6 a9 00 fb c7 da cd 9c a3 99 c2 3d 31 72 +61 53 77 ac 0c c6 b0 ed 43 bf 59 7f 21 cd 25 9d +8f 80 88 7b 15 9d 96 d6 61 61 d5 58 9b 95 f1 fe + +# Seed: +99 1a 2a 7c 06 1c 23 a8 eb c9 48 9a bc 1b 4a 64 +a5 d4 e8 38 d9 fc ba 42 88 c0 1f ea d6 6d 59 f4 +96 36 e4 a8 d7 52 4c b8 9d 7a dc 7a f3 f6 1a e6 +b3 9b 58 8f b7 7e b7 02 23 62 ff d2 6b + +# Encryption: +7e 54 a4 32 f5 25 c5 23 33 ab e3 bb 45 48 7e 03 +9a f9 4d d3 ef c3 58 44 dd 8e 83 5e e1 00 61 78 +e2 4d cd 19 fc 07 66 7b 4a 34 f3 bd 77 1d 09 a7 +e2 9f 8c a1 7e 88 d0 29 b9 0d db 5f 28 13 be 99 +00 0d 59 f5 43 2c 46 6a 84 28 75 77 20 4b f7 65 +97 39 27 69 98 30 57 47 66 7f af d8 02 9c dc bb +59 18 39 3c 2c fc e4 d8 4a 92 20 ea 3e 38 19 72 +53 36 f2 5f ee 8e 08 5d eb ed 33 32 d5 dd f1 ee + +# PKCS#1 v1.5 Encryption Example 3.17 +# ---------------------------------- + +# Message: +9e 2a 7b 37 74 b1 1e 62 b6 49 0b 56 51 a0 c1 8e +09 2e 9f ab 8b 22 84 ae 46 43 be c3 6b 26 5e 5b +a3 c5 1a c3 85 b2 c7 3d 22 0b 2d c2 e1 0b 0d 69 +0f 67 94 5a 0c 42 b3 bd 09 d0 a8 a7 + +# Seed: +a1 8b fb 74 f6 de bc ed cf b4 7c 7d 5d bf 10 6e +77 4d 7e f6 63 8e c3 82 18 69 cd 2e d6 2d d5 32 +5f 4e 57 33 b8 bf d5 fa fc 43 e4 16 4e 78 d4 38 +99 4d 85 33 7d 7f 0d 38 f0 ea 3b a3 7f 4f 41 b6 +a7 + +# Encryption: +18 c8 8a ee 25 36 d9 42 f7 62 2a 64 4f ad 6f ec +d3 32 28 c7 ae a0 ca da 0e 53 1f 4c cb f1 c1 f2 +69 cc 95 86 29 a4 3b 97 52 fc af 2b f9 53 ec 9f +7e f4 bb 0e 62 d1 28 e0 cf 4b ab e9 2c 6d 92 84 +9e 98 38 dd 88 e2 b4 68 bd ce fc 04 a9 e4 cb 55 +e2 a5 18 ca 25 9f 9e 81 a4 9f 28 df 34 76 1f 9d +ea 2e 70 59 56 62 62 6c f9 6a c0 5a 7c 8b 10 33 +33 e9 06 e1 32 63 9b 65 a7 66 f4 09 2c 8c a0 78 + +# PKCS#1 v1.5 Encryption Example 3.18 +# ---------------------------------- + +# Message: +0a c5 2d 40 01 f2 5c 2c 9d b9 1c e5 0b dd f0 d5 +91 9e 19 96 2e 83 b0 7c b7 9a db 00 43 6e 13 66 +b0 aa 8f 3f d1 ee 79 6b 23 c8 bc 56 0c cf a4 bc +bd b1 f8 40 4d d6 f7 55 15 20 d7 d9 e2 + +# Seed: +22 ff dc fe c6 f0 6b 1b bd 14 53 97 70 43 a3 4e +dd f8 59 4d a0 22 13 09 14 97 55 42 f2 f0 0e 98 +f3 1e 0d d0 c4 8f 7e e5 f0 9d 6a 52 71 21 ad 23 +37 1c 6c d0 e0 79 0e b7 30 8b bb 08 96 dd 59 0d + +# Encryption: +b2 69 57 c5 62 29 4d e1 f3 93 24 b1 cd 80 3c fc +39 fc ee 2d 3c 9d 13 79 f8 a1 12 07 9d 69 43 68 +f5 55 03 c2 09 4d 98 8a 8a 5b 5a c5 49 be 1c f5 +53 16 04 5d f5 b6 f6 33 a4 ef 1e 1f 01 9b a1 b5 +42 bf 0a 87 fa 3e 5c a3 f6 b6 1c c8 56 61 28 a0 +fa 41 8b 08 25 c9 0e c2 f1 ec 74 e5 87 cd 80 57 +d9 52 96 7a c4 52 1c cd bf 63 26 f3 50 93 00 93 +82 6d 2e fa 05 8e d6 44 15 37 4d b3 20 48 85 ca + +# PKCS#1 v1.5 Encryption Example 3.19 +# ---------------------------------- + +# Message: +a8 00 34 62 f8 06 b7 f6 61 fb 66 46 32 + +# Seed: +c7 43 f4 a6 da 03 ab 2d e5 a7 31 cb 88 d8 ca 9b +61 c7 31 9a 5f 8b f9 d2 37 87 7a 05 d0 f3 68 c3 +60 8a 05 2a c6 ce 13 73 17 95 47 55 42 ea 16 a8 +62 91 3d 04 32 f0 8b d8 c8 b6 ff 81 95 69 1f ee +5e d1 42 fb 9e ca 94 67 52 4b d3 b5 fa 5a 4a c6 +14 3b 0d 38 25 0a e6 21 d4 39 90 9c be 3a 6b 5c +01 fb ea 2d 7a 3f 1a e4 1d 61 fd d6 47 64 14 9f + +# Encryption: +b7 38 e1 c4 29 f8 fc 06 82 fa ad c8 ca 87 ed 8f +16 df 93 0f af 43 b1 99 1a ac 71 d8 8f 26 4c 0d +82 9a c0 3d 23 c2 5f c5 f3 e8 5d d3 02 cb 7b 15 +33 e6 8c 24 16 c5 1a 79 bb cc 7c 29 b0 7e 2e 0e +23 c6 f2 df 0d 07 81 91 7e ba 1a 57 08 62 8e ed +8a 15 b3 b1 84 af 70 0d 0d ab b1 4d f6 0b 09 ba +d2 12 7d f1 80 f4 d6 f7 29 65 87 60 d6 33 c7 77 +5a 7b 59 6d 09 d9 03 49 1f 21 09 6c 34 c3 95 3b + +# PKCS#1 v1.5 Encryption Example 3.20 +# ---------------------------------- + +# Message: +ef 32 + +# Seed: +43 99 cb 04 4a 60 07 6d 18 cc b3 4e 8b 07 8c 81 +8e a7 7f 63 b0 a4 3a bd ec c5 77 81 93 a8 bb ba +5d 56 d0 fc 4e 82 a2 11 51 6b bd ef 44 e7 f4 e7 +fe bb e1 e1 92 3c 99 9a 7e 96 1c d6 ee 1c 41 6a +85 96 e2 4b 63 83 a4 69 93 5f 33 d1 56 fd 5b cf +db d4 27 46 0d 48 66 83 06 1e 41 05 f3 5b 5e 75 +23 20 15 5c 7f 69 ad 8e b4 02 cc 11 06 e0 28 9a +9b 49 65 82 3e 7a 51 cf e4 d2 6d + +# Encryption: +13 1b 62 5e 86 e6 cd 1e 08 ac f1 95 d9 3c d3 a0 +dc 8b a9 e2 dc d6 fc 99 6b e2 17 24 af 17 90 b6 +88 d7 9d 3e a9 a9 50 98 ca bb e8 a5 d4 85 92 e4 +74 6b 0e d2 af 7c af 89 b7 b6 15 2e 38 24 d9 15 +89 ee ec 33 75 c7 1a 89 97 48 70 3a cc 1e 8d 1d +e4 71 ea 75 28 04 0b 79 5f 29 9e 66 8c ec 9f 5a +f3 eb 48 f9 8c 0d 85 20 67 77 3e 10 1f a2 4a eb +6b 40 4d af b4 2e 7a 63 b0 4a 66 bd 0e 9f 9c 94 + +# ============================================= + +# Example 4: A 1024-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +e9 f2 5e 48 14 0b 5d cf 46 99 e3 03 7f a8 34 f0 +c7 8b 16 73 5f f7 9f 6b 18 ae 60 b5 18 48 d3 06 +99 ec 64 6d 85 7f 15 77 0e 2c 7a 0c 0c 90 0f b6 +04 0b 5f 34 48 4e 9c f5 ce da 23 d5 b2 50 ef 93 +28 6f 01 1e 9a 5b f9 e5 42 e5 c9 f4 42 de 54 58 +e2 3e 41 d1 d9 cd 9f 0c e1 cf 20 08 d3 ea 4d 80 +32 e8 54 cf fc df 5f 69 8d 13 16 e0 29 c4 88 fc +bb 2b e2 9a 4e 7b fb 8e 6e 81 d3 42 12 3e e7 5b + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +e9 f2 5e 48 14 0b 5d cf 46 99 e3 03 7f a8 34 f0 +c7 8b 16 73 5f f7 9f 6b 18 ae 60 b5 18 48 d3 06 +99 ec 64 6d 85 7f 15 77 0e 2c 7a 0c 0c 90 0f b6 +04 0b 5f 34 48 4e 9c f5 ce da 23 d5 b2 50 ef 93 +28 6f 01 1e 9a 5b f9 e5 42 e5 c9 f4 42 de 54 58 +e2 3e 41 d1 d9 cd 9f 0c e1 cf 20 08 d3 ea 4d 80 +32 e8 54 cf fc df 5f 69 8d 13 16 e0 29 c4 88 fc +bb 2b e2 9a 4e 7b fb 8e 6e 81 d3 42 12 3e e7 5b + +# Public exponent: +01 00 01 + +# Exponent: +45 45 88 68 44 53 27 48 60 49 e1 bf df f5 61 13 +a8 aa 45 10 0d ab 07 4f d1 63 94 ec 1a 90 39 b8 +1b 2c b5 81 fe 84 e6 48 b5 f0 32 85 4d d4 fc 69 +f3 61 a0 a3 9d 03 76 13 8c d7 e7 c3 77 84 e2 a2 +f9 d4 f2 66 84 cc 5c c9 f5 12 ba 62 15 eb d2 32 +f9 aa 3d a4 69 db 43 da 1c 06 46 e7 5b 33 aa c5 +70 08 1b 5b 2e 96 ea b7 54 6a cf 93 17 85 aa 2f +d1 82 4c be 2c 5f 9b f5 63 34 ec 15 66 d1 cf 45 + +# Prime 1: +fc df 1c 49 35 8a 1a ac 93 88 c4 6c aa 04 72 fa +35 b2 1b df 99 a2 7b c2 ac 65 46 7b 88 d0 16 1f +bc 70 f3 f4 fa 13 a5 f3 a9 8b 59 c0 67 ea bf 19 +62 16 a1 b8 9e 20 af b2 e5 e5 ed de ae 8e e1 ef + +# Prime 2: +ec d7 51 d3 d3 f3 b2 08 bd 71 8a e4 35 5d 23 f9 +16 fa 8f f6 7d f0 36 61 6b fd a7 cb c8 7a eb ef +aa 7e da 69 1f b9 8f bb 03 8a 02 07 22 01 3c a8 +ee 3d 04 8f 97 ba d2 a2 93 0b e4 b9 6f b7 4d 55 + +# Prime exponent 1: +1d 2f 73 08 50 11 9c 7a 86 9c a6 6f 14 40 67 34 +d1 b5 b8 d9 d9 d5 93 0b 28 f2 97 6b f2 a2 71 ab +40 08 99 5f 90 ed 6b 9d ef d7 91 88 4f 76 1c 90 +45 6d ef 44 6b 9b c2 2b 97 b5 2d fb 21 92 84 29 + +# Prime exponent 2: +4d 50 95 03 c3 83 20 31 3e 36 9c 92 96 e1 0a e7 +3b 9b 1b f7 e9 70 cb 2f ce 63 05 ad be 8a 72 0e +d0 e7 8c 41 18 fc 28 71 72 5c 51 01 27 16 a4 48 +b9 4c ed fa 3a 1b e0 ba f5 a9 c2 46 ce b3 55 e9 + +# Coefficient: +bc 15 f4 7c 0b b6 de 6a 7a 3a 1f e9 28 89 80 9b +4a 3c 0c fa 65 0c 2f ec 36 b8 92 85 14 65 47 a5 +7d 2b 15 71 ac b9 d3 0a a7 91 ec 97 fd 51 fd e1 +ec 26 f5 6b 32 63 da ec 9e 29 2e 9c 17 37 36 4b + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 4.1 +# ---------------------------------- + +# Message: +ca 24 72 1c 88 e0 47 74 f4 15 b4 c4 6c a0 fc 26 +d5 bb 53 aa fb 19 92 f6 de 78 5c 76 3a + +# Seed: +fc 7f 85 c1 38 6d c4 3c 3a 28 46 e4 da e4 d9 54 +80 54 45 9d a2 31 82 f9 84 07 9b 07 1f db 5e 6d +9d 0f a0 b2 2e 3d e6 36 ee 5b 25 3a 42 f9 5e ed +44 22 95 6c 70 f4 8d fe cf 0e 55 5b 05 15 7b 15 +6a 55 c8 bc 65 8c d3 b5 39 7f ab 78 d7 11 56 4e +89 c7 e6 24 8a a0 6a d1 05 c4 0c 31 c4 b1 99 7d + +# Encryption: +e3 95 ff 1f a5 52 fc 2e 79 c4 a5 35 58 df 14 00 +f8 70 4e b3 6c f7 cb 05 1b ab 93 15 0a c6 39 6a +dd 63 66 9b 04 24 8b 9d b3 6a 9c 94 f5 19 8c 6e +5d 9a 17 d4 74 ed b2 03 45 fd 6a 78 b5 1d e8 16 +6e 98 ca b5 b6 d1 65 68 b4 1a 8e 93 e4 83 88 65 +d4 bd 9c 51 cd e8 df be ee a5 88 2b 09 dc 70 bc +9f e7 49 b5 d2 4b b7 ca 51 1d b2 c2 b8 29 a7 c9 +14 6c 77 4e b0 bd 7a af dc 5c 38 d3 d7 cd 58 27 + +# PKCS#1 v1.5 Encryption Example 4.2 +# ---------------------------------- + +# Message: +25 c7 bc 4c b2 43 ac 1f 07 40 86 9c d2 6b a8 26 +f3 55 d4 77 c4 aa 6c be 54 3a dd ea 84 44 44 f4 +1c 35 92 bb 3d a7 d4 21 + +# Seed: +27 2b e3 fb cc 76 14 99 6f 1a c0 e0 a5 e2 69 06 +23 bb 0b 69 70 fc de 0b 6f 45 58 ee 62 34 26 fa +60 ad d6 c5 a8 a1 0d 4a 37 51 50 15 36 fe 8a 45 +c5 42 f6 27 f4 22 9f a1 24 57 c1 13 31 13 72 05 +55 2b 01 4c 91 b1 c4 e0 9e 45 96 78 34 0a 74 c2 +85 e2 6a ef b9 + +# Encryption: +76 50 d6 f8 1a ef 5c 0e 32 0e c7 7f c8 9b 7c 3e +61 83 85 0d 10 c9 8a d7 e9 fe ea 47 e3 8c fb 37 +a0 25 db 42 1f b6 d0 05 80 9e 38 bb 3c 51 95 1d +a9 d9 43 3b a7 ef b1 7d e7 d8 fe 3e 9b 9c e4 55 +53 74 ea 66 3a 1b 5d a4 a0 92 29 4c e9 66 98 56 +55 e2 dd d2 0d 7d e3 aa 35 37 05 8c fd 7e 7a 7b +97 fc dd 98 53 79 2b a8 3f cc 89 07 4a 8d 0f 3c +ef df 98 5b 9e 78 ae bf b0 59 67 36 4f 24 11 cd + +# PKCS#1 v1.5 Encryption Example 4.3 +# ---------------------------------- + +# Message: +cf 00 7e bd 23 da 06 97 1a f7 9a a6 34 d5 d2 55 +05 bd 52 29 + +# Seed: +9c f7 23 7e 28 a8 6e 41 8d 66 4f e3 be 7a e3 0e +eb 95 5a 3f 71 02 b2 7d 5f a0 96 74 9c 7f c2 06 +4c 88 0b f3 d3 0e aa 98 1f ce 39 86 a9 10 fe ea +e1 84 c0 10 25 04 8b a6 79 48 96 fc cf f7 4a 59 +42 f9 62 f3 e3 63 71 f6 b3 55 18 29 43 4a d8 d0 +0a 2c 59 7c f6 d4 51 ea ce 88 86 85 38 a4 80 f6 +8c e6 8f c6 85 6e bb 57 dc + +# Encryption: +b6 32 52 af 2e 8e a2 71 e7 06 fd 68 3d 0f 8c 10 +b3 f4 a3 45 c4 f5 b6 78 5b a9 32 9f 44 62 43 c6 +f3 69 e3 0e a8 fb 11 08 4d b9 79 88 e9 c3 87 4b +34 d6 fd 08 71 7d 9e 81 0e 9c 22 43 60 34 6b ec +cd 3e 0e 53 d1 0b 1e d4 58 e6 4f 3f b0 92 f4 8c +b6 6a e0 3b 64 f6 aa 9c 63 bd 27 9f ae 4c 33 f4 +2a 9d 73 bb 39 11 8e b8 7d 25 12 b9 d9 36 a2 7e +d2 e4 49 60 7d bf 0e 3e 22 3a 53 95 26 35 59 9c + +# PKCS#1 v1.5 Encryption Example 4.4 +# ---------------------------------- + +# Message: +ef da 79 e9 c3 36 c2 34 ff 37 b4 f5 8f db d3 1a +f3 67 5b 3d 2b 10 5e af be ad 4b bb ff f5 4e 68 +6a b5 + +# Seed: +30 c2 09 43 f1 bf c4 23 61 d4 d2 2f 51 a8 d7 86 +cb 2d 0d d5 ff 7d 70 5b 30 28 60 18 11 29 3d be +5d 72 c3 55 97 10 ce 0a e9 5d 2f 16 b2 39 a4 ac +84 45 53 7d 48 8e 3e 6d 2c f5 b7 a6 4c 06 c3 75 +6e 11 60 67 63 63 3e db dd bf 26 be e6 51 18 42 +d2 75 2d cd 88 89 6c b8 55 8a 87 + +# Encryption: +bb 91 b2 f6 f4 33 1d 64 d0 73 6a 2e a6 03 29 aa +16 c2 ed 7a 4d 5c a8 d7 84 e6 30 4c e4 84 4c 71 +58 f8 22 d2 af 29 c8 90 97 7d 75 a9 35 e4 3d 93 +b5 be 10 c1 d4 4f a0 0c e2 8e 75 f5 27 bd 84 a3 +be 5a f5 be e9 45 67 c5 5e 15 ee 3e 93 42 6a d8 +d5 0f 06 4c 57 93 ca 38 c4 3a 70 c5 f5 60 74 0b +16 ee a1 6b 7f 13 41 5f 75 1b 3f db 87 7a 88 29 +33 21 f5 0f ff a6 f1 24 94 96 c2 b0 27 a2 18 ed + +# PKCS#1 v1.5 Encryption Example 4.5 +# ---------------------------------- + +# Message: +4a 01 fc 13 c1 d8 6f e7 b2 fd c7 92 f5 28 0f 87 +5a dc 5a e9 9f f9 11 d0 2c 8c 00 3d 39 bb ee 54 +b8 51 ef a3 4b 41 31 be 52 0d 81 00 ef 62 c2 5a +4b 51 7e 9b + +# Seed: +be 6b a5 d1 1d f1 bf cb 2b 84 67 71 b6 c9 df c9 +33 4d a8 6c 4b 7c 25 43 93 18 e8 ba 8e 47 49 2b +cd 51 1b d4 ca e1 67 7d 31 2c a2 2a 94 57 cc 81 +d9 0e 4d 52 4b a2 26 5f 0f bc a1 8e 3c 3f 48 2d +ca a7 88 33 22 39 34 6d 6f + +# Encryption: +16 bf cf b4 2d 28 b9 d1 62 70 cd 13 8d c3 ca 64 +42 95 6a 41 82 5e d0 23 0b 71 09 16 13 33 3a 9e +7c 52 ce 8c c4 b0 bf 29 10 79 41 a0 d7 2c c3 4a +fd 00 48 bb f4 c7 16 c7 3a a9 b0 c7 8d 37 c1 93 +71 9e be 03 a9 31 74 53 b5 53 d4 f5 b3 85 d1 41 +fc 3b 0e d1 9b 96 dc 35 0d fd 4d 12 e3 dd 03 ff +18 39 d4 78 2c 6d fd 5f df 59 71 f3 dd b0 e3 12 +a9 16 06 f3 13 73 02 0d b3 a7 6d 04 fd 6d 65 d6 + +# PKCS#1 v1.5 Encryption Example 4.6 +# ---------------------------------- + +# Message: +7a b0 6e 19 69 22 c0 + +# Seed: +de 0d 60 33 c1 e9 6b 5f d8 31 21 4f 30 d8 1b 8f +d9 a2 69 3e 5e 8a 36 ea ff d0 39 e7 47 3c 28 ee +43 a3 91 6c 78 c9 a1 12 95 8a 94 ce 67 1c cc 40 +d9 7e d4 18 7a 3f ff a0 dc 12 9d 88 a8 b8 c4 96 +6e a3 94 a9 10 89 61 25 f5 4d af bb 3b 17 b9 fa +10 c4 82 20 09 64 90 c6 f7 5b e2 51 83 e9 98 4d +f5 e4 d7 eb f9 47 5d 11 ea 39 33 5a c7 2f 93 d3 +33 bd 74 22 19 42 + +# Encryption: +54 18 23 f9 05 57 6d a1 42 e2 65 d8 90 45 ab 66 +20 fd 1a 74 c9 53 3a da 4b c7 b4 3d 95 62 9a 31 +18 6f 4e 89 89 20 83 d2 54 9b 0e 63 8b df c0 d2 +7e 14 ec 18 c4 5c a3 58 61 df e6 12 a3 a1 ed aa +fc 72 fb 46 81 a9 9e a6 e6 48 be 89 62 f1 56 1e +75 0d 14 49 f2 3f 43 0a f9 30 72 25 54 4d 8a 8b +89 65 af 5d d1 8c b7 89 53 ce 6d 16 d8 5e b2 11 +af 0c 64 68 a2 af 9f 72 e7 86 61 b0 fc aa 48 15 + +# PKCS#1 v1.5 Encryption Example 4.7 +# ---------------------------------- + +# Message: +9a da 9c 10 b8 ae 22 + +# Seed: +cc 23 43 72 4a c5 0e e5 47 08 fc 5f d0 3f 09 a1 +cc 12 22 a4 4b cd 44 03 87 7c 6b de 86 bf 43 e4 +2c 10 84 f6 ef ff 20 fa c0 ac c3 1e ca 17 c7 38 +d4 68 68 73 65 52 fd 2f 7e 93 b8 22 25 61 05 4e +6d ad c3 15 60 4e af 8f 77 f0 5d d8 58 3a 93 bf +03 cb 9c c2 13 9b c4 19 bb 10 e9 b2 01 b2 a7 e1 +8b 03 79 0c c8 3e d6 05 d6 d5 66 33 05 34 71 39 +c7 5e 1a e2 a5 6a + +# Encryption: +9f 54 d0 de a0 5a 5d 00 72 23 5b c4 67 93 cf c4 +7b 00 6d aa ac 02 41 c7 e6 6d 33 3e 23 c3 cf 97 +63 b6 1d 9e ea dd d8 3f 5d 7f 0a a9 7d 16 c7 69 +92 55 cf 7e 48 72 b6 a0 07 95 62 d2 60 7d 64 40 +d7 ed 37 c6 71 3c e9 66 43 a4 41 f8 39 55 64 d2 +6a de a5 82 3a 49 42 da 4a b8 e4 7b ed 58 81 b9 +d1 84 05 79 57 df 65 39 e4 36 da 35 e3 0a 25 3a +f1 2d 54 1d 4b 0e f8 3c 5e f3 c1 35 ab 95 94 9a + +# PKCS#1 v1.5 Encryption Example 4.8 +# ---------------------------------- + +# Message: +d8 12 6f 4a 88 78 97 82 93 11 76 51 b3 0e 79 22 +d1 4a cf + +# Seed: +ad f9 b0 a9 15 2f 0e 6e c6 f4 39 59 71 ad 40 3f +02 e7 fa 98 f8 15 56 0a fa ff a7 ca d5 b4 47 4b +6e ce 65 ed ab e2 7e c2 4a 0a a4 73 ed 75 a6 1f +5c 24 90 a5 36 b1 a4 df 7b 03 41 77 37 c5 34 e1 +d4 5b f7 26 94 38 6b ee 82 0c 48 db d1 83 17 bd +61 7c 04 b6 a4 17 e3 0e ed 79 58 8d c2 3f d4 db +a1 37 44 b4 b2 aa 5a f8 0a 8a + +# Encryption: +3b 2b 85 ed fc d7 c7 c2 7b de de e1 c2 8a b6 18 +7a bf 1c 96 d9 45 30 07 92 cf 8a f1 97 c2 f9 a3 +91 b4 8b 83 32 cf de 7e 4c 7d c3 4c 42 30 29 56 +92 ce fd a5 ef b2 57 35 49 2b 9f f7 84 c7 ba e7 +35 11 c6 18 e3 aa 7b c8 7b c3 13 f2 67 09 a8 ea +4a d7 3a 34 9a b9 e5 ad 82 6c 96 ad 0e ca 97 e3 +13 28 6b cc bf 8e 33 c9 1f 03 68 39 b9 94 8b 4e +b0 c3 8e 21 3e f4 7f 77 66 1a 27 f8 cf e4 99 03 + +# PKCS#1 v1.5 Encryption Example 4.9 +# ---------------------------------- + +# Message: +f5 df 01 af e6 a9 22 51 8b 3f 4b 80 cd 4f ca 73 +b9 7b ab 61 71 6e 27 d2 51 bd 46 5f 4b 35 a1 a2 +32 e2 da 00 90 1c 29 4b f2 23 50 ce 49 0d 09 9f +64 2b 53 75 61 2d b6 3b a1 f2 + +# Seed: +6b f2 81 0d b8 fb 26 93 98 41 2d bb 88 06 02 82 +d4 5f be 96 27 33 7e 54 34 26 1a 5d bc 19 3a d6 +18 c1 1f 7b de c1 de 25 05 f8 60 37 fc 18 51 bf +6f b4 9d 23 60 62 73 47 49 9e fc 98 e2 92 05 da +90 6d 32 + +# Encryption: +40 12 fc c5 cf b9 78 de f8 8f b8 f8 17 4a a5 b4 +a3 07 75 ac 45 59 f0 b2 f3 d3 b4 38 9b 82 8a 79 +d1 40 25 10 c9 a0 33 7d 48 9d 11 82 ab 31 c8 38 +ac 7c 80 b7 48 60 9a 2a a5 37 da 7a cc 3a 4a 7a +31 d2 ad 25 2b fd 59 28 0b 3d 18 13 a2 6f 93 c5 +9e e8 c5 ee 68 87 18 f4 27 83 93 fe ce 32 3a 9d +ff 83 37 55 e8 9a c8 ee 1f a2 90 4b f2 4c df 4f +01 e6 ea ed b6 a8 ef 01 f4 07 be f3 30 9f 03 39 + +# PKCS#1 v1.5 Encryption Example 4.10 +# ---------------------------------- + +# Message: +a3 82 3f af + +# Seed: +94 f6 70 fd 82 f6 91 32 75 ee a4 c6 71 16 ca aa +bd 33 57 8c f8 4d 22 63 64 38 a6 fd 7e cf ee fc +0b 18 7d ec f7 93 89 1c 6e 4c fc 52 b5 67 d8 72 +bf fb ee 0a 67 47 2a 1a 48 c0 f1 ba 59 8a d8 25 +89 01 c5 6a 55 92 f1 41 14 7e 81 33 9d 74 7e 06 +32 de f0 0d 3d be e9 5c 4e 43 21 cc 25 b5 31 14 +47 a3 02 c5 34 92 9c f7 e5 34 f9 ae 67 f4 1e 01 +e2 2a 3d 7c e4 1b 3b 31 35 + +# Encryption: +7b 60 25 42 b6 4f 0a 1e 0e c2 aa 01 cb ed 37 7e +33 1e a3 ff 86 f3 56 fb 7a 58 83 76 4b e4 cb f7 +d0 75 4c 58 29 64 31 36 f2 57 23 36 a2 3f 15 41 +1d 83 85 14 a1 43 87 24 ad 74 09 e8 ec 8f e2 63 +41 ae ea 56 68 34 5d 0d 82 3f b5 c2 1d f4 59 e8 +bf 7c 15 b8 0b 07 2e 5f 8a 84 65 a4 4a a9 d0 9d +82 5c 03 15 a0 ec d2 d6 49 70 2b 10 9b e8 fe 35 +eb 22 84 3a 20 e7 fd 87 4f 1c 6b 46 a8 0b 68 df + +# PKCS#1 v1.5 Encryption Example 4.11 +# ---------------------------------- + +# Message: +75 b9 a4 a0 bb 2d 46 43 e4 78 f6 54 f2 cc 1a 8c +1b b4 67 19 76 0d 45 41 a8 a7 33 f3 3b 71 3d 32 +c6 0b fd 35 f1 61 74 83 48 47 e8 81 2c bd 7f 06 +ce 72 89 f3 72 c5 82 30 f2 b0 01 45 9b 5d + +# Seed: +49 a7 3d eb 93 e3 f1 be aa ad 3a 19 9a 70 56 9e +09 9a fa ca f7 a7 5f c4 ce 64 8f a8 2e af 2a 0f +e4 11 d2 64 fe 45 f7 45 25 c9 1f 3c 75 10 17 f8 +0a 02 ba bf f3 57 99 62 6f 2b 8d db 9f 36 91 + +# Encryption: +e5 ae e7 0d e8 62 72 3c 51 73 df fb f6 92 6c 3d +33 16 d5 90 9c f5 a1 d6 63 e6 80 ab 2b b5 76 e3 +5b 93 fd 43 27 43 a1 8e 8d b4 fa a3 32 f4 46 68 +a3 d1 9e 5e 69 57 32 f8 4b bd 86 d0 dd ed 76 65 +b7 0b 97 63 2e ab e2 36 4c af ef 7b 74 dc d1 bf +bd 62 5e 2b bb f6 65 4c c0 26 61 81 ac 0a 75 7c +3f ba bd 43 0a e8 63 71 eb 56 af 61 0f 77 cf 2f +ff 6e 24 8f 8c 57 91 60 b9 1d ce cc 0d 20 2b 50 + +# PKCS#1 v1.5 Encryption Example 4.12 +# ---------------------------------- + +# Message: +15 06 eb 34 91 78 5a a7 21 06 bf 6c 85 d0 10 02 +04 6d 1c 16 d4 35 dd 4e 7c 4b 7e 8e 90 dd df 16 +33 2f 94 f4 b8 35 d0 e4 ad 55 d8 3a 81 b3 5c 54 +b6 79 d3 cf + +# Seed: +f6 6e 6a 84 75 84 40 86 e2 84 77 22 97 46 80 1d +43 50 d9 ad 07 68 f3 c3 d8 fa a8 10 7d 95 fb 20 +5e 4b a8 c6 4b 73 8e 54 e5 ac 0d fe ab 99 6d 61 +12 5c 26 79 80 72 59 bc 9e 47 d8 bd d2 c0 40 95 +05 44 8b bf 87 2b f6 64 7a + +# Encryption: +d1 fa 39 52 cc 61 45 ff 77 1b 6c 5a 68 27 5b bc +22 d0 03 92 03 66 17 37 5f 0c 2b ec 3e 28 85 83 +ec fd c6 df 6a 82 8d e3 7f 77 c5 56 a8 cb c4 d4 +43 36 e8 d2 e3 05 87 e3 31 58 73 17 e9 7b 05 a3 +fd 78 02 5b 2d 49 6b 3b be eb 6c 72 5d 9e a5 61 +a7 32 28 82 33 d6 8b 79 49 7f b0 b6 fe e0 a6 b6 +8a c3 13 66 1b 4b 65 47 39 f9 18 f6 fd 3b ff c1 +7c 1d f4 1f 01 44 95 d5 5f 95 90 14 7b 82 d1 5d + +# PKCS#1 v1.5 Encryption Example 4.13 +# ---------------------------------- + +# Message: +9e 3e + +# Seed: +9b 3d df 17 cd 74 e7 6c 69 b5 ca 3a 01 0a 0e 0f +bd 17 05 d6 9c 30 74 35 3b e7 d3 c0 c2 05 f0 99 +c7 a8 10 b7 a1 ad e0 9f 5a 03 6b b7 69 ef f5 3a +53 d4 c6 f8 71 52 92 2d 9a 7b 86 ed eb a3 72 37 +d7 f1 73 4d 9d 97 39 38 3f 48 80 af 3a d6 88 87 +e0 fe 7c 87 a1 74 fb 32 38 b1 e5 1e ad 2a 84 34 +40 c2 b2 7f 22 dd a4 22 8d ce 70 f9 1c 98 d4 71 +a8 74 4d 27 65 55 79 58 81 02 44 + +# Encryption: +42 12 6b 49 2a 1e 7c c0 33 95 b2 ac 70 33 cf 6a +67 36 b1 2e 76 82 5a 17 3b 9e 01 1a e8 bf ed 44 +fe cb 8d 9f 58 cc e1 99 11 fe 42 d4 55 e2 49 20 +09 32 a9 b6 8f e2 e4 19 bc 63 9c 11 78 d1 1f fb +db d9 95 5d 45 9f 5e cf e0 90 20 09 8e 29 7b 8e +91 48 5e 94 bf 11 e7 bf 77 ed f5 a2 70 11 c8 2b +92 73 65 a1 2c 9c 77 c7 e4 9b b7 fe 2f 61 33 39 +de 3f 51 20 87 79 53 86 ca 58 5a 70 24 78 27 90 + +# PKCS#1 v1.5 Encryption Example 4.14 +# ---------------------------------- + +# Message: +70 aa 78 a4 d3 7f 74 c1 81 aa 27 40 7f 2f 9f e6 +63 a9 1b 16 be 9b ea 6f c6 12 88 7f + +# Seed: +d0 fd 16 c0 f0 d7 90 9a 38 86 17 08 11 e4 4f 24 +fa df 94 ff 17 03 9a 56 84 a0 9b 24 e1 93 3f a0 +c4 71 51 63 5d 75 7b 73 c2 3f f3 91 01 cb e2 52 +9a 63 a7 f3 a0 19 5b 6e 47 51 07 11 de 17 1a 16 +56 c9 ea b3 cf 82 d1 c6 52 26 b5 8f d0 fe 58 ec +31 96 24 7f 34 b1 a0 55 27 02 dc 03 75 12 c6 81 +04 + +# Encryption: +95 36 d4 7e 1d 68 7f 1f 24 99 6c b4 6c e9 46 ae +54 d4 a1 49 b3 4b 5b c3 44 43 a2 01 51 83 87 f4 +b6 38 18 37 cb 7e 4b 0a 44 75 13 70 42 f1 44 8c +1e a4 15 15 ef 31 c2 fc bf 62 e7 e9 58 67 b6 74 +ac 23 0a ed 9c 7d 8d 61 c5 27 52 b2 fc 2a 0b ba +fc 77 b3 1c 51 49 30 de 98 23 b4 38 b6 fa aa 40 +d2 55 31 03 3c 66 48 3f a0 02 3a f2 1d a6 4f cc +8b b8 c5 d5 2d 3f 6c 43 80 f1 d6 08 d8 c0 11 8f + +# PKCS#1 v1.5 Encryption Example 4.15 +# ---------------------------------- + +# Message: +01 16 a4 61 77 73 b6 dd b2 19 16 1c 4f d0 71 93 +7b bb 07 15 cc 62 7c 17 b8 e7 52 80 d9 9c dd 41 +6e a5 cd fa 09 06 b9 af 0a 20 cd 47 7f dc ad 14 +15 a1 9a 9d 1b 96 fd c3 c0 ed b9 + +# Seed: +86 b1 58 60 9b fa 08 a8 ed e4 ef 3f 23 e1 2e b5 +0d 24 55 74 26 4d 76 4d 87 12 67 db 8a 95 24 ea +3f a2 e3 84 5f fc 29 1b da 98 99 89 bf 71 5a a2 +b0 8c 49 79 8a 81 9f 68 58 d9 fa 35 f9 4d f3 c7 +e0 86 + +# Encryption: +74 a3 df 38 5d 20 87 7b ca 9d bc eb ca 2e 53 2c +6a be 95 62 d6 81 7b e1 6e 11 8a 60 f4 ab 0a 1a +c0 a8 46 66 53 a8 f8 17 0e 35 fc e1 4b 44 9c d5 +9f 55 8e 02 0a 89 88 94 bd 2a 71 75 58 e6 65 0f +3a 12 85 70 d8 c1 69 a7 74 66 63 c1 d7 ef 62 14 +5f 4b 75 c5 fe b6 38 6f db 85 33 94 c6 59 a9 1a +a2 aa e0 3b ef 91 13 dd 49 28 ff 28 b3 80 92 7a +d1 ba 4e 8a 37 ed d1 72 ef e8 e9 ea bb 61 4d 83 + +# PKCS#1 v1.5 Encryption Example 4.16 +# ---------------------------------- + +# Message: +15 c5 fc c7 54 7d 63 76 1f 6a f1 f2 6e ed 9b e8 +13 4f 9f 92 12 7e 76 b0 3a 33 a9 7b 9b e3 f7 8b +2e 22 fc 7c 85 06 99 a1 5c 0e 0e ce be 2a 71 80 +5f 02 4b 93 88 a3 bd b2 b3 60 d6 9c 5c 0c 46 + +# Seed: +5b 4f 17 a9 de 91 73 7a 7f e8 54 e8 a1 76 be 5a +0a 16 fc 10 42 cb 87 0c c0 18 92 fc d3 8e a7 5b +07 3c 0f fa 01 4f 96 a3 58 e3 aa 5e 73 ea f8 a9 +1f ce 75 47 0b de 64 e8 7a b8 91 ba 3b f2 + +# Encryption: +73 62 d7 39 8d 0c 25 1f 83 58 17 e4 79 37 a9 25 +58 36 ca 02 30 45 7f f6 08 b0 78 d5 09 31 a8 80 +33 ea 76 50 81 12 65 f8 e2 68 b5 33 15 d8 43 8e +52 a6 a4 b1 b3 89 5d 30 c3 da e1 1a 3b 8e a8 c3 +0f 05 e9 d7 1d ef 46 d4 51 11 92 a1 0f 54 21 8d +39 36 cb 17 98 3a 1e 7a ff 18 18 89 39 b9 46 92 +76 49 b0 fc 4f 7b bf cb fc 14 e1 c0 ec a0 7d 00 +c9 03 db 78 16 9c 50 ef 0a 38 f1 da 19 ae 44 59 + +# PKCS#1 v1.5 Encryption Example 4.17 +# ---------------------------------- + +# Message: +7c ad 18 f1 75 13 87 42 28 5e 90 35 d1 3a d4 1f +c3 a8 52 10 e1 54 4e 24 de a3 fc fe 66 + +# Seed: +9a 06 ca 10 fc c6 61 0e 77 df f9 0d d1 76 f8 2e +3f 96 e4 a9 d7 ab 87 2c 74 8e d4 22 f3 4b 33 48 +61 94 40 f0 aa a2 2a 66 98 51 da c8 89 4a 8e fa +34 ea 2c 2d a5 e9 58 69 e0 ad c0 05 a4 9b a4 58 +18 ca a4 74 11 5c 34 49 96 6a 85 c4 18 fc aa 8f +45 63 0e fe 0b 1b 4d 3d 69 be 1b c0 06 8a a7 99 + +# Encryption: +1e fa d4 14 46 b9 1f da dd 8b 80 61 9f 68 27 36 +68 b7 58 5f d9 1f 34 49 ec 85 c2 42 d0 84 9e 4a +53 a5 97 7b 61 aa 40 d1 2c c4 85 ec 7e 4f f2 0f +98 86 91 cb 9d 73 af 46 ea 37 6a fc 69 ba 22 33 +86 e9 f1 5d 03 26 97 da 75 e2 f9 52 be 2a f0 62 +e8 24 6c f7 49 b8 9c 4c bc d6 4e 23 f8 82 bb 55 +3c 3c e3 05 20 36 22 b5 a7 39 77 35 a6 34 aa b0 +d1 7e f9 b5 55 9d dd 34 f4 87 2b 56 e7 98 6e fc + +# PKCS#1 v1.5 Encryption Example 4.18 +# ---------------------------------- + +# Message: +fd 98 c3 8b e3 19 30 70 b5 c4 33 4b 11 c2 5b 33 +4a 44 + +# Seed: +f3 57 91 11 03 e9 87 d1 a9 f1 5c c2 e5 2f 42 39 +0e 0f aa 50 02 c4 f1 7d 40 a4 af 50 f3 1a 23 17 +50 e7 af 61 d9 af df 9c aa 38 61 a2 0d c7 21 89 +58 61 fb 11 8e 08 8d 32 18 e6 fb 35 56 b1 62 d6 +bd 67 91 1d bc 94 21 98 42 65 82 72 a5 d4 9b f5 +ab b4 a0 87 94 95 c5 e6 e6 86 28 59 29 a5 5a 36 +8f 52 4c 14 a4 0b 0c 61 38 0d 0e + +# Encryption: +de ae 18 3b 56 c3 fb 38 41 ea 57 42 34 ac d3 0a +ff 00 d0 05 1f 57 80 37 58 a4 71 4a bc be dc da +8b d1 a4 8a 98 01 53 df 89 6b 13 76 aa 4b 45 95 +80 13 d6 19 be 7e af f6 c1 a6 75 e2 92 ef c3 f4 +39 3d db de ab 47 e8 90 a7 8c ef 69 00 24 49 57 +87 48 90 6c 10 21 b8 91 b9 43 d8 18 d3 a6 1e 67 +a3 15 61 2d 4c b1 cf 19 7c e5 df ab ef da eb 59 +0b 8e 8c 73 68 5e 74 7e 59 a3 95 c8 45 c5 d0 c3 + +# PKCS#1 v1.5 Encryption Example 4.19 +# ---------------------------------- + +# Message: +96 53 d7 94 69 f0 5d 40 19 65 a9 5c e8 74 fa 22 +5e c4 79 74 e8 d0 68 41 c1 3b 47 85 e0 0d 54 7f +9d 31 44 c3 87 9e 6c cd af 78 7a ef c2 f8 45 2a +4a 3c 88 4e 38 ee + +# Seed: +85 5d 6d 15 12 e5 43 a4 5d 3a 9a a9 68 5d 5d fd +a7 04 79 ba 39 52 63 64 14 1b b6 36 27 45 89 85 +71 20 01 22 f4 bc 82 c6 22 43 45 c6 9d 3e f5 42 +f1 23 bd e3 01 5b 60 c4 c0 ff b9 8d 63 01 31 ae +e8 1f e4 a0 b0 15 38 + +# Encryption: +69 ca 62 e2 9a 5b db 4b 04 e2 40 16 21 2c 25 91 +40 a6 0c fa 81 eb 66 93 bf fa fc 9f 60 0d ce 10 +82 2a 00 7b 6a de 93 fa cd a1 b2 b1 65 b5 57 76 +0f 0a 67 5a c9 bc b2 06 b9 64 fb 90 cf 6a 2c f9 +9f 18 6b 36 d2 eb 99 1d 82 53 a0 75 4f 9c c2 d7 +2d e5 49 ab ae 90 94 f5 a8 6c e1 db 49 4d bb 6e +51 62 86 71 5b 3d d4 05 59 b3 10 7b 95 24 b7 29 +ac 65 4c fb 40 f9 ab 35 d0 34 e0 27 19 7c bc 36 + +# PKCS#1 v1.5 Encryption Example 4.20 +# ---------------------------------- + +# Message: +0b df 3f ce 8e 48 7d b2 2d 07 60 ab 71 15 86 ca +8e 45 9c 39 4f f8 b1 a1 86 70 67 a9 31 51 99 a8 +01 24 74 b0 f9 0d cc 87 cb + +# Seed: +c9 b7 8d ce 9d fd 7f 04 04 ff 98 2e 06 b5 96 50 +ba fe 31 ea 19 bc 1f 2e 1f 39 89 f4 ce fc e4 6f +c6 52 42 3d b3 c9 9d 92 a8 fb 58 f3 ee 39 3d 55 +5b 76 84 88 9a 4b f8 15 a1 3e 3b 9b f2 43 71 40 +66 b9 07 58 90 67 50 47 f1 7e 93 5b dc f0 e6 6f +cf e3 9b cf + +# Encryption: +43 ad 3e 62 5f b1 72 15 57 8b ef 2f 46 5f aa 72 +ae 69 43 83 36 9f f7 aa 15 12 01 a3 f2 59 c8 d8 +ce 8c 16 bd 25 52 21 49 f6 66 e8 d6 92 a0 79 5e +a7 15 69 d2 88 1f 97 07 08 5d 3f 59 bd fa 28 73 +66 d7 f5 a3 f7 6e a5 dc 10 9f cb 03 30 2d a0 b7 +86 99 71 3e 0d 30 09 58 4f 97 17 6c 1b 9b a6 3e +80 cf a8 fd 4c 01 3d 74 b5 fa de 84 72 d5 2c 11 +e2 e9 36 81 ba 19 d3 53 d3 1c e6 fa 3c 0a b6 0d + +# ============================================= + +# Example 5: A 1024-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +ab 29 d4 9c dc 92 5c 69 ca e7 52 92 fc 03 62 03 +73 c6 fb 36 d3 c2 49 dd 5b b5 0f 88 1a 4c 93 89 +af e7 3e 8c 56 b8 d6 67 a5 ea f2 b5 71 4a da f4 +ca a0 06 a4 9a c4 bd 4b 91 d5 45 cf 3c 10 00 9d +31 8a 9d e0 f3 bb d8 38 4e 8c 7e 96 ca 15 95 e3 +2a 70 41 d1 68 ca a7 34 43 b8 85 bf 7f 61 4a e1 +21 2e 3b 5a dd a2 9d fa d5 01 b8 b1 a8 1c 3f 48 +a4 56 e1 33 ad 52 da 2a bc e5 d6 e7 82 f2 75 c9 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +ab 29 d4 9c dc 92 5c 69 ca e7 52 92 fc 03 62 03 +73 c6 fb 36 d3 c2 49 dd 5b b5 0f 88 1a 4c 93 89 +af e7 3e 8c 56 b8 d6 67 a5 ea f2 b5 71 4a da f4 +ca a0 06 a4 9a c4 bd 4b 91 d5 45 cf 3c 10 00 9d +31 8a 9d e0 f3 bb d8 38 4e 8c 7e 96 ca 15 95 e3 +2a 70 41 d1 68 ca a7 34 43 b8 85 bf 7f 61 4a e1 +21 2e 3b 5a dd a2 9d fa d5 01 b8 b1 a8 1c 3f 48 +a4 56 e1 33 ad 52 da 2a bc e5 d6 e7 82 f2 75 c9 + +# Public exponent: +01 00 01 + +# Exponent: +07 7b b2 73 32 34 86 ec 4c 25 ed 67 06 34 1a a8 +a6 7a ec 58 43 0d 53 3f e5 86 c6 b9 4f 57 0a 3b +42 90 c4 5c 0b dd 94 68 1f 29 a4 b7 58 8e ea 80 +39 cc a1 c5 b8 0b 82 70 27 9d d0 a9 c5 09 39 11 +93 e3 d5 c2 5c 10 75 c4 a1 d3 dc 32 74 06 6d ab +81 7f b5 1b 16 bc 26 7e d9 a9 98 0f fb c0 92 85 +d9 7f 11 2f 15 26 95 e6 e0 9c ae 72 bb 55 06 6c +b9 db d0 98 a7 5c eb 47 b4 62 72 00 5c 6b d2 15 + +# Prime 1: +e9 4e a6 b6 19 be c3 e4 78 87 8e 87 8c f1 23 b7 +a9 f1 2c ab b1 95 e0 aa e0 22 f3 17 73 46 69 31 +38 b1 1a 86 fa 5c b7 55 5a 10 b8 e4 62 2c e9 52 +0c 57 2b ef 29 1d f7 0a 16 d8 85 f5 97 e5 90 4d + +# Prime 2: +bb cf cc 5a 60 95 34 ee 43 4a 6c bc a3 f7 e9 62 +e7 6d 45 5e 32 64 c1 9f 60 5f 6e 5f f6 13 7c 65 +c5 6d 7f b3 44 cd 52 bc 93 37 4f 3d 16 6c 9f 0c +6f 9c 50 6b ad 19 33 09 72 d2 1c ac 19 ce 99 6d + +# Prime exponent 1: +e8 a6 0d 88 39 54 09 73 a2 dd 4a 3b d1 48 05 1d +f8 d1 0e 82 87 ab b5 45 b0 0c 29 ec 90 7e fe 16 +9f 39 bc 02 2d 56 97 5a fd 5c ff 82 7e 83 da 86 +7e d7 ce 6f c6 c8 a2 b7 e4 e0 35 75 19 eb 49 61 + +# Prime exponent 2: +8f f2 e2 27 37 35 c5 5f 05 56 6a e7 5f 29 a9 c9 +33 a6 2d ef d7 e2 20 01 7f 05 45 fc e9 07 e0 65 +c4 9f 7b ac 34 84 c6 f0 60 49 99 43 32 07 c9 13 +e8 0b c0 1b f7 8d 83 ef af 00 da 17 12 a4 a6 35 + +# Coefficient: +5f 1f f9 6a 8a 90 19 78 4f 92 26 e2 5c 9b fe 25 +08 02 39 43 73 90 25 dd 6b ab 03 7f f4 7d c6 42 +49 85 15 c2 f9 e6 ff 60 60 c5 b7 d2 34 30 d8 d5 +0f 1c 0f 6d 50 c1 80 b4 ae a8 a4 a8 2f cd 2b 74 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 5.1 +# ---------------------------------- + +# Message: +5d c9 f8 b1 2d c8 12 a0 9a a4 b0 6d fc b5 7e 1d +2e 8d 1c 7d 2c 07 6b 25 d5 c1 8e db c0 46 bd 63 +c7 ca 4a 59 9f 18 de 26 f3 be 73 8c c2 8d 16 67 +2c 00 6e 4d 9c + +# Seed: +43 d6 05 a5 74 0a 97 0b 32 37 27 af 35 2a 1b d4 +8d e6 9d 95 05 e2 2c 2f ad 03 0c 3b 84 b6 de a2 +d2 2f 91 64 06 a7 69 3c f5 06 c2 d2 51 88 6f 02 +20 3e 3f 76 55 a3 0a 68 37 af 8a 8c be c7 b5 c9 +2f c0 4c 8c 18 df e9 d3 + +# Encryption: +21 5a 35 f4 c0 43 5b 07 ed 5d 2c 4b 68 65 bc 28 +1c ea 70 50 cf ea 7a 7e 86 e0 3f 8a cb 28 b5 8d +be e6 54 58 91 9c ea a5 a3 3e dd 98 20 1e a6 e7 +63 2d 76 22 d5 a5 1d 35 a3 5f ed e8 6e f2 03 ee +f6 eb 34 75 ec 8f 19 e6 9c 0e d5 2c 05 dd 7d 59 +e3 53 f5 2b 67 10 af 40 26 65 55 04 10 7d db 86 +f9 57 e6 c0 6b a6 7b 1f 4f c9 f1 21 e1 5f 82 73 +67 09 d2 de 8d 77 43 2d f0 8d cc d2 a0 cc 77 04 + +# PKCS#1 v1.5 Encryption Example 5.2 +# ---------------------------------- + +# Message: +d7 74 07 d8 f6 9f 80 dc 08 eb a5 f4 26 28 2d e7 + +# Seed: +b8 29 c7 89 be 38 1c d5 9d e2 14 89 db a1 41 e0 +bd 1f a8 a3 c3 82 6d 59 c6 d1 10 e7 df 72 42 ba +98 c4 7a 43 92 c7 f2 ac 1c 6e 9d ae 22 b9 eb 74 +a7 64 36 08 8b d0 ba 6e 19 91 e1 9e 3a f7 9c f3 +f7 de fb 6a 11 61 80 25 34 ba 0e 7e d1 65 34 93 +88 72 ec a6 77 05 8a c7 34 67 d4 9e d1 12 5b 50 +df e5 d6 d6 5a 5d 24 53 99 b6 bf 1b f1 + +# Encryption: +2d 48 06 cf af e4 af 36 bd 02 f6 2d 6a 43 b0 0b +41 6f 70 8e 96 85 b1 7a c8 e3 a4 d8 c2 91 80 93 +05 76 9d 78 98 f6 fc 85 91 7b a2 fd 8e 58 9f f7 +a8 bb 84 bb 7c 12 20 2e d2 79 e0 64 09 a5 c0 a7 +d3 24 bc 46 ae 4f 92 82 c9 02 3d 3d fb 3a 79 15 +de fc 16 4b 3f 08 26 6a cf 12 41 f8 26 24 98 15 +07 41 4e 56 29 78 35 1d c8 b7 a7 9e f5 31 40 21 +01 a8 d3 d3 ea a3 53 9b bf 62 aa d9 9a 3b b1 1e + +# PKCS#1 v1.5 Encryption Example 5.3 +# ---------------------------------- + +# Message: +23 8a + +# Seed: +a5 88 1a cf f3 52 9f 25 1b 1b 9c 61 9c e9 f9 df +91 e0 a0 3d d8 89 16 36 46 87 1a 62 72 07 ee f1 +47 68 0c 32 f4 50 a7 76 e1 9f 54 ec 05 5d c6 8b +04 bd 4d 89 37 6d f3 ea fa 6f ca f6 0e b8 31 84 +39 10 b6 25 b6 4f 25 d9 29 9a fc 30 6a 23 76 53 +80 45 51 94 b7 5d c0 13 5d 27 c3 b7 d7 2d f9 08 +77 5c 7e 90 be fc 0c 5a df 74 a1 69 ed 58 68 f3 +d6 34 32 7a 05 78 18 92 54 45 43 + +# Encryption: +77 10 ee a8 65 7d fd 15 65 16 65 62 df 0e 2e 84 +0e c3 e3 de dc 0b 80 2b b0 21 3e 47 a5 ce 97 f4 +b8 5b a9 ba 14 19 77 36 3d 8f 54 b0 6d 57 8d 5b +2a 96 e9 69 cf a9 15 df 21 9f 00 2a 85 d0 32 57 +04 7b 31 16 a1 c4 dd af 79 1d 93 98 2d 1b 9f fa +24 31 86 e9 e2 b1 9e f0 74 1c e9 8d e2 a4 a1 58 +6e 50 12 c4 81 de 23 a0 ef f8 82 fd 62 38 38 d2 +01 1f 4f 63 73 8a ff d7 ef b8 c5 0f 46 a6 c2 0e + +# PKCS#1 v1.5 Encryption Example 5.4 +# ---------------------------------- + +# Message: +25 a2 7e b1 b2 1f 10 cf 9d 57 1c 33 05 61 0b 97 +f0 da ee 39 90 5c 65 94 bf bf 45 2a 9a 00 d9 e8 +2b + +# Seed: +25 04 61 80 11 c6 73 db 3c 41 22 79 dc 8a d1 65 +ab 7b 64 73 ae 19 5e 8d 6d 41 21 49 18 19 8b 34 +51 a6 50 8d 61 38 ce dc 51 8d 80 12 ba 0e c7 9b +38 6a f8 fa 40 b0 34 78 bb f2 ba 06 5e 58 2d 61 +95 cc be 15 8f 11 78 1e ae b1 b1 72 0b 72 d9 b5 +21 27 de b9 55 17 11 e8 87 db d0 b8 + +# Encryption: +35 72 bd ea 23 05 e1 78 5c 75 4d e7 44 c4 fa 3f +a2 cb 75 71 60 e5 cb 39 a3 14 97 e1 48 5b bd 7c +08 99 c5 35 85 b2 bb bb d9 90 81 b4 16 ef c6 85 +78 db 78 e0 ec d0 8d a7 a3 95 3e 38 6b b2 5c 12 +bb b8 7c 78 94 42 83 a8 c8 01 87 b4 50 8d ab bc +76 97 f4 3a 8a e7 8a 33 fe bb 15 f3 cd 58 1c 80 +d4 9b 97 1b cb d4 8e 44 14 2f 58 c2 c9 1a db 1a +e1 45 aa 9a 83 b3 c5 81 5a a1 a8 ff 8d d2 31 fe + +# PKCS#1 v1.5 Encryption Example 5.5 +# ---------------------------------- + +# Message: +59 cf 0b 6b 50 ea + +# Seed: +2b f1 91 60 df 69 88 93 5b d2 46 10 6b 89 09 dd +7b b3 e5 16 90 df 84 d7 6e 4d 31 ac 82 10 44 56 +34 6b 4c 3c 9b a7 b5 e9 e6 8e e2 08 6c 84 73 c6 +83 02 e2 59 9a bf 6b 31 ce b3 f7 81 ad 6b 56 89 +86 f2 1c d6 d7 55 32 8f b8 3a fd 55 48 50 1d 07 +0a c2 dd 8f 5c df b6 2c ef 54 5e 81 5f e3 82 bc +0c 67 b6 76 e5 45 6e bb 9a b6 7d f4 77 40 c6 a4 +3d e3 f9 a2 47 7a 9b + +# Encryption: +2e d5 91 fd 4b 35 7e 94 f4 81 ba 84 ff 4e be 7a +e4 31 05 4e 5c d9 8a 99 58 96 48 e6 16 cd 68 e0 +d4 72 4f a8 a6 c5 99 68 6b fe e1 74 7a d0 77 db +ed ad 45 f1 24 4d 7f 8e 00 da 3a 3a 06 d2 31 32 +d3 17 1d 74 4e f1 4e 1e 97 cd da 10 9b d2 e5 56 +a5 fc 7b bc 60 9a 7f f2 4c fa be f4 b5 6c bb b7 +0e 05 06 53 b6 98 48 d7 11 30 75 a5 de be 7a 46 +82 15 f8 dc 08 e7 ef 84 fd 55 77 8c d5 b5 96 e5 + +# PKCS#1 v1.5 Encryption Example 5.6 +# ---------------------------------- + +# Message: +e9 44 52 f5 0a 5e db e6 75 73 ab 22 30 9f a2 1b +ab c6 d2 25 20 e6 e8 3b f7 2e 7a fa 6d 71 e2 02 +96 da ea f5 4a 60 c8 03 63 04 87 9a 21 31 d1 78 +78 0e 34 8e e0 12 0b 99 7c + +# Seed: +c5 30 44 3a 16 ef d8 d6 d7 2a b4 44 3f 8d b2 44 +91 de 99 d5 aa be 51 88 b3 f6 1d c0 48 3b 7e e0 +0b 1c 13 25 9b 8a e2 40 9f 1a e6 2d 99 30 c1 1a +4d de f3 e8 35 82 93 88 93 f9 ac 66 8f 79 c6 4c +7f 5d 79 6d + +# Encryption: +0e ee 90 c7 08 18 22 1a e2 70 4b be 38 d6 8f 8e +15 4c 6e e7 ad e5 3e 2a 1f 4d 1d ba ac 98 c5 75 +91 eb b6 c6 38 bc b6 8e 18 14 35 b7 00 01 ba d1 +80 19 2b fd a0 57 32 c0 5e 7f b5 af 22 aa 89 d2 +a8 ff 80 cf 9f 08 62 f0 4c 05 ca ca 3d 2a 3a 5b +07 79 94 6c 6d df a0 4c d7 9f a1 64 d6 02 f1 b7 +de 5c 95 be 85 e9 60 84 67 e2 5c 29 d0 35 c4 66 +09 06 26 9f 6d c0 0a 47 2b 04 46 ea 56 e7 2a 59 + +# PKCS#1 v1.5 Encryption Example 5.7 +# ---------------------------------- + +# Message: +1c bf a0 e7 b1 a1 0c 13 d7 50 77 b1 cb d8 03 10 +cd 24 10 34 0d 5f 53 72 93 46 4a 67 81 a9 cc 30 +2c b5 38 0e d9 26 7b 3e b2 3c db 13 + +# Seed: +d3 6b 7e 17 99 05 9d 1e d1 34 7b 0b f8 24 7c 6b +e5 18 7d 8f 15 21 9e 3c b6 6e c6 2e 1a c4 1f f7 +ed 35 7e d7 ca 03 84 e3 1d 39 94 85 61 fc 16 cb +d9 6b 7e 70 42 79 e5 72 bf 56 4e 06 c3 a3 40 1a +27 14 dd 51 d7 21 5b eb a1 c6 61 54 f6 0d d0 cd +4d + +# Encryption: +9c 03 dc 01 33 a6 e6 aa ba 92 05 9b df 5a 6c c1 +b1 44 b9 0d 2a 94 a4 8e 7b 3c b9 0b 0b b6 f6 24 +c7 b1 d1 72 33 1e 43 23 d0 8d 2e 8e 09 95 32 dc +b3 b2 a8 7c a4 20 74 9f c6 34 5c 0d 86 e9 ab ca +71 af 09 a0 92 9e de ee de 83 e7 22 44 20 3b 2b +f4 5c eb 18 7e 9d b3 c7 d3 ad 05 b2 3b 59 62 4c +24 66 96 cf c7 58 06 39 14 02 e4 44 e3 97 49 69 +88 e1 e1 f4 2c 6a de d3 0c dc 93 79 37 f3 00 54 + +# PKCS#1 v1.5 Encryption Example 5.8 +# ---------------------------------- + +# Message: +e1 72 a6 b8 b4 96 f0 77 73 8b 74 f6 d8 b2 92 dd +a6 07 f2 ad bf b3 72 be 37 ee 00 08 88 be a3 1f +99 cb a1 cf 39 32 e4 be 37 17 c9 e1 68 90 1a 32 +d1 b8 20 be 4f b0 13 75 27 a2 48 18 77 fe 01 ee + +# Seed: +84 0c e1 3b bc 96 17 dc 9f 3f 26 b1 47 30 1a 6f +46 30 0d 77 81 a5 d9 81 16 2f 86 92 87 37 1f 1d +59 58 76 4f b0 0b 05 53 70 ec 71 1b ba 52 83 fc +b0 0b 83 bc 02 17 5e a1 01 7b cc 83 53 + +# Encryption: +99 3e 39 6f b5 7b 2e a6 a1 a3 fc ed 9a 69 d3 61 +cb b6 26 5b 26 50 3c 17 5f 84 c6 1a 41 ea 3e 1c +e4 fb b6 2e 01 d6 42 0e 22 fe f1 d9 e2 8a 58 83 +e2 ea c8 2e 05 f3 58 ea 75 f7 7d a4 89 7b 6b 64 +9a a4 74 28 39 41 93 dd ec 64 8c 3a 7f b8 1c fc +f4 b5 1c e3 eb ba 78 ae dc a7 bb 91 7b 35 b3 e2 +2a eb 20 1c ea 96 59 2e 50 e0 d2 84 1e 7d 2c e0 +d6 9f f3 03 9d c0 1e 96 4a 97 7a 01 76 83 b3 87 + +# PKCS#1 v1.5 Encryption Example 5.9 +# ---------------------------------- + +# Message: +c8 f0 ea 23 e0 66 11 e4 fd 27 b6 1d b7 92 0c 55 +f3 c0 a2 22 12 88 38 e4 cd b0 62 e1 76 b2 1f c2 +32 53 55 8c 5d 40 de 2d fd 62 0f b7 cd f1 39 9c +2a f8 fc 77 ca 33 35 + +# Seed: +16 4d 77 b5 d2 6a e6 d7 ab e7 ca ed 62 5d 87 c2 +11 cc 50 9a d0 17 2c 20 83 3d 8f 98 ca e3 8a 2c +37 0e f2 1d 40 96 da 84 1d be ee 94 8e c6 34 03 +ca bd 4a 5f 71 ac e4 93 64 aa 7d e2 0f 32 c9 88 +33 7a 11 5f 83 46 + +# Encryption: +7a 8f 15 ee f5 10 ad e8 d5 c3 17 f9 06 4a d7 da +e6 c9 3e 7c f1 56 a7 37 22 02 32 58 f8 b5 74 47 +34 70 00 34 a3 de 6f 13 7a f6 e9 00 46 d8 6e 9b +90 59 0f a5 a6 50 ce f4 fd b4 d3 36 02 33 af 86 +f4 a7 a2 3c 24 3d 19 51 c6 66 b6 73 c3 3c 7d ec +4f 51 ac e3 4b 80 5c 0a 9e 67 e2 09 cc 7f 9e d6 +9b 8f 5e b5 c5 53 e0 f1 5c 10 30 4b f5 6d 7b e1 +71 f3 1c ce 88 f3 7d 1f b4 a2 a0 04 18 89 75 76 + +# PKCS#1 v1.5 Encryption Example 5.10 +# ---------------------------------- + +# Message: +19 db 24 22 05 c0 3d 7f a9 93 5d 9e 04 fa 6e cf +38 a5 1e a9 98 ac 8e 4b ac a6 cd fd 6a 0a ce 1d +f3 67 e7 3d 23 c2 40 af 76 b6 2e 9f e9 21 5f e9 +43 + +# Seed: +be 49 52 05 55 69 56 fa e2 a2 2e a7 0c e1 02 de +06 6c 9e 58 95 96 06 21 74 84 a5 b1 50 36 ff a1 +d4 61 23 9d d4 7b 4f 38 1c ea 71 51 6e 2d b0 fc +36 9d 72 b4 40 69 65 12 a9 72 88 f0 6f c0 bc eb +96 82 86 e9 95 e0 2d 21 8d 9c 26 62 + +# Encryption: +55 12 b3 99 9b 30 c9 c1 44 0e 59 75 93 1d 55 f2 +1e 9e b4 22 b6 2d af cd ab 5d 50 03 a7 5e b1 24 +81 99 86 36 19 13 36 1d fc 46 ac 29 aa ba 8e 1a +a0 2e 1b a4 44 67 16 2d 20 f6 3a d1 70 fe 0d 87 +a5 3d 93 c6 4e 02 6b 12 be 6b c2 b8 eb 0e 57 c0 +39 eb 60 f3 2c 4b 52 70 35 f7 03 a7 a8 37 4b d7 +fa a7 b5 40 4a 3c 5a ad b7 92 e2 5f f9 28 76 b2 +3d d3 a7 42 2c 45 26 6c 6d 98 6e ec 53 34 b9 ba + +# PKCS#1 v1.5 Encryption Example 5.11 +# ---------------------------------- + +# Message: +49 a7 61 f8 c1 8e f9 23 62 d6 ab b2 4c 07 fc 72 +82 55 84 24 53 69 4e 17 60 58 99 f4 37 b3 1a c9 +8d b5 16 + +# Seed: +d8 cd 85 ed fa 0a 84 d0 76 a9 f8 b2 f9 3d aa eb +a9 ae 37 43 81 ea 4f 8c ea bc 14 f6 2a 4e d7 63 +8c 1e 39 67 57 de 3a e2 b7 ef a3 a1 7c 9a 55 86 +da 84 a5 e5 0e cd ed 61 08 7f a6 f0 ce 93 82 87 +99 8a c1 b9 bc 33 21 a7 ed 16 0d 28 67 04 e0 52 +6e ce 7b 30 b4 68 14 64 9f ec + +# Encryption: +9b 47 82 68 40 62 12 ca 05 30 f4 31 bd b2 63 72 +61 50 84 ca 48 8d a4 34 51 d2 5a 22 b3 5a c6 fc +61 e3 70 74 a5 c2 2b c1 c7 01 db 19 32 b8 c5 57 +b8 48 7c ea 56 60 50 e4 8a d6 e0 37 6f 8d b4 19 +8c 4d 27 db 2e 6b 28 c2 5a ed 83 7e f4 77 42 d5 +eb 8e b1 d8 b4 32 c9 d5 73 cd 4b 86 fd f3 2c 52 +a3 d0 f6 cf 92 cf 3c d9 51 96 77 a5 8b 1d 1d 99 +4f c1 c9 05 7a c1 06 e8 16 04 59 26 b4 5b 00 e5 + +# PKCS#1 v1.5 Encryption Example 5.12 +# ---------------------------------- + +# Message: +84 e8 28 f7 15 f2 28 a6 02 65 + +# Seed: +f7 f2 75 a8 53 d4 e1 26 d7 d0 c3 8e f7 03 f3 fb +da 7a 95 20 78 8d 7a 81 a3 1b 05 30 d4 3f e6 c9 +4b 1b 1b b1 08 51 20 9d b2 6a c4 b8 88 ae ce ea +77 13 82 4c 29 38 b4 c6 43 1b 2b 03 c6 93 ab 7b +54 63 15 41 54 6a c4 03 94 79 85 48 fb ba 95 88 +2d 91 a1 7c 27 e7 dd 53 02 6c 96 79 1e e5 5f 24 +7d 7f 89 8f ea b3 70 9a 13 2a 78 26 66 a1 4d 0d +f1 a8 4e + +# Encryption: +4e 3f e9 6e 8f 96 e5 b3 c6 11 ca db 96 ed 51 04 +20 98 ec c5 47 be 7b 88 f8 de a7 65 ae 14 e8 35 +0c fe 39 dc b1 c1 d6 e4 17 9c a4 04 d5 38 4d 87 +b0 66 50 75 ee d7 da 7a af 71 00 8e 24 67 d7 0b +ff f6 23 b4 59 4b 6d ff f9 0e 3d 84 85 f9 41 89 +48 6c a0 ca 9e 72 2b 2a 77 7e 25 b5 82 f7 ad 4e +c5 10 3a d7 67 85 9a c5 9a 1b 8c 5c 19 71 30 17 +48 fc c2 64 f6 c9 29 36 4a 8d 9a f4 22 55 c0 f6 + +# PKCS#1 v1.5 Encryption Example 5.13 +# ---------------------------------- + +# Message: +c4 79 7e 8a 6f 26 9b f2 5d 4c b4 ec 3f a4 6f 8f +11 e6 b3 69 fb da ec 1e 51 97 83 58 d4 6f 3c f3 +b8 42 91 7d 96 7a a9 d3 0b 18 34 53 93 7a 68 26 +56 b2 7b + +# Seed: +17 77 42 19 7f 04 11 44 3b d8 7e 28 ea 88 d5 4b +4f 2c 7a b1 dc ae d8 1a 56 f8 d7 87 91 12 44 54 +02 85 04 d3 22 e1 de 34 60 47 a4 93 93 3e 87 62 +8c e0 8b 06 c0 17 08 2d cc d3 8b 48 94 65 14 ea +37 7c 2d fc 75 2a dc 24 fb 57 + +# Encryption: +79 84 c3 ba d8 6a 54 79 90 e0 47 5a 48 4f 8d ba +5d 4d ce b0 d3 e3 fc e0 71 d6 f8 71 76 b7 cb e6 +f8 11 2d 81 d7 cd aa d7 7e d0 d5 78 8e 65 f8 bf +5f 0c 2a d0 df 07 cc df 54 b2 da ce fc 19 ba 65 +20 1c cf d3 61 d1 86 b7 d9 e2 69 aa 1e 6a d2 c7 +2b d2 3f 58 08 4f db c3 bc 60 e1 7a 33 e3 c5 5a +95 eb 0c 38 a0 81 bc 0d 39 81 db 26 a7 21 2d 6f +69 1b 33 6d ac 46 b6 4a e2 25 38 a7 b0 08 7f 25 + +# PKCS#1 v1.5 Encryption Example 5.14 +# ---------------------------------- + +# Message: +a5 e9 de b1 c2 0f 98 2d 5b 7d 4b 87 d7 99 46 1f +05 3d 91 9e + +# Seed: +59 75 9c f5 f8 38 d9 52 49 3d 0f 42 81 e3 ea 0f +e2 16 97 1c 0a 2e 24 54 b9 6c 8a 11 b4 c6 91 27 +15 90 24 db 6e c5 c3 36 40 d1 20 29 58 99 f6 66 +6c 94 17 b2 02 a8 6c 26 ef d7 c6 13 4c 92 fd 86 +b8 32 3d 17 4a 62 53 48 81 38 2d 7c 6c 9e 1b 8c +1e 95 da f2 10 c3 e9 ba 43 e5 88 79 f3 4f 2f a7 +1e f6 ae 4b 68 d6 41 47 be + +# Encryption: +70 ac 10 2d 07 1e 3d 90 22 81 83 62 16 e0 81 29 +0b b5 df cd 56 68 d1 1d ae fa 0a b0 64 59 9d 0f +91 4b 47 29 61 37 5b bf 5f 2a 66 6f ae 0f 6a 25 +ba fd 44 f6 65 c1 7c 14 4d c4 d4 cc 0a 5d 5b a5 +5c 47 a4 cd e9 59 b3 2b aa 52 32 a0 7f bf 93 78 +c9 c5 3c a2 b3 77 81 c9 3a 1c c8 d6 52 94 78 a1 +c6 73 03 4d da 7f f3 35 60 78 6a 46 4f 5b 4a 55 +9c 62 6a e2 95 bc 91 d0 ee d9 37 5f 49 e3 e4 aa + +# PKCS#1 v1.5 Encryption Example 5.15 +# ---------------------------------- + +# Message: +73 9f a7 6d bd 12 73 03 b7 ab f9 3e 1d 7b a7 29 +75 5d 6c 81 1b 5e 93 35 5e 0c 01 1f 74 46 4c 7d +b4 79 19 3c 3f b7 38 0a 62 a0 c0 06 a2 d1 dc 49 +a7 66 af 63 fb a4 52 7c d1 57 50 6d 62 c2 1a + +# Seed: +a0 b4 da ff 3e 26 ce bb 3e 4e 3a 43 db 36 c4 66 +fb 8c e6 05 b2 5a f4 c9 da 74 4b 62 d4 1f 9e 62 +c2 28 5c 39 0d 60 d1 8e 3d 7e 67 5b 4a c3 19 67 +24 45 19 46 bc 1c cf 2a 9b 56 2c 45 33 c9 + +# Encryption: +2b 79 80 91 b3 a3 91 53 3d 62 dc 0e 41 7b a6 de +da 00 5b fc 30 ab 7d c8 2e 8f 9b cc 74 17 bc b0 +04 34 8c 6d 00 e5 37 d2 72 2b 84 38 61 48 92 45 +ab 0d 51 f2 11 44 7d ac 33 a3 f9 dd 6f 3c a6 6b +bf a0 d1 ad f9 8b c9 09 95 15 92 69 76 b9 25 8a +ab 63 20 4a d8 91 65 c8 7b be fd 8d 98 85 34 b3 +74 07 df 7d 43 ad 39 1e ed 99 82 47 28 ef c3 a5 +33 b7 89 b4 7e 8a a7 12 16 17 47 4f 33 25 c5 1a + +# PKCS#1 v1.5 Encryption Example 5.16 +# ---------------------------------- + +# Message: +5a 44 b5 47 bd a1 9e cc a1 dc 7b c0 45 50 20 5f +66 c5 de 0a cb + +# Seed: +2f 54 85 d2 5f e5 ce 40 ae 62 a1 12 97 6c b4 a5 +39 b7 4d 96 ef 8b e8 73 32 5e 20 4b b3 f8 66 07 +a1 6a 2c 2a b5 0f 69 78 09 ed 03 01 72 70 ef 20 +a1 02 c4 3a 2c 4c 3b e6 ab 7a 8a e2 dc b5 69 84 +d5 e0 65 52 45 93 eb 70 70 83 4c e5 53 f1 75 69 +20 bb cb be 4f b2 6d 35 d4 ad cb 59 df 52 46 35 +6f f1 2e 7a a9 ee 6d ef + +# Encryption: +62 d1 48 9a 40 3a 90 fa ac 67 7a bc 17 4a a7 24 +3b c7 51 a9 64 69 5f 6c 32 b3 9d e0 18 fe 46 43 +44 20 ea 76 59 be 2c 41 0b c5 6c 4e 3e 7a 1b 16 +77 fd f4 ad fb 23 24 f0 41 ed d5 79 0c 4c df ab +36 55 e0 7e 41 fe 9d 73 29 21 51 b0 dd 5b 96 fc +84 a6 b2 0f 6f 3b c0 f6 0e ae a8 d8 29 17 b2 10 +83 05 59 40 fc 02 ee 3e 17 c3 78 bd 4d 85 06 d0 +8e c4 5f 33 de 57 80 f0 1b d3 18 a9 a1 67 87 ad + +# PKCS#1 v1.5 Encryption Example 5.17 +# ---------------------------------- + +# Message: +16 80 2d 80 3c + +# Seed: +02 f0 e7 62 c3 39 17 bf 6a 4d f1 1f a2 84 73 54 +7a 5a b0 76 7d d3 a6 1a 8d 05 cc 1e 6f 98 34 5a +f1 a0 0e 42 f6 2b d8 ec ca cb d3 7f 4c cb 80 9e +9e 05 5f 73 d3 37 5a 60 41 d9 78 2c cd 85 d5 9d +14 f4 3e 5c 94 10 25 7b 90 6e 41 cc 8b 97 35 47 +d0 62 2b d2 1d b2 9a 91 38 d3 b1 be de 38 ce 5c +94 c4 e1 d2 a0 a8 40 0b 45 ba cd 42 69 79 7c 38 +5a a3 06 6e 65 80 72 99 + +# Encryption: +75 3b 9c ee 70 d4 18 1f 95 63 87 80 db 7a 04 f9 +b1 2e a3 8e 5d ae e4 f2 89 4c 02 67 3a 53 f4 85 +30 74 6f f2 85 8b 78 7e fc b4 2d 45 e5 31 be a1 +c8 da e9 48 77 15 3b 95 6a c7 b2 87 46 ee 21 c6 +31 bf 9a 3b a7 9d 2b a8 13 21 b7 96 03 b1 d0 1a +4e 90 9e d5 a2 7c bf 27 c9 57 78 3d 3f 79 50 e0 +1d d8 f4 47 f1 0e ce d3 6f 2d 19 35 86 f5 cc 17 +fb 62 2a 05 fa a1 fb 5c d2 aa 06 4c 08 67 b1 ca + +# PKCS#1 v1.5 Encryption Example 5.18 +# ---------------------------------- + +# Message: +d6 d0 f6 03 85 97 9c a5 06 fc 83 34 21 bc d2 2d +a6 a0 6a 8f 37 0a 7f 02 fe f4 7c 1c b2 19 9f 26 +45 c7 54 90 fb f7 89 ad 52 47 04 da 8a 27 66 c6 + +# Seed: +a0 3c 05 67 2e fe 23 b4 4b 26 c7 93 e7 05 3a 77 +04 8b a2 db b4 b5 3a e9 75 18 54 e7 ad d7 d6 7c +12 cb d1 6c 0b 19 34 d2 c2 3e 77 cd cc 89 ce 1d +45 c7 61 15 8a a8 61 31 71 a7 39 01 ac 1f 61 c6 +57 05 53 3d 3e 63 9b 57 a2 48 92 91 79 + +# Encryption: +00 78 dc 48 a6 61 58 99 2a aa 68 fc 3c cc 62 8f +92 a7 08 d0 b1 d4 38 37 20 8d 53 4b c3 f9 be 1c +14 12 ed 0f 9f 7b ef 49 43 0d c9 e9 98 f7 52 e0 +74 77 68 b4 ae 38 14 46 96 c0 03 d6 d2 5e a1 a6 +ca 6a ec 92 4a 9f 4d 9b 57 5a 8f 13 6b ba 29 bf +31 c1 3b 70 50 bd 55 d1 00 0d 43 3d aa 6c f1 0b +49 11 6c 80 63 10 7f d3 a5 bd f6 15 45 c5 d8 63 +f6 a7 88 81 78 6c c8 dc 37 6d 36 c9 11 36 82 25 + +# PKCS#1 v1.5 Encryption Example 5.19 +# ---------------------------------- + +# Message: +b0 38 1c ac 04 f3 10 15 04 96 8f 26 d6 55 47 45 +38 3b d1 71 d3 61 56 dd 36 80 b3 db 6f ad 7f 77 +1f 7d + +# Seed: +cc 54 8a 67 77 cd e9 53 c1 5a 71 fc 49 7c 0c 36 +17 b1 bb 05 6b 03 28 8d 9a 54 8b 69 3b b4 30 8b +67 c1 da c3 8b b9 b8 c9 cc 89 6a c2 44 a9 e3 0d +13 24 30 f4 ce ae 57 90 34 3d bc e3 8d 05 6f 27 +b8 6b dd 9d 32 a8 17 1f 3b 3c c2 fd 14 22 65 ac +9a 68 dc 35 36 27 33 9c d8 83 03 + +# Encryption: +45 6f 7c 3e 3b e8 5f f7 bd d6 b5 b2 50 bf b8 1c +d6 fb b1 86 d2 5e 0c 1c 52 59 d6 78 87 93 c5 41 +ed ac b4 ec de db 8a 89 29 01 34 a6 06 f4 6a 81 +99 1c 13 b1 20 e3 30 56 bc 0f c7 e9 7b 34 2d 0f +20 05 18 13 dd e4 5e 0b 59 6a 7d cd 69 04 90 3b +8f c0 76 a6 e2 4b 3a d8 01 34 16 d9 fd 18 48 30 +55 4a d5 4d 55 48 bc ad da f5 92 0a 02 49 55 88 +78 25 dd 37 1a e4 ef 90 06 9a 4f 31 1c 5a 17 29 + +# PKCS#1 v1.5 Encryption Example 5.20 +# ---------------------------------- + +# Message: +e5 + +# Seed: +fe 0b c7 ac b5 6c e1 4b 4e 2f 55 fb a0 e2 b1 71 +54 90 7b e9 4c e4 85 c6 98 4d 61 f6 7c 04 a7 40 +a2 8d 60 94 ae ae 33 b3 ea 0d 58 18 3e 1e c7 f6 +01 b2 ab 82 0f b8 a7 ff ac 0b 4f 96 0e 1b 4a cb +e5 7c dc 35 b2 25 c4 97 fc ac a0 30 19 a2 95 b3 +e6 6d a9 6f 53 79 cc d1 da 44 47 9a 4f 21 35 e1 +06 3d 71 a2 82 c1 e6 6f db d5 d9 53 f5 71 8c 25 +39 d0 0c e4 9b 45 18 20 45 4d 2d 49 + +# Encryption: +5c 53 36 77 a1 dc b3 63 95 da 9a 6d 34 77 bf bf +71 51 2c 6a 93 3d 04 1c a3 13 44 e1 cb e1 e5 55 +88 a1 14 6e 3d ec 46 10 ef ac 41 b5 f8 02 66 02 +66 52 b3 d7 aa 59 42 74 d9 d9 20 d3 3a a0 ad 9b +4e c5 9a a8 80 71 2a 1d 1c 36 8a 45 7f 35 c7 43 +88 b0 42 f2 49 8e 9f 4b d4 5a 26 f3 21 dd 9e b3 +33 ef 80 af e3 af 9f 72 9c a1 8f 42 c8 8a 71 73 +85 8c 54 20 66 f8 a2 52 cc f0 fe af e6 b5 a9 24 + +# ============================================= + +# Example 6: A 1024-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +dd ca d6 a3 8b 37 04 cb e0 6b b1 b5 1d 11 62 58 +49 78 a4 29 1f b6 73 b4 ea 30 ed 8b 51 a4 bf 26 +1d c9 f0 f4 69 ce 99 88 a0 89 f0 84 36 64 64 a1 +80 cf d7 17 10 69 a6 f6 36 d7 5f 23 40 1b 30 cf +43 ad cf 87 0e cd 24 58 2f 4d a2 95 22 91 51 dd +cf c7 c9 91 86 b2 45 88 5c b6 31 96 c4 a5 72 6f +20 7e e3 60 af 3a d8 c4 83 85 a4 e0 84 1d 7d 85 +1d 54 54 5d e7 67 d8 f9 99 dc 17 eb 0c 57 11 89 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +dd ca d6 a3 8b 37 04 cb e0 6b b1 b5 1d 11 62 58 +49 78 a4 29 1f b6 73 b4 ea 30 ed 8b 51 a4 bf 26 +1d c9 f0 f4 69 ce 99 88 a0 89 f0 84 36 64 64 a1 +80 cf d7 17 10 69 a6 f6 36 d7 5f 23 40 1b 30 cf +43 ad cf 87 0e cd 24 58 2f 4d a2 95 22 91 51 dd +cf c7 c9 91 86 b2 45 88 5c b6 31 96 c4 a5 72 6f +20 7e e3 60 af 3a d8 c4 83 85 a4 e0 84 1d 7d 85 +1d 54 54 5d e7 67 d8 f9 99 dc 17 eb 0c 57 11 89 + +# Public exponent: +01 00 01 + +# Exponent: +5e 48 e0 3d dd ec a1 a9 59 d9 ee 4d a3 f1 c3 f0 +ec 2a d0 fe 7a 70 c1 77 63 27 31 94 4c 3c d0 d5 +8f 4c 4d 96 59 74 6e 68 5a 76 c9 3c 2b 33 3a 64 +3d b2 1d 29 bc dc 6d 11 b5 f6 90 87 17 b5 77 65 +99 ff 30 88 b2 01 4f fc 51 f1 8d 93 22 24 f1 05 +9b 22 39 ea 56 44 e8 06 9a 5c c4 31 ae f6 07 38 +0a a9 24 c1 58 ab cb dd 97 51 f5 4e 67 79 c4 ec +23 21 68 b0 01 4f 4c 8b 49 7b e9 49 ae e6 57 51 + +# Prime 1: +f9 47 1f 2d 22 13 a9 2c f0 a7 c3 84 04 d4 0e 32 +2f 14 f4 39 61 f0 1e 92 33 63 cf 66 53 e8 98 4f +b6 e6 8d 66 e6 f1 59 80 3a 44 bc dd 09 e0 56 19 +6d a4 00 7a e2 a3 7f 40 57 bf 7e 3b 5e 4a 80 23 + +# Prime 2: +e3 c5 f8 cb fd 51 c6 c2 66 b1 a3 2f b2 f6 fa 48 +9b 97 54 b2 27 c7 7f 53 59 c5 5d fa 03 80 fe 9a +02 b4 d3 95 05 f3 ab 36 95 7c eb fa d5 34 d7 f9 +a2 67 eb ee 19 af e5 c6 24 04 3e 30 19 d0 ac 63 + +# Prime exponent 1: +2c f4 79 97 df 1c 62 97 1b 33 76 1c 19 ee d0 3c +96 a7 15 c0 3f 7c 59 57 0e 73 82 94 b6 af 2c c0 +bb 80 6a a1 d3 26 55 78 bd 89 65 f2 0a f4 ed 32 +1a c6 c7 db 61 82 10 d1 de c1 47 17 97 d2 a1 b7 + +# Prime exponent 2: +a6 c0 29 bb d5 91 c7 cc 4c 78 61 fa aa af 8b 5e +1a a2 78 7c 11 09 49 5a d1 0e e0 15 07 f9 a8 eb +41 6d f6 b4 53 ee 26 fb 48 07 73 8f 68 05 4e d4 +50 24 7a a2 0e a6 2a b6 9b 69 8b c9 95 2c a2 f7 + +# Coefficient: +aa d0 60 de 5e db 35 81 8b d6 3e 85 d4 2e ee 55 +e4 cf 8f a4 2d 4e a5 92 83 ce f9 6a ca ad 55 5d +47 8d 2f d7 c3 8f a9 31 fa 1a eb 6d e5 66 55 3d +08 f1 cb c0 6a 51 0f c2 e5 69 b5 a8 22 67 ac 91 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 6.1 +# ---------------------------------- + +# Message: +a3 e1 52 75 fb 33 ae c3 7b d3 dd 58 2e 19 f5 d3 +8b 9d 0d + +# Seed: +78 da a6 1c 07 f9 41 b4 b4 40 e7 38 33 8d 06 cc +15 7a 01 57 4a 72 fa 78 d3 63 dc e9 94 09 04 22 +0a 71 32 35 69 96 f0 7c 01 d5 4e e5 4f a3 2c 5f +aa 1b 90 d2 43 0c 80 a2 32 17 e0 6b b1 c8 04 3d +61 ff a1 8a a1 d1 8e 15 e4 30 aa 12 1c df f4 3f +ab 2b b0 de bf 73 e3 d5 a7 5b 46 f9 0d f7 3d 65 +6b b0 66 ac 1c 76 8f a3 83 e4 + +# Encryption: +9b f1 dc fc 65 4c a7 a2 3d 80 a1 2c 09 c2 59 d0 +4b ae 07 e8 31 f6 09 e9 f0 35 d3 56 41 4e d1 06 +f9 b4 62 35 fa 3d a9 1a 32 b8 fd c8 fb 88 30 c9 +65 23 dc aa 9b 25 38 fc 01 02 dc 0f 7a 5f ae 86 +35 b3 b1 23 14 c3 90 55 fa ac fb e0 0a 15 16 34 +24 14 8c c9 e0 f0 ab 42 df 09 02 3c 05 2a 46 ae +3f 86 a1 8d cc 53 80 ce 39 06 2e 36 23 75 d3 a5 +f9 e3 b3 4a 5d a2 5c f0 de 9c c1 9c 4d 04 f6 3f + +# PKCS#1 v1.5 Encryption Example 6.2 +# ---------------------------------- + +# Message: +44 3a b0 3c 46 04 db d8 bf 80 06 ae cc 2a a8 de +64 a1 55 b4 f9 0c db 08 59 98 6d 5c a3 60 66 03 +59 80 8c 59 bd 9c 2d e7 75 fc 18 52 02 24 b6 69 +c3 25 + +# Seed: +3a 6a 60 89 f7 27 dd 16 92 97 a5 79 fc af 8e a7 +f8 e1 2d 54 27 f1 f7 90 1a 90 22 a2 1e 2d 82 d2 +f0 8e 63 ba ca 26 7b 65 3a af 89 de 23 2b a3 d3 +92 d1 cb 49 dd 76 b3 88 b2 da df b0 09 4f da 97 +18 f1 78 37 38 d1 8f a7 aa a6 29 + +# Encryption: +5a 0a e0 de 28 fd 33 cc 98 01 bf 4d d3 06 71 23 +74 53 63 ca ce 4d d8 b7 b8 b8 11 d6 48 2f 59 12 +0c 0d 65 3e ee 86 a6 1a 01 2a 18 0e c5 d1 7e 99 +14 6d 0c ca 0a 58 7c 85 cf 01 dc 7a dd 84 23 0d +91 80 bd df 5a 77 19 f6 9d 1f c4 81 af 6f 47 db +8c bd 4e e1 87 1a 57 3f c8 76 7c e8 be ed b5 c7 +3f a9 3f 0c 53 80 4a fe 2e 76 cc eb b8 7c ba 00 +cd ac 94 de 40 e2 b0 be aa 8e 2e 41 58 c7 78 50 + +# PKCS#1 v1.5 Encryption Example 6.3 +# ---------------------------------- + +# Message: +d1 ba 30 e8 8c dd a3 3d 2b 41 89 6f 43 df 08 1e +ef 20 ca f7 8d 7c 1b 97 0c 6a 61 72 e8 38 39 dc +43 d4 be 29 f9 a7 72 ba 41 59 73 8b c6 13 29 68 +61 8d c7 19 7c 0e dc 57 a1 + +# Seed: +9b b6 2b f9 a7 51 fe 41 81 66 43 68 98 ed e8 35 +cf ae e2 f5 0e fc ad 60 94 2f 2f b2 da 1a 20 38 +03 f0 be 80 be b1 7f fa d0 da b2 18 b1 28 02 7f +34 97 a4 f8 d4 1a b9 a1 be 26 4e 96 b4 45 48 76 +7b e8 d4 a7 + +# Encryption: +81 19 1c 54 75 27 3d e6 6a 41 bf 56 04 f3 2b 58 +b7 59 a1 4e 74 26 c7 46 de 4b 53 ba f7 80 bb a4 +2b 42 e9 27 8a a9 45 27 f0 ee bf 85 5f 46 2d 6f +bb 29 78 a4 65 30 37 d8 b4 48 e1 b8 07 a1 83 1d +bc 53 22 d0 66 98 4e ec 28 11 4f b7 20 1c 79 6b +57 3a dc c5 cc 92 7f 3a 58 97 b2 00 55 64 ef 1a +2c 01 67 f5 43 65 51 18 34 ac 6f 49 58 b8 31 8d +09 e6 78 54 d6 31 ca 52 80 76 86 ab 70 5d 71 a3 + +# PKCS#1 v1.5 Encryption Example 6.4 +# ---------------------------------- + +# Message: +a5 4b c2 27 8b 56 76 85 c9 b5 68 54 e4 c1 c4 06 +d9 16 17 47 c6 81 34 80 16 3e e3 af 23 b2 1e d1 +99 83 e0 f4 2b fc 93 25 cb 5c 82 e1 a4 7b 8f + +# Seed: +cc ba 5f a5 c9 4e 79 83 2a b0 46 c9 77 74 95 b1 +63 bd 3a f2 17 59 0f ec 5a c4 8c 62 78 6a 27 f3 +70 d2 85 99 55 e4 5a fb 2b 79 f1 2d e4 16 11 45 +be 62 ac 13 a0 3b f4 81 95 fb 9e 5a 18 b8 2d eb +bf 3d df c8 08 25 d5 93 fc d4 02 e7 4e ef + +# Encryption: +3d e4 c3 e0 59 35 7b 8a 54 83 7e a1 59 62 cf e2 +00 7c 5e a8 98 5c 93 51 91 64 a6 89 b7 55 b6 1c +8b d2 73 96 9d 33 3c 4b cd 9b 06 03 53 c3 7b af +13 eb 42 2f 1c b9 77 56 e6 b4 94 6a df e1 af 75 +e9 fe 2d 95 b4 b1 3d a1 73 2b d8 b8 be 11 97 02 +79 19 53 0c 34 7f 3d d1 03 9e 34 8a 53 b1 16 f9 +f8 fe 89 36 a8 4a cc 39 f2 e0 69 56 b6 78 d2 0f +df 95 17 07 2e 02 f5 70 78 fd c0 46 59 40 0c 5c + +# PKCS#1 v1.5 Encryption Example 6.5 +# ---------------------------------- + +# Message: +f3 c0 0b 00 9e 5e 08 a6 3b e1 e4 00 35 cd ac a5 +01 1c c7 01 cf 7e eb cb 99 f0 ff e1 7c fd 0a 4b +f7 be fd 2d d5 36 ac 94 6d b7 97 fd bc 67 9c be +68 f1 a2 f3 62 59 c5 58 f0 4d + +# Seed: +e2 2d 5e 43 b1 eb a1 ac 0c e6 5c 32 70 51 0e 0f +13 c9 4e 96 24 ee 52 56 59 ef 4d 57 37 88 20 c9 +35 22 9b 30 99 aa 2b 23 50 61 4f 8c c4 29 58 15 +a2 c9 ed b2 d9 c5 9c 73 d1 aa 90 0c 21 34 c0 a7 +d0 90 9c + +# Encryption: +53 3e 67 a2 bc 5b 3f 01 34 2d 8c b8 d9 25 d7 3b +4d b3 4c b6 75 da 90 39 22 6a 98 e4 d8 13 c6 20 +11 09 90 a8 e6 ac ba 50 fd 04 f3 30 7d eb af 20 +d4 f3 74 cf 6d e0 d9 b2 1d 86 e2 66 07 9c f2 f1 +8b 45 03 20 8a 21 5d e2 b1 1c ca 9e 34 64 fc 5a +c1 dd 7e 96 b2 fc 04 09 e4 2f 46 a5 06 12 a6 b2 +06 1e d1 61 9a 7f e4 67 96 ed 8f 52 06 9a 5b fc +84 08 d5 58 f5 2a 03 33 2e e8 ed de f8 f7 45 d9 + +# PKCS#1 v1.5 Encryption Example 6.6 +# ---------------------------------- + +# Message: +aa fe 5b 27 11 11 ef b8 79 2f 5a a9 23 83 07 29 +76 b7 2a 0a 27 2f 90 c5 24 61 f8 8a fb 1b b6 b7 +ec 26 38 1c 65 76 a4 10 87 a0 39 80 9d 14 f6 11 +60 67 59 4e bb + +# Seed: +75 0e f0 86 9f 8c 75 7e f4 31 57 8b 45 a6 e7 41 +bd 1d 96 0e fc 37 89 b1 0d 2b de 27 38 18 07 4e +bf e5 fa ae 10 ac 24 4f 89 f6 c0 2d e5 d1 ad ae +fc 7a 8f d2 4d 7b c3 76 fd 65 d3 5e 39 50 8c 42 +36 ac be 2d 5c a7 69 4b + +# Encryption: +34 4d 43 37 61 2b 22 dd 40 2b e3 79 e6 b2 65 0b +51 9e f3 7b 7a b4 85 81 94 52 d1 67 c1 b2 15 db +d3 fb 24 f9 b2 f9 29 86 69 cb 1a ee 14 1a 7d 89 +01 64 20 43 11 1f c3 8b 3f 40 ef 0b 7f fd 7d f7 +6c 2d 92 e3 29 41 1c 75 e0 f1 72 85 bb 6b b8 26 +88 12 8e d9 bb 95 1c ae dd 7d 06 7e dd 0b 13 e8 +27 5a c8 86 25 d9 7c e8 d2 0b 69 b3 57 38 b2 f4 +72 6e 29 84 b8 df a8 66 95 aa e8 8d 9e 17 6d f6 + +# PKCS#1 v1.5 Encryption Example 6.7 +# ---------------------------------- + +# Message: +a1 22 4d f9 aa b6 58 78 45 b2 a3 93 a5 a8 76 c1 +7d 95 9d 53 5b 54 19 d4 12 a9 a5 31 bb 43 7e 1d +ac 1b 54 6d 62 + +# Seed: +76 1d c4 f5 1b c8 51 8d 62 7c 45 b3 e9 81 8b 85 +42 a0 6f fe 17 2b e3 af 5c e7 a9 05 3f e5 4e 69 +70 12 49 73 37 4d fc c1 f4 9f cf fe 95 7a ae 8c +9c 3b 13 0f 46 05 d2 c3 ef a2 93 2a d0 83 de c5 +8e 70 d4 f6 92 6c 80 b5 d4 89 1a 1a 55 9e db 0c +af fa ca d7 5e b2 64 83 + +# Encryption: +78 5f 6a aa b4 d2 f3 18 d4 af 37 b6 e0 07 4e d5 +a4 19 4f a6 05 a7 ec 87 d0 5a 07 f3 34 9b 5b 92 +f5 fc 47 90 ea b1 37 86 cb f0 35 c7 8f fc f1 34 +4d 1f 3e cd aa e0 16 72 22 2e 6d 4a 96 55 59 e2 +c0 82 91 cb 1d 4c 2d 4e 68 ff 8e e7 15 23 f6 dd +ae c5 0a 4a b2 2e dc a2 47 36 4c 92 d8 73 99 e8 +a7 1d f7 43 6b 62 d8 ba 8a d2 02 94 cb c6 0d ca +e0 30 5c 79 73 f7 fc b4 a5 cb ed 15 71 3a 7a 16 + +# PKCS#1 v1.5 Encryption Example 6.8 +# ---------------------------------- + +# Message: +1e 0e 3f 65 0c 32 db b2 f6 91 6f 36 f1 35 bc ae +88 1d 54 55 07 40 2d 6a fd 3d 5b 3b d8 38 5a 50 +b4 fa d6 f7 89 49 fd e6 21 64 ed 76 89 e5 f9 a4 + +# Seed: +ee a9 0a 54 d0 16 da 7e 8f 08 76 a7 33 b0 f2 a0 +6f 90 a7 3c 1a 3c d6 39 b6 cf a9 06 ce 08 ef 78 +8b b6 fe a7 4f 22 eb 91 a6 ab 32 84 cd fc 1e 72 +e6 3e 78 d1 8a 64 d6 7f 9d 1a 29 19 49 ed 2e 32 +3e 91 dc 03 38 76 ee eb 09 ff a7 1f 59 + +# Encryption: +6b bd ae 20 f9 89 bf aa 5d 65 da dc d6 1a 86 b6 +63 07 a0 60 2f b5 51 a7 38 06 12 2d b1 88 ec 1d +41 e8 4d aa 2c c7 d6 be 54 1e 12 28 88 09 a1 7e +08 5f 2c af a8 ae 13 67 0e 0f 33 65 a1 47 1c b3 +15 7c 06 e0 f6 3b 82 00 f3 16 0c 16 3f de 7c 90 +1e f3 26 e5 70 0c 9f 5e 07 fe 01 98 81 0f a8 0c +8c 5d c5 3a 50 bc e2 54 f7 d1 99 01 cf 6c bb 60 +34 13 e4 1f 90 30 e7 39 c8 ba 96 49 97 84 74 99 + +# PKCS#1 v1.5 Encryption Example 6.9 +# ---------------------------------- + +# Message: +73 dd f0 a1 4d 57 ba 65 b4 f6 93 ac 76 1e 20 2b +1e 5b 85 7c 8b 34 04 e1 41 85 df a8 aa f0 49 89 + +# Seed: +fd 43 3d 7b 01 76 b7 31 d7 80 dd 6c 58 51 b8 2f +17 6d 62 b8 0d 96 ae b6 31 d7 fb 8a c5 be 55 ac +21 7f 4e 08 bc 7e cf 81 f8 e3 f5 dd aa cd c6 c2 +17 8d f7 81 88 23 97 53 3a 63 8e 62 f0 74 ac 48 +8f 4c 12 aa 57 be 2e ce 5b b6 e9 09 6c d9 22 59 +a4 5b 0b 03 2f 10 14 31 a2 8b 86 40 fb + +# Encryption: +ae 97 ff 43 4e 9a 5e e4 87 76 1d b3 56 90 0b 06 +37 37 46 5b e5 05 8d c0 3a 28 a3 22 e5 c0 e0 91 +b7 99 bf 65 94 55 cf be 05 42 7a c4 d0 44 05 e5 +6e e0 4e 06 3a 23 73 db cb 9b 4f a1 6e 43 07 94 +6a 49 b3 56 34 52 0d 41 6f 65 c3 c3 22 ed c5 46 +71 56 91 28 a2 a1 52 a7 6f e4 44 c4 30 aa 6f 03 +c4 12 9c 6e 21 31 75 5d 76 4c ec 4a 14 86 a8 1b +a8 a3 16 8d 16 e7 4d ca 8e 77 bb fd 67 ea 37 2b + +# PKCS#1 v1.5 Encryption Example 6.10 +# ---------------------------------- + +# Message: +ef 3e 76 98 e7 d9 cc 86 3b 46 6b b2 88 55 6e 4a +c2 52 82 e0 94 fb 5b 57 c1 76 17 bb 98 + +# Seed: +db 90 a7 58 0d 8d 42 9e 22 bd 7e a5 c7 b4 cd 0c +65 ad 0e 2e 27 f5 33 41 bc 23 a8 b1 35 8a 76 a0 +b5 e9 4f c5 b4 2a 9f 75 6c c6 3b 9d 62 3f 55 17 +67 fb c6 f7 11 4e 40 ba 73 61 fd 32 d6 f8 d7 72 +34 37 43 6d f7 24 b1 32 7a ae f7 b9 57 56 27 68 +f8 fa dd 57 86 2b a0 b3 14 09 6a 3b 38 77 0e 31 + +# Encryption: +43 f8 cc ce a8 12 d3 38 5f 43 fa 83 7c b5 e6 fa +59 0f 1a ff b8 62 d2 ca cc c6 d8 e8 bb 5d 5c 0d +50 ff b9 f8 f8 09 89 00 c1 2e 77 2a 84 7b 37 81 +57 78 2b 0a 90 40 f7 a6 16 c2 eb 05 8e 44 d4 a7 +e2 0b 48 5a c2 9f 40 d6 8e 03 c3 9d dc 8d ae 7e +7e 09 e2 8f 9d d2 19 0f 3a 9f 35 74 b2 f6 34 00 +15 44 36 3c 86 1f e2 7f 7a 39 23 66 92 fe 35 82 +14 0b 21 72 ce 64 7e ed 41 76 85 c6 e1 db 85 6c + +# PKCS#1 v1.5 Encryption Example 6.11 +# ---------------------------------- + +# Message: +f8 69 18 47 4f 88 16 97 11 1b dd dc 1f 00 61 3e +b2 c3 d9 c1 78 76 68 35 3e bb 02 b3 20 a3 26 + +# Seed: +cb 7d 99 da 9b 11 ea 57 f6 40 55 43 44 7d d1 5f +b5 cc a0 a1 0f 3b 69 b4 d2 33 09 ef f2 75 0c 48 +6c a6 55 32 5b 55 a3 27 ff e8 bd 6d ca 99 bc 8e +fb 5b c2 94 2e c0 39 e2 84 25 e4 a5 6a 07 d3 80 +12 f1 0d 21 5a 22 d6 37 68 59 43 d3 64 72 53 01 +dd 40 e2 17 22 8a b7 91 59 89 98 83 6b bf + +# Encryption: +2a 40 87 80 ad 51 4e 56 71 fe 1d fc 36 7d 7a a4 +65 fc 34 69 f1 c1 52 ae e1 81 45 e0 f5 f0 75 9f +44 69 b4 3d 55 12 3f 5d c9 ff c6 17 f2 3f a4 9b +78 96 02 19 66 0e c6 22 74 d6 c5 9b a3 14 60 bd +10 94 1e bb 5e 05 69 41 51 c5 7b 5b 95 88 ca f0 +9f 45 50 20 a5 4e 97 7c 3c c0 27 da e3 1f 2c e4 +42 17 02 3e 10 ad b6 f2 d8 aa 0f 80 84 fc 45 86 +05 80 3f d4 4b 21 ab c2 7b db 8d 4c 56 17 84 cf + +# PKCS#1 v1.5 Encryption Example 6.12 +# ---------------------------------- + +# Message: +6a 40 bb 60 70 8c 5a 99 2e cf dc 7e e5 3f 54 08 +4d 19 af fd 4d 21 + +# Seed: +c3 f4 fa ca 56 c1 ff 07 d1 ad 10 37 07 d1 b6 68 +20 47 b4 d9 d6 24 6c 2e 5c 4b 0c e6 55 3d 55 31 +3f 8f 38 ae e5 e4 d8 07 3a 55 d2 4a d7 96 c4 b7 +61 26 c8 aa 61 c4 6a 4e e8 5f a9 05 7a 52 6c d0 +aa 24 5e 58 28 f2 18 1b 4a 64 79 86 87 48 e7 47 +9f 40 34 53 3c 0f 3e 1e b4 35 fa 47 d5 3b 58 e4 +2c 96 17 bf 7e 77 7e + +# Encryption: +c4 64 11 c7 11 6f e6 f4 6f 1c a0 f7 4c 60 81 a5 +5d f4 1d 2c 0b 8f c5 d3 8f aa 34 0b 5e cf 71 83 +f8 5f 88 c4 fb 28 ac 5f b1 f1 8a eb fc fc 10 bf +dd 3a 19 00 2c 6b 52 24 14 92 70 4b 6f e6 3d 61 +a7 30 10 c1 49 ff 63 03 28 3e 99 78 cd 84 54 04 +fa 06 b8 c6 98 aa ea 8f 86 13 61 d8 86 b2 c0 f0 +1b 47 a1 a9 a3 dd 90 3f 8a 58 ae d6 6a fc 85 e9 +b7 1e fc 3f 55 a1 21 66 74 16 a3 00 00 13 13 e8 + +# PKCS#1 v1.5 Encryption Example 6.13 +# ---------------------------------- + +# Message: +32 52 fe 99 62 09 74 e0 77 d6 eb 55 75 + +# Seed: +bf 06 9b 4b cf 15 44 8b c3 9e 45 f4 42 6a ad 0d +5d 82 b7 4e 93 ae 1c dd 71 f7 1b b9 be b9 b2 3d +59 73 2f 9c 8b c6 34 3d 13 02 31 de 18 f7 c8 9f +c2 f4 22 18 9c d9 27 e5 09 b1 31 97 aa 56 d8 1a +73 76 f8 33 3e 47 42 44 8c c8 92 de 40 44 97 2c +7f 67 dc be 85 44 a9 0e ec 59 e7 95 ae 59 64 08 +39 2a f5 77 6d a0 d6 cb 29 c7 e0 a7 86 81 30 a7 + +# Encryption: +76 53 cb ff 58 68 92 cd d2 58 bf e6 ba eb d9 91 +45 eb 1b 22 89 4e 1a 76 4d 02 b2 ba 99 59 52 a0 +12 58 20 8d e1 a0 1d 8e 8c bb 5c da f0 d6 03 69 +4f 88 25 5e 80 90 97 b7 0e 9d 79 e6 2b d5 c0 d8 +36 dc c2 9d d1 9b 05 a1 60 26 90 42 05 b6 0c 45 +03 d4 fb e9 93 38 55 e8 68 02 c7 54 28 d9 a6 34 +73 03 16 76 32 d3 3c 5d 9e cc 8a e2 49 3b 58 c3 +6b 2a 65 53 a7 b9 e2 b1 35 8a e2 8d ad 50 28 0d + +# PKCS#1 v1.5 Encryption Example 6.14 +# ---------------------------------- + +# Message: +dc 94 + +# Seed: +05 e8 05 bf fb d1 b7 4d 1a 5a 83 8d 85 71 67 b4 +c7 d4 0a 6c d3 e6 8f 31 be 46 93 b9 8c ec 6d 75 +89 49 19 ab 18 57 2c 75 82 2e 75 e9 de d7 2d a0 +67 97 83 a7 72 18 14 e1 99 16 0b 75 07 f6 7f 4e +de 58 7c 88 be 76 81 5c 50 b2 61 df 30 8b 31 43 +23 73 0c 1e 07 3a a7 29 98 cc 2f 8e 0a 8a 5b d6 +5b f9 34 ac a8 a6 48 59 e2 5f 02 c5 a2 71 39 41 +c8 c8 e6 27 20 84 6d fb 51 c2 ff + +# Encryption: +6a dd e2 44 f0 63 8c 5a b7 45 ff ba b5 ab e1 fe +80 0b 0e ee 15 35 50 c4 8c 36 f4 24 9f 9d 5d 36 +b4 7b 28 cc da 71 a7 dd 83 2e 64 35 ad 0e b8 5e +f7 55 6b b8 4b f9 5a 59 cc c9 c2 07 51 ed 3e 1a +d0 de 10 29 94 a7 12 c5 14 01 46 92 a6 7f 1d 87 +ca 2e 4f ef 29 ec 83 e0 1e 29 ad 0c 97 8a cc a4 +d5 c5 02 74 5a 6c 50 0d f2 00 04 bc 9b f1 6f 5f +cc 69 bf 52 70 9e 31 cf 6a 2b 9f e6 24 d9 a3 64 + +# PKCS#1 v1.5 Encryption Example 6.15 +# ---------------------------------- + +# Message: +4f ae 6c f3 7e 9d 5f 59 + +# Seed: +e7 f9 ed 4a 0c 3a 64 66 69 03 9b d0 1f 24 9f 32 +be a1 e6 57 6c 21 d4 51 89 d0 f8 91 cf 4a fd 62 +32 08 3a 32 1e d2 d3 4d 07 09 84 f5 e9 45 78 39 +b2 eb c1 e0 3a 2c 0d 8d d7 09 73 1e 95 b2 e6 94 +1c a0 90 71 87 af fd cf 5a 87 f5 cb ea d2 f9 05 +2c 38 d0 ee 54 e1 f1 28 ff c3 37 de 45 66 a5 92 +5e 1e 94 7a ef 50 88 1c bd ae d9 9b 1b bc 1a f5 +13 23 2c 0f f4 + +# Encryption: +46 e6 70 5e b1 25 2d eb f8 ec 67 2c 4f de af 69 +88 26 84 59 f9 95 89 bb d3 05 41 33 d4 83 ab e1 +e2 7c aa b0 a7 f0 22 1b 1b 67 a1 4e bf 45 12 6e +60 13 48 b0 43 44 06 da 3a 8c 76 d4 f1 e3 f1 a0 +e0 6d 0d b8 23 da 51 17 b9 2a 40 b6 f3 9f 57 e4 +83 a7 da 36 e9 9b 67 7b b3 f7 6e 6c 5d b0 3f 3c +e4 45 04 eb d4 5e 9f 14 fe 0f 61 3a 2e b7 95 47 +ab 57 8c 58 6d 3b 65 4a 06 fe 1e f3 7a 22 10 66 + +# PKCS#1 v1.5 Encryption Example 6.16 +# ---------------------------------- + +# Message: +cd fd fd aa bc a3 76 7e 70 bb c5 e9 ab f6 + +# Seed: +ac 77 7f 67 29 9d e4 c1 c4 c5 74 f3 1f 67 4f 6f +aa bd e0 31 f8 ec 33 e8 26 76 eb 32 a9 3f 65 79 +aa c3 e9 59 35 9f c5 73 ee 5c 0e 3e 07 76 53 ef +f9 d5 f8 db 4b 1e 7a ca db 05 99 71 53 1f 49 b0 +7c 93 eb 9f de dc f0 90 3a 7d 50 b4 79 67 6f cd +e8 74 0a fb d7 d3 7c 3a 21 02 41 2b de 1d 3a 82 +44 15 6a d8 08 9d 45 df dc 91 cd e6 c3 a1 59 + +# Encryption: +51 3c 76 1e b1 92 9a ff 79 77 a9 ff 0e 61 b7 a1 +d5 11 c8 cb 25 39 24 33 24 25 56 9a 07 e2 29 cb +39 01 71 53 90 f7 de 37 bd 36 2c 96 fc 0b 0d 79 +81 0c 1e 8b 15 e1 3b 00 32 73 47 78 cf 96 4e 6f +6d 17 fc 41 c7 86 76 72 b2 54 0f 56 9d 0a 46 0a +80 fa d5 6b 5f 05 4a b8 e4 9e 40 9e 9e 0b 86 13 +cb 3d a2 0c 35 c3 e1 bb 99 b7 ec ab 7a 00 fc 1f +c2 37 0f 9c 80 85 67 df 89 be 2e dd bd b6 b1 10 + +# PKCS#1 v1.5 Encryption Example 6.17 +# ---------------------------------- + +# Message: +b8 20 c3 2e 73 7d aa 23 4f 29 ba 90 64 7f c3 bf +0a 8e + +# Seed: +f5 ca f8 fe b4 2d f7 b6 b3 89 f5 05 99 a4 ec 20 +e6 19 ca 22 d2 bf c9 1b c7 f1 4a e9 f1 22 9e 07 +c8 88 ed 57 aa 6a d3 c1 04 10 44 c5 1a fb 55 21 +7b 0c aa 23 34 ad 79 f4 7a bb f9 b4 20 83 33 b7 +2b 4b a4 bb 5f d0 37 98 1d d8 01 70 c8 03 60 c1 +4d 5a f5 1e 5f 82 ab f5 1f d3 6f 02 18 67 a6 ec +09 7b c3 39 22 ac ea d9 e3 35 58 + +# Encryption: +3e 23 25 18 41 db 2e 20 7a 27 10 1f 13 29 19 1a +b7 fa 6a 70 1a 52 62 61 48 23 53 a1 a2 21 ef a9 +d3 a9 d4 59 cd 2a 2d 86 68 90 8b 78 3b b0 9c 87 +9a 21 7f 1e 40 0f 95 b2 17 b0 40 a5 3e 34 1c 17 +b9 3d 3c 3d 65 46 0c 5c 7f 2b 4d 79 a3 4b 5a 96 +11 7a a3 67 51 d9 ea f2 33 b0 3f 68 db a6 a4 57 +1b 90 71 77 f8 28 33 6e 82 5a 92 26 1b 62 36 39 +be c9 8d 3a 09 f8 72 c2 ec 59 1b 4c 38 3a 69 c7 + +# PKCS#1 v1.5 Encryption Example 6.18 +# ---------------------------------- + +# Message: +60 6b bd 61 37 15 dd cd 92 c7 b6 df 04 b3 60 72 +f0 11 62 d0 08 76 63 12 ca 69 77 dd 3a 06 eb 95 +e1 ba c7 bc 1b c6 60 2c 9e e6 44 + +# Seed: +51 3a 5c 95 68 e8 9b 9a 53 d5 af 71 6e 55 fb 34 +0f 8a 39 23 70 e8 88 a8 0c ae da 50 2e 7f 9d fc +17 51 95 a5 0e 47 07 13 96 d6 ec 55 4e b7 2f 18 +3b e1 8f 3b f4 ec 73 b3 05 92 fa ef 2f b5 14 de +be fc c6 5c 8d 23 c4 ad 25 94 56 c1 e8 0b 36 0a +d4 59 + +# Encryption: +47 21 a2 39 40 18 87 30 f5 de ac 85 00 2e 38 31 +b1 49 ae 57 af c6 97 35 a0 45 ee 3f c3 53 64 72 +fc 83 3c 27 c8 7e ab 6f c9 05 e3 67 96 1b 31 24 +98 63 6b e6 c7 7a a8 0b 8d a2 f5 d9 48 aa a7 7b +5f ab 72 4b bf 64 ee 89 d2 81 ee d4 7b 21 2c 32 +95 26 65 77 f4 fd 93 a2 22 39 de e5 40 c9 40 0f +e5 6d 7a ef 51 df 36 a8 9a e9 2f 92 6f 55 83 31 +e4 1b fd fe fe 35 75 8b 93 ce 11 40 ac 9b 6a 54 + +# PKCS#1 v1.5 Encryption Example 6.19 +# ---------------------------------- + +# Message: +1d 82 de f8 c5 92 87 50 08 a5 f8 9e 7e b6 4e 25 +2e dd e9 dd b8 81 d3 73 62 31 7f 6e 6e 6e 99 3c +60 23 3b 0f + +# Seed: +87 5e 07 5e f1 b0 54 b5 84 1e 08 45 0d 78 eb 54 +a5 5c 88 b6 d0 18 13 c1 07 a0 9b 74 54 3b 3f 9f +e1 b7 c9 02 11 c6 2e a7 33 81 20 d4 ae 0f 73 ba +82 c0 1d 28 f8 19 4b 3a 39 6b df 50 f9 41 3a 7f +b0 3b e2 25 fe 05 45 db 80 cd f0 f6 10 a9 5f d9 +03 76 e0 39 e3 83 1f f9 9e + +# Encryption: +8f b5 46 26 3c 1d 18 75 c7 43 f5 2f 02 67 b2 f2 +fe 68 8d 25 42 02 10 49 f5 34 89 ce 7c 35 91 30 +f8 e1 1e 3c 46 1c 5e 86 3e 4d c1 9f 07 a1 3a 4c +1a 88 22 4b 26 c5 c0 cb e2 02 02 45 d9 1e 1b 83 +42 42 52 52 f5 3f c4 0e 4b 14 fa 02 bb d7 47 37 +d4 02 2c c5 4f e3 8f 0d 27 d8 fe a5 0f 2f dd 84 +65 d4 f3 2f 8a c0 3e e0 06 be 62 33 e4 d1 a3 c1 +6e b1 44 b5 d8 be 72 9a d3 04 f8 23 61 e0 7c fb + +# PKCS#1 v1.5 Encryption Example 6.20 +# ---------------------------------- + +# Message: +8a 8a 3e ab dc a7 ca b0 cc 29 6a 29 1e a8 a9 3d +a4 d2 d2 a1 96 ff 2f 8d 18 1f ee 1f + +# Seed: +2e 47 36 e4 29 6a b4 66 18 b1 ef 34 da 26 77 6e +92 ef 66 f7 cd 17 4e f9 47 69 72 42 23 a7 65 b4 +eb ef 08 a8 8f ed be 27 05 60 e5 f6 74 37 cf 49 +d5 7e a6 62 0a ca 59 89 8a fd 52 cd ef 30 a8 b0 +d9 85 5e 5d fb e3 47 de 77 c4 c0 28 0b 0f 1f d4 +4d 4f e6 89 06 be 8a 4f 12 c5 33 08 7b f5 bc ea +fb + +# Encryption: +03 f3 e4 ba 03 48 31 a0 e3 0a 4a 33 44 ce ad 61 +b2 8b 43 be 31 53 2c 2d 76 37 53 9b 90 13 83 7e +dc b1 f2 16 d3 2f df ae 73 32 36 74 a2 81 45 65 +db f2 9e 71 2d 18 c4 37 39 64 df 60 c9 39 9f da +54 14 a0 eb 45 bd e8 66 1a 89 09 12 95 a1 ef 71 +61 6a 3c d1 45 e9 b3 18 b6 51 af 17 5d 4e c3 50 +1d 5e b7 63 e8 d3 5a 2b 72 74 6e 02 0b 4b a5 99 +73 83 4b 21 50 02 6b 43 2b 17 9a 9a e8 17 2b 7b + +# ============================================= + +# Example 7: A 1025-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +01 70 93 41 d2 ec 08 04 a7 40 34 e8 fa 72 86 42 +98 3d 16 50 d7 46 e4 49 c9 ee 40 79 aa 15 e5 1f +1f c1 34 24 2e 52 4b 0d 3d 0d bf 5a 51 21 93 9b +12 5f cc 86 3e 51 41 60 b6 34 e3 7a a6 98 94 77 +6c 7d 33 e1 e7 c6 19 52 1d e4 82 a0 ae a4 5c 3c +6a bc 3f 33 e2 5d 86 ff a1 39 33 25 65 9b f2 d4 +09 8d f1 69 b4 07 21 87 66 0e 27 77 00 19 9b 7a +3e 34 84 b3 84 5f 6f bf 31 98 65 7d f8 cb f3 a8 +1b + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +01 70 93 41 d2 ec 08 04 a7 40 34 e8 fa 72 86 42 +98 3d 16 50 d7 46 e4 49 c9 ee 40 79 aa 15 e5 1f +1f c1 34 24 2e 52 4b 0d 3d 0d bf 5a 51 21 93 9b +12 5f cc 86 3e 51 41 60 b6 34 e3 7a a6 98 94 77 +6c 7d 33 e1 e7 c6 19 52 1d e4 82 a0 ae a4 5c 3c +6a bc 3f 33 e2 5d 86 ff a1 39 33 25 65 9b f2 d4 +09 8d f1 69 b4 07 21 87 66 0e 27 77 00 19 9b 7a +3e 34 84 b3 84 5f 6f bf 31 98 65 7d f8 cb f3 a8 +1b + +# Public exponent: +01 00 01 + +# Exponent: +6f eb f7 98 12 1e 99 33 24 97 2c 8c 28 cc c6 5a +2e 6a a1 5f cd e2 32 da 03 e4 46 4d b4 da 5f aa +27 e4 2a 7c 7a 76 d9 ed 49 48 6b 27 a9 d7 85 c6 +7d 9a c0 c5 19 ad 8d ad a6 bf d1 15 d7 cd 75 b9 +9c 4b 59 c7 69 83 a7 01 5b 0d a6 97 3c 69 fa 95 +08 10 ae 27 68 d9 75 88 90 05 62 e8 6a 6d f7 c7 +14 b8 44 b1 e0 46 68 6a 5a fc 66 7b 13 57 3a 55 +be 9b 5b 38 b9 9b d3 cf 54 e4 34 4a 2f 2d 0e 21 + +# Prime 1: +01 40 ef 5b 50 70 54 d5 a6 94 46 4e f4 7e 49 86 +8c b3 3c 97 e0 e3 ed d7 7b f4 5a 52 5e 60 8d 7e +21 5f 91 33 48 a9 b8 27 c8 39 73 7a 42 b6 ad fb +b2 bb 49 7e 14 78 92 2f 71 88 97 d9 fe ed 27 7a +6b + +# Prime 2: +01 26 00 4b be 2d f7 6b 6f 38 ae a1 64 b1 fd 0f +97 61 2b 2d b9 6c ed e2 8a 3a 91 ce 0d 74 25 3b +b3 f9 55 9b 89 f4 81 33 75 65 2a 50 70 06 ce 99 +95 a9 8f 0e 6e f3 bc 22 e5 51 9b 61 3b fb cd 55 +11 + +# Prime exponent 1: +98 14 d4 e0 b9 5a 7a 24 05 ff 8b 4a b0 cd 86 c5 +05 ea a0 ce 21 34 83 f8 69 42 a3 e5 b5 3b 57 99 +d8 ff a5 9d b9 4f 5b 0a b6 ae d2 30 eb 00 67 55 +bb 0a 88 84 8a de 3b 3d 41 cd 33 b0 6a 11 5b 21 + +# Prime exponent 2: +1c 4b 1c fe f1 67 85 34 4f ed 26 65 0d 68 00 2f +1e 4f cc 77 b2 ce f5 e5 3d 9b b8 8b bc e8 b4 65 +2e 92 99 84 5e 3e 6c d8 58 63 09 18 ae df 05 12 +cd 1d 92 53 05 2b ce e3 e8 c5 9e 46 ea 85 a9 31 + +# Coefficient: +fd c5 10 c4 d9 79 07 30 b0 fd 47 d3 13 ab d4 08 +58 c7 df d5 8f 4b 37 91 5f 7a 4b 1d b3 d7 d8 ab +d0 6d 3d a0 02 de 98 4a 76 09 cc 18 a9 44 86 46 +0a 61 74 6c 7e a6 31 17 a6 8a a2 82 59 74 4f 49 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 7.1 +# ---------------------------------- + +# Message: +da 50 9d ce 45 e2 47 00 37 9b fe 5a a1 a8 1c 24 +70 6c 18 42 d9 b1 3e 7a 2e 0a 15 d3 a4 af 8e 6d +08 61 2d ca a1 5d 46 0e ce 87 29 88 e3 e9 0f b2 +7e 5c a5 c1 0f a1 fa cd cb 0e + +# Seed: +80 8c 20 46 fb 50 5c 37 69 5c 8d c3 5c 38 f9 f9 +90 5a b4 8a 2b 8a 14 6e 8e 8e da 33 85 ce d9 5a +31 3b 2d c6 eb 41 83 67 fe ef f7 9a 02 ad 74 64 +6d f7 a5 d8 70 54 ac dd af 34 ea fd 5c 1d b5 8e +5d ec 04 81 + +# Encryption: +00 fc 3d 0a aa f2 6c df 25 a1 a8 df cb 71 70 0f +b6 5e 2a b5 55 1a e5 f4 19 b2 d2 f9 4c ef 01 73 +02 b0 0a bd 9e 6c 6e fa e9 44 74 d1 8e 68 da 0a +7c 17 ef 2c 5f cc 89 07 1d 3b 07 12 1b 9c 01 e3 +0f f0 53 66 3f 61 f8 9f db c4 9b dc f8 e6 71 66 +94 43 91 9d 41 34 28 45 e3 e9 9e 46 a8 a3 b4 8e +23 98 a8 8e 5b 45 d9 9a 17 dd 1f 21 2e da bc bc +d3 00 a8 4d 39 8e f5 79 35 bd ae 95 9e 60 54 e7 +3a + +# PKCS#1 v1.5 Encryption Example 7.2 +# ---------------------------------- + +# Message: +ce 0a 79 47 49 87 41 60 e5 d2 e4 ff + +# Seed: +f4 b2 c9 f3 11 c1 fd 41 d4 79 44 b5 0e 17 55 d4 +ea c5 ee 65 08 7c 9f c6 d2 f0 75 b7 38 c6 49 26 +ea f7 d4 31 6b cd b6 36 54 d5 42 0d a6 1e 02 45 +f1 95 b9 e8 24 aa 0b 06 c8 87 99 b1 27 fe 9b 03 +6d f3 61 75 c0 a6 bd 80 e4 e0 af 6e bc 2f 42 70 +b0 4c e3 0b 9f a2 7f 04 35 86 0f cc f4 0b 3d c7 +ea ef fd ba b9 e1 76 66 19 bb 01 6c 17 90 26 63 +cb 24 + +# Encryption: +01 0c f7 4b eb c2 63 6d 2c 49 d9 c6 22 bd 76 cc +0b 1d 02 eb b5 2f df ae c0 1c 4a c1 e7 56 07 1a +8e f7 6e 12 2a 4c 62 c6 ba 32 65 fa 4c 90 56 26 +d1 13 d5 9d b7 9a d6 5f 86 40 b3 c4 34 4d 73 40 +c1 6e 38 de b1 89 e3 a1 b1 1e aa b0 b2 60 6a 7f +82 f5 94 6d 41 9a ce bb bb 3a 93 7d 41 e2 9b 33 +ed d3 ad 15 f1 e7 77 0f cf c3 0a e0 6a a0 1b cd +03 d5 df b1 62 f8 7a 18 39 67 55 3c 25 02 cb 5f +fe + +# PKCS#1 v1.5 Encryption Example 7.3 +# ---------------------------------- + +# Message: +41 d6 + +# Seed: +55 6e 59 b2 c1 89 58 75 08 e2 08 92 fa 56 02 d2 +49 fb fb 71 a1 09 05 ed 5a f7 b7 9b e8 71 11 a0 +c6 9a dd b1 9e ef 31 6d 7c 0b 21 81 79 90 dc 3e +d8 c7 6c b2 3e 83 0e 17 c0 f4 38 73 15 9f ab 7c +5c 4a 6c f2 19 cb 1d c5 c5 da 45 53 a3 e0 bf 18 +3b 8e 11 2b 61 f6 92 a7 dd f0 04 bd bf dc c8 d6 +65 9c 3d d8 0c b2 3a ab e8 c6 fd f2 67 5d 07 3b +66 23 12 e4 ac cd e9 1c 12 25 e6 d1 + +# Encryption: +00 2a 10 04 95 59 66 55 30 4b dd f9 09 7f 78 d9 +dd b5 eb 42 9b 66 63 5a 58 a2 98 f1 92 8e ed 61 +53 4f 80 b4 ea 05 ee 39 b0 2a 64 56 6f 6c 45 6e +3b 58 6e 7c b4 3a 88 94 0e e1 29 34 0f 57 8e 56 +e7 2d 8b 27 83 36 10 06 d9 71 29 ab ef 02 cf 1c +19 12 e1 7f 0c d1 d7 1c 0b 32 8d 0b 48 a4 ac 7a +ec e3 c0 05 a6 19 0e ac 22 c1 99 10 41 15 9a 2a +d1 db 08 96 01 5c 4f f1 d7 b3 54 47 cf c1 0a 24 +be + +# PKCS#1 v1.5 Encryption Example 7.4 +# ---------------------------------- + +# Message: +0b b4 ab c7 dc 6c a4 23 5c 29 ed 0a 2c b6 3f d1 +41 34 1e 2c 4c 90 1e 6d c9 5d a9 f0 01 0f a2 e0 +22 cc fe 8a df db 6e cf 4d 89 f5 79 a1 0a 51 70 +be 18 c4 6a 24 1c a7 ee d1 07 ca fe 4a 9d + +# Seed: +bb 80 be 78 02 dd 8b f5 fb 5b 1b 86 39 66 54 f4 +73 9f 5d 43 51 f1 9c e3 1b 72 c2 10 ae a1 a2 ed +21 42 d8 d6 f7 ae 37 4f 06 13 3a 31 5c 62 64 da +65 ce f2 33 ed 3d cc 81 59 d7 6c 3a 17 f3 6d 0c + +# Encryption: +00 6f 1b 6c 1f b3 7a e5 c8 c0 24 44 9a bc 38 40 +e8 e5 09 71 43 ee d1 6b ea f6 7b 6c 7a 48 24 ac +38 b6 f8 c3 53 b6 45 c8 ce a4 fa b0 9c 02 fa 6c +32 5a 50 74 38 b9 64 5e c8 23 00 86 b3 15 e3 4e +7a 56 ad b0 ec d8 9f d0 7b 98 73 9c 24 db 6f e1 +1f f2 e5 ad 38 31 8e c3 1d f2 ed 25 08 de bc a7 +a6 7e 24 01 96 aa 9a cd 80 32 9f 4c 43 43 c1 0b +72 69 9f 9d 6b 5b c2 43 99 5b 09 c4 6d d3 d8 03 +ce + +# PKCS#1 v1.5 Encryption Example 7.5 +# ---------------------------------- + +# Message: +ed 26 ec 20 2d 5e 69 74 0d a3 48 84 06 bb bd + +# Seed: +f2 fd 08 cc 0d b9 a5 5a bf eb d9 2e 2a 9d 75 87 +2a b7 df fb 0b 4d a1 36 06 e1 52 75 9f 86 6f 22 +eb 87 29 fb 8c 9a 5c 45 ba 2f 4a ca e4 31 59 a7 +ad 3c f7 8e 81 fd 09 54 90 9b 1f 0e 70 89 ca 86 +a4 58 8d 8c 87 a1 a6 1f 1a 48 39 82 36 de f9 b4 +97 5e 25 49 57 3f 60 ad b5 e8 61 b7 c3 b2 df eb +81 0d 13 e2 97 a6 cd 3f 2a fe cb 0e 4f 14 7c + +# Encryption: +00 93 3c 58 a5 0c 70 15 0d a0 82 3a 7c 1e 36 7d +36 e5 21 3f 66 a3 00 50 fd ed 72 d5 75 5b 5f 9c +24 05 0b 41 14 f5 35 09 98 8b 62 54 20 cf d0 0a +c1 c8 cd 84 48 9c a2 6b 74 3f b4 7d 1b 64 d0 a8 +80 8e e3 21 27 c7 71 22 4a 0d d5 a5 64 e6 36 ad +d7 3b cf f7 b4 73 e9 a1 2b 7d 46 4d 7d d4 a7 52 +04 86 61 a8 b0 74 b9 fa 15 06 fe f6 03 dd 96 d1 +19 96 a7 d9 e7 48 79 f9 9b b2 d9 1c 37 aa b1 35 +72 + +# PKCS#1 v1.5 Encryption Example 7.6 +# ---------------------------------- + +# Message: +dc 28 5a 26 39 59 39 e7 99 72 04 c7 1a 93 2f 79 +5b 4d e4 01 e9 6f 34 e1 89 36 32 37 e9 cf da dc +61 + +# Seed: +d8 0b fc c2 91 ce 51 8c e0 bb 6a e9 34 df d8 56 +58 b2 39 fb 45 39 cb e0 5d a1 26 a8 98 b7 f3 64 +88 7c 0d df b1 ea ea 1d 5a 90 de 76 95 66 5c 55 +82 2a 11 72 cb 5b e8 a1 12 d2 8c 86 02 c5 13 be +48 c2 92 f0 59 72 e6 71 1a 44 cb c7 28 17 15 09 +4b 49 0f de 29 16 5a 6b 6b 7d 99 db ed + +# Encryption: +01 57 e7 b5 4a 34 1b 8d f8 bd 9b 99 fc 2e 6c 58 +d8 86 fc 79 e7 44 2a 9e 76 d0 d6 7e 48 58 c4 ab +f0 ed 25 c3 3d f6 2e 2a ad a3 99 df ea dc 7f f6 +89 28 e6 b9 00 71 02 dd f8 09 f5 90 8e ef c1 0f +2a 73 71 06 09 23 1f 5d 45 e0 0a dd a1 34 b6 02 +dd 0e ee 0f 67 22 49 4b 7e 4f 7b 40 57 72 c8 31 +b6 37 29 be 0f 1c 4b 6d 2a 54 2c 15 65 c7 df 23 +1d 9e 89 2e 58 6a 18 ec 54 37 73 76 db 77 f8 13 +84 + +# PKCS#1 v1.5 Encryption Example 7.7 +# ---------------------------------- + +# Message: +46 47 d8 41 c5 a0 b9 97 3a 91 45 4d d1 a0 5e c0 +e5 75 03 ed 99 67 2a c0 02 df ee 77 7f 7f a5 06 +fb 41 b2 ec 8b 8d 2c db 9b ef 01 33 bd 5e 3a 7d +0c 43 44 b2 8f a8 db + +# Seed: +f5 27 a1 4e 2e 06 e7 3f 1c 24 5d 19 0d 02 cc ed +01 1e 46 84 87 ac fa 5e 0b ce 39 78 6b 46 a9 a8 +c7 51 a8 b4 40 6c cf a1 fc 5b 7a b9 ba da 7b 4a +d4 52 46 7e 50 b7 fc 41 31 8e dc 73 dc 2d 84 a2 +8a 08 1f a1 79 05 bc + +# Encryption: +00 4e 03 ca a9 48 1d 7f 96 78 20 7c 17 b6 82 2a +5f 69 17 ed 01 eb 40 2e 7f 23 01 35 a1 23 cd 9b +6d e3 be c3 b9 bf 33 8a de f8 07 6f b7 65 2f c7 +e3 a3 73 fc 16 22 f1 dc 67 9d 41 5c 32 00 02 6d +8a 8a 50 f8 db 6a 58 3f 66 69 29 d0 31 8e bf 91 +d9 59 12 fc 06 10 2d 9b e8 75 25 a7 36 b5 af 21 +e1 6d e3 ef aa 66 e9 cf 41 ca 73 48 23 23 dd e8 +0e ec 30 85 81 a4 4c a3 aa bf 76 dd 48 1d e6 52 +9a + +# PKCS#1 v1.5 Encryption Example 7.8 +# ---------------------------------- + +# Message: +ba 10 d4 7a 9f 62 42 81 + +# Seed: +37 9f dc fa 5d 8c 61 37 c3 6b ad 14 3f d9 b1 f7 +e8 94 fa 0e 9a c0 fb 9c ec 60 e8 6c 82 53 97 5d +8e 78 74 21 08 49 5e 59 4a d0 89 8f d0 4c 91 e4 +01 e7 c8 80 89 a8 7b 4a 4a 82 e8 34 cd 37 77 a7 +d3 f8 0e 64 86 81 2d 4a b0 d3 37 23 16 2b cb c7 +e0 81 a9 9d 3f 9b 5c 3b a4 4b 19 bd f8 84 a4 62 +6f d7 de f7 67 40 57 be a0 82 e0 0d b4 b7 61 ad +75 3a b5 98 5a 94 + +# Encryption: +00 c4 96 5e 29 63 d7 bc 5b 10 44 d8 fc 75 eb 33 +82 ce dd 99 07 41 97 92 ef c8 8c 92 b1 d5 c3 90 +fa b1 90 01 1c 51 8a c9 ce 45 c1 b8 e7 27 6b ff +c7 c7 e0 5c 25 37 08 91 37 a9 8d f6 e0 c6 92 02 +0e d6 54 af 83 33 9b ab 11 92 71 77 f2 f5 23 22 +6b 4f e6 4b 99 c1 72 9f 6c 92 29 06 bc 16 d3 1f +0c 94 dc 2e a4 13 81 0d 55 94 0c 97 af dd 48 29 +fb f1 61 8a 8c 9d e8 9d c2 40 06 e7 e4 21 a5 8d +38 + +# PKCS#1 v1.5 Encryption Example 7.9 +# ---------------------------------- + +# Message: +ef c7 48 9f ec 77 9e 05 2e 37 9c 1a d9 04 59 03 +b6 84 2a 9c a4 1b 48 bd dc e5 80 80 a5 ed ec 63 +f3 6e e1 15 60 fd + +# Seed: +c8 ec ba 62 72 14 c4 14 d7 c3 fd d3 16 c2 d8 2a +98 53 57 28 b9 a9 37 6f 69 a9 53 d7 cd 1c ea d7 +10 53 db e0 14 0c 7f 02 bd 71 e0 13 7f ea 29 cd +4c 21 a5 8b de c6 66 40 99 0d 28 c1 0b 70 17 59 +3c 1d 11 fe 9a be bd 71 24 e1 d9 85 63 1e 94 e9 +e5 12 41 26 0f 9e f1 f1 + +# Encryption: +00 32 18 4e f2 88 fa 0a aa 0c 2c 1a 19 e7 c2 9f +81 c7 01 2f 45 29 eb 9e eb 53 68 1f 62 47 f8 d4 +35 69 13 45 a5 14 8a 2c 87 7b 2b 18 92 6b ae 9d +e5 b3 17 ba c0 e9 02 c9 60 25 ee c2 f9 ea bd 0f +9e 88 86 ef 95 19 c8 24 9f eb 83 46 65 c1 01 0d +b7 62 4f 48 7e 16 1f 89 f6 ae 00 18 c1 f4 e0 ab +54 72 f7 f0 99 35 61 cd 59 85 f3 83 d0 49 dd 83 +2b 82 c8 37 48 b2 28 1b fb 99 d9 d5 00 8d c8 07 +de + +# PKCS#1 v1.5 Encryption Example 7.10 +# ---------------------------------- + +# Message: +5b 26 4f f8 8d ef d3 c2 99 99 3d 81 12 9a 6e 5d +d2 b5 7b + +# Seed: +0b e7 ab 5b 29 70 48 43 c1 c0 d7 e4 ef 5e 93 f3 +ba 71 7d b7 81 5a f5 72 e3 a9 ab 3f 99 b1 ac 9a +22 b9 2d 9b 43 da 2b 99 65 c7 97 70 57 17 3c 03 +57 3f 32 48 0a 92 70 19 af ff 0e 0e 34 e4 09 5e +4a 4d 39 2d cd 1b d9 f2 7d 32 fd e7 15 9f 02 3c +83 08 9e 88 a7 1f 24 33 64 8e f8 c8 40 45 b9 c3 +6d 8e 5f 6e ff 03 4b 91 b7 02 34 + +# Encryption: +00 4c 65 29 35 56 f2 fd 15 ab 90 eb 22 e0 75 33 +b3 dc 17 33 4f 5e ed 27 a3 99 31 80 c5 6c 8e 3d +8f 51 ee b2 75 95 f8 78 d2 36 65 ba 3a b0 e7 28 +a5 ae f7 23 4f 60 36 b0 23 f8 71 c2 d6 55 2a 18 +ad 5a 25 be c5 5b c7 6b ee 63 83 46 12 81 d3 9a +30 f6 d6 60 92 e0 cf f6 92 32 68 fc 04 3c df 74 +7e 8d 54 89 50 4e 7d b3 0a 7b d9 1a 2b fc 6c 1b +34 14 40 57 01 75 3d 5b 85 ff 73 52 01 2d 55 e9 +23 + +# PKCS#1 v1.5 Encryption Example 7.11 +# ---------------------------------- + +# Message: +72 e2 09 00 e5 bc c2 3c f8 79 ed 35 31 88 9a 1e +d5 aa 3d 5c 79 2e 34 e3 b1 26 90 d9 ac 24 03 d0 +f6 f7 8f 59 23 + +# Seed: +11 62 75 e9 be 1b d4 e6 f2 03 ff e4 f0 ab 9a 32 +73 84 10 e9 23 e8 39 71 ee 9a 6b 99 2c 65 0a 03 +1f 94 0f 6e f3 3d 61 50 df f8 b3 9d cf 22 50 d5 +66 5c 04 27 3b 2b e2 de c9 97 12 bb c0 12 f7 5a +31 b3 0b a0 6f f9 eb e3 b8 9f 58 a6 8f 26 85 e3 +38 ff 6c b8 d4 18 1a 8a 14 + +# Encryption: +00 21 4a 83 be 45 3a 75 bc da 94 33 a7 b9 51 43 +34 39 98 30 72 07 1c c8 21 12 b7 77 42 be 0c 38 +22 6c a3 c6 f3 8d 55 b9 ca 3f 08 c8 79 37 89 79 +6e 6c de 67 37 6d 67 3f 5e c5 7d ac c3 74 c4 c3 +17 34 44 dd 8a 63 76 de 8f 9d dc 31 a4 c0 60 d7 +72 f0 2e b7 49 51 2d cd 04 02 31 17 5d 0b 69 42 +a9 47 b2 c8 2f 7c 19 e2 ce 87 50 00 af 84 27 4c +be 2a db f2 fb fb 53 7c cb e2 fb d0 72 87 13 78 +75 + +# PKCS#1 v1.5 Encryption Example 7.12 +# ---------------------------------- + +# Message: +16 b1 10 e2 90 9b 11 b0 cf 36 b0 52 c6 f3 93 6a +2c a1 3f c3 a5 + +# Seed: +c2 bf 9e 4f b1 ed 70 ca 21 2d 15 ee 8e b3 cd 66 +0e b6 5c 52 78 e0 3a 3b 10 eb 12 b2 53 34 a4 72 +8b 94 99 20 12 2f b9 92 bf 2c e4 30 10 3d 74 ab +74 e6 d6 e7 62 b8 5d 6e f9 be b7 d7 25 98 f2 93 +a4 35 62 e9 06 89 54 11 11 51 1d 31 4a 9c 46 02 +23 76 ad 05 5d 54 ce d6 ac 1f 36 e9 8c 2b 25 a0 +ac de 64 dc f6 52 2c 3d 22 + +# Encryption: +01 6a a9 5a 08 23 82 c1 0c 04 53 10 fe fe cc 8d +17 db f2 16 d8 ed c0 4b da cd 4f 52 4d e4 85 b7 +fe 8a 26 f1 4c ab d2 97 e7 f0 3b 3c 85 08 6a 16 +14 7d 5f 61 93 91 9b b9 5a 53 c1 46 c7 84 c0 0b +53 32 e0 18 f6 43 cf 95 87 24 cd 08 07 5e b6 4c +a5 68 0c 27 c7 05 d4 0d 88 b9 d7 f4 26 b7 36 e3 +c5 f6 39 4e a6 83 b6 5c 23 73 a6 fc eb 14 f2 ea +85 1c a8 e0 00 e2 4d c8 f7 e7 c8 1b 1d 4e 72 0c +36 + +# PKCS#1 v1.5 Encryption Example 7.13 +# ---------------------------------- + +# Message: +3c 86 0a 28 fa e8 da 2a c0 d9 a3 39 89 97 7f fa +04 + +# Seed: +7c 96 99 90 6c 9f 16 65 12 5c 0b 10 67 3f 3d ad +98 c9 1a 4f f0 fa aa 64 7d b5 54 fd 62 27 ef 50 +90 9c 97 b7 06 09 2b e2 10 db 2c 24 ba 9e 8e 6a +87 f9 dd d9 f3 f4 91 29 10 29 ac 6e e4 6e 08 d0 +d7 a5 3c 46 2d b4 f0 fd 1c c2 3e c8 f5 5e da 07 +f4 ca 0d 3e 3c d3 76 22 85 5b 4d b0 8f 64 be 3e +26 c3 e9 78 75 17 12 94 ea df 86 fc d6 + +# Encryption: +01 0c 1e 04 a8 58 c6 15 ee 96 95 f6 4a b2 db 99 +80 6d a4 82 d2 b4 60 29 3c 46 dc 7b 71 7a 59 76 +a3 c7 e3 6d 8d 47 a8 4a 34 d6 3c df ca 2c 1e 38 +45 25 73 ed 44 c3 a0 40 40 5e cf 3f bf 36 83 41 +c4 a1 fc 90 83 a8 f5 52 93 67 b9 9c b8 9f c5 a0 +8b 8f 34 75 a0 d5 5e 3e 42 cc cb eb 20 d0 4a 19 +97 ee da 4e 3c c9 e9 92 d2 37 ec 7d 32 fe 25 84 +5a b0 24 d5 88 28 05 ed 52 f1 0e d7 d2 5d 62 d0 +af + +# PKCS#1 v1.5 Encryption Example 7.14 +# ---------------------------------- + +# Message: +4e df 4a d3 44 0f 17 b1 0d 26 af cd f4 e4 44 d2 +aa 61 a1 97 55 a6 21 07 98 3f 01 22 fb 2a + +# Seed: +e0 20 09 39 39 b4 18 9e 93 4c b6 2d 27 ca 5e 97 +19 65 2c 13 7f c4 9e 72 1c 4a b9 e9 f3 98 b0 a6 +12 de 8a 8a 89 99 af 0d bc 1c ea 0b 61 63 da 42 +61 23 28 14 ed 92 eb 21 60 cf 4b 26 d0 55 1b 1b +dd 91 9d 49 47 93 78 6e 1b 86 f7 9d 64 16 61 2a +28 22 61 36 3d 6c 9b 7a 0d 92 ad 17 58 ea ad 51 + +# Encryption: +00 8c f9 b3 f3 e7 60 90 d1 01 17 4e cd 97 d1 0b +ff 6d e4 d4 64 40 00 3f c0 d4 28 f1 9b 85 58 f3 +13 74 a5 fa 28 3d 03 d4 dd 43 f9 3a 4d 9f 14 ca +00 68 dc 2c f3 e2 54 37 b0 5a b1 d4 06 21 ee bd +84 16 f5 82 8a e7 c6 cf d2 97 b4 51 8f 79 94 2b +91 43 23 28 4e 29 76 a5 4d 3c d9 11 63 3a 30 7e +da f1 ed b6 74 98 46 6b 3e 98 91 6f 99 04 f4 a0 +ea 9b 87 a9 83 44 f0 73 83 3e df 9b 2b 53 94 cf +d7 + +# PKCS#1 v1.5 Encryption Example 7.15 +# ---------------------------------- + +# Message: +8a 6d 53 b0 ad a1 85 4e 23 13 69 1a ab 23 06 3d +e1 31 bc 36 c7 64 + +# Seed: +26 85 45 8a eb fb d6 07 4e be b0 fc 0c c4 92 1c +27 3e 8c 0a 88 15 51 50 2e 4c 29 9f 33 4d d5 67 +f5 16 75 b0 ff 30 f2 c4 82 63 20 03 64 99 66 99 +f9 b1 72 af fe c0 e7 9e 5c 52 3d 1e 77 9e c0 6d +ec d4 76 a5 74 30 78 1e 2d c8 1f 25 d6 0d 3a 73 +97 65 79 a2 f0 1f 07 58 4c f8 e5 fb 3e bd 8d 5a +93 2d 57 aa 8a 18 0a aa + +# Encryption: +01 3a 3d 32 ee c7 35 eb da 13 f8 be 76 02 a0 47 +5c f3 cf 28 5b 42 86 ad 93 d6 12 c3 ad 91 72 48 +80 9d 1c 4c 18 0b 36 70 15 cc 66 c4 d8 e7 86 73 +84 16 8c f4 cb 71 9b d5 93 35 53 55 cd d7 d7 53 +0c 80 c8 67 74 5f 96 61 c6 c3 3b cb 97 f2 cf 75 +a4 c2 7c 3c bb db be 7e af 4f 82 34 f2 12 e3 05 +82 56 d4 43 9a 9f 97 81 df 48 ef db 02 35 68 f9 +4a e4 59 46 54 a0 f9 ba f6 ea 30 b7 d8 d9 48 0a +d3 + +# PKCS#1 v1.5 Encryption Example 7.16 +# ---------------------------------- + +# Message: +20 f0 20 44 e6 3a c9 2e b9 fa f1 a0 ce 35 ba 72 +09 + +# Seed: +2d e1 fc c1 17 f8 21 f1 de a7 94 b5 ee b3 13 f4 +29 e0 0b 97 6b 53 41 9d 3d 03 ec aa 1b 50 76 88 +77 e8 b7 fb d6 c3 63 04 7e 15 c2 55 79 3b 3c be +0f 58 84 f0 a5 11 25 4d 31 bf b2 37 41 02 3c 1f +88 1f e0 16 a1 2e ef 1b 8a f2 2b 93 68 20 7e 7b +16 39 f7 27 1d eb e3 c8 df 52 93 ee c3 a0 32 f1 +ce 55 9c 0a 04 77 1b bf 88 98 94 7c a4 + +# Encryption: +01 70 06 e8 6f 6c 58 58 fe 5a de 0d cb fa 9c cd +11 c0 2d 4e 7d 0d e6 c1 58 ad f9 ee f1 01 07 e7 +a4 c3 6b d3 d9 29 ea 6a 47 6e cf a0 b6 ec d0 51 +49 b5 12 15 95 48 93 a1 ab 26 69 c0 42 da 83 e8 +c8 18 b0 0a e7 34 de 5f 9e 0b 97 ba 1f e3 e9 c4 +6a e9 81 6b 63 b1 5c 2d cc 61 cb 3b 8b 2c 23 dd +b9 9f cd 54 e9 55 60 91 8b 9a 0f a3 c4 b6 27 3d +1b 28 a2 13 e1 20 b4 f2 42 86 96 5e be e9 4f f8 +96 + +# PKCS#1 v1.5 Encryption Example 7.17 +# ---------------------------------- + +# Message: +d3 88 3b + +# Seed: +5c a3 bb f9 92 d7 ae 35 94 c6 05 c3 9c 3e 97 90 +25 cc b0 a3 5c 6e f0 fa 57 4a 98 be 05 ef 7c 32 +8a 19 a2 77 5b a0 6f 2d d1 e0 ff 6f 0f 1f 6a 3b +20 fb da 21 62 d0 92 4f f5 5b 70 eb fe 2b 16 d4 +ff 6a ef 8d 47 eb e5 96 38 e5 81 0f fd b5 8d b0 +5f 4d 9b 4a 3a 42 3f 96 7f e5 79 f8 73 78 36 9d +5c 5c 07 e5 e3 cb 5d dd f3 89 62 11 80 27 0a 21 +e0 10 78 c8 9a fb ab 18 9e 87 f7 + +# Encryption: +01 6f 55 05 f7 4f f1 10 4d a1 f8 a5 2e 50 bf e2 +9c 99 87 10 c5 7d e4 40 98 a9 57 9e 7a 33 13 b6 +29 60 31 02 f0 8d 2d 91 1f 91 7a 9c 96 62 60 8c +97 a1 ea 37 17 34 f6 7c bf 70 03 d9 3c 4c 31 4c +3a 0e 77 f3 65 8f a4 d0 72 25 62 c4 e1 3e 85 a7 +c8 d0 d9 d4 fb f7 12 58 84 ba 62 ad 28 59 b4 d9 +61 36 f7 a2 45 54 69 ce b6 0b 63 ba 84 74 e6 16 +0c 83 17 92 1a 07 b4 b6 43 6f 37 6c 5f 98 25 7b +17 + +# PKCS#1 v1.5 Encryption Example 7.18 +# ---------------------------------- + +# Message: +06 a2 ae 82 a4 85 32 07 c9 f9 75 + +# Seed: +e2 c3 36 33 d5 47 54 ad dd 24 c8 5c 32 d2 8a d8 +70 f1 60 3d 44 44 60 a0 3a ac ad 7d cb 80 96 01 +56 bb b2 59 ca d3 46 be 90 c0 d4 f3 fb 18 ac 6e +9d 5a 9a e2 a5 ab 98 a1 f8 4b 8e 70 c7 1d 0c cc +0a 1a 2a a3 99 70 d9 c8 3b 4b 0c 25 ae a4 3a 5a +5d ea df 9d c6 11 b9 6d 11 33 4e f9 43 09 03 89 +a8 d3 c6 6c f3 18 77 aa 2c df f1 11 99 43 27 8a +dd ff 5e + +# Encryption: +01 22 41 0e 76 5b 2c 9e 90 bd ac bc ff 1b ca 8a +e6 4b e9 9c f0 13 29 74 85 72 17 68 37 0c 36 f8 +c0 d9 db 8d 79 37 62 54 b9 c6 91 52 72 0e 05 ca +ef d4 ce 7e ae 08 b3 df e3 ea a9 1c 46 02 ef f3 +8e 4d 81 bc d3 78 7a 14 d6 22 db b7 9c e8 64 4c +4f d1 d2 e4 1f 7c 1c 97 27 96 11 74 0f c5 00 00 +31 78 b3 7b bd 81 c5 a5 82 9b 5c 14 bf 45 9c 42 +38 b0 3b ee f7 3e 49 8f 86 5f 6c a7 9a 9e d6 0f +65 + +# PKCS#1 v1.5 Encryption Example 7.19 +# ---------------------------------- + +# Message: +ad 8b 11 a9 27 de + +# Seed: +5e ca cf f6 3a 79 38 e9 98 06 8a 2f 4b a6 bc c1 +02 0e 1f 28 c7 34 e4 34 e8 86 3c 48 e6 df fa e2 +8d 18 52 72 7f fa 7f 2e fa 3d e7 01 3b 81 2a 02 +b2 17 1a 0f 94 0b 36 d9 28 db db 96 0a 6b 22 03 +0c 89 37 89 cb fd ea 97 35 e9 ad 10 94 a6 84 61 +c2 eb 6f 71 8b e4 74 d9 3a 51 93 0e 3c da 02 c2 +1f 63 63 91 4e 7e da 54 84 03 7a 76 ad c5 33 12 +eb 9d bb e4 5e 23 a1 4b + +# Encryption: +01 1f a4 3f 5f 4f bb 98 30 11 81 4d 4a f5 45 52 +1d f0 b5 9e 9b 6f fd 71 33 3b 8f 9b ba aa 0f cd +c1 42 1c e4 bf 31 bf 99 59 fd c6 b0 9b 4f 42 51 +dd ee e8 21 0f c3 a5 2f e7 c7 1a 87 6e 6d de 1d +fb 59 a4 da b2 7d 34 fd ce 5b bf c6 ed 62 3e 89 +96 7f b6 fe 73 16 20 15 28 2c 5f 45 01 38 f2 50 +4a b6 1c 1f 12 d2 64 9d 81 5d 6e 81 38 43 8f 8a +80 46 c4 e8 40 cb 71 85 98 e1 e4 a9 fc 25 a9 45 +64 + +# PKCS#1 v1.5 Encryption Example 7.20 +# ---------------------------------- + +# Message: +be e2 94 36 c2 a0 de 16 f6 60 42 91 70 07 fb 51 +30 f3 c1 aa 7d f2 c7 c3 bd 99 fb c1 b4 13 af 4f +96 a6 5b 0e 54 3e c6 a5 0b e8 3a 9f + +# Seed: +23 91 a6 84 25 dd 8f 0b 83 c9 b3 61 24 67 a7 79 +cf 92 f5 ff 96 11 c0 14 93 bc be f8 65 e1 5b ba +5e 8f cf 74 be b9 ea 25 73 a9 fc e5 41 64 d0 6b +aa 8b 6d f3 67 cc 4c 6a 11 4a a0 34 6c 45 4a 2a +9e 60 53 59 18 d3 66 0c 66 48 4e d9 53 72 7a 9c +9a 25 + +# Encryption: +00 98 9d db d2 8d 60 95 ad a6 88 1e 28 34 1c e7 +a0 a1 ca 6b f7 f3 1f 77 2f 91 04 93 af db a2 d6 +35 9d 50 b9 83 3f 83 d0 ab 87 13 ab e8 e2 10 2a +27 ab 2a 60 1f b7 7b 9a 25 d6 a0 af f4 0c fd cf +9e 12 c4 28 43 eb ad 32 83 24 a7 19 f2 9e 8d 79 +ea 9e 5d 0d 98 86 95 73 60 34 db 5f ea 73 dd 36 +00 13 6f 57 a3 98 fe 35 2b 27 8c 60 cb 74 ec 98 +ad 57 a3 e1 d8 c4 47 8c a6 17 9f 4d 04 26 f0 f4 +20 + +# ============================================= + +# Example 8: A 1026-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +02 52 e9 5b b1 1b a1 e1 c7 c9 5b 68 53 f8 de 0b +fe 2b 64 03 ac 1b de 81 9d 91 89 07 74 7b 01 99 +fa db 80 59 c2 5a af 1a c5 65 a7 49 29 d0 15 a2 +01 f8 97 a9 ba fe 75 41 68 95 5b 35 5b b0 09 ce +16 14 93 12 28 3c 39 ce e2 20 d0 f0 85 8b 13 81 +2e 86 a7 d4 e5 38 8b 7e ae 5a ca 7c 88 6a 76 d3 +b1 e6 dd 67 92 68 a8 23 11 e2 82 03 18 cb 8f 0f +7e 85 f0 e6 69 2e b0 de df 30 88 1c af 73 15 d2 +7d + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +02 52 e9 5b b1 1b a1 e1 c7 c9 5b 68 53 f8 de 0b +fe 2b 64 03 ac 1b de 81 9d 91 89 07 74 7b 01 99 +fa db 80 59 c2 5a af 1a c5 65 a7 49 29 d0 15 a2 +01 f8 97 a9 ba fe 75 41 68 95 5b 35 5b b0 09 ce +16 14 93 12 28 3c 39 ce e2 20 d0 f0 85 8b 13 81 +2e 86 a7 d4 e5 38 8b 7e ae 5a ca 7c 88 6a 76 d3 +b1 e6 dd 67 92 68 a8 23 11 e2 82 03 18 cb 8f 0f +7e 85 f0 e6 69 2e b0 de df 30 88 1c af 73 15 d2 +7d + +# Public exponent: +01 00 01 + +# Exponent: +01 04 c8 5f d5 d8 d7 93 2a 29 85 c4 cb 7e 9e 13 +a2 c4 f1 90 3c 8b 70 f3 df 97 12 fa ee 20 17 b9 +20 82 c5 16 53 c0 bd de 9d e6 6c 39 01 b7 c2 2b +e4 f2 4c c5 6d ff aa 75 d4 3b 18 a2 e0 c0 df e3 +72 6b 19 8c aa 0c 96 65 26 3a 93 79 6a 27 d3 29 +84 46 5f 4b 4a ff ca 0d 92 f4 e5 1a 37 e4 1a b1 +55 07 66 d5 ca 7e 90 d4 de 90 9b bd 79 4e 8b c5 +2b 74 99 a7 3e 46 8a b4 42 13 cb 3a 3b 54 52 d2 +ff + +# Prime 1: +01 93 3f 8f 85 82 b8 ff f3 e6 bd 30 42 81 97 f0 +ac ec 63 e6 91 f7 9b 91 fb d4 d4 c4 94 2b 8a e9 +13 a4 01 f0 e1 7b a7 66 d0 a8 ee ec 4c b0 e3 da +17 b6 d9 1f 1a 74 24 88 09 20 1e 37 30 15 18 61 +8f + +# Prime 2: +01 79 ad 28 3c ac 68 af 21 6a 06 86 f4 38 b1 e0 +e5 c3 6b 95 5f 74 e1 07 f3 9c 0d dd cc 99 0a d5 +73 dc 48 a9 73 23 5b 6d 82 54 36 18 f2 e9 55 10 +5d 8c 4a 5f 49 14 be e2 5d e3 c6 93 41 de 07 ed +33 + +# Prime exponent 1: +01 6e f5 3d 6f 3a d9 8d 9a 6f d4 a4 71 31 2b 8a +8a 62 88 3a cf 84 6b 5e fa b3 e0 77 8f 7a dc 6b +64 43 30 bc fb 04 a2 ff 0e 4d 5d 37 4e 46 fe e2 +7e 08 18 27 94 d4 32 56 55 2f 94 2f 96 a2 eb d0 +03 + +# Prime exponent 2: +e6 c6 e6 25 5c fc 82 b7 1a 40 6e ca 60 b2 60 c8 +45 07 42 39 18 04 41 85 9c 3f e4 de 16 4e 46 6c +0b 98 e2 e2 16 22 d1 e1 a7 6f 7f 03 3f 8c d8 f9 +30 b6 69 4f 10 bc 2b 3a 4f ea 91 24 d8 75 63 7d + +# Coefficient: +35 42 45 2e 83 2c 16 ac f9 c3 f4 13 49 23 5e dd +d2 75 c7 05 3c 55 3b f8 9e 1a 84 57 12 48 33 3a +ad 52 0e 3a 34 46 c4 c5 e3 fd d9 ba ec d9 29 48 +0e b5 b8 fb ef 8e 03 ad e9 e3 9a 28 fd 8e 75 6c + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 8.1 +# ---------------------------------- + +# Message: +f7 26 37 ae c2 8d 2b 6e bf 8f 73 d7 48 75 df 01 +cd 12 24 8f 00 20 60 8e 61 c7 3d 1a 01 f9 72 f7 +4d ee + +# Seed: +cc 20 77 a2 40 01 f3 e3 86 96 94 e4 fe 27 72 bf +93 8f 76 27 66 7b 62 d5 90 f9 ee 4f cf ff bb b4 +7a fd 5f ed 6a 18 08 44 a9 12 1a 32 ed 7c bc 56 +cd 28 70 a2 d6 96 b9 43 d6 fd e9 76 7c 1b 96 48 +61 6c 32 ed 6c 40 0d 42 3d d4 ab 72 16 af ad a0 +28 40 2e b2 a1 c3 eb cc 24 5a fc 7f + +# Encryption: +00 72 57 5d 3b 11 c5 ff d6 ae 24 f3 53 ff 74 99 +27 b4 ae 5d f4 63 f7 0c 5f 3e f5 49 6b 0d 14 5e +b2 b8 a5 3c 28 d5 3e fe 8b f9 f2 7b 2e f4 ce ea +48 31 05 77 c3 d2 b4 b9 49 a1 2e 3d f3 f5 67 76 +82 88 18 45 2d 81 bd 45 af 15 8c 87 bb 57 74 5b +8a 10 fc 1a 92 a0 ea 55 c8 51 39 f8 42 f7 3f 1d +61 3b 9a 96 4a f8 ed 72 0d 0e 08 47 f7 ae 5b 30 +5c 05 f1 2c bc 4c 9c 16 84 ac f9 02 97 0d 82 09 +49 + +# PKCS#1 v1.5 Encryption Example 8.2 +# ---------------------------------- + +# Message: +2a 8e 3e e7 ea c6 b2 2e c6 58 ad 44 d6 66 c8 cd +3f 57 ec ea 29 9b 5c b7 bf 9a 37 3d fa 66 97 2f +13 e5 f3 a3 00 e8 0e 6d bf 74 15 68 0d 0d 24 90 +1a d6 b1 40 b0 00 aa b8 53 51 f9 2f + +# Seed: +fb 19 20 9d 8a 29 af af bc 05 3a c1 f3 20 ba 60 +fc 1f e1 04 aa 78 39 c8 4c 9b 3e aa 18 a8 f9 43 +bb 21 9f 59 cc 16 7a 38 4b ac 7b d3 65 82 4e 10 +36 31 b9 7b b9 a6 d1 18 f4 f0 a9 51 fa 47 8a 05 +ea 09 + +# Encryption: +02 1b 54 64 65 71 a9 a9 3f 0b 0a 03 82 e5 40 a8 +c3 97 4c b3 1c 87 eb f1 7b 3b a6 2a 1c 95 21 c5 +0d 7f 90 70 2e 13 ae 0e 22 26 38 34 e7 64 60 35 +15 94 45 a0 87 7d 9a 4f 5b 16 17 7f 7f e0 52 bb +d0 23 d0 81 89 4f 2d 97 ca c2 45 20 76 ca 11 91 +a1 71 a4 8f a1 cb bb c3 f0 f6 f3 bc 1a 44 78 40 +3a 5a 48 8f eb b3 a4 13 80 16 3d 94 2c 97 7b b8 +ec d2 86 6c 5f 5d 91 9e d2 0c 0d b3 ee 31 ef 2f +51 + +# PKCS#1 v1.5 Encryption Example 8.3 +# ---------------------------------- + +# Message: +d9 9b 4f 10 d9 f3 2e 12 ec fa e2 63 0b 22 ac 02 +6a f9 64 b9 c7 15 d2 07 + +# Seed: +e0 af 8b 7e ab 36 a6 ee 31 6d 78 13 67 f0 9e a1 +1e 31 fd c1 ef 2c f9 c9 7c 37 9e aa cf 68 72 a8 +21 3c be 4c e2 e2 9c 77 8b 35 95 40 10 06 3f 17 +76 ab 5b 17 2d a6 24 b4 06 a1 c5 8e 0b 57 4a 03 +b1 b1 b2 cd 7d 3a 9e 50 35 a9 a9 73 05 8f 04 97 +65 2d 2f 73 b1 dc 8f 48 7c 09 cf e7 1d 8f f8 f1 +45 8c 79 0e e0 c5 + +# Encryption: +01 02 3b be 85 57 c2 63 0a 26 22 46 db 7a bc 54 +03 43 88 70 38 f6 4c 64 1f d7 4e e8 74 ae 96 70 +fb 28 62 d4 24 70 3d a2 0b e4 f4 8b 23 9c d0 60 +43 81 9d 8f 61 51 44 e2 b1 f0 0c 8f 88 49 2e 62 +f6 e0 73 16 f8 49 05 35 3b 0b 18 80 ed 77 da 2b +62 d3 a9 3b b7 0f f6 a5 00 79 38 b9 73 b4 cd 5a +bf ee 0c f1 3f 5d 4a b2 16 01 02 68 5c ac 80 81 +83 4f 95 55 80 6b b3 22 d0 dc 5b 8a 2b f1 28 45 +62 + +# PKCS#1 v1.5 Encryption Example 8.4 +# ---------------------------------- + +# Message: +ca ec a8 e5 9b 81 0c f7 51 12 f7 ed 04 7a 46 69 +2c a0 b7 a8 6e 18 41 d7 19 + +# Seed: +76 1f 68 64 dc eb c9 5a 77 9b c0 b1 6a 95 86 6c +33 dc 8d ca ce 61 cd 7b f9 01 72 d9 9a a4 57 db +6d 90 88 7d 84 c4 73 8d 25 cd f0 e8 95 69 ae 47 +d3 07 3e c4 46 ee ed d5 2d 57 20 8b db 69 45 57 +03 46 57 a7 03 78 49 37 ba 69 4d 42 51 21 38 53 +2b 8a d1 d9 86 fe 47 31 8b 28 23 de 82 ce 27 6f +a6 f0 d3 c8 ef + +# Encryption: +01 1c 0c 03 f7 b6 e1 c1 a8 41 17 40 a6 e5 b4 73 +c2 8d 62 21 17 6c 9d 4f 68 02 4c a5 7c da 27 3a +f5 54 74 03 60 99 0a 1b 74 de 34 bc ea 10 3c 2d +0c 36 57 60 02 08 0b 30 bd 28 f0 76 fb 75 fc 9b +eb 9e 05 d1 98 9a 31 1d 12 c1 f2 8f d6 93 92 ad +4b e5 2c e3 89 de c1 1e ba 94 6b e0 59 91 da 7f +d8 87 a8 d8 76 8d e7 36 b9 05 bf 4b db e8 8b 85 +df c3 b2 5a ea 30 fe 90 df 1d 22 d8 a8 d6 15 65 +1c + +# PKCS#1 v1.5 Encryption Example 8.5 +# ---------------------------------- + +# Message: +10 12 12 85 6e 60 cd 27 2f b1 69 cf 62 cf 47 f1 +bc 50 ef 9f 1f cf d2 14 81 6c 80 7f 18 4a 90 3f +16 f0 e8 09 ac f5 e0 + +# Seed: +60 43 c8 df 6a 7f 4a b8 3e 31 97 e8 cd 02 25 dc +38 66 b5 d8 e6 99 3c 2c c5 b8 76 35 1e e3 3c 71 +c1 a4 cc dc e4 5f 3e 9d c7 b7 e5 1b 52 ee be 0e +27 0e 71 62 07 ca 14 03 e1 3e 72 3c e7 3f 10 45 +5e db de 85 b0 82 90 52 ed af e5 6e 9a 22 02 4d +40 68 37 1d 36 c9 1f + +# Encryption: +00 05 c5 cf f8 9b 93 3d 8b 65 23 b3 59 06 bb 3a +71 1a 0f 7f 50 3f 92 14 74 66 59 85 03 91 27 30 +3b 00 11 e7 a4 2b 41 c3 3b d2 0d b3 1b 15 60 c9 +b5 22 20 89 cd cf 53 b8 2c 95 f8 c1 ad cd 8b 78 +3f d4 b4 8a 45 40 20 66 8e 0b 62 52 0e 52 58 52 +09 db 52 9f 38 70 86 49 d8 e0 64 89 0b 22 8f b3 +c1 98 1b 2a ef 3a 54 65 ce b1 30 21 eb e0 8d 02 +e3 3a a2 dc 3c 39 28 4e f7 a8 58 dc ce b2 8f fa +28 + +# PKCS#1 v1.5 Encryption Example 8.6 +# ---------------------------------- + +# Message: +6f 03 b5 72 52 30 de 7f 99 63 69 8e db 79 75 ec +e8 + +# Seed: +a3 0e e5 ae ab 59 31 03 3e fb 70 af bc 2d 3d 11 +a6 33 84 cb 8c b3 3a 8f ca e6 14 66 84 e6 3f 0c +c3 2e 89 a7 e4 ea 43 32 7b f0 35 66 95 43 19 28 +86 de c3 fb 4e 2d 08 11 ef a9 ae c5 10 9e 31 b6 +a0 56 e5 3e 31 7f 6a 90 4b 13 a7 35 6f 5e 7a e6 +0b 97 21 5e d1 48 17 d2 8f 74 b1 64 0b 1f 2e 42 +ef 0d 38 ca 35 a3 54 a0 af ef a8 03 a4 + +# Encryption: +00 10 bd 2b 35 6f 9e ab c2 2f 7e 68 f7 2f 61 75 +f9 ab 9d ed a9 64 23 b7 4b 11 de 82 c6 07 a1 38 +86 3e 17 96 6c 07 f5 6c de 9e d6 bc 42 2e d9 fe +aa 1f 65 36 7c cf 91 cd 4c 91 58 a7 49 57 1a 0e +9f 96 07 cb 48 cd 00 a4 48 de 03 64 91 06 ce 0c +24 06 aa 50 aa 12 17 17 8c db 06 80 1c 70 a8 9a +7a 1a 83 06 8e 68 db 95 d2 4c a3 db 33 a7 e5 e4 +3a 68 15 22 74 bb bf 40 06 d9 fb 69 f0 51 4c c9 +e2 + +# PKCS#1 v1.5 Encryption Example 8.7 +# ---------------------------------- + +# Message: +87 99 13 04 54 61 bc 0e ac + +# Seed: +c3 c6 a2 4a c3 40 a4 a3 ff 3b 2c 30 2b 56 eb 83 +91 bb d9 5f af b6 64 78 38 44 38 ab d8 b4 5d 13 +2b 26 99 09 b1 87 84 0a 68 44 ad 39 9f a8 13 72 +05 e0 2c ca e7 77 5c e6 66 21 20 e1 54 b7 bf d3 +0e 8e a4 d3 4a 7d b6 a2 34 88 a5 da ea 38 08 5b +ed 56 78 0c ff 87 27 12 5f 1a d5 f9 d5 a0 bc 3b +e5 80 bc 4f a0 68 26 7b 27 de 38 3c 55 c7 fc 17 +64 c8 6a c2 1a + +# Encryption: +01 d2 1e ce 33 f4 40 c7 2a 11 1d 62 ef 48 6c 77 +c6 c8 90 cd 81 a4 eb 05 32 ad 2c 0e c7 68 dd 1d +e5 b2 11 2f df 04 e2 87 a9 5b 95 0b 1f ca 5a e6 +93 cf 0e 8a cc 93 6f 37 47 14 de 74 95 90 8c 29 +15 a7 07 21 3a c3 db da ba d8 1b 4b a1 cb 50 b9 +5f 93 14 53 1f ec 83 3f 08 21 c0 4b 57 40 d7 3b +8c f1 f9 e3 d7 ab c9 74 49 26 13 8f b0 15 c0 f0 +56 cc 4b a2 f3 16 37 34 db 44 3e bd 68 85 8c 4f +a6 + +# PKCS#1 v1.5 Encryption Example 8.8 +# ---------------------------------- + +# Message: +5b + +# Seed: +42 b9 99 fb 16 3a 6f fa 67 a9 bc 4e 6b a1 2f 81 +b1 d5 6e 54 bf 08 66 39 7f d3 14 eb 0c f9 7f 13 +b7 80 4f 76 8f ba 54 06 21 f0 5c d3 72 64 d8 e8 +f5 82 28 fb 6a b3 0e f5 4e 30 fa 8c fc b5 a8 7e +14 8f ba bf 85 88 6a b1 f0 d5 25 49 2f 56 c6 47 +f7 22 9b 2b f3 94 a0 ce ab bd 37 c9 3e 6d a8 09 +7e 82 72 7b 3d 53 e8 c2 ad 1f 77 13 e3 4e d1 3b +a5 9e 0a 91 4d b0 6f aa e4 9c b3 79 96 + +# Encryption: +00 90 e5 35 59 47 90 2b c3 fb 58 0a 84 77 09 03 +a3 95 5b 3d d7 19 1c 92 8f 74 07 ba 74 72 65 dc +8c bc 1d 22 f9 37 72 72 b1 a8 c3 5c 23 8f 04 a1 +19 37 d1 b4 35 4f 64 37 95 e9 86 de e2 e4 0a 40 +67 41 b0 21 fd f0 5c 4b a1 15 62 e8 3e 9f 28 59 +2e 0a 79 14 fe 88 b2 c0 fe 7a 5e ea f5 00 f7 e9 +8a 5b a9 54 f7 50 77 bc 8f 65 9f 21 bb 22 03 31 +4b e0 d6 d2 1e 63 20 c0 5e 6e 2d 55 79 79 22 6b +80 + +# PKCS#1 v1.5 Encryption Example 8.9 +# ---------------------------------- + +# Message: +f6 35 29 90 13 24 a2 0f e5 e9 25 8a da 2f 95 37 +b0 1f 58 39 b4 45 97 e3 29 3a 12 25 ca 3a 2a df +68 4a 72 a7 93 c6 9c 56 af 2d 34 98 d3 2a 09 2e +91 4b + +# Seed: +7b fa 85 97 a4 34 cd ad fe 15 63 14 44 95 13 d7 +6c 10 5d f1 bf c4 8c 4d 07 6a bf c0 5b 5d da 72 +e0 dd 15 f9 fe 82 a9 95 5b d5 6d 33 43 e7 c6 f2 +5a 60 74 12 07 e7 3a 2d 10 bb 95 d1 d7 29 a2 27 +93 e6 c4 55 e9 16 23 5a 81 16 94 db + +# Encryption: +00 ad f4 78 74 67 ea c2 ea 61 fe 7e f8 2f d8 7c +2d a5 89 9f 30 30 2b bc 11 27 86 d2 fb 11 c1 42 +f3 f1 d8 cf 37 16 0d 2e 4a 43 98 3f fb d3 93 a4 +1b 59 9e e6 a2 7e 24 64 25 50 2d 46 90 20 2f e5 +f8 ee 1b c6 c1 d5 d1 6b e2 3b 97 3a ed f7 f9 11 +1b d8 b1 42 84 42 65 fd 93 57 7a 43 c3 ac c6 e2 +af 20 89 d9 d2 f3 f3 1a 5c 24 7a 7b 68 31 5b ae +25 d5 ae 81 40 a5 1f fc 00 97 10 7e c1 62 0a b3 +b5 + +# PKCS#1 v1.5 Encryption Example 8.10 +# ---------------------------------- + +# Message: +c6 d1 4b 04 71 45 f3 17 78 1d d7 38 2d c0 a9 72 +57 d5 54 bb 53 53 9e e9 a2 92 e7 da 5c b6 42 6f + +# Seed: +01 ff 38 d5 de d6 c4 3d c1 dc 5c 27 a7 e4 81 3f +44 8f 45 c9 6e df 4b d9 3e 96 fa da 9b c8 ec 5b +43 4f 06 19 a3 8e 04 35 6e 06 27 85 51 40 7b 7f +37 e4 2d 91 45 62 0a 81 98 18 50 a4 9e 28 51 17 +2d 23 0b 37 82 41 10 f8 ff db 84 77 94 63 9d 26 +50 cb ed 36 26 01 05 f1 f1 29 6e 52 a7 d4 + +# Encryption: +00 5e dc 93 97 89 cf bf aa ff 28 2b af 97 01 d6 +1f 9d be e6 f2 d2 06 cf ab 77 57 61 f4 2c b2 74 +ec ba 31 c7 cd 2f e6 03 1a ba 0b 84 d4 62 7d 30 +37 e3 1c e7 e1 56 23 ba 7c b7 69 02 51 c0 63 27 +a4 31 37 12 98 df 29 21 95 b6 45 11 62 d2 da 92 +a7 07 8e 2d 07 c9 f5 6a 07 06 8a 9a 3e 17 3e 4a +ae 25 a5 d1 c6 8e 68 20 8c b5 25 3a 0a 53 aa 6e +2e f6 c2 95 d1 51 65 69 b8 62 cb 92 ca 82 3c cb +ab + +# PKCS#1 v1.5 Encryption Example 8.11 +# ---------------------------------- + +# Message: +c1 16 53 e8 10 b5 3e 65 11 f1 33 23 fe 52 26 a1 +70 c2 1f 6d aa 44 29 d9 68 ef da 05 29 d7 b6 e1 +0d ce d8 0c 6b 63 01 de d2 2f 52 91 1c 0f 7f f4 +53 5b d5 e2 0f f5 35 88 cd 3d e6 64 8a c0 2d + +# Seed: +85 fa 7c 6c e9 6d 0a 8a 1f ba 75 04 71 7c cb e1 +37 13 80 93 95 6e ff 06 3f c2 ef d4 a4 6d 7d c7 +4e 90 f1 da 9e 43 db a9 12 9f 14 ec 55 9a 4d 2d +6c 5a 19 cb f3 a6 8c 62 d0 98 34 52 a9 ee 0c + +# Encryption: +01 b0 8d 49 83 13 a7 d7 4a 05 53 14 eb 43 15 ba +02 87 60 da d4 11 14 d5 94 2d 63 bf 8d 27 be 3f +49 cc d9 4a cf 9d 3a a2 2d 09 b9 9b f9 74 09 bc +f3 32 13 c0 99 67 07 86 82 03 a9 ab 27 70 8d 3f +ff 69 b8 9d 02 e3 6e 01 21 a1 19 b8 d4 d9 bf d4 +fe 8b 16 8f d7 c1 2a 24 3f 7a 00 0b 39 bf 8d 56 +48 17 24 20 80 23 bb 60 7b 30 50 5d d1 74 2f 87 +9f 16 c1 0c e4 90 d3 4a 68 0d 27 ac 39 60 7d a2 +4e + +# PKCS#1 v1.5 Encryption Example 8.12 +# ---------------------------------- + +# Message: +09 5b 77 c9 4d c1 b1 87 88 e4 00 e6 91 6a 4b 4c +fd 73 ac e0 df 9a 3a c1 31 bd f9 ad 0a 12 db 76 +6d eb 22 53 59 d9 01 cd 56 ed 88 cd a3 d3 28 56 +54 02 + +# Seed: +a3 4a 68 05 55 71 09 c2 61 dd df 5f 85 d3 71 ae +65 20 f4 5a df 46 96 01 b5 c3 59 fe c7 44 cb 2a +ae 80 98 3c 73 2d b6 c5 45 df 55 e0 20 8a cf bb +f1 c2 c5 e7 99 88 f3 4e cd 6e 5b b4 b5 25 c1 b8 +bc b0 70 d0 d8 42 48 b1 f8 e7 48 0e + +# Encryption: +00 39 56 36 a8 26 67 dc f0 0d 5d bd d8 54 12 06 +94 8d 49 36 89 17 ec 0e 00 fd 7a c5 ca 8b f4 4e +c5 83 78 38 6e 59 4b c0 65 a9 a6 3c f2 a3 55 a6 +08 b6 f0 ba cb a5 60 08 bb a4 72 2a 7c 47 05 45 +a2 0f 38 78 53 d4 60 31 3b 2e 86 4e 17 b2 33 e5 +96 35 41 32 af 17 3b 4d 04 49 26 47 79 02 62 d3 +a4 3f 84 27 37 88 37 46 6b 06 73 a8 15 27 e6 be +10 45 80 32 6f ec 84 ba 37 1e a6 10 91 fa 40 33 +a4 + +# PKCS#1 v1.5 Encryption Example 8.13 +# ---------------------------------- + +# Message: +38 + +# Seed: +54 7c 91 75 19 05 d5 a2 84 ac 3f e4 32 cb e0 30 +55 b2 85 06 58 96 11 0e a3 6d 05 a1 40 08 3c e3 +95 5f a8 28 41 ea f6 db 4a 50 d1 2c 07 4f 45 a6 +88 b5 57 6d 6e 61 68 07 54 0a c1 17 58 5c 5b c3 +be 52 60 72 7c df 12 3c 77 4d b4 0c ff 29 70 88 +62 48 53 e4 69 51 36 b9 31 16 15 17 a7 b9 b5 dd +cd 9d 32 de 3d fe 3e e2 ea 68 8c f7 bf 88 2c cf +7b 9c 48 d5 e1 9e ff a6 50 4a 42 62 0b + +# Encryption: +00 89 e3 9d cf df 91 69 3d ef e3 9d 12 bb 25 f8 +0a 76 8d 44 1b 48 1d 6a 75 48 69 50 42 48 0c d4 +a0 ba 97 83 d5 c5 bd 38 89 6d ce 06 ac b1 77 a4 +ac 59 68 e6 55 a7 aa f5 0d 69 4a 64 97 13 b7 a4 +bd d1 4c 81 9f 83 b2 04 7d e2 19 5f 73 03 66 54 +53 a8 a1 11 5e 5b 48 ac 0e 9a 65 ed db 31 89 51 +7b 04 6f cb c2 d1 43 81 77 6a 77 fb 46 8e 11 29 +3c 78 c8 37 4c 8f 46 60 35 1a c2 b2 c7 84 5a 25 +fe + +# PKCS#1 v1.5 Encryption Example 8.14 +# ---------------------------------- + +# Message: +80 64 6b 3c 4d f0 eb 79 1b da 0c cc 4d 97 d8 1e +a8 f6 f7 4e b2 45 e2 c7 c3 48 fd 7f b9 90 16 a9 +d4 0a 60 5a c7 42 b2 7a d2 48 + +# Seed: +11 b8 e7 98 d7 a1 42 d0 82 e0 59 8a 8c b4 f8 c2 +aa 87 5d 5b 65 17 8c 4e e6 7a 5c b8 41 d1 cd a3 +04 31 d0 20 df 28 80 d7 93 58 15 d5 9d 91 b9 99 +3e 53 ac 34 1c 97 28 61 ea a2 66 97 cf 10 ca 8b +27 94 b4 53 03 be 03 48 9e be 07 4d 8f 23 98 54 +c3 a6 06 fb + +# Encryption: +01 f1 e5 a3 db d8 24 75 2d 2f ba 3c 32 42 e9 d9 +96 e6 27 43 0d 49 3e 1b 44 6a 2d bc d8 6a 48 09 +3e 37 a2 e1 28 b2 8c 49 d2 d1 72 bf 5a 97 7c 36 +9b aa 9f fb 83 9b d2 fd f0 0b d3 0f f5 22 8b 57 +6b 94 e6 d8 ec f9 44 24 7a da d0 19 f2 1d 06 fb +e4 18 d3 a6 d5 4c df 11 3e 8d 14 f6 ea 06 d8 db +79 64 93 bc b1 89 6f c4 f3 f3 03 86 c5 c8 ba b7 +03 7c 87 9a fe a4 7c 8f b7 a3 c5 b5 0b 29 18 66 +b9 + +# PKCS#1 v1.5 Encryption Example 8.15 +# ---------------------------------- + +# Message: +6b 63 1c 7c 35 ea 75 a1 b0 + +# Seed: +3e 42 40 c3 e0 9e a7 83 55 35 8c da 61 29 53 47 +30 f4 8a 9c 9a 1a 52 13 28 4b fd 07 71 21 6a d4 +ca 23 3d 99 3e e6 35 7f 4b 1b 12 a6 ba a1 77 43 +13 4a 85 7f d7 69 a8 bc 78 d6 1f b1 4f ea 05 22 +1d cf 5a eb 1a ff d4 0d 8b c6 94 5c 30 10 45 b6 +86 c6 11 fa 43 7e 30 ca 0f ab 5a 4c de f5 20 5b +af 99 26 c6 07 be 96 37 b1 50 7f 50 83 e9 40 cc +fa 2f b3 86 19 + +# Encryption: +00 47 cb 9a 91 98 d9 83 b3 22 24 cf 27 fc 72 99 +bb d4 ae 07 78 a8 3f c5 9c 47 45 fa 99 e9 17 bb +74 f8 bd 4e f1 3f 14 0c a9 b7 2e 2a a1 74 ce ea +26 48 94 e2 15 f4 1c 36 d4 e6 f3 46 f6 9b 4f 85 +50 5c 54 cd 46 25 9c 71 2e 30 c4 92 94 ba db 1c +47 16 85 1f 2b 75 e3 96 12 cd 54 66 ba 56 e3 f3 +15 99 c2 dc e2 3d 04 c9 3a 64 40 22 27 df 40 b5 +14 c7 4d 0a a3 6e 1e 86 58 e2 92 77 b3 05 af 35 +15 + +# PKCS#1 v1.5 Encryption Example 8.16 +# ---------------------------------- + +# Message: +40 08 55 da 54 a6 d1 fe 5f b5 8a 73 d2 a5 e5 58 +38 70 fb d5 25 d2 f5 72 ad b5 96 30 06 d0 a1 33 +9b ea 88 9d 6d 46 a4 37 62 f5 13 bb 7c c0 36 22 +bf 85 92 44 d6 + +# Seed: +49 6e 50 ba b5 ef 18 f2 2c 3f 62 b9 21 14 8d 36 +c1 01 ad 0a 9a 20 38 67 58 08 ce 8b 62 f8 a6 a0 +ba 8d 91 05 f9 2e d8 a0 2b 31 2f 32 4f 3f d3 91 +92 bd 41 53 78 4f b5 59 05 c3 b6 69 30 7b ad a8 +27 af a1 b5 cb 3d c1 1d c4 + +# Encryption: +00 d3 a8 5d ec 97 d3 44 88 ee 33 c6 58 ba 18 8e +64 cb 57 83 7d 2e dd bc ba 8e e5 2f 13 f1 e4 fe +9b ec 2f 92 e7 21 09 87 e1 c3 fe 34 5d 40 19 77 +0b 07 74 94 51 b0 4d 67 30 d5 3a 91 01 5b 25 7e +81 0d ae 0a 0c 11 6a 4f 22 45 14 ed bd 39 b2 c6 +5e 15 2d 3b 97 89 dd a4 f0 d4 5b f9 83 2d 27 9d +34 31 06 2b 4d e1 b0 67 7e f5 9c 6c 33 27 68 ec +da 3a a6 bc d1 0f 70 bd 06 03 0a 76 65 ed 3f 20 +79 + +# PKCS#1 v1.5 Encryption Example 8.17 +# ---------------------------------- + +# Message: +b8 7e db 45 5a 7e 85 53 9f 92 8e da e9 09 fb f8 +f7 a1 99 c0 3a 94 a9 a4 5a ca b2 5e fa ee cc 26 +29 74 ca e0 bb 72 24 3a 99 c6 47 20 79 f1 97 38 + +# Seed: +03 5e 31 59 4a 56 65 60 5b 84 fe c9 3a df 92 58 +50 85 1d f7 b3 94 e9 bb ec be 4d 72 c9 2f 27 03 +b6 d6 08 96 e0 05 4c 59 ca fa 5e 0d 28 6c 81 2b +23 e5 37 88 5e 4c 34 38 a7 72 a1 61 0a e9 fa e9 +18 e3 4d 49 92 c7 f2 63 f3 e8 e2 f9 80 b8 + +# Encryption: +02 1c 8c 95 9a ec 47 29 68 87 68 93 0d 67 e2 02 +99 dd 47 90 2d b0 79 f2 39 b8 c2 88 b0 a7 04 47 +c7 19 6b 84 91 2e aa 5b c3 af f6 ba 63 0c 2e aa +3f cb b2 4b e4 63 83 65 31 25 0b d4 c4 f2 a1 da +68 c8 bf 4f 40 cf 5c 98 b6 85 eb ec a4 d0 3e 76 +b3 34 af 0b 1b 34 48 8b 58 2e 29 35 25 35 72 f7 +fc fa a8 35 44 e7 fd 52 ef 45 8a cc cb 19 30 1a +4d dd 50 51 6f 16 a5 fb 78 f3 95 99 00 db cc a1 +f2 + +# PKCS#1 v1.5 Encryption Example 8.18 +# ---------------------------------- + +# Message: +30 2a c8 0e 30 c6 55 3e 93 59 df 85 b1 e2 4a 16 +c8 62 a2 0f f4 fd 9d 5f 14 6b e2 81 dc 30 66 ae +b8 fa 00 b5 2a 99 + +# Seed: +32 6c 99 35 8c 4e 5f a4 d2 c0 43 f0 2f 92 70 5f +79 1c f7 12 bc 01 04 5b 4c f3 49 b4 2a e5 ac fa +c3 78 38 11 bb f0 7f 34 bd 6c 85 19 55 cb a4 a8 +b2 a7 d1 39 a7 8b c4 d8 8e 3a 88 e6 c4 cf 49 4e +6a 4a 52 35 41 45 e1 18 83 cb 5c 78 b5 72 f3 0a +51 ed 23 f2 56 4b 69 60 + +# Encryption: +02 03 29 87 cc f7 5a 63 86 24 17 80 64 db a4 b7 +2b e5 39 e0 7e cd f5 30 03 56 cc 43 d7 29 fe 34 +fb 35 bb bf 5a 32 17 2c e3 9e a1 fb 47 d3 8e 49 +7a 03 b6 01 ee af da af 99 a3 4f d7 21 18 4a f2 +e1 8e 83 d0 50 a4 10 8b 15 e5 e3 a2 7e 0e 63 6d +f8 d9 4f 98 16 58 eb de cd ab 0d ef cc 0d af 3a +c9 a2 7b 3f 22 a0 54 1d 35 00 27 52 e9 cc 4f b2 +58 2f ae 25 11 a1 32 ec 5c 22 8a 88 72 bd ba d6 +87 + +# PKCS#1 v1.5 Encryption Example 8.19 +# ---------------------------------- + +# Message: +00 b3 82 01 74 6d ca f4 03 48 af 57 ba d7 25 70 +ca f5 a2 85 5f ec 6c 42 ee 22 dc fe 64 c9 97 ec +62 a5 c9 75 62 4b bd 1f 8e c9 16 + +# Seed: +93 91 05 c0 04 c0 1a a9 f4 74 46 d3 cc f5 30 e9 +b2 17 4c 50 ae bc a0 a9 5c b7 a4 d8 39 54 ef b8 +03 9e 59 1c 19 71 d7 76 ce c7 61 12 92 06 db 7a +d3 dd 87 16 68 25 5a 55 50 ac 4e 94 8b e0 5c 16 +22 20 dc ef ec 13 ff 1f d8 a5 a7 f7 8b f7 15 b4 +9d 03 ba + +# Encryption: +01 2b a8 7d c0 3a 1a 38 bf ed f1 21 ed 87 22 82 +7b d9 7d d6 3f dd fd d5 90 50 c5 3c 5e 7b 49 fb +7a e6 03 84 87 82 0e fd 5f b9 71 43 81 ce 8d ae +b5 6d 13 50 bf c6 7d f0 91 be a2 ac df fd e9 29 +2a b1 29 1c c9 75 1d 9e 39 a8 26 f0 54 ad 1f 33 +a2 b7 94 da 50 ef 80 67 29 17 e0 b3 81 40 45 d2 +3d f4 5d ba 3f dc 6f 09 ab 0a 01 8b 06 0a a9 fa +fc 3a 5d 19 d5 eb 64 31 0b d6 02 a9 91 1d cb 7f +24 + +# PKCS#1 v1.5 Encryption Example 8.20 +# ---------------------------------- + +# Message: +ba 28 33 66 04 76 d8 73 15 07 66 9f 50 29 8c 2c +68 d4 4c 53 e3 d0 a8 03 78 6e + +# Seed: +86 ce 8e 92 ad 88 b1 46 2a 17 1a f2 8b 4e 99 08 +8c 04 98 a2 9b 4c a5 e6 6f 64 f8 6a de c7 f9 64 +e8 eb 82 57 c5 c0 1c da 16 5e 0f 75 11 db 14 7c +10 bc 07 51 5f 04 f0 5f 52 d2 bc 89 22 83 57 c6 +61 b4 3f 43 d5 42 db e7 78 34 09 1c 7c e7 0b 18 +2e 19 bc 93 6c 30 68 4a 83 1e 2c 3b 8a 4a 74 46 +3f 0c 9f 1b + +# Encryption: +01 12 ac 28 98 a2 5c 13 28 79 1f c9 6a 82 b7 29 +18 b5 1a 66 8c 54 0b cf fc 8e 0b 3a af e2 05 ee +87 1f 5e b7 6a d1 16 d3 04 cc 04 42 bd b1 af 5b +9a 63 45 82 7e 67 8e 40 e3 3f c8 58 ef 6c 45 6b +e4 36 52 bb 2e bc 39 64 b4 bf 4a 93 a8 ee ef 84 +04 ae f1 a0 44 41 5a 15 6f 7c fd 79 95 ac 25 e7 +b0 30 26 69 8e 14 48 9e fc c1 ae 92 96 58 bb 66 +3d e0 ac 44 a7 a5 5c aa 0b 0b 20 34 c2 aa ec 13 +4e + +# ============================================= + +# Example 9: A 1027-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +06 8e f0 b2 74 15 7d 7b 5e c7 29 03 86 59 56 18 +3e 0e 34 62 ec d2 21 14 ca d4 c7 ba ac 94 c7 c2 +c5 e6 cb df a2 ab fe af 8d 23 18 2e 9c 08 81 5d +10 0d 8e 8f 62 1d 3c d4 af bb 99 85 96 6f d6 a4 +18 2b 59 90 88 a3 5d 77 fe 01 78 ac f7 53 1c 70 +d8 96 ff 78 8e dc 82 06 05 40 ef ef d9 f3 c2 4d +5b e6 9a f7 f2 f4 44 85 b1 91 18 a4 68 81 4f c5 +13 e3 a1 ce d6 77 91 f9 03 6e ee 56 fa 9e 20 60 +2b + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +06 8e f0 b2 74 15 7d 7b 5e c7 29 03 86 59 56 18 +3e 0e 34 62 ec d2 21 14 ca d4 c7 ba ac 94 c7 c2 +c5 e6 cb df a2 ab fe af 8d 23 18 2e 9c 08 81 5d +10 0d 8e 8f 62 1d 3c d4 af bb 99 85 96 6f d6 a4 +18 2b 59 90 88 a3 5d 77 fe 01 78 ac f7 53 1c 70 +d8 96 ff 78 8e dc 82 06 05 40 ef ef d9 f3 c2 4d +5b e6 9a f7 f2 f4 44 85 b1 91 18 a4 68 81 4f c5 +13 e3 a1 ce d6 77 91 f9 03 6e ee 56 fa 9e 20 60 +2b + +# Public exponent: +01 00 01 + +# Exponent: +71 94 0b e6 79 7b b3 28 5e bd c2 0c c9 27 5f 5d +77 55 88 e9 af 6f 68 7a 2e 39 d2 c1 91 11 10 76 +95 dd ed e3 91 d2 19 6b 29 58 1d f3 15 4a 37 12 +fa 6f cd f8 5b b4 fd 48 64 1f 07 1f fd b1 de 08 +a1 d5 92 1c a1 0e 68 dc 04 13 13 c9 bb cb 80 81 +bd b5 d4 60 42 27 cb e5 78 07 41 65 74 d1 a3 8d +a0 b2 34 4b b2 15 b4 18 2b 10 6b 2b 53 4a 8d 32 +06 f2 d7 d3 03 b8 dd 5b ce 29 2a bf 75 cd 76 49 + +# Prime 1: +02 95 10 b9 33 b7 c8 4e 41 ff cc 72 2e 32 38 60 +c9 b2 d0 88 3c 68 33 62 4b a5 bb b8 97 53 d7 60 +3a 7d cf 26 6c c8 f4 bb 07 48 48 26 0f 68 dd 82 +6b 63 8a 8d d2 ef af 68 aa ee 26 5a e8 98 39 b1 +63 + +# Prime 2: +02 8a 2d 03 34 49 44 62 f6 11 f3 60 3e 0d 37 4f +3e 32 d2 fa b5 e9 d6 97 2d fd 70 79 64 46 a4 8b +c3 03 ee 25 8b 75 a1 b7 ac e7 0d 48 58 51 79 4e +42 84 f2 dc 51 d3 97 8d 55 53 7b ea 22 55 11 f4 +99 + +# Prime exponent 1: +01 b9 55 0d df da 3d 6f 09 9e e5 f6 00 a3 64 82 +31 86 20 b4 23 68 09 8e 01 24 e7 5b 88 23 e0 31 +0d 3b ba d5 53 61 22 09 cf 05 d1 ad 1f 32 8a 57 +ac ac 2a ef 1e 39 08 69 1f 5c 98 dc ae 56 1a 86 +33 + +# Prime exponent 2: +e8 ff a4 8c 52 4d 5d a1 8d 61 48 76 34 4a 43 ed +a8 4d 0f 67 ad bb 27 46 65 f2 ae ae 0e da dc f3 +30 2f 61 e9 0e 68 bb e8 0c 8d 28 05 ee 7c a8 5d +12 43 ee 4c ac a5 3d 12 fc ee 05 43 f4 74 90 d1 + +# Coefficient: +01 98 4a 81 5c db 46 ad 81 cd 82 10 aa 07 22 70 +0c 59 90 9d dc 9c 4a 49 f1 9b e1 5d a6 04 47 8c +21 88 81 d5 43 a7 54 6b f7 75 69 4c 2b d1 3d da +69 2c d0 bc 24 39 ef 22 ef b6 7f fc 5d 46 95 21 +b2 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 9.1 +# ---------------------------------- + +# Message: +96 ad 3b a4 d2 9b dd 35 25 bb c5 d0 2e 88 c0 13 +3f fd ea 40 94 74 db 34 df 73 3c a5 9c 3a 23 2f +6a 64 c2 14 3c a1 31 a7 f1 8d 00 5b b3 aa 6c a1 +ea be aa 13 6b ec 37 db 11 1d 4d 8f 61 + +# Seed: +10 e9 f5 09 3c ec 87 2e db 16 16 2b 6b bd 52 12 +f6 10 1a 71 d5 1d c1 42 0c ad d1 d5 50 fa f9 af +40 f5 73 d3 e3 ab 68 91 d8 a8 82 ef 06 56 bc 30 +06 2a 05 b1 cc 27 7a 11 c9 ba 2e fd 51 03 c5 6e +23 + +# Encryption: +04 de c0 1b bf 8e 0c 22 96 d9 f5 bc 2d 2b a8 95 +34 3e c3 0e c5 44 13 57 6d 80 84 b9 31 43 cf a2 +d2 03 3b f4 c2 c2 e0 3f 5b 02 59 ed f1 4a 8f 3e +11 69 85 77 65 2a 2a b9 f5 1a b0 18 7c c7 51 75 +c8 6d fc 9a 45 b1 e4 eb 8b 54 47 a9 4a b9 b5 17 +7a 04 04 ba 49 e5 7f 83 c9 3f 7f e2 de 24 18 45 +f5 81 f6 42 12 43 7e 0c 04 ff 34 ea 1d ee 6d d2 +8f 6f f3 36 72 35 44 13 74 f0 f2 ef 71 a9 cd ae +9e + +# PKCS#1 v1.5 Encryption Example 9.2 +# ---------------------------------- + +# Message: +7f 92 ab b6 e5 2e d5 d4 20 84 9e d6 cc ab 36 c3 +d0 84 92 55 43 1e 19 3d 67 bd 94 4b 6c 0f ce fb +77 29 cf 5a 31 + +# Seed: +ce a9 68 be 78 ab 5f aa c2 27 dc 3c 6f c9 ce d4 +9f 85 1e d5 8b 08 d5 ca 37 54 28 48 9a fb ef 3b +f5 ed 83 74 6d 95 9a 0a 56 e9 ac 66 ff 2e 7c 8b +8c 3a da 97 fa 15 dd 7f 99 13 41 74 70 70 cc ad +65 42 bd 7f 4b 33 f5 56 04 45 8b 91 03 ae 13 dc +89 b4 e6 2c cb f8 4f f7 3b + +# Encryption: +02 5a 1e 65 eb 37 f4 b3 28 cc 31 b0 17 24 f8 3c +26 ed 8d 18 a6 51 65 21 3b a0 ef f7 ae 76 7e e6 +0b 99 27 76 1a 06 94 b5 c3 bb 64 b7 e0 39 96 a3 +56 8d 6f d1 ac 6b 7a 8b 71 97 5b b0 71 6d 94 5c +02 d4 73 68 96 6f ff b1 d4 49 fc 6e d7 3e 2d 19 +83 1b 86 d1 87 67 51 29 36 69 e7 7d 6e 12 a0 f0 +c9 62 df cd 40 0f b8 3c e8 26 07 16 31 7a d5 fd +e2 18 49 aa 6f 68 e7 0c e0 b5 b3 11 42 89 8a d1 +a2 + +# PKCS#1 v1.5 Encryption Example 9.3 +# ---------------------------------- + +# Message: +f5 b5 35 b6 3d 53 5e 21 37 73 2c 30 13 37 c9 53 +ea 2e dd 58 a7 8c 20 25 83 2d ca 9d 6b cd ad 87 +c9 97 c9 06 83 6b 2b f9 5c 83 f0 3f 7a fa 29 01 +34 6d 67 4a a6 9a 1b 47 f6 b9 16 fd 4b + +# Seed: +c8 9e fd b2 34 e0 1a 2f 07 76 29 57 e8 c0 a4 f9 +1a ba e6 d4 f3 60 e8 9a 7c 48 6c 55 49 f3 d0 ad +75 77 7f 0c cd 97 a0 97 5e 98 44 d9 86 87 02 76 +c9 82 5f 5d 1e ef 3d 1b 48 7a bc d1 9b 51 2d 08 +be + +# Encryption: +03 9a 1c e8 c0 91 62 51 a0 1e 5f b6 61 5d 2e 11 +98 2f 4f ae 7d 46 df 21 da a2 98 f2 c7 46 11 b5 +58 16 cc 27 fa 37 27 9a af 59 02 ec b6 c8 39 fa +90 0c f3 af 86 ff 40 a4 47 dc 40 22 35 f9 06 67 +91 23 f3 cd 38 19 04 f3 3e ee 35 3a c9 0d 5f 7f +20 3a 6e a8 91 35 1a db 11 60 1b d9 d6 b0 a0 24 +33 3a 24 55 be 1c a6 2e d8 2c f3 7c f8 de 4e 23 +92 dd 54 e7 75 03 3c 56 99 0b ae 5c 43 91 b6 65 +3a + +# PKCS#1 v1.5 Encryption Example 9.4 +# ---------------------------------- + +# Message: +a7 cf 29 82 03 47 a5 2a b9 cc 42 04 bb 6a c1 bd +7f d9 0a 75 8a 15 6d fa 9c e7 19 27 e7 4e e2 15 +98 70 8c f6 9c fd 79 85 74 2f 50 27 ff a7 10 + +# Seed: +10 9f 0d 6c a0 e1 3f 50 4c 07 d8 4a 5b be 43 ed +6a 94 ac ba fa b0 48 89 36 05 d3 41 c5 d2 8d 85 +44 c3 fd 28 43 50 f2 c2 2d 1f 36 7d fb 9b 6a 67 +51 d0 6a ae b1 7c 3c 0a 10 11 ae 38 fb a4 e4 6d +4e 44 c4 82 87 9e ba 06 44 37 48 71 b5 c5 3b + +# Encryption: +04 48 c3 9c c4 57 d6 cc c3 0b 0d 76 ff 5a 13 2e +00 c7 5d 53 36 46 b8 44 0b 13 ce 73 0e 1b 7a d8 +3b b2 ba 4a 08 2b b5 a3 3c f4 14 66 e0 67 fc f1 +6c 6a 29 f1 87 9f 77 e9 b0 db f3 ec 08 05 75 be +ba c0 c5 67 6b ae e0 02 d5 73 d1 bc c8 a7 0f ed +2a b6 79 43 ef c9 bc 13 13 9e 5d 8d de 2c b3 0e +1b 93 4f 50 cf 6c 45 73 92 3f 73 98 de 66 70 cc +26 34 1f 3e 35 a4 19 36 1e 59 f6 08 98 f2 69 2b +94 + +# PKCS#1 v1.5 Encryption Example 9.5 +# ---------------------------------- + +# Message: +b8 03 c7 ef 5f 9a 9b d5 84 01 + +# Seed: +8e 77 58 ed 4d 1b a4 dc e0 88 92 6c 10 b2 f3 d4 +c1 e2 67 1a e7 2e 65 9f 72 1f f7 be 6f c0 35 e3 +85 d5 12 d0 7a 38 dc ca 1e b8 31 fe f9 06 10 04 +44 ee 99 5c b0 7b c2 6a 5d c9 2b 27 2a 74 a9 2d +21 49 73 25 22 d5 39 43 4f a4 d0 3b 07 cf 96 99 +95 8c 19 89 1d 1d 59 06 aa 36 d0 a8 d0 6c 6f c8 +7a 45 51 bf 18 58 bd fe d5 f8 86 cc 8d 31 ee 4c +16 4e 98 1d + +# Encryption: +04 b6 2d 4d 4b 9c 1c 3e 05 13 09 79 5c 69 24 8a +ed 38 9d e2 4a 6c 79 53 8a 2d 51 d5 d0 37 19 a8 +a5 28 75 0d 5d 25 4a 1b 91 40 96 db 96 d8 3d 2d +9a aa 2a 16 5b b1 34 6e 44 c3 57 27 56 c3 8d 52 +f8 d3 07 c0 4e 1e fe e5 84 78 22 31 7a b4 69 34 +5b 86 c7 b8 5b 54 15 41 c9 92 ab ea 98 d1 08 a7 +df c7 09 1c 30 c6 68 5a f0 e3 3d 04 66 ac e4 cc +cc b3 4e 5b 26 6d 3d 6b 94 7b c7 c0 ae 34 d5 e2 +64 + +# PKCS#1 v1.5 Encryption Example 9.6 +# ---------------------------------- + +# Message: +61 7e a9 e4 a5 6c 4e c1 d3 d7 fd 7f 32 81 ae 7f +a9 32 b2 a0 a6 cf 55 eb 60 48 14 56 81 b3 58 8e +df 70 12 69 f8 9f e6 4a a1 4a d8 df 0d 46 79 61 +31 + +# Seed: +64 d7 eb d0 48 50 eb 6f 7a e1 af 48 12 0a 80 13 +0f 32 ed b5 03 69 64 0b 22 2b 8d 63 ef f6 57 12 +70 dc ab 31 76 d0 24 72 28 dc d1 c3 f3 cf d5 13 +31 b7 56 a8 65 2a 14 dd aa b9 93 96 b9 19 9a 73 +87 50 d6 9e fc d3 77 f1 84 ae 19 b5 a9 + +# Encryption: +02 df e7 29 58 59 58 81 d8 07 56 6d 3e 36 07 c0 +22 e4 61 fe 1d be d3 cc 6d 63 de dc b7 19 0f 06 +c7 d2 4b 4f 03 26 4c af bb 74 82 ec 28 b9 ba 48 +9d 03 11 5a f5 8f de 47 5e da 58 bf 01 55 cd f1 +af 16 df 20 6b cd 12 57 04 c3 e3 15 ad 3d 95 44 +b9 e2 c2 fe a8 10 ce 48 45 56 d2 9e 07 ad bf 0f +f4 61 cc bc f6 62 bd 74 95 9a 43 7d 4c 80 11 ce +ad a5 50 2a f7 67 6d 9a 15 21 e3 18 9d af de 00 +dd + +# PKCS#1 v1.5 Encryption Example 9.7 +# ---------------------------------- + +# Message: +c9 1f 2c 98 c7 5b 2f d4 cd 8d 5c 7f f2 e7 69 b1 +2f 28 f3 13 fb ac b5 1b 5e 50 14 df ce 9d 63 5e +7c 6b 2d 88 af 5e ac 30 d1 62 b8 dd c2 2e d8 bc +7b ee 50 6b fb f3 1e 51 ba 48 f4 26 + +# Seed: +6c 44 59 61 f8 6f a2 98 d7 64 7c 22 24 d9 5b c1 +27 da fc bd 5b 90 21 ec 7e 9e bd e9 6f 5d 7a 76 +f4 ee d0 ac 92 2a 6e 93 eb 3b 4c 3c 43 f8 a5 7e +18 29 4e 1a 51 73 b0 f7 e2 dd 2c 4e 57 7a 4b ec +e7 14 + +# Encryption: +03 a8 85 aa f7 b7 d9 4f da e3 4b 41 c3 74 17 66 +a4 09 c1 ee 02 32 b1 c5 3e 5f 6c 5a a5 4a c1 ef +0e 5b f9 9b 9f 7d f3 e9 b0 0c ed 94 76 ee 1a db +8f c5 71 68 91 f5 4d 45 ce da 70 b9 db 3b 8f ad +25 e7 77 95 af 14 81 ec 49 21 84 c4 9e 9d f8 23 +ee 64 66 41 0f 65 01 3c e3 c5 79 16 63 5d a8 30 +67 7f 93 2b da ba b5 c0 a2 08 d7 f4 36 7a 7e ab +a7 5b 04 5d 25 ac fd b4 15 fe e0 52 19 a5 84 23 +7a + +# PKCS#1 v1.5 Encryption Example 9.8 +# ---------------------------------- + +# Message: +7b 1c 31 51 a3 8d 32 ec 7b 82 c4 8c 00 0a a4 81 +de 41 8e 80 3b 67 3d 2e 9a 0f c3 d5 e9 74 ad cd +ce bd 3c 2a 8f 41 14 21 18 a5 5e 87 d0 4b ba d5 +b3 64 25 + +# Seed: +b0 f5 be 9b 3f 23 7c c5 af ca 5a 99 fc cb 77 b6 +ef d8 68 94 7f 98 55 4f be ce ac fa 88 4c 15 15 +39 d7 cf 42 3e 72 60 31 bf eb 8d d2 d4 f3 01 da +6b df ca d6 e5 81 65 82 ad dc e1 0d 85 d5 ee 1d +04 46 f3 73 b9 5e e1 60 bc f0 35 + +# Encryption: +06 6c 30 09 dc 6c ba c7 b8 bd 51 41 c5 5c f8 6a +3d 79 69 d5 85 45 2e 3a 66 54 0f 94 02 db a2 15 +e3 fb 3a 27 7f 0d 33 96 c8 c0 08 af 19 91 3e 3d +91 e4 0f 86 76 06 b5 bf 54 30 4c 04 71 da dd 64 +04 b6 7a 48 57 bf 52 24 6c 0d 60 18 23 dd 03 80 +c6 60 9d ac b9 2d b6 02 e5 57 64 ae 46 50 df 1a +db b4 b9 5f a5 af 4b cd 11 21 f1 3c 0a 73 23 ad +a8 c6 0d e3 d0 81 72 9d 19 7f 9c f8 e2 7c de 80 +b1 + +# PKCS#1 v1.5 Encryption Example 9.9 +# ---------------------------------- + +# Message: +b2 93 c6 f6 d0 5d 1f 38 b5 61 ea 3d 0d 0a d6 a2 +af 83 09 bb 9a de fa 77 8f d6 bb 9f ff 3e 01 0c +40 4c 53 39 97 cc fe d7 e1 91 7a 66 92 61 cf cc +a4 e3 70 29 99 1d 2d e9 b2 99 + +# Seed: +87 bd 2f 6b b4 82 45 59 1d 65 f0 23 a6 5b 63 bb +ba 84 19 79 2c 01 41 09 2b 1d b1 be 53 e8 c9 b4 +df 95 f0 ad 55 b9 6e 5e 57 61 5d 21 4b 49 77 87 +0a 27 2f 72 31 66 c6 20 45 76 5e 6b 4a 73 a7 c9 +eb e1 1d 24 + +# Encryption: +03 10 4e c6 c4 ab 9d ac ae 42 7f b1 06 99 bc ae +00 3d a5 6f 6d 07 50 95 87 14 5b 73 3e db 53 23 +9a 6f 42 22 86 83 9c ac 06 4a df ee e5 dc 89 78 +0c dd ad cc 80 72 19 d6 a9 7b 85 c1 3f 27 93 7d +70 32 7f 82 cc 36 a5 da 8e 45 63 77 fc a2 3a ee +51 4e 04 4a bf 1f 66 c3 e7 bd eb c2 cf f6 28 bd +52 4a 09 66 e2 63 8d 28 33 bf a3 43 eb c7 41 f7 +6b 5b 70 a1 13 6f 4a bc 60 28 64 a2 ad 43 a7 91 +bd + +# PKCS#1 v1.5 Encryption Example 9.10 +# ---------------------------------- + +# Message: +08 38 f4 a5 92 + +# Seed: +89 c5 89 8c 6c 3d c6 cb db 1a cb 28 05 df 53 98 +f0 b3 35 8a 18 e5 e6 3c 14 d2 0c 98 d2 1d 9f d8 +b2 ec c9 a0 e8 3d af 0c 06 92 68 bb e8 6f ee a5 +1c 93 79 1b 68 e5 d9 3b 74 5f ea f6 ad c4 2b 83 +c3 09 c9 cd 3d fe 1c 06 15 3a b8 80 85 56 18 98 +90 be 05 3a 92 54 88 d0 29 fe 50 40 e3 e7 d5 d5 +31 b3 2e b9 d2 f4 ee a2 21 11 b3 8a 65 53 f0 0e +dd 23 65 57 5b b9 49 f3 63 + +# Encryption: +01 4f 27 97 dd e8 d4 60 18 ff 23 d8 9b e2 e3 ae +04 6e ed 31 97 c8 79 c6 0e 26 f3 d2 40 08 66 eb +50 d7 b4 5f 6b 01 ae 9c a0 06 84 7e fb e9 ab cc +9b c3 e3 56 90 07 2b 68 db 9e cd 92 6d 94 5f 78 +7b 27 c3 75 3b f9 6b 2d 49 98 30 84 14 2c 42 a1 +26 1a ff 7b 17 ff 4b 20 de 9b ff a5 86 24 ab 37 +1d 4c e2 f9 64 69 a8 e1 03 8d 57 20 b8 1c f0 42 +dc 78 bf da 9a 3c cb 61 60 81 2d de a1 58 bd 2f +5c + +# PKCS#1 v1.5 Encryption Example 9.11 +# ---------------------------------- + +# Message: +12 38 0c 5e 80 bb 95 bb c8 85 73 57 fe fd 17 bf +9e 50 96 27 d2 8c df cd 12 bb 13 16 61 b3 42 df +a6 ca 67 2e 13 a8 85 1f ce 19 b1 a8 ca f0 e3 3c +d6 ef 53 8a 05 fa 54 26 9a 13 78 e7 + +# Seed: +88 03 31 eb e9 1a b6 ce 16 84 d9 af 5d 97 7e b4 +26 ca 71 56 e0 b6 f4 33 6c 6e 09 33 d6 fa 48 78 +2c 0a c9 69 f3 dd e6 1d 8f d7 4c 47 fe 9e 30 61 +71 0d 24 5b 1d 38 11 04 28 60 c1 f4 8d 2b 8f fd +80 9e + +# Encryption: +04 6c 54 5f f4 96 c2 1f 69 01 27 24 54 18 cc 5f +b1 8f 09 10 2e 7a ca 87 e2 6e 20 82 fc 16 f6 2f +e9 f4 2a 72 22 71 a7 9e ae e9 62 5a 7e 63 2c 19 +36 40 4c ec 62 11 d8 23 86 3b a0 2c 6b 0a 83 19 +58 b4 ed 8f c6 25 a2 e5 2a 05 4f 8f 18 1f 13 0f +8b c4 b1 df bd 44 b7 0a 35 b3 5e 9c 7f 4a c5 5e +e5 e2 cb 06 8b 75 86 39 b2 cd 64 3d bf a8 2e 2d +97 20 e4 89 f5 c8 21 d8 eb dc 13 68 a9 d3 46 8a +37 + +# PKCS#1 v1.5 Encryption Example 9.12 +# ---------------------------------- + +# Message: +ee e1 e4 5d 18 b1 47 c2 69 a6 0a 9c 64 20 18 ed +6c d1 15 7c d0 ce 2b 29 68 df a4 b4 97 fc 40 b2 +24 bd 86 1e 25 35 12 2b + +# Seed: +5c 51 3e 51 44 52 b1 4a ee 33 b6 17 60 b8 58 c5 +35 7c 7d 7f 20 e4 a3 7c 7e ef e4 19 ca e3 fd 16 +f9 d8 3e 5e cd e1 9e e6 32 85 dd ce 66 80 ee 94 +64 fe 83 75 6e 90 31 d6 37 9e 6a 6b 38 4c e2 77 +bc 64 2c ed 83 b2 9c f7 4b 72 ce ff f5 30 71 04 +e1 83 de 2c e6 a1 + +# Encryption: +03 a8 64 83 cb b7 2c 15 f5 a6 93 2b 01 2f 40 c4 +b1 73 33 3b 26 86 f4 98 4b a6 6e 24 c7 cf 44 41 +23 ba 2e a6 66 a1 75 5d 09 35 7b ee a4 37 9c e3 +cd b0 a7 7a 6e e3 b7 ca 60 db 68 24 17 f7 16 3d +7d 3a c7 35 28 11 bb 94 c5 b7 71 f3 d3 fd a7 73 +e5 ce bc 8b c6 60 11 55 b3 f4 e4 b4 ca 85 d9 ba +b8 ec 25 8c ec ff 44 33 c9 2e 8f 86 3d 96 fc c7 +94 29 49 8a 9e 17 90 33 0b c4 87 c0 10 d7 99 24 +5d + +# PKCS#1 v1.5 Encryption Example 9.13 +# ---------------------------------- + +# Message: +55 09 a5 c1 ac 54 89 dc b7 65 f3 7c eb be 7d 81 +cf 02 76 b1 f2 cf f9 5d 27 4b bd 04 + +# Seed: +76 e8 1a 51 37 1f b5 07 41 14 1d cb 31 d5 1d 1c +46 1f cc 02 6a ea 85 20 15 d4 68 74 0b 45 23 40 +5f 95 ba 87 9b 08 69 bf 03 1a 60 65 4f c4 e5 68 +c1 95 7c e4 e4 2a 35 0a 95 bf 8c b2 a8 b5 fd e6 +dc fd 25 05 c0 37 a2 9e de 68 9c 53 d8 32 19 e7 +3e 64 08 17 bf 8a fc 9a b0 04 ec ae c8 43 e4 fe +4e 38 + +# Encryption: +02 55 de 28 0b 71 af ef af a2 0f 24 1e 08 1b 7e +c6 c1 62 dd da 18 84 fa 9f 82 5c 4c e7 63 6e fb +c1 1b 84 a6 eb ea 35 89 25 71 ac 9e 6b 1a d8 47 +3f a5 73 c8 83 c9 f2 15 a1 95 80 c3 ea 30 2f 88 +f4 4f 48 e4 d9 5c 34 40 d4 93 1f 17 66 a1 fe 7e +79 0e 5d 38 e8 5d 1f 63 85 0a 3c 70 7a d8 97 7b +88 c3 8c b9 ed 98 34 5c d3 50 c3 dd 45 30 9f c8 +1c b4 62 76 e4 ad 64 7f a8 4c 14 12 5e fd 67 d8 +ba + +# PKCS#1 v1.5 Encryption Example 9.14 +# ---------------------------------- + +# Message: +02 53 81 a5 5c 8e 48 7d 7f 4f f7 c3 6c fb 37 50 +07 d1 9f 93 71 13 6e 2b 3d f4 42 5e ee ee 5d 79 +c3 52 61 fb b4 ea 68 bd 91 e8 ed ab a2 32 9e 29 +31 53 06 c7 d7 18 33 15 5b 88 + +# Seed: +aa 31 0f 62 da 90 da 4a 20 28 b3 81 39 9c b7 e0 +ed 3b b5 10 57 5c 9b d0 f6 38 21 5b af 78 08 e3 +24 5e af 38 b7 6e 26 52 29 0b 7c c6 20 90 7c da +0c b7 af 07 3c 12 2f f8 3d aa e1 98 6b 43 ec 1a +14 82 db a6 + +# Encryption: +04 9b fa c6 41 0b 77 80 39 7a 49 fb 88 93 b2 4d +90 3b 36 00 f3 3c 78 2c 14 75 b5 d2 4b 4f 4e 88 +fd 11 24 ef 06 45 f3 d3 91 ed 31 00 6d d1 b7 c2 +64 12 8d 0d b9 aa 0d 65 a0 9f fb e2 9a 94 cc a3 +58 da 64 bd 1b 72 ff 55 88 88 08 10 5b e0 91 ae +23 ea 3f 34 75 05 17 9e cc b2 41 0d 89 de cb 62 +33 0f 36 c7 44 26 2e b2 b0 78 b4 25 4b cd ce ce +21 1c f0 57 4a 24 68 e2 a1 e0 18 bc 31 f5 02 22 +35 + +# PKCS#1 v1.5 Encryption Example 9.15 +# ---------------------------------- + +# Message: +07 3c 43 67 ba fd 48 10 d7 70 44 60 c7 83 d3 50 +f7 cc d0 99 47 2f 79 f7 fd f2 3e f0 cf aa cc ab +95 71 df 53 fd e4 + +# Seed: +f9 5a 39 96 de f1 ca fc 1a 4a 0b 34 14 6b 73 de +6b 5a 92 cb 81 2e 20 b2 0c 12 2a 25 1e 6b 22 e0 +46 9c 98 db 12 8d 43 ce fc dd 80 c7 ff 36 99 80 +16 a8 92 a8 b6 34 b3 6b 9b 0c e8 7e a8 0b 5d d9 +fd 7a 08 29 14 e7 3b 83 a3 84 1d e5 1b 71 b1 a6 +b7 ef 7d e4 e4 b8 8e dc + +# Encryption: +02 de e4 8b 0f 99 53 ee 12 c7 18 b3 03 b0 c8 9d +61 50 eb be 83 ad 62 4e 11 7e 3f 27 04 a0 b1 7a +2e be e8 38 52 56 f0 e6 42 80 fb 06 c3 b1 46 c0 +99 af 23 a9 f2 47 93 39 37 81 a5 55 ac 4e a2 d8 +8d 78 5d 8c db 6e 7a 2f 89 52 d2 50 3c cf 90 1f +12 39 f6 f7 b1 ac d4 41 21 c3 65 fd ae 37 07 46 +de 45 26 e7 c6 56 0f 87 54 6e d5 77 cf 97 98 be +f4 7e 49 20 65 50 9c 49 21 2d 37 0d ea 05 22 d7 +94 + +# PKCS#1 v1.5 Encryption Example 9.16 +# ---------------------------------- + +# Message: +ba b2 0b 9a 6a 53 2e 6f 8a f0 78 b3 a1 85 e0 aa +86 e6 16 81 bd 1b d7 75 04 4a 2c 95 8d 61 ed c2 +51 60 7c d9 f3 11 48 f5 a9 11 + +# Seed: +37 6c f0 18 14 3b 0c e6 70 21 68 4c bb 36 e4 af +e2 ff 9d e1 8b c7 f0 2b ed 86 3b f1 bc 34 66 31 +9e 72 0f ee f1 9d 38 e2 6b ca 7e 99 d4 09 6a 9e +ed 8d e5 bf 20 3f c7 dd 9c 84 85 df a5 b6 90 75 +ef 0c c0 37 fc df b5 5a 0c 92 8c da c0 cb a0 49 +7e b6 0e 3f + +# Encryption: +04 8d d7 50 99 18 43 0e da bc 01 46 8d b7 e2 87 +a7 38 1e 42 8b 5f c9 3c e8 de fd 7f 49 d5 e9 34 +15 30 43 d1 37 ac a9 f7 b9 75 77 b7 0d c0 16 80 +f2 db a9 1e 93 2b 53 ac f2 a7 f3 34 8f 56 54 b2 +cf cf e7 5d 48 f0 fa 45 00 d1 ba 5d 29 24 7f f1 +42 d6 b9 80 e1 1b 9d ba 68 83 f7 3b b8 55 a2 4c +c4 eb 90 68 23 6d aa 0f 2f 93 45 8d 72 72 6c 2d +8e 31 25 9a cd 3a 7f de b6 fe b5 c6 d2 ed 17 8d +db + +# PKCS#1 v1.5 Encryption Example 9.17 +# ---------------------------------- + +# Message: +19 b1 f4 cd 3d bd f0 5b 3d 5f 16 80 85 6c 5a 74 +4f 51 62 b5 20 bf cd fc 98 87 dd 92 be 9d 8c b6 +25 c7 25 ad 75 f4 f2 ca a5 ef 51 fa ca 71 b5 e6 +6f 84 f2 fc 6f 67 8a ce 80 9d 76 b8 42 ea fe + +# Seed: +78 a7 18 82 85 3d 85 af 16 5c c0 b2 2f fd c8 87 +3d f4 9e 2d 6c c0 ad 0b 0a 99 5b 4a 25 9c 86 7d +c1 aa b6 42 8a 5b 8e 9f 3b e8 7d 87 f9 e6 ea c5 +50 f4 df 11 36 8e 7f 6c fd 7d 0e 47 6a 45 9b + +# Encryption: +06 2a 78 db 5c a6 9a 30 48 10 78 94 93 db 8c d6 +44 fb 29 4e 17 fd 36 45 32 b8 ec 17 ce 3f da 70 +47 64 65 62 4a 60 a6 ec db d5 d9 72 40 c8 d8 9d +ea c1 1d c3 0d 7b 85 14 41 40 8e dd 64 28 81 a0 +11 2b 62 f8 cf de 34 d9 c1 13 85 c2 91 89 bf 38 +93 a6 ab ac e0 4a 10 aa 68 0c d3 a6 ee 00 2c 30 +70 35 d2 39 9a 2a 60 b5 a7 f1 ca af 05 84 d1 0f +d0 6d 6e fd 56 11 4c 05 e4 3d 42 d8 34 f0 3e 3f +e9 + +# PKCS#1 v1.5 Encryption Example 9.18 +# ---------------------------------- + +# Message: +8c b7 3b c4 78 50 c1 7f eb d3 4f f4 b7 32 3b 50 +53 03 0b 96 22 14 03 cd ef 45 de c6 5b a6 0e a3 + +# Seed: +ed 64 78 61 48 81 eb e3 fd d6 d9 ee 05 f2 76 5f +c8 a3 ea a5 80 31 23 5a f9 6f 86 e7 f2 c8 13 ec +04 80 66 1d 1c 2b 4d ef 74 2b 2e 41 41 9d f2 88 +3e d5 86 79 cb 9a da e4 de c4 cf 77 f8 bc 29 41 +d0 33 f8 87 7a 90 6d dc 88 d6 dd 3c 53 96 ad aa +c0 3e b2 a7 09 4c 0f df 0a 44 a6 b9 23 ab + +# Encryption: +03 97 8d 4e ff c6 d6 2f 23 2b f4 6b 42 90 c5 01 +1d 73 28 0a b0 e8 0a b9 d6 05 0a 85 2a 66 79 e0 +17 e1 70 d9 e7 15 6c 8d cb d4 6c de da 70 ff 9a +55 16 8b 9f dc 03 65 b8 aa bb 90 9a ad 40 d5 95 +c9 0b 9f 00 c1 e0 0a d6 f0 1d 54 43 07 b2 54 ea +f4 25 5d e6 2b fd 8a 5f 7e 79 dc fc 74 45 ce c6 +3d f0 c2 bd 0a d9 6c b7 02 42 b3 0b 32 42 07 88 +16 b5 8b 0a 9f fa 16 f1 d8 63 15 f8 a1 cb 2f 8f +6b + +# PKCS#1 v1.5 Encryption Example 9.19 +# ---------------------------------- + +# Message: +8e a5 56 43 df e7 cb e0 75 c1 7b 93 c6 ba 6b 5a +74 ea 8d 1a ba b9 c7 28 ae 5b 00 86 6c 62 88 0d +3c 00 05 20 37 cf 80 2d 2c f2 a8 e1 be a5 8c 7b +a6 04 77 4d 4f 80 bc 04 + +# Seed: +af 9d 9d 31 2e 22 57 0f bc 4b c8 5a 44 5e d8 d8 +99 66 0e d2 4c f0 30 15 33 94 6e 5c b9 47 1a 27 +c5 10 cd 17 55 91 d2 3d 36 3d c4 e3 e6 9c 7b b4 +65 51 7a 4c d1 d1 ce 41 3e 10 16 ae af d5 5d 2c +b9 de bc fe 4b 1d + +# Encryption: +05 87 11 19 16 bb 42 f8 47 57 69 1e fe de 7e b7 +79 6a 5c f8 87 c3 7c a9 f6 1b 45 1f b1 ba de 38 +9c fc 5f dc 21 98 41 bb 41 da 82 74 52 72 5f c8 +2b 4d 1a de 56 9c ee c8 05 79 ed b1 b4 b1 5b 46 +ad 7d 45 b2 45 98 80 23 ea 0d fc b3 74 4a 69 2e +b9 ac a8 5f 21 10 10 af b1 e9 89 4f 85 4a 5e 34 +fe 89 aa 05 19 68 a3 b2 36 2c 15 0c 6d 97 0e dd +82 b9 e2 d1 3b 38 c3 c2 95 6d 91 50 08 86 41 d5 +30 + +# PKCS#1 v1.5 Encryption Example 9.20 +# ---------------------------------- + +# Message: +52 5c ff a3 + +# Seed: +0c 99 30 4c c6 26 3d 1e e2 44 6e 24 8c 27 11 2c +8f 96 da 82 51 5f 06 f8 12 39 8a 88 81 1f 39 fb +05 62 05 c4 4d 6b d4 85 5a 62 c2 1c 60 1b 88 f8 +02 34 e2 32 41 f7 16 32 2d 80 54 a8 4a 1f c3 c8 +46 de fb 61 76 7c c4 d8 16 fa 7b 37 47 f8 72 9b +f3 37 2a c2 c2 29 d0 52 f4 5b c4 2f c3 80 50 dc +a3 f2 63 2e 60 07 b6 08 53 b7 e0 cc b3 da a4 94 +e5 53 35 fd 04 f1 3d 5f ad a7 + +# Encryption: +06 3e 45 08 e5 31 2b 5c 38 69 4d e8 2a 71 ed a3 +12 e9 ae d0 5b c1 43 d3 38 f7 f2 28 12 d9 3c 28 +65 12 6a 9b 3a 42 c3 ca 19 ed b3 46 01 c0 b2 8a +75 66 3b 18 f2 39 f5 ad ca a4 e9 fa 9f 61 18 04 +72 6f a1 29 62 bb a3 23 0c b8 86 d6 67 82 a4 7e +a9 50 2a 83 71 e7 57 3b b6 b0 26 6c 33 64 6b df +53 f8 de 36 8e f2 05 b1 1a 85 ba f2 1d af 3c e7 +a2 59 9f 00 8b 99 45 ee b1 86 ec 19 2c 54 0a c2 +3c + +# ============================================= + +# Example 10: A 1028-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +0b 52 cb 6b 5c 3b 9e c5 aa ad 89 4e 51 77 f7 f4 +5b 8d 33 dc bb e9 6a 5b 26 f3 00 72 bf 15 73 a6 +c4 1f b0 a9 7a e1 e5 2e d8 c2 5c 62 b9 8b f5 9d +e7 b6 8a b9 8c 2d 8b 93 c4 94 27 23 cc 4b ae d2 +b3 93 c0 7b 2b 11 90 9c 73 2d f7 c1 dc bb 43 3a +83 9d 46 f4 28 e9 dd c8 d3 5f d3 3e ed 29 81 80 +f7 5f 2d 5c 9f e8 53 4f 03 47 f8 68 5c 28 c4 37 +ea 5b 81 1a 28 6e 81 0c 69 7a 88 cd 7e 45 36 4c +1f + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +0b 52 cb 6b 5c 3b 9e c5 aa ad 89 4e 51 77 f7 f4 +5b 8d 33 dc bb e9 6a 5b 26 f3 00 72 bf 15 73 a6 +c4 1f b0 a9 7a e1 e5 2e d8 c2 5c 62 b9 8b f5 9d +e7 b6 8a b9 8c 2d 8b 93 c4 94 27 23 cc 4b ae d2 +b3 93 c0 7b 2b 11 90 9c 73 2d f7 c1 dc bb 43 3a +83 9d 46 f4 28 e9 dd c8 d3 5f d3 3e ed 29 81 80 +f7 5f 2d 5c 9f e8 53 4f 03 47 f8 68 5c 28 c4 37 +ea 5b 81 1a 28 6e 81 0c 69 7a 88 cd 7e 45 36 4c +1f + +# Public exponent: +01 00 01 + +# Exponent: +45 cc 14 17 b2 6f ce 3e 9f d3 10 89 b1 a3 cc c4 +6f 8f f2 1e ac 2e 1d 67 c0 ae 20 15 2d c5 0d 1c +e7 ce 6f 26 40 4e 2e 64 95 b9 77 bf 13 f9 a4 05 +b2 45 80 d6 39 3a 85 22 54 96 e4 ab c4 9e be ff +de 70 cf 26 76 68 66 f2 76 e1 5b 49 2a f8 03 3f +1b ac 7f 66 b7 1a 3b af 57 1f fc cc 03 8a 48 86 +93 94 cc a3 fa 00 49 85 b4 34 a5 15 17 87 7e ae +97 a3 84 94 7f 01 a7 2c f4 b2 01 93 dd 27 64 81 + +# Prime 1: +03 5f ed ee 7e 64 fd 68 65 79 31 a9 df 9d 55 62 +28 df c6 33 a7 50 02 76 8f 65 d7 15 f0 44 f2 3b +3f e7 88 bb 17 86 4d 61 df 57 9e 68 df 80 de a3 +a6 31 90 62 9d ac 7d e6 29 ef 9a b8 f4 df 0b 27 +7f + +# Prime 2: +03 5a f8 e6 fe 2f 84 61 fc 89 a6 45 00 f8 19 9c +cb d3 f4 69 07 85 96 15 56 03 d3 f0 88 08 33 c3 +77 db 07 8e 43 7e 35 60 00 4a d1 d6 f8 d3 47 88 +3f 3e b0 1d 18 9d 52 ef f6 e2 60 e5 2f ba a6 2b +61 + +# Prime exponent 1: +b2 43 b3 49 8b 67 2a aa 7d 96 7c d9 f2 6a 12 e6 +22 3e 90 9b fe 8b 73 91 65 4f 3b 6c a7 9d 60 12 +70 a1 2b 11 d0 99 99 0f 6f d1 f5 0b e1 58 8f 66 +14 a6 19 63 35 9b 88 e9 b0 52 39 c5 f5 5c 24 db + +# Prime exponent 2: +01 35 25 ad e5 3f ee d2 61 54 9d 3d ea 8a 60 95 +79 1a 90 b5 98 5a 70 d8 be fb 63 b5 07 10 84 a8 +ce 23 4b 85 dd 2e b8 41 13 f9 d9 aa 18 25 da 71 +e3 e9 48 f3 3f df a7 70 ec 17 2f ae 6c ce 2d 6e +21 + +# Coefficient: +1c 52 92 93 3c 58 d0 22 59 2f c0 03 38 bf 22 ed +fc ba 33 16 16 b7 9f 8d 2e fd 1f a2 4c 64 f5 dc +fa d9 aa 52 ba a4 6e 86 59 dd a9 ea b3 a7 86 3e +61 37 4a c0 da e0 18 5f b5 8e cb 0b 74 65 ee 07 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 10.1 +# ---------------------------------- + +# Message: +59 22 d0 9f df 65 22 80 2f bc f7 a2 8e c3 d9 fa +df 60 72 03 a3 1b d0 da 96 3a a0 31 5f 35 e1 a0 +a3 74 d4 87 dd 08 62 a6 f6 be c9 32 b7 db + +# Seed: +61 39 5a 0f a1 2e 1e c2 ff ea 2a 88 90 65 3e 8f +37 8d c4 6c e2 b8 aa 4a 0a 1c 56 7b 30 e5 9c 3a +33 a6 68 98 97 14 fc 3d 45 ac 88 63 27 e3 6c 34 +5d a8 58 f9 03 d1 e6 06 74 03 14 cb 80 8d 86 ab +c3 1b 49 b3 5b 3f 20 e3 79 29 dc c8 59 d5 91 41 + +# Encryption: +04 39 e7 dd 09 af 61 c0 ee 25 f3 e5 c2 95 1d a4 +9d 3f d7 08 b2 97 a3 05 5f f9 98 3a 9e a5 38 b8 +3d 59 da bd b8 5d af 82 ae 7b b1 97 8e 7d a2 a6 +dc 05 87 ef 9c 73 2e e6 88 37 3f bc bf a2 da cf +f9 b3 c1 2f 70 4e e1 4f 83 24 bd 4c c6 bf 9d cd +3f 05 33 c3 b1 1a 0d 38 db cc 7b b7 ef 9a 72 29 +6b 6c 13 dc 42 d7 ec 17 f8 51 a5 16 12 c7 49 4c +63 68 a7 fb ec 93 d2 2e 8f 9b 72 bd c0 44 9f b4 +30 + +# PKCS#1 v1.5 Encryption Example 10.2 +# ---------------------------------- + +# Message: +5f ba d4 3a 91 0a 29 0e 50 55 d5 14 e7 1c 8e ab +f1 f9 33 20 eb d0 da 8f 90 d1 46 a8 f3 dd 5c 1a +2c 72 0b 93 21 1e 48 29 34 14 9f 1d 21 b9 78 f4 +8a 0b b8 e4 cc a3 f5 d4 5d 3f 3e 3b a8 e1 + +# Seed: +21 04 52 61 80 4b f7 54 bc b8 bf 34 98 b1 ad 10 +af f3 3d a1 f2 25 ed a5 64 65 90 45 8b 20 70 9f +c8 d0 b4 98 90 7a 83 64 ce 1c 43 6b 6b 1e 73 18 +1c 86 c6 77 af 45 c1 7f 9e 4a f3 75 9c ad 24 87 + +# Encryption: +02 9f 64 ac 33 01 34 00 7f 77 f7 2c 37 f4 17 7c +24 d6 60 be 4e ba c1 86 8a d1 1f 9e 30 51 b8 cd +77 c4 69 11 99 ac 49 19 db 2e d3 63 74 0d 2d de +32 91 f1 0d 92 68 e7 c7 de 37 ea 42 1e bb 1f ad +65 29 f2 92 19 2a 96 80 ba 96 3e da 93 74 03 7a +b9 52 9a 48 6f 35 cb d2 9e 09 ea 98 a5 04 5d 9e +16 bb 87 70 15 5d 70 af d2 17 a1 46 86 27 49 ec +1a d1 59 cf 6e 6a 63 df 14 2b 82 46 d8 44 a7 37 +2d + +# PKCS#1 v1.5 Encryption Example 10.3 +# ---------------------------------- + +# Message: +22 bb c6 16 ec 6e f3 57 31 56 b4 17 61 ac 3b db +57 bd 9b 70 36 ed c9 a6 97 88 75 e2 a6 14 cd e3 +ef ed af d3 88 9a 5d bd cc 5f ad 9e 9b ec f8 a8 +bb 80 33 ff 91 df ed 60 4b f8 c6 e9 bb c7 + +# Seed: +3b 47 d2 ca 95 54 b3 4f 94 29 57 8d 4f de c5 d9 +6e ca 89 b6 81 72 d1 db 13 56 b3 da 7a 69 f1 58 +4d 4c 84 6b 18 43 2f 02 f2 59 ca dc 24 e1 54 ff +15 f8 06 f2 53 43 50 0e 13 b5 be 43 c7 b5 ae 7e + +# Encryption: +00 c4 e6 c1 0c 25 5e 4b eb 2b 31 c1 65 68 46 b9 +7c a2 3a 3b a3 2a b1 9c 64 85 20 11 3d 70 34 df +a4 6b 0c d2 3d 73 99 a9 3c b0 2f 1e ba 94 83 18 +e3 79 1c 30 6a 2e b9 c0 c5 6d 8f 7e 83 25 0f 83 +ad 49 2f ad f7 83 17 69 f0 2e 18 24 34 74 45 d0 +41 9b 98 b8 e7 95 45 65 32 30 0b 92 d6 e4 55 b5 +a4 eb a8 53 d6 f7 45 92 90 ab 02 31 99 48 53 a8 +c0 7e 54 f5 9c 62 45 37 08 02 89 f9 31 43 eb c6 +61 + +# PKCS#1 v1.5 Encryption Example 10.4 +# ---------------------------------- + +# Message: +31 6c c4 45 0a 53 70 3c 05 8c 90 1f 50 7d 7a d0 +cb 63 96 c5 51 d4 f0 61 82 ab d3 a4 3a ac ba bb +31 59 c0 26 b3 e7 db c1 60 f4 19 53 31 7e 0f 20 +80 8c + +# Seed: +c1 ec b1 16 4b 3e 66 23 f0 d9 b9 c5 eb f9 9e 78 +8b 7b d9 4e b7 43 74 f6 1e d3 14 30 4c af 46 f8 +4a 3f ea 1b a0 e4 7f c8 be 41 97 d1 d2 cd 41 41 +cb 9a 61 5d 89 c4 bd 91 10 ca 6a c9 a5 60 f0 76 +eb e6 9b 74 a1 0f e9 cc db 76 da bd + +# Encryption: +06 16 b8 bc 77 2c 55 64 d4 51 b1 28 d9 b1 36 4c +9e 33 b6 e5 58 ec 67 f2 10 5c 98 00 11 7d 0b 73 +cc ab 9d b5 1d 96 7a 9d 66 32 2c bc 5a 01 74 6e +47 31 dd 7d 04 e6 36 e6 4d 35 f2 c8 6c a3 9d 26 +14 92 17 6b 8d ab db 13 4b e9 4b e5 1b 6c 02 3a +0d 55 fc c1 f0 4c 94 c8 6d 47 7d b4 03 b0 4f b6 +c0 28 50 57 24 79 38 40 cb f4 68 aa aa 91 bc 54 +e0 d6 47 7c e6 48 ce dd 12 76 f2 ad 2d 4d 42 3b +6c + +# PKCS#1 v1.5 Encryption Example 10.5 +# ---------------------------------- + +# Message: +d5 4e a3 7c bf bd b8 18 3b 3b 54 7f 6d f2 d5 d6 +3c 41 5b 1c 44 ed 63 93 c6 97 b4 d9 3a 97 fa 0d +2f 4d 30 0a 68 e9 8f 7f d0 46 07 01 d1 57 9d 96 +83 61 2b + +# Seed: +d1 ce b0 c0 72 d6 88 8f a9 1a 75 7c bf 50 d6 69 +76 bb b7 2e 61 94 62 61 4d 5d ec 0f c0 bb ca bb +07 07 89 c2 b0 89 50 91 b8 fa 9c 7e 75 ab 20 b8 +97 58 f9 7f d0 47 bc 44 a5 68 a2 61 2d 0d 50 1d +15 d4 fb 82 e7 75 28 79 69 49 f3 + +# Encryption: +03 c1 38 c7 91 99 b0 b1 70 0b ab 2e 63 e1 d2 a0 +03 1e f6 02 f7 dd f1 ed 3a 16 1a 5e 70 f1 64 51 +da a1 01 f7 4c dd 65 47 a7 c6 52 c7 32 9b b1 73 +7f b1 4c 1c c0 c0 c3 e7 61 2a e2 0e e0 21 ab 21 +d7 0b f9 51 7b 4d 33 a9 d8 09 61 2e 7f 42 68 85 +b7 9b 31 2e 26 6e 42 b2 02 b5 71 c6 6f 9a 10 7b +8f d7 c5 6c 05 0a 8e 1e b1 89 56 db 06 a0 20 9d +d1 6e f2 d9 05 24 db 87 91 7f 34 00 6b e6 b1 5a +13 + +# PKCS#1 v1.5 Encryption Example 10.6 +# ---------------------------------- + +# Message: +f6 4b 25 11 cb e3 cc 65 81 + +# Seed: +da ca 19 63 cb 3d e5 24 57 79 e9 64 77 ff da 27 +7f 4b 92 3f a9 a8 d9 38 5d 52 31 69 23 3f 58 79 +a3 c9 fc 7a 38 e1 b2 08 c3 2d e4 0b be 1d a0 77 +47 1e 61 c8 b9 b7 09 3c 41 b0 a6 5c 99 64 32 d6 +45 52 11 84 a6 6a fc b9 6f 07 a8 f8 ee bb 6e f8 +17 e0 27 ee 2f 37 95 45 23 9e f6 f9 c1 d0 d8 60 +e8 21 44 ec 71 59 7f 24 6a 83 cc f6 60 ea 4c 70 +ee 1d f0 14 ef + +# Encryption: +05 08 ed 84 5c 96 23 8e 3a 07 e8 ec 02 7f 7b 09 +8a 83 f0 3e ac 1f ec 42 6f 4d 60 05 b6 0d 07 35 +db 05 37 08 2f 23 b7 50 f6 db 54 88 21 41 81 e1 +14 cf 1f 72 07 41 9c a2 93 75 0a a7 66 fa 7a 5b +9b e0 0e 37 29 2c 23 23 1c 6a b3 be 2d ed ee d3 +21 b0 f9 cd 83 2c 5e db 41 67 7c 1a b9 83 e7 e3 +eb c8 b5 19 93 82 1d 76 df 2a c2 29 8d 8b 80 ab +17 c3 8b 38 53 f1 8f e3 09 cc 7b f7 c4 a2 c2 7d +63 + +# PKCS#1 v1.5 Encryption Example 10.7 +# ---------------------------------- + +# Message: +85 26 49 01 52 06 e2 a4 09 78 76 f8 ab b9 b8 46 + +# Seed: +03 4f e3 4e 20 e6 06 a8 dc 7c bc d0 d6 ab 3e 07 +97 c5 dc 4e d7 86 8e dc 79 59 89 3e 58 13 7d 26 +32 b2 c5 a2 9a 81 35 c2 4a f6 99 b5 9d 68 10 3a +1f 42 33 93 e3 88 6e 3f a8 54 e3 97 21 50 19 41 +3a f0 b0 d4 fb 1b d6 9b d4 93 4d 4d 1e 2e 9f 3b +9e 7c 46 d4 98 4f e9 e7 a3 7a b2 f1 c7 8b 0b 8d +9c d8 fa bb 3d 18 d4 c5 06 e2 fd 3f 85 ae + +# Encryption: +01 6f bf 2a 7d 36 80 71 cc 7b e5 94 49 35 4b 9d +e0 5a 85 e1 bb 97 b2 51 4b 52 b8 d1 f3 e2 69 94 +e1 2c fe da 59 e0 58 a2 f3 c8 79 23 50 c0 68 41 +7f 99 44 1b fe 74 17 e0 b5 31 6e 16 3b a8 d1 f9 +e3 2c 59 a4 44 98 82 f4 7a d9 b2 4f 68 76 d4 78 +d3 f5 b7 d2 75 35 73 e3 f6 97 bf 64 c7 b3 ac 22 +28 ce 69 e7 5e 8e 14 ab 93 f2 19 78 05 9a 14 3b +87 7c 6d d4 21 b6 e2 0b 07 35 a5 36 05 55 2a b0 +a8 + +# PKCS#1 v1.5 Encryption Example 10.8 +# ---------------------------------- + +# Message: +f4 fb 50 be ab ec ba 77 e7 1d d8 d1 6c 97 5a 86 +f6 19 ea 7d bf 41 96 9a 24 ba e2 b8 42 c2 69 e0 +b4 d6 a2 9e 82 9d be 2e 49 79 9c 9e d9 71 a3 03 +35 e6 ed 9b f3 9d 12 4b e0 f8 + +# Seed: +9d bd 92 da ee b8 2b de 81 6c 59 3f 70 6b 15 92 +56 85 22 bc a0 79 7f 9e 81 1d d9 dc 0e 89 6e 98 +4a 4a 9a ce 77 de f5 a9 25 0d b7 95 81 af 33 fb +6d e2 42 7d 1a f6 a5 f6 92 9f a8 b6 7b ad 02 3f +04 b3 ff d2 + +# Encryption: +02 92 ed fb ac 38 e2 22 45 45 af 82 86 23 27 63 +bc b1 8b ae 13 70 97 99 e3 50 77 58 d0 14 1a c2 +97 6f 30 b8 54 67 d7 83 ab f6 fc 71 df 61 9e 1a +59 e6 23 4f 27 b6 32 fe aa bf d9 85 33 77 35 4d +93 3e f4 ec 59 94 c0 d5 0d 95 2e 0e ce 0b e1 be +4d 38 f1 1f 66 e7 c3 da 88 c8 3b 4b ed cc 06 2e +09 f9 af 95 ea ca c0 09 9c 52 5f 24 1e a7 d5 65 +e1 b7 68 cb 97 08 f3 bc d5 91 77 b6 76 6a 37 34 +88 + +# PKCS#1 v1.5 Encryption Example 10.9 +# ---------------------------------- + +# Message: +76 91 3e 84 8f b7 b9 fa ca 91 ba f4 f4 42 01 06 +a9 4d 6c e2 5d 14 97 fc 4e 7f 85 96 54 79 5d 7f +24 39 9f 3a 12 08 af 02 8e 61 67 8a 6d 19 a1 86 +40 b4 d5 0f 75 55 86 00 + +# Seed: +9c ee aa 26 09 ba 90 eb 61 e4 f7 49 c4 cd a0 1a +ea 23 68 81 76 2d fc 15 0d 97 c1 1e b6 44 0c b0 +57 e5 3c 3f d9 b3 9e 56 0a 46 e9 d3 fa 3a f3 fe +e5 ee 2d 02 fa 42 49 af 99 98 f5 3e d0 4d b0 10 +e9 6d 8a 01 ff 6b + +# Encryption: +01 96 30 89 c3 43 ed 88 b5 6d 6a cf ef bc 65 5a +37 cc fd 96 20 3f 21 87 64 69 5a d3 10 c0 b2 66 +65 ee 74 5e b0 10 fc 83 be 8c 20 64 5c 43 47 dc +d9 44 65 5d 9f e6 cd 98 77 dc 70 e5 c1 88 cf c9 +a6 6e 71 da 74 5c d3 e1 a7 b7 f5 a1 b2 5b 4f c1 +47 0a df bf 7d 8e 45 fb 10 7c 5a eb 50 ea 8b 56 +e0 4c a5 5b 9b 65 2a d8 34 d9 c9 65 77 b6 42 ef +33 f1 64 d4 93 1f b8 9e 0c 8c 6b f9 17 08 fd a6 +db + +# PKCS#1 v1.5 Encryption Example 10.10 +# ---------------------------------- + +# Message: +c3 39 f8 57 e4 d0 23 1f a3 7c 06 f0 95 6b 4d 53 +a6 c5 8e 06 10 d8 da 43 17 dc 84 11 d3 a0 f8 98 +49 b9 4e 8d 7c cd b0 c7 d5 33 0c 25 + +# Seed: +24 90 81 6a c9 69 76 ca 72 5e b4 98 e2 ff 04 0a +fe 3d 64 17 d3 2e 4f fb d9 fc 9e 3f a6 8c e8 49 +c8 81 be 37 9f 17 50 4b 97 e1 e0 d2 2d 32 ff 8d +fe 76 bb 45 49 f7 13 b5 b8 d8 70 ed 36 59 dd d3 +98 4b 6f b3 9f 6e bd dc 11 77 ad 69 8d 90 44 39 +68 ab + +# Encryption: +00 b5 fb 7b 1e 9d 71 df 8b 16 c6 3a 1a 49 6e 6f +7b f7 72 86 4c b4 11 55 2b 50 e0 b7 f1 5e 45 97 +16 f5 64 62 43 68 76 33 a9 10 6c 34 6c 8c 6b 7c +fa c7 50 b4 56 6b 1b 88 aa c0 ac b9 16 c0 7a 78 +0b e0 6d f7 97 5c cd 8b 72 60 78 68 7a 8e a5 d3 +90 3e 04 ab 1d 23 dc 9b 1e d3 60 00 c9 bb c3 dc +81 61 e9 48 3a 18 ab b8 64 1e bb 1f dd 02 66 c0 +84 bf 0b d0 9c c9 4e eb b9 28 3c 5a 5f 74 e3 60 +13 + +# PKCS#1 v1.5 Encryption Example 10.11 +# ---------------------------------- + +# Message: +47 58 65 a5 7b db 91 ad df 77 7c c9 d0 a1 7a 71 +a9 f9 71 0a 93 1b d0 c3 14 9b 23 91 a3 53 + +# Seed: +56 2f 79 70 94 6a c4 cf 05 ed fb 26 34 16 7e 14 +d6 65 8d 24 cd ae f7 5b 40 7c 90 04 81 8e fa 75 +d1 64 5e 81 52 d1 fc 80 d6 99 df e9 9a 27 a7 df +99 7a 8a 66 47 5a af ce 41 95 98 e2 a1 91 99 fc +20 53 e3 ac dd 07 fe c8 ba 61 f2 b0 3e fc 7d ee +d8 15 cd a8 95 2e 21 e3 c0 b9 a9 35 2a b3 6f 5e + +# Encryption: +03 e2 68 d7 d1 80 d0 3c 7c bc 85 07 ed 1f 83 0e +d3 7a 79 95 71 2d 7d 91 57 32 24 3d e6 85 d5 bd +99 a1 4a 8e 86 a6 7c dd 60 dc d9 0c 33 92 10 83 +5a 46 ce ac 19 36 ab 3a a9 c3 81 88 2d 76 94 a8 +38 3d 68 98 e2 73 44 bd 15 6f e9 28 2c 71 32 26 +25 d6 8d 30 70 ef f0 1a c8 d5 95 f6 48 6d 79 b7 +88 e3 69 12 fd 3c cf 28 4e dd 5f ce e2 40 9d ca +7d 4f 29 cc 18 2a 78 47 8b d3 ea 23 62 11 25 10 +a5 + +# PKCS#1 v1.5 Encryption Example 10.12 +# ---------------------------------- + +# Message: +9e 1e 53 f9 86 59 9d a8 98 d5 6d c1 c7 55 6f ef +ca a3 39 5d 84 50 d5 2b 3b a7 + +# Seed: +0b 17 63 cc 34 0e 6e 39 78 62 6a 06 d6 ef c4 0d +ed 73 db 53 5a 82 2e c0 4c 99 24 d9 ec 40 d3 85 +20 15 d7 e1 02 9c 13 93 ad cf 01 50 30 8a cb 27 +3c 36 35 68 28 a4 77 fc f9 a2 9a ca b9 09 35 70 +42 50 26 da c1 4d a6 cd 30 4c da a5 4c 9a 4c 5a +99 4e d6 8a 5c ea c7 e0 81 de c4 64 6e 23 7e 47 +1e 52 5e f8 + +# Encryption: +06 d5 19 a7 30 ea 5f 54 9f e1 9e 30 1b a5 15 2d +10 3a 3e ad 3f 89 ab 35 16 ff 7b 34 4c 4f 72 a1 +c2 6a a9 0d 5a 01 a2 a6 51 93 d3 cf 63 41 e5 9a +31 fd 2d 7d fe 43 5c 09 84 d1 bb e8 11 32 01 0f +43 58 ee bf e8 3f af 24 1e 7f 35 af 98 b7 c7 ab +91 e4 f0 e8 a3 2a 2f 57 f0 7f 49 d5 c2 1f 1e 13 +80 ba 0e 17 9a 38 d3 a2 ca 46 4f c1 4d 2b 74 a0 +3a 88 84 aa 85 7b 66 01 47 02 b1 bc 4e 7c c5 e1 +eb + +# PKCS#1 v1.5 Encryption Example 10.13 +# ---------------------------------- + +# Message: +1a e3 1e 0c be 44 97 ba 43 c5 d1 5f 53 5f e0 18 +84 1c 73 14 57 67 a6 a4 c8 + +# Seed: +8f f0 fa a7 a2 b4 ff 55 3c cb b2 0f f3 10 ac 5e +0e a9 28 18 56 2e c9 a0 60 64 f5 de 79 86 b4 f6 +c9 ae a2 b9 f0 11 42 38 e5 a4 99 a8 ae 20 ea e4 +02 1f cd d8 f0 60 c9 93 a9 bf 64 2d a0 25 67 39 +33 48 08 e3 88 e1 da 82 37 27 8b f4 f4 7e 05 01 +5a 8b 88 c5 42 0c eb c8 bb 37 ee 43 52 83 7a f7 +64 70 18 41 97 + +# Encryption: +04 a2 10 f7 6c 0f 84 93 99 09 53 58 98 86 f6 2c +1c 48 25 01 2a f4 4b dc f2 c9 9b 32 a7 0a 17 f7 +64 a3 a9 7b 2b 04 7e 39 d8 0c de 15 4e be d5 d2 +81 3e e8 4a c9 c8 d6 ec 6a 96 f4 02 db b3 26 d5 +a6 e9 c0 f7 87 c1 5e 98 23 c5 08 b3 23 5f 3a 00 +8d dd cd db 07 9e 80 ff 50 fe 37 25 4a 0c c4 68 +29 7e e3 32 53 a7 4c 1e 03 70 26 05 69 58 ad 07 +78 e0 aa 12 50 df 1c 14 85 7c b0 d7 1a a6 93 7e +31 + +# PKCS#1 v1.5 Encryption Example 10.14 +# ---------------------------------- + +# Message: +a6 e3 d1 07 03 21 d8 ff 76 b8 5c 70 93 fa a0 42 +83 + +# Seed: +d1 60 b1 2c 76 62 2c 3d 34 d8 55 87 e6 e8 1c f0 +54 61 8a 34 6b 67 52 d5 36 9a 71 c4 92 35 7a 13 +4b 7f 67 f3 34 a4 f3 b3 28 ba a9 f0 07 18 47 d0 +da fd ac 22 5d 7b 7f 07 16 18 ea 86 81 fc d2 d2 +30 5c 2f 64 63 1e 62 31 85 fc 09 96 e6 1c 84 f4 +18 0c 63 7b f6 ea 2d 06 03 75 f1 6a 65 e5 b1 e2 +b8 65 28 5d a3 d8 fb 1b 6a 60 ea 36 e1 + +# Encryption: +0a 70 03 b5 86 1a 85 a8 f7 2f 19 9d c6 5c 17 fc +58 a9 24 bc c4 08 19 e2 8c 95 83 e8 21 03 8c 00 +05 36 5e 90 9e ee 4f 32 66 f5 9a 84 e3 25 b1 be +a9 d2 81 b4 82 3f 2f ce 44 15 3f 03 17 0f ad cb +16 a2 79 b2 c9 58 7f 6b 79 ef fc 55 a3 c4 34 e0 +bc 5d af e9 d4 03 26 48 aa e7 e4 ed 1d 7f 14 1b +fe 72 26 83 fa 32 c8 9d dd 67 3c 3f 0c 03 c8 54 +59 89 0a b7 fb c1 d9 a8 14 bf e9 b0 d1 2a b1 7f +51 + +# PKCS#1 v1.5 Encryption Example 10.15 +# ---------------------------------- + +# Message: +d0 bc 89 03 9b a1 9e e5 0a 73 82 98 4e 42 8a ed +88 61 4f 78 98 13 01 89 16 e2 e7 eb 0d b8 3d a2 +8e c2 3c 04 a0 c2 f7 6a + +# Seed: +c6 4d 10 a4 b5 2f 49 0a b6 2a 60 38 b3 2b 23 c6 +3a 1c 85 97 0d 93 45 14 83 94 cd 35 cf d6 f6 b1 +59 0f ce 8c 67 5b ee f8 7c d0 34 5e 5c ad e8 95 +09 45 56 54 26 b6 b2 83 03 b0 b0 39 32 98 cd d9 +5c 88 1f a0 65 33 ca 9d 2d 27 14 d0 f1 37 85 a6 +1b 3a 17 a7 81 40 + +# Encryption: +00 8b 19 75 58 ca 4c e5 90 14 58 ab d8 e8 fd 52 +d9 89 96 0f 01 c2 16 ef b5 81 f8 61 14 8d 1a 2b +44 eb 0b 7c 15 dd c3 45 dc 83 f9 03 7d db 8f e2 +ea a2 cb ed 9b 1c 1e ee ae b8 65 bd 29 f4 4e e1 +47 8c 95 e9 fb f4 44 82 8e ed cb c0 17 02 00 de +35 49 b2 2c 11 e4 b4 33 79 8b 9d 63 bb 49 f0 b0 +2d af 56 58 ce ed ea a9 3c 0f ae b9 44 65 38 ba +92 eb 17 c8 5d b5 ee a2 04 ba 2f 49 c3 ce 65 bf +13 + +# PKCS#1 v1.5 Encryption Example 10.16 +# ---------------------------------- + +# Message: +ce 0a 4a 59 39 f6 aa 26 3b bf 8e 1e 5e 94 31 03 +56 ab a5 75 59 c4 1b 39 44 27 70 b6 1f 6b 3c 9b +5f e7 27 f3 19 52 28 08 d5 80 19 + +# Seed: +27 cc e2 d4 3c 71 31 8e d4 fc 8c 0b db 9b 79 13 +53 19 9f 3d 89 fc 12 ac 47 fd b6 d8 8b 44 c6 54 +5e 9e ee d9 f4 c6 85 15 d4 f5 30 b8 13 7d 77 45 +71 3b ad 0e bb 70 52 23 1f 6b 4c ed 18 7a ec d1 +e7 a1 69 d8 6c bd 13 d5 0b 78 be 27 c6 54 5d 81 +92 e0 ec + +# Encryption: +0a d3 ae 7e 5a 98 65 2c 1b f3 45 c4 91 90 3f 55 +17 c6 11 ac 31 00 05 87 7f a9 1a bc ee 64 85 f2 +77 8a bf 0a 6c 73 87 87 37 63 9b 26 72 fd d0 0a +39 65 d7 d3 d8 d7 68 8e 77 b5 45 9e 14 5e ce 64 +a9 a5 2c 37 97 f3 61 07 c9 36 8b df 79 90 f3 fb +6c 5c ff 59 f4 f8 a3 d4 90 93 df fe 74 06 c9 10 +aa 57 23 22 8d ae 5a 9b 29 a4 cc 47 69 af 8b d5 +fd 6e ce 88 58 a2 9d b1 b1 9c 08 1b f0 d6 b0 dc +78 + +# PKCS#1 v1.5 Encryption Example 10.17 +# ---------------------------------- + +# Message: +03 bf b2 59 bd 92 46 de 3f 71 c3 13 9c 72 85 74 +b4 4d 97 ad 57 bb dd 67 01 94 95 c2 a2 00 41 39 +26 34 e3 1a ad 63 f6 3b + +# Seed: +5f a4 bb b7 0e 1f 9e cb 5e b2 14 7b f4 59 d1 d0 +64 43 f0 25 c0 8e 36 4c cc 1b 16 0c 16 41 6f b1 +74 b4 4b 95 36 38 a9 68 8c 5e a2 d0 60 17 1f 30 +54 f3 ca 3f e0 13 b9 e3 18 8e e3 9d a9 1f 80 16 +d4 b7 33 18 79 35 1f 32 2a e5 29 86 4d 90 74 09 +8a a2 51 6b 44 ca + +# Encryption: +01 78 e3 a0 17 ed 2f c1 18 bb 2e 03 28 be b2 8a +98 c8 53 b9 e5 a5 f8 30 80 c0 f1 01 7f dc a8 37 +92 07 72 2c 25 73 7a 89 15 e0 eb 72 c5 22 85 e8 +8f 61 30 a1 cf 56 ad 1d 96 ca 2c e4 b7 1e c3 68 +94 7b d0 71 f8 36 59 10 c7 92 57 5b 8c d6 fd 27 +e5 23 e8 59 65 dd a9 22 82 d5 df d1 c0 64 ea ab +6a be ac 65 e1 6a e0 4f 0d 40 b3 bb 68 41 0b 92 +74 df ee a3 2a 43 f9 40 83 c1 07 80 35 3f 43 e4 +3c + +# PKCS#1 v1.5 Encryption Example 10.18 +# ---------------------------------- + +# Message: +16 2c ca 9e d4 70 8d d1 03 40 e1 94 c3 5c 0a 5f +a4 9a 5c 3b 5b 24 71 71 20 3c a4 8a 79 e5 2d ff +40 f2 bc a9 9a + +# Seed: +4d 73 ff cd c2 69 43 a8 70 78 23 47 8d a3 1a ac +01 27 4b 17 17 c5 0c 6a d0 c6 2e e2 bc d5 57 95 +2e f1 3f 15 ff af 66 bb 4f 45 39 99 11 c6 d6 5a +d1 87 57 2b c1 eb a0 d2 86 cc 45 aa 49 32 e7 3e +47 0c 5d c8 29 39 04 02 5c 86 3f bc 96 22 37 04 +90 c9 1c 87 40 b0 94 d8 f0 + +# Encryption: +04 2b ce 0d fc ec a9 ff 05 a6 e3 f7 4a 6a 70 cd +cb e0 de c8 1e dd c8 8e 46 7f 47 bb 76 0d a4 4c +79 4d 3c dc ab 93 92 49 f8 49 d1 d4 39 56 64 1b +0b 79 c6 86 1c 5f 71 5b 9d 8d 8b e9 f0 76 6a db +3f 18 af 7d b3 6a d9 5f fc d7 e0 fa c1 62 85 23 +e8 f6 9a de b7 ff 50 94 a2 b5 bf 92 b9 d0 ef b1 +11 8b 85 39 26 25 fd 56 f8 8f aa 0a 16 d5 47 30 +fb c5 ca f1 66 82 e9 e4 1b 7e 79 d2 02 2f 7c cf +96 + +# PKCS#1 v1.5 Encryption Example 10.19 +# ---------------------------------- + +# Message: +8e 1b 52 cb 4e 00 77 27 c4 b5 f6 5d 78 47 f3 49 +16 89 1e f9 c7 3a d1 8c f2 71 f8 9f 18 2c 69 3e +52 89 dc 31 da bc 34 cf 7f 44 fb de 57 9e 64 51 +69 ec ba 6e 4e 87 7f 7d ef 44 + +# Seed: +ba 14 74 8e 6d a7 b6 ac 18 33 32 32 95 ad b5 42 +2d bd 19 e2 ec 72 df d0 aa fd 7b d0 7b fb 97 e7 +db 10 8a 3e aa dc ff 67 b6 7e c7 e4 c6 70 04 c1 +78 34 6a 12 5d d3 b6 ca 55 23 70 59 4f 7f 42 cb +33 4b 44 85 + +# Encryption: +09 4b 40 30 e3 0c 8b 46 2e ca 00 f1 6b b1 70 19 +d1 ea 31 25 f1 c6 4c 67 1c b0 0d 46 e3 ad 87 84 +28 52 b2 01 49 6e e2 b3 d5 42 28 93 a8 0c 66 a3 +0d a2 c9 f1 a3 2a d4 d4 e7 73 77 43 ca 1b 78 ef +7d 4a 63 c5 e1 e0 be 7e 51 88 cc e9 42 95 69 74 +ff d4 81 e6 47 83 44 23 0c 37 da 5b 25 f6 b5 99 +a5 9a 05 80 f1 a0 00 c2 59 54 f3 a4 63 f2 89 5f +32 b0 5c c0 88 21 b1 a0 23 60 9f 18 ca 7d 44 9c +b4 + +# PKCS#1 v1.5 Encryption Example 10.20 +# ---------------------------------- + +# Message: +82 ff 62 af fa d8 00 30 94 cc 65 35 + +# Seed: +1c 7f 21 fd 02 09 79 07 40 5e aa 77 ae 72 88 65 +72 1d 93 86 f5 aa bc 2e 0a 95 f3 ed b0 5d 46 e2 +33 79 3b a1 a3 88 e4 b0 dd a0 0c c3 2b 94 8a c2 +65 ae 6a 2b f2 c3 90 a4 dc ce 11 0d 5e 86 64 47 +28 f5 37 81 36 47 6c f7 1d c7 ba ac 50 cc 41 c2 +01 48 dd 37 d5 f7 0a 81 2a 29 4e 24 2d e8 03 b4 +8b 63 40 f4 28 d3 c9 bc a9 6f 76 6f c4 f4 41 67 +e0 4a + +# Encryption: +00 30 3c 35 2e 1f dd 2a f8 a8 e3 a1 69 b5 da c5 +43 45 ca a3 35 a7 1a 37 e9 38 bf 98 47 08 86 56 +84 18 ae 98 d0 aa df e7 9d 0c 65 1b 3f 51 6e 70 +f1 01 74 fe 63 22 cd 37 6d a0 2f 22 6d 15 b3 6a +bf 6d 1c bd ab 6d d5 65 4d 99 25 f7 25 3c e9 91 +51 2a 44 e9 fa 15 27 12 d7 b8 db 7f 18 33 75 80 +fe 51 dc 32 a0 58 2c e2 60 53 f1 b9 49 28 69 b9 +c4 7d f9 28 39 c0 50 2f 2d b4 cc 4d 0b 20 4f 6f +d1 + +# ============================================= + +# Example 11: A 1029-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +11 65 47 94 f4 64 9a 97 ac 87 ef 67 94 f6 a6 ff +b5 cd ab 87 02 c2 32 54 fd e0 34 f3 12 9a ad 82 +5c f3 c0 cc 38 80 a9 6f b6 4e 48 d7 59 5e de 06 +c3 1d 0a cb d1 f8 ef 9c d1 f9 f6 f0 0b 24 ba 53 +45 ab a1 46 d4 1c 56 3b ae ce 3b 25 23 df 6a 9f +43 01 8a 5f 08 69 b6 ec 99 34 69 88 6b 5d 23 17 +d5 9c ff d4 ed e9 46 6a 03 f6 df ec 17 5c ad 5a +85 44 30 95 c7 30 b9 8b bf a0 48 9b 91 bb 27 39 +9d + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +11 65 47 94 f4 64 9a 97 ac 87 ef 67 94 f6 a6 ff +b5 cd ab 87 02 c2 32 54 fd e0 34 f3 12 9a ad 82 +5c f3 c0 cc 38 80 a9 6f b6 4e 48 d7 59 5e de 06 +c3 1d 0a cb d1 f8 ef 9c d1 f9 f6 f0 0b 24 ba 53 +45 ab a1 46 d4 1c 56 3b ae ce 3b 25 23 df 6a 9f +43 01 8a 5f 08 69 b6 ec 99 34 69 88 6b 5d 23 17 +d5 9c ff d4 ed e9 46 6a 03 f6 df ec 17 5c ad 5a +85 44 30 95 c7 30 b9 8b bf a0 48 9b 91 bb 27 39 +9d + +# Public exponent: +01 00 01 + +# Exponent: +1d 4c 4c 6e 13 da b2 84 6c e6 85 d0 c4 93 52 5b +b0 ad 35 62 59 6d b9 ad 16 94 5d 44 5c e6 7c 54 +e9 38 f6 54 54 2b 09 34 48 02 91 ac 21 ae d0 98 +e8 5a d6 fe c6 d0 fe 15 4c 3c 34 2b 16 99 9a 8c +ec e7 fa f9 90 b7 c8 ce 87 b6 6f e3 27 fb 35 2e +d0 11 32 3d 2b 81 9a 36 ca be cc 5a ae 72 30 d3 +f8 e0 02 45 af 35 af 80 88 62 e5 4d 92 56 07 ee +8b 58 e6 a9 f3 ad 8f a7 28 fc e2 68 56 c3 67 b1 + +# Prime 1: +04 41 0a b5 54 60 2d 7e fb 0c ce 92 71 a5 22 20 +f2 52 50 02 34 b3 82 02 fa fc 94 aa 26 b4 fb 04 +e5 f5 08 74 9a 44 ef b8 9b 75 78 db 00 7e 03 06 +23 89 48 69 12 80 f7 3c 12 7a 49 30 b4 63 39 ba +d9 + +# Prime 2: +04 16 d3 fd ed 8f 9e 7b 01 9f 67 12 32 0e ec 11 +d8 cc 83 81 ea 86 26 6e e0 3f 00 72 e9 a2 fc dd +80 81 ae 74 fe 27 88 70 f4 fd a2 a0 00 6c 4f 54 +23 9e 24 a1 5d 1a eb c6 7d 90 d8 18 4d 29 5f 52 +65 + +# Prime exponent 1: +04 06 7b 98 7b 5f 8a 8d 56 06 97 4d 11 06 1d 96 +29 55 63 e9 c2 6e 7d 3e 4e ba 43 fe 01 24 4d 46 +24 46 49 1a f4 82 f8 86 a9 6b 6d d1 64 d4 d8 0d +ae 00 90 29 04 5e 4e 13 64 b4 9b 9e df 81 e8 b5 +79 + +# Prime exponent 2: +e1 38 72 e5 6d 84 d7 4a 1e 15 7a e0 b2 3d 30 09 +c8 d6 72 59 16 cb a6 07 31 06 d3 b2 58 92 b6 c5 +33 21 69 a2 54 b7 12 36 63 6b 5d a9 39 a4 47 a1 +f2 20 47 67 54 a7 6d 69 0e 84 af 95 ca 54 eb d1 + +# Coefficient: +02 51 37 ae 5d 25 fe 1d af 9b 38 32 f8 07 56 b8 +6d b5 ca 0e 37 2e 51 63 03 4e a3 39 1f 5e 54 58 +2a 1d d0 47 58 b9 92 a5 a8 e4 6e e1 6f 8a d3 8c +a6 52 27 45 aa 7d f5 1d f8 9f c2 21 08 01 0e 00 +4e + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 11.1 +# ---------------------------------- + +# Message: +4e a8 df da 3a 9c 26 70 ca 9b 80 fa 89 71 0a + +# Seed: +96 06 42 1b 97 3a b4 ba 2a e2 2f f5 38 70 7d 7d +4e 56 3e 8f 05 f2 0b c3 38 1f f4 5b 0c 29 19 a1 +b3 46 b0 76 03 5a e7 74 b3 2a f8 ee 56 6c 73 e2 +09 49 68 4e 44 74 80 df a3 4d bb 0c 22 66 61 50 +90 9a 59 e1 bb 22 d0 95 ab e5 02 5a 76 d6 0e c1 +01 c7 80 e8 3a 0f f1 59 46 5c 3e 7a c0 21 2b b3 +8b 2f 1e 0e 6e 0b 54 d3 5f 4c 76 04 c2 d0 93 + +# Encryption: +09 bb cd 8b 63 b2 9c e9 52 26 ec 1d 51 91 2a f3 +97 89 fc e5 e7 7e 7b e6 78 96 c2 c4 e4 c4 37 6f +a4 28 ec 5d 8a 49 7a cc a9 e0 82 1e 1f 6d e1 06 +78 19 c4 8a 51 6f 06 91 cb ea cb b1 9d 1b a5 09 +f0 4f c0 13 36 d9 0f 73 96 b4 3a a2 f2 b5 15 0c +28 a4 5f 35 a9 de 1a 29 73 ea 10 28 67 94 94 0a +b7 9f 12 9e 31 8c f9 7a 5f d7 2b 04 5b 46 6d 66 +6e 5d e0 b7 14 f2 12 a0 b9 05 2a 0c 91 44 8e 52 +0d + +# PKCS#1 v1.5 Encryption Example 11.2 +# ---------------------------------- + +# Message: +c6 e2 57 f3 a1 b3 5b bd c5 cf 42 0b d7 65 4c 52 +b2 52 df 32 c5 70 d4 28 e6 3e a2 + +# Seed: +77 bb d7 2b 7b 8f d2 85 02 ec f7 9f d1 c8 af 8e +bf e2 44 32 70 93 b8 24 79 5e 95 c0 b4 36 eb 41 +e5 f0 f2 ae c4 33 63 aa 2c 08 fc 33 f2 87 e6 53 +80 40 e4 28 0d ba 47 23 e5 32 92 e0 a6 7b 21 ef +77 70 79 85 b7 2b 2e ca de 28 0a 61 fa 73 d7 3d +bb 2f db 17 f7 75 f4 5f a1 75 b7 7c b1 06 7d 6f +93 a4 37 + +# Encryption: +0d 21 49 5c 49 28 c2 6a 92 c1 6a 90 7f 08 33 35 +ad e8 eb 0c 20 b0 b4 5f e0 e0 8e f3 9a e2 4e c0 +b5 05 7e 60 78 dd 7a 1b 9d 10 2c 24 81 85 57 e9 +0b 83 ff da 14 f3 cc 37 3c 84 c1 05 ce ee 71 bc +73 1a 7f 35 71 bd 7b bb a1 d4 f2 3f f4 df 0a 84 +f3 12 99 0f f7 71 ff 11 8f 05 bc fa 22 2f 11 c1 +ea 01 f6 a4 68 ca 5a 87 50 80 40 98 f8 46 a8 64 +30 ea 23 e9 f0 7e 23 48 46 1e f0 0b a6 25 34 fc +e7 + +# PKCS#1 v1.5 Encryption Example 11.3 +# ---------------------------------- + +# Message: +2d 30 7f 44 dd ff 9c 45 35 a0 6e da 01 4a 19 13 +04 fb 3f a8 e3 a2 be 88 bb 3b 7b e9 9f 94 d1 33 +9c 21 9a 51 ff 5c ad da 93 + +# Seed: +5f ab 24 2d d9 f2 92 4b 20 d3 78 a8 87 b5 de 21 +d1 95 76 9c 3b 53 71 c0 0f 4c 3f 1b 63 26 8b 01 +0c 31 f3 2b b8 7c 9a 52 29 e0 d9 30 5f 5f c8 3b +89 34 b9 98 d8 ce df 91 6f 7a 4d 72 68 fe 3b e5 +12 35 f8 be ac 80 0d 4f ff ca 6f fd db 29 da 4f +a1 c7 76 9d 51 + +# Encryption: +0f af b6 1c 37 16 c7 96 69 fc d1 64 52 46 a0 d3 +b0 75 b2 8b 73 82 20 15 a8 ca dc 88 a2 2b 7d a5 +39 43 e2 54 4d e3 96 be ee d3 b0 a9 89 ad 20 a7 +3d dc d1 91 e8 aa 5c ae b6 e9 08 8a 4a 3a e8 40 +67 f9 19 8e 92 4a 9c fe 14 50 b0 18 a6 b6 9d d2 +37 58 e9 25 1c 76 cc ea e8 40 da 2c c6 25 17 39 +e2 3b 9a 42 b6 34 46 ec a0 d6 15 99 a1 46 b7 41 +fd 43 51 1c 73 66 3a 92 3e 37 57 f1 8a 17 1c 3b +12 + +# PKCS#1 v1.5 Encryption Example 11.4 +# ---------------------------------- + +# Message: +1f 03 33 88 55 4b eb fa a0 1c + +# Seed: +9d 81 57 56 74 66 3b 3d 87 7d 4b 0a a4 fd c6 05 +47 0a bc 55 0b 53 52 72 c8 23 70 18 86 7c 50 22 +ca fe 6a 4a c8 37 37 e9 9c 6e ba fe 69 ca a7 fd +ca 70 27 c8 fb c4 37 ec 52 32 ce 2e 25 29 a0 f7 +03 e2 01 f7 e5 10 32 35 ba 65 a6 47 94 f1 90 ef +42 54 93 b6 48 ed 24 a2 19 7d 0a b0 4d 81 c7 b3 +35 a2 da fd 6b 59 c9 43 a0 9b 48 ea c3 5e 35 59 +62 91 f5 f7 + +# Encryption: +00 1b df 33 93 34 2c 38 13 ee 3b 87 07 ea f5 46 +47 ba de 4c 71 8a 4b 64 54 78 12 e0 10 c2 b7 46 +c8 8c da fd c3 16 f0 36 9a 6c 43 0a e7 e6 c5 0f +05 d5 45 c3 f7 98 de b1 d9 a5 bb 69 c5 91 39 33 +c2 d7 79 2f ae 9d 42 ad 76 49 4d c9 a3 e2 7c 21 +1d b4 ef 19 85 18 7a 6c 4d 28 1c 47 72 17 74 a7 +a1 1c 12 18 d4 dd 26 7b 57 48 58 77 aa 75 1f 6c +28 19 f8 1b 50 54 a2 8a 26 a5 3d f3 ea 34 82 b3 +40 + +# PKCS#1 v1.5 Encryption Example 11.5 +# ---------------------------------- + +# Message: +f7 1b c7 37 4b d5 9c 37 77 59 76 f3 35 24 4a 36 +84 3c 59 e7 48 9a d2 8b 1a 82 2d 2d 7d 0b 9a 6f +e9 ac 5b f4 36 82 d6 3d 63 6e f6 + +# Seed: +a1 ff 98 44 a7 3e c4 b3 be fb 1a 86 03 52 cf 9b +75 fc 66 ff 47 9a 2d ed 59 98 84 5a 79 77 3a 8c +62 06 a3 64 36 c8 80 a5 5e 18 71 18 35 45 6d 91 +45 4b 5b a1 32 07 8f 20 37 fb da 72 86 25 1b ad +d1 2d 0a 97 81 af 3f 58 97 cd 94 7b 1e 14 25 f9 +70 55 09 + +# Encryption: +09 3f b6 85 26 ce ad 01 0a 54 d1 16 cd 7d 60 35 +09 9b f1 ab ff e9 33 1d e3 64 86 f0 53 a8 02 98 +e4 ab fa b4 0d 3b 03 a3 e7 e9 25 59 73 38 f1 70 +3b 04 53 5a 9c 87 c6 58 36 f1 61 11 aa e8 89 e6 +c8 d9 0a 24 07 d4 41 a1 c2 a3 11 cb d9 46 11 a4 +2e 93 c7 3a 3d 21 48 3f ad b8 f4 e2 46 d0 89 f1 +cf d7 08 52 b4 dc 77 8a 60 d1 52 d3 fc a7 5f d6 +06 67 04 e9 33 bf 99 f5 bb 77 af c9 a9 cb 3b 8c +b5 + +# PKCS#1 v1.5 Encryption Example 11.6 +# ---------------------------------- + +# Message: +46 87 83 d4 ea c8 81 34 32 04 85 47 ce 24 1f 72 +db 1c 85 ce 4a db e3 ee 2c + +# Seed: +c6 e3 26 30 ed 90 d0 af b1 68 c0 8b 75 22 59 ef +4b 9e 81 17 62 f7 cf 4c 53 5c b4 a0 a0 4b 1d 43 +65 4e d4 fa df c7 dd bc 3a ad 03 14 07 8b 22 6c +4f 3e 97 84 45 7c 91 c7 76 8c 5c 37 b7 60 08 93 +2e 8d 04 57 85 05 73 ce 6b 41 a4 3c dd a9 70 03 +18 36 84 0e 4e 60 a3 48 7b 47 a1 85 c8 6f 8a 16 +f6 f2 21 d0 a0 + +# Encryption: +01 71 a1 2b 00 cf d1 09 67 4e 5b f7 f8 43 47 fd +a3 fe 4a 8e a2 f4 8e 0d 6b 6d 94 b4 9f d7 bd fb +26 e3 24 00 a7 12 51 ab 84 22 06 92 1d 83 72 3a +89 ea 09 93 00 25 92 0e 3e f8 a8 87 d2 bc 24 15 +a7 f1 ed 37 ba 8a 5d 03 ef 92 6a ce f6 11 90 00 +1c 5e a0 f8 cd 92 02 0c d8 96 67 e9 ea 5f 7f 2b +15 37 8a 21 0b 8a e9 14 81 90 98 da 1c be c9 c5 +43 a2 63 30 0f 99 4f b0 b4 92 85 71 40 1c 20 2b +d6 + +# PKCS#1 v1.5 Encryption Example 11.7 +# ---------------------------------- + +# Message: +af 63 1d 76 c9 7f d9 95 e4 94 aa 9b 4b d7 58 c5 +c6 72 c5 e4 15 8f 3a af 87 4b + +# Seed: +40 6e 1e 23 f9 92 bb 07 62 12 5c a4 63 bd 0f 2e +fd f1 bf cb 08 2a 8d f5 06 af 5f 72 70 c3 9f de +01 d9 ee d3 22 66 61 db 22 a9 c4 04 b7 d7 65 fa +38 4f 9a d4 f5 1b 93 69 d7 4b 0e 37 70 66 31 bc +65 36 f6 55 5e c7 fd eb d3 48 ef 3c f5 f8 a8 77 +f6 06 43 7c 27 8c b8 16 3a d3 49 38 4b aa e3 2f +31 b6 86 e0 + +# Encryption: +01 ff 8f e7 9a f3 18 d7 56 f2 84 08 3b 51 b4 3b +66 aa e8 3c 6a a9 1a 99 93 4b 4d e8 4b d5 fd 24 +fa 8d 07 c7 55 14 74 66 5e 62 36 0a 65 98 4e 67 +a4 85 6c 3d bd 2c 75 f2 46 e2 22 22 e9 f4 b9 69 +51 67 26 ed 28 7f 42 3a 67 47 82 1f bb b7 fa 17 +62 35 c8 50 a8 61 f2 99 f7 39 4c 2c 43 07 b1 02 +59 09 40 fe d1 20 6a d5 9b 9d d6 44 4e 1e 19 6e +94 73 25 22 4f fa ca 06 9e 9c df 8c 62 02 69 07 +7d + +# PKCS#1 v1.5 Encryption Example 11.8 +# ---------------------------------- + +# Message: +73 cb 53 90 82 fb 06 dc ae 3c 20 68 e9 89 e7 c0 +d8 ff f0 fb 34 0b 6d e8 0d 0b a5 d1 e0 06 4f 22 +13 92 8a 4b af 20 a8 03 48 af 3c de 9d e6 3f 88 +6d 63 e5 6a 3e 32 cd 8e + +# Seed: +28 e2 a9 7c 7e 9e 03 3b 49 aa dc ee 8f dc 07 ed +fd fd b9 50 35 4b 70 8c e5 df 84 8d 1b 51 aa 2f +4a ff 99 74 16 01 81 42 29 47 b1 33 76 4c 5a 40 +06 57 04 6a 49 36 3f fd f1 f9 3c a4 8b 3e 52 93 +7e 1f 38 fb 50 fb + +# Encryption: +0c 72 e6 95 48 c3 4e ca f2 48 b2 dc 6b b6 43 87 +f4 f3 35 0f 66 8e 59 01 35 60 80 8c 41 3f a8 35 +fd 36 0e 04 e4 74 7a 00 31 c8 a6 4a 9d 7a 07 b3 +63 fa d2 93 b7 03 a7 dc 99 0f 80 6f b9 0e 39 12 +21 a1 16 df 10 8f 54 6e ae 51 71 6b a0 45 01 ab +77 7b 0c 2a 17 71 2f 71 e4 06 27 5f 01 73 77 cf +24 88 c4 35 ef 6c 6e 7c 45 cd b9 8f 24 47 7c ed +18 0e b3 ef c8 70 3e 96 38 26 bf b3 44 f1 6e b4 +a1 + +# PKCS#1 v1.5 Encryption Example 11.9 +# ---------------------------------- + +# Message: +f2 f9 85 b8 03 12 73 cb 5f c8 9a 31 dd eb 4c 67 +a4 e4 f3 8c 09 d3 02 87 42 09 b3 9c 69 b7 1f 84 +95 88 86 8f a5 f8 + +# Seed: +c1 20 44 6f 5b dd a0 6c 63 73 8f 18 15 55 95 f6 +2b c2 65 67 28 4c 35 03 65 91 cd 5d 75 3e 4e f7 +90 0d ff 33 bf dd 3b 10 8c 10 2d 08 98 80 c7 b6 +9d 86 e9 ce 3d 68 8c da 15 6f d6 a9 92 31 05 8c +c3 18 33 96 38 09 46 e8 a9 69 a7 fc be 9e dc 95 +9a 0e 50 45 32 ba b8 ea + +# Encryption: +10 e0 bc 14 ba 16 01 26 98 cc 76 cb 82 04 5e 2b +fd bc b2 b1 18 f1 83 06 79 59 d7 13 7f d5 0f a8 +8f e4 f9 ce cf 66 31 a9 9c cc ab 76 cd b7 74 4b +ab d0 6b 2b ed fb ca 77 24 da fd 91 e6 df a8 8b +ea 2b 44 a8 cb b0 62 19 b1 5c 2a e7 68 72 fa d2 +88 e8 43 8a cd 39 5c e5 cb e2 8a 71 2b 67 f5 61 +a1 78 6d 75 34 3e d9 ad 0d 0a 5e b6 fa ed 07 b0 +6a ef 03 31 8f f1 af e4 72 db 4e e3 e2 1e c1 29 +33 + +# PKCS#1 v1.5 Encryption Example 11.10 +# ---------------------------------- + +# Message: +39 87 2c fd 6c f7 4b 4c cc 1a 70 d9 73 b3 18 99 +a6 7a ee de e5 d6 71 e0 5b d6 01 12 e6 45 12 bb +e4 3b b8 40 + +# Seed: +68 ac 3f 96 97 b7 50 75 4f a7 53 2e 41 61 c1 20 +18 e0 33 a6 02 51 c8 dc a8 38 78 16 f4 23 79 ab +97 8e 15 57 8a e2 e9 4c 17 76 48 8b 0c fd ff 18 +6f a6 d7 98 88 f8 16 9e e4 49 ea dd c8 e7 f5 a6 +58 d0 99 7a 93 4f 58 6e 31 f7 47 30 be 60 3f 1e +e6 2f a6 c0 8b 0b ff ae 6b 88 + +# Encryption: +09 b7 70 07 f1 5d 65 9e fc ca ca 66 c1 e7 d9 62 +e0 47 a1 e1 49 e5 2d cc 0e 1a dc 9e 18 3b f7 3b +5f 23 48 d3 43 28 24 1b 40 7f 61 82 2f 6d 57 e1 +ab b3 22 d3 02 f4 53 0d 2c b9 a4 1a 27 70 23 8a +1b df 87 5e dd 79 78 10 d9 04 e9 7a 4d 7c 51 51 +32 d6 ab bf 3a 4a 40 74 86 dd 00 4e a3 8a ff 8d +4e d3 82 5f e1 31 42 f1 36 fd 1d 71 3e 80 e0 cf +22 57 69 b4 19 cc a5 4c 15 6e 54 66 8b 30 6b 5f +2a + +# PKCS#1 v1.5 Encryption Example 11.11 +# ---------------------------------- + +# Message: +74 d5 6b f8 d9 c1 80 dc 09 93 71 a5 af 72 + +# Seed: +33 78 70 f0 47 9c f1 28 3a 0c 87 c9 c4 af 54 ba +8f 85 06 44 d5 9a 20 25 26 3d 2b dc 49 bf a6 63 +6e 75 18 f9 4b 6a b1 8f 85 b1 93 21 20 9b 76 9f +0c 19 75 d1 d5 ad a0 6f d2 a7 6c 82 45 0e 4e 09 +cd ad b7 83 2f fb 8a e7 dc b4 74 10 b2 87 80 4d +dd c7 49 3d 61 0a 81 39 9b 6d f6 df 5e f1 52 09 +29 84 fe 27 76 a4 f9 30 54 6b e1 dc 18 31 3c 14 + +# Encryption: +07 61 eb aa d8 ff 1c 3d be 71 0f 60 e3 be 9f 28 +9f b2 7a 6b 53 77 75 5b 71 fb 38 4c 5f ac b1 60 +3c 95 3e 1e 2c a1 1e 78 43 25 ae 42 f3 21 ae 5c +58 64 8c 84 f5 24 df 9d e9 f9 3f b4 b0 c2 e0 97 +97 ff 2d 11 40 70 73 b9 5a 78 6d f5 1a 43 f7 99 +82 d8 6c 49 fb 9e 50 14 b1 b7 68 76 0a 51 30 26 +6d 06 99 30 6a 90 4e d2 df e2 01 38 d5 31 c5 dc +4b bf 4d cc f1 02 49 a6 e2 b3 55 f7 cc b3 26 a4 +8a + +# PKCS#1 v1.5 Encryption Example 11.12 +# ---------------------------------- + +# Message: +61 10 63 b5 da 12 3c e2 12 96 17 df 38 59 95 57 +b9 5d 1b 05 e6 b6 6b cd 49 af e9 83 1a 04 21 a5 +be 4e 48 + +# Seed: +10 f9 df 30 ec 97 77 fc ab 5a 92 4d ed 36 fd fd +6e 1f 38 14 49 ad 99 d2 0a ea 0e 39 72 ea 60 4e +a2 27 50 d0 60 1d 10 a3 77 da d1 a9 4f 9b 02 73 +40 94 81 23 82 73 98 bb 22 b1 44 5f 71 c5 05 c6 +23 aa f5 16 cd 9f b3 e9 77 f7 78 cf dd 3a 5d 28 +c2 29 9e 4b 2a bd 9f 98 c4 35 5a + +# Encryption: +07 f2 d5 8b c4 16 39 94 d7 6f 49 1e dd 69 74 3c +45 dd a0 c3 8c cb 07 69 de 9c f9 f4 fd 00 55 d3 +0a 0c f0 02 80 0d 76 ed 8c 12 cb d3 6a f0 51 a9 +d7 33 7b 29 bc 77 4d c3 c4 01 2b f5 c2 8a ea d8 +c3 e0 36 aa 41 39 8a 8b 0f e9 91 c0 bf 66 b5 34 +1c 99 d9 37 7d 94 70 4a d4 90 a9 f8 74 6f c5 ce +f7 26 e1 96 f3 41 f9 3a 1f 1e ae 2c 13 e0 0c fd +22 06 2f 8e b3 da 9d af b9 5a 1e 7b 81 b1 fd b6 +56 + +# PKCS#1 v1.5 Encryption Example 11.13 +# ---------------------------------- + +# Message: +80 76 4f 78 5f d4 17 6e 16 41 e1 29 a3 5a 9b 31 +b3 a8 9a 75 67 ad 6c 1f 0d 65 ec 8a f9 5f c1 6e +15 28 14 09 + +# Seed: +20 36 d0 98 a6 e9 35 f9 a4 11 20 1d 2b cb 62 9f +79 0a 94 db 2e c6 98 67 43 3b 17 61 d7 c6 95 4b +e9 1a 9f c7 19 19 0e 10 86 13 cd 58 4c bb 97 76 +87 04 69 24 bc a6 b2 fe 1a 54 bf 76 ac f7 7b 36 +8c 39 65 0f 6d 0a 49 8d bd ed ae 3f 4c 21 04 0a +8a ed 63 4d e4 ed 8a f1 34 6e + +# Encryption: +04 9c 61 44 4e 92 47 72 f9 4a 79 5c cd 99 eb 2f +e4 30 99 7b 91 b4 2d e6 16 36 29 ab 98 d2 5a 71 +e7 f9 68 86 a5 7e 97 9d 9c 94 c9 62 20 9c 1f 71 +2c 70 57 1a 81 f3 77 ea f7 4e 80 e7 07 22 e1 be +3d 13 37 c5 04 5f 79 7b d5 7d f2 f5 ae 5e f3 3a +e5 79 e9 3b 38 fb 25 0d f0 c2 bc 59 b3 3a 74 86 +7b 8f 3d fe 5b a7 85 d7 28 b8 9d 96 b3 00 2b c0 +05 4d b5 bb 0d 84 fd a4 5d b4 a1 f2 62 8a b1 12 +30 + +# PKCS#1 v1.5 Encryption Example 11.14 +# ---------------------------------- + +# Message: +0a bc 2b c5 fc d0 40 18 9f 84 22 f1 ca 04 50 21 +da 95 + +# Seed: +e4 73 2e 49 90 69 9f d7 47 40 c8 52 ae 8d 4d 70 +7f bd 79 46 0f 88 74 09 84 ae 53 ff b9 fc 39 62 +68 3e ad 0d 14 04 f5 31 51 d1 ae e8 0f cd 6a 1f +f6 5f c8 8e f0 8f d7 6d 9f dc a8 f9 e3 ac 7d 8d +82 b8 2e ce 78 9c 66 c5 40 22 80 b3 e5 68 10 1c +e2 a2 a7 b2 b2 f1 e9 65 19 cf b4 1e 60 49 3d 76 +8e b5 b9 6c cc 49 bb 0f 6e c7 11 fd + +# Encryption: +03 d8 ae 60 4f 92 95 31 73 c7 7a 01 ff a0 90 aa +0e 37 a3 8a 47 c9 72 19 c0 b9 f8 64 d3 48 74 6a +f7 f4 a6 32 11 29 c6 04 6a 99 4c ed 1c cf 33 24 +da 93 71 53 88 8d d6 c6 70 19 a7 ca a7 65 5a 36 +42 83 8e df a0 e2 ed 8d c2 5c 14 bf f8 bf f5 65 +c7 18 f8 b6 c9 20 56 c9 bb e8 d9 30 83 70 c7 cd +75 a0 4e 11 b6 e2 5a a6 c3 c2 cd dd 17 2a 4b 6a +ee f0 4f b8 35 b6 86 37 cf 0c a0 b9 a9 11 b8 b8 +74 + +# PKCS#1 v1.5 Encryption Example 11.15 +# ---------------------------------- + +# Message: +8f 98 35 ef b6 9c ca 8c 07 bf ef 4d 8f 53 5d 0c +bd a5 36 7b bd 41 08 0a + +# Seed: +32 d4 be 07 e6 c7 fb 81 d5 20 8c 25 01 c5 df 7c +56 d1 98 6d c6 d6 31 10 ad 21 d8 1e 57 ce 11 3f +3d bb fe be 0f 80 c0 16 b7 19 e9 d5 c3 d9 a3 bb +bb 2f 35 be 95 d4 56 22 2b 51 c3 d6 5b 38 8e 7a +da f6 b9 ce ae 1f d4 6a 6e 05 ca 1b b1 99 c2 7b +ac dc 8b 5f d1 4f 03 51 ae b3 fd d6 dc 1d 93 f3 +b5 31 56 ef a3 c6 + +# Encryption: +0e 47 ad 4d 92 d1 9a 1e bc ac bf 87 5d 80 19 27 +d4 fe 5a fa f6 6e d8 01 5c 55 9b 56 6a 9f 3c bf +0a be 8a 76 fe 73 24 f6 28 c2 e4 f3 45 84 a5 0f +f7 7e 82 2a 54 11 8e fa 9b ae 9d 0f a5 02 94 c6 +18 0b af 3a 8b 0c 7e 45 3a 74 37 ab 1a 19 cc 00 +30 7a 8c 6a ed 95 c3 15 b2 4b 47 90 07 24 56 c9 +44 60 99 5d bb 1f e5 a1 2b 4c f4 45 42 96 f7 40 +02 83 ce fd ce 6b 00 cc 80 49 dd 5d d8 cb 2a f3 +6f + +# PKCS#1 v1.5 Encryption Example 11.16 +# ---------------------------------- + +# Message: +6d fb d9 3b 00 78 d4 9a e4 fe 1e 24 cc a9 7d 0a +9a ff d7 be e0 62 ae d2 9d ef 0b 1c 0b 3a ef ad +81 1d 6e 7a ce 8b 49 d7 24 2a 9f e6 e2 3c 22 + +# Seed: +31 9f 9c da 2c 93 38 8e be 1a 50 e7 6c 93 97 55 +9d ca f1 4f e1 03 52 aa 51 1d c5 ba a6 4d c1 52 +fc c7 9c bb 23 d4 e6 9b 12 b9 f2 7a 79 09 15 98 +87 bb 04 12 9a d6 35 16 81 33 86 37 4f 31 89 2d +4c dc 4f e6 39 69 b5 bf dd c6 67 f9 46 89 7d + +# Encryption: +01 c5 ce 83 6b e2 20 8a 3d 81 4e 7e 60 c2 76 74 +ac b7 cd 3e 31 c0 24 d9 d3 8f c2 29 53 aa fe 73 +af 52 40 43 4d cf 54 a3 88 99 2e ac 36 ec 84 64 +d9 a0 42 ac 58 d1 8a 70 39 8b 8a 77 3e 66 69 bb +3d 76 ee ac df 1f d1 52 47 40 99 bf a6 62 a4 81 +db ab 4c a4 67 14 95 87 45 e2 b7 83 2a 59 cc b0 +05 36 49 b7 e0 95 07 43 33 3f 5f cd 6f 65 19 7d +dc b4 e1 bc 12 a6 6e 8e 92 a8 65 9f ae e5 71 31 +e2 + +# PKCS#1 v1.5 Encryption Example 11.17 +# ---------------------------------- + +# Message: +e5 87 9f fc e0 b6 29 b8 85 7c 19 5c f5 d0 9f 7b +93 bf f1 f7 a9 f2 d8 a4 5a 56 3b bb e9 e6 2d + +# Seed: +ba ce 2c ea 0b fe c2 5a 2d 34 d7 29 92 c2 b8 ea +0a ea 17 b7 a3 a8 be d6 0d 1b b5 10 13 34 7b 2d +03 6a 75 a4 ec 3e b2 c1 78 8d 44 a9 e1 c5 c8 8d +04 1e 82 af 87 81 55 dd c7 d8 1b 3e 27 cd dd 20 +40 9d bd da 4a 64 bf 83 11 a7 b7 eb 77 29 93 12 +66 1a 6e 37 df 35 02 f8 6a 22 49 2b ef ac f4 + +# Encryption: +01 e4 fa eb ca b8 9d 7b aa 3e 03 93 f7 16 84 b0 +ae 53 df 8e b9 87 3e 65 a7 16 ec 2f 41 74 1f 8b +78 16 d2 e1 97 d9 76 fd 53 a8 ee 7f 92 4b f4 bf +d4 10 42 e1 64 45 e9 06 0b 55 a0 b6 dc 16 aa f3 +06 44 91 d1 89 28 22 39 50 39 33 28 c1 47 db d0 +35 31 ec 01 2d 8c 52 75 02 e7 eb 3d ca 50 9b 7d +e1 69 95 92 46 07 c8 b2 8a 2b da 9b cb 2c 77 81 +46 1c 76 66 3b 88 7b 96 43 e2 31 7f 0e a1 d1 bb +14 + +# PKCS#1 v1.5 Encryption Example 11.18 +# ---------------------------------- + +# Message: +0a 2e 24 13 0e 8a 9d 28 df cb 9d f9 76 5f 46 83 +e9 da 78 42 5a 28 19 98 06 a9 3b 32 2e fa 88 49 +3a c3 72 52 c2 9a 26 4f 3e 85 ae 56 53 8e 80 8d +c5 56 42 a4 88 5f 05 46 40 f6 9c 89 81 fe + +# Seed: +20 43 1e f3 1f ce 19 93 9d a5 45 a0 85 30 11 2d +b0 fa 07 13 8d d8 6d b1 cc 65 e2 b0 3f c2 be 60 +7c 3e 60 38 eb b7 89 17 55 b2 31 29 fb 96 9a 7f +e1 06 10 f2 eb c3 f0 77 b2 c8 f4 60 1e 09 ab 4c + +# Encryption: +0c 14 b7 d3 2d 3d 4c e2 b0 8e e4 4f 51 6a ee 29 +90 b6 30 52 40 b2 5d 23 34 aa 31 75 2a ef 28 02 +16 39 f7 6a 4c 47 19 56 9b 30 05 2d 4b d0 8b 3a +07 f2 3b e6 86 23 7e 48 1e 67 bf 3f 5a 01 ad d7 +56 da 77 2c 7d c1 3d 32 29 8b 9b bc 3d 33 e6 df +82 d8 5c 08 9d 34 76 00 49 7a 8b 8e a4 de 68 ab +b9 0e 5c 6a eb 26 9a 97 be 42 6c ef ac de bb cc +0c 1f 2c 40 9b bc 7c 72 d9 0b db 42 6b 13 cc c1 +9a + +# PKCS#1 v1.5 Encryption Example 11.19 +# ---------------------------------- + +# Message: +7e fc 62 7b a5 fa 28 25 aa e0 ca 94 03 0e 70 47 +08 d3 5f 92 23 98 26 b4 2e 2d 4d bb e4 02 ab 7d +19 6a 7f 54 88 0c f2 c5 a4 d0 fc e5 3a 20 a3 2b +68 30 e6 2d cd 00 db cb f3 3b 5c 0c 70 44 01 + +# Seed: +f0 49 79 19 c1 42 f3 a9 8e f5 5b cd 59 88 23 4f +dc 8a eb f7 36 d4 7a f9 70 90 a7 a9 dd e0 a7 35 +09 f9 cd 41 36 26 bb 8b a7 67 c9 d6 38 49 1c 28 +6e 67 bf 22 d6 70 d5 6b 24 c1 5b ad 70 35 1e + +# Encryption: +01 db ce 3b 3f 84 b2 da 06 b1 67 e2 06 64 9d 42 +4a 42 b8 e9 ea 54 53 a1 6b 5f c6 c2 e9 cb 17 ed +a1 ef fe 4e 78 36 a5 e5 8f 99 e5 31 53 0b 40 17 +1e 4b 51 fc 0b 92 de 30 31 30 09 36 d2 59 5e 39 +10 09 e2 e5 3c 32 f7 59 60 4a 6d ba d9 c9 70 90 +0f a6 e4 1a 35 08 3f 78 7b 9b f3 be bc ea a1 a7 +71 84 1b 5e 6e 4c 8b 50 96 29 00 7b 46 7e 3c ec +8a 1d 03 23 c3 c5 db c3 4d 8d 41 25 a3 98 c9 d5 +3d + +# PKCS#1 v1.5 Encryption Example 11.20 +# ---------------------------------- + +# Message: +59 3d 3f cd 05 ac ee 30 29 81 5e 1e 76 a8 90 + +# Seed: +12 35 ee 3e 7a 9d f5 96 7f e9 8d 97 10 ff dd 5f +7e b2 2d c0 71 47 af 43 6f e2 0a a5 26 bf 0b 94 +19 0c ab b5 21 3d e9 8a 23 f5 ef 27 50 22 a2 f7 +3e 60 e9 ef e2 c0 34 c5 5c eb 26 aa 80 6c de d6 +73 9d db 2c bd 3e c3 b5 55 20 4a 79 84 65 c3 7c +67 57 19 56 86 a3 ea 3c 56 57 c3 60 a0 15 8d 99 +2d 4f eb fa 04 29 ee b7 c9 2a 46 84 34 c5 b7 + +# Encryption: +0f 69 98 81 a1 52 46 18 bc 25 d4 e5 14 e2 07 30 +68 ea 7d 35 38 4b af d4 6f c2 82 e1 d8 55 11 9e +e9 69 f2 11 c7 18 4a 07 03 06 47 fc 40 99 0e cf +2e a4 05 22 86 5d 91 77 8a 62 7e ca 8e 50 c2 bb +97 60 b0 45 da af 12 77 a4 fa 98 35 76 ca 8c fa +d7 60 83 29 c1 88 15 88 01 7d 63 72 2b 70 e9 8b +e5 24 e0 03 39 95 98 25 73 d3 38 70 78 c8 b7 c1 +c5 f9 ae f2 64 a0 48 46 84 b3 42 66 43 73 7d 34 +bb + +# ============================================= + +# Example 12: A 1030-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +26 1f e0 28 44 59 c2 fa 6f 05 54 6b ed 58 5e 1e +e0 a1 30 b7 1c 2b 8a 6f bb 3b dc 75 78 7b 26 55 +d0 ed 4e 32 5b 54 c7 b3 71 a6 fc f2 b6 78 82 77 +a5 0d 47 05 ba 23 c5 96 28 5d a7 e3 c9 30 4a 41 +e7 cc 48 8b 44 92 2f 7b e2 b4 7c 16 31 9e 33 74 +51 17 3d 40 b1 ea 48 1d 1a 9c 11 29 b1 fe b7 d0 +9f 67 49 7a eb 98 94 8f 1a bf 3b 77 86 bd 3b 87 +04 71 87 c8 f3 70 15 68 2b 3f 2d e5 0e 07 8e 8d +0f + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +26 1f e0 28 44 59 c2 fa 6f 05 54 6b ed 58 5e 1e +e0 a1 30 b7 1c 2b 8a 6f bb 3b dc 75 78 7b 26 55 +d0 ed 4e 32 5b 54 c7 b3 71 a6 fc f2 b6 78 82 77 +a5 0d 47 05 ba 23 c5 96 28 5d a7 e3 c9 30 4a 41 +e7 cc 48 8b 44 92 2f 7b e2 b4 7c 16 31 9e 33 74 +51 17 3d 40 b1 ea 48 1d 1a 9c 11 29 b1 fe b7 d0 +9f 67 49 7a eb 98 94 8f 1a bf 3b 77 86 bd 3b 87 +04 71 87 c8 f3 70 15 68 2b 3f 2d e5 0e 07 8e 8d +0f + +# Public exponent: +01 00 01 + +# Exponent: +05 df 76 83 72 cc 0a 64 d3 c2 14 18 30 24 23 13 +9f 47 95 73 e5 0b 5c 09 b6 e3 be 23 fb c9 aa 1a +76 d3 27 99 a0 47 76 1f fc 21 07 94 48 17 01 04 +cc a5 e2 a1 4c e4 57 d0 0d 80 7d 42 c7 6a 55 f6 +16 87 4b a7 f7 ea a1 ce 63 cb f1 32 de b0 81 aa +d2 fd 80 d1 24 c4 da 86 ec 6c 02 0e 8c a8 2d cd +cd 35 54 e6 9b b1 98 72 26 2a 50 31 ab 5d b7 cc +8c 92 59 a1 46 d5 8b 1d b9 4c c7 e7 56 25 3d 5a +a1 + +# Prime 1: +06 77 25 ab 55 34 18 e1 eb 8a 41 f4 fd 92 d2 80 +b6 9f 85 b0 8c b4 02 f0 1a a4 96 92 c7 20 9b 36 +42 98 ee f4 e3 3d c4 22 bb a3 35 03 d1 1a 12 7d +d2 86 43 f7 e7 75 58 97 e2 eb 96 c4 dd bb 91 12 +f1 + +# Prime 2: +05 e5 8c eb d4 7d 87 b1 e7 8d a2 fe ee 6d c5 f9 +bf a2 20 c3 55 e8 20 c8 fb aa 88 46 df 11 00 36 +2c d1 69 1f 5c bf 5c 78 68 c4 72 d0 28 2a be 01 +03 16 1f 4d 8c 62 af f3 5b b1 fb 7c c6 99 d9 9f +ff + +# Prime exponent 1: +01 6c c9 14 95 d6 c1 95 29 40 73 80 f7 52 20 aa +d5 95 1a f5 ea 4c d2 48 f0 d6 4d 89 53 f1 cf c3 +89 b2 03 18 5d ed 03 09 54 a9 87 c9 ab 90 3f 7b +13 a7 1b db cb 5b 85 87 14 30 30 2e 7b 60 17 7d +41 + +# Prime exponent 2: +f9 cc 89 15 ff b3 dd c7 c0 93 71 76 49 2a 12 bb +18 7c 2d 76 e0 d3 d4 0e 79 58 d5 c9 82 09 b3 ed +54 b5 fd 9f 9e 77 11 e1 dc 68 57 73 de 26 d5 0a +0a b6 21 62 12 ce a5 09 ce 79 1c 5b cd 07 cb 47 + +# Coefficient: +05 fe 93 3b 87 3f 1d 68 f6 be 2d 4d 5a a2 2d 96 +8f 2b 7a f5 41 a2 dc d6 4e 09 c0 30 b1 50 35 8a +98 02 ae 86 59 95 d7 6a 50 03 7d 19 8d 7e 70 4d +26 84 7a da 8a e3 d3 85 c2 96 5f b1 7f cf 15 2f +77 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# ---------------------------------- + +# PKCS#1 v1.5 Encryption Example 12.1 +# Message: +7d e6 9c d9 22 8b bc fb 9a 8c a8 c6 c3 ef af 05 +6f e4 a7 f4 + +# Seed: +33 d6 2c d6 67 82 3f bf 13 d5 92 ae 4d 02 a2 37 +0d 1d 99 db 06 c7 25 42 5e 0d 12 fc b4 83 4e f9 +e5 49 9d 60 7e 8a ae fe ba 81 96 49 fb 3d 61 c7 +05 f5 e9 a3 a2 f8 96 27 61 89 a3 20 0d 2f af f7 +76 79 e0 56 34 9a 5b 9b 7b 44 49 b6 75 cd 48 b6 +98 09 32 c2 cf c4 6b f8 9a 77 34 f6 8d d9 f4 fe +77 e1 d9 cf 1f 31 b2 1c 4c 61 + +# Encryption: +04 ca ef fc d5 1c 3f c9 23 63 46 77 4d a0 cf a7 +7e 9e 64 65 f6 43 7f f4 6d 9f a4 58 b3 62 34 12 +c3 10 30 09 fb fe 20 31 96 df 72 96 26 e0 ee 3a +fb 6b 10 a5 ac d7 2e 84 28 1d 9d 9b cb a3 e0 ef +77 dd 84 f3 db 19 2d 31 b5 b6 66 f7 6c 93 81 06 +81 37 3b aa 58 e6 da db 01 fa 5c 65 ec 89 fa 51 +cc 24 74 61 1b 9a 7c b0 0e 86 2f d3 d4 9b 1c d3 +1a fc 2d b4 49 e0 9d ae 2d 0a 7d 4d f0 bc 32 0b +5a + +# PKCS#1 v1.5 Encryption Example 12.2 +# ---------------------------------- + +# Message: +97 ee a8 56 a9 bd bc 71 4e b3 ac 22 f6 eb 32 71 +96 69 c4 2f 94 30 c5 89 50 c6 4c 0d ab ff 3a 9e +20 43 41 6c 67 ca aa ab 7c 68 cc b3 ca 99 a3 + +# Seed: +9f 14 12 61 ce c4 f2 c5 2f 96 91 25 a3 6f 14 10 +27 08 82 50 d3 6b 17 42 1c d0 96 14 76 19 06 46 +8a fa b7 62 2c 0d 02 19 36 91 74 47 91 e0 d3 5b +6b c9 f3 37 7e 10 b2 85 6c 8e d9 19 9c 89 f4 a4 +16 13 d3 c4 0c ca 37 3a 7c c6 3c 52 60 fe 5a + +# Encryption: +0d 26 a0 5d e9 3b 70 7b 85 40 fd c1 98 89 d2 d1 +e7 93 71 57 d3 2d 30 3c 52 8d e3 5e 55 3f 94 20 +28 74 4a f6 a0 40 2e ca 0f cf 5a 85 26 1a d4 75 +d8 71 0c c9 f8 b1 1b a2 c6 da f1 d6 72 69 0c 68 +ed 11 e0 35 e9 c6 60 ec e1 d8 0c da b8 00 ea d3 +c6 e0 78 61 7a 1b 0d 27 3d ed d8 d6 57 49 16 6b +d0 77 74 fb 4c 14 86 aa 8a 0a df 59 5d bc 3d 10 +ff ae f1 83 84 98 a6 75 55 c7 7b 6e d9 83 d5 b9 +de + +# PKCS#1 v1.5 Encryption Example 12.3 +# ---------------------------------- + +# Message: +8e 3e 77 2f 39 + +# Seed: +9e b7 31 fa 6d 8d 5b 75 81 f8 fa d2 c8 22 5b c9 +68 34 af 61 db 3d 40 9d d5 63 04 ae 23 ea 62 69 +63 a4 d8 04 40 c2 4e 43 1e 41 97 60 90 3a c4 4b +fe 41 a7 50 81 a5 46 2b ae 65 47 c0 e7 a0 6e 91 +60 df 9c 01 fa 6c 53 54 c8 33 18 db 65 6d ee 0a +43 77 87 fa 46 39 4e 55 2e a5 33 15 59 b4 01 7b +b6 a0 e1 d6 fc 8a 65 b4 5d a0 c4 5d 88 95 48 61 +cd 6e 7a 41 7e 03 7b 1b 05 + +# Encryption: +24 4a 86 34 51 9a f4 9f 56 9b 69 86 ab 47 79 64 +a6 b2 92 0d 84 3a 1d 97 ef d7 fe f8 3e 81 ba da +4c 4b 56 29 61 ef 4e 1f c3 33 46 4b 92 6b d7 4b +07 ad 50 c6 5b 68 16 83 d3 89 fe 41 d6 d2 13 b6 +46 9f 18 2b 14 b4 62 d7 2c 1c e3 92 8c a8 06 d9 +66 b5 2d 42 d0 bf d6 0c 9d 04 91 4d 50 83 7c da +e0 9b 33 0e 37 27 44 dc e1 7f 18 e9 4d 71 1c 8b +58 ea 44 9f 14 49 d3 69 fa ef 51 46 83 d3 01 60 +79 + +# PKCS#1 v1.5 Encryption Example 12.4 +# ---------------------------------- + +# Message: +dc fa e7 71 8c 24 7c 40 f9 a2 a3 c3 53 5c 50 92 +80 c8 73 c3 + +# Seed: +b9 3b be a6 c1 85 3f 15 3b 5e 01 e7 e4 e5 d0 c6 +3d 9d fb 24 5f c6 cf 64 04 3d 7a 92 20 b0 b8 1a +c2 af 65 6b 99 71 4b a4 30 e0 a3 96 95 d2 5f f2 +69 b0 b9 b8 65 fc 4d 4e ee 5e 07 a5 b5 be 35 43 +82 aa a4 14 bc 62 08 54 5c 86 ce 02 38 8c 07 b3 +76 fb 02 98 c3 7d 1a c3 9e a1 89 b0 ad f7 80 f6 +e8 30 bc e9 17 b5 0a db 7a 31 + +# Encryption: +0c 41 20 52 d4 ef 4a b5 1b 2f 62 37 05 f0 7f 41 +fa d6 4d af fd ba 62 44 ef d4 7f 51 9d e2 e7 1a +01 a6 c5 7d 1f 28 b6 bf 7b 5c 8d bb 9f e7 b1 49 +b0 eb aa 53 59 61 99 37 6d f4 90 32 3d 25 c2 17 +bc 71 be 37 f1 81 03 5c f4 57 eb 5c 06 d6 a3 de +d3 d6 6d 5b 35 f0 61 81 bf 94 d0 ec 13 ec 44 7c +70 82 33 49 1c 55 4f 9e 99 1f 6b cb 8b 78 d3 3c +9c 36 95 5b 8d ce 51 79 ff 8b c5 92 44 f6 67 90 +87 + +# PKCS#1 v1.5 Encryption Example 12.5 +# ---------------------------------- + +# Message: +d7 1d d8 7a 13 99 1a 0d a2 c7 4a 58 b0 48 56 34 +b3 e0 4f ec 9e 3f 1c f2 60 4a 93 be d7 96 96 fa +63 78 eb 1b a0 e5 d2 04 70 a4 + +# Seed: +09 90 59 92 58 e9 7a 2e bf be 10 97 72 25 c4 16 +76 2e 95 d2 55 3a 80 1f 72 6c c2 49 bc df 32 21 +32 58 57 19 fc 12 39 9a cd 72 54 ae 77 da 34 3f +e2 a9 a3 ac b1 1c 14 e2 14 e2 d8 5a 76 70 8c 3e +72 17 3d a5 d9 90 58 e0 c8 70 9e df 28 c3 69 38 +76 9f 1f 22 + +# Encryption: +0f f9 cc e7 b6 9d 7f ca 48 d7 c4 f6 cc ff 24 8c +3d b8 8b f1 b7 85 2c d9 d8 52 5c 3b 41 e4 4a 9b +54 0f 20 8f fb b8 c8 5b fa 89 0a c0 2e 99 49 59 +d6 b0 7f 64 81 40 78 55 6f 8e c6 0d b3 57 ac ea +f8 39 11 5f ad 41 f8 91 8d 69 c2 1a 3a ff ef 6e +b1 4a 5d 2c d0 64 5c d7 06 b5 81 43 39 4a 27 35 +36 82 e3 ba a1 98 00 2e 16 80 f2 8f 34 be 08 9a +57 84 ac e5 ca 6b 11 08 99 df b9 58 2f 2e 4b 2a +40 + +# PKCS#1 v1.5 Encryption Example 12.6 +# ---------------------------------- + +# Message: +5e 4b 15 8f 8d cb cd d7 e3 08 38 5b 40 19 0f 5d +ef 8c f3 30 5f c4 9d e6 3c 9e 35 b4 02 36 ae e1 +f4 56 20 5a 52 67 a2 aa 7d 88 cb 2c 11 af 7f 28 +99 d0 1d a1 b2 c7 46 6f fe f7 + +# Seed: +a5 22 f9 80 8d 9c 01 d8 ff 79 77 5f 7b 22 09 8f +c5 fe 32 54 e1 b0 4e b1 cb 85 0e 10 e2 c5 06 5e +23 27 4d c0 a0 55 87 43 6d a3 75 59 33 5f e7 09 +3f a5 e7 a2 a9 c9 a4 dc af 23 51 79 d0 e9 8f a3 +3e 34 b6 16 + +# Encryption: +1c 0e 86 a6 36 6b eb 1e 12 d6 bc fa 6a d4 94 06 +c8 b7 e4 8d 1d 5b e4 5c bd 83 19 49 87 49 6f aa +3e 21 92 7e c6 62 f5 02 ac 3f 91 a4 b4 b9 1d 16 +0c 19 86 a5 ed 09 27 66 88 3b 85 55 e3 c9 31 4b +44 ba 33 83 db 28 74 23 af 91 b4 13 91 8c 08 02 +c7 77 8e 46 c2 96 dc 9f 04 cd b8 b0 6a dc 7c 53 +d8 59 f4 42 cc bd 5f fa b5 af 75 2b 97 9b f5 23 +a4 0a 1d 08 d7 60 63 ff b3 d5 cf c8 2f 15 eb d6 +d4 + +# PKCS#1 v1.5 Encryption Example 12.7 +# ---------------------------------- + +# Message: +35 9b a5 07 56 a8 03 30 40 9d 3f 23 6a 34 0b 90 +f4 2f 73 2a 87 71 1f e2 23 52 d4 c8 25 0d 45 47 +5e 32 b9 58 83 e1 60 97 55 a1 3c df c1 bf 39 4c +5c 67 36 9e ca 1f 9a 33 e8 ba + +# Seed: +f9 eb dd ac 9d e1 70 9a 06 bf 6b bd df 58 94 e2 +3b 96 2b a0 c0 64 bf cd 7c c5 76 60 3b 0a 1a 1f +f3 5d 64 5e e8 7a c6 f8 21 a6 a1 51 e6 bb b0 5b +f3 e0 5c d9 a6 e2 cd 9c 6c f5 53 bf b0 7b d2 fd +a0 40 df b6 + +# Encryption: +08 33 60 e6 49 05 9d 00 65 8d ba 21 f2 df 28 a2 +76 4c 45 89 f7 a7 7d 5a f9 95 79 a8 ab 44 80 c8 +26 a7 7c 2f b7 95 4f 4f 31 fe 1d 9e b1 bf 40 e8 +09 57 7f 39 30 1a d3 ab 95 b3 81 6c 90 ec 3f 1c +d6 29 c4 39 61 74 be d9 fe 1e 0f 47 68 23 e5 3b +41 d1 35 b4 9a 02 b0 0e ff c7 61 ec 90 94 23 af +15 85 52 37 b7 7e e0 7d f2 5a b4 e8 58 46 7d 4c +cf e8 08 43 24 1b bf 88 eb 4f 85 3e f4 b4 3b a3 +ac + +# PKCS#1 v1.5 Encryption Example 12.8 +# ---------------------------------- + +# Message: +a9 f3 9f 8b a0 64 66 25 0c 26 5d f0 ca 46 57 0a +16 01 12 cf 38 fd 74 59 99 + +# Seed: +88 b3 c2 8b d3 99 9a 86 0b 8d e7 75 93 5b 8e d7 +8f a2 f2 7c 26 8b 24 3a 02 45 af 86 72 25 47 19 +f2 3a 4b 7f ed c0 0d 54 e1 2e 9d 70 1f 64 69 94 +24 b6 b8 7d 14 d9 67 6e fa 95 9b e2 1a 04 b6 43 +5d 25 10 03 dd 15 3d 7d 08 ff 28 d9 3a 93 20 dc +1b bc 3d b3 97 a5 48 94 f2 05 79 f9 3e 4e ad 65 +c3 1a 40 7e b4 + +# Encryption: +19 83 96 50 b9 25 f1 f9 6d 61 1e 4d bb 91 49 93 +54 5c 67 39 0c 32 93 5f bf 82 25 9d ad 10 f2 37 +30 eb 48 f3 42 00 46 5a 20 38 72 77 e2 b9 61 e0 +83 18 d2 07 74 47 c9 10 92 71 e4 de d8 ff 3d c4 +f3 79 ee e4 55 ae 96 08 1a 1a e2 4b 96 ca 73 0a +62 f7 ac c5 a5 ea 52 28 e3 a4 8e a6 74 1c b3 0e +82 9d 55 09 cc c6 c2 87 c7 29 1f 3a 1d 89 d6 26 +bc 98 15 77 de 52 a1 1f 12 ae 21 43 d3 b0 b5 2f +86 + +# PKCS#1 v1.5 Encryption Example 12.9 +# ---------------------------------- + +# Message: +68 + +# Seed: +53 8b 09 5e 4f 2a d6 77 30 68 74 21 91 52 42 25 +1d 07 f6 61 ed ac 7f e7 9e 31 d6 c3 45 af f5 9d +f3 88 c7 18 2f ff 0c 04 27 b5 99 35 c6 91 da b8 +bc 42 be 47 d7 69 11 88 0d 91 7b 86 27 18 b4 c1 +c1 88 8d 42 20 b9 f8 23 1a cd f1 2d 9b 85 18 6b +e0 95 0c 1a ff 84 cd 0f e3 65 86 a5 0e 7e 04 b1 +72 ca 9c 85 9e 2d ed 6b 8e a5 79 dd 5e 6e ee 77 +2c ca a6 b4 a5 d8 ab 17 31 a8 35 d6 a8 + +# Encryption: +1e 86 8a db 0e 65 32 80 60 4e 8d 3b c4 d9 69 84 +a2 0a a0 9d 48 0b 4d ff ac 62 ba 78 cb b7 ee d0 +64 5a 6d 94 d9 d2 f2 d1 e9 17 c1 46 b4 1f aa 3d +1d 2c 19 01 05 36 8f b4 84 06 a1 d2 42 6a f3 dc +c8 5b d0 2d 5c 26 c8 97 cc b2 2e 57 59 12 64 1a +18 8e f4 ac 47 a0 a9 fe 9a a2 70 6d 8e 10 61 f5 +d9 30 63 f4 90 17 00 3b 23 09 ca 7d 8d 36 70 3b +fd da 3f 7f 43 df 15 8a 15 bb 22 13 9a ae 15 10 +77 + +# PKCS#1 v1.5 Encryption Example 12.10 +# ---------------------------------- + +# Message: +35 65 87 e6 c6 c0 b4 6c 24 45 e0 18 63 52 76 ab +84 5f d1 07 6d 10 7f + +# Seed: +e5 d3 3e 4d 93 c7 08 44 ee 4a 01 65 56 24 2d 08 +e8 e6 2f 1a 7f 79 47 79 e2 23 ee 9d fb 23 1c 3a +52 0f 29 7e 50 73 e4 f9 2f 53 5c f1 44 55 7f 94 +ee 1e 1e 5c c6 bf 4c 0c 0c 8e 5e d4 0d 06 63 56 +06 f7 54 cc 2d d8 3f e0 2c 57 6c cd 2b 83 5f d0 +f5 3a 99 08 3f 4d 15 bf e9 26 88 99 ef 09 ff 5f +2f 3c ec 9f 9b 8a 7e + +# Encryption: +15 d3 64 a4 49 9b 30 a5 f7 8b 6d 7d 4f 66 7a 1f +76 d7 15 15 8f 28 01 19 b0 55 e1 f2 66 3f c7 96 +e3 3c 0e b6 4e 34 a8 da da 5c 81 75 42 57 a8 bd +f0 ed 81 15 f6 07 b7 c9 cc a4 81 f7 45 20 b6 d9 +ac 98 f5 e7 2c 2b af 3c bb 6b d9 ba ea 5d 75 86 +0c bd ae 34 03 fd 5c 37 96 4a ae 64 36 6a b0 9b +c9 c6 72 76 95 14 48 19 3b b4 b1 af a2 70 79 c3 +41 70 a2 69 56 51 0d 44 27 64 22 99 08 42 0f e8 +0a + +# PKCS#1 v1.5 Encryption Example 12.11 +# ---------------------------------- + +# Message: +e1 53 27 6a 68 79 67 8f ee 19 89 48 28 d6 26 2e +a3 9a d0 54 c8 9e dc b2 3f 72 dc da 1b 00 73 c2 +87 62 02 18 d9 2d 0e b3 0c 62 af bf 2b 45 df 62 +d0 66 65 f8 05 25 b6 72 7f 95 e3 42 29 e6 82 a8 + +# Seed: +2a d7 14 2f cf a3 bd be b7 55 b2 c5 b5 cf 13 e6 +96 9e b7 3b 7a 06 bc 29 bc ad 7e 75 30 a5 90 23 +0f 6a 43 fc 03 d6 c3 a9 c6 41 e5 3a 41 77 d5 75 +02 91 ec 6d 4b 33 f8 71 66 8a d8 56 90 77 + +# Encryption: +17 8e 49 77 0a 4c 8f fb 7f 65 f3 82 cd b5 76 e6 +08 e9 75 c4 37 13 39 10 2b 95 2a 1e 71 cb cb 91 +fd cd 0c 0e d5 a8 5f bd 26 3d a6 a7 4e 49 1f b0 +4b 60 a5 96 1d 8e 6a c7 24 ec 8a 81 61 c2 2a e3 +10 40 7f 59 f7 e6 02 da 48 aa 2d ad 68 3e 88 db +1d 84 29 5e 0f ba 5f f2 f6 73 df 32 85 4d 01 b7 +1a 89 46 0f f0 e6 e1 be 98 ae bf a2 27 e3 97 ea +cc 8b 23 17 41 47 c4 4e 16 20 1e c6 ba bd 16 5b +a4 + +# PKCS#1 v1.5 Encryption Example 12.12 +# ---------------------------------- + +# Message: +fa 4e b9 31 a7 e2 09 0f 31 ed b1 ff 7d 83 61 + +# Seed: +43 7f a1 51 f4 34 05 db 22 42 2c b3 5d 1c 57 61 +16 1c b9 a7 8a bc b6 f0 6d c4 e7 a8 69 48 1f 40 +b2 1a e1 d3 3e 07 5c 48 5c d8 50 1a 3c aa 60 18 +32 5b 7f 85 0d 4d 8f 6d cf d2 af fe 19 d3 e6 c7 +08 74 e7 10 11 14 f0 fb b9 82 25 81 ba e6 ba 2b +a1 e7 49 88 81 a5 dc 5b b8 85 27 38 a8 2f b0 6d +15 27 b4 33 44 87 b3 24 01 3e 32 bc f1 7b ab + +# Encryption: +22 6d 77 67 00 c5 e1 dd b9 99 4b 32 91 f1 d3 34 +b6 9d d8 63 06 5f a8 34 21 e0 1d 52 06 ec 2c db +89 90 cf 78 97 31 09 dc 9f 12 6b 60 33 d6 d5 d6 +91 8e c8 50 d6 9c 71 3c b5 bb e3 2e e5 9e 44 5b +cb 4e 50 c6 f1 64 43 4d 2a 6c a6 39 69 a2 9b 25 +03 64 15 b0 f7 cb 21 b4 f8 b3 4a 8d 9b 74 65 3f +ff 4f 5d b9 d1 a6 b5 15 2a 64 48 36 b6 8b 8e de +9d c5 a1 69 dc 60 dc 5f ac 46 8f 24 27 84 58 10 +62 + +# PKCS#1 v1.5 Encryption Example 12.13 +# ---------------------------------- + +# Message: +58 81 15 e5 37 09 eb 15 a3 37 4c 25 32 9e 88 38 +26 e3 21 3f 37 a1 b7 a6 5d e1 2d f2 31 72 f1 7f +a4 96 ff 49 2b 09 17 3b a0 c6 f5 8c 29 3d 47 f1 +48 + +# Seed: +07 81 85 e0 83 cb b0 6f e1 a7 49 74 35 15 f3 a0 +b4 b2 6f 85 3b 10 e5 68 e8 70 82 ce 44 41 2c a6 +7e 59 88 8c cc 0f 50 31 01 52 1a ca bf d9 8f b7 +b5 c1 1d 8a 94 1b a0 3c 49 5a a0 3e 13 52 2f 48 +7f 6e 16 16 be c2 07 2b 39 96 fa ee 29 + +# Encryption: +0e 7e 50 a7 b2 47 b0 29 7d ec 65 c9 52 3f 67 ca +b6 b5 2a 02 5f 53 32 0e 94 86 cd 20 74 10 ca dc +74 e4 b0 3f c0 6b be d5 98 b0 22 b6 3b 37 76 2a +65 fd 35 1c b2 72 7f 3d 80 35 a4 cd ba 9c 6a 31 +e4 ed 6b eb 4f ed 31 34 eb 63 df ce ab 4f 5f 24 +59 e5 9f ca 01 74 75 8a ab 37 53 b5 c1 93 c8 1e +11 49 0f 97 b6 22 b7 3f a7 3f 8e ae 7d a8 39 34 +84 b8 29 79 71 a3 e9 23 12 9c e4 35 7b 64 5c c6 +38 + +# PKCS#1 v1.5 Encryption Example 12.14 +# ---------------------------------- + +# Message: +20 f1 cf aa 63 67 c7 c3 9b 54 a0 + +# Seed: +4a 1c 7b 70 f7 83 ba 0d 5a 26 d4 64 5c f0 5f a6 +10 f5 be 01 77 fd de 9f 2c 34 50 57 db 42 44 57 +fa a4 30 c9 42 4a 54 f7 e5 5f cf ee 6f ae a4 24 +4c 03 97 74 81 ed fc bb 28 88 37 c6 a4 8d bd 72 +96 67 7a 24 e0 6c c9 d8 5e 68 8c 14 09 0f a2 83 +0f f4 96 79 33 ea f0 db 69 4b 6a e4 02 ca f9 c2 +be ff 04 a5 2a 2f 84 7f e4 0f 4f fb df 3d 58 b7 +c4 fd a8 + +# Encryption: +1e 52 84 20 bc bb a7 d5 9c 6c 40 d4 46 d1 aa 95 +6a ff 03 05 36 5b 4d 7c e9 81 0f 22 c3 4f 09 a5 +55 e5 ff be 51 75 03 7f 90 3e aa 6c 40 56 36 36 +d3 81 f4 53 25 b5 e6 1a 2c 70 51 12 55 64 02 a7 +dc be 86 cf a5 4a 6e 6a 50 37 8d 05 e2 1c 95 cc +6c 45 ff dd 05 17 f7 7a 36 b2 24 d1 70 0a 1f 3e +bb 81 d3 67 8a 66 e1 45 34 a8 0a 59 8b d7 17 26 +fe 32 2e 73 9c 17 eb a5 08 da 8a 03 1a 27 f6 bb +28 + +# PKCS#1 v1.5 Encryption Example 12.15 +# ---------------------------------- + +# Message: +73 60 cd b6 c1 59 96 b0 60 33 1e 9f 2a 36 89 95 +c0 64 ad da 56 55 95 27 78 2c 17 0c 69 1b b3 bd +3b + +# Seed: +58 dd 80 f4 fd c5 c9 5d d9 eb 56 ac 80 a0 2d 53 +e8 cc 2e fb 3c ba c6 72 7d 75 b1 e7 b3 5e 05 42 +19 43 3a f5 aa e1 98 fd 62 f2 ec d2 ab 8e 26 38 +77 b5 c9 1e d5 13 e2 35 49 7a 63 19 2d b9 a9 bc +b3 bc a9 7a e9 bf ce df 93 56 44 b2 d3 bc 20 e0 +2a e5 e7 42 4e 81 2a 29 49 61 6b 82 01 + +# Encryption: +20 3b cd e1 b4 12 e3 ce a2 5b 86 30 b2 08 f9 78 +ab 22 c1 da 81 25 07 6e 10 ff 91 d7 bc fa ef d7 +dc d8 39 16 55 c8 86 e8 a9 45 a7 f5 7a 74 ce 2d +c0 e8 ec 7f db 17 cf 19 57 80 d3 ce 80 e0 dd e7 +63 9c 67 72 05 b8 f9 ec ea 11 54 68 97 7b de a3 +50 0b 23 9f ce 0d 7a 94 be 6d e3 33 ea 7e cc 22 +c0 7e 65 d0 eb d6 5a 39 0a 18 5f 18 17 89 e7 ca +8c 1a c2 fc a8 28 bb 8d 28 22 7e 38 c9 88 9c e0 +08 + +# PKCS#1 v1.5 Encryption Example 12.16 +# ---------------------------------- + +# Message: +31 9b 82 94 bd f0 7c d4 06 85 e8 80 09 fa 7b 3f +12 90 16 0e f3 30 67 ad d5 ef 4d 80 fd + +# Seed: +4e 07 d7 f9 63 be 24 ee 6d 8b d4 dd 95 e9 e3 33 +49 30 e0 3e 65 8d 29 6b b7 95 48 6d 72 4e 07 41 +dd 50 73 47 a5 b5 7b 79 c9 0d 3c 90 c1 ae a7 16 +19 09 1a cc 81 98 b5 51 22 da 50 99 58 2e 0d b7 +da 3c bd 3c fd 85 29 8f 31 55 4e 29 cb cb a1 19 +9c e4 70 16 3c a0 33 7c c4 14 ad 32 76 70 81 11 +d6 + +# Encryption: +04 fc 7b b6 fb 64 19 61 2b 6e f5 4b 3c a0 0a 87 +46 51 95 c3 7f 7f 94 0c 23 3e cb 1d 4a 50 5d 3c +56 ed 23 e0 9e 03 f1 45 4f 04 b5 6f 6d a2 5d 0a +6f ca b0 c4 00 87 4a e9 80 6e e1 87 80 b7 5c 6c +a5 66 29 e5 77 e8 e7 b5 d2 fc 2c 44 0b 98 00 19 +5b 58 51 1b c3 a7 95 44 12 c8 f2 73 cc 0e 9d 97 +1a bb dd d7 02 8e 6f 84 87 6a 30 58 a4 54 fe 2f +33 c7 5e 3d d0 62 f1 19 cd 3e ca 81 06 b6 bf be +a4 + +# PKCS#1 v1.5 Encryption Example 12.17 +# ---------------------------------- + +# Message: +79 c6 82 a2 b9 79 fe 5c 96 32 af 18 31 c2 aa cf +0c 6b f5 66 88 5b f5 25 62 50 + +# Seed: +5c 2a 95 6d 4b 5f 06 f7 50 83 5a b8 b2 9c f7 c6 +41 d7 93 c5 56 e1 2a ab a9 56 df de 46 32 d5 e5 +02 d5 90 41 78 3a fd 1d a7 b2 e2 d2 4e 22 d6 44 +78 35 bf 6d 77 c6 ee bc 0d 2d 64 e7 ed 2c 14 17 +18 ad 86 87 c5 97 b7 71 8f 38 bf 1a 33 16 ed ef +f6 b7 2e 28 51 82 88 07 bc ff a9 b8 e1 a8 52 f3 +fa a8 07 f6 + +# Encryption: +25 1d 48 56 b7 a7 58 0d 53 88 01 62 28 1b b4 e4 +1b de b2 a8 7d db d5 ae 1b 30 7d 44 48 be 1f 11 +69 5f f7 22 c4 32 41 5d 0c 74 ba a3 fc 0d d5 11 +66 ac 86 5b 31 0c 4f 5c 87 07 98 62 54 c8 96 04 +cc da bc e6 c6 92 44 66 21 89 8b 4f 5a 08 bc df +64 62 e5 18 ee 3a eb 75 e2 6d 8f 63 a0 6f cb b3 +df 09 8c ee bb 0f d2 f6 37 e3 a7 93 7f 4d 19 e3 +a1 92 4c 16 08 2e dc 33 3c b6 de 37 63 72 46 e4 +98 + +# PKCS#1 v1.5 Encryption Example 12.18 +# ---------------------------------- + +# Message: +1e 0d 18 07 a2 bd 49 6b b0 cb a8 41 c7 71 58 bf +a5 f8 aa 77 d0 56 75 c6 4a 5e b1 85 65 91 d3 48 +54 f8 65 92 5b 37 1b 68 6a aa b4 45 98 b4 a1 6a +b6 b7 93 44 d3 c2 3f 7d 5b f1 73 b8 42 d7 8c + +# Seed: +db af a5 33 2f 0b 55 27 96 63 6d 8a 09 28 b7 d8 +7d 9c ee 3d 4b e6 a3 1c 77 e1 4e 0e 5d fd d4 03 +ef b9 8f a3 38 81 6e 12 62 c0 64 96 fd e9 d5 57 +c0 0c c0 dd 35 fc 33 ac cd 79 a3 15 06 90 eb + +# Encryption: +1b 2e ce a5 fa 90 03 fa b6 55 98 57 c6 d9 4f 95 +70 03 f4 e4 1c 09 45 64 80 4f e6 96 39 e5 40 b6 +8f 26 3f aa ec a1 99 69 7a 48 85 8b 8a 0f ce a4 +91 05 7d f2 fb 8b 35 d0 93 d8 94 ae c1 7c 5c de +5d fd 8f 33 51 2b cc 66 cd e7 6d a0 73 36 98 5a +97 43 5b 6e fe e4 ee 09 d3 a2 8a ff 34 ce 6a e8 +75 0d a4 1e 16 ca 47 e9 38 81 8e 44 a9 b4 1f e9 +1a 6a 80 1d 35 5e e8 d6 60 e2 7e 4f e2 ce 7f 32 +5b + +# PKCS#1 v1.5 Encryption Example 12.19 +# ---------------------------------- + +# Message: +1c 10 5d 5e be a3 66 46 a9 72 84 c1 7a 86 c4 + +# Seed: +c6 f8 03 40 a6 55 7e 07 53 a9 57 3f e4 f5 21 49 +77 ef db 08 2a 50 eb 5d 5c 51 7d 46 72 9f d2 a3 +4a f7 ce e1 aa 46 b7 9d 47 e2 5d 83 09 0a eb 4f +50 22 98 c0 31 37 24 fa b5 4e 54 be bb 48 d6 cd +9b eb dd cb ee 0f 07 53 77 27 d6 5c 50 e7 d4 cc +0c 6d 19 fc 48 0b a5 78 67 26 2c f2 ee dd 9c fa +ba 60 7d 65 82 87 eb a4 2b 46 99 44 cc b6 12 + +# Encryption: +05 b2 3d c0 c6 2d 90 c1 77 1e ba 37 8e 43 17 9d +7c a6 af 51 5e 26 19 ae 4d 7c 8f c8 bd a3 78 cb +f7 a1 db ba 1a 14 f4 94 c4 e0 d7 13 38 79 7c 7e +e0 6e 1a 79 e9 ff 28 56 fb f7 4f e6 f1 a7 ca 6e +5b 9c a2 83 c4 c9 7e 61 cf 9f 40 73 e0 32 ca 27 +d6 9b 1b 4e eb ea 77 cc 95 a9 28 1f 26 b6 4a 05 +a9 39 44 c8 2c 5a 13 42 8e ce 21 fb 44 01 ad 42 +6e 7a c1 f0 5b ff 84 b3 47 cd c4 db e5 2e 67 8a +ed + +# PKCS#1 v1.5 Encryption Example 12.20 +# ---------------------------------- + +# Message: +f1 04 02 f0 02 05 c5 27 57 ed 6e 9d + +# Seed: +e2 ae e7 fc f4 3c ed e0 75 52 a2 df e5 b5 a9 ef +80 82 76 d8 f1 0e b3 f9 bc 50 f1 bd 94 0a aa e6 +34 c9 d8 a0 78 8d 44 d4 1e 8a 5c 60 36 49 ef ea +83 03 32 31 51 6c 69 d3 3e 12 f1 f5 d3 f0 ac 1f +c2 3a 9b 3f 5d a4 e0 ef 6e 45 50 cb 43 fd ff 02 +b2 5d ac 86 27 2d 66 db 59 cd d6 35 f9 c0 dd 0d +aa 08 57 91 0c 15 88 1b 16 0d 70 ea 53 40 5a a9 +59 f4 + +# Encryption: +0b 96 56 31 78 32 a9 40 c7 95 bb a5 8d aa 15 9a +4f 73 3e 82 6c e5 5a 4e c5 64 33 c5 16 84 44 4c +78 e2 e2 fc b3 7f 85 ad 87 79 16 52 2d 8a 35 a4 +3f 53 c5 95 17 a8 18 e5 21 e1 98 2a 50 91 bf 2c +68 b0 0e e4 9a bd 90 dd 77 6c 02 f6 4f 34 f6 80 +a8 8e ee 05 ec 08 88 92 bc 0a 95 55 b3 f2 0c 8b +ee 57 9c 0d dd e1 51 1a 18 af 98 bc 1d 9c f9 0b +81 bf 13 2a bd 58 97 0b 3e 84 d8 14 e2 7d 02 5b +73 + +# ============================================= + +# Example 13: A 1031-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +55 5d c2 ba f0 41 b7 f0 9a 04 78 42 3a eb cb 5f +49 b9 5d be 15 70 e9 a5 42 12 8d 33 22 87 86 6a +c4 cc 63 e7 6f 8e 3a ef 22 c9 75 3a 54 51 99 94 +24 52 41 8a 67 d1 a2 23 0d db 6f 42 22 c6 63 d3 +8e 80 05 0e eb 67 95 6e c5 f5 49 94 a0 be a6 95 +fa 59 fa df 2d cf e7 ac b5 4e d9 da 3d 0b eb 12 +2c 8a 69 1b 0b b5 1a e6 5a 77 4d 75 b1 b3 49 cb +68 c5 17 cb d3 86 ae 48 2f 05 ee 46 03 ec f2 95 +5d + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +55 5d c2 ba f0 41 b7 f0 9a 04 78 42 3a eb cb 5f +49 b9 5d be 15 70 e9 a5 42 12 8d 33 22 87 86 6a +c4 cc 63 e7 6f 8e 3a ef 22 c9 75 3a 54 51 99 94 +24 52 41 8a 67 d1 a2 23 0d db 6f 42 22 c6 63 d3 +8e 80 05 0e eb 67 95 6e c5 f5 49 94 a0 be a6 95 +fa 59 fa df 2d cf e7 ac b5 4e d9 da 3d 0b eb 12 +2c 8a 69 1b 0b b5 1a e6 5a 77 4d 75 b1 b3 49 cb +68 c5 17 cb d3 86 ae 48 2f 05 ee 46 03 ec f2 95 +5d + +# Public exponent: +01 00 01 + +# Exponent: +05 97 87 bb 01 23 fc ed 98 d9 34 1b 7a 8a 99 9e +db 50 76 30 8e 6d 00 11 20 3b e0 dd f9 a4 11 0d +0b 69 2c 1e 2b f3 90 2e bc 03 a0 57 3a d0 c1 93 +af b1 67 b3 ae 4b 50 28 a5 ae bb 22 04 ef 23 f8 +e5 83 60 be 94 84 95 1e 34 71 11 76 06 2e 53 e3 +f6 38 74 fc 9e 35 91 a9 d9 06 8a a5 e6 c8 c7 a9 +ab 08 e9 79 24 70 06 6d 71 a0 7c 34 33 dd 70 3a +42 a6 b3 a9 b1 bf fb 31 49 49 8d cf f8 b3 57 56 +ed + +# Prime 1: +0a 7d bd 7e e6 de f3 87 5b 4c 55 9f 56 69 30 7d +17 6b c1 25 b0 9f 5e b8 26 01 b8 13 48 57 6c 1c +a7 dc f4 c2 bd 7f 2b 42 a2 c5 46 00 02 fc e0 a9 +a2 1d ac 5a 97 97 db 23 3d 9d 4a 92 93 ad d3 df +73 + +# Prime 2: +08 23 0f cf 26 fd c5 75 11 9c f9 05 78 d3 66 56 +4c fd a8 65 a2 82 0f 38 bc d6 3e ca a0 95 57 65 +77 2a 88 32 fb 31 69 7f d0 dd 45 bb ec c0 4d d6 +a5 9e c1 1c 1d 5c 6e 87 7c 6b 9d 77 c6 a2 76 e3 +ef + +# Prime exponent 1: +08 d1 c7 d9 c4 d0 2c bd df 7c 7e 86 62 a8 2f 41 +19 cd 56 24 0f 25 0b 05 97 bd de 37 27 9b 86 a1 +58 64 a1 c6 8c 73 39 b4 dd 0d 26 59 a0 29 61 dc +79 12 a4 ef cb 7c b7 96 1a 97 fe 36 d6 bb 4c e0 +0d + +# Prime exponent 2: +01 d4 91 3b d1 d3 87 d5 3b af 09 bd 17 5e c6 48 +67 6d 2f b2 1d 0a 10 8e 7c bb dc c8 0b b3 4c 43 +80 b8 ca 86 5d 46 d2 2a 74 3b 31 f2 81 e1 08 21 +5e 84 05 80 63 82 65 42 88 d4 54 49 9b 1e f4 8b +75 + +# Coefficient: +08 7b 2e f2 11 44 8e 5c 96 1c 9f 6d fe e6 aa 26 +8e e8 97 7e 31 1c 07 cc 8d b4 72 da 6c 49 86 3f +aa f3 3b f5 05 dc fd 81 f5 3a 53 be 12 1e 44 5e +89 d7 e0 38 ef 27 f3 72 7b 51 2a 2b 80 94 41 20 +ea + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 13.1 +# ---------------------------------- + +# Message: +7b c8 1d 81 46 e3 59 + +# Seed: +76 65 5e 4a d8 fb 99 34 d1 84 7c c9 0c 02 47 3c +57 2b 5f df d1 64 a9 70 a3 cd 96 bc 8c d7 96 ac +80 2c 50 28 22 90 ea d4 c7 7a a5 cc 2a 7e 34 34 +18 c9 df 47 ef b8 87 86 af 4c c8 d1 82 1c 50 07 +39 09 e8 4f 7b 45 1a f4 a3 2a ee 6c 7c c8 97 ee +f7 66 0e 1c 4c 53 5d 10 03 9d 3a a2 03 5c 98 51 +01 25 ec 5f 2a 2e 9d ac 63 95 89 ff 8b b3 9f 07 +43 8d ef b7 d1 33 77 + +# Encryption: +14 6d 65 12 df df fb c0 2d 5d 54 bf f3 e0 36 a3 +5b 4c 2a a9 44 d6 f6 72 47 93 30 65 37 08 1b d1 +1e e5 68 a4 e9 71 9f 1e 31 f2 d1 4e 18 c2 da 62 +44 70 c5 b0 ff ab 39 7f 92 31 b6 ef 46 34 f6 3a +18 28 5d f3 41 45 17 a5 1f 93 58 6d 66 b0 3c ab +1e 78 a4 eb 94 1b 9d 3d 7f 92 03 b5 9e 1c b3 bb +48 64 b6 46 dc 17 a0 64 11 eb d5 ff 03 37 20 58 +88 1b 4a 24 b2 4f 4c 2d cd 5c b4 4c 2e ea be 6f +72 + +# PKCS#1 v1.5 Encryption Example 13.2 +# ---------------------------------- + +# Message: +68 6a 81 0a 03 1d 80 61 e4 1a 77 6a 7d fb db 3a +f6 26 fe 97 69 de ee a4 60 ba 28 67 ac f0 3d 9f +92 4d 32 1e 8a 8f 42 5c 28 51 92 98 67 a3 26 ae +27 5b 49 d2 + +# Seed: +f7 9b 49 f6 a6 be 3e 68 88 4c 80 df e1 e8 50 1e +54 4c a7 82 23 88 43 d4 19 76 41 12 25 0e dc 1b +69 c7 d1 c3 58 7f dc 75 98 7c 62 cb 4c 33 bb 81 +20 2f 72 db a7 ee e2 4b fc f8 9d 4d ae 15 0c 07 +27 24 58 fb 01 b6 cd 27 09 25 + +# Encryption: +08 8a 47 f1 1c b1 34 de c4 b5 08 77 25 e8 a5 bd +04 f7 fe 58 2a 69 91 4f 68 3e e6 de 7c 32 4f ed +7e 07 f5 70 05 c0 e0 df 75 00 e3 70 a4 2e fd 6f +e5 b2 90 19 95 19 b1 98 06 b6 e6 91 69 8a fd 95 +17 d7 80 da 0b eb f7 0a 26 d6 5c 5b 64 e3 40 a6 +40 5e 88 95 55 df a0 a9 2c 42 9a e9 c3 ec 88 e8 +88 ee da 04 5e 41 0e 3a 9e 61 99 ab 39 eb 1a c8 +64 e2 28 c2 cc 1b 64 e3 36 16 95 b5 aa 11 3d c5 +a7 + +# PKCS#1 v1.5 Encryption Example 13.3 +# ---------------------------------- + +# Message: +18 54 4a ad 24 ab 07 5d 3a + +# Seed: +23 20 4b 8a d9 45 75 f6 e2 f4 6c 79 7b b8 73 aa +3f 46 1a cd 05 e7 db 78 46 a2 31 57 59 2d 52 e9 +a9 a7 04 38 19 c4 88 96 27 5e d9 df 0b 1e 54 04 +93 c0 77 ea 15 41 9a fa 87 dc 35 f9 fd f7 ab 8a +af 47 ee e1 d3 3e cc 28 95 06 45 f1 b6 91 38 2d +87 54 1e d0 64 06 93 0c 7e e1 10 9a a5 ca 75 a4 +90 93 4e a8 d3 b2 a0 4b a1 52 1b e0 92 c8 68 f7 +ea 5b e3 78 ea + +# Encryption: +34 d6 e5 46 d6 9e 27 06 cd fc 6d 9e 74 18 f8 be +03 e4 57 56 a8 b1 9b 60 c2 1d 27 34 20 aa 7d 5e +bb bf 46 0e f4 c8 4f 6d 47 77 e6 bf 20 3f f9 18 +5f d5 7d c7 23 b5 8f 35 c1 e9 b5 ff f4 7c f9 5a +e5 69 a5 cb 64 dd 9c b8 d6 40 7c 0b a5 ef d1 48 +f1 8b 56 96 b0 47 da aa a2 77 ed 8d 45 28 61 4e +e3 da 52 38 71 32 b7 a9 cc fe 07 3b e5 03 32 c9 +e2 83 73 53 c6 7d aa 0f df ef c3 b6 52 cf 7d 79 +fd + +# PKCS#1 v1.5 Encryption Example 13.4 +# ---------------------------------- + +# Message: +d9 0f a3 8f + +# Seed: +3e 09 f6 50 6f 7f 71 91 47 ae 21 e3 94 53 ae 0b +41 60 98 da 10 3a f8 4c 0f 7c ef ae 50 01 99 c9 +85 59 67 a8 30 0a 1a 7f 8d 2c c1 3b 91 72 7e eb +d9 3c f7 7d 3f ac b1 9e 83 a8 40 eb 58 3b ce a6 +c6 11 3a 9c 6f 6f 1f b5 a0 b3 32 55 9a 6b 43 15 +47 45 7c da 1d 3d ce e3 41 d1 71 c6 2e 95 e7 ea +ae 16 ae 0e af 1c 1f e8 10 fb b0 b7 13 8c fa 3d +66 c6 38 50 f3 81 e4 9a 2d ad + +# Encryption: +27 13 3f 43 79 1b 39 22 7c 8e 95 4e 1c aa 83 0f +a6 59 95 f8 a9 f8 8e 0d 1f 75 67 85 ed 5c 8c 78 +54 fb 1a 9d c4 a9 5f a4 4d bd f0 f2 85 99 c4 72 +84 93 79 75 0a 6a 1b cb 42 ca fb 5b bf e0 8c 65 +10 6d c8 40 cb ec 8e e2 cb 5a 20 6c 81 18 aa 06 +1d a4 d2 1d 1b 5c 46 11 7f 77 c8 96 bc 71 ce e2 +f8 75 7a ff 5c b2 b3 c3 47 74 55 8e 8b 82 ed b4 +ef 9b f2 d4 f2 ca 4f c5 97 fa b4 0a 2d 74 e5 23 +3a + +# PKCS#1 v1.5 Encryption Example 13.5 +# ---------------------------------- + +# Message: +fc bd d0 24 8d f8 57 af 17 5b 43 96 87 5c 00 6d +51 14 cc 11 16 42 80 04 38 08 aa 79 88 6c 4c aa +29 11 7b f3 ce 45 a9 be 55 07 c6 b8 bf 0d 30 + +# Seed: +2c 9d 14 57 ba 44 50 df 40 21 e4 e5 11 83 f7 95 +d0 91 c0 7f 6a e0 dd 96 2d 57 28 c5 4b 7f c3 c7 +72 d7 9d 7b ec e1 bb 0c 99 6c 9a c0 7f 99 54 dd +a7 68 7b ec 86 bc db 31 40 b2 45 bb 5e 01 27 5b +38 d1 f2 52 33 5e 36 c6 8c 0e 58 f4 ce 11 7e + +# Encryption: +2c ed de f2 02 69 1a ae 42 71 85 2a 89 83 de 7c +21 4c ee 00 db e1 a1 58 84 f4 c3 c1 de 7a 3e a0 +1e cc f4 7a e8 6c 26 93 24 ae 52 37 73 37 b6 ca +82 e8 5d 55 3f bb 2e e5 f9 77 dc 66 4e 14 2f 1b +54 53 8f af 85 ca c2 7c 29 f2 ed 0c 40 42 67 33 +5d 48 ea 40 e8 a3 dd d8 96 bb b3 e0 ed f0 e1 6f +9e 89 44 68 3b 8c fb aa b5 ea f2 25 30 f1 58 c4 +88 0b c3 e4 60 c0 6a 24 03 42 21 0a a8 7b 79 09 +68 + +# PKCS#1 v1.5 Encryption Example 13.6 +# ---------------------------------- + +# Message: +25 f2 a3 06 ea be 6e 3a 18 30 dc 93 6b fa 41 cd +eb b8 80 05 17 5d f4 a3 c9 c4 64 23 01 45 61 11 +5a a8 + +# Seed: +cb 8e 0f f4 1b ab 01 a1 42 f9 6e 7d 7c d3 92 82 +0a 82 a1 73 66 74 b9 21 35 ef 33 08 96 88 dd 30 +b2 c2 f7 ba 11 1a f7 8d 3f 76 a3 7f 66 7d b3 97 +5f ce 64 ec 9a fb 09 68 50 7f 7b 31 09 7e aa e4 +88 1b 36 24 06 56 16 ca 09 0c 20 4c 1f a4 be 13 +48 50 ea 5e 90 fe cd c8 45 b9 d8 39 + +# Encryption: +4c 7a c8 12 45 e7 d4 de 3c 4d bf b3 15 c4 68 34 +1c bf 22 87 57 35 c5 f8 05 90 50 58 53 06 8d 6b +e7 03 9b 1c ee 6d 07 ec b7 66 9c 42 f6 b9 2f 2a +71 f6 45 f7 2c ba ff 76 34 16 37 d2 f1 d6 b1 fe +ce b0 7f 21 e1 4c 70 fb 77 bc 7f 87 b0 31 c2 c8 +f2 ad a4 ec 43 e9 12 68 2c 2f 49 63 9e 75 71 57 +18 77 fc 48 1c bf 26 98 b3 73 15 bd 4b 93 07 83 +f4 79 45 64 2b 7d 81 5e 04 32 d4 5d d1 d0 d3 b2 +a5 + +# PKCS#1 v1.5 Encryption Example 13.7 +# ---------------------------------- + +# Message: +a0 da ab 4f 9f e0 4a 2a 51 bf 08 32 70 11 5d 0d +06 dc 29 21 cf 8d d1 3f 5c ff 26 04 bc 55 1e fd +98 3d 9b 25 b7 27 4f 3c cb 0a dc c1 1b 1a 39 54 +ab 9d b4 + +# Seed: +c8 1d 1c 02 f0 6e 7f fd 6e 03 b8 1b 71 93 aa bd +ac 56 63 ab 14 25 a6 7d 1a 29 50 88 5f 5d 1c 4b +72 5e 20 9d cb ce 9f 7b f2 96 75 23 42 f1 84 fe +a0 6a 7d 6c b2 bd 39 b2 a3 18 07 51 64 a2 e7 61 +b7 02 70 2b 01 92 46 c1 e5 0e 6e + +# Encryption: +06 c0 6c 97 5f c6 b9 c2 60 d3 d8 81 3b 57 14 24 +8b eb 39 9b 7d 68 fc ac 25 03 38 ca c5 4c 40 72 +95 9f 62 03 84 44 e9 e6 66 ba b5 f9 36 06 70 47 +bc af 4b a4 ed 68 c6 c8 18 57 46 29 32 56 e7 c7 +24 16 65 81 54 de c0 67 f4 25 0d c6 b2 9b ba c1 +8e 82 1e 49 a4 c9 b1 63 83 1f 7b b3 83 92 32 6c +6b 46 85 46 4f e4 f0 26 c9 ae 4d bc 58 49 47 7b +4c 26 0a a4 ac 02 d2 1a 26 40 20 f1 0c a1 1b 4b +0e + +# PKCS#1 v1.5 Encryption Example 13.8 +# ---------------------------------- + +# Message: +74 3c dd b3 61 c0 bb 32 47 64 95 ad 5d c6 3a 2b +ce 5f ba c1 c8 c2 03 93 69 32 67 d8 43 f2 8b 8c +f3 ea 13 e3 74 e0 9d 0a a3 f7 ae 5d 8f 72 d8 e6 +cb 9d bd + +# Seed: +f7 2e d2 d0 69 b8 ae 50 27 04 6e 03 27 b9 87 84 +58 09 b4 e8 16 c8 86 58 24 fc 4a 23 01 b4 56 80 +2b 18 9c bb 43 f0 48 32 ac 25 c8 48 d7 4f be 1d +62 5a a9 8a e0 5e b6 25 47 76 1c 78 b8 17 61 c3 +03 f9 3d f3 fc 0f ea 3c 5a 7b b1 + +# Encryption: +38 3e bb f1 59 e1 d0 a2 1c 74 eb 61 e3 64 3c b6 +31 be 18 c7 a2 a5 4e 24 89 33 58 7d 34 5e 99 52 +72 46 6d c1 bd 61 3a dd b4 cd 7b a5 01 92 fc 2d +89 4d 7f da f7 83 63 b0 79 d9 98 01 9f 16 42 31 +cc 2d 75 2d b7 6a 9f 9d 0c 52 04 bf b0 f9 93 05 +53 09 6b 5b 76 80 b0 89 4f b9 9c 11 42 5c 67 d6 +5d 96 5e 35 12 8e 15 47 46 b3 fe d8 d0 16 99 30 +70 a7 0e 07 eb eb e0 6f 2f 4e 97 6c 9a 63 fb e3 +20 + +# PKCS#1 v1.5 Encryption Example 13.9 +# ---------------------------------- + +# Message: +e5 31 92 fe bc d3 69 58 bd 08 03 f2 ea 0a fd bf +df 99 3b 58 a9 e4 ee 70 df 95 b0 6d 4e 7d 74 b6 +74 5b 87 f5 81 f3 42 f8 ae f9 ae 4c 31 82 c4 19 +9b 65 51 fe 18 f8 d3 b9 ff e4 + +# Seed: +ad 98 2f a7 29 f2 7f ce 8a 67 49 03 ec ac 69 4d +d3 34 13 c7 8e 34 28 ae ed 46 9f 84 d9 57 5c 6d +a2 75 29 f2 c1 4b 53 b7 58 d2 0f b6 b2 47 c8 29 +c5 fb 1a 16 af 55 07 9a 70 73 cc a0 56 25 96 2b +6d 1a 6b ef + +# Encryption: +22 1d 88 a8 6c 9e d3 7a a0 9c f5 72 54 97 82 e5 +8c a8 d4 85 1f 01 6a cf 28 9e e8 bf 23 79 0b 1a +8f 14 8c 16 55 08 bc 3f db 1e f9 c9 01 16 27 42 +7c 5f 32 e5 ca b8 50 cb 6b c0 bc 04 a1 1d a2 f0 +18 13 f3 41 41 7b 3e 63 2b ca e0 02 97 7d 64 ff +c9 62 c7 fa 75 72 f5 6d 26 17 e2 a5 2d 3e f9 17 +c4 4a 33 b7 15 82 af f1 39 0b 7c 77 4d 60 7c 8d +57 8f 7b c9 0b 35 80 d7 7b 03 73 19 14 77 bc 14 +26 + +# PKCS#1 v1.5 Encryption Example 13.10 +# ---------------------------------- + +# Message: +d0 eb 48 0e 27 45 77 9c 8a 30 fe 82 0a ef 56 d4 +ce 39 ef 84 ea 40 c7 df 0c + +# Seed: +46 5f 91 e3 f0 7c b7 22 83 bc 2b be 52 8b 9a b3 +68 16 54 fe 20 b6 1a 33 f1 23 ad e5 2e 83 2f fa +8a 1b 74 a4 44 3c c8 92 95 a2 1a 2a ac 98 74 da +0a 56 79 d1 8c b5 c4 cd 69 0b d0 a2 0c bd 9e 9a +a0 72 aa 87 13 44 8f 95 e5 d6 a6 e6 24 d5 b9 08 +5c fc ec b7 99 2f 10 ea 2d a6 d6 26 eb e5 43 d8 +70 22 36 ee 6c + +# Encryption: +06 f3 f8 c7 0d 0f c4 e7 44 73 e6 8f d2 3c c9 df +1e dd 42 35 b4 28 b7 72 a0 83 b4 1c 34 51 62 5a +6f 15 de a4 bf 31 3b f4 f0 3f dc 4f e9 f6 a2 07 +1a c6 9a a3 f0 fc 41 57 ef c6 21 f9 59 40 61 f6 +c1 98 06 bd 5d 75 9a d0 23 ca d1 48 e4 47 d2 59 +b6 2b f7 34 25 91 be 83 ba ec 77 71 4c fe 2b 90 +1f 36 9a ea 68 02 48 ba bf 06 87 10 cb b9 70 48 +4f 32 4a 23 52 53 a3 1e 02 25 34 ab ec 7b 39 96 +06 + +# PKCS#1 v1.5 Encryption Example 13.11 +# ---------------------------------- + +# Message: +1c 42 97 f6 df c0 7f fe 57 59 aa 1e aa 5b 79 37 +8a fc dd 1a 9a 33 a2 13 3a 39 ac + +# Seed: +a7 af 2a 86 01 e4 08 c3 18 fd 1e 0f 82 44 5b 50 +95 44 d5 ec 97 a7 95 8f 59 4b 20 54 c5 09 f7 ef +fd d4 16 30 6b 2b 2c 91 b5 a6 37 a1 56 82 0d 60 +1a 23 ff db 31 fb 35 d3 05 aa 93 74 57 8e ef b8 +10 2e 8b 72 44 19 1f 4e c7 4a a2 6a 0b 7d b3 6c +ab 44 99 9c 81 b3 61 57 01 6b 55 89 06 e5 d7 08 +8d 51 32 + +# Encryption: +3c df 2d c6 7a 4a a5 31 cf a1 42 80 08 bd 05 44 +ab bd 03 29 22 dc c2 43 6d a0 b5 d7 ef 9a 70 17 +e6 19 3a 8b af 38 c5 8e 91 96 2d 65 a3 75 f0 8c +1d 55 57 9c f9 4a 79 5c 9c 70 b6 e4 2e 16 43 ce +f5 40 dc e1 e9 86 dd 99 88 87 b6 95 52 44 4b 6d +e9 3b a7 d5 f7 64 83 54 bf cb 70 21 39 ed 39 54 +94 7d 7b 18 0b 6c 02 bc ad 82 43 a0 ab 27 ca 66 +52 76 29 1b 46 cc 31 8d a9 b5 f6 0a 04 af fe bc +b0 + +# PKCS#1 v1.5 Encryption Example 13.12 +# ---------------------------------- + +# Message: +00 92 7f ca 7f 5e c7 6f 54 8d d4 82 63 e3 39 be + +# Seed: +de bc 2c 1f 22 d9 32 ff cb 89 7c f1 0a e6 2c 3e +05 1e 3f 78 46 3a e6 7d 95 61 cf 1a 73 d5 5c 4b +14 ac a6 c2 1d 83 ba f9 76 cd 8b f2 46 c2 29 78 +61 a6 b1 e9 c9 ef 30 81 c5 1c 4b 68 7c 67 b5 dd +0f e0 f7 55 3f 73 8c 2c 8a 5f 81 d1 26 8a 0c 2d +4a 46 1d 63 5b 0e 59 d2 3b a4 17 ab b8 04 5e 9c +10 d6 6b 0e c8 92 f9 53 c6 f2 11 f0 2f f0 + +# Encryption: +49 b9 20 89 b5 2a b7 8c 33 b5 bb 30 32 cf 70 24 +94 4a c6 8e 13 9d 2d 56 06 8c 7a 26 2a 53 e7 80 +9f b5 b0 15 65 cc 65 61 d7 13 30 46 87 52 30 ac +21 75 64 72 96 cf 2b 48 47 e1 2b 73 63 19 72 53 +21 be a2 64 75 7d e0 eb 49 88 72 d8 9a 4d 7c e4 +a1 bd b7 33 5d ae a7 8b a1 96 fd 50 d9 03 82 e6 +d6 2f 8d f7 ae 68 5a 1d fc 84 9e 11 99 7d ee 88 +60 d1 0f 70 7b 0d 35 36 5a 81 24 30 73 1e 7a 50 +8d + +# PKCS#1 v1.5 Encryption Example 13.13 +# ---------------------------------- + +# Message: +8b 6d f2 d6 da 63 1a c8 d5 55 6a 26 97 54 28 fc +4d 20 ef 5b 4a 1f 06 8e d2 e5 + +# Seed: +ff 2c 06 98 85 2d 1b 0a e3 c5 c5 c9 be 26 e8 3c +90 44 84 2c 16 07 f5 f4 08 6a 6d 6c f1 08 ad ca +61 ea f6 65 40 0d 7c ff 2a 3a da df af d8 0c 64 +95 6d a2 d7 d7 c1 35 ab f5 a0 d1 76 06 25 56 eb +4d 8b 75 b9 5c d1 1e a9 c0 44 2f 84 6f 03 7d a8 +77 29 02 bf fc de 65 59 e1 b5 9e 60 c6 d0 f9 89 +6b a5 c3 c4 + +# Encryption: +41 52 76 69 80 33 39 eb d8 f2 d1 cc 18 6c 7e 8e +bb 80 cf 4b 94 9d 8a 28 43 65 32 9f 3c e4 6e bd +ac 0a 96 9f 67 61 90 0c fe 34 2b c8 4c 7d 69 51 +ac cf 45 28 0b af 24 a0 cb b2 42 a9 42 18 ef 9f +d3 71 b1 e0 08 24 62 62 07 0b f5 54 ed 57 00 7b +97 39 79 16 35 86 1d 86 c6 5b 1a 82 56 f4 25 f9 +f3 ae 51 9e 1b 1b dc 58 75 b8 78 dd cf c1 47 0f +ee f2 ae eb 01 4b 7e 33 ef b9 f4 dd 07 83 d1 71 +23 + +# PKCS#1 v1.5 Encryption Example 13.14 +# ---------------------------------- + +# Message: +ea 03 96 69 bc d7 a8 cd ce ab 58 55 91 b5 63 61 +e9 0b da 0e a4 40 10 49 64 e8 89 ec e1 8a eb 04 +ce 0a b5 b1 cc b2 30 ae 03 25 5a 39 + +# Seed: +20 4f ae b3 13 96 5c c1 a1 8f af 10 39 fd de 68 +1b c4 3b 22 3e 28 bc 47 1c 50 42 3d a0 bd 79 7d +6a 8c 73 8c 54 03 3c 8e 55 9e a2 d1 0c 3b 79 b8 +0e 2e fd ec fe 89 1c ea 2e cb 34 51 a1 a8 e2 ec +2f 44 7b 79 8d 7d e5 64 1b da 4a a9 90 b3 01 e1 +dd e7 + +# Encryption: +4c a1 c8 5c e3 c6 20 d4 29 91 cf 41 73 3e ad 26 +a0 93 11 18 5f ff e5 8f 41 28 8f 6d 0b b6 84 5b +2d 5a cf 1a a0 6c 78 d7 1f 76 93 96 a9 43 42 03 +e3 8b b0 1f d8 8e b2 3e 6b c5 1b a0 c5 f3 ee b3 +27 13 ca d4 d0 87 80 50 61 ab 47 3a 15 67 e7 9b +bf 4e ae 49 36 f1 8d 02 05 b3 74 6a 17 e0 64 8c +52 22 3d d9 f9 99 72 81 b5 35 ab 2f b3 cf f0 3c +a8 90 f7 10 aa 88 fd 2d 0f 39 2f f4 a8 8d 31 1a +a1 + +# PKCS#1 v1.5 Encryption Example 13.15 +# ---------------------------------- + +# Message: +0f 46 2b eb c6 + +# Seed: +4e ae 5d 54 92 d9 44 ff db 04 2a d9 50 16 81 ad +b3 eb 6a b5 28 b6 e8 13 53 55 b6 23 ab 55 a7 40 +87 b1 9f c5 9b 85 34 da 9a 88 da 29 f6 6f 71 f9 +45 2a ed e0 e3 e9 39 07 70 9c 34 49 56 72 85 74 +b6 6f b9 a6 f3 38 3d 58 a0 13 6f 94 c4 ed 86 ca +9d d3 8b ff 07 0f cc 2d ef 29 bd d6 fc 98 59 70 +96 7f 02 fd 6f 93 01 cd 56 d0 48 a4 42 d7 02 40 +9a 98 a1 32 ab 6b ed d4 fe + +# Encryption: +29 36 9e b0 0a 3f 87 84 38 c9 38 f9 d7 bd a3 85 +6c 45 a6 d7 7c 17 88 51 1b 98 2c 58 f6 3d be a3 +3e 63 ae 1d 45 c2 df 6b a8 0f 0d e9 97 59 2e 1f +8a 3b 3a 09 ed 76 06 51 45 3e 10 99 78 cf de 3a +60 0a 74 fa a8 a9 1b 7c 72 4f 97 3c b8 0b 96 83 +5f 05 0b 7d c0 9d 2f 15 74 76 c5 b7 05 1f 94 d9 +c0 f3 17 e1 f1 88 e3 09 80 79 5b 09 6c f9 bb ce +b5 63 6b 3d b9 87 05 4a 56 08 75 22 75 96 29 97 +e7 + +# PKCS#1 v1.5 Encryption Example 13.16 +# ---------------------------------- + +# Message: +51 4d 3b 38 00 22 b3 78 2e 8a 77 d7 7b f2 4a fd +f9 2f 33 97 47 4d ae 0d 4b d6 e4 fa 31 ca 60 83 +df 49 6b 36 62 6e 7f 8e 1c 91 9f 9f 2e + +# Seed: +d4 d3 a9 e8 fb eb 1d c6 07 b4 dd 78 87 ba 25 c3 +d0 bd 81 34 84 bd 53 76 dc 83 ef b5 8e c5 b2 56 +2c b4 4f 98 5e 59 f5 0b 9a de 3c 66 71 6c c6 f4 +2e 51 c6 0a 2f 4d 8d 75 bf b9 b8 24 10 5d 1e e1 +58 35 f5 f5 f2 54 fc 6f 68 0e ee 0b 85 af 54 7c +17 + +# Encryption: +19 fb 39 1a 31 00 87 bc 3d 08 79 1f d5 99 94 be +80 12 df fd 76 a0 2a db d4 79 cc 0c 15 56 60 5d +4d a2 a3 46 1c 7c 71 a8 5e d8 cf 85 e0 8f 45 da +de 51 8c 00 af 09 f4 93 ee 8a 55 46 ff be fb 05 +3c ca 2e ef 06 84 76 3c f7 80 f2 e0 97 bd 8e 5c +2e a8 4c b1 a8 b8 f8 49 6c c9 18 16 7f 65 6c dc +9e 1d 3b 2a 23 38 b6 4c 61 e9 0e cc 27 4a 12 10 +e3 db 57 83 ae 3c 00 ab d3 74 8a 81 0f d9 14 91 +14 + +# PKCS#1 v1.5 Encryption Example 13.17 +# ---------------------------------- + +# Message: +fb a1 63 17 b0 93 08 3e 37 20 aa 06 48 17 e7 4c +a7 51 a5 17 87 4b 69 26 50 c4 14 7f 11 9f 68 90 +70 2c f8 b1 4f 0c 18 82 21 2d 72 40 6c 3a 45 d7 +d9 ff a4 31 24 10 a6 + +# Seed: +9c c9 a4 bf 8c c2 75 a6 b9 b1 35 10 31 91 10 91 +7a d8 53 24 c5 a4 34 5e 58 f1 fa 47 27 5e e5 92 +15 69 dc bc bd 72 36 70 cf 4a 24 eb cd 57 f5 7e +99 8c 4b bd 4a 95 67 9d 60 ba a0 ab e8 79 66 8a +2c b6 ed 0f b9 4e 4a + +# Encryption: +4c 41 b9 cb cc 6f a8 7f 23 f1 7a 36 d0 51 e7 78 +0a 07 06 56 ca e7 be ba 14 fa 91 c5 55 b8 58 8e +88 09 e7 d3 35 4e 7e f5 e0 fa ef e1 cf 39 2e 6f +da d4 04 4a ef 08 e3 3e 6f c2 01 c5 47 fd bd f7 +c7 3d 3b e0 96 ed 25 3f 9d f4 af 52 e1 3b 9a 19 +25 aa 73 93 a6 42 95 30 20 92 01 e5 5b 20 e5 1d +50 05 d0 6b 58 35 3b fa fc ee c3 7d 60 e1 ca 0d +9d dd d8 68 0b d0 a5 d6 92 e7 4f 2d bd fc e2 66 +02 + +# PKCS#1 v1.5 Encryption Example 13.18 +# ---------------------------------- + +# Message: +5f fe 82 e0 33 54 42 45 b8 49 62 d3 92 7c 2f a5 +99 72 ef 59 c2 37 a3 86 a5 1b d0 ba 1f 2c 1f 8e +45 b4 6a 05 ad 97 db 49 d3 ac c6 34 4f 1e da df +65 64 c2 8c e1 + +# Seed: +cc 23 59 bf d0 d5 7b ce bf 07 5b 87 a5 85 a9 bd +e6 59 3e b2 49 61 ef f1 98 7e 73 56 05 d4 e3 0e +97 19 37 f6 f3 f5 be 52 78 fd 47 6d c6 60 ee 07 +30 cd 07 e5 d1 f4 20 09 a3 33 31 2d 93 28 f3 b0 +08 5c 40 75 bc 70 9a 10 f1 + +# Encryption: +05 8b 50 e0 bc a6 b9 34 c0 1b f7 c3 3b b6 15 b7 +22 ea 41 80 7a 7d 2c 7c b3 d4 38 e2 8d be 33 3e +d6 d8 37 47 7a f8 4b b0 06 bb b1 0b 36 94 4f 15 +d4 f6 d2 8b 5e d2 49 d5 69 0c 08 37 a1 6e 15 7b +a8 80 22 74 10 1c d4 4e 7f ed 72 a7 59 81 c9 75 +66 bc 70 e5 55 97 02 bf 5b 62 fb 09 b2 13 60 56 +73 aa eb b7 fe 9b 1a e6 d8 04 03 a2 01 33 80 3e +1e d2 35 0b 8e 15 ff 01 9a 70 0f 2a be 87 d6 e7 +33 + +# PKCS#1 v1.5 Encryption Example 13.19 +# ---------------------------------- + +# Message: +22 63 3c c3 fe 7a 7b 4f 00 fa 99 9c 4f e0 d8 82 +c3 1b dc 0d 67 0c 0c c3 d2 88 96 1f be 63 72 e0 +e5 32 46 42 c7 b1 fa 85 2e 1b 4f 69 6f 12 f5 58 +66 + +# Seed: +3e df ca f4 88 71 d2 91 d5 b7 f7 72 3d 92 d9 51 +51 52 b6 bf 52 b8 23 69 9c 58 8f 75 f3 4e 37 95 +55 0d 07 81 18 e2 86 c9 6e 90 07 ae e1 54 f5 7c +e7 f1 d4 60 39 47 3a 4a 37 a9 b5 90 a3 7e ea 59 +94 7f e8 58 7c 95 69 88 bc b1 74 e9 7c + +# Encryption: +3d eb bc 6c fb 0e ed 87 16 6b cc d5 4c 75 97 ad +36 ca 0a c9 6c f1 66 76 e1 87 4b f5 f1 0a 0e c6 +9c 3b e2 25 96 78 ee a6 3a 18 08 d9 06 65 ff ce +9a f0 82 7e e6 29 ed d6 59 43 43 7f 8c a0 a6 71 +17 2c 52 1c c0 d1 dd 01 e2 2f 20 a6 c7 9c 42 7a +da 88 56 00 0c 4e 03 5d 9c 5e f2 e1 05 f2 c9 f6 +45 7d 9e e9 5b 43 bc 4b e3 29 4a 0e e1 d5 c8 33 +ae 91 07 8a ed 09 e7 92 bb 42 c2 5e 00 b0 87 e5 +61 + +# PKCS#1 v1.5 Encryption Example 13.20 +# ---------------------------------- + +# Message: +55 2b 38 4c 5e 51 74 f5 1f 38 0d 8b 53 e3 c8 97 +b4 8c 66 9a 9c 2d 11 98 5b 86 54 de 7f 76 d9 62 +39 6a 37 b9 53 41 f9 9d ec e4 af d7 1d 3c 84 e1 +28 7b 0f 0f 86 ee ff cf d9 7b a1 88 e3 79 9e + +# Seed: +2e 2f 3e 3f 46 d4 74 0c b2 6c bc 65 aa e2 af e4 +9d 0b e6 66 39 d0 db 10 df d6 af 60 64 46 f3 b7 +de 98 21 2f 86 17 4b df a5 b2 e2 35 85 07 45 3c +20 ad a6 9a 4f fe 0a 35 e1 2e fb ab 3b b4 4c + +# Encryption: +14 92 91 ee b5 36 fc 07 03 f7 bd f1 f0 31 a4 30 +cc 83 ad c4 3e 09 68 64 91 26 69 34 ef 37 ea ea +b1 1b c7 f3 91 49 ab 33 43 66 94 59 36 73 cc c6 +39 0b 52 9e 64 d3 42 e9 f2 1d 17 6d a2 1f a6 5a +bd 57 ee c6 0d de c7 d1 a0 93 db a3 76 44 5f 1b +cf e5 a6 aa ce 9f 13 42 af 39 db 8a d4 85 ba 22 +2d 39 12 62 28 fa ee b4 9b b3 b2 71 fd 38 e1 15 +25 d8 03 15 4e 74 08 4b 75 c3 db cd ff 2e 3d 10 +42 + +# ============================================= + +# Example 14: A 1536-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +be 0c a0 1f 9c 17 21 66 f9 12 39 1e 5d 58 dd c3 +0d 5d d0 27 9a 49 bb 31 2a 31 e4 c8 a6 6a 52 fb +4e 8b 67 42 fa ac b2 24 c3 03 9f 1e 19 8f 33 23 +b8 88 ba 0e 35 bb 94 c5 11 bd 22 b8 86 40 5a 71 +5e 40 9d e3 bc eb 4f c9 91 1b 0e 9c 3b 1e 42 e2 +57 d5 bb ea 07 22 b5 d5 dd 35 37 56 9d c7 56 06 +46 a7 50 b8 7e aa 6f 3a 40 5a 94 bf 2a da 72 b5 +0a 4b 01 87 bb 9d 00 ec 45 1d 50 a6 a9 1a 1e 2a +91 19 2a 7f d7 56 b9 00 14 1f e8 8f 96 e2 08 0d +fd d8 01 66 a7 bf 67 e3 71 44 d0 9e 3a f8 99 74 +e5 7c 72 b0 3a 2b 88 fd 29 95 25 2a ce 4f 30 e2 +e4 7c 28 18 05 72 40 53 6b 58 db 42 07 50 9e 59 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +be 0c a0 1f 9c 17 21 66 f9 12 39 1e 5d 58 dd c3 +0d 5d d0 27 9a 49 bb 31 2a 31 e4 c8 a6 6a 52 fb +4e 8b 67 42 fa ac b2 24 c3 03 9f 1e 19 8f 33 23 +b8 88 ba 0e 35 bb 94 c5 11 bd 22 b8 86 40 5a 71 +5e 40 9d e3 bc eb 4f c9 91 1b 0e 9c 3b 1e 42 e2 +57 d5 bb ea 07 22 b5 d5 dd 35 37 56 9d c7 56 06 +46 a7 50 b8 7e aa 6f 3a 40 5a 94 bf 2a da 72 b5 +0a 4b 01 87 bb 9d 00 ec 45 1d 50 a6 a9 1a 1e 2a +91 19 2a 7f d7 56 b9 00 14 1f e8 8f 96 e2 08 0d +fd d8 01 66 a7 bf 67 e3 71 44 d0 9e 3a f8 99 74 +e5 7c 72 b0 3a 2b 88 fd 29 95 25 2a ce 4f 30 e2 +e4 7c 28 18 05 72 40 53 6b 58 db 42 07 50 9e 59 + +# Public exponent: +01 00 01 + +# Exponent: +f3 7d 28 d6 1f 28 99 a5 c0 e0 a0 74 9d 13 89 38 +7c 64 c8 c3 58 a9 71 da d1 3c ff 85 c5 9a 62 dd +a7 bb c0 f7 e5 bd c6 5d ff 9d e9 c7 45 40 46 31 +75 81 48 16 8d fe 6a c0 a2 87 6a 56 05 3b ab 2a +2a 9f f2 72 79 4d d5 d8 13 9e ed 10 bc fb 4d f3 +30 20 d5 9e 30 48 fd 2f 0c 43 14 26 14 5e 36 a1 +d0 a6 bf ce 44 43 ef 3c 7e 31 d4 a9 2f b8 51 7a +49 f7 88 c3 b4 e1 37 39 5a 4b ee ea 63 e0 e0 ad +c3 22 4f 98 09 25 03 7d f6 f5 b2 6c 00 72 39 b4 +f0 1f 8a 9a 61 ea 0b 51 19 bc 9d 54 96 a9 5b 60 +ea 76 6c cb ad e0 37 e3 40 32 4f 25 f0 2e 72 45 +c2 36 ea e4 36 7a 64 68 a7 a0 93 8d 85 c0 a1 + +# Prime 1: +df cc 92 74 2c 48 d3 34 c6 6f ca a6 d8 a7 e4 22 +54 43 0f 80 a8 35 9e a2 3b 9a 83 b2 41 e4 7f 39 +9b 3f fe 3d ab 3f 15 be 8f a5 c9 e6 46 df f9 7c +cf 9b 43 17 61 07 80 ad 44 cb 1f bc ef bd 6e ba +05 5d 96 94 3c 02 47 e0 c8 76 78 eb 0b f7 6c 88 +76 c3 ab b9 ef 72 cf 01 8f 58 11 a6 be e0 4f 09 + +# Prime 2: +d9 64 e9 6e a6 fa 43 70 b5 91 ee 79 e7 e7 2e cc +21 81 53 78 7a 60 e2 f7 ae 94 fa 95 b9 bd 68 69 +d2 81 ac 3c cf b6 57 24 7c 58 3e af dc 13 d4 d7 +a7 d7 76 5e 44 67 df 76 b5 28 bf 94 bd 03 a3 ea +73 b8 1b e2 6c ca d9 89 b9 f0 77 28 da d5 3b 38 +ef 7f e9 eb e9 11 40 cb ad 17 dc 7e cb 1d 58 d1 + +# Prime exponent 1: +9e 79 f6 9b 5d 60 94 6f 22 b5 b7 03 3f 18 64 6c +0a cf 12 03 41 19 f7 23 5a a1 a7 f0 6a c8 ab 6e +d7 89 11 38 0a 33 b9 ea 1f 3e 7f 22 19 be 30 a5 +39 3d f0 dc 75 51 22 c5 8f 99 66 f8 1b ac 40 e4 +69 38 44 90 e3 8d 99 e8 8b 0b 99 c4 97 cc b5 86 +4c d3 72 9f 4f f8 34 ae 1e 1b 77 24 64 b5 e2 41 + +# Prime exponent 2: +3a 05 e9 18 13 91 30 76 e0 bf 76 7b 2b 1e 55 2b +3e b6 19 e5 4a 24 99 ef a9 b5 31 bc cc ba 75 27 +e9 7b 9a d1 10 4f 86 aa c2 55 7b 45 cc e3 ae 27 +71 30 dc f3 04 27 05 49 d5 c8 6e 79 f0 89 0c 33 +03 77 dc 59 6e d8 25 7f d1 15 11 78 e2 0f 8f a2 +fe a9 91 71 d9 df 35 00 27 ce fa 97 0c f7 64 41 + +# Coefficient: +18 b1 0d d7 3b 14 7d 86 b6 0c f7 fe bf 46 35 93 +c0 bd d6 bc 83 a8 39 57 3b 4b 3f e6 5c 0b 13 e7 +b6 94 b8 1a 56 57 21 0b e9 47 01 1d 8d 49 29 c1 +27 fd 2f 3e 31 06 c2 53 38 3b e6 35 41 d1 23 5b +d7 9c 57 2e 92 e2 36 34 28 20 98 be e9 4d 48 bd +62 8a 0e b2 1e d2 61 cf a3 5b 69 b9 77 70 e2 93 + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 14.1 +# ---------------------------------- + +# Message: +2b d6 e3 c1 de fd dd 5a 43 + +# Seed: +e7 84 d5 25 03 e6 29 1f 25 8e 44 2d b5 77 f9 91 +63 82 a0 d1 4c 7b 9d cc bd b6 07 af 01 f0 25 8f +dc 97 23 97 da 12 39 d4 44 9a 58 28 6e ce 20 08 +f7 18 f6 90 ce e7 3a 02 7f ab f8 4b df 7a ce 45 +f7 ed 2d 77 32 4c be e9 0e cc 6f 1e 7b 86 cc 29 +35 a4 7b a1 56 65 0b 42 fc 71 aa d0 70 99 a2 7e +97 fe 5a 3f 25 fe 13 48 e4 42 39 12 12 a5 cf 1b +44 5a 1e 70 19 1f fa 8f ca de 63 5d 2e 44 65 f5 +f9 13 c5 3e 33 b5 91 52 cd 8a 14 97 84 f2 7d 83 +18 28 af 2d 66 6a 5c 30 9b 56 d0 71 9c fd 80 73 +40 69 a2 3e 09 2d 83 15 39 9f 95 c4 0a d7 fd 0b +b5 f9 43 77 + +# Encryption: +85 ef 3e 47 76 77 bf 76 07 1a 27 bb c7 39 57 15 +cb 35 07 96 e4 4f 1b 52 a0 8e 90 5e 08 ff 12 56 +70 5a 9b f0 15 2e 87 2b dc 74 bb 1f 2f c8 63 1e +f8 81 2d 16 94 6a 30 b5 8f 44 64 d6 e7 b2 45 0b +e4 5b 48 cc ff 5d 8e cf 7a 00 b1 b7 8f c8 fa 54 +71 3d d6 96 a1 4a cb 68 00 c0 d3 b6 9a 0b 44 43 +77 fa 30 3a 7d 66 db 49 27 91 8a 4b fb 0f d4 93 +bf aa 01 6a eb ff 99 53 30 a6 dc b6 21 5d d3 bd +b3 5d 7c d6 1c cf 0e 9c cc bf 51 e9 ea 65 8e a3 +1d 12 43 44 4c 4b 72 ff f0 1a c9 3f 28 eb 7f 67 +c1 83 2e 56 8e d7 2f d9 57 d5 b4 fd 2f 00 b6 02 +31 71 b8 5a b0 ca a1 03 0e d3 e3 ed c9 50 31 45 + +# PKCS#1 v1.5 Encryption Example 14.2 +# ---------------------------------- + +# Message: +10 47 35 d9 ad 72 60 46 47 3d f4 b1 3b 2f 5f a2 +85 c3 d2 33 ec d4 61 70 58 2d d2 28 cd ee 46 4d +a5 09 5e 20 8c f8 fb ca 05 38 8b + +# Seed: +dc 6a 63 1e 29 75 45 d2 f6 fe 9c 69 a5 d3 06 a1 +09 16 d7 e7 ef 0d c9 53 f2 1b 6a 04 14 31 ec 8b +a5 ce 1c 13 87 43 fa ac 54 97 d6 99 f2 ff 1d 4a +44 a3 e0 63 7c c5 e5 e6 38 cd 73 67 7d 09 af ee +3e c9 fe 80 52 94 7a 73 33 4c 32 70 47 28 56 f3 +07 24 3a c5 8b f8 63 80 74 66 7d 7f 7c 18 e3 ab +32 7e a3 fc 78 91 f1 c5 8a b4 7e 4f fa 6e 7d 90 +11 a3 3d 9b 40 a2 d7 89 ee 42 21 25 62 30 ca 8a +61 81 1b 09 72 cf d9 86 01 75 26 18 1d 24 ee bb +32 cc + +# Encryption: +92 1d 2b 02 6d 6b 7e 22 20 1d e7 7f bf 67 99 90 +f9 af f4 ea 7f e7 ce 45 02 21 5f 9e 7a a4 18 b8 +5f 72 ea db 6b 69 42 bb 08 a0 8b e7 da 66 19 aa +5f 1d 2f f9 61 c9 dc 2c 34 1a e3 2a 25 4f de ab +a2 f6 45 0a c4 47 4b 62 74 f0 c3 46 f2 6d a4 ed +55 5a 8c 95 11 89 dc 83 69 f3 4d 76 d8 37 d6 f3 +8a 95 18 a6 27 1c 5b 56 34 62 25 a5 ab 8d a6 03 +2a 59 30 fd 5b 77 72 9d e6 32 e1 75 2f c7 2a 0c +34 ae ce 25 65 7b 28 1b e8 93 2c 56 50 c9 82 fa +14 5f de 0b cd d4 8a 73 aa 02 88 b4 de 46 11 33 +f2 7d 51 e3 86 01 6a 72 72 6a 9e de 1d 32 df c7 +e6 f9 78 0c 04 eb 70 ff ff c2 68 82 95 66 73 33 + +# PKCS#1 v1.5 Encryption Example 14.3 +# ---------------------------------- + +# Message: +31 7e 6f 5e 17 50 0f e9 4f df f2 84 bb e5 03 01 +04 4d 14 22 d3 ca 70 05 98 + +# Seed: +46 6d 53 c8 d0 bb 9e d4 60 ca a6 3d 79 bf b8 77 +bc 4e a3 45 ca b4 35 7e 63 9a 95 dc ae 37 9d dc +ea 5d 64 fe e9 9f b6 f7 5f f2 4e b7 4d 44 03 44 +d1 47 e4 33 14 a0 f8 9f 8b 96 14 82 15 36 8e b8 +65 1f 6d 3c a0 d0 8d 0b 4c 73 e6 d1 a7 68 40 98 +26 d4 3c 2f 81 f3 08 40 60 5c 43 d0 fe 67 1d 3f +02 4c 70 d0 b8 99 23 cf 90 4e 39 97 99 62 cd 51 +5c 16 74 29 2a a3 0d ac 70 0d b4 eb 7e 63 d5 6f +df 08 c2 24 70 f2 43 86 19 45 d0 0f a4 e2 79 90 +21 2c fe d4 28 5d f1 ed da 4b 0a ec 91 35 59 f5 +9d 12 55 90 + +# Encryption: +14 1f ca 68 dd 2e 4d 1d e5 08 6d bb 78 5f f4 7d +81 e3 9c 31 1d 91 7a 99 39 a6 ff 5b 13 43 9c a9 +56 c9 74 2b cf e4 50 b5 bd 03 5b 54 1f ab 30 7f +24 fb fb 3f 8b 90 21 5b 56 04 67 6e 56 96 f3 ba +95 fd b8 d0 90 a6 c2 4a 29 d9 90 fb ff 1d a2 02 +81 42 55 8f 0a d7 53 43 c7 2f 38 82 3d b7 66 7b +05 e1 6b 51 92 b9 33 60 07 f7 58 10 6c 32 8b d4 +76 11 8d f8 2a d0 75 48 a7 26 92 1f b2 e1 92 b4 +3c 8c 30 cc 9b 84 34 63 0e 27 fd 8b 23 ef 8d 8f +22 be 7f 73 ae cd cb 2b 1e c5 53 9d 5f bb 2c ff +9e d5 e7 f1 9b 49 18 3d 22 1d fd 53 7d 4f 37 03 +2e f3 2f 63 b6 ff 74 ee 24 a0 96 cf 45 59 27 09 + +# PKCS#1 v1.5 Encryption Example 14.4 +# ---------------------------------- + +# Message: +90 96 3d da b3 78 91 e7 28 8b 53 be 5d 9d c5 67 +b1 a0 7a 15 66 c2 af dd d7 72 73 24 ba + +# Seed: +a4 9f 12 15 17 5b a0 4c 27 4a bc 05 1f 0c 17 a0 +8a 63 64 89 43 db 2e 8c 76 22 bc bb 1d cc 56 7e +be 6a dd 8c 44 48 16 c9 d4 36 ee 93 ce fe 23 ec +41 dd fc b0 a4 03 bb 6d bf f0 ae 5d 6f cd d7 64 +da c1 a7 2a 48 4f 36 47 1f 4f 3b d7 25 b2 db 5a +fa 6a cf 53 0e 4e 4e 86 b4 fd a8 78 20 47 87 1c +b0 55 ad 68 c8 41 de 54 5a 55 40 c8 cc 12 e7 e3 +f1 58 14 a0 03 9a 81 03 4b de 9c 68 ae 22 85 e6 +16 b7 b5 55 5f 98 c6 13 ce 2e f6 66 a0 22 46 5c +63 67 d0 bd a4 0c 12 e9 41 f6 99 8a 14 a2 b5 e3 + +# Encryption: +8a d5 bf 78 23 2a a3 6f b7 83 58 3e 71 bc 13 93 +03 7d 13 e7 74 54 a9 dc 11 11 43 4e 75 dd 80 20 +46 ba b4 20 25 42 0c 63 96 1e a0 06 26 57 ca 50 +65 de b6 53 ac 78 eb 64 98 cf 14 d1 70 4c ec 59 +11 69 60 8d b0 1f c9 3d 0d 68 e6 28 01 b4 65 a3 +87 a9 c7 2f 7e b3 5b 0b a5 3a 5e fa 98 c9 f0 cb +7c 7c ba 18 04 cd 70 1d 02 97 b6 60 05 ae 25 ec +3b 6c d4 cf 31 94 a3 fa 65 d9 8c 4b 95 33 30 79 +0e fd e7 4f a2 75 d2 a7 9d 33 10 a5 bc c2 c8 1c +91 fc 25 56 2c a9 39 f8 d9 c1 75 ed f4 b0 76 73 +d5 39 24 e2 7b 15 52 88 1c 10 83 19 23 71 5d 14 +9f 1f 31 9e 38 e9 1d fa 56 6c 54 53 ba cc 14 8b + +# PKCS#1 v1.5 Encryption Example 14.5 +# ---------------------------------- + +# Message: +3d 81 02 1f f6 47 33 37 e0 4b 92 + +# Seed: +9b 70 29 73 13 77 e8 26 97 fa 56 b0 86 ce 49 d3 +c4 b1 54 9d e8 1e 3e 99 e1 6c d9 72 29 7a 56 0f +f4 83 f2 ef 5b 71 b0 0f c6 84 74 4f 22 4e 85 7e +6d 72 39 f1 56 d7 b6 10 2f 23 04 f8 a5 50 50 b3 +75 6c 54 8f 6e a2 6e a6 f7 39 4d 2b b3 79 33 35 +84 e3 b4 81 d0 73 c0 a5 8a 0a d7 87 ad b4 80 e1 +f2 0a 1a 59 0e 03 1e 6b 2b b7 f3 6a 93 61 0d df +70 83 a5 07 68 c9 98 62 3f 6e 64 37 6a 29 b4 a4 +18 03 2d 27 39 bd 4e 74 7d df c7 7f e3 cf 27 93 +a2 9b c7 67 bf ac c7 13 e5 f1 0e 53 1b 4c 71 89 +97 b9 bb 6b 65 15 e0 71 13 28 89 74 7e 54 6b 13 +46 8d + +# Encryption: +1b 88 4b 06 7d 0b b1 59 7f 5f ab 93 30 95 75 5a +53 0d 9d 04 e2 75 4a 57 97 ff ff 5e f9 ce f1 89 +54 99 98 23 00 50 3b 3f eb cb aa 09 d3 6b 7d ac +c3 0d f3 c8 68 f0 1a 5f 17 ed 4a 72 a8 5b 6a dc +80 a2 6a 1b 81 97 6b 39 3c ba 9b 0c 82 cb 1e 2c +58 3a b6 f3 14 ed a2 9a 43 32 21 b6 e3 ed 53 51 +53 74 bb cd 2b 96 f5 cb 5b d5 81 5d 1a 5d cb f0 +80 d2 d3 7c b9 6c 4d 96 1d c4 7e 13 0d b7 b8 d0 +18 2e 33 69 de f4 c0 f6 c4 2c 6c 20 53 1a f1 a1 +90 36 de f0 8d 4b ac a7 1b 99 af 3c 4e 1e d5 27 +d5 1f 37 d0 ee 1e a2 c8 b8 eb f4 fd 52 79 85 1d +c3 20 e7 42 00 8e 04 04 4d 0d a0 64 36 61 3d 1b + +# PKCS#1 v1.5 Encryption Example 14.6 +# ---------------------------------- + +# Message: +5c 74 5d d4 a8 c5 92 93 4e d1 5e 22 fa 9d ec 4a +4d c2 0a 9f + +# Seed: +0e 6a bb 82 9a 3b 16 d0 8b 0b d4 3e b9 5c 79 1a +f2 a3 39 12 ea 83 3e e6 89 3e d5 ad 3e e7 44 c8 +b2 dd 28 fc ee 80 8d 3f 01 49 58 25 be 0f e6 37 +32 07 a8 78 d4 a5 25 ea 72 cf b0 bb 58 a2 67 76 +fb 39 ee bd 33 5f 04 cf 71 86 be 61 c5 63 5d 95 +e5 60 ed df d4 5d d8 6a 4e 67 0d 33 56 8d 83 d2 +ca 20 3e d2 8d 90 e4 8b 06 4d 09 a7 5f 82 8d ea +cd 5b 37 ef cf 78 4f b1 1b 17 d6 d9 f2 31 52 24 +f8 e7 63 79 1b ac 6c f4 6e 1c 23 b0 b0 25 2c 19 +ed f0 40 d3 5f 59 25 53 26 5b 88 6b 29 ca 56 eb +c5 38 63 71 41 4d 82 a3 40 + +# Encryption: +2b 0a 43 b3 cd c9 9d 6c fc 74 da 2a 86 ec d7 d5 +76 24 75 d1 43 e5 48 6f a9 cb eb bf 27 d8 e4 14 +1e f7 2b 6d 4f 13 f6 64 b3 d2 e9 ec 32 22 7c 1a +d5 b7 6c 0d 1b ef bd 65 89 68 c7 db 14 95 23 82 +49 bc d9 5e 75 40 25 4e 65 74 98 23 b8 a3 4b f6 +a1 41 07 21 df 34 f3 c8 d5 79 f3 6a ed 9e 0b ac +23 1e 54 c2 7f 76 73 19 7d 19 f5 1c e6 ac bb cb +7b 1a 55 e3 8e de be ed 34 61 07 3e 80 c7 9a 4f +c3 09 31 30 69 6b ff f2 bb cb 74 90 5f 2d 34 44 +33 80 57 fd fa cb c4 db 81 93 5b 29 e9 9e 55 cc +c1 d4 8d 89 e9 dc 4a 63 a0 11 a6 23 32 cf 57 02 +62 a0 63 59 cc 36 c0 5a 6f e1 8a fb 78 32 b3 2e + +# PKCS#1 v1.5 Encryption Example 14.7 +# ---------------------------------- + +# Message: +b0 e7 7f 42 c1 a1 e3 f4 15 57 23 a9 0d b8 8e b1 +53 cb 3d 3a 28 ed df 25 9c 47 05 6a 47 0c 91 5e +c9 55 f8 31 89 f7 1a ea cd d5 5c 33 5f + +# Seed: +fb 36 01 10 5c aa 9a 2f dd 6d d6 c5 74 6f 4f ca +fe f4 41 bc b0 fb 8a 2c c0 3d 0b 57 34 9f 93 21 +af 9d 99 84 e6 4e 2e c4 85 c9 ad 75 5f 14 0c 0b +66 db 1c fc 26 69 1c 26 77 31 d1 a3 af e6 87 20 +2a 96 77 e4 2e 84 4d 47 7b 75 bc bb 8c 97 d9 9f +cf 72 b3 fb 6d 34 9f a9 c4 76 61 91 47 21 7a 04 +dc 06 aa 3c 3c 17 64 95 38 0c b9 2c 0a 7e 09 7b +4b 4c 5f fe 04 63 1a b1 d1 bf ea 03 67 86 50 c8 +5c 17 0f a4 a1 d6 4a 4c 13 5e 61 48 14 90 b6 2b + +# Encryption: +a4 bd d4 92 fe c7 9c 3a 79 09 3a 44 33 42 72 d9 +d1 7f 54 3d 02 02 c3 9e 40 8b fb 39 36 6b e2 de +61 df 50 ac 45 8c ae dd ef fb 69 e2 13 ca 92 b7 +49 53 66 34 7e de 73 3f f3 99 ae c7 96 c3 c3 b1 +df 34 9f 01 1d a0 1f ee 7d 21 c1 c2 61 84 3d e8 +82 08 56 0c 0e 89 84 b9 52 23 ea 37 31 db 91 c5 +93 7a 79 b0 db 93 87 59 1c e3 2e c7 f5 83 e6 00 +f5 24 44 df a7 67 1c e8 27 38 98 fb bc a3 a4 aa +68 32 cb b3 54 3a be 96 47 e5 f8 c1 37 72 82 52 +ce 54 40 fc e1 0e 4d 4e f7 5d 56 b8 14 d5 19 64 +44 41 41 1c 10 a2 a1 4c 35 04 72 82 7c 99 ea 3e +e5 fd a3 88 0f 34 1d ca 8d 3d 3a 4e 5e 05 ba 42 + +# PKCS#1 v1.5 Encryption Example 14.8 +# ---------------------------------- + +# Message: +b8 7f 04 b3 35 0e 12 63 da a3 f9 40 5e 6f d3 d2 +5d 8e fa 13 25 56 a4 95 71 f5 70 8a 42 52 7a f3 +1d b0 1e df 79 82 0f 93 26 64 5f b1 + +# Seed: +ec 8d 01 4d 6e b8 d0 23 9a 97 73 bd d3 20 bf b3 +f2 ee 8f c2 7d 5f dd 91 f3 f3 90 5d c8 a4 c5 ff +13 52 9a ee e4 61 85 4c cc d4 e0 9b 62 4a fa 64 +7a 7c 04 81 4e b1 e5 7b a1 4d f4 c7 95 b4 2e 84 +c4 d0 86 29 24 5d ac bb ed 27 39 9a 72 5a 94 8f +3b a2 f8 b6 4d 26 02 dd 0d 5f 55 cb 23 ea af fb +3a 66 50 8e 4a 68 9a d9 ee e6 44 e6 a2 6d 43 8f +36 63 fe a9 bd 03 12 bb 0e 7e 5a 6d ee 04 bb e8 +a0 74 5a 73 d5 ac 89 fa a0 96 a5 2e d3 04 6d 77 +de + +# Encryption: +77 5d c3 24 fe 9d 5e 05 ad 01 50 13 d6 5f 0e ba +0d cd 52 ff 9d fc 17 95 ea 93 d0 f4 33 57 98 96 +86 fe 3f 8b 04 62 23 bb a5 c7 84 9a ca c3 12 35 +43 43 26 16 c3 10 3a c2 ba 8d b0 a1 d2 99 40 bb +a2 62 47 0e 5e 53 be 60 e0 eb 72 4d 07 cd 91 2a +ef bb 87 fb 51 98 0e 9e 1a c1 94 da 31 92 95 41 +ca 43 22 4b 15 2b e6 f2 df 6c 5f 04 42 b4 f4 d2 +cc 2f b0 27 39 d4 85 a0 11 62 bc 8d bb ad 14 76 +eb 06 e2 45 ab 36 c4 c7 2d 3f 36 07 d0 50 84 a0 +f6 b7 2d c8 ba c3 46 bd 19 09 1b 02 f5 98 2c 91 +45 7c 7b 10 f4 47 2b 57 18 45 24 21 4b 23 82 5b +59 f4 34 cc 48 a2 b8 54 ca b5 0f f7 9e 59 09 1c + +# PKCS#1 v1.5 Encryption Example 14.9 +# ---------------------------------- + +# Message: +e1 95 a0 36 a5 30 e1 c2 a9 d7 a1 03 35 8d c2 bd +25 b1 01 bf 70 44 50 ab 8e 50 62 cb 63 df 56 10 +35 + +# Seed: +0e f8 81 de fc 45 ad 3f 3e 58 b1 10 5e 49 b4 23 +ab 89 12 4a 65 b5 2c fd 81 cf d5 42 b9 1e 7c 4c +1a 60 71 a2 cf 12 b4 82 7e d5 d1 9c ba f8 fe ea +54 bb 3d 73 85 7e e8 7c 71 5c 71 b9 ed 1c 07 c3 +af d9 0f ce 40 44 8b b5 7e 35 24 d0 38 80 98 39 +e3 6a 4f 55 44 c3 e1 81 e8 c2 e2 93 cd 57 54 c8 +65 74 ad e6 df ce 0a b3 4a 80 b4 d4 8a 9d 42 e7 +11 5d 8c bc b1 fa 28 c8 a2 65 01 db 7d 0b b4 96 +d0 1d d6 92 65 a0 26 e1 a9 7e 9d 3a 1a 65 a8 aa +8e c2 df 06 34 e6 f2 65 1e f4 35 40 + +# Encryption: +1a d7 7a 00 7c a4 37 ab d0 15 9e d4 b0 b6 81 54 +16 f9 f0 9d 1b 12 15 fb 7c ff 11 52 97 60 1a 88 +30 f2 09 17 86 35 63 85 3e d7 8e 9c 3d 7b a4 c9 +7a 05 cf 19 dd 32 92 48 47 1a 47 03 a4 65 17 8b +85 d4 ec d5 42 24 12 98 c2 fe cd 41 3e 23 a7 0c +8a 5d 47 c2 0e 31 c2 da be 3c 82 a9 54 50 27 27 +49 ae 2e bb 89 98 5d 00 b6 3d ed d9 59 6d 05 16 +d1 2a 78 c3 74 b7 ed dc 7d ce e8 e4 fd d1 6c 1d +fa bf f7 ff d4 c1 fd 61 ce 04 be 8e 49 75 c5 cd +71 e2 cb 0e 54 1b 84 61 bb 81 fb 28 cc e7 73 65 +3e 8b 16 b2 8a 8c 20 74 28 89 5f 28 53 55 87 a5 +c9 9d 46 ba 4d f9 ae 08 50 18 51 3d 69 ab a3 f6 + +# PKCS#1 v1.5 Encryption Example 14.10 +# ---------------------------------- + +# Message: +04 2a 39 22 aa 87 1e ea 0d 78 42 2c e7 85 66 ab +bb 5b 08 c2 dd f1 ee 30 cf + +# Seed: +5a e8 51 14 b0 02 7a 23 c7 2b db 46 ae 7b b8 87 +be c5 ba d7 a9 88 4e 93 f6 f4 fd 0b c9 38 bc 72 +41 0c ce 96 a1 4f 4d e1 99 19 77 35 05 1e fc dc +c1 96 f3 ad bf aa 06 3c b3 f7 a2 34 c6 cf 99 d7 +0f bb 7e 35 b6 ae c6 64 14 66 93 91 e3 cb e7 21 +ec 99 1a 1e 5d fb b0 38 f2 70 36 85 93 74 9b 20 +8d 08 9a ae e2 ef 35 c3 da f6 23 8b 5f e4 2d 13 +dd e4 07 df 14 f2 d6 18 c9 79 c9 7d 2d e0 29 33 +b5 7f e8 81 22 04 86 2b 2f 1d ee 98 3f 24 c2 c5 +96 ea 66 8e 63 7d 0a 6a e6 dc 52 65 27 69 94 e7 +e4 f0 2b 6e + +# Encryption: +12 44 de 88 0e 0f 78 52 e9 96 95 9d 76 2f ca d9 +15 65 a4 d0 ad 3b c5 27 50 d4 a0 44 0f 0b 5c 65 +1a a0 e6 f4 92 06 1b 2c 86 24 c5 2e de 68 58 fa +25 18 ae 8e 8b 11 65 58 b2 c8 07 6c 17 ae 78 3d +8d b2 5f 0d 8f b1 f2 75 8a 82 ab 97 1f a7 28 3e +f0 74 9a 37 be 28 93 f8 94 37 fb 8e a9 00 72 b5 +85 5a 26 08 fc 54 2f 5d 2e 0c b5 43 f4 fa c5 28 +f9 43 52 d0 16 40 fc 2c 53 1b 79 81 0c 00 77 7b +c9 e1 0d d9 ea 99 96 e7 40 87 fa dc b7 1a a1 43 +00 67 65 71 61 48 82 94 3f 4a 56 14 12 c0 54 67 +dc a6 6c a4 9f 82 29 35 18 23 db 8a 6b 9f 80 3d +70 9c 11 87 ed 74 10 cf 91 00 15 59 5c ea b6 3e + +# PKCS#1 v1.5 Encryption Example 14.11 +# ---------------------------------- + +# Message: +f3 1d 3d 0c 30 fd 65 d7 b9 8b 70 99 44 78 2e 20 +52 5c a7 c1 f4 2d 5d 03 a0 f6 d2 75 9d f1 91 9e +ea 82 f8 0f 10 00 fd 5c f8 59 df 59 87 1b ac 82 +dd 90 76 cf + +# Seed: +04 4b c3 77 e8 58 9f a5 af 1c 17 34 7d 50 e0 cb +bf 90 15 76 f2 41 de 69 0c 88 16 c1 29 cd 9f 2f +b0 83 1a 01 7b ec 30 b8 2b 68 f6 98 31 1a f6 e0 +77 72 bc d8 98 fa 0c 27 f6 2a fd e8 95 89 77 84 +46 25 55 2d 9b cb 5a 81 aa 3d 74 15 b2 42 a0 3b +12 fc 1d 3f e2 d2 ce 6e 5f 71 c4 a4 a4 c7 ca 83 +e0 65 6f 50 02 ac 36 d8 d0 2b 69 ae 65 73 44 98 +f1 31 95 2c ea 48 1f a2 c2 96 5b 6e f0 51 7e de +50 dd b0 9b 3e a7 02 6d 06 + +# Encryption: +86 f6 6f 0c 25 05 85 06 59 43 de 2f 71 1f ae 4f +f2 62 70 0e 0d 33 06 a2 4c 94 30 f8 7c fd 93 de +f4 c3 44 7c c7 21 0f d9 4a 14 33 62 f4 f9 45 c6 +db e2 80 bd ef 5d 14 f7 5e b7 bb 31 32 0b cb d0 +d8 8f 0c cf 2c 95 a7 4c b4 58 c6 27 2b 58 bf 74 +30 93 c4 bb a2 d7 be e9 ea 2d d3 0c f7 2f e2 93 +c9 0c 97 43 0a 04 7b 17 26 63 91 c5 1f 5c 39 8b +a3 df 8c b7 4b a3 e3 72 f9 55 5c cc 97 d6 db 76 +14 ea 06 d5 c4 8c 1c 60 06 13 3d 0e 9d 69 95 79 +93 85 92 0a d8 af c3 de ad f6 31 ce cc 55 9c af +f4 95 b0 8d 68 3f b2 2a a6 97 d7 1c 69 6e 46 b1 +bf 4f d7 6b 8d 0b 39 f1 79 bf 66 84 1b bb 97 07 + +# PKCS#1 v1.5 Encryption Example 14.12 +# ---------------------------------- + +# Message: +6a 35 55 57 9d ad 03 94 35 43 ff 74 e1 74 7c 25 +7a 83 d3 52 94 c2 53 93 83 e2 35 de 69 + +# Seed: +5d 92 43 4e db d4 f5 bd 27 19 71 71 f8 53 ce b7 +26 30 30 83 ad 45 67 a1 d7 c6 10 4d 19 2b 9b cc +df d0 da ed a2 74 e5 cd fb 3d 0c 5d 19 c9 68 25 +81 ec 7a dc 1a 87 e0 81 51 41 5d 5a 9a dc 1a f4 +50 b1 ba 88 d0 ef 32 ac 2d 1f 8a e3 45 95 28 14 +75 3a f3 8e 12 63 5c ff 8c 09 21 59 b4 e7 5d ee +a1 98 3e d3 d2 d9 ec 2f e7 b9 a2 e1 6a 14 1e 81 +8b 84 cd 9b 71 c1 29 a8 b3 c6 db 62 02 32 dc 03 +a2 40 1f 73 1f f8 a6 3d a4 58 a7 d8 78 90 56 25 +ae e1 fc 09 4d fb 07 b4 57 5a 7f 0a ad 23 3e 82 + +# Encryption: +93 10 27 2d 12 4b c5 cd b7 21 88 98 40 aa 77 15 +e7 67 32 17 00 cb 39 b2 b8 a5 a8 2a e3 f0 2e b9 +67 e8 db 46 84 3b c1 bf 62 ed 8b d2 ab e8 14 34 +49 7f 99 00 64 02 53 98 2d 37 2b 2b f7 c1 b0 9b +d5 01 96 74 a8 34 fb bd ff 35 68 a2 82 4a ed 4a +80 48 d2 b8 61 36 27 75 bd 5f 0d 63 b3 48 36 3d +13 78 69 1f 5d d1 d7 96 10 74 ed 95 fc 90 07 bd +5f 5c 29 23 c1 7c 42 90 4e 2b f9 d2 48 77 9f df +b2 03 97 38 41 a1 12 90 c7 e9 e9 35 6d 4e ab 17 +0e 43 1b fe 45 4a 88 01 0d 9a ff 33 70 0c ee 55 +c7 04 c8 2a 7f fb 15 e2 53 ef 84 f4 01 9e 12 43 +8f 7c 73 86 dc 53 5b 19 ca 86 af 71 d4 77 60 8e + +# PKCS#1 v1.5 Encryption Example 14.13 +# ---------------------------------- + +# Message: +cb 79 af 5a ea fd f2 ba d2 1d fe 62 92 66 42 cb +a8 04 ec 7f d0 ea 5d 54 08 ac e9 ed ff 28 e7 e8 +df ff 6d f3 83 af 14 40 21 46 04 76 c0 c8 2c + +# Seed: +5f ce a2 57 cf a9 2c 84 f0 b8 93 7d 17 3f ae cf +75 03 ab 16 2e 0b ae ef 7e 4c 51 1f 3e 32 a3 24 +ed 40 e2 42 a8 52 ba 57 89 5b 7c fe 4d 61 79 61 +e0 36 f6 63 e0 22 8a 29 cd 1a 95 ac ac 08 a2 55 +26 d1 eb ff 0a b3 f0 33 ed bf 1a e2 76 a8 d2 36 +73 6c c7 af 51 b5 d2 bd c8 3d cc 7d 7d 3b f5 b8 +22 af 2e ff ed 7e fc b6 17 e0 83 e5 1b e9 94 ae +d6 56 9b 23 83 b9 41 ae e5 94 c7 b0 12 e6 75 1c +37 b7 a5 4e 2a 19 18 24 a1 30 d5 5c f8 45 + +# Encryption: +11 fa 81 9d 3a 63 88 04 ee f1 d9 56 0a 11 f5 23 +0a 0b ad fd 66 eb 68 4e 7d 69 df a2 89 8c 8e 0b +6e 04 af 8e fc 70 61 08 1e c5 9e 45 85 76 42 e8 +b2 00 41 af 50 8d 9d 4e 28 82 20 f9 fd 38 9d e8 +b2 91 24 ce 74 7e b6 8e 2e aa 8c 8f 6f b4 93 f6 +11 ac 09 b7 23 09 5d 07 ee d9 24 f6 ab 8e 09 ff +93 c5 51 6d 1f 0e bf 62 c5 f0 22 f5 bb 4f 4c b5 +b8 f5 d4 87 a1 7d f7 d0 12 d7 04 35 7a bf 17 48 +67 ce 40 cd c5 50 11 b0 71 39 be a4 5c a0 e5 81 +78 0d e6 54 17 cc 83 5f f2 69 84 fd 0f eb a1 87 +69 c3 94 a2 e4 85 02 3e 31 d3 b0 a8 88 a7 b1 4c +78 1d d8 5b ab 40 86 74 f5 f5 7e 4b 76 3d 84 35 + +# PKCS#1 v1.5 Encryption Example 14.14 +# ---------------------------------- + +# Message: +d1 62 33 fc 77 5c 31 9f 15 7a a2 00 47 6c d6 ed +64 a1 ea + +# Seed: +bb 33 b2 2b 5f 46 79 4b e8 3e 6a ff 34 a0 e4 11 +d1 f3 f4 b8 da f9 b5 85 87 24 ef fd b9 69 c9 55 +25 c6 2d c4 4b b2 b0 83 38 60 03 05 4b bd 36 66 +b7 82 82 60 6f e6 ea 17 27 31 be e1 16 72 d6 01 +de 32 42 3d 83 f4 63 cc 29 30 f5 fb 79 da 15 34 +c4 15 c9 65 82 75 65 94 a9 99 b2 26 35 42 48 a0 +9f 14 1c ae cf 88 83 90 78 f7 7f 40 bd 48 51 34 +9c 1f c7 5e 1e ce 6f d6 96 6b c9 c9 d5 ec 12 09 +6e d5 04 35 46 85 9e 4f 95 7d 31 88 e1 d9 06 0b +59 c1 f7 f6 2e fb fe 82 5d da 45 35 3e 6f d4 fa +ba c9 83 f9 44 f4 c2 c7 9c bb + +# Encryption: +10 c2 0c 0c 71 b1 1b be ce 14 c8 14 83 dc fa 73 +0c 23 d4 dd 61 b8 75 5b 39 94 9d fd 4a 3c 50 33 +21 60 ee c6 f7 71 0e 09 c7 a9 7a f9 3f 70 44 b9 +2f 41 d0 9f a3 e6 c6 ce 1f 64 11 48 4e d4 75 40 +a1 b5 9e 23 c1 93 34 b6 6d 68 20 c2 d4 4d b0 f6 +aa f8 5a a2 7f 53 a4 1f 85 6b f6 a5 91 36 59 86 +9b a4 ab dd ec be 87 41 3a c9 5b e6 40 09 59 3b +5c a2 d0 78 3a 16 f6 08 66 57 55 24 53 93 fc 14 +4f e3 ea 5e 9a ac 9f 1f 99 1a 92 85 38 b4 69 97 +d3 06 3c c1 a6 9a dc 19 2a 40 c7 6f 92 d4 7a 05 +80 e3 c0 21 20 02 3e ce 70 32 80 7b 7c 09 13 43 +aa 87 3f 6a 4d dd e4 3f b2 dc c3 79 ae ee f6 54 + +# PKCS#1 v1.5 Encryption Example 14.15 +# ---------------------------------- + +# Message: +d2 f3 c2 e6 f4 3b 0f c9 fc 22 93 b8 45 88 e6 61 +15 + +# Seed: +b9 81 64 89 52 5c d0 26 15 6f b4 e8 a4 a8 f3 4a +ea 8a 3a a1 a6 34 cc cb 32 58 91 8f e8 5c b8 d4 +aa 02 a5 28 52 a8 94 1d 3e a6 c0 48 b5 8c c6 c7 +56 85 67 56 25 e5 e4 dd 7d f9 3b 8a ce c0 79 67 +0b 49 f3 dc 6e 07 63 ed 4c 8e 2d 0e e9 b5 ca 5b +b6 2d e0 06 91 98 38 e4 b6 9b a1 05 d4 c5 a4 cc +6d ca 67 b1 21 93 a0 32 b6 92 73 96 44 cc cf 72 +3f 9f 69 e4 8b 94 c0 bd ce 5a a3 5f 75 dc 53 92 +7b 81 e3 42 ce 72 c6 b6 5c f7 5e ae ca c5 fe 0d +ea 93 88 5b a4 20 af 99 32 d8 4c a4 b5 0e 07 e3 +28 ec 5f 81 6d 2d 86 96 b2 0d f7 5f + +# Encryption: +80 f1 df 25 f3 6f 31 4b 98 2c 9c 8a af c0 b8 a1 +a2 f1 74 ab b2 98 08 69 c2 9d 19 be 1d 2d 93 b4 +fb 42 99 90 6c 35 7f dd 40 e8 9a 19 54 92 a9 79 +76 61 f0 5d 38 71 d1 bd 0a 5c 45 d8 f9 b0 fe e5 +65 b0 00 4f f5 af c5 a6 f8 9a d6 03 e8 22 83 57 +0b db 4c 6e 0c fc 31 3e 4e 66 5a 94 34 b3 2f cc +77 3d 6e da bc e8 5f e7 c8 0f 03 30 2a 84 e2 08 +b5 bd 0a ad 91 ce 62 fb 8c 2b f5 4b a6 6f 7e 8d +00 21 92 16 29 20 a4 6e 36 de a5 66 1f dd 75 81 +53 56 40 74 b8 55 9f 88 93 62 42 fc 09 98 14 8f +19 eb 50 fc 11 fb 24 a7 ed 8c 83 49 65 8f e9 d3 +1e 62 74 d4 5d 6f 2b 60 9b b5 cc d1 7e 28 4c 99 + +# PKCS#1 v1.5 Encryption Example 14.16 +# ---------------------------------- + +# Message: +21 ee 58 12 e3 24 6d ab 9c 3c 25 9b 21 37 d6 5f +98 a0 5e 57 40 46 5c a2 2c 69 34 97 00 a4 2c be +4f fb 39 3f e2 81 99 33 9c 51 03 1c d3 b2 2f 2f +0a 83 + +# Seed: +e9 de 5b d3 55 e6 af f1 9f a1 1a 2d 0d 3e dc 3f +64 69 bd 3c 75 72 06 d6 6b 3f 09 90 8f f6 18 af +48 01 ac 77 b5 2c de 03 d4 ae 74 9d 02 15 5e 5c +70 fc 99 5f 48 76 72 d2 80 63 58 55 db 4b 64 a2 +26 09 b0 c1 60 67 16 3c 51 90 42 05 7c b3 67 12 +c7 c2 fe fe d1 1f 73 c2 8b db 9d 25 f0 63 6a 4c +aa 11 26 9e 5f e6 5a 2b 17 56 86 a1 5f 1e 48 d2 +8d 34 5d d9 a1 b2 90 0a 24 f9 dd da 3d f3 a6 9f +fb 9c f5 04 5a c4 a1 93 ae 90 2f + +# Encryption: +7d 8c 53 1d 4d 35 49 e0 bd 2e e1 62 b6 82 53 9d +a6 17 22 b8 8e cf 8c 7d f6 d6 b8 1f ef 50 18 bc +4e a1 0a 7e 1a 4e aa 02 15 d9 b3 cd f4 13 47 92 +9e ac 27 48 eb d7 79 94 5c 9b c4 61 dc 51 f4 8d +f6 52 75 53 f0 70 37 e5 33 ce b1 34 8a 46 a7 ea +79 7d 85 a2 6a 9f 44 c5 88 69 99 6e f1 14 69 bc +c1 0b 75 6c 02 d5 c0 e6 18 83 68 5c c3 7d 75 8d +fd e4 c9 b7 35 4e 3b 4f 31 6c a7 f7 fd e6 59 c3 +fd 5e 33 2e 1b 63 92 a2 92 9e 13 17 66 ce 9b a1 +d9 71 ad 24 6f 3d f0 22 43 38 63 8b b6 53 45 8c +d4 b5 26 d9 61 74 4d af ec d5 99 8a d7 2a ed 3c +34 59 9f 7a 40 98 e3 d2 df 9d 13 a2 1c e2 37 0c + +# PKCS#1 v1.5 Encryption Example 14.17 +# ---------------------------------- + +# Message: +a0 34 a6 c1 66 cf 0b 25 d2 dd e5 3a f4 b8 33 b4 +78 c6 b0 d2 fb 0c ef 13 7f bf 5c 27 12 70 64 91 +23 7f 7b 28 6d 12 11 d5 73 10 f8 a7 62 b1 b3 bf +e1 9c 9a 4b 16 d3 e0 a8 + +# Seed: +d8 44 17 97 22 87 13 0a 24 a6 06 f5 83 29 7a c9 +11 52 8a dc db bd 7d e1 4a 5b 48 9b 67 86 f9 f6 +f7 e0 b7 3b ab 53 8e b6 c4 5f f3 4b d5 dc 43 ea +e8 d8 c4 3f 71 65 16 a6 0d a2 47 53 6f 63 4b e0 +65 d9 4e 7f 92 ad f5 2a 96 7e e0 5f d9 af d7 32 +33 3f 99 ad 05 82 97 b2 8f 8e c6 fe ff 80 28 44 +a0 09 7d f9 1a 97 70 2c 48 3a a1 c7 89 2c 7d 43 +b6 b9 1c d4 d8 5d 3e d2 f1 e9 55 39 57 06 c3 b3 +39 ba f2 a0 e0 + +# Encryption: +90 4e 04 07 23 ab 97 88 a5 ed 03 52 eb 96 c7 f3 +d7 07 cf 0d bc 25 8c 51 dc f6 24 34 06 f0 c7 42 +c6 cd f2 07 67 13 2c 09 5e 6c 82 a5 02 5b e7 b4 +13 4d 8f a4 de 18 7f 8e cf 12 fd d3 be ab db 06 +15 8a ef 46 c3 fe d2 d1 83 34 06 ec a7 a6 9e b2 +d2 08 a2 f6 f4 40 d5 4f 6b e5 dd 56 47 09 ed a8 +12 ac 06 29 a9 4c 7f 8a ee 78 be af 9e 93 78 c8 +dd 9c 62 03 74 bb ac a3 94 18 59 dd 70 2f 6f 7b +25 a2 38 45 9e e8 97 59 de 94 22 b5 bb 6d 28 57 +16 6c a2 12 0e 63 47 74 a0 d1 d4 2e b8 d9 48 15 +a1 04 4b ea 8b fb 02 da 58 62 cd 9a 74 5f 15 92 +47 8c 6f 57 bf d1 3a 5f df 4b 8f aa e8 a4 bf c4 + +# PKCS#1 v1.5 Encryption Example 14.18 +# ---------------------------------- + +# Message: +8f c6 39 4c d6 e1 75 33 d1 ff 8e bb f3 e1 ae ae +a3 30 ed 9f 5a 6e 1e fb 83 45 42 94 c6 ce 24 f6 +90 4a 0e + +# Seed: +be 1c 18 02 db 44 68 2e 58 c6 1f e3 87 57 ea 0e +38 4e ba dd 79 59 48 4b 38 bb 23 57 55 c4 61 77 +e6 71 76 9f 36 57 3d 7c b0 ee 7e 82 08 7b 58 4b +58 bb 30 05 30 33 68 c6 59 0a d9 f2 88 2c fa 74 +0d 51 dc 55 eb 0c 79 0f 5b b6 b6 a3 bd 71 f8 b2 +14 6b b9 e8 03 4c 35 b7 ca bc be 10 93 6f fc 5f +0a 8d 7b 30 47 6a b9 16 85 ae d8 fa 95 8e 73 c1 +ee a3 04 4c 56 b4 b8 70 da 89 37 1a 93 b8 96 52 +79 b5 5b b9 2c c3 16 c2 3e f0 97 53 51 c7 49 81 +7d b5 dc d8 6b 94 ad f6 03 bd + +# Encryption: +b8 3c 71 8c e5 c6 ab 1e 40 ff a5 67 0a c1 66 66 +4d 3a 68 33 cb 3b de f4 62 79 4a 25 d5 3e 17 04 +60 06 85 8e 63 f8 8a b9 5d 04 f4 fb 67 74 f7 00 +5d bb 2e 22 d5 19 36 0d 5e 13 38 ad 15 30 8f 6c +64 12 54 95 67 00 7e 02 1c b2 37 ed 4a f5 ee f3 +bc f9 b7 31 59 9f 72 53 ce ba 83 04 f4 ee 8c 34 +33 39 d0 a0 64 eb 77 f1 e9 3f d1 cc 7b a5 fc 3b +b8 18 4c ed 0e 86 97 ac 47 b7 46 20 c4 94 ea b5 +86 ed 9f e7 6e 07 e4 bd 2a 2d 1b 95 59 5b 69 c6 +46 77 a8 83 5d 56 ac 63 9d f8 f6 43 24 1b 3e 2c +46 88 d2 ad f2 28 de 2d a9 bb 0a 36 34 38 e7 51 +b5 25 0d ea e3 05 a3 90 5e 7e 07 7a 4e 8c 74 66 + +# PKCS#1 v1.5 Encryption Example 14.19 +# ---------------------------------- + +# Message: +89 a1 2d 22 bf 87 7d 44 0a 2e 03 ae a9 32 eb 51 +83 37 9b 3c 8b 90 be e8 fe d6 fc 6d af b0 cf 05 +27 + +# Seed: +60 72 89 5e 47 80 c8 f7 7e 0b 19 5f c9 f5 db 78 +33 f7 b6 f5 c8 1c 1d 30 cb e9 e8 0c cb 38 66 06 +9f 8d b6 96 3a d4 6d 52 94 2a 5a 73 f6 a3 27 a9 +4e d1 19 df ce 4c 37 65 84 37 13 b6 19 f9 c4 38 +32 03 d5 5e 2a b6 1d a8 96 1a 81 03 7f 11 18 a7 +82 97 eb 36 6a 1c 51 d9 f9 46 6b 71 5b b6 29 99 +e0 a9 d6 e0 25 01 d4 7f 97 db 40 9e 38 86 e1 36 +6c 3e ff 2b a7 90 e2 62 43 22 7a a1 58 80 82 bc +e6 d5 cd e3 ea 7e fb f1 5c 6c 7d fa 54 54 72 fa +9e 93 95 6a 45 51 d5 a7 7c a0 0e 26 + +# Encryption: +b7 ac bb cf f0 fa 9f ca 6f 0b bd e5 a2 f0 a1 e6 +a0 ab ad b3 2c 89 e3 17 25 5b d1 8d 12 e1 a6 0b +3e 00 2c 1d 69 35 64 48 32 9a 49 b5 bd 24 19 10 +fa 0c e0 3b 3e 68 a5 90 50 75 99 39 1e d1 53 97 +92 29 3f ef 13 17 4d ac ea 6d 2a 05 b3 9f 68 48 +28 a5 d6 d2 17 f8 4b 78 2c 8f c9 84 3c af 6a eb +17 8f 0e 2c 6b d2 a0 e6 f7 b8 09 29 61 17 cc 8a +6b f7 37 35 84 64 24 ad eb a1 ab 31 14 5f ca 3b +8a f7 68 c9 d0 a2 8e 09 d5 8a d4 96 42 31 08 f0 +8c aa c1 74 ac d1 f3 ac 43 48 69 61 c5 c9 0e 1e +fb 89 bd db 7b b3 9f 4c a3 af 57 12 f5 53 af 59 +4c d5 d3 64 13 29 14 26 10 07 aa 1d 5f 21 6b 8e + +# PKCS#1 v1.5 Encryption Example 14.20 +# ---------------------------------- + +# Message: +09 d6 94 8c e1 c1 f2 4c 6d 52 9c bc 5d 6d 6c 1b +ea ab 56 95 b3 0c aa b7 44 96 9b f7 f9 db d2 83 +33 5e 98 a9 bc d6 5d ad 2b 4f 0e 3c ec 89 0b 05 +e6 7f e9 78 23 d4 + +# Seed: +ed ed 62 a6 50 f7 de 3b 12 80 22 9d 5f b1 c4 40 +8e 82 df e0 31 7e 64 30 fc f4 71 b1 e2 8d a8 cf +6b 4b f4 c5 d0 31 e3 ee 68 8b 64 07 72 aa 50 08 +e5 86 3c 70 7a 40 22 c3 29 a6 66 4e 71 10 12 06 +b5 4d b5 40 6e 7f a9 c8 22 6f 42 93 11 19 62 0c +a3 0d e7 d0 3b e1 43 94 0c bb 4d 1a 9c 86 e9 86 +3c 98 7b ff 07 02 3d e1 98 64 f7 33 da 0c 89 bd +03 9f 19 f4 d8 ed 61 6f 7c 6e 94 94 18 5b 60 4a +1a 7b f7 49 0f d0 d8 + +# Encryption: +7a dd b0 5c bf 0b 17 aa 50 8a 0b 17 0c 4c 5a ee +84 ce 06 65 0d 08 c9 96 6d 95 d3 07 1a 9a 8f 3a +93 f9 6a 87 53 99 b4 78 c2 56 d0 41 5e 74 84 95 +98 21 1f 9f 9d 0b 89 36 7b aa af 17 4b 7f 13 d8 +49 0b aa a7 40 96 1f 52 d7 e3 53 c5 04 81 8a 00 +0b 03 67 4d 9c e4 93 dc 3a 4e e9 16 13 01 f6 1d +e5 21 ae f3 f6 d4 1d 82 e1 c5 dc e0 2e 63 6e 77 +40 a1 83 f8 02 3a d2 61 49 41 d9 b1 61 cd bd f4 +8f 8a 56 2c 8f fe 44 f5 7a 74 6f 26 39 e5 e8 3b +cf d3 92 d2 3e 1f b4 a8 d8 5e 3b a5 e1 cb 9c 0e +53 f0 d9 1b 01 ce c0 f0 ef 9d fe 3f 2b 30 65 bd +55 b7 2f b1 70 60 ab e8 83 0a ca 00 44 64 fe 7d + +# ============================================= + +# Example 15: A 2048-bit RSA key pair +# --------------------------------------------------- + + +# Public key +# ---------- + +# Modulus: +dc fa 10 ff a7 46 65 ae ef 87 09 74 ea 99 b2 ce +54 54 7c 67 f4 2a aa 6d d0 1a 2e d3 1f d2 c2 42 +af 5d 96 0b 1f 89 6e fb a3 54 3d 65 54 b7 b1 26 +87 a5 c6 88 56 8f 32 e0 26 c5 32 d2 59 93 b9 7a +7c 28 42 ec 2b 8e 12 35 ee e2 41 4d 25 80 6c 6f +ba e4 38 95 4e ba 9d 27 55 df fe eb 1b 47 70 09 +57 81 5a 8a 23 3f 97 b1 a2 c7 14 b3 e2 be 2e 42 +d8 be 30 b1 96 15 82 ea 99 48 91 0e 0c 79 7c 50 +fc 4b b4 55 f0 fc 45 e5 e3 4e 63 96 ac 5b 2d 46 +23 93 65 c7 f3 da af 09 09 40 0d 61 cf 9e 0c a8 +08 3e af 33 5a 6f ce b6 86 3c 1c c0 cf 5a 17 1a +ff 35 d9 7e cb 60 ef 25 1c 7e c2 c8 a5 88 36 1d +c4 12 66 a4 b7 ed 38 b0 26 ce 0d 53 78 64 49 db +b1 1a 06 ea 33 cc f1 ec a5 75 20 1e d1 aa 47 3e +d1 18 7e c1 d8 a7 44 ea 34 5b ed 7e a0 0e e4 e8 +1b ba 46 48 60 1d d5 37 dc 91 01 5d 31 f0 c2 c1 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +dc fa 10 ff a7 46 65 ae ef 87 09 74 ea 99 b2 ce +54 54 7c 67 f4 2a aa 6d d0 1a 2e d3 1f d2 c2 42 +af 5d 96 0b 1f 89 6e fb a3 54 3d 65 54 b7 b1 26 +87 a5 c6 88 56 8f 32 e0 26 c5 32 d2 59 93 b9 7a +7c 28 42 ec 2b 8e 12 35 ee e2 41 4d 25 80 6c 6f +ba e4 38 95 4e ba 9d 27 55 df fe eb 1b 47 70 09 +57 81 5a 8a 23 3f 97 b1 a2 c7 14 b3 e2 be 2e 42 +d8 be 30 b1 96 15 82 ea 99 48 91 0e 0c 79 7c 50 +fc 4b b4 55 f0 fc 45 e5 e3 4e 63 96 ac 5b 2d 46 +23 93 65 c7 f3 da af 09 09 40 0d 61 cf 9e 0c a8 +08 3e af 33 5a 6f ce b6 86 3c 1c c0 cf 5a 17 1a +ff 35 d9 7e cb 60 ef 25 1c 7e c2 c8 a5 88 36 1d +c4 12 66 a4 b7 ed 38 b0 26 ce 0d 53 78 64 49 db +b1 1a 06 ea 33 cc f1 ec a5 75 20 1e d1 aa 47 3e +d1 18 7e c1 d8 a7 44 ea 34 5b ed 7e a0 0e e4 e8 +1b ba 46 48 60 1d d5 37 dc 91 01 5d 31 f0 c2 c1 + +# Public exponent: +01 00 01 + +# Exponent: +21 95 08 51 cd f2 53 20 31 8b 30 5a fa 0f 37 1f +07 ae 5a 44 b3 14 eb d7 29 f5 dc b1 5d a7 fa 39 +47 ac dd 91 5d ae d5 74 bd 16 df 88 bf 85 f6 10 +60 b3 87 17 2f ae 6e 01 26 2b 38 64 c2 d3 c2 2f +94 e0 4a 81 59 42 2b 4e d2 79 c4 8a 4c 9d 76 7d +49 66 07 1a 5b bf 5d 04 3e 16 ff 46 ec 1b a0 71 +6f 00 bb c9 7b ff 5d 56 93 e2 14 e9 9c 97 21 f1 +2b 3e c6 28 2a e2 a4 85 72 1b 96 dd cf 74 03 fa +03 7d 0c 57 ab 46 3c 44 8d e5 cc 12 26 5a dd 88 +6d 31 1e a8 d8 a5 90 3f a5 6c 5f 1c 9c f2 eb 11 +cb 65 7a 1a 7d 3e 41 35 2d c3 e6 86 89 8c 4c e4 +30 5e 8b 63 8e 1b 08 a2 a8 6c c9 eb 98 66 f3 49 +9a c7 7b 61 36 b8 1c b2 76 d6 14 cf eb 7b 6e d3 +f3 bc 77 5e 46 c0 00 66 eb ee e2 cf f7 16 6b 57 +52 05 98 94 7f f6 21 03 20 b2 88 fb 4f 2c 3f 8f +e9 7b 27 94 14 eb f7 20 30 00 a1 9f c0 42 48 75 + +# Prime 1: +f1 23 bf e5 3d e9 7a 56 9d 91 ad cf 55 6f a6 25 +ad 30 f3 fd 3d 81 1f 9e 91 e6 af 44 b6 e7 80 cb +0f 32 78 29 fb 21 19 0a e2 80 66 46 d7 28 cd 9b +65 31 13 2b 1e bf ef 12 72 99 30 60 f1 ce 70 b1 +24 39 30 91 ee 85 93 b7 27 36 7e db ba 00 9e c5 +be 17 c4 ac ee 12 0c 84 12 67 d4 76 31 a1 6c 36 +a6 d1 c9 99 73 c1 b0 b5 a8 35 bf 39 fe af e8 f6 +42 1f d9 c2 a9 0b c2 79 76 65 9e 67 bc 83 12 4d + +# Prime 2: +ea 98 39 b7 e3 7e a8 9b bd a2 7e 4c 93 47 1c b4 +fd 92 18 9a 0a 96 bc b4 d7 56 93 f1 8a 5c 2f 74 +2a f9 e3 6f de 67 9f bd 9e ae 34 5f a2 69 52 7b +69 65 02 1c 4b df 54 d6 85 bf 08 96 0c c9 76 f6 +8d ca 21 ce bf 44 f2 68 a5 9d ab 8d 1a 25 e5 19 +f5 14 7e 1f 45 fe 28 7d 74 cf 72 5b ec 13 26 d3 +42 12 c5 6c f4 ff fa 20 2f 57 b6 8e e8 cc a9 43 +f3 c1 38 c4 cd e3 3b df 2c 94 40 df 65 32 24 45 + +# Prime exponent 1: +ca 0c 9b 60 b8 e4 a6 06 67 56 c6 5d 20 88 41 9d +f6 25 3b 7b 68 8a 85 f4 f6 e9 64 d8 5d ad 52 a4 +52 62 86 7f 1e 96 18 06 9f cc d8 65 e9 28 9e 46 +e3 9e 20 22 94 4c 5c 44 87 d3 45 cf 25 2d 46 0d +97 7d 77 ed fe fe db cb ae 46 a2 3a f7 fa 47 0f +07 7d a0 e5 09 42 04 4c b1 a3 60 49 7c c2 76 0a +c0 f2 ad 4a 2f cd 0e 84 d7 a1 d9 4d fd d2 65 8f +d9 ce 18 47 5c 1f a7 5e e0 ce ba d0 cf 0a c0 4d + +# Prime exponent 2: +52 81 71 23 3c 4e 4a 6c 63 b8 67 64 f5 13 38 84 +6a fd db cb 29 58 34 4c 01 c4 00 4a 1d d8 28 14 +5a 1d 02 a1 50 7d ef 4f 58 24 7a 64 fc 10 c0 a2 +88 c1 ae 89 57 21 d7 8b 8f 04 4d b7 c0 0d 86 da +55 a9 b6 54 29 2e cd 76 82 70 be 69 e4 bd 59 22 +d4 ef fd 1f 70 95 5f 96 27 e3 e1 9b 74 9e 93 b4 +0e f3 dd 1d 61 d9 39 15 e2 b0 9d 93 0b 4b 17 68 +bf ac c0 13 6f 39 b0 cf df b4 d0 50 01 1e 2e 65 + +# Coefficient: +df 2e b2 32 2c c2 da ab f4 d1 46 55 08 f4 15 21 +cd a7 ce ff 23 eb e6 1d 00 d4 41 ee 72 8d da 5d +16 c7 bf 92 0c d9 5f 34 be b4 fe 32 ee 81 7e f3 +36 2e 0b cd 1d 12 45 f7 b0 77 93 ea a1 90 dc 5a +37 fd af 4c 68 e2 ca 13 97 2d 7f 51 48 b7 96 b6 +fb 6d 7a dd a0 7b d2 cd 13 be 98 ce be d1 ed c6 +ca 41 2e 39 53 50 c5 9a 1d 84 2b c4 aa 2f 3c 0b +24 3f de 7d fd 95 35 6f 24 39 25 1a 11 72 c4 5e + +# PKCS#1 v1.5 encryption of 20 random messages with random seeds +# --------------------------------------------------------------------------- + +# PKCS#1 v1.5 Encryption Example 15.1 +# ---------------------------------- + +# Message: +2a ac ec 86 f4 23 dd 92 5e c1 58 82 2a 74 8c be +6c 31 a0 + +# Seed: +cc 4b 87 f6 74 49 7b b0 e3 3d 9e 2a 4a 80 70 b7 +d7 8b 5f d2 c4 b4 f6 eb ac cd 4e e5 05 b7 1f ca +fe 21 56 33 7d df 27 b4 75 af 33 f6 c3 40 5b 8e +3c 0c 20 6e c2 81 29 22 fc d8 a3 66 1b 86 19 bb +c1 82 f8 07 f3 a1 07 2e 62 ca 2b f1 fa 8b 94 4e +58 a0 e2 03 db b7 53 f9 f1 b6 ef 62 7e be e5 98 +96 7b 38 7a 5f 96 36 d8 b6 41 b3 89 84 b1 ca 03 +7e 3a ae aa 17 10 f5 16 25 ea 85 f8 fb 9a 6e 02 +9e 64 57 58 14 d5 30 fc 14 6b 34 45 ac 42 01 b4 +e4 08 ad f6 55 f6 78 43 d8 87 1c ac e5 d9 06 d7 +fc 03 8f ea 88 5b 96 fb 8e b1 a7 21 c6 c1 4a bb +eb 78 fb 4c 79 8a 19 58 99 59 89 84 55 a3 16 84 +3c 6c d9 9e f5 8c 2b 0b 49 b8 ab 41 91 b4 02 a5 +4c 92 97 31 0c d2 24 b1 7f 21 41 67 72 5c 48 fc +c6 1b c4 7c fa cc f1 5e b3 b0 + +# Encryption: +60 42 e7 45 58 9a f0 3a f8 75 20 f9 3c 45 d8 c3 +59 85 ad a1 16 1a 37 d8 22 e9 f9 46 0f c7 5f cf +01 79 d8 49 1b 8f 5d 1e 4d e8 ce b3 1e 07 c4 86 +5c 5a 3e fd bb b6 9a 88 03 b8 9e e6 5a 43 0a 58 +09 c7 07 56 91 50 b5 80 bb 68 6a 94 c5 54 1c 46 +ad cd 82 79 60 ce 24 4f f6 88 38 7d 16 16 e8 5b +4d 17 80 c6 48 36 06 cf 92 4b 54 f0 80 cf 41 54 +e6 68 29 bf 6e 53 24 81 04 8e c4 1f ad c0 7d 75 +5b b3 4b b2 81 45 21 9c b3 0d 47 d0 d6 18 70 91 +80 e9 03 03 ff 9e f0 90 18 be d3 da 75 76 1d a7 +94 81 1f 96 bc 9e 8d 7c 4b a1 b5 94 6b da 0b d3 +13 fa ec 4c 99 3e d2 74 8e ed 8c ce 4b db 52 0b +a7 db 16 5f 9f e5 6a a8 45 4d 6f f3 38 74 fe ee +bf 29 de 2d f5 b7 f0 0a a1 d9 fb 07 3f c4 06 7b +58 dc 50 62 4e 12 7f 71 1d de 2c c2 cf da b4 91 +9c cf 28 c8 36 60 df c2 27 b0 f5 00 ec 1f 90 4f + +# PKCS#1 v1.5 Encryption Example 15.2 +# ---------------------------------- + +# Message: +5c 8b f2 ac ab 08 bf fe fa 64 80 95 2b 24 da a5 +01 9d 12 5f ee + +# Seed: +5e 16 30 70 ef dd b7 9f 47 64 f8 a8 1d 44 46 0b +5c 40 0b ec 70 37 52 29 20 f7 72 95 9f d4 cf 3a +ef 2f 14 45 4d cd 9e 86 25 12 ca 69 db 83 68 a4 +cd 8d 1a 44 da 59 5d 6b 43 93 91 c9 31 46 b1 23 +f1 86 08 3c 4b 64 47 bf 7e 20 81 51 46 ac 75 49 +ef b6 74 60 e8 ff 1b 2b ba 5c 95 a5 1e f8 13 d5 +dc 4e 6c 38 92 bc 4f 43 9c 99 11 7e d0 6c 14 a6 +c5 40 fd 4c 65 d1 95 d8 c6 1e a7 79 68 38 e5 a5 +df af 11 d0 71 3c 19 1e 8a 0b 80 80 f7 a7 7e 70 +3a b3 66 22 f1 c6 48 b7 65 43 5b 90 27 97 18 11 +b1 15 2d 97 2f b7 6a a8 92 05 03 3d 95 78 18 7a +e6 34 88 fd a3 c8 6b 2f 28 e7 79 ac 4c 89 cd 25 +20 17 d1 a9 95 8a 52 c5 b8 7e c1 bf 9c bd f7 de +0e 97 c5 8b a1 1b a3 a3 37 05 f3 f4 99 58 9a 3a +72 e2 c0 fc 5b 16 fc a2 + +# Encryption: +44 e6 71 e0 3b b6 67 80 ec 05 86 d5 6f 8f 6a 49 +41 5a d4 bb ce 22 6d 75 d7 0f 06 ce 29 de ea 7d +a1 af a8 28 7e 44 36 3c 51 0f 34 eb 8b f3 1c a2 +47 29 59 26 9c 18 df 09 36 ff 12 c6 16 6f 4f 45 +96 cb 1c ae c4 1d ed a8 c5 09 99 bf 4c 94 4d 21 +37 5b 36 75 31 91 b4 cb 7c aa 1b 43 e9 11 6c bf +1d a8 b2 01 d2 97 a4 d0 8b b0 e5 bd c8 95 32 70 +f7 c2 80 96 78 c4 4b ea 75 e8 1f ac 22 d2 71 06 +30 2b b6 9d a0 74 b6 ef a6 68 8c f8 35 c8 0b f5 +e4 55 35 28 ec e0 b7 c1 b7 7b 66 6e a3 45 23 ec +1f cb 3e 25 05 4e 0b b8 e4 ba 02 7e 5c 21 bf 7a +51 43 bf 04 1c e9 cc bc fa fa 87 80 82 fe 41 f7 +8c 70 bf 4e 53 cf 48 7c 1a ad b0 19 15 ce dd e8 +cd 9f b8 4e fd 98 1a c9 8c d5 7a 82 56 d4 e9 e2 +d0 86 2d ab 04 54 d3 ff 4f b9 85 26 4a 46 99 5a +b0 68 a7 4e dc 7e d8 ae ff 5f a3 0f 3a 7d 75 94 + +# PKCS#1 v1.5 Encryption Example 15.3 +# ---------------------------------- + +# Message: +e2 00 4b 31 07 39 98 2c fa 9e 95 45 3a + +# Seed: +e9 3e 64 12 33 7a b7 b0 f1 b5 69 80 1a 3c 16 4a +6f 23 e3 c2 7c 7c 55 a8 c5 ac 9e af 31 88 55 f8 +32 8b 5d 7a b4 cb 86 19 a0 0e 99 41 cc aa 94 85 +70 52 71 82 61 74 43 c1 d2 1e 4a 6e 21 b3 f6 d4 +f6 98 a6 1a e0 29 17 2c f4 da 03 9d 91 58 5a 87 +da d1 28 c2 fa c5 53 1b 2f 45 dc ef 9b 9f c3 31 +c8 04 48 85 28 84 7c 90 87 5d 19 07 5f ff b0 05 +76 3d 88 e0 81 47 66 92 28 a9 aa d0 16 25 bc 61 +11 2c c7 b7 72 f3 21 d4 33 d4 f2 69 78 20 9d 0e +79 67 6a f3 b8 a7 4b 97 3f 52 ab 91 90 85 f3 52 +35 5f 85 6a a4 0f fa bc e5 43 d4 e7 6d 45 48 92 +98 9c b3 83 f3 e6 6b bb 0e 8f ee bf f7 c6 a5 4e +f2 62 5f c4 05 0e 6f 87 a3 23 13 2a 4e 67 12 68 +fb 83 cf f2 d8 22 51 b7 9c be 32 da a8 e5 53 20 +2f e8 87 22 61 f6 0d 5b b5 11 f2 fa 2f 14 21 a3 + +# Encryption: +2b bf 6b 0c 5c f2 0e f2 f6 c5 a0 aa 48 45 4f 85 +0a a5 f6 bb eb 03 0d b4 e2 be c1 1f b2 00 f0 1e +4e ae f0 44 d8 14 33 33 33 8e 5e 66 38 00 87 66 +0e d0 17 3a 76 82 12 85 67 7e 37 1f 28 ec 45 00 +f4 d5 9f ab ab 20 73 e7 34 36 5f c6 b0 94 ee 0a +db ce ac cf e2 49 88 ce 61 5d 60 5f c3 40 8c 03 +be 22 1c 99 3f 61 aa 72 4f c8 71 4a 8a 4a 18 15 +f9 e9 a9 98 82 aa 46 88 3e 70 47 4e 33 29 b9 91 +e6 d5 3d c6 b5 00 86 19 92 34 3a 6d a8 9a 8b d6 +f3 7f 34 e5 de ee f8 0e 7d 56 b9 3a 45 17 60 66 +36 50 fa 45 5d 55 41 89 9a 76 aa d1 c6 27 5e c8 +2c 46 07 12 26 59 b5 08 cb 5d c0 26 ac f9 3f a0 +1a 5f ca 3d 81 c1 bb 20 a5 a5 cf 35 7a 23 c9 56 +88 ea 42 eb 1e f2 c9 d4 6a e3 7f 8c be 61 5c 20 +84 d9 89 b8 92 f0 16 7b 23 be 33 62 fa ce 80 8d +6a 5e b8 96 19 44 08 db 7c 01 63 9c 58 62 30 4c + +# PKCS#1 v1.5 Encryption Example 15.4 +# ---------------------------------- + +# Message: +db 6a f1 29 23 05 27 8c 5b 33 83 f8 a4 1d 6c 83 +52 21 14 c9 88 85 50 74 06 5b 23 f9 fe ae 8e a4 +31 fd 5d a3 6f 9b ab f9 dc 61 df 2e 39 23 47 83 +04 73 38 ec 4f + +# Seed: +cb 85 1f b2 76 a7 49 1c d3 ef e4 d3 39 50 16 c1 +ec 2b 15 09 4a 1e c6 d9 30 d4 ca 21 b4 20 f8 47 +ff 68 68 f0 14 d2 09 ff 80 7e 8b 1f 71 67 0b 32 +50 94 c0 f6 e3 2f 84 f7 68 22 22 02 b2 1b e3 6a +28 6b 30 e0 82 ef 3b ba 64 7c eb ee af e3 10 69 +44 18 d7 0a 67 9e b2 01 07 80 dd 0e 96 55 3c 43 +cb c6 d0 0e ac 22 aa 71 f2 48 21 c4 d6 c1 77 8e +78 6c d8 c7 bf 2c bb f2 14 e2 03 e2 ef 2f 33 35 +78 cf 1a 94 7e 27 e5 99 96 29 0c bc d6 ca 3f 8f +96 ba 67 e0 e3 41 30 cf df 86 ef 48 e6 7c 90 b8 +b7 2e 6f 42 55 01 7d a2 d1 f3 ae dd 7f b1 d9 de +42 ef c0 37 ab e6 61 6e bd a8 d0 b4 0b d7 80 cb +db 68 ce 54 31 8f da fd + +# Encryption: +c9 9a 9a b6 7c ad 0c 41 ec 84 7b c2 74 67 fd f5 +bf 61 ed 6d 04 c6 5f 7d 9d d8 bb 70 07 a8 a9 b8 +3a 3c 38 a9 cb 92 5e 3e 7b 3c 40 7d 64 66 93 15 +b3 54 49 e7 54 28 ae 96 19 14 b0 b9 10 23 e7 83 +19 1f 95 41 b6 78 65 97 1c 95 b0 be 18 93 1e b1 +c8 47 c2 6a 29 83 c0 58 4e b2 17 c9 9c 70 5f 5a +d8 cb b0 9f 99 b0 6b df 7b d1 26 28 ae 36 67 c1 +2c 72 27 d9 6f f9 c1 08 dc e3 22 51 06 f6 2f 9a +4a 3a 81 17 a9 92 f2 88 c3 b5 97 91 09 87 8f cd +59 c6 79 6b 19 98 48 2e a8 2f 30 1c 93 91 83 b2 +dd 47 88 04 48 67 8a cb a1 2d 7b c8 a5 52 eb 32 +76 34 e9 2d 0c dc f7 1e ff b6 66 ad 90 2d 9e 26 +ad 18 60 e2 92 81 d0 2f b0 c5 49 3b f7 4a c0 2c +94 40 43 6e 0d 75 32 28 92 77 7d 32 5e c8 45 2d +e7 58 cc 6a 5c bb 02 d3 41 f4 5c 9a c8 ed f1 50 +da d7 15 82 dc 77 95 8a 85 44 b0 b5 58 ee 2a 0b + +# PKCS#1 v1.5 Encryption Example 15.5 +# ---------------------------------- + +# Message: +e7 99 e4 eb c8 69 31 9e e2 25 80 + +# Seed: +3a 07 57 cb 49 a3 fe 6a e8 0d 37 42 06 8b 5c 80 +68 b8 c5 88 54 20 01 10 93 c2 20 99 ed aa db 49 +1f 22 6f 85 60 66 16 3a b5 10 5e 78 79 c7 49 1c +18 35 98 5d c4 94 21 0e f7 8b ad 48 16 d9 b6 94 +c9 c8 be 46 6a 4d 17 8a 7d de cb ce 53 65 40 0d +68 21 b6 e9 ae 0e 03 bb 69 ad c4 ec 73 4a fd cd +ea 6d c0 c4 85 96 c4 8b 27 35 ef 70 f3 73 4c 18 +6d 03 18 37 8d 2b f8 09 96 88 67 2f a3 85 91 da +4a e6 fc 11 2b 72 7e c8 19 84 df 7b 56 c9 84 4e +25 b0 fc d8 1d 2b e7 d1 8d 01 64 6a 6d 9f e2 25 +d3 69 7c 34 ed 2e 33 6c c0 37 3d aa 28 d8 82 e4 +97 75 7b 0a 65 10 86 2e ac 10 d3 b2 4a db 25 2f +30 d4 34 e3 0a 63 76 46 9d 80 b9 57 11 16 17 78 +df 35 88 9b 3a cf b1 f6 53 ea 63 07 2f 35 a3 c8 +9f 6b a5 2a fb bd c2 8f 23 d3 8f 4d 4e 79 fc 39 +7c 10 + +# Encryption: +3a 3e 72 5c 6e 4b b0 06 12 69 61 8c bb 8a 62 67 +d9 55 83 ab aa 03 d8 df 85 a4 f6 a5 cc 35 9b f1 +15 26 0d db 70 ae 7c 66 bb 8d 87 d6 33 1f f1 b0 +b5 4b e5 64 8e 83 e8 3a 91 c5 4c f3 71 49 6e e5 +ca 02 73 b1 9f 70 03 70 c2 c8 cd f4 28 13 38 a6 +e7 2f 66 32 41 68 ea 8c db c6 4c 60 9b a9 67 91 +c7 91 b5 ac 84 00 99 2a 8c 66 fb 09 f4 e3 13 07 +49 12 af 0c b7 41 5f b2 15 eb 97 fa eb be f1 a4 +47 23 9a 91 db 4a 34 fc a4 d8 43 46 25 9e e0 a1 +da dd 10 b7 f0 1f c8 c5 3e 42 0f 88 cd fa 0c bc +f6 2b e4 4b 8a 79 40 86 4f f8 13 7e db 12 2a c2 +da e5 41 0a 47 cf 07 62 e2 0f 20 86 cb f6 6f f4 +d1 a9 f7 27 0f 00 9c b2 e0 7d 90 20 b4 8a 76 d2 +41 08 e9 98 9b f9 04 e4 a7 1d db 91 74 0a d7 e5 +d1 b6 8e c6 4e 3e 66 cd 0e 89 7d cc 66 57 39 eb +ac 45 19 93 f0 2c c5 bf c6 3a 60 2f 55 83 81 da + +# PKCS#1 v1.5 Encryption Example 15.6 +# ---------------------------------- + +# Message: +09 97 12 b8 26 ba 67 cf 92 92 25 bd 61 2e c0 65 +d4 51 ed e2 31 c8 d5 c2 04 04 d4 70 e7 9a 7a 1f +24 6e 3e ec dc c7 5f 08 53 29 f8 f1 7b 81 d1 30 +30 0f c3 b9 f0 93 a2 + +# Seed: +81 cd 64 c8 4d 77 65 fc 60 e4 de 3b a9 b4 dd 21 +dd fb 74 fe 2d fb 7c f6 19 db a4 cb cc 17 6e d9 +4e 6f 37 ed 1a 97 e3 bf d3 63 65 d2 64 4d 3b 6e +e6 c7 71 09 fa 18 41 2e e7 cd dd 3b e8 d4 bd ee +94 c0 96 f0 72 ca b6 f1 88 6e 3a 84 a7 fd b5 af +f3 dd 83 f7 e5 c5 b4 9b b1 b3 8f 8f aa 75 25 31 +d8 9c 88 39 3e 9e b8 f5 7e dc 5b 9f e6 ed 2b c9 +5d 27 2c a9 95 f7 e2 59 b0 08 32 d9 8b 87 23 12 +cb ef 8a 04 8f 6e b7 91 97 84 ae d3 d3 1e b4 b1 +2f d8 07 60 a1 34 c9 d6 c3 34 c2 dd 3d fd f4 97 +5c f1 b5 1e 87 12 2b 97 33 33 44 96 08 ff bb 2c +f3 0a 02 bc 46 ea 24 7b 45 39 b1 86 07 bd 47 d3 +cd f0 87 72 14 ba + +# Encryption: +78 6b 3f 59 9d 1b 74 3e 23 58 26 24 fa 2c 94 a3 +6f b6 bd 33 fd dd 57 64 08 cc 85 4a d7 cf 66 7f +17 38 0a f2 0b 0b 73 0c 6b e9 8c 01 80 76 b9 b5 +04 1d af 2e eb 02 54 69 30 0a a4 36 43 35 be 26 +7d 33 b0 6b 4a 7a 79 7a 3c 0a a5 fd 3f 91 6a 55 +dc 27 4c 0a 24 87 f1 25 f9 da 82 59 6f 43 4c 7f +ba c7 ec e2 ef 6c 83 e0 34 8b f4 f2 c0 83 05 07 +55 b5 6a 9c 63 47 f3 9c 76 b0 e0 ee dc 61 54 10 +25 c2 3a a1 85 5c 0b 22 b4 46 fe 1e c5 f1 11 2c +5a 7f c2 85 ef dc 84 20 ec 01 a3 a7 c3 3f 73 5b +45 55 09 2a 9e 8d e1 6f 3f 7d 46 9f 88 cd 75 c0 +1c 7f 2e 7d 54 6a 1b 9e 7f 49 84 fa 29 a2 cc 80 +d3 10 f9 d7 81 8d f6 d9 ad 6c c2 05 37 4d 52 e8 +e1 73 90 bd e7 2f 25 b7 12 a4 26 9f 23 ae b2 41 +a6 66 e9 64 96 cd 84 b8 33 fb 53 d0 57 1f 7a c2 +d1 96 4b 8f 2a 7e 13 33 6d 9a 7e 03 04 1d cf cb + +# PKCS#1 v1.5 Encryption Example 15.7 +# ---------------------------------- + +# Message: +5f 2a 5c 7f 93 e7 14 ee ca b3 a5 5a 69 c7 9a 3c +bc 15 bd 19 df 27 98 9a 9b ab 59 fb be a9 ff cc +66 3b f8 e1 e7 40 7d c2 73 + +# Seed: +e0 19 60 82 6d 1a 69 f6 84 c9 c0 b8 5d 84 dc a5 +81 1c 89 a2 c0 74 2f 33 a2 ad 19 9f b6 57 a1 aa +98 13 60 1d 29 93 6a 43 d9 b9 eb 4d 32 89 cd 7d +37 06 ab 86 b4 d6 6a da a7 e0 a1 34 51 b2 ed b2 +bc 77 10 91 11 0c da dd 7e e2 e6 aa ea 2b 35 cf +ae 4c e3 b1 da 18 16 68 4c 89 c0 b3 fb 2f 87 79 +b2 5c e0 c1 2d 42 b1 d3 d3 0b 8f 20 be b8 99 91 +6e 4f d0 a1 58 86 37 19 2e 05 28 ce 6e a5 4c 8e +b7 54 fd 7f f0 03 25 81 a9 50 59 98 e6 9e 14 f0 +72 bf 95 df ef f0 14 df 99 ed 78 53 b9 82 e8 89 +41 29 a1 d2 7c 53 ea aa 23 4c 8d 14 a7 ff c5 f5 +e2 18 7c ef 79 eb f5 2b 3d 6c 06 65 89 5b fb 87 +e4 bd 61 0e 35 8f 35 26 da 05 92 c9 e5 02 b7 2b +76 e4 65 66 + +# Encryption: +77 d9 07 18 1c c3 b1 bb 19 81 e8 cb 22 f7 ad 75 +f8 82 e2 6a fd 28 1b 64 db 70 c8 4c 6a 50 fe 74 +24 9e 22 fb ee 90 e3 0d 0b 70 ae 2f 7e 12 ac dd +f6 78 f0 0d 22 7e 53 61 54 26 62 43 02 69 fe ea +34 12 47 92 af b3 f8 7b 30 f9 50 f4 ed f2 2c 44 +04 c9 68 8d ec 38 ea 0b 99 cb 3d c3 84 bd 88 fa +31 83 d7 e0 7a 20 54 d7 3e a5 1d 42 86 bb 39 da +e3 ae 6d 0b 96 51 f1 ea 48 8f 80 5f 2a 21 6e a2 +1a 56 76 b9 7d 1b 11 d3 b4 03 6c e1 67 fe f6 4e +0e ba 41 9a f6 73 98 3f c6 ee 01 c6 37 b1 64 e5 +aa ac c9 9a de e9 f4 7d 21 92 54 69 6c 8f ce ec +6c 74 ac 4e 39 05 1e 15 26 94 01 73 82 64 f0 ca +5b f1 22 c5 5c 9e 5d d8 47 b1 d5 77 4e 74 08 c3 +68 4a a9 74 b0 ba af 40 ed c2 2a 03 57 af 72 c8 +16 cf 73 1f cb 63 96 53 60 69 9f 26 99 97 b8 48 +0f 30 a6 b5 d5 7e 12 a5 cc 54 ec 0c 80 5f dc f6 + +# PKCS#1 v1.5 Encryption Example 15.8 +# ---------------------------------- + +# Message: +55 61 39 59 3e ee 8b 6e 87 + +# Seed: +2d e2 a5 72 24 f5 f5 b1 2e 22 3e b5 f8 2b 9f 47 +24 9d 25 55 93 79 13 6e af 18 e2 f6 c8 33 e3 f0 +1b de ea 9c 30 3b d9 67 7c 2a 85 71 7d 59 3a 28 +02 ae cb c6 b3 b7 1f 2c 79 03 ff 69 0e 3f 3c 49 +57 dd 74 cc 9c 2a 68 dc 1d 31 9c 1e 17 87 bb b7 +f0 e6 e5 1e 39 a5 ba db ba 9f d4 67 66 19 74 31 +2b 55 7a f1 89 52 54 9f 6e ba 9d f4 9f 70 ea b3 +68 9f 9f a8 fb ea 1c 97 e1 bb 2f 09 3e 6a ca 9c +38 0e dc 54 6a 19 c4 4f 91 f6 dc aa 28 9b d1 14 +fe a1 b0 36 f9 9b 1a 57 f8 61 43 d8 67 5b d0 7d +4d ea bc 9d 51 0c 61 70 99 44 9c cc ed 5c 45 07 +b7 9e 85 1e fe b1 8d 06 b1 99 81 0b b6 b3 cb e4 +12 73 ba a7 35 16 02 e5 f9 52 13 f9 69 55 ad 5f +dd 3a 20 52 db c7 5f cf 60 aa 22 47 f2 d4 e6 03 +da 45 37 0d e1 c1 da 68 7e 26 8e e4 46 67 f9 4d +ad 13 bc 9b + +# Encryption: +4a ce 54 a7 52 f5 56 e3 6e ab b1 19 48 95 84 12 +14 0c 80 c3 1b 61 dc 40 f8 1a 6b 12 17 a0 1c e0 +67 ab 37 f5 3d f4 c7 7d 9e a9 c2 d7 95 0c 8c d4 +97 00 b8 cd 24 d4 e7 8f 7f a3 46 29 62 cb fd e6 +d0 2f b0 e5 03 65 64 93 25 05 ae 1c 85 1a a6 d1 +d8 4e fd 04 d5 78 ad 68 27 3a 36 a8 ae 23 d1 45 +2f 94 a9 37 88 17 71 3e 76 4a 09 17 45 26 29 b5 +dc 75 b5 7b 0d 5e 6a 72 8c 83 69 11 72 d2 cd 95 +f8 ba d0 7d b4 68 eb f5 45 b7 f3 f2 c8 63 b6 e2 +0c 67 c4 76 9d ed 03 91 a3 36 f3 a5 d8 7e 24 fc +f9 1a af 77 4b ee 77 a7 89 a5 90 80 09 c7 a5 5e +ac 92 af 4c 3d 46 1e 7b 40 61 6c e8 06 19 4b fc +20 74 c3 f4 f1 35 59 70 0b 27 08 a0 b7 55 78 96 +70 a3 62 6a 14 63 88 11 bb 18 e1 5b 10 25 c3 b9 +be f1 11 17 6b c1 f2 46 9e a9 9a ad 20 86 05 73 +d6 c6 a1 fe 40 db 51 e3 6f e3 38 00 10 1b da 20 + +# PKCS#1 v1.5 Encryption Example 15.9 +# ---------------------------------- + +# Message: +9a 13 96 62 2d 06 6c 10 56 08 58 c2 c4 cd 5c 04 +44 9e 2b 95 50 c5 bc 92 93 76 1a 91 04 41 1d a1 +8a 57 d9 b6 a9 97 33 3c db ce 77 e9 fd be 6b b8 +31 + +# Seed: +f1 78 61 ac ff b2 4c ac ed 90 ba 38 aa 7e a0 f2 +e5 4e ea a6 2a e6 64 98 f3 c2 8f 99 6b ce e2 53 +be e8 19 9e 3e b8 0d 62 7f ee b6 e0 b3 94 90 ed +f7 6d 16 a2 a0 bc 20 09 32 52 a9 d7 f1 f9 38 8b +06 19 44 85 2a fb e7 3c e4 13 a3 fc a5 21 b9 47 +4e 67 81 29 46 4d 91 b8 2b ca a5 9f 56 ec fb 12 +4f 61 f5 04 67 13 01 05 b2 cb c6 94 3b 95 36 95 +cf cd 20 c9 b6 ef 53 f3 f2 10 33 1d 39 32 dc 01 +0c 73 59 29 09 6b 2e 68 ff 16 66 4b 0b 90 a0 fa +1b e4 60 57 85 92 b0 cb 4d 6c a4 5e a0 6b de 3e +8a 1e bf ef 70 d8 3e f7 9b 3a 74 db 06 0f c0 20 +3b 74 80 7f 40 70 01 f4 b4 d9 9e c5 15 8e 8e 7e +4b 10 2a 51 5d e9 5d 2b 70 fe 1f b4 + +# Encryption: +10 0e ce 63 45 25 d4 67 f6 d4 a6 b6 6e de 1c c2 +37 f6 1f b2 b6 70 23 a8 3d c4 56 b9 2c da 18 3e +d6 62 0f e5 7d 5a 67 33 2c 77 23 3a c1 e8 72 5b +36 f8 e1 b1 08 41 2c a6 fb 35 dc d4 d8 16 77 a2 +b3 0d 5e af 25 e0 b9 19 1b 38 f7 ee f8 3f 91 21 +a8 08 43 8c 92 ab 03 f5 20 80 7b c9 a8 94 70 5e +af 4e ed 06 68 23 a6 7a a2 a5 59 9c d9 5e 58 da +7c 09 48 36 d2 af eb a3 9d d0 09 a6 4a de 03 05 +33 76 f0 29 36 cf 3f 56 bf 64 c1 f3 bd c0 7c 45 +a9 5b 9f cd 93 96 cd 9a 8d 41 bc c5 64 24 93 7a +13 71 b3 84 7c 90 5b 9a b5 84 02 39 3d 40 46 e4 +a0 15 c1 47 08 f7 4c e7 79 0e ba 8a f7 92 07 24 +40 bc af b1 4c 0f 81 08 97 11 87 c8 0f 46 3a 1f +ff 25 86 46 ea 16 e5 1c 6e e3 61 b6 61 a1 4f 07 +cd 4f 5a 82 c7 09 f4 94 f1 df 0f 80 3b 6f 64 a7 +2f b9 c4 50 ff e2 68 fc ab 48 7d 4d 63 01 3e 41 + +# PKCS#1 v1.5 Encryption Example 15.10 +# ---------------------------------- + +# Message: +b3 82 4f b5 45 a8 3f 82 ef 82 23 11 82 84 c5 45 +6b ab 60 0a df 79 f5 07 33 b6 66 8f bc 51 5d a5 +96 31 62 a6 d7 d7 e9 6f f9 1a ff 12 eb 3e 93 11 +e2 21 e7 0b c0 + +# Seed: +b8 26 8e 4b ce 7e 53 f2 e8 be 98 b1 92 d6 3a d0 +65 44 a8 0d 6e 62 d6 32 48 6e 15 e5 75 ba 70 6e +3e 76 89 30 dc 8e 41 1f 8e eb 0b 6e 8f 06 06 29 +da 8a 24 23 68 e4 79 cc b3 31 69 70 70 b4 b3 52 +4e 69 16 92 76 ba b0 a9 45 14 cc d6 60 70 25 28 +ed 20 b5 d1 df 07 77 9a 62 c6 56 86 e7 d6 68 46 +6f fc 74 8e b3 43 44 ca 6f 30 5c da 3d c3 e8 f0 +1c 43 ea 91 79 da 46 21 47 f4 d3 ec 92 f8 88 b7 +ee aa 41 0e 12 c8 6d 89 42 c7 d0 12 f4 5c 61 ff +a6 e2 b7 8f 84 3e 9a 75 d9 67 32 14 d5 58 ca f0 +1b 45 f9 36 86 ee da 54 79 db 80 52 79 25 59 cc +23 6a 4a 1e e6 5d 3c a6 0e 09 a3 c1 84 d4 b3 95 +d7 0b 8e f8 8d 78 09 1a + +# Encryption: +c0 e9 8d 50 89 4a da 84 9f ce 89 83 f6 f8 95 74 +03 4d 6c f3 b8 35 2b fc 50 72 4a 70 3d d4 f4 2f +40 06 ae 00 8a d9 72 33 ce f6 f1 6c e1 b4 23 f5 +2c 6b 67 7e f0 05 13 1b a9 87 f9 8c 72 2f aa 49 +42 ec ce 2c 99 66 37 40 a1 a1 e9 81 20 fa ed 97 +fd 03 ff 36 fe 73 75 8e 70 df 17 f3 1f 1f 39 41 +81 2d 34 ca e6 c3 9d e7 87 ef 57 04 bc 39 c9 20 +ea 5b 0e b1 83 3e 83 b4 57 94 fd e0 ff 00 05 c6 +27 33 c7 0a 29 6c a0 bd 47 f0 65 50 3d dc e2 d6 +49 de 1c 32 8d df 60 32 a3 3f ad 46 ba 04 1d c0 +a9 94 bf 0f 56 a4 65 f1 62 5f cb 81 ce 01 fa 29 +9f c2 b3 c8 09 39 eb e6 a6 73 82 6e 2b 2f 12 ec +dd a5 03 5c 95 09 31 2d d1 9f 10 c3 5c 8a 8b 0d +a6 3c 08 51 97 00 6a 9b e2 36 10 8e b9 87 91 b2 +6e 28 08 b5 cc d5 ac ec 73 8b ca 02 5b 24 18 2e +f4 ab 9c cc b1 71 a6 9f b4 23 a4 6e 03 7a 4d 0a + +# PKCS#1 v1.5 Encryption Example 15.11 +# ---------------------------------- + +# Message: +a3 a7 da 1b ed b2 ca 99 fc de b7 a4 6d 63 3e ca +35 06 2d f2 89 6b 69 59 07 a7 f9 71 d2 cc 50 b6 +e3 d2 a3 67 d1 6e 72 7f 56 97 c0 + +# Seed: +f0 18 a9 b1 3f be 56 0b fe 95 52 ed 8a 86 06 be +ea 90 05 5e d3 f6 2b b2 af 07 f6 92 cb 60 ac fb +6d 59 07 d6 0e 0a 59 7a 54 ca ea f8 44 91 1c dc +87 4f af 95 69 53 a2 7d 30 0e 9b 71 5b 10 4d f3 +c2 32 c3 c9 63 82 cf 5b 5f 3d 07 b2 30 b5 25 bb +33 0e 31 9d 1a 7c 82 d1 53 af 81 7e f1 1c f7 2e +76 dd 50 b0 d7 e5 56 22 65 c8 34 5d a8 29 f5 60 +d6 a5 4e 6f 1e 28 8a 3d c2 17 6d 19 a6 8a 0b 1c +5c 92 b1 6b 8b b2 9e 4d 01 df bd 0b 18 07 9b d4 +0c fc d5 23 35 b3 a1 8b c4 ee 92 44 76 0e b4 94 +f5 be 5b 19 71 88 6c a2 be ec e0 a3 94 4f ff 8b +e6 b4 2d 96 e1 c2 c7 2e 4e 90 f8 7e d1 36 15 46 +7c fc 91 c2 6e b3 8a 7a f9 f5 66 86 93 1a 47 26 +da 04 + +# Encryption: +25 17 7b fe 12 61 9b 44 f4 a4 fe 7c b7 6d e9 3d +4e d4 a0 5a 31 e5 be 8c c4 e5 60 66 1d e9 a3 4a +e3 17 cc 02 ff 63 10 67 08 32 8b d3 f7 87 63 ab +3e 57 65 2c 63 f1 05 f7 97 1d 2d 8d 70 1e 62 97 +a7 9c 78 7b 7c cd 62 a5 3b 39 d9 c0 39 46 e6 6f +48 8a 92 e8 e1 7d c6 ec b0 f6 5b f0 1e 3a ff ee +99 76 87 31 1b e0 e9 45 ad d6 3f a3 f4 00 38 2c +b8 ff d8 91 57 54 01 8c c7 5e 82 82 26 b5 03 9c +d9 c5 7f c6 d9 9c be 8e a4 a3 d2 9c bd 09 d5 4d +95 cc 07 34 c2 35 44 f8 e1 fb c7 49 3e 06 d1 6c +0a 0a c1 53 0d 21 f0 33 7e 26 2f d9 d2 7f cc 4a +fe b5 74 d6 68 66 d4 ca 84 cf d6 e0 af 2b b9 77 +a5 d9 9a 5b 0b 37 44 04 2d 33 2b 93 6b bd d8 69 +e5 f2 c8 83 b4 00 ac 8b c0 68 3e 67 90 63 42 9d +98 d4 94 f3 18 04 d6 5b b3 c9 74 aa 72 e6 65 7d +4c 16 38 c6 79 c8 1a 16 45 3f 6b 0b aa 3f 05 17 + +# PKCS#1 v1.5 Encryption Example 15.12 +# ---------------------------------- + +# Message: +49 f6 f8 a4 a8 6a 8a a0 97 63 aa c8 55 72 b0 e7 +ee 77 6a ef f8 a8 29 00 07 76 ff a6 + +# Seed: +6d b6 a8 27 ac 2a 5e 06 16 c0 f4 43 b2 34 58 e1 +75 ac f9 a3 b2 55 f5 c8 52 5e 72 53 42 4f aa 91 +38 05 4c 3d ba a4 71 f2 7f e8 55 c1 c0 ce c3 62 +59 7a 1a 1e 6e b4 f2 98 ac 3e b7 34 d3 1f f0 ef +10 08 c0 e0 2b 9b 06 e2 93 15 fc 09 4a 7e d2 6b +11 ea 55 27 0a 3d cb 67 06 f4 6a 94 50 bf 83 12 +88 10 65 13 02 48 d2 64 47 66 a7 99 66 ef da db +aa f5 75 ef 4d d3 5a 93 7f f0 bf bf 3d 95 61 c7 +54 40 9b e7 b8 84 7a 60 8d 79 1f b9 87 ee d4 6a +fe b0 db 1c a9 75 c0 5f 61 57 0d d0 70 98 5f 13 +e4 e0 ed 7a 8c b3 91 ce 4d 42 08 32 b4 5a 8b 7e +9f 90 88 4e 61 18 98 f4 72 a0 ac 46 c5 7a a7 f8 +46 8a a1 9d 9c 7b 31 2f 13 43 22 99 03 93 88 1d +32 aa 14 68 f6 e5 f8 eb 85 a2 c3 c2 da ed 92 b9 +3c + +# Encryption: +0f f9 5f 4a 2a 07 18 d6 73 f9 20 2c 80 9f 10 45 +10 1f 52 b9 db a7 72 88 fe 28 8c b2 77 c4 db aa +35 db 93 27 ec ee c3 76 5a e0 33 e0 b6 b7 77 b2 +2c a6 be 66 20 03 ea fa 2b fb da 60 6f d8 ce e7 +ee e0 6c 6a 00 c9 45 a6 55 6c 60 b0 08 69 f9 99 +97 1a 8c 57 af e1 dd ee 7a 75 77 04 7a 0d b9 0f +62 cd 24 7a 88 7f 32 27 ef 6d a9 07 a7 5b cf f1 +9a a3 0c 90 8f 58 35 ef 10 10 0a dc 7f 6a d6 fb +31 99 79 0b 3f 4d 6a d1 9a 0d f5 02 7f db 8f 84 +66 04 e0 2d af 33 55 d9 56 40 77 79 af 15 5a cf +a5 a3 2e 6d 61 74 dc 90 13 1d bd 7a be 58 5d d7 +59 fa 3c b7 e9 f7 21 45 3f 3e 35 4f e7 be 0b 11 +8e f5 b8 79 42 b5 fe d4 c3 0d 7a 08 fe 24 64 eb +79 a3 de ba b3 7b 6d 3a 0a b3 15 77 de 7e 93 22 +9b 49 d1 e8 fd 56 32 d0 26 d8 3e e0 6a a7 85 34 +ce e3 08 1b 22 2e c4 cd 94 88 cc de 4e 15 29 05 + +# PKCS#1 v1.5 Encryption Example 15.13 +# ---------------------------------- + +# Message: +12 97 5d b7 3d + +# Seed: +6a 4b 4f b8 05 80 72 72 96 5b ff 2f 4c 80 0f 96 +4f a3 ae b9 fb 43 3b 40 c8 ac c5 98 b4 84 02 98 +93 a2 19 c9 53 21 34 c0 6a c8 42 5c 28 a5 f0 63 +c2 84 20 0a 04 56 43 48 97 16 51 6a 98 7b f8 1b +a1 86 f4 ce b8 d8 d9 dc 1d 73 f2 26 7f d1 98 8d +6a 2f fd 68 cd 36 69 de 2b 04 70 09 43 d0 d4 44 +ae 3d a8 f0 59 4e 62 61 e5 ff f6 07 f0 4d f3 1e +3d 9c 91 22 d7 6f b9 0f 3f 82 c3 93 25 3b 75 20 +16 5b d1 f3 19 ab 3b 87 5e cc 6a b3 ed 02 47 d0 +37 70 f8 d6 47 1d 69 cd 13 ee 25 7c 1f c8 b3 0f +19 b9 3f e4 f2 fc 9c 21 49 28 13 d1 fc 85 2a f7 +0c dc 63 84 d2 ae 55 b9 1e 39 ae 6c 3b 19 fd 1a +7d ea f7 18 c0 5d 57 80 95 96 a2 88 fc 9a ef b8 +15 ae a2 9f af 67 83 c0 05 35 fd 71 d6 25 49 40 +b7 62 f5 07 26 1f 20 9b c8 ba 94 79 bb 3f 5d 64 +64 23 19 cc 31 86 85 9c + +# Encryption: +27 15 d6 eb 53 ae e6 d4 bd dd 3b e9 b6 63 14 4a +41 0d 03 81 77 9f 79 9d ca 88 07 92 ab 43 1a f9 +98 9d eb 17 36 9d c6 74 38 ad d8 2b df 0a 59 dd +3b c2 78 01 02 58 c7 df 87 69 84 ff 52 76 78 bf +9b 34 c0 77 43 b5 d2 2f 4f 30 cb 5d 7d 8a 6c fd +50 58 24 f2 e0 94 02 4f b0 43 30 f6 6d a7 cb c0 +1d 5e cc 8d fc a1 ca 9e 50 91 b9 d9 c8 e3 8d 0a +c3 93 1d e5 d1 fd c8 33 73 84 82 a7 fd 15 2c 1d +24 e6 9e a0 1d d3 e1 fa 77 23 54 a6 07 d6 2c 60 +b5 61 dc 5c cb 01 2b 71 2f 5c 2d a1 89 2c 31 20 +ef 99 0d 74 61 1d dd 35 66 af 1a cd 8b 48 50 06 +1c 91 28 f8 2a d1 12 da 9f 68 ac 88 39 3f 9a 5c +2c 10 20 aa 77 e9 b6 2e 2d 1e 98 5f ef 86 4c c1 +ae b4 51 ac 83 9c 72 0c b9 73 e7 b5 df 24 a9 8c +cb 6e 67 72 66 29 a3 66 fe a3 f9 a9 52 1d aa 19 +b0 44 30 e8 10 f2 c4 5a 57 d4 25 3b ed b9 1d a0 + +# PKCS#1 v1.5 Encryption Example 15.14 +# ---------------------------------- + +# Message: +8d e0 f5 a4 13 a7 f7 86 39 6f 09 a4 5e 5e 77 4f +3c 60 9c e6 f1 b4 90 dd e2 22 b3 22 d5 34 0e 9b +10 55 81 f4 c5 be 44 ea bb 3d 1b 23 f8 45 + +# Seed: +f8 71 a8 97 ae e8 45 c3 bb 82 69 90 b7 31 d2 77 +7c f4 76 b5 cf c5 59 6d f3 a5 23 ba 69 79 c7 a4 +51 79 da 5f d6 0f 81 0b f4 14 c5 4e 18 2f 26 01 +72 0f fe 8a 50 d7 d9 d1 1e 56 43 18 e9 02 6f 07 +c5 aa a1 3e f8 91 28 3a 96 63 c1 e3 d2 7b 93 81 +7d 01 a5 6f ce 33 d5 16 9b fe a6 2a 8e e6 c3 70 +a3 aa 8c 71 94 d9 d3 53 d0 98 16 61 fe 85 81 62 +50 e0 32 4e ae 1b 84 7f c7 32 91 91 60 d0 1e 11 +92 ac 16 be 0e b8 e9 95 e4 86 40 27 6a 2d b7 b8 +7f 84 b3 fa c0 4c e8 62 f0 22 38 62 3f 62 b9 2a +2e 32 7b 01 b8 c7 b9 e5 ec 87 05 5c 6c b7 b5 56 +51 ab 5a c9 89 83 3b 03 4f 8b e0 11 6f 28 b1 e8 +86 a2 ce d1 23 29 8e b0 04 07 5a 6b 5b 71 b1 + +# Encryption: +d3 67 ac a8 d4 f1 74 14 e9 bf 09 ad 81 1d 78 db +0e 85 0c 45 c8 f9 d7 02 44 75 d3 e5 6e 3c bf be +6e e8 ab bf d7 74 58 26 41 7c c8 ed 52 f5 4e 00 +a9 2f 81 7e f9 83 e9 8d 10 0a 1f 99 0d b1 e2 90 +a8 51 6d 60 9b b3 2e 50 2a 77 e1 1f 76 20 0b 00 +25 76 5e 9b d2 85 9b a9 4a 69 63 33 a5 eb e2 eb +25 ba 9d 19 00 7f 64 36 0c c0 75 ca d7 f0 99 50 +e4 b7 af cb ac 36 e6 ec b0 17 cf 4a 1f 25 a4 d2 +b9 51 bb 85 e8 1c b2 b4 eb 6f 45 cd d4 00 d2 ac +4e 21 69 89 6d 94 15 82 44 9c e3 0f 69 c1 7c b4 +49 32 1f 65 e4 4d f3 03 87 86 27 62 13 51 f5 2e +5a 07 52 e3 b5 eb 12 63 61 69 7f 53 cf 24 66 16 +5c 3f bd 66 2b 83 75 80 b7 6d 45 9f f0 44 97 e5 +fe 1b 3c d1 8c 4d 58 ff ed ab dd 04 a8 c1 08 d8 +59 b6 52 98 63 9c 3a f8 0c d9 4e 23 87 a8 69 44 +09 ef 9e 0b 78 b6 f4 67 39 0b e1 08 57 9c 9b 2c + +# PKCS#1 v1.5 Encryption Example 15.15 +# ---------------------------------- + +# Message: +9e 78 c8 2b fd 0f 23 d3 91 e7 60 01 64 01 9a ad +28 f5 9b 14 15 44 04 d9 e9 66 13 3c 10 3f c3 7c + +# Seed: +bb 42 24 7d b2 40 ba ca cb cb e8 c6 8c b0 f7 0e +46 0a 49 73 da e6 56 99 35 8f ef 82 70 d6 5c 3d +0c 45 5a 37 9c 56 3c 59 7b 28 f4 ff a0 70 e0 ec +1e bb 9e d4 27 fe 89 ab cd 47 93 c4 22 c3 38 87 +8c 8b 14 5b 46 c4 f7 13 78 a0 fd 7d 50 53 b8 67 +98 bc 02 d9 32 93 fe d8 47 f1 8f e0 61 59 07 4a +c1 89 d9 56 23 20 74 db 6d dc f9 94 1a 70 f2 8b +60 e4 83 39 5a 2d 21 01 54 b6 2a ba b8 75 0f 5a +eb f1 ac ef e2 05 6f 5a bd 2f 0e 0e c4 94 af a8 +2f c5 9b b3 57 f1 16 a9 4e c1 cd 06 03 b5 2f e5 +6d 31 a4 3b 87 aa 63 77 88 c7 24 cb 6f 88 37 3c +92 f6 07 11 bf 3f 35 94 e2 3d ee 2f ec ed fe 6f +5f c8 86 e9 6a ee 7c 74 68 22 e5 6c ba 7e bd aa +2a 92 10 ea 81 98 e4 c2 2d e9 29 89 45 + +# Encryption: +81 8d cb ba 98 c3 46 79 3c 79 d4 bb 78 5a a6 40 +19 1b 05 f8 83 5f f7 39 74 44 3b ce 35 7a 26 9d +44 64 6e 8c 79 10 2d ce 22 92 39 78 a3 94 1e bc +b9 90 4f c1 bb 1f b4 3f 11 27 5e 71 eb 7a 84 d2 +74 be 10 4b 00 af 92 25 e2 a4 f7 f5 a0 48 ab b6 +6c ba b6 52 5d 1b 11 5d a8 c0 bb 08 de ea ec 7f +80 eb 6c 39 50 4d c4 eb 38 15 4c e4 b6 91 b4 06 +93 19 b2 93 c2 5d c3 0b 8f b3 8b ca 15 3e 2f a6 +1b 33 76 dd c3 c5 3a 57 93 21 d9 10 a1 71 fc 42 +aa f1 70 50 ed 6d 31 1a 7d f5 b9 a5 cf 3a 98 fd +69 aa 85 ac 23 46 c1 6f a0 3b 1e 53 d1 03 d6 f5 +a0 4b 0d 9d 3f 18 83 53 1e 2f 63 41 fd 91 bd 63 +a5 aa 99 3b 6e db 99 92 e5 db 17 a7 be 55 5e af +a3 bb ab 32 08 6e 92 b8 b7 91 06 69 68 e0 0f 8a +17 71 61 44 0c e5 38 57 97 89 c2 91 2e bd 7a d0 +19 be 29 37 6c ad ee c2 99 21 07 c9 db 07 60 49 + +# PKCS#1 v1.5 Encryption Example 15.16 +# ---------------------------------- + +# Message: +6d 72 08 b2 ff b0 1a d2 36 0c 46 09 f3 ba d3 15 +79 c8 d4 00 5c c9 60 14 2e 2b 69 6b 26 e9 4f 2d +99 98 0b ad 38 41 05 b1 89 95 57 af 89 05 25 + +# Seed: +72 ae 49 97 18 28 ba 54 23 ab 96 3c db 18 f4 bd +fd bc 74 73 cf 70 fb 77 21 34 41 f1 d4 46 ae 48 +10 93 03 a2 60 c0 91 ab 51 99 d9 64 e6 21 63 c2 +46 57 24 71 73 cb 05 11 b9 cb b1 63 45 9c 95 6f +9c 0b 18 83 b6 91 b5 e4 ea e0 4f 0a f2 4e a3 28 +c6 de 88 2c eb c4 f8 9a 56 37 32 82 d6 0a f2 ba +96 7e 25 7a c4 01 a3 7f 94 41 c1 1f 2e 0e 42 1b +2d 15 1e b2 43 a9 7e ae 5a aa 86 cd 38 df 43 c2 +6a 1d 6e 3b 12 c1 3f a3 59 7b 85 bb aa 13 09 45 +2c 7e 9b 32 5d 8c 73 fa 79 9c 57 56 52 73 7b 92 +a2 47 d2 3c 4c 70 12 40 c5 3d cf e2 ea 69 7a f6 +1c 07 2f a7 6b db 05 2a 58 c9 19 e6 9e c5 7b 39 +a2 a6 c4 7d 77 0e de 67 10 fc 7b dd e6 01 + +# Encryption: +4b 56 dc d3 04 bd c7 f0 cc b7 0d 2c 58 6f 52 74 +60 1e e6 05 36 bb 21 80 61 67 13 50 d6 d3 ae 2e +28 4f 07 b5 ed 63 01 79 26 94 13 12 2b 98 37 60 +90 f7 a4 a4 f6 43 4a f7 3a c4 0c 7a f4 b6 d7 a3 +e3 14 70 2a b9 b8 5e 08 73 1d a0 d1 2e d3 f0 07 +0b 0d 20 95 05 3b 3f 0d 09 d6 c2 cd 8f 98 ba de +d9 11 48 c3 5b 7b 33 c5 43 65 3c cc 32 d8 36 f5 +f7 f2 ee 39 ca bd 0b d8 9d d9 a4 a9 4e 91 2b 4c +a9 7f 18 51 d0 17 45 1f 60 96 ac bf 20 a6 5e c5 +a2 9f 08 f8 13 5c 73 18 a2 21 6d 1b 7d 10 37 95 +c7 ec 8e e5 7a 79 28 0f 9a 84 4b d6 ab 71 28 82 +0e 1f b5 e8 25 54 fe c0 2a 78 aa 8d 3f d6 a1 3e +0f ad 0e ce e7 ab 61 1d e4 b0 a0 48 1f 42 b8 d0 +b5 5c b8 81 3d 1c a6 e2 61 5c f5 ae 8a e8 6d 0b +5d 46 95 50 75 49 f7 a3 73 66 a4 45 fb 55 b7 c4 +b6 b5 8e a6 99 db e5 dd c8 19 3e 2b f3 d5 b8 40 + +# PKCS#1 v1.5 Encryption Example 15.17 +# ---------------------------------- + +# Message: +7d eb 6d 40 41 48 23 2c 48 21 63 4d 3d f9 bc + +# Seed: +e6 f8 3c 8c 99 3e 60 15 af 43 04 09 68 4e 62 7f +3d 9b 84 ad 05 55 c6 a6 c0 91 13 a7 12 47 2a bb +36 f6 11 92 32 6c f8 40 82 aa bd 1e c9 5f 4d 1a +92 d9 10 7e 30 61 0c 8d 27 59 55 6d 5d 61 47 5c +a3 f3 cb d9 49 fa c2 20 3c 42 3d 56 c2 75 58 e6 +11 8f aa 0f 6f 68 4a da 13 c3 15 3f 6d 25 53 38 +bf f7 34 e9 5f 60 ad 29 19 ab f2 88 15 d3 cc 0b +1e fd 38 5d 0d 45 81 b0 ee 84 94 f2 bb e2 99 59 +91 ac 1e a8 15 40 cb 7e 88 56 68 e5 a5 2e ca 90 +57 ed 9a 1f b2 3f df 83 b5 75 51 35 8c 23 cd 43 +ce 0e 7a 33 c7 25 66 b8 8f e5 93 43 f1 87 24 46 +d3 2c 44 b3 99 0a a4 db 3e e5 93 42 4c 8e 09 46 +d2 61 e3 27 0e f4 07 6b b3 5d f3 c3 c6 da 4b be +42 3f 59 1b 5c 93 ba 56 c5 cf 01 d4 f0 a9 40 96 +71 09 d3 9b 93 9d f2 82 53 2e 54 83 10 8b + +# Encryption: +aa 6e 6e 4a f6 89 26 4d 61 bf a8 f5 08 6d 82 79 +dd c2 28 9c 55 41 af 45 35 19 c4 4b 95 ea e6 a1 +5e 7e 7b d1 5f d3 1a 4f ad 5f 7c 85 90 5e fc a2 +26 93 0d 67 da f5 58 b7 15 b2 1f 36 28 f6 1a 3b +04 2c 1a 38 f9 af 3a da 82 ec 44 88 c8 ad e5 f1 +da 81 e1 a8 ab 90 e1 b3 12 dc da 83 5f 9e 92 5f +2e 72 46 3f a8 33 a0 8b 93 25 3f df e8 cf 4e 5f +3c fa 91 10 77 19 a6 a9 46 9a cd 71 25 ae 67 b2 +bd 75 85 7c 59 be 0a be 98 40 74 e2 95 47 8a f2 +74 0e 25 89 4e 56 a6 25 0e f7 36 21 94 13 81 03 +74 3c a9 54 47 33 d2 50 55 71 be e0 0f 17 8a 2c +fa 38 e1 f8 f2 2f b2 39 30 d6 a7 5d d1 7c 68 9a +47 6d 87 15 31 85 95 10 8f cc e8 95 e3 44 9e ca +97 a7 dd ba e3 e6 d6 f0 e3 5e 66 6d 6f bd 78 78 +48 f8 68 13 37 b1 d4 c5 23 8b 1c 24 de 77 a7 e6 +75 e7 ae d8 dc 13 dd 9e b1 06 87 98 51 7c 0b 6e + +# PKCS#1 v1.5 Encryption Example 15.18 +# ---------------------------------- + +# Message: +03 1f c3 a3 ea a4 2b 0d 9f 6d 7d d5 99 3d 61 89 +cb b2 e0 e9 6f aa 33 d6 1f 31 7b 6b 3c 00 + +# Seed: +16 ab 64 85 ca c0 39 71 14 88 0e 6f 72 bc 1f 1e +f3 4b a2 7d 1c 43 3d 77 f3 37 2b 1f d5 b2 1b a5 +7a 50 5c d8 f3 5b 75 24 2c f1 b7 6d 38 1c 68 34 +24 01 ee ef c8 42 53 a2 de 1a 19 13 e4 38 77 3b +7b cb 31 cb ab 25 8f 72 6a c9 34 a8 71 26 96 9a +db 7f 76 8c 1b ab 87 54 a1 3a 3c cb ba 6f 3d d8 +d0 ec 6a 7c 6d 68 7d 04 95 b6 e2 2c 9a e7 67 af +c9 d9 4f 2e 45 a1 06 13 3c 42 c7 9b 52 c2 6a d4 +b6 7b d8 ec e5 5e 84 32 5c a6 f4 9c 8e 95 31 f5 +f6 b9 ca c3 5c 93 3e eb e3 b9 a1 1b 9b b1 c9 ea +8c e6 d2 28 5d a9 08 e5 91 97 82 b5 b3 08 fe 47 +8d 98 e4 9a ea 54 3b f8 ca 1b 22 ed f4 3f db f6 +af 31 cc 8c d4 fb 7d e2 d8 19 af a5 48 3e ac dd +56 d7 78 7b c8 bb 16 22 38 40 49 bc 30 9a 66 + +# Encryption: +61 c7 54 76 30 43 b5 84 e4 a8 54 6b 79 f0 a3 e2 +e0 f3 b3 e2 db 6c 94 ad 81 7e 92 81 f4 85 c0 82 +08 fe d4 f4 d7 d0 a7 8c 6c 31 1a 07 c7 5b 9b be +85 04 f4 b7 a6 92 99 02 16 de 12 58 5c 00 9a e5 +8c 26 f0 85 07 1f 39 5e 5a f8 92 5f 39 33 f6 d9 +f4 12 d4 25 54 64 54 e8 00 b7 e3 aa c7 8b 7a 08 +b9 2e 79 8b b8 34 eb ea dc 4b 4a 63 56 af 1c a0 +9b f5 86 74 5f 61 6d 51 74 8c c7 a3 7b 48 cb 10 +97 7e 30 3b be 10 bf 27 c6 9b df f0 ba 5c ab 8f +62 d0 58 7a 09 d6 e0 22 82 32 33 c8 c7 aa 41 87 +22 23 ed 15 a7 4a cc b0 f1 f8 22 f2 4d 75 94 ed +99 25 a1 c6 c0 c0 f9 ad 0e 07 1e b6 b5 eb e1 ba +b6 ba 3b 6d 99 a3 16 52 04 7f 46 92 60 be e8 71 +0e 37 0f 04 ed 70 75 93 93 7a 08 dd 82 26 49 92 +31 1f 4a f9 88 4c f8 ad 34 af b9 f6 75 99 3c 8a +bf 41 51 98 39 f7 6f a1 e9 31 bd ae 1d 08 a6 34 + +# PKCS#1 v1.5 Encryption Example 15.19 +# ---------------------------------- + +# Message: +c9 c9 3a fe a9 97 b1 ee 36 fa 72 72 03 54 c7 04 +64 9b c6 ef 44 f5 18 7c 6c 28 54 2b 9a e9 55 a7 +19 3f ff ec 86 7b b6 2e 21 9e 68 + +# Seed: +52 d4 c3 bf 0c 77 2c 02 d3 bb 71 1d 7f 14 6d 8c +49 76 f8 30 81 be 49 53 d4 af eb 07 8e 54 12 a3 +2c 3d c7 37 b5 9b c4 54 c3 de 93 a1 ae d0 7c 1b +a6 4d 1d e4 36 80 14 d0 4f 64 40 55 6a 4a 16 97 +9d 08 03 cc 29 22 da 97 ed 67 61 90 12 f8 f7 d3 +b1 a4 55 84 b0 94 6a f6 db d4 a0 85 7d 4c 2d b9 +9a 17 bb d2 7a cd 9a 62 e6 7f 88 79 db ef 27 f1 +04 6a 86 7e 69 95 16 2b 2a 1a 1c cc dc ea f4 5b +e1 33 7e 5f a8 f8 5e da ad f7 50 8d 58 f3 26 aa +7c f3 01 f4 41 ba 55 8b 60 e0 fa c6 e0 d1 99 20 +61 a0 a4 69 be 02 16 26 89 0e e8 7e 68 13 9b d5 +19 ae 77 3e 3e c4 81 b7 f2 b3 77 33 1f 52 f2 e3 +86 88 4f 76 57 23 e2 6c d4 a8 d9 68 61 4c 9c 33 +dc db + +# Encryption: +d0 68 67 02 2a 0f af 57 3d 62 cc 24 a6 e0 6a 44 +cd 3d 83 ea c5 d0 80 9e bf 91 30 45 68 cb 1b 27 +56 1b b2 92 e8 77 6e 21 6d 1d 02 3e 75 3c 12 4b +51 86 7b 94 dc 60 89 4d 62 c7 da e5 fa 1a 9f af +03 76 e1 75 8c b6 ad c7 14 17 e8 31 02 52 8f 23 +f4 c5 e5 b5 03 62 a3 9e 2a a9 76 8b 10 62 08 6f +a8 c5 3f f1 c3 9a 0e e0 3d 38 3d 24 bf 49 07 22 +b7 86 da ec 90 8c d7 15 1e 18 5d dd 17 88 26 78 +02 7e 36 8b 05 12 cf 98 41 3f 3e 59 6f a3 db 4e +c1 96 ae 5f f5 24 a8 26 6d 76 0e 00 51 43 3d 18 +98 ff c2 30 e9 6a 2f 0b fd f2 b2 44 29 ad fa 91 +8a ba 1a 45 0f 76 78 34 72 30 12 93 84 8b d8 2d +5a 33 84 31 d6 cb 1c 10 6d c7 41 d2 34 bf 5a 80 +db d3 25 da 64 a3 94 a0 06 5f 22 02 8d 0f dc 5a +df 0d 0d e2 9f 22 fb 8c 2a 41 33 1f e1 fc b6 15 +89 e0 ec 75 00 ed 84 42 d6 18 46 df 6c ca 46 cc + +# PKCS#1 v1.5 Encryption Example 15.20 +# ---------------------------------- + +# Message: +69 b7 64 48 55 f9 1d 1c 61 c8 49 8e 4b a1 ba 4d +84 5b a8 82 b1 73 + +# Seed: +b2 2f c7 de 85 c5 f7 5a 2f 32 af 1b fb cd 57 89 +71 56 87 de 06 e6 6d 06 4a e3 eb 8d fb 07 a2 57 +5b e0 e9 e6 f2 9f 50 d7 39 6d 07 8b 36 ef 80 2f +75 1a 77 cc 92 d7 61 4c 91 dd 27 99 31 fc e0 07 +eb f9 15 a0 f1 4e 31 2c e9 1f e5 aa 6f b3 74 51 +61 4f e3 7c 73 fc 6f 6d 6f 8e 52 78 9b 5d 88 e8 +6b eb 16 33 f5 dd d5 c0 70 f1 4f d3 cf ee 97 dd +4a 64 3d 35 d4 5d d9 bf 34 df 8c 31 0b 48 59 2e +94 68 31 b3 4e f3 c0 b9 16 f1 7c b0 ac b2 cf c1 +c2 5d 03 09 ac c1 12 4f 26 5c 1a 83 ed 88 5c 87 +fa 82 6f da 57 10 b5 4e 16 ec 0f 44 8c db 7e e0 +58 0f f7 38 65 30 ea 46 1e 04 2a 0b 77 42 c4 61 +97 6b b5 a3 80 ad bc b0 01 06 f2 67 1b 6c ce 4f +72 67 75 2f 80 66 80 42 78 35 0b 01 75 3e 31 b3 +8e cc fb e9 05 69 f6 + +# Encryption: +ab 42 67 97 2c 77 96 83 93 88 d4 ad 87 de d7 4b +b6 53 e9 a7 05 0e 28 2e 82 19 28 75 68 9f 70 ee +1d a1 8a 1f 73 22 09 2c d2 9f d0 01 19 92 2a 6d +e1 26 01 98 0a a9 fa 6e 61 9e 27 75 e8 7a da e3 +16 95 c1 30 4e 77 f5 2c ce 01 66 65 f2 26 7c 20 +76 26 43 c6 00 3c 01 6d 84 80 44 3c 70 1d f6 c1 +d8 d6 55 54 96 00 ee 45 5b 70 e4 73 31 9b 0d 44 +45 e0 b7 55 2a 1f 80 8e 88 f3 26 48 42 73 5a e6 +1d f0 32 5e d0 36 90 d6 d5 d6 93 ad 1f ed 22 66 +84 50 37 9d b5 32 3d c0 1c 89 af fa e3 69 b9 c3 +01 c3 19 c3 7d df 51 ed f4 6e 09 b2 1e 5d e9 14 +83 e8 e3 cb 21 ee b7 05 7b c2 eb dc 3a aa 3d 65 +00 c9 2f 99 b1 7b 31 80 bb a0 47 d7 60 73 77 63 +36 b1 5d 05 4d 79 a4 40 cc 5e 98 5e a5 43 fc aa +25 db 1d d8 92 b7 1b b7 4a 5c f6 82 63 d8 fd 58 +f1 a4 8e 6c 2f cb 8c 0b 71 a2 51 cf c1 a2 01 57 + +# ============================================= diff --git a/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.c b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.c new file mode 100644 index 0000000..0483c87 --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.c @@ -0,0 +1,4261 @@ +/* Generated from file: pkcs1v15sign-vectors.txt + * with md5 hash: d799f020ab2fc966cae369de7ff62641 + */ + + +typedef struct rsaKey { + int n_l; + unsigned char n[256]; + int e_l; + unsigned char e[256]; + int d_l; + unsigned char d[256]; + int p_l; + unsigned char p[256]; + int q_l; + unsigned char q[256]; + int dP_l; + unsigned char dP[256]; + int dQ_l; + unsigned char dQ[256]; + int qInv_l; + unsigned char qInv[256]; +} rsaKey_t; + +typedef struct rsaData { + const char* name; + int o1_l; + unsigned char o1[256]; + int o2_l; + unsigned char o2[256]; +} rsaData_t; + +typedef struct testcase { + const char* name; + rsaKey_t rsa; +#ifdef LTC_TEST_EXT + rsaData_t data[20]; +#else + rsaData_t data[1]; +#endif /* LTC_TEST_EXT */ +} testcase_t; + +testcase_t testcases_emsa[] = + { +{ + "Example 1: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51, 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e, 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a, 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62, 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf, 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab, 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d, 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77, 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59, 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3, 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f, 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8, 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51, 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf, 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe, 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f, 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3, 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44, 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10, 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27, 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c, 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f, 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e, 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc, 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 } +, + /* Prime 1 */ + 64, + { 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73, 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa, 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96, 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb, 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b, 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e, 0xda, 0x8e, 0x64, 0x43 } +, + /* Prime 2 */ + 64, + { 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7, 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f, 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48, 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba, 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e, 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26, 0x9a, 0x67, 0x99, 0xfd } +, + /* Prime exponent 1 */ + 64, + { 0x28, 0xfa, 0x13, 0x93, 0x86, 0x55, 0xbe, 0x1f, 0x8a, 0x15, 0x9c, 0xba, 0xca, 0x5a, 0x72, 0xea, 0x19, 0x0c, 0x30, 0x08, 0x9e, 0x19, 0xcd, 0x27, 0x4a, 0x55, 0x6f, 0x36, 0xc4, 0xf6, 0xe1, 0x9f, 0x55, 0x4b, 0x34, 0xc0, 0x77, 0x79, 0x04, 0x27, 0xbb, 0xdd, 0x8d, 0xd3, 0xed, 0xe2, 0x44, 0x83, 0x28, 0xf3, 0x85, 0xd8, 0x1b, 0x30, 0xe8, 0xe4, 0x3b, 0x2f, 0xff, 0xa0, 0x27, 0x86, 0x19, 0x79 } +, + /* Prime exponent 2 */ + 64, + { 0x1a, 0x8b, 0x38, 0xf3, 0x98, 0xfa, 0x71, 0x20, 0x49, 0x89, 0x8d, 0x7f, 0xb7, 0x9e, 0xe0, 0xa7, 0x76, 0x68, 0x79, 0x12, 0x99, 0xcd, 0xfa, 0x09, 0xef, 0xc0, 0xe5, 0x07, 0xac, 0xb2, 0x1e, 0xd7, 0x43, 0x01, 0xef, 0x5b, 0xfd, 0x48, 0xbe, 0x45, 0x5e, 0xae, 0xb6, 0xe1, 0x67, 0x82, 0x55, 0x82, 0x75, 0x80, 0xa8, 0xe4, 0xe8, 0xe1, 0x41, 0x51, 0xd1, 0x51, 0x0a, 0x82, 0xa3, 0xf2, 0xe7, 0x29 } +, + /* Coefficient */ + 64, + { 0x27, 0x15, 0x6a, 0xba, 0x41, 0x26, 0xd2, 0x4a, 0x81, 0xf3, 0xa5, 0x28, 0xcb, 0xfb, 0x27, 0xf5, 0x68, 0x86, 0xf8, 0x40, 0xa9, 0xf6, 0xe8, 0x6e, 0x17, 0xa4, 0x4b, 0x94, 0xfe, 0x93, 0x19, 0x58, 0x4b, 0x8e, 0x22, 0xfd, 0xde, 0x1e, 0x5a, 0x2e, 0x3b, 0xd8, 0xaa, 0x5b, 0xa8, 0xd8, 0x58, 0x41, 0x94, 0xeb, 0x21, 0x90, 0xac, 0xf8, 0x32, 0xb8, 0x47, 0xf1, 0x3a, 0x3d, 0x24, 0xa7, 0x9f, 0x4d } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 1.1", + /* Message to be signed */ + 217, + { 0xcd, 0xc8, 0x7d, 0xa2, 0x23, 0xd7, 0x86, 0xdf, 0x3b, 0x45, 0xe0, 0xbb, 0xbc, 0x72, 0x13, 0x26, 0xd1, 0xee, 0x2a, 0xf8, 0x06, 0xcc, 0x31, 0x54, 0x75, 0xcc, 0x6f, 0x0d, 0x9c, 0x66, 0xe1, 0xb6, 0x23, 0x71, 0xd4, 0x5c, 0xe2, 0x39, 0x2e, 0x1a, 0xc9, 0x28, 0x44, 0xc3, 0x10, 0x10, 0x2f, 0x15, 0x6a, 0x0d, 0x8d, 0x52, 0xc1, 0xf4, 0xc4, 0x0b, 0xa3, 0xaa, 0x65, 0x09, 0x57, 0x86, 0xcb, 0x76, 0x97, 0x57, 0xa6, 0x56, 0x3b, 0xa9, 0x58, 0xfe, 0xd0, 0xbc, 0xc9, 0x84, 0xe8, 0xb5, 0x17, 0xa3, 0xd5, 0xf5, 0x15, 0xb2, 0x3b, 0x8a, 0x41, 0xe7, 0x4a, 0xa8, 0x67, 0x69, 0x3f, 0x90, 0xdf, 0xb0, 0x61, 0xa6, 0xe8, 0x6d, 0xfa, 0xae, 0xe6, 0x44, 0x72, 0xc0, 0x0e, 0x5f, 0x20, 0x94, 0x57, 0x29, 0xcb, 0xeb, 0xe7, 0x7f, 0x06, 0xce, 0x78, 0xe0, 0x8f, 0x40, 0x98, 0xfb, 0xa4, 0x1f, 0x9d, 0x61, 0x93, 0xc0, 0x31, 0x7e, 0x8b, 0x60, 0xd4, 0xb6, 0x08, 0x4a, 0xcb, 0x42, 0xd2, 0x9e, 0x38, 0x08, 0xa3, 0xbc, 0x37, 0x2d, 0x85, 0xe3, 0x31, 0x17, 0x0f, 0xcb, 0xf7, 0xcc, 0x72, 0xd0, 0xb7, 0x1c, 0x29, 0x66, 0x48, 0xb3, 0xa4, 0xd1, 0x0f, 0x41, 0x62, 0x95, 0xd0, 0x80, 0x7a, 0xa6, 0x25, 0xca, 0xb2, 0x74, 0x4f, 0xd9, 0xea, 0x8f, 0xd2, 0x23, 0xc4, 0x25, 0x37, 0x02, 0x98, 0x28, 0xbd, 0x16, 0xbe, 0x02, 0x54, 0x6f, 0x13, 0x0f, 0xd2, 0xe3, 0x3b, 0x93, 0x6d, 0x26, 0x76, 0xe0, 0x8a, 0xed, 0x1b, 0x73, 0x31, 0x8b, 0x75, 0x0a, 0x01, 0x67, 0xd0 } +, + /* Signature */ + 128, + { 0x6b, 0xc3, 0xa0, 0x66, 0x56, 0x84, 0x29, 0x30, 0xa2, 0x47, 0xe3, 0x0d, 0x58, 0x64, 0xb4, 0xd8, 0x19, 0x23, 0x6b, 0xa7, 0xc6, 0x89, 0x65, 0x86, 0x2a, 0xd7, 0xdb, 0xc4, 0xe2, 0x4a, 0xf2, 0x8e, 0x86, 0xbb, 0x53, 0x1f, 0x03, 0x35, 0x8b, 0xe5, 0xfb, 0x74, 0x77, 0x7c, 0x60, 0x86, 0xf8, 0x50, 0xca, 0xef, 0x89, 0x3f, 0x0d, 0x6f, 0xcc, 0x2d, 0x0c, 0x91, 0xec, 0x01, 0x36, 0x93, 0xb4, 0xea, 0x00, 0xb8, 0x0c, 0xd4, 0x9a, 0xac, 0x4e, 0xcb, 0x5f, 0x89, 0x11, 0xaf, 0xe5, 0x39, 0xad, 0xa4, 0xa8, 0xf3, 0x82, 0x3d, 0x1d, 0x13, 0xe4, 0x72, 0xd1, 0x49, 0x05, 0x47, 0xc6, 0x59, 0xc7, 0x61, 0x7f, 0x3d, 0x24, 0x08, 0x7d, 0xdb, 0x6f, 0x2b, 0x72, 0x09, 0x61, 0x67, 0xfc, 0x09, 0x7c, 0xab, 0x18, 0xe9, 0xa4, 0x58, 0xfc, 0xb6, 0x34, 0xcd, 0xce, 0x8e, 0xe3, 0x58, 0x94, 0xc4, 0x84, 0xd7 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 1.2", + /* Message to be signed */ + 51, + { 0x85, 0x13, 0x84, 0xcd, 0xfe, 0x81, 0x9c, 0x22, 0xed, 0x6c, 0x4c, 0xcb, 0x30, 0xda, 0xeb, 0x5c, 0xf0, 0x59, 0xbc, 0x8e, 0x11, 0x66, 0xb7, 0xe3, 0x53, 0x0c, 0x4c, 0x23, 0x3e, 0x2b, 0x5f, 0x8f, 0x71, 0xa1, 0xcc, 0xa5, 0x82, 0xd4, 0x3e, 0xcc, 0x72, 0xb1, 0xbc, 0xa1, 0x6d, 0xfc, 0x70, 0x13, 0x22, 0x6b, 0x9e } +, + /* Signature */ + 128, + { 0x84, 0xfd, 0x2c, 0xe7, 0x34, 0xec, 0x1d, 0xa8, 0x28, 0xd0, 0xf1, 0x5b, 0xf4, 0x9a, 0x87, 0x07, 0xc1, 0x5d, 0x05, 0x94, 0x81, 0x36, 0xde, 0x53, 0x7a, 0x3d, 0xb4, 0x21, 0x38, 0x41, 0x67, 0xc8, 0x6f, 0xae, 0x02, 0x25, 0x87, 0xee, 0x9e, 0x13, 0x7d, 0xae, 0xe7, 0x54, 0x73, 0x82, 0x62, 0x93, 0x2d, 0x27, 0x1c, 0x74, 0x4c, 0x6d, 0x3a, 0x18, 0x9a, 0xd4, 0x31, 0x1b, 0xdb, 0x02, 0x04, 0x92, 0xe3, 0x22, 0xfb, 0xdd, 0xc4, 0x04, 0x06, 0xea, 0x86, 0x0d, 0x4e, 0x8e, 0xa2, 0xa4, 0x08, 0x4a, 0xa9, 0x8b, 0x96, 0x22, 0xa4, 0x46, 0x75, 0x6f, 0xdb, 0x74, 0x0d, 0xdb, 0x3d, 0x91, 0xdb, 0x76, 0x70, 0xe2, 0x11, 0x66, 0x1b, 0xbf, 0x87, 0x09, 0xb1, 0x1c, 0x08, 0xa7, 0x07, 0x71, 0x42, 0x2d, 0x1a, 0x12, 0xde, 0xf2, 0x9f, 0x06, 0x88, 0xa1, 0x92, 0xae, 0xbd, 0x89, 0xe0, 0xf8, 0x96, 0xf8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.3", + /* Message to be signed */ + 228, + { 0xa4, 0xb1, 0x59, 0x94, 0x17, 0x61, 0xc4, 0x0c, 0x6a, 0x82, 0xf2, 0xb8, 0x0d, 0x1b, 0x94, 0xf5, 0xaa, 0x26, 0x54, 0xfd, 0x17, 0xe1, 0x2d, 0x58, 0x88, 0x64, 0x67, 0x9b, 0x54, 0xcd, 0x04, 0xef, 0x8b, 0xd0, 0x30, 0x12, 0xbe, 0x8d, 0xc3, 0x7f, 0x4b, 0x83, 0xaf, 0x79, 0x63, 0xfa, 0xff, 0x0d, 0xfa, 0x22, 0x54, 0x77, 0x43, 0x7c, 0x48, 0x01, 0x7f, 0xf2, 0xbe, 0x81, 0x91, 0xcf, 0x39, 0x55, 0xfc, 0x07, 0x35, 0x6e, 0xab, 0x3f, 0x32, 0x2f, 0x7f, 0x62, 0x0e, 0x21, 0xd2, 0x54, 0xe5, 0xdb, 0x43, 0x24, 0x27, 0x9f, 0xe0, 0x67, 0xe0, 0x91, 0x0e, 0x2e, 0x81, 0xca, 0x2c, 0xab, 0x31, 0xc7, 0x45, 0xe6, 0x7a, 0x54, 0x05, 0x8e, 0xb5, 0x0d, 0x99, 0x3c, 0xdb, 0x9e, 0xd0, 0xb4, 0xd0, 0x29, 0xc0, 0x6d, 0x21, 0xa9, 0x4c, 0xa6, 0x61, 0xc3, 0xce, 0x27, 0xfa, 0xe1, 0xd6, 0xcb, 0x20, 0xf4, 0x56, 0x4d, 0x66, 0xce, 0x47, 0x67, 0x58, 0x3d, 0x0e, 0x5f, 0x06, 0x02, 0x15, 0xb5, 0x90, 0x17, 0xbe, 0x85, 0xea, 0x84, 0x89, 0x39, 0x12, 0x7b, 0xd8, 0xc9, 0xc4, 0xd4, 0x7b, 0x51, 0x05, 0x6c, 0x03, 0x1c, 0xf3, 0x36, 0xf1, 0x7c, 0x99, 0x80, 0xf3, 0xb8, 0xf5, 0xb9, 0xb6, 0x87, 0x8e, 0x8b, 0x79, 0x7a, 0xa4, 0x3b, 0x88, 0x26, 0x84, 0x33, 0x3e, 0x17, 0x89, 0x3f, 0xe9, 0xca, 0xa6, 0xaa, 0x29, 0x9f, 0x7e, 0xd1, 0xa1, 0x8e, 0xe2, 0xc5, 0x48, 0x64, 0xb7, 0xb2, 0xb9, 0x9b, 0x72, 0x61, 0x8f, 0xb0, 0x25, 0x74, 0xd1, 0x39, 0xef, 0x50, 0xf0, 0x19, 0xc9, 0xee, 0xf4, 0x16, 0x97, 0x13, 0x38, 0xe7, 0xd4, 0x70 } +, + /* Signature */ + 128, + { 0x0b, 0x1f, 0x2e, 0x51, 0x80, 0xe5, 0xc7, 0xb4, 0xb5, 0xe6, 0x72, 0x92, 0x9f, 0x66, 0x4c, 0x48, 0x96, 0xe5, 0x0c, 0x35, 0x13, 0x4b, 0x6d, 0xe4, 0xd5, 0xa9, 0x34, 0x25, 0x2a, 0x3a, 0x24, 0x5f, 0xf4, 0x83, 0x40, 0x92, 0x0e, 0x10, 0x34, 0xb7, 0xd5, 0xa5, 0xb5, 0x24, 0xeb, 0x0e, 0x1c, 0xf1, 0x2b, 0xef, 0xef, 0x49, 0xb2, 0x7b, 0x73, 0x2d, 0x2c, 0x19, 0xe1, 0xc4, 0x32, 0x17, 0xd6, 0xe1, 0x41, 0x73, 0x81, 0x11, 0x1a, 0x1d, 0x36, 0xde, 0x63, 0x75, 0xcf, 0x45, 0x5b, 0x3c, 0x98, 0x12, 0x63, 0x9d, 0xbc, 0x27, 0x60, 0x0c, 0x75, 0x19, 0x94, 0xfb, 0x61, 0x79, 0x9e, 0xcf, 0x7d, 0xa6, 0xbc, 0xf5, 0x15, 0x40, 0xaf, 0xd0, 0x17, 0x4d, 0xb4, 0x03, 0x31, 0x88, 0x55, 0x66, 0x75, 0xb1, 0xd7, 0x63, 0x36, 0x0a, 0xf4, 0x6f, 0xee, 0xca, 0x5b, 0x60, 0xf8, 0x82, 0x82, 0x9e, 0xe7, 0xb2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.4", + /* Message to be signed */ + 9, + { 0xbc, 0x65, 0x67, 0x47, 0xfa, 0x9e, 0xaf, 0xb3, 0xf0 } +, + /* Signature */ + 128, + { 0x45, 0x60, 0x7a, 0xd6, 0x11, 0xcf, 0x57, 0x47, 0xa4, 0x1a, 0xc9, 0x4d, 0x0f, 0xfe, 0xc8, 0x78, 0xbd, 0xaf, 0x63, 0xf6, 0xb5, 0x7a, 0x4b, 0x08, 0x8b, 0xf3, 0x6e, 0x34, 0xe1, 0x09, 0xf8, 0x40, 0xf2, 0x4b, 0x74, 0x2a, 0xda, 0x16, 0x10, 0x2d, 0xab, 0xf9, 0x51, 0xcb, 0xc4, 0x4f, 0x89, 0x82, 0xe9, 0x4e, 0xd4, 0xcd, 0x09, 0x44, 0x8d, 0x20, 0xec, 0x0e, 0xfa, 0x73, 0x54, 0x5f, 0x80, 0xb6, 0x54, 0x06, 0xbe, 0xd6, 0x19, 0x4a, 0x61, 0xc3, 0x40, 0xb4, 0xad, 0x15, 0x68, 0xcb, 0xb7, 0x58, 0x51, 0x04, 0x9f, 0x11, 0xaf, 0x17, 0x34, 0x96, 0x40, 0x76, 0xe0, 0x20, 0x29, 0xae, 0xe2, 0x00, 0xe4, 0x0e, 0x80, 0xbe, 0x0f, 0x43, 0x61, 0xf6, 0x98, 0x41, 0xc4, 0xf9, 0x2a, 0x44, 0x50, 0xa2, 0x28, 0x6d, 0x43, 0x28, 0x9b, 0x40, 0x55, 0x54, 0xc5, 0x4d, 0x25, 0xc6, 0xec, 0xb5, 0x84, 0xf4 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.5", + /* Message to be signed */ + 149, + { 0xb4, 0x55, 0x81, 0x54, 0x7e, 0x54, 0x27, 0x77, 0x0c, 0x76, 0x8e, 0x8b, 0x82, 0xb7, 0x55, 0x64, 0xe0, 0xea, 0x4e, 0x9c, 0x32, 0x59, 0x4d, 0x6b, 0xff, 0x70, 0x65, 0x44, 0xde, 0x0a, 0x87, 0x76, 0xc7, 0xa8, 0x0b, 0x45, 0x76, 0x55, 0x0e, 0xee, 0x1b, 0x2a, 0xca, 0xbc, 0x7e, 0x8b, 0x7d, 0x3e, 0xf7, 0xbb, 0x5b, 0x03, 0xe4, 0x62, 0xc1, 0x10, 0x47, 0xea, 0xdd, 0x00, 0x62, 0x9a, 0xe5, 0x75, 0x48, 0x0a, 0xc1, 0x47, 0x0f, 0xe0, 0x46, 0xf1, 0x3a, 0x2b, 0xf5, 0xaf, 0x17, 0x92, 0x1d, 0xc4, 0xb0, 0xaa, 0x8b, 0x02, 0xbe, 0xe6, 0x33, 0x49, 0x11, 0x65, 0x1d, 0x7f, 0x85, 0x25, 0xd1, 0x0f, 0x32, 0xb5, 0x1d, 0x33, 0xbe, 0x52, 0x0d, 0x3d, 0xdf, 0x5a, 0x70, 0x99, 0x55, 0xa3, 0xdf, 0xe7, 0x82, 0x83, 0xb9, 0xe0, 0xab, 0x54, 0x04, 0x6d, 0x15, 0x0c, 0x17, 0x7f, 0x03, 0x7f, 0xdc, 0xcc, 0x5b, 0xe4, 0xea, 0x5f, 0x68, 0xb5, 0xe5, 0xa3, 0x8c, 0x9d, 0x7e, 0xdc, 0xcc, 0xc4, 0x97, 0x5f, 0x45, 0x5a, 0x69, 0x09, 0xb4 } +, + /* Signature */ + 128, + { 0x54, 0xbe, 0x9d, 0x90, 0x87, 0x75, 0x15, 0xf4, 0x50, 0x27, 0x9c, 0x15, 0xb5, 0xf6, 0x1a, 0xd6, 0xf1, 0x5e, 0xcc, 0x95, 0xf1, 0x8c, 0xbe, 0xd8, 0x2b, 0x65, 0xb1, 0x66, 0x7a, 0x57, 0x58, 0x09, 0x58, 0x79, 0x94, 0x66, 0x80, 0x44, 0xf3, 0xbc, 0x2a, 0xe7, 0xf8, 0x84, 0x50, 0x1f, 0x64, 0xf0, 0xb4, 0x3f, 0x58, 0x8c, 0xfa, 0x20, 0x5a, 0x6a, 0xb7, 0x04, 0x32, 0x8c, 0x2d, 0x4a, 0xb9, 0x2a, 0x7a, 0xe1, 0x34, 0x40, 0x61, 0x4d, 0x3e, 0x08, 0x5f, 0x40, 0x1d, 0xa9, 0xad, 0x28, 0xe2, 0x10, 0x5e, 0x4a, 0x0e, 0xdb, 0x68, 0x1a, 0x64, 0x24, 0xdf, 0x04, 0x73, 0x88, 0xce, 0x05, 0x1e, 0xe9, 0xdf, 0x7b, 0xc2, 0x16, 0x3f, 0xe3, 0x47, 0x52, 0x0a, 0xd5, 0x1c, 0xcd, 0x51, 0x80, 0x64, 0x38, 0x3e, 0x74, 0x1a, 0xca, 0xd3, 0xcb, 0xdc, 0x2c, 0xb5, 0xa7, 0xc6, 0x8e, 0x86, 0x84, 0x64, 0xc2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.6", + /* Message to be signed */ + 233, + { 0x10, 0xaa, 0xe9, 0xa0, 0xab, 0x0b, 0x59, 0x5d, 0x08, 0x41, 0x20, 0x7b, 0x70, 0x0d, 0x48, 0xd7, 0x5f, 0xae, 0xdd, 0xe3, 0xb7, 0x75, 0xcd, 0x6b, 0x4c, 0xc8, 0x8a, 0xe0, 0x6e, 0x46, 0x94, 0xec, 0x74, 0xba, 0x18, 0xf8, 0x52, 0x0d, 0x4f, 0x5e, 0xa6, 0x9c, 0xbb, 0xe7, 0xcc, 0x2b, 0xeb, 0xa4, 0x3e, 0xfd, 0xc1, 0x02, 0x15, 0xac, 0x4e, 0xb3, 0x2d, 0xc3, 0x02, 0xa1, 0xf5, 0x3d, 0xc6, 0xc4, 0x35, 0x22, 0x67, 0xe7, 0x93, 0x6c, 0xfe, 0xbf, 0x7c, 0x8d, 0x67, 0x03, 0x57, 0x84, 0xa3, 0x90, 0x9f, 0xa8, 0x59, 0xc7, 0xb7, 0xb5, 0x9b, 0x8e, 0x39, 0xc5, 0xc2, 0x34, 0x9f, 0x18, 0x86, 0xb7, 0x05, 0xa3, 0x02, 0x67, 0xd4, 0x02, 0xf7, 0x48, 0x6a, 0xb4, 0xf5, 0x8c, 0xad, 0x5d, 0x69, 0xad, 0xb1, 0x7a, 0xb8, 0xcd, 0x0c, 0xe1, 0xca, 0xf5, 0x02, 0x5a, 0xf4, 0xae, 0x24, 0xb1, 0xfb, 0x87, 0x94, 0xc6, 0x07, 0x0c, 0xc0, 0x9a, 0x51, 0xe2, 0xf9, 0x91, 0x13, 0x11, 0xe3, 0x87, 0x7d, 0x00, 0x44, 0xc7, 0x1c, 0x57, 0xa9, 0x93, 0x39, 0x50, 0x08, 0x80, 0x6b, 0x72, 0x3a, 0xc3, 0x83, 0x73, 0xd3, 0x95, 0x48, 0x18, 0x18, 0x52, 0x8c, 0x1e, 0x70, 0x53, 0x73, 0x92, 0x82, 0x05, 0x35, 0x29, 0x51, 0x0e, 0x93, 0x5c, 0xd0, 0xfa, 0x77, 0xb8, 0xfa, 0x53, 0xcc, 0x2d, 0x47, 0x4b, 0xd4, 0xfb, 0x3c, 0xc5, 0xc6, 0x72, 0xd6, 0xff, 0xdc, 0x90, 0xa0, 0x0f, 0x98, 0x48, 0x71, 0x2c, 0x4b, 0xcf, 0xe4, 0x6c, 0x60, 0x57, 0x36, 0x59, 0xb1, 0x1e, 0x64, 0x57, 0xe8, 0x61, 0xf0, 0xf6, 0x04, 0xb6, 0x13, 0x8d, 0x14, 0x4f, 0x8c, 0xe4, 0xe2, 0xda, 0x73 } +, + /* Signature */ + 128, + { 0x0e, 0x6f, 0xf6, 0x3a, 0x85, 0x6b, 0x9c, 0xbd, 0x5d, 0xbe, 0x42, 0x31, 0x83, 0x12, 0x20, 0x47, 0xdd, 0x39, 0xd6, 0xf7, 0x6d, 0x1b, 0x23, 0x10, 0xe5, 0x46, 0xfe, 0x9e, 0xe7, 0x3b, 0x33, 0xef, 0xa7, 0xc7, 0x8f, 0x94, 0x74, 0x45, 0x5c, 0x9e, 0x5b, 0x88, 0xcb, 0x38, 0x3a, 0xaf, 0xc3, 0x69, 0x86, 0x68, 0xe7, 0xb7, 0xa5, 0x9a, 0x9c, 0xbb, 0x5b, 0x08, 0x97, 0xb6, 0xc5, 0xaf, 0xb7, 0xf8, 0xba, 0xc4, 0xb9, 0x24, 0xe9, 0x8d, 0x76, 0x0a, 0x15, 0xfc, 0x43, 0xd2, 0x81, 0x4a, 0xb2, 0xd5, 0x18, 0x7f, 0x79, 0xbe, 0xd9, 0x91, 0x5a, 0x93, 0x39, 0x7e, 0xbc, 0x22, 0xa7, 0x67, 0x75, 0x06, 0xa0, 0x2e, 0x07, 0x6d, 0x3f, 0xfd, 0xc0, 0x44, 0x1d, 0xbd, 0x4d, 0xb0, 0x04, 0x53, 0xdc, 0x28, 0xd8, 0x30, 0xe0, 0x57, 0x3f, 0x77, 0xb8, 0x17, 0xb5, 0x05, 0xc3, 0x8b, 0x4a, 0x4b, 0xb5, 0xd0 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.7", + /* Message to be signed */ + 127, + { 0xef, 0xb5, 0xda, 0x1b, 0x4d, 0x1e, 0x6d, 0x9a, 0x5d, 0xff, 0x92, 0xd0, 0x18, 0x4d, 0xa7, 0xe3, 0x1f, 0x87, 0x7d, 0x12, 0x81, 0xdd, 0xda, 0x62, 0x56, 0x64, 0x86, 0x9e, 0x83, 0x79, 0xe6, 0x7a, 0xd3, 0xb7, 0x5e, 0xae, 0x74, 0xa5, 0x80, 0xe9, 0x82, 0x7a, 0xbd, 0x6e, 0xb7, 0xa0, 0x02, 0xcb, 0x54, 0x11, 0xf5, 0x26, 0x67, 0x97, 0x76, 0x8f, 0xb8, 0xe9, 0x5a, 0xe4, 0x0e, 0x3e, 0x8b, 0x34, 0x66, 0xf5, 0xab, 0x15, 0xd6, 0x95, 0x53, 0x95, 0x29, 0x39, 0xec, 0x23, 0xe6, 0x1d, 0x58, 0x49, 0x7f, 0xac, 0x76, 0xaa, 0x1c, 0x0b, 0xb5, 0xa3, 0xcb, 0x4a, 0x54, 0x38, 0x35, 0x87, 0xc7, 0xbb, 0x78, 0xd1, 0x3e, 0xef, 0xda, 0x20, 0x54, 0x43, 0xe6, 0xce, 0x43, 0x65, 0x80, 0x2d, 0xf5, 0x5c, 0x64, 0x71, 0x34, 0x97, 0x98, 0x4e, 0x7c, 0xa9, 0x67, 0x22, 0xb3, 0xed, 0xf8, 0x4d, 0x56 } +, + /* Signature */ + 128, + { 0x83, 0x85, 0xd5, 0x85, 0x33, 0xa9, 0x95, 0xf7, 0x2d, 0xf2, 0x62, 0xb7, 0x0f, 0x40, 0xb3, 0x91, 0xdd, 0xf5, 0x15, 0xf4, 0x64, 0xb9, 0xd2, 0xcc, 0x2d, 0x66, 0x39, 0x8f, 0xc0, 0x56, 0x89, 0xd8, 0x11, 0x63, 0x29, 0x46, 0xd6, 0x2e, 0xab, 0xdc, 0xa7, 0xa3, 0x1f, 0xcf, 0x6c, 0xd6, 0xc9, 0x81, 0xd2, 0x8b, 0xbc, 0x29, 0x08, 0x3e, 0x4a, 0x6d, 0x5b, 0x2b, 0x37, 0x8c, 0xa4, 0xe5, 0x40, 0xf0, 0x60, 0xb9, 0x6d, 0x53, 0xad, 0x26, 0x93, 0xf8, 0x21, 0x78, 0xb9, 0x4e, 0x2e, 0x2f, 0x86, 0xb9, 0xac, 0xcf, 0xa0, 0x20, 0x25, 0x10, 0x7e, 0x06, 0x2a, 0xb7, 0x08, 0x01, 0x75, 0x68, 0x45, 0x01, 0x02, 0x8f, 0x67, 0x64, 0x61, 0xd8, 0x1c, 0x00, 0x8f, 0xe4, 0x75, 0x06, 0x71, 0x64, 0x99, 0x70, 0x87, 0x8f, 0xc1, 0x75, 0xcf, 0x98, 0xe9, 0x6b, 0x2e, 0xcb, 0xf6, 0x87, 0x4d, 0x77, 0xda, 0xcb } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.8", + /* Message to be signed */ + 232, + { 0x53, 0xbb, 0x58, 0xce, 0x42, 0xf1, 0x98, 0x49, 0x40, 0x55, 0x26, 0x57, 0x23, 0x3b, 0x14, 0x96, 0x9a, 0xf3, 0x65, 0xc0, 0xa5, 0x61, 0xa4, 0x13, 0x2a, 0xf1, 0x8a, 0xf3, 0x94, 0x32, 0x28, 0x0e, 0x3e, 0x43, 0x70, 0x82, 0x43, 0x4b, 0x19, 0x23, 0x18, 0x37, 0x18, 0x4f, 0x02, 0xcf, 0x2b, 0x2e, 0x72, 0x6b, 0xeb, 0xf7, 0x4d, 0x7a, 0xe3, 0x25, 0x6d, 0x8b, 0x72, 0xf3, 0xea, 0xfd, 0xb1, 0x34, 0xd3, 0x3d, 0xe0, 0x6f, 0x29, 0x91, 0xd2, 0x99, 0xd5, 0x9f, 0x54, 0x68, 0xd4, 0x3b, 0x99, 0x58, 0xd6, 0xa9, 0x68, 0xf5, 0x96, 0x9e, 0xdb, 0xbc, 0x6e, 0x71, 0x85, 0xcb, 0xc7, 0x16, 0xc7, 0xc9, 0x45, 0xda, 0xfa, 0x9c, 0xc7, 0x1d, 0xdf, 0xaa, 0xa0, 0x10, 0x94, 0xa4, 0x52, 0xdd, 0xf5, 0xe2, 0x40, 0x73, 0x20, 0x40, 0x0b, 0xf0, 0x5e, 0xa9, 0x72, 0x9c, 0xaf, 0xbf, 0x06, 0x00, 0xe7, 0x88, 0x07, 0xef, 0x94, 0x62, 0xe3, 0xfd, 0xe3, 0x2e, 0xd7, 0xd9, 0x81, 0xa5, 0x6f, 0x47, 0x51, 0xef, 0x64, 0xfb, 0x45, 0x49, 0x91, 0x0e, 0xcc, 0x91, 0x1d, 0x72, 0x80, 0x53, 0xb3, 0x99, 0x43, 0x00, 0x47, 0x40, 0xe6, 0xf5, 0x82, 0x1f, 0xe8, 0xd7, 0x5c, 0x06, 0x17, 0xbf, 0x2c, 0x6b, 0x24, 0xbb, 0xfc, 0x34, 0x01, 0x3f, 0xc9, 0x5f, 0x0d, 0xed, 0xf5, 0xba, 0x29, 0x7f, 0x50, 0x4f, 0xb8, 0x33, 0xda, 0x2a, 0x43, 0x6d, 0x1d, 0x8f, 0xf1, 0xcc, 0x51, 0x93, 0xe2, 0xa6, 0x43, 0x89, 0xfc, 0xed, 0x91, 0x8e, 0x7f, 0xeb, 0x67, 0x16, 0x33, 0x0f, 0x66, 0x80, 0x1d, 0xb9, 0x49, 0x75, 0x49, 0xcf, 0x1d, 0x3b, 0xd9, 0x7c, 0xf1, 0xbc, 0x62, 0x55 } +, + /* Signature */ + 128, + { 0x8e, 0x1f, 0x3d, 0x26, 0xec, 0x7c, 0x6b, 0xbb, 0x8c, 0x54, 0xc5, 0xd2, 0x5f, 0x31, 0x20, 0x58, 0x78, 0x03, 0xaf, 0x6d, 0x3c, 0x2b, 0x99, 0xa3, 0x7c, 0xed, 0x6a, 0x36, 0x57, 0xd4, 0xae, 0x54, 0x26, 0x6f, 0x63, 0xff, 0xfd, 0xe6, 0x60, 0xc8, 0x66, 0xd6, 0x5d, 0x0a, 0xb0, 0x58, 0x9e, 0x1d, 0x12, 0xd9, 0xce, 0x60, 0x54, 0xb0, 0x5c, 0x86, 0x68, 0xae, 0x12, 0x71, 0x71, 0xcc, 0xaa, 0xe7, 0xf1, 0xcd, 0x40, 0x96, 0x77, 0xf5, 0x21, 0x57, 0xb6, 0x12, 0x3a, 0xb2, 0x27, 0xf2, 0x7a, 0x00, 0x96, 0x6d, 0x14, 0x39, 0xb4, 0x2a, 0x32, 0x16, 0x9d, 0x10, 0x70, 0x39, 0x40, 0x26, 0xfc, 0x8b, 0xc9, 0x35, 0x45, 0xb1, 0xac, 0x25, 0x2d, 0x0f, 0x7d, 0xa7, 0x51, 0xc0, 0x2e, 0x33, 0xa4, 0x78, 0x31, 0xfb, 0xd7, 0x15, 0x14, 0xc2, 0xbb, 0xbd, 0x3a, 0xdb, 0x67, 0x40, 0xc0, 0xfd, 0x68, 0xad } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.9", + /* Message to be signed */ + 42, + { 0x27, 0xca, 0xdc, 0x69, 0x84, 0x50, 0x94, 0x5f, 0x20, 0x4e, 0xc3, 0xcf, 0x8c, 0x6c, 0xbd, 0x8c, 0xeb, 0x4c, 0xc0, 0xcb, 0xe3, 0x12, 0x27, 0x4f, 0xa9, 0x6b, 0x04, 0xde, 0xac, 0x85, 0x51, 0x60, 0xc0, 0xe0, 0x4e, 0x4a, 0xc5, 0xd3, 0x82, 0x10, 0xc2, 0x7c } +, + /* Signature */ + 128, + { 0x7b, 0x63, 0xf9, 0x22, 0x33, 0x56, 0xf3, 0x5f, 0x61, 0x17, 0xf6, 0x8c, 0x8f, 0x82, 0x20, 0x03, 0x4f, 0xc2, 0x38, 0x4a, 0xb5, 0xdc, 0x69, 0x04, 0x14, 0x1f, 0x13, 0x93, 0x14, 0xd6, 0xee, 0x89, 0xf5, 0x4e, 0xc6, 0xff, 0xd1, 0x8c, 0x41, 0x3a, 0x23, 0xc5, 0x93, 0x1c, 0x7f, 0xbb, 0x13, 0xc5, 0x55, 0xcc, 0xfd, 0x59, 0x0e, 0x0e, 0xaa, 0x85, 0x3c, 0x8c, 0x94, 0xd2, 0x52, 0x0c, 0xd4, 0x25, 0x0d, 0x9a, 0x05, 0xa1, 0x93, 0xb6, 0x5d, 0xc7, 0x49, 0xb8, 0x24, 0x78, 0xaf, 0x01, 0x56, 0xee, 0x1d, 0xe5, 0x5d, 0xda, 0xd3, 0x3e, 0xc1, 0xf0, 0x09, 0x9c, 0xad, 0x6c, 0x89, 0x1a, 0x36, 0x17, 0xc7, 0x39, 0x3d, 0x05, 0xfb, 0xfb, 0xbb, 0x00, 0x52, 0x8a, 0x00, 0x1d, 0xf0, 0xb2, 0x04, 0xeb, 0xdf, 0x1a, 0x34, 0x10, 0x90, 0xde, 0xa8, 0x9f, 0x87, 0x0a, 0x87, 0x74, 0x58, 0x42, 0x7f, 0x7b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.10", + /* Message to be signed */ + 19, + { 0x71, 0x64, 0x07, 0xe9, 0x01, 0xb9, 0xef, 0x92, 0xd7, 0x61, 0xb0, 0x13, 0xfd, 0x13, 0xeb, 0x7a, 0xd7, 0x2a, 0xed } +, + /* Signature */ + 128, + { 0x2a, 0x22, 0xdb, 0xe3, 0x77, 0x4d, 0x5b, 0x29, 0x72, 0x01, 0xb5, 0x5a, 0x0f, 0x17, 0xf4, 0x2d, 0xce, 0x63, 0xb7, 0x84, 0x5c, 0xb3, 0x25, 0xcf, 0xe9, 0x51, 0xd0, 0xba, 0xdb, 0x5c, 0x5a, 0x14, 0x47, 0x21, 0x43, 0xd8, 0x96, 0xc8, 0x6c, 0xc3, 0x39, 0xf8, 0x36, 0x71, 0x16, 0x42, 0x15, 0xab, 0xc9, 0x78, 0x62, 0xf2, 0x15, 0x16, 0x54, 0xe7, 0x5a, 0x3b, 0x35, 0x7c, 0x37, 0x31, 0x1b, 0x3d, 0x72, 0x68, 0xca, 0xb5, 0x40, 0x20, 0x2e, 0x23, 0xbe, 0xe5, 0x27, 0x36, 0xf2, 0xcd, 0x86, 0xcc, 0xe0, 0xc7, 0xdb, 0xde, 0x95, 0xe1, 0xc6, 0x00, 0xa4, 0x73, 0x95, 0xdc, 0x5e, 0xb0, 0xa4, 0x72, 0x15, 0x3f, 0xbc, 0x4f, 0xb2, 0x1b, 0x64, 0x3e, 0x0c, 0x04, 0xae, 0x14, 0xdd, 0x37, 0xe9, 0x7e, 0x61, 0x7a, 0x75, 0x67, 0xc8, 0x96, 0x52, 0x21, 0x97, 0x81, 0x00, 0x1b, 0xa6, 0xf8, 0x32, 0x98 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.11", + /* Message to be signed */ + 206, + { 0x46, 0xc2, 0x4e, 0x41, 0x03, 0x00, 0x16, 0x29, 0xc7, 0x12, 0xdd, 0x4c, 0xe8, 0xd7, 0x47, 0xee, 0x59, 0x5d, 0x6c, 0x74, 0x4c, 0xcc, 0x4f, 0x71, 0x34, 0x7d, 0x9b, 0x8a, 0xbf, 0x49, 0xd1, 0xb8, 0xfb, 0x2e, 0xf9, 0x1b, 0x95, 0xdc, 0x89, 0x9d, 0x4c, 0x0e, 0x3d, 0x29, 0x97, 0xe6, 0x38, 0xf4, 0xcf, 0x3f, 0x68, 0xe0, 0x49, 0x8d, 0xe5, 0xaa, 0xbd, 0x13, 0xf0, 0xdf, 0xe0, 0x2f, 0xf2, 0x6b, 0xa4, 0x37, 0x91, 0x04, 0xe7, 0x8f, 0xfa, 0x95, 0xff, 0xbd, 0x15, 0x06, 0x7e, 0xf8, 0xcb, 0xd7, 0xeb, 0x78, 0x60, 0xfe, 0xcc, 0x71, 0xab, 0xe1, 0x3d, 0x5c, 0x72, 0x0a, 0x66, 0x85, 0x1f, 0x2d, 0xef, 0xd4, 0xe7, 0x95, 0x05, 0x4d, 0x7b, 0xec, 0x02, 0x4b, 0xb4, 0x22, 0xa4, 0x6a, 0x73, 0x68, 0xb5, 0x6d, 0x95, 0xb4, 0x7a, 0xeb, 0xaf, 0xbe, 0xad, 0xd6, 0x12, 0x81, 0x25, 0x93, 0xa7, 0x0d, 0xb9, 0xf9, 0x6d, 0x45, 0x1e, 0xe1, 0x5e, 0xdb, 0x29, 0x93, 0x08, 0xd7, 0x77, 0xf4, 0xbb, 0x68, 0xed, 0x33, 0x77, 0xc3, 0x21, 0x56, 0xb4, 0x1b, 0x7a, 0x9c, 0x92, 0xa1, 0x4c, 0x8b, 0x81, 0x14, 0x43, 0x99, 0xc5, 0x6a, 0x5a, 0x43, 0x2f, 0x4f, 0x77, 0x0a, 0xa9, 0x7d, 0xa8, 0x41, 0x5d, 0x0b, 0xda, 0x2e, 0x81, 0x32, 0x06, 0x03, 0x1e, 0x70, 0x62, 0x00, 0x31, 0xc8, 0x81, 0xd6, 0x16, 0xbf, 0xfd, 0x5f, 0x03, 0xbf, 0x14, 0x7c, 0x1e, 0x73, 0x76, 0x6c, 0x26, 0x24, 0x62, 0x08 } +, + /* Signature */ + 128, + { 0x12, 0x23, 0x5b, 0x0b, 0x40, 0x61, 0x26, 0xd9, 0xd2, 0x60, 0xd4, 0x47, 0xe9, 0x23, 0xa1, 0x10, 0x51, 0xfb, 0x24, 0x30, 0x79, 0xf4, 0x46, 0xfd, 0x73, 0xa7, 0x01, 0x81, 0xd5, 0x36, 0x34, 0xd7, 0xa0, 0x96, 0x8e, 0x4e, 0xe2, 0x77, 0x77, 0xed, 0xa6, 0x3f, 0x6e, 0x4a, 0x3a, 0x91, 0xad, 0x59, 0x85, 0x99, 0x8a, 0x48, 0x48, 0xda, 0x59, 0xce, 0x69, 0x7b, 0x24, 0xbb, 0x33, 0x2f, 0xa2, 0xad, 0x9c, 0xe4, 0x62, 0xca, 0x4a, 0xff, 0xdc, 0x21, 0xda, 0xb9, 0x08, 0xe8, 0xce, 0x15, 0xaf, 0x6e, 0xb9, 0x10, 0x5b, 0x1a, 0xbc, 0xf3, 0x91, 0x42, 0xaa, 0x17, 0xb3, 0x4c, 0x4c, 0x09, 0x23, 0x86, 0xa7, 0xab, 0xbf, 0xe0, 0x28, 0xaf, 0xdb, 0xeb, 0xc1, 0x4f, 0x2c, 0xe2, 0x6f, 0xbe, 0xe5, 0xed, 0xec, 0xa1, 0x15, 0x02, 0xd3, 0x9a, 0x6b, 0x74, 0x03, 0x15, 0x48, 0x43, 0xd9, 0x8a, 0x62, 0xa7 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.12", + /* Message to be signed */ + 107, + { 0xbc, 0x99, 0xa9, 0x32, 0xaa, 0x16, 0xd6, 0x22, 0xbf, 0xff, 0x79, 0xc5, 0x0b, 0x4c, 0x42, 0x35, 0x86, 0x73, 0x26, 0x11, 0x29, 0xe2, 0x8d, 0x6a, 0x91, 0x8f, 0xf1, 0xb0, 0xf1, 0xc4, 0xf4, 0x6a, 0xd8, 0xaf, 0xa9, 0x8b, 0x0c, 0xa0, 0xf5, 0x6f, 0x96, 0x79, 0x75, 0xb0, 0xa2, 0x9b, 0xe8, 0x82, 0xe9, 0x3b, 0x6c, 0xd3, 0xfc, 0x33, 0xe1, 0xfa, 0xef, 0x72, 0xe5, 0x2b, 0x2a, 0xe0, 0xa3, 0xf1, 0x20, 0x24, 0x50, 0x6e, 0x25, 0x69, 0x0e, 0x90, 0x2e, 0x78, 0x29, 0x82, 0x14, 0x55, 0x56, 0x53, 0x22, 0x84, 0xcf, 0x50, 0x57, 0x89, 0x73, 0x8f, 0x4d, 0xa3, 0x1f, 0xa1, 0x33, 0x3d, 0x3a, 0xf8, 0x62, 0xb2, 0xba, 0x6b, 0x6c, 0xe7, 0xab, 0x4c, 0xce, 0x6a, 0xba } +, + /* Signature */ + 128, + { 0x87, 0x2e, 0xc5, 0xad, 0x4f, 0x18, 0x46, 0x25, 0x6f, 0x17, 0xe9, 0x93, 0x6a, 0xc5, 0x0e, 0x43, 0xe9, 0x96, 0x3e, 0xa8, 0xc1, 0xe7, 0x6f, 0x15, 0x87, 0x9b, 0x78, 0x74, 0xd7, 0x7d, 0x12, 0x2a, 0x60, 0x9d, 0xc8, 0xc5, 0x61, 0x14, 0x5b, 0x94, 0xbf, 0x4f, 0xfd, 0xff, 0xde, 0xb1, 0x7e, 0x6e, 0x76, 0xff, 0xc6, 0xc1, 0x0c, 0x07, 0x47, 0xf5, 0xe3, 0x7a, 0x9f, 0x43, 0x4f, 0x56, 0x09, 0xe7, 0x9d, 0xa5, 0x25, 0x02, 0x15, 0xa4, 0x57, 0xaf, 0xdf, 0x12, 0xc6, 0x50, 0x7c, 0xc1, 0x55, 0x1f, 0x54, 0xa2, 0x80, 0x10, 0x59, 0x58, 0x26, 0xa2, 0xc9, 0xb9, 0x7f, 0xa0, 0xaa, 0x85, 0x1c, 0xc6, 0x8b, 0x70, 0x5d, 0x7a, 0x06, 0xd7, 0x20, 0xba, 0x02, 0x7e, 0x4a, 0x1c, 0x0b, 0x01, 0x95, 0x00, 0xfb, 0x63, 0xb7, 0x80, 0x71, 0x68, 0x4d, 0xcf, 0xa9, 0x77, 0x27, 0x00, 0xb9, 0x82, 0xdc, 0x66 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.13", + /* Message to be signed */ + 128, + { 0x73, 0x1e, 0x17, 0x2a, 0xc0, 0x63, 0x99, 0x2c, 0x5b, 0x11, 0xba, 0x17, 0x0d, 0xfb, 0x23, 0xbb, 0x00, 0x0d, 0x47, 0xba, 0x19, 0x53, 0x29, 0xcf, 0x27, 0x80, 0x61, 0x03, 0x73, 0x81, 0x51, 0x4c, 0x14, 0x60, 0x64, 0xc5, 0x28, 0x5d, 0xb1, 0x30, 0xdd, 0x5b, 0xae, 0x98, 0xb7, 0x72, 0x22, 0x59, 0x50, 0xea, 0xb0, 0x5d, 0x3e, 0xa9, 0x96, 0xf6, 0xff, 0xfb, 0x9a, 0x8c, 0x86, 0x22, 0x91, 0x3f, 0x27, 0x99, 0x14, 0xc8, 0x9a, 0xda, 0x4f, 0x3d, 0xd7, 0x76, 0x66, 0xa8, 0x68, 0xbf, 0xcb, 0xff, 0x2b, 0x95, 0xb7, 0xda, 0xf4, 0x53, 0xd4, 0xe2, 0xc9, 0xd7, 0x5b, 0xee, 0xe7, 0xf8, 0xe7, 0x09, 0x05, 0xe4, 0x06, 0x6a, 0x4f, 0x73, 0xae, 0xcc, 0x67, 0xf9, 0x56, 0xaa, 0x5a, 0x32, 0x92, 0xb8, 0x48, 0x8c, 0x91, 0x7d, 0x31, 0x7c, 0xfd, 0xc8, 0x62, 0x53, 0xe6, 0x90, 0x38, 0x1e, 0x15, 0xab } +, + /* Signature */ + 128, + { 0x76, 0x20, 0x4e, 0xac, 0xc1, 0xd6, 0x3e, 0xc1, 0xd6, 0xad, 0x5b, 0xd0, 0x69, 0x2e, 0x1a, 0x2f, 0x68, 0x6d, 0xf6, 0xe6, 0x4c, 0xa9, 0x45, 0xc7, 0x7a, 0x82, 0x4d, 0xe2, 0x12, 0xef, 0xa6, 0xd9, 0x78, 0x2d, 0x81, 0xb4, 0x59, 0x14, 0x03, 0xff, 0x40, 0x20, 0x62, 0x02, 0x98, 0xc0, 0x7e, 0xbd, 0x3a, 0x8a, 0x61, 0xc5, 0xbf, 0x4d, 0xad, 0x62, 0xcb, 0xfc, 0x4a, 0xe6, 0xa0, 0x39, 0x37, 0xbe, 0x4b, 0x49, 0xa2, 0x16, 0xd5, 0x70, 0xfc, 0x6e, 0x81, 0x87, 0x29, 0x37, 0x87, 0x6e, 0x27, 0xbd, 0x19, 0xcf, 0x60, 0x1e, 0xff, 0xc3, 0x0d, 0xdc, 0xa5, 0x73, 0xc9, 0xd5, 0x6c, 0xd4, 0x56, 0x9b, 0xdb, 0x48, 0x51, 0xc4, 0x50, 0xc4, 0x2c, 0xb2, 0x1e, 0x73, 0x8c, 0xdd, 0x61, 0x02, 0x7b, 0x8b, 0xe5, 0xe9, 0xb4, 0x10, 0xfc, 0x46, 0xaa, 0x3f, 0x29, 0xe4, 0xbe, 0x9e, 0x64, 0x45, 0x13, 0x46 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.14", + /* Message to be signed */ + 217, + { 0x02, 0x11, 0x38, 0x26, 0x83, 0xa7, 0x4d, 0x8d, 0x2a, 0x2c, 0xb6, 0xa0, 0x65, 0x50, 0x56, 0x3b, 0xe1, 0xc2, 0x6c, 0xa6, 0x28, 0x21, 0xe4, 0xff, 0x16, 0x3b, 0x72, 0x04, 0x64, 0xfc, 0x3a, 0x28, 0xd9, 0x1b, 0xed, 0xdd, 0xc6, 0x27, 0x49, 0xa5, 0x53, 0x8e, 0xaf, 0x41, 0xfb, 0xe0, 0xc8, 0x2a, 0x77, 0xe0, 0x6a, 0xd9, 0x93, 0x83, 0xc9, 0xe9, 0x85, 0xff, 0xb8, 0xa9, 0x3f, 0xd4, 0xd7, 0xc5, 0x8d, 0xb5, 0x1a, 0xd9, 0x1b, 0xa4, 0x61, 0xd6, 0x9a, 0x8f, 0xd7, 0xdd, 0xab, 0xe2, 0x49, 0x67, 0x57, 0xa0, 0xc4, 0x91, 0x22, 0xc1, 0xa7, 0x9a, 0x85, 0xcc, 0x05, 0x53, 0xe8, 0x21, 0x4d, 0x03, 0x6d, 0xfe, 0x01, 0x85, 0xef, 0xa0, 0xd0, 0x58, 0x60, 0xc6, 0x12, 0xfa, 0x08, 0x82, 0xc8, 0x2d, 0x24, 0x6e, 0x58, 0x30, 0xa6, 0x73, 0x55, 0xdf, 0xf1, 0x8a, 0x2c, 0x36, 0xb7, 0x32, 0xf9, 0x88, 0xcf, 0xed, 0xc5, 0x62, 0x26, 0x4c, 0x62, 0x54, 0xb4, 0x0f, 0xca, 0xbb, 0x97, 0xb7, 0x60, 0x94, 0x75, 0x68, 0xdc, 0xd6, 0xa1, 0x7c, 0xda, 0x6e, 0xe8, 0x85, 0x5b, 0xdd, 0xba, 0xb9, 0x37, 0x02, 0x47, 0x1a, 0xa0, 0xcf, 0xb1, 0xbe, 0xd2, 0xe1, 0x31, 0x18, 0xeb, 0xa1, 0x17, 0x5b, 0x73, 0xc9, 0x62, 0x53, 0xc1, 0x08, 0xd0, 0xb2, 0xab, 0xa0, 0x5a, 0xb8, 0xe1, 0x7e, 0x84, 0x39, 0x2e, 0x20, 0x08, 0x5f, 0x47, 0x40, 0x4d, 0x83, 0x65, 0x52, 0x7d, 0xc3, 0xfb, 0x8f, 0x2b, 0xb4, 0x8a, 0x50, 0x03, 0x8e, 0x71, 0x36, 0x1c, 0xcf, 0x97, 0x34, 0x07 } +, + /* Signature */ + 128, + { 0x52, 0x55, 0x00, 0x91, 0x83, 0x31, 0xf1, 0x04, 0x2e, 0xae, 0x0c, 0x5c, 0x20, 0x54, 0xaa, 0x7f, 0x92, 0xde, 0xb2, 0x69, 0x91, 0xb5, 0x79, 0x66, 0x34, 0xf2, 0x29, 0xda, 0xf9, 0xb4, 0x9e, 0xb2, 0x05, 0x4d, 0x87, 0x31, 0x9f, 0x3c, 0xfa, 0x9b, 0x46, 0x6b, 0xd0, 0x75, 0xef, 0x66, 0x99, 0xae, 0xa4, 0xbd, 0x4a, 0x19, 0x5a, 0x1c, 0x52, 0x96, 0x8b, 0x5e, 0x2b, 0x75, 0xe0, 0x92, 0xd8, 0x46, 0xea, 0x1b, 0x5c, 0xc2, 0x79, 0x05, 0xa8, 0xe1, 0xd5, 0xe5, 0xde, 0x0e, 0xdf, 0xdb, 0x21, 0x39, 0x1e, 0xbb, 0x95, 0x18, 0x64, 0xeb, 0xd9, 0xf0, 0xb0, 0xec, 0x35, 0xb6, 0x54, 0x28, 0x71, 0x36, 0x0a, 0x31, 0x7b, 0x7e, 0xf1, 0x3a, 0xe0, 0x6a, 0xf6, 0x84, 0xe3, 0x8e, 0x21, 0xb1, 0xe1, 0x9b, 0xc7, 0x29, 0x8e, 0x5d, 0x6f, 0xe0, 0x01, 0x3a, 0x16, 0x4b, 0xfa, 0x25, 0xd3, 0xe7, 0x31, 0x3d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.15", + /* Message to be signed */ + 66, + { 0xfc, 0x6b, 0x70, 0x0d, 0x22, 0x58, 0x33, 0x88, 0xab, 0x2f, 0x8d, 0xaf, 0xca, 0xf1, 0xa0, 0x56, 0x20, 0x69, 0x80, 0x20, 0xda, 0x4b, 0xae, 0x44, 0xda, 0xfb, 0xd0, 0x87, 0x7b, 0x50, 0x12, 0x50, 0x6d, 0xc3, 0x18, 0x1d, 0x5c, 0x66, 0xbf, 0x02, 0x3f, 0x34, 0x8b, 0x41, 0xfd, 0x9f, 0x94, 0x79, 0x5a, 0xb9, 0x64, 0x52, 0xa4, 0x21, 0x9f, 0x2d, 0x39, 0xd7, 0x2a, 0xf3, 0x59, 0xcf, 0x19, 0x56, 0x51, 0xc7 } +, + /* Signature */ + 128, + { 0x44, 0x52, 0xa6, 0xcc, 0x26, 0x26, 0xb0, 0x1e, 0x95, 0xab, 0x30, 0x6d, 0xf0, 0xd0, 0xcc, 0x74, 0x84, 0xfb, 0xab, 0x3c, 0x22, 0xe9, 0x70, 0x32, 0x83, 0x56, 0x7f, 0x66, 0xea, 0xdc, 0x24, 0x8d, 0xbd, 0xa5, 0x8f, 0xce, 0x7d, 0xd0, 0xc7, 0x0c, 0xce, 0x3f, 0x15, 0x0f, 0xca, 0x4b, 0x36, 0x9d, 0xff, 0x3b, 0x62, 0x37, 0xe2, 0xb1, 0x62, 0x81, 0xab, 0x55, 0xb5, 0x3f, 0xb1, 0x30, 0x89, 0xc8, 0x5c, 0xd2, 0x65, 0x05, 0x6b, 0x3d, 0x62, 0xa8, 0x8b, 0xfc, 0x21, 0x35, 0xb1, 0x67, 0x91, 0xf7, 0xfb, 0xca, 0xb9, 0xfd, 0x2d, 0xc3, 0x3b, 0xec, 0xb6, 0x17, 0xbe, 0x41, 0x9d, 0x2c, 0x04, 0x61, 0x42, 0xa4, 0xd4, 0x7b, 0x33, 0x83, 0x14, 0x55, 0x2e, 0xdd, 0x4b, 0x6f, 0xe9, 0xce, 0x11, 0x04, 0xec, 0xec, 0x4a, 0x99, 0x58, 0xd7, 0x33, 0x1e, 0x93, 0x0f, 0xc0, 0x9b, 0xf0, 0x8a, 0x6e, 0x64 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.16", + /* Message to be signed */ + 169, + { 0x13, 0xba, 0x08, 0x6d, 0x70, 0x9c, 0xfa, 0x5f, 0xed, 0xaa, 0x55, 0x7a, 0x89, 0x18, 0x1a, 0x61, 0x40, 0xf2, 0x30, 0x0e, 0xd6, 0xd7, 0xc3, 0xfe, 0xbb, 0x6c, 0xf6, 0x8a, 0xbe, 0xbc, 0xbc, 0x67, 0x8f, 0x2b, 0xca, 0x3d, 0xc2, 0x33, 0x02, 0x95, 0xee, 0xc4, 0x5b, 0xb1, 0xc4, 0x07, 0x5f, 0x3a, 0xda, 0x98, 0x7e, 0xae, 0x88, 0xb3, 0x9c, 0x51, 0x60, 0x6c, 0xb8, 0x04, 0x29, 0xe6, 0x49, 0xd9, 0x8a, 0xcc, 0x84, 0x41, 0xb1, 0xf8, 0x89, 0x7d, 0xb8, 0x6c, 0x5a, 0x4c, 0xe0, 0xab, 0xf2, 0x8b, 0x1b, 0x81, 0xdc, 0xa3, 0x66, 0x76, 0x97, 0xb8, 0x50, 0x69, 0x6b, 0x74, 0xa5, 0xeb, 0xd8, 0x5d, 0xec, 0x56, 0xc9, 0x0f, 0x8a, 0xbe, 0x51, 0x3e, 0xfa, 0x85, 0x78, 0x53, 0x72, 0x0b, 0xe3, 0x19, 0x60, 0x79, 0x21, 0xbc, 0xa9, 0x47, 0x52, 0x2c, 0xd8, 0xfa, 0xc8, 0xca, 0xce, 0x5b, 0x82, 0x7c, 0x3e, 0x5a, 0x12, 0x9e, 0x7e, 0xe5, 0x7f, 0x6b, 0x84, 0x93, 0x2f, 0x14, 0x14, 0x1a, 0xc4, 0x27, 0x4e, 0x8c, 0xbb, 0x46, 0xe6, 0x91, 0x2b, 0x0d, 0x3e, 0x21, 0x77, 0xd4, 0x99, 0xd1, 0x84, 0x0c, 0xd4, 0x7d, 0x4d, 0x7a, 0xe0, 0xb4, 0xcd, 0xc4, 0xd3 } +, + /* Signature */ + 128, + { 0x1f, 0x3b, 0x5a, 0x87, 0xdb, 0x72, 0xa2, 0xc9, 0x7b, 0xb3, 0xef, 0xf2, 0xa6, 0x5a, 0x30, 0x12, 0x68, 0xea, 0xcd, 0x89, 0xf4, 0x2a, 0xbc, 0x10, 0x98, 0xc1, 0xf2, 0xde, 0x77, 0xb0, 0x83, 0x2a, 0x65, 0xd7, 0x81, 0x5f, 0xeb, 0x35, 0x07, 0x00, 0x63, 0xf2, 0x21, 0xbb, 0x34, 0x53, 0xbd, 0x43, 0x43, 0x86, 0xc9, 0xa3, 0xfd, 0xe1, 0x8e, 0x3c, 0xa1, 0x68, 0x7f, 0xb6, 0x49, 0xe8, 0x6c, 0x51, 0xd6, 0x58, 0x61, 0x9d, 0xde, 0x5d, 0xeb, 0xb8, 0x6f, 0xe1, 0x54, 0x91, 0xff, 0x77, 0xab, 0x74, 0x83, 0x73, 0xf1, 0xbe, 0x50, 0x88, 0x80, 0xd6, 0x6e, 0xa8, 0x1e, 0x87, 0x0e, 0x91, 0xcd, 0xf1, 0x70, 0x48, 0x75, 0xc1, 0x7f, 0x0b, 0x10, 0x10, 0x31, 0x88, 0xbc, 0x64, 0xee, 0xf5, 0xa3, 0x55, 0x1b, 0x41, 0x4c, 0x73, 0x36, 0x70, 0x21, 0x5b, 0x1a, 0x22, 0x70, 0x25, 0x62, 0x58, 0x1a, 0xb1 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.17", + /* Message to be signed */ + 4, + { 0xeb, 0x1e, 0x59, 0x35 } +, + /* Signature */ + 128, + { 0x37, 0x0c, 0xb9, 0x83, 0x9a, 0xe6, 0x07, 0x4f, 0x84, 0xb2, 0xac, 0xd6, 0xe6, 0xf6, 0xb7, 0x92, 0x1b, 0x4b, 0x52, 0x34, 0x63, 0x75, 0x7f, 0x64, 0x46, 0x71, 0x61, 0x40, 0xc4, 0xe6, 0xc0, 0xe7, 0x5b, 0xec, 0x6a, 0xd0, 0x19, 0x7e, 0xbf, 0xa8, 0x6b, 0xf4, 0x6d, 0x09, 0x4f, 0x5f, 0x6c, 0xd3, 0x6d, 0xca, 0x3a, 0x5c, 0xc7, 0x3c, 0x8b, 0xbb, 0x70, 0xe2, 0xc7, 0xc9, 0xab, 0x5d, 0x96, 0x4e, 0xc8, 0xe3, 0xdf, 0xde, 0x48, 0x1b, 0x4a, 0x1b, 0xef, 0xfd, 0x01, 0xb4, 0xad, 0x15, 0xb3, 0x1a, 0xe7, 0xae, 0xbb, 0x9b, 0x70, 0x34, 0x4a, 0x94, 0x11, 0x08, 0x31, 0x65, 0xfd, 0xf9, 0xc3, 0x75, 0x4b, 0xbb, 0x8b, 0x94, 0xdd, 0x34, 0xbd, 0x48, 0x13, 0xdf, 0xad, 0xa1, 0xf6, 0x93, 0x7d, 0xe4, 0x26, 0x7d, 0x55, 0x97, 0xca, 0x09, 0xa3, 0x1e, 0x83, 0xd7, 0xf1, 0xa7, 0x9d, 0xd1, 0x9b, 0x5e } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.18", + /* Message to be signed */ + 28, + { 0x63, 0x46, 0xb1, 0x53, 0xe8, 0x89, 0xc8, 0x22, 0x82, 0x09, 0x63, 0x00, 0x71, 0xc8, 0xa5, 0x77, 0x83, 0xf3, 0x68, 0x76, 0x0b, 0x8e, 0xb9, 0x08, 0xcf, 0xc2, 0xb2, 0x76 } +, + /* Signature */ + 128, + { 0x24, 0x79, 0xc9, 0x75, 0xc5, 0xb1, 0xae, 0x4c, 0x4e, 0x94, 0x0f, 0x47, 0x3a, 0x90, 0x45, 0xb8, 0xbf, 0x5b, 0x0b, 0xfc, 0xa7, 0x8e, 0xc2, 0x9a, 0x38, 0xdf, 0xbe, 0xdc, 0x8a, 0x74, 0x9b, 0x7a, 0x26, 0x92, 0xf7, 0xc5, 0x2d, 0x5b, 0xc7, 0xc8, 0x31, 0xc7, 0x23, 0x23, 0x72, 0xa0, 0x0f, 0xed, 0x3b, 0x6b, 0x49, 0xe7, 0x60, 0xec, 0x99, 0xe0, 0x74, 0xff, 0x2e, 0xea, 0xd5, 0x13, 0x4e, 0x83, 0x05, 0x72, 0x5d, 0xfa, 0x39, 0x21, 0x2b, 0x84, 0xbd, 0x4b, 0x8d, 0x80, 0xbc, 0x8b, 0xc1, 0x7a, 0x51, 0x28, 0x23, 0xa3, 0xbe, 0xb1, 0x8f, 0xc0, 0x8e, 0x45, 0xed, 0x19, 0xc2, 0x6c, 0x81, 0x77, 0x07, 0xd6, 0x7f, 0xb0, 0x58, 0x32, 0xef, 0x1f, 0x12, 0xa3, 0x3e, 0x90, 0xcd, 0x93, 0xb8, 0xa7, 0x80, 0x31, 0x9e, 0x29, 0x63, 0xca, 0x25, 0xa2, 0xaf, 0x7b, 0x09, 0xad, 0x8f, 0x59, 0x5c, 0x21 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.19", + /* Message to be signed */ + 50, + { 0x64, 0x70, 0x2d, 0xb9, 0xf8, 0x25, 0xa0, 0xf3, 0xab, 0xc3, 0x61, 0x97, 0x46, 0x59, 0xf5, 0xe9, 0xd3, 0x0c, 0x3a, 0xa4, 0xf5, 0x6f, 0xea, 0xc6, 0x90, 0x50, 0xc7, 0x29, 0x05, 0xe7, 0x7f, 0xe0, 0xc2, 0x2f, 0x88, 0xa3, 0x78, 0xc2, 0x1f, 0xcf, 0x45, 0xfe, 0x8a, 0x5c, 0x71, 0x73, 0x02, 0x09, 0x39, 0x29 } +, + /* Signature */ + 128, + { 0x15, 0x2f, 0x34, 0x51, 0xc8, 0x58, 0xd6, 0x95, 0x94, 0xe6, 0x56, 0x7d, 0xfb, 0x31, 0x29, 0x1c, 0x1e, 0xe7, 0x86, 0x0b, 0x9d, 0x15, 0xeb, 0xd5, 0xa5, 0xed, 0xd2, 0x76, 0xac, 0x3e, 0x6f, 0x7a, 0x8d, 0x14, 0x80, 0xe4, 0x2b, 0x33, 0x81, 0xd2, 0xbe, 0x02, 0x3a, 0xcf, 0x7e, 0xbb, 0xdb, 0x28, 0xde, 0x3d, 0x21, 0x63, 0xae, 0x44, 0x25, 0x9c, 0x6d, 0xf9, 0x8c, 0x33, 0x5d, 0x04, 0x5b, 0x61, 0xda, 0xc9, 0xdb, 0xa9, 0xdb, 0xbb, 0x4e, 0x6a, 0xb4, 0xa0, 0x83, 0xcd, 0x76, 0xb5, 0x80, 0xcb, 0xe4, 0x72, 0x20, 0x6a, 0x1a, 0x9f, 0xd6, 0x06, 0x80, 0xce, 0xea, 0x1a, 0x57, 0x0a, 0x29, 0xb0, 0x88, 0x1c, 0x77, 0x5e, 0xae, 0xf5, 0x52, 0x5d, 0x6d, 0x2f, 0x34, 0x4c, 0x28, 0x83, 0x7d, 0x0a, 0xca, 0x42, 0x2b, 0xbb, 0x0f, 0x1a, 0xba, 0x8f, 0x68, 0x61, 0xae, 0x18, 0xbd, 0x73, 0xfe, 0x44 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 1.20", + /* Message to be signed */ + 43, + { 0x94, 0x19, 0x21, 0xde, 0x4a, 0x1c, 0x9c, 0x16, 0x18, 0xd6, 0xf3, 0xca, 0x3c, 0x17, 0x9f, 0x6e, 0x29, 0xba, 0xe6, 0xdd, 0xf9, 0xa6, 0xa5, 0x64, 0xf9, 0x29, 0xe3, 0xce, 0x82, 0xcf, 0x32, 0x65, 0xd7, 0x83, 0x7d, 0x5e, 0x69, 0x2b, 0xe8, 0xdc, 0xc9, 0xe8, 0x6c } +, + /* Signature */ + 128, + { 0x70, 0x76, 0xc2, 0x87, 0xfc, 0x6f, 0xff, 0x2b, 0x20, 0x53, 0x74, 0x35, 0xe5, 0xa3, 0x10, 0x7c, 0xe4, 0xda, 0x10, 0x71, 0x61, 0x86, 0xd0, 0x15, 0x39, 0x41, 0x3e, 0x60, 0x9d, 0x27, 0xd1, 0xda, 0x6f, 0xd9, 0x52, 0xc6, 0x1f, 0x4b, 0xab, 0x91, 0xc0, 0x45, 0xfa, 0x4f, 0x86, 0x83, 0xec, 0xc4, 0xf8, 0xdd, 0xe7, 0x42, 0x27, 0xf7, 0x73, 0xcf, 0xf3, 0xd9, 0x6d, 0xb8, 0x47, 0x18, 0xc4, 0x94, 0x4b, 0x06, 0xaf, 0xfe, 0xba, 0x94, 0xb7, 0x25, 0xf1, 0xb0, 0x7d, 0x39, 0x28, 0xb2, 0x49, 0x0a, 0x85, 0xc2, 0xf1, 0xab, 0xf4, 0x92, 0xa9, 0x17, 0x7a, 0x7c, 0xd2, 0xea, 0x0c, 0x96, 0x68, 0x75, 0x6f, 0x82, 0x5b, 0xbe, 0xc9, 0x00, 0xfa, 0x8a, 0xc3, 0x82, 0x4e, 0x11, 0x43, 0x87, 0xef, 0x57, 0x37, 0x80, 0xca, 0x33, 0x48, 0x82, 0x38, 0x7b, 0x94, 0xe5, 0xaa, 0xd7, 0xa2, 0x7a, 0x28, 0xdc } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 2: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xac, 0x13, 0xd9, 0xfd, 0xae, 0x7b, 0x73, 0x35, 0xb6, 0x9c, 0xd9, 0x85, 0x67, 0xe9, 0x64, 0x7d, 0x99, 0xbf, 0x37, 0x3a, 0x9e, 0x05, 0xce, 0x34, 0x35, 0xd6, 0x64, 0x65, 0xf3, 0x28, 0xb7, 0xf7, 0x33, 0x4b, 0x79, 0x2a, 0xee, 0x7e, 0xfa, 0x04, 0x4e, 0xbc, 0x4c, 0x7a, 0x30, 0xb2, 0x1a, 0x5d, 0x7a, 0x89, 0xcd, 0xb3, 0xa3, 0x0d, 0xfc, 0xd9, 0xfe, 0xe9, 0x99, 0x5e, 0x09, 0x41, 0x5e, 0xdc, 0x0b, 0xf9, 0xe5, 0xb4, 0xc3, 0xf7, 0x4f, 0xf5, 0x3f, 0xb4, 0xd2, 0x94, 0x41, 0xbf, 0x1b, 0x7e, 0xd6, 0xcb, 0xdd, 0x4a, 0x47, 0xf9, 0x25, 0x22, 0x69, 0xe1, 0x64, 0x6f, 0x6c, 0x1a, 0xee, 0x05, 0x14, 0xe9, 0x3f, 0x6c, 0xb9, 0xdf, 0x71, 0xd0, 0x6c, 0x06, 0x0a, 0x21, 0x04, 0xb4, 0x7b, 0x72, 0x60, 0xac, 0x37, 0xc1, 0x06, 0x86, 0x1d, 0xc7, 0x8c, 0xa5, 0xa2, 0x5f, 0xaa, 0x9c, 0xb2, 0xe3 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x04, 0x84, 0xcc, 0xef, 0xad, 0x7a, 0x4e, 0x6f, 0x35, 0xa9, 0x6e, 0xc8, 0xe3, 0x0e, 0xac, 0xf5, 0xe3, 0x68, 0xb3, 0x11, 0x95, 0xfe, 0xbf, 0x08, 0x7d, 0xf5, 0x70, 0x53, 0x81, 0x0c, 0x2b, 0xb0, 0x91, 0x27, 0x45, 0x3a, 0x4c, 0x63, 0x07, 0x3b, 0xbf, 0xb9, 0x90, 0x24, 0x91, 0x4c, 0xcc, 0x06, 0x72, 0x66, 0x56, 0x01, 0x86, 0xa1, 0xa2, 0x67, 0x33, 0x1b, 0x7d, 0x4c, 0x8b, 0xdf, 0xac, 0x96, 0xfd, 0xa9, 0xf3, 0xf7, 0x0b, 0xec, 0x4e, 0xea, 0xbc, 0xe7, 0xcd, 0x52, 0x19, 0x34, 0x3c, 0x2e, 0x49, 0x1c, 0xce, 0x82, 0x7e, 0x44, 0xee, 0x23, 0x0e, 0x4f, 0x69, 0x58, 0x9e, 0x57, 0x5a, 0xe9, 0x06, 0x30, 0x30, 0x44, 0x2a, 0x31, 0xc8, 0x2c, 0xde, 0x30, 0xdc, 0x9c, 0x79, 0xcf, 0x64, 0xe7, 0xa0, 0x97, 0x5e, 0x75, 0xe1, 0x6e, 0xa4, 0x58, 0x15, 0x48, 0x8b, 0x45, 0x52, 0x56, 0xee, 0xb1 } +, + /* Prime 1 */ + 64, + { 0xdf, 0x85, 0xf4, 0xa0, 0xb4, 0x33, 0xbd, 0x37, 0x43, 0x3c, 0xd7, 0x97, 0x8c, 0x9b, 0x37, 0xf9, 0xe4, 0x17, 0x29, 0xd8, 0x3a, 0x26, 0x2b, 0x98, 0x46, 0x53, 0x8e, 0x50, 0x39, 0xe6, 0x59, 0x68, 0xb5, 0x95, 0xa4, 0x62, 0x72, 0xbd, 0x5f, 0x4a, 0x2c, 0x3a, 0xbf, 0x89, 0x0a, 0x35, 0x50, 0x8a, 0x5b, 0xcb, 0x4c, 0x29, 0xef, 0xbd, 0x91, 0x02, 0x85, 0x03, 0x83, 0x4c, 0xfa, 0xb2, 0xc0, 0xf9 } +, + /* Prime 2 */ + 64, + { 0xc5, 0x14, 0x59, 0xa6, 0x72, 0xed, 0x8b, 0x72, 0x4c, 0x6a, 0x8f, 0x28, 0x5c, 0xbb, 0x8e, 0xa7, 0x6a, 0x23, 0x93, 0x91, 0x79, 0x28, 0xbe, 0x56, 0xc0, 0xdc, 0xdf, 0xc9, 0x43, 0xc3, 0x0b, 0xda, 0x3c, 0xee, 0xfb, 0x86, 0xdc, 0xc8, 0xc4, 0x55, 0x67, 0x8c, 0xfe, 0x88, 0x25, 0xf3, 0x88, 0x77, 0xa3, 0x72, 0x8a, 0x1f, 0x10, 0x29, 0x1f, 0x54, 0x7b, 0x1e, 0x8b, 0x16, 0x04, 0x83, 0xe5, 0xbb } +, + /* Prime exponent 1 */ + 64, + { 0xb6, 0xba, 0x83, 0xa9, 0x7c, 0xa7, 0x6f, 0x5f, 0xe6, 0x0f, 0xaf, 0x0f, 0xad, 0x5a, 0x97, 0x00, 0x2a, 0x7e, 0xe5, 0x2e, 0x67, 0x1b, 0x1d, 0x38, 0x77, 0x05, 0x87, 0xa9, 0xfe, 0x2b, 0x59, 0x9c, 0x48, 0x15, 0xf5, 0x34, 0xa6, 0x28, 0x39, 0xe6, 0x21, 0x12, 0x45, 0xd2, 0x7a, 0x0d, 0xeb, 0xb1, 0xb0, 0x29, 0x1a, 0x32, 0x8e, 0x52, 0xa2, 0x61, 0x34, 0xec, 0x12, 0x42, 0xb4, 0x0f, 0xbd, 0xc1 } +, + /* Prime exponent 2 */ + 64, + { 0xb9, 0xb1, 0xc6, 0x13, 0x2e, 0xe1, 0x22, 0x6e, 0x6d, 0x10, 0x4e, 0x99, 0x72, 0x5f, 0x0b, 0x38, 0x35, 0xab, 0x15, 0xe5, 0x91, 0x6a, 0xd1, 0x85, 0xbe, 0xad, 0x9f, 0x72, 0xed, 0x95, 0x3f, 0x7a, 0xbf, 0xc5, 0x52, 0x5c, 0xad, 0x75, 0xc2, 0x80, 0xd2, 0x54, 0x28, 0x94, 0xb2, 0x65, 0xb8, 0x65, 0x3a, 0x2d, 0xb7, 0x75, 0x33, 0x6d, 0xfb, 0xe6, 0x47, 0x27, 0xed, 0x57, 0xae, 0xa3, 0x74, 0xf7 } +, + /* Coefficient */ + 64, + { 0x7b, 0x8d, 0x15, 0xa5, 0xdd, 0x28, 0x90, 0xa6, 0x7d, 0x1b, 0x54, 0x9c, 0x93, 0x5f, 0x58, 0x5a, 0x38, 0xda, 0x56, 0xf7, 0xc8, 0x15, 0x5a, 0x51, 0x9d, 0xc8, 0xf1, 0xf6, 0xad, 0xe5, 0x53, 0xd6, 0x37, 0x93, 0xc7, 0x8a, 0x0e, 0xce, 0x8d, 0x53, 0x72, 0x4e, 0x62, 0xae, 0x50, 0x3a, 0xd5, 0x25, 0xbf, 0xaf, 0x10, 0xcf, 0x61, 0x6a, 0x47, 0x73, 0xce, 0x7c, 0xcd, 0x5c, 0x1b, 0x31, 0x51, 0xbd } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 2.1", + /* Message to be signed */ + 158, + { 0xe1, 0xc0, 0xf9, 0x8d, 0x53, 0xf8, 0xf8, 0xb1, 0x41, 0x90, 0x57, 0xd5, 0xb9, 0xb1, 0x0b, 0x07, 0xfe, 0xea, 0xec, 0x32, 0xc0, 0x46, 0x3a, 0x4d, 0x68, 0x38, 0x2f, 0x53, 0x1b, 0xa1, 0xd6, 0xcf, 0xe4, 0xed, 0x38, 0xa2, 0x69, 0x4a, 0x34, 0xb9, 0xc8, 0x05, 0xad, 0xf0, 0x72, 0xff, 0xbc, 0xeb, 0xe2, 0x1d, 0x8d, 0x4b, 0x5c, 0x0e, 0x8c, 0x33, 0x45, 0x2d, 0xd8, 0xf9, 0xc9, 0xbf, 0x45, 0xd1, 0xe6, 0x33, 0x75, 0x11, 0x33, 0x58, 0x82, 0x29, 0xd2, 0x93, 0xc6, 0x49, 0x6b, 0x7c, 0x98, 0x3c, 0x2c, 0x72, 0xbd, 0x21, 0xd3, 0x39, 0x27, 0x2d, 0x78, 0x28, 0xb0, 0xd0, 0x9d, 0x01, 0x0b, 0xba, 0xd3, 0x18, 0xd9, 0x98, 0xf7, 0x04, 0x79, 0x67, 0x33, 0x8a, 0xce, 0xfd, 0x01, 0xe8, 0x74, 0xac, 0xe5, 0xf8, 0x6d, 0x2a, 0x60, 0xf3, 0xb3, 0xca, 0xe1, 0x3f, 0xc5, 0xc6, 0x65, 0x08, 0xcf, 0xb7, 0x23, 0x78, 0xfd, 0xd6, 0xc8, 0xde, 0x24, 0x97, 0x65, 0x10, 0x3c, 0xe8, 0xfe, 0x7c, 0xd3, 0x3a, 0xd0, 0xef, 0x16, 0x86, 0xfe, 0xb2, 0x5e, 0x6a, 0x35, 0xfb, 0x64, 0xe0, 0x96, 0xa4 } +, + /* Signature */ + 128, + { 0x64, 0xac, 0x09, 0x39, 0x71, 0xf8, 0xf0, 0x96, 0xa4, 0xc1, 0xd4, 0xa5, 0x43, 0x66, 0x2a, 0x2e, 0x5a, 0x12, 0x81, 0xc9, 0x50, 0x98, 0x7d, 0xe8, 0x98, 0x70, 0x7f, 0x02, 0x9c, 0x15, 0x9b, 0xd8, 0x32, 0xca, 0xc5, 0x5d, 0x91, 0x36, 0xe0, 0xe9, 0xb4, 0xa8, 0x0b, 0xf6, 0xf2, 0x1b, 0x68, 0xcf, 0x97, 0x70, 0xa6, 0x34, 0x9a, 0xe5, 0x1e, 0x7f, 0x09, 0xdb, 0xda, 0x9d, 0x59, 0xc4, 0x58, 0x37, 0x37, 0x47, 0x2d, 0x4d, 0x65, 0x32, 0xc7, 0x17, 0x7e, 0xe9, 0x81, 0x08, 0xd2, 0xcf, 0x42, 0xcd, 0x08, 0x5a, 0xbb, 0x49, 0x22, 0xeb, 0x29, 0xd9, 0x6f, 0x3d, 0x0f, 0x6b, 0x1d, 0x0d, 0x43, 0xc7, 0x39, 0xcc, 0xf1, 0xba, 0x65, 0x16, 0x75, 0xe1, 0x96, 0x8b, 0x50, 0x7d, 0x51, 0x90, 0x2f, 0x38, 0xcd, 0xec, 0x0b, 0x61, 0x32, 0x72, 0x90, 0x45, 0x32, 0x5f, 0xc1, 0xfb, 0x8f, 0xd5, 0x58, 0xe8 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 2.2", + /* Message to be signed */ + 177, + { 0xc1, 0x11, 0x46, 0x4e, 0x00, 0x2e, 0x4e, 0xc6, 0x18, 0xa8, 0xe2, 0x63, 0xdb, 0xcc, 0xa9, 0x1f, 0xb1, 0x8a, 0x00, 0xa1, 0x8b, 0x44, 0x0c, 0x4b, 0x55, 0x97, 0xbe, 0xe7, 0xdb, 0x2a, 0xed, 0xa8, 0x31, 0xe6, 0x21, 0xfc, 0xac, 0x8d, 0xd8, 0x1c, 0xee, 0x35, 0x03, 0x24, 0x2b, 0x33, 0xb0, 0xda, 0xa9, 0x87, 0xfe, 0x2f, 0x54, 0x93, 0xad, 0x2d, 0x06, 0xa1, 0x50, 0x07, 0x59, 0x00, 0x40, 0xce, 0x3c, 0x22, 0x77, 0x64, 0x2f, 0xd2, 0x7f, 0x3f, 0x25, 0x5e, 0x3d, 0x98, 0xd8, 0x9d, 0xfa, 0xeb, 0x86, 0xbe, 0x34, 0xe0, 0xb8, 0xfb, 0xb9, 0x35, 0xfb, 0x92, 0x85, 0x60, 0xfa, 0x29, 0x2d, 0x26, 0x34, 0x62, 0x5a, 0x50, 0x7d, 0xd5, 0x80, 0xa8, 0x91, 0x24, 0xb9, 0x21, 0x29, 0x3e, 0x8d, 0xfe, 0xdd, 0xc2, 0x81, 0xd7, 0x9e, 0xb3, 0xa5, 0x69, 0xd5, 0x9e, 0x0d, 0xb8, 0x01, 0x3e, 0x53, 0xf7, 0xd4, 0xc2, 0xf9, 0x6e, 0x5f, 0x2e, 0xc2, 0x7f, 0xd8, 0xdd, 0xb0, 0x18, 0x25, 0xd1, 0x7f, 0xca, 0x40, 0x6d, 0xaa, 0x62, 0x24, 0xc7, 0x60, 0x6d, 0x2c, 0x91, 0x52, 0x82, 0x09, 0x6a, 0x78, 0x05, 0x5a, 0x49, 0x62, 0x15, 0x37, 0xb4, 0xf0, 0x25, 0xa6, 0xe5, 0xb2, 0x12, 0x9b, 0xc8, 0xc1, 0xa4, 0x07 } +, + /* Signature */ + 128, + { 0x6e, 0x7e, 0xaa, 0xd8, 0x04, 0x94, 0x5e, 0xb0, 0x46, 0x70, 0xdd, 0x86, 0x76, 0xb7, 0x05, 0x7d, 0x03, 0xac, 0x3e, 0x22, 0x64, 0x65, 0xb1, 0xfb, 0x84, 0x03, 0xe6, 0xae, 0x79, 0x83, 0xe0, 0xa4, 0x6a, 0x89, 0xa4, 0xeb, 0x32, 0xbd, 0xc8, 0xe7, 0xae, 0x5a, 0x53, 0xd4, 0x8a, 0xa6, 0x4b, 0xc9, 0xc3, 0xdb, 0xc8, 0xcf, 0x9c, 0xd6, 0xdc, 0x6a, 0x68, 0xfc, 0xea, 0xe9, 0xe2, 0x9f, 0x47, 0x45, 0xfa, 0x49, 0xe1, 0x8d, 0x18, 0x4d, 0xc5, 0xd2, 0x6c, 0x4f, 0xeb, 0x35, 0x1f, 0xb4, 0xb2, 0x28, 0xc4, 0xc1, 0x8c, 0xab, 0xdb, 0xde, 0x86, 0x01, 0x72, 0x4a, 0xe3, 0x80, 0x3d, 0xb3, 0x05, 0xf2, 0xa0, 0x76, 0xfa, 0x8a, 0x57, 0xf4, 0x61, 0x0b, 0x8a, 0x6e, 0x0e, 0xd4, 0x35, 0x75, 0xbe, 0x5d, 0x5b, 0xfc, 0x16, 0x30, 0x47, 0x9d, 0xf3, 0xbc, 0xbc, 0x51, 0x51, 0x77, 0xaf, 0xe4, 0x99, 0x4a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.3", + /* Message to be signed */ + 65, + { 0x29, 0xb8, 0x5b, 0x14, 0xb2, 0xda, 0x94, 0x7a, 0x4c, 0x3a, 0xd1, 0xe5, 0x93, 0x7d, 0xa1, 0x92, 0xc6, 0x05, 0x08, 0x65, 0xaf, 0x95, 0x04, 0xa5, 0x44, 0x53, 0x70, 0xe4, 0x3d, 0x3a, 0x8d, 0xa5, 0xd3, 0x55, 0xfd, 0x58, 0x76, 0x6b, 0x25, 0x43, 0xac, 0x6f, 0x93, 0x10, 0x87, 0x83, 0xc1, 0x3f, 0xf2, 0x8b, 0x2b, 0xe5, 0x60, 0x83, 0xf0, 0x29, 0x82, 0x39, 0xe0, 0xee, 0x96, 0x81, 0xee, 0x47, 0xc6 } +, + /* Signature */ + 128, + { 0x80, 0xb3, 0x8c, 0xe7, 0x35, 0x12, 0x6c, 0x85, 0x45, 0xd9, 0x1d, 0x18, 0xec, 0x90, 0x37, 0x65, 0x4d, 0x46, 0xe4, 0xf3, 0xc5, 0x1a, 0x6b, 0x86, 0x18, 0xe1, 0x5f, 0x72, 0xcd, 0x20, 0x75, 0x00, 0xa4, 0x70, 0x01, 0x75, 0x77, 0xd0, 0xa8, 0xc5, 0x5a, 0x2b, 0xa3, 0x34, 0x38, 0x3f, 0x1f, 0x8d, 0x99, 0xfc, 0xe2, 0x46, 0x0b, 0x32, 0x97, 0xbc, 0x03, 0x7e, 0xf6, 0x4a, 0xc4, 0xa3, 0x09, 0x8c, 0x6a, 0xaa, 0x24, 0xa4, 0xd0, 0x14, 0x4a, 0xf1, 0x02, 0xd0, 0xdd, 0xa1, 0x7e, 0x07, 0xdc, 0x69, 0x59, 0x23, 0x93, 0x2e, 0x56, 0x8a, 0xda, 0x00, 0xdc, 0x4f, 0x7d, 0xbf, 0xbc, 0xde, 0xc4, 0x3c, 0xc9, 0x08, 0x38, 0x80, 0x17, 0xd2, 0xee, 0xf0, 0x4e, 0x60, 0xdf, 0xe4, 0xd5, 0x73, 0x40, 0xfa, 0xb9, 0x16, 0xe2, 0xb8, 0x11, 0x24, 0x4c, 0xb1, 0xe4, 0xa5, 0x52, 0x38, 0x6f, 0xe3, 0xed, 0x4c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.4", + /* Message to be signed */ + 93, + { 0xd3, 0xb7, 0xaa, 0xd3, 0x7a, 0x48, 0x90, 0xe0, 0x36, 0x5b, 0x86, 0xc7, 0xda, 0x94, 0x91, 0xe7, 0x3c, 0xdf, 0x55, 0x5d, 0x1b, 0x02, 0xb4, 0x51, 0x81, 0x6d, 0xc5, 0x2f, 0x96, 0x30, 0xd5, 0x90, 0xde, 0x83, 0xa5, 0xc9, 0x39, 0x61, 0x01, 0x25, 0x22, 0xdf, 0xf6, 0xdb, 0xbb, 0x9c, 0xdb, 0x0e, 0x71, 0xae, 0x51, 0x40, 0x19, 0x64, 0xaf, 0x18, 0x90, 0xe8, 0x93, 0x25, 0xdb, 0xd6, 0x26, 0xf2, 0xda, 0x01, 0x34, 0x58, 0xe3, 0x9e, 0xec, 0xa5, 0x83, 0xe8, 0x9e, 0x4c, 0x08, 0xe5, 0xd4, 0x12, 0xbe, 0x49, 0x84, 0x95, 0x88, 0x6e, 0x05, 0x51, 0xcf, 0xe7, 0x42, 0xb8, 0xb5 } +, + /* Signature */ + 128, + { 0x9d, 0x8a, 0x88, 0x89, 0xa3, 0x11, 0xb4, 0x86, 0xcb, 0xe2, 0x22, 0x57, 0x03, 0xf5, 0xd4, 0xae, 0x2a, 0x54, 0xc2, 0xbc, 0xaa, 0xad, 0x06, 0xfe, 0x76, 0x48, 0xb9, 0xe2, 0xd8, 0x5e, 0xdd, 0xa1, 0xa0, 0x7d, 0x85, 0x6d, 0x6a, 0xe9, 0xbd, 0x5c, 0xc1, 0xe5, 0x15, 0x32, 0x66, 0xec, 0x7f, 0x1e, 0x1d, 0xf3, 0xd9, 0x29, 0xcc, 0x44, 0x70, 0x0f, 0xac, 0x92, 0x64, 0x58, 0x41, 0x4c, 0x28, 0x41, 0xda, 0x83, 0x32, 0x8e, 0x81, 0xe0, 0xb9, 0xd6, 0xc3, 0x88, 0x5e, 0x76, 0x73, 0x70, 0xad, 0x5c, 0xf1, 0xf5, 0x76, 0xd9, 0xdc, 0xe3, 0x48, 0xca, 0xec, 0x5e, 0x64, 0x43, 0xe0, 0xae, 0xb7, 0xc3, 0xf7, 0x2b, 0x7d, 0xd2, 0x53, 0x66, 0x70, 0x23, 0xb9, 0xa4, 0x77, 0xab, 0x34, 0xdf, 0x8f, 0x20, 0x67, 0xe2, 0x25, 0xad, 0xcb, 0x73, 0xee, 0x11, 0xe1, 0x59, 0xeb, 0x64, 0x91, 0x47, 0xd6, 0x02 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.5", + /* Message to be signed */ + 82, + { 0xf6, 0x58, 0x18, 0x8c, 0x8f, 0x9d, 0xe6, 0x0b, 0x5e, 0x99, 0xa2, 0x9f, 0x52, 0xd3, 0xb8, 0x89, 0x20, 0x1b, 0x30, 0xd4, 0x64, 0xc3, 0xb7, 0x27, 0x92, 0xa3, 0x02, 0x09, 0x5d, 0xc1, 0xe7, 0x7d, 0x45, 0xe9, 0x4f, 0x5d, 0xab, 0x73, 0xdb, 0xb3, 0x13, 0x54, 0x38, 0x57, 0xff, 0x91, 0xdb, 0xf4, 0x73, 0xdf, 0xc1, 0x45, 0xd7, 0x3b, 0xd5, 0x06, 0x20, 0x75, 0xd1, 0x92, 0xa3, 0xfb, 0xf4, 0xa1, 0x33, 0xe7, 0xe5, 0x68, 0xdf, 0x20, 0xb8, 0xcf, 0xf7, 0x7b, 0x3a, 0xf6, 0x87, 0xaa, 0x22, 0x55, 0x9e, 0xc1 } +, + /* Signature */ + 128, + { 0x0a, 0x95, 0xa4, 0x4f, 0x62, 0x74, 0xe7, 0x4c, 0xec, 0x45, 0x17, 0x96, 0xaf, 0x56, 0x88, 0xd4, 0xbe, 0x01, 0x08, 0x93, 0xfa, 0xae, 0x27, 0xd4, 0x90, 0xf4, 0x77, 0x1b, 0x00, 0x3f, 0x70, 0x46, 0xcc, 0xcd, 0x41, 0x9f, 0xc8, 0x19, 0xd7, 0x33, 0x19, 0x55, 0xf4, 0x1e, 0xac, 0x93, 0x39, 0xf5, 0x46, 0xc5, 0x84, 0xa8, 0xb4, 0x2a, 0x5a, 0xc6, 0x32, 0x90, 0x58, 0x3f, 0xf3, 0xeb, 0x6b, 0x29, 0xca, 0xdc, 0x75, 0x4a, 0xe5, 0x8d, 0x5a, 0x56, 0x37, 0xb6, 0x60, 0x97, 0x96, 0xe8, 0x05, 0x51, 0x73, 0xff, 0x20, 0xa9, 0xcc, 0xe4, 0x92, 0xfd, 0x78, 0x37, 0x46, 0x86, 0x15, 0xe8, 0x41, 0x08, 0x87, 0xf0, 0xb4, 0xa5, 0x9f, 0xf2, 0x52, 0xa8, 0x25, 0x97, 0x76, 0xc8, 0xff, 0xda, 0xa6, 0x7c, 0x87, 0xdf, 0xf8, 0x98, 0x3a, 0xe6, 0x79, 0xd1, 0xde, 0x22, 0xea, 0x15, 0x8d, 0x48, 0xf6, 0x8b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.6", + /* Message to be signed */ + 128, + { 0x31, 0xae, 0x5f, 0x83, 0xa0, 0xfb, 0x3a, 0xc9, 0x25, 0x5f, 0xfa, 0x43, 0x5f, 0x70, 0xe2, 0xab, 0x65, 0x55, 0x66, 0xe5, 0xfb, 0x8b, 0x78, 0xb8, 0x02, 0xc1, 0x87, 0xcf, 0xf1, 0xc5, 0xe4, 0x0f, 0xed, 0x06, 0x97, 0x8c, 0x5d, 0x59, 0x76, 0xeb, 0x4c, 0xa7, 0x75, 0x80, 0x63, 0x99, 0xa6, 0xfc, 0x4d, 0xb5, 0x0c, 0x1f, 0x88, 0x66, 0x1b, 0xa6, 0x8a, 0xbc, 0x21, 0xfb, 0x2c, 0xcd, 0x53, 0x7f, 0x50, 0x18, 0xf3, 0x6e, 0xd1, 0xf7, 0xd4, 0x53, 0x83, 0xfd, 0x46, 0x9e, 0x77, 0xba, 0xb3, 0xe8, 0xa9, 0x5d, 0xfa, 0x1b, 0x94, 0x1e, 0x43, 0x0d, 0xde, 0xc5, 0x52, 0xdc, 0xd8, 0x2f, 0x5d, 0x10, 0xd2, 0x9c, 0xd1, 0x0a, 0x22, 0xd1, 0x7c, 0xe2, 0x42, 0x59, 0x28, 0xff, 0x5d, 0x07, 0x10, 0xdc, 0xe7, 0xd9, 0xf8, 0x3b, 0x12, 0xe0, 0x4c, 0x1a, 0x01, 0x59, 0xc2, 0x71, 0x76, 0xe0, 0x4a, 0xcc } +, + /* Signature */ + 128, + { 0x3f, 0x11, 0xea, 0x73, 0x9f, 0x32, 0x9c, 0x9d, 0x40, 0x04, 0x60, 0x34, 0xb6, 0xc0, 0xcf, 0xce, 0xb4, 0x9b, 0xc3, 0x20, 0x1a, 0x5f, 0x25, 0xea, 0xf5, 0x01, 0x5a, 0xed, 0xed, 0x02, 0x18, 0x9c, 0xe0, 0xb0, 0xcf, 0xde, 0x19, 0x12, 0x5b, 0xd2, 0x88, 0xb7, 0xd0, 0xc0, 0x62, 0x32, 0x1a, 0x5b, 0xdc, 0x2c, 0xfa, 0x42, 0x26, 0xf5, 0x10, 0x4a, 0x1f, 0xba, 0xeb, 0xbe, 0x7f, 0x72, 0xf5, 0xf7, 0x92, 0x7e, 0x1e, 0xae, 0x26, 0xfd, 0xc5, 0xba, 0x92, 0xf2, 0xd3, 0xf8, 0x69, 0xeb, 0xc3, 0x2d, 0x90, 0x18, 0xdd, 0x04, 0xed, 0xe8, 0x6d, 0xe5, 0xc4, 0x54, 0xf1, 0xf7, 0xa1, 0xb2, 0xe2, 0xd1, 0x94, 0x0a, 0xac, 0xae, 0x27, 0x79, 0x63, 0x55, 0xfe, 0x18, 0xac, 0x80, 0x97, 0x53, 0x53, 0x92, 0x9a, 0xc6, 0xa8, 0x38, 0x45, 0x8b, 0x5d, 0x9d, 0xc7, 0x57, 0x6e, 0x38, 0x87, 0xee, 0x7b, 0xca } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.7", + /* Message to be signed */ + 256, + { 0x96, 0xff, 0x99, 0xf1, 0x50, 0x60, 0xc9, 0x73, 0xa6, 0x5b, 0x69, 0xa8, 0xb5, 0xb6, 0x3a, 0xdb, 0x33, 0x25, 0x32, 0x0d, 0xa9, 0x37, 0x29, 0x75, 0x84, 0xad, 0x4f, 0xad, 0x5c, 0x3c, 0x74, 0x69, 0x01, 0x9e, 0x9c, 0xf7, 0x2a, 0xcb, 0x31, 0x5f, 0x1e, 0x49, 0x19, 0x27, 0xbb, 0xa1, 0x94, 0x87, 0x55, 0x82, 0x3e, 0xb0, 0x7e, 0x3f, 0x20, 0xac, 0xdf, 0x78, 0x65, 0x3c, 0xae, 0x45, 0x0e, 0x47, 0xbc, 0x54, 0xba, 0xf8, 0xca, 0x11, 0x67, 0xa5, 0x05, 0x08, 0x44, 0xe0, 0x22, 0x22, 0x0e, 0xe6, 0x65, 0x8a, 0x8d, 0xdd, 0x95, 0x63, 0x2e, 0x9a, 0xdc, 0x1a, 0x6c, 0x14, 0x37, 0x9c, 0x1c, 0x5a, 0xe5, 0xa0, 0xce, 0x5d, 0xc4, 0x02, 0x08, 0x09, 0x62, 0x2a, 0xfd, 0xec, 0xf8, 0x1f, 0x18, 0xa5, 0x1e, 0x28, 0x66, 0x6d, 0x02, 0xb1, 0xdc, 0xda, 0x0a, 0x27, 0xb8, 0xc3, 0xd2, 0xc2, 0x7b, 0x2c, 0x07, 0xb3, 0x80, 0x22, 0x00, 0x01, 0x7a, 0x7c, 0x12, 0x4a, 0x43, 0x37, 0xcc, 0x4b, 0x6e, 0xa2, 0xae, 0xa7, 0x5c, 0x68, 0xb4, 0x40, 0xe3, 0x79, 0x47, 0xe3, 0x61, 0x9b, 0xcf, 0xee, 0x05, 0x5b, 0xb2, 0xed, 0xab, 0xc4, 0x24, 0x49, 0x07, 0xe0, 0x48, 0x3d, 0xd3, 0xa1, 0x7d, 0x8e, 0xdf, 0xf3, 0xa6, 0x50, 0x29, 0x3f, 0xd4, 0xab, 0xf5, 0xc4, 0x5d, 0x1a, 0x5b, 0x6c, 0x54, 0x02, 0xba, 0x2b, 0x81, 0xb7, 0xb0, 0xe0, 0xc9, 0x5e, 0xe9, 0x49, 0xb2, 0xa2, 0x38, 0xc1, 0x99, 0x56, 0x20, 0x6c, 0x12, 0x4e, 0x0c, 0xd9, 0xc2, 0x46, 0x20, 0xb3, 0x6a, 0x83, 0xbf, 0x93, 0xb9, 0x6e, 0xf2, 0x04, 0xbd, 0xe5, 0x31, 0x6c, 0x1f, 0x53, 0x27, 0xc0, 0xa6, 0x21, 0xec, 0xce, 0x20, 0x93, 0xc0, 0x65, 0x2d, 0xdf, 0x32, 0x17, 0x68, 0xd7, 0x45, 0x02, 0xf1, 0x90, 0x85, 0x29, 0x62, 0x9b, 0xab, 0x68 } +, + /* Signature */ + 128, + { 0x18, 0x3f, 0x85, 0x3d, 0x0d, 0x03, 0x62, 0x18, 0x70, 0xe3, 0xba, 0x58, 0x68, 0x50, 0xc5, 0xea, 0x59, 0xfc, 0x4e, 0x9a, 0xcf, 0x37, 0x94, 0xb9, 0xad, 0x59, 0xa1, 0xbb, 0x80, 0x18, 0x1e, 0x77, 0xb1, 0x11, 0xd6, 0x64, 0x86, 0x47, 0xe1, 0x39, 0xa3, 0x9e, 0xc0, 0x4f, 0x86, 0x18, 0x74, 0x91, 0xe7, 0x7b, 0x4d, 0x75, 0xc0, 0x60, 0x79, 0x5b, 0xf7, 0x27, 0x08, 0x46, 0xd3, 0x96, 0xe0, 0xbf, 0xea, 0x83, 0x15, 0x79, 0x5e, 0x79, 0xd7, 0x6a, 0x91, 0x9e, 0xa7, 0x6b, 0x06, 0xee, 0xc1, 0x3b, 0xaf, 0x4c, 0xe8, 0xaf, 0xe1, 0xe3, 0x4b, 0xc2, 0x24, 0x57, 0xd7, 0xb7, 0x99, 0x2e, 0x08, 0x42, 0xef, 0xad, 0xe1, 0x79, 0xb0, 0xae, 0xda, 0xcc, 0xfb, 0xe2, 0xd2, 0x3d, 0x3e, 0xb3, 0x14, 0xe1, 0xde, 0x91, 0xc8, 0x71, 0xb9, 0xdb, 0x5a, 0xbf, 0xfb, 0x17, 0x47, 0x7f, 0xba, 0x23, 0x3a, 0x06 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.8", + /* Message to be signed */ + 179, + { 0x3a, 0x17, 0x6c, 0x79, 0x3a, 0x54, 0x6e, 0x2d, 0x27, 0x6f, 0xb8, 0xff, 0xc3, 0x28, 0x16, 0x3b, 0x49, 0x49, 0x97, 0xa5, 0x30, 0x2a, 0xae, 0x2e, 0x50, 0x45, 0xa2, 0xa2, 0x06, 0x87, 0xea, 0x6d, 0x1f, 0x18, 0x1c, 0x6a, 0xbf, 0xe6, 0x09, 0x0c, 0x8d, 0xc4, 0x02, 0x56, 0xdb, 0x3d, 0xe0, 0x83, 0x22, 0x64, 0x7f, 0xb7, 0x95, 0xbb, 0xa1, 0x71, 0x3f, 0xb5, 0x7e, 0x33, 0xd5, 0x3e, 0x0e, 0x13, 0xbe, 0xda, 0xc6, 0xa6, 0x58, 0xad, 0x4a, 0xb4, 0x91, 0x22, 0x38, 0x81, 0x19, 0x8d, 0xf2, 0x93, 0x67, 0xfa, 0xad, 0xe8, 0xbe, 0x9f, 0xca, 0xa4, 0xe4, 0x83, 0xf7, 0xb7, 0xf3, 0xdc, 0x7c, 0xbb, 0xf9, 0x7a, 0x17, 0xaa, 0xd8, 0x8c, 0x26, 0xcf, 0xc6, 0x41, 0x0f, 0x94, 0x5b, 0x54, 0xfc, 0x53, 0xdb, 0x55, 0xac, 0x80, 0x3d, 0x8b, 0x73, 0x69, 0x1b, 0x14, 0x84, 0x84, 0x7d, 0x7f, 0x3b, 0x7e, 0x93, 0x94, 0xe5, 0x5f, 0x0a, 0x51, 0xfe, 0x61, 0xae, 0x84, 0x52, 0x3c, 0x94, 0xb2, 0x2e, 0x82, 0x39, 0x6d, 0xb6, 0xcf, 0xac, 0xb7, 0x2e, 0x0e, 0xe4, 0x94, 0xaa, 0x0f, 0x1f, 0xa5, 0x93, 0x12, 0x54, 0x43, 0xae, 0x15, 0x55, 0xa6, 0xa9, 0x33, 0xfa, 0xce, 0x00, 0x74, 0x79, 0x1d, 0xc2, 0xc2, 0x92, 0x42, 0xeb } +, + /* Signature */ + 128, + { 0x41, 0x3c, 0x92, 0x23, 0xa2, 0xe9, 0xb1, 0x22, 0xcd, 0x87, 0x25, 0x77, 0xe5, 0x2f, 0x31, 0x3d, 0x41, 0xda, 0xc7, 0x9a, 0x26, 0xcb, 0x10, 0x33, 0xda, 0x0b, 0x6f, 0xcc, 0x4b, 0x48, 0x21, 0x07, 0x74, 0x4b, 0xf4, 0x90, 0xfa, 0x79, 0x8d, 0xcc, 0xd0, 0xcb, 0xd1, 0x18, 0xef, 0x39, 0xc0, 0xf5, 0x59, 0xd8, 0x7b, 0x89, 0x33, 0x5d, 0xb0, 0x9b, 0xe7, 0x70, 0x0f, 0xb0, 0x9f, 0xdb, 0xd3, 0x40, 0x40, 0xa0, 0x0b, 0xe5, 0xca, 0x42, 0x88, 0x34, 0x77, 0xb0, 0x6e, 0x4e, 0x10, 0xa7, 0xcb, 0x11, 0x76, 0x8f, 0xcb, 0x02, 0xc3, 0x4f, 0xb1, 0x06, 0xe5, 0x22, 0x86, 0x0d, 0x10, 0x69, 0x39, 0x06, 0x26, 0x0f, 0x43, 0xd9, 0x06, 0x12, 0x99, 0x03, 0x93, 0xa8, 0xff, 0xac, 0x9f, 0xd7, 0x0c, 0xa3, 0x78, 0x29, 0x11, 0x1e, 0xeb, 0xa6, 0xf3, 0xde, 0xe5, 0x4e, 0xf1, 0xc1, 0x62, 0x68, 0xb3, 0x3e } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.9", + /* Message to be signed */ + 197, + { 0x06, 0x8a, 0x99, 0x1b, 0x32, 0xb6, 0x76, 0xc6, 0x4b, 0x89, 0x8c, 0x67, 0xe1, 0x13, 0x72, 0x82, 0xb4, 0x37, 0x11, 0xb0, 0xd0, 0x67, 0x1c, 0x24, 0x7d, 0x9f, 0x7c, 0x48, 0xf5, 0x04, 0x3e, 0x4f, 0xc2, 0x06, 0xdc, 0x65, 0xaf, 0x89, 0x06, 0xf2, 0x52, 0xf0, 0x24, 0x52, 0x05, 0xea, 0x08, 0x43, 0x23, 0xd4, 0x27, 0x6b, 0xe5, 0xaa, 0x0f, 0xc5, 0xaf, 0x9c, 0x3f, 0x34, 0xb2, 0xfd, 0x66, 0x34, 0xdf, 0x57, 0x2f, 0xc3, 0x13, 0xd2, 0x73, 0xb5, 0x3e, 0x9e, 0x36, 0xb9, 0x46, 0xe7, 0xe6, 0x72, 0xf9, 0x8d, 0x85, 0x7d, 0x7e, 0xdd, 0xd3, 0xdd, 0x04, 0x39, 0x31, 0x32, 0xf4, 0x61, 0xf2, 0x2c, 0x99, 0x00, 0x26, 0x16, 0x6f, 0x38, 0x5b, 0xe1, 0x59, 0x5c, 0x7f, 0x23, 0xf8, 0x9f, 0xf5, 0x7e, 0x05, 0xa7, 0xbe, 0x28, 0x5d, 0x10, 0x56, 0x15, 0x48, 0x5f, 0x35, 0x6a, 0xba, 0xb1, 0xff, 0x2a, 0xb9, 0x27, 0xd6, 0x09, 0x95, 0x2a, 0x62, 0x7e, 0x46, 0x8c, 0xa7, 0x59, 0x0a, 0xcb, 0x52, 0x13, 0xf4, 0x31, 0x39, 0xf8, 0xe2, 0xc9, 0xd4, 0xd1, 0x7c, 0x6b, 0xd7, 0x91, 0x4e, 0x53, 0xf0, 0x2f, 0xd1, 0x9a, 0x13, 0x1f, 0xf4, 0x9c, 0xd2, 0x5e, 0xde, 0x8f, 0x41, 0x8a, 0x88, 0x53, 0x0a, 0x82, 0x39, 0x88, 0x7f, 0x0f, 0xc7, 0x97, 0xed, 0xb5, 0x04, 0x64, 0x79, 0x64, 0xbf, 0x31, 0xca, 0xaf, 0x08, 0x0d, 0x58, 0x17, 0xa0 } +, + /* Signature */ + 128, + { 0x57, 0x5d, 0xa9, 0xe9, 0xbe, 0xfc, 0xa1, 0x82, 0x95, 0x46, 0xe8, 0x29, 0x38, 0x15, 0x00, 0x11, 0x32, 0x03, 0x0e, 0x74, 0x9c, 0xa5, 0x10, 0x88, 0xf1, 0x68, 0xbd, 0x15, 0x0b, 0x13, 0x94, 0xc7, 0xac, 0xd5, 0x97, 0x8b, 0xca, 0x03, 0xf7, 0xb9, 0xd9, 0x2a, 0x29, 0xb8, 0xe2, 0x85, 0x6b, 0x0d, 0xa0, 0x7f, 0x0b, 0xb1, 0x5c, 0x0b, 0x33, 0xe0, 0x54, 0x87, 0x99, 0x1a, 0xd9, 0x7a, 0x81, 0x2d, 0xc9, 0x04, 0xaa, 0xf0, 0xfd, 0x1e, 0x38, 0x7e, 0xf1, 0xc2, 0x70, 0xc6, 0x86, 0x8d, 0x3e, 0xe1, 0xc6, 0x11, 0x57, 0x7b, 0xc4, 0xd0, 0x7f, 0xf4, 0x56, 0xb2, 0x43, 0x98, 0x32, 0x90, 0x8a, 0x3d, 0xcc, 0x4f, 0xc0, 0x99, 0x04, 0x72, 0xfd, 0xa3, 0xcc, 0x61, 0x11, 0x93, 0x0b, 0x99, 0x79, 0x5d, 0x60, 0xc0, 0xe3, 0x78, 0x88, 0xe8, 0x7c, 0xe0, 0x0b, 0xbf, 0x3c, 0x1c, 0xf3, 0x07, 0xf9, 0xe1 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.10", + /* Message to be signed */ + 88, + { 0xd6, 0x83, 0x9e, 0xe6, 0xd0, 0x74, 0x50, 0x32, 0x7e, 0x09, 0xa0, 0x3e, 0x1e, 0xc2, 0x80, 0xe1, 0xc8, 0xd1, 0x15, 0x00, 0xdc, 0x39, 0x0a, 0x49, 0xa9, 0xc9, 0x82, 0x87, 0x49, 0xc3, 0xe9, 0xa4, 0xbe, 0xe2, 0xba, 0x57, 0x6f, 0x6d, 0x12, 0x17, 0xa8, 0xe7, 0x85, 0x4a, 0x90, 0x7e, 0xeb, 0x93, 0xdf, 0xff, 0x92, 0x30, 0x8a, 0xd0, 0xd9, 0x4e, 0x2b, 0x38, 0x1f, 0x92, 0xb0, 0xe8, 0x4a, 0x47, 0x1b, 0xf1, 0xf3, 0x7a, 0x68, 0xe9, 0x65, 0xf6, 0x58, 0x59, 0xd1, 0xfd, 0xfd, 0x6f, 0xea, 0x84, 0x40, 0x79, 0xc4, 0x03, 0x70, 0xdc, 0xea, 0xe2 } +, + /* Signature */ + 128, + { 0xa7, 0xc5, 0xf6, 0xd0, 0xde, 0x9c, 0xf8, 0xf4, 0x17, 0x37, 0xf2, 0x3a, 0xe3, 0xe8, 0xcf, 0x60, 0x9a, 0xeb, 0xcf, 0x22, 0xd5, 0xde, 0x12, 0x13, 0xd9, 0x57, 0x3c, 0xb9, 0x44, 0x03, 0xf8, 0x9c, 0x0f, 0x70, 0x88, 0xff, 0xfc, 0x61, 0x10, 0x6f, 0xa6, 0x09, 0xc7, 0x37, 0x1a, 0x8d, 0x7e, 0x1b, 0xcd, 0x22, 0x1b, 0xc1, 0xad, 0x94, 0x91, 0x2f, 0xab, 0xf2, 0xff, 0xc0, 0x2f, 0x84, 0x84, 0x56, 0x4c, 0x22, 0x5c, 0x06, 0x9b, 0xfc, 0x6d, 0xa9, 0xf3, 0xf9, 0xf4, 0x97, 0x4e, 0x08, 0xe1, 0xfe, 0x56, 0xf7, 0x48, 0xff, 0x79, 0x05, 0x97, 0x90, 0x6a, 0x95, 0x4e, 0x38, 0x37, 0x43, 0xa3, 0x7e, 0x57, 0x5f, 0xef, 0x07, 0x4f, 0x06, 0x0f, 0x3d, 0xd1, 0x5b, 0x5e, 0xe0, 0xf9, 0x4d, 0xba, 0x69, 0xd8, 0x6c, 0x99, 0x22, 0x3f, 0xa9, 0xc3, 0xa6, 0x1a, 0x8c, 0xb2, 0xaf, 0x2f, 0xab, 0x1e, 0x04 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.11", + /* Message to be signed */ + 33, + { 0x33, 0x84, 0x9c, 0x67, 0xdf, 0x9a, 0x6f, 0xfa, 0xc3, 0xda, 0x90, 0xa8, 0xcd, 0x31, 0x73, 0x1a, 0x02, 0x97, 0xb9, 0xd6, 0x01, 0x0a, 0x03, 0x32, 0x0f, 0x88, 0x45, 0x03, 0x5f, 0xc3, 0x43, 0x09, 0xad } +, + /* Signature */ + 128, + { 0x1b, 0x87, 0x05, 0x1f, 0x15, 0x91, 0xc8, 0xae, 0x7e, 0xe3, 0xcb, 0x24, 0x26, 0x70, 0x39, 0xa7, 0x28, 0x40, 0x5d, 0xbf, 0x23, 0x1c, 0xaf, 0x21, 0xf3, 0x24, 0x7f, 0x05, 0x85, 0x8b, 0x2a, 0x51, 0x65, 0x0b, 0x81, 0xbc, 0x53, 0x77, 0x86, 0x5e, 0x4c, 0x1e, 0x8f, 0xd0, 0x36, 0x41, 0x52, 0xa1, 0x6b, 0xc5, 0x8f, 0x7d, 0x2a, 0xc0, 0x1c, 0xa6, 0x79, 0xcc, 0x49, 0xdd, 0x04, 0x89, 0x03, 0xd5, 0x5a, 0xd0, 0x5f, 0x10, 0x2c, 0x74, 0xb3, 0x60, 0x1f, 0x25, 0xad, 0x30, 0x62, 0x40, 0x25, 0xc3, 0x0b, 0x6f, 0x0f, 0x79, 0x11, 0xfc, 0x22, 0x45, 0x8e, 0x5d, 0x43, 0x5f, 0x38, 0x8e, 0x3f, 0xbc, 0x49, 0x5f, 0xa0, 0xc6, 0x10, 0xc1, 0x29, 0x8f, 0x82, 0x1d, 0xa5, 0x38, 0x40, 0x3a, 0x93, 0x36, 0x4d, 0x2e, 0xab, 0xf1, 0xe3, 0xb3, 0x2f, 0x81, 0x10, 0xa7, 0xe0, 0x3e, 0x37, 0x2e, 0xcb, 0xc5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.12", + /* Message to be signed */ + 77, + { 0xb3, 0xda, 0xba, 0xca, 0x20, 0x59, 0xa7, 0x0e, 0x25, 0xcb, 0xdd, 0xf4, 0xaa, 0x59, 0x25, 0x99, 0x57, 0x54, 0xac, 0xe4, 0x3c, 0x5d, 0x60, 0x36, 0x40, 0x48, 0x9a, 0xf4, 0x8f, 0xea, 0x6e, 0xdc, 0x4e, 0x19, 0xcb, 0xee, 0xa2, 0xc0, 0xdb, 0x62, 0xae, 0x0a, 0x10, 0x4c, 0x72, 0xe4, 0xcd, 0x56, 0xcb, 0x53, 0x2f, 0x4f, 0xe5, 0x77, 0xb3, 0x6a, 0x81, 0x98, 0xb4, 0x87, 0x9d, 0x7f, 0xf8, 0x04, 0x26, 0x90, 0xf6, 0x62, 0x77, 0x3f, 0x3d, 0x63, 0x93, 0xf2, 0x58, 0x98, 0xd2 } +, + /* Signature */ + 128, + { 0x26, 0xf1, 0x37, 0x70, 0x26, 0x3f, 0xc5, 0xbd, 0xbe, 0xad, 0xf8, 0x8f, 0xb4, 0xdd, 0x30, 0x7a, 0x38, 0x95, 0x9b, 0x16, 0xf3, 0xdf, 0x94, 0x6a, 0xde, 0x86, 0x4b, 0x1e, 0x7e, 0x91, 0x4d, 0x36, 0x4e, 0xbf, 0x9a, 0xdf, 0xd8, 0x6a, 0x70, 0x02, 0x2d, 0xc6, 0x1b, 0x43, 0xfb, 0x1f, 0xdf, 0x86, 0x96, 0x97, 0x8e, 0x2d, 0x1f, 0x6a, 0x2d, 0xef, 0xee, 0x75, 0xad, 0xaa, 0x69, 0xa3, 0x95, 0x32, 0x07, 0x40, 0x50, 0xbe, 0x70, 0x8e, 0xaf, 0x03, 0x1d, 0x5f, 0xae, 0x0f, 0xfe, 0x24, 0x5b, 0xa4, 0xff, 0x3c, 0x5e, 0x34, 0x0a, 0xf5, 0xdf, 0xec, 0x6a, 0x4c, 0xce, 0x0e, 0x18, 0x87, 0x6c, 0xfc, 0x13, 0x66, 0xee, 0xed, 0xdf, 0xce, 0x0f, 0x83, 0x5b, 0x38, 0xe8, 0x18, 0x81, 0xb1, 0xfc, 0x58, 0x32, 0x93, 0x0f, 0xc7, 0x9b, 0x08, 0xf1, 0xfb, 0x34, 0xfb, 0x22, 0x42, 0x33, 0xf4, 0xc4, 0x68 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.13", + /* Message to be signed */ + 94, + { 0x09, 0x91, 0x12, 0xfa, 0xe7, 0x40, 0x88, 0x8c, 0xea, 0xac, 0x70, 0x54, 0xd5, 0x97, 0x35, 0x1d, 0x79, 0xe1, 0x59, 0xa9, 0x58, 0xd8, 0x12, 0x15, 0x78, 0xe5, 0x2c, 0x83, 0x7d, 0xb3, 0x54, 0x3c, 0xfa, 0x6f, 0x8e, 0x7f, 0x1d, 0xbd, 0x2a, 0x61, 0x97, 0x86, 0x45, 0xa4, 0xd3, 0x85, 0xb9, 0xbb, 0x1c, 0x60, 0xbf, 0xb1, 0x1b, 0xb3, 0xc8, 0x75, 0x2a, 0xe3, 0x1f, 0x99, 0x6d, 0xbb, 0x52, 0x62, 0x8f, 0x93, 0xd5, 0x26, 0x94, 0xf1, 0x82, 0xe6, 0x90, 0x35, 0xa5, 0xe5, 0x57, 0xec, 0x71, 0x82, 0x62, 0xf4, 0x03, 0xdf, 0x52, 0x11, 0xf7, 0x3c, 0x6d, 0xe0, 0xd5, 0x5a, 0x0b, 0xa7 } +, + /* Signature */ + 128, + { 0x8d, 0x8c, 0x8f, 0x3a, 0x86, 0xf4, 0x9e, 0xdb, 0xd1, 0x25, 0xc8, 0x3e, 0xbf, 0x6d, 0x52, 0xe7, 0x65, 0x16, 0x15, 0x01, 0x48, 0x21, 0x54, 0x59, 0x8c, 0x28, 0x3a, 0xbe, 0x94, 0x02, 0x77, 0x87, 0x2b, 0x00, 0xd0, 0x77, 0x7c, 0x2e, 0x69, 0x7b, 0x78, 0x83, 0xcc, 0x32, 0x1e, 0x15, 0x1c, 0x80, 0x11, 0x6f, 0x9f, 0xcd, 0x17, 0x7a, 0xc4, 0xc7, 0xde, 0xdd, 0xf0, 0x3c, 0xa1, 0xb2, 0xc5, 0x93, 0x31, 0xdc, 0x1c, 0x8e, 0x94, 0x7f, 0x1e, 0xb2, 0xaa, 0xee, 0x8c, 0xc9, 0x41, 0xdd, 0xc5, 0xf3, 0x74, 0xa6, 0x3d, 0x6c, 0x99, 0x38, 0xec, 0xd8, 0xe8, 0x8c, 0xbc, 0xec, 0x58, 0x92, 0x9c, 0xff, 0xdd, 0xef, 0x0b, 0xa2, 0x17, 0x58, 0x85, 0xa8, 0x0d, 0xc4, 0xcd, 0x92, 0xd6, 0xb7, 0x9d, 0x9c, 0x6a, 0x81, 0x69, 0x6e, 0x16, 0xf9, 0xa8, 0x3a, 0x10, 0xca, 0x8e, 0xfa, 0xf1, 0x97, 0x5f, 0x55 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.14", + /* Message to be signed */ + 194, + { 0xaa, 0x17, 0xe6, 0xbb, 0xd6, 0xdb, 0x19, 0xe5, 0x4b, 0xee, 0x1a, 0x7f, 0x0e, 0xdc, 0xca, 0xce, 0xab, 0x63, 0x5d, 0x76, 0x28, 0xfc, 0xaa, 0x18, 0xec, 0xfa, 0xfc, 0x40, 0x1c, 0xb3, 0xfe, 0xb5, 0x1f, 0x9a, 0x37, 0x31, 0xf3, 0x80, 0x2c, 0xbe, 0xa8, 0x1c, 0x73, 0x30, 0x28, 0xc9, 0x58, 0x4b, 0x6b, 0x78, 0xe2, 0x05, 0x59, 0x54, 0xcf, 0x91, 0x04, 0xda, 0xa6, 0x77, 0xaa, 0x40, 0xbe, 0x9b, 0x7c, 0x65, 0xb0, 0x7a, 0xc4, 0xa8, 0xbf, 0x25, 0xc1, 0x14, 0x9e, 0x05, 0x47, 0x35, 0xcf, 0x3c, 0xe3, 0x32, 0xd4, 0x29, 0xbc, 0x73, 0x80, 0x24, 0x45, 0xdf, 0xb3, 0x68, 0x8b, 0xb8, 0x19, 0x48, 0xb5, 0x7e, 0x27, 0x6a, 0xf3, 0x24, 0x62, 0xf7, 0xad, 0x80, 0x4d, 0x50, 0xc9, 0x3b, 0xc7, 0xe9, 0xef, 0x75, 0x37, 0x69, 0x5a, 0x27, 0x1a, 0xf7, 0x2e, 0x4b, 0xd4, 0x7c, 0xe5, 0xfa, 0x9d, 0x62, 0xf2, 0xda, 0xc0, 0x33, 0x36, 0x23, 0xf4, 0x9e, 0xb9, 0xd6, 0xd7, 0x80, 0x34, 0xed, 0x1d, 0xf6, 0xe1, 0x2b, 0xfd, 0x04, 0x26, 0x1b, 0xbe, 0x5c, 0xe0, 0x40, 0xe0, 0x3e, 0xbe, 0x25, 0x8d, 0x2d, 0x05, 0x2a, 0x12, 0xad, 0x4e, 0x3b, 0xf2, 0x53, 0x04, 0x23, 0x01, 0xc7, 0x64, 0x58, 0xed, 0x91, 0x0c, 0x5f, 0xfa, 0x70, 0x5c, 0x74, 0x7a, 0xd8, 0xca, 0x0c, 0x1c, 0x62, 0x28, 0xda, 0x2c, 0x97, 0xe1, 0x38 } +, + /* Signature */ + 128, + { 0x64, 0x4e, 0xa0, 0x76, 0x21, 0x4d, 0xbd, 0xdd, 0x30, 0x05, 0x5d, 0x7c, 0x56, 0x18, 0x92, 0x27, 0x9b, 0x46, 0xba, 0xb1, 0xe1, 0x22, 0x53, 0x42, 0x4c, 0x28, 0xf4, 0x49, 0xe1, 0x72, 0x64, 0x6a, 0xf3, 0x49, 0x8c, 0x7a, 0xfc, 0xbf, 0xf7, 0x68, 0xe0, 0x46, 0xa7, 0xc2, 0xe3, 0xd9, 0xc0, 0xe7, 0x12, 0x8f, 0x87, 0x7b, 0x92, 0x19, 0x5a, 0xa2, 0xbb, 0x9f, 0x1c, 0xfb, 0xdf, 0xd1, 0x5b, 0xb6, 0x5f, 0xbd, 0x23, 0xef, 0xb2, 0x94, 0xfb, 0xb1, 0x1a, 0x3c, 0x66, 0x05, 0x6d, 0x60, 0x63, 0x85, 0x3b, 0xb2, 0x3c, 0x27, 0x46, 0x65, 0xa1, 0x3e, 0xf4, 0xf3, 0xc1, 0x2f, 0x59, 0x21, 0xa4, 0x19, 0xe9, 0x49, 0xb3, 0x0c, 0x0b, 0xc0, 0xd7, 0x7d, 0x6b, 0x28, 0x69, 0x1d, 0x23, 0x64, 0xd9, 0x5b, 0xf6, 0x8b, 0xe8, 0xd5, 0x97, 0x8e, 0xf1, 0xbc, 0x98, 0x52, 0xa4, 0xf0, 0x66, 0x04, 0x47, 0x4a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.15", + /* Message to be signed */ + 141, + { 0x28, 0x24, 0x9c, 0x38, 0x7a, 0x06, 0x14, 0x40, 0xe9, 0x86, 0x38, 0xe1, 0xed, 0x78, 0xa4, 0x86, 0x51, 0x30, 0xe5, 0x75, 0x33, 0xd7, 0x89, 0x10, 0x8c, 0x63, 0xe1, 0x5f, 0xd8, 0x01, 0x9b, 0xad, 0x2c, 0xd1, 0xa7, 0x55, 0x2b, 0xd8, 0xaf, 0xd2, 0x06, 0xd9, 0x78, 0xeb, 0x1f, 0x2c, 0xf3, 0xf2, 0x3a, 0xfc, 0x4b, 0x34, 0xe6, 0xdd, 0x7f, 0x69, 0xc1, 0xfd, 0xf4, 0xfe, 0xc2, 0x52, 0x68, 0xd1, 0x86, 0x55, 0x51, 0x94, 0x49, 0x22, 0x90, 0x6d, 0xce, 0x6d, 0xc4, 0x41, 0xf9, 0x4a, 0x46, 0x6b, 0xf8, 0x39, 0x1a, 0xd8, 0x2b, 0xf5, 0x94, 0x0e, 0x44, 0x71, 0x10, 0xf1, 0xd1, 0x5d, 0xe1, 0x29, 0x31, 0x29, 0xfb, 0x44, 0x24, 0xa1, 0x71, 0x75, 0x19, 0xd6, 0xd4, 0x28, 0xd6, 0x6b, 0x7a, 0x10, 0x91, 0x42, 0xac, 0xc9, 0x15, 0xf1, 0xea, 0xc9, 0x6d, 0xef, 0x2c, 0x32, 0x90, 0xb0, 0x1d, 0x05, 0x99, 0x0b, 0xf8, 0x02, 0x3a, 0x6a, 0x64, 0x71, 0x2f, 0x63, 0x13, 0x7a, 0x8e } +, + /* Signature */ + 128, + { 0x57, 0x02, 0x06, 0x06, 0x69, 0xed, 0x47, 0xbb, 0xca, 0x11, 0xb9, 0x16, 0x68, 0x28, 0x9e, 0xa3, 0xf5, 0xe7, 0x46, 0xad, 0x2e, 0x38, 0x6d, 0xd1, 0xbc, 0x2a, 0x8b, 0xab, 0x17, 0x46, 0xba, 0x2a, 0x64, 0xbf, 0x15, 0xb3, 0xfc, 0x2e, 0xc8, 0xb0, 0xcc, 0x99, 0xd8, 0x54, 0xfa, 0x32, 0x11, 0xc9, 0x55, 0xc4, 0x55, 0xd7, 0xff, 0x2e, 0x1e, 0xe2, 0x39, 0xf5, 0x4f, 0x38, 0x6a, 0x42, 0xbb, 0x25, 0x40, 0xa8, 0x75, 0x8f, 0x32, 0x97, 0xe5, 0x52, 0xde, 0x1e, 0xbe, 0x8e, 0xac, 0x70, 0xf3, 0x54, 0x87, 0x94, 0x2b, 0xba, 0xda, 0xd5, 0xbd, 0x95, 0x73, 0x90, 0xff, 0x17, 0x93, 0xaf, 0x3d, 0x30, 0xd9, 0x36, 0xb6, 0xf7, 0x9b, 0x44, 0xa9, 0xb6, 0x3c, 0xee, 0x62, 0xd5, 0x58, 0x4d, 0xa3, 0xa1, 0xfc, 0xff, 0xa5, 0xb6, 0xfe, 0xee, 0xc1, 0x1c, 0xd6, 0x3b, 0x18, 0x0f, 0x0b, 0xfc, 0x5b, 0x6b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.16", + /* Message to be signed */ + 135, + { 0xe4, 0x91, 0xa1, 0x56, 0xfd, 0xba, 0x31, 0x6a, 0x2a, 0x20, 0xa1, 0x2e, 0xea, 0x50, 0xbe, 0x77, 0x4e, 0xc9, 0xaa, 0xbe, 0xb1, 0xc3, 0x98, 0xe9, 0x08, 0xbe, 0xa3, 0x29, 0x68, 0x21, 0x7e, 0xa4, 0x1e, 0x96, 0x6d, 0xb7, 0x27, 0x2f, 0x0e, 0xfa, 0x37, 0xc9, 0x0a, 0xe4, 0xe9, 0xf3, 0x86, 0x21, 0xa6, 0x27, 0xa9, 0xd1, 0x2c, 0x8b, 0x4e, 0x80, 0x60, 0xc5, 0x45, 0xc5, 0x60, 0x59, 0xe9, 0xe4, 0x8a, 0x7f, 0x16, 0x81, 0x36, 0x72, 0x47, 0x33, 0x58, 0x19, 0xba, 0x12, 0x7e, 0x65, 0x93, 0x1e, 0x1d, 0x9f, 0xb7, 0x0d, 0xfd, 0xdf, 0x4c, 0x99, 0x56, 0xa5, 0xb0, 0x4c, 0x52, 0xbc, 0xf8, 0xcb, 0xdf, 0xcd, 0xf2, 0x29, 0x19, 0x64, 0xda, 0xfa, 0xca, 0x7e, 0xe7, 0x0e, 0x80, 0xa2, 0x75, 0x9c, 0xec, 0x73, 0x5d, 0x01, 0xac, 0xa8, 0xff, 0x89, 0x4b, 0x68, 0x9b, 0x93, 0x78, 0x3d, 0xa8, 0x93, 0x9c, 0x62, 0x09, 0xdd, 0x68, 0x3c, 0x60 } +, + /* Signature */ + 128, + { 0x9f, 0x20, 0x5b, 0xa9, 0x0d, 0xf2, 0xd4, 0x01, 0x49, 0x26, 0x48, 0x1f, 0x9b, 0x3f, 0x45, 0xa8, 0x9d, 0x23, 0xec, 0xd8, 0x4f, 0x5f, 0x16, 0xe6, 0x73, 0x34, 0xc4, 0xca, 0xf3, 0xf3, 0xb9, 0xc2, 0x01, 0xa7, 0x98, 0xd4, 0xee, 0xc5, 0x62, 0x76, 0x59, 0x88, 0x23, 0x18, 0x0e, 0x07, 0x8d, 0x0a, 0xef, 0x4f, 0x8f, 0xba, 0x0b, 0x25, 0xc1, 0xfd, 0xa3, 0xe3, 0x36, 0x54, 0xc4, 0x74, 0xa9, 0xc1, 0x1a, 0x23, 0xb0, 0x87, 0x10, 0x91, 0x3d, 0xff, 0x76, 0x56, 0xf0, 0xe7, 0xee, 0x22, 0xcc, 0x44, 0xc9, 0x99, 0xc0, 0x95, 0xa6, 0x51, 0x4a, 0x9d, 0x2f, 0xc0, 0xca, 0x4e, 0xf2, 0x08, 0xde, 0x0d, 0x92, 0x93, 0xb0, 0xc5, 0x60, 0x8b, 0xae, 0xd1, 0x07, 0x4a, 0x0c, 0xfd, 0x57, 0xb9, 0x9e, 0xf8, 0xce, 0xab, 0xfd, 0x34, 0x72, 0xb7, 0xdb, 0x3a, 0xb9, 0x60, 0x6d, 0x13, 0xf9, 0xbb, 0x43, 0x9a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.17", + /* Message to be signed */ + 62, + { 0x06, 0xad, 0xd7, 0x5a, 0xb6, 0x89, 0xde, 0x06, 0x77, 0x44, 0xe6, 0x9a, 0x2e, 0xbd, 0x4b, 0x90, 0xfa, 0x93, 0x83, 0x00, 0x3c, 0xd0, 0x5f, 0xf5, 0x36, 0xcb, 0xf2, 0x94, 0xcd, 0x21, 0x5f, 0x09, 0x23, 0xb7, 0xfc, 0x90, 0x04, 0xf0, 0xaa, 0x18, 0x52, 0x71, 0xa1, 0xd0, 0x06, 0x1f, 0xd0, 0xe9, 0x77, 0x7a, 0xd1, 0xec, 0x0c, 0x71, 0x59, 0x1f, 0x57, 0x8b, 0xf7, 0xb8, 0xe5, 0xa1 } +, + /* Signature */ + 128, + { 0x45, 0x14, 0x21, 0x0e, 0x54, 0x1d, 0x5b, 0xad, 0x7d, 0xd6, 0x0a, 0xe5, 0x49, 0xb9, 0x43, 0xac, 0xc4, 0x4f, 0x21, 0x39, 0x0d, 0xf5, 0xb6, 0x13, 0x18, 0x45, 0x5a, 0x17, 0x61, 0x0d, 0xf5, 0xb7, 0x4d, 0x84, 0xae, 0xd2, 0x32, 0xf1, 0x7e, 0x59, 0xd9, 0x1d, 0xd2, 0x65, 0x99, 0x22, 0xf8, 0x12, 0xdb, 0xd4, 0x96, 0x81, 0x69, 0x03, 0x84, 0xb9, 0x54, 0xe9, 0xad, 0xfb, 0x9b, 0x1a, 0x96, 0x8c, 0x0c, 0xbf, 0xf7, 0x63, 0xec, 0xee, 0xd6, 0x27, 0x50, 0xc5, 0x91, 0x64, 0xb5, 0xe0, 0x80, 0xa8, 0xfe, 0xf3, 0xd5, 0x5b, 0xfe, 0x2a, 0xcf, 0xad, 0x27, 0x52, 0xa6, 0xa8, 0x45, 0x9f, 0xa1, 0xfa, 0xb4, 0x9a, 0xd3, 0x78, 0xc6, 0x96, 0x4b, 0x23, 0xee, 0x97, 0xfd, 0x10, 0x34, 0x61, 0x0c, 0x5c, 0xc1, 0x4c, 0x61, 0xe0, 0xeb, 0xfb, 0x17, 0x11, 0xf8, 0xad, 0xe9, 0x6f, 0xe6, 0x55, 0x7b, 0x38 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.18", + /* Message to be signed */ + 78, + { 0x31, 0x1c, 0x88, 0x80, 0x05, 0x35, 0xd1, 0xb4, 0xe9, 0xbc, 0x78, 0x65, 0x18, 0x31, 0xa3, 0xe9, 0x67, 0xe7, 0x4b, 0x58, 0x28, 0xe0, 0x14, 0x11, 0x5f, 0xbe, 0x5f, 0x60, 0x9c, 0xe8, 0x65, 0xfe, 0xd2, 0x41, 0x97, 0x0f, 0x87, 0x2e, 0xc8, 0xf2, 0x3d, 0xc2, 0xbf, 0x61, 0x6b, 0x80, 0x20, 0xe4, 0x45, 0x64, 0xf9, 0x34, 0xdc, 0xbf, 0x72, 0x38, 0x61, 0x70, 0x07, 0x4d, 0x92, 0x0b, 0xa8, 0x95, 0xd3, 0x3d, 0xdf, 0x27, 0x93, 0x69, 0xf2, 0x36, 0xa1, 0x9a, 0xcd, 0x4f, 0xeb, 0x2b } +, + /* Signature */ + 128, + { 0x89, 0x46, 0x63, 0xe6, 0x3e, 0xc1, 0x9f, 0x56, 0x20, 0x3f, 0x4a, 0x44, 0x6b, 0x5e, 0x2b, 0x51, 0x74, 0xc8, 0x14, 0xa5, 0x4c, 0xbe, 0xa2, 0xc8, 0xe2, 0x98, 0xf9, 0x9b, 0x34, 0xc4, 0xbb, 0xc2, 0xc8, 0xb1, 0x77, 0xba, 0x98, 0x57, 0xd8, 0x1c, 0x85, 0x44, 0x36, 0xbd, 0x99, 0xaf, 0x58, 0xc0, 0x9d, 0xde, 0x5a, 0xca, 0xd2, 0xd6, 0x41, 0x50, 0x43, 0xfb, 0x40, 0xe7, 0x84, 0x75, 0xef, 0x74, 0x01, 0x2e, 0x4d, 0x4f, 0x75, 0xb2, 0xe9, 0x58, 0x85, 0xc8, 0x51, 0xa2, 0x3b, 0x4a, 0x25, 0x54, 0x93, 0xf3, 0x0c, 0x17, 0x2e, 0xae, 0x01, 0xd4, 0x79, 0x10, 0xfa, 0xbd, 0x26, 0x9f, 0x57, 0x94, 0x0b, 0xa4, 0x43, 0x50, 0x6c, 0x05, 0x22, 0xbf, 0x72, 0x8a, 0x25, 0x7a, 0xc1, 0x07, 0x3b, 0xdf, 0x99, 0xb4, 0x29, 0x56, 0xdb, 0x00, 0x2a, 0x30, 0xa5, 0x4d, 0xbd, 0xaf, 0x28, 0x4d, 0x8f, 0x69 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.19", + /* Message to be signed */ + 28, + { 0xb2, 0x65, 0xa9, 0x77, 0x7f, 0xaa, 0xf1, 0x58, 0xa8, 0x08, 0xaa, 0xe7, 0x08, 0x5a, 0x83, 0xe7, 0x07, 0x9c, 0xef, 0x80, 0xd5, 0xfc, 0x9d, 0x7c, 0xdc, 0x96, 0x3e, 0xc9 } +, + /* Signature */ + 128, + { 0x28, 0x1e, 0x88, 0xce, 0x19, 0x0e, 0x98, 0x62, 0x90, 0x34, 0x36, 0xa8, 0x6b, 0xa4, 0x37, 0x27, 0x16, 0x44, 0x9c, 0xc0, 0xce, 0x8d, 0x55, 0x4f, 0x70, 0x2d, 0x72, 0x52, 0xa0, 0x67, 0x60, 0xaf, 0x42, 0x12, 0x1d, 0xd0, 0x9b, 0xf6, 0xea, 0x13, 0xf0, 0xeb, 0x25, 0x2e, 0xcc, 0x76, 0x42, 0x10, 0x61, 0xf5, 0x74, 0x4b, 0xd8, 0xe3, 0x2c, 0x5a, 0x8c, 0x4f, 0xc1, 0xf9, 0x52, 0x1b, 0x3f, 0x5c, 0x29, 0x14, 0x6d, 0xd0, 0x59, 0x12, 0x91, 0xac, 0xbd, 0xc5, 0xb6, 0x3b, 0x55, 0x1d, 0x22, 0x8a, 0xe5, 0x38, 0x95, 0xb1, 0x97, 0xe6, 0xe2, 0x7a, 0x70, 0x68, 0xaa, 0x31, 0x03, 0xb7, 0x0c, 0xfb, 0x30, 0xf4, 0x15, 0x84, 0x5c, 0x7e, 0x52, 0x87, 0xf1, 0x11, 0x4e, 0x4c, 0xdf, 0xb4, 0x01, 0xed, 0x51, 0x98, 0x64, 0xcf, 0x61, 0xbc, 0x46, 0x9c, 0x66, 0x69, 0x9b, 0x29, 0x60, 0xa0, 0xaf, 0xf2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 2.20", + /* Message to be signed */ + 102, + { 0x7c, 0x43, 0x9e, 0x7a, 0xb9, 0x90, 0xcd, 0xef, 0x95, 0x6c, 0x42, 0x39, 0x47, 0x9b, 0x49, 0xda, 0x84, 0x2f, 0x8b, 0x76, 0x76, 0x5a, 0x7a, 0xd4, 0x89, 0x7b, 0xc1, 0x6c, 0x61, 0xed, 0x3d, 0x09, 0x80, 0x5d, 0x76, 0xe8, 0xa5, 0xbe, 0x8b, 0x57, 0x8b, 0x95, 0x1f, 0x45, 0x45, 0xdf, 0x92, 0xa8, 0xa5, 0x37, 0xba, 0x3e, 0x2c, 0x13, 0xdc, 0xe0, 0xa0, 0x03, 0xe7, 0xb6, 0x24, 0x9e, 0x32, 0xbe, 0x94, 0x1f, 0x21, 0xcd, 0xa7, 0x25, 0xb8, 0x04, 0x07, 0xbe, 0x1e, 0x28, 0xbb, 0x9e, 0x39, 0x37, 0x38, 0x32, 0x53, 0x56, 0xec, 0x21, 0x74, 0x1d, 0x5c, 0x86, 0xf3, 0xc2, 0xb4, 0xf7, 0xb9, 0x47, 0xaf, 0xd5, 0x6b, 0x2d, 0x3a, 0xec } +, + /* Signature */ + 128, + { 0x6a, 0xfa, 0xd7, 0x7a, 0x05, 0x6d, 0x07, 0x29, 0x05, 0x86, 0xe9, 0x13, 0x80, 0x9a, 0x04, 0x37, 0xd3, 0x9a, 0xb3, 0x07, 0x32, 0x45, 0x12, 0xb2, 0xf5, 0xbc, 0x2b, 0xaf, 0x58, 0x0b, 0xf4, 0x55, 0x43, 0xeb, 0x04, 0xff, 0x83, 0xe9, 0x63, 0xa6, 0xd7, 0xf3, 0x3e, 0x9d, 0xff, 0xc1, 0xfc, 0xf4, 0x24, 0x48, 0xc5, 0xfc, 0xfa, 0x47, 0x27, 0x19, 0xc6, 0x51, 0xf8, 0x1f, 0x3c, 0x62, 0x22, 0x98, 0x3d, 0x38, 0x91, 0x7e, 0x29, 0xb4, 0x84, 0x85, 0x87, 0x9c, 0xeb, 0xb0, 0xa6, 0x1d, 0x38, 0x9e, 0x23, 0x8c, 0x9c, 0x71, 0xc3, 0x68, 0xed, 0xe4, 0x08, 0x3a, 0x94, 0x62, 0x97, 0xf7, 0x19, 0x0b, 0x4c, 0xef, 0x86, 0x7e, 0x9c, 0xcd, 0xa8, 0xf9, 0xff, 0xc6, 0x19, 0x84, 0xfc, 0xf0, 0x5d, 0x4f, 0xba, 0xfe, 0x10, 0x7d, 0xac, 0xf5, 0xb1, 0xdc, 0x8e, 0x2b, 0x14, 0x95, 0xb2, 0x44, 0xf8, 0xe7 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 3: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xb5, 0xd7, 0x07, 0xb7, 0x92, 0xe0, 0x56, 0xf7, 0x2f, 0xd7, 0x6d, 0x8d, 0xa8, 0x89, 0xa5, 0x3c, 0xe4, 0xd8, 0xeb, 0xaa, 0x08, 0x2a, 0xee, 0xb2, 0x30, 0x32, 0xe3, 0xc5, 0xd8, 0xeb, 0xc4, 0xc1, 0x55, 0x61, 0x31, 0x9b, 0xe8, 0xdf, 0xe1, 0x88, 0x99, 0x1a, 0x89, 0x51, 0xd4, 0xb2, 0x3a, 0x51, 0xe8, 0xa9, 0x38, 0x2c, 0x80, 0x5e, 0x4c, 0xfd, 0x49, 0x0e, 0xbb, 0xce, 0xaa, 0x20, 0x80, 0x2a, 0xd6, 0x83, 0xb0, 0x5a, 0x10, 0x0f, 0x29, 0x98, 0x5f, 0x01, 0x1c, 0x3c, 0x8a, 0x44, 0x26, 0x25, 0x52, 0xd8, 0x3d, 0x9a, 0x1b, 0x7c, 0x27, 0x31, 0x5e, 0x14, 0x4a, 0xd8, 0xdf, 0x5c, 0xbe, 0x8b, 0xc6, 0x40, 0x0f, 0xd9, 0xcb, 0xe7, 0x6b, 0x74, 0x21, 0xd7, 0x08, 0xaa, 0x64, 0xf0, 0x40, 0xba, 0xe0, 0x7b, 0x7b, 0xd6, 0xf9, 0x22, 0x18, 0xf9, 0xa7, 0x29, 0x28, 0x4c, 0xc5, 0x98, 0xcd, 0xd1 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x45, 0x17, 0x92, 0xb5, 0x94, 0x47, 0xcc, 0x93, 0x78, 0xa8, 0xa4, 0xd6, 0x45, 0xfb, 0x22, 0xff, 0x4b, 0xbf, 0x06, 0x70, 0x61, 0x51, 0x1a, 0xc8, 0x36, 0xdb, 0x27, 0x43, 0xa6, 0x24, 0x13, 0x6b, 0x18, 0x6b, 0x69, 0x43, 0xa1, 0xcc, 0xeb, 0x6f, 0x91, 0x29, 0x0d, 0x93, 0x3b, 0xbb, 0x8a, 0xc0, 0x53, 0xa4, 0x74, 0x95, 0x28, 0x23, 0x6c, 0xa2, 0x72, 0xcf, 0x77, 0xd9, 0xd3, 0x37, 0xad, 0x2a, 0xb3, 0x6a, 0x87, 0xa9, 0x15, 0x3c, 0x5e, 0x16, 0x71, 0x6e, 0x09, 0xba, 0x0b, 0xea, 0xa6, 0x4b, 0x31, 0x25, 0x26, 0xd4, 0xa8, 0xc2, 0xdc, 0x68, 0xfe, 0x09, 0xe3, 0x7e, 0x50, 0x74, 0xa0, 0x90, 0x9d, 0x3f, 0x04, 0xab, 0x73, 0x90, 0x8a, 0x98, 0x0d, 0xec, 0x1d, 0xa7, 0xeb, 0x45, 0x05, 0xa4, 0x8b, 0xca, 0xd3, 0xb6, 0x0d, 0x01, 0x60, 0x84, 0x58, 0x64, 0xa6, 0x51, 0x1f, 0xf5, 0x59, 0xa7 } +, + /* Prime 1 */ + 64, + { 0xff, 0xa9, 0xf8, 0xe8, 0xb0, 0x82, 0x17, 0x0b, 0x63, 0x73, 0xf0, 0x0d, 0x73, 0xc4, 0x23, 0x86, 0xd4, 0x02, 0xf2, 0x80, 0x8b, 0x39, 0x3b, 0x32, 0xf7, 0x8f, 0x86, 0xea, 0xf6, 0x4b, 0x21, 0xbf, 0xdd, 0x33, 0x4f, 0xb9, 0xaa, 0xd1, 0x6b, 0xa6, 0xd9, 0xda, 0xdb, 0xc8, 0x94, 0x3a, 0x29, 0xe6, 0x63, 0xc8, 0xb3, 0x9c, 0x09, 0x59, 0x69, 0x02, 0x5b, 0xb9, 0xb2, 0xd9, 0xd6, 0xfe, 0x67, 0xb7 } +, + /* Prime 2 */ + 64, + { 0xb6, 0x14, 0x37, 0x8d, 0x5e, 0x3d, 0xa5, 0xa8, 0x0a, 0x6d, 0x73, 0x52, 0xfc, 0x66, 0xa5, 0x64, 0x59, 0x7b, 0x06, 0x8f, 0xc9, 0xd3, 0xaf, 0x5d, 0xb0, 0xe4, 0xe7, 0x35, 0xbe, 0xf8, 0x81, 0xdd, 0x40, 0x17, 0xee, 0x70, 0x82, 0x96, 0x19, 0x0b, 0x6f, 0xdc, 0x84, 0x04, 0xf0, 0x7b, 0xd9, 0xdc, 0x5c, 0xd5, 0xd2, 0xbe, 0x48, 0x86, 0xa7, 0xcb, 0xbc, 0xb2, 0x1d, 0x8c, 0x3d, 0x64, 0xa6, 0xb7 } +, + /* Prime exponent 1 */ + 64, + { 0x51, 0x0e, 0x68, 0x96, 0x0d, 0x70, 0x11, 0x32, 0x51, 0x23, 0xae, 0xd5, 0xf5, 0x00, 0x18, 0x6b, 0x64, 0xc8, 0x52, 0x6e, 0x22, 0xb5, 0xd0, 0x69, 0x06, 0x48, 0x00, 0xf4, 0x79, 0x85, 0xb4, 0x7b, 0x89, 0xfb, 0xfc, 0xa8, 0xd6, 0xd9, 0x72, 0x92, 0x01, 0xbb, 0xfb, 0xb6, 0x8a, 0x18, 0x2e, 0xb4, 0x96, 0xaa, 0x49, 0x17, 0x8d, 0x77, 0x45, 0x6d, 0xb3, 0xfb, 0x1a, 0x13, 0x2a, 0xb0, 0x99, 0xdd } +, + /* Prime exponent 2 */ + 64, + { 0x57, 0xeb, 0xbf, 0x3f, 0x76, 0x48, 0x52, 0x5b, 0xa8, 0x5d, 0x5d, 0x98, 0xae, 0xe4, 0x69, 0xec, 0xe1, 0x00, 0x75, 0x14, 0xad, 0xa2, 0x98, 0x45, 0xa7, 0x8b, 0x80, 0xd2, 0x05, 0x1b, 0x3e, 0xaa, 0x35, 0xae, 0xd8, 0xa6, 0x5f, 0x88, 0x57, 0x23, 0x9c, 0xaa, 0x60, 0xdd, 0x79, 0xba, 0x74, 0x62, 0xe2, 0x39, 0x26, 0x00, 0x58, 0x49, 0x1d, 0x71, 0x55, 0xf6, 0xb4, 0x29, 0xe9, 0xe3, 0x56, 0x55 } +, + /* Coefficient */ + 64, + { 0xee, 0x10, 0x7d, 0xc7, 0xef, 0xec, 0xe9, 0xa6, 0x5c, 0x0e, 0x87, 0x78, 0x9a, 0xf5, 0x59, 0x0c, 0x93, 0x83, 0x9d, 0xfe, 0x82, 0x85, 0x20, 0xda, 0x17, 0x74, 0xff, 0x80, 0xf7, 0xe5, 0x14, 0x55, 0x7f, 0xff, 0x10, 0xbd, 0x8c, 0xae, 0x18, 0x46, 0xef, 0xee, 0x7c, 0x10, 0xd7, 0xa1, 0x2c, 0x4a, 0x05, 0x5c, 0xc1, 0x36, 0xe4, 0xa4, 0xef, 0x25, 0xfd, 0x3e, 0xd9, 0xd0, 0xcd, 0xdf, 0x74, 0xf9 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 3.1", + /* Message to be signed */ + 82, + { 0x98, 0x6e, 0x7c, 0x43, 0xdb, 0xb6, 0x71, 0xbd, 0x41, 0xb9, 0xa7, 0xf4, 0xb6, 0xaf, 0xc8, 0x0e, 0x80, 0x5f, 0x24, 0x23, 0x48, 0x8f, 0xb4, 0x31, 0xf5, 0xee, 0x79, 0x2b, 0x6c, 0x2a, 0xc7, 0xdb, 0x53, 0xcc, 0x42, 0x86, 0x55, 0xae, 0xb3, 0x2d, 0x03, 0xf4, 0xe8, 0x89, 0xc5, 0xc2, 0x5d, 0xe6, 0x83, 0xc4, 0x61, 0xb5, 0x3a, 0xcf, 0x89, 0xf9, 0xf8, 0xd3, 0xaa, 0xbd, 0xf6, 0xb9, 0xf0, 0xc2, 0xa1, 0xde, 0x12, 0xe1, 0x5b, 0x49, 0xed, 0xb3, 0x91, 0x9a, 0x65, 0x2f, 0xe9, 0x49, 0x1c, 0x25, 0xa7, 0xfc } +, + /* Signature */ + 128, + { 0x62, 0x75, 0xe8, 0x73, 0x97, 0xe3, 0x09, 0x2a, 0xab, 0x36, 0x98, 0xbb, 0x1b, 0x5c, 0xf2, 0x4b, 0x8c, 0xd7, 0x71, 0x2b, 0xec, 0xac, 0x35, 0xe3, 0x22, 0x03, 0xd5, 0x43, 0x14, 0xe5, 0x47, 0x0e, 0xa9, 0xaa, 0xbc, 0x86, 0x57, 0xf5, 0x64, 0x34, 0xe5, 0xaf, 0x9f, 0xae, 0x77, 0x8f, 0xf6, 0x04, 0x5c, 0x20, 0xe2, 0xe1, 0xef, 0x7c, 0xbd, 0xf8, 0x8f, 0x00, 0x75, 0xf3, 0x3e, 0xa9, 0x92, 0x77, 0x7c, 0xb7, 0xe9, 0x2f, 0x7d, 0xa1, 0x8a, 0x0f, 0xfd, 0x00, 0xaa, 0x46, 0x71, 0xed, 0x63, 0x91, 0x1f, 0xe9, 0xe9, 0x2f, 0xb4, 0xa7, 0x6e, 0x77, 0xdc, 0x6e, 0x0a, 0x91, 0x65, 0x76, 0x71, 0x6c, 0x15, 0xea, 0xef, 0x08, 0x9a, 0x71, 0xa0, 0xae, 0xa3, 0x5b, 0xed, 0x94, 0x47, 0xa6, 0xc1, 0x7f, 0x2a, 0xad, 0xb7, 0x27, 0xfd, 0x42, 0xf0, 0xac, 0xc8, 0x24, 0x62, 0x38, 0x1d, 0x9f, 0xa2, 0xef } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 3.2", + /* Message to be signed */ + 11, + { 0x4c, 0x7b, 0x98, 0x12, 0x0c, 0x87, 0x50, 0x90, 0x87, 0xc4, 0x78 } +, + /* Signature */ + 128, + { 0x59, 0xe5, 0xcb, 0xe7, 0x33, 0x1b, 0x92, 0xe0, 0xcb, 0x8f, 0x68, 0x9e, 0xae, 0xbb, 0x30, 0xf2, 0xb3, 0x34, 0xa7, 0x46, 0xa6, 0x57, 0x05, 0x59, 0x12, 0xff, 0x1c, 0x92, 0x76, 0x0b, 0x0b, 0x85, 0xbc, 0x42, 0x82, 0xf3, 0x18, 0x4b, 0x9a, 0x81, 0x4f, 0x44, 0x37, 0xf8, 0x25, 0xae, 0x07, 0xd3, 0x56, 0xba, 0xc6, 0x9e, 0x54, 0x0c, 0x90, 0x94, 0x2c, 0x7f, 0x7e, 0x6f, 0xf4, 0x4f, 0xe5, 0x74, 0xf1, 0x21, 0x25, 0x0a, 0xd2, 0x30, 0xf4, 0xb5, 0x0c, 0x78, 0x31, 0x1e, 0x4f, 0xd3, 0xc9, 0xe2, 0x65, 0xf5, 0x17, 0xce, 0x32, 0x97, 0xc3, 0xe1, 0xdd, 0xdb, 0x5c, 0x86, 0x9c, 0x69, 0x8f, 0x44, 0xaf, 0x52, 0x5e, 0x73, 0x64, 0x01, 0xa8, 0x1b, 0x45, 0x9f, 0x19, 0x8a, 0xd1, 0x80, 0x8c, 0xcd, 0x92, 0x9d, 0x49, 0x04, 0x74, 0xca, 0xf7, 0x00, 0x5f, 0x91, 0x0d, 0xac, 0xde, 0x21, 0xb0, 0x77 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.3", + /* Message to be signed */ + 233, + { 0x66, 0xf7, 0x07, 0x54, 0x22, 0xc8, 0xec, 0x42, 0x16, 0xa9, 0xc4, 0xff, 0x49, 0x42, 0x7d, 0x48, 0x3c, 0xae, 0x10, 0xc8, 0x53, 0x4a, 0x41, 0xb2, 0xfd, 0x15, 0xfe, 0xe0, 0x69, 0x60, 0xec, 0x6f, 0xb3, 0xf7, 0xa7, 0xe9, 0x4a, 0x2f, 0x8a, 0x2e, 0x3e, 0x43, 0xdc, 0x4a, 0x40, 0x57, 0x6c, 0x30, 0x97, 0xac, 0x95, 0x3b, 0x1d, 0xe8, 0x6f, 0x0b, 0x4e, 0xd3, 0x6d, 0x64, 0x4f, 0x23, 0xae, 0x14, 0x42, 0x55, 0x29, 0x62, 0x24, 0x64, 0xca, 0x0c, 0xbf, 0x0b, 0x17, 0x41, 0x34, 0x72, 0x38, 0x15, 0x7f, 0xab, 0x59, 0xe4, 0xde, 0x55, 0x24, 0x09, 0x6d, 0x62, 0xba, 0xec, 0x63, 0xac, 0x64, 0x50, 0x32, 0x7e, 0xfe, 0xc6, 0x29, 0x2f, 0x98, 0x01, 0x9f, 0xc6, 0x7a, 0x2a, 0x66, 0x38, 0x56, 0x3e, 0x9b, 0x6e, 0x2d, 0x15, 0xef, 0xd2, 0x37, 0xbb, 0x09, 0x8a, 0x44, 0x3a, 0xee, 0xb2, 0xbf, 0x6c, 0x3f, 0x8c, 0x81, 0xb8, 0xc0, 0x1b, 0x7f, 0xcb, 0x3f, 0xeb, 0xb0, 0xde, 0x3f, 0xc2, 0x5b, 0x65, 0xf5, 0xaf, 0x96, 0xb1, 0xd5, 0xcc, 0x3b, 0x27, 0xd0, 0xc6, 0x05, 0x30, 0x87, 0xb3, 0x96, 0x80, 0xe4, 0x92, 0xa4, 0xab, 0x23, 0x67, 0x47, 0x11, 0x69, 0xe5, 0x28, 0x38, 0x94, 0x5d, 0xba, 0x9d, 0xd7, 0x72, 0x3f, 0x4e, 0x62, 0x4a, 0x05, 0xf7, 0x37, 0x5b, 0x92, 0x7a, 0x87, 0xab, 0xe6, 0xa8, 0x93, 0xa1, 0x65, 0x8f, 0xd4, 0x9f, 0x47, 0xf6, 0xc7, 0xb0, 0xfa, 0x59, 0x6c, 0x65, 0xfa, 0x68, 0xa2, 0x3f, 0x0a, 0xb4, 0x32, 0x96, 0x2d, 0x18, 0xd4, 0x34, 0x3b, 0xd6, 0xfd, 0x67, 0xd0, 0x0b, 0x25, 0xb8, 0x1b, 0x09, 0xb5, 0x62, 0x03, 0x85, 0x64 } +, + /* Signature */ + 128, + { 0x59, 0x9e, 0x69, 0xc1, 0x54, 0xe4, 0xfe, 0x66, 0xb3, 0x6a, 0x69, 0x04, 0x92, 0xfa, 0xeb, 0xb2, 0xbb, 0xe7, 0x34, 0xe0, 0x41, 0x5d, 0x9f, 0x3c, 0xf7, 0xe3, 0x78, 0x28, 0xf5, 0x3e, 0x61, 0x13, 0x04, 0x49, 0x17, 0x3a, 0x33, 0x46, 0x0c, 0x6b, 0x4c, 0x8d, 0xc7, 0xd6, 0x81, 0xca, 0x6f, 0x4d, 0xaf, 0x1c, 0xb8, 0x16, 0xd4, 0x0a, 0xa9, 0x08, 0x2e, 0xe1, 0x93, 0x7b, 0xe4, 0xbc, 0x6a, 0x09, 0xc6, 0xde, 0x79, 0x8c, 0x82, 0x86, 0xfc, 0xd2, 0xa2, 0xb2, 0x19, 0x6c, 0x59, 0x99, 0x4c, 0x93, 0x7f, 0x37, 0x13, 0x07, 0x52, 0x61, 0x2c, 0x6b, 0xff, 0x6d, 0xbb, 0x53, 0xe0, 0x64, 0x7f, 0x88, 0x58, 0xbc, 0x38, 0x38, 0x64, 0x02, 0x1e, 0x6d, 0x56, 0x68, 0x19, 0x20, 0x24, 0x92, 0x97, 0x82, 0x22, 0x46, 0xa0, 0xf5, 0x28, 0xaa, 0xb3, 0xed, 0x18, 0x5e, 0xeb, 0xce, 0x91, 0x9c, 0xf8, 0x3e } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.4", + /* Message to be signed */ + 148, + { 0xd9, 0x34, 0x44, 0x28, 0xfa, 0x8a, 0x58, 0xf8, 0xfa, 0x7b, 0x44, 0x3e, 0x51, 0xfc, 0x9b, 0x51, 0xe3, 0x7a, 0x70, 0x21, 0x0d, 0xb8, 0xbd, 0x1d, 0xe7, 0xf8, 0x67, 0x5d, 0x84, 0x79, 0xff, 0x65, 0x7c, 0xa7, 0x29, 0x55, 0xb2, 0x3c, 0x6f, 0x4a, 0x09, 0x16, 0x37, 0x9a, 0x4e, 0xde, 0xe1, 0xf2, 0x6c, 0x85, 0xe0, 0x52, 0x90, 0x21, 0x1e, 0xeb, 0x25, 0x83, 0x2b, 0x09, 0xcb, 0xe5, 0xea, 0xed, 0x3e, 0x39, 0x65, 0xb0, 0x5a, 0x52, 0xfb, 0x5b, 0x16, 0x49, 0x11, 0x82, 0xc5, 0x91, 0x3c, 0xb1, 0x82, 0x57, 0x48, 0xe8, 0x1a, 0xd0, 0x14, 0xf1, 0x3d, 0x29, 0x6d, 0xc1, 0x69, 0x57, 0x08, 0x2b, 0x1b, 0x83, 0xb4, 0xbe, 0x50, 0xa0, 0xf9, 0x59, 0xc9, 0xe7, 0xf3, 0xaa, 0x80, 0x77, 0x97, 0x2e, 0x2b, 0x93, 0xc2, 0xef, 0xfd, 0x9f, 0x30, 0x86, 0x25, 0xb8, 0xca, 0x7f, 0x54, 0xd7, 0xb6, 0x96, 0x48, 0x79, 0x04, 0x47, 0xac, 0x91, 0xf7, 0x98, 0x5e, 0x51, 0x0d, 0xf7, 0x0d, 0x6e, 0xbc, 0x35, 0x72, 0xc2, 0x05, 0xe6 } +, + /* Signature */ + 128, + { 0x2c, 0x06, 0x01, 0x65, 0xfc, 0xc5, 0x65, 0x5c, 0x06, 0x57, 0xc8, 0xfe, 0x08, 0xe0, 0x5b, 0xdc, 0x8c, 0xd7, 0x7c, 0x1f, 0xec, 0xb6, 0xd1, 0x8b, 0x89, 0x38, 0x11, 0xc9, 0x9d, 0xd0, 0x91, 0xe0, 0xd8, 0x50, 0x6d, 0xcc, 0xb4, 0x9e, 0x33, 0xda, 0xaf, 0xf6, 0xda, 0x96, 0x7b, 0x99, 0xe3, 0x44, 0xcb, 0x17, 0xfa, 0x3c, 0x96, 0x31, 0x29, 0x9b, 0x35, 0x89, 0x81, 0x8b, 0x37, 0xed, 0x9d, 0x5d, 0x78, 0x94, 0xe4, 0xa6, 0x9d, 0xdb, 0x24, 0x83, 0x2e, 0x1a, 0x88, 0x60, 0x01, 0x4e, 0xe5, 0xe5, 0xeb, 0x95, 0x3e, 0x8b, 0x35, 0x48, 0x4b, 0xa4, 0xfe, 0xc9, 0xc3, 0x03, 0x3a, 0xe2, 0xe1, 0x18, 0x9a, 0xf7, 0x94, 0xa7, 0x2e, 0x42, 0x67, 0x21, 0x5b, 0xfe, 0x45, 0x8f, 0x0f, 0xce, 0x6b, 0x37, 0xa5, 0x54, 0x9e, 0xf8, 0x05, 0x43, 0xd0, 0xd4, 0x1a, 0x87, 0xb2, 0xc6, 0xe4, 0xd8, 0x4c, 0xb5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.5", + /* Message to be signed */ + 201, + { 0x8c, 0x67, 0x02, 0xda, 0xaf, 0x58, 0xf6, 0xa4, 0x75, 0xfa, 0xd2, 0xc7, 0xa4, 0xbb, 0x15, 0x6a, 0x57, 0x06, 0x42, 0x55, 0x77, 0xd5, 0xe3, 0x0c, 0x6a, 0x6b, 0xd3, 0x66, 0x9f, 0xd0, 0x30, 0xaf, 0xd7, 0x89, 0xfa, 0xa3, 0xd0, 0x10, 0x18, 0xd4, 0x5d, 0xb2, 0xa0, 0x47, 0xf5, 0x2c, 0xb4, 0xf6, 0x3d, 0xea, 0x36, 0x09, 0x42, 0xaf, 0xe4, 0x76, 0x26, 0x42, 0x06, 0xd9, 0x83, 0xad, 0x38, 0x36, 0xe1, 0x55, 0xc5, 0x6b, 0x2e, 0xcc, 0x08, 0x76, 0x3a, 0xfb, 0x9f, 0xd5, 0x1d, 0x19, 0x99, 0x0e, 0xfc, 0x33, 0x63, 0xf6, 0x57, 0xe2, 0x85, 0xe0, 0x35, 0x21, 0xe8, 0xca, 0xd0, 0x1d, 0x2c, 0x93, 0x5a, 0x18, 0x3a, 0xe2, 0x3f, 0x0e, 0xe8, 0x71, 0x00, 0x86, 0xa8, 0x5b, 0x9f, 0xad, 0x4e, 0x7f, 0x2b, 0x09, 0x45, 0x2e, 0xbc, 0x40, 0x3c, 0xe0, 0xc0, 0xe5, 0x75, 0x5a, 0x7b, 0x2f, 0x33, 0xf4, 0xde, 0xf0, 0xdb, 0x71, 0xc9, 0x79, 0x31, 0xff, 0x90, 0x4a, 0x81, 0x31, 0x99, 0x84, 0xbd, 0xc5, 0x16, 0x6f, 0x6b, 0x92, 0x0c, 0x97, 0xee, 0x74, 0xfb, 0x7e, 0x89, 0x0f, 0x49, 0x0c, 0x90, 0xde, 0x30, 0xca, 0xc9, 0x76, 0xb7, 0x17, 0x23, 0xe2, 0xf8, 0x6e, 0x9d, 0xe1, 0xd5, 0x03, 0xa4, 0x1b, 0xc8, 0x1d, 0x53, 0xcc, 0xbe, 0xf8, 0xac, 0x40, 0x53, 0x57, 0xd9, 0xdf, 0xdf, 0x30, 0x64, 0x66, 0xb4, 0x26, 0x95, 0x80, 0x21, 0x2e, 0x9d, 0x71, 0x32 } +, + /* Signature */ + 128, + { 0x0d, 0x89, 0xfc, 0xf8, 0x44, 0xa9, 0xdc, 0x22, 0x3d, 0x5f, 0x63, 0x8d, 0xcc, 0x3a, 0x59, 0x78, 0x71, 0x6f, 0x26, 0x28, 0xb8, 0xa8, 0x3a, 0xb3, 0x3e, 0x6e, 0x25, 0x5f, 0xf8, 0xaa, 0x01, 0x57, 0x8c, 0x14, 0xe3, 0x89, 0x7d, 0xa4, 0x5a, 0xef, 0xd6, 0x3f, 0xa8, 0x7c, 0xf3, 0x5e, 0x24, 0x4b, 0xf4, 0x82, 0x8e, 0xcd, 0x21, 0x95, 0x0f, 0x30, 0x85, 0xa3, 0x66, 0x21, 0xc9, 0xda, 0x1b, 0xbe, 0x7e, 0xa6, 0x27, 0x31, 0xc6, 0x8d, 0x4d, 0xe0, 0xa3, 0x76, 0xe2, 0x2d, 0xac, 0x2f, 0x54, 0x8c, 0xd4, 0xba, 0x4a, 0x54, 0x2e, 0x71, 0x0f, 0x55, 0xce, 0x85, 0xa9, 0xc1, 0x95, 0x93, 0xc0, 0x8c, 0x87, 0xd2, 0x96, 0xd6, 0x35, 0x87, 0xb3, 0xfe, 0x2c, 0x5d, 0x11, 0x65, 0xee, 0x27, 0x74, 0x4c, 0x75, 0xd8, 0xf4, 0xf1, 0x43, 0x71, 0x63, 0x7c, 0x0c, 0x0a, 0x44, 0x62, 0x76, 0x28, 0x95, 0x83 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.6", + /* Message to be signed */ + 225, + { 0x56, 0xf4, 0xff, 0xd1, 0x27, 0x9d, 0xcf, 0xe5, 0x62, 0xa9, 0xdd, 0xd4, 0x1e, 0xcd, 0xf6, 0x0a, 0x3f, 0xf5, 0x82, 0x46, 0xbf, 0xaf, 0x95, 0x65, 0xcf, 0x67, 0x4b, 0x0b, 0x90, 0x75, 0xf4, 0x0e, 0xea, 0xc0, 0x8f, 0x0b, 0x89, 0x66, 0x61, 0x8a, 0x19, 0x6b, 0x12, 0x28, 0xeb, 0xce, 0x93, 0xfc, 0x9d, 0xd7, 0x9b, 0xd4, 0x63, 0xea, 0x7d, 0x2c, 0x97, 0x4d, 0x2c, 0x2f, 0x53, 0x9e, 0xaf, 0xb1, 0xb2, 0xbc, 0x1e, 0xa3, 0x4d, 0x74, 0xf7, 0x20, 0xe1, 0x19, 0x34, 0x2f, 0xf7, 0x13, 0x12, 0x25, 0xaa, 0x9a, 0xda, 0x89, 0x4b, 0x76, 0xb2, 0xec, 0xb1, 0x2f, 0x2f, 0x40, 0x28, 0x44, 0xb4, 0x42, 0x5c, 0xf8, 0xf1, 0xa3, 0x9b, 0x0a, 0x9c, 0x83, 0xb4, 0x5b, 0x03, 0xcf, 0xc0, 0xd1, 0x5f, 0xd3, 0x14, 0xd6, 0xab, 0xf5, 0x32, 0xb8, 0xed, 0xfc, 0xf2, 0x36, 0x51, 0x4b, 0x2e, 0x45, 0x86, 0x97, 0x86, 0xfe, 0xfe, 0x27, 0xf5, 0x4d, 0x66, 0x6e, 0xe5, 0x24, 0xe4, 0xb9, 0xc0, 0x53, 0xbe, 0x39, 0x75, 0x01, 0x58, 0x29, 0x91, 0xfa, 0x2d, 0x80, 0x2c, 0x7d, 0x1b, 0x17, 0x8b, 0x23, 0xe9, 0xb6, 0xec, 0xe6, 0xfd, 0x2e, 0xf0, 0x13, 0x2c, 0x06, 0x01, 0xa8, 0x6f, 0x07, 0x68, 0xba, 0xdc, 0x59, 0xc5, 0xcc, 0x33, 0xf2, 0x4d, 0xed, 0x55, 0x4a, 0xe5, 0x1a, 0xe3, 0xec, 0x23, 0xf9, 0xdd, 0x08, 0x9e, 0x32, 0x4a, 0x68, 0x21, 0xf6, 0x15, 0x7f, 0x12, 0x84, 0x42, 0xac, 0x58, 0x07, 0x65, 0x8a, 0xd3, 0x40, 0x26, 0xb8, 0xfc, 0xfd, 0xa6, 0xdc, 0x7f, 0x02, 0xa9, 0x3c, 0x16, 0x6e, 0xc9, 0x45, 0xee } +, + /* Signature */ + 128, + { 0x0d, 0xeb, 0x39, 0x7b, 0xf2, 0xcf, 0xf9, 0x79, 0xd4, 0x71, 0x9c, 0x64, 0x8b, 0x0a, 0x35, 0x25, 0x35, 0x1f, 0x5e, 0x08, 0x40, 0x5c, 0xa2, 0x61, 0x4a, 0x83, 0xe5, 0x6a, 0xce, 0x86, 0xf5, 0x52, 0xe4, 0x1b, 0xb9, 0x28, 0xde, 0x50, 0xf0, 0xbc, 0x0f, 0xe3, 0x1a, 0x2e, 0xf2, 0xad, 0x79, 0x9f, 0xd3, 0xcf, 0x47, 0x42, 0xb1, 0x13, 0x1a, 0x37, 0xbd, 0x08, 0xf2, 0xa1, 0x3c, 0xac, 0xda, 0x67, 0xf4, 0x95, 0xc9, 0xf1, 0xa9, 0xef, 0x64, 0x85, 0x70, 0x72, 0x32, 0x9f, 0x00, 0xcc, 0x4c, 0x01, 0x22, 0x35, 0x59, 0x9a, 0x83, 0xfc, 0x45, 0x94, 0xfe, 0xd9, 0x23, 0x03, 0x49, 0x01, 0xed, 0xc2, 0x7d, 0x5f, 0x05, 0x79, 0x98, 0x34, 0x93, 0x5c, 0xab, 0xe2, 0x64, 0xff, 0xc1, 0x96, 0x63, 0x71, 0x4d, 0x8c, 0x3d, 0xe8, 0xe9, 0x61, 0x9f, 0xd2, 0x84, 0x2d, 0x22, 0x98, 0xf7, 0xa7, 0x2c, 0x99 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.7", + /* Message to be signed */ + 179, + { 0x0e, 0x79, 0xac, 0x9c, 0x9c, 0x03, 0x96, 0xd9, 0x69, 0xfb, 0x3f, 0x7c, 0xc9, 0x94, 0x7b, 0x07, 0x8b, 0xac, 0x49, 0x3b, 0x03, 0x52, 0xc8, 0xe0, 0xcd, 0xe5, 0x46, 0x3e, 0xa5, 0xc1, 0x18, 0x4f, 0xd5, 0x2a, 0x1f, 0xb7, 0x48, 0x19, 0x3c, 0x14, 0x7a, 0x74, 0x80, 0x0d, 0x24, 0xf7, 0x51, 0xba, 0x93, 0x5e, 0x19, 0xc9, 0x11, 0x5e, 0xdf, 0x07, 0x22, 0x88, 0x33, 0x0b, 0xf3, 0x83, 0xf4, 0x95, 0x29, 0x6b, 0xe1, 0xaa, 0x4a, 0x50, 0x95, 0xb9, 0x57, 0x3b, 0xcb, 0xdb, 0x22, 0x8a, 0x43, 0x13, 0x12, 0x37, 0x86, 0x5d, 0x26, 0xdf, 0xbf, 0xcf, 0xef, 0x07, 0x8f, 0x35, 0x9f, 0x9a, 0x95, 0x62, 0xe2, 0x5b, 0x69, 0x63, 0x85, 0xe1, 0x28, 0x13, 0xff, 0xfb, 0xc8, 0xd5, 0x29, 0x81, 0x9a, 0x91, 0x45, 0x1d, 0x33, 0xa5, 0x07, 0x26, 0x39, 0x2e, 0x4f, 0xef, 0x29, 0x41, 0x8c, 0xca, 0x2c, 0x73, 0xa0, 0x68, 0xe6, 0x0e, 0xae, 0x31, 0x84, 0x70, 0x33, 0x1a, 0x0f, 0x1d, 0xb4, 0xbb, 0xb6, 0x37, 0x17, 0x3b, 0xe8, 0x0f, 0xea, 0x03, 0xc8, 0x2c, 0x15, 0xd0, 0x01, 0x93, 0x36, 0x2d, 0x3a, 0x18, 0xad, 0x9e, 0x2f, 0x68, 0x05, 0x00, 0xd7, 0x26, 0x5b, 0x15, 0x57, 0x03, 0x3a, 0x52, 0x09, 0x77, 0xd8, 0x10, 0xfc } +, + /* Signature */ + 128, + { 0x73, 0x3b, 0x7f, 0xea, 0x12, 0x0c, 0xa5, 0xf0, 0x35, 0x9a, 0x89, 0x05, 0x75, 0x0c, 0x49, 0xc3, 0x63, 0xd8, 0x84, 0xf5, 0x6c, 0x2b, 0x7a, 0x72, 0x9f, 0xad, 0x7b, 0xff, 0x44, 0x5a, 0x1e, 0x54, 0x79, 0x89, 0x41, 0x74, 0x53, 0x93, 0xe1, 0x76, 0x77, 0x12, 0xac, 0x4b, 0x9d, 0xd2, 0x68, 0x38, 0x88, 0xd9, 0xe6, 0x8b, 0x90, 0x5d, 0xba, 0xb8, 0x79, 0x21, 0x85, 0x18, 0x48, 0x72, 0x73, 0x86, 0x02, 0xea, 0xf4, 0xa8, 0x0f, 0x45, 0x95, 0xf7, 0x8f, 0xd4, 0xa4, 0x61, 0x0b, 0xf8, 0x22, 0x0b, 0x86, 0xa2, 0x88, 0x5f, 0xda, 0x24, 0xe1, 0x99, 0x64, 0x28, 0xcc, 0xd1, 0x5f, 0x20, 0x08, 0xe0, 0x68, 0x51, 0xb2, 0xee, 0xad, 0xc3, 0xdc, 0x8e, 0x03, 0x01, 0x2f, 0x9b, 0xdb, 0x3c, 0xe0, 0x57, 0x5d, 0xdc, 0x3a, 0xdc, 0x7c, 0x59, 0x08, 0x49, 0x8b, 0x69, 0xa7, 0x97, 0xba, 0x58, 0x29, 0xc7 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.8", + /* Message to be signed */ + 29, + { 0x22, 0xeb, 0x7d, 0xba, 0x73, 0x30, 0x7c, 0x7c, 0x52, 0xa0, 0x7c, 0xed, 0x89, 0xdb, 0x8b, 0xc5, 0x39, 0x4a, 0xed, 0x22, 0x72, 0xf7, 0xe8, 0x1a, 0x74, 0xf4, 0xc0, 0x2d, 0x14 } +, + /* Signature */ + 128, + { 0x9e, 0xa4, 0x60, 0x0a, 0x1a, 0x65, 0x49, 0xfd, 0x39, 0x75, 0xf6, 0x49, 0x8a, 0x04, 0xd6, 0x9f, 0x96, 0xfa, 0xd0, 0xe8, 0xe6, 0xfe, 0xbc, 0xfb, 0xe0, 0x1c, 0x2f, 0x83, 0x17, 0x0b, 0xc7, 0x4e, 0xb9, 0x1f, 0x2e, 0x33, 0x53, 0x38, 0xd5, 0x83, 0xe8, 0x85, 0xaa, 0xc6, 0x14, 0x24, 0xc9, 0xb2, 0x66, 0xc3, 0xd2, 0xd9, 0x8e, 0x79, 0x77, 0xff, 0xe4, 0x95, 0xf9, 0xc1, 0xa6, 0xee, 0x5e, 0xf4, 0x1a, 0x4c, 0xc7, 0x47, 0x8c, 0x24, 0xb3, 0x16, 0xc7, 0xd9, 0xf6, 0xdb, 0xaa, 0x65, 0xa4, 0xca, 0xde, 0xf1, 0x81, 0xca, 0x94, 0x6f, 0x9b, 0x92, 0x18, 0x4f, 0xae, 0xca, 0x8a, 0x13, 0x16, 0xae, 0xab, 0x5c, 0xd3, 0x87, 0x8c, 0x6d, 0xf0, 0x74, 0xf9, 0x06, 0x0b, 0x9d, 0xb6, 0x6d, 0xec, 0xe9, 0xa9, 0x36, 0x7d, 0x75, 0x49, 0x03, 0x5a, 0xc6, 0xbf, 0x19, 0x62, 0x36, 0x5e, 0x1f, 0xd3, 0xfc } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.9", + /* Message to be signed */ + 2, + { 0xf6, 0x80 } +, + /* Signature */ + 128, + { 0x51, 0x63, 0x90, 0x61, 0xfa, 0x7b, 0x7c, 0xd5, 0xdf, 0x64, 0xb3, 0x0a, 0x39, 0x4c, 0xcf, 0x7e, 0x24, 0x26, 0x97, 0x2a, 0xa1, 0xdc, 0xf5, 0xd4, 0x5e, 0xb8, 0xec, 0x2c, 0xd9, 0x0b, 0x9b, 0x19, 0x68, 0x92, 0xbe, 0x5f, 0xa0, 0x3c, 0x43, 0xf3, 0xc3, 0x72, 0x3a, 0xe3, 0x13, 0x0d, 0x61, 0x51, 0xb3, 0x3a, 0x63, 0x7c, 0xfc, 0x50, 0xba, 0x35, 0x26, 0xa7, 0x39, 0x6c, 0xf8, 0x47, 0x9c, 0x50, 0x8c, 0x18, 0x11, 0x81, 0x0d, 0x68, 0xb3, 0x88, 0x0a, 0xf6, 0xe6, 0x4b, 0x16, 0xbd, 0x70, 0x79, 0xbe, 0x9c, 0x00, 0x39, 0x29, 0x51, 0x22, 0x61, 0x89, 0x8f, 0xa5, 0x7c, 0x06, 0xff, 0x7e, 0x1d, 0x80, 0x39, 0xfa, 0x99, 0x3f, 0xd2, 0x05, 0x6a, 0xc7, 0x01, 0x9b, 0x8d, 0xbc, 0xf2, 0x53, 0x0d, 0x53, 0x80, 0xe6, 0x01, 0xa4, 0xa1, 0x87, 0x1b, 0x86, 0xc2, 0x0b, 0xc1, 0xc4, 0x89, 0xc5, 0xf3 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.10", + /* Message to be signed */ + 104, + { 0x65, 0x0e, 0x64, 0xed, 0x1d, 0xa8, 0x8b, 0xcf, 0x8a, 0xe2, 0x75, 0x22, 0xbe, 0x1d, 0x5c, 0x99, 0x19, 0xf2, 0x09, 0x9d, 0xd6, 0x32, 0x45, 0x5f, 0x66, 0xd9, 0xaf, 0xe8, 0xba, 0xf4, 0x6c, 0xc8, 0xa1, 0x98, 0x40, 0x9b, 0x09, 0x28, 0xdd, 0x87, 0x22, 0x62, 0x84, 0xd6, 0x69, 0xbf, 0x01, 0xbc, 0xec, 0x44, 0x37, 0x6c, 0xb0, 0xe9, 0xbd, 0xc6, 0x86, 0xac, 0xaa, 0x8b, 0x46, 0x34, 0x86, 0x08, 0x59, 0x94, 0xca, 0xfb, 0x5a, 0x8c, 0xfc, 0x33, 0xd4, 0x9c, 0xee, 0xf4, 0x79, 0xfc, 0x6e, 0x04, 0xf8, 0xee, 0xf6, 0x37, 0xeb, 0x68, 0xcb, 0x57, 0x81, 0x8d, 0x5f, 0x97, 0x70, 0xac, 0x52, 0x3e, 0xd5, 0xb0, 0x16, 0x38, 0x36, 0x7f, 0xf4, 0x7f } +, + /* Signature */ + 128, + { 0x50, 0x3e, 0x05, 0x66, 0x1d, 0x68, 0x1e, 0xca, 0x57, 0x4e, 0x02, 0x30, 0xaf, 0x2d, 0xaa, 0x87, 0x7b, 0x90, 0x51, 0x6e, 0x5e, 0x19, 0x72, 0x8c, 0x91, 0x76, 0x8d, 0x6e, 0xef, 0xee, 0x00, 0x1b, 0x35, 0x41, 0x9c, 0x5f, 0xcb, 0x56, 0x11, 0xd6, 0x0e, 0x7e, 0xcb, 0xe3, 0xc9, 0x5e, 0x5c, 0x88, 0xba, 0x93, 0x46, 0x07, 0x04, 0xf1, 0x69, 0x4a, 0xe8, 0x04, 0x44, 0xeb, 0x97, 0x18, 0xa0, 0x8b, 0x66, 0x86, 0xfa, 0xd8, 0x6e, 0x52, 0x59, 0x90, 0xc3, 0xc1, 0xa6, 0x6c, 0x8c, 0x53, 0xaa, 0x31, 0xae, 0xd8, 0xcb, 0xc4, 0x0f, 0xd5, 0x4f, 0x5f, 0xf8, 0xa1, 0x34, 0x74, 0x9d, 0x79, 0xd3, 0x8f, 0xbb, 0x0d, 0x58, 0x44, 0x26, 0x78, 0xff, 0x2f, 0x70, 0xc6, 0xc5, 0x0f, 0x25, 0x47, 0x2a, 0x72, 0xd6, 0x32, 0x05, 0xe7, 0x82, 0x42, 0x3d, 0xf4, 0x0b, 0x6c, 0x43, 0xde, 0x03, 0xa1, 0x8f, 0x8b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.11", + /* Message to be signed */ + 50, + { 0x57, 0xf8, 0xac, 0x6a, 0x9e, 0x46, 0x8b, 0x7f, 0x1f, 0x74, 0x5d, 0xff, 0xe3, 0x9e, 0x9c, 0xbf, 0x90, 0x24, 0xa0, 0xff, 0x36, 0xe0, 0x22, 0x83, 0x92, 0xbe, 0x6b, 0x29, 0x94, 0x29, 0x17, 0x76, 0xb8, 0x9c, 0x0a, 0x4b, 0x1f, 0xa8, 0x6b, 0x2e, 0xc8, 0xbb, 0x7c, 0x3e, 0x64, 0xf5, 0x58, 0x5a, 0xfa, 0x77 } +, + /* Signature */ + 128, + { 0x90, 0xbe, 0x16, 0xb4, 0x08, 0xb3, 0x85, 0x73, 0x95, 0x39, 0xb3, 0xb9, 0xa2, 0x9b, 0x94, 0xc7, 0x29, 0x38, 0x5f, 0x79, 0xdd, 0x4a, 0x79, 0x81, 0x1e, 0x6f, 0x67, 0xc8, 0x0e, 0xd3, 0x59, 0xe5, 0xf4, 0xb2, 0xa1, 0x9c, 0x22, 0x2a, 0x82, 0xb3, 0xd6, 0xd6, 0x2a, 0x90, 0x3f, 0xb1, 0x80, 0xc1, 0xf4, 0x3c, 0xb3, 0xfe, 0x06, 0xa2, 0x50, 0xbc, 0xb0, 0xe7, 0xc6, 0x88, 0x66, 0x5c, 0x83, 0x68, 0xa1, 0x1a, 0xb1, 0x16, 0x0a, 0xdb, 0x74, 0x02, 0x91, 0x35, 0x2b, 0x38, 0x38, 0xb6, 0x92, 0x3a, 0x4a, 0x37, 0xad, 0x06, 0x04, 0x0a, 0x53, 0x59, 0x20, 0xdc, 0x0f, 0x10, 0x57, 0x9e, 0xcf, 0x48, 0x1c, 0xd4, 0x41, 0x37, 0x17, 0xd7, 0xd4, 0xd9, 0x60, 0xaa, 0x75, 0x1a, 0x74, 0x3e, 0x2f, 0x7c, 0x61, 0x6e, 0x54, 0x2e, 0xe6, 0x5f, 0xbb, 0xfe, 0x24, 0x66, 0x0e, 0x10, 0x1d, 0xaa, 0x2b, 0xdd } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.12", + /* Message to be signed */ + 77, + { 0x80, 0xef, 0x01, 0xaa, 0xcc, 0x5b, 0xfb, 0x0d, 0xb4, 0x8c, 0x6d, 0xe3, 0xd8, 0x14, 0x95, 0xb9, 0xc2, 0x31, 0x1a, 0x38, 0x93, 0x89, 0xf2, 0x3b, 0x70, 0xc0, 0x24, 0xda, 0x44, 0x78, 0xbf, 0xab, 0x2b, 0xfe, 0x4e, 0x54, 0x6f, 0x13, 0xff, 0xfd, 0xb9, 0x63, 0x89, 0x4e, 0xc6, 0xda, 0xdb, 0x3d, 0x2b, 0x0e, 0xe3, 0x37, 0xf1, 0x16, 0x31, 0x05, 0x8e, 0xac, 0x86, 0x09, 0xe5, 0xa1, 0x55, 0x4a, 0xf7, 0x97, 0xa9, 0xf9, 0xab, 0x47, 0x8c, 0x2d, 0x5b, 0x91, 0x88, 0xc8, 0x25 } +, + /* Signature */ + 128, + { 0x44, 0xc3, 0xf5, 0x1d, 0xcc, 0x6f, 0xb2, 0xb4, 0xe7, 0x0f, 0x53, 0x7f, 0x54, 0x64, 0xc6, 0x32, 0x0a, 0xd4, 0x2e, 0x21, 0x28, 0xfa, 0xdf, 0xd9, 0xa7, 0xe9, 0x37, 0xcd, 0x65, 0xdc, 0xbf, 0x35, 0xac, 0x66, 0xcf, 0xfa, 0xfd, 0x39, 0x28, 0x39, 0x66, 0xf2, 0xf1, 0x5d, 0xe5, 0x27, 0x72, 0x35, 0x50, 0x71, 0x5a, 0x31, 0x04, 0x29, 0x45, 0xe2, 0x00, 0xcc, 0x5c, 0x86, 0xfa, 0xba, 0x5e, 0xc8, 0xab, 0xaf, 0x50, 0x9c, 0x0c, 0xcd, 0x64, 0xd9, 0x9d, 0xed, 0xc7, 0x6e, 0x3c, 0xea, 0xa8, 0xc4, 0x47, 0x17, 0x93, 0x37, 0xf4, 0xa0, 0x77, 0x7b, 0x11, 0x52, 0x6e, 0x47, 0x2a, 0xcd, 0x41, 0x3b, 0x4a, 0xc7, 0xc3, 0x03, 0xcd, 0xcd, 0x84, 0xca, 0xfc, 0x02, 0x52, 0x43, 0xef, 0x00, 0x6f, 0x79, 0xdd, 0xaf, 0x55, 0xc1, 0x5c, 0xc4, 0xa8, 0xf1, 0x5e, 0xa2, 0xc8, 0x7f, 0x05, 0x77, 0x38, 0x14 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.13", + /* Message to be signed */ + 184, + { 0xac, 0x17, 0x95, 0x91, 0x55, 0x28, 0x3b, 0x0c, 0x7c, 0xff, 0x51, 0x5c, 0x33, 0x15, 0xd8, 0x9b, 0xdf, 0xe9, 0x58, 0x7c, 0xc0, 0x01, 0x20, 0xd3, 0xab, 0x31, 0xbb, 0x76, 0x07, 0xbd, 0xb3, 0x01, 0xca, 0xea, 0xf5, 0xe1, 0x5f, 0x5a, 0x6f, 0x58, 0xc9, 0xc5, 0x68, 0xff, 0xb3, 0xd2, 0x34, 0x02, 0x51, 0x6f, 0xfe, 0x23, 0x0c, 0x69, 0x81, 0xa8, 0x1c, 0x17, 0x8a, 0x8a, 0x18, 0xca, 0x33, 0x0b, 0xb8, 0xec, 0xaf, 0xb4, 0x81, 0xb2, 0x49, 0xb4, 0x66, 0xa8, 0xcf, 0x78, 0xb7, 0x0d, 0x9e, 0x78, 0xa1, 0x39, 0xa8, 0x8f, 0x48, 0x4c, 0xce, 0x7c, 0x20, 0x35, 0xb2, 0xe8, 0x9d, 0x49, 0x3b, 0xde, 0x88, 0x5e, 0x1c, 0xde, 0x42, 0xcb, 0x1a, 0x94, 0x49, 0xff, 0x57, 0x0d, 0xcf, 0x9e, 0x33, 0xc5, 0xcc, 0x77, 0xb2, 0x59, 0xbe, 0xe2, 0x83, 0x05, 0x39, 0x68, 0x02, 0xed, 0xc1, 0x6f, 0xc5, 0xa8, 0xe1, 0x0b, 0x56, 0xda, 0x2d, 0xa7, 0x86, 0xb5, 0xfb, 0x6c, 0x81, 0x2b, 0x2e, 0x17, 0x5b, 0x69, 0x6b, 0x1a, 0x9a, 0x96, 0xfc, 0x72, 0x2a, 0x43, 0x21, 0x46, 0x45, 0x0f, 0x07, 0xa6, 0x48, 0xef, 0x3c, 0xcf, 0x99, 0x6e, 0xf3, 0x08, 0x1f, 0xa5, 0xbb, 0x42, 0x21, 0xc9, 0x13, 0xba, 0x22, 0x28, 0x97, 0x0c, 0x9b, 0x0e, 0xa5, 0x26, 0x6b, 0xff } +, + /* Signature */ + 128, + { 0x48, 0x45, 0x8c, 0x72, 0xf0, 0x67, 0xdd, 0x9a, 0xb7, 0x20, 0xef, 0x16, 0x0c, 0xf3, 0x18, 0x4b, 0xb9, 0x80, 0x1e, 0x26, 0xd6, 0x14, 0xa8, 0x89, 0xa8, 0x35, 0x84, 0x41, 0x07, 0xac, 0x01, 0x65, 0x0b, 0x11, 0x84, 0xa0, 0x0b, 0xca, 0xa7, 0xaf, 0x1f, 0xf7, 0xde, 0x3a, 0x2e, 0xf2, 0xe7, 0xce, 0xb5, 0xb2, 0x5c, 0x3b, 0x5d, 0x5b, 0xcb, 0x29, 0x86, 0x59, 0x34, 0x32, 0x47, 0x48, 0xc6, 0x8f, 0x07, 0xde, 0x17, 0x4e, 0x17, 0x80, 0xa7, 0x0f, 0xa2, 0x4d, 0x6a, 0x3a, 0x9f, 0x7a, 0x41, 0xb8, 0x19, 0x37, 0xc4, 0x98, 0x4b, 0x2c, 0xbe, 0x06, 0xb3, 0xd7, 0xb4, 0x4c, 0xda, 0xe9, 0xcb, 0xd4, 0x16, 0x32, 0xd0, 0x09, 0x43, 0xc3, 0xb5, 0x73, 0xb1, 0xaa, 0x29, 0x12, 0x75, 0x0a, 0x9a, 0xeb, 0x07, 0xf1, 0x10, 0x13, 0x0b, 0xa3, 0x61, 0xdc, 0xf8, 0xf5, 0x36, 0x79, 0x0d, 0x60, 0x78, 0x47 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.14", + /* Message to be signed */ + 232, + { 0x99, 0x09, 0x8f, 0x77, 0xf6, 0xed, 0x35, 0xc0, 0x8f, 0xab, 0x3f, 0xa9, 0x78, 0x86, 0x93, 0x67, 0x1a, 0x58, 0x00, 0xdc, 0x30, 0x3c, 0x9c, 0xce, 0x42, 0x46, 0x16, 0xfa, 0x0c, 0x7e, 0xe8, 0x88, 0x86, 0x87, 0x67, 0x4c, 0xa8, 0x8a, 0xb2, 0x2a, 0x5f, 0xf2, 0xd1, 0x2e, 0x2b, 0x38, 0x8b, 0x09, 0x4f, 0xfd, 0x7d, 0xbf, 0x9a, 0x09, 0x27, 0xa9, 0x62, 0x17, 0x17, 0x15, 0x1e, 0x08, 0xec, 0xb8, 0xad, 0xe1, 0x55, 0x9f, 0x4b, 0x48, 0xe2, 0x3d, 0x31, 0xcf, 0x57, 0xcd, 0x38, 0x84, 0xdf, 0xe2, 0xb3, 0xe4, 0xb2, 0x60, 0xe8, 0x96, 0x02, 0x94, 0x07, 0x96, 0x94, 0x96, 0x02, 0x6c, 0x74, 0xa2, 0x18, 0x90, 0xd9, 0xa9, 0xaf, 0xd2, 0xcb, 0xb8, 0xf2, 0x83, 0x0a, 0x56, 0x6a, 0xed, 0x24, 0xf0, 0x16, 0x19, 0x74, 0x01, 0xa8, 0xcd, 0x22, 0xc8, 0x2f, 0xb8, 0xb2, 0x28, 0x91, 0x84, 0x58, 0x24, 0x0a, 0x23, 0xd1, 0x01, 0x85, 0xeb, 0xe7, 0x72, 0xdc, 0x19, 0xbc, 0xfe, 0x3e, 0x44, 0x92, 0x2f, 0xe7, 0x32, 0x09, 0xc1, 0xee, 0x00, 0x40, 0x07, 0x9f, 0xb0, 0x3b, 0x82, 0x7c, 0x82, 0x17, 0xd9, 0xed, 0x7c, 0x98, 0xc9, 0x5f, 0x30, 0x97, 0x4f, 0xbe, 0x4f, 0xbd, 0xdc, 0xf0, 0xf2, 0x8d, 0x60, 0x21, 0xc0, 0xe9, 0x1d, 0xa6, 0x0c, 0xa2, 0xad, 0x77, 0x79, 0x7e, 0xce, 0x86, 0xde, 0x5b, 0xf7, 0x68, 0x75, 0x0d, 0xdb, 0x5e, 0xd6, 0xa3, 0x11, 0x6a, 0xd9, 0x9b, 0xbd, 0x17, 0xed, 0xf7, 0xf7, 0x82, 0xf0, 0xdb, 0x1c, 0xd0, 0x5b, 0x0f, 0x67, 0x74, 0x68, 0xc5, 0xea, 0x42, 0x0d, 0xc1, 0x16, 0xb1, 0x0e, 0x80, 0xd1, 0x10, 0xde, 0x2b, 0x04 } +, + /* Signature */ + 128, + { 0xb4, 0x6a, 0xe8, 0x66, 0x13, 0x91, 0x89, 0xb6, 0xb1, 0x71, 0xa7, 0x62, 0x05, 0xfb, 0x9c, 0xe0, 0x41, 0xb4, 0x02, 0x98, 0xe5, 0xba, 0x92, 0xc2, 0xe9, 0xcc, 0x0b, 0xbf, 0xbb, 0x4a, 0x76, 0x42, 0x5d, 0xe6, 0xce, 0x13, 0x02, 0x1a, 0xe1, 0xa4, 0xa9, 0x42, 0x29, 0x9f, 0x98, 0xff, 0x89, 0xf5, 0x52, 0xf4, 0x3a, 0x90, 0x73, 0xde, 0x64, 0xf4, 0x9c, 0x2c, 0xa3, 0x62, 0x0d, 0x09, 0xd7, 0xe6, 0xe3, 0xfe, 0x28, 0x22, 0x1e, 0x93, 0x68, 0x98, 0x7e, 0x11, 0x0c, 0xd6, 0x06, 0x71, 0x06, 0xc4, 0xdb, 0x31, 0xa0, 0x38, 0x90, 0x23, 0x67, 0x96, 0xc8, 0x42, 0x52, 0xf5, 0x6c, 0x95, 0x03, 0x4a, 0x01, 0xc5, 0xfe, 0x98, 0x1e, 0x81, 0xb6, 0x54, 0x85, 0x5a, 0xaf, 0x27, 0x47, 0x50, 0x11, 0x55, 0x72, 0x0c, 0x21, 0x93, 0xf3, 0xa1, 0xd1, 0x0f, 0x49, 0xfe, 0xe9, 0x0c, 0x52, 0xfe, 0xe9, 0xe4 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.15", + /* Message to be signed */ + 33, + { 0xff, 0x79, 0x06, 0x42, 0x30, 0x5b, 0xf3, 0x02, 0x00, 0x38, 0x92, 0xe5, 0x4d, 0xf9, 0xf6, 0x67, 0x50, 0x9d, 0xc5, 0x39, 0x20, 0xdf, 0x58, 0x3f, 0x50, 0xa3, 0xdd, 0x61, 0xab, 0xb6, 0xfa, 0xb7, 0x5d } +, + /* Signature */ + 128, + { 0x07, 0x56, 0x32, 0x47, 0x73, 0x4f, 0x3c, 0x3d, 0x7a, 0x31, 0x02, 0xbc, 0xb4, 0x5b, 0xb5, 0x68, 0x15, 0x68, 0xed, 0x10, 0xf2, 0xec, 0x45, 0x9e, 0x46, 0x9e, 0x1a, 0x9e, 0x34, 0x09, 0xa1, 0x39, 0xfb, 0x15, 0x1b, 0x98, 0xd3, 0xf3, 0xb6, 0x2d, 0xaa, 0xac, 0x8b, 0x8f, 0x89, 0x16, 0xdf, 0x85, 0xd6, 0xdf, 0xa9, 0xab, 0x76, 0x0d, 0xf1, 0xe1, 0x5a, 0xc8, 0x90, 0x44, 0xe5, 0x79, 0xcf, 0x47, 0xa1, 0xaf, 0x6c, 0xd6, 0xec, 0x70, 0x4c, 0xed, 0x9b, 0x03, 0x4c, 0x6a, 0xaa, 0x90, 0xd0, 0xe7, 0x0e, 0x08, 0x52, 0x14, 0x0e, 0x75, 0x41, 0xf2, 0xef, 0xbe, 0x2c, 0xf1, 0x90, 0xb9, 0x58, 0x94, 0x1e, 0xc8, 0xb5, 0x97, 0x4f, 0x9c, 0x44, 0x4d, 0x26, 0xc3, 0x43, 0x16, 0xc9, 0x21, 0x6b, 0x65, 0x95, 0xe6, 0x56, 0xbc, 0x6c, 0x78, 0x44, 0xfa, 0xc1, 0x6c, 0x51, 0x52, 0x60, 0x92, 0x8e, 0x78 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.16", + /* Message to be signed */ + 91, + { 0xe9, 0x9f, 0xcb, 0xf8, 0x59, 0x2d, 0xbe, 0x2d, 0x7e, 0x27, 0x45, 0x3c, 0xb4, 0x4d, 0xe0, 0x71, 0x00, 0xeb, 0xb1, 0xa2, 0xa1, 0x98, 0x11, 0xa4, 0x78, 0xad, 0xbe, 0xab, 0x27, 0x0f, 0x94, 0xe8, 0xfe, 0x36, 0x9d, 0x90, 0xb3, 0xca, 0x61, 0x2f, 0x9f, 0x22, 0xd7, 0x1d, 0x54, 0x36, 0x3a, 0x42, 0x17, 0xaa, 0x55, 0x11, 0x3f, 0x05, 0x9b, 0x33, 0x84, 0xe3, 0xe5, 0x7e, 0x44, 0x52, 0x28, 0x80, 0x62, 0xaf, 0xc0, 0x8f, 0xcd, 0xb7, 0xc5, 0xf8, 0x65, 0x0b, 0x29, 0x83, 0x73, 0x00, 0x46, 0x1d, 0xd5, 0x67, 0x6c, 0x17, 0xa2, 0x0a, 0x3c, 0x8f, 0xb5, 0x14, 0x89 } +, + /* Signature */ + 128, + { 0x22, 0x74, 0x64, 0x36, 0x16, 0x4e, 0x63, 0x93, 0x78, 0x71, 0xc1, 0xd4, 0x7d, 0x8e, 0x3e, 0x70, 0xc9, 0xe5, 0x2d, 0x11, 0x17, 0x31, 0x6b, 0xb1, 0x54, 0xcd, 0x55, 0x2e, 0x83, 0x6f, 0x2a, 0x3f, 0xbe, 0x6d, 0x89, 0xd6, 0x07, 0x4b, 0x51, 0xb0, 0x15, 0x9c, 0x26, 0xc2, 0x8d, 0xf7, 0x5e, 0x3d, 0x7c, 0xfb, 0x7c, 0xf0, 0x02, 0xf6, 0x5d, 0x1e, 0xe5, 0x21, 0xed, 0xc2, 0xc3, 0xa6, 0x5c, 0x52, 0x6c, 0x98, 0xc7, 0xc0, 0x25, 0xfa, 0x8b, 0xb6, 0x31, 0x47, 0x09, 0x16, 0xd3, 0x01, 0xb8, 0xf7, 0x80, 0x9d, 0xdd, 0x91, 0x9d, 0xed, 0x31, 0xa0, 0xd4, 0x66, 0x83, 0xec, 0x5b, 0xb4, 0x41, 0x70, 0x61, 0x6e, 0xab, 0xcd, 0x97, 0x02, 0x05, 0xed, 0x76, 0x02, 0x02, 0xd0, 0xd8, 0x7a, 0x65, 0x79, 0x59, 0x08, 0xb2, 0x8d, 0x32, 0x6f, 0x93, 0x62, 0x13, 0xf2, 0x9f, 0xeb, 0x59, 0x77, 0x34, 0x91 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.17", + /* Message to be signed */ + 224, + { 0x6a, 0x6a, 0x0c, 0x9b, 0x5b, 0x15, 0xbc, 0xda, 0x19, 0x6a, 0x9d, 0x0c, 0x76, 0xb1, 0x19, 0xd5, 0x34, 0xd8, 0x5a, 0xbd, 0x12, 0x39, 0x62, 0xd5, 0x83, 0xb7, 0x6c, 0xe9, 0xd1, 0x80, 0xbc, 0xe1, 0xca, 0x4a, 0xf8, 0x70, 0xfb, 0xc6, 0x51, 0x60, 0x12, 0xca, 0x91, 0x6c, 0x70, 0xba, 0x86, 0x2a, 0xc7, 0xe8, 0x24, 0x36, 0x17, 0x30, 0x6f, 0x4f, 0x9a, 0xb9, 0x50, 0x11, 0x99, 0xce, 0xf5, 0x5c, 0x6c, 0xf4, 0x08, 0xfe, 0x7b, 0x36, 0xc5, 0x57, 0xc4, 0x9d, 0x42, 0x0a, 0x47, 0x63, 0xd2, 0x46, 0x3c, 0x8a, 0xd4, 0x4b, 0x3c, 0xfc, 0x5b, 0xe2, 0x74, 0x2c, 0x0e, 0x7d, 0x9b, 0x0f, 0x66, 0x08, 0xf0, 0x8c, 0x7f, 0x47, 0xb6, 0x93, 0xee, 0x40, 0xd2, 0xe1, 0x80, 0xfa, 0xe1, 0xea, 0xc4, 0x39, 0xc1, 0x90, 0xb5, 0x6c, 0x2c, 0x0e, 0x14, 0xdd, 0xf9, 0xa2, 0x26, 0xba, 0xe1, 0x7d, 0x20, 0x38, 0x5d, 0x50, 0x19, 0x55, 0x82, 0x3c, 0x3f, 0x66, 0x62, 0x54, 0xc1, 0xd3, 0xdd, 0x36, 0xad, 0x51, 0x68, 0xb8, 0xf1, 0x8d, 0x28, 0x6f, 0xdc, 0xf6, 0x7a, 0x7d, 0xad, 0x94, 0x09, 0x70, 0x85, 0xfa, 0xb7, 0xed, 0x86, 0xfe, 0x21, 0x42, 0xa2, 0x87, 0x71, 0x71, 0x79, 0x97, 0xef, 0x1a, 0x7a, 0x08, 0x88, 0x4e, 0xfc, 0x39, 0x35, 0x6d, 0x76, 0x07, 0x7a, 0xaf, 0x82, 0x45, 0x9a, 0x7f, 0xad, 0x45, 0x84, 0x88, 0x75, 0xf2, 0x81, 0x9b, 0x09, 0x89, 0x37, 0xfe, 0x92, 0x3b, 0xcc, 0x9d, 0xc4, 0x42, 0xd7, 0x2d, 0x75, 0x4d, 0x81, 0x20, 0x25, 0x09, 0x0c, 0x9b, 0xc0, 0x3d, 0xb3, 0x08, 0x0c, 0x13 } +, + /* Signature */ + 128, + { 0x41, 0x93, 0x22, 0xfa, 0xca, 0xce, 0x76, 0xf2, 0xd5, 0xe2, 0xfb, 0xc1, 0x9a, 0xab, 0x86, 0xc7, 0x18, 0xa2, 0x80, 0x64, 0xf1, 0xd7, 0xb4, 0xc6, 0x62, 0xf0, 0x47, 0x4a, 0x87, 0x77, 0xa9, 0x59, 0xbd, 0x65, 0x69, 0x53, 0x8c, 0x16, 0x08, 0x1c, 0x0f, 0x52, 0x69, 0x8b, 0x2f, 0x00, 0x17, 0x30, 0xc0, 0x3b, 0x9a, 0x3d, 0x26, 0x94, 0x73, 0x74, 0xc9, 0x61, 0xfd, 0xed, 0xa1, 0x15, 0xb6, 0xb7, 0xda, 0xf6, 0x65, 0x18, 0xf1, 0xfe, 0x82, 0x0f, 0x67, 0xc3, 0xff, 0x12, 0xf0, 0xbc, 0x3f, 0x11, 0x01, 0xe3, 0x91, 0x1c, 0x43, 0x90, 0x6b, 0x0a, 0x12, 0x7e, 0x50, 0xbe, 0x01, 0x40, 0xc5, 0xef, 0xc4, 0x35, 0xe2, 0x95, 0x7b, 0x44, 0x2e, 0x60, 0xad, 0x52, 0x5a, 0xd7, 0x0a, 0xc9, 0xef, 0x61, 0xc3, 0xd6, 0x4f, 0x0e, 0x56, 0x6c, 0xbc, 0x1f, 0x9d, 0x51, 0xba, 0xe1, 0xd4, 0x72, 0x71, 0xda } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.18", + /* Message to be signed */ + 56, + { 0x3b, 0x93, 0xef, 0x4a, 0x55, 0x50, 0x96, 0x69, 0x19, 0x15, 0xdc, 0x23, 0xc0, 0x0e, 0x95, 0x4c, 0xde, 0xb2, 0x0a, 0x47, 0xcd, 0x55, 0xd1, 0x6c, 0x3d, 0x86, 0x81, 0xd4, 0x6e, 0xd7, 0xf2, 0xed, 0x5e, 0xa4, 0x27, 0x95, 0xbe, 0x17, 0xba, 0xed, 0x25, 0xf0, 0xf4, 0xd1, 0x13, 0xb3, 0x63, 0x6a, 0xdd, 0xd5, 0x85, 0xf1, 0x6a, 0x8b, 0x5a, 0xec } +, + /* Signature */ + 128, + { 0xae, 0x21, 0x1f, 0x4f, 0x77, 0xda, 0x1b, 0xe6, 0xaf, 0x9c, 0x9e, 0xa7, 0x04, 0xdb, 0xac, 0x4b, 0x3f, 0x3e, 0x27, 0x0d, 0x2f, 0xac, 0xf3, 0x65, 0x1d, 0x78, 0x7d, 0x0e, 0xbf, 0x59, 0xa7, 0x9a, 0x39, 0x61, 0x2d, 0xa1, 0x2d, 0x57, 0xc4, 0xac, 0x8a, 0xbc, 0x72, 0x8e, 0x1d, 0xa3, 0xf0, 0x1a, 0x15, 0x20, 0xfc, 0x9b, 0x32, 0xcb, 0x0f, 0xfe, 0x00, 0x8c, 0x80, 0x69, 0x92, 0x8f, 0x83, 0xe1, 0x35, 0x90, 0xa7, 0x8b, 0x81, 0x7e, 0x81, 0x9f, 0xbf, 0x2f, 0xd0, 0x58, 0x93, 0xec, 0xe5, 0xb1, 0x41, 0x86, 0xd9, 0x01, 0xc7, 0x68, 0xe3, 0x42, 0xdc, 0x54, 0x72, 0x23, 0x45, 0xae, 0x8a, 0xa8, 0x73, 0x8d, 0x4d, 0x59, 0x70, 0xc5, 0x08, 0x54, 0x72, 0xbd, 0x98, 0x99, 0xfa, 0x00, 0x42, 0xcf, 0x14, 0xbc, 0xed, 0xff, 0xdb, 0xc0, 0xef, 0x50, 0x81, 0x90, 0x75, 0x84, 0x2f, 0xc3, 0x6b, 0xb8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.19", + /* Message to be signed */ + 62, + { 0x49, 0xff, 0xd5, 0x6b, 0xf7, 0xef, 0xc1, 0x13, 0x04, 0xa5, 0xaf, 0xbc, 0x19, 0xd4, 0x79, 0x24, 0x90, 0x18, 0xfd, 0xf4, 0xe0, 0x9f, 0x61, 0x87, 0x26, 0x44, 0x04, 0x95, 0xde, 0x11, 0xdd, 0xee, 0xe3, 0x88, 0x72, 0xd7, 0x75, 0xfc, 0xea, 0x74, 0xa2, 0x38, 0x96, 0xb5, 0x34, 0x3c, 0x9c, 0x38, 0xd4, 0x6a, 0xf0, 0xdb, 0xa2, 0x24, 0xd0, 0x47, 0x58, 0x0c, 0xc6, 0x0a, 0x65, 0xe9 } +, + /* Signature */ + 128, + { 0x68, 0xfb, 0x0b, 0xd5, 0x19, 0xbf, 0x6f, 0x96, 0xe0, 0x76, 0xaf, 0x29, 0x01, 0x2f, 0x3c, 0x3a, 0x11, 0x37, 0xc0, 0x98, 0x8d, 0xe7, 0xb6, 0xfc, 0xed, 0xf4, 0xf5, 0x1b, 0xdf, 0xee, 0x64, 0x5b, 0x89, 0x7f, 0x17, 0x70, 0x9e, 0x05, 0xca, 0xa0, 0xb1, 0x13, 0x50, 0x0d, 0x90, 0x4d, 0xc0, 0x60, 0x0d, 0x17, 0xa9, 0xff, 0x8e, 0xb0, 0x2e, 0x1e, 0xfc, 0x9c, 0x46, 0x7a, 0x24, 0x00, 0x3e, 0xf8, 0x1e, 0x72, 0x74, 0x67, 0xc4, 0x7d, 0xd6, 0x56, 0x35, 0x6d, 0x70, 0x37, 0x2a, 0x15, 0xea, 0x88, 0x41, 0x21, 0x63, 0x4b, 0x01, 0x5d, 0x29, 0x51, 0x1f, 0x28, 0x95, 0x55, 0x77, 0x99, 0x07, 0x9d, 0x03, 0xc6, 0xd4, 0xde, 0x25, 0x9b, 0x3b, 0x36, 0x2b, 0x80, 0x49, 0x2d, 0x81, 0xbc, 0x9f, 0xe8, 0x54, 0x44, 0x63, 0xec, 0x03, 0x0b, 0xb5, 0xc9, 0xc7, 0x3c, 0x32, 0x74, 0xe3, 0xed, 0x12, 0x22 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 3.20", + /* Message to be signed */ + 136, + { 0xbc, 0x25, 0x5a, 0xf8, 0x9a, 0x6a, 0x19, 0x9b, 0xca, 0x4a, 0x39, 0x1e, 0xad, 0xbc, 0x3a, 0x24, 0x90, 0x3c, 0x0b, 0xd6, 0x67, 0x36, 0x8f, 0x6b, 0xe7, 0x8e, 0x3f, 0xea, 0xbf, 0xb4, 0xff, 0xd4, 0x63, 0x12, 0x27, 0x63, 0x74, 0x0f, 0xfb, 0xbe, 0xfe, 0xab, 0x9a, 0x25, 0x56, 0x4b, 0xc5, 0xd1, 0xc2, 0x4c, 0x93, 0xe4, 0x22, 0xf7, 0x50, 0x73, 0xe2, 0xad, 0x72, 0xbf, 0x45, 0xb1, 0x0d, 0xf0, 0x0b, 0x52, 0xa1, 0x47, 0x12, 0x8e, 0x73, 0xfe, 0xe3, 0x3f, 0xa3, 0xf0, 0x57, 0x7d, 0x77, 0xf8, 0x0f, 0xbc, 0x2d, 0xf1, 0xbe, 0xd3, 0x13, 0x29, 0x0c, 0x12, 0x77, 0x7f, 0x50, 0xa3, 0x34, 0xdb, 0x6f, 0xae, 0xbf, 0x11, 0x08, 0x1a, 0x04, 0xf8, 0x7c, 0x2d, 0x62, 0x1c, 0xde, 0xc7, 0x93, 0x0b, 0x9b, 0x18, 0x3a, 0x99, 0x04, 0x75, 0xdc, 0xbb, 0x9c, 0xc7, 0xf3, 0x45, 0xa3, 0xb5, 0x58, 0x03, 0x03, 0x0c, 0xf0, 0x36, 0x1a, 0x5d, 0x80, 0x81 } +, + /* Signature */ + 128, + { 0x41, 0xf6, 0x52, 0xdf, 0x79, 0xfd, 0xd2, 0x6d, 0xe9, 0x5c, 0x7a, 0x98, 0xfa, 0x85, 0x87, 0x13, 0xfb, 0x56, 0x6d, 0x8b, 0x39, 0x92, 0x8e, 0x71, 0x76, 0x4b, 0x2b, 0xeb, 0x19, 0x84, 0x03, 0xe0, 0x3b, 0x7e, 0x06, 0xdc, 0x96, 0x0c, 0x50, 0x51, 0x57, 0xbd, 0xf4, 0x05, 0x92, 0xc4, 0xd7, 0x75, 0x03, 0xfb, 0x72, 0xa4, 0xe0, 0x05, 0x5f, 0x97, 0x4f, 0xe9, 0x39, 0x44, 0x8d, 0xa3, 0x68, 0xf5, 0x3b, 0xd2, 0xef, 0xe2, 0x6e, 0x6f, 0x9a, 0x25, 0x4b, 0x3e, 0x87, 0x32, 0xaa, 0xd8, 0x16, 0x87, 0xb3, 0x61, 0xe2, 0x1a, 0x40, 0xcf, 0x3e, 0x5e, 0x92, 0x38, 0x9a, 0x2b, 0x48, 0x9c, 0x05, 0xc5, 0x97, 0xf0, 0xe1, 0x64, 0xe2, 0x67, 0x70, 0x93, 0x72, 0x00, 0x43, 0x27, 0x16, 0x35, 0x62, 0xdd, 0x8a, 0x0a, 0xdb, 0xbd, 0xfe, 0x3b, 0xc6, 0x16, 0xbd, 0x08, 0x42, 0x96, 0x84, 0xc2, 0x0c, 0x69 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 4: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xd1, 0x31, 0xe0, 0x92, 0x43, 0x37, 0x0d, 0xd2, 0xcd, 0x54, 0x25, 0xc8, 0xd0, 0x30, 0xf9, 0x9a, 0xdb, 0x10, 0x5b, 0x14, 0x7b, 0x8a, 0x3d, 0x00, 0x67, 0xc6, 0x16, 0x44, 0x3b, 0x7d, 0x4b, 0x96, 0x82, 0x38, 0xe0, 0x6d, 0xbb, 0x5f, 0x20, 0x28, 0xe8, 0x53, 0x57, 0x4b, 0x7c, 0x14, 0xbe, 0x10, 0x83, 0xc1, 0xe5, 0x7e, 0x13, 0x2c, 0x1d, 0xf4, 0xa3, 0xa2, 0x71, 0x32, 0x63, 0xfa, 0xde, 0x12, 0xf7, 0x11, 0x4f, 0x43, 0x69, 0xbb, 0xf0, 0x56, 0x20, 0x55, 0x48, 0x41, 0x33, 0x1e, 0xd8, 0x11, 0x00, 0x50, 0x52, 0x19, 0x25, 0x72, 0xce, 0xb4, 0x8d, 0x66, 0x24, 0x07, 0xfd, 0x30, 0x81, 0xcf, 0xab, 0x8b, 0x48, 0xc7, 0xe9, 0x2d, 0x3c, 0x4a, 0x26, 0xa9, 0x64, 0x5a, 0x38, 0xe6, 0xde, 0xe8, 0x8b, 0xb0, 0x07, 0x59, 0x75, 0xa4, 0xda, 0xd9, 0x64, 0x6b, 0x21, 0x60, 0x38, 0x40, 0xaf, 0x5f } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x56, 0xb5, 0x31, 0xbb, 0xee, 0x18, 0x37, 0xa6, 0x94, 0x6c, 0xb8, 0x6c, 0x8f, 0xbe, 0x7c, 0xf6, 0xee, 0xad, 0xcc, 0xd2, 0xa4, 0x92, 0x1b, 0xce, 0xbb, 0x34, 0xa3, 0xae, 0x0c, 0x6a, 0x56, 0x96, 0x3f, 0xcb, 0x8b, 0x5a, 0x70, 0x3b, 0x71, 0x7d, 0x03, 0x2e, 0xe8, 0x13, 0xe5, 0x8e, 0x43, 0x69, 0x5c, 0xf3, 0x55, 0x47, 0xf8, 0x72, 0x64, 0xc8, 0x2d, 0xba, 0xfa, 0xe8, 0x44, 0x00, 0x8b, 0x62, 0xd9, 0x12, 0x2e, 0x9d, 0xe8, 0x95, 0x85, 0x60, 0xc8, 0xdb, 0xb0, 0x07, 0x72, 0x7e, 0x71, 0x39, 0xe0, 0xa9, 0x82, 0xe0, 0x75, 0x88, 0x14, 0x11, 0x3d, 0xe5, 0x4b, 0xa0, 0xa4, 0x55, 0x17, 0x51, 0xfc, 0xa0, 0xfc, 0xb1, 0x2d, 0x8d, 0xe3, 0x0d, 0x78, 0xb8, 0xb1, 0x12, 0x98, 0xa7, 0xf7, 0x8f, 0x0b, 0x08, 0x8f, 0x16, 0x87, 0x05, 0x3c, 0x84, 0xa5, 0x76, 0x2f, 0x62, 0xa4, 0xbd, 0x05, 0xc1 } +, + /* Prime 1 */ + 64, + { 0xee, 0x22, 0xa4, 0x24, 0x62, 0xf7, 0x71, 0x8d, 0xfe, 0xcf, 0x02, 0x4b, 0x17, 0xc9, 0x26, 0x76, 0x78, 0x05, 0x91, 0x71, 0x33, 0x9c, 0xc0, 0x07, 0x06, 0x52, 0x60, 0xd3, 0x04, 0x7e, 0x5f, 0x89, 0xfe, 0xd9, 0x10, 0x34, 0x28, 0x43, 0x37, 0x8c, 0x22, 0x68, 0x5d, 0x53, 0x2e, 0x84, 0xd2, 0x59, 0x3a, 0x7c, 0x8c, 0x02, 0x6a, 0x87, 0x66, 0xc5, 0xa2, 0xb2, 0xed, 0x55, 0x8e, 0x88, 0x23, 0x19 } +, + /* Prime 2 */ + 64, + { 0xe0, 0xe3, 0x70, 0x0c, 0x99, 0xa3, 0xe8, 0x15, 0xd7, 0x4b, 0x75, 0x2a, 0x84, 0xfb, 0x42, 0xec, 0x20, 0xe5, 0x20, 0x3c, 0xa7, 0xc1, 0xaf, 0x97, 0xfb, 0xf3, 0x97, 0xb9, 0x5d, 0x11, 0x05, 0x37, 0x6c, 0xf5, 0xd6, 0x3e, 0x3c, 0x57, 0xbf, 0xa6, 0x58, 0x55, 0xe5, 0x08, 0x14, 0x6c, 0x86, 0xdb, 0xaa, 0xb2, 0x89, 0xc9, 0x5b, 0xc0, 0x45, 0x5a, 0x58, 0x2d, 0xd8, 0xf5, 0x3f, 0xfb, 0xed, 0x37 } +, + /* Prime exponent 1 */ + 64, + { 0xd1, 0xf1, 0x34, 0x68, 0xe7, 0xdf, 0x62, 0xfb, 0x5e, 0xb3, 0xbe, 0x3f, 0xd9, 0xde, 0x7a, 0xcc, 0x63, 0x0f, 0xf5, 0xa3, 0xa9, 0x6e, 0xfe, 0x54, 0xb3, 0x1c, 0x19, 0x44, 0xb0, 0x67, 0x81, 0x6f, 0x35, 0x80, 0xc4, 0xaa, 0x56, 0xfc, 0xbb, 0x92, 0x0e, 0x1b, 0x98, 0x7b, 0x67, 0x3d, 0xad, 0xfd, 0x00, 0x75, 0x21, 0x32, 0x58, 0x1c, 0xbb, 0x5c, 0x6e, 0x0d, 0xf4, 0xf3, 0x42, 0xcf, 0x7e, 0xb1 } +, + /* Prime exponent 2 */ + 64, + { 0xac, 0xd0, 0xda, 0x38, 0x34, 0x90, 0xea, 0x36, 0x6e, 0x7d, 0xc4, 0x09, 0xea, 0xab, 0x13, 0x20, 0x55, 0x9e, 0xfd, 0x88, 0xde, 0xf9, 0x4e, 0x30, 0xa3, 0x22, 0xec, 0x03, 0x3b, 0xeb, 0x6a, 0x70, 0xcf, 0x40, 0x93, 0x64, 0xbc, 0x06, 0x4a, 0x76, 0x50, 0x07, 0xa1, 0xba, 0xf5, 0xc6, 0xf8, 0x53, 0x31, 0xf7, 0x85, 0x3e, 0xc1, 0x4d, 0x1d, 0x7e, 0x71, 0xa8, 0xb9, 0xc2, 0xad, 0x6a, 0xb1, 0x3d } +, + /* Coefficient */ + 64, + { 0x1e, 0xda, 0x83, 0xd4, 0xa6, 0xd0, 0x99, 0xb6, 0x0b, 0x2b, 0x2b, 0x84, 0xc6, 0xae, 0x41, 0x65, 0xc7, 0x22, 0x50, 0x3e, 0xbd, 0x37, 0x3c, 0x83, 0x6f, 0x97, 0x35, 0xca, 0x3b, 0x20, 0xa3, 0xeb, 0x08, 0x1b, 0x31, 0xe7, 0x83, 0x04, 0x13, 0x20, 0xdf, 0xc6, 0xdd, 0xf9, 0x05, 0x14, 0xca, 0xb6, 0xec, 0x4b, 0x80, 0xae, 0x0c, 0x05, 0x2d, 0xd1, 0xe7, 0xce, 0x34, 0x18, 0xae, 0xee, 0x24, 0xa4 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 4.1", + /* Message to be signed */ + 174, + { 0x2c, 0x93, 0x6b, 0xf6, 0x13, 0x3a, 0x96, 0x93, 0xf1, 0x46, 0xee, 0x5a, 0x1a, 0x91, 0xc2, 0xf1, 0x69, 0xb2, 0xe6, 0x44, 0xa5, 0x18, 0xe8, 0x5a, 0x75, 0xf6, 0xe4, 0x3b, 0x56, 0x0d, 0x4a, 0x72, 0xf3, 0x8c, 0x64, 0xf8, 0x4c, 0x05, 0x24, 0x0e, 0x8b, 0x4e, 0x55, 0x78, 0x61, 0x63, 0xe7, 0x27, 0x62, 0x65, 0xba, 0x21, 0x3b, 0xa9, 0x3d, 0xee, 0x1b, 0x2e, 0x10, 0x21, 0x35, 0xa9, 0x89, 0xb6, 0x24, 0x8e, 0x88, 0x32, 0x7e, 0x30, 0x03, 0x61, 0xa7, 0x4f, 0x2e, 0x9b, 0xc4, 0x1f, 0x2a, 0x37, 0x68, 0x3f, 0x1a, 0x1a, 0x15, 0xf9, 0xdd, 0x47, 0x2e, 0x11, 0x8e, 0x1c, 0x4b, 0x3e, 0xde, 0x58, 0xdd, 0x70, 0xf3, 0xba, 0xcc, 0x25, 0x2e, 0x0c, 0x65, 0x4b, 0x0f, 0x7a, 0x6e, 0x41, 0xa9, 0x28, 0x75, 0x10, 0xef, 0xa0, 0x3b, 0xc9, 0x2e, 0x80, 0x5e, 0x5b, 0x2c, 0x91, 0x3f, 0x51, 0xe2, 0x5c, 0x7f, 0x85, 0x86, 0x40, 0xca, 0xfa, 0xc9, 0xd3, 0xc9, 0x17, 0x68, 0x65, 0x07, 0xfa, 0x94, 0xf8, 0x86, 0x6f, 0x86, 0x9a, 0x4e, 0x5a, 0x6a, 0x3d, 0x4f, 0x9d, 0x97, 0xed, 0x81, 0x37, 0xf4, 0x14, 0xd1, 0x44, 0x7a, 0x86, 0xee, 0xf9, 0xe1, 0x49, 0x69, 0x94, 0xad, 0x2d, 0xa5, 0x97 } +, + /* Signature */ + 128, + { 0x9e, 0x93, 0xf7, 0xac, 0xc5, 0x0f, 0xb3, 0xa0, 0xb1, 0x24, 0x3d, 0xc3, 0x38, 0xc8, 0xcc, 0xb1, 0x2b, 0xca, 0xb4, 0xaa, 0x45, 0x04, 0x40, 0xb6, 0x30, 0x6c, 0x81, 0xb5, 0x0b, 0x8f, 0x95, 0xa9, 0x36, 0xdd, 0x16, 0x63, 0x30, 0xc6, 0x99, 0xb2, 0x85, 0x80, 0xda, 0x1b, 0xe2, 0x75, 0x61, 0x64, 0x02, 0xda, 0x85, 0xbf, 0xd8, 0xee, 0xfc, 0xd6, 0x99, 0x35, 0x87, 0xe6, 0x09, 0x28, 0x65, 0xd8, 0x25, 0x3b, 0x04, 0x08, 0x1d, 0x57, 0x2f, 0x26, 0x27, 0x59, 0xf5, 0x56, 0xdf, 0xb9, 0x11, 0xe8, 0xd9, 0x4e, 0x92, 0xe5, 0x5a, 0xf6, 0xd5, 0x89, 0x80, 0x18, 0xff, 0x33, 0xe5, 0xf6, 0xb1, 0xf9, 0x90, 0x19, 0x96, 0xe9, 0x2f, 0xaf, 0x33, 0x6e, 0x2d, 0xcc, 0xe3, 0xab, 0x0a, 0x93, 0xdb, 0x93, 0x2e, 0x94, 0x2c, 0xc6, 0x47, 0x8d, 0x6c, 0xc2, 0xfb, 0x66, 0x08, 0x11, 0x91, 0x0c, 0xcd, 0x17 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 4.2", + /* Message to be signed */ + 154, + { 0x94, 0x32, 0x3f, 0x7c, 0x38, 0xb9, 0x95, 0xcc, 0x6b, 0xd8, 0x5d, 0x47, 0x9f, 0x8d, 0xe2, 0xde, 0xc1, 0xef, 0x2e, 0x84, 0xb1, 0xfe, 0xef, 0xec, 0xf3, 0x91, 0x50, 0xb5, 0xd9, 0xf2, 0xcb, 0x15, 0x85, 0xac, 0x0d, 0x71, 0x9a, 0xb3, 0x48, 0xbd, 0xc9, 0x75, 0x0d, 0xdb, 0x8e, 0x32, 0x76, 0xdb, 0x89, 0x81, 0x87, 0x35, 0xbd, 0x62, 0x31, 0x41, 0x3c, 0xbc, 0xa2, 0xde, 0x94, 0x1b, 0x55, 0xe8, 0xcf, 0xa1, 0xab, 0x13, 0x2c, 0xc7, 0x8a, 0xa4, 0xf2, 0xb5, 0x1f, 0xd6, 0x57, 0x8e, 0xe2, 0xe0, 0x32, 0xe9, 0x0e, 0x34, 0x08, 0x0f, 0x0f, 0x8e, 0x3d, 0xb1, 0x4d, 0x1b, 0x56, 0xf3, 0xd0, 0x77, 0xf2, 0x9d, 0xbc, 0x02, 0x16, 0xa4, 0x13, 0x44, 0x99, 0x8c, 0x0f, 0xe1, 0xab, 0x41, 0x22, 0x47, 0xdf, 0x21, 0xe7, 0x4e, 0xc2, 0x2f, 0x5d, 0xb0, 0x14, 0x8e, 0xca, 0xf4, 0x73, 0xee, 0xec, 0xcc, 0x14, 0xff, 0x9e, 0x45, 0xd5, 0x8c, 0x2e, 0x62, 0xb5, 0xfe, 0x6a, 0x50, 0x1a, 0xb9, 0x6f, 0xd7, 0xc5, 0xed, 0xde, 0xf1, 0x4a, 0xa8, 0x92, 0x66, 0x69, 0x2e } +, + /* Signature */ + 128, + { 0x09, 0x40, 0x2a, 0x43, 0x56, 0xbe, 0x73, 0x44, 0x9b, 0x46, 0x9e, 0x36, 0x31, 0xe1, 0xb0, 0x23, 0x07, 0xc5, 0xca, 0xc2, 0xce, 0x15, 0x28, 0xd7, 0x84, 0xfa, 0xb9, 0x26, 0xdf, 0xf5, 0x1f, 0x86, 0x24, 0x1b, 0x9d, 0x66, 0xf7, 0x9d, 0x6d, 0x8e, 0xee, 0xeb, 0x24, 0x9d, 0x76, 0xfa, 0x9f, 0x16, 0x6f, 0xf9, 0xa8, 0xc6, 0xa3, 0x9e, 0x83, 0x2d, 0x5d, 0x14, 0xb9, 0xd7, 0xec, 0x5a, 0x3d, 0xc2, 0x8f, 0x01, 0xeb, 0xb0, 0x6e, 0x39, 0xd5, 0x9e, 0x84, 0x61, 0xb9, 0x55, 0xb2, 0xa7, 0xf5, 0xb1, 0xf2, 0x04, 0xb0, 0x4c, 0xc6, 0xcc, 0x62, 0x64, 0x61, 0x61, 0xac, 0x1c, 0x2b, 0xf5, 0xba, 0xb5, 0x0f, 0x06, 0x8c, 0x90, 0x8d, 0x28, 0xde, 0x5e, 0xae, 0xf7, 0xe8, 0xeb, 0xfc, 0xab, 0xb0, 0x9b, 0x7d, 0x75, 0xd8, 0x35, 0x40, 0xdd, 0x4b, 0x35, 0x4d, 0x13, 0x1d, 0x86, 0xf0, 0x77, 0x07, 0x17 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.3", + /* Message to be signed */ + 154, + { 0x0e, 0x23, 0x3b, 0x25, 0x49, 0xbd, 0xd2, 0x1b, 0xa5, 0x14, 0x80, 0xda, 0x8e, 0x3d, 0xce, 0xf4, 0xdb, 0x20, 0xe0, 0xdc, 0xc0, 0x5e, 0xe2, 0x37, 0x35, 0x1e, 0xdb, 0xc9, 0xa5, 0x3c, 0x52, 0xf6, 0x74, 0xd1, 0x05, 0xfe, 0xc0, 0x93, 0x9d, 0x36, 0x99, 0x64, 0x7e, 0xfc, 0x1e, 0x25, 0xcb, 0x4e, 0x9b, 0x1a, 0xb7, 0x52, 0xab, 0x6f, 0xe2, 0x88, 0x69, 0xff, 0x73, 0xf2, 0x3e, 0x01, 0xee, 0xf8, 0x67, 0x4c, 0x53, 0x5c, 0x4c, 0x93, 0x35, 0xf7, 0x98, 0xf1, 0xde, 0xec, 0xd4, 0x89, 0xd0, 0x6d, 0xc8, 0x8f, 0xd6, 0xbc, 0x1d, 0x49, 0x96, 0xef, 0xf7, 0x2b, 0x43, 0x9e, 0x3c, 0x01, 0x4d, 0xd1, 0x4c, 0xbf, 0x17, 0x71, 0x5c, 0x15, 0x89, 0x43, 0xde, 0x2e, 0x6f, 0x97, 0x1c, 0x34, 0x99, 0x87, 0xa1, 0xb3, 0x95, 0xd6, 0x82, 0xc3, 0xb0, 0xc1, 0x7b, 0x66, 0xcd, 0x3c, 0xa4, 0x10, 0x60, 0xb5, 0x71, 0x11, 0xe2, 0x28, 0x31, 0x4b, 0x2d, 0x34, 0xb5, 0xe4, 0x4e, 0x55, 0xf1, 0xc1, 0x1c, 0x31, 0xa6, 0xeb, 0x80, 0xb5, 0xf8, 0x2d, 0x96, 0xbd, 0x4a, 0x17 } +, + /* Signature */ + 128, + { 0xd0, 0x75, 0xbe, 0x06, 0xcb, 0xd6, 0x22, 0x3e, 0x87, 0x1b, 0x0f, 0x33, 0x62, 0xa7, 0x97, 0xde, 0x28, 0x2d, 0xa5, 0xc4, 0x03, 0x23, 0xf3, 0x7c, 0x2c, 0xc3, 0x74, 0x65, 0xa1, 0xa8, 0x63, 0x68, 0xdd, 0xcf, 0xa6, 0xda, 0xa1, 0x35, 0x86, 0x6c, 0x32, 0x03, 0xd0, 0x47, 0x22, 0x60, 0xb2, 0x9c, 0x3c, 0x9b, 0x1b, 0x88, 0x94, 0x08, 0x5d, 0x54, 0x7c, 0x5e, 0xb9, 0x31, 0x42, 0x4f, 0x24, 0x14, 0x0a, 0x5c, 0xba, 0x15, 0x3b, 0xde, 0xd4, 0xb9, 0xce, 0x7d, 0xae, 0xdc, 0x64, 0x5d, 0x39, 0x80, 0xc5, 0xf5, 0x83, 0xf7, 0x67, 0x11, 0xc6, 0x7b, 0x19, 0x3a, 0x52, 0x12, 0xf2, 0xa9, 0x35, 0x4a, 0x67, 0x96, 0xaf, 0x09, 0x08, 0x20, 0x91, 0x31, 0x34, 0xec, 0xf3, 0x05, 0xbe, 0xfb, 0x65, 0x32, 0xcd, 0x48, 0xd4, 0x11, 0x3a, 0x0e, 0xc4, 0x86, 0x9a, 0x0a, 0x56, 0x55, 0xdb, 0xdc, 0x72, 0x59 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.4", + /* Message to be signed */ + 103, + { 0xd4, 0x7c, 0x0f, 0x5c, 0x92, 0x2e, 0x4f, 0x80, 0x9e, 0x9c, 0xee, 0xd2, 0x07, 0xf1, 0x24, 0xa5, 0xac, 0xde, 0x37, 0xfa, 0x14, 0x63, 0x8e, 0x8f, 0xbd, 0x0a, 0x72, 0xfe, 0x45, 0x26, 0x21, 0x95, 0x8e, 0x37, 0x68, 0x2c, 0x6f, 0xf2, 0x83, 0xf3, 0xd5, 0x1d, 0xa1, 0x52, 0xaa, 0x1f, 0x63, 0x74, 0xcd, 0x27, 0xd2, 0xa4, 0xa5, 0x33, 0x05, 0x39, 0x16, 0xdf, 0xf1, 0xc0, 0x7b, 0xa9, 0x36, 0x31, 0x74, 0x81, 0x69, 0x63, 0x60, 0x69, 0x04, 0x58, 0xd8, 0xd1, 0xe5, 0xd6, 0x6c, 0x35, 0xf9, 0xc9, 0x9a, 0x50, 0x55, 0xd9, 0xf7, 0xcf, 0xe7, 0x60, 0x5c, 0xca, 0x57, 0xea, 0xc3, 0x35, 0xad, 0xe2, 0xef, 0xf6, 0xb5, 0xaa, 0x62, 0x7d, 0x5b } +, + /* Signature */ + 128, + { 0x11, 0x86, 0x0b, 0xf4, 0xd7, 0x45, 0x19, 0xff, 0x8c, 0xfc, 0xce, 0x3d, 0x33, 0xe3, 0xaa, 0xbd, 0xf7, 0x71, 0x40, 0xa1, 0x56, 0x36, 0xb2, 0x67, 0x8d, 0xf9, 0x67, 0x31, 0x44, 0xc2, 0x41, 0xb0, 0xa9, 0x9a, 0x0a, 0x37, 0xf2, 0x92, 0xca, 0xd5, 0x1d, 0xf0, 0xb6, 0x3b, 0x14, 0xf8, 0xab, 0x17, 0xe3, 0xfa, 0x15, 0x58, 0x77, 0x90, 0xfb, 0x06, 0x2b, 0x5f, 0x26, 0x6c, 0x16, 0x6b, 0x2c, 0xa7, 0x51, 0x57, 0xa0, 0xf9, 0xe1, 0xa5, 0xc8, 0xec, 0x26, 0xb9, 0x19, 0x9d, 0x07, 0x18, 0x77, 0x99, 0x80, 0x6a, 0x1d, 0xe9, 0x87, 0x15, 0xfb, 0xe5, 0x27, 0x57, 0xa7, 0x03, 0x77, 0x3c, 0x91, 0x8a, 0x00, 0x0c, 0x21, 0x1a, 0x78, 0x22, 0x85, 0x25, 0xcb, 0x52, 0xeb, 0x44, 0x1b, 0x26, 0x9b, 0x3f, 0x33, 0x05, 0x0e, 0xd1, 0x93, 0x5a, 0xc0, 0xe8, 0x59, 0x63, 0x19, 0xae, 0x80, 0xc7, 0x5b, 0x84 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.5", + /* Message to be signed */ + 107, + { 0xbe, 0xbd, 0x9d, 0xde, 0xa3, 0xab, 0xf9, 0xf8, 0xeb, 0x58, 0x55, 0x97, 0x66, 0xf8, 0xb3, 0xab, 0x83, 0x53, 0x52, 0x38, 0xc4, 0x3d, 0xcd, 0x81, 0xa2, 0x94, 0x93, 0x03, 0xa9, 0x5f, 0x05, 0x5a, 0x83, 0x40, 0xce, 0xee, 0x16, 0x15, 0xe5, 0x8d, 0xf1, 0xe0, 0x14, 0xc7, 0x55, 0x2d, 0x76, 0x9f, 0x88, 0x41, 0xba, 0x09, 0x97, 0x5c, 0xef, 0xe7, 0xe4, 0x8d, 0xfc, 0x6a, 0x26, 0x49, 0xe8, 0x20, 0x03, 0xe7, 0xbf, 0x42, 0x0e, 0x70, 0x10, 0x1b, 0x32, 0x7d, 0x91, 0x70, 0xf7, 0x3e, 0x8d, 0x88, 0x7c, 0xd2, 0x98, 0xf5, 0x3d, 0xc1, 0xbf, 0xc8, 0x82, 0xcf, 0x0e, 0xfc, 0xfa, 0xd6, 0xe8, 0x6a, 0x0e, 0x7f, 0x90, 0x94, 0xc4, 0xf2, 0x6c, 0x46, 0x92, 0x1e, 0x09 } +, + /* Signature */ + 128, + { 0x84, 0xa2, 0x6f, 0xbe, 0x67, 0x01, 0x0a, 0xa1, 0xef, 0x2d, 0x6c, 0x79, 0x26, 0x32, 0x39, 0xb9, 0x78, 0xf4, 0xe8, 0x93, 0xdd, 0x1e, 0xc6, 0xf0, 0x7d, 0x23, 0x17, 0xf1, 0x51, 0xa2, 0xa1, 0xb3, 0x23, 0xe5, 0x05, 0xf9, 0x45, 0x0c, 0x37, 0xdf, 0x6b, 0x1b, 0xf3, 0xe2, 0x4f, 0x38, 0xb6, 0x36, 0xbf, 0x77, 0x4e, 0x96, 0x74, 0x1f, 0xfa, 0xa7, 0x69, 0xcf, 0xd7, 0xa8, 0xa6, 0xb3, 0xa5, 0xef, 0xab, 0xa2, 0x3a, 0xab, 0x3a, 0x43, 0x7a, 0x22, 0x5b, 0xd9, 0x41, 0x86, 0xe9, 0x1d, 0x39, 0x2b, 0xed, 0x2e, 0xad, 0x8a, 0x78, 0xf3, 0x81, 0xf4, 0x09, 0x49, 0xcf, 0x1f, 0x3d, 0x27, 0x24, 0x58, 0x1f, 0x25, 0x70, 0x4b, 0xdf, 0x66, 0x08, 0xdd, 0x11, 0x9e, 0x36, 0xd8, 0x7d, 0x03, 0x55, 0xe6, 0x70, 0x6c, 0x8a, 0x52, 0x59, 0xfd, 0x60, 0xc8, 0xdf, 0x13, 0xbc, 0x62, 0xaa, 0x9f, 0xd5, 0x7a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.6", + /* Message to be signed */ + 247, + { 0x9d, 0x19, 0x8e, 0x2c, 0x6e, 0x12, 0xf7, 0x4a, 0x9a, 0x08, 0x1b, 0xcf, 0x70, 0xfc, 0x04, 0x16, 0x8a, 0x49, 0xe0, 0x9c, 0x5f, 0xaa, 0xa0, 0x11, 0xe9, 0xa0, 0x9e, 0x2c, 0x43, 0xee, 0x2c, 0xd3, 0x9b, 0xb2, 0xf7, 0xe5, 0x68, 0x2d, 0xea, 0xb1, 0xfa, 0x11, 0x1e, 0x41, 0xa3, 0x19, 0x4a, 0x20, 0xa8, 0x6d, 0xa5, 0x51, 0x01, 0x82, 0x4d, 0x3d, 0x78, 0xa7, 0xe3, 0x2d, 0xb2, 0xb6, 0x0a, 0xa7, 0x73, 0x77, 0x0b, 0x57, 0x39, 0x07, 0xb4, 0x09, 0xa2, 0x59, 0x2c, 0x83, 0xf3, 0x47, 0xfe, 0xbb, 0x2d, 0x5c, 0x85, 0xe9, 0x25, 0x5d, 0x6d, 0xc1, 0x2a, 0xaa, 0x33, 0x5a, 0xdf, 0xbb, 0x5d, 0xc8, 0x62, 0xd7, 0x86, 0x19, 0x53, 0xe2, 0x68, 0x7d, 0x53, 0x03, 0xb6, 0x86, 0xff, 0xf9, 0x63, 0x4e, 0xe4, 0xd1, 0x5c, 0xbc, 0xc2, 0x9f, 0x7a, 0x35, 0x05, 0xa7, 0x3d, 0xeb, 0x6f, 0x9e, 0x38, 0x8e, 0x96, 0x85, 0xff, 0xf4, 0xd5, 0x45, 0x0f, 0x1e, 0x32, 0x75, 0x35, 0x9a, 0x2b, 0x99, 0x44, 0x0c, 0x67, 0x39, 0xf5, 0xb9, 0x1e, 0xbd, 0x14, 0xef, 0x78, 0xae, 0x73, 0xc1, 0xa6, 0x19, 0x11, 0xf5, 0xae, 0x3a, 0x2b, 0x91, 0x49, 0x67, 0x49, 0x17, 0x27, 0x81, 0x80, 0x65, 0xee, 0x01, 0x0d, 0xf4, 0x9d, 0x5a, 0x16, 0xed, 0x8d, 0xce, 0xe8, 0x48, 0xae, 0x09, 0x48, 0xa2, 0x52, 0x4e, 0xac, 0x7c, 0x4f, 0xf9, 0x09, 0x6c, 0xed, 0x61, 0x35, 0x76, 0x42, 0xc5, 0xe0, 0xf8, 0x06, 0x80, 0xaf, 0xff, 0xce, 0x0b, 0xa7, 0xeb, 0x59, 0x58, 0x99, 0x49, 0x52, 0x6f, 0xf5, 0x12, 0x35, 0xcd, 0xc7, 0x2d, 0x47, 0xa2, 0x7b, 0x39, 0xb8, 0xd4, 0xac, 0x84, 0x9c, 0x3b, 0xc0, 0x4f, 0xa8, 0x36, 0xcf, 0x18, 0x4b, 0xae, 0x0c, 0x83, 0x41, 0x59, 0x56 } +, + /* Signature */ + 128, + { 0x38, 0xef, 0x24, 0x5b, 0x94, 0x0d, 0x93, 0x97, 0x0a, 0x50, 0x3b, 0xf4, 0x3e, 0x28, 0xe1, 0x7b, 0x8a, 0xff, 0x08, 0x3c, 0xcb, 0xe1, 0xe9, 0xc4, 0x8e, 0x4d, 0x80, 0xf5, 0x16, 0xc2, 0x7d, 0x08, 0x5c, 0xa2, 0xa4, 0xe5, 0x73, 0x23, 0x6a, 0x24, 0x94, 0xd9, 0xb9, 0x97, 0xf8, 0x12, 0x48, 0x48, 0x12, 0xf6, 0x65, 0x25, 0xd0, 0x6c, 0x0a, 0x0b, 0xb2, 0x13, 0x0c, 0x15, 0xd6, 0xce, 0x18, 0xb2, 0x2f, 0x3c, 0xee, 0x57, 0x09, 0x7f, 0xc0, 0xd5, 0x58, 0xaf, 0xd9, 0xaf, 0x27, 0xf1, 0x51, 0xf8, 0x43, 0x6f, 0xbc, 0x87, 0xd6, 0xbe, 0x61, 0x42, 0x64, 0x7a, 0x17, 0xe0, 0x4d, 0xf6, 0xde, 0xc7, 0x0a, 0x95, 0xc7, 0xda, 0xa8, 0x4e, 0xde, 0x94, 0xcc, 0xb4, 0x3e, 0x1d, 0x2c, 0x37, 0xb9, 0x45, 0x81, 0x73, 0x10, 0xd1, 0x4a, 0x22, 0xb5, 0xb9, 0xae, 0x61, 0x14, 0x48, 0xee, 0x41, 0xbc, 0x70 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.7", + /* Message to be signed */ + 47, + { 0x8e, 0x8b, 0xa8, 0x43, 0x6f, 0xe3, 0x10, 0x4b, 0x7c, 0xe2, 0xa4, 0xef, 0xc3, 0x6c, 0x85, 0x7d, 0x49, 0xe8, 0x49, 0xc0, 0x08, 0x5f, 0xc6, 0x57, 0xba, 0xa0, 0x33, 0x17, 0x93, 0xb3, 0xf3, 0x6c, 0x7c, 0xe7, 0x38, 0xb6, 0x13, 0x0b, 0xfa, 0xc7, 0x5e, 0x50, 0x11, 0xf3, 0x2a, 0xa3, 0xd1 } +, + /* Signature */ + 128, + { 0x78, 0x44, 0x69, 0x9f, 0x1c, 0x4f, 0x29, 0x6e, 0x50, 0x26, 0x1f, 0x15, 0x26, 0xe0, 0xdd, 0x84, 0xf0, 0x1c, 0x82, 0xcb, 0x85, 0xfa, 0x24, 0x60, 0x9e, 0xb0, 0x33, 0x58, 0x75, 0x2c, 0x6c, 0xf5, 0x99, 0x94, 0xd8, 0x4e, 0x12, 0xf4, 0x6a, 0x72, 0x00, 0xcf, 0x5a, 0xd9, 0x7c, 0x08, 0xdd, 0x4f, 0xfc, 0x44, 0x65, 0x7d, 0xb5, 0x72, 0x14, 0xcd, 0x1f, 0x4e, 0xed, 0x6b, 0x77, 0xd2, 0x39, 0xfb, 0x58, 0x21, 0x69, 0x88, 0xc5, 0xe5, 0xbc, 0x73, 0x5a, 0x4f, 0xdf, 0xf4, 0x08, 0xeb, 0x9f, 0x12, 0x79, 0xd6, 0x5b, 0xba, 0xf6, 0xa6, 0x81, 0x92, 0x44, 0x18, 0x34, 0x9e, 0x62, 0xff, 0x5e, 0x58, 0x15, 0xea, 0xea, 0x59, 0x2d, 0x90, 0xd1, 0xee, 0xf5, 0x56, 0xfc, 0xd4, 0xd5, 0xb4, 0xb8, 0x9c, 0x6c, 0x70, 0x73, 0x9d, 0x6f, 0x0d, 0x3d, 0x0b, 0xd1, 0x6a, 0x50, 0xf1, 0xe0, 0x02, 0x4e, 0x98 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.8", + /* Message to be signed */ + 185, + { 0x58, 0x5f, 0xa6, 0xa7, 0xf7, 0x7a, 0x4b, 0x6e, 0xba, 0x56, 0x90, 0xe7, 0x3e, 0x71, 0x28, 0xb7, 0x2e, 0x67, 0x7c, 0xdb, 0x3a, 0xaa, 0x86, 0x29, 0xed, 0x61, 0xf2, 0xee, 0x63, 0xaf, 0x1a, 0x71, 0xba, 0x87, 0x13, 0x6a, 0x52, 0xdb, 0x1a, 0x33, 0x21, 0xfc, 0xfe, 0xb2, 0x48, 0xbf, 0x2e, 0x5c, 0xf5, 0xc6, 0x39, 0x57, 0x1d, 0x58, 0x95, 0xad, 0xf1, 0xfb, 0x06, 0x17, 0xed, 0x14, 0x0a, 0x2a, 0x0d, 0x98, 0x37, 0xc3, 0xc1, 0xd8, 0x45, 0x0c, 0x28, 0x9d, 0x33, 0xbc, 0x96, 0x23, 0x79, 0xd7, 0x3e, 0x30, 0x87, 0xf2, 0xb7, 0xee, 0x6e, 0xad, 0xd6, 0x65, 0x01, 0x48, 0xc0, 0x42, 0xb6, 0xff, 0x04, 0x48, 0x21, 0x96, 0xc7, 0x18, 0xfd, 0xc0, 0xce, 0x57, 0x9c, 0xeb, 0x62, 0xa8, 0x1e, 0x58, 0x43, 0x73, 0xeb, 0x93, 0x75, 0x40, 0xc4, 0x26, 0xb5, 0x56, 0x6a, 0x9f, 0x40, 0x7c, 0xfc, 0xcf, 0xbc, 0x4b, 0x75, 0x36, 0x94, 0xaf, 0x0d, 0xf4, 0xcd, 0x6a, 0xa9, 0xf1, 0x65, 0x46, 0xa6, 0x33, 0x94, 0xa0, 0xf6, 0x57, 0x73, 0x71, 0x34, 0x3f, 0xfd, 0xdb, 0x65, 0x1a, 0x62, 0xa3, 0xa5, 0x8e, 0xdd, 0xec, 0x67, 0xa2, 0x9c, 0xca, 0xe8, 0x96, 0x56, 0x3c, 0x63, 0xe3, 0xc9, 0x0d, 0x54, 0xd9, 0x13, 0x58, 0xad, 0xf1, 0x94, 0xe6, 0xaa, 0xb1, 0xf9 } +, + /* Signature */ + 128, + { 0x68, 0x93, 0x35, 0x1c, 0x73, 0x91, 0x5f, 0xac, 0x47, 0xc9, 0x62, 0xcc, 0x60, 0x17, 0xca, 0x74, 0xa5, 0xb5, 0xee, 0x4c, 0xb1, 0xbb, 0x5a, 0x10, 0xad, 0xa2, 0xa4, 0x31, 0x58, 0xa2, 0x26, 0x1e, 0xb2, 0x7b, 0x86, 0x6d, 0xb3, 0x9d, 0x35, 0x90, 0xb4, 0xf8, 0xd2, 0x0e, 0xe6, 0x7c, 0xb1, 0xa5, 0x78, 0x94, 0x63, 0x15, 0x0d, 0x83, 0x93, 0x43, 0x23, 0x25, 0x43, 0xc8, 0x26, 0x50, 0x51, 0x01, 0xe1, 0xd2, 0x57, 0x04, 0x26, 0xab, 0x9f, 0xef, 0xd6, 0x5b, 0xa8, 0x4f, 0xaa, 0xec, 0x73, 0x1f, 0x27, 0x37, 0x4a, 0xb1, 0x01, 0x91, 0xc9, 0x60, 0x83, 0x16, 0x93, 0xf2, 0x9a, 0x85, 0x4c, 0x38, 0x12, 0x85, 0x99, 0xf7, 0x28, 0x77, 0x49, 0xb0, 0xb4, 0x8b, 0xf7, 0xe9, 0xdf, 0xda, 0xed, 0xc8, 0x4e, 0xec, 0xe0, 0x71, 0x40, 0x45, 0x84, 0x73, 0x0c, 0xec, 0xce, 0x0d, 0x5c, 0xf0, 0x05, 0xcc } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.9", + /* Message to be signed */ + 5, + { 0x78, 0x3c, 0x18, 0xb1, 0x1f } +, + /* Signature */ + 128, + { 0x13, 0x2f, 0xdf, 0xb8, 0x41, 0x93, 0xdf, 0xb7, 0x9f, 0xdf, 0xe6, 0xba, 0xbc, 0x2e, 0xfd, 0x39, 0xb2, 0x6a, 0xa2, 0x09, 0x68, 0xa0, 0x7c, 0x0e, 0x41, 0x56, 0x0e, 0xe4, 0xdf, 0xcd, 0x4f, 0xca, 0x79, 0x17, 0x49, 0x0f, 0x24, 0xe8, 0xdf, 0x84, 0xf4, 0xe0, 0x11, 0x5a, 0x3e, 0x63, 0x27, 0x3e, 0x7a, 0x3b, 0x12, 0x8a, 0xbb, 0xbd, 0x17, 0xb8, 0xaa, 0x5a, 0x06, 0xba, 0x15, 0x5e, 0xcb, 0x23, 0x0f, 0xe7, 0x97, 0x26, 0x04, 0x79, 0x95, 0x70, 0x10, 0xe4, 0x4b, 0xa5, 0x75, 0x29, 0x2e, 0xc3, 0xf1, 0x51, 0xab, 0xf4, 0x8e, 0x91, 0x03, 0xe5, 0x51, 0x42, 0xec, 0x67, 0xa4, 0x13, 0x4d, 0xd8, 0xf3, 0x8e, 0xc6, 0x59, 0xf9, 0xa7, 0x89, 0xfd, 0x03, 0x41, 0xce, 0xf2, 0xbb, 0xcf, 0x9f, 0x52, 0x9b, 0x93, 0x21, 0x8f, 0xc3, 0xe4, 0x3a, 0x76, 0x69, 0x69, 0xd1, 0xbf, 0x87, 0x88, 0x48, 0x07 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.10", + /* Message to be signed */ + 85, + { 0x96, 0xdc, 0x98, 0xb0, 0xeb, 0x84, 0xf5, 0x59, 0x48, 0x30, 0x7a, 0xdd, 0xec, 0xcb, 0xe7, 0x64, 0x39, 0xca, 0x36, 0x58, 0xbc, 0x36, 0x35, 0x96, 0x24, 0xc8, 0xfe, 0x2f, 0xa0, 0x9c, 0x52, 0xe4, 0x7a, 0xcd, 0xc3, 0x2a, 0x15, 0x6d, 0x90, 0x76, 0x82, 0x41, 0x0a, 0x85, 0x67, 0xab, 0xca, 0xfd, 0xc6, 0xd8, 0xbb, 0x53, 0x25, 0x35, 0x9e, 0xc7, 0x5f, 0xfd, 0xb7, 0x3e, 0xe0, 0xa9, 0x51, 0x5a, 0x4d, 0xdf, 0x9a, 0x31, 0xe5, 0xd5, 0x19, 0x46, 0x03, 0x74, 0x28, 0x0a, 0xda, 0x30, 0xde, 0x7d, 0xd5, 0x34, 0xde, 0xaa, 0x57 } +, + /* Signature */ + 128, + { 0x8f, 0xb4, 0x3d, 0xc8, 0xf0, 0x6f, 0x2b, 0xa4, 0x8f, 0x19, 0xbe, 0x5b, 0x1a, 0x09, 0x31, 0x21, 0x3a, 0x99, 0x0a, 0xed, 0x9c, 0x9f, 0xed, 0x1d, 0xe5, 0xd6, 0xf3, 0x5a, 0x2a, 0x78, 0x2f, 0x0a, 0x19, 0x8f, 0xf6, 0x38, 0x8d, 0x96, 0xe9, 0xd5, 0x9b, 0x88, 0xe9, 0x78, 0x22, 0xf3, 0x49, 0xff, 0x41, 0x64, 0xee, 0xa5, 0x0a, 0x62, 0x93, 0x5c, 0x61, 0xcb, 0xc7, 0x6e, 0x3d, 0xf7, 0x5f, 0x68, 0x4d, 0x96, 0x24, 0x75, 0xe5, 0x63, 0x59, 0x64, 0x96, 0xc9, 0x88, 0x0a, 0x48, 0xed, 0x97, 0x8a, 0x63, 0x15, 0xa3, 0x45, 0x57, 0x17, 0x91, 0xcb, 0x2d, 0xdc, 0x88, 0xda, 0xbe, 0x41, 0x87, 0x98, 0xa6, 0xa4, 0x41, 0xc4, 0x7a, 0xfb, 0xb1, 0xcd, 0x15, 0x21, 0x3e, 0xca, 0x3b, 0x11, 0x15, 0xec, 0x8f, 0x58, 0xf8, 0x77, 0xbe, 0x8f, 0xbd, 0x38, 0xf4, 0xfd, 0xae, 0xf9, 0x39, 0xf5, 0x26, 0x40 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.11", + /* Message to be signed */ + 115, + { 0x37, 0x20, 0x01, 0x59, 0x9d, 0x99, 0x30, 0xc7, 0xd5, 0x57, 0x45, 0x8b, 0x43, 0x6d, 0xec, 0xfd, 0xc1, 0x4d, 0x06, 0xcb, 0x7b, 0x96, 0xb0, 0x67, 0x18, 0xc4, 0x8d, 0x7d, 0xe5, 0x74, 0x82, 0xa8, 0x68, 0xae, 0x7f, 0x06, 0x58, 0x70, 0xa6, 0x21, 0x65, 0x06, 0xd1, 0x1b, 0x77, 0x93, 0x23, 0xdf, 0xdf, 0x04, 0x6c, 0xf5, 0x77, 0x51, 0x29, 0x13, 0x4b, 0x4d, 0x56, 0x89, 0xe4, 0xd9, 0xc0, 0xce, 0x1e, 0x12, 0xd7, 0xd4, 0xb0, 0x6c, 0xb5, 0xfc, 0x58, 0x20, 0xde, 0xcf, 0xa4, 0x1b, 0xaf, 0x59, 0xbf, 0x25, 0x7b, 0x32, 0xf0, 0x25, 0xb7, 0x67, 0x9b, 0x44, 0x5b, 0x94, 0x99, 0xc9, 0x25, 0x55, 0x14, 0x58, 0x85, 0x99, 0x2f, 0x1b, 0x76, 0xf8, 0x48, 0x91, 0xee, 0x4d, 0x3b, 0xe0, 0xf5, 0x15, 0x0f, 0xd5, 0x90 } +, + /* Signature */ + 128, + { 0xa8, 0x97, 0xc7, 0xf9, 0x72, 0xe1, 0x17, 0x49, 0xe1, 0xe7, 0xc1, 0x55, 0xce, 0x94, 0x62, 0xaa, 0x7e, 0x1c, 0xc0, 0xa9, 0x79, 0xc1, 0x27, 0x29, 0x79, 0x51, 0x26, 0xcb, 0x8c, 0x0e, 0xa5, 0x02, 0x21, 0xc4, 0x26, 0xf1, 0xbb, 0x06, 0xc1, 0xca, 0xf7, 0xc5, 0x1a, 0xc2, 0xfb, 0xd9, 0x4d, 0x68, 0x8d, 0xa6, 0x7d, 0xdf, 0x3e, 0xf6, 0x66, 0x06, 0xe9, 0x89, 0xa1, 0x6d, 0xe1, 0xf9, 0x2b, 0x17, 0x70, 0x6f, 0x88, 0xe8, 0x7d, 0x9f, 0x14, 0x69, 0xa0, 0x05, 0xc9, 0xfd, 0x76, 0x78, 0x8e, 0xe8, 0xc4, 0xa7, 0xf0, 0x12, 0x09, 0xe2, 0x8b, 0x86, 0xf6, 0x74, 0x88, 0x1a, 0xf5, 0x7d, 0xb6, 0xc3, 0x42, 0x9b, 0x6f, 0xb4, 0x56, 0x98, 0xbf, 0x5d, 0x30, 0x07, 0xf6, 0x1c, 0x7d, 0x44, 0x11, 0x78, 0xad, 0x12, 0x43, 0xa4, 0x9b, 0x2a, 0xa6, 0x02, 0x9b, 0xfe, 0x90, 0x2d, 0x26, 0xe4, 0x23, 0x75 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.12", + /* Message to be signed */ + 35, + { 0xbf, 0xbf, 0xd0, 0x73, 0x21, 0xf0, 0xf1, 0xd5, 0xfa, 0x9f, 0xdf, 0x00, 0x14, 0xc2, 0xfc, 0xb0, 0x35, 0x8a, 0xad, 0x0e, 0x35, 0x4b, 0x0d, 0x29, 0x08, 0x1b, 0x23, 0x3b, 0x43, 0x56, 0x77, 0x50, 0xbd, 0x6e, 0x78 } +, + /* Signature */ + 128, + { 0xc2, 0x4d, 0x31, 0x04, 0x94, 0x09, 0xaa, 0x16, 0xd3, 0xf9, 0x72, 0xef, 0x8b, 0x75, 0x95, 0xea, 0xa0, 0x07, 0x83, 0x3e, 0x2b, 0xcd, 0xc7, 0x50, 0x48, 0x52, 0xf2, 0x50, 0x5f, 0xba, 0x1f, 0xc1, 0x5f, 0x19, 0xa0, 0xea, 0xdd, 0xe8, 0x33, 0x5c, 0x73, 0x06, 0xfc, 0x3f, 0x51, 0x66, 0x1d, 0xa5, 0x20, 0xec, 0xc8, 0xdb, 0x7f, 0x47, 0x38, 0x85, 0xca, 0xbd, 0xe9, 0x3f, 0x0c, 0xeb, 0xf1, 0xdf, 0x9e, 0x8a, 0x82, 0x37, 0x0b, 0x00, 0xa0, 0x43, 0xad, 0x63, 0x2c, 0xdc, 0xc7, 0x8f, 0x3f, 0xac, 0x1d, 0x8a, 0x37, 0x57, 0xfc, 0x8e, 0x52, 0x41, 0xbf, 0xed, 0x55, 0xc4, 0x96, 0x04, 0xac, 0x19, 0xab, 0xda, 0xc0, 0xc9, 0xc4, 0x0d, 0xa3, 0x73, 0xc1, 0x5f, 0x3c, 0x1b, 0xcc, 0x97, 0x3f, 0xfb, 0x4f, 0x8b, 0x7b, 0x5b, 0x55, 0x3a, 0xe0, 0x75, 0xe1, 0xb1, 0xbd, 0xdd, 0xd2, 0x3d, 0x7d, 0x2a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.13", + /* Message to be signed */ + 107, + { 0xc6, 0x97, 0x39, 0xd2, 0x2a, 0xc8, 0x96, 0x6b, 0xf1, 0x1c, 0x11, 0x6f, 0x61, 0x4b, 0x16, 0x67, 0x40, 0xe9, 0x6b, 0x90, 0x65, 0x3e, 0x57, 0x50, 0x94, 0x5f, 0xcf, 0x77, 0x21, 0x86, 0xc0, 0x37, 0x90, 0xa0, 0x7f, 0xda, 0x32, 0x3e, 0x1a, 0x61, 0x91, 0x6b, 0x06, 0xee, 0x21, 0x57, 0xdb, 0x3d, 0xff, 0x80, 0xd6, 0x7d, 0x5e, 0x39, 0xa5, 0x3a, 0xe2, 0x68, 0xc8, 0xf0, 0x9e, 0xd9, 0x9a, 0x73, 0x20, 0x05, 0xb0, 0xbc, 0x6a, 0x04, 0xaf, 0x4e, 0x08, 0xd5, 0x7a, 0x00, 0xe7, 0x20, 0x1b, 0x30, 0x60, 0xef, 0xaa, 0xdb, 0x73, 0x11, 0x3b, 0xfc, 0x08, 0x7f, 0xd8, 0x37, 0x09, 0x3a, 0xa2, 0x52, 0x35, 0xb8, 0xc1, 0x49, 0xf5, 0x62, 0x15, 0xf0, 0x31, 0xc2, 0x4a } +, + /* Signature */ + 128, + { 0xd0, 0x6d, 0x32, 0x26, 0x0d, 0xa2, 0xdb, 0x48, 0x10, 0x4f, 0xbd, 0xc2, 0x4e, 0x16, 0xa6, 0x5b, 0x48, 0x73, 0x7d, 0x43, 0xce, 0x24, 0x37, 0x04, 0x04, 0x2a, 0xad, 0x6c, 0x03, 0xfd, 0xe5, 0xa3, 0xdc, 0x0f, 0x2c, 0xc6, 0xe3, 0xad, 0x68, 0xc3, 0xc6, 0x2e, 0xab, 0xfa, 0x1f, 0x7b, 0x1c, 0xab, 0x00, 0x9d, 0x11, 0x75, 0xaf, 0xf7, 0x7b, 0xe5, 0x8f, 0xb1, 0x2a, 0x4e, 0x58, 0x12, 0x7f, 0xed, 0x63, 0xea, 0x3d, 0xf4, 0x41, 0x81, 0xbd, 0xa3, 0x8c, 0x77, 0x3c, 0x83, 0xb9, 0xe8, 0x04, 0xbb, 0x3d, 0xb7, 0x96, 0x32, 0x63, 0xdf, 0x30, 0xe9, 0x2c, 0x4c, 0x27, 0x19, 0x56, 0xe7, 0xe8, 0x10, 0x45, 0x2c, 0x15, 0xe0, 0x6e, 0x93, 0x96, 0x66, 0xdf, 0x0c, 0x83, 0x34, 0x03, 0x30, 0x96, 0xc0, 0x7d, 0xea, 0x05, 0xb4, 0x4e, 0xbb, 0x14, 0x24, 0x92, 0xe7, 0x66, 0x91, 0x31, 0xeb, 0xcf, 0x2c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.14", + /* Message to be signed */ + 16, + { 0x73, 0x30, 0x47, 0xf3, 0x36, 0xf9, 0x15, 0x47, 0x38, 0x67, 0x45, 0x47, 0xdb, 0x02, 0xa9, 0xf4 } +, + /* Signature */ + 128, + { 0xc1, 0x13, 0xc0, 0x46, 0x5c, 0x84, 0xcb, 0xfb, 0x0f, 0xa1, 0xbd, 0xbc, 0x54, 0xc3, 0xe1, 0x06, 0x8c, 0xa2, 0x3e, 0x69, 0xb8, 0x39, 0x19, 0x09, 0xc3, 0x90, 0x0f, 0xe5, 0xb4, 0xe7, 0xe3, 0xf0, 0x34, 0xc9, 0xa9, 0x88, 0xa3, 0xdd, 0xc3, 0xc3, 0x81, 0x75, 0x6a, 0x1e, 0x1a, 0x27, 0xc1, 0xec, 0xfb, 0x3a, 0x70, 0xe1, 0xee, 0x0e, 0x92, 0x04, 0x18, 0xac, 0x4a, 0xb6, 0xd9, 0x53, 0x2b, 0x8d, 0x09, 0x59, 0xa6, 0x53, 0xb4, 0xc5, 0x08, 0x67, 0x06, 0x63, 0x46, 0x2b, 0x2e, 0x13, 0x58, 0x16, 0xb6, 0x94, 0xa6, 0xb9, 0xb4, 0x68, 0xa2, 0x9f, 0x38, 0xde, 0x53, 0xbf, 0xcd, 0xdf, 0x97, 0xe0, 0x3d, 0x8d, 0xd2, 0x4f, 0x97, 0x26, 0x33, 0xa4, 0x9c, 0xf3, 0xea, 0xae, 0x1d, 0x69, 0x62, 0x94, 0x38, 0x60, 0xdd, 0x25, 0x43, 0x40, 0x08, 0x6b, 0x10, 0x35, 0x7b, 0x80, 0xc1, 0xcf, 0xbf, 0x31 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.15", + /* Message to be signed */ + 119, + { 0xa9, 0x74, 0x0b, 0x9a, 0xa0, 0xd3, 0x40, 0x58, 0xfd, 0x3b, 0x90, 0x6e, 0x4f, 0x78, 0x59, 0xdf, 0xb0, 0x7d, 0x71, 0x73, 0xe5, 0xe6, 0xf6, 0x35, 0x0a, 0xda, 0xc2, 0x1f, 0x27, 0xb2, 0x30, 0x74, 0x69, 0xbd, 0x0c, 0xe1, 0x95, 0x49, 0xd0, 0x70, 0x01, 0x20, 0xcb, 0xe5, 0x10, 0x77, 0xdb, 0xbb, 0xb0, 0x0a, 0x8d, 0x8b, 0x09, 0xde, 0x8d, 0x83, 0x96, 0xe3, 0x65, 0x07, 0xfe, 0x1e, 0xf6, 0xa1, 0x90, 0x17, 0x54, 0x8e, 0x0c, 0x71, 0x66, 0x74, 0xc2, 0xfe, 0xc2, 0x33, 0xad, 0xb2, 0xf7, 0x75, 0x66, 0x5e, 0xc4, 0x1f, 0x2b, 0xd0, 0xba, 0x39, 0x6b, 0x06, 0x1a, 0x9d, 0xaa, 0x7e, 0x86, 0x6f, 0x7c, 0x23, 0xfd, 0x35, 0x31, 0x95, 0x43, 0x00, 0xa3, 0x42, 0xf9, 0x24, 0x53, 0x5e, 0xa1, 0x49, 0x8c, 0x48, 0xf6, 0xc8, 0x79, 0x93, 0x28 } +, + /* Signature */ + 128, + { 0x4f, 0xbd, 0x4f, 0xb2, 0x37, 0x04, 0xf4, 0x14, 0x9a, 0xda, 0x32, 0x7f, 0xa5, 0x33, 0x88, 0x52, 0x6a, 0x07, 0xdd, 0x43, 0xd9, 0x15, 0xfc, 0xbd, 0xa9, 0xa1, 0x3b, 0xb2, 0xa3, 0x73, 0x8f, 0x4a, 0xdb, 0x1c, 0x3d, 0xb2, 0x6a, 0xb6, 0x90, 0x48, 0x80, 0x5a, 0x80, 0xc8, 0x16, 0x05, 0xc9, 0x6d, 0x68, 0xf8, 0x41, 0x80, 0x2f, 0x5a, 0xbb, 0x02, 0x05, 0x7b, 0x61, 0x1f, 0xe2, 0xf3, 0x94, 0x71, 0x62, 0x65, 0xe5, 0x45, 0x25, 0x2c, 0x23, 0x0c, 0xe4, 0x74, 0xaf, 0xf0, 0xbb, 0xd4, 0xff, 0x1f, 0x38, 0x08, 0x49, 0x60, 0x36, 0xa4, 0x94, 0x8c, 0xa7, 0xa1, 0x10, 0xff, 0x26, 0xc6, 0x38, 0xc5, 0x0f, 0x32, 0x15, 0xb2, 0x8a, 0x09, 0xf2, 0x3a, 0xf6, 0xf8, 0x4c, 0xdc, 0x89, 0x78, 0x98, 0xd0, 0xfd, 0x22, 0x3b, 0x13, 0x48, 0x1f, 0xe8, 0x92, 0xb1, 0xa5, 0x8b, 0xa2, 0xe4, 0xb3, 0x68, 0x5b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.16", + /* Message to be signed */ + 51, + { 0xaf, 0x8f, 0x08, 0x87, 0xc2, 0x19, 0x00, 0x4d, 0x2a, 0xbd, 0x89, 0x4e, 0xa9, 0x25, 0x59, 0xee, 0x31, 0x98, 0xaf, 0x3a, 0x73, 0x4f, 0xe9, 0xb9, 0x63, 0x8c, 0x26, 0x3a, 0x72, 0x8a, 0xd9, 0x5a, 0x5a, 0xe8, 0xce, 0x3e, 0xb1, 0x58, 0x39, 0xf3, 0xaa, 0x78, 0x52, 0xbb, 0x39, 0x07, 0x06, 0xe7, 0x76, 0x0e, 0x43 } +, + /* Signature */ + 128, + { 0x32, 0x7e, 0xc9, 0xd0, 0xbe, 0x7a, 0xab, 0x7b, 0xc9, 0x59, 0xd4, 0x02, 0x27, 0xe1, 0xd0, 0x04, 0x81, 0xfc, 0x04, 0x01, 0x1f, 0xe0, 0x8f, 0xd5, 0x44, 0x9b, 0x90, 0xc0, 0xf0, 0x54, 0xe0, 0xd6, 0x59, 0xb9, 0x26, 0xcc, 0x81, 0x29, 0x21, 0xc2, 0x0a, 0x56, 0x3c, 0x4a, 0xbe, 0x4f, 0x82, 0x5d, 0x6b, 0x5e, 0xef, 0x57, 0xb3, 0xe2, 0xd6, 0x5d, 0x20, 0xa8, 0x01, 0x3a, 0x50, 0xdd, 0x5c, 0x93, 0x23, 0x8c, 0xf0, 0x49, 0xf2, 0xff, 0x0c, 0x7e, 0xbe, 0xb8, 0xe8, 0xca, 0xf7, 0x2e, 0x46, 0xe7, 0xcf, 0x8a, 0x0c, 0x3f, 0x49, 0x25, 0x61, 0x6b, 0x1b, 0xc1, 0x82, 0x6f, 0xfc, 0xb0, 0xbd, 0xa6, 0x0b, 0xbe, 0xbe, 0xdf, 0xd4, 0xc6, 0x0f, 0x27, 0x88, 0xd1, 0x66, 0x6f, 0xb8, 0x45, 0x11, 0x85, 0x36, 0x46, 0xc2, 0xdd, 0x46, 0x68, 0x51, 0xfa, 0xc8, 0x5b, 0xe0, 0xed, 0x5a, 0xce, 0x5f, 0xe2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.17", + /* Message to be signed */ + 115, + { 0x38, 0xdf, 0x86, 0x55, 0x7f, 0x37, 0x5d, 0x09, 0xcc, 0xd8, 0xbd, 0x15, 0xd8, 0xcc, 0xf6, 0x1f, 0x5d, 0x78, 0xca, 0x5c, 0x7f, 0x5c, 0xde, 0x78, 0x2e, 0x6b, 0xf5, 0xd0, 0x05, 0x70, 0x56, 0xd4, 0xba, 0xd9, 0x8b, 0x3d, 0x2f, 0x95, 0x75, 0xe8, 0x24, 0xab, 0x7a, 0x33, 0xff, 0x57, 0xb0, 0xac, 0x10, 0x0a, 0xb0, 0xd6, 0xea, 0xd7, 0xaa, 0x0b, 0x50, 0xf6, 0xe4, 0xd3, 0xe5, 0xec, 0x0b, 0x96, 0x6b, 0x81, 0x57, 0x79, 0xa9, 0x1b, 0x3a, 0x8b, 0xd0, 0x49, 0xbf, 0x2a, 0xeb, 0x92, 0x01, 0x42, 0x77, 0x22, 0x22, 0xc9, 0xca, 0x0c, 0x32, 0x8c, 0x65, 0x9e, 0x0a, 0x64, 0x37, 0x43, 0x3c, 0xce, 0xb7, 0x3c, 0x14, 0x9a, 0xec, 0x4a, 0x74, 0x80, 0xd5, 0xbb, 0xc4, 0x29, 0x20, 0xd7, 0xca, 0x23, 0x5d, 0xb6, 0x74 } +, + /* Signature */ + 128, + { 0x30, 0x46, 0x05, 0x5c, 0x2b, 0x8e, 0xf7, 0xfa, 0x92, 0xc8, 0xa9, 0xe3, 0x95, 0x98, 0x5b, 0xd4, 0x60, 0xfb, 0x6b, 0x47, 0x98, 0x65, 0x53, 0x94, 0x4d, 0x21, 0x04, 0x51, 0x19, 0xf7, 0xe7, 0x61, 0x7e, 0x03, 0xfe, 0x80, 0x87, 0x0a, 0xc6, 0xaa, 0xbf, 0x63, 0xb0, 0x96, 0xca, 0xd5, 0xcc, 0xe7, 0xf5, 0x06, 0x95, 0x3a, 0x7f, 0x69, 0x3f, 0xe1, 0x37, 0xad, 0xfb, 0x97, 0xcd, 0x45, 0x81, 0x28, 0xae, 0x95, 0xc4, 0x7c, 0xa9, 0x48, 0xda, 0xcf, 0x24, 0x03, 0x6a, 0xde, 0xaa, 0x48, 0xf2, 0x9a, 0x46, 0x9f, 0xb5, 0x13, 0x19, 0x1e, 0x05, 0xac, 0xf7, 0x9e, 0x67, 0xa7, 0x93, 0xa3, 0xaf, 0x5e, 0x4f, 0x9c, 0x6d, 0x0d, 0x01, 0xfd, 0xd0, 0xe0, 0xcd, 0x42, 0x96, 0xad, 0x3d, 0xa2, 0xca, 0x89, 0xa5, 0x0e, 0xed, 0xcd, 0x9f, 0x7b, 0x87, 0x7d, 0x2a, 0xe1, 0xd5, 0x8d, 0x98, 0xdc, 0xd7, 0x8f } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.18", + /* Message to be signed */ + 12, + { 0xcb, 0x34, 0xed, 0xd5, 0xab, 0x65, 0x40, 0x41, 0xb6, 0x14, 0x30, 0x56 } +, + /* Signature */ + 128, + { 0x1d, 0xdf, 0x48, 0xba, 0x53, 0x51, 0xbe, 0xd0, 0x79, 0x5f, 0x55, 0xb3, 0x06, 0xaa, 0x1c, 0x6e, 0xd8, 0x36, 0xf5, 0x92, 0xba, 0x93, 0xcf, 0x0c, 0x46, 0xb7, 0xc2, 0x73, 0x70, 0x9d, 0x36, 0xb8, 0xdf, 0xf0, 0x2a, 0xbd, 0xb1, 0xa7, 0x68, 0xd1, 0xc7, 0x11, 0x4a, 0x86, 0xa4, 0x57, 0x49, 0x6d, 0xa5, 0x79, 0xe4, 0xd8, 0x19, 0xf7, 0x2a, 0x19, 0x2e, 0x29, 0x8b, 0xe2, 0x15, 0x2f, 0x7c, 0xf3, 0x9d, 0x1e, 0x30, 0x82, 0x7d, 0x02, 0x82, 0xcc, 0xf3, 0x4d, 0xc8, 0x88, 0x9f, 0x1c, 0x2f, 0x59, 0x70, 0x93, 0x0d, 0x97, 0x35, 0x04, 0x2f, 0x8a, 0x5a, 0x71, 0x22, 0x63, 0x16, 0x5d, 0x6e, 0x6c, 0x50, 0x35, 0xe2, 0xe4, 0xa5, 0x0e, 0x86, 0x3c, 0x06, 0x79, 0x9e, 0x3c, 0x89, 0xcc, 0xb5, 0xcb, 0x0e, 0x70, 0xb3, 0xc9, 0x9c, 0x08, 0x40, 0x30, 0x67, 0x7a, 0x7c, 0x97, 0x90, 0x7a, 0x17, 0x24 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.19", + /* Message to be signed */ + 181, + { 0x5b, 0x09, 0xec, 0x88, 0xb1, 0x52, 0x71, 0x78, 0xfa, 0x04, 0x32, 0x63, 0xf3, 0x06, 0x7d, 0x9f, 0xfe, 0x97, 0x30, 0x32, 0xa9, 0x9f, 0x4c, 0xb0, 0x8a, 0xd2, 0xc7, 0xe0, 0xa2, 0x45, 0x6c, 0xdd, 0x57, 0xa7, 0xdf, 0x56, 0xfe, 0x60, 0x53, 0x52, 0x7a, 0x5a, 0xeb, 0x67, 0xd7, 0xe5, 0x52, 0x06, 0x3c, 0x1c, 0xa9, 0x7b, 0x1b, 0xef, 0xfa, 0x7b, 0x39, 0xe9, 0x97, 0xca, 0xf2, 0x78, 0x78, 0xea, 0x0f, 0x62, 0xcb, 0xeb, 0xc8, 0xc2, 0x1d, 0xf4, 0xc8, 0x89, 0xa2, 0x02, 0x85, 0x1e, 0x94, 0x90, 0x88, 0x49, 0x0c, 0x24, 0x9b, 0x6e, 0x9a, 0xcf, 0x1d, 0x80, 0x63, 0xf5, 0xbe, 0x23, 0x43, 0x98, 0x9b, 0xf9, 0x5c, 0x4d, 0xa0, 0x1a, 0x2b, 0xe7, 0x8b, 0x4a, 0xb6, 0xb3, 0x78, 0x01, 0x5b, 0xc3, 0x79, 0x57, 0xf7, 0x69, 0x48, 0xb5, 0xe5, 0x8e, 0x44, 0x0c, 0x28, 0x45, 0x3d, 0x40, 0xd7, 0xcf, 0xd5, 0x7e, 0x7d, 0x69, 0x06, 0x00, 0x47, 0x4a, 0xb5, 0xe7, 0x59, 0x73, 0xb1, 0xea, 0x0c, 0x5f, 0x1e, 0x45, 0xd1, 0x41, 0x90, 0xaf, 0xe2, 0xf4, 0xeb, 0x6d, 0x3b, 0xdf, 0x71, 0xf1, 0xd2, 0xf8, 0xbb, 0x15, 0x6a, 0x1c, 0x29, 0x5d, 0x04, 0xaa, 0xeb, 0x9d, 0x68, 0x9d, 0xce, 0x79, 0xed, 0x62, 0xbc, 0x44, 0x3e, 0xe2, 0x0c } +, + /* Signature */ + 128, + { 0xaf, 0x56, 0xfc, 0x32, 0x97, 0x39, 0xe2, 0xf7, 0x75, 0x4b, 0x6c, 0xa2, 0x51, 0x64, 0xa6, 0xfa, 0x58, 0xf6, 0x85, 0xdd, 0xb7, 0x42, 0xb4, 0x84, 0x1d, 0x73, 0xa5, 0xe2, 0xc4, 0xc4, 0x53, 0x43, 0xb7, 0x4d, 0xfd, 0x2f, 0x0d, 0x37, 0x0e, 0xdd, 0xdd, 0x36, 0xa0, 0x17, 0x56, 0x4a, 0x8d, 0x3a, 0xd4, 0x02, 0xe2, 0xa3, 0x41, 0xc9, 0x72, 0x06, 0x2c, 0x23, 0x81, 0x4a, 0x00, 0x13, 0x1e, 0x17, 0xb1, 0xde, 0xc7, 0xb4, 0xc5, 0x7c, 0x5b, 0xf1, 0xd4, 0xfa, 0x79, 0x22, 0x29, 0x37, 0xa4, 0xdc, 0x5c, 0x00, 0x23, 0x5f, 0x85, 0x3d, 0xd2, 0x3d, 0xc9, 0x75, 0x7f, 0x33, 0x5c, 0x85, 0xc2, 0x07, 0xeb, 0x07, 0x4d, 0x4b, 0xcc, 0x24, 0x3e, 0xda, 0xa7, 0x83, 0x1b, 0x83, 0x13, 0x56, 0x55, 0xe2, 0x27, 0x7e, 0xf2, 0x9e, 0x7a, 0xeb, 0xf3, 0x4a, 0x0f, 0x7b, 0x23, 0x4a, 0x28, 0x65, 0x0a, 0x30 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 4.20", + /* Message to be signed */ + 17, + { 0x3c, 0x33, 0x0c, 0x1e, 0xf7, 0x18, 0xc1, 0x41, 0xe4, 0x7b, 0x8f, 0xa8, 0x59, 0xbe, 0x4d, 0x5b, 0x96 } +, + /* Signature */ + 128, + { 0x0b, 0x10, 0x22, 0xdc, 0x38, 0xe2, 0x17, 0xfd, 0x3b, 0x0e, 0x7e, 0xf1, 0x9d, 0xfc, 0xb4, 0xb4, 0x56, 0x36, 0x62, 0x40, 0x98, 0x30, 0x95, 0xf6, 0xdb, 0x96, 0x58, 0x31, 0xa7, 0x0f, 0x0f, 0x8e, 0x20, 0xe2, 0xdd, 0x2a, 0xc2, 0x31, 0xcc, 0x37, 0x90, 0x45, 0xc2, 0x73, 0x65, 0xe7, 0x3a, 0x53, 0x71, 0x9b, 0xb6, 0xf0, 0x11, 0xc3, 0xf8, 0x63, 0x6b, 0x64, 0x99, 0x4c, 0xa4, 0x80, 0x60, 0x2f, 0xb3, 0xb4, 0xf0, 0xe2, 0x27, 0x4b, 0x58, 0xb3, 0x63, 0xe0, 0xd3, 0x08, 0xb5, 0x28, 0xe1, 0x58, 0x59, 0xa9, 0x1d, 0xcf, 0x99, 0xbf, 0xfe, 0xfb, 0xc8, 0x05, 0x22, 0x41, 0xb9, 0x74, 0x19, 0x2e, 0x63, 0x62, 0x18, 0xf3, 0x98, 0x33, 0x2d, 0xaf, 0xe8, 0x25, 0x9c, 0xa5, 0xf5, 0xcc, 0xfa, 0x54, 0xc9, 0xb3, 0x2b, 0x27, 0x35, 0xaf, 0x07, 0x24, 0xf4, 0x0b, 0x5a, 0x5d, 0x61, 0x21, 0xa4, 0x0d } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 5: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xc5, 0x5f, 0xfb, 0xdd, 0x6a, 0x27, 0x53, 0xbc, 0x02, 0xaf, 0x20, 0xae, 0x18, 0xea, 0x0d, 0xaf, 0x23, 0x0b, 0xb6, 0xf8, 0x79, 0x5d, 0x05, 0xef, 0xec, 0xc8, 0x15, 0xba, 0xec, 0xe2, 0x2b, 0x38, 0x79, 0x99, 0x5f, 0x6d, 0x97, 0x64, 0xc1, 0xdf, 0x8f, 0x97, 0x85, 0x13, 0x81, 0x68, 0x62, 0x66, 0xb8, 0x09, 0x2f, 0xb6, 0x01, 0x18, 0x98, 0xa7, 0x67, 0x07, 0xa4, 0xd1, 0xd5, 0xbd, 0xa0, 0x8d, 0x24, 0x6c, 0x68, 0x7a, 0x8b, 0xba, 0xfa, 0x63, 0x98, 0xac, 0x9e, 0xa2, 0x72, 0x68, 0x23, 0x71, 0x4a, 0x0c, 0x39, 0x34, 0xca, 0x6e, 0x5f, 0x8c, 0xe3, 0x39, 0x87, 0xb5, 0x34, 0x85, 0x7e, 0xa9, 0xf8, 0x5c, 0xc4, 0xe1, 0x9a, 0x1d, 0x21, 0x83, 0xe0, 0xe4, 0xc8, 0xaa, 0x55, 0xcb, 0x22, 0x7b, 0x0e, 0x56, 0xce, 0xb2, 0xb6, 0x2b, 0x30, 0xef, 0xc7, 0x88, 0x64, 0xb2, 0xf9, 0xfb, 0x92, 0x49 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x07, 0xe3, 0xfa, 0x71, 0xb3, 0x98, 0xb6, 0xe4, 0x41, 0x47, 0x37, 0x0b, 0x3e, 0xbb, 0xbc, 0xa8, 0x4f, 0xc2, 0x5c, 0x22, 0x3a, 0xd7, 0xd9, 0x30, 0xea, 0x4a, 0x65, 0x73, 0xff, 0x9c, 0x5b, 0x15, 0xfa, 0xe6, 0x82, 0xc6, 0x22, 0xd3, 0x48, 0x5c, 0xe3, 0xa4, 0xaf, 0x11, 0x44, 0x8f, 0x23, 0xbf, 0xef, 0x83, 0x8e, 0x80, 0xbc, 0x32, 0x7b, 0x87, 0xd5, 0xba, 0x9c, 0x80, 0x37, 0x07, 0x49, 0xaf, 0xc8, 0xc1, 0xc0, 0x17, 0x54, 0x6f, 0xc6, 0xb6, 0x59, 0x31, 0xb7, 0x59, 0xca, 0x43, 0x41, 0xfa, 0x5e, 0x5e, 0x10, 0xb2, 0x40, 0x87, 0xe6, 0xe2, 0xc0, 0xf4, 0xdb, 0xb7, 0x90, 0x69, 0x52, 0x99, 0x9c, 0xbd, 0x90, 0xd2, 0x43, 0x5f, 0xca, 0xcc, 0x9c, 0x82, 0xe4, 0x8f, 0xdf, 0x24, 0xe4, 0x95, 0xcf, 0xf3, 0x0a, 0xd4, 0x19, 0xe7, 0x12, 0x3e, 0x3a, 0xc9, 0x42, 0x27, 0x2e, 0x1a, 0xba, 0xb1 } +, + /* Prime 1 */ + 64, + { 0xf7, 0xf7, 0xc0, 0x02, 0xf0, 0x19, 0x6e, 0xcd, 0xd7, 0x1b, 0xa5, 0xad, 0x74, 0x2b, 0x69, 0x48, 0x27, 0xd2, 0x88, 0xaf, 0x1b, 0x1b, 0xb6, 0x9c, 0x5e, 0xd7, 0xfb, 0x22, 0x9d, 0xee, 0x4b, 0x7a, 0x32, 0xf2, 0xf7, 0x56, 0x8a, 0x6f, 0xca, 0xf3, 0x83, 0xd8, 0x9a, 0xda, 0x9f, 0xc1, 0x4a, 0x7b, 0xa5, 0xd0, 0xa4, 0xa4, 0x6c, 0x2c, 0x54, 0x3e, 0xec, 0x17, 0x75, 0x49, 0xc8, 0xa0, 0x48, 0xb7 } +, + /* Prime 2 */ + 64, + { 0xcb, 0xc4, 0xb2, 0x86, 0x04, 0x76, 0xa2, 0xd3, 0xe8, 0xa4, 0xda, 0x21, 0x00, 0x16, 0xca, 0xce, 0xd0, 0xe3, 0x67, 0xcb, 0x86, 0x77, 0x10, 0xa4, 0xb5, 0xaa, 0x2d, 0xf2, 0xb8, 0xe5, 0xda, 0xf5, 0xfd, 0xc6, 0x47, 0x80, 0x7d, 0x4d, 0x5e, 0xbb, 0x6c, 0x56, 0xb9, 0x76, 0x3c, 0xcd, 0xae, 0x4d, 0xea, 0x33, 0x08, 0xeb, 0x0a, 0xc2, 0xa8, 0x95, 0x01, 0xcb, 0x20, 0x9d, 0x26, 0x39, 0xfc, 0xff } +, + /* Prime exponent 1 */ + 64, + { 0x6c, 0x76, 0x27, 0xbc, 0xa1, 0x3c, 0xde, 0xa4, 0x96, 0xa4, 0x77, 0x31, 0x89, 0x90, 0xbb, 0x7a, 0x5e, 0x40, 0xce, 0x9c, 0x99, 0x24, 0xe4, 0x19, 0x3d, 0xbb, 0x07, 0x14, 0x3b, 0x34, 0x52, 0x3b, 0x5f, 0x31, 0xbb, 0x52, 0x55, 0x37, 0x54, 0xf4, 0x73, 0x05, 0x39, 0xa6, 0xcb, 0x1e, 0x06, 0xf0, 0x52, 0xb5, 0x12, 0x6f, 0x01, 0x09, 0xda, 0xc7, 0xb3, 0x09, 0x07, 0xba, 0x80, 0x50, 0xeb, 0xbd } +, + /* Prime exponent 2 */ + 64, + { 0x40, 0x92, 0x74, 0x80, 0x43, 0xa9, 0xd4, 0xaf, 0x92, 0x69, 0xab, 0x36, 0x09, 0xf1, 0x2f, 0x13, 0x9a, 0xde, 0x75, 0x65, 0xe9, 0x96, 0x91, 0x8f, 0xa0, 0x81, 0xed, 0x4d, 0x9d, 0x8a, 0x39, 0x78, 0xfa, 0x92, 0x7a, 0xd6, 0x1c, 0xdf, 0x07, 0xc6, 0x1c, 0xee, 0xde, 0x96, 0xb9, 0x6d, 0xf4, 0x6e, 0x7c, 0x68, 0xef, 0xca, 0x8b, 0xfe, 0x63, 0xad, 0xd4, 0x83, 0xaa, 0x32, 0x22, 0x8a, 0xfd, 0xc1 } +, + /* Coefficient */ + 64, + { 0x2a, 0x61, 0x94, 0xca, 0x29, 0x70, 0x72, 0x38, 0x45, 0xff, 0xf3, 0x8c, 0xa1, 0xa9, 0xa3, 0xb5, 0x66, 0xb4, 0x24, 0x5d, 0xe2, 0xf9, 0x01, 0x34, 0xb8, 0xe6, 0xae, 0xc8, 0xae, 0x07, 0xf3, 0xbb, 0x7c, 0x5e, 0x5a, 0xe6, 0xe1, 0x83, 0x34, 0x85, 0xe5, 0x5d, 0x8c, 0xa6, 0x0c, 0xe1, 0x64, 0x2f, 0x72, 0x75, 0x96, 0x8e, 0x66, 0x12, 0x38, 0x35, 0x52, 0x11, 0xc6, 0x38, 0x48, 0x94, 0x0f, 0x3c } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 5.1", + /* Message to be signed */ + 187, + { 0xea, 0xe9, 0xa4, 0x0b, 0xff, 0x18, 0x3f, 0x41, 0x14, 0x73, 0x2e, 0x7b, 0x3b, 0xa5, 0x56, 0xf4, 0xce, 0x28, 0x8d, 0xaa, 0x83, 0xe3, 0xff, 0x23, 0x61, 0x12, 0x44, 0xa7, 0xa0, 0x90, 0x1f, 0x11, 0x7d, 0x86, 0xc0, 0x9c, 0x33, 0xa5, 0x23, 0x2b, 0xd3, 0x20, 0xfa, 0x37, 0xa2, 0x38, 0xa8, 0xaa, 0x62, 0xdd, 0x21, 0xab, 0xbf, 0xac, 0xdb, 0x93, 0xfa, 0x1c, 0x44, 0xcc, 0x55, 0xac, 0x61, 0xbe, 0xa2, 0x4a, 0x6a, 0x34, 0xcc, 0x64, 0x76, 0x75, 0x38, 0x37, 0xe1, 0x6f, 0xac, 0xd8, 0x2e, 0xb4, 0x9e, 0x1c, 0x57, 0xc9, 0x58, 0xfb, 0xbf, 0xf5, 0x68, 0x88, 0x7c, 0xf8, 0x2e, 0xeb, 0xe9, 0x61, 0xe5, 0x80, 0xe0, 0x64, 0xdb, 0x9c, 0xbe, 0xc3, 0xb5, 0x3d, 0xf1, 0xf2, 0x71, 0x99, 0xe4, 0x9a, 0x04, 0xcb, 0xe5, 0x9c, 0x69, 0xa2, 0x65, 0xcf, 0xac, 0x8c, 0xe4, 0xf9, 0x1c, 0xa9, 0x5d, 0x52, 0xb1, 0x14, 0x5c, 0x8b, 0x9f, 0x44, 0x40, 0xb3, 0x9c, 0x18, 0x50, 0x94, 0xbe, 0x18, 0x48, 0x74, 0xda, 0x59, 0x71, 0xd7, 0xd7, 0x63, 0xfe, 0x07, 0xce, 0x16, 0xe5, 0x7f, 0x1e, 0x50, 0xd2, 0x28, 0x65, 0x04, 0xb4, 0x81, 0xe2, 0xc6, 0x85, 0xbc, 0x9d, 0x9c, 0x01, 0x49, 0x3f, 0xd3, 0xa6, 0xd8, 0xbb, 0x9b, 0x2e, 0x96, 0xbf, 0xde, 0xb6, 0xc9, 0x29, 0x14, 0xca } +, + /* Signature */ + 128, + { 0x44, 0xce, 0xb4, 0x42, 0x24, 0x2b, 0xae, 0x08, 0x59, 0x94, 0xea, 0xd0, 0x7b, 0x70, 0x95, 0x43, 0xea, 0x23, 0x95, 0xa6, 0xe8, 0xd4, 0x64, 0x73, 0xd7, 0x0d, 0xf3, 0x4a, 0x95, 0x55, 0xaa, 0x56, 0x7f, 0x4d, 0xa1, 0x38, 0xe9, 0x63, 0xfe, 0x92, 0x86, 0xa8, 0x4f, 0xb7, 0xc5, 0xcf, 0x82, 0x00, 0x03, 0x59, 0x04, 0xb5, 0x0c, 0x32, 0x40, 0x3c, 0xae, 0x51, 0x7b, 0xfa, 0x7f, 0xca, 0x8a, 0x66, 0xfc, 0xfd, 0x63, 0x2a, 0xf7, 0x47, 0xc4, 0x9c, 0xdf, 0xb0, 0xb9, 0xae, 0xe3, 0x52, 0x28, 0xb7, 0xdc, 0x4c, 0x21, 0x00, 0x39, 0x69, 0xb0, 0xa0, 0x13, 0xed, 0xe1, 0x29, 0x2b, 0x65, 0xd1, 0x0a, 0x50, 0xc9, 0x02, 0x63, 0xfb, 0x0b, 0xf4, 0xf4, 0xb8, 0x37, 0x66, 0x41, 0xb0, 0x3e, 0x1f, 0xaf, 0xb8, 0x83, 0xf0, 0x38, 0xf4, 0x32, 0x3d, 0xfe, 0x5b, 0xea, 0xc4, 0x68, 0xde, 0xea, 0x99, 0xc3 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 5.2", + /* Message to be signed */ + 92, + { 0x9d, 0xe5, 0xca, 0x46, 0x74, 0x85, 0x61, 0xa0, 0xb9, 0x28, 0xb2, 0x60, 0xa9, 0x5a, 0x3e, 0xd9, 0x20, 0xad, 0xc8, 0xd5, 0xee, 0xb9, 0x27, 0x1d, 0xc7, 0x1b, 0xc1, 0x4f, 0x69, 0xcc, 0xd6, 0x31, 0x1d, 0x18, 0x6a, 0x77, 0x9f, 0x5e, 0xb8, 0xdb, 0x17, 0xc6, 0x90, 0xd6, 0x86, 0x7c, 0xf3, 0x36, 0x9b, 0xbf, 0xf1, 0x5f, 0xab, 0xb3, 0xcd, 0x2c, 0xfd, 0xd6, 0xf7, 0xd7, 0x52, 0x86, 0xff, 0x2d, 0x24, 0x99, 0xc5, 0xab, 0xb4, 0x8e, 0xd5, 0x4f, 0xd4, 0xd8, 0x49, 0xa9, 0x18, 0x0e, 0x11, 0x0e, 0x0a, 0x53, 0xa7, 0x21, 0x39, 0x82, 0x92, 0x11, 0x0f, 0xe8, 0xbe, 0x26 } +, + /* Signature */ + 128, + { 0x44, 0x5f, 0xf5, 0xb6, 0x87, 0x9f, 0x8c, 0xe7, 0x53, 0x95, 0x01, 0x6f, 0x04, 0x95, 0xf1, 0x31, 0x35, 0xb1, 0x79, 0xe7, 0x3a, 0x3c, 0xae, 0xb3, 0x30, 0xe3, 0xcd, 0xa7, 0xf3, 0x1f, 0x1d, 0xcb, 0xa7, 0xaa, 0x82, 0xe2, 0x68, 0xc9, 0x35, 0xe9, 0xd7, 0x01, 0x4e, 0x0b, 0x0d, 0xce, 0xa6, 0x9c, 0x7b, 0x96, 0x8a, 0xdb, 0x17, 0x42, 0x4a, 0x64, 0xdf, 0xd1, 0xe2, 0xbc, 0x57, 0x07, 0xf9, 0x20, 0xfc, 0x0c, 0x83, 0xcc, 0x63, 0xdf, 0xc7, 0x4b, 0x96, 0x3e, 0x68, 0x2b, 0x46, 0xa2, 0x2a, 0xc2, 0x56, 0xac, 0x6b, 0xe5, 0x70, 0x9c, 0x07, 0xcf, 0xcc, 0x3d, 0x4e, 0xba, 0x3a, 0x1d, 0x61, 0xab, 0x15, 0xf1, 0xba, 0xdb, 0x0a, 0x49, 0xfb, 0x5c, 0xf0, 0x9a, 0x1f, 0x74, 0x81, 0xa3, 0xaa, 0xea, 0xf7, 0xc2, 0x57, 0x54, 0x03, 0x77, 0xae, 0xa7, 0xb5, 0x44, 0x17, 0xa6, 0x09, 0xc7, 0x6f, 0x4c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.3", + /* Message to be signed */ + 232, + { 0x18, 0x3b, 0xa1, 0xa3, 0x81, 0x1d, 0x62, 0x5c, 0xa9, 0xda, 0x1b, 0xba, 0xae, 0xdc, 0x76, 0x19, 0x20, 0x12, 0xfc, 0xb6, 0x74, 0xbb, 0x9e, 0x77, 0xd8, 0xf3, 0x77, 0x08, 0xd2, 0x40, 0xd3, 0x49, 0xe0, 0x57, 0x97, 0x41, 0x6f, 0xeb, 0x24, 0xe3, 0x01, 0x8c, 0x7a, 0x20, 0x5d, 0x05, 0x9d, 0xe8, 0xe0, 0xae, 0x05, 0xa8, 0xd7, 0xe0, 0x9e, 0xaf, 0xee, 0xb9, 0xf0, 0x6d, 0xe5, 0xd4, 0x28, 0x7a, 0xbb, 0xef, 0x05, 0x9b, 0xc5, 0x86, 0xb2, 0x1c, 0x82, 0xd6, 0x4a, 0xec, 0xe8, 0xd7, 0x42, 0x8a, 0xfc, 0xd7, 0xb2, 0x2f, 0xc5, 0xd1, 0x68, 0xbc, 0x07, 0x6b, 0x61, 0x5f, 0x02, 0x73, 0x3c, 0xb6, 0x31, 0x25, 0xc8, 0xf3, 0x6d, 0x5c, 0xb8, 0x09, 0xce, 0x80, 0x65, 0x08, 0x23, 0x98, 0xb3, 0x88, 0x5a, 0x89, 0x19, 0x57, 0x0c, 0x47, 0x8a, 0x07, 0x2f, 0x59, 0x66, 0x15, 0xd7, 0x8f, 0x01, 0x36, 0xd1, 0x1b, 0xe3, 0x2b, 0x3f, 0xe0, 0xf4, 0xfb, 0xe3, 0xc7, 0xda, 0x5d, 0x81, 0x34, 0x19, 0x10, 0x17, 0x7e, 0x48, 0xb1, 0xbb, 0xac, 0x27, 0x6c, 0x12, 0xee, 0x81, 0x54, 0x65, 0xdc, 0x67, 0xd4, 0x53, 0x24, 0xf9, 0x05, 0xaa, 0xca, 0x48, 0x38, 0xd8, 0x1f, 0x74, 0x31, 0x46, 0x3e, 0x89, 0xeb, 0x8b, 0x95, 0x36, 0x58, 0x69, 0x36, 0xaf, 0xb4, 0x2c, 0xb4, 0x7b, 0xd8, 0xc3, 0x18, 0x29, 0xd3, 0x1e, 0xc1, 0xee, 0x29, 0xf9, 0x1c, 0xcc, 0x6d, 0xf9, 0xcd, 0x1b, 0x0b, 0x9b, 0x86, 0x46, 0xb6, 0x02, 0x67, 0xfd, 0x7e, 0xce, 0xae, 0x92, 0xc0, 0xae, 0x9e, 0x0c, 0xe5, 0xff, 0x6f, 0x7e, 0x0b, 0xf7, 0x56, 0xa9, 0xb8, 0xff, 0xc9, 0xc6, 0x16 } +, + /* Signature */ + 128, + { 0xab, 0x4b, 0x78, 0x96, 0x4c, 0x2a, 0x35, 0xd3, 0x28, 0x55, 0xe0, 0xef, 0xce, 0xd3, 0x4b, 0xf8, 0x02, 0x19, 0xb5, 0x8c, 0x48, 0x8e, 0xa3, 0x75, 0xb1, 0xf3, 0x27, 0x16, 0x6a, 0x51, 0x35, 0xe5, 0xda, 0x99, 0x45, 0xc2, 0x87, 0x29, 0x7a, 0x3d, 0x93, 0x2e, 0x57, 0x27, 0x46, 0xf0, 0x22, 0x74, 0x8b, 0x85, 0x58, 0x5a, 0x0a, 0xbd, 0x91, 0x86, 0xf4, 0xac, 0x35, 0xed, 0xc8, 0x50, 0xd2, 0xfd, 0x88, 0x05, 0xb9, 0xe9, 0xf5, 0x1a, 0x5a, 0xdc, 0xb9, 0x5e, 0x1a, 0xc1, 0x72, 0x9e, 0x57, 0xb8, 0x53, 0x31, 0xc1, 0xed, 0x15, 0xc3, 0xd0, 0xcf, 0xae, 0x33, 0xf6, 0x1c, 0x11, 0x9b, 0x55, 0xc9, 0x5e, 0x34, 0x4b, 0x72, 0xf2, 0xb4, 0xf8, 0xe7, 0xe8, 0xfa, 0xc7, 0xa3, 0x3e, 0x5b, 0x8b, 0x27, 0x6a, 0x60, 0x88, 0xa7, 0xfa, 0xbf, 0x4f, 0xa1, 0x72, 0x35, 0x7f, 0xb6, 0xe3, 0xf4, 0x4a, 0x94 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.4", + /* Message to be signed */ + 215, + { 0x87, 0x07, 0xdc, 0xdb, 0x49, 0xd2, 0x83, 0xa2, 0x3a, 0x9b, 0xd6, 0xff, 0x87, 0xaf, 0xf8, 0x34, 0xf0, 0x6f, 0xf7, 0xf4, 0x7b, 0x0e, 0x5f, 0x57, 0xff, 0x1a, 0x0d, 0x99, 0x5b, 0xba, 0x9c, 0xdd, 0x5e, 0xa0, 0x1b, 0x42, 0xb2, 0x5d, 0x6f, 0xf1, 0x7a, 0x0d, 0xc1, 0x06, 0x05, 0xcf, 0x45, 0x2a, 0xca, 0x73, 0xbe, 0x54, 0xed, 0x5e, 0x0c, 0xe2, 0x15, 0x66, 0xaf, 0xcc, 0x17, 0x91, 0x2a, 0xbe, 0x18, 0xdf, 0xac, 0xd1, 0xbc, 0x03, 0xe3, 0xe2, 0x88, 0x2a, 0x4b, 0xb3, 0xa4, 0xf3, 0x9e, 0xea, 0xf9, 0x63, 0xd7, 0xc3, 0x5e, 0x6b, 0xa8, 0x58, 0xb1, 0x37, 0x6a, 0x07, 0x51, 0x60, 0xc6, 0xcf, 0xae, 0xd5, 0xe8, 0xc5, 0x2e, 0x45, 0x11, 0x32, 0x34, 0x72, 0x19, 0xbd, 0x88, 0x89, 0x3e, 0xeb, 0xe3, 0x56, 0x59, 0xa0, 0xee, 0x4d, 0x94, 0xf9, 0x4d, 0x03, 0x5b, 0x7a, 0x86, 0x86, 0xff, 0xb4, 0x16, 0xeb, 0x99, 0xfb, 0x2a, 0xaa, 0x81, 0x23, 0x6b, 0x05, 0xac, 0x46, 0x45, 0x92, 0x5f, 0x2c, 0x2b, 0xc1, 0x9e, 0xbe, 0x89, 0xa6, 0x3f, 0x2f, 0x45, 0x1d, 0x0b, 0x13, 0xb2, 0xfe, 0xf0, 0x61, 0xe5, 0x30, 0xa3, 0x49, 0xba, 0xf3, 0xb2, 0x35, 0x64, 0x22, 0xb0, 0x95, 0xfd, 0x9f, 0x19, 0x29, 0x93, 0xab, 0x99, 0xc9, 0xf9, 0x22, 0x6e, 0xf9, 0xa7, 0xb3, 0xcf, 0xb3, 0x65, 0x82, 0x08, 0x59, 0x29, 0xc8, 0x76, 0xb5, 0xe9, 0xd7, 0xc6, 0xac, 0xac, 0x7b, 0xb0, 0x27, 0x52, 0x34, 0xe4, 0x1e, 0xd3, 0x51, 0xc8, 0x38, 0xb7, 0xa3, 0x1a } +, + /* Signature */ + 128, + { 0x17, 0x53, 0x98, 0x8b, 0x39, 0xdc, 0x74, 0x5d, 0xf9, 0x69, 0x1a, 0xf9, 0xee, 0x69, 0xca, 0xda, 0x73, 0xa9, 0x87, 0x7c, 0xca, 0x12, 0xf6, 0xd4, 0x06, 0x27, 0xdc, 0xed, 0x76, 0x22, 0x14, 0x7e, 0xc9, 0x01, 0xa5, 0xb4, 0x63, 0xe7, 0xef, 0x9b, 0x37, 0xfb, 0xd6, 0x92, 0x78, 0x5a, 0xa2, 0x2a, 0x46, 0x5d, 0xf4, 0x03, 0xaf, 0x92, 0xa2, 0x9f, 0x79, 0x5d, 0x40, 0xa8, 0x3f, 0xa9, 0x64, 0xb8, 0x5a, 0x7e, 0xc0, 0x5a, 0x3c, 0xda, 0xe3, 0xf8, 0xbc, 0x8a, 0x61, 0xa7, 0x9d, 0xc8, 0x42, 0xe1, 0xd3, 0x77, 0xbc, 0x5e, 0x1d, 0x46, 0xad, 0xaa, 0xa8, 0x66, 0xbe, 0x28, 0x2c, 0x6e, 0x23, 0x88, 0x17, 0x36, 0x44, 0xf4, 0x06, 0x27, 0xbc, 0xf8, 0xa0, 0x97, 0x4a, 0x4b, 0xe8, 0xfc, 0xc4, 0x8a, 0xee, 0x7e, 0x82, 0x59, 0xf8, 0x68, 0xa2, 0xbd, 0x78, 0x9a, 0x90, 0x89, 0x92, 0x05, 0x6e, 0x55 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.5", + /* Message to be signed */ + 246, + { 0xac, 0x9f, 0xa3, 0xf6, 0x3d, 0xf0, 0x68, 0xe9, 0x0d, 0x69, 0x2e, 0xcc, 0xfa, 0x7d, 0x87, 0x96, 0x49, 0x1a, 0xca, 0x79, 0x5b, 0x98, 0x58, 0xa4, 0x55, 0x18, 0x62, 0x32, 0x29, 0xaf, 0x28, 0xb1, 0x3a, 0x50, 0x2d, 0x8c, 0xb3, 0xb9, 0x50, 0x92, 0x50, 0x58, 0x82, 0xeb, 0x99, 0x4d, 0xe7, 0x46, 0x59, 0x62, 0x56, 0x98, 0xa0, 0x05, 0x04, 0x17, 0x94, 0x0d, 0x8b, 0xfa, 0x28, 0xa3, 0xf9, 0x3d, 0x14, 0x9f, 0xf8, 0xb0, 0xbb, 0x39, 0x26, 0xf6, 0x18, 0xef, 0x91, 0x96, 0x6f, 0x4d, 0x39, 0xbd, 0xba, 0x5a, 0x05, 0x17, 0xdd, 0xeb, 0xb1, 0x6d, 0x2b, 0xc4, 0xb4, 0xe3, 0x3a, 0x7d, 0x61, 0x9c, 0x95, 0xa3, 0x3c, 0xf5, 0xf5, 0x72, 0xdb, 0xe0, 0x7f, 0xab, 0x4a, 0xa6, 0x7f, 0xb3, 0xf3, 0x9a, 0xa2, 0x98, 0x1a, 0x3d, 0xc0, 0xca, 0xee, 0x64, 0x75, 0x8e, 0xa8, 0x98, 0xeb, 0xce, 0x10, 0xbf, 0x3a, 0xa4, 0xfc, 0x84, 0x49, 0xe8, 0xe0, 0xcf, 0x7e, 0x88, 0xb1, 0x88, 0x23, 0x8c, 0x20, 0x68, 0xef, 0xac, 0xeb, 0xfe, 0xef, 0x40, 0x73, 0xa6, 0x54, 0xa5, 0x8a, 0x30, 0x99, 0xd0, 0x36, 0xae, 0xee, 0x2d, 0x81, 0x82, 0x98, 0xd4, 0xab, 0x39, 0x23, 0x8e, 0xdc, 0x45, 0x9a, 0x9f, 0xd3, 0x57, 0x7e, 0x9f, 0x5b, 0xfc, 0x03, 0x68, 0xaa, 0x65, 0x7a, 0xee, 0xda, 0x1e, 0xeb, 0x8a, 0xe7, 0xf5, 0xac, 0x1e, 0xaf, 0x3b, 0x1c, 0x95, 0x81, 0x7d, 0xde, 0x2e, 0xc1, 0xa5, 0x9f, 0xcb, 0x5e, 0xf2, 0x7c, 0xc3, 0x4f, 0xb7, 0x53, 0x31, 0xda, 0x7a, 0x49, 0x96, 0x92, 0x5a, 0xc3, 0xad, 0x17, 0xbb, 0xc3, 0xda, 0xfe, 0x6a, 0x9c, 0x64, 0x4e, 0x30, 0x98, 0xef, 0xfe, 0xf8, 0xfe, 0xa5, 0xcc, 0x0d, 0x5f, 0x0c, 0x04, 0x8e, 0x10, 0x88 } +, + /* Signature */ + 128, + { 0x11, 0xe1, 0xa8, 0x28, 0xf0, 0x0a, 0x98, 0x7e, 0x03, 0xd6, 0x2e, 0x2a, 0x53, 0x6c, 0x29, 0x7d, 0xda, 0xc0, 0x22, 0xe0, 0x63, 0xee, 0x0d, 0xe4, 0xe4, 0x69, 0x5d, 0xed, 0x1f, 0xdb, 0x22, 0x09, 0x00, 0xa3, 0xac, 0x3f, 0x87, 0xd1, 0xbe, 0x75, 0xf9, 0x59, 0xc2, 0x8b, 0x57, 0x8a, 0x43, 0xb2, 0x56, 0x64, 0x3c, 0xdf, 0xff, 0x92, 0x15, 0x95, 0xfd, 0xfb, 0xea, 0xf4, 0x10, 0xc2, 0xae, 0xd9, 0xe5, 0xe4, 0x7e, 0x1d, 0x15, 0x1a, 0xe2, 0x8c, 0x76, 0x99, 0xae, 0xe2, 0x25, 0xa6, 0x45, 0xbc, 0x42, 0xb3, 0xbe, 0xb5, 0x2f, 0x08, 0x38, 0x7e, 0xc5, 0x54, 0xd0, 0x20, 0x4d, 0x28, 0x3c, 0x3b, 0xcc, 0xbc, 0xca, 0x21, 0x6e, 0xda, 0xd9, 0x4e, 0xc6, 0x4f, 0x9c, 0x20, 0xb3, 0x40, 0x6a, 0xb7, 0x8a, 0x6c, 0x4a, 0x4d, 0xae, 0x3f, 0xa6, 0x17, 0xa0, 0x0c, 0x6a, 0xb2, 0xf8, 0xe2, 0x47, 0x62 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.6", + /* Message to be signed */ + 16, + { 0x15, 0x74, 0x69, 0x73, 0x44, 0xe9, 0x86, 0x85, 0xcd, 0x6e, 0x65, 0xe4, 0x67, 0x83, 0xf0, 0xb5 } +, + /* Signature */ + 128, + { 0x3b, 0x7d, 0x67, 0xd1, 0x3c, 0xd3, 0xc0, 0xfd, 0x30, 0x5a, 0xd4, 0x04, 0xd8, 0xa3, 0xdc, 0xde, 0x4a, 0x45, 0x17, 0x9c, 0x2d, 0x0b, 0x87, 0x11, 0x5d, 0x6d, 0x06, 0x0c, 0x24, 0x9b, 0x87, 0xf3, 0x9e, 0x46, 0x3b, 0x76, 0x4b, 0x42, 0x07, 0xc4, 0x8a, 0x74, 0xcf, 0xce, 0x25, 0x31, 0xe8, 0x18, 0x3d, 0x3d, 0x01, 0x25, 0x85, 0xce, 0x57, 0x39, 0xd1, 0x62, 0xc4, 0xea, 0x22, 0x32, 0x44, 0x02, 0xea, 0x2e, 0x6e, 0xaf, 0xb8, 0xa5, 0x73, 0xfc, 0xff, 0x40, 0x15, 0xc9, 0x5c, 0x45, 0xe4, 0xca, 0x7a, 0xc5, 0x1a, 0xe3, 0xa0, 0x6f, 0x42, 0x1e, 0x60, 0x6d, 0x68, 0x3f, 0x5e, 0x12, 0x2b, 0x55, 0x79, 0x14, 0x8a, 0x9c, 0x46, 0x6a, 0xde, 0xb0, 0x24, 0x28, 0xf4, 0x89, 0x6a, 0x86, 0xdf, 0x63, 0xbe, 0x58, 0x7d, 0xdd, 0x7a, 0x6a, 0x8d, 0xe7, 0x17, 0x6b, 0xe4, 0xe7, 0xff, 0x4a, 0xaa, 0x99 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.7", + /* Message to be signed */ + 150, + { 0xbe, 0x46, 0xbe, 0x8b, 0xdd, 0x85, 0x43, 0xd3, 0x70, 0xbb, 0xb7, 0xac, 0x83, 0x9f, 0x5e, 0x64, 0x53, 0xf3, 0x0c, 0xd8, 0x75, 0x2a, 0x4b, 0x92, 0x67, 0x32, 0xc5, 0x9e, 0x61, 0x09, 0x04, 0x4b, 0xe3, 0xa0, 0x75, 0x6c, 0x70, 0x25, 0xa2, 0x32, 0x80, 0xdf, 0x2e, 0xd7, 0x66, 0xba, 0x39, 0xab, 0xb2, 0x0b, 0x94, 0x4c, 0x06, 0x5f, 0xe1, 0x48, 0x7d, 0xea, 0x31, 0xb4, 0x70, 0x8a, 0x68, 0x9a, 0x50, 0xb2, 0x8d, 0x54, 0x29, 0x94, 0xcb, 0xbb, 0x3a, 0x5b, 0xb9, 0x46, 0x0e, 0xe7, 0xa9, 0xc1, 0x53, 0x8b, 0xda, 0x75, 0x1a, 0x52, 0x8b, 0x76, 0x70, 0xf9, 0x15, 0x78, 0xd6, 0x67, 0x3e, 0x08, 0xab, 0xcc, 0xdf, 0x5f, 0x4d, 0x8c, 0x1e, 0xbe, 0xcf, 0xca, 0xc7, 0x5c, 0xc4, 0x2d, 0xbb, 0xb8, 0xcd, 0xe3, 0xc1, 0xb4, 0x74, 0xb5, 0x56, 0xb3, 0x2b, 0xb8, 0x48, 0xfc, 0x32, 0x7b, 0xa6, 0xe3, 0xcf, 0x5f, 0x77, 0xb1, 0xeb, 0xc0, 0x4a, 0x19, 0xf3, 0xc8, 0xc3, 0x9b, 0x6b, 0x84, 0x77, 0x84, 0xea, 0xa3, 0x25, 0xa2, 0xb6, 0xf3 } +, + /* Signature */ + 128, + { 0x91, 0xde, 0x2f, 0x90, 0x32, 0x47, 0xb2, 0xd1, 0x3a, 0xbe, 0x93, 0xdd, 0xd9, 0x6d, 0xfa, 0xef, 0x1b, 0x4d, 0x17, 0x2b, 0x09, 0x09, 0x58, 0xf0, 0xcc, 0x34, 0xfa, 0x92, 0x83, 0x5a, 0xd6, 0x0c, 0x44, 0xb4, 0x27, 0xfe, 0x03, 0x1c, 0xad, 0xbf, 0x92, 0xff, 0x1c, 0xd0, 0x38, 0x41, 0x44, 0xc9, 0xb5, 0xf2, 0x8f, 0x64, 0x5c, 0x63, 0xe8, 0xd7, 0x16, 0xbc, 0xec, 0x2e, 0x04, 0x3b, 0xc3, 0x96, 0x56, 0x64, 0x17, 0x85, 0xc2, 0x6b, 0xa3, 0x6b, 0xa2, 0xa1, 0x09, 0xe3, 0x64, 0x4e, 0xbf, 0xd9, 0x62, 0xd7, 0xa3, 0x16, 0x91, 0x6b, 0x3f, 0x13, 0x66, 0x20, 0x13, 0xcc, 0x0f, 0x37, 0xad, 0x8f, 0x9e, 0x0d, 0x9e, 0xc8, 0xb4, 0xc8, 0xad, 0x5c, 0x75, 0x32, 0xcf, 0xa0, 0x44, 0xae, 0xdc, 0x73, 0x78, 0x77, 0x94, 0xc2, 0x98, 0x79, 0x7c, 0x8a, 0x7e, 0x14, 0x49, 0xea, 0xd6, 0x15, 0x0d, 0xed } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.8", + /* Message to be signed */ + 167, + { 0x0b, 0x7e, 0x06, 0x63, 0xe7, 0x15, 0xea, 0x38, 0xbc, 0x93, 0x0e, 0xc9, 0xd8, 0xe2, 0xa0, 0x29, 0xaa, 0x1a, 0x4c, 0x95, 0xe7, 0xb2, 0x00, 0x47, 0xae, 0x15, 0x44, 0xd5, 0xb2, 0xd8, 0x47, 0x6f, 0xc8, 0x05, 0x53, 0x9f, 0xb0, 0xef, 0xab, 0x7d, 0x5f, 0xf1, 0x2c, 0x36, 0xd7, 0x6a, 0x79, 0x7b, 0x75, 0xc0, 0xb5, 0x3f, 0xa9, 0x26, 0x54, 0x73, 0xda, 0xb6, 0x80, 0xc2, 0x55, 0xd5, 0x7e, 0x99, 0xb6, 0xd9, 0xfe, 0x08, 0xcf, 0x1a, 0x57, 0x34, 0x91, 0xe2, 0x19, 0x78, 0xfa, 0xe9, 0x53, 0x9c, 0xc0, 0x58, 0x84, 0x63, 0x3a, 0x1d, 0xd5, 0xcb, 0x21, 0x53, 0x6f, 0xd4, 0x2d, 0xdd, 0x73, 0x1c, 0xa7, 0x6c, 0x34, 0x57, 0x81, 0x3c, 0xe1, 0xbb, 0x59, 0xc2, 0x1d, 0xd3, 0x1b, 0xf2, 0xae, 0x3b, 0xfd, 0x7d, 0x20, 0xc6, 0xc7, 0x12, 0xa9, 0xdd, 0x43, 0x95, 0x1f, 0x1b, 0x19, 0x8d, 0xea, 0xf7, 0x41, 0x08, 0xea, 0xd2, 0x29, 0x26, 0xd2, 0xb0, 0x19, 0x1e, 0x59, 0xd5, 0xf6, 0x79, 0xad, 0x97, 0xc7, 0x1e, 0xdc, 0x69, 0xde, 0x97, 0x98, 0x7e, 0x54, 0x3e, 0x87, 0xa9, 0x6a, 0x9f, 0xee, 0x77, 0xe3, 0xf0, 0xea, 0x95, 0x7b, 0xd4, 0x6a } +, + /* Signature */ + 128, + { 0x48, 0x51, 0x09, 0x8a, 0x85, 0xe7, 0x0d, 0xa3, 0x33, 0x92, 0xa9, 0xe9, 0x0b, 0x34, 0x76, 0xa4, 0x8b, 0xa0, 0xe3, 0x2c, 0xd6, 0xad, 0x3d, 0xc1, 0xdd, 0x91, 0xda, 0x57, 0xe8, 0x8d, 0xfb, 0xc7, 0xb6, 0x57, 0x4b, 0x08, 0xe8, 0x71, 0x60, 0x80, 0xe1, 0x5d, 0xf4, 0x05, 0x79, 0xc5, 0x70, 0x5d, 0x5b, 0xef, 0x58, 0x4b, 0x08, 0xb2, 0x63, 0xdb, 0xc4, 0xf0, 0xd1, 0x59, 0x56, 0xff, 0x11, 0x25, 0xc4, 0x8f, 0x89, 0x59, 0x1e, 0xbc, 0x94, 0x1d, 0x9f, 0xe8, 0xf9, 0xa7, 0x80, 0xc8, 0x2e, 0xa3, 0x2b, 0xf3, 0xef, 0xa1, 0x6c, 0xab, 0xbe, 0xe5, 0x80, 0xfd, 0x6b, 0x95, 0x74, 0x08, 0x0f, 0x69, 0x07, 0xfe, 0xaf, 0xf8, 0x1d, 0x48, 0xc4, 0x9a, 0x6d, 0xe2, 0x24, 0x84, 0x80, 0xf1, 0xd8, 0x52, 0x39, 0xe9, 0xa4, 0x18, 0xdd, 0x53, 0x10, 0xde, 0xf7, 0x76, 0xe0, 0x8f, 0x50, 0x9a, 0x14, 0x78 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.9", + /* Message to be signed */ + 226, + { 0x13, 0x42, 0x33, 0xba, 0xcf, 0xa1, 0x6d, 0xc8, 0x4d, 0x8f, 0xa4, 0xbd, 0xbb, 0x47, 0x93, 0xd1, 0xda, 0xc0, 0x7d, 0x60, 0x54, 0xbd, 0x08, 0x39, 0x61, 0xda, 0x68, 0x67, 0x9c, 0xa3, 0x75, 0x33, 0x4f, 0x09, 0x20, 0xb9, 0xdf, 0xb8, 0xa6, 0x8e, 0xd7, 0x7f, 0x27, 0xfd, 0x92, 0x19, 0x28, 0x13, 0x61, 0xe0, 0x9f, 0xa6, 0x08, 0x4f, 0x96, 0xe6, 0x98, 0x85, 0xb4, 0x7e, 0xa7, 0x75, 0xaf, 0x06, 0x77, 0x2d, 0x66, 0x12, 0xd4, 0xd1, 0x6f, 0x4a, 0x5c, 0xc4, 0xcd, 0x0d, 0x1e, 0xb2, 0x3b, 0x7a, 0x1f, 0x09, 0x56, 0x4b, 0x84, 0x2e, 0xa0, 0x7c, 0xbd, 0xde, 0x60, 0x45, 0x3a, 0x2a, 0xa4, 0xab, 0x69, 0xdd, 0xfe, 0xb5, 0xb1, 0x3e, 0x9f, 0x08, 0xcd, 0x07, 0x2e, 0x5b, 0x71, 0xce, 0xd3, 0x34, 0xea, 0x70, 0x4c, 0x74, 0x9f, 0xf4, 0x72, 0x7e, 0xbe, 0x12, 0xc0, 0x29, 0x0e, 0x00, 0xa8, 0x41, 0xd7, 0x4b, 0x06, 0x55, 0xcf, 0xd8, 0x06, 0x5d, 0x28, 0x20, 0xfd, 0xf8, 0xfd, 0xc1, 0xbd, 0x45, 0x58, 0x81, 0x80, 0x8b, 0xff, 0x0e, 0xc7, 0x27, 0x60, 0x74, 0x75, 0xbf, 0x0b, 0x2b, 0xc8, 0x93, 0x59, 0x58, 0x32, 0x9b, 0x77, 0x8e, 0xfc, 0xe5, 0x60, 0xfc, 0x26, 0xc3, 0xbb, 0x6e, 0x2d, 0xc9, 0xae, 0xf1, 0x8f, 0x96, 0x9f, 0xba, 0x64, 0x74, 0x5e, 0xd4, 0xd8, 0x5b, 0x14, 0x75, 0x7b, 0xb8, 0x33, 0xea, 0xdb, 0x9c, 0x5c, 0xb0, 0xea, 0xed, 0x08, 0xd3, 0x0b, 0x95, 0x15, 0x00, 0x5a, 0x3e, 0x88, 0x09, 0x1f, 0xc5, 0xcd, 0x2f, 0x36, 0xad, 0x95, 0x5b, 0x7c, 0x6f, 0x2b, 0x19, 0xbb, 0xa3, 0x74, 0xfd } +, + /* Signature */ + 128, + { 0x3e, 0x37, 0xb4, 0x2d, 0xbe, 0xc1, 0x29, 0xdb, 0x81, 0xc5, 0xe2, 0xa2, 0x22, 0xf3, 0x1e, 0x81, 0xb9, 0x37, 0xff, 0x02, 0x24, 0x95, 0x18, 0x18, 0x37, 0x30, 0x37, 0x8b, 0x4c, 0x09, 0x2a, 0xa7, 0xf3, 0xb2, 0x34, 0x59, 0x61, 0x1a, 0x82, 0x4f, 0xc5, 0x27, 0x54, 0x42, 0x1a, 0x27, 0xcc, 0xe9, 0x18, 0xb6, 0x2a, 0xa7, 0xb4, 0x46, 0x38, 0xa0, 0xc0, 0x82, 0x79, 0x80, 0x52, 0xa5, 0x88, 0x46, 0x68, 0x82, 0x51, 0x06, 0x90, 0xac, 0x77, 0x30, 0x23, 0x28, 0x02, 0x46, 0xc8, 0x90, 0xff, 0x1f, 0x62, 0x27, 0x04, 0x9e, 0x66, 0x8b, 0xc9, 0xd6, 0xe4, 0x89, 0xb6, 0x94, 0x4a, 0x34, 0xe8, 0xf9, 0x30, 0x02, 0xbb, 0xb0, 0x0d, 0x75, 0x2b, 0x57, 0x7c, 0xe3, 0x52, 0x53, 0x00, 0x82, 0xbe, 0xcd, 0x30, 0x9b, 0x0d, 0xac, 0xcd, 0x1d, 0x68, 0xd0, 0x6e, 0x1d, 0xf7, 0x12, 0x21, 0xc6, 0x22, 0x69 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.10", + /* Message to be signed */ + 111, + { 0x35, 0xda, 0x3d, 0x02, 0x34, 0xbd, 0x74, 0xfc, 0xd7, 0x6e, 0x8e, 0x69, 0x52, 0x8f, 0x65, 0x1b, 0x88, 0x27, 0x1c, 0xbf, 0x16, 0x28, 0x69, 0x38, 0xc2, 0xc4, 0xa3, 0x7d, 0x41, 0x1d, 0xe8, 0xf6, 0x75, 0x78, 0xeb, 0x8b, 0x3d, 0x20, 0xa8, 0xfd, 0x7d, 0xcd, 0xe7, 0xb6, 0x56, 0xfe, 0x96, 0xa6, 0x80, 0x87, 0x32, 0x28, 0xed, 0x0f, 0x9a, 0x62, 0x0f, 0x15, 0x05, 0x44, 0x23, 0x72, 0xf9, 0xb2, 0xb4, 0x16, 0x84, 0x98, 0x72, 0x34, 0x90, 0xf8, 0x11, 0xf3, 0x11, 0x1f, 0x5f, 0x77, 0x38, 0x63, 0x47, 0xb4, 0x82, 0x2e, 0xd9, 0xd6, 0xb5, 0x53, 0x83, 0x92, 0x21, 0x5c, 0xb6, 0xc4, 0x86, 0x5b, 0xb7, 0xb5, 0xb7, 0xe2, 0x84, 0x2e, 0xea, 0x0e, 0x90, 0x01, 0xca, 0x0c, 0xdf, 0x5d, 0x6b } +, + /* Signature */ + 128, + { 0x12, 0xff, 0x2a, 0xb5, 0xfc, 0x83, 0xd6, 0x49, 0x59, 0x7c, 0x47, 0xbf, 0xf3, 0x29, 0xb7, 0xf4, 0x61, 0xdb, 0xbb, 0xda, 0x01, 0xfb, 0x6b, 0xad, 0x26, 0x54, 0x3e, 0x4d, 0xbc, 0xd6, 0x0c, 0x5e, 0x2c, 0xde, 0xbf, 0xb1, 0x12, 0x78, 0x4a, 0x96, 0x4e, 0x27, 0xf2, 0xa2, 0xe7, 0xfd, 0x07, 0xec, 0x39, 0x0a, 0xab, 0x14, 0x94, 0x37, 0x03, 0x58, 0xa7, 0x5b, 0x5e, 0x1f, 0xa4, 0xf1, 0xad, 0x52, 0x02, 0xe6, 0xd5, 0x46, 0xc0, 0xf3, 0x15, 0xe8, 0x6f, 0xaf, 0xf1, 0xd2, 0x5b, 0x94, 0x72, 0x82, 0xda, 0x32, 0xea, 0xb5, 0x6c, 0x22, 0xf0, 0x6c, 0x8a, 0x9d, 0x32, 0xae, 0xf2, 0x81, 0xd6, 0xf0, 0xaa, 0x55, 0xd7, 0xad, 0x3b, 0xcd, 0xfd, 0xb2, 0x09, 0xa1, 0x6e, 0xf4, 0x5c, 0xc6, 0xf9, 0x68, 0x2e, 0xae, 0x96, 0x3c, 0xbb, 0x21, 0x3a, 0xdb, 0x7f, 0xad, 0x1b, 0xef, 0x49, 0xc0, 0x70, 0x4f } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.11", + /* Message to be signed */ + 50, + { 0x75, 0xfd, 0xb0, 0x72, 0x73, 0xf7, 0x54, 0xd1, 0x11, 0x6f, 0x99, 0x7a, 0xf2, 0xd1, 0x1a, 0x51, 0x2b, 0x94, 0xe9, 0xe0, 0x48, 0x01, 0xb3, 0xfc, 0x73, 0x91, 0x30, 0xb7, 0x47, 0xb4, 0xbe, 0x87, 0x44, 0xd7, 0xe7, 0xf8, 0xa2, 0x97, 0xa0, 0x89, 0xd9, 0x05, 0x0c, 0x5f, 0x54, 0xf8, 0xa3, 0x9a, 0xa3, 0xf2 } +, + /* Signature */ + 128, + { 0x07, 0xff, 0xc1, 0xb7, 0xa1, 0x0d, 0xda, 0xba, 0x96, 0x05, 0xf0, 0xa3, 0xd9, 0x3c, 0x8a, 0x5e, 0x4c, 0x0b, 0x77, 0x58, 0x61, 0x39, 0x05, 0x07, 0x31, 0xd9, 0xcc, 0x9b, 0x3c, 0x83, 0xd2, 0xb7, 0x3f, 0xaf, 0x9a, 0x4e, 0x24, 0xd1, 0xc8, 0xbb, 0x0d, 0x62, 0x3d, 0xf1, 0x0f, 0xc8, 0x40, 0x7d, 0x15, 0x14, 0x48, 0xfa, 0x43, 0xee, 0x65, 0x81, 0xe7, 0xb0, 0xac, 0x80, 0xd1, 0x4a, 0xdf, 0xa4, 0xf6, 0xd2, 0x7a, 0x76, 0x67, 0x50, 0xb2, 0x31, 0xcb, 0xc1, 0xc5, 0xcf, 0xd6, 0x2d, 0xf1, 0xb9, 0x72, 0x7d, 0x8b, 0x87, 0x41, 0x46, 0x9f, 0x68, 0xe5, 0x0a, 0x9b, 0x3b, 0xc7, 0xad, 0xe1, 0x37, 0xdb, 0x06, 0x74, 0x76, 0x03, 0x74, 0x28, 0x56, 0xd5, 0xe7, 0xdd, 0xb4, 0xe1, 0x6a, 0x5b, 0x49, 0xd7, 0x36, 0x5d, 0xb2, 0x76, 0x3b, 0xf5, 0xfd, 0xea, 0x08, 0x3d, 0x81, 0xfa, 0xc9, 0x2d, 0x87 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.12", + /* Message to be signed */ + 245, + { 0x96, 0xc9, 0xfa, 0xce, 0xfb, 0xa2, 0xed, 0x33, 0xed, 0x8b, 0x7b, 0x3d, 0x8b, 0x6d, 0xf2, 0x8f, 0x2f, 0xab, 0x0d, 0xcd, 0xd7, 0xa3, 0xcd, 0x7a, 0x7d, 0xed, 0xa2, 0x54, 0x5e, 0xd4, 0x47, 0x0e, 0xd2, 0x5b, 0x46, 0xd2, 0x16, 0x6e, 0xeb, 0xb7, 0xe1, 0x47, 0x10, 0x17, 0x83, 0xb6, 0x45, 0xba, 0xc6, 0x26, 0x64, 0xb8, 0x72, 0x70, 0x09, 0xf3, 0x5d, 0x1e, 0xa5, 0xfd, 0xa5, 0xe7, 0xc2, 0x8d, 0x6a, 0xf6, 0xfe, 0x92, 0x04, 0x6c, 0xa7, 0x24, 0xca, 0xb8, 0x42, 0x5a, 0x52, 0xa0, 0x85, 0xf9, 0xac, 0x90, 0x83, 0xd4, 0xd6, 0x90, 0xbb, 0xdd, 0xdf, 0xd0, 0xa8, 0x2d, 0x94, 0x8f, 0x70, 0xd6, 0x85, 0xe2, 0x6b, 0xb9, 0xf5, 0x27, 0x40, 0x8a, 0xbc, 0x84, 0x7b, 0xff, 0x12, 0x02, 0xde, 0xdf, 0x6d, 0x2f, 0xac, 0x6c, 0xf3, 0x68, 0x2a, 0x51, 0x6b, 0xa7, 0x2f, 0x4f, 0xe9, 0x7b, 0x90, 0x46, 0x6a, 0xf6, 0xe5, 0x43, 0x12, 0x31, 0x65, 0xb8, 0xa6, 0x83, 0xca, 0xba, 0x2f, 0xa2, 0x3a, 0x86, 0xac, 0x06, 0x21, 0x30, 0x65, 0xe1, 0xed, 0x9b, 0x4f, 0x49, 0xaf, 0x4f, 0xff, 0x6d, 0x46, 0xb3, 0x6d, 0x13, 0x3d, 0x8d, 0xa2, 0xdd, 0x29, 0xd5, 0x5f, 0x9f, 0x32, 0x2c, 0x40, 0x78, 0x5d, 0xdc, 0x21, 0xc4, 0x26, 0xc5, 0xe0, 0xa6, 0x7d, 0x41, 0x4f, 0x5a, 0xb9, 0x71, 0xc4, 0x46, 0x0f, 0xf9, 0xb1, 0x14, 0x30, 0x5a, 0x8a, 0xe7, 0xe7, 0xb9, 0x5c, 0x73, 0x03, 0x4e, 0x8e, 0x93, 0xc0, 0x35, 0x29, 0xdd, 0x50, 0xc9, 0x4f, 0x07, 0x62, 0x79, 0x77, 0x5a, 0x5a, 0x3a, 0x80, 0xc5, 0xd2, 0x48, 0x6a, 0x2d, 0x51, 0x08, 0x48, 0xbd, 0xc9, 0xb8, 0x52, 0xac, 0x1d, 0x32, 0xce, 0xb7, 0xc0, 0x41, 0xa0, 0x8f, 0x2f, 0x8e, 0x62 } +, + /* Signature */ + 128, + { 0x46, 0xd0, 0x3f, 0xae, 0xc4, 0xa7, 0x23, 0x18, 0x62, 0x1e, 0xf4, 0xd0, 0xc1, 0xbc, 0xa7, 0x1a, 0x2a, 0xee, 0xa7, 0xa8, 0x1d, 0xf8, 0xfe, 0xbb, 0x8b, 0xa3, 0xfb, 0x35, 0x40, 0xd7, 0x2d, 0x15, 0x34, 0xb9, 0x82, 0x69, 0x16, 0xe8, 0x9f, 0x27, 0xd3, 0x25, 0x67, 0x6c, 0xcf, 0x5a, 0x0a, 0xa1, 0x61, 0x12, 0xdb, 0x2d, 0x93, 0x03, 0xe0, 0xeb, 0xce, 0x4b, 0x85, 0x58, 0x7c, 0x55, 0xac, 0xa0, 0x68, 0x50, 0xde, 0x84, 0xde, 0xc2, 0x13, 0xd1, 0x13, 0x74, 0x04, 0xa5, 0xde, 0xe6, 0xca, 0x88, 0xd9, 0x1a, 0xe2, 0x8b, 0x7b, 0x53, 0x6c, 0x90, 0x20, 0x2b, 0xc7, 0x72, 0x6d, 0xa5, 0x04, 0x2a, 0x85, 0x08, 0xd3, 0xb1, 0x3c, 0xfb, 0xaa, 0xdc, 0xee, 0x12, 0x78, 0xd3, 0x5d, 0x30, 0x3a, 0xcf, 0xee, 0x6e, 0x07, 0x41, 0x90, 0x49, 0x11, 0xa5, 0xf1, 0x88, 0x10, 0xad, 0xd3, 0xe7, 0xb8, 0xf6 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.13", + /* Message to be signed */ + 58, + { 0xc4, 0xb4, 0xc9, 0x96, 0x6e, 0x56, 0xf4, 0x0a, 0xff, 0x47, 0x08, 0x13, 0x1c, 0xd3, 0x71, 0x44, 0x21, 0x34, 0x3e, 0xde, 0x70, 0xc4, 0xd4, 0x6d, 0xb6, 0xef, 0xbe, 0x1b, 0x19, 0xa9, 0xe3, 0xc2, 0xe5, 0x81, 0x06, 0x00, 0x8a, 0x98, 0x38, 0x59, 0xcf, 0x94, 0x2a, 0x31, 0x97, 0x74, 0x69, 0x5a, 0x0c, 0x98, 0xa9, 0x63, 0xe2, 0xfe, 0x9d, 0x93, 0x79, 0xbc } +, + /* Signature */ + 128, + { 0xb1, 0x6b, 0x10, 0xf2, 0xbd, 0x7e, 0xa0, 0xf7, 0x6a, 0x9e, 0xd2, 0xff, 0xcf, 0x3e, 0xc1, 0x0e, 0xdc, 0xb8, 0x24, 0x60, 0xfe, 0x55, 0x82, 0xa7, 0x76, 0x4c, 0x0c, 0x50, 0x56, 0xec, 0xfb, 0x09, 0x72, 0x06, 0x48, 0xd5, 0xf1, 0x9b, 0x3d, 0xea, 0xf2, 0xac, 0xc9, 0x86, 0x46, 0x0e, 0x71, 0x14, 0x26, 0x15, 0x83, 0xa5, 0xf4, 0xa9, 0x90, 0xe9, 0x22, 0xfe, 0xb5, 0xb4, 0x78, 0x97, 0x34, 0xfd, 0xcc, 0xe1, 0x5d, 0xdc, 0x87, 0xca, 0xc3, 0xf6, 0xc7, 0xc9, 0xe9, 0xe2, 0x19, 0x23, 0x15, 0xf0, 0x84, 0x1f, 0x43, 0xea, 0x86, 0xde, 0xa9, 0xa9, 0x38, 0x05, 0x08, 0xb0, 0x6c, 0x9c, 0xa5, 0xe9, 0xd4, 0xa6, 0x51, 0xd0, 0x12, 0x16, 0x62, 0x7c, 0x46, 0x6b, 0xf0, 0xd6, 0xae, 0x74, 0x4b, 0xf3, 0x0f, 0xd7, 0x91, 0xa8, 0x21, 0x03, 0x39, 0xf5, 0x05, 0x7f, 0xf8, 0x5c, 0xeb, 0x84, 0xf1, 0x96 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.14", + /* Message to be signed */ + 165, + { 0xb8, 0x38, 0xa5, 0xd8, 0x88, 0x95, 0x0f, 0x1b, 0x8e, 0x4d, 0x94, 0x7b, 0xba, 0x51, 0xaf, 0xf9, 0xbb, 0x60, 0xb8, 0x3d, 0x09, 0xed, 0x9d, 0x97, 0x96, 0x7a, 0x76, 0x95, 0x5e, 0xd1, 0xdd, 0xf0, 0x48, 0x15, 0x20, 0xbc, 0xf4, 0xf0, 0x8b, 0xeb, 0xbf, 0x89, 0x9c, 0xc7, 0xc3, 0xef, 0x0c, 0x04, 0xd5, 0x00, 0x1b, 0x1e, 0x2e, 0x84, 0x5f, 0xaf, 0xc5, 0x83, 0x30, 0x0c, 0x98, 0xac, 0xa7, 0xa0, 0x3e, 0x90, 0xa4, 0x34, 0xde, 0x77, 0xfe, 0xf7, 0x20, 0xda, 0x36, 0x63, 0xf2, 0x19, 0x98, 0x20, 0x8a, 0x94, 0xf8, 0x94, 0x76, 0x7d, 0x3e, 0xd8, 0x13, 0x96, 0xb7, 0xef, 0xb2, 0x86, 0xe0, 0xff, 0x7d, 0xb6, 0xea, 0x8f, 0xdb, 0x4e, 0x72, 0x83, 0x46, 0x00, 0xfe, 0x5f, 0x7f, 0x15, 0x0a, 0x01, 0xb1, 0xd4, 0xa0, 0x8b, 0x5e, 0xc9, 0xee, 0x1f, 0xbc, 0x10, 0x01, 0xd1, 0x2d, 0x52, 0x36, 0xdb, 0xf0, 0x72, 0x7e, 0x7e, 0xa3, 0x60, 0x78, 0xf3, 0xeb, 0xac, 0x50, 0x46, 0xb7, 0x65, 0xb4, 0xe2, 0x3c, 0xdc, 0xef, 0xd1, 0x15, 0xd6, 0x2a, 0x50, 0x34, 0x4d, 0xbb, 0xd7, 0x42, 0x8d, 0x48, 0xff, 0xc9, 0x4b, 0x11, 0xe2, 0x1c } +, + /* Signature */ + 128, + { 0xb1, 0x56, 0x81, 0xee, 0xf2, 0x96, 0xa6, 0x6b, 0x9f, 0xcd, 0x66, 0x30, 0xf8, 0x9c, 0x55, 0x82, 0x6a, 0x38, 0x9e, 0x0c, 0x2d, 0x3d, 0x47, 0x6a, 0x0f, 0x8a, 0x1e, 0x08, 0xcb, 0xca, 0xcc, 0x66, 0x02, 0xc7, 0x14, 0x43, 0x8f, 0x32, 0xf3, 0x4e, 0x02, 0xc3, 0x6e, 0x5c, 0x0f, 0x16, 0x8a, 0xb0, 0x28, 0x91, 0x7e, 0x90, 0x50, 0xfb, 0xc8, 0x50, 0xf0, 0xcf, 0x65, 0xd5, 0xee, 0xdb, 0x3b, 0x54, 0xbe, 0x54, 0x95, 0xbb, 0xf0, 0xfa, 0xee, 0xb3, 0x2b, 0xbe, 0x5a, 0x8f, 0x87, 0xbb, 0xac, 0xdd, 0x25, 0x85, 0xfb, 0x90, 0x7b, 0x13, 0x18, 0x5b, 0x02, 0x61, 0x56, 0x63, 0xd2, 0x01, 0x1e, 0xf2, 0x3d, 0x0a, 0xb0, 0x4d, 0xad, 0x1f, 0xfa, 0x67, 0x9b, 0x53, 0x15, 0x2c, 0x9c, 0x42, 0xb8, 0x46, 0x39, 0x68, 0x4e, 0xae, 0xaf, 0x64, 0x4e, 0x4f, 0xc6, 0xff, 0x2e, 0xc7, 0xd4, 0x7b, 0xa5, 0xac } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.15", + /* Message to be signed */ + 77, + { 0x9f, 0xd5, 0x39, 0xc8, 0xad, 0x86, 0x49, 0x24, 0xee, 0xc1, 0xd6, 0x55, 0xc0, 0x7d, 0x1f, 0x28, 0x27, 0x0c, 0xdb, 0x32, 0x6b, 0x57, 0x2c, 0x46, 0x67, 0xec, 0xa6, 0x48, 0x8c, 0x03, 0x36, 0x57, 0xff, 0x29, 0x25, 0x4b, 0x91, 0xf3, 0x21, 0x6e, 0x1c, 0xac, 0x97, 0x97, 0x53, 0xf2, 0x23, 0xb1, 0x79, 0xea, 0x5f, 0x9e, 0xfc, 0x23, 0x6d, 0x40, 0x1d, 0x1b, 0x9a, 0x3c, 0x20, 0xeb, 0x2a, 0xfc, 0x9b, 0xfc, 0xfd, 0x07, 0x92, 0xac, 0xc5, 0xb0, 0x0c, 0x98, 0x28, 0xa6, 0x45 } +, + /* Signature */ + 128, + { 0x38, 0xbf, 0xdf, 0xd3, 0x27, 0x2e, 0x48, 0xcf, 0xee, 0x68, 0xce, 0xb9, 0x13, 0x04, 0xeb, 0x91, 0xee, 0x25, 0xe4, 0x83, 0x40, 0x1f, 0x30, 0xfe, 0x12, 0xd5, 0xe4, 0x35, 0x18, 0xe4, 0xb7, 0x71, 0x14, 0xa1, 0x2c, 0x8c, 0x79, 0x92, 0xae, 0xe7, 0xd2, 0xe7, 0x74, 0xff, 0xf9, 0x1d, 0x8f, 0xd1, 0xcb, 0x7c, 0x6a, 0x2a, 0xdf, 0x79, 0xb7, 0xc8, 0xab, 0x93, 0xe8, 0x37, 0x4d, 0xb7, 0x4c, 0x26, 0x90, 0x9c, 0x65, 0x9a, 0x97, 0xc7, 0x6a, 0x22, 0x2d, 0xf4, 0xfc, 0x8c, 0x7e, 0xf5, 0x19, 0x90, 0x80, 0xea, 0xae, 0x2d, 0x03, 0x1c, 0xa7, 0x51, 0xc5, 0x01, 0x32, 0x89, 0xdb, 0x4e, 0xad, 0x77, 0xb2, 0x8b, 0x76, 0xa4, 0xc4, 0x96, 0xad, 0x0e, 0xb4, 0x22, 0xfc, 0xa8, 0x8f, 0xc6, 0x84, 0xe4, 0x2a, 0xea, 0x88, 0xfd, 0x33, 0xc2, 0x56, 0x75, 0x1b, 0xa0, 0x66, 0x83, 0x4e, 0x77, 0xa1, 0xe2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.16", + /* Message to be signed */ + 23, + { 0x1d, 0xe8, 0x07, 0x40, 0x9d, 0x0a, 0x61, 0xb0, 0x32, 0x2d, 0xfe, 0xd4, 0x99, 0xe8, 0xc3, 0x32, 0x41, 0xec, 0x89, 0xcd, 0x7d, 0x9f, 0xc5 } +, + /* Signature */ + 128, + { 0x8b, 0x66, 0x64, 0xf8, 0x69, 0xd7, 0x55, 0xc5, 0xd3, 0xe6, 0xdf, 0x99, 0x22, 0xe2, 0x27, 0xc1, 0x10, 0x91, 0x8a, 0x6f, 0xbd, 0x88, 0xc1, 0xa2, 0xe1, 0x28, 0x95, 0x23, 0xad, 0xbb, 0xd8, 0xaa, 0x43, 0x1d, 0x07, 0x86, 0x85, 0x3a, 0xb5, 0x96, 0xdd, 0x5b, 0x00, 0x12, 0x43, 0xb5, 0x4a, 0x2c, 0xb1, 0x0c, 0x31, 0x66, 0xbf, 0x00, 0x23, 0x38, 0xfc, 0xa2, 0x03, 0x45, 0xae, 0xde, 0x1b, 0x22, 0xea, 0x1f, 0xa3, 0xd2, 0x41, 0xc8, 0x6c, 0x76, 0xbf, 0xc0, 0x2f, 0x4f, 0xce, 0xae, 0x12, 0xc8, 0xa9, 0xd7, 0xe4, 0x4a, 0xd6, 0x17, 0x16, 0x65, 0xe8, 0x8f, 0x12, 0x85, 0x22, 0xdd, 0x53, 0x5a, 0x9d, 0x65, 0x00, 0x8f, 0x6a, 0x73, 0x2d, 0x40, 0xaf, 0x20, 0x4e, 0x22, 0x0f, 0x1f, 0xac, 0xd9, 0x42, 0xe0, 0x9d, 0x15, 0x09, 0x9f, 0xdc, 0x51, 0xb3, 0xa1, 0x42, 0x6c, 0xb2, 0xdd, 0x32, 0x93 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.17", + /* Message to be signed */ + 22, + { 0x4b, 0x2b, 0xcb, 0x26, 0x79, 0xa1, 0x4c, 0x3c, 0x4c, 0x06, 0x9e, 0xd0, 0x89, 0xa6, 0x5a, 0xba, 0x29, 0xf2, 0x2b, 0x61, 0x78, 0xc0 } +, + /* Signature */ + 128, + { 0x1c, 0x47, 0x82, 0x8e, 0xa5, 0x3f, 0xb6, 0x43, 0x6e, 0x95, 0x96, 0xb0, 0xce, 0x47, 0xd9, 0xf3, 0x8b, 0x5d, 0xeb, 0x0b, 0x19, 0x7c, 0x1b, 0xc4, 0x74, 0xe2, 0xe8, 0x22, 0x65, 0x70, 0xcc, 0x1b, 0x72, 0xf2, 0x39, 0x31, 0x2a, 0xe7, 0xc3, 0xc6, 0x38, 0x2e, 0x1d, 0x8c, 0xda, 0x7d, 0x4f, 0x12, 0xfe, 0xba, 0xd7, 0x0a, 0xfa, 0xe5, 0xac, 0xbf, 0x24, 0x28, 0xab, 0xc0, 0x44, 0x21, 0xbb, 0x4e, 0x1e, 0x59, 0x90, 0x11, 0x1b, 0x9a, 0xc8, 0x3c, 0x62, 0x43, 0x5c, 0x21, 0xaa, 0x25, 0xfd, 0x9b, 0x49, 0x07, 0x58, 0x54, 0x11, 0xd2, 0x53, 0xba, 0x9b, 0x87, 0x78, 0xf6, 0x24, 0x05, 0x3d, 0x46, 0xfe, 0x95, 0xd7, 0xe2, 0x2c, 0xa3, 0x93, 0x81, 0xc7, 0x79, 0x2e, 0xff, 0x46, 0x43, 0x8f, 0xbc, 0x16, 0x5e, 0xd7, 0x62, 0x9c, 0x2f, 0xc1, 0xce, 0xf1, 0xb3, 0x4d, 0x77, 0x76, 0x8a, 0x20, 0x55 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.18", + /* Message to be signed */ + 238, + { 0xef, 0x46, 0xae, 0x51, 0xe0, 0x15, 0x8c, 0xd0, 0xef, 0x9c, 0x78, 0xd7, 0x1e, 0x00, 0x15, 0x67, 0xd6, 0x6a, 0xe3, 0xc5, 0xe9, 0xa6, 0x4f, 0x24, 0x57, 0x15, 0xc7, 0xc2, 0xad, 0x8e, 0xea, 0x0f, 0x9d, 0x32, 0x00, 0x23, 0x07, 0x2f, 0xdb, 0x0f, 0xb8, 0x6a, 0x45, 0x21, 0x7f, 0xd7, 0x12, 0xcc, 0x80, 0xe5, 0xb9, 0x41, 0x47, 0xc4, 0x5f, 0xe0, 0x0b, 0x69, 0x2c, 0xcd, 0xa1, 0x10, 0x25, 0x98, 0x41, 0xb2, 0xc7, 0xe5, 0xc3, 0xdc, 0xff, 0x59, 0x56, 0xf2, 0xa5, 0x96, 0xcd, 0xa6, 0x8e, 0xb7, 0x7f, 0x4c, 0x85, 0x90, 0xd7, 0x36, 0xb8, 0xfd, 0x60, 0x66, 0x77, 0x3e, 0xf6, 0xf9, 0x5a, 0x38, 0xcd, 0x38, 0x4e, 0x94, 0x83, 0xa8, 0x9d, 0xc2, 0xb6, 0xc2, 0xe8, 0x74, 0x5c, 0x95, 0xc1, 0x2f, 0xa6, 0x72, 0xa1, 0xbe, 0xcf, 0xb6, 0x3e, 0xac, 0x9b, 0x55, 0x3e, 0xda, 0x8d, 0x29, 0x37, 0x54, 0xec, 0x39, 0x47, 0xea, 0xc0, 0x22, 0x8d, 0xe2, 0x63, 0x14, 0xb5, 0x9b, 0x66, 0x99, 0x4c, 0xc6, 0x0e, 0x83, 0x60, 0xe7, 0x5d, 0x38, 0x76, 0x29, 0x8f, 0x8f, 0x8a, 0x7d, 0x14, 0x1d, 0xa0, 0x64, 0xe5, 0xca, 0x02, 0x6a, 0x97, 0x3e, 0x28, 0xf2, 0x54, 0x73, 0x8c, 0xee, 0x66, 0x9c, 0x72, 0x1b, 0x03, 0x4c, 0xb5, 0xf8, 0xe2, 0x44, 0xda, 0xdd, 0x7c, 0xd1, 0xe1, 0x59, 0xd4, 0x51, 0xd4, 0xbf, 0x65, 0x80, 0xf3, 0xe6, 0x9c, 0xdc, 0x02, 0x71, 0x38, 0x2e, 0x8d, 0xc1, 0x4b, 0xc7, 0x33, 0xaf, 0x38, 0x99, 0x2c, 0x1c, 0xd8, 0x82, 0xc7, 0xb1, 0x50, 0xd2, 0x3a, 0x06, 0x7b, 0x9b, 0xcf, 0x3c, 0xcd, 0xab, 0x6b, 0x0f, 0xba, 0x13, 0x2b, 0x4c, 0x14, 0x47, 0xc8, 0x7c, 0x39, 0x3f } +, + /* Signature */ + 128, + { 0x8c, 0x1d, 0xe1, 0x5a, 0xb8, 0x6c, 0xbf, 0x5b, 0xd9, 0x31, 0x7c, 0xe2, 0xb8, 0xfc, 0x82, 0xf5, 0x72, 0x2d, 0xb6, 0x96, 0x1c, 0x9f, 0x55, 0x51, 0x40, 0xf7, 0x8e, 0xbd, 0xa2, 0x4e, 0x3f, 0x51, 0xfd, 0x73, 0x01, 0xc1, 0xe4, 0xfe, 0x12, 0xb6, 0x95, 0x7c, 0x30, 0x14, 0x4f, 0xa1, 0xe1, 0x27, 0x27, 0x46, 0x03, 0xdc, 0x02, 0x05, 0x11, 0x30, 0xb2, 0x53, 0x85, 0xfc, 0x86, 0x46, 0xee, 0x96, 0xa7, 0x45, 0x50, 0xd2, 0xd6, 0x3f, 0x85, 0x81, 0x85, 0xbb, 0x98, 0x46, 0x52, 0xa3, 0x43, 0x1d, 0x53, 0x3d, 0xa6, 0x01, 0x46, 0x22, 0xa6, 0x4e, 0x06, 0x91, 0x66, 0x2a, 0x4f, 0x7c, 0x9d, 0x58, 0x31, 0x9b, 0xa3, 0xf8, 0x5f, 0x19, 0x18, 0x24, 0x75, 0xe1, 0x50, 0x9b, 0xbf, 0x21, 0x3a, 0xf0, 0x10, 0x10, 0xb4, 0xb9, 0xf8, 0x2e, 0x64, 0x75, 0x11, 0xfc, 0x97, 0xc6, 0xb7, 0xc9, 0x7e, 0x8d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.19", + /* Message to be signed */ + 192, + { 0xf8, 0x7b, 0xb1, 0x2d, 0xaa, 0xad, 0x62, 0xc8, 0x64, 0xac, 0x3d, 0x44, 0x4d, 0x51, 0x4e, 0xec, 0x6e, 0x59, 0xb6, 0x7c, 0xd0, 0x82, 0x0d, 0xfc, 0xbd, 0xf8, 0x51, 0xea, 0x73, 0x89, 0x1f, 0x58, 0xa8, 0xbe, 0x6e, 0x84, 0x3e, 0xe8, 0x77, 0x3e, 0x4d, 0xc1, 0xc7, 0xd7, 0x42, 0xda, 0x82, 0xff, 0x16, 0xc1, 0x01, 0x1b, 0x99, 0x56, 0x6b, 0x9f, 0x3f, 0xd1, 0x7d, 0x68, 0xd5, 0xac, 0x99, 0xce, 0xf5, 0xa3, 0xa0, 0xf7, 0x53, 0x18, 0x76, 0x9d, 0xc0, 0x13, 0xbb, 0x05, 0x5b, 0xe1, 0x30, 0x56, 0xdf, 0x49, 0xa8, 0x39, 0xb8, 0x39, 0x52, 0x51, 0x39, 0x9b, 0x27, 0xa0, 0xbb, 0x31, 0xc5, 0x54, 0xae, 0xdf, 0x3d, 0x9c, 0x74, 0x82, 0xb6, 0x62, 0x0c, 0x5d, 0x7c, 0x69, 0x14, 0xa5, 0x64, 0xdb, 0x04, 0xa0, 0x00, 0x04, 0x56, 0x99, 0xee, 0x1e, 0x50, 0x88, 0xa5, 0xb6, 0x8d, 0x81, 0x4e, 0xfe, 0x9d, 0x13, 0x0d, 0xc3, 0x4e, 0x2b, 0xd9, 0x78, 0x51, 0x13, 0x9c, 0x73, 0x46, 0x07, 0x65, 0xb1, 0xf2, 0x65, 0x46, 0x86, 0xfe, 0xde, 0x9c, 0x9b, 0x3e, 0x92, 0x40, 0x9d, 0xb2, 0xd4, 0x2a, 0x32, 0xba, 0x9e, 0x20, 0xbc, 0xae, 0xb2, 0xc4, 0xf9, 0xff, 0x9b, 0x0e, 0x83, 0x4b, 0x74, 0x92, 0xa2, 0xb1, 0xd8, 0xc6, 0x5c, 0x8b, 0xa4, 0x98, 0x34, 0x2a, 0xe7, 0xd1, 0xd9, 0xfe, 0x74, 0x05, 0xc2 } +, + /* Signature */ + 128, + { 0x20, 0x7a, 0x34, 0x8c, 0xdf, 0x68, 0x4a, 0xa8, 0xe1, 0xa4, 0xaf, 0x7b, 0x7c, 0x25, 0x27, 0x07, 0xce, 0x6f, 0x1f, 0x9d, 0xb2, 0x29, 0x1f, 0x2a, 0x95, 0xa0, 0x71, 0x5d, 0x9c, 0x7f, 0xc5, 0x1a, 0xa2, 0x30, 0x11, 0x0b, 0x5b, 0x51, 0x8a, 0x9c, 0x8f, 0x95, 0x8d, 0xd2, 0x0c, 0x75, 0x24, 0xd5, 0xb6, 0x51, 0x06, 0xd7, 0x42, 0x1b, 0xa9, 0xfc, 0xfb, 0x78, 0x91, 0x78, 0x41, 0x2c, 0x36, 0x40, 0xf5, 0x40, 0xb8, 0x1b, 0xb3, 0x18, 0x97, 0xd2, 0x64, 0x5e, 0xc7, 0x9d, 0x8e, 0x59, 0x75, 0x04, 0x8e, 0x45, 0x22, 0x61, 0xa1, 0xc2, 0x00, 0x9c, 0xfe, 0xee, 0x07, 0x15, 0xa0, 0x1b, 0xee, 0xfd, 0x75, 0xe7, 0x04, 0xb2, 0xa6, 0xf0, 0xf0, 0xae, 0x7e, 0xa3, 0x6c, 0x53, 0xcf, 0xe3, 0x6f, 0x57, 0xf0, 0x34, 0xe3, 0x85, 0x44, 0x8f, 0xca, 0xab, 0x08, 0xdc, 0xff, 0x47, 0x7d, 0x36, 0xff, 0x15 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 5.20", + /* Message to be signed */ + 2, + { 0x4c, 0x4b } +, + /* Signature */ + 128, + { 0x1c, 0xb6, 0x88, 0x12, 0x83, 0xdc, 0xd1, 0x86, 0x3b, 0xa7, 0x9d, 0xfb, 0x22, 0x35, 0x1b, 0xc9, 0xa8, 0xe0, 0x35, 0x8b, 0x2f, 0x8a, 0x1d, 0xe3, 0xf9, 0x06, 0x5d, 0x8c, 0xa8, 0x59, 0x31, 0x4a, 0xe1, 0x12, 0x13, 0xa2, 0xcc, 0x87, 0xb2, 0xf6, 0x32, 0xef, 0xa6, 0x7d, 0x21, 0x03, 0xf3, 0x82, 0x00, 0xb9, 0x19, 0x3e, 0xb8, 0xd4, 0x99, 0x82, 0x09, 0x9a, 0xfc, 0x74, 0x42, 0x8f, 0x4b, 0x41, 0x31, 0x6f, 0x48, 0x78, 0xb3, 0xf6, 0x00, 0xbc, 0x2f, 0xb3, 0x04, 0x58, 0xcc, 0x9c, 0x2a, 0x03, 0x4a, 0x06, 0x8e, 0x98, 0xd5, 0x7a, 0xe7, 0x9c, 0xe3, 0xe2, 0xfc, 0x84, 0xb6, 0xa7, 0x45, 0xf0, 0x37, 0xa5, 0xde, 0xa2, 0xb9, 0xda, 0x4e, 0x8d, 0xb4, 0xad, 0xa6, 0x9f, 0xb8, 0x2d, 0x20, 0xa4, 0x1b, 0xb8, 0x43, 0x07, 0x93, 0xee, 0xf9, 0x2a, 0x4f, 0xd6, 0x18, 0x6d, 0x17, 0x96, 0x63, 0xcb } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 6: A 1024-bit RSA key pair", +{ + /* Modulus */ + 128, + { 0xd6, 0x31, 0x14, 0x57, 0xe1, 0xca, 0xf1, 0x22, 0x44, 0x36, 0x69, 0x79, 0x83, 0xc8, 0x6d, 0xd3, 0x38, 0x20, 0x58, 0x62, 0xd2, 0xa1, 0x05, 0xba, 0xf7, 0x10, 0x34, 0x28, 0xfd, 0x83, 0x53, 0xa1, 0x9b, 0x7b, 0xa4, 0x22, 0x8f, 0x78, 0xb4, 0x7f, 0x79, 0x07, 0x35, 0x70, 0x34, 0xc5, 0x2d, 0x85, 0x97, 0xda, 0x2b, 0x5d, 0x13, 0xdc, 0x53, 0x5b, 0x83, 0x6c, 0x74, 0x13, 0x0a, 0x36, 0x48, 0x91, 0x8d, 0x4a, 0x7a, 0x83, 0x99, 0x0c, 0x2e, 0x28, 0x81, 0x6a, 0xec, 0x0f, 0xca, 0x01, 0xd1, 0x05, 0xc6, 0xc6, 0x52, 0xec, 0x57, 0x33, 0xd0, 0x1f, 0x00, 0x58, 0xb2, 0xdf, 0x5a, 0xe6, 0x73, 0x33, 0x40, 0x5a, 0x3a, 0x5b, 0x12, 0x20, 0xa2, 0x6a, 0xc3, 0xd1, 0x42, 0xf2, 0xb4, 0xd8, 0x37, 0xeb, 0x73, 0x86, 0xa4, 0x0a, 0x74, 0xcc, 0x3d, 0x1e, 0x4f, 0xbc, 0x64, 0xfd, 0x7d, 0xa6, 0x3c, 0x41 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 127, + { 0x5e, 0xa6, 0x11, 0x77, 0x44, 0x2f, 0x89, 0x9e, 0xba, 0xc5, 0xd0, 0x96, 0x01, 0xc5, 0xef, 0xc2, 0x06, 0x6b, 0x44, 0xa3, 0x66, 0xb0, 0x00, 0xf8, 0x3d, 0x74, 0xcb, 0x97, 0xd1, 0x6e, 0xd6, 0xe5, 0xf2, 0xef, 0x0f, 0xf8, 0xb5, 0xad, 0x81, 0x15, 0x53, 0x45, 0xfc, 0x37, 0x39, 0x1a, 0x68, 0xa3, 0x40, 0x17, 0x08, 0x52, 0x79, 0x14, 0x43, 0x41, 0x8d, 0x31, 0xbf, 0x99, 0x2a, 0x4a, 0x12, 0x86, 0x6f, 0xe9, 0xff, 0xcc, 0xde, 0xbb, 0xbb, 0xa6, 0x37, 0xee, 0x88, 0x7b, 0x71, 0x6c, 0xaa, 0x92, 0xe2, 0x49, 0xce, 0xd6, 0x57, 0xee, 0xd7, 0x1f, 0x5c, 0xcd, 0xd9, 0x16, 0x3f, 0x32, 0x69, 0x52, 0x5d, 0x78, 0x9f, 0x4b, 0x33, 0xc4, 0x8a, 0x95, 0x76, 0x44, 0x36, 0xec, 0x32, 0x5e, 0x86, 0x89, 0x69, 0x1c, 0x27, 0x2d, 0x90, 0xbd, 0x88, 0x88, 0x98, 0x51, 0x37, 0x2f, 0xb8, 0xdc, 0xb9 } +, + /* Prime 1 */ + 64, + { 0xf3, 0xd4, 0xb8, 0x51, 0xad, 0x7a, 0xc7, 0x78, 0xbe, 0xcd, 0xdd, 0xae, 0x71, 0xb6, 0x13, 0xf6, 0x59, 0x7c, 0x70, 0x75, 0xc4, 0xd2, 0x8d, 0xdb, 0xae, 0x1e, 0xfa, 0xcf, 0x03, 0x59, 0x71, 0xab, 0x63, 0xee, 0x90, 0xdb, 0xbd, 0xfb, 0xda, 0x43, 0x25, 0xa1, 0x5f, 0xbf, 0x84, 0x5e, 0xea, 0x54, 0xbb, 0xcd, 0x05, 0x57, 0x4b, 0x1c, 0xd6, 0x01, 0xdc, 0xad, 0xba, 0x12, 0x06, 0x28, 0x05, 0xb9 } +, + /* Prime 2 */ + 64, + { 0xe0, 0xe1, 0xad, 0x57, 0xd6, 0x8f, 0x30, 0x13, 0x28, 0x8c, 0x14, 0x83, 0xe8, 0xc5, 0xb1, 0x2e, 0xfe, 0xb6, 0xec, 0x14, 0x5a, 0xe4, 0x18, 0x8e, 0x1b, 0x3b, 0x39, 0x04, 0x87, 0x90, 0x0a, 0xd2, 0xc3, 0x25, 0xd2, 0x32, 0x80, 0x6a, 0x62, 0x17, 0x34, 0x2a, 0x65, 0x75, 0x95, 0x14, 0xf2, 0x26, 0x8f, 0xca, 0x72, 0xc4, 0xc5, 0xbb, 0xa0, 0x32, 0x81, 0x89, 0xdc, 0xfa, 0xe2, 0x06, 0xae, 0xc9 } +, + /* Prime exponent 1 */ + 64, + { 0x3b, 0xb6, 0xd2, 0xd5, 0x1d, 0xf9, 0x3d, 0xb4, 0xb2, 0x75, 0xd4, 0x5e, 0x8e, 0x76, 0x9a, 0xf8, 0xef, 0xfd, 0x6b, 0xc5, 0x4b, 0xc8, 0x8c, 0xf9, 0x49, 0xf1, 0x48, 0x57, 0x3e, 0x68, 0xbf, 0x4f, 0xcc, 0x0f, 0x76, 0xe6, 0x79, 0xe6, 0x9e, 0x13, 0x67, 0xb9, 0xd7, 0xab, 0x1d, 0x8d, 0xe9, 0x31, 0x8b, 0x34, 0xb0, 0xa4, 0x2a, 0x3f, 0x0b, 0xa2, 0x35, 0x1b, 0x4e, 0xc0, 0x6f, 0x45, 0x89, 0xf1 } +, + /* Prime exponent 2 */ + 64, + { 0x71, 0xf4, 0xaa, 0x5c, 0x8a, 0x93, 0x80, 0xaf, 0x14, 0xaa, 0xf7, 0x72, 0x68, 0xb0, 0x55, 0x3b, 0x15, 0x44, 0x28, 0x99, 0x9f, 0xfd, 0x5a, 0x1c, 0x18, 0xdc, 0x87, 0xe6, 0x2d, 0xb3, 0xe6, 0x68, 0x2b, 0x0f, 0xad, 0x56, 0x7e, 0x10, 0x6a, 0xa8, 0x8b, 0x7c, 0xb8, 0x71, 0x3f, 0x1c, 0xa0, 0x20, 0xbe, 0x58, 0xbe, 0x93, 0xcc, 0x07, 0x6a, 0x04, 0x6d, 0xf4, 0x28, 0x90, 0xd1, 0x9c, 0xc5, 0x51 } +, + /* Coefficient */ + 64, + { 0x23, 0x1a, 0xb8, 0xdd, 0x9a, 0x56, 0x99, 0xd7, 0x97, 0x59, 0x11, 0xef, 0x0e, 0xf8, 0x7c, 0x28, 0xdd, 0xb9, 0x2e, 0x24, 0x6e, 0xc3, 0x4c, 0x5f, 0xac, 0x33, 0x83, 0x22, 0xdd, 0xec, 0x89, 0x8d, 0x56, 0x68, 0x67, 0x45, 0x3d, 0xe6, 0xd7, 0x8a, 0x45, 0xc3, 0x16, 0xb1, 0x45, 0xa2, 0x86, 0x18, 0x94, 0x0e, 0x1a, 0xcd, 0x11, 0x58, 0xc3, 0xaf, 0x92, 0xfa, 0xab, 0xfd, 0xc3, 0x97, 0x84, 0x32 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 6.1", + /* Message to be signed */ + 74, + { 0x8f, 0x75, 0x0e, 0x65, 0x95, 0x1b, 0x5d, 0xe7, 0x58, 0x14, 0xb0, 0xb7, 0x66, 0x30, 0xdc, 0x9f, 0x1c, 0x62, 0x53, 0xa0, 0x59, 0x0e, 0xac, 0xb5, 0x51, 0x2a, 0x8a, 0x4e, 0x1a, 0x8b, 0xe8, 0x52, 0x5d, 0x36, 0x94, 0x1f, 0xa9, 0xd0, 0x92, 0xf6, 0xbb, 0x44, 0x22, 0xaa, 0x8c, 0x0a, 0xd6, 0x42, 0x3e, 0xa2, 0x8c, 0x10, 0xca, 0xa6, 0xe9, 0x54, 0xb7, 0x95, 0x69, 0xd4, 0x4c, 0x86, 0x0f, 0x1c, 0x65, 0x81, 0xeb, 0x17, 0xa7, 0x54, 0x3e, 0x7b, 0xf7, 0xfe } +, + /* Signature */ + 128, + { 0xb1, 0x8b, 0x5e, 0xc8, 0x8d, 0x4e, 0x24, 0xc9, 0x14, 0xb6, 0x65, 0xff, 0x9a, 0x2c, 0x75, 0xf4, 0xe9, 0x19, 0x37, 0xdf, 0x8c, 0x19, 0x95, 0x59, 0x43, 0xe4, 0x51, 0xad, 0xdf, 0x34, 0x84, 0xe4, 0x97, 0x97, 0x8d, 0x26, 0xda, 0x23, 0x1a, 0xf1, 0x4d, 0x9c, 0x29, 0x27, 0xed, 0x21, 0x0a, 0xfb, 0xf9, 0xde, 0xe3, 0x32, 0x67, 0xaa, 0x45, 0x68, 0x46, 0x49, 0xe8, 0x6f, 0xb2, 0x25, 0xa0, 0x53, 0xb5, 0x45, 0x52, 0x90, 0xc3, 0x20, 0xe3, 0xf6, 0x40, 0x62, 0x3c, 0x75, 0xca, 0x42, 0x37, 0x21, 0xf2, 0x80, 0xb8, 0x87, 0x44, 0x24, 0x97, 0xf3, 0x2a, 0x90, 0xd7, 0x8f, 0x64, 0x44, 0x04, 0x77, 0xad, 0x09, 0x27, 0xc7, 0xba, 0x01, 0xc4, 0x4d, 0xa9, 0xd5, 0xc2, 0x83, 0xa4, 0x38, 0xbe, 0x0d, 0xc5, 0x80, 0xa0, 0x05, 0x28, 0xfc, 0x65, 0xe2, 0x04, 0xd4, 0x2a, 0x2d, 0x4e, 0x29, 0x13, 0xc1 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 6.2", + /* Message to be signed */ + 53, + { 0xbd, 0xbf, 0x3b, 0x36, 0x40, 0x73, 0xfe, 0x04, 0x8f, 0xba, 0xe5, 0x5e, 0x3c, 0xde, 0x66, 0x8e, 0x84, 0xf7, 0x53, 0xab, 0xfc, 0x71, 0x0b, 0x8c, 0xdb, 0x7b, 0x6c, 0x0c, 0xf8, 0x2d, 0xd5, 0xb6, 0x74, 0xd2, 0x1e, 0x2b, 0x3e, 0x36, 0xb1, 0xb0, 0x36, 0x0d, 0xf8, 0xbf, 0x7e, 0x62, 0x27, 0xc9, 0x2e, 0x15, 0xf3, 0xd7, 0x84 } +, + /* Signature */ + 128, + { 0x66, 0xac, 0xf0, 0x43, 0xbc, 0x6a, 0xae, 0x81, 0xa4, 0xd5, 0x2b, 0x4e, 0x8c, 0x40, 0x12, 0x8b, 0x25, 0xc6, 0xd1, 0x0a, 0x8c, 0x69, 0x8c, 0x83, 0xae, 0xd7, 0x1e, 0x8f, 0x35, 0x83, 0x89, 0x8b, 0xe8, 0xf4, 0xc9, 0xbe, 0xa4, 0xb6, 0x31, 0x90, 0xe2, 0x15, 0x26, 0xca, 0xf8, 0x3a, 0xb1, 0x4a, 0x4f, 0x8b, 0xeb, 0xe8, 0x13, 0xa5, 0xab, 0xeb, 0x95, 0x95, 0x67, 0xbb, 0x2f, 0x06, 0xc5, 0xf1, 0x1e, 0x46, 0x4b, 0x5c, 0xdf, 0x7b, 0x2a, 0x13, 0x2d, 0x42, 0x6d, 0xdb, 0xec, 0xf5, 0x85, 0x90, 0x0a, 0x0d, 0x80, 0x92, 0xca, 0x52, 0xb6, 0xdc, 0x0a, 0xbc, 0x35, 0xf1, 0x40, 0x94, 0x69, 0x89, 0x46, 0xe1, 0xcd, 0x0e, 0xcd, 0x6b, 0xd4, 0x1e, 0x2c, 0x6f, 0x96, 0x3e, 0xe8, 0x9c, 0x82, 0x19, 0x3e, 0xcc, 0x5f, 0xd4, 0x76, 0x30, 0xd3, 0x4a, 0xd1, 0x6c, 0xa2, 0x47, 0x9e, 0xaf, 0x06, 0x2d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.3", + /* Message to be signed */ + 223, + { 0x3c, 0x5c, 0x74, 0xbc, 0x8f, 0xae, 0x80, 0x7a, 0xe5, 0x8b, 0xd2, 0x13, 0xe6, 0x27, 0x2a, 0xa3, 0x85, 0x79, 0x31, 0x57, 0x5c, 0x2a, 0xa2, 0xbe, 0x4b, 0xca, 0xe4, 0xd7, 0x9a, 0xe0, 0x87, 0xb6, 0xb8, 0x6f, 0x91, 0x5d, 0xf8, 0xc0, 0x96, 0xc1, 0x22, 0xed, 0xfb, 0xdc, 0x79, 0x7f, 0x9d, 0x70, 0xb9, 0x76, 0x13, 0x97, 0xfc, 0xe3, 0xd3, 0xe0, 0xb8, 0xa6, 0xf2, 0x56, 0xdb, 0xc6, 0x60, 0x5b, 0xa9, 0x48, 0xd5, 0xfb, 0xe6, 0xf5, 0x24, 0x5c, 0x02, 0x95, 0xce, 0x5d, 0xd7, 0x3b, 0xf7, 0x43, 0x65, 0x17, 0xf7, 0xc4, 0x22, 0x2d, 0x2c, 0xfd, 0x85, 0x42, 0xe7, 0xa1, 0x00, 0xcf, 0x05, 0x13, 0x04, 0xa1, 0xab, 0x6f, 0xe0, 0x05, 0xda, 0x07, 0x7b, 0x62, 0x87, 0x8f, 0xd0, 0xb7, 0x41, 0xe6, 0x27, 0x1e, 0x0d, 0x34, 0x6b, 0x20, 0x72, 0x3b, 0x7e, 0x00, 0xb3, 0xb8, 0x19, 0x4e, 0x1a, 0x46, 0x0c, 0x6b, 0xf2, 0x56, 0x00, 0x76, 0x82, 0x90, 0xc1, 0xdc, 0xaa, 0x2f, 0x41, 0xb9, 0x41, 0xa6, 0x4f, 0xd9, 0x02, 0x14, 0xd5, 0x16, 0x6d, 0x78, 0xaa, 0xbb, 0xaf, 0x7e, 0x41, 0xd2, 0x4f, 0xf6, 0x36, 0xc9, 0x76, 0x2f, 0xd8, 0x92, 0x19, 0x9d, 0x2c, 0xfd, 0x9d, 0xed, 0xa5, 0x00, 0x51, 0xe0, 0x01, 0xb9, 0xfd, 0x3e, 0x5e, 0x22, 0x27, 0xae, 0xcb, 0x15, 0xc1, 0xb3, 0x13, 0x71, 0xb3, 0x5a, 0x78, 0xb3, 0xb8, 0xb7, 0x63, 0x63, 0x76, 0xf1, 0x34, 0x56, 0x2b, 0x4e, 0x52, 0xf4, 0x51, 0xb7, 0x41, 0xa1, 0x9a, 0xc9, 0x32, 0x56, 0x9f, 0xf3, 0x04, 0x1f, 0xaf, 0x12, 0x27, 0x9f, 0x90 } +, + /* Signature */ + 128, + { 0x5e, 0x89, 0x7f, 0x87, 0x9b, 0xa4, 0x6f, 0x67, 0x11, 0x2c, 0xd7, 0xc7, 0xc6, 0xfb, 0x27, 0x37, 0xad, 0x79, 0x3a, 0x87, 0x28, 0x79, 0x05, 0x2a, 0x88, 0x45, 0x7a, 0xf5, 0xe9, 0xd5, 0x99, 0x59, 0xa8, 0x48, 0x13, 0x4a, 0x68, 0x24, 0xde, 0x3a, 0x67, 0x4f, 0x72, 0xa9, 0x06, 0x87, 0x9e, 0x95, 0xbe, 0x0e, 0xd8, 0x7e, 0xa9, 0xf9, 0x74, 0xa7, 0xa0, 0x7b, 0xa9, 0xad, 0xbe, 0xc2, 0xfb, 0xfa, 0x02, 0x94, 0x37, 0x8b, 0x14, 0xe7, 0x35, 0xf5, 0x5f, 0x40, 0x3c, 0xa0, 0x53, 0x08, 0x4f, 0x51, 0xd3, 0xd3, 0x42, 0xd8, 0xaf, 0x9c, 0x64, 0xb4, 0xd1, 0x54, 0xad, 0x9a, 0xa3, 0xc6, 0xbc, 0xaa, 0xce, 0x1f, 0x1b, 0xbe, 0x62, 0xee, 0xb5, 0xd0, 0xe6, 0xc4, 0xc0, 0x30, 0x93, 0xc2, 0xaf, 0x0f, 0x07, 0x88, 0x8b, 0x8b, 0xbe, 0xfa, 0x79, 0x40, 0x03, 0x23, 0x13, 0x3f, 0x77, 0x6a, 0x32, 0x13 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.4", + /* Message to be signed */ + 61, + { 0x42, 0x56, 0x46, 0x65, 0x0d, 0x6b, 0x37, 0x9e, 0x16, 0xe1, 0x5b, 0xf3, 0x85, 0x3d, 0xdc, 0x9d, 0x44, 0x4f, 0x44, 0x53, 0x5c, 0x49, 0x3a, 0x37, 0x03, 0xb0, 0x01, 0x63, 0xaf, 0x34, 0x76, 0xdf, 0x37, 0x2a, 0x5b, 0x28, 0xf3, 0x34, 0xc0, 0x86, 0x03, 0x13, 0xe8, 0x13, 0x6d, 0xe6, 0x08, 0x29, 0x1b, 0x33, 0x78, 0x38, 0x1b, 0x9e, 0x21, 0xeb, 0xef, 0x24, 0x82, 0x5d, 0x12 } +, + /* Signature */ + 128, + { 0xa6, 0xa0, 0xcb, 0x02, 0x48, 0x1a, 0xf2, 0x48, 0xab, 0xae, 0x89, 0xcd, 0xf4, 0x16, 0x1f, 0x67, 0x76, 0xd4, 0x71, 0x08, 0xf1, 0x8e, 0xc6, 0xe8, 0x43, 0x7c, 0x22, 0x4a, 0x14, 0xf4, 0x52, 0xad, 0xa1, 0x36, 0x52, 0x0f, 0x0f, 0xe0, 0x10, 0xa7, 0x34, 0x5a, 0xf1, 0x97, 0x1a, 0x02, 0xe4, 0xbc, 0xf8, 0xc9, 0x8b, 0x26, 0xc5, 0xb8, 0xc6, 0x00, 0x3d, 0xe4, 0xd2, 0xb4, 0x07, 0x2d, 0x8d, 0xef, 0x1e, 0x19, 0x23, 0xd9, 0xcc, 0xe0, 0xa6, 0x75, 0x14, 0x1d, 0x37, 0x87, 0x3e, 0x59, 0x48, 0xea, 0x6c, 0x8a, 0x78, 0x0e, 0xd2, 0xa5, 0xec, 0xc2, 0xba, 0x9a, 0x81, 0x20, 0x6c, 0x7e, 0xcc, 0xc8, 0x0e, 0xac, 0x02, 0x6d, 0xb7, 0xd7, 0x60, 0x22, 0x3a, 0xa2, 0x38, 0x7a, 0x18, 0x2e, 0x98, 0xd6, 0x6f, 0x1e, 0x23, 0xdf, 0xea, 0xf3, 0x51, 0x5c, 0xee, 0x4f, 0xa1, 0xab, 0xd4, 0x64, 0xb7, 0x68 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.5", + /* Message to be signed */ + 85, + { 0xf4, 0x7d, 0x87, 0xbf, 0xd4, 0x88, 0xaf, 0x5b, 0x24, 0xdb, 0x34, 0xad, 0x0c, 0x13, 0x1e, 0xfc, 0xa1, 0x0c, 0xdd, 0x1a, 0xae, 0xff, 0xbe, 0x6e, 0x36, 0x48, 0x47, 0x22, 0xed, 0x68, 0x09, 0xb1, 0xd5, 0x7a, 0x18, 0x3b, 0xa0, 0x3d, 0x5e, 0x40, 0x5d, 0x12, 0x56, 0xb2, 0x50, 0x5e, 0xcb, 0x84, 0xdb, 0x35, 0xdf, 0xa9, 0x4d, 0xe8, 0x5d, 0xc2, 0xa1, 0x58, 0x8b, 0x6e, 0x83, 0x12, 0x4c, 0xf8, 0x6c, 0x5e, 0x91, 0x66, 0x86, 0x0d, 0x4d, 0xd4, 0x71, 0x70, 0x43, 0x2b, 0x08, 0xae, 0x6a, 0x6e, 0x30, 0x87, 0x10, 0x86, 0xfa } +, + /* Signature */ + 128, + { 0x6c, 0x00, 0x8f, 0xf0, 0xe1, 0x28, 0xfc, 0xec, 0x26, 0x5f, 0x37, 0x9e, 0xb0, 0x83, 0xdb, 0x50, 0x62, 0x4a, 0x27, 0x98, 0xf9, 0x33, 0x67, 0xc6, 0xd1, 0x6e, 0x5d, 0x95, 0xa9, 0x89, 0xf4, 0xf1, 0xee, 0xd0, 0xcc, 0x4c, 0xd8, 0x61, 0xc6, 0xa5, 0x24, 0xf2, 0xb9, 0xfa, 0x30, 0xe8, 0x86, 0xf1, 0x47, 0x77, 0x41, 0xd7, 0xea, 0x8a, 0x60, 0xdf, 0x14, 0x0a, 0xec, 0xf3, 0xa6, 0xcc, 0xf0, 0x04, 0x3d, 0xab, 0x92, 0xcb, 0xe7, 0x29, 0x53, 0xcb, 0x1c, 0x18, 0x41, 0xe0, 0x59, 0x18, 0xec, 0xed, 0x5b, 0x0f, 0x69, 0x4a, 0xf9, 0xa9, 0x8e, 0xc7, 0xf4, 0xe2, 0x28, 0x6d, 0x23, 0x3d, 0xfd, 0x35, 0x13, 0x2a, 0x0b, 0x58, 0x4b, 0xf0, 0xe0, 0xdc, 0xbf, 0x05, 0x11, 0x9c, 0xe2, 0xe3, 0xa4, 0xd8, 0x13, 0xcf, 0x02, 0x8f, 0xec, 0x48, 0xc3, 0x4a, 0x18, 0x81, 0xeb, 0xb5, 0x31, 0xca, 0x48, 0x9b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.6", + /* Message to be signed */ + 6, + { 0x03, 0x18, 0x78, 0xd5, 0x88, 0xee } +, + /* Signature */ + 128, + { 0xcc, 0x15, 0x4e, 0x1a, 0xf7, 0x13, 0xf2, 0xf9, 0x5e, 0x16, 0xf4, 0x11, 0x17, 0x5d, 0x98, 0x36, 0xad, 0x6d, 0x8b, 0xbd, 0xc8, 0xf9, 0x8c, 0xf0, 0x5c, 0xfa, 0x00, 0x58, 0x23, 0x5d, 0x1f, 0xdd, 0xe0, 0x40, 0x82, 0x76, 0x4c, 0x29, 0xdc, 0xdc, 0xc5, 0x9e, 0xbe, 0x26, 0x57, 0x8b, 0xf9, 0xe8, 0xad, 0x6a, 0x5a, 0xa8, 0x6b, 0x9d, 0x62, 0x91, 0x4b, 0x4c, 0xf6, 0x96, 0xa8, 0xec, 0x2d, 0xa8, 0x79, 0xf8, 0xfa, 0x42, 0x31, 0x46, 0x31, 0x32, 0xea, 0xd7, 0xbb, 0x3b, 0xe7, 0x50, 0xae, 0x0c, 0x56, 0x28, 0xa3, 0x96, 0xb7, 0x0a, 0xdf, 0xa2, 0x7b, 0x40, 0x34, 0x23, 0xb1, 0x00, 0x18, 0xf9, 0xd2, 0x4f, 0xea, 0x33, 0x70, 0x30, 0x14, 0x7f, 0xbf, 0xaa, 0x15, 0xd4, 0x75, 0x32, 0xc9, 0x25, 0x7c, 0x2c, 0x7f, 0x54, 0x1b, 0x5b, 0x97, 0x4d, 0x15, 0xdd, 0x1e, 0x3f, 0xd2, 0xe2, 0x0a, 0x69 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.7", + /* Message to be signed */ + 136, + { 0x27, 0x26, 0x38, 0x52, 0xea, 0xa9, 0x60, 0xbf, 0x76, 0x71, 0x87, 0x6f, 0xc7, 0x90, 0x0f, 0x89, 0x8e, 0xa8, 0x2e, 0xb2, 0xb0, 0xfc, 0x41, 0x85, 0x65, 0xfd, 0xae, 0x62, 0xf7, 0xd9, 0xec, 0x4c, 0xe2, 0x21, 0x7b, 0x97, 0x99, 0x0d, 0xd2, 0x72, 0xdb, 0x15, 0x7f, 0x99, 0xf6, 0x3c, 0x0d, 0xcb, 0xb9, 0xfb, 0xac, 0xdb, 0xd4, 0xc4, 0xda, 0xdb, 0x6d, 0xf6, 0x77, 0x56, 0x35, 0x8c, 0xa4, 0x40, 0x11, 0x5d, 0x3e, 0x5b, 0x3d, 0xeb, 0x1b, 0xa1, 0xbd, 0x90, 0xca, 0x12, 0x86, 0xfd, 0x10, 0x0c, 0xaf, 0x9b, 0xe4, 0x85, 0xa4, 0x4a, 0x38, 0x45, 0x00, 0x57, 0x18, 0x10, 0x4b, 0xbd, 0xfc, 0x5e, 0x78, 0x1a, 0x9e, 0x37, 0xd6, 0x7a, 0xff, 0xe5, 0x56, 0xdc, 0xa1, 0x0f, 0x8e, 0xfa, 0x39, 0xf9, 0xcb, 0x63, 0x92, 0xa7, 0x2e, 0x3f, 0x28, 0x25, 0x81, 0x1a, 0x2c, 0x05, 0xaf, 0x84, 0xaf, 0x9b, 0xe7, 0xf3, 0x71, 0xdb, 0xd4, 0x10, 0x6d, 0x9f } +, + /* Signature */ + 128, + { 0x94, 0x79, 0x8d, 0x17, 0x94, 0x78, 0xbf, 0xe0, 0x6d, 0x96, 0xa3, 0x4a, 0xc9, 0x9b, 0xc9, 0xd5, 0xde, 0x35, 0xdc, 0x46, 0x97, 0xac, 0x3f, 0x70, 0xe9, 0xb3, 0x4c, 0x95, 0xe2, 0x2b, 0x1c, 0x30, 0xd1, 0x42, 0x6b, 0xe3, 0x50, 0x8e, 0x62, 0x2c, 0x1a, 0x18, 0xab, 0x3c, 0x46, 0x72, 0xfe, 0x3d, 0xe3, 0x40, 0xeb, 0x51, 0x0f, 0xb9, 0x87, 0xb5, 0x3a, 0xe9, 0x3a, 0x59, 0xaf, 0x6b, 0x00, 0xbb, 0xae, 0xe0, 0xe8, 0x27, 0x08, 0xe6, 0xc6, 0xae, 0x82, 0xc8, 0x45, 0x53, 0x24, 0x01, 0x78, 0x36, 0xdb, 0x17, 0x66, 0x0d, 0x06, 0x9d, 0x80, 0x27, 0x1e, 0x1e, 0xa9, 0x98, 0x11, 0x63, 0xb1, 0x4b, 0x66, 0x87, 0x6d, 0xfd, 0x12, 0x8f, 0x09, 0xcd, 0x2e, 0x3d, 0x6a, 0x36, 0xb7, 0x3c, 0x3b, 0x40, 0xad, 0x8e, 0x13, 0x24, 0x84, 0x90, 0x29, 0xc8, 0xb8, 0xe3, 0xc8, 0x89, 0x4e, 0xbf, 0xa1, 0x94 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.8", + /* Message to be signed */ + 200, + { 0xa4, 0xfb, 0x21, 0x03, 0xd0, 0xbe, 0x29, 0x0e, 0x99, 0x60, 0x16, 0xa4, 0x39, 0x46, 0x2e, 0x6b, 0xbd, 0xb0, 0x72, 0x4d, 0x86, 0xcd, 0x51, 0x85, 0x91, 0x33, 0xca, 0x3d, 0x39, 0xda, 0xb7, 0x7d, 0xa2, 0x06, 0x9d, 0x82, 0x83, 0x58, 0x96, 0x38, 0x7c, 0xcf, 0x3d, 0xf5, 0xcd, 0xd7, 0xa5, 0x79, 0x3f, 0x22, 0x3f, 0x3d, 0x92, 0x3e, 0xa4, 0x63, 0x51, 0x35, 0x31, 0xad, 0xa6, 0x67, 0xab, 0xfe, 0xf7, 0x53, 0x98, 0xc7, 0xa4, 0xbc, 0x6e, 0xfa, 0xdd, 0x4e, 0xde, 0xef, 0x35, 0xab, 0x8f, 0x54, 0x01, 0xe0, 0xda, 0xf7, 0xc2, 0xfc, 0xa1, 0xcd, 0xbb, 0xee, 0xd3, 0xbc, 0xdd, 0x09, 0x33, 0xff, 0x3e, 0xe4, 0xc5, 0xe2, 0x88, 0xab, 0xdf, 0x21, 0x9e, 0x36, 0xa3, 0xee, 0x6f, 0x21, 0x08, 0x41, 0xa0, 0x3c, 0x9e, 0x3e, 0x4d, 0xac, 0x18, 0x12, 0x24, 0x82, 0xef, 0x85, 0xf4, 0x9f, 0xda, 0xcd, 0xc5, 0x02, 0xd2, 0x79, 0xf1, 0x57, 0x7b, 0xe7, 0x7a, 0x4e, 0x00, 0xb7, 0xc7, 0xf1, 0x7b, 0xa5, 0xda, 0x6b, 0x28, 0xc0, 0x1a, 0x07, 0xa8, 0x63, 0xdf, 0xb2, 0x1c, 0x15, 0x6d, 0xa3, 0x20, 0x01, 0xf5, 0x3d, 0x7e, 0xa3, 0xfc, 0xb8, 0xc9, 0x55, 0x4f, 0x07, 0x54, 0x59, 0xa6, 0x7c, 0xc3, 0xc4, 0xe6, 0x9a, 0x6a, 0x37, 0x17, 0x87, 0x87, 0x46, 0x3c, 0xeb, 0xca, 0xed, 0xa6, 0x49, 0x0a, 0x8f, 0x80, 0xb3, 0x92, 0xde, 0xf9, 0xf2, 0x2a, 0x4f } +, + /* Signature */ + 128, + { 0x72, 0x66, 0x70, 0xc9, 0x51, 0x0b, 0x58, 0x35, 0x4c, 0x8a, 0xf3, 0x2b, 0x41, 0xdb, 0x8f, 0x69, 0x21, 0x07, 0xc0, 0xc8, 0x76, 0xe5, 0x52, 0x73, 0xa8, 0x20, 0xa0, 0xc3, 0x0d, 0x39, 0x24, 0x46, 0x0f, 0xa5, 0xbc, 0x33, 0xdf, 0xe1, 0x9d, 0x72, 0xe5, 0x63, 0x49, 0x28, 0x2a, 0x80, 0xfb, 0x12, 0xa8, 0xfa, 0x9e, 0xa4, 0xa5, 0xda, 0x69, 0xc5, 0x82, 0xd7, 0xc6, 0x41, 0x22, 0xa8, 0xa7, 0x91, 0xb3, 0x21, 0x2c, 0x39, 0xe0, 0x28, 0x26, 0x5b, 0x84, 0x54, 0xdf, 0x71, 0x5b, 0xa3, 0x0b, 0x00, 0x3d, 0x12, 0x91, 0x69, 0xcf, 0x12, 0x51, 0x1c, 0x0d, 0x3e, 0x7a, 0xae, 0xce, 0xf3, 0x79, 0x2c, 0xf1, 0x85, 0x64, 0x4c, 0xf8, 0x0e, 0x44, 0x81, 0x47, 0xb1, 0xa7, 0x96, 0x1a, 0xf3, 0x84, 0x41, 0x7d, 0x18, 0x2c, 0x6f, 0x85, 0x52, 0x46, 0xda, 0xd5, 0xb8, 0x93, 0xd9, 0xa7, 0x68, 0x0e, 0xbc } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.9", + /* Message to be signed */ + 160, + { 0xe5, 0x50, 0x6e, 0x04, 0xb1, 0x91, 0x84, 0x10, 0x76, 0x85, 0x87, 0x25, 0xa9, 0xfd, 0xd8, 0xf9, 0x74, 0x5f, 0x24, 0x2e, 0x99, 0x49, 0x4a, 0x42, 0x3f, 0x80, 0x36, 0x74, 0x74, 0x27, 0x1d, 0xce, 0x95, 0xa9, 0x9a, 0x2f, 0x71, 0x13, 0x4f, 0x39, 0xfb, 0x3f, 0x2e, 0x47, 0xc6, 0xa0, 0xb2, 0xfb, 0x6f, 0x61, 0x5b, 0x0d, 0xee, 0x6d, 0xf3, 0x3b, 0x28, 0xf8, 0xb0, 0xd4, 0x1e, 0x92, 0xd1, 0x42, 0xb1, 0x46, 0xe8, 0xcd, 0xe9, 0xb1, 0x1d, 0x6e, 0xc1, 0xd3, 0x7d, 0x71, 0xfd, 0x82, 0xb7, 0x19, 0xce, 0x1a, 0xdd, 0xb8, 0x21, 0xca, 0x4c, 0xaf, 0xbd, 0x2a, 0xa4, 0xf1, 0xe6, 0x11, 0xa2, 0x59, 0xe5, 0xf0, 0x5b, 0x53, 0x1f, 0xa1, 0x1e, 0x3b, 0x67, 0x1b, 0x7a, 0x5b, 0x10, 0xb4, 0xc8, 0x15, 0x6c, 0x25, 0xb0, 0xa5, 0x9e, 0xc6, 0xe1, 0x58, 0xf6, 0xd3, 0x46, 0xd8, 0x48, 0x04, 0xfc, 0xf9, 0x2a, 0x72, 0x76, 0x8f, 0x4e, 0xbc, 0x93, 0x5e, 0xee, 0x5c, 0xfe, 0xc7, 0xf6, 0xe6, 0xe8, 0x3c, 0xbe, 0x15, 0x8a, 0x13, 0x27, 0x5e, 0x84, 0x18, 0x3a, 0x94, 0xd7, 0x24, 0xb0, 0xe9, 0x66, 0x96 } +, + /* Signature */ + 128, + { 0x34, 0x22, 0x0e, 0xda, 0xfd, 0x4a, 0xc8, 0x84, 0xb9, 0xd0, 0x0f, 0xbb, 0xfb, 0x71, 0xa4, 0xa6, 0xc4, 0xd4, 0xb7, 0x1c, 0x19, 0x84, 0x22, 0x05, 0x07, 0x99, 0xd0, 0xc0, 0xfd, 0x54, 0xe9, 0x09, 0xa4, 0xca, 0xd2, 0x29, 0x8f, 0xaa, 0xb3, 0x34, 0x7a, 0x0a, 0xf0, 0xd2, 0x7d, 0x53, 0x01, 0xa8, 0x86, 0x00, 0x9c, 0xf5, 0xc6, 0xf1, 0x25, 0xdf, 0xc1, 0x13, 0x1a, 0xce, 0x38, 0x8b, 0xb2, 0x14, 0xc2, 0x84, 0x44, 0x20, 0xc0, 0x23, 0xdb, 0xc8, 0xb4, 0xa9, 0x66, 0x11, 0xb3, 0xb3, 0x93, 0xac, 0xc3, 0x83, 0x94, 0x90, 0xfc, 0x4e, 0xe2, 0xd3, 0x69, 0xb8, 0xc3, 0xc8, 0x76, 0x57, 0x22, 0x83, 0xef, 0x34, 0xd7, 0x0c, 0x64, 0x03, 0xef, 0x9e, 0x2e, 0x87, 0xa2, 0x76, 0xb2, 0x35, 0x72, 0xed, 0x82, 0xe2, 0x40, 0x22, 0x67, 0xc2, 0x73, 0x7f, 0x75, 0xbb, 0x4a, 0x27, 0xd3, 0xcf, 0x16, 0xd2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.10", + /* Message to be signed */ + 166, + { 0x8f, 0xc9, 0xcf, 0xa7, 0x21, 0xdf, 0xa0, 0x9b, 0xa0, 0x72, 0x9e, 0xf9, 0x18, 0x9e, 0x54, 0x27, 0xb3, 0xe7, 0x38, 0xc5, 0xae, 0x38, 0xa2, 0x65, 0x7f, 0x7c, 0x7e, 0x31, 0x4a, 0x49, 0xca, 0xeb, 0xa0, 0xfc, 0x9d, 0x45, 0x40, 0xf5, 0xf8, 0xd6, 0xc0, 0x47, 0x53, 0x60, 0x0e, 0xf6, 0xb9, 0xc3, 0x39, 0x65, 0x40, 0xf8, 0x6c, 0x11, 0x75, 0xb6, 0x0b, 0xf4, 0x0e, 0x3d, 0x8c, 0x84, 0x51, 0x35, 0x5e, 0x13, 0x74, 0xf4, 0x30, 0x43, 0xc0, 0xc6, 0xaa, 0x41, 0xd3, 0x79, 0x6b, 0xd8, 0x27, 0x9b, 0x3c, 0x30, 0x62, 0xb3, 0x74, 0x99, 0x6b, 0x7e, 0xae, 0xdd, 0x4d, 0xb0, 0xae, 0xe8, 0xc9, 0x4b, 0x93, 0xb1, 0x71, 0xfc, 0x41, 0x1d, 0x4d, 0xfc, 0x37, 0x28, 0xd0, 0x23, 0x15, 0x58, 0xcf, 0xc8, 0xfa, 0x45, 0xf9, 0x51, 0xb3, 0x5c, 0x9d, 0x46, 0x12, 0x18, 0xa6, 0x50, 0xc7, 0x02, 0xce, 0xa9, 0x3b, 0xb3, 0xfa, 0x14, 0x36, 0xed, 0x44, 0x5c, 0x95, 0x24, 0x9d, 0xc2, 0x20, 0x54, 0x71, 0x01, 0xb9, 0xa9, 0x3e, 0xb0, 0x14, 0xcd, 0x84, 0x3f, 0xf3, 0x9c, 0xe4, 0xc9, 0x6f, 0x82, 0xa3, 0x9f, 0x86, 0x3a, 0x4c, 0x2e, 0x1f, 0xa9 } +, + /* Signature */ + 128, + { 0xa2, 0x6e, 0x7d, 0xbd, 0x5d, 0xfe, 0x08, 0xc7, 0x2b, 0xd8, 0x0d, 0x5e, 0x26, 0x68, 0xd5, 0xd7, 0x2a, 0xbb, 0x1a, 0x0c, 0x04, 0x20, 0xff, 0x0e, 0xa8, 0x6a, 0x9c, 0x76, 0x08, 0xc4, 0x70, 0xe1, 0xc3, 0xf7, 0x2e, 0xbf, 0x44, 0x5d, 0x12, 0x18, 0x71, 0x81, 0x41, 0x55, 0x58, 0xdd, 0x03, 0xeb, 0xe4, 0x07, 0xaa, 0x06, 0xb5, 0x16, 0x47, 0xba, 0xfe, 0x0c, 0x85, 0xf3, 0xd3, 0xb8, 0xdc, 0xe9, 0x0c, 0xeb, 0xf0, 0xa0, 0xee, 0xcb, 0xac, 0x12, 0x28, 0xe7, 0x85, 0x82, 0x0c, 0x4f, 0x90, 0x9d, 0x2e, 0xf3, 0x92, 0xf0, 0x31, 0x17, 0x56, 0x1e, 0xc3, 0x8e, 0xb0, 0xd8, 0x8b, 0x02, 0x32, 0x72, 0xa4, 0x28, 0x63, 0x51, 0x62, 0x0f, 0x21, 0x04, 0x3c, 0xca, 0xf7, 0x50, 0x36, 0x84, 0x00, 0x29, 0x57, 0xef, 0x79, 0xbc, 0xff, 0x9d, 0x1c, 0x20, 0x1c, 0x42, 0xe0, 0x96, 0x0b, 0xd9, 0x69, 0x79 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.11", + /* Message to be signed */ + 238, + { 0x96, 0x1f, 0xe3, 0x4a, 0x21, 0x2c, 0xb0, 0xe6, 0xf6, 0xdc, 0xde, 0xcf, 0x1a, 0x4c, 0xb7, 0xb2, 0x14, 0x39, 0x0a, 0x77, 0xf4, 0x4d, 0x3a, 0x3b, 0x3e, 0xe2, 0xb1, 0x2f, 0x1f, 0x0e, 0xe3, 0x14, 0x2e, 0x9e, 0xaf, 0x70, 0x89, 0x55, 0xec, 0x83, 0x7e, 0xa1, 0xd0, 0xd2, 0x95, 0x4e, 0x6c, 0xe9, 0x50, 0xf3, 0x4c, 0x87, 0x30, 0x54, 0x8f, 0x2e, 0x09, 0x5d, 0x5d, 0xbb, 0x93, 0x8b, 0x19, 0x0b, 0x73, 0x8b, 0xff, 0x81, 0x71, 0x93, 0x02, 0xb6, 0x79, 0x8b, 0x76, 0x8b, 0x0b, 0xbd, 0xd2, 0xe2, 0xb9, 0x67, 0x2d, 0x89, 0x14, 0x05, 0xc7, 0x71, 0xa7, 0x79, 0x02, 0xfd, 0x54, 0x27, 0x42, 0x5a, 0xf0, 0x4e, 0x21, 0xb9, 0x1c, 0x5f, 0x39, 0x37, 0x20, 0x41, 0xe4, 0x94, 0xd9, 0xbe, 0x62, 0xde, 0xce, 0x31, 0xbd, 0x8a, 0x26, 0x2f, 0x6d, 0xdb, 0x84, 0x9f, 0x06, 0x8a, 0xa9, 0x9f, 0x7d, 0x62, 0x62, 0xe1, 0x84, 0xab, 0x9c, 0xb1, 0x62, 0x24, 0x47, 0xd6, 0x2f, 0xf6, 0x71, 0x09, 0x20, 0x30, 0x70, 0x71, 0xc2, 0x72, 0xbe, 0x0b, 0xb3, 0x7f, 0x0e, 0xef, 0x64, 0x5f, 0x99, 0xea, 0xb5, 0x1b, 0x0b, 0xcb, 0xbb, 0x64, 0x87, 0xd8, 0xd2, 0xb4, 0x9f, 0x3f, 0x23, 0xe0, 0xaa, 0x91, 0x8c, 0x89, 0xac, 0x85, 0x56, 0x53, 0xe1, 0xcc, 0xc0, 0x05, 0x91, 0x58, 0x0e, 0x0c, 0xe1, 0xe3, 0x87, 0x79, 0xc0, 0x4b, 0xe7, 0xdf, 0x1c, 0x66, 0x63, 0xac, 0xd9, 0x93, 0x7e, 0x47, 0x2b, 0x3e, 0xb6, 0xd4, 0xb7, 0x0a, 0x08, 0x0d, 0xe8, 0xe0, 0x35, 0x48, 0xf5, 0x12, 0x45, 0xbe, 0x7c, 0xe0, 0xb8, 0x6d, 0xee, 0xc1, 0x76, 0xe0, 0x0e, 0x54, 0xbd, 0x63, 0xbd, 0x5b, 0xb0, 0x2f, 0xc9, 0x54 } +, + /* Signature */ + 128, + { 0x98, 0xac, 0x47, 0x73, 0x59, 0x15, 0x9e, 0x93, 0xe1, 0xb3, 0x36, 0xee, 0x05, 0x60, 0x6d, 0x42, 0xb7, 0xe1, 0x25, 0x0d, 0x12, 0x95, 0x60, 0xc0, 0xd0, 0x95, 0xf8, 0xf8, 0xea, 0x3c, 0x04, 0x74, 0x32, 0xa9, 0x9c, 0x1e, 0xc4, 0xbc, 0x88, 0x7d, 0x7f, 0x07, 0xf6, 0x1d, 0xf1, 0x6f, 0x0c, 0x09, 0xf7, 0x15, 0xb7, 0x05, 0x38, 0x8b, 0xb8, 0xa6, 0x11, 0x87, 0x34, 0x6e, 0x8d, 0x7b, 0x07, 0xea, 0xb2, 0xfc, 0x05, 0xdb, 0x89, 0xe0, 0x30, 0x09, 0x44, 0xae, 0x37, 0x73, 0xe4, 0x4c, 0xb9, 0x2c, 0x5c, 0xf0, 0xf4, 0xfb, 0xe0, 0x1a, 0x05, 0xad, 0x79, 0xbf, 0xaa, 0x24, 0x7f, 0x83, 0xed, 0x1e, 0xda, 0x48, 0xba, 0xaf, 0xd1, 0xe1, 0x80, 0x07, 0x8c, 0xa8, 0xd3, 0x21, 0xd5, 0x0b, 0x42, 0x57, 0x87, 0xf0, 0x12, 0x43, 0xa4, 0x93, 0x37, 0x4e, 0x84, 0xf5, 0xcd, 0x56, 0xb7, 0x53, 0xd7, 0xac } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.12", + /* Message to be signed */ + 121, + { 0x96, 0xff, 0x0a, 0x5e, 0xca, 0xc9, 0x51, 0x16, 0xbd, 0x73, 0x43, 0x79, 0x5a, 0xf8, 0x3c, 0x87, 0xed, 0x9f, 0x83, 0x45, 0xd0, 0x3f, 0x6f, 0x32, 0x2f, 0x29, 0x54, 0x93, 0xf4, 0x0b, 0x19, 0xba, 0x8f, 0xfe, 0x2c, 0x89, 0x8c, 0x7b, 0x20, 0x66, 0x21, 0xf7, 0x2e, 0x02, 0xc7, 0xf0, 0xf0, 0x0f, 0x9f, 0x1c, 0x52, 0x3d, 0x73, 0xd3, 0x35, 0xa2, 0x6c, 0xed, 0xdc, 0x73, 0x98, 0xb7, 0xca, 0x20, 0x09, 0xca, 0xcb, 0xb1, 0x82, 0x83, 0xb7, 0x6b, 0x28, 0x15, 0xd1, 0xe9, 0x01, 0x00, 0x09, 0x6e, 0x95, 0xb8, 0x85, 0x30, 0xf1, 0xc4, 0x8c, 0x39, 0x61, 0xc4, 0x35, 0xbc, 0xe0, 0x28, 0x9f, 0xf6, 0x2e, 0x21, 0xbf, 0x4d, 0x3e, 0xc8, 0x99, 0xc8, 0x7e, 0x14, 0xc8, 0xea, 0xd7, 0x92, 0x2e, 0x79, 0x5e, 0x3e, 0x6f, 0x41, 0x80, 0xc0, 0x89, 0x9e, 0xa0 } +, + /* Signature */ + 128, + { 0x7c, 0x7b, 0x01, 0x57, 0xf6, 0xa5, 0x09, 0x09, 0x51, 0x09, 0x63, 0x28, 0x2f, 0x00, 0x11, 0x1e, 0xea, 0x70, 0x19, 0x37, 0x54, 0xe4, 0x27, 0xa0, 0x2b, 0x34, 0x6f, 0xeb, 0x68, 0x2f, 0x4c, 0x71, 0x87, 0xbb, 0x38, 0x1d, 0x31, 0xd2, 0x3b, 0x94, 0x76, 0x88, 0x43, 0x24, 0x5a, 0xad, 0x53, 0x61, 0xfc, 0xa4, 0x2d, 0x8b, 0x28, 0x4c, 0x8d, 0x92, 0xe6, 0xfb, 0x99, 0x2f, 0xa7, 0x71, 0x2f, 0xa5, 0xa9, 0x31, 0x55, 0xdf, 0x02, 0x0d, 0x30, 0x0a, 0x3b, 0xf8, 0x98, 0x86, 0x66, 0x8c, 0xf3, 0x7b, 0xd1, 0x3b, 0x55, 0x0a, 0xdb, 0x2d, 0x2a, 0x86, 0xc6, 0x9d, 0xaa, 0xac, 0xdc, 0x50, 0x30, 0xdc, 0x84, 0x34, 0x3c, 0x8b, 0x49, 0x34, 0xf0, 0x3c, 0xdc, 0x0e, 0xef, 0x0f, 0x6c, 0x1e, 0xa7, 0xec, 0x09, 0x62, 0x00, 0x79, 0x03, 0xb4, 0x48, 0x21, 0x7d, 0xe9, 0x3b, 0x75, 0x07, 0x54, 0x9b, 0x2e } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.13", + /* Message to be signed */ + 79, + { 0x32, 0xa1, 0x2e, 0x0c, 0x67, 0x0e, 0xd2, 0x15, 0xae, 0x54, 0x49, 0xa0, 0x91, 0x7a, 0xe9, 0x5e, 0x23, 0xdb, 0x80, 0x3a, 0xd2, 0x8a, 0x18, 0x42, 0xed, 0xfa, 0x90, 0xbc, 0x40, 0x5d, 0xd8, 0x9a, 0x1b, 0x46, 0x8a, 0xce, 0xbd, 0x08, 0xfe, 0x9c, 0x69, 0x3d, 0x8f, 0xb1, 0x05, 0xe8, 0x22, 0x2e, 0xb5, 0x7f, 0x79, 0xe4, 0xb2, 0x27, 0x00, 0xe0, 0x7f, 0x27, 0x6d, 0x4a, 0xec, 0xc7, 0xa1, 0x5f, 0xb7, 0x47, 0x33, 0x06, 0x56, 0x27, 0xb8, 0x79, 0xb0, 0x16, 0xee, 0xd4, 0xab, 0x4a, 0x1c } +, + /* Signature */ + 128, + { 0x85, 0xb9, 0x0e, 0xb8, 0x26, 0x51, 0x4a, 0x0e, 0xc0, 0xfc, 0x1b, 0xdc, 0x34, 0x86, 0xa8, 0xdc, 0x8b, 0x0f, 0x26, 0x3e, 0xfe, 0x57, 0xcf, 0x17, 0x50, 0xa4, 0x2a, 0x6b, 0x5b, 0x99, 0x72, 0x64, 0xfa, 0x61, 0x78, 0x64, 0x83, 0x7e, 0x63, 0x9f, 0x45, 0xd9, 0x20, 0x58, 0x41, 0xcd, 0xc1, 0x34, 0xab, 0xea, 0xcf, 0x6e, 0xe0, 0xec, 0xda, 0x09, 0xb9, 0x8d, 0x76, 0x9f, 0x51, 0xf3, 0x94, 0x7a, 0x33, 0x58, 0x7f, 0xf0, 0xc8, 0xdd, 0x01, 0xb7, 0xf6, 0xb2, 0x4a, 0x2f, 0xbf, 0x29, 0xc9, 0xff, 0xf7, 0x37, 0xee, 0xe5, 0x6a, 0xda, 0x2c, 0xeb, 0x74, 0x6b, 0x02, 0x5d, 0x95, 0x65, 0x22, 0xd9, 0x20, 0xd1, 0x2d, 0xdd, 0x13, 0xdb, 0xa0, 0x8b, 0x20, 0xe1, 0xee, 0xe1, 0x3a, 0x8b, 0x25, 0x80, 0xe5, 0x92, 0xc3, 0x4e, 0x39, 0x33, 0x37, 0x66, 0x11, 0x5a, 0x23, 0xb9, 0xd0, 0x0e, 0x2a, 0x42 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.14", + /* Message to be signed */ + 78, + { 0xbb, 0xda, 0x73, 0xcb, 0xe2, 0xbf, 0xf7, 0xff, 0x53, 0x62, 0xeb, 0xe9, 0x32, 0xc0, 0xa0, 0xdd, 0x68, 0xac, 0x84, 0xee, 0x99, 0x8f, 0xbf, 0x59, 0xa2, 0xa9, 0x26, 0x55, 0x20, 0x32, 0x31, 0x63, 0xb3, 0x0d, 0x9e, 0x70, 0x08, 0xb9, 0x4b, 0x0c, 0x0e, 0xbc, 0x5f, 0x6c, 0x4c, 0x97, 0x3c, 0x13, 0xff, 0x15, 0x3d, 0x31, 0x69, 0x0c, 0x3c, 0x95, 0xab, 0x23, 0x1f, 0x0c, 0x9e, 0xc9, 0x98, 0xfb, 0xfc, 0xad, 0xc2, 0x8b, 0x2d, 0x7f, 0x06, 0x50, 0x7e, 0x17, 0xd2, 0x1e, 0x82, 0xda } +, + /* Signature */ + 128, + { 0x26, 0xf9, 0x52, 0xb6, 0x57, 0xfd, 0xb9, 0xa1, 0x1d, 0xc8, 0x43, 0x79, 0x0c, 0x9d, 0x2a, 0x6a, 0x51, 0xc9, 0x76, 0x10, 0x1e, 0xfb, 0x82, 0xd0, 0x53, 0x60, 0x67, 0x62, 0xab, 0xa3, 0x3a, 0xf6, 0x28, 0x0b, 0xde, 0x38, 0x15, 0xe0, 0x87, 0x4d, 0x60, 0x78, 0x75, 0x38, 0x42, 0xe5, 0xb1, 0xc9, 0x0c, 0xf7, 0x99, 0x12, 0x20, 0xfc, 0xfa, 0x62, 0x28, 0x49, 0x43, 0x69, 0x0c, 0x30, 0x1e, 0x9f, 0xc6, 0xe4, 0x79, 0xaf, 0x68, 0xb9, 0x69, 0x47, 0x85, 0xbe, 0x40, 0xd4, 0x69, 0x86, 0xa6, 0x2a, 0x12, 0x1a, 0xa9, 0xad, 0x0d, 0xe9, 0x69, 0x52, 0x1f, 0x1c, 0xb8, 0xe7, 0xc4, 0xbd, 0x70, 0xc7, 0xc8, 0xcd, 0x7a, 0x9d, 0x13, 0x54, 0xe7, 0xd0, 0xaa, 0x0d, 0x85, 0xd6, 0xd7, 0xaa, 0x00, 0xe4, 0x64, 0x90, 0x26, 0xd6, 0xf0, 0x70, 0xf8, 0xb3, 0xc2, 0x7c, 0x98, 0x55, 0x6b, 0xea, 0xa4, 0xc0 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.15", + /* Message to be signed */ + 150, + { 0x2c, 0x32, 0x5d, 0xda, 0xf6, 0x52, 0x6a, 0x1e, 0xa3, 0x51, 0x8e, 0xe5, 0xe5, 0x40, 0x7f, 0x03, 0x90, 0xe0, 0xeb, 0xaa, 0xa5, 0xf4, 0x72, 0xa1, 0xe9, 0xab, 0x46, 0xf7, 0x46, 0xd7, 0x1b, 0xa2, 0xe2, 0x17, 0xfa, 0xa8, 0x17, 0x99, 0xbf, 0x35, 0x8f, 0x95, 0xe9, 0x83, 0x08, 0x27, 0x0b, 0x18, 0xa0, 0x01, 0x99, 0x29, 0xa2, 0x88, 0xd0, 0xc9, 0x56, 0xe0, 0xbf, 0x17, 0xc5, 0x19, 0x8c, 0xeb, 0x2c, 0xd9, 0xfe, 0x40, 0xd7, 0x02, 0xa4, 0x4e, 0x56, 0x45, 0xec, 0xa5, 0xb4, 0x39, 0xab, 0xca, 0x7b, 0x2c, 0x6f, 0x95, 0xac, 0xc3, 0xc2, 0xc3, 0x65, 0x19, 0x5c, 0x79, 0x5e, 0x91, 0xd6, 0x3b, 0x3c, 0x09, 0x33, 0x24, 0x4f, 0xf1, 0x25, 0x63, 0xaf, 0x66, 0x22, 0xa4, 0x0c, 0x74, 0x15, 0xdb, 0x60, 0xa7, 0x8d, 0xca, 0x02, 0x60, 0x25, 0x14, 0x39, 0x53, 0x8d, 0x38, 0xaa, 0x38, 0x28, 0x9d, 0x92, 0x88, 0x86, 0xab, 0x12, 0x87, 0x36, 0xa6, 0xa8, 0x73, 0x9c, 0x14, 0x55, 0xc4, 0x84, 0x9f, 0x2d, 0x54, 0x56, 0x45, 0x37, 0x93 } +, + /* Signature */ + 128, + { 0x6d, 0x1f, 0x20, 0x3d, 0xc3, 0xff, 0xa7, 0xa3, 0x34, 0xd3, 0x1b, 0x9a, 0x75, 0xe0, 0x12, 0x58, 0x1b, 0x8d, 0x62, 0xb2, 0xbf, 0x73, 0x80, 0x0b, 0xe5, 0x1d, 0x02, 0x65, 0x33, 0x99, 0x83, 0x18, 0xc0, 0xca, 0xc9, 0x2a, 0x02, 0xd4, 0x6d, 0x75, 0x9b, 0xf8, 0x0a, 0x41, 0xda, 0xa0, 0xa6, 0xa2, 0x9f, 0x4f, 0xa0, 0xbb, 0x60, 0x66, 0x4c, 0xac, 0xad, 0xe2, 0x4a, 0x65, 0xcb, 0x47, 0x65, 0x11, 0x09, 0xbe, 0xec, 0x82, 0x31, 0x91, 0x95, 0x25, 0xd1, 0x47, 0x32, 0x68, 0x74, 0x55, 0x78, 0xdb, 0x9e, 0x30, 0x64, 0x10, 0x8a, 0xe4, 0x6a, 0x48, 0x70, 0xf1, 0x80, 0x66, 0x78, 0x9b, 0x03, 0x66, 0xa7, 0xd0, 0xce, 0x37, 0xe0, 0x30, 0xb5, 0x89, 0x46, 0xec, 0x8c, 0x1a, 0x14, 0x11, 0x54, 0xdb, 0x0e, 0x26, 0x1b, 0xef, 0x8b, 0xaf, 0x2e, 0x9f, 0x65, 0xfc, 0xd1, 0x6b, 0x7d, 0x57, 0x97, 0xb6 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.16", + /* Message to be signed */ + 25, + { 0x29, 0x85, 0xe8, 0xb5, 0x50, 0x81, 0x2f, 0xb6, 0x6c, 0x18, 0xf8, 0x0e, 0x6f, 0x09, 0x2a, 0x94, 0x5d, 0x09, 0x15, 0x83, 0x86, 0x1b, 0x62, 0x5d, 0x1e } +, + /* Signature */ + 128, + { 0x2e, 0x84, 0x30, 0x13, 0xcd, 0x5e, 0x79, 0x5e, 0x21, 0x66, 0xc8, 0xe9, 0x1b, 0x06, 0xc3, 0x13, 0x1d, 0xc3, 0xa5, 0xe1, 0x21, 0x36, 0xd7, 0x16, 0x0f, 0xfd, 0x11, 0xbb, 0xef, 0xcf, 0x6a, 0xb6, 0x40, 0xe0, 0x5d, 0x76, 0xe0, 0xc6, 0x1e, 0xd3, 0x06, 0xf6, 0x08, 0x6b, 0xbb, 0x56, 0x7c, 0xa8, 0x7e, 0x40, 0xc6, 0x92, 0x4d, 0x5c, 0x84, 0xa6, 0xce, 0x28, 0xa8, 0x39, 0x50, 0xbd, 0x4b, 0x84, 0xe2, 0x7f, 0xc5, 0x06, 0x9f, 0xd0, 0x62, 0x4d, 0x50, 0xea, 0xc2, 0x4a, 0x94, 0x11, 0xb5, 0xf7, 0x67, 0x85, 0xd9, 0xdb, 0x5d, 0xa3, 0x0f, 0x42, 0x56, 0x95, 0xb0, 0x19, 0xb8, 0x4c, 0xdb, 0xb8, 0x25, 0xbd, 0x46, 0xe7, 0x35, 0x2e, 0x08, 0xf1, 0x14, 0xc8, 0x7b, 0x06, 0x6f, 0xe4, 0x3d, 0x10, 0x56, 0xa2, 0xc6, 0x10, 0xce, 0xa7, 0xe3, 0xd3, 0xdc, 0x98, 0xbf, 0x44, 0x97, 0xeb, 0x4f, 0x13 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.17", + /* Message to be signed */ + 146, + { 0x77, 0x78, 0x8e, 0x83, 0x8b, 0x83, 0x4e, 0x8f, 0x4d, 0x04, 0x5a, 0xa8, 0x94, 0xb9, 0x0a, 0xbb, 0x85, 0x94, 0x0c, 0xfc, 0x58, 0xd7, 0x72, 0x5e, 0x7f, 0x37, 0x3d, 0xa5, 0x54, 0x71, 0x37, 0xc6, 0x0b, 0xea, 0x75, 0x1e, 0x01, 0x42, 0xbf, 0x9a, 0x6f, 0x46, 0x49, 0xae, 0xb5, 0x46, 0xed, 0x56, 0x0c, 0xc4, 0xea, 0x15, 0x62, 0xd4, 0xa5, 0xfa, 0x3e, 0xb1, 0xb1, 0x14, 0x77, 0xa3, 0x05, 0x1e, 0x24, 0xc6, 0x06, 0xb8, 0xa7, 0x1c, 0x1a, 0x77, 0x4b, 0xdc, 0xf1, 0xa5, 0x31, 0x0f, 0xed, 0x55, 0x59, 0x23, 0x73, 0x0f, 0xa8, 0xaf, 0x4c, 0x15, 0x80, 0x0d, 0x36, 0x2b, 0x37, 0xad, 0xf1, 0x4f, 0x7a, 0xfc, 0xe7, 0x8e, 0xfa, 0x6b, 0xd8, 0x93, 0x56, 0x3e, 0xfe, 0x0b, 0x3b, 0x82, 0x8e, 0xbd, 0x49, 0x9f, 0x12, 0xa2, 0xfe, 0x33, 0x2b, 0xfe, 0x46, 0xdc, 0xbb, 0x31, 0x4b, 0xbd, 0xbf, 0x69, 0x08, 0x7e, 0x2a, 0x66, 0x5d, 0xf1, 0x10, 0x83, 0x5d, 0xe5, 0x5d, 0x61, 0xe5, 0xc2, 0x02, 0x5f, 0xd8, 0xdb } +, + /* Signature */ + 128, + { 0x8e, 0x5f, 0x33, 0x53, 0xc4, 0x9c, 0xbb, 0xb2, 0xea, 0x69, 0x6a, 0xbb, 0x57, 0x40, 0xba, 0xe0, 0x15, 0xef, 0xfd, 0x95, 0x0d, 0x56, 0x07, 0x13, 0x76, 0x05, 0xa1, 0x00, 0xc4, 0xa5, 0x3f, 0x1b, 0x95, 0x17, 0x6c, 0xaf, 0x34, 0x9f, 0x4f, 0xd5, 0x88, 0xae, 0xdd, 0xdc, 0xf5, 0x06, 0x0c, 0xcb, 0x72, 0x47, 0x8c, 0xfb, 0x09, 0x85, 0x62, 0xf3, 0x4d, 0x8f, 0x8e, 0xba, 0x44, 0x6a, 0x38, 0x47, 0x56, 0x5a, 0x7b, 0x89, 0x55, 0xad, 0x9e, 0x0c, 0x6e, 0xb6, 0x70, 0x99, 0xe1, 0xa4, 0x6c, 0x3e, 0xb2, 0xd4, 0x9d, 0x90, 0x90, 0xae, 0x5f, 0x63, 0xe8, 0xa0, 0x8b, 0x6e, 0x8f, 0x21, 0xf0, 0x03, 0xe4, 0x51, 0xd2, 0x50, 0xff, 0xc5, 0xa7, 0x90, 0xd6, 0x6a, 0x0e, 0x2e, 0x3e, 0x28, 0xa6, 0x33, 0x9f, 0xe9, 0x1d, 0x11, 0x29, 0x21, 0xf5, 0x5d, 0x12, 0x30, 0x30, 0x6f, 0xad, 0x5c, 0x01, 0x90 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.18", + /* Message to be signed */ + 62, + { 0x1d, 0x59, 0x9d, 0x76, 0x2c, 0xd5, 0x4d, 0xf7, 0x0f, 0x1a, 0x09, 0x83, 0xbc, 0x3e, 0xa2, 0xbb, 0xca, 0x6f, 0xcb, 0xbd, 0x16, 0x26, 0x03, 0xba, 0x81, 0x56, 0x10, 0x77, 0xfd, 0x92, 0x84, 0x92, 0x5c, 0xf1, 0xf1, 0xb0, 0x8b, 0xea, 0x1e, 0x70, 0xbc, 0x59, 0x5d, 0xf0, 0xb3, 0x43, 0xb8, 0x3b, 0x9c, 0xf3, 0xd6, 0x34, 0xf9, 0x5e, 0x37, 0xe8, 0xd1, 0xc5, 0x85, 0xfa, 0xb1, 0x99 } +, + /* Signature */ + 128, + { 0x71, 0x74, 0x97, 0xa4, 0xe6, 0x0d, 0xbf, 0xfa, 0x19, 0x6e, 0xff, 0x75, 0x8e, 0x90, 0x1c, 0xe1, 0xfe, 0x6e, 0x2b, 0xc7, 0xe1, 0xd5, 0x3a, 0x3d, 0xcf, 0x62, 0x25, 0x67, 0x1a, 0xf1, 0x46, 0xc5, 0xde, 0xe2, 0x00, 0xa8, 0x14, 0xf4, 0x89, 0x8d, 0x16, 0xa9, 0xb5, 0xf5, 0x08, 0xdc, 0x9f, 0xde, 0x4d, 0x64, 0x07, 0x0e, 0x55, 0xae, 0x3b, 0x1f, 0xdf, 0x79, 0x19, 0xf4, 0x2b, 0x7c, 0xff, 0xb7, 0xe9, 0x28, 0xc4, 0xca, 0xeb, 0x55, 0x2d, 0xc6, 0xfd, 0x08, 0x18, 0x34, 0xb2, 0xdc, 0x2f, 0xed, 0x07, 0xe7, 0xe6, 0x27, 0xd3, 0x4b, 0x39, 0x10, 0xca, 0x71, 0x3b, 0xf4, 0x15, 0x4e, 0xff, 0x99, 0x96, 0x57, 0x36, 0x15, 0x18, 0xfc, 0xe5, 0xa8, 0xf6, 0x42, 0xdc, 0x9a, 0x18, 0xa6, 0x6e, 0xde, 0x22, 0x19, 0x0f, 0x60, 0xaa, 0xf9, 0x58, 0xd6, 0x24, 0x6b, 0x00, 0xa0, 0x32, 0xc3, 0x98, 0x41 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.19", + /* Message to be signed */ + 169, + { 0xda, 0x51, 0x00, 0x86, 0x60, 0xb6, 0x3b, 0x87, 0x67, 0xe6, 0x5f, 0x12, 0xc6, 0x30, 0x8e, 0xc1, 0x8e, 0xd9, 0x57, 0x5a, 0x42, 0x6b, 0xc5, 0xfb, 0xe6, 0x60, 0x10, 0xec, 0x3f, 0x01, 0x17, 0x5f, 0xfa, 0x57, 0x41, 0xea, 0xcc, 0xdd, 0xb0, 0x2f, 0xce, 0x7b, 0x2e, 0xf7, 0x78, 0x44, 0x40, 0xd7, 0x2d, 0x37, 0x52, 0x20, 0x3f, 0x53, 0x4e, 0x52, 0xfc, 0xf6, 0x26, 0xa8, 0xc5, 0x96, 0x51, 0x3f, 0x41, 0x90, 0x64, 0xbb, 0xba, 0xfd, 0xe7, 0xf8, 0xd6, 0x5f, 0x30, 0xd7, 0xca, 0x68, 0x71, 0x89, 0x70, 0xde, 0x71, 0xfc, 0x8c, 0x0e, 0xed, 0x4d, 0xa0, 0x0a, 0x4e, 0x1a, 0xb5, 0x41, 0x02, 0xd9, 0xd1, 0x65, 0xbd, 0x7c, 0x54, 0xaf, 0x5c, 0x31, 0xc1, 0x5c, 0x05, 0xbc, 0xa5, 0x5b, 0x6f, 0xdd, 0x19, 0x10, 0x86, 0xa5, 0x3e, 0x52, 0x96, 0xf4, 0x84, 0xc3, 0x47, 0xd8, 0xfb, 0x94, 0x5a, 0x10, 0xc4, 0x94, 0x49, 0x75, 0x27, 0x32, 0xf6, 0x2f, 0x34, 0xc3, 0x25, 0x15, 0x58, 0x86, 0x51, 0x13, 0x79, 0x19, 0x28, 0x5a, 0x2c, 0x8e, 0xf7, 0xb4, 0xaa, 0x0e, 0x69, 0x0b, 0x0b, 0x65, 0x43, 0x7f, 0xf8, 0xd5, 0x6f, 0xc9, 0x5d, 0xcb, 0xc3, 0xe7, 0x8d } +, + /* Signature */ + 128, + { 0x32, 0x67, 0x72, 0x28, 0xff, 0x08, 0xc6, 0x6f, 0xd0, 0x3b, 0xb3, 0x1f, 0x0d, 0xfe, 0x89, 0x01, 0x53, 0xb3, 0x44, 0x6b, 0x57, 0xeb, 0x84, 0xef, 0x39, 0x56, 0x20, 0x8f, 0x72, 0xa0, 0x7c, 0x87, 0x67, 0xe6, 0xbf, 0x09, 0xf0, 0x38, 0xbc, 0xf7, 0xf7, 0x35, 0xee, 0x24, 0xa1, 0xf6, 0x40, 0xa1, 0x89, 0x8d, 0x40, 0x9e, 0xb5, 0x3a, 0xbd, 0xb6, 0x93, 0x94, 0x27, 0x34, 0x56, 0x9a, 0xf7, 0x1a, 0x4c, 0xd9, 0x9a, 0x65, 0x20, 0xba, 0xca, 0x5d, 0x42, 0x86, 0xb1, 0x99, 0xcc, 0x67, 0x62, 0x8e, 0x2f, 0xca, 0xd2, 0x96, 0xa3, 0x0e, 0xca, 0x49, 0x9e, 0xb8, 0x80, 0x50, 0x7f, 0x6a, 0x37, 0x44, 0x0b, 0x61, 0xc1, 0x28, 0x4c, 0x40, 0x3c, 0x41, 0x32, 0x1b, 0x99, 0x05, 0x3f, 0x5d, 0x69, 0x72, 0x8d, 0x5b, 0x97, 0x35, 0x76, 0xcf, 0x04, 0x74, 0x83, 0x33, 0xd8, 0x08, 0xd5, 0xe6, 0x8a, 0x8f } + +} +, +{ + "PKCS#1 v1.5 Signature Example 6.20", + /* Message to be signed */ + 50, + { 0x8c, 0xd2, 0xda, 0xd2, 0xa5, 0xd5, 0xf9, 0xfa, 0xa0, 0x7e, 0x24, 0xa9, 0x6e, 0x86, 0xf9, 0xb0, 0xac, 0x8b, 0x40, 0x22, 0x2a, 0xc9, 0xfb, 0x8a, 0x8a, 0x15, 0x72, 0x7c, 0xf2, 0xf5, 0x3e, 0x68, 0x4a, 0xf4, 0xab, 0xdc, 0x98, 0x68, 0xa7, 0x25, 0x3b, 0x25, 0xb0, 0x96, 0xbd, 0x70, 0x1f, 0x46, 0xa9, 0x43 } +, + /* Signature */ + 128, + { 0x8f, 0x03, 0x22, 0xeb, 0x2c, 0x54, 0x05, 0x24, 0x85, 0xa6, 0x45, 0x49, 0xad, 0xff, 0x2a, 0x36, 0x31, 0xdb, 0x65, 0x76, 0xfc, 0x0c, 0xaf, 0xb5, 0x51, 0x69, 0x7d, 0xc5, 0x35, 0x6f, 0x02, 0xe0, 0x93, 0xcb, 0x69, 0x17, 0x3a, 0x7e, 0x83, 0x55, 0xa0, 0xda, 0xde, 0xbf, 0xa5, 0x3c, 0xb2, 0x90, 0x7f, 0x00, 0x2d, 0xb3, 0xa3, 0xe3, 0x87, 0xda, 0x05, 0x7b, 0x7c, 0x73, 0x55, 0x16, 0x43, 0x84, 0x3e, 0xf5, 0x74, 0x48, 0x1f, 0x80, 0x74, 0x15, 0x17, 0x7e, 0x4b, 0x34, 0xc2, 0x5b, 0xd5, 0x5f, 0x4c, 0x02, 0xfa, 0x0a, 0xde, 0xa3, 0xa9, 0x58, 0x04, 0x65, 0xf3, 0x58, 0xc0, 0x05, 0x96, 0xb5, 0xcc, 0x06, 0x2d, 0x58, 0x92, 0x30, 0x3e, 0x1a, 0xcc, 0x11, 0x3c, 0x3b, 0x4b, 0xc7, 0x4d, 0x42, 0xe8, 0x58, 0x02, 0x90, 0x78, 0x48, 0x2a, 0x1b, 0x23, 0x4a, 0x62, 0x5b, 0x04, 0x28, 0x44, 0x06 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 7: A 1025-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x01, 0x69, 0x34, 0xcd, 0xff, 0x48, 0x50, 0xb6, 0x00, 0x2c, 0xc0, 0xf0, 0xf4, 0x01, 0x0a, 0x32, 0xc6, 0x55, 0xe5, 0xcf, 0x6e, 0x7c, 0x89, 0x93, 0x7f, 0xd7, 0x55, 0xef, 0x6a, 0xbe, 0x37, 0x9d, 0xad, 0xde, 0x70, 0xcc, 0x21, 0x77, 0x51, 0xf1, 0x4c, 0xba, 0x6d, 0x90, 0xfe, 0x52, 0xdc, 0x0a, 0xf5, 0x8b, 0x25, 0x2f, 0x26, 0xbf, 0x72, 0xda, 0x57, 0x9f, 0xda, 0xf5, 0x7d, 0xdd, 0x6c, 0xd6, 0x02, 0x18, 0x79, 0x94, 0x9a, 0x02, 0x76, 0xb4, 0x43, 0x3f, 0xf0, 0x1e, 0xfc, 0xcc, 0xf3, 0x5a, 0x11, 0xe7, 0xc7, 0x7b, 0x38, 0xc1, 0x8c, 0xca, 0x94, 0xae, 0x01, 0x2d, 0x0f, 0x37, 0x04, 0x21, 0x49, 0x1c, 0x52, 0xad, 0x15, 0xac, 0x76, 0xb1, 0x2e, 0xcd, 0x21, 0x8f, 0x52, 0xe7, 0x57, 0x86, 0x6e, 0x08, 0x9d, 0xd8, 0xad, 0xbb, 0x48, 0xe9, 0xba, 0x89, 0x43, 0x36, 0xc5, 0x75, 0xc4, 0x06, 0x55 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0x0d, 0x17, 0x19, 0xe5, 0xbd, 0x47, 0x6d, 0x87, 0xc7, 0xec, 0xc3, 0x1e, 0xb8, 0xab, 0x42, 0x5d, 0x4f, 0xe4, 0xc8, 0xf5, 0xc7, 0xae, 0x23, 0x0a, 0x10, 0x47, 0x55, 0x3f, 0xfb, 0x53, 0x9f, 0xd3, 0x85, 0x5a, 0xf5, 0xa4, 0x3b, 0x2d, 0xdd, 0x4e, 0x95, 0xa2, 0xb3, 0x0d, 0x40, 0x7a, 0xa8, 0x81, 0x59, 0xbb, 0xad, 0x2a, 0x87, 0x3d, 0x80, 0x93, 0xb4, 0x8a, 0x4b, 0xce, 0x20, 0xad, 0x99, 0x26, 0x25, 0x3e, 0xd3, 0x39, 0xac, 0x3b, 0x54, 0x3f, 0xc7, 0x42, 0x96, 0x95, 0x33, 0x8d, 0xb0, 0xbc, 0x1d, 0xc3, 0x68, 0x6c, 0xfd, 0x13, 0x9b, 0xb5, 0xb2, 0x87, 0x36, 0xbc, 0x16, 0x60, 0xa9, 0x53, 0x48, 0xfc, 0x91, 0xc3, 0x25, 0xd0, 0x3a, 0x7f, 0xb2, 0x16, 0xd2, 0xd9, 0xcd, 0x93, 0x64, 0xde, 0x4e, 0xe7, 0xd2, 0x11, 0x9c, 0x3b, 0x0f, 0xbb, 0xa8, 0xa7, 0x1f, 0x0d, 0x3f, 0x5a, 0xb9, 0xb9 } +, + /* Prime 1 */ + 65, + { 0x01, 0x58, 0xc0, 0x24, 0x6c, 0xd1, 0x69, 0xfc, 0x59, 0x3b, 0x25, 0x8b, 0xbf, 0x45, 0x23, 0xab, 0x2b, 0x55, 0xc4, 0x60, 0x73, 0x3a, 0x7f, 0xb4, 0x69, 0x10, 0x90, 0x77, 0xb3, 0x0e, 0x4d, 0x35, 0xf2, 0x1a, 0x35, 0xb1, 0xf4, 0x1e, 0x42, 0x04, 0xe8, 0x1d, 0x2e, 0x4c, 0x46, 0x3c, 0x24, 0x11, 0x39, 0x34, 0x09, 0x8b, 0x45, 0x2d, 0xab, 0x4b, 0xe1, 0x59, 0x97, 0x20, 0xef, 0x68, 0x72, 0x83, 0x3d } +, + /* Prime 2 */ + 65, + { 0x01, 0x0c, 0x38, 0x2d, 0xea, 0x5e, 0x7d, 0x79, 0x29, 0x8c, 0x64, 0x1f, 0xb2, 0xe4, 0xfa, 0x09, 0xf2, 0x4f, 0x6a, 0x7a, 0x45, 0x9a, 0x88, 0x2c, 0x87, 0xa8, 0x03, 0x49, 0x5f, 0x05, 0x6e, 0xcc, 0x3b, 0x43, 0xc5, 0x37, 0x73, 0x1f, 0x85, 0xef, 0xc8, 0xfb, 0x53, 0x87, 0xad, 0x67, 0x31, 0xa6, 0x43, 0x53, 0x32, 0x15, 0xde, 0xcc, 0x38, 0x7d, 0x96, 0x76, 0x12, 0x2c, 0x17, 0x0e, 0x91, 0xe0, 0xf9 } +, + /* Prime exponent 1 */ + 64, + { 0xd5, 0x78, 0xdc, 0xd5, 0x38, 0xf2, 0xfc, 0xdc, 0x30, 0x00, 0xb6, 0xc0, 0xf0, 0x49, 0xfe, 0xe2, 0xad, 0x90, 0x14, 0xfd, 0x24, 0xfb, 0x10, 0xb6, 0x82, 0x18, 0x42, 0xd6, 0x70, 0x03, 0xa5, 0x64, 0xcd, 0x8f, 0xf4, 0x2a, 0x2a, 0x56, 0x4c, 0xfd, 0x81, 0x9c, 0x3a, 0x84, 0xbf, 0x16, 0xc2, 0x47, 0x7e, 0x8e, 0x6e, 0x5b, 0x9e, 0xc4, 0xd4, 0x0e, 0xad, 0x50, 0x24, 0x87, 0xba, 0x50, 0x36, 0x2d } +, + /* Prime exponent 2 */ + 64, + { 0x88, 0x88, 0xdc, 0x8e, 0xae, 0x94, 0xee, 0xa5, 0x80, 0xca, 0xc2, 0xfc, 0x1c, 0xe5, 0x4f, 0x44, 0xe2, 0xba, 0x50, 0x0d, 0xb8, 0x71, 0x53, 0x41, 0xa6, 0xfc, 0x2d, 0x50, 0x4a, 0x82, 0xb1, 0x42, 0x05, 0xe8, 0x91, 0xa6, 0x6f, 0xc8, 0x8d, 0x5c, 0x60, 0xdb, 0x8f, 0x78, 0x6c, 0xcc, 0x70, 0x57, 0x5b, 0x35, 0x66, 0xbe, 0xa8, 0x74, 0xa5, 0x31, 0x7f, 0x5f, 0x16, 0xc4, 0x91, 0xed, 0x1e, 0x79 } +, + /* Coefficient */ + 64, + { 0x17, 0xb0, 0xd6, 0x23, 0x36, 0x19, 0x1e, 0x63, 0xbc, 0xa1, 0x59, 0x93, 0x4d, 0x06, 0x16, 0xcb, 0x89, 0x97, 0x40, 0x9c, 0xbf, 0xca, 0x37, 0x05, 0x69, 0x5b, 0x14, 0xfb, 0x64, 0xa0, 0x81, 0xc1, 0xc9, 0xf5, 0x86, 0x19, 0x3e, 0x52, 0x3a, 0xbd, 0x0b, 0xeb, 0x8d, 0x72, 0x0c, 0xfe, 0x53, 0x7d, 0xfa, 0x1e, 0xde, 0xc4, 0xa6, 0x64, 0x37, 0xd2, 0x41, 0x19, 0x6b, 0x7a, 0x2c, 0xe5, 0x56, 0xc4 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 7.1", + /* Message to be signed */ + 157, + { 0x35, 0x39, 0x99, 0x7a, 0xe7, 0x09, 0xfe, 0x32, 0xc1, 0x03, 0x6a, 0x13, 0x27, 0x57, 0xf2, 0xa1, 0x66, 0x7a, 0x91, 0xcc, 0x83, 0xbe, 0x73, 0x3a, 0xad, 0xa1, 0xbd, 0xd2, 0x17, 0x92, 0x4c, 0x9a, 0x2c, 0x9f, 0xed, 0x1f, 0xec, 0xf6, 0x1d, 0x1c, 0xf7, 0x9d, 0xae, 0x9a, 0x83, 0xf8, 0xae, 0x3f, 0x4d, 0x05, 0x1b, 0x34, 0xfb, 0xb5, 0x59, 0xcb, 0xfd, 0xa4, 0x92, 0xf1, 0xd8, 0x3b, 0x8b, 0xeb, 0xa0, 0x45, 0xd4, 0xae, 0x1c, 0x8f, 0xea, 0x15, 0xb7, 0x57, 0x7a, 0x1b, 0x8a, 0x3f, 0x55, 0xba, 0xc1, 0x72, 0x7e, 0xdc, 0xa7, 0xf8, 0xf5, 0x2c, 0xb4, 0xba, 0x61, 0xca, 0xf1, 0xfa, 0x8f, 0x8f, 0xd9, 0xaa, 0xc7, 0x79, 0x09, 0x5c, 0xa8, 0x4c, 0x79, 0x91, 0x52, 0x9f, 0xb8, 0x06, 0x99, 0xd0, 0xd4, 0x68, 0x8d, 0xfd, 0xb1, 0x42, 0xed, 0x61, 0xa9, 0x5b, 0x89, 0xce, 0x33, 0x06, 0xbf, 0x97, 0x80, 0xe1, 0xb9, 0x1b, 0x84, 0x8c, 0x8d, 0x20, 0x03, 0x97, 0x0e, 0x52, 0x70, 0x2a, 0x1f, 0x61, 0x2e, 0x2f, 0x40, 0x17, 0xcf, 0xe0, 0xa9, 0x1d, 0xb9, 0xe4, 0x6d, 0xb9, 0xdc } +, + /* Signature */ + 129, + { 0x00, 0x08, 0x0f, 0x77, 0x0a, 0x2d, 0x1f, 0x6a, 0xbf, 0x5f, 0x22, 0x1f, 0x62, 0xe1, 0x66, 0xab, 0xd7, 0x9d, 0x06, 0xc7, 0xb9, 0xa8, 0x78, 0xd6, 0x1b, 0x80, 0xfc, 0x4d, 0x5b, 0xa2, 0x90, 0xb2, 0x3a, 0xba, 0xab, 0x51, 0x8f, 0x09, 0x44, 0x7e, 0x45, 0xae, 0xe6, 0xf3, 0xbd, 0x06, 0x10, 0x24, 0x44, 0x36, 0xa4, 0x73, 0x01, 0x60, 0xe6, 0xa6, 0x72, 0x11, 0x0c, 0x01, 0xae, 0xb5, 0x62, 0x4b, 0x71, 0x8d, 0xc7, 0xc0, 0x86, 0x1e, 0x58, 0x6b, 0xa8, 0xb6, 0x0a, 0x29, 0xd6, 0xa5, 0x75, 0x5c, 0xd2, 0xcc, 0x50, 0x85, 0x99, 0xc6, 0xe2, 0x8d, 0x73, 0x55, 0xb2, 0x7e, 0x40, 0xb7, 0x40, 0xc6, 0xfb, 0xbb, 0xb1, 0xa9, 0x18, 0x23, 0xb1, 0xc1, 0x24, 0x2b, 0xa6, 0x93, 0xd4, 0x52, 0x69, 0x51, 0x47, 0xdb, 0xb2, 0x3e, 0xa8, 0x9c, 0xbf, 0x11, 0xeb, 0x8b, 0x07, 0xec, 0x3a, 0x02, 0x7b, 0x0f, 0x17 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 7.2", + /* Message to be signed */ + 180, + { 0x31, 0x80, 0x08, 0x87, 0x3c, 0x4c, 0xfe, 0xa7, 0x12, 0x5e, 0xa6, 0xfd, 0x52, 0x15, 0xdf, 0xd9, 0x8d, 0x5c, 0x5e, 0x73, 0x32, 0x3f, 0x03, 0xf2, 0x15, 0xc6, 0x9c, 0x8f, 0x2b, 0xb1, 0x98, 0x3b, 0x59, 0xdf, 0xa6, 0xe9, 0x9a, 0xdd, 0x30, 0x69, 0x66, 0xf3, 0x11, 0x0c, 0x16, 0x1c, 0xa2, 0x26, 0x24, 0xb8, 0x80, 0x70, 0x26, 0x5b, 0x8f, 0x3f, 0x9d, 0x5d, 0xf7, 0x29, 0x91, 0xe7, 0x9e, 0x5b, 0x18, 0x9a, 0xa3, 0xd9, 0xcd, 0x9b, 0x20, 0x47, 0xcf, 0xa6, 0x1d, 0x01, 0x23, 0x4b, 0x23, 0x3d, 0x36, 0xac, 0x4b, 0x96, 0xed, 0x08, 0x16, 0x48, 0x87, 0x74, 0x90, 0xfa, 0x4a, 0x80, 0xec, 0x4c, 0xbb, 0xd9, 0xd2, 0xe0, 0x06, 0x2c, 0x39, 0xe1, 0x85, 0x3a, 0x0c, 0x38, 0x34, 0x4b, 0xa8, 0x58, 0xbd, 0x1d, 0x99, 0x5f, 0x6c, 0xaa, 0x28, 0xbf, 0x90, 0x40, 0x26, 0x26, 0x8a, 0x99, 0x72, 0x11, 0x43, 0xc8, 0x6a, 0x43, 0x43, 0xba, 0xf8, 0x9b, 0x6d, 0x55, 0x07, 0x64, 0x25, 0x1f, 0xb0, 0x7d, 0x16, 0x7b, 0x4c, 0x4b, 0x1b, 0x70, 0xf9, 0x9e, 0xf5, 0xfe, 0x50, 0xe6, 0x2e, 0x54, 0x13, 0xfc, 0xce, 0x0f, 0x99, 0x59, 0xc2, 0xa3, 0x78, 0xc4, 0x1d, 0x6f, 0x42, 0x36, 0x17, 0x8b, 0x14, 0xb8, 0x91, 0x9d, 0xb1, 0xd0 } +, + /* Signature */ + 129, + { 0x00, 0x6d, 0x54, 0x7d, 0xa4, 0xed, 0xcb, 0x10, 0x33, 0x15, 0xcb, 0x8e, 0x4b, 0x66, 0x9b, 0xee, 0x96, 0xaa, 0x21, 0x56, 0x23, 0x5c, 0xa5, 0xc3, 0xe3, 0x1b, 0x24, 0xa1, 0x5a, 0x13, 0x92, 0xe4, 0x94, 0x04, 0x7f, 0xed, 0xcb, 0x70, 0x81, 0x90, 0x7c, 0x56, 0x17, 0xa8, 0xaa, 0x18, 0xd1, 0x01, 0xb0, 0x53, 0x2a, 0x36, 0x32, 0x45, 0x19, 0x23, 0xc4, 0x8a, 0x75, 0xb0, 0xec, 0x21, 0x76, 0xcb, 0x98, 0xe5, 0xce, 0x51, 0x58, 0x8b, 0xcf, 0x86, 0x8e, 0x29, 0xd5, 0xd9, 0x69, 0x4f, 0x00, 0xae, 0x2c, 0x92, 0x4e, 0x73, 0xd2, 0xe6, 0xdd, 0x14, 0x4d, 0x24, 0xfa, 0x45, 0xd0, 0x12, 0x06, 0xa3, 0xf5, 0xd9, 0x36, 0x41, 0x3c, 0xcb, 0xb7, 0x4b, 0x0e, 0x2d, 0x04, 0x7d, 0x82, 0xb6, 0x00, 0xb8, 0x9d, 0x51, 0x59, 0x4f, 0xce, 0x7d, 0xe6, 0xbb, 0xd9, 0x5b, 0x97, 0xfc, 0xfe, 0xc5, 0x98, 0xc4, 0xeb } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.3", + /* Message to be signed */ + 37, + { 0x7f, 0x83, 0xb3, 0xe0, 0x54, 0xc0, 0x24, 0x82, 0x50, 0x78, 0xdd, 0x9f, 0x04, 0x0e, 0x1d, 0x09, 0x05, 0x82, 0x00, 0xc9, 0x75, 0x7b, 0x76, 0xfb, 0x37, 0x2b, 0x8b, 0x52, 0x66, 0xb9, 0xdc, 0x26, 0x9e, 0xc7, 0x56, 0x9d, 0x00 } +, + /* Signature */ + 129, + { 0x01, 0x34, 0xee, 0x21, 0x51, 0x51, 0xe5, 0x32, 0x50, 0xf5, 0xa0, 0x01, 0x6a, 0xcc, 0xe3, 0x70, 0x1e, 0x2a, 0x58, 0xdd, 0xaa, 0xd6, 0xcc, 0x36, 0x9d, 0xf0, 0xdc, 0xd9, 0x34, 0x6a, 0x2b, 0x53, 0x0f, 0xe3, 0x71, 0x5a, 0xfe, 0xff, 0x1e, 0x9b, 0xcb, 0x72, 0x08, 0x31, 0xc1, 0x25, 0x58, 0x97, 0x0a, 0x9e, 0x03, 0x89, 0x60, 0x04, 0xf2, 0x87, 0xad, 0xb8, 0x21, 0xf3, 0x17, 0xcf, 0x63, 0x93, 0x00, 0xca, 0xe6, 0xe9, 0x09, 0xe9, 0x1e, 0xd2, 0xa3, 0xea, 0xcb, 0x99, 0x52, 0xa7, 0xcc, 0x54, 0x94, 0x76, 0x52, 0x64, 0x24, 0x79, 0x51, 0xd2, 0x8c, 0x16, 0xaf, 0x03, 0xe2, 0x4b, 0x80, 0xee, 0x32, 0xb0, 0xb6, 0x2e, 0xdf, 0x10, 0xd7, 0x00, 0x91, 0x92, 0x71, 0x35, 0xf0, 0x5a, 0x88, 0x9f, 0x2f, 0x60, 0x56, 0xb9, 0x5c, 0xdd, 0xac, 0xe4, 0x7c, 0x69, 0xf9, 0x73, 0x08, 0xc0, 0xdf, 0x2e, 0xba } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.4", + /* Message to be signed */ + 198, + { 0x17, 0xeb, 0xc1, 0x50, 0x07, 0xbb, 0x5e, 0x4a, 0xf9, 0x17, 0x20, 0x1c, 0x3b, 0xa3, 0x84, 0x92, 0x65, 0x89, 0xc3, 0x15, 0x9a, 0x89, 0xd1, 0xab, 0xd4, 0xc2, 0xc9, 0x86, 0xfb, 0xa0, 0x37, 0x9e, 0x8a, 0xf1, 0x29, 0x75, 0xc5, 0xd0, 0x31, 0xd1, 0xbf, 0xc1, 0x5c, 0xa9, 0x17, 0x36, 0xf0, 0x7b, 0x17, 0x66, 0xd8, 0xb8, 0xa7, 0x2d, 0xb1, 0x0c, 0x26, 0x8c, 0x98, 0xfd, 0x7a, 0xa1, 0x1e, 0x29, 0x99, 0xf0, 0x6d, 0x86, 0x12, 0x7c, 0xc8, 0x89, 0xcf, 0x15, 0x0d, 0xcc, 0x73, 0x8f, 0x6a, 0xb8, 0xba, 0xae, 0x94, 0x3c, 0xc6, 0x06, 0xdd, 0x4d, 0x9e, 0xce, 0x70, 0x1a, 0x4a, 0x7b, 0x10, 0x1e, 0x35, 0x1d, 0xee, 0x20, 0xb1, 0x5e, 0xbc, 0x55, 0x25, 0x6d, 0xb3, 0xce, 0x46, 0xa6, 0xbd, 0x50, 0x61, 0x12, 0x5b, 0x62, 0xb9, 0x95, 0xe9, 0x70, 0xd1, 0x6f, 0x7c, 0x9a, 0x8f, 0xc1, 0x57, 0xff, 0x68, 0xce, 0xc7, 0xe6, 0x0f, 0x60, 0x8f, 0x66, 0x26, 0xdd, 0x39, 0x52, 0x8b, 0x24, 0x09, 0xaa, 0x2f, 0xf9, 0x32, 0xfc, 0x11, 0x9b, 0x2a, 0x7a, 0x81, 0x77, 0x2a, 0x57, 0x6b, 0x3d, 0x50, 0xa0, 0xd2, 0x87, 0xa7, 0xfa, 0x2d, 0xb8, 0x7d, 0x2b, 0x92, 0xe1, 0xc9, 0x61, 0xa7, 0x0c, 0xaa, 0x44, 0xd8, 0x81, 0x37, 0xb9, 0x50, 0xe1, 0x00, 0x71, 0x1a, 0x98, 0x54, 0xad, 0xfa, 0xfb, 0x49, 0x4d, 0x34, 0xe2, 0x86, 0x06, 0xa2, 0x7c } +, + /* Signature */ + 129, + { 0x01, 0x05, 0xda, 0xdc, 0x99, 0xc5, 0x9b, 0x5e, 0x3a, 0xc5, 0x54, 0xb1, 0xb5, 0xe7, 0x48, 0x0e, 0x5c, 0x0a, 0x62, 0xc7, 0xab, 0xae, 0xfd, 0xac, 0xf4, 0x42, 0x6e, 0xcc, 0xfe, 0x68, 0x6b, 0x8a, 0xaa, 0x1c, 0xa4, 0xf5, 0x1e, 0xba, 0xbf, 0xfa, 0x77, 0xd9, 0x98, 0x03, 0xe7, 0xee, 0x8d, 0x20, 0xd1, 0x20, 0x4a, 0xad, 0x8c, 0x67, 0x38, 0x5d, 0x07, 0x44, 0xc8, 0x54, 0xde, 0x2f, 0x99, 0x7a, 0x56, 0xaa, 0xae, 0x04, 0xce, 0xcc, 0x65, 0x65, 0x35, 0xc1, 0x6b, 0xb2, 0x14, 0x5d, 0x18, 0x01, 0x81, 0x25, 0x94, 0xa8, 0x01, 0x3b, 0x0e, 0xb5, 0x4e, 0x7b, 0xf6, 0x5d, 0x38, 0x42, 0x00, 0x54, 0xec, 0x46, 0xda, 0xc7, 0x1a, 0x12, 0x52, 0x08, 0xb3, 0x02, 0x21, 0x4a, 0x7c, 0x9b, 0x3a, 0x92, 0xca, 0x9b, 0xf7, 0x37, 0x39, 0xc7, 0x66, 0x30, 0x9a, 0xf8, 0x03, 0xed, 0xde, 0x7c, 0x54, 0xd2, 0x46 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.5", + /* Message to be signed */ + 51, + { 0x6a, 0x52, 0xba, 0x19, 0x0e, 0x44, 0xca, 0x0f, 0x10, 0x70, 0x02, 0x10, 0x48, 0x76, 0x2f, 0x3e, 0x79, 0xed, 0x51, 0xc9, 0x4f, 0x6d, 0xc1, 0xa9, 0xf1, 0xed, 0x78, 0x35, 0x2e, 0xf3, 0x79, 0xaa, 0x49, 0xb3, 0xa9, 0x38, 0x7e, 0x3c, 0xa7, 0xa1, 0x96, 0xf1, 0x05, 0xdc, 0xab, 0x18, 0x50, 0x6f, 0x29, 0x4a, 0x69 } +, + /* Signature */ + 129, + { 0x00, 0x0b, 0x70, 0xe6, 0x01, 0xc5, 0xec, 0x58, 0x68, 0x4e, 0x09, 0x18, 0xba, 0x7a, 0x53, 0x9e, 0x9d, 0x2d, 0xd2, 0x9b, 0x01, 0xa3, 0xf4, 0x53, 0xca, 0xd4, 0xa9, 0xa4, 0x0e, 0x50, 0xf5, 0xdb, 0xdf, 0x72, 0xc1, 0x10, 0x52, 0xf2, 0x0b, 0xe4, 0x4a, 0x5d, 0x38, 0x51, 0xb0, 0x1f, 0xd0, 0x9d, 0x9c, 0x92, 0x08, 0x47, 0x0f, 0x0a, 0x4a, 0x95, 0x03, 0x5e, 0x98, 0x9e, 0xed, 0x7d, 0x6b, 0x06, 0x2e, 0x13, 0xf4, 0x99, 0x5b, 0xf0, 0x93, 0x0b, 0x4a, 0x3d, 0x9b, 0x8a, 0x9e, 0xd7, 0x5e, 0x33, 0x88, 0x6e, 0x4b, 0x19, 0x4a, 0xb5, 0xcc, 0xd6, 0xb4, 0x12, 0x95, 0x9c, 0xb4, 0xf5, 0x49, 0x8b, 0xd3, 0x2f, 0x66, 0x85, 0x46, 0xbe, 0x2c, 0x00, 0x7a, 0xe8, 0xde, 0x5d, 0x98, 0x97, 0x7b, 0x94, 0xb1, 0x7e, 0x12, 0x63, 0x88, 0x4b, 0x54, 0xe7, 0x84, 0xb3, 0x8f, 0xc1, 0x12, 0xb8, 0xcb, 0xdd, 0x56 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.6", + /* Message to be signed */ + 236, + { 0xbb, 0xe0, 0xb9, 0xde, 0x2b, 0x5e, 0x9d, 0xcd, 0x31, 0x67, 0x42, 0x94, 0x3f, 0x92, 0x19, 0xb2, 0x4f, 0x66, 0xa3, 0x8f, 0x9d, 0xe7, 0x09, 0x46, 0x4f, 0xa5, 0x49, 0x5d, 0x79, 0x4a, 0x63, 0x7b, 0x9e, 0xbc, 0x06, 0x77, 0x62, 0xda, 0x7a, 0x6e, 0xef, 0xf0, 0x98, 0xfa, 0x44, 0xf3, 0xcc, 0x36, 0xf2, 0xcc, 0xef, 0x67, 0xfd, 0x46, 0xc5, 0x9e, 0x24, 0x73, 0x8c, 0x81, 0x0c, 0x69, 0xed, 0xdc, 0xd9, 0x0c, 0xc7, 0xd7, 0x1a, 0x4c, 0x3e, 0x69, 0x3b, 0xca, 0xa2, 0x8a, 0x53, 0x3d, 0x90, 0x4b, 0x41, 0xce, 0xd3, 0x39, 0x9b, 0x4c, 0x76, 0x47, 0xe5, 0xec, 0x4b, 0x3a, 0xd9, 0x03, 0x87, 0x0f, 0x5b, 0x5f, 0x8d, 0x6a, 0x8d, 0x81, 0x28, 0xae, 0x23, 0x81, 0xce, 0xc8, 0x6c, 0x4d, 0x85, 0xb7, 0x8a, 0x45, 0x1e, 0x1e, 0xa9, 0x7e, 0x33, 0x93, 0xff, 0xe9, 0x97, 0xe5, 0x46, 0xb0, 0x9c, 0x8c, 0xf8, 0x22, 0x52, 0xb3, 0x3f, 0x74, 0x5f, 0xee, 0xd4, 0x13, 0x32, 0x06, 0x51, 0x8e, 0x2b, 0x88, 0x03, 0x19, 0xdc, 0xdf, 0x91, 0x06, 0x71, 0x8a, 0xfb, 0x01, 0x6c, 0x51, 0x4b, 0x38, 0x05, 0x32, 0x65, 0xbc, 0x98, 0x79, 0x10, 0x0e, 0x47, 0xb0, 0x3e, 0xba, 0x03, 0x68, 0xf0, 0x9e, 0x29, 0x23, 0xac, 0x6f, 0x40, 0xa0, 0x4b, 0x75, 0x05, 0x4c, 0xd5, 0x05, 0xbb, 0xc8, 0x96, 0x5d, 0x64, 0x9a, 0x1b, 0xae, 0x7b, 0xb6, 0x64, 0x3c, 0xb7, 0x41, 0x95, 0xe9, 0x1c, 0x51, 0xf4, 0x18, 0x3d, 0xb2, 0xd7, 0x38, 0xce, 0x60, 0x35, 0x50, 0xd6, 0x34, 0xe6, 0xdd, 0x4f, 0x27, 0xf4, 0xda, 0xac, 0x61, 0x56, 0xcf, 0xa7, 0xe2, 0x46, 0x8b, 0x5d, 0x6a, 0xeb, 0x78, 0x29, 0x09 } +, + /* Signature */ + 129, + { 0x00, 0xc2, 0xe0, 0x74, 0xdf, 0xbc, 0xd0, 0xe7, 0x3a, 0xc0, 0x02, 0x1a, 0xeb, 0x99, 0x33, 0x10, 0x6b, 0x20, 0x1b, 0x93, 0xc1, 0x7a, 0x7b, 0xf9, 0x33, 0x56, 0xd2, 0x91, 0xfb, 0x4a, 0xae, 0xb3, 0xd1, 0x31, 0x63, 0x00, 0xa8, 0xde, 0x7b, 0x07, 0xe3, 0xd7, 0x79, 0xbc, 0xc2, 0x99, 0xe5, 0x2b, 0x6c, 0xb0, 0x30, 0x88, 0x01, 0x6d, 0xae, 0xb8, 0x41, 0x38, 0x2e, 0xb3, 0x43, 0x5f, 0x2e, 0x03, 0xeb, 0xf2, 0x2d, 0xc0, 0x86, 0xfb, 0x20, 0xeb, 0xe5, 0x3a, 0xc5, 0x45, 0x90, 0x24, 0x97, 0x63, 0xa2, 0x65, 0x5a, 0xa7, 0xeb, 0x0e, 0x7d, 0x38, 0x64, 0x93, 0x6b, 0x34, 0x00, 0x6a, 0x6c, 0x4f, 0xa0, 0x2d, 0x9c, 0xa1, 0x04, 0xad, 0xad, 0xa6, 0xaa, 0x01, 0xb9, 0x77, 0xb6, 0xde, 0xf2, 0x75, 0x06, 0x08, 0xa7, 0x8f, 0x3e, 0xd8, 0x3a, 0xd7, 0x12, 0xa7, 0xa1, 0xb0, 0xfb, 0xde, 0x7c, 0x7c, 0x8d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.7", + /* Message to be signed */ + 64, + { 0x83, 0xa4, 0x8b, 0xff, 0x88, 0x6d, 0x1d, 0x68, 0xf2, 0x92, 0x0a, 0x0e, 0xcf, 0xf2, 0x98, 0x32, 0x1a, 0x96, 0xf5, 0xca, 0xdc, 0xdf, 0xd8, 0xbe, 0x16, 0xb5, 0x0d, 0x34, 0xd6, 0x7d, 0x94, 0xcd, 0xb1, 0xa1, 0xbf, 0xa0, 0xea, 0xe2, 0x46, 0x99, 0xb6, 0x63, 0xc7, 0xba, 0x3a, 0x08, 0xa3, 0x90, 0xf7, 0x22, 0x58, 0x84, 0x85, 0x67, 0x94, 0xd1, 0x80, 0xc5, 0x46, 0xca, 0xc0, 0x6e, 0x41, 0x18 } +, + /* Signature */ + 129, + { 0x01, 0x2e, 0x81, 0xbd, 0x38, 0x63, 0x50, 0x65, 0xbf, 0x65, 0x54, 0x33, 0x6b, 0x00, 0xd1, 0x06, 0x18, 0x33, 0x05, 0x53, 0xe0, 0xe8, 0x08, 0x78, 0xaa, 0xd3, 0x55, 0xf0, 0x0d, 0x59, 0x40, 0xd8, 0xba, 0x45, 0x01, 0xc5, 0xc4, 0x9f, 0x10, 0x16, 0xd5, 0xf0, 0xe6, 0xa7, 0x3a, 0x4d, 0x9f, 0x87, 0x40, 0xd2, 0xcf, 0xc2, 0x5e, 0xa2, 0x48, 0xdf, 0x3f, 0x7b, 0x1a, 0xe8, 0xfc, 0xd2, 0x6b, 0xd5, 0x62, 0xe0, 0xf6, 0xeb, 0x77, 0x7f, 0x46, 0xd7, 0x57, 0x30, 0x69, 0xdb, 0x89, 0x07, 0xc0, 0x21, 0xb6, 0x45, 0xd3, 0xb2, 0x40, 0x58, 0x47, 0x51, 0x99, 0xa9, 0x1b, 0x55, 0x72, 0xd8, 0xac, 0x87, 0xf8, 0x3e, 0xe6, 0xaf, 0x5c, 0xf9, 0xe1, 0x71, 0xa8, 0x58, 0xf6, 0x0d, 0x2b, 0x81, 0x40, 0xf5, 0x2d, 0xae, 0xd6, 0x84, 0x42, 0x22, 0x8b, 0x4f, 0xff, 0xd8, 0xde, 0x40, 0x07, 0x8d, 0x3d, 0xe8, 0xcb } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.8", + /* Message to be signed */ + 1, + { 0x18 } +, + /* Signature */ + 129, + { 0x00, 0xf2, 0xc2, 0x99, 0x02, 0x4a, 0xb7, 0xbd, 0x25, 0x2c, 0x69, 0x46, 0xbe, 0xa1, 0x0d, 0xc0, 0x53, 0x97, 0x38, 0x98, 0xbd, 0x5f, 0x0e, 0x3c, 0x94, 0x60, 0xe6, 0xfe, 0x09, 0xd7, 0xd1, 0x91, 0xe7, 0x1b, 0xf7, 0x9d, 0x43, 0x6c, 0xaa, 0x84, 0xe9, 0x86, 0xbe, 0x3f, 0xc0, 0x98, 0x19, 0xc0, 0x80, 0xe5, 0x6a, 0x08, 0x5c, 0xf4, 0x24, 0x41, 0x4a, 0xf3, 0xfc, 0x70, 0x07, 0xcf, 0x1a, 0xc3, 0x6f, 0x1c, 0xf8, 0x63, 0x57, 0x80, 0xb5, 0x56, 0x8d, 0x73, 0x4a, 0xd6, 0xd8, 0x1a, 0x2b, 0xa8, 0xeb, 0x18, 0x8b, 0x29, 0x46, 0x69, 0xd8, 0x71, 0xca, 0x40, 0xe6, 0x08, 0xf0, 0xed, 0x33, 0xd5, 0x69, 0x0c, 0xc6, 0x15, 0x70, 0xc5, 0xb8, 0x47, 0xeb, 0xdb, 0xdc, 0xdc, 0x4f, 0xa7, 0x8f, 0x42, 0x9e, 0xfc, 0xe1, 0x3c, 0x67, 0x47, 0xe5, 0x4d, 0x6f, 0x26, 0x1b, 0x04, 0x55, 0xd6, 0xdd, 0x65, 0xc2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.9", + /* Message to be signed */ + 40, + { 0x04, 0xa6, 0xe2, 0x4b, 0x93, 0xc2, 0xe5, 0xf6, 0xb4, 0xbb, 0xe0, 0x5f, 0x5f, 0xb0, 0xaf, 0xa0, 0x42, 0xd2, 0x04, 0xfe, 0x33, 0x78, 0xd3, 0x65, 0xc2, 0xf2, 0x88, 0xb6, 0xa8, 0xda, 0xd7, 0xef, 0xe4, 0x5d, 0x15, 0x3e, 0xef, 0x40, 0xca, 0xcc } +, + /* Signature */ + 129, + { 0x00, 0xec, 0xc8, 0x95, 0xfb, 0xd9, 0x47, 0xe2, 0xdf, 0xc4, 0x7c, 0x03, 0xba, 0x2e, 0x99, 0x3d, 0x1a, 0x14, 0x3a, 0x7a, 0x6a, 0xd6, 0x3a, 0x91, 0x6e, 0xd5, 0x44, 0x83, 0xce, 0x26, 0x38, 0x9f, 0x89, 0xd5, 0x80, 0xf4, 0xed, 0xbd, 0xd0, 0xb3, 0x7e, 0x08, 0xca, 0xaa, 0x5a, 0x0c, 0x1e, 0x52, 0x6e, 0x1e, 0x9a, 0x1a, 0x8c, 0x0d, 0xc9, 0xcf, 0x50, 0xed, 0x77, 0xde, 0x26, 0x76, 0x46, 0x0d, 0x28, 0x8d, 0xce, 0x56, 0x5f, 0x12, 0x8a, 0x26, 0x6e, 0xa2, 0x9b, 0x4e, 0xcc, 0x32, 0x9a, 0x94, 0xcc, 0x25, 0x23, 0x96, 0xdc, 0x50, 0xd5, 0xc0, 0xa1, 0x3d, 0x80, 0x93, 0x81, 0xfa, 0xd8, 0x8a, 0x07, 0x89, 0xad, 0x4f, 0x56, 0xaa, 0x77, 0xe5, 0x44, 0xec, 0x25, 0x70, 0xaf, 0x99, 0x18, 0xb7, 0xf7, 0x41, 0xb4, 0x86, 0xca, 0x50, 0xb3, 0x38, 0x4a, 0xd1, 0x12, 0x40, 0x60, 0x59, 0x16, 0x85, 0xa1 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.10", + /* Message to be signed */ + 229, + { 0x99, 0x65, 0xbd, 0xa5, 0x5c, 0xbf, 0x0e, 0xfe, 0xd8, 0xd6, 0x55, 0x3b, 0x40, 0x27, 0xf2, 0xd8, 0x62, 0x08, 0xa6, 0xe6, 0xb4, 0x89, 0xc1, 0x76, 0x12, 0x80, 0x92, 0xd6, 0x29, 0xe4, 0x9d, 0x16, 0x9f, 0x16, 0xfe, 0x51, 0xc4, 0xc0, 0x8a, 0x64, 0x94, 0xb5, 0x00, 0x73, 0x62, 0x20, 0x91, 0xa3, 0x82, 0x2e, 0xa5, 0x7c, 0x32, 0x8b, 0xd9, 0xb6, 0x9d, 0x24, 0x65, 0xa2, 0x12, 0x2a, 0xf1, 0x78, 0xbf, 0x6b, 0x1b, 0xe3, 0x07, 0xee, 0x4c, 0x31, 0x47, 0x9f, 0xfd, 0x9f, 0x4d, 0x11, 0xf3, 0x3e, 0xa2, 0x0b, 0x7a, 0xec, 0xe8, 0x12, 0xca, 0xb4, 0xee, 0xdd, 0x46, 0x99, 0x31, 0x51, 0xd5, 0x68, 0xff, 0x64, 0xa1, 0x67, 0x04, 0xa5, 0x5d, 0x95, 0x0a, 0xb7, 0x79, 0x1a, 0xa2, 0x3b, 0x26, 0xa0, 0xa8, 0xaf, 0x88, 0x0f, 0x6f, 0x80, 0x56, 0xbd, 0xd2, 0x06, 0x83, 0x8b, 0x44, 0xc6, 0x07, 0xb6, 0x61, 0xb4, 0xf1, 0xdc, 0x36, 0x21, 0x06, 0x5f, 0xde, 0xd3, 0xdb, 0x6f, 0x9e, 0x3f, 0x2d, 0xc8, 0xf4, 0x00, 0xef, 0xe3, 0xc2, 0xaf, 0xa6, 0xc0, 0x27, 0x99, 0x40, 0x57, 0x6b, 0xb0, 0x5e, 0x39, 0x80, 0x4b, 0xd3, 0x50, 0x5f, 0x4b, 0xd2, 0x82, 0x52, 0x91, 0x8b, 0x28, 0xe7, 0x4e, 0x05, 0x8f, 0x24, 0xf2, 0x7e, 0xf0, 0xdb, 0x3d, 0x0d, 0xcf, 0x9e, 0xb2, 0x9d, 0x41, 0xff, 0xc1, 0x10, 0x07, 0xce, 0x86, 0xb9, 0x82, 0xe8, 0x9c, 0x03, 0x75, 0xbd, 0x99, 0x76, 0xa5, 0xaf, 0x13, 0x1a, 0x61, 0x4d, 0x28, 0x08, 0xba, 0x25, 0x07, 0x9d, 0x97, 0x7f, 0x0b, 0x23, 0x97, 0x96, 0xba, 0x6b, 0x1b, 0xcd, 0x5e, 0x85, 0x5d, 0x96 } +, + /* Signature */ + 129, + { 0x01, 0x56, 0x62, 0xe3, 0x0e, 0x79, 0x0e, 0x37, 0x86, 0x83, 0x81, 0xb4, 0xf6, 0x77, 0xa2, 0xae, 0xd6, 0xb2, 0xac, 0xc5, 0x64, 0x49, 0x17, 0x31, 0x82, 0x49, 0x10, 0xed, 0x80, 0xad, 0xc4, 0x77, 0x15, 0x9c, 0x88, 0x61, 0x8c, 0xc7, 0xd0, 0xbe, 0xb0, 0x49, 0xb1, 0xaa, 0xe7, 0x4b, 0x17, 0x21, 0xe9, 0x0b, 0xa7, 0xf7, 0xb0, 0xea, 0x26, 0xbf, 0x33, 0xad, 0x04, 0xf8, 0x6f, 0xf3, 0x14, 0x38, 0x97, 0xbf, 0x0d, 0x4e, 0xb4, 0x5e, 0xb7, 0xde, 0xb5, 0x44, 0x11, 0xba, 0x96, 0x80, 0xaa, 0xb1, 0x3a, 0xdb, 0xfc, 0xf1, 0x8a, 0xf4, 0x6b, 0x87, 0xfc, 0xb1, 0x46, 0x1c, 0x26, 0x20, 0x6a, 0x95, 0x3b, 0xc3, 0xcd, 0xbb, 0x31, 0xe2, 0x96, 0xea, 0x09, 0x02, 0x4b, 0xc5, 0xc7, 0xb6, 0x2d, 0xe6, 0xc6, 0x9c, 0x14, 0xbf, 0xcf, 0xeb, 0x56, 0x39, 0x1a, 0x9e, 0xf5, 0x8c, 0xd8, 0x05, 0xeb, 0x63, 0x1f } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.11", + /* Message to be signed */ + 186, + { 0x71, 0xc7, 0xb1, 0x8b, 0x4a, 0xa8, 0xea, 0x53, 0x89, 0xad, 0x78, 0x49, 0x23, 0x28, 0x65, 0xbe, 0x2a, 0x93, 0xe3, 0x47, 0xa1, 0x68, 0xd2, 0x5c, 0x6c, 0x6e, 0xa2, 0x43, 0x9c, 0x1c, 0xc8, 0x0b, 0xb0, 0xb7, 0x22, 0x3b, 0xe9, 0xc8, 0x93, 0x71, 0x22, 0x84, 0x5b, 0xb0, 0xa3, 0x9c, 0x02, 0x5c, 0x43, 0x75, 0x9d, 0xef, 0xe6, 0xe4, 0xe8, 0xeb, 0x3b, 0xaa, 0xb4, 0xf1, 0xeb, 0xdc, 0xa2, 0xc8, 0xad, 0x12, 0xa4, 0x65, 0xa3, 0x0f, 0x8a, 0x65, 0x25, 0xb1, 0x20, 0xef, 0x6a, 0xae, 0xc9, 0xbd, 0xdb, 0x45, 0xcd, 0x42, 0xc0, 0x15, 0x0c, 0x40, 0x7b, 0x04, 0x8e, 0xdf, 0x65, 0x19, 0x94, 0x92, 0xf2, 0x07, 0xca, 0x01, 0xaa, 0xa5, 0x54, 0x3a, 0xf3, 0x8e, 0xe9, 0x8d, 0x53, 0xbd, 0x10, 0xd8, 0xee, 0xbc, 0x3b, 0x64, 0x97, 0x7e, 0x75, 0x75, 0x1d, 0x74, 0x50, 0xdd, 0xb1, 0xc0, 0xe1, 0xfc, 0x24, 0xda, 0x17, 0x18, 0x81, 0x1f, 0xbe, 0x9b, 0x0a, 0xbf, 0xc3, 0xca, 0x31, 0xe6, 0x99, 0x5f, 0xc7, 0x34, 0x90, 0x73, 0xe2, 0x17, 0xb3, 0x7e, 0x23, 0xc5, 0xf1, 0x7a, 0x8b, 0x7a, 0x3f, 0x00, 0x48, 0x6a, 0x37, 0x02, 0xb9, 0x51, 0x0d, 0x6f, 0x05, 0x1b, 0x27, 0x61, 0x71, 0x6e, 0x32, 0xc6, 0x2b, 0xb5, 0x93, 0x9b, 0x2f, 0xb1, 0x1a, 0xcb, 0x1c, 0x83 } +, + /* Signature */ + 129, + { 0x01, 0x3a, 0xb6, 0x3a, 0xb1, 0x83, 0x35, 0x3a, 0x23, 0x5f, 0xb8, 0x93, 0xab, 0x4c, 0x35, 0xd6, 0x40, 0x9c, 0x21, 0x84, 0x9d, 0xcf, 0xcd, 0xa3, 0xbf, 0xda, 0x14, 0x29, 0xfe, 0xe7, 0x42, 0xa7, 0xd8, 0x16, 0x0f, 0xd3, 0xc8, 0x3b, 0x38, 0x53, 0xa3, 0x33, 0xf9, 0x51, 0x53, 0x9b, 0xb5, 0x77, 0x1f, 0x4d, 0x0f, 0xe1, 0x3a, 0xde, 0xb6, 0x4e, 0x40, 0x30, 0xb9, 0x2e, 0x8b, 0x08, 0x13, 0xeb, 0x52, 0xb1, 0xaa, 0x33, 0xbd, 0x94, 0xc5, 0xb8, 0xbc, 0x1b, 0xbc, 0xcd, 0xf6, 0xc1, 0xdf, 0x0b, 0xa6, 0x70, 0x71, 0x7c, 0x0c, 0xf6, 0xfd, 0x48, 0x5b, 0xe2, 0xfe, 0x9e, 0x16, 0x81, 0x3b, 0xe8, 0xcd, 0xd5, 0x80, 0xe6, 0x10, 0x86, 0x67, 0x5e, 0x31, 0x83, 0x1c, 0x92, 0x4a, 0x41, 0xd4, 0x67, 0x1a, 0x95, 0xd8, 0x35, 0xe3, 0xfc, 0xa4, 0x95, 0xe8, 0x86, 0x58, 0xd1, 0xe5, 0x70, 0xe6, 0x28, 0xc7 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.12", + /* Message to be signed */ + 111, + { 0x0b, 0xeb, 0x19, 0xb5, 0x62, 0x92, 0x8c, 0x27, 0x1b, 0xb7, 0x06, 0x18, 0x9e, 0x43, 0xcf, 0xa5, 0x7b, 0xe7, 0x6b, 0x2f, 0x7a, 0x83, 0xe0, 0x2a, 0xa2, 0xcc, 0xb0, 0x37, 0xc0, 0xf4, 0xf7, 0xf7, 0x31, 0x62, 0xd6, 0xc2, 0x6f, 0x70, 0xde, 0x97, 0x18, 0x21, 0xe7, 0xb9, 0x66, 0x5c, 0xb9, 0x31, 0xbb, 0x0e, 0xac, 0x82, 0x0b, 0xf8, 0x59, 0x98, 0x4d, 0xb4, 0xbe, 0xef, 0xef, 0x4a, 0xb8, 0x8e, 0x91, 0x63, 0x1c, 0x0c, 0xd3, 0x1d, 0xb7, 0xf9, 0x35, 0x8a, 0x5a, 0xa1, 0xdf, 0xf2, 0x40, 0x6b, 0x45, 0xf9, 0xbd, 0xcb, 0xef, 0x20, 0xd5, 0x5c, 0x28, 0x2b, 0xae, 0x5c, 0xfb, 0x61, 0x06, 0x02, 0x3b, 0x56, 0x33, 0xc0, 0x51, 0xaf, 0x17, 0xe7, 0x29, 0xbb, 0x07, 0xc9, 0xaf, 0x6d, 0xd2 } +, + /* Signature */ + 129, + { 0x00, 0xd6, 0x3d, 0xa4, 0xd5, 0xd3, 0xe2, 0x28, 0x4a, 0x19, 0x2a, 0x6a, 0x9d, 0xa3, 0xf1, 0xa7, 0xd3, 0xfc, 0xc1, 0x64, 0xb9, 0xfc, 0x3d, 0xfd, 0x74, 0x52, 0xb0, 0x2f, 0xed, 0x6e, 0xf1, 0xbe, 0x5a, 0xd2, 0xa7, 0x69, 0xec, 0x9c, 0x36, 0x05, 0x9b, 0x71, 0x91, 0x1c, 0xcf, 0x7a, 0xb7, 0x1c, 0xe3, 0x09, 0x87, 0xec, 0x47, 0xbb, 0xf5, 0x5e, 0x6d, 0x46, 0x30, 0xd6, 0x23, 0x42, 0xb3, 0x15, 0x50, 0x48, 0xee, 0x0b, 0xf4, 0x3d, 0x24, 0xfe, 0x69, 0xab, 0xda, 0xc1, 0x2f, 0x79, 0x4b, 0x67, 0x98, 0xbd, 0x1a, 0x7c, 0xb4, 0x89, 0xa6, 0x4c, 0xe0, 0x82, 0x25, 0x4c, 0x3d, 0x92, 0xf4, 0x75, 0x56, 0x6b, 0x56, 0x40, 0x0d, 0x96, 0x20, 0xcd, 0xfd, 0x63, 0xfc, 0x17, 0xc1, 0x93, 0xc4, 0x25, 0xd7, 0xed, 0xe9, 0x41, 0xf7, 0x6d, 0xa1, 0xe3, 0x45, 0xaf, 0x0e, 0x2a, 0x8b, 0x88, 0x44, 0xc7, 0x40 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.13", + /* Message to be signed */ + 12, + { 0x02, 0x87, 0xab, 0xe2, 0x67, 0x0a, 0x45, 0xf8, 0x77, 0x90, 0x48, 0xf5 } +, + /* Signature */ + 129, + { 0x00, 0x42, 0xf4, 0x14, 0x78, 0x2d, 0xf6, 0x5d, 0x93, 0x47, 0xbf, 0x1c, 0xad, 0x53, 0x48, 0x53, 0x74, 0x6c, 0xc0, 0xb8, 0x53, 0xc1, 0xc5, 0x26, 0xf9, 0x17, 0x14, 0x45, 0xfc, 0xfa, 0xa4, 0x99, 0x1a, 0x70, 0xf5, 0xa8, 0x44, 0x5b, 0xcf, 0x41, 0x14, 0xf0, 0x7f, 0xc8, 0x35, 0x4c, 0x84, 0xa9, 0x3b, 0x94, 0x37, 0x33, 0xd3, 0x93, 0x7a, 0x59, 0x88, 0x3b, 0x89, 0x6c, 0xe6, 0x5f, 0xdb, 0x16, 0x5b, 0x1e, 0x30, 0x55, 0x37, 0x4c, 0xe2, 0x42, 0xe1, 0x26, 0x8c, 0x16, 0x41, 0xcc, 0x44, 0x3b, 0xb9, 0xe7, 0xda, 0x7f, 0x71, 0xf3, 0xe7, 0xf6, 0x31, 0x3f, 0x23, 0x9e, 0x62, 0x00, 0xe7, 0x9a, 0x1b, 0xe3, 0xea, 0xd6, 0xc3, 0x6e, 0x94, 0x1f, 0x24, 0x46, 0x0b, 0xaa, 0x57, 0xdf, 0x63, 0x9e, 0x57, 0xda, 0xb3, 0xef, 0xf9, 0xe7, 0x7b, 0x87, 0xaf, 0x35, 0x5b, 0x83, 0xda, 0xe7, 0x7c, 0xbe, 0x06 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.14", + /* Message to be signed */ + 91, + { 0x3f, 0x49, 0x54, 0x2c, 0x0e, 0x9f, 0x50, 0x93, 0x2c, 0x0d, 0x45, 0x3d, 0xc9, 0x53, 0x20, 0xaf, 0x21, 0xdd, 0x2b, 0xd1, 0x72, 0x9c, 0x29, 0xf4, 0xf0, 0x8c, 0x70, 0x94, 0x4c, 0x2c, 0xc7, 0x5d, 0xe9, 0x16, 0x6b, 0x4f, 0xd2, 0x30, 0xaa, 0x93, 0x70, 0x2c, 0x5f, 0x2c, 0x3d, 0x9c, 0x29, 0x9a, 0x35, 0x91, 0x02, 0x57, 0x00, 0x33, 0x54, 0x0e, 0xb8, 0x28, 0xca, 0xd7, 0x5a, 0x57, 0x76, 0xd2, 0xe8, 0xcb, 0x45, 0x61, 0x41, 0xa6, 0xfa, 0x97, 0xbc, 0x4e, 0x6e, 0x62, 0xd3, 0xdf, 0x08, 0x29, 0x82, 0xa4, 0xd9, 0x8c, 0x2d, 0xe4, 0x41, 0xe5, 0x9e, 0x93, 0x12 } +, + /* Signature */ + 129, + { 0x01, 0x5c, 0x39, 0x93, 0xce, 0xeb, 0xd8, 0xdb, 0xa4, 0x5a, 0x36, 0x8d, 0xd4, 0x05, 0xaf, 0x8a, 0x53, 0xb9, 0x3e, 0x82, 0x70, 0x19, 0xf9, 0x94, 0xe4, 0xed, 0x78, 0x2c, 0x39, 0x11, 0xb9, 0xb5, 0x80, 0xd5, 0x42, 0x24, 0x26, 0x9b, 0x79, 0x97, 0xf1, 0x74, 0x96, 0x30, 0xe5, 0x2f, 0x22, 0x1f, 0xaf, 0xab, 0x96, 0x41, 0xc7, 0x81, 0xe7, 0x04, 0x4d, 0x32, 0x56, 0xe2, 0xe4, 0x4e, 0x14, 0x37, 0x91, 0x72, 0x32, 0x69, 0x45, 0x18, 0xba, 0x9e, 0x71, 0x38, 0xda, 0x47, 0xfe, 0x53, 0x43, 0x29, 0xb8, 0xc9, 0x68, 0x9e, 0x27, 0x85, 0xc0, 0x2b, 0x60, 0x3d, 0xd1, 0x60, 0xd3, 0x73, 0x36, 0xa2, 0xb0, 0x5b, 0xe0, 0x47, 0x82, 0x65, 0x9a, 0xc0, 0xe9, 0x67, 0x1f, 0xe9, 0x32, 0xea, 0x80, 0x91, 0xd6, 0x13, 0x18, 0xb2, 0xb2, 0x01, 0xbd, 0xa7, 0x9a, 0xf6, 0xc0, 0xc4, 0x44, 0x69, 0x38, 0xe3, 0xf6 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.15", + /* Message to be signed */ + 221, + { 0xd0, 0xdb, 0xc9, 0x6c, 0xf9, 0xbf, 0xb1, 0xe3, 0xcd, 0x6d, 0xe2, 0xea, 0xa0, 0x8d, 0x6d, 0x79, 0x5b, 0xed, 0x81, 0x87, 0xce, 0xb0, 0x85, 0x65, 0x80, 0xe4, 0xb1, 0x42, 0xb9, 0xae, 0x60, 0xa0, 0x98, 0xcd, 0x42, 0x98, 0x4e, 0x8d, 0xbf, 0x1d, 0x05, 0xa0, 0xc0, 0xab, 0x83, 0x51, 0x54, 0x8f, 0x0a, 0x13, 0x64, 0x6f, 0x33, 0x39, 0x0b, 0x2b, 0xb0, 0xc8, 0x64, 0xb3, 0x97, 0xcf, 0x13, 0x37, 0x1f, 0x8b, 0x2f, 0x67, 0x5a, 0x82, 0xe4, 0x6b, 0xf1, 0x6c, 0x4a, 0xfc, 0x60, 0x5e, 0xe3, 0xe5, 0xa1, 0x46, 0x9c, 0xac, 0x51, 0xfa, 0x73, 0x4b, 0x44, 0x65, 0xd4, 0xc1, 0x3d, 0x5b, 0x2d, 0xd1, 0x2e, 0xed, 0xa5, 0x4e, 0x7d, 0x08, 0x1c, 0xd9, 0xe3, 0xea, 0xaf, 0x9e, 0x57, 0xdb, 0x42, 0x20, 0x20, 0xa0, 0xb5, 0xa5, 0xec, 0x28, 0xca, 0x43, 0x97, 0x7a, 0x5d, 0x67, 0x6f, 0xfa, 0xb6, 0x2f, 0x78, 0x10, 0x71, 0x93, 0x59, 0x41, 0x59, 0xce, 0xbf, 0xbd, 0x86, 0x26, 0x98, 0x19, 0xa0, 0xf3, 0x41, 0xa0, 0xf4, 0x12, 0x84, 0xdd, 0x0a, 0x73, 0xca, 0x80, 0x14, 0xd2, 0xe0, 0xb8, 0x01, 0x79, 0xc6, 0x38, 0x0b, 0x40, 0x3a, 0xfb, 0xb1, 0x1b, 0x42, 0xdb, 0x34, 0x9b, 0xaf, 0xd7, 0x57, 0x0f, 0xbe, 0xcb, 0xd1, 0x4b, 0xd0, 0xc2, 0x1a, 0xd6, 0x41, 0x68, 0x7a, 0x6a, 0xc3, 0x29, 0x25, 0xf7, 0x03, 0x1a, 0x24, 0xa6, 0x56, 0x8a, 0xb9, 0xe2, 0x87, 0xeb, 0x80, 0x75, 0x41, 0x10, 0xdf, 0xba, 0x68, 0x8a, 0x59, 0x63, 0x25, 0xbc, 0xac, 0x4a, 0x39, 0xce, 0x8b, 0x84, 0xa4 } +, + /* Signature */ + 129, + { 0x00, 0x8c, 0xc8, 0x2d, 0x64, 0x55, 0x9d, 0xe0, 0x04, 0x0f, 0x55, 0x41, 0x19, 0x9a, 0xef, 0xf3, 0x99, 0x9f, 0xe2, 0xf0, 0x86, 0xf1, 0x57, 0xff, 0x51, 0xf2, 0x22, 0x0d, 0xb3, 0x45, 0x51, 0x9a, 0xa1, 0x14, 0xb0, 0x17, 0x62, 0xe7, 0x0b, 0xc9, 0x65, 0x83, 0xbb, 0x38, 0xb2, 0x2b, 0x3f, 0x87, 0xbe, 0xab, 0x32, 0xe2, 0x3a, 0x3d, 0xeb, 0xdb, 0x8a, 0x59, 0x54, 0x29, 0xff, 0x12, 0xfa, 0xd4, 0x95, 0xd7, 0x4e, 0x22, 0x0e, 0x4f, 0x7d, 0xca, 0x22, 0x27, 0x28, 0x43, 0x89, 0x9e, 0x81, 0x04, 0xc6, 0x9a, 0x59, 0x64, 0x2f, 0x6f, 0xa8, 0x25, 0x89, 0x0f, 0xe8, 0x13, 0x2a, 0x0f, 0x79, 0x94, 0x02, 0x53, 0xe5, 0x00, 0x7f, 0xb1, 0x17, 0x7a, 0x5b, 0xf4, 0x18, 0x06, 0x7e, 0xdd, 0xc8, 0xd3, 0x2c, 0x5e, 0x59, 0x35, 0xbf, 0x33, 0x8f, 0x1c, 0x69, 0x0e, 0xfc, 0x80, 0x11, 0xdc, 0x8c, 0x84, 0x2e } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.16", + /* Message to be signed */ + 230, + { 0x7d, 0xf0, 0x23, 0x6e, 0x87, 0x1a, 0x71, 0xc3, 0x17, 0x90, 0xeb, 0x5f, 0x01, 0x1c, 0x91, 0x1c, 0x27, 0xc6, 0x03, 0x73, 0xb8, 0xdc, 0x9e, 0xbb, 0x13, 0xac, 0x85, 0xac, 0xcb, 0x3b, 0xcb, 0xd3, 0xb4, 0x74, 0xf9, 0x78, 0x86, 0x2d, 0xd8, 0x42, 0x02, 0xab, 0x20, 0xb3, 0x34, 0x73, 0x94, 0x25, 0xe1, 0xb7, 0x9e, 0x0b, 0xb8, 0xb4, 0xbc, 0x47, 0xdc, 0x71, 0x53, 0xf5, 0x7a, 0xda, 0x04, 0x12, 0x44, 0x7b, 0xf5, 0xa5, 0xe6, 0x67, 0x34, 0x19, 0xba, 0xad, 0x65, 0x3e, 0x5f, 0x5c, 0x39, 0xe2, 0xef, 0x7c, 0xfe, 0x7e, 0xf4, 0x77, 0x8a, 0xb9, 0x98, 0xca, 0xf9, 0x7c, 0xe1, 0x6c, 0x58, 0x33, 0x27, 0x72, 0xdd, 0xdf, 0x82, 0x6f, 0x1e, 0xec, 0x1a, 0xf3, 0xdb, 0x80, 0xe3, 0x13, 0x75, 0xd6, 0x68, 0x0a, 0xa2, 0x54, 0xb4, 0xab, 0x6e, 0xf9, 0xa3, 0xec, 0x0e, 0x04, 0x03, 0xe4, 0xb5, 0x83, 0xd3, 0x71, 0xdd, 0xd9, 0x6d, 0xd5, 0x7b, 0x2c, 0x61, 0xa6, 0xe4, 0x01, 0x25, 0x1a, 0x1a, 0x63, 0x0d, 0x1d, 0xdc, 0xdd, 0x84, 0xd9, 0x0d, 0x82, 0xfa, 0xf5, 0xa0, 0x18, 0xd2, 0xa8, 0x8e, 0x26, 0x58, 0x55, 0xe9, 0xd7, 0xca, 0x36, 0xc6, 0x87, 0x95, 0xf0, 0xb3, 0x1b, 0x59, 0x1c, 0xd6, 0x58, 0x7c, 0x71, 0xd0, 0x60, 0xa0, 0xb3, 0xf7, 0xf3, 0xea, 0xef, 0x43, 0x79, 0x59, 0x22, 0x02, 0x8b, 0xc2, 0xb6, 0xad, 0x46, 0x7c, 0xfc, 0x2d, 0x7f, 0x65, 0x9c, 0x53, 0x85, 0xaa, 0x70, 0xba, 0x36, 0x72, 0xcd, 0xde, 0x4c, 0xfe, 0x49, 0x70, 0xcc, 0x79, 0x04, 0x60, 0x1b, 0x27, 0x88, 0x72, 0xbf, 0x51, 0x32, 0x1c, 0x4a, 0x97, 0x2f } +, + /* Signature */ + 129, + { 0x01, 0x45, 0x5e, 0x3b, 0xb2, 0x9c, 0xbc, 0xa8, 0x83, 0x9b, 0x9f, 0x54, 0x4d, 0x51, 0x47, 0x2e, 0xbc, 0xfd, 0x25, 0xc2, 0x92, 0x27, 0xc4, 0x65, 0x5d, 0x5f, 0x7e, 0xbb, 0xd8, 0x3c, 0x48, 0xe7, 0x64, 0x3e, 0x7b, 0x59, 0x4d, 0x6f, 0x7c, 0xd5, 0xf6, 0xbf, 0x9a, 0x40, 0xb0, 0x5c, 0x4a, 0x05, 0xcb, 0xee, 0x1f, 0xd6, 0x59, 0xd3, 0xce, 0xde, 0x3e, 0x7c, 0xad, 0x61, 0xe6, 0xfd, 0xf8, 0xf0, 0xe4, 0xfd, 0xef, 0x08, 0x12, 0xa8, 0x53, 0x90, 0x8f, 0x0f, 0x99, 0xca, 0x7e, 0x38, 0x8e, 0xbc, 0x19, 0xe8, 0x74, 0x76, 0x5b, 0x11, 0x64, 0x0f, 0x1e, 0xe1, 0xe9, 0x8f, 0x54, 0x95, 0x3d, 0xe6, 0x17, 0x6f, 0x15, 0x82, 0x03, 0x70, 0x17, 0xc8, 0x38, 0x60, 0x9a, 0x57, 0xa1, 0x2a, 0xcb, 0xaf, 0xa6, 0xa5, 0x65, 0x47, 0xf5, 0x7d, 0x62, 0xdb, 0xe8, 0x76, 0x69, 0xed, 0xc0, 0xfe, 0x3b, 0xaa, 0xda } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.17", + /* Message to be signed */ + 144, + { 0x12, 0x88, 0xc0, 0x3f, 0x95, 0x00, 0x6e, 0xa3, 0x2f, 0x56, 0x2d, 0x40, 0xd5, 0x2a, 0xf9, 0xfe, 0xb3, 0x2f, 0x0f, 0xa0, 0x6d, 0xb6, 0x5b, 0x58, 0x8a, 0x23, 0x7b, 0x34, 0xe5, 0x92, 0xd5, 0x5c, 0xf9, 0x79, 0xf9, 0x03, 0xa6, 0x42, 0xef, 0x64, 0xd2, 0xed, 0x54, 0x2a, 0xa8, 0xc7, 0x7d, 0xc1, 0xdd, 0x76, 0x2f, 0x45, 0xa5, 0x93, 0x03, 0xed, 0x75, 0xe5, 0x41, 0xca, 0x27, 0x1e, 0x2b, 0x60, 0xca, 0x70, 0x9e, 0x44, 0xfa, 0x06, 0x61, 0x13, 0x1e, 0x8d, 0x5d, 0x41, 0x63, 0xfd, 0x8d, 0x39, 0x85, 0x66, 0xce, 0x26, 0xde, 0x87, 0x30, 0xe7, 0x2f, 0x9c, 0xca, 0x73, 0x76, 0x41, 0xc2, 0x44, 0x15, 0x94, 0x20, 0x63, 0x70, 0x28, 0xdf, 0x0a, 0x18, 0x07, 0x9d, 0x62, 0x08, 0xea, 0x8b, 0x47, 0x11, 0xa2, 0xc7, 0x50, 0xf5, 0xc0, 0xa4, 0x25, 0x31, 0x3d, 0xf8, 0xd7, 0x56, 0x4b, 0xd2, 0x43, 0x4d, 0x31, 0x15, 0x23, 0xd5, 0x25, 0x7e, 0xed, 0x80, 0x6a, 0xc8, 0xc9, 0xc6, 0xaf, 0x04, 0xac } +, + /* Signature */ + 129, + { 0x00, 0x6b, 0xeb, 0xb9, 0x6f, 0x0e, 0x28, 0x2f, 0x1b, 0x4d, 0x03, 0xe6, 0xc5, 0x65, 0x05, 0xb9, 0x37, 0x78, 0xda, 0x9f, 0x49, 0x36, 0x50, 0xe8, 0xaa, 0xeb, 0x65, 0xcf, 0xe6, 0x28, 0x50, 0x04, 0x2f, 0x75, 0xab, 0xe6, 0xe6, 0xea, 0xfe, 0xb9, 0xa7, 0x0a, 0xbd, 0x21, 0xeb, 0x5d, 0xba, 0x73, 0xcb, 0xb8, 0x7c, 0x12, 0x98, 0x0a, 0xac, 0xdf, 0x16, 0x71, 0x6b, 0x19, 0x98, 0xc9, 0x49, 0x9c, 0xe4, 0x39, 0xc5, 0x4a, 0xab, 0x4d, 0x19, 0xce, 0x72, 0x7b, 0x78, 0x75, 0xa4, 0x1a, 0x3d, 0x30, 0x81, 0x4e, 0x50, 0x8d, 0xaa, 0x26, 0xeb, 0x70, 0xaa, 0xbb, 0xd0, 0xdc, 0xae, 0xcc, 0x4d, 0x4b, 0x51, 0x69, 0x80, 0x71, 0x51, 0x1e, 0xb3, 0x1b, 0x21, 0x0e, 0x66, 0xdc, 0xbc, 0x7f, 0xc0, 0xb8, 0xc6, 0x23, 0x14, 0xda, 0xea, 0x69, 0xd4, 0x7a, 0xe2, 0x78, 0x10, 0x0d, 0xeb, 0x51, 0x40, 0x92, 0x00 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.18", + /* Message to be signed */ + 10, + { 0x54, 0x13, 0x99, 0x3c, 0x26, 0x58, 0xbc, 0x1d, 0x98, 0x85 } +, + /* Signature */ + 129, + { 0x00, 0xbb, 0xeb, 0x2c, 0xa0, 0xbd, 0x64, 0xcb, 0x89, 0x60, 0x37, 0x5b, 0x08, 0xa9, 0x48, 0x0e, 0x69, 0xc0, 0x9f, 0xd3, 0x82, 0xde, 0xa2, 0xf9, 0x40, 0x89, 0xb1, 0x53, 0x3a, 0x08, 0x51, 0xfa, 0x0c, 0xbd, 0x0e, 0xad, 0xef, 0xca, 0x8c, 0x70, 0xb7, 0x70, 0x79, 0x7a, 0xd0, 0x89, 0xe8, 0x40, 0xd2, 0xfe, 0x1a, 0x8f, 0xb8, 0x54, 0x9f, 0x32, 0x90, 0x58, 0x3b, 0xbb, 0x81, 0xd3, 0xee, 0x2b, 0x1c, 0x48, 0xf1, 0xea, 0x75, 0x1b, 0xf3, 0x2f, 0x95, 0x90, 0xbe, 0x3a, 0xfd, 0xb7, 0x74, 0x5e, 0x16, 0x6e, 0x0b, 0x32, 0x2c, 0x08, 0x31, 0x24, 0xe6, 0x45, 0x83, 0x94, 0x82, 0xd0, 0x81, 0x26, 0x22, 0xd3, 0x1a, 0xb1, 0x87, 0x7a, 0x9b, 0xb4, 0x1b, 0x8d, 0xaa, 0xd8, 0x68, 0xf3, 0x0e, 0x75, 0x07, 0x83, 0x2a, 0xc3, 0x41, 0x01, 0x12, 0x13, 0x3a, 0xa1, 0x7b, 0x2d, 0x47, 0x6d, 0x47, 0x6d, 0x89 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.19", + /* Message to be signed */ + 232, + { 0x9c, 0x84, 0xc1, 0x48, 0x6b, 0xc1, 0x2b, 0x3f, 0xa6, 0xc5, 0x98, 0x71, 0xb6, 0x82, 0x7c, 0x8c, 0xe2, 0x53, 0xca, 0x5f, 0xef, 0xa8, 0xa8, 0xc6, 0x90, 0xbf, 0x32, 0x6e, 0x8e, 0x37, 0xcd, 0xb9, 0x6d, 0x90, 0xa8, 0x2e, 0xba, 0xb6, 0x9f, 0x86, 0x35, 0x0e, 0x18, 0x22, 0xe8, 0xbd, 0x53, 0x6a, 0x2e, 0xb3, 0x07, 0xc4, 0x3b, 0x48, 0x50, 0xa8, 0xda, 0xc2, 0xf1, 0x5f, 0x32, 0xe3, 0x78, 0x39, 0xef, 0x8c, 0x5c, 0x0e, 0x91, 0xdd, 0x0a, 0xfa, 0xd4, 0x2c, 0xcd, 0x4f, 0xc6, 0x06, 0x54, 0xa5, 0x50, 0x02, 0xd2, 0x28, 0xf5, 0x2a, 0x4a, 0x5f, 0xe0, 0x3b, 0x8b, 0xbb, 0x08, 0xca, 0x82, 0xda, 0xca, 0x55, 0x8b, 0x44, 0xdb, 0xe1, 0x26, 0x6e, 0x50, 0xc0, 0xe7, 0x45, 0xa3, 0x6d, 0x9d, 0x29, 0x04, 0xe3, 0x40, 0x8a, 0xbc, 0xd1, 0xfd, 0x56, 0x99, 0x94, 0x06, 0x3f, 0x4a, 0x75, 0xcc, 0x72, 0xf2, 0xfe, 0xe2, 0xa0, 0xcd, 0x89, 0x3a, 0x43, 0xaf, 0x1c, 0x5b, 0x8b, 0x48, 0x7d, 0xf0, 0xa7, 0x16, 0x10, 0x02, 0x4e, 0x4f, 0x6d, 0xdf, 0x9f, 0x28, 0xad, 0x08, 0x13, 0xc1, 0xaa, 0xb9, 0x1b, 0xcb, 0x3c, 0x90, 0x64, 0xd5, 0xff, 0x74, 0x2d, 0xef, 0xfe, 0xa6, 0x57, 0x09, 0x41, 0x39, 0x36, 0x9e, 0x5e, 0xa6, 0xf4, 0xa9, 0x63, 0x19, 0xa5, 0xcc, 0x82, 0x24, 0x14, 0x5b, 0x54, 0x50, 0x62, 0x75, 0x8f, 0xef, 0xd1, 0xfe, 0x34, 0x09, 0xae, 0x16, 0x92, 0x59, 0xc6, 0xcd, 0xfd, 0x6b, 0x5f, 0x29, 0x58, 0xe3, 0x14, 0xfa, 0xec, 0xbe, 0x69, 0xd2, 0xca, 0xce, 0x58, 0xee, 0x55, 0x17, 0x9a, 0xb9, 0xb3, 0xe6, 0xd1, 0xec, 0xc1, 0x4a, 0x55 } +, + /* Signature */ + 129, + { 0x00, 0xe6, 0xbe, 0x96, 0xe1, 0x8d, 0xce, 0xbf, 0x83, 0x88, 0xba, 0x82, 0xec, 0x6f, 0x27, 0x10, 0x5b, 0xc2, 0x78, 0x71, 0x59, 0x5e, 0x01, 0x70, 0x5a, 0x2b, 0x97, 0xa1, 0xf4, 0xd7, 0x88, 0x38, 0x35, 0x2b, 0x0e, 0x7c, 0x0a, 0x2c, 0x62, 0x7a, 0x6f, 0xf3, 0x7d, 0xb1, 0x69, 0xa9, 0xa4, 0x64, 0x8a, 0xd2, 0x7a, 0xf0, 0x65, 0x33, 0xa4, 0xf0, 0x41, 0xd4, 0xc8, 0x20, 0xab, 0xf4, 0xfb, 0x52, 0x64, 0x64, 0x08, 0x14, 0x34, 0xdf, 0x36, 0x78, 0x85, 0x03, 0xc6, 0x5a, 0xf7, 0x62, 0xaa, 0x21, 0x9f, 0xb7, 0x6a, 0x91, 0xcb, 0xb4, 0x0e, 0x14, 0x92, 0xa9, 0xcb, 0x77, 0x36, 0x9b, 0xb4, 0xcc, 0xa1, 0x93, 0x4e, 0x38, 0x53, 0xde, 0x6c, 0x86, 0xa5, 0xdc, 0x11, 0x48, 0xed, 0xee, 0xb3, 0xb0, 0x03, 0x04, 0x14, 0xfe, 0x30, 0x83, 0xad, 0x72, 0xfe, 0x29, 0x5c, 0x29, 0xb5, 0xea, 0x9b, 0x66, 0x60 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 7.20", + /* Message to be signed */ + 165, + { 0x94, 0x0c, 0xda, 0xb4, 0xa3, 0xe9, 0x20, 0x09, 0xcc, 0xd4, 0x2e, 0x1e, 0x94, 0x7b, 0x13, 0x14, 0xe3, 0x22, 0x38, 0xa2, 0xde, 0xce, 0x7d, 0x23, 0xa8, 0x9b, 0x5b, 0x30, 0xc7, 0x51, 0xfd, 0x0a, 0x4a, 0x43, 0x0d, 0x2c, 0x54, 0x85, 0x94, 0x9a, 0x2b, 0x00, 0x7e, 0x80, 0x97, 0x8b, 0xbb, 0x19, 0x2c, 0x35, 0x4e, 0xb7, 0xda, 0x9a, 0xed, 0xfc, 0x74, 0xdb, 0xf5, 0xf7, 0x1d, 0xfd, 0x43, 0xb4, 0x6c, 0x93, 0xdb, 0x82, 0x62, 0x9b, 0xda, 0xe2, 0xbd, 0x0a, 0x12, 0xb8, 0x82, 0xea, 0x04, 0xc3, 0xb4, 0x65, 0xf5, 0xcf, 0x93, 0x02, 0x3f, 0x01, 0x05, 0x96, 0x26, 0xdb, 0xbe, 0x99, 0xf2, 0x6b, 0xb1, 0xbe, 0x94, 0x9d, 0xdd, 0xd1, 0x6d, 0xc7, 0xf3, 0xde, 0xbb, 0x19, 0xa1, 0x94, 0x62, 0x7f, 0x0b, 0x22, 0x44, 0x34, 0xdf, 0x7d, 0x87, 0x00, 0xe9, 0xe9, 0x8b, 0x06, 0xe3, 0x60, 0xc1, 0x2f, 0xdb, 0xe3, 0xd1, 0x9f, 0x51, 0xc9, 0x68, 0x4e, 0xb9, 0x08, 0x9e, 0xcb, 0xb0, 0xa2, 0xf0, 0x45, 0x03, 0x99, 0xd3, 0xf5, 0x9e, 0xac, 0x72, 0x94, 0x08, 0x5d, 0x04, 0x4f, 0x53, 0x93, 0xc6, 0xce, 0x73, 0x74, 0x23, 0xd8, 0xb8 } +, + /* Signature */ + 129, + { 0x00, 0x80, 0xe2, 0xc3, 0x4f, 0xd4, 0xab, 0x4d, 0x1d, 0x70, 0x1e, 0xa3, 0xf0, 0x85, 0x76, 0x3a, 0xca, 0xff, 0xc9, 0xfd, 0x3e, 0xd9, 0x18, 0xd0, 0x4b, 0xff, 0xee, 0x19, 0x31, 0x62, 0x48, 0x98, 0xc7, 0x8f, 0x89, 0x41, 0xbd, 0x2a, 0x59, 0xce, 0xb5, 0xb8, 0x40, 0xf0, 0x11, 0x45, 0x16, 0xce, 0x41, 0x1f, 0xae, 0x75, 0x2b, 0x1b, 0x8a, 0x22, 0x1f, 0xfc, 0xa7, 0xa6, 0x87, 0x66, 0xc6, 0x97, 0xc5, 0x0a, 0x3d, 0x88, 0xd8, 0xd0, 0x2f, 0xfc, 0x12, 0x41, 0xd8, 0x4b, 0xb7, 0xa7, 0x22, 0x7f, 0x3d, 0x05, 0x14, 0x9e, 0x15, 0x11, 0x12, 0x77, 0xa1, 0x36, 0xa5, 0xb8, 0xdd, 0x96, 0xdd, 0x4b, 0x22, 0x5c, 0x5f, 0x49, 0xcd, 0xf6, 0x07, 0x1d, 0xbf, 0x71, 0x93, 0x5c, 0x7a, 0x6f, 0x1e, 0x2e, 0x9a, 0xf3, 0x02, 0x1c, 0x0d, 0x58, 0xa9, 0xb8, 0x1c, 0x9b, 0xde, 0x61, 0xfa, 0x47, 0x2c, 0x07, 0xa6 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 8: A 1026-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x03, 0x33, 0x12, 0x64, 0x88, 0xf7, 0xa2, 0x91, 0x51, 0x32, 0xe3, 0x0d, 0x5e, 0x97, 0xf6, 0xed, 0x7b, 0xbb, 0x67, 0xb6, 0x19, 0x85, 0x00, 0x8e, 0xae, 0xa2, 0xa5, 0xda, 0xfb, 0x96, 0xa4, 0x48, 0xab, 0x75, 0xce, 0x3d, 0x6e, 0x68, 0xa6, 0x26, 0x5e, 0x7c, 0x24, 0x56, 0x84, 0x99, 0x93, 0x24, 0xc8, 0x1e, 0x0b, 0xa6, 0x38, 0x98, 0x63, 0xfe, 0xb4, 0x88, 0xb3, 0xf2, 0x55, 0xd0, 0xd6, 0x19, 0xc1, 0x90, 0x40, 0xb7, 0x4c, 0x18, 0x9f, 0x0c, 0x9a, 0xf4, 0xb0, 0xd5, 0xa5, 0x5a, 0x54, 0x4c, 0x09, 0x0c, 0xd6, 0x15, 0x2c, 0x90, 0xa6, 0xf2, 0x55, 0x0d, 0x7d, 0x2a, 0x6b, 0x6d, 0x34, 0x7d, 0x5b, 0x1b, 0x9d, 0xfb, 0x1d, 0xe4, 0x40, 0x3c, 0x79, 0x66, 0x23, 0xd7, 0x03, 0xbf, 0x9d, 0xb4, 0x43, 0xbf, 0x67, 0x02, 0x68, 0x3b, 0x8d, 0x2a, 0x9c, 0x61, 0xe9, 0x36, 0x8a, 0xc4, 0x25, 0xa5, 0x81 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x01, 0x4a, 0x2b, 0x15, 0xdf, 0xa8, 0x83, 0x1d, 0xb4, 0xef, 0xa0, 0x5b, 0x19, 0x50, 0x84, 0xb7, 0x42, 0x73, 0x4e, 0xe1, 0x36, 0xf4, 0x48, 0x3f, 0x3b, 0xe2, 0x50, 0x9d, 0x2f, 0x61, 0x90, 0x23, 0xc3, 0x0a, 0x1f, 0xf2, 0xdf, 0x78, 0xcb, 0xd1, 0x17, 0xb1, 0x4f, 0x2c, 0x99, 0x13, 0x17, 0x1f, 0x72, 0x93, 0xb9, 0xfa, 0x6d, 0x41, 0xf0, 0xbd, 0x11, 0xa5, 0x31, 0x74, 0x74, 0x67, 0x54, 0x86, 0xd7, 0xf0, 0xae, 0xc0, 0xa7, 0x78, 0xba, 0x92, 0x0e, 0x81, 0xf5, 0x64, 0xd1, 0x59, 0x30, 0xcd, 0xde, 0xe7, 0xe2, 0xb0, 0x6a, 0xd8, 0xad, 0xb6, 0x12, 0x75, 0x1f, 0x4e, 0x38, 0x4d, 0x6f, 0x3f, 0xa0, 0xa6, 0x63, 0x9f, 0xd6, 0x2e, 0xdf, 0x86, 0xf5, 0x2c, 0x9f, 0xe0, 0x77, 0x62, 0x91, 0x83, 0x21, 0x83, 0xd3, 0x59, 0xb7, 0x34, 0x32, 0x60, 0xc9, 0x4e, 0x12, 0x5f, 0x4a, 0xb8, 0xbf, 0x43, 0x69 } +, + /* Prime 1 */ + 65, + { 0x01, 0xd6, 0xe7, 0xbd, 0x8e, 0x39, 0x5b, 0xbe, 0xf2, 0x10, 0x46, 0x49, 0xc0, 0x12, 0x78, 0xcc, 0x1c, 0x51, 0xc9, 0x68, 0x7d, 0xef, 0xb4, 0x59, 0x1f, 0x03, 0xb6, 0x78, 0x52, 0xa4, 0xbc, 0xb5, 0x30, 0x75, 0x0c, 0xf9, 0xbf, 0xca, 0xd0, 0x72, 0x8c, 0x53, 0x99, 0xd8, 0x70, 0x35, 0x01, 0x06, 0xcb, 0xa3, 0xec, 0x41, 0x6a, 0x31, 0xe4, 0x2d, 0x0b, 0x59, 0x75, 0x10, 0xff, 0x1c, 0x9d, 0x53, 0xbb } +, + /* Prime 2 */ + 65, + { 0x01, 0xbd, 0x46, 0x6f, 0x43, 0xa4, 0xd4, 0x61, 0x3e, 0x42, 0x64, 0xf0, 0x1b, 0x2d, 0xac, 0x2e, 0x5a, 0xa4, 0x20, 0x43, 0xf8, 0xfb, 0x5f, 0x69, 0xfa, 0x87, 0x1d, 0x14, 0xfb, 0x27, 0x3e, 0x76, 0x7a, 0x53, 0x1c, 0x40, 0xf0, 0x2f, 0x34, 0x3b, 0xc2, 0xfb, 0x45, 0xa0, 0xc7, 0xe0, 0xf6, 0xbe, 0x25, 0x61, 0x92, 0x3a, 0x77, 0x21, 0x1d, 0x66, 0xa6, 0xe2, 0xdb, 0xb4, 0x3c, 0x36, 0x63, 0x51, 0xf3 } +, + /* Prime exponent 1 */ + 64, + { 0xfb, 0x66, 0x85, 0x00, 0x65, 0x06, 0xe2, 0x0e, 0x01, 0x3a, 0x45, 0x2d, 0x51, 0xaf, 0x43, 0xe8, 0xea, 0x91, 0x08, 0x44, 0x13, 0xb0, 0xc8, 0xd3, 0x91, 0xfb, 0xdc, 0x88, 0xe2, 0x82, 0x0c, 0x89, 0x6e, 0x34, 0x1b, 0x31, 0x95, 0x69, 0x6b, 0x7e, 0x17, 0x33, 0xcf, 0x25, 0x38, 0x66, 0xef, 0xe5, 0xd0, 0x01, 0xd5, 0x7a, 0x88, 0x60, 0x34, 0xdc, 0x16, 0x4a, 0x35, 0x64, 0xbd, 0x36, 0x10, 0xf9 } +, + /* Prime exponent 2 */ + 64, + { 0xbe, 0x4e, 0x9e, 0x3b, 0x40, 0xf5, 0x6c, 0x62, 0x59, 0xaa, 0x1e, 0x5c, 0xdf, 0x56, 0x59, 0xb1, 0x6f, 0xb8, 0x42, 0x94, 0xe5, 0x8a, 0xd0, 0x16, 0xbd, 0x2c, 0x96, 0xcd, 0x08, 0xe6, 0xcf, 0x68, 0x54, 0xa1, 0x1c, 0xb8, 0x0a, 0xd4, 0xbe, 0x3e, 0x05, 0x7a, 0xaa, 0xcf, 0x02, 0xbd, 0x32, 0x63, 0x73, 0xa2, 0x35, 0xce, 0xb8, 0x9e, 0x82, 0x43, 0x0d, 0x6e, 0x6d, 0x47, 0xd6, 0xce, 0xf8, 0x35 } +, + /* Coefficient */ + 64, + { 0xc0, 0x23, 0x5c, 0x89, 0x73, 0xcf, 0xbf, 0x30, 0xbf, 0x1d, 0xd3, 0xc8, 0x39, 0xf0, 0x2c, 0x94, 0xc6, 0x9d, 0xc5, 0x34, 0xcb, 0xfc, 0x98, 0x88, 0x05, 0xd6, 0xfc, 0x46, 0x2a, 0xdb, 0xd3, 0x77, 0xd1, 0x75, 0xb9, 0xa9, 0x64, 0x60, 0x18, 0xd7, 0xfa, 0xb7, 0x5c, 0x1d, 0x1f, 0x7d, 0x61, 0xb7, 0x7f, 0xa7, 0x95, 0x59, 0xb8, 0x6f, 0xfa, 0x9e, 0xc6, 0xe2, 0x11, 0x33, 0xfa, 0x7f, 0x1a, 0x45 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 8.1", + /* Message to be signed */ + 181, + { 0x9a, 0x28, 0x20, 0xf3, 0xb9, 0x02, 0x9a, 0xbc, 0x18, 0x65, 0xeb, 0x06, 0xfe, 0x61, 0xb8, 0xd3, 0x97, 0xb6, 0x55, 0x72, 0xd6, 0x00, 0x61, 0xca, 0xa7, 0x4e, 0x63, 0x56, 0x93, 0x1e, 0x25, 0x6b, 0x89, 0x71, 0x2d, 0x18, 0x66, 0x84, 0xb4, 0xde, 0x1e, 0x14, 0xc9, 0xeb, 0xfe, 0xf1, 0x6e, 0x40, 0xd9, 0x9d, 0x10, 0x94, 0x39, 0x6c, 0x56, 0x1c, 0x88, 0x31, 0x77, 0xe5, 0x12, 0x6b, 0x9b, 0xe2, 0xd9, 0xa9, 0x68, 0x03, 0x27, 0xd5, 0x37, 0x0c, 0x6f, 0x26, 0x86, 0x1f, 0x58, 0x20, 0xc4, 0x3d, 0xa6, 0x7a, 0x3a, 0xd6, 0x09, 0x04, 0xe2, 0x15, 0xee, 0x6f, 0xf9, 0x34, 0xb9, 0xda, 0x70, 0xd7, 0x73, 0x0c, 0x87, 0x34, 0xab, 0xfc, 0xec, 0xde, 0x89, 0x7f, 0xdd, 0x67, 0x0a, 0x01, 0x46, 0x58, 0x68, 0xad, 0xc9, 0x3f, 0x26, 0x13, 0x19, 0x57, 0xa5, 0x0c, 0x52, 0xfb, 0x77, 0x7c, 0xdb, 0xaa, 0x30, 0x89, 0x2c, 0x9e, 0x12, 0x36, 0x11, 0x64, 0xec, 0x13, 0x97, 0x9d, 0x43, 0x04, 0x81, 0x18, 0xe4, 0x44, 0x5d, 0xb8, 0x7b, 0xee, 0x58, 0xdd, 0x98, 0x7b, 0x34, 0x25, 0xd0, 0x20, 0x71, 0xd8, 0xdb, 0xae, 0x80, 0x70, 0x8b, 0x03, 0x9d, 0xbb, 0x64, 0xdb, 0xd1, 0xde, 0x56, 0x57, 0xd9, 0xfe, 0xd0, 0xc1, 0x18, 0xa5, 0x41 } +, + /* Signature */ + 129, + { 0x03, 0x22, 0xd0, 0x0f, 0xc1, 0xd9, 0x66, 0x94, 0xf3, 0x6e, 0xae, 0xd2, 0x30, 0x90, 0x56, 0xf3, 0xea, 0x1c, 0x1c, 0xc2, 0x2b, 0x13, 0xb6, 0x5e, 0x79, 0x11, 0x8d, 0x20, 0x2c, 0x42, 0xd1, 0x61, 0x30, 0x99, 0x38, 0x05, 0x09, 0xda, 0x74, 0x35, 0xbb, 0x57, 0x92, 0x16, 0xfd, 0x57, 0x65, 0x06, 0x68, 0x42, 0xe3, 0x56, 0xa6, 0x41, 0x6f, 0xc8, 0x42, 0xa2, 0x4a, 0x9e, 0xa1, 0xbc, 0x6a, 0x90, 0x98, 0x05, 0x23, 0xb4, 0x28, 0xe3, 0x99, 0xbb, 0xd6, 0xfc, 0xdc, 0x2c, 0xb7, 0x71, 0xda, 0xf0, 0x03, 0x7a, 0x2d, 0xe8, 0xc7, 0x64, 0x9b, 0xd5, 0x33, 0x17, 0xde, 0x0e, 0x37, 0xc3, 0x14, 0xba, 0xb0, 0xc4, 0x37, 0xbb, 0xd7, 0x98, 0xdf, 0xb9, 0x65, 0x50, 0x6c, 0x34, 0x8b, 0x74, 0x2f, 0x13, 0x8e, 0xf1, 0xd1, 0xa2, 0x03, 0xe0, 0x51, 0xe3, 0x4b, 0xdd, 0x3a, 0x30, 0xe0, 0xfc, 0xe1, 0xac, 0x43 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 8.2", + /* Message to be signed */ + 118, + { 0xea, 0x9a, 0x1a, 0x04, 0xb7, 0xcf, 0x47, 0x8a, 0x89, 0x7a, 0x70, 0x8f, 0xd9, 0x88, 0xf4, 0x8e, 0x80, 0x1e, 0xdb, 0x0b, 0x70, 0x39, 0xdf, 0x8c, 0x23, 0xbb, 0x3c, 0x56, 0xf4, 0xe8, 0x21, 0xac, 0x8b, 0x2b, 0xdd, 0x4b, 0x40, 0xfa, 0xf5, 0x45, 0xc7, 0x78, 0xdd, 0xf9, 0xbc, 0x1a, 0x49, 0xcb, 0x57, 0xf9, 0xb7, 0x1b, 0x6d, 0x48, 0xb2, 0xb6, 0xa5, 0x7a, 0x63, 0xc8, 0x4c, 0xea, 0x85, 0x9d, 0x65, 0xc6, 0x68, 0x28, 0x4b, 0x08, 0xd9, 0x6b, 0xdc, 0xaa, 0xbe, 0x25, 0x2d, 0xb0, 0xe4, 0xa9, 0x6c, 0xb1, 0xba, 0xc6, 0x01, 0x93, 0x41, 0xdb, 0x6f, 0xbe, 0xfb, 0x8d, 0x10, 0x6b, 0x0e, 0x90, 0xed, 0xa6, 0xbc, 0xc6, 0xc6, 0x26, 0x2f, 0x37, 0xe7, 0xea, 0x9c, 0x7e, 0x5d, 0x22, 0x6b, 0xd7, 0xdf, 0x85, 0xec, 0x5e, 0x71, 0xef } +, + /* Signature */ + 129, + { 0x02, 0x68, 0x44, 0x09, 0x39, 0x99, 0x6a, 0xe5, 0xcb, 0xda, 0xfd, 0xbc, 0xa8, 0x6a, 0x7c, 0x42, 0x8a, 0x04, 0xb5, 0x78, 0xfe, 0x2d, 0xbe, 0x51, 0x26, 0xa8, 0x2f, 0xaf, 0x2b, 0xec, 0xff, 0x09, 0x9a, 0xc6, 0x0c, 0xb8, 0x1b, 0x11, 0x7f, 0x1e, 0xbf, 0x42, 0x04, 0xfe, 0x43, 0x70, 0x54, 0x8d, 0x5d, 0x2c, 0x46, 0x80, 0x63, 0x68, 0x2d, 0xa8, 0x7d, 0xc8, 0x01, 0x79, 0xbb, 0x3b, 0xba, 0x85, 0xa1, 0x48, 0xae, 0x2d, 0xe7, 0xdc, 0xb4, 0x94, 0xf4, 0x76, 0x22, 0x1d, 0xf8, 0x21, 0x9d, 0x4a, 0xae, 0x1e, 0x45, 0xaf, 0x65, 0xde, 0x33, 0x4a, 0x1a, 0x6d, 0xc1, 0x45, 0x52, 0x86, 0xae, 0x09, 0xcf, 0x26, 0x72, 0x58, 0x85, 0xe7, 0x74, 0x80, 0x99, 0x72, 0xd7, 0x81, 0x98, 0x05, 0xff, 0xf5, 0xa8, 0xc8, 0x9d, 0x37, 0x37, 0x64, 0x50, 0x73, 0x92, 0x49, 0xf5, 0x7e, 0xb1, 0x51, 0xb7, 0x1d, 0xc0 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.3", + /* Message to be signed */ + 23, + { 0x07, 0xdf, 0x58, 0x6b, 0x90, 0x5b, 0x23, 0xb9, 0x1a, 0xf1, 0x3d, 0xa1, 0x23, 0x04, 0xbf, 0x83, 0xec, 0xa8, 0xa7, 0x3e, 0x87, 0x1f, 0xf9 } +, + /* Signature */ + 129, + { 0x01, 0xbf, 0xd9, 0x15, 0xff, 0x77, 0x80, 0xf1, 0x4c, 0xcc, 0x55, 0xbd, 0x03, 0x06, 0xb3, 0xae, 0xda, 0x5b, 0x5b, 0x59, 0x55, 0xa8, 0x26, 0xd4, 0x52, 0x6b, 0x0b, 0xc7, 0x66, 0x15, 0x4f, 0xa8, 0xda, 0x59, 0x56, 0x05, 0x78, 0xcc, 0xd4, 0x88, 0x2f, 0xe9, 0x70, 0x92, 0xfb, 0xc7, 0x36, 0xfd, 0xa7, 0x3c, 0xee, 0xfd, 0x10, 0x38, 0x94, 0x06, 0x3e, 0x93, 0xe2, 0x2a, 0x7b, 0x5c, 0x44, 0xf7, 0xa8, 0x5e, 0x3b, 0xdb, 0x96, 0x71, 0x9a, 0x09, 0x37, 0x43, 0x03, 0xc9, 0x1e, 0xd7, 0xe2, 0x27, 0x49, 0xfe, 0x3c, 0x4d, 0x6b, 0x96, 0x69, 0x9d, 0x50, 0x7c, 0x50, 0xad, 0xcf, 0xbd, 0xfc, 0x13, 0x1d, 0x6b, 0x5f, 0x2c, 0xf1, 0x83, 0x0e, 0x31, 0xea, 0xbe, 0x39, 0xae, 0xb5, 0x17, 0x96, 0x9c, 0x94, 0xa8, 0x1c, 0xfe, 0xfe, 0x67, 0x31, 0xaa, 0x2c, 0xdf, 0xfe, 0x28, 0xc8, 0xaf, 0x71, 0x40, 0xf4 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.4", + /* Message to be signed */ + 116, + { 0x50, 0x0b, 0x87, 0x77, 0xc7, 0xf8, 0x39, 0xba, 0xf0, 0xa6, 0x4b, 0xbb, 0xdb, 0xc5, 0xce, 0x79, 0x75, 0x5c, 0x57, 0xa2, 0x05, 0xb8, 0x45, 0xc1, 0x74, 0xe2, 0xd2, 0xe9, 0x05, 0x46, 0xa0, 0x89, 0xc4, 0xe6, 0xec, 0x8a, 0xdf, 0xfa, 0x23, 0xa7, 0xea, 0x97, 0xba, 0xe6, 0xb6, 0x5d, 0x78, 0x2b, 0x82, 0xdb, 0x5d, 0x2b, 0x5a, 0x56, 0xd2, 0x2a, 0x29, 0xa0, 0x5e, 0x7c, 0x44, 0x33, 0xe2, 0xb8, 0x2a, 0x62, 0x1a, 0xbb, 0xa9, 0x0a, 0xdd, 0x05, 0xce, 0x39, 0x3f, 0xc4, 0x8a, 0x84, 0x05, 0x42, 0x45, 0x1a, 0xc7, 0xcd, 0x69, 0x8d, 0x84, 0xb6, 0x51, 0x28, 0xd8, 0x83, 0x5e, 0x3a, 0x8b, 0x1e, 0xb0, 0xe0, 0x1c, 0xb5, 0x41, 0xec, 0x50, 0xf1, 0x03, 0x6e, 0x00, 0x8e, 0x71, 0xe9, 0x64, 0xda, 0xdc, 0x92, 0x19, 0xed } +, + /* Signature */ + 129, + { 0x00, 0x7a, 0xe0, 0xcf, 0xd7, 0xf4, 0xc6, 0xad, 0x1f, 0xf8, 0x4b, 0x4a, 0x60, 0x6b, 0xa1, 0xc4, 0x79, 0x8c, 0x2e, 0x49, 0x9b, 0x04, 0x5b, 0x56, 0x7d, 0x32, 0x63, 0x4f, 0xd9, 0x55, 0xf2, 0x68, 0x26, 0x0a, 0xb6, 0x59, 0xbf, 0x5b, 0xe9, 0x9e, 0x08, 0x26, 0xeb, 0x38, 0x70, 0xe8, 0xf6, 0x2f, 0x5a, 0x3c, 0xe7, 0x58, 0xe6, 0xd1, 0x56, 0xc3, 0x29, 0x9b, 0x43, 0x1c, 0xd9, 0xdf, 0xc6, 0x58, 0x37, 0xee, 0x94, 0x22, 0x0d, 0x95, 0x23, 0x51, 0x14, 0x87, 0x99, 0xbe, 0x9f, 0xca, 0xf9, 0xbe, 0x26, 0x4d, 0xae, 0xbe, 0xba, 0x2b, 0xe8, 0x66, 0x05, 0x20, 0x1e, 0xf9, 0xa0, 0xd9, 0x8f, 0x58, 0xec, 0x63, 0x8a, 0xbf, 0xc4, 0xf2, 0x78, 0x48, 0xf5, 0xd4, 0x79, 0xd3, 0x34, 0xac, 0xc2, 0xa9, 0x7f, 0xdd, 0x2d, 0x32, 0x7e, 0xc4, 0xc7, 0xdd, 0xc5, 0xa8, 0xab, 0xd5, 0x66, 0xde, 0x35, 0xd1, 0x4f } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.5", + /* Message to be signed */ + 238, + { 0x6b, 0x3f, 0x6a, 0x63, 0xd4, 0xe7, 0x78, 0x59, 0x24, 0x3c, 0x9c, 0xcc, 0xdc, 0x98, 0x01, 0x65, 0x23, 0xab, 0xb0, 0x24, 0x83, 0xb3, 0x55, 0x91, 0xc3, 0x3a, 0xad, 0x81, 0x21, 0x3b, 0xb7, 0xc7, 0xbb, 0x1a, 0x47, 0x0a, 0xab, 0xc1, 0x0d, 0x44, 0x25, 0x6c, 0x4d, 0x45, 0x59, 0xd9, 0x16, 0xef, 0xa8, 0xbf, 0xf9, 0x62, 0x12, 0xb2, 0xf4, 0xa3, 0xf3, 0x71, 0xa1, 0x0d, 0x57, 0x41, 0x52, 0x65, 0x5f, 0x5d, 0xfb, 0xa2, 0x25, 0xf1, 0x08, 0x95, 0xa8, 0x77, 0x16, 0xc1, 0x37, 0x45, 0x0b, 0xb9, 0x51, 0x9d, 0xfa, 0xa1, 0xf2, 0x07, 0xfa, 0xa9, 0x42, 0xea, 0x88, 0xab, 0xf7, 0x1e, 0x9c, 0x17, 0x98, 0x00, 0x85, 0xb5, 0x55, 0xae, 0xba, 0xb7, 0x62, 0x64, 0xae, 0x2a, 0x3a, 0xb9, 0x3c, 0x2d, 0x12, 0x98, 0x11, 0x91, 0xdd, 0xac, 0x6f, 0xb5, 0x94, 0x9e, 0xb3, 0x6a, 0xee, 0x3c, 0x5d, 0xa9, 0x40, 0xf0, 0x07, 0x52, 0xc9, 0x16, 0xd9, 0x46, 0x08, 0xfa, 0x7d, 0x97, 0xba, 0x6a, 0x29, 0x15, 0xb6, 0x88, 0xf2, 0x03, 0x23, 0xd4, 0xe9, 0xd9, 0x68, 0x01, 0xd8, 0x9a, 0x72, 0xab, 0x58, 0x92, 0xdc, 0x21, 0x17, 0xc0, 0x74, 0x34, 0xfc, 0xf9, 0x72, 0xe0, 0x58, 0xcf, 0x8c, 0x41, 0xca, 0x4b, 0x4f, 0xf5, 0x54, 0xf7, 0xd5, 0x06, 0x8a, 0xd3, 0x15, 0x5f, 0xce, 0xd0, 0xf3, 0x12, 0x5b, 0xc0, 0x4f, 0x91, 0x93, 0x37, 0x8a, 0x8f, 0x5c, 0x4c, 0x3b, 0x8c, 0xb4, 0xdd, 0x6d, 0x1c, 0xc6, 0x9d, 0x30, 0xec, 0xca, 0x6e, 0xaa, 0x51, 0xe3, 0x6a, 0x05, 0x73, 0x0e, 0x9e, 0x34, 0x2e, 0x85, 0x5b, 0xaf, 0x09, 0x9d, 0xef, 0xb8, 0xaf, 0xd7, 0xad, 0x8b, 0x15, 0x23, 0x70, 0x36, 0x46 } +, + /* Signature */ + 129, + { 0x01, 0x92, 0x1f, 0x22, 0xf4, 0x71, 0xa0, 0x8a, 0xf8, 0x19, 0xa9, 0x52, 0xe1, 0x83, 0x68, 0xce, 0x15, 0xf9, 0xb0, 0x64, 0xeb, 0x1d, 0x00, 0xb1, 0x28, 0x99, 0x78, 0x02, 0x44, 0xfe, 0x8c, 0x44, 0x24, 0xb2, 0x1f, 0x64, 0x35, 0x0b, 0x92, 0x26, 0xfe, 0x95, 0xff, 0x54, 0xf1, 0x14, 0x39, 0x83, 0x9b, 0xfb, 0x54, 0xf9, 0x39, 0xc9, 0x14, 0x95, 0xe4, 0xf0, 0x27, 0x90, 0x18, 0x97, 0x27, 0x3c, 0xfa, 0x29, 0x5a, 0x57, 0x15, 0x1f, 0x4e, 0x91, 0x1d, 0xc1, 0x02, 0xa7, 0x7d, 0x95, 0x8b, 0x62, 0x27, 0x24, 0xc0, 0xfd, 0x3a, 0x34, 0xb3, 0xb7, 0xbe, 0xfb, 0x8b, 0x8c, 0xd0, 0x66, 0x6e, 0x81, 0x5d, 0x0c, 0x07, 0xf2, 0xec, 0xb7, 0xc4, 0xdd, 0x2f, 0x42, 0xb7, 0xf4, 0x09, 0x13, 0x12, 0xe3, 0xd7, 0xb2, 0xdf, 0x26, 0x78, 0x87, 0xe0, 0xac, 0xa7, 0x0b, 0x54, 0x1c, 0x4c, 0x1e, 0xea, 0x16, 0xb5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.6", + /* Message to be signed */ + 10, + { 0x93, 0x29, 0xa5, 0x80, 0x90, 0xde, 0x8b, 0xe5, 0x7c, 0x42 } +, + /* Signature */ + 129, + { 0x01, 0x5c, 0xe2, 0x4a, 0x6f, 0x2b, 0x37, 0x3a, 0x19, 0x99, 0x7b, 0xb2, 0x0c, 0x18, 0xac, 0x65, 0x9f, 0x1e, 0xdc, 0x0f, 0x25, 0xc9, 0xe5, 0xbf, 0x76, 0xd5, 0x69, 0x99, 0x65, 0x20, 0xc2, 0x80, 0xef, 0xdc, 0xf1, 0x5e, 0x2d, 0x63, 0xca, 0xaf, 0xf6, 0xc7, 0x7a, 0xe0, 0x38, 0x97, 0x03, 0x7a, 0x06, 0x15, 0xf9, 0x83, 0x8c, 0x52, 0x10, 0x4e, 0x97, 0x25, 0x18, 0xe2, 0x90, 0xfa, 0xc3, 0x8f, 0x63, 0x24, 0x75, 0x30, 0xb4, 0xcf, 0x61, 0xc6, 0xec, 0xe3, 0x42, 0x9b, 0x53, 0x07, 0x81, 0xcf, 0x34, 0x96, 0x4f, 0x32, 0xae, 0x50, 0xf1, 0x09, 0x34, 0x63, 0x83, 0x86, 0xd3, 0xb4, 0xdf, 0x76, 0x1c, 0x59, 0x7d, 0x4a, 0xa7, 0xfe, 0xca, 0x26, 0x6c, 0x27, 0xf8, 0xce, 0x66, 0xad, 0xe1, 0xbe, 0x26, 0x59, 0xce, 0x14, 0x2b, 0xa5, 0xf9, 0x35, 0x88, 0x3c, 0x7e, 0x8c, 0x9b, 0x89, 0x57, 0xab, 0xf2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.7", + /* Message to be signed */ + 211, + { 0x6a, 0xce, 0x0f, 0x1e, 0x1d, 0xc6, 0x3e, 0x39, 0x4a, 0x06, 0x1f, 0x52, 0x2a, 0x54, 0x2f, 0xbe, 0x71, 0x20, 0x25, 0x4e, 0x36, 0xe9, 0xf6, 0x5d, 0x19, 0x57, 0xc9, 0x56, 0x28, 0x78, 0x2c, 0xb0, 0x36, 0x8f, 0x3c, 0x13, 0xda, 0xd6, 0x56, 0x71, 0x79, 0xc1, 0xea, 0x24, 0xfe, 0x83, 0x5a, 0x26, 0x63, 0x85, 0xe4, 0x68, 0x83, 0x17, 0xb8, 0x2b, 0x0c, 0x3f, 0xe6, 0x3c, 0xf2, 0xd5, 0x2f, 0x04, 0xae, 0x8a, 0x38, 0xa5, 0x75, 0x59, 0xbb, 0x95, 0xd9, 0xeb, 0xd5, 0xfe, 0x8a, 0x9a, 0xfe, 0x14, 0x79, 0x90, 0x9e, 0xb9, 0x9e, 0x0d, 0x3e, 0xf3, 0xf3, 0x12, 0xe0, 0xa4, 0xab, 0xb7, 0x66, 0xc7, 0xe2, 0x13, 0x1a, 0x5f, 0xfb, 0x48, 0x31, 0x83, 0xfb, 0xb4, 0x22, 0x34, 0xd3, 0x2e, 0x58, 0x1f, 0x59, 0x50, 0x65, 0xc4, 0x89, 0x82, 0x61, 0xec, 0xd0, 0xae, 0x57, 0x2c, 0x22, 0x1c, 0x25, 0x8d, 0xe9, 0x50, 0xa4, 0x08, 0x01, 0xef, 0x79, 0x6d, 0x4d, 0xd0, 0x04, 0x06, 0x45, 0xfc, 0x53, 0x4d, 0x8e, 0x78, 0x58, 0x23, 0x48, 0x38, 0xed, 0x12, 0xc6, 0x87, 0x40, 0xc1, 0x4e, 0x37, 0x16, 0x13, 0xf0, 0x04, 0x61, 0x76, 0xbb, 0xb0, 0xf4, 0x3d, 0x99, 0x75, 0x19, 0xc4, 0x0c, 0x67, 0x14, 0x96, 0xff, 0x35, 0x0a, 0x3f, 0xdf, 0x42, 0x9c, 0xc2, 0x2f, 0x46, 0x4f, 0x43, 0x5f, 0x6b, 0x29, 0xe7, 0xe1, 0xc3, 0x0e, 0xbd, 0x50, 0x59, 0x27, 0xd4, 0xa0, 0x96, 0x58, 0x7f, 0xc3, 0x8d, 0x3d, 0x64, 0x94, 0x39, 0x1e } +, + /* Signature */ + 129, + { 0x02, 0x73, 0xba, 0x2c, 0x50, 0x2b, 0x3f, 0x29, 0x84, 0xc5, 0x48, 0xd9, 0xf7, 0xd6, 0xc9, 0xb3, 0xd7, 0xfd, 0x46, 0x08, 0x78, 0xc8, 0x4d, 0x6b, 0xe3, 0x3b, 0x28, 0x10, 0x6e, 0x15, 0xfc, 0x22, 0x17, 0xef, 0xf7, 0x41, 0xcd, 0xc2, 0x66, 0x83, 0x4b, 0xea, 0xa8, 0x6d, 0xa4, 0x05, 0xf3, 0xca, 0xe6, 0x06, 0xcc, 0x61, 0xf2, 0x54, 0x7b, 0xb9, 0x22, 0x92, 0x03, 0x45, 0xfe, 0x8f, 0xbb, 0x5e, 0x7b, 0x6a, 0xbf, 0x91, 0xea, 0xe8, 0xc4, 0x26, 0x60, 0x64, 0x50, 0x25, 0xcc, 0x7f, 0xc0, 0x7a, 0x53, 0x4b, 0x76, 0xd3, 0x78, 0x75, 0xe3, 0xf4, 0x0d, 0x52, 0x70, 0xc1, 0x0e, 0xf4, 0x6c, 0x7f, 0xe4, 0x5a, 0xfa, 0xbc, 0xff, 0xae, 0x2a, 0x9c, 0x94, 0x11, 0xbd, 0x04, 0xd6, 0x1d, 0x4c, 0x0e, 0x5f, 0xfc, 0x02, 0x2c, 0xb3, 0x6a, 0x64, 0xb7, 0xc3, 0xa8, 0xc8, 0x9b, 0xfd, 0xe4, 0x36, 0xba, 0xfd } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.8", + /* Message to be signed */ + 157, + { 0xfd, 0xcc, 0x0f, 0x1e, 0x5d, 0xcb, 0xe5, 0x01, 0x6a, 0x6b, 0x0f, 0x8c, 0x28, 0xf5, 0xb3, 0x31, 0xff, 0x58, 0x28, 0x37, 0x13, 0x8d, 0xbf, 0x62, 0xef, 0x7f, 0xf6, 0x1b, 0xc1, 0xa3, 0x53, 0x96, 0xc9, 0x2e, 0x3d, 0x54, 0x8d, 0x39, 0x9e, 0x35, 0x0a, 0x3c, 0x6b, 0xc2, 0xfd, 0xb5, 0xda, 0x94, 0xb9, 0x86, 0xa4, 0xce, 0x6d, 0xee, 0x10, 0x4e, 0x9f, 0x27, 0x4b, 0x15, 0x25, 0x58, 0xbf, 0xa7, 0x22, 0xcc, 0xfd, 0xda, 0x3b, 0x26, 0xb9, 0xf8, 0xe5, 0x15, 0x25, 0xf3, 0x81, 0x03, 0x4c, 0x51, 0xfd, 0xc9, 0xf7, 0x91, 0x2a, 0xc9, 0x27, 0xd1, 0xa7, 0x08, 0xcc, 0x2d, 0xbb, 0xcd, 0x7b, 0xa6, 0xc0, 0x31, 0xb0, 0x11, 0xcb, 0xa8, 0xe2, 0xdf, 0x8f, 0xc9, 0xb8, 0x83, 0x64, 0xee, 0x96, 0x5f, 0x24, 0x27, 0x0e, 0x43, 0x48, 0x62, 0x32, 0x53, 0xcb, 0x9e, 0x59, 0xd6, 0xf7, 0x94, 0x09, 0x09, 0x94, 0xa7, 0xa4, 0xc9, 0x30, 0x02, 0x70, 0xb5, 0x7f, 0x24, 0x39, 0xeb, 0xbb, 0xa4, 0x65, 0x84, 0x67, 0xaf, 0xdb, 0x7f, 0xe8, 0x6b, 0x4f, 0x1a, 0xad, 0x1d, 0x3d, 0x3b, 0x2f } +, + /* Signature */ + 129, + { 0x00, 0xa7, 0xc4, 0x50, 0xb3, 0x0b, 0x2e, 0xcb, 0x19, 0xbb, 0x70, 0x9a, 0x92, 0x31, 0xcb, 0xfa, 0x9f, 0x0d, 0x61, 0x69, 0x7a, 0x26, 0xb9, 0x0a, 0x96, 0xd9, 0x1c, 0x24, 0xc4, 0xda, 0x70, 0xd7, 0xb0, 0x0b, 0x59, 0x23, 0xc8, 0xe1, 0x2d, 0x41, 0x09, 0x4b, 0x70, 0x5d, 0x50, 0xc7, 0x78, 0xbb, 0xda, 0xce, 0xc6, 0x60, 0xd5, 0xc1, 0x5d, 0xff, 0xd3, 0xa2, 0x47, 0x8f, 0xd9, 0x33, 0x70, 0x80, 0xdc, 0xa1, 0x6b, 0x9c, 0x13, 0xe6, 0x23, 0x3b, 0x82, 0x92, 0xb2, 0xfd, 0xcc, 0x29, 0xe9, 0xbf, 0x3b, 0x21, 0xa7, 0x18, 0x78, 0xf3, 0x4e, 0xf5, 0xeb, 0x7c, 0xd5, 0x0a, 0xd4, 0x12, 0x03, 0x72, 0x5a, 0x0f, 0x1c, 0x66, 0x3f, 0x73, 0x42, 0xec, 0x7c, 0x3d, 0xf3, 0xd5, 0xaa, 0x51, 0xd0, 0x58, 0xdf, 0xcc, 0xce, 0x5f, 0xe6, 0x9d, 0x36, 0x3b, 0x42, 0x84, 0x32, 0x08, 0x79, 0xe8, 0x6d, 0x58, 0xb5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.9", + /* Message to be signed */ + 92, + { 0x2d, 0x1f, 0xcd, 0x17, 0x66, 0xf7, 0xd4, 0x5f, 0x29, 0x59, 0x4f, 0x9d, 0x4f, 0x74, 0x39, 0x41, 0xae, 0x91, 0x2a, 0x97, 0x91, 0x1f, 0xfc, 0x3d, 0x65, 0xdc, 0xd9, 0x65, 0x60, 0x10, 0x77, 0x3b, 0xb0, 0x22, 0x4b, 0xa6, 0xdf, 0x11, 0x1b, 0x1c, 0x13, 0x68, 0x38, 0x4f, 0x24, 0x92, 0xfc, 0x4f, 0xa7, 0x28, 0x0c, 0x06, 0x65, 0x14, 0xae, 0x84, 0xf7, 0x61, 0x45, 0x63, 0xd9, 0x05, 0x2c, 0xa9, 0x4e, 0xf4, 0x46, 0xa3, 0x1b, 0x46, 0x3b, 0xd6, 0xc2, 0x50, 0x56, 0x80, 0x50, 0x88, 0xc1, 0xd3, 0x1a, 0xba, 0xff, 0x52, 0x15, 0xf7, 0xa8, 0xf8, 0x9e, 0x7b, 0x64, 0xf2 } +, + /* Signature */ + 129, + { 0x02, 0xc0, 0xe0, 0x71, 0xe8, 0x36, 0x90, 0xdc, 0x14, 0xd9, 0xa3, 0x7d, 0x61, 0xe0, 0xaf, 0xc2, 0x7d, 0xf9, 0x78, 0x03, 0x9d, 0xa6, 0x01, 0xca, 0x2c, 0xec, 0x1d, 0xec, 0x8f, 0x0d, 0x17, 0xd2, 0xff, 0xc4, 0x50, 0xe6, 0x78, 0x38, 0x0a, 0x02, 0x5a, 0x41, 0xc7, 0x46, 0x11, 0x8f, 0x58, 0x36, 0x42, 0x52, 0xa1, 0x22, 0x53, 0x9e, 0xcc, 0xbb, 0xb4, 0xab, 0x3d, 0x8d, 0x37, 0x7b, 0xdb, 0xb9, 0x11, 0xc5, 0x8a, 0x4c, 0xb9, 0x46, 0x2f, 0x36, 0xdc, 0x38, 0x92, 0x48, 0x50, 0x1b, 0xd0, 0x8f, 0x48, 0xe3, 0x53, 0x3b, 0x82, 0x59, 0x1a, 0x2a, 0x20, 0xcf, 0x62, 0xdf, 0x5f, 0x5a, 0x1f, 0x84, 0xea, 0x30, 0x0c, 0xb3, 0x94, 0x57, 0x13, 0x71, 0x41, 0xad, 0x8c, 0xd1, 0xd1, 0x85, 0xab, 0xb1, 0x7b, 0xa5, 0xd0, 0x3b, 0xe3, 0x48, 0xc0, 0x67, 0x97, 0xb0, 0x95, 0x58, 0xf0, 0x33, 0x1c, 0x24, 0xb9 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.10", + /* Message to be signed */ + 179, + { 0x4f, 0x46, 0x9a, 0xb7, 0x9c, 0xb8, 0x93, 0xa5, 0x3c, 0x0e, 0xe3, 0x81, 0x5a, 0x8b, 0xc0, 0x87, 0xeb, 0x74, 0xea, 0x36, 0x61, 0x5b, 0xdd, 0xc3, 0x33, 0xde, 0xe0, 0x5f, 0xc7, 0x26, 0x65, 0xaa, 0x6d, 0x0b, 0xd5, 0x9e, 0x47, 0x22, 0x98, 0x29, 0x83, 0x4b, 0x1f, 0x91, 0xc9, 0xcd, 0x81, 0xce, 0x28, 0xd6, 0x8f, 0x14, 0x82, 0x5a, 0x34, 0x5f, 0x3a, 0x4f, 0x38, 0xa0, 0x1b, 0x2d, 0xae, 0x59, 0x10, 0x07, 0x64, 0xaa, 0xb9, 0x90, 0xa8, 0x50, 0xb1, 0x1c, 0x13, 0xd5, 0xdf, 0xe4, 0x19, 0xf1, 0xd9, 0x20, 0xd0, 0x0c, 0xf1, 0x3b, 0xf4, 0x30, 0xe4, 0xca, 0x82, 0x87, 0x98, 0x9b, 0xee, 0xbe, 0xda, 0x3e, 0x5d, 0x40, 0x36, 0x02, 0x8c, 0x8e, 0xf9, 0x54, 0x6e, 0x35, 0x01, 0x50, 0xd1, 0x96, 0xf0, 0x05, 0x60, 0xba, 0xe1, 0x47, 0x22, 0x99, 0xe7, 0xf4, 0x29, 0x1d, 0x54, 0x46, 0x29, 0xc4, 0xf6, 0x52, 0xe3, 0x5c, 0xde, 0x4f, 0x80, 0x3e, 0x1b, 0x3c, 0xa3, 0x38, 0x09, 0x51, 0x5e, 0xf2, 0x3d, 0x25, 0x4b, 0x8e, 0x65, 0x20, 0x2a, 0x14, 0xa4, 0x11, 0xb1, 0xbc, 0x31, 0x5c, 0x5f, 0xfa, 0xec, 0xb8, 0x21, 0x11, 0x97, 0x80, 0x9d, 0xcb, 0x5c, 0xed, 0x68, 0x2c, 0x09, 0xf6, 0x7e, 0x41, 0xd1, 0x60, 0x2c } +, + /* Signature */ + 129, + { 0x01, 0x71, 0x29, 0x64, 0xea, 0x9a, 0xb9, 0x70, 0x29, 0x5b, 0x81, 0xb0, 0xfb, 0xd8, 0x35, 0x7e, 0x54, 0xb9, 0x36, 0xee, 0x87, 0x72, 0xd8, 0xae, 0x9c, 0x96, 0x12, 0x71, 0x6f, 0xcc, 0x2f, 0xcb, 0x78, 0x4c, 0xa9, 0xab, 0xee, 0xeb, 0xb8, 0xfc, 0xb6, 0x89, 0x82, 0x16, 0x1c, 0xc7, 0x4e, 0x40, 0xc7, 0xc0, 0x22, 0x47, 0xc0, 0xd0, 0x0e, 0x03, 0xbc, 0x8e, 0x1a, 0x70, 0x51, 0xb8, 0x7c, 0x90, 0xdd, 0x7d, 0x3d, 0xfc, 0x95, 0xe0, 0xb3, 0xc8, 0x8e, 0x7a, 0x0f, 0x37, 0xf3, 0x0e, 0x1b, 0xd5, 0xfe, 0x8b, 0x6e, 0xee, 0x46, 0x5a, 0x0b, 0x34, 0xcb, 0x59, 0xc6, 0x4e, 0xbd, 0xb5, 0x7d, 0x6f, 0x5f, 0xdf, 0xf2, 0xe7, 0x0b, 0xb1, 0x9c, 0x60, 0xd9, 0x88, 0xea, 0x95, 0x6c, 0xdc, 0xdd, 0x1b, 0xe5, 0x62, 0xf2, 0x6f, 0xb3, 0x7c, 0x34, 0xda, 0x52, 0xa9, 0xf9, 0x11, 0xb9, 0x97, 0x43, 0x81, 0x2c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.11", + /* Message to be signed */ + 35, + { 0x52, 0xbb, 0x76, 0xc9, 0xea, 0x26, 0x5d, 0x6f, 0xad, 0x10, 0x83, 0x72, 0xff, 0xab, 0x25, 0x03, 0xbb, 0x20, 0xd3, 0x8d, 0x37, 0xdf, 0x19, 0x92, 0x54, 0xa2, 0xf6, 0xde, 0x0c, 0x4f, 0xca, 0x7a, 0x73, 0x03, 0x36 } +, + /* Signature */ + 129, + { 0x01, 0x0c, 0x55, 0x34, 0x23, 0x60, 0x22, 0x60, 0x15, 0x8a, 0x17, 0x13, 0x3b, 0x5d, 0x30, 0xef, 0xe9, 0x8e, 0x9a, 0xeb, 0x35, 0x3b, 0xab, 0x33, 0x71, 0xe4, 0x91, 0xcd, 0xbe, 0xbd, 0x35, 0x0a, 0x0a, 0x47, 0x0b, 0x9d, 0xbf, 0xd1, 0x89, 0x33, 0x51, 0x1f, 0x0d, 0x0e, 0x36, 0x94, 0xa8, 0xac, 0x4b, 0xf3, 0xf5, 0xb6, 0xeb, 0x9b, 0xf7, 0x1c, 0x23, 0xd9, 0x4c, 0x2e, 0x64, 0xbe, 0xb7, 0xb7, 0xc7, 0x22, 0x52, 0xca, 0x82, 0x7b, 0xd0, 0xc0, 0x56, 0x7b, 0xa8, 0xa1, 0x0a, 0x6d, 0x3b, 0x7e, 0x18, 0x7b, 0x0f, 0xd8, 0xe9, 0xe9, 0x5d, 0x4f, 0xe4, 0x80, 0xf2, 0x50, 0xdc, 0x7f, 0x03, 0x42, 0x29, 0x0e, 0x9a, 0x7d, 0x32, 0x70, 0x3a, 0x72, 0x13, 0xc6, 0x52, 0x13, 0xad, 0xed, 0x45, 0x57, 0x54, 0x78, 0x1f, 0x3d, 0xb7, 0x3e, 0x79, 0xe3, 0xd1, 0xba, 0x6a, 0xf7, 0xf6, 0x90, 0xfe, 0x81, 0x73 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.12", + /* Message to be signed */ + 72, + { 0x5f, 0x59, 0x7a, 0x19, 0xcb, 0xf5, 0x14, 0x30, 0xd3, 0xc6, 0xa2, 0x47, 0xa5, 0x23, 0x54, 0x07, 0x38, 0x6c, 0xae, 0xd0, 0xa2, 0x94, 0xf3, 0xf4, 0x1f, 0x3f, 0x37, 0x82, 0x50, 0xd4, 0xc5, 0xa2, 0xc9, 0x92, 0x75, 0xf9, 0x55, 0x44, 0xcc, 0xc1, 0xd7, 0x7e, 0x5c, 0x15, 0x1a, 0xf1, 0x3e, 0xd6, 0x0b, 0xe5, 0x22, 0xeb, 0x8c, 0xab, 0xed, 0x89, 0xa9, 0xb4, 0x5b, 0x09, 0x65, 0x46, 0x00, 0xf9, 0xfc, 0x75, 0x1e, 0x8b, 0x12, 0xe6, 0x7e, 0x52 } +, + /* Signature */ + 129, + { 0x00, 0x3b, 0xd4, 0xaa, 0x90, 0x81, 0xfe, 0x7e, 0x9f, 0x69, 0xa2, 0x69, 0xfe, 0xc8, 0xc8, 0xa7, 0x36, 0x70, 0xc0, 0x37, 0xe8, 0x5a, 0x1f, 0x36, 0xfc, 0xad, 0x74, 0xe5, 0xb5, 0x2d, 0x71, 0x0a, 0x5a, 0x18, 0xba, 0x09, 0x5b, 0x98, 0x10, 0xcc, 0x69, 0x37, 0xbc, 0x76, 0x34, 0x09, 0x51, 0xe7, 0xfe, 0xd7, 0x5b, 0x32, 0x6d, 0x0a, 0x3b, 0x0f, 0x26, 0xc2, 0x9c, 0xd5, 0xeb, 0x64, 0x15, 0xbb, 0xf7, 0xe2, 0xdd, 0x60, 0xad, 0xf6, 0xa0, 0xe6, 0x13, 0x02, 0xdc, 0xc6, 0x60, 0xcc, 0xe9, 0x10, 0x40, 0x8b, 0x4f, 0x99, 0xa4, 0x40, 0xae, 0x2a, 0xd6, 0xc3, 0x07, 0x72, 0xc2, 0x9a, 0x9e, 0x7b, 0x32, 0x80, 0xe2, 0xe2, 0x93, 0x9a, 0xba, 0x0b, 0x54, 0xab, 0x02, 0x2a, 0xa3, 0x29, 0x50, 0x22, 0x71, 0x8c, 0xd3, 0xb7, 0x87, 0xb1, 0x13, 0x79, 0x90, 0xfb, 0xeb, 0xef, 0xac, 0xec, 0x8c, 0xb7, 0x49 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.13", + /* Message to be signed */ + 36, + { 0x84, 0x0c, 0xc9, 0x00, 0xcb, 0x4b, 0x2c, 0xb6, 0x7a, 0x30, 0x4a, 0x9b, 0x02, 0x82, 0x6d, 0xb0, 0xd6, 0x67, 0x36, 0x92, 0x2e, 0x78, 0x70, 0x13, 0xd6, 0xbf, 0x21, 0x4d, 0xf5, 0x79, 0xff, 0x0c, 0xf4, 0x82, 0x1f, 0x9b } +, + /* Signature */ + 129, + { 0x01, 0x3b, 0x6c, 0x08, 0x0f, 0x68, 0x93, 0x95, 0x05, 0xe1, 0x87, 0xa4, 0x94, 0x82, 0xc7, 0x91, 0x27, 0x8d, 0xa3, 0xad, 0x4a, 0x74, 0x7c, 0x4f, 0x01, 0x79, 0x1b, 0x92, 0x48, 0x05, 0xb6, 0x82, 0xf6, 0x49, 0xbb, 0xd8, 0x0d, 0xba, 0x12, 0xfb, 0xbe, 0x59, 0x40, 0xf1, 0x7f, 0x27, 0xe7, 0x5d, 0x42, 0x67, 0x7c, 0x4c, 0xcc, 0xdf, 0xfd, 0x00, 0x48, 0x77, 0x2e, 0x36, 0x93, 0x4c, 0x69, 0x12, 0x12, 0x8f, 0xf9, 0x03, 0xaf, 0xea, 0x5e, 0x1c, 0xa8, 0xfe, 0x94, 0x24, 0xfc, 0x97, 0x9b, 0x21, 0x87, 0x98, 0x76, 0x98, 0xa5, 0xc5, 0xa7, 0x5e, 0x7d, 0x70, 0x70, 0xa2, 0xa6, 0x74, 0x85, 0x2b, 0xd8, 0x05, 0xbf, 0x13, 0xbb, 0xd1, 0x29, 0x6b, 0xff, 0x13, 0x10, 0xa6, 0xd6, 0xed, 0x45, 0xfd, 0xf8, 0x67, 0x2d, 0x52, 0x41, 0xe7, 0x4c, 0xd4, 0xc4, 0x19, 0x86, 0xe4, 0x36, 0x25, 0x50, 0x0c, 0x23 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.14", + /* Message to be signed */ + 216, + { 0xc6, 0x41, 0x71, 0x94, 0x13, 0x3b, 0x5f, 0x8e, 0xa6, 0x3d, 0x95, 0x58, 0x1c, 0x89, 0x6f, 0x5b, 0x9e, 0xf3, 0xd8, 0x7c, 0xf6, 0x6c, 0x02, 0x91, 0x64, 0x0f, 0x35, 0x0a, 0x32, 0x5b, 0x49, 0x11, 0x52, 0xe9, 0xd1, 0x43, 0x0d, 0x68, 0x70, 0x34, 0x6e, 0x46, 0x8e, 0x71, 0x99, 0x45, 0xd4, 0xe3, 0x65, 0xd0, 0x01, 0x07, 0x5f, 0xa9, 0x70, 0xf2, 0xa9, 0x87, 0x0a, 0x1c, 0x65, 0x43, 0x4b, 0xa1, 0x70, 0x02, 0x41, 0x2a, 0xcc, 0x4c, 0xc7, 0x4d, 0x28, 0xb2, 0xde, 0xe2, 0x9b, 0x36, 0xe3, 0x97, 0xb6, 0x8c, 0x5d, 0x59, 0xcf, 0x67, 0x7c, 0x29, 0xae, 0xe7, 0x93, 0xa9, 0x30, 0x0b, 0x7b, 0xf4, 0xc6, 0x73, 0xb3, 0xe0, 0xb6, 0x03, 0xa3, 0x61, 0x1c, 0xa9, 0x02, 0x44, 0xff, 0x08, 0x78, 0x75, 0xc5, 0x16, 0x88, 0x57, 0xcb, 0x92, 0xa9, 0x5a, 0xaa, 0x61, 0xdf, 0xf3, 0xc2, 0x12, 0xdc, 0x62, 0x06, 0xf1, 0x71, 0x47, 0xc4, 0x4b, 0x95, 0x07, 0xd5, 0xc8, 0x90, 0x75, 0x8b, 0xb3, 0x5b, 0xb7, 0x2a, 0x2a, 0x5e, 0x9d, 0x4d, 0xb2, 0x65, 0xe5, 0x37, 0x3a, 0x5b, 0x34, 0x02, 0x90, 0x4f, 0x0f, 0x1a, 0x12, 0x05, 0xd5, 0xbc, 0xc5, 0x90, 0x25, 0xd3, 0x22, 0x0a, 0x5d, 0xe1, 0xb1, 0x82, 0xa8, 0x4d, 0x30, 0x41, 0x2b, 0x84, 0x26, 0xd4, 0x69, 0x32, 0x32, 0x1b, 0x57, 0xef, 0x72, 0x64, 0x0a, 0xdd, 0x2c, 0xee, 0xbf, 0x5b, 0xe9, 0x68, 0x43, 0x6b, 0xcd, 0x12, 0x16, 0x90, 0x78, 0x84, 0x82, 0x32, 0x93, 0xb0, 0x10, 0xec, 0x28, 0xf0, 0xd9 } +, + /* Signature */ + 129, + { 0x01, 0x60, 0x47, 0xca, 0xad, 0x6c, 0x47, 0xbf, 0x27, 0xd0, 0xcc, 0xfa, 0x03, 0x41, 0x01, 0x7e, 0x56, 0x5e, 0x02, 0x8c, 0xf2, 0x6c, 0x8e, 0x66, 0x0f, 0x79, 0xe0, 0x91, 0xf3, 0x50, 0xce, 0xb2, 0xaa, 0xcf, 0x92, 0xf7, 0xd0, 0x1d, 0x37, 0x3f, 0x71, 0x55, 0x11, 0x9c, 0x07, 0x29, 0x17, 0xf2, 0x4f, 0x01, 0xbf, 0x74, 0x7b, 0xe2, 0xdc, 0xdc, 0x41, 0xd1, 0xbe, 0x58, 0x85, 0x35, 0xc2, 0xd6, 0xac, 0x17, 0x04, 0xc5, 0xfb, 0x16, 0xf6, 0xe5, 0xdc, 0x4b, 0xbc, 0x84, 0x53, 0xf5, 0x21, 0xdb, 0x73, 0x1e, 0xba, 0x78, 0x98, 0xe6, 0xe5, 0x21, 0x2b, 0x80, 0xce, 0x9d, 0xa0, 0xf1, 0x56, 0x28, 0x18, 0x99, 0x98, 0x31, 0x35, 0x03, 0xdf, 0xd4, 0x4e, 0x3d, 0x69, 0xde, 0x9b, 0xa9, 0xcb, 0x5e, 0xb3, 0x2a, 0xc4, 0x1c, 0xb8, 0xe3, 0x62, 0x1b, 0xa1, 0xd2, 0x91, 0xd0, 0xc5, 0xda, 0x24, 0x9f, 0x15 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.15", + /* Message to be signed */ + 15, + { 0xa6, 0x42, 0xf0, 0xf7, 0x0b, 0x4b, 0xd3, 0xb5, 0x4b, 0xe2, 0x20, 0x11, 0x9a, 0x7f, 0x79 } +, + /* Signature */ + 129, + { 0x00, 0xa0, 0x33, 0x6e, 0x63, 0x67, 0x52, 0x7b, 0xbf, 0x13, 0xb0, 0xa9, 0x33, 0xb6, 0x31, 0xc7, 0x2c, 0xb3, 0x3e, 0xab, 0xbc, 0x29, 0x2a, 0x0f, 0x8f, 0x75, 0x55, 0x0c, 0x22, 0x30, 0xfe, 0x82, 0x57, 0xf2, 0xaf, 0x76, 0xd5, 0x43, 0xcc, 0xd1, 0x07, 0xdd, 0x2c, 0x87, 0x78, 0xd3, 0xac, 0x8a, 0x7b, 0x5b, 0xb4, 0xac, 0xfa, 0x57, 0xf2, 0xaf, 0x6a, 0x23, 0x14, 0x95, 0x23, 0x5a, 0x51, 0xda, 0xdd, 0xb0, 0x83, 0xe3, 0x73, 0xb7, 0x77, 0xa9, 0x5c, 0xf9, 0xc4, 0xa9, 0xb6, 0xbe, 0x77, 0x51, 0xb6, 0x5f, 0xeb, 0x62, 0x3a, 0xb3, 0x34, 0x43, 0x36, 0x54, 0xb1, 0x21, 0x0f, 0x7f, 0x78, 0x2b, 0x17, 0x25, 0xc6, 0xba, 0x4f, 0xfd, 0x20, 0xd1, 0x7e, 0xd4, 0xb6, 0xec, 0x4a, 0x3a, 0xf6, 0x4b, 0xd2, 0x73, 0x47, 0x55, 0xb7, 0x73, 0x9e, 0xeb, 0xf4, 0x18, 0xf0, 0x9d, 0x3a, 0xff, 0x28, 0x9d, 0x13 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.16", + /* Message to be signed */ + 230, + { 0xca, 0x16, 0xe4, 0x3d, 0x9c, 0x82, 0xd9, 0xd3, 0x0c, 0x8f, 0xcb, 0x40, 0x22, 0x93, 0x3c, 0xff, 0xc7, 0xd7, 0x4c, 0xaa, 0x0d, 0xf4, 0x86, 0x35, 0x09, 0x31, 0x8e, 0xda, 0xba, 0x4e, 0x0d, 0x51, 0x99, 0x77, 0x9c, 0x03, 0x50, 0x4a, 0xff, 0xa2, 0x7d, 0x87, 0x19, 0x1b, 0x6b, 0xf6, 0x86, 0xa8, 0x4d, 0x97, 0x9a, 0x2f, 0xdd, 0x5b, 0x8a, 0x4c, 0x49, 0x32, 0x14, 0x45, 0xc6, 0xf7, 0x5d, 0x25, 0x23, 0x59, 0x17, 0xad, 0xbe, 0xe2, 0xa5, 0xcf, 0xf8, 0xa9, 0x7a, 0xef, 0x78, 0xc0, 0x09, 0x22, 0x10, 0x11, 0xd8, 0x3c, 0x0f, 0x9d, 0x37, 0x16, 0x08, 0x75, 0xaf, 0x73, 0x67, 0x71, 0x8b, 0x10, 0xee, 0xc3, 0xb4, 0x29, 0x90, 0xe6, 0x43, 0xf6, 0x37, 0x07, 0xcf, 0xbb, 0x30, 0xa7, 0xfa, 0x74, 0xab, 0x16, 0xa7, 0xeb, 0xf1, 0xc8, 0x38, 0xc3, 0xb2, 0x26, 0x37, 0xb6, 0x3c, 0xcd, 0xcb, 0x6e, 0xb3, 0x4c, 0x62, 0xeb, 0xa9, 0xe9, 0x48, 0xc7, 0xac, 0x90, 0x30, 0xf0, 0x63, 0x77, 0x29, 0xd3, 0xe2, 0x78, 0x0a, 0xe6, 0xbe, 0x4d, 0x2f, 0xaf, 0x34, 0x6c, 0x11, 0x63, 0xd3, 0xf9, 0x82, 0x48, 0x19, 0x3a, 0x76, 0x39, 0x9f, 0xb7, 0x84, 0xca, 0xcf, 0x68, 0xfb, 0x33, 0xc7, 0x4b, 0xab, 0xc9, 0xdd, 0xb6, 0x27, 0x52, 0x0c, 0x0c, 0x61, 0x12, 0x34, 0x64, 0x68, 0xcf, 0x20, 0xa8, 0xe0, 0x2c, 0xc9, 0xa9, 0xbd, 0x27, 0x91, 0x0e, 0x83, 0x29, 0x7b, 0x85, 0xe8, 0x57, 0x32, 0x4a, 0x01, 0x00, 0xf5, 0xcd, 0xd5, 0x93, 0x1b, 0x6a, 0x6d, 0xe0, 0x5f, 0x94, 0x83, 0x3a, 0xa8, 0x61, 0x0a, 0x3a, 0x4b, 0x08, 0xa5, 0xa3, 0x93, 0x53 } +, + /* Signature */ + 129, + { 0x02, 0x48, 0x59, 0x23, 0x3f, 0xb9, 0xdb, 0x7c, 0xd1, 0x41, 0xf4, 0xb8, 0x77, 0x6a, 0x1d, 0x83, 0xe1, 0x03, 0xdb, 0x3a, 0xc9, 0x42, 0x89, 0xd3, 0x6e, 0xf4, 0x0f, 0x5e, 0x6e, 0x63, 0xc3, 0x12, 0x12, 0xaf, 0xdd, 0xdd, 0x16, 0x88, 0xc2, 0xc1, 0xc8, 0xd4, 0xdb, 0x04, 0x71, 0x9e, 0x1c, 0x6e, 0x8d, 0xbf, 0x7d, 0x60, 0xbe, 0x25, 0xf1, 0xd6, 0x88, 0x87, 0xfd, 0xad, 0xda, 0x3d, 0x11, 0x2e, 0x3d, 0x0d, 0x24, 0xc0, 0xcd, 0xd7, 0x98, 0x8a, 0x55, 0xc7, 0x10, 0x29, 0x40, 0x08, 0x2d, 0x1a, 0xc3, 0x1f, 0xb3, 0xef, 0xab, 0xe7, 0xc2, 0x88, 0xcb, 0x4e, 0xe7, 0x2a, 0x99, 0x2a, 0xc9, 0x6d, 0x1e, 0xdd, 0x78, 0xec, 0x72, 0x82, 0x73, 0x97, 0x0a, 0x79, 0x69, 0x95, 0xc3, 0xe2, 0xa3, 0x85, 0x81, 0xe2, 0x28, 0x03, 0x25, 0x8e, 0xb4, 0xcd, 0x9d, 0xa2, 0x04, 0x0f, 0xaf, 0x74, 0x1c, 0x54, 0x2a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.17", + /* Message to be signed */ + 162, + { 0x3b, 0xaa, 0x7e, 0x9a, 0xda, 0x21, 0x43, 0xf8, 0x48, 0x82, 0x5d, 0x22, 0x93, 0x67, 0x04, 0xd1, 0xc9, 0x97, 0xb2, 0xda, 0x76, 0x76, 0x9c, 0x98, 0x6f, 0xa1, 0x52, 0xb8, 0x98, 0xae, 0xb1, 0x1c, 0x10, 0xb9, 0x45, 0x79, 0x76, 0x4f, 0x9d, 0xc9, 0x33, 0x65, 0x2a, 0x81, 0x03, 0x67, 0x04, 0x76, 0x95, 0x8d, 0x59, 0x86, 0x7a, 0xb2, 0x4a, 0x97, 0x12, 0x84, 0x05, 0x6e, 0x99, 0xc6, 0x48, 0xb7, 0x7e, 0x7a, 0x65, 0x36, 0x44, 0x87, 0x0f, 0xe4, 0xc7, 0xce, 0xf3, 0x7f, 0x90, 0x01, 0x60, 0x48, 0x72, 0xad, 0xed, 0xe1, 0x6a, 0xac, 0xed, 0x8a, 0xa5, 0xdf, 0x42, 0x05, 0x33, 0x04, 0xe4, 0xd1, 0x71, 0x12, 0x0d, 0x7a, 0xb3, 0xce, 0x81, 0xa4, 0xd1, 0xa2, 0x74, 0x98, 0xd1, 0x38, 0x01, 0x8f, 0x66, 0x21, 0xbd, 0xfc, 0x1d, 0x53, 0xe7, 0xf3, 0xc1, 0xa5, 0xaa, 0x5d, 0x62, 0xb0, 0x9a, 0x55, 0x4a, 0x56, 0xf1, 0xed, 0x4f, 0x38, 0x5a, 0x07, 0x68, 0xea, 0xa2, 0xda, 0x0c, 0x9f, 0x56, 0x37, 0x03, 0x4c, 0x2e, 0xef, 0x58, 0xcc, 0x35, 0x17, 0x8b, 0xc2, 0xa6, 0x27, 0x2c, 0xf5, 0x29, 0xb6, 0x5a, 0xdf } +, + /* Signature */ + 129, + { 0x01, 0xe6, 0x3b, 0x86, 0xd0, 0xc1, 0x59, 0x99, 0x09, 0x3d, 0x44, 0x28, 0xaf, 0x7c, 0x6d, 0xe6, 0x48, 0x07, 0x45, 0xd8, 0x19, 0xe4, 0x29, 0x62, 0x3f, 0x47, 0x2b, 0x45, 0xde, 0x61, 0xaa, 0x56, 0x7b, 0x60, 0xd9, 0x94, 0x79, 0x2a, 0x0d, 0x11, 0x65, 0x80, 0x55, 0x98, 0xf4, 0xe2, 0x1f, 0xe6, 0x13, 0x99, 0x9a, 0x96, 0x22, 0x5d, 0x0b, 0xba, 0x98, 0xf9, 0xcf, 0xbe, 0xe8, 0x3a, 0xf5, 0x85, 0xfa, 0x07, 0x84, 0x39, 0xa7, 0x42, 0x51, 0x5a, 0xe2, 0x18, 0xec, 0x31, 0xf8, 0xd5, 0x08, 0xf2, 0x9b, 0x0e, 0x58, 0x75, 0xfc, 0xa8, 0xf0, 0x4f, 0x11, 0xa1, 0xc8, 0x2f, 0x2b, 0xb0, 0xae, 0x52, 0x8f, 0xda, 0xd3, 0xca, 0x50, 0x75, 0xbb, 0x3f, 0x41, 0xbb, 0x57, 0x83, 0x34, 0x81, 0x33, 0xfb, 0xa8, 0xa0, 0xb3, 0xad, 0x95, 0x1a, 0x1a, 0x64, 0x9c, 0xa0, 0xf9, 0x75, 0x8b, 0x20, 0xc8, 0x70, 0xfd } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.18", + /* Message to be signed */ + 184, + { 0x7e, 0xb3, 0xc9, 0x8e, 0x46, 0xfd, 0x1b, 0x5c, 0x9f, 0xf1, 0xb1, 0x1b, 0xe1, 0x61, 0x9b, 0x56, 0x60, 0x57, 0xf2, 0x6c, 0x55, 0xe2, 0x88, 0xf4, 0x84, 0x4c, 0xcd, 0x50, 0xba, 0xa9, 0x1b, 0x03, 0x8d, 0x60, 0x95, 0x83, 0x6f, 0x77, 0x1f, 0xc1, 0xc4, 0x25, 0xfb, 0x53, 0x3e, 0xf2, 0xb1, 0xdc, 0x4a, 0x3e, 0x94, 0x9b, 0xb9, 0x95, 0x25, 0xc2, 0x8f, 0xe8, 0xa3, 0xe9, 0x31, 0x78, 0xf3, 0xa0, 0xac, 0x97, 0xfd, 0x5d, 0xaa, 0x81, 0xb5, 0x92, 0x86, 0x18, 0x8e, 0x17, 0xb4, 0x4b, 0x37, 0x71, 0xbc, 0xa8, 0x55, 0xd8, 0x5f, 0x3c, 0x4d, 0x28, 0x6f, 0x10, 0x68, 0x10, 0xf4, 0xe5, 0x22, 0xea, 0x05, 0x83, 0x4f, 0x11, 0xa3, 0x1e, 0x89, 0xc3, 0x59, 0x90, 0xc5, 0x1b, 0x08, 0x0c, 0x03, 0xa6, 0x61, 0xe3, 0xd4, 0xa1, 0xb9, 0x7a, 0x2c, 0x27, 0x94, 0x0f, 0x5b, 0x2e, 0x41, 0x2b, 0x69, 0x9e, 0xa6, 0x10, 0xe8, 0x99, 0x6a, 0xe6, 0x71, 0x5a, 0xb6, 0xe2, 0x09, 0x69, 0xb6, 0xaa, 0x54, 0xcc, 0x72, 0x31, 0x9d, 0xfe, 0xe6, 0x3b, 0xd2, 0xca, 0xcf, 0xd0, 0x60, 0x8d, 0x40, 0xe2, 0xb4, 0x03, 0x95, 0xfe, 0x55, 0xdd, 0xa5, 0xbe, 0xa3, 0xb0, 0xf9, 0xb9, 0x4b, 0x5a, 0xad, 0xc0, 0x98, 0xdd, 0x56, 0x8d, 0xa3, 0x95, 0xdb, 0x2d, 0x44, 0xe4 } +, + /* Signature */ + 129, + { 0x01, 0x5c, 0xfa, 0xd9, 0x6e, 0x4b, 0x57, 0xd9, 0xcb, 0xb5, 0x78, 0xc7, 0x90, 0x74, 0xa2, 0xba, 0x86, 0x9c, 0x06, 0x02, 0x88, 0x68, 0xc5, 0xa3, 0xfc, 0xf4, 0xa5, 0xe3, 0x61, 0x83, 0x1b, 0xd8, 0xc0, 0x2c, 0x25, 0xb1, 0x2b, 0x90, 0x23, 0x4c, 0x8e, 0xa4, 0x82, 0x2f, 0xb6, 0x5e, 0x82, 0xd0, 0x91, 0xa9, 0x0f, 0x89, 0xb6, 0xc1, 0x15, 0x6e, 0x4b, 0x44, 0xd7, 0x8d, 0x32, 0xa6, 0x47, 0x37, 0xd6, 0x15, 0x87, 0xc0, 0xce, 0x3f, 0x4b, 0x34, 0x3e, 0x71, 0xf8, 0xf7, 0xa8, 0x4c, 0x6f, 0x8f, 0xc8, 0xae, 0xf8, 0xf4, 0x64, 0xc8, 0xb3, 0x59, 0xe4, 0xfb, 0x18, 0xad, 0xc6, 0x99, 0xc5, 0xa0, 0x76, 0x45, 0x37, 0x55, 0x93, 0x0c, 0x5f, 0x6f, 0xa7, 0x07, 0x1f, 0x8f, 0xec, 0xb8, 0x63, 0x1a, 0xa4, 0x14, 0xf5, 0x08, 0x35, 0x03, 0x8b, 0xe7, 0xab, 0x05, 0xa4, 0xb0, 0x50, 0xf3, 0xf5, 0x6e, 0x86 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.19", + /* Message to be signed */ + 184, + { 0x6a, 0x45, 0xee, 0x0b, 0x7e, 0xa8, 0x03, 0x68, 0xb2, 0xc4, 0x29, 0xaf, 0x28, 0x81, 0x53, 0xf4, 0x56, 0xcc, 0x66, 0x32, 0x17, 0xa8, 0xff, 0xcd, 0x2a, 0xa0, 0x5c, 0x5d, 0x32, 0x2d, 0xb7, 0x57, 0x56, 0xcd, 0xbc, 0x0f, 0x68, 0x41, 0x41, 0xfe, 0x6b, 0xca, 0xe1, 0x89, 0xbf, 0x24, 0xde, 0x1c, 0x8e, 0xdd, 0x5b, 0x11, 0x36, 0x44, 0xa4, 0x50, 0x0d, 0x0d, 0x4f, 0xf5, 0x80, 0x08, 0x36, 0x40, 0xe1, 0x2a, 0x2c, 0x95, 0xde, 0x69, 0xe9, 0x59, 0x6b, 0xfb, 0x1d, 0x44, 0x36, 0x57, 0x86, 0xe1, 0x67, 0xd0, 0x25, 0xd8, 0x9e, 0xa2, 0xf8, 0xd1, 0x3a, 0x0e, 0x64, 0x77, 0xf1, 0x3b, 0x85, 0xbb, 0xdc, 0xf1, 0x60, 0x77, 0x4b, 0x18, 0x25, 0x8c, 0xa0, 0xbe, 0xc0, 0xbd, 0x7b, 0xf1, 0x39, 0x11, 0xb3, 0x89, 0x6b, 0x48, 0x89, 0xfa, 0x3d, 0xe0, 0x4a, 0xb2, 0x6b, 0xd6, 0x82, 0xb4, 0xab, 0x43, 0x7c, 0x0c, 0x17, 0xf3, 0x53, 0xa2, 0x3a, 0x43, 0xe9, 0x2e, 0x20, 0xe7, 0xf8, 0x20, 0x69, 0x4e, 0x40, 0x3a, 0xab, 0xdd, 0x5d, 0x19, 0x6e, 0x93, 0x89, 0x5b, 0x47, 0x92, 0x55, 0xdf, 0x40, 0x30, 0xad, 0x8c, 0xe3, 0xa5, 0x3d, 0x15, 0x73, 0xbe, 0x22, 0x6d, 0x81, 0xaa, 0x18, 0xe4, 0x85, 0x89, 0x57, 0xa2, 0xd0, 0xa3, 0x35, 0x9c, 0x2e, 0x7a } +, + /* Signature */ + 129, + { 0x01, 0x64, 0xf0, 0xdb, 0xcd, 0xd9, 0x52, 0x11, 0x86, 0xa2, 0x80, 0x84, 0xa3, 0xf3, 0xae, 0x6a, 0xac, 0xb6, 0x59, 0x6b, 0x85, 0x6e, 0x8a, 0xab, 0x2e, 0x72, 0xa7, 0xf2, 0x33, 0xd6, 0x2d, 0x2d, 0x3e, 0xf1, 0x96, 0xd3, 0x78, 0x7e, 0x4b, 0x04, 0x57, 0x31, 0xda, 0x9c, 0x61, 0x50, 0xad, 0x9d, 0x5f, 0x91, 0x8c, 0x6b, 0x06, 0xc9, 0x2a, 0x11, 0xa0, 0xbf, 0xd5, 0xef, 0xcc, 0xb7, 0xb0, 0x3a, 0x01, 0x07, 0x24, 0x14, 0x39, 0xd3, 0x4d, 0x31, 0x3d, 0x35, 0xb3, 0x6a, 0x0d, 0x8c, 0xa0, 0x81, 0x3c, 0x36, 0x23, 0xb2, 0xbd, 0x78, 0xf2, 0xe3, 0xa9, 0x71, 0x99, 0x64, 0x8d, 0xa3, 0x58, 0x06, 0xff, 0xc5, 0x8e, 0xed, 0x33, 0xac, 0x9f, 0xcf, 0x79, 0x53, 0x8f, 0xa8, 0x89, 0x15, 0xb1, 0xa5, 0x75, 0x85, 0x78, 0xb9, 0xa2, 0xdb, 0x01, 0x38, 0x04, 0xbf, 0x32, 0xe7, 0xa5, 0x6d, 0xc7, 0x24, 0x37 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 8.20", + /* Message to be signed */ + 79, + { 0x92, 0xa4, 0xb4, 0xbc, 0xe3, 0xda, 0xa0, 0xa7, 0xa6, 0x4b, 0x72, 0xad, 0x87, 0x1f, 0x3a, 0xa8, 0xea, 0xb5, 0xac, 0x40, 0x11, 0xaa, 0xae, 0xa2, 0xce, 0xeb, 0xa8, 0x92, 0x77, 0xc6, 0x43, 0x29, 0x57, 0x26, 0x26, 0xc9, 0x56, 0x88, 0x4f, 0x48, 0x54, 0xf8, 0x61, 0x3d, 0x22, 0x51, 0x8b, 0x14, 0xf0, 0x38, 0xfc, 0xaf, 0x9e, 0x68, 0xe1, 0x30, 0x02, 0xfb, 0x0a, 0x00, 0xa7, 0x8c, 0xc2, 0xea, 0x51, 0x44, 0xfc, 0x13, 0x11, 0x76, 0xd5, 0xe5, 0xd6, 0x7e, 0x10, 0x6a, 0x99, 0x87, 0x9c } +, + /* Signature */ + 129, + { 0x01, 0x24, 0xfd, 0x8b, 0x2a, 0xcf, 0x22, 0x37, 0xfc, 0x71, 0xa2, 0xee, 0x97, 0xe2, 0x6a, 0x4d, 0xab, 0x7d, 0xea, 0x82, 0x9e, 0x15, 0xbe, 0xb2, 0xf8, 0xa7, 0x37, 0x91, 0xa0, 0xba, 0x15, 0x2d, 0xa5, 0xb0, 0x6a, 0xdf, 0x34, 0x1d, 0x74, 0x09, 0xe8, 0xd3, 0xd3, 0x17, 0x5b, 0x51, 0x01, 0x34, 0x32, 0x5a, 0x35, 0x32, 0x97, 0xa8, 0xd6, 0xd6, 0x6c, 0x09, 0x70, 0x03, 0x22, 0xee, 0xc5, 0xe3, 0x3f, 0x62, 0x48, 0x6a, 0x21, 0x11, 0x30, 0xd7, 0x4c, 0x70, 0xdd, 0x92, 0x5d, 0xf8, 0x60, 0x2a, 0xe3, 0xc4, 0xc6, 0xcc, 0xaf, 0x93, 0xcc, 0x9a, 0x97, 0x0d, 0x1e, 0x85, 0x32, 0x60, 0xee, 0xc6, 0x94, 0x81, 0xc5, 0xf1, 0x33, 0x7e, 0x9d, 0xd3, 0xae, 0xda, 0x88, 0xd8, 0x82, 0x99, 0xbe, 0x08, 0x09, 0x5b, 0x71, 0x5a, 0x5b, 0x21, 0x66, 0xe6, 0x17, 0xc9, 0x26, 0x72, 0x2c, 0xed, 0xd6, 0xef, 0x34 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 9: A 1027-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x05, 0xf3, 0x74, 0x34, 0x88, 0x26, 0x1c, 0x6f, 0x06, 0x25, 0xe4, 0x32, 0xfa, 0x6e, 0xb8, 0x7f, 0xb1, 0x2b, 0x26, 0x21, 0x82, 0x90, 0xbf, 0xe3, 0x96, 0xba, 0x76, 0xea, 0x42, 0x61, 0x32, 0x2f, 0x81, 0x43, 0xe4, 0xb4, 0xeb, 0xcd, 0x5d, 0x2a, 0xe1, 0x9b, 0x0f, 0x9d, 0x8d, 0xcd, 0x2f, 0xc7, 0xe6, 0x82, 0x32, 0x08, 0xa7, 0x51, 0x83, 0x3d, 0x3b, 0x4e, 0x8e, 0x38, 0x7c, 0x39, 0xf8, 0xed, 0x6b, 0xbc, 0x9f, 0xda, 0xec, 0x32, 0xd3, 0xea, 0x9a, 0xbb, 0xff, 0x57, 0x47, 0x23, 0xf3, 0xf1, 0x22, 0x99, 0x90, 0x96, 0x3e, 0xa4, 0xfd, 0x9f, 0xb5, 0x44, 0xf6, 0x42, 0x90, 0xaa, 0x2e, 0xa7, 0xda, 0x63, 0x11, 0x91, 0xa2, 0x0d, 0xbc, 0x94, 0x23, 0xb4, 0x61, 0x23, 0x3b, 0x93, 0x72, 0x49, 0xf2, 0xf4, 0xea, 0x10, 0x92, 0x8f, 0xae, 0x2a, 0x6f, 0xe6, 0x64, 0xf1, 0x2c, 0x09, 0x23, 0xed, 0x11 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x01, 0x4c, 0xc3, 0x26, 0x32, 0x52, 0xf8, 0xc4, 0xfb, 0x77, 0xcd, 0x57, 0xa1, 0x42, 0x0c, 0x04, 0xc0, 0x43, 0x27, 0x8a, 0x0c, 0x45, 0xe7, 0xd4, 0x23, 0x79, 0x49, 0x3e, 0x34, 0x0f, 0x9c, 0xf1, 0xa9, 0x6f, 0x96, 0x06, 0x3a, 0xb7, 0x59, 0xd1, 0x63, 0x04, 0x06, 0xae, 0x28, 0x6a, 0x18, 0x34, 0xb6, 0xd1, 0xdb, 0x71, 0xee, 0x72, 0x2c, 0x93, 0x74, 0x5f, 0xdd, 0x4a, 0xd3, 0x3f, 0xaa, 0x72, 0xd8, 0x93, 0x51, 0xda, 0x69, 0x1a, 0x7d, 0x0a, 0x71, 0xd2, 0xc5, 0x5c, 0x57, 0x97, 0xd2, 0xcc, 0xb3, 0xb4, 0x62, 0x62, 0x08, 0xbc, 0x5f, 0x5c, 0x84, 0xfe, 0x43, 0x2f, 0x66, 0x4d, 0xc3, 0x0e, 0xde, 0x09, 0x63, 0xe6, 0x58, 0x45, 0x2b, 0x2a, 0xd5, 0xef, 0xa4, 0x93, 0x5a, 0x12, 0x2f, 0x46, 0x1d, 0x1e, 0xab, 0x84, 0x1c, 0x8a, 0xe0, 0xe6, 0xe8, 0x2f, 0xc1, 0xfe, 0xe8, 0x5d, 0x18, 0x1c, 0xbd } +, + /* Prime 1 */ + 65, + { 0x02, 0x94, 0xea, 0x0f, 0xa3, 0x4e, 0xc3, 0x13, 0x72, 0x33, 0x44, 0x20, 0x2e, 0x85, 0xec, 0xa2, 0x4b, 0x5d, 0xf6, 0x46, 0x1a, 0x1c, 0x30, 0x08, 0x7d, 0xca, 0xb5, 0xd2, 0x53, 0x39, 0x4a, 0xf5, 0x66, 0x6f, 0x03, 0x5c, 0x33, 0x35, 0x41, 0x0d, 0x8b, 0xb9, 0x86, 0x62, 0xc9, 0x78, 0xf6, 0x1d, 0x37, 0xdb, 0x4d, 0x83, 0xf0, 0xb2, 0x4c, 0xdc, 0xb6, 0x3f, 0xca, 0xdb, 0x79, 0xc5, 0x27, 0xf5, 0xab } +, + /* Prime 2 */ + 65, + { 0x02, 0x4e, 0x19, 0x16, 0x52, 0xf1, 0x70, 0x9f, 0xf4, 0x74, 0x37, 0x40, 0x85, 0x81, 0x88, 0x8a, 0x9d, 0xa1, 0x09, 0x17, 0xc5, 0xb5, 0xab, 0xaf, 0x91, 0x46, 0x10, 0x9f, 0xda, 0xc6, 0x94, 0x76, 0x6f, 0x4c, 0x8f, 0xb0, 0x57, 0x96, 0x8e, 0x84, 0x8d, 0x99, 0x58, 0x6b, 0x05, 0xf8, 0xa0, 0x2f, 0xba, 0x6c, 0xa1, 0xeb, 0x12, 0xba, 0x08, 0xdf, 0xd4, 0x9b, 0x62, 0xc2, 0x7a, 0x8f, 0x15, 0xf4, 0x33 } +, + /* Prime exponent 1 */ + 65, + { 0x01, 0x22, 0x7f, 0x36, 0xdc, 0x6b, 0x14, 0x27, 0x89, 0xfc, 0xaa, 0xa7, 0x12, 0x8b, 0xdf, 0x14, 0xfe, 0xd7, 0x90, 0x16, 0x04, 0x07, 0xfb, 0xbc, 0xdf, 0xbd, 0xa7, 0xe9, 0x88, 0x97, 0x18, 0x31, 0x81, 0x12, 0xae, 0x81, 0x6a, 0x28, 0xb0, 0x2d, 0x4a, 0x0b, 0x03, 0xdc, 0x8b, 0xfd, 0xd4, 0xff, 0xc6, 0xbb, 0x67, 0xf8, 0xe4, 0x65, 0x1a, 0x8f, 0xb0, 0xb3, 0x9d, 0x70, 0x96, 0xb7, 0x67, 0xf6, 0xfd } +, + /* Prime exponent 2 */ + 65, + { 0x02, 0x25, 0xec, 0x05, 0x3c, 0xe8, 0xda, 0x6f, 0x86, 0xad, 0xe3, 0x6b, 0xd2, 0xbf, 0x43, 0x93, 0x02, 0x91, 0x37, 0x5b, 0x1b, 0x1a, 0x51, 0xd4, 0x7d, 0x0b, 0x11, 0xa5, 0x17, 0x8a, 0x26, 0x83, 0x34, 0xf7, 0xe1, 0x94, 0x92, 0x1b, 0xb1, 0xd7, 0x5f, 0xea, 0x7f, 0x56, 0xc5, 0xaa, 0xcd, 0x05, 0x8d, 0xb3, 0x7d, 0x36, 0x08, 0x2e, 0xac, 0xe4, 0x83, 0x4b, 0x07, 0xbf, 0x7b, 0xdd, 0xea, 0xb4, 0xb7 } +, + /* Coefficient */ + 65, + { 0x02, 0x0b, 0xd0, 0xf5, 0x15, 0x80, 0x87, 0xed, 0xe3, 0x8c, 0xb5, 0xdc, 0x66, 0xe4, 0x01, 0x0a, 0xe4, 0xe4, 0x8c, 0xc0, 0x04, 0x2e, 0x15, 0x2c, 0xd5, 0xee, 0xb0, 0x51, 0xc9, 0xec, 0x45, 0xad, 0x23, 0x40, 0x24, 0x53, 0x52, 0xc0, 0x1d, 0x94, 0xc6, 0xa5, 0x26, 0xaa, 0x5a, 0x45, 0x4c, 0xdb, 0xae, 0xac, 0x85, 0x95, 0x34, 0x9b, 0xbe, 0x6a, 0x8d, 0x55, 0x19, 0xa3, 0xc9, 0xb7, 0xd0, 0x7c, 0x3a } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 9.1", + /* Message to be signed */ + 13, + { 0x82, 0xe5, 0xc5, 0xaa, 0xe6, 0x4e, 0x60, 0x8b, 0x27, 0x50, 0x4b, 0x91, 0xdb } +, + /* Signature */ + 129, + { 0x01, 0x45, 0x82, 0xda, 0xe9, 0x35, 0xe6, 0xb2, 0xae, 0xff, 0x7d, 0x72, 0x50, 0x89, 0xda, 0xb0, 0x58, 0xc6, 0x78, 0xb2, 0xee, 0x28, 0xbc, 0xd4, 0x44, 0xa7, 0x2b, 0xdf, 0xac, 0x31, 0x46, 0x3e, 0x18, 0xe9, 0x4d, 0x7b, 0x5e, 0xcc, 0x84, 0xa4, 0x31, 0x69, 0x6a, 0x1c, 0xdd, 0x79, 0xf9, 0xc0, 0x8c, 0x33, 0xe1, 0xd4, 0xb3, 0x22, 0xdd, 0x27, 0x7b, 0x50, 0x3a, 0xe6, 0xe4, 0xf9, 0xc3, 0x15, 0x30, 0x5b, 0x43, 0x72, 0xfe, 0x45, 0xfe, 0x4a, 0x7e, 0xbb, 0xfc, 0x4a, 0xe5, 0x90, 0xfa, 0x3c, 0x52, 0x0b, 0xf8, 0x28, 0x15, 0x8f, 0x78, 0x20, 0x29, 0x9f, 0x09, 0xb1, 0x34, 0xed, 0xe1, 0x17, 0xb6, 0x72, 0xa1, 0xea, 0xc2, 0xf0, 0x50, 0xc0, 0x44, 0xb2, 0x55, 0xca, 0x8d, 0x45, 0x52, 0xd4, 0xb5, 0xf3, 0xf5, 0x7b, 0x87, 0x34, 0xdb, 0x24, 0x74, 0x50, 0x07, 0x44, 0xa5, 0x33, 0x75, 0x00, 0x5e } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 9.2", + /* Message to be signed */ + 104, + { 0x77, 0xe0, 0xfb, 0xdc, 0xd6, 0xe0, 0x49, 0x8f, 0xc5, 0x68, 0x4f, 0xf1, 0x3d, 0x4c, 0x9f, 0x5b, 0x78, 0x0e, 0x77, 0xe2, 0x46, 0x46, 0x37, 0xff, 0x66, 0xea, 0xa2, 0xd7, 0xd9, 0xc3, 0xde, 0xfb, 0x9b, 0x0e, 0x3a, 0x38, 0x37, 0x73, 0xdb, 0x97, 0xa4, 0xfb, 0x49, 0x1b, 0xeb, 0x21, 0x14, 0xfd, 0xea, 0x2c, 0x2a, 0x48, 0x0f, 0xfc, 0x21, 0x9b, 0x79, 0x6a, 0xd8, 0x05, 0xd5, 0x4f, 0xbe, 0xc1, 0x7d, 0xcb, 0x34, 0xb1, 0xda, 0x17, 0x96, 0xcb, 0x9c, 0xd5, 0xf2, 0x41, 0x6a, 0xb5, 0xe7, 0x66, 0xf8, 0xe0, 0x06, 0x91, 0x8e, 0xbe, 0xc1, 0x82, 0x29, 0x98, 0xa2, 0x8f, 0xff, 0xa6, 0x23, 0x0c, 0x07, 0x87, 0x26, 0xfb, 0xa2, 0xe4, 0xa7, 0xb0 } +, + /* Signature */ + 129, + { 0x05, 0x93, 0x27, 0xce, 0xe7, 0x26, 0xff, 0xb6, 0x03, 0xe8, 0xa9, 0xfc, 0xd5, 0x74, 0xab, 0xa9, 0xcb, 0xdf, 0xc3, 0x6c, 0x0a, 0xa6, 0x6f, 0xcf, 0xe3, 0x55, 0x5c, 0xf2, 0xef, 0x35, 0x82, 0xd3, 0x22, 0x0d, 0xf9, 0xd6, 0xbf, 0x8a, 0x78, 0xe3, 0xff, 0xf0, 0xc1, 0x29, 0xb3, 0xab, 0xb3, 0xdc, 0x71, 0x21, 0x12, 0xa2, 0x05, 0x6b, 0xca, 0x08, 0x63, 0x65, 0x54, 0xc1, 0xac, 0x57, 0xdf, 0x87, 0xf3, 0x66, 0x41, 0x52, 0x68, 0x8c, 0x6a, 0xc7, 0x2e, 0x6b, 0x88, 0xf5, 0x63, 0x7c, 0xd7, 0x3f, 0x16, 0x69, 0x89, 0xc8, 0x29, 0x09, 0xfb, 0x67, 0xbc, 0x1f, 0xa2, 0xe2, 0xd5, 0x23, 0xe5, 0x1c, 0x91, 0x8f, 0x2b, 0xbe, 0xc1, 0xd7, 0x52, 0x02, 0xaf, 0x24, 0x0a, 0x61, 0xcd, 0x2d, 0xcc, 0x55, 0x5c, 0xae, 0xae, 0x9a, 0x68, 0x57, 0x0d, 0x77, 0x81, 0x0c, 0xf1, 0xdf, 0x81, 0x23, 0xff, 0x41, 0xc0 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.3", + /* Message to be signed */ + 116, + { 0x0d, 0xfa, 0x5b, 0xaa, 0x1c, 0xdd, 0xb8, 0x34, 0x70, 0x7a, 0x5f, 0x8c, 0xc6, 0xec, 0xe5, 0x71, 0xa7, 0xa7, 0xfc, 0xa5, 0x67, 0x63, 0x62, 0xd2, 0xb2, 0x37, 0x41, 0xa9, 0x57, 0x0a, 0xe2, 0x63, 0x8f, 0x6b, 0x1c, 0x23, 0x89, 0x85, 0x36, 0x75, 0xcc, 0xc6, 0xcc, 0x1b, 0x4c, 0x6d, 0xae, 0x23, 0xcd, 0xa7, 0x1a, 0xb9, 0x6b, 0x5a, 0x2f, 0x22, 0x14, 0x57, 0x50, 0x43, 0x3e, 0x2d, 0x6b, 0xa4, 0x27, 0x6a, 0xc1, 0xff, 0x9a, 0x48, 0xaf, 0xc9, 0xf3, 0x12, 0xf4, 0x13, 0x37, 0x85, 0xca, 0x5a, 0xf3, 0x74, 0x66, 0x74, 0x31, 0x9a, 0x67, 0x57, 0xa1, 0x64, 0xe3, 0x4d, 0x14, 0x98, 0xbd, 0x55, 0x30, 0x90, 0x2e, 0x32, 0x18, 0x55, 0xe3, 0xbe, 0xd4, 0x08, 0x81, 0xf0, 0x05, 0x42, 0x25, 0x6a, 0xa2, 0x1a, 0x42, 0xfc } +, + /* Signature */ + 129, + { 0x01, 0xd1, 0x95, 0x41, 0x69, 0xaf, 0x58, 0x99, 0x3e, 0x14, 0x77, 0x2a, 0x94, 0xf1, 0x9b, 0xc4, 0x79, 0x24, 0xcc, 0xdb, 0x2e, 0x90, 0xee, 0x43, 0x36, 0xfb, 0x6e, 0x08, 0x49, 0x8a, 0xf4, 0xda, 0x26, 0x51, 0xa2, 0xb7, 0x83, 0x6c, 0x31, 0x3a, 0x57, 0xc8, 0x61, 0xb5, 0x51, 0x84, 0xec, 0x3b, 0x15, 0xfa, 0xc8, 0x14, 0x53, 0x51, 0xbe, 0xc5, 0xa7, 0x27, 0x0a, 0x3a, 0xa8, 0x69, 0x4d, 0xb4, 0xe9, 0xa9, 0x2c, 0xb9, 0x32, 0x7b, 0xb7, 0xa4, 0xf7, 0xb7, 0x0d, 0x24, 0x4e, 0xaf, 0x9e, 0xbf, 0xa9, 0xed, 0xfd, 0x4d, 0x54, 0x78, 0x2f, 0x3f, 0x97, 0x26, 0x26, 0x95, 0xb9, 0x7d, 0x41, 0x6e, 0x52, 0x7b, 0xe4, 0xea, 0x2d, 0xef, 0xfe, 0x6e, 0xb5, 0xe0, 0x6c, 0xda, 0x6f, 0x0a, 0x7e, 0x41, 0x66, 0x77, 0xac, 0x0f, 0xd6, 0xf8, 0x19, 0x5d, 0x4c, 0xe2, 0x89, 0x70, 0xd2, 0xca, 0x41, 0x1a, 0x2b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.4", + /* Message to be signed */ + 45, + { 0x16, 0x7e, 0x79, 0x56, 0x8c, 0x77, 0x36, 0x69, 0x0c, 0x3b, 0xed, 0xbb, 0xc8, 0xd4, 0x24, 0xeb, 0x53, 0x6a, 0x12, 0x85, 0x5a, 0x60, 0xcd, 0xb1, 0x0f, 0x94, 0xba, 0x11, 0x23, 0x17, 0xe9, 0x17, 0xa1, 0xb7, 0xd6, 0xfc, 0xfa, 0xa3, 0x43, 0x8d, 0x68, 0xee, 0x09, 0xfd, 0x47 } +, + /* Signature */ + 129, + { 0x02, 0x9a, 0x2b, 0x90, 0x86, 0x14, 0xed, 0x7a, 0x5f, 0xab, 0x72, 0xf2, 0xa1, 0xc8, 0xe5, 0x48, 0xb6, 0xf8, 0xb8, 0xb4, 0x5b, 0x75, 0x81, 0xfd, 0x24, 0x51, 0xfe, 0x45, 0xa6, 0x22, 0xfa, 0x0f, 0x08, 0xdd, 0x0b, 0xa2, 0xe8, 0xf3, 0xc4, 0x17, 0x20, 0x1e, 0xa0, 0x27, 0x79, 0x10, 0x18, 0x4f, 0x37, 0x6d, 0xa8, 0x03, 0xfa, 0x72, 0xc5, 0x0d, 0x39, 0xbe, 0x28, 0x82, 0x52, 0x6d, 0x1e, 0x85, 0xdf, 0x9a, 0xb1, 0x79, 0x75, 0x76, 0x4a, 0xcf, 0xb2, 0x07, 0x36, 0x6f, 0x6c, 0xd2, 0xc8, 0xb1, 0x36, 0xa9, 0x99, 0xda, 0xaf, 0x48, 0xf1, 0xc0, 0x8a, 0x9e, 0xa1, 0xf0, 0x84, 0x25, 0xc2, 0x1b, 0x65, 0x41, 0x80, 0xda, 0x4a, 0xdf, 0x10, 0x9b, 0x4b, 0xc5, 0xb8, 0x17, 0xdd, 0x67, 0xbf, 0x7d, 0xaa, 0xb4, 0xa3, 0x84, 0x03, 0x4a, 0xb4, 0xad, 0xe6, 0x94, 0x89, 0x8c, 0xfc, 0x27, 0x2a, 0xb6, 0x53 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.5", + /* Message to be signed */ + 229, + { 0x0d, 0x03, 0xf7, 0x12, 0x84, 0xf2, 0xe4, 0x83, 0x24, 0x2d, 0x92, 0x3f, 0xd1, 0xe1, 0x53, 0xbc, 0x16, 0x0f, 0x0c, 0xdc, 0x2c, 0x0b, 0x76, 0xf1, 0xbc, 0x2c, 0xf7, 0xd1, 0xbe, 0x9c, 0xcc, 0x7f, 0xaf, 0xa6, 0xaf, 0xc3, 0x90, 0x34, 0x01, 0x84, 0x09, 0xcc, 0xfd, 0x16, 0x28, 0xa7, 0x0b, 0x35, 0x83, 0x33, 0xbd, 0x96, 0xee, 0xd3, 0xad, 0xf3, 0x14, 0x2b, 0x17, 0x60, 0xbf, 0x8a, 0x9b, 0xb1, 0x9e, 0xa2, 0x47, 0x3a, 0x2e, 0xd8, 0x5c, 0x91, 0xcd, 0x5f, 0x0a, 0x5f, 0x2d, 0x46, 0x32, 0xd6, 0x17, 0x64, 0x19, 0xfa, 0x1d, 0x8c, 0xc8, 0x8b, 0x67, 0x08, 0x47, 0x77, 0x11, 0xea, 0x49, 0x58, 0xa8, 0x39, 0x01, 0xfe, 0xf2, 0x84, 0xf5, 0xa6, 0xc5, 0x02, 0x79, 0x8c, 0x8b, 0xd0, 0xa3, 0x50, 0xf2, 0xea, 0x83, 0xed, 0x18, 0x1e, 0xb9, 0x70, 0xd3, 0x0b, 0x78, 0x13, 0x4c, 0x8e, 0x1d, 0x64, 0xf0, 0xd1, 0x49, 0x5b, 0x70, 0x17, 0x24, 0x5f, 0xa6, 0x9b, 0xd5, 0x74, 0x27, 0xf7, 0x49, 0x20, 0xba, 0x0e, 0xed, 0xe9, 0xcb, 0xa3, 0x4e, 0xb2, 0x22, 0x76, 0xb0, 0xf2, 0x74, 0x13, 0xba, 0x3f, 0x0d, 0xa8, 0xeb, 0xde, 0xdb, 0x9b, 0x0c, 0x80, 0x0e, 0x44, 0x48, 0x1d, 0x01, 0xe6, 0xbb, 0xb0, 0xdf, 0xeb, 0xf9, 0xa1, 0x5e, 0xf6, 0xa7, 0x02, 0x0b, 0x2c, 0x55, 0xee, 0x02, 0x79, 0x11, 0x79, 0x6f, 0x66, 0xf4, 0x3d, 0xd8, 0x46, 0x02, 0x1f, 0x8d, 0x6f, 0x7e, 0x01, 0xbb, 0x80, 0x2b, 0xac, 0x09, 0xfd, 0xe9, 0xb9, 0x04, 0xbe, 0xcf, 0x99, 0x90, 0xe6, 0x84, 0xe6, 0x56, 0x9a, 0xca, 0xeb, 0x3c, 0xc6, 0x4d, 0xcf, 0x5d } +, + /* Signature */ + 129, + { 0x04, 0x22, 0x79, 0x1f, 0xe7, 0xb4, 0x3e, 0x1f, 0x31, 0x9a, 0xe6, 0x7d, 0x91, 0x8c, 0x59, 0x87, 0xe6, 0x39, 0x36, 0x81, 0xa1, 0x86, 0x1c, 0x1e, 0x71, 0xdd, 0x6f, 0xce, 0x19, 0x23, 0x71, 0x0d, 0xbc, 0xed, 0x43, 0x01, 0xfd, 0xcd, 0x4a, 0xad, 0x8f, 0x4f, 0xc2, 0x7d, 0xfa, 0x02, 0xa9, 0x4d, 0x91, 0xbd, 0x96, 0x20, 0x0a, 0xed, 0x8b, 0x3c, 0x5a, 0x96, 0xef, 0xee, 0x7d, 0x11, 0xaf, 0x90, 0x87, 0xfb, 0x81, 0x90, 0x5c, 0x5d, 0xf2, 0xc2, 0x4e, 0xd7, 0xed, 0x63, 0xd5, 0xfc, 0x22, 0xba, 0xbd, 0x6b, 0x9e, 0x3b, 0x57, 0xcd, 0x25, 0x41, 0x9a, 0x78, 0x17, 0xe9, 0x36, 0x16, 0xe9, 0x34, 0x54, 0xb9, 0x58, 0x53, 0xfe, 0x52, 0x04, 0xb5, 0x8c, 0x09, 0x8b, 0x46, 0xde, 0x0b, 0x3f, 0x01, 0xf5, 0x82, 0x76, 0x32, 0x48, 0xc2, 0x90, 0xb9, 0xe8, 0x09, 0x69, 0x65, 0x24, 0x42, 0xa4, 0xd8, 0xe5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.6", + /* Message to be signed */ + 222, + { 0x4a, 0xca, 0x96, 0x3f, 0x14, 0xac, 0xf6, 0xa7, 0x9c, 0x51, 0x08, 0x1e, 0xf2, 0x57, 0x16, 0x66, 0x71, 0xe3, 0xb4, 0x5f, 0xee, 0x31, 0x24, 0x07, 0xba, 0x3c, 0xf6, 0xd7, 0x11, 0xab, 0xa1, 0xae, 0x25, 0xa4, 0xa8, 0xba, 0x45, 0x48, 0x19, 0xa3, 0x91, 0x2a, 0x31, 0x2e, 0x99, 0x0f, 0x1f, 0xa7, 0x4c, 0xbc, 0xb7, 0x27, 0x77, 0xf1, 0xc7, 0xc6, 0x63, 0xa2, 0xd1, 0xcd, 0xb2, 0xc5, 0xc0, 0x07, 0x4d, 0x45, 0x16, 0xf4, 0x87, 0x17, 0xde, 0x14, 0x03, 0xe8, 0xff, 0x7d, 0x0f, 0x9d, 0xe7, 0xc7, 0xc8, 0x51, 0xf3, 0xe3, 0x51, 0x16, 0x8b, 0xa6, 0xc4, 0x14, 0xbe, 0xd5, 0xd4, 0x2b, 0xae, 0x52, 0x7b, 0x72, 0x4c, 0xeb, 0x83, 0x4d, 0x79, 0xba, 0xcf, 0x70, 0x2c, 0x56, 0xa6, 0x23, 0xc1, 0x68, 0x80, 0x87, 0xdc, 0x9d, 0xe9, 0x53, 0x8e, 0xa7, 0xc7, 0xc7, 0x61, 0xcd, 0x2f, 0xd5, 0x78, 0xf0, 0xdc, 0x3f, 0x55, 0x2f, 0xfb, 0xd4, 0xaf, 0xc7, 0xf4, 0xec, 0x71, 0x22, 0xfd, 0xec, 0x1a, 0x3a, 0x2b, 0x10, 0x4d, 0x53, 0x2d, 0xb8, 0x1c, 0xb9, 0x14, 0x18, 0x54, 0xd5, 0x7d, 0xcf, 0x54, 0xb7, 0x56, 0x01, 0xa9, 0x05, 0xfa, 0xed, 0xa6, 0x5c, 0x2a, 0x7a, 0x7b, 0xc2, 0xb0, 0x29, 0xad, 0x12, 0xdd, 0x7a, 0x6a, 0xd1, 0xb4, 0x0b, 0xe0, 0x40, 0x28, 0xb4, 0xb5, 0xb6, 0x37, 0x30, 0xef, 0x98, 0x44, 0x73, 0xf0, 0xc4, 0x82, 0x14, 0x89, 0x93, 0xc3, 0x6b, 0x44, 0xe5, 0x4b, 0xe9, 0xa5, 0xf2, 0x34, 0xe7, 0x43, 0x29, 0x2a, 0x12, 0xa3, 0x4b, 0xf2, 0xff, 0x73, 0xb7, 0xf7, 0x98 } +, + /* Signature */ + 129, + { 0x04, 0x26, 0x43, 0xc0, 0x3a, 0xda, 0x72, 0x4e, 0x2d, 0xbb, 0x19, 0xcc, 0x07, 0xad, 0x0e, 0x75, 0x22, 0x28, 0xb9, 0xd3, 0x6f, 0x65, 0x3c, 0x6a, 0x9c, 0x0c, 0x29, 0x35, 0x6c, 0xf4, 0xc3, 0xf1, 0xca, 0x19, 0x37, 0x76, 0xd5, 0xfe, 0xf4, 0x3f, 0xc5, 0x54, 0x17, 0x71, 0x66, 0x69, 0xde, 0x9a, 0xb2, 0xad, 0xdd, 0x3e, 0xa8, 0x8a, 0x90, 0xae, 0x93, 0x9a, 0x5e, 0xb1, 0x10, 0x13, 0xe2, 0x28, 0xae, 0x08, 0x16, 0xee, 0xfa, 0x4d, 0xd4, 0x2c, 0x6c, 0x08, 0xc8, 0x78, 0xbd, 0x58, 0xb4, 0x90, 0x40, 0x29, 0x6a, 0x86, 0x3b, 0xfd, 0x11, 0x28, 0x5f, 0x8b, 0xbd, 0x31, 0x5b, 0xe1, 0x6d, 0x2d, 0x65, 0xd7, 0xf5, 0xe5, 0xf2, 0x6a, 0xa9, 0x71, 0x47, 0xf9, 0x5f, 0x5e, 0xe3, 0x6f, 0x98, 0x9a, 0xa8, 0x96, 0xd7, 0xf9, 0xf1, 0xb3, 0x05, 0x1f, 0x82, 0x42, 0x44, 0xf9, 0x05, 0x96, 0x72, 0x3d, 0x11 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.7", + /* Message to be signed */ + 4, + { 0xa7, 0x5a, 0x45, 0x80 } +, + /* Signature */ + 129, + { 0x00, 0x4f, 0xe4, 0xc5, 0xd9, 0x14, 0x3c, 0x85, 0x1e, 0x46, 0x16, 0x7c, 0xc1, 0x81, 0x57, 0x5c, 0x07, 0x5e, 0x69, 0xb9, 0x81, 0xf9, 0xc1, 0x03, 0xf9, 0xd9, 0xb0, 0x11, 0xff, 0x8b, 0x29, 0xba, 0x55, 0xa4, 0x31, 0x87, 0xce, 0x87, 0x77, 0x99, 0x63, 0x17, 0xa0, 0x3c, 0x9d, 0x90, 0xaf, 0xc1, 0x89, 0x0a, 0x9a, 0xde, 0xec, 0x8e, 0xac, 0x08, 0x7f, 0x99, 0xb8, 0x15, 0xe6, 0xeb, 0x2b, 0x87, 0x1d, 0xcd, 0xdc, 0x80, 0x92, 0x24, 0x9d, 0x8f, 0x51, 0x3c, 0x6c, 0x56, 0x09, 0xfd, 0xae, 0x2c, 0xfc, 0x6b, 0xf0, 0x1f, 0xcb, 0x80, 0x25, 0xa4, 0xf7, 0x9b, 0xf1, 0x2a, 0xa8, 0xe1, 0x09, 0x82, 0x9a, 0x0b, 0xb3, 0x8a, 0x09, 0xd1, 0xa3, 0x93, 0x65, 0xe0, 0x40, 0x56, 0x52, 0xda, 0xe4, 0x51, 0xe5, 0xc3, 0x29, 0x8f, 0x47, 0x04, 0x05, 0x98, 0xec, 0xd7, 0x0e, 0x4b, 0x40, 0x33, 0x89, 0xbc, 0xd5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.8", + /* Message to be signed */ + 109, + { 0x7c, 0xfc, 0x00, 0xa6, 0x43, 0xae, 0x99, 0x79, 0x68, 0x01, 0xee, 0x3c, 0xeb, 0xe2, 0xcb, 0xb1, 0xa6, 0xbe, 0x1c, 0xac, 0x15, 0xc6, 0x48, 0xd4, 0xba, 0x33, 0x01, 0x29, 0x38, 0x71, 0xa9, 0x9f, 0x7c, 0xb1, 0x43, 0xc1, 0x28, 0xc7, 0x7f, 0x96, 0x31, 0x1f, 0xe4, 0x3a, 0x39, 0x01, 0xdf, 0x2c, 0x2a, 0x5c, 0x40, 0x4b, 0xe8, 0x31, 0x46, 0x97, 0xe0, 0x9b, 0x2e, 0x80, 0xaa, 0xc6, 0xac, 0x39, 0x97, 0x1b, 0xbe, 0x0d, 0xbc, 0x26, 0x67, 0x3f, 0x31, 0x95, 0x9f, 0x23, 0x8e, 0xaf, 0xd1, 0x50, 0x12, 0xe4, 0x96, 0x7d, 0x33, 0x55, 0x18, 0x92, 0xa3, 0xd3, 0x65, 0x1f, 0xe4, 0x46, 0x9b, 0x2d, 0xba, 0x45, 0x57, 0xdf, 0x89, 0x3a, 0xb6, 0xb9, 0x4f, 0x13, 0x25, 0xc3, 0xa1 } +, + /* Signature */ + 129, + { 0x05, 0x98, 0x5a, 0x4c, 0xce, 0xd0, 0xe8, 0xfd, 0xc5, 0x89, 0x24, 0xed, 0xba, 0x9e, 0x40, 0x0e, 0x67, 0x48, 0x21, 0x4f, 0x8d, 0x0b, 0x83, 0xaa, 0xfa, 0x20, 0x35, 0x0b, 0xbf, 0x0e, 0x68, 0x76, 0xca, 0x5a, 0x9a, 0xf3, 0x97, 0x0d, 0xd6, 0x3b, 0xe6, 0x84, 0xf9, 0x93, 0x6d, 0xb2, 0x82, 0xff, 0x8b, 0x53, 0xcf, 0x5f, 0x1b, 0xb1, 0xcb, 0xf4, 0x47, 0x33, 0x01, 0xf3, 0x72, 0xd9, 0x94, 0x8a, 0xf9, 0x39, 0x1b, 0x20, 0x02, 0xb2, 0xbe, 0x3e, 0x45, 0xff, 0x24, 0xa2, 0xd8, 0x99, 0xae, 0x8b, 0x52, 0xb6, 0x71, 0xb0, 0x4b, 0xab, 0x46, 0x01, 0x06, 0xbe, 0xdc, 0xfa, 0xc0, 0x13, 0x95, 0x9a, 0x48, 0x18, 0x95, 0x98, 0x42, 0x7f, 0xb9, 0x57, 0x15, 0x9a, 0x6d, 0x32, 0x9c, 0x19, 0xf3, 0x6c, 0xa7, 0x53, 0x81, 0xb9, 0x35, 0x0d, 0x34, 0x38, 0x9c, 0x16, 0xe1, 0x80, 0xa8, 0x51, 0xe4, 0x57, 0xcd } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.9", + /* Message to be signed */ + 206, + { 0x3d, 0x90, 0xde, 0x72, 0x35, 0x51, 0x59, 0x49, 0x24, 0x5f, 0x49, 0x03, 0x68, 0xc1, 0xf4, 0x93, 0x83, 0xe4, 0x4c, 0x1d, 0xb5, 0x1d, 0xd5, 0x38, 0x5b, 0xdf, 0xf5, 0xbd, 0x34, 0x45, 0x0e, 0x63, 0xce, 0x42, 0x15, 0x0b, 0x44, 0x1e, 0xf9, 0xeb, 0xc7, 0x29, 0xa9, 0x03, 0x34, 0x53, 0xf0, 0xa9, 0x39, 0x9f, 0xf6, 0x86, 0x1f, 0x50, 0x65, 0xb6, 0x66, 0x6d, 0xc2, 0x0b, 0x28, 0x72, 0x03, 0x42, 0x8e, 0x72, 0xbd, 0xf4, 0xcb, 0x74, 0x8a, 0xc8, 0xd4, 0xa5, 0x5f, 0x43, 0xd2, 0x23, 0x5e, 0x0a, 0xb2, 0xec, 0x2c, 0xf2, 0xb0, 0x6a, 0x01, 0x5f, 0x41, 0xe3, 0x51, 0x68, 0xac, 0x7e, 0x3c, 0x56, 0x8f, 0x2f, 0x16, 0xef, 0x57, 0x28, 0xb2, 0xbe, 0x95, 0x24, 0x91, 0x9d, 0x36, 0x76, 0xd6, 0x8f, 0x53, 0x7e, 0xfe, 0xf2, 0x9a, 0x05, 0xaf, 0x97, 0xcf, 0xed, 0x7c, 0xe9, 0xec, 0x45, 0xc1, 0x2f, 0x16, 0x5e, 0x4d, 0x7a, 0x4f, 0xe7, 0x2b, 0x99, 0xea, 0xbf, 0x83, 0x31, 0x6c, 0xdf, 0x2b, 0xd1, 0x64, 0x4b, 0x82, 0xfa, 0x13, 0xe4, 0xff, 0xc4, 0x49, 0xe7, 0x6d, 0x44, 0xc3, 0x87, 0x69, 0x63, 0x51, 0x47, 0x8b, 0x1a, 0x0f, 0x85, 0x96, 0x15, 0xda, 0x90, 0x5f, 0x20, 0xe6, 0x8b, 0x24, 0x56, 0x5c, 0x87, 0x3f, 0x83, 0x4e, 0x59, 0x34, 0x58, 0x51, 0x8a, 0xde, 0x41, 0xc1, 0x42, 0x81, 0x74, 0xda, 0x0c, 0x47, 0x66, 0x3a, 0x76, 0x00, 0xc6, 0x50, 0x25, 0x01, 0x5e, 0x09, 0xc1 } +, + /* Signature */ + 129, + { 0x00, 0x98, 0x13, 0xb2, 0xfd, 0xc5, 0x1b, 0xff, 0x88, 0xde, 0xdb, 0xec, 0xa3, 0xb1, 0x4a, 0xe5, 0x8b, 0xc7, 0xe7, 0x14, 0xc1, 0xd9, 0x2d, 0x74, 0x26, 0xe4, 0x94, 0x4e, 0xf9, 0x3e, 0xf9, 0xce, 0x6d, 0x10, 0xdc, 0x98, 0x9e, 0xaf, 0xe7, 0x34, 0x8d, 0x0a, 0x95, 0xf9, 0x9f, 0x56, 0x94, 0x8f, 0x72, 0x60, 0x2a, 0xc5, 0xe8, 0x61, 0x4f, 0x6b, 0x38, 0xe6, 0x8d, 0xa7, 0x9f, 0x48, 0xe2, 0x76, 0x8e, 0xda, 0x58, 0x64, 0xcf, 0xf2, 0x54, 0x51, 0x37, 0xf3, 0xcf, 0x4d, 0x81, 0xa5, 0xae, 0xb8, 0x9b, 0x21, 0x07, 0x26, 0x74, 0xca, 0xeb, 0xa0, 0x00, 0x71, 0x00, 0xc0, 0x7e, 0xf4, 0xdc, 0xbb, 0xd0, 0x5a, 0xfb, 0xad, 0x9e, 0x8b, 0x30, 0xd7, 0x46, 0xea, 0x36, 0x0d, 0x6c, 0xf8, 0x75, 0xd1, 0x0a, 0x67, 0xa5, 0x7f, 0x4b, 0x5d, 0xf4, 0x12, 0x1d, 0x72, 0x97, 0xa4, 0xbd, 0xce, 0x12, 0x8c, 0xb5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.10", + /* Message to be signed */ + 253, + { 0x20, 0xe6, 0xa3, 0xfe, 0x16, 0xb5, 0x21, 0xb3, 0xc1, 0xe6, 0xae, 0x99, 0x3e, 0xc6, 0xe8, 0x49, 0xa9, 0xc1, 0x1f, 0x20, 0x42, 0xa2, 0xd4, 0xce, 0x89, 0xcf, 0x0f, 0x99, 0xe1, 0xb4, 0xb9, 0x47, 0x1d, 0xa9, 0xa1, 0x73, 0x0d, 0xa8, 0x85, 0x1f, 0xc5, 0xab, 0x3c, 0x09, 0x22, 0x05, 0x5f, 0x00, 0x37, 0x58, 0xb2, 0x35, 0xc2, 0x8d, 0xe4, 0x08, 0x80, 0x66, 0x3f, 0xcd, 0x80, 0x14, 0x07, 0x18, 0x15, 0xdd, 0x06, 0x49, 0x4a, 0x54, 0x7c, 0xce, 0xc3, 0x34, 0x8e, 0x12, 0xd5, 0x38, 0xd5, 0xdf, 0xb4, 0x8f, 0x80, 0x7b, 0x59, 0xe9, 0xb7, 0xcd, 0x81, 0xf3, 0x91, 0xc0, 0x2c, 0x01, 0x6c, 0xd9, 0xc1, 0xa8, 0x4f, 0x9c, 0x59, 0x51, 0x79, 0xd8, 0xf2, 0x00, 0x24, 0x2a, 0x56, 0x68, 0x18, 0x2c, 0xf2, 0xcb, 0xa3, 0xb9, 0xfb, 0x6e, 0xad, 0x45, 0x1d, 0x6d, 0x27, 0xd9, 0xc7, 0x36, 0x15, 0x25, 0xd6, 0x88, 0xb5, 0x52, 0x33, 0xff, 0x45, 0x29, 0x1c, 0xc0, 0x74, 0x02, 0xd2, 0x92, 0xde, 0x0b, 0xe8, 0x3d, 0x16, 0x46, 0xc4, 0x3c, 0x28, 0x88, 0x1f, 0xd4, 0x55, 0x49, 0xb1, 0x4d, 0x12, 0x61, 0xb1, 0x2f, 0x12, 0x04, 0x38, 0x27, 0x6c, 0x6b, 0x3f, 0x98, 0xf5, 0x5b, 0xcf, 0x17, 0x80, 0xbc, 0x1a, 0x91, 0xeb, 0x11, 0xd0, 0x22, 0x9e, 0x1d, 0x78, 0x68, 0xd7, 0xfe, 0xe4, 0x9d, 0x6b, 0x91, 0x68, 0xe2, 0x4d, 0xe1, 0xcb, 0x4f, 0x0f, 0x22, 0xe6, 0x7c, 0xbb, 0x15, 0x69, 0x20, 0x41, 0x13, 0x02, 0x72, 0x94, 0xb3, 0x7e, 0xc7, 0xfa, 0xe5, 0x8b, 0xc6, 0x4e, 0x82, 0x5e, 0xaa, 0x4d, 0x56, 0x94, 0xd0, 0x05, 0x8f, 0x2c, 0xd4, 0xc7, 0xd2, 0x14, 0x18, 0xda, 0x3c, 0x03, 0x07, 0xfa, 0x2f, 0x04, 0x92, 0xe8, 0xb3, 0x77, 0x58, 0xd3, 0xea, 0x40, 0xa4, 0xe3, 0x0f, 0x60 } +, + /* Signature */ + 129, + { 0x01, 0xf0, 0x2b, 0x3f, 0x83, 0x91, 0x23, 0xaf, 0xf2, 0xa3, 0xf4, 0x3d, 0xa5, 0xaa, 0xa0, 0xb6, 0xbb, 0xb6, 0x0c, 0x04, 0x37, 0x82, 0xf4, 0x96, 0x2a, 0x7b, 0x9f, 0x02, 0x5c, 0x94, 0x8e, 0x34, 0x32, 0x2e, 0x98, 0xde, 0x37, 0x03, 0xe3, 0xbb, 0x45, 0xa7, 0x06, 0xa2, 0xbb, 0x05, 0x09, 0xbe, 0xd9, 0xf4, 0x10, 0x52, 0x8c, 0x88, 0x1a, 0xb9, 0xa1, 0xdc, 0x01, 0x97, 0x06, 0x8c, 0x37, 0x28, 0xc3, 0x71, 0x6d, 0x83, 0x81, 0xd9, 0xf8, 0x67, 0x80, 0xfe, 0x78, 0xa6, 0x43, 0x4b, 0x72, 0xf5, 0x1e, 0x69, 0xcd, 0x32, 0xa7, 0x21, 0x3c, 0xce, 0xa7, 0x43, 0xb3, 0x3c, 0x3c, 0x96, 0xeb, 0x00, 0x42, 0xfb, 0x98, 0xa7, 0x0c, 0x2e, 0x52, 0xfc, 0x17, 0x8a, 0xb2, 0xcb, 0x9f, 0xf8, 0xbd, 0xdd, 0xc1, 0x04, 0x6b, 0x08, 0xe0, 0x47, 0xba, 0xdd, 0xd6, 0x5a, 0x45, 0xa4, 0xe6, 0x53, 0x39, 0xd7, 0x25 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.11", + /* Message to be signed */ + 159, + { 0x6e, 0xb4, 0x9f, 0x8a, 0xbc, 0x5b, 0x49, 0x48, 0x72, 0x0a, 0x7f, 0x42, 0xf7, 0x40, 0x84, 0x78, 0x00, 0x22, 0xe0, 0xe9, 0xf9, 0xf6, 0x88, 0x86, 0xd9, 0xf3, 0x4e, 0x7f, 0x7f, 0x8a, 0xc1, 0x54, 0xdb, 0xe1, 0x9c, 0x91, 0xb8, 0xed, 0x38, 0xec, 0x03, 0x6b, 0x61, 0x42, 0x12, 0xca, 0x35, 0xf7, 0x9e, 0xd8, 0x74, 0x57, 0x9e, 0x24, 0x85, 0xda, 0xc8, 0x20, 0x5d, 0x0e, 0x56, 0xb4, 0xb4, 0xc0, 0x00, 0x0a, 0x8a, 0x75, 0xa6, 0xd4, 0x97, 0xfc, 0x51, 0x19, 0x11, 0x1a, 0x40, 0xdb, 0x51, 0x3d, 0xf6, 0x61, 0x96, 0x55, 0xb5, 0x8a, 0x11, 0x6f, 0xab, 0xee, 0x08, 0x2b, 0xfa, 0x79, 0x37, 0x3d, 0x91, 0x76, 0x56, 0x87, 0x10, 0x11, 0x24, 0x18, 0x87, 0xf4, 0x42, 0x60, 0x8b, 0xd1, 0xeb, 0x1d, 0x95, 0xd1, 0x76, 0x80, 0x65, 0xfa, 0x63, 0x32, 0x4f, 0xab, 0x27, 0x36, 0xf9, 0x22, 0x70, 0x5c, 0xf2, 0x89, 0xfd, 0xe9, 0x26, 0x74, 0x33, 0x85, 0x92, 0x07, 0xa8, 0xbc, 0xf1, 0x2d, 0x17, 0x86, 0x1c, 0xfd, 0x06, 0x2b, 0x88, 0xdf, 0x78, 0x87, 0x0d, 0x5a, 0x5e, 0x91, 0x13, 0x1b, 0x63 } +, + /* Signature */ + 129, + { 0x02, 0xa2, 0xfa, 0x32, 0x71, 0x77, 0x96, 0x71, 0x0b, 0x52, 0xb0, 0x51, 0x90, 0x6c, 0xdb, 0x98, 0x15, 0xb2, 0xd0, 0x36, 0x6c, 0x07, 0x0a, 0x78, 0xff, 0x72, 0xd4, 0x59, 0x42, 0xd7, 0xad, 0xde, 0xae, 0x7e, 0xdc, 0x73, 0xca, 0x93, 0x01, 0xf1, 0xf9, 0xfa, 0xe6, 0x8a, 0x0b, 0xd4, 0xb1, 0xdf, 0x05, 0xa9, 0xa6, 0x71, 0xf8, 0xa5, 0xb7, 0xd4, 0x5c, 0xd1, 0x1f, 0xdc, 0x0f, 0x0b, 0xa0, 0x9d, 0x25, 0xce, 0xc3, 0xb6, 0x30, 0x3d, 0x9a, 0x66, 0x6c, 0x76, 0x32, 0x64, 0x96, 0xea, 0x31, 0xae, 0x38, 0x86, 0xa0, 0xc3, 0xb7, 0xd2, 0x27, 0x62, 0xee, 0xa2, 0x78, 0x93, 0x4b, 0x96, 0xa4, 0xf9, 0x0a, 0x50, 0x1a, 0xd3, 0x08, 0x8f, 0x70, 0x2e, 0x14, 0x76, 0x3c, 0xe3, 0x38, 0x46, 0xe2, 0xfd, 0xbe, 0x6d, 0x66, 0x1c, 0xb8, 0x2e, 0x6d, 0x98, 0x9d, 0xf3, 0xc5, 0xac, 0x8f, 0xe4, 0x0a, 0x85, 0x62 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.12", + /* Message to be signed */ + 76, + { 0x45, 0xcf, 0xec, 0x13, 0x2e, 0xe5, 0x93, 0xf0, 0xc3, 0xf3, 0x81, 0x3d, 0x3c, 0xb4, 0x49, 0xe6, 0xe5, 0xe6, 0x1d, 0x13, 0xde, 0x52, 0x9a, 0xe3, 0xe7, 0x1c, 0x99, 0x8e, 0xa4, 0x56, 0x35, 0x9c, 0xe6, 0x6b, 0x82, 0x04, 0x5b, 0x7a, 0xc7, 0x97, 0xfe, 0x96, 0x98, 0x5d, 0xea, 0xbc, 0x51, 0x22, 0x53, 0x0b, 0x2e, 0x29, 0xef, 0xc9, 0x75, 0xee, 0x96, 0x03, 0xb4, 0xf9, 0x6f, 0x3f, 0xf4, 0xe5, 0x9b, 0x0e, 0x35, 0xa9, 0xad, 0x92, 0xf2, 0xb8, 0x67, 0x79, 0x4d, 0x8e } +, + /* Signature */ + 129, + { 0x03, 0x9b, 0xe4, 0x8f, 0x13, 0x3a, 0xe7, 0xf0, 0xb1, 0x9e, 0xdd, 0xb2, 0x13, 0x56, 0x09, 0x73, 0xa3, 0xe2, 0xa1, 0x14, 0x6c, 0x79, 0x42, 0xf8, 0x26, 0x4b, 0xba, 0x5a, 0xd0, 0x08, 0x69, 0x2d, 0x11, 0x38, 0x01, 0xfc, 0x27, 0x78, 0xa7, 0xe3, 0x3a, 0x9e, 0x11, 0x5e, 0xa6, 0x32, 0xe5, 0x01, 0x88, 0xc8, 0x7b, 0x69, 0xe8, 0xd4, 0xd8, 0xcc, 0xa4, 0x8a, 0xbf, 0x9f, 0x25, 0x1e, 0xfc, 0x00, 0x17, 0xb9, 0x9e, 0xde, 0xe5, 0x66, 0xdc, 0xdc, 0x0b, 0xc5, 0x8d, 0xbf, 0x6d, 0x67, 0xbf, 0x86, 0x3d, 0xb8, 0xa8, 0x9a, 0xbd, 0xf1, 0x2a, 0x77, 0xf1, 0xb7, 0x0d, 0xe4, 0x39, 0xd1, 0x76, 0xf2, 0xea, 0xad, 0xa5, 0x46, 0x4c, 0x79, 0xa5, 0x84, 0x27, 0x0c, 0xa5, 0x14, 0xf4, 0x8f, 0x1d, 0xae, 0x86, 0x78, 0xec, 0xf1, 0xac, 0x29, 0x6d, 0x07, 0xc4, 0x68, 0x98, 0xba, 0xd4, 0x1a, 0xcb, 0x19, 0x9d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.13", + /* Message to be signed */ + 26, + { 0x22, 0x51, 0x29, 0x87, 0x15, 0x7c, 0xf9, 0xb9, 0xab, 0x4e, 0x53, 0x37, 0xb0, 0x98, 0x91, 0xd6, 0x3c, 0xec, 0x37, 0x43, 0xc0, 0xf7, 0xbc, 0x9d, 0x18, 0x2e } +, + /* Signature */ + 129, + { 0x02, 0xc7, 0x75, 0x7f, 0x99, 0x93, 0xef, 0x8c, 0x6d, 0x60, 0xa3, 0xf5, 0xab, 0xed, 0xce, 0xa5, 0x35, 0xdf, 0xf5, 0x5a, 0xb9, 0xf4, 0xf6, 0x2d, 0x12, 0x54, 0xbf, 0x26, 0x1d, 0xd6, 0xa2, 0xee, 0x52, 0xda, 0x63, 0x49, 0xf4, 0x7b, 0x9b, 0x28, 0x9f, 0x1d, 0x0e, 0xa3, 0xe0, 0xff, 0x08, 0xf4, 0x55, 0xfa, 0x54, 0x85, 0x65, 0x8e, 0x42, 0x17, 0xf4, 0x40, 0xc0, 0x8b, 0x90, 0xae, 0x4c, 0x6c, 0xc2, 0x56, 0x97, 0xcb, 0x83, 0x35, 0x31, 0xdb, 0xb4, 0x74, 0x03, 0x25, 0x43, 0x10, 0x0b, 0x5f, 0x92, 0xb6, 0x78, 0x19, 0x5d, 0xdb, 0xfb, 0x1b, 0x59, 0xc5, 0x9b, 0xe7, 0xc8, 0x3d, 0xd8, 0x17, 0x45, 0xcd, 0x4e, 0x70, 0x9a, 0x0e, 0x3f, 0x79, 0x8e, 0xad, 0x5b, 0xf8, 0x66, 0x2d, 0xa6, 0x5c, 0x10, 0x57, 0xcc, 0x08, 0x2d, 0x90, 0x50, 0x50, 0xc4, 0x65, 0x95, 0x8b, 0x55, 0x5d, 0x77, 0xb8, 0xb1 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.14", + /* Message to be signed */ + 245, + { 0xae, 0x48, 0xcd, 0x83, 0xf4, 0xa1, 0xf9, 0x4e, 0x17, 0x19, 0x21, 0x96, 0x90, 0xc8, 0xc6, 0xf6, 0x73, 0x7a, 0xbd, 0x15, 0xe0, 0xd0, 0x8e, 0x7f, 0xc2, 0xea, 0x0d, 0x31, 0x5b, 0x45, 0xbe, 0xc2, 0x46, 0xe8, 0x45, 0xbf, 0x17, 0x60, 0xc8, 0x6c, 0x3f, 0x82, 0xd8, 0x4b, 0x1e, 0x9d, 0x68, 0xdc, 0xcc, 0x01, 0xd9, 0xa7, 0xd0, 0x7e, 0xcc, 0x6b, 0xfb, 0xee, 0xd8, 0x3d, 0x7a, 0xd0, 0x3a, 0x6d, 0x56, 0x6a, 0x89, 0xbc, 0x64, 0x42, 0x1e, 0x7e, 0xb4, 0x7e, 0x52, 0xc0, 0x23, 0x86, 0x58, 0xd5, 0xe4, 0xc5, 0x59, 0x7f, 0x12, 0x5a, 0xfc, 0x6c, 0x83, 0x3c, 0x63, 0xcd, 0x6f, 0x97, 0xf9, 0xdd, 0x5c, 0xce, 0x8a, 0x26, 0x38, 0x80, 0x7c, 0xe8, 0xa5, 0x83, 0xda, 0x03, 0x2b, 0xec, 0x81, 0xa3, 0x8c, 0xd2, 0x99, 0xa9, 0xc7, 0x8e, 0x82, 0x54, 0xf2, 0x88, 0x51, 0x64, 0x13, 0x52, 0x5f, 0xd9, 0x4a, 0x9e, 0x0a, 0x95, 0xc6, 0x56, 0xd7, 0x3c, 0xd5, 0x2a, 0x4d, 0xcc, 0x7d, 0xd0, 0x94, 0x7f, 0x4a, 0x00, 0x5e, 0xae, 0xdc, 0xcf, 0xd0, 0x3b, 0xb1, 0x71, 0x5c, 0x35, 0x1c, 0xf0, 0x59, 0xcd, 0x52, 0x2c, 0x7f, 0x53, 0x8c, 0x16, 0x28, 0xe7, 0x2a, 0x05, 0x64, 0x4e, 0x8f, 0xff, 0x50, 0x92, 0x6f, 0xa8, 0x68, 0x2a, 0x67, 0x53, 0x78, 0x6f, 0x2a, 0xa2, 0x61, 0x0a, 0xbf, 0xaa, 0x95, 0xbf, 0x99, 0xaf, 0x15, 0x61, 0x71, 0x51, 0xd0, 0xbd, 0x0f, 0xc4, 0x6f, 0xc3, 0xb2, 0x9c, 0xbe, 0xe1, 0xe6, 0x63, 0xb9, 0x23, 0x13, 0x6b, 0x5e, 0x19, 0x92, 0x83, 0x9f, 0x0b, 0xa5, 0x2e, 0x44, 0xfc, 0xcb, 0xd9, 0xf3, 0x20, 0xed, 0xe2, 0x0f, 0x55, 0xa4, 0x23, 0x77, 0x0e, 0x57, 0x3a, 0x9f, 0xb2, 0xb3, 0x6d, 0xc8, 0xf1, 0x84 } +, + /* Signature */ + 129, + { 0x00, 0xfb, 0xa9, 0xf6, 0xf9, 0x59, 0xb1, 0x70, 0xb0, 0x94, 0x6d, 0xcb, 0xdb, 0x98, 0xdc, 0x8e, 0x84, 0x79, 0xc6, 0x69, 0xad, 0xba, 0x6c, 0x54, 0x63, 0x6a, 0x2d, 0xc7, 0xd7, 0xf7, 0x03, 0x3d, 0x35, 0x04, 0x05, 0xd7, 0x17, 0xf2, 0xd6, 0x3d, 0xae, 0x65, 0xc2, 0x4b, 0x37, 0xdb, 0x1d, 0xc3, 0xe9, 0xf6, 0x17, 0x43, 0xaf, 0x1c, 0xe6, 0xde, 0x24, 0x67, 0xd1, 0x85, 0xae, 0xf0, 0x8d, 0x2b, 0xf8, 0x65, 0xf0, 0x75, 0xba, 0xa6, 0xa2, 0x9c, 0x58, 0x06, 0x61, 0xdc, 0xd4, 0xa4, 0x8f, 0x21, 0xff, 0x4e, 0x7b, 0x03, 0x9e, 0xef, 0x1e, 0x1e, 0x20, 0xba, 0x80, 0xcf, 0x20, 0xea, 0xb6, 0xec, 0xde, 0x60, 0xfa, 0x5d, 0x37, 0x67, 0xa3, 0x0e, 0x6a, 0xd4, 0x14, 0x47, 0x13, 0xca, 0x49, 0xfc, 0x03, 0x80, 0x99, 0xaf, 0x53, 0x6c, 0x0d, 0x5f, 0x55, 0xc4, 0xcb, 0x15, 0x33, 0x53, 0x81, 0xbe, 0xa0 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.15", + /* Message to be signed */ + 238, + { 0x2c, 0x8a, 0x00, 0x7b, 0x60, 0x30, 0x56, 0xd3, 0x31, 0x87, 0xbf, 0x52, 0xce, 0xf6, 0x16, 0x1a, 0xa5, 0xf5, 0xf5, 0x33, 0x7f, 0xc3, 0x59, 0xd4, 0x63, 0x44, 0x72, 0x1d, 0x94, 0x5f, 0xbc, 0x4d, 0x24, 0x0d, 0x30, 0x62, 0x0b, 0x29, 0x6c, 0x39, 0x77, 0xcf, 0x45, 0xc2, 0x47, 0xeb, 0x2c, 0x36, 0x39, 0x40, 0x79, 0x98, 0x3f, 0x03, 0xad, 0x82, 0x39, 0x9c, 0x4b, 0x28, 0x6c, 0x48, 0x16, 0x59, 0x10, 0xb3, 0x48, 0xb9, 0x5e, 0xf3, 0x9c, 0x43, 0xbf, 0xbe, 0xb3, 0x56, 0x6d, 0x1d, 0x1e, 0xea, 0x5a, 0x42, 0x7f, 0x4c, 0xb1, 0x68, 0x1f, 0x2a, 0x7c, 0x40, 0x1f, 0x3f, 0x0d, 0x6d, 0x9e, 0xe7, 0x99, 0x3b, 0xe5, 0xec, 0x5d, 0x34, 0xa7, 0x55, 0x41, 0xe9, 0xf8, 0xdc, 0x7c, 0x60, 0x69, 0xa8, 0x97, 0x7c, 0x9f, 0x93, 0x6e, 0xdb, 0xe4, 0x1a, 0x4e, 0xf7, 0x85, 0xa3, 0xef, 0x7b, 0xa0, 0x51, 0x89, 0x90, 0x09, 0xed, 0x61, 0x2a, 0x22, 0x8f, 0x90, 0x31, 0x67, 0xa9, 0x34, 0xee, 0xe6, 0x9b, 0x4f, 0x87, 0x36, 0xc2, 0x95, 0x11, 0xc6, 0xbd, 0xc6, 0x1e, 0xee, 0x96, 0x08, 0xa9, 0x91, 0x1b, 0xba, 0x52, 0x83, 0x9b, 0xe9, 0x9f, 0x91, 0xd2, 0xef, 0x85, 0xb8, 0xcf, 0x10, 0xc1, 0xd6, 0x35, 0x08, 0x08, 0x29, 0xba, 0x79, 0x91, 0xfe, 0x2e, 0xf8, 0x2e, 0x2b, 0xae, 0x27, 0x08, 0x14, 0x06, 0xe8, 0x9b, 0xab, 0x75, 0xc3, 0xed, 0x19, 0xe8, 0x7a, 0x4a, 0xdb, 0x72, 0xec, 0x26, 0x21, 0xf3, 0xf2, 0x58, 0x5b, 0x38, 0xcb, 0xb3, 0x6b, 0x3c, 0x0d, 0x40, 0x5f, 0xfc, 0xa7, 0xa6, 0xfb, 0x02, 0x24, 0x42, 0x07, 0x94, 0xcb, 0xd8, 0xd7, 0x83, 0x18, 0x01, 0xc8, 0x81, 0xe1, 0x65 } +, + /* Signature */ + 129, + { 0x04, 0x10, 0x47, 0xe2, 0x42, 0xb6, 0x44, 0x87, 0x41, 0xf2, 0x8a, 0x4c, 0x8b, 0x2d, 0xfe, 0xca, 0xcc, 0x0f, 0xf6, 0x61, 0x9e, 0x95, 0x6a, 0x6a, 0x6b, 0x10, 0xcd, 0xd0, 0x1e, 0xed, 0xd2, 0x01, 0xc8, 0x0e, 0x0f, 0xbf, 0x7c, 0x5b, 0xef, 0x52, 0xa7, 0xaa, 0x99, 0x00, 0xa8, 0x59, 0x39, 0x4b, 0x47, 0xe8, 0x3d, 0x08, 0xb5, 0xe1, 0xda, 0x03, 0xa3, 0x35, 0x54, 0x00, 0x0c, 0xce, 0x17, 0xc1, 0xd8, 0x62, 0x29, 0xa3, 0xa2, 0x03, 0x50, 0xd1, 0x16, 0x43, 0xa7, 0x58, 0xc1, 0x16, 0xb8, 0xfb, 0xf7, 0x26, 0x60, 0xdf, 0x4c, 0x86, 0xef, 0x8c, 0x1f, 0xc4, 0x54, 0x4c, 0x3a, 0xe1, 0xd1, 0xfc, 0x3c, 0xe9, 0xf2, 0x63, 0xf6, 0x2e, 0x80, 0x07, 0xcd, 0x7f, 0xf7, 0xea, 0x8d, 0x50, 0xa0, 0x82, 0x83, 0x89, 0xff, 0x43, 0x1f, 0xc5, 0xc5, 0x62, 0x81, 0x6d, 0x3d, 0x24, 0xb6, 0x07, 0x21, 0x1d, 0x29 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.16", + /* Message to be signed */ + 211, + { 0x7b, 0x15, 0xd1, 0xa7, 0x9c, 0x7a, 0xd2, 0xd1, 0x2f, 0x75, 0xda, 0x57, 0xd1, 0x4a, 0x8e, 0xb7, 0x1f, 0xdd, 0x4c, 0x4e, 0xff, 0x52, 0x43, 0x74, 0x1a, 0xcd, 0xe2, 0x3c, 0xe6, 0xda, 0xd3, 0x08, 0xc8, 0x1d, 0x5d, 0x58, 0x0f, 0xf9, 0xc3, 0xf8, 0x93, 0xff, 0x12, 0x4f, 0xe4, 0x58, 0xb3, 0x18, 0x84, 0xda, 0xf7, 0xfc, 0x44, 0x66, 0xd7, 0x00, 0xdc, 0x49, 0x3f, 0x1c, 0x7a, 0x7d, 0xbf, 0x62, 0x24, 0x1b, 0x17, 0xe7, 0x36, 0x23, 0xfa, 0x17, 0x81, 0x4a, 0xb4, 0xd2, 0xc9, 0x24, 0x5b, 0xe8, 0x3b, 0xb3, 0xcc, 0x5f, 0x94, 0x44, 0xb1, 0x52, 0x17, 0xb2, 0x44, 0x1f, 0x45, 0x9c, 0x00, 0xb8, 0x2e, 0x58, 0x68, 0x9a, 0x11, 0xdd, 0x5c, 0x59, 0xfa, 0x39, 0x5d, 0x1a, 0x6f, 0x9b, 0x2c, 0x25, 0xcc, 0x84, 0x99, 0x92, 0x7a, 0xb9, 0xa4, 0x98, 0x28, 0x53, 0x36, 0x52, 0xce, 0xe2, 0x32, 0x32, 0x97, 0x2d, 0x65, 0x69, 0xee, 0x56, 0x44, 0x78, 0x66, 0xf1, 0x0e, 0xba, 0xd5, 0x4e, 0xa3, 0xf0, 0x61, 0x32, 0x0c, 0x6d, 0x3f, 0xef, 0xce, 0x34, 0x55, 0x2b, 0x62, 0x66, 0x96, 0x7b, 0x05, 0x78, 0xd6, 0xc4, 0x55, 0xb9, 0xac, 0x24, 0x66, 0x36, 0x17, 0x12, 0xe7, 0xd0, 0x5b, 0xd3, 0x33, 0x2e, 0xc1, 0x30, 0xd4, 0x5c, 0x6a, 0x49, 0x76, 0x16, 0x2c, 0x79, 0x7a, 0xd1, 0x36, 0x3f, 0x49, 0x69, 0xe4, 0xae, 0x3d, 0xed, 0x6e, 0x36, 0xea, 0x2c, 0xd7, 0xfb, 0x35, 0x66, 0x09, 0xbe, 0x03, 0x1a, 0x79, 0xb2, 0x94 } +, + /* Signature */ + 129, + { 0x03, 0x02, 0x52, 0x90, 0xb4, 0x46, 0x2f, 0x9a, 0xb7, 0x9f, 0xdf, 0xaa, 0x7b, 0x1d, 0x53, 0xa4, 0xd1, 0x27, 0x96, 0xc8, 0x5a, 0xac, 0x28, 0xde, 0xac, 0x21, 0x27, 0xc8, 0x25, 0x2c, 0x2a, 0x62, 0x39, 0x5a, 0x8b, 0x81, 0x9d, 0xfc, 0xee, 0xbf, 0x68, 0xdd, 0x4d, 0xbf, 0xc8, 0x7c, 0x1c, 0xf3, 0xd0, 0x17, 0xa5, 0x3a, 0x26, 0x40, 0x92, 0x50, 0x6b, 0xb6, 0xfc, 0x95, 0x28, 0xe6, 0xf8, 0x76, 0x78, 0x73, 0x6c, 0xa5, 0x6a, 0x14, 0xa1, 0xaa, 0x26, 0x77, 0xa8, 0xb8, 0x4f, 0x5e, 0x03, 0xfa, 0x2c, 0x0c, 0xe4, 0x78, 0x5b, 0x26, 0xba, 0x92, 0xe7, 0x5f, 0xbd, 0xc1, 0x6d, 0x8d, 0x4c, 0x7f, 0xb0, 0xbc, 0x39, 0xa8, 0x8e, 0x13, 0x2e, 0x1e, 0x05, 0xad, 0x00, 0xf1, 0x2f, 0x07, 0x27, 0x06, 0x34, 0x3f, 0x5e, 0xb3, 0xda, 0xb5, 0x11, 0x2e, 0x3b, 0xbe, 0x76, 0xed, 0x0b, 0xbc, 0x7b, 0xdf, 0xcf } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.17", + /* Message to be signed */ + 104, + { 0x7a, 0x76, 0x44, 0x00, 0x1f, 0x80, 0x13, 0xc5, 0x0f, 0xd7, 0x17, 0xb2, 0x44, 0x65, 0x47, 0x7a, 0xbc, 0x34, 0xba, 0x9c, 0x1e, 0x53, 0xad, 0x76, 0x32, 0x64, 0x5a, 0x6e, 0xf7, 0xc8, 0xe6, 0x4e, 0x8e, 0xcb, 0x7b, 0xca, 0x5b, 0x4f, 0x09, 0xb5, 0x2f, 0x4d, 0xd4, 0x8f, 0x8b, 0xb3, 0xdd, 0x33, 0x8c, 0x78, 0x18, 0x2c, 0xe8, 0x6e, 0x8b, 0xfb, 0x1c, 0x68, 0xa8, 0x76, 0xf7, 0x32, 0x16, 0x63, 0x06, 0xa8, 0xea, 0x8c, 0x0d, 0x7c, 0x21, 0xff, 0x26, 0xfa, 0xaf, 0x4a, 0xb4, 0x55, 0x10, 0x36, 0x19, 0x50, 0xc7, 0x6f, 0x95, 0xc2, 0x73, 0x0b, 0x9d, 0x3e, 0x4d, 0x6d, 0x85, 0xea, 0x25, 0x58, 0x4a, 0xc9, 0x67, 0xa0, 0x2b, 0x1e, 0x0a, 0x26 } +, + /* Signature */ + 129, + { 0x03, 0xb2, 0xac, 0xcf, 0xef, 0xf0, 0x63, 0xbd, 0x17, 0x5e, 0xf8, 0xae, 0x0c, 0xb8, 0x5b, 0xdb, 0x80, 0x0d, 0xdc, 0x27, 0x77, 0x6f, 0x8d, 0x3d, 0xc7, 0xe2, 0x1d, 0x19, 0x9b, 0xb8, 0xd6, 0x5f, 0x5b, 0x24, 0x2e, 0x79, 0xd4, 0x5e, 0xcd, 0xcf, 0xf0, 0x2e, 0x80, 0x3f, 0x56, 0x81, 0xff, 0x04, 0x4a, 0x43, 0xb5, 0x5a, 0x9a, 0xac, 0xb1, 0xea, 0xf1, 0x67, 0x84, 0x83, 0x8b, 0x1d, 0x5a, 0x2b, 0x7c, 0x1a, 0x36, 0x4d, 0xc4, 0x05, 0x31, 0x1a, 0x65, 0x55, 0x05, 0x7e, 0xc7, 0x3f, 0x0a, 0x8f, 0x4e, 0x0f, 0xfc, 0xa4, 0x23, 0x02, 0x2c, 0xa6, 0xad, 0x74, 0x46, 0x9b, 0xbd, 0x55, 0x57, 0xbf, 0xa1, 0xcf, 0x4b, 0x95, 0x63, 0x6f, 0x53, 0x45, 0x37, 0xef, 0xf2, 0xfb, 0x16, 0xaf, 0x5e, 0x64, 0x71, 0x82, 0x4a, 0xfe, 0x21, 0x67, 0x91, 0x8c, 0x89, 0xad, 0xe0, 0x1d, 0x52, 0xae, 0xa7, 0x39, 0x9d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.18", + /* Message to be signed */ + 22, + { 0x12, 0xd2, 0x24, 0xfc, 0x10, 0xa0, 0xfc, 0x40, 0x95, 0x3a, 0xb6, 0xd7, 0x01, 0xc4, 0x16, 0xc3, 0xa8, 0x23, 0x77, 0x2b, 0xea, 0xfa } +, + /* Signature */ + 129, + { 0x03, 0x2c, 0xb5, 0xc8, 0xd6, 0x12, 0x90, 0xb7, 0x66, 0xe6, 0x49, 0x8a, 0xa6, 0x01, 0x49, 0x4d, 0x9f, 0x06, 0x6f, 0x27, 0xa4, 0x7a, 0x28, 0x70, 0xf3, 0x67, 0x89, 0x43, 0x29, 0x1a, 0xb2, 0x2d, 0x3c, 0x45, 0xc0, 0x76, 0xe5, 0x60, 0x81, 0x9d, 0x33, 0xf8, 0x89, 0xf8, 0xcf, 0xab, 0x2d, 0xf6, 0xc6, 0x3c, 0x0c, 0xe1, 0xed, 0x5c, 0xeb, 0x51, 0x54, 0x70, 0x77, 0xc0, 0x82, 0x78, 0x18, 0x7a, 0x82, 0x72, 0xfe, 0xc7, 0xde, 0x95, 0x54, 0xcd, 0xc9, 0x16, 0xca, 0x72, 0xf2, 0xc4, 0x51, 0x43, 0xf2, 0xcf, 0x32, 0x43, 0xc4, 0xbd, 0x20, 0x0c, 0x6e, 0x99, 0x3f, 0x0d, 0xb5, 0xb7, 0x1d, 0x4f, 0x63, 0x77, 0x1e, 0x24, 0x9b, 0x19, 0xb9, 0x97, 0xa6, 0xe5, 0xa9, 0x19, 0xca, 0x10, 0x0c, 0x90, 0xfe, 0xa6, 0xa2, 0xd4, 0xdc, 0x68, 0x81, 0xc3, 0xa0, 0xe1, 0xc1, 0x35, 0x53, 0x83, 0xcf, 0xbb, 0x4b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.19", + /* Message to be signed */ + 200, + { 0xe0, 0xd4, 0xe2, 0xa5, 0xe9, 0x8a, 0x51, 0x23, 0x7d, 0xa5, 0x08, 0x5d, 0xcf, 0x09, 0x8a, 0xe2, 0xc0, 0x5b, 0x4e, 0x16, 0x92, 0x54, 0xee, 0x6d, 0xda, 0x16, 0x21, 0x0e, 0x4a, 0x3f, 0xe8, 0x1c, 0x72, 0x56, 0xea, 0xef, 0xf2, 0x8c, 0x0c, 0x63, 0xd8, 0x54, 0xb7, 0x84, 0x1a, 0x13, 0x6c, 0x43, 0x60, 0xb2, 0x15, 0xdc, 0xa0, 0x58, 0x74, 0x8a, 0x4b, 0xfa, 0x82, 0x58, 0x68, 0x04, 0x28, 0x21, 0x99, 0x2a, 0x4e, 0xd5, 0xa7, 0xd5, 0x8f, 0x80, 0x12, 0x20, 0x75, 0x49, 0xbe, 0x8c, 0xc9, 0xce, 0xcc, 0x85, 0x01, 0xb9, 0xf8, 0x02, 0x83, 0x0f, 0x86, 0x58, 0x45, 0xce, 0x2e, 0x33, 0x9b, 0xec, 0x28, 0x05, 0x96, 0x11, 0xa1, 0xa0, 0x0b, 0x55, 0x35, 0xc3, 0xc6, 0x15, 0xe9, 0xd2, 0xa1, 0x39, 0x59, 0xf1, 0x01, 0x5c, 0x8b, 0xad, 0x2d, 0x75, 0x3a, 0x59, 0xa6, 0x14, 0x3b, 0x3a, 0x30, 0x58, 0xef, 0x72, 0x25, 0x60, 0xff, 0xe1, 0xc1, 0x84, 0x87, 0xc7, 0x41, 0xda, 0xd6, 0x1f, 0x07, 0xa1, 0x56, 0x42, 0xe7, 0x26, 0xad, 0x18, 0xa9, 0x84, 0x87, 0x5e, 0x68, 0xc6, 0x2e, 0xeb, 0xed, 0xcf, 0x94, 0x6f, 0x13, 0xb8, 0x93, 0xb2, 0x80, 0x8f, 0x78, 0xf9, 0x29, 0x48, 0x07, 0xd7, 0x74, 0x68, 0x54, 0x94, 0xe6, 0xb8, 0x90, 0x40, 0xee, 0xe6, 0xde, 0x1b, 0xa7, 0x18, 0xba, 0x2e, 0x08, 0x2c, 0x3d, 0x5e, 0xf1, 0x7c, 0x10, 0x28, 0xcd, 0x66 } +, + /* Signature */ + 129, + { 0x03, 0xe7, 0x83, 0xbb, 0x53, 0xdb, 0xb6, 0x7c, 0xf2, 0x19, 0x5f, 0xc1, 0xa5, 0x7f, 0x4b, 0x74, 0xc9, 0x82, 0x03, 0xb1, 0xf3, 0xd6, 0x15, 0xfe, 0xb9, 0x20, 0xe4, 0xab, 0xe8, 0x37, 0x58, 0x34, 0x67, 0x2f, 0x4b, 0x8f, 0x55, 0xfe, 0xf2, 0xac, 0xa8, 0xb5, 0xd4, 0x0a, 0xef, 0xe4, 0xef, 0xbd, 0xaa, 0xc3, 0xe8, 0x21, 0x08, 0xd0, 0x7f, 0x2f, 0x1c, 0xf8, 0xc0, 0xd4, 0xdf, 0xf8, 0x1b, 0x39, 0x66, 0xec, 0x69, 0xbe, 0x51, 0x17, 0xac, 0x1a, 0xa6, 0x11, 0x8e, 0x46, 0x0b, 0x92, 0xd8, 0x8f, 0xcd, 0xd9, 0x4d, 0x08, 0xeb, 0xaa, 0x53, 0x62, 0xe5, 0x9d, 0x52, 0x00, 0x4b, 0x43, 0x36, 0x95, 0x14, 0x37, 0xda, 0x0f, 0x51, 0xd6, 0x3e, 0x50, 0x56, 0x15, 0xb4, 0xb7, 0x55, 0x54, 0x08, 0x0b, 0x94, 0x89, 0x7f, 0xef, 0x29, 0x3a, 0x34, 0xc4, 0x04, 0x00, 0xc4, 0xf9, 0x9a, 0xa1, 0xde, 0xfe, 0x35 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 9.20", + /* Message to be signed */ + 111, + { 0x64, 0xb3, 0xba, 0x40, 0x98, 0x03, 0xc9, 0xb9, 0x60, 0xc1, 0xc4, 0x96, 0x2f, 0x51, 0x27, 0x1b, 0xc8, 0x9a, 0x40, 0xbd, 0x40, 0x5c, 0xe5, 0xbc, 0xdc, 0x88, 0x51, 0xd9, 0x7c, 0x9b, 0xe5, 0xe5, 0xb7, 0x46, 0x4e, 0x50, 0xd9, 0x9b, 0x6c, 0xf8, 0xad, 0xf8, 0xff, 0x83, 0x2b, 0x73, 0x7d, 0xe8, 0xb6, 0xff, 0x1a, 0xbe, 0xb8, 0x9d, 0xba, 0xe9, 0x3a, 0x90, 0x63, 0x94, 0x87, 0x80, 0x6b, 0x05, 0x96, 0xcd, 0x31, 0x68, 0x60, 0xf6, 0x8f, 0x00, 0x27, 0xa3, 0x50, 0x3e, 0x15, 0x89, 0x67, 0xaf, 0xdf, 0xf4, 0x69, 0x07, 0x68, 0x17, 0xfc, 0x7d, 0xa3, 0x22, 0x3c, 0xca, 0x1e, 0x6c, 0x48, 0x97, 0x3b, 0x57, 0x0e, 0x0b, 0xf7, 0x4b, 0xb8, 0xb3, 0x96, 0x54, 0x37, 0x2b, 0x7a, 0x1d, 0x6f } +, + /* Signature */ + 129, + { 0x00, 0xd2, 0x00, 0xeb, 0xa0, 0xb6, 0x52, 0x2a, 0xfb, 0x42, 0x0e, 0xbf, 0x16, 0x48, 0x8c, 0x53, 0x03, 0x52, 0xc4, 0x2d, 0xde, 0x81, 0xe7, 0x64, 0xc0, 0xca, 0xdb, 0x43, 0x82, 0x8c, 0xb9, 0x98, 0xd0, 0xa6, 0x0b, 0x23, 0xb5, 0xb6, 0x95, 0x8a, 0x00, 0xfc, 0x25, 0x53, 0xe2, 0x35, 0xe8, 0x57, 0x4e, 0x4d, 0x4f, 0xec, 0x9e, 0x66, 0x8d, 0xba, 0x40, 0xde, 0x66, 0x61, 0xab, 0xe1, 0x3f, 0xcb, 0x84, 0xc1, 0xad, 0x15, 0xc4, 0xb0, 0xcc, 0x0c, 0x6f, 0x4f, 0x0f, 0x83, 0x77, 0x87, 0xc4, 0x32, 0x5f, 0x04, 0x5d, 0x61, 0xee, 0x2c, 0x99, 0x72, 0xb0, 0x1f, 0x32, 0x12, 0x65, 0x4e, 0xc4, 0x26, 0x62, 0x56, 0x7f, 0xaa, 0xc4, 0x0e, 0x9c, 0x0a, 0x28, 0x15, 0x8a, 0x2a, 0x6c, 0x31, 0xf0, 0x1a, 0x84, 0x91, 0x26, 0xdf, 0x9e, 0x96, 0xcb, 0x82, 0x09, 0xbe, 0xb5, 0x81, 0xd6, 0x84, 0x6b, 0xb5, 0xab } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 10: A 1028-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x0d, 0x5f, 0xb9, 0x9f, 0xde, 0xdf, 0x42, 0x56, 0xe2, 0x8d, 0x4b, 0x41, 0xd7, 0x07, 0xfc, 0x27, 0x63, 0x3e, 0x89, 0x95, 0x15, 0xf4, 0xda, 0xbf, 0x6b, 0x46, 0x27, 0x10, 0xac, 0x11, 0x25, 0x81, 0xfa, 0x73, 0xfa, 0x83, 0x69, 0x58, 0x2c, 0x9f, 0xd4, 0x52, 0x5a, 0x70, 0x16, 0x18, 0x99, 0xdf, 0x63, 0x25, 0x84, 0x9e, 0x5c, 0x43, 0x49, 0x3e, 0x13, 0x35, 0x4e, 0x27, 0x09, 0x55, 0xa4, 0x3e, 0x38, 0x35, 0xb5, 0x99, 0x8e, 0xd4, 0x2a, 0x57, 0x5b, 0xbf, 0x68, 0x8d, 0x69, 0xec, 0x36, 0x6d, 0x2b, 0xa6, 0xf0, 0x50, 0x4c, 0x1e, 0xe1, 0x7d, 0xc5, 0x9b, 0x7e, 0xa0, 0xb4, 0x64, 0x0c, 0xbe, 0xcd, 0x8b, 0xd7, 0x96, 0x2b, 0xe8, 0x56, 0x6f, 0x0e, 0xbd, 0x65, 0x57, 0x43, 0x65, 0x6a, 0x29, 0x12, 0x85, 0xe0, 0x37, 0xbb, 0xfa, 0x86, 0x55, 0x80, 0x1b, 0xd0, 0x31, 0x4f, 0x46, 0x4c, 0x56, 0x91 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 128, + { 0xe7, 0x6f, 0x42, 0xb4, 0x74, 0x02, 0xd5, 0xe0, 0xf9, 0x64, 0x64, 0x92, 0x5a, 0xb4, 0xb3, 0xbc, 0x68, 0x94, 0x30, 0x0e, 0xe4, 0x86, 0xfb, 0x70, 0xce, 0xd4, 0x91, 0xf2, 0xd1, 0xb3, 0x67, 0x80, 0x84, 0xc1, 0xc2, 0xcb, 0x96, 0x95, 0x68, 0xa5, 0xf7, 0x7d, 0xab, 0xcd, 0x40, 0x93, 0x39, 0x37, 0xa8, 0x67, 0xf9, 0x34, 0xfb, 0x2a, 0xea, 0xae, 0x6d, 0x78, 0x67, 0x98, 0xe0, 0xd0, 0x4a, 0x10, 0x6f, 0x54, 0x5e, 0x41, 0xa9, 0xc9, 0x38, 0x33, 0xd8, 0x1f, 0xd4, 0xd7, 0x53, 0x53, 0x17, 0x9c, 0xb0, 0xbc, 0xa4, 0x5e, 0x79, 0xaa, 0xc9, 0x41, 0x34, 0x64, 0xb0, 0x36, 0x7f, 0x31, 0xac, 0x5a, 0xca, 0x56, 0x6f, 0x22, 0x14, 0xbf, 0x51, 0x46, 0xa9, 0x48, 0x4b, 0x87, 0xe4, 0x2b, 0xda, 0xc2, 0xb0, 0x1a, 0x99, 0x67, 0x03, 0x50, 0x6b, 0xe0, 0x77, 0x49, 0xaa, 0x0f, 0xbe, 0xb3, 0xb2, 0x29 } +, + /* Prime 1 */ + 65, + { 0x03, 0xff, 0xaf, 0x4a, 0x61, 0x21, 0xd7, 0x42, 0x0c, 0xfd, 0xa6, 0x4c, 0x41, 0x71, 0x2f, 0x47, 0xc8, 0xf2, 0xd0, 0xd2, 0x5b, 0x17, 0xe9, 0x5b, 0x35, 0x41, 0x42, 0x84, 0x69, 0x10, 0xaf, 0xef, 0xbd, 0xf2, 0x1e, 0x74, 0x23, 0xe8, 0xb3, 0xbe, 0x44, 0xae, 0xd9, 0xaf, 0x5e, 0x49, 0x81, 0x68, 0x5d, 0x3b, 0x9a, 0x1d, 0x59, 0xc9, 0xb9, 0x47, 0xfb, 0x9c, 0x33, 0x9c, 0x9a, 0x31, 0xe5, 0x7b, 0xd9 } +, + /* Prime 2 */ + 65, + { 0x03, 0x58, 0x31, 0xe3, 0xb9, 0x29, 0x3b, 0xcd, 0xa4, 0x51, 0xbe, 0x9d, 0xb1, 0x91, 0x97, 0x48, 0x6a, 0xa2, 0xe2, 0x2e, 0x92, 0x98, 0x65, 0x0f, 0x2b, 0x7f, 0xf4, 0x25, 0x69, 0xeb, 0xec, 0x33, 0xd2, 0x0a, 0x34, 0x98, 0x44, 0xa3, 0x3b, 0xea, 0xa0, 0x93, 0xd1, 0x43, 0x4a, 0xfb, 0x4a, 0x04, 0xa0, 0x4a, 0xed, 0xd3, 0xbb, 0xc4, 0xb3, 0x87, 0x77, 0xa5, 0x5f, 0xe6, 0x50, 0x5b, 0x8c, 0x15, 0x79 } +, + /* Prime exponent 1 */ + 65, + { 0x02, 0x8e, 0x91, 0xd5, 0xab, 0xba, 0x69, 0xdc, 0x50, 0x56, 0x38, 0xe9, 0xf5, 0xc6, 0x9c, 0x06, 0xf8, 0xd5, 0x5a, 0xf5, 0xc7, 0x4d, 0xc8, 0xe7, 0x8b, 0x6c, 0x09, 0x4e, 0x85, 0xa8, 0x27, 0xf7, 0xd2, 0xab, 0x69, 0x11, 0xb6, 0x8c, 0x6b, 0xb2, 0xb4, 0x54, 0x61, 0xd9, 0xa3, 0x1e, 0xb9, 0x62, 0xb4, 0x8b, 0x12, 0x06, 0xc6, 0x8d, 0x18, 0xae, 0x90, 0x92, 0xd6, 0xe5, 0xc2, 0x2b, 0x39, 0xa4, 0x31 } +, + /* Prime exponent 2 */ + 65, + { 0x02, 0x98, 0x04, 0xe1, 0x32, 0xfa, 0x3a, 0xaa, 0x4b, 0x15, 0x26, 0xbb, 0x50, 0x3a, 0xb4, 0xd4, 0x71, 0xf7, 0x6f, 0x69, 0x65, 0x42, 0x11, 0xa6, 0x89, 0x3b, 0x0c, 0x13, 0x74, 0x29, 0x87, 0x9f, 0xcc, 0xf7, 0x23, 0x41, 0x30, 0x82, 0x54, 0x76, 0xac, 0x20, 0xd7, 0xfb, 0xd3, 0x8c, 0x3e, 0x24, 0x86, 0x58, 0x76, 0x48, 0x6e, 0xe8, 0xa7, 0xbf, 0x99, 0x58, 0x45, 0x9e, 0xee, 0x95, 0x81, 0x78, 0x29 } +, + /* Coefficient */ + 65, + { 0x02, 0x11, 0x97, 0x5e, 0x88, 0x56, 0xd4, 0xea, 0x9d, 0x1d, 0xdf, 0x87, 0xb8, 0x7d, 0x39, 0x79, 0x2f, 0x1c, 0xf7, 0xe2, 0xf1, 0x82, 0xf4, 0xa4, 0xe6, 0x91, 0xe5, 0x00, 0x2b, 0x10, 0xa0, 0x8a, 0x46, 0xdc, 0xa1, 0xa4, 0xf4, 0x83, 0x00, 0x85, 0xd8, 0xd4, 0x0b, 0xea, 0x1d, 0xff, 0x11, 0xb0, 0xc0, 0xdf, 0x20, 0x22, 0x43, 0xeb, 0x99, 0x3e, 0x58, 0x0a, 0x94, 0x49, 0x9b, 0x9c, 0xed, 0xd2, 0xbe } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 10.1", + /* Message to be signed */ + 157, + { 0xb2, 0xd5, 0x88, 0x50, 0x9c, 0x2e, 0xac, 0xda, 0x28, 0x1e, 0x76, 0x71, 0xcb, 0xa2, 0xfc, 0xa9, 0x14, 0xef, 0x73, 0xa3, 0xae, 0xa9, 0x20, 0x20, 0x43, 0xea, 0xd6, 0xb7, 0x21, 0x25, 0xc1, 0xb0, 0xd5, 0xcc, 0x15, 0x41, 0x46, 0x20, 0xd5, 0x73, 0xd7, 0xab, 0x0b, 0x3a, 0x8a, 0xb6, 0x6a, 0x92, 0xdf, 0x87, 0x0b, 0x75, 0xb1, 0xc4, 0xd6, 0x8e, 0xa7, 0x05, 0x6b, 0xe0, 0x41, 0x9e, 0xa2, 0x53, 0xe6, 0xb0, 0x8b, 0x12, 0x9e, 0x0f, 0x64, 0xf1, 0x0a, 0xbf, 0x82, 0xe1, 0x67, 0xf8, 0xe3, 0xe9, 0x28, 0x2e, 0x7b, 0xf7, 0x1b, 0x04, 0x3b, 0xaa, 0x2b, 0xa2, 0xd8, 0x75, 0x6d, 0x46, 0xb6, 0xd3, 0x6e, 0x97, 0x34, 0x15, 0xf4, 0xf8, 0xc0, 0xeb, 0x43, 0xfc, 0x60, 0x4c, 0xed, 0x49, 0x3d, 0xc0, 0x46, 0xa2, 0x5a, 0x11, 0x9b, 0xd1, 0x58, 0x1d, 0xbb, 0x59, 0x7c, 0x3e, 0x67, 0xc2, 0xfd, 0xdc, 0x39, 0x6d, 0xf5, 0xd2, 0x3b, 0x7b, 0xa8, 0x0b, 0xd2, 0xe3, 0x12, 0x90, 0xbf, 0xc2, 0x62, 0x25, 0xe0, 0x09, 0x55, 0xa9, 0x8d, 0x91, 0x19, 0x11, 0xa3, 0x99, 0x67, 0x6f, 0xbb } +, + /* Signature */ + 129, + { 0x07, 0x9a, 0x7b, 0x91, 0x6f, 0x67, 0x41, 0x17, 0xf1, 0xd8, 0x77, 0xf4, 0x93, 0x43, 0x25, 0x68, 0x41, 0x48, 0xd5, 0xd0, 0xb0, 0xd5, 0xc2, 0xc6, 0x15, 0x6a, 0x11, 0x15, 0x9b, 0xc0, 0xbd, 0x30, 0xd0, 0xa7, 0x35, 0x34, 0xdc, 0x94, 0x45, 0xeb, 0xe2, 0x06, 0xd6, 0x07, 0x5e, 0xb4, 0xea, 0x7a, 0x7c, 0x04, 0x32, 0xbd, 0x44, 0xb8, 0x3c, 0xfa, 0xe4, 0x68, 0x5a, 0x9e, 0xb9, 0xa9, 0x7c, 0xbb, 0xfa, 0x4e, 0x82, 0xf7, 0x1d, 0xb5, 0x1a, 0xfa, 0x0d, 0x27, 0xcf, 0x27, 0xf0, 0x60, 0x9b, 0xb3, 0xf8, 0x80, 0x64, 0x13, 0x24, 0x7d, 0x5d, 0x49, 0x54, 0xf7, 0x89, 0xa1, 0x01, 0xbf, 0x39, 0x21, 0x72, 0x8b, 0x48, 0x7e, 0x85, 0xfa, 0x3f, 0xd4, 0xdc, 0xd7, 0x2d, 0x04, 0x44, 0x8e, 0x42, 0xd3, 0xec, 0x05, 0xcc, 0x47, 0x5d, 0x74, 0xcb, 0xf7, 0x65, 0xc3, 0x4e, 0x3e, 0xc1, 0x4c, 0xca, 0x50, 0x40 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 10.2", + /* Message to be signed */ + 148, + { 0xca, 0x25, 0x18, 0xa5, 0xa2, 0x24, 0xb2, 0x3d, 0x42, 0x05, 0xd8, 0xdd, 0x7e, 0xb0, 0x4c, 0xbd, 0xcd, 0x0c, 0xcb, 0x82, 0xbc, 0x87, 0x96, 0x1d, 0x85, 0x9d, 0x66, 0x00, 0xb1, 0xac, 0x3e, 0x25, 0xa9, 0x40, 0x7b, 0x6c, 0x06, 0x50, 0x27, 0xc0, 0x40, 0x81, 0xf4, 0x45, 0xa2, 0x30, 0xab, 0x93, 0x08, 0xe7, 0x55, 0xf3, 0x3a, 0x75, 0x97, 0x73, 0xbe, 0x6b, 0x96, 0x9e, 0x0e, 0xa7, 0x74, 0xaa, 0x6e, 0x33, 0x4f, 0xb6, 0x04, 0x18, 0x42, 0x75, 0xf3, 0x6a, 0x03, 0x1d, 0xae, 0xa6, 0x51, 0x86, 0x97, 0x79, 0x5b, 0xd6, 0xa7, 0xd6, 0x69, 0x7b, 0x40, 0x6d, 0xa2, 0xce, 0xce, 0x15, 0xdc, 0x11, 0x3d, 0x85, 0x44, 0x98, 0x85, 0x61, 0x13, 0x1d, 0x4f, 0xc6, 0xf6, 0xe3, 0xc5, 0x80, 0xd8, 0x06, 0x80, 0x7d, 0xf2, 0xc6, 0x85, 0x65, 0x09, 0x54, 0x2e, 0x4e, 0xd3, 0x9d, 0x34, 0x6e, 0xba, 0x15, 0x97, 0x6a, 0x8f, 0xd0, 0x1d, 0x79, 0x41, 0xb0, 0x16, 0x56, 0x06, 0xc7, 0x61, 0x76, 0x64, 0x9a, 0x16, 0x10, 0x05, 0xa0 } +, + /* Signature */ + 129, + { 0x00, 0xbe, 0xb9, 0x21, 0xce, 0x74, 0x89, 0x81, 0x9d, 0x2f, 0x85, 0xc7, 0x88, 0x39, 0xa2, 0x7d, 0x7e, 0x19, 0xea, 0x0a, 0x76, 0x4a, 0xc5, 0x31, 0x01, 0xe8, 0x6f, 0x31, 0x70, 0xa7, 0x6e, 0x31, 0x8a, 0x7e, 0xe8, 0x9b, 0x1f, 0x5e, 0x23, 0xe7, 0xe2, 0xdb, 0x96, 0x66, 0xeb, 0x43, 0x91, 0xb2, 0x79, 0x2a, 0x57, 0x67, 0xee, 0x35, 0x9b, 0x5c, 0x71, 0xe2, 0x74, 0x79, 0x10, 0xc8, 0x2c, 0x60, 0x83, 0xd6, 0xd3, 0x48, 0x29, 0xb9, 0x6f, 0xa5, 0xa2, 0xec, 0x0f, 0x62, 0xf1, 0xbc, 0xda, 0x5d, 0x78, 0xf8, 0xdc, 0x3c, 0x65, 0x0b, 0x94, 0xe3, 0x2b, 0x38, 0x60, 0xda, 0x5f, 0xc5, 0xb1, 0x7f, 0xbf, 0x68, 0x7e, 0xc0, 0x07, 0x5a, 0x9c, 0x73, 0xdc, 0x1e, 0x98, 0xd1, 0xf3, 0x6a, 0xae, 0xc4, 0x49, 0x3f, 0x78, 0x91, 0xe3, 0xab, 0x08, 0xe2, 0x04, 0x2d, 0x8b, 0x1e, 0x46, 0x2e, 0x8c, 0x4c, 0x33 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.3", + /* Message to be signed */ + 131, + { 0xd4, 0x33, 0xd1, 0x5b, 0x2d, 0x61, 0xb8, 0x6a, 0xc8, 0xec, 0x0d, 0xae, 0xba, 0x65, 0xe1, 0x1d, 0xed, 0x3c, 0x38, 0x84, 0x25, 0x25, 0xe4, 0xb7, 0xc8, 0xe4, 0x53, 0xb0, 0xf5, 0x53, 0xcb, 0x4e, 0xb8, 0x75, 0xa6, 0x9d, 0x78, 0x16, 0xf5, 0x4c, 0x87, 0x79, 0x3e, 0x3a, 0xbb, 0x79, 0xfc, 0x55, 0x11, 0x35, 0x37, 0xb4, 0x76, 0x29, 0x65, 0xcf, 0xee, 0x58, 0x6e, 0x0a, 0x17, 0x99, 0x78, 0x51, 0xe3, 0xdc, 0x9e, 0xaf, 0x6f, 0x1c, 0x9c, 0x2e, 0x98, 0xc9, 0x61, 0x3e, 0x3b, 0xbe, 0xa0, 0x13, 0xff, 0x58, 0x61, 0x6b, 0x2a, 0xb0, 0x5a, 0xb3, 0x24, 0xa9, 0xc5, 0xff, 0x4c, 0x5e, 0xfd, 0xd9, 0x90, 0xdd, 0x97, 0xd9, 0x16, 0x93, 0xc1, 0xeb, 0xd4, 0xc0, 0x9c, 0x73, 0x21, 0x16, 0xc8, 0xdf, 0xc3, 0xec, 0x51, 0x5c, 0x20, 0x53, 0x2c, 0xba, 0x7e, 0x47, 0x58, 0xc6, 0x8a, 0x69, 0xcf, 0xa0, 0xac, 0x31, 0x86 } +, + /* Signature */ + 129, + { 0x03, 0xae, 0x3b, 0xe1, 0xc7, 0x44, 0x6a, 0xd3, 0xef, 0xd8, 0xba, 0xe6, 0x1b, 0x3d, 0x32, 0xd3, 0xef, 0x15, 0x24, 0x82, 0xb1, 0xbf, 0xee, 0x31, 0x2f, 0xe9, 0xe6, 0xbe, 0xee, 0xab, 0x8c, 0xbd, 0x08, 0xf4, 0xc8, 0xf9, 0xcf, 0x06, 0x7d, 0xea, 0xb6, 0xba, 0xc7, 0xc0, 0xfe, 0xcd, 0x87, 0xbb, 0xab, 0xc7, 0xf6, 0x79, 0x8c, 0x77, 0xef, 0x1c, 0x3f, 0xd8, 0xbc, 0xa2, 0x8c, 0xf9, 0xec, 0xe6, 0x56, 0x79, 0x5f, 0x60, 0xb3, 0x78, 0x75, 0xea, 0xbe, 0xf8, 0x21, 0x53, 0xa1, 0x2b, 0xc7, 0xfd, 0xe3, 0xfb, 0xc9, 0xe5, 0xe1, 0x48, 0xf4, 0xe1, 0x6c, 0xb7, 0x2a, 0x77, 0x3d, 0x9d, 0xd0, 0x23, 0x17, 0xf7, 0x0b, 0x33, 0x91, 0x40, 0x08, 0x05, 0xe8, 0x5e, 0x7a, 0x23, 0x56, 0x7b, 0x34, 0xaa, 0x65, 0xa3, 0x5f, 0x74, 0x41, 0x70, 0xaf, 0xfc, 0xb3, 0x23, 0x37, 0x1a, 0xd2, 0xab, 0x9f, 0x1e, 0x4d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.4", + /* Message to be signed */ + 52, + { 0x7d, 0x0f, 0x5b, 0xd7, 0x90, 0x0f, 0x1e, 0x65, 0x65, 0x4e, 0x6c, 0x7e, 0xeb, 0x06, 0x4c, 0xb8, 0x28, 0xf3, 0x55, 0xd6, 0xde, 0x9b, 0xf0, 0xd3, 0x47, 0x83, 0xff, 0xcb, 0xe8, 0x0a, 0xb1, 0xb8, 0xae, 0x07, 0xb7, 0xf1, 0xe3, 0xf5, 0xa3, 0x20, 0xdd, 0x9b, 0x8b, 0x76, 0xbe, 0x0e, 0x97, 0x72, 0xde, 0x19, 0xa8, 0xd3 } +, + /* Signature */ + 129, + { 0x09, 0xe7, 0xa5, 0x30, 0x41, 0x71, 0xda, 0x63, 0x8b, 0xe7, 0x60, 0x1f, 0xbf, 0xf6, 0xe4, 0x95, 0x36, 0xf3, 0x36, 0x60, 0x82, 0x25, 0x3a, 0xbc, 0x1d, 0xb5, 0xd1, 0xb6, 0x54, 0x93, 0xda, 0x59, 0x5e, 0xc9, 0x3c, 0x37, 0xf5, 0x89, 0x0b, 0x5f, 0x47, 0x15, 0xbd, 0x5e, 0x80, 0xc0, 0xbb, 0xc5, 0xc6, 0x3b, 0x74, 0xaf, 0x2e, 0x60, 0x43, 0x91, 0x32, 0xd2, 0x52, 0x13, 0x75, 0x0b, 0xc1, 0xde, 0x30, 0x2e, 0x3e, 0x8b, 0x83, 0xda, 0xd2, 0xde, 0x0d, 0xff, 0xc4, 0xfa, 0xab, 0x40, 0x56, 0xdd, 0x7c, 0x40, 0x5e, 0x04, 0xd5, 0x94, 0x24, 0x53, 0x65, 0x9d, 0x49, 0x0f, 0x3c, 0x3d, 0xaa, 0x7d, 0x3f, 0x11, 0x70, 0x11, 0x81, 0x6b, 0x56, 0x59, 0x01, 0x04, 0xde, 0x7f, 0x9c, 0x05, 0x23, 0x73, 0xe2, 0xdd, 0xe4, 0x14, 0x49, 0x04, 0x27, 0xa5, 0x89, 0x64, 0x49, 0x3f, 0xf4, 0x5f, 0x08, 0xa6, 0xe8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.5", + /* Message to be signed */ + 14, + { 0xd9, 0x6a, 0xa0, 0x91, 0xc1, 0x60, 0xb5, 0x52, 0xb1, 0x6d, 0xf0, 0x65, 0x8f, 0xa8 } +, + /* Signature */ + 129, + { 0x0b, 0x69, 0x75, 0x4e, 0xd6, 0xd7, 0xa7, 0xd2, 0xd8, 0x5b, 0x2c, 0x7a, 0x30, 0x6c, 0x78, 0xd6, 0x3d, 0x0f, 0xfa, 0x43, 0x8f, 0x43, 0xbe, 0xec, 0x3a, 0x02, 0x86, 0xce, 0x57, 0xe7, 0xe0, 0xf8, 0x5c, 0xa4, 0x30, 0xe6, 0x39, 0x08, 0xc0, 0xfa, 0x58, 0x4b, 0xa2, 0x50, 0x5f, 0x8c, 0x94, 0x65, 0x6e, 0xc0, 0x24, 0x94, 0xbb, 0x03, 0x2f, 0x92, 0x0c, 0x4b, 0x6b, 0x8c, 0x94, 0x3e, 0x6b, 0xe9, 0x2f, 0x57, 0x8a, 0xa8, 0xcc, 0xdf, 0xaa, 0xc0, 0xa5, 0x4b, 0x8a, 0x9c, 0x0d, 0xf5, 0x48, 0x27, 0x1f, 0x89, 0x73, 0xc9, 0xff, 0xa2, 0xa2, 0x0c, 0x84, 0x76, 0x2e, 0x90, 0x17, 0xe7, 0x45, 0x2e, 0x5d, 0x74, 0xda, 0x69, 0x0f, 0x75, 0xc0, 0x99, 0xab, 0x91, 0xe2, 0xa7, 0x96, 0x3b, 0xc5, 0x37, 0xf9, 0xc2, 0x4c, 0xcc, 0x3c, 0x41, 0x8c, 0x6e, 0x98, 0x58, 0x61, 0xd9, 0x3d, 0xaa, 0xb2, 0xe6, 0x13 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.6", + /* Message to be signed */ + 215, + { 0x56, 0xf0, 0x48, 0x64, 0x5a, 0x49, 0xfa, 0x01, 0x41, 0xf4, 0xd6, 0x74, 0xaa, 0xfc, 0xf2, 0xff, 0xfa, 0x83, 0xf9, 0xb4, 0x52, 0xf1, 0xfe, 0xed, 0x43, 0x05, 0x7c, 0xac, 0x27, 0x67, 0x5e, 0xa1, 0xa1, 0x41, 0xd8, 0x7f, 0x92, 0xf9, 0xce, 0xbf, 0x6e, 0xe4, 0xf7, 0x8f, 0x8e, 0xd4, 0xc3, 0xa2, 0x9d, 0xeb, 0x72, 0x97, 0x47, 0xb4, 0xf9, 0x8e, 0x4c, 0x75, 0x90, 0xaa, 0xa8, 0xd5, 0x6d, 0xbc, 0x61, 0xd3, 0x8c, 0xb5, 0x62, 0x22, 0x26, 0xf6, 0x8e, 0x43, 0xf9, 0xc4, 0xf4, 0xc0, 0x39, 0x98, 0xae, 0xe9, 0x09, 0x34, 0x39, 0x5b, 0xc8, 0x40, 0xc8, 0x6d, 0xcc, 0x88, 0x74, 0x77, 0x6f, 0x43, 0x03, 0x9f, 0x56, 0xa8, 0x9d, 0x24, 0xbd, 0xc4, 0xb3, 0x05, 0xdf, 0x09, 0xe5, 0xca, 0x0c, 0x05, 0x12, 0xad, 0x6d, 0x15, 0x71, 0x91, 0x9a, 0x3d, 0xb3, 0xa6, 0xbd, 0x98, 0xb7, 0x82, 0x0a, 0xda, 0x08, 0x69, 0xd2, 0x25, 0xa4, 0x04, 0x02, 0x7a, 0xcb, 0x6d, 0x76, 0x7f, 0xc3, 0x14, 0xdb, 0x37, 0x7e, 0x8d, 0x1d, 0xb6, 0xef, 0x0a, 0xf2, 0x94, 0x54, 0xdb, 0x2b, 0xd4, 0xc1, 0xce, 0xe0, 0x13, 0xa5, 0x97, 0x43, 0x48, 0x6d, 0x32, 0x32, 0x95, 0x83, 0xcf, 0x80, 0x11, 0x3c, 0xda, 0xa1, 0x0e, 0x4f, 0x2c, 0xea, 0x6c, 0x4f, 0x9f, 0xc6, 0xe4, 0xe2, 0x71, 0x6e, 0xde, 0x85, 0x72, 0x7c, 0x3a, 0xfd, 0x43, 0x49, 0x46, 0x09, 0x77, 0x76, 0x30, 0xee, 0x33, 0x63, 0x7e, 0xa3, 0x5c, 0x9b, 0x4f, 0x68, 0x8e, 0x49, 0x2c, 0x3c, 0x64, 0x0d } +, + /* Signature */ + 129, + { 0x06, 0x66, 0xef, 0x71, 0xe2, 0xc8, 0xa1, 0xeb, 0x1c, 0x46, 0x40, 0x3f, 0xd2, 0x3e, 0x52, 0x18, 0x83, 0xad, 0xa1, 0xb9, 0xbc, 0x5f, 0xbd, 0x35, 0x3b, 0xbb, 0x3c, 0x3d, 0xfb, 0x57, 0x0a, 0xc1, 0xc7, 0x21, 0xfa, 0xf3, 0xf5, 0x97, 0x32, 0xf2, 0x13, 0x37, 0x73, 0x80, 0x39, 0x79, 0x48, 0x46, 0x2f, 0xd2, 0x0a, 0x3f, 0x0e, 0x5e, 0x08, 0x91, 0xa6, 0xb0, 0x7c, 0x31, 0xb3, 0x60, 0xaa, 0xa9, 0x65, 0xe2, 0xf0, 0x93, 0x0e, 0xb3, 0x41, 0xee, 0x77, 0xec, 0x43, 0x90, 0x65, 0xc0, 0xaa, 0xd9, 0x17, 0x87, 0xab, 0x6d, 0x2e, 0x6c, 0xde, 0xdd, 0xf5, 0x54, 0x81, 0x65, 0x1a, 0xeb, 0xbf, 0x9d, 0x11, 0xd5, 0x4b, 0xc1, 0x13, 0x26, 0x18, 0x3e, 0xbf, 0xf4, 0x9b, 0xd4, 0x0b, 0xdf, 0x76, 0xd7, 0xef, 0x69, 0xb6, 0x7e, 0xa3, 0x96, 0x8f, 0xa8, 0x49, 0x03, 0x2f, 0xb8, 0x24, 0xb6, 0xdd, 0x6a, 0xe3 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.7", + /* Message to be signed */ + 165, + { 0x79, 0xda, 0x89, 0xe3, 0x55, 0xd5, 0x51, 0xa0, 0xe0, 0x31, 0xf4, 0xfb, 0x71, 0xab, 0x6f, 0x41, 0x44, 0xc4, 0x76, 0x2e, 0x07, 0xd0, 0x64, 0x14, 0x33, 0xcb, 0x5e, 0xc8, 0x61, 0x34, 0x96, 0x3f, 0x7d, 0x2c, 0x4d, 0xc7, 0xbe, 0xb5, 0xc6, 0xd4, 0x61, 0x57, 0xc6, 0xc4, 0xe1, 0x4a, 0x4b, 0x9c, 0x7a, 0x2c, 0x0d, 0x46, 0x0f, 0x1f, 0xc0, 0x62, 0xea, 0x1b, 0x4f, 0x98, 0x74, 0xd5, 0xb1, 0xc2, 0x9a, 0xe2, 0xf2, 0xa5, 0xb3, 0x90, 0x62, 0xe4, 0x12, 0x12, 0xe6, 0x5c, 0x85, 0xc2, 0x8e, 0x76, 0x75, 0x89, 0x96, 0x5d, 0x17, 0x10, 0xad, 0x5b, 0xc7, 0x6f, 0xa5, 0xa6, 0x72, 0x9a, 0x06, 0xfd, 0x49, 0x6e, 0x2e, 0x09, 0x97, 0xe5, 0x73, 0x37, 0xbd, 0x51, 0x6e, 0x6b, 0xc7, 0x9b, 0xe9, 0xe0, 0x70, 0xaa, 0x7b, 0x86, 0xc2, 0xdd, 0xf1, 0x4f, 0x94, 0x98, 0x5f, 0xe1, 0x58, 0x2a, 0x29, 0x2c, 0xd1, 0x39, 0x34, 0xb3, 0xc3, 0x8d, 0xfe, 0x59, 0x77, 0xed, 0x1d, 0x9f, 0x8a, 0xd3, 0x24, 0xc0, 0xdc, 0x07, 0xe5, 0x85, 0x3c, 0x7e, 0x48, 0x90, 0xbf, 0xbd, 0xc1, 0xa0, 0x1e, 0xcd, 0x72, 0xc5, 0xff, 0x68, 0xa0, 0x2f, 0x1e } +, + /* Signature */ + 129, + { 0x0a, 0x06, 0x82, 0xf7, 0x42, 0xe7, 0x43, 0xe1, 0xc7, 0xda, 0xba, 0xac, 0x61, 0x8a, 0x78, 0x6f, 0x28, 0xed, 0x13, 0xa6, 0x58, 0x7a, 0xdf, 0xc3, 0x3c, 0x98, 0x29, 0xd7, 0x52, 0xc1, 0x3e, 0xf2, 0x7a, 0x00, 0xc7, 0xe6, 0xd4, 0x5e, 0x27, 0x17, 0x1a, 0x58, 0x41, 0x77, 0x1d, 0x78, 0x69, 0x8c, 0x6c, 0xc6, 0x67, 0x78, 0xb8, 0xc0, 0x93, 0x38, 0xe3, 0x5b, 0x9b, 0x6f, 0x59, 0xc0, 0x64, 0xce, 0xb3, 0xeb, 0x20, 0xce, 0x90, 0x9a, 0x5c, 0x6c, 0xea, 0xae, 0xbb, 0xe9, 0x3e, 0x86, 0xc7, 0xc5, 0xff, 0x4a, 0x39, 0x17, 0xf1, 0x26, 0x81, 0x96, 0x32, 0xcf, 0x96, 0xfa, 0xb1, 0xd3, 0x91, 0x73, 0xa7, 0xae, 0x7f, 0xc2, 0xff, 0x5c, 0x0f, 0xb4, 0x09, 0x05, 0x35, 0xda, 0xdb, 0x58, 0xd8, 0x7d, 0x0d, 0xa3, 0xdb, 0x32, 0xec, 0xec, 0x13, 0x71, 0x8b, 0x3a, 0xc5, 0xc3, 0x0b, 0xa8, 0x02, 0xe3, 0x8b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.8", + /* Message to be signed */ + 92, + { 0xe6, 0x9a, 0xc9, 0x43, 0x3e, 0x6c, 0x28, 0xac, 0x53, 0xf8, 0x03, 0x4a, 0x86, 0x8d, 0xa9, 0x88, 0x3e, 0x31, 0x9e, 0x82, 0xe6, 0xbc, 0x2e, 0x49, 0x45, 0x5e, 0x6e, 0x4f, 0x09, 0x8b, 0x53, 0xf2, 0x87, 0xa8, 0x58, 0xda, 0x1d, 0x87, 0x6a, 0x9a, 0x5a, 0x6a, 0x9f, 0xc1, 0x4f, 0xd2, 0x42, 0x38, 0xcd, 0x4e, 0x4b, 0x57, 0x31, 0x07, 0x7a, 0x4d, 0xbd, 0xd5, 0x03, 0x8a, 0x9b, 0xc1, 0xf5, 0xde, 0xf4, 0x3f, 0xec, 0x77, 0xf6, 0x7e, 0xb0, 0x62, 0xfa, 0xef, 0xef, 0x7d, 0x04, 0x29, 0x23, 0x8b, 0x25, 0xd0, 0x31, 0x85, 0x78, 0x96, 0x62, 0x3a, 0x3f, 0x1d, 0x37, 0xbf } +, + /* Signature */ + 129, + { 0x08, 0xa0, 0x20, 0xe4, 0x20, 0x98, 0x78, 0xf1, 0xe6, 0x37, 0xad, 0x59, 0xda, 0xaf, 0x83, 0x5d, 0xaf, 0x4c, 0xa6, 0x64, 0x84, 0x47, 0x94, 0xc1, 0xc6, 0x48, 0xf0, 0xe2, 0x23, 0x3d, 0xba, 0x75, 0x48, 0xbd, 0x16, 0x1f, 0x0c, 0x0a, 0x18, 0x24, 0xd7, 0x62, 0x03, 0x1a, 0x41, 0x75, 0x72, 0x84, 0x2f, 0x8e, 0x64, 0x4a, 0xa9, 0x3f, 0x9d, 0x91, 0xdd, 0x77, 0x09, 0xe1, 0x6a, 0x42, 0x9c, 0xc1, 0x43, 0x90, 0x3e, 0xf4, 0xf8, 0x37, 0xa4, 0x58, 0x39, 0x6b, 0xca, 0xc2, 0x40, 0x92, 0xb0, 0x17, 0x24, 0xc6, 0xfe, 0x3d, 0xd1, 0xad, 0x24, 0x3f, 0x3f, 0x70, 0xb5, 0xae, 0x6f, 0xaa, 0x09, 0xf3, 0x70, 0xca, 0xa5, 0x12, 0x10, 0x4b, 0x91, 0x76, 0x06, 0x0d, 0xf2, 0xbf, 0x12, 0x1c, 0xbc, 0xe9, 0x19, 0x8e, 0xc2, 0xfe, 0x45, 0xa5, 0x9e, 0xbd, 0xdc, 0x46, 0x75, 0x32, 0xb5, 0xaf, 0xb9, 0xb2, 0x35 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.9", + /* Message to be signed */ + 152, + { 0x45, 0xe0, 0x90, 0x56, 0xa2, 0x8e, 0x4b, 0x2e, 0x7c, 0x11, 0xf6, 0x5e, 0x68, 0x8a, 0x1e, 0x3c, 0x33, 0xf0, 0xe5, 0x2c, 0x9a, 0x03, 0x6c, 0x09, 0xd8, 0x1d, 0xe5, 0xa6, 0xda, 0xb5, 0x8d, 0x4d, 0x55, 0xcf, 0x41, 0x1b, 0x53, 0xad, 0x64, 0x6e, 0x83, 0xa3, 0x4b, 0x0c, 0x08, 0xc2, 0x21, 0xae, 0x03, 0x76, 0xab, 0x76, 0xa7, 0x9d, 0x1f, 0xee, 0x67, 0x1a, 0x58, 0x44, 0x20, 0x56, 0x4f, 0x8e, 0x85, 0x2e, 0xb6, 0xf2, 0xd4, 0x27, 0xae, 0xe0, 0xa0, 0x96, 0xdd, 0x72, 0xdb, 0xe8, 0x50, 0x7c, 0x67, 0x7f, 0x8a, 0xa0, 0x0e, 0xb7, 0xc2, 0x5d, 0xfb, 0x0a, 0x49, 0xdd, 0x88, 0xa6, 0xc7, 0x84, 0x76, 0xb8, 0x00, 0x11, 0xb6, 0x82, 0x8b, 0x3a, 0xaf, 0x46, 0x47, 0x79, 0x44, 0x22, 0xba, 0x6b, 0xd6, 0x3b, 0x7a, 0xb0, 0xe7, 0xda, 0xfb, 0xd3, 0x6f, 0x6c, 0x41, 0xde, 0xa0, 0x3d, 0x73, 0x22, 0x35, 0x64, 0x96, 0x94, 0x60, 0xd9, 0x28, 0x54, 0x0b, 0x73, 0x92, 0x57, 0xe7, 0x0b, 0xb6, 0x8d, 0x5c, 0x65, 0x3c, 0x37, 0x96, 0x94, 0x58, 0x95 } +, + /* Signature */ + 129, + { 0x08, 0x71, 0x7d, 0x50, 0x86, 0xa6, 0x45, 0x3b, 0xde, 0xff, 0x77, 0xd4, 0xc2, 0xb8, 0x56, 0xe3, 0xba, 0x99, 0x0b, 0xab, 0xf6, 0x97, 0x01, 0xdf, 0x6c, 0xa0, 0xa3, 0xb3, 0xa8, 0x1b, 0x55, 0x69, 0x7d, 0x31, 0x88, 0x9d, 0x10, 0x0d, 0x68, 0x95, 0xc9, 0x7f, 0x0a, 0x56, 0xb4, 0x71, 0x68, 0xc9, 0x8d, 0xa6, 0x2e, 0x59, 0xec, 0x79, 0xd7, 0xae, 0xab, 0x2f, 0x9a, 0x57, 0x07, 0x46, 0x98, 0x8a, 0x26, 0xf4, 0x23, 0x57, 0x6c, 0x70, 0x3f, 0xd8, 0x41, 0xae, 0x51, 0xc9, 0xc2, 0x29, 0xa2, 0xe9, 0xc2, 0x5f, 0xe9, 0x4c, 0x5b, 0x6c, 0xe2, 0xfa, 0x64, 0x54, 0x12, 0xbe, 0xe6, 0x59, 0xfa, 0xf6, 0x09, 0xa3, 0x2e, 0xb2, 0xc0, 0x5b, 0xee, 0xab, 0xaa, 0x4f, 0x58, 0xca, 0xac, 0x31, 0x33, 0xe5, 0xea, 0xaa, 0x27, 0x34, 0x4d, 0x30, 0xee, 0xca, 0x22, 0xc6, 0xeb, 0xd8, 0xd9, 0xe3, 0x44, 0x41, 0x0e } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.10", + /* Message to be signed */ + 141, + { 0xb8, 0x1c, 0x8b, 0xc4, 0xac, 0x1f, 0xd9, 0x71, 0xb2, 0x1f, 0x02, 0x7e, 0x06, 0xf4, 0xd8, 0x7b, 0x34, 0xd5, 0x76, 0x9d, 0x23, 0xc8, 0x59, 0x9d, 0x1f, 0x15, 0x7b, 0x08, 0xa7, 0xf9, 0x2e, 0x34, 0x19, 0xfe, 0xc4, 0xc8, 0xc1, 0xb3, 0x4c, 0xa4, 0x63, 0xc7, 0x68, 0xb7, 0x2e, 0x07, 0xf9, 0xda, 0xbc, 0x3c, 0xbb, 0xdd, 0x8b, 0x56, 0x17, 0xcc, 0x25, 0x28, 0x75, 0x00, 0x2a, 0x1a, 0x13, 0x92, 0xaf, 0x0f, 0xaf, 0xc0, 0x8c, 0x72, 0x11, 0x75, 0x8f, 0x3c, 0x04, 0x20, 0x50, 0xad, 0x73, 0x1b, 0x63, 0x6c, 0x0e, 0x83, 0x19, 0x1a, 0x79, 0xde, 0x5a, 0xa2, 0xcb, 0x94, 0xdc, 0x8b, 0x0b, 0xdd, 0xe7, 0x5d, 0xb7, 0xd0, 0xc8, 0xba, 0xfb, 0x42, 0x23, 0xd3, 0x47, 0xb0, 0x24, 0xb3, 0xd9, 0xc6, 0xb2, 0x39, 0x61, 0x9b, 0x5d, 0x8b, 0x63, 0x46, 0xea, 0x86, 0xfb, 0x8f, 0x24, 0xc5, 0x84, 0xdc, 0x1a, 0x47, 0x79, 0x1c, 0xb7, 0xc8, 0xc7, 0xeb, 0xf1, 0xed, 0x43, 0x8b, 0x88 } +, + /* Signature */ + 129, + { 0x01, 0xb9, 0xf4, 0x33, 0x94, 0xc7, 0xcb, 0x88, 0x5b, 0xfd, 0xcc, 0x3c, 0x84, 0x96, 0x22, 0x23, 0xe8, 0xaa, 0xa9, 0x4c, 0x6c, 0x9b, 0x79, 0x05, 0x40, 0x1d, 0x24, 0xf0, 0xdc, 0x44, 0x3b, 0x2e, 0x8d, 0x84, 0x0e, 0x28, 0xa9, 0x5f, 0xa2, 0x2e, 0x1a, 0xe3, 0x6f, 0xfe, 0x08, 0x96, 0x6f, 0x38, 0xd3, 0x87, 0x14, 0xcf, 0x68, 0xda, 0x8d, 0xb2, 0x37, 0x64, 0xb8, 0x8c, 0x4b, 0xb2, 0xbe, 0x4f, 0xd3, 0xda, 0x9c, 0xcd, 0x1b, 0x50, 0x69, 0x42, 0xaa, 0x9d, 0x73, 0xfc, 0x09, 0x38, 0x2d, 0xc3, 0x30, 0x83, 0x14, 0x70, 0x6e, 0x6c, 0xe2, 0x7f, 0x00, 0x76, 0x1f, 0x3c, 0x9b, 0xd5, 0x4f, 0xa0, 0xe3, 0x1c, 0x96, 0x71, 0x9a, 0xfb, 0xf0, 0x76, 0x3e, 0x35, 0xca, 0xd8, 0x89, 0xb7, 0x2e, 0x13, 0xbd, 0x12, 0xb7, 0x6d, 0x6f, 0x20, 0x20, 0xfa, 0xf6, 0x1d, 0xd3, 0xd7, 0x08, 0x22, 0x8d, 0xf0, 0x6d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.11", + /* Message to be signed */ + 31, + { 0xd0, 0x32, 0x28, 0x83, 0xe5, 0x98, 0x16, 0x3d, 0x72, 0x20, 0x36, 0xda, 0x3e, 0x63, 0x2a, 0xa6, 0x55, 0x97, 0xac, 0xbc, 0xd1, 0xf4, 0x76, 0x03, 0x10, 0x96, 0x96, 0xf9, 0xb3, 0x9f, 0xdc } +, + /* Signature */ + 129, + { 0x07, 0x8d, 0x17, 0xab, 0x8e, 0x6f, 0xf0, 0xbe, 0x50, 0xb3, 0x53, 0x9e, 0xb0, 0x3a, 0xe8, 0xf0, 0x90, 0x3b, 0x7a, 0x07, 0x74, 0x81, 0x78, 0x1f, 0xb0, 0xb1, 0xf0, 0x9e, 0xdc, 0xf7, 0x78, 0x86, 0x31, 0x2a, 0xd6, 0xc0, 0x60, 0x27, 0x4f, 0x0c, 0x38, 0x9c, 0x16, 0x31, 0x40, 0x40, 0xc8, 0xd7, 0xd9, 0x90, 0x9c, 0xb7, 0x5d, 0xf1, 0x8c, 0x82, 0xd6, 0x2d, 0xd3, 0x4e, 0xb5, 0x9c, 0x6a, 0x87, 0xd3, 0xc4, 0x6a, 0x7e, 0xf7, 0x47, 0x4a, 0x5e, 0x44, 0x7f, 0x77, 0x44, 0xa6, 0xa9, 0x2f, 0x59, 0x90, 0xea, 0xec, 0x7b, 0xfb, 0x00, 0x84, 0x4d, 0x68, 0x4d, 0x30, 0x7d, 0xdb, 0x49, 0x81, 0x89, 0x41, 0x49, 0xe7, 0x52, 0xbf, 0xbe, 0x2e, 0x77, 0x05, 0x7d, 0xa7, 0x60, 0x54, 0x69, 0xaf, 0x7f, 0xfb, 0x67, 0x27, 0xa9, 0x98, 0x1b, 0x94, 0x39, 0xca, 0xa5, 0xd8, 0x0e, 0x6a, 0xe3, 0xb3, 0xd6, 0x51 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.12", + /* Message to be signed */ + 20, + { 0xe8, 0x74, 0x2f, 0x04, 0xb5, 0x65, 0x4d, 0x92, 0x88, 0xb2, 0x31, 0xa4, 0x7a, 0x36, 0x58, 0x39, 0xbb, 0x01, 0xbe, 0x87 } +, + /* Signature */ + 129, + { 0x09, 0xb7, 0x53, 0x06, 0xa7, 0x21, 0x2e, 0xa6, 0xf4, 0x7e, 0xb0, 0xcc, 0xf4, 0xe2, 0xe0, 0xd6, 0xf8, 0xf3, 0xab, 0xdb, 0x9c, 0xdc, 0xfa, 0xad, 0xbe, 0x51, 0x92, 0x2f, 0x92, 0xea, 0x62, 0x62, 0x3c, 0x58, 0xea, 0x74, 0xea, 0x1a, 0x24, 0x7c, 0x9d, 0x73, 0x1f, 0x2c, 0x03, 0x35, 0x36, 0xb3, 0x52, 0x73, 0xc7, 0x17, 0x49, 0x5f, 0x32, 0x5a, 0x60, 0x40, 0x5b, 0xd5, 0xf5, 0xe4, 0x05, 0xb6, 0x80, 0x27, 0x9e, 0x75, 0x21, 0x60, 0x47, 0x87, 0x40, 0x45, 0x72, 0x16, 0xdc, 0x92, 0x9d, 0xdd, 0x65, 0xde, 0xa5, 0x05, 0x53, 0x55, 0x46, 0xe4, 0x77, 0x0f, 0x82, 0x11, 0xb8, 0x49, 0xc3, 0x65, 0x21, 0x8e, 0x56, 0x6e, 0x5b, 0xb4, 0x1b, 0xfc, 0x36, 0x1b, 0x65, 0xcd, 0xcc, 0xb0, 0xe6, 0x04, 0xc9, 0xed, 0xb9, 0x70, 0xee, 0x6a, 0x28, 0x6a, 0x1f, 0xce, 0xc0, 0xae, 0x9d, 0x92, 0x55, 0x8e, 0xab } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.13", + /* Message to be signed */ + 249, + { 0xa0, 0x3c, 0x2b, 0x85, 0xfd, 0xe4, 0x64, 0x68, 0xd1, 0xc5, 0x06, 0x37, 0xb0, 0x0a, 0x72, 0xdc, 0xfc, 0x32, 0xc4, 0x16, 0x31, 0x73, 0x9c, 0x06, 0x02, 0x45, 0xf5, 0x3e, 0x57, 0xc6, 0x6c, 0x51, 0x76, 0x6f, 0x24, 0xea, 0xfd, 0x93, 0xe6, 0xc6, 0x67, 0x43, 0x48, 0x05, 0x91, 0xbf, 0x14, 0x44, 0x6e, 0x04, 0x0b, 0x67, 0xa4, 0xf8, 0x46, 0x99, 0x57, 0x6c, 0x2e, 0x14, 0x63, 0xca, 0xcc, 0xbc, 0xb0, 0x73, 0xe4, 0xb7, 0xec, 0x6d, 0xa6, 0xc8, 0xcb, 0x41, 0xd4, 0xa1, 0x23, 0xc7, 0x48, 0xcd, 0x7e, 0x83, 0xd2, 0x61, 0xe5, 0x4c, 0x2f, 0xd2, 0xbc, 0x49, 0x5b, 0xc4, 0xc4, 0x4a, 0x78, 0xf9, 0x82, 0x00, 0x34, 0x03, 0x09, 0x2e, 0xc6, 0x96, 0x0c, 0x08, 0x8e, 0x2b, 0xcd, 0xe3, 0x48, 0xa2, 0xe0, 0xe5, 0x5a, 0x4b, 0x4f, 0x42, 0xea, 0xb2, 0x29, 0xb9, 0x5c, 0x38, 0x3f, 0x21, 0x13, 0xed, 0x6c, 0xd1, 0xf3, 0xf3, 0x16, 0x7d, 0xe3, 0xd2, 0x8d, 0x36, 0x2c, 0x8d, 0x78, 0xb2, 0xeb, 0x6e, 0x31, 0x62, 0x0e, 0x34, 0xb2, 0xf0, 0xf9, 0x41, 0xda, 0xcd, 0xf7, 0xb4, 0xb8, 0x56, 0x8c, 0x6a, 0x86, 0x3a, 0x55, 0x1d, 0x7b, 0xd4, 0xa5, 0xd7, 0x09, 0x3e, 0xda, 0x69, 0xe1, 0xe2, 0x80, 0x56, 0xdc, 0xb1, 0xeb, 0x69, 0xae, 0x03, 0xad, 0x74, 0xbe, 0x72, 0xa7, 0x5a, 0xe8, 0xfb, 0x56, 0xa2, 0x71, 0x25, 0xca, 0x3d, 0x2d, 0xb3, 0x76, 0x9d, 0x13, 0xd3, 0x5d, 0xb1, 0x08, 0xe2, 0x64, 0x4a, 0x7f, 0x3b, 0x37, 0x93, 0x8f, 0xec, 0x97, 0x62, 0x31, 0x52, 0x06, 0xd3, 0x0c, 0xcf, 0xd5, 0x76, 0xae, 0x7d, 0xe0, 0x76, 0x98, 0x69, 0xe5, 0x04, 0x4d, 0x07, 0x64, 0x6c, 0xf7, 0x8c, 0x64, 0xa4, 0x86, 0x48, 0x0b, 0x0f, 0xd4, 0x2c, 0xc7, 0xb2, 0x46 } +, + /* Signature */ + 129, + { 0x05, 0x8d, 0xa5, 0x49, 0x4c, 0x4e, 0x98, 0xaa, 0x12, 0x1f, 0x67, 0xf6, 0x5a, 0x2c, 0x86, 0x54, 0x25, 0xa9, 0xe6, 0x00, 0x2b, 0x22, 0x3f, 0x03, 0x88, 0x80, 0x97, 0x53, 0x57, 0x3b, 0x4f, 0x33, 0x4d, 0xe4, 0x5d, 0x8f, 0x00, 0x07, 0x25, 0x5d, 0x11, 0x2d, 0xdc, 0x84, 0xdb, 0x26, 0x67, 0x00, 0xe4, 0x40, 0xb5, 0xa8, 0x69, 0x00, 0xc3, 0xd3, 0xd3, 0x5b, 0x02, 0x4c, 0x18, 0xd8, 0xa2, 0x5a, 0x58, 0x00, 0x22, 0x6d, 0x0a, 0x56, 0xd8, 0x38, 0xd8, 0x91, 0x9e, 0x6d, 0x5a, 0x87, 0x30, 0xd6, 0x19, 0x49, 0x90, 0x15, 0xec, 0x46, 0x65, 0xc6, 0x3d, 0x77, 0x80, 0x83, 0xa0, 0x42, 0xdd, 0x4f, 0x05, 0x2a, 0x1b, 0xbb, 0x5f, 0x40, 0x80, 0xcb, 0xbb, 0x41, 0xfa, 0x94, 0x5b, 0xad, 0x6a, 0x74, 0x77, 0x9f, 0x68, 0x07, 0x25, 0xe4, 0x7a, 0x08, 0xa0, 0x51, 0x4f, 0x35, 0x0f, 0xa5, 0xad, 0xf9, 0x0a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.14", + /* Message to be signed */ + 47, + { 0xc4, 0x0c, 0x70, 0xf2, 0x6d, 0xa5, 0x69, 0x48, 0x6b, 0xac, 0xe7, 0x85, 0xda, 0x32, 0xe3, 0x37, 0xa0, 0xeb, 0x94, 0xfb, 0x3a, 0x0a, 0xa4, 0x09, 0xc5, 0x77, 0x01, 0x75, 0xc8, 0xe8, 0xcb, 0x2b, 0xaa, 0x8d, 0x2a, 0x1b, 0x98, 0x46, 0xc3, 0x7d, 0xf7, 0xd6, 0x71, 0x03, 0x6d, 0x5e, 0x91 } +, + /* Signature */ + 129, + { 0x05, 0x25, 0x61, 0x28, 0xaf, 0xba, 0x1f, 0x55, 0xd8, 0x1f, 0x79, 0xea, 0x33, 0x87, 0x91, 0x47, 0xa2, 0x4a, 0xd7, 0x77, 0x93, 0x46, 0xee, 0x79, 0x8b, 0x21, 0x1c, 0x24, 0x71, 0x53, 0xea, 0x38, 0xd2, 0x6b, 0x21, 0x70, 0x65, 0xf6, 0x1e, 0x01, 0x10, 0xb5, 0x3d, 0x72, 0xcb, 0x64, 0x93, 0x4d, 0x9b, 0x1a, 0xd1, 0xb3, 0xde, 0xc3, 0x32, 0x09, 0x2d, 0x25, 0x8f, 0x0c, 0xaf, 0x1c, 0x4a, 0xee, 0x8b, 0x23, 0xe0, 0x9b, 0xab, 0x0f, 0x0c, 0x27, 0x88, 0x58, 0xb4, 0x41, 0xd0, 0x8c, 0xa3, 0xae, 0x9f, 0x00, 0xaa, 0x9a, 0x3f, 0x01, 0x8f, 0x7d, 0x9f, 0xa9, 0x8a, 0x18, 0xdf, 0x0d, 0x24, 0x84, 0x7e, 0x56, 0x7a, 0x47, 0xf5, 0x77, 0x9b, 0xd1, 0x79, 0x3a, 0x4b, 0x02, 0x52, 0xf2, 0xba, 0xd4, 0x0c, 0x9c, 0x4a, 0x81, 0x30, 0x1c, 0xc2, 0x8c, 0x26, 0x09, 0xd7, 0xbb, 0x33, 0x37, 0xe9, 0x7f, 0x14 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.15", + /* Message to be signed */ + 83, + { 0x9e, 0x6d, 0xcb, 0x11, 0xe0, 0xe8, 0x47, 0x71, 0x39, 0xfa, 0xf0, 0x41, 0xa7, 0x4e, 0x2b, 0xed, 0x64, 0x3a, 0x62, 0xad, 0xed, 0xac, 0x7c, 0xbe, 0xf3, 0x65, 0xec, 0xc4, 0x3a, 0xe4, 0xe5, 0x82, 0x60, 0xbc, 0x72, 0x46, 0x23, 0xbd, 0x63, 0x42, 0xdc, 0x66, 0x0d, 0x66, 0x14, 0x2e, 0xa6, 0x36, 0x80, 0x71, 0x5f, 0x52, 0x2f, 0xf3, 0xcd, 0x4b, 0x63, 0x6f, 0x84, 0xaa, 0x9d, 0x75, 0xfb, 0xfb, 0xc3, 0x84, 0x10, 0x7e, 0x43, 0x00, 0x4d, 0x98, 0x6f, 0xbc, 0xe1, 0xa2, 0x7f, 0x7e, 0xcc, 0x7d, 0x02, 0x39, 0x2c } +, + /* Signature */ + 129, + { 0x0c, 0xcf, 0x23, 0x4e, 0xb4, 0x80, 0x08, 0x5d, 0x92, 0x0d, 0x37, 0xd6, 0x87, 0x96, 0x5d, 0x2f, 0xd2, 0xe4, 0xa4, 0xf3, 0xbd, 0x3b, 0xf7, 0xdd, 0xc1, 0x6b, 0x5d, 0x62, 0xa6, 0x90, 0x32, 0x74, 0x20, 0x7c, 0x6f, 0x90, 0x83, 0x6e, 0x29, 0xff, 0xc6, 0x3a, 0x57, 0xf9, 0x81, 0x30, 0xc5, 0x25, 0x23, 0x25, 0x19, 0xc7, 0x08, 0xf0, 0xdc, 0x8a, 0x12, 0x55, 0xab, 0x55, 0xdb, 0x1a, 0x2b, 0x9a, 0xbc, 0x11, 0x06, 0x16, 0x02, 0x07, 0x5f, 0xf6, 0xf9, 0x7f, 0x90, 0x92, 0x79, 0x6b, 0x98, 0x87, 0x1a, 0x6c, 0xd5, 0xd2, 0x61, 0x7d, 0xdc, 0x9d, 0x25, 0x5a, 0x73, 0x00, 0xc9, 0x10, 0xfd, 0x21, 0x0b, 0x14, 0xa9, 0x81, 0xe5, 0xa0, 0xe0, 0xc6, 0xbb, 0x2b, 0x04, 0x5f, 0xa9, 0x75, 0x68, 0x98, 0xb9, 0x3b, 0x8a, 0x63, 0x45, 0x44, 0xd7, 0x7a, 0xfd, 0xb1, 0xcf, 0x0e, 0x79, 0x58, 0xf1, 0x1a, 0x43 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.16", + /* Message to be signed */ + 177, + { 0x20, 0xbc, 0x46, 0x3b, 0x5e, 0x12, 0x20, 0xa3, 0x9c, 0x84, 0xe8, 0x9f, 0xe6, 0x71, 0x6e, 0xec, 0xab, 0x55, 0x55, 0xf8, 0xbf, 0xce, 0x60, 0xcf, 0xb8, 0x37, 0x93, 0xcc, 0x40, 0xa4, 0xda, 0x1d, 0x22, 0xc0, 0xab, 0x4e, 0xaa, 0x93, 0x1f, 0xb7, 0x47, 0xbe, 0x35, 0xf1, 0xcf, 0x6f, 0xb1, 0x46, 0x5b, 0xef, 0x1d, 0xf2, 0x76, 0x0f, 0xcb, 0x3f, 0x70, 0xd3, 0xe2, 0x96, 0xe7, 0xb2, 0x70, 0x45, 0x0d, 0xff, 0xe2, 0xd5, 0x88, 0xc4, 0x39, 0x6a, 0x5f, 0x6f, 0x1e, 0x63, 0x87, 0xaa, 0x86, 0x97, 0x1f, 0xb0, 0xad, 0x24, 0xdf, 0x55, 0x04, 0x43, 0xdd, 0x12, 0x2b, 0xdb, 0x2c, 0xf3, 0xc9, 0xed, 0x61, 0x25, 0xfe, 0x55, 0xce, 0xc9, 0x91, 0xcb, 0xae, 0x8e, 0xe1, 0x56, 0x2a, 0x8c, 0x0f, 0x4f, 0x36, 0x4f, 0x8f, 0x0a, 0x80, 0xcb, 0x30, 0xfd, 0x99, 0x44, 0x0b, 0xf6, 0x55, 0xf0, 0x80, 0x4f, 0x92, 0x96, 0x8c, 0xa2, 0xe0, 0x1c, 0x0d, 0x5a, 0xbb, 0x4e, 0xe2, 0x67, 0x63, 0x6d, 0xd4, 0xf5, 0x11, 0xa8, 0xd3, 0x29, 0x41, 0x16, 0x21, 0x6b, 0xed, 0xc1, 0x08, 0x86, 0x45, 0xe4, 0x65, 0xd8, 0xe1, 0x98, 0xb8, 0xaf, 0xe1, 0xcd, 0x54, 0x24, 0xb4, 0x2a, 0x53, 0x3c, 0xed, 0x19, 0x8a, 0xd5, 0x97 } +, + /* Signature */ + 129, + { 0x05, 0x1b, 0x71, 0x42, 0x66, 0x06, 0x6b, 0xbb, 0x81, 0x9a, 0x2a, 0x38, 0x05, 0xa8, 0x9c, 0xff, 0x46, 0x18, 0x75, 0xc0, 0x95, 0xf4, 0xf3, 0x89, 0x82, 0xd1, 0xaf, 0xc2, 0xad, 0x2f, 0x14, 0x24, 0x50, 0xb8, 0xa7, 0x52, 0x94, 0x7f, 0x03, 0x1c, 0xce, 0x2c, 0x9c, 0x34, 0x0c, 0x8a, 0xc9, 0xf9, 0xf7, 0xa5, 0x48, 0xb7, 0xcc, 0x17, 0xe4, 0xcc, 0x52, 0x56, 0x96, 0xea, 0x0c, 0x87, 0x53, 0xa1, 0xe1, 0x5b, 0xcb, 0x98, 0x5d, 0xea, 0xec, 0x77, 0x6f, 0xb9, 0xe7, 0xd9, 0xf7, 0x58, 0x62, 0xf8, 0x98, 0x35, 0x23, 0xd9, 0xf8, 0x71, 0xc6, 0x3f, 0xb7, 0x56, 0x1a, 0xc7, 0x1c, 0x37, 0x6b, 0xf4, 0x95, 0xd4, 0x32, 0x38, 0x59, 0xbd, 0x14, 0x18, 0x8f, 0xcd, 0xfb, 0x4b, 0x37, 0xab, 0xcb, 0x5d, 0xc1, 0xa5, 0x8e, 0xed, 0xea, 0x7e, 0x0f, 0xe6, 0x2a, 0xc1, 0x6e, 0x20, 0x8a, 0xab, 0x4c, 0xee, 0x26 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.17", + /* Message to be signed */ + 232, + { 0x92, 0xda, 0x26, 0x0b, 0xc2, 0x13, 0xb7, 0x2b, 0x48, 0xa0, 0x57, 0x53, 0x50, 0x3d, 0x00, 0xa1, 0xdb, 0xfd, 0x02, 0xac, 0x7b, 0x9f, 0xd4, 0x4d, 0x24, 0x01, 0xea, 0x7a, 0xd5, 0x8a, 0xd1, 0x86, 0x1f, 0xda, 0x53, 0x63, 0x29, 0xae, 0x41, 0x73, 0xc9, 0x16, 0x80, 0x05, 0xb9, 0x66, 0x2c, 0x05, 0xcb, 0xea, 0x47, 0xad, 0x86, 0x4a, 0xf7, 0xcb, 0x16, 0x60, 0x2d, 0x3d, 0x18, 0x34, 0x71, 0xbc, 0x98, 0xbc, 0xc6, 0x2c, 0x6d, 0x00, 0xd3, 0x34, 0xbf, 0xf5, 0xb9, 0x0c, 0xfe, 0x7d, 0x7e, 0x12, 0xd0, 0x7f, 0xe7, 0xd4, 0xcb, 0xd9, 0xdc, 0xd3, 0xc4, 0xc2, 0x34, 0x90, 0xbe, 0x8c, 0xba, 0xdc, 0x08, 0xc9, 0x17, 0x79, 0x80, 0x37, 0x3c, 0x79, 0xeb, 0x4e, 0xea, 0x6d, 0x81, 0xa6, 0xbe, 0xe2, 0x27, 0x0b, 0xf4, 0x20, 0xf9, 0x19, 0x79, 0xad, 0x3f, 0x27, 0x1f, 0xd6, 0x8d, 0xd4, 0x28, 0x3b, 0xe8, 0x14, 0x10, 0x92, 0x8c, 0xa4, 0x5b, 0x9d, 0xeb, 0x58, 0xd3, 0xae, 0x98, 0xb2, 0xf4, 0xfc, 0xa6, 0x21, 0x25, 0x95, 0x0b, 0x5e, 0xe1, 0x28, 0xdb, 0xa1, 0x05, 0xc3, 0x5c, 0xc3, 0x98, 0xd1, 0x5e, 0x74, 0x2b, 0xba, 0x92, 0x69, 0x7b, 0x5c, 0x62, 0xb2, 0x67, 0xce, 0x01, 0x14, 0x1c, 0xec, 0xef, 0x80, 0x75, 0x07, 0xde, 0x29, 0xc4, 0x85, 0x30, 0x5d, 0x0a, 0x99, 0x09, 0x43, 0x23, 0x0d, 0x8d, 0x9b, 0x72, 0x52, 0xee, 0x0b, 0x19, 0x56, 0xde, 0x84, 0x5f, 0x2f, 0xbb, 0x28, 0x38, 0x78, 0x5b, 0x47, 0x0a, 0x7c, 0x20, 0x53, 0xdb, 0x39, 0x6b, 0x31, 0x5a, 0x30, 0xd8, 0xa7, 0xf9, 0x1c, 0xff, 0xfd, 0x03, 0xe8, 0xa3, 0x9b, 0xa8, 0xbc } +, + /* Signature */ + 129, + { 0x03, 0xe2, 0x3f, 0x86, 0x52, 0x37, 0x4d, 0x48, 0xd3, 0x81, 0xc3, 0x78, 0x35, 0x3e, 0xb4, 0x7d, 0x90, 0x64, 0xcd, 0x70, 0x8e, 0x1b, 0x9b, 0xf6, 0x88, 0x70, 0x4c, 0x04, 0xc0, 0x09, 0x00, 0x88, 0x46, 0xe6, 0xa4, 0x7e, 0x0b, 0xd2, 0xe3, 0x0c, 0x33, 0x40, 0xf5, 0xd4, 0xe1, 0x9d, 0x2d, 0xc5, 0xd8, 0x89, 0x0c, 0x8f, 0x01, 0x04, 0xdd, 0x6f, 0x5d, 0xd6, 0xca, 0xd9, 0xc4, 0xd9, 0x94, 0x84, 0x09, 0xc3, 0xcc, 0x0b, 0xe6, 0x70, 0x71, 0x9d, 0xd0, 0x48, 0x41, 0x80, 0x89, 0x1c, 0x93, 0x5b, 0x99, 0x79, 0xdb, 0x8e, 0xb4, 0x68, 0xa2, 0x3e, 0x4e, 0xf4, 0x60, 0x29, 0xf3, 0xaf, 0x14, 0x57, 0x4b, 0xd1, 0x0b, 0x47, 0x3e, 0xdd, 0x9b, 0x12, 0x7a, 0x30, 0x6e, 0x51, 0x24, 0xad, 0xa4, 0x02, 0xc1, 0x48, 0xf5, 0x1b, 0x52, 0xe7, 0xe6, 0x28, 0xbf, 0xac, 0xec, 0x3f, 0xc2, 0x54, 0x3a, 0x0f, 0x92 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.18", + /* Message to be signed */ + 113, + { 0x86, 0x03, 0xa5, 0x62, 0x2a, 0x2d, 0xbb, 0xbc, 0xbb, 0xe5, 0x33, 0x30, 0xe9, 0x08, 0xd5, 0xa2, 0x5f, 0x6e, 0x67, 0xa5, 0x1e, 0x07, 0x68, 0xd7, 0xc3, 0xc3, 0xfb, 0xe8, 0xb9, 0x2e, 0x8b, 0x1b, 0x36, 0xdc, 0x00, 0x74, 0x3c, 0xe3, 0x3d, 0xa0, 0xf1, 0xc8, 0xcf, 0xb0, 0x0d, 0x63, 0xed, 0xd6, 0xb2, 0x25, 0x2f, 0xb6, 0x72, 0x13, 0x97, 0xd2, 0x50, 0x4b, 0x30, 0xed, 0x1d, 0x29, 0x3a, 0x82, 0xe2, 0x44, 0xc9, 0x51, 0xbb, 0xfc, 0x24, 0x29, 0x8a, 0x42, 0xff, 0xee, 0x26, 0xe4, 0x56, 0xa7, 0xbe, 0x10, 0x5c, 0xb5, 0xe3, 0x7b, 0x3d, 0x25, 0xde, 0x28, 0xbf, 0xc0, 0x10, 0x42, 0xc4, 0xa8, 0x2c, 0xe8, 0x70, 0x45, 0x54, 0x87, 0xe5, 0xb3, 0x0e, 0x26, 0xf8, 0xd5, 0x39, 0x8c, 0x86, 0x12, 0x6e } +, + /* Signature */ + 129, + { 0x08, 0x22, 0xfc, 0x22, 0xa9, 0xcd, 0x87, 0x7c, 0x09, 0xb6, 0xf9, 0x2e, 0x80, 0x17, 0xcc, 0xc0, 0x28, 0xd5, 0x37, 0x99, 0x67, 0xc7, 0xd0, 0x4e, 0xf3, 0x2f, 0x86, 0x9c, 0x7e, 0xf6, 0x7d, 0x59, 0x3c, 0x77, 0x45, 0xf6, 0x29, 0xd9, 0x3d, 0xf2, 0x60, 0x03, 0x8c, 0xd3, 0x33, 0xea, 0xee, 0x92, 0x35, 0x9f, 0xdb, 0xbf, 0x84, 0x62, 0x3b, 0x7b, 0x55, 0x14, 0x23, 0x5b, 0x83, 0x06, 0x27, 0x2f, 0x4e, 0xfd, 0x13, 0xa6, 0x70, 0x0b, 0xe9, 0x28, 0x9a, 0xd5, 0x4e, 0x57, 0xd5, 0x2d, 0x1f, 0xeb, 0xb4, 0x6a, 0x37, 0xaf, 0xd6, 0x95, 0x94, 0x2c, 0x4c, 0xbc, 0xfd, 0x37, 0x68, 0xf2, 0x82, 0x1e, 0x88, 0x8e, 0xfa, 0x0e, 0x2c, 0x5f, 0xd3, 0xc9, 0xc4, 0x2c, 0xc3, 0x55, 0x50, 0xd7, 0x95, 0x5c, 0xdb, 0xd3, 0x5c, 0x8e, 0xf8, 0x58, 0x1b, 0x41, 0xf8, 0xdd, 0xab, 0x26, 0x18, 0x26, 0x2e, 0x3d, 0xff } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.19", + /* Message to be signed */ + 43, + { 0x06, 0x7d, 0x4b, 0xec, 0xb0, 0x3e, 0x1e, 0xb2, 0x75, 0xae, 0x22, 0x50, 0x7a, 0x77, 0xa5, 0x39, 0x6e, 0x71, 0x9b, 0x5f, 0x00, 0xb1, 0x05, 0x95, 0x0b, 0xc7, 0x99, 0x8e, 0x08, 0x03, 0xda, 0x57, 0xa4, 0xde, 0x08, 0xa4, 0x07, 0x8b, 0x9a, 0x00, 0xd2, 0xd4, 0x6f } +, + /* Signature */ + 129, + { 0x09, 0x10, 0x8d, 0x44, 0x57, 0x5f, 0x61, 0x4a, 0x68, 0x3e, 0xe4, 0xd7, 0x8b, 0xce, 0x1c, 0x58, 0xf5, 0x24, 0x36, 0x87, 0xcb, 0xe9, 0xc5, 0x48, 0x34, 0x60, 0xb6, 0x5d, 0xf2, 0x36, 0x92, 0x7d, 0xbc, 0x78, 0xc0, 0x64, 0x39, 0xce, 0x1c, 0x7c, 0x51, 0x97, 0x39, 0xc8, 0xf8, 0x95, 0x00, 0x82, 0xd9, 0x56, 0xd6, 0x0f, 0xc3, 0x64, 0x5b, 0xa7, 0xaf, 0x8e, 0x78, 0x89, 0x54, 0x70, 0x63, 0x1b, 0xb4, 0xda, 0x00, 0xc0, 0x1b, 0x98, 0x2c, 0xc1, 0x1c, 0x68, 0xd2, 0x65, 0x0c, 0x7c, 0xae, 0xa4, 0xa2, 0x6e, 0x21, 0x0f, 0xf4, 0xb1, 0xca, 0xe1, 0xdb, 0x50, 0x5f, 0xce, 0xa9, 0x29, 0x34, 0x87, 0xb2, 0x07, 0x31, 0x78, 0xca, 0x24, 0x5c, 0xf0, 0xca, 0x23, 0x56, 0xba, 0xf8, 0x65, 0x54, 0x6b, 0x54, 0xaf, 0x95, 0x35, 0xba, 0xb1, 0x8d, 0xb6, 0x79, 0xef, 0x56, 0x27, 0x09, 0x29, 0x79, 0xc0, 0xa8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 10.20", + /* Message to be signed */ + 238, + { 0x88, 0x4f, 0xc5, 0x02, 0xc8, 0x82, 0x48, 0x49, 0x47, 0x8b, 0x2e, 0xac, 0x1e, 0x7e, 0xbb, 0xb7, 0xca, 0xf2, 0x8e, 0xeb, 0x48, 0x89, 0x45, 0x86, 0x02, 0xec, 0x70, 0x35, 0x81, 0xd0, 0x5e, 0xf9, 0xb1, 0xa4, 0x22, 0x0b, 0xd2, 0xf9, 0x22, 0xf2, 0x5e, 0x46, 0x4c, 0x88, 0x07, 0x01, 0xc8, 0xa4, 0x5b, 0x1d, 0x1f, 0xab, 0xc8, 0x66, 0x2e, 0xb2, 0x49, 0x40, 0x04, 0x26, 0xc2, 0x22, 0x62, 0x38, 0xeb, 0x8a, 0xd0, 0xf9, 0x06, 0x9c, 0x90, 0xf0, 0x01, 0x82, 0x77, 0x44, 0x80, 0x25, 0xa6, 0x41, 0x80, 0xed, 0x55, 0xd1, 0xaf, 0xd2, 0x7a, 0xff, 0x4f, 0x00, 0x70, 0x2f, 0x71, 0x5d, 0x29, 0x10, 0x00, 0x0d, 0xf3, 0x92, 0x5c, 0x70, 0x10, 0xff, 0x11, 0x7f, 0x6d, 0x8d, 0x2a, 0x81, 0x67, 0x09, 0x48, 0x9e, 0xfd, 0x29, 0xa4, 0x5c, 0x59, 0x23, 0x17, 0x7b, 0xf9, 0x2c, 0xd0, 0xbf, 0x6b, 0x94, 0x74, 0x5d, 0x34, 0x8a, 0x14, 0x4e, 0x98, 0x74, 0x0f, 0x72, 0x22, 0x6a, 0x3e, 0x2a, 0x9d, 0x41, 0x7b, 0x7c, 0x1f, 0xd8, 0xf8, 0x95, 0xf5, 0x15, 0xc5, 0xc6, 0xd4, 0x06, 0xa7, 0x2b, 0xdc, 0xcd, 0x39, 0x15, 0x2c, 0x30, 0xfd, 0xbd, 0xda, 0x0e, 0x62, 0x82, 0x3e, 0xe9, 0xdf, 0xab, 0x34, 0x32, 0xe6, 0x64, 0x2e, 0xec, 0xb6, 0x98, 0x7b, 0x90, 0x46, 0xe0, 0x40, 0xa4, 0x78, 0xa4, 0xdf, 0x64, 0x8d, 0xef, 0xb3, 0x01, 0x6a, 0xa4, 0x43, 0xd0, 0x67, 0xa1, 0xfa, 0x41, 0x55, 0x55, 0x53, 0x74, 0xf8, 0xba, 0x32, 0x5a, 0x8b, 0x55, 0xe4, 0xd6, 0xb5, 0xfa, 0x09, 0x0e, 0xeb, 0xae, 0xc9, 0xc9, 0x2e, 0x26, 0x1c, 0xc0, 0x4c, 0xea, 0xa4, 0x8b, 0x3b, 0xed, 0x7b, 0x3f, 0x87, 0xd3 } +, + /* Signature */ + 129, + { 0x0b, 0x41, 0xb4, 0x12, 0x19, 0x71, 0x26, 0x15, 0x9e, 0x9b, 0xda, 0x1a, 0x24, 0x62, 0xc8, 0xa4, 0xfd, 0x3d, 0xff, 0xdc, 0x6e, 0x98, 0xe4, 0xdb, 0xfc, 0x06, 0xcf, 0xcc, 0xf1, 0x6f, 0x74, 0xfc, 0xb5, 0x23, 0x38, 0xaf, 0x14, 0xed, 0x39, 0x36, 0xe0, 0x2c, 0x1d, 0x7e, 0x77, 0x23, 0x6c, 0xc6, 0xa4, 0x89, 0xf0, 0x0f, 0x08, 0x98, 0x52, 0xde, 0x5c, 0xc4, 0x25, 0xb4, 0x50, 0x94, 0xa0, 0x42, 0xe3, 0x85, 0x46, 0x4b, 0x64, 0xc3, 0xb2, 0xff, 0xd0, 0x1f, 0x19, 0xa0, 0x1c, 0x2c, 0x03, 0x81, 0xf7, 0x58, 0xa6, 0x73, 0x65, 0xd1, 0xe6, 0x5a, 0x70, 0x7b, 0x13, 0x4e, 0x3f, 0x8a, 0x93, 0x16, 0xb4, 0xaa, 0xcb, 0x7e, 0x85, 0x1a, 0x5e, 0xab, 0x3c, 0xd8, 0x11, 0xbd, 0x45, 0x22, 0xdd, 0x14, 0x1a, 0x00, 0x15, 0x7d, 0xc3, 0xfc, 0xaf, 0xc4, 0x15, 0x4c, 0xaf, 0x05, 0x93, 0xca, 0x62, 0x10, 0x2e } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 11: A 1029-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x1e, 0xd7, 0xee, 0xa9, 0x40, 0x5f, 0x50, 0x7f, 0x94, 0x16, 0x23, 0xa1, 0x7b, 0xea, 0x71, 0x7b, 0x86, 0x0d, 0xe4, 0x4c, 0xb7, 0x76, 0x87, 0xb8, 0xb8, 0x5a, 0x6d, 0x7d, 0x1e, 0xf4, 0xf8, 0x62, 0x8d, 0x25, 0x7c, 0xb9, 0x42, 0x38, 0xc6, 0x25, 0xba, 0x25, 0xd4, 0x6a, 0xae, 0x59, 0x39, 0x60, 0xaf, 0x79, 0xf7, 0x5e, 0x28, 0xab, 0x63, 0xac, 0x3c, 0xac, 0x48, 0x20, 0xb8, 0x2d, 0xa1, 0xcf, 0x75, 0x0d, 0x6c, 0x93, 0x0d, 0x6b, 0x82, 0x78, 0x54, 0xaa, 0xf6, 0xca, 0xc0, 0xc1, 0x7b, 0x80, 0xb0, 0x29, 0xf5, 0xd3, 0x19, 0xcc, 0xca, 0x66, 0x5c, 0x56, 0x94, 0xf5, 0x4b, 0xa5, 0xf0, 0x96, 0xf4, 0x54, 0x34, 0x13, 0xec, 0x4c, 0x5e, 0x97, 0xcc, 0x1d, 0xda, 0x89, 0xd2, 0xaf, 0xd4, 0x28, 0x57, 0x87, 0x59, 0x03, 0x2a, 0xdf, 0x92, 0x89, 0x50, 0x65, 0xba, 0xaf, 0xe8, 0x8d, 0x2d, 0x8b, 0x61 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x0d, 0x93, 0x80, 0x72, 0xb1, 0x6a, 0x02, 0xf5, 0xd5, 0x0a, 0x15, 0xae, 0xeb, 0xeb, 0x5a, 0xfe, 0x43, 0x18, 0x74, 0x48, 0x2c, 0x6d, 0x18, 0xfa, 0x7e, 0xf3, 0x16, 0xc4, 0x7f, 0x4e, 0xd6, 0xd2, 0x12, 0x4c, 0xd0, 0xe4, 0x7e, 0xb8, 0x9c, 0xc7, 0x58, 0x73, 0x74, 0x57, 0x6c, 0xdc, 0xcb, 0x3b, 0xba, 0xa1, 0x95, 0xf7, 0xb5, 0x31, 0x13, 0x93, 0x69, 0xb5, 0x6f, 0x9e, 0x2f, 0x53, 0xae, 0xa8, 0xac, 0x7a, 0x97, 0xe1, 0xd7, 0x45, 0x8f, 0x52, 0x6c, 0xf7, 0xd7, 0x10, 0xc4, 0x90, 0x2a, 0xae, 0xdf, 0x99, 0x7c, 0x11, 0x94, 0xb8, 0x7b, 0x62, 0xcc, 0xd8, 0xda, 0xb8, 0xff, 0x5b, 0x67, 0xd4, 0x0f, 0xe8, 0x3d, 0xe1, 0xb8, 0x2b, 0x91, 0x60, 0x9a, 0x7c, 0x5c, 0xf3, 0x92, 0x29, 0xeb, 0x3a, 0x1b, 0x2f, 0x0e, 0xbf, 0x0b, 0x12, 0x5c, 0xb8, 0x00, 0x91, 0xa0, 0x7e, 0xbc, 0x77, 0x9c, 0xe7, 0xfd } +, + /* Prime 1 */ + 65, + { 0x05, 0x90, 0xa1, 0xe5, 0x18, 0x71, 0x07, 0xfa, 0xef, 0x1e, 0x0c, 0xd5, 0x2f, 0xa2, 0xdc, 0xad, 0xa2, 0xd5, 0x8a, 0xbc, 0xc9, 0xe0, 0x73, 0x8f, 0xf4, 0x85, 0x0f, 0x7d, 0x2d, 0xee, 0x19, 0x82, 0x3f, 0x6e, 0x3e, 0x2c, 0xa9, 0x11, 0xb7, 0x17, 0x4b, 0xe7, 0x0b, 0x15, 0xc1, 0xb8, 0x87, 0xe0, 0xae, 0x15, 0x10, 0x21, 0x22, 0x42, 0x2f, 0xa1, 0x58, 0xb9, 0x8b, 0x0d, 0x38, 0x21, 0x15, 0x24, 0x5f } +, + /* Prime 2 */ + 65, + { 0x05, 0x8a, 0xdd, 0x02, 0x9b, 0xc9, 0x7e, 0xcf, 0xd1, 0xd0, 0xdb, 0x26, 0xbe, 0x45, 0xee, 0x8d, 0x3e, 0x54, 0xbf, 0xe6, 0x36, 0xfc, 0x4d, 0xa6, 0x66, 0xdc, 0xf2, 0x50, 0xab, 0x2c, 0x2e, 0x96, 0x56, 0x62, 0x16, 0xb8, 0xa5, 0x17, 0xf1, 0x0f, 0x75, 0xb9, 0x8f, 0xde, 0x6c, 0xcd, 0x8a, 0x58, 0xe8, 0xfc, 0x58, 0x2e, 0x78, 0x74, 0x90, 0xe1, 0x95, 0x8f, 0x7a, 0x0f, 0xda, 0x82, 0xad, 0x68, 0x3f } +, + /* Prime exponent 1 */ + 65, + { 0x01, 0x80, 0xee, 0xfd, 0xa3, 0xf9, 0x06, 0x9a, 0xfa, 0xf9, 0x37, 0xa6, 0x72, 0xd4, 0xa2, 0xa4, 0x18, 0x17, 0x73, 0x01, 0x47, 0xda, 0xe9, 0xde, 0xbf, 0xc7, 0x24, 0x44, 0x42, 0xa0, 0xcf, 0x2b, 0xae, 0x4f, 0xef, 0x64, 0xc9, 0xda, 0x0b, 0x8a, 0xb3, 0xeb, 0x9d, 0xc7, 0x27, 0x2c, 0xe1, 0x2a, 0x08, 0x5f, 0x90, 0x98, 0x23, 0x55, 0x96, 0xe1, 0x15, 0xc4, 0x2c, 0x9a, 0x49, 0xcc, 0x46, 0x96, 0x29 } +, + /* Prime exponent 2 */ + 65, + { 0x05, 0x12, 0xe1, 0x4e, 0x11, 0x05, 0x7d, 0x84, 0x8c, 0x23, 0xf1, 0x6b, 0x5f, 0x46, 0x2f, 0xa2, 0xb7, 0x8b, 0xe7, 0xfc, 0xbd, 0x1b, 0x6d, 0x8e, 0x46, 0x9e, 0x3f, 0x69, 0x9f, 0xb9, 0x9b, 0x90, 0x5e, 0xd5, 0xfe, 0xcc, 0xdb, 0xbd, 0xb6, 0x1d, 0x1b, 0xfd, 0x5a, 0x7a, 0x19, 0x0a, 0x74, 0x7a, 0xfe, 0x16, 0x7c, 0x37, 0x56, 0x68, 0x07, 0x75, 0xab, 0x6f, 0xa4, 0x23, 0x3d, 0x3a, 0xe1, 0xba, 0x0b } +, + /* Coefficient */ + 64, + { 0x26, 0x2e, 0x28, 0x23, 0x16, 0x98, 0xbe, 0x32, 0x87, 0xa9, 0xc7, 0x06, 0xf3, 0x94, 0x7b, 0x7d, 0x5c, 0x2f, 0x5f, 0xd2, 0xb9, 0x14, 0x46, 0xf5, 0xe9, 0xa3, 0x15, 0x44, 0xd9, 0xaf, 0xf4, 0x55, 0xa3, 0xec, 0xc6, 0xb5, 0x43, 0x14, 0x82, 0x0c, 0x2a, 0x48, 0x82, 0x61, 0xd9, 0xf9, 0x8d, 0x34, 0x8d, 0x9c, 0x3d, 0x10, 0x02, 0xe4, 0xe8, 0x28, 0x7a, 0x15, 0x2c, 0x12, 0x87, 0x09, 0x65, 0x60 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 11.1", + /* Message to be signed */ + 218, + { 0x84, 0x55, 0x19, 0xdd, 0x45, 0xd2, 0xdd, 0xcb, 0xc8, 0xdb, 0xe0, 0xb8, 0x29, 0x54, 0xc4, 0x58, 0xc3, 0x66, 0x4d, 0x88, 0x27, 0x4e, 0x50, 0x2d, 0x27, 0x91, 0x46, 0xb1, 0x8f, 0x6a, 0x81, 0x67, 0x50, 0xe9, 0x4b, 0x4e, 0xcd, 0xee, 0x68, 0x32, 0xcb, 0x35, 0xdf, 0xcb, 0xdb, 0xdd, 0x3e, 0x5d, 0xc0, 0x64, 0x04, 0xd5, 0xf0, 0xc7, 0x0e, 0x7c, 0x7c, 0xd0, 0xe1, 0x9f, 0x38, 0xbc, 0x5a, 0xe3, 0x2c, 0x7c, 0xd9, 0x1f, 0x94, 0xd8, 0xf5, 0x67, 0x82, 0x39, 0x7b, 0xc7, 0x4e, 0x6b, 0x06, 0x98, 0x27, 0xec, 0x27, 0x30, 0x17, 0x37, 0x40, 0xce, 0x4a, 0x10, 0xe6, 0x48, 0xc7, 0x88, 0x97, 0xaf, 0x1a, 0x89, 0xe8, 0x33, 0x31, 0xd0, 0xf4, 0x61, 0x37, 0x8d, 0x06, 0x05, 0x28, 0x73, 0xf1, 0x7d, 0x9f, 0xfc, 0xe4, 0x6a, 0x32, 0x47, 0x26, 0x07, 0xfe, 0x73, 0xe4, 0xa5, 0x61, 0x87, 0x9e, 0x61, 0x9e, 0x7c, 0x1a, 0xe8, 0x14, 0xe4, 0x5e, 0x1d, 0x2b, 0xdb, 0x12, 0x19, 0x46, 0xb2, 0xae, 0xb8, 0x56, 0x39, 0x16, 0xc5, 0x43, 0xeb, 0xfd, 0xc2, 0xc0, 0x90, 0xfe, 0xb5, 0x56, 0x65, 0x00, 0xa8, 0xce, 0x74, 0xaf, 0xa4, 0x53, 0x72, 0xbd, 0xe0, 0xc6, 0x67, 0x3a, 0x7f, 0x6a, 0xcc, 0xb0, 0xee, 0x9d, 0x57, 0xbd, 0xe9, 0x3c, 0x36, 0xdd, 0xc5, 0x7b, 0x84, 0x90, 0xaa, 0x2d, 0x68, 0x58, 0x5a, 0x3d, 0xb7, 0x29, 0x7a, 0xda, 0x6d, 0x9b, 0x3f, 0x35, 0x6d, 0xbc, 0x74, 0xd3, 0x15, 0xc5, 0xfa, 0x1a, 0xbf, 0x7d, 0xe6, 0xce, 0xbc, 0xa8, 0x3c, 0x9d, 0xf7 } +, + /* Signature */ + 129, + { 0x08, 0x63, 0xa6, 0x26, 0xdc, 0x42, 0xba, 0xf3, 0xe1, 0x61, 0xc3, 0x5b, 0x3d, 0xe3, 0xb1, 0xab, 0xc1, 0xaa, 0x5a, 0xdf, 0x54, 0x16, 0x46, 0x5d, 0x4c, 0x7b, 0x6b, 0x01, 0xae, 0x2d, 0xad, 0x73, 0xf9, 0xf1, 0x58, 0xeb, 0x21, 0x3d, 0xbc, 0x36, 0x0b, 0xe4, 0xd4, 0x7e, 0x57, 0x07, 0x87, 0x1c, 0x39, 0xc3, 0x8d, 0xbb, 0xc9, 0x6b, 0x46, 0xc8, 0xf9, 0xaf, 0xeb, 0xd3, 0xdd, 0xac, 0x87, 0x16, 0x90, 0x98, 0xe1, 0xa7, 0x67, 0x18, 0xd3, 0x54, 0xcd, 0x09, 0x1c, 0xa3, 0x52, 0x96, 0xa7, 0x7c, 0x21, 0xd2, 0x51, 0x2f, 0xfe, 0x65, 0xe3, 0xb7, 0x1b, 0x90, 0x22, 0xe9, 0xcd, 0x1f, 0x7c, 0x35, 0xce, 0x13, 0x65, 0xfd, 0x1f, 0x2c, 0x2c, 0xb9, 0x67, 0xff, 0x4c, 0x8f, 0x90, 0xf0, 0xc8, 0xea, 0xef, 0x0d, 0xb7, 0x3f, 0xed, 0x00, 0xe9, 0x8c, 0xfc, 0x83, 0xf8, 0x0c, 0x67, 0xb3, 0xbe, 0x1d, 0x33 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 11.2", + /* Message to be signed */ + 40, + { 0x86, 0x8e, 0x7c, 0x4f, 0xc6, 0x34, 0x0b, 0x6b, 0xbe, 0xb7, 0xb8, 0x6e, 0xa8, 0x9e, 0xe7, 0x26, 0x5f, 0x32, 0x31, 0xf4, 0x8b, 0xaa, 0x92, 0xe4, 0xa2, 0xe8, 0xce, 0x0f, 0xa1, 0xc1, 0xa8, 0xc0, 0xfb, 0x0a, 0xca, 0x94, 0x4c, 0x74, 0xbc, 0xcd } +, + /* Signature */ + 129, + { 0x10, 0xcb, 0xf8, 0x71, 0x7f, 0x76, 0x27, 0x8f, 0xcc, 0x8f, 0xc0, 0xaa, 0xb4, 0x6e, 0x90, 0xa3, 0xd1, 0x80, 0xc3, 0xc9, 0x2a, 0x4a, 0x83, 0xeb, 0x93, 0xc8, 0x92, 0x0a, 0xf8, 0x8b, 0xd6, 0x50, 0x6b, 0x40, 0x73, 0x45, 0x3f, 0x0b, 0xef, 0xf3, 0xe6, 0x1e, 0xdb, 0xb4, 0xdb, 0xc9, 0xc9, 0x47, 0xc6, 0x9d, 0xeb, 0x69, 0xa1, 0xac, 0x92, 0x9e, 0xfc, 0x15, 0x62, 0x5b, 0x9e, 0xd7, 0xcf, 0x1b, 0xc4, 0x23, 0xa8, 0x87, 0x5f, 0x37, 0x80, 0xdd, 0xda, 0x9e, 0xb2, 0xfc, 0xcd, 0x9f, 0xa0, 0x14, 0x62, 0x6a, 0x7f, 0xcf, 0x99, 0x86, 0x49, 0xbc, 0xfa, 0x59, 0x53, 0xa3, 0xc4, 0x3e, 0xfb, 0xcc, 0x38, 0x70, 0x4d, 0x02, 0x49, 0x19, 0xdf, 0x2f, 0xc4, 0xad, 0xea, 0x39, 0xe3, 0x4c, 0xd1, 0x5c, 0xd4, 0xf8, 0x6a, 0xd3, 0xf5, 0x01, 0x01, 0x2f, 0x6b, 0xd2, 0x8a, 0xa5, 0x00, 0x2c, 0x3b, 0x41, 0xba } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.3", + /* Message to be signed */ + 78, + { 0x92, 0xcf, 0x88, 0x0d, 0xa5, 0x89, 0x15, 0xe3, 0xaa, 0x95, 0x08, 0x93, 0x53, 0xe4, 0x61, 0x84, 0xc9, 0x15, 0x94, 0x5c, 0x57, 0x67, 0x9c, 0x1e, 0x4b, 0xd3, 0x82, 0x5e, 0xd9, 0x19, 0xa3, 0x20, 0x52, 0xe9, 0x78, 0x6e, 0x23, 0xb9, 0x42, 0x53, 0x9b, 0x93, 0x15, 0xf5, 0x81, 0xda, 0xf0, 0xb4, 0x1f, 0xa3, 0x26, 0x1b, 0x96, 0x7d, 0xe4, 0x0c, 0xd5, 0xd9, 0x2a, 0x48, 0x24, 0xf3, 0x64, 0xbd, 0x1e, 0x1f, 0x51, 0x84, 0x4b, 0x10, 0x9b, 0x14, 0x54, 0x13, 0x4a, 0xdf, 0x23, 0x4e } +, + /* Signature */ + 129, + { 0x08, 0x82, 0x89, 0x66, 0xac, 0x58, 0x36, 0xc5, 0x13, 0xda, 0x4f, 0xfb, 0x87, 0x61, 0x87, 0x97, 0x94, 0x3c, 0x61, 0x2e, 0xde, 0x7e, 0x12, 0xb3, 0x10, 0x03, 0xef, 0x17, 0x10, 0x65, 0xb4, 0xce, 0xdc, 0x6a, 0x80, 0xb1, 0x45, 0x6c, 0x21, 0xb6, 0x74, 0xb3, 0x77, 0x9a, 0xd3, 0x5f, 0x70, 0x17, 0x7a, 0xa9, 0x2c, 0x6e, 0xac, 0x0b, 0x83, 0x3a, 0x96, 0x7d, 0x7e, 0x98, 0x99, 0x0b, 0x48, 0x24, 0x42, 0x05, 0xdb, 0xf2, 0x6f, 0x5c, 0xd5, 0x7e, 0xf8, 0x7d, 0xc6, 0xfe, 0x5e, 0xd9, 0x99, 0xcf, 0x8c, 0xa7, 0x5d, 0xc8, 0xe6, 0x26, 0xfd, 0x6e, 0xb2, 0x81, 0xc4, 0x99, 0xaf, 0xf7, 0x29, 0x89, 0xed, 0xf5, 0x2e, 0xc6, 0xf3, 0xbc, 0xaf, 0x81, 0xec, 0x5f, 0x8e, 0x82, 0x30, 0xb8, 0x7e, 0xde, 0xdc, 0xf7, 0xb7, 0x78, 0x14, 0x3e, 0xd6, 0xc8, 0xce, 0xbb, 0xac, 0x9d, 0xe5, 0x41, 0x09, 0xdc, 0xf7 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.4", + /* Message to be signed */ + 68, + { 0x87, 0x3c, 0x47, 0x15, 0x90, 0x2f, 0xf1, 0x9d, 0xe0, 0x8b, 0xcc, 0xb0, 0xcf, 0x26, 0x37, 0x63, 0xfa, 0xb0, 0x16, 0xd0, 0x22, 0x0f, 0x03, 0x27, 0xb4, 0x75, 0x5e, 0x35, 0x4e, 0xb2, 0x47, 0xf5, 0xdb, 0xc2, 0xd3, 0x96, 0x98, 0x9b, 0xbd, 0x36, 0xd3, 0x1f, 0x61, 0x98, 0x93, 0x90, 0xca, 0xc1, 0x66, 0x43, 0x12, 0x5e, 0x63, 0xe1, 0xa1, 0xae, 0x1f, 0x1b, 0xc9, 0xbb, 0xed, 0xac, 0xce, 0x67, 0xfc, 0x1b, 0x51, 0xa7 } +, + /* Signature */ + 129, + { 0x05, 0x25, 0x9c, 0x48, 0x15, 0x93, 0xea, 0x86, 0xd1, 0xf0, 0x02, 0xca, 0x58, 0xaa, 0xee, 0x93, 0x29, 0xfa, 0xfe, 0x21, 0x8f, 0x67, 0x50, 0xf0, 0xe5, 0x88, 0xf3, 0x3b, 0x64, 0xe7, 0x08, 0xfb, 0x27, 0xa6, 0xfe, 0x81, 0xeb, 0xca, 0x8a, 0xda, 0xec, 0x75, 0x7a, 0x14, 0xff, 0x55, 0xa0, 0xc8, 0x8a, 0xda, 0x2c, 0x3b, 0x43, 0xe3, 0x9e, 0x8d, 0xfb, 0xe6, 0x76, 0x89, 0x43, 0x65, 0xa2, 0x21, 0x0c, 0x2a, 0xa8, 0x1f, 0x42, 0x4d, 0x85, 0x29, 0xc2, 0x07, 0x6b, 0x00, 0xc9, 0x2d, 0xd8, 0xc8, 0xae, 0x3b, 0x78, 0x0d, 0x87, 0xdb, 0xa7, 0x29, 0xdd, 0xfd, 0xef, 0x7d, 0x40, 0x7f, 0x85, 0x4a, 0x71, 0xcb, 0x68, 0x8b, 0x9f, 0x03, 0xc7, 0x1f, 0x3b, 0xaa, 0x24, 0xa2, 0xa6, 0xe1, 0xcb, 0x41, 0x07, 0x74, 0x30, 0x9e, 0x40, 0xc1, 0x3c, 0x2b, 0x26, 0x47, 0x38, 0xe5, 0x69, 0x7c, 0xfd, 0xde, 0xf3 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.5", + /* Message to be signed */ + 54, + { 0x14, 0xb2, 0x76, 0x02, 0xec, 0xe8, 0xf0, 0x67, 0xb5, 0x84, 0x83, 0xaf, 0x17, 0x77, 0xc4, 0xed, 0x10, 0xb8, 0xb6, 0x4e, 0x64, 0xc6, 0x9f, 0x57, 0xef, 0x88, 0x9a, 0x1c, 0xa5, 0xd5, 0xb5, 0xd6, 0x51, 0xc6, 0x08, 0xdb, 0x23, 0x9d, 0xee, 0xa1, 0x50, 0xff, 0x12, 0xcf, 0x50, 0xc8, 0x67, 0x96, 0x12, 0xf9, 0x7e, 0xcb, 0x09, 0xf7 } +, + /* Signature */ + 129, + { 0x15, 0xc4, 0xb3, 0xf0, 0x81, 0xa2, 0xe5, 0x8a, 0xf5, 0x94, 0xe4, 0x2f, 0xd6, 0xac, 0xcf, 0x1d, 0x0d, 0x61, 0xd9, 0x3a, 0x5e, 0x3a, 0x84, 0xcf, 0x90, 0x4b, 0x98, 0xd9, 0xad, 0x71, 0x33, 0x61, 0xb7, 0x84, 0xb2, 0x4d, 0x92, 0x95, 0xe4, 0x3c, 0x23, 0xbe, 0x93, 0xef, 0x36, 0x51, 0x4a, 0x9b, 0xac, 0x2c, 0x1b, 0xdf, 0x4e, 0xe7, 0x32, 0x34, 0x36, 0x76, 0x3a, 0x20, 0x66, 0x2f, 0x2d, 0xb3, 0x41, 0xd9, 0xe3, 0x8b, 0xed, 0x5f, 0x12, 0xc7, 0xdd, 0x18, 0xbc, 0x3b, 0xb0, 0xfc, 0xba, 0x5c, 0x00, 0x50, 0xbd, 0x1a, 0x2a, 0x44, 0x03, 0x71, 0x97, 0xb8, 0xc9, 0xfc, 0x2a, 0xa5, 0x99, 0xeb, 0x43, 0xc3, 0xd9, 0x67, 0x92, 0x42, 0xc9, 0x9b, 0xbc, 0x49, 0xb0, 0x3b, 0x98, 0xea, 0xca, 0x83, 0x46, 0x28, 0x72, 0x59, 0xe6, 0xea, 0x2e, 0x89, 0x15, 0x5d, 0x0d, 0xd2, 0xb4, 0x77, 0x80, 0x35, 0x75 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.6", + /* Message to be signed */ + 106, + { 0xe5, 0x66, 0xe5, 0xfa, 0x55, 0x6c, 0x76, 0x5b, 0x62, 0xbd, 0x6e, 0x37, 0x45, 0x21, 0xf5, 0x08, 0xfe, 0x44, 0x66, 0x68, 0xc6, 0x47, 0x4b, 0xef, 0x04, 0x6c, 0xc6, 0x89, 0x4a, 0x87, 0x32, 0x2e, 0x19, 0x31, 0xe8, 0x0d, 0x9e, 0xd9, 0xea, 0x80, 0x6b, 0x16, 0x7a, 0x3a, 0xf7, 0x7f, 0xc0, 0x49, 0x38, 0xb5, 0x54, 0x8e, 0xfb, 0xc0, 0x68, 0xd4, 0xf1, 0x96, 0x6a, 0x99, 0x76, 0x25, 0xaf, 0x31, 0xa4, 0x00, 0x7f, 0x06, 0x98, 0xa8, 0x46, 0x9a, 0xb6, 0x81, 0xf4, 0xd5, 0x08, 0xb4, 0xa4, 0x8c, 0x8f, 0xe7, 0x20, 0xcb, 0x5a, 0x94, 0xa7, 0xf4, 0x43, 0xdd, 0x5a, 0x58, 0x03, 0x04, 0x97, 0xda, 0xa9, 0x59, 0xa3, 0xaa, 0xf6, 0xe3, 0x41, 0x84, 0x39, 0x7a } +, + /* Signature */ + 129, + { 0x07, 0xe7, 0xc9, 0x44, 0x26, 0x24, 0xbd, 0x26, 0x6c, 0xc1, 0xcd, 0x1a, 0xf3, 0xb8, 0xf0, 0x62, 0x94, 0xdd, 0xa1, 0xc0, 0x77, 0x67, 0xfe, 0x19, 0xbc, 0xed, 0x6c, 0x9e, 0xd7, 0xc4, 0xb1, 0xed, 0x7f, 0x26, 0xe2, 0x03, 0xdb, 0x7f, 0x3a, 0x1b, 0xfa, 0x57, 0xda, 0xba, 0x6f, 0x3a, 0xa0, 0x60, 0x03, 0xbc, 0xdc, 0x1e, 0x00, 0xc2, 0xd3, 0xd7, 0x6b, 0x9c, 0xbf, 0xf9, 0x68, 0x49, 0xb1, 0xaf, 0xf5, 0x42, 0xd0, 0xd7, 0xaf, 0xc6, 0xe4, 0x22, 0x49, 0x2e, 0xab, 0x0a, 0xb7, 0xf8, 0xe1, 0xd1, 0xae, 0x0b, 0x27, 0x9b, 0x85, 0x19, 0x45, 0xb7, 0x65, 0x85, 0x1b, 0x9f, 0x8a, 0xd8, 0x80, 0xdd, 0x16, 0x4c, 0x11, 0xac, 0x4a, 0x57, 0xf9, 0x6a, 0x0e, 0x48, 0x4b, 0xa1, 0x6a, 0xbf, 0x1c, 0xbe, 0x8a, 0xac, 0x09, 0x0a, 0xdb, 0x6a, 0x71, 0x79, 0x7e, 0x13, 0x35, 0xee, 0xfe, 0x2a, 0xc9, 0x98, 0x0d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.7", + /* Message to be signed */ + 9, + { 0xb4, 0x43, 0xc3, 0x43, 0x52, 0x7b, 0x30, 0xd5, 0xff } +, + /* Signature */ + 129, + { 0x0b, 0x3f, 0x13, 0xc2, 0x72, 0x24, 0xd1, 0x61, 0x01, 0xb9, 0xc8, 0x20, 0x1f, 0x1b, 0x4f, 0x85, 0x37, 0xdb, 0x3c, 0x11, 0x6f, 0x3c, 0xe1, 0x30, 0xbe, 0x0d, 0xe0, 0xdc, 0x0d, 0xd2, 0x0f, 0x77, 0x3c, 0xdf, 0x7b, 0x7f, 0x37, 0x23, 0x87, 0xc4, 0xb6, 0x53, 0xe5, 0xdd, 0x44, 0x21, 0x84, 0x45, 0x74, 0x11, 0xa8, 0x2f, 0x8e, 0xd0, 0x03, 0x66, 0xec, 0xc0, 0x77, 0xa4, 0x26, 0x7c, 0x9d, 0x7e, 0x56, 0x54, 0x96, 0x63, 0x23, 0x9b, 0x43, 0x19, 0xfe, 0x49, 0x9a, 0xa7, 0x89, 0x54, 0x04, 0x9c, 0x74, 0x3b, 0xbf, 0x09, 0xd7, 0x7b, 0x30, 0x29, 0xd9, 0x18, 0xbb, 0x7b, 0x9a, 0x6a, 0xe8, 0x0b, 0x12, 0x9e, 0x41, 0xbb, 0x56, 0xda, 0xd2, 0xb8, 0xa4, 0xb6, 0xf3, 0x19, 0x33, 0x74, 0xc8, 0x29, 0x2f, 0xe0, 0x17, 0xd0, 0x63, 0x34, 0x7e, 0x91, 0xcb, 0xf4, 0xdd, 0x39, 0x39, 0xc2, 0x37, 0xf8, 0x3c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.8", + /* Message to be signed */ + 230, + { 0xdb, 0x90, 0x04, 0x7f, 0x61, 0x5a, 0xd7, 0x19, 0x72, 0xba, 0xed, 0x0c, 0x10, 0x62, 0x6e, 0xc8, 0xcb, 0x18, 0xc6, 0xd7, 0x5e, 0xaa, 0xe0, 0x58, 0x21, 0x9f, 0xd6, 0x19, 0x54, 0x26, 0xd4, 0x4d, 0x5c, 0x54, 0x3b, 0xef, 0x3c, 0x4c, 0x14, 0x98, 0xe8, 0x77, 0xd7, 0xc8, 0x53, 0xe5, 0x31, 0x21, 0xeb, 0x31, 0x57, 0x00, 0x81, 0xd5, 0xde, 0x48, 0x85, 0xcb, 0xc9, 0x25, 0xa6, 0xc2, 0x23, 0x21, 0xcc, 0xc9, 0xc3, 0x78, 0x4e, 0xb2, 0x19, 0xe4, 0x2b, 0x7e, 0xdb, 0x92, 0x88, 0x77, 0x60, 0x73, 0x29, 0x79, 0x8d, 0x55, 0x73, 0x9c, 0x89, 0xd6, 0xd6, 0xb3, 0xf0, 0xd4, 0x30, 0xbb, 0xbc, 0x47, 0x22, 0xea, 0xfa, 0x67, 0xde, 0xfc, 0x86, 0xab, 0xa6, 0xe6, 0x34, 0x83, 0xfd, 0x64, 0x99, 0xb0, 0x3f, 0xab, 0xdc, 0x84, 0x65, 0xd9, 0x8b, 0xbb, 0xe4, 0x40, 0x2b, 0x02, 0x31, 0x13, 0x5c, 0x21, 0x24, 0x3d, 0x7e, 0x02, 0xad, 0x5f, 0x7e, 0x9e, 0x8b, 0x94, 0x60, 0xc1, 0x2d, 0xde, 0x2a, 0x39, 0x5b, 0x45, 0x69, 0x61, 0xcc, 0x3d, 0xfd, 0x9a, 0x12, 0xf5, 0xd9, 0x35, 0x9e, 0x0b, 0x3a, 0x6b, 0xd7, 0x7f, 0x44, 0x65, 0x5b, 0x60, 0x3b, 0x02, 0x55, 0xdb, 0xba, 0xff, 0x8b, 0xc8, 0x40, 0x75, 0x9a, 0x34, 0x62, 0xfe, 0xce, 0x0d, 0x8d, 0xb6, 0xe4, 0x5e, 0x2f, 0xe2, 0xbb, 0xf8, 0xb6, 0xe9, 0x7b, 0x3f, 0xea, 0xc0, 0x79, 0x86, 0x73, 0x82, 0x57, 0xab, 0x9f, 0x8c, 0xfa, 0x79, 0x5a, 0x20, 0x19, 0x2b, 0x5e, 0x2c, 0xea, 0x11, 0x8c, 0xa7, 0x62, 0x25, 0x2a, 0xf6, 0xc6, 0xeb, 0x00, 0xec, 0x5c, 0x68, 0x20, 0xbc, 0xc7, 0xc7 } +, + /* Signature */ + 129, + { 0x00, 0xaa, 0xb0, 0x67, 0xd3, 0xa8, 0x63, 0x3d, 0x0b, 0xeb, 0xd5, 0x91, 0xed, 0x34, 0xd0, 0x67, 0xf4, 0x71, 0x8c, 0xd7, 0xf9, 0xb1, 0xe3, 0x5a, 0xaa, 0x40, 0x5d, 0xa1, 0x22, 0x2a, 0xb9, 0x40, 0x38, 0x66, 0x92, 0x1f, 0xbd, 0x05, 0x74, 0x33, 0x40, 0x7a, 0x4a, 0xae, 0x7e, 0x26, 0xc5, 0xcf, 0xa0, 0xbc, 0x9c, 0x11, 0x57, 0x05, 0x7b, 0x1d, 0xa1, 0xcf, 0x36, 0x28, 0x51, 0x87, 0x19, 0xa6, 0x03, 0xf6, 0xc3, 0xc4, 0xde, 0xa3, 0x0b, 0xf4, 0x9d, 0xb9, 0xb0, 0x68, 0xaf, 0xec, 0x69, 0x81, 0x21, 0xdc, 0xe5, 0xd6, 0x0d, 0x93, 0xa6, 0xf5, 0x63, 0x3f, 0xc6, 0xaf, 0x9d, 0xf4, 0xc5, 0xdc, 0xcc, 0x13, 0x8c, 0x29, 0x4e, 0xdd, 0x42, 0x9d, 0x4a, 0xfe, 0x3b, 0x33, 0x78, 0x86, 0x82, 0x55, 0xcc, 0x53, 0x78, 0x8c, 0xf2, 0xb4, 0x77, 0x45, 0xd6, 0x4a, 0xcd, 0x88, 0x5b, 0xb4, 0x7d, 0x2e, 0xec } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.9", + /* Message to be signed */ + 160, + { 0x2b, 0xe0, 0x06, 0x7b, 0x95, 0x18, 0x5b, 0xad, 0xe1, 0x18, 0xdc, 0xe9, 0x5c, 0x57, 0x02, 0x9b, 0x55, 0x4b, 0x25, 0xe1, 0xc3, 0x95, 0x19, 0xf8, 0xf8, 0x90, 0x73, 0xb9, 0xa0, 0x4b, 0x7e, 0x91, 0x29, 0x9c, 0xdb, 0x87, 0xb0, 0xbd, 0x17, 0xc9, 0xf1, 0x51, 0x92, 0x5c, 0x75, 0x6e, 0xb9, 0xb6, 0x45, 0x07, 0x25, 0x61, 0x26, 0x41, 0x07, 0x88, 0x21, 0x38, 0x85, 0x4a, 0xe7, 0xd5, 0x07, 0xe1, 0x5f, 0xcf, 0xe8, 0x47, 0x09, 0x45, 0x40, 0xe7, 0x1a, 0x54, 0x7f, 0x63, 0xb5, 0x90, 0x46, 0x7f, 0xad, 0xff, 0x64, 0x7f, 0x64, 0x3e, 0x1c, 0xec, 0x11, 0x24, 0x65, 0x29, 0x06, 0x2c, 0x9e, 0x40, 0x88, 0x92, 0xf2, 0xa2, 0x0c, 0xcc, 0xc0, 0xae, 0x45, 0xca, 0x97, 0xa4, 0x7f, 0xca, 0xdc, 0x8f, 0xed, 0xe2, 0x1a, 0x24, 0x71, 0x11, 0x67, 0x70, 0x6c, 0xc4, 0xb5, 0xd6, 0x94, 0x77, 0xe5, 0xa8, 0xa1, 0x46, 0xb9, 0x60, 0xcd, 0x4b, 0x17, 0x27, 0x42, 0x7b, 0x16, 0x51, 0x7b, 0x63, 0xeb, 0xfb, 0xcf, 0x84, 0xd0, 0xb1, 0xac, 0x8e, 0x7e, 0x70, 0xf0, 0x44, 0x35, 0x75, 0x22, 0xb1, 0xd0, 0xcb } +, + /* Signature */ + 129, + { 0x09, 0x76, 0x81, 0x12, 0x17, 0x71, 0x45, 0x44, 0x41, 0x01, 0x33, 0x24, 0x3b, 0xeb, 0xa9, 0xa2, 0x1a, 0x6f, 0x72, 0x12, 0xc6, 0x87, 0x91, 0x5c, 0x72, 0x02, 0x7b, 0xba, 0x31, 0x12, 0xf6, 0x97, 0x05, 0x42, 0x5c, 0xb9, 0x94, 0xcb, 0xb6, 0xd3, 0x59, 0xc1, 0x46, 0xb9, 0x5d, 0xb1, 0x44, 0x64, 0x35, 0xd4, 0xcf, 0x96, 0x1d, 0xfd, 0x5c, 0x49, 0x87, 0x39, 0xbf, 0xd4, 0xbe, 0x6e, 0xf1, 0xad, 0xd7, 0x4b, 0x81, 0xb2, 0x89, 0x8a, 0x4c, 0xe4, 0x3d, 0xc3, 0x7c, 0xb0, 0xe9, 0xed, 0x77, 0x44, 0xcf, 0x40, 0x9b, 0xab, 0xff, 0x71, 0x78, 0x85, 0x42, 0xff, 0xd2, 0x86, 0xeb, 0xe5, 0x25, 0x5d, 0x63, 0xdd, 0x7b, 0xd5, 0x5b, 0xa4, 0x3f, 0x51, 0x84, 0xe2, 0x48, 0xd3, 0xa6, 0x69, 0x33, 0xcd, 0xb0, 0x69, 0x91, 0xec, 0xc9, 0x0e, 0xb3, 0x9e, 0xe7, 0x1d, 0x65, 0xc8, 0x8e, 0xd2, 0x4d, 0x94, 0x4c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.10", + /* Message to be signed */ + 222, + { 0xa7, 0x90, 0xe6, 0xac, 0x5d, 0x55, 0x6f, 0xb7, 0xcf, 0x44, 0x46, 0x0c, 0x7b, 0x9b, 0xe5, 0xeb, 0x7f, 0x24, 0xf9, 0x87, 0xff, 0x89, 0x0d, 0xcb, 0x78, 0x40, 0x24, 0x1d, 0x45, 0x54, 0x5b, 0x71, 0x05, 0x63, 0x5a, 0x1a, 0xaf, 0x44, 0x57, 0xe6, 0x41, 0x0c, 0x65, 0xae, 0xce, 0x50, 0x11, 0xe2, 0x77, 0x5e, 0xc8, 0x53, 0x0a, 0x64, 0xa1, 0x88, 0x39, 0xe9, 0xc5, 0x8a, 0x7b, 0x77, 0x42, 0x4f, 0x74, 0x29, 0x3d, 0xcb, 0x9e, 0x9e, 0xa8, 0x73, 0x6d, 0x6b, 0xa5, 0x8b, 0x1c, 0x66, 0x53, 0xd5, 0x7b, 0xea, 0xab, 0x98, 0x73, 0x5f, 0x7a, 0xf7, 0x32, 0x47, 0x7b, 0x9a, 0xf6, 0xa3, 0x3f, 0xf0, 0x75, 0xc7, 0xe4, 0x66, 0x39, 0xd7, 0x48, 0x55, 0x08, 0x20, 0xba, 0x6a, 0xbd, 0x4a, 0x9d, 0x48, 0xcb, 0x49, 0x03, 0xf6, 0x5b, 0x76, 0xf8, 0x14, 0xc6, 0xcd, 0xc9, 0x5e, 0x8d, 0x9e, 0x87, 0x0c, 0x24, 0x4a, 0x02, 0x9b, 0x29, 0x4a, 0x8a, 0x5c, 0x82, 0x6a, 0xb1, 0x61, 0xf6, 0xf9, 0x78, 0xd9, 0xf1, 0xc0, 0x3f, 0xcd, 0xda, 0xae, 0xfb, 0xfa, 0xdb, 0x8c, 0xaa, 0xe8, 0x4b, 0xc2, 0xdd, 0x33, 0x2e, 0xb0, 0x49, 0x97, 0xd6, 0x1e, 0xfa, 0x91, 0xe9, 0x24, 0x1e, 0x4c, 0xcd, 0x97, 0x64, 0xc7, 0x26, 0xe7, 0x66, 0xed, 0x3b, 0x03, 0x38, 0xd0, 0x86, 0xf1, 0x03, 0x2c, 0x15, 0x33, 0xef, 0x59, 0x3f, 0x88, 0xfd, 0x56, 0x03, 0x37, 0x91, 0xb1, 0xd0, 0x62, 0x5c, 0x6c, 0xa5, 0x1e, 0xec, 0x27, 0x9c, 0xfb, 0x6a, 0xe3, 0xf1, 0x27, 0x00, 0xcf, 0x5b, 0xac, 0x27, 0x1e, 0x65, 0x67 } +, + /* Signature */ + 129, + { 0x0d, 0x1b, 0x11, 0x1c, 0xe8, 0xde, 0x1d, 0x7c, 0x4f, 0x7f, 0xce, 0xac, 0x73, 0xdf, 0x70, 0xaa, 0x6e, 0xda, 0x58, 0xdc, 0x32, 0xeb, 0x98, 0xf7, 0x8e, 0x7f, 0xb9, 0xbc, 0x25, 0xde, 0x3e, 0x6b, 0x09, 0xab, 0x8c, 0xae, 0x3b, 0x20, 0x26, 0xb6, 0x18, 0x7f, 0xf6, 0x36, 0x72, 0xe5, 0x7d, 0xa4, 0xac, 0x28, 0x96, 0x24, 0x45, 0xd1, 0xfe, 0x95, 0x1d, 0x27, 0xbe, 0x6a, 0x6c, 0xe7, 0xa5, 0x80, 0x7e, 0x13, 0x76, 0x13, 0x94, 0x46, 0xe8, 0x54, 0x9d, 0x48, 0xaa, 0x59, 0xfc, 0x22, 0x33, 0x54, 0xd1, 0x21, 0xfd, 0xcc, 0x38, 0xf1, 0xd0, 0x27, 0x5e, 0x41, 0x86, 0x92, 0x27, 0x00, 0xad, 0xc6, 0x1d, 0xae, 0x1e, 0x4b, 0xe8, 0x05, 0x22, 0x2a, 0x1c, 0xf0, 0x7f, 0x11, 0x0a, 0x61, 0x58, 0xa2, 0xa2, 0x62, 0x58, 0xf1, 0x9c, 0x65, 0x7a, 0x11, 0x0c, 0x0d, 0x9a, 0xd2, 0x91, 0x68, 0x0c, 0x75, 0x96 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.11", + /* Message to be signed */ + 256, + { 0x32, 0xaf, 0xd1, 0x3e, 0x60, 0x7d, 0x87, 0xb2, 0x5f, 0xf4, 0x0a, 0x88, 0x5b, 0x25, 0x09, 0xf5, 0x21, 0xf2, 0xa0, 0xa7, 0x72, 0xa9, 0x6a, 0x39, 0xfb, 0x3f, 0x71, 0xc9, 0x63, 0x84, 0xb3, 0xd7, 0x57, 0x8f, 0x48, 0xfc, 0xea, 0x97, 0x39, 0x56, 0x0a, 0x65, 0xbf, 0xb4, 0x83, 0xd9, 0x60, 0x8d, 0x20, 0x25, 0x55, 0xf6, 0x6d, 0x61, 0x2d, 0x16, 0xb9, 0x25, 0x53, 0x87, 0xb4, 0xe1, 0x12, 0x41, 0x15, 0xed, 0x48, 0xbf, 0xef, 0x8b, 0x89, 0xd8, 0xdd, 0xfc, 0x21, 0x9c, 0xcc, 0xe4, 0x87, 0x86, 0xc9, 0xe6, 0x42, 0x6a, 0x92, 0x12, 0xe7, 0xb1, 0x6d, 0x97, 0x1d, 0x27, 0x8a, 0x11, 0x18, 0xf2, 0xf8, 0x6b, 0x9c, 0x4b, 0xbf, 0x75, 0xc9, 0xc2, 0xd0, 0x99, 0xe3, 0xf6, 0x65, 0x48, 0xf1, 0xf4, 0xa8, 0xa8, 0x21, 0xd7, 0x27, 0x44, 0x98, 0xf7, 0xcc, 0xe6, 0xec, 0x5e, 0x2b, 0xf2, 0xbf, 0xad, 0x2c, 0x6f, 0xc0, 0x05, 0xe8, 0x0a, 0x48, 0xca, 0xe4, 0x69, 0x92, 0xfc, 0x82, 0x67, 0xa6, 0x48, 0x0a, 0xcb, 0x89, 0x4c, 0xcc, 0x9b, 0x62, 0x09, 0x5c, 0xad, 0x97, 0xdb, 0x70, 0xd8, 0x82, 0xa1, 0x3f, 0xb3, 0x85, 0x88, 0xc4, 0x8c, 0xa1, 0x90, 0xf1, 0x80, 0xcb, 0x3e, 0x61, 0xac, 0xb4, 0xe2, 0xcf, 0xd9, 0xcd, 0xbf, 0x85, 0x5c, 0x53, 0x99, 0x21, 0xf6, 0x8e, 0x11, 0x49, 0xd0, 0x54, 0x7e, 0xf5, 0x9a, 0xf5, 0x37, 0x92, 0xdc, 0x66, 0x0d, 0xa5, 0xef, 0x48, 0xa7, 0xab, 0x89, 0x36, 0xd3, 0xd3, 0x6e, 0xd6, 0xb6, 0x46, 0x9e, 0xb6, 0xfd, 0x95, 0xe3, 0xaf, 0x18, 0x2c, 0x87, 0x68, 0xfa, 0x60, 0x04, 0x78, 0x54, 0xf1, 0x8f, 0x37, 0x41, 0xc1, 0x88, 0x3b, 0xb0, 0x79, 0x26, 0x88, 0xca, 0xdb, 0x9e, 0x4d, 0xf3, 0x91, 0xd9, 0x11, 0x45, 0xb8, 0x5e, 0x2a, 0xe2, 0x4f, 0xfd, 0xfe, 0x51 } +, + /* Signature */ + 129, + { 0x01, 0xa9, 0x37, 0xb3, 0xcc, 0x82, 0x54, 0xd5, 0x15, 0x08, 0x70, 0x9e, 0x4a, 0x4d, 0xe7, 0xb1, 0x81, 0xde, 0xd9, 0xa4, 0x47, 0xb3, 0xec, 0x8d, 0xad, 0x49, 0x2c, 0x39, 0x79, 0x52, 0xdf, 0x7c, 0x55, 0x0e, 0x4b, 0x26, 0xc9, 0x50, 0x17, 0x29, 0x9d, 0x8d, 0x45, 0x5f, 0xf7, 0x97, 0x1c, 0x33, 0x8c, 0xd0, 0x14, 0xdf, 0x78, 0xe2, 0xa8, 0xaa, 0x5e, 0xbe, 0xe2, 0x58, 0xf4, 0x92, 0x53, 0xd5, 0x1a, 0xce, 0x9a, 0x49, 0x31, 0x9f, 0xfc, 0x80, 0x7a, 0xd7, 0x0b, 0x2d, 0xf2, 0xc9, 0x6d, 0xcd, 0xb7, 0x3b, 0x48, 0xac, 0xbc, 0x4f, 0x6c, 0x3c, 0x2a, 0x70, 0x1e, 0x7c, 0x15, 0x4b, 0x27, 0x9b, 0x07, 0x05, 0xbd, 0xf2, 0x54, 0x8c, 0x8b, 0x36, 0x11, 0xb9, 0x7d, 0xa1, 0xac, 0x09, 0xcd, 0x12, 0x12, 0x50, 0x99, 0x54, 0x0b, 0xf7, 0xba, 0x99, 0xb0, 0x8c, 0x2f, 0x3d, 0x5f, 0x6a, 0xea, 0x7d, 0x40 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.12", + /* Message to be signed */ + 162, + { 0x5b, 0x00, 0xb8, 0xb7, 0x94, 0xa1, 0x0d, 0x21, 0xf1, 0xb4, 0x5e, 0xca, 0xa2, 0x0d, 0xf7, 0xc5, 0xb3, 0x52, 0x2c, 0x1b, 0x1d, 0xb4, 0xb0, 0x84, 0xb9, 0x59, 0xaa, 0x4e, 0x56, 0x58, 0xac, 0x54, 0x68, 0xf6, 0xe8, 0xfb, 0x61, 0x2f, 0xf9, 0x9f, 0x32, 0x16, 0xb5, 0xd2, 0x1c, 0xb4, 0xac, 0xc0, 0xbb, 0x42, 0xee, 0xfd, 0xb8, 0xe8, 0x2d, 0x75, 0x4b, 0x85, 0xd0, 0x97, 0x45, 0x89, 0x4a, 0x52, 0x3c, 0x01, 0x62, 0xd0, 0x8e, 0xcc, 0xe4, 0x8b, 0x99, 0xdd, 0x6c, 0x38, 0xe2, 0xbd, 0x3d, 0x53, 0x1c, 0x85, 0x62, 0xde, 0xec, 0xfc, 0x61, 0x52, 0x36, 0x9a, 0xac, 0xf5, 0x80, 0xea, 0xf9, 0xdb, 0x6c, 0x68, 0xb6, 0x9d, 0xf2, 0xfb, 0xf3, 0x05, 0x3f, 0x60, 0x1f, 0x70, 0x02, 0x2c, 0x9e, 0x38, 0x1d, 0xfb, 0xc5, 0x90, 0x99, 0xc3, 0x7b, 0xde, 0x5a, 0xd8, 0x9a, 0x8c, 0xc1, 0xef, 0xe4, 0xc7, 0xb7, 0xd7, 0x8e, 0x90, 0x97, 0xe0, 0x81, 0x21, 0xed, 0xa6, 0x4a, 0xc4, 0x5c, 0x32, 0x7e, 0x5e, 0xda, 0xf9, 0x22, 0xd3, 0xc3, 0x5f, 0x88, 0xb5, 0x2c, 0x93, 0xd3, 0x99, 0xf4, 0xc2, 0x38, 0x36, 0x2f, 0xe9 } +, + /* Signature */ + 129, + { 0x0f, 0xc6, 0xac, 0x1d, 0x42, 0x94, 0x79, 0x38, 0xcd, 0x25, 0x86, 0xd0, 0xe7, 0xfc, 0x3a, 0x05, 0x42, 0xb9, 0xaf, 0x12, 0xd3, 0x6e, 0xeb, 0xf9, 0x2b, 0x5d, 0x04, 0x9c, 0x79, 0x65, 0xb1, 0x1b, 0xa9, 0xcc, 0xbf, 0x47, 0x00, 0xf3, 0x45, 0x60, 0x91, 0x11, 0x77, 0xb9, 0xd1, 0x29, 0x6f, 0x1c, 0x68, 0xe3, 0xaf, 0x46, 0x9f, 0x4f, 0x39, 0x9d, 0xbc, 0x18, 0x9c, 0x23, 0xea, 0x74, 0x65, 0x98, 0x28, 0x13, 0x32, 0x33, 0x05, 0xed, 0x6c, 0x35, 0xff, 0x9c, 0xc1, 0x09, 0xd0, 0xa2, 0x30, 0x3f, 0xe7, 0xd3, 0x29, 0xca, 0x31, 0x7e, 0xc4, 0xb1, 0x8e, 0xdd, 0x19, 0xc6, 0x2c, 0x60, 0xa3, 0xc8, 0xc3, 0x10, 0x6f, 0x86, 0xdb, 0xd0, 0x72, 0xe3, 0xe1, 0xeb, 0x87, 0x85, 0x28, 0x8c, 0x21, 0xab, 0xca, 0xc2, 0x2e, 0x0c, 0x0d, 0x41, 0xf4, 0xe2, 0x3e, 0x7f, 0x39, 0x4d, 0x46, 0x82, 0xf6, 0xce, 0x87 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.13", + /* Message to be signed */ + 26, + { 0xb7, 0x50, 0xae, 0x6d, 0x4d, 0x2c, 0xeb, 0x92, 0x14, 0x05, 0x34, 0x64, 0x8d, 0x36, 0xef, 0x25, 0xe4, 0x51, 0x55, 0xf5, 0x2b, 0xde, 0x1b, 0xf2, 0x6a, 0xb7 } +, + /* Signature */ + 129, + { 0x16, 0xaa, 0xde, 0xdc, 0xa0, 0x9e, 0x06, 0x25, 0x60, 0xc6, 0x61, 0xd2, 0xa4, 0x9b, 0x0e, 0xe4, 0xd9, 0xce, 0x23, 0x90, 0x7c, 0x69, 0xd1, 0x00, 0x04, 0xf1, 0x49, 0xd1, 0x03, 0xc5, 0x9c, 0x16, 0xfe, 0x7d, 0x43, 0x73, 0x59, 0x7d, 0xb9, 0xff, 0xd8, 0x92, 0x3a, 0x77, 0xa6, 0xb9, 0x43, 0xb1, 0x88, 0xc4, 0x74, 0x25, 0xe2, 0xa9, 0xe5, 0x30, 0x41, 0x3e, 0xfd, 0xb6, 0x84, 0x8d, 0xd3, 0x42, 0x0b, 0xa5, 0x3e, 0xf8, 0x1c, 0x25, 0xc5, 0x78, 0xf8, 0xd9, 0x51, 0x4d, 0x93, 0xfc, 0xc9, 0xcb, 0x1f, 0xb5, 0x2f, 0x58, 0xd8, 0x8a, 0x57, 0xd1, 0xfd, 0x3f, 0xe2, 0x2d, 0xa3, 0x10, 0xec, 0xea, 0x9e, 0xce, 0x55, 0xe9, 0x60, 0x8d, 0x63, 0xae, 0x21, 0xdb, 0xae, 0xa6, 0x57, 0x1b, 0x78, 0xfc, 0xfd, 0xd2, 0x71, 0xbb, 0x65, 0x92, 0x57, 0x47, 0x6b, 0x59, 0x95, 0x68, 0x7a, 0x02, 0xbb, 0xe7, 0x89 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.14", + /* Message to be signed */ + 183, + { 0x47, 0xbe, 0x01, 0x02, 0x0e, 0xb7, 0xe7, 0x87, 0x5b, 0xd4, 0xfc, 0xc0, 0x05, 0xa8, 0x2b, 0x36, 0xfd, 0xf2, 0x14, 0x5e, 0xf1, 0x32, 0xe2, 0xed, 0x16, 0x2f, 0xf6, 0x94, 0xbc, 0x71, 0x58, 0x9c, 0x7d, 0xc6, 0xd5, 0xa3, 0xf8, 0x9d, 0x59, 0x7f, 0x2d, 0x2a, 0xa3, 0x43, 0x33, 0x51, 0x18, 0xf6, 0xfd, 0xbd, 0xee, 0xf2, 0x3e, 0x61, 0x3c, 0xba, 0xcc, 0xde, 0x41, 0x95, 0xe6, 0x64, 0xa0, 0x09, 0x4b, 0x07, 0xfc, 0x0a, 0x32, 0x84, 0x8d, 0x61, 0x39, 0x03, 0x1c, 0xf5, 0x72, 0xa1, 0xe3, 0x23, 0xc5, 0xa7, 0x07, 0xb6, 0xfa, 0x2a, 0xee, 0xf2, 0xdc, 0x87, 0x2d, 0xd5, 0xa3, 0xe7, 0x6b, 0x13, 0xf8, 0xef, 0x94, 0xad, 0xeb, 0xd4, 0xe2, 0x05, 0x74, 0x8e, 0x48, 0x5b, 0x40, 0x01, 0xd5, 0xd2, 0xa0, 0x90, 0xb8, 0x9b, 0x2e, 0x64, 0x74, 0xc4, 0x79, 0xe7, 0xb0, 0x0d, 0x2d, 0x57, 0xf5, 0x86, 0xab, 0x76, 0xb8, 0x0f, 0x79, 0x5b, 0xa8, 0x99, 0x62, 0x88, 0x29, 0x2c, 0x3f, 0x2c, 0xa5, 0x1a, 0x44, 0xe4, 0xe8, 0x41, 0xc0, 0x37, 0x07, 0xe4, 0x80, 0x25, 0xaf, 0x4b, 0xfd, 0x0a, 0xb6, 0xef, 0xeb, 0x83, 0x62, 0xed, 0xd5, 0xd2, 0x34, 0x05, 0xba, 0x0e, 0x23, 0x1b, 0x33, 0x24, 0xe1, 0xca, 0x3c, 0x5d, 0x63, 0x9d, 0x2c, 0x9d, 0x82 } +, + /* Signature */ + 129, + { 0x06, 0x39, 0x17, 0x92, 0x9b, 0xbb, 0x20, 0x92, 0x17, 0xff, 0x48, 0xed, 0x4f, 0x55, 0xd0, 0x7a, 0x03, 0xf7, 0x6d, 0x6d, 0x94, 0x04, 0x8b, 0x6f, 0x71, 0x31, 0x0b, 0x2c, 0x96, 0xe2, 0x14, 0xab, 0x22, 0x0d, 0x4e, 0x45, 0xac, 0x01, 0xc9, 0x3d, 0xcc, 0x8a, 0x5c, 0x26, 0xa0, 0x2d, 0xf6, 0x1f, 0xfd, 0xb3, 0x17, 0x54, 0x96, 0x65, 0x61, 0x0c, 0x84, 0xbd, 0xb8, 0x94, 0x5f, 0xc6, 0xbb, 0xd3, 0x8b, 0xae, 0xd7, 0xfe, 0xe9, 0x8e, 0xb0, 0x56, 0xd9, 0xf0, 0x39, 0xa8, 0x60, 0xd4, 0x52, 0xb3, 0xac, 0xac, 0x18, 0x00, 0xa9, 0x32, 0xa2, 0x8c, 0x88, 0x28, 0x6a, 0xbd, 0xa8, 0xde, 0x3c, 0xb6, 0xc0, 0xd7, 0x94, 0xda, 0xab, 0x7a, 0x8b, 0xa0, 0x11, 0x09, 0x33, 0xb4, 0xd1, 0xde, 0xd2, 0x39, 0xcb, 0xdd, 0x55, 0x7d, 0x3e, 0x5a, 0x16, 0x29, 0x17, 0x85, 0x33, 0x15, 0xde, 0x68, 0x09, 0x00, 0xa8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.15", + /* Message to be signed */ + 238, + { 0x4b, 0x9c, 0x09, 0x64, 0x48, 0x10, 0xd4, 0xb3, 0x06, 0x55, 0xed, 0x83, 0x38, 0xbb, 0x27, 0x6b, 0x62, 0x4c, 0x68, 0x01, 0x98, 0x22, 0xd1, 0xfc, 0x8f, 0x78, 0x86, 0x1e, 0x13, 0xe2, 0x2a, 0xc1, 0x71, 0x82, 0x1c, 0xfd, 0xbd, 0x3f, 0x8f, 0x5b, 0x8d, 0xc9, 0xc0, 0xde, 0x73, 0x2b, 0x74, 0x6e, 0x1d, 0x13, 0x2e, 0x5f, 0x3f, 0x14, 0x9a, 0x5a, 0x86, 0x7c, 0x2e, 0xe4, 0x78, 0xe8, 0xf1, 0x4a, 0xd4, 0xb9, 0xdd, 0xeb, 0xd3, 0xae, 0x78, 0x17, 0xe8, 0x49, 0x55, 0xb3, 0x40, 0x4b, 0x09, 0x43, 0x93, 0xe6, 0x1c, 0xa0, 0x18, 0x9d, 0x05, 0x53, 0x69, 0xb4, 0x24, 0x30, 0x09, 0xa0, 0xf5, 0x40, 0x3f, 0x41, 0xc1, 0x00, 0x23, 0x08, 0xc0, 0x0c, 0xe6, 0x99, 0x67, 0x19, 0x37, 0xba, 0xf1, 0x3c, 0x78, 0x93, 0xd6, 0x63, 0xc9, 0x47, 0xfc, 0x7f, 0x84, 0x07, 0x1a, 0x67, 0x2e, 0x5e, 0x07, 0x37, 0x8a, 0xac, 0x08, 0xb3, 0xfa, 0xf0, 0xfc, 0xcf, 0x5b, 0xf2, 0x83, 0x09, 0x25, 0x85, 0xeb, 0xe2, 0x40, 0xa3, 0x00, 0x46, 0x20, 0xb6, 0xf3, 0xae, 0xb6, 0x73, 0x2b, 0x7b, 0x9d, 0x8d, 0x3b, 0xea, 0xfc, 0x84, 0x67, 0xd1, 0xf1, 0xf1, 0xc7, 0xda, 0x66, 0xb1, 0xbf, 0x5c, 0xcc, 0x14, 0x5b, 0x32, 0x24, 0x24, 0x5f, 0xae, 0x31, 0xdf, 0xb4, 0x03, 0xf4, 0x93, 0xc0, 0x75, 0x53, 0x57, 0xad, 0xd7, 0xcb, 0x27, 0x63, 0x71, 0x32, 0x26, 0xc5, 0x4f, 0x43, 0x64, 0x0f, 0x7a, 0x67, 0x0e, 0xb7, 0xb1, 0xf6, 0xe9, 0xe7, 0x72, 0xf2, 0xe5, 0x14, 0x17, 0xa7, 0x05, 0xcf, 0xc5, 0x87, 0x3f, 0xfb, 0x88, 0xa5, 0xdb, 0x07, 0xec, 0xc4, 0xee, 0x89, 0xf3, 0x30, 0xa6, 0x69, 0x0a, 0x88, 0x12 } +, + /* Signature */ + 129, + { 0x1a, 0x0b, 0x69, 0x8c, 0xf3, 0xa0, 0x58, 0xb4, 0x49, 0x19, 0xaf, 0x73, 0xc3, 0xde, 0x32, 0x8e, 0x86, 0xce, 0x9a, 0x5d, 0x49, 0x99, 0xe0, 0x12, 0x2f, 0x41, 0x4b, 0x94, 0xf3, 0x2b, 0x2d, 0x8a, 0xb1, 0xe6, 0x55, 0x0c, 0xc0, 0xd4, 0x8d, 0xc0, 0x4b, 0xef, 0xac, 0x2c, 0x67, 0xa4, 0xd0, 0x69, 0xa7, 0x20, 0x8f, 0x14, 0x2d, 0xc2, 0x67, 0xb3, 0xe3, 0x8f, 0x63, 0x38, 0xa0, 0xb1, 0x83, 0x9a, 0x93, 0xa8, 0x36, 0x80, 0x7d, 0x18, 0x1e, 0x3f, 0x0c, 0x7e, 0x87, 0x7f, 0xb2, 0x42, 0x16, 0x02, 0x00, 0x5b, 0xca, 0x25, 0xa9, 0xc3, 0x72, 0x26, 0x6d, 0x18, 0xe6, 0xd5, 0x00, 0xc5, 0xc7, 0xab, 0x13, 0x38, 0x52, 0x83, 0xd2, 0xaf, 0x91, 0x9d, 0x0b, 0xba, 0x0d, 0xcb, 0x88, 0xbf, 0x7b, 0xb9, 0x97, 0x2d, 0x67, 0x00, 0x8f, 0xf4, 0x98, 0x54, 0x7d, 0x80, 0xfc, 0xa6, 0x58, 0xef, 0xe7, 0x64, 0xa5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.16", + /* Message to be signed */ + 216, + { 0xec, 0x9f, 0xf1, 0x4b, 0x9f, 0x19, 0x7a, 0x2b, 0x4f, 0x24, 0x94, 0x8c, 0x29, 0xd2, 0xf6, 0x4a, 0x64, 0x62, 0x52, 0x23, 0xdd, 0xb8, 0x53, 0x46, 0x37, 0x8c, 0x2c, 0x25, 0x34, 0x3f, 0xcb, 0xef, 0x58, 0x5a, 0x99, 0xe1, 0xec, 0x0b, 0xef, 0x0e, 0xf9, 0xd0, 0x9e, 0xad, 0x85, 0xbe, 0xe1, 0xc4, 0xbf, 0xb3, 0x5e, 0x48, 0xfb, 0x26, 0x41, 0x1b, 0xdf, 0x18, 0x0d, 0xc5, 0xcf, 0x31, 0x7b, 0x3a, 0x34, 0x83, 0x71, 0xc7, 0xc5, 0xf4, 0xaa, 0x6d, 0x59, 0x08, 0xfc, 0xfc, 0x1e, 0xa3, 0x90, 0x18, 0xcf, 0x04, 0x49, 0xe5, 0x5f, 0x4e, 0xf9, 0x94, 0xbf, 0xda, 0x40, 0x4f, 0x1c, 0x18, 0x9f, 0xdb, 0x8a, 0x0a, 0x5b, 0x09, 0x06, 0xc3, 0xd4, 0x0d, 0xe1, 0xe7, 0x87, 0xc2, 0xdb, 0x4d, 0x88, 0xdb, 0xc2, 0x10, 0xb9, 0xf8, 0x01, 0xf4, 0xcd, 0x9c, 0x97, 0x22, 0x7e, 0x9b, 0x2f, 0xbc, 0x28, 0x11, 0xe3, 0x8c, 0xed, 0xd9, 0xe9, 0xf0, 0x35, 0x60, 0x03, 0x1d, 0x4c, 0x95, 0x8a, 0x76, 0x81, 0xba, 0x9d, 0x7e, 0xa5, 0xe7, 0x8e, 0x9b, 0xd8, 0xbd, 0xed, 0xdb, 0x41, 0x56, 0x79, 0x0e, 0xf2, 0x1f, 0xb7, 0x4f, 0xbc, 0x41, 0x58, 0xc2, 0x93, 0x9e, 0x4e, 0xfc, 0xb8, 0x2e, 0xfd, 0xc8, 0x81, 0x88, 0x6a, 0x5b, 0x67, 0x13, 0xa2, 0x4b, 0x9b, 0x5f, 0x2e, 0xe2, 0x5c, 0xcf, 0x72, 0x1a, 0x64, 0xe0, 0xf6, 0x40, 0x77, 0x8e, 0xcb, 0x3d, 0x35, 0xb4, 0xb8, 0xee, 0xa8, 0xec, 0xe3, 0x12, 0x32, 0x63, 0x63, 0x10, 0xae, 0x3c, 0xc6, 0xb8, 0x2b, 0x8a } +, + /* Signature */ + 129, + { 0x01, 0x3b, 0x42, 0x05, 0x78, 0x20, 0xc7, 0x3e, 0x3a, 0xcf, 0xc1, 0xdf, 0x4d, 0xe1, 0x44, 0x0c, 0x65, 0x8e, 0x01, 0x80, 0x43, 0x6d, 0xa7, 0x18, 0x5a, 0x9f, 0xab, 0xd2, 0x6e, 0xb3, 0x26, 0x74, 0xb5, 0x54, 0xde, 0x35, 0x4d, 0x1f, 0x4f, 0x24, 0xe8, 0x77, 0x73, 0x26, 0x7f, 0xed, 0x9d, 0xd0, 0xfd, 0x82, 0x93, 0xea, 0xca, 0x4a, 0xf3, 0xd3, 0xa9, 0xdc, 0x51, 0x8c, 0x8e, 0x49, 0x5a, 0x14, 0x76, 0x95, 0x11, 0x1d, 0x3d, 0xc1, 0x77, 0x63, 0xf1, 0xf0, 0x2e, 0xec, 0x1e, 0xe2, 0x9f, 0xb1, 0xab, 0x74, 0x9c, 0xf3, 0x0c, 0x78, 0x86, 0xda, 0x8b, 0x2f, 0x64, 0x69, 0x69, 0x59, 0x8a, 0xa7, 0x0f, 0x9a, 0x92, 0xfa, 0x4f, 0x93, 0x5c, 0x7c, 0xc7, 0x7b, 0xfa, 0xb6, 0x98, 0x1f, 0x0d, 0xf0, 0xd2, 0x85, 0xcf, 0xb1, 0x0d, 0x66, 0x58, 0x15, 0x39, 0xf7, 0x8d, 0x03, 0x68, 0xed, 0x4f, 0x93, 0x01 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.17", + /* Message to be signed */ + 209, + { 0x41, 0x4c, 0xea, 0x8e, 0xec, 0x6d, 0xa3, 0xc6, 0x6f, 0xfc, 0x84, 0x70, 0xf7, 0xe1, 0x47, 0x60, 0xf7, 0x4b, 0xf6, 0xe7, 0x5b, 0x84, 0xdc, 0x98, 0xfc, 0x80, 0x60, 0xdd, 0x3c, 0x21, 0x9e, 0x76, 0x77, 0x7d, 0xfa, 0xba, 0xa6, 0xe6, 0xb9, 0x29, 0x55, 0x37, 0x9f, 0x3e, 0xca, 0xaf, 0x5f, 0xcb, 0x8a, 0xa5, 0x54, 0x9e, 0xc9, 0xcd, 0xd1, 0xf5, 0xd5, 0x77, 0x20, 0x1b, 0x8e, 0x32, 0x9f, 0x72, 0xfa, 0xa2, 0xbc, 0xad, 0xea, 0xee, 0x38, 0x8d, 0xaf, 0x7d, 0x40, 0x8a, 0xfd, 0xe6, 0x55, 0x3d, 0x24, 0x17, 0x86, 0x0f, 0x3c, 0x8e, 0x25, 0x30, 0x5d, 0xff, 0x76, 0xdb, 0xbd, 0x95, 0x16, 0xb6, 0x86, 0x8e, 0xe4, 0x56, 0xfc, 0x1f, 0x7b, 0x58, 0xd9, 0xed, 0x18, 0xa4, 0x6e, 0x4f, 0xc1, 0xe3, 0x53, 0xe8, 0xd0, 0x76, 0xbe, 0xa3, 0x0b, 0xf2, 0x47, 0xc6, 0x0e, 0x6f, 0x68, 0x58, 0x01, 0xa6, 0xd3, 0xf6, 0x30, 0xae, 0xa6, 0xab, 0xb4, 0x12, 0xa9, 0x41, 0xff, 0xa6, 0xf6, 0x07, 0xf6, 0xbf, 0xb1, 0x3d, 0x90, 0x01, 0x27, 0xbb, 0xec, 0xee, 0x4f, 0x98, 0xa7, 0xac, 0xa6, 0x92, 0x08, 0x11, 0x57, 0x50, 0x53, 0xab, 0x2d, 0x42, 0x70, 0x13, 0x80, 0x1d, 0x8c, 0xfb, 0xc3, 0x88, 0x0f, 0x14, 0x75, 0x43, 0x15, 0x55, 0xa0, 0x86, 0xfa, 0x55, 0x60, 0xc6, 0xe2, 0x20, 0x6d, 0x9e, 0xe9, 0x38, 0x13, 0x44, 0xb8, 0x24, 0x1c, 0x1d, 0xd1, 0xd8, 0x64, 0x48, 0x75, 0x3a, 0xf4, 0x4b, 0x00, 0xa0, 0xc9 } +, + /* Signature */ + 129, + { 0x16, 0x97, 0xbb, 0x23, 0xe2, 0x91, 0x52, 0x5f, 0x4a, 0x0e, 0x79, 0x26, 0x2f, 0x34, 0x06, 0x63, 0x0d, 0x0d, 0x6d, 0xf3, 0x32, 0x49, 0x69, 0x26, 0xc4, 0xe5, 0xae, 0xf9, 0x6e, 0x41, 0xd9, 0x55, 0x14, 0x86, 0x47, 0xea, 0xf7, 0x90, 0x69, 0x6a, 0xf6, 0x8c, 0x78, 0xeb, 0x2a, 0xb6, 0x2f, 0xf7, 0x19, 0x62, 0x96, 0xe1, 0xea, 0x88, 0x6d, 0xf0, 0x91, 0x73, 0x66, 0x09, 0x0b, 0x63, 0x0a, 0xa3, 0x18, 0x58, 0xb5, 0x16, 0x15, 0x87, 0x3f, 0xa6, 0xbc, 0x8f, 0xf0, 0x88, 0x5c, 0x57, 0xb2, 0xe7, 0x7a, 0x04, 0x90, 0x88, 0x93, 0xcc, 0xef, 0xb1, 0x41, 0x24, 0x03, 0x99, 0x1d, 0x0d, 0x23, 0xc5, 0x57, 0xd2, 0x22, 0x29, 0x1c, 0xb8, 0x51, 0x7b, 0x43, 0x28, 0x6e, 0xe0, 0x05, 0x67, 0x58, 0xd9, 0xc1, 0x0b, 0xcd, 0x69, 0xbd, 0x68, 0xb8, 0x4a, 0x2d, 0x1f, 0x53, 0x79, 0x05, 0xb8, 0xa4, 0x65, 0xe9 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.18", + /* Message to be signed */ + 169, + { 0x17, 0x89, 0xb8, 0x08, 0xb1, 0x0d, 0xe8, 0xd1, 0x77, 0x8a, 0xa4, 0x3f, 0x94, 0x10, 0x1c, 0xb8, 0x9f, 0x56, 0x34, 0x30, 0x61, 0xa1, 0xa9, 0x43, 0xbb, 0x8d, 0xa5, 0x5e, 0xe6, 0xb9, 0x79, 0xe2, 0x7a, 0xfe, 0xab, 0x0e, 0xd8, 0xee, 0x37, 0x14, 0xfb, 0xe7, 0x0b, 0x3b, 0xe8, 0x20, 0x60, 0x3e, 0x5c, 0xea, 0xde, 0xc4, 0xb2, 0x2f, 0x95, 0x87, 0x73, 0x22, 0x5d, 0xf3, 0xaa, 0xd4, 0x87, 0xb2, 0x80, 0x57, 0xeb, 0xfe, 0xbe, 0x2c, 0x87, 0x93, 0xda, 0x38, 0x46, 0xbd, 0xb1, 0x59, 0x03, 0xac, 0x71, 0xe9, 0xc9, 0x3b, 0x20, 0x16, 0x66, 0x8b, 0xd9, 0x06, 0x30, 0x1a, 0x0a, 0x7d, 0x50, 0xdc, 0x60, 0xb2, 0xfa, 0xd8, 0x75, 0x9d, 0x18, 0xdb, 0x14, 0x7f, 0x20, 0x66, 0x86, 0x5f, 0xd9, 0x09, 0x50, 0xa1, 0x88, 0x74, 0x7d, 0x9b, 0x69, 0x68, 0x53, 0x48, 0x6d, 0xea, 0xab, 0x8e, 0x44, 0x3f, 0xad, 0x29, 0x92, 0xfc, 0x8a, 0x56, 0x5b, 0xdc, 0xba, 0xda, 0xb0, 0xb9, 0x33, 0x3a, 0xb7, 0xfc, 0xdb, 0x9c, 0x3d, 0x0b, 0xcf, 0xde, 0x50, 0xa5, 0x8d, 0x2a, 0xea, 0xf1, 0xce, 0xfb, 0x0c, 0x95, 0xf9, 0x07, 0x73, 0xb2, 0xfa, 0xc1, 0x37, 0xcd, 0xbc } +, + /* Signature */ + 129, + { 0x02, 0xf9, 0x97, 0x51, 0xc8, 0x44, 0x38, 0xea, 0xc7, 0xf9, 0x96, 0x32, 0x50, 0xd9, 0xee, 0x22, 0xfd, 0xa7, 0x29, 0x7b, 0x6e, 0x86, 0xe2, 0xa8, 0xbc, 0xc7, 0xa9, 0xb5, 0xac, 0x01, 0xf7, 0x90, 0xe0, 0x99, 0x11, 0x70, 0x46, 0x60, 0x85, 0x8e, 0xa5, 0xc1, 0x62, 0x72, 0xc3, 0x81, 0x33, 0xfa, 0xda, 0xde, 0xfa, 0x23, 0xc1, 0x02, 0x90, 0x8e, 0x41, 0x9d, 0xe2, 0xeb, 0xe9, 0xac, 0x27, 0x19, 0x45, 0x72, 0x87, 0x8e, 0x2a, 0x97, 0x1f, 0x88, 0x31, 0xc8, 0xf9, 0x17, 0xe8, 0x52, 0xe8, 0x51, 0xdf, 0x99, 0xd4, 0xdf, 0x01, 0x8f, 0xdd, 0xb2, 0xce, 0xa3, 0x1a, 0xc3, 0xa7, 0xb6, 0x89, 0x75, 0xe8, 0x0a, 0x99, 0x7c, 0xb7, 0xdd, 0x4d, 0x4d, 0xf7, 0x57, 0xbb, 0x8c, 0x3e, 0xcd, 0x91, 0x0b, 0xcb, 0x06, 0x03, 0x35, 0x52, 0x12, 0x7a, 0xc3, 0x08, 0x11, 0x77, 0x39, 0xa0, 0x2c, 0x20, 0x17, 0x17 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.19", + /* Message to be signed */ + 151, + { 0xff, 0x87, 0x5c, 0xca, 0x0e, 0xfc, 0x3d, 0x90, 0xf5, 0x6e, 0x31, 0xf4, 0xbb, 0x66, 0x84, 0x14, 0x89, 0x4d, 0x09, 0xde, 0x90, 0x12, 0x7f, 0x84, 0x66, 0x32, 0x43, 0x10, 0xe1, 0x13, 0x69, 0xa3, 0xf2, 0xf6, 0x49, 0x3c, 0x1c, 0x78, 0xa3, 0x62, 0xb2, 0xa1, 0x4f, 0xb5, 0x48, 0x8c, 0xb5, 0x6c, 0xe0, 0x22, 0x73, 0x9e, 0x43, 0xaa, 0x76, 0x3d, 0x9c, 0x1c, 0x97, 0xb6, 0x21, 0xcc, 0x53, 0x68, 0xc9, 0xc0, 0x0e, 0x81, 0x60, 0x67, 0x92, 0x69, 0x5f, 0x9a, 0xf9, 0xab, 0x63, 0x3e, 0xf2, 0x39, 0xea, 0xb3, 0x44, 0x9d, 0xda, 0x9e, 0x66, 0x07, 0x08, 0x9c, 0x37, 0x51, 0x90, 0x35, 0x4f, 0x7a, 0x59, 0xa4, 0xb3, 0xef, 0x75, 0x22, 0x9d, 0x1c, 0x47, 0xec, 0xda, 0xe3, 0x3b, 0x27, 0x69, 0xff, 0x55, 0x42, 0x65, 0x5e, 0x78, 0x10, 0x22, 0xd0, 0xc4, 0x3b, 0x42, 0x1a, 0x99, 0x84, 0x3c, 0x3d, 0xe1, 0x04, 0x22, 0xad, 0x2f, 0xd8, 0x9d, 0xfe, 0x44, 0x66, 0x15, 0xf5, 0x19, 0x2e, 0x75, 0x79, 0xd4, 0x37, 0x43, 0x79, 0xbb, 0xff, 0xb9 } +, + /* Signature */ + 129, + { 0x02, 0x68, 0x91, 0x7f, 0x8b, 0xda, 0xac, 0x9e, 0xbe, 0x32, 0xb0, 0xdc, 0x6c, 0xd9, 0xd3, 0x9e, 0xfd, 0x3f, 0x88, 0xd8, 0x17, 0xd6, 0x6c, 0xb6, 0x39, 0x0d, 0x7b, 0x55, 0xc6, 0x92, 0x12, 0x21, 0x84, 0x4a, 0xb8, 0xc0, 0x89, 0x86, 0xd3, 0xf2, 0xea, 0x49, 0xbc, 0x6e, 0x3a, 0x10, 0x02, 0x08, 0x6c, 0x0b, 0x6d, 0xf1, 0x63, 0xf7, 0x9d, 0x16, 0x11, 0x6a, 0x93, 0xc4, 0xa2, 0xcc, 0x04, 0x22, 0xc9, 0x48, 0x41, 0xe1, 0xe3, 0xb9, 0x45, 0xab, 0x1d, 0x25, 0x3a, 0xb8, 0xd7, 0xd1, 0x39, 0xc9, 0x18, 0x8b, 0xa8, 0x30, 0x27, 0xc5, 0x93, 0xf8, 0x3a, 0x6f, 0x38, 0x37, 0x0e, 0x7f, 0x03, 0x79, 0xff, 0xdd, 0xf1, 0x42, 0x7d, 0x6f, 0xcc, 0xcf, 0x60, 0x83, 0x31, 0x3f, 0x18, 0x15, 0xb5, 0xde, 0xd6, 0x73, 0x74, 0x30, 0xbb, 0x4a, 0x70, 0xba, 0x81, 0x48, 0x48, 0x34, 0xd8, 0xd1, 0xd2, 0x9a, 0x5e } + +} +, +{ + "PKCS#1 v1.5 Signature Example 11.20", + /* Message to be signed */ + 86, + { 0xe0, 0x7e, 0xcf, 0x00, 0xe2, 0x40, 0x1a, 0xc9, 0x8b, 0x2d, 0x5a, 0xe0, 0xc9, 0xb8, 0x3f, 0x21, 0x9a, 0xb0, 0x27, 0xa6, 0x51, 0x99, 0xfd, 0xb6, 0x34, 0x59, 0x6e, 0x23, 0x44, 0x62, 0x41, 0x38, 0x72, 0x95, 0x32, 0x49, 0x53, 0x28, 0xf9, 0x3f, 0xb3, 0xa3, 0x32, 0x55, 0x27, 0x8f, 0x3e, 0xc2, 0x60, 0x65, 0xce, 0x54, 0x99, 0x5d, 0x42, 0x41, 0x93, 0xbc, 0xb7, 0x58, 0x1b, 0xfe, 0x1a, 0xb8, 0x95, 0x7d, 0x0b, 0x96, 0x1c, 0x30, 0x30, 0xb8, 0x20, 0xd0, 0x9c, 0x9e, 0x32, 0x6c, 0xc3, 0x0c, 0x0a, 0xf6, 0x42, 0x66, 0x61, 0x54 } +, + /* Signature */ + 129, + { 0x00, 0xc4, 0x6d, 0xb4, 0x1b, 0x65, 0xdd, 0xc7, 0x1f, 0xbb, 0xfc, 0x12, 0x5a, 0x4f, 0x9b, 0xab, 0x88, 0x0a, 0x2f, 0x0c, 0x1f, 0x04, 0x1c, 0x41, 0x1d, 0xf7, 0xd4, 0x5d, 0x1e, 0x19, 0x99, 0x7b, 0x34, 0x8e, 0xab, 0xba, 0x19, 0xbf, 0x79, 0xb2, 0x21, 0x77, 0xb2, 0xa0, 0xd7, 0x3f, 0xef, 0xa5, 0x00, 0x83, 0x62, 0xce, 0x59, 0x60, 0xd7, 0xef, 0x58, 0xa5, 0x89, 0x93, 0xe7, 0x46, 0x03, 0xd4, 0xd9, 0xd0, 0xb3, 0xda, 0xd4, 0xb2, 0x0c, 0x82, 0x9d, 0x36, 0xef, 0xca, 0xf5, 0x7f, 0x0c, 0x4f, 0x0c, 0xef, 0x89, 0x01, 0x5a, 0x48, 0x45, 0x02, 0x42, 0xbd, 0x02, 0x0d, 0x5f, 0x52, 0xd8, 0xb5, 0x0e, 0xa1, 0x3e, 0x56, 0xa1, 0xaa, 0xd6, 0x01, 0x91, 0x5d, 0x60, 0xec, 0x9a, 0xbf, 0xc3, 0x07, 0xf1, 0x8a, 0xf2, 0x06, 0x72, 0x38, 0x4d, 0xcc, 0x12, 0xf9, 0x82, 0x27, 0x31, 0x36, 0x99, 0x71, 0x40 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 12: A 1030-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x36, 0x98, 0x1a, 0x95, 0xae, 0x24, 0x18, 0x14, 0x52, 0xda, 0x25, 0x7c, 0x03, 0x8f, 0x05, 0x82, 0x14, 0x12, 0xd8, 0x4e, 0xb4, 0x7a, 0x43, 0xfc, 0xc7, 0xef, 0x12, 0x17, 0x95, 0x9b, 0xa6, 0x77, 0x02, 0x7f, 0x70, 0x86, 0xd3, 0xa8, 0x5c, 0xdd, 0x34, 0x9f, 0x92, 0x0f, 0x03, 0x4c, 0x02, 0x78, 0x79, 0x2d, 0xc8, 0xa8, 0xcf, 0x0c, 0x00, 0x80, 0xe5, 0xc6, 0x1f, 0x47, 0x48, 0x83, 0xc6, 0x87, 0x9f, 0x4d, 0xee, 0x0a, 0xe9, 0x52, 0x47, 0x8a, 0x5e, 0xe2, 0xce, 0x4e, 0x39, 0x18, 0x64, 0x1e, 0x81, 0x3c, 0xb3, 0x74, 0xf7, 0xb2, 0x83, 0x2b, 0xcd, 0x6a, 0xea, 0x80, 0x9d, 0x25, 0x4f, 0xc2, 0xca, 0x9a, 0xc5, 0xa3, 0x32, 0x42, 0x4a, 0xb6, 0x5c, 0x2a, 0x26, 0x12, 0x75, 0xd1, 0x9a, 0x41, 0x4b, 0x61, 0x65, 0x00, 0xd5, 0xe3, 0x73, 0x70, 0x63, 0x15, 0xf0, 0x63, 0xdc, 0x88, 0x5d, 0x7f, 0xb9 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x09, 0xad, 0x03, 0x17, 0x30, 0xb6, 0x32, 0x73, 0x55, 0xac, 0xd6, 0x94, 0x68, 0x70, 0x0e, 0x7e, 0x9b, 0xae, 0xac, 0x5a, 0x24, 0xa7, 0xff, 0xc9, 0x3b, 0x29, 0x2e, 0xb8, 0x71, 0xda, 0x54, 0x92, 0x46, 0xa5, 0xce, 0x0c, 0x83, 0x52, 0x55, 0x65, 0x1a, 0x28, 0xc6, 0xe2, 0xf4, 0xc7, 0x61, 0xaf, 0xb6, 0xf0, 0x6b, 0x9e, 0x29, 0x95, 0xfb, 0xb7, 0xdc, 0xa1, 0x74, 0xd5, 0x36, 0x2f, 0xae, 0xbd, 0xc3, 0x9a, 0x72, 0xc5, 0x79, 0x5d, 0x1f, 0x33, 0x92, 0xec, 0x08, 0x8b, 0x5d, 0xc2, 0xa7, 0x85, 0xb2, 0xc9, 0xc4, 0xc6, 0xe6, 0x69, 0xe7, 0x23, 0xb5, 0xdd, 0x0c, 0xe4, 0x43, 0x25, 0x55, 0x12, 0x67, 0xdd, 0x62, 0xe0, 0xf7, 0x8d, 0x24, 0x24, 0xad, 0xae, 0x48, 0xe2, 0x49, 0x44, 0x3a, 0xef, 0x4a, 0x37, 0x04, 0x10, 0xdb, 0x9e, 0x70, 0x93, 0x99, 0xac, 0x37, 0xcc, 0x48, 0x1b, 0x59, 0x00, 0xc5 } +, + /* Prime 1 */ + 65, + { 0x07, 0x72, 0x0f, 0x21, 0xcd, 0xdb, 0x92, 0x27, 0x45, 0xb7, 0x1c, 0xf8, 0x11, 0x6a, 0x83, 0x66, 0x9a, 0x0d, 0xdb, 0x89, 0xe8, 0xf3, 0xf0, 0x6c, 0x34, 0x7c, 0xa7, 0x87, 0xcf, 0x10, 0xef, 0x16, 0x93, 0xbd, 0xfe, 0x3a, 0x0c, 0x36, 0x4c, 0x7a, 0x7e, 0x89, 0x04, 0x17, 0xf2, 0xaf, 0x49, 0x47, 0x5c, 0x7d, 0x07, 0x6f, 0x9c, 0xee, 0xaa, 0xe7, 0x6d, 0xbd, 0x4e, 0x92, 0x15, 0xaf, 0x45, 0x69, 0x4d } +, + /* Prime 2 */ + 65, + { 0x07, 0x55, 0x1c, 0x27, 0xe9, 0xaa, 0xf1, 0x1f, 0x47, 0x4f, 0x1c, 0x9a, 0x14, 0xbf, 0x14, 0x4c, 0xfa, 0xef, 0xe2, 0x7f, 0xca, 0x4f, 0x20, 0x79, 0x5d, 0xec, 0x85, 0x34, 0xc9, 0x37, 0xbb, 0x00, 0xfe, 0x16, 0x23, 0x5e, 0xcd, 0x69, 0x1f, 0xd2, 0x3e, 0x32, 0xcd, 0xfb, 0x8b, 0x78, 0x66, 0x6b, 0xb7, 0x82, 0x84, 0xae, 0x15, 0xd5, 0x9b, 0xe5, 0xca, 0x74, 0x73, 0xe6, 0x2d, 0x46, 0xa9, 0xda, 0x1d } +, + /* Prime exponent 1 */ + 65, + { 0x02, 0xe2, 0x2c, 0x74, 0x16, 0x0a, 0x94, 0x36, 0xbb, 0x6c, 0x28, 0x3e, 0xf6, 0x57, 0xbe, 0xdd, 0xec, 0x89, 0xb3, 0x5d, 0x5c, 0xa7, 0xa4, 0x93, 0xf3, 0x5b, 0xd7, 0x71, 0xe4, 0x42, 0x95, 0xa5, 0xb3, 0xc0, 0x20, 0x06, 0x11, 0x16, 0xb2, 0x55, 0xba, 0x4d, 0x8c, 0x15, 0x4e, 0x3a, 0x8e, 0x71, 0xa1, 0xa3, 0x16, 0x4f, 0x26, 0x82, 0xd4, 0x13, 0x5e, 0xcf, 0xb2, 0xef, 0x26, 0x90, 0xc3, 0x9b, 0xfd } +, + /* Prime exponent 2 */ + 65, + { 0x01, 0xd2, 0xbf, 0xf5, 0x8c, 0xbc, 0xdc, 0xc8, 0x12, 0x4b, 0x31, 0xa9, 0x7e, 0x8f, 0x24, 0xd5, 0x1f, 0x70, 0x96, 0xb9, 0x7f, 0xec, 0xbc, 0xfe, 0x70, 0xc4, 0x67, 0x3b, 0x00, 0xed, 0xc2, 0xaa, 0x34, 0x83, 0xfc, 0xb7, 0x8e, 0x0c, 0x1d, 0xc5, 0x81, 0x81, 0xd0, 0x86, 0x43, 0xdf, 0xe4, 0x57, 0xd4, 0x81, 0xb7, 0xcc, 0x31, 0xd1, 0xb3, 0xba, 0x27, 0xe5, 0x5d, 0x0c, 0x57, 0x25, 0xc3, 0x06, 0x61 } +, + /* Coefficient */ + 65, + { 0x06, 0xd2, 0x27, 0x72, 0x57, 0x42, 0xef, 0x03, 0x46, 0x2d, 0x1c, 0xf6, 0x12, 0x67, 0x4a, 0x78, 0x83, 0x1d, 0x61, 0x9d, 0xa3, 0xd6, 0x40, 0xeb, 0x7c, 0x71, 0xc8, 0x7b, 0x53, 0x28, 0x69, 0x72, 0x73, 0xc5, 0xf7, 0x51, 0xe1, 0x4d, 0x7b, 0x81, 0xc1, 0x2b, 0x6d, 0xeb, 0x44, 0x75, 0x1a, 0x92, 0x95, 0xcb, 0x67, 0x1e, 0x81, 0x48, 0x4d, 0xea, 0xa8, 0x3b, 0x4d, 0xf1, 0xfd, 0x37, 0xe2, 0xff, 0x3c } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 12.1", + /* Message to be signed */ + 9, + { 0xe4, 0xb2, 0xd6, 0x0e, 0x3b, 0xdd, 0x27, 0x81, 0x6f } +, + /* Signature */ + 129, + { 0x13, 0xfd, 0x4a, 0xc1, 0xac, 0x68, 0x48, 0x17, 0x37, 0x80, 0x96, 0x5a, 0xff, 0x5e, 0x61, 0xc5, 0x96, 0x89, 0x2b, 0xc1, 0x47, 0x76, 0x0d, 0x43, 0x07, 0x9b, 0x5d, 0x71, 0x77, 0xe4, 0x23, 0xd4, 0x86, 0xf5, 0xa7, 0x3e, 0x1a, 0x16, 0xb3, 0xce, 0x9b, 0x5e, 0xda, 0xc1, 0x61, 0xea, 0x6d, 0x4f, 0x6c, 0x23, 0xfc, 0xfc, 0x3e, 0x62, 0x19, 0xca, 0xc5, 0x56, 0x06, 0x7f, 0xfa, 0xed, 0x4a, 0xda, 0xc0, 0xa9, 0x50, 0x05, 0x09, 0x0b, 0x89, 0x84, 0x4c, 0x54, 0x35, 0x4d, 0xb2, 0x2a, 0xaf, 0xf9, 0xee, 0xff, 0x9d, 0xa5, 0xaa, 0xa5, 0x49, 0x04, 0x25, 0xe1, 0x35, 0xcc, 0x0f, 0x64, 0x58, 0x4c, 0x7f, 0x05, 0xfe, 0x33, 0x6e, 0x44, 0x40, 0xbb, 0x86, 0x92, 0x86, 0xd4, 0x4a, 0xf1, 0x57, 0x88, 0x0e, 0x3a, 0x40, 0xfb, 0x06, 0x72, 0x5d, 0x09, 0xde, 0xb3, 0x7f, 0x1e, 0xbb, 0x18, 0x1c, 0x8f, 0x5c } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 12.2", + /* Message to be signed */ + 164, + { 0x78, 0x86, 0x85, 0xfc, 0x58, 0x05, 0xd6, 0x27, 0xb1, 0x3f, 0x2f, 0xe7, 0xfe, 0x6f, 0x7c, 0x9a, 0xb2, 0xca, 0x49, 0x44, 0xab, 0xf3, 0x08, 0xb8, 0x6d, 0x1a, 0x0f, 0x58, 0x3d, 0x17, 0xb5, 0x76, 0x02, 0x43, 0x9e, 0x1f, 0x2c, 0x6e, 0x0c, 0x5b, 0xf7, 0x81, 0x70, 0x50, 0x13, 0x38, 0xb4, 0xc4, 0x47, 0xe9, 0x19, 0x7b, 0x65, 0x03, 0xfb, 0x73, 0xeb, 0xab, 0xf7, 0x76, 0xde, 0xfa, 0xe3, 0x3b, 0xdc, 0xdc, 0xe7, 0x7d, 0xe7, 0x9b, 0x82, 0xbe, 0x14, 0x85, 0xa8, 0xaa, 0x9b, 0x82, 0x09, 0x37, 0xdb, 0xf4, 0x28, 0xa2, 0x05, 0x50, 0x96, 0x6a, 0x86, 0xb6, 0x2a, 0x17, 0x2e, 0x6c, 0xfb, 0xdc, 0xfe, 0x0d, 0x6f, 0xc6, 0x7a, 0x4d, 0xb6, 0x22, 0x52, 0xfd, 0xaf, 0x85, 0xf1, 0xe6, 0xbc, 0x14, 0xf8, 0xab, 0x1c, 0x53, 0x32, 0x6a, 0xa6, 0xa7, 0xbc, 0x5e, 0xec, 0x88, 0xe0, 0xb1, 0x1d, 0x48, 0xd2, 0xb5, 0x61, 0xf2, 0x26, 0x06, 0x50, 0x10, 0x2f, 0xf2, 0x7b, 0x57, 0xb7, 0x00, 0x72, 0xbc, 0xc1, 0x21, 0xe3, 0x5e, 0x70, 0xf3, 0x78, 0x0c, 0x83, 0x33, 0xb5, 0xbf, 0x6b, 0x08, 0xfa, 0x12, 0x08, 0x26, 0x0f, 0x33 } +, + /* Signature */ + 129, + { 0x09, 0x04, 0xcc, 0x11, 0xac, 0x66, 0xa9, 0x83, 0x7b, 0x74, 0x56, 0x8b, 0xe2, 0x50, 0xe5, 0x3a, 0xe4, 0xbe, 0xf7, 0x8d, 0xc6, 0x7f, 0xfe, 0xe5, 0x09, 0xe5, 0xd9, 0xb4, 0x72, 0x58, 0x3e, 0xaa, 0xa5, 0x6d, 0x4c, 0x9e, 0xe7, 0x0f, 0x6e, 0x82, 0xdc, 0x99, 0x8b, 0x53, 0xef, 0xf1, 0x27, 0x2b, 0xf0, 0x1f, 0x09, 0xe5, 0x26, 0x2b, 0x15, 0x5a, 0x6e, 0x56, 0xd1, 0x50, 0x40, 0x03, 0xe4, 0xc8, 0xa4, 0x6e, 0x65, 0x02, 0x55, 0x32, 0x78, 0x23, 0x0d, 0x6e, 0x81, 0xb7, 0x29, 0x18, 0x43, 0xab, 0x97, 0x69, 0x73, 0x7f, 0x3c, 0x69, 0x31, 0x52, 0xf1, 0x7b, 0xf2, 0xd8, 0xbf, 0xc7, 0x82, 0xbd, 0xb3, 0xfa, 0x0a, 0xea, 0xdf, 0x0d, 0x44, 0x1e, 0x1e, 0x52, 0xde, 0xa5, 0x4b, 0x75, 0xcf, 0x16, 0x5e, 0x35, 0xc3, 0x82, 0xd3, 0x11, 0x74, 0xf6, 0x67, 0x9d, 0x2f, 0x21, 0xb9, 0x81, 0xf4, 0x13, 0x58 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.3", + /* Message to be signed */ + 126, + { 0x4e, 0xc7, 0x39, 0x3f, 0xdc, 0x4b, 0x90, 0xaf, 0x8f, 0xff, 0xca, 0xf3, 0x4e, 0x84, 0x5a, 0x09, 0x65, 0x6a, 0xef, 0x9d, 0xda, 0x12, 0xb0, 0x34, 0x2c, 0x46, 0xeb, 0x04, 0x91, 0x74, 0xaa, 0x51, 0x1b, 0x43, 0xc9, 0x4d, 0x75, 0xc0, 0xe2, 0x90, 0x70, 0xaf, 0xf5, 0xb4, 0x14, 0x23, 0xa1, 0x70, 0xd9, 0xb3, 0xe8, 0xb2, 0x12, 0x24, 0xaa, 0xbc, 0x53, 0x1d, 0x88, 0x88, 0x6e, 0x26, 0x46, 0xd6, 0x78, 0x8f, 0x1b, 0xaa, 0xd4, 0xef, 0x4b, 0x0b, 0x4b, 0xde, 0x4b, 0x12, 0xce, 0x90, 0x52, 0x08, 0x2e, 0x2d, 0xdd, 0x0e, 0x3e, 0x6c, 0xaa, 0xbb, 0x0a, 0x14, 0x34, 0x4b, 0x0a, 0x58, 0x3f, 0x40, 0x4c, 0x1b, 0x6a, 0x3c, 0x7b, 0xca, 0x8a, 0x58, 0x85, 0xd5, 0xf2, 0x24, 0xaf, 0x1f, 0xca, 0xc3, 0xfa, 0xd9, 0x37, 0x0e, 0x9b, 0x29, 0x74, 0xe8, 0xca, 0x62, 0xe2, 0x2a, 0xce, 0xb9 } +, + /* Signature */ + 129, + { 0x21, 0xa6, 0x6a, 0xf6, 0x27, 0xee, 0x0d, 0xd0, 0x5f, 0xe7, 0x56, 0x3c, 0xc1, 0xd2, 0x9c, 0xcf, 0x6f, 0x87, 0x31, 0xb4, 0x1e, 0x3d, 0xb3, 0x95, 0x97, 0x89, 0x3b, 0xa1, 0xcf, 0x37, 0x5f, 0x78, 0x17, 0x88, 0xfd, 0xf0, 0x73, 0xb0, 0xb5, 0x93, 0xc7, 0x6d, 0xf2, 0x81, 0x6e, 0xc6, 0xde, 0xfc, 0x22, 0x42, 0x21, 0xac, 0x19, 0xf5, 0xbe, 0xe4, 0x4f, 0xc0, 0xe5, 0xd4, 0x09, 0x3d, 0x34, 0x68, 0x27, 0x8f, 0xb4, 0x2d, 0x40, 0x5a, 0x07, 0x04, 0x46, 0x53, 0x22, 0xda, 0x4d, 0x3a, 0x7c, 0xa9, 0xc3, 0xda, 0x73, 0xc3, 0xd0, 0x82, 0xae, 0xe5, 0x67, 0xb7, 0x70, 0x83, 0x32, 0x3e, 0x75, 0xbb, 0x35, 0xed, 0x77, 0xe8, 0xdb, 0x9c, 0x01, 0xb4, 0x96, 0xa0, 0x4c, 0xc4, 0xa8, 0x99, 0xdf, 0x35, 0x9d, 0xa4, 0xa2, 0x28, 0x7c, 0xaf, 0xff, 0xe1, 0xed, 0x63, 0xcd, 0xde, 0xad, 0x87, 0x6c, 0x94, 0x07 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.4", + /* Message to be signed */ + 250, + { 0x90, 0x77, 0x60, 0xdb, 0x32, 0x96, 0x9b, 0x09, 0x7d, 0xc1, 0x24, 0xef, 0x89, 0x75, 0x15, 0x11, 0xa5, 0xd2, 0x30, 0x59, 0x6d, 0x2f, 0xd8, 0xa8, 0x91, 0xff, 0x00, 0xf0, 0x5f, 0xba, 0xd4, 0x5f, 0x72, 0xa4, 0x5d, 0x46, 0x56, 0x24, 0xa3, 0xab, 0x67, 0xaf, 0xdb, 0xb9, 0xe5, 0xf9, 0xe6, 0x5b, 0x63, 0xe3, 0x0c, 0x2e, 0x57, 0xfe, 0x7f, 0x32, 0xf3, 0x99, 0x01, 0x10, 0x33, 0xdc, 0x05, 0x29, 0xc0, 0x97, 0x1f, 0xbe, 0x06, 0x4f, 0xc5, 0xed, 0xb0, 0x1f, 0x84, 0xcd, 0x57, 0x28, 0x3f, 0xbb, 0xbd, 0x2a, 0xa0, 0x29, 0x44, 0x11, 0x0b, 0x6b, 0x53, 0x4f, 0x74, 0x08, 0x2f, 0x56, 0xbe, 0x34, 0x6c, 0xc3, 0x43, 0xbd, 0x4d, 0x0b, 0x34, 0x80, 0x91, 0xc0, 0x05, 0xc6, 0x19, 0x9a, 0x7e, 0x3d, 0x56, 0x88, 0x52, 0x47, 0xb0, 0xc1, 0x6a, 0x36, 0xb2, 0x35, 0xb8, 0xf5, 0xd4, 0xf0, 0x0a, 0x6c, 0x6b, 0xb6, 0xfe, 0xed, 0xe8, 0x8f, 0xcd, 0x78, 0x8d, 0x75, 0xca, 0xcf, 0xf7, 0xd9, 0x56, 0x87, 0x99, 0x65, 0x71, 0x55, 0x9c, 0x05, 0x79, 0x6a, 0x55, 0x71, 0x1d, 0x77, 0x46, 0xbb, 0x92, 0xd8, 0x52, 0x89, 0x3b, 0xa9, 0x06, 0x75, 0xf9, 0x8b, 0x0f, 0x54, 0x08, 0x48, 0x1b, 0xf1, 0x54, 0x3f, 0x39, 0xde, 0x3d, 0x0c, 0x0c, 0x1f, 0x53, 0x49, 0x5b, 0xd2, 0x12, 0xdd, 0xcd, 0xc6, 0xd0, 0xe5, 0x7d, 0x7a, 0x3d, 0xbe, 0x24, 0x20, 0x8c, 0xb2, 0x4e, 0xd4, 0x1d, 0xe0, 0x3a, 0x5f, 0x05, 0x2a, 0x9b, 0x58, 0x12, 0x70, 0x0a, 0x5c, 0xe0, 0x5c, 0x02, 0x00, 0xd4, 0x71, 0x9c, 0x55, 0x54, 0x4e, 0x7f, 0xb2, 0x94, 0xd3, 0x44, 0xa4, 0xf2, 0x05, 0xef, 0x9a, 0x34, 0x97, 0xb5, 0x67, 0x54, 0x7c, 0xbd, 0x1a, 0x63, 0x3e, 0x2b, 0x79, 0xd3, 0x34, 0x90, 0x95 } +, + /* Signature */ + 129, + { 0x0e, 0xc9, 0x38, 0xa0, 0xd4, 0xb2, 0xa4, 0xed, 0xd2, 0x78, 0xd6, 0x3d, 0xe7, 0x61, 0xc1, 0x02, 0xe2, 0x59, 0x21, 0x02, 0xee, 0x05, 0xdb, 0x1b, 0x59, 0x1e, 0x0d, 0x85, 0x7b, 0xf6, 0x66, 0x84, 0x9e, 0x74, 0xcc, 0x19, 0xb7, 0xe4, 0xe9, 0xcc, 0x39, 0x2d, 0xe5, 0x39, 0xf7, 0x90, 0xfc, 0x68, 0xe3, 0xb5, 0x21, 0xdb, 0x3a, 0x1a, 0x26, 0x7e, 0x5a, 0x4e, 0x12, 0x19, 0x75, 0x2e, 0x01, 0x99, 0xe7, 0x01, 0x9a, 0x24, 0x85, 0x54, 0xc5, 0xba, 0xe3, 0x11, 0x2b, 0xee, 0xa4, 0x0c, 0xf3, 0xe6, 0x4f, 0x8a, 0xaf, 0x9b, 0xb1, 0xe9, 0xd1, 0xc1, 0xd8, 0x83, 0x3c, 0x2b, 0xfa, 0x31, 0xb9, 0xd5, 0x45, 0x0f, 0xa2, 0x49, 0x29, 0x7f, 0xe2, 0xe4, 0x6a, 0xb0, 0x3e, 0x99, 0xb1, 0xf9, 0xc6, 0x51, 0xd5, 0x39, 0xeb, 0x53, 0xce, 0x09, 0x61, 0xce, 0x60, 0x23, 0xc1, 0x7d, 0xd7, 0x38, 0x3d, 0xd1, 0x2b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.5", + /* Message to be signed */ + 124, + { 0xbd, 0xa5, 0x54, 0x95, 0x47, 0x32, 0xd1, 0xd5, 0xf3, 0x94, 0x75, 0x55, 0xc6, 0x1f, 0xfa, 0xb8, 0x01, 0xdb, 0xcd, 0xc8, 0x12, 0x1d, 0xc6, 0x81, 0x91, 0x27, 0xc2, 0xf2, 0x2a, 0x43, 0x6d, 0x20, 0x62, 0x2d, 0x1f, 0x4a, 0x44, 0x7c, 0x3a, 0x77, 0xb6, 0x58, 0x57, 0x31, 0xaf, 0xc0, 0x3e, 0x77, 0xba, 0xeb, 0x70, 0x9c, 0x1b, 0xfb, 0x90, 0x6a, 0x1a, 0xa1, 0x94, 0x9a, 0xb6, 0x76, 0x3a, 0x15, 0xc7, 0xda, 0x5a, 0x12, 0xa8, 0xf3, 0x95, 0x10, 0x1e, 0x64, 0x6a, 0x83, 0x71, 0x73, 0x14, 0x1f, 0x2a, 0x0c, 0xf5, 0x36, 0x02, 0x4b, 0x36, 0x91, 0x8c, 0xf9, 0xdb, 0x95, 0xb1, 0xcc, 0x40, 0x5a, 0xef, 0xe6, 0x3a, 0x3a, 0x93, 0xbc, 0x4a, 0xda, 0x60, 0xa0, 0xf4, 0xe0, 0x72, 0x9f, 0x4d, 0xb8, 0xb7, 0x6f, 0xd6, 0x4e, 0xfc, 0xbc, 0xb6, 0x6f, 0x0e, 0x4a, 0xaf, 0xf3 } +, + /* Signature */ + 129, + { 0x07, 0x26, 0x2f, 0xe1, 0xf3, 0xd7, 0xb7, 0x79, 0x32, 0xcd, 0xb7, 0xcd, 0x96, 0xac, 0x19, 0x8b, 0x93, 0x03, 0xeb, 0x44, 0x46, 0x0f, 0x52, 0x98, 0xe8, 0xe5, 0x2f, 0xe6, 0x70, 0x52, 0x99, 0xbb, 0xd6, 0x18, 0xef, 0xd0, 0xb3, 0x63, 0x31, 0x56, 0x2f, 0x20, 0xb2, 0x0e, 0x86, 0x6d, 0x99, 0xc2, 0xd0, 0x4a, 0x01, 0x49, 0xf5, 0x64, 0xdd, 0xf6, 0x6b, 0xa3, 0x19, 0xf3, 0xb8, 0x48, 0x25, 0x39, 0x6e, 0xa8, 0xb8, 0x93, 0xba, 0x5b, 0x3e, 0xe5, 0xe5, 0x24, 0x5c, 0xfe, 0x6b, 0x61, 0x6e, 0x30, 0xa9, 0x00, 0xbf, 0x83, 0xbb, 0x76, 0x3d, 0x20, 0xb3, 0x30, 0x37, 0x01, 0xca, 0xbe, 0x94, 0x33, 0x41, 0x48, 0x88, 0x2a, 0xe4, 0xef, 0x14, 0xe6, 0xd9, 0xe6, 0xc7, 0x52, 0xbc, 0xe2, 0x53, 0xbd, 0xda, 0x57, 0x39, 0xe3, 0x3b, 0xdc, 0x32, 0xeb, 0x08, 0x28, 0x28, 0xc1, 0xc3, 0x99, 0xc2, 0x2f, 0xea } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.6", + /* Message to be signed */ + 73, + { 0x51, 0x76, 0xad, 0x7c, 0x99, 0xbe, 0x4c, 0xdb, 0xbb, 0x5d, 0x79, 0xba, 0x5f, 0x49, 0x6c, 0xad, 0x9f, 0x42, 0xdc, 0x25, 0xd5, 0x27, 0xa5, 0xd5, 0xe8, 0xe3, 0x35, 0x91, 0x79, 0x22, 0x5e, 0x6b, 0x0e, 0x43, 0x66, 0x6d, 0x3d, 0x82, 0xab, 0x5b, 0xaf, 0x42, 0x4c, 0x85, 0xc3, 0x31, 0x21, 0x60, 0x6e, 0xb7, 0x9a, 0xda, 0x6b, 0xaf, 0xca, 0xb5, 0xc1, 0xe2, 0x54, 0x6c, 0xab, 0xf6, 0xa3, 0x60, 0x03, 0x84, 0x05, 0xca, 0x18, 0xc0, 0x08, 0x36, 0x67 } +, + /* Signature */ + 129, + { 0x06, 0x27, 0x23, 0x8b, 0x0b, 0x93, 0xe4, 0xcf, 0x98, 0x57, 0x13, 0xd2, 0x91, 0x29, 0x6c, 0xed, 0xe3, 0x45, 0xe8, 0x8e, 0x17, 0x82, 0x45, 0x25, 0x53, 0x59, 0x39, 0xb3, 0xf3, 0xd5, 0xff, 0x4e, 0xbc, 0x40, 0x74, 0x00, 0x11, 0x49, 0x00, 0x25, 0xdf, 0xea, 0xae, 0xe9, 0x06, 0x38, 0xc5, 0x39, 0x1e, 0xb4, 0x4e, 0x9f, 0xf3, 0x70, 0x45, 0x7b, 0x60, 0xd5, 0xde, 0x80, 0xc1, 0x65, 0x38, 0xcb, 0x38, 0x60, 0x55, 0x95, 0x85, 0xca, 0xf5, 0xe3, 0x33, 0x2c, 0x7b, 0x1f, 0xdd, 0x8f, 0x45, 0xfb, 0x6e, 0x35, 0x57, 0xf2, 0xc7, 0xa6, 0x0d, 0x09, 0x9e, 0x94, 0xf8, 0xe9, 0x6b, 0xaa, 0x1e, 0x03, 0x19, 0x9a, 0xc8, 0x3c, 0xec, 0x8f, 0x9c, 0x16, 0xbb, 0x49, 0x15, 0x1a, 0x88, 0x72, 0xcb, 0xfe, 0x70, 0xf0, 0x02, 0xcf, 0x3b, 0x53, 0xb6, 0x11, 0xd6, 0xcb, 0xb6, 0x65, 0x89, 0x7c, 0xeb, 0xf5, 0x99 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.7", + /* Message to be signed */ + 20, + { 0xe1, 0x74, 0x71, 0x93, 0x64, 0xf7, 0xbd, 0xc8, 0x6e, 0x2f, 0x0c, 0x61, 0x26, 0x5b, 0xf8, 0x05, 0x7d, 0x64, 0x9c, 0xca } +, + /* Signature */ + 129, + { 0x09, 0x77, 0x19, 0x54, 0xfc, 0x8a, 0x1f, 0xee, 0xe9, 0x0f, 0x60, 0xc4, 0xb8, 0xa5, 0xbb, 0xd4, 0x62, 0xc6, 0x34, 0x37, 0x9a, 0xb3, 0xda, 0x19, 0xff, 0xeb, 0xa6, 0xe0, 0x31, 0xb4, 0x24, 0x3a, 0x83, 0x50, 0x9c, 0xee, 0xed, 0x6e, 0x01, 0x2a, 0x91, 0x63, 0xc6, 0x14, 0x5c, 0xf7, 0x05, 0x02, 0xa9, 0xfb, 0x0c, 0x21, 0xdb, 0x31, 0xfa, 0xd5, 0xad, 0x14, 0x69, 0x5d, 0xe0, 0x02, 0x62, 0xe4, 0xe5, 0x67, 0x09, 0x5e, 0x16, 0x11, 0x0c, 0x6e, 0x65, 0xd6, 0xbc, 0xb9, 0xcc, 0x02, 0xe9, 0x19, 0xf9, 0x0d, 0x19, 0xe7, 0x30, 0x7f, 0x44, 0x34, 0x50, 0x3f, 0x9f, 0xe0, 0x2c, 0x12, 0xc1, 0xd3, 0xf5, 0x0c, 0xc1, 0x60, 0x08, 0x6f, 0xe4, 0x60, 0x29, 0x8c, 0x88, 0x12, 0x25, 0xbf, 0xf2, 0xe9, 0xe3, 0x13, 0xda, 0x38, 0x44, 0x44, 0xbe, 0xc7, 0x2a, 0x67, 0xac, 0x34, 0x44, 0x67, 0xe8, 0x2b, 0x66 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.8", + /* Message to be signed */ + 232, + { 0x98, 0xcb, 0xc9, 0x1f, 0xd4, 0x9b, 0x50, 0x7c, 0x88, 0x7e, 0x97, 0xc3, 0xcf, 0xa9, 0xb5, 0x9c, 0x26, 0x00, 0x1f, 0xca, 0xc1, 0x64, 0x87, 0xf6, 0x00, 0x4f, 0x0b, 0x68, 0x74, 0x54, 0x63, 0x20, 0x02, 0xd5, 0x49, 0xb5, 0x46, 0x1f, 0xf1, 0x53, 0x0c, 0x0f, 0x5f, 0xc0, 0x9a, 0xac, 0xc4, 0x6a, 0xda, 0xda, 0x7d, 0xc9, 0xd7, 0xb3, 0xe2, 0x0f, 0xed, 0xfe, 0xec, 0xd8, 0xf2, 0xf1, 0x68, 0x41, 0x77, 0x32, 0x68, 0x54, 0x2e, 0x86, 0x43, 0x1c, 0x7f, 0xb4, 0xd1, 0x63, 0xf3, 0x1e, 0x8e, 0x31, 0x72, 0x20, 0x34, 0x26, 0xbc, 0x0d, 0x88, 0xa2, 0x3b, 0x13, 0x76, 0x34, 0xbf, 0xc7, 0x14, 0x01, 0x72, 0x20, 0xfb, 0xfb, 0xec, 0x88, 0x8e, 0x01, 0xe3, 0xef, 0xf7, 0xbb, 0xbd, 0xf9, 0x3f, 0x08, 0x3b, 0x88, 0xfd, 0xd6, 0x40, 0x7d, 0x98, 0x9b, 0xcc, 0x5e, 0xcb, 0x15, 0x3c, 0x9c, 0xee, 0x34, 0x10, 0xfd, 0x00, 0x6b, 0xcd, 0xf0, 0x7a, 0xf2, 0x28, 0x79, 0x0f, 0xd5, 0xe0, 0x4f, 0x5c, 0x0a, 0x1b, 0x63, 0x64, 0x8d, 0x48, 0x60, 0x9b, 0xf1, 0x63, 0xc6, 0xfd, 0x65, 0x60, 0x20, 0x75, 0x7c, 0x3c, 0x06, 0x38, 0xe1, 0xb8, 0x2d, 0x75, 0xe2, 0xb4, 0xb9, 0x08, 0xb7, 0xe0, 0xa3, 0xc8, 0xd7, 0x26, 0x6b, 0x80, 0x1f, 0x60, 0xfc, 0x2b, 0x4f, 0x31, 0x7e, 0xbb, 0x8b, 0xf2, 0x2a, 0xb9, 0xe1, 0xcb, 0x7b, 0x77, 0x84, 0x39, 0x5b, 0xd7, 0xb4, 0x24, 0x32, 0x9e, 0x86, 0x1d, 0x47, 0x86, 0x61, 0xf6, 0xdc, 0x12, 0x98, 0x51, 0x5f, 0x48, 0x56, 0x4a, 0x3f, 0xf9, 0x97, 0x35, 0xbb, 0x90, 0x03, 0x38, 0x75, 0xa2, 0x5b, 0xe8, 0xb7, 0x24, 0xf3 } +, + /* Signature */ + 129, + { 0x0f, 0x2d, 0x7a, 0x5e, 0xab, 0x83, 0x58, 0x45, 0x03, 0xd9, 0x4e, 0xbf, 0x7d, 0xde, 0x9e, 0xed, 0x49, 0x41, 0x10, 0xbe, 0x94, 0xed, 0x64, 0x8a, 0xf0, 0xcf, 0x6e, 0x89, 0x1b, 0x06, 0x2d, 0x2c, 0x9d, 0xef, 0x95, 0x87, 0x55, 0xb1, 0xa3, 0x08, 0x48, 0x8d, 0x16, 0x70, 0x74, 0x29, 0x51, 0xec, 0x00, 0x60, 0x54, 0x5d, 0x2e, 0xc4, 0x3f, 0xe8, 0x4a, 0xec, 0x89, 0x01, 0xad, 0xf4, 0xfe, 0x8d, 0x67, 0xaa, 0xe5, 0x7a, 0x31, 0x9f, 0x49, 0x1c, 0x85, 0xc2, 0x1c, 0xd7, 0xf9, 0xc5, 0x99, 0x81, 0x3c, 0xeb, 0x9d, 0xf8, 0x47, 0x78, 0xad, 0xc8, 0x2a, 0x33, 0xc4, 0xe7, 0x67, 0x4d, 0x7f, 0xbe, 0x13, 0x48, 0xdc, 0x20, 0x75, 0x51, 0x10, 0x4f, 0x54, 0x42, 0xac, 0xd6, 0x84, 0x86, 0x9a, 0xc2, 0x2c, 0xac, 0x51, 0x6c, 0xc9, 0x88, 0x7f, 0xd1, 0xd0, 0x21, 0xef, 0xcc, 0x54, 0xab, 0xda, 0xf2, 0xb6 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.9", + /* Message to be signed */ + 139, + { 0x3e, 0xed, 0x6b, 0xf1, 0x16, 0xcb, 0x31, 0xe0, 0xfd, 0xd4, 0xc5, 0xc9, 0x33, 0x58, 0xba, 0xb6, 0x8f, 0xbf, 0xa8, 0xb5, 0xc5, 0x15, 0xbc, 0xab, 0xf9, 0x05, 0x1c, 0xdf, 0x95, 0xa2, 0x43, 0xe5, 0xee, 0x68, 0x15, 0x15, 0x4e, 0xeb, 0x4a, 0xc1, 0x0f, 0x52, 0x31, 0xd0, 0x49, 0x38, 0x13, 0xe2, 0x81, 0x49, 0xe9, 0x68, 0x2b, 0xb1, 0xc8, 0xb7, 0x7a, 0x6e, 0x13, 0x60, 0xb2, 0xb2, 0xc0, 0xf9, 0xc3, 0x16, 0x1e, 0x41, 0x7e, 0xf6, 0xcb, 0x3d, 0x9a, 0xbb, 0xdc, 0x74, 0x2c, 0xe0, 0x25, 0xfa, 0xfc, 0xd5, 0x38, 0xc7, 0x7c, 0x4d, 0x07, 0x16, 0x49, 0x1d, 0xa5, 0x4b, 0xcd, 0xf1, 0x67, 0xb4, 0x7a, 0x61, 0xa0, 0x35, 0x27, 0xc9, 0x6e, 0x4b, 0x42, 0xbf, 0xdc, 0x98, 0x5b, 0x17, 0x87, 0x81, 0xb6, 0x92, 0x0f, 0x60, 0xf1, 0x1c, 0xd5, 0xfa, 0x76, 0x66, 0x3f, 0x56, 0xf3, 0x19, 0xf4, 0x50, 0xcc, 0x2a, 0x7f, 0x13, 0xbc, 0xce, 0x59, 0xe4, 0x1c, 0xb6, 0x66 } +, + /* Signature */ + 129, + { 0x07, 0x67, 0x3f, 0xa6, 0x83, 0xe0, 0x98, 0xbf, 0xa2, 0xb9, 0x55, 0xb6, 0xc3, 0x4e, 0x9c, 0xe8, 0xec, 0xcc, 0x5a, 0xb0, 0xab, 0x4c, 0x2c, 0xf7, 0x9b, 0x9b, 0xe1, 0xe6, 0x64, 0x42, 0x5a, 0x7c, 0x17, 0x7a, 0x47, 0xd5, 0x32, 0x0c, 0xd5, 0x70, 0x86, 0xf9, 0x51, 0x89, 0x18, 0x45, 0x09, 0x4b, 0x1f, 0xbb, 0xc9, 0xde, 0xe5, 0xf9, 0xb5, 0x56, 0xdf, 0x3e, 0x61, 0xe7, 0xe6, 0x69, 0x73, 0xd6, 0x3e, 0x69, 0xc9, 0xda, 0x17, 0x29, 0x6f, 0xe6, 0x15, 0xd6, 0x33, 0xc8, 0x62, 0x18, 0xdc, 0xa3, 0x99, 0x25, 0x8c, 0x04, 0xf8, 0x05, 0xbd, 0x04, 0xd9, 0xdc, 0x97, 0xa2, 0x9f, 0x39, 0xd6, 0x06, 0xff, 0x8e, 0x9c, 0x0a, 0x13, 0x71, 0xaa, 0xee, 0xc0, 0x03, 0xea, 0x27, 0x48, 0x95, 0xff, 0x7b, 0xa1, 0x50, 0x2b, 0x28, 0xf8, 0x17, 0x63, 0x02, 0xc2, 0x4e, 0xec, 0xe5, 0xb5, 0x28, 0xd6, 0x71, 0x00 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.10", + /* Message to be signed */ + 146, + { 0x08, 0x4e, 0xc2, 0x87, 0x86, 0x5e, 0x8f, 0xe6, 0x88, 0x04, 0x72, 0x37, 0x20, 0x97, 0xad, 0x5b, 0x96, 0x4c, 0x40, 0xa9, 0x35, 0xee, 0xd1, 0xbe, 0xa5, 0x1a, 0xb1, 0xb5, 0xbc, 0x75, 0xc8, 0x46, 0xbb, 0xcb, 0xd9, 0x54, 0x88, 0xe9, 0xec, 0xc3, 0x63, 0xcf, 0x07, 0x3a, 0x90, 0xb2, 0x0b, 0xe8, 0xb6, 0x79, 0x36, 0x46, 0x22, 0xf3, 0x45, 0xe1, 0x22, 0xd0, 0x56, 0x6a, 0xcd, 0x34, 0xa4, 0xae, 0x11, 0x24, 0x45, 0x25, 0xa3, 0x8f, 0x47, 0xdc, 0x1f, 0x92, 0xb1, 0x7f, 0x89, 0xed, 0xe0, 0x6d, 0x83, 0x6b, 0x44, 0x26, 0xec, 0xbb, 0xea, 0x79, 0x33, 0xac, 0x0e, 0x84, 0x7e, 0x55, 0x10, 0x33, 0xb5, 0xf7, 0xea, 0x4e, 0xaf, 0x1f, 0x63, 0xf3, 0x47, 0x9d, 0xb7, 0xea, 0xf8, 0x02, 0xc9, 0x96, 0xde, 0x92, 0x33, 0x86, 0xcd, 0x15, 0xb1, 0x22, 0xde, 0x5a, 0x23, 0x98, 0xd3, 0xf3, 0x97, 0x02, 0xc3, 0xe9, 0x06, 0x5c, 0x32, 0x73, 0x95, 0xb9, 0xa9, 0x95, 0xfa, 0x25, 0x4d, 0xe9, 0xc7, 0xad, 0xb4, 0x51 } +, + /* Signature */ + 129, + { 0x13, 0xa7, 0xf0, 0x04, 0xc0, 0xa8, 0x8d, 0x51, 0x3e, 0x2f, 0x1a, 0xae, 0xab, 0x41, 0x7f, 0xa0, 0xb2, 0x70, 0x2f, 0xb9, 0x3b, 0x82, 0x87, 0x20, 0xcc, 0xd8, 0x00, 0xcb, 0xb0, 0xaf, 0x5a, 0x19, 0x65, 0x72, 0x5b, 0x6e, 0xe0, 0x58, 0x71, 0x17, 0xcb, 0xcb, 0x81, 0xa4, 0x63, 0x18, 0x52, 0x1c, 0x95, 0x0d, 0xd8, 0x46, 0x9b, 0xd8, 0x55, 0x73, 0xf5, 0xd2, 0x9d, 0x86, 0x53, 0x03, 0xeb, 0xac, 0x45, 0xc7, 0xf6, 0x03, 0x1c, 0x6f, 0x93, 0x78, 0xeb, 0x12, 0xb4, 0x2f, 0x05, 0x09, 0x44, 0x31, 0x6f, 0x0b, 0x93, 0xdb, 0x89, 0x9b, 0xec, 0x93, 0x7d, 0x5d, 0x0f, 0x58, 0xed, 0x40, 0x70, 0x04, 0x01, 0xcd, 0x32, 0x65, 0xa6, 0xa4, 0x4b, 0x09, 0xbb, 0x11, 0xa4, 0x38, 0xee, 0xa0, 0x77, 0x15, 0xef, 0xe4, 0x2d, 0xe4, 0xe8, 0x80, 0x8f, 0x88, 0x24, 0x02, 0x61, 0x14, 0x8e, 0x8d, 0xe2, 0x93, 0xed } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.11", + /* Message to be signed */ + 154, + { 0x61, 0x07, 0x00, 0x00, 0x7c, 0x3c, 0x6c, 0xb0, 0x96, 0xc9, 0x94, 0xd6, 0x5d, 0x95, 0xc9, 0xb9, 0xa1, 0x47, 0xc3, 0x46, 0x14, 0xcd, 0x72, 0x2f, 0x29, 0xeb, 0xc5, 0xe0, 0x93, 0x78, 0x6f, 0x79, 0x09, 0x48, 0x02, 0x14, 0x1a, 0x31, 0x08, 0xd2, 0xec, 0x8a, 0x87, 0x4c, 0x53, 0x18, 0x7e, 0xb0, 0xd6, 0xee, 0x2a, 0x85, 0x91, 0x38, 0xcf, 0xbc, 0x29, 0x22, 0x15, 0x06, 0xd0, 0xbd, 0x89, 0xb0, 0xf3, 0xdb, 0xef, 0x50, 0x6b, 0xd1, 0xba, 0x40, 0x36, 0xb0, 0xf1, 0xec, 0x00, 0x73, 0x32, 0x70, 0x60, 0x75, 0x2b, 0x42, 0x8c, 0xfa, 0x12, 0xdb, 0x28, 0x0c, 0x53, 0xaa, 0xe5, 0xf3, 0xe3, 0x57, 0x0e, 0x91, 0x8c, 0xb0, 0x9b, 0x90, 0xe9, 0x84, 0x7f, 0x1f, 0x5c, 0xa4, 0x48, 0x7a, 0x6b, 0xf3, 0xed, 0xad, 0x42, 0x5f, 0x78, 0x40, 0x7e, 0xcb, 0xe3, 0xf9, 0xbc, 0x7c, 0xab, 0x00, 0x75, 0x66, 0x58, 0x79, 0x43, 0x1c, 0x6c, 0xc3, 0x9e, 0x0c, 0x7e, 0x67, 0x00, 0x60, 0x67, 0x41, 0x8b, 0xee, 0x8d, 0x0d, 0xb5, 0xe7, 0xdb, 0xe1, 0x2d, 0xa7, 0x16, 0xca } +, + /* Signature */ + 129, + { 0x1e, 0xbe, 0xaf, 0x85, 0xd1, 0x8f, 0x37, 0x84, 0x0e, 0x8a, 0x3e, 0xaf, 0x07, 0xd6, 0x9f, 0x52, 0x4d, 0x88, 0x3f, 0xa4, 0x2f, 0x29, 0x1e, 0x20, 0x07, 0xdb, 0x59, 0x5a, 0xd6, 0x93, 0x0e, 0x8d, 0x5a, 0x75, 0xb4, 0x0b, 0xb9, 0x5b, 0xeb, 0x72, 0xd7, 0xce, 0xd0, 0x38, 0x17, 0x97, 0x47, 0xe9, 0x66, 0x1d, 0x08, 0x38, 0x40, 0xd5, 0x87, 0xdc, 0xdf, 0x21, 0xc3, 0xad, 0xc7, 0xd4, 0x7a, 0x01, 0xf6, 0xec, 0xa9, 0xc7, 0xbf, 0x9e, 0x2a, 0x98, 0x87, 0x75, 0x1b, 0x36, 0xd1, 0xab, 0xaf, 0x25, 0xa3, 0x13, 0xfc, 0x29, 0xd7, 0xf8, 0x34, 0xd2, 0xa2, 0x48, 0x29, 0x85, 0x57, 0x5e, 0x1b, 0xe2, 0x4b, 0xc4, 0xef, 0x43, 0xa5, 0x7e, 0xf4, 0xb0, 0xa6, 0x83, 0x69, 0x93, 0xe1, 0x1b, 0x67, 0x07, 0x85, 0x04, 0xe3, 0xb7, 0x9c, 0x72, 0x17, 0x75, 0xf5, 0xb9, 0x9b, 0xfa, 0xcc, 0xc4, 0x8a, 0x8c, 0x34 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.12", + /* Message to be signed */ + 6, + { 0xda, 0x31, 0xf9, 0xbe, 0x26, 0x09 } +, + /* Signature */ + 129, + { 0x1d, 0x2b, 0xba, 0xfc, 0xa4, 0x1c, 0xa0, 0x6c, 0x4b, 0x81, 0x1c, 0xb9, 0xd8, 0x36, 0x96, 0x87, 0x16, 0x6d, 0x14, 0xd9, 0xf9, 0x2c, 0x5b, 0x98, 0xfc, 0x7c, 0x77, 0x2f, 0x2d, 0x75, 0xd3, 0x5a, 0x5f, 0x9a, 0xcc, 0xe5, 0x9b, 0x99, 0xef, 0xb2, 0xdc, 0xb9, 0x7d, 0xcc, 0xbb, 0xc8, 0x6d, 0x7f, 0xd6, 0xb4, 0xae, 0x8b, 0xea, 0xb1, 0xe9, 0x81, 0xe6, 0xc7, 0x74, 0x5a, 0x1b, 0xfb, 0x4c, 0x1f, 0x44, 0xa4, 0x72, 0xb2, 0xad, 0x07, 0xd4, 0x1c, 0xc1, 0x75, 0x15, 0xb7, 0xb1, 0x4a, 0x49, 0x99, 0x0b, 0x24, 0x34, 0x42, 0xff, 0x2c, 0x8f, 0xe5, 0x05, 0xb1, 0x84, 0x9f, 0xa9, 0x91, 0xca, 0xcf, 0x68, 0x09, 0xa2, 0x0e, 0x55, 0xf2, 0xaf, 0x77, 0x98, 0x87, 0x0d, 0x65, 0x77, 0x6f, 0x1f, 0x9e, 0xe4, 0x87, 0x97, 0xe3, 0x13, 0xaa, 0x66, 0xa4, 0x7e, 0x69, 0x5f, 0x3e, 0x73, 0x1b, 0x2c, 0x7f, 0x30 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.13", + /* Message to be signed */ + 9, + { 0xf9, 0x8b, 0xe5, 0x2d, 0x9a, 0x5e, 0x55, 0xad, 0x92 } +, + /* Signature */ + 129, + { 0x29, 0x2e, 0xa3, 0x4d, 0x3e, 0x61, 0x18, 0xbf, 0x8c, 0xd0, 0x54, 0xe2, 0x15, 0x17, 0xe8, 0x63, 0xce, 0x7c, 0xb7, 0xdd, 0x72, 0x73, 0x30, 0x8f, 0x7e, 0xcf, 0xea, 0xcf, 0x9b, 0x45, 0x75, 0x83, 0xd9, 0xb9, 0xb9, 0x7c, 0x54, 0xab, 0xf7, 0x4e, 0x5a, 0x5c, 0xa3, 0x6a, 0x87, 0x06, 0x7e, 0x47, 0xd6, 0x7a, 0xa0, 0x47, 0xa1, 0xc2, 0xed, 0x7a, 0x23, 0xd0, 0x55, 0xab, 0x4f, 0x09, 0x4a, 0x83, 0xc4, 0x39, 0xef, 0x8d, 0xd2, 0xd0, 0x20, 0x35, 0xef, 0x05, 0x62, 0xd9, 0x67, 0x31, 0x3d, 0x81, 0x10, 0x2f, 0xc6, 0x8b, 0x74, 0x52, 0x5b, 0xb0, 0xe1, 0xd7, 0x96, 0x2e, 0xb2, 0x75, 0x8e, 0xc5, 0xe5, 0xae, 0xab, 0x65, 0xa9, 0x3d, 0x2e, 0xc8, 0xe6, 0x55, 0x40, 0x5a, 0xf8, 0x8c, 0x00, 0xfa, 0x35, 0xf5, 0x9d, 0xe9, 0xd0, 0xcd, 0x80, 0x45, 0xab, 0xd3, 0x71, 0x73, 0xb9, 0xfc, 0x6c, 0x51, 0xd8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.14", + /* Message to be signed */ + 215, + { 0xf4, 0x38, 0xef, 0xf8, 0x4c, 0x37, 0x3f, 0xc1, 0x27, 0x44, 0xa3, 0x84, 0x15, 0x82, 0x43, 0xdd, 0x97, 0xf4, 0x36, 0x5e, 0x87, 0xd7, 0x1e, 0x8b, 0x56, 0xb2, 0x97, 0x91, 0xdf, 0x44, 0xad, 0xf3, 0x49, 0xe7, 0x62, 0x60, 0x04, 0xa2, 0xc5, 0x33, 0x35, 0xec, 0x63, 0x52, 0xcc, 0xe2, 0xed, 0xd9, 0x63, 0x94, 0x7f, 0xd2, 0x39, 0x38, 0x93, 0xc2, 0x48, 0xba, 0x1b, 0x84, 0x08, 0x42, 0xca, 0x77, 0x6c, 0x31, 0x72, 0x9f, 0x70, 0x7a, 0xf5, 0x04, 0x11, 0x00, 0x1c, 0x28, 0x7f, 0xba, 0x8f, 0xe7, 0x25, 0x02, 0x32, 0x0c, 0x44, 0x5b, 0xb1, 0x43, 0xfb, 0x7b, 0xf5, 0x39, 0x4e, 0xc1, 0xfb, 0x2c, 0xd5, 0x01, 0x59, 0x24, 0x32, 0x15, 0x40, 0x91, 0xde, 0x5a, 0x23, 0x65, 0xd6, 0x78, 0xf3, 0x57, 0x82, 0xfe, 0xa8, 0xb4, 0x7f, 0x64, 0xd6, 0x09, 0x19, 0xf0, 0xf1, 0xd5, 0xaf, 0xa7, 0x62, 0x6c, 0x40, 0xd1, 0x6c, 0xec, 0x19, 0xbf, 0xe0, 0x25, 0xd1, 0x16, 0xf4, 0x2d, 0x22, 0xe2, 0x0a, 0xdb, 0x56, 0x37, 0x5a, 0xd7, 0x70, 0x89, 0xf9, 0xa9, 0x33, 0x81, 0xfd, 0x78, 0xb7, 0xb1, 0x51, 0x1c, 0xb4, 0xe4, 0x98, 0x4d, 0x2d, 0xdc, 0x7c, 0x9d, 0x75, 0xb3, 0x10, 0xf2, 0x95, 0x42, 0x25, 0x60, 0xd6, 0x6e, 0x36, 0x02, 0xa8, 0x71, 0x20, 0x96, 0x16, 0x13, 0x1a, 0x84, 0x71, 0x43, 0xdd, 0x07, 0x8f, 0x23, 0x58, 0x7d, 0xb5, 0x02, 0xdd, 0xa0, 0x3e, 0x18, 0x60, 0x64, 0x82, 0xdb, 0xbe, 0x01, 0x4e, 0xa0, 0x83, 0xb7, 0xec, 0x16, 0x1b } +, + /* Signature */ + 129, + { 0x0e, 0xaf, 0xeb, 0xf1, 0x5d, 0x84, 0xee, 0x4a, 0x13, 0xf1, 0xa8, 0x2b, 0x84, 0x05, 0x11, 0x86, 0x41, 0xe2, 0x2e, 0x51, 0xda, 0x94, 0xd8, 0x58, 0x87, 0xfc, 0x4a, 0x3b, 0x11, 0xf0, 0x32, 0x49, 0xcc, 0x39, 0xa0, 0x37, 0x45, 0x01, 0x07, 0x1c, 0x7e, 0xef, 0x4a, 0xba, 0xa1, 0x14, 0x08, 0xd0, 0x2f, 0xae, 0x17, 0x86, 0xde, 0xa3, 0x75, 0x88, 0x47, 0x9c, 0x90, 0xd6, 0x27, 0x69, 0x85, 0x91, 0xc3, 0xba, 0xe1, 0xfe, 0xfd, 0x6e, 0x8c, 0x40, 0xe3, 0xff, 0x4b, 0x9f, 0x60, 0x61, 0xe0, 0x6c, 0x12, 0xfd, 0xd2, 0x1c, 0x7f, 0x45, 0xdd, 0xc5, 0xb7, 0x8d, 0x1c, 0xbc, 0x41, 0xc1, 0x57, 0x06, 0xfa, 0x20, 0xba, 0x92, 0xf9, 0x9f, 0x58, 0xb2, 0x2b, 0xe2, 0x76, 0x75, 0xbe, 0xe0, 0x81, 0xa0, 0x60, 0x67, 0xee, 0xd1, 0x58, 0xf8, 0xe2, 0x0b, 0xf0, 0x4a, 0x6e, 0x96, 0x8f, 0x71, 0x9a, 0x32, 0x34 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.15", + /* Message to be signed */ + 89, + { 0xfa, 0x1c, 0x0f, 0x7b, 0x10, 0x15, 0xa8, 0x95, 0xb1, 0xa5, 0x65, 0xf3, 0x29, 0x96, 0xb2, 0xb8, 0xcc, 0xfd, 0x86, 0x4b, 0x95, 0x54, 0x4d, 0xbb, 0x9c, 0xf4, 0xf6, 0xe1, 0xa8, 0x41, 0xde, 0x92, 0x06, 0xd5, 0x57, 0x26, 0xfd, 0xf7, 0xee, 0xa2, 0xbf, 0x33, 0x6a, 0x82, 0x9f, 0xd2, 0xbc, 0x12, 0x09, 0xbd, 0x21, 0x5a, 0xab, 0xb9, 0x77, 0xd2, 0x3a, 0x08, 0x3f, 0x10, 0xae, 0x69, 0xdb, 0x43, 0x7c, 0xa3, 0x2d, 0x7b, 0xfe, 0x4c, 0x88, 0x25, 0xb9, 0x34, 0x88, 0xf0, 0x1a, 0xfd, 0xf7, 0x84, 0x45, 0x8c, 0xef, 0x5c, 0xdd, 0x8d, 0xff, 0xdd, 0x17 } +, + /* Signature */ + 129, + { 0x25, 0xe2, 0x2e, 0x6d, 0xf7, 0xfc, 0x6b, 0xd4, 0xe0, 0xf6, 0x1e, 0xbc, 0x8d, 0xa0, 0x63, 0xfe, 0x47, 0x8a, 0x3e, 0xd7, 0x4d, 0x68, 0xf7, 0x76, 0x34, 0x35, 0xe0, 0xe3, 0x74, 0xf6, 0x52, 0x62, 0xa5, 0xd7, 0x61, 0x2e, 0x86, 0x78, 0x59, 0x61, 0x22, 0xc0, 0xe5, 0xb8, 0xfa, 0x0c, 0x0b, 0x12, 0x81, 0x2b, 0xa9, 0x65, 0x3a, 0x0f, 0x27, 0x38, 0x83, 0xc6, 0x26, 0x4c, 0x6d, 0xfb, 0x74, 0xbb, 0x34, 0x40, 0x5d, 0x2a, 0x04, 0x30, 0x43, 0xfb, 0xb0, 0xab, 0xf2, 0xaf, 0x7a, 0x12, 0x3d, 0x2d, 0xdb, 0xf1, 0x69, 0x92, 0xe0, 0x9b, 0xaa, 0x37, 0xd7, 0x31, 0xd7, 0x2e, 0xf1, 0x99, 0x62, 0x65, 0x8a, 0x8f, 0xb0, 0x10, 0xa1, 0x0f, 0x7d, 0x55, 0x62, 0xad, 0x54, 0x33, 0x47, 0x90, 0x01, 0xaf, 0x36, 0xd3, 0xd3, 0x26, 0xea, 0xdb, 0x2e, 0x9a, 0xbe, 0xc7, 0xb5, 0x55, 0x70, 0x9d, 0x5d, 0x47, 0xe9 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.16", + /* Message to be signed */ + 223, + { 0x82, 0x8e, 0xbe, 0x2f, 0x51, 0xe5, 0x88, 0x29, 0xcf, 0xa6, 0x15, 0x26, 0xdd, 0xed, 0x7e, 0x1f, 0x1b, 0xa3, 0x11, 0xdb, 0xf1, 0x06, 0x4c, 0x08, 0xac, 0x0b, 0xb5, 0xd6, 0x71, 0x6e, 0xab, 0x29, 0x8a, 0x23, 0xd6, 0x3b, 0x79, 0x3f, 0xfd, 0x9d, 0x9c, 0xea, 0x60, 0x22, 0x95, 0x98, 0x82, 0x3f, 0x28, 0x2f, 0x10, 0x7b, 0x6e, 0xe8, 0x8a, 0x53, 0xfd, 0x93, 0xe7, 0xdd, 0xd4, 0x8a, 0x73, 0x1a, 0x21, 0x09, 0xff, 0xed, 0xc8, 0x9a, 0xeb, 0xa2, 0xc0, 0xf1, 0x6b, 0xcb, 0x14, 0x0a, 0x0a, 0x89, 0xdc, 0x57, 0xee, 0x8b, 0x5d, 0x00, 0x0a, 0x21, 0x42, 0x17, 0x5b, 0xc7, 0x07, 0xbb, 0x40, 0x9a, 0xae, 0x3a, 0x03, 0x9c, 0x66, 0x3d, 0x01, 0x9a, 0x0b, 0xd9, 0x13, 0xc1, 0x3f, 0x7f, 0xf6, 0xf6, 0xb9, 0x1e, 0x90, 0x5a, 0x58, 0x9d, 0x38, 0xb1, 0x50, 0x48, 0x5d, 0x89, 0x09, 0x2d, 0x18, 0xa3, 0xa7, 0x62, 0x25, 0x27, 0x65, 0x52, 0x5d, 0x98, 0x45, 0x66, 0x42, 0x5b, 0x05, 0x77, 0x0d, 0xe9, 0xa8, 0xbe, 0xf4, 0x43, 0xff, 0x5f, 0xc1, 0x48, 0x33, 0xaf, 0xa4, 0xcc, 0xec, 0xe5, 0x42, 0xd4, 0xf2, 0xce, 0xf1, 0xe7, 0x96, 0xf5, 0x9f, 0xb3, 0xa4, 0xbf, 0x37, 0xcb, 0x67, 0x7a, 0xe4, 0x22, 0x36, 0x66, 0xc8, 0x2b, 0x31, 0xa1, 0x6a, 0x6c, 0xd7, 0x01, 0xa0, 0x49, 0x3c, 0xd9, 0x96, 0x86, 0x6c, 0x84, 0xbf, 0xcd, 0xdf, 0x85, 0x2b, 0x19, 0xff, 0xc8, 0x9e, 0x93, 0x61, 0x79, 0xfc, 0xe8, 0xb9, 0x9e, 0x72, 0xfd, 0x4a, 0xfc, 0x28, 0xb5, 0x11, 0x73, 0xaf, 0xbb, 0x25, 0xc4, 0xc7 } +, + /* Signature */ + 129, + { 0x16, 0x17, 0x55, 0x9e, 0x43, 0xba, 0x18, 0x2e, 0x95, 0x34, 0x86, 0x43, 0x6f, 0x15, 0xb6, 0x02, 0x83, 0x1e, 0x42, 0xee, 0xd2, 0x03, 0xc2, 0x69, 0xf6, 0x53, 0xbf, 0x63, 0x9c, 0x2b, 0x76, 0x0b, 0x0d, 0x49, 0xfb, 0x53, 0x2c, 0xa8, 0xad, 0x01, 0xe7, 0xb4, 0xaf, 0x83, 0x72, 0x92, 0x55, 0xdb, 0x55, 0x9b, 0xcf, 0x55, 0xfa, 0xb3, 0x65, 0x9c, 0xeb, 0xec, 0xd5, 0x37, 0x69, 0x4f, 0xef, 0x2d, 0xef, 0x9c, 0x9e, 0x76, 0x2d, 0x05, 0xd2, 0x32, 0x1e, 0xd6, 0x88, 0xc3, 0xf7, 0xe2, 0xc0, 0x57, 0x33, 0xab, 0x4f, 0xa8, 0x1b, 0x08, 0xcf, 0x79, 0xfa, 0xcb, 0x75, 0xc3, 0x20, 0x0b, 0x7a, 0x48, 0x3a, 0xf0, 0x8c, 0xb1, 0x83, 0xc5, 0x09, 0x27, 0xcc, 0x61, 0x69, 0xe4, 0x32, 0xf7, 0xfc, 0x9b, 0x11, 0x78, 0x0d, 0xbf, 0x4d, 0x3b, 0x72, 0xd2, 0xd0, 0xb8, 0x55, 0x93, 0xd8, 0xb5, 0xb0, 0x18, 0x2a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.17", + /* Message to be signed */ + 47, + { 0xbb, 0x4a, 0x6e, 0xcc, 0xbd, 0xd6, 0xde, 0x0a, 0xc5, 0xc3, 0xb7, 0xf9, 0x97, 0x98, 0x10, 0x4a, 0x58, 0x69, 0xc1, 0xcf, 0x1a, 0x1f, 0xac, 0x7f, 0x85, 0x9f, 0xe9, 0x51, 0x49, 0x29, 0x7e, 0xb7, 0x79, 0x11, 0x00, 0x59, 0xe2, 0x69, 0xf1, 0x27, 0x56, 0xf0, 0x8a, 0x54, 0x8b, 0x66, 0xaf } +, + /* Signature */ + 129, + { 0x27, 0x7b, 0xae, 0x63, 0xe6, 0xe3, 0x25, 0x3a, 0x0e, 0x20, 0x4f, 0x4e, 0x6c, 0x9f, 0xe8, 0x4b, 0x04, 0x0b, 0x86, 0x4f, 0x21, 0xed, 0xd4, 0x42, 0x6d, 0x82, 0xbe, 0x8f, 0x1b, 0x91, 0x1b, 0x0b, 0xd2, 0x81, 0xcf, 0x11, 0x49, 0x53, 0xd4, 0x02, 0x09, 0xda, 0x2e, 0x9a, 0xae, 0x13, 0x3b, 0xcd, 0x18, 0x55, 0xef, 0x0a, 0x99, 0x69, 0x3a, 0x94, 0x43, 0xc9, 0x3f, 0x6d, 0xd2, 0x75, 0xf0, 0x58, 0xfd, 0x1b, 0xb6, 0x95, 0x32, 0xb6, 0x4a, 0x1d, 0xd7, 0xe1, 0xd0, 0xe7, 0x80, 0xd7, 0x52, 0x04, 0xfa, 0x8c, 0x61, 0xc2, 0xeb, 0x5d, 0xe8, 0x82, 0x72, 0xcb, 0x93, 0xae, 0xf0, 0x80, 0xf7, 0x02, 0xbb, 0x78, 0x88, 0x94, 0x25, 0xa5, 0xf1, 0x66, 0xf6, 0x3b, 0x5b, 0x1a, 0x31, 0xec, 0x5c, 0x1c, 0x26, 0xa5, 0x99, 0xfa, 0xfe, 0x58, 0x77, 0x42, 0x98, 0xb9, 0x7d, 0xb3, 0x14, 0xfc, 0x81, 0xd0, 0x92 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.18", + /* Message to be signed */ + 256, + { 0xf1, 0xd1, 0x11, 0xad, 0x08, 0xe0, 0x38, 0xca, 0x3a, 0xb4, 0xe5, 0x2e, 0x5e, 0xab, 0x71, 0x01, 0x87, 0x6c, 0xa9, 0xbe, 0x62, 0x6a, 0x13, 0x59, 0x17, 0xf4, 0x5b, 0x1f, 0x9d, 0x1b, 0x32, 0xef, 0xe4, 0xff, 0x86, 0x7a, 0xb8, 0xa3, 0x05, 0xf9, 0x49, 0xc0, 0x04, 0x8b, 0x25, 0xf5, 0x46, 0x22, 0x61, 0xb1, 0xa3, 0x49, 0x3b, 0x81, 0x90, 0x21, 0x0f, 0x5c, 0xfa, 0x6b, 0xf7, 0xe5, 0xc3, 0x00, 0x54, 0x98, 0xde, 0xec, 0xc1, 0xe1, 0xc5, 0x04, 0xf3, 0xa3, 0x49, 0x98, 0xbe, 0x6a, 0xd6, 0xac, 0x00, 0x40, 0x51, 0xc4, 0xe0, 0xa3, 0xdb, 0x2c, 0x22, 0xeb, 0x5e, 0x14, 0x16, 0x55, 0x28, 0xdf, 0x78, 0x12, 0xa2, 0x0d, 0x5c, 0x7f, 0x05, 0xb9, 0x40, 0xca, 0x13, 0xe9, 0x38, 0x3a, 0xe0, 0x0d, 0x6c, 0xd4, 0xd0, 0xf4, 0xae, 0x3d, 0xad, 0x04, 0x7a, 0xb9, 0xc4, 0x17, 0x8d, 0xb6, 0x6d, 0x3b, 0x80, 0x96, 0x0c, 0xaf, 0x0a, 0x92, 0x4d, 0xc9, 0x4e, 0xb8, 0xe0, 0x77, 0x09, 0xbc, 0xdb, 0x34, 0x9e, 0x90, 0xfa, 0x2e, 0x10, 0xc5, 0xd5, 0x26, 0xd2, 0x21, 0x9c, 0xa7, 0x6f, 0x88, 0x01, 0xfd, 0xc6, 0x61, 0xbd, 0xca, 0x6a, 0x93, 0xda, 0x48, 0xd0, 0x45, 0xac, 0x37, 0x51, 0x34, 0xcc, 0xd6, 0xff, 0x7c, 0x52, 0xfd, 0x15, 0xc7, 0xcd, 0x3d, 0x1f, 0x31, 0xaf, 0xe5, 0x04, 0xbc, 0xe7, 0xc0, 0x33, 0x3a, 0x89, 0x79, 0xe3, 0xce, 0xcc, 0x53, 0xc4, 0xea, 0xdd, 0x7d, 0x95, 0xd4, 0x6f, 0xa3, 0xb2, 0xa9, 0xf0, 0x06, 0x10, 0x0d, 0x6b, 0xfc, 0x0e, 0xd5, 0xee, 0x77, 0x69, 0x4f, 0xf1, 0xa2, 0x4e, 0x16, 0xa5, 0x44, 0xde, 0x71, 0x46, 0x52, 0x90, 0xdd, 0xdd, 0x18, 0x9f, 0x01, 0x67, 0x03, 0x59, 0xf8, 0xc6, 0xb5, 0xd4, 0xc6, 0xb6, 0xb9, 0xf5, 0xc5, 0x7a, 0xa5, 0xa3, 0x8f, 0x07, 0x99 } +, + /* Signature */ + 129, + { 0x0d, 0xe9, 0x42, 0x31, 0xc0, 0x6a, 0xb1, 0x87, 0xb0, 0x0d, 0xda, 0x2b, 0x34, 0xe2, 0xb4, 0xcb, 0xac, 0x41, 0xf6, 0x08, 0xc4, 0x8c, 0x72, 0x27, 0xa6, 0x28, 0x2a, 0x17, 0x9e, 0x58, 0xc3, 0x2e, 0xf5, 0xdd, 0xc9, 0x76, 0x4f, 0xa2, 0xdf, 0xc3, 0xfb, 0xe0, 0x21, 0xdd, 0xb4, 0x81, 0x56, 0xa6, 0x37, 0x3c, 0xd6, 0x9b, 0x85, 0xd3, 0x64, 0xd8, 0x9b, 0x5a, 0x32, 0xfa, 0xbb, 0x2d, 0x46, 0x5d, 0x05, 0x62, 0xd4, 0xa1, 0xdd, 0x6f, 0xca, 0x64, 0x78, 0x0b, 0x06, 0x2a, 0x94, 0x71, 0x24, 0xa7, 0xfc, 0x0b, 0x82, 0xe4, 0xfe, 0xd1, 0x2b, 0x8b, 0x4f, 0x72, 0x6a, 0x0c, 0x85, 0x39, 0xc6, 0xcd, 0xe2, 0x1a, 0xf6, 0x55, 0xac, 0xc8, 0xde, 0x1e, 0x7b, 0xa9, 0xd6, 0x7b, 0x87, 0xb8, 0xe7, 0x77, 0xd4, 0x8a, 0xcd, 0x86, 0x8a, 0x80, 0xdb, 0x15, 0x31, 0x4f, 0x35, 0x55, 0x60, 0x10, 0x35, 0x77, 0xeb } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.19", + /* Message to be signed */ + 193, + { 0x9c, 0x4e, 0xcc, 0x4b, 0x24, 0x44, 0xa4, 0x01, 0xbf, 0xb6, 0xf4, 0xb7, 0x24, 0x49, 0x23, 0xa5, 0xad, 0x33, 0x86, 0xc3, 0xb8, 0x41, 0x67, 0x8c, 0xf5, 0xe6, 0x44, 0x7b, 0x8a, 0x3a, 0x07, 0x59, 0x86, 0xc3, 0x3f, 0xd0, 0x01, 0xb8, 0x43, 0x72, 0x4d, 0xdd, 0xc4, 0x21, 0x2f, 0xf4, 0x5a, 0xb3, 0xfe, 0xca, 0xa9, 0x0a, 0x16, 0xf6, 0xb5, 0x59, 0x2c, 0x51, 0x5c, 0xc4, 0xee, 0x54, 0xae, 0xa4, 0x59, 0x34, 0x32, 0x16, 0x70, 0x96, 0x67, 0x8f, 0x93, 0x41, 0x59, 0x85, 0x6d, 0x14, 0xc4, 0x32, 0xe7, 0xd6, 0xd2, 0x8d, 0x71, 0xb2, 0x68, 0x7f, 0x54, 0xed, 0x71, 0x9e, 0x5c, 0x20, 0x11, 0x00, 0x68, 0x8e, 0x85, 0xf2, 0x0e, 0x79, 0xa9, 0xee, 0x8a, 0xa4, 0xb6, 0x14, 0x31, 0x34, 0x3d, 0x1e, 0x99, 0xc2, 0x14, 0x35, 0xc6, 0x1e, 0x8b, 0xc1, 0x04, 0xf2, 0xba, 0xd5, 0x29, 0x60, 0xfc, 0xee, 0xe6, 0x7b, 0x85, 0x03, 0x3d, 0x3a, 0xee, 0xfa, 0xe4, 0x13, 0xce, 0x29, 0x70, 0x1e, 0xff, 0xcb, 0x02, 0xb4, 0x84, 0xa0, 0x31, 0xe2, 0xf3, 0x19, 0xef, 0x7e, 0xd0, 0xd6, 0xe6, 0x9b, 0x29, 0x16, 0xee, 0xb3, 0x8c, 0x4f, 0x19, 0x42, 0xba, 0x23, 0xc2, 0xa1, 0x79, 0x0c, 0xe3, 0xfe, 0x09, 0xd0, 0x1b, 0x9b, 0x9f, 0xe6, 0xdb, 0xa8, 0xdc, 0x21, 0x0e, 0xaa, 0x8f, 0xe7, 0x3c, 0xa7, 0x6f, 0x1b, 0x5b } +, + /* Signature */ + 129, + { 0x18, 0x53, 0xc2, 0x1a, 0x4a, 0x18, 0x54, 0x7d, 0x86, 0x7b, 0x3c, 0xed, 0x02, 0xda, 0xf0, 0xb2, 0x2c, 0xe8, 0xd4, 0xd5, 0xaf, 0x2b, 0x8e, 0xf5, 0xf7, 0xc8, 0xfd, 0x38, 0x5b, 0x81, 0x53, 0x64, 0x8d, 0x81, 0x83, 0x1d, 0x6a, 0xcb, 0x5d, 0xa8, 0x30, 0xf6, 0x77, 0x40, 0x25, 0x9f, 0xfb, 0x33, 0x9f, 0x7b, 0x90, 0xaf, 0x48, 0x83, 0x81, 0x9c, 0x47, 0x15, 0xe0, 0x8c, 0x28, 0x99, 0xd4, 0xc7, 0x24, 0x6e, 0x07, 0xe5, 0xbc, 0x6e, 0xf3, 0xcf, 0xd9, 0xa0, 0x4d, 0xa0, 0x6c, 0x43, 0xe9, 0x5c, 0x77, 0x2b, 0xe2, 0x21, 0xcf, 0xaa, 0xf6, 0x95, 0x4e, 0xf9, 0x33, 0x31, 0xe5, 0x95, 0xff, 0x48, 0x92, 0x1f, 0x05, 0xfc, 0xe8, 0xfa, 0x0d, 0x42, 0x9e, 0x0c, 0x99, 0x56, 0x2a, 0x9c, 0x2f, 0x68, 0xeb, 0xf3, 0x2c, 0xf1, 0xc6, 0xc6, 0xbb, 0x8b, 0x27, 0x4a, 0x2e, 0x42, 0xd6, 0x71, 0x59, 0x12, 0xff } + +} +, +{ + "PKCS#1 v1.5 Signature Example 12.20", + /* Message to be signed */ + 146, + { 0xc3, 0x81, 0xe6, 0x03, 0x99, 0x86, 0x51, 0x66, 0xd2, 0xba, 0xa0, 0x31, 0x45, 0x26, 0x83, 0x34, 0x18, 0x40, 0x39, 0xe0, 0x53, 0x35, 0xa3, 0x00, 0xc2, 0x80, 0x4e, 0x2b, 0xfe, 0xf5, 0xa7, 0xd1, 0x4c, 0x44, 0x3d, 0x65, 0x38, 0xe1, 0x6b, 0xdf, 0x9d, 0xa7, 0xad, 0x1f, 0xea, 0x63, 0x4e, 0xbf, 0xe1, 0x13, 0xbc, 0x82, 0x1e, 0x79, 0xa4, 0x49, 0xb2, 0xeb, 0x2f, 0x57, 0xc2, 0x1f, 0xba, 0x35, 0xff, 0xcc, 0x6a, 0x7e, 0x52, 0x55, 0x72, 0x27, 0x7e, 0x8f, 0x55, 0x37, 0xc7, 0xb5, 0xb9, 0x79, 0x4d, 0xef, 0xb3, 0x9a, 0xab, 0x06, 0x07, 0x85, 0xd1, 0x99, 0x40, 0x02, 0xdc, 0xf8, 0x07, 0x01, 0x2e, 0x1d, 0x17, 0x91, 0xda, 0x94, 0x3b, 0x2b, 0x75, 0x9c, 0x36, 0x6b, 0xb4, 0x24, 0xe4, 0x2c, 0x9c, 0x20, 0x43, 0xce, 0x78, 0x8a, 0x25, 0xfb, 0xfe, 0xbb, 0x87, 0xe7, 0x4c, 0xb0, 0x20, 0xb1, 0x1e, 0x8e, 0xaf, 0x16, 0x18, 0x84, 0xd6, 0x67, 0x2b, 0xbe, 0x9c, 0x09, 0xfb, 0xb3, 0xb8, 0xaf, 0xa0, 0x61 } +, + /* Signature */ + 129, + { 0x19, 0x90, 0x69, 0x57, 0x37, 0x53, 0x01, 0x8f, 0x33, 0x59, 0x2a, 0xf1, 0x5c, 0x1d, 0x31, 0x31, 0xbf, 0x5d, 0x8a, 0xc4, 0xf6, 0x4c, 0xf6, 0x14, 0xd3, 0xa0, 0x1b, 0xf3, 0x72, 0xdf, 0x00, 0x2e, 0xb5, 0xb5, 0xfc, 0x8f, 0x82, 0xba, 0x13, 0x7f, 0x83, 0xdc, 0x14, 0x2e, 0xde, 0x38, 0xc5, 0x81, 0x80, 0xe7, 0xbd, 0xa6, 0x9c, 0x4f, 0x1b, 0xc7, 0xbf, 0x96, 0xec, 0xd3, 0xfa, 0x79, 0xbc, 0xcb, 0xdd, 0xb7, 0xd9, 0x2e, 0x4f, 0xd8, 0x64, 0xc5, 0xfa, 0x93, 0x3a, 0x4d, 0xfc, 0x60, 0x0e, 0x10, 0x83, 0x00, 0x8a, 0x38, 0x6f, 0x4d, 0x02, 0x2c, 0x20, 0x24, 0xff, 0x7e, 0x0b, 0x37, 0x22, 0xea, 0xfe, 0xa0, 0x5a, 0x1e, 0x02, 0xc7, 0xa6, 0x3e, 0xeb, 0x40, 0xf4, 0xf4, 0xc4, 0xf6, 0x60, 0xc3, 0x24, 0x72, 0xa0, 0xa7, 0x89, 0x23, 0xe3, 0x86, 0x3a, 0x99, 0x44, 0x5e, 0x7c, 0xfe, 0x27, 0x00, 0x60 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 13: A 1031-bit RSA key pair", +{ + /* Modulus */ + 129, + { 0x70, 0xe9, 0x23, 0xa5, 0xa0, 0xcd, 0x8e, 0xcd, 0xf9, 0x9b, 0xbe, 0x93, 0xd7, 0xd0, 0x28, 0x82, 0x95, 0x5d, 0x91, 0xb6, 0xef, 0xe3, 0xce, 0xc8, 0x6c, 0x93, 0xd2, 0x1c, 0x0a, 0xc3, 0x01, 0xb8, 0x29, 0x3e, 0x51, 0x43, 0x5b, 0x87, 0x8b, 0xc6, 0xb3, 0x4b, 0xed, 0x41, 0x11, 0x59, 0x0e, 0x76, 0x46, 0x76, 0x58, 0x8b, 0x11, 0x6c, 0x2a, 0x36, 0xa4, 0xc7, 0x7e, 0xd9, 0xc9, 0x0a, 0x13, 0xc1, 0x4d, 0x23, 0xe1, 0x99, 0x47, 0x87, 0xfc, 0xdb, 0x8f, 0x5c, 0x97, 0x41, 0x0f, 0xca, 0xd4, 0x04, 0x5b, 0x85, 0x85, 0x70, 0x2c, 0xce, 0x29, 0xda, 0x11, 0xf9, 0x7e, 0x79, 0xa9, 0x7c, 0x2e, 0x5f, 0x6a, 0x5f, 0xc0, 0xbb, 0x8c, 0xe7, 0x6d, 0x15, 0x54, 0xa8, 0xbc, 0x47, 0x96, 0x17, 0x20, 0xd3, 0x64, 0x05, 0x0b, 0xf2, 0x74, 0x19, 0xbf, 0xf1, 0x68, 0xc0, 0xa7, 0xec, 0xc8, 0x73, 0x4c, 0xb5, 0xa5 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 129, + { 0x02, 0x9e, 0x10, 0xf6, 0xbb, 0xb7, 0xd0, 0x2d, 0xeb, 0xb1, 0xa5, 0xd5, 0x19, 0x0d, 0x69, 0x06, 0xff, 0xed, 0xeb, 0x9d, 0x15, 0x4a, 0x0f, 0x66, 0xdb, 0x87, 0x80, 0xb9, 0x28, 0x31, 0xb5, 0x96, 0x3e, 0x94, 0x84, 0x7f, 0x3e, 0x7d, 0xb1, 0xaa, 0x91, 0x48, 0xfb, 0x0e, 0xc5, 0x57, 0x6e, 0x6b, 0xa4, 0xfe, 0x04, 0xd6, 0xf2, 0x78, 0x32, 0xb1, 0x52, 0x18, 0x12, 0xd3, 0x7b, 0x22, 0xd9, 0xea, 0xe2, 0x80, 0x08, 0xe0, 0x92, 0xc6, 0x7e, 0x72, 0x32, 0x42, 0x67, 0xe1, 0xb1, 0xee, 0x45, 0x43, 0x55, 0x74, 0x1d, 0x8d, 0xe1, 0xd2, 0xa6, 0xa0, 0x50, 0x74, 0xbb, 0x1c, 0xe5, 0x81, 0x8b, 0x41, 0xbd, 0x19, 0xdc, 0x6b, 0x58, 0xc8, 0x93, 0x7d, 0x8a, 0xd6, 0x40, 0xd7, 0x04, 0x3f, 0xa1, 0x1f, 0x46, 0x8d, 0x6c, 0xcb, 0xec, 0x4a, 0xde, 0x52, 0x0a, 0x9e, 0x15, 0x9d, 0x60, 0x5d, 0x09, 0x28, 0x29 } +, + /* Prime 1 */ + 65, + { 0x0a, 0xb4, 0x64, 0xfd, 0x6f, 0xe3, 0x3c, 0x45, 0x9a, 0xb2, 0xdc, 0xce, 0x5f, 0x78, 0xa4, 0xd7, 0x4f, 0x92, 0xb9, 0x97, 0xd4, 0xbf, 0x54, 0x2e, 0x2d, 0x85, 0x4e, 0x76, 0x2c, 0x85, 0x86, 0xfc, 0x43, 0x57, 0xcc, 0x58, 0xcb, 0x33, 0x36, 0x33, 0xb0, 0x95, 0xa5, 0xee, 0x04, 0xa0, 0x32, 0x48, 0x53, 0x64, 0xd7, 0x0f, 0x67, 0xa3, 0xaa, 0x04, 0x85, 0x4c, 0x7a, 0x87, 0xa6, 0x9c, 0xf4, 0xc2, 0xad } +, + /* Prime 2 */ + 65, + { 0x0a, 0x8c, 0x3c, 0xc5, 0x04, 0x13, 0x40, 0xf4, 0x32, 0xfe, 0x0a, 0x78, 0x73, 0x13, 0x57, 0x79, 0x16, 0xfe, 0x76, 0xc0, 0x39, 0xf9, 0x71, 0x75, 0x9e, 0xc5, 0x0e, 0xd6, 0xc5, 0xb9, 0xa7, 0x36, 0x9b, 0x68, 0x96, 0x9e, 0xcb, 0x52, 0x59, 0xfe, 0x9c, 0x50, 0xd0, 0x75, 0x9b, 0xf8, 0xb3, 0xaa, 0xc1, 0xa5, 0xd5, 0xb5, 0x28, 0x8d, 0x67, 0x89, 0xe7, 0x18, 0xfa, 0x37, 0xef, 0x42, 0x39, 0x95, 0xd9 } +, + /* Prime exponent 1 */ + 64, + { 0xbb, 0x29, 0x5a, 0x95, 0xd5, 0xb3, 0x3c, 0x1d, 0xc0, 0xb1, 0x8b, 0xf6, 0xc1, 0x4a, 0xa0, 0xd9, 0xf2, 0x6f, 0x72, 0x8b, 0x39, 0x36, 0x0a, 0xa1, 0x59, 0x45, 0x6e, 0x94, 0xc3, 0xd9, 0xe0, 0x48, 0xc9, 0x2a, 0x4f, 0xb6, 0x31, 0x1d, 0x36, 0x92, 0x8c, 0xe5, 0xf4, 0x47, 0xa4, 0x99, 0x4a, 0x8f, 0x47, 0x87, 0xd8, 0xa9, 0x7f, 0x68, 0x11, 0x3e, 0xf9, 0x66, 0x34, 0xf5, 0x90, 0x2a, 0xb7, 0x51 } +, + /* Prime exponent 2 */ + 65, + { 0x02, 0xfa, 0x11, 0x2c, 0x89, 0x39, 0xe5, 0xdb, 0x05, 0x89, 0x2c, 0xeb, 0x51, 0x8e, 0xe3, 0xe1, 0x08, 0xdc, 0x48, 0x27, 0x78, 0x35, 0x2e, 0x10, 0x43, 0xfe, 0xd9, 0x71, 0x43, 0xdc, 0x61, 0x94, 0xc7, 0xc7, 0x7c, 0xba, 0xd4, 0x27, 0x29, 0xbe, 0xf1, 0xde, 0xdc, 0xf6, 0x54, 0x4e, 0x9c, 0x66, 0x54, 0xc0, 0xb8, 0xcf, 0xa7, 0xe2, 0x40, 0x96, 0x6a, 0xe2, 0x61, 0xbb, 0xe7, 0x8a, 0x89, 0x36, 0x01 } +, + /* Coefficient */ + 64, + { 0xa8, 0x8b, 0xf3, 0xff, 0xe9, 0x3f, 0x40, 0x4e, 0x06, 0x82, 0x1c, 0x97, 0x71, 0xea, 0xe6, 0x08, 0x15, 0x71, 0x2d, 0x6f, 0x94, 0x52, 0x71, 0xf6, 0xf3, 0x6f, 0x03, 0x69, 0xd9, 0x66, 0xc9, 0x20, 0xc7, 0xf8, 0xcb, 0xc7, 0x84, 0x25, 0xac, 0xbb, 0x9c, 0xe0, 0xfa, 0x1a, 0x03, 0x22, 0xf5, 0x0c, 0x97, 0xb8, 0x11, 0x5b, 0xd1, 0x51, 0x91, 0xf2, 0x24, 0xb5, 0x68, 0xd1, 0xd6, 0xec, 0xa6, 0xdb } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 13.1", + /* Message to be signed */ + 36, + { 0xb5, 0xe8, 0x6c, 0x8b, 0xa3, 0x98, 0x5a, 0xa5, 0x54, 0x1d, 0xf9, 0x5e, 0x51, 0x3c, 0xff, 0x67, 0x61, 0x2e, 0xaf, 0x2e, 0x16, 0x68, 0x85, 0x76, 0xf7, 0xd6, 0x73, 0xf6, 0xf1, 0x89, 0x1f, 0xb7, 0x5c, 0x9d, 0xd2, 0xcd } +, + /* Signature */ + 129, + { 0x6b, 0x42, 0xfd, 0x51, 0x63, 0x09, 0x19, 0x7f, 0x8a, 0xf3, 0xc7, 0x3e, 0x39, 0x62, 0x4d, 0x8e, 0xba, 0xbe, 0xcd, 0xa3, 0xec, 0x3c, 0xe6, 0x57, 0xb1, 0x11, 0x7f, 0x43, 0xe9, 0x83, 0x87, 0x7a, 0x1b, 0xa1, 0xaa, 0xf8, 0xe9, 0x5c, 0xc3, 0x99, 0x91, 0xd9, 0x2e, 0x35, 0xe2, 0xdb, 0x1e, 0x41, 0x30, 0x90, 0x14, 0x3d, 0x16, 0x46, 0x71, 0x98, 0xb9, 0xb9, 0xa9, 0x90, 0xd7, 0x74, 0xc2, 0x7a, 0xd3, 0xbb, 0xb4, 0x35, 0x2d, 0x3f, 0x07, 0x5d, 0x61, 0x73, 0x2c, 0x6b, 0x58, 0xec, 0x0f, 0x66, 0xe4, 0x92, 0xa3, 0xf7, 0xac, 0x4b, 0xbc, 0xf0, 0x12, 0xed, 0x6b, 0x40, 0x1f, 0xeb, 0x4f, 0xf3, 0x95, 0xcb, 0x8b, 0x21, 0x8a, 0x81, 0xd6, 0x17, 0x31, 0xee, 0xce, 0x37, 0x6f, 0x68, 0x8e, 0x66, 0xae, 0xa6, 0x98, 0xb4, 0xa8, 0x86, 0x2f, 0x58, 0xc9, 0x1d, 0x87, 0x60, 0x85, 0x49, 0x6f, 0xd0, 0x14 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 13.2", + /* Message to be signed */ + 253, + { 0x95, 0x46, 0x34, 0x6c, 0xf2, 0x21, 0x94, 0xc7, 0x87, 0x88, 0x81, 0x70, 0xa4, 0x82, 0xf7, 0xf4, 0x92, 0x17, 0xc3, 0x94, 0x0d, 0xc6, 0x21, 0x0c, 0xe3, 0x9e, 0x45, 0x50, 0xa3, 0x9b, 0x45, 0x28, 0x22, 0x41, 0x9a, 0xea, 0xc2, 0x4b, 0xec, 0x19, 0x8b, 0xb3, 0x59, 0xd0, 0x8b, 0xe8, 0x19, 0x6d, 0xf2, 0xe7, 0x57, 0x76, 0x61, 0x96, 0xc9, 0x58, 0xe2, 0xb1, 0x59, 0xc7, 0x4c, 0x1c, 0x30, 0x23, 0xc2, 0xdb, 0xcc, 0xe9, 0xed, 0x5d, 0x0e, 0xf3, 0xfb, 0x51, 0x45, 0x0b, 0xff, 0x64, 0x45, 0xdb, 0x26, 0x5e, 0x60, 0x6e, 0x19, 0x4b, 0xee, 0x06, 0x4c, 0xa5, 0xb3, 0x21, 0xd7, 0xe1, 0x55, 0x14, 0x23, 0x0c, 0x2b, 0x3b, 0x55, 0xd5, 0xda, 0x4c, 0xd0, 0x40, 0x52, 0x2f, 0x7b, 0xb8, 0x6a, 0x96, 0x2b, 0x81, 0x3f, 0x9d, 0xa3, 0x9e, 0x51, 0x38, 0x9b, 0xc6, 0x4f, 0x56, 0xe4, 0x47, 0xb2, 0xa2, 0xbf, 0x81, 0x9d, 0x7a, 0x80, 0x09, 0x4e, 0x2b, 0x8d, 0xe2, 0x7f, 0x10, 0x4b, 0xb6, 0xeb, 0x2f, 0x2f, 0xb4, 0x3a, 0xf1, 0xd0, 0x1e, 0xad, 0xca, 0x23, 0xa1, 0x96, 0xba, 0x12, 0x5b, 0x6a, 0x78, 0x57, 0x99, 0x74, 0xc0, 0xee, 0xc8, 0xa5, 0x49, 0x67, 0x71, 0xf6, 0x7d, 0xbd, 0x50, 0x69, 0xf3, 0x36, 0xe4, 0xef, 0x1f, 0x40, 0x47, 0x42, 0xdf, 0xc6, 0x9c, 0xe3, 0x25, 0xaa, 0x64, 0x9f, 0x8a, 0x63, 0x31, 0xcf, 0x40, 0x35, 0x55, 0xe1, 0x3f, 0x08, 0x10, 0xa7, 0x63, 0x50, 0xa7, 0xe1, 0x8d, 0x29, 0x92, 0xfa, 0xb4, 0x8f, 0x39, 0x7f, 0x3b, 0x93, 0xc5, 0xbd, 0x5a, 0x6f, 0xe1, 0xd2, 0xc4, 0x61, 0x8b, 0xa1, 0xf5, 0x9f, 0x00, 0x2d, 0xc2, 0x57, 0xec, 0x39, 0xee, 0x2f, 0x87, 0x62, 0x98, 0xda, 0x90, 0xf7, 0x44, 0x0a, 0xd4, 0xc6, 0xc9, 0x3f, 0xc1, 0x14, 0xdf, 0x05 } +, + /* Signature */ + 129, + { 0x67, 0xe4, 0x14, 0x99, 0x3f, 0x98, 0x7a, 0x22, 0x64, 0x3d, 0xd0, 0x39, 0xe7, 0xf9, 0xfe, 0x1c, 0xae, 0x74, 0x4a, 0x7a, 0xe4, 0x1d, 0x4c, 0x04, 0x4f, 0xa4, 0xed, 0x8d, 0xc9, 0xe3, 0x40, 0xce, 0xbb, 0x1e, 0x2a, 0xfb, 0x19, 0x8e, 0x84, 0x7a, 0xef, 0x4b, 0xc0, 0x61, 0xfd, 0x80, 0x0d, 0x81, 0xd4, 0xd3, 0x67, 0xb0, 0xfc, 0x2f, 0x73, 0x09, 0x33, 0xc1, 0x9b, 0x88, 0xd4, 0xdd, 0xf0, 0x5e, 0xd9, 0x8a, 0x58, 0x56, 0xde, 0x5e, 0xb4, 0x5b, 0x11, 0x6b, 0x7d, 0x24, 0xfe, 0xb4, 0x56, 0x77, 0x84, 0x9d, 0xab, 0x76, 0xe9, 0xe0, 0xcc, 0xb4, 0x5b, 0xa6, 0xb6, 0xf6, 0x14, 0x1f, 0x37, 0xbb, 0xad, 0x7c, 0x19, 0x1c, 0x37, 0x77, 0x11, 0x3b, 0xc7, 0x38, 0x8e, 0x4e, 0x46, 0x44, 0xec, 0xa9, 0x47, 0x03, 0xa7, 0x2b, 0xdd, 0xcc, 0x6f, 0x50, 0xcf, 0x98, 0x0e, 0x3f, 0x6d, 0xe3, 0x9d, 0x73, 0x12 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.3", + /* Message to be signed */ + 121, + { 0x56, 0x52, 0xb4, 0xc5, 0x75, 0x20, 0xb2, 0x55, 0xfb, 0x96, 0xf7, 0x0a, 0x30, 0xab, 0x92, 0xee, 0xc1, 0x93, 0x99, 0x56, 0xb6, 0xa9, 0x43, 0xc8, 0x3e, 0xd0, 0x98, 0x6e, 0x2e, 0x6e, 0xe4, 0xef, 0xbf, 0x8a, 0x52, 0x28, 0x78, 0x67, 0x28, 0x12, 0x03, 0xa7, 0xa6, 0xd1, 0xd8, 0x86, 0xb7, 0x00, 0x59, 0x52, 0xb4, 0x3b, 0x77, 0x85, 0x44, 0xed, 0xa8, 0x98, 0xe0, 0xdf, 0x2f, 0xa0, 0x6f, 0x68, 0x38, 0x03, 0x18, 0xf1, 0x4a, 0x53, 0xfe, 0x55, 0xd7, 0x2f, 0x8c, 0xfa, 0x6a, 0xf2, 0x1d, 0x93, 0xbb, 0xfc, 0x20, 0xd3, 0x58, 0xc2, 0x08, 0xc5, 0x62, 0xd7, 0x39, 0xbe, 0x00, 0x01, 0xce, 0x07, 0xfd, 0x8c, 0xd2, 0xf4, 0x6c, 0x3b, 0x44, 0xc8, 0x36, 0x51, 0x88, 0x09, 0xb7, 0x6f, 0x3a, 0x70, 0xcf, 0x69, 0x26, 0xbe, 0x06, 0x9c, 0x35, 0x75, 0xd5 } +, + /* Signature */ + 129, + { 0x01, 0x64, 0x11, 0xa2, 0x31, 0xa7, 0x38, 0x94, 0x4b, 0x3e, 0x44, 0xf7, 0x88, 0x5c, 0xf8, 0x1a, 0xca, 0xb7, 0x32, 0xd1, 0x73, 0x6d, 0xe3, 0x4c, 0x56, 0xcf, 0x40, 0xf9, 0x9a, 0x6c, 0xe4, 0x00, 0x70, 0xa2, 0x0a, 0xa9, 0x4c, 0x48, 0x78, 0x44, 0xa9, 0x3c, 0xef, 0x28, 0x7a, 0x58, 0xbc, 0x0e, 0xa1, 0x81, 0xb2, 0xcf, 0x27, 0xd9, 0x14, 0xf2, 0x93, 0xb9, 0x29, 0x77, 0x9d, 0x39, 0x03, 0x6c, 0x4e, 0x5a, 0xae, 0xd3, 0x5e, 0xee, 0x8a, 0x7f, 0xd5, 0x0e, 0xfd, 0x09, 0x6c, 0x91, 0xa8, 0xf7, 0x2c, 0x3c, 0x14, 0x1c, 0x57, 0x6c, 0x8d, 0x10, 0xb6, 0x36, 0xfc, 0x4d, 0xdc, 0x1e, 0x67, 0x14, 0xf1, 0x7f, 0xfc, 0xce, 0x10, 0x6d, 0x22, 0x1b, 0x4f, 0xd7, 0xd6, 0xfe, 0x1e, 0x7c, 0xbd, 0x3f, 0x3b, 0x08, 0xf5, 0x54, 0x6b, 0x44, 0xd1, 0xfe, 0xb7, 0x18, 0xfb, 0xc1, 0x33, 0x70, 0xc7, 0xfa, 0x2c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.4", + /* Message to be signed */ + 211, + { 0x6d, 0x57, 0xf0, 0x79, 0xa3, 0xe8, 0xad, 0xcb, 0x47, 0xcf, 0x2e, 0x3c, 0xa9, 0x76, 0xe0, 0x3b, 0x09, 0xc7, 0x7d, 0x1d, 0x9d, 0x9d, 0x84, 0x84, 0x35, 0x7e, 0x91, 0x23, 0x09, 0xe8, 0xf4, 0xa8, 0x3c, 0xb5, 0x0c, 0xb6, 0xa7, 0x38, 0x8c, 0x41, 0x4a, 0xec, 0x84, 0x46, 0x71, 0xff, 0x81, 0x06, 0x51, 0xe8, 0x28, 0x10, 0x3a, 0x1f, 0x6a, 0x19, 0x9b, 0xe2, 0x60, 0xf7, 0x46, 0x00, 0x02, 0x8c, 0x6a, 0x7b, 0x7b, 0xb9, 0x41, 0x6c, 0xe7, 0xb6, 0x35, 0x0a, 0x3a, 0x68, 0x05, 0x62, 0x0c, 0xf5, 0xe6, 0xb0, 0x09, 0x5d, 0xfa, 0x22, 0xb5, 0x46, 0x01, 0xf6, 0x19, 0xaf, 0xd1, 0x0d, 0xa2, 0x03, 0xd2, 0x81, 0x90, 0xcf, 0x9b, 0x0d, 0xb5, 0x98, 0x6d, 0x29, 0x30, 0x33, 0x69, 0x1e, 0xc5, 0xbb, 0xba, 0x6d, 0x73, 0xea, 0x32, 0x47, 0x2e, 0xfa, 0x3f, 0x16, 0x0f, 0xd2, 0xb1, 0xb5, 0xe4, 0x3b, 0x0b, 0xfa, 0xd3, 0x16, 0x77, 0x30, 0x5f, 0xef, 0x46, 0x72, 0x44, 0x11, 0x4e, 0xe1, 0x0f, 0x5c, 0xb2, 0xd6, 0x7b, 0x47, 0x83, 0x23, 0xa7, 0x11, 0x04, 0x1e, 0x29, 0x4c, 0x46, 0xb2, 0xed, 0x39, 0xcc, 0xde, 0x07, 0x9c, 0x87, 0x7f, 0xe7, 0x5c, 0xb8, 0x75, 0x14, 0x4a, 0xc3, 0x1e, 0xb0, 0x31, 0xa7, 0x38, 0xa4, 0xce, 0xfe, 0xf9, 0x1f, 0x01, 0x7b, 0xa7, 0x15, 0x23, 0xf5, 0x12, 0x48, 0x18, 0xcf, 0x48, 0xb9, 0x72, 0xbc, 0x47, 0xc8, 0xf2, 0xed, 0x35, 0x6f, 0x5b, 0xf6, 0x91, 0xfd, 0x94, 0x67, 0x0b, 0xb2 } +, + /* Signature */ + 129, + { 0x31, 0x5c, 0xe4, 0x17, 0xd0, 0xbb, 0xd7, 0x3e, 0x7c, 0x43, 0x56, 0x79, 0x7e, 0x73, 0xed, 0x7a, 0xbf, 0xe9, 0xfc, 0xff, 0xf1, 0xa5, 0x34, 0x28, 0x99, 0xa7, 0xd1, 0x1f, 0xb0, 0xd0, 0x54, 0x2b, 0xfc, 0xab, 0x66, 0xde, 0x2e, 0x4e, 0xc0, 0x7c, 0x7d, 0xc2, 0xbe, 0x7d, 0x79, 0x72, 0x90, 0xa3, 0x0d, 0xb8, 0xc4, 0x07, 0xdd, 0x16, 0x37, 0x65, 0x88, 0xa6, 0xdc, 0xc1, 0xa2, 0x07, 0xbf, 0x7f, 0xf3, 0x11, 0x54, 0x0f, 0xaa, 0x9d, 0xd6, 0xf1, 0x9a, 0x73, 0xab, 0x25, 0xa7, 0x49, 0x6e, 0x68, 0x2f, 0xa8, 0xa7, 0x05, 0x40, 0x81, 0x07, 0x6c, 0x1a, 0x02, 0x15, 0x7b, 0xe6, 0x3e, 0x7f, 0x64, 0x5d, 0xe8, 0x2d, 0xf7, 0xc6, 0x15, 0x50, 0x3f, 0xa8, 0x3b, 0x4e, 0xdb, 0xa2, 0x05, 0x81, 0x81, 0x2e, 0x09, 0x7f, 0x65, 0x05, 0x6e, 0xd4, 0x17, 0xf6, 0xf2, 0x48, 0x03, 0x53, 0x0c, 0xf8, 0x18, 0x58 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.5", + /* Message to be signed */ + 241, + { 0xbb, 0x75, 0x44, 0x6f, 0x78, 0x78, 0x23, 0xdd, 0xa2, 0x42, 0x2b, 0x1a, 0xdc, 0x7d, 0x7f, 0xef, 0xd0, 0x6a, 0x6e, 0x9a, 0xf5, 0xc0, 0x49, 0x01, 0xac, 0x5b, 0x99, 0x91, 0x3a, 0xd6, 0x29, 0x8c, 0x9d, 0x1a, 0x33, 0x22, 0xe8, 0xb2, 0x17, 0xe4, 0xe0, 0x99, 0x4c, 0x42, 0x20, 0x42, 0x80, 0xd4, 0x04, 0xd0, 0x1e, 0xce, 0xb5, 0xec, 0x53, 0xfb, 0x86, 0xf7, 0x61, 0xa3, 0x96, 0xb2, 0x3a, 0xe1, 0x9d, 0x46, 0x79, 0x05, 0xa0, 0xfe, 0x80, 0x50, 0xb8, 0x95, 0xd8, 0xba, 0x37, 0x46, 0x68, 0x5c, 0x47, 0x43, 0x9f, 0x90, 0xc3, 0x66, 0x9c, 0x70, 0xff, 0xb8, 0x19, 0x94, 0x56, 0x5c, 0x4d, 0xf2, 0xa3, 0x1e, 0xb2, 0xa4, 0x52, 0xbc, 0x3c, 0xb3, 0x12, 0xb8, 0x14, 0x7c, 0xec, 0x19, 0x10, 0x32, 0xf3, 0x8f, 0x3b, 0x3d, 0x89, 0xd7, 0x58, 0x2b, 0xf1, 0x8e, 0x7b, 0x72, 0x75, 0xfb, 0x4f, 0x16, 0xee, 0x89, 0x56, 0x7e, 0x2a, 0x56, 0xbc, 0x73, 0xb3, 0xe2, 0xe1, 0x09, 0xf9, 0x94, 0x0e, 0xbd, 0x10, 0xb9, 0xdf, 0x2b, 0x88, 0xac, 0xcf, 0x0b, 0xa1, 0x8e, 0x5b, 0x34, 0x95, 0x20, 0xd2, 0xc7, 0xf5, 0xa3, 0x1b, 0xd5, 0x22, 0x6d, 0x12, 0xec, 0x35, 0xbf, 0xc9, 0xe3, 0x62, 0x03, 0xe1, 0x35, 0x06, 0xba, 0x12, 0xb7, 0x56, 0xc8, 0xba, 0x00, 0xaf, 0x91, 0xb8, 0x5b, 0x0b, 0x4c, 0x07, 0xc7, 0xf4, 0x84, 0xad, 0xc4, 0x58, 0xc9, 0x26, 0xaa, 0xeb, 0x4f, 0x08, 0x2f, 0xec, 0x98, 0x7d, 0x9f, 0x27, 0x6b, 0x89, 0x49, 0x59, 0x7e, 0xc0, 0x40, 0x1b, 0xb7, 0x1a, 0x2f, 0xea, 0x9c, 0x7b, 0x74, 0xe0, 0xdf, 0xe6, 0xaa, 0x52, 0xac, 0x8b, 0x80, 0xbe, 0xea, 0xd3, 0x36, 0xa4, 0x9d, 0xb2, 0x2f, 0xb3 } +, + /* Signature */ + 129, + { 0x53, 0xd0, 0xd7, 0x95, 0xbb, 0x08, 0x2f, 0x20, 0x01, 0x03, 0x6f, 0x47, 0x2c, 0x2e, 0xce, 0x6e, 0x7d, 0x2d, 0xb6, 0x9f, 0x29, 0x2d, 0xa7, 0x21, 0x36, 0x75, 0xc7, 0xcb, 0xba, 0x0d, 0x33, 0xb2, 0x32, 0x12, 0xf8, 0xf4, 0x3a, 0x4a, 0x8e, 0x09, 0xa6, 0xa5, 0x0e, 0x01, 0x9b, 0xbd, 0xd5, 0x9a, 0x58, 0x89, 0x8c, 0xc4, 0x6c, 0x58, 0xa4, 0x6e, 0x42, 0xce, 0x7b, 0xa0, 0x93, 0xfb, 0x46, 0x92, 0xf3, 0x83, 0xde, 0x33, 0xa9, 0xa3, 0x4f, 0x47, 0xc7, 0xe6, 0x19, 0x38, 0xbf, 0x8a, 0x6a, 0xda, 0xa8, 0x8d, 0xf2, 0x12, 0x96, 0xb4, 0xc6, 0x7b, 0x52, 0x68, 0x35, 0xf7, 0x57, 0xf2, 0xc2, 0x6c, 0x1d, 0x30, 0x9d, 0x7c, 0xdd, 0x5a, 0xd5, 0xfd, 0x8f, 0x61, 0xf8, 0x51, 0xed, 0x23, 0xc4, 0xbe, 0x2a, 0xbb, 0x62, 0x7d, 0xfd, 0x81, 0x7f, 0x84, 0x77, 0xdc, 0x04, 0x2b, 0x6a, 0x2e, 0x40, 0x69, 0x40 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.6", + /* Message to be signed */ + 245, + { 0x88, 0x39, 0x39, 0xd1, 0x49, 0xa5, 0x44, 0xe6, 0x2e, 0xf0, 0x4c, 0x61, 0x03, 0x51, 0xa2, 0xdf, 0xa2, 0x52, 0xeb, 0x9a, 0x9d, 0x1e, 0x11, 0xae, 0x54, 0xc9, 0xb0, 0x7e, 0xbc, 0xf1, 0xfd, 0xc4, 0x7e, 0xc1, 0xd9, 0x47, 0x03, 0x41, 0x1d, 0xa4, 0x15, 0xf5, 0x9f, 0xb3, 0xe5, 0x04, 0x1e, 0xd9, 0x47, 0x0e, 0x7b, 0xcc, 0x81, 0x9b, 0x5a, 0xfe, 0xaf, 0x86, 0x0c, 0x01, 0x6e, 0xf1, 0x25, 0xbd, 0x08, 0xa6, 0xcb, 0x8b, 0xcd, 0xf3, 0xb9, 0x3a, 0x51, 0xdc, 0xad, 0xb2, 0xf6, 0x8c, 0x8c, 0xc3, 0x77, 0x55, 0x14, 0x28, 0x2a, 0xff, 0x75, 0x67, 0xec, 0x65, 0xf2, 0x70, 0xd0, 0x2b, 0xeb, 0x95, 0xfb, 0x8f, 0xac, 0x24, 0x09, 0x5e, 0x17, 0x06, 0xe4, 0x8b, 0x52, 0x48, 0x65, 0xbc, 0x14, 0x46, 0x1d, 0x3e, 0xce, 0x8c, 0x50, 0x1c, 0x3d, 0x80, 0x2a, 0xde, 0x98, 0x5a, 0xe9, 0x5c, 0xfe, 0x1a, 0xb9, 0xd6, 0xb9, 0xab, 0x0d, 0x15, 0xfc, 0xc8, 0x86, 0x6f, 0x7f, 0x25, 0x9c, 0x5e, 0x41, 0xc0, 0x2c, 0xd4, 0x13, 0x43, 0x7e, 0x7d, 0x6b, 0xa7, 0xf1, 0x5b, 0x0a, 0x70, 0xda, 0xfb, 0xd5, 0x5c, 0x0e, 0xdb, 0x6b, 0x80, 0x75, 0xc2, 0x7c, 0xff, 0x3b, 0x28, 0x9e, 0x6c, 0x99, 0xe9, 0xa8, 0x84, 0xff, 0x7f, 0x08, 0x6d, 0xa9, 0xf7, 0x5d, 0x6a, 0x4c, 0xbb, 0xcc, 0xaf, 0x52, 0xba, 0x25, 0xc6, 0x34, 0x2c, 0x38, 0xa7, 0x6b, 0x44, 0xe1, 0x01, 0x15, 0x5d, 0xf7, 0x55, 0xe3, 0x9c, 0x14, 0x86, 0x2e, 0x22, 0x0c, 0xa3, 0x6f, 0xfb, 0xcc, 0x83, 0x2a, 0xfe, 0xcb, 0xa8, 0x7f, 0x8a, 0xbd, 0x96, 0x0a, 0x57, 0x7f, 0x56, 0xca, 0x6c, 0xd8, 0xe9, 0x91, 0x26, 0x65, 0x8f, 0x27, 0xac, 0x6e, 0x53, 0xc4, 0x42, 0xed, 0x47, 0x66 } +, + /* Signature */ + 129, + { 0x1e, 0xc0, 0x2a, 0xe6, 0xa0, 0xa3, 0xf6, 0x11, 0x99, 0x29, 0x61, 0xca, 0x27, 0xcc, 0xbf, 0x29, 0x6e, 0x11, 0x36, 0x18, 0x32, 0xe1, 0xee, 0x75, 0x20, 0x56, 0x9a, 0x9a, 0xee, 0x06, 0x34, 0x5c, 0xda, 0x22, 0xb4, 0xfa, 0x48, 0xfc, 0x34, 0x5e, 0x47, 0x78, 0xbc, 0x3c, 0xcd, 0xfe, 0xbd, 0x2d, 0xc5, 0xa6, 0xc9, 0xd4, 0x84, 0x51, 0xaa, 0x44, 0x1b, 0xea, 0x4b, 0x95, 0x11, 0x99, 0x65, 0x4a, 0xe8, 0xd2, 0xf7, 0x52, 0x2e, 0x17, 0xed, 0xbc, 0x2f, 0x51, 0xce, 0x15, 0xcb, 0xcd, 0x36, 0x6f, 0x49, 0x39, 0xcb, 0x53, 0xc3, 0xb7, 0x70, 0x81, 0xf4, 0xa7, 0x37, 0x50, 0x05, 0x4e, 0x00, 0xb3, 0x0b, 0xa2, 0xfe, 0x58, 0xf6, 0xf0, 0x2e, 0x36, 0xa8, 0x62, 0x54, 0x23, 0x97, 0xdb, 0xa6, 0xa3, 0xcd, 0x22, 0x77, 0x70, 0x88, 0x19, 0xe7, 0x8a, 0x2d, 0x87, 0x6a, 0x23, 0xa5, 0xa2, 0x69, 0xd7, 0x75 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.7", + /* Message to be signed */ + 71, + { 0x40, 0x31, 0xe0, 0xde, 0xf4, 0xf3, 0xd1, 0xad, 0x9b, 0xc0, 0x82, 0x77, 0x0a, 0x88, 0xa1, 0xd9, 0xb4, 0xb7, 0x10, 0x75, 0x48, 0xcd, 0xf8, 0x46, 0x2b, 0x0b, 0xae, 0x3d, 0x99, 0x4d, 0x8e, 0xbc, 0x4d, 0xa0, 0x44, 0xb9, 0x05, 0xdd, 0x8e, 0xd9, 0x1a, 0x1d, 0xa6, 0x76, 0x72, 0x78, 0x22, 0x36, 0x0e, 0xe2, 0xb6, 0xd5, 0xe1, 0x2b, 0xb7, 0x03, 0x16, 0xd7, 0x9e, 0x8a, 0xbb, 0x82, 0xa6, 0x43, 0x44, 0xaf, 0xb3, 0xb2, 0x25, 0x88, 0x5c } +, + /* Signature */ + 129, + { 0x0b, 0xe5, 0xa6, 0xd0, 0x43, 0xbe, 0x5d, 0x27, 0xd1, 0xd5, 0x1d, 0x9e, 0x3a, 0xa6, 0x1d, 0x92, 0xc9, 0xd8, 0x43, 0x23, 0x11, 0x9b, 0x48, 0xc8, 0x4a, 0x80, 0x38, 0x97, 0x18, 0xd7, 0xa1, 0xaa, 0xf5, 0x7a, 0x9a, 0x0d, 0x21, 0x4f, 0x65, 0x06, 0x48, 0x48, 0x64, 0xdf, 0xae, 0x85, 0xdb, 0x7b, 0x84, 0x74, 0x07, 0x3a, 0x8f, 0x97, 0x7b, 0x42, 0xb5, 0x3b, 0x40, 0x7e, 0x44, 0xc7, 0xc6, 0x2b, 0x16, 0x8d, 0x1e, 0x77, 0x78, 0xf4, 0xf2, 0x78, 0x57, 0xbf, 0xba, 0x85, 0xdd, 0xdc, 0x8b, 0x0e, 0x9f, 0x0e, 0x9a, 0x5b, 0x6d, 0xe7, 0x1a, 0x04, 0x43, 0x72, 0x0e, 0x92, 0xbb, 0x88, 0xb0, 0x77, 0xcb, 0xa1, 0x5d, 0x3f, 0x6e, 0x2b, 0xe4, 0xd2, 0x7a, 0x7c, 0x50, 0x9c, 0x7d, 0xc0, 0x3f, 0x1f, 0xdd, 0x4f, 0xe3, 0x38, 0xa4, 0xe5, 0x45, 0xc4, 0x6c, 0x03, 0x45, 0x22, 0xcc, 0xc0, 0xd4, 0x5d, 0x4c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.8", + /* Message to be signed */ + 64, + { 0x7f, 0xdc, 0x96, 0xa4, 0x56, 0x57, 0x74, 0x02, 0x9f, 0xff, 0xa9, 0x3b, 0x39, 0xf0, 0x5d, 0xee, 0x9f, 0x84, 0xfa, 0x89, 0x53, 0xfd, 0x0f, 0x63, 0x38, 0xc8, 0x1c, 0x9d, 0xec, 0x6c, 0xdd, 0x66, 0x1f, 0xfa, 0xb9, 0x6f, 0x0e, 0x08, 0xeb, 0x0b, 0x9b, 0xa9, 0xca, 0x5b, 0xe1, 0x7b, 0x57, 0xc4, 0xb4, 0x86, 0x8f, 0xd5, 0x34, 0x11, 0x54, 0xde, 0x50, 0x27, 0x71, 0x13, 0xc7, 0x18, 0x53, 0x41 } +, + /* Signature */ + 129, + { 0x1d, 0xd2, 0x1f, 0xa4, 0x95, 0xbe, 0x7c, 0x49, 0x0f, 0x98, 0x2f, 0x69, 0xea, 0xb1, 0x4e, 0x24, 0xda, 0xa0, 0x4b, 0xd1, 0x38, 0xb7, 0x14, 0x32, 0x49, 0xcd, 0xcc, 0xd7, 0x8c, 0xcf, 0xc9, 0x10, 0x6a, 0xca, 0xa0, 0x3e, 0xc8, 0x76, 0x69, 0x42, 0x32, 0x56, 0x6e, 0xc6, 0xca, 0xb9, 0x12, 0x28, 0x40, 0xf6, 0x69, 0xc8, 0x00, 0xf2, 0xee, 0x09, 0x2b, 0xb9, 0xb6, 0xcb, 0x2a, 0x45, 0x42, 0xa9, 0x0d, 0xe6, 0x04, 0xc4, 0xf1, 0x05, 0x00, 0x0a, 0x3a, 0x0d, 0xec, 0xcd, 0x3d, 0xd9, 0x7a, 0x32, 0x61, 0xfa, 0x38, 0x22, 0x7e, 0xb3, 0x81, 0xa1, 0xf8, 0xf2, 0x3b, 0x66, 0x65, 0xd2, 0x84, 0x80, 0xdf, 0xb7, 0x21, 0x17, 0x88, 0x2e, 0xd8, 0xdb, 0x25, 0xd7, 0x6d, 0xe4, 0x0d, 0xe2, 0xfb, 0xe7, 0x2d, 0xc3, 0x94, 0xec, 0x6f, 0xbd, 0xaa, 0x99, 0xc6, 0x4f, 0xad, 0xe7, 0x29, 0x78, 0xa5, 0x1f, 0xc4 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.9", + /* Message to be signed */ + 175, + { 0x63, 0x18, 0x32, 0xab, 0x19, 0x18, 0xcd, 0x02, 0x08, 0x28, 0xe4, 0x7a, 0xe2, 0xb4, 0x47, 0x6b, 0x14, 0x69, 0xf2, 0x72, 0xe3, 0x0e, 0x53, 0xe5, 0x96, 0xfb, 0xa2, 0x6b, 0x40, 0x29, 0x37, 0xdc, 0x44, 0xc2, 0xea, 0x57, 0x45, 0xc7, 0x9d, 0x2d, 0xc6, 0x4a, 0x10, 0xe1, 0x22, 0x5c, 0xa0, 0xb6, 0x92, 0x9d, 0x49, 0x54, 0xbc, 0x5d, 0x37, 0x40, 0x96, 0xfd, 0x87, 0x8d, 0xd1, 0x01, 0xf7, 0x66, 0x63, 0x13, 0xd9, 0xa8, 0xf8, 0x26, 0xbc, 0x67, 0x14, 0x01, 0x42, 0x2c, 0x1c, 0xfe, 0x1a, 0x6d, 0x01, 0xa4, 0xd7, 0x86, 0x4a, 0x14, 0xc6, 0x0c, 0xeb, 0xc2, 0xf0, 0x70, 0x91, 0x4c, 0xee, 0xde, 0xb1, 0x78, 0x2f, 0xe5, 0x40, 0xa0, 0xa5, 0xd2, 0x57, 0x84, 0x44, 0xf9, 0xb3, 0x60, 0x34, 0xec, 0x77, 0xd6, 0xb8, 0x03, 0xa0, 0xc9, 0x76, 0x1b, 0x32, 0x75, 0x92, 0xaa, 0x48, 0x46, 0x63, 0x5c, 0x56, 0x3f, 0x1c, 0x6a, 0x6d, 0xf6, 0x8f, 0xaa, 0xbc, 0xe4, 0x97, 0xaf, 0x4d, 0xc9, 0xa3, 0x64, 0x2b, 0x75, 0xa4, 0xa2, 0x94, 0xd3, 0x08, 0x56, 0x8e, 0x6d, 0x73, 0xc1, 0x1d, 0xb5, 0x67, 0x24, 0x04, 0x2b, 0x55, 0xc3, 0xa2, 0x4a, 0x7b, 0xc7, 0xa1, 0x05, 0x0e, 0x4f, 0x44, 0x8b, 0x6a } +, + /* Signature */ + 129, + { 0x45, 0xd3, 0xa6, 0xae, 0x8f, 0x48, 0x35, 0x5c, 0x01, 0x2b, 0x50, 0x10, 0x79, 0xee, 0x92, 0xaf, 0xfe, 0x3c, 0x9e, 0x60, 0x2e, 0x4a, 0x08, 0x0c, 0xfc, 0x94, 0x72, 0x3a, 0xe9, 0x6d, 0xac, 0x2a, 0x66, 0xe4, 0x55, 0xa4, 0x0e, 0x72, 0x8b, 0x2a, 0x1b, 0x27, 0xe6, 0x22, 0x40, 0x55, 0x4e, 0xc7, 0xc5, 0xc0, 0xad, 0x6a, 0xa0, 0x0c, 0x09, 0x22, 0xe5, 0x3d, 0x7b, 0x12, 0xed, 0x42, 0xc0, 0x87, 0x32, 0x2d, 0x15, 0x36, 0xe4, 0x6b, 0x7d, 0xeb, 0xda, 0x80, 0x95, 0xf5, 0x5d, 0x1e, 0x12, 0xbc, 0x24, 0x42, 0xf4, 0x3b, 0x4d, 0x12, 0x8f, 0xee, 0x23, 0x1d, 0xcd, 0x6f, 0x8c, 0x37, 0xaa, 0x6b, 0xcf, 0x4f, 0xe7, 0xb5, 0xe0, 0xde, 0xa9, 0xc6, 0x70, 0x9d, 0x3d, 0x91, 0xf9, 0xe4, 0x2a, 0x53, 0x16, 0x8a, 0x16, 0xb6, 0xfe, 0x99, 0x7b, 0x5d, 0xfe, 0xba, 0xfb, 0x46, 0xed, 0x9a, 0xea, 0x5c, 0x66 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.10", + /* Message to be signed */ + 157, + { 0x8b, 0x04, 0x3d, 0x90, 0xda, 0xe3, 0x41, 0x66, 0x85, 0xd5, 0x3a, 0x5b, 0x4c, 0x3c, 0xc2, 0x54, 0xcd, 0xa0, 0xcb, 0xd2, 0x3b, 0x4e, 0x40, 0x8d, 0xe8, 0x20, 0xa4, 0xda, 0x7a, 0xde, 0x6d, 0xd9, 0x5d, 0x4e, 0x1a, 0x97, 0xe2, 0x31, 0x2c, 0x3e, 0x84, 0x26, 0x1e, 0xe0, 0xb6, 0xce, 0xfe, 0x60, 0xe6, 0xb0, 0x82, 0xfd, 0x59, 0x65, 0xef, 0xa1, 0x64, 0x8f, 0x4f, 0xae, 0x61, 0x60, 0x5f, 0xe3, 0x55, 0x33, 0x27, 0x00, 0x46, 0x96, 0x05, 0x26, 0x53, 0x47, 0xe6, 0x54, 0x7a, 0xea, 0x77, 0x5b, 0x85, 0x6e, 0x5a, 0x46, 0xc3, 0x41, 0xd2, 0x99, 0x52, 0xbb, 0xea, 0x92, 0x70, 0x49, 0x96, 0x3e, 0x37, 0x40, 0x20, 0x8c, 0xfb, 0x0b, 0x65, 0x28, 0x57, 0xb6, 0xf5, 0x2e, 0x36, 0x6a, 0x17, 0x0b, 0xe3, 0x4f, 0x13, 0xd3, 0x58, 0x46, 0xbd, 0xe6, 0x97, 0x20, 0x46, 0x20, 0x01, 0xb0, 0x9d, 0xd2, 0x68, 0xb8, 0x9b, 0x09, 0x00, 0x31, 0x8e, 0x73, 0x3d, 0xb2, 0x00, 0x9e, 0xfd, 0x9b, 0x51, 0x77, 0x41, 0xe5, 0x10, 0xd3, 0xf3, 0x94, 0xf7, 0xad, 0xb5, 0x45, 0x59, 0xb1, 0x57 } +, + /* Signature */ + 129, + { 0x6b, 0x27, 0x8f, 0x36, 0x2c, 0x29, 0x2e, 0xea, 0x09, 0xb9, 0x0b, 0xf3, 0x53, 0xd1, 0x43, 0xf2, 0xca, 0x09, 0x9f, 0xf8, 0x79, 0x57, 0x34, 0x79, 0xdf, 0x2a, 0xff, 0x9b, 0x25, 0x0d, 0x1c, 0x91, 0x87, 0xc6, 0xa3, 0x34, 0x3e, 0xa1, 0x4c, 0x07, 0x6f, 0x2a, 0x20, 0xc1, 0xa1, 0x9d, 0xb2, 0x6a, 0xad, 0x35, 0x48, 0xec, 0x6f, 0xb3, 0xb2, 0xfa, 0xfc, 0x75, 0x1b, 0x59, 0x08, 0x2d, 0x8b, 0x23, 0xc8, 0x2c, 0x8a, 0x51, 0xf7, 0xfa, 0xf7, 0xa4, 0xd4, 0xa8, 0x23, 0x98, 0xbf, 0xbe, 0xd4, 0x49, 0xbd, 0xe4, 0xee, 0x9d, 0xc8, 0x68, 0x01, 0x60, 0x66, 0x6f, 0xd9, 0xc7, 0x74, 0xc6, 0xaa, 0x57, 0x7b, 0x4e, 0xc5, 0x4c, 0xf0, 0xd5, 0xbd, 0x9e, 0x3d, 0x1a, 0xfa, 0x9c, 0x3b, 0x4b, 0x91, 0x46, 0x76, 0x78, 0xc9, 0xd4, 0xc4, 0xfe, 0x40, 0x0a, 0xa8, 0x57, 0xa3, 0xb0, 0x54, 0x5b, 0xdf, 0x84, 0xa6 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.11", + /* Message to be signed */ + 148, + { 0x3b, 0x28, 0xa6, 0x09, 0x2e, 0x47, 0x08, 0x98, 0xaf, 0x07, 0x0a, 0x08, 0x7c, 0x45, 0x53, 0x18, 0x8d, 0xe6, 0xc3, 0x44, 0xbb, 0x0b, 0x5f, 0xdc, 0x7f, 0x66, 0xfb, 0xc5, 0x2d, 0xc9, 0x3a, 0x8b, 0x92, 0xa3, 0x74, 0x11, 0x20, 0x37, 0xd6, 0xa4, 0x32, 0x86, 0x12, 0x8a, 0xce, 0xf9, 0x5a, 0x35, 0x05, 0xc0, 0xab, 0xb1, 0xaf, 0xa6, 0x2c, 0x48, 0xcb, 0x21, 0x36, 0x07, 0x7f, 0x8a, 0x0e, 0x0e, 0x0b, 0x5a, 0x4e, 0xe9, 0xb2, 0xc7, 0x7d, 0x7a, 0x0c, 0x0b, 0x53, 0xf3, 0x8a, 0x51, 0xcc, 0x3d, 0xb9, 0xb5, 0x83, 0xb3, 0xae, 0xc0, 0x7f, 0x1e, 0x22, 0x4f, 0xcb, 0x3f, 0x1d, 0xad, 0x19, 0x5e, 0x05, 0x86, 0x59, 0xa9, 0xd1, 0x1f, 0x8e, 0xdc, 0x74, 0x44, 0x99, 0x46, 0x86, 0xed, 0x62, 0xc9, 0x75, 0x66, 0xe9, 0xe0, 0x0c, 0xbf, 0x8f, 0x0d, 0xbc, 0x17, 0x16, 0xe6, 0xb7, 0xf0, 0xf8, 0x8f, 0xe8, 0x9a, 0x86, 0x7a, 0x41, 0xd6, 0x43, 0x13, 0x5a, 0xd8, 0xb1, 0x8a, 0xa1, 0x43, 0xe7, 0x37, 0x5d, 0xf1, 0x95, 0x29 } +, + /* Signature */ + 129, + { 0x32, 0x62, 0xfe, 0x17, 0xe4, 0x4e, 0x5e, 0xcc, 0x84, 0x31, 0x70, 0xd3, 0xae, 0x27, 0x51, 0xda, 0x1f, 0x48, 0xd6, 0xe9, 0x61, 0xd8, 0x1e, 0x93, 0x59, 0xb0, 0x98, 0x2c, 0x6d, 0x61, 0x30, 0x8e, 0xba, 0xcf, 0xe2, 0x60, 0x7c, 0x53, 0x8c, 0x17, 0x0c, 0xe0, 0xe7, 0x2a, 0x07, 0xbc, 0x01, 0x48, 0x7b, 0x29, 0x5c, 0x36, 0xb8, 0xe2, 0x2a, 0xfd, 0xf6, 0xe7, 0xfe, 0x39, 0xc0, 0x3a, 0x5c, 0x0c, 0x36, 0x61, 0x06, 0x1f, 0x23, 0xfb, 0xf5, 0x89, 0x0e, 0xad, 0x59, 0xf8, 0x72, 0xc9, 0x46, 0xcc, 0xe0, 0xf8, 0x16, 0xc9, 0xed, 0x3a, 0x2c, 0x1e, 0x11, 0xf8, 0xf7, 0x4d, 0xa1, 0xe9, 0x7a, 0x39, 0x0d, 0x53, 0x4d, 0x78, 0x55, 0x78, 0xa2, 0x45, 0x5f, 0xcd, 0x87, 0x47, 0x83, 0xf4, 0x57, 0x2a, 0x15, 0xf4, 0x93, 0x7d, 0xca, 0x98, 0x09, 0x3f, 0xd0, 0xe9, 0x99, 0x0a, 0xf0, 0x00, 0x52, 0x56, 0xbf } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.12", + /* Message to be signed */ + 52, + { 0x4f, 0xdd, 0x6a, 0x36, 0x31, 0xdd, 0xd4, 0xbc, 0x3c, 0x76, 0x07, 0x19, 0x02, 0xa2, 0x27, 0xfd, 0x5b, 0x36, 0x53, 0xb1, 0xf9, 0x70, 0xf2, 0xb7, 0x67, 0xef, 0x55, 0x4e, 0x1c, 0x75, 0xca, 0xde, 0x81, 0x9d, 0x8d, 0x1f, 0xca, 0x76, 0xbc, 0x10, 0x54, 0x1c, 0xbf, 0x8b, 0x1d, 0x8b, 0x0e, 0x72, 0x55, 0xf9, 0x57, 0x40 } +, + /* Signature */ + 129, + { 0x29, 0xcb, 0xa5, 0xb4, 0x3f, 0xa3, 0x56, 0x57, 0x75, 0x89, 0x34, 0x91, 0xb1, 0x18, 0x57, 0x8b, 0x14, 0xb5, 0xfa, 0x1e, 0xeb, 0xe0, 0xc8, 0x07, 0x59, 0xa6, 0xd1, 0x91, 0xe7, 0xc2, 0x13, 0x1e, 0xe1, 0x0a, 0xc5, 0xb9, 0xb8, 0xae, 0x1a, 0xa7, 0xd6, 0x96, 0xc9, 0x84, 0x88, 0xa3, 0x5c, 0xdf, 0xa2, 0xaa, 0x00, 0x6d, 0x91, 0xbf, 0x7e, 0x05, 0xa5, 0xc1, 0x90, 0x9e, 0xfb, 0x20, 0xda, 0xbc, 0x82, 0x13, 0x3b, 0x62, 0x64, 0xc0, 0x42, 0x18, 0x0c, 0x2c, 0xca, 0x65, 0x45, 0x9f, 0x66, 0xcc, 0x7e, 0xb1, 0xba, 0x75, 0xd1, 0x5d, 0x4f, 0x56, 0xc7, 0x52, 0x8a, 0xab, 0x28, 0x38, 0xe6, 0x79, 0x53, 0x7a, 0x4c, 0x8d, 0xcd, 0x37, 0xd4, 0xb4, 0xca, 0x82, 0x5c, 0xe1, 0x65, 0xfa, 0x4a, 0x97, 0x15, 0x82, 0x44, 0xdc, 0x87, 0xc0, 0x61, 0xfb, 0x12, 0x00, 0x1e, 0x55, 0x33, 0xfb, 0xd4, 0xcc, 0x62 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.13", + /* Message to be signed */ + 169, + { 0x59, 0x0c, 0xd2, 0x30, 0x50, 0xe5, 0x7b, 0x28, 0xd5, 0xc2, 0x18, 0x5e, 0xad, 0x60, 0xb1, 0xe9, 0x52, 0x9f, 0x2b, 0xd5, 0x26, 0x13, 0xeb, 0x03, 0xf6, 0xed, 0x1a, 0xef, 0xa4, 0xa6, 0x72, 0x88, 0xd5, 0xa3, 0xa3, 0x4f, 0xd9, 0x5c, 0xa6, 0x38, 0x94, 0xaf, 0x3a, 0x40, 0xcd, 0x68, 0x87, 0x3a, 0x1f, 0x37, 0xe3, 0x54, 0xd3, 0x04, 0x14, 0x29, 0x7b, 0x19, 0x25, 0x4b, 0xc6, 0xc1, 0xa3, 0xf7, 0xa4, 0x75, 0x20, 0xee, 0xa5, 0x6e, 0xff, 0x77, 0xdb, 0xfd, 0xa6, 0xbd, 0x77, 0x79, 0xd0, 0x2f, 0xd8, 0x16, 0xfc, 0x0e, 0x99, 0x91, 0x9f, 0xe4, 0x39, 0x5e, 0xae, 0xe5, 0xb2, 0xf5, 0xf0, 0x32, 0xcf, 0xc4, 0x33, 0x6f, 0x9c, 0xf9, 0xac, 0xef, 0x74, 0xdb, 0xbf, 0x4c, 0x9a, 0x09, 0x18, 0xda, 0x65, 0x58, 0xb4, 0xb4, 0xe3, 0x20, 0x9b, 0xfc, 0xd7, 0x1d, 0xdd, 0x59, 0x76, 0x07, 0xb6, 0xe2, 0x8c, 0x39, 0x85, 0xdb, 0xf5, 0x2c, 0xa7, 0xd1, 0xd7, 0x51, 0xcb, 0x81, 0x69, 0xc0, 0xb1, 0xb1, 0x3f, 0xf8, 0xb6, 0x5b, 0x73, 0x1e, 0x69, 0xdd, 0x2e, 0xff, 0xe4, 0x4c, 0x63, 0x6f, 0x2b, 0x69, 0x95, 0x35, 0x83, 0x1a, 0xeb, 0x5e, 0x62, 0x90, 0x2f } +, + /* Signature */ + 129, + { 0x67, 0xeb, 0x89, 0x57, 0xce, 0x4c, 0x06, 0xf7, 0x39, 0x1d, 0x00, 0xc7, 0x41, 0x24, 0x53, 0xf4, 0xb6, 0x8b, 0x33, 0x03, 0xa1, 0x29, 0x25, 0x54, 0xe2, 0xa5, 0xfc, 0x72, 0x62, 0xc5, 0x2e, 0x74, 0xbe, 0xd7, 0x0e, 0xc5, 0x8c, 0x89, 0x50, 0xcd, 0xc4, 0x31, 0x5a, 0x8f, 0xb7, 0xc6, 0x80, 0x15, 0x54, 0xcd, 0x35, 0x78, 0x1d, 0x44, 0xfb, 0x5e, 0x57, 0xd6, 0x8d, 0x59, 0xa0, 0x0f, 0x43, 0xb8, 0x6d, 0x53, 0xb8, 0x43, 0x72, 0xd5, 0x56, 0xe5, 0xa4, 0x15, 0x3c, 0xbe, 0x6b, 0x39, 0x7c, 0x4c, 0x9c, 0x68, 0x00, 0x70, 0x5d, 0x2f, 0xc0, 0xc5, 0x48, 0x64, 0x5e, 0x11, 0xb9, 0xd8, 0xd5, 0x12, 0xb2, 0xdd, 0x9b, 0xf5, 0x9f, 0x3d, 0xc5, 0xd1, 0x1c, 0x3c, 0x77, 0x3d, 0x59, 0xcc, 0xbe, 0xd9, 0xe6, 0xbc, 0x14, 0x32, 0x09, 0x10, 0xcd, 0xf8, 0x3b, 0x46, 0x59, 0x01, 0xb7, 0x46, 0xb5, 0x96, 0x74 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.14", + /* Message to be signed */ + 66, + { 0x80, 0x8c, 0xb9, 0x76, 0x13, 0xfd, 0x87, 0x85, 0x35, 0x80, 0x1c, 0x80, 0x08, 0x79, 0x15, 0x10, 0xa5, 0xfe, 0x86, 0x6a, 0xd5, 0xb6, 0x84, 0x3a, 0x6e, 0x00, 0x19, 0xa0, 0xfc, 0xc2, 0x17, 0x76, 0x03, 0x54, 0xf6, 0x0c, 0xc6, 0x99, 0xfb, 0xbe, 0x1a, 0xdf, 0xe8, 0xb0, 0x0e, 0xcd, 0x6a, 0x36, 0xa2, 0xb5, 0xa5, 0xa1, 0xfa, 0xa2, 0x3d, 0x34, 0x38, 0x20, 0x02, 0x4e, 0x3a, 0x31, 0x97, 0xae, 0x67, 0x3c } +, + /* Signature */ + 129, + { 0x1c, 0x53, 0x96, 0x59, 0xf8, 0x72, 0x46, 0x99, 0x16, 0xfb, 0x00, 0x07, 0xef, 0x9e, 0x48, 0x57, 0x4e, 0x96, 0x4e, 0x4c, 0x0e, 0x6a, 0x2f, 0xa7, 0x4b, 0x13, 0x73, 0xfd, 0x60, 0xb6, 0x64, 0xa7, 0x98, 0xac, 0x81, 0x29, 0xc0, 0x8c, 0x12, 0xcd, 0xbf, 0x37, 0x49, 0x75, 0x0b, 0xe1, 0x25, 0x60, 0x2a, 0x71, 0x54, 0x32, 0x67, 0x67, 0x32, 0x7e, 0x92, 0xba, 0x57, 0xb5, 0xe2, 0x89, 0xb5, 0xac, 0x9d, 0x77, 0x71, 0xb4, 0x52, 0x0a, 0x7a, 0x2c, 0xe6, 0x6c, 0x5e, 0xaf, 0x70, 0x4a, 0xfc, 0x5a, 0x19, 0x0f, 0xa6, 0x0b, 0xe1, 0x37, 0x6f, 0x94, 0x3d, 0x2b, 0xaf, 0x70, 0x52, 0x3e, 0x47, 0xc3, 0xde, 0xfc, 0x0a, 0x25, 0xa6, 0x00, 0x18, 0x31, 0xa3, 0x7a, 0xab, 0x0c, 0xf1, 0xf6, 0x48, 0x7b, 0xe3, 0x7f, 0x0e, 0x31, 0xca, 0x7d, 0xb5, 0xac, 0x41, 0xb5, 0x63, 0x09, 0x57, 0x55, 0x93, 0x69, 0xff } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.15", + /* Message to be signed */ + 202, + { 0x57, 0xed, 0xaa, 0x05, 0x66, 0x25, 0x16, 0x86, 0xf6, 0x52, 0x05, 0xef, 0xc6, 0x26, 0x60, 0xe2, 0xc2, 0xe0, 0x4f, 0xa5, 0xea, 0xa3, 0x30, 0x2d, 0xe8, 0x7a, 0x3f, 0x6b, 0x49, 0x1f, 0x7f, 0xa3, 0xac, 0x72, 0x70, 0xcc, 0x76, 0x75, 0x1a, 0x43, 0x69, 0x42, 0xac, 0x76, 0x5e, 0xf5, 0xf4, 0x74, 0x91, 0x62, 0xd7, 0xe7, 0x97, 0x12, 0x6b, 0xcb, 0x8f, 0xda, 0xc1, 0x9c, 0xf1, 0x8d, 0xcc, 0x6e, 0xff, 0x48, 0x59, 0x3c, 0x05, 0xc8, 0x89, 0x3b, 0x59, 0x1a, 0x51, 0x33, 0x2f, 0xa2, 0x6a, 0xb8, 0x63, 0xc5, 0xea, 0xa4, 0xd7, 0x51, 0xe8, 0xd1, 0xb1, 0x9c, 0x58, 0x26, 0x90, 0xb5, 0x41, 0x5e, 0x6a, 0x89, 0xe0, 0x5f, 0x23, 0x1b, 0x33, 0xac, 0x38, 0xc5, 0x3f, 0x95, 0xa2, 0xd5, 0xf9, 0x10, 0x51, 0xc2, 0xec, 0x6d, 0xdb, 0x2b, 0x6d, 0xba, 0x78, 0x9d, 0x55, 0x3a, 0xdb, 0x9f, 0x10, 0xc5, 0x83, 0x59, 0x70, 0x36, 0xd3, 0x48, 0x6f, 0xbb, 0x32, 0x17, 0x2a, 0x1c, 0x11, 0x07, 0x9e, 0x5f, 0x09, 0xaa, 0x29, 0xeb, 0x46, 0x74, 0xc8, 0xd7, 0xbf, 0x5b, 0xbd, 0x6d, 0x05, 0x7e, 0x6b, 0x87, 0xa8, 0xb3, 0xaa, 0xf4, 0x80, 0x86, 0xd7, 0x21, 0xcb, 0xbc, 0x8e, 0xfa, 0xc6, 0x24, 0x4d, 0x32, 0x39, 0xae, 0x18, 0xf1, 0x66, 0x23, 0xfa, 0x52, 0x8e, 0x2e, 0x70, 0xfa, 0x25, 0x65, 0x6a, 0x6a, 0x4a, 0x22, 0x92, 0x95, 0x0f, 0xc9, 0x28, 0xed, 0xb8, 0x1c } +, + /* Signature */ + 129, + { 0x33, 0x73, 0x2f, 0xcc, 0x23, 0x34, 0x2c, 0x58, 0x51, 0x38, 0xb2, 0x5b, 0x17, 0xc8, 0x12, 0xee, 0x3e, 0x9d, 0x3d, 0xa4, 0x1f, 0x6f, 0xfb, 0xcc, 0x16, 0x17, 0xa2, 0xee, 0x75, 0xcc, 0x5b, 0x25, 0x01, 0x25, 0x4f, 0xd1, 0x97, 0x6d, 0x25, 0x88, 0x00, 0xe9, 0x05, 0xd7, 0xe4, 0x4a, 0x0a, 0xb6, 0xfb, 0x4b, 0x8a, 0x88, 0xbb, 0x7b, 0xf9, 0x31, 0x73, 0x95, 0x30, 0x3a, 0xb2, 0xfc, 0xa4, 0x31, 0x28, 0x48, 0x6a, 0x2b, 0xab, 0x36, 0xc7, 0x5e, 0xf6, 0xaa, 0x5e, 0xb3, 0xfc, 0x5b, 0xd5, 0x55, 0xb3, 0xea, 0x79, 0x12, 0x4a, 0xad, 0x78, 0x97, 0xe3, 0xa4, 0x34, 0xde, 0xe7, 0x92, 0x63, 0x71, 0xde, 0x2d, 0x6d, 0x23, 0x7e, 0x89, 0xb0, 0x3b, 0x8d, 0xd7, 0x09, 0x60, 0x58, 0xe2, 0xa4, 0xb3, 0x2c, 0xb5, 0x57, 0xc7, 0xad, 0xa2, 0x98, 0xa7, 0xe2, 0xed, 0xd3, 0xa3, 0xa3, 0xb5, 0x29, 0xb4, 0xd2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.16", + /* Message to be signed */ + 99, + { 0x08, 0x33, 0x76, 0xbb, 0x82, 0x21, 0x2b, 0xf8, 0x80, 0xbe, 0x12, 0x85, 0x65, 0x3a, 0xf2, 0xca, 0xd6, 0x25, 0xc5, 0x2e, 0x94, 0xe3, 0x21, 0x43, 0x68, 0x77, 0xf7, 0x25, 0xa8, 0x3b, 0xbd, 0x43, 0xf4, 0x48, 0x6d, 0x89, 0x6c, 0xf6, 0x7e, 0x31, 0x39, 0x1b, 0x87, 0x06, 0xf8, 0xc0, 0xf8, 0xf4, 0xbb, 0x1d, 0xdb, 0xa9, 0x5c, 0x33, 0x2f, 0x03, 0x4f, 0x39, 0x09, 0x11, 0x3f, 0x65, 0x56, 0x92, 0x60, 0xa2, 0xe4, 0xf1, 0x04, 0x06, 0x65, 0x7c, 0x99, 0xfa, 0xff, 0x00, 0x1f, 0xe1, 0x6e, 0xbb, 0x89, 0x6e, 0x9e, 0x18, 0x11, 0x5a, 0xf1, 0xd4, 0x98, 0x6c, 0x85, 0x79, 0xab, 0x56, 0x52, 0xcc, 0xca, 0x47, 0x74 } +, + /* Signature */ + 129, + { 0x2a, 0xf4, 0x6c, 0x00, 0xd1, 0xd9, 0x15, 0x94, 0x1e, 0x21, 0x2a, 0x7b, 0x8d, 0x81, 0x05, 0xee, 0x0f, 0x0e, 0xc4, 0x80, 0xff, 0xfb, 0xb4, 0xf1, 0x3b, 0xf2, 0x8d, 0x73, 0xe2, 0xb3, 0x19, 0xb9, 0x84, 0xa7, 0xb7, 0xc8, 0x36, 0x7a, 0xdc, 0xa7, 0xab, 0x12, 0xaa, 0xf5, 0x3a, 0xcb, 0x98, 0xd0, 0xcb, 0x54, 0xee, 0x34, 0x20, 0x4c, 0x90, 0x8e, 0x60, 0xc7, 0xc7, 0x9e, 0xfb, 0x42, 0xc3, 0x11, 0x4a, 0x02, 0x58, 0x9e, 0x1a, 0xe6, 0xaf, 0xb5, 0x97, 0x53, 0x54, 0x57, 0x8c, 0x14, 0x35, 0xec, 0xc8, 0x9c, 0x11, 0x6e, 0x90, 0x26, 0xb6, 0xbc, 0x88, 0x9e, 0xe2, 0x88, 0xae, 0x4d, 0xaf, 0x03, 0x47, 0xcc, 0xce, 0xfc, 0x5d, 0xfd, 0x1e, 0xf8, 0x3c, 0xb8, 0x68, 0x52, 0xee, 0xff, 0xd8, 0x40, 0x98, 0x59, 0x9b, 0x72, 0x5b, 0xf6, 0x02, 0xee, 0x62, 0x0b, 0xdf, 0x44, 0xaf, 0xbd, 0x84, 0xc0, 0xcd } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.17", + /* Message to be signed */ + 17, + { 0x8c, 0x87, 0x4c, 0xd0, 0xce, 0x33, 0x51, 0x39, 0xc0, 0x8d, 0x76, 0x0b, 0x82, 0x5e, 0xb9, 0x90, 0x5d } +, + /* Signature */ + 129, + { 0x66, 0x9a, 0x8a, 0xd7, 0xcb, 0x81, 0xef, 0x21, 0x87, 0xf5, 0xa8, 0x56, 0x47, 0x68, 0x4b, 0x72, 0x48, 0x4a, 0xff, 0x27, 0x9f, 0x0a, 0xf3, 0x54, 0x35, 0x86, 0x7c, 0xc2, 0xb0, 0x43, 0x33, 0xa1, 0x96, 0xec, 0xa6, 0xcf, 0x44, 0xa9, 0x7a, 0x1b, 0xd3, 0x9d, 0x0f, 0x6a, 0x0f, 0xf9, 0x59, 0x57, 0x02, 0x83, 0x5b, 0xc8, 0x0a, 0x72, 0xd7, 0x14, 0x04, 0xef, 0x3f, 0x46, 0xfa, 0x3b, 0x0d, 0x20, 0xe8, 0x6d, 0x7a, 0x1d, 0x5f, 0x7e, 0xfc, 0x3f, 0x3b, 0x8e, 0x8a, 0x7e, 0x37, 0xe8, 0x7e, 0x27, 0xa9, 0x9f, 0xeb, 0xa9, 0x6a, 0xd8, 0x13, 0x20, 0xbe, 0x8f, 0xff, 0x78, 0x55, 0x7d, 0x07, 0xbf, 0xba, 0xe2, 0x16, 0x03, 0xa1, 0x36, 0x8c, 0xaf, 0xa5, 0xae, 0x1d, 0x1b, 0x63, 0x0a, 0xa2, 0x1f, 0xf2, 0x0e, 0x45, 0x85, 0x65, 0x0a, 0x77, 0x3d, 0x7e, 0x2f, 0x5e, 0x7f, 0x51, 0x72, 0x97, 0x19, 0x3c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.18", + /* Message to be signed */ + 102, + { 0xcb, 0x3e, 0x61, 0x21, 0xd3, 0x8b, 0x7d, 0x97, 0xe1, 0x8b, 0xa1, 0x5c, 0x49, 0x3d, 0x1a, 0xc3, 0x2e, 0x9d, 0x2e, 0xf4, 0xe3, 0xbd, 0x16, 0xdf, 0x9c, 0x67, 0xe4, 0xa1, 0x96, 0xe9, 0x24, 0x7a, 0x8d, 0x0c, 0x24, 0xb2, 0x1c, 0x4a, 0xb2, 0x3e, 0x77, 0xd6, 0xdb, 0x11, 0x7d, 0x59, 0x11, 0x95, 0xbb, 0xaf, 0x44, 0x66, 0x82, 0x5f, 0x63, 0x97, 0x8f, 0x11, 0x40, 0x85, 0x28, 0x1b, 0x79, 0xae, 0xa3, 0x7e, 0x32, 0xc6, 0xb3, 0x6c, 0x1e, 0x9d, 0xdd, 0x4a, 0xd1, 0x23, 0x6e, 0x97, 0xfd, 0x42, 0x7b, 0x4d, 0x97, 0x6e, 0x07, 0x64, 0x9d, 0xca, 0x4f, 0x33, 0xa8, 0x9c, 0x46, 0xfb, 0x8c, 0x00, 0xb4, 0x26, 0x7b, 0x14, 0x47, 0x04 } +, + /* Signature */ + 129, + { 0x56, 0x84, 0x17, 0x80, 0x3a, 0x40, 0x0e, 0x9d, 0x05, 0x0a, 0x43, 0x20, 0xae, 0x7b, 0x7d, 0x8d, 0x24, 0x8e, 0x16, 0x36, 0x50, 0x86, 0x9d, 0x9f, 0xdd, 0x10, 0x0c, 0xc1, 0xa6, 0xb9, 0xbc, 0x29, 0x1c, 0x3f, 0x23, 0xf1, 0x25, 0x60, 0x03, 0x16, 0x4f, 0x61, 0x9d, 0xbc, 0x78, 0x63, 0x5e, 0xbd, 0xf0, 0x89, 0x49, 0x0a, 0xfa, 0x5a, 0xa0, 0x0b, 0x6f, 0x97, 0xeb, 0x06, 0x36, 0xc3, 0xbb, 0xa8, 0x9d, 0x86, 0x36, 0x0a, 0xfe, 0x26, 0x00, 0x43, 0xd8, 0x61, 0xa7, 0x4f, 0x64, 0xc7, 0x1d, 0x9c, 0xbd, 0x31, 0xea, 0xe2, 0x39, 0x3a, 0x1a, 0xf1, 0x56, 0x1f, 0x1a, 0xb9, 0x2c, 0xaa, 0x76, 0xdd, 0x1e, 0x76, 0xab, 0x23, 0x33, 0x09, 0x8c, 0x83, 0xc2, 0xd9, 0x9f, 0xae, 0x82, 0x73, 0x98, 0x75, 0x80, 0x05, 0xc1, 0x76, 0xcb, 0xc4, 0xa2, 0xe2, 0x2e, 0xfa, 0x0e, 0x6c, 0x12, 0xf4, 0xe3, 0x42, 0x81 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.19", + /* Message to be signed */ + 81, + { 0x21, 0x9a, 0x2f, 0x8d, 0x0b, 0x00, 0x0a, 0xed, 0xb5, 0xf1, 0x85, 0x45, 0x5e, 0xd3, 0xea, 0x09, 0x4c, 0x45, 0x42, 0x6b, 0x28, 0x5b, 0xab, 0x4a, 0x07, 0xcf, 0x3d, 0x0a, 0x29, 0x06, 0xf3, 0xe2, 0x03, 0x18, 0x4c, 0x2d, 0x3d, 0x81, 0xa8, 0x09, 0xb8, 0x9c, 0x9f, 0xc4, 0x8b, 0xc9, 0xaf, 0x9a, 0xb3, 0x2f, 0x84, 0xf1, 0x5d, 0x81, 0x38, 0x9c, 0x4e, 0xdb, 0x0a, 0xc6, 0x8a, 0xd0, 0x95, 0x02, 0xe3, 0xf3, 0x0c, 0x7c, 0xf6, 0x45, 0x10, 0x29, 0x54, 0xb2, 0x97, 0xc8, 0x66, 0x14, 0x66, 0xfc, 0x10 } +, + /* Signature */ + 129, + { 0x03, 0x83, 0x5d, 0x90, 0x57, 0xe2, 0xb8, 0x21, 0xdc, 0x4c, 0x6e, 0xac, 0xa3, 0xf4, 0x15, 0x6a, 0x56, 0x55, 0x0b, 0x6f, 0x9d, 0x74, 0x00, 0xfc, 0x5c, 0x51, 0x95, 0xa4, 0xae, 0xe4, 0x71, 0x7d, 0xf3, 0x29, 0x29, 0x12, 0x2b, 0x43, 0x27, 0x3a, 0x07, 0x9a, 0x24, 0xf9, 0x9d, 0xd9, 0xe7, 0xc3, 0x40, 0x56, 0xae, 0xa4, 0xfc, 0x4e, 0x45, 0x7d, 0x83, 0x14, 0xef, 0x34, 0x42, 0x7f, 0x8e, 0x20, 0x4b, 0x81, 0xbb, 0x49, 0x03, 0xfb, 0x3e, 0x77, 0x9e, 0x38, 0x9e, 0x41, 0x33, 0x90, 0x68, 0xc1, 0x57, 0xd9, 0xb0, 0x9f, 0x2c, 0x5e, 0x99, 0xcc, 0x54, 0xe6, 0xef, 0x86, 0xee, 0xac, 0x0e, 0x19, 0xf4, 0x4e, 0x33, 0xe7, 0x07, 0xc4, 0x26, 0x1a, 0x0a, 0x83, 0xce, 0xb4, 0x22, 0xf2, 0xe0, 0x6b, 0xcc, 0xae, 0x3b, 0x8b, 0xba, 0x42, 0x8d, 0x75, 0x57, 0x15, 0x2f, 0x40, 0x84, 0x6e, 0xc0, 0x11, 0x34 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 13.20", + /* Message to be signed */ + 97, + { 0xe3, 0x9c, 0xa4, 0x0d, 0x2e, 0x9d, 0x03, 0xae, 0x05, 0x96, 0xf6, 0x0e, 0xb8, 0xf6, 0x09, 0x99, 0x30, 0x85, 0xa5, 0xdb, 0x15, 0x6b, 0x0d, 0x50, 0x98, 0xfe, 0x5f, 0xaa, 0xc5, 0x5f, 0x70, 0x99, 0x3f, 0xe1, 0x76, 0xd2, 0xd0, 0xc0, 0x38, 0xb8, 0x60, 0xbb, 0xf9, 0xa6, 0x62, 0x43, 0xf5, 0xe7, 0x8e, 0x6c, 0xbe, 0x52, 0x6e, 0xcf, 0x25, 0x12, 0x8d, 0xae, 0x31, 0x96, 0x56, 0xcc, 0x32, 0x1e, 0xe8, 0x0a, 0x50, 0x53, 0x14, 0x90, 0xc9, 0xa6, 0x24, 0x3f, 0xbd, 0xb0, 0xc5, 0xeb, 0x4c, 0xd6, 0x42, 0xd2, 0x61, 0x15, 0x05, 0xae, 0x10, 0x84, 0x97, 0x57, 0x38, 0xad, 0x84, 0x62, 0x1d, 0x67, 0xf5 } +, + /* Signature */ + 129, + { 0x4f, 0xcf, 0xa5, 0x73, 0x97, 0xf2, 0x7e, 0xe0, 0xf8, 0xae, 0x75, 0xa0, 0xa5, 0x4d, 0x54, 0xb0, 0xc5, 0x1b, 0x95, 0x7e, 0xe6, 0x3b, 0xf7, 0x90, 0x1b, 0x60, 0x55, 0xcc, 0x39, 0x87, 0xc3, 0x2d, 0xf7, 0x22, 0x0e, 0x16, 0x6a, 0x71, 0x60, 0x6a, 0xbc, 0x78, 0xf9, 0x11, 0x07, 0xf9, 0x74, 0xdf, 0xf7, 0xd6, 0x25, 0x7c, 0x25, 0x6d, 0xc6, 0xed, 0x7a, 0x69, 0xc3, 0xc9, 0x9f, 0x9f, 0x89, 0xab, 0xb5, 0x8f, 0xe5, 0x89, 0xb7, 0xee, 0x7c, 0xad, 0x0f, 0x48, 0xc1, 0x60, 0x10, 0xd0, 0x46, 0xa9, 0xc4, 0xe0, 0x04, 0xbb, 0xe1, 0xa8, 0x29, 0x79, 0x68, 0xd4, 0x0b, 0xc7, 0x06, 0x82, 0xeb, 0xae, 0xa4, 0x48, 0x52, 0x5d, 0xbe, 0xe1, 0x6b, 0x03, 0xbd, 0x0b, 0x65, 0x26, 0xd0, 0x98, 0xd0, 0x9b, 0x6b, 0xad, 0x9a, 0xba, 0x03, 0x93, 0x05, 0xe2, 0xab, 0x79, 0x69, 0x02, 0x08, 0x65, 0x80, 0xcc, 0xf0 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 14: A 1536-bit RSA key pair", +{ + /* Modulus */ + 192, + { 0xd8, 0x70, 0xa7, 0x76, 0xcd, 0x13, 0xed, 0x44, 0x3d, 0xf3, 0x99, 0x08, 0xbe, 0xe2, 0xca, 0xd7, 0x3c, 0x48, 0x5f, 0xd9, 0xbf, 0x06, 0x32, 0x13, 0x22, 0x88, 0x7f, 0xbe, 0x65, 0x5c, 0x08, 0xcb, 0xe4, 0xc8, 0xf6, 0x3e, 0x25, 0x4f, 0xc9, 0x1c, 0x75, 0xf0, 0x55, 0x7d, 0x90, 0x1d, 0x43, 0x5b, 0x0e, 0x8d, 0xed, 0x82, 0xd4, 0x91, 0x73, 0x41, 0x4d, 0x29, 0x86, 0x03, 0x24, 0xe4, 0x6c, 0x1b, 0x03, 0x0d, 0xfe, 0xaa, 0x29, 0xd8, 0x0f, 0x98, 0x98, 0xc2, 0xc5, 0xe1, 0x01, 0xcb, 0xf6, 0xda, 0xa0, 0x62, 0x89, 0x78, 0xd4, 0x15, 0xb5, 0x02, 0xde, 0xa2, 0x6d, 0xe6, 0x56, 0x1c, 0x79, 0xab, 0x06, 0x5c, 0x6d, 0xca, 0x6a, 0xbc, 0x4d, 0x4d, 0x4d, 0x5e, 0x9f, 0x5c, 0x74, 0xcb, 0x3e, 0x6a, 0x5a, 0xf7, 0x1d, 0x1f, 0x90, 0xfa, 0x5e, 0xaa, 0x1b, 0xe0, 0xca, 0x94, 0x7a, 0x70, 0xa3, 0x9e, 0xfd, 0x31, 0x5c, 0x4d, 0xf2, 0x1a, 0x1a, 0x82, 0x1c, 0xaa, 0xff, 0x8d, 0xcb, 0xad, 0x13, 0xb2, 0x9c, 0x7e, 0x82, 0xaa, 0xd5, 0x3c, 0x64, 0xf5, 0x82, 0xec, 0x9e, 0xc3, 0x1e, 0x6b, 0xde, 0x82, 0xea, 0x5a, 0x5f, 0x4c, 0xcc, 0xf0, 0xc4, 0x57, 0xb8, 0x88, 0xf1, 0x55, 0x0c, 0x4f, 0xf8, 0xe1, 0xc1, 0x78, 0xa7, 0x6a, 0x46, 0xc1, 0x96, 0xf4, 0xbe, 0xf5, 0x9e, 0x61, 0xdd, 0x94, 0x4e, 0x47 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 192, + { 0x05, 0x88, 0x8f, 0xc7, 0x7a, 0x43, 0xbd, 0xa7, 0xa6, 0x7b, 0xd1, 0x58, 0x47, 0x65, 0x0d, 0xf1, 0x85, 0xc1, 0x85, 0xed, 0xcf, 0xb3, 0xed, 0x58, 0xce, 0xe3, 0xb5, 0x7c, 0x5d, 0x24, 0x06, 0xb7, 0x8b, 0xc0, 0x55, 0x87, 0x4e, 0x35, 0xe5, 0x7a, 0xdc, 0x4b, 0x0a, 0x2c, 0x7d, 0x20, 0x3a, 0x66, 0x1c, 0x0f, 0xa5, 0xd8, 0x57, 0xed, 0xe6, 0x07, 0xef, 0xdc, 0x95, 0x68, 0x04, 0x2b, 0xf0, 0xd5, 0x99, 0xf4, 0xe4, 0x23, 0x5e, 0x91, 0x7f, 0x08, 0x94, 0x33, 0x3a, 0x92, 0xdf, 0x94, 0x62, 0xd9, 0xc1, 0x0a, 0xf3, 0xdf, 0xca, 0x70, 0x49, 0xa1, 0xea, 0xa6, 0x35, 0x70, 0x13, 0x98, 0x83, 0xc5, 0xbe, 0xfe, 0xbe, 0xe4, 0xe2, 0x21, 0x89, 0x43, 0xd3, 0x0f, 0xc6, 0x45, 0xff, 0xe8, 0xb9, 0x14, 0xd2, 0x18, 0xdd, 0x58, 0x96, 0x0a, 0xad, 0xc1, 0x21, 0x71, 0x5b, 0xce, 0x5c, 0xcd, 0xde, 0x4a, 0x2c, 0x73, 0xa8, 0xd9, 0xd8, 0x6a, 0x4e, 0xb6, 0xe4, 0x55, 0xdc, 0x92, 0x4f, 0xd7, 0x4a, 0x0b, 0x1f, 0x75, 0x69, 0x1c, 0x28, 0x1b, 0xae, 0x91, 0x4d, 0x69, 0x9e, 0xe2, 0x59, 0xd8, 0x5c, 0x5f, 0xb5, 0xdd, 0x99, 0x9e, 0xbe, 0xf9, 0xb7, 0x0a, 0x4b, 0xd9, 0x4a, 0xa4, 0xfa, 0xfa, 0xe2, 0x6c, 0xa7, 0x84, 0xd3, 0x2f, 0xd4, 0xe0, 0x77, 0xdb, 0xb6, 0xea, 0x69, 0x3b, 0xcd, 0x6d, 0x27, 0xd5 } +, + /* Prime 1 */ + 96, + { 0xff, 0x8e, 0xf1, 0xe7, 0x4c, 0x44, 0x5a, 0x5c, 0xc8, 0x97, 0x3a, 0x81, 0x9c, 0x75, 0x45, 0x49, 0x12, 0x35, 0x72, 0x0c, 0xf9, 0xeb, 0x83, 0xf1, 0x81, 0x13, 0x3c, 0x78, 0xa1, 0x4d, 0xcc, 0x4c, 0xe5, 0xe7, 0x75, 0xbe, 0x3e, 0x0c, 0x46, 0xed, 0x2f, 0x21, 0x9a, 0xb8, 0x8d, 0x87, 0x77, 0xad, 0x6e, 0xcb, 0xe4, 0x0c, 0xf9, 0x18, 0x76, 0x4d, 0x7e, 0x37, 0xc6, 0x68, 0x35, 0x91, 0xe7, 0xaa, 0xa1, 0x3b, 0x24, 0x4b, 0x7f, 0xcc, 0x0e, 0xb6, 0xdf, 0xd7, 0x6a, 0x11, 0x5f, 0x30, 0xed, 0x2d, 0x63, 0x68, 0xc8, 0xea, 0x78, 0x0a, 0x21, 0x1c, 0x0a, 0xc9, 0xc0, 0x72, 0x5d, 0xfa, 0xb0, 0x8d } +, + /* Prime 2 */ + 96, + { 0xd8, 0xd0, 0x67, 0x64, 0xc1, 0xf7, 0x64, 0x54, 0xc6, 0x8a, 0x3a, 0x08, 0x1e, 0x95, 0xd7, 0x47, 0xc2, 0x94, 0x11, 0xad, 0xc4, 0x03, 0xa7, 0xcb, 0x71, 0xb4, 0x3a, 0xf5, 0x05, 0xca, 0xbe, 0x41, 0xb4, 0x9c, 0x97, 0x1c, 0x13, 0xad, 0x65, 0x63, 0xb8, 0xc9, 0x0b, 0x93, 0xb5, 0x89, 0x79, 0xbb, 0x74, 0xf8, 0x20, 0xef, 0xb8, 0xde, 0xd8, 0x1f, 0x46, 0x30, 0x54, 0xa7, 0x7f, 0xb3, 0x0b, 0xb0, 0x99, 0x98, 0x51, 0xa4, 0x3c, 0xcd, 0x01, 0x69, 0x18, 0x51, 0x31, 0xf7, 0x43, 0x1b, 0x02, 0xe9, 0xc6, 0xb9, 0xf8, 0x38, 0x71, 0xd9, 0xcd, 0x5e, 0x0c, 0x3c, 0x58, 0x70, 0xcf, 0x97, 0x97, 0x23 } +, + /* Prime exponent 1 */ + 96, + { 0xe8, 0xd6, 0x15, 0xf4, 0x04, 0x7a, 0xaa, 0x51, 0xaa, 0xb8, 0x8e, 0x27, 0x94, 0xa3, 0x0b, 0xd3, 0x3d, 0x71, 0xd0, 0x4d, 0x9e, 0x4e, 0x43, 0xd2, 0x7f, 0x25, 0x45, 0x8d, 0x2a, 0x79, 0xb5, 0x4f, 0xc2, 0x8f, 0x95, 0xa9, 0x14, 0xe3, 0x1e, 0xa3, 0xee, 0xb3, 0x11, 0x42, 0x60, 0x40, 0x32, 0x7b, 0xa3, 0x5c, 0xc4, 0x94, 0x45, 0x47, 0x52, 0x51, 0xdc, 0x53, 0x78, 0xc3, 0x6d, 0x3b, 0x57, 0xf5, 0x10, 0x1c, 0xd0, 0x3e, 0xb1, 0x5a, 0xfb, 0x75, 0x06, 0x90, 0x3f, 0x25, 0x40, 0xb3, 0x55, 0x04, 0x6b, 0x74, 0x06, 0xca, 0x09, 0x40, 0x41, 0x56, 0x49, 0x45, 0xf3, 0xbe, 0xbf, 0x7d, 0x2d, 0xe9 } +, + /* Prime exponent 2 */ + 96, + { 0x73, 0x5d, 0xb1, 0x26, 0x73, 0xef, 0x67, 0x7b, 0x94, 0x89, 0x48, 0x87, 0xb9, 0x7e, 0x91, 0xa6, 0xa5, 0x6a, 0x94, 0x5d, 0x99, 0xc7, 0x38, 0x29, 0x90, 0xbf, 0x0e, 0x00, 0x02, 0xac, 0xf6, 0xbf, 0x8f, 0x93, 0x22, 0xf4, 0xd5, 0xa3, 0x96, 0x27, 0x91, 0xd3, 0xa8, 0x4d, 0x58, 0x73, 0x66, 0x4a, 0xd0, 0xda, 0x96, 0xeb, 0xf7, 0xba, 0xdb, 0xd5, 0x08, 0x4b, 0xff, 0x3f, 0x81, 0x3b, 0x8c, 0x24, 0xd4, 0x15, 0xb0, 0x9b, 0x6b, 0x9e, 0xc9, 0xf9, 0x59, 0xef, 0x1a, 0x5f, 0x2f, 0x5d, 0xd8, 0x16, 0xfc, 0x9f, 0x47, 0xed, 0x00, 0xe7, 0x9b, 0xd7, 0x47, 0x3b, 0x74, 0xf3, 0xd2, 0x02, 0x1f, 0x71 } +, + /* Coefficient */ + 96, + { 0x10, 0x62, 0x18, 0xaf, 0x97, 0x1d, 0x92, 0x95, 0x91, 0x59, 0x90, 0xa4, 0xed, 0x3e, 0x09, 0xd3, 0x63, 0xdb, 0x33, 0x06, 0xb0, 0x90, 0xa1, 0x33, 0xeb, 0xd7, 0x54, 0xe2, 0xbd, 0x77, 0x6b, 0x25, 0x85, 0x99, 0x9d, 0x4f, 0x88, 0x43, 0x03, 0x0a, 0xc7, 0x0c, 0x0f, 0xf5, 0xde, 0x52, 0x12, 0x67, 0x22, 0x34, 0xc0, 0x07, 0xce, 0x74, 0x56, 0x4c, 0x79, 0x1e, 0xdc, 0xd5, 0x76, 0xf9, 0x68, 0x44, 0x04, 0x8c, 0xfa, 0x66, 0x36, 0x46, 0xb8, 0xfd, 0x80, 0xc7, 0x51, 0x26, 0xb2, 0x26, 0x6e, 0x48, 0xf1, 0xfa, 0xa7, 0x05, 0x44, 0xad, 0x42, 0x04, 0xfd, 0x61, 0x56, 0x29, 0x2e, 0x51, 0x6e, 0x13 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 14.1", + /* Message to be signed */ + 135, + { 0xf7, 0xa3, 0xc6, 0x7e, 0x92, 0xa7, 0x87, 0xf3, 0x5d, 0xcc, 0x47, 0xae, 0xd7, 0xd6, 0xb6, 0x19, 0x29, 0x67, 0xbd, 0xfd, 0x00, 0xa6, 0xac, 0xbf, 0x6f, 0x7e, 0xfe, 0x46, 0xd3, 0xac, 0xae, 0xd9, 0x78, 0x8a, 0xa4, 0xf1, 0xdb, 0x18, 0x44, 0x02, 0x24, 0x9f, 0x9a, 0xce, 0xfc, 0x1c, 0x7d, 0xfb, 0x1e, 0x69, 0x0d, 0x24, 0x73, 0x8d, 0xe8, 0x6f, 0xa5, 0xb5, 0x25, 0x0f, 0x97, 0x9e, 0xbd, 0x8f, 0x77, 0x8e, 0xec, 0x0d, 0x7f, 0xcf, 0x73, 0x1f, 0xa2, 0x25, 0x08, 0x6c, 0x86, 0x65, 0x64, 0xed, 0x3e, 0xb1, 0x54, 0xdd, 0x45, 0x8d, 0x05, 0x00, 0x28, 0x2f, 0x86, 0x80, 0x48, 0x87, 0xd4, 0x43, 0x5e, 0xda, 0x9a, 0x44, 0x36, 0xa8, 0xe9, 0x23, 0xa2, 0x0c, 0xb4, 0xb4, 0xd0, 0xe8, 0x1c, 0x91, 0x11, 0x4b, 0xdc, 0x06, 0x82, 0x27, 0x8e, 0xc2, 0x58, 0x86, 0x07, 0x99, 0xb5, 0x9c, 0x94, 0x36, 0xf4, 0x3a, 0x53, 0xca, 0xb4, 0xc4, 0xcd } +, + /* Signature */ + 192, + { 0x09, 0xd1, 0x43, 0x5b, 0xf5, 0xa9, 0xc1, 0x72, 0x03, 0xd5, 0x37, 0xfe, 0x57, 0xdf, 0x98, 0x7b, 0x7a, 0x51, 0xf3, 0x4b, 0x2a, 0x14, 0x09, 0x7e, 0x06, 0xa0, 0xde, 0x56, 0x3b, 0xe7, 0xd6, 0x4b, 0x4e, 0xa3, 0x79, 0x73, 0xb4, 0xfe, 0x99, 0x73, 0xa6, 0x6a, 0x3f, 0x31, 0xba, 0x8e, 0x07, 0xe9, 0x11, 0x7b, 0x6a, 0x1e, 0xe7, 0x09, 0x61, 0x33, 0x7b, 0x4d, 0x2b, 0x0d, 0xf5, 0x98, 0x10, 0xb6, 0x24, 0x08, 0x51, 0x18, 0xbd, 0xa7, 0x0a, 0xc7, 0x4a, 0xe4, 0x3e, 0x2f, 0xbc, 0xf8, 0x92, 0x27, 0x63, 0x03, 0x23, 0xda, 0x68, 0x30, 0xf5, 0xb1, 0xa2, 0xb9, 0x54, 0xf1, 0xb1, 0x5a, 0xea, 0x07, 0x54, 0xdf, 0x2c, 0x51, 0x18, 0x57, 0x95, 0x16, 0xe8, 0x77, 0xcc, 0xb0, 0xb1, 0x28, 0x6c, 0x57, 0x24, 0x65, 0x5e, 0xf8, 0xd2, 0x91, 0x85, 0x66, 0x6f, 0x6e, 0x9b, 0xd3, 0x2a, 0x6b, 0xd9, 0xce, 0x9e, 0x1e, 0xf9, 0x47, 0x29, 0xfc, 0x67, 0xd6, 0xa3, 0x0e, 0x64, 0x56, 0x0e, 0xcf, 0x78, 0xbf, 0x8e, 0x1b, 0x2b, 0x40, 0xe5, 0x06, 0x05, 0xe2, 0x5a, 0xe8, 0x0c, 0x38, 0x67, 0x64, 0xae, 0xd1, 0x1a, 0x0e, 0x71, 0x44, 0x90, 0x49, 0xc9, 0x39, 0xb2, 0x96, 0x2f, 0x6c, 0x24, 0x17, 0xa3, 0x58, 0xcd, 0xc8, 0x10, 0x6b, 0x12, 0xb1, 0xa5, 0x58, 0x76, 0x39, 0x43, 0x8a, 0xf1, 0xa6, 0x8d, 0x32 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 14.2", + /* Message to be signed */ + 131, + { 0x2a, 0x13, 0x30, 0x03, 0xab, 0x67, 0xcd, 0xd2, 0xe8, 0x3b, 0x44, 0xe9, 0xe9, 0xdc, 0x77, 0x7d, 0xe0, 0x1f, 0x4d, 0x23, 0x3d, 0x22, 0xe7, 0xd2, 0xb4, 0x46, 0x7f, 0x04, 0x81, 0x2a, 0x3a, 0xeb, 0xff, 0xb1, 0x0a, 0x09, 0x24, 0x54, 0xe3, 0x3b, 0x9e, 0x70, 0x28, 0x24, 0x93, 0x28, 0x74, 0x7e, 0xa1, 0x4a, 0x11, 0xc7, 0x98, 0xac, 0x2e, 0x14, 0x6e, 0x4e, 0x49, 0x65, 0x9b, 0xa8, 0x60, 0x67, 0xdb, 0x64, 0xe9, 0xbd, 0x80, 0xa7, 0x02, 0x1a, 0xab, 0xcc, 0x22, 0x85, 0x6e, 0x81, 0x01, 0x40, 0xc2, 0x0f, 0xd8, 0xc6, 0x52, 0x7b, 0xad, 0xbb, 0xd9, 0xfa, 0x59, 0x53, 0xfa, 0x77, 0xe6, 0x85, 0x87, 0x00, 0xbe, 0xb6, 0xc7, 0x4d, 0x5a, 0x46, 0x3c, 0x9d, 0xa8, 0x61, 0x13, 0x3b, 0xaa, 0x5b, 0xd6, 0xa5, 0x99, 0x80, 0x7a, 0xe9, 0x16, 0x2e, 0x3a, 0xf3, 0xa3, 0x48, 0xd0, 0x4a, 0x4e, 0xdd, 0x2f, 0xfb, 0xab } +, + /* Signature */ + 192, + { 0x35, 0xe6, 0x66, 0xcf, 0xb8, 0x7c, 0x04, 0x88, 0xa8, 0x6f, 0xdf, 0xed, 0x5f, 0x9d, 0xea, 0xed, 0xbc, 0x46, 0x74, 0x17, 0x1c, 0x31, 0x84, 0x59, 0xac, 0xaa, 0xaa, 0x20, 0xe1, 0xca, 0xd7, 0xc5, 0x86, 0x04, 0x14, 0x0a, 0x80, 0xff, 0x7f, 0x56, 0x5b, 0xfb, 0xc8, 0x6e, 0x90, 0x32, 0x8d, 0x4c, 0x72, 0x9b, 0x91, 0xbf, 0x72, 0xa9, 0x8d, 0xb7, 0x01, 0xc1, 0xbe, 0x63, 0x8a, 0x6e, 0x8f, 0x2e, 0x46, 0x8f, 0x20, 0x39, 0x24, 0x70, 0xc7, 0xc5, 0xc3, 0x44, 0x42, 0xd5, 0x1b, 0x1b, 0x15, 0x5f, 0xb4, 0x64, 0xb8, 0xa5, 0x56, 0xf4, 0xa1, 0x70, 0xc0, 0x23, 0x01, 0xfe, 0xd0, 0xd1, 0xaa, 0x92, 0xaa, 0xfd, 0xeb, 0xc3, 0xf1, 0x8e, 0xa8, 0xb4, 0xd7, 0x1e, 0x24, 0x5c, 0x25, 0x26, 0xf6, 0xfe, 0x66, 0x5d, 0xe4, 0x83, 0x85, 0xf4, 0x6c, 0xe1, 0xbf, 0x33, 0x12, 0xfa, 0x89, 0x28, 0x09, 0x8e, 0xd3, 0x31, 0x2b, 0x61, 0x11, 0x6c, 0xa7, 0xe4, 0x23, 0x20, 0x4e, 0xf0, 0x8b, 0xd2, 0xdf, 0x3a, 0xd7, 0xbb, 0xc8, 0x50, 0x09, 0x8c, 0xb0, 0x26, 0x83, 0x26, 0x66, 0x25, 0xbb, 0xd9, 0x59, 0x82, 0x51, 0x35, 0xa4, 0x5f, 0x03, 0x82, 0x9d, 0x09, 0x6f, 0xed, 0x18, 0xb2, 0x0b, 0xaa, 0x3f, 0x9d, 0x44, 0xb0, 0x07, 0xaa, 0x24, 0x1f, 0x92, 0xf8, 0x88, 0x60, 0x55, 0xd9, 0x8e, 0x0e, 0x07, 0x04 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.3", + /* Message to be signed */ + 42, + { 0x58, 0x62, 0x7f, 0xfa, 0xaa, 0x8e, 0x80, 0x0a, 0x8b, 0xe9, 0x8e, 0x42, 0xf5, 0x1a, 0x83, 0x61, 0x1c, 0xfa, 0xb7, 0xee, 0x37, 0x6b, 0x34, 0x73, 0x7b, 0x3e, 0x48, 0xe1, 0xbc, 0x17, 0x42, 0xda, 0xa7, 0x7d, 0xe4, 0x7e, 0x1a, 0x9b, 0x29, 0x33, 0x77, 0xaa } +, + /* Signature */ + 192, + { 0x3d, 0x17, 0xcb, 0x38, 0x6c, 0x88, 0x78, 0x4d, 0x35, 0x9a, 0xd3, 0xc3, 0x8d, 0xbe, 0x88, 0x8b, 0xfa, 0xe8, 0x31, 0xbf, 0xb8, 0xed, 0xc9, 0xd0, 0xe8, 0x01, 0xe7, 0xd6, 0x9e, 0x1d, 0xd4, 0xc2, 0x44, 0x1d, 0x68, 0xfd, 0xbb, 0x35, 0x12, 0x6c, 0x73, 0xa4, 0xed, 0xab, 0xbf, 0xf5, 0x4e, 0x74, 0xfa, 0x51, 0x09, 0xda, 0xd8, 0xb5, 0xc3, 0x13, 0xd8, 0x6a, 0x79, 0xe4, 0xd4, 0x12, 0x76, 0x60, 0xfc, 0x2a, 0x8e, 0x1c, 0x93, 0xfa, 0x8d, 0x09, 0x2a, 0xcc, 0xf0, 0x1c, 0xc1, 0x8a, 0x60, 0x6c, 0xf0, 0x7d, 0xe2, 0xdc, 0x3e, 0x7b, 0x55, 0x33, 0x11, 0x52, 0xdb, 0x01, 0xb6, 0xca, 0xea, 0x1e, 0xce, 0xc9, 0x09, 0x31, 0x99, 0xbe, 0x62, 0xc3, 0xe1, 0x23, 0xe2, 0x87, 0x31, 0x13, 0x50, 0x3b, 0x22, 0x03, 0x0f, 0x16, 0x8d, 0xaf, 0xc4, 0xe6, 0xbd, 0x06, 0x5a, 0xd2, 0xf6, 0xb1, 0xde, 0xd0, 0x5b, 0xe0, 0xc2, 0xf9, 0xb6, 0x7b, 0xdc, 0x1a, 0x3b, 0xb1, 0x8d, 0xa9, 0x59, 0x4c, 0x95, 0x7d, 0xa4, 0xe4, 0x9f, 0xac, 0x3f, 0xe7, 0x6e, 0x07, 0x66, 0xf7, 0x4e, 0xb0, 0xd5, 0x23, 0xe4, 0xdd, 0x1a, 0xe7, 0x59, 0xda, 0xd6, 0xb9, 0xb9, 0x08, 0xb7, 0xfc, 0x8b, 0x97, 0xef, 0x5f, 0x4c, 0x82, 0x92, 0x32, 0x0a, 0xc3, 0x87, 0xc3, 0x50, 0x8b, 0x54, 0xcf, 0xb8, 0x5d, 0x34, 0xf6, 0xad, 0x39 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.4", + /* Message to be signed */ + 173, + { 0x0f, 0x0f, 0x8d, 0x3c, 0x0e, 0x4d, 0x26, 0x08, 0xaf, 0xad, 0x5a, 0x88, 0x8e, 0xa1, 0x4b, 0x3f, 0x6b, 0x2b, 0x27, 0x89, 0xdd, 0x22, 0x12, 0xb8, 0x59, 0x09, 0xe6, 0x4b, 0xfb, 0x10, 0x4d, 0x0f, 0x7d, 0xe4, 0x27, 0xd1, 0x4a, 0x9f, 0xfa, 0x85, 0x5e, 0x2d, 0x4c, 0xa2, 0x44, 0x23, 0x36, 0xe5, 0x59, 0x56, 0x8b, 0x28, 0x41, 0x5d, 0x60, 0xcf, 0x80, 0x63, 0xde, 0x55, 0x92, 0x17, 0x1b, 0x26, 0x9b, 0x3d, 0x76, 0x33, 0x51, 0xc7, 0xf7, 0xd9, 0xd2, 0x58, 0x09, 0xe7, 0x02, 0x20, 0xee, 0x30, 0xfe, 0x8a, 0x00, 0xb9, 0x5d, 0x4c, 0x20, 0x20, 0x26, 0x89, 0x7e, 0xd2, 0xc6, 0x1d, 0x7a, 0xd4, 0x3a, 0xed, 0xdf, 0x36, 0xb5, 0xc2, 0xcb, 0xe2, 0x1e, 0x00, 0x86, 0xdb, 0xd0, 0xfd, 0xfd, 0x19, 0xe4, 0x3f, 0x02, 0x77, 0xf3, 0xbc, 0x95, 0xed, 0x55, 0xa3, 0x4a, 0xf9, 0x30, 0x91, 0x66, 0x02, 0x19, 0x3c, 0xfe, 0x04, 0x51, 0x4b, 0xd2, 0x6a, 0x05, 0x7e, 0x56, 0x2a, 0x11, 0x90, 0xc2, 0x7e, 0xaa, 0xb6, 0xc3, 0x22, 0xfc, 0xfa, 0xf4, 0xbb, 0xcc, 0x7f, 0x20, 0xc3, 0x77, 0x9c, 0x63, 0x8d, 0x7b, 0xbc, 0x07, 0x08, 0x6c, 0xf7, 0x5b, 0xf8, 0x39, 0x96, 0xdb, 0x44, 0x63 } +, + /* Signature */ + 192, + { 0x50, 0x90, 0x45, 0x12, 0x36, 0x10, 0x50, 0x87, 0x2e, 0xae, 0x80, 0x10, 0x26, 0x28, 0xb6, 0x3d, 0x02, 0x16, 0x8d, 0xca, 0x52, 0xf0, 0xab, 0xd8, 0x77, 0x20, 0xea, 0x48, 0x05, 0x0d, 0x2c, 0x62, 0x06, 0x1a, 0xa2, 0x15, 0x32, 0x68, 0xbe, 0xf8, 0xef, 0xb3, 0x4e, 0xed, 0x46, 0x17, 0x1a, 0x62, 0x88, 0xe5, 0x04, 0xd4, 0x20, 0xf6, 0xfc, 0x14, 0x51, 0x38, 0x61, 0x1e, 0x75, 0xed, 0x3c, 0xf7, 0x9b, 0x4d, 0x10, 0x26, 0x64, 0xd8, 0x64, 0x4f, 0xf3, 0xe9, 0xe5, 0xdb, 0xfd, 0x71, 0xcd, 0xc2, 0x7a, 0x21, 0x0e, 0xfb, 0x10, 0xbe, 0x90, 0x27, 0x56, 0x04, 0xf8, 0xd4, 0x49, 0x14, 0x8b, 0x3f, 0x86, 0x09, 0x90, 0x39, 0xc3, 0x3a, 0xef, 0x90, 0xbf, 0x19, 0x1b, 0x35, 0x18, 0xeb, 0x45, 0x9d, 0xa3, 0xba, 0x14, 0xfd, 0x0c, 0x72, 0x22, 0x9d, 0xea, 0x5f, 0xac, 0x2f, 0x7d, 0xad, 0xe1, 0x08, 0x5c, 0x8a, 0x23, 0x70, 0xbb, 0xfc, 0xfa, 0x2e, 0x3a, 0x9e, 0x63, 0xca, 0x22, 0x4f, 0x6d, 0xe8, 0xc8, 0xd2, 0x97, 0xa3, 0xb1, 0xf0, 0x6f, 0x1f, 0xc9, 0x49, 0x78, 0x90, 0xfd, 0x0e, 0x0e, 0x13, 0x88, 0x7f, 0xac, 0xb1, 0x52, 0xd1, 0x2d, 0x96, 0x39, 0x25, 0x28, 0xef, 0x28, 0xd0, 0x72, 0x43, 0x31, 0xff, 0x41, 0x40, 0x30, 0xc7, 0xa6, 0x38, 0x55, 0x81, 0x3c, 0xcd, 0x89, 0xfb, 0xdb, 0x1b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.5", + /* Message to be signed */ + 13, + { 0x26, 0x65, 0xcb, 0x5e, 0xe3, 0x6a, 0xa9, 0xbb, 0x1a, 0x5c, 0xde, 0x7c, 0xe8 } +, + /* Signature */ + 192, + { 0x4f, 0x38, 0xc2, 0xba, 0x84, 0xc5, 0x0d, 0x46, 0xdf, 0x53, 0x10, 0x91, 0xb6, 0x27, 0x12, 0x14, 0x9c, 0x1f, 0x42, 0xdb, 0xd7, 0x7e, 0x03, 0xd1, 0x85, 0xea, 0x96, 0xed, 0xa8, 0x02, 0x33, 0x7c, 0x22, 0xc1, 0x13, 0x0b, 0xc3, 0xbe, 0xce, 0xbf, 0x15, 0x39, 0xfd, 0x11, 0x89, 0x38, 0x51, 0xda, 0xe3, 0xcc, 0x15, 0x67, 0xcb, 0x6c, 0x73, 0xa7, 0x2f, 0xa1, 0xc9, 0x69, 0x48, 0x68, 0x21, 0x12, 0x7e, 0x7c, 0xfe, 0xa1, 0x36, 0x3e, 0xee, 0x95, 0x2b, 0x7c, 0x6e, 0xb5, 0x9e, 0x10, 0x2c, 0x66, 0x57, 0xc0, 0x80, 0x35, 0x27, 0x2c, 0xdf, 0x4a, 0xb5, 0xe5, 0x83, 0xed, 0x73, 0x7a, 0xd0, 0x28, 0xac, 0x1c, 0xfa, 0xfe, 0xdd, 0xc9, 0x07, 0x3d, 0xfb, 0xd7, 0xd3, 0xba, 0x3d, 0xa9, 0xe8, 0xdc, 0xd8, 0x46, 0xfa, 0x36, 0x5c, 0x9c, 0xcd, 0x8e, 0x9b, 0x39, 0x48, 0x3d, 0x37, 0x07, 0x3c, 0x1a, 0x7b, 0x78, 0x2e, 0xe7, 0x12, 0x1b, 0xb1, 0xa2, 0xad, 0x8b, 0xf5, 0xf8, 0xed, 0x6e, 0x65, 0x3e, 0x92, 0x4d, 0xeb, 0xad, 0x87, 0x1b, 0x74, 0x43, 0x39, 0xe5, 0xae, 0x7e, 0x96, 0xf6, 0x0d, 0xcc, 0x45, 0xea, 0x5d, 0x69, 0x7d, 0x3b, 0x1c, 0xc7, 0xc5, 0xe8, 0xda, 0x04, 0xe9, 0x2b, 0xe0, 0x6c, 0xad, 0x2e, 0x61, 0x4e, 0xac, 0x31, 0x8a, 0xec, 0xaf, 0x12, 0xd5, 0xa7, 0x62, 0x34, 0xc2, 0xc0 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.6", + /* Message to be signed */ + 125, + { 0x7b, 0x7b, 0x61, 0x61, 0x02, 0x0f, 0xaf, 0xb4, 0x88, 0x71, 0x63, 0x21, 0x34, 0x0d, 0xaf, 0x2c, 0x06, 0xac, 0x43, 0xce, 0x21, 0x32, 0x86, 0x86, 0x84, 0xaa, 0xaf, 0xab, 0x13, 0x99, 0x65, 0x3d, 0x35, 0x3b, 0x26, 0x93, 0xad, 0x73, 0xcb, 0x55, 0xb7, 0x1d, 0x66, 0xac, 0xd0, 0x1a, 0x16, 0x0c, 0xbf, 0x74, 0x37, 0x67, 0xbd, 0x96, 0xe7, 0xfd, 0x1c, 0x7a, 0x13, 0x32, 0x06, 0x65, 0xbb, 0xad, 0x1c, 0x4a, 0x0c, 0xed, 0x26, 0x59, 0x3c, 0xe8, 0x9c, 0xd8, 0x2f, 0x54, 0x6b, 0xd4, 0xd1, 0xb1, 0xbc, 0xd8, 0x2c, 0x65, 0xa4, 0x66, 0xf9, 0x9d, 0xa0, 0x12, 0xa4, 0x1e, 0x8c, 0x41, 0x20, 0x69, 0x81, 0x09, 0x58, 0x47, 0x5b, 0x4d, 0x9c, 0x2f, 0x80, 0xd8, 0x2d, 0x06, 0x41, 0x4c, 0x83, 0x25, 0xeb, 0x4f, 0x2c, 0x5a, 0x11, 0x66, 0xf1, 0xf1, 0xd2, 0xd1, 0x07, 0xd4, 0x8c } +, + /* Signature */ + 192, + { 0xd5, 0xcb, 0xb6, 0xc7, 0xef, 0xf4, 0xa6, 0x3a, 0xd8, 0x25, 0x0d, 0xe9, 0x4c, 0xc2, 0x9f, 0x7f, 0x31, 0xa0, 0xd7, 0x10, 0x6d, 0x5d, 0x77, 0x1b, 0x71, 0x5d, 0xf8, 0xa6, 0x75, 0xfd, 0x16, 0x34, 0xd6, 0xe8, 0xab, 0x58, 0x87, 0x5c, 0xc4, 0xc1, 0x51, 0x7b, 0x2f, 0xad, 0xf4, 0xe8, 0x5c, 0x1c, 0xb8, 0xb8, 0x53, 0x60, 0xe0, 0x68, 0x75, 0x87, 0xd1, 0x48, 0x08, 0x9f, 0x3f, 0x48, 0xb7, 0x9d, 0x98, 0xd2, 0x02, 0x7c, 0x50, 0x77, 0x0b, 0x33, 0x4f, 0x12, 0x52, 0xac, 0x0c, 0x3b, 0x2f, 0x03, 0x65, 0x34, 0xc3, 0xc2, 0x97, 0x22, 0xf6, 0x08, 0x7d, 0x06, 0xd7, 0x06, 0xce, 0xc7, 0xc4, 0xbd, 0xce, 0x1c, 0xd6, 0x4f, 0x7b, 0x4e, 0x07, 0x99, 0xa8, 0x7a, 0xa0, 0x73, 0xea, 0x83, 0x20, 0x29, 0x2b, 0x8e, 0xc8, 0x27, 0x17, 0x40, 0x6d, 0x36, 0xef, 0x91, 0x25, 0xe4, 0x1f, 0xb5, 0xd5, 0x3b, 0xcc, 0xdd, 0x62, 0x2d, 0x38, 0x8f, 0xcc, 0xee, 0x60, 0xa3, 0x85, 0xec, 0x20, 0x6a, 0x71, 0x5d, 0xc5, 0x4d, 0x78, 0x77, 0xbd, 0x72, 0x85, 0xd0, 0x84, 0x4c, 0x25, 0xd5, 0x93, 0x77, 0x97, 0x91, 0x27, 0x83, 0x96, 0xff, 0x9a, 0x8a, 0x91, 0x30, 0x6a, 0x54, 0xea, 0x76, 0x60, 0x7c, 0x81, 0x3f, 0x80, 0x1f, 0x38, 0x76, 0x0c, 0x3a, 0x81, 0x4b, 0x93, 0x96, 0x95, 0x9c, 0x29, 0xdb, 0xff, 0x9d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.7", + /* Message to be signed */ + 12, + { 0x2b, 0x0a, 0xd6, 0x13, 0x82, 0x28, 0x78, 0xa5, 0x72, 0xe1, 0x42, 0x80 } +, + /* Signature */ + 192, + { 0x89, 0xc8, 0x10, 0x84, 0xda, 0xa8, 0xf9, 0x14, 0xb7, 0xe2, 0x44, 0x55, 0x10, 0x74, 0x17, 0xca, 0x62, 0x1c, 0x91, 0x02, 0xd5, 0x01, 0xee, 0xb4, 0x3d, 0x17, 0x4c, 0x7b, 0xad, 0x38, 0x1d, 0xb1, 0x8d, 0x95, 0x33, 0xc3, 0x41, 0x1a, 0xec, 0x60, 0x57, 0xca, 0x5a, 0x4d, 0xfd, 0xc3, 0xf1, 0x31, 0xc8, 0x88, 0xb8, 0x8f, 0x01, 0x30, 0x03, 0xd6, 0x17, 0xe0, 0x6d, 0x64, 0x47, 0x95, 0x02, 0xae, 0x7e, 0x42, 0x4a, 0x5d, 0xd6, 0x37, 0xb0, 0x33, 0x56, 0x40, 0x4d, 0x26, 0x0f, 0x5e, 0xd6, 0xb8, 0xcb, 0x16, 0xd2, 0x57, 0x85, 0x28, 0xcc, 0x3e, 0x85, 0x00, 0x34, 0x6e, 0xb7, 0x90, 0xbd, 0xad, 0x41, 0xb2, 0xe3, 0x6c, 0xa6, 0xf1, 0x98, 0x85, 0xe3, 0xf6, 0xf5, 0x10, 0x86, 0xbf, 0xfb, 0x6a, 0xbb, 0x9c, 0x66, 0x33, 0x6b, 0x49, 0x47, 0x34, 0x64, 0xc5, 0xd7, 0xed, 0x8e, 0x9f, 0xf8, 0x5e, 0x11, 0xae, 0xff, 0x40, 0x90, 0x67, 0xba, 0xb0, 0xa0, 0x5c, 0x41, 0xe8, 0x15, 0x1b, 0x8b, 0xe9, 0x87, 0xf3, 0xf5, 0x95, 0x8e, 0x3e, 0x6f, 0x26, 0x51, 0x5d, 0x96, 0xbf, 0x23, 0x4b, 0x22, 0xab, 0x91, 0xc0, 0x85, 0x7b, 0x6c, 0x08, 0xa4, 0x6b, 0x03, 0x05, 0xfe, 0x04, 0x4c, 0xa9, 0xaa, 0xa0, 0xd7, 0x0a, 0x27, 0x58, 0xa1, 0xce, 0x43, 0x16, 0x64, 0xa8, 0xdd, 0x79, 0x40, 0x8c, 0x16, 0xba } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.8", + /* Message to be signed */ + 76, + { 0x36, 0x93, 0x8c, 0x8c, 0x7c, 0x6f, 0x7e, 0x35, 0x52, 0x34, 0xdb, 0x5a, 0x32, 0xa6, 0x48, 0x10, 0xdb, 0x50, 0x2b, 0x67, 0xc6, 0xf5, 0x92, 0x54, 0x4f, 0xfb, 0x27, 0xeb, 0x1f, 0x22, 0xe0, 0x6f, 0x2d, 0x63, 0x8b, 0x56, 0xd5, 0xd2, 0xf7, 0xd1, 0x9e, 0x9e, 0x27, 0x1f, 0x2c, 0xc9, 0x0c, 0xc0, 0xdd, 0x36, 0xd6, 0xcc, 0x2c, 0x06, 0x17, 0x8b, 0xcc, 0x70, 0x6a, 0xef, 0x20, 0xe5, 0x6a, 0x35, 0x8e, 0x52, 0x4f, 0x63, 0x16, 0x76, 0x9c, 0x54, 0xb6, 0xde, 0x2d, 0xd5 } +, + /* Signature */ + 192, + { 0xa0, 0x37, 0x53, 0xa5, 0xfb, 0x54, 0xaa, 0x51, 0xf6, 0xdd, 0x8d, 0xab, 0x91, 0xf1, 0x9c, 0xb8, 0x65, 0x56, 0x84, 0x85, 0xf8, 0x55, 0x8f, 0x0d, 0x10, 0x3f, 0x0d, 0x2b, 0x6d, 0x78, 0x53, 0x6e, 0x79, 0xc8, 0x15, 0xc4, 0xa0, 0x37, 0xbc, 0xaf, 0x11, 0xb6, 0x9d, 0x4c, 0xdb, 0xab, 0x03, 0x5a, 0xbe, 0x21, 0x6f, 0x71, 0x52, 0xf6, 0x30, 0xff, 0xc7, 0x9f, 0x84, 0x9d, 0x8d, 0xcd, 0x46, 0x3a, 0xae, 0x6a, 0xe9, 0x7d, 0x3d, 0xf1, 0x5a, 0x9e, 0x73, 0xd2, 0x3f, 0x18, 0x78, 0xfa, 0xc7, 0x54, 0xcb, 0xdd, 0x57, 0x1a, 0xfe, 0xa5, 0xd2, 0x53, 0x57, 0xd4, 0xb8, 0x83, 0x45, 0xf4, 0x89, 0xbe, 0x0d, 0x67, 0xb9, 0xbf, 0xad, 0xf0, 0x23, 0xf2, 0x6e, 0x67, 0x31, 0x5e, 0xd5, 0xfb, 0xf3, 0x91, 0x91, 0x0a, 0xf4, 0x96, 0x9b, 0x72, 0x4b, 0xf0, 0xca, 0x31, 0xc1, 0x05, 0x9f, 0x8a, 0x39, 0x13, 0xb4, 0x8a, 0x13, 0x81, 0x9c, 0x23, 0x6c, 0x9b, 0xe8, 0xe8, 0x24, 0xca, 0x4c, 0xb6, 0x19, 0xfb, 0x7d, 0x78, 0x4c, 0xd5, 0xf9, 0x52, 0x6b, 0x39, 0x7c, 0x76, 0xc5, 0xd0, 0xc6, 0x0c, 0xf7, 0xf4, 0x8d, 0x11, 0x19, 0x6e, 0x54, 0xf7, 0x2a, 0x08, 0xbb, 0x42, 0xf7, 0x5a, 0xef, 0xe3, 0x8f, 0x0b, 0x91, 0xb4, 0x2b, 0xb8, 0x06, 0xde, 0x4b, 0x87, 0xc9, 0x08, 0x2f, 0x72, 0x1a, 0x68, 0x80, 0xca } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.9", + /* Message to be signed */ + 95, + { 0x60, 0x83, 0x0c, 0x01, 0xcf, 0xa8, 0x6f, 0xf2, 0xdc, 0xac, 0x7a, 0xf9, 0x32, 0x1e, 0xe5, 0xfe, 0x50, 0x2e, 0x0e, 0x7a, 0x6f, 0xac, 0xb7, 0x3e, 0x3f, 0x6b, 0xc9, 0x02, 0x64, 0x0a, 0x61, 0x09, 0x5f, 0x64, 0x6f, 0xd0, 0x3e, 0x80, 0xd5, 0x81, 0x82, 0x46, 0x53, 0x31, 0xe7, 0x5d, 0x66, 0x11, 0xa0, 0x97, 0x76, 0x81, 0x62, 0x70, 0x86, 0x24, 0x17, 0x29, 0xde, 0x9f, 0x44, 0xab, 0x43, 0x94, 0x9d, 0xac, 0x19, 0x36, 0x73, 0xbd, 0x6c, 0xf8, 0x7f, 0x5d, 0x65, 0x77, 0x1e, 0xf8, 0x72, 0x81, 0x63, 0x3f, 0xdd, 0x07, 0xba, 0xc4, 0x09, 0xa6, 0xe2, 0x32, 0xb6, 0x01, 0xae, 0xce, 0x2d } +, + /* Signature */ + 192, + { 0x40, 0x58, 0xf6, 0xe0, 0x24, 0x0d, 0x85, 0x1d, 0x61, 0x93, 0x95, 0xa7, 0x52, 0x87, 0xa8, 0x8f, 0xaf, 0xd8, 0xdc, 0x56, 0x00, 0xb0, 0x69, 0xbf, 0x19, 0xdc, 0x3e, 0x19, 0x21, 0xe1, 0x17, 0xb4, 0x97, 0xb8, 0x2b, 0x3c, 0x52, 0x02, 0x69, 0xb1, 0xd1, 0x12, 0x81, 0x64, 0xfc, 0xd8, 0x8d, 0xd2, 0xb4, 0x6d, 0xc8, 0x5c, 0x42, 0xec, 0xf6, 0x7d, 0xeb, 0xad, 0x21, 0xa3, 0xb9, 0xa1, 0x55, 0x42, 0xfe, 0xa2, 0x26, 0x06, 0xea, 0xb5, 0x82, 0xfc, 0x32, 0x97, 0x11, 0xff, 0xc0, 0x7f, 0x4e, 0xef, 0x1f, 0x3b, 0xbf, 0xe0, 0x88, 0x8c, 0xbc, 0xa4, 0x85, 0xba, 0xfc, 0x11, 0x88, 0xb0, 0xaf, 0xe8, 0x09, 0xc9, 0xaa, 0xf8, 0xfa, 0x36, 0x66, 0xb9, 0xc9, 0x05, 0x85, 0x39, 0xdb, 0x1e, 0xc6, 0xa1, 0x8e, 0x5b, 0xe0, 0xb8, 0x01, 0x44, 0xd2, 0xc3, 0x7c, 0xa6, 0x14, 0xc0, 0x90, 0xb4, 0xa7, 0xf1, 0x34, 0x58, 0xe0, 0xd3, 0xa4, 0xcb, 0x0c, 0xb7, 0x3d, 0xcc, 0x4d, 0x90, 0x80, 0x6f, 0x61, 0x08, 0x58, 0x89, 0xeb, 0x5c, 0x9b, 0x14, 0x09, 0xde, 0xf3, 0x60, 0xfd, 0x1c, 0x2e, 0x49, 0x43, 0x8d, 0x7c, 0x67, 0xd7, 0x9d, 0xbd, 0x9a, 0x59, 0x2a, 0xb5, 0x04, 0xc4, 0x71, 0x5f, 0x65, 0xb2, 0x9d, 0x84, 0x65, 0x09, 0x95, 0x15, 0x69, 0xa8, 0xc3, 0x79, 0x09, 0xf5, 0xd5, 0x50, 0xee, 0xff, 0xfa } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.10", + /* Message to be signed */ + 153, + { 0x63, 0x5d, 0x22, 0x03, 0xed, 0x9d, 0x5b, 0x91, 0x20, 0xe3, 0x1b, 0xf6, 0x9d, 0x30, 0x5b, 0xe6, 0x06, 0x86, 0x97, 0xe3, 0x5c, 0xe5, 0x9c, 0x55, 0x3e, 0x50, 0x8d, 0xc7, 0x7b, 0x07, 0x3f, 0xfa, 0x3a, 0xaa, 0x59, 0xf9, 0x96, 0xc3, 0x0b, 0x2e, 0x68, 0x63, 0x23, 0x81, 0x9f, 0xde, 0x22, 0xbe, 0x6c, 0x8d, 0x53, 0x86, 0x84, 0x14, 0xb3, 0x54, 0x5a, 0xbf, 0x43, 0x57, 0x68, 0xa6, 0x11, 0xf0, 0xc1, 0xa4, 0x79, 0xa0, 0xc7, 0x66, 0x0d, 0x53, 0x5e, 0x80, 0x5b, 0x5f, 0xed, 0xc3, 0x77, 0x9c, 0xf0, 0xc5, 0x2c, 0x3c, 0xd0, 0x40, 0xab, 0x65, 0x14, 0xc7, 0xf8, 0x13, 0x3d, 0x47, 0xb0, 0xac, 0xc6, 0x91, 0x4e, 0x6d, 0x4a, 0xd3, 0xc4, 0x73, 0x7c, 0xf5, 0x12, 0x91, 0x09, 0x4e, 0x85, 0x94, 0x33, 0xba, 0x30, 0x66, 0xe1, 0x9d, 0x6a, 0xa2, 0xda, 0x89, 0x6d, 0xc9, 0xd9, 0x5e, 0xf9, 0xe5, 0x63, 0x6d, 0xab, 0x35, 0xf7, 0x29, 0x87, 0x05, 0xc6, 0xd8, 0x76, 0x17, 0x54, 0x12, 0xf8, 0x84, 0x25, 0x19, 0xff, 0xe1, 0x6c, 0xf7, 0x43, 0x62, 0xab } +, + /* Signature */ + 192, + { 0x94, 0x61, 0xa1, 0xa8, 0x41, 0x42, 0x3e, 0xd5, 0xcf, 0xc6, 0x08, 0x9a, 0x74, 0xdb, 0xfc, 0x53, 0x73, 0x11, 0x03, 0xbf, 0x49, 0x85, 0xdd, 0xb1, 0x50, 0xb0, 0xe9, 0x38, 0x0d, 0x3f, 0xe0, 0xcf, 0x6d, 0x45, 0x7c, 0x5c, 0x68, 0xa7, 0xf2, 0x55, 0x04, 0x02, 0x2d, 0x69, 0x5f, 0xf8, 0x42, 0x11, 0x8e, 0xbf, 0x61, 0x02, 0x2f, 0xea, 0x47, 0xfa, 0x45, 0xf7, 0xc1, 0xcc, 0x72, 0x6e, 0x1d, 0xe5, 0x0b, 0xd0, 0x64, 0xb3, 0xbb, 0x70, 0x16, 0x57, 0x16, 0x2b, 0x88, 0xc0, 0xb9, 0x10, 0xfe, 0xb7, 0x2f, 0x48, 0x7a, 0x5c, 0x7f, 0x4b, 0x9e, 0xcf, 0xee, 0x24, 0xe0, 0x7a, 0xa2, 0xd1, 0x98, 0xd1, 0x13, 0xcb, 0x84, 0x5d, 0x81, 0x7b, 0xb5, 0x9b, 0xb1, 0xda, 0x24, 0xa8, 0x2b, 0x91, 0xc2, 0xfe, 0x3f, 0xba, 0x89, 0x51, 0x83, 0xcb, 0xd9, 0xc0, 0xfe, 0x0a, 0xc0, 0xbe, 0x64, 0xfe, 0xf2, 0xe0, 0x13, 0x92, 0x05, 0xb1, 0x0b, 0xca, 0xbf, 0xe5, 0xa3, 0xa7, 0xa8, 0x90, 0xfc, 0x0f, 0xe7, 0x8d, 0xab, 0xe1, 0xad, 0xb5, 0xbd, 0x11, 0x44, 0x85, 0x03, 0xcb, 0x0d, 0xcd, 0x0b, 0x68, 0xf1, 0x60, 0x19, 0x6e, 0x96, 0x13, 0xe2, 0x9f, 0xbe, 0x9a, 0x3f, 0x94, 0x06, 0xec, 0x20, 0xc0, 0x30, 0xe8, 0x1e, 0xc3, 0x09, 0x65, 0xea, 0x01, 0x9c, 0x17, 0xaa, 0x97, 0x11, 0x01, 0xc2, 0xe5, 0x30, 0x59 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.11", + /* Message to be signed */ + 182, + { 0x87, 0xfb, 0xa9, 0x89, 0xf3, 0xcc, 0x15, 0xaf, 0x7e, 0xe7, 0x61, 0xc0, 0x88, 0x26, 0x4a, 0xb7, 0x71, 0x52, 0x39, 0xe0, 0xb8, 0xc8, 0xa9, 0xe4, 0x8e, 0x11, 0xdb, 0x68, 0x03, 0x31, 0x39, 0xc2, 0xa2, 0x89, 0xea, 0x42, 0x6e, 0xbe, 0x26, 0x9f, 0x5f, 0xb7, 0x07, 0x09, 0x0a, 0xfb, 0x89, 0x1a, 0x49, 0xca, 0x05, 0xc0, 0x55, 0x0d, 0x72, 0x9b, 0xf4, 0xd3, 0x7c, 0x8f, 0x1d, 0xa7, 0xa3, 0xca, 0x2f, 0x43, 0x87, 0xa4, 0x0b, 0x5f, 0x79, 0x13, 0xa3, 0x85, 0xf5, 0x5b, 0x81, 0x41, 0xaf, 0x36, 0xbe, 0x8f, 0x57, 0x16, 0x65, 0xf8, 0x57, 0xe7, 0x7a, 0x5c, 0x9c, 0xcc, 0xe6, 0xba, 0x8f, 0x2b, 0xe4, 0x63, 0x23, 0xcc, 0x56, 0x91, 0x56, 0x6f, 0xf4, 0xb6, 0xd7, 0x85, 0x43, 0x04, 0xb9, 0x3b, 0xba, 0x1a, 0x17, 0x59, 0xdf, 0xb1, 0x44, 0xc9, 0x54, 0x7c, 0xf2, 0xbc, 0x8e, 0xaa, 0xed, 0xaa, 0x4f, 0x1d, 0xd2, 0x52, 0x82, 0x3b, 0x72, 0x87, 0xca, 0x55, 0x5d, 0x21, 0x06, 0x08, 0x9a, 0x24, 0x3e, 0x5d, 0xfe, 0x8f, 0xc3, 0x1d, 0x3f, 0x46, 0x22, 0x2a, 0x68, 0xab, 0xaf, 0x31, 0x81, 0x5a, 0x94, 0x7e, 0x58, 0x57, 0xcf, 0x6a, 0x33, 0x17, 0x0e, 0xcc, 0xb6, 0xa5, 0xe0, 0x6d, 0x23, 0xcc, 0x9d, 0x48, 0xea, 0xf6, 0xcd, 0xbc } +, + /* Signature */ + 192, + { 0x0b, 0x5f, 0x1c, 0xfc, 0x25, 0x3b, 0xaa, 0xd4, 0xb9, 0x83, 0xf8, 0xfe, 0x05, 0x0d, 0x4a, 0x01, 0x7c, 0xc4, 0x66, 0x98, 0x0e, 0xbd, 0x23, 0xc9, 0xd5, 0x53, 0x43, 0xf5, 0x10, 0x7e, 0x04, 0x1e, 0xb6, 0x54, 0x78, 0x10, 0xfd, 0xba, 0x46, 0x86, 0xe6, 0x10, 0x83, 0x2f, 0x92, 0x82, 0xed, 0xf0, 0x66, 0x04, 0xb0, 0xab, 0xfe, 0xea, 0x38, 0x01, 0x32, 0x79, 0x17, 0x79, 0x40, 0x99, 0x7b, 0x28, 0x90, 0x2b, 0x14, 0xdb, 0x37, 0x9e, 0xeb, 0x4f, 0x44, 0x00, 0x5d, 0xfc, 0xb0, 0x03, 0x68, 0x03, 0xc9, 0xf1, 0x25, 0xbc, 0xe1, 0xf2, 0xa8, 0x2c, 0x4d, 0x30, 0x07, 0xae, 0x96, 0xb8, 0x48, 0xb8, 0x13, 0xec, 0x8c, 0x97, 0xca, 0x3f, 0x71, 0x0a, 0x9a, 0xe0, 0xdb, 0xc2, 0x8a, 0x55, 0xe0, 0x58, 0x81, 0xb8, 0x58, 0xdb, 0x55, 0x71, 0x20, 0xf3, 0x3c, 0x59, 0xcd, 0x43, 0x60, 0xf9, 0x20, 0x8c, 0x74, 0xb2, 0x7e, 0xc6, 0x5d, 0x11, 0xea, 0x41, 0xfa, 0x6a, 0x9e, 0xac, 0xf2, 0xa6, 0x11, 0x68, 0xad, 0x07, 0xc2, 0x09, 0x94, 0x8f, 0x35, 0xa1, 0x61, 0xf4, 0x1f, 0x87, 0x54, 0x0e, 0xa1, 0x82, 0x84, 0xaa, 0xb8, 0xd8, 0xf9, 0x78, 0x61, 0x31, 0xf0, 0x43, 0x90, 0x2b, 0x89, 0xc1, 0x7a, 0x56, 0x0d, 0x90, 0x94, 0x64, 0x47, 0x5a, 0x0d, 0xfc, 0xe5, 0x89, 0x09, 0x18, 0x7c, 0xd6, 0xe4, 0x46 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.12", + /* Message to be signed */ + 100, + { 0x4b, 0x5e, 0x80, 0x30, 0x5c, 0xbe, 0xa9, 0x0d, 0x63, 0x7f, 0xdb, 0x23, 0x47, 0xc6, 0xfe, 0xb6, 0x78, 0x42, 0xeb, 0xac, 0x6f, 0x90, 0x3d, 0xb5, 0xa7, 0x1e, 0xba, 0xab, 0x8a, 0x1c, 0x2d, 0xf1, 0x12, 0x60, 0xa1, 0xec, 0x90, 0x7b, 0x8b, 0x63, 0x4d, 0x37, 0xd3, 0x6e, 0xd8, 0xde, 0x7d, 0x0d, 0xa1, 0x03, 0xbc, 0x4a, 0x9e, 0x93, 0x3f, 0xb7, 0xbf, 0xee, 0x59, 0x1c, 0xc9, 0x33, 0x29, 0x9f, 0xee, 0x46, 0x0f, 0x35, 0x42, 0xc9, 0x78, 0xf3, 0x07, 0xae, 0x05, 0x24, 0x64, 0xf3, 0x06, 0x20, 0xce, 0xbf, 0x3c, 0x9a, 0x9c, 0xb6, 0xa9, 0x01, 0x53, 0x0c, 0x1d, 0x56, 0x13, 0xdf, 0x07, 0x74, 0x31, 0x2d, 0x4b, 0x5f } +, + /* Signature */ + 192, + { 0xb6, 0xf0, 0x3d, 0x35, 0x33, 0x50, 0x07, 0xa7, 0x47, 0xae, 0x68, 0x67, 0x60, 0xf9, 0xed, 0xad, 0x08, 0x89, 0xd2, 0xd4, 0xca, 0x0c, 0xb8, 0x8b, 0x67, 0x43, 0x12, 0xd3, 0x2c, 0x55, 0x2b, 0x7a, 0x66, 0xc5, 0xa9, 0x52, 0x8c, 0x01, 0x4b, 0x58, 0xc8, 0x49, 0xf2, 0x31, 0xa2, 0xe0, 0x45, 0x68, 0x2e, 0x3b, 0xbb, 0x14, 0xc7, 0xf9, 0x5f, 0xf8, 0xbd, 0xb6, 0x58, 0x7f, 0x25, 0x11, 0xcc, 0x6b, 0xf9, 0x24, 0x39, 0x60, 0x08, 0x11, 0x03, 0xd4, 0x7e, 0x77, 0x69, 0xa1, 0x77, 0xeb, 0xdb, 0x91, 0xf1, 0x28, 0x73, 0xde, 0xcd, 0x5d, 0xc0, 0x67, 0xe4, 0x5c, 0x2b, 0x2a, 0x04, 0x4f, 0xfa, 0x3f, 0xbb, 0x04, 0xc2, 0x0a, 0x3d, 0xc2, 0x01, 0x38, 0x40, 0x3f, 0xf2, 0x5c, 0xa0, 0xeb, 0xad, 0x96, 0xe4, 0x85, 0x9f, 0xa4, 0xa0, 0xd7, 0x32, 0x85, 0x2a, 0xf3, 0x50, 0xa2, 0x75, 0x69, 0x9a, 0x94, 0xaa, 0x6e, 0x47, 0xf2, 0x17, 0xe3, 0x83, 0xef, 0x8f, 0xce, 0x8e, 0xb6, 0xee, 0xd7, 0x82, 0x6d, 0x7c, 0x61, 0x58, 0xfc, 0x58, 0x82, 0xe4, 0x61, 0x35, 0x45, 0xfa, 0x26, 0xee, 0xe0, 0xc9, 0xf9, 0x3d, 0xe7, 0xa1, 0x65, 0x08, 0xea, 0x16, 0x19, 0x70, 0x46, 0x0d, 0x6a, 0x7c, 0xa7, 0x70, 0xf8, 0xde, 0x8b, 0xa9, 0x3c, 0xea, 0xf3, 0x97, 0xdd, 0xf1, 0xfb, 0xce, 0xe2, 0x82, 0xa1, 0x53, 0x7d } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.13", + /* Message to be signed */ + 86, + { 0xe5, 0xad, 0x62, 0x7f, 0x24, 0xf4, 0x11, 0x7a, 0x0a, 0x6b, 0xe4, 0xa5, 0x5f, 0xdb, 0x88, 0x3d, 0x75, 0xa6, 0x73, 0x12, 0x15, 0x4a, 0x71, 0x89, 0x23, 0xd0, 0xe8, 0xf5, 0x73, 0x0a, 0x54, 0xd8, 0xca, 0x7c, 0x97, 0x4e, 0x4d, 0x59, 0x33, 0x8b, 0xb5, 0x71, 0x30, 0x5c, 0xce, 0x99, 0x0c, 0xbb, 0xcf, 0xa9, 0x1e, 0xa9, 0xb7, 0x73, 0xb8, 0x3d, 0x7a, 0x1f, 0x0f, 0xfe, 0xc4, 0xc6, 0xb1, 0x43, 0xfe, 0x05, 0x05, 0x8b, 0xc9, 0x0c, 0xe1, 0x46, 0xf3, 0x69, 0xcb, 0xae, 0x3b, 0x3d, 0x99, 0x70, 0x5e, 0xf4, 0x3d, 0x07, 0x21, 0xb8 } +, + /* Signature */ + 192, + { 0x73, 0x29, 0x86, 0xd4, 0xed, 0xdb, 0x8a, 0x7e, 0x9b, 0x65, 0xdc, 0x01, 0x6d, 0xd5, 0x71, 0xef, 0xab, 0xeb, 0x84, 0x49, 0x0e, 0x88, 0xe3, 0xe7, 0x3b, 0x63, 0xe8, 0x0d, 0x1c, 0xc8, 0x6a, 0x45, 0x2d, 0xec, 0x29, 0xfc, 0x81, 0x7e, 0x8a, 0xd4, 0xee, 0xbd, 0xdc, 0xd9, 0x7c, 0x74, 0x5b, 0xc4, 0x79, 0x7e, 0x54, 0xfe, 0xc6, 0xac, 0xe2, 0x91, 0xb1, 0x96, 0xdc, 0x24, 0x65, 0xf0, 0x8c, 0xf1, 0xdd, 0xd2, 0x17, 0xe7, 0x7a, 0xaf, 0x7d, 0x50, 0x98, 0x77, 0x91, 0xde, 0x81, 0xb0, 0x41, 0x10, 0xd1, 0x1a, 0xb8, 0x55, 0x89, 0x06, 0x60, 0x4e, 0xb9, 0xd9, 0x2b, 0x35, 0xf9, 0x00, 0x75, 0xaf, 0x42, 0x28, 0x01, 0x45, 0xb0, 0x88, 0xe8, 0x75, 0x3d, 0x0d, 0xb7, 0x3c, 0xd3, 0xa3, 0x2b, 0xd1, 0x9c, 0xea, 0x35, 0x38, 0xee, 0x4f, 0x09, 0x27, 0x3e, 0xf6, 0x6d, 0x07, 0x05, 0xd4, 0x5e, 0xe7, 0x10, 0x9f, 0xe5, 0x95, 0xdf, 0x55, 0x76, 0x7b, 0x3d, 0x10, 0x81, 0x72, 0x27, 0xbb, 0x6b, 0xa3, 0x95, 0x75, 0xb8, 0x5d, 0x6a, 0x35, 0xa2, 0xff, 0xb8, 0x8c, 0xb2, 0x67, 0xdb, 0xfc, 0x28, 0x2b, 0xb8, 0xa3, 0xde, 0xe0, 0x2e, 0xc7, 0x7b, 0x0c, 0xb8, 0x13, 0x55, 0x70, 0xf8, 0xa7, 0xd7, 0xad, 0x04, 0x34, 0x1a, 0x08, 0x64, 0xe6, 0x7f, 0xf6, 0xfa, 0x02, 0x59, 0xa1, 0x69, 0x74, 0xc8, 0x6a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.14", + /* Message to be signed */ + 75, + { 0x03, 0xe3, 0x9b, 0xa7, 0xa8, 0x0c, 0x77, 0x14, 0x16, 0xd8, 0x52, 0x63, 0xe4, 0xd4, 0x3c, 0x63, 0x93, 0xdf, 0xe7, 0x96, 0x52, 0x3b, 0x89, 0xe0, 0xa4, 0x61, 0x62, 0x88, 0x80, 0x80, 0x0d, 0x8f, 0xc2, 0x43, 0x1b, 0x66, 0x30, 0x54, 0x09, 0xe0, 0x6c, 0x95, 0xae, 0x7a, 0x17, 0xd5, 0x34, 0xb1, 0xe8, 0x4c, 0x19, 0x9d, 0xfe, 0x73, 0x1d, 0xa9, 0x49, 0xf1, 0x64, 0x57, 0x1d, 0xec, 0xc8, 0xb1, 0x66, 0xbe, 0xb8, 0xdc, 0x08, 0x7c, 0xb4, 0x86, 0x99, 0x98, 0xc2 } +, + /* Signature */ + 192, + { 0x60, 0x76, 0x3b, 0xea, 0xf7, 0xc3, 0xe2, 0x2b, 0x3b, 0x22, 0xdc, 0x44, 0xd9, 0x47, 0x82, 0x6e, 0x23, 0xfc, 0xf9, 0x6b, 0x01, 0xb7, 0x74, 0x1b, 0x24, 0xb1, 0xb9, 0xd9, 0x3c, 0x07, 0xf0, 0xc6, 0x4d, 0x39, 0x67, 0x98, 0xbb, 0x58, 0x9b, 0xd4, 0x25, 0x29, 0x53, 0x69, 0xbf, 0xb8, 0x79, 0xad, 0xd3, 0x42, 0xcd, 0x76, 0x28, 0x0b, 0x57, 0xe6, 0x35, 0x4f, 0x61, 0x95, 0xe8, 0x42, 0xfa, 0x2a, 0x95, 0xf1, 0xc4, 0x6f, 0x0b, 0x70, 0x78, 0x6c, 0x31, 0x8d, 0xe9, 0xa5, 0x5a, 0x8a, 0xc4, 0x54, 0x5e, 0xe7, 0xcf, 0xf3, 0x99, 0xc6, 0x78, 0xe5, 0x78, 0xf8, 0x93, 0x9e, 0xd4, 0x9e, 0x84, 0xbb, 0xa9, 0xaa, 0xe5, 0x7c, 0x1a, 0x36, 0xfc, 0xc3, 0x94, 0x86, 0x46, 0x6e, 0x40, 0x12, 0xf9, 0x58, 0x87, 0xa6, 0x81, 0x10, 0xf1, 0xa4, 0x84, 0x67, 0xe4, 0xc2, 0x34, 0xf5, 0x81, 0xc5, 0xec, 0x47, 0x71, 0x06, 0xcc, 0xb3, 0xec, 0x86, 0x17, 0xb4, 0xbe, 0x21, 0x93, 0x37, 0x44, 0x8f, 0xe7, 0x2e, 0x25, 0xde, 0xab, 0x53, 0xea, 0xcb, 0x92, 0xe5, 0x96, 0x62, 0x95, 0xb3, 0xa5, 0x57, 0x12, 0x19, 0x58, 0xdf, 0xe7, 0x9c, 0xa4, 0x72, 0xf7, 0x9e, 0xfb, 0xda, 0x1d, 0xcf, 0xba, 0x9d, 0xbd, 0x0f, 0x97, 0x67, 0x32, 0xc0, 0x93, 0xb9, 0x8f, 0xf1, 0x93, 0xc9, 0x02, 0x98, 0x7a, 0x42, 0x6c, 0x0f } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.15", + /* Message to be signed */ + 243, + { 0xd4, 0xc2, 0x35, 0x96, 0x7d, 0x4e, 0x87, 0xb6, 0x71, 0x1e, 0x32, 0xac, 0x70, 0x37, 0xa3, 0x97, 0xf9, 0x9b, 0x1c, 0xad, 0x95, 0xa1, 0x88, 0x94, 0x6a, 0x48, 0x64, 0x0e, 0xb6, 0xb7, 0xb0, 0x03, 0xc3, 0x2f, 0x85, 0xa1, 0x21, 0xb0, 0x9c, 0xa4, 0xc8, 0xbe, 0xc0, 0xb8, 0x27, 0x44, 0xaa, 0xf2, 0x7d, 0x16, 0x6c, 0xef, 0xc7, 0xa9, 0x70, 0x2a, 0xd3, 0x1d, 0xbd, 0x15, 0xea, 0x2a, 0x18, 0x5f, 0x5b, 0x9b, 0xa6, 0x42, 0xf9, 0x49, 0x07, 0x8b, 0xc6, 0x09, 0xb9, 0xa8, 0xa3, 0x36, 0x92, 0xd7, 0x18, 0x49, 0x39, 0xd1, 0xf9, 0xeb, 0x42, 0x6a, 0x6d, 0xb7, 0x40, 0xea, 0xd9, 0x4c, 0xfe, 0xa1, 0x7f, 0xeb, 0x06, 0x18, 0xd7, 0x4d, 0x9a, 0x65, 0x16, 0x88, 0xe9, 0x0b, 0x9b, 0xb7, 0x05, 0x24, 0x30, 0x5d, 0x61, 0x8c, 0x88, 0xa5, 0x5f, 0x45, 0x44, 0x50, 0xe0, 0xc5, 0x85, 0xd3, 0xa8, 0xd9, 0x81, 0x65, 0x81, 0x8f, 0x36, 0x3b, 0x20, 0xa2, 0x52, 0x49, 0x2e, 0x15, 0x12, 0x58, 0x58, 0x90, 0xa8, 0xc3, 0x20, 0xa7, 0x18, 0x71, 0x58, 0xce, 0x0d, 0x4e, 0x4b, 0xe1, 0xc7, 0x01, 0xf8, 0xaf, 0xdc, 0x54, 0x5c, 0x4d, 0xab, 0x86, 0x8d, 0x41, 0xd4, 0x1c, 0x21, 0xc2, 0xcb, 0x1f, 0x67, 0xdf, 0x79, 0x53, 0xd5, 0xf7, 0x26, 0x1c, 0x50, 0x92, 0xbb, 0xc4, 0x33, 0x2a, 0xc5, 0x57, 0x5b, 0x6e, 0x0e, 0x03, 0x14, 0x9c, 0x04, 0x0c, 0x3e, 0x20, 0x1c, 0x79, 0x15, 0xac, 0x20, 0x22, 0x88, 0x4e, 0xa0, 0xe6, 0xc2, 0x14, 0x03, 0xf0, 0xb4, 0x4e, 0x0f, 0x71, 0x34, 0x3f, 0xc9, 0x11, 0x1a, 0x7d, 0xb2, 0xf5, 0xe9, 0xe5, 0x09, 0xc2, 0xd8, 0x97, 0x84, 0xef, 0xb2, 0x2c, 0x31, 0xe8, 0x16, 0x5e, 0x0e, 0x93, 0x6c } +, + /* Signature */ + 192, + { 0x46, 0x9f, 0x08, 0xbd, 0xd0, 0x3b, 0x75, 0x64, 0x0e, 0x8a, 0x44, 0xa0, 0x7c, 0xa8, 0xde, 0x4b, 0xac, 0xf8, 0x33, 0x1f, 0xe3, 0x9c, 0x44, 0xd2, 0x3a, 0xa7, 0xb5, 0x81, 0xdc, 0x3f, 0x00, 0xf5, 0x42, 0x1b, 0x5c, 0x17, 0x2d, 0x0f, 0xfc, 0xe9, 0x14, 0x97, 0xd3, 0xd4, 0xb1, 0x04, 0xf5, 0x6a, 0x98, 0xec, 0x94, 0xf7, 0x19, 0x27, 0x1e, 0x58, 0xb4, 0x3e, 0xfb, 0xd8, 0x76, 0xe1, 0xc1, 0x31, 0xfa, 0x97, 0x82, 0x07, 0x28, 0xa5, 0x56, 0x75, 0x55, 0x21, 0x4c, 0xd9, 0x4a, 0x18, 0xfc, 0xce, 0x5c, 0x2f, 0x53, 0xb1, 0x9d, 0x1f, 0x3c, 0x73, 0xd0, 0x9f, 0x7b, 0xe1, 0x80, 0x97, 0x38, 0xb0, 0x3c, 0xe7, 0x69, 0xe4, 0x54, 0xed, 0x4c, 0xbe, 0xdc, 0xaf, 0x43, 0xc4, 0x8b, 0xd3, 0x9d, 0xf2, 0xf8, 0xbb, 0x63, 0xb8, 0xfc, 0x4d, 0x0d, 0x4d, 0x5b, 0x20, 0x4f, 0xc2, 0x20, 0x01, 0x3a, 0x66, 0x8c, 0x19, 0xf9, 0x75, 0x02, 0x93, 0xa4, 0x71, 0x15, 0x83, 0x88, 0x26, 0x45, 0xdb, 0xf3, 0xac, 0x4f, 0x83, 0x9b, 0x6f, 0xd1, 0xcf, 0x3b, 0x5e, 0xe8, 0xd7, 0x34, 0xe1, 0xda, 0x37, 0x4d, 0x91, 0xd8, 0x9e, 0xa3, 0x18, 0xe9, 0x18, 0x34, 0x83, 0xf4, 0xa0, 0x9a, 0x93, 0x51, 0x4a, 0xf5, 0x4f, 0x75, 0xd0, 0xa3, 0x56, 0x51, 0xb2, 0x40, 0xf7, 0x9f, 0x20, 0xa2, 0x97, 0x7d, 0x14, 0x57, 0x8c } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.16", + /* Message to be signed */ + 119, + { 0xd0, 0x6a, 0xdc, 0xa4, 0xc2, 0x0f, 0x0d, 0x9f, 0x7b, 0xe6, 0x5a, 0x20, 0x32, 0x7c, 0x29, 0x47, 0x56, 0xe3, 0xed, 0xd9, 0xe1, 0xd3, 0x9d, 0x0f, 0x95, 0xc7, 0x9d, 0xf1, 0xba, 0xc3, 0x34, 0x35, 0x9f, 0xab, 0x94, 0x3d, 0x85, 0x45, 0xa3, 0xba, 0xa3, 0x7a, 0x59, 0x29, 0x5c, 0x58, 0xb2, 0x37, 0x75, 0x2b, 0x8d, 0xe7, 0xd4, 0x32, 0x3c, 0x56, 0xe9, 0xd7, 0xcb, 0x0c, 0x7f, 0x83, 0x1d, 0x54, 0x9c, 0xb3, 0x87, 0x19, 0xa0, 0x81, 0xd5, 0x8b, 0x60, 0x57, 0xec, 0xb7, 0x42, 0x9e, 0x2c, 0xa6, 0x07, 0xcd, 0x13, 0x06, 0x35, 0x59, 0x43, 0x15, 0x9d, 0xc9, 0x24, 0xad, 0x3e, 0x9c, 0xb1, 0x3d, 0x0e, 0x71, 0xea, 0xdc, 0xb0, 0x05, 0xe1, 0x84, 0xc0, 0xc2, 0xce, 0xaa, 0xf9, 0xd7, 0x4a, 0x1c, 0x1d, 0xf6, 0xfe, 0xc1, 0x8c, 0x97, 0xa0 } +, + /* Signature */ + 192, + { 0x9f, 0xd9, 0x52, 0x5c, 0x15, 0xc8, 0x43, 0xb8, 0x06, 0x9c, 0x15, 0xf2, 0x6d, 0x3f, 0x95, 0x24, 0x6a, 0xf3, 0x7a, 0x8b, 0x8e, 0x6b, 0x93, 0x9d, 0xdf, 0x5b, 0x38, 0x28, 0xcd, 0xb6, 0x2c, 0xfa, 0x37, 0x3a, 0x92, 0xec, 0xc4, 0x13, 0x84, 0xa8, 0x77, 0xca, 0xa0, 0x90, 0xaa, 0x13, 0xc8, 0x47, 0xef, 0x28, 0x29, 0xdd, 0xca, 0x14, 0x14, 0x20, 0x14, 0x02, 0x14, 0x81, 0x55, 0x05, 0x50, 0xda, 0xa2, 0x9d, 0xe2, 0xab, 0x70, 0x01, 0xb8, 0x55, 0xc9, 0x34, 0x2f, 0x0c, 0x90, 0xbf, 0xa6, 0xc3, 0x34, 0x9b, 0x2c, 0x39, 0x62, 0x13, 0xef, 0x70, 0xcb, 0xd8, 0x4b, 0xb4, 0xce, 0x6e, 0xf5, 0x8b, 0x17, 0x6e, 0x9f, 0x6f, 0xcc, 0xdb, 0x6e, 0x46, 0xca, 0xc3, 0x41, 0x14, 0xa1, 0xb9, 0xf9, 0x8a, 0x8a, 0x32, 0x75, 0x7b, 0xf7, 0x5d, 0x6b, 0xfc, 0x45, 0x5a, 0xde, 0x6a, 0x01, 0xf9, 0x60, 0x50, 0x1b, 0x79, 0xf5, 0xfb, 0xe3, 0xb3, 0x8f, 0xca, 0x03, 0x46, 0x4e, 0x43, 0xd4, 0x96, 0x63, 0xc7, 0x9f, 0xf6, 0x4d, 0x32, 0x98, 0x1e, 0x44, 0x80, 0xcd, 0xf4, 0x2d, 0x8a, 0xf8, 0xda, 0xa7, 0xf1, 0x2b, 0x81, 0xa5, 0xaa, 0x96, 0x5f, 0xad, 0xaa, 0x3c, 0x03, 0xb7, 0xff, 0x22, 0xd3, 0xcf, 0xdf, 0xfe, 0x3c, 0xad, 0xf4, 0xd5, 0x98, 0x9e, 0xd1, 0x4c, 0x96, 0x9a, 0x6e, 0x8c, 0x9a, 0x1e, 0x04 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.17", + /* Message to be signed */ + 209, + { 0x3a, 0x63, 0x02, 0xd7, 0x9e, 0x26, 0xb5, 0x55, 0xc7, 0x7d, 0xe9, 0x2a, 0x91, 0xe0, 0x78, 0x57, 0x1e, 0xd1, 0x57, 0x2f, 0xfc, 0x3e, 0x4f, 0xc9, 0x05, 0xce, 0x53, 0xf1, 0x04, 0xb3, 0x22, 0x00, 0x95, 0x7e, 0xb2, 0xb5, 0xe5, 0xf3, 0xe3, 0xfc, 0xbb, 0xc1, 0x62, 0xf9, 0xe5, 0x25, 0xc7, 0x06, 0xf1, 0xdd, 0x04, 0xfc, 0xab, 0x51, 0x6b, 0xc1, 0x8a, 0x8e, 0x4f, 0x88, 0xa9, 0x38, 0xa5, 0xb2, 0x56, 0x85, 0xd7, 0x8d, 0xdc, 0x9f, 0x10, 0x4e, 0x49, 0xbf, 0x5c, 0xa0, 0xb6, 0x5a, 0x4b, 0x96, 0x57, 0xe0, 0x4a, 0x71, 0xfb, 0x50, 0xeb, 0x4a, 0xac, 0x22, 0xc0, 0xbb, 0x93, 0xf6, 0x0c, 0xac, 0x94, 0x83, 0xf1, 0x77, 0x13, 0x55, 0x3d, 0xca, 0x4b, 0x31, 0xe2, 0x72, 0x7b, 0x32, 0xe3, 0x50, 0xfe, 0x20, 0x4c, 0xec, 0xd9, 0xa7, 0xcd, 0xa4, 0xda, 0xda, 0x2e, 0x87, 0xff, 0x6f, 0x2b, 0x73, 0xe7, 0xb0, 0x78, 0x1e, 0x21, 0x2f, 0x34, 0xfe, 0x36, 0x36, 0x10, 0xf0, 0x18, 0xa7, 0x99, 0x37, 0x37, 0x55, 0xab, 0x46, 0x66, 0x7b, 0xb6, 0x52, 0x5d, 0x7d, 0xc7, 0xa0, 0xe8, 0x28, 0x90, 0x17, 0xf5, 0x48, 0x7f, 0xa6, 0x92, 0xef, 0x2f, 0xdd, 0xce, 0x38, 0xad, 0x3f, 0x45, 0x30, 0xde, 0x7e, 0xe5, 0x05, 0x66, 0x70, 0xa7, 0x35, 0xd3, 0x78, 0xd1, 0xef, 0xc9, 0x94, 0x81, 0xf8, 0xc9, 0xfb, 0xee, 0xa9, 0x9f, 0x56, 0x6a, 0x0b, 0x6e, 0x28, 0x46, 0x26, 0x44, 0xa6, 0xd9, 0xc6, 0xcc, 0x88, 0xfb } +, + /* Signature */ + 192, + { 0xb7, 0x57, 0xfa, 0x74, 0x7c, 0x5c, 0x87, 0x67, 0x66, 0xf3, 0x58, 0xac, 0xbf, 0xc7, 0xe7, 0xb8, 0x05, 0x96, 0x36, 0x8d, 0x0d, 0x86, 0x29, 0x50, 0xe5, 0x55, 0xf4, 0x71, 0x64, 0x6f, 0x64, 0x0e, 0x85, 0x1d, 0x61, 0x2a, 0x55, 0x6f, 0x55, 0xa7, 0x4a, 0x32, 0x92, 0x42, 0x9e, 0x4c, 0x14, 0xf7, 0x8b, 0xa3, 0xeb, 0xbd, 0x96, 0x87, 0xf3, 0x08, 0xde, 0xdb, 0x3c, 0xfe, 0xd7, 0x1f, 0x4a, 0x9d, 0xd2, 0x6f, 0xa5, 0x12, 0x2f, 0x7f, 0x71, 0x94, 0xae, 0xb6, 0x3b, 0xc8, 0xb7, 0x5c, 0x34, 0x31, 0x87, 0x11, 0x5a, 0x1d, 0xbd, 0x35, 0x95, 0x90, 0xf7, 0xff, 0x38, 0x62, 0xb7, 0x08, 0x85, 0xaf, 0x1c, 0xa9, 0x34, 0xb8, 0xce, 0xbc, 0x2c, 0xc9, 0xe6, 0x47, 0x25, 0x3f, 0xd1, 0x32, 0x7a, 0x2e, 0xd4, 0x24, 0x4d, 0xc8, 0xf5, 0x85, 0x55, 0xa6, 0x89, 0x7c, 0xa3, 0x22, 0x9c, 0x80, 0x1e, 0x7b, 0xf6, 0x28, 0xf5, 0x25, 0xe6, 0xc9, 0x48, 0x80, 0x4d, 0x0b, 0x1b, 0x6d, 0xbc, 0xd7, 0x90, 0x2a, 0xcd, 0xe7, 0xa2, 0x5b, 0xa5, 0x91, 0xd8, 0x86, 0xe2, 0x8d, 0xaa, 0x8d, 0xed, 0x5e, 0xe4, 0x01, 0xe3, 0x4e, 0x64, 0x12, 0xf1, 0xe6, 0x44, 0xee, 0xc1, 0x2a, 0xe9, 0x42, 0x61, 0x90, 0x6a, 0x17, 0x26, 0x11, 0xdd, 0x5a, 0x98, 0x67, 0x78, 0x9c, 0x41, 0x90, 0x34, 0x68, 0x84, 0x29, 0xe9, 0x06 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.18", + /* Message to be signed */ + 93, + { 0x9d, 0xc7, 0xce, 0x1d, 0x02, 0xca, 0xdc, 0xf1, 0x0d, 0xf1, 0x11, 0x04, 0x56, 0xb8, 0xa7, 0xa5, 0xea, 0x43, 0x76, 0xb2, 0x7e, 0x8b, 0xf8, 0xcc, 0x8d, 0xb8, 0x10, 0x49, 0xfd, 0xa3, 0xfb, 0xd0, 0xdb, 0x8a, 0x3d, 0x0f, 0x6b, 0xd7, 0x48, 0x6b, 0x8d, 0x84, 0xbf, 0x9f, 0xfd, 0x4b, 0x64, 0x17, 0x52, 0xdf, 0x7e, 0xdf, 0x50, 0x86, 0x5e, 0x8e, 0x58, 0xad, 0x49, 0xf7, 0x24, 0x0e, 0x47, 0xd3, 0xfc, 0x98, 0x5e, 0xdb, 0x59, 0x6d, 0xab, 0xfe, 0x01, 0x72, 0x2a, 0x22, 0x77, 0x60, 0x38, 0x3c, 0xe2, 0x4d, 0x4a, 0x05, 0xd8, 0xb0, 0x6e, 0xf5, 0xb9, 0x6f, 0x11, 0x7d, 0x81 } +, + /* Signature */ + 192, + { 0x05, 0xa9, 0x5e, 0x11, 0xb5, 0xbf, 0xb0, 0x1d, 0xcf, 0xde, 0x3e, 0xfa, 0x9f, 0x31, 0x3d, 0x81, 0xbb, 0x0d, 0xfd, 0x46, 0xde, 0x63, 0xb0, 0x65, 0x80, 0x56, 0xc5, 0x3a, 0xf7, 0xad, 0x9e, 0x89, 0x43, 0x8b, 0x7d, 0xe7, 0x8f, 0xf8, 0xea, 0x88, 0xd0, 0x72, 0xb1, 0x74, 0x9a, 0x52, 0x9f, 0x1c, 0xc9, 0xcf, 0x2c, 0xf3, 0x2e, 0x5a, 0xb7, 0x20, 0xe0, 0x69, 0xb4, 0x90, 0x6d, 0x28, 0x2a, 0x03, 0xdd, 0x78, 0xd1, 0xb3, 0xca, 0x2a, 0x3f, 0x92, 0x5b, 0xf5, 0x1c, 0x74, 0x91, 0xb7, 0x3b, 0xa0, 0xbf, 0x54, 0xd5, 0x0d, 0x97, 0x1d, 0xe5, 0xb2, 0x77, 0x26, 0xd8, 0xfb, 0x3e, 0xe2, 0x77, 0x34, 0x97, 0xdf, 0x35, 0x49, 0x51, 0x7e, 0xed, 0xcd, 0x9d, 0xe6, 0x8d, 0x90, 0xdf, 0x35, 0xd3, 0xf0, 0x50, 0x81, 0x15, 0x1a, 0xda, 0xb5, 0x39, 0x73, 0x85, 0xab, 0xee, 0xa7, 0x2b, 0x69, 0xbd, 0x0d, 0xe1, 0x8d, 0xce, 0xe9, 0xa2, 0xbe, 0x00, 0xe9, 0x1a, 0x03, 0x24, 0x03, 0xb1, 0xf8, 0x1b, 0xbc, 0x0a, 0xe7, 0x31, 0xc6, 0xc0, 0xd9, 0xcf, 0xdd, 0x06, 0xc3, 0x31, 0xed, 0x89, 0xd7, 0xde, 0x1d, 0xe1, 0xdf, 0x46, 0xcf, 0x09, 0xce, 0x53, 0xdf, 0x15, 0x97, 0xfb, 0x69, 0x94, 0x68, 0x1c, 0x7f, 0xbe, 0x94, 0xc9, 0xb0, 0x8e, 0x50, 0xaa, 0x1b, 0x12, 0x41, 0x96, 0x02, 0x98, 0x7f, 0x37, 0xdd } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.19", + /* Message to be signed */ + 253, + { 0x87, 0xa6, 0x45, 0x61, 0x1b, 0xb1, 0x91, 0x85, 0x3f, 0x4f, 0xd9, 0xb7, 0x40, 0xb2, 0xde, 0x4c, 0x16, 0x3e, 0x75, 0x62, 0xb1, 0x17, 0x62, 0x63, 0x3e, 0x72, 0xdf, 0xb6, 0xf6, 0xbe, 0x7e, 0xfb, 0x90, 0x41, 0xa9, 0x65, 0x82, 0x94, 0x3a, 0xb2, 0x01, 0x83, 0x91, 0xc0, 0x5a, 0xdf, 0xab, 0x46, 0x4d, 0xd6, 0xe3, 0x3f, 0x96, 0x0d, 0xdb, 0xf3, 0xb1, 0x7a, 0xc6, 0x2b, 0xb7, 0x8a, 0xfc, 0x1c, 0x6a, 0x45, 0x39, 0x6c, 0x09, 0x08, 0x70, 0x7c, 0x62, 0x36, 0x12, 0x55, 0xcb, 0xf0, 0x9b, 0xad, 0x95, 0x9b, 0x31, 0x33, 0xda, 0x48, 0xd5, 0x32, 0xba, 0x7e, 0xf1, 0xd2, 0x0f, 0xb6, 0x57, 0x2a, 0x1f, 0x0e, 0xd6, 0xf2, 0xc6, 0xe1, 0xbe, 0xc1, 0xb1, 0x7c, 0xc3, 0x19, 0xba, 0xf7, 0x2a, 0x19, 0x8a, 0xa0, 0x01, 0xb8, 0x3d, 0x4e, 0x98, 0x69, 0xc3, 0x40, 0x90, 0xf2, 0x29, 0xa9, 0xc7, 0xf1, 0x42, 0xa7, 0x4e, 0x85, 0xab, 0x3e, 0xd5, 0x1c, 0x69, 0xac, 0x15, 0xfa, 0xb4, 0xab, 0xe4, 0x67, 0x15, 0x73, 0xcf, 0x5a, 0xd2, 0xb5, 0x8e, 0x78, 0xa9, 0x44, 0xed, 0xcc, 0xea, 0xc5, 0xee, 0x58, 0xbf, 0xce, 0x66, 0xf4, 0x0a, 0xac, 0x2a, 0xbe, 0x4e, 0x5f, 0xa0, 0x72, 0xdd, 0x0f, 0x66, 0x4f, 0xac, 0x81, 0x1a, 0xef, 0x08, 0x42, 0x10, 0xe5, 0x64, 0x1b, 0x9c, 0xd0, 0x8c, 0x87, 0x24, 0xf4, 0xb4, 0x1e, 0xed, 0x1d, 0x9d, 0x4a, 0x18, 0x77, 0x80, 0x46, 0x59, 0x7b, 0xd1, 0xa2, 0x7b, 0xbb, 0xc0, 0x56, 0xc1, 0x5e, 0x43, 0xc0, 0x38, 0xef, 0x37, 0x5b, 0x43, 0x5e, 0x73, 0xa7, 0xd3, 0x2f, 0x01, 0x50, 0x16, 0xb7, 0x82, 0x35, 0xce, 0x75, 0xa7, 0xb7, 0x62, 0x04, 0x99, 0x68, 0xe9, 0x93, 0x22, 0x53, 0xe4, 0x2c, 0xa9, 0x76, 0xc8, 0xd8, 0xdc, 0xa1, 0xbb, 0x2d, 0xbf } +, + /* Signature */ + 192, + { 0xb8, 0x80, 0x62, 0x26, 0xfb, 0xd3, 0xd9, 0x7b, 0x79, 0xf0, 0xdd, 0x1d, 0x8c, 0xf9, 0xa2, 0x35, 0xe5, 0x1b, 0x94, 0xb7, 0xe2, 0x23, 0xec, 0x68, 0x33, 0x2d, 0x68, 0x6e, 0xd3, 0x31, 0x3e, 0xd1, 0xbe, 0xf6, 0x88, 0x70, 0x23, 0xaf, 0x7a, 0x5c, 0x99, 0xdf, 0x03, 0x68, 0xa3, 0x49, 0xc6, 0xa5, 0x94, 0x79, 0x5b, 0x62, 0x35, 0x36, 0x10, 0x13, 0x42, 0x69, 0x0d, 0xeb, 0x5f, 0xad, 0x90, 0x23, 0x78, 0x2f, 0x6d, 0xbe, 0x16, 0x43, 0xa4, 0x56, 0x18, 0x57, 0x4f, 0x16, 0x72, 0x81, 0x12, 0xa7, 0xe0, 0xef, 0x9f, 0x58, 0x65, 0x6f, 0x6a, 0xdb, 0xf4, 0x00, 0x40, 0x9f, 0x4a, 0xa5, 0x01, 0x3c, 0x15, 0x9a, 0x36, 0x8c, 0xa5, 0x9b, 0xde, 0x6b, 0x39, 0x18, 0xdf, 0xe1, 0xd8, 0x02, 0xfa, 0x6c, 0xfa, 0x06, 0xc9, 0xca, 0x31, 0xac, 0xa7, 0x8c, 0xb2, 0x63, 0xc8, 0xed, 0x91, 0x7a, 0xf9, 0xa9, 0xa7, 0x95, 0xd5, 0xe2, 0xc4, 0x01, 0xe7, 0x29, 0x96, 0x4c, 0xf7, 0xac, 0x28, 0xcc, 0xdb, 0x36, 0xd9, 0x59, 0xed, 0x7f, 0xd9, 0xaf, 0x1c, 0x47, 0x09, 0x7b, 0x62, 0x55, 0xc6, 0x4e, 0x1b, 0x16, 0xf2, 0x1d, 0x86, 0x87, 0x04, 0x55, 0xd5, 0xf0, 0xbf, 0x90, 0x1f, 0xcc, 0x68, 0xc3, 0x4b, 0x72, 0xc1, 0xbe, 0xe7, 0x2e, 0x6b, 0x8c, 0x4e, 0x36, 0xae, 0x33, 0x99, 0x6c, 0x7a, 0x59, 0xd0, 0x9a } + +} +, +{ + "PKCS#1 v1.5 Signature Example 14.20", + /* Message to be signed */ + 41, + { 0x03, 0x2e, 0x28, 0x3e, 0x59, 0x6e, 0x87, 0xfa, 0xa6, 0xcf, 0xcf, 0xb8, 0xfa, 0x04, 0xdf, 0x6a, 0x61, 0xe6, 0x11, 0xdf, 0xe7, 0x3b, 0xbf, 0x66, 0x8e, 0xe6, 0x7b, 0x49, 0x6b, 0xfb, 0x0f, 0xfb, 0x7f, 0x9d, 0xc9, 0x31, 0xa9, 0x8b, 0xce, 0xdb, 0x25 } +, + /* Signature */ + 192, + { 0xb9, 0xfd, 0xc0, 0x3d, 0xc1, 0x99, 0x70, 0x71, 0x3c, 0x4a, 0x17, 0xe8, 0x7e, 0x7e, 0xbb, 0x5f, 0x13, 0x50, 0x5d, 0x59, 0xcb, 0xb2, 0x2b, 0xa7, 0x2e, 0x9f, 0xf1, 0x6b, 0xdf, 0x8b, 0x65, 0x9c, 0x33, 0x30, 0xa9, 0x3d, 0xcc, 0x09, 0x2a, 0x5d, 0x38, 0x5b, 0x2d, 0x5e, 0x15, 0x34, 0x00, 0x31, 0x46, 0xc0, 0x50, 0xb7, 0xdd, 0xc4, 0xf7, 0x56, 0x56, 0x9d, 0xa2, 0x11, 0x80, 0x15, 0x82, 0x26, 0x61, 0x19, 0xf5, 0x59, 0x9b, 0x1e, 0x65, 0xe8, 0xeb, 0xea, 0x6b, 0xc9, 0x64, 0x42, 0xee, 0x12, 0xac, 0xb9, 0x6c, 0x6d, 0xba, 0x08, 0x3e, 0x92, 0x10, 0x94, 0xda, 0x9c, 0x9e, 0xcf, 0x5a, 0xfa, 0xa5, 0x4b, 0x7f, 0xde, 0x7a, 0x0c, 0xae, 0x3f, 0xdf, 0xe4, 0xd2, 0x51, 0x93, 0x3a, 0x52, 0xf0, 0x2d, 0xc2, 0x3e, 0x1b, 0x32, 0x14, 0xc6, 0x83, 0xe1, 0x9a, 0xf4, 0x6e, 0x18, 0xc7, 0x49, 0x56, 0xdc, 0x6a, 0xb3, 0x50, 0x2d, 0x46, 0xca, 0xac, 0x3c, 0xb2, 0x6b, 0x70, 0x7c, 0xdc, 0x30, 0x25, 0xb6, 0xde, 0x4e, 0x83, 0x54, 0x3b, 0x95, 0x84, 0x5b, 0x4a, 0x15, 0x97, 0x60, 0x77, 0x0a, 0x4b, 0xd0, 0x9e, 0x46, 0x35, 0xa0, 0x4e, 0x21, 0x7d, 0x66, 0x5c, 0x95, 0x94, 0x87, 0x9f, 0x38, 0x1d, 0x71, 0x10, 0x09, 0x34, 0xfa, 0xda, 0x61, 0xc7, 0xcc, 0x22, 0xb8, 0xd2, 0xff, 0x8e, 0xb3, 0x5a } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 15: A 2048-bit RSA key pair", +{ + /* Modulus */ + 256, + { 0xdf, 0x27, 0x1f, 0xd2, 0x5f, 0x86, 0x44, 0x49, 0x6b, 0x0c, 0x81, 0xbe, 0x4b, 0xd5, 0x02, 0x97, 0xef, 0x09, 0x9b, 0x00, 0x2a, 0x6f, 0xd6, 0x77, 0x27, 0xeb, 0x44, 0x9c, 0xea, 0x56, 0x6e, 0xd6, 0xa3, 0x98, 0x1a, 0x71, 0x31, 0x2a, 0x14, 0x1c, 0xab, 0xc9, 0x81, 0x5c, 0x12, 0x09, 0xe3, 0x20, 0xa2, 0x5b, 0x32, 0x46, 0x4e, 0x99, 0x99, 0xf1, 0x8c, 0xa1, 0x3a, 0x9f, 0xd3, 0x89, 0x25, 0x58, 0xf9, 0xe0, 0xad, 0xef, 0xdd, 0x36, 0x50, 0xdd, 0x23, 0xa3, 0xf0, 0x36, 0xd6, 0x0f, 0xe3, 0x98, 0x84, 0x37, 0x06, 0xa4, 0x0b, 0x0b, 0x84, 0x62, 0xc8, 0xbe, 0xe3, 0xbc, 0xe1, 0x2f, 0x1f, 0x28, 0x60, 0xc2, 0x44, 0x4c, 0xdc, 0x6a, 0x44, 0x47, 0x6a, 0x75, 0xff, 0x4a, 0xa2, 0x42, 0x73, 0xcc, 0xbe, 0x3b, 0xf8, 0x02, 0x48, 0x46, 0x5f, 0x8f, 0xf8, 0xc3, 0xa7, 0xf3, 0x36, 0x7d, 0xfc, 0x0d, 0xf5, 0xb6, 0x50, 0x9a, 0x4f, 0x82, 0x81, 0x1c, 0xed, 0xd8, 0x1c, 0xda, 0xaa, 0x73, 0xc4, 0x91, 0xda, 0x41, 0x21, 0x70, 0xd5, 0x44, 0xd4, 0xba, 0x96, 0xb9, 0x7f, 0x0a, 0xfc, 0x80, 0x65, 0x49, 0x8d, 0x3a, 0x49, 0xfd, 0x91, 0x09, 0x92, 0xa1, 0xf0, 0x72, 0x5b, 0xe2, 0x4f, 0x46, 0x5c, 0xfe, 0x7e, 0x0e, 0xab, 0xf6, 0x78, 0x99, 0x6c, 0x50, 0xbc, 0x5e, 0x75, 0x24, 0xab, 0xf7, 0x3f, 0x15, 0xe5, 0xbe, 0xf7, 0xd5, 0x18, 0x39, 0x4e, 0x31, 0x38, 0xce, 0x49, 0x44, 0x50, 0x6a, 0xaa, 0xaf, 0x3f, 0x9b, 0x23, 0x6d, 0xca, 0xb8, 0xfc, 0x00, 0xf8, 0x7a, 0xf5, 0x96, 0xfd, 0xc3, 0xd9, 0xd6, 0xc7, 0x5c, 0xd5, 0x08, 0x36, 0x2f, 0xae, 0x2c, 0xbe, 0xdd, 0xcc, 0x4c, 0x74, 0x50, 0xb1, 0x7b, 0x77, 0x6c, 0x07, 0x9e, 0xcc, 0xa1, 0xf2, 0x56, 0x35, 0x1a, 0x43, 0xb9, 0x7d, 0xbe, 0x21, 0x53 } +, + /* Public exponent */ + 3, + { 0x01, 0x00, 0x01 } +, + /* Exponent */ + 256, + { 0x5b, 0xd9, 0x10, 0x25, 0x78, 0x30, 0xdc, 0xe1, 0x75, 0x20, 0xb0, 0x34, 0x41, 0xa5, 0x1a, 0x8c, 0xab, 0x94, 0x02, 0x0a, 0xc6, 0xec, 0xc2, 0x52, 0xc8, 0x08, 0xf3, 0x74, 0x3c, 0x95, 0xb7, 0xc8, 0x3b, 0x8c, 0x8a, 0xf1, 0xa5, 0x01, 0x43, 0x46, 0xeb, 0xc4, 0x24, 0x2c, 0xdf, 0xb5, 0xd7, 0x18, 0xe3, 0x0a, 0x73, 0x3e, 0x71, 0xf2, 0x91, 0xe4, 0xd4, 0x73, 0xb6, 0x1b, 0xfb, 0xa6, 0xda, 0xca, 0xed, 0x0a, 0x77, 0xbd, 0x1f, 0x09, 0x50, 0xae, 0x3c, 0x91, 0xa8, 0xf9, 0x01, 0x11, 0x88, 0x25, 0x89, 0xe1, 0xd6, 0x27, 0x65, 0xee, 0x67, 0x1e, 0x7b, 0xae, 0xea, 0x30, 0x9f, 0x64, 0xd4, 0x47, 0xbb, 0xcf, 0xa9, 0xea, 0x12, 0xdc, 0xe0, 0x5e, 0x9e, 0xa8, 0x93, 0x9b, 0xc5, 0xfe, 0x61, 0x08, 0x58, 0x12, 0x79, 0xc9, 0x82, 0xb3, 0x08, 0x79, 0x4b, 0x34, 0x48, 0xe7, 0xf7, 0xb9, 0x52, 0x29, 0x2d, 0xf8, 0x8c, 0x80, 0xcb, 0x40, 0x14, 0x2c, 0x4b, 0x5c, 0xf5, 0xf8, 0xdd, 0xaa, 0x08, 0x91, 0x67, 0x8d, 0x61, 0x0e, 0x58, 0x2f, 0xcb, 0x88, 0x0f, 0x0d, 0x70, 0x7c, 0xaf, 0x47, 0xd0, 0x9a, 0x84, 0xe1, 0x4c, 0xa6, 0x58, 0x41, 0xe5, 0xa3, 0xab, 0xc5, 0xe9, 0xdb, 0xa9, 0x40, 0x75, 0xa9, 0x08, 0x43, 0x41, 0xf0, 0xed, 0xad, 0x9b, 0x68, 0xe3, 0xb8, 0xe0, 0x82, 0xb8, 0x0b, 0x6e, 0x6e, 0x8a, 0x05, 0x47, 0xb4, 0x4f, 0xb5, 0x06, 0x1b, 0x6a, 0x91, 0x31, 0x60, 0x3a, 0x55, 0x37, 0xdd, 0xab, 0xd0, 0x1d, 0x8e, 0x86, 0x3d, 0x89, 0x22, 0xe9, 0xaa, 0x3e, 0x4b, 0xfa, 0xea, 0x0b, 0x39, 0xd7, 0x92, 0x83, 0xad, 0x2c, 0xbc, 0x8a, 0x59, 0xcc, 0xe7, 0xa6, 0xec, 0xf4, 0xe4, 0xc8, 0x1e, 0xd4, 0xc6, 0x59, 0x1c, 0x80, 0x7d, 0xef, 0xd7, 0x1a, 0xb0, 0x68, 0x66, 0xbb, 0x5e, 0x77, 0x45 } +, + /* Prime 1 */ + 128, + { 0xf4, 0x4f, 0x5e, 0x42, 0x46, 0x39, 0x1f, 0x48, 0x2b, 0x2f, 0x52, 0x96, 0xe3, 0x60, 0x2e, 0xb3, 0x4a, 0xa1, 0x36, 0x42, 0x77, 0x10, 0xf7, 0xc0, 0x41, 0x6d, 0x40, 0x3f, 0xd6, 0x9d, 0x4b, 0x29, 0x13, 0x0c, 0xfe, 0xbe, 0xf3, 0x4e, 0x88, 0x5a, 0xbd, 0xb1, 0xa8, 0xa0, 0xa5, 0xf0, 0xe9, 0xb5, 0xc3, 0x3e, 0x1f, 0xc3, 0xbf, 0xc2, 0x85, 0xb1, 0xae, 0x17, 0xe4, 0x0c, 0xc6, 0x7a, 0x19, 0x13, 0xdd, 0x56, 0x37, 0x19, 0x81, 0x5e, 0xba, 0xf8, 0x51, 0x4c, 0x2a, 0x7a, 0xa0, 0x01, 0x8e, 0x63, 0xb6, 0xc6, 0x31, 0xdc, 0x31, 0x5a, 0x46, 0x23, 0x57, 0x16, 0x42, 0x3d, 0x11, 0xff, 0x58, 0x03, 0x4e, 0x61, 0x06, 0x45, 0x70, 0x36, 0x06, 0x91, 0x9f, 0x5c, 0x7c, 0xe2, 0x66, 0x0c, 0xd1, 0x48, 0xbd, 0x9e, 0xfc, 0x12, 0x3d, 0x9c, 0x54, 0xb6, 0x70, 0x55, 0x90, 0xd0, 0x06, 0xcf, 0xcf, 0x3f } +, + /* Prime 2 */ + 128, + { 0xe9, 0xd4, 0x98, 0x41, 0xe0, 0xe0, 0xa6, 0xad, 0x0d, 0x51, 0x78, 0x57, 0x13, 0x3e, 0x36, 0xdc, 0x72, 0xc1, 0xbd, 0xd9, 0x0f, 0x91, 0x74, 0xb5, 0x2e, 0x26, 0x57, 0x0f, 0x37, 0x36, 0x40, 0xf1, 0xc1, 0x85, 0xe7, 0xea, 0x8e, 0x2e, 0xd7, 0xf1, 0xe4, 0xeb, 0xb9, 0x51, 0xf7, 0x0a, 0x58, 0x02, 0x36, 0x33, 0xb0, 0x09, 0x7a, 0xec, 0x67, 0xc6, 0xdc, 0xb8, 0x00, 0xfc, 0x1a, 0x67, 0xf9, 0xbb, 0x05, 0x63, 0x61, 0x0f, 0x08, 0xeb, 0xc8, 0x74, 0x6a, 0xd1, 0x29, 0x77, 0x21, 0x36, 0xeb, 0x1d, 0xda, 0xf4, 0x64, 0x36, 0x45, 0x0d, 0x31, 0x83, 0x32, 0xa8, 0x49, 0x82, 0xfe, 0x5d, 0x28, 0xdb, 0xe5, 0xb3, 0xe9, 0x12, 0x40, 0x7c, 0x3e, 0x0e, 0x03, 0x10, 0x0d, 0x87, 0xd4, 0x36, 0xee, 0x40, 0x9e, 0xec, 0x1c, 0xf8, 0x5e, 0x80, 0xab, 0xa0, 0x79, 0xb2, 0xe6, 0x10, 0x6b, 0x97, 0xbc, 0xed } +, + /* Prime exponent 1 */ + 128, + { 0xed, 0x10, 0x2a, 0xcd, 0xb2, 0x68, 0x71, 0x53, 0x4d, 0x1c, 0x41, 0x4e, 0xca, 0xd9, 0xa4, 0xd7, 0x32, 0xfe, 0x95, 0xb1, 0x0e, 0xea, 0x37, 0x0d, 0xa6, 0x2f, 0x05, 0xde, 0x2c, 0x39, 0x3b, 0x1a, 0x63, 0x33, 0x03, 0xea, 0x74, 0x1b, 0x6b, 0x32, 0x69, 0xc9, 0x7f, 0x70, 0x4b, 0x35, 0x27, 0x02, 0xc9, 0xae, 0x79, 0x92, 0x2f, 0x7b, 0xe8, 0xd1, 0x0d, 0xb6, 0x7f, 0x02, 0x6a, 0x81, 0x45, 0xde, 0x41, 0xb3, 0x0c, 0x0a, 0x42, 0xbf, 0x92, 0x3b, 0xac, 0x5f, 0x75, 0x04, 0xc2, 0x48, 0x60, 0x4b, 0x9f, 0xaa, 0x57, 0xed, 0x6b, 0x32, 0x46, 0xc6, 0xba, 0x15, 0x8e, 0x36, 0xc6, 0x44, 0xf8, 0xb9, 0x54, 0x8f, 0xcf, 0x4f, 0x07, 0xe0, 0x54, 0xa5, 0x6f, 0x76, 0x86, 0x74, 0x05, 0x44, 0x40, 0xbc, 0x0d, 0xcb, 0xbc, 0x9b, 0x52, 0x8f, 0x64, 0xa0, 0x17, 0x06, 0xe0, 0x5b, 0x0b, 0x91, 0x10, 0x6f } +, + /* Prime exponent 2 */ + 128, + { 0x68, 0x27, 0x92, 0x4a, 0x85, 0xe8, 0x8b, 0x55, 0xba, 0x00, 0xf8, 0x21, 0x91, 0x28, 0xbd, 0x37, 0x24, 0xc6, 0xb7, 0xd1, 0xdf, 0xe5, 0x62, 0x9e, 0xf1, 0x97, 0x92, 0x5f, 0xec, 0xaf, 0xf5, 0xed, 0xb9, 0xcd, 0xf3, 0xa7, 0xbe, 0xfd, 0x8e, 0xa2, 0xe8, 0xdd, 0x37, 0x07, 0x13, 0x8b, 0x3f, 0xf8, 0x7c, 0x3c, 0x39, 0xc5, 0x7f, 0x43, 0x9e, 0x56, 0x2e, 0x2a, 0xa8, 0x05, 0xa3, 0x9d, 0x7c, 0xd7, 0x99, 0x66, 0xd2, 0xec, 0xe7, 0x84, 0x5f, 0x1d, 0xbc, 0x16, 0xbe, 0xe9, 0x99, 0x99, 0xe4, 0xd0, 0xbf, 0x9e, 0xec, 0xa4, 0x5f, 0xcd, 0xa8, 0xa8, 0x50, 0x00, 0x35, 0xfe, 0x6b, 0x5f, 0x03, 0xbc, 0x2f, 0x6d, 0x1b, 0xfc, 0x4d, 0x4d, 0x0a, 0x37, 0x23, 0x96, 0x1a, 0xf0, 0xcd, 0xce, 0x4a, 0x01, 0xee, 0xc8, 0x2d, 0x7f, 0x54, 0x58, 0xec, 0x19, 0xe7, 0x1b, 0x90, 0xee, 0xef, 0x7d, 0xff, 0x61 } +, + /* Coefficient */ + 128, + { 0x57, 0xb7, 0x38, 0x88, 0xd1, 0x83, 0xa9, 0x9a, 0x63, 0x07, 0x42, 0x22, 0x77, 0x55, 0x1a, 0x3d, 0x9e, 0x18, 0xad, 0xf0, 0x6a, 0x91, 0xe8, 0xb5, 0x5c, 0xef, 0xfe, 0xf9, 0x07, 0x7c, 0x84, 0x96, 0x94, 0x8e, 0xcb, 0x3b, 0x16, 0xb7, 0x81, 0x55, 0xcb, 0x2a, 0x3a, 0x57, 0xc1, 0x19, 0xd3, 0x79, 0x95, 0x1c, 0x01, 0x0a, 0xa6, 0x35, 0xed, 0xcf, 0x62, 0xd8, 0x4c, 0x5a, 0x12, 0x2a, 0x8d, 0x67, 0xab, 0x5f, 0xa9, 0xe5, 0xa4, 0xa8, 0x77, 0x2a, 0x1e, 0x94, 0x3b, 0xaf, 0xc7, 0x0a, 0xe3, 0xa4, 0xc1, 0xf0, 0xf3, 0xa4, 0xdd, 0xff, 0xae, 0xfd, 0x18, 0x92, 0xc8, 0xcb, 0x33, 0xbb, 0x0d, 0x0b, 0x95, 0x90, 0xe9, 0x63, 0xa6, 0x91, 0x10, 0xfb, 0x34, 0xdb, 0x7b, 0x90, 0x6f, 0xc4, 0xba, 0x28, 0x36, 0x99, 0x5a, 0xac, 0x7e, 0x52, 0x74, 0x90, 0xac, 0x95, 0x2a, 0x02, 0x26, 0x8a, 0x4f, 0x18 } + +} +, +{{ + "PKCS#1 v1.5 Signature Example 15.1", + /* Message to be signed */ + 229, + { 0xf4, 0x5d, 0x55, 0xf3, 0x55, 0x51, 0xe9, 0x75, 0xd6, 0xa8, 0xdc, 0x7e, 0xa9, 0xf4, 0x88, 0x59, 0x39, 0x40, 0xcc, 0x75, 0x69, 0x4a, 0x27, 0x8f, 0x27, 0xe5, 0x78, 0xa1, 0x63, 0xd8, 0x39, 0xb3, 0x40, 0x40, 0x84, 0x18, 0x08, 0xcf, 0x9c, 0x58, 0xc9, 0xb8, 0x72, 0x8b, 0xf5, 0xf9, 0xce, 0x8e, 0xe8, 0x11, 0xea, 0x91, 0x71, 0x4f, 0x47, 0xba, 0xb9, 0x2d, 0x0f, 0x6d, 0x5a, 0x26, 0xfc, 0xfe, 0xea, 0x6c, 0xd9, 0x3b, 0x91, 0x0c, 0x0a, 0x2c, 0x96, 0x3e, 0x64, 0xeb, 0x18, 0x23, 0xf1, 0x02, 0x75, 0x3d, 0x41, 0xf0, 0x33, 0x59, 0x10, 0xad, 0x3a, 0x97, 0x71, 0x04, 0xf1, 0xaa, 0xf6, 0xc3, 0x74, 0x27, 0x16, 0xa9, 0x75, 0x5d, 0x11, 0xb8, 0xee, 0xd6, 0x90, 0x47, 0x7f, 0x44, 0x5c, 0x5d, 0x27, 0x20, 0x8b, 0x2e, 0x28, 0x43, 0x30, 0xfa, 0x3d, 0x30, 0x14, 0x23, 0xfa, 0x7f, 0x2d, 0x08, 0x6e, 0x0a, 0xd0, 0xb8, 0x92, 0xb9, 0xdb, 0x54, 0x4e, 0x45, 0x6d, 0x3f, 0x0d, 0xab, 0x85, 0xd9, 0x53, 0xc1, 0x2d, 0x34, 0x0a, 0xa8, 0x73, 0xed, 0xa7, 0x27, 0xc8, 0xa6, 0x49, 0xdb, 0x7f, 0xa6, 0x37, 0x40, 0xe2, 0x5e, 0x9a, 0xf1, 0x53, 0x3b, 0x30, 0x7e, 0x61, 0x32, 0x99, 0x93, 0x11, 0x0e, 0x95, 0x19, 0x4e, 0x03, 0x93, 0x99, 0xc3, 0x82, 0x4d, 0x24, 0xc5, 0x1f, 0x22, 0xb2, 0x6b, 0xde, 0x10, 0x24, 0xcd, 0x39, 0x59, 0x58, 0xa2, 0xdf, 0xeb, 0x48, 0x16, 0xa6, 0xe8, 0xad, 0xed, 0xb5, 0x0b, 0x1f, 0x6b, 0x56, 0xd0, 0xb3, 0x06, 0x0f, 0xf0, 0xf1, 0xc4, 0xcb, 0x0d, 0x0e, 0x00, 0x1d, 0xd5, 0x9d, 0x73, 0xbe, 0x12 } +, + /* Signature */ + 256, + { 0xb7, 0x5a, 0x54, 0x66, 0xb6, 0x5d, 0x0f, 0x30, 0x0e, 0xf5, 0x38, 0x33, 0xf2, 0x17, 0x5c, 0x8a, 0x34, 0x7a, 0x38, 0x04, 0xfc, 0x63, 0x45, 0x1d, 0xc9, 0x02, 0xf0, 0xb7, 0x1f, 0x90, 0x83, 0x45, 0x9e, 0xd3, 0x7a, 0x51, 0x79, 0xa3, 0xb7, 0x23, 0xa5, 0x3f, 0x10, 0x51, 0x64, 0x2d, 0x77, 0x37, 0x4c, 0x4c, 0x6c, 0x8d, 0xbb, 0x1c, 0xa2, 0x05, 0x25, 0xf5, 0xc9, 0xf3, 0x2d, 0xb7, 0x76, 0x95, 0x35, 0x56, 0xda, 0x31, 0x29, 0x0e, 0x22, 0x19, 0x74, 0x82, 0xce, 0xb6, 0x99, 0x06, 0xc4, 0x6a, 0x75, 0x8f, 0xb0, 0xe7, 0x40, 0x9b, 0xa8, 0x01, 0x07, 0x7d, 0x2a, 0x0a, 0x20, 0xea, 0xe7, 0xd1, 0xd6, 0xd3, 0x92, 0xab, 0x49, 0x57, 0xe8, 0x6b, 0x76, 0xf0, 0x65, 0x2d, 0x68, 0xb8, 0x39, 0x88, 0xa7, 0x8f, 0x26, 0xe1, 0x11, 0x72, 0xea, 0x60, 0x9b, 0xf8, 0x49, 0xfb, 0xbd, 0x78, 0xad, 0x7e, 0xdc, 0xe2, 0x1d, 0xe6, 0x62, 0xa0, 0x81, 0x36, 0x8c, 0x04, 0x06, 0x07, 0xce, 0xe2, 0x9d, 0xb0, 0x62, 0x72, 0x27, 0xf4, 0x49, 0x63, 0xad, 0x17, 0x1d, 0x22, 0x93, 0xb6, 0x33, 0xa3, 0x92, 0xe3, 0x31, 0xdc, 0xa5, 0x4f, 0xe3, 0x08, 0x27, 0x52, 0xf4, 0x3f, 0x63, 0xc1, 0x61, 0xb4, 0x47, 0xa4, 0xc6, 0x5a, 0x68, 0x75, 0x67, 0x0d, 0x5f, 0x66, 0x00, 0xfc, 0xc8, 0x60, 0xa1, 0xca, 0xeb, 0x0a, 0x88, 0xf8, 0xfd, 0xec, 0x4e, 0x56, 0x43, 0x98, 0xa5, 0xc4, 0x6c, 0x87, 0xf6, 0x8c, 0xe0, 0x70, 0x01, 0xf6, 0x21, 0x3a, 0xbe, 0x0a, 0xb5, 0x62, 0x5f, 0x87, 0xd1, 0x90, 0x25, 0xf0, 0x8d, 0x81, 0xda, 0xc7, 0xbd, 0x45, 0x86, 0xbc, 0x93, 0x82, 0x19, 0x1f, 0x6d, 0x28, 0x80, 0xf6, 0x22, 0x7e, 0x5d, 0xf3, 0xee, 0xd2, 0x1e, 0x77, 0x92, 0xd2, 0x49, 0x48, 0x04, 0x87, 0xf3, 0x65, 0x52, 0x61 } + +} +, +#ifdef LTC_TEST_EXT +{ + "PKCS#1 v1.5 Signature Example 15.2", + /* Message to be signed */ + 153, + { 0xc1, 0x4b, 0x4c, 0x60, 0x75, 0xb2, 0xf9, 0xaa, 0xd6, 0x61, 0xde, 0xf4, 0xec, 0xfd, 0x3c, 0xb9, 0x33, 0xc6, 0x23, 0xf4, 0xe6, 0x3b, 0xf5, 0x34, 0x10, 0xd2, 0xf0, 0x16, 0xd1, 0xab, 0x98, 0xe2, 0x72, 0x9e, 0xcc, 0xf8, 0x00, 0x6c, 0xd8, 0xe0, 0x80, 0x50, 0x73, 0x7d, 0x95, 0xfd, 0xbf, 0x29, 0x6b, 0x66, 0xf5, 0xb9, 0x79, 0x2a, 0x90, 0x29, 0x36, 0xc4, 0xf7, 0xac, 0x69, 0xf5, 0x14, 0x53, 0xce, 0x43, 0x69, 0x45, 0x2d, 0xc2, 0x2d, 0x96, 0xf0, 0x37, 0x74, 0x81, 0x14, 0x66, 0x20, 0x00, 0xdd, 0x9c, 0xd3, 0xa5, 0xe1, 0x79, 0xf4, 0xe0, 0xf8, 0x1f, 0xa6, 0xa0, 0x31, 0x1c, 0xa1, 0xae, 0xe6, 0x51, 0x9a, 0x0f, 0x63, 0xce, 0xc7, 0x8d, 0x27, 0xbb, 0x72, 0x63, 0x93, 0xfb, 0x7f, 0x1f, 0x88, 0xcd, 0xe7, 0xc9, 0x7f, 0x8a, 0x66, 0xcd, 0x66, 0x30, 0x12, 0x81, 0xda, 0xc3, 0xf3, 0xa4, 0x33, 0x24, 0x8c, 0x75, 0xd6, 0xc2, 0xdc, 0xd7, 0x08, 0xb6, 0xa9, 0x7b, 0x0a, 0x3f, 0x32, 0x5e, 0x0b, 0x29, 0x64, 0xf8, 0xa5, 0x81, 0x9e, 0x47, 0x9b } +, + /* Signature */ + 256, + { 0xaf, 0xa7, 0x34, 0x34, 0x62, 0xbe, 0xa1, 0x22, 0xcc, 0x14, 0x9f, 0xca, 0x70, 0xab, 0xda, 0xe7, 0x94, 0x46, 0x67, 0x7d, 0xb5, 0x37, 0x36, 0x66, 0xaf, 0x7d, 0xc3, 0x13, 0x01, 0x5f, 0x4d, 0xe7, 0x86, 0xe6, 0xe3, 0x94, 0x94, 0x6f, 0xad, 0x3c, 0xc0, 0xe2, 0xb0, 0x2b, 0xed, 0xba, 0x50, 0x47, 0xfe, 0x9e, 0x2d, 0x7d, 0x09, 0x97, 0x05, 0xe4, 0xa3, 0x9f, 0x28, 0x68, 0x32, 0x79, 0xcf, 0x0a, 0xc8, 0x5c, 0x15, 0x30, 0x41, 0x22, 0x42, 0xc0, 0xe9, 0x18, 0x95, 0x3b, 0xe0, 0x00, 0xe9, 0x39, 0xcf, 0x3b, 0xf1, 0x82, 0x52, 0x5e, 0x19, 0x93, 0x70, 0xfa, 0x79, 0x07, 0xeb, 0xa6, 0x9d, 0x5d, 0xb4, 0x63, 0x10, 0x17, 0xc0, 0xe3, 0x6d, 0xf7, 0x03, 0x79, 0xb5, 0xdb, 0x8d, 0x4c, 0x69, 0x5a, 0x97, 0x9a, 0x8e, 0x61, 0x73, 0x22, 0x40, 0x65, 0xd7, 0xdc, 0x15, 0x13, 0x2e, 0xf2, 0x8c, 0xd8, 0x22, 0x79, 0x51, 0x63, 0x06, 0x3b, 0x54, 0xc6, 0x51, 0x14, 0x1b, 0xe8, 0x6d, 0x36, 0xe3, 0x67, 0x35, 0xbc, 0x61, 0xf3, 0x1f, 0xca, 0x57, 0x4e, 0x53, 0x09, 0xf3, 0xa3, 0xbb, 0xdf, 0x91, 0xef, 0xf1, 0x2b, 0x99, 0xe9, 0xcc, 0x17, 0x44, 0xf1, 0xee, 0x9a, 0x1b, 0xd2, 0x2c, 0x5b, 0xad, 0x96, 0xad, 0x48, 0x19, 0x29, 0x25, 0x1f, 0x03, 0x43, 0xfd, 0x36, 0xbc, 0xf0, 0xac, 0xde, 0x7f, 0x11, 0xe5, 0xad, 0x60, 0x97, 0x77, 0x21, 0x20, 0x27, 0x96, 0xfe, 0x06, 0x1f, 0x9a, 0xda, 0x1f, 0xc4, 0xc8, 0xe0, 0x0d, 0x60, 0x22, 0xa8, 0x35, 0x75, 0x85, 0xff, 0xe9, 0xfd, 0xd5, 0x93, 0x31, 0xa2, 0x8c, 0x4a, 0xa3, 0x12, 0x15, 0x88, 0xfb, 0x6c, 0xf6, 0x83, 0x96, 0xd8, 0xac, 0x05, 0x46, 0x59, 0x95, 0x00, 0xc9, 0x70, 0x85, 0x00, 0xa5, 0x97, 0x2b, 0xd5, 0x4f, 0x72, 0xcf, 0x8d, 0xb0, 0xc8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.3", + /* Message to be signed */ + 243, + { 0xd0, 0x23, 0x71, 0xad, 0x7e, 0xe4, 0x8b, 0xbf, 0xdb, 0x27, 0x63, 0xde, 0x7a, 0x84, 0x3b, 0x94, 0x08, 0xce, 0x5e, 0xb5, 0xab, 0xf8, 0x47, 0xca, 0x3d, 0x73, 0x59, 0x86, 0xdf, 0x84, 0xe9, 0x06, 0x0b, 0xdb, 0xcd, 0xd3, 0xa5, 0x5b, 0xa5, 0x5d, 0xde, 0x20, 0xd4, 0x76, 0x1e, 0x1a, 0x21, 0xd2, 0x25, 0xc1, 0xa1, 0x86, 0xf4, 0xac, 0x4b, 0x30, 0x19, 0xd3, 0xad, 0xf7, 0x8f, 0xe6, 0x33, 0x46, 0x67, 0xf5, 0x6f, 0x70, 0xc9, 0x01, 0xa0, 0xa2, 0x70, 0x0c, 0x6f, 0x0d, 0x56, 0xad, 0xd7, 0x19, 0x59, 0x2d, 0xc8, 0x8f, 0x6d, 0x23, 0x06, 0xc7, 0x00, 0x9f, 0x6e, 0x7a, 0x63, 0x5b, 0x4c, 0xb3, 0xa5, 0x02, 0xdf, 0xe6, 0x8d, 0xdc, 0x58, 0xd0, 0x3b, 0xe1, 0x0a, 0x11, 0x70, 0x00, 0x4f, 0xe7, 0x4d, 0xd3, 0xe4, 0x6b, 0x82, 0x59, 0x1f, 0xf7, 0x54, 0x14, 0xf0, 0xc4, 0xa0, 0x3e, 0x60, 0x5e, 0x20, 0x52, 0x4f, 0x24, 0x16, 0xf1, 0x2e, 0xca, 0x58, 0x9f, 0x11, 0x1b, 0x75, 0xd6, 0x39, 0xc6, 0x1b, 0xaa, 0x80, 0xca, 0xfd, 0x05, 0xcf, 0x35, 0x00, 0x24, 0x4a, 0x21, 0x9e, 0xd9, 0xce, 0xd9, 0xf0, 0xb1, 0x02, 0x97, 0x18, 0x2b, 0x65, 0x3b, 0x52, 0x6f, 0x40, 0x0f, 0x29, 0x53, 0xba, 0x21, 0x4d, 0x5b, 0xcd, 0x47, 0x88, 0x41, 0x32, 0x87, 0x2a, 0xe9, 0x0d, 0x4d, 0x6b, 0x1f, 0x42, 0x15, 0x39, 0xf9, 0xf3, 0x46, 0x62, 0xa5, 0x6d, 0xc0, 0xe7, 0xb4, 0xb9, 0x23, 0xb6, 0x23, 0x1e, 0x30, 0xd2, 0x67, 0x67, 0x97, 0x81, 0x7f, 0x7c, 0x33, 0x7b, 0x5a, 0xc8, 0x24, 0xba, 0x93, 0x14, 0x3b, 0x33, 0x81, 0xfa, 0x3d, 0xce, 0x0e, 0x6a, 0xeb, 0xd3, 0x8e, 0x67, 0x73, 0x51, 0x87, 0xb1, 0xeb, 0xd9, 0x5c, 0x02 } +, + /* Signature */ + 256, + { 0x3b, 0xac, 0x63, 0xf8, 0x6e, 0x3b, 0x70, 0x27, 0x12, 0x03, 0x10, 0x6b, 0x9c, 0x79, 0xaa, 0xbd, 0x9f, 0x47, 0x7c, 0x56, 0xe4, 0xee, 0x58, 0xa4, 0xfc, 0xe5, 0xba, 0xf2, 0xca, 0xb4, 0x96, 0x0f, 0x88, 0x39, 0x1c, 0x9c, 0x23, 0x69, 0x8b, 0xe7, 0x5c, 0x99, 0xae, 0xdf, 0x9e, 0x1a, 0xbf, 0x17, 0x05, 0xbe, 0x1d, 0xac, 0x33, 0x14, 0x0a, 0xdb, 0x48, 0xeb, 0x31, 0xf4, 0x50, 0xbb, 0x9e, 0xfe, 0x83, 0xb7, 0xb9, 0x0d, 0xb7, 0xf1, 0x57, 0x6d, 0x33, 0xf4, 0x0c, 0x1c, 0xba, 0x4b, 0x8d, 0x6b, 0x1d, 0x33, 0x23, 0x56, 0x4b, 0x0f, 0x17, 0x74, 0x11, 0x4f, 0xa7, 0xc0, 0x8e, 0x6d, 0x1e, 0x20, 0xdd, 0x8f, 0xbb, 0xa9, 0xb6, 0xac, 0x7a, 0xd4, 0x1e, 0x26, 0xb4, 0x56, 0x8f, 0x4a, 0x8a, 0xac, 0xbf, 0xd1, 0x78, 0xa8, 0xf8, 0xd2, 0xc9, 0xd5, 0xf5, 0xb8, 0x81, 0x12, 0x93, 0x5a, 0x8b, 0xc9, 0xae, 0x32, 0xcd, 0xa4, 0x0b, 0x8d, 0x20, 0x37, 0x55, 0x10, 0x73, 0x50, 0x96, 0x53, 0x68, 0x18, 0xce, 0x2b, 0x2d, 0xb7, 0x1a, 0x97, 0x72, 0xc9, 0xb0, 0xdd, 0xa0, 0x9a, 0xe1, 0x01, 0x52, 0xfa, 0x11, 0x46, 0x62, 0x18, 0xd0, 0x91, 0xb5, 0x3d, 0x92, 0x54, 0x30, 0x61, 0xb7, 0x29, 0x4a, 0x55, 0xbe, 0x82, 0xff, 0x35, 0xd5, 0xc3, 0x2f, 0xa2, 0x33, 0xf0, 0x5a, 0xaa, 0xc7, 0x58, 0x50, 0x30, 0x7e, 0xcf, 0x81, 0x38, 0x3c, 0x11, 0x16, 0x74, 0x39, 0x7b, 0x1a, 0x1b, 0x9d, 0x3b, 0xf7, 0x61, 0x2c, 0xcb, 0xe5, 0xba, 0xcd, 0x2b, 0x38, 0xf0, 0xa9, 0x83, 0x97, 0xb2, 0x4c, 0x83, 0x65, 0x8f, 0xb6, 0xc0, 0xb4, 0x14, 0x0e, 0xf1, 0x19, 0x70, 0xc4, 0x63, 0x0d, 0x44, 0x34, 0x4e, 0x76, 0xea, 0xed, 0x74, 0xdc, 0xbe, 0xe8, 0x11, 0xdb, 0xf6, 0x57, 0x59, 0x41, 0xf0, 0x8a, 0x65, 0x23, 0xb8 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.4", + /* Message to be signed */ + 58, + { 0x29, 0x03, 0x55, 0x84, 0xab, 0x7e, 0x02, 0x26, 0xa9, 0xec, 0x4b, 0x02, 0xe8, 0xdc, 0xf1, 0x27, 0x2d, 0xc9, 0xa4, 0x1d, 0x73, 0xe2, 0x82, 0x00, 0x07, 0xb0, 0xf6, 0xe2, 0x1f, 0xec, 0xcd, 0x5b, 0xd9, 0xdb, 0xb9, 0xef, 0x88, 0xcd, 0x67, 0x58, 0x76, 0x9e, 0xe1, 0xf9, 0x56, 0xda, 0x7a, 0xd1, 0x84, 0x41, 0xde, 0x6f, 0xab, 0x83, 0x86, 0xdb, 0xc6, 0x93 } +, + /* Signature */ + 256, + { 0x28, 0xd8, 0xe3, 0xfc, 0xd5, 0xdd, 0xdb, 0x21, 0xff, 0xbd, 0x8d, 0xf1, 0x63, 0x0d, 0x73, 0x77, 0xaa, 0x26, 0x51, 0xe1, 0x4c, 0xad, 0x1c, 0x0e, 0x43, 0xcc, 0xc5, 0x2f, 0x90, 0x7f, 0x94, 0x6d, 0x66, 0xde, 0x72, 0x54, 0xe2, 0x7a, 0x6c, 0x19, 0x0e, 0xb0, 0x22, 0xee, 0x89, 0xec, 0xf6, 0x22, 0x4b, 0x09, 0x7b, 0x71, 0x06, 0x8c, 0xd6, 0x07, 0x28, 0xa1, 0xae, 0xd6, 0x4b, 0x80, 0xe5, 0x45, 0x7b, 0xd3, 0x10, 0x6d, 0xd9, 0x17, 0x06, 0xc9, 0x37, 0xc9, 0x79, 0x5f, 0x2b, 0x36, 0x36, 0x7f, 0xf1, 0x53, 0xdc, 0x25, 0x19, 0xa8, 0xdb, 0x9b, 0xdf, 0x2c, 0x80, 0x74, 0x30, 0xc4, 0x51, 0xde, 0x17, 0xbb, 0xcd, 0x0c, 0xe7, 0x82, 0xb3, 0xe8, 0xf1, 0x02, 0x4d, 0x90, 0x62, 0x4d, 0xea, 0x7f, 0x1e, 0xed, 0xc7, 0x42, 0x0b, 0x7e, 0x7c, 0xaa, 0x65, 0x77, 0xce, 0xf4, 0x31, 0x41, 0xa7, 0x26, 0x42, 0x06, 0x58, 0x0e, 0x44, 0xa1, 0x67, 0xdf, 0x5e, 0x41, 0xee, 0xa0, 0xe6, 0x9a, 0x80, 0x54, 0x54, 0xc4, 0x0e, 0xef, 0xc1, 0x3f, 0x48, 0xe4, 0x23, 0xd7, 0xa3, 0x2d, 0x02, 0xed, 0x42, 0xc0, 0xab, 0x03, 0xd0, 0xa7, 0xcf, 0x70, 0xc5, 0x86, 0x0a, 0xc9, 0x2e, 0x03, 0xee, 0x00, 0x5b, 0x60, 0xff, 0x35, 0x03, 0x42, 0x4b, 0x98, 0xcc, 0x89, 0x45, 0x68, 0xc7, 0xc5, 0x6a, 0x02, 0x33, 0x55, 0x1c, 0xeb, 0xe5, 0x88, 0xcf, 0x8b, 0x01, 0x67, 0xb7, 0xdf, 0x13, 0xad, 0xca, 0xd8, 0x28, 0x67, 0x68, 0x10, 0x49, 0x9c, 0x70, 0x4d, 0xa7, 0xae, 0x23, 0x41, 0x4d, 0x69, 0xe3, 0xc0, 0xd2, 0xdb, 0x5d, 0xcb, 0xc2, 0x61, 0x3b, 0xc1, 0x20, 0x42, 0x1f, 0x9e, 0x36, 0x53, 0xc5, 0xa8, 0x76, 0x72, 0x97, 0x64, 0x3c, 0x7e, 0x07, 0x40, 0xde, 0x01, 0x63, 0x55, 0x45, 0x3d, 0x6c, 0x95, 0xae, 0x72 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.5", + /* Message to be signed */ + 14, + { 0xbd, 0xa3, 0xa1, 0xc7, 0x90, 0x59, 0xea, 0xe5, 0x98, 0x30, 0x8d, 0x3d, 0xf6, 0x09 } +, + /* Signature */ + 256, + { 0xa1, 0x56, 0x17, 0x6c, 0xb9, 0x67, 0x77, 0xc7, 0xfb, 0x96, 0x10, 0x5d, 0xbd, 0x91, 0x3b, 0xc4, 0xf7, 0x40, 0x54, 0xf6, 0x80, 0x7c, 0x60, 0x08, 0xa1, 0xa9, 0x56, 0xea, 0x92, 0xc1, 0xf8, 0x1c, 0xb8, 0x97, 0xdc, 0x4b, 0x92, 0xef, 0x9f, 0x4e, 0x40, 0x66, 0x8d, 0xc7, 0xc5, 0x56, 0x90, 0x1a, 0xcb, 0x6c, 0xf2, 0x69, 0xfe, 0x61, 0x5b, 0x0f, 0xb7, 0x2b, 0x30, 0xa5, 0x13, 0x38, 0x69, 0x23, 0x14, 0xb0, 0xe5, 0x87, 0x8a, 0x88, 0xc2, 0xc7, 0x77, 0x4b, 0xd1, 0x69, 0x39, 0xb5, 0xab, 0xd8, 0x2b, 0x44, 0x29, 0xd6, 0x7b, 0xd7, 0xac, 0x8e, 0x5e, 0xa7, 0xfe, 0x92, 0x4e, 0x20, 0xa6, 0xec, 0x66, 0x22, 0x91, 0xf2, 0x54, 0x8d, 0x73, 0x4f, 0x66, 0x34, 0x86, 0x8b, 0x03, 0x9a, 0xa5, 0xf9, 0xd4, 0xd9, 0x06, 0xb2, 0xd0, 0xcb, 0x85, 0x85, 0xbf, 0x42, 0x85, 0x47, 0xaf, 0xc9, 0x1c, 0x6e, 0x20, 0x52, 0xdd, 0xcd, 0x00, 0x1c, 0x3e, 0xf8, 0xc8, 0xee, 0xfc, 0x3b, 0x6b, 0x2a, 0x82, 0xb6, 0xf9, 0xc8, 0x8c, 0x56, 0xf2, 0xe2, 0xc3, 0xcb, 0x0b, 0xe4, 0xb8, 0x0d, 0xa9, 0x5e, 0xba, 0x37, 0x1d, 0x8b, 0x5f, 0x60, 0xf9, 0x25, 0x38, 0x74, 0x3d, 0xdb, 0xb5, 0xda, 0x29, 0x72, 0xc7, 0x1f, 0xe7, 0xb9, 0xf1, 0xb7, 0x90, 0x26, 0x8a, 0x0e, 0x77, 0x0f, 0xc5, 0xeb, 0x4d, 0x5d, 0xd8, 0x52, 0x47, 0xd4, 0x8a, 0xe2, 0xec, 0x3f, 0x26, 0x25, 0x5a, 0x39, 0x85, 0x52, 0x02, 0x06, 0xa1, 0xf2, 0x68, 0xe4, 0x83, 0xe9, 0xdb, 0xb1, 0xd5, 0xca, 0xb1, 0x90, 0x91, 0x76, 0x06, 0xde, 0x31, 0xe7, 0xc5, 0x18, 0x2d, 0x8f, 0x15, 0x1b, 0xf4, 0x1d, 0xfe, 0xcc, 0xae, 0xd7, 0xcd, 0xe6, 0x90, 0xb2, 0x16, 0x47, 0x10, 0x6b, 0x49, 0x0c, 0x72, 0x9d, 0x54, 0xa8, 0xfe, 0x28, 0x02, 0xa6, 0xd1, 0x26 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.6", + /* Message to be signed */ + 97, + { 0xc1, 0x87, 0x91, 0x5e, 0x4e, 0x87, 0xda, 0x81, 0xc0, 0x8e, 0xd4, 0x35, 0x6a, 0x0c, 0xce, 0xac, 0x1c, 0x4f, 0xb5, 0xc0, 0x46, 0xb4, 0x52, 0x81, 0xb3, 0x87, 0xec, 0x28, 0xf1, 0xab, 0xfd, 0x56, 0x7e, 0x54, 0x6b, 0x23, 0x6b, 0x37, 0xd0, 0x1a, 0xe7, 0x1d, 0x3b, 0x28, 0x34, 0x36, 0x5d, 0x3d, 0xf3, 0x80, 0xb7, 0x50, 0x61, 0xb7, 0x36, 0xb0, 0x13, 0x0b, 0x07, 0x0b, 0xe5, 0x8a, 0xe8, 0xa4, 0x6d, 0x12, 0x16, 0x63, 0x61, 0xb6, 0x13, 0xdb, 0xc4, 0x7d, 0xfa, 0xeb, 0x4c, 0xa7, 0x46, 0x45, 0x6c, 0x2e, 0x88, 0x83, 0x85, 0x52, 0x5c, 0xca, 0x9d, 0xd1, 0xc3, 0xc7, 0xa9, 0xad, 0xa7, 0x6d, 0x6c } +, + /* Signature */ + 256, + { 0x9c, 0xab, 0x74, 0x16, 0x36, 0x08, 0x66, 0x9f, 0x75, 0x55, 0xa3, 0x33, 0xcf, 0x19, 0x6f, 0xe3, 0xa0, 0xe9, 0xe5, 0xeb, 0x1a, 0x32, 0xd3, 0x4b, 0xb5, 0xc8, 0x5f, 0xf6, 0x89, 0xaa, 0xab, 0x0e, 0x3e, 0x65, 0x66, 0x8e, 0xd3, 0xb1, 0x15, 0x3f, 0x94, 0xeb, 0x3d, 0x8b, 0xe3, 0x79, 0xb8, 0xee, 0xf0, 0x07, 0xc4, 0xa0, 0x2c, 0x70, 0x71, 0xce, 0x30, 0xd8, 0xbb, 0x34, 0x1e, 0x58, 0xc6, 0x20, 0xf7, 0x3d, 0x37, 0xb4, 0xec, 0xbf, 0x48, 0xbe, 0x29, 0x4f, 0x6c, 0x9e, 0x0e, 0xcb, 0x5e, 0x63, 0xfe, 0xc4, 0x1f, 0x12, 0x0e, 0x55, 0x53, 0xdf, 0xa0, 0xeb, 0xeb, 0xbb, 0x72, 0x64, 0x0a, 0x95, 0x37, 0xba, 0xdc, 0xb4, 0x51, 0x33, 0x02, 0x29, 0xd9, 0xf7, 0x10, 0xf6, 0x2e, 0x3e, 0xd8, 0xec, 0x78, 0x4e, 0x50, 0xee, 0x1d, 0x92, 0x62, 0xb4, 0x26, 0x71, 0x34, 0x00, 0x11, 0xd7, 0xd0, 0x98, 0xc6, 0xf2, 0x55, 0x7b, 0x21, 0x31, 0xfa, 0x9b, 0xd0, 0x25, 0x46, 0x36, 0x59, 0x7e, 0x88, 0xec, 0xb3, 0x5a, 0x24, 0x0e, 0xf0, 0xfd, 0x85, 0x95, 0x71, 0x24, 0xdf, 0x80, 0x80, 0xfe, 0xe1, 0xe1, 0x49, 0xaf, 0x93, 0x99, 0x89, 0xe8, 0x6b, 0x26, 0xc8, 0x5a, 0x58, 0x81, 0xfa, 0xe8, 0x67, 0x3d, 0x9f, 0xd4, 0x08, 0x00, 0xdd, 0x13, 0x4e, 0xb9, 0xbd, 0xb6, 0x41, 0x0f, 0x42, 0x0b, 0x0a, 0xa9, 0x7b, 0x20, 0xef, 0xcf, 0x2e, 0xb0, 0xc8, 0x07, 0xfa, 0xeb, 0x83, 0xa3, 0xcc, 0xd9, 0xb5, 0x1d, 0x45, 0x53, 0xe4, 0x1d, 0xfc, 0x0d, 0xf6, 0xca, 0x80, 0xa1, 0xe8, 0x1d, 0xc2, 0x34, 0xbb, 0x83, 0x89, 0xdd, 0x19, 0x5a, 0x38, 0xb4, 0x2d, 0xe4, 0xed, 0xc4, 0x9d, 0x34, 0x64, 0x78, 0xb9, 0xf1, 0x1f, 0x05, 0x57, 0x20, 0x5f, 0x5b, 0x0b, 0xd7, 0xff, 0xe9, 0xc8, 0x50, 0xf3, 0x96, 0xd7, 0xc4 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.7", + /* Message to be signed */ + 121, + { 0xab, 0xfa, 0x2e, 0xcb, 0x7d, 0x29, 0xbd, 0x5b, 0xcb, 0x99, 0x31, 0xce, 0x2b, 0xad, 0x2f, 0x74, 0x38, 0x3e, 0x95, 0x68, 0x3c, 0xee, 0x11, 0x02, 0x2f, 0x08, 0xe8, 0xe7, 0xd0, 0xb8, 0xfa, 0x05, 0x8b, 0xf9, 0xeb, 0x7e, 0xb5, 0xf9, 0x88, 0x68, 0xb5, 0xbb, 0x1f, 0xb5, 0xc3, 0x1c, 0xed, 0xa3, 0xa6, 0x4f, 0x1a, 0x12, 0xcd, 0xf2, 0x0f, 0xcd, 0x0e, 0x5a, 0x24, 0x6d, 0x7a, 0x17, 0x73, 0xd8, 0xdb, 0xa0, 0xe3, 0xb2, 0x77, 0x54, 0x5b, 0xab, 0xe5, 0x8f, 0x2b, 0x96, 0xe3, 0xf4, 0xed, 0xc1, 0x8e, 0xab, 0xf5, 0xcd, 0x2a, 0x56, 0x0f, 0xca, 0x75, 0xfe, 0x96, 0xe0, 0x7d, 0x85, 0x9d, 0xef, 0xb2, 0x56, 0x4f, 0x3a, 0x34, 0xf1, 0x6f, 0x11, 0xe9, 0x1b, 0x3a, 0x71, 0x7b, 0x41, 0xaf, 0x53, 0xf6, 0x60, 0x53, 0x23, 0x00, 0x1a, 0xa4, 0x06, 0xc6 } +, + /* Signature */ + 256, + { 0xc4, 0xb4, 0x37, 0xbc, 0xf7, 0x03, 0xf3, 0x52, 0xe1, 0xfa, 0xf7, 0x4e, 0xb9, 0x62, 0x20, 0x39, 0x42, 0x6b, 0x56, 0x72, 0xca, 0xf2, 0xa7, 0xb3, 0x81, 0xc6, 0xc4, 0xf0, 0x19, 0x1e, 0x7e, 0x4a, 0x98, 0xf0, 0xee, 0xbc, 0xd6, 0xf4, 0x17, 0x84, 0xc2, 0x53, 0x7f, 0xf0, 0xf9, 0x9e, 0x74, 0x98, 0x2c, 0x87, 0x20, 0x1b, 0xfb, 0xc6, 0x5e, 0xae, 0x83, 0x2d, 0xb7, 0x1d, 0x16, 0xda, 0xca, 0xdb, 0x09, 0x77, 0xe5, 0xc5, 0x04, 0x67, 0x9e, 0x40, 0xbe, 0x0f, 0x9d, 0xb0, 0x6f, 0xfd, 0x84, 0x8d, 0xd2, 0xe5, 0xc3, 0x8a, 0x7e, 0xc0, 0x21, 0xe7, 0xf6, 0x8c, 0x47, 0xdf, 0xd3, 0x8c, 0xc3, 0x54, 0x49, 0x3d, 0x53, 0x39, 0xb4, 0x59, 0x5a, 0x5b, 0xf3, 0x1e, 0x3f, 0x8f, 0x13, 0x81, 0x68, 0x07, 0x37, 0x3d, 0xf6, 0xad, 0x0d, 0xc7, 0xe7, 0x31, 0xe5, 0x1a, 0xd1, 0x9e, 0xb4, 0x75, 0x4b, 0x13, 0x44, 0x85, 0x84, 0x2f, 0xe7, 0x09, 0xd3, 0x78, 0x44, 0x4d, 0x8e, 0x36, 0xb1, 0x72, 0x4a, 0x4f, 0xda, 0x21, 0xca, 0xfe, 0xe6, 0x53, 0xab, 0x80, 0x74, 0x7f, 0x79, 0x52, 0xee, 0x80, 0x4d, 0xea, 0xb1, 0x03, 0x9d, 0x84, 0x13, 0x99, 0x45, 0xbb, 0xf4, 0xbe, 0x82, 0x00, 0x87, 0x53, 0xf3, 0xc5, 0x4c, 0x78, 0x21, 0xa1, 0xd2, 0x41, 0xf4, 0x21, 0x79, 0xc7, 0x94, 0xef, 0x70, 0x42, 0xbb, 0xf9, 0x95, 0x56, 0x56, 0x22, 0x2e, 0x45, 0xc3, 0x43, 0x69, 0xa3, 0x84, 0x69, 0x7b, 0x6a, 0xe7, 0x42, 0xe1, 0x8f, 0xa5, 0xca, 0x7a, 0xba, 0xd2, 0x7d, 0x9f, 0xe7, 0x10, 0x52, 0xe3, 0x31, 0x0d, 0x0f, 0x52, 0xc8, 0xd1, 0x2e, 0xa3, 0x3b, 0xf0, 0x53, 0xa3, 0x00, 0xf4, 0xaf, 0xc4, 0xf0, 0x98, 0xdf, 0x4e, 0x6d, 0x88, 0x67, 0x79, 0xd6, 0x45, 0x94, 0xd3, 0x69, 0x15, 0x8f, 0xdb, 0xc1, 0xf6, 0x94 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.8", + /* Message to be signed */ + 224, + { 0xdf, 0x40, 0x44, 0xa8, 0x9a, 0x83, 0xe9, 0xfc, 0xbf, 0x12, 0x62, 0x54, 0x0a, 0xe3, 0x03, 0x8b, 0xbc, 0x90, 0xf2, 0xb2, 0x62, 0x8b, 0xf2, 0xa4, 0x46, 0x7a, 0xc6, 0x77, 0x22, 0xd8, 0x54, 0x6b, 0x3a, 0x71, 0xcb, 0x0e, 0xa4, 0x16, 0x69, 0xd5, 0xb4, 0xd6, 0x18, 0x59, 0xc1, 0xb4, 0xe4, 0x7c, 0xec, 0xc5, 0x93, 0x3f, 0x75, 0x7e, 0xc8, 0x6d, 0xb0, 0x64, 0x4e, 0x31, 0x18, 0x12, 0xd0, 0x0f, 0xb8, 0x02, 0xf0, 0x34, 0x00, 0x63, 0x9c, 0x0e, 0x36, 0x4d, 0xae, 0x5a, 0xeb, 0xc5, 0x79, 0x1b, 0xc6, 0x55, 0x76, 0x23, 0x61, 0xbc, 0x43, 0xc5, 0x3d, 0x3c, 0x78, 0x86, 0x76, 0x8f, 0x79, 0x68, 0xc1, 0xc5, 0x44, 0xc6, 0xf7, 0x9f, 0x7b, 0xe8, 0x20, 0xc7, 0xe2, 0xbd, 0x2f, 0x9d, 0x73, 0xe6, 0x2d, 0xed, 0x6d, 0x2e, 0x93, 0x7e, 0x6a, 0x6d, 0xae, 0xf9, 0x0e, 0xe3, 0x7a, 0x1a, 0x52, 0xa5, 0x4f, 0x00, 0xe3, 0x1a, 0xdd, 0xd6, 0x48, 0x94, 0xcf, 0x4c, 0x02, 0xe1, 0x60, 0x99, 0xe2, 0x9f, 0x9e, 0xb7, 0xf1, 0xa7, 0xbb, 0x7f, 0x84, 0xc4, 0x7a, 0x2b, 0x59, 0x48, 0x13, 0xbe, 0x02, 0xa1, 0x7b, 0x7f, 0xc4, 0x3b, 0x34, 0xc2, 0x2c, 0x91, 0x92, 0x52, 0x64, 0x12, 0x6c, 0x89, 0xf8, 0x6b, 0xb4, 0xd8, 0x7f, 0x3e, 0xf1, 0x31, 0x29, 0x6c, 0x53, 0xa3, 0x08, 0xe0, 0x33, 0x1d, 0xac, 0x8b, 0xaf, 0x3b, 0x63, 0x42, 0x22, 0x66, 0xec, 0xef, 0x2b, 0x90, 0x78, 0x15, 0x35, 0xdb, 0xda, 0x41, 0xcb, 0xd0, 0xcf, 0x22, 0xa8, 0xcb, 0xfb, 0x53, 0x2e, 0xc6, 0x8f, 0xc6, 0xaf, 0xb2, 0xac, 0x06 } +, + /* Signature */ + 256, + { 0x14, 0x14, 0xb3, 0x85, 0x67, 0xae, 0x6d, 0x97, 0x3e, 0xde, 0x4a, 0x06, 0x84, 0x2d, 0xcc, 0x0e, 0x05, 0x59, 0xb1, 0x9e, 0x65, 0xa4, 0x88, 0x9b, 0xdb, 0xab, 0xd0, 0xfd, 0x02, 0x80, 0x68, 0x29, 0x13, 0xba, 0xcd, 0x5d, 0xc2, 0xf0, 0x1b, 0x30, 0xbb, 0x19, 0xeb, 0x81, 0x0b, 0x7d, 0x9d, 0xed, 0x32, 0xb2, 0x84, 0xf1, 0x47, 0xbb, 0xe7, 0x71, 0xc9, 0x30, 0xc6, 0x05, 0x2a, 0xa7, 0x34, 0x13, 0x90, 0xa8, 0x49, 0xf8, 0x1d, 0xa9, 0xcd, 0x11, 0xe5, 0xec, 0xcf, 0x24, 0x6d, 0xba, 0xe9, 0x5f, 0xa9, 0x58, 0x28, 0xe9, 0xae, 0x0c, 0xa3, 0x55, 0x03, 0x25, 0x32, 0x6d, 0xee, 0xf9, 0xf4, 0x95, 0x30, 0xba, 0x44, 0x1b, 0xed, 0x4a, 0xc2, 0x9c, 0x02, 0x9c, 0x9a, 0x27, 0x36, 0xb1, 0xa4, 0x19, 0x0b, 0x85, 0x08, 0x4a, 0xd1, 0x50, 0x42, 0x6b, 0x46, 0xd7, 0xf8, 0x5b, 0xd7, 0x02, 0xf4, 0x8d, 0xac, 0x5f, 0x71, 0x33, 0x0b, 0xc4, 0x23, 0xa7, 0x66, 0xc6, 0x5c, 0xc1, 0xdc, 0xab, 0x20, 0xd3, 0xd3, 0xbb, 0xa7, 0x2b, 0x63, 0xb3, 0xef, 0x82, 0x44, 0xd4, 0x2f, 0x15, 0x7c, 0xb7, 0xe3, 0xa8, 0xba, 0x5c, 0x05, 0x27, 0x2c, 0x64, 0xcc, 0x1a, 0xd2, 0x1a, 0x13, 0x49, 0x3c, 0x39, 0x11, 0xf6, 0x0b, 0x4e, 0x9f, 0x4e, 0xcc, 0x99, 0x00, 0xeb, 0x05, 0x6e, 0xe5, 0x9d, 0x6f, 0xe4, 0xb8, 0xff, 0x6e, 0x80, 0x48, 0xcc, 0xc0, 0xf3, 0x8f, 0x28, 0x36, 0xfd, 0x3d, 0xfe, 0x91, 0xbf, 0x4a, 0x38, 0x6e, 0x1e, 0xcc, 0x2c, 0x32, 0x83, 0x9f, 0x0c, 0xa4, 0xd1, 0xb2, 0x7a, 0x56, 0x8f, 0xa9, 0x40, 0xdd, 0x64, 0xad, 0x16, 0xbd, 0x01, 0x25, 0xd0, 0x34, 0x8e, 0x38, 0x30, 0x85, 0xf0, 0x88, 0x94, 0x86, 0x1c, 0xa1, 0x89, 0x87, 0x22, 0x7d, 0x37, 0xb4, 0x2b, 0x58, 0x4a, 0x83, 0x57, 0xcb, 0x04 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.9", + /* Message to be signed */ + 183, + { 0xea, 0x94, 0x1f, 0xf0, 0x6f, 0x86, 0xc2, 0x26, 0x92, 0x7f, 0xcf, 0x0e, 0x3b, 0x11, 0xb0, 0x87, 0x26, 0x76, 0x17, 0x0c, 0x1b, 0xfc, 0x33, 0xbd, 0xa8, 0xe2, 0x65, 0xc7, 0x77, 0x71, 0xf9, 0xd0, 0x85, 0x01, 0x64, 0xa5, 0xee, 0xcb, 0xcc, 0x5c, 0xe8, 0x27, 0xfb, 0xfa, 0x07, 0xc8, 0x52, 0x14, 0x79, 0x6d, 0x81, 0x27, 0xe8, 0xca, 0xa8, 0x18, 0x94, 0xea, 0x61, 0xce, 0xb1, 0x44, 0x9e, 0x72, 0xfe, 0xa0, 0xa4, 0xc9, 0x43, 0xb2, 0xda, 0x6d, 0x9b, 0x10, 0x5f, 0xe0, 0x53, 0xb9, 0x03, 0x9a, 0x9c, 0xc5, 0x3d, 0x42, 0x0b, 0x75, 0x39, 0xfa, 0xb2, 0x23, 0x9c, 0x6b, 0x51, 0xd1, 0x7e, 0x69, 0x4c, 0x95, 0x7d, 0x4b, 0x0f, 0x09, 0x84, 0x46, 0x18, 0x79, 0xa0, 0x75, 0x9c, 0x44, 0x01, 0xbe, 0xec, 0xd4, 0xc6, 0x06, 0xa0, 0xaf, 0xbd, 0x7a, 0x07, 0x6f, 0x50, 0xa2, 0xdf, 0xc2, 0x80, 0x7f, 0x24, 0xf1, 0x91, 0x9b, 0xaa, 0x77, 0x46, 0xd3, 0xa6, 0x4e, 0x26, 0x8e, 0xd3, 0xf5, 0xf8, 0xe6, 0xda, 0x83, 0xa2, 0xa5, 0xc9, 0x15, 0x2f, 0x83, 0x7c, 0xb0, 0x78, 0x12, 0xbd, 0x5b, 0xa7, 0xd3, 0xa0, 0x79, 0x85, 0xde, 0x88, 0x11, 0x3c, 0x17, 0x96, 0xe9, 0xb4, 0x66, 0xec, 0x29, 0x9c, 0x5a, 0xc1, 0x05, 0x9e, 0x27, 0xf0, 0x94, 0x15 } +, + /* Signature */ + 256, + { 0xce, 0xeb, 0x84, 0xcc, 0xb4, 0xe9, 0x09, 0x92, 0x65, 0x65, 0x07, 0x21, 0xee, 0xa0, 0xe8, 0xec, 0x89, 0xca, 0x25, 0xbd, 0x35, 0x4d, 0x4f, 0x64, 0x56, 0x49, 0x67, 0xbe, 0x9d, 0x4b, 0x08, 0xb3, 0xf1, 0xc0, 0x18, 0x53, 0x9c, 0x9d, 0x37, 0x1c, 0xf8, 0x96, 0x1f, 0x22, 0x91, 0xfb, 0xe0, 0xdc, 0x2f, 0x2f, 0x95, 0xfe, 0xa4, 0x7b, 0x63, 0x9f, 0x1e, 0x12, 0xf4, 0xbc, 0x38, 0x1c, 0xef, 0x0c, 0x2b, 0x7a, 0x7b, 0x95, 0xc3, 0xad, 0xf2, 0x76, 0x05, 0xb7, 0xf6, 0x39, 0x98, 0xc3, 0xcb, 0xad, 0x54, 0x28, 0x08, 0xc3, 0x82, 0x2e, 0x06, 0x4d, 0x4a, 0xd1, 0x40, 0x93, 0x67, 0x9e, 0x6e, 0x01, 0x41, 0x8a, 0x6d, 0x5c, 0x05, 0x96, 0x84, 0xcd, 0x56, 0xe3, 0x4e, 0xd6, 0x5a, 0xb6, 0x05, 0xb8, 0xde, 0x4f, 0xcf, 0xa6, 0x40, 0x47, 0x4a, 0x54, 0xa8, 0x25, 0x1b, 0xbb, 0x73, 0x26, 0xa4, 0x2d, 0x08, 0x58, 0x5c, 0xfc, 0xfc, 0x95, 0x67, 0x69, 0xb1, 0x5b, 0x6d, 0x7f, 0xdf, 0x7d, 0xa8, 0x4f, 0x81, 0x97, 0x6e, 0xaa, 0x41, 0xd6, 0x92, 0x38, 0x0f, 0xf1, 0x0e, 0xae, 0xcf, 0xe0, 0xa5, 0x79, 0x68, 0x29, 0x09, 0xb5, 0x52, 0x1f, 0xad, 0xe8, 0x54, 0xd7, 0x97, 0xb8, 0xa0, 0x34, 0x5b, 0x9a, 0x86, 0x4e, 0x05, 0x88, 0xf6, 0xca, 0xdd, 0xbf, 0x65, 0xf1, 0x77, 0x99, 0x8e, 0x18, 0x0d, 0x1f, 0x10, 0x24, 0x43, 0xe6, 0xdc, 0xa5, 0x3a, 0x94, 0x82, 0x3c, 0xaa, 0x9c, 0x3b, 0x35, 0xf3, 0x22, 0x58, 0x3c, 0x70, 0x3a, 0xf6, 0x74, 0x76, 0x15, 0x9e, 0xc7, 0xec, 0x93, 0xd1, 0x76, 0x9b, 0x30, 0x0a, 0xf0, 0xe7, 0x15, 0x7d, 0xc2, 0x98, 0xc6, 0xcd, 0x2d, 0xee, 0x22, 0x62, 0xf8, 0xcd, 0xdc, 0x10, 0xf1, 0x1e, 0x01, 0x74, 0x14, 0x71, 0xbb, 0xfd, 0x65, 0x18, 0xa1, 0x75, 0x73, 0x45, 0x75 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.10", + /* Message to be signed */ + 65, + { 0xd8, 0xb8, 0x16, 0x45, 0xc1, 0x3c, 0xd7, 0xec, 0xf5, 0xd0, 0x0e, 0xd2, 0xc9, 0x1b, 0x9a, 0xcd, 0x46, 0xc1, 0x55, 0x68, 0xe5, 0x30, 0x3c, 0x4a, 0x97, 0x75, 0xed, 0xe7, 0x6b, 0x48, 0x40, 0x3d, 0x6b, 0xe5, 0x6c, 0x05, 0xb6, 0xb1, 0xcf, 0x77, 0xc6, 0xe7, 0x5d, 0xe0, 0x96, 0xc5, 0xcb, 0x35, 0x51, 0xcb, 0x6f, 0xa9, 0x64, 0xf3, 0xc8, 0x79, 0xcf, 0x58, 0x9d, 0x28, 0xe1, 0xda, 0x2f, 0x9d, 0xec } +, + /* Signature */ + 256, + { 0x27, 0x45, 0x07, 0x4c, 0xa9, 0x71, 0x75, 0xd9, 0x92, 0xe2, 0xb4, 0x47, 0x91, 0xc3, 0x23, 0xc5, 0x71, 0x67, 0x16, 0x5c, 0xdd, 0x8d, 0xa5, 0x79, 0xcd, 0xef, 0x46, 0x86, 0xb9, 0xbb, 0x40, 0x4b, 0xd3, 0x6a, 0x56, 0x50, 0x4e, 0xb1, 0xfd, 0x77, 0x0f, 0x60, 0xbf, 0xa1, 0x88, 0xa7, 0xb2, 0x4b, 0x0c, 0x91, 0xe8, 0x81, 0xc2, 0x4e, 0x35, 0xb0, 0x4d, 0xc4, 0xdd, 0x4c, 0xe3, 0x85, 0x66, 0xbc, 0xc9, 0xce, 0x54, 0xf4, 0x9a, 0x17, 0x5f, 0xc9, 0xd0, 0xb2, 0x25, 0x22, 0xd9, 0x57, 0x90, 0x47, 0xf9, 0xed, 0x42, 0xec, 0xa8, 0x3f, 0x76, 0x4a, 0x10, 0x16, 0x39, 0x97, 0x94, 0x7e, 0x7d, 0x2b, 0x52, 0xff, 0x08, 0x98, 0x0e, 0x7e, 0x7c, 0x22, 0x57, 0x93, 0x7b, 0x23, 0xf3, 0xd2, 0x79, 0xd4, 0xcd, 0x17, 0xd6, 0xf4, 0x95, 0x54, 0x63, 0x73, 0xd9, 0x83, 0xd5, 0x36, 0xef, 0xd7, 0xd1, 0xb6, 0x71, 0x81, 0xca, 0x2c, 0xb5, 0x0a, 0xc6, 0x16, 0xc5, 0xc7, 0xab, 0xfb, 0xb9, 0x26, 0x0b, 0x91, 0xb1, 0xa3, 0x8e, 0x47, 0x24, 0x20, 0x01, 0xff, 0x45, 0x2f, 0x8d, 0xe1, 0x0c, 0xa6, 0xea, 0xea, 0xdc, 0xaf, 0x9e, 0xdc, 0x28, 0x95, 0x6f, 0x28, 0xa7, 0x11, 0x29, 0x1f, 0xc9, 0xa8, 0x08, 0x78, 0xb8, 0xba, 0x4c, 0xfe, 0x25, 0xb8, 0x28, 0x1c, 0xb8, 0x0b, 0xc9, 0xcd, 0x6d, 0x2b, 0xd1, 0x82, 0x52, 0x46, 0xee, 0xbe, 0x25, 0x2d, 0x99, 0x57, 0xef, 0x93, 0x70, 0x73, 0x52, 0x08, 0x4e, 0x6d, 0x36, 0xd4, 0x23, 0x55, 0x1b, 0xf2, 0x66, 0xa8, 0x53, 0x40, 0xfb, 0x4a, 0x6a, 0xf3, 0x70, 0x88, 0x0a, 0xab, 0x07, 0x15, 0x3d, 0x01, 0xf4, 0x8d, 0x08, 0x6d, 0xf0, 0xbf, 0xbe, 0xc0, 0x5e, 0x7b, 0x44, 0x3b, 0x97, 0xe7, 0x17, 0x18, 0x97, 0x0e, 0x2f, 0x4b, 0xf6, 0x20, 0x23, 0xe9, 0x5b, 0x67 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.11", + /* Message to be signed */ + 130, + { 0xe5, 0x73, 0x9b, 0x6c, 0x14, 0xc9, 0x2d, 0x51, 0x0d, 0x95, 0xb8, 0x26, 0x93, 0x33, 0x37, 0xff, 0x0d, 0x24, 0xef, 0x72, 0x1a, 0xc4, 0xef, 0x64, 0xc2, 0xba, 0xd2, 0x64, 0xbe, 0x8b, 0x44, 0xef, 0xa1, 0x51, 0x6e, 0x08, 0xa2, 0x7e, 0xb6, 0xb6, 0x11, 0xd3, 0x30, 0x1d, 0xf0, 0x06, 0x2d, 0xae, 0xfc, 0x73, 0xa8, 0xc0, 0xd9, 0x2e, 0x2c, 0x52, 0x1f, 0xac, 0xbc, 0x7b, 0x26, 0x47, 0x38, 0x76, 0x7e, 0xa6, 0xfc, 0x97, 0xd5, 0x88, 0xa0, 0xba, 0xf6, 0xce, 0x50, 0xad, 0xf7, 0x9e, 0x60, 0x0b, 0xd2, 0x9e, 0x34, 0x5f, 0xcb, 0x1d, 0xba, 0x71, 0xac, 0x5c, 0x02, 0x89, 0x02, 0x3f, 0xe4, 0xa8, 0x2b, 0x46, 0xa5, 0x40, 0x77, 0x19, 0x19, 0x7d, 0x2e, 0x95, 0x8e, 0x35, 0x31, 0xfd, 0x54, 0xae, 0xf9, 0x03, 0xaa, 0xbb, 0x43, 0x55, 0xf8, 0x83, 0x18, 0x99, 0x4e, 0xd3, 0xc3, 0xdd, 0x62, 0xf4, 0x20, 0xa7 } +, + /* Signature */ + 256, + { 0xbe, 0x40, 0xa5, 0xfb, 0x94, 0xf1, 0x13, 0xe1, 0xb3, 0xef, 0xf6, 0xb6, 0xa3, 0x39, 0x86, 0xf2, 0x02, 0xe3, 0x63, 0xf0, 0x74, 0x83, 0xb7, 0x92, 0xe6, 0x8d, 0xfa, 0x55, 0x54, 0xdf, 0x04, 0x66, 0xcc, 0x32, 0x15, 0x09, 0x50, 0x78, 0x3b, 0x4d, 0x96, 0x8b, 0x63, 0x9a, 0x04, 0xfd, 0x2f, 0xb9, 0x7f, 0x6e, 0xb9, 0x67, 0x02, 0x1f, 0x5a, 0xdc, 0xcb, 0x9f, 0xca, 0x95, 0xac, 0xc8, 0xf2, 0xcd, 0x88, 0x5a, 0x38, 0x0b, 0x0a, 0x4e, 0x82, 0xbc, 0x76, 0x07, 0x64, 0xdb, 0xab, 0x88, 0xc1, 0xe6, 0xc0, 0x25, 0x5c, 0xaa, 0x94, 0xf2, 0x32, 0x19, 0x9d, 0x6f, 0x59, 0x7c, 0xc9, 0x14, 0x5b, 0x00, 0xe3, 0xd4, 0xba, 0x34, 0x6b, 0x55, 0x9a, 0x88, 0x33, 0xad, 0x15, 0x16, 0xad, 0x51, 0x63, 0xf0, 0x16, 0xaf, 0x6a, 0x59, 0x83, 0x1c, 0x82, 0xea, 0x13, 0xc8, 0x22, 0x4d, 0x84, 0xd0, 0x76, 0x5a, 0x9d, 0x12, 0x38, 0x4d, 0xa4, 0x60, 0xa8, 0x53, 0x1b, 0x4c, 0x40, 0x7e, 0x04, 0xf4, 0xf3, 0x50, 0x70, 0x9e, 0xb9, 0xf0, 0x8f, 0x5b, 0x22, 0x0f, 0xfb, 0x45, 0xab, 0xf6, 0xb7, 0x5d, 0x15, 0x79, 0xfd, 0x3f, 0x1e, 0xb5, 0x5f, 0xc7, 0x5b, 0x00, 0xaf, 0x8b, 0xa3, 0xb0, 0x87, 0x82, 0x7f, 0xe9, 0xae, 0x9f, 0xb4, 0xf6, 0xc5, 0xfa, 0x63, 0x03, 0x1f, 0xe5, 0x82, 0x85, 0x2f, 0xe2, 0x83, 0x4f, 0x9c, 0x89, 0xbf, 0xf5, 0x3e, 0x25, 0x52, 0x21, 0x6b, 0xc7, 0xc1, 0xd4, 0xa3, 0xd5, 0xdc, 0x2b, 0xa6, 0x95, 0x5c, 0xd9, 0xb1, 0x7d, 0x13, 0x63, 0xe7, 0xfe, 0xe8, 0xed, 0x76, 0x29, 0x75, 0x3f, 0xf3, 0x12, 0x5e, 0xdd, 0x48, 0x52, 0x1a, 0xe3, 0xb9, 0xb0, 0x32, 0x17, 0xf4, 0x49, 0x6d, 0x0d, 0x8e, 0xde, 0x57, 0xac, 0xbc, 0x5b, 0xd4, 0xde, 0xae, 0x74, 0xa5, 0x6f, 0x86, 0x67, 0x1d, 0xe2 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.12", + /* Message to be signed */ + 256, + { 0x7a, 0xf4, 0x28, 0x35, 0x91, 0x7a, 0x88, 0xd6, 0xb3, 0xc6, 0x71, 0x6b, 0xa2, 0xf5, 0xb0, 0xd5, 0xb2, 0x0b, 0xd4, 0xe2, 0xe6, 0xe5, 0x74, 0xe0, 0x6a, 0xf1, 0xee, 0xf7, 0xc8, 0x11, 0x31, 0xbe, 0x22, 0xbf, 0x81, 0x28, 0xb9, 0xcb, 0xc6, 0xec, 0x00, 0x27, 0x5b, 0xa8, 0x02, 0x94, 0xa5, 0xd1, 0x17, 0x2d, 0x08, 0x24, 0xa7, 0x9e, 0x8f, 0xdd, 0x83, 0x01, 0x83, 0xe4, 0xc0, 0x0b, 0x96, 0x78, 0x28, 0x67, 0xb1, 0x22, 0x7f, 0xea, 0x24, 0x9a, 0xad, 0x32, 0xff, 0xc5, 0xfe, 0x00, 0x7b, 0xc5, 0x1f, 0x21, 0x79, 0x2f, 0x72, 0x8d, 0xed, 0xa8, 0xb5, 0x70, 0x8a, 0xa9, 0x9c, 0xab, 0xab, 0x20, 0xa4, 0xaa, 0x78, 0x3e, 0xd8, 0x6f, 0x0f, 0x27, 0xb5, 0xd5, 0x63, 0xf4, 0x2e, 0x07, 0x15, 0x8c, 0xea, 0x72, 0xd0, 0x97, 0xaa, 0x68, 0x87, 0xec, 0x41, 0x1d, 0xd0, 0x12, 0x91, 0x2a, 0x5e, 0x03, 0x2b, 0xbf, 0xa6, 0x78, 0x50, 0x71, 0x44, 0xbc, 0xc9, 0x5f, 0x39, 0xb5, 0x8b, 0xe7, 0xbf, 0xd1, 0x75, 0x9a, 0xdb, 0x9a, 0x91, 0xfa, 0x1d, 0x6d, 0x82, 0x26, 0xa8, 0x34, 0x3a, 0x8b, 0x84, 0x9d, 0xae, 0x76, 0xf7, 0xb9, 0x82, 0x24, 0xd5, 0x9e, 0x28, 0xf7, 0x81, 0xf1, 0x3e, 0xce, 0x60, 0x5f, 0x84, 0xf6, 0xc9, 0x0b, 0xae, 0x5f, 0x8c, 0xf3, 0x78, 0x81, 0x6f, 0x40, 0x20, 0xa7, 0xdd, 0xa1, 0xbe, 0xd9, 0x0c, 0x92, 0xa2, 0x36, 0x34, 0xd2, 0x03, 0xfa, 0xc3, 0xfc, 0xd8, 0x6d, 0x68, 0xd3, 0x18, 0x2a, 0x7d, 0x9c, 0xca, 0xbe, 0x7b, 0x07, 0x95, 0xf5, 0xc6, 0x55, 0xe9, 0xac, 0xc4, 0xe3, 0xec, 0x18, 0x51, 0x40, 0xd1, 0x0c, 0xef, 0x05, 0x34, 0x64, 0xab, 0x17, 0x5c, 0x83, 0xbd, 0x83, 0x93, 0x5e, 0x3d, 0xab, 0xaf, 0x34, 0x62, 0xee, 0xbe, 0x63, 0xd1, 0x5f, 0x57, 0x3d, 0x26, 0x9a } +, + /* Signature */ + 256, + { 0x4e, 0x78, 0xc5, 0x90, 0x2b, 0x80, 0x79, 0x14, 0xd1, 0x2f, 0xa5, 0x37, 0xae, 0x68, 0x71, 0xc8, 0x6d, 0xb8, 0x02, 0x1e, 0x55, 0xd1, 0xad, 0xb8, 0xeb, 0x0c, 0xcf, 0x1b, 0x8f, 0x36, 0xab, 0x7d, 0xad, 0x1f, 0x68, 0x2e, 0x94, 0x7a, 0x62, 0x70, 0x72, 0xf0, 0x3e, 0x62, 0x73, 0x71, 0x78, 0x1d, 0x33, 0x22, 0x1d, 0x17, 0x4a, 0xbe, 0x46, 0x0d, 0xbd, 0x88, 0x56, 0x0c, 0x22, 0xf6, 0x90, 0x11, 0x6e, 0x2f, 0xbb, 0xe6, 0xe9, 0x64, 0x36, 0x3a, 0x3e, 0x52, 0x83, 0xbb, 0x5d, 0x94, 0x6e, 0xf1, 0xc0, 0x04, 0x7e, 0xba, 0x03, 0x8c, 0x75, 0x6c, 0x40, 0xbe, 0x79, 0x23, 0x05, 0x58, 0x09, 0xb0, 0xe9, 0xf3, 0x4a, 0x03, 0xa5, 0x88, 0x15, 0xeb, 0xdd, 0xe7, 0x67, 0x93, 0x1f, 0x01, 0x8f, 0x6f, 0x18, 0x78, 0xf2, 0xef, 0x4f, 0x47, 0xdd, 0x37, 0x40, 0x51, 0xdd, 0x48, 0x68, 0x5d, 0xed, 0x6e, 0xfb, 0x3e, 0xa8, 0x02, 0x1f, 0x44, 0xbe, 0x1d, 0x7d, 0x14, 0x93, 0x98, 0xf9, 0x8e, 0xa9, 0xc0, 0x8d, 0x62, 0x88, 0x8e, 0xbb, 0x56, 0x19, 0x2d, 0x17, 0x74, 0x7b, 0x6b, 0x8e, 0x17, 0x09, 0x54, 0x31, 0xf1, 0x25, 0xa8, 0xa8, 0xe9, 0x96, 0x2a, 0xa3, 0x1c, 0x28, 0x52, 0x64, 0xe0, 0x8f, 0xb2, 0x1a, 0xac, 0x33, 0x6c, 0xe6, 0xc3, 0x8a, 0xa3, 0x75, 0xe4, 0x2b, 0xc9, 0x2a, 0xb0, 0xab, 0x91, 0x03, 0x84, 0x31, 0xe1, 0xf9, 0x2c, 0x39, 0xd2, 0xaf, 0x5d, 0xed, 0x7e, 0x43, 0xbc, 0x15, 0x1e, 0x6e, 0xbe, 0xa4, 0xc3, 0xe2, 0x58, 0x3a, 0xf3, 0x43, 0x7e, 0x82, 0xc4, 0x3c, 0x5e, 0x3b, 0x5b, 0x07, 0xcf, 0x03, 0x59, 0x68, 0x3d, 0x22, 0x98, 0xe3, 0x59, 0x48, 0xed, 0x80, 0x6c, 0x06, 0x3c, 0x60, 0x6e, 0xa1, 0x78, 0x15, 0x0b, 0x1e, 0xfc, 0x15, 0x85, 0x69, 0x34, 0xc7, 0x25, 0x5c, 0xfe } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.13", + /* Message to be signed */ + 59, + { 0xeb, 0xae, 0xf3, 0xf9, 0xf2, 0x3b, 0xdf, 0xe5, 0xfa, 0x6b, 0x8a, 0xf4, 0xc2, 0x08, 0xc1, 0x89, 0xf2, 0x25, 0x1b, 0xf3, 0x2f, 0x5f, 0x13, 0x7b, 0x9d, 0xe4, 0x40, 0x63, 0x78, 0x68, 0x6b, 0x3f, 0x07, 0x21, 0xf6, 0x2d, 0x24, 0xcb, 0x86, 0x88, 0xd6, 0xfc, 0x41, 0xa2, 0x7c, 0xba, 0xe2, 0x1d, 0x30, 0xe4, 0x29, 0xfe, 0xac, 0xc7, 0x11, 0x19, 0x41, 0xc2, 0x77 } +, + /* Signature */ + 256, + { 0xc4, 0x8d, 0xbe, 0xf5, 0x07, 0x11, 0x4f, 0x03, 0xc9, 0x5f, 0xaf, 0xbe, 0xb4, 0xdf, 0x1b, 0xfa, 0x88, 0xe0, 0x18, 0x4a, 0x33, 0xcc, 0x4f, 0x8a, 0x9a, 0x10, 0x35, 0xff, 0x7f, 0x82, 0x2a, 0x5e, 0x38, 0xcd, 0xa1, 0x87, 0x23, 0x91, 0x5f, 0xf0, 0x78, 0x24, 0x44, 0x29, 0xe0, 0xf6, 0x08, 0x1c, 0x14, 0xfd, 0x83, 0x33, 0x1f, 0xa6, 0x5c, 0x6b, 0xa7, 0xbb, 0x9a, 0x12, 0xdb, 0xf6, 0x62, 0x23, 0x74, 0xcd, 0x0c, 0xa5, 0x7d, 0xe3, 0x77, 0x4e, 0x2b, 0xd7, 0xae, 0x82, 0x36, 0x77, 0xd0, 0x61, 0xd5, 0x3a, 0xe9, 0xc4, 0x04, 0x0d, 0x2d, 0xa7, 0xef, 0x70, 0x14, 0xf3, 0xbb, 0xdc, 0x95, 0xa3, 0x61, 0xa4, 0x38, 0x55, 0xc8, 0xce, 0x9b, 0x97, 0xec, 0xab, 0xce, 0x17, 0x4d, 0x92, 0x62, 0x85, 0x14, 0x2b, 0x53, 0x4a, 0x30, 0x87, 0xf9, 0xf4, 0xef, 0x74, 0x51, 0x1e, 0xc7, 0x42, 0xb0, 0xd5, 0x68, 0x56, 0x03, 0xfa, 0xf4, 0x03, 0xb5, 0x07, 0x2b, 0x98, 0x5d, 0xf4, 0x6a, 0xdf, 0x2d, 0x25, 0x29, 0xa0, 0x2d, 0x40, 0x71, 0x1e, 0x21, 0x90, 0x91, 0x70, 0x52, 0x37, 0x1b, 0x79, 0xb7, 0x49, 0xb8, 0x3a, 0xbf, 0x0a, 0xe2, 0x94, 0x86, 0xc3, 0xf2, 0xf6, 0x24, 0x77, 0xb2, 0xbd, 0x36, 0x2b, 0x03, 0x9c, 0x01, 0x3c, 0x0c, 0x50, 0x76, 0xef, 0x52, 0x0d, 0xbb, 0x40, 0x5f, 0x42, 0xce, 0xe9, 0x54, 0x25, 0xc3, 0x73, 0xa9, 0x75, 0xe1, 0xcd, 0xd0, 0x32, 0xc4, 0x96, 0x22, 0xc8, 0x50, 0x79, 0xb0, 0x9e, 0x88, 0xda, 0xb2, 0xb1, 0x39, 0x69, 0xef, 0x7a, 0x72, 0x39, 0x73, 0x78, 0x10, 0x40, 0x45, 0x9f, 0x57, 0xd5, 0x01, 0x36, 0x38, 0x48, 0x3d, 0xe2, 0xd9, 0x1c, 0xb3, 0xc4, 0x90, 0xda, 0x81, 0xc4, 0x6d, 0xe6, 0xcd, 0x76, 0xea, 0x8a, 0x0c, 0x8f, 0x6f, 0xe3, 0x31, 0x71, 0x2d, 0x24 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.14", + /* Message to be signed */ + 169, + { 0xc5, 0xa2, 0x71, 0x12, 0x78, 0x76, 0x1d, 0xfc, 0xdd, 0x4f, 0x0c, 0x99, 0xe6, 0xf5, 0x61, 0x9d, 0x6c, 0x48, 0xb5, 0xd4, 0xc1, 0xa8, 0x09, 0x82, 0xfa, 0xa6, 0xb4, 0xcf, 0x1c, 0xf7, 0xa6, 0x0f, 0xf3, 0x27, 0xab, 0xef, 0x93, 0xc8, 0x01, 0x42, 0x9e, 0xfd, 0xe0, 0x86, 0x40, 0x85, 0x81, 0x46, 0x10, 0x56, 0xac, 0xc3, 0x3f, 0x3d, 0x04, 0xf5, 0xad, 0xa2, 0x12, 0x16, 0xca, 0xcd, 0x5f, 0xd1, 0xf9, 0xed, 0x83, 0x20, 0x3e, 0x0e, 0x2f, 0xe6, 0x13, 0x8e, 0x3e, 0xae, 0x84, 0x24, 0xe5, 0x91, 0x5a, 0x08, 0x3f, 0x3f, 0x7a, 0xb7, 0x60, 0x52, 0xc8, 0xbe, 0x55, 0xae, 0x88, 0x2d, 0x6e, 0xc1, 0x48, 0x2b, 0x1e, 0x45, 0xc5, 0xda, 0xe9, 0xf4, 0x10, 0x15, 0x40, 0x53, 0x27, 0x02, 0x2e, 0xc3, 0x2f, 0x0e, 0xa2, 0x42, 0x97, 0x63, 0xb2, 0x55, 0x04, 0x3b, 0x19, 0x58, 0xee, 0x3c, 0xf6, 0xd6, 0x39, 0x83, 0x59, 0x6e, 0xb3, 0x85, 0x84, 0x4f, 0x85, 0x28, 0xcc, 0x9a, 0x98, 0x65, 0x83, 0x5d, 0xc5, 0x11, 0x3c, 0x02, 0xb8, 0x0d, 0x0f, 0xca, 0x68, 0xaa, 0x25, 0xe7, 0x2b, 0xca, 0xae, 0xb3, 0xcf, 0x9d, 0x79, 0xd8, 0x4f, 0x98, 0x4f, 0xd4, 0x17 } +, + /* Signature */ + 256, + { 0x6b, 0xd5, 0x25, 0x7a, 0xa0, 0x66, 0x11, 0xfb, 0x46, 0x60, 0x08, 0x7c, 0xb4, 0xbc, 0x4a, 0x9e, 0x44, 0x91, 0x59, 0xd3, 0x16, 0x52, 0xbd, 0x98, 0x08, 0x44, 0xda, 0xf3, 0xb1, 0xc7, 0xb3, 0x53, 0xf8, 0xe5, 0x61, 0x42, 0xf7, 0xea, 0x98, 0x57, 0x43, 0x3b, 0x18, 0x57, 0x3b, 0x4d, 0xee, 0xde, 0x81, 0x8a, 0x93, 0xb0, 0x29, 0x02, 0x97, 0x78, 0x3f, 0x1a, 0x2f, 0x23, 0xcb, 0xc7, 0x27, 0x97, 0xa6, 0x72, 0x53, 0x7f, 0x01, 0xf6, 0x24, 0x84, 0xcd, 0x41, 0x62, 0xc3, 0x21, 0x4b, 0x9a, 0xc6, 0x28, 0x22, 0x4c, 0x5d, 0xe0, 0x1f, 0x32, 0xbb, 0x9b, 0x76, 0xb2, 0x73, 0x54, 0xf2, 0xb1, 0x51, 0xd0, 0xe8, 0xc4, 0x21, 0x3e, 0x46, 0x15, 0xad, 0x0b, 0xc7, 0x1f, 0x51, 0x5e, 0x30, 0x0d, 0x6a, 0x64, 0xc6, 0x74, 0x34, 0x11, 0xff, 0xfd, 0xe8, 0xe5, 0xff, 0x19, 0x0e, 0x54, 0x92, 0x30, 0x43, 0x12, 0x6e, 0xcf, 0xc4, 0xc4, 0x53, 0x90, 0x22, 0x66, 0x8f, 0xb6, 0x75, 0xf2, 0x5c, 0x07, 0xe2, 0x00, 0x99, 0xee, 0x31, 0x5b, 0x98, 0xd6, 0xaf, 0xec, 0x4b, 0x1a, 0x9a, 0x93, 0xdc, 0x33, 0x49, 0x6a, 0x15, 0xbd, 0x6f, 0xde, 0x16, 0x63, 0xa7, 0xd4, 0x9b, 0x9f, 0x1e, 0x63, 0x9d, 0x38, 0x66, 0x4b, 0x37, 0xa0, 0x10, 0xb1, 0xf3, 0x5e, 0x65, 0x86, 0x82, 0xd9, 0xcd, 0x63, 0xe5, 0x7d, 0xe0, 0xf1, 0x5e, 0x8b, 0xdd, 0x09, 0x65, 0x58, 0xf0, 0x7e, 0xc0, 0xca, 0xa2, 0x18, 0xa8, 0xc0, 0x6f, 0x47, 0x88, 0x45, 0x39, 0x40, 0x28, 0x7c, 0x9d, 0x34, 0xb6, 0xd4, 0x0a, 0x3f, 0x09, 0xbf, 0x77, 0x99, 0xfe, 0x98, 0xae, 0x4e, 0xb4, 0x9f, 0x3f, 0xf4, 0x1c, 0x50, 0x40, 0xa5, 0x0c, 0xef, 0xc9, 0xbd, 0xf2, 0x39, 0x4b, 0x74, 0x9c, 0xf1, 0x64, 0x48, 0x0d, 0xf1, 0xab, 0x68, 0x80, 0x27, 0x3b } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.15", + /* Message to be signed */ + 215, + { 0x9b, 0xf8, 0xaa, 0x25, 0x3b, 0x87, 0x2e, 0xa7, 0x7a, 0x7e, 0x23, 0x47, 0x6b, 0xe2, 0x6b, 0x23, 0x29, 0x57, 0x8c, 0xf6, 0xac, 0x9e, 0xa2, 0x80, 0x5b, 0x35, 0x7f, 0x6f, 0xc3, 0xad, 0x13, 0x0d, 0xba, 0xeb, 0x3d, 0x86, 0x9a, 0x13, 0xcc, 0xe7, 0xa8, 0x08, 0xbb, 0xbb, 0xc9, 0x69, 0x85, 0x7e, 0x03, 0x94, 0x5c, 0x7b, 0xb6, 0x1d, 0xf1, 0xb5, 0xc2, 0x58, 0x9b, 0x8e, 0x04, 0x6c, 0x2a, 0x5d, 0x7e, 0x40, 0x57, 0xb1, 0xa7, 0x4f, 0x24, 0xc7, 0x11, 0x21, 0x63, 0x64, 0x28, 0x85, 0x29, 0xec, 0x95, 0x70, 0xf2, 0x51, 0x97, 0x21, 0x3b, 0xe1, 0xf5, 0xc2, 0xe5, 0x96, 0xf8, 0xbf, 0x8b, 0x2c, 0xf3, 0xcb, 0x38, 0xaa, 0x56, 0xff, 0xe5, 0xe3, 0x1d, 0xf7, 0x39, 0x58, 0x20, 0xe9, 0x4e, 0xcf, 0x3b, 0x11, 0x89, 0xa9, 0x65, 0xdc, 0xf9, 0xa9, 0xcb, 0x42, 0x98, 0xd3, 0xc8, 0x8b, 0x29, 0x23, 0xc1, 0x9f, 0xc6, 0xbc, 0x34, 0xaa, 0xce, 0xca, 0xd4, 0xe0, 0x93, 0x1a, 0x7c, 0x4e, 0x5d, 0x73, 0xdc, 0x86, 0xdf, 0xa7, 0x98, 0xa8, 0x47, 0x6d, 0x82, 0x46, 0x3e, 0xef, 0xaa, 0x90, 0xa8, 0xa9, 0x19, 0x2a, 0xb0, 0x8b, 0x23, 0x08, 0x8d, 0xd5, 0x8e, 0x12, 0x80, 0xf7, 0xd7, 0x2e, 0x45, 0x48, 0x39, 0x6b, 0xaa, 0xc1, 0x12, 0x25, 0x2d, 0xd5, 0xc5, 0x34, 0x6a, 0xdb, 0x20, 0x04, 0xa2, 0xf7, 0x10, 0x1c, 0xcc, 0x89, 0x9c, 0xc7, 0xfa, 0xfa, 0xe8, 0xbb, 0xe2, 0x95, 0x73, 0x88, 0x96, 0xa5, 0xb2, 0x01, 0x22, 0x85, 0x01, 0x4e, 0xf6 } +, + /* Signature */ + 256, + { 0x27, 0xf7, 0xf4, 0xda, 0x9b, 0xd6, 0x10, 0x10, 0x6e, 0xf5, 0x7d, 0x32, 0x38, 0x3a, 0x44, 0x8a, 0x8a, 0x62, 0x45, 0xc8, 0x3d, 0xc1, 0x30, 0x9c, 0x6d, 0x77, 0x0d, 0x35, 0x7b, 0xa8, 0x9e, 0x73, 0xf2, 0xad, 0x08, 0x32, 0x06, 0x2e, 0xb0, 0xfe, 0x0a, 0xc9, 0x15, 0x57, 0x5b, 0xcd, 0x6b, 0x8b, 0xca, 0xdb, 0x4e, 0x2b, 0xa6, 0xfa, 0x9d, 0xa7, 0x3a, 0x59, 0x17, 0x51, 0x52, 0xb2, 0xd4, 0xfe, 0x72, 0xb0, 0x70, 0xc9, 0xb7, 0x37, 0x9e, 0x50, 0x00, 0x0e, 0x55, 0xe6, 0xc2, 0x69, 0xf6, 0x65, 0x8c, 0x93, 0x79, 0x72, 0x79, 0x7d, 0x3a, 0xdd, 0x69, 0xf1, 0x30, 0xe3, 0x4b, 0x85, 0xbd, 0xec, 0x9f, 0x3a, 0x9b, 0x39, 0x22, 0x02, 0xd6, 0xf3, 0xe4, 0x30, 0xd0, 0x9c, 0xac, 0xa8, 0x22, 0x77, 0x59, 0xab, 0x82, 0x5f, 0x70, 0x12, 0xd2, 0xff, 0x4b, 0x5b, 0x62, 0xc8, 0x50, 0x4d, 0xba, 0xd8, 0x55, 0xc0, 0x5e, 0xdd, 0x5c, 0xab, 0x5a, 0x4c, 0xcc, 0xdc, 0x67, 0xf0, 0x1d, 0xd6, 0x51, 0x7c, 0x7d, 0x41, 0xc4, 0x3e, 0x2a, 0x49, 0x57, 0xaf, 0xf1, 0x9d, 0xb6, 0xf1, 0x8b, 0x17, 0x85, 0x9a, 0xf0, 0xbc, 0x84, 0xab, 0x67, 0x14, 0x6e, 0xc1, 0xa4, 0xa6, 0x0a, 0x17, 0xd7, 0xe0, 0x5f, 0x8b, 0x4f, 0x9c, 0xed, 0x6a, 0xd1, 0x09, 0x08, 0xd8, 0xd7, 0x8f, 0x7f, 0xc8, 0x8b, 0x76, 0xad, 0xc8, 0x29, 0x0f, 0x87, 0xda, 0xf2, 0xa7, 0xbe, 0x10, 0xae, 0x40, 0x85, 0x21, 0x39, 0x5d, 0x54, 0xed, 0x25, 0x56, 0xfb, 0x76, 0x61, 0x85, 0x4a, 0x73, 0x0c, 0xe3, 0xd8, 0x2c, 0x71, 0xa8, 0xd4, 0x93, 0xec, 0x49, 0xa3, 0x78, 0xac, 0x8a, 0x3c, 0x74, 0x43, 0x9f, 0x7c, 0xc5, 0x55, 0xba, 0x13, 0xf8, 0x59, 0x07, 0x08, 0x90, 0xee, 0x18, 0xff, 0x65, 0x8f, 0xa4, 0xd7, 0x41, 0x96, 0x9d, 0x70, 0xa5 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.16", + /* Message to be signed */ + 247, + { 0x32, 0x47, 0x48, 0x30, 0xe2, 0x20, 0x37, 0x54, 0xc8, 0xbf, 0x06, 0x81, 0xdc, 0x4f, 0x84, 0x2a, 0xfe, 0x36, 0x09, 0x30, 0x37, 0x86, 0x16, 0xc1, 0x08, 0xe8, 0x33, 0x65, 0x6e, 0x56, 0x40, 0xc8, 0x68, 0x56, 0x88, 0x5b, 0xb0, 0x5d, 0x1e, 0xb9, 0x43, 0x8e, 0xfe, 0xde, 0x67, 0x92, 0x63, 0xde, 0x07, 0xcb, 0x39, 0x55, 0x3f, 0x6a, 0x25, 0xe0, 0x06, 0xb0, 0xa5, 0x23, 0x11, 0xa0, 0x63, 0xca, 0x08, 0x82, 0x66, 0xd2, 0x56, 0x4f, 0xf6, 0x49, 0x0c, 0x46, 0xb5, 0x60, 0x98, 0x18, 0x54, 0x8f, 0x88, 0x76, 0x4d, 0xad, 0x34, 0xa2, 0x5e, 0x3a, 0x85, 0xd5, 0x75, 0x02, 0x3f, 0x0b, 0x9e, 0x66, 0x50, 0x48, 0xa0, 0x3c, 0x35, 0x05, 0x79, 0xa9, 0xd3, 0x24, 0x46, 0xc7, 0xbb, 0x96, 0xcc, 0x92, 0xe0, 0x65, 0xab, 0x94, 0xd3, 0xc8, 0x95, 0x2e, 0x8d, 0xf6, 0x8e, 0xf0, 0xd9, 0xfa, 0x45, 0x6b, 0x3a, 0x06, 0xbb, 0x80, 0xe3, 0xbb, 0xc4, 0xb2, 0x8e, 0x6a, 0x94, 0xb6, 0xd0, 0xff, 0x76, 0x96, 0xa6, 0x4e, 0xfe, 0x05, 0xe7, 0x35, 0xfe, 0xa0, 0x25, 0xd7, 0xbd, 0xbc, 0x41, 0x39, 0xf3, 0xa3, 0xb5, 0x46, 0x07, 0x5c, 0xba, 0x7e, 0xfa, 0x94, 0x73, 0x74, 0xd3, 0xf0, 0xac, 0x80, 0xa6, 0x8d, 0x76, 0x5f, 0x5d, 0xf6, 0x21, 0x0b, 0xca, 0x06, 0x9a, 0x2d, 0x88, 0x64, 0x7a, 0xf7, 0xea, 0x04, 0x2d, 0xac, 0x69, 0x0c, 0xb5, 0x73, 0x78, 0xec, 0x07, 0x77, 0x61, 0x4f, 0xb8, 0xb6, 0x5f, 0xf4, 0x53, 0xca, 0x6b, 0x7d, 0xce, 0x60, 0x98, 0x45, 0x1a, 0x2f, 0x8c, 0x0d, 0xa9, 0xbf, 0xec, 0xf1, 0xfd, 0xf3, 0x91, 0xbb, 0xaa, 0x4e, 0x2a, 0x91, 0xca, 0x18, 0xa1, 0x12, 0x1a, 0x75, 0x23, 0xa2, 0xab, 0xd4, 0x25, 0x14, 0xf4, 0x89, 0xe8 } +, + /* Signature */ + 256, + { 0x69, 0x17, 0x43, 0x72, 0x57, 0xc2, 0x2c, 0xcb, 0x54, 0x03, 0x29, 0x0c, 0x3d, 0xee, 0x82, 0xd9, 0xcf, 0x75, 0x50, 0xb3, 0x1b, 0xd3, 0x1c, 0x51, 0xbd, 0x57, 0xbf, 0xd3, 0x5d, 0x45, 0x2a, 0xb4, 0xdb, 0x7c, 0x4b, 0xe6, 0xb2, 0xe2, 0x5a, 0xc9, 0xa5, 0x9a, 0x1d, 0x2a, 0x7f, 0xeb, 0x62, 0x7f, 0x0a, 0xfd, 0x49, 0x76, 0xb3, 0x00, 0x3c, 0xc9, 0xcf, 0xfd, 0x88, 0x96, 0x50, 0x5e, 0xc3, 0x82, 0xf2, 0x65, 0x10, 0x4d, 0x4c, 0xf8, 0xc9, 0x32, 0xfa, 0x9f, 0xe8, 0x6e, 0x00, 0x87, 0x07, 0x95, 0x99, 0x12, 0x38, 0x9d, 0xa4, 0xb2, 0xd6, 0xb3, 0x69, 0xb3, 0x6a, 0x5e, 0x72, 0xe2, 0x9d, 0x24, 0xc9, 0xa9, 0x8c, 0x9d, 0x31, 0xa3, 0xab, 0x44, 0xe6, 0x43, 0xe6, 0x94, 0x12, 0x66, 0xa4, 0x7a, 0x45, 0xe3, 0x44, 0x6c, 0xe8, 0x77, 0x6a, 0xbe, 0x24, 0x1a, 0x8f, 0x5f, 0xc6, 0x42, 0x3b, 0x24, 0xb1, 0xff, 0x25, 0x0d, 0xc2, 0xc3, 0xa8, 0x17, 0x23, 0x53, 0x56, 0x10, 0x77, 0xe8, 0x50, 0xa7, 0x69, 0xb2, 0x5f, 0x03, 0x25, 0xda, 0xc8, 0x89, 0x65, 0xa3, 0xb9, 0xb4, 0x72, 0xc4, 0x94, 0xe9, 0x5f, 0x71, 0x9b, 0x4e, 0xac, 0x33, 0x2c, 0xaa, 0x7a, 0x65, 0xc7, 0xdf, 0xe4, 0x6d, 0x9a, 0xa7, 0xe6, 0xe0, 0x0f, 0x52, 0x5f, 0x30, 0x3d, 0xd6, 0x3a, 0xb7, 0x91, 0x92, 0x18, 0x90, 0x18, 0x68, 0xf9, 0x33, 0x7f, 0x8c, 0xd2, 0x6a, 0xaf, 0xe6, 0xf3, 0x3b, 0x7f, 0xb2, 0xc9, 0x88, 0x10, 0xaf, 0x19, 0xf7, 0xfc, 0xb2, 0x82, 0xba, 0x15, 0x77, 0x91, 0x2c, 0x1d, 0x36, 0x89, 0x75, 0xfd, 0x5d, 0x44, 0x0b, 0x86, 0xe1, 0x0c, 0x19, 0x97, 0x15, 0xfa, 0x0b, 0x6f, 0x42, 0x50, 0xb5, 0x33, 0x73, 0x2d, 0x0b, 0xef, 0xe1, 0x54, 0x51, 0x50, 0xfc, 0x47, 0xb8, 0x76, 0xde, 0x09, 0xb0, 0x0a, 0x94 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.17", + /* Message to be signed */ + 61, + { 0x00, 0x8e, 0x59, 0x50, 0x5e, 0xaf, 0xb5, 0x50, 0xaa, 0xe5, 0xe8, 0x45, 0x58, 0x4c, 0xeb, 0xb0, 0x0b, 0x6d, 0xe1, 0x73, 0x3e, 0x9f, 0x95, 0xd4, 0x2c, 0x88, 0x2a, 0x5b, 0xbe, 0xb5, 0xce, 0x1c, 0x57, 0xe1, 0x19, 0xe7, 0xc0, 0xd4, 0xda, 0xca, 0x9f, 0x1f, 0xf7, 0x87, 0x02, 0x17, 0xf7, 0xcf, 0xd8, 0xa6, 0xb3, 0x73, 0x97, 0x7c, 0xac, 0x9c, 0xab, 0x8e, 0x71, 0xe4, 0x20 } +, + /* Signature */ + 256, + { 0x92, 0x25, 0x03, 0xb6, 0x73, 0xee, 0x5f, 0x3e, 0x69, 0x1e, 0x1c, 0xa8, 0x5e, 0x9f, 0xf4, 0x17, 0x3c, 0xf7, 0x2b, 0x05, 0xac, 0x2c, 0x13, 0x1d, 0xa5, 0x60, 0x35, 0x93, 0xe3, 0xbc, 0x25, 0x9c, 0x94, 0xc1, 0xf7, 0xd3, 0xa0, 0x6a, 0x5b, 0x98, 0x91, 0xbf, 0x11, 0x3f, 0xa3, 0x9e, 0x59, 0xff, 0x7c, 0x1e, 0xd6, 0x46, 0x5e, 0x90, 0x80, 0x49, 0xcb, 0x89, 0xe4, 0xe1, 0x25, 0xcd, 0x37, 0xd2, 0xff, 0xd9, 0x22, 0x7a, 0x41, 0xb4, 0xa0, 0xa1, 0x9c, 0x0a, 0x44, 0xfb, 0xbf, 0x3d, 0xe5, 0x5b, 0xab, 0x80, 0x20, 0x87, 0xa3, 0xbb, 0x8d, 0x4f, 0xf6, 0x68, 0xee, 0x6b, 0xbb, 0x8a, 0xd8, 0x9e, 0x68, 0x57, 0xa7, 0x9a, 0x9c, 0x72, 0x78, 0x19, 0x90, 0xdf, 0xcf, 0x92, 0xcd, 0x51, 0x94, 0x04, 0xc9, 0x50, 0xf1, 0x3d, 0x11, 0x43, 0xc3, 0x18, 0x4f, 0x1d, 0x25, 0x0c, 0x90, 0xe1, 0x7a, 0xc6, 0xce, 0x36, 0x16, 0x3b, 0x98, 0x95, 0x62, 0x7a, 0xd6, 0xff, 0xec, 0x14, 0x22, 0x44, 0x1f, 0x55, 0xe4, 0x49, 0x9d, 0xba, 0x9b, 0xe8, 0x95, 0x46, 0xae, 0x8b, 0xc6, 0x3c, 0xca, 0x01, 0xdd, 0x08, 0x46, 0x3a, 0xe7, 0xf1, 0xfc, 0xe3, 0xd8, 0x93, 0x99, 0x69, 0x38, 0x77, 0x8c, 0x18, 0x12, 0xe6, 0x74, 0xad, 0x9c, 0x30, 0x9c, 0x5a, 0xcc, 0xa3, 0xfd, 0xe4, 0x4e, 0x7d, 0xd8, 0x69, 0x59, 0x93, 0xe9, 0xc1, 0xfa, 0x87, 0xac, 0xda, 0x99, 0xec, 0xe5, 0xc8, 0x49, 0x9e, 0x46, 0x89, 0x57, 0xad, 0x66, 0x35, 0x9b, 0xf1, 0x2a, 0x51, 0xad, 0xbe, 0x78, 0xd3, 0xa2, 0x13, 0xb4, 0x49, 0xbf, 0x0b, 0x5f, 0x8d, 0x4d, 0x49, 0x6a, 0xcf, 0x03, 0xd3, 0x03, 0x3b, 0x7c, 0xcd, 0x19, 0x6b, 0xc2, 0x2f, 0x68, 0xfb, 0x7b, 0xef, 0x4f, 0x69, 0x7c, 0x5e, 0xa2, 0xb3, 0x50, 0x62, 0xf4, 0x8a, 0x36, 0xdd } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.18", + /* Message to be signed */ + 69, + { 0x6a, 0xbc, 0x54, 0xcf, 0x8d, 0x1d, 0xff, 0x1f, 0x53, 0xb1, 0x7d, 0x81, 0x60, 0x36, 0x88, 0x78, 0xa8, 0x78, 0x8c, 0xc6, 0xd2, 0x2f, 0xa5, 0xc2, 0x25, 0x8c, 0x88, 0xe6, 0x60, 0xb0, 0x9a, 0x89, 0x33, 0xf9, 0xf2, 0xc0, 0x50, 0x4d, 0xda, 0xdc, 0x21, 0xf6, 0xe7, 0x5e, 0x0b, 0x83, 0x3b, 0xeb, 0x55, 0x52, 0x29, 0xde, 0xe6, 0x56, 0xb9, 0x04, 0x7b, 0x92, 0xf6, 0x2e, 0x76, 0xb8, 0xff, 0xcc, 0x60, 0xda, 0xb0, 0x6b, 0x80 } +, + /* Signature */ + 256, + { 0x0b, 0x6d, 0xaf, 0x42, 0xf7, 0xa8, 0x62, 0x14, 0x7e, 0x41, 0x74, 0x93, 0xc2, 0xc4, 0x01, 0xef, 0xae, 0x32, 0x63, 0x6a, 0xb4, 0xcb, 0xd4, 0x41, 0x92, 0xbb, 0xf5, 0xf1, 0x95, 0xb5, 0x0a, 0xe0, 0x96, 0xa4, 0x75, 0xa1, 0x61, 0x4f, 0x0a, 0x9f, 0xa8, 0xf7, 0xa0, 0x26, 0xcb, 0x46, 0xc6, 0x50, 0x6e, 0x51, 0x8e, 0x33, 0xd8, 0x3e, 0x56, 0x47, 0x7a, 0x87, 0x5a, 0xca, 0x8c, 0x7e, 0x71, 0x4c, 0xe1, 0xbd, 0xbd, 0x61, 0xef, 0x5d, 0x53, 0x52, 0x39, 0xb3, 0x3f, 0x2b, 0xfd, 0xd6, 0x17, 0x71, 0xba, 0xb6, 0x27, 0x76, 0xd7, 0x81, 0x71, 0xa1, 0x42, 0x3c, 0xea, 0x87, 0x31, 0xf8, 0x2e, 0x60, 0x76, 0x6d, 0x64, 0x54, 0x26, 0x56, 0x20, 0xb1, 0x5f, 0x5c, 0x5a, 0x58, 0x4f, 0x55, 0xf9, 0x5b, 0x80, 0x2f, 0xe7, 0x8c, 0x57, 0x4e, 0xd5, 0xda, 0xcf, 0xc8, 0x31, 0xf3, 0xcf, 0x2b, 0x05, 0x02, 0xc0, 0xb2, 0x98, 0xf2, 0x5c, 0xcf, 0x11, 0xf9, 0x73, 0xb3, 0x1f, 0x85, 0xe4, 0x74, 0x42, 0x19, 0x85, 0xf3, 0xcf, 0xf7, 0x02, 0xdf, 0x39, 0x46, 0xef, 0x0a, 0x66, 0x05, 0x68, 0x21, 0x11, 0xb2, 0xf5, 0x5b, 0x1f, 0x8a, 0xb0, 0xd2, 0xea, 0x3a, 0x68, 0x3c, 0x69, 0x98, 0x5e, 0xad, 0x93, 0xed, 0x44, 0x9e, 0xa4, 0x8f, 0x03, 0x58, 0xdd, 0xf7, 0x08, 0x02, 0xcb, 0x41, 0xde, 0x2f, 0xd8, 0x3f, 0x3c, 0x80, 0x80, 0x82, 0xd8, 0x49, 0x36, 0x94, 0x8e, 0x0c, 0x84, 0xa1, 0x31, 0xb4, 0x92, 0x78, 0x27, 0x46, 0x05, 0x27, 0xbb, 0x5c, 0xd2, 0x4b, 0xfa, 0xb7, 0xb4, 0x8e, 0x07, 0x1b, 0x24, 0x17, 0x19, 0x30, 0xf9, 0x97, 0x63, 0x27, 0x2f, 0x97, 0x97, 0xbc, 0xb7, 0x6f, 0x1d, 0x24, 0x81, 0x57, 0x55, 0x58, 0xfc, 0xf2, 0x60, 0xb1, 0xf0, 0xe5, 0x54, 0xeb, 0xb3, 0xdf, 0x3c, 0xfc, 0xb9, 0x58 } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.19", + /* Message to be signed */ + 177, + { 0xaf, 0x2d, 0x78, 0x15, 0x2c, 0xf1, 0x0e, 0xfe, 0x01, 0xd2, 0x74, 0xf2, 0x17, 0xb1, 0x77, 0xf6, 0xb0, 0x1b, 0x5e, 0x74, 0x9f, 0x15, 0x67, 0x71, 0x5d, 0xa3, 0x24, 0x85, 0x9c, 0xd3, 0xdd, 0x88, 0xdb, 0x84, 0x8e, 0xc7, 0x9f, 0x48, 0xdb, 0xba, 0x7b, 0x6f, 0x1d, 0x33, 0x11, 0x1e, 0xf3, 0x1b, 0x64, 0x89, 0x9e, 0x73, 0x91, 0xc2, 0xbf, 0xfd, 0x69, 0xf4, 0x90, 0x25, 0xcf, 0x20, 0x1f, 0xc5, 0x85, 0xdb, 0xd1, 0x54, 0x2c, 0x1c, 0x77, 0x8a, 0x2c, 0xe7, 0xa7, 0xee, 0x10, 0x8a, 0x30, 0x9f, 0xec, 0xa2, 0x6d, 0x13, 0x3a, 0x5f, 0xfe, 0xdc, 0x4e, 0x86, 0x9d, 0xcd, 0x76, 0x56, 0x59, 0x6a, 0xc8, 0x42, 0x7e, 0xa3, 0xef, 0x6e, 0x3f, 0xd7, 0x8f, 0xe9, 0x9d, 0x8d, 0xdc, 0x71, 0xd8, 0x39, 0xf6, 0x78, 0x6e, 0x0d, 0xa6, 0xe7, 0x86, 0xbd, 0x62, 0xb3, 0xa4, 0xf1, 0x9b, 0x89, 0x1a, 0x56, 0x15, 0x7a, 0x55, 0x4e, 0xc2, 0xa2, 0xb3, 0x9e, 0x25, 0xa1, 0xd7, 0xc7, 0xd3, 0x73, 0x21, 0xc7, 0xa1, 0xd9, 0x46, 0xcf, 0x4f, 0xbe, 0x75, 0x8d, 0x92, 0x76, 0xf0, 0x85, 0x63, 0x44, 0x9d, 0x67, 0x41, 0x4a, 0x2c, 0x03, 0x0f, 0x42, 0x51, 0xcf, 0xe2, 0x21, 0x3d, 0x04, 0xa5, 0x41, 0x06, 0x37, 0x87 } +, + /* Signature */ + 256, + { 0x20, 0x9c, 0x61, 0x15, 0x78, 0x57, 0x38, 0x7b, 0x71, 0xe2, 0x4b, 0xf3, 0xdd, 0x56, 0x41, 0x45, 0x50, 0x50, 0x3b, 0xec, 0x18, 0x0f, 0xf5, 0x3b, 0xdd, 0x9b, 0xac, 0x06, 0x2a, 0x2d, 0x49, 0x95, 0x09, 0xbf, 0x99, 0x12, 0x81, 0xb7, 0x95, 0x27, 0xdf, 0x91, 0x36, 0x61, 0x5b, 0x7a, 0x6d, 0x9d, 0xb3, 0xa1, 0x03, 0xb5, 0x35, 0xe0, 0x20, 0x2a, 0x2c, 0xac, 0xa1, 0x97, 0xa7, 0xb7, 0x4e, 0x53, 0x56, 0xf3, 0xdd, 0x59, 0x5b, 0x49, 0xac, 0xfd, 0x9d, 0x30, 0x04, 0x9a, 0x98, 0xca, 0x88, 0xf6, 0x25, 0xbc, 0xa1, 0xd5, 0xf2, 0x2a, 0x39, 0x2d, 0x8a, 0x74, 0x9e, 0xfb, 0x6e, 0xed, 0x9b, 0x78, 0x21, 0xd3, 0x11, 0x0a, 0xc0, 0xd2, 0x44, 0x19, 0x9e, 0xcb, 0x4a, 0xa3, 0xd7, 0x35, 0xa8, 0x3a, 0x2e, 0x88, 0x93, 0xc6, 0xbf, 0x85, 0x81, 0x38, 0x3c, 0xca, 0xee, 0x83, 0x46, 0x35, 0xb7, 0xfa, 0x1f, 0xaf, 0xfa, 0x45, 0xb1, 0x3d, 0x15, 0xc1, 0xda, 0x33, 0xaf, 0x71, 0xe8, 0x93, 0x03, 0xd6, 0x80, 0x90, 0xff, 0x62, 0xee, 0x61, 0x5f, 0xdf, 0x5a, 0x84, 0xd1, 0x20, 0x71, 0x1d, 0xa5, 0x3c, 0x28, 0x89, 0x19, 0x8a, 0xb3, 0x83, 0x17, 0xa9, 0x73, 0x4a, 0xb2, 0x7d, 0x67, 0x92, 0x4c, 0xea, 0x74, 0x15, 0x6f, 0xf9, 0x9b, 0xef, 0x98, 0x76, 0xbb, 0x5c, 0x33, 0x9e, 0x93, 0x74, 0x52, 0x83, 0xe1, 0xb3, 0x4e, 0x07, 0x22, 0x26, 0xb8, 0x80, 0x45, 0xe0, 0x17, 0xe9, 0xf0, 0x5b, 0x2a, 0x8c, 0x41, 0x67, 0x40, 0x25, 0x8e, 0x22, 0x3b, 0x26, 0x90, 0x02, 0x74, 0x91, 0x73, 0x22, 0x73, 0xf3, 0x22, 0x9d, 0x9e, 0xf2, 0xb1, 0xb3, 0x80, 0x7e, 0x32, 0x10, 0x18, 0x92, 0x0a, 0xd3, 0xe5, 0x3d, 0xae, 0x47, 0xe6, 0xd9, 0x39, 0x5c, 0x18, 0x4b, 0x93, 0xa3, 0x74, 0xc6, 0x71, 0xfa, 0xa2, 0xce } + +} +, +{ + "PKCS#1 v1.5 Signature Example 15.20", + /* Message to be signed */ + 179, + { 0x40, 0xee, 0x99, 0x24, 0x58, 0xd6, 0xf6, 0x14, 0x86, 0xd2, 0x56, 0x76, 0xa9, 0x6d, 0xd2, 0xcb, 0x93, 0xa3, 0x7f, 0x04, 0xb1, 0x78, 0x48, 0x2f, 0x2b, 0x18, 0x6c, 0xf8, 0x82, 0x15, 0x27, 0x0d, 0xba, 0x29, 0xd7, 0x86, 0xd7, 0x74, 0xb0, 0xc5, 0xe7, 0x8c, 0x7f, 0x6e, 0x56, 0xa9, 0x56, 0xe7, 0xf7, 0x39, 0x50, 0xa2, 0xb0, 0xc0, 0xc1, 0x0a, 0x08, 0xdb, 0xcd, 0x67, 0xe5, 0xb2, 0x10, 0xbb, 0x21, 0xc5, 0x8e, 0x27, 0x67, 0xd4, 0x4f, 0x7d, 0xd4, 0x01, 0x4e, 0x39, 0x66, 0x14, 0x3b, 0xf7, 0xe3, 0xd6, 0x6f, 0xf0, 0xc0, 0x9b, 0xe4, 0xc5, 0x5f, 0x93, 0xb3, 0x99, 0x94, 0xb8, 0x51, 0x8d, 0x9c, 0x1d, 0x76, 0xd5, 0xb4, 0x73, 0x74, 0xde, 0xa0, 0x8f, 0x15, 0x7d, 0x57, 0xd7, 0x06, 0x34, 0x97, 0x8f, 0x38, 0x56, 0xe0, 0xe5, 0xb4, 0x81, 0xaf, 0xbb, 0xdb, 0x5a, 0x3a, 0xc4, 0x8d, 0x48, 0x4b, 0xe9, 0x2c, 0x93, 0xde, 0x22, 0x91, 0x78, 0x35, 0x4c, 0x2d, 0xe5, 0x26, 0xe9, 0xc6, 0x5a, 0x31, 0xed, 0xe1, 0xef, 0x68, 0xcb, 0x63, 0x98, 0xd7, 0x91, 0x16, 0x84, 0xfe, 0xc0, 0xba, 0xbc, 0x3a, 0x78, 0x1a, 0x66, 0x66, 0x07, 0x83, 0x50, 0x69, 0x74, 0xd0, 0xe1, 0x48, 0x25, 0x10, 0x1c, 0x3b, 0xfa, 0xea } +, + /* Signature */ + 256, + { 0x92, 0x75, 0x02, 0xb8, 0x24, 0xaf, 0xc4, 0x25, 0x13, 0xca, 0x65, 0x70, 0xde, 0x33, 0x8b, 0x8a, 0x64, 0xc3, 0xa8, 0x5e, 0xb8, 0x28, 0xd3, 0x19, 0x36, 0x24, 0xf2, 0x7e, 0x8b, 0x10, 0x29, 0xc5, 0x5c, 0x11, 0x9c, 0x97, 0x33, 0xb1, 0x8f, 0x58, 0x49, 0xb3, 0x50, 0x09, 0x18, 0xbc, 0xc0, 0x05, 0x51, 0xd9, 0xa8, 0xfd, 0xf5, 0x3a, 0x97, 0x74, 0x9f, 0xa8, 0xdc, 0x48, 0x0d, 0x6f, 0xe9, 0x74, 0x2a, 0x58, 0x71, 0xf9, 0x73, 0x92, 0x65, 0x28, 0x97, 0x2a, 0x1a, 0xf4, 0x9e, 0x39, 0x25, 0xb0, 0xad, 0xf1, 0x4a, 0x84, 0x27, 0x19, 0xb4, 0xa5, 0xa2, 0xd8, 0x9f, 0xa9, 0xc0, 0xb6, 0x60, 0x5d, 0x21, 0x2b, 0xed, 0x1e, 0x67, 0x23, 0xb9, 0x34, 0x06, 0xad, 0x30, 0xe8, 0x68, 0x29, 0xa5, 0xc7, 0x19, 0xb8, 0x90, 0xb3, 0x89, 0x30, 0x6d, 0xc5, 0x50, 0x64, 0x86, 0xee, 0x2f, 0x36, 0xa8, 0xdf, 0xe0, 0xa9, 0x6a, 0xf6, 0x78, 0xc9, 0xcb, 0xd6, 0xaf, 0xf3, 0x97, 0xca, 0x20, 0x0e, 0x3e, 0xdc, 0x1e, 0x36, 0xbd, 0x2f, 0x08, 0xb3, 0x1d, 0x54, 0x0c, 0x0c, 0xb2, 0x82, 0xa9, 0x55, 0x9e, 0x4a, 0xdd, 0x4f, 0xc9, 0xe6, 0x49, 0x2e, 0xed, 0x0c, 0xcb, 0xd3, 0xa6, 0x98, 0x2e, 0x5f, 0xaa, 0x2d, 0xdd, 0x17, 0xbe, 0x47, 0x41, 0x7c, 0x80, 0xb4, 0xe5, 0x45, 0x2d, 0x31, 0xf7, 0x24, 0x01, 0xa0, 0x42, 0x32, 0x51, 0x09, 0x54, 0x4d, 0x95, 0x4c, 0x01, 0x93, 0x90, 0x79, 0xd4, 0x09, 0xa5, 0xc3, 0x78, 0xd7, 0x51, 0x2d, 0xfc, 0x2d, 0x2a, 0x71, 0xef, 0xcc, 0x34, 0x32, 0xa7, 0x65, 0xd1, 0xc6, 0xa5, 0x2c, 0xfc, 0xe8, 0x99, 0xcd, 0x79, 0xb1, 0x5b, 0x4f, 0xc3, 0x72, 0x36, 0x41, 0xef, 0x6b, 0xd0, 0x0a, 0xcc, 0x10, 0x40, 0x7e, 0x5d, 0xf5, 0x8d, 0xd1, 0xc3, 0xc5, 0xc5, 0x59, 0xa5, 0x06 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +}; + diff --git a/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.txt b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.txt new file mode 100644 index 0000000..cc8ee38 --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/pkcs1v15sign-vectors.txt @@ -0,0 +1,9049 @@ +Test vectors for RSA PKCS#1 v1.5 Signature +========================================== + +This file contains test vectors for the PKCS#1 v1.5 signature +scheme with appendix. 15 RSA keys of different sizes have +been generated. For each key, 20 random messages of length +between 1 and 256 octets have been PKCS#1 v1.5 signed. +As specified in PKCS#1, the block type for this operation +is 1. The digest algorithm is SHA-1; i.e. the given message +must be hashed and the SHA-1 hash must be encapsulated in a +DigestInfo structure as specified in PKCS#1 v1.5. + +Key lengths: + +Key 1: 1024 bits +Key 2: 1024 bits +Key 3: 1024 bits +Key 4: 1024 bits +Key 5: 1024 bits +Key 6: 1024 bits +Key 7: 1025 bits +Key 8: 1026 bits +Key 9: 1027 bits +Key 10: 1028 bits +Key 11: 1029 bits +Key 12: 1030 bits +Key 13: 1031 bits +Key 14: 1536 bits +Key 15: 2048 bits + +These test vectors have been derived from the PSS test vectors. +============================================================================ +# Thirteen RSA keys with bit sizes between 1024 and 1031, one 1536-bit key, +# and one 2048-bit key are generated. + +# For each key, 20 random messages are PKCS#1 v1.5 signed. + +# Example 1: A 1024-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 +56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 +d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 +94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df +d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 +c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 +05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 +ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 +56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 +d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 +94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df +d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 +c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 +05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 +ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 + +# Public exponent: +01 00 01 + +# Exponent: +33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47 +71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8 +94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8 +c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a +e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27 +a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c +31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b +d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25 + +# Prime 1: +e7 e8 94 27 20 a8 77 51 72 73 a3 56 05 3e a2 a1 +bc 0c 94 aa 72 d5 5c 6e 86 29 6b 2d fc 96 79 48 +c0 a7 2c bc cc a7 ea cb 35 70 6e 09 a1 df 55 a1 +53 5b d9 b3 cc 34 16 0b 3b 6d cd 3e da 8e 64 43 + +# Prime 2: +b6 9d ca 1c f7 d4 d7 ec 81 e7 5b 90 fc ca 87 4a +bc de 12 3f d2 70 01 80 aa 90 47 9b 6e 48 de 8d +67 ed 24 f9 f1 9d 85 ba 27 58 74 f5 42 cd 20 dc +72 3e 69 63 36 4a 1f 94 25 45 2b 26 9a 67 99 fd + +# Prime exponent 1: +28 fa 13 93 86 55 be 1f 8a 15 9c ba ca 5a 72 ea +19 0c 30 08 9e 19 cd 27 4a 55 6f 36 c4 f6 e1 9f +55 4b 34 c0 77 79 04 27 bb dd 8d d3 ed e2 44 83 +28 f3 85 d8 1b 30 e8 e4 3b 2f ff a0 27 86 19 79 + +# Prime exponent 2: +1a 8b 38 f3 98 fa 71 20 49 89 8d 7f b7 9e e0 a7 +76 68 79 12 99 cd fa 09 ef c0 e5 07 ac b2 1e d7 +43 01 ef 5b fd 48 be 45 5e ae b6 e1 67 82 55 82 +75 80 a8 e4 e8 e1 41 51 d1 51 0a 82 a3 f2 e7 29 + +# Coefficient: +27 15 6a ba 41 26 d2 4a 81 f3 a5 28 cb fb 27 f5 +68 86 f8 40 a9 f6 e8 6e 17 a4 4b 94 fe 93 19 58 +4b 8e 22 fd de 1e 5a 2e 3b d8 aa 5b a8 d8 58 41 +94 eb 21 90 ac f8 32 b8 47 f1 3a 3d 24 a7 9f 4d + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 1.1 + +# ----------------- + +# Message to be signed: +cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26 +d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6 +23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15 +6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76 +97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3 +d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0 +61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29 +cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61 +93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08 +a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c +29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca +b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16 +be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed +1b 73 31 8b 75 0a 01 67 d0 + +# Signature: +6b c3 a0 66 56 84 29 30 a2 47 e3 0d 58 64 b4 d8 +19 23 6b a7 c6 89 65 86 2a d7 db c4 e2 4a f2 8e +86 bb 53 1f 03 35 8b e5 fb 74 77 7c 60 86 f8 50 +ca ef 89 3f 0d 6f cc 2d 0c 91 ec 01 36 93 b4 ea +00 b8 0c d4 9a ac 4e cb 5f 89 11 af e5 39 ad a4 +a8 f3 82 3d 1d 13 e4 72 d1 49 05 47 c6 59 c7 61 +7f 3d 24 08 7d db 6f 2b 72 09 61 67 fc 09 7c ab +18 e9 a4 58 fc b6 34 cd ce 8e e3 58 94 c4 84 d7 + +# PKCS#1 v1.5 Signature Example 1.2 + +# ----------------- + +# Message to be signed: +85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c +f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f +71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13 +22 6b 9e + +# Signature: +84 fd 2c e7 34 ec 1d a8 28 d0 f1 5b f4 9a 87 07 +c1 5d 05 94 81 36 de 53 7a 3d b4 21 38 41 67 c8 +6f ae 02 25 87 ee 9e 13 7d ae e7 54 73 82 62 93 +2d 27 1c 74 4c 6d 3a 18 9a d4 31 1b db 02 04 92 +e3 22 fb dd c4 04 06 ea 86 0d 4e 8e a2 a4 08 4a +a9 8b 96 22 a4 46 75 6f db 74 0d db 3d 91 db 76 +70 e2 11 66 1b bf 87 09 b1 1c 08 a7 07 71 42 2d +1a 12 de f2 9f 06 88 a1 92 ae bd 89 e0 f8 96 f8 + +# PKCS#1 v1.5 Signature Example 1.3 + +# ----------------- + +# Message to be signed: +a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5 +aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef +8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d +fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55 +fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db +43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7 +45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29 +c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4 +56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17 +be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c +03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b +79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa +29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61 +8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13 +38 e7 d4 70 + +# Signature: +0b 1f 2e 51 80 e5 c7 b4 b5 e6 72 92 9f 66 4c 48 +96 e5 0c 35 13 4b 6d e4 d5 a9 34 25 2a 3a 24 5f +f4 83 40 92 0e 10 34 b7 d5 a5 b5 24 eb 0e 1c f1 +2b ef ef 49 b2 7b 73 2d 2c 19 e1 c4 32 17 d6 e1 +41 73 81 11 1a 1d 36 de 63 75 cf 45 5b 3c 98 12 +63 9d bc 27 60 0c 75 19 94 fb 61 79 9e cf 7d a6 +bc f5 15 40 af d0 17 4d b4 03 31 88 55 66 75 b1 +d7 63 36 0a f4 6f ee ca 5b 60 f8 82 82 9e e7 b2 + +# PKCS#1 v1.5 Signature Example 1.4 + +# ----------------- + +# Message to be signed: +bc 65 67 47 fa 9e af b3 f0 + +# Signature: +45 60 7a d6 11 cf 57 47 a4 1a c9 4d 0f fe c8 78 +bd af 63 f6 b5 7a 4b 08 8b f3 6e 34 e1 09 f8 40 +f2 4b 74 2a da 16 10 2d ab f9 51 cb c4 4f 89 82 +e9 4e d4 cd 09 44 8d 20 ec 0e fa 73 54 5f 80 b6 +54 06 be d6 19 4a 61 c3 40 b4 ad 15 68 cb b7 58 +51 04 9f 11 af 17 34 96 40 76 e0 20 29 ae e2 00 +e4 0e 80 be 0f 43 61 f6 98 41 c4 f9 2a 44 50 a2 +28 6d 43 28 9b 40 55 54 c5 4d 25 c6 ec b5 84 f4 + +# PKCS#1 v1.5 Signature Example 1.5 + +# ----------------- + +# Message to be signed: +b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64 +e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76 +c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e +f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75 +48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4 +b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f +32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7 +82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc +5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f +45 5a 69 09 b4 + +# Signature: +54 be 9d 90 87 75 15 f4 50 27 9c 15 b5 f6 1a d6 +f1 5e cc 95 f1 8c be d8 2b 65 b1 66 7a 57 58 09 +58 79 94 66 80 44 f3 bc 2a e7 f8 84 50 1f 64 f0 +b4 3f 58 8c fa 20 5a 6a b7 04 32 8c 2d 4a b9 2a +7a e1 34 40 61 4d 3e 08 5f 40 1d a9 ad 28 e2 10 +5e 4a 0e db 68 1a 64 24 df 04 73 88 ce 05 1e e9 +df 7b c2 16 3f e3 47 52 0a d5 1c cd 51 80 64 38 +3e 74 1a ca d3 cb dc 2c b5 a7 c6 8e 86 84 64 c2 + +# PKCS#1 v1.5 Signature Example 1.6 + +# ----------------- + +# Message to be signed: +10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7 +5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec +74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4 +3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4 +35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90 +9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7 +05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad +b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87 +94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00 +44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73 +d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29 +51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb +3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf +e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6 +13 8d 14 4f 8c e4 e2 da 73 + +# Signature: +0e 6f f6 3a 85 6b 9c bd 5d be 42 31 83 12 20 47 +dd 39 d6 f7 6d 1b 23 10 e5 46 fe 9e e7 3b 33 ef +a7 c7 8f 94 74 45 5c 9e 5b 88 cb 38 3a af c3 69 +86 68 e7 b7 a5 9a 9c bb 5b 08 97 b6 c5 af b7 f8 +ba c4 b9 24 e9 8d 76 0a 15 fc 43 d2 81 4a b2 d5 +18 7f 79 be d9 91 5a 93 39 7e bc 22 a7 67 75 06 +a0 2e 07 6d 3f fd c0 44 1d bd 4d b0 04 53 dc 28 +d8 30 e0 57 3f 77 b8 17 b5 05 c3 8b 4a 4b b5 d0 + +# PKCS#1 v1.5 Signature Example 1.7 + +# ----------------- + +# Message to be signed: +ef b5 da 1b 4d 1e 6d 9a 5d ff 92 d0 18 4d a7 e3 +1f 87 7d 12 81 dd da 62 56 64 86 9e 83 79 e6 7a +d3 b7 5e ae 74 a5 80 e9 82 7a bd 6e b7 a0 02 cb +54 11 f5 26 67 97 76 8f b8 e9 5a e4 0e 3e 8b 34 +66 f5 ab 15 d6 95 53 95 29 39 ec 23 e6 1d 58 49 +7f ac 76 aa 1c 0b b5 a3 cb 4a 54 38 35 87 c7 bb +78 d1 3e ef da 20 54 43 e6 ce 43 65 80 2d f5 5c +64 71 34 97 98 4e 7c a9 67 22 b3 ed f8 4d 56 + +# Signature: +83 85 d5 85 33 a9 95 f7 2d f2 62 b7 0f 40 b3 91 +dd f5 15 f4 64 b9 d2 cc 2d 66 39 8f c0 56 89 d8 +11 63 29 46 d6 2e ab dc a7 a3 1f cf 6c d6 c9 81 +d2 8b bc 29 08 3e 4a 6d 5b 2b 37 8c a4 e5 40 f0 +60 b9 6d 53 ad 26 93 f8 21 78 b9 4e 2e 2f 86 b9 +ac cf a0 20 25 10 7e 06 2a b7 08 01 75 68 45 01 +02 8f 67 64 61 d8 1c 00 8f e4 75 06 71 64 99 70 +87 8f c1 75 cf 98 e9 6b 2e cb f6 87 4d 77 da cb + +# PKCS#1 v1.5 Signature Example 1.8 + +# ----------------- + +# Message to be signed: +53 bb 58 ce 42 f1 98 49 40 55 26 57 23 3b 14 96 +9a f3 65 c0 a5 61 a4 13 2a f1 8a f3 94 32 28 0e +3e 43 70 82 43 4b 19 23 18 37 18 4f 02 cf 2b 2e +72 6b eb f7 4d 7a e3 25 6d 8b 72 f3 ea fd b1 34 +d3 3d e0 6f 29 91 d2 99 d5 9f 54 68 d4 3b 99 58 +d6 a9 68 f5 96 9e db bc 6e 71 85 cb c7 16 c7 c9 +45 da fa 9c c7 1d df aa a0 10 94 a4 52 dd f5 e2 +40 73 20 40 0b f0 5e a9 72 9c af bf 06 00 e7 88 +07 ef 94 62 e3 fd e3 2e d7 d9 81 a5 6f 47 51 ef +64 fb 45 49 91 0e cc 91 1d 72 80 53 b3 99 43 00 +47 40 e6 f5 82 1f e8 d7 5c 06 17 bf 2c 6b 24 bb +fc 34 01 3f c9 5f 0d ed f5 ba 29 7f 50 4f b8 33 +da 2a 43 6d 1d 8f f1 cc 51 93 e2 a6 43 89 fc ed +91 8e 7f eb 67 16 33 0f 66 80 1d b9 49 75 49 cf +1d 3b d9 7c f1 bc 62 55 + +# Signature: +8e 1f 3d 26 ec 7c 6b bb 8c 54 c5 d2 5f 31 20 58 +78 03 af 6d 3c 2b 99 a3 7c ed 6a 36 57 d4 ae 54 +26 6f 63 ff fd e6 60 c8 66 d6 5d 0a b0 58 9e 1d +12 d9 ce 60 54 b0 5c 86 68 ae 12 71 71 cc aa e7 +f1 cd 40 96 77 f5 21 57 b6 12 3a b2 27 f2 7a 00 +96 6d 14 39 b4 2a 32 16 9d 10 70 39 40 26 fc 8b +c9 35 45 b1 ac 25 2d 0f 7d a7 51 c0 2e 33 a4 78 +31 fb d7 15 14 c2 bb bd 3a db 67 40 c0 fd 68 ad + +# PKCS#1 v1.5 Signature Example 1.9 + +# ----------------- + +# Message to be signed: +27 ca dc 69 84 50 94 5f 20 4e c3 cf 8c 6c bd 8c +eb 4c c0 cb e3 12 27 4f a9 6b 04 de ac 85 51 60 +c0 e0 4e 4a c5 d3 82 10 c2 7c + +# Signature: +7b 63 f9 22 33 56 f3 5f 61 17 f6 8c 8f 82 20 03 +4f c2 38 4a b5 dc 69 04 14 1f 13 93 14 d6 ee 89 +f5 4e c6 ff d1 8c 41 3a 23 c5 93 1c 7f bb 13 c5 +55 cc fd 59 0e 0e aa 85 3c 8c 94 d2 52 0c d4 25 +0d 9a 05 a1 93 b6 5d c7 49 b8 24 78 af 01 56 ee +1d e5 5d da d3 3e c1 f0 09 9c ad 6c 89 1a 36 17 +c7 39 3d 05 fb fb bb 00 52 8a 00 1d f0 b2 04 eb +df 1a 34 10 90 de a8 9f 87 0a 87 74 58 42 7f 7b + +# PKCS#1 v1.5 Signature Example 1.10 + +# ----------------- + +# Message to be signed: +71 64 07 e9 01 b9 ef 92 d7 61 b0 13 fd 13 eb 7a +d7 2a ed + +# Signature: +2a 22 db e3 77 4d 5b 29 72 01 b5 5a 0f 17 f4 2d +ce 63 b7 84 5c b3 25 cf e9 51 d0 ba db 5c 5a 14 +47 21 43 d8 96 c8 6c c3 39 f8 36 71 16 42 15 ab +c9 78 62 f2 15 16 54 e7 5a 3b 35 7c 37 31 1b 3d +72 68 ca b5 40 20 2e 23 be e5 27 36 f2 cd 86 cc +e0 c7 db de 95 e1 c6 00 a4 73 95 dc 5e b0 a4 72 +15 3f bc 4f b2 1b 64 3e 0c 04 ae 14 dd 37 e9 7e +61 7a 75 67 c8 96 52 21 97 81 00 1b a6 f8 32 98 + +# PKCS#1 v1.5 Signature Example 1.11 + +# ----------------- + +# Message to be signed: +46 c2 4e 41 03 00 16 29 c7 12 dd 4c e8 d7 47 ee +59 5d 6c 74 4c cc 4f 71 34 7d 9b 8a bf 49 d1 b8 +fb 2e f9 1b 95 dc 89 9d 4c 0e 3d 29 97 e6 38 f4 +cf 3f 68 e0 49 8d e5 aa bd 13 f0 df e0 2f f2 6b +a4 37 91 04 e7 8f fa 95 ff bd 15 06 7e f8 cb d7 +eb 78 60 fe cc 71 ab e1 3d 5c 72 0a 66 85 1f 2d +ef d4 e7 95 05 4d 7b ec 02 4b b4 22 a4 6a 73 68 +b5 6d 95 b4 7a eb af be ad d6 12 81 25 93 a7 0d +b9 f9 6d 45 1e e1 5e db 29 93 08 d7 77 f4 bb 68 +ed 33 77 c3 21 56 b4 1b 7a 9c 92 a1 4c 8b 81 14 +43 99 c5 6a 5a 43 2f 4f 77 0a a9 7d a8 41 5d 0b +da 2e 81 32 06 03 1e 70 62 00 31 c8 81 d6 16 bf +fd 5f 03 bf 14 7c 1e 73 76 6c 26 24 62 08 + +# Signature: +12 23 5b 0b 40 61 26 d9 d2 60 d4 47 e9 23 a1 10 +51 fb 24 30 79 f4 46 fd 73 a7 01 81 d5 36 34 d7 +a0 96 8e 4e e2 77 77 ed a6 3f 6e 4a 3a 91 ad 59 +85 99 8a 48 48 da 59 ce 69 7b 24 bb 33 2f a2 ad +9c e4 62 ca 4a ff dc 21 da b9 08 e8 ce 15 af 6e +b9 10 5b 1a bc f3 91 42 aa 17 b3 4c 4c 09 23 86 +a7 ab bf e0 28 af db eb c1 4f 2c e2 6f be e5 ed +ec a1 15 02 d3 9a 6b 74 03 15 48 43 d9 8a 62 a7 + +# PKCS#1 v1.5 Signature Example 1.12 + +# ----------------- + +# Message to be signed: +bc 99 a9 32 aa 16 d6 22 bf ff 79 c5 0b 4c 42 35 +86 73 26 11 29 e2 8d 6a 91 8f f1 b0 f1 c4 f4 6a +d8 af a9 8b 0c a0 f5 6f 96 79 75 b0 a2 9b e8 82 +e9 3b 6c d3 fc 33 e1 fa ef 72 e5 2b 2a e0 a3 f1 +20 24 50 6e 25 69 0e 90 2e 78 29 82 14 55 56 53 +22 84 cf 50 57 89 73 8f 4d a3 1f a1 33 3d 3a f8 +62 b2 ba 6b 6c e7 ab 4c ce 6a ba + +# Signature: +87 2e c5 ad 4f 18 46 25 6f 17 e9 93 6a c5 0e 43 +e9 96 3e a8 c1 e7 6f 15 87 9b 78 74 d7 7d 12 2a +60 9d c8 c5 61 14 5b 94 bf 4f fd ff de b1 7e 6e +76 ff c6 c1 0c 07 47 f5 e3 7a 9f 43 4f 56 09 e7 +9d a5 25 02 15 a4 57 af df 12 c6 50 7c c1 55 1f +54 a2 80 10 59 58 26 a2 c9 b9 7f a0 aa 85 1c c6 +8b 70 5d 7a 06 d7 20 ba 02 7e 4a 1c 0b 01 95 00 +fb 63 b7 80 71 68 4d cf a9 77 27 00 b9 82 dc 66 + +# PKCS#1 v1.5 Signature Example 1.13 + +# ----------------- + +# Message to be signed: +73 1e 17 2a c0 63 99 2c 5b 11 ba 17 0d fb 23 bb +00 0d 47 ba 19 53 29 cf 27 80 61 03 73 81 51 4c +14 60 64 c5 28 5d b1 30 dd 5b ae 98 b7 72 22 59 +50 ea b0 5d 3e a9 96 f6 ff fb 9a 8c 86 22 91 3f +27 99 14 c8 9a da 4f 3d d7 76 66 a8 68 bf cb ff +2b 95 b7 da f4 53 d4 e2 c9 d7 5b ee e7 f8 e7 09 +05 e4 06 6a 4f 73 ae cc 67 f9 56 aa 5a 32 92 b8 +48 8c 91 7d 31 7c fd c8 62 53 e6 90 38 1e 15 ab + +# Signature: +76 20 4e ac c1 d6 3e c1 d6 ad 5b d0 69 2e 1a 2f +68 6d f6 e6 4c a9 45 c7 7a 82 4d e2 12 ef a6 d9 +78 2d 81 b4 59 14 03 ff 40 20 62 02 98 c0 7e bd +3a 8a 61 c5 bf 4d ad 62 cb fc 4a e6 a0 39 37 be +4b 49 a2 16 d5 70 fc 6e 81 87 29 37 87 6e 27 bd +19 cf 60 1e ff c3 0d dc a5 73 c9 d5 6c d4 56 9b +db 48 51 c4 50 c4 2c b2 1e 73 8c dd 61 02 7b 8b +e5 e9 b4 10 fc 46 aa 3f 29 e4 be 9e 64 45 13 46 + +# PKCS#1 v1.5 Signature Example 1.14 + +# ----------------- + +# Message to be signed: +02 11 38 26 83 a7 4d 8d 2a 2c b6 a0 65 50 56 3b +e1 c2 6c a6 28 21 e4 ff 16 3b 72 04 64 fc 3a 28 +d9 1b ed dd c6 27 49 a5 53 8e af 41 fb e0 c8 2a +77 e0 6a d9 93 83 c9 e9 85 ff b8 a9 3f d4 d7 c5 +8d b5 1a d9 1b a4 61 d6 9a 8f d7 dd ab e2 49 67 +57 a0 c4 91 22 c1 a7 9a 85 cc 05 53 e8 21 4d 03 +6d fe 01 85 ef a0 d0 58 60 c6 12 fa 08 82 c8 2d +24 6e 58 30 a6 73 55 df f1 8a 2c 36 b7 32 f9 88 +cf ed c5 62 26 4c 62 54 b4 0f ca bb 97 b7 60 94 +75 68 dc d6 a1 7c da 6e e8 85 5b dd ba b9 37 02 +47 1a a0 cf b1 be d2 e1 31 18 eb a1 17 5b 73 c9 +62 53 c1 08 d0 b2 ab a0 5a b8 e1 7e 84 39 2e 20 +08 5f 47 40 4d 83 65 52 7d c3 fb 8f 2b b4 8a 50 +03 8e 71 36 1c cf 97 34 07 + +# Signature: +52 55 00 91 83 31 f1 04 2e ae 0c 5c 20 54 aa 7f +92 de b2 69 91 b5 79 66 34 f2 29 da f9 b4 9e b2 +05 4d 87 31 9f 3c fa 9b 46 6b d0 75 ef 66 99 ae +a4 bd 4a 19 5a 1c 52 96 8b 5e 2b 75 e0 92 d8 46 +ea 1b 5c c2 79 05 a8 e1 d5 e5 de 0e df db 21 39 +1e bb 95 18 64 eb d9 f0 b0 ec 35 b6 54 28 71 36 +0a 31 7b 7e f1 3a e0 6a f6 84 e3 8e 21 b1 e1 9b +c7 29 8e 5d 6f e0 01 3a 16 4b fa 25 d3 e7 31 3d + +# PKCS#1 v1.5 Signature Example 1.15 + +# ----------------- + +# Message to be signed: +fc 6b 70 0d 22 58 33 88 ab 2f 8d af ca f1 a0 56 +20 69 80 20 da 4b ae 44 da fb d0 87 7b 50 12 50 +6d c3 18 1d 5c 66 bf 02 3f 34 8b 41 fd 9f 94 79 +5a b9 64 52 a4 21 9f 2d 39 d7 2a f3 59 cf 19 56 +51 c7 + +# Signature: +44 52 a6 cc 26 26 b0 1e 95 ab 30 6d f0 d0 cc 74 +84 fb ab 3c 22 e9 70 32 83 56 7f 66 ea dc 24 8d +bd a5 8f ce 7d d0 c7 0c ce 3f 15 0f ca 4b 36 9d +ff 3b 62 37 e2 b1 62 81 ab 55 b5 3f b1 30 89 c8 +5c d2 65 05 6b 3d 62 a8 8b fc 21 35 b1 67 91 f7 +fb ca b9 fd 2d c3 3b ec b6 17 be 41 9d 2c 04 61 +42 a4 d4 7b 33 83 14 55 2e dd 4b 6f e9 ce 11 04 +ec ec 4a 99 58 d7 33 1e 93 0f c0 9b f0 8a 6e 64 + +# PKCS#1 v1.5 Signature Example 1.16 + +# ----------------- + +# Message to be signed: +13 ba 08 6d 70 9c fa 5f ed aa 55 7a 89 18 1a 61 +40 f2 30 0e d6 d7 c3 fe bb 6c f6 8a be bc bc 67 +8f 2b ca 3d c2 33 02 95 ee c4 5b b1 c4 07 5f 3a +da 98 7e ae 88 b3 9c 51 60 6c b8 04 29 e6 49 d9 +8a cc 84 41 b1 f8 89 7d b8 6c 5a 4c e0 ab f2 8b +1b 81 dc a3 66 76 97 b8 50 69 6b 74 a5 eb d8 5d +ec 56 c9 0f 8a be 51 3e fa 85 78 53 72 0b e3 19 +60 79 21 bc a9 47 52 2c d8 fa c8 ca ce 5b 82 7c +3e 5a 12 9e 7e e5 7f 6b 84 93 2f 14 14 1a c4 27 +4e 8c bb 46 e6 91 2b 0d 3e 21 77 d4 99 d1 84 0c +d4 7d 4d 7a e0 b4 cd c4 d3 + +# Signature: +1f 3b 5a 87 db 72 a2 c9 7b b3 ef f2 a6 5a 30 12 +68 ea cd 89 f4 2a bc 10 98 c1 f2 de 77 b0 83 2a +65 d7 81 5f eb 35 07 00 63 f2 21 bb 34 53 bd 43 +43 86 c9 a3 fd e1 8e 3c a1 68 7f b6 49 e8 6c 51 +d6 58 61 9d de 5d eb b8 6f e1 54 91 ff 77 ab 74 +83 73 f1 be 50 88 80 d6 6e a8 1e 87 0e 91 cd f1 +70 48 75 c1 7f 0b 10 10 31 88 bc 64 ee f5 a3 55 +1b 41 4c 73 36 70 21 5b 1a 22 70 25 62 58 1a b1 + +# PKCS#1 v1.5 Signature Example 1.17 + +# ----------------- + +# Message to be signed: +eb 1e 59 35 + +# Signature: +37 0c b9 83 9a e6 07 4f 84 b2 ac d6 e6 f6 b7 92 +1b 4b 52 34 63 75 7f 64 46 71 61 40 c4 e6 c0 e7 +5b ec 6a d0 19 7e bf a8 6b f4 6d 09 4f 5f 6c d3 +6d ca 3a 5c c7 3c 8b bb 70 e2 c7 c9 ab 5d 96 4e +c8 e3 df de 48 1b 4a 1b ef fd 01 b4 ad 15 b3 1a +e7 ae bb 9b 70 34 4a 94 11 08 31 65 fd f9 c3 75 +4b bb 8b 94 dd 34 bd 48 13 df ad a1 f6 93 7d e4 +26 7d 55 97 ca 09 a3 1e 83 d7 f1 a7 9d d1 9b 5e + +# PKCS#1 v1.5 Signature Example 1.18 + +# ----------------- + +# Message to be signed: +63 46 b1 53 e8 89 c8 22 82 09 63 00 71 c8 a5 77 +83 f3 68 76 0b 8e b9 08 cf c2 b2 76 + +# Signature: +24 79 c9 75 c5 b1 ae 4c 4e 94 0f 47 3a 90 45 b8 +bf 5b 0b fc a7 8e c2 9a 38 df be dc 8a 74 9b 7a +26 92 f7 c5 2d 5b c7 c8 31 c7 23 23 72 a0 0f ed +3b 6b 49 e7 60 ec 99 e0 74 ff 2e ea d5 13 4e 83 +05 72 5d fa 39 21 2b 84 bd 4b 8d 80 bc 8b c1 7a +51 28 23 a3 be b1 8f c0 8e 45 ed 19 c2 6c 81 77 +07 d6 7f b0 58 32 ef 1f 12 a3 3e 90 cd 93 b8 a7 +80 31 9e 29 63 ca 25 a2 af 7b 09 ad 8f 59 5c 21 + +# PKCS#1 v1.5 Signature Example 1.19 + +# ----------------- + +# Message to be signed: +64 70 2d b9 f8 25 a0 f3 ab c3 61 97 46 59 f5 e9 +d3 0c 3a a4 f5 6f ea c6 90 50 c7 29 05 e7 7f e0 +c2 2f 88 a3 78 c2 1f cf 45 fe 8a 5c 71 73 02 09 +39 29 + +# Signature: +15 2f 34 51 c8 58 d6 95 94 e6 56 7d fb 31 29 1c +1e e7 86 0b 9d 15 eb d5 a5 ed d2 76 ac 3e 6f 7a +8d 14 80 e4 2b 33 81 d2 be 02 3a cf 7e bb db 28 +de 3d 21 63 ae 44 25 9c 6d f9 8c 33 5d 04 5b 61 +da c9 db a9 db bb 4e 6a b4 a0 83 cd 76 b5 80 cb +e4 72 20 6a 1a 9f d6 06 80 ce ea 1a 57 0a 29 b0 +88 1c 77 5e ae f5 52 5d 6d 2f 34 4c 28 83 7d 0a +ca 42 2b bb 0f 1a ba 8f 68 61 ae 18 bd 73 fe 44 + +# PKCS#1 v1.5 Signature Example 1.20 + +# ----------------- + +# Message to be signed: +94 19 21 de 4a 1c 9c 16 18 d6 f3 ca 3c 17 9f 6e +29 ba e6 dd f9 a6 a5 64 f9 29 e3 ce 82 cf 32 65 +d7 83 7d 5e 69 2b e8 dc c9 e8 6c + +# Signature: +70 76 c2 87 fc 6f ff 2b 20 53 74 35 e5 a3 10 7c +e4 da 10 71 61 86 d0 15 39 41 3e 60 9d 27 d1 da +6f d9 52 c6 1f 4b ab 91 c0 45 fa 4f 86 83 ec c4 +f8 dd e7 42 27 f7 73 cf f3 d9 6d b8 47 18 c4 94 +4b 06 af fe ba 94 b7 25 f1 b0 7d 39 28 b2 49 0a +85 c2 f1 ab f4 92 a9 17 7a 7c d2 ea 0c 96 68 75 +6f 82 5b be c9 00 fa 8a c3 82 4e 11 43 87 ef 57 +37 80 ca 33 48 82 38 7b 94 e5 aa d7 a2 7a 28 dc + +# ============================================= + +# Example 2: A 1024-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +ac 13 d9 fd ae 7b 73 35 b6 9c d9 85 67 e9 64 7d +99 bf 37 3a 9e 05 ce 34 35 d6 64 65 f3 28 b7 f7 +33 4b 79 2a ee 7e fa 04 4e bc 4c 7a 30 b2 1a 5d +7a 89 cd b3 a3 0d fc d9 fe e9 99 5e 09 41 5e dc +0b f9 e5 b4 c3 f7 4f f5 3f b4 d2 94 41 bf 1b 7e +d6 cb dd 4a 47 f9 25 22 69 e1 64 6f 6c 1a ee 05 +14 e9 3f 6c b9 df 71 d0 6c 06 0a 21 04 b4 7b 72 +60 ac 37 c1 06 86 1d c7 8c a5 a2 5f aa 9c b2 e3 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +ac 13 d9 fd ae 7b 73 35 b6 9c d9 85 67 e9 64 7d +99 bf 37 3a 9e 05 ce 34 35 d6 64 65 f3 28 b7 f7 +33 4b 79 2a ee 7e fa 04 4e bc 4c 7a 30 b2 1a 5d +7a 89 cd b3 a3 0d fc d9 fe e9 99 5e 09 41 5e dc +0b f9 e5 b4 c3 f7 4f f5 3f b4 d2 94 41 bf 1b 7e +d6 cb dd 4a 47 f9 25 22 69 e1 64 6f 6c 1a ee 05 +14 e9 3f 6c b9 df 71 d0 6c 06 0a 21 04 b4 7b 72 +60 ac 37 c1 06 86 1d c7 8c a5 a2 5f aa 9c b2 e3 + +# Public exponent: +01 00 01 + +# Exponent: +04 84 cc ef ad 7a 4e 6f 35 a9 6e c8 e3 0e ac f5 +e3 68 b3 11 95 fe bf 08 7d f5 70 53 81 0c 2b b0 +91 27 45 3a 4c 63 07 3b bf b9 90 24 91 4c cc 06 +72 66 56 01 86 a1 a2 67 33 1b 7d 4c 8b df ac 96 +fd a9 f3 f7 0b ec 4e ea bc e7 cd 52 19 34 3c 2e +49 1c ce 82 7e 44 ee 23 0e 4f 69 58 9e 57 5a e9 +06 30 30 44 2a 31 c8 2c de 30 dc 9c 79 cf 64 e7 +a0 97 5e 75 e1 6e a4 58 15 48 8b 45 52 56 ee b1 + +# Prime 1: +df 85 f4 a0 b4 33 bd 37 43 3c d7 97 8c 9b 37 f9 +e4 17 29 d8 3a 26 2b 98 46 53 8e 50 39 e6 59 68 +b5 95 a4 62 72 bd 5f 4a 2c 3a bf 89 0a 35 50 8a +5b cb 4c 29 ef bd 91 02 85 03 83 4c fa b2 c0 f9 + +# Prime 2: +c5 14 59 a6 72 ed 8b 72 4c 6a 8f 28 5c bb 8e a7 +6a 23 93 91 79 28 be 56 c0 dc df c9 43 c3 0b da +3c ee fb 86 dc c8 c4 55 67 8c fe 88 25 f3 88 77 +a3 72 8a 1f 10 29 1f 54 7b 1e 8b 16 04 83 e5 bb + +# Prime exponent 1: +b6 ba 83 a9 7c a7 6f 5f e6 0f af 0f ad 5a 97 00 +2a 7e e5 2e 67 1b 1d 38 77 05 87 a9 fe 2b 59 9c +48 15 f5 34 a6 28 39 e6 21 12 45 d2 7a 0d eb b1 +b0 29 1a 32 8e 52 a2 61 34 ec 12 42 b4 0f bd c1 + +# Prime exponent 2: +b9 b1 c6 13 2e e1 22 6e 6d 10 4e 99 72 5f 0b 38 +35 ab 15 e5 91 6a d1 85 be ad 9f 72 ed 95 3f 7a +bf c5 52 5c ad 75 c2 80 d2 54 28 94 b2 65 b8 65 +3a 2d b7 75 33 6d fb e6 47 27 ed 57 ae a3 74 f7 + +# Coefficient: +7b 8d 15 a5 dd 28 90 a6 7d 1b 54 9c 93 5f 58 5a +38 da 56 f7 c8 15 5a 51 9d c8 f1 f6 ad e5 53 d6 +37 93 c7 8a 0e ce 8d 53 72 4e 62 ae 50 3a d5 25 +bf af 10 cf 61 6a 47 73 ce 7c cd 5c 1b 31 51 bd + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 2.1 + +# ----------------- + +# Message to be signed: +e1 c0 f9 8d 53 f8 f8 b1 41 90 57 d5 b9 b1 0b 07 +fe ea ec 32 c0 46 3a 4d 68 38 2f 53 1b a1 d6 cf +e4 ed 38 a2 69 4a 34 b9 c8 05 ad f0 72 ff bc eb +e2 1d 8d 4b 5c 0e 8c 33 45 2d d8 f9 c9 bf 45 d1 +e6 33 75 11 33 58 82 29 d2 93 c6 49 6b 7c 98 3c +2c 72 bd 21 d3 39 27 2d 78 28 b0 d0 9d 01 0b ba +d3 18 d9 98 f7 04 79 67 33 8a ce fd 01 e8 74 ac +e5 f8 6d 2a 60 f3 b3 ca e1 3f c5 c6 65 08 cf b7 +23 78 fd d6 c8 de 24 97 65 10 3c e8 fe 7c d3 3a +d0 ef 16 86 fe b2 5e 6a 35 fb 64 e0 96 a4 + +# Signature: +64 ac 09 39 71 f8 f0 96 a4 c1 d4 a5 43 66 2a 2e +5a 12 81 c9 50 98 7d e8 98 70 7f 02 9c 15 9b d8 +32 ca c5 5d 91 36 e0 e9 b4 a8 0b f6 f2 1b 68 cf +97 70 a6 34 9a e5 1e 7f 09 db da 9d 59 c4 58 37 +37 47 2d 4d 65 32 c7 17 7e e9 81 08 d2 cf 42 cd +08 5a bb 49 22 eb 29 d9 6f 3d 0f 6b 1d 0d 43 c7 +39 cc f1 ba 65 16 75 e1 96 8b 50 7d 51 90 2f 38 +cd ec 0b 61 32 72 90 45 32 5f c1 fb 8f d5 58 e8 + +# PKCS#1 v1.5 Signature Example 2.2 + +# ----------------- + +# Message to be signed: +c1 11 46 4e 00 2e 4e c6 18 a8 e2 63 db cc a9 1f +b1 8a 00 a1 8b 44 0c 4b 55 97 be e7 db 2a ed a8 +31 e6 21 fc ac 8d d8 1c ee 35 03 24 2b 33 b0 da +a9 87 fe 2f 54 93 ad 2d 06 a1 50 07 59 00 40 ce +3c 22 77 64 2f d2 7f 3f 25 5e 3d 98 d8 9d fa eb +86 be 34 e0 b8 fb b9 35 fb 92 85 60 fa 29 2d 26 +34 62 5a 50 7d d5 80 a8 91 24 b9 21 29 3e 8d fe +dd c2 81 d7 9e b3 a5 69 d5 9e 0d b8 01 3e 53 f7 +d4 c2 f9 6e 5f 2e c2 7f d8 dd b0 18 25 d1 7f ca +40 6d aa 62 24 c7 60 6d 2c 91 52 82 09 6a 78 05 +5a 49 62 15 37 b4 f0 25 a6 e5 b2 12 9b c8 c1 a4 +07 + +# Signature: +6e 7e aa d8 04 94 5e b0 46 70 dd 86 76 b7 05 7d +03 ac 3e 22 64 65 b1 fb 84 03 e6 ae 79 83 e0 a4 +6a 89 a4 eb 32 bd c8 e7 ae 5a 53 d4 8a a6 4b c9 +c3 db c8 cf 9c d6 dc 6a 68 fc ea e9 e2 9f 47 45 +fa 49 e1 8d 18 4d c5 d2 6c 4f eb 35 1f b4 b2 28 +c4 c1 8c ab db de 86 01 72 4a e3 80 3d b3 05 f2 +a0 76 fa 8a 57 f4 61 0b 8a 6e 0e d4 35 75 be 5d +5b fc 16 30 47 9d f3 bc bc 51 51 77 af e4 99 4a + +# PKCS#1 v1.5 Signature Example 2.3 + +# ----------------- + +# Message to be signed: +29 b8 5b 14 b2 da 94 7a 4c 3a d1 e5 93 7d a1 92 +c6 05 08 65 af 95 04 a5 44 53 70 e4 3d 3a 8d a5 +d3 55 fd 58 76 6b 25 43 ac 6f 93 10 87 83 c1 3f +f2 8b 2b e5 60 83 f0 29 82 39 e0 ee 96 81 ee 47 +c6 + +# Signature: +80 b3 8c e7 35 12 6c 85 45 d9 1d 18 ec 90 37 65 +4d 46 e4 f3 c5 1a 6b 86 18 e1 5f 72 cd 20 75 00 +a4 70 01 75 77 d0 a8 c5 5a 2b a3 34 38 3f 1f 8d +99 fc e2 46 0b 32 97 bc 03 7e f6 4a c4 a3 09 8c +6a aa 24 a4 d0 14 4a f1 02 d0 dd a1 7e 07 dc 69 +59 23 93 2e 56 8a da 00 dc 4f 7d bf bc de c4 3c +c9 08 38 80 17 d2 ee f0 4e 60 df e4 d5 73 40 fa +b9 16 e2 b8 11 24 4c b1 e4 a5 52 38 6f e3 ed 4c + +# PKCS#1 v1.5 Signature Example 2.4 + +# ----------------- + +# Message to be signed: +d3 b7 aa d3 7a 48 90 e0 36 5b 86 c7 da 94 91 e7 +3c df 55 5d 1b 02 b4 51 81 6d c5 2f 96 30 d5 90 +de 83 a5 c9 39 61 01 25 22 df f6 db bb 9c db 0e +71 ae 51 40 19 64 af 18 90 e8 93 25 db d6 26 f2 +da 01 34 58 e3 9e ec a5 83 e8 9e 4c 08 e5 d4 12 +be 49 84 95 88 6e 05 51 cf e7 42 b8 b5 + +# Signature: +9d 8a 88 89 a3 11 b4 86 cb e2 22 57 03 f5 d4 ae +2a 54 c2 bc aa ad 06 fe 76 48 b9 e2 d8 5e dd a1 +a0 7d 85 6d 6a e9 bd 5c c1 e5 15 32 66 ec 7f 1e +1d f3 d9 29 cc 44 70 0f ac 92 64 58 41 4c 28 41 +da 83 32 8e 81 e0 b9 d6 c3 88 5e 76 73 70 ad 5c +f1 f5 76 d9 dc e3 48 ca ec 5e 64 43 e0 ae b7 c3 +f7 2b 7d d2 53 66 70 23 b9 a4 77 ab 34 df 8f 20 +67 e2 25 ad cb 73 ee 11 e1 59 eb 64 91 47 d6 02 + +# PKCS#1 v1.5 Signature Example 2.5 + +# ----------------- + +# Message to be signed: +f6 58 18 8c 8f 9d e6 0b 5e 99 a2 9f 52 d3 b8 89 +20 1b 30 d4 64 c3 b7 27 92 a3 02 09 5d c1 e7 7d +45 e9 4f 5d ab 73 db b3 13 54 38 57 ff 91 db f4 +73 df c1 45 d7 3b d5 06 20 75 d1 92 a3 fb f4 a1 +33 e7 e5 68 df 20 b8 cf f7 7b 3a f6 87 aa 22 55 +9e c1 + +# Signature: +0a 95 a4 4f 62 74 e7 4c ec 45 17 96 af 56 88 d4 +be 01 08 93 fa ae 27 d4 90 f4 77 1b 00 3f 70 46 +cc cd 41 9f c8 19 d7 33 19 55 f4 1e ac 93 39 f5 +46 c5 84 a8 b4 2a 5a c6 32 90 58 3f f3 eb 6b 29 +ca dc 75 4a e5 8d 5a 56 37 b6 60 97 96 e8 05 51 +73 ff 20 a9 cc e4 92 fd 78 37 46 86 15 e8 41 08 +87 f0 b4 a5 9f f2 52 a8 25 97 76 c8 ff da a6 7c +87 df f8 98 3a e6 79 d1 de 22 ea 15 8d 48 f6 8b + +# PKCS#1 v1.5 Signature Example 2.6 + +# ----------------- + +# Message to be signed: +31 ae 5f 83 a0 fb 3a c9 25 5f fa 43 5f 70 e2 ab +65 55 66 e5 fb 8b 78 b8 02 c1 87 cf f1 c5 e4 0f +ed 06 97 8c 5d 59 76 eb 4c a7 75 80 63 99 a6 fc +4d b5 0c 1f 88 66 1b a6 8a bc 21 fb 2c cd 53 7f +50 18 f3 6e d1 f7 d4 53 83 fd 46 9e 77 ba b3 e8 +a9 5d fa 1b 94 1e 43 0d de c5 52 dc d8 2f 5d 10 +d2 9c d1 0a 22 d1 7c e2 42 59 28 ff 5d 07 10 dc +e7 d9 f8 3b 12 e0 4c 1a 01 59 c2 71 76 e0 4a cc + +# Signature: +3f 11 ea 73 9f 32 9c 9d 40 04 60 34 b6 c0 cf ce +b4 9b c3 20 1a 5f 25 ea f5 01 5a ed ed 02 18 9c +e0 b0 cf de 19 12 5b d2 88 b7 d0 c0 62 32 1a 5b +dc 2c fa 42 26 f5 10 4a 1f ba eb be 7f 72 f5 f7 +92 7e 1e ae 26 fd c5 ba 92 f2 d3 f8 69 eb c3 2d +90 18 dd 04 ed e8 6d e5 c4 54 f1 f7 a1 b2 e2 d1 +94 0a ac ae 27 79 63 55 fe 18 ac 80 97 53 53 92 +9a c6 a8 38 45 8b 5d 9d c7 57 6e 38 87 ee 7b ca + +# PKCS#1 v1.5 Signature Example 2.7 + +# ----------------- + +# Message to be signed: +96 ff 99 f1 50 60 c9 73 a6 5b 69 a8 b5 b6 3a db +33 25 32 0d a9 37 29 75 84 ad 4f ad 5c 3c 74 69 +01 9e 9c f7 2a cb 31 5f 1e 49 19 27 bb a1 94 87 +55 82 3e b0 7e 3f 20 ac df 78 65 3c ae 45 0e 47 +bc 54 ba f8 ca 11 67 a5 05 08 44 e0 22 22 0e e6 +65 8a 8d dd 95 63 2e 9a dc 1a 6c 14 37 9c 1c 5a +e5 a0 ce 5d c4 02 08 09 62 2a fd ec f8 1f 18 a5 +1e 28 66 6d 02 b1 dc da 0a 27 b8 c3 d2 c2 7b 2c +07 b3 80 22 00 01 7a 7c 12 4a 43 37 cc 4b 6e a2 +ae a7 5c 68 b4 40 e3 79 47 e3 61 9b cf ee 05 5b +b2 ed ab c4 24 49 07 e0 48 3d d3 a1 7d 8e df f3 +a6 50 29 3f d4 ab f5 c4 5d 1a 5b 6c 54 02 ba 2b +81 b7 b0 e0 c9 5e e9 49 b2 a2 38 c1 99 56 20 6c +12 4e 0c d9 c2 46 20 b3 6a 83 bf 93 b9 6e f2 04 +bd e5 31 6c 1f 53 27 c0 a6 21 ec ce 20 93 c0 65 +2d df 32 17 68 d7 45 02 f1 90 85 29 62 9b ab 68 + +# Signature: +18 3f 85 3d 0d 03 62 18 70 e3 ba 58 68 50 c5 ea +59 fc 4e 9a cf 37 94 b9 ad 59 a1 bb 80 18 1e 77 +b1 11 d6 64 86 47 e1 39 a3 9e c0 4f 86 18 74 91 +e7 7b 4d 75 c0 60 79 5b f7 27 08 46 d3 96 e0 bf +ea 83 15 79 5e 79 d7 6a 91 9e a7 6b 06 ee c1 3b +af 4c e8 af e1 e3 4b c2 24 57 d7 b7 99 2e 08 42 +ef ad e1 79 b0 ae da cc fb e2 d2 3d 3e b3 14 e1 +de 91 c8 71 b9 db 5a bf fb 17 47 7f ba 23 3a 06 + +# PKCS#1 v1.5 Signature Example 2.8 + +# ----------------- + +# Message to be signed: +3a 17 6c 79 3a 54 6e 2d 27 6f b8 ff c3 28 16 3b +49 49 97 a5 30 2a ae 2e 50 45 a2 a2 06 87 ea 6d +1f 18 1c 6a bf e6 09 0c 8d c4 02 56 db 3d e0 83 +22 64 7f b7 95 bb a1 71 3f b5 7e 33 d5 3e 0e 13 +be da c6 a6 58 ad 4a b4 91 22 38 81 19 8d f2 93 +67 fa ad e8 be 9f ca a4 e4 83 f7 b7 f3 dc 7c bb +f9 7a 17 aa d8 8c 26 cf c6 41 0f 94 5b 54 fc 53 +db 55 ac 80 3d 8b 73 69 1b 14 84 84 7d 7f 3b 7e +93 94 e5 5f 0a 51 fe 61 ae 84 52 3c 94 b2 2e 82 +39 6d b6 cf ac b7 2e 0e e4 94 aa 0f 1f a5 93 12 +54 43 ae 15 55 a6 a9 33 fa ce 00 74 79 1d c2 c2 +92 42 eb + +# Signature: +41 3c 92 23 a2 e9 b1 22 cd 87 25 77 e5 2f 31 3d +41 da c7 9a 26 cb 10 33 da 0b 6f cc 4b 48 21 07 +74 4b f4 90 fa 79 8d cc d0 cb d1 18 ef 39 c0 f5 +59 d8 7b 89 33 5d b0 9b e7 70 0f b0 9f db d3 40 +40 a0 0b e5 ca 42 88 34 77 b0 6e 4e 10 a7 cb 11 +76 8f cb 02 c3 4f b1 06 e5 22 86 0d 10 69 39 06 +26 0f 43 d9 06 12 99 03 93 a8 ff ac 9f d7 0c a3 +78 29 11 1e eb a6 f3 de e5 4e f1 c1 62 68 b3 3e + +# PKCS#1 v1.5 Signature Example 2.9 + +# ----------------- + +# Message to be signed: +06 8a 99 1b 32 b6 76 c6 4b 89 8c 67 e1 13 72 82 +b4 37 11 b0 d0 67 1c 24 7d 9f 7c 48 f5 04 3e 4f +c2 06 dc 65 af 89 06 f2 52 f0 24 52 05 ea 08 43 +23 d4 27 6b e5 aa 0f c5 af 9c 3f 34 b2 fd 66 34 +df 57 2f c3 13 d2 73 b5 3e 9e 36 b9 46 e7 e6 72 +f9 8d 85 7d 7e dd d3 dd 04 39 31 32 f4 61 f2 2c +99 00 26 16 6f 38 5b e1 59 5c 7f 23 f8 9f f5 7e +05 a7 be 28 5d 10 56 15 48 5f 35 6a ba b1 ff 2a +b9 27 d6 09 95 2a 62 7e 46 8c a7 59 0a cb 52 13 +f4 31 39 f8 e2 c9 d4 d1 7c 6b d7 91 4e 53 f0 2f +d1 9a 13 1f f4 9c d2 5e de 8f 41 8a 88 53 0a 82 +39 88 7f 0f c7 97 ed b5 04 64 79 64 bf 31 ca af +08 0d 58 17 a0 + +# Signature: +57 5d a9 e9 be fc a1 82 95 46 e8 29 38 15 00 11 +32 03 0e 74 9c a5 10 88 f1 68 bd 15 0b 13 94 c7 +ac d5 97 8b ca 03 f7 b9 d9 2a 29 b8 e2 85 6b 0d +a0 7f 0b b1 5c 0b 33 e0 54 87 99 1a d9 7a 81 2d +c9 04 aa f0 fd 1e 38 7e f1 c2 70 c6 86 8d 3e e1 +c6 11 57 7b c4 d0 7f f4 56 b2 43 98 32 90 8a 3d +cc 4f c0 99 04 72 fd a3 cc 61 11 93 0b 99 79 5d +60 c0 e3 78 88 e8 7c e0 0b bf 3c 1c f3 07 f9 e1 + +# PKCS#1 v1.5 Signature Example 2.10 + +# ----------------- + +# Message to be signed: +d6 83 9e e6 d0 74 50 32 7e 09 a0 3e 1e c2 80 e1 +c8 d1 15 00 dc 39 0a 49 a9 c9 82 87 49 c3 e9 a4 +be e2 ba 57 6f 6d 12 17 a8 e7 85 4a 90 7e eb 93 +df ff 92 30 8a d0 d9 4e 2b 38 1f 92 b0 e8 4a 47 +1b f1 f3 7a 68 e9 65 f6 58 59 d1 fd fd 6f ea 84 +40 79 c4 03 70 dc ea e2 + +# Signature: +a7 c5 f6 d0 de 9c f8 f4 17 37 f2 3a e3 e8 cf 60 +9a eb cf 22 d5 de 12 13 d9 57 3c b9 44 03 f8 9c +0f 70 88 ff fc 61 10 6f a6 09 c7 37 1a 8d 7e 1b +cd 22 1b c1 ad 94 91 2f ab f2 ff c0 2f 84 84 56 +4c 22 5c 06 9b fc 6d a9 f3 f9 f4 97 4e 08 e1 fe +56 f7 48 ff 79 05 97 90 6a 95 4e 38 37 43 a3 7e +57 5f ef 07 4f 06 0f 3d d1 5b 5e e0 f9 4d ba 69 +d8 6c 99 22 3f a9 c3 a6 1a 8c b2 af 2f ab 1e 04 + +# PKCS#1 v1.5 Signature Example 2.11 + +# ----------------- + +# Message to be signed: +33 84 9c 67 df 9a 6f fa c3 da 90 a8 cd 31 73 1a +02 97 b9 d6 01 0a 03 32 0f 88 45 03 5f c3 43 09 +ad + +# Signature: +1b 87 05 1f 15 91 c8 ae 7e e3 cb 24 26 70 39 a7 +28 40 5d bf 23 1c af 21 f3 24 7f 05 85 8b 2a 51 +65 0b 81 bc 53 77 86 5e 4c 1e 8f d0 36 41 52 a1 +6b c5 8f 7d 2a c0 1c a6 79 cc 49 dd 04 89 03 d5 +5a d0 5f 10 2c 74 b3 60 1f 25 ad 30 62 40 25 c3 +0b 6f 0f 79 11 fc 22 45 8e 5d 43 5f 38 8e 3f bc +49 5f a0 c6 10 c1 29 8f 82 1d a5 38 40 3a 93 36 +4d 2e ab f1 e3 b3 2f 81 10 a7 e0 3e 37 2e cb c5 + +# PKCS#1 v1.5 Signature Example 2.12 + +# ----------------- + +# Message to be signed: +b3 da ba ca 20 59 a7 0e 25 cb dd f4 aa 59 25 99 +57 54 ac e4 3c 5d 60 36 40 48 9a f4 8f ea 6e dc +4e 19 cb ee a2 c0 db 62 ae 0a 10 4c 72 e4 cd 56 +cb 53 2f 4f e5 77 b3 6a 81 98 b4 87 9d 7f f8 04 +26 90 f6 62 77 3f 3d 63 93 f2 58 98 d2 + +# Signature: +26 f1 37 70 26 3f c5 bd be ad f8 8f b4 dd 30 7a +38 95 9b 16 f3 df 94 6a de 86 4b 1e 7e 91 4d 36 +4e bf 9a df d8 6a 70 02 2d c6 1b 43 fb 1f df 86 +96 97 8e 2d 1f 6a 2d ef ee 75 ad aa 69 a3 95 32 +07 40 50 be 70 8e af 03 1d 5f ae 0f fe 24 5b a4 +ff 3c 5e 34 0a f5 df ec 6a 4c ce 0e 18 87 6c fc +13 66 ee ed df ce 0f 83 5b 38 e8 18 81 b1 fc 58 +32 93 0f c7 9b 08 f1 fb 34 fb 22 42 33 f4 c4 68 + +# PKCS#1 v1.5 Signature Example 2.13 + +# ----------------- + +# Message to be signed: +09 91 12 fa e7 40 88 8c ea ac 70 54 d5 97 35 1d +79 e1 59 a9 58 d8 12 15 78 e5 2c 83 7d b3 54 3c +fa 6f 8e 7f 1d bd 2a 61 97 86 45 a4 d3 85 b9 bb +1c 60 bf b1 1b b3 c8 75 2a e3 1f 99 6d bb 52 62 +8f 93 d5 26 94 f1 82 e6 90 35 a5 e5 57 ec 71 82 +62 f4 03 df 52 11 f7 3c 6d e0 d5 5a 0b a7 + +# Signature: +8d 8c 8f 3a 86 f4 9e db d1 25 c8 3e bf 6d 52 e7 +65 16 15 01 48 21 54 59 8c 28 3a be 94 02 77 87 +2b 00 d0 77 7c 2e 69 7b 78 83 cc 32 1e 15 1c 80 +11 6f 9f cd 17 7a c4 c7 de dd f0 3c a1 b2 c5 93 +31 dc 1c 8e 94 7f 1e b2 aa ee 8c c9 41 dd c5 f3 +74 a6 3d 6c 99 38 ec d8 e8 8c bc ec 58 92 9c ff +dd ef 0b a2 17 58 85 a8 0d c4 cd 92 d6 b7 9d 9c +6a 81 69 6e 16 f9 a8 3a 10 ca 8e fa f1 97 5f 55 + +# PKCS#1 v1.5 Signature Example 2.14 + +# ----------------- + +# Message to be signed: +aa 17 e6 bb d6 db 19 e5 4b ee 1a 7f 0e dc ca ce +ab 63 5d 76 28 fc aa 18 ec fa fc 40 1c b3 fe b5 +1f 9a 37 31 f3 80 2c be a8 1c 73 30 28 c9 58 4b +6b 78 e2 05 59 54 cf 91 04 da a6 77 aa 40 be 9b +7c 65 b0 7a c4 a8 bf 25 c1 14 9e 05 47 35 cf 3c +e3 32 d4 29 bc 73 80 24 45 df b3 68 8b b8 19 48 +b5 7e 27 6a f3 24 62 f7 ad 80 4d 50 c9 3b c7 e9 +ef 75 37 69 5a 27 1a f7 2e 4b d4 7c e5 fa 9d 62 +f2 da c0 33 36 23 f4 9e b9 d6 d7 80 34 ed 1d f6 +e1 2b fd 04 26 1b be 5c e0 40 e0 3e be 25 8d 2d +05 2a 12 ad 4e 3b f2 53 04 23 01 c7 64 58 ed 91 +0c 5f fa 70 5c 74 7a d8 ca 0c 1c 62 28 da 2c 97 +e1 38 + +# Signature: +64 4e a0 76 21 4d bd dd 30 05 5d 7c 56 18 92 27 +9b 46 ba b1 e1 22 53 42 4c 28 f4 49 e1 72 64 6a +f3 49 8c 7a fc bf f7 68 e0 46 a7 c2 e3 d9 c0 e7 +12 8f 87 7b 92 19 5a a2 bb 9f 1c fb df d1 5b b6 +5f bd 23 ef b2 94 fb b1 1a 3c 66 05 6d 60 63 85 +3b b2 3c 27 46 65 a1 3e f4 f3 c1 2f 59 21 a4 19 +e9 49 b3 0c 0b c0 d7 7d 6b 28 69 1d 23 64 d9 5b +f6 8b e8 d5 97 8e f1 bc 98 52 a4 f0 66 04 47 4a + +# PKCS#1 v1.5 Signature Example 2.15 + +# ----------------- + +# Message to be signed: +28 24 9c 38 7a 06 14 40 e9 86 38 e1 ed 78 a4 86 +51 30 e5 75 33 d7 89 10 8c 63 e1 5f d8 01 9b ad +2c d1 a7 55 2b d8 af d2 06 d9 78 eb 1f 2c f3 f2 +3a fc 4b 34 e6 dd 7f 69 c1 fd f4 fe c2 52 68 d1 +86 55 51 94 49 22 90 6d ce 6d c4 41 f9 4a 46 6b +f8 39 1a d8 2b f5 94 0e 44 71 10 f1 d1 5d e1 29 +31 29 fb 44 24 a1 71 75 19 d6 d4 28 d6 6b 7a 10 +91 42 ac c9 15 f1 ea c9 6d ef 2c 32 90 b0 1d 05 +99 0b f8 02 3a 6a 64 71 2f 63 13 7a 8e + +# Signature: +57 02 06 06 69 ed 47 bb ca 11 b9 16 68 28 9e a3 +f5 e7 46 ad 2e 38 6d d1 bc 2a 8b ab 17 46 ba 2a +64 bf 15 b3 fc 2e c8 b0 cc 99 d8 54 fa 32 11 c9 +55 c4 55 d7 ff 2e 1e e2 39 f5 4f 38 6a 42 bb 25 +40 a8 75 8f 32 97 e5 52 de 1e be 8e ac 70 f3 54 +87 94 2b ba da d5 bd 95 73 90 ff 17 93 af 3d 30 +d9 36 b6 f7 9b 44 a9 b6 3c ee 62 d5 58 4d a3 a1 +fc ff a5 b6 fe ee c1 1c d6 3b 18 0f 0b fc 5b 6b + +# PKCS#1 v1.5 Signature Example 2.16 + +# ----------------- + +# Message to be signed: +e4 91 a1 56 fd ba 31 6a 2a 20 a1 2e ea 50 be 77 +4e c9 aa be b1 c3 98 e9 08 be a3 29 68 21 7e a4 +1e 96 6d b7 27 2f 0e fa 37 c9 0a e4 e9 f3 86 21 +a6 27 a9 d1 2c 8b 4e 80 60 c5 45 c5 60 59 e9 e4 +8a 7f 16 81 36 72 47 33 58 19 ba 12 7e 65 93 1e +1d 9f b7 0d fd df 4c 99 56 a5 b0 4c 52 bc f8 cb +df cd f2 29 19 64 da fa ca 7e e7 0e 80 a2 75 9c +ec 73 5d 01 ac a8 ff 89 4b 68 9b 93 78 3d a8 93 +9c 62 09 dd 68 3c 60 + +# Signature: +9f 20 5b a9 0d f2 d4 01 49 26 48 1f 9b 3f 45 a8 +9d 23 ec d8 4f 5f 16 e6 73 34 c4 ca f3 f3 b9 c2 +01 a7 98 d4 ee c5 62 76 59 88 23 18 0e 07 8d 0a +ef 4f 8f ba 0b 25 c1 fd a3 e3 36 54 c4 74 a9 c1 +1a 23 b0 87 10 91 3d ff 76 56 f0 e7 ee 22 cc 44 +c9 99 c0 95 a6 51 4a 9d 2f c0 ca 4e f2 08 de 0d +92 93 b0 c5 60 8b ae d1 07 4a 0c fd 57 b9 9e f8 +ce ab fd 34 72 b7 db 3a b9 60 6d 13 f9 bb 43 9a + +# PKCS#1 v1.5 Signature Example 2.17 + +# ----------------- + +# Message to be signed: +06 ad d7 5a b6 89 de 06 77 44 e6 9a 2e bd 4b 90 +fa 93 83 00 3c d0 5f f5 36 cb f2 94 cd 21 5f 09 +23 b7 fc 90 04 f0 aa 18 52 71 a1 d0 06 1f d0 e9 +77 7a d1 ec 0c 71 59 1f 57 8b f7 b8 e5 a1 + +# Signature: +45 14 21 0e 54 1d 5b ad 7d d6 0a e5 49 b9 43 ac +c4 4f 21 39 0d f5 b6 13 18 45 5a 17 61 0d f5 b7 +4d 84 ae d2 32 f1 7e 59 d9 1d d2 65 99 22 f8 12 +db d4 96 81 69 03 84 b9 54 e9 ad fb 9b 1a 96 8c +0c bf f7 63 ec ee d6 27 50 c5 91 64 b5 e0 80 a8 +fe f3 d5 5b fe 2a cf ad 27 52 a6 a8 45 9f a1 fa +b4 9a d3 78 c6 96 4b 23 ee 97 fd 10 34 61 0c 5c +c1 4c 61 e0 eb fb 17 11 f8 ad e9 6f e6 55 7b 38 + +# PKCS#1 v1.5 Signature Example 2.18 + +# ----------------- + +# Message to be signed: +31 1c 88 80 05 35 d1 b4 e9 bc 78 65 18 31 a3 e9 +67 e7 4b 58 28 e0 14 11 5f be 5f 60 9c e8 65 fe +d2 41 97 0f 87 2e c8 f2 3d c2 bf 61 6b 80 20 e4 +45 64 f9 34 dc bf 72 38 61 70 07 4d 92 0b a8 95 +d3 3d df 27 93 69 f2 36 a1 9a cd 4f eb 2b + +# Signature: +89 46 63 e6 3e c1 9f 56 20 3f 4a 44 6b 5e 2b 51 +74 c8 14 a5 4c be a2 c8 e2 98 f9 9b 34 c4 bb c2 +c8 b1 77 ba 98 57 d8 1c 85 44 36 bd 99 af 58 c0 +9d de 5a ca d2 d6 41 50 43 fb 40 e7 84 75 ef 74 +01 2e 4d 4f 75 b2 e9 58 85 c8 51 a2 3b 4a 25 54 +93 f3 0c 17 2e ae 01 d4 79 10 fa bd 26 9f 57 94 +0b a4 43 50 6c 05 22 bf 72 8a 25 7a c1 07 3b df +99 b4 29 56 db 00 2a 30 a5 4d bd af 28 4d 8f 69 + +# PKCS#1 v1.5 Signature Example 2.19 + +# ----------------- + +# Message to be signed: +b2 65 a9 77 7f aa f1 58 a8 08 aa e7 08 5a 83 e7 +07 9c ef 80 d5 fc 9d 7c dc 96 3e c9 + +# Signature: +28 1e 88 ce 19 0e 98 62 90 34 36 a8 6b a4 37 27 +16 44 9c c0 ce 8d 55 4f 70 2d 72 52 a0 67 60 af +42 12 1d d0 9b f6 ea 13 f0 eb 25 2e cc 76 42 10 +61 f5 74 4b d8 e3 2c 5a 8c 4f c1 f9 52 1b 3f 5c +29 14 6d d0 59 12 91 ac bd c5 b6 3b 55 1d 22 8a +e5 38 95 b1 97 e6 e2 7a 70 68 aa 31 03 b7 0c fb +30 f4 15 84 5c 7e 52 87 f1 11 4e 4c df b4 01 ed +51 98 64 cf 61 bc 46 9c 66 69 9b 29 60 a0 af f2 + +# PKCS#1 v1.5 Signature Example 2.20 + +# ----------------- + +# Message to be signed: +7c 43 9e 7a b9 90 cd ef 95 6c 42 39 47 9b 49 da +84 2f 8b 76 76 5a 7a d4 89 7b c1 6c 61 ed 3d 09 +80 5d 76 e8 a5 be 8b 57 8b 95 1f 45 45 df 92 a8 +a5 37 ba 3e 2c 13 dc e0 a0 03 e7 b6 24 9e 32 be +94 1f 21 cd a7 25 b8 04 07 be 1e 28 bb 9e 39 37 +38 32 53 56 ec 21 74 1d 5c 86 f3 c2 b4 f7 b9 47 +af d5 6b 2d 3a ec + +# Signature: +6a fa d7 7a 05 6d 07 29 05 86 e9 13 80 9a 04 37 +d3 9a b3 07 32 45 12 b2 f5 bc 2b af 58 0b f4 55 +43 eb 04 ff 83 e9 63 a6 d7 f3 3e 9d ff c1 fc f4 +24 48 c5 fc fa 47 27 19 c6 51 f8 1f 3c 62 22 98 +3d 38 91 7e 29 b4 84 85 87 9c eb b0 a6 1d 38 9e +23 8c 9c 71 c3 68 ed e4 08 3a 94 62 97 f7 19 0b +4c ef 86 7e 9c cd a8 f9 ff c6 19 84 fc f0 5d 4f +ba fe 10 7d ac f5 b1 dc 8e 2b 14 95 b2 44 f8 e7 + +# ============================================= + +# Example 3: A 1024-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +b5 d7 07 b7 92 e0 56 f7 2f d7 6d 8d a8 89 a5 3c +e4 d8 eb aa 08 2a ee b2 30 32 e3 c5 d8 eb c4 c1 +55 61 31 9b e8 df e1 88 99 1a 89 51 d4 b2 3a 51 +e8 a9 38 2c 80 5e 4c fd 49 0e bb ce aa 20 80 2a +d6 83 b0 5a 10 0f 29 98 5f 01 1c 3c 8a 44 26 25 +52 d8 3d 9a 1b 7c 27 31 5e 14 4a d8 df 5c be 8b +c6 40 0f d9 cb e7 6b 74 21 d7 08 aa 64 f0 40 ba +e0 7b 7b d6 f9 22 18 f9 a7 29 28 4c c5 98 cd d1 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +b5 d7 07 b7 92 e0 56 f7 2f d7 6d 8d a8 89 a5 3c +e4 d8 eb aa 08 2a ee b2 30 32 e3 c5 d8 eb c4 c1 +55 61 31 9b e8 df e1 88 99 1a 89 51 d4 b2 3a 51 +e8 a9 38 2c 80 5e 4c fd 49 0e bb ce aa 20 80 2a +d6 83 b0 5a 10 0f 29 98 5f 01 1c 3c 8a 44 26 25 +52 d8 3d 9a 1b 7c 27 31 5e 14 4a d8 df 5c be 8b +c6 40 0f d9 cb e7 6b 74 21 d7 08 aa 64 f0 40 ba +e0 7b 7b d6 f9 22 18 f9 a7 29 28 4c c5 98 cd d1 + +# Public exponent: +01 00 01 + +# Exponent: +45 17 92 b5 94 47 cc 93 78 a8 a4 d6 45 fb 22 ff +4b bf 06 70 61 51 1a c8 36 db 27 43 a6 24 13 6b +18 6b 69 43 a1 cc eb 6f 91 29 0d 93 3b bb 8a c0 +53 a4 74 95 28 23 6c a2 72 cf 77 d9 d3 37 ad 2a +b3 6a 87 a9 15 3c 5e 16 71 6e 09 ba 0b ea a6 4b +31 25 26 d4 a8 c2 dc 68 fe 09 e3 7e 50 74 a0 90 +9d 3f 04 ab 73 90 8a 98 0d ec 1d a7 eb 45 05 a4 +8b ca d3 b6 0d 01 60 84 58 64 a6 51 1f f5 59 a7 + +# Prime 1: +ff a9 f8 e8 b0 82 17 0b 63 73 f0 0d 73 c4 23 86 +d4 02 f2 80 8b 39 3b 32 f7 8f 86 ea f6 4b 21 bf +dd 33 4f b9 aa d1 6b a6 d9 da db c8 94 3a 29 e6 +63 c8 b3 9c 09 59 69 02 5b b9 b2 d9 d6 fe 67 b7 + +# Prime 2: +b6 14 37 8d 5e 3d a5 a8 0a 6d 73 52 fc 66 a5 64 +59 7b 06 8f c9 d3 af 5d b0 e4 e7 35 be f8 81 dd +40 17 ee 70 82 96 19 0b 6f dc 84 04 f0 7b d9 dc +5c d5 d2 be 48 86 a7 cb bc b2 1d 8c 3d 64 a6 b7 + +# Prime exponent 1: +51 0e 68 96 0d 70 11 32 51 23 ae d5 f5 00 18 6b +64 c8 52 6e 22 b5 d0 69 06 48 00 f4 79 85 b4 7b +89 fb fc a8 d6 d9 72 92 01 bb fb b6 8a 18 2e b4 +96 aa 49 17 8d 77 45 6d b3 fb 1a 13 2a b0 99 dd + +# Prime exponent 2: +57 eb bf 3f 76 48 52 5b a8 5d 5d 98 ae e4 69 ec +e1 00 75 14 ad a2 98 45 a7 8b 80 d2 05 1b 3e aa +35 ae d8 a6 5f 88 57 23 9c aa 60 dd 79 ba 74 62 +e2 39 26 00 58 49 1d 71 55 f6 b4 29 e9 e3 56 55 + +# Coefficient: +ee 10 7d c7 ef ec e9 a6 5c 0e 87 78 9a f5 59 0c +93 83 9d fe 82 85 20 da 17 74 ff 80 f7 e5 14 55 +7f ff 10 bd 8c ae 18 46 ef ee 7c 10 d7 a1 2c 4a +05 5c c1 36 e4 a4 ef 25 fd 3e d9 d0 cd df 74 f9 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 3.1 + +# ----------------- + +# Message to be signed: +98 6e 7c 43 db b6 71 bd 41 b9 a7 f4 b6 af c8 0e +80 5f 24 23 48 8f b4 31 f5 ee 79 2b 6c 2a c7 db +53 cc 42 86 55 ae b3 2d 03 f4 e8 89 c5 c2 5d e6 +83 c4 61 b5 3a cf 89 f9 f8 d3 aa bd f6 b9 f0 c2 +a1 de 12 e1 5b 49 ed b3 91 9a 65 2f e9 49 1c 25 +a7 fc + +# Signature: +62 75 e8 73 97 e3 09 2a ab 36 98 bb 1b 5c f2 4b +8c d7 71 2b ec ac 35 e3 22 03 d5 43 14 e5 47 0e +a9 aa bc 86 57 f5 64 34 e5 af 9f ae 77 8f f6 04 +5c 20 e2 e1 ef 7c bd f8 8f 00 75 f3 3e a9 92 77 +7c b7 e9 2f 7d a1 8a 0f fd 00 aa 46 71 ed 63 91 +1f e9 e9 2f b4 a7 6e 77 dc 6e 0a 91 65 76 71 6c +15 ea ef 08 9a 71 a0 ae a3 5b ed 94 47 a6 c1 7f +2a ad b7 27 fd 42 f0 ac c8 24 62 38 1d 9f a2 ef + +# PKCS#1 v1.5 Signature Example 3.2 + +# ----------------- + +# Message to be signed: +4c 7b 98 12 0c 87 50 90 87 c4 78 + +# Signature: +59 e5 cb e7 33 1b 92 e0 cb 8f 68 9e ae bb 30 f2 +b3 34 a7 46 a6 57 05 59 12 ff 1c 92 76 0b 0b 85 +bc 42 82 f3 18 4b 9a 81 4f 44 37 f8 25 ae 07 d3 +56 ba c6 9e 54 0c 90 94 2c 7f 7e 6f f4 4f e5 74 +f1 21 25 0a d2 30 f4 b5 0c 78 31 1e 4f d3 c9 e2 +65 f5 17 ce 32 97 c3 e1 dd db 5c 86 9c 69 8f 44 +af 52 5e 73 64 01 a8 1b 45 9f 19 8a d1 80 8c cd +92 9d 49 04 74 ca f7 00 5f 91 0d ac de 21 b0 77 + +# PKCS#1 v1.5 Signature Example 3.3 + +# ----------------- + +# Message to be signed: +66 f7 07 54 22 c8 ec 42 16 a9 c4 ff 49 42 7d 48 +3c ae 10 c8 53 4a 41 b2 fd 15 fe e0 69 60 ec 6f +b3 f7 a7 e9 4a 2f 8a 2e 3e 43 dc 4a 40 57 6c 30 +97 ac 95 3b 1d e8 6f 0b 4e d3 6d 64 4f 23 ae 14 +42 55 29 62 24 64 ca 0c bf 0b 17 41 34 72 38 15 +7f ab 59 e4 de 55 24 09 6d 62 ba ec 63 ac 64 50 +32 7e fe c6 29 2f 98 01 9f c6 7a 2a 66 38 56 3e +9b 6e 2d 15 ef d2 37 bb 09 8a 44 3a ee b2 bf 6c +3f 8c 81 b8 c0 1b 7f cb 3f eb b0 de 3f c2 5b 65 +f5 af 96 b1 d5 cc 3b 27 d0 c6 05 30 87 b3 96 80 +e4 92 a4 ab 23 67 47 11 69 e5 28 38 94 5d ba 9d +d7 72 3f 4e 62 4a 05 f7 37 5b 92 7a 87 ab e6 a8 +93 a1 65 8f d4 9f 47 f6 c7 b0 fa 59 6c 65 fa 68 +a2 3f 0a b4 32 96 2d 18 d4 34 3b d6 fd 67 d0 0b +25 b8 1b 09 b5 62 03 85 64 + +# Signature: +59 9e 69 c1 54 e4 fe 66 b3 6a 69 04 92 fa eb b2 +bb e7 34 e0 41 5d 9f 3c f7 e3 78 28 f5 3e 61 13 +04 49 17 3a 33 46 0c 6b 4c 8d c7 d6 81 ca 6f 4d +af 1c b8 16 d4 0a a9 08 2e e1 93 7b e4 bc 6a 09 +c6 de 79 8c 82 86 fc d2 a2 b2 19 6c 59 99 4c 93 +7f 37 13 07 52 61 2c 6b ff 6d bb 53 e0 64 7f 88 +58 bc 38 38 64 02 1e 6d 56 68 19 20 24 92 97 82 +22 46 a0 f5 28 aa b3 ed 18 5e eb ce 91 9c f8 3e + +# PKCS#1 v1.5 Signature Example 3.4 + +# ----------------- + +# Message to be signed: +d9 34 44 28 fa 8a 58 f8 fa 7b 44 3e 51 fc 9b 51 +e3 7a 70 21 0d b8 bd 1d e7 f8 67 5d 84 79 ff 65 +7c a7 29 55 b2 3c 6f 4a 09 16 37 9a 4e de e1 f2 +6c 85 e0 52 90 21 1e eb 25 83 2b 09 cb e5 ea ed +3e 39 65 b0 5a 52 fb 5b 16 49 11 82 c5 91 3c b1 +82 57 48 e8 1a d0 14 f1 3d 29 6d c1 69 57 08 2b +1b 83 b4 be 50 a0 f9 59 c9 e7 f3 aa 80 77 97 2e +2b 93 c2 ef fd 9f 30 86 25 b8 ca 7f 54 d7 b6 96 +48 79 04 47 ac 91 f7 98 5e 51 0d f7 0d 6e bc 35 +72 c2 05 e6 + +# Signature: +2c 06 01 65 fc c5 65 5c 06 57 c8 fe 08 e0 5b dc +8c d7 7c 1f ec b6 d1 8b 89 38 11 c9 9d d0 91 e0 +d8 50 6d cc b4 9e 33 da af f6 da 96 7b 99 e3 44 +cb 17 fa 3c 96 31 29 9b 35 89 81 8b 37 ed 9d 5d +78 94 e4 a6 9d db 24 83 2e 1a 88 60 01 4e e5 e5 +eb 95 3e 8b 35 48 4b a4 fe c9 c3 03 3a e2 e1 18 +9a f7 94 a7 2e 42 67 21 5b fe 45 8f 0f ce 6b 37 +a5 54 9e f8 05 43 d0 d4 1a 87 b2 c6 e4 d8 4c b5 + +# PKCS#1 v1.5 Signature Example 3.5 + +# ----------------- + +# Message to be signed: +8c 67 02 da af 58 f6 a4 75 fa d2 c7 a4 bb 15 6a +57 06 42 55 77 d5 e3 0c 6a 6b d3 66 9f d0 30 af +d7 89 fa a3 d0 10 18 d4 5d b2 a0 47 f5 2c b4 f6 +3d ea 36 09 42 af e4 76 26 42 06 d9 83 ad 38 36 +e1 55 c5 6b 2e cc 08 76 3a fb 9f d5 1d 19 99 0e +fc 33 63 f6 57 e2 85 e0 35 21 e8 ca d0 1d 2c 93 +5a 18 3a e2 3f 0e e8 71 00 86 a8 5b 9f ad 4e 7f +2b 09 45 2e bc 40 3c e0 c0 e5 75 5a 7b 2f 33 f4 +de f0 db 71 c9 79 31 ff 90 4a 81 31 99 84 bd c5 +16 6f 6b 92 0c 97 ee 74 fb 7e 89 0f 49 0c 90 de +30 ca c9 76 b7 17 23 e2 f8 6e 9d e1 d5 03 a4 1b +c8 1d 53 cc be f8 ac 40 53 57 d9 df df 30 64 66 +b4 26 95 80 21 2e 9d 71 32 + +# Signature: +0d 89 fc f8 44 a9 dc 22 3d 5f 63 8d cc 3a 59 78 +71 6f 26 28 b8 a8 3a b3 3e 6e 25 5f f8 aa 01 57 +8c 14 e3 89 7d a4 5a ef d6 3f a8 7c f3 5e 24 4b +f4 82 8e cd 21 95 0f 30 85 a3 66 21 c9 da 1b be +7e a6 27 31 c6 8d 4d e0 a3 76 e2 2d ac 2f 54 8c +d4 ba 4a 54 2e 71 0f 55 ce 85 a9 c1 95 93 c0 8c +87 d2 96 d6 35 87 b3 fe 2c 5d 11 65 ee 27 74 4c +75 d8 f4 f1 43 71 63 7c 0c 0a 44 62 76 28 95 83 + +# PKCS#1 v1.5 Signature Example 3.6 + +# ----------------- + +# Message to be signed: +56 f4 ff d1 27 9d cf e5 62 a9 dd d4 1e cd f6 0a +3f f5 82 46 bf af 95 65 cf 67 4b 0b 90 75 f4 0e +ea c0 8f 0b 89 66 61 8a 19 6b 12 28 eb ce 93 fc +9d d7 9b d4 63 ea 7d 2c 97 4d 2c 2f 53 9e af b1 +b2 bc 1e a3 4d 74 f7 20 e1 19 34 2f f7 13 12 25 +aa 9a da 89 4b 76 b2 ec b1 2f 2f 40 28 44 b4 42 +5c f8 f1 a3 9b 0a 9c 83 b4 5b 03 cf c0 d1 5f d3 +14 d6 ab f5 32 b8 ed fc f2 36 51 4b 2e 45 86 97 +86 fe fe 27 f5 4d 66 6e e5 24 e4 b9 c0 53 be 39 +75 01 58 29 91 fa 2d 80 2c 7d 1b 17 8b 23 e9 b6 +ec e6 fd 2e f0 13 2c 06 01 a8 6f 07 68 ba dc 59 +c5 cc 33 f2 4d ed 55 4a e5 1a e3 ec 23 f9 dd 08 +9e 32 4a 68 21 f6 15 7f 12 84 42 ac 58 07 65 8a +d3 40 26 b8 fc fd a6 dc 7f 02 a9 3c 16 6e c9 45 +ee + +# Signature: +0d eb 39 7b f2 cf f9 79 d4 71 9c 64 8b 0a 35 25 +35 1f 5e 08 40 5c a2 61 4a 83 e5 6a ce 86 f5 52 +e4 1b b9 28 de 50 f0 bc 0f e3 1a 2e f2 ad 79 9f +d3 cf 47 42 b1 13 1a 37 bd 08 f2 a1 3c ac da 67 +f4 95 c9 f1 a9 ef 64 85 70 72 32 9f 00 cc 4c 01 +22 35 59 9a 83 fc 45 94 fe d9 23 03 49 01 ed c2 +7d 5f 05 79 98 34 93 5c ab e2 64 ff c1 96 63 71 +4d 8c 3d e8 e9 61 9f d2 84 2d 22 98 f7 a7 2c 99 + +# PKCS#1 v1.5 Signature Example 3.7 + +# ----------------- + +# Message to be signed: +0e 79 ac 9c 9c 03 96 d9 69 fb 3f 7c c9 94 7b 07 +8b ac 49 3b 03 52 c8 e0 cd e5 46 3e a5 c1 18 4f +d5 2a 1f b7 48 19 3c 14 7a 74 80 0d 24 f7 51 ba +93 5e 19 c9 11 5e df 07 22 88 33 0b f3 83 f4 95 +29 6b e1 aa 4a 50 95 b9 57 3b cb db 22 8a 43 13 +12 37 86 5d 26 df bf cf ef 07 8f 35 9f 9a 95 62 +e2 5b 69 63 85 e1 28 13 ff fb c8 d5 29 81 9a 91 +45 1d 33 a5 07 26 39 2e 4f ef 29 41 8c ca 2c 73 +a0 68 e6 0e ae 31 84 70 33 1a 0f 1d b4 bb b6 37 +17 3b e8 0f ea 03 c8 2c 15 d0 01 93 36 2d 3a 18 +ad 9e 2f 68 05 00 d7 26 5b 15 57 03 3a 52 09 77 +d8 10 fc + +# Signature: +73 3b 7f ea 12 0c a5 f0 35 9a 89 05 75 0c 49 c3 +63 d8 84 f5 6c 2b 7a 72 9f ad 7b ff 44 5a 1e 54 +79 89 41 74 53 93 e1 76 77 12 ac 4b 9d d2 68 38 +88 d9 e6 8b 90 5d ba b8 79 21 85 18 48 72 73 86 +02 ea f4 a8 0f 45 95 f7 8f d4 a4 61 0b f8 22 0b +86 a2 88 5f da 24 e1 99 64 28 cc d1 5f 20 08 e0 +68 51 b2 ee ad c3 dc 8e 03 01 2f 9b db 3c e0 57 +5d dc 3a dc 7c 59 08 49 8b 69 a7 97 ba 58 29 c7 + +# PKCS#1 v1.5 Signature Example 3.8 + +# ----------------- + +# Message to be signed: +22 eb 7d ba 73 30 7c 7c 52 a0 7c ed 89 db 8b c5 +39 4a ed 22 72 f7 e8 1a 74 f4 c0 2d 14 + +# Signature: +9e a4 60 0a 1a 65 49 fd 39 75 f6 49 8a 04 d6 9f +96 fa d0 e8 e6 fe bc fb e0 1c 2f 83 17 0b c7 4e +b9 1f 2e 33 53 38 d5 83 e8 85 aa c6 14 24 c9 b2 +66 c3 d2 d9 8e 79 77 ff e4 95 f9 c1 a6 ee 5e f4 +1a 4c c7 47 8c 24 b3 16 c7 d9 f6 db aa 65 a4 ca +de f1 81 ca 94 6f 9b 92 18 4f ae ca 8a 13 16 ae +ab 5c d3 87 8c 6d f0 74 f9 06 0b 9d b6 6d ec e9 +a9 36 7d 75 49 03 5a c6 bf 19 62 36 5e 1f d3 fc + +# PKCS#1 v1.5 Signature Example 3.9 + +# ----------------- + +# Message to be signed: +f6 80 + +# Signature: +51 63 90 61 fa 7b 7c d5 df 64 b3 0a 39 4c cf 7e +24 26 97 2a a1 dc f5 d4 5e b8 ec 2c d9 0b 9b 19 +68 92 be 5f a0 3c 43 f3 c3 72 3a e3 13 0d 61 51 +b3 3a 63 7c fc 50 ba 35 26 a7 39 6c f8 47 9c 50 +8c 18 11 81 0d 68 b3 88 0a f6 e6 4b 16 bd 70 79 +be 9c 00 39 29 51 22 61 89 8f a5 7c 06 ff 7e 1d +80 39 fa 99 3f d2 05 6a c7 01 9b 8d bc f2 53 0d +53 80 e6 01 a4 a1 87 1b 86 c2 0b c1 c4 89 c5 f3 + +# PKCS#1 v1.5 Signature Example 3.10 + +# ----------------- + +# Message to be signed: +65 0e 64 ed 1d a8 8b cf 8a e2 75 22 be 1d 5c 99 +19 f2 09 9d d6 32 45 5f 66 d9 af e8 ba f4 6c c8 +a1 98 40 9b 09 28 dd 87 22 62 84 d6 69 bf 01 bc +ec 44 37 6c b0 e9 bd c6 86 ac aa 8b 46 34 86 08 +59 94 ca fb 5a 8c fc 33 d4 9c ee f4 79 fc 6e 04 +f8 ee f6 37 eb 68 cb 57 81 8d 5f 97 70 ac 52 3e +d5 b0 16 38 36 7f f4 7f + +# Signature: +50 3e 05 66 1d 68 1e ca 57 4e 02 30 af 2d aa 87 +7b 90 51 6e 5e 19 72 8c 91 76 8d 6e ef ee 00 1b +35 41 9c 5f cb 56 11 d6 0e 7e cb e3 c9 5e 5c 88 +ba 93 46 07 04 f1 69 4a e8 04 44 eb 97 18 a0 8b +66 86 fa d8 6e 52 59 90 c3 c1 a6 6c 8c 53 aa 31 +ae d8 cb c4 0f d5 4f 5f f8 a1 34 74 9d 79 d3 8f +bb 0d 58 44 26 78 ff 2f 70 c6 c5 0f 25 47 2a 72 +d6 32 05 e7 82 42 3d f4 0b 6c 43 de 03 a1 8f 8b + +# PKCS#1 v1.5 Signature Example 3.11 + +# ----------------- + +# Message to be signed: +57 f8 ac 6a 9e 46 8b 7f 1f 74 5d ff e3 9e 9c bf +90 24 a0 ff 36 e0 22 83 92 be 6b 29 94 29 17 76 +b8 9c 0a 4b 1f a8 6b 2e c8 bb 7c 3e 64 f5 58 5a +fa 77 + +# Signature: +90 be 16 b4 08 b3 85 73 95 39 b3 b9 a2 9b 94 c7 +29 38 5f 79 dd 4a 79 81 1e 6f 67 c8 0e d3 59 e5 +f4 b2 a1 9c 22 2a 82 b3 d6 d6 2a 90 3f b1 80 c1 +f4 3c b3 fe 06 a2 50 bc b0 e7 c6 88 66 5c 83 68 +a1 1a b1 16 0a db 74 02 91 35 2b 38 38 b6 92 3a +4a 37 ad 06 04 0a 53 59 20 dc 0f 10 57 9e cf 48 +1c d4 41 37 17 d7 d4 d9 60 aa 75 1a 74 3e 2f 7c +61 6e 54 2e e6 5f bb fe 24 66 0e 10 1d aa 2b dd + +# PKCS#1 v1.5 Signature Example 3.12 + +# ----------------- + +# Message to be signed: +80 ef 01 aa cc 5b fb 0d b4 8c 6d e3 d8 14 95 b9 +c2 31 1a 38 93 89 f2 3b 70 c0 24 da 44 78 bf ab +2b fe 4e 54 6f 13 ff fd b9 63 89 4e c6 da db 3d +2b 0e e3 37 f1 16 31 05 8e ac 86 09 e5 a1 55 4a +f7 97 a9 f9 ab 47 8c 2d 5b 91 88 c8 25 + +# Signature: +44 c3 f5 1d cc 6f b2 b4 e7 0f 53 7f 54 64 c6 32 +0a d4 2e 21 28 fa df d9 a7 e9 37 cd 65 dc bf 35 +ac 66 cf fa fd 39 28 39 66 f2 f1 5d e5 27 72 35 +50 71 5a 31 04 29 45 e2 00 cc 5c 86 fa ba 5e c8 +ab af 50 9c 0c cd 64 d9 9d ed c7 6e 3c ea a8 c4 +47 17 93 37 f4 a0 77 7b 11 52 6e 47 2a cd 41 3b +4a c7 c3 03 cd cd 84 ca fc 02 52 43 ef 00 6f 79 +dd af 55 c1 5c c4 a8 f1 5e a2 c8 7f 05 77 38 14 + +# PKCS#1 v1.5 Signature Example 3.13 + +# ----------------- + +# Message to be signed: +ac 17 95 91 55 28 3b 0c 7c ff 51 5c 33 15 d8 9b +df e9 58 7c c0 01 20 d3 ab 31 bb 76 07 bd b3 01 +ca ea f5 e1 5f 5a 6f 58 c9 c5 68 ff b3 d2 34 02 +51 6f fe 23 0c 69 81 a8 1c 17 8a 8a 18 ca 33 0b +b8 ec af b4 81 b2 49 b4 66 a8 cf 78 b7 0d 9e 78 +a1 39 a8 8f 48 4c ce 7c 20 35 b2 e8 9d 49 3b de +88 5e 1c de 42 cb 1a 94 49 ff 57 0d cf 9e 33 c5 +cc 77 b2 59 be e2 83 05 39 68 02 ed c1 6f c5 a8 +e1 0b 56 da 2d a7 86 b5 fb 6c 81 2b 2e 17 5b 69 +6b 1a 9a 96 fc 72 2a 43 21 46 45 0f 07 a6 48 ef +3c cf 99 6e f3 08 1f a5 bb 42 21 c9 13 ba 22 28 +97 0c 9b 0e a5 26 6b ff + +# Signature: +48 45 8c 72 f0 67 dd 9a b7 20 ef 16 0c f3 18 4b +b9 80 1e 26 d6 14 a8 89 a8 35 84 41 07 ac 01 65 +0b 11 84 a0 0b ca a7 af 1f f7 de 3a 2e f2 e7 ce +b5 b2 5c 3b 5d 5b cb 29 86 59 34 32 47 48 c6 8f +07 de 17 4e 17 80 a7 0f a2 4d 6a 3a 9f 7a 41 b8 +19 37 c4 98 4b 2c be 06 b3 d7 b4 4c da e9 cb d4 +16 32 d0 09 43 c3 b5 73 b1 aa 29 12 75 0a 9a eb +07 f1 10 13 0b a3 61 dc f8 f5 36 79 0d 60 78 47 + +# PKCS#1 v1.5 Signature Example 3.14 + +# ----------------- + +# Message to be signed: +99 09 8f 77 f6 ed 35 c0 8f ab 3f a9 78 86 93 67 +1a 58 00 dc 30 3c 9c ce 42 46 16 fa 0c 7e e8 88 +86 87 67 4c a8 8a b2 2a 5f f2 d1 2e 2b 38 8b 09 +4f fd 7d bf 9a 09 27 a9 62 17 17 15 1e 08 ec b8 +ad e1 55 9f 4b 48 e2 3d 31 cf 57 cd 38 84 df e2 +b3 e4 b2 60 e8 96 02 94 07 96 94 96 02 6c 74 a2 +18 90 d9 a9 af d2 cb b8 f2 83 0a 56 6a ed 24 f0 +16 19 74 01 a8 cd 22 c8 2f b8 b2 28 91 84 58 24 +0a 23 d1 01 85 eb e7 72 dc 19 bc fe 3e 44 92 2f +e7 32 09 c1 ee 00 40 07 9f b0 3b 82 7c 82 17 d9 +ed 7c 98 c9 5f 30 97 4f be 4f bd dc f0 f2 8d 60 +21 c0 e9 1d a6 0c a2 ad 77 79 7e ce 86 de 5b f7 +68 75 0d db 5e d6 a3 11 6a d9 9b bd 17 ed f7 f7 +82 f0 db 1c d0 5b 0f 67 74 68 c5 ea 42 0d c1 16 +b1 0e 80 d1 10 de 2b 04 + +# Signature: +b4 6a e8 66 13 91 89 b6 b1 71 a7 62 05 fb 9c e0 +41 b4 02 98 e5 ba 92 c2 e9 cc 0b bf bb 4a 76 42 +5d e6 ce 13 02 1a e1 a4 a9 42 29 9f 98 ff 89 f5 +52 f4 3a 90 73 de 64 f4 9c 2c a3 62 0d 09 d7 e6 +e3 fe 28 22 1e 93 68 98 7e 11 0c d6 06 71 06 c4 +db 31 a0 38 90 23 67 96 c8 42 52 f5 6c 95 03 4a +01 c5 fe 98 1e 81 b6 54 85 5a af 27 47 50 11 55 +72 0c 21 93 f3 a1 d1 0f 49 fe e9 0c 52 fe e9 e4 + +# PKCS#1 v1.5 Signature Example 3.15 + +# ----------------- + +# Message to be signed: +ff 79 06 42 30 5b f3 02 00 38 92 e5 4d f9 f6 67 +50 9d c5 39 20 df 58 3f 50 a3 dd 61 ab b6 fa b7 +5d + +# Signature: +07 56 32 47 73 4f 3c 3d 7a 31 02 bc b4 5b b5 68 +15 68 ed 10 f2 ec 45 9e 46 9e 1a 9e 34 09 a1 39 +fb 15 1b 98 d3 f3 b6 2d aa ac 8b 8f 89 16 df 85 +d6 df a9 ab 76 0d f1 e1 5a c8 90 44 e5 79 cf 47 +a1 af 6c d6 ec 70 4c ed 9b 03 4c 6a aa 90 d0 e7 +0e 08 52 14 0e 75 41 f2 ef be 2c f1 90 b9 58 94 +1e c8 b5 97 4f 9c 44 4d 26 c3 43 16 c9 21 6b 65 +95 e6 56 bc 6c 78 44 fa c1 6c 51 52 60 92 8e 78 + +# PKCS#1 v1.5 Signature Example 3.16 + +# ----------------- + +# Message to be signed: +e9 9f cb f8 59 2d be 2d 7e 27 45 3c b4 4d e0 71 +00 eb b1 a2 a1 98 11 a4 78 ad be ab 27 0f 94 e8 +fe 36 9d 90 b3 ca 61 2f 9f 22 d7 1d 54 36 3a 42 +17 aa 55 11 3f 05 9b 33 84 e3 e5 7e 44 52 28 80 +62 af c0 8f cd b7 c5 f8 65 0b 29 83 73 00 46 1d +d5 67 6c 17 a2 0a 3c 8f b5 14 89 + +# Signature: +22 74 64 36 16 4e 63 93 78 71 c1 d4 7d 8e 3e 70 +c9 e5 2d 11 17 31 6b b1 54 cd 55 2e 83 6f 2a 3f +be 6d 89 d6 07 4b 51 b0 15 9c 26 c2 8d f7 5e 3d +7c fb 7c f0 02 f6 5d 1e e5 21 ed c2 c3 a6 5c 52 +6c 98 c7 c0 25 fa 8b b6 31 47 09 16 d3 01 b8 f7 +80 9d dd 91 9d ed 31 a0 d4 66 83 ec 5b b4 41 70 +61 6e ab cd 97 02 05 ed 76 02 02 d0 d8 7a 65 79 +59 08 b2 8d 32 6f 93 62 13 f2 9f eb 59 77 34 91 + +# PKCS#1 v1.5 Signature Example 3.17 + +# ----------------- + +# Message to be signed: +6a 6a 0c 9b 5b 15 bc da 19 6a 9d 0c 76 b1 19 d5 +34 d8 5a bd 12 39 62 d5 83 b7 6c e9 d1 80 bc e1 +ca 4a f8 70 fb c6 51 60 12 ca 91 6c 70 ba 86 2a +c7 e8 24 36 17 30 6f 4f 9a b9 50 11 99 ce f5 5c +6c f4 08 fe 7b 36 c5 57 c4 9d 42 0a 47 63 d2 46 +3c 8a d4 4b 3c fc 5b e2 74 2c 0e 7d 9b 0f 66 08 +f0 8c 7f 47 b6 93 ee 40 d2 e1 80 fa e1 ea c4 39 +c1 90 b5 6c 2c 0e 14 dd f9 a2 26 ba e1 7d 20 38 +5d 50 19 55 82 3c 3f 66 62 54 c1 d3 dd 36 ad 51 +68 b8 f1 8d 28 6f dc f6 7a 7d ad 94 09 70 85 fa +b7 ed 86 fe 21 42 a2 87 71 71 79 97 ef 1a 7a 08 +88 4e fc 39 35 6d 76 07 7a af 82 45 9a 7f ad 45 +84 88 75 f2 81 9b 09 89 37 fe 92 3b cc 9d c4 42 +d7 2d 75 4d 81 20 25 09 0c 9b c0 3d b3 08 0c 13 + +# Signature: +41 93 22 fa ca ce 76 f2 d5 e2 fb c1 9a ab 86 c7 +18 a2 80 64 f1 d7 b4 c6 62 f0 47 4a 87 77 a9 59 +bd 65 69 53 8c 16 08 1c 0f 52 69 8b 2f 00 17 30 +c0 3b 9a 3d 26 94 73 74 c9 61 fd ed a1 15 b6 b7 +da f6 65 18 f1 fe 82 0f 67 c3 ff 12 f0 bc 3f 11 +01 e3 91 1c 43 90 6b 0a 12 7e 50 be 01 40 c5 ef +c4 35 e2 95 7b 44 2e 60 ad 52 5a d7 0a c9 ef 61 +c3 d6 4f 0e 56 6c bc 1f 9d 51 ba e1 d4 72 71 da + +# PKCS#1 v1.5 Signature Example 3.18 + +# ----------------- + +# Message to be signed: +3b 93 ef 4a 55 50 96 69 19 15 dc 23 c0 0e 95 4c +de b2 0a 47 cd 55 d1 6c 3d 86 81 d4 6e d7 f2 ed +5e a4 27 95 be 17 ba ed 25 f0 f4 d1 13 b3 63 6a +dd d5 85 f1 6a 8b 5a ec + +# Signature: +ae 21 1f 4f 77 da 1b e6 af 9c 9e a7 04 db ac 4b +3f 3e 27 0d 2f ac f3 65 1d 78 7d 0e bf 59 a7 9a +39 61 2d a1 2d 57 c4 ac 8a bc 72 8e 1d a3 f0 1a +15 20 fc 9b 32 cb 0f fe 00 8c 80 69 92 8f 83 e1 +35 90 a7 8b 81 7e 81 9f bf 2f d0 58 93 ec e5 b1 +41 86 d9 01 c7 68 e3 42 dc 54 72 23 45 ae 8a a8 +73 8d 4d 59 70 c5 08 54 72 bd 98 99 fa 00 42 cf +14 bc ed ff db c0 ef 50 81 90 75 84 2f c3 6b b8 + +# PKCS#1 v1.5 Signature Example 3.19 + +# ----------------- + +# Message to be signed: +49 ff d5 6b f7 ef c1 13 04 a5 af bc 19 d4 79 24 +90 18 fd f4 e0 9f 61 87 26 44 04 95 de 11 dd ee +e3 88 72 d7 75 fc ea 74 a2 38 96 b5 34 3c 9c 38 +d4 6a f0 db a2 24 d0 47 58 0c c6 0a 65 e9 + +# Signature: +68 fb 0b d5 19 bf 6f 96 e0 76 af 29 01 2f 3c 3a +11 37 c0 98 8d e7 b6 fc ed f4 f5 1b df ee 64 5b +89 7f 17 70 9e 05 ca a0 b1 13 50 0d 90 4d c0 60 +0d 17 a9 ff 8e b0 2e 1e fc 9c 46 7a 24 00 3e f8 +1e 72 74 67 c4 7d d6 56 35 6d 70 37 2a 15 ea 88 +41 21 63 4b 01 5d 29 51 1f 28 95 55 77 99 07 9d +03 c6 d4 de 25 9b 3b 36 2b 80 49 2d 81 bc 9f e8 +54 44 63 ec 03 0b b5 c9 c7 3c 32 74 e3 ed 12 22 + +# PKCS#1 v1.5 Signature Example 3.20 + +# ----------------- + +# Message to be signed: +bc 25 5a f8 9a 6a 19 9b ca 4a 39 1e ad bc 3a 24 +90 3c 0b d6 67 36 8f 6b e7 8e 3f ea bf b4 ff d4 +63 12 27 63 74 0f fb be fe ab 9a 25 56 4b c5 d1 +c2 4c 93 e4 22 f7 50 73 e2 ad 72 bf 45 b1 0d f0 +0b 52 a1 47 12 8e 73 fe e3 3f a3 f0 57 7d 77 f8 +0f bc 2d f1 be d3 13 29 0c 12 77 7f 50 a3 34 db +6f ae bf 11 08 1a 04 f8 7c 2d 62 1c de c7 93 0b +9b 18 3a 99 04 75 dc bb 9c c7 f3 45 a3 b5 58 03 +03 0c f0 36 1a 5d 80 81 + +# Signature: +41 f6 52 df 79 fd d2 6d e9 5c 7a 98 fa 85 87 13 +fb 56 6d 8b 39 92 8e 71 76 4b 2b eb 19 84 03 e0 +3b 7e 06 dc 96 0c 50 51 57 bd f4 05 92 c4 d7 75 +03 fb 72 a4 e0 05 5f 97 4f e9 39 44 8d a3 68 f5 +3b d2 ef e2 6e 6f 9a 25 4b 3e 87 32 aa d8 16 87 +b3 61 e2 1a 40 cf 3e 5e 92 38 9a 2b 48 9c 05 c5 +97 f0 e1 64 e2 67 70 93 72 00 43 27 16 35 62 dd +8a 0a db bd fe 3b c6 16 bd 08 42 96 84 c2 0c 69 + +# ============================================= + +# Example 4: A 1024-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +d1 31 e0 92 43 37 0d d2 cd 54 25 c8 d0 30 f9 9a +db 10 5b 14 7b 8a 3d 00 67 c6 16 44 3b 7d 4b 96 +82 38 e0 6d bb 5f 20 28 e8 53 57 4b 7c 14 be 10 +83 c1 e5 7e 13 2c 1d f4 a3 a2 71 32 63 fa de 12 +f7 11 4f 43 69 bb f0 56 20 55 48 41 33 1e d8 11 +00 50 52 19 25 72 ce b4 8d 66 24 07 fd 30 81 cf +ab 8b 48 c7 e9 2d 3c 4a 26 a9 64 5a 38 e6 de e8 +8b b0 07 59 75 a4 da d9 64 6b 21 60 38 40 af 5f + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +d1 31 e0 92 43 37 0d d2 cd 54 25 c8 d0 30 f9 9a +db 10 5b 14 7b 8a 3d 00 67 c6 16 44 3b 7d 4b 96 +82 38 e0 6d bb 5f 20 28 e8 53 57 4b 7c 14 be 10 +83 c1 e5 7e 13 2c 1d f4 a3 a2 71 32 63 fa de 12 +f7 11 4f 43 69 bb f0 56 20 55 48 41 33 1e d8 11 +00 50 52 19 25 72 ce b4 8d 66 24 07 fd 30 81 cf +ab 8b 48 c7 e9 2d 3c 4a 26 a9 64 5a 38 e6 de e8 +8b b0 07 59 75 a4 da d9 64 6b 21 60 38 40 af 5f + +# Public exponent: +01 00 01 + +# Exponent: +56 b5 31 bb ee 18 37 a6 94 6c b8 6c 8f be 7c f6 +ee ad cc d2 a4 92 1b ce bb 34 a3 ae 0c 6a 56 96 +3f cb 8b 5a 70 3b 71 7d 03 2e e8 13 e5 8e 43 69 +5c f3 55 47 f8 72 64 c8 2d ba fa e8 44 00 8b 62 +d9 12 2e 9d e8 95 85 60 c8 db b0 07 72 7e 71 39 +e0 a9 82 e0 75 88 14 11 3d e5 4b a0 a4 55 17 51 +fc a0 fc b1 2d 8d e3 0d 78 b8 b1 12 98 a7 f7 8f +0b 08 8f 16 87 05 3c 84 a5 76 2f 62 a4 bd 05 c1 + +# Prime 1: +ee 22 a4 24 62 f7 71 8d fe cf 02 4b 17 c9 26 76 +78 05 91 71 33 9c c0 07 06 52 60 d3 04 7e 5f 89 +fe d9 10 34 28 43 37 8c 22 68 5d 53 2e 84 d2 59 +3a 7c 8c 02 6a 87 66 c5 a2 b2 ed 55 8e 88 23 19 + +# Prime 2: +e0 e3 70 0c 99 a3 e8 15 d7 4b 75 2a 84 fb 42 ec +20 e5 20 3c a7 c1 af 97 fb f3 97 b9 5d 11 05 37 +6c f5 d6 3e 3c 57 bf a6 58 55 e5 08 14 6c 86 db +aa b2 89 c9 5b c0 45 5a 58 2d d8 f5 3f fb ed 37 + +# Prime exponent 1: +d1 f1 34 68 e7 df 62 fb 5e b3 be 3f d9 de 7a cc +63 0f f5 a3 a9 6e fe 54 b3 1c 19 44 b0 67 81 6f +35 80 c4 aa 56 fc bb 92 0e 1b 98 7b 67 3d ad fd +00 75 21 32 58 1c bb 5c 6e 0d f4 f3 42 cf 7e b1 + +# Prime exponent 2: +ac d0 da 38 34 90 ea 36 6e 7d c4 09 ea ab 13 20 +55 9e fd 88 de f9 4e 30 a3 22 ec 03 3b eb 6a 70 +cf 40 93 64 bc 06 4a 76 50 07 a1 ba f5 c6 f8 53 +31 f7 85 3e c1 4d 1d 7e 71 a8 b9 c2 ad 6a b1 3d + +# Coefficient: +1e da 83 d4 a6 d0 99 b6 0b 2b 2b 84 c6 ae 41 65 +c7 22 50 3e bd 37 3c 83 6f 97 35 ca 3b 20 a3 eb +08 1b 31 e7 83 04 13 20 df c6 dd f9 05 14 ca b6 +ec 4b 80 ae 0c 05 2d d1 e7 ce 34 18 ae ee 24 a4 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 4.1 + +# ----------------- + +# Message to be signed: +2c 93 6b f6 13 3a 96 93 f1 46 ee 5a 1a 91 c2 f1 +69 b2 e6 44 a5 18 e8 5a 75 f6 e4 3b 56 0d 4a 72 +f3 8c 64 f8 4c 05 24 0e 8b 4e 55 78 61 63 e7 27 +62 65 ba 21 3b a9 3d ee 1b 2e 10 21 35 a9 89 b6 +24 8e 88 32 7e 30 03 61 a7 4f 2e 9b c4 1f 2a 37 +68 3f 1a 1a 15 f9 dd 47 2e 11 8e 1c 4b 3e de 58 +dd 70 f3 ba cc 25 2e 0c 65 4b 0f 7a 6e 41 a9 28 +75 10 ef a0 3b c9 2e 80 5e 5b 2c 91 3f 51 e2 5c +7f 85 86 40 ca fa c9 d3 c9 17 68 65 07 fa 94 f8 +86 6f 86 9a 4e 5a 6a 3d 4f 9d 97 ed 81 37 f4 14 +d1 44 7a 86 ee f9 e1 49 69 94 ad 2d a5 97 + +# Signature: +9e 93 f7 ac c5 0f b3 a0 b1 24 3d c3 38 c8 cc b1 +2b ca b4 aa 45 04 40 b6 30 6c 81 b5 0b 8f 95 a9 +36 dd 16 63 30 c6 99 b2 85 80 da 1b e2 75 61 64 +02 da 85 bf d8 ee fc d6 99 35 87 e6 09 28 65 d8 +25 3b 04 08 1d 57 2f 26 27 59 f5 56 df b9 11 e8 +d9 4e 92 e5 5a f6 d5 89 80 18 ff 33 e5 f6 b1 f9 +90 19 96 e9 2f af 33 6e 2d cc e3 ab 0a 93 db 93 +2e 94 2c c6 47 8d 6c c2 fb 66 08 11 91 0c cd 17 + +# PKCS#1 v1.5 Signature Example 4.2 + +# ----------------- + +# Message to be signed: +94 32 3f 7c 38 b9 95 cc 6b d8 5d 47 9f 8d e2 de +c1 ef 2e 84 b1 fe ef ec f3 91 50 b5 d9 f2 cb 15 +85 ac 0d 71 9a b3 48 bd c9 75 0d db 8e 32 76 db +89 81 87 35 bd 62 31 41 3c bc a2 de 94 1b 55 e8 +cf a1 ab 13 2c c7 8a a4 f2 b5 1f d6 57 8e e2 e0 +32 e9 0e 34 08 0f 0f 8e 3d b1 4d 1b 56 f3 d0 77 +f2 9d bc 02 16 a4 13 44 99 8c 0f e1 ab 41 22 47 +df 21 e7 4e c2 2f 5d b0 14 8e ca f4 73 ee ec cc +14 ff 9e 45 d5 8c 2e 62 b5 fe 6a 50 1a b9 6f d7 +c5 ed de f1 4a a8 92 66 69 2e + +# Signature: +09 40 2a 43 56 be 73 44 9b 46 9e 36 31 e1 b0 23 +07 c5 ca c2 ce 15 28 d7 84 fa b9 26 df f5 1f 86 +24 1b 9d 66 f7 9d 6d 8e ee eb 24 9d 76 fa 9f 16 +6f f9 a8 c6 a3 9e 83 2d 5d 14 b9 d7 ec 5a 3d c2 +8f 01 eb b0 6e 39 d5 9e 84 61 b9 55 b2 a7 f5 b1 +f2 04 b0 4c c6 cc 62 64 61 61 ac 1c 2b f5 ba b5 +0f 06 8c 90 8d 28 de 5e ae f7 e8 eb fc ab b0 9b +7d 75 d8 35 40 dd 4b 35 4d 13 1d 86 f0 77 07 17 + +# PKCS#1 v1.5 Signature Example 4.3 + +# ----------------- + +# Message to be signed: +0e 23 3b 25 49 bd d2 1b a5 14 80 da 8e 3d ce f4 +db 20 e0 dc c0 5e e2 37 35 1e db c9 a5 3c 52 f6 +74 d1 05 fe c0 93 9d 36 99 64 7e fc 1e 25 cb 4e +9b 1a b7 52 ab 6f e2 88 69 ff 73 f2 3e 01 ee f8 +67 4c 53 5c 4c 93 35 f7 98 f1 de ec d4 89 d0 6d +c8 8f d6 bc 1d 49 96 ef f7 2b 43 9e 3c 01 4d d1 +4c bf 17 71 5c 15 89 43 de 2e 6f 97 1c 34 99 87 +a1 b3 95 d6 82 c3 b0 c1 7b 66 cd 3c a4 10 60 b5 +71 11 e2 28 31 4b 2d 34 b5 e4 4e 55 f1 c1 1c 31 +a6 eb 80 b5 f8 2d 96 bd 4a 17 + +# Signature: +d0 75 be 06 cb d6 22 3e 87 1b 0f 33 62 a7 97 de +28 2d a5 c4 03 23 f3 7c 2c c3 74 65 a1 a8 63 68 +dd cf a6 da a1 35 86 6c 32 03 d0 47 22 60 b2 9c +3c 9b 1b 88 94 08 5d 54 7c 5e b9 31 42 4f 24 14 +0a 5c ba 15 3b de d4 b9 ce 7d ae dc 64 5d 39 80 +c5 f5 83 f7 67 11 c6 7b 19 3a 52 12 f2 a9 35 4a +67 96 af 09 08 20 91 31 34 ec f3 05 be fb 65 32 +cd 48 d4 11 3a 0e c4 86 9a 0a 56 55 db dc 72 59 + +# PKCS#1 v1.5 Signature Example 4.4 + +# ----------------- + +# Message to be signed: +d4 7c 0f 5c 92 2e 4f 80 9e 9c ee d2 07 f1 24 a5 +ac de 37 fa 14 63 8e 8f bd 0a 72 fe 45 26 21 95 +8e 37 68 2c 6f f2 83 f3 d5 1d a1 52 aa 1f 63 74 +cd 27 d2 a4 a5 33 05 39 16 df f1 c0 7b a9 36 31 +74 81 69 63 60 69 04 58 d8 d1 e5 d6 6c 35 f9 c9 +9a 50 55 d9 f7 cf e7 60 5c ca 57 ea c3 35 ad e2 +ef f6 b5 aa 62 7d 5b + +# Signature: +11 86 0b f4 d7 45 19 ff 8c fc ce 3d 33 e3 aa bd +f7 71 40 a1 56 36 b2 67 8d f9 67 31 44 c2 41 b0 +a9 9a 0a 37 f2 92 ca d5 1d f0 b6 3b 14 f8 ab 17 +e3 fa 15 58 77 90 fb 06 2b 5f 26 6c 16 6b 2c a7 +51 57 a0 f9 e1 a5 c8 ec 26 b9 19 9d 07 18 77 99 +80 6a 1d e9 87 15 fb e5 27 57 a7 03 77 3c 91 8a +00 0c 21 1a 78 22 85 25 cb 52 eb 44 1b 26 9b 3f +33 05 0e d1 93 5a c0 e8 59 63 19 ae 80 c7 5b 84 + +# PKCS#1 v1.5 Signature Example 4.5 + +# ----------------- + +# Message to be signed: +be bd 9d de a3 ab f9 f8 eb 58 55 97 66 f8 b3 ab +83 53 52 38 c4 3d cd 81 a2 94 93 03 a9 5f 05 5a +83 40 ce ee 16 15 e5 8d f1 e0 14 c7 55 2d 76 9f +88 41 ba 09 97 5c ef e7 e4 8d fc 6a 26 49 e8 20 +03 e7 bf 42 0e 70 10 1b 32 7d 91 70 f7 3e 8d 88 +7c d2 98 f5 3d c1 bf c8 82 cf 0e fc fa d6 e8 6a +0e 7f 90 94 c4 f2 6c 46 92 1e 09 + +# Signature: +84 a2 6f be 67 01 0a a1 ef 2d 6c 79 26 32 39 b9 +78 f4 e8 93 dd 1e c6 f0 7d 23 17 f1 51 a2 a1 b3 +23 e5 05 f9 45 0c 37 df 6b 1b f3 e2 4f 38 b6 36 +bf 77 4e 96 74 1f fa a7 69 cf d7 a8 a6 b3 a5 ef +ab a2 3a ab 3a 43 7a 22 5b d9 41 86 e9 1d 39 2b +ed 2e ad 8a 78 f3 81 f4 09 49 cf 1f 3d 27 24 58 +1f 25 70 4b df 66 08 dd 11 9e 36 d8 7d 03 55 e6 +70 6c 8a 52 59 fd 60 c8 df 13 bc 62 aa 9f d5 7a + +# PKCS#1 v1.5 Signature Example 4.6 + +# ----------------- + +# Message to be signed: +9d 19 8e 2c 6e 12 f7 4a 9a 08 1b cf 70 fc 04 16 +8a 49 e0 9c 5f aa a0 11 e9 a0 9e 2c 43 ee 2c d3 +9b b2 f7 e5 68 2d ea b1 fa 11 1e 41 a3 19 4a 20 +a8 6d a5 51 01 82 4d 3d 78 a7 e3 2d b2 b6 0a a7 +73 77 0b 57 39 07 b4 09 a2 59 2c 83 f3 47 fe bb +2d 5c 85 e9 25 5d 6d c1 2a aa 33 5a df bb 5d c8 +62 d7 86 19 53 e2 68 7d 53 03 b6 86 ff f9 63 4e +e4 d1 5c bc c2 9f 7a 35 05 a7 3d eb 6f 9e 38 8e +96 85 ff f4 d5 45 0f 1e 32 75 35 9a 2b 99 44 0c +67 39 f5 b9 1e bd 14 ef 78 ae 73 c1 a6 19 11 f5 +ae 3a 2b 91 49 67 49 17 27 81 80 65 ee 01 0d f4 +9d 5a 16 ed 8d ce e8 48 ae 09 48 a2 52 4e ac 7c +4f f9 09 6c ed 61 35 76 42 c5 e0 f8 06 80 af ff +ce 0b a7 eb 59 58 99 49 52 6f f5 12 35 cd c7 2d +47 a2 7b 39 b8 d4 ac 84 9c 3b c0 4f a8 36 cf 18 +4b ae 0c 83 41 59 56 + +# Signature: +38 ef 24 5b 94 0d 93 97 0a 50 3b f4 3e 28 e1 7b +8a ff 08 3c cb e1 e9 c4 8e 4d 80 f5 16 c2 7d 08 +5c a2 a4 e5 73 23 6a 24 94 d9 b9 97 f8 12 48 48 +12 f6 65 25 d0 6c 0a 0b b2 13 0c 15 d6 ce 18 b2 +2f 3c ee 57 09 7f c0 d5 58 af d9 af 27 f1 51 f8 +43 6f bc 87 d6 be 61 42 64 7a 17 e0 4d f6 de c7 +0a 95 c7 da a8 4e de 94 cc b4 3e 1d 2c 37 b9 45 +81 73 10 d1 4a 22 b5 b9 ae 61 14 48 ee 41 bc 70 + +# PKCS#1 v1.5 Signature Example 4.7 + +# ----------------- + +# Message to be signed: +8e 8b a8 43 6f e3 10 4b 7c e2 a4 ef c3 6c 85 7d +49 e8 49 c0 08 5f c6 57 ba a0 33 17 93 b3 f3 6c +7c e7 38 b6 13 0b fa c7 5e 50 11 f3 2a a3 d1 + +# Signature: +78 44 69 9f 1c 4f 29 6e 50 26 1f 15 26 e0 dd 84 +f0 1c 82 cb 85 fa 24 60 9e b0 33 58 75 2c 6c f5 +99 94 d8 4e 12 f4 6a 72 00 cf 5a d9 7c 08 dd 4f +fc 44 65 7d b5 72 14 cd 1f 4e ed 6b 77 d2 39 fb +58 21 69 88 c5 e5 bc 73 5a 4f df f4 08 eb 9f 12 +79 d6 5b ba f6 a6 81 92 44 18 34 9e 62 ff 5e 58 +15 ea ea 59 2d 90 d1 ee f5 56 fc d4 d5 b4 b8 9c +6c 70 73 9d 6f 0d 3d 0b d1 6a 50 f1 e0 02 4e 98 + +# PKCS#1 v1.5 Signature Example 4.8 + +# ----------------- + +# Message to be signed: +58 5f a6 a7 f7 7a 4b 6e ba 56 90 e7 3e 71 28 b7 +2e 67 7c db 3a aa 86 29 ed 61 f2 ee 63 af 1a 71 +ba 87 13 6a 52 db 1a 33 21 fc fe b2 48 bf 2e 5c +f5 c6 39 57 1d 58 95 ad f1 fb 06 17 ed 14 0a 2a +0d 98 37 c3 c1 d8 45 0c 28 9d 33 bc 96 23 79 d7 +3e 30 87 f2 b7 ee 6e ad d6 65 01 48 c0 42 b6 ff +04 48 21 96 c7 18 fd c0 ce 57 9c eb 62 a8 1e 58 +43 73 eb 93 75 40 c4 26 b5 56 6a 9f 40 7c fc cf +bc 4b 75 36 94 af 0d f4 cd 6a a9 f1 65 46 a6 33 +94 a0 f6 57 73 71 34 3f fd db 65 1a 62 a3 a5 8e +dd ec 67 a2 9c ca e8 96 56 3c 63 e3 c9 0d 54 d9 +13 58 ad f1 94 e6 aa b1 f9 + +# Signature: +68 93 35 1c 73 91 5f ac 47 c9 62 cc 60 17 ca 74 +a5 b5 ee 4c b1 bb 5a 10 ad a2 a4 31 58 a2 26 1e +b2 7b 86 6d b3 9d 35 90 b4 f8 d2 0e e6 7c b1 a5 +78 94 63 15 0d 83 93 43 23 25 43 c8 26 50 51 01 +e1 d2 57 04 26 ab 9f ef d6 5b a8 4f aa ec 73 1f +27 37 4a b1 01 91 c9 60 83 16 93 f2 9a 85 4c 38 +12 85 99 f7 28 77 49 b0 b4 8b f7 e9 df da ed c8 +4e ec e0 71 40 45 84 73 0c ec ce 0d 5c f0 05 cc + +# PKCS#1 v1.5 Signature Example 4.9 + +# ----------------- + +# Message to be signed: +78 3c 18 b1 1f + +# Signature: +13 2f df b8 41 93 df b7 9f df e6 ba bc 2e fd 39 +b2 6a a2 09 68 a0 7c 0e 41 56 0e e4 df cd 4f ca +79 17 49 0f 24 e8 df 84 f4 e0 11 5a 3e 63 27 3e +7a 3b 12 8a bb bd 17 b8 aa 5a 06 ba 15 5e cb 23 +0f e7 97 26 04 79 95 70 10 e4 4b a5 75 29 2e c3 +f1 51 ab f4 8e 91 03 e5 51 42 ec 67 a4 13 4d d8 +f3 8e c6 59 f9 a7 89 fd 03 41 ce f2 bb cf 9f 52 +9b 93 21 8f c3 e4 3a 76 69 69 d1 bf 87 88 48 07 + +# PKCS#1 v1.5 Signature Example 4.10 + +# ----------------- + +# Message to be signed: +96 dc 98 b0 eb 84 f5 59 48 30 7a dd ec cb e7 64 +39 ca 36 58 bc 36 35 96 24 c8 fe 2f a0 9c 52 e4 +7a cd c3 2a 15 6d 90 76 82 41 0a 85 67 ab ca fd +c6 d8 bb 53 25 35 9e c7 5f fd b7 3e e0 a9 51 5a +4d df 9a 31 e5 d5 19 46 03 74 28 0a da 30 de 7d +d5 34 de aa 57 + +# Signature: +8f b4 3d c8 f0 6f 2b a4 8f 19 be 5b 1a 09 31 21 +3a 99 0a ed 9c 9f ed 1d e5 d6 f3 5a 2a 78 2f 0a +19 8f f6 38 8d 96 e9 d5 9b 88 e9 78 22 f3 49 ff +41 64 ee a5 0a 62 93 5c 61 cb c7 6e 3d f7 5f 68 +4d 96 24 75 e5 63 59 64 96 c9 88 0a 48 ed 97 8a +63 15 a3 45 57 17 91 cb 2d dc 88 da be 41 87 98 +a6 a4 41 c4 7a fb b1 cd 15 21 3e ca 3b 11 15 ec +8f 58 f8 77 be 8f bd 38 f4 fd ae f9 39 f5 26 40 + +# PKCS#1 v1.5 Signature Example 4.11 + +# ----------------- + +# Message to be signed: +37 20 01 59 9d 99 30 c7 d5 57 45 8b 43 6d ec fd +c1 4d 06 cb 7b 96 b0 67 18 c4 8d 7d e5 74 82 a8 +68 ae 7f 06 58 70 a6 21 65 06 d1 1b 77 93 23 df +df 04 6c f5 77 51 29 13 4b 4d 56 89 e4 d9 c0 ce +1e 12 d7 d4 b0 6c b5 fc 58 20 de cf a4 1b af 59 +bf 25 7b 32 f0 25 b7 67 9b 44 5b 94 99 c9 25 55 +14 58 85 99 2f 1b 76 f8 48 91 ee 4d 3b e0 f5 15 +0f d5 90 + +# Signature: +a8 97 c7 f9 72 e1 17 49 e1 e7 c1 55 ce 94 62 aa +7e 1c c0 a9 79 c1 27 29 79 51 26 cb 8c 0e a5 02 +21 c4 26 f1 bb 06 c1 ca f7 c5 1a c2 fb d9 4d 68 +8d a6 7d df 3e f6 66 06 e9 89 a1 6d e1 f9 2b 17 +70 6f 88 e8 7d 9f 14 69 a0 05 c9 fd 76 78 8e e8 +c4 a7 f0 12 09 e2 8b 86 f6 74 88 1a f5 7d b6 c3 +42 9b 6f b4 56 98 bf 5d 30 07 f6 1c 7d 44 11 78 +ad 12 43 a4 9b 2a a6 02 9b fe 90 2d 26 e4 23 75 + +# PKCS#1 v1.5 Signature Example 4.12 + +# ----------------- + +# Message to be signed: +bf bf d0 73 21 f0 f1 d5 fa 9f df 00 14 c2 fc b0 +35 8a ad 0e 35 4b 0d 29 08 1b 23 3b 43 56 77 50 +bd 6e 78 + +# Signature: +c2 4d 31 04 94 09 aa 16 d3 f9 72 ef 8b 75 95 ea +a0 07 83 3e 2b cd c7 50 48 52 f2 50 5f ba 1f c1 +5f 19 a0 ea dd e8 33 5c 73 06 fc 3f 51 66 1d a5 +20 ec c8 db 7f 47 38 85 ca bd e9 3f 0c eb f1 df +9e 8a 82 37 0b 00 a0 43 ad 63 2c dc c7 8f 3f ac +1d 8a 37 57 fc 8e 52 41 bf ed 55 c4 96 04 ac 19 +ab da c0 c9 c4 0d a3 73 c1 5f 3c 1b cc 97 3f fb +4f 8b 7b 5b 55 3a e0 75 e1 b1 bd dd d2 3d 7d 2a + +# PKCS#1 v1.5 Signature Example 4.13 + +# ----------------- + +# Message to be signed: +c6 97 39 d2 2a c8 96 6b f1 1c 11 6f 61 4b 16 67 +40 e9 6b 90 65 3e 57 50 94 5f cf 77 21 86 c0 37 +90 a0 7f da 32 3e 1a 61 91 6b 06 ee 21 57 db 3d +ff 80 d6 7d 5e 39 a5 3a e2 68 c8 f0 9e d9 9a 73 +20 05 b0 bc 6a 04 af 4e 08 d5 7a 00 e7 20 1b 30 +60 ef aa db 73 11 3b fc 08 7f d8 37 09 3a a2 52 +35 b8 c1 49 f5 62 15 f0 31 c2 4a + +# Signature: +d0 6d 32 26 0d a2 db 48 10 4f bd c2 4e 16 a6 5b +48 73 7d 43 ce 24 37 04 04 2a ad 6c 03 fd e5 a3 +dc 0f 2c c6 e3 ad 68 c3 c6 2e ab fa 1f 7b 1c ab +00 9d 11 75 af f7 7b e5 8f b1 2a 4e 58 12 7f ed +63 ea 3d f4 41 81 bd a3 8c 77 3c 83 b9 e8 04 bb +3d b7 96 32 63 df 30 e9 2c 4c 27 19 56 e7 e8 10 +45 2c 15 e0 6e 93 96 66 df 0c 83 34 03 30 96 c0 +7d ea 05 b4 4e bb 14 24 92 e7 66 91 31 eb cf 2c + +# PKCS#1 v1.5 Signature Example 4.14 + +# ----------------- + +# Message to be signed: +73 30 47 f3 36 f9 15 47 38 67 45 47 db 02 a9 f4 + +# Signature: +c1 13 c0 46 5c 84 cb fb 0f a1 bd bc 54 c3 e1 06 +8c a2 3e 69 b8 39 19 09 c3 90 0f e5 b4 e7 e3 f0 +34 c9 a9 88 a3 dd c3 c3 81 75 6a 1e 1a 27 c1 ec +fb 3a 70 e1 ee 0e 92 04 18 ac 4a b6 d9 53 2b 8d +09 59 a6 53 b4 c5 08 67 06 63 46 2b 2e 13 58 16 +b6 94 a6 b9 b4 68 a2 9f 38 de 53 bf cd df 97 e0 +3d 8d d2 4f 97 26 33 a4 9c f3 ea ae 1d 69 62 94 +38 60 dd 25 43 40 08 6b 10 35 7b 80 c1 cf bf 31 + +# PKCS#1 v1.5 Signature Example 4.15 + +# ----------------- + +# Message to be signed: +a9 74 0b 9a a0 d3 40 58 fd 3b 90 6e 4f 78 59 df +b0 7d 71 73 e5 e6 f6 35 0a da c2 1f 27 b2 30 74 +69 bd 0c e1 95 49 d0 70 01 20 cb e5 10 77 db bb +b0 0a 8d 8b 09 de 8d 83 96 e3 65 07 fe 1e f6 a1 +90 17 54 8e 0c 71 66 74 c2 fe c2 33 ad b2 f7 75 +66 5e c4 1f 2b d0 ba 39 6b 06 1a 9d aa 7e 86 6f +7c 23 fd 35 31 95 43 00 a3 42 f9 24 53 5e a1 49 +8c 48 f6 c8 79 93 28 + +# Signature: +4f bd 4f b2 37 04 f4 14 9a da 32 7f a5 33 88 52 +6a 07 dd 43 d9 15 fc bd a9 a1 3b b2 a3 73 8f 4a +db 1c 3d b2 6a b6 90 48 80 5a 80 c8 16 05 c9 6d +68 f8 41 80 2f 5a bb 02 05 7b 61 1f e2 f3 94 71 +62 65 e5 45 25 2c 23 0c e4 74 af f0 bb d4 ff 1f +38 08 49 60 36 a4 94 8c a7 a1 10 ff 26 c6 38 c5 +0f 32 15 b2 8a 09 f2 3a f6 f8 4c dc 89 78 98 d0 +fd 22 3b 13 48 1f e8 92 b1 a5 8b a2 e4 b3 68 5b + +# PKCS#1 v1.5 Signature Example 4.16 + +# ----------------- + +# Message to be signed: +af 8f 08 87 c2 19 00 4d 2a bd 89 4e a9 25 59 ee +31 98 af 3a 73 4f e9 b9 63 8c 26 3a 72 8a d9 5a +5a e8 ce 3e b1 58 39 f3 aa 78 52 bb 39 07 06 e7 +76 0e 43 + +# Signature: +32 7e c9 d0 be 7a ab 7b c9 59 d4 02 27 e1 d0 04 +81 fc 04 01 1f e0 8f d5 44 9b 90 c0 f0 54 e0 d6 +59 b9 26 cc 81 29 21 c2 0a 56 3c 4a be 4f 82 5d +6b 5e ef 57 b3 e2 d6 5d 20 a8 01 3a 50 dd 5c 93 +23 8c f0 49 f2 ff 0c 7e be b8 e8 ca f7 2e 46 e7 +cf 8a 0c 3f 49 25 61 6b 1b c1 82 6f fc b0 bd a6 +0b be be df d4 c6 0f 27 88 d1 66 6f b8 45 11 85 +36 46 c2 dd 46 68 51 fa c8 5b e0 ed 5a ce 5f e2 + +# PKCS#1 v1.5 Signature Example 4.17 + +# ----------------- + +# Message to be signed: +38 df 86 55 7f 37 5d 09 cc d8 bd 15 d8 cc f6 1f +5d 78 ca 5c 7f 5c de 78 2e 6b f5 d0 05 70 56 d4 +ba d9 8b 3d 2f 95 75 e8 24 ab 7a 33 ff 57 b0 ac +10 0a b0 d6 ea d7 aa 0b 50 f6 e4 d3 e5 ec 0b 96 +6b 81 57 79 a9 1b 3a 8b d0 49 bf 2a eb 92 01 42 +77 22 22 c9 ca 0c 32 8c 65 9e 0a 64 37 43 3c ce +b7 3c 14 9a ec 4a 74 80 d5 bb c4 29 20 d7 ca 23 +5d b6 74 + +# Signature: +30 46 05 5c 2b 8e f7 fa 92 c8 a9 e3 95 98 5b d4 +60 fb 6b 47 98 65 53 94 4d 21 04 51 19 f7 e7 61 +7e 03 fe 80 87 0a c6 aa bf 63 b0 96 ca d5 cc e7 +f5 06 95 3a 7f 69 3f e1 37 ad fb 97 cd 45 81 28 +ae 95 c4 7c a9 48 da cf 24 03 6a de aa 48 f2 9a +46 9f b5 13 19 1e 05 ac f7 9e 67 a7 93 a3 af 5e +4f 9c 6d 0d 01 fd d0 e0 cd 42 96 ad 3d a2 ca 89 +a5 0e ed cd 9f 7b 87 7d 2a e1 d5 8d 98 dc d7 8f + +# PKCS#1 v1.5 Signature Example 4.18 + +# ----------------- + +# Message to be signed: +cb 34 ed d5 ab 65 40 41 b6 14 30 56 + +# Signature: +1d df 48 ba 53 51 be d0 79 5f 55 b3 06 aa 1c 6e +d8 36 f5 92 ba 93 cf 0c 46 b7 c2 73 70 9d 36 b8 +df f0 2a bd b1 a7 68 d1 c7 11 4a 86 a4 57 49 6d +a5 79 e4 d8 19 f7 2a 19 2e 29 8b e2 15 2f 7c f3 +9d 1e 30 82 7d 02 82 cc f3 4d c8 88 9f 1c 2f 59 +70 93 0d 97 35 04 2f 8a 5a 71 22 63 16 5d 6e 6c +50 35 e2 e4 a5 0e 86 3c 06 79 9e 3c 89 cc b5 cb +0e 70 b3 c9 9c 08 40 30 67 7a 7c 97 90 7a 17 24 + +# PKCS#1 v1.5 Signature Example 4.19 + +# ----------------- + +# Message to be signed: +5b 09 ec 88 b1 52 71 78 fa 04 32 63 f3 06 7d 9f +fe 97 30 32 a9 9f 4c b0 8a d2 c7 e0 a2 45 6c dd +57 a7 df 56 fe 60 53 52 7a 5a eb 67 d7 e5 52 06 +3c 1c a9 7b 1b ef fa 7b 39 e9 97 ca f2 78 78 ea +0f 62 cb eb c8 c2 1d f4 c8 89 a2 02 85 1e 94 90 +88 49 0c 24 9b 6e 9a cf 1d 80 63 f5 be 23 43 98 +9b f9 5c 4d a0 1a 2b e7 8b 4a b6 b3 78 01 5b c3 +79 57 f7 69 48 b5 e5 8e 44 0c 28 45 3d 40 d7 cf +d5 7e 7d 69 06 00 47 4a b5 e7 59 73 b1 ea 0c 5f +1e 45 d1 41 90 af e2 f4 eb 6d 3b df 71 f1 d2 f8 +bb 15 6a 1c 29 5d 04 aa eb 9d 68 9d ce 79 ed 62 +bc 44 3e e2 0c + +# Signature: +af 56 fc 32 97 39 e2 f7 75 4b 6c a2 51 64 a6 fa +58 f6 85 dd b7 42 b4 84 1d 73 a5 e2 c4 c4 53 43 +b7 4d fd 2f 0d 37 0e dd dd 36 a0 17 56 4a 8d 3a +d4 02 e2 a3 41 c9 72 06 2c 23 81 4a 00 13 1e 17 +b1 de c7 b4 c5 7c 5b f1 d4 fa 79 22 29 37 a4 dc +5c 00 23 5f 85 3d d2 3d c9 75 7f 33 5c 85 c2 07 +eb 07 4d 4b cc 24 3e da a7 83 1b 83 13 56 55 e2 +27 7e f2 9e 7a eb f3 4a 0f 7b 23 4a 28 65 0a 30 + +# PKCS#1 v1.5 Signature Example 4.20 + +# ----------------- + +# Message to be signed: +3c 33 0c 1e f7 18 c1 41 e4 7b 8f a8 59 be 4d 5b +96 + +# Signature: +0b 10 22 dc 38 e2 17 fd 3b 0e 7e f1 9d fc b4 b4 +56 36 62 40 98 30 95 f6 db 96 58 31 a7 0f 0f 8e +20 e2 dd 2a c2 31 cc 37 90 45 c2 73 65 e7 3a 53 +71 9b b6 f0 11 c3 f8 63 6b 64 99 4c a4 80 60 2f +b3 b4 f0 e2 27 4b 58 b3 63 e0 d3 08 b5 28 e1 58 +59 a9 1d cf 99 bf fe fb c8 05 22 41 b9 74 19 2e +63 62 18 f3 98 33 2d af e8 25 9c a5 f5 cc fa 54 +c9 b3 2b 27 35 af 07 24 f4 0b 5a 5d 61 21 a4 0d + +# ============================================= + +# Example 5: A 1024-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +c5 5f fb dd 6a 27 53 bc 02 af 20 ae 18 ea 0d af +23 0b b6 f8 79 5d 05 ef ec c8 15 ba ec e2 2b 38 +79 99 5f 6d 97 64 c1 df 8f 97 85 13 81 68 62 66 +b8 09 2f b6 01 18 98 a7 67 07 a4 d1 d5 bd a0 8d +24 6c 68 7a 8b ba fa 63 98 ac 9e a2 72 68 23 71 +4a 0c 39 34 ca 6e 5f 8c e3 39 87 b5 34 85 7e a9 +f8 5c c4 e1 9a 1d 21 83 e0 e4 c8 aa 55 cb 22 7b +0e 56 ce b2 b6 2b 30 ef c7 88 64 b2 f9 fb 92 49 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +c5 5f fb dd 6a 27 53 bc 02 af 20 ae 18 ea 0d af +23 0b b6 f8 79 5d 05 ef ec c8 15 ba ec e2 2b 38 +79 99 5f 6d 97 64 c1 df 8f 97 85 13 81 68 62 66 +b8 09 2f b6 01 18 98 a7 67 07 a4 d1 d5 bd a0 8d +24 6c 68 7a 8b ba fa 63 98 ac 9e a2 72 68 23 71 +4a 0c 39 34 ca 6e 5f 8c e3 39 87 b5 34 85 7e a9 +f8 5c c4 e1 9a 1d 21 83 e0 e4 c8 aa 55 cb 22 7b +0e 56 ce b2 b6 2b 30 ef c7 88 64 b2 f9 fb 92 49 + +# Public exponent: +01 00 01 + +# Exponent: +07 e3 fa 71 b3 98 b6 e4 41 47 37 0b 3e bb bc a8 +4f c2 5c 22 3a d7 d9 30 ea 4a 65 73 ff 9c 5b 15 +fa e6 82 c6 22 d3 48 5c e3 a4 af 11 44 8f 23 bf +ef 83 8e 80 bc 32 7b 87 d5 ba 9c 80 37 07 49 af +c8 c1 c0 17 54 6f c6 b6 59 31 b7 59 ca 43 41 fa +5e 5e 10 b2 40 87 e6 e2 c0 f4 db b7 90 69 52 99 +9c bd 90 d2 43 5f ca cc 9c 82 e4 8f df 24 e4 95 +cf f3 0a d4 19 e7 12 3e 3a c9 42 27 2e 1a ba b1 + +# Prime 1: +f7 f7 c0 02 f0 19 6e cd d7 1b a5 ad 74 2b 69 48 +27 d2 88 af 1b 1b b6 9c 5e d7 fb 22 9d ee 4b 7a +32 f2 f7 56 8a 6f ca f3 83 d8 9a da 9f c1 4a 7b +a5 d0 a4 a4 6c 2c 54 3e ec 17 75 49 c8 a0 48 b7 + +# Prime 2: +cb c4 b2 86 04 76 a2 d3 e8 a4 da 21 00 16 ca ce +d0 e3 67 cb 86 77 10 a4 b5 aa 2d f2 b8 e5 da f5 +fd c6 47 80 7d 4d 5e bb 6c 56 b9 76 3c cd ae 4d +ea 33 08 eb 0a c2 a8 95 01 cb 20 9d 26 39 fc ff + +# Prime exponent 1: +6c 76 27 bc a1 3c de a4 96 a4 77 31 89 90 bb 7a +5e 40 ce 9c 99 24 e4 19 3d bb 07 14 3b 34 52 3b +5f 31 bb 52 55 37 54 f4 73 05 39 a6 cb 1e 06 f0 +52 b5 12 6f 01 09 da c7 b3 09 07 ba 80 50 eb bd + +# Prime exponent 2: +40 92 74 80 43 a9 d4 af 92 69 ab 36 09 f1 2f 13 +9a de 75 65 e9 96 91 8f a0 81 ed 4d 9d 8a 39 78 +fa 92 7a d6 1c df 07 c6 1c ee de 96 b9 6d f4 6e +7c 68 ef ca 8b fe 63 ad d4 83 aa 32 22 8a fd c1 + +# Coefficient: +2a 61 94 ca 29 70 72 38 45 ff f3 8c a1 a9 a3 b5 +66 b4 24 5d e2 f9 01 34 b8 e6 ae c8 ae 07 f3 bb +7c 5e 5a e6 e1 83 34 85 e5 5d 8c a6 0c e1 64 2f +72 75 96 8e 66 12 38 35 52 11 c6 38 48 94 0f 3c + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 5.1 + +# ----------------- + +# Message to be signed: +ea e9 a4 0b ff 18 3f 41 14 73 2e 7b 3b a5 56 f4 +ce 28 8d aa 83 e3 ff 23 61 12 44 a7 a0 90 1f 11 +7d 86 c0 9c 33 a5 23 2b d3 20 fa 37 a2 38 a8 aa +62 dd 21 ab bf ac db 93 fa 1c 44 cc 55 ac 61 be +a2 4a 6a 34 cc 64 76 75 38 37 e1 6f ac d8 2e b4 +9e 1c 57 c9 58 fb bf f5 68 88 7c f8 2e eb e9 61 +e5 80 e0 64 db 9c be c3 b5 3d f1 f2 71 99 e4 9a +04 cb e5 9c 69 a2 65 cf ac 8c e4 f9 1c a9 5d 52 +b1 14 5c 8b 9f 44 40 b3 9c 18 50 94 be 18 48 74 +da 59 71 d7 d7 63 fe 07 ce 16 e5 7f 1e 50 d2 28 +65 04 b4 81 e2 c6 85 bc 9d 9c 01 49 3f d3 a6 d8 +bb 9b 2e 96 bf de b6 c9 29 14 ca + +# Signature: +44 ce b4 42 24 2b ae 08 59 94 ea d0 7b 70 95 43 +ea 23 95 a6 e8 d4 64 73 d7 0d f3 4a 95 55 aa 56 +7f 4d a1 38 e9 63 fe 92 86 a8 4f b7 c5 cf 82 00 +03 59 04 b5 0c 32 40 3c ae 51 7b fa 7f ca 8a 66 +fc fd 63 2a f7 47 c4 9c df b0 b9 ae e3 52 28 b7 +dc 4c 21 00 39 69 b0 a0 13 ed e1 29 2b 65 d1 0a +50 c9 02 63 fb 0b f4 f4 b8 37 66 41 b0 3e 1f af +b8 83 f0 38 f4 32 3d fe 5b ea c4 68 de ea 99 c3 + +# PKCS#1 v1.5 Signature Example 5.2 + +# ----------------- + +# Message to be signed: +9d e5 ca 46 74 85 61 a0 b9 28 b2 60 a9 5a 3e d9 +20 ad c8 d5 ee b9 27 1d c7 1b c1 4f 69 cc d6 31 +1d 18 6a 77 9f 5e b8 db 17 c6 90 d6 86 7c f3 36 +9b bf f1 5f ab b3 cd 2c fd d6 f7 d7 52 86 ff 2d +24 99 c5 ab b4 8e d5 4f d4 d8 49 a9 18 0e 11 0e +0a 53 a7 21 39 82 92 11 0f e8 be 26 + +# Signature: +44 5f f5 b6 87 9f 8c e7 53 95 01 6f 04 95 f1 31 +35 b1 79 e7 3a 3c ae b3 30 e3 cd a7 f3 1f 1d cb +a7 aa 82 e2 68 c9 35 e9 d7 01 4e 0b 0d ce a6 9c +7b 96 8a db 17 42 4a 64 df d1 e2 bc 57 07 f9 20 +fc 0c 83 cc 63 df c7 4b 96 3e 68 2b 46 a2 2a c2 +56 ac 6b e5 70 9c 07 cf cc 3d 4e ba 3a 1d 61 ab +15 f1 ba db 0a 49 fb 5c f0 9a 1f 74 81 a3 aa ea +f7 c2 57 54 03 77 ae a7 b5 44 17 a6 09 c7 6f 4c + +# PKCS#1 v1.5 Signature Example 5.3 + +# ----------------- + +# Message to be signed: +18 3b a1 a3 81 1d 62 5c a9 da 1b ba ae dc 76 19 +20 12 fc b6 74 bb 9e 77 d8 f3 77 08 d2 40 d3 49 +e0 57 97 41 6f eb 24 e3 01 8c 7a 20 5d 05 9d e8 +e0 ae 05 a8 d7 e0 9e af ee b9 f0 6d e5 d4 28 7a +bb ef 05 9b c5 86 b2 1c 82 d6 4a ec e8 d7 42 8a +fc d7 b2 2f c5 d1 68 bc 07 6b 61 5f 02 73 3c b6 +31 25 c8 f3 6d 5c b8 09 ce 80 65 08 23 98 b3 88 +5a 89 19 57 0c 47 8a 07 2f 59 66 15 d7 8f 01 36 +d1 1b e3 2b 3f e0 f4 fb e3 c7 da 5d 81 34 19 10 +17 7e 48 b1 bb ac 27 6c 12 ee 81 54 65 dc 67 d4 +53 24 f9 05 aa ca 48 38 d8 1f 74 31 46 3e 89 eb +8b 95 36 58 69 36 af b4 2c b4 7b d8 c3 18 29 d3 +1e c1 ee 29 f9 1c cc 6d f9 cd 1b 0b 9b 86 46 b6 +02 67 fd 7e ce ae 92 c0 ae 9e 0c e5 ff 6f 7e 0b +f7 56 a9 b8 ff c9 c6 16 + +# Signature: +ab 4b 78 96 4c 2a 35 d3 28 55 e0 ef ce d3 4b f8 +02 19 b5 8c 48 8e a3 75 b1 f3 27 16 6a 51 35 e5 +da 99 45 c2 87 29 7a 3d 93 2e 57 27 46 f0 22 74 +8b 85 58 5a 0a bd 91 86 f4 ac 35 ed c8 50 d2 fd +88 05 b9 e9 f5 1a 5a dc b9 5e 1a c1 72 9e 57 b8 +53 31 c1 ed 15 c3 d0 cf ae 33 f6 1c 11 9b 55 c9 +5e 34 4b 72 f2 b4 f8 e7 e8 fa c7 a3 3e 5b 8b 27 +6a 60 88 a7 fa bf 4f a1 72 35 7f b6 e3 f4 4a 94 + +# PKCS#1 v1.5 Signature Example 5.4 + +# ----------------- + +# Message to be signed: +87 07 dc db 49 d2 83 a2 3a 9b d6 ff 87 af f8 34 +f0 6f f7 f4 7b 0e 5f 57 ff 1a 0d 99 5b ba 9c dd +5e a0 1b 42 b2 5d 6f f1 7a 0d c1 06 05 cf 45 2a +ca 73 be 54 ed 5e 0c e2 15 66 af cc 17 91 2a be +18 df ac d1 bc 03 e3 e2 88 2a 4b b3 a4 f3 9e ea +f9 63 d7 c3 5e 6b a8 58 b1 37 6a 07 51 60 c6 cf +ae d5 e8 c5 2e 45 11 32 34 72 19 bd 88 89 3e eb +e3 56 59 a0 ee 4d 94 f9 4d 03 5b 7a 86 86 ff b4 +16 eb 99 fb 2a aa 81 23 6b 05 ac 46 45 92 5f 2c +2b c1 9e be 89 a6 3f 2f 45 1d 0b 13 b2 fe f0 61 +e5 30 a3 49 ba f3 b2 35 64 22 b0 95 fd 9f 19 29 +93 ab 99 c9 f9 22 6e f9 a7 b3 cf b3 65 82 08 59 +29 c8 76 b5 e9 d7 c6 ac ac 7b b0 27 52 34 e4 1e +d3 51 c8 38 b7 a3 1a + +# Signature: +17 53 98 8b 39 dc 74 5d f9 69 1a f9 ee 69 ca da +73 a9 87 7c ca 12 f6 d4 06 27 dc ed 76 22 14 7e +c9 01 a5 b4 63 e7 ef 9b 37 fb d6 92 78 5a a2 2a +46 5d f4 03 af 92 a2 9f 79 5d 40 a8 3f a9 64 b8 +5a 7e c0 5a 3c da e3 f8 bc 8a 61 a7 9d c8 42 e1 +d3 77 bc 5e 1d 46 ad aa a8 66 be 28 2c 6e 23 88 +17 36 44 f4 06 27 bc f8 a0 97 4a 4b e8 fc c4 8a +ee 7e 82 59 f8 68 a2 bd 78 9a 90 89 92 05 6e 55 + +# PKCS#1 v1.5 Signature Example 5.5 + +# ----------------- + +# Message to be signed: +ac 9f a3 f6 3d f0 68 e9 0d 69 2e cc fa 7d 87 96 +49 1a ca 79 5b 98 58 a4 55 18 62 32 29 af 28 b1 +3a 50 2d 8c b3 b9 50 92 50 58 82 eb 99 4d e7 46 +59 62 56 98 a0 05 04 17 94 0d 8b fa 28 a3 f9 3d +14 9f f8 b0 bb 39 26 f6 18 ef 91 96 6f 4d 39 bd +ba 5a 05 17 dd eb b1 6d 2b c4 b4 e3 3a 7d 61 9c +95 a3 3c f5 f5 72 db e0 7f ab 4a a6 7f b3 f3 9a +a2 98 1a 3d c0 ca ee 64 75 8e a8 98 eb ce 10 bf +3a a4 fc 84 49 e8 e0 cf 7e 88 b1 88 23 8c 20 68 +ef ac eb fe ef 40 73 a6 54 a5 8a 30 99 d0 36 ae +ee 2d 81 82 98 d4 ab 39 23 8e dc 45 9a 9f d3 57 +7e 9f 5b fc 03 68 aa 65 7a ee da 1e eb 8a e7 f5 +ac 1e af 3b 1c 95 81 7d de 2e c1 a5 9f cb 5e f2 +7c c3 4f b7 53 31 da 7a 49 96 92 5a c3 ad 17 bb +c3 da fe 6a 9c 64 4e 30 98 ef fe f8 fe a5 cc 0d +5f 0c 04 8e 10 88 + +# Signature: +11 e1 a8 28 f0 0a 98 7e 03 d6 2e 2a 53 6c 29 7d +da c0 22 e0 63 ee 0d e4 e4 69 5d ed 1f db 22 09 +00 a3 ac 3f 87 d1 be 75 f9 59 c2 8b 57 8a 43 b2 +56 64 3c df ff 92 15 95 fd fb ea f4 10 c2 ae d9 +e5 e4 7e 1d 15 1a e2 8c 76 99 ae e2 25 a6 45 bc +42 b3 be b5 2f 08 38 7e c5 54 d0 20 4d 28 3c 3b +cc bc ca 21 6e da d9 4e c6 4f 9c 20 b3 40 6a b7 +8a 6c 4a 4d ae 3f a6 17 a0 0c 6a b2 f8 e2 47 62 + +# PKCS#1 v1.5 Signature Example 5.6 + +# ----------------- + +# Message to be signed: +15 74 69 73 44 e9 86 85 cd 6e 65 e4 67 83 f0 b5 + +# Signature: +3b 7d 67 d1 3c d3 c0 fd 30 5a d4 04 d8 a3 dc de +4a 45 17 9c 2d 0b 87 11 5d 6d 06 0c 24 9b 87 f3 +9e 46 3b 76 4b 42 07 c4 8a 74 cf ce 25 31 e8 18 +3d 3d 01 25 85 ce 57 39 d1 62 c4 ea 22 32 44 02 +ea 2e 6e af b8 a5 73 fc ff 40 15 c9 5c 45 e4 ca +7a c5 1a e3 a0 6f 42 1e 60 6d 68 3f 5e 12 2b 55 +79 14 8a 9c 46 6a de b0 24 28 f4 89 6a 86 df 63 +be 58 7d dd 7a 6a 8d e7 17 6b e4 e7 ff 4a aa 99 + +# PKCS#1 v1.5 Signature Example 5.7 + +# ----------------- + +# Message to be signed: +be 46 be 8b dd 85 43 d3 70 bb b7 ac 83 9f 5e 64 +53 f3 0c d8 75 2a 4b 92 67 32 c5 9e 61 09 04 4b +e3 a0 75 6c 70 25 a2 32 80 df 2e d7 66 ba 39 ab +b2 0b 94 4c 06 5f e1 48 7d ea 31 b4 70 8a 68 9a +50 b2 8d 54 29 94 cb bb 3a 5b b9 46 0e e7 a9 c1 +53 8b da 75 1a 52 8b 76 70 f9 15 78 d6 67 3e 08 +ab cc df 5f 4d 8c 1e be cf ca c7 5c c4 2d bb b8 +cd e3 c1 b4 74 b5 56 b3 2b b8 48 fc 32 7b a6 e3 +cf 5f 77 b1 eb c0 4a 19 f3 c8 c3 9b 6b 84 77 84 +ea a3 25 a2 b6 f3 + +# Signature: +91 de 2f 90 32 47 b2 d1 3a be 93 dd d9 6d fa ef +1b 4d 17 2b 09 09 58 f0 cc 34 fa 92 83 5a d6 0c +44 b4 27 fe 03 1c ad bf 92 ff 1c d0 38 41 44 c9 +b5 f2 8f 64 5c 63 e8 d7 16 bc ec 2e 04 3b c3 96 +56 64 17 85 c2 6b a3 6b a2 a1 09 e3 64 4e bf d9 +62 d7 a3 16 91 6b 3f 13 66 20 13 cc 0f 37 ad 8f +9e 0d 9e c8 b4 c8 ad 5c 75 32 cf a0 44 ae dc 73 +78 77 94 c2 98 79 7c 8a 7e 14 49 ea d6 15 0d ed + +# PKCS#1 v1.5 Signature Example 5.8 + +# ----------------- + +# Message to be signed: +0b 7e 06 63 e7 15 ea 38 bc 93 0e c9 d8 e2 a0 29 +aa 1a 4c 95 e7 b2 00 47 ae 15 44 d5 b2 d8 47 6f +c8 05 53 9f b0 ef ab 7d 5f f1 2c 36 d7 6a 79 7b +75 c0 b5 3f a9 26 54 73 da b6 80 c2 55 d5 7e 99 +b6 d9 fe 08 cf 1a 57 34 91 e2 19 78 fa e9 53 9c +c0 58 84 63 3a 1d d5 cb 21 53 6f d4 2d dd 73 1c +a7 6c 34 57 81 3c e1 bb 59 c2 1d d3 1b f2 ae 3b +fd 7d 20 c6 c7 12 a9 dd 43 95 1f 1b 19 8d ea f7 +41 08 ea d2 29 26 d2 b0 19 1e 59 d5 f6 79 ad 97 +c7 1e dc 69 de 97 98 7e 54 3e 87 a9 6a 9f ee 77 +e3 f0 ea 95 7b d4 6a + +# Signature: +48 51 09 8a 85 e7 0d a3 33 92 a9 e9 0b 34 76 a4 +8b a0 e3 2c d6 ad 3d c1 dd 91 da 57 e8 8d fb c7 +b6 57 4b 08 e8 71 60 80 e1 5d f4 05 79 c5 70 5d +5b ef 58 4b 08 b2 63 db c4 f0 d1 59 56 ff 11 25 +c4 8f 89 59 1e bc 94 1d 9f e8 f9 a7 80 c8 2e a3 +2b f3 ef a1 6c ab be e5 80 fd 6b 95 74 08 0f 69 +07 fe af f8 1d 48 c4 9a 6d e2 24 84 80 f1 d8 52 +39 e9 a4 18 dd 53 10 de f7 76 e0 8f 50 9a 14 78 + +# PKCS#1 v1.5 Signature Example 5.9 + +# ----------------- + +# Message to be signed: +13 42 33 ba cf a1 6d c8 4d 8f a4 bd bb 47 93 d1 +da c0 7d 60 54 bd 08 39 61 da 68 67 9c a3 75 33 +4f 09 20 b9 df b8 a6 8e d7 7f 27 fd 92 19 28 13 +61 e0 9f a6 08 4f 96 e6 98 85 b4 7e a7 75 af 06 +77 2d 66 12 d4 d1 6f 4a 5c c4 cd 0d 1e b2 3b 7a +1f 09 56 4b 84 2e a0 7c bd de 60 45 3a 2a a4 ab +69 dd fe b5 b1 3e 9f 08 cd 07 2e 5b 71 ce d3 34 +ea 70 4c 74 9f f4 72 7e be 12 c0 29 0e 00 a8 41 +d7 4b 06 55 cf d8 06 5d 28 20 fd f8 fd c1 bd 45 +58 81 80 8b ff 0e c7 27 60 74 75 bf 0b 2b c8 93 +59 58 32 9b 77 8e fc e5 60 fc 26 c3 bb 6e 2d c9 +ae f1 8f 96 9f ba 64 74 5e d4 d8 5b 14 75 7b b8 +33 ea db 9c 5c b0 ea ed 08 d3 0b 95 15 00 5a 3e +88 09 1f c5 cd 2f 36 ad 95 5b 7c 6f 2b 19 bb a3 +74 fd + +# Signature: +3e 37 b4 2d be c1 29 db 81 c5 e2 a2 22 f3 1e 81 +b9 37 ff 02 24 95 18 18 37 30 37 8b 4c 09 2a a7 +f3 b2 34 59 61 1a 82 4f c5 27 54 42 1a 27 cc e9 +18 b6 2a a7 b4 46 38 a0 c0 82 79 80 52 a5 88 46 +68 82 51 06 90 ac 77 30 23 28 02 46 c8 90 ff 1f +62 27 04 9e 66 8b c9 d6 e4 89 b6 94 4a 34 e8 f9 +30 02 bb b0 0d 75 2b 57 7c e3 52 53 00 82 be cd +30 9b 0d ac cd 1d 68 d0 6e 1d f7 12 21 c6 22 69 + +# PKCS#1 v1.5 Signature Example 5.10 + +# ----------------- + +# Message to be signed: +35 da 3d 02 34 bd 74 fc d7 6e 8e 69 52 8f 65 1b +88 27 1c bf 16 28 69 38 c2 c4 a3 7d 41 1d e8 f6 +75 78 eb 8b 3d 20 a8 fd 7d cd e7 b6 56 fe 96 a6 +80 87 32 28 ed 0f 9a 62 0f 15 05 44 23 72 f9 b2 +b4 16 84 98 72 34 90 f8 11 f3 11 1f 5f 77 38 63 +47 b4 82 2e d9 d6 b5 53 83 92 21 5c b6 c4 86 5b +b7 b5 b7 e2 84 2e ea 0e 90 01 ca 0c df 5d 6b + +# Signature: +12 ff 2a b5 fc 83 d6 49 59 7c 47 bf f3 29 b7 f4 +61 db bb da 01 fb 6b ad 26 54 3e 4d bc d6 0c 5e +2c de bf b1 12 78 4a 96 4e 27 f2 a2 e7 fd 07 ec +39 0a ab 14 94 37 03 58 a7 5b 5e 1f a4 f1 ad 52 +02 e6 d5 46 c0 f3 15 e8 6f af f1 d2 5b 94 72 82 +da 32 ea b5 6c 22 f0 6c 8a 9d 32 ae f2 81 d6 f0 +aa 55 d7 ad 3b cd fd b2 09 a1 6e f4 5c c6 f9 68 +2e ae 96 3c bb 21 3a db 7f ad 1b ef 49 c0 70 4f + +# PKCS#1 v1.5 Signature Example 5.11 + +# ----------------- + +# Message to be signed: +75 fd b0 72 73 f7 54 d1 11 6f 99 7a f2 d1 1a 51 +2b 94 e9 e0 48 01 b3 fc 73 91 30 b7 47 b4 be 87 +44 d7 e7 f8 a2 97 a0 89 d9 05 0c 5f 54 f8 a3 9a +a3 f2 + +# Signature: +07 ff c1 b7 a1 0d da ba 96 05 f0 a3 d9 3c 8a 5e +4c 0b 77 58 61 39 05 07 31 d9 cc 9b 3c 83 d2 b7 +3f af 9a 4e 24 d1 c8 bb 0d 62 3d f1 0f c8 40 7d +15 14 48 fa 43 ee 65 81 e7 b0 ac 80 d1 4a df a4 +f6 d2 7a 76 67 50 b2 31 cb c1 c5 cf d6 2d f1 b9 +72 7d 8b 87 41 46 9f 68 e5 0a 9b 3b c7 ad e1 37 +db 06 74 76 03 74 28 56 d5 e7 dd b4 e1 6a 5b 49 +d7 36 5d b2 76 3b f5 fd ea 08 3d 81 fa c9 2d 87 + +# PKCS#1 v1.5 Signature Example 5.12 + +# ----------------- + +# Message to be signed: +96 c9 fa ce fb a2 ed 33 ed 8b 7b 3d 8b 6d f2 8f +2f ab 0d cd d7 a3 cd 7a 7d ed a2 54 5e d4 47 0e +d2 5b 46 d2 16 6e eb b7 e1 47 10 17 83 b6 45 ba +c6 26 64 b8 72 70 09 f3 5d 1e a5 fd a5 e7 c2 8d +6a f6 fe 92 04 6c a7 24 ca b8 42 5a 52 a0 85 f9 +ac 90 83 d4 d6 90 bb dd df d0 a8 2d 94 8f 70 d6 +85 e2 6b b9 f5 27 40 8a bc 84 7b ff 12 02 de df +6d 2f ac 6c f3 68 2a 51 6b a7 2f 4f e9 7b 90 46 +6a f6 e5 43 12 31 65 b8 a6 83 ca ba 2f a2 3a 86 +ac 06 21 30 65 e1 ed 9b 4f 49 af 4f ff 6d 46 b3 +6d 13 3d 8d a2 dd 29 d5 5f 9f 32 2c 40 78 5d dc +21 c4 26 c5 e0 a6 7d 41 4f 5a b9 71 c4 46 0f f9 +b1 14 30 5a 8a e7 e7 b9 5c 73 03 4e 8e 93 c0 35 +29 dd 50 c9 4f 07 62 79 77 5a 5a 3a 80 c5 d2 48 +6a 2d 51 08 48 bd c9 b8 52 ac 1d 32 ce b7 c0 41 +a0 8f 2f 8e 62 + +# Signature: +46 d0 3f ae c4 a7 23 18 62 1e f4 d0 c1 bc a7 1a +2a ee a7 a8 1d f8 fe bb 8b a3 fb 35 40 d7 2d 15 +34 b9 82 69 16 e8 9f 27 d3 25 67 6c cf 5a 0a a1 +61 12 db 2d 93 03 e0 eb ce 4b 85 58 7c 55 ac a0 +68 50 de 84 de c2 13 d1 13 74 04 a5 de e6 ca 88 +d9 1a e2 8b 7b 53 6c 90 20 2b c7 72 6d a5 04 2a +85 08 d3 b1 3c fb aa dc ee 12 78 d3 5d 30 3a cf +ee 6e 07 41 90 49 11 a5 f1 88 10 ad d3 e7 b8 f6 + +# PKCS#1 v1.5 Signature Example 5.13 + +# ----------------- + +# Message to be signed: +c4 b4 c9 96 6e 56 f4 0a ff 47 08 13 1c d3 71 44 +21 34 3e de 70 c4 d4 6d b6 ef be 1b 19 a9 e3 c2 +e5 81 06 00 8a 98 38 59 cf 94 2a 31 97 74 69 5a +0c 98 a9 63 e2 fe 9d 93 79 bc + +# Signature: +b1 6b 10 f2 bd 7e a0 f7 6a 9e d2 ff cf 3e c1 0e +dc b8 24 60 fe 55 82 a7 76 4c 0c 50 56 ec fb 09 +72 06 48 d5 f1 9b 3d ea f2 ac c9 86 46 0e 71 14 +26 15 83 a5 f4 a9 90 e9 22 fe b5 b4 78 97 34 fd +cc e1 5d dc 87 ca c3 f6 c7 c9 e9 e2 19 23 15 f0 +84 1f 43 ea 86 de a9 a9 38 05 08 b0 6c 9c a5 e9 +d4 a6 51 d0 12 16 62 7c 46 6b f0 d6 ae 74 4b f3 +0f d7 91 a8 21 03 39 f5 05 7f f8 5c eb 84 f1 96 + +# PKCS#1 v1.5 Signature Example 5.14 + +# ----------------- + +# Message to be signed: +b8 38 a5 d8 88 95 0f 1b 8e 4d 94 7b ba 51 af f9 +bb 60 b8 3d 09 ed 9d 97 96 7a 76 95 5e d1 dd f0 +48 15 20 bc f4 f0 8b eb bf 89 9c c7 c3 ef 0c 04 +d5 00 1b 1e 2e 84 5f af c5 83 30 0c 98 ac a7 a0 +3e 90 a4 34 de 77 fe f7 20 da 36 63 f2 19 98 20 +8a 94 f8 94 76 7d 3e d8 13 96 b7 ef b2 86 e0 ff +7d b6 ea 8f db 4e 72 83 46 00 fe 5f 7f 15 0a 01 +b1 d4 a0 8b 5e c9 ee 1f bc 10 01 d1 2d 52 36 db +f0 72 7e 7e a3 60 78 f3 eb ac 50 46 b7 65 b4 e2 +3c dc ef d1 15 d6 2a 50 34 4d bb d7 42 8d 48 ff +c9 4b 11 e2 1c + +# Signature: +b1 56 81 ee f2 96 a6 6b 9f cd 66 30 f8 9c 55 82 +6a 38 9e 0c 2d 3d 47 6a 0f 8a 1e 08 cb ca cc 66 +02 c7 14 43 8f 32 f3 4e 02 c3 6e 5c 0f 16 8a b0 +28 91 7e 90 50 fb c8 50 f0 cf 65 d5 ee db 3b 54 +be 54 95 bb f0 fa ee b3 2b be 5a 8f 87 bb ac dd +25 85 fb 90 7b 13 18 5b 02 61 56 63 d2 01 1e f2 +3d 0a b0 4d ad 1f fa 67 9b 53 15 2c 9c 42 b8 46 +39 68 4e ae af 64 4e 4f c6 ff 2e c7 d4 7b a5 ac + +# PKCS#1 v1.5 Signature Example 5.15 + +# ----------------- + +# Message to be signed: +9f d5 39 c8 ad 86 49 24 ee c1 d6 55 c0 7d 1f 28 +27 0c db 32 6b 57 2c 46 67 ec a6 48 8c 03 36 57 +ff 29 25 4b 91 f3 21 6e 1c ac 97 97 53 f2 23 b1 +79 ea 5f 9e fc 23 6d 40 1d 1b 9a 3c 20 eb 2a fc +9b fc fd 07 92 ac c5 b0 0c 98 28 a6 45 + +# Signature: +38 bf df d3 27 2e 48 cf ee 68 ce b9 13 04 eb 91 +ee 25 e4 83 40 1f 30 fe 12 d5 e4 35 18 e4 b7 71 +14 a1 2c 8c 79 92 ae e7 d2 e7 74 ff f9 1d 8f d1 +cb 7c 6a 2a df 79 b7 c8 ab 93 e8 37 4d b7 4c 26 +90 9c 65 9a 97 c7 6a 22 2d f4 fc 8c 7e f5 19 90 +80 ea ae 2d 03 1c a7 51 c5 01 32 89 db 4e ad 77 +b2 8b 76 a4 c4 96 ad 0e b4 22 fc a8 8f c6 84 e4 +2a ea 88 fd 33 c2 56 75 1b a0 66 83 4e 77 a1 e2 + +# PKCS#1 v1.5 Signature Example 5.16 + +# ----------------- + +# Message to be signed: +1d e8 07 40 9d 0a 61 b0 32 2d fe d4 99 e8 c3 32 +41 ec 89 cd 7d 9f c5 + +# Signature: +8b 66 64 f8 69 d7 55 c5 d3 e6 df 99 22 e2 27 c1 +10 91 8a 6f bd 88 c1 a2 e1 28 95 23 ad bb d8 aa +43 1d 07 86 85 3a b5 96 dd 5b 00 12 43 b5 4a 2c +b1 0c 31 66 bf 00 23 38 fc a2 03 45 ae de 1b 22 +ea 1f a3 d2 41 c8 6c 76 bf c0 2f 4f ce ae 12 c8 +a9 d7 e4 4a d6 17 16 65 e8 8f 12 85 22 dd 53 5a +9d 65 00 8f 6a 73 2d 40 af 20 4e 22 0f 1f ac d9 +42 e0 9d 15 09 9f dc 51 b3 a1 42 6c b2 dd 32 93 + +# PKCS#1 v1.5 Signature Example 5.17 + +# ----------------- + +# Message to be signed: +4b 2b cb 26 79 a1 4c 3c 4c 06 9e d0 89 a6 5a ba +29 f2 2b 61 78 c0 + +# Signature: +1c 47 82 8e a5 3f b6 43 6e 95 96 b0 ce 47 d9 f3 +8b 5d eb 0b 19 7c 1b c4 74 e2 e8 22 65 70 cc 1b +72 f2 39 31 2a e7 c3 c6 38 2e 1d 8c da 7d 4f 12 +fe ba d7 0a fa e5 ac bf 24 28 ab c0 44 21 bb 4e +1e 59 90 11 1b 9a c8 3c 62 43 5c 21 aa 25 fd 9b +49 07 58 54 11 d2 53 ba 9b 87 78 f6 24 05 3d 46 +fe 95 d7 e2 2c a3 93 81 c7 79 2e ff 46 43 8f bc +16 5e d7 62 9c 2f c1 ce f1 b3 4d 77 76 8a 20 55 + +# PKCS#1 v1.5 Signature Example 5.18 + +# ----------------- + +# Message to be signed: +ef 46 ae 51 e0 15 8c d0 ef 9c 78 d7 1e 00 15 67 +d6 6a e3 c5 e9 a6 4f 24 57 15 c7 c2 ad 8e ea 0f +9d 32 00 23 07 2f db 0f b8 6a 45 21 7f d7 12 cc +80 e5 b9 41 47 c4 5f e0 0b 69 2c cd a1 10 25 98 +41 b2 c7 e5 c3 dc ff 59 56 f2 a5 96 cd a6 8e b7 +7f 4c 85 90 d7 36 b8 fd 60 66 77 3e f6 f9 5a 38 +cd 38 4e 94 83 a8 9d c2 b6 c2 e8 74 5c 95 c1 2f +a6 72 a1 be cf b6 3e ac 9b 55 3e da 8d 29 37 54 +ec 39 47 ea c0 22 8d e2 63 14 b5 9b 66 99 4c c6 +0e 83 60 e7 5d 38 76 29 8f 8f 8a 7d 14 1d a0 64 +e5 ca 02 6a 97 3e 28 f2 54 73 8c ee 66 9c 72 1b +03 4c b5 f8 e2 44 da dd 7c d1 e1 59 d4 51 d4 bf +65 80 f3 e6 9c dc 02 71 38 2e 8d c1 4b c7 33 af +38 99 2c 1c d8 82 c7 b1 50 d2 3a 06 7b 9b cf 3c +cd ab 6b 0f ba 13 2b 4c 14 47 c8 7c 39 3f + +# Signature: +8c 1d e1 5a b8 6c bf 5b d9 31 7c e2 b8 fc 82 f5 +72 2d b6 96 1c 9f 55 51 40 f7 8e bd a2 4e 3f 51 +fd 73 01 c1 e4 fe 12 b6 95 7c 30 14 4f a1 e1 27 +27 46 03 dc 02 05 11 30 b2 53 85 fc 86 46 ee 96 +a7 45 50 d2 d6 3f 85 81 85 bb 98 46 52 a3 43 1d +53 3d a6 01 46 22 a6 4e 06 91 66 2a 4f 7c 9d 58 +31 9b a3 f8 5f 19 18 24 75 e1 50 9b bf 21 3a f0 +10 10 b4 b9 f8 2e 64 75 11 fc 97 c6 b7 c9 7e 8d + +# PKCS#1 v1.5 Signature Example 5.19 + +# ----------------- + +# Message to be signed: +f8 7b b1 2d aa ad 62 c8 64 ac 3d 44 4d 51 4e ec +6e 59 b6 7c d0 82 0d fc bd f8 51 ea 73 89 1f 58 +a8 be 6e 84 3e e8 77 3e 4d c1 c7 d7 42 da 82 ff +16 c1 01 1b 99 56 6b 9f 3f d1 7d 68 d5 ac 99 ce +f5 a3 a0 f7 53 18 76 9d c0 13 bb 05 5b e1 30 56 +df 49 a8 39 b8 39 52 51 39 9b 27 a0 bb 31 c5 54 +ae df 3d 9c 74 82 b6 62 0c 5d 7c 69 14 a5 64 db +04 a0 00 04 56 99 ee 1e 50 88 a5 b6 8d 81 4e fe +9d 13 0d c3 4e 2b d9 78 51 13 9c 73 46 07 65 b1 +f2 65 46 86 fe de 9c 9b 3e 92 40 9d b2 d4 2a 32 +ba 9e 20 bc ae b2 c4 f9 ff 9b 0e 83 4b 74 92 a2 +b1 d8 c6 5c 8b a4 98 34 2a e7 d1 d9 fe 74 05 c2 + +# Signature: +20 7a 34 8c df 68 4a a8 e1 a4 af 7b 7c 25 27 07 +ce 6f 1f 9d b2 29 1f 2a 95 a0 71 5d 9c 7f c5 1a +a2 30 11 0b 5b 51 8a 9c 8f 95 8d d2 0c 75 24 d5 +b6 51 06 d7 42 1b a9 fc fb 78 91 78 41 2c 36 40 +f5 40 b8 1b b3 18 97 d2 64 5e c7 9d 8e 59 75 04 +8e 45 22 61 a1 c2 00 9c fe ee 07 15 a0 1b ee fd +75 e7 04 b2 a6 f0 f0 ae 7e a3 6c 53 cf e3 6f 57 +f0 34 e3 85 44 8f ca ab 08 dc ff 47 7d 36 ff 15 + +# PKCS#1 v1.5 Signature Example 5.20 + +# ----------------- + +# Message to be signed: +4c 4b + +# Signature: +1c b6 88 12 83 dc d1 86 3b a7 9d fb 22 35 1b c9 +a8 e0 35 8b 2f 8a 1d e3 f9 06 5d 8c a8 59 31 4a +e1 12 13 a2 cc 87 b2 f6 32 ef a6 7d 21 03 f3 82 +00 b9 19 3e b8 d4 99 82 09 9a fc 74 42 8f 4b 41 +31 6f 48 78 b3 f6 00 bc 2f b3 04 58 cc 9c 2a 03 +4a 06 8e 98 d5 7a e7 9c e3 e2 fc 84 b6 a7 45 f0 +37 a5 de a2 b9 da 4e 8d b4 ad a6 9f b8 2d 20 a4 +1b b8 43 07 93 ee f9 2a 4f d6 18 6d 17 96 63 cb + +# ============================================= + +# Example 6: A 1024-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +d6 31 14 57 e1 ca f1 22 44 36 69 79 83 c8 6d d3 +38 20 58 62 d2 a1 05 ba f7 10 34 28 fd 83 53 a1 +9b 7b a4 22 8f 78 b4 7f 79 07 35 70 34 c5 2d 85 +97 da 2b 5d 13 dc 53 5b 83 6c 74 13 0a 36 48 91 +8d 4a 7a 83 99 0c 2e 28 81 6a ec 0f ca 01 d1 05 +c6 c6 52 ec 57 33 d0 1f 00 58 b2 df 5a e6 73 33 +40 5a 3a 5b 12 20 a2 6a c3 d1 42 f2 b4 d8 37 eb +73 86 a4 0a 74 cc 3d 1e 4f bc 64 fd 7d a6 3c 41 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +d6 31 14 57 e1 ca f1 22 44 36 69 79 83 c8 6d d3 +38 20 58 62 d2 a1 05 ba f7 10 34 28 fd 83 53 a1 +9b 7b a4 22 8f 78 b4 7f 79 07 35 70 34 c5 2d 85 +97 da 2b 5d 13 dc 53 5b 83 6c 74 13 0a 36 48 91 +8d 4a 7a 83 99 0c 2e 28 81 6a ec 0f ca 01 d1 05 +c6 c6 52 ec 57 33 d0 1f 00 58 b2 df 5a e6 73 33 +40 5a 3a 5b 12 20 a2 6a c3 d1 42 f2 b4 d8 37 eb +73 86 a4 0a 74 cc 3d 1e 4f bc 64 fd 7d a6 3c 41 + +# Public exponent: +01 00 01 + +# Exponent: +5e a6 11 77 44 2f 89 9e ba c5 d0 96 01 c5 ef c2 +06 6b 44 a3 66 b0 00 f8 3d 74 cb 97 d1 6e d6 e5 +f2 ef 0f f8 b5 ad 81 15 53 45 fc 37 39 1a 68 a3 +40 17 08 52 79 14 43 41 8d 31 bf 99 2a 4a 12 86 +6f e9 ff cc de bb bb a6 37 ee 88 7b 71 6c aa 92 +e2 49 ce d6 57 ee d7 1f 5c cd d9 16 3f 32 69 52 +5d 78 9f 4b 33 c4 8a 95 76 44 36 ec 32 5e 86 89 +69 1c 27 2d 90 bd 88 88 98 51 37 2f b8 dc b9 + +# Prime 1: +f3 d4 b8 51 ad 7a c7 78 be cd dd ae 71 b6 13 f6 +59 7c 70 75 c4 d2 8d db ae 1e fa cf 03 59 71 ab +63 ee 90 db bd fb da 43 25 a1 5f bf 84 5e ea 54 +bb cd 05 57 4b 1c d6 01 dc ad ba 12 06 28 05 b9 + +# Prime 2: +e0 e1 ad 57 d6 8f 30 13 28 8c 14 83 e8 c5 b1 2e +fe b6 ec 14 5a e4 18 8e 1b 3b 39 04 87 90 0a d2 +c3 25 d2 32 80 6a 62 17 34 2a 65 75 95 14 f2 26 +8f ca 72 c4 c5 bb a0 32 81 89 dc fa e2 06 ae c9 + +# Prime exponent 1: +3b b6 d2 d5 1d f9 3d b4 b2 75 d4 5e 8e 76 9a f8 +ef fd 6b c5 4b c8 8c f9 49 f1 48 57 3e 68 bf 4f +cc 0f 76 e6 79 e6 9e 13 67 b9 d7 ab 1d 8d e9 31 +8b 34 b0 a4 2a 3f 0b a2 35 1b 4e c0 6f 45 89 f1 + +# Prime exponent 2: +71 f4 aa 5c 8a 93 80 af 14 aa f7 72 68 b0 55 3b +15 44 28 99 9f fd 5a 1c 18 dc 87 e6 2d b3 e6 68 +2b 0f ad 56 7e 10 6a a8 8b 7c b8 71 3f 1c a0 20 +be 58 be 93 cc 07 6a 04 6d f4 28 90 d1 9c c5 51 + +# Coefficient: +23 1a b8 dd 9a 56 99 d7 97 59 11 ef 0e f8 7c 28 +dd b9 2e 24 6e c3 4c 5f ac 33 83 22 dd ec 89 8d +56 68 67 45 3d e6 d7 8a 45 c3 16 b1 45 a2 86 18 +94 0e 1a cd 11 58 c3 af 92 fa ab fd c3 97 84 32 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 6.1 + +# ----------------- + +# Message to be signed: +8f 75 0e 65 95 1b 5d e7 58 14 b0 b7 66 30 dc 9f +1c 62 53 a0 59 0e ac b5 51 2a 8a 4e 1a 8b e8 52 +5d 36 94 1f a9 d0 92 f6 bb 44 22 aa 8c 0a d6 42 +3e a2 8c 10 ca a6 e9 54 b7 95 69 d4 4c 86 0f 1c +65 81 eb 17 a7 54 3e 7b f7 fe + +# Signature: +b1 8b 5e c8 8d 4e 24 c9 14 b6 65 ff 9a 2c 75 f4 +e9 19 37 df 8c 19 95 59 43 e4 51 ad df 34 84 e4 +97 97 8d 26 da 23 1a f1 4d 9c 29 27 ed 21 0a fb +f9 de e3 32 67 aa 45 68 46 49 e8 6f b2 25 a0 53 +b5 45 52 90 c3 20 e3 f6 40 62 3c 75 ca 42 37 21 +f2 80 b8 87 44 24 97 f3 2a 90 d7 8f 64 44 04 77 +ad 09 27 c7 ba 01 c4 4d a9 d5 c2 83 a4 38 be 0d +c5 80 a0 05 28 fc 65 e2 04 d4 2a 2d 4e 29 13 c1 + +# PKCS#1 v1.5 Signature Example 6.2 + +# ----------------- + +# Message to be signed: +bd bf 3b 36 40 73 fe 04 8f ba e5 5e 3c de 66 8e +84 f7 53 ab fc 71 0b 8c db 7b 6c 0c f8 2d d5 b6 +74 d2 1e 2b 3e 36 b1 b0 36 0d f8 bf 7e 62 27 c9 +2e 15 f3 d7 84 + +# Signature: +66 ac f0 43 bc 6a ae 81 a4 d5 2b 4e 8c 40 12 8b +25 c6 d1 0a 8c 69 8c 83 ae d7 1e 8f 35 83 89 8b +e8 f4 c9 be a4 b6 31 90 e2 15 26 ca f8 3a b1 4a +4f 8b eb e8 13 a5 ab eb 95 95 67 bb 2f 06 c5 f1 +1e 46 4b 5c df 7b 2a 13 2d 42 6d db ec f5 85 90 +0a 0d 80 92 ca 52 b6 dc 0a bc 35 f1 40 94 69 89 +46 e1 cd 0e cd 6b d4 1e 2c 6f 96 3e e8 9c 82 19 +3e cc 5f d4 76 30 d3 4a d1 6c a2 47 9e af 06 2d + +# PKCS#1 v1.5 Signature Example 6.3 + +# ----------------- + +# Message to be signed: +3c 5c 74 bc 8f ae 80 7a e5 8b d2 13 e6 27 2a a3 +85 79 31 57 5c 2a a2 be 4b ca e4 d7 9a e0 87 b6 +b8 6f 91 5d f8 c0 96 c1 22 ed fb dc 79 7f 9d 70 +b9 76 13 97 fc e3 d3 e0 b8 a6 f2 56 db c6 60 5b +a9 48 d5 fb e6 f5 24 5c 02 95 ce 5d d7 3b f7 43 +65 17 f7 c4 22 2d 2c fd 85 42 e7 a1 00 cf 05 13 +04 a1 ab 6f e0 05 da 07 7b 62 87 8f d0 b7 41 e6 +27 1e 0d 34 6b 20 72 3b 7e 00 b3 b8 19 4e 1a 46 +0c 6b f2 56 00 76 82 90 c1 dc aa 2f 41 b9 41 a6 +4f d9 02 14 d5 16 6d 78 aa bb af 7e 41 d2 4f f6 +36 c9 76 2f d8 92 19 9d 2c fd 9d ed a5 00 51 e0 +01 b9 fd 3e 5e 22 27 ae cb 15 c1 b3 13 71 b3 5a +78 b3 b8 b7 63 63 76 f1 34 56 2b 4e 52 f4 51 b7 +41 a1 9a c9 32 56 9f f3 04 1f af 12 27 9f 90 + +# Signature: +5e 89 7f 87 9b a4 6f 67 11 2c d7 c7 c6 fb 27 37 +ad 79 3a 87 28 79 05 2a 88 45 7a f5 e9 d5 99 59 +a8 48 13 4a 68 24 de 3a 67 4f 72 a9 06 87 9e 95 +be 0e d8 7e a9 f9 74 a7 a0 7b a9 ad be c2 fb fa +02 94 37 8b 14 e7 35 f5 5f 40 3c a0 53 08 4f 51 +d3 d3 42 d8 af 9c 64 b4 d1 54 ad 9a a3 c6 bc aa +ce 1f 1b be 62 ee b5 d0 e6 c4 c0 30 93 c2 af 0f +07 88 8b 8b be fa 79 40 03 23 13 3f 77 6a 32 13 + +# PKCS#1 v1.5 Signature Example 6.4 + +# ----------------- + +# Message to be signed: +42 56 46 65 0d 6b 37 9e 16 e1 5b f3 85 3d dc 9d +44 4f 44 53 5c 49 3a 37 03 b0 01 63 af 34 76 df +37 2a 5b 28 f3 34 c0 86 03 13 e8 13 6d e6 08 29 +1b 33 78 38 1b 9e 21 eb ef 24 82 5d 12 + +# Signature: +a6 a0 cb 02 48 1a f2 48 ab ae 89 cd f4 16 1f 67 +76 d4 71 08 f1 8e c6 e8 43 7c 22 4a 14 f4 52 ad +a1 36 52 0f 0f e0 10 a7 34 5a f1 97 1a 02 e4 bc +f8 c9 8b 26 c5 b8 c6 00 3d e4 d2 b4 07 2d 8d ef +1e 19 23 d9 cc e0 a6 75 14 1d 37 87 3e 59 48 ea +6c 8a 78 0e d2 a5 ec c2 ba 9a 81 20 6c 7e cc c8 +0e ac 02 6d b7 d7 60 22 3a a2 38 7a 18 2e 98 d6 +6f 1e 23 df ea f3 51 5c ee 4f a1 ab d4 64 b7 68 + +# PKCS#1 v1.5 Signature Example 6.5 + +# ----------------- + +# Message to be signed: +f4 7d 87 bf d4 88 af 5b 24 db 34 ad 0c 13 1e fc +a1 0c dd 1a ae ff be 6e 36 48 47 22 ed 68 09 b1 +d5 7a 18 3b a0 3d 5e 40 5d 12 56 b2 50 5e cb 84 +db 35 df a9 4d e8 5d c2 a1 58 8b 6e 83 12 4c f8 +6c 5e 91 66 86 0d 4d d4 71 70 43 2b 08 ae 6a 6e +30 87 10 86 fa + +# Signature: +6c 00 8f f0 e1 28 fc ec 26 5f 37 9e b0 83 db 50 +62 4a 27 98 f9 33 67 c6 d1 6e 5d 95 a9 89 f4 f1 +ee d0 cc 4c d8 61 c6 a5 24 f2 b9 fa 30 e8 86 f1 +47 77 41 d7 ea 8a 60 df 14 0a ec f3 a6 cc f0 04 +3d ab 92 cb e7 29 53 cb 1c 18 41 e0 59 18 ec ed +5b 0f 69 4a f9 a9 8e c7 f4 e2 28 6d 23 3d fd 35 +13 2a 0b 58 4b f0 e0 dc bf 05 11 9c e2 e3 a4 d8 +13 cf 02 8f ec 48 c3 4a 18 81 eb b5 31 ca 48 9b + +# PKCS#1 v1.5 Signature Example 6.6 + +# ----------------- + +# Message to be signed: +03 18 78 d5 88 ee + +# Signature: +cc 15 4e 1a f7 13 f2 f9 5e 16 f4 11 17 5d 98 36 +ad 6d 8b bd c8 f9 8c f0 5c fa 00 58 23 5d 1f dd +e0 40 82 76 4c 29 dc dc c5 9e be 26 57 8b f9 e8 +ad 6a 5a a8 6b 9d 62 91 4b 4c f6 96 a8 ec 2d a8 +79 f8 fa 42 31 46 31 32 ea d7 bb 3b e7 50 ae 0c +56 28 a3 96 b7 0a df a2 7b 40 34 23 b1 00 18 f9 +d2 4f ea 33 70 30 14 7f bf aa 15 d4 75 32 c9 25 +7c 2c 7f 54 1b 5b 97 4d 15 dd 1e 3f d2 e2 0a 69 + +# PKCS#1 v1.5 Signature Example 6.7 + +# ----------------- + +# Message to be signed: +27 26 38 52 ea a9 60 bf 76 71 87 6f c7 90 0f 89 +8e a8 2e b2 b0 fc 41 85 65 fd ae 62 f7 d9 ec 4c +e2 21 7b 97 99 0d d2 72 db 15 7f 99 f6 3c 0d cb +b9 fb ac db d4 c4 da db 6d f6 77 56 35 8c a4 40 +11 5d 3e 5b 3d eb 1b a1 bd 90 ca 12 86 fd 10 0c +af 9b e4 85 a4 4a 38 45 00 57 18 10 4b bd fc 5e +78 1a 9e 37 d6 7a ff e5 56 dc a1 0f 8e fa 39 f9 +cb 63 92 a7 2e 3f 28 25 81 1a 2c 05 af 84 af 9b +e7 f3 71 db d4 10 6d 9f + +# Signature: +94 79 8d 17 94 78 bf e0 6d 96 a3 4a c9 9b c9 d5 +de 35 dc 46 97 ac 3f 70 e9 b3 4c 95 e2 2b 1c 30 +d1 42 6b e3 50 8e 62 2c 1a 18 ab 3c 46 72 fe 3d +e3 40 eb 51 0f b9 87 b5 3a e9 3a 59 af 6b 00 bb +ae e0 e8 27 08 e6 c6 ae 82 c8 45 53 24 01 78 36 +db 17 66 0d 06 9d 80 27 1e 1e a9 98 11 63 b1 4b +66 87 6d fd 12 8f 09 cd 2e 3d 6a 36 b7 3c 3b 40 +ad 8e 13 24 84 90 29 c8 b8 e3 c8 89 4e bf a1 94 + +# PKCS#1 v1.5 Signature Example 6.8 + +# ----------------- + +# Message to be signed: +a4 fb 21 03 d0 be 29 0e 99 60 16 a4 39 46 2e 6b +bd b0 72 4d 86 cd 51 85 91 33 ca 3d 39 da b7 7d +a2 06 9d 82 83 58 96 38 7c cf 3d f5 cd d7 a5 79 +3f 22 3f 3d 92 3e a4 63 51 35 31 ad a6 67 ab fe +f7 53 98 c7 a4 bc 6e fa dd 4e de ef 35 ab 8f 54 +01 e0 da f7 c2 fc a1 cd bb ee d3 bc dd 09 33 ff +3e e4 c5 e2 88 ab df 21 9e 36 a3 ee 6f 21 08 41 +a0 3c 9e 3e 4d ac 18 12 24 82 ef 85 f4 9f da cd +c5 02 d2 79 f1 57 7b e7 7a 4e 00 b7 c7 f1 7b a5 +da 6b 28 c0 1a 07 a8 63 df b2 1c 15 6d a3 20 01 +f5 3d 7e a3 fc b8 c9 55 4f 07 54 59 a6 7c c3 c4 +e6 9a 6a 37 17 87 87 46 3c eb ca ed a6 49 0a 8f +80 b3 92 de f9 f2 2a 4f + +# Signature: +72 66 70 c9 51 0b 58 35 4c 8a f3 2b 41 db 8f 69 +21 07 c0 c8 76 e5 52 73 a8 20 a0 c3 0d 39 24 46 +0f a5 bc 33 df e1 9d 72 e5 63 49 28 2a 80 fb 12 +a8 fa 9e a4 a5 da 69 c5 82 d7 c6 41 22 a8 a7 91 +b3 21 2c 39 e0 28 26 5b 84 54 df 71 5b a3 0b 00 +3d 12 91 69 cf 12 51 1c 0d 3e 7a ae ce f3 79 2c +f1 85 64 4c f8 0e 44 81 47 b1 a7 96 1a f3 84 41 +7d 18 2c 6f 85 52 46 da d5 b8 93 d9 a7 68 0e bc + +# PKCS#1 v1.5 Signature Example 6.9 + +# ----------------- + +# Message to be signed: +e5 50 6e 04 b1 91 84 10 76 85 87 25 a9 fd d8 f9 +74 5f 24 2e 99 49 4a 42 3f 80 36 74 74 27 1d ce +95 a9 9a 2f 71 13 4f 39 fb 3f 2e 47 c6 a0 b2 fb +6f 61 5b 0d ee 6d f3 3b 28 f8 b0 d4 1e 92 d1 42 +b1 46 e8 cd e9 b1 1d 6e c1 d3 7d 71 fd 82 b7 19 +ce 1a dd b8 21 ca 4c af bd 2a a4 f1 e6 11 a2 59 +e5 f0 5b 53 1f a1 1e 3b 67 1b 7a 5b 10 b4 c8 15 +6c 25 b0 a5 9e c6 e1 58 f6 d3 46 d8 48 04 fc f9 +2a 72 76 8f 4e bc 93 5e ee 5c fe c7 f6 e6 e8 3c +be 15 8a 13 27 5e 84 18 3a 94 d7 24 b0 e9 66 96 + +# Signature: +34 22 0e da fd 4a c8 84 b9 d0 0f bb fb 71 a4 a6 +c4 d4 b7 1c 19 84 22 05 07 99 d0 c0 fd 54 e9 09 +a4 ca d2 29 8f aa b3 34 7a 0a f0 d2 7d 53 01 a8 +86 00 9c f5 c6 f1 25 df c1 13 1a ce 38 8b b2 14 +c2 84 44 20 c0 23 db c8 b4 a9 66 11 b3 b3 93 ac +c3 83 94 90 fc 4e e2 d3 69 b8 c3 c8 76 57 22 83 +ef 34 d7 0c 64 03 ef 9e 2e 87 a2 76 b2 35 72 ed +82 e2 40 22 67 c2 73 7f 75 bb 4a 27 d3 cf 16 d2 + +# PKCS#1 v1.5 Signature Example 6.10 + +# ----------------- + +# Message to be signed: +8f c9 cf a7 21 df a0 9b a0 72 9e f9 18 9e 54 27 +b3 e7 38 c5 ae 38 a2 65 7f 7c 7e 31 4a 49 ca eb +a0 fc 9d 45 40 f5 f8 d6 c0 47 53 60 0e f6 b9 c3 +39 65 40 f8 6c 11 75 b6 0b f4 0e 3d 8c 84 51 35 +5e 13 74 f4 30 43 c0 c6 aa 41 d3 79 6b d8 27 9b +3c 30 62 b3 74 99 6b 7e ae dd 4d b0 ae e8 c9 4b +93 b1 71 fc 41 1d 4d fc 37 28 d0 23 15 58 cf c8 +fa 45 f9 51 b3 5c 9d 46 12 18 a6 50 c7 02 ce a9 +3b b3 fa 14 36 ed 44 5c 95 24 9d c2 20 54 71 01 +b9 a9 3e b0 14 cd 84 3f f3 9c e4 c9 6f 82 a3 9f +86 3a 4c 2e 1f a9 + +# Signature: +a2 6e 7d bd 5d fe 08 c7 2b d8 0d 5e 26 68 d5 d7 +2a bb 1a 0c 04 20 ff 0e a8 6a 9c 76 08 c4 70 e1 +c3 f7 2e bf 44 5d 12 18 71 81 41 55 58 dd 03 eb +e4 07 aa 06 b5 16 47 ba fe 0c 85 f3 d3 b8 dc e9 +0c eb f0 a0 ee cb ac 12 28 e7 85 82 0c 4f 90 9d +2e f3 92 f0 31 17 56 1e c3 8e b0 d8 8b 02 32 72 +a4 28 63 51 62 0f 21 04 3c ca f7 50 36 84 00 29 +57 ef 79 bc ff 9d 1c 20 1c 42 e0 96 0b d9 69 79 + +# PKCS#1 v1.5 Signature Example 6.11 + +# ----------------- + +# Message to be signed: +96 1f e3 4a 21 2c b0 e6 f6 dc de cf 1a 4c b7 b2 +14 39 0a 77 f4 4d 3a 3b 3e e2 b1 2f 1f 0e e3 14 +2e 9e af 70 89 55 ec 83 7e a1 d0 d2 95 4e 6c e9 +50 f3 4c 87 30 54 8f 2e 09 5d 5d bb 93 8b 19 0b +73 8b ff 81 71 93 02 b6 79 8b 76 8b 0b bd d2 e2 +b9 67 2d 89 14 05 c7 71 a7 79 02 fd 54 27 42 5a +f0 4e 21 b9 1c 5f 39 37 20 41 e4 94 d9 be 62 de +ce 31 bd 8a 26 2f 6d db 84 9f 06 8a a9 9f 7d 62 +62 e1 84 ab 9c b1 62 24 47 d6 2f f6 71 09 20 30 +70 71 c2 72 be 0b b3 7f 0e ef 64 5f 99 ea b5 1b +0b cb bb 64 87 d8 d2 b4 9f 3f 23 e0 aa 91 8c 89 +ac 85 56 53 e1 cc c0 05 91 58 0e 0c e1 e3 87 79 +c0 4b e7 df 1c 66 63 ac d9 93 7e 47 2b 3e b6 d4 +b7 0a 08 0d e8 e0 35 48 f5 12 45 be 7c e0 b8 6d +ee c1 76 e0 0e 54 bd 63 bd 5b b0 2f c9 54 + +# Signature: +98 ac 47 73 59 15 9e 93 e1 b3 36 ee 05 60 6d 42 +b7 e1 25 0d 12 95 60 c0 d0 95 f8 f8 ea 3c 04 74 +32 a9 9c 1e c4 bc 88 7d 7f 07 f6 1d f1 6f 0c 09 +f7 15 b7 05 38 8b b8 a6 11 87 34 6e 8d 7b 07 ea +b2 fc 05 db 89 e0 30 09 44 ae 37 73 e4 4c b9 2c +5c f0 f4 fb e0 1a 05 ad 79 bf aa 24 7f 83 ed 1e +da 48 ba af d1 e1 80 07 8c a8 d3 21 d5 0b 42 57 +87 f0 12 43 a4 93 37 4e 84 f5 cd 56 b7 53 d7 ac + +# PKCS#1 v1.5 Signature Example 6.12 + +# ----------------- + +# Message to be signed: +96 ff 0a 5e ca c9 51 16 bd 73 43 79 5a f8 3c 87 +ed 9f 83 45 d0 3f 6f 32 2f 29 54 93 f4 0b 19 ba +8f fe 2c 89 8c 7b 20 66 21 f7 2e 02 c7 f0 f0 0f +9f 1c 52 3d 73 d3 35 a2 6c ed dc 73 98 b7 ca 20 +09 ca cb b1 82 83 b7 6b 28 15 d1 e9 01 00 09 6e +95 b8 85 30 f1 c4 8c 39 61 c4 35 bc e0 28 9f f6 +2e 21 bf 4d 3e c8 99 c8 7e 14 c8 ea d7 92 2e 79 +5e 3e 6f 41 80 c0 89 9e a0 + +# Signature: +7c 7b 01 57 f6 a5 09 09 51 09 63 28 2f 00 11 1e +ea 70 19 37 54 e4 27 a0 2b 34 6f eb 68 2f 4c 71 +87 bb 38 1d 31 d2 3b 94 76 88 43 24 5a ad 53 61 +fc a4 2d 8b 28 4c 8d 92 e6 fb 99 2f a7 71 2f a5 +a9 31 55 df 02 0d 30 0a 3b f8 98 86 66 8c f3 7b +d1 3b 55 0a db 2d 2a 86 c6 9d aa ac dc 50 30 dc +84 34 3c 8b 49 34 f0 3c dc 0e ef 0f 6c 1e a7 ec +09 62 00 79 03 b4 48 21 7d e9 3b 75 07 54 9b 2e + +# PKCS#1 v1.5 Signature Example 6.13 + +# ----------------- + +# Message to be signed: +32 a1 2e 0c 67 0e d2 15 ae 54 49 a0 91 7a e9 5e +23 db 80 3a d2 8a 18 42 ed fa 90 bc 40 5d d8 9a +1b 46 8a ce bd 08 fe 9c 69 3d 8f b1 05 e8 22 2e +b5 7f 79 e4 b2 27 00 e0 7f 27 6d 4a ec c7 a1 5f +b7 47 33 06 56 27 b8 79 b0 16 ee d4 ab 4a 1c + +# Signature: +85 b9 0e b8 26 51 4a 0e c0 fc 1b dc 34 86 a8 dc +8b 0f 26 3e fe 57 cf 17 50 a4 2a 6b 5b 99 72 64 +fa 61 78 64 83 7e 63 9f 45 d9 20 58 41 cd c1 34 +ab ea cf 6e e0 ec da 09 b9 8d 76 9f 51 f3 94 7a +33 58 7f f0 c8 dd 01 b7 f6 b2 4a 2f bf 29 c9 ff +f7 37 ee e5 6a da 2c eb 74 6b 02 5d 95 65 22 d9 +20 d1 2d dd 13 db a0 8b 20 e1 ee e1 3a 8b 25 80 +e5 92 c3 4e 39 33 37 66 11 5a 23 b9 d0 0e 2a 42 + +# PKCS#1 v1.5 Signature Example 6.14 + +# ----------------- + +# Message to be signed: +bb da 73 cb e2 bf f7 ff 53 62 eb e9 32 c0 a0 dd +68 ac 84 ee 99 8f bf 59 a2 a9 26 55 20 32 31 63 +b3 0d 9e 70 08 b9 4b 0c 0e bc 5f 6c 4c 97 3c 13 +ff 15 3d 31 69 0c 3c 95 ab 23 1f 0c 9e c9 98 fb +fc ad c2 8b 2d 7f 06 50 7e 17 d2 1e 82 da + +# Signature: +26 f9 52 b6 57 fd b9 a1 1d c8 43 79 0c 9d 2a 6a +51 c9 76 10 1e fb 82 d0 53 60 67 62 ab a3 3a f6 +28 0b de 38 15 e0 87 4d 60 78 75 38 42 e5 b1 c9 +0c f7 99 12 20 fc fa 62 28 49 43 69 0c 30 1e 9f +c6 e4 79 af 68 b9 69 47 85 be 40 d4 69 86 a6 2a +12 1a a9 ad 0d e9 69 52 1f 1c b8 e7 c4 bd 70 c7 +c8 cd 7a 9d 13 54 e7 d0 aa 0d 85 d6 d7 aa 00 e4 +64 90 26 d6 f0 70 f8 b3 c2 7c 98 55 6b ea a4 c0 + +# PKCS#1 v1.5 Signature Example 6.15 + +# ----------------- + +# Message to be signed: +2c 32 5d da f6 52 6a 1e a3 51 8e e5 e5 40 7f 03 +90 e0 eb aa a5 f4 72 a1 e9 ab 46 f7 46 d7 1b a2 +e2 17 fa a8 17 99 bf 35 8f 95 e9 83 08 27 0b 18 +a0 01 99 29 a2 88 d0 c9 56 e0 bf 17 c5 19 8c eb +2c d9 fe 40 d7 02 a4 4e 56 45 ec a5 b4 39 ab ca +7b 2c 6f 95 ac c3 c2 c3 65 19 5c 79 5e 91 d6 3b +3c 09 33 24 4f f1 25 63 af 66 22 a4 0c 74 15 db +60 a7 8d ca 02 60 25 14 39 53 8d 38 aa 38 28 9d +92 88 86 ab 12 87 36 a6 a8 73 9c 14 55 c4 84 9f +2d 54 56 45 37 93 + +# Signature: +6d 1f 20 3d c3 ff a7 a3 34 d3 1b 9a 75 e0 12 58 +1b 8d 62 b2 bf 73 80 0b e5 1d 02 65 33 99 83 18 +c0 ca c9 2a 02 d4 6d 75 9b f8 0a 41 da a0 a6 a2 +9f 4f a0 bb 60 66 4c ac ad e2 4a 65 cb 47 65 11 +09 be ec 82 31 91 95 25 d1 47 32 68 74 55 78 db +9e 30 64 10 8a e4 6a 48 70 f1 80 66 78 9b 03 66 +a7 d0 ce 37 e0 30 b5 89 46 ec 8c 1a 14 11 54 db +0e 26 1b ef 8b af 2e 9f 65 fc d1 6b 7d 57 97 b6 + +# PKCS#1 v1.5 Signature Example 6.16 + +# ----------------- + +# Message to be signed: +29 85 e8 b5 50 81 2f b6 6c 18 f8 0e 6f 09 2a 94 +5d 09 15 83 86 1b 62 5d 1e + +# Signature: +2e 84 30 13 cd 5e 79 5e 21 66 c8 e9 1b 06 c3 13 +1d c3 a5 e1 21 36 d7 16 0f fd 11 bb ef cf 6a b6 +40 e0 5d 76 e0 c6 1e d3 06 f6 08 6b bb 56 7c a8 +7e 40 c6 92 4d 5c 84 a6 ce 28 a8 39 50 bd 4b 84 +e2 7f c5 06 9f d0 62 4d 50 ea c2 4a 94 11 b5 f7 +67 85 d9 db 5d a3 0f 42 56 95 b0 19 b8 4c db b8 +25 bd 46 e7 35 2e 08 f1 14 c8 7b 06 6f e4 3d 10 +56 a2 c6 10 ce a7 e3 d3 dc 98 bf 44 97 eb 4f 13 + +# PKCS#1 v1.5 Signature Example 6.17 + +# ----------------- + +# Message to be signed: +77 78 8e 83 8b 83 4e 8f 4d 04 5a a8 94 b9 0a bb +85 94 0c fc 58 d7 72 5e 7f 37 3d a5 54 71 37 c6 +0b ea 75 1e 01 42 bf 9a 6f 46 49 ae b5 46 ed 56 +0c c4 ea 15 62 d4 a5 fa 3e b1 b1 14 77 a3 05 1e +24 c6 06 b8 a7 1c 1a 77 4b dc f1 a5 31 0f ed 55 +59 23 73 0f a8 af 4c 15 80 0d 36 2b 37 ad f1 4f +7a fc e7 8e fa 6b d8 93 56 3e fe 0b 3b 82 8e bd +49 9f 12 a2 fe 33 2b fe 46 dc bb 31 4b bd bf 69 +08 7e 2a 66 5d f1 10 83 5d e5 5d 61 e5 c2 02 5f +d8 db + +# Signature: +8e 5f 33 53 c4 9c bb b2 ea 69 6a bb 57 40 ba e0 +15 ef fd 95 0d 56 07 13 76 05 a1 00 c4 a5 3f 1b +95 17 6c af 34 9f 4f d5 88 ae dd dc f5 06 0c cb +72 47 8c fb 09 85 62 f3 4d 8f 8e ba 44 6a 38 47 +56 5a 7b 89 55 ad 9e 0c 6e b6 70 99 e1 a4 6c 3e +b2 d4 9d 90 90 ae 5f 63 e8 a0 8b 6e 8f 21 f0 03 +e4 51 d2 50 ff c5 a7 90 d6 6a 0e 2e 3e 28 a6 33 +9f e9 1d 11 29 21 f5 5d 12 30 30 6f ad 5c 01 90 + +# PKCS#1 v1.5 Signature Example 6.18 + +# ----------------- + +# Message to be signed: +1d 59 9d 76 2c d5 4d f7 0f 1a 09 83 bc 3e a2 bb +ca 6f cb bd 16 26 03 ba 81 56 10 77 fd 92 84 92 +5c f1 f1 b0 8b ea 1e 70 bc 59 5d f0 b3 43 b8 3b +9c f3 d6 34 f9 5e 37 e8 d1 c5 85 fa b1 99 + +# Signature: +71 74 97 a4 e6 0d bf fa 19 6e ff 75 8e 90 1c e1 +fe 6e 2b c7 e1 d5 3a 3d cf 62 25 67 1a f1 46 c5 +de e2 00 a8 14 f4 89 8d 16 a9 b5 f5 08 dc 9f de +4d 64 07 0e 55 ae 3b 1f df 79 19 f4 2b 7c ff b7 +e9 28 c4 ca eb 55 2d c6 fd 08 18 34 b2 dc 2f ed +07 e7 e6 27 d3 4b 39 10 ca 71 3b f4 15 4e ff 99 +96 57 36 15 18 fc e5 a8 f6 42 dc 9a 18 a6 6e de +22 19 0f 60 aa f9 58 d6 24 6b 00 a0 32 c3 98 41 + +# PKCS#1 v1.5 Signature Example 6.19 + +# ----------------- + +# Message to be signed: +da 51 00 86 60 b6 3b 87 67 e6 5f 12 c6 30 8e c1 +8e d9 57 5a 42 6b c5 fb e6 60 10 ec 3f 01 17 5f +fa 57 41 ea cc dd b0 2f ce 7b 2e f7 78 44 40 d7 +2d 37 52 20 3f 53 4e 52 fc f6 26 a8 c5 96 51 3f +41 90 64 bb ba fd e7 f8 d6 5f 30 d7 ca 68 71 89 +70 de 71 fc 8c 0e ed 4d a0 0a 4e 1a b5 41 02 d9 +d1 65 bd 7c 54 af 5c 31 c1 5c 05 bc a5 5b 6f dd +19 10 86 a5 3e 52 96 f4 84 c3 47 d8 fb 94 5a 10 +c4 94 49 75 27 32 f6 2f 34 c3 25 15 58 86 51 13 +79 19 28 5a 2c 8e f7 b4 aa 0e 69 0b 0b 65 43 7f +f8 d5 6f c9 5d cb c3 e7 8d + +# Signature: +32 67 72 28 ff 08 c6 6f d0 3b b3 1f 0d fe 89 01 +53 b3 44 6b 57 eb 84 ef 39 56 20 8f 72 a0 7c 87 +67 e6 bf 09 f0 38 bc f7 f7 35 ee 24 a1 f6 40 a1 +89 8d 40 9e b5 3a bd b6 93 94 27 34 56 9a f7 1a +4c d9 9a 65 20 ba ca 5d 42 86 b1 99 cc 67 62 8e +2f ca d2 96 a3 0e ca 49 9e b8 80 50 7f 6a 37 44 +0b 61 c1 28 4c 40 3c 41 32 1b 99 05 3f 5d 69 72 +8d 5b 97 35 76 cf 04 74 83 33 d8 08 d5 e6 8a 8f + +# PKCS#1 v1.5 Signature Example 6.20 + +# ----------------- + +# Message to be signed: +8c d2 da d2 a5 d5 f9 fa a0 7e 24 a9 6e 86 f9 b0 +ac 8b 40 22 2a c9 fb 8a 8a 15 72 7c f2 f5 3e 68 +4a f4 ab dc 98 68 a7 25 3b 25 b0 96 bd 70 1f 46 +a9 43 + +# Signature: +8f 03 22 eb 2c 54 05 24 85 a6 45 49 ad ff 2a 36 +31 db 65 76 fc 0c af b5 51 69 7d c5 35 6f 02 e0 +93 cb 69 17 3a 7e 83 55 a0 da de bf a5 3c b2 90 +7f 00 2d b3 a3 e3 87 da 05 7b 7c 73 55 16 43 84 +3e f5 74 48 1f 80 74 15 17 7e 4b 34 c2 5b d5 5f +4c 02 fa 0a de a3 a9 58 04 65 f3 58 c0 05 96 b5 +cc 06 2d 58 92 30 3e 1a cc 11 3c 3b 4b c7 4d 42 +e8 58 02 90 78 48 2a 1b 23 4a 62 5b 04 28 44 06 + +# ============================================= + +# Example 7: A 1025-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +01 69 34 cd ff 48 50 b6 00 2c c0 f0 f4 01 0a 32 +c6 55 e5 cf 6e 7c 89 93 7f d7 55 ef 6a be 37 9d +ad de 70 cc 21 77 51 f1 4c ba 6d 90 fe 52 dc 0a +f5 8b 25 2f 26 bf 72 da 57 9f da f5 7d dd 6c d6 +02 18 79 94 9a 02 76 b4 43 3f f0 1e fc cc f3 5a +11 e7 c7 7b 38 c1 8c ca 94 ae 01 2d 0f 37 04 21 +49 1c 52 ad 15 ac 76 b1 2e cd 21 8f 52 e7 57 86 +6e 08 9d d8 ad bb 48 e9 ba 89 43 36 c5 75 c4 06 +55 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +01 69 34 cd ff 48 50 b6 00 2c c0 f0 f4 01 0a 32 +c6 55 e5 cf 6e 7c 89 93 7f d7 55 ef 6a be 37 9d +ad de 70 cc 21 77 51 f1 4c ba 6d 90 fe 52 dc 0a +f5 8b 25 2f 26 bf 72 da 57 9f da f5 7d dd 6c d6 +02 18 79 94 9a 02 76 b4 43 3f f0 1e fc cc f3 5a +11 e7 c7 7b 38 c1 8c ca 94 ae 01 2d 0f 37 04 21 +49 1c 52 ad 15 ac 76 b1 2e cd 21 8f 52 e7 57 86 +6e 08 9d d8 ad bb 48 e9 ba 89 43 36 c5 75 c4 06 +55 + +# Public exponent: +01 00 01 + +# Exponent: +0d 17 19 e5 bd 47 6d 87 c7 ec c3 1e b8 ab 42 5d +4f e4 c8 f5 c7 ae 23 0a 10 47 55 3f fb 53 9f d3 +85 5a f5 a4 3b 2d dd 4e 95 a2 b3 0d 40 7a a8 81 +59 bb ad 2a 87 3d 80 93 b4 8a 4b ce 20 ad 99 26 +25 3e d3 39 ac 3b 54 3f c7 42 96 95 33 8d b0 bc +1d c3 68 6c fd 13 9b b5 b2 87 36 bc 16 60 a9 53 +48 fc 91 c3 25 d0 3a 7f b2 16 d2 d9 cd 93 64 de +4e e7 d2 11 9c 3b 0f bb a8 a7 1f 0d 3f 5a b9 b9 + +# Prime 1: +01 58 c0 24 6c d1 69 fc 59 3b 25 8b bf 45 23 ab +2b 55 c4 60 73 3a 7f b4 69 10 90 77 b3 0e 4d 35 +f2 1a 35 b1 f4 1e 42 04 e8 1d 2e 4c 46 3c 24 11 +39 34 09 8b 45 2d ab 4b e1 59 97 20 ef 68 72 83 +3d + +# Prime 2: +01 0c 38 2d ea 5e 7d 79 29 8c 64 1f b2 e4 fa 09 +f2 4f 6a 7a 45 9a 88 2c 87 a8 03 49 5f 05 6e cc +3b 43 c5 37 73 1f 85 ef c8 fb 53 87 ad 67 31 a6 +43 53 32 15 de cc 38 7d 96 76 12 2c 17 0e 91 e0 +f9 + +# Prime exponent 1: +d5 78 dc d5 38 f2 fc dc 30 00 b6 c0 f0 49 fe e2 +ad 90 14 fd 24 fb 10 b6 82 18 42 d6 70 03 a5 64 +cd 8f f4 2a 2a 56 4c fd 81 9c 3a 84 bf 16 c2 47 +7e 8e 6e 5b 9e c4 d4 0e ad 50 24 87 ba 50 36 2d + +# Prime exponent 2: +88 88 dc 8e ae 94 ee a5 80 ca c2 fc 1c e5 4f 44 +e2 ba 50 0d b8 71 53 41 a6 fc 2d 50 4a 82 b1 42 +05 e8 91 a6 6f c8 8d 5c 60 db 8f 78 6c cc 70 57 +5b 35 66 be a8 74 a5 31 7f 5f 16 c4 91 ed 1e 79 + +# Coefficient: +17 b0 d6 23 36 19 1e 63 bc a1 59 93 4d 06 16 cb +89 97 40 9c bf ca 37 05 69 5b 14 fb 64 a0 81 c1 +c9 f5 86 19 3e 52 3a bd 0b eb 8d 72 0c fe 53 7d +fa 1e de c4 a6 64 37 d2 41 19 6b 7a 2c e5 56 c4 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 7.1 + +# ----------------- + +# Message to be signed: +35 39 99 7a e7 09 fe 32 c1 03 6a 13 27 57 f2 a1 +66 7a 91 cc 83 be 73 3a ad a1 bd d2 17 92 4c 9a +2c 9f ed 1f ec f6 1d 1c f7 9d ae 9a 83 f8 ae 3f +4d 05 1b 34 fb b5 59 cb fd a4 92 f1 d8 3b 8b eb +a0 45 d4 ae 1c 8f ea 15 b7 57 7a 1b 8a 3f 55 ba +c1 72 7e dc a7 f8 f5 2c b4 ba 61 ca f1 fa 8f 8f +d9 aa c7 79 09 5c a8 4c 79 91 52 9f b8 06 99 d0 +d4 68 8d fd b1 42 ed 61 a9 5b 89 ce 33 06 bf 97 +80 e1 b9 1b 84 8c 8d 20 03 97 0e 52 70 2a 1f 61 +2e 2f 40 17 cf e0 a9 1d b9 e4 6d b9 dc + +# Signature: +00 08 0f 77 0a 2d 1f 6a bf 5f 22 1f 62 e1 66 ab +d7 9d 06 c7 b9 a8 78 d6 1b 80 fc 4d 5b a2 90 b2 +3a ba ab 51 8f 09 44 7e 45 ae e6 f3 bd 06 10 24 +44 36 a4 73 01 60 e6 a6 72 11 0c 01 ae b5 62 4b +71 8d c7 c0 86 1e 58 6b a8 b6 0a 29 d6 a5 75 5c +d2 cc 50 85 99 c6 e2 8d 73 55 b2 7e 40 b7 40 c6 +fb bb b1 a9 18 23 b1 c1 24 2b a6 93 d4 52 69 51 +47 db b2 3e a8 9c bf 11 eb 8b 07 ec 3a 02 7b 0f +17 + +# PKCS#1 v1.5 Signature Example 7.2 + +# ----------------- + +# Message to be signed: +31 80 08 87 3c 4c fe a7 12 5e a6 fd 52 15 df d9 +8d 5c 5e 73 32 3f 03 f2 15 c6 9c 8f 2b b1 98 3b +59 df a6 e9 9a dd 30 69 66 f3 11 0c 16 1c a2 26 +24 b8 80 70 26 5b 8f 3f 9d 5d f7 29 91 e7 9e 5b +18 9a a3 d9 cd 9b 20 47 cf a6 1d 01 23 4b 23 3d +36 ac 4b 96 ed 08 16 48 87 74 90 fa 4a 80 ec 4c +bb d9 d2 e0 06 2c 39 e1 85 3a 0c 38 34 4b a8 58 +bd 1d 99 5f 6c aa 28 bf 90 40 26 26 8a 99 72 11 +43 c8 6a 43 43 ba f8 9b 6d 55 07 64 25 1f b0 7d +16 7b 4c 4b 1b 70 f9 9e f5 fe 50 e6 2e 54 13 fc +ce 0f 99 59 c2 a3 78 c4 1d 6f 42 36 17 8b 14 b8 +91 9d b1 d0 + +# Signature: +00 6d 54 7d a4 ed cb 10 33 15 cb 8e 4b 66 9b ee +96 aa 21 56 23 5c a5 c3 e3 1b 24 a1 5a 13 92 e4 +94 04 7f ed cb 70 81 90 7c 56 17 a8 aa 18 d1 01 +b0 53 2a 36 32 45 19 23 c4 8a 75 b0 ec 21 76 cb +98 e5 ce 51 58 8b cf 86 8e 29 d5 d9 69 4f 00 ae +2c 92 4e 73 d2 e6 dd 14 4d 24 fa 45 d0 12 06 a3 +f5 d9 36 41 3c cb b7 4b 0e 2d 04 7d 82 b6 00 b8 +9d 51 59 4f ce 7d e6 bb d9 5b 97 fc fe c5 98 c4 +eb + +# PKCS#1 v1.5 Signature Example 7.3 + +# ----------------- + +# Message to be signed: +7f 83 b3 e0 54 c0 24 82 50 78 dd 9f 04 0e 1d 09 +05 82 00 c9 75 7b 76 fb 37 2b 8b 52 66 b9 dc 26 +9e c7 56 9d 00 + +# Signature: +01 34 ee 21 51 51 e5 32 50 f5 a0 01 6a cc e3 70 +1e 2a 58 dd aa d6 cc 36 9d f0 dc d9 34 6a 2b 53 +0f e3 71 5a fe ff 1e 9b cb 72 08 31 c1 25 58 97 +0a 9e 03 89 60 04 f2 87 ad b8 21 f3 17 cf 63 93 +00 ca e6 e9 09 e9 1e d2 a3 ea cb 99 52 a7 cc 54 +94 76 52 64 24 79 51 d2 8c 16 af 03 e2 4b 80 ee +32 b0 b6 2e df 10 d7 00 91 92 71 35 f0 5a 88 9f +2f 60 56 b9 5c dd ac e4 7c 69 f9 73 08 c0 df 2e +ba + +# PKCS#1 v1.5 Signature Example 7.4 + +# ----------------- + +# Message to be signed: +17 eb c1 50 07 bb 5e 4a f9 17 20 1c 3b a3 84 92 +65 89 c3 15 9a 89 d1 ab d4 c2 c9 86 fb a0 37 9e +8a f1 29 75 c5 d0 31 d1 bf c1 5c a9 17 36 f0 7b +17 66 d8 b8 a7 2d b1 0c 26 8c 98 fd 7a a1 1e 29 +99 f0 6d 86 12 7c c8 89 cf 15 0d cc 73 8f 6a b8 +ba ae 94 3c c6 06 dd 4d 9e ce 70 1a 4a 7b 10 1e +35 1d ee 20 b1 5e bc 55 25 6d b3 ce 46 a6 bd 50 +61 12 5b 62 b9 95 e9 70 d1 6f 7c 9a 8f c1 57 ff +68 ce c7 e6 0f 60 8f 66 26 dd 39 52 8b 24 09 aa +2f f9 32 fc 11 9b 2a 7a 81 77 2a 57 6b 3d 50 a0 +d2 87 a7 fa 2d b8 7d 2b 92 e1 c9 61 a7 0c aa 44 +d8 81 37 b9 50 e1 00 71 1a 98 54 ad fa fb 49 4d +34 e2 86 06 a2 7c + +# Signature: +01 05 da dc 99 c5 9b 5e 3a c5 54 b1 b5 e7 48 0e +5c 0a 62 c7 ab ae fd ac f4 42 6e cc fe 68 6b 8a +aa 1c a4 f5 1e ba bf fa 77 d9 98 03 e7 ee 8d 20 +d1 20 4a ad 8c 67 38 5d 07 44 c8 54 de 2f 99 7a +56 aa ae 04 ce cc 65 65 35 c1 6b b2 14 5d 18 01 +81 25 94 a8 01 3b 0e b5 4e 7b f6 5d 38 42 00 54 +ec 46 da c7 1a 12 52 08 b3 02 21 4a 7c 9b 3a 92 +ca 9b f7 37 39 c7 66 30 9a f8 03 ed de 7c 54 d2 +46 + +# PKCS#1 v1.5 Signature Example 7.5 + +# ----------------- + +# Message to be signed: +6a 52 ba 19 0e 44 ca 0f 10 70 02 10 48 76 2f 3e +79 ed 51 c9 4f 6d c1 a9 f1 ed 78 35 2e f3 79 aa +49 b3 a9 38 7e 3c a7 a1 96 f1 05 dc ab 18 50 6f +29 4a 69 + +# Signature: +00 0b 70 e6 01 c5 ec 58 68 4e 09 18 ba 7a 53 9e +9d 2d d2 9b 01 a3 f4 53 ca d4 a9 a4 0e 50 f5 db +df 72 c1 10 52 f2 0b e4 4a 5d 38 51 b0 1f d0 9d +9c 92 08 47 0f 0a 4a 95 03 5e 98 9e ed 7d 6b 06 +2e 13 f4 99 5b f0 93 0b 4a 3d 9b 8a 9e d7 5e 33 +88 6e 4b 19 4a b5 cc d6 b4 12 95 9c b4 f5 49 8b +d3 2f 66 85 46 be 2c 00 7a e8 de 5d 98 97 7b 94 +b1 7e 12 63 88 4b 54 e7 84 b3 8f c1 12 b8 cb dd +56 + +# PKCS#1 v1.5 Signature Example 7.6 + +# ----------------- + +# Message to be signed: +bb e0 b9 de 2b 5e 9d cd 31 67 42 94 3f 92 19 b2 +4f 66 a3 8f 9d e7 09 46 4f a5 49 5d 79 4a 63 7b +9e bc 06 77 62 da 7a 6e ef f0 98 fa 44 f3 cc 36 +f2 cc ef 67 fd 46 c5 9e 24 73 8c 81 0c 69 ed dc +d9 0c c7 d7 1a 4c 3e 69 3b ca a2 8a 53 3d 90 4b +41 ce d3 39 9b 4c 76 47 e5 ec 4b 3a d9 03 87 0f +5b 5f 8d 6a 8d 81 28 ae 23 81 ce c8 6c 4d 85 b7 +8a 45 1e 1e a9 7e 33 93 ff e9 97 e5 46 b0 9c 8c +f8 22 52 b3 3f 74 5f ee d4 13 32 06 51 8e 2b 88 +03 19 dc df 91 06 71 8a fb 01 6c 51 4b 38 05 32 +65 bc 98 79 10 0e 47 b0 3e ba 03 68 f0 9e 29 23 +ac 6f 40 a0 4b 75 05 4c d5 05 bb c8 96 5d 64 9a +1b ae 7b b6 64 3c b7 41 95 e9 1c 51 f4 18 3d b2 +d7 38 ce 60 35 50 d6 34 e6 dd 4f 27 f4 da ac 61 +56 cf a7 e2 46 8b 5d 6a eb 78 29 09 + +# Signature: +00 c2 e0 74 df bc d0 e7 3a c0 02 1a eb 99 33 10 +6b 20 1b 93 c1 7a 7b f9 33 56 d2 91 fb 4a ae b3 +d1 31 63 00 a8 de 7b 07 e3 d7 79 bc c2 99 e5 2b +6c b0 30 88 01 6d ae b8 41 38 2e b3 43 5f 2e 03 +eb f2 2d c0 86 fb 20 eb e5 3a c5 45 90 24 97 63 +a2 65 5a a7 eb 0e 7d 38 64 93 6b 34 00 6a 6c 4f +a0 2d 9c a1 04 ad ad a6 aa 01 b9 77 b6 de f2 75 +06 08 a7 8f 3e d8 3a d7 12 a7 a1 b0 fb de 7c 7c +8d + +# PKCS#1 v1.5 Signature Example 7.7 + +# ----------------- + +# Message to be signed: +83 a4 8b ff 88 6d 1d 68 f2 92 0a 0e cf f2 98 32 +1a 96 f5 ca dc df d8 be 16 b5 0d 34 d6 7d 94 cd +b1 a1 bf a0 ea e2 46 99 b6 63 c7 ba 3a 08 a3 90 +f7 22 58 84 85 67 94 d1 80 c5 46 ca c0 6e 41 18 + +# Signature: +01 2e 81 bd 38 63 50 65 bf 65 54 33 6b 00 d1 06 +18 33 05 53 e0 e8 08 78 aa d3 55 f0 0d 59 40 d8 +ba 45 01 c5 c4 9f 10 16 d5 f0 e6 a7 3a 4d 9f 87 +40 d2 cf c2 5e a2 48 df 3f 7b 1a e8 fc d2 6b d5 +62 e0 f6 eb 77 7f 46 d7 57 30 69 db 89 07 c0 21 +b6 45 d3 b2 40 58 47 51 99 a9 1b 55 72 d8 ac 87 +f8 3e e6 af 5c f9 e1 71 a8 58 f6 0d 2b 81 40 f5 +2d ae d6 84 42 22 8b 4f ff d8 de 40 07 8d 3d e8 +cb + +# PKCS#1 v1.5 Signature Example 7.8 + +# ----------------- + +# Message to be signed: +18 + +# Signature: +00 f2 c2 99 02 4a b7 bd 25 2c 69 46 be a1 0d c0 +53 97 38 98 bd 5f 0e 3c 94 60 e6 fe 09 d7 d1 91 +e7 1b f7 9d 43 6c aa 84 e9 86 be 3f c0 98 19 c0 +80 e5 6a 08 5c f4 24 41 4a f3 fc 70 07 cf 1a c3 +6f 1c f8 63 57 80 b5 56 8d 73 4a d6 d8 1a 2b a8 +eb 18 8b 29 46 69 d8 71 ca 40 e6 08 f0 ed 33 d5 +69 0c c6 15 70 c5 b8 47 eb db dc dc 4f a7 8f 42 +9e fc e1 3c 67 47 e5 4d 6f 26 1b 04 55 d6 dd 65 +c2 + +# PKCS#1 v1.5 Signature Example 7.9 + +# ----------------- + +# Message to be signed: +04 a6 e2 4b 93 c2 e5 f6 b4 bb e0 5f 5f b0 af a0 +42 d2 04 fe 33 78 d3 65 c2 f2 88 b6 a8 da d7 ef +e4 5d 15 3e ef 40 ca cc + +# Signature: +00 ec c8 95 fb d9 47 e2 df c4 7c 03 ba 2e 99 3d +1a 14 3a 7a 6a d6 3a 91 6e d5 44 83 ce 26 38 9f +89 d5 80 f4 ed bd d0 b3 7e 08 ca aa 5a 0c 1e 52 +6e 1e 9a 1a 8c 0d c9 cf 50 ed 77 de 26 76 46 0d +28 8d ce 56 5f 12 8a 26 6e a2 9b 4e cc 32 9a 94 +cc 25 23 96 dc 50 d5 c0 a1 3d 80 93 81 fa d8 8a +07 89 ad 4f 56 aa 77 e5 44 ec 25 70 af 99 18 b7 +f7 41 b4 86 ca 50 b3 38 4a d1 12 40 60 59 16 85 +a1 + +# PKCS#1 v1.5 Signature Example 7.10 + +# ----------------- + +# Message to be signed: +99 65 bd a5 5c bf 0e fe d8 d6 55 3b 40 27 f2 d8 +62 08 a6 e6 b4 89 c1 76 12 80 92 d6 29 e4 9d 16 +9f 16 fe 51 c4 c0 8a 64 94 b5 00 73 62 20 91 a3 +82 2e a5 7c 32 8b d9 b6 9d 24 65 a2 12 2a f1 78 +bf 6b 1b e3 07 ee 4c 31 47 9f fd 9f 4d 11 f3 3e +a2 0b 7a ec e8 12 ca b4 ee dd 46 99 31 51 d5 68 +ff 64 a1 67 04 a5 5d 95 0a b7 79 1a a2 3b 26 a0 +a8 af 88 0f 6f 80 56 bd d2 06 83 8b 44 c6 07 b6 +61 b4 f1 dc 36 21 06 5f de d3 db 6f 9e 3f 2d c8 +f4 00 ef e3 c2 af a6 c0 27 99 40 57 6b b0 5e 39 +80 4b d3 50 5f 4b d2 82 52 91 8b 28 e7 4e 05 8f +24 f2 7e f0 db 3d 0d cf 9e b2 9d 41 ff c1 10 07 +ce 86 b9 82 e8 9c 03 75 bd 99 76 a5 af 13 1a 61 +4d 28 08 ba 25 07 9d 97 7f 0b 23 97 96 ba 6b 1b +cd 5e 85 5d 96 + +# Signature: +01 56 62 e3 0e 79 0e 37 86 83 81 b4 f6 77 a2 ae +d6 b2 ac c5 64 49 17 31 82 49 10 ed 80 ad c4 77 +15 9c 88 61 8c c7 d0 be b0 49 b1 aa e7 4b 17 21 +e9 0b a7 f7 b0 ea 26 bf 33 ad 04 f8 6f f3 14 38 +97 bf 0d 4e b4 5e b7 de b5 44 11 ba 96 80 aa b1 +3a db fc f1 8a f4 6b 87 fc b1 46 1c 26 20 6a 95 +3b c3 cd bb 31 e2 96 ea 09 02 4b c5 c7 b6 2d e6 +c6 9c 14 bf cf eb 56 39 1a 9e f5 8c d8 05 eb 63 +1f + +# PKCS#1 v1.5 Signature Example 7.11 + +# ----------------- + +# Message to be signed: +71 c7 b1 8b 4a a8 ea 53 89 ad 78 49 23 28 65 be +2a 93 e3 47 a1 68 d2 5c 6c 6e a2 43 9c 1c c8 0b +b0 b7 22 3b e9 c8 93 71 22 84 5b b0 a3 9c 02 5c +43 75 9d ef e6 e4 e8 eb 3b aa b4 f1 eb dc a2 c8 +ad 12 a4 65 a3 0f 8a 65 25 b1 20 ef 6a ae c9 bd +db 45 cd 42 c0 15 0c 40 7b 04 8e df 65 19 94 92 +f2 07 ca 01 aa a5 54 3a f3 8e e9 8d 53 bd 10 d8 +ee bc 3b 64 97 7e 75 75 1d 74 50 dd b1 c0 e1 fc +24 da 17 18 81 1f be 9b 0a bf c3 ca 31 e6 99 5f +c7 34 90 73 e2 17 b3 7e 23 c5 f1 7a 8b 7a 3f 00 +48 6a 37 02 b9 51 0d 6f 05 1b 27 61 71 6e 32 c6 +2b b5 93 9b 2f b1 1a cb 1c 83 + +# Signature: +01 3a b6 3a b1 83 35 3a 23 5f b8 93 ab 4c 35 d6 +40 9c 21 84 9d cf cd a3 bf da 14 29 fe e7 42 a7 +d8 16 0f d3 c8 3b 38 53 a3 33 f9 51 53 9b b5 77 +1f 4d 0f e1 3a de b6 4e 40 30 b9 2e 8b 08 13 eb +52 b1 aa 33 bd 94 c5 b8 bc 1b bc cd f6 c1 df 0b +a6 70 71 7c 0c f6 fd 48 5b e2 fe 9e 16 81 3b e8 +cd d5 80 e6 10 86 67 5e 31 83 1c 92 4a 41 d4 67 +1a 95 d8 35 e3 fc a4 95 e8 86 58 d1 e5 70 e6 28 +c7 + +# PKCS#1 v1.5 Signature Example 7.12 + +# ----------------- + +# Message to be signed: +0b eb 19 b5 62 92 8c 27 1b b7 06 18 9e 43 cf a5 +7b e7 6b 2f 7a 83 e0 2a a2 cc b0 37 c0 f4 f7 f7 +31 62 d6 c2 6f 70 de 97 18 21 e7 b9 66 5c b9 31 +bb 0e ac 82 0b f8 59 98 4d b4 be ef ef 4a b8 8e +91 63 1c 0c d3 1d b7 f9 35 8a 5a a1 df f2 40 6b +45 f9 bd cb ef 20 d5 5c 28 2b ae 5c fb 61 06 02 +3b 56 33 c0 51 af 17 e7 29 bb 07 c9 af 6d d2 + +# Signature: +00 d6 3d a4 d5 d3 e2 28 4a 19 2a 6a 9d a3 f1 a7 +d3 fc c1 64 b9 fc 3d fd 74 52 b0 2f ed 6e f1 be +5a d2 a7 69 ec 9c 36 05 9b 71 91 1c cf 7a b7 1c +e3 09 87 ec 47 bb f5 5e 6d 46 30 d6 23 42 b3 15 +50 48 ee 0b f4 3d 24 fe 69 ab da c1 2f 79 4b 67 +98 bd 1a 7c b4 89 a6 4c e0 82 25 4c 3d 92 f4 75 +56 6b 56 40 0d 96 20 cd fd 63 fc 17 c1 93 c4 25 +d7 ed e9 41 f7 6d a1 e3 45 af 0e 2a 8b 88 44 c7 +40 + +# PKCS#1 v1.5 Signature Example 7.13 + +# ----------------- + +# Message to be signed: +02 87 ab e2 67 0a 45 f8 77 90 48 f5 + +# Signature: +00 42 f4 14 78 2d f6 5d 93 47 bf 1c ad 53 48 53 +74 6c c0 b8 53 c1 c5 26 f9 17 14 45 fc fa a4 99 +1a 70 f5 a8 44 5b cf 41 14 f0 7f c8 35 4c 84 a9 +3b 94 37 33 d3 93 7a 59 88 3b 89 6c e6 5f db 16 +5b 1e 30 55 37 4c e2 42 e1 26 8c 16 41 cc 44 3b +b9 e7 da 7f 71 f3 e7 f6 31 3f 23 9e 62 00 e7 9a +1b e3 ea d6 c3 6e 94 1f 24 46 0b aa 57 df 63 9e +57 da b3 ef f9 e7 7b 87 af 35 5b 83 da e7 7c be +06 + +# PKCS#1 v1.5 Signature Example 7.14 + +# ----------------- + +# Message to be signed: +3f 49 54 2c 0e 9f 50 93 2c 0d 45 3d c9 53 20 af +21 dd 2b d1 72 9c 29 f4 f0 8c 70 94 4c 2c c7 5d +e9 16 6b 4f d2 30 aa 93 70 2c 5f 2c 3d 9c 29 9a +35 91 02 57 00 33 54 0e b8 28 ca d7 5a 57 76 d2 +e8 cb 45 61 41 a6 fa 97 bc 4e 6e 62 d3 df 08 29 +82 a4 d9 8c 2d e4 41 e5 9e 93 12 + +# Signature: +01 5c 39 93 ce eb d8 db a4 5a 36 8d d4 05 af 8a +53 b9 3e 82 70 19 f9 94 e4 ed 78 2c 39 11 b9 b5 +80 d5 42 24 26 9b 79 97 f1 74 96 30 e5 2f 22 1f +af ab 96 41 c7 81 e7 04 4d 32 56 e2 e4 4e 14 37 +91 72 32 69 45 18 ba 9e 71 38 da 47 fe 53 43 29 +b8 c9 68 9e 27 85 c0 2b 60 3d d1 60 d3 73 36 a2 +b0 5b e0 47 82 65 9a c0 e9 67 1f e9 32 ea 80 91 +d6 13 18 b2 b2 01 bd a7 9a f6 c0 c4 44 69 38 e3 +f6 + +# PKCS#1 v1.5 Signature Example 7.15 + +# ----------------- + +# Message to be signed: +d0 db c9 6c f9 bf b1 e3 cd 6d e2 ea a0 8d 6d 79 +5b ed 81 87 ce b0 85 65 80 e4 b1 42 b9 ae 60 a0 +98 cd 42 98 4e 8d bf 1d 05 a0 c0 ab 83 51 54 8f +0a 13 64 6f 33 39 0b 2b b0 c8 64 b3 97 cf 13 37 +1f 8b 2f 67 5a 82 e4 6b f1 6c 4a fc 60 5e e3 e5 +a1 46 9c ac 51 fa 73 4b 44 65 d4 c1 3d 5b 2d d1 +2e ed a5 4e 7d 08 1c d9 e3 ea af 9e 57 db 42 20 +20 a0 b5 a5 ec 28 ca 43 97 7a 5d 67 6f fa b6 2f +78 10 71 93 59 41 59 ce bf bd 86 26 98 19 a0 f3 +41 a0 f4 12 84 dd 0a 73 ca 80 14 d2 e0 b8 01 79 +c6 38 0b 40 3a fb b1 1b 42 db 34 9b af d7 57 0f +be cb d1 4b d0 c2 1a d6 41 68 7a 6a c3 29 25 f7 +03 1a 24 a6 56 8a b9 e2 87 eb 80 75 41 10 df ba +68 8a 59 63 25 bc ac 4a 39 ce 8b 84 a4 + +# Signature: +00 8c c8 2d 64 55 9d e0 04 0f 55 41 19 9a ef f3 +99 9f e2 f0 86 f1 57 ff 51 f2 22 0d b3 45 51 9a +a1 14 b0 17 62 e7 0b c9 65 83 bb 38 b2 2b 3f 87 +be ab 32 e2 3a 3d eb db 8a 59 54 29 ff 12 fa d4 +95 d7 4e 22 0e 4f 7d ca 22 27 28 43 89 9e 81 04 +c6 9a 59 64 2f 6f a8 25 89 0f e8 13 2a 0f 79 94 +02 53 e5 00 7f b1 17 7a 5b f4 18 06 7e dd c8 d3 +2c 5e 59 35 bf 33 8f 1c 69 0e fc 80 11 dc 8c 84 +2e + +# PKCS#1 v1.5 Signature Example 7.16 + +# ----------------- + +# Message to be signed: +7d f0 23 6e 87 1a 71 c3 17 90 eb 5f 01 1c 91 1c +27 c6 03 73 b8 dc 9e bb 13 ac 85 ac cb 3b cb d3 +b4 74 f9 78 86 2d d8 42 02 ab 20 b3 34 73 94 25 +e1 b7 9e 0b b8 b4 bc 47 dc 71 53 f5 7a da 04 12 +44 7b f5 a5 e6 67 34 19 ba ad 65 3e 5f 5c 39 e2 +ef 7c fe 7e f4 77 8a b9 98 ca f9 7c e1 6c 58 33 +27 72 dd df 82 6f 1e ec 1a f3 db 80 e3 13 75 d6 +68 0a a2 54 b4 ab 6e f9 a3 ec 0e 04 03 e4 b5 83 +d3 71 dd d9 6d d5 7b 2c 61 a6 e4 01 25 1a 1a 63 +0d 1d dc dd 84 d9 0d 82 fa f5 a0 18 d2 a8 8e 26 +58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59 1c d6 58 +7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59 22 02 8b +c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa 70 ba 36 +72 cd de 4c fe 49 70 cc 79 04 60 1b 27 88 72 bf +51 32 1c 4a 97 2f + +# Signature: +01 45 5e 3b b2 9c bc a8 83 9b 9f 54 4d 51 47 2e +bc fd 25 c2 92 27 c4 65 5d 5f 7e bb d8 3c 48 e7 +64 3e 7b 59 4d 6f 7c d5 f6 bf 9a 40 b0 5c 4a 05 +cb ee 1f d6 59 d3 ce de 3e 7c ad 61 e6 fd f8 f0 +e4 fd ef 08 12 a8 53 90 8f 0f 99 ca 7e 38 8e bc +19 e8 74 76 5b 11 64 0f 1e e1 e9 8f 54 95 3d e6 +17 6f 15 82 03 70 17 c8 38 60 9a 57 a1 2a cb af +a6 a5 65 47 f5 7d 62 db e8 76 69 ed c0 fe 3b aa +da + +# PKCS#1 v1.5 Signature Example 7.17 + +# ----------------- + +# Message to be signed: +12 88 c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe +b3 2f 0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c +f9 79 f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 +dd 76 2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 +ca 70 9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 +85 66 ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 +15 94 20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 +11 a2 c7 50 f5 c0 a4 25 31 3d f8 d7 56 4b d2 43 +4d 31 15 23 d5 25 7e ed 80 6a c8 c9 c6 af 04 ac + +# Signature: +00 6b eb b9 6f 0e 28 2f 1b 4d 03 e6 c5 65 05 b9 +37 78 da 9f 49 36 50 e8 aa eb 65 cf e6 28 50 04 +2f 75 ab e6 e6 ea fe b9 a7 0a bd 21 eb 5d ba 73 +cb b8 7c 12 98 0a ac df 16 71 6b 19 98 c9 49 9c +e4 39 c5 4a ab 4d 19 ce 72 7b 78 75 a4 1a 3d 30 +81 4e 50 8d aa 26 eb 70 aa bb d0 dc ae cc 4d 4b +51 69 80 71 51 1e b3 1b 21 0e 66 dc bc 7f c0 b8 +c6 23 14 da ea 69 d4 7a e2 78 10 0d eb 51 40 92 +00 + +# PKCS#1 v1.5 Signature Example 7.18 + +# ----------------- + +# Message to be signed: +54 13 99 3c 26 58 bc 1d 98 85 + +# Signature: +00 bb eb 2c a0 bd 64 cb 89 60 37 5b 08 a9 48 0e +69 c0 9f d3 82 de a2 f9 40 89 b1 53 3a 08 51 fa +0c bd 0e ad ef ca 8c 70 b7 70 79 7a d0 89 e8 40 +d2 fe 1a 8f b8 54 9f 32 90 58 3b bb 81 d3 ee 2b +1c 48 f1 ea 75 1b f3 2f 95 90 be 3a fd b7 74 5e +16 6e 0b 32 2c 08 31 24 e6 45 83 94 82 d0 81 26 +22 d3 1a b1 87 7a 9b b4 1b 8d aa d8 68 f3 0e 75 +07 83 2a c3 41 01 12 13 3a a1 7b 2d 47 6d 47 6d +89 + +# PKCS#1 v1.5 Signature Example 7.19 + +# ----------------- + +# Message to be signed: +9c 84 c1 48 6b c1 2b 3f a6 c5 98 71 b6 82 7c 8c +e2 53 ca 5f ef a8 a8 c6 90 bf 32 6e 8e 37 cd b9 +6d 90 a8 2e ba b6 9f 86 35 0e 18 22 e8 bd 53 6a +2e b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 +ef 8c 5c 0e 91 dd 0a fa d4 2c cd 4f c6 06 54 a5 +50 02 d2 28 f5 2a 4a 5f e0 3b 8b bb 08 ca 82 da +ca 55 8b 44 db e1 26 6e 50 c0 e7 45 a3 6d 9d 29 +04 e3 40 8a bc d1 fd 56 99 94 06 3f 4a 75 cc 72 +f2 fe e2 a0 cd 89 3a 43 af 1c 5b 8b 48 7d f0 a7 +16 10 02 4e 4f 6d df 9f 28 ad 08 13 c1 aa b9 1b +cb 3c 90 64 d5 ff 74 2d ef fe a6 57 09 41 39 36 +9e 5e a6 f4 a9 63 19 a5 cc 82 24 14 5b 54 50 62 +75 8f ef d1 fe 34 09 ae 16 92 59 c6 cd fd 6b 5f +29 58 e3 14 fa ec be 69 d2 ca ce 58 ee 55 17 9a +b9 b3 e6 d1 ec c1 4a 55 + +# Signature: +00 e6 be 96 e1 8d ce bf 83 88 ba 82 ec 6f 27 10 +5b c2 78 71 59 5e 01 70 5a 2b 97 a1 f4 d7 88 38 +35 2b 0e 7c 0a 2c 62 7a 6f f3 7d b1 69 a9 a4 64 +8a d2 7a f0 65 33 a4 f0 41 d4 c8 20 ab f4 fb 52 +64 64 08 14 34 df 36 78 85 03 c6 5a f7 62 aa 21 +9f b7 6a 91 cb b4 0e 14 92 a9 cb 77 36 9b b4 cc +a1 93 4e 38 53 de 6c 86 a5 dc 11 48 ed ee b3 b0 +03 04 14 fe 30 83 ad 72 fe 29 5c 29 b5 ea 9b 66 +60 + +# PKCS#1 v1.5 Signature Example 7.20 + +# ----------------- + +# Message to be signed: +94 0c da b4 a3 e9 20 09 cc d4 2e 1e 94 7b 13 14 +e3 22 38 a2 de ce 7d 23 a8 9b 5b 30 c7 51 fd 0a +4a 43 0d 2c 54 85 94 9a 2b 00 7e 80 97 8b bb 19 +2c 35 4e b7 da 9a ed fc 74 db f5 f7 1d fd 43 b4 +6c 93 db 82 62 9b da e2 bd 0a 12 b8 82 ea 04 c3 +b4 65 f5 cf 93 02 3f 01 05 96 26 db be 99 f2 6b +b1 be 94 9d dd d1 6d c7 f3 de bb 19 a1 94 62 7f +0b 22 44 34 df 7d 87 00 e9 e9 8b 06 e3 60 c1 2f +db e3 d1 9f 51 c9 68 4e b9 08 9e cb b0 a2 f0 45 +03 99 d3 f5 9e ac 72 94 08 5d 04 4f 53 93 c6 ce +73 74 23 d8 b8 + +# Signature: +00 80 e2 c3 4f d4 ab 4d 1d 70 1e a3 f0 85 76 3a +ca ff c9 fd 3e d9 18 d0 4b ff ee 19 31 62 48 98 +c7 8f 89 41 bd 2a 59 ce b5 b8 40 f0 11 45 16 ce +41 1f ae 75 2b 1b 8a 22 1f fc a7 a6 87 66 c6 97 +c5 0a 3d 88 d8 d0 2f fc 12 41 d8 4b b7 a7 22 7f +3d 05 14 9e 15 11 12 77 a1 36 a5 b8 dd 96 dd 4b +22 5c 5f 49 cd f6 07 1d bf 71 93 5c 7a 6f 1e 2e +9a f3 02 1c 0d 58 a9 b8 1c 9b de 61 fa 47 2c 07 +a6 + +# ============================================= + +# Example 8: A 1026-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +03 33 12 64 88 f7 a2 91 51 32 e3 0d 5e 97 f6 ed +7b bb 67 b6 19 85 00 8e ae a2 a5 da fb 96 a4 48 +ab 75 ce 3d 6e 68 a6 26 5e 7c 24 56 84 99 93 24 +c8 1e 0b a6 38 98 63 fe b4 88 b3 f2 55 d0 d6 19 +c1 90 40 b7 4c 18 9f 0c 9a f4 b0 d5 a5 5a 54 4c +09 0c d6 15 2c 90 a6 f2 55 0d 7d 2a 6b 6d 34 7d +5b 1b 9d fb 1d e4 40 3c 79 66 23 d7 03 bf 9d b4 +43 bf 67 02 68 3b 8d 2a 9c 61 e9 36 8a c4 25 a5 +81 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +03 33 12 64 88 f7 a2 91 51 32 e3 0d 5e 97 f6 ed +7b bb 67 b6 19 85 00 8e ae a2 a5 da fb 96 a4 48 +ab 75 ce 3d 6e 68 a6 26 5e 7c 24 56 84 99 93 24 +c8 1e 0b a6 38 98 63 fe b4 88 b3 f2 55 d0 d6 19 +c1 90 40 b7 4c 18 9f 0c 9a f4 b0 d5 a5 5a 54 4c +09 0c d6 15 2c 90 a6 f2 55 0d 7d 2a 6b 6d 34 7d +5b 1b 9d fb 1d e4 40 3c 79 66 23 d7 03 bf 9d b4 +43 bf 67 02 68 3b 8d 2a 9c 61 e9 36 8a c4 25 a5 +81 + +# Public exponent: +01 00 01 + +# Exponent: +01 4a 2b 15 df a8 83 1d b4 ef a0 5b 19 50 84 b7 +42 73 4e e1 36 f4 48 3f 3b e2 50 9d 2f 61 90 23 +c3 0a 1f f2 df 78 cb d1 17 b1 4f 2c 99 13 17 1f +72 93 b9 fa 6d 41 f0 bd 11 a5 31 74 74 67 54 86 +d7 f0 ae c0 a7 78 ba 92 0e 81 f5 64 d1 59 30 cd +de e7 e2 b0 6a d8 ad b6 12 75 1f 4e 38 4d 6f 3f +a0 a6 63 9f d6 2e df 86 f5 2c 9f e0 77 62 91 83 +21 83 d3 59 b7 34 32 60 c9 4e 12 5f 4a b8 bf 43 +69 + +# Prime 1: +01 d6 e7 bd 8e 39 5b be f2 10 46 49 c0 12 78 cc +1c 51 c9 68 7d ef b4 59 1f 03 b6 78 52 a4 bc b5 +30 75 0c f9 bf ca d0 72 8c 53 99 d8 70 35 01 06 +cb a3 ec 41 6a 31 e4 2d 0b 59 75 10 ff 1c 9d 53 +bb + +# Prime 2: +01 bd 46 6f 43 a4 d4 61 3e 42 64 f0 1b 2d ac 2e +5a a4 20 43 f8 fb 5f 69 fa 87 1d 14 fb 27 3e 76 +7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0 c7 e0 f6 be +25 61 92 3a 77 21 1d 66 a6 e2 db b4 3c 36 63 51 +f3 + +# Prime exponent 1: +fb 66 85 00 65 06 e2 0e 01 3a 45 2d 51 af 43 e8 +ea 91 08 44 13 b0 c8 d3 91 fb dc 88 e2 82 0c 89 +6e 34 1b 31 95 69 6b 7e 17 33 cf 25 38 66 ef e5 +d0 01 d5 7a 88 60 34 dc 16 4a 35 64 bd 36 10 f9 + +# Prime exponent 2: +be 4e 9e 3b 40 f5 6c 62 59 aa 1e 5c df 56 59 b1 +6f b8 42 94 e5 8a d0 16 bd 2c 96 cd 08 e6 cf 68 +54 a1 1c b8 0a d4 be 3e 05 7a aa cf 02 bd 32 63 +73 a2 35 ce b8 9e 82 43 0d 6e 6d 47 d6 ce f8 35 + +# Coefficient: +c0 23 5c 89 73 cf bf 30 bf 1d d3 c8 39 f0 2c 94 +c6 9d c5 34 cb fc 98 88 05 d6 fc 46 2a db d3 77 +d1 75 b9 a9 64 60 18 d7 fa b7 5c 1d 1f 7d 61 b7 +7f a7 95 59 b8 6f fa 9e c6 e2 11 33 fa 7f 1a 45 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 8.1 + +# ----------------- + +# Message to be signed: +9a 28 20 f3 b9 02 9a bc 18 65 eb 06 fe 61 b8 d3 +97 b6 55 72 d6 00 61 ca a7 4e 63 56 93 1e 25 6b +89 71 2d 18 66 84 b4 de 1e 14 c9 eb fe f1 6e 40 +d9 9d 10 94 39 6c 56 1c 88 31 77 e5 12 6b 9b e2 +d9 a9 68 03 27 d5 37 0c 6f 26 86 1f 58 20 c4 3d +a6 7a 3a d6 09 04 e2 15 ee 6f f9 34 b9 da 70 d7 +73 0c 87 34 ab fc ec de 89 7f dd 67 0a 01 46 58 +68 ad c9 3f 26 13 19 57 a5 0c 52 fb 77 7c db aa +30 89 2c 9e 12 36 11 64 ec 13 97 9d 43 04 81 18 +e4 44 5d b8 7b ee 58 dd 98 7b 34 25 d0 20 71 d8 +db ae 80 70 8b 03 9d bb 64 db d1 de 56 57 d9 fe +d0 c1 18 a5 41 + +# Signature: +03 22 d0 0f c1 d9 66 94 f3 6e ae d2 30 90 56 f3 +ea 1c 1c c2 2b 13 b6 5e 79 11 8d 20 2c 42 d1 61 +30 99 38 05 09 da 74 35 bb 57 92 16 fd 57 65 06 +68 42 e3 56 a6 41 6f c8 42 a2 4a 9e a1 bc 6a 90 +98 05 23 b4 28 e3 99 bb d6 fc dc 2c b7 71 da f0 +03 7a 2d e8 c7 64 9b d5 33 17 de 0e 37 c3 14 ba +b0 c4 37 bb d7 98 df b9 65 50 6c 34 8b 74 2f 13 +8e f1 d1 a2 03 e0 51 e3 4b dd 3a 30 e0 fc e1 ac +43 + +# PKCS#1 v1.5 Signature Example 8.2 + +# ----------------- + +# Message to be signed: +ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e +80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac +8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb +57 f9 b7 1b 6d 48 b2 b6 a5 7a 63 c8 4c ea 85 9d +65 c6 68 28 4b 08 d9 6b dc aa be 25 2d b0 e4 a9 +6c b1 ba c6 01 93 41 db 6f be fb 8d 10 6b 0e 90 +ed a6 bc c6 c6 26 2f 37 e7 ea 9c 7e 5d 22 6b d7 +df 85 ec 5e 71 ef + +# Signature: +02 68 44 09 39 99 6a e5 cb da fd bc a8 6a 7c 42 +8a 04 b5 78 fe 2d be 51 26 a8 2f af 2b ec ff 09 +9a c6 0c b8 1b 11 7f 1e bf 42 04 fe 43 70 54 8d +5d 2c 46 80 63 68 2d a8 7d c8 01 79 bb 3b ba 85 +a1 48 ae 2d e7 dc b4 94 f4 76 22 1d f8 21 9d 4a +ae 1e 45 af 65 de 33 4a 1a 6d c1 45 52 86 ae 09 +cf 26 72 58 85 e7 74 80 99 72 d7 81 98 05 ff f5 +a8 c8 9d 37 37 64 50 73 92 49 f5 7e b1 51 b7 1d +c0 + +# PKCS#1 v1.5 Signature Example 8.3 + +# ----------------- + +# Message to be signed: +07 df 58 6b 90 5b 23 b9 1a f1 3d a1 23 04 bf 83 +ec a8 a7 3e 87 1f f9 + +# Signature: +01 bf d9 15 ff 77 80 f1 4c cc 55 bd 03 06 b3 ae +da 5b 5b 59 55 a8 26 d4 52 6b 0b c7 66 15 4f a8 +da 59 56 05 78 cc d4 88 2f e9 70 92 fb c7 36 fd +a7 3c ee fd 10 38 94 06 3e 93 e2 2a 7b 5c 44 f7 +a8 5e 3b db 96 71 9a 09 37 43 03 c9 1e d7 e2 27 +49 fe 3c 4d 6b 96 69 9d 50 7c 50 ad cf bd fc 13 +1d 6b 5f 2c f1 83 0e 31 ea be 39 ae b5 17 96 9c +94 a8 1c fe fe 67 31 aa 2c df fe 28 c8 af 71 40 +f4 + +# PKCS#1 v1.5 Signature Example 8.4 + +# ----------------- + +# Message to be signed: +50 0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 +75 5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 +c4 e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b +82 db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 +2a 62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 +45 1a c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e +b0 e0 1c b5 41 ec 50 f1 03 6e 00 8e 71 e9 64 da +dc 92 19 ed + +# Signature: +00 7a e0 cf d7 f4 c6 ad 1f f8 4b 4a 60 6b a1 c4 +79 8c 2e 49 9b 04 5b 56 7d 32 63 4f d9 55 f2 68 +26 0a b6 59 bf 5b e9 9e 08 26 eb 38 70 e8 f6 2f +5a 3c e7 58 e6 d1 56 c3 29 9b 43 1c d9 df c6 58 +37 ee 94 22 0d 95 23 51 14 87 99 be 9f ca f9 be +26 4d ae be ba 2b e8 66 05 20 1e f9 a0 d9 8f 58 +ec 63 8a bf c4 f2 78 48 f5 d4 79 d3 34 ac c2 a9 +7f dd 2d 32 7e c4 c7 dd c5 a8 ab d5 66 de 35 d1 +4f + +# PKCS#1 v1.5 Signature Example 8.5 + +# ----------------- + +# Message to be signed: +6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98 01 65 +23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b b7 c7 +bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9 16 ef +a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52 65 +5f 5d fb a2 25 f1 08 95 a8 77 16 c1 37 45 0b b9 +51 9d fa a1 f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 +98 00 85 b5 55 ae ba b7 62 64 ae 2a 3a b9 3c 2d +12 98 11 91 dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 +40 f0 07 52 c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 +b6 88 f2 03 23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 +dc 21 17 c0 74 34 fc f9 72 e0 58 cf 8c 41 ca 4b +4f f5 54 f7 d5 06 8a d3 15 5f ce d0 f3 12 5b c0 +4f 91 93 37 8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d +30 ec ca 6e aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b +af 09 9d ef b8 af d7 ad 8b 15 23 70 36 46 + +# Signature: +01 92 1f 22 f4 71 a0 8a f8 19 a9 52 e1 83 68 ce +15 f9 b0 64 eb 1d 00 b1 28 99 78 02 44 fe 8c 44 +24 b2 1f 64 35 0b 92 26 fe 95 ff 54 f1 14 39 83 +9b fb 54 f9 39 c9 14 95 e4 f0 27 90 18 97 27 3c +fa 29 5a 57 15 1f 4e 91 1d c1 02 a7 7d 95 8b 62 +27 24 c0 fd 3a 34 b3 b7 be fb 8b 8c d0 66 6e 81 +5d 0c 07 f2 ec b7 c4 dd 2f 42 b7 f4 09 13 12 e3 +d7 b2 df 26 78 87 e0 ac a7 0b 54 1c 4c 1e ea 16 +b5 + +# PKCS#1 v1.5 Signature Example 8.6 + +# ----------------- + +# Message to be signed: +93 29 a5 80 90 de 8b e5 7c 42 + +# Signature: +01 5c e2 4a 6f 2b 37 3a 19 99 7b b2 0c 18 ac 65 +9f 1e dc 0f 25 c9 e5 bf 76 d5 69 99 65 20 c2 80 +ef dc f1 5e 2d 63 ca af f6 c7 7a e0 38 97 03 7a +06 15 f9 83 8c 52 10 4e 97 25 18 e2 90 fa c3 8f +63 24 75 30 b4 cf 61 c6 ec e3 42 9b 53 07 81 cf +34 96 4f 32 ae 50 f1 09 34 63 83 86 d3 b4 df 76 +1c 59 7d 4a a7 fe ca 26 6c 27 f8 ce 66 ad e1 be +26 59 ce 14 2b a5 f9 35 88 3c 7e 8c 9b 89 57 ab +f2 + +# PKCS#1 v1.5 Signature Example 8.7 + +# ----------------- + +# Message to be signed: +6a ce 0f 1e 1d c6 3e 39 4a 06 1f 52 2a 54 2f be +71 20 25 4e 36 e9 f6 5d 19 57 c9 56 28 78 2c b0 +36 8f 3c 13 da d6 56 71 79 c1 ea 24 fe 83 5a 26 +63 85 e4 68 83 17 b8 2b 0c 3f e6 3c f2 d5 2f 04 +ae 8a 38 a5 75 59 bb 95 d9 eb d5 fe 8a 9a fe 14 +79 90 9e b9 9e 0d 3e f3 f3 12 e0 a4 ab b7 66 c7 +e2 13 1a 5f fb 48 31 83 fb b4 22 34 d3 2e 58 1f +59 50 65 c4 89 82 61 ec d0 ae 57 2c 22 1c 25 8d +e9 50 a4 08 01 ef 79 6d 4d d0 04 06 45 fc 53 4d +8e 78 58 23 48 38 ed 12 c6 87 40 c1 4e 37 16 13 +f0 04 61 76 bb b0 f4 3d 99 75 19 c4 0c 67 14 96 +ff 35 0a 3f df 42 9c c2 2f 46 4f 43 5f 6b 29 e7 +e1 c3 0e bd 50 59 27 d4 a0 96 58 7f c3 8d 3d 64 +94 39 1e + +# Signature: +02 73 ba 2c 50 2b 3f 29 84 c5 48 d9 f7 d6 c9 b3 +d7 fd 46 08 78 c8 4d 6b e3 3b 28 10 6e 15 fc 22 +17 ef f7 41 cd c2 66 83 4b ea a8 6d a4 05 f3 ca +e6 06 cc 61 f2 54 7b b9 22 92 03 45 fe 8f bb 5e +7b 6a bf 91 ea e8 c4 26 60 64 50 25 cc 7f c0 7a +53 4b 76 d3 78 75 e3 f4 0d 52 70 c1 0e f4 6c 7f +e4 5a fa bc ff ae 2a 9c 94 11 bd 04 d6 1d 4c 0e +5f fc 02 2c b3 6a 64 b7 c3 a8 c8 9b fd e4 36 ba +fd + +# PKCS#1 v1.5 Signature Example 8.8 + +# ----------------- + +# Message to be signed: +fd cc 0f 1e 5d cb e5 01 6a 6b 0f 8c 28 f5 b3 31 +ff 58 28 37 13 8d bf 62 ef 7f f6 1b c1 a3 53 96 +c9 2e 3d 54 8d 39 9e 35 0a 3c 6b c2 fd b5 da 94 +b9 86 a4 ce 6d ee 10 4e 9f 27 4b 15 25 58 bf a7 +22 cc fd da 3b 26 b9 f8 e5 15 25 f3 81 03 4c 51 +fd c9 f7 91 2a c9 27 d1 a7 08 cc 2d bb cd 7b a6 +c0 31 b0 11 cb a8 e2 df 8f c9 b8 83 64 ee 96 5f +24 27 0e 43 48 62 32 53 cb 9e 59 d6 f7 94 09 09 +94 a7 a4 c9 30 02 70 b5 7f 24 39 eb bb a4 65 84 +67 af db 7f e8 6b 4f 1a ad 1d 3d 3b 2f + +# Signature: +00 a7 c4 50 b3 0b 2e cb 19 bb 70 9a 92 31 cb fa +9f 0d 61 69 7a 26 b9 0a 96 d9 1c 24 c4 da 70 d7 +b0 0b 59 23 c8 e1 2d 41 09 4b 70 5d 50 c7 78 bb +da ce c6 60 d5 c1 5d ff d3 a2 47 8f d9 33 70 80 +dc a1 6b 9c 13 e6 23 3b 82 92 b2 fd cc 29 e9 bf +3b 21 a7 18 78 f3 4e f5 eb 7c d5 0a d4 12 03 72 +5a 0f 1c 66 3f 73 42 ec 7c 3d f3 d5 aa 51 d0 58 +df cc ce 5f e6 9d 36 3b 42 84 32 08 79 e8 6d 58 +b5 + +# PKCS#1 v1.5 Signature Example 8.9 + +# ----------------- + +# Message to be signed: +2d 1f cd 17 66 f7 d4 5f 29 59 4f 9d 4f 74 39 41 +ae 91 2a 97 91 1f fc 3d 65 dc d9 65 60 10 77 3b +b0 22 4b a6 df 11 1b 1c 13 68 38 4f 24 92 fc 4f +a7 28 0c 06 65 14 ae 84 f7 61 45 63 d9 05 2c a9 +4e f4 46 a3 1b 46 3b d6 c2 50 56 80 50 88 c1 d3 +1a ba ff 52 15 f7 a8 f8 9e 7b 64 f2 + +# Signature: +02 c0 e0 71 e8 36 90 dc 14 d9 a3 7d 61 e0 af c2 +7d f9 78 03 9d a6 01 ca 2c ec 1d ec 8f 0d 17 d2 +ff c4 50 e6 78 38 0a 02 5a 41 c7 46 11 8f 58 36 +42 52 a1 22 53 9e cc bb b4 ab 3d 8d 37 7b db b9 +11 c5 8a 4c b9 46 2f 36 dc 38 92 48 50 1b d0 8f +48 e3 53 3b 82 59 1a 2a 20 cf 62 df 5f 5a 1f 84 +ea 30 0c b3 94 57 13 71 41 ad 8c d1 d1 85 ab b1 +7b a5 d0 3b e3 48 c0 67 97 b0 95 58 f0 33 1c 24 +b9 + +# PKCS#1 v1.5 Signature Example 8.10 + +# ----------------- + +# Message to be signed: +4f 46 9a b7 9c b8 93 a5 3c 0e e3 81 5a 8b c0 87 +eb 74 ea 36 61 5b dd c3 33 de e0 5f c7 26 65 aa +6d 0b d5 9e 47 22 98 29 83 4b 1f 91 c9 cd 81 ce +28 d6 8f 14 82 5a 34 5f 3a 4f 38 a0 1b 2d ae 59 +10 07 64 aa b9 90 a8 50 b1 1c 13 d5 df e4 19 f1 +d9 20 d0 0c f1 3b f4 30 e4 ca 82 87 98 9b ee be +da 3e 5d 40 36 02 8c 8e f9 54 6e 35 01 50 d1 96 +f0 05 60 ba e1 47 22 99 e7 f4 29 1d 54 46 29 c4 +f6 52 e3 5c de 4f 80 3e 1b 3c a3 38 09 51 5e f2 +3d 25 4b 8e 65 20 2a 14 a4 11 b1 bc 31 5c 5f fa +ec b8 21 11 97 80 9d cb 5c ed 68 2c 09 f6 7e 41 +d1 60 2c + +# Signature: +01 71 29 64 ea 9a b9 70 29 5b 81 b0 fb d8 35 7e +54 b9 36 ee 87 72 d8 ae 9c 96 12 71 6f cc 2f cb +78 4c a9 ab ee eb b8 fc b6 89 82 16 1c c7 4e 40 +c7 c0 22 47 c0 d0 0e 03 bc 8e 1a 70 51 b8 7c 90 +dd 7d 3d fc 95 e0 b3 c8 8e 7a 0f 37 f3 0e 1b d5 +fe 8b 6e ee 46 5a 0b 34 cb 59 c6 4e bd b5 7d 6f +5f df f2 e7 0b b1 9c 60 d9 88 ea 95 6c dc dd 1b +e5 62 f2 6f b3 7c 34 da 52 a9 f9 11 b9 97 43 81 +2c + +# PKCS#1 v1.5 Signature Example 8.11 + +# ----------------- + +# Message to be signed: +52 bb 76 c9 ea 26 5d 6f ad 10 83 72 ff ab 25 03 +bb 20 d3 8d 37 df 19 92 54 a2 f6 de 0c 4f ca 7a +73 03 36 + +# Signature: +01 0c 55 34 23 60 22 60 15 8a 17 13 3b 5d 30 ef +e9 8e 9a eb 35 3b ab 33 71 e4 91 cd be bd 35 0a +0a 47 0b 9d bf d1 89 33 51 1f 0d 0e 36 94 a8 ac +4b f3 f5 b6 eb 9b f7 1c 23 d9 4c 2e 64 be b7 b7 +c7 22 52 ca 82 7b d0 c0 56 7b a8 a1 0a 6d 3b 7e +18 7b 0f d8 e9 e9 5d 4f e4 80 f2 50 dc 7f 03 42 +29 0e 9a 7d 32 70 3a 72 13 c6 52 13 ad ed 45 57 +54 78 1f 3d b7 3e 79 e3 d1 ba 6a f7 f6 90 fe 81 +73 + +# PKCS#1 v1.5 Signature Example 8.12 + +# ----------------- + +# Message to be signed: +5f 59 7a 19 cb f5 14 30 d3 c6 a2 47 a5 23 54 07 +38 6c ae d0 a2 94 f3 f4 1f 3f 37 82 50 d4 c5 a2 +c9 92 75 f9 55 44 cc c1 d7 7e 5c 15 1a f1 3e d6 +0b e5 22 eb 8c ab ed 89 a9 b4 5b 09 65 46 00 f9 +fc 75 1e 8b 12 e6 7e 52 + +# Signature: +00 3b d4 aa 90 81 fe 7e 9f 69 a2 69 fe c8 c8 a7 +36 70 c0 37 e8 5a 1f 36 fc ad 74 e5 b5 2d 71 0a +5a 18 ba 09 5b 98 10 cc 69 37 bc 76 34 09 51 e7 +fe d7 5b 32 6d 0a 3b 0f 26 c2 9c d5 eb 64 15 bb +f7 e2 dd 60 ad f6 a0 e6 13 02 dc c6 60 cc e9 10 +40 8b 4f 99 a4 40 ae 2a d6 c3 07 72 c2 9a 9e 7b +32 80 e2 e2 93 9a ba 0b 54 ab 02 2a a3 29 50 22 +71 8c d3 b7 87 b1 13 79 90 fb eb ef ac ec 8c b7 +49 + +# PKCS#1 v1.5 Signature Example 8.13 + +# ----------------- + +# Message to be signed: +84 0c c9 00 cb 4b 2c b6 7a 30 4a 9b 02 82 6d b0 +d6 67 36 92 2e 78 70 13 d6 bf 21 4d f5 79 ff 0c +f4 82 1f 9b + +# Signature: +01 3b 6c 08 0f 68 93 95 05 e1 87 a4 94 82 c7 91 +27 8d a3 ad 4a 74 7c 4f 01 79 1b 92 48 05 b6 82 +f6 49 bb d8 0d ba 12 fb be 59 40 f1 7f 27 e7 5d +42 67 7c 4c cc df fd 00 48 77 2e 36 93 4c 69 12 +12 8f f9 03 af ea 5e 1c a8 fe 94 24 fc 97 9b 21 +87 98 76 98 a5 c5 a7 5e 7d 70 70 a2 a6 74 85 2b +d8 05 bf 13 bb d1 29 6b ff 13 10 a6 d6 ed 45 fd +f8 67 2d 52 41 e7 4c d4 c4 19 86 e4 36 25 50 0c +23 + +# PKCS#1 v1.5 Signature Example 8.14 + +# ----------------- + +# Message to be signed: +c6 41 71 94 13 3b 5f 8e a6 3d 95 58 1c 89 6f 5b +9e f3 d8 7c f6 6c 02 91 64 0f 35 0a 32 5b 49 11 +52 e9 d1 43 0d 68 70 34 6e 46 8e 71 99 45 d4 e3 +65 d0 01 07 5f a9 70 f2 a9 87 0a 1c 65 43 4b a1 +70 02 41 2a cc 4c c7 4d 28 b2 de e2 9b 36 e3 97 +b6 8c 5d 59 cf 67 7c 29 ae e7 93 a9 30 0b 7b f4 +c6 73 b3 e0 b6 03 a3 61 1c a9 02 44 ff 08 78 75 +c5 16 88 57 cb 92 a9 5a aa 61 df f3 c2 12 dc 62 +06 f1 71 47 c4 4b 95 07 d5 c8 90 75 8b b3 5b b7 +2a 2a 5e 9d 4d b2 65 e5 37 3a 5b 34 02 90 4f 0f +1a 12 05 d5 bc c5 90 25 d3 22 0a 5d e1 b1 82 a8 +4d 30 41 2b 84 26 d4 69 32 32 1b 57 ef 72 64 0a +dd 2c ee bf 5b e9 68 43 6b cd 12 16 90 78 84 82 +32 93 b0 10 ec 28 f0 d9 + +# Signature: +01 60 47 ca ad 6c 47 bf 27 d0 cc fa 03 41 01 7e +56 5e 02 8c f2 6c 8e 66 0f 79 e0 91 f3 50 ce b2 +aa cf 92 f7 d0 1d 37 3f 71 55 11 9c 07 29 17 f2 +4f 01 bf 74 7b e2 dc dc 41 d1 be 58 85 35 c2 d6 +ac 17 04 c5 fb 16 f6 e5 dc 4b bc 84 53 f5 21 db +73 1e ba 78 98 e6 e5 21 2b 80 ce 9d a0 f1 56 28 +18 99 98 31 35 03 df d4 4e 3d 69 de 9b a9 cb 5e +b3 2a c4 1c b8 e3 62 1b a1 d2 91 d0 c5 da 24 9f +15 + +# PKCS#1 v1.5 Signature Example 8.15 + +# ----------------- + +# Message to be signed: +a6 42 f0 f7 0b 4b d3 b5 4b e2 20 11 9a 7f 79 + +# Signature: +00 a0 33 6e 63 67 52 7b bf 13 b0 a9 33 b6 31 c7 +2c b3 3e ab bc 29 2a 0f 8f 75 55 0c 22 30 fe 82 +57 f2 af 76 d5 43 cc d1 07 dd 2c 87 78 d3 ac 8a +7b 5b b4 ac fa 57 f2 af 6a 23 14 95 23 5a 51 da +dd b0 83 e3 73 b7 77 a9 5c f9 c4 a9 b6 be 77 51 +b6 5f eb 62 3a b3 34 43 36 54 b1 21 0f 7f 78 2b +17 25 c6 ba 4f fd 20 d1 7e d4 b6 ec 4a 3a f6 4b +d2 73 47 55 b7 73 9e eb f4 18 f0 9d 3a ff 28 9d +13 + +# PKCS#1 v1.5 Signature Example 8.16 + +# ----------------- + +# Message to be signed: +ca 16 e4 3d 9c 82 d9 d3 0c 8f cb 40 22 93 3c ff +c7 d7 4c aa 0d f4 86 35 09 31 8e da ba 4e 0d 51 +99 77 9c 03 50 4a ff a2 7d 87 19 1b 6b f6 86 a8 +4d 97 9a 2f dd 5b 8a 4c 49 32 14 45 c6 f7 5d 25 +23 59 17 ad be e2 a5 cf f8 a9 7a ef 78 c0 09 22 +10 11 d8 3c 0f 9d 37 16 08 75 af 73 67 71 8b 10 +ee c3 b4 29 90 e6 43 f6 37 07 cf bb 30 a7 fa 74 +ab 16 a7 eb f1 c8 38 c3 b2 26 37 b6 3c cd cb 6e +b3 4c 62 eb a9 e9 48 c7 ac 90 30 f0 63 77 29 d3 +e2 78 0a e6 be 4d 2f af 34 6c 11 63 d3 f9 82 48 +19 3a 76 39 9f b7 84 ca cf 68 fb 33 c7 4b ab c9 +dd b6 27 52 0c 0c 61 12 34 64 68 cf 20 a8 e0 2c +c9 a9 bd 27 91 0e 83 29 7b 85 e8 57 32 4a 01 00 +f5 cd d5 93 1b 6a 6d e0 5f 94 83 3a a8 61 0a 3a +4b 08 a5 a3 93 53 + +# Signature: +02 48 59 23 3f b9 db 7c d1 41 f4 b8 77 6a 1d 83 +e1 03 db 3a c9 42 89 d3 6e f4 0f 5e 6e 63 c3 12 +12 af dd dd 16 88 c2 c1 c8 d4 db 04 71 9e 1c 6e +8d bf 7d 60 be 25 f1 d6 88 87 fd ad da 3d 11 2e +3d 0d 24 c0 cd d7 98 8a 55 c7 10 29 40 08 2d 1a +c3 1f b3 ef ab e7 c2 88 cb 4e e7 2a 99 2a c9 6d +1e dd 78 ec 72 82 73 97 0a 79 69 95 c3 e2 a3 85 +81 e2 28 03 25 8e b4 cd 9d a2 04 0f af 74 1c 54 +2a + +# PKCS#1 v1.5 Signature Example 8.17 + +# ----------------- + +# Message to be signed: +3b aa 7e 9a da 21 43 f8 48 82 5d 22 93 67 04 d1 +c9 97 b2 da 76 76 9c 98 6f a1 52 b8 98 ae b1 1c +10 b9 45 79 76 4f 9d c9 33 65 2a 81 03 67 04 76 +95 8d 59 86 7a b2 4a 97 12 84 05 6e 99 c6 48 b7 +7e 7a 65 36 44 87 0f e4 c7 ce f3 7f 90 01 60 48 +72 ad ed e1 6a ac ed 8a a5 df 42 05 33 04 e4 d1 +71 12 0d 7a b3 ce 81 a4 d1 a2 74 98 d1 38 01 8f +66 21 bd fc 1d 53 e7 f3 c1 a5 aa 5d 62 b0 9a 55 +4a 56 f1 ed 4f 38 5a 07 68 ea a2 da 0c 9f 56 37 +03 4c 2e ef 58 cc 35 17 8b c2 a6 27 2c f5 29 b6 +5a df + +# Signature: +01 e6 3b 86 d0 c1 59 99 09 3d 44 28 af 7c 6d e6 +48 07 45 d8 19 e4 29 62 3f 47 2b 45 de 61 aa 56 +7b 60 d9 94 79 2a 0d 11 65 80 55 98 f4 e2 1f e6 +13 99 9a 96 22 5d 0b ba 98 f9 cf be e8 3a f5 85 +fa 07 84 39 a7 42 51 5a e2 18 ec 31 f8 d5 08 f2 +9b 0e 58 75 fc a8 f0 4f 11 a1 c8 2f 2b b0 ae 52 +8f da d3 ca 50 75 bb 3f 41 bb 57 83 34 81 33 fb +a8 a0 b3 ad 95 1a 1a 64 9c a0 f9 75 8b 20 c8 70 +fd + +# PKCS#1 v1.5 Signature Example 8.18 + +# ----------------- + +# Message to be signed: +7e b3 c9 8e 46 fd 1b 5c 9f f1 b1 1b e1 61 9b 56 +60 57 f2 6c 55 e2 88 f4 84 4c cd 50 ba a9 1b 03 +8d 60 95 83 6f 77 1f c1 c4 25 fb 53 3e f2 b1 dc +4a 3e 94 9b b9 95 25 c2 8f e8 a3 e9 31 78 f3 a0 +ac 97 fd 5d aa 81 b5 92 86 18 8e 17 b4 4b 37 71 +bc a8 55 d8 5f 3c 4d 28 6f 10 68 10 f4 e5 22 ea +05 83 4f 11 a3 1e 89 c3 59 90 c5 1b 08 0c 03 a6 +61 e3 d4 a1 b9 7a 2c 27 94 0f 5b 2e 41 2b 69 9e +a6 10 e8 99 6a e6 71 5a b6 e2 09 69 b6 aa 54 cc +72 31 9d fe e6 3b d2 ca cf d0 60 8d 40 e2 b4 03 +95 fe 55 dd a5 be a3 b0 f9 b9 4b 5a ad c0 98 dd +56 8d a3 95 db 2d 44 e4 + +# Signature: +01 5c fa d9 6e 4b 57 d9 cb b5 78 c7 90 74 a2 ba +86 9c 06 02 88 68 c5 a3 fc f4 a5 e3 61 83 1b d8 +c0 2c 25 b1 2b 90 23 4c 8e a4 82 2f b6 5e 82 d0 +91 a9 0f 89 b6 c1 15 6e 4b 44 d7 8d 32 a6 47 37 +d6 15 87 c0 ce 3f 4b 34 3e 71 f8 f7 a8 4c 6f 8f +c8 ae f8 f4 64 c8 b3 59 e4 fb 18 ad c6 99 c5 a0 +76 45 37 55 93 0c 5f 6f a7 07 1f 8f ec b8 63 1a +a4 14 f5 08 35 03 8b e7 ab 05 a4 b0 50 f3 f5 6e +86 + +# PKCS#1 v1.5 Signature Example 8.19 + +# ----------------- + +# Message to be signed: +6a 45 ee 0b 7e a8 03 68 b2 c4 29 af 28 81 53 f4 +56 cc 66 32 17 a8 ff cd 2a a0 5c 5d 32 2d b7 57 +56 cd bc 0f 68 41 41 fe 6b ca e1 89 bf 24 de 1c +8e dd 5b 11 36 44 a4 50 0d 0d 4f f5 80 08 36 40 +e1 2a 2c 95 de 69 e9 59 6b fb 1d 44 36 57 86 e1 +67 d0 25 d8 9e a2 f8 d1 3a 0e 64 77 f1 3b 85 bb +dc f1 60 77 4b 18 25 8c a0 be c0 bd 7b f1 39 11 +b3 89 6b 48 89 fa 3d e0 4a b2 6b d6 82 b4 ab 43 +7c 0c 17 f3 53 a2 3a 43 e9 2e 20 e7 f8 20 69 4e +40 3a ab dd 5d 19 6e 93 89 5b 47 92 55 df 40 30 +ad 8c e3 a5 3d 15 73 be 22 6d 81 aa 18 e4 85 89 +57 a2 d0 a3 35 9c 2e 7a + +# Signature: +01 64 f0 db cd d9 52 11 86 a2 80 84 a3 f3 ae 6a +ac b6 59 6b 85 6e 8a ab 2e 72 a7 f2 33 d6 2d 2d +3e f1 96 d3 78 7e 4b 04 57 31 da 9c 61 50 ad 9d +5f 91 8c 6b 06 c9 2a 11 a0 bf d5 ef cc b7 b0 3a +01 07 24 14 39 d3 4d 31 3d 35 b3 6a 0d 8c a0 81 +3c 36 23 b2 bd 78 f2 e3 a9 71 99 64 8d a3 58 06 +ff c5 8e ed 33 ac 9f cf 79 53 8f a8 89 15 b1 a5 +75 85 78 b9 a2 db 01 38 04 bf 32 e7 a5 6d c7 24 +37 + +# PKCS#1 v1.5 Signature Example 8.20 + +# ----------------- + +# Message to be signed: +92 a4 b4 bc e3 da a0 a7 a6 4b 72 ad 87 1f 3a a8 +ea b5 ac 40 11 aa ae a2 ce eb a8 92 77 c6 43 29 +57 26 26 c9 56 88 4f 48 54 f8 61 3d 22 51 8b 14 +f0 38 fc af 9e 68 e1 30 02 fb 0a 00 a7 8c c2 ea +51 44 fc 13 11 76 d5 e5 d6 7e 10 6a 99 87 9c + +# Signature: +01 24 fd 8b 2a cf 22 37 fc 71 a2 ee 97 e2 6a 4d +ab 7d ea 82 9e 15 be b2 f8 a7 37 91 a0 ba 15 2d +a5 b0 6a df 34 1d 74 09 e8 d3 d3 17 5b 51 01 34 +32 5a 35 32 97 a8 d6 d6 6c 09 70 03 22 ee c5 e3 +3f 62 48 6a 21 11 30 d7 4c 70 dd 92 5d f8 60 2a +e3 c4 c6 cc af 93 cc 9a 97 0d 1e 85 32 60 ee c6 +94 81 c5 f1 33 7e 9d d3 ae da 88 d8 82 99 be 08 +09 5b 71 5a 5b 21 66 e6 17 c9 26 72 2c ed d6 ef +34 + +# ============================================= + +# Example 9: A 1027-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +05 f3 74 34 88 26 1c 6f 06 25 e4 32 fa 6e b8 7f +b1 2b 26 21 82 90 bf e3 96 ba 76 ea 42 61 32 2f +81 43 e4 b4 eb cd 5d 2a e1 9b 0f 9d 8d cd 2f c7 +e6 82 32 08 a7 51 83 3d 3b 4e 8e 38 7c 39 f8 ed +6b bc 9f da ec 32 d3 ea 9a bb ff 57 47 23 f3 f1 +22 99 90 96 3e a4 fd 9f b5 44 f6 42 90 aa 2e a7 +da 63 11 91 a2 0d bc 94 23 b4 61 23 3b 93 72 49 +f2 f4 ea 10 92 8f ae 2a 6f e6 64 f1 2c 09 23 ed +11 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +05 f3 74 34 88 26 1c 6f 06 25 e4 32 fa 6e b8 7f +b1 2b 26 21 82 90 bf e3 96 ba 76 ea 42 61 32 2f +81 43 e4 b4 eb cd 5d 2a e1 9b 0f 9d 8d cd 2f c7 +e6 82 32 08 a7 51 83 3d 3b 4e 8e 38 7c 39 f8 ed +6b bc 9f da ec 32 d3 ea 9a bb ff 57 47 23 f3 f1 +22 99 90 96 3e a4 fd 9f b5 44 f6 42 90 aa 2e a7 +da 63 11 91 a2 0d bc 94 23 b4 61 23 3b 93 72 49 +f2 f4 ea 10 92 8f ae 2a 6f e6 64 f1 2c 09 23 ed +11 + +# Public exponent: +01 00 01 + +# Exponent: +01 4c c3 26 32 52 f8 c4 fb 77 cd 57 a1 42 0c 04 +c0 43 27 8a 0c 45 e7 d4 23 79 49 3e 34 0f 9c f1 +a9 6f 96 06 3a b7 59 d1 63 04 06 ae 28 6a 18 34 +b6 d1 db 71 ee 72 2c 93 74 5f dd 4a d3 3f aa 72 +d8 93 51 da 69 1a 7d 0a 71 d2 c5 5c 57 97 d2 cc +b3 b4 62 62 08 bc 5f 5c 84 fe 43 2f 66 4d c3 0e +de 09 63 e6 58 45 2b 2a d5 ef a4 93 5a 12 2f 46 +1d 1e ab 84 1c 8a e0 e6 e8 2f c1 fe e8 5d 18 1c +bd + +# Prime 1: +02 94 ea 0f a3 4e c3 13 72 33 44 20 2e 85 ec a2 +4b 5d f6 46 1a 1c 30 08 7d ca b5 d2 53 39 4a f5 +66 6f 03 5c 33 35 41 0d 8b b9 86 62 c9 78 f6 1d +37 db 4d 83 f0 b2 4c dc b6 3f ca db 79 c5 27 f5 +ab + +# Prime 2: +02 4e 19 16 52 f1 70 9f f4 74 37 40 85 81 88 8a +9d a1 09 17 c5 b5 ab af 91 46 10 9f da c6 94 76 +6f 4c 8f b0 57 96 8e 84 8d 99 58 6b 05 f8 a0 2f +ba 6c a1 eb 12 ba 08 df d4 9b 62 c2 7a 8f 15 f4 +33 + +# Prime exponent 1: +01 22 7f 36 dc 6b 14 27 89 fc aa a7 12 8b df 14 +fe d7 90 16 04 07 fb bc df bd a7 e9 88 97 18 31 +81 12 ae 81 6a 28 b0 2d 4a 0b 03 dc 8b fd d4 ff +c6 bb 67 f8 e4 65 1a 8f b0 b3 9d 70 96 b7 67 f6 +fd + +# Prime exponent 2: +02 25 ec 05 3c e8 da 6f 86 ad e3 6b d2 bf 43 93 +02 91 37 5b 1b 1a 51 d4 7d 0b 11 a5 17 8a 26 83 +34 f7 e1 94 92 1b b1 d7 5f ea 7f 56 c5 aa cd 05 +8d b3 7d 36 08 2e ac e4 83 4b 07 bf 7b dd ea b4 +b7 + +# Coefficient: +02 0b d0 f5 15 80 87 ed e3 8c b5 dc 66 e4 01 0a +e4 e4 8c c0 04 2e 15 2c d5 ee b0 51 c9 ec 45 ad +23 40 24 53 52 c0 1d 94 c6 a5 26 aa 5a 45 4c db +ae ac 85 95 34 9b be 6a 8d 55 19 a3 c9 b7 d0 7c +3a + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 9.1 + +# ----------------- + +# Message to be signed: +82 e5 c5 aa e6 4e 60 8b 27 50 4b 91 db + +# Signature: +01 45 82 da e9 35 e6 b2 ae ff 7d 72 50 89 da b0 +58 c6 78 b2 ee 28 bc d4 44 a7 2b df ac 31 46 3e +18 e9 4d 7b 5e cc 84 a4 31 69 6a 1c dd 79 f9 c0 +8c 33 e1 d4 b3 22 dd 27 7b 50 3a e6 e4 f9 c3 15 +30 5b 43 72 fe 45 fe 4a 7e bb fc 4a e5 90 fa 3c +52 0b f8 28 15 8f 78 20 29 9f 09 b1 34 ed e1 17 +b6 72 a1 ea c2 f0 50 c0 44 b2 55 ca 8d 45 52 d4 +b5 f3 f5 7b 87 34 db 24 74 50 07 44 a5 33 75 00 +5e + +# PKCS#1 v1.5 Signature Example 9.2 + +# ----------------- + +# Message to be signed: +77 e0 fb dc d6 e0 49 8f c5 68 4f f1 3d 4c 9f 5b +78 0e 77 e2 46 46 37 ff 66 ea a2 d7 d9 c3 de fb +9b 0e 3a 38 37 73 db 97 a4 fb 49 1b eb 21 14 fd +ea 2c 2a 48 0f fc 21 9b 79 6a d8 05 d5 4f be c1 +7d cb 34 b1 da 17 96 cb 9c d5 f2 41 6a b5 e7 66 +f8 e0 06 91 8e be c1 82 29 98 a2 8f ff a6 23 0c +07 87 26 fb a2 e4 a7 b0 + +# Signature: +05 93 27 ce e7 26 ff b6 03 e8 a9 fc d5 74 ab a9 +cb df c3 6c 0a a6 6f cf e3 55 5c f2 ef 35 82 d3 +22 0d f9 d6 bf 8a 78 e3 ff f0 c1 29 b3 ab b3 dc +71 21 12 a2 05 6b ca 08 63 65 54 c1 ac 57 df 87 +f3 66 41 52 68 8c 6a c7 2e 6b 88 f5 63 7c d7 3f +16 69 89 c8 29 09 fb 67 bc 1f a2 e2 d5 23 e5 1c +91 8f 2b be c1 d7 52 02 af 24 0a 61 cd 2d cc 55 +5c ae ae 9a 68 57 0d 77 81 0c f1 df 81 23 ff 41 +c0 + +# PKCS#1 v1.5 Signature Example 9.3 + +# ----------------- + +# Message to be signed: +0d fa 5b aa 1c dd b8 34 70 7a 5f 8c c6 ec e5 71 +a7 a7 fc a5 67 63 62 d2 b2 37 41 a9 57 0a e2 63 +8f 6b 1c 23 89 85 36 75 cc c6 cc 1b 4c 6d ae 23 +cd a7 1a b9 6b 5a 2f 22 14 57 50 43 3e 2d 6b a4 +27 6a c1 ff 9a 48 af c9 f3 12 f4 13 37 85 ca 5a +f3 74 66 74 31 9a 67 57 a1 64 e3 4d 14 98 bd 55 +30 90 2e 32 18 55 e3 be d4 08 81 f0 05 42 25 6a +a2 1a 42 fc + +# Signature: +01 d1 95 41 69 af 58 99 3e 14 77 2a 94 f1 9b c4 +79 24 cc db 2e 90 ee 43 36 fb 6e 08 49 8a f4 da +26 51 a2 b7 83 6c 31 3a 57 c8 61 b5 51 84 ec 3b +15 fa c8 14 53 51 be c5 a7 27 0a 3a a8 69 4d b4 +e9 a9 2c b9 32 7b b7 a4 f7 b7 0d 24 4e af 9e bf +a9 ed fd 4d 54 78 2f 3f 97 26 26 95 b9 7d 41 6e +52 7b e4 ea 2d ef fe 6e b5 e0 6c da 6f 0a 7e 41 +66 77 ac 0f d6 f8 19 5d 4c e2 89 70 d2 ca 41 1a +2b + +# PKCS#1 v1.5 Signature Example 9.4 + +# ----------------- + +# Message to be signed: +16 7e 79 56 8c 77 36 69 0c 3b ed bb c8 d4 24 eb +53 6a 12 85 5a 60 cd b1 0f 94 ba 11 23 17 e9 17 +a1 b7 d6 fc fa a3 43 8d 68 ee 09 fd 47 + +# Signature: +02 9a 2b 90 86 14 ed 7a 5f ab 72 f2 a1 c8 e5 48 +b6 f8 b8 b4 5b 75 81 fd 24 51 fe 45 a6 22 fa 0f +08 dd 0b a2 e8 f3 c4 17 20 1e a0 27 79 10 18 4f +37 6d a8 03 fa 72 c5 0d 39 be 28 82 52 6d 1e 85 +df 9a b1 79 75 76 4a cf b2 07 36 6f 6c d2 c8 b1 +36 a9 99 da af 48 f1 c0 8a 9e a1 f0 84 25 c2 1b +65 41 80 da 4a df 10 9b 4b c5 b8 17 dd 67 bf 7d +aa b4 a3 84 03 4a b4 ad e6 94 89 8c fc 27 2a b6 +53 + +# PKCS#1 v1.5 Signature Example 9.5 + +# ----------------- + +# Message to be signed: +0d 03 f7 12 84 f2 e4 83 24 2d 92 3f d1 e1 53 bc +16 0f 0c dc 2c 0b 76 f1 bc 2c f7 d1 be 9c cc 7f +af a6 af c3 90 34 01 84 09 cc fd 16 28 a7 0b 35 +83 33 bd 96 ee d3 ad f3 14 2b 17 60 bf 8a 9b b1 +9e a2 47 3a 2e d8 5c 91 cd 5f 0a 5f 2d 46 32 d6 +17 64 19 fa 1d 8c c8 8b 67 08 47 77 11 ea 49 58 +a8 39 01 fe f2 84 f5 a6 c5 02 79 8c 8b d0 a3 50 +f2 ea 83 ed 18 1e b9 70 d3 0b 78 13 4c 8e 1d 64 +f0 d1 49 5b 70 17 24 5f a6 9b d5 74 27 f7 49 20 +ba 0e ed e9 cb a3 4e b2 22 76 b0 f2 74 13 ba 3f +0d a8 eb de db 9b 0c 80 0e 44 48 1d 01 e6 bb b0 +df eb f9 a1 5e f6 a7 02 0b 2c 55 ee 02 79 11 79 +6f 66 f4 3d d8 46 02 1f 8d 6f 7e 01 bb 80 2b ac +09 fd e9 b9 04 be cf 99 90 e6 84 e6 56 9a ca eb +3c c6 4d cf 5d + +# Signature: +04 22 79 1f e7 b4 3e 1f 31 9a e6 7d 91 8c 59 87 +e6 39 36 81 a1 86 1c 1e 71 dd 6f ce 19 23 71 0d +bc ed 43 01 fd cd 4a ad 8f 4f c2 7d fa 02 a9 4d +91 bd 96 20 0a ed 8b 3c 5a 96 ef ee 7d 11 af 90 +87 fb 81 90 5c 5d f2 c2 4e d7 ed 63 d5 fc 22 ba +bd 6b 9e 3b 57 cd 25 41 9a 78 17 e9 36 16 e9 34 +54 b9 58 53 fe 52 04 b5 8c 09 8b 46 de 0b 3f 01 +f5 82 76 32 48 c2 90 b9 e8 09 69 65 24 42 a4 d8 +e5 + +# PKCS#1 v1.5 Signature Example 9.6 + +# ----------------- + +# Message to be signed: +4a ca 96 3f 14 ac f6 a7 9c 51 08 1e f2 57 16 66 +71 e3 b4 5f ee 31 24 07 ba 3c f6 d7 11 ab a1 ae +25 a4 a8 ba 45 48 19 a3 91 2a 31 2e 99 0f 1f a7 +4c bc b7 27 77 f1 c7 c6 63 a2 d1 cd b2 c5 c0 07 +4d 45 16 f4 87 17 de 14 03 e8 ff 7d 0f 9d e7 c7 +c8 51 f3 e3 51 16 8b a6 c4 14 be d5 d4 2b ae 52 +7b 72 4c eb 83 4d 79 ba cf 70 2c 56 a6 23 c1 68 +80 87 dc 9d e9 53 8e a7 c7 c7 61 cd 2f d5 78 f0 +dc 3f 55 2f fb d4 af c7 f4 ec 71 22 fd ec 1a 3a +2b 10 4d 53 2d b8 1c b9 14 18 54 d5 7d cf 54 b7 +56 01 a9 05 fa ed a6 5c 2a 7a 7b c2 b0 29 ad 12 +dd 7a 6a d1 b4 0b e0 40 28 b4 b5 b6 37 30 ef 98 +44 73 f0 c4 82 14 89 93 c3 6b 44 e5 4b e9 a5 f2 +34 e7 43 29 2a 12 a3 4b f2 ff 73 b7 f7 98 + +# Signature: +04 26 43 c0 3a da 72 4e 2d bb 19 cc 07 ad 0e 75 +22 28 b9 d3 6f 65 3c 6a 9c 0c 29 35 6c f4 c3 f1 +ca 19 37 76 d5 fe f4 3f c5 54 17 71 66 69 de 9a +b2 ad dd 3e a8 8a 90 ae 93 9a 5e b1 10 13 e2 28 +ae 08 16 ee fa 4d d4 2c 6c 08 c8 78 bd 58 b4 90 +40 29 6a 86 3b fd 11 28 5f 8b bd 31 5b e1 6d 2d +65 d7 f5 e5 f2 6a a9 71 47 f9 5f 5e e3 6f 98 9a +a8 96 d7 f9 f1 b3 05 1f 82 42 44 f9 05 96 72 3d +11 + +# PKCS#1 v1.5 Signature Example 9.7 + +# ----------------- + +# Message to be signed: +a7 5a 45 80 + +# Signature: +00 4f e4 c5 d9 14 3c 85 1e 46 16 7c c1 81 57 5c +07 5e 69 b9 81 f9 c1 03 f9 d9 b0 11 ff 8b 29 ba +55 a4 31 87 ce 87 77 99 63 17 a0 3c 9d 90 af c1 +89 0a 9a de ec 8e ac 08 7f 99 b8 15 e6 eb 2b 87 +1d cd dc 80 92 24 9d 8f 51 3c 6c 56 09 fd ae 2c +fc 6b f0 1f cb 80 25 a4 f7 9b f1 2a a8 e1 09 82 +9a 0b b3 8a 09 d1 a3 93 65 e0 40 56 52 da e4 51 +e5 c3 29 8f 47 04 05 98 ec d7 0e 4b 40 33 89 bc +d5 + +# PKCS#1 v1.5 Signature Example 9.8 + +# ----------------- + +# Message to be signed: +7c fc 00 a6 43 ae 99 79 68 01 ee 3c eb e2 cb b1 +a6 be 1c ac 15 c6 48 d4 ba 33 01 29 38 71 a9 9f +7c b1 43 c1 28 c7 7f 96 31 1f e4 3a 39 01 df 2c +2a 5c 40 4b e8 31 46 97 e0 9b 2e 80 aa c6 ac 39 +97 1b be 0d bc 26 67 3f 31 95 9f 23 8e af d1 50 +12 e4 96 7d 33 55 18 92 a3 d3 65 1f e4 46 9b 2d +ba 45 57 df 89 3a b6 b9 4f 13 25 c3 a1 + +# Signature: +05 98 5a 4c ce d0 e8 fd c5 89 24 ed ba 9e 40 0e +67 48 21 4f 8d 0b 83 aa fa 20 35 0b bf 0e 68 76 +ca 5a 9a f3 97 0d d6 3b e6 84 f9 93 6d b2 82 ff +8b 53 cf 5f 1b b1 cb f4 47 33 01 f3 72 d9 94 8a +f9 39 1b 20 02 b2 be 3e 45 ff 24 a2 d8 99 ae 8b +52 b6 71 b0 4b ab 46 01 06 be dc fa c0 13 95 9a +48 18 95 98 42 7f b9 57 15 9a 6d 32 9c 19 f3 6c +a7 53 81 b9 35 0d 34 38 9c 16 e1 80 a8 51 e4 57 +cd + +# PKCS#1 v1.5 Signature Example 9.9 + +# ----------------- + +# Message to be signed: +3d 90 de 72 35 51 59 49 24 5f 49 03 68 c1 f4 93 +83 e4 4c 1d b5 1d d5 38 5b df f5 bd 34 45 0e 63 +ce 42 15 0b 44 1e f9 eb c7 29 a9 03 34 53 f0 a9 +39 9f f6 86 1f 50 65 b6 66 6d c2 0b 28 72 03 42 +8e 72 bd f4 cb 74 8a c8 d4 a5 5f 43 d2 23 5e 0a +b2 ec 2c f2 b0 6a 01 5f 41 e3 51 68 ac 7e 3c 56 +8f 2f 16 ef 57 28 b2 be 95 24 91 9d 36 76 d6 8f +53 7e fe f2 9a 05 af 97 cf ed 7c e9 ec 45 c1 2f +16 5e 4d 7a 4f e7 2b 99 ea bf 83 31 6c df 2b d1 +64 4b 82 fa 13 e4 ff c4 49 e7 6d 44 c3 87 69 63 +51 47 8b 1a 0f 85 96 15 da 90 5f 20 e6 8b 24 56 +5c 87 3f 83 4e 59 34 58 51 8a de 41 c1 42 81 74 +da 0c 47 66 3a 76 00 c6 50 25 01 5e 09 c1 + +# Signature: +00 98 13 b2 fd c5 1b ff 88 de db ec a3 b1 4a e5 +8b c7 e7 14 c1 d9 2d 74 26 e4 94 4e f9 3e f9 ce +6d 10 dc 98 9e af e7 34 8d 0a 95 f9 9f 56 94 8f +72 60 2a c5 e8 61 4f 6b 38 e6 8d a7 9f 48 e2 76 +8e da 58 64 cf f2 54 51 37 f3 cf 4d 81 a5 ae b8 +9b 21 07 26 74 ca eb a0 00 71 00 c0 7e f4 dc bb +d0 5a fb ad 9e 8b 30 d7 46 ea 36 0d 6c f8 75 d1 +0a 67 a5 7f 4b 5d f4 12 1d 72 97 a4 bd ce 12 8c +b5 + +# PKCS#1 v1.5 Signature Example 9.10 + +# ----------------- + +# Message to be signed: +20 e6 a3 fe 16 b5 21 b3 c1 e6 ae 99 3e c6 e8 49 +a9 c1 1f 20 42 a2 d4 ce 89 cf 0f 99 e1 b4 b9 47 +1d a9 a1 73 0d a8 85 1f c5 ab 3c 09 22 05 5f 00 +37 58 b2 35 c2 8d e4 08 80 66 3f cd 80 14 07 18 +15 dd 06 49 4a 54 7c ce c3 34 8e 12 d5 38 d5 df +b4 8f 80 7b 59 e9 b7 cd 81 f3 91 c0 2c 01 6c d9 +c1 a8 4f 9c 59 51 79 d8 f2 00 24 2a 56 68 18 2c +f2 cb a3 b9 fb 6e ad 45 1d 6d 27 d9 c7 36 15 25 +d6 88 b5 52 33 ff 45 29 1c c0 74 02 d2 92 de 0b +e8 3d 16 46 c4 3c 28 88 1f d4 55 49 b1 4d 12 61 +b1 2f 12 04 38 27 6c 6b 3f 98 f5 5b cf 17 80 bc +1a 91 eb 11 d0 22 9e 1d 78 68 d7 fe e4 9d 6b 91 +68 e2 4d e1 cb 4f 0f 22 e6 7c bb 15 69 20 41 13 +02 72 94 b3 7e c7 fa e5 8b c6 4e 82 5e aa 4d 56 +94 d0 05 8f 2c d4 c7 d2 14 18 da 3c 03 07 fa 2f +04 92 e8 b3 77 58 d3 ea 40 a4 e3 0f 60 + +# Signature: +01 f0 2b 3f 83 91 23 af f2 a3 f4 3d a5 aa a0 b6 +bb b6 0c 04 37 82 f4 96 2a 7b 9f 02 5c 94 8e 34 +32 2e 98 de 37 03 e3 bb 45 a7 06 a2 bb 05 09 be +d9 f4 10 52 8c 88 1a b9 a1 dc 01 97 06 8c 37 28 +c3 71 6d 83 81 d9 f8 67 80 fe 78 a6 43 4b 72 f5 +1e 69 cd 32 a7 21 3c ce a7 43 b3 3c 3c 96 eb 00 +42 fb 98 a7 0c 2e 52 fc 17 8a b2 cb 9f f8 bd dd +c1 04 6b 08 e0 47 ba dd d6 5a 45 a4 e6 53 39 d7 +25 + +# PKCS#1 v1.5 Signature Example 9.11 + +# ----------------- + +# Message to be signed: +6e b4 9f 8a bc 5b 49 48 72 0a 7f 42 f7 40 84 78 +00 22 e0 e9 f9 f6 88 86 d9 f3 4e 7f 7f 8a c1 54 +db e1 9c 91 b8 ed 38 ec 03 6b 61 42 12 ca 35 f7 +9e d8 74 57 9e 24 85 da c8 20 5d 0e 56 b4 b4 c0 +00 0a 8a 75 a6 d4 97 fc 51 19 11 1a 40 db 51 3d +f6 61 96 55 b5 8a 11 6f ab ee 08 2b fa 79 37 3d +91 76 56 87 10 11 24 18 87 f4 42 60 8b d1 eb 1d +95 d1 76 80 65 fa 63 32 4f ab 27 36 f9 22 70 5c +f2 89 fd e9 26 74 33 85 92 07 a8 bc f1 2d 17 86 +1c fd 06 2b 88 df 78 87 0d 5a 5e 91 13 1b 63 + +# Signature: +02 a2 fa 32 71 77 96 71 0b 52 b0 51 90 6c db 98 +15 b2 d0 36 6c 07 0a 78 ff 72 d4 59 42 d7 ad de +ae 7e dc 73 ca 93 01 f1 f9 fa e6 8a 0b d4 b1 df +05 a9 a6 71 f8 a5 b7 d4 5c d1 1f dc 0f 0b a0 9d +25 ce c3 b6 30 3d 9a 66 6c 76 32 64 96 ea 31 ae +38 86 a0 c3 b7 d2 27 62 ee a2 78 93 4b 96 a4 f9 +0a 50 1a d3 08 8f 70 2e 14 76 3c e3 38 46 e2 fd +be 6d 66 1c b8 2e 6d 98 9d f3 c5 ac 8f e4 0a 85 +62 + +# PKCS#1 v1.5 Signature Example 9.12 + +# ----------------- + +# Message to be signed: +45 cf ec 13 2e e5 93 f0 c3 f3 81 3d 3c b4 49 e6 +e5 e6 1d 13 de 52 9a e3 e7 1c 99 8e a4 56 35 9c +e6 6b 82 04 5b 7a c7 97 fe 96 98 5d ea bc 51 22 +53 0b 2e 29 ef c9 75 ee 96 03 b4 f9 6f 3f f4 e5 +9b 0e 35 a9 ad 92 f2 b8 67 79 4d 8e + +# Signature: +03 9b e4 8f 13 3a e7 f0 b1 9e dd b2 13 56 09 73 +a3 e2 a1 14 6c 79 42 f8 26 4b ba 5a d0 08 69 2d +11 38 01 fc 27 78 a7 e3 3a 9e 11 5e a6 32 e5 01 +88 c8 7b 69 e8 d4 d8 cc a4 8a bf 9f 25 1e fc 00 +17 b9 9e de e5 66 dc dc 0b c5 8d bf 6d 67 bf 86 +3d b8 a8 9a bd f1 2a 77 f1 b7 0d e4 39 d1 76 f2 +ea ad a5 46 4c 79 a5 84 27 0c a5 14 f4 8f 1d ae +86 78 ec f1 ac 29 6d 07 c4 68 98 ba d4 1a cb 19 +9d + +# PKCS#1 v1.5 Signature Example 9.13 + +# ----------------- + +# Message to be signed: +22 51 29 87 15 7c f9 b9 ab 4e 53 37 b0 98 91 d6 +3c ec 37 43 c0 f7 bc 9d 18 2e + +# Signature: +02 c7 75 7f 99 93 ef 8c 6d 60 a3 f5 ab ed ce a5 +35 df f5 5a b9 f4 f6 2d 12 54 bf 26 1d d6 a2 ee +52 da 63 49 f4 7b 9b 28 9f 1d 0e a3 e0 ff 08 f4 +55 fa 54 85 65 8e 42 17 f4 40 c0 8b 90 ae 4c 6c +c2 56 97 cb 83 35 31 db b4 74 03 25 43 10 0b 5f +92 b6 78 19 5d db fb 1b 59 c5 9b e7 c8 3d d8 17 +45 cd 4e 70 9a 0e 3f 79 8e ad 5b f8 66 2d a6 5c +10 57 cc 08 2d 90 50 50 c4 65 95 8b 55 5d 77 b8 +b1 + +# PKCS#1 v1.5 Signature Example 9.14 + +# ----------------- + +# Message to be signed: +ae 48 cd 83 f4 a1 f9 4e 17 19 21 96 90 c8 c6 f6 +73 7a bd 15 e0 d0 8e 7f c2 ea 0d 31 5b 45 be c2 +46 e8 45 bf 17 60 c8 6c 3f 82 d8 4b 1e 9d 68 dc +cc 01 d9 a7 d0 7e cc 6b fb ee d8 3d 7a d0 3a 6d +56 6a 89 bc 64 42 1e 7e b4 7e 52 c0 23 86 58 d5 +e4 c5 59 7f 12 5a fc 6c 83 3c 63 cd 6f 97 f9 dd +5c ce 8a 26 38 80 7c e8 a5 83 da 03 2b ec 81 a3 +8c d2 99 a9 c7 8e 82 54 f2 88 51 64 13 52 5f d9 +4a 9e 0a 95 c6 56 d7 3c d5 2a 4d cc 7d d0 94 7f +4a 00 5e ae dc cf d0 3b b1 71 5c 35 1c f0 59 cd +52 2c 7f 53 8c 16 28 e7 2a 05 64 4e 8f ff 50 92 +6f a8 68 2a 67 53 78 6f 2a a2 61 0a bf aa 95 bf +99 af 15 61 71 51 d0 bd 0f c4 6f c3 b2 9c be e1 +e6 63 b9 23 13 6b 5e 19 92 83 9f 0b a5 2e 44 fc +cb d9 f3 20 ed e2 0f 55 a4 23 77 0e 57 3a 9f b2 +b3 6d c8 f1 84 + +# Signature: +00 fb a9 f6 f9 59 b1 70 b0 94 6d cb db 98 dc 8e +84 79 c6 69 ad ba 6c 54 63 6a 2d c7 d7 f7 03 3d +35 04 05 d7 17 f2 d6 3d ae 65 c2 4b 37 db 1d c3 +e9 f6 17 43 af 1c e6 de 24 67 d1 85 ae f0 8d 2b +f8 65 f0 75 ba a6 a2 9c 58 06 61 dc d4 a4 8f 21 +ff 4e 7b 03 9e ef 1e 1e 20 ba 80 cf 20 ea b6 ec +de 60 fa 5d 37 67 a3 0e 6a d4 14 47 13 ca 49 fc +03 80 99 af 53 6c 0d 5f 55 c4 cb 15 33 53 81 be +a0 + +# PKCS#1 v1.5 Signature Example 9.15 + +# ----------------- + +# Message to be signed: +2c 8a 00 7b 60 30 56 d3 31 87 bf 52 ce f6 16 1a +a5 f5 f5 33 7f c3 59 d4 63 44 72 1d 94 5f bc 4d +24 0d 30 62 0b 29 6c 39 77 cf 45 c2 47 eb 2c 36 +39 40 79 98 3f 03 ad 82 39 9c 4b 28 6c 48 16 59 +10 b3 48 b9 5e f3 9c 43 bf be b3 56 6d 1d 1e ea +5a 42 7f 4c b1 68 1f 2a 7c 40 1f 3f 0d 6d 9e e7 +99 3b e5 ec 5d 34 a7 55 41 e9 f8 dc 7c 60 69 a8 +97 7c 9f 93 6e db e4 1a 4e f7 85 a3 ef 7b a0 51 +89 90 09 ed 61 2a 22 8f 90 31 67 a9 34 ee e6 9b +4f 87 36 c2 95 11 c6 bd c6 1e ee 96 08 a9 91 1b +ba 52 83 9b e9 9f 91 d2 ef 85 b8 cf 10 c1 d6 35 +08 08 29 ba 79 91 fe 2e f8 2e 2b ae 27 08 14 06 +e8 9b ab 75 c3 ed 19 e8 7a 4a db 72 ec 26 21 f3 +f2 58 5b 38 cb b3 6b 3c 0d 40 5f fc a7 a6 fb 02 +24 42 07 94 cb d8 d7 83 18 01 c8 81 e1 65 + +# Signature: +04 10 47 e2 42 b6 44 87 41 f2 8a 4c 8b 2d fe ca +cc 0f f6 61 9e 95 6a 6a 6b 10 cd d0 1e ed d2 01 +c8 0e 0f bf 7c 5b ef 52 a7 aa 99 00 a8 59 39 4b +47 e8 3d 08 b5 e1 da 03 a3 35 54 00 0c ce 17 c1 +d8 62 29 a3 a2 03 50 d1 16 43 a7 58 c1 16 b8 fb +f7 26 60 df 4c 86 ef 8c 1f c4 54 4c 3a e1 d1 fc +3c e9 f2 63 f6 2e 80 07 cd 7f f7 ea 8d 50 a0 82 +83 89 ff 43 1f c5 c5 62 81 6d 3d 24 b6 07 21 1d +29 + +# PKCS#1 v1.5 Signature Example 9.16 + +# ----------------- + +# Message to be signed: +7b 15 d1 a7 9c 7a d2 d1 2f 75 da 57 d1 4a 8e b7 +1f dd 4c 4e ff 52 43 74 1a cd e2 3c e6 da d3 08 +c8 1d 5d 58 0f f9 c3 f8 93 ff 12 4f e4 58 b3 18 +84 da f7 fc 44 66 d7 00 dc 49 3f 1c 7a 7d bf 62 +24 1b 17 e7 36 23 fa 17 81 4a b4 d2 c9 24 5b e8 +3b b3 cc 5f 94 44 b1 52 17 b2 44 1f 45 9c 00 b8 +2e 58 68 9a 11 dd 5c 59 fa 39 5d 1a 6f 9b 2c 25 +cc 84 99 92 7a b9 a4 98 28 53 36 52 ce e2 32 32 +97 2d 65 69 ee 56 44 78 66 f1 0e ba d5 4e a3 f0 +61 32 0c 6d 3f ef ce 34 55 2b 62 66 96 7b 05 78 +d6 c4 55 b9 ac 24 66 36 17 12 e7 d0 5b d3 33 2e +c1 30 d4 5c 6a 49 76 16 2c 79 7a d1 36 3f 49 69 +e4 ae 3d ed 6e 36 ea 2c d7 fb 35 66 09 be 03 1a +79 b2 94 + +# Signature: +03 02 52 90 b4 46 2f 9a b7 9f df aa 7b 1d 53 a4 +d1 27 96 c8 5a ac 28 de ac 21 27 c8 25 2c 2a 62 +39 5a 8b 81 9d fc ee bf 68 dd 4d bf c8 7c 1c f3 +d0 17 a5 3a 26 40 92 50 6b b6 fc 95 28 e6 f8 76 +78 73 6c a5 6a 14 a1 aa 26 77 a8 b8 4f 5e 03 fa +2c 0c e4 78 5b 26 ba 92 e7 5f bd c1 6d 8d 4c 7f +b0 bc 39 a8 8e 13 2e 1e 05 ad 00 f1 2f 07 27 06 +34 3f 5e b3 da b5 11 2e 3b be 76 ed 0b bc 7b df +cf + +# PKCS#1 v1.5 Signature Example 9.17 + +# ----------------- + +# Message to be signed: +7a 76 44 00 1f 80 13 c5 0f d7 17 b2 44 65 47 7a +bc 34 ba 9c 1e 53 ad 76 32 64 5a 6e f7 c8 e6 4e +8e cb 7b ca 5b 4f 09 b5 2f 4d d4 8f 8b b3 dd 33 +8c 78 18 2c e8 6e 8b fb 1c 68 a8 76 f7 32 16 63 +06 a8 ea 8c 0d 7c 21 ff 26 fa af 4a b4 55 10 36 +19 50 c7 6f 95 c2 73 0b 9d 3e 4d 6d 85 ea 25 58 +4a c9 67 a0 2b 1e 0a 26 + +# Signature: +03 b2 ac cf ef f0 63 bd 17 5e f8 ae 0c b8 5b db +80 0d dc 27 77 6f 8d 3d c7 e2 1d 19 9b b8 d6 5f +5b 24 2e 79 d4 5e cd cf f0 2e 80 3f 56 81 ff 04 +4a 43 b5 5a 9a ac b1 ea f1 67 84 83 8b 1d 5a 2b +7c 1a 36 4d c4 05 31 1a 65 55 05 7e c7 3f 0a 8f +4e 0f fc a4 23 02 2c a6 ad 74 46 9b bd 55 57 bf +a1 cf 4b 95 63 6f 53 45 37 ef f2 fb 16 af 5e 64 +71 82 4a fe 21 67 91 8c 89 ad e0 1d 52 ae a7 39 +9d + +# PKCS#1 v1.5 Signature Example 9.18 + +# ----------------- + +# Message to be signed: +12 d2 24 fc 10 a0 fc 40 95 3a b6 d7 01 c4 16 c3 +a8 23 77 2b ea fa + +# Signature: +03 2c b5 c8 d6 12 90 b7 66 e6 49 8a a6 01 49 4d +9f 06 6f 27 a4 7a 28 70 f3 67 89 43 29 1a b2 2d +3c 45 c0 76 e5 60 81 9d 33 f8 89 f8 cf ab 2d f6 +c6 3c 0c e1 ed 5c eb 51 54 70 77 c0 82 78 18 7a +82 72 fe c7 de 95 54 cd c9 16 ca 72 f2 c4 51 43 +f2 cf 32 43 c4 bd 20 0c 6e 99 3f 0d b5 b7 1d 4f +63 77 1e 24 9b 19 b9 97 a6 e5 a9 19 ca 10 0c 90 +fe a6 a2 d4 dc 68 81 c3 a0 e1 c1 35 53 83 cf bb +4b + +# PKCS#1 v1.5 Signature Example 9.19 + +# ----------------- + +# Message to be signed: +e0 d4 e2 a5 e9 8a 51 23 7d a5 08 5d cf 09 8a e2 +c0 5b 4e 16 92 54 ee 6d da 16 21 0e 4a 3f e8 1c +72 56 ea ef f2 8c 0c 63 d8 54 b7 84 1a 13 6c 43 +60 b2 15 dc a0 58 74 8a 4b fa 82 58 68 04 28 21 +99 2a 4e d5 a7 d5 8f 80 12 20 75 49 be 8c c9 ce +cc 85 01 b9 f8 02 83 0f 86 58 45 ce 2e 33 9b ec +28 05 96 11 a1 a0 0b 55 35 c3 c6 15 e9 d2 a1 39 +59 f1 01 5c 8b ad 2d 75 3a 59 a6 14 3b 3a 30 58 +ef 72 25 60 ff e1 c1 84 87 c7 41 da d6 1f 07 a1 +56 42 e7 26 ad 18 a9 84 87 5e 68 c6 2e eb ed cf +94 6f 13 b8 93 b2 80 8f 78 f9 29 48 07 d7 74 68 +54 94 e6 b8 90 40 ee e6 de 1b a7 18 ba 2e 08 2c +3d 5e f1 7c 10 28 cd 66 + +# Signature: +03 e7 83 bb 53 db b6 7c f2 19 5f c1 a5 7f 4b 74 +c9 82 03 b1 f3 d6 15 fe b9 20 e4 ab e8 37 58 34 +67 2f 4b 8f 55 fe f2 ac a8 b5 d4 0a ef e4 ef bd +aa c3 e8 21 08 d0 7f 2f 1c f8 c0 d4 df f8 1b 39 +66 ec 69 be 51 17 ac 1a a6 11 8e 46 0b 92 d8 8f +cd d9 4d 08 eb aa 53 62 e5 9d 52 00 4b 43 36 95 +14 37 da 0f 51 d6 3e 50 56 15 b4 b7 55 54 08 0b +94 89 7f ef 29 3a 34 c4 04 00 c4 f9 9a a1 de fe +35 + +# PKCS#1 v1.5 Signature Example 9.20 + +# ----------------- + +# Message to be signed: +64 b3 ba 40 98 03 c9 b9 60 c1 c4 96 2f 51 27 1b +c8 9a 40 bd 40 5c e5 bc dc 88 51 d9 7c 9b e5 e5 +b7 46 4e 50 d9 9b 6c f8 ad f8 ff 83 2b 73 7d e8 +b6 ff 1a be b8 9d ba e9 3a 90 63 94 87 80 6b 05 +96 cd 31 68 60 f6 8f 00 27 a3 50 3e 15 89 67 af +df f4 69 07 68 17 fc 7d a3 22 3c ca 1e 6c 48 97 +3b 57 0e 0b f7 4b b8 b3 96 54 37 2b 7a 1d 6f + +# Signature: +00 d2 00 eb a0 b6 52 2a fb 42 0e bf 16 48 8c 53 +03 52 c4 2d de 81 e7 64 c0 ca db 43 82 8c b9 98 +d0 a6 0b 23 b5 b6 95 8a 00 fc 25 53 e2 35 e8 57 +4e 4d 4f ec 9e 66 8d ba 40 de 66 61 ab e1 3f cb +84 c1 ad 15 c4 b0 cc 0c 6f 4f 0f 83 77 87 c4 32 +5f 04 5d 61 ee 2c 99 72 b0 1f 32 12 65 4e c4 26 +62 56 7f aa c4 0e 9c 0a 28 15 8a 2a 6c 31 f0 1a +84 91 26 df 9e 96 cb 82 09 be b5 81 d6 84 6b b5 +ab + +# ============================================= + +# Example 10: A 1028-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +0d 5f b9 9f de df 42 56 e2 8d 4b 41 d7 07 fc 27 +63 3e 89 95 15 f4 da bf 6b 46 27 10 ac 11 25 81 +fa 73 fa 83 69 58 2c 9f d4 52 5a 70 16 18 99 df +63 25 84 9e 5c 43 49 3e 13 35 4e 27 09 55 a4 3e +38 35 b5 99 8e d4 2a 57 5b bf 68 8d 69 ec 36 6d +2b a6 f0 50 4c 1e e1 7d c5 9b 7e a0 b4 64 0c be +cd 8b d7 96 2b e8 56 6f 0e bd 65 57 43 65 6a 29 +12 85 e0 37 bb fa 86 55 80 1b d0 31 4f 46 4c 56 +91 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +0d 5f b9 9f de df 42 56 e2 8d 4b 41 d7 07 fc 27 +63 3e 89 95 15 f4 da bf 6b 46 27 10 ac 11 25 81 +fa 73 fa 83 69 58 2c 9f d4 52 5a 70 16 18 99 df +63 25 84 9e 5c 43 49 3e 13 35 4e 27 09 55 a4 3e +38 35 b5 99 8e d4 2a 57 5b bf 68 8d 69 ec 36 6d +2b a6 f0 50 4c 1e e1 7d c5 9b 7e a0 b4 64 0c be +cd 8b d7 96 2b e8 56 6f 0e bd 65 57 43 65 6a 29 +12 85 e0 37 bb fa 86 55 80 1b d0 31 4f 46 4c 56 +91 + +# Public exponent: +01 00 01 + +# Exponent: +e7 6f 42 b4 74 02 d5 e0 f9 64 64 92 5a b4 b3 bc +68 94 30 0e e4 86 fb 70 ce d4 91 f2 d1 b3 67 80 +84 c1 c2 cb 96 95 68 a5 f7 7d ab cd 40 93 39 37 +a8 67 f9 34 fb 2a ea ae 6d 78 67 98 e0 d0 4a 10 +6f 54 5e 41 a9 c9 38 33 d8 1f d4 d7 53 53 17 9c +b0 bc a4 5e 79 aa c9 41 34 64 b0 36 7f 31 ac 5a +ca 56 6f 22 14 bf 51 46 a9 48 4b 87 e4 2b da c2 +b0 1a 99 67 03 50 6b e0 77 49 aa 0f be b3 b2 29 + +# Prime 1: +03 ff af 4a 61 21 d7 42 0c fd a6 4c 41 71 2f 47 +c8 f2 d0 d2 5b 17 e9 5b 35 41 42 84 69 10 af ef +bd f2 1e 74 23 e8 b3 be 44 ae d9 af 5e 49 81 68 +5d 3b 9a 1d 59 c9 b9 47 fb 9c 33 9c 9a 31 e5 7b +d9 + +# Prime 2: +03 58 31 e3 b9 29 3b cd a4 51 be 9d b1 91 97 48 +6a a2 e2 2e 92 98 65 0f 2b 7f f4 25 69 eb ec 33 +d2 0a 34 98 44 a3 3b ea a0 93 d1 43 4a fb 4a 04 +a0 4a ed d3 bb c4 b3 87 77 a5 5f e6 50 5b 8c 15 +79 + +# Prime exponent 1: +02 8e 91 d5 ab ba 69 dc 50 56 38 e9 f5 c6 9c 06 +f8 d5 5a f5 c7 4d c8 e7 8b 6c 09 4e 85 a8 27 f7 +d2 ab 69 11 b6 8c 6b b2 b4 54 61 d9 a3 1e b9 62 +b4 8b 12 06 c6 8d 18 ae 90 92 d6 e5 c2 2b 39 a4 +31 + +# Prime exponent 2: +02 98 04 e1 32 fa 3a aa 4b 15 26 bb 50 3a b4 d4 +71 f7 6f 69 65 42 11 a6 89 3b 0c 13 74 29 87 9f +cc f7 23 41 30 82 54 76 ac 20 d7 fb d3 8c 3e 24 +86 58 76 48 6e e8 a7 bf 99 58 45 9e ee 95 81 78 +29 + +# Coefficient: +02 11 97 5e 88 56 d4 ea 9d 1d df 87 b8 7d 39 79 +2f 1c f7 e2 f1 82 f4 a4 e6 91 e5 00 2b 10 a0 8a +46 dc a1 a4 f4 83 00 85 d8 d4 0b ea 1d ff 11 b0 +c0 df 20 22 43 eb 99 3e 58 0a 94 49 9b 9c ed d2 +be + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 10.1 + +# ----------------- + +# Message to be signed: +b2 d5 88 50 9c 2e ac da 28 1e 76 71 cb a2 fc a9 +14 ef 73 a3 ae a9 20 20 43 ea d6 b7 21 25 c1 b0 +d5 cc 15 41 46 20 d5 73 d7 ab 0b 3a 8a b6 6a 92 +df 87 0b 75 b1 c4 d6 8e a7 05 6b e0 41 9e a2 53 +e6 b0 8b 12 9e 0f 64 f1 0a bf 82 e1 67 f8 e3 e9 +28 2e 7b f7 1b 04 3b aa 2b a2 d8 75 6d 46 b6 d3 +6e 97 34 15 f4 f8 c0 eb 43 fc 60 4c ed 49 3d c0 +46 a2 5a 11 9b d1 58 1d bb 59 7c 3e 67 c2 fd dc +39 6d f5 d2 3b 7b a8 0b d2 e3 12 90 bf c2 62 25 +e0 09 55 a9 8d 91 19 11 a3 99 67 6f bb + +# Signature: +07 9a 7b 91 6f 67 41 17 f1 d8 77 f4 93 43 25 68 +41 48 d5 d0 b0 d5 c2 c6 15 6a 11 15 9b c0 bd 30 +d0 a7 35 34 dc 94 45 eb e2 06 d6 07 5e b4 ea 7a +7c 04 32 bd 44 b8 3c fa e4 68 5a 9e b9 a9 7c bb +fa 4e 82 f7 1d b5 1a fa 0d 27 cf 27 f0 60 9b b3 +f8 80 64 13 24 7d 5d 49 54 f7 89 a1 01 bf 39 21 +72 8b 48 7e 85 fa 3f d4 dc d7 2d 04 44 8e 42 d3 +ec 05 cc 47 5d 74 cb f7 65 c3 4e 3e c1 4c ca 50 +40 + +# PKCS#1 v1.5 Signature Example 10.2 + +# ----------------- + +# Message to be signed: +ca 25 18 a5 a2 24 b2 3d 42 05 d8 dd 7e b0 4c bd +cd 0c cb 82 bc 87 96 1d 85 9d 66 00 b1 ac 3e 25 +a9 40 7b 6c 06 50 27 c0 40 81 f4 45 a2 30 ab 93 +08 e7 55 f3 3a 75 97 73 be 6b 96 9e 0e a7 74 aa +6e 33 4f b6 04 18 42 75 f3 6a 03 1d ae a6 51 86 +97 79 5b d6 a7 d6 69 7b 40 6d a2 ce ce 15 dc 11 +3d 85 44 98 85 61 13 1d 4f c6 f6 e3 c5 80 d8 06 +80 7d f2 c6 85 65 09 54 2e 4e d3 9d 34 6e ba 15 +97 6a 8f d0 1d 79 41 b0 16 56 06 c7 61 76 64 9a +16 10 05 a0 + +# Signature: +00 be b9 21 ce 74 89 81 9d 2f 85 c7 88 39 a2 7d +7e 19 ea 0a 76 4a c5 31 01 e8 6f 31 70 a7 6e 31 +8a 7e e8 9b 1f 5e 23 e7 e2 db 96 66 eb 43 91 b2 +79 2a 57 67 ee 35 9b 5c 71 e2 74 79 10 c8 2c 60 +83 d6 d3 48 29 b9 6f a5 a2 ec 0f 62 f1 bc da 5d +78 f8 dc 3c 65 0b 94 e3 2b 38 60 da 5f c5 b1 7f +bf 68 7e c0 07 5a 9c 73 dc 1e 98 d1 f3 6a ae c4 +49 3f 78 91 e3 ab 08 e2 04 2d 8b 1e 46 2e 8c 4c +33 + +# PKCS#1 v1.5 Signature Example 10.3 + +# ----------------- + +# Message to be signed: +d4 33 d1 5b 2d 61 b8 6a c8 ec 0d ae ba 65 e1 1d +ed 3c 38 84 25 25 e4 b7 c8 e4 53 b0 f5 53 cb 4e +b8 75 a6 9d 78 16 f5 4c 87 79 3e 3a bb 79 fc 55 +11 35 37 b4 76 29 65 cf ee 58 6e 0a 17 99 78 51 +e3 dc 9e af 6f 1c 9c 2e 98 c9 61 3e 3b be a0 13 +ff 58 61 6b 2a b0 5a b3 24 a9 c5 ff 4c 5e fd d9 +90 dd 97 d9 16 93 c1 eb d4 c0 9c 73 21 16 c8 df +c3 ec 51 5c 20 53 2c ba 7e 47 58 c6 8a 69 cf a0 +ac 31 86 + +# Signature: +03 ae 3b e1 c7 44 6a d3 ef d8 ba e6 1b 3d 32 d3 +ef 15 24 82 b1 bf ee 31 2f e9 e6 be ee ab 8c bd +08 f4 c8 f9 cf 06 7d ea b6 ba c7 c0 fe cd 87 bb +ab c7 f6 79 8c 77 ef 1c 3f d8 bc a2 8c f9 ec e6 +56 79 5f 60 b3 78 75 ea be f8 21 53 a1 2b c7 fd +e3 fb c9 e5 e1 48 f4 e1 6c b7 2a 77 3d 9d d0 23 +17 f7 0b 33 91 40 08 05 e8 5e 7a 23 56 7b 34 aa +65 a3 5f 74 41 70 af fc b3 23 37 1a d2 ab 9f 1e +4d + +# PKCS#1 v1.5 Signature Example 10.4 + +# ----------------- + +# Message to be signed: +7d 0f 5b d7 90 0f 1e 65 65 4e 6c 7e eb 06 4c b8 +28 f3 55 d6 de 9b f0 d3 47 83 ff cb e8 0a b1 b8 +ae 07 b7 f1 e3 f5 a3 20 dd 9b 8b 76 be 0e 97 72 +de 19 a8 d3 + +# Signature: +09 e7 a5 30 41 71 da 63 8b e7 60 1f bf f6 e4 95 +36 f3 36 60 82 25 3a bc 1d b5 d1 b6 54 93 da 59 +5e c9 3c 37 f5 89 0b 5f 47 15 bd 5e 80 c0 bb c5 +c6 3b 74 af 2e 60 43 91 32 d2 52 13 75 0b c1 de +30 2e 3e 8b 83 da d2 de 0d ff c4 fa ab 40 56 dd +7c 40 5e 04 d5 94 24 53 65 9d 49 0f 3c 3d aa 7d +3f 11 70 11 81 6b 56 59 01 04 de 7f 9c 05 23 73 +e2 dd e4 14 49 04 27 a5 89 64 49 3f f4 5f 08 a6 +e8 + +# PKCS#1 v1.5 Signature Example 10.5 + +# ----------------- + +# Message to be signed: +d9 6a a0 91 c1 60 b5 52 b1 6d f0 65 8f a8 + +# Signature: +0b 69 75 4e d6 d7 a7 d2 d8 5b 2c 7a 30 6c 78 d6 +3d 0f fa 43 8f 43 be ec 3a 02 86 ce 57 e7 e0 f8 +5c a4 30 e6 39 08 c0 fa 58 4b a2 50 5f 8c 94 65 +6e c0 24 94 bb 03 2f 92 0c 4b 6b 8c 94 3e 6b e9 +2f 57 8a a8 cc df aa c0 a5 4b 8a 9c 0d f5 48 27 +1f 89 73 c9 ff a2 a2 0c 84 76 2e 90 17 e7 45 2e +5d 74 da 69 0f 75 c0 99 ab 91 e2 a7 96 3b c5 37 +f9 c2 4c cc 3c 41 8c 6e 98 58 61 d9 3d aa b2 e6 +13 + +# PKCS#1 v1.5 Signature Example 10.6 + +# ----------------- + +# Message to be signed: +56 f0 48 64 5a 49 fa 01 41 f4 d6 74 aa fc f2 ff +fa 83 f9 b4 52 f1 fe ed 43 05 7c ac 27 67 5e a1 +a1 41 d8 7f 92 f9 ce bf 6e e4 f7 8f 8e d4 c3 a2 +9d eb 72 97 47 b4 f9 8e 4c 75 90 aa a8 d5 6d bc +61 d3 8c b5 62 22 26 f6 8e 43 f9 c4 f4 c0 39 98 +ae e9 09 34 39 5b c8 40 c8 6d cc 88 74 77 6f 43 +03 9f 56 a8 9d 24 bd c4 b3 05 df 09 e5 ca 0c 05 +12 ad 6d 15 71 91 9a 3d b3 a6 bd 98 b7 82 0a da +08 69 d2 25 a4 04 02 7a cb 6d 76 7f c3 14 db 37 +7e 8d 1d b6 ef 0a f2 94 54 db 2b d4 c1 ce e0 13 +a5 97 43 48 6d 32 32 95 83 cf 80 11 3c da a1 0e +4f 2c ea 6c 4f 9f c6 e4 e2 71 6e de 85 72 7c 3a +fd 43 49 46 09 77 76 30 ee 33 63 7e a3 5c 9b 4f +68 8e 49 2c 3c 64 0d + +# Signature: +06 66 ef 71 e2 c8 a1 eb 1c 46 40 3f d2 3e 52 18 +83 ad a1 b9 bc 5f bd 35 3b bb 3c 3d fb 57 0a c1 +c7 21 fa f3 f5 97 32 f2 13 37 73 80 39 79 48 46 +2f d2 0a 3f 0e 5e 08 91 a6 b0 7c 31 b3 60 aa a9 +65 e2 f0 93 0e b3 41 ee 77 ec 43 90 65 c0 aa d9 +17 87 ab 6d 2e 6c de dd f5 54 81 65 1a eb bf 9d +11 d5 4b c1 13 26 18 3e bf f4 9b d4 0b df 76 d7 +ef 69 b6 7e a3 96 8f a8 49 03 2f b8 24 b6 dd 6a +e3 + +# PKCS#1 v1.5 Signature Example 10.7 + +# ----------------- + +# Message to be signed: +79 da 89 e3 55 d5 51 a0 e0 31 f4 fb 71 ab 6f 41 +44 c4 76 2e 07 d0 64 14 33 cb 5e c8 61 34 96 3f +7d 2c 4d c7 be b5 c6 d4 61 57 c6 c4 e1 4a 4b 9c +7a 2c 0d 46 0f 1f c0 62 ea 1b 4f 98 74 d5 b1 c2 +9a e2 f2 a5 b3 90 62 e4 12 12 e6 5c 85 c2 8e 76 +75 89 96 5d 17 10 ad 5b c7 6f a5 a6 72 9a 06 fd +49 6e 2e 09 97 e5 73 37 bd 51 6e 6b c7 9b e9 e0 +70 aa 7b 86 c2 dd f1 4f 94 98 5f e1 58 2a 29 2c +d1 39 34 b3 c3 8d fe 59 77 ed 1d 9f 8a d3 24 c0 +dc 07 e5 85 3c 7e 48 90 bf bd c1 a0 1e cd 72 c5 +ff 68 a0 2f 1e + +# Signature: +0a 06 82 f7 42 e7 43 e1 c7 da ba ac 61 8a 78 6f +28 ed 13 a6 58 7a df c3 3c 98 29 d7 52 c1 3e f2 +7a 00 c7 e6 d4 5e 27 17 1a 58 41 77 1d 78 69 8c +6c c6 67 78 b8 c0 93 38 e3 5b 9b 6f 59 c0 64 ce +b3 eb 20 ce 90 9a 5c 6c ea ae bb e9 3e 86 c7 c5 +ff 4a 39 17 f1 26 81 96 32 cf 96 fa b1 d3 91 73 +a7 ae 7f c2 ff 5c 0f b4 09 05 35 da db 58 d8 7d +0d a3 db 32 ec ec 13 71 8b 3a c5 c3 0b a8 02 e3 +8b + +# PKCS#1 v1.5 Signature Example 10.8 + +# ----------------- + +# Message to be signed: +e6 9a c9 43 3e 6c 28 ac 53 f8 03 4a 86 8d a9 88 +3e 31 9e 82 e6 bc 2e 49 45 5e 6e 4f 09 8b 53 f2 +87 a8 58 da 1d 87 6a 9a 5a 6a 9f c1 4f d2 42 38 +cd 4e 4b 57 31 07 7a 4d bd d5 03 8a 9b c1 f5 de +f4 3f ec 77 f6 7e b0 62 fa ef ef 7d 04 29 23 8b +25 d0 31 85 78 96 62 3a 3f 1d 37 bf + +# Signature: +08 a0 20 e4 20 98 78 f1 e6 37 ad 59 da af 83 5d +af 4c a6 64 84 47 94 c1 c6 48 f0 e2 23 3d ba 75 +48 bd 16 1f 0c 0a 18 24 d7 62 03 1a 41 75 72 84 +2f 8e 64 4a a9 3f 9d 91 dd 77 09 e1 6a 42 9c c1 +43 90 3e f4 f8 37 a4 58 39 6b ca c2 40 92 b0 17 +24 c6 fe 3d d1 ad 24 3f 3f 70 b5 ae 6f aa 09 f3 +70 ca a5 12 10 4b 91 76 06 0d f2 bf 12 1c bc e9 +19 8e c2 fe 45 a5 9e bd dc 46 75 32 b5 af b9 b2 +35 + +# PKCS#1 v1.5 Signature Example 10.9 + +# ----------------- + +# Message to be signed: +45 e0 90 56 a2 8e 4b 2e 7c 11 f6 5e 68 8a 1e 3c +33 f0 e5 2c 9a 03 6c 09 d8 1d e5 a6 da b5 8d 4d +55 cf 41 1b 53 ad 64 6e 83 a3 4b 0c 08 c2 21 ae +03 76 ab 76 a7 9d 1f ee 67 1a 58 44 20 56 4f 8e +85 2e b6 f2 d4 27 ae e0 a0 96 dd 72 db e8 50 7c +67 7f 8a a0 0e b7 c2 5d fb 0a 49 dd 88 a6 c7 84 +76 b8 00 11 b6 82 8b 3a af 46 47 79 44 22 ba 6b +d6 3b 7a b0 e7 da fb d3 6f 6c 41 de a0 3d 73 22 +35 64 96 94 60 d9 28 54 0b 73 92 57 e7 0b b6 8d +5c 65 3c 37 96 94 58 95 + +# Signature: +08 71 7d 50 86 a6 45 3b de ff 77 d4 c2 b8 56 e3 +ba 99 0b ab f6 97 01 df 6c a0 a3 b3 a8 1b 55 69 +7d 31 88 9d 10 0d 68 95 c9 7f 0a 56 b4 71 68 c9 +8d a6 2e 59 ec 79 d7 ae ab 2f 9a 57 07 46 98 8a +26 f4 23 57 6c 70 3f d8 41 ae 51 c9 c2 29 a2 e9 +c2 5f e9 4c 5b 6c e2 fa 64 54 12 be e6 59 fa f6 +09 a3 2e b2 c0 5b ee ab aa 4f 58 ca ac 31 33 e5 +ea aa 27 34 4d 30 ee ca 22 c6 eb d8 d9 e3 44 41 +0e + +# PKCS#1 v1.5 Signature Example 10.10 + +# ----------------- + +# Message to be signed: +b8 1c 8b c4 ac 1f d9 71 b2 1f 02 7e 06 f4 d8 7b +34 d5 76 9d 23 c8 59 9d 1f 15 7b 08 a7 f9 2e 34 +19 fe c4 c8 c1 b3 4c a4 63 c7 68 b7 2e 07 f9 da +bc 3c bb dd 8b 56 17 cc 25 28 75 00 2a 1a 13 92 +af 0f af c0 8c 72 11 75 8f 3c 04 20 50 ad 73 1b +63 6c 0e 83 19 1a 79 de 5a a2 cb 94 dc 8b 0b dd +e7 5d b7 d0 c8 ba fb 42 23 d3 47 b0 24 b3 d9 c6 +b2 39 61 9b 5d 8b 63 46 ea 86 fb 8f 24 c5 84 dc +1a 47 79 1c b7 c8 c7 eb f1 ed 43 8b 88 + +# Signature: +01 b9 f4 33 94 c7 cb 88 5b fd cc 3c 84 96 22 23 +e8 aa a9 4c 6c 9b 79 05 40 1d 24 f0 dc 44 3b 2e +8d 84 0e 28 a9 5f a2 2e 1a e3 6f fe 08 96 6f 38 +d3 87 14 cf 68 da 8d b2 37 64 b8 8c 4b b2 be 4f +d3 da 9c cd 1b 50 69 42 aa 9d 73 fc 09 38 2d c3 +30 83 14 70 6e 6c e2 7f 00 76 1f 3c 9b d5 4f a0 +e3 1c 96 71 9a fb f0 76 3e 35 ca d8 89 b7 2e 13 +bd 12 b7 6d 6f 20 20 fa f6 1d d3 d7 08 22 8d f0 +6d + +# PKCS#1 v1.5 Signature Example 10.11 + +# ----------------- + +# Message to be signed: +d0 32 28 83 e5 98 16 3d 72 20 36 da 3e 63 2a a6 +55 97 ac bc d1 f4 76 03 10 96 96 f9 b3 9f dc + +# Signature: +07 8d 17 ab 8e 6f f0 be 50 b3 53 9e b0 3a e8 f0 +90 3b 7a 07 74 81 78 1f b0 b1 f0 9e dc f7 78 86 +31 2a d6 c0 60 27 4f 0c 38 9c 16 31 40 40 c8 d7 +d9 90 9c b7 5d f1 8c 82 d6 2d d3 4e b5 9c 6a 87 +d3 c4 6a 7e f7 47 4a 5e 44 7f 77 44 a6 a9 2f 59 +90 ea ec 7b fb 00 84 4d 68 4d 30 7d db 49 81 89 +41 49 e7 52 bf be 2e 77 05 7d a7 60 54 69 af 7f +fb 67 27 a9 98 1b 94 39 ca a5 d8 0e 6a e3 b3 d6 +51 + +# PKCS#1 v1.5 Signature Example 10.12 + +# ----------------- + +# Message to be signed: +e8 74 2f 04 b5 65 4d 92 88 b2 31 a4 7a 36 58 39 +bb 01 be 87 + +# Signature: +09 b7 53 06 a7 21 2e a6 f4 7e b0 cc f4 e2 e0 d6 +f8 f3 ab db 9c dc fa ad be 51 92 2f 92 ea 62 62 +3c 58 ea 74 ea 1a 24 7c 9d 73 1f 2c 03 35 36 b3 +52 73 c7 17 49 5f 32 5a 60 40 5b d5 f5 e4 05 b6 +80 27 9e 75 21 60 47 87 40 45 72 16 dc 92 9d dd +65 de a5 05 53 55 46 e4 77 0f 82 11 b8 49 c3 65 +21 8e 56 6e 5b b4 1b fc 36 1b 65 cd cc b0 e6 04 +c9 ed b9 70 ee 6a 28 6a 1f ce c0 ae 9d 92 55 8e +ab + +# PKCS#1 v1.5 Signature Example 10.13 + +# ----------------- + +# Message to be signed: +a0 3c 2b 85 fd e4 64 68 d1 c5 06 37 b0 0a 72 dc +fc 32 c4 16 31 73 9c 06 02 45 f5 3e 57 c6 6c 51 +76 6f 24 ea fd 93 e6 c6 67 43 48 05 91 bf 14 44 +6e 04 0b 67 a4 f8 46 99 57 6c 2e 14 63 ca cc bc +b0 73 e4 b7 ec 6d a6 c8 cb 41 d4 a1 23 c7 48 cd +7e 83 d2 61 e5 4c 2f d2 bc 49 5b c4 c4 4a 78 f9 +82 00 34 03 09 2e c6 96 0c 08 8e 2b cd e3 48 a2 +e0 e5 5a 4b 4f 42 ea b2 29 b9 5c 38 3f 21 13 ed +6c d1 f3 f3 16 7d e3 d2 8d 36 2c 8d 78 b2 eb 6e +31 62 0e 34 b2 f0 f9 41 da cd f7 b4 b8 56 8c 6a +86 3a 55 1d 7b d4 a5 d7 09 3e da 69 e1 e2 80 56 +dc b1 eb 69 ae 03 ad 74 be 72 a7 5a e8 fb 56 a2 +71 25 ca 3d 2d b3 76 9d 13 d3 5d b1 08 e2 64 4a +7f 3b 37 93 8f ec 97 62 31 52 06 d3 0c cf d5 76 +ae 7d e0 76 98 69 e5 04 4d 07 64 6c f7 8c 64 a4 +86 48 0b 0f d4 2c c7 b2 46 + +# Signature: +05 8d a5 49 4c 4e 98 aa 12 1f 67 f6 5a 2c 86 54 +25 a9 e6 00 2b 22 3f 03 88 80 97 53 57 3b 4f 33 +4d e4 5d 8f 00 07 25 5d 11 2d dc 84 db 26 67 00 +e4 40 b5 a8 69 00 c3 d3 d3 5b 02 4c 18 d8 a2 5a +58 00 22 6d 0a 56 d8 38 d8 91 9e 6d 5a 87 30 d6 +19 49 90 15 ec 46 65 c6 3d 77 80 83 a0 42 dd 4f +05 2a 1b bb 5f 40 80 cb bb 41 fa 94 5b ad 6a 74 +77 9f 68 07 25 e4 7a 08 a0 51 4f 35 0f a5 ad f9 +0a + +# PKCS#1 v1.5 Signature Example 10.14 + +# ----------------- + +# Message to be signed: +c4 0c 70 f2 6d a5 69 48 6b ac e7 85 da 32 e3 37 +a0 eb 94 fb 3a 0a a4 09 c5 77 01 75 c8 e8 cb 2b +aa 8d 2a 1b 98 46 c3 7d f7 d6 71 03 6d 5e 91 + +# Signature: +05 25 61 28 af ba 1f 55 d8 1f 79 ea 33 87 91 47 +a2 4a d7 77 93 46 ee 79 8b 21 1c 24 71 53 ea 38 +d2 6b 21 70 65 f6 1e 01 10 b5 3d 72 cb 64 93 4d +9b 1a d1 b3 de c3 32 09 2d 25 8f 0c af 1c 4a ee +8b 23 e0 9b ab 0f 0c 27 88 58 b4 41 d0 8c a3 ae +9f 00 aa 9a 3f 01 8f 7d 9f a9 8a 18 df 0d 24 84 +7e 56 7a 47 f5 77 9b d1 79 3a 4b 02 52 f2 ba d4 +0c 9c 4a 81 30 1c c2 8c 26 09 d7 bb 33 37 e9 7f +14 + +# PKCS#1 v1.5 Signature Example 10.15 + +# ----------------- + +# Message to be signed: +9e 6d cb 11 e0 e8 47 71 39 fa f0 41 a7 4e 2b ed +64 3a 62 ad ed ac 7c be f3 65 ec c4 3a e4 e5 82 +60 bc 72 46 23 bd 63 42 dc 66 0d 66 14 2e a6 36 +80 71 5f 52 2f f3 cd 4b 63 6f 84 aa 9d 75 fb fb +c3 84 10 7e 43 00 4d 98 6f bc e1 a2 7f 7e cc 7d +02 39 2c + +# Signature: +0c cf 23 4e b4 80 08 5d 92 0d 37 d6 87 96 5d 2f +d2 e4 a4 f3 bd 3b f7 dd c1 6b 5d 62 a6 90 32 74 +20 7c 6f 90 83 6e 29 ff c6 3a 57 f9 81 30 c5 25 +23 25 19 c7 08 f0 dc 8a 12 55 ab 55 db 1a 2b 9a +bc 11 06 16 02 07 5f f6 f9 7f 90 92 79 6b 98 87 +1a 6c d5 d2 61 7d dc 9d 25 5a 73 00 c9 10 fd 21 +0b 14 a9 81 e5 a0 e0 c6 bb 2b 04 5f a9 75 68 98 +b9 3b 8a 63 45 44 d7 7a fd b1 cf 0e 79 58 f1 1a +43 + +# PKCS#1 v1.5 Signature Example 10.16 + +# ----------------- + +# Message to be signed: +20 bc 46 3b 5e 12 20 a3 9c 84 e8 9f e6 71 6e ec +ab 55 55 f8 bf ce 60 cf b8 37 93 cc 40 a4 da 1d +22 c0 ab 4e aa 93 1f b7 47 be 35 f1 cf 6f b1 46 +5b ef 1d f2 76 0f cb 3f 70 d3 e2 96 e7 b2 70 45 +0d ff e2 d5 88 c4 39 6a 5f 6f 1e 63 87 aa 86 97 +1f b0 ad 24 df 55 04 43 dd 12 2b db 2c f3 c9 ed +61 25 fe 55 ce c9 91 cb ae 8e e1 56 2a 8c 0f 4f +36 4f 8f 0a 80 cb 30 fd 99 44 0b f6 55 f0 80 4f +92 96 8c a2 e0 1c 0d 5a bb 4e e2 67 63 6d d4 f5 +11 a8 d3 29 41 16 21 6b ed c1 08 86 45 e4 65 d8 +e1 98 b8 af e1 cd 54 24 b4 2a 53 3c ed 19 8a d5 +97 + +# Signature: +05 1b 71 42 66 06 6b bb 81 9a 2a 38 05 a8 9c ff +46 18 75 c0 95 f4 f3 89 82 d1 af c2 ad 2f 14 24 +50 b8 a7 52 94 7f 03 1c ce 2c 9c 34 0c 8a c9 f9 +f7 a5 48 b7 cc 17 e4 cc 52 56 96 ea 0c 87 53 a1 +e1 5b cb 98 5d ea ec 77 6f b9 e7 d9 f7 58 62 f8 +98 35 23 d9 f8 71 c6 3f b7 56 1a c7 1c 37 6b f4 +95 d4 32 38 59 bd 14 18 8f cd fb 4b 37 ab cb 5d +c1 a5 8e ed ea 7e 0f e6 2a c1 6e 20 8a ab 4c ee +26 + +# PKCS#1 v1.5 Signature Example 10.17 + +# ----------------- + +# Message to be signed: +92 da 26 0b c2 13 b7 2b 48 a0 57 53 50 3d 00 a1 +db fd 02 ac 7b 9f d4 4d 24 01 ea 7a d5 8a d1 86 +1f da 53 63 29 ae 41 73 c9 16 80 05 b9 66 2c 05 +cb ea 47 ad 86 4a f7 cb 16 60 2d 3d 18 34 71 bc +98 bc c6 2c 6d 00 d3 34 bf f5 b9 0c fe 7d 7e 12 +d0 7f e7 d4 cb d9 dc d3 c4 c2 34 90 be 8c ba dc +08 c9 17 79 80 37 3c 79 eb 4e ea 6d 81 a6 be e2 +27 0b f4 20 f9 19 79 ad 3f 27 1f d6 8d d4 28 3b +e8 14 10 92 8c a4 5b 9d eb 58 d3 ae 98 b2 f4 fc +a6 21 25 95 0b 5e e1 28 db a1 05 c3 5c c3 98 d1 +5e 74 2b ba 92 69 7b 5c 62 b2 67 ce 01 14 1c ec +ef 80 75 07 de 29 c4 85 30 5d 0a 99 09 43 23 0d +8d 9b 72 52 ee 0b 19 56 de 84 5f 2f bb 28 38 78 +5b 47 0a 7c 20 53 db 39 6b 31 5a 30 d8 a7 f9 1c +ff fd 03 e8 a3 9b a8 bc + +# Signature: +03 e2 3f 86 52 37 4d 48 d3 81 c3 78 35 3e b4 7d +90 64 cd 70 8e 1b 9b f6 88 70 4c 04 c0 09 00 88 +46 e6 a4 7e 0b d2 e3 0c 33 40 f5 d4 e1 9d 2d c5 +d8 89 0c 8f 01 04 dd 6f 5d d6 ca d9 c4 d9 94 84 +09 c3 cc 0b e6 70 71 9d d0 48 41 80 89 1c 93 5b +99 79 db 8e b4 68 a2 3e 4e f4 60 29 f3 af 14 57 +4b d1 0b 47 3e dd 9b 12 7a 30 6e 51 24 ad a4 02 +c1 48 f5 1b 52 e7 e6 28 bf ac ec 3f c2 54 3a 0f +92 + +# PKCS#1 v1.5 Signature Example 10.18 + +# ----------------- + +# Message to be signed: +86 03 a5 62 2a 2d bb bc bb e5 33 30 e9 08 d5 a2 +5f 6e 67 a5 1e 07 68 d7 c3 c3 fb e8 b9 2e 8b 1b +36 dc 00 74 3c e3 3d a0 f1 c8 cf b0 0d 63 ed d6 +b2 25 2f b6 72 13 97 d2 50 4b 30 ed 1d 29 3a 82 +e2 44 c9 51 bb fc 24 29 8a 42 ff ee 26 e4 56 a7 +be 10 5c b5 e3 7b 3d 25 de 28 bf c0 10 42 c4 a8 +2c e8 70 45 54 87 e5 b3 0e 26 f8 d5 39 8c 86 12 +6e + +# Signature: +08 22 fc 22 a9 cd 87 7c 09 b6 f9 2e 80 17 cc c0 +28 d5 37 99 67 c7 d0 4e f3 2f 86 9c 7e f6 7d 59 +3c 77 45 f6 29 d9 3d f2 60 03 8c d3 33 ea ee 92 +35 9f db bf 84 62 3b 7b 55 14 23 5b 83 06 27 2f +4e fd 13 a6 70 0b e9 28 9a d5 4e 57 d5 2d 1f eb +b4 6a 37 af d6 95 94 2c 4c bc fd 37 68 f2 82 1e +88 8e fa 0e 2c 5f d3 c9 c4 2c c3 55 50 d7 95 5c +db d3 5c 8e f8 58 1b 41 f8 dd ab 26 18 26 2e 3d +ff + +# PKCS#1 v1.5 Signature Example 10.19 + +# ----------------- + +# Message to be signed: +06 7d 4b ec b0 3e 1e b2 75 ae 22 50 7a 77 a5 39 +6e 71 9b 5f 00 b1 05 95 0b c7 99 8e 08 03 da 57 +a4 de 08 a4 07 8b 9a 00 d2 d4 6f + +# Signature: +09 10 8d 44 57 5f 61 4a 68 3e e4 d7 8b ce 1c 58 +f5 24 36 87 cb e9 c5 48 34 60 b6 5d f2 36 92 7d +bc 78 c0 64 39 ce 1c 7c 51 97 39 c8 f8 95 00 82 +d9 56 d6 0f c3 64 5b a7 af 8e 78 89 54 70 63 1b +b4 da 00 c0 1b 98 2c c1 1c 68 d2 65 0c 7c ae a4 +a2 6e 21 0f f4 b1 ca e1 db 50 5f ce a9 29 34 87 +b2 07 31 78 ca 24 5c f0 ca 23 56 ba f8 65 54 6b +54 af 95 35 ba b1 8d b6 79 ef 56 27 09 29 79 c0 +a8 + +# PKCS#1 v1.5 Signature Example 10.20 + +# ----------------- + +# Message to be signed: +88 4f c5 02 c8 82 48 49 47 8b 2e ac 1e 7e bb b7 +ca f2 8e eb 48 89 45 86 02 ec 70 35 81 d0 5e f9 +b1 a4 22 0b d2 f9 22 f2 5e 46 4c 88 07 01 c8 a4 +5b 1d 1f ab c8 66 2e b2 49 40 04 26 c2 22 62 38 +eb 8a d0 f9 06 9c 90 f0 01 82 77 44 80 25 a6 41 +80 ed 55 d1 af d2 7a ff 4f 00 70 2f 71 5d 29 10 +00 0d f3 92 5c 70 10 ff 11 7f 6d 8d 2a 81 67 09 +48 9e fd 29 a4 5c 59 23 17 7b f9 2c d0 bf 6b 94 +74 5d 34 8a 14 4e 98 74 0f 72 22 6a 3e 2a 9d 41 +7b 7c 1f d8 f8 95 f5 15 c5 c6 d4 06 a7 2b dc cd +39 15 2c 30 fd bd da 0e 62 82 3e e9 df ab 34 32 +e6 64 2e ec b6 98 7b 90 46 e0 40 a4 78 a4 df 64 +8d ef b3 01 6a a4 43 d0 67 a1 fa 41 55 55 53 74 +f8 ba 32 5a 8b 55 e4 d6 b5 fa 09 0e eb ae c9 c9 +2e 26 1c c0 4c ea a4 8b 3b ed 7b 3f 87 d3 + +# Signature: +0b 41 b4 12 19 71 26 15 9e 9b da 1a 24 62 c8 a4 +fd 3d ff dc 6e 98 e4 db fc 06 cf cc f1 6f 74 fc +b5 23 38 af 14 ed 39 36 e0 2c 1d 7e 77 23 6c c6 +a4 89 f0 0f 08 98 52 de 5c c4 25 b4 50 94 a0 42 +e3 85 46 4b 64 c3 b2 ff d0 1f 19 a0 1c 2c 03 81 +f7 58 a6 73 65 d1 e6 5a 70 7b 13 4e 3f 8a 93 16 +b4 aa cb 7e 85 1a 5e ab 3c d8 11 bd 45 22 dd 14 +1a 00 15 7d c3 fc af c4 15 4c af 05 93 ca 62 10 +2e + +# ============================================= + +# Example 11: A 1029-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +1e d7 ee a9 40 5f 50 7f 94 16 23 a1 7b ea 71 7b +86 0d e4 4c b7 76 87 b8 b8 5a 6d 7d 1e f4 f8 62 +8d 25 7c b9 42 38 c6 25 ba 25 d4 6a ae 59 39 60 +af 79 f7 5e 28 ab 63 ac 3c ac 48 20 b8 2d a1 cf +75 0d 6c 93 0d 6b 82 78 54 aa f6 ca c0 c1 7b 80 +b0 29 f5 d3 19 cc ca 66 5c 56 94 f5 4b a5 f0 96 +f4 54 34 13 ec 4c 5e 97 cc 1d da 89 d2 af d4 28 +57 87 59 03 2a df 92 89 50 65 ba af e8 8d 2d 8b +61 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +1e d7 ee a9 40 5f 50 7f 94 16 23 a1 7b ea 71 7b +86 0d e4 4c b7 76 87 b8 b8 5a 6d 7d 1e f4 f8 62 +8d 25 7c b9 42 38 c6 25 ba 25 d4 6a ae 59 39 60 +af 79 f7 5e 28 ab 63 ac 3c ac 48 20 b8 2d a1 cf +75 0d 6c 93 0d 6b 82 78 54 aa f6 ca c0 c1 7b 80 +b0 29 f5 d3 19 cc ca 66 5c 56 94 f5 4b a5 f0 96 +f4 54 34 13 ec 4c 5e 97 cc 1d da 89 d2 af d4 28 +57 87 59 03 2a df 92 89 50 65 ba af e8 8d 2d 8b +61 + +# Public exponent: +01 00 01 + +# Exponent: +0d 93 80 72 b1 6a 02 f5 d5 0a 15 ae eb eb 5a fe +43 18 74 48 2c 6d 18 fa 7e f3 16 c4 7f 4e d6 d2 +12 4c d0 e4 7e b8 9c c7 58 73 74 57 6c dc cb 3b +ba a1 95 f7 b5 31 13 93 69 b5 6f 9e 2f 53 ae a8 +ac 7a 97 e1 d7 45 8f 52 6c f7 d7 10 c4 90 2a ae +df 99 7c 11 94 b8 7b 62 cc d8 da b8 ff 5b 67 d4 +0f e8 3d e1 b8 2b 91 60 9a 7c 5c f3 92 29 eb 3a +1b 2f 0e bf 0b 12 5c b8 00 91 a0 7e bc 77 9c e7 +fd + +# Prime 1: +05 90 a1 e5 18 71 07 fa ef 1e 0c d5 2f a2 dc ad +a2 d5 8a bc c9 e0 73 8f f4 85 0f 7d 2d ee 19 82 +3f 6e 3e 2c a9 11 b7 17 4b e7 0b 15 c1 b8 87 e0 +ae 15 10 21 22 42 2f a1 58 b9 8b 0d 38 21 15 24 +5f + +# Prime 2: +05 8a dd 02 9b c9 7e cf d1 d0 db 26 be 45 ee 8d +3e 54 bf e6 36 fc 4d a6 66 dc f2 50 ab 2c 2e 96 +56 62 16 b8 a5 17 f1 0f 75 b9 8f de 6c cd 8a 58 +e8 fc 58 2e 78 74 90 e1 95 8f 7a 0f da 82 ad 68 +3f + +# Prime exponent 1: +01 80 ee fd a3 f9 06 9a fa f9 37 a6 72 d4 a2 a4 +18 17 73 01 47 da e9 de bf c7 24 44 42 a0 cf 2b +ae 4f ef 64 c9 da 0b 8a b3 eb 9d c7 27 2c e1 2a +08 5f 90 98 23 55 96 e1 15 c4 2c 9a 49 cc 46 96 +29 + +# Prime exponent 2: +05 12 e1 4e 11 05 7d 84 8c 23 f1 6b 5f 46 2f a2 +b7 8b e7 fc bd 1b 6d 8e 46 9e 3f 69 9f b9 9b 90 +5e d5 fe cc db bd b6 1d 1b fd 5a 7a 19 0a 74 7a +fe 16 7c 37 56 68 07 75 ab 6f a4 23 3d 3a e1 ba +0b + +# Coefficient: +26 2e 28 23 16 98 be 32 87 a9 c7 06 f3 94 7b 7d +5c 2f 5f d2 b9 14 46 f5 e9 a3 15 44 d9 af f4 55 +a3 ec c6 b5 43 14 82 0c 2a 48 82 61 d9 f9 8d 34 +8d 9c 3d 10 02 e4 e8 28 7a 15 2c 12 87 09 65 60 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 11.1 + +# ----------------- + +# Message to be signed: +84 55 19 dd 45 d2 dd cb c8 db e0 b8 29 54 c4 58 +c3 66 4d 88 27 4e 50 2d 27 91 46 b1 8f 6a 81 67 +50 e9 4b 4e cd ee 68 32 cb 35 df cb db dd 3e 5d +c0 64 04 d5 f0 c7 0e 7c 7c d0 e1 9f 38 bc 5a e3 +2c 7c d9 1f 94 d8 f5 67 82 39 7b c7 4e 6b 06 98 +27 ec 27 30 17 37 40 ce 4a 10 e6 48 c7 88 97 af +1a 89 e8 33 31 d0 f4 61 37 8d 06 05 28 73 f1 7d +9f fc e4 6a 32 47 26 07 fe 73 e4 a5 61 87 9e 61 +9e 7c 1a e8 14 e4 5e 1d 2b db 12 19 46 b2 ae b8 +56 39 16 c5 43 eb fd c2 c0 90 fe b5 56 65 00 a8 +ce 74 af a4 53 72 bd e0 c6 67 3a 7f 6a cc b0 ee +9d 57 bd e9 3c 36 dd c5 7b 84 90 aa 2d 68 58 5a +3d b7 29 7a da 6d 9b 3f 35 6d bc 74 d3 15 c5 fa +1a bf 7d e6 ce bc a8 3c 9d f7 + +# Signature: +08 63 a6 26 dc 42 ba f3 e1 61 c3 5b 3d e3 b1 ab +c1 aa 5a df 54 16 46 5d 4c 7b 6b 01 ae 2d ad 73 +f9 f1 58 eb 21 3d bc 36 0b e4 d4 7e 57 07 87 1c +39 c3 8d bb c9 6b 46 c8 f9 af eb d3 dd ac 87 16 +90 98 e1 a7 67 18 d3 54 cd 09 1c a3 52 96 a7 7c +21 d2 51 2f fe 65 e3 b7 1b 90 22 e9 cd 1f 7c 35 +ce 13 65 fd 1f 2c 2c b9 67 ff 4c 8f 90 f0 c8 ea +ef 0d b7 3f ed 00 e9 8c fc 83 f8 0c 67 b3 be 1d +33 + +# PKCS#1 v1.5 Signature Example 11.2 + +# ----------------- + +# Message to be signed: +86 8e 7c 4f c6 34 0b 6b be b7 b8 6e a8 9e e7 26 +5f 32 31 f4 8b aa 92 e4 a2 e8 ce 0f a1 c1 a8 c0 +fb 0a ca 94 4c 74 bc cd + +# Signature: +10 cb f8 71 7f 76 27 8f cc 8f c0 aa b4 6e 90 a3 +d1 80 c3 c9 2a 4a 83 eb 93 c8 92 0a f8 8b d6 50 +6b 40 73 45 3f 0b ef f3 e6 1e db b4 db c9 c9 47 +c6 9d eb 69 a1 ac 92 9e fc 15 62 5b 9e d7 cf 1b +c4 23 a8 87 5f 37 80 dd da 9e b2 fc cd 9f a0 14 +62 6a 7f cf 99 86 49 bc fa 59 53 a3 c4 3e fb cc +38 70 4d 02 49 19 df 2f c4 ad ea 39 e3 4c d1 5c +d4 f8 6a d3 f5 01 01 2f 6b d2 8a a5 00 2c 3b 41 +ba + +# PKCS#1 v1.5 Signature Example 11.3 + +# ----------------- + +# Message to be signed: +92 cf 88 0d a5 89 15 e3 aa 95 08 93 53 e4 61 84 +c9 15 94 5c 57 67 9c 1e 4b d3 82 5e d9 19 a3 20 +52 e9 78 6e 23 b9 42 53 9b 93 15 f5 81 da f0 b4 +1f a3 26 1b 96 7d e4 0c d5 d9 2a 48 24 f3 64 bd +1e 1f 51 84 4b 10 9b 14 54 13 4a df 23 4e + +# Signature: +08 82 89 66 ac 58 36 c5 13 da 4f fb 87 61 87 97 +94 3c 61 2e de 7e 12 b3 10 03 ef 17 10 65 b4 ce +dc 6a 80 b1 45 6c 21 b6 74 b3 77 9a d3 5f 70 17 +7a a9 2c 6e ac 0b 83 3a 96 7d 7e 98 99 0b 48 24 +42 05 db f2 6f 5c d5 7e f8 7d c6 fe 5e d9 99 cf +8c a7 5d c8 e6 26 fd 6e b2 81 c4 99 af f7 29 89 +ed f5 2e c6 f3 bc af 81 ec 5f 8e 82 30 b8 7e de +dc f7 b7 78 14 3e d6 c8 ce bb ac 9d e5 41 09 dc +f7 + +# PKCS#1 v1.5 Signature Example 11.4 + +# ----------------- + +# Message to be signed: +87 3c 47 15 90 2f f1 9d e0 8b cc b0 cf 26 37 63 +fa b0 16 d0 22 0f 03 27 b4 75 5e 35 4e b2 47 f5 +db c2 d3 96 98 9b bd 36 d3 1f 61 98 93 90 ca c1 +66 43 12 5e 63 e1 a1 ae 1f 1b c9 bb ed ac ce 67 +fc 1b 51 a7 + +# Signature: +05 25 9c 48 15 93 ea 86 d1 f0 02 ca 58 aa ee 93 +29 fa fe 21 8f 67 50 f0 e5 88 f3 3b 64 e7 08 fb +27 a6 fe 81 eb ca 8a da ec 75 7a 14 ff 55 a0 c8 +8a da 2c 3b 43 e3 9e 8d fb e6 76 89 43 65 a2 21 +0c 2a a8 1f 42 4d 85 29 c2 07 6b 00 c9 2d d8 c8 +ae 3b 78 0d 87 db a7 29 dd fd ef 7d 40 7f 85 4a +71 cb 68 8b 9f 03 c7 1f 3b aa 24 a2 a6 e1 cb 41 +07 74 30 9e 40 c1 3c 2b 26 47 38 e5 69 7c fd de +f3 + +# PKCS#1 v1.5 Signature Example 11.5 + +# ----------------- + +# Message to be signed: +14 b2 76 02 ec e8 f0 67 b5 84 83 af 17 77 c4 ed +10 b8 b6 4e 64 c6 9f 57 ef 88 9a 1c a5 d5 b5 d6 +51 c6 08 db 23 9d ee a1 50 ff 12 cf 50 c8 67 96 +12 f9 7e cb 09 f7 + +# Signature: +15 c4 b3 f0 81 a2 e5 8a f5 94 e4 2f d6 ac cf 1d +0d 61 d9 3a 5e 3a 84 cf 90 4b 98 d9 ad 71 33 61 +b7 84 b2 4d 92 95 e4 3c 23 be 93 ef 36 51 4a 9b +ac 2c 1b df 4e e7 32 34 36 76 3a 20 66 2f 2d b3 +41 d9 e3 8b ed 5f 12 c7 dd 18 bc 3b b0 fc ba 5c +00 50 bd 1a 2a 44 03 71 97 b8 c9 fc 2a a5 99 eb +43 c3 d9 67 92 42 c9 9b bc 49 b0 3b 98 ea ca 83 +46 28 72 59 e6 ea 2e 89 15 5d 0d d2 b4 77 80 35 +75 + +# PKCS#1 v1.5 Signature Example 11.6 + +# ----------------- + +# Message to be signed: +e5 66 e5 fa 55 6c 76 5b 62 bd 6e 37 45 21 f5 08 +fe 44 66 68 c6 47 4b ef 04 6c c6 89 4a 87 32 2e +19 31 e8 0d 9e d9 ea 80 6b 16 7a 3a f7 7f c0 49 +38 b5 54 8e fb c0 68 d4 f1 96 6a 99 76 25 af 31 +a4 00 7f 06 98 a8 46 9a b6 81 f4 d5 08 b4 a4 8c +8f e7 20 cb 5a 94 a7 f4 43 dd 5a 58 03 04 97 da +a9 59 a3 aa f6 e3 41 84 39 7a + +# Signature: +07 e7 c9 44 26 24 bd 26 6c c1 cd 1a f3 b8 f0 62 +94 dd a1 c0 77 67 fe 19 bc ed 6c 9e d7 c4 b1 ed +7f 26 e2 03 db 7f 3a 1b fa 57 da ba 6f 3a a0 60 +03 bc dc 1e 00 c2 d3 d7 6b 9c bf f9 68 49 b1 af +f5 42 d0 d7 af c6 e4 22 49 2e ab 0a b7 f8 e1 d1 +ae 0b 27 9b 85 19 45 b7 65 85 1b 9f 8a d8 80 dd +16 4c 11 ac 4a 57 f9 6a 0e 48 4b a1 6a bf 1c be +8a ac 09 0a db 6a 71 79 7e 13 35 ee fe 2a c9 98 +0d + +# PKCS#1 v1.5 Signature Example 11.7 + +# ----------------- + +# Message to be signed: +b4 43 c3 43 52 7b 30 d5 ff + +# Signature: +0b 3f 13 c2 72 24 d1 61 01 b9 c8 20 1f 1b 4f 85 +37 db 3c 11 6f 3c e1 30 be 0d e0 dc 0d d2 0f 77 +3c df 7b 7f 37 23 87 c4 b6 53 e5 dd 44 21 84 45 +74 11 a8 2f 8e d0 03 66 ec c0 77 a4 26 7c 9d 7e +56 54 96 63 23 9b 43 19 fe 49 9a a7 89 54 04 9c +74 3b bf 09 d7 7b 30 29 d9 18 bb 7b 9a 6a e8 0b +12 9e 41 bb 56 da d2 b8 a4 b6 f3 19 33 74 c8 29 +2f e0 17 d0 63 34 7e 91 cb f4 dd 39 39 c2 37 f8 +3c + +# PKCS#1 v1.5 Signature Example 11.8 + +# ----------------- + +# Message to be signed: +db 90 04 7f 61 5a d7 19 72 ba ed 0c 10 62 6e c8 +cb 18 c6 d7 5e aa e0 58 21 9f d6 19 54 26 d4 4d +5c 54 3b ef 3c 4c 14 98 e8 77 d7 c8 53 e5 31 21 +eb 31 57 00 81 d5 de 48 85 cb c9 25 a6 c2 23 21 +cc c9 c3 78 4e b2 19 e4 2b 7e db 92 88 77 60 73 +29 79 8d 55 73 9c 89 d6 d6 b3 f0 d4 30 bb bc 47 +22 ea fa 67 de fc 86 ab a6 e6 34 83 fd 64 99 b0 +3f ab dc 84 65 d9 8b bb e4 40 2b 02 31 13 5c 21 +24 3d 7e 02 ad 5f 7e 9e 8b 94 60 c1 2d de 2a 39 +5b 45 69 61 cc 3d fd 9a 12 f5 d9 35 9e 0b 3a 6b +d7 7f 44 65 5b 60 3b 02 55 db ba ff 8b c8 40 75 +9a 34 62 fe ce 0d 8d b6 e4 5e 2f e2 bb f8 b6 e9 +7b 3f ea c0 79 86 73 82 57 ab 9f 8c fa 79 5a 20 +19 2b 5e 2c ea 11 8c a7 62 25 2a f6 c6 eb 00 ec +5c 68 20 bc c7 c7 + +# Signature: +00 aa b0 67 d3 a8 63 3d 0b eb d5 91 ed 34 d0 67 +f4 71 8c d7 f9 b1 e3 5a aa 40 5d a1 22 2a b9 40 +38 66 92 1f bd 05 74 33 40 7a 4a ae 7e 26 c5 cf +a0 bc 9c 11 57 05 7b 1d a1 cf 36 28 51 87 19 a6 +03 f6 c3 c4 de a3 0b f4 9d b9 b0 68 af ec 69 81 +21 dc e5 d6 0d 93 a6 f5 63 3f c6 af 9d f4 c5 dc +cc 13 8c 29 4e dd 42 9d 4a fe 3b 33 78 86 82 55 +cc 53 78 8c f2 b4 77 45 d6 4a cd 88 5b b4 7d 2e +ec + +# PKCS#1 v1.5 Signature Example 11.9 + +# ----------------- + +# Message to be signed: +2b e0 06 7b 95 18 5b ad e1 18 dc e9 5c 57 02 9b +55 4b 25 e1 c3 95 19 f8 f8 90 73 b9 a0 4b 7e 91 +29 9c db 87 b0 bd 17 c9 f1 51 92 5c 75 6e b9 b6 +45 07 25 61 26 41 07 88 21 38 85 4a e7 d5 07 e1 +5f cf e8 47 09 45 40 e7 1a 54 7f 63 b5 90 46 7f +ad ff 64 7f 64 3e 1c ec 11 24 65 29 06 2c 9e 40 +88 92 f2 a2 0c cc c0 ae 45 ca 97 a4 7f ca dc 8f +ed e2 1a 24 71 11 67 70 6c c4 b5 d6 94 77 e5 a8 +a1 46 b9 60 cd 4b 17 27 42 7b 16 51 7b 63 eb fb +cf 84 d0 b1 ac 8e 7e 70 f0 44 35 75 22 b1 d0 cb + +# Signature: +09 76 81 12 17 71 45 44 41 01 33 24 3b eb a9 a2 +1a 6f 72 12 c6 87 91 5c 72 02 7b ba 31 12 f6 97 +05 42 5c b9 94 cb b6 d3 59 c1 46 b9 5d b1 44 64 +35 d4 cf 96 1d fd 5c 49 87 39 bf d4 be 6e f1 ad +d7 4b 81 b2 89 8a 4c e4 3d c3 7c b0 e9 ed 77 44 +cf 40 9b ab ff 71 78 85 42 ff d2 86 eb e5 25 5d +63 dd 7b d5 5b a4 3f 51 84 e2 48 d3 a6 69 33 cd +b0 69 91 ec c9 0e b3 9e e7 1d 65 c8 8e d2 4d 94 +4c + +# PKCS#1 v1.5 Signature Example 11.10 + +# ----------------- + +# Message to be signed: +a7 90 e6 ac 5d 55 6f b7 cf 44 46 0c 7b 9b e5 eb +7f 24 f9 87 ff 89 0d cb 78 40 24 1d 45 54 5b 71 +05 63 5a 1a af 44 57 e6 41 0c 65 ae ce 50 11 e2 +77 5e c8 53 0a 64 a1 88 39 e9 c5 8a 7b 77 42 4f +74 29 3d cb 9e 9e a8 73 6d 6b a5 8b 1c 66 53 d5 +7b ea ab 98 73 5f 7a f7 32 47 7b 9a f6 a3 3f f0 +75 c7 e4 66 39 d7 48 55 08 20 ba 6a bd 4a 9d 48 +cb 49 03 f6 5b 76 f8 14 c6 cd c9 5e 8d 9e 87 0c +24 4a 02 9b 29 4a 8a 5c 82 6a b1 61 f6 f9 78 d9 +f1 c0 3f cd da ae fb fa db 8c aa e8 4b c2 dd 33 +2e b0 49 97 d6 1e fa 91 e9 24 1e 4c cd 97 64 c7 +26 e7 66 ed 3b 03 38 d0 86 f1 03 2c 15 33 ef 59 +3f 88 fd 56 03 37 91 b1 d0 62 5c 6c a5 1e ec 27 +9c fb 6a e3 f1 27 00 cf 5b ac 27 1e 65 67 + +# Signature: +0d 1b 11 1c e8 de 1d 7c 4f 7f ce ac 73 df 70 aa +6e da 58 dc 32 eb 98 f7 8e 7f b9 bc 25 de 3e 6b +09 ab 8c ae 3b 20 26 b6 18 7f f6 36 72 e5 7d a4 +ac 28 96 24 45 d1 fe 95 1d 27 be 6a 6c e7 a5 80 +7e 13 76 13 94 46 e8 54 9d 48 aa 59 fc 22 33 54 +d1 21 fd cc 38 f1 d0 27 5e 41 86 92 27 00 ad c6 +1d ae 1e 4b e8 05 22 2a 1c f0 7f 11 0a 61 58 a2 +a2 62 58 f1 9c 65 7a 11 0c 0d 9a d2 91 68 0c 75 +96 + +# PKCS#1 v1.5 Signature Example 11.11 + +# ----------------- + +# Message to be signed: +32 af d1 3e 60 7d 87 b2 5f f4 0a 88 5b 25 09 f5 +21 f2 a0 a7 72 a9 6a 39 fb 3f 71 c9 63 84 b3 d7 +57 8f 48 fc ea 97 39 56 0a 65 bf b4 83 d9 60 8d +20 25 55 f6 6d 61 2d 16 b9 25 53 87 b4 e1 12 41 +15 ed 48 bf ef 8b 89 d8 dd fc 21 9c cc e4 87 86 +c9 e6 42 6a 92 12 e7 b1 6d 97 1d 27 8a 11 18 f2 +f8 6b 9c 4b bf 75 c9 c2 d0 99 e3 f6 65 48 f1 f4 +a8 a8 21 d7 27 44 98 f7 cc e6 ec 5e 2b f2 bf ad +2c 6f c0 05 e8 0a 48 ca e4 69 92 fc 82 67 a6 48 +0a cb 89 4c cc 9b 62 09 5c ad 97 db 70 d8 82 a1 +3f b3 85 88 c4 8c a1 90 f1 80 cb 3e 61 ac b4 e2 +cf d9 cd bf 85 5c 53 99 21 f6 8e 11 49 d0 54 7e +f5 9a f5 37 92 dc 66 0d a5 ef 48 a7 ab 89 36 d3 +d3 6e d6 b6 46 9e b6 fd 95 e3 af 18 2c 87 68 fa +60 04 78 54 f1 8f 37 41 c1 88 3b b0 79 26 88 ca +db 9e 4d f3 91 d9 11 45 b8 5e 2a e2 4f fd fe 51 + +# Signature: +01 a9 37 b3 cc 82 54 d5 15 08 70 9e 4a 4d e7 b1 +81 de d9 a4 47 b3 ec 8d ad 49 2c 39 79 52 df 7c +55 0e 4b 26 c9 50 17 29 9d 8d 45 5f f7 97 1c 33 +8c d0 14 df 78 e2 a8 aa 5e be e2 58 f4 92 53 d5 +1a ce 9a 49 31 9f fc 80 7a d7 0b 2d f2 c9 6d cd +b7 3b 48 ac bc 4f 6c 3c 2a 70 1e 7c 15 4b 27 9b +07 05 bd f2 54 8c 8b 36 11 b9 7d a1 ac 09 cd 12 +12 50 99 54 0b f7 ba 99 b0 8c 2f 3d 5f 6a ea 7d +40 + +# PKCS#1 v1.5 Signature Example 11.12 + +# ----------------- + +# Message to be signed: +5b 00 b8 b7 94 a1 0d 21 f1 b4 5e ca a2 0d f7 c5 +b3 52 2c 1b 1d b4 b0 84 b9 59 aa 4e 56 58 ac 54 +68 f6 e8 fb 61 2f f9 9f 32 16 b5 d2 1c b4 ac c0 +bb 42 ee fd b8 e8 2d 75 4b 85 d0 97 45 89 4a 52 +3c 01 62 d0 8e cc e4 8b 99 dd 6c 38 e2 bd 3d 53 +1c 85 62 de ec fc 61 52 36 9a ac f5 80 ea f9 db +6c 68 b6 9d f2 fb f3 05 3f 60 1f 70 02 2c 9e 38 +1d fb c5 90 99 c3 7b de 5a d8 9a 8c c1 ef e4 c7 +b7 d7 8e 90 97 e0 81 21 ed a6 4a c4 5c 32 7e 5e +da f9 22 d3 c3 5f 88 b5 2c 93 d3 99 f4 c2 38 36 +2f e9 + +# Signature: +0f c6 ac 1d 42 94 79 38 cd 25 86 d0 e7 fc 3a 05 +42 b9 af 12 d3 6e eb f9 2b 5d 04 9c 79 65 b1 1b +a9 cc bf 47 00 f3 45 60 91 11 77 b9 d1 29 6f 1c +68 e3 af 46 9f 4f 39 9d bc 18 9c 23 ea 74 65 98 +28 13 32 33 05 ed 6c 35 ff 9c c1 09 d0 a2 30 3f +e7 d3 29 ca 31 7e c4 b1 8e dd 19 c6 2c 60 a3 c8 +c3 10 6f 86 db d0 72 e3 e1 eb 87 85 28 8c 21 ab +ca c2 2e 0c 0d 41 f4 e2 3e 7f 39 4d 46 82 f6 ce +87 + +# PKCS#1 v1.5 Signature Example 11.13 + +# ----------------- + +# Message to be signed: +b7 50 ae 6d 4d 2c eb 92 14 05 34 64 8d 36 ef 25 +e4 51 55 f5 2b de 1b f2 6a b7 + +# Signature: +16 aa de dc a0 9e 06 25 60 c6 61 d2 a4 9b 0e e4 +d9 ce 23 90 7c 69 d1 00 04 f1 49 d1 03 c5 9c 16 +fe 7d 43 73 59 7d b9 ff d8 92 3a 77 a6 b9 43 b1 +88 c4 74 25 e2 a9 e5 30 41 3e fd b6 84 8d d3 42 +0b a5 3e f8 1c 25 c5 78 f8 d9 51 4d 93 fc c9 cb +1f b5 2f 58 d8 8a 57 d1 fd 3f e2 2d a3 10 ec ea +9e ce 55 e9 60 8d 63 ae 21 db ae a6 57 1b 78 fc +fd d2 71 bb 65 92 57 47 6b 59 95 68 7a 02 bb e7 +89 + +# PKCS#1 v1.5 Signature Example 11.14 + +# ----------------- + +# Message to be signed: +47 be 01 02 0e b7 e7 87 5b d4 fc c0 05 a8 2b 36 +fd f2 14 5e f1 32 e2 ed 16 2f f6 94 bc 71 58 9c +7d c6 d5 a3 f8 9d 59 7f 2d 2a a3 43 33 51 18 f6 +fd bd ee f2 3e 61 3c ba cc de 41 95 e6 64 a0 09 +4b 07 fc 0a 32 84 8d 61 39 03 1c f5 72 a1 e3 23 +c5 a7 07 b6 fa 2a ee f2 dc 87 2d d5 a3 e7 6b 13 +f8 ef 94 ad eb d4 e2 05 74 8e 48 5b 40 01 d5 d2 +a0 90 b8 9b 2e 64 74 c4 79 e7 b0 0d 2d 57 f5 86 +ab 76 b8 0f 79 5b a8 99 62 88 29 2c 3f 2c a5 1a +44 e4 e8 41 c0 37 07 e4 80 25 af 4b fd 0a b6 ef +eb 83 62 ed d5 d2 34 05 ba 0e 23 1b 33 24 e1 ca +3c 5d 63 9d 2c 9d 82 + +# Signature: +06 39 17 92 9b bb 20 92 17 ff 48 ed 4f 55 d0 7a +03 f7 6d 6d 94 04 8b 6f 71 31 0b 2c 96 e2 14 ab +22 0d 4e 45 ac 01 c9 3d cc 8a 5c 26 a0 2d f6 1f +fd b3 17 54 96 65 61 0c 84 bd b8 94 5f c6 bb d3 +8b ae d7 fe e9 8e b0 56 d9 f0 39 a8 60 d4 52 b3 +ac ac 18 00 a9 32 a2 8c 88 28 6a bd a8 de 3c b6 +c0 d7 94 da ab 7a 8b a0 11 09 33 b4 d1 de d2 39 +cb dd 55 7d 3e 5a 16 29 17 85 33 15 de 68 09 00 +a8 + +# PKCS#1 v1.5 Signature Example 11.15 + +# ----------------- + +# Message to be signed: +4b 9c 09 64 48 10 d4 b3 06 55 ed 83 38 bb 27 6b +62 4c 68 01 98 22 d1 fc 8f 78 86 1e 13 e2 2a c1 +71 82 1c fd bd 3f 8f 5b 8d c9 c0 de 73 2b 74 6e +1d 13 2e 5f 3f 14 9a 5a 86 7c 2e e4 78 e8 f1 4a +d4 b9 dd eb d3 ae 78 17 e8 49 55 b3 40 4b 09 43 +93 e6 1c a0 18 9d 05 53 69 b4 24 30 09 a0 f5 40 +3f 41 c1 00 23 08 c0 0c e6 99 67 19 37 ba f1 3c +78 93 d6 63 c9 47 fc 7f 84 07 1a 67 2e 5e 07 37 +8a ac 08 b3 fa f0 fc cf 5b f2 83 09 25 85 eb e2 +40 a3 00 46 20 b6 f3 ae b6 73 2b 7b 9d 8d 3b ea +fc 84 67 d1 f1 f1 c7 da 66 b1 bf 5c cc 14 5b 32 +24 24 5f ae 31 df b4 03 f4 93 c0 75 53 57 ad d7 +cb 27 63 71 32 26 c5 4f 43 64 0f 7a 67 0e b7 b1 +f6 e9 e7 72 f2 e5 14 17 a7 05 cf c5 87 3f fb 88 +a5 db 07 ec c4 ee 89 f3 30 a6 69 0a 88 12 + +# Signature: +1a 0b 69 8c f3 a0 58 b4 49 19 af 73 c3 de 32 8e +86 ce 9a 5d 49 99 e0 12 2f 41 4b 94 f3 2b 2d 8a +b1 e6 55 0c c0 d4 8d c0 4b ef ac 2c 67 a4 d0 69 +a7 20 8f 14 2d c2 67 b3 e3 8f 63 38 a0 b1 83 9a +93 a8 36 80 7d 18 1e 3f 0c 7e 87 7f b2 42 16 02 +00 5b ca 25 a9 c3 72 26 6d 18 e6 d5 00 c5 c7 ab +13 38 52 83 d2 af 91 9d 0b ba 0d cb 88 bf 7b b9 +97 2d 67 00 8f f4 98 54 7d 80 fc a6 58 ef e7 64 +a5 + +# PKCS#1 v1.5 Signature Example 11.16 + +# ----------------- + +# Message to be signed: +ec 9f f1 4b 9f 19 7a 2b 4f 24 94 8c 29 d2 f6 4a +64 62 52 23 dd b8 53 46 37 8c 2c 25 34 3f cb ef +58 5a 99 e1 ec 0b ef 0e f9 d0 9e ad 85 be e1 c4 +bf b3 5e 48 fb 26 41 1b df 18 0d c5 cf 31 7b 3a +34 83 71 c7 c5 f4 aa 6d 59 08 fc fc 1e a3 90 18 +cf 04 49 e5 5f 4e f9 94 bf da 40 4f 1c 18 9f db +8a 0a 5b 09 06 c3 d4 0d e1 e7 87 c2 db 4d 88 db +c2 10 b9 f8 01 f4 cd 9c 97 22 7e 9b 2f bc 28 11 +e3 8c ed d9 e9 f0 35 60 03 1d 4c 95 8a 76 81 ba +9d 7e a5 e7 8e 9b d8 bd ed db 41 56 79 0e f2 1f +b7 4f bc 41 58 c2 93 9e 4e fc b8 2e fd c8 81 88 +6a 5b 67 13 a2 4b 9b 5f 2e e2 5c cf 72 1a 64 e0 +f6 40 77 8e cb 3d 35 b4 b8 ee a8 ec e3 12 32 63 +63 10 ae 3c c6 b8 2b 8a + +# Signature: +01 3b 42 05 78 20 c7 3e 3a cf c1 df 4d e1 44 0c +65 8e 01 80 43 6d a7 18 5a 9f ab d2 6e b3 26 74 +b5 54 de 35 4d 1f 4f 24 e8 77 73 26 7f ed 9d d0 +fd 82 93 ea ca 4a f3 d3 a9 dc 51 8c 8e 49 5a 14 +76 95 11 1d 3d c1 77 63 f1 f0 2e ec 1e e2 9f b1 +ab 74 9c f3 0c 78 86 da 8b 2f 64 69 69 59 8a a7 +0f 9a 92 fa 4f 93 5c 7c c7 7b fa b6 98 1f 0d f0 +d2 85 cf b1 0d 66 58 15 39 f7 8d 03 68 ed 4f 93 +01 + +# PKCS#1 v1.5 Signature Example 11.17 + +# ----------------- + +# Message to be signed: +41 4c ea 8e ec 6d a3 c6 6f fc 84 70 f7 e1 47 60 +f7 4b f6 e7 5b 84 dc 98 fc 80 60 dd 3c 21 9e 76 +77 7d fa ba a6 e6 b9 29 55 37 9f 3e ca af 5f cb +8a a5 54 9e c9 cd d1 f5 d5 77 20 1b 8e 32 9f 72 +fa a2 bc ad ea ee 38 8d af 7d 40 8a fd e6 55 3d +24 17 86 0f 3c 8e 25 30 5d ff 76 db bd 95 16 b6 +86 8e e4 56 fc 1f 7b 58 d9 ed 18 a4 6e 4f c1 e3 +53 e8 d0 76 be a3 0b f2 47 c6 0e 6f 68 58 01 a6 +d3 f6 30 ae a6 ab b4 12 a9 41 ff a6 f6 07 f6 bf +b1 3d 90 01 27 bb ec ee 4f 98 a7 ac a6 92 08 11 +57 50 53 ab 2d 42 70 13 80 1d 8c fb c3 88 0f 14 +75 43 15 55 a0 86 fa 55 60 c6 e2 20 6d 9e e9 38 +13 44 b8 24 1c 1d d1 d8 64 48 75 3a f4 4b 00 a0 +c9 + +# Signature: +16 97 bb 23 e2 91 52 5f 4a 0e 79 26 2f 34 06 63 +0d 0d 6d f3 32 49 69 26 c4 e5 ae f9 6e 41 d9 55 +14 86 47 ea f7 90 69 6a f6 8c 78 eb 2a b6 2f f7 +19 62 96 e1 ea 88 6d f0 91 73 66 09 0b 63 0a a3 +18 58 b5 16 15 87 3f a6 bc 8f f0 88 5c 57 b2 e7 +7a 04 90 88 93 cc ef b1 41 24 03 99 1d 0d 23 c5 +57 d2 22 29 1c b8 51 7b 43 28 6e e0 05 67 58 d9 +c1 0b cd 69 bd 68 b8 4a 2d 1f 53 79 05 b8 a4 65 +e9 + +# PKCS#1 v1.5 Signature Example 11.18 + +# ----------------- + +# Message to be signed: +17 89 b8 08 b1 0d e8 d1 77 8a a4 3f 94 10 1c b8 +9f 56 34 30 61 a1 a9 43 bb 8d a5 5e e6 b9 79 e2 +7a fe ab 0e d8 ee 37 14 fb e7 0b 3b e8 20 60 3e +5c ea de c4 b2 2f 95 87 73 22 5d f3 aa d4 87 b2 +80 57 eb fe be 2c 87 93 da 38 46 bd b1 59 03 ac +71 e9 c9 3b 20 16 66 8b d9 06 30 1a 0a 7d 50 dc +60 b2 fa d8 75 9d 18 db 14 7f 20 66 86 5f d9 09 +50 a1 88 74 7d 9b 69 68 53 48 6d ea ab 8e 44 3f +ad 29 92 fc 8a 56 5b dc ba da b0 b9 33 3a b7 fc +db 9c 3d 0b cf de 50 a5 8d 2a ea f1 ce fb 0c 95 +f9 07 73 b2 fa c1 37 cd bc + +# Signature: +02 f9 97 51 c8 44 38 ea c7 f9 96 32 50 d9 ee 22 +fd a7 29 7b 6e 86 e2 a8 bc c7 a9 b5 ac 01 f7 90 +e0 99 11 70 46 60 85 8e a5 c1 62 72 c3 81 33 fa +da de fa 23 c1 02 90 8e 41 9d e2 eb e9 ac 27 19 +45 72 87 8e 2a 97 1f 88 31 c8 f9 17 e8 52 e8 51 +df 99 d4 df 01 8f dd b2 ce a3 1a c3 a7 b6 89 75 +e8 0a 99 7c b7 dd 4d 4d f7 57 bb 8c 3e cd 91 0b +cb 06 03 35 52 12 7a c3 08 11 77 39 a0 2c 20 17 +17 + +# PKCS#1 v1.5 Signature Example 11.19 + +# ----------------- + +# Message to be signed: +ff 87 5c ca 0e fc 3d 90 f5 6e 31 f4 bb 66 84 14 +89 4d 09 de 90 12 7f 84 66 32 43 10 e1 13 69 a3 +f2 f6 49 3c 1c 78 a3 62 b2 a1 4f b5 48 8c b5 6c +e0 22 73 9e 43 aa 76 3d 9c 1c 97 b6 21 cc 53 68 +c9 c0 0e 81 60 67 92 69 5f 9a f9 ab 63 3e f2 39 +ea b3 44 9d da 9e 66 07 08 9c 37 51 90 35 4f 7a +59 a4 b3 ef 75 22 9d 1c 47 ec da e3 3b 27 69 ff +55 42 65 5e 78 10 22 d0 c4 3b 42 1a 99 84 3c 3d +e1 04 22 ad 2f d8 9d fe 44 66 15 f5 19 2e 75 79 +d4 37 43 79 bb ff b9 + +# Signature: +02 68 91 7f 8b da ac 9e be 32 b0 dc 6c d9 d3 9e +fd 3f 88 d8 17 d6 6c b6 39 0d 7b 55 c6 92 12 21 +84 4a b8 c0 89 86 d3 f2 ea 49 bc 6e 3a 10 02 08 +6c 0b 6d f1 63 f7 9d 16 11 6a 93 c4 a2 cc 04 22 +c9 48 41 e1 e3 b9 45 ab 1d 25 3a b8 d7 d1 39 c9 +18 8b a8 30 27 c5 93 f8 3a 6f 38 37 0e 7f 03 79 +ff dd f1 42 7d 6f cc cf 60 83 31 3f 18 15 b5 de +d6 73 74 30 bb 4a 70 ba 81 48 48 34 d8 d1 d2 9a +5e + +# PKCS#1 v1.5 Signature Example 11.20 + +# ----------------- + +# Message to be signed: +e0 7e cf 00 e2 40 1a c9 8b 2d 5a e0 c9 b8 3f 21 +9a b0 27 a6 51 99 fd b6 34 59 6e 23 44 62 41 38 +72 95 32 49 53 28 f9 3f b3 a3 32 55 27 8f 3e c2 +60 65 ce 54 99 5d 42 41 93 bc b7 58 1b fe 1a b8 +95 7d 0b 96 1c 30 30 b8 20 d0 9c 9e 32 6c c3 0c +0a f6 42 66 61 54 + +# Signature: +00 c4 6d b4 1b 65 dd c7 1f bb fc 12 5a 4f 9b ab +88 0a 2f 0c 1f 04 1c 41 1d f7 d4 5d 1e 19 99 7b +34 8e ab ba 19 bf 79 b2 21 77 b2 a0 d7 3f ef a5 +00 83 62 ce 59 60 d7 ef 58 a5 89 93 e7 46 03 d4 +d9 d0 b3 da d4 b2 0c 82 9d 36 ef ca f5 7f 0c 4f +0c ef 89 01 5a 48 45 02 42 bd 02 0d 5f 52 d8 b5 +0e a1 3e 56 a1 aa d6 01 91 5d 60 ec 9a bf c3 07 +f1 8a f2 06 72 38 4d cc 12 f9 82 27 31 36 99 71 +40 + +# ============================================= + +# Example 12: A 1030-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +36 98 1a 95 ae 24 18 14 52 da 25 7c 03 8f 05 82 +14 12 d8 4e b4 7a 43 fc c7 ef 12 17 95 9b a6 77 +02 7f 70 86 d3 a8 5c dd 34 9f 92 0f 03 4c 02 78 +79 2d c8 a8 cf 0c 00 80 e5 c6 1f 47 48 83 c6 87 +9f 4d ee 0a e9 52 47 8a 5e e2 ce 4e 39 18 64 1e +81 3c b3 74 f7 b2 83 2b cd 6a ea 80 9d 25 4f c2 +ca 9a c5 a3 32 42 4a b6 5c 2a 26 12 75 d1 9a 41 +4b 61 65 00 d5 e3 73 70 63 15 f0 63 dc 88 5d 7f +b9 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +36 98 1a 95 ae 24 18 14 52 da 25 7c 03 8f 05 82 +14 12 d8 4e b4 7a 43 fc c7 ef 12 17 95 9b a6 77 +02 7f 70 86 d3 a8 5c dd 34 9f 92 0f 03 4c 02 78 +79 2d c8 a8 cf 0c 00 80 e5 c6 1f 47 48 83 c6 87 +9f 4d ee 0a e9 52 47 8a 5e e2 ce 4e 39 18 64 1e +81 3c b3 74 f7 b2 83 2b cd 6a ea 80 9d 25 4f c2 +ca 9a c5 a3 32 42 4a b6 5c 2a 26 12 75 d1 9a 41 +4b 61 65 00 d5 e3 73 70 63 15 f0 63 dc 88 5d 7f +b9 + +# Public exponent: +01 00 01 + +# Exponent: +09 ad 03 17 30 b6 32 73 55 ac d6 94 68 70 0e 7e +9b ae ac 5a 24 a7 ff c9 3b 29 2e b8 71 da 54 92 +46 a5 ce 0c 83 52 55 65 1a 28 c6 e2 f4 c7 61 af +b6 f0 6b 9e 29 95 fb b7 dc a1 74 d5 36 2f ae bd +c3 9a 72 c5 79 5d 1f 33 92 ec 08 8b 5d c2 a7 85 +b2 c9 c4 c6 e6 69 e7 23 b5 dd 0c e4 43 25 55 12 +67 dd 62 e0 f7 8d 24 24 ad ae 48 e2 49 44 3a ef +4a 37 04 10 db 9e 70 93 99 ac 37 cc 48 1b 59 00 +c5 + +# Prime 1: +07 72 0f 21 cd db 92 27 45 b7 1c f8 11 6a 83 66 +9a 0d db 89 e8 f3 f0 6c 34 7c a7 87 cf 10 ef 16 +93 bd fe 3a 0c 36 4c 7a 7e 89 04 17 f2 af 49 47 +5c 7d 07 6f 9c ee aa e7 6d bd 4e 92 15 af 45 69 +4d + +# Prime 2: +07 55 1c 27 e9 aa f1 1f 47 4f 1c 9a 14 bf 14 4c +fa ef e2 7f ca 4f 20 79 5d ec 85 34 c9 37 bb 00 +fe 16 23 5e cd 69 1f d2 3e 32 cd fb 8b 78 66 6b +b7 82 84 ae 15 d5 9b e5 ca 74 73 e6 2d 46 a9 da +1d + +# Prime exponent 1: +02 e2 2c 74 16 0a 94 36 bb 6c 28 3e f6 57 be dd +ec 89 b3 5d 5c a7 a4 93 f3 5b d7 71 e4 42 95 a5 +b3 c0 20 06 11 16 b2 55 ba 4d 8c 15 4e 3a 8e 71 +a1 a3 16 4f 26 82 d4 13 5e cf b2 ef 26 90 c3 9b +fd + +# Prime exponent 2: +01 d2 bf f5 8c bc dc c8 12 4b 31 a9 7e 8f 24 d5 +1f 70 96 b9 7f ec bc fe 70 c4 67 3b 00 ed c2 aa +34 83 fc b7 8e 0c 1d c5 81 81 d0 86 43 df e4 57 +d4 81 b7 cc 31 d1 b3 ba 27 e5 5d 0c 57 25 c3 06 +61 + +# Coefficient: +06 d2 27 72 57 42 ef 03 46 2d 1c f6 12 67 4a 78 +83 1d 61 9d a3 d6 40 eb 7c 71 c8 7b 53 28 69 72 +73 c5 f7 51 e1 4d 7b 81 c1 2b 6d eb 44 75 1a 92 +95 cb 67 1e 81 48 4d ea a8 3b 4d f1 fd 37 e2 ff +3c + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 12.1 + +# ----------------- + +# Message to be signed: +e4 b2 d6 0e 3b dd 27 81 6f + +# Signature: +13 fd 4a c1 ac 68 48 17 37 80 96 5a ff 5e 61 c5 +96 89 2b c1 47 76 0d 43 07 9b 5d 71 77 e4 23 d4 +86 f5 a7 3e 1a 16 b3 ce 9b 5e da c1 61 ea 6d 4f +6c 23 fc fc 3e 62 19 ca c5 56 06 7f fa ed 4a da +c0 a9 50 05 09 0b 89 84 4c 54 35 4d b2 2a af f9 +ee ff 9d a5 aa a5 49 04 25 e1 35 cc 0f 64 58 4c +7f 05 fe 33 6e 44 40 bb 86 92 86 d4 4a f1 57 88 +0e 3a 40 fb 06 72 5d 09 de b3 7f 1e bb 18 1c 8f +5c + +# PKCS#1 v1.5 Signature Example 12.2 + +# ----------------- + +# Message to be signed: +78 86 85 fc 58 05 d6 27 b1 3f 2f e7 fe 6f 7c 9a +b2 ca 49 44 ab f3 08 b8 6d 1a 0f 58 3d 17 b5 76 +02 43 9e 1f 2c 6e 0c 5b f7 81 70 50 13 38 b4 c4 +47 e9 19 7b 65 03 fb 73 eb ab f7 76 de fa e3 3b +dc dc e7 7d e7 9b 82 be 14 85 a8 aa 9b 82 09 37 +db f4 28 a2 05 50 96 6a 86 b6 2a 17 2e 6c fb dc +fe 0d 6f c6 7a 4d b6 22 52 fd af 85 f1 e6 bc 14 +f8 ab 1c 53 32 6a a6 a7 bc 5e ec 88 e0 b1 1d 48 +d2 b5 61 f2 26 06 50 10 2f f2 7b 57 b7 00 72 bc +c1 21 e3 5e 70 f3 78 0c 83 33 b5 bf 6b 08 fa 12 +08 26 0f 33 + +# Signature: +09 04 cc 11 ac 66 a9 83 7b 74 56 8b e2 50 e5 3a +e4 be f7 8d c6 7f fe e5 09 e5 d9 b4 72 58 3e aa +a5 6d 4c 9e e7 0f 6e 82 dc 99 8b 53 ef f1 27 2b +f0 1f 09 e5 26 2b 15 5a 6e 56 d1 50 40 03 e4 c8 +a4 6e 65 02 55 32 78 23 0d 6e 81 b7 29 18 43 ab +97 69 73 7f 3c 69 31 52 f1 7b f2 d8 bf c7 82 bd +b3 fa 0a ea df 0d 44 1e 1e 52 de a5 4b 75 cf 16 +5e 35 c3 82 d3 11 74 f6 67 9d 2f 21 b9 81 f4 13 +58 + +# PKCS#1 v1.5 Signature Example 12.3 + +# ----------------- + +# Message to be signed: +4e c7 39 3f dc 4b 90 af 8f ff ca f3 4e 84 5a 09 +65 6a ef 9d da 12 b0 34 2c 46 eb 04 91 74 aa 51 +1b 43 c9 4d 75 c0 e2 90 70 af f5 b4 14 23 a1 70 +d9 b3 e8 b2 12 24 aa bc 53 1d 88 88 6e 26 46 d6 +78 8f 1b aa d4 ef 4b 0b 4b de 4b 12 ce 90 52 08 +2e 2d dd 0e 3e 6c aa bb 0a 14 34 4b 0a 58 3f 40 +4c 1b 6a 3c 7b ca 8a 58 85 d5 f2 24 af 1f ca c3 +fa d9 37 0e 9b 29 74 e8 ca 62 e2 2a ce b9 + +# Signature: +21 a6 6a f6 27 ee 0d d0 5f e7 56 3c c1 d2 9c cf +6f 87 31 b4 1e 3d b3 95 97 89 3b a1 cf 37 5f 78 +17 88 fd f0 73 b0 b5 93 c7 6d f2 81 6e c6 de fc +22 42 21 ac 19 f5 be e4 4f c0 e5 d4 09 3d 34 68 +27 8f b4 2d 40 5a 07 04 46 53 22 da 4d 3a 7c a9 +c3 da 73 c3 d0 82 ae e5 67 b7 70 83 32 3e 75 bb +35 ed 77 e8 db 9c 01 b4 96 a0 4c c4 a8 99 df 35 +9d a4 a2 28 7c af ff e1 ed 63 cd de ad 87 6c 94 +07 + +# PKCS#1 v1.5 Signature Example 12.4 + +# ----------------- + +# Message to be signed: +90 77 60 db 32 96 9b 09 7d c1 24 ef 89 75 15 11 +a5 d2 30 59 6d 2f d8 a8 91 ff 00 f0 5f ba d4 5f +72 a4 5d 46 56 24 a3 ab 67 af db b9 e5 f9 e6 5b +63 e3 0c 2e 57 fe 7f 32 f3 99 01 10 33 dc 05 29 +c0 97 1f be 06 4f c5 ed b0 1f 84 cd 57 28 3f bb +bd 2a a0 29 44 11 0b 6b 53 4f 74 08 2f 56 be 34 +6c c3 43 bd 4d 0b 34 80 91 c0 05 c6 19 9a 7e 3d +56 88 52 47 b0 c1 6a 36 b2 35 b8 f5 d4 f0 0a 6c +6b b6 fe ed e8 8f cd 78 8d 75 ca cf f7 d9 56 87 +99 65 71 55 9c 05 79 6a 55 71 1d 77 46 bb 92 d8 +52 89 3b a9 06 75 f9 8b 0f 54 08 48 1b f1 54 3f +39 de 3d 0c 0c 1f 53 49 5b d2 12 dd cd c6 d0 e5 +7d 7a 3d be 24 20 8c b2 4e d4 1d e0 3a 5f 05 2a +9b 58 12 70 0a 5c e0 5c 02 00 d4 71 9c 55 54 4e +7f b2 94 d3 44 a4 f2 05 ef 9a 34 97 b5 67 54 7c +bd 1a 63 3e 2b 79 d3 34 90 95 + +# Signature: +0e c9 38 a0 d4 b2 a4 ed d2 78 d6 3d e7 61 c1 02 +e2 59 21 02 ee 05 db 1b 59 1e 0d 85 7b f6 66 84 +9e 74 cc 19 b7 e4 e9 cc 39 2d e5 39 f7 90 fc 68 +e3 b5 21 db 3a 1a 26 7e 5a 4e 12 19 75 2e 01 99 +e7 01 9a 24 85 54 c5 ba e3 11 2b ee a4 0c f3 e6 +4f 8a af 9b b1 e9 d1 c1 d8 83 3c 2b fa 31 b9 d5 +45 0f a2 49 29 7f e2 e4 6a b0 3e 99 b1 f9 c6 51 +d5 39 eb 53 ce 09 61 ce 60 23 c1 7d d7 38 3d d1 +2b + +# PKCS#1 v1.5 Signature Example 12.5 + +# ----------------- + +# Message to be signed: +bd a5 54 95 47 32 d1 d5 f3 94 75 55 c6 1f fa b8 +01 db cd c8 12 1d c6 81 91 27 c2 f2 2a 43 6d 20 +62 2d 1f 4a 44 7c 3a 77 b6 58 57 31 af c0 3e 77 +ba eb 70 9c 1b fb 90 6a 1a a1 94 9a b6 76 3a 15 +c7 da 5a 12 a8 f3 95 10 1e 64 6a 83 71 73 14 1f +2a 0c f5 36 02 4b 36 91 8c f9 db 95 b1 cc 40 5a +ef e6 3a 3a 93 bc 4a da 60 a0 f4 e0 72 9f 4d b8 +b7 6f d6 4e fc bc b6 6f 0e 4a af f3 + +# Signature: +07 26 2f e1 f3 d7 b7 79 32 cd b7 cd 96 ac 19 8b +93 03 eb 44 46 0f 52 98 e8 e5 2f e6 70 52 99 bb +d6 18 ef d0 b3 63 31 56 2f 20 b2 0e 86 6d 99 c2 +d0 4a 01 49 f5 64 dd f6 6b a3 19 f3 b8 48 25 39 +6e a8 b8 93 ba 5b 3e e5 e5 24 5c fe 6b 61 6e 30 +a9 00 bf 83 bb 76 3d 20 b3 30 37 01 ca be 94 33 +41 48 88 2a e4 ef 14 e6 d9 e6 c7 52 bc e2 53 bd +da 57 39 e3 3b dc 32 eb 08 28 28 c1 c3 99 c2 2f +ea + +# PKCS#1 v1.5 Signature Example 12.6 + +# ----------------- + +# Message to be signed: +51 76 ad 7c 99 be 4c db bb 5d 79 ba 5f 49 6c ad +9f 42 dc 25 d5 27 a5 d5 e8 e3 35 91 79 22 5e 6b +0e 43 66 6d 3d 82 ab 5b af 42 4c 85 c3 31 21 60 +6e b7 9a da 6b af ca b5 c1 e2 54 6c ab f6 a3 60 +03 84 05 ca 18 c0 08 36 67 + +# Signature: +06 27 23 8b 0b 93 e4 cf 98 57 13 d2 91 29 6c ed +e3 45 e8 8e 17 82 45 25 53 59 39 b3 f3 d5 ff 4e +bc 40 74 00 11 49 00 25 df ea ae e9 06 38 c5 39 +1e b4 4e 9f f3 70 45 7b 60 d5 de 80 c1 65 38 cb +38 60 55 95 85 ca f5 e3 33 2c 7b 1f dd 8f 45 fb +6e 35 57 f2 c7 a6 0d 09 9e 94 f8 e9 6b aa 1e 03 +19 9a c8 3c ec 8f 9c 16 bb 49 15 1a 88 72 cb fe +70 f0 02 cf 3b 53 b6 11 d6 cb b6 65 89 7c eb f5 +99 + +# PKCS#1 v1.5 Signature Example 12.7 + +# ----------------- + +# Message to be signed: +e1 74 71 93 64 f7 bd c8 6e 2f 0c 61 26 5b f8 05 +7d 64 9c ca + +# Signature: +09 77 19 54 fc 8a 1f ee e9 0f 60 c4 b8 a5 bb d4 +62 c6 34 37 9a b3 da 19 ff eb a6 e0 31 b4 24 3a +83 50 9c ee ed 6e 01 2a 91 63 c6 14 5c f7 05 02 +a9 fb 0c 21 db 31 fa d5 ad 14 69 5d e0 02 62 e4 +e5 67 09 5e 16 11 0c 6e 65 d6 bc b9 cc 02 e9 19 +f9 0d 19 e7 30 7f 44 34 50 3f 9f e0 2c 12 c1 d3 +f5 0c c1 60 08 6f e4 60 29 8c 88 12 25 bf f2 e9 +e3 13 da 38 44 44 be c7 2a 67 ac 34 44 67 e8 2b +66 + +# PKCS#1 v1.5 Signature Example 12.8 + +# ----------------- + +# Message to be signed: +98 cb c9 1f d4 9b 50 7c 88 7e 97 c3 cf a9 b5 9c +26 00 1f ca c1 64 87 f6 00 4f 0b 68 74 54 63 20 +02 d5 49 b5 46 1f f1 53 0c 0f 5f c0 9a ac c4 6a +da da 7d c9 d7 b3 e2 0f ed fe ec d8 f2 f1 68 41 +77 32 68 54 2e 86 43 1c 7f b4 d1 63 f3 1e 8e 31 +72 20 34 26 bc 0d 88 a2 3b 13 76 34 bf c7 14 01 +72 20 fb fb ec 88 8e 01 e3 ef f7 bb bd f9 3f 08 +3b 88 fd d6 40 7d 98 9b cc 5e cb 15 3c 9c ee 34 +10 fd 00 6b cd f0 7a f2 28 79 0f d5 e0 4f 5c 0a +1b 63 64 8d 48 60 9b f1 63 c6 fd 65 60 20 75 7c +3c 06 38 e1 b8 2d 75 e2 b4 b9 08 b7 e0 a3 c8 d7 +26 6b 80 1f 60 fc 2b 4f 31 7e bb 8b f2 2a b9 e1 +cb 7b 77 84 39 5b d7 b4 24 32 9e 86 1d 47 86 61 +f6 dc 12 98 51 5f 48 56 4a 3f f9 97 35 bb 90 03 +38 75 a2 5b e8 b7 24 f3 + +# Signature: +0f 2d 7a 5e ab 83 58 45 03 d9 4e bf 7d de 9e ed +49 41 10 be 94 ed 64 8a f0 cf 6e 89 1b 06 2d 2c +9d ef 95 87 55 b1 a3 08 48 8d 16 70 74 29 51 ec +00 60 54 5d 2e c4 3f e8 4a ec 89 01 ad f4 fe 8d +67 aa e5 7a 31 9f 49 1c 85 c2 1c d7 f9 c5 99 81 +3c eb 9d f8 47 78 ad c8 2a 33 c4 e7 67 4d 7f be +13 48 dc 20 75 51 10 4f 54 42 ac d6 84 86 9a c2 +2c ac 51 6c c9 88 7f d1 d0 21 ef cc 54 ab da f2 +b6 + +# PKCS#1 v1.5 Signature Example 12.9 + +# ----------------- + +# Message to be signed: +3e ed 6b f1 16 cb 31 e0 fd d4 c5 c9 33 58 ba b6 +8f bf a8 b5 c5 15 bc ab f9 05 1c df 95 a2 43 e5 +ee 68 15 15 4e eb 4a c1 0f 52 31 d0 49 38 13 e2 +81 49 e9 68 2b b1 c8 b7 7a 6e 13 60 b2 b2 c0 f9 +c3 16 1e 41 7e f6 cb 3d 9a bb dc 74 2c e0 25 fa +fc d5 38 c7 7c 4d 07 16 49 1d a5 4b cd f1 67 b4 +7a 61 a0 35 27 c9 6e 4b 42 bf dc 98 5b 17 87 81 +b6 92 0f 60 f1 1c d5 fa 76 66 3f 56 f3 19 f4 50 +cc 2a 7f 13 bc ce 59 e4 1c b6 66 + +# Signature: +07 67 3f a6 83 e0 98 bf a2 b9 55 b6 c3 4e 9c e8 +ec cc 5a b0 ab 4c 2c f7 9b 9b e1 e6 64 42 5a 7c +17 7a 47 d5 32 0c d5 70 86 f9 51 89 18 45 09 4b +1f bb c9 de e5 f9 b5 56 df 3e 61 e7 e6 69 73 d6 +3e 69 c9 da 17 29 6f e6 15 d6 33 c8 62 18 dc a3 +99 25 8c 04 f8 05 bd 04 d9 dc 97 a2 9f 39 d6 06 +ff 8e 9c 0a 13 71 aa ee c0 03 ea 27 48 95 ff 7b +a1 50 2b 28 f8 17 63 02 c2 4e ec e5 b5 28 d6 71 +00 + +# PKCS#1 v1.5 Signature Example 12.10 + +# ----------------- + +# Message to be signed: +08 4e c2 87 86 5e 8f e6 88 04 72 37 20 97 ad 5b +96 4c 40 a9 35 ee d1 be a5 1a b1 b5 bc 75 c8 46 +bb cb d9 54 88 e9 ec c3 63 cf 07 3a 90 b2 0b e8 +b6 79 36 46 22 f3 45 e1 22 d0 56 6a cd 34 a4 ae +11 24 45 25 a3 8f 47 dc 1f 92 b1 7f 89 ed e0 6d +83 6b 44 26 ec bb ea 79 33 ac 0e 84 7e 55 10 33 +b5 f7 ea 4e af 1f 63 f3 47 9d b7 ea f8 02 c9 96 +de 92 33 86 cd 15 b1 22 de 5a 23 98 d3 f3 97 02 +c3 e9 06 5c 32 73 95 b9 a9 95 fa 25 4d e9 c7 ad +b4 51 + +# Signature: +13 a7 f0 04 c0 a8 8d 51 3e 2f 1a ae ab 41 7f a0 +b2 70 2f b9 3b 82 87 20 cc d8 00 cb b0 af 5a 19 +65 72 5b 6e e0 58 71 17 cb cb 81 a4 63 18 52 1c +95 0d d8 46 9b d8 55 73 f5 d2 9d 86 53 03 eb ac +45 c7 f6 03 1c 6f 93 78 eb 12 b4 2f 05 09 44 31 +6f 0b 93 db 89 9b ec 93 7d 5d 0f 58 ed 40 70 04 +01 cd 32 65 a6 a4 4b 09 bb 11 a4 38 ee a0 77 15 +ef e4 2d e4 e8 80 8f 88 24 02 61 14 8e 8d e2 93 +ed + +# PKCS#1 v1.5 Signature Example 12.11 + +# ----------------- + +# Message to be signed: +61 07 00 00 7c 3c 6c b0 96 c9 94 d6 5d 95 c9 b9 +a1 47 c3 46 14 cd 72 2f 29 eb c5 e0 93 78 6f 79 +09 48 02 14 1a 31 08 d2 ec 8a 87 4c 53 18 7e b0 +d6 ee 2a 85 91 38 cf bc 29 22 15 06 d0 bd 89 b0 +f3 db ef 50 6b d1 ba 40 36 b0 f1 ec 00 73 32 70 +60 75 2b 42 8c fa 12 db 28 0c 53 aa e5 f3 e3 57 +0e 91 8c b0 9b 90 e9 84 7f 1f 5c a4 48 7a 6b f3 +ed ad 42 5f 78 40 7e cb e3 f9 bc 7c ab 00 75 66 +58 79 43 1c 6c c3 9e 0c 7e 67 00 60 67 41 8b ee +8d 0d b5 e7 db e1 2d a7 16 ca + +# Signature: +1e be af 85 d1 8f 37 84 0e 8a 3e af 07 d6 9f 52 +4d 88 3f a4 2f 29 1e 20 07 db 59 5a d6 93 0e 8d +5a 75 b4 0b b9 5b eb 72 d7 ce d0 38 17 97 47 e9 +66 1d 08 38 40 d5 87 dc df 21 c3 ad c7 d4 7a 01 +f6 ec a9 c7 bf 9e 2a 98 87 75 1b 36 d1 ab af 25 +a3 13 fc 29 d7 f8 34 d2 a2 48 29 85 57 5e 1b e2 +4b c4 ef 43 a5 7e f4 b0 a6 83 69 93 e1 1b 67 07 +85 04 e3 b7 9c 72 17 75 f5 b9 9b fa cc c4 8a 8c +34 + +# PKCS#1 v1.5 Signature Example 12.12 + +# ----------------- + +# Message to be signed: +da 31 f9 be 26 09 + +# Signature: +1d 2b ba fc a4 1c a0 6c 4b 81 1c b9 d8 36 96 87 +16 6d 14 d9 f9 2c 5b 98 fc 7c 77 2f 2d 75 d3 5a +5f 9a cc e5 9b 99 ef b2 dc b9 7d cc bb c8 6d 7f +d6 b4 ae 8b ea b1 e9 81 e6 c7 74 5a 1b fb 4c 1f +44 a4 72 b2 ad 07 d4 1c c1 75 15 b7 b1 4a 49 99 +0b 24 34 42 ff 2c 8f e5 05 b1 84 9f a9 91 ca cf +68 09 a2 0e 55 f2 af 77 98 87 0d 65 77 6f 1f 9e +e4 87 97 e3 13 aa 66 a4 7e 69 5f 3e 73 1b 2c 7f +30 + +# PKCS#1 v1.5 Signature Example 12.13 + +# ----------------- + +# Message to be signed: +f9 8b e5 2d 9a 5e 55 ad 92 + +# Signature: +29 2e a3 4d 3e 61 18 bf 8c d0 54 e2 15 17 e8 63 +ce 7c b7 dd 72 73 30 8f 7e cf ea cf 9b 45 75 83 +d9 b9 b9 7c 54 ab f7 4e 5a 5c a3 6a 87 06 7e 47 +d6 7a a0 47 a1 c2 ed 7a 23 d0 55 ab 4f 09 4a 83 +c4 39 ef 8d d2 d0 20 35 ef 05 62 d9 67 31 3d 81 +10 2f c6 8b 74 52 5b b0 e1 d7 96 2e b2 75 8e c5 +e5 ae ab 65 a9 3d 2e c8 e6 55 40 5a f8 8c 00 fa +35 f5 9d e9 d0 cd 80 45 ab d3 71 73 b9 fc 6c 51 +d8 + +# PKCS#1 v1.5 Signature Example 12.14 + +# ----------------- + +# Message to be signed: +f4 38 ef f8 4c 37 3f c1 27 44 a3 84 15 82 43 dd +97 f4 36 5e 87 d7 1e 8b 56 b2 97 91 df 44 ad f3 +49 e7 62 60 04 a2 c5 33 35 ec 63 52 cc e2 ed d9 +63 94 7f d2 39 38 93 c2 48 ba 1b 84 08 42 ca 77 +6c 31 72 9f 70 7a f5 04 11 00 1c 28 7f ba 8f e7 +25 02 32 0c 44 5b b1 43 fb 7b f5 39 4e c1 fb 2c +d5 01 59 24 32 15 40 91 de 5a 23 65 d6 78 f3 57 +82 fe a8 b4 7f 64 d6 09 19 f0 f1 d5 af a7 62 6c +40 d1 6c ec 19 bf e0 25 d1 16 f4 2d 22 e2 0a db +56 37 5a d7 70 89 f9 a9 33 81 fd 78 b7 b1 51 1c +b4 e4 98 4d 2d dc 7c 9d 75 b3 10 f2 95 42 25 60 +d6 6e 36 02 a8 71 20 96 16 13 1a 84 71 43 dd 07 +8f 23 58 7d b5 02 dd a0 3e 18 60 64 82 db be 01 +4e a0 83 b7 ec 16 1b + +# Signature: +0e af eb f1 5d 84 ee 4a 13 f1 a8 2b 84 05 11 86 +41 e2 2e 51 da 94 d8 58 87 fc 4a 3b 11 f0 32 49 +cc 39 a0 37 45 01 07 1c 7e ef 4a ba a1 14 08 d0 +2f ae 17 86 de a3 75 88 47 9c 90 d6 27 69 85 91 +c3 ba e1 fe fd 6e 8c 40 e3 ff 4b 9f 60 61 e0 6c +12 fd d2 1c 7f 45 dd c5 b7 8d 1c bc 41 c1 57 06 +fa 20 ba 92 f9 9f 58 b2 2b e2 76 75 be e0 81 a0 +60 67 ee d1 58 f8 e2 0b f0 4a 6e 96 8f 71 9a 32 +34 + +# PKCS#1 v1.5 Signature Example 12.15 + +# ----------------- + +# Message to be signed: +fa 1c 0f 7b 10 15 a8 95 b1 a5 65 f3 29 96 b2 b8 +cc fd 86 4b 95 54 4d bb 9c f4 f6 e1 a8 41 de 92 +06 d5 57 26 fd f7 ee a2 bf 33 6a 82 9f d2 bc 12 +09 bd 21 5a ab b9 77 d2 3a 08 3f 10 ae 69 db 43 +7c a3 2d 7b fe 4c 88 25 b9 34 88 f0 1a fd f7 84 +45 8c ef 5c dd 8d ff dd 17 + +# Signature: +25 e2 2e 6d f7 fc 6b d4 e0 f6 1e bc 8d a0 63 fe +47 8a 3e d7 4d 68 f7 76 34 35 e0 e3 74 f6 52 62 +a5 d7 61 2e 86 78 59 61 22 c0 e5 b8 fa 0c 0b 12 +81 2b a9 65 3a 0f 27 38 83 c6 26 4c 6d fb 74 bb +34 40 5d 2a 04 30 43 fb b0 ab f2 af 7a 12 3d 2d +db f1 69 92 e0 9b aa 37 d7 31 d7 2e f1 99 62 65 +8a 8f b0 10 a1 0f 7d 55 62 ad 54 33 47 90 01 af +36 d3 d3 26 ea db 2e 9a be c7 b5 55 70 9d 5d 47 +e9 + +# PKCS#1 v1.5 Signature Example 12.16 + +# ----------------- + +# Message to be signed: +82 8e be 2f 51 e5 88 29 cf a6 15 26 dd ed 7e 1f +1b a3 11 db f1 06 4c 08 ac 0b b5 d6 71 6e ab 29 +8a 23 d6 3b 79 3f fd 9d 9c ea 60 22 95 98 82 3f +28 2f 10 7b 6e e8 8a 53 fd 93 e7 dd d4 8a 73 1a +21 09 ff ed c8 9a eb a2 c0 f1 6b cb 14 0a 0a 89 +dc 57 ee 8b 5d 00 0a 21 42 17 5b c7 07 bb 40 9a +ae 3a 03 9c 66 3d 01 9a 0b d9 13 c1 3f 7f f6 f6 +b9 1e 90 5a 58 9d 38 b1 50 48 5d 89 09 2d 18 a3 +a7 62 25 27 65 52 5d 98 45 66 42 5b 05 77 0d e9 +a8 be f4 43 ff 5f c1 48 33 af a4 cc ec e5 42 d4 +f2 ce f1 e7 96 f5 9f b3 a4 bf 37 cb 67 7a e4 22 +36 66 c8 2b 31 a1 6a 6c d7 01 a0 49 3c d9 96 86 +6c 84 bf cd df 85 2b 19 ff c8 9e 93 61 79 fc e8 +b9 9e 72 fd 4a fc 28 b5 11 73 af bb 25 c4 c7 + +# Signature: +16 17 55 9e 43 ba 18 2e 95 34 86 43 6f 15 b6 02 +83 1e 42 ee d2 03 c2 69 f6 53 bf 63 9c 2b 76 0b +0d 49 fb 53 2c a8 ad 01 e7 b4 af 83 72 92 55 db +55 9b cf 55 fa b3 65 9c eb ec d5 37 69 4f ef 2d +ef 9c 9e 76 2d 05 d2 32 1e d6 88 c3 f7 e2 c0 57 +33 ab 4f a8 1b 08 cf 79 fa cb 75 c3 20 0b 7a 48 +3a f0 8c b1 83 c5 09 27 cc 61 69 e4 32 f7 fc 9b +11 78 0d bf 4d 3b 72 d2 d0 b8 55 93 d8 b5 b0 18 +2a + +# PKCS#1 v1.5 Signature Example 12.17 + +# ----------------- + +# Message to be signed: +bb 4a 6e cc bd d6 de 0a c5 c3 b7 f9 97 98 10 4a +58 69 c1 cf 1a 1f ac 7f 85 9f e9 51 49 29 7e b7 +79 11 00 59 e2 69 f1 27 56 f0 8a 54 8b 66 af + +# Signature: +27 7b ae 63 e6 e3 25 3a 0e 20 4f 4e 6c 9f e8 4b +04 0b 86 4f 21 ed d4 42 6d 82 be 8f 1b 91 1b 0b +d2 81 cf 11 49 53 d4 02 09 da 2e 9a ae 13 3b cd +18 55 ef 0a 99 69 3a 94 43 c9 3f 6d d2 75 f0 58 +fd 1b b6 95 32 b6 4a 1d d7 e1 d0 e7 80 d7 52 04 +fa 8c 61 c2 eb 5d e8 82 72 cb 93 ae f0 80 f7 02 +bb 78 88 94 25 a5 f1 66 f6 3b 5b 1a 31 ec 5c 1c +26 a5 99 fa fe 58 77 42 98 b9 7d b3 14 fc 81 d0 +92 + +# PKCS#1 v1.5 Signature Example 12.18 + +# ----------------- + +# Message to be signed: +f1 d1 11 ad 08 e0 38 ca 3a b4 e5 2e 5e ab 71 01 +87 6c a9 be 62 6a 13 59 17 f4 5b 1f 9d 1b 32 ef +e4 ff 86 7a b8 a3 05 f9 49 c0 04 8b 25 f5 46 22 +61 b1 a3 49 3b 81 90 21 0f 5c fa 6b f7 e5 c3 00 +54 98 de ec c1 e1 c5 04 f3 a3 49 98 be 6a d6 ac +00 40 51 c4 e0 a3 db 2c 22 eb 5e 14 16 55 28 df +78 12 a2 0d 5c 7f 05 b9 40 ca 13 e9 38 3a e0 0d +6c d4 d0 f4 ae 3d ad 04 7a b9 c4 17 8d b6 6d 3b +80 96 0c af 0a 92 4d c9 4e b8 e0 77 09 bc db 34 +9e 90 fa 2e 10 c5 d5 26 d2 21 9c a7 6f 88 01 fd +c6 61 bd ca 6a 93 da 48 d0 45 ac 37 51 34 cc d6 +ff 7c 52 fd 15 c7 cd 3d 1f 31 af e5 04 bc e7 c0 +33 3a 89 79 e3 ce cc 53 c4 ea dd 7d 95 d4 6f a3 +b2 a9 f0 06 10 0d 6b fc 0e d5 ee 77 69 4f f1 a2 +4e 16 a5 44 de 71 46 52 90 dd dd 18 9f 01 67 03 +59 f8 c6 b5 d4 c6 b6 b9 f5 c5 7a a5 a3 8f 07 99 + +# Signature: +0d e9 42 31 c0 6a b1 87 b0 0d da 2b 34 e2 b4 cb +ac 41 f6 08 c4 8c 72 27 a6 28 2a 17 9e 58 c3 2e +f5 dd c9 76 4f a2 df c3 fb e0 21 dd b4 81 56 a6 +37 3c d6 9b 85 d3 64 d8 9b 5a 32 fa bb 2d 46 5d +05 62 d4 a1 dd 6f ca 64 78 0b 06 2a 94 71 24 a7 +fc 0b 82 e4 fe d1 2b 8b 4f 72 6a 0c 85 39 c6 cd +e2 1a f6 55 ac c8 de 1e 7b a9 d6 7b 87 b8 e7 77 +d4 8a cd 86 8a 80 db 15 31 4f 35 55 60 10 35 77 +eb + +# PKCS#1 v1.5 Signature Example 12.19 + +# ----------------- + +# Message to be signed: +9c 4e cc 4b 24 44 a4 01 bf b6 f4 b7 24 49 23 a5 +ad 33 86 c3 b8 41 67 8c f5 e6 44 7b 8a 3a 07 59 +86 c3 3f d0 01 b8 43 72 4d dd c4 21 2f f4 5a b3 +fe ca a9 0a 16 f6 b5 59 2c 51 5c c4 ee 54 ae a4 +59 34 32 16 70 96 67 8f 93 41 59 85 6d 14 c4 32 +e7 d6 d2 8d 71 b2 68 7f 54 ed 71 9e 5c 20 11 00 +68 8e 85 f2 0e 79 a9 ee 8a a4 b6 14 31 34 3d 1e +99 c2 14 35 c6 1e 8b c1 04 f2 ba d5 29 60 fc ee +e6 7b 85 03 3d 3a ee fa e4 13 ce 29 70 1e ff cb +02 b4 84 a0 31 e2 f3 19 ef 7e d0 d6 e6 9b 29 16 +ee b3 8c 4f 19 42 ba 23 c2 a1 79 0c e3 fe 09 d0 +1b 9b 9f e6 db a8 dc 21 0e aa 8f e7 3c a7 6f 1b +5b + +# Signature: +18 53 c2 1a 4a 18 54 7d 86 7b 3c ed 02 da f0 b2 +2c e8 d4 d5 af 2b 8e f5 f7 c8 fd 38 5b 81 53 64 +8d 81 83 1d 6a cb 5d a8 30 f6 77 40 25 9f fb 33 +9f 7b 90 af 48 83 81 9c 47 15 e0 8c 28 99 d4 c7 +24 6e 07 e5 bc 6e f3 cf d9 a0 4d a0 6c 43 e9 5c +77 2b e2 21 cf aa f6 95 4e f9 33 31 e5 95 ff 48 +92 1f 05 fc e8 fa 0d 42 9e 0c 99 56 2a 9c 2f 68 +eb f3 2c f1 c6 c6 bb 8b 27 4a 2e 42 d6 71 59 12 +ff + +# PKCS#1 v1.5 Signature Example 12.20 + +# ----------------- + +# Message to be signed: +c3 81 e6 03 99 86 51 66 d2 ba a0 31 45 26 83 34 +18 40 39 e0 53 35 a3 00 c2 80 4e 2b fe f5 a7 d1 +4c 44 3d 65 38 e1 6b df 9d a7 ad 1f ea 63 4e bf +e1 13 bc 82 1e 79 a4 49 b2 eb 2f 57 c2 1f ba 35 +ff cc 6a 7e 52 55 72 27 7e 8f 55 37 c7 b5 b9 79 +4d ef b3 9a ab 06 07 85 d1 99 40 02 dc f8 07 01 +2e 1d 17 91 da 94 3b 2b 75 9c 36 6b b4 24 e4 2c +9c 20 43 ce 78 8a 25 fb fe bb 87 e7 4c b0 20 b1 +1e 8e af 16 18 84 d6 67 2b be 9c 09 fb b3 b8 af +a0 61 + +# Signature: +19 90 69 57 37 53 01 8f 33 59 2a f1 5c 1d 31 31 +bf 5d 8a c4 f6 4c f6 14 d3 a0 1b f3 72 df 00 2e +b5 b5 fc 8f 82 ba 13 7f 83 dc 14 2e de 38 c5 81 +80 e7 bd a6 9c 4f 1b c7 bf 96 ec d3 fa 79 bc cb +dd b7 d9 2e 4f d8 64 c5 fa 93 3a 4d fc 60 0e 10 +83 00 8a 38 6f 4d 02 2c 20 24 ff 7e 0b 37 22 ea +fe a0 5a 1e 02 c7 a6 3e eb 40 f4 f4 c4 f6 60 c3 +24 72 a0 a7 89 23 e3 86 3a 99 44 5e 7c fe 27 00 +60 + +# ============================================= + +# Example 13: A 1031-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +70 e9 23 a5 a0 cd 8e cd f9 9b be 93 d7 d0 28 82 +95 5d 91 b6 ef e3 ce c8 6c 93 d2 1c 0a c3 01 b8 +29 3e 51 43 5b 87 8b c6 b3 4b ed 41 11 59 0e 76 +46 76 58 8b 11 6c 2a 36 a4 c7 7e d9 c9 0a 13 c1 +4d 23 e1 99 47 87 fc db 8f 5c 97 41 0f ca d4 04 +5b 85 85 70 2c ce 29 da 11 f9 7e 79 a9 7c 2e 5f +6a 5f c0 bb 8c e7 6d 15 54 a8 bc 47 96 17 20 d3 +64 05 0b f2 74 19 bf f1 68 c0 a7 ec c8 73 4c b5 +a5 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +70 e9 23 a5 a0 cd 8e cd f9 9b be 93 d7 d0 28 82 +95 5d 91 b6 ef e3 ce c8 6c 93 d2 1c 0a c3 01 b8 +29 3e 51 43 5b 87 8b c6 b3 4b ed 41 11 59 0e 76 +46 76 58 8b 11 6c 2a 36 a4 c7 7e d9 c9 0a 13 c1 +4d 23 e1 99 47 87 fc db 8f 5c 97 41 0f ca d4 04 +5b 85 85 70 2c ce 29 da 11 f9 7e 79 a9 7c 2e 5f +6a 5f c0 bb 8c e7 6d 15 54 a8 bc 47 96 17 20 d3 +64 05 0b f2 74 19 bf f1 68 c0 a7 ec c8 73 4c b5 +a5 + +# Public exponent: +01 00 01 + +# Exponent: +02 9e 10 f6 bb b7 d0 2d eb b1 a5 d5 19 0d 69 06 +ff ed eb 9d 15 4a 0f 66 db 87 80 b9 28 31 b5 96 +3e 94 84 7f 3e 7d b1 aa 91 48 fb 0e c5 57 6e 6b +a4 fe 04 d6 f2 78 32 b1 52 18 12 d3 7b 22 d9 ea +e2 80 08 e0 92 c6 7e 72 32 42 67 e1 b1 ee 45 43 +55 74 1d 8d e1 d2 a6 a0 50 74 bb 1c e5 81 8b 41 +bd 19 dc 6b 58 c8 93 7d 8a d6 40 d7 04 3f a1 1f +46 8d 6c cb ec 4a de 52 0a 9e 15 9d 60 5d 09 28 +29 + +# Prime 1: +0a b4 64 fd 6f e3 3c 45 9a b2 dc ce 5f 78 a4 d7 +4f 92 b9 97 d4 bf 54 2e 2d 85 4e 76 2c 85 86 fc +43 57 cc 58 cb 33 36 33 b0 95 a5 ee 04 a0 32 48 +53 64 d7 0f 67 a3 aa 04 85 4c 7a 87 a6 9c f4 c2 +ad + +# Prime 2: +0a 8c 3c c5 04 13 40 f4 32 fe 0a 78 73 13 57 79 +16 fe 76 c0 39 f9 71 75 9e c5 0e d6 c5 b9 a7 36 +9b 68 96 9e cb 52 59 fe 9c 50 d0 75 9b f8 b3 aa +c1 a5 d5 b5 28 8d 67 89 e7 18 fa 37 ef 42 39 95 +d9 + +# Prime exponent 1: +bb 29 5a 95 d5 b3 3c 1d c0 b1 8b f6 c1 4a a0 d9 +f2 6f 72 8b 39 36 0a a1 59 45 6e 94 c3 d9 e0 48 +c9 2a 4f b6 31 1d 36 92 8c e5 f4 47 a4 99 4a 8f +47 87 d8 a9 7f 68 11 3e f9 66 34 f5 90 2a b7 51 + +# Prime exponent 2: +02 fa 11 2c 89 39 e5 db 05 89 2c eb 51 8e e3 e1 +08 dc 48 27 78 35 2e 10 43 fe d9 71 43 dc 61 94 +c7 c7 7c ba d4 27 29 be f1 de dc f6 54 4e 9c 66 +54 c0 b8 cf a7 e2 40 96 6a e2 61 bb e7 8a 89 36 +01 + +# Coefficient: +a8 8b f3 ff e9 3f 40 4e 06 82 1c 97 71 ea e6 08 +15 71 2d 6f 94 52 71 f6 f3 6f 03 69 d9 66 c9 20 +c7 f8 cb c7 84 25 ac bb 9c e0 fa 1a 03 22 f5 0c +97 b8 11 5b d1 51 91 f2 24 b5 68 d1 d6 ec a6 db + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 13.1 + +# ----------------- + +# Message to be signed: +b5 e8 6c 8b a3 98 5a a5 54 1d f9 5e 51 3c ff 67 +61 2e af 2e 16 68 85 76 f7 d6 73 f6 f1 89 1f b7 +5c 9d d2 cd + +# Signature: +6b 42 fd 51 63 09 19 7f 8a f3 c7 3e 39 62 4d 8e +ba be cd a3 ec 3c e6 57 b1 11 7f 43 e9 83 87 7a +1b a1 aa f8 e9 5c c3 99 91 d9 2e 35 e2 db 1e 41 +30 90 14 3d 16 46 71 98 b9 b9 a9 90 d7 74 c2 7a +d3 bb b4 35 2d 3f 07 5d 61 73 2c 6b 58 ec 0f 66 +e4 92 a3 f7 ac 4b bc f0 12 ed 6b 40 1f eb 4f f3 +95 cb 8b 21 8a 81 d6 17 31 ee ce 37 6f 68 8e 66 +ae a6 98 b4 a8 86 2f 58 c9 1d 87 60 85 49 6f d0 +14 + +# PKCS#1 v1.5 Signature Example 13.2 + +# ----------------- + +# Message to be signed: +95 46 34 6c f2 21 94 c7 87 88 81 70 a4 82 f7 f4 +92 17 c3 94 0d c6 21 0c e3 9e 45 50 a3 9b 45 28 +22 41 9a ea c2 4b ec 19 8b b3 59 d0 8b e8 19 6d +f2 e7 57 76 61 96 c9 58 e2 b1 59 c7 4c 1c 30 23 +c2 db cc e9 ed 5d 0e f3 fb 51 45 0b ff 64 45 db +26 5e 60 6e 19 4b ee 06 4c a5 b3 21 d7 e1 55 14 +23 0c 2b 3b 55 d5 da 4c d0 40 52 2f 7b b8 6a 96 +2b 81 3f 9d a3 9e 51 38 9b c6 4f 56 e4 47 b2 a2 +bf 81 9d 7a 80 09 4e 2b 8d e2 7f 10 4b b6 eb 2f +2f b4 3a f1 d0 1e ad ca 23 a1 96 ba 12 5b 6a 78 +57 99 74 c0 ee c8 a5 49 67 71 f6 7d bd 50 69 f3 +36 e4 ef 1f 40 47 42 df c6 9c e3 25 aa 64 9f 8a +63 31 cf 40 35 55 e1 3f 08 10 a7 63 50 a7 e1 8d +29 92 fa b4 8f 39 7f 3b 93 c5 bd 5a 6f e1 d2 c4 +61 8b a1 f5 9f 00 2d c2 57 ec 39 ee 2f 87 62 98 +da 90 f7 44 0a d4 c6 c9 3f c1 14 df 05 + +# Signature: +67 e4 14 99 3f 98 7a 22 64 3d d0 39 e7 f9 fe 1c +ae 74 4a 7a e4 1d 4c 04 4f a4 ed 8d c9 e3 40 ce +bb 1e 2a fb 19 8e 84 7a ef 4b c0 61 fd 80 0d 81 +d4 d3 67 b0 fc 2f 73 09 33 c1 9b 88 d4 dd f0 5e +d9 8a 58 56 de 5e b4 5b 11 6b 7d 24 fe b4 56 77 +84 9d ab 76 e9 e0 cc b4 5b a6 b6 f6 14 1f 37 bb +ad 7c 19 1c 37 77 11 3b c7 38 8e 4e 46 44 ec a9 +47 03 a7 2b dd cc 6f 50 cf 98 0e 3f 6d e3 9d 73 +12 + +# PKCS#1 v1.5 Signature Example 13.3 + +# ----------------- + +# Message to be signed: +56 52 b4 c5 75 20 b2 55 fb 96 f7 0a 30 ab 92 ee +c1 93 99 56 b6 a9 43 c8 3e d0 98 6e 2e 6e e4 ef +bf 8a 52 28 78 67 28 12 03 a7 a6 d1 d8 86 b7 00 +59 52 b4 3b 77 85 44 ed a8 98 e0 df 2f a0 6f 68 +38 03 18 f1 4a 53 fe 55 d7 2f 8c fa 6a f2 1d 93 +bb fc 20 d3 58 c2 08 c5 62 d7 39 be 00 01 ce 07 +fd 8c d2 f4 6c 3b 44 c8 36 51 88 09 b7 6f 3a 70 +cf 69 26 be 06 9c 35 75 d5 + +# Signature: +01 64 11 a2 31 a7 38 94 4b 3e 44 f7 88 5c f8 1a +ca b7 32 d1 73 6d e3 4c 56 cf 40 f9 9a 6c e4 00 +70 a2 0a a9 4c 48 78 44 a9 3c ef 28 7a 58 bc 0e +a1 81 b2 cf 27 d9 14 f2 93 b9 29 77 9d 39 03 6c +4e 5a ae d3 5e ee 8a 7f d5 0e fd 09 6c 91 a8 f7 +2c 3c 14 1c 57 6c 8d 10 b6 36 fc 4d dc 1e 67 14 +f1 7f fc ce 10 6d 22 1b 4f d7 d6 fe 1e 7c bd 3f +3b 08 f5 54 6b 44 d1 fe b7 18 fb c1 33 70 c7 fa +2c + +# PKCS#1 v1.5 Signature Example 13.4 + +# ----------------- + +# Message to be signed: +6d 57 f0 79 a3 e8 ad cb 47 cf 2e 3c a9 76 e0 3b +09 c7 7d 1d 9d 9d 84 84 35 7e 91 23 09 e8 f4 a8 +3c b5 0c b6 a7 38 8c 41 4a ec 84 46 71 ff 81 06 +51 e8 28 10 3a 1f 6a 19 9b e2 60 f7 46 00 02 8c +6a 7b 7b b9 41 6c e7 b6 35 0a 3a 68 05 62 0c f5 +e6 b0 09 5d fa 22 b5 46 01 f6 19 af d1 0d a2 03 +d2 81 90 cf 9b 0d b5 98 6d 29 30 33 69 1e c5 bb +ba 6d 73 ea 32 47 2e fa 3f 16 0f d2 b1 b5 e4 3b +0b fa d3 16 77 30 5f ef 46 72 44 11 4e e1 0f 5c +b2 d6 7b 47 83 23 a7 11 04 1e 29 4c 46 b2 ed 39 +cc de 07 9c 87 7f e7 5c b8 75 14 4a c3 1e b0 31 +a7 38 a4 ce fe f9 1f 01 7b a7 15 23 f5 12 48 18 +cf 48 b9 72 bc 47 c8 f2 ed 35 6f 5b f6 91 fd 94 +67 0b b2 + +# Signature: +31 5c e4 17 d0 bb d7 3e 7c 43 56 79 7e 73 ed 7a +bf e9 fc ff f1 a5 34 28 99 a7 d1 1f b0 d0 54 2b +fc ab 66 de 2e 4e c0 7c 7d c2 be 7d 79 72 90 a3 +0d b8 c4 07 dd 16 37 65 88 a6 dc c1 a2 07 bf 7f +f3 11 54 0f aa 9d d6 f1 9a 73 ab 25 a7 49 6e 68 +2f a8 a7 05 40 81 07 6c 1a 02 15 7b e6 3e 7f 64 +5d e8 2d f7 c6 15 50 3f a8 3b 4e db a2 05 81 81 +2e 09 7f 65 05 6e d4 17 f6 f2 48 03 53 0c f8 18 +58 + +# PKCS#1 v1.5 Signature Example 13.5 + +# ----------------- + +# Message to be signed: +bb 75 44 6f 78 78 23 dd a2 42 2b 1a dc 7d 7f ef +d0 6a 6e 9a f5 c0 49 01 ac 5b 99 91 3a d6 29 8c +9d 1a 33 22 e8 b2 17 e4 e0 99 4c 42 20 42 80 d4 +04 d0 1e ce b5 ec 53 fb 86 f7 61 a3 96 b2 3a e1 +9d 46 79 05 a0 fe 80 50 b8 95 d8 ba 37 46 68 5c +47 43 9f 90 c3 66 9c 70 ff b8 19 94 56 5c 4d f2 +a3 1e b2 a4 52 bc 3c b3 12 b8 14 7c ec 19 10 32 +f3 8f 3b 3d 89 d7 58 2b f1 8e 7b 72 75 fb 4f 16 +ee 89 56 7e 2a 56 bc 73 b3 e2 e1 09 f9 94 0e bd +10 b9 df 2b 88 ac cf 0b a1 8e 5b 34 95 20 d2 c7 +f5 a3 1b d5 22 6d 12 ec 35 bf c9 e3 62 03 e1 35 +06 ba 12 b7 56 c8 ba 00 af 91 b8 5b 0b 4c 07 c7 +f4 84 ad c4 58 c9 26 aa eb 4f 08 2f ec 98 7d 9f +27 6b 89 49 59 7e c0 40 1b b7 1a 2f ea 9c 7b 74 +e0 df e6 aa 52 ac 8b 80 be ea d3 36 a4 9d b2 2f +b3 + +# Signature: +53 d0 d7 95 bb 08 2f 20 01 03 6f 47 2c 2e ce 6e +7d 2d b6 9f 29 2d a7 21 36 75 c7 cb ba 0d 33 b2 +32 12 f8 f4 3a 4a 8e 09 a6 a5 0e 01 9b bd d5 9a +58 89 8c c4 6c 58 a4 6e 42 ce 7b a0 93 fb 46 92 +f3 83 de 33 a9 a3 4f 47 c7 e6 19 38 bf 8a 6a da +a8 8d f2 12 96 b4 c6 7b 52 68 35 f7 57 f2 c2 6c +1d 30 9d 7c dd 5a d5 fd 8f 61 f8 51 ed 23 c4 be +2a bb 62 7d fd 81 7f 84 77 dc 04 2b 6a 2e 40 69 +40 + +# PKCS#1 v1.5 Signature Example 13.6 + +# ----------------- + +# Message to be signed: +88 39 39 d1 49 a5 44 e6 2e f0 4c 61 03 51 a2 df +a2 52 eb 9a 9d 1e 11 ae 54 c9 b0 7e bc f1 fd c4 +7e c1 d9 47 03 41 1d a4 15 f5 9f b3 e5 04 1e d9 +47 0e 7b cc 81 9b 5a fe af 86 0c 01 6e f1 25 bd +08 a6 cb 8b cd f3 b9 3a 51 dc ad b2 f6 8c 8c c3 +77 55 14 28 2a ff 75 67 ec 65 f2 70 d0 2b eb 95 +fb 8f ac 24 09 5e 17 06 e4 8b 52 48 65 bc 14 46 +1d 3e ce 8c 50 1c 3d 80 2a de 98 5a e9 5c fe 1a +b9 d6 b9 ab 0d 15 fc c8 86 6f 7f 25 9c 5e 41 c0 +2c d4 13 43 7e 7d 6b a7 f1 5b 0a 70 da fb d5 5c +0e db 6b 80 75 c2 7c ff 3b 28 9e 6c 99 e9 a8 84 +ff 7f 08 6d a9 f7 5d 6a 4c bb cc af 52 ba 25 c6 +34 2c 38 a7 6b 44 e1 01 15 5d f7 55 e3 9c 14 86 +2e 22 0c a3 6f fb cc 83 2a fe cb a8 7f 8a bd 96 +0a 57 7f 56 ca 6c d8 e9 91 26 65 8f 27 ac 6e 53 +c4 42 ed 47 66 + +# Signature: +1e c0 2a e6 a0 a3 f6 11 99 29 61 ca 27 cc bf 29 +6e 11 36 18 32 e1 ee 75 20 56 9a 9a ee 06 34 5c +da 22 b4 fa 48 fc 34 5e 47 78 bc 3c cd fe bd 2d +c5 a6 c9 d4 84 51 aa 44 1b ea 4b 95 11 99 65 4a +e8 d2 f7 52 2e 17 ed bc 2f 51 ce 15 cb cd 36 6f +49 39 cb 53 c3 b7 70 81 f4 a7 37 50 05 4e 00 b3 +0b a2 fe 58 f6 f0 2e 36 a8 62 54 23 97 db a6 a3 +cd 22 77 70 88 19 e7 8a 2d 87 6a 23 a5 a2 69 d7 +75 + +# PKCS#1 v1.5 Signature Example 13.7 + +# ----------------- + +# Message to be signed: +40 31 e0 de f4 f3 d1 ad 9b c0 82 77 0a 88 a1 d9 +b4 b7 10 75 48 cd f8 46 2b 0b ae 3d 99 4d 8e bc +4d a0 44 b9 05 dd 8e d9 1a 1d a6 76 72 78 22 36 +0e e2 b6 d5 e1 2b b7 03 16 d7 9e 8a bb 82 a6 43 +44 af b3 b2 25 88 5c + +# Signature: +0b e5 a6 d0 43 be 5d 27 d1 d5 1d 9e 3a a6 1d 92 +c9 d8 43 23 11 9b 48 c8 4a 80 38 97 18 d7 a1 aa +f5 7a 9a 0d 21 4f 65 06 48 48 64 df ae 85 db 7b +84 74 07 3a 8f 97 7b 42 b5 3b 40 7e 44 c7 c6 2b +16 8d 1e 77 78 f4 f2 78 57 bf ba 85 dd dc 8b 0e +9f 0e 9a 5b 6d e7 1a 04 43 72 0e 92 bb 88 b0 77 +cb a1 5d 3f 6e 2b e4 d2 7a 7c 50 9c 7d c0 3f 1f +dd 4f e3 38 a4 e5 45 c4 6c 03 45 22 cc c0 d4 5d +4c + +# PKCS#1 v1.5 Signature Example 13.8 + +# ----------------- + +# Message to be signed: +7f dc 96 a4 56 57 74 02 9f ff a9 3b 39 f0 5d ee +9f 84 fa 89 53 fd 0f 63 38 c8 1c 9d ec 6c dd 66 +1f fa b9 6f 0e 08 eb 0b 9b a9 ca 5b e1 7b 57 c4 +b4 86 8f d5 34 11 54 de 50 27 71 13 c7 18 53 41 + +# Signature: +1d d2 1f a4 95 be 7c 49 0f 98 2f 69 ea b1 4e 24 +da a0 4b d1 38 b7 14 32 49 cd cc d7 8c cf c9 10 +6a ca a0 3e c8 76 69 42 32 56 6e c6 ca b9 12 28 +40 f6 69 c8 00 f2 ee 09 2b b9 b6 cb 2a 45 42 a9 +0d e6 04 c4 f1 05 00 0a 3a 0d ec cd 3d d9 7a 32 +61 fa 38 22 7e b3 81 a1 f8 f2 3b 66 65 d2 84 80 +df b7 21 17 88 2e d8 db 25 d7 6d e4 0d e2 fb e7 +2d c3 94 ec 6f bd aa 99 c6 4f ad e7 29 78 a5 1f +c4 + +# PKCS#1 v1.5 Signature Example 13.9 + +# ----------------- + +# Message to be signed: +63 18 32 ab 19 18 cd 02 08 28 e4 7a e2 b4 47 6b +14 69 f2 72 e3 0e 53 e5 96 fb a2 6b 40 29 37 dc +44 c2 ea 57 45 c7 9d 2d c6 4a 10 e1 22 5c a0 b6 +92 9d 49 54 bc 5d 37 40 96 fd 87 8d d1 01 f7 66 +63 13 d9 a8 f8 26 bc 67 14 01 42 2c 1c fe 1a 6d +01 a4 d7 86 4a 14 c6 0c eb c2 f0 70 91 4c ee de +b1 78 2f e5 40 a0 a5 d2 57 84 44 f9 b3 60 34 ec +77 d6 b8 03 a0 c9 76 1b 32 75 92 aa 48 46 63 5c +56 3f 1c 6a 6d f6 8f aa bc e4 97 af 4d c9 a3 64 +2b 75 a4 a2 94 d3 08 56 8e 6d 73 c1 1d b5 67 24 +04 2b 55 c3 a2 4a 7b c7 a1 05 0e 4f 44 8b 6a + +# Signature: +45 d3 a6 ae 8f 48 35 5c 01 2b 50 10 79 ee 92 af +fe 3c 9e 60 2e 4a 08 0c fc 94 72 3a e9 6d ac 2a +66 e4 55 a4 0e 72 8b 2a 1b 27 e6 22 40 55 4e c7 +c5 c0 ad 6a a0 0c 09 22 e5 3d 7b 12 ed 42 c0 87 +32 2d 15 36 e4 6b 7d eb da 80 95 f5 5d 1e 12 bc +24 42 f4 3b 4d 12 8f ee 23 1d cd 6f 8c 37 aa 6b +cf 4f e7 b5 e0 de a9 c6 70 9d 3d 91 f9 e4 2a 53 +16 8a 16 b6 fe 99 7b 5d fe ba fb 46 ed 9a ea 5c +66 + +# PKCS#1 v1.5 Signature Example 13.10 + +# ----------------- + +# Message to be signed: +8b 04 3d 90 da e3 41 66 85 d5 3a 5b 4c 3c c2 54 +cd a0 cb d2 3b 4e 40 8d e8 20 a4 da 7a de 6d d9 +5d 4e 1a 97 e2 31 2c 3e 84 26 1e e0 b6 ce fe 60 +e6 b0 82 fd 59 65 ef a1 64 8f 4f ae 61 60 5f e3 +55 33 27 00 46 96 05 26 53 47 e6 54 7a ea 77 5b +85 6e 5a 46 c3 41 d2 99 52 bb ea 92 70 49 96 3e +37 40 20 8c fb 0b 65 28 57 b6 f5 2e 36 6a 17 0b +e3 4f 13 d3 58 46 bd e6 97 20 46 20 01 b0 9d d2 +68 b8 9b 09 00 31 8e 73 3d b2 00 9e fd 9b 51 77 +41 e5 10 d3 f3 94 f7 ad b5 45 59 b1 57 + +# Signature: +6b 27 8f 36 2c 29 2e ea 09 b9 0b f3 53 d1 43 f2 +ca 09 9f f8 79 57 34 79 df 2a ff 9b 25 0d 1c 91 +87 c6 a3 34 3e a1 4c 07 6f 2a 20 c1 a1 9d b2 6a +ad 35 48 ec 6f b3 b2 fa fc 75 1b 59 08 2d 8b 23 +c8 2c 8a 51 f7 fa f7 a4 d4 a8 23 98 bf be d4 49 +bd e4 ee 9d c8 68 01 60 66 6f d9 c7 74 c6 aa 57 +7b 4e c5 4c f0 d5 bd 9e 3d 1a fa 9c 3b 4b 91 46 +76 78 c9 d4 c4 fe 40 0a a8 57 a3 b0 54 5b df 84 +a6 + +# PKCS#1 v1.5 Signature Example 13.11 + +# ----------------- + +# Message to be signed: +3b 28 a6 09 2e 47 08 98 af 07 0a 08 7c 45 53 18 +8d e6 c3 44 bb 0b 5f dc 7f 66 fb c5 2d c9 3a 8b +92 a3 74 11 20 37 d6 a4 32 86 12 8a ce f9 5a 35 +05 c0 ab b1 af a6 2c 48 cb 21 36 07 7f 8a 0e 0e +0b 5a 4e e9 b2 c7 7d 7a 0c 0b 53 f3 8a 51 cc 3d +b9 b5 83 b3 ae c0 7f 1e 22 4f cb 3f 1d ad 19 5e +05 86 59 a9 d1 1f 8e dc 74 44 99 46 86 ed 62 c9 +75 66 e9 e0 0c bf 8f 0d bc 17 16 e6 b7 f0 f8 8f +e8 9a 86 7a 41 d6 43 13 5a d8 b1 8a a1 43 e7 37 +5d f1 95 29 + +# Signature: +32 62 fe 17 e4 4e 5e cc 84 31 70 d3 ae 27 51 da +1f 48 d6 e9 61 d8 1e 93 59 b0 98 2c 6d 61 30 8e +ba cf e2 60 7c 53 8c 17 0c e0 e7 2a 07 bc 01 48 +7b 29 5c 36 b8 e2 2a fd f6 e7 fe 39 c0 3a 5c 0c +36 61 06 1f 23 fb f5 89 0e ad 59 f8 72 c9 46 cc +e0 f8 16 c9 ed 3a 2c 1e 11 f8 f7 4d a1 e9 7a 39 +0d 53 4d 78 55 78 a2 45 5f cd 87 47 83 f4 57 2a +15 f4 93 7d ca 98 09 3f d0 e9 99 0a f0 00 52 56 +bf + +# PKCS#1 v1.5 Signature Example 13.12 + +# ----------------- + +# Message to be signed: +4f dd 6a 36 31 dd d4 bc 3c 76 07 19 02 a2 27 fd +5b 36 53 b1 f9 70 f2 b7 67 ef 55 4e 1c 75 ca de +81 9d 8d 1f ca 76 bc 10 54 1c bf 8b 1d 8b 0e 72 +55 f9 57 40 + +# Signature: +29 cb a5 b4 3f a3 56 57 75 89 34 91 b1 18 57 8b +14 b5 fa 1e eb e0 c8 07 59 a6 d1 91 e7 c2 13 1e +e1 0a c5 b9 b8 ae 1a a7 d6 96 c9 84 88 a3 5c df +a2 aa 00 6d 91 bf 7e 05 a5 c1 90 9e fb 20 da bc +82 13 3b 62 64 c0 42 18 0c 2c ca 65 45 9f 66 cc +7e b1 ba 75 d1 5d 4f 56 c7 52 8a ab 28 38 e6 79 +53 7a 4c 8d cd 37 d4 b4 ca 82 5c e1 65 fa 4a 97 +15 82 44 dc 87 c0 61 fb 12 00 1e 55 33 fb d4 cc +62 + +# PKCS#1 v1.5 Signature Example 13.13 + +# ----------------- + +# Message to be signed: +59 0c d2 30 50 e5 7b 28 d5 c2 18 5e ad 60 b1 e9 +52 9f 2b d5 26 13 eb 03 f6 ed 1a ef a4 a6 72 88 +d5 a3 a3 4f d9 5c a6 38 94 af 3a 40 cd 68 87 3a +1f 37 e3 54 d3 04 14 29 7b 19 25 4b c6 c1 a3 f7 +a4 75 20 ee a5 6e ff 77 db fd a6 bd 77 79 d0 2f +d8 16 fc 0e 99 91 9f e4 39 5e ae e5 b2 f5 f0 32 +cf c4 33 6f 9c f9 ac ef 74 db bf 4c 9a 09 18 da +65 58 b4 b4 e3 20 9b fc d7 1d dd 59 76 07 b6 e2 +8c 39 85 db f5 2c a7 d1 d7 51 cb 81 69 c0 b1 b1 +3f f8 b6 5b 73 1e 69 dd 2e ff e4 4c 63 6f 2b 69 +95 35 83 1a eb 5e 62 90 2f + +# Signature: +67 eb 89 57 ce 4c 06 f7 39 1d 00 c7 41 24 53 f4 +b6 8b 33 03 a1 29 25 54 e2 a5 fc 72 62 c5 2e 74 +be d7 0e c5 8c 89 50 cd c4 31 5a 8f b7 c6 80 15 +54 cd 35 78 1d 44 fb 5e 57 d6 8d 59 a0 0f 43 b8 +6d 53 b8 43 72 d5 56 e5 a4 15 3c be 6b 39 7c 4c +9c 68 00 70 5d 2f c0 c5 48 64 5e 11 b9 d8 d5 12 +b2 dd 9b f5 9f 3d c5 d1 1c 3c 77 3d 59 cc be d9 +e6 bc 14 32 09 10 cd f8 3b 46 59 01 b7 46 b5 96 +74 + +# PKCS#1 v1.5 Signature Example 13.14 + +# ----------------- + +# Message to be signed: +80 8c b9 76 13 fd 87 85 35 80 1c 80 08 79 15 10 +a5 fe 86 6a d5 b6 84 3a 6e 00 19 a0 fc c2 17 76 +03 54 f6 0c c6 99 fb be 1a df e8 b0 0e cd 6a 36 +a2 b5 a5 a1 fa a2 3d 34 38 20 02 4e 3a 31 97 ae +67 3c + +# Signature: +1c 53 96 59 f8 72 46 99 16 fb 00 07 ef 9e 48 57 +4e 96 4e 4c 0e 6a 2f a7 4b 13 73 fd 60 b6 64 a7 +98 ac 81 29 c0 8c 12 cd bf 37 49 75 0b e1 25 60 +2a 71 54 32 67 67 32 7e 92 ba 57 b5 e2 89 b5 ac +9d 77 71 b4 52 0a 7a 2c e6 6c 5e af 70 4a fc 5a +19 0f a6 0b e1 37 6f 94 3d 2b af 70 52 3e 47 c3 +de fc 0a 25 a6 00 18 31 a3 7a ab 0c f1 f6 48 7b +e3 7f 0e 31 ca 7d b5 ac 41 b5 63 09 57 55 93 69 +ff + +# PKCS#1 v1.5 Signature Example 13.15 + +# ----------------- + +# Message to be signed: +57 ed aa 05 66 25 16 86 f6 52 05 ef c6 26 60 e2 +c2 e0 4f a5 ea a3 30 2d e8 7a 3f 6b 49 1f 7f a3 +ac 72 70 cc 76 75 1a 43 69 42 ac 76 5e f5 f4 74 +91 62 d7 e7 97 12 6b cb 8f da c1 9c f1 8d cc 6e +ff 48 59 3c 05 c8 89 3b 59 1a 51 33 2f a2 6a b8 +63 c5 ea a4 d7 51 e8 d1 b1 9c 58 26 90 b5 41 5e +6a 89 e0 5f 23 1b 33 ac 38 c5 3f 95 a2 d5 f9 10 +51 c2 ec 6d db 2b 6d ba 78 9d 55 3a db 9f 10 c5 +83 59 70 36 d3 48 6f bb 32 17 2a 1c 11 07 9e 5f +09 aa 29 eb 46 74 c8 d7 bf 5b bd 6d 05 7e 6b 87 +a8 b3 aa f4 80 86 d7 21 cb bc 8e fa c6 24 4d 32 +39 ae 18 f1 66 23 fa 52 8e 2e 70 fa 25 65 6a 6a +4a 22 92 95 0f c9 28 ed b8 1c + +# Signature: +33 73 2f cc 23 34 2c 58 51 38 b2 5b 17 c8 12 ee +3e 9d 3d a4 1f 6f fb cc 16 17 a2 ee 75 cc 5b 25 +01 25 4f d1 97 6d 25 88 00 e9 05 d7 e4 4a 0a b6 +fb 4b 8a 88 bb 7b f9 31 73 95 30 3a b2 fc a4 31 +28 48 6a 2b ab 36 c7 5e f6 aa 5e b3 fc 5b d5 55 +b3 ea 79 12 4a ad 78 97 e3 a4 34 de e7 92 63 71 +de 2d 6d 23 7e 89 b0 3b 8d d7 09 60 58 e2 a4 b3 +2c b5 57 c7 ad a2 98 a7 e2 ed d3 a3 a3 b5 29 b4 +d2 + +# PKCS#1 v1.5 Signature Example 13.16 + +# ----------------- + +# Message to be signed: +08 33 76 bb 82 21 2b f8 80 be 12 85 65 3a f2 ca +d6 25 c5 2e 94 e3 21 43 68 77 f7 25 a8 3b bd 43 +f4 48 6d 89 6c f6 7e 31 39 1b 87 06 f8 c0 f8 f4 +bb 1d db a9 5c 33 2f 03 4f 39 09 11 3f 65 56 92 +60 a2 e4 f1 04 06 65 7c 99 fa ff 00 1f e1 6e bb +89 6e 9e 18 11 5a f1 d4 98 6c 85 79 ab 56 52 cc +ca 47 74 + +# Signature: +2a f4 6c 00 d1 d9 15 94 1e 21 2a 7b 8d 81 05 ee +0f 0e c4 80 ff fb b4 f1 3b f2 8d 73 e2 b3 19 b9 +84 a7 b7 c8 36 7a dc a7 ab 12 aa f5 3a cb 98 d0 +cb 54 ee 34 20 4c 90 8e 60 c7 c7 9e fb 42 c3 11 +4a 02 58 9e 1a e6 af b5 97 53 54 57 8c 14 35 ec +c8 9c 11 6e 90 26 b6 bc 88 9e e2 88 ae 4d af 03 +47 cc ce fc 5d fd 1e f8 3c b8 68 52 ee ff d8 40 +98 59 9b 72 5b f6 02 ee 62 0b df 44 af bd 84 c0 +cd + +# PKCS#1 v1.5 Signature Example 13.17 + +# ----------------- + +# Message to be signed: +8c 87 4c d0 ce 33 51 39 c0 8d 76 0b 82 5e b9 90 +5d + +# Signature: +66 9a 8a d7 cb 81 ef 21 87 f5 a8 56 47 68 4b 72 +48 4a ff 27 9f 0a f3 54 35 86 7c c2 b0 43 33 a1 +96 ec a6 cf 44 a9 7a 1b d3 9d 0f 6a 0f f9 59 57 +02 83 5b c8 0a 72 d7 14 04 ef 3f 46 fa 3b 0d 20 +e8 6d 7a 1d 5f 7e fc 3f 3b 8e 8a 7e 37 e8 7e 27 +a9 9f eb a9 6a d8 13 20 be 8f ff 78 55 7d 07 bf +ba e2 16 03 a1 36 8c af a5 ae 1d 1b 63 0a a2 1f +f2 0e 45 85 65 0a 77 3d 7e 2f 5e 7f 51 72 97 19 +3c + +# PKCS#1 v1.5 Signature Example 13.18 + +# ----------------- + +# Message to be signed: +cb 3e 61 21 d3 8b 7d 97 e1 8b a1 5c 49 3d 1a c3 +2e 9d 2e f4 e3 bd 16 df 9c 67 e4 a1 96 e9 24 7a +8d 0c 24 b2 1c 4a b2 3e 77 d6 db 11 7d 59 11 95 +bb af 44 66 82 5f 63 97 8f 11 40 85 28 1b 79 ae +a3 7e 32 c6 b3 6c 1e 9d dd 4a d1 23 6e 97 fd 42 +7b 4d 97 6e 07 64 9d ca 4f 33 a8 9c 46 fb 8c 00 +b4 26 7b 14 47 04 + +# Signature: +56 84 17 80 3a 40 0e 9d 05 0a 43 20 ae 7b 7d 8d +24 8e 16 36 50 86 9d 9f dd 10 0c c1 a6 b9 bc 29 +1c 3f 23 f1 25 60 03 16 4f 61 9d bc 78 63 5e bd +f0 89 49 0a fa 5a a0 0b 6f 97 eb 06 36 c3 bb a8 +9d 86 36 0a fe 26 00 43 d8 61 a7 4f 64 c7 1d 9c +bd 31 ea e2 39 3a 1a f1 56 1f 1a b9 2c aa 76 dd +1e 76 ab 23 33 09 8c 83 c2 d9 9f ae 82 73 98 75 +80 05 c1 76 cb c4 a2 e2 2e fa 0e 6c 12 f4 e3 42 +81 + +# PKCS#1 v1.5 Signature Example 13.19 + +# ----------------- + +# Message to be signed: +21 9a 2f 8d 0b 00 0a ed b5 f1 85 45 5e d3 ea 09 +4c 45 42 6b 28 5b ab 4a 07 cf 3d 0a 29 06 f3 e2 +03 18 4c 2d 3d 81 a8 09 b8 9c 9f c4 8b c9 af 9a +b3 2f 84 f1 5d 81 38 9c 4e db 0a c6 8a d0 95 02 +e3 f3 0c 7c f6 45 10 29 54 b2 97 c8 66 14 66 fc +10 + +# Signature: +03 83 5d 90 57 e2 b8 21 dc 4c 6e ac a3 f4 15 6a +56 55 0b 6f 9d 74 00 fc 5c 51 95 a4 ae e4 71 7d +f3 29 29 12 2b 43 27 3a 07 9a 24 f9 9d d9 e7 c3 +40 56 ae a4 fc 4e 45 7d 83 14 ef 34 42 7f 8e 20 +4b 81 bb 49 03 fb 3e 77 9e 38 9e 41 33 90 68 c1 +57 d9 b0 9f 2c 5e 99 cc 54 e6 ef 86 ee ac 0e 19 +f4 4e 33 e7 07 c4 26 1a 0a 83 ce b4 22 f2 e0 6b +cc ae 3b 8b ba 42 8d 75 57 15 2f 40 84 6e c0 11 +34 + +# PKCS#1 v1.5 Signature Example 13.20 + +# ----------------- + +# Message to be signed: +e3 9c a4 0d 2e 9d 03 ae 05 96 f6 0e b8 f6 09 99 +30 85 a5 db 15 6b 0d 50 98 fe 5f aa c5 5f 70 99 +3f e1 76 d2 d0 c0 38 b8 60 bb f9 a6 62 43 f5 e7 +8e 6c be 52 6e cf 25 12 8d ae 31 96 56 cc 32 1e +e8 0a 50 53 14 90 c9 a6 24 3f bd b0 c5 eb 4c d6 +42 d2 61 15 05 ae 10 84 97 57 38 ad 84 62 1d 67 +f5 + +# Signature: +4f cf a5 73 97 f2 7e e0 f8 ae 75 a0 a5 4d 54 b0 +c5 1b 95 7e e6 3b f7 90 1b 60 55 cc 39 87 c3 2d +f7 22 0e 16 6a 71 60 6a bc 78 f9 11 07 f9 74 df +f7 d6 25 7c 25 6d c6 ed 7a 69 c3 c9 9f 9f 89 ab +b5 8f e5 89 b7 ee 7c ad 0f 48 c1 60 10 d0 46 a9 +c4 e0 04 bb e1 a8 29 79 68 d4 0b c7 06 82 eb ae +a4 48 52 5d be e1 6b 03 bd 0b 65 26 d0 98 d0 9b +6b ad 9a ba 03 93 05 e2 ab 79 69 02 08 65 80 cc +f0 + +# ============================================= + +# Example 14: A 1536-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +d8 70 a7 76 cd 13 ed 44 3d f3 99 08 be e2 ca d7 +3c 48 5f d9 bf 06 32 13 22 88 7f be 65 5c 08 cb +e4 c8 f6 3e 25 4f c9 1c 75 f0 55 7d 90 1d 43 5b +0e 8d ed 82 d4 91 73 41 4d 29 86 03 24 e4 6c 1b +03 0d fe aa 29 d8 0f 98 98 c2 c5 e1 01 cb f6 da +a0 62 89 78 d4 15 b5 02 de a2 6d e6 56 1c 79 ab +06 5c 6d ca 6a bc 4d 4d 4d 5e 9f 5c 74 cb 3e 6a +5a f7 1d 1f 90 fa 5e aa 1b e0 ca 94 7a 70 a3 9e +fd 31 5c 4d f2 1a 1a 82 1c aa ff 8d cb ad 13 b2 +9c 7e 82 aa d5 3c 64 f5 82 ec 9e c3 1e 6b de 82 +ea 5a 5f 4c cc f0 c4 57 b8 88 f1 55 0c 4f f8 e1 +c1 78 a7 6a 46 c1 96 f4 be f5 9e 61 dd 94 4e 47 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +d8 70 a7 76 cd 13 ed 44 3d f3 99 08 be e2 ca d7 +3c 48 5f d9 bf 06 32 13 22 88 7f be 65 5c 08 cb +e4 c8 f6 3e 25 4f c9 1c 75 f0 55 7d 90 1d 43 5b +0e 8d ed 82 d4 91 73 41 4d 29 86 03 24 e4 6c 1b +03 0d fe aa 29 d8 0f 98 98 c2 c5 e1 01 cb f6 da +a0 62 89 78 d4 15 b5 02 de a2 6d e6 56 1c 79 ab +06 5c 6d ca 6a bc 4d 4d 4d 5e 9f 5c 74 cb 3e 6a +5a f7 1d 1f 90 fa 5e aa 1b e0 ca 94 7a 70 a3 9e +fd 31 5c 4d f2 1a 1a 82 1c aa ff 8d cb ad 13 b2 +9c 7e 82 aa d5 3c 64 f5 82 ec 9e c3 1e 6b de 82 +ea 5a 5f 4c cc f0 c4 57 b8 88 f1 55 0c 4f f8 e1 +c1 78 a7 6a 46 c1 96 f4 be f5 9e 61 dd 94 4e 47 + +# Public exponent: +01 00 01 + +# Exponent: +05 88 8f c7 7a 43 bd a7 a6 7b d1 58 47 65 0d f1 +85 c1 85 ed cf b3 ed 58 ce e3 b5 7c 5d 24 06 b7 +8b c0 55 87 4e 35 e5 7a dc 4b 0a 2c 7d 20 3a 66 +1c 0f a5 d8 57 ed e6 07 ef dc 95 68 04 2b f0 d5 +99 f4 e4 23 5e 91 7f 08 94 33 3a 92 df 94 62 d9 +c1 0a f3 df ca 70 49 a1 ea a6 35 70 13 98 83 c5 +be fe be e4 e2 21 89 43 d3 0f c6 45 ff e8 b9 14 +d2 18 dd 58 96 0a ad c1 21 71 5b ce 5c cd de 4a +2c 73 a8 d9 d8 6a 4e b6 e4 55 dc 92 4f d7 4a 0b +1f 75 69 1c 28 1b ae 91 4d 69 9e e2 59 d8 5c 5f +b5 dd 99 9e be f9 b7 0a 4b d9 4a a4 fa fa e2 6c +a7 84 d3 2f d4 e0 77 db b6 ea 69 3b cd 6d 27 d5 + +# Prime 1: +ff 8e f1 e7 4c 44 5a 5c c8 97 3a 81 9c 75 45 49 +12 35 72 0c f9 eb 83 f1 81 13 3c 78 a1 4d cc 4c +e5 e7 75 be 3e 0c 46 ed 2f 21 9a b8 8d 87 77 ad +6e cb e4 0c f9 18 76 4d 7e 37 c6 68 35 91 e7 aa +a1 3b 24 4b 7f cc 0e b6 df d7 6a 11 5f 30 ed 2d +63 68 c8 ea 78 0a 21 1c 0a c9 c0 72 5d fa b0 8d + +# Prime 2: +d8 d0 67 64 c1 f7 64 54 c6 8a 3a 08 1e 95 d7 47 +c2 94 11 ad c4 03 a7 cb 71 b4 3a f5 05 ca be 41 +b4 9c 97 1c 13 ad 65 63 b8 c9 0b 93 b5 89 79 bb +74 f8 20 ef b8 de d8 1f 46 30 54 a7 7f b3 0b b0 +99 98 51 a4 3c cd 01 69 18 51 31 f7 43 1b 02 e9 +c6 b9 f8 38 71 d9 cd 5e 0c 3c 58 70 cf 97 97 23 + +# Prime exponent 1: +e8 d6 15 f4 04 7a aa 51 aa b8 8e 27 94 a3 0b d3 +3d 71 d0 4d 9e 4e 43 d2 7f 25 45 8d 2a 79 b5 4f +c2 8f 95 a9 14 e3 1e a3 ee b3 11 42 60 40 32 7b +a3 5c c4 94 45 47 52 51 dc 53 78 c3 6d 3b 57 f5 +10 1c d0 3e b1 5a fb 75 06 90 3f 25 40 b3 55 04 +6b 74 06 ca 09 40 41 56 49 45 f3 be bf 7d 2d e9 + +# Prime exponent 2: +73 5d b1 26 73 ef 67 7b 94 89 48 87 b9 7e 91 a6 +a5 6a 94 5d 99 c7 38 29 90 bf 0e 00 02 ac f6 bf +8f 93 22 f4 d5 a3 96 27 91 d3 a8 4d 58 73 66 4a +d0 da 96 eb f7 ba db d5 08 4b ff 3f 81 3b 8c 24 +d4 15 b0 9b 6b 9e c9 f9 59 ef 1a 5f 2f 5d d8 16 +fc 9f 47 ed 00 e7 9b d7 47 3b 74 f3 d2 02 1f 71 + +# Coefficient: +10 62 18 af 97 1d 92 95 91 59 90 a4 ed 3e 09 d3 +63 db 33 06 b0 90 a1 33 eb d7 54 e2 bd 77 6b 25 +85 99 9d 4f 88 43 03 0a c7 0c 0f f5 de 52 12 67 +22 34 c0 07 ce 74 56 4c 79 1e dc d5 76 f9 68 44 +04 8c fa 66 36 46 b8 fd 80 c7 51 26 b2 26 6e 48 +f1 fa a7 05 44 ad 42 04 fd 61 56 29 2e 51 6e 13 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 14.1 + +# ----------------- + +# Message to be signed: +f7 a3 c6 7e 92 a7 87 f3 5d cc 47 ae d7 d6 b6 19 +29 67 bd fd 00 a6 ac bf 6f 7e fe 46 d3 ac ae d9 +78 8a a4 f1 db 18 44 02 24 9f 9a ce fc 1c 7d fb +1e 69 0d 24 73 8d e8 6f a5 b5 25 0f 97 9e bd 8f +77 8e ec 0d 7f cf 73 1f a2 25 08 6c 86 65 64 ed +3e b1 54 dd 45 8d 05 00 28 2f 86 80 48 87 d4 43 +5e da 9a 44 36 a8 e9 23 a2 0c b4 b4 d0 e8 1c 91 +11 4b dc 06 82 27 8e c2 58 86 07 99 b5 9c 94 36 +f4 3a 53 ca b4 c4 cd + +# Signature: +09 d1 43 5b f5 a9 c1 72 03 d5 37 fe 57 df 98 7b +7a 51 f3 4b 2a 14 09 7e 06 a0 de 56 3b e7 d6 4b +4e a3 79 73 b4 fe 99 73 a6 6a 3f 31 ba 8e 07 e9 +11 7b 6a 1e e7 09 61 33 7b 4d 2b 0d f5 98 10 b6 +24 08 51 18 bd a7 0a c7 4a e4 3e 2f bc f8 92 27 +63 03 23 da 68 30 f5 b1 a2 b9 54 f1 b1 5a ea 07 +54 df 2c 51 18 57 95 16 e8 77 cc b0 b1 28 6c 57 +24 65 5e f8 d2 91 85 66 6f 6e 9b d3 2a 6b d9 ce +9e 1e f9 47 29 fc 67 d6 a3 0e 64 56 0e cf 78 bf +8e 1b 2b 40 e5 06 05 e2 5a e8 0c 38 67 64 ae d1 +1a 0e 71 44 90 49 c9 39 b2 96 2f 6c 24 17 a3 58 +cd c8 10 6b 12 b1 a5 58 76 39 43 8a f1 a6 8d 32 + +# PKCS#1 v1.5 Signature Example 14.2 + +# ----------------- + +# Message to be signed: +2a 13 30 03 ab 67 cd d2 e8 3b 44 e9 e9 dc 77 7d +e0 1f 4d 23 3d 22 e7 d2 b4 46 7f 04 81 2a 3a eb +ff b1 0a 09 24 54 e3 3b 9e 70 28 24 93 28 74 7e +a1 4a 11 c7 98 ac 2e 14 6e 4e 49 65 9b a8 60 67 +db 64 e9 bd 80 a7 02 1a ab cc 22 85 6e 81 01 40 +c2 0f d8 c6 52 7b ad bb d9 fa 59 53 fa 77 e6 85 +87 00 be b6 c7 4d 5a 46 3c 9d a8 61 13 3b aa 5b +d6 a5 99 80 7a e9 16 2e 3a f3 a3 48 d0 4a 4e dd +2f fb ab + +# Signature: +35 e6 66 cf b8 7c 04 88 a8 6f df ed 5f 9d ea ed +bc 46 74 17 1c 31 84 59 ac aa aa 20 e1 ca d7 c5 +86 04 14 0a 80 ff 7f 56 5b fb c8 6e 90 32 8d 4c +72 9b 91 bf 72 a9 8d b7 01 c1 be 63 8a 6e 8f 2e +46 8f 20 39 24 70 c7 c5 c3 44 42 d5 1b 1b 15 5f +b4 64 b8 a5 56 f4 a1 70 c0 23 01 fe d0 d1 aa 92 +aa fd eb c3 f1 8e a8 b4 d7 1e 24 5c 25 26 f6 fe +66 5d e4 83 85 f4 6c e1 bf 33 12 fa 89 28 09 8e +d3 31 2b 61 11 6c a7 e4 23 20 4e f0 8b d2 df 3a +d7 bb c8 50 09 8c b0 26 83 26 66 25 bb d9 59 82 +51 35 a4 5f 03 82 9d 09 6f ed 18 b2 0b aa 3f 9d +44 b0 07 aa 24 1f 92 f8 88 60 55 d9 8e 0e 07 04 + +# PKCS#1 v1.5 Signature Example 14.3 + +# ----------------- + +# Message to be signed: +58 62 7f fa aa 8e 80 0a 8b e9 8e 42 f5 1a 83 61 +1c fa b7 ee 37 6b 34 73 7b 3e 48 e1 bc 17 42 da +a7 7d e4 7e 1a 9b 29 33 77 aa + +# Signature: +3d 17 cb 38 6c 88 78 4d 35 9a d3 c3 8d be 88 8b +fa e8 31 bf b8 ed c9 d0 e8 01 e7 d6 9e 1d d4 c2 +44 1d 68 fd bb 35 12 6c 73 a4 ed ab bf f5 4e 74 +fa 51 09 da d8 b5 c3 13 d8 6a 79 e4 d4 12 76 60 +fc 2a 8e 1c 93 fa 8d 09 2a cc f0 1c c1 8a 60 6c +f0 7d e2 dc 3e 7b 55 33 11 52 db 01 b6 ca ea 1e +ce c9 09 31 99 be 62 c3 e1 23 e2 87 31 13 50 3b +22 03 0f 16 8d af c4 e6 bd 06 5a d2 f6 b1 de d0 +5b e0 c2 f9 b6 7b dc 1a 3b b1 8d a9 59 4c 95 7d +a4 e4 9f ac 3f e7 6e 07 66 f7 4e b0 d5 23 e4 dd +1a e7 59 da d6 b9 b9 08 b7 fc 8b 97 ef 5f 4c 82 +92 32 0a c3 87 c3 50 8b 54 cf b8 5d 34 f6 ad 39 + +# PKCS#1 v1.5 Signature Example 14.4 + +# ----------------- + +# Message to be signed: +0f 0f 8d 3c 0e 4d 26 08 af ad 5a 88 8e a1 4b 3f +6b 2b 27 89 dd 22 12 b8 59 09 e6 4b fb 10 4d 0f +7d e4 27 d1 4a 9f fa 85 5e 2d 4c a2 44 23 36 e5 +59 56 8b 28 41 5d 60 cf 80 63 de 55 92 17 1b 26 +9b 3d 76 33 51 c7 f7 d9 d2 58 09 e7 02 20 ee 30 +fe 8a 00 b9 5d 4c 20 20 26 89 7e d2 c6 1d 7a d4 +3a ed df 36 b5 c2 cb e2 1e 00 86 db d0 fd fd 19 +e4 3f 02 77 f3 bc 95 ed 55 a3 4a f9 30 91 66 02 +19 3c fe 04 51 4b d2 6a 05 7e 56 2a 11 90 c2 7e +aa b6 c3 22 fc fa f4 bb cc 7f 20 c3 77 9c 63 8d +7b bc 07 08 6c f7 5b f8 39 96 db 44 63 + +# Signature: +50 90 45 12 36 10 50 87 2e ae 80 10 26 28 b6 3d +02 16 8d ca 52 f0 ab d8 77 20 ea 48 05 0d 2c 62 +06 1a a2 15 32 68 be f8 ef b3 4e ed 46 17 1a 62 +88 e5 04 d4 20 f6 fc 14 51 38 61 1e 75 ed 3c f7 +9b 4d 10 26 64 d8 64 4f f3 e9 e5 db fd 71 cd c2 +7a 21 0e fb 10 be 90 27 56 04 f8 d4 49 14 8b 3f +86 09 90 39 c3 3a ef 90 bf 19 1b 35 18 eb 45 9d +a3 ba 14 fd 0c 72 22 9d ea 5f ac 2f 7d ad e1 08 +5c 8a 23 70 bb fc fa 2e 3a 9e 63 ca 22 4f 6d e8 +c8 d2 97 a3 b1 f0 6f 1f c9 49 78 90 fd 0e 0e 13 +88 7f ac b1 52 d1 2d 96 39 25 28 ef 28 d0 72 43 +31 ff 41 40 30 c7 a6 38 55 81 3c cd 89 fb db 1b + +# PKCS#1 v1.5 Signature Example 14.5 + +# ----------------- + +# Message to be signed: +26 65 cb 5e e3 6a a9 bb 1a 5c de 7c e8 + +# Signature: +4f 38 c2 ba 84 c5 0d 46 df 53 10 91 b6 27 12 14 +9c 1f 42 db d7 7e 03 d1 85 ea 96 ed a8 02 33 7c +22 c1 13 0b c3 be ce bf 15 39 fd 11 89 38 51 da +e3 cc 15 67 cb 6c 73 a7 2f a1 c9 69 48 68 21 12 +7e 7c fe a1 36 3e ee 95 2b 7c 6e b5 9e 10 2c 66 +57 c0 80 35 27 2c df 4a b5 e5 83 ed 73 7a d0 28 +ac 1c fa fe dd c9 07 3d fb d7 d3 ba 3d a9 e8 dc +d8 46 fa 36 5c 9c cd 8e 9b 39 48 3d 37 07 3c 1a +7b 78 2e e7 12 1b b1 a2 ad 8b f5 f8 ed 6e 65 3e +92 4d eb ad 87 1b 74 43 39 e5 ae 7e 96 f6 0d cc +45 ea 5d 69 7d 3b 1c c7 c5 e8 da 04 e9 2b e0 6c +ad 2e 61 4e ac 31 8a ec af 12 d5 a7 62 34 c2 c0 + +# PKCS#1 v1.5 Signature Example 14.6 + +# ----------------- + +# Message to be signed: +7b 7b 61 61 02 0f af b4 88 71 63 21 34 0d af 2c +06 ac 43 ce 21 32 86 86 84 aa af ab 13 99 65 3d +35 3b 26 93 ad 73 cb 55 b7 1d 66 ac d0 1a 16 0c +bf 74 37 67 bd 96 e7 fd 1c 7a 13 32 06 65 bb ad +1c 4a 0c ed 26 59 3c e8 9c d8 2f 54 6b d4 d1 b1 +bc d8 2c 65 a4 66 f9 9d a0 12 a4 1e 8c 41 20 69 +81 09 58 47 5b 4d 9c 2f 80 d8 2d 06 41 4c 83 25 +eb 4f 2c 5a 11 66 f1 f1 d2 d1 07 d4 8c + +# Signature: +d5 cb b6 c7 ef f4 a6 3a d8 25 0d e9 4c c2 9f 7f +31 a0 d7 10 6d 5d 77 1b 71 5d f8 a6 75 fd 16 34 +d6 e8 ab 58 87 5c c4 c1 51 7b 2f ad f4 e8 5c 1c +b8 b8 53 60 e0 68 75 87 d1 48 08 9f 3f 48 b7 9d +98 d2 02 7c 50 77 0b 33 4f 12 52 ac 0c 3b 2f 03 +65 34 c3 c2 97 22 f6 08 7d 06 d7 06 ce c7 c4 bd +ce 1c d6 4f 7b 4e 07 99 a8 7a a0 73 ea 83 20 29 +2b 8e c8 27 17 40 6d 36 ef 91 25 e4 1f b5 d5 3b +cc dd 62 2d 38 8f cc ee 60 a3 85 ec 20 6a 71 5d +c5 4d 78 77 bd 72 85 d0 84 4c 25 d5 93 77 97 91 +27 83 96 ff 9a 8a 91 30 6a 54 ea 76 60 7c 81 3f +80 1f 38 76 0c 3a 81 4b 93 96 95 9c 29 db ff 9d + +# PKCS#1 v1.5 Signature Example 14.7 + +# ----------------- + +# Message to be signed: +2b 0a d6 13 82 28 78 a5 72 e1 42 80 + +# Signature: +89 c8 10 84 da a8 f9 14 b7 e2 44 55 10 74 17 ca +62 1c 91 02 d5 01 ee b4 3d 17 4c 7b ad 38 1d b1 +8d 95 33 c3 41 1a ec 60 57 ca 5a 4d fd c3 f1 31 +c8 88 b8 8f 01 30 03 d6 17 e0 6d 64 47 95 02 ae +7e 42 4a 5d d6 37 b0 33 56 40 4d 26 0f 5e d6 b8 +cb 16 d2 57 85 28 cc 3e 85 00 34 6e b7 90 bd ad +41 b2 e3 6c a6 f1 98 85 e3 f6 f5 10 86 bf fb 6a +bb 9c 66 33 6b 49 47 34 64 c5 d7 ed 8e 9f f8 5e +11 ae ff 40 90 67 ba b0 a0 5c 41 e8 15 1b 8b e9 +87 f3 f5 95 8e 3e 6f 26 51 5d 96 bf 23 4b 22 ab +91 c0 85 7b 6c 08 a4 6b 03 05 fe 04 4c a9 aa a0 +d7 0a 27 58 a1 ce 43 16 64 a8 dd 79 40 8c 16 ba + +# PKCS#1 v1.5 Signature Example 14.8 + +# ----------------- + +# Message to be signed: +36 93 8c 8c 7c 6f 7e 35 52 34 db 5a 32 a6 48 10 +db 50 2b 67 c6 f5 92 54 4f fb 27 eb 1f 22 e0 6f +2d 63 8b 56 d5 d2 f7 d1 9e 9e 27 1f 2c c9 0c c0 +dd 36 d6 cc 2c 06 17 8b cc 70 6a ef 20 e5 6a 35 +8e 52 4f 63 16 76 9c 54 b6 de 2d d5 + +# Signature: +a0 37 53 a5 fb 54 aa 51 f6 dd 8d ab 91 f1 9c b8 +65 56 84 85 f8 55 8f 0d 10 3f 0d 2b 6d 78 53 6e +79 c8 15 c4 a0 37 bc af 11 b6 9d 4c db ab 03 5a +be 21 6f 71 52 f6 30 ff c7 9f 84 9d 8d cd 46 3a +ae 6a e9 7d 3d f1 5a 9e 73 d2 3f 18 78 fa c7 54 +cb dd 57 1a fe a5 d2 53 57 d4 b8 83 45 f4 89 be +0d 67 b9 bf ad f0 23 f2 6e 67 31 5e d5 fb f3 91 +91 0a f4 96 9b 72 4b f0 ca 31 c1 05 9f 8a 39 13 +b4 8a 13 81 9c 23 6c 9b e8 e8 24 ca 4c b6 19 fb +7d 78 4c d5 f9 52 6b 39 7c 76 c5 d0 c6 0c f7 f4 +8d 11 19 6e 54 f7 2a 08 bb 42 f7 5a ef e3 8f 0b +91 b4 2b b8 06 de 4b 87 c9 08 2f 72 1a 68 80 ca + +# PKCS#1 v1.5 Signature Example 14.9 + +# ----------------- + +# Message to be signed: +60 83 0c 01 cf a8 6f f2 dc ac 7a f9 32 1e e5 fe +50 2e 0e 7a 6f ac b7 3e 3f 6b c9 02 64 0a 61 09 +5f 64 6f d0 3e 80 d5 81 82 46 53 31 e7 5d 66 11 +a0 97 76 81 62 70 86 24 17 29 de 9f 44 ab 43 94 +9d ac 19 36 73 bd 6c f8 7f 5d 65 77 1e f8 72 81 +63 3f dd 07 ba c4 09 a6 e2 32 b6 01 ae ce 2d + +# Signature: +40 58 f6 e0 24 0d 85 1d 61 93 95 a7 52 87 a8 8f +af d8 dc 56 00 b0 69 bf 19 dc 3e 19 21 e1 17 b4 +97 b8 2b 3c 52 02 69 b1 d1 12 81 64 fc d8 8d d2 +b4 6d c8 5c 42 ec f6 7d eb ad 21 a3 b9 a1 55 42 +fe a2 26 06 ea b5 82 fc 32 97 11 ff c0 7f 4e ef +1f 3b bf e0 88 8c bc a4 85 ba fc 11 88 b0 af e8 +09 c9 aa f8 fa 36 66 b9 c9 05 85 39 db 1e c6 a1 +8e 5b e0 b8 01 44 d2 c3 7c a6 14 c0 90 b4 a7 f1 +34 58 e0 d3 a4 cb 0c b7 3d cc 4d 90 80 6f 61 08 +58 89 eb 5c 9b 14 09 de f3 60 fd 1c 2e 49 43 8d +7c 67 d7 9d bd 9a 59 2a b5 04 c4 71 5f 65 b2 9d +84 65 09 95 15 69 a8 c3 79 09 f5 d5 50 ee ff fa + +# PKCS#1 v1.5 Signature Example 14.10 + +# ----------------- + +# Message to be signed: +63 5d 22 03 ed 9d 5b 91 20 e3 1b f6 9d 30 5b e6 +06 86 97 e3 5c e5 9c 55 3e 50 8d c7 7b 07 3f fa +3a aa 59 f9 96 c3 0b 2e 68 63 23 81 9f de 22 be +6c 8d 53 86 84 14 b3 54 5a bf 43 57 68 a6 11 f0 +c1 a4 79 a0 c7 66 0d 53 5e 80 5b 5f ed c3 77 9c +f0 c5 2c 3c d0 40 ab 65 14 c7 f8 13 3d 47 b0 ac +c6 91 4e 6d 4a d3 c4 73 7c f5 12 91 09 4e 85 94 +33 ba 30 66 e1 9d 6a a2 da 89 6d c9 d9 5e f9 e5 +63 6d ab 35 f7 29 87 05 c6 d8 76 17 54 12 f8 84 +25 19 ff e1 6c f7 43 62 ab + +# Signature: +94 61 a1 a8 41 42 3e d5 cf c6 08 9a 74 db fc 53 +73 11 03 bf 49 85 dd b1 50 b0 e9 38 0d 3f e0 cf +6d 45 7c 5c 68 a7 f2 55 04 02 2d 69 5f f8 42 11 +8e bf 61 02 2f ea 47 fa 45 f7 c1 cc 72 6e 1d e5 +0b d0 64 b3 bb 70 16 57 16 2b 88 c0 b9 10 fe b7 +2f 48 7a 5c 7f 4b 9e cf ee 24 e0 7a a2 d1 98 d1 +13 cb 84 5d 81 7b b5 9b b1 da 24 a8 2b 91 c2 fe +3f ba 89 51 83 cb d9 c0 fe 0a c0 be 64 fe f2 e0 +13 92 05 b1 0b ca bf e5 a3 a7 a8 90 fc 0f e7 8d +ab e1 ad b5 bd 11 44 85 03 cb 0d cd 0b 68 f1 60 +19 6e 96 13 e2 9f be 9a 3f 94 06 ec 20 c0 30 e8 +1e c3 09 65 ea 01 9c 17 aa 97 11 01 c2 e5 30 59 + +# PKCS#1 v1.5 Signature Example 14.11 + +# ----------------- + +# Message to be signed: +87 fb a9 89 f3 cc 15 af 7e e7 61 c0 88 26 4a b7 +71 52 39 e0 b8 c8 a9 e4 8e 11 db 68 03 31 39 c2 +a2 89 ea 42 6e be 26 9f 5f b7 07 09 0a fb 89 1a +49 ca 05 c0 55 0d 72 9b f4 d3 7c 8f 1d a7 a3 ca +2f 43 87 a4 0b 5f 79 13 a3 85 f5 5b 81 41 af 36 +be 8f 57 16 65 f8 57 e7 7a 5c 9c cc e6 ba 8f 2b +e4 63 23 cc 56 91 56 6f f4 b6 d7 85 43 04 b9 3b +ba 1a 17 59 df b1 44 c9 54 7c f2 bc 8e aa ed aa +4f 1d d2 52 82 3b 72 87 ca 55 5d 21 06 08 9a 24 +3e 5d fe 8f c3 1d 3f 46 22 2a 68 ab af 31 81 5a +94 7e 58 57 cf 6a 33 17 0e cc b6 a5 e0 6d 23 cc +9d 48 ea f6 cd bc + +# Signature: +0b 5f 1c fc 25 3b aa d4 b9 83 f8 fe 05 0d 4a 01 +7c c4 66 98 0e bd 23 c9 d5 53 43 f5 10 7e 04 1e +b6 54 78 10 fd ba 46 86 e6 10 83 2f 92 82 ed f0 +66 04 b0 ab fe ea 38 01 32 79 17 79 40 99 7b 28 +90 2b 14 db 37 9e eb 4f 44 00 5d fc b0 03 68 03 +c9 f1 25 bc e1 f2 a8 2c 4d 30 07 ae 96 b8 48 b8 +13 ec 8c 97 ca 3f 71 0a 9a e0 db c2 8a 55 e0 58 +81 b8 58 db 55 71 20 f3 3c 59 cd 43 60 f9 20 8c +74 b2 7e c6 5d 11 ea 41 fa 6a 9e ac f2 a6 11 68 +ad 07 c2 09 94 8f 35 a1 61 f4 1f 87 54 0e a1 82 +84 aa b8 d8 f9 78 61 31 f0 43 90 2b 89 c1 7a 56 +0d 90 94 64 47 5a 0d fc e5 89 09 18 7c d6 e4 46 + +# PKCS#1 v1.5 Signature Example 14.12 + +# ----------------- + +# Message to be signed: +4b 5e 80 30 5c be a9 0d 63 7f db 23 47 c6 fe b6 +78 42 eb ac 6f 90 3d b5 a7 1e ba ab 8a 1c 2d f1 +12 60 a1 ec 90 7b 8b 63 4d 37 d3 6e d8 de 7d 0d +a1 03 bc 4a 9e 93 3f b7 bf ee 59 1c c9 33 29 9f +ee 46 0f 35 42 c9 78 f3 07 ae 05 24 64 f3 06 20 +ce bf 3c 9a 9c b6 a9 01 53 0c 1d 56 13 df 07 74 +31 2d 4b 5f + +# Signature: +b6 f0 3d 35 33 50 07 a7 47 ae 68 67 60 f9 ed ad +08 89 d2 d4 ca 0c b8 8b 67 43 12 d3 2c 55 2b 7a +66 c5 a9 52 8c 01 4b 58 c8 49 f2 31 a2 e0 45 68 +2e 3b bb 14 c7 f9 5f f8 bd b6 58 7f 25 11 cc 6b +f9 24 39 60 08 11 03 d4 7e 77 69 a1 77 eb db 91 +f1 28 73 de cd 5d c0 67 e4 5c 2b 2a 04 4f fa 3f +bb 04 c2 0a 3d c2 01 38 40 3f f2 5c a0 eb ad 96 +e4 85 9f a4 a0 d7 32 85 2a f3 50 a2 75 69 9a 94 +aa 6e 47 f2 17 e3 83 ef 8f ce 8e b6 ee d7 82 6d +7c 61 58 fc 58 82 e4 61 35 45 fa 26 ee e0 c9 f9 +3d e7 a1 65 08 ea 16 19 70 46 0d 6a 7c a7 70 f8 +de 8b a9 3c ea f3 97 dd f1 fb ce e2 82 a1 53 7d + +# PKCS#1 v1.5 Signature Example 14.13 + +# ----------------- + +# Message to be signed: +e5 ad 62 7f 24 f4 11 7a 0a 6b e4 a5 5f db 88 3d +75 a6 73 12 15 4a 71 89 23 d0 e8 f5 73 0a 54 d8 +ca 7c 97 4e 4d 59 33 8b b5 71 30 5c ce 99 0c bb +cf a9 1e a9 b7 73 b8 3d 7a 1f 0f fe c4 c6 b1 43 +fe 05 05 8b c9 0c e1 46 f3 69 cb ae 3b 3d 99 70 +5e f4 3d 07 21 b8 + +# Signature: +73 29 86 d4 ed db 8a 7e 9b 65 dc 01 6d d5 71 ef +ab eb 84 49 0e 88 e3 e7 3b 63 e8 0d 1c c8 6a 45 +2d ec 29 fc 81 7e 8a d4 ee bd dc d9 7c 74 5b c4 +79 7e 54 fe c6 ac e2 91 b1 96 dc 24 65 f0 8c f1 +dd d2 17 e7 7a af 7d 50 98 77 91 de 81 b0 41 10 +d1 1a b8 55 89 06 60 4e b9 d9 2b 35 f9 00 75 af +42 28 01 45 b0 88 e8 75 3d 0d b7 3c d3 a3 2b d1 +9c ea 35 38 ee 4f 09 27 3e f6 6d 07 05 d4 5e e7 +10 9f e5 95 df 55 76 7b 3d 10 81 72 27 bb 6b a3 +95 75 b8 5d 6a 35 a2 ff b8 8c b2 67 db fc 28 2b +b8 a3 de e0 2e c7 7b 0c b8 13 55 70 f8 a7 d7 ad +04 34 1a 08 64 e6 7f f6 fa 02 59 a1 69 74 c8 6a + +# PKCS#1 v1.5 Signature Example 14.14 + +# ----------------- + +# Message to be signed: +03 e3 9b a7 a8 0c 77 14 16 d8 52 63 e4 d4 3c 63 +93 df e7 96 52 3b 89 e0 a4 61 62 88 80 80 0d 8f +c2 43 1b 66 30 54 09 e0 6c 95 ae 7a 17 d5 34 b1 +e8 4c 19 9d fe 73 1d a9 49 f1 64 57 1d ec c8 b1 +66 be b8 dc 08 7c b4 86 99 98 c2 + +# Signature: +60 76 3b ea f7 c3 e2 2b 3b 22 dc 44 d9 47 82 6e +23 fc f9 6b 01 b7 74 1b 24 b1 b9 d9 3c 07 f0 c6 +4d 39 67 98 bb 58 9b d4 25 29 53 69 bf b8 79 ad +d3 42 cd 76 28 0b 57 e6 35 4f 61 95 e8 42 fa 2a +95 f1 c4 6f 0b 70 78 6c 31 8d e9 a5 5a 8a c4 54 +5e e7 cf f3 99 c6 78 e5 78 f8 93 9e d4 9e 84 bb +a9 aa e5 7c 1a 36 fc c3 94 86 46 6e 40 12 f9 58 +87 a6 81 10 f1 a4 84 67 e4 c2 34 f5 81 c5 ec 47 +71 06 cc b3 ec 86 17 b4 be 21 93 37 44 8f e7 2e +25 de ab 53 ea cb 92 e5 96 62 95 b3 a5 57 12 19 +58 df e7 9c a4 72 f7 9e fb da 1d cf ba 9d bd 0f +97 67 32 c0 93 b9 8f f1 93 c9 02 98 7a 42 6c 0f + +# PKCS#1 v1.5 Signature Example 14.15 + +# ----------------- + +# Message to be signed: +d4 c2 35 96 7d 4e 87 b6 71 1e 32 ac 70 37 a3 97 +f9 9b 1c ad 95 a1 88 94 6a 48 64 0e b6 b7 b0 03 +c3 2f 85 a1 21 b0 9c a4 c8 be c0 b8 27 44 aa f2 +7d 16 6c ef c7 a9 70 2a d3 1d bd 15 ea 2a 18 5f +5b 9b a6 42 f9 49 07 8b c6 09 b9 a8 a3 36 92 d7 +18 49 39 d1 f9 eb 42 6a 6d b7 40 ea d9 4c fe a1 +7f eb 06 18 d7 4d 9a 65 16 88 e9 0b 9b b7 05 24 +30 5d 61 8c 88 a5 5f 45 44 50 e0 c5 85 d3 a8 d9 +81 65 81 8f 36 3b 20 a2 52 49 2e 15 12 58 58 90 +a8 c3 20 a7 18 71 58 ce 0d 4e 4b e1 c7 01 f8 af +dc 54 5c 4d ab 86 8d 41 d4 1c 21 c2 cb 1f 67 df +79 53 d5 f7 26 1c 50 92 bb c4 33 2a c5 57 5b 6e +0e 03 14 9c 04 0c 3e 20 1c 79 15 ac 20 22 88 4e +a0 e6 c2 14 03 f0 b4 4e 0f 71 34 3f c9 11 1a 7d +b2 f5 e9 e5 09 c2 d8 97 84 ef b2 2c 31 e8 16 5e +0e 93 6c + +# Signature: +46 9f 08 bd d0 3b 75 64 0e 8a 44 a0 7c a8 de 4b +ac f8 33 1f e3 9c 44 d2 3a a7 b5 81 dc 3f 00 f5 +42 1b 5c 17 2d 0f fc e9 14 97 d3 d4 b1 04 f5 6a +98 ec 94 f7 19 27 1e 58 b4 3e fb d8 76 e1 c1 31 +fa 97 82 07 28 a5 56 75 55 21 4c d9 4a 18 fc ce +5c 2f 53 b1 9d 1f 3c 73 d0 9f 7b e1 80 97 38 b0 +3c e7 69 e4 54 ed 4c be dc af 43 c4 8b d3 9d f2 +f8 bb 63 b8 fc 4d 0d 4d 5b 20 4f c2 20 01 3a 66 +8c 19 f9 75 02 93 a4 71 15 83 88 26 45 db f3 ac +4f 83 9b 6f d1 cf 3b 5e e8 d7 34 e1 da 37 4d 91 +d8 9e a3 18 e9 18 34 83 f4 a0 9a 93 51 4a f5 4f +75 d0 a3 56 51 b2 40 f7 9f 20 a2 97 7d 14 57 8c + +# PKCS#1 v1.5 Signature Example 14.16 + +# ----------------- + +# Message to be signed: +d0 6a dc a4 c2 0f 0d 9f 7b e6 5a 20 32 7c 29 47 +56 e3 ed d9 e1 d3 9d 0f 95 c7 9d f1 ba c3 34 35 +9f ab 94 3d 85 45 a3 ba a3 7a 59 29 5c 58 b2 37 +75 2b 8d e7 d4 32 3c 56 e9 d7 cb 0c 7f 83 1d 54 +9c b3 87 19 a0 81 d5 8b 60 57 ec b7 42 9e 2c a6 +07 cd 13 06 35 59 43 15 9d c9 24 ad 3e 9c b1 3d +0e 71 ea dc b0 05 e1 84 c0 c2 ce aa f9 d7 4a 1c +1d f6 fe c1 8c 97 a0 + +# Signature: +9f d9 52 5c 15 c8 43 b8 06 9c 15 f2 6d 3f 95 24 +6a f3 7a 8b 8e 6b 93 9d df 5b 38 28 cd b6 2c fa +37 3a 92 ec c4 13 84 a8 77 ca a0 90 aa 13 c8 47 +ef 28 29 dd ca 14 14 20 14 02 14 81 55 05 50 da +a2 9d e2 ab 70 01 b8 55 c9 34 2f 0c 90 bf a6 c3 +34 9b 2c 39 62 13 ef 70 cb d8 4b b4 ce 6e f5 8b +17 6e 9f 6f cc db 6e 46 ca c3 41 14 a1 b9 f9 8a +8a 32 75 7b f7 5d 6b fc 45 5a de 6a 01 f9 60 50 +1b 79 f5 fb e3 b3 8f ca 03 46 4e 43 d4 96 63 c7 +9f f6 4d 32 98 1e 44 80 cd f4 2d 8a f8 da a7 f1 +2b 81 a5 aa 96 5f ad aa 3c 03 b7 ff 22 d3 cf df +fe 3c ad f4 d5 98 9e d1 4c 96 9a 6e 8c 9a 1e 04 + +# PKCS#1 v1.5 Signature Example 14.17 + +# ----------------- + +# Message to be signed: +3a 63 02 d7 9e 26 b5 55 c7 7d e9 2a 91 e0 78 57 +1e d1 57 2f fc 3e 4f c9 05 ce 53 f1 04 b3 22 00 +95 7e b2 b5 e5 f3 e3 fc bb c1 62 f9 e5 25 c7 06 +f1 dd 04 fc ab 51 6b c1 8a 8e 4f 88 a9 38 a5 b2 +56 85 d7 8d dc 9f 10 4e 49 bf 5c a0 b6 5a 4b 96 +57 e0 4a 71 fb 50 eb 4a ac 22 c0 bb 93 f6 0c ac +94 83 f1 77 13 55 3d ca 4b 31 e2 72 7b 32 e3 50 +fe 20 4c ec d9 a7 cd a4 da da 2e 87 ff 6f 2b 73 +e7 b0 78 1e 21 2f 34 fe 36 36 10 f0 18 a7 99 37 +37 55 ab 46 66 7b b6 52 5d 7d c7 a0 e8 28 90 17 +f5 48 7f a6 92 ef 2f dd ce 38 ad 3f 45 30 de 7e +e5 05 66 70 a7 35 d3 78 d1 ef c9 94 81 f8 c9 fb +ee a9 9f 56 6a 0b 6e 28 46 26 44 a6 d9 c6 cc 88 +fb + +# Signature: +b7 57 fa 74 7c 5c 87 67 66 f3 58 ac bf c7 e7 b8 +05 96 36 8d 0d 86 29 50 e5 55 f4 71 64 6f 64 0e +85 1d 61 2a 55 6f 55 a7 4a 32 92 42 9e 4c 14 f7 +8b a3 eb bd 96 87 f3 08 de db 3c fe d7 1f 4a 9d +d2 6f a5 12 2f 7f 71 94 ae b6 3b c8 b7 5c 34 31 +87 11 5a 1d bd 35 95 90 f7 ff 38 62 b7 08 85 af +1c a9 34 b8 ce bc 2c c9 e6 47 25 3f d1 32 7a 2e +d4 24 4d c8 f5 85 55 a6 89 7c a3 22 9c 80 1e 7b +f6 28 f5 25 e6 c9 48 80 4d 0b 1b 6d bc d7 90 2a +cd e7 a2 5b a5 91 d8 86 e2 8d aa 8d ed 5e e4 01 +e3 4e 64 12 f1 e6 44 ee c1 2a e9 42 61 90 6a 17 +26 11 dd 5a 98 67 78 9c 41 90 34 68 84 29 e9 06 + +# PKCS#1 v1.5 Signature Example 14.18 + +# ----------------- + +# Message to be signed: +9d c7 ce 1d 02 ca dc f1 0d f1 11 04 56 b8 a7 a5 +ea 43 76 b2 7e 8b f8 cc 8d b8 10 49 fd a3 fb d0 +db 8a 3d 0f 6b d7 48 6b 8d 84 bf 9f fd 4b 64 17 +52 df 7e df 50 86 5e 8e 58 ad 49 f7 24 0e 47 d3 +fc 98 5e db 59 6d ab fe 01 72 2a 22 77 60 38 3c +e2 4d 4a 05 d8 b0 6e f5 b9 6f 11 7d 81 + +# Signature: +05 a9 5e 11 b5 bf b0 1d cf de 3e fa 9f 31 3d 81 +bb 0d fd 46 de 63 b0 65 80 56 c5 3a f7 ad 9e 89 +43 8b 7d e7 8f f8 ea 88 d0 72 b1 74 9a 52 9f 1c +c9 cf 2c f3 2e 5a b7 20 e0 69 b4 90 6d 28 2a 03 +dd 78 d1 b3 ca 2a 3f 92 5b f5 1c 74 91 b7 3b a0 +bf 54 d5 0d 97 1d e5 b2 77 26 d8 fb 3e e2 77 34 +97 df 35 49 51 7e ed cd 9d e6 8d 90 df 35 d3 f0 +50 81 15 1a da b5 39 73 85 ab ee a7 2b 69 bd 0d +e1 8d ce e9 a2 be 00 e9 1a 03 24 03 b1 f8 1b bc +0a e7 31 c6 c0 d9 cf dd 06 c3 31 ed 89 d7 de 1d +e1 df 46 cf 09 ce 53 df 15 97 fb 69 94 68 1c 7f +be 94 c9 b0 8e 50 aa 1b 12 41 96 02 98 7f 37 dd + +# PKCS#1 v1.5 Signature Example 14.19 + +# ----------------- + +# Message to be signed: +87 a6 45 61 1b b1 91 85 3f 4f d9 b7 40 b2 de 4c +16 3e 75 62 b1 17 62 63 3e 72 df b6 f6 be 7e fb +90 41 a9 65 82 94 3a b2 01 83 91 c0 5a df ab 46 +4d d6 e3 3f 96 0d db f3 b1 7a c6 2b b7 8a fc 1c +6a 45 39 6c 09 08 70 7c 62 36 12 55 cb f0 9b ad +95 9b 31 33 da 48 d5 32 ba 7e f1 d2 0f b6 57 2a +1f 0e d6 f2 c6 e1 be c1 b1 7c c3 19 ba f7 2a 19 +8a a0 01 b8 3d 4e 98 69 c3 40 90 f2 29 a9 c7 f1 +42 a7 4e 85 ab 3e d5 1c 69 ac 15 fa b4 ab e4 67 +15 73 cf 5a d2 b5 8e 78 a9 44 ed cc ea c5 ee 58 +bf ce 66 f4 0a ac 2a be 4e 5f a0 72 dd 0f 66 4f +ac 81 1a ef 08 42 10 e5 64 1b 9c d0 8c 87 24 f4 +b4 1e ed 1d 9d 4a 18 77 80 46 59 7b d1 a2 7b bb +c0 56 c1 5e 43 c0 38 ef 37 5b 43 5e 73 a7 d3 2f +01 50 16 b7 82 35 ce 75 a7 b7 62 04 99 68 e9 93 +22 53 e4 2c a9 76 c8 d8 dc a1 bb 2d bf + +# Signature: +b8 80 62 26 fb d3 d9 7b 79 f0 dd 1d 8c f9 a2 35 +e5 1b 94 b7 e2 23 ec 68 33 2d 68 6e d3 31 3e d1 +be f6 88 70 23 af 7a 5c 99 df 03 68 a3 49 c6 a5 +94 79 5b 62 35 36 10 13 42 69 0d eb 5f ad 90 23 +78 2f 6d be 16 43 a4 56 18 57 4f 16 72 81 12 a7 +e0 ef 9f 58 65 6f 6a db f4 00 40 9f 4a a5 01 3c +15 9a 36 8c a5 9b de 6b 39 18 df e1 d8 02 fa 6c +fa 06 c9 ca 31 ac a7 8c b2 63 c8 ed 91 7a f9 a9 +a7 95 d5 e2 c4 01 e7 29 96 4c f7 ac 28 cc db 36 +d9 59 ed 7f d9 af 1c 47 09 7b 62 55 c6 4e 1b 16 +f2 1d 86 87 04 55 d5 f0 bf 90 1f cc 68 c3 4b 72 +c1 be e7 2e 6b 8c 4e 36 ae 33 99 6c 7a 59 d0 9a + +# PKCS#1 v1.5 Signature Example 14.20 + +# ----------------- + +# Message to be signed: +03 2e 28 3e 59 6e 87 fa a6 cf cf b8 fa 04 df 6a +61 e6 11 df e7 3b bf 66 8e e6 7b 49 6b fb 0f fb +7f 9d c9 31 a9 8b ce db 25 + +# Signature: +b9 fd c0 3d c1 99 70 71 3c 4a 17 e8 7e 7e bb 5f +13 50 5d 59 cb b2 2b a7 2e 9f f1 6b df 8b 65 9c +33 30 a9 3d cc 09 2a 5d 38 5b 2d 5e 15 34 00 31 +46 c0 50 b7 dd c4 f7 56 56 9d a2 11 80 15 82 26 +61 19 f5 59 9b 1e 65 e8 eb ea 6b c9 64 42 ee 12 +ac b9 6c 6d ba 08 3e 92 10 94 da 9c 9e cf 5a fa +a5 4b 7f de 7a 0c ae 3f df e4 d2 51 93 3a 52 f0 +2d c2 3e 1b 32 14 c6 83 e1 9a f4 6e 18 c7 49 56 +dc 6a b3 50 2d 46 ca ac 3c b2 6b 70 7c dc 30 25 +b6 de 4e 83 54 3b 95 84 5b 4a 15 97 60 77 0a 4b +d0 9e 46 35 a0 4e 21 7d 66 5c 95 94 87 9f 38 1d +71 10 09 34 fa da 61 c7 cc 22 b8 d2 ff 8e b3 5a + +# ============================================= + +# Example 15: A 2048-bit RSA key pair +# ----------------------------------- + + +# Public key +# ---------- + +# Modulus: +df 27 1f d2 5f 86 44 49 6b 0c 81 be 4b d5 02 97 +ef 09 9b 00 2a 6f d6 77 27 eb 44 9c ea 56 6e d6 +a3 98 1a 71 31 2a 14 1c ab c9 81 5c 12 09 e3 20 +a2 5b 32 46 4e 99 99 f1 8c a1 3a 9f d3 89 25 58 +f9 e0 ad ef dd 36 50 dd 23 a3 f0 36 d6 0f e3 98 +84 37 06 a4 0b 0b 84 62 c8 be e3 bc e1 2f 1f 28 +60 c2 44 4c dc 6a 44 47 6a 75 ff 4a a2 42 73 cc +be 3b f8 02 48 46 5f 8f f8 c3 a7 f3 36 7d fc 0d +f5 b6 50 9a 4f 82 81 1c ed d8 1c da aa 73 c4 91 +da 41 21 70 d5 44 d4 ba 96 b9 7f 0a fc 80 65 49 +8d 3a 49 fd 91 09 92 a1 f0 72 5b e2 4f 46 5c fe +7e 0e ab f6 78 99 6c 50 bc 5e 75 24 ab f7 3f 15 +e5 be f7 d5 18 39 4e 31 38 ce 49 44 50 6a aa af +3f 9b 23 6d ca b8 fc 00 f8 7a f5 96 fd c3 d9 d6 +c7 5c d5 08 36 2f ae 2c be dd cc 4c 74 50 b1 7b +77 6c 07 9e cc a1 f2 56 35 1a 43 b9 7d be 21 53 + +# Exponent: +01 00 01 + +# Private key +# ----------- + +# Modulus: +df 27 1f d2 5f 86 44 49 6b 0c 81 be 4b d5 02 97 +ef 09 9b 00 2a 6f d6 77 27 eb 44 9c ea 56 6e d6 +a3 98 1a 71 31 2a 14 1c ab c9 81 5c 12 09 e3 20 +a2 5b 32 46 4e 99 99 f1 8c a1 3a 9f d3 89 25 58 +f9 e0 ad ef dd 36 50 dd 23 a3 f0 36 d6 0f e3 98 +84 37 06 a4 0b 0b 84 62 c8 be e3 bc e1 2f 1f 28 +60 c2 44 4c dc 6a 44 47 6a 75 ff 4a a2 42 73 cc +be 3b f8 02 48 46 5f 8f f8 c3 a7 f3 36 7d fc 0d +f5 b6 50 9a 4f 82 81 1c ed d8 1c da aa 73 c4 91 +da 41 21 70 d5 44 d4 ba 96 b9 7f 0a fc 80 65 49 +8d 3a 49 fd 91 09 92 a1 f0 72 5b e2 4f 46 5c fe +7e 0e ab f6 78 99 6c 50 bc 5e 75 24 ab f7 3f 15 +e5 be f7 d5 18 39 4e 31 38 ce 49 44 50 6a aa af +3f 9b 23 6d ca b8 fc 00 f8 7a f5 96 fd c3 d9 d6 +c7 5c d5 08 36 2f ae 2c be dd cc 4c 74 50 b1 7b +77 6c 07 9e cc a1 f2 56 35 1a 43 b9 7d be 21 53 + +# Public exponent: +01 00 01 + +# Exponent: +5b d9 10 25 78 30 dc e1 75 20 b0 34 41 a5 1a 8c +ab 94 02 0a c6 ec c2 52 c8 08 f3 74 3c 95 b7 c8 +3b 8c 8a f1 a5 01 43 46 eb c4 24 2c df b5 d7 18 +e3 0a 73 3e 71 f2 91 e4 d4 73 b6 1b fb a6 da ca +ed 0a 77 bd 1f 09 50 ae 3c 91 a8 f9 01 11 88 25 +89 e1 d6 27 65 ee 67 1e 7b ae ea 30 9f 64 d4 47 +bb cf a9 ea 12 dc e0 5e 9e a8 93 9b c5 fe 61 08 +58 12 79 c9 82 b3 08 79 4b 34 48 e7 f7 b9 52 29 +2d f8 8c 80 cb 40 14 2c 4b 5c f5 f8 dd aa 08 91 +67 8d 61 0e 58 2f cb 88 0f 0d 70 7c af 47 d0 9a +84 e1 4c a6 58 41 e5 a3 ab c5 e9 db a9 40 75 a9 +08 43 41 f0 ed ad 9b 68 e3 b8 e0 82 b8 0b 6e 6e +8a 05 47 b4 4f b5 06 1b 6a 91 31 60 3a 55 37 dd +ab d0 1d 8e 86 3d 89 22 e9 aa 3e 4b fa ea 0b 39 +d7 92 83 ad 2c bc 8a 59 cc e7 a6 ec f4 e4 c8 1e +d4 c6 59 1c 80 7d ef d7 1a b0 68 66 bb 5e 77 45 + +# Prime 1: +f4 4f 5e 42 46 39 1f 48 2b 2f 52 96 e3 60 2e b3 +4a a1 36 42 77 10 f7 c0 41 6d 40 3f d6 9d 4b 29 +13 0c fe be f3 4e 88 5a bd b1 a8 a0 a5 f0 e9 b5 +c3 3e 1f c3 bf c2 85 b1 ae 17 e4 0c c6 7a 19 13 +dd 56 37 19 81 5e ba f8 51 4c 2a 7a a0 01 8e 63 +b6 c6 31 dc 31 5a 46 23 57 16 42 3d 11 ff 58 03 +4e 61 06 45 70 36 06 91 9f 5c 7c e2 66 0c d1 48 +bd 9e fc 12 3d 9c 54 b6 70 55 90 d0 06 cf cf 3f + +# Prime 2: +e9 d4 98 41 e0 e0 a6 ad 0d 51 78 57 13 3e 36 dc +72 c1 bd d9 0f 91 74 b5 2e 26 57 0f 37 36 40 f1 +c1 85 e7 ea 8e 2e d7 f1 e4 eb b9 51 f7 0a 58 02 +36 33 b0 09 7a ec 67 c6 dc b8 00 fc 1a 67 f9 bb +05 63 61 0f 08 eb c8 74 6a d1 29 77 21 36 eb 1d +da f4 64 36 45 0d 31 83 32 a8 49 82 fe 5d 28 db +e5 b3 e9 12 40 7c 3e 0e 03 10 0d 87 d4 36 ee 40 +9e ec 1c f8 5e 80 ab a0 79 b2 e6 10 6b 97 bc ed + +# Prime exponent 1: +ed 10 2a cd b2 68 71 53 4d 1c 41 4e ca d9 a4 d7 +32 fe 95 b1 0e ea 37 0d a6 2f 05 de 2c 39 3b 1a +63 33 03 ea 74 1b 6b 32 69 c9 7f 70 4b 35 27 02 +c9 ae 79 92 2f 7b e8 d1 0d b6 7f 02 6a 81 45 de +41 b3 0c 0a 42 bf 92 3b ac 5f 75 04 c2 48 60 4b +9f aa 57 ed 6b 32 46 c6 ba 15 8e 36 c6 44 f8 b9 +54 8f cf 4f 07 e0 54 a5 6f 76 86 74 05 44 40 bc +0d cb bc 9b 52 8f 64 a0 17 06 e0 5b 0b 91 10 6f + +# Prime exponent 2: +68 27 92 4a 85 e8 8b 55 ba 00 f8 21 91 28 bd 37 +24 c6 b7 d1 df e5 62 9e f1 97 92 5f ec af f5 ed +b9 cd f3 a7 be fd 8e a2 e8 dd 37 07 13 8b 3f f8 +7c 3c 39 c5 7f 43 9e 56 2e 2a a8 05 a3 9d 7c d7 +99 66 d2 ec e7 84 5f 1d bc 16 be e9 99 99 e4 d0 +bf 9e ec a4 5f cd a8 a8 50 00 35 fe 6b 5f 03 bc +2f 6d 1b fc 4d 4d 0a 37 23 96 1a f0 cd ce 4a 01 +ee c8 2d 7f 54 58 ec 19 e7 1b 90 ee ef 7d ff 61 + +# Coefficient: +57 b7 38 88 d1 83 a9 9a 63 07 42 22 77 55 1a 3d +9e 18 ad f0 6a 91 e8 b5 5c ef fe f9 07 7c 84 96 +94 8e cb 3b 16 b7 81 55 cb 2a 3a 57 c1 19 d3 79 +95 1c 01 0a a6 35 ed cf 62 d8 4c 5a 12 2a 8d 67 +ab 5f a9 e5 a4 a8 77 2a 1e 94 3b af c7 0a e3 a4 +c1 f0 f3 a4 dd ff ae fd 18 92 c8 cb 33 bb 0d 0b +95 90 e9 63 a6 91 10 fb 34 db 7b 90 6f c4 ba 28 +36 99 5a ac 7e 52 74 90 ac 95 2a 02 26 8a 4f 18 + +# PKCS#1 v1.5 signing of 20 random messages +# ------------------------------------------------------- + +# PKCS#1 v1.5 Signature Example 15.1 + +# ----------------- + +# Message to be signed: +f4 5d 55 f3 55 51 e9 75 d6 a8 dc 7e a9 f4 88 59 +39 40 cc 75 69 4a 27 8f 27 e5 78 a1 63 d8 39 b3 +40 40 84 18 08 cf 9c 58 c9 b8 72 8b f5 f9 ce 8e +e8 11 ea 91 71 4f 47 ba b9 2d 0f 6d 5a 26 fc fe +ea 6c d9 3b 91 0c 0a 2c 96 3e 64 eb 18 23 f1 02 +75 3d 41 f0 33 59 10 ad 3a 97 71 04 f1 aa f6 c3 +74 27 16 a9 75 5d 11 b8 ee d6 90 47 7f 44 5c 5d +27 20 8b 2e 28 43 30 fa 3d 30 14 23 fa 7f 2d 08 +6e 0a d0 b8 92 b9 db 54 4e 45 6d 3f 0d ab 85 d9 +53 c1 2d 34 0a a8 73 ed a7 27 c8 a6 49 db 7f a6 +37 40 e2 5e 9a f1 53 3b 30 7e 61 32 99 93 11 0e +95 19 4e 03 93 99 c3 82 4d 24 c5 1f 22 b2 6b de +10 24 cd 39 59 58 a2 df eb 48 16 a6 e8 ad ed b5 +0b 1f 6b 56 d0 b3 06 0f f0 f1 c4 cb 0d 0e 00 1d +d5 9d 73 be 12 + +# Signature: +b7 5a 54 66 b6 5d 0f 30 0e f5 38 33 f2 17 5c 8a +34 7a 38 04 fc 63 45 1d c9 02 f0 b7 1f 90 83 45 +9e d3 7a 51 79 a3 b7 23 a5 3f 10 51 64 2d 77 37 +4c 4c 6c 8d bb 1c a2 05 25 f5 c9 f3 2d b7 76 95 +35 56 da 31 29 0e 22 19 74 82 ce b6 99 06 c4 6a +75 8f b0 e7 40 9b a8 01 07 7d 2a 0a 20 ea e7 d1 +d6 d3 92 ab 49 57 e8 6b 76 f0 65 2d 68 b8 39 88 +a7 8f 26 e1 11 72 ea 60 9b f8 49 fb bd 78 ad 7e +dc e2 1d e6 62 a0 81 36 8c 04 06 07 ce e2 9d b0 +62 72 27 f4 49 63 ad 17 1d 22 93 b6 33 a3 92 e3 +31 dc a5 4f e3 08 27 52 f4 3f 63 c1 61 b4 47 a4 +c6 5a 68 75 67 0d 5f 66 00 fc c8 60 a1 ca eb 0a +88 f8 fd ec 4e 56 43 98 a5 c4 6c 87 f6 8c e0 70 +01 f6 21 3a be 0a b5 62 5f 87 d1 90 25 f0 8d 81 +da c7 bd 45 86 bc 93 82 19 1f 6d 28 80 f6 22 7e +5d f3 ee d2 1e 77 92 d2 49 48 04 87 f3 65 52 61 + +# PKCS#1 v1.5 Signature Example 15.2 + +# ----------------- + +# Message to be signed: +c1 4b 4c 60 75 b2 f9 aa d6 61 de f4 ec fd 3c b9 +33 c6 23 f4 e6 3b f5 34 10 d2 f0 16 d1 ab 98 e2 +72 9e cc f8 00 6c d8 e0 80 50 73 7d 95 fd bf 29 +6b 66 f5 b9 79 2a 90 29 36 c4 f7 ac 69 f5 14 53 +ce 43 69 45 2d c2 2d 96 f0 37 74 81 14 66 20 00 +dd 9c d3 a5 e1 79 f4 e0 f8 1f a6 a0 31 1c a1 ae +e6 51 9a 0f 63 ce c7 8d 27 bb 72 63 93 fb 7f 1f +88 cd e7 c9 7f 8a 66 cd 66 30 12 81 da c3 f3 a4 +33 24 8c 75 d6 c2 dc d7 08 b6 a9 7b 0a 3f 32 5e +0b 29 64 f8 a5 81 9e 47 9b + +# Signature: +af a7 34 34 62 be a1 22 cc 14 9f ca 70 ab da e7 +94 46 67 7d b5 37 36 66 af 7d c3 13 01 5f 4d e7 +86 e6 e3 94 94 6f ad 3c c0 e2 b0 2b ed ba 50 47 +fe 9e 2d 7d 09 97 05 e4 a3 9f 28 68 32 79 cf 0a +c8 5c 15 30 41 22 42 c0 e9 18 95 3b e0 00 e9 39 +cf 3b f1 82 52 5e 19 93 70 fa 79 07 eb a6 9d 5d +b4 63 10 17 c0 e3 6d f7 03 79 b5 db 8d 4c 69 5a +97 9a 8e 61 73 22 40 65 d7 dc 15 13 2e f2 8c d8 +22 79 51 63 06 3b 54 c6 51 14 1b e8 6d 36 e3 67 +35 bc 61 f3 1f ca 57 4e 53 09 f3 a3 bb df 91 ef +f1 2b 99 e9 cc 17 44 f1 ee 9a 1b d2 2c 5b ad 96 +ad 48 19 29 25 1f 03 43 fd 36 bc f0 ac de 7f 11 +e5 ad 60 97 77 21 20 27 96 fe 06 1f 9a da 1f c4 +c8 e0 0d 60 22 a8 35 75 85 ff e9 fd d5 93 31 a2 +8c 4a a3 12 15 88 fb 6c f6 83 96 d8 ac 05 46 59 +95 00 c9 70 85 00 a5 97 2b d5 4f 72 cf 8d b0 c8 + +# PKCS#1 v1.5 Signature Example 15.3 + +# ----------------- + +# Message to be signed: +d0 23 71 ad 7e e4 8b bf db 27 63 de 7a 84 3b 94 +08 ce 5e b5 ab f8 47 ca 3d 73 59 86 df 84 e9 06 +0b db cd d3 a5 5b a5 5d de 20 d4 76 1e 1a 21 d2 +25 c1 a1 86 f4 ac 4b 30 19 d3 ad f7 8f e6 33 46 +67 f5 6f 70 c9 01 a0 a2 70 0c 6f 0d 56 ad d7 19 +59 2d c8 8f 6d 23 06 c7 00 9f 6e 7a 63 5b 4c b3 +a5 02 df e6 8d dc 58 d0 3b e1 0a 11 70 00 4f e7 +4d d3 e4 6b 82 59 1f f7 54 14 f0 c4 a0 3e 60 5e +20 52 4f 24 16 f1 2e ca 58 9f 11 1b 75 d6 39 c6 +1b aa 80 ca fd 05 cf 35 00 24 4a 21 9e d9 ce d9 +f0 b1 02 97 18 2b 65 3b 52 6f 40 0f 29 53 ba 21 +4d 5b cd 47 88 41 32 87 2a e9 0d 4d 6b 1f 42 15 +39 f9 f3 46 62 a5 6d c0 e7 b4 b9 23 b6 23 1e 30 +d2 67 67 97 81 7f 7c 33 7b 5a c8 24 ba 93 14 3b +33 81 fa 3d ce 0e 6a eb d3 8e 67 73 51 87 b1 eb +d9 5c 02 + +# Signature: +3b ac 63 f8 6e 3b 70 27 12 03 10 6b 9c 79 aa bd +9f 47 7c 56 e4 ee 58 a4 fc e5 ba f2 ca b4 96 0f +88 39 1c 9c 23 69 8b e7 5c 99 ae df 9e 1a bf 17 +05 be 1d ac 33 14 0a db 48 eb 31 f4 50 bb 9e fe +83 b7 b9 0d b7 f1 57 6d 33 f4 0c 1c ba 4b 8d 6b +1d 33 23 56 4b 0f 17 74 11 4f a7 c0 8e 6d 1e 20 +dd 8f bb a9 b6 ac 7a d4 1e 26 b4 56 8f 4a 8a ac +bf d1 78 a8 f8 d2 c9 d5 f5 b8 81 12 93 5a 8b c9 +ae 32 cd a4 0b 8d 20 37 55 10 73 50 96 53 68 18 +ce 2b 2d b7 1a 97 72 c9 b0 dd a0 9a e1 01 52 fa +11 46 62 18 d0 91 b5 3d 92 54 30 61 b7 29 4a 55 +be 82 ff 35 d5 c3 2f a2 33 f0 5a aa c7 58 50 30 +7e cf 81 38 3c 11 16 74 39 7b 1a 1b 9d 3b f7 61 +2c cb e5 ba cd 2b 38 f0 a9 83 97 b2 4c 83 65 8f +b6 c0 b4 14 0e f1 19 70 c4 63 0d 44 34 4e 76 ea +ed 74 dc be e8 11 db f6 57 59 41 f0 8a 65 23 b8 + +# PKCS#1 v1.5 Signature Example 15.4 + +# ----------------- + +# Message to be signed: +29 03 55 84 ab 7e 02 26 a9 ec 4b 02 e8 dc f1 27 +2d c9 a4 1d 73 e2 82 00 07 b0 f6 e2 1f ec cd 5b +d9 db b9 ef 88 cd 67 58 76 9e e1 f9 56 da 7a d1 +84 41 de 6f ab 83 86 db c6 93 + +# Signature: +28 d8 e3 fc d5 dd db 21 ff bd 8d f1 63 0d 73 77 +aa 26 51 e1 4c ad 1c 0e 43 cc c5 2f 90 7f 94 6d +66 de 72 54 e2 7a 6c 19 0e b0 22 ee 89 ec f6 22 +4b 09 7b 71 06 8c d6 07 28 a1 ae d6 4b 80 e5 45 +7b d3 10 6d d9 17 06 c9 37 c9 79 5f 2b 36 36 7f +f1 53 dc 25 19 a8 db 9b df 2c 80 74 30 c4 51 de +17 bb cd 0c e7 82 b3 e8 f1 02 4d 90 62 4d ea 7f +1e ed c7 42 0b 7e 7c aa 65 77 ce f4 31 41 a7 26 +42 06 58 0e 44 a1 67 df 5e 41 ee a0 e6 9a 80 54 +54 c4 0e ef c1 3f 48 e4 23 d7 a3 2d 02 ed 42 c0 +ab 03 d0 a7 cf 70 c5 86 0a c9 2e 03 ee 00 5b 60 +ff 35 03 42 4b 98 cc 89 45 68 c7 c5 6a 02 33 55 +1c eb e5 88 cf 8b 01 67 b7 df 13 ad ca d8 28 67 +68 10 49 9c 70 4d a7 ae 23 41 4d 69 e3 c0 d2 db +5d cb c2 61 3b c1 20 42 1f 9e 36 53 c5 a8 76 72 +97 64 3c 7e 07 40 de 01 63 55 45 3d 6c 95 ae 72 + +# PKCS#1 v1.5 Signature Example 15.5 + +# ----------------- + +# Message to be signed: +bd a3 a1 c7 90 59 ea e5 98 30 8d 3d f6 09 + +# Signature: +a1 56 17 6c b9 67 77 c7 fb 96 10 5d bd 91 3b c4 +f7 40 54 f6 80 7c 60 08 a1 a9 56 ea 92 c1 f8 1c +b8 97 dc 4b 92 ef 9f 4e 40 66 8d c7 c5 56 90 1a +cb 6c f2 69 fe 61 5b 0f b7 2b 30 a5 13 38 69 23 +14 b0 e5 87 8a 88 c2 c7 77 4b d1 69 39 b5 ab d8 +2b 44 29 d6 7b d7 ac 8e 5e a7 fe 92 4e 20 a6 ec +66 22 91 f2 54 8d 73 4f 66 34 86 8b 03 9a a5 f9 +d4 d9 06 b2 d0 cb 85 85 bf 42 85 47 af c9 1c 6e +20 52 dd cd 00 1c 3e f8 c8 ee fc 3b 6b 2a 82 b6 +f9 c8 8c 56 f2 e2 c3 cb 0b e4 b8 0d a9 5e ba 37 +1d 8b 5f 60 f9 25 38 74 3d db b5 da 29 72 c7 1f +e7 b9 f1 b7 90 26 8a 0e 77 0f c5 eb 4d 5d d8 52 +47 d4 8a e2 ec 3f 26 25 5a 39 85 52 02 06 a1 f2 +68 e4 83 e9 db b1 d5 ca b1 90 91 76 06 de 31 e7 +c5 18 2d 8f 15 1b f4 1d fe cc ae d7 cd e6 90 b2 +16 47 10 6b 49 0c 72 9d 54 a8 fe 28 02 a6 d1 26 + +# PKCS#1 v1.5 Signature Example 15.6 + +# ----------------- + +# Message to be signed: +c1 87 91 5e 4e 87 da 81 c0 8e d4 35 6a 0c ce ac +1c 4f b5 c0 46 b4 52 81 b3 87 ec 28 f1 ab fd 56 +7e 54 6b 23 6b 37 d0 1a e7 1d 3b 28 34 36 5d 3d +f3 80 b7 50 61 b7 36 b0 13 0b 07 0b e5 8a e8 a4 +6d 12 16 63 61 b6 13 db c4 7d fa eb 4c a7 46 45 +6c 2e 88 83 85 52 5c ca 9d d1 c3 c7 a9 ad a7 6d +6c + +# Signature: +9c ab 74 16 36 08 66 9f 75 55 a3 33 cf 19 6f e3 +a0 e9 e5 eb 1a 32 d3 4b b5 c8 5f f6 89 aa ab 0e +3e 65 66 8e d3 b1 15 3f 94 eb 3d 8b e3 79 b8 ee +f0 07 c4 a0 2c 70 71 ce 30 d8 bb 34 1e 58 c6 20 +f7 3d 37 b4 ec bf 48 be 29 4f 6c 9e 0e cb 5e 63 +fe c4 1f 12 0e 55 53 df a0 eb eb bb 72 64 0a 95 +37 ba dc b4 51 33 02 29 d9 f7 10 f6 2e 3e d8 ec +78 4e 50 ee 1d 92 62 b4 26 71 34 00 11 d7 d0 98 +c6 f2 55 7b 21 31 fa 9b d0 25 46 36 59 7e 88 ec +b3 5a 24 0e f0 fd 85 95 71 24 df 80 80 fe e1 e1 +49 af 93 99 89 e8 6b 26 c8 5a 58 81 fa e8 67 3d +9f d4 08 00 dd 13 4e b9 bd b6 41 0f 42 0b 0a a9 +7b 20 ef cf 2e b0 c8 07 fa eb 83 a3 cc d9 b5 1d +45 53 e4 1d fc 0d f6 ca 80 a1 e8 1d c2 34 bb 83 +89 dd 19 5a 38 b4 2d e4 ed c4 9d 34 64 78 b9 f1 +1f 05 57 20 5f 5b 0b d7 ff e9 c8 50 f3 96 d7 c4 + +# PKCS#1 v1.5 Signature Example 15.7 + +# ----------------- + +# Message to be signed: +ab fa 2e cb 7d 29 bd 5b cb 99 31 ce 2b ad 2f 74 +38 3e 95 68 3c ee 11 02 2f 08 e8 e7 d0 b8 fa 05 +8b f9 eb 7e b5 f9 88 68 b5 bb 1f b5 c3 1c ed a3 +a6 4f 1a 12 cd f2 0f cd 0e 5a 24 6d 7a 17 73 d8 +db a0 e3 b2 77 54 5b ab e5 8f 2b 96 e3 f4 ed c1 +8e ab f5 cd 2a 56 0f ca 75 fe 96 e0 7d 85 9d ef +b2 56 4f 3a 34 f1 6f 11 e9 1b 3a 71 7b 41 af 53 +f6 60 53 23 00 1a a4 06 c6 + +# Signature: +c4 b4 37 bc f7 03 f3 52 e1 fa f7 4e b9 62 20 39 +42 6b 56 72 ca f2 a7 b3 81 c6 c4 f0 19 1e 7e 4a +98 f0 ee bc d6 f4 17 84 c2 53 7f f0 f9 9e 74 98 +2c 87 20 1b fb c6 5e ae 83 2d b7 1d 16 da ca db +09 77 e5 c5 04 67 9e 40 be 0f 9d b0 6f fd 84 8d +d2 e5 c3 8a 7e c0 21 e7 f6 8c 47 df d3 8c c3 54 +49 3d 53 39 b4 59 5a 5b f3 1e 3f 8f 13 81 68 07 +37 3d f6 ad 0d c7 e7 31 e5 1a d1 9e b4 75 4b 13 +44 85 84 2f e7 09 d3 78 44 4d 8e 36 b1 72 4a 4f +da 21 ca fe e6 53 ab 80 74 7f 79 52 ee 80 4d ea +b1 03 9d 84 13 99 45 bb f4 be 82 00 87 53 f3 c5 +4c 78 21 a1 d2 41 f4 21 79 c7 94 ef 70 42 bb f9 +95 56 56 22 2e 45 c3 43 69 a3 84 69 7b 6a e7 42 +e1 8f a5 ca 7a ba d2 7d 9f e7 10 52 e3 31 0d 0f +52 c8 d1 2e a3 3b f0 53 a3 00 f4 af c4 f0 98 df +4e 6d 88 67 79 d6 45 94 d3 69 15 8f db c1 f6 94 + +# PKCS#1 v1.5 Signature Example 15.8 + +# ----------------- + +# Message to be signed: +df 40 44 a8 9a 83 e9 fc bf 12 62 54 0a e3 03 8b +bc 90 f2 b2 62 8b f2 a4 46 7a c6 77 22 d8 54 6b +3a 71 cb 0e a4 16 69 d5 b4 d6 18 59 c1 b4 e4 7c +ec c5 93 3f 75 7e c8 6d b0 64 4e 31 18 12 d0 0f +b8 02 f0 34 00 63 9c 0e 36 4d ae 5a eb c5 79 1b +c6 55 76 23 61 bc 43 c5 3d 3c 78 86 76 8f 79 68 +c1 c5 44 c6 f7 9f 7b e8 20 c7 e2 bd 2f 9d 73 e6 +2d ed 6d 2e 93 7e 6a 6d ae f9 0e e3 7a 1a 52 a5 +4f 00 e3 1a dd d6 48 94 cf 4c 02 e1 60 99 e2 9f +9e b7 f1 a7 bb 7f 84 c4 7a 2b 59 48 13 be 02 a1 +7b 7f c4 3b 34 c2 2c 91 92 52 64 12 6c 89 f8 6b +b4 d8 7f 3e f1 31 29 6c 53 a3 08 e0 33 1d ac 8b +af 3b 63 42 22 66 ec ef 2b 90 78 15 35 db da 41 +cb d0 cf 22 a8 cb fb 53 2e c6 8f c6 af b2 ac 06 + +# Signature: +14 14 b3 85 67 ae 6d 97 3e de 4a 06 84 2d cc 0e +05 59 b1 9e 65 a4 88 9b db ab d0 fd 02 80 68 29 +13 ba cd 5d c2 f0 1b 30 bb 19 eb 81 0b 7d 9d ed +32 b2 84 f1 47 bb e7 71 c9 30 c6 05 2a a7 34 13 +90 a8 49 f8 1d a9 cd 11 e5 ec cf 24 6d ba e9 5f +a9 58 28 e9 ae 0c a3 55 03 25 32 6d ee f9 f4 95 +30 ba 44 1b ed 4a c2 9c 02 9c 9a 27 36 b1 a4 19 +0b 85 08 4a d1 50 42 6b 46 d7 f8 5b d7 02 f4 8d +ac 5f 71 33 0b c4 23 a7 66 c6 5c c1 dc ab 20 d3 +d3 bb a7 2b 63 b3 ef 82 44 d4 2f 15 7c b7 e3 a8 +ba 5c 05 27 2c 64 cc 1a d2 1a 13 49 3c 39 11 f6 +0b 4e 9f 4e cc 99 00 eb 05 6e e5 9d 6f e4 b8 ff +6e 80 48 cc c0 f3 8f 28 36 fd 3d fe 91 bf 4a 38 +6e 1e cc 2c 32 83 9f 0c a4 d1 b2 7a 56 8f a9 40 +dd 64 ad 16 bd 01 25 d0 34 8e 38 30 85 f0 88 94 +86 1c a1 89 87 22 7d 37 b4 2b 58 4a 83 57 cb 04 + +# PKCS#1 v1.5 Signature Example 15.9 + +# ----------------- + +# Message to be signed: +ea 94 1f f0 6f 86 c2 26 92 7f cf 0e 3b 11 b0 87 +26 76 17 0c 1b fc 33 bd a8 e2 65 c7 77 71 f9 d0 +85 01 64 a5 ee cb cc 5c e8 27 fb fa 07 c8 52 14 +79 6d 81 27 e8 ca a8 18 94 ea 61 ce b1 44 9e 72 +fe a0 a4 c9 43 b2 da 6d 9b 10 5f e0 53 b9 03 9a +9c c5 3d 42 0b 75 39 fa b2 23 9c 6b 51 d1 7e 69 +4c 95 7d 4b 0f 09 84 46 18 79 a0 75 9c 44 01 be +ec d4 c6 06 a0 af bd 7a 07 6f 50 a2 df c2 80 7f +24 f1 91 9b aa 77 46 d3 a6 4e 26 8e d3 f5 f8 e6 +da 83 a2 a5 c9 15 2f 83 7c b0 78 12 bd 5b a7 d3 +a0 79 85 de 88 11 3c 17 96 e9 b4 66 ec 29 9c 5a +c1 05 9e 27 f0 94 15 + +# Signature: +ce eb 84 cc b4 e9 09 92 65 65 07 21 ee a0 e8 ec +89 ca 25 bd 35 4d 4f 64 56 49 67 be 9d 4b 08 b3 +f1 c0 18 53 9c 9d 37 1c f8 96 1f 22 91 fb e0 dc +2f 2f 95 fe a4 7b 63 9f 1e 12 f4 bc 38 1c ef 0c +2b 7a 7b 95 c3 ad f2 76 05 b7 f6 39 98 c3 cb ad +54 28 08 c3 82 2e 06 4d 4a d1 40 93 67 9e 6e 01 +41 8a 6d 5c 05 96 84 cd 56 e3 4e d6 5a b6 05 b8 +de 4f cf a6 40 47 4a 54 a8 25 1b bb 73 26 a4 2d +08 58 5c fc fc 95 67 69 b1 5b 6d 7f df 7d a8 4f +81 97 6e aa 41 d6 92 38 0f f1 0e ae cf e0 a5 79 +68 29 09 b5 52 1f ad e8 54 d7 97 b8 a0 34 5b 9a +86 4e 05 88 f6 ca dd bf 65 f1 77 99 8e 18 0d 1f +10 24 43 e6 dc a5 3a 94 82 3c aa 9c 3b 35 f3 22 +58 3c 70 3a f6 74 76 15 9e c7 ec 93 d1 76 9b 30 +0a f0 e7 15 7d c2 98 c6 cd 2d ee 22 62 f8 cd dc +10 f1 1e 01 74 14 71 bb fd 65 18 a1 75 73 45 75 + +# PKCS#1 v1.5 Signature Example 15.10 + +# ----------------- + +# Message to be signed: +d8 b8 16 45 c1 3c d7 ec f5 d0 0e d2 c9 1b 9a cd +46 c1 55 68 e5 30 3c 4a 97 75 ed e7 6b 48 40 3d +6b e5 6c 05 b6 b1 cf 77 c6 e7 5d e0 96 c5 cb 35 +51 cb 6f a9 64 f3 c8 79 cf 58 9d 28 e1 da 2f 9d +ec + +# Signature: +27 45 07 4c a9 71 75 d9 92 e2 b4 47 91 c3 23 c5 +71 67 16 5c dd 8d a5 79 cd ef 46 86 b9 bb 40 4b +d3 6a 56 50 4e b1 fd 77 0f 60 bf a1 88 a7 b2 4b +0c 91 e8 81 c2 4e 35 b0 4d c4 dd 4c e3 85 66 bc +c9 ce 54 f4 9a 17 5f c9 d0 b2 25 22 d9 57 90 47 +f9 ed 42 ec a8 3f 76 4a 10 16 39 97 94 7e 7d 2b +52 ff 08 98 0e 7e 7c 22 57 93 7b 23 f3 d2 79 d4 +cd 17 d6 f4 95 54 63 73 d9 83 d5 36 ef d7 d1 b6 +71 81 ca 2c b5 0a c6 16 c5 c7 ab fb b9 26 0b 91 +b1 a3 8e 47 24 20 01 ff 45 2f 8d e1 0c a6 ea ea +dc af 9e dc 28 95 6f 28 a7 11 29 1f c9 a8 08 78 +b8 ba 4c fe 25 b8 28 1c b8 0b c9 cd 6d 2b d1 82 +52 46 ee be 25 2d 99 57 ef 93 70 73 52 08 4e 6d +36 d4 23 55 1b f2 66 a8 53 40 fb 4a 6a f3 70 88 +0a ab 07 15 3d 01 f4 8d 08 6d f0 bf be c0 5e 7b +44 3b 97 e7 17 18 97 0e 2f 4b f6 20 23 e9 5b 67 + +# PKCS#1 v1.5 Signature Example 15.11 + +# ----------------- + +# Message to be signed: +e5 73 9b 6c 14 c9 2d 51 0d 95 b8 26 93 33 37 ff +0d 24 ef 72 1a c4 ef 64 c2 ba d2 64 be 8b 44 ef +a1 51 6e 08 a2 7e b6 b6 11 d3 30 1d f0 06 2d ae +fc 73 a8 c0 d9 2e 2c 52 1f ac bc 7b 26 47 38 76 +7e a6 fc 97 d5 88 a0 ba f6 ce 50 ad f7 9e 60 0b +d2 9e 34 5f cb 1d ba 71 ac 5c 02 89 02 3f e4 a8 +2b 46 a5 40 77 19 19 7d 2e 95 8e 35 31 fd 54 ae +f9 03 aa bb 43 55 f8 83 18 99 4e d3 c3 dd 62 f4 +20 a7 + +# Signature: +be 40 a5 fb 94 f1 13 e1 b3 ef f6 b6 a3 39 86 f2 +02 e3 63 f0 74 83 b7 92 e6 8d fa 55 54 df 04 66 +cc 32 15 09 50 78 3b 4d 96 8b 63 9a 04 fd 2f b9 +7f 6e b9 67 02 1f 5a dc cb 9f ca 95 ac c8 f2 cd +88 5a 38 0b 0a 4e 82 bc 76 07 64 db ab 88 c1 e6 +c0 25 5c aa 94 f2 32 19 9d 6f 59 7c c9 14 5b 00 +e3 d4 ba 34 6b 55 9a 88 33 ad 15 16 ad 51 63 f0 +16 af 6a 59 83 1c 82 ea 13 c8 22 4d 84 d0 76 5a +9d 12 38 4d a4 60 a8 53 1b 4c 40 7e 04 f4 f3 50 +70 9e b9 f0 8f 5b 22 0f fb 45 ab f6 b7 5d 15 79 +fd 3f 1e b5 5f c7 5b 00 af 8b a3 b0 87 82 7f e9 +ae 9f b4 f6 c5 fa 63 03 1f e5 82 85 2f e2 83 4f +9c 89 bf f5 3e 25 52 21 6b c7 c1 d4 a3 d5 dc 2b +a6 95 5c d9 b1 7d 13 63 e7 fe e8 ed 76 29 75 3f +f3 12 5e dd 48 52 1a e3 b9 b0 32 17 f4 49 6d 0d +8e de 57 ac bc 5b d4 de ae 74 a5 6f 86 67 1d e2 + +# PKCS#1 v1.5 Signature Example 15.12 + +# ----------------- + +# Message to be signed: +7a f4 28 35 91 7a 88 d6 b3 c6 71 6b a2 f5 b0 d5 +b2 0b d4 e2 e6 e5 74 e0 6a f1 ee f7 c8 11 31 be +22 bf 81 28 b9 cb c6 ec 00 27 5b a8 02 94 a5 d1 +17 2d 08 24 a7 9e 8f dd 83 01 83 e4 c0 0b 96 78 +28 67 b1 22 7f ea 24 9a ad 32 ff c5 fe 00 7b c5 +1f 21 79 2f 72 8d ed a8 b5 70 8a a9 9c ab ab 20 +a4 aa 78 3e d8 6f 0f 27 b5 d5 63 f4 2e 07 15 8c +ea 72 d0 97 aa 68 87 ec 41 1d d0 12 91 2a 5e 03 +2b bf a6 78 50 71 44 bc c9 5f 39 b5 8b e7 bf d1 +75 9a db 9a 91 fa 1d 6d 82 26 a8 34 3a 8b 84 9d +ae 76 f7 b9 82 24 d5 9e 28 f7 81 f1 3e ce 60 5f +84 f6 c9 0b ae 5f 8c f3 78 81 6f 40 20 a7 dd a1 +be d9 0c 92 a2 36 34 d2 03 fa c3 fc d8 6d 68 d3 +18 2a 7d 9c ca be 7b 07 95 f5 c6 55 e9 ac c4 e3 +ec 18 51 40 d1 0c ef 05 34 64 ab 17 5c 83 bd 83 +93 5e 3d ab af 34 62 ee be 63 d1 5f 57 3d 26 9a + +# Signature: +4e 78 c5 90 2b 80 79 14 d1 2f a5 37 ae 68 71 c8 +6d b8 02 1e 55 d1 ad b8 eb 0c cf 1b 8f 36 ab 7d +ad 1f 68 2e 94 7a 62 70 72 f0 3e 62 73 71 78 1d +33 22 1d 17 4a be 46 0d bd 88 56 0c 22 f6 90 11 +6e 2f bb e6 e9 64 36 3a 3e 52 83 bb 5d 94 6e f1 +c0 04 7e ba 03 8c 75 6c 40 be 79 23 05 58 09 b0 +e9 f3 4a 03 a5 88 15 eb dd e7 67 93 1f 01 8f 6f +18 78 f2 ef 4f 47 dd 37 40 51 dd 48 68 5d ed 6e +fb 3e a8 02 1f 44 be 1d 7d 14 93 98 f9 8e a9 c0 +8d 62 88 8e bb 56 19 2d 17 74 7b 6b 8e 17 09 54 +31 f1 25 a8 a8 e9 96 2a a3 1c 28 52 64 e0 8f b2 +1a ac 33 6c e6 c3 8a a3 75 e4 2b c9 2a b0 ab 91 +03 84 31 e1 f9 2c 39 d2 af 5d ed 7e 43 bc 15 1e +6e be a4 c3 e2 58 3a f3 43 7e 82 c4 3c 5e 3b 5b +07 cf 03 59 68 3d 22 98 e3 59 48 ed 80 6c 06 3c +60 6e a1 78 15 0b 1e fc 15 85 69 34 c7 25 5c fe + +# PKCS#1 v1.5 Signature Example 15.13 + +# ----------------- + +# Message to be signed: +eb ae f3 f9 f2 3b df e5 fa 6b 8a f4 c2 08 c1 89 +f2 25 1b f3 2f 5f 13 7b 9d e4 40 63 78 68 6b 3f +07 21 f6 2d 24 cb 86 88 d6 fc 41 a2 7c ba e2 1d +30 e4 29 fe ac c7 11 19 41 c2 77 + +# Signature: +c4 8d be f5 07 11 4f 03 c9 5f af be b4 df 1b fa +88 e0 18 4a 33 cc 4f 8a 9a 10 35 ff 7f 82 2a 5e +38 cd a1 87 23 91 5f f0 78 24 44 29 e0 f6 08 1c +14 fd 83 33 1f a6 5c 6b a7 bb 9a 12 db f6 62 23 +74 cd 0c a5 7d e3 77 4e 2b d7 ae 82 36 77 d0 61 +d5 3a e9 c4 04 0d 2d a7 ef 70 14 f3 bb dc 95 a3 +61 a4 38 55 c8 ce 9b 97 ec ab ce 17 4d 92 62 85 +14 2b 53 4a 30 87 f9 f4 ef 74 51 1e c7 42 b0 d5 +68 56 03 fa f4 03 b5 07 2b 98 5d f4 6a df 2d 25 +29 a0 2d 40 71 1e 21 90 91 70 52 37 1b 79 b7 49 +b8 3a bf 0a e2 94 86 c3 f2 f6 24 77 b2 bd 36 2b +03 9c 01 3c 0c 50 76 ef 52 0d bb 40 5f 42 ce e9 +54 25 c3 73 a9 75 e1 cd d0 32 c4 96 22 c8 50 79 +b0 9e 88 da b2 b1 39 69 ef 7a 72 39 73 78 10 40 +45 9f 57 d5 01 36 38 48 3d e2 d9 1c b3 c4 90 da +81 c4 6d e6 cd 76 ea 8a 0c 8f 6f e3 31 71 2d 24 + +# PKCS#1 v1.5 Signature Example 15.14 + +# ----------------- + +# Message to be signed: +c5 a2 71 12 78 76 1d fc dd 4f 0c 99 e6 f5 61 9d +6c 48 b5 d4 c1 a8 09 82 fa a6 b4 cf 1c f7 a6 0f +f3 27 ab ef 93 c8 01 42 9e fd e0 86 40 85 81 46 +10 56 ac c3 3f 3d 04 f5 ad a2 12 16 ca cd 5f d1 +f9 ed 83 20 3e 0e 2f e6 13 8e 3e ae 84 24 e5 91 +5a 08 3f 3f 7a b7 60 52 c8 be 55 ae 88 2d 6e c1 +48 2b 1e 45 c5 da e9 f4 10 15 40 53 27 02 2e c3 +2f 0e a2 42 97 63 b2 55 04 3b 19 58 ee 3c f6 d6 +39 83 59 6e b3 85 84 4f 85 28 cc 9a 98 65 83 5d +c5 11 3c 02 b8 0d 0f ca 68 aa 25 e7 2b ca ae b3 +cf 9d 79 d8 4f 98 4f d4 17 + +# Signature: +6b d5 25 7a a0 66 11 fb 46 60 08 7c b4 bc 4a 9e +44 91 59 d3 16 52 bd 98 08 44 da f3 b1 c7 b3 53 +f8 e5 61 42 f7 ea 98 57 43 3b 18 57 3b 4d ee de +81 8a 93 b0 29 02 97 78 3f 1a 2f 23 cb c7 27 97 +a6 72 53 7f 01 f6 24 84 cd 41 62 c3 21 4b 9a c6 +28 22 4c 5d e0 1f 32 bb 9b 76 b2 73 54 f2 b1 51 +d0 e8 c4 21 3e 46 15 ad 0b c7 1f 51 5e 30 0d 6a +64 c6 74 34 11 ff fd e8 e5 ff 19 0e 54 92 30 43 +12 6e cf c4 c4 53 90 22 66 8f b6 75 f2 5c 07 e2 +00 99 ee 31 5b 98 d6 af ec 4b 1a 9a 93 dc 33 49 +6a 15 bd 6f de 16 63 a7 d4 9b 9f 1e 63 9d 38 66 +4b 37 a0 10 b1 f3 5e 65 86 82 d9 cd 63 e5 7d e0 +f1 5e 8b dd 09 65 58 f0 7e c0 ca a2 18 a8 c0 6f +47 88 45 39 40 28 7c 9d 34 b6 d4 0a 3f 09 bf 77 +99 fe 98 ae 4e b4 9f 3f f4 1c 50 40 a5 0c ef c9 +bd f2 39 4b 74 9c f1 64 48 0d f1 ab 68 80 27 3b + +# PKCS#1 v1.5 Signature Example 15.15 + +# ----------------- + +# Message to be signed: +9b f8 aa 25 3b 87 2e a7 7a 7e 23 47 6b e2 6b 23 +29 57 8c f6 ac 9e a2 80 5b 35 7f 6f c3 ad 13 0d +ba eb 3d 86 9a 13 cc e7 a8 08 bb bb c9 69 85 7e +03 94 5c 7b b6 1d f1 b5 c2 58 9b 8e 04 6c 2a 5d +7e 40 57 b1 a7 4f 24 c7 11 21 63 64 28 85 29 ec +95 70 f2 51 97 21 3b e1 f5 c2 e5 96 f8 bf 8b 2c +f3 cb 38 aa 56 ff e5 e3 1d f7 39 58 20 e9 4e cf +3b 11 89 a9 65 dc f9 a9 cb 42 98 d3 c8 8b 29 23 +c1 9f c6 bc 34 aa ce ca d4 e0 93 1a 7c 4e 5d 73 +dc 86 df a7 98 a8 47 6d 82 46 3e ef aa 90 a8 a9 +19 2a b0 8b 23 08 8d d5 8e 12 80 f7 d7 2e 45 48 +39 6b aa c1 12 25 2d d5 c5 34 6a db 20 04 a2 f7 +10 1c cc 89 9c c7 fa fa e8 bb e2 95 73 88 96 a5 +b2 01 22 85 01 4e f6 + +# Signature: +27 f7 f4 da 9b d6 10 10 6e f5 7d 32 38 3a 44 8a +8a 62 45 c8 3d c1 30 9c 6d 77 0d 35 7b a8 9e 73 +f2 ad 08 32 06 2e b0 fe 0a c9 15 57 5b cd 6b 8b +ca db 4e 2b a6 fa 9d a7 3a 59 17 51 52 b2 d4 fe +72 b0 70 c9 b7 37 9e 50 00 0e 55 e6 c2 69 f6 65 +8c 93 79 72 79 7d 3a dd 69 f1 30 e3 4b 85 bd ec +9f 3a 9b 39 22 02 d6 f3 e4 30 d0 9c ac a8 22 77 +59 ab 82 5f 70 12 d2 ff 4b 5b 62 c8 50 4d ba d8 +55 c0 5e dd 5c ab 5a 4c cc dc 67 f0 1d d6 51 7c +7d 41 c4 3e 2a 49 57 af f1 9d b6 f1 8b 17 85 9a +f0 bc 84 ab 67 14 6e c1 a4 a6 0a 17 d7 e0 5f 8b +4f 9c ed 6a d1 09 08 d8 d7 8f 7f c8 8b 76 ad c8 +29 0f 87 da f2 a7 be 10 ae 40 85 21 39 5d 54 ed +25 56 fb 76 61 85 4a 73 0c e3 d8 2c 71 a8 d4 93 +ec 49 a3 78 ac 8a 3c 74 43 9f 7c c5 55 ba 13 f8 +59 07 08 90 ee 18 ff 65 8f a4 d7 41 96 9d 70 a5 + +# PKCS#1 v1.5 Signature Example 15.16 + +# ----------------- + +# Message to be signed: +32 47 48 30 e2 20 37 54 c8 bf 06 81 dc 4f 84 2a +fe 36 09 30 37 86 16 c1 08 e8 33 65 6e 56 40 c8 +68 56 88 5b b0 5d 1e b9 43 8e fe de 67 92 63 de +07 cb 39 55 3f 6a 25 e0 06 b0 a5 23 11 a0 63 ca +08 82 66 d2 56 4f f6 49 0c 46 b5 60 98 18 54 8f +88 76 4d ad 34 a2 5e 3a 85 d5 75 02 3f 0b 9e 66 +50 48 a0 3c 35 05 79 a9 d3 24 46 c7 bb 96 cc 92 +e0 65 ab 94 d3 c8 95 2e 8d f6 8e f0 d9 fa 45 6b +3a 06 bb 80 e3 bb c4 b2 8e 6a 94 b6 d0 ff 76 96 +a6 4e fe 05 e7 35 fe a0 25 d7 bd bc 41 39 f3 a3 +b5 46 07 5c ba 7e fa 94 73 74 d3 f0 ac 80 a6 8d +76 5f 5d f6 21 0b ca 06 9a 2d 88 64 7a f7 ea 04 +2d ac 69 0c b5 73 78 ec 07 77 61 4f b8 b6 5f f4 +53 ca 6b 7d ce 60 98 45 1a 2f 8c 0d a9 bf ec f1 +fd f3 91 bb aa 4e 2a 91 ca 18 a1 12 1a 75 23 a2 +ab d4 25 14 f4 89 e8 + +# Signature: +69 17 43 72 57 c2 2c cb 54 03 29 0c 3d ee 82 d9 +cf 75 50 b3 1b d3 1c 51 bd 57 bf d3 5d 45 2a b4 +db 7c 4b e6 b2 e2 5a c9 a5 9a 1d 2a 7f eb 62 7f +0a fd 49 76 b3 00 3c c9 cf fd 88 96 50 5e c3 82 +f2 65 10 4d 4c f8 c9 32 fa 9f e8 6e 00 87 07 95 +99 12 38 9d a4 b2 d6 b3 69 b3 6a 5e 72 e2 9d 24 +c9 a9 8c 9d 31 a3 ab 44 e6 43 e6 94 12 66 a4 7a +45 e3 44 6c e8 77 6a be 24 1a 8f 5f c6 42 3b 24 +b1 ff 25 0d c2 c3 a8 17 23 53 56 10 77 e8 50 a7 +69 b2 5f 03 25 da c8 89 65 a3 b9 b4 72 c4 94 e9 +5f 71 9b 4e ac 33 2c aa 7a 65 c7 df e4 6d 9a a7 +e6 e0 0f 52 5f 30 3d d6 3a b7 91 92 18 90 18 68 +f9 33 7f 8c d2 6a af e6 f3 3b 7f b2 c9 88 10 af +19 f7 fc b2 82 ba 15 77 91 2c 1d 36 89 75 fd 5d +44 0b 86 e1 0c 19 97 15 fa 0b 6f 42 50 b5 33 73 +2d 0b ef e1 54 51 50 fc 47 b8 76 de 09 b0 0a 94 + +# PKCS#1 v1.5 Signature Example 15.17 + +# ----------------- + +# Message to be signed: +00 8e 59 50 5e af b5 50 aa e5 e8 45 58 4c eb b0 +0b 6d e1 73 3e 9f 95 d4 2c 88 2a 5b be b5 ce 1c +57 e1 19 e7 c0 d4 da ca 9f 1f f7 87 02 17 f7 cf +d8 a6 b3 73 97 7c ac 9c ab 8e 71 e4 20 + +# Signature: +92 25 03 b6 73 ee 5f 3e 69 1e 1c a8 5e 9f f4 17 +3c f7 2b 05 ac 2c 13 1d a5 60 35 93 e3 bc 25 9c +94 c1 f7 d3 a0 6a 5b 98 91 bf 11 3f a3 9e 59 ff +7c 1e d6 46 5e 90 80 49 cb 89 e4 e1 25 cd 37 d2 +ff d9 22 7a 41 b4 a0 a1 9c 0a 44 fb bf 3d e5 5b +ab 80 20 87 a3 bb 8d 4f f6 68 ee 6b bb 8a d8 9e +68 57 a7 9a 9c 72 78 19 90 df cf 92 cd 51 94 04 +c9 50 f1 3d 11 43 c3 18 4f 1d 25 0c 90 e1 7a c6 +ce 36 16 3b 98 95 62 7a d6 ff ec 14 22 44 1f 55 +e4 49 9d ba 9b e8 95 46 ae 8b c6 3c ca 01 dd 08 +46 3a e7 f1 fc e3 d8 93 99 69 38 77 8c 18 12 e6 +74 ad 9c 30 9c 5a cc a3 fd e4 4e 7d d8 69 59 93 +e9 c1 fa 87 ac da 99 ec e5 c8 49 9e 46 89 57 ad +66 35 9b f1 2a 51 ad be 78 d3 a2 13 b4 49 bf 0b +5f 8d 4d 49 6a cf 03 d3 03 3b 7c cd 19 6b c2 2f +68 fb 7b ef 4f 69 7c 5e a2 b3 50 62 f4 8a 36 dd + +# PKCS#1 v1.5 Signature Example 15.18 + +# ----------------- + +# Message to be signed: +6a bc 54 cf 8d 1d ff 1f 53 b1 7d 81 60 36 88 78 +a8 78 8c c6 d2 2f a5 c2 25 8c 88 e6 60 b0 9a 89 +33 f9 f2 c0 50 4d da dc 21 f6 e7 5e 0b 83 3b eb +55 52 29 de e6 56 b9 04 7b 92 f6 2e 76 b8 ff cc +60 da b0 6b 80 + +# Signature: +0b 6d af 42 f7 a8 62 14 7e 41 74 93 c2 c4 01 ef +ae 32 63 6a b4 cb d4 41 92 bb f5 f1 95 b5 0a e0 +96 a4 75 a1 61 4f 0a 9f a8 f7 a0 26 cb 46 c6 50 +6e 51 8e 33 d8 3e 56 47 7a 87 5a ca 8c 7e 71 4c +e1 bd bd 61 ef 5d 53 52 39 b3 3f 2b fd d6 17 71 +ba b6 27 76 d7 81 71 a1 42 3c ea 87 31 f8 2e 60 +76 6d 64 54 26 56 20 b1 5f 5c 5a 58 4f 55 f9 5b +80 2f e7 8c 57 4e d5 da cf c8 31 f3 cf 2b 05 02 +c0 b2 98 f2 5c cf 11 f9 73 b3 1f 85 e4 74 42 19 +85 f3 cf f7 02 df 39 46 ef 0a 66 05 68 21 11 b2 +f5 5b 1f 8a b0 d2 ea 3a 68 3c 69 98 5e ad 93 ed +44 9e a4 8f 03 58 dd f7 08 02 cb 41 de 2f d8 3f +3c 80 80 82 d8 49 36 94 8e 0c 84 a1 31 b4 92 78 +27 46 05 27 bb 5c d2 4b fa b7 b4 8e 07 1b 24 17 +19 30 f9 97 63 27 2f 97 97 bc b7 6f 1d 24 81 57 +55 58 fc f2 60 b1 f0 e5 54 eb b3 df 3c fc b9 58 + +# PKCS#1 v1.5 Signature Example 15.19 + +# ----------------- + +# Message to be signed: +af 2d 78 15 2c f1 0e fe 01 d2 74 f2 17 b1 77 f6 +b0 1b 5e 74 9f 15 67 71 5d a3 24 85 9c d3 dd 88 +db 84 8e c7 9f 48 db ba 7b 6f 1d 33 11 1e f3 1b +64 89 9e 73 91 c2 bf fd 69 f4 90 25 cf 20 1f c5 +85 db d1 54 2c 1c 77 8a 2c e7 a7 ee 10 8a 30 9f +ec a2 6d 13 3a 5f fe dc 4e 86 9d cd 76 56 59 6a +c8 42 7e a3 ef 6e 3f d7 8f e9 9d 8d dc 71 d8 39 +f6 78 6e 0d a6 e7 86 bd 62 b3 a4 f1 9b 89 1a 56 +15 7a 55 4e c2 a2 b3 9e 25 a1 d7 c7 d3 73 21 c7 +a1 d9 46 cf 4f be 75 8d 92 76 f0 85 63 44 9d 67 +41 4a 2c 03 0f 42 51 cf e2 21 3d 04 a5 41 06 37 +87 + +# Signature: +20 9c 61 15 78 57 38 7b 71 e2 4b f3 dd 56 41 45 +50 50 3b ec 18 0f f5 3b dd 9b ac 06 2a 2d 49 95 +09 bf 99 12 81 b7 95 27 df 91 36 61 5b 7a 6d 9d +b3 a1 03 b5 35 e0 20 2a 2c ac a1 97 a7 b7 4e 53 +56 f3 dd 59 5b 49 ac fd 9d 30 04 9a 98 ca 88 f6 +25 bc a1 d5 f2 2a 39 2d 8a 74 9e fb 6e ed 9b 78 +21 d3 11 0a c0 d2 44 19 9e cb 4a a3 d7 35 a8 3a +2e 88 93 c6 bf 85 81 38 3c ca ee 83 46 35 b7 fa +1f af fa 45 b1 3d 15 c1 da 33 af 71 e8 93 03 d6 +80 90 ff 62 ee 61 5f df 5a 84 d1 20 71 1d a5 3c +28 89 19 8a b3 83 17 a9 73 4a b2 7d 67 92 4c ea +74 15 6f f9 9b ef 98 76 bb 5c 33 9e 93 74 52 83 +e1 b3 4e 07 22 26 b8 80 45 e0 17 e9 f0 5b 2a 8c +41 67 40 25 8e 22 3b 26 90 02 74 91 73 22 73 f3 +22 9d 9e f2 b1 b3 80 7e 32 10 18 92 0a d3 e5 3d +ae 47 e6 d9 39 5c 18 4b 93 a3 74 c6 71 fa a2 ce + +# PKCS#1 v1.5 Signature Example 15.20 + +# ----------------- + +# Message to be signed: +40 ee 99 24 58 d6 f6 14 86 d2 56 76 a9 6d d2 cb +93 a3 7f 04 b1 78 48 2f 2b 18 6c f8 82 15 27 0d +ba 29 d7 86 d7 74 b0 c5 e7 8c 7f 6e 56 a9 56 e7 +f7 39 50 a2 b0 c0 c1 0a 08 db cd 67 e5 b2 10 bb +21 c5 8e 27 67 d4 4f 7d d4 01 4e 39 66 14 3b f7 +e3 d6 6f f0 c0 9b e4 c5 5f 93 b3 99 94 b8 51 8d +9c 1d 76 d5 b4 73 74 de a0 8f 15 7d 57 d7 06 34 +97 8f 38 56 e0 e5 b4 81 af bb db 5a 3a c4 8d 48 +4b e9 2c 93 de 22 91 78 35 4c 2d e5 26 e9 c6 5a +31 ed e1 ef 68 cb 63 98 d7 91 16 84 fe c0 ba bc +3a 78 1a 66 66 07 83 50 69 74 d0 e1 48 25 10 1c +3b fa ea + +# Signature: +92 75 02 b8 24 af c4 25 13 ca 65 70 de 33 8b 8a +64 c3 a8 5e b8 28 d3 19 36 24 f2 7e 8b 10 29 c5 +5c 11 9c 97 33 b1 8f 58 49 b3 50 09 18 bc c0 05 +51 d9 a8 fd f5 3a 97 74 9f a8 dc 48 0d 6f e9 74 +2a 58 71 f9 73 92 65 28 97 2a 1a f4 9e 39 25 b0 +ad f1 4a 84 27 19 b4 a5 a2 d8 9f a9 c0 b6 60 5d +21 2b ed 1e 67 23 b9 34 06 ad 30 e8 68 29 a5 c7 +19 b8 90 b3 89 30 6d c5 50 64 86 ee 2f 36 a8 df +e0 a9 6a f6 78 c9 cb d6 af f3 97 ca 20 0e 3e dc +1e 36 bd 2f 08 b3 1d 54 0c 0c b2 82 a9 55 9e 4a +dd 4f c9 e6 49 2e ed 0c cb d3 a6 98 2e 5f aa 2d +dd 17 be 47 41 7c 80 b4 e5 45 2d 31 f7 24 01 a0 +42 32 51 09 54 4d 95 4c 01 93 90 79 d4 09 a5 c3 +78 d7 51 2d fc 2d 2a 71 ef cc 34 32 a7 65 d1 c6 +a5 2c fc e8 99 cd 79 b1 5b 4f c3 72 36 41 ef 6b +d0 0a cc 10 40 7e 5d f5 8d d1 c3 c5 c5 59 a5 06 + +# ============================================= diff --git a/deps/libtomcrypt/notes/rsa-testvectors/pss-int.txt b/deps/libtomcrypt/notes/rsa-testvectors/pss-int.txt new file mode 100644 index 0000000..eb365ac --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/pss-int.txt @@ -0,0 +1,162 @@ +# ================================= +# WORKED-OUT EXAMPLE FOR RSASSA-PSS +# ================================= +# +# This file gives an example of the process of +# signing a message with RSASSA-PSS as +# specified in PKCS #1 v2.1. +# +# The message is an octet string of length 114, +# while the size of the modulus in the public +# key is 1024 bits. The message is signed via a +# random salt of length 20 octets +# +# The underlying hash function in the EMSA-PSS +# encoding method is SHA-1; the mask generation +# function is MGF1 with SHA-1 as specified in +# PKCS #1 v2.1. +# +# Integers are represented by strings of octets +# with the leftmost octet being the most +# significant octet. For example, +# +# 9,202,000 = (0x)8c 69 50. +# +# ============================================= + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +a2 ba 40 ee 07 e3 b2 bd 2f 02 ce 22 7f 36 a1 95 +02 44 86 e4 9c 19 cb 41 bb bd fb ba 98 b2 2b 0e +57 7c 2e ea ff a2 0d 88 3a 76 e6 5e 39 4c 69 d4 +b3 c0 5a 1e 8f ad da 27 ed b2 a4 2b c0 00 fe 88 +8b 9b 32 c2 2d 15 ad d0 cd 76 b3 e7 93 6e 19 95 +5b 22 0d d1 7d 4e a9 04 b1 ec 10 2b 2e 4d e7 75 +12 22 aa 99 15 10 24 c7 cb 41 cc 5e a2 1d 00 ee +b4 1f 7c 80 08 34 d2 c6 e0 6b ce 3b ce 7e a9 a5 + +# RSA public exponent e: +01 00 01 + +# Prime p: +d1 7f 65 5b f2 7c 8b 16 d3 54 62 c9 05 cc 04 a2 +6f 37 e2 a6 7f a9 c0 ce 0d ce d4 72 39 4a 0d f7 +43 fe 7f 92 9e 37 8e fd b3 68 ed df f4 53 cf 00 +7a f6 d9 48 e0 ad e7 57 37 1f 8a 71 1e 27 8f 6b + +# Prime q: +c6 d9 2b 6f ee 74 14 d1 35 8c e1 54 6f b6 29 87 +53 0b 90 bd 15 e0 f1 49 63 a5 e2 63 5a db 69 34 +7e c0 c0 1b 2a b1 76 3f d8 ac 1a 59 2f b2 27 57 +46 3a 98 24 25 bb 97 a3 a4 37 c5 bf 86 d0 3f 2f + +# p's CRT exponent dP: +9d 0d bf 83 e5 ce 9e 4b 17 54 dc d5 cd 05 bc b7 +b5 5f 15 08 33 0e a4 9f 14 d4 e8 89 55 0f 82 56 +cb 5f 80 6d ff 34 b1 7a da 44 20 88 53 57 7d 08 +e4 26 28 90 ac f7 52 46 1c ea 05 54 76 01 bc 4f + +# q's CRT exponent dQ: +12 91 a5 24 c6 b7 c0 59 e9 0e 46 dc 83 b2 17 1e +b3 fa 98 81 8f d1 79 b6 c8 bf 6c ec aa 47 63 03 +ab f2 83 fe 05 76 9c fc 49 57 88 fe 5b 1d df de +9e 88 4a 3c d5 e9 36 b7 e9 55 eb f9 7e b5 63 b1 + +# CRT coefficient qInv: +a6 3f 1d a3 8b 95 0c 9a d1 c6 7c e0 d6 77 ec 29 +14 cd 7d 40 06 2d f4 2a 67 eb 19 8a 17 6f 97 42 +aa c7 c5 fe a1 4f 22 97 66 2b 84 81 2c 4d ef c4 +9a 80 25 ab 43 82 28 6b e4 c0 37 88 dd 01 d6 9f + +# --------------------------------- +# Step-by-step RSASSA-PSS Signature +# --------------------------------- + +# Message M to be signed: +85 9e ef 2f d7 8a ca 00 30 8b dc 47 11 93 bf 55 +bf 9d 78 db 8f 8a 67 2b 48 46 34 f3 c9 c2 6e 64 +78 ae 10 26 0f e0 dd 8c 08 2e 53 a5 29 3a f2 17 +3c d5 0c 6d 5d 35 4f eb f7 8b 26 02 1c 25 c0 27 +12 e7 8c d4 69 4c 9f 46 97 77 e4 51 e7 f8 e9 e0 +4c d3 73 9c 6b bf ed ae 48 7f b5 56 44 e9 ca 74 +ff 77 a5 3c b7 29 80 2f 6e d4 a5 ff a8 ba 15 98 +90 fc + +# mHash = Hash(M) +# salt = random string of octets +# M' = Padding || mHash || salt +# H = Hash(M') +# DB = Padding || salt +# dbMask = MGF(H, length(DB)) +# maskedDB = DB xor dbMask (leftmost bit set to +# zero) +# EM = maskedDB || H || 0xbc + +# mHash: +37 b6 6a e0 44 58 43 35 3d 47 ec b0 b4 fd 14 c1 +10 e6 2d 6a + +# salt: +e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8 +3b ce 7e 61 + +# M': +00 00 00 00 00 00 00 00 37 b6 6a e0 44 58 43 35 +3d 47 ec b0 b4 fd 14 c1 10 e6 2d 6a e3 b5 d5 d0 +02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8 3b ce 7e 61 + +# H: +df 1a 89 6f 9d 8b c8 16 d9 7c d7 a2 c4 3b ad 54 +6f be 8c fe + +# DB: +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +00 00 00 00 00 00 01 e3 b5 d5 d0 02 c1 bc e5 0c +2b 65 ef 88 a1 88 d8 3b ce 7e 61 + +# dbMask: +66 e4 67 2e 83 6a d1 21 ba 24 4b ed 65 76 b8 67 +d9 a4 47 c2 8a 6e 66 a5 b8 7d ee 7f bc 7e 65 af +50 57 f8 6f ae 89 84 d9 ba 7f 96 9a d6 fe 02 a4 +d7 5f 74 45 fe fd d8 5b 6d 3a 47 7c 28 d2 4b a1 +e3 75 6f 79 2d d1 dc e8 ca 94 44 0e cb 52 79 ec +d3 18 3a 31 1f c8 97 39 a9 66 43 13 6e 8b 0f 46 +5e 87 a4 53 5c d4 c5 9b 10 02 8d + +# maskedDB: +66 e4 67 2e 83 6a d1 21 ba 24 4b ed 65 76 b8 67 +d9 a4 47 c2 8a 6e 66 a5 b8 7d ee 7f bc 7e 65 af +50 57 f8 6f ae 89 84 d9 ba 7f 96 9a d6 fe 02 a4 +d7 5f 74 45 fe fd d8 5b 6d 3a 47 7c 28 d2 4b a1 +e3 75 6f 79 2d d1 dc e8 ca 94 44 0e cb 52 79 ec +d3 18 3a 31 1f c8 96 da 1c b3 93 11 af 37 ea 4a +75 e2 4b db fd 5c 1d a0 de 7c ec + +# Encoded message EM: +66 e4 67 2e 83 6a d1 21 ba 24 4b ed 65 76 b8 67 +d9 a4 47 c2 8a 6e 66 a5 b8 7d ee 7f bc 7e 65 af +50 57 f8 6f ae 89 84 d9 ba 7f 96 9a d6 fe 02 a4 +d7 5f 74 45 fe fd d8 5b 6d 3a 47 7c 28 d2 4b a1 +e3 75 6f 79 2d d1 dc e8 ca 94 44 0e cb 52 79 ec +d3 18 3a 31 1f c8 96 da 1c b3 93 11 af 37 ea 4a +75 e2 4b db fd 5c 1d a0 de 7c ec df 1a 89 6f 9d +8b c8 16 d9 7c d7 a2 c4 3b ad 54 6f be 8c fe bc + +# Signature S, the RSA decryption of EM: +8d aa 62 7d 3d e7 59 5d 63 05 6c 7e c6 59 e5 44 +06 f1 06 10 12 8b aa e8 21 c8 b2 a0 f3 93 6d 54 +dc 3b dc e4 66 89 f6 b7 95 1b b1 8e 84 05 42 76 +97 18 d5 71 5d 21 0d 85 ef bb 59 61 92 03 2c 42 +be 4c 29 97 2c 85 62 75 eb 6d 5a 45 f0 5f 51 87 +6f c6 74 3d ed dd 28 ca ec 9b b3 0e a9 9e 02 c3 +48 82 69 60 4f e4 97 f7 4c cd 7c 7f ca 16 71 89 +71 23 cb d3 0d ef 5d 54 a2 b5 53 6a d9 0a 74 7e + +# ============================================= diff --git a/deps/libtomcrypt/notes/rsa-testvectors/pss-vect.c b/deps/libtomcrypt/notes/rsa-testvectors/pss-vect.c new file mode 100644 index 0000000..3db5f5b --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/pss-vect.c @@ -0,0 +1,1418 @@ +/* Generated from file: pss-vect.txt + * with md5 hash: af66c6ca63a09d0443d5f78ff0e59c29 + */ + + +typedef struct rsaKey { + int n_l; + unsigned char n[256]; + int e_l; + unsigned char e[256]; + int d_l; + unsigned char d[256]; + int p_l; + unsigned char p[256]; + int q_l; + unsigned char q[256]; + int dP_l; + unsigned char dP[256]; + int dQ_l; + unsigned char dQ[256]; + int qInv_l; + unsigned char qInv[256]; +} rsaKey_t; + +typedef struct rsaData { + const char* name; + int o1_l; + unsigned char o1[256]; + int o2_l; + unsigned char o2[256]; + int o3_l; + unsigned char o3[256]; +} rsaData_t; + +typedef struct testcase { + const char* name; + rsaKey_t rsa; +#ifdef LTC_TEST_EXT + rsaData_t data[6]; +#else + rsaData_t data[1]; +#endif /* LTC_TEST_EXT */ +} testcase_t; + +testcase_t testcases_pss[] = + { +{ + "Example 1: A 1024-bit RSA Key Pair", +{ + /* RSA modulus n */ + 128, + { 0xa5, 0x6e, 0x4a, 0x0e, 0x70, 0x10, 0x17, 0x58, 0x9a, 0x51, 0x87, 0xdc, 0x7e, 0xa8, 0x41, 0xd1, 0x56, 0xf2, 0xec, 0x0e, 0x36, 0xad, 0x52, 0xa4, 0x4d, 0xfe, 0xb1, 0xe6, 0x1f, 0x7a, 0xd9, 0x91, 0xd8, 0xc5, 0x10, 0x56, 0xff, 0xed, 0xb1, 0x62, 0xb4, 0xc0, 0xf2, 0x83, 0xa1, 0x2a, 0x88, 0xa3, 0x94, 0xdf, 0xf5, 0x26, 0xab, 0x72, 0x91, 0xcb, 0xb3, 0x07, 0xce, 0xab, 0xfc, 0xe0, 0xb1, 0xdf, 0xd5, 0xcd, 0x95, 0x08, 0x09, 0x6d, 0x5b, 0x2b, 0x8b, 0x6d, 0xf5, 0xd6, 0x71, 0xef, 0x63, 0x77, 0xc0, 0x92, 0x1c, 0xb2, 0x3c, 0x27, 0x0a, 0x70, 0xe2, 0x59, 0x8e, 0x6f, 0xf8, 0x9d, 0x19, 0xf1, 0x05, 0xac, 0xc2, 0xd3, 0xf0, 0xcb, 0x35, 0xf2, 0x92, 0x80, 0xe1, 0x38, 0x6b, 0x6f, 0x64, 0xc4, 0xef, 0x22, 0xe1, 0xe1, 0xf2, 0x0d, 0x0c, 0xe8, 0xcf, 0xfb, 0x22, 0x49, 0xbd, 0x9a, 0x21, 0x37 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x33, 0xa5, 0x04, 0x2a, 0x90, 0xb2, 0x7d, 0x4f, 0x54, 0x51, 0xca, 0x9b, 0xbb, 0xd0, 0xb4, 0x47, 0x71, 0xa1, 0x01, 0xaf, 0x88, 0x43, 0x40, 0xae, 0xf9, 0x88, 0x5f, 0x2a, 0x4b, 0xbe, 0x92, 0xe8, 0x94, 0xa7, 0x24, 0xac, 0x3c, 0x56, 0x8c, 0x8f, 0x97, 0x85, 0x3a, 0xd0, 0x7c, 0x02, 0x66, 0xc8, 0xc6, 0xa3, 0xca, 0x09, 0x29, 0xf1, 0xe8, 0xf1, 0x12, 0x31, 0x88, 0x44, 0x29, 0xfc, 0x4d, 0x9a, 0xe5, 0x5f, 0xee, 0x89, 0x6a, 0x10, 0xce, 0x70, 0x7c, 0x3e, 0xd7, 0xe7, 0x34, 0xe4, 0x47, 0x27, 0xa3, 0x95, 0x74, 0x50, 0x1a, 0x53, 0x26, 0x83, 0x10, 0x9c, 0x2a, 0xba, 0xca, 0xba, 0x28, 0x3c, 0x31, 0xb4, 0xbd, 0x2f, 0x53, 0xc3, 0xee, 0x37, 0xe3, 0x52, 0xce, 0xe3, 0x4f, 0x9e, 0x50, 0x3b, 0xd8, 0x0c, 0x06, 0x22, 0xad, 0x79, 0xc6, 0xdc, 0xee, 0x88, 0x35, 0x47, 0xc6, 0xa3, 0xb3, 0x25 } +, + /* Prime p */ + 64, + { 0xe7, 0xe8, 0x94, 0x27, 0x20, 0xa8, 0x77, 0x51, 0x72, 0x73, 0xa3, 0x56, 0x05, 0x3e, 0xa2, 0xa1, 0xbc, 0x0c, 0x94, 0xaa, 0x72, 0xd5, 0x5c, 0x6e, 0x86, 0x29, 0x6b, 0x2d, 0xfc, 0x96, 0x79, 0x48, 0xc0, 0xa7, 0x2c, 0xbc, 0xcc, 0xa7, 0xea, 0xcb, 0x35, 0x70, 0x6e, 0x09, 0xa1, 0xdf, 0x55, 0xa1, 0x53, 0x5b, 0xd9, 0xb3, 0xcc, 0x34, 0x16, 0x0b, 0x3b, 0x6d, 0xcd, 0x3e, 0xda, 0x8e, 0x64, 0x43 } +, + /* Prime q */ + 64, + { 0xb6, 0x9d, 0xca, 0x1c, 0xf7, 0xd4, 0xd7, 0xec, 0x81, 0xe7, 0x5b, 0x90, 0xfc, 0xca, 0x87, 0x4a, 0xbc, 0xde, 0x12, 0x3f, 0xd2, 0x70, 0x01, 0x80, 0xaa, 0x90, 0x47, 0x9b, 0x6e, 0x48, 0xde, 0x8d, 0x67, 0xed, 0x24, 0xf9, 0xf1, 0x9d, 0x85, 0xba, 0x27, 0x58, 0x74, 0xf5, 0x42, 0xcd, 0x20, 0xdc, 0x72, 0x3e, 0x69, 0x63, 0x36, 0x4a, 0x1f, 0x94, 0x25, 0x45, 0x2b, 0x26, 0x9a, 0x67, 0x99, 0xfd } +, + /* p's CRT exponent dP */ + 64, + { 0x28, 0xfa, 0x13, 0x93, 0x86, 0x55, 0xbe, 0x1f, 0x8a, 0x15, 0x9c, 0xba, 0xca, 0x5a, 0x72, 0xea, 0x19, 0x0c, 0x30, 0x08, 0x9e, 0x19, 0xcd, 0x27, 0x4a, 0x55, 0x6f, 0x36, 0xc4, 0xf6, 0xe1, 0x9f, 0x55, 0x4b, 0x34, 0xc0, 0x77, 0x79, 0x04, 0x27, 0xbb, 0xdd, 0x8d, 0xd3, 0xed, 0xe2, 0x44, 0x83, 0x28, 0xf3, 0x85, 0xd8, 0x1b, 0x30, 0xe8, 0xe4, 0x3b, 0x2f, 0xff, 0xa0, 0x27, 0x86, 0x19, 0x79 } +, + /* q's CRT exponent dQ */ + 64, + { 0x1a, 0x8b, 0x38, 0xf3, 0x98, 0xfa, 0x71, 0x20, 0x49, 0x89, 0x8d, 0x7f, 0xb7, 0x9e, 0xe0, 0xa7, 0x76, 0x68, 0x79, 0x12, 0x99, 0xcd, 0xfa, 0x09, 0xef, 0xc0, 0xe5, 0x07, 0xac, 0xb2, 0x1e, 0xd7, 0x43, 0x01, 0xef, 0x5b, 0xfd, 0x48, 0xbe, 0x45, 0x5e, 0xae, 0xb6, 0xe1, 0x67, 0x82, 0x55, 0x82, 0x75, 0x80, 0xa8, 0xe4, 0xe8, 0xe1, 0x41, 0x51, 0xd1, 0x51, 0x0a, 0x82, 0xa3, 0xf2, 0xe7, 0x29 } +, + /* CRT coefficient qInv */ + 64, + { 0x27, 0x15, 0x6a, 0xba, 0x41, 0x26, 0xd2, 0x4a, 0x81, 0xf3, 0xa5, 0x28, 0xcb, 0xfb, 0x27, 0xf5, 0x68, 0x86, 0xf8, 0x40, 0xa9, 0xf6, 0xe8, 0x6e, 0x17, 0xa4, 0x4b, 0x94, 0xfe, 0x93, 0x19, 0x58, 0x4b, 0x8e, 0x22, 0xfd, 0xde, 0x1e, 0x5a, 0x2e, 0x3b, 0xd8, 0xaa, 0x5b, 0xa8, 0xd8, 0x58, 0x41, 0x94, 0xeb, 0x21, 0x90, 0xac, 0xf8, 0x32, 0xb8, 0x47, 0xf1, 0x3a, 0x3d, 0x24, 0xa7, 0x9f, 0x4d } + +} +, +{{ + "RSASSA-PSS Signature Example 1.1", + /* Message to be signed */ + 217, + { 0xcd, 0xc8, 0x7d, 0xa2, 0x23, 0xd7, 0x86, 0xdf, 0x3b, 0x45, 0xe0, 0xbb, 0xbc, 0x72, 0x13, 0x26, 0xd1, 0xee, 0x2a, 0xf8, 0x06, 0xcc, 0x31, 0x54, 0x75, 0xcc, 0x6f, 0x0d, 0x9c, 0x66, 0xe1, 0xb6, 0x23, 0x71, 0xd4, 0x5c, 0xe2, 0x39, 0x2e, 0x1a, 0xc9, 0x28, 0x44, 0xc3, 0x10, 0x10, 0x2f, 0x15, 0x6a, 0x0d, 0x8d, 0x52, 0xc1, 0xf4, 0xc4, 0x0b, 0xa3, 0xaa, 0x65, 0x09, 0x57, 0x86, 0xcb, 0x76, 0x97, 0x57, 0xa6, 0x56, 0x3b, 0xa9, 0x58, 0xfe, 0xd0, 0xbc, 0xc9, 0x84, 0xe8, 0xb5, 0x17, 0xa3, 0xd5, 0xf5, 0x15, 0xb2, 0x3b, 0x8a, 0x41, 0xe7, 0x4a, 0xa8, 0x67, 0x69, 0x3f, 0x90, 0xdf, 0xb0, 0x61, 0xa6, 0xe8, 0x6d, 0xfa, 0xae, 0xe6, 0x44, 0x72, 0xc0, 0x0e, 0x5f, 0x20, 0x94, 0x57, 0x29, 0xcb, 0xeb, 0xe7, 0x7f, 0x06, 0xce, 0x78, 0xe0, 0x8f, 0x40, 0x98, 0xfb, 0xa4, 0x1f, 0x9d, 0x61, 0x93, 0xc0, 0x31, 0x7e, 0x8b, 0x60, 0xd4, 0xb6, 0x08, 0x4a, 0xcb, 0x42, 0xd2, 0x9e, 0x38, 0x08, 0xa3, 0xbc, 0x37, 0x2d, 0x85, 0xe3, 0x31, 0x17, 0x0f, 0xcb, 0xf7, 0xcc, 0x72, 0xd0, 0xb7, 0x1c, 0x29, 0x66, 0x48, 0xb3, 0xa4, 0xd1, 0x0f, 0x41, 0x62, 0x95, 0xd0, 0x80, 0x7a, 0xa6, 0x25, 0xca, 0xb2, 0x74, 0x4f, 0xd9, 0xea, 0x8f, 0xd2, 0x23, 0xc4, 0x25, 0x37, 0x02, 0x98, 0x28, 0xbd, 0x16, 0xbe, 0x02, 0x54, 0x6f, 0x13, 0x0f, 0xd2, 0xe3, 0x3b, 0x93, 0x6d, 0x26, 0x76, 0xe0, 0x8a, 0xed, 0x1b, 0x73, 0x31, 0x8b, 0x75, 0x0a, 0x01, 0x67, 0xd0 } +, + /* Salt */ + 20, + { 0xde, 0xe9, 0x59, 0xc7, 0xe0, 0x64, 0x11, 0x36, 0x14, 0x20, 0xff, 0x80, 0x18, 0x5e, 0xd5, 0x7f, 0x3e, 0x67, 0x76, 0xaf } +, + /* Signature */ + 128, + { 0x90, 0x74, 0x30, 0x8f, 0xb5, 0x98, 0xe9, 0x70, 0x1b, 0x22, 0x94, 0x38, 0x8e, 0x52, 0xf9, 0x71, 0xfa, 0xac, 0x2b, 0x60, 0xa5, 0x14, 0x5a, 0xf1, 0x85, 0xdf, 0x52, 0x87, 0xb5, 0xed, 0x28, 0x87, 0xe5, 0x7c, 0xe7, 0xfd, 0x44, 0xdc, 0x86, 0x34, 0xe4, 0x07, 0xc8, 0xe0, 0xe4, 0x36, 0x0b, 0xc2, 0x26, 0xf3, 0xec, 0x22, 0x7f, 0x9d, 0x9e, 0x54, 0x63, 0x8e, 0x8d, 0x31, 0xf5, 0x05, 0x12, 0x15, 0xdf, 0x6e, 0xbb, 0x9c, 0x2f, 0x95, 0x79, 0xaa, 0x77, 0x59, 0x8a, 0x38, 0xf9, 0x14, 0xb5, 0xb9, 0xc1, 0xbd, 0x83, 0xc4, 0xe2, 0xf9, 0xf3, 0x82, 0xa0, 0xd0, 0xaa, 0x35, 0x42, 0xff, 0xee, 0x65, 0x98, 0x4a, 0x60, 0x1b, 0xc6, 0x9e, 0xb2, 0x8d, 0xeb, 0x27, 0xdc, 0xa1, 0x2c, 0x82, 0xc2, 0xd4, 0xc3, 0xf6, 0x6c, 0xd5, 0x00, 0xf1, 0xff, 0x2b, 0x99, 0x4d, 0x8a, 0x4e, 0x30, 0xcb, 0xb3, 0x3c } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 1.2", + /* Message to be signed */ + 51, + { 0x85, 0x13, 0x84, 0xcd, 0xfe, 0x81, 0x9c, 0x22, 0xed, 0x6c, 0x4c, 0xcb, 0x30, 0xda, 0xeb, 0x5c, 0xf0, 0x59, 0xbc, 0x8e, 0x11, 0x66, 0xb7, 0xe3, 0x53, 0x0c, 0x4c, 0x23, 0x3e, 0x2b, 0x5f, 0x8f, 0x71, 0xa1, 0xcc, 0xa5, 0x82, 0xd4, 0x3e, 0xcc, 0x72, 0xb1, 0xbc, 0xa1, 0x6d, 0xfc, 0x70, 0x13, 0x22, 0x6b, 0x9e } +, + /* Salt */ + 20, + { 0xef, 0x28, 0x69, 0xfa, 0x40, 0xc3, 0x46, 0xcb, 0x18, 0x3d, 0xab, 0x3d, 0x7b, 0xff, 0xc9, 0x8f, 0xd5, 0x6d, 0xf4, 0x2d } +, + /* Signature */ + 128, + { 0x3e, 0xf7, 0xf4, 0x6e, 0x83, 0x1b, 0xf9, 0x2b, 0x32, 0x27, 0x41, 0x42, 0xa5, 0x85, 0xff, 0xce, 0xfb, 0xdc, 0xa7, 0xb3, 0x2a, 0xe9, 0x0d, 0x10, 0xfb, 0x0f, 0x0c, 0x72, 0x99, 0x84, 0xf0, 0x4e, 0xf2, 0x9a, 0x9d, 0xf0, 0x78, 0x07, 0x75, 0xce, 0x43, 0x73, 0x9b, 0x97, 0x83, 0x83, 0x90, 0xdb, 0x0a, 0x55, 0x05, 0xe6, 0x3d, 0xe9, 0x27, 0x02, 0x8d, 0x9d, 0x29, 0xb2, 0x19, 0xca, 0x2c, 0x45, 0x17, 0x83, 0x25, 0x58, 0xa5, 0x5d, 0x69, 0x4a, 0x6d, 0x25, 0xb9, 0xda, 0xb6, 0x60, 0x03, 0xc4, 0xcc, 0xcd, 0x90, 0x78, 0x02, 0x19, 0x3b, 0xe5, 0x17, 0x0d, 0x26, 0x14, 0x7d, 0x37, 0xb9, 0x35, 0x90, 0x24, 0x1b, 0xe5, 0x1c, 0x25, 0x05, 0x5f, 0x47, 0xef, 0x62, 0x75, 0x2c, 0xfb, 0xe2, 0x14, 0x18, 0xfa, 0xfe, 0x98, 0xc2, 0x2c, 0x4d, 0x4d, 0x47, 0x72, 0x4f, 0xdb, 0x56, 0x69, 0xe8, 0x43 } + +} +, +{ + "RSASSA-PSS Signature Example 1.3", + /* Message to be signed */ + 228, + { 0xa4, 0xb1, 0x59, 0x94, 0x17, 0x61, 0xc4, 0x0c, 0x6a, 0x82, 0xf2, 0xb8, 0x0d, 0x1b, 0x94, 0xf5, 0xaa, 0x26, 0x54, 0xfd, 0x17, 0xe1, 0x2d, 0x58, 0x88, 0x64, 0x67, 0x9b, 0x54, 0xcd, 0x04, 0xef, 0x8b, 0xd0, 0x30, 0x12, 0xbe, 0x8d, 0xc3, 0x7f, 0x4b, 0x83, 0xaf, 0x79, 0x63, 0xfa, 0xff, 0x0d, 0xfa, 0x22, 0x54, 0x77, 0x43, 0x7c, 0x48, 0x01, 0x7f, 0xf2, 0xbe, 0x81, 0x91, 0xcf, 0x39, 0x55, 0xfc, 0x07, 0x35, 0x6e, 0xab, 0x3f, 0x32, 0x2f, 0x7f, 0x62, 0x0e, 0x21, 0xd2, 0x54, 0xe5, 0xdb, 0x43, 0x24, 0x27, 0x9f, 0xe0, 0x67, 0xe0, 0x91, 0x0e, 0x2e, 0x81, 0xca, 0x2c, 0xab, 0x31, 0xc7, 0x45, 0xe6, 0x7a, 0x54, 0x05, 0x8e, 0xb5, 0x0d, 0x99, 0x3c, 0xdb, 0x9e, 0xd0, 0xb4, 0xd0, 0x29, 0xc0, 0x6d, 0x21, 0xa9, 0x4c, 0xa6, 0x61, 0xc3, 0xce, 0x27, 0xfa, 0xe1, 0xd6, 0xcb, 0x20, 0xf4, 0x56, 0x4d, 0x66, 0xce, 0x47, 0x67, 0x58, 0x3d, 0x0e, 0x5f, 0x06, 0x02, 0x15, 0xb5, 0x90, 0x17, 0xbe, 0x85, 0xea, 0x84, 0x89, 0x39, 0x12, 0x7b, 0xd8, 0xc9, 0xc4, 0xd4, 0x7b, 0x51, 0x05, 0x6c, 0x03, 0x1c, 0xf3, 0x36, 0xf1, 0x7c, 0x99, 0x80, 0xf3, 0xb8, 0xf5, 0xb9, 0xb6, 0x87, 0x8e, 0x8b, 0x79, 0x7a, 0xa4, 0x3b, 0x88, 0x26, 0x84, 0x33, 0x3e, 0x17, 0x89, 0x3f, 0xe9, 0xca, 0xa6, 0xaa, 0x29, 0x9f, 0x7e, 0xd1, 0xa1, 0x8e, 0xe2, 0xc5, 0x48, 0x64, 0xb7, 0xb2, 0xb9, 0x9b, 0x72, 0x61, 0x8f, 0xb0, 0x25, 0x74, 0xd1, 0x39, 0xef, 0x50, 0xf0, 0x19, 0xc9, 0xee, 0xf4, 0x16, 0x97, 0x13, 0x38, 0xe7, 0xd4, 0x70 } +, + /* Salt */ + 20, + { 0x71, 0x0b, 0x9c, 0x47, 0x47, 0xd8, 0x00, 0xd4, 0xde, 0x87, 0xf1, 0x2a, 0xfd, 0xce, 0x6d, 0xf1, 0x81, 0x07, 0xcc, 0x77 } +, + /* Signature */ + 128, + { 0x66, 0x60, 0x26, 0xfb, 0xa7, 0x1b, 0xd3, 0xe7, 0xcf, 0x13, 0x15, 0x7c, 0xc2, 0xc5, 0x1a, 0x8e, 0x4a, 0xa6, 0x84, 0xaf, 0x97, 0x78, 0xf9, 0x18, 0x49, 0xf3, 0x43, 0x35, 0xd1, 0x41, 0xc0, 0x01, 0x54, 0xc4, 0x19, 0x76, 0x21, 0xf9, 0x62, 0x4a, 0x67, 0x5b, 0x5a, 0xbc, 0x22, 0xee, 0x7d, 0x5b, 0xaa, 0xff, 0xaa, 0xe1, 0xc9, 0xba, 0xca, 0x2c, 0xc3, 0x73, 0xb3, 0xf3, 0x3e, 0x78, 0xe6, 0x14, 0x3c, 0x39, 0x5a, 0x91, 0xaa, 0x7f, 0xac, 0xa6, 0x64, 0xeb, 0x73, 0x3a, 0xfd, 0x14, 0xd8, 0x82, 0x72, 0x59, 0xd9, 0x9a, 0x75, 0x50, 0xfa, 0xca, 0x50, 0x1e, 0xf2, 0xb0, 0x4e, 0x33, 0xc2, 0x3a, 0xa5, 0x1f, 0x4b, 0x9e, 0x82, 0x82, 0xef, 0xdb, 0x72, 0x8c, 0xc0, 0xab, 0x09, 0x40, 0x5a, 0x91, 0x60, 0x7c, 0x63, 0x69, 0x96, 0x1b, 0xc8, 0x27, 0x0d, 0x2d, 0x4f, 0x39, 0xfc, 0xe6, 0x12, 0xb1 } + +} +, +{ + "RSASSA-PSS Signature Example 1.4", + /* Message to be signed */ + 9, + { 0xbc, 0x65, 0x67, 0x47, 0xfa, 0x9e, 0xaf, 0xb3, 0xf0 } +, + /* Salt */ + 20, + { 0x05, 0x6f, 0x00, 0x98, 0x5d, 0xe1, 0x4d, 0x8e, 0xf5, 0xce, 0xa9, 0xe8, 0x2f, 0x8c, 0x27, 0xbe, 0xf7, 0x20, 0x33, 0x5e } +, + /* Signature */ + 128, + { 0x46, 0x09, 0x79, 0x3b, 0x23, 0xe9, 0xd0, 0x93, 0x62, 0xdc, 0x21, 0xbb, 0x47, 0xda, 0x0b, 0x4f, 0x3a, 0x76, 0x22, 0x64, 0x9a, 0x47, 0xd4, 0x64, 0x01, 0x9b, 0x9a, 0xea, 0xfe, 0x53, 0x35, 0x9c, 0x17, 0x8c, 0x91, 0xcd, 0x58, 0xba, 0x6b, 0xcb, 0x78, 0xbe, 0x03, 0x46, 0xa7, 0xbc, 0x63, 0x7f, 0x4b, 0x87, 0x3d, 0x4b, 0xab, 0x38, 0xee, 0x66, 0x1f, 0x19, 0x96, 0x34, 0xc5, 0x47, 0xa1, 0xad, 0x84, 0x42, 0xe0, 0x3d, 0xa0, 0x15, 0xb1, 0x36, 0xe5, 0x43, 0xf7, 0xab, 0x07, 0xc0, 0xc1, 0x3e, 0x42, 0x25, 0xb8, 0xde, 0x8c, 0xce, 0x25, 0xd4, 0xf6, 0xeb, 0x84, 0x00, 0xf8, 0x1f, 0x7e, 0x18, 0x33, 0xb7, 0xee, 0x6e, 0x33, 0x4d, 0x37, 0x09, 0x64, 0xca, 0x79, 0xfd, 0xb8, 0x72, 0xb4, 0xd7, 0x52, 0x23, 0xb5, 0xee, 0xb0, 0x81, 0x01, 0x59, 0x1f, 0xb5, 0x32, 0xd1, 0x55, 0xa6, 0xde, 0x87 } + +} +, +{ + "RSASSA-PSS Signature Example 1.5", + /* Message to be signed */ + 149, + { 0xb4, 0x55, 0x81, 0x54, 0x7e, 0x54, 0x27, 0x77, 0x0c, 0x76, 0x8e, 0x8b, 0x82, 0xb7, 0x55, 0x64, 0xe0, 0xea, 0x4e, 0x9c, 0x32, 0x59, 0x4d, 0x6b, 0xff, 0x70, 0x65, 0x44, 0xde, 0x0a, 0x87, 0x76, 0xc7, 0xa8, 0x0b, 0x45, 0x76, 0x55, 0x0e, 0xee, 0x1b, 0x2a, 0xca, 0xbc, 0x7e, 0x8b, 0x7d, 0x3e, 0xf7, 0xbb, 0x5b, 0x03, 0xe4, 0x62, 0xc1, 0x10, 0x47, 0xea, 0xdd, 0x00, 0x62, 0x9a, 0xe5, 0x75, 0x48, 0x0a, 0xc1, 0x47, 0x0f, 0xe0, 0x46, 0xf1, 0x3a, 0x2b, 0xf5, 0xaf, 0x17, 0x92, 0x1d, 0xc4, 0xb0, 0xaa, 0x8b, 0x02, 0xbe, 0xe6, 0x33, 0x49, 0x11, 0x65, 0x1d, 0x7f, 0x85, 0x25, 0xd1, 0x0f, 0x32, 0xb5, 0x1d, 0x33, 0xbe, 0x52, 0x0d, 0x3d, 0xdf, 0x5a, 0x70, 0x99, 0x55, 0xa3, 0xdf, 0xe7, 0x82, 0x83, 0xb9, 0xe0, 0xab, 0x54, 0x04, 0x6d, 0x15, 0x0c, 0x17, 0x7f, 0x03, 0x7f, 0xdc, 0xcc, 0x5b, 0xe4, 0xea, 0x5f, 0x68, 0xb5, 0xe5, 0xa3, 0x8c, 0x9d, 0x7e, 0xdc, 0xcc, 0xc4, 0x97, 0x5f, 0x45, 0x5a, 0x69, 0x09, 0xb4 } +, + /* Salt */ + 20, + { 0x80, 0xe7, 0x0f, 0xf8, 0x6a, 0x08, 0xde, 0x3e, 0xc6, 0x09, 0x72, 0xb3, 0x9b, 0x4f, 0xbf, 0xdc, 0xea, 0x67, 0xae, 0x8e } +, + /* Signature */ + 128, + { 0x1d, 0x2a, 0xad, 0x22, 0x1c, 0xa4, 0xd3, 0x1d, 0xdf, 0x13, 0x50, 0x92, 0x39, 0x01, 0x93, 0x98, 0xe3, 0xd1, 0x4b, 0x32, 0xdc, 0x34, 0xdc, 0x5a, 0xf4, 0xae, 0xae, 0xa3, 0xc0, 0x95, 0xaf, 0x73, 0x47, 0x9c, 0xf0, 0xa4, 0x5e, 0x56, 0x29, 0x63, 0x5a, 0x53, 0xa0, 0x18, 0x37, 0x76, 0x15, 0xb1, 0x6c, 0xb9, 0xb1, 0x3b, 0x3e, 0x09, 0xd6, 0x71, 0xeb, 0x71, 0xe3, 0x87, 0xb8, 0x54, 0x5c, 0x59, 0x60, 0xda, 0x5a, 0x64, 0x77, 0x6e, 0x76, 0x8e, 0x82, 0xb2, 0xc9, 0x35, 0x83, 0xbf, 0x10, 0x4c, 0x3f, 0xdb, 0x23, 0x51, 0x2b, 0x7b, 0x4e, 0x89, 0xf6, 0x33, 0xdd, 0x00, 0x63, 0xa5, 0x30, 0xdb, 0x45, 0x24, 0xb0, 0x1c, 0x3f, 0x38, 0x4c, 0x09, 0x31, 0x0e, 0x31, 0x5a, 0x79, 0xdc, 0xd3, 0xd6, 0x84, 0x02, 0x2a, 0x7f, 0x31, 0xc8, 0x65, 0xa6, 0x64, 0xe3, 0x16, 0x97, 0x8b, 0x75, 0x9f, 0xad } + +} +, +{ + "RSASSA-PSS Signature Example 1.6", + /* Message to be signed */ + 233, + { 0x10, 0xaa, 0xe9, 0xa0, 0xab, 0x0b, 0x59, 0x5d, 0x08, 0x41, 0x20, 0x7b, 0x70, 0x0d, 0x48, 0xd7, 0x5f, 0xae, 0xdd, 0xe3, 0xb7, 0x75, 0xcd, 0x6b, 0x4c, 0xc8, 0x8a, 0xe0, 0x6e, 0x46, 0x94, 0xec, 0x74, 0xba, 0x18, 0xf8, 0x52, 0x0d, 0x4f, 0x5e, 0xa6, 0x9c, 0xbb, 0xe7, 0xcc, 0x2b, 0xeb, 0xa4, 0x3e, 0xfd, 0xc1, 0x02, 0x15, 0xac, 0x4e, 0xb3, 0x2d, 0xc3, 0x02, 0xa1, 0xf5, 0x3d, 0xc6, 0xc4, 0x35, 0x22, 0x67, 0xe7, 0x93, 0x6c, 0xfe, 0xbf, 0x7c, 0x8d, 0x67, 0x03, 0x57, 0x84, 0xa3, 0x90, 0x9f, 0xa8, 0x59, 0xc7, 0xb7, 0xb5, 0x9b, 0x8e, 0x39, 0xc5, 0xc2, 0x34, 0x9f, 0x18, 0x86, 0xb7, 0x05, 0xa3, 0x02, 0x67, 0xd4, 0x02, 0xf7, 0x48, 0x6a, 0xb4, 0xf5, 0x8c, 0xad, 0x5d, 0x69, 0xad, 0xb1, 0x7a, 0xb8, 0xcd, 0x0c, 0xe1, 0xca, 0xf5, 0x02, 0x5a, 0xf4, 0xae, 0x24, 0xb1, 0xfb, 0x87, 0x94, 0xc6, 0x07, 0x0c, 0xc0, 0x9a, 0x51, 0xe2, 0xf9, 0x91, 0x13, 0x11, 0xe3, 0x87, 0x7d, 0x00, 0x44, 0xc7, 0x1c, 0x57, 0xa9, 0x93, 0x39, 0x50, 0x08, 0x80, 0x6b, 0x72, 0x3a, 0xc3, 0x83, 0x73, 0xd3, 0x95, 0x48, 0x18, 0x18, 0x52, 0x8c, 0x1e, 0x70, 0x53, 0x73, 0x92, 0x82, 0x05, 0x35, 0x29, 0x51, 0x0e, 0x93, 0x5c, 0xd0, 0xfa, 0x77, 0xb8, 0xfa, 0x53, 0xcc, 0x2d, 0x47, 0x4b, 0xd4, 0xfb, 0x3c, 0xc5, 0xc6, 0x72, 0xd6, 0xff, 0xdc, 0x90, 0xa0, 0x0f, 0x98, 0x48, 0x71, 0x2c, 0x4b, 0xcf, 0xe4, 0x6c, 0x60, 0x57, 0x36, 0x59, 0xb1, 0x1e, 0x64, 0x57, 0xe8, 0x61, 0xf0, 0xf6, 0x04, 0xb6, 0x13, 0x8d, 0x14, 0x4f, 0x8c, 0xe4, 0xe2, 0xda, 0x73 } +, + /* Salt */ + 20, + { 0xa8, 0xab, 0x69, 0xdd, 0x80, 0x1f, 0x00, 0x74, 0xc2, 0xa1, 0xfc, 0x60, 0x64, 0x98, 0x36, 0xc6, 0x16, 0xd9, 0x96, 0x81 } +, + /* Signature */ + 128, + { 0x2a, 0x34, 0xf6, 0x12, 0x5e, 0x1f, 0x6b, 0x0b, 0xf9, 0x71, 0xe8, 0x4f, 0xbd, 0x41, 0xc6, 0x32, 0xbe, 0x8f, 0x2c, 0x2a, 0xce, 0x7d, 0xe8, 0xb6, 0x92, 0x6e, 0x31, 0xff, 0x93, 0xe9, 0xaf, 0x98, 0x7f, 0xbc, 0x06, 0xe5, 0x1e, 0x9b, 0xe1, 0x4f, 0x51, 0x98, 0xf9, 0x1f, 0x3f, 0x95, 0x3b, 0xd6, 0x7d, 0xa6, 0x0a, 0x9d, 0xf5, 0x97, 0x64, 0xc3, 0xdc, 0x0f, 0xe0, 0x8e, 0x1c, 0xbe, 0xf0, 0xb7, 0x5f, 0x86, 0x8d, 0x10, 0xad, 0x3f, 0xba, 0x74, 0x9f, 0xef, 0x59, 0xfb, 0x6d, 0xac, 0x46, 0xa0, 0xd6, 0xe5, 0x04, 0x36, 0x93, 0x31, 0x58, 0x6f, 0x58, 0xe4, 0x62, 0x8f, 0x39, 0xaa, 0x27, 0x89, 0x82, 0x54, 0x3b, 0xc0, 0xee, 0xb5, 0x37, 0xdc, 0x61, 0x95, 0x80, 0x19, 0xb3, 0x94, 0xfb, 0x27, 0x3f, 0x21, 0x58, 0x58, 0xa0, 0xa0, 0x1a, 0xc4, 0xd6, 0x50, 0xb9, 0x55, 0xc6, 0x7f, 0x4c, 0x58 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 2: A 1025-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x01, 0xd4, 0x0c, 0x1b, 0xcf, 0x97, 0xa6, 0x8a, 0xe7, 0xcd, 0xbd, 0x8a, 0x7b, 0xf3, 0xe3, 0x4f, 0xa1, 0x9d, 0xcc, 0xa4, 0xef, 0x75, 0xa4, 0x74, 0x54, 0x37, 0x5f, 0x94, 0x51, 0x4d, 0x88, 0xfe, 0xd0, 0x06, 0xfb, 0x82, 0x9f, 0x84, 0x19, 0xff, 0x87, 0xd6, 0x31, 0x5d, 0xa6, 0x8a, 0x1f, 0xf3, 0xa0, 0x93, 0x8e, 0x9a, 0xbb, 0x34, 0x64, 0x01, 0x1c, 0x30, 0x3a, 0xd9, 0x91, 0x99, 0xcf, 0x0c, 0x7c, 0x7a, 0x8b, 0x47, 0x7d, 0xce, 0x82, 0x9e, 0x88, 0x44, 0xf6, 0x25, 0xb1, 0x15, 0xe5, 0xe9, 0xc4, 0xa5, 0x9c, 0xf8, 0xf8, 0x11, 0x3b, 0x68, 0x34, 0x33, 0x6a, 0x2f, 0xd2, 0x68, 0x9b, 0x47, 0x2c, 0xbb, 0x5e, 0x5c, 0xab, 0xe6, 0x74, 0x35, 0x0c, 0x59, 0xb6, 0xc1, 0x7e, 0x17, 0x68, 0x74, 0xfb, 0x42, 0xf8, 0xfc, 0x3d, 0x17, 0x6a, 0x01, 0x7e, 0xdc, 0x61, 0xfd, 0x32, 0x6c, 0x4b, 0x33, 0xc9 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x02, 0x7d, 0x14, 0x7e, 0x46, 0x73, 0x05, 0x73, 0x77, 0xfd, 0x1e, 0xa2, 0x01, 0x56, 0x57, 0x72, 0x17, 0x6a, 0x7d, 0xc3, 0x83, 0x58, 0xd3, 0x76, 0x04, 0x56, 0x85, 0xa2, 0xe7, 0x87, 0xc2, 0x3c, 0x15, 0x57, 0x6b, 0xc1, 0x6b, 0x9f, 0x44, 0x44, 0x02, 0xd6, 0xbf, 0xc5, 0xd9, 0x8a, 0x3e, 0x88, 0xea, 0x13, 0xef, 0x67, 0xc3, 0x53, 0xec, 0xa0, 0xc0, 0xdd, 0xba, 0x92, 0x55, 0xbd, 0x7b, 0x8b, 0xb5, 0x0a, 0x64, 0x4a, 0xfd, 0xfd, 0x1d, 0xd5, 0x16, 0x95, 0xb2, 0x52, 0xd2, 0x2e, 0x73, 0x18, 0xd1, 0xb6, 0x68, 0x7a, 0x1c, 0x10, 0xff, 0x75, 0x54, 0x5f, 0x3d, 0xb0, 0xfe, 0x60, 0x2d, 0x5f, 0x2b, 0x7f, 0x29, 0x4e, 0x36, 0x01, 0xea, 0xb7, 0xb9, 0xd1, 0xce, 0xcd, 0x76, 0x7f, 0x64, 0x69, 0x2e, 0x3e, 0x53, 0x6c, 0xa2, 0x84, 0x6c, 0xb0, 0xc2, 0xdd, 0x48, 0x6a, 0x39, 0xfa, 0x75, 0xb1 } +, + /* Prime p */ + 65, + { 0x01, 0x66, 0x01, 0xe9, 0x26, 0xa0, 0xf8, 0xc9, 0xe2, 0x6e, 0xca, 0xb7, 0x69, 0xea, 0x65, 0xa5, 0xe7, 0xc5, 0x2c, 0xc9, 0xe0, 0x80, 0xef, 0x51, 0x94, 0x57, 0xc6, 0x44, 0xda, 0x68, 0x91, 0xc5, 0xa1, 0x04, 0xd3, 0xea, 0x79, 0x55, 0x92, 0x9a, 0x22, 0xe7, 0xc6, 0x8a, 0x7a, 0xf9, 0xfc, 0xad, 0x77, 0x7c, 0x3c, 0xcc, 0x2b, 0x9e, 0x3d, 0x36, 0x50, 0xbc, 0xe4, 0x04, 0x39, 0x9b, 0x7e, 0x59, 0xd1 } +, + /* Prime q */ + 65, + { 0x01, 0x4e, 0xaf, 0xa1, 0xd4, 0xd0, 0x18, 0x4d, 0xa7, 0xe3, 0x1f, 0x87, 0x7d, 0x12, 0x81, 0xdd, 0xda, 0x62, 0x56, 0x64, 0x86, 0x9e, 0x83, 0x79, 0xe6, 0x7a, 0xd3, 0xb7, 0x5e, 0xae, 0x74, 0xa5, 0x80, 0xe9, 0x82, 0x7a, 0xbd, 0x6e, 0xb7, 0xa0, 0x02, 0xcb, 0x54, 0x11, 0xf5, 0x26, 0x67, 0x97, 0x76, 0x8f, 0xb8, 0xe9, 0x5a, 0xe4, 0x0e, 0x3e, 0x8a, 0x01, 0xf3, 0x5f, 0xf8, 0x9e, 0x56, 0xc0, 0x79 } +, + /* p's CRT exponent dP */ + 64, + { 0xe2, 0x47, 0xcc, 0xe5, 0x04, 0x93, 0x9b, 0x8f, 0x0a, 0x36, 0x09, 0x0d, 0xe2, 0x00, 0x93, 0x87, 0x55, 0xe2, 0x44, 0x4b, 0x29, 0x53, 0x9a, 0x7d, 0xa7, 0xa9, 0x02, 0xf6, 0x05, 0x68, 0x35, 0xc0, 0xdb, 0x7b, 0x52, 0x55, 0x94, 0x97, 0xcf, 0xe2, 0xc6, 0x1a, 0x80, 0x86, 0xd0, 0x21, 0x3c, 0x47, 0x2c, 0x78, 0x85, 0x18, 0x00, 0xb1, 0x71, 0xf6, 0x40, 0x1d, 0xe2, 0xe9, 0xc2, 0x75, 0x6f, 0x31 } +, + /* q's CRT exponent dQ */ + 64, + { 0xb1, 0x2f, 0xba, 0x75, 0x78, 0x55, 0xe5, 0x86, 0xe4, 0x6f, 0x64, 0xc3, 0x8a, 0x70, 0xc6, 0x8b, 0x3f, 0x54, 0x8d, 0x93, 0xd7, 0x87, 0xb3, 0x99, 0x99, 0x9d, 0x4c, 0x8f, 0x0b, 0xbd, 0x25, 0x81, 0xc2, 0x1e, 0x19, 0xed, 0x00, 0x18, 0xa6, 0xd5, 0xd3, 0xdf, 0x86, 0x42, 0x4b, 0x3a, 0xbc, 0xad, 0x40, 0x19, 0x9d, 0x31, 0x49, 0x5b, 0x61, 0x30, 0x9f, 0x27, 0xc1, 0xbf, 0x55, 0xd4, 0x87, 0xc1 } +, + /* CRT coefficient qInv */ + 64, + { 0x56, 0x4b, 0x1e, 0x1f, 0xa0, 0x03, 0xbd, 0xa9, 0x1e, 0x89, 0x09, 0x04, 0x25, 0xaa, 0xc0, 0x5b, 0x91, 0xda, 0x9e, 0xe2, 0x50, 0x61, 0xe7, 0x62, 0x8d, 0x5f, 0x51, 0x30, 0x4a, 0x84, 0x99, 0x2f, 0xdc, 0x33, 0x76, 0x2b, 0xd3, 0x78, 0xa5, 0x9f, 0x03, 0x0a, 0x33, 0x4d, 0x53, 0x2b, 0xd0, 0xda, 0xe8, 0xf2, 0x98, 0xea, 0x9e, 0xd8, 0x44, 0x63, 0x6a, 0xd5, 0xfb, 0x8c, 0xbd, 0xc0, 0x3c, 0xad } + +} +, +{{ + "RSASSA-PSS Signature Example 2.1", + /* Message to be signed */ + 61, + { 0xda, 0xba, 0x03, 0x20, 0x66, 0x26, 0x3f, 0xae, 0xdb, 0x65, 0x98, 0x48, 0x11, 0x52, 0x78, 0xa5, 0x2c, 0x44, 0xfa, 0xa3, 0xa7, 0x6f, 0x37, 0x51, 0x5e, 0xd3, 0x36, 0x32, 0x10, 0x72, 0xc4, 0x0a, 0x9d, 0x9b, 0x53, 0xbc, 0x05, 0x01, 0x40, 0x78, 0xad, 0xf5, 0x20, 0x87, 0x51, 0x46, 0xaa, 0xe7, 0x0f, 0xf0, 0x60, 0x22, 0x6d, 0xcb, 0x7b, 0x1f, 0x1f, 0xc2, 0x7e, 0x93, 0x60 } +, + /* Salt */ + 20, + { 0x57, 0xbf, 0x16, 0x0b, 0xcb, 0x02, 0xbb, 0x1d, 0xc7, 0x28, 0x0c, 0xf0, 0x45, 0x85, 0x30, 0xb7, 0xd2, 0x83, 0x2f, 0xf7 } +, + /* Signature */ + 129, + { 0x01, 0x4c, 0x5b, 0xa5, 0x33, 0x83, 0x28, 0xcc, 0xc6, 0xe7, 0xa9, 0x0b, 0xf1, 0xc0, 0xab, 0x3f, 0xd6, 0x06, 0xff, 0x47, 0x96, 0xd3, 0xc1, 0x2e, 0x4b, 0x63, 0x9e, 0xd9, 0x13, 0x6a, 0x5f, 0xec, 0x6c, 0x16, 0xd8, 0x88, 0x4b, 0xdd, 0x99, 0xcf, 0xdc, 0x52, 0x14, 0x56, 0xb0, 0x74, 0x2b, 0x73, 0x68, 0x68, 0xcf, 0x90, 0xde, 0x09, 0x9a, 0xdb, 0x8d, 0x5f, 0xfd, 0x1d, 0xef, 0xf3, 0x9b, 0xa4, 0x00, 0x7a, 0xb7, 0x46, 0xce, 0xfd, 0xb2, 0x2d, 0x7d, 0xf0, 0xe2, 0x25, 0xf5, 0x46, 0x27, 0xdc, 0x65, 0x46, 0x61, 0x31, 0x72, 0x1b, 0x90, 0xaf, 0x44, 0x53, 0x63, 0xa8, 0x35, 0x8b, 0x9f, 0x60, 0x76, 0x42, 0xf7, 0x8f, 0xab, 0x0a, 0xb0, 0xf4, 0x3b, 0x71, 0x68, 0xd6, 0x4b, 0xae, 0x70, 0xd8, 0x82, 0x78, 0x48, 0xd8, 0xef, 0x1e, 0x42, 0x1c, 0x57, 0x54, 0xdd, 0xf4, 0x2c, 0x25, 0x89, 0xb5, 0xb3 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 2.2", + /* Message to be signed */ + 234, + { 0xe4, 0xf8, 0x60, 0x1a, 0x8a, 0x6d, 0xa1, 0xbe, 0x34, 0x44, 0x7c, 0x09, 0x59, 0xc0, 0x58, 0x57, 0x0c, 0x36, 0x68, 0xcf, 0xd5, 0x1d, 0xd5, 0xf9, 0xcc, 0xd6, 0xad, 0x44, 0x11, 0xfe, 0x82, 0x13, 0x48, 0x6d, 0x78, 0xa6, 0xc4, 0x9f, 0x93, 0xef, 0xc2, 0xca, 0x22, 0x88, 0xce, 0xbc, 0x2b, 0x9b, 0x60, 0xbd, 0x04, 0xb1, 0xe2, 0x20, 0xd8, 0x6e, 0x3d, 0x48, 0x48, 0xd7, 0x09, 0xd0, 0x32, 0xd1, 0xe8, 0xc6, 0xa0, 0x70, 0xc6, 0xaf, 0x9a, 0x49, 0x9f, 0xcf, 0x95, 0x35, 0x4b, 0x14, 0xba, 0x61, 0x27, 0xc7, 0x39, 0xde, 0x1b, 0xb0, 0xfd, 0x16, 0x43, 0x1e, 0x46, 0x93, 0x8a, 0xec, 0x0c, 0xf8, 0xad, 0x9e, 0xb7, 0x2e, 0x83, 0x2a, 0x70, 0x35, 0xde, 0x9b, 0x78, 0x07, 0xbd, 0xc0, 0xed, 0x8b, 0x68, 0xeb, 0x0f, 0x5a, 0xc2, 0x21, 0x6b, 0xe4, 0x0c, 0xe9, 0x20, 0xc0, 0xdb, 0x0e, 0xdd, 0xd3, 0x86, 0x0e, 0xd7, 0x88, 0xef, 0xac, 0xca, 0xca, 0x50, 0x2d, 0x8f, 0x2b, 0xd6, 0xd1, 0xa7, 0xc1, 0xf4, 0x1f, 0xf4, 0x6f, 0x16, 0x81, 0xc8, 0xf1, 0xf8, 0x18, 0xe9, 0xc4, 0xf6, 0xd9, 0x1a, 0x0c, 0x78, 0x03, 0xcc, 0xc6, 0x3d, 0x76, 0xa6, 0x54, 0x4d, 0x84, 0x3e, 0x08, 0x4e, 0x36, 0x3b, 0x8a, 0xcc, 0x55, 0xaa, 0x53, 0x17, 0x33, 0xed, 0xb5, 0xde, 0xe5, 0xb5, 0x19, 0x6e, 0x9f, 0x03, 0xe8, 0xb7, 0x31, 0xb3, 0x77, 0x64, 0x28, 0xd9, 0xe4, 0x57, 0xfe, 0x3f, 0xbc, 0xb3, 0xdb, 0x72, 0x74, 0x44, 0x2d, 0x78, 0x58, 0x90, 0xe9, 0xcb, 0x08, 0x54, 0xb6, 0x44, 0x4d, 0xac, 0xe7, 0x91, 0xd7, 0x27, 0x3d, 0xe1, 0x88, 0x97, 0x19, 0x33, 0x8a, 0x77, 0xfe } +, + /* Salt */ + 20, + { 0x7f, 0x6d, 0xd3, 0x59, 0xe6, 0x04, 0xe6, 0x08, 0x70, 0xe8, 0x98, 0xe4, 0x7b, 0x19, 0xbf, 0x2e, 0x5a, 0x7b, 0x2a, 0x90 } +, + /* Signature */ + 129, + { 0x01, 0x09, 0x91, 0x65, 0x6c, 0xca, 0x18, 0x2b, 0x7f, 0x29, 0xd2, 0xdb, 0xc0, 0x07, 0xe7, 0xae, 0x0f, 0xec, 0x15, 0x8e, 0xb6, 0x75, 0x9c, 0xb9, 0xc4, 0x5c, 0x5f, 0xf8, 0x7c, 0x76, 0x35, 0xdd, 0x46, 0xd1, 0x50, 0x88, 0x2f, 0x4d, 0xe1, 0xe9, 0xae, 0x65, 0xe7, 0xf7, 0xd9, 0x01, 0x8f, 0x68, 0x36, 0x95, 0x4a, 0x47, 0xc0, 0xa8, 0x1a, 0x8a, 0x6b, 0x6f, 0x83, 0xf2, 0x94, 0x4d, 0x60, 0x81, 0xb1, 0xaa, 0x7c, 0x75, 0x9b, 0x25, 0x4b, 0x2c, 0x34, 0xb6, 0x91, 0xda, 0x67, 0xcc, 0x02, 0x26, 0xe2, 0x0b, 0x2f, 0x18, 0xb4, 0x22, 0x12, 0x76, 0x1d, 0xcd, 0x4b, 0x90, 0x8a, 0x62, 0xb3, 0x71, 0xb5, 0x91, 0x8c, 0x57, 0x42, 0xaf, 0x4b, 0x53, 0x7e, 0x29, 0x69, 0x17, 0x67, 0x4f, 0xb9, 0x14, 0x19, 0x47, 0x61, 0x62, 0x1c, 0xc1, 0x9a, 0x41, 0xf6, 0xfb, 0x95, 0x3f, 0xbc, 0xbb, 0x64, 0x9d, 0xea } + +} +, +{ + "RSASSA-PSS Signature Example 2.3", + /* Message to be signed */ + 102, + { 0x52, 0xa1, 0xd9, 0x6c, 0x8a, 0xc3, 0x9e, 0x41, 0xe4, 0x55, 0x80, 0x98, 0x01, 0xb9, 0x27, 0xa5, 0xb4, 0x45, 0xc1, 0x0d, 0x90, 0x2a, 0x0d, 0xcd, 0x38, 0x50, 0xd2, 0x2a, 0x66, 0xd2, 0xbb, 0x07, 0x03, 0xe6, 0x7d, 0x58, 0x67, 0x11, 0x45, 0x95, 0xaa, 0xbf, 0x5a, 0x7a, 0xeb, 0x5a, 0x8f, 0x87, 0x03, 0x4b, 0xbb, 0x30, 0xe1, 0x3c, 0xfd, 0x48, 0x17, 0xa9, 0xbe, 0x76, 0x23, 0x00, 0x23, 0x60, 0x6d, 0x02, 0x86, 0xa3, 0xfa, 0xf8, 0xa4, 0xd2, 0x2b, 0x72, 0x8e, 0xc5, 0x18, 0x07, 0x9f, 0x9e, 0x64, 0x52, 0x6e, 0x3a, 0x0c, 0xc7, 0x94, 0x1a, 0xa3, 0x38, 0xc4, 0x37, 0x99, 0x7c, 0x68, 0x0c, 0xca, 0xc6, 0x7c, 0x66, 0xbf, 0xa1 } +, + /* Salt */ + 20, + { 0xfc, 0xa8, 0x62, 0x06, 0x8b, 0xce, 0x22, 0x46, 0x72, 0x4b, 0x70, 0x8a, 0x05, 0x19, 0xda, 0x17, 0xe6, 0x48, 0x68, 0x8c } +, + /* Signature */ + 129, + { 0x00, 0x7f, 0x00, 0x30, 0x01, 0x8f, 0x53, 0xcd, 0xc7, 0x1f, 0x23, 0xd0, 0x36, 0x59, 0xfd, 0xe5, 0x4d, 0x42, 0x41, 0xf7, 0x58, 0xa7, 0x50, 0xb4, 0x2f, 0x18, 0x5f, 0x87, 0x57, 0x85, 0x20, 0xc3, 0x07, 0x42, 0xaf, 0xd8, 0x43, 0x59, 0xb6, 0xe6, 0xe8, 0xd3, 0xed, 0x95, 0x9d, 0xc6, 0xfe, 0x48, 0x6b, 0xed, 0xc8, 0xe2, 0xcf, 0x00, 0x1f, 0x63, 0xa7, 0xab, 0xe1, 0x62, 0x56, 0xa1, 0xb8, 0x4d, 0xf0, 0xd2, 0x49, 0xfc, 0x05, 0xd3, 0x19, 0x4c, 0xe5, 0xf0, 0x91, 0x27, 0x42, 0xdb, 0xbf, 0x80, 0xdd, 0x17, 0x4f, 0x6c, 0x51, 0xf6, 0xba, 0xd7, 0xf1, 0x6c, 0xf3, 0x36, 0x4e, 0xba, 0x09, 0x5a, 0x06, 0x26, 0x7d, 0xc3, 0x79, 0x38, 0x03, 0xac, 0x75, 0x26, 0xae, 0xbe, 0x0a, 0x47, 0x5d, 0x38, 0xb8, 0xc2, 0x24, 0x7a, 0xb5, 0x1c, 0x48, 0x98, 0xdf, 0x70, 0x47, 0xdc, 0x6a, 0xdf, 0x52, 0xc6, 0xc4 } + +} +, +{ + "RSASSA-PSS Signature Example 2.4", + /* Message to be signed */ + 30, + { 0xa7, 0x18, 0x2c, 0x83, 0xac, 0x18, 0xbe, 0x65, 0x70, 0xa1, 0x06, 0xaa, 0x9d, 0x5c, 0x4e, 0x3d, 0xbb, 0xd4, 0xaf, 0xae, 0xb0, 0xc6, 0x0c, 0x4a, 0x23, 0xe1, 0x96, 0x9d, 0x79, 0xff } +, + /* Salt */ + 20, + { 0x80, 0x70, 0xef, 0x2d, 0xe9, 0x45, 0xc0, 0x23, 0x87, 0x68, 0x4b, 0xa0, 0xd3, 0x30, 0x96, 0x73, 0x22, 0x35, 0xd4, 0x40 } +, + /* Signature */ + 129, + { 0x00, 0x9c, 0xd2, 0xf4, 0xed, 0xbe, 0x23, 0xe1, 0x23, 0x46, 0xae, 0x8c, 0x76, 0xdd, 0x9a, 0xd3, 0x23, 0x0a, 0x62, 0x07, 0x61, 0x41, 0xf1, 0x6c, 0x15, 0x2b, 0xa1, 0x85, 0x13, 0xa4, 0x8e, 0xf6, 0xf0, 0x10, 0xe0, 0xe3, 0x7f, 0xd3, 0xdf, 0x10, 0xa1, 0xec, 0x62, 0x9a, 0x0c, 0xb5, 0xa3, 0xb5, 0xd2, 0x89, 0x30, 0x07, 0x29, 0x8c, 0x30, 0x93, 0x6a, 0x95, 0x90, 0x3b, 0x6b, 0xa8, 0x55, 0x55, 0xd9, 0xec, 0x36, 0x73, 0xa0, 0x61, 0x08, 0xfd, 0x62, 0xa2, 0xfd, 0xa5, 0x6d, 0x1c, 0xe2, 0xe8, 0x5c, 0x4d, 0xb6, 0xb2, 0x4a, 0x81, 0xca, 0x3b, 0x49, 0x6c, 0x36, 0xd4, 0xfd, 0x06, 0xeb, 0x7c, 0x91, 0x66, 0xd8, 0xe9, 0x48, 0x77, 0xc4, 0x2b, 0xea, 0x62, 0x2b, 0x3b, 0xfe, 0x92, 0x51, 0xfd, 0xc2, 0x1d, 0x8d, 0x53, 0x71, 0xba, 0xda, 0xd7, 0x8a, 0x48, 0x82, 0x14, 0x79, 0x63, 0x35, 0xb4, 0x0b } + +} +, +{ + "RSASSA-PSS Signature Example 2.5", + /* Message to be signed */ + 56, + { 0x86, 0xa8, 0x3d, 0x4a, 0x72, 0xee, 0x93, 0x2a, 0x4f, 0x56, 0x30, 0xaf, 0x65, 0x79, 0xa3, 0x86, 0xb7, 0x8f, 0xe8, 0x89, 0x99, 0xe0, 0xab, 0xd2, 0xd4, 0x90, 0x34, 0xa4, 0xbf, 0xc8, 0x54, 0xdd, 0x94, 0xf1, 0x09, 0x4e, 0x2e, 0x8c, 0xd7, 0xa1, 0x79, 0xd1, 0x95, 0x88, 0xe4, 0xae, 0xfc, 0x1b, 0x1b, 0xd2, 0x5e, 0x95, 0xe3, 0xdd, 0x46, 0x1f } +, + /* Salt */ + 20, + { 0x17, 0x63, 0x9a, 0x4e, 0x88, 0xd7, 0x22, 0xc4, 0xfc, 0xa2, 0x4d, 0x07, 0x9a, 0x8b, 0x29, 0xc3, 0x24, 0x33, 0xb0, 0xc9 } +, + /* Signature */ + 129, + { 0x00, 0xec, 0x43, 0x08, 0x24, 0x93, 0x1e, 0xbd, 0x3b, 0xaa, 0x43, 0x03, 0x4d, 0xae, 0x98, 0xba, 0x64, 0x6b, 0x8c, 0x36, 0x01, 0x3d, 0x16, 0x71, 0xc3, 0xcf, 0x1c, 0xf8, 0x26, 0x0c, 0x37, 0x4b, 0x19, 0xf8, 0xe1, 0xcc, 0x8d, 0x96, 0x50, 0x12, 0x40, 0x5e, 0x7e, 0x9b, 0xf7, 0x37, 0x86, 0x12, 0xdf, 0xcc, 0x85, 0xfc, 0xe1, 0x2c, 0xda, 0x11, 0xf9, 0x50, 0xbd, 0x0b, 0xa8, 0x87, 0x67, 0x40, 0x43, 0x6c, 0x1d, 0x25, 0x95, 0xa6, 0x4a, 0x1b, 0x32, 0xef, 0xcf, 0xb7, 0x4a, 0x21, 0xc8, 0x73, 0xb3, 0xcc, 0x33, 0xaa, 0xf4, 0xe3, 0xdc, 0x39, 0x53, 0xde, 0x67, 0xf0, 0x67, 0x4c, 0x04, 0x53, 0xb4, 0xfd, 0x9f, 0x60, 0x44, 0x06, 0xd4, 0x41, 0xb8, 0x16, 0x09, 0x8c, 0xb1, 0x06, 0xfe, 0x34, 0x72, 0xbc, 0x25, 0x1f, 0x81, 0x5f, 0x59, 0xdb, 0x2e, 0x43, 0x78, 0xa3, 0xad, 0xdc, 0x18, 0x1e, 0xcf } + +} +, +{ + "RSASSA-PSS Signature Example 2.6", + /* Message to be signed */ + 26, + { 0x04, 0x9f, 0x91, 0x54, 0xd8, 0x71, 0xac, 0x4a, 0x7c, 0x7a, 0xb4, 0x53, 0x25, 0xba, 0x75, 0x45, 0xa1, 0xed, 0x08, 0xf7, 0x05, 0x25, 0xb2, 0x66, 0x7c, 0xf1 } +, + /* Salt */ + 20, + { 0x37, 0x81, 0x0d, 0xef, 0x10, 0x55, 0xed, 0x92, 0x2b, 0x06, 0x3d, 0xf7, 0x98, 0xde, 0x5d, 0x0a, 0xab, 0xf8, 0x86, 0xee } +, + /* Signature */ + 129, + { 0x00, 0x47, 0x5b, 0x16, 0x48, 0xf8, 0x14, 0xa8, 0xdc, 0x0a, 0xbd, 0xc3, 0x7b, 0x55, 0x27, 0xf5, 0x43, 0xb6, 0x66, 0xbb, 0x6e, 0x39, 0xd3, 0x0e, 0x5b, 0x49, 0xd3, 0xb8, 0x76, 0xdc, 0xcc, 0x58, 0xea, 0xc1, 0x4e, 0x32, 0xa2, 0xd5, 0x5c, 0x26, 0x16, 0x01, 0x44, 0x56, 0xad, 0x2f, 0x24, 0x6f, 0xc8, 0xe3, 0xd5, 0x60, 0xda, 0x3d, 0xdf, 0x37, 0x9a, 0x1c, 0x0b, 0xd2, 0x00, 0xf1, 0x02, 0x21, 0xdf, 0x07, 0x8c, 0x21, 0x9a, 0x15, 0x1b, 0xc8, 0xd4, 0xec, 0x9d, 0x2f, 0xc2, 0x56, 0x44, 0x67, 0x81, 0x10, 0x14, 0xef, 0x15, 0xd8, 0xea, 0x01, 0xc2, 0xeb, 0xbf, 0xf8, 0xc2, 0xc8, 0xef, 0xab, 0x38, 0x09, 0x6e, 0x55, 0xfc, 0xbe, 0x32, 0x85, 0xc7, 0xaa, 0x55, 0x88, 0x51, 0x25, 0x4f, 0xaf, 0xfa, 0x92, 0xc1, 0xc7, 0x2b, 0x78, 0x75, 0x86, 0x63, 0xef, 0x45, 0x82, 0x84, 0x31, 0x39, 0xd7, 0xa6 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 3: A 1026-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x02, 0xf2, 0x46, 0xef, 0x45, 0x1e, 0xd3, 0xee, 0xbb, 0x9a, 0x31, 0x02, 0x00, 0xcc, 0x25, 0x85, 0x9c, 0x04, 0x8e, 0x4b, 0xe7, 0x98, 0x30, 0x29, 0x91, 0x11, 0x2e, 0xb6, 0x8c, 0xe6, 0xdb, 0x67, 0x4e, 0x28, 0x0d, 0xa2, 0x1f, 0xed, 0xed, 0x1a, 0xe7, 0x48, 0x80, 0xca, 0x52, 0x2b, 0x18, 0xdb, 0x24, 0x93, 0x85, 0x01, 0x28, 0x27, 0xc5, 0x15, 0xf0, 0xe4, 0x66, 0xa1, 0xff, 0xa6, 0x91, 0xd9, 0x81, 0x70, 0x57, 0x4e, 0x9d, 0x0e, 0xad, 0xb0, 0x87, 0x58, 0x6c, 0xa4, 0x89, 0x33, 0xda, 0x3c, 0xc9, 0x53, 0xd9, 0x5b, 0xd0, 0xed, 0x50, 0xde, 0x10, 0xdd, 0xcb, 0x67, 0x36, 0x10, 0x7d, 0x6c, 0x83, 0x1c, 0x7f, 0x66, 0x3e, 0x83, 0x3c, 0xa4, 0xc0, 0x97, 0xe7, 0x00, 0xce, 0x0f, 0xb9, 0x45, 0xf8, 0x8f, 0xb8, 0x5f, 0xe8, 0xe5, 0xa7, 0x73, 0x17, 0x25, 0x65, 0xb9, 0x14, 0xa4, 0x71, 0xa4, 0x43 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x65, 0x14, 0x51, 0x73, 0x3b, 0x56, 0xde, 0x5a, 0xc0, 0xa6, 0x89, 0xa4, 0xae, 0xb6, 0xe6, 0x89, 0x4a, 0x69, 0x01, 0x4e, 0x07, 0x6c, 0x88, 0xdd, 0x7a, 0x66, 0x7e, 0xab, 0x32, 0x32, 0xbb, 0xcc, 0xd2, 0xfc, 0x44, 0xba, 0x2f, 0xa9, 0xc3, 0x1d, 0xb4, 0x6f, 0x21, 0xed, 0xd1, 0xfd, 0xb2, 0x3c, 0x5c, 0x12, 0x8a, 0x5d, 0xa5, 0xba, 0xb9, 0x1e, 0x7f, 0x95, 0x2b, 0x67, 0x75, 0x9c, 0x7c, 0xff, 0x70, 0x54, 0x15, 0xac, 0x9f, 0xa0, 0x90, 0x7c, 0x7c, 0xa6, 0x17, 0x8f, 0x66, 0x8f, 0xb9, 0x48, 0xd8, 0x69, 0xda, 0x4c, 0xc3, 0xb7, 0x35, 0x6f, 0x40, 0x08, 0xdf, 0xd5, 0x44, 0x9d, 0x32, 0xee, 0x02, 0xd9, 0xa4, 0x77, 0xeb, 0x69, 0xfc, 0x29, 0x26, 0x6e, 0x5d, 0x90, 0x70, 0x51, 0x23, 0x75, 0xa5, 0x0f, 0xbb, 0xcc, 0x27, 0xe2, 0x38, 0xad, 0x98, 0x42, 0x5f, 0x6e, 0xbb, 0xf8, 0x89, 0x91 } +, + /* Prime p */ + 65, + { 0x01, 0xbd, 0x36, 0xe1, 0x8e, 0xce, 0x4b, 0x0f, 0xdb, 0x2e, 0x9c, 0x9d, 0x54, 0x8b, 0xd1, 0xa7, 0xd6, 0xe2, 0xc2, 0x1c, 0x6f, 0xdc, 0x35, 0x07, 0x4a, 0x1d, 0x05, 0xb1, 0xc6, 0xc8, 0xb3, 0xd5, 0x58, 0xea, 0x26, 0x39, 0xc9, 0xa9, 0xa4, 0x21, 0x68, 0x01, 0x69, 0x31, 0x72, 0x52, 0x55, 0x8b, 0xd1, 0x48, 0xad, 0x21, 0x5a, 0xac, 0x55, 0x0e, 0x2d, 0xcf, 0x12, 0xa8, 0x2d, 0x0e, 0xbf, 0xe8, 0x53 } +, + /* Prime q */ + 65, + { 0x01, 0xb1, 0xb6, 0x56, 0xad, 0x86, 0xd8, 0xe1, 0x9d, 0x5d, 0xc8, 0x62, 0x92, 0xb3, 0xa1, 0x92, 0xfd, 0xf6, 0xe0, 0xdd, 0x37, 0x87, 0x7b, 0xad, 0x14, 0x82, 0x2f, 0xa0, 0x01, 0x90, 0xca, 0xb2, 0x65, 0xf9, 0x0d, 0x3f, 0x02, 0x05, 0x7b, 0x6f, 0x54, 0xd6, 0xec, 0xb1, 0x44, 0x91, 0xe5, 0xad, 0xea, 0xce, 0xbc, 0x48, 0xbf, 0x0e, 0xbd, 0x2a, 0x2a, 0xd2, 0x6d, 0x40, 0x2e, 0x54, 0xf6, 0x16, 0x51 } +, + /* p's CRT exponent dP */ + 64, + { 0x1f, 0x27, 0x79, 0xfd, 0x2e, 0x3e, 0x5e, 0x6b, 0xae, 0x05, 0x53, 0x95, 0x18, 0xfb, 0xa0, 0xcd, 0x0e, 0xad, 0x1a, 0xa4, 0x51, 0x3a, 0x7c, 0xba, 0x18, 0xf1, 0xcf, 0x10, 0xe3, 0xf6, 0x81, 0x95, 0x69, 0x3d, 0x27, 0x8a, 0x0f, 0x0e, 0xe7, 0x2f, 0x89, 0xf9, 0xbc, 0x76, 0x0d, 0x80, 0xe2, 0xf9, 0xd0, 0x26, 0x1d, 0x51, 0x65, 0x01, 0xc6, 0xae, 0x39, 0xf1, 0x4a, 0x47, 0x6c, 0xe2, 0xcc, 0xf5 } +, + /* q's CRT exponent dQ */ + 65, + { 0x01, 0x1a, 0x0d, 0x36, 0x79, 0x4b, 0x04, 0xa8, 0x54, 0xaa, 0xb4, 0xb2, 0x46, 0x2d, 0x43, 0x9a, 0x50, 0x46, 0xc9, 0x1d, 0x94, 0x0b, 0x2b, 0xc6, 0xf7, 0x5b, 0x62, 0x95, 0x6f, 0xef, 0x35, 0xa2, 0xa6, 0xe6, 0x3c, 0x53, 0x09, 0x81, 0x7f, 0x30, 0x7b, 0xbf, 0xf9, 0xd5, 0x9e, 0x7e, 0x33, 0x1b, 0xd3, 0x63, 0xf6, 0xd6, 0x68, 0x49, 0xb1, 0x83, 0x46, 0xad, 0xea, 0x16, 0x9f, 0x0a, 0xe9, 0xae, 0xc1 } +, + /* CRT coefficient qInv */ + 64, + { 0x0b, 0x30, 0xf0, 0xec, 0xf5, 0x58, 0x75, 0x2f, 0xb3, 0xa6, 0xce, 0x4b, 0xa2, 0xb8, 0xc6, 0x75, 0xf6, 0x59, 0xeb, 0xa6, 0xc3, 0x76, 0x58, 0x5a, 0x1b, 0x39, 0x71, 0x2d, 0x03, 0x8a, 0xe3, 0xd2, 0xb4, 0x6f, 0xcb, 0x41, 0x8a, 0xe1, 0x5d, 0x09, 0x05, 0xda, 0x64, 0x40, 0xe1, 0x51, 0x3a, 0x30, 0xb9, 0xb7, 0xd6, 0x66, 0x8f, 0xbc, 0x5e, 0x88, 0xe5, 0xab, 0x7a, 0x17, 0x5e, 0x73, 0xba, 0x35 } + +} +, +{{ + "RSASSA-PSS Signature Example 3.1", + /* Message to be signed */ + 30, + { 0x59, 0x4b, 0x37, 0x33, 0x3b, 0xbb, 0x2c, 0x84, 0x52, 0x4a, 0x87, 0xc1, 0xa0, 0x1f, 0x75, 0xfc, 0xec, 0x0e, 0x32, 0x56, 0xf1, 0x08, 0xe3, 0x8d, 0xca, 0x36, 0xd7, 0x0d, 0x00, 0x57 } +, + /* Salt */ + 20, + { 0xf3, 0x1a, 0xd6, 0xc8, 0xcf, 0x89, 0xdf, 0x78, 0xed, 0x77, 0xfe, 0xac, 0xbc, 0xc2, 0xf8, 0xb0, 0xa8, 0xe4, 0xcf, 0xaa } +, + /* Signature */ + 129, + { 0x00, 0x88, 0xb1, 0x35, 0xfb, 0x17, 0x94, 0xb6, 0xb9, 0x6c, 0x4a, 0x3e, 0x67, 0x81, 0x97, 0xf8, 0xca, 0xc5, 0x2b, 0x64, 0xb2, 0xfe, 0x90, 0x7d, 0x6f, 0x27, 0xde, 0x76, 0x11, 0x24, 0x96, 0x4a, 0x99, 0xa0, 0x1a, 0x88, 0x27, 0x40, 0xec, 0xfa, 0xed, 0x6c, 0x01, 0xa4, 0x74, 0x64, 0xbb, 0x05, 0x18, 0x23, 0x13, 0xc0, 0x13, 0x38, 0xa8, 0xcd, 0x09, 0x72, 0x14, 0xcd, 0x68, 0xca, 0x10, 0x3b, 0xd5, 0x7d, 0x3b, 0xc9, 0xe8, 0x16, 0x21, 0x3e, 0x61, 0xd7, 0x84, 0xf1, 0x82, 0x46, 0x7a, 0xbf, 0x8a, 0x01, 0xcf, 0x25, 0x3e, 0x99, 0xa1, 0x56, 0xea, 0xa8, 0xe3, 0xe1, 0xf9, 0x0e, 0x3c, 0x6e, 0x4e, 0x3a, 0xa2, 0xd8, 0x3e, 0xd0, 0x34, 0x5b, 0x89, 0xfa, 0xfc, 0x9c, 0x26, 0x07, 0x7c, 0x14, 0xb6, 0xac, 0x51, 0x45, 0x4f, 0xa2, 0x6e, 0x44, 0x6e, 0x3a, 0x2f, 0x15, 0x3b, 0x2b, 0x16, 0x79, 0x7f } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 3.2", + /* Message to be signed */ + 29, + { 0x8b, 0x76, 0x95, 0x28, 0x88, 0x4a, 0x0d, 0x1f, 0xfd, 0x09, 0x0c, 0xf1, 0x02, 0x99, 0x3e, 0x79, 0x6d, 0xad, 0xcf, 0xbd, 0xdd, 0x38, 0xe4, 0x4f, 0xf6, 0x32, 0x4c, 0xa4, 0x51 } +, + /* Salt */ + 20, + { 0xfc, 0xf9, 0xf0, 0xe1, 0xf1, 0x99, 0xa3, 0xd1, 0xd0, 0xda, 0x68, 0x1c, 0x5b, 0x86, 0x06, 0xfc, 0x64, 0x29, 0x39, 0xf7 } +, + /* Signature */ + 129, + { 0x02, 0xa5, 0xf0, 0xa8, 0x58, 0xa0, 0x86, 0x4a, 0x4f, 0x65, 0x01, 0x7a, 0x7d, 0x69, 0x45, 0x4f, 0x3f, 0x97, 0x3a, 0x29, 0x99, 0x83, 0x9b, 0x7b, 0xbc, 0x48, 0xbf, 0x78, 0x64, 0x11, 0x69, 0x17, 0x95, 0x56, 0xf5, 0x95, 0xfa, 0x41, 0xf6, 0xff, 0x18, 0xe2, 0x86, 0xc2, 0x78, 0x30, 0x79, 0xbc, 0x09, 0x10, 0xee, 0x9c, 0xc3, 0x4f, 0x49, 0xba, 0x68, 0x11, 0x24, 0xf9, 0x23, 0xdf, 0xa8, 0x8f, 0x42, 0x61, 0x41, 0xa3, 0x68, 0xa5, 0xf5, 0xa9, 0x30, 0xc6, 0x28, 0xc2, 0xc3, 0xc2, 0x00, 0xe1, 0x8a, 0x76, 0x44, 0x72, 0x1a, 0x0c, 0xbe, 0xc6, 0xdd, 0x3f, 0x62, 0x79, 0xbd, 0xe3, 0xe8, 0xf2, 0xbe, 0x5e, 0x2d, 0x4e, 0xe5, 0x6f, 0x97, 0xe7, 0xce, 0xaf, 0x33, 0x05, 0x4b, 0xe7, 0x04, 0x2b, 0xd9, 0x1a, 0x63, 0xbb, 0x09, 0xf8, 0x97, 0xbd, 0x41, 0xe8, 0x11, 0x97, 0xde, 0xe9, 0x9b, 0x11, 0xaf } + +} +, +{ + "RSASSA-PSS Signature Example 3.3", + /* Message to be signed */ + 167, + { 0x1a, 0xbd, 0xba, 0x48, 0x9c, 0x5a, 0xda, 0x2f, 0x99, 0x5e, 0xd1, 0x6f, 0x19, 0xd5, 0xa9, 0x4d, 0x9e, 0x6e, 0xc3, 0x4a, 0x8d, 0x84, 0xf8, 0x45, 0x57, 0xd2, 0x6e, 0x5e, 0xf9, 0xb0, 0x2b, 0x22, 0x88, 0x7e, 0x3f, 0x9a, 0x4b, 0x69, 0x0a, 0xd1, 0x14, 0x92, 0x09, 0xc2, 0x0c, 0x61, 0x43, 0x1f, 0x0c, 0x01, 0x7c, 0x36, 0xc2, 0x65, 0x7b, 0x35, 0xd7, 0xb0, 0x7d, 0x3f, 0x5a, 0xd8, 0x70, 0x85, 0x07, 0xa9, 0xc1, 0xb8, 0x31, 0xdf, 0x83, 0x5a, 0x56, 0xf8, 0x31, 0x07, 0x18, 0x14, 0xea, 0x5d, 0x3d, 0x8d, 0x8f, 0x6a, 0xde, 0x40, 0xcb, 0xa3, 0x8b, 0x42, 0xdb, 0x7a, 0x2d, 0x3d, 0x7a, 0x29, 0xc8, 0xf0, 0xa7, 0x9a, 0x78, 0x38, 0xcf, 0x58, 0xa9, 0x75, 0x7f, 0xa2, 0xfe, 0x4c, 0x40, 0xdf, 0x9b, 0xaa, 0x19, 0x3b, 0xfc, 0x6f, 0x92, 0xb1, 0x23, 0xad, 0x57, 0xb0, 0x7a, 0xce, 0x3e, 0x6a, 0xc0, 0x68, 0xc9, 0xf1, 0x06, 0xaf, 0xd9, 0xee, 0xb0, 0x3b, 0x4f, 0x37, 0xc2, 0x5d, 0xbf, 0xbc, 0xfb, 0x30, 0x71, 0xf6, 0xf9, 0x77, 0x17, 0x66, 0xd0, 0x72, 0xf3, 0xbb, 0x07, 0x0a, 0xf6, 0x60, 0x55, 0x32, 0x97, 0x3a, 0xe2, 0x50, 0x51 } +, + /* Salt */ + 20, + { 0x98, 0x6e, 0x7c, 0x43, 0xdb, 0xb6, 0x71, 0xbd, 0x41, 0xb9, 0xa7, 0xf4, 0xb6, 0xaf, 0xc8, 0x0e, 0x80, 0x5f, 0x24, 0x23 } +, + /* Signature */ + 129, + { 0x02, 0x44, 0xbc, 0xd1, 0xc8, 0xc1, 0x69, 0x55, 0x73, 0x6c, 0x80, 0x3b, 0xe4, 0x01, 0x27, 0x2e, 0x18, 0xcb, 0x99, 0x08, 0x11, 0xb1, 0x4f, 0x72, 0xdb, 0x96, 0x41, 0x24, 0xd5, 0xfa, 0x76, 0x06, 0x49, 0xcb, 0xb5, 0x7a, 0xfb, 0x87, 0x55, 0xdb, 0xb6, 0x2b, 0xf5, 0x1f, 0x46, 0x6c, 0xf2, 0x3a, 0x0a, 0x16, 0x07, 0x57, 0x6e, 0x98, 0x3d, 0x77, 0x8f, 0xce, 0xff, 0xa9, 0x2d, 0xf7, 0x54, 0x8a, 0xea, 0x8e, 0xa4, 0xec, 0xad, 0x2c, 0x29, 0xdd, 0x9f, 0x95, 0xbc, 0x07, 0xfe, 0x91, 0xec, 0xf8, 0xbe, 0xe2, 0x55, 0xbf, 0xe8, 0x76, 0x2f, 0xd7, 0x69, 0x0a, 0xa9, 0xbf, 0xa4, 0xfa, 0x08, 0x49, 0xef, 0x72, 0x8c, 0x2c, 0x42, 0xc4, 0x53, 0x23, 0x64, 0x52, 0x2d, 0xf2, 0xab, 0x7f, 0x9f, 0x8a, 0x03, 0xb6, 0x3f, 0x7a, 0x49, 0x91, 0x75, 0x82, 0x86, 0x68, 0xf5, 0xef, 0x5a, 0x29, 0xe3, 0x80, 0x2c } + +} +, +{ + "RSASSA-PSS Signature Example 3.4", + /* Message to be signed */ + 73, + { 0x8f, 0xb4, 0x31, 0xf5, 0xee, 0x79, 0x2b, 0x6c, 0x2a, 0xc7, 0xdb, 0x53, 0xcc, 0x42, 0x86, 0x55, 0xae, 0xb3, 0x2d, 0x03, 0xf4, 0xe8, 0x89, 0xc5, 0xc2, 0x5d, 0xe6, 0x83, 0xc4, 0x61, 0xb5, 0x3a, 0xcf, 0x89, 0xf9, 0xf8, 0xd3, 0xaa, 0xbd, 0xf6, 0xb9, 0xf0, 0xc2, 0xa1, 0xde, 0x12, 0xe1, 0x5b, 0x49, 0xed, 0xb3, 0x91, 0x9a, 0x65, 0x2f, 0xe9, 0x49, 0x1c, 0x25, 0xa7, 0xfc, 0xe1, 0xf7, 0x22, 0xc2, 0x54, 0x36, 0x08, 0xb6, 0x9d, 0xc3, 0x75, 0xec } +, + /* Salt */ + 20, + { 0xf8, 0x31, 0x2d, 0x9c, 0x8e, 0xea, 0x13, 0xec, 0x0a, 0x4c, 0x7b, 0x98, 0x12, 0x0c, 0x87, 0x50, 0x90, 0x87, 0xc4, 0x78 } +, + /* Signature */ + 129, + { 0x01, 0x96, 0xf1, 0x2a, 0x00, 0x5b, 0x98, 0x12, 0x9c, 0x8d, 0xf1, 0x3c, 0x4c, 0xb1, 0x6f, 0x8a, 0xa8, 0x87, 0xd3, 0xc4, 0x0d, 0x96, 0xdf, 0x3a, 0x88, 0xe7, 0x53, 0x2e, 0xf3, 0x9c, 0xd9, 0x92, 0xf2, 0x73, 0xab, 0xc3, 0x70, 0xbc, 0x1b, 0xe6, 0xf0, 0x97, 0xcf, 0xeb, 0xbf, 0x01, 0x18, 0xfd, 0x9e, 0xf4, 0xb9, 0x27, 0x15, 0x5f, 0x3d, 0xf2, 0x2b, 0x90, 0x4d, 0x90, 0x70, 0x2d, 0x1f, 0x7b, 0xa7, 0xa5, 0x2b, 0xed, 0x8b, 0x89, 0x42, 0xf4, 0x12, 0xcd, 0x7b, 0xd6, 0x76, 0xc9, 0xd1, 0x8e, 0x17, 0x03, 0x91, 0xdc, 0xd3, 0x45, 0xc0, 0x6a, 0x73, 0x09, 0x64, 0xb3, 0xf3, 0x0b, 0xcc, 0xe0, 0xbb, 0x20, 0xba, 0x10, 0x6f, 0x9a, 0xb0, 0xee, 0xb3, 0x9c, 0xf8, 0xa6, 0x60, 0x7f, 0x75, 0xc0, 0x34, 0x7f, 0x0a, 0xf7, 0x9f, 0x16, 0xaf, 0xa0, 0x81, 0xd2, 0xc9, 0x2d, 0x1e, 0xe6, 0xf8, 0x36, 0xb8 } + +} +, +{ + "RSASSA-PSS Signature Example 3.5", + /* Message to be signed */ + 115, + { 0xfe, 0xf4, 0x16, 0x1d, 0xfa, 0xaf, 0x9c, 0x52, 0x95, 0x05, 0x1d, 0xfc, 0x1f, 0xf3, 0x81, 0x0c, 0x8c, 0x9e, 0xc2, 0xe8, 0x66, 0xf7, 0x07, 0x54, 0x22, 0xc8, 0xec, 0x42, 0x16, 0xa9, 0xc4, 0xff, 0x49, 0x42, 0x7d, 0x48, 0x3c, 0xae, 0x10, 0xc8, 0x53, 0x4a, 0x41, 0xb2, 0xfd, 0x15, 0xfe, 0xe0, 0x69, 0x60, 0xec, 0x6f, 0xb3, 0xf7, 0xa7, 0xe9, 0x4a, 0x2f, 0x8a, 0x2e, 0x3e, 0x43, 0xdc, 0x4a, 0x40, 0x57, 0x6c, 0x30, 0x97, 0xac, 0x95, 0x3b, 0x1d, 0xe8, 0x6f, 0x0b, 0x4e, 0xd3, 0x6d, 0x64, 0x4f, 0x23, 0xae, 0x14, 0x42, 0x55, 0x29, 0x62, 0x24, 0x64, 0xca, 0x0c, 0xbf, 0x0b, 0x17, 0x41, 0x34, 0x72, 0x38, 0x15, 0x7f, 0xab, 0x59, 0xe4, 0xde, 0x55, 0x24, 0x09, 0x6d, 0x62, 0xba, 0xec, 0x63, 0xac, 0x64 } +, + /* Salt */ + 20, + { 0x50, 0x32, 0x7e, 0xfe, 0xc6, 0x29, 0x2f, 0x98, 0x01, 0x9f, 0xc6, 0x7a, 0x2a, 0x66, 0x38, 0x56, 0x3e, 0x9b, 0x6e, 0x2d } +, + /* Signature */ + 129, + { 0x02, 0x1e, 0xca, 0x3a, 0xb4, 0x89, 0x22, 0x64, 0xec, 0x22, 0x41, 0x1a, 0x75, 0x2d, 0x92, 0x22, 0x10, 0x76, 0xd4, 0xe0, 0x1c, 0x0e, 0x6f, 0x0d, 0xde, 0x9a, 0xfd, 0x26, 0xba, 0x5a, 0xcf, 0x6d, 0x73, 0x9e, 0xf9, 0x87, 0x54, 0x5d, 0x16, 0x68, 0x3e, 0x56, 0x74, 0xc9, 0xe7, 0x0f, 0x1d, 0xe6, 0x49, 0xd7, 0xe6, 0x1d, 0x48, 0xd0, 0xca, 0xeb, 0x4f, 0xb4, 0xd8, 0xb2, 0x4f, 0xba, 0x84, 0xa6, 0xe3, 0x10, 0x8f, 0xee, 0x7d, 0x07, 0x05, 0x97, 0x32, 0x66, 0xac, 0x52, 0x4b, 0x4a, 0xd2, 0x80, 0xf7, 0xae, 0x17, 0xdc, 0x59, 0xd9, 0x6d, 0x33, 0x51, 0x58, 0x6b, 0x5a, 0x3b, 0xdb, 0x89, 0x5d, 0x1e, 0x1f, 0x78, 0x20, 0xac, 0x61, 0x35, 0xd8, 0x75, 0x34, 0x80, 0x99, 0x83, 0x82, 0xba, 0x32, 0xb7, 0x34, 0x95, 0x59, 0x60, 0x8c, 0x38, 0x74, 0x52, 0x90, 0xa8, 0x5e, 0xf4, 0xe9, 0xf9, 0xbd, 0x83 } + +} +, +{ + "RSASSA-PSS Signature Example 3.6", + /* Message to be signed */ + 22, + { 0xef, 0xd2, 0x37, 0xbb, 0x09, 0x8a, 0x44, 0x3a, 0xee, 0xb2, 0xbf, 0x6c, 0x3f, 0x8c, 0x81, 0xb8, 0xc0, 0x1b, 0x7f, 0xcb, 0x3f, 0xeb } +, + /* Salt */ + 20, + { 0xb0, 0xde, 0x3f, 0xc2, 0x5b, 0x65, 0xf5, 0xaf, 0x96, 0xb1, 0xd5, 0xcc, 0x3b, 0x27, 0xd0, 0xc6, 0x05, 0x30, 0x87, 0xb3 } +, + /* Signature */ + 129, + { 0x01, 0x2f, 0xaf, 0xec, 0x86, 0x2f, 0x56, 0xe9, 0xe9, 0x2f, 0x60, 0xab, 0x0c, 0x77, 0x82, 0x4f, 0x42, 0x99, 0xa0, 0xca, 0x73, 0x4e, 0xd2, 0x6e, 0x06, 0x44, 0xd5, 0xd2, 0x22, 0xc7, 0xf0, 0xbd, 0xe0, 0x39, 0x64, 0xf8, 0xe7, 0x0a, 0x5c, 0xb6, 0x5e, 0xd4, 0x4e, 0x44, 0xd5, 0x6a, 0xe0, 0xed, 0xf1, 0xff, 0x86, 0xca, 0x03, 0x2c, 0xc5, 0xdd, 0x44, 0x04, 0xdb, 0xb7, 0x6a, 0xb8, 0x54, 0x58, 0x6c, 0x44, 0xee, 0xd8, 0x33, 0x6d, 0x08, 0xd4, 0x57, 0xce, 0x6c, 0x03, 0x69, 0x3b, 0x45, 0xc0, 0xf1, 0xef, 0xef, 0x93, 0x62, 0x4b, 0x95, 0xb8, 0xec, 0x16, 0x9c, 0x61, 0x6d, 0x20, 0xe5, 0x53, 0x8e, 0xbc, 0x0b, 0x67, 0x37, 0xa6, 0xf8, 0x2b, 0x4b, 0xc0, 0x57, 0x09, 0x24, 0xfc, 0x6b, 0x35, 0x75, 0x9a, 0x33, 0x48, 0x42, 0x62, 0x79, 0xf8, 0xb3, 0xd7, 0x74, 0x4e, 0x2d, 0x22, 0x24, 0x26, 0xce } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 4: A 1027-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x05, 0x4a, 0xdb, 0x78, 0x86, 0x44, 0x7e, 0xfe, 0x6f, 0x57, 0xe0, 0x36, 0x8f, 0x06, 0xcf, 0x52, 0xb0, 0xa3, 0x37, 0x07, 0x60, 0xd1, 0x61, 0xce, 0xf1, 0x26, 0xb9, 0x1b, 0xe7, 0xf8, 0x9c, 0x42, 0x1b, 0x62, 0xa6, 0xec, 0x1d, 0xa3, 0xc3, 0x11, 0xd7, 0x5e, 0xd5, 0x0e, 0x0a, 0xb5, 0xff, 0xf3, 0xfd, 0x33, 0x8a, 0xcc, 0x3a, 0xa8, 0xa4, 0xe7, 0x7e, 0xe2, 0x63, 0x69, 0xac, 0xb8, 0x1b, 0xa9, 0x00, 0xfa, 0x83, 0xf5, 0x30, 0x0c, 0xf9, 0xbb, 0x6c, 0x53, 0xad, 0x1d, 0xc8, 0xa1, 0x78, 0xb8, 0x15, 0xdb, 0x42, 0x35, 0xa9, 0xa9, 0xda, 0x0c, 0x06, 0xde, 0x4e, 0x61, 0x5e, 0xa1, 0x27, 0x7c, 0xe5, 0x59, 0xe9, 0xc1, 0x08, 0xde, 0x58, 0xc1, 0x4a, 0x81, 0xaa, 0x77, 0xf5, 0xa6, 0xf8, 0xd1, 0x33, 0x54, 0x94, 0x49, 0x88, 0x48, 0xc8, 0xb9, 0x59, 0x40, 0x74, 0x0b, 0xe7, 0xbf, 0x7c, 0x37, 0x05 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0xfa, 0x04, 0x1f, 0x8c, 0xd9, 0x69, 0x7c, 0xee, 0xd3, 0x8e, 0xc8, 0xca, 0xa2, 0x75, 0x52, 0x3b, 0x4d, 0xd7, 0x2b, 0x09, 0xa3, 0x01, 0xd3, 0x54, 0x1d, 0x72, 0xf5, 0xd3, 0x1c, 0x05, 0xcb, 0xce, 0x2d, 0x69, 0x83, 0xb3, 0x61, 0x83, 0xaf, 0x10, 0x69, 0x0b, 0xd4, 0x6c, 0x46, 0x13, 0x1e, 0x35, 0x78, 0x94, 0x31, 0xa5, 0x56, 0x77, 0x1d, 0xd0, 0x04, 0x9b, 0x57, 0x46, 0x1b, 0xf0, 0x60, 0xc1, 0xf6, 0x84, 0x72, 0xe8, 0xa6, 0x7c, 0x25, 0xf3, 0x57, 0xe5, 0xb6, 0xb4, 0x73, 0x8f, 0xa5, 0x41, 0xa7, 0x30, 0x34, 0x6b, 0x4a, 0x07, 0x64, 0x9a, 0x2d, 0xfa, 0x80, 0x6a, 0x69, 0xc9, 0x75, 0xb6, 0xab, 0xa6, 0x46, 0x78, 0xac, 0xc7, 0xf5, 0x91, 0x3e, 0x89, 0xc6, 0x22, 0xf2, 0xd8, 0xab, 0xb1, 0xe3, 0xe3, 0x25, 0x54, 0xe3, 0x9d, 0xf9, 0x4b, 0xa6, 0x0c, 0x00, 0x2e, 0x38, 0x7d, 0x90, 0x11 } +, + /* Prime p */ + 65, + { 0x02, 0x92, 0x32, 0x33, 0x6d, 0x28, 0x38, 0x94, 0x5d, 0xba, 0x9d, 0xd7, 0x72, 0x3f, 0x4e, 0x62, 0x4a, 0x05, 0xf7, 0x37, 0x5b, 0x92, 0x7a, 0x87, 0xab, 0xe6, 0xa8, 0x93, 0xa1, 0x65, 0x8f, 0xd4, 0x9f, 0x47, 0xf6, 0xc7, 0xb0, 0xfa, 0x59, 0x6c, 0x65, 0xfa, 0x68, 0xa2, 0x3f, 0x0a, 0xb4, 0x32, 0x96, 0x2d, 0x18, 0xd4, 0x34, 0x3b, 0xd6, 0xfd, 0x67, 0x1a, 0x5e, 0xa8, 0xd1, 0x48, 0x41, 0x39, 0x95 } +, + /* Prime q */ + 65, + { 0x02, 0x0e, 0xf5, 0xef, 0xe7, 0xc5, 0x39, 0x4a, 0xed, 0x22, 0x72, 0xf7, 0xe8, 0x1a, 0x74, 0xf4, 0xc0, 0x2d, 0x14, 0x58, 0x94, 0xcb, 0x1b, 0x3c, 0xab, 0x23, 0xa9, 0xa0, 0x71, 0x0a, 0x2a, 0xfc, 0x7e, 0x33, 0x29, 0xac, 0xbb, 0x74, 0x3d, 0x01, 0xf6, 0x80, 0xc4, 0xd0, 0x2a, 0xfb, 0x4c, 0x8f, 0xde, 0x7e, 0x20, 0x93, 0x08, 0x11, 0xbb, 0x2b, 0x99, 0x57, 0x88, 0xb5, 0xe8, 0x72, 0xc2, 0x0b, 0xb1 } +, + /* p's CRT exponent dP */ + 65, + { 0x02, 0x6e, 0x7e, 0x28, 0x01, 0x0e, 0xcf, 0x24, 0x12, 0xd9, 0x52, 0x3a, 0xd7, 0x04, 0x64, 0x7f, 0xb4, 0xfe, 0x9b, 0x66, 0xb1, 0xa6, 0x81, 0x58, 0x1b, 0x0e, 0x15, 0x55, 0x3a, 0x89, 0xb1, 0x54, 0x28, 0x28, 0x89, 0x8f, 0x27, 0x24, 0x3e, 0xba, 0xb4, 0x5f, 0xf5, 0xe1, 0xac, 0xb9, 0xd4, 0xdf, 0x1b, 0x05, 0x1f, 0xbc, 0x62, 0x82, 0x4d, 0xbc, 0x6f, 0x6c, 0x93, 0x26, 0x1a, 0x78, 0xb9, 0xa7, 0x59 } +, + /* q's CRT exponent dQ */ + 65, + { 0x01, 0x2d, 0xdc, 0xc8, 0x6e, 0xf6, 0x55, 0x99, 0x8c, 0x39, 0xdd, 0xae, 0x11, 0x71, 0x86, 0x69, 0xe5, 0xe4, 0x6c, 0xf1, 0x49, 0x5b, 0x07, 0xe1, 0x3b, 0x10, 0x14, 0xcd, 0x69, 0xb3, 0xaf, 0x68, 0x30, 0x4a, 0xd2, 0xa6, 0xb6, 0x43, 0x21, 0xe7, 0x8b, 0xf3, 0xbb, 0xca, 0x9b, 0xb4, 0x94, 0xe9, 0x1d, 0x45, 0x17, 0x17, 0xe2, 0xd9, 0x75, 0x64, 0xc6, 0x54, 0x94, 0x65, 0xd0, 0x20, 0x5c, 0xf4, 0x21 } +, + /* CRT coefficient qInv */ + 65, + { 0x01, 0x06, 0x00, 0xc4, 0xc2, 0x18, 0x47, 0x45, 0x9f, 0xe5, 0x76, 0x70, 0x3e, 0x2e, 0xbe, 0xca, 0xe8, 0xa5, 0x09, 0x4e, 0xe6, 0x3f, 0x53, 0x6b, 0xf4, 0xac, 0x68, 0xd3, 0xc1, 0x3e, 0x5e, 0x4f, 0x12, 0xac, 0x5c, 0xc1, 0x0a, 0xb6, 0xa2, 0xd0, 0x5a, 0x19, 0x92, 0x14, 0xd1, 0x82, 0x47, 0x47, 0xd5, 0x51, 0x90, 0x96, 0x36, 0xb7, 0x74, 0xc2, 0x2c, 0xac, 0x0b, 0x83, 0x75, 0x99, 0xab, 0xcc, 0x75 } + +} +, +{{ + "RSASSA-PSS Signature Example 4.1", + /* Message to be signed */ + 8, + { 0x9f, 0xb0, 0x3b, 0x82, 0x7c, 0x82, 0x17, 0xd9 } +, + /* Salt */ + 20, + { 0xed, 0x7c, 0x98, 0xc9, 0x5f, 0x30, 0x97, 0x4f, 0xbe, 0x4f, 0xbd, 0xdc, 0xf0, 0xf2, 0x8d, 0x60, 0x21, 0xc0, 0xe9, 0x1d } +, + /* Signature */ + 129, + { 0x03, 0x23, 0xd5, 0xb7, 0xbf, 0x20, 0xba, 0x45, 0x39, 0x28, 0x9a, 0xe4, 0x52, 0xae, 0x42, 0x97, 0x08, 0x0f, 0xef, 0xf4, 0x51, 0x84, 0x23, 0xff, 0x48, 0x11, 0xa8, 0x17, 0x83, 0x7e, 0x7d, 0x82, 0xf1, 0x83, 0x6c, 0xdf, 0xab, 0x54, 0x51, 0x4f, 0xf0, 0x88, 0x7b, 0xdd, 0xee, 0xbf, 0x40, 0xbf, 0x99, 0xb0, 0x47, 0xab, 0xc3, 0xec, 0xfa, 0x6a, 0x37, 0xa3, 0xef, 0x00, 0xf4, 0xa0, 0xc4, 0xa8, 0x8a, 0xae, 0x09, 0x04, 0xb7, 0x45, 0xc8, 0x46, 0xc4, 0x10, 0x7e, 0x87, 0x97, 0x72, 0x3e, 0x8a, 0xc8, 0x10, 0xd9, 0xe3, 0xd9, 0x5d, 0xfa, 0x30, 0xff, 0x49, 0x66, 0xf4, 0xd7, 0x5d, 0x13, 0x76, 0x8d, 0x20, 0x85, 0x7f, 0x2b, 0x14, 0x06, 0xf2, 0x64, 0xcf, 0xe7, 0x5e, 0x27, 0xd7, 0x65, 0x2f, 0x4b, 0x5e, 0xd3, 0x57, 0x5f, 0x28, 0xa7, 0x02, 0xf8, 0xc4, 0xed, 0x9c, 0xf9, 0xb2, 0xd4, 0x49, 0x48 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 4.2", + /* Message to be signed */ + 167, + { 0x0c, 0xa2, 0xad, 0x77, 0x79, 0x7e, 0xce, 0x86, 0xde, 0x5b, 0xf7, 0x68, 0x75, 0x0d, 0xdb, 0x5e, 0xd6, 0xa3, 0x11, 0x6a, 0xd9, 0x9b, 0xbd, 0x17, 0xed, 0xf7, 0xf7, 0x82, 0xf0, 0xdb, 0x1c, 0xd0, 0x5b, 0x0f, 0x67, 0x74, 0x68, 0xc5, 0xea, 0x42, 0x0d, 0xc1, 0x16, 0xb1, 0x0e, 0x80, 0xd1, 0x10, 0xde, 0x2b, 0x04, 0x61, 0xea, 0x14, 0xa3, 0x8b, 0xe6, 0x86, 0x20, 0x39, 0x2e, 0x7e, 0x89, 0x3c, 0xb4, 0xea, 0x93, 0x93, 0xfb, 0x88, 0x6c, 0x20, 0xff, 0x79, 0x06, 0x42, 0x30, 0x5b, 0xf3, 0x02, 0x00, 0x38, 0x92, 0xe5, 0x4d, 0xf9, 0xf6, 0x67, 0x50, 0x9d, 0xc5, 0x39, 0x20, 0xdf, 0x58, 0x3f, 0x50, 0xa3, 0xdd, 0x61, 0xab, 0xb6, 0xfa, 0xb7, 0x5d, 0x60, 0x03, 0x77, 0xe3, 0x83, 0xe6, 0xac, 0xa6, 0x71, 0x0e, 0xee, 0xa2, 0x71, 0x56, 0xe0, 0x67, 0x52, 0xc9, 0x4c, 0xe2, 0x5a, 0xe9, 0x9f, 0xcb, 0xf8, 0x59, 0x2d, 0xbe, 0x2d, 0x7e, 0x27, 0x45, 0x3c, 0xb4, 0x4d, 0xe0, 0x71, 0x00, 0xeb, 0xb1, 0xa2, 0xa1, 0x98, 0x11, 0xa4, 0x78, 0xad, 0xbe, 0xab, 0x27, 0x0f, 0x94, 0xe8, 0xfe, 0x36, 0x9d, 0x90, 0xb3, 0xca, 0x61, 0x2f, 0x9f } +, + /* Salt */ + 20, + { 0x22, 0xd7, 0x1d, 0x54, 0x36, 0x3a, 0x42, 0x17, 0xaa, 0x55, 0x11, 0x3f, 0x05, 0x9b, 0x33, 0x84, 0xe3, 0xe5, 0x7e, 0x44 } +, + /* Signature */ + 129, + { 0x04, 0x9d, 0x01, 0x85, 0x84, 0x5a, 0x26, 0x4d, 0x28, 0xfe, 0xb1, 0xe6, 0x9e, 0xda, 0xec, 0x09, 0x06, 0x09, 0xe8, 0xe4, 0x6d, 0x93, 0xab, 0xb3, 0x83, 0x71, 0xce, 0x51, 0xf4, 0xaa, 0x65, 0xa5, 0x99, 0xbd, 0xaa, 0xa8, 0x1d, 0x24, 0xfb, 0xa6, 0x6a, 0x08, 0xa1, 0x16, 0xcb, 0x64, 0x4f, 0x3f, 0x1e, 0x65, 0x3d, 0x95, 0xc8, 0x9d, 0xb8, 0xbb, 0xd5, 0xda, 0xac, 0x27, 0x09, 0xc8, 0x98, 0x40, 0x00, 0x17, 0x84, 0x10, 0xa7, 0xc6, 0xaa, 0x86, 0x67, 0xdd, 0xc3, 0x8c, 0x74, 0x1f, 0x71, 0x0e, 0xc8, 0x66, 0x5a, 0xa9, 0x05, 0x2b, 0xe9, 0x29, 0xd4, 0xe3, 0xb1, 0x67, 0x82, 0xc1, 0x66, 0x21, 0x14, 0xc5, 0x41, 0x4b, 0xb0, 0x35, 0x34, 0x55, 0xc3, 0x92, 0xfc, 0x28, 0xf3, 0xdb, 0x59, 0x05, 0x4b, 0x5f, 0x36, 0x5c, 0x49, 0xe1, 0xd1, 0x56, 0xf8, 0x76, 0xee, 0x10, 0xcb, 0x4f, 0xd7, 0x05, 0x98 } + +} +, +{ + "RSASSA-PSS Signature Example 4.3", + /* Message to be signed */ + 83, + { 0x28, 0x80, 0x62, 0xaf, 0xc0, 0x8f, 0xcd, 0xb7, 0xc5, 0xf8, 0x65, 0x0b, 0x29, 0x83, 0x73, 0x00, 0x46, 0x1d, 0xd5, 0x67, 0x6c, 0x17, 0xa2, 0x0a, 0x3c, 0x8f, 0xb5, 0x14, 0x89, 0x49, 0xe3, 0xf7, 0x3d, 0x66, 0xb3, 0xae, 0x82, 0xc7, 0x24, 0x0e, 0x27, 0xc5, 0xb3, 0xec, 0x43, 0x28, 0xee, 0x7d, 0x6d, 0xdf, 0x6a, 0x6a, 0x0c, 0x9b, 0x5b, 0x15, 0xbc, 0xda, 0x19, 0x6a, 0x9d, 0x0c, 0x76, 0xb1, 0x19, 0xd5, 0x34, 0xd8, 0x5a, 0xbd, 0x12, 0x39, 0x62, 0xd5, 0x83, 0xb7, 0x6c, 0xe9, 0xd1, 0x80, 0xbc, 0xe1, 0xca } +, + /* Salt */ + 20, + { 0x4a, 0xf8, 0x70, 0xfb, 0xc6, 0x51, 0x60, 0x12, 0xca, 0x91, 0x6c, 0x70, 0xba, 0x86, 0x2a, 0xc7, 0xe8, 0x24, 0x36, 0x17 } +, + /* Signature */ + 129, + { 0x03, 0xfb, 0xc4, 0x10, 0xa2, 0xce, 0xd5, 0x95, 0x00, 0xfb, 0x99, 0xf9, 0xe2, 0xaf, 0x27, 0x81, 0xad, 0xa7, 0x4e, 0x13, 0x14, 0x56, 0x24, 0x60, 0x27, 0x82, 0xe2, 0x99, 0x48, 0x13, 0xee, 0xfc, 0xa0, 0x51, 0x9e, 0xcd, 0x25, 0x3b, 0x85, 0x5f, 0xb6, 0x26, 0xa9, 0x0d, 0x77, 0x1e, 0xae, 0x02, 0x8b, 0x0c, 0x47, 0xa1, 0x99, 0xcb, 0xd9, 0xf8, 0xe3, 0x26, 0x97, 0x34, 0xaf, 0x41, 0x63, 0x59, 0x90, 0x90, 0x71, 0x3a, 0x3f, 0xa9, 0x10, 0xfa, 0x09, 0x60, 0x65, 0x27, 0x21, 0x43, 0x2b, 0x97, 0x10, 0x36, 0xa7, 0x18, 0x1a, 0x2b, 0xc0, 0xca, 0xb4, 0x3b, 0x0b, 0x59, 0x8b, 0xc6, 0x21, 0x74, 0x61, 0xd7, 0xdb, 0x30, 0x5f, 0xf7, 0xe9, 0x54, 0xc5, 0xb5, 0xbb, 0x23, 0x1c, 0x39, 0xe7, 0x91, 0xaf, 0x6b, 0xcf, 0xa7, 0x6b, 0x14, 0x7b, 0x08, 0x13, 0x21, 0xf7, 0x26, 0x41, 0x48, 0x2a, 0x2a, 0xad } + +} +, +{ + "RSASSA-PSS Signature Example 4.4", + /* Message to be signed */ + 49, + { 0x6f, 0x4f, 0x9a, 0xb9, 0x50, 0x11, 0x99, 0xce, 0xf5, 0x5c, 0x6c, 0xf4, 0x08, 0xfe, 0x7b, 0x36, 0xc5, 0x57, 0xc4, 0x9d, 0x42, 0x0a, 0x47, 0x63, 0xd2, 0x46, 0x3c, 0x8a, 0xd4, 0x4b, 0x3c, 0xfc, 0x5b, 0xe2, 0x74, 0x2c, 0x0e, 0x7d, 0x9b, 0x0f, 0x66, 0x08, 0xf0, 0x8c, 0x7f, 0x47, 0xb6, 0x93, 0xee } +, + /* Salt */ + 20, + { 0x40, 0xd2, 0xe1, 0x80, 0xfa, 0xe1, 0xea, 0xc4, 0x39, 0xc1, 0x90, 0xb5, 0x6c, 0x2c, 0x0e, 0x14, 0xdd, 0xf9, 0xa2, 0x26 } +, + /* Signature */ + 129, + { 0x04, 0x86, 0x64, 0x4b, 0xc6, 0x6b, 0xf7, 0x5d, 0x28, 0x33, 0x5a, 0x61, 0x79, 0xb1, 0x08, 0x51, 0xf4, 0x3f, 0x09, 0xbd, 0xed, 0x9f, 0xac, 0x1a, 0xf3, 0x32, 0x52, 0xbb, 0x99, 0x53, 0xba, 0x42, 0x98, 0xcd, 0x64, 0x66, 0xb2, 0x75, 0x39, 0xa7, 0x0a, 0xda, 0xa3, 0xf8, 0x9b, 0x3d, 0xb3, 0xc7, 0x4a, 0xb6, 0x35, 0xd1, 0x22, 0xf4, 0xee, 0x7c, 0xe5, 0x57, 0xa6, 0x1e, 0x59, 0xb8, 0x2f, 0xfb, 0x78, 0x66, 0x30, 0xe5, 0xf9, 0xdb, 0x53, 0xc7, 0x7d, 0x9a, 0x0c, 0x12, 0xfa, 0xb5, 0x95, 0x8d, 0x4c, 0x2c, 0xe7, 0xda, 0xa8, 0x07, 0xcd, 0x89, 0xba, 0x2c, 0xc7, 0xfc, 0xd0, 0x2f, 0xf4, 0x70, 0xca, 0x67, 0xb2, 0x29, 0xfc, 0xce, 0x81, 0x4c, 0x85, 0x2c, 0x73, 0xcc, 0x93, 0xbe, 0xa3, 0x5b, 0xe6, 0x84, 0x59, 0xce, 0x47, 0x8e, 0x9d, 0x46, 0x55, 0xd1, 0x21, 0xc8, 0x47, 0x2f, 0x37, 0x1d, 0x4f } + +} +, +{ + "RSASSA-PSS Signature Example 4.5", + /* Message to be signed */ + 187, + { 0xe1, 0x7d, 0x20, 0x38, 0x5d, 0x50, 0x19, 0x55, 0x82, 0x3c, 0x3f, 0x66, 0x62, 0x54, 0xc1, 0xd3, 0xdd, 0x36, 0xad, 0x51, 0x68, 0xb8, 0xf1, 0x8d, 0x28, 0x6f, 0xdc, 0xf6, 0x7a, 0x7d, 0xad, 0x94, 0x09, 0x70, 0x85, 0xfa, 0xb7, 0xed, 0x86, 0xfe, 0x21, 0x42, 0xa2, 0x87, 0x71, 0x71, 0x79, 0x97, 0xef, 0x1a, 0x7a, 0x08, 0x88, 0x4e, 0xfc, 0x39, 0x35, 0x6d, 0x76, 0x07, 0x7a, 0xaf, 0x82, 0x45, 0x9a, 0x7f, 0xad, 0x45, 0x84, 0x88, 0x75, 0xf2, 0x81, 0x9b, 0x09, 0x89, 0x37, 0xfe, 0x92, 0x3b, 0xcc, 0x9d, 0xc4, 0x42, 0xd7, 0x2d, 0x75, 0x4d, 0x81, 0x20, 0x25, 0x09, 0x0c, 0x9b, 0xc0, 0x3d, 0xb3, 0x08, 0x0c, 0x13, 0x8d, 0xd6, 0x3b, 0x35, 0x5d, 0x0b, 0x4b, 0x85, 0xd6, 0x68, 0x8a, 0xc1, 0x9f, 0x4d, 0xe1, 0x50, 0x84, 0xa0, 0xba, 0x4e, 0x37, 0x3b, 0x93, 0xef, 0x4a, 0x55, 0x50, 0x96, 0x69, 0x19, 0x15, 0xdc, 0x23, 0xc0, 0x0e, 0x95, 0x4c, 0xde, 0xb2, 0x0a, 0x47, 0xcd, 0x55, 0xd1, 0x6c, 0x3d, 0x86, 0x81, 0xd4, 0x6e, 0xd7, 0xf2, 0xed, 0x5e, 0xa4, 0x27, 0x95, 0xbe, 0x17, 0xba, 0xed, 0x25, 0xf0, 0xf4, 0xd1, 0x13, 0xb3, 0x63, 0x6a, 0xdd, 0xd5, 0x85, 0xf1, 0x6a, 0x8b, 0x5a, 0xec, 0x0c, 0x8f, 0xa9, 0xc5, 0xf0, 0x3c, 0xbf, 0x3b, 0x9b, 0x73 } +, + /* Salt */ + 20, + { 0x24, 0x97, 0xdc, 0x2b, 0x46, 0x15, 0xdf, 0xae, 0x5a, 0x66, 0x3d, 0x49, 0xff, 0xd5, 0x6b, 0xf7, 0xef, 0xc1, 0x13, 0x04 } +, + /* Signature */ + 129, + { 0x02, 0x2a, 0x80, 0x04, 0x53, 0x53, 0x90, 0x4c, 0xb3, 0x0c, 0xbb, 0x54, 0x2d, 0x7d, 0x49, 0x90, 0x42, 0x1a, 0x6e, 0xec, 0x16, 0xa8, 0x02, 0x9a, 0x84, 0x22, 0xad, 0xfd, 0x22, 0xd6, 0xaf, 0xf8, 0xc4, 0xcc, 0x02, 0x94, 0xaf, 0x11, 0x0a, 0x0c, 0x06, 0x7e, 0xc8, 0x6a, 0x7d, 0x36, 0x41, 0x34, 0x45, 0x9b, 0xb1, 0xae, 0x8f, 0xf8, 0x36, 0xd5, 0xa8, 0xa2, 0x57, 0x98, 0x40, 0x99, 0x6b, 0x32, 0x0b, 0x19, 0xf1, 0x3a, 0x13, 0xfa, 0xd3, 0x78, 0xd9, 0x31, 0xa6, 0x56, 0x25, 0xda, 0xe2, 0x73, 0x9f, 0x0c, 0x53, 0x67, 0x0b, 0x35, 0xd9, 0xd3, 0xcb, 0xac, 0x08, 0xe7, 0x33, 0xe4, 0xec, 0x2b, 0x83, 0xaf, 0x4b, 0x91, 0x96, 0xd6, 0x3e, 0x7c, 0x4f, 0xf1, 0xdd, 0xea, 0xe2, 0xa1, 0x22, 0x79, 0x1a, 0x12, 0x5b, 0xfe, 0xa8, 0xde, 0xb0, 0xde, 0x8c, 0xcf, 0x1f, 0x4f, 0xfa, 0xf6, 0xe6, 0xfb, 0x0a } + +} +, +{ + "RSASSA-PSS Signature Example 4.6", + /* Message to be signed */ + 166, + { 0xaf, 0xbc, 0x19, 0xd4, 0x79, 0x24, 0x90, 0x18, 0xfd, 0xf4, 0xe0, 0x9f, 0x61, 0x87, 0x26, 0x44, 0x04, 0x95, 0xde, 0x11, 0xdd, 0xee, 0xe3, 0x88, 0x72, 0xd7, 0x75, 0xfc, 0xea, 0x74, 0xa2, 0x38, 0x96, 0xb5, 0x34, 0x3c, 0x9c, 0x38, 0xd4, 0x6a, 0xf0, 0xdb, 0xa2, 0x24, 0xd0, 0x47, 0x58, 0x0c, 0xc6, 0x0a, 0x65, 0xe9, 0x39, 0x1c, 0xf9, 0xb5, 0x9b, 0x36, 0xa8, 0x60, 0x59, 0x8d, 0x4e, 0x82, 0x16, 0x72, 0x2f, 0x99, 0x3b, 0x91, 0xcf, 0xae, 0x87, 0xbc, 0x25, 0x5a, 0xf8, 0x9a, 0x6a, 0x19, 0x9b, 0xca, 0x4a, 0x39, 0x1e, 0xad, 0xbc, 0x3a, 0x24, 0x90, 0x3c, 0x0b, 0xd6, 0x67, 0x36, 0x8f, 0x6b, 0xe7, 0x8e, 0x3f, 0xea, 0xbf, 0xb4, 0xff, 0xd4, 0x63, 0x12, 0x27, 0x63, 0x74, 0x0f, 0xfb, 0xbe, 0xfe, 0xab, 0x9a, 0x25, 0x56, 0x4b, 0xc5, 0xd1, 0xc2, 0x4c, 0x93, 0xe4, 0x22, 0xf7, 0x50, 0x73, 0xe2, 0xad, 0x72, 0xbf, 0x45, 0xb1, 0x0d, 0xf0, 0x0b, 0x52, 0xa1, 0x47, 0x12, 0x8e, 0x73, 0xfe, 0xe3, 0x3f, 0xa3, 0xf0, 0x57, 0x7d, 0x77, 0xf8, 0x0f, 0xbc, 0x2d, 0xf1, 0xbe, 0xd3, 0x13, 0x29, 0x0c, 0x12, 0x77, 0x7f, 0x50 } +, + /* Salt */ + 20, + { 0xa3, 0x34, 0xdb, 0x6f, 0xae, 0xbf, 0x11, 0x08, 0x1a, 0x04, 0xf8, 0x7c, 0x2d, 0x62, 0x1c, 0xde, 0xc7, 0x93, 0x0b, 0x9b } +, + /* Signature */ + 129, + { 0x00, 0x93, 0x8d, 0xcb, 0x6d, 0x58, 0x30, 0x46, 0x06, 0x5f, 0x69, 0xc7, 0x8d, 0xa7, 0xa1, 0xf1, 0x75, 0x70, 0x66, 0xa7, 0xfa, 0x75, 0x12, 0x5a, 0x9d, 0x29, 0x29, 0xf0, 0xb7, 0x9a, 0x60, 0xb6, 0x27, 0xb0, 0x82, 0xf1, 0x1f, 0x5b, 0x19, 0x6f, 0x28, 0xeb, 0x9d, 0xaa, 0x6f, 0x21, 0xc0, 0x5e, 0x51, 0x40, 0xf6, 0xae, 0xf1, 0x73, 0x7d, 0x20, 0x23, 0x07, 0x5c, 0x05, 0xec, 0xf0, 0x4a, 0x02, 0x8c, 0x68, 0x6a, 0x2a, 0xb3, 0xe7, 0xd5, 0xa0, 0x66, 0x4f, 0x29, 0x5c, 0xe1, 0x29, 0x95, 0xe8, 0x90, 0x90, 0x8b, 0x6a, 0xd2, 0x1f, 0x08, 0x39, 0xeb, 0x65, 0xb7, 0x03, 0x93, 0xa7, 0xb5, 0xaf, 0xd9, 0x87, 0x1d, 0xe0, 0xca, 0xa0, 0xce, 0xde, 0xc5, 0xb8, 0x19, 0x62, 0x67, 0x56, 0x20, 0x9d, 0x13, 0xab, 0x1e, 0x7b, 0xb9, 0x54, 0x6a, 0x26, 0xff, 0x37, 0xe9, 0xa5, 0x1a, 0xf9, 0xfd, 0x56, 0x2e } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 5: A 1028-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x0d, 0x10, 0xf6, 0x61, 0xf2, 0x99, 0x40, 0xf5, 0xed, 0x39, 0xaa, 0x26, 0x09, 0x66, 0xde, 0xb4, 0x78, 0x43, 0x67, 0x9d, 0x2b, 0x6f, 0xb2, 0x5b, 0x3d, 0xe3, 0x70, 0xf3, 0xac, 0x7c, 0x19, 0x91, 0x63, 0x91, 0xfd, 0x25, 0xfb, 0x52, 0x7e, 0xbf, 0xa6, 0xa4, 0xb4, 0xdf, 0x45, 0xa1, 0x75, 0x9d, 0x99, 0x6c, 0x4b, 0xb4, 0xeb, 0xd1, 0x88, 0x28, 0xc4, 0x4f, 0xc5, 0x2d, 0x01, 0x91, 0x87, 0x17, 0x40, 0x52, 0x5f, 0x47, 0xa4, 0xb0, 0xcc, 0x8d, 0xa3, 0x25, 0xed, 0x8a, 0xa6, 0x76, 0xb0, 0xd0, 0xf6, 0x26, 0xe0, 0xa7, 0x7f, 0x07, 0x69, 0x21, 0x70, 0xac, 0xac, 0x80, 0x82, 0xf4, 0x2f, 0xaa, 0x7d, 0xc7, 0xcd, 0x12, 0x3e, 0x73, 0x0e, 0x31, 0xa8, 0x79, 0x85, 0x20, 0x4c, 0xab, 0xcb, 0xe6, 0x67, 0x0d, 0x43, 0xa2, 0xdd, 0x2b, 0x2d, 0xde, 0xf5, 0xe0, 0x53, 0x92, 0xfc, 0x21, 0x3b, 0xc5, 0x07 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 129, + { 0x03, 0xce, 0x08, 0xb1, 0x04, 0xff, 0xf3, 0x96, 0xa9, 0x79, 0xbd, 0x3e, 0x4e, 0x46, 0x92, 0x5b, 0x63, 0x19, 0xdd, 0xb6, 0x3a, 0xcb, 0xcf, 0xd8, 0x19, 0xf1, 0x7d, 0x16, 0xb8, 0x07, 0x7b, 0x3a, 0x87, 0x10, 0x1f, 0xf3, 0x4b, 0x77, 0xfe, 0x48, 0xb8, 0xb2, 0x05, 0xa9, 0x6e, 0x91, 0x51, 0xba, 0x8e, 0xce, 0xa6, 0x4d, 0x0c, 0xce, 0x7b, 0x23, 0xc3, 0xe6, 0xa6, 0xb8, 0x30, 0x58, 0xbc, 0x49, 0xda, 0xe8, 0x16, 0xae, 0x73, 0x6d, 0xb5, 0xa4, 0x70, 0x8e, 0x2a, 0xd4, 0x35, 0x23, 0x2b, 0x56, 0x7f, 0x90, 0x96, 0xce, 0x59, 0xff, 0x28, 0x06, 0x1e, 0x79, 0xab, 0x1c, 0x02, 0xd7, 0x17, 0xe6, 0xb2, 0x3c, 0xea, 0x6d, 0xb8, 0xeb, 0x51, 0x92, 0xfa, 0x7c, 0x1e, 0xab, 0x22, 0x7d, 0xba, 0x74, 0x62, 0x1c, 0x45, 0x60, 0x18, 0x96, 0xee, 0xf1, 0x37, 0x92, 0xc8, 0x44, 0x0b, 0xeb, 0x15, 0xaa, 0xc1 } +, + /* Prime p */ + 65, + { 0x03, 0xf2, 0xf3, 0x31, 0xf4, 0x14, 0x2d, 0x4f, 0x24, 0xb4, 0x3a, 0xa1, 0x02, 0x79, 0xa8, 0x96, 0x52, 0xd4, 0xe7, 0x53, 0x72, 0x21, 0xa1, 0xa7, 0xb2, 0xa2, 0x5d, 0xeb, 0x55, 0x1e, 0x5d, 0xe9, 0xac, 0x49, 0x74, 0x11, 0xc2, 0x27, 0xa9, 0x4e, 0x45, 0xf9, 0x1c, 0x2d, 0x1c, 0x13, 0xcc, 0x04, 0x6c, 0xf4, 0xce, 0x14, 0xe3, 0x2d, 0x05, 0x87, 0x34, 0x21, 0x0d, 0x44, 0xa8, 0x7e, 0xe1, 0xb7, 0x3f } +, + /* Prime q */ + 65, + { 0x03, 0x4f, 0x09, 0x0d, 0x73, 0xb5, 0x58, 0x03, 0x03, 0x0c, 0xf0, 0x36, 0x1a, 0x5d, 0x80, 0x81, 0xbf, 0xb7, 0x9f, 0x85, 0x15, 0x23, 0xfe, 0xac, 0x0a, 0x21, 0x24, 0xd0, 0x8d, 0x40, 0x13, 0xff, 0x08, 0x48, 0x77, 0x71, 0xa8, 0x70, 0xd0, 0x47, 0x9d, 0xc0, 0x68, 0x6c, 0x62, 0xf7, 0x71, 0x8d, 0xfe, 0xcf, 0x02, 0x4b, 0x17, 0xc9, 0x26, 0x76, 0x78, 0x05, 0x91, 0x71, 0x33, 0x9c, 0xc0, 0x08, 0x39 } +, + /* p's CRT exponent dP */ + 65, + { 0x02, 0xaa, 0x66, 0x3a, 0xdb, 0xf5, 0x1a, 0xb8, 0x87, 0xa0, 0x18, 0xcb, 0x42, 0x6e, 0x78, 0xbc, 0x2f, 0xe1, 0x82, 0xdc, 0xb2, 0xf7, 0xbc, 0xb5, 0x04, 0x41, 0xd1, 0x7f, 0xdf, 0x0f, 0x06, 0x79, 0x8b, 0x50, 0x71, 0xc6, 0xe2, 0xf5, 0xfe, 0xb4, 0xd5, 0x4a, 0xd8, 0x18, 0x23, 0x11, 0xc1, 0xef, 0x62, 0xd4, 0xc4, 0x9f, 0x18, 0xd1, 0xf5, 0x1f, 0x54, 0xb2, 0xd2, 0xcf, 0xfb, 0xa4, 0xda, 0x1b, 0xe5 } +, + /* q's CRT exponent dQ */ + 65, + { 0x02, 0xbb, 0xe7, 0x06, 0x07, 0x8b, 0x5c, 0x0b, 0x39, 0x15, 0x12, 0xd4, 0x11, 0xdb, 0x1b, 0x19, 0x9b, 0x5a, 0x56, 0x64, 0xb8, 0x40, 0x42, 0xea, 0xd3, 0x7f, 0xe9, 0x94, 0xae, 0x72, 0xb9, 0x53, 0x2d, 0xfb, 0xfb, 0x3e, 0x9e, 0x69, 0x81, 0xa0, 0xfb, 0xb8, 0x06, 0x51, 0x31, 0x41, 0xb7, 0xc2, 0x16, 0x3f, 0xe5, 0x6c, 0x39, 0x5e, 0x4b, 0xfa, 0xee, 0x57, 0xe3, 0x83, 0x3f, 0x9b, 0x91, 0x8d, 0xf9 } +, + /* CRT coefficient qInv */ + 64, + { 0x02, 0x42, 0xb6, 0xcd, 0x00, 0xd3, 0x0a, 0x76, 0x7a, 0xee, 0x9a, 0x89, 0x8e, 0xad, 0x45, 0x3c, 0x8e, 0xae, 0xa6, 0x3d, 0x50, 0x0b, 0x7d, 0x1e, 0x00, 0x71, 0x3e, 0xda, 0xe5, 0x1c, 0xe3, 0x6b, 0x23, 0xb6, 0x64, 0xdf, 0x26, 0xe6, 0x3e, 0x26, 0x6e, 0xc8, 0xf7, 0x6e, 0x6e, 0x63, 0xed, 0x1b, 0xa4, 0x1e, 0xb0, 0x33, 0xb1, 0x20, 0xf7, 0xea, 0x52, 0x12, 0xae, 0x21, 0xa9, 0x8f, 0xbc, 0x16 } + +} +, +{{ + "RSASSA-PSS Signature Example 5.1", + /* Message to be signed */ + 154, + { 0x30, 0xc7, 0xd5, 0x57, 0x45, 0x8b, 0x43, 0x6d, 0xec, 0xfd, 0xc1, 0x4d, 0x06, 0xcb, 0x7b, 0x96, 0xb0, 0x67, 0x18, 0xc4, 0x8d, 0x7d, 0xe5, 0x74, 0x82, 0xa8, 0x68, 0xae, 0x7f, 0x06, 0x58, 0x70, 0xa6, 0x21, 0x65, 0x06, 0xd1, 0x1b, 0x77, 0x93, 0x23, 0xdf, 0xdf, 0x04, 0x6c, 0xf5, 0x77, 0x51, 0x29, 0x13, 0x4b, 0x4d, 0x56, 0x89, 0xe4, 0xd9, 0xc0, 0xce, 0x1e, 0x12, 0xd7, 0xd4, 0xb0, 0x6c, 0xb5, 0xfc, 0x58, 0x20, 0xde, 0xcf, 0xa4, 0x1b, 0xaf, 0x59, 0xbf, 0x25, 0x7b, 0x32, 0xf0, 0x25, 0xb7, 0x67, 0x9b, 0x44, 0x5b, 0x94, 0x99, 0xc9, 0x25, 0x55, 0x14, 0x58, 0x85, 0x99, 0x2f, 0x1b, 0x76, 0xf8, 0x48, 0x91, 0xee, 0x4d, 0x3b, 0xe0, 0xf5, 0x15, 0x0f, 0xd5, 0x90, 0x1e, 0x3a, 0x4c, 0x8e, 0xd4, 0x3f, 0xd3, 0x6b, 0x61, 0xd0, 0x22, 0xe6, 0x5a, 0xd5, 0x00, 0x8d, 0xbf, 0x33, 0x29, 0x3c, 0x22, 0xbf, 0xbf, 0xd0, 0x73, 0x21, 0xf0, 0xf1, 0xd5, 0xfa, 0x9f, 0xdf, 0x00, 0x14, 0xc2, 0xfc, 0xb0, 0x35, 0x8a, 0xad, 0x0e, 0x35, 0x4b, 0x0d, 0x29 } +, + /* Salt */ + 20, + { 0x08, 0x1b, 0x23, 0x3b, 0x43, 0x56, 0x77, 0x50, 0xbd, 0x6e, 0x78, 0xf3, 0x96, 0xa8, 0x8b, 0x9f, 0x6a, 0x44, 0x51, 0x51 } +, + /* Signature */ + 129, + { 0x0b, 0xa3, 0x73, 0xf7, 0x6e, 0x09, 0x21, 0xb7, 0x0a, 0x8f, 0xbf, 0xe6, 0x22, 0xf0, 0xbf, 0x77, 0xb2, 0x8a, 0x3d, 0xb9, 0x8e, 0x36, 0x10, 0x51, 0xc3, 0xd7, 0xcb, 0x92, 0xad, 0x04, 0x52, 0x91, 0x5a, 0x4d, 0xe9, 0xc0, 0x17, 0x22, 0xf6, 0x82, 0x3e, 0xeb, 0x6a, 0xdf, 0x7e, 0x0c, 0xa8, 0x29, 0x0f, 0x5d, 0xe3, 0xe5, 0x49, 0x89, 0x0a, 0xc2, 0xa3, 0xc5, 0x95, 0x0a, 0xb2, 0x17, 0xba, 0x58, 0x59, 0x08, 0x94, 0x95, 0x2d, 0xe9, 0x6f, 0x8d, 0xf1, 0x11, 0xb2, 0x57, 0x52, 0x15, 0xda, 0x6c, 0x16, 0x15, 0x90, 0xc7, 0x45, 0xbe, 0x61, 0x24, 0x76, 0xee, 0x57, 0x8e, 0xd3, 0x84, 0xab, 0x33, 0xe3, 0xec, 0xe9, 0x74, 0x81, 0xa2, 0x52, 0xf5, 0xc7, 0x9a, 0x98, 0xb5, 0x53, 0x2a, 0xe0, 0x0c, 0xdd, 0x62, 0xf2, 0xec, 0xc0, 0xcd, 0x1b, 0xae, 0xfe, 0x80, 0xd8, 0x0b, 0x96, 0x21, 0x93, 0xec, 0x1d } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 5.2", + /* Message to be signed */ + 209, + { 0xe7, 0xb3, 0x2e, 0x15, 0x56, 0xea, 0x1b, 0x27, 0x95, 0x04, 0x6a, 0xc6, 0x97, 0x39, 0xd2, 0x2a, 0xc8, 0x96, 0x6b, 0xf1, 0x1c, 0x11, 0x6f, 0x61, 0x4b, 0x16, 0x67, 0x40, 0xe9, 0x6b, 0x90, 0x65, 0x3e, 0x57, 0x50, 0x94, 0x5f, 0xcf, 0x77, 0x21, 0x86, 0xc0, 0x37, 0x90, 0xa0, 0x7f, 0xda, 0x32, 0x3e, 0x1a, 0x61, 0x91, 0x6b, 0x06, 0xee, 0x21, 0x57, 0xdb, 0x3d, 0xff, 0x80, 0xd6, 0x7d, 0x5e, 0x39, 0xa5, 0x3a, 0xe2, 0x68, 0xc8, 0xf0, 0x9e, 0xd9, 0x9a, 0x73, 0x20, 0x05, 0xb0, 0xbc, 0x6a, 0x04, 0xaf, 0x4e, 0x08, 0xd5, 0x7a, 0x00, 0xe7, 0x20, 0x1b, 0x30, 0x60, 0xef, 0xaa, 0xdb, 0x73, 0x11, 0x3b, 0xfc, 0x08, 0x7f, 0xd8, 0x37, 0x09, 0x3a, 0xa2, 0x52, 0x35, 0xb8, 0xc1, 0x49, 0xf5, 0x62, 0x15, 0xf0, 0x31, 0xc2, 0x4a, 0xd5, 0xbd, 0xe7, 0xf2, 0x99, 0x60, 0xdf, 0x7d, 0x52, 0x40, 0x70, 0xf7, 0x44, 0x9c, 0x6f, 0x78, 0x50, 0x84, 0xbe, 0x1a, 0x0f, 0x73, 0x30, 0x47, 0xf3, 0x36, 0xf9, 0x15, 0x47, 0x38, 0x67, 0x45, 0x47, 0xdb, 0x02, 0xa9, 0xf4, 0x4d, 0xfc, 0x6e, 0x60, 0x30, 0x10, 0x81, 0xe1, 0xce, 0x99, 0x84, 0x7f, 0x3b, 0x5b, 0x60, 0x1f, 0xf0, 0x6b, 0x4d, 0x57, 0x76, 0xa9, 0x74, 0x0b, 0x9a, 0xa0, 0xd3, 0x40, 0x58, 0xfd, 0x3b, 0x90, 0x6e, 0x4f, 0x78, 0x59, 0xdf, 0xb0, 0x7d, 0x71, 0x73, 0xe5, 0xe6, 0xf6, 0x35, 0x0a, 0xda, 0xc2, 0x1f, 0x27, 0xb2, 0x30, 0x74, 0x69 } +, + /* Salt */ + 20, + { 0xbd, 0x0c, 0xe1, 0x95, 0x49, 0xd0, 0x70, 0x01, 0x20, 0xcb, 0xe5, 0x10, 0x77, 0xdb, 0xbb, 0xb0, 0x0a, 0x8d, 0x8b, 0x09 } +, + /* Signature */ + 129, + { 0x08, 0x18, 0x0d, 0xe8, 0x25, 0xe4, 0xb8, 0xb0, 0x14, 0xa3, 0x2d, 0xa8, 0xba, 0x76, 0x15, 0x55, 0x92, 0x12, 0x04, 0xf2, 0xf9, 0x0d, 0x5f, 0x24, 0xb7, 0x12, 0x90, 0x8f, 0xf8, 0x4f, 0x3e, 0x22, 0x0a, 0xd1, 0x79, 0x97, 0xc0, 0xdd, 0x6e, 0x70, 0x66, 0x30, 0xba, 0x3e, 0x84, 0xad, 0xd4, 0xd5, 0xe7, 0xab, 0x00, 0x4e, 0x58, 0x07, 0x4b, 0x54, 0x97, 0x09, 0x56, 0x5d, 0x43, 0xad, 0x9e, 0x97, 0xb5, 0xa7, 0xa1, 0xa2, 0x9e, 0x85, 0xb9, 0xf9, 0x0f, 0x4a, 0xaf, 0xcd, 0xf5, 0x83, 0x21, 0xde, 0x8c, 0x59, 0x74, 0xef, 0x9a, 0xbf, 0x2d, 0x52, 0x6f, 0x33, 0xc0, 0xf2, 0xf8, 0x2e, 0x95, 0xd1, 0x58, 0xea, 0x6b, 0x81, 0xf1, 0x73, 0x6d, 0xb8, 0xd1, 0xaf, 0x3d, 0x6a, 0xc6, 0xa8, 0x3b, 0x32, 0xd1, 0x8b, 0xae, 0x0f, 0xf1, 0xb2, 0xfe, 0x27, 0xde, 0x4c, 0x76, 0xed, 0x8c, 0x79, 0x80, 0xa3, 0x4e } + +} +, +{ + "RSASSA-PSS Signature Example 5.3", + /* Message to be signed */ + 223, + { 0x8d, 0x83, 0x96, 0xe3, 0x65, 0x07, 0xfe, 0x1e, 0xf6, 0xa1, 0x90, 0x17, 0x54, 0x8e, 0x0c, 0x71, 0x66, 0x74, 0xc2, 0xfe, 0xc2, 0x33, 0xad, 0xb2, 0xf7, 0x75, 0x66, 0x5e, 0xc4, 0x1f, 0x2b, 0xd0, 0xba, 0x39, 0x6b, 0x06, 0x1a, 0x9d, 0xaa, 0x7e, 0x86, 0x6f, 0x7c, 0x23, 0xfd, 0x35, 0x31, 0x95, 0x43, 0x00, 0xa3, 0x42, 0xf9, 0x24, 0x53, 0x5e, 0xa1, 0x49, 0x8c, 0x48, 0xf6, 0xc8, 0x79, 0x93, 0x28, 0x65, 0xfc, 0x02, 0x00, 0x0c, 0x52, 0x87, 0x23, 0xb7, 0xad, 0x03, 0x35, 0x74, 0x5b, 0x51, 0x20, 0x9a, 0x0a, 0xfe, 0xd9, 0x32, 0xaf, 0x8f, 0x08, 0x87, 0xc2, 0x19, 0x00, 0x4d, 0x2a, 0xbd, 0x89, 0x4e, 0xa9, 0x25, 0x59, 0xee, 0x31, 0x98, 0xaf, 0x3a, 0x73, 0x4f, 0xe9, 0xb9, 0x63, 0x8c, 0x26, 0x3a, 0x72, 0x8a, 0xd9, 0x5a, 0x5a, 0xe8, 0xce, 0x3e, 0xb1, 0x58, 0x39, 0xf3, 0xaa, 0x78, 0x52, 0xbb, 0x39, 0x07, 0x06, 0xe7, 0x76, 0x0e, 0x43, 0xa7, 0x12, 0x91, 0xa2, 0xe3, 0xf8, 0x27, 0x23, 0x7d, 0xed, 0xa8, 0x51, 0x87, 0x4c, 0x51, 0x76, 0x65, 0xf5, 0x45, 0xf2, 0x72, 0x38, 0xdf, 0x86, 0x55, 0x7f, 0x37, 0x5d, 0x09, 0xcc, 0xd8, 0xbd, 0x15, 0xd8, 0xcc, 0xf6, 0x1f, 0x5d, 0x78, 0xca, 0x5c, 0x7f, 0x5c, 0xde, 0x78, 0x2e, 0x6b, 0xf5, 0xd0, 0x05, 0x70, 0x56, 0xd4, 0xba, 0xd9, 0x8b, 0x3d, 0x2f, 0x95, 0x75, 0xe8, 0x24, 0xab, 0x7a, 0x33, 0xff, 0x57, 0xb0, 0xac, 0x10, 0x0a, 0xb0, 0xd6, 0xea, 0xd7, 0xaa, 0x0b, 0x50, 0xf6, 0xe4, 0xd3, 0xe5, 0xec, 0x0b, 0x96, 0x6b } +, + /* Salt */ + 20, + { 0x81, 0x57, 0x79, 0xa9, 0x1b, 0x3a, 0x8b, 0xd0, 0x49, 0xbf, 0x2a, 0xeb, 0x92, 0x01, 0x42, 0x77, 0x22, 0x22, 0xc9, 0xca } +, + /* Signature */ + 129, + { 0x05, 0xe0, 0xfd, 0xbd, 0xf6, 0xf7, 0x56, 0xef, 0x73, 0x31, 0x85, 0xcc, 0xfa, 0x8c, 0xed, 0x2e, 0xb6, 0xd0, 0x29, 0xd9, 0xd5, 0x6e, 0x35, 0x56, 0x1b, 0x5d, 0xb8, 0xe7, 0x02, 0x57, 0xee, 0x6f, 0xd0, 0x19, 0xd2, 0xf0, 0xbb, 0xf6, 0x69, 0xfe, 0x9b, 0x98, 0x21, 0xe7, 0x8d, 0xf6, 0xd4, 0x1e, 0x31, 0x60, 0x8d, 0x58, 0x28, 0x0f, 0x31, 0x8e, 0xe3, 0x4f, 0x55, 0x99, 0x41, 0xc8, 0xdf, 0x13, 0x28, 0x75, 0x74, 0xba, 0xc0, 0x00, 0xb7, 0xe5, 0x8d, 0xc4, 0xf4, 0x14, 0xba, 0x49, 0xfb, 0x12, 0x7f, 0x9d, 0x0f, 0x89, 0x36, 0x63, 0x8c, 0x76, 0xe8, 0x53, 0x56, 0xc9, 0x94, 0xf7, 0x97, 0x50, 0xf7, 0xfa, 0x3c, 0xf4, 0xfd, 0x48, 0x2d, 0xf7, 0x5e, 0x3f, 0xb9, 0x97, 0x8c, 0xd0, 0x61, 0xf7, 0xab, 0xb1, 0x75, 0x72, 0xe6, 0xe6, 0x3e, 0x0b, 0xde, 0x12, 0xcb, 0xdc, 0xf1, 0x8c, 0x68, 0xb9, 0x79 } + +} +, +{ + "RSASSA-PSS Signature Example 5.4", + /* Message to be signed */ + 13, + { 0x32, 0x8c, 0x65, 0x9e, 0x0a, 0x64, 0x37, 0x43, 0x3c, 0xce, 0xb7, 0x3c, 0x14 } +, + /* Salt */ + 20, + { 0x9a, 0xec, 0x4a, 0x74, 0x80, 0xd5, 0xbb, 0xc4, 0x29, 0x20, 0xd7, 0xca, 0x23, 0x5d, 0xb6, 0x74, 0x98, 0x9c, 0x9a, 0xac } +, + /* Signature */ + 129, + { 0x0b, 0xc9, 0x89, 0x85, 0x3b, 0xc2, 0xea, 0x86, 0x87, 0x32, 0x71, 0xce, 0x18, 0x3a, 0x92, 0x3a, 0xb6, 0x5e, 0x8a, 0x53, 0x10, 0x0e, 0x6d, 0xf5, 0xd8, 0x7a, 0x24, 0xc4, 0x19, 0x4e, 0xb7, 0x97, 0x81, 0x3e, 0xe2, 0xa1, 0x87, 0xc0, 0x97, 0xdd, 0x87, 0x2d, 0x59, 0x1d, 0xa6, 0x0c, 0x56, 0x86, 0x05, 0xdd, 0x7e, 0x74, 0x2d, 0x5a, 0xf4, 0xe3, 0x3b, 0x11, 0x67, 0x8c, 0xcb, 0x63, 0x90, 0x32, 0x04, 0xa3, 0xd0, 0x80, 0xb0, 0x90, 0x2c, 0x89, 0xab, 0xa8, 0x86, 0x8f, 0x00, 0x9c, 0x0f, 0x1c, 0x0c, 0xb8, 0x58, 0x10, 0xbb, 0xdd, 0x29, 0x12, 0x1a, 0xbb, 0x84, 0x71, 0xff, 0x2d, 0x39, 0xe4, 0x9f, 0xd9, 0x2d, 0x56, 0xc6, 0x55, 0xc8, 0xe0, 0x37, 0xad, 0x18, 0xfa, 0xfb, 0xdc, 0x92, 0xc9, 0x58, 0x63, 0xf7, 0xf6, 0x1e, 0xa9, 0xef, 0xa2, 0x8f, 0xea, 0x40, 0x13, 0x69, 0xd1, 0x9d, 0xae, 0xa1 } + +} +, +{ + "RSASSA-PSS Signature Example 5.5", + /* Message to be signed */ + 228, + { 0xf3, 0x7b, 0x96, 0x23, 0x79, 0xa4, 0x7d, 0x41, 0x5a, 0x37, 0x6e, 0xec, 0x89, 0x73, 0x15, 0x0b, 0xcb, 0x34, 0xed, 0xd5, 0xab, 0x65, 0x40, 0x41, 0xb6, 0x14, 0x30, 0x56, 0x0c, 0x21, 0x44, 0x58, 0x2b, 0xa1, 0x33, 0xc8, 0x67, 0xd8, 0x52, 0xd6, 0xb8, 0xe2, 0x33, 0x21, 0x90, 0x13, 0x02, 0xec, 0xb4, 0x5b, 0x09, 0xec, 0x88, 0xb1, 0x52, 0x71, 0x78, 0xfa, 0x04, 0x32, 0x63, 0xf3, 0x06, 0x7d, 0x9f, 0xfe, 0x97, 0x30, 0x32, 0xa9, 0x9f, 0x4c, 0xb0, 0x8a, 0xd2, 0xc7, 0xe0, 0xa2, 0x45, 0x6c, 0xdd, 0x57, 0xa7, 0xdf, 0x56, 0xfe, 0x60, 0x53, 0x52, 0x7a, 0x5a, 0xeb, 0x67, 0xd7, 0xe5, 0x52, 0x06, 0x3c, 0x1c, 0xa9, 0x7b, 0x1b, 0xef, 0xfa, 0x7b, 0x39, 0xe9, 0x97, 0xca, 0xf2, 0x78, 0x78, 0xea, 0x0f, 0x62, 0xcb, 0xeb, 0xc8, 0xc2, 0x1d, 0xf4, 0xc8, 0x89, 0xa2, 0x02, 0x85, 0x1e, 0x94, 0x90, 0x88, 0x49, 0x0c, 0x24, 0x9b, 0x6e, 0x9a, 0xcf, 0x1d, 0x80, 0x63, 0xf5, 0xbe, 0x23, 0x43, 0x98, 0x9b, 0xf9, 0x5c, 0x4d, 0xa0, 0x1a, 0x2b, 0xe7, 0x8b, 0x4a, 0xb6, 0xb3, 0x78, 0x01, 0x5b, 0xc3, 0x79, 0x57, 0xf7, 0x69, 0x48, 0xb5, 0xe5, 0x8e, 0x44, 0x0c, 0x28, 0x45, 0x3d, 0x40, 0xd7, 0xcf, 0xd5, 0x7e, 0x7d, 0x69, 0x06, 0x00, 0x47, 0x4a, 0xb5, 0xe7, 0x59, 0x73, 0xb1, 0xea, 0x0c, 0x5f, 0x1e, 0x45, 0xd1, 0x41, 0x90, 0xaf, 0xe2, 0xf4, 0xeb, 0x6d, 0x3b, 0xdf, 0x71, 0xf1, 0xd2, 0xf8, 0xbb, 0x15, 0x6a, 0x1c, 0x29, 0x5d, 0x04, 0xaa, 0xeb, 0x9d, 0x68, 0x9d, 0xce, 0x79, 0xed, 0x62, 0xbc, 0x44, 0x3e } +, + /* Salt */ + 20, + { 0xe2, 0x0c, 0x1e, 0x98, 0x78, 0x51, 0x2c, 0x39, 0x97, 0x0f, 0x58, 0x37, 0x5e, 0x15, 0x49, 0xa6, 0x8b, 0x64, 0xf3, 0x1d } +, + /* Signature */ + 129, + { 0x0a, 0xef, 0xa9, 0x43, 0xb6, 0x98, 0xb9, 0x60, 0x9e, 0xdf, 0x89, 0x8a, 0xd2, 0x27, 0x44, 0xac, 0x28, 0xdc, 0x23, 0x94, 0x97, 0xce, 0xa3, 0x69, 0xcb, 0xbd, 0x84, 0xf6, 0x5c, 0x95, 0xc0, 0xad, 0x77, 0x6b, 0x59, 0x47, 0x40, 0x16, 0x4b, 0x59, 0xa7, 0x39, 0xc6, 0xff, 0x7c, 0x2f, 0x07, 0xc7, 0xc0, 0x77, 0xa8, 0x6d, 0x95, 0x23, 0x8f, 0xe5, 0x1e, 0x1f, 0xcf, 0x33, 0x57, 0x4a, 0x4a, 0xe0, 0x68, 0x4b, 0x42, 0xa3, 0xf6, 0xbf, 0x67, 0x7d, 0x91, 0x82, 0x0c, 0xa8, 0x98, 0x74, 0x46, 0x7b, 0x2c, 0x23, 0xad, 0xd7, 0x79, 0x69, 0xc8, 0x07, 0x17, 0x43, 0x0d, 0x0e, 0xfc, 0x1d, 0x36, 0x95, 0x89, 0x2c, 0xe8, 0x55, 0xcb, 0x7f, 0x70, 0x11, 0x63, 0x0f, 0x4d, 0xf2, 0x6d, 0xef, 0x8d, 0xdf, 0x36, 0xfc, 0x23, 0x90, 0x5f, 0x57, 0xfa, 0x62, 0x43, 0xa4, 0x85, 0xc7, 0x70, 0xd5, 0x68, 0x1f, 0xcd } + +} +, +{ + "RSASSA-PSS Signature Example 5.6", + /* Message to be signed */ + 138, + { 0xc6, 0x10, 0x3c, 0x33, 0x0c, 0x1e, 0xf7, 0x18, 0xc1, 0x41, 0xe4, 0x7b, 0x8f, 0xa8, 0x59, 0xbe, 0x4d, 0x5b, 0x96, 0x25, 0x9e, 0x7d, 0x14, 0x20, 0x70, 0xec, 0xd4, 0x85, 0x83, 0x9d, 0xba, 0x5a, 0x83, 0x69, 0xc1, 0x7c, 0x11, 0x14, 0x03, 0x5e, 0x53, 0x2d, 0x19, 0x5c, 0x74, 0xf4, 0x4a, 0x04, 0x76, 0xa2, 0xd3, 0xe8, 0xa4, 0xda, 0x21, 0x00, 0x16, 0xca, 0xce, 0xd0, 0xe3, 0x67, 0xcb, 0x86, 0x77, 0x10, 0xa4, 0xb5, 0xaa, 0x2d, 0xf2, 0xb8, 0xe5, 0xda, 0xf5, 0xfd, 0xc6, 0x47, 0x80, 0x7d, 0x4d, 0x5e, 0xbb, 0x6c, 0x56, 0xb9, 0x76, 0x3c, 0xcd, 0xae, 0x4d, 0xea, 0x33, 0x08, 0xeb, 0x0a, 0xc2, 0xa8, 0x95, 0x01, 0xcb, 0x20, 0x9d, 0x26, 0x39, 0xfa, 0x5b, 0xf8, 0x7c, 0xe7, 0x90, 0x74, 0x7d, 0x3c, 0xb2, 0xd2, 0x95, 0xe8, 0x45, 0x64, 0xf2, 0xf6, 0x37, 0x82, 0x4f, 0x0c, 0x13, 0x02, 0x81, 0x29, 0xb0, 0xaa, 0x4a, 0x42, 0x2d, 0x16, 0x22, 0x82 } +, + /* Salt */ + 20, + { 0x23, 0x29, 0x1e, 0x4a, 0x33, 0x07, 0xe8, 0xbb, 0xb7, 0x76, 0x62, 0x3a, 0xb3, 0x4e, 0x4a, 0x5f, 0x4c, 0xc8, 0xa8, 0xdb } +, + /* Signature */ + 129, + { 0x02, 0x80, 0x2d, 0xcc, 0xfa, 0x8d, 0xfa, 0xf5, 0x27, 0x9b, 0xf0, 0xb4, 0xa2, 0x9b, 0xa1, 0xb1, 0x57, 0x61, 0x1f, 0xae, 0xaa, 0xf4, 0x19, 0xb8, 0x91, 0x9d, 0x15, 0x94, 0x19, 0x00, 0xc1, 0x33, 0x9e, 0x7e, 0x92, 0xe6, 0xfa, 0xe5, 0x62, 0xc5, 0x3e, 0x6c, 0xc8, 0xe8, 0x41, 0x04, 0xb1, 0x10, 0xbc, 0xe0, 0x3a, 0xd1, 0x85, 0x25, 0xe3, 0xc4, 0x9a, 0x0e, 0xad, 0xad, 0x5d, 0x3f, 0x28, 0xf2, 0x44, 0xa8, 0xed, 0x89, 0xed, 0xba, 0xfb, 0xb6, 0x86, 0x27, 0x7c, 0xfa, 0x8a, 0xe9, 0x09, 0x71, 0x4d, 0x6b, 0x28, 0xf4, 0xbf, 0x8e, 0x29, 0x3a, 0xa0, 0x4c, 0x41, 0xef, 0xe7, 0xc0, 0xa8, 0x12, 0x66, 0xd5, 0xc0, 0x61, 0xe2, 0x57, 0x5b, 0xe0, 0x32, 0xaa, 0x46, 0x46, 0x74, 0xff, 0x71, 0x62, 0x62, 0x19, 0xbd, 0x74, 0xcc, 0x45, 0xf0, 0xe7, 0xed, 0x4e, 0x3f, 0xf9, 0x6e, 0xee, 0x75, 0x8e, 0x8f } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 6: A 1029-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x16, 0x4c, 0xa3, 0x1c, 0xff, 0x60, 0x9f, 0x3a, 0x0e, 0x71, 0x01, 0xb0, 0x39, 0xf2, 0xe4, 0xfe, 0x6d, 0xd3, 0x75, 0x19, 0xab, 0x98, 0x59, 0x8d, 0x17, 0x9e, 0x17, 0x49, 0x96, 0x59, 0x80, 0x71, 0xf4, 0x7d, 0x3a, 0x04, 0x55, 0x91, 0x58, 0xd7, 0xbe, 0x37, 0x3c, 0xf1, 0xaa, 0x53, 0xf0, 0xaa, 0x6e, 0xf0, 0x90, 0x39, 0xe5, 0x67, 0x8c, 0x2a, 0x4c, 0x63, 0x90, 0x05, 0x14, 0xc8, 0xc4, 0xf8, 0xaa, 0xed, 0x5d, 0xe1, 0x2a, 0x5f, 0x10, 0xb0, 0x9c, 0x31, 0x1a, 0xf8, 0xc0, 0xff, 0xb5, 0xb7, 0xa2, 0x97, 0xf2, 0xef, 0xc6, 0x3b, 0x8d, 0x6b, 0x05, 0x10, 0x93, 0x1f, 0x0b, 0x98, 0xe4, 0x8b, 0xf5, 0xfc, 0x6e, 0xc4, 0xe7, 0xb8, 0xdb, 0x1f, 0xfa, 0xeb, 0x08, 0xc3, 0x8e, 0x02, 0xad, 0xb8, 0xf0, 0x3a, 0x48, 0x22, 0x9c, 0x99, 0xe9, 0x69, 0x43, 0x1f, 0x61, 0xcb, 0x8c, 0x4d, 0xc6, 0x98, 0xd1 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 129, + { 0x03, 0xb6, 0x64, 0xee, 0x3b, 0x75, 0x66, 0x72, 0x3f, 0xc6, 0xea, 0xf2, 0x8a, 0xbb, 0x43, 0x0a, 0x39, 0x80, 0xf1, 0x12, 0x6c, 0x81, 0xde, 0x8a, 0xd7, 0x09, 0xea, 0xb3, 0x9a, 0xc9, 0xdc, 0xd0, 0xb1, 0x55, 0x0b, 0x37, 0x29, 0xd8, 0x70, 0x68, 0xe9, 0x52, 0x00, 0x9d, 0xf5, 0x44, 0x53, 0x4c, 0x1f, 0x50, 0x82, 0x9a, 0x78, 0xf4, 0x59, 0x1e, 0xb8, 0xfd, 0x57, 0x14, 0x04, 0x26, 0xa6, 0xbb, 0x04, 0x05, 0xb6, 0xa6, 0xf5, 0x1a, 0x57, 0xd9, 0x26, 0x7b, 0x7b, 0xbc, 0x65, 0x33, 0x91, 0xa6, 0x99, 0xa2, 0xa9, 0x0d, 0xac, 0x8a, 0xe2, 0x26, 0xbc, 0xc6, 0x0f, 0xa8, 0xcd, 0x93, 0x4c, 0x73, 0xc7, 0xb0, 0x3b, 0x1f, 0x6b, 0x81, 0x81, 0x58, 0x63, 0x18, 0x38, 0xa8, 0x61, 0x2e, 0x6e, 0x6e, 0xa9, 0x2b, 0xe2, 0x4f, 0x83, 0x24, 0xfa, 0xf5, 0xb1, 0xfd, 0x85, 0x87, 0x22, 0x52, 0x67, 0xba, 0x6f } +, + /* Prime p */ + 65, + { 0x04, 0xf0, 0x54, 0x8c, 0x96, 0x26, 0xab, 0x1e, 0xbf, 0x12, 0x44, 0x93, 0x47, 0x41, 0xd9, 0x9a, 0x06, 0x22, 0x0e, 0xfa, 0x2a, 0x58, 0x56, 0xaa, 0x0e, 0x75, 0x73, 0x0b, 0x2e, 0xc9, 0x6a, 0xdc, 0x86, 0xbe, 0x89, 0x4f, 0xa2, 0x80, 0x3b, 0x53, 0xa5, 0xe8, 0x5d, 0x27, 0x6a, 0xcb, 0xd2, 0x9a, 0xb8, 0x23, 0xf8, 0x0a, 0x73, 0x91, 0xbb, 0x54, 0xa5, 0x05, 0x16, 0x72, 0xfb, 0x04, 0xee, 0xb5, 0x43 } +, + /* Prime q */ + 65, + { 0x04, 0x83, 0xe0, 0xae, 0x47, 0x91, 0x55, 0x87, 0x74, 0x3f, 0xf3, 0x45, 0x36, 0x2b, 0x55, 0x5d, 0x39, 0x62, 0xd9, 0x8b, 0xb6, 0xf1, 0x5f, 0x84, 0x8b, 0x4c, 0x92, 0xb1, 0x77, 0x1c, 0xa8, 0xed, 0x10, 0x7d, 0x8d, 0x3e, 0xe6, 0x5e, 0xc4, 0x45, 0x17, 0xdd, 0x0f, 0xaa, 0x48, 0x1a, 0x38, 0x7e, 0x90, 0x2f, 0x7a, 0x2e, 0x74, 0x7c, 0x26, 0x9e, 0x7e, 0xa4, 0x44, 0x80, 0xbc, 0x53, 0x8b, 0x8e, 0x5b } +, + /* p's CRT exponent dP */ + 65, + { 0x03, 0xa8, 0xe8, 0xae, 0xa9, 0x92, 0x0c, 0x1a, 0xa3, 0xb2, 0xf0, 0xd8, 0x46, 0xe4, 0xb8, 0x50, 0xd8, 0x1c, 0xa3, 0x06, 0xa5, 0x1c, 0x83, 0x54, 0x4f, 0x94, 0x9f, 0x64, 0xf9, 0x0d, 0xcf, 0x3f, 0x8e, 0x26, 0x61, 0xf0, 0x7e, 0x56, 0x12, 0x20, 0xa1, 0x80, 0x38, 0x8f, 0xbe, 0x27, 0x3e, 0x70, 0xe2, 0xe5, 0xdc, 0xa8, 0x3a, 0x0e, 0x13, 0x48, 0xdd, 0x64, 0x90, 0xc7, 0x31, 0xd6, 0xec, 0xe1, 0xab } +, + /* q's CRT exponent dQ */ + 65, + { 0x01, 0x35, 0xbd, 0xcd, 0xb6, 0x0b, 0xf2, 0x19, 0x7c, 0x43, 0x6e, 0xd3, 0x4b, 0x32, 0xcd, 0x8b, 0x4f, 0xc7, 0x77, 0x78, 0x83, 0x2b, 0xa7, 0x67, 0x03, 0x55, 0x1f, 0xb2, 0x42, 0xb3, 0x01, 0x69, 0x95, 0x93, 0xaf, 0x77, 0xfd, 0x8f, 0xc3, 0x94, 0xa8, 0x52, 0x6a, 0xd2, 0x3c, 0xc4, 0x1a, 0x03, 0x80, 0x6b, 0xd8, 0x97, 0xfe, 0x4b, 0x0e, 0xa6, 0x46, 0x55, 0x8a, 0xad, 0xdc, 0xc9, 0x9e, 0x8a, 0x25 } +, + /* CRT coefficient qInv */ + 65, + { 0x03, 0x04, 0xc0, 0x3d, 0x9c, 0x73, 0x65, 0x03, 0xa9, 0x84, 0xab, 0xbd, 0x9b, 0xa2, 0x23, 0x01, 0x40, 0x7c, 0x4a, 0x2a, 0xb1, 0xdd, 0x85, 0x76, 0x64, 0x81, 0xb6, 0x0d, 0x45, 0x40, 0x11, 0x52, 0xe6, 0x92, 0xbe, 0x14, 0xf4, 0x12, 0x1d, 0x9a, 0xa3, 0xfd, 0x6e, 0x0b, 0x4d, 0x1d, 0x3a, 0x97, 0x35, 0x38, 0xa3, 0x1d, 0x42, 0xee, 0x6e, 0x1e, 0x5e, 0xf6, 0x20, 0x23, 0x1a, 0x2b, 0xba, 0xf3, 0x5f } + +} +, +{{ + "RSASSA-PSS Signature Example 6.1", + /* Message to be signed */ + 109, + { 0x0a, 0x20, 0xb7, 0x74, 0xad, 0xdc, 0x2f, 0xa5, 0x12, 0x45, 0xed, 0x7c, 0xb9, 0xda, 0x60, 0x9e, 0x50, 0xca, 0xc6, 0x63, 0x6a, 0x52, 0x54, 0x3f, 0x97, 0x45, 0x8e, 0xed, 0x73, 0x40, 0xf8, 0xd5, 0x3f, 0xfc, 0x64, 0x91, 0x8f, 0x94, 0x90, 0x78, 0xee, 0x03, 0xef, 0x60, 0xd4, 0x2b, 0x5f, 0xec, 0x24, 0x60, 0x50, 0xbd, 0x55, 0x05, 0xcd, 0x8c, 0xb5, 0x97, 0xba, 0xd3, 0xc4, 0xe7, 0x13, 0xb0, 0xef, 0x30, 0x64, 0x4e, 0x76, 0xad, 0xab, 0xb0, 0xde, 0x01, 0xa1, 0x56, 0x1e, 0xfb, 0x25, 0x51, 0x58, 0xc7, 0x4f, 0xc8, 0x01, 0xe6, 0xe9, 0x19, 0xe5, 0x81, 0xb4, 0x6f, 0x0f, 0x0d, 0xdd, 0x08, 0xe4, 0xf3, 0x4c, 0x78, 0x10, 0xb5, 0xed, 0x83, 0x18, 0xf9, 0x1d, 0x7c, 0x8c } +, + /* Salt */ + 20, + { 0x5b, 0x4e, 0xa2, 0xef, 0x62, 0x9c, 0xc2, 0x2f, 0x3b, 0x53, 0x8e, 0x01, 0x69, 0x04, 0xb4, 0x7b, 0x1e, 0x40, 0xbf, 0xd5 } +, + /* Signature */ + 129, + { 0x04, 0xc0, 0xcf, 0xac, 0xec, 0x04, 0xe5, 0xba, 0xdb, 0xec, 0xe1, 0x59, 0xa5, 0xa1, 0x10, 0x3f, 0x69, 0xb3, 0xf3, 0x2b, 0xa5, 0x93, 0xcb, 0x4c, 0xc4, 0xb1, 0xb7, 0xab, 0x45, 0x59, 0x16, 0xa9, 0x6a, 0x27, 0xcd, 0x26, 0x78, 0xea, 0x0f, 0x46, 0xba, 0x37, 0xf7, 0xfc, 0x9c, 0x86, 0x32, 0x5f, 0x29, 0x73, 0x3b, 0x38, 0x9f, 0x1d, 0x97, 0xf4, 0x3e, 0x72, 0x01, 0xc0, 0xf3, 0x48, 0xfc, 0x45, 0xfe, 0x42, 0x89, 0x23, 0x35, 0x36, 0x2e, 0xee, 0x01, 0x8b, 0x5b, 0x16, 0x1f, 0x2f, 0x93, 0x93, 0x03, 0x12, 0x25, 0xc7, 0x13, 0x01, 0x2a, 0x57, 0x6b, 0xc8, 0x8e, 0x23, 0x05, 0x24, 0x89, 0x86, 0x8d, 0x90, 0x10, 0xcb, 0xf0, 0x33, 0xec, 0xc5, 0x68, 0xe8, 0xbc, 0x15, 0x2b, 0xdc, 0x59, 0xd5, 0x60, 0xe4, 0x12, 0x91, 0x91, 0x5d, 0x28, 0x56, 0x52, 0x08, 0xe2, 0x2a, 0xee, 0xc9, 0xef, 0x85, 0xd1 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 6.2", + /* Message to be signed */ + 199, + { 0x2a, 0xaf, 0xf6, 0x63, 0x1f, 0x62, 0x1c, 0xe6, 0x15, 0x76, 0x0a, 0x9e, 0xbc, 0xe9, 0x4b, 0xb3, 0x33, 0x07, 0x7a, 0xd8, 0x64, 0x88, 0xc8, 0x61, 0xd4, 0xb7, 0x6d, 0x29, 0xc1, 0xf4, 0x87, 0x46, 0xc6, 0x11, 0xae, 0x1e, 0x03, 0xce, 0xd4, 0x44, 0x5d, 0x7c, 0xfa, 0x1f, 0xe5, 0xf6, 0x2e, 0x1b, 0x3f, 0x08, 0x45, 0x2b, 0xde, 0x3b, 0x6e, 0xf8, 0x19, 0x73, 0xba, 0xfb, 0xb5, 0x7f, 0x97, 0xbc, 0xee, 0xf8, 0x73, 0x98, 0x53, 0x95, 0xb8, 0x26, 0x05, 0x89, 0xaa, 0x88, 0xcb, 0x7d, 0xb5, 0x0a, 0xb4, 0x69, 0x26, 0x2e, 0x55, 0x1b, 0xdc, 0xd9, 0xa5, 0x6f, 0x27, 0x5a, 0x0a, 0xc4, 0xfe, 0x48, 0x47, 0x00, 0xc3, 0x5f, 0x3d, 0xbf, 0x2b, 0x46, 0x9e, 0xde, 0x86, 0x47, 0x41, 0xb8, 0x6f, 0xa5, 0x91, 0x72, 0xa3, 0x60, 0xba, 0x95, 0xa0, 0x2e, 0x13, 0x9b, 0xe5, 0x0d, 0xdf, 0xb7, 0xcf, 0x0b, 0x42, 0xfa, 0xea, 0xbb, 0xfb, 0xba, 0xa8, 0x6a, 0x44, 0x97, 0x69, 0x9c, 0x4f, 0x2d, 0xfd, 0x5b, 0x08, 0x40, 0x6a, 0xf7, 0xe1, 0x41, 0x44, 0x42, 0x7c, 0x25, 0x3e, 0xc0, 0xef, 0xa2, 0x0e, 0xaf, 0x9a, 0x8b, 0xe8, 0xcd, 0x49, 0xce, 0x1f, 0x1b, 0xc4, 0xe9, 0x3e, 0x61, 0x9c, 0xf2, 0xaa, 0x8e, 0xd4, 0xfb, 0x39, 0xbc, 0x85, 0x90, 0xd0, 0xf7, 0xb9, 0x64, 0x88, 0xf7, 0x31, 0x7a, 0xc9, 0xab, 0xf7, 0xbe, 0xe4, 0xe3, 0xa0, 0xe7, 0x15 } +, + /* Salt */ + 20, + { 0x83, 0x14, 0x6a, 0x9e, 0x78, 0x27, 0x22, 0xc2, 0x8b, 0x01, 0x4f, 0x98, 0xb4, 0x26, 0x7b, 0xda, 0x2a, 0xc9, 0x50, 0x4f } +, + /* Signature */ + 129, + { 0x0a, 0x23, 0x14, 0x25, 0x0c, 0xf5, 0x2b, 0x6e, 0x4e, 0x90, 0x8d, 0xe5, 0xb3, 0x56, 0x46, 0xbc, 0xaa, 0x24, 0x36, 0x1d, 0xa8, 0x16, 0x0f, 0xb0, 0xf9, 0x25, 0x75, 0x90, 0xab, 0x3a, 0xce, 0x42, 0xb0, 0xdc, 0x3e, 0x77, 0xad, 0x2d, 0xb7, 0xc2, 0x03, 0xa2, 0x0b, 0xd9, 0x52, 0xfb, 0xb5, 0x6b, 0x15, 0x67, 0x04, 0x6e, 0xcf, 0xaa, 0x93, 0x3d, 0x7b, 0x10, 0x00, 0xc3, 0xde, 0x9f, 0xf0, 0x5b, 0x7d, 0x98, 0x9b, 0xa4, 0x6f, 0xd4, 0x3b, 0xc4, 0xc2, 0xd0, 0xa3, 0x98, 0x6b, 0x7f, 0xfa, 0x13, 0x47, 0x1d, 0x37, 0xeb, 0x5b, 0x47, 0xd6, 0x47, 0x07, 0xbd, 0x29, 0x0c, 0xfd, 0x6a, 0x9f, 0x39, 0x3a, 0xd0, 0x8e, 0xc1, 0xe3, 0xbd, 0x71, 0xbb, 0x57, 0x92, 0x61, 0x50, 0x35, 0xcd, 0xaf, 0x2d, 0x89, 0x29, 0xae, 0xd3, 0xbe, 0x09, 0x83, 0x79, 0x37, 0x7e, 0x77, 0x7c, 0xe7, 0x9a, 0xaa, 0x47, 0x73 } + +} +, +{ + "RSASSA-PSS Signature Example 6.3", + /* Message to be signed */ + 62, + { 0x0f, 0x61, 0x95, 0xd0, 0x4a, 0x6e, 0x6f, 0xc7, 0xe2, 0xc9, 0x60, 0x0d, 0xbf, 0x84, 0x0c, 0x39, 0xea, 0x8d, 0x4d, 0x62, 0x4f, 0xd5, 0x35, 0x07, 0x01, 0x6b, 0x0e, 0x26, 0x85, 0x8a, 0x5e, 0x0a, 0xec, 0xd7, 0xad, 0xa5, 0x43, 0xae, 0x5c, 0x0a, 0xb3, 0xa6, 0x25, 0x99, 0xcb, 0xa0, 0xa5, 0x4e, 0x6b, 0xf4, 0x46, 0xe2, 0x62, 0xf9, 0x89, 0x97, 0x8f, 0x9d, 0xdf, 0x5e, 0x9a, 0x41 } +, + /* Salt */ + 20, + { 0xa8, 0x7b, 0x8a, 0xed, 0x07, 0xd7, 0xb8, 0xe2, 0xda, 0xf1, 0x4d, 0xdc, 0xa4, 0xac, 0x68, 0xc4, 0xd0, 0xaa, 0xbf, 0xf8 } +, + /* Signature */ + 129, + { 0x08, 0x6d, 0xf6, 0xb5, 0x00, 0x09, 0x8c, 0x12, 0x0f, 0x24, 0xff, 0x84, 0x23, 0xf7, 0x27, 0xd9, 0xc6, 0x1a, 0x5c, 0x90, 0x07, 0xd3, 0xb6, 0xa3, 0x1c, 0xe7, 0xcf, 0x8f, 0x3c, 0xbe, 0xc1, 0xa2, 0x6b, 0xb2, 0x0e, 0x2b, 0xd4, 0xa0, 0x46, 0x79, 0x32, 0x99, 0xe0, 0x3e, 0x37, 0xa2, 0x1b, 0x40, 0x19, 0x4f, 0xb0, 0x45, 0xf9, 0x0b, 0x18, 0xbf, 0x20, 0xa4, 0x79, 0x92, 0xcc, 0xd7, 0x99, 0xcf, 0x9c, 0x05, 0x9c, 0x29, 0x9c, 0x05, 0x26, 0x85, 0x49, 0x54, 0xaa, 0xde, 0x8a, 0x6a, 0xd9, 0xd9, 0x7e, 0xc9, 0x1a, 0x11, 0x45, 0x38, 0x3f, 0x42, 0x46, 0x8b, 0x23, 0x1f, 0x4d, 0x72, 0xf2, 0x37, 0x06, 0xd9, 0x85, 0x3c, 0x3f, 0xa4, 0x3c, 0xe8, 0xac, 0xe8, 0xbf, 0xe7, 0x48, 0x49, 0x87, 0xa1, 0xec, 0x6a, 0x16, 0xc8, 0xda, 0xf8, 0x1f, 0x7c, 0x8b, 0xf4, 0x27, 0x74, 0x70, 0x7a, 0x9d, 0xf4, 0x56 } + +} +, +{ + "RSASSA-PSS Signature Example 6.4", + /* Message to be signed */ + 112, + { 0x33, 0x7d, 0x25, 0xfe, 0x98, 0x10, 0xeb, 0xca, 0x0d, 0xe4, 0xd4, 0x65, 0x8d, 0x3c, 0xeb, 0x8e, 0x0f, 0xe4, 0xc0, 0x66, 0xab, 0xa3, 0xbc, 0xc4, 0x8b, 0x10, 0x5d, 0x3b, 0xf7, 0xe0, 0x25, 0x7d, 0x44, 0xfe, 0xce, 0xa6, 0x59, 0x6f, 0x4d, 0x0c, 0x59, 0xa0, 0x84, 0x02, 0x83, 0x36, 0x78, 0xf7, 0x06, 0x20, 0xf9, 0x13, 0x8d, 0xfe, 0xb7, 0xde, 0xd9, 0x05, 0xe4, 0xa6, 0xd5, 0xf0, 0x5c, 0x47, 0x3d, 0x55, 0x93, 0x66, 0x52, 0xe2, 0xa5, 0xdf, 0x43, 0xc0, 0xcf, 0xda, 0x7b, 0xac, 0xaf, 0x30, 0x87, 0xf4, 0x52, 0x4b, 0x06, 0xcf, 0x42, 0x15, 0x7d, 0x01, 0x53, 0x97, 0x39, 0xf7, 0xfd, 0xde, 0xc9, 0xd5, 0x81, 0x25, 0xdf, 0x31, 0xa3, 0x2e, 0xab, 0x06, 0xc1, 0x9b, 0x71, 0xf1, 0xd5, 0xbf } +, + /* Salt */ + 20, + { 0xa3, 0x79, 0x32, 0xf8, 0xa7, 0x49, 0x4a, 0x94, 0x2d, 0x6f, 0x76, 0x74, 0x38, 0xe7, 0x24, 0xd6, 0xd0, 0xc0, 0xef, 0x18 } +, + /* Signature */ + 129, + { 0x0b, 0x5b, 0x11, 0xad, 0x54, 0x98, 0x63, 0xff, 0xa9, 0xc5, 0x1a, 0x14, 0xa1, 0x10, 0x6c, 0x2a, 0x72, 0xcc, 0x8b, 0x64, 0x6e, 0x5c, 0x72, 0x62, 0x50, 0x97, 0x86, 0x10, 0x5a, 0x98, 0x47, 0x76, 0x53, 0x4c, 0xa9, 0xb5, 0x4c, 0x1c, 0xc6, 0x4b, 0xf2, 0xd5, 0xa4, 0x4f, 0xd7, 0xe8, 0xa6, 0x9d, 0xb6, 0x99, 0xd5, 0xea, 0x52, 0x08, 0x7a, 0x47, 0x48, 0xfd, 0x2a, 0xbc, 0x1a, 0xfe, 0xd1, 0xe5, 0xd6, 0xf7, 0xc8, 0x90, 0x25, 0x53, 0x0b, 0xda, 0xa2, 0x21, 0x3d, 0x7e, 0x03, 0x0f, 0xa5, 0x5d, 0xf6, 0xf3, 0x4b, 0xcf, 0x1c, 0xe4, 0x6d, 0x2e, 0xdf, 0x4e, 0x3a, 0xe4, 0xf3, 0xb0, 0x18, 0x91, 0xa0, 0x68, 0xc9, 0xe3, 0xa4, 0x4b, 0xbc, 0x43, 0x13, 0x3e, 0xda, 0xd6, 0xec, 0xb9, 0xf3, 0x54, 0x00, 0xc4, 0x25, 0x2a, 0x57, 0x62, 0xd6, 0x57, 0x44, 0xb9, 0x9c, 0xb9, 0xf4, 0xc5, 0x59, 0x32, 0x9f } + +} +, +{ + "RSASSA-PSS Signature Example 6.5", + /* Message to be signed */ + 176, + { 0x84, 0xec, 0x50, 0x2b, 0x07, 0x2e, 0x82, 0x87, 0x78, 0x9d, 0x8f, 0x92, 0x35, 0x82, 0x9e, 0xa3, 0xb1, 0x87, 0xaf, 0xd4, 0xd4, 0xc7, 0x85, 0x61, 0x1b, 0xda, 0x5f, 0x9e, 0xb3, 0xcb, 0x96, 0x71, 0x7e, 0xfa, 0x70, 0x07, 0x22, 0x7f, 0x1c, 0x08, 0xcb, 0xcb, 0x97, 0x2e, 0x66, 0x72, 0x35, 0xe0, 0xfb, 0x7d, 0x43, 0x1a, 0x65, 0x70, 0x32, 0x6d, 0x2e, 0xcc, 0xe3, 0x5a, 0xdb, 0x37, 0x3d, 0xc7, 0x53, 0xb3, 0xbe, 0x5f, 0x82, 0x9b, 0x89, 0x17, 0x54, 0x93, 0x19, 0x3f, 0xab, 0x16, 0xba, 0xdb, 0x41, 0x37, 0x1b, 0x3a, 0xac, 0x0a, 0xe6, 0x70, 0x07, 0x6f, 0x24, 0xbe, 0xf4, 0x20, 0xc1, 0x35, 0xad, 0xd7, 0xce, 0xe8, 0xd3, 0x5f, 0xbc, 0x94, 0x4d, 0x79, 0xfa, 0xfb, 0x9e, 0x30, 0x7a, 0x13, 0xb0, 0xf5, 0x56, 0xcb, 0x65, 0x4a, 0x06, 0xf9, 0x73, 0xed, 0x22, 0x67, 0x23, 0x30, 0x19, 0x7e, 0xf5, 0xa7, 0x48, 0xbf, 0x82, 0x6a, 0x5d, 0xb2, 0x38, 0x3a, 0x25, 0x36, 0x4b, 0x68, 0x6b, 0x93, 0x72, 0xbb, 0x23, 0x39, 0xae, 0xb1, 0xac, 0x9e, 0x98, 0x89, 0x32, 0x7d, 0x01, 0x6f, 0x16, 0x70, 0x77, 0x6d, 0xb0, 0x62, 0x01, 0xad, 0xbd, 0xca, 0xf8, 0xa5, 0xe3, 0xb7, 0x4e, 0x10, 0x8b, 0x73 } +, + /* Salt */ + 20, + { 0x7b, 0x79, 0x0c, 0x1d, 0x62, 0xf7, 0xb8, 0x4e, 0x94, 0xdf, 0x6a, 0xf2, 0x89, 0x17, 0xcf, 0x57, 0x10, 0x18, 0x11, 0x0e } +, + /* Signature */ + 129, + { 0x02, 0xd7, 0x1f, 0xa9, 0xb5, 0x3e, 0x46, 0x54, 0xfe, 0xfb, 0x7f, 0x08, 0x38, 0x5c, 0xf6, 0xb0, 0xae, 0x3a, 0x81, 0x79, 0x42, 0xeb, 0xf6, 0x6c, 0x35, 0xac, 0x67, 0xf0, 0xb0, 0x69, 0x95, 0x2a, 0x3c, 0xe9, 0xc7, 0xe1, 0xf1, 0xb0, 0x2e, 0x48, 0x0a, 0x95, 0x00, 0x83, 0x6d, 0xe5, 0xd6, 0x4c, 0xdb, 0x7e, 0xcd, 0xe0, 0x45, 0x42, 0xf7, 0xa7, 0x99, 0x88, 0x78, 0x7e, 0x24, 0xc2, 0xba, 0x05, 0xf5, 0xfd, 0x48, 0x2c, 0x02, 0x3e, 0xd5, 0xc3, 0x0e, 0x04, 0x83, 0x9d, 0xc4, 0x4b, 0xed, 0x2a, 0x3a, 0x3a, 0x4f, 0xee, 0x01, 0x11, 0x3c, 0x89, 0x1a, 0x47, 0xd3, 0x2e, 0xb8, 0x02, 0x5c, 0x28, 0xcb, 0x05, 0x0b, 0x5c, 0xdb, 0x57, 0x6c, 0x70, 0xfe, 0x76, 0xef, 0x52, 0x34, 0x05, 0xc0, 0x84, 0x17, 0xfa, 0xf3, 0x50, 0xb0, 0x37, 0xa4, 0x3c, 0x37, 0x93, 0x39, 0xfc, 0xb1, 0x8d, 0x3a, 0x35, 0x6b } + +} +, +{ + "RSASSA-PSS Signature Example 6.6", + /* Message to be signed */ + 139, + { 0x99, 0x06, 0xd8, 0x9f, 0x97, 0xa9, 0xfd, 0xed, 0xd3, 0xcc, 0xd8, 0x24, 0xdb, 0x68, 0x73, 0x26, 0xf3, 0x0f, 0x00, 0xaa, 0x25, 0xa7, 0xfc, 0xa2, 0xaf, 0xcb, 0x3b, 0x0f, 0x86, 0xcd, 0x41, 0xe7, 0x3f, 0x0e, 0x8f, 0xf7, 0xd2, 0xd8, 0x3f, 0x59, 0xe2, 0x8e, 0xd3, 0x1a, 0x5a, 0x0d, 0x55, 0x15, 0x23, 0x37, 0x4d, 0xe2, 0x2e, 0x4c, 0x7e, 0x8f, 0xf5, 0x68, 0xb3, 0x86, 0xee, 0x3d, 0xc4, 0x11, 0x63, 0xf1, 0x0b, 0xf6, 0x7b, 0xb0, 0x06, 0x26, 0x1c, 0x90, 0x82, 0xf9, 0xaf, 0x90, 0xbf, 0x1d, 0x90, 0x49, 0xa6, 0xb9, 0xfa, 0xe7, 0x1c, 0x7f, 0x84, 0xfb, 0xe6, 0xe5, 0x5f, 0x02, 0x78, 0x9d, 0xe7, 0x74, 0xf2, 0x30, 0xf1, 0x15, 0x02, 0x6a, 0x4b, 0x4e, 0x96, 0xc5, 0x5b, 0x04, 0xa9, 0x5d, 0xa3, 0xaa, 0xcb, 0xb2, 0xce, 0xce, 0x8f, 0x81, 0x76, 0x4a, 0x1f, 0x1c, 0x99, 0x51, 0x54, 0x11, 0x08, 0x7c, 0xf7, 0xd3, 0x4a, 0xed, 0xed, 0x09, 0x32, 0xc1, 0x83 } +, + /* Salt */ + 20, + { 0xfb, 0xbe, 0x05, 0x90, 0x25, 0xb6, 0x9b, 0x89, 0xfb, 0x14, 0xae, 0x22, 0x89, 0xe7, 0xaa, 0xaf, 0xe6, 0x0c, 0x0f, 0xcd } +, + /* Signature */ + 129, + { 0x0a, 0x40, 0xa1, 0x6e, 0x2f, 0xe2, 0xb3, 0x8d, 0x1d, 0xf9, 0x05, 0x46, 0x16, 0x7c, 0xf9, 0x46, 0x9c, 0x9e, 0x3c, 0x36, 0x81, 0xa3, 0x44, 0x2b, 0x4b, 0x2c, 0x2f, 0x58, 0x1d, 0xeb, 0x38, 0x5c, 0xe9, 0x9f, 0xc6, 0x18, 0x8b, 0xb0, 0x2a, 0x84, 0x1d, 0x56, 0xe7, 0x6d, 0x30, 0x18, 0x91, 0xe2, 0x45, 0x60, 0x55, 0x0f, 0xcc, 0x2a, 0x26, 0xb5, 0x5f, 0x4c, 0xcb, 0x26, 0xd8, 0x37, 0xd3, 0x50, 0xa1, 0x54, 0xbc, 0xac, 0xa8, 0x39, 0x2d, 0x98, 0xfa, 0x67, 0x95, 0x9e, 0x97, 0x27, 0xb7, 0x8c, 0xad, 0x03, 0x26, 0x9f, 0x56, 0x96, 0x8f, 0xc5, 0x6b, 0x68, 0xbd, 0x67, 0x99, 0x26, 0xd8, 0x3c, 0xc9, 0xcb, 0x21, 0x55, 0x50, 0x64, 0x5c, 0xcd, 0xa3, 0x1c, 0x76, 0x0f, 0xf3, 0x58, 0x88, 0x94, 0x3d, 0x2d, 0x8a, 0x1d, 0x35, 0x1e, 0x81, 0xe5, 0xd0, 0x7b, 0x86, 0x18, 0x2e, 0x75, 0x10, 0x81, 0xef } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 7: A 1030-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x37, 0xc9, 0xda, 0x4a, 0x66, 0xc8, 0xc4, 0x08, 0xb8, 0xda, 0x27, 0xd0, 0xc9, 0xd7, 0x9f, 0x8c, 0xcb, 0x1e, 0xaf, 0xc1, 0xd2, 0xfe, 0x48, 0x74, 0x6d, 0x94, 0x0b, 0x7c, 0x4e, 0xf5, 0xde, 0xe1, 0x8a, 0xd1, 0x26, 0x47, 0xce, 0xfa, 0xa0, 0xc4, 0xb3, 0x18, 0x8b, 0x22, 0x1c, 0x51, 0x53, 0x86, 0x75, 0x9b, 0x93, 0xf0, 0x20, 0x24, 0xb2, 0x5a, 0xb9, 0x24, 0x2f, 0x83, 0x57, 0xd8, 0xf3, 0xfd, 0x49, 0x64, 0x0e, 0xe5, 0xe6, 0x43, 0xea, 0xf6, 0xc6, 0x4d, 0xee, 0xfa, 0x70, 0x89, 0x72, 0x7c, 0x8f, 0xf0, 0x39, 0x93, 0x33, 0x39, 0x15, 0xc6, 0xef, 0x21, 0xbf, 0x59, 0x75, 0xb6, 0xe5, 0x0d, 0x11, 0x8b, 0x51, 0x00, 0x8e, 0xc3, 0x3e, 0x9f, 0x01, 0xa0, 0xa5, 0x45, 0xa1, 0x0a, 0x83, 0x6a, 0x43, 0xdd, 0xbc, 0xa9, 0xd8, 0xb5, 0xc5, 0xd3, 0x54, 0x80, 0x22, 0xd7, 0x06, 0x4e, 0xa2, 0x9a, 0xb3 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x3b, 0xed, 0x99, 0x90, 0x52, 0xd9, 0x57, 0xbc, 0x06, 0xd6, 0x51, 0xee, 0xf6, 0xe3, 0xa9, 0x80, 0x94, 0xb1, 0x62, 0x1b, 0xd3, 0x8b, 0x54, 0x49, 0xbd, 0x6c, 0x4a, 0xea, 0x3d, 0xe7, 0xe0, 0x84, 0x67, 0x9a, 0x44, 0x84, 0xde, 0xd2, 0x5b, 0xe0, 0xf0, 0x82, 0x6c, 0xf3, 0x37, 0x78, 0x25, 0x41, 0x4b, 0x14, 0xd4, 0xd6, 0x1d, 0xb1, 0x4d, 0xe6, 0x26, 0xfb, 0xb8, 0x0e, 0x5f, 0x4f, 0xae, 0xc9, 0x56, 0xf9, 0xa0, 0xa2, 0xd2, 0x4f, 0x99, 0x57, 0x63, 0x80, 0xf0, 0x84, 0xeb, 0x62, 0xe4, 0x6a, 0x57, 0xd5, 0x54, 0x27, 0x8b, 0x53, 0x56, 0x26, 0x19, 0x3c, 0xe0, 0x20, 0x60, 0x57, 0x5e, 0xb6, 0x6c, 0x57, 0x98, 0xd3, 0x6f, 0x6c, 0x5d, 0x40, 0xfb, 0x00, 0xd8, 0x09, 0xb4, 0x2a, 0x73, 0x10, 0x2c, 0x1c, 0x74, 0xee, 0x95, 0xbd, 0x71, 0x42, 0x0f, 0xff, 0xef, 0x63, 0x18, 0xb5, 0x2c, 0x29 } +, + /* Prime p */ + 65, + { 0x07, 0xee, 0xfb, 0x42, 0x4b, 0x0e, 0x3a, 0x40, 0xe4, 0x20, 0x8e, 0xe5, 0xaf, 0xb2, 0x80, 0xb2, 0x23, 0x17, 0x30, 0x81, 0x14, 0xdd, 0xe0, 0xb4, 0xb6, 0x4f, 0x73, 0x01, 0x84, 0xec, 0x68, 0xda, 0x6c, 0xe2, 0x86, 0x7a, 0x9f, 0x48, 0xed, 0x77, 0x26, 0xd5, 0xe2, 0x61, 0x4e, 0xd0, 0x4a, 0x54, 0x10, 0x73, 0x6c, 0x8c, 0x71, 0x4e, 0xe7, 0x02, 0x47, 0x42, 0x98, 0xc6, 0x29, 0x2a, 0xf0, 0x75, 0x35 } +, + /* Prime q */ + 65, + { 0x07, 0x08, 0x30, 0xdb, 0xf9, 0x47, 0xea, 0xc0, 0x22, 0x8d, 0xe2, 0x63, 0x14, 0xb5, 0x9b, 0x66, 0x99, 0x4c, 0xc6, 0x0e, 0x83, 0x60, 0xe7, 0x5d, 0x38, 0x76, 0x29, 0x8f, 0x8f, 0x8a, 0x7d, 0x14, 0x1d, 0xa0, 0x64, 0xe5, 0xca, 0x02, 0x6a, 0x97, 0x3e, 0x28, 0xf2, 0x54, 0x73, 0x8c, 0xee, 0x66, 0x9c, 0x72, 0x1b, 0x03, 0x4c, 0xb5, 0xf8, 0xe2, 0x44, 0xda, 0xdd, 0x7c, 0xd1, 0xe1, 0x59, 0xd5, 0x47 } +, + /* p's CRT exponent dP */ + 65, + { 0x05, 0x24, 0xd2, 0x0c, 0x3d, 0x95, 0xcf, 0xf7, 0x5a, 0xf2, 0x31, 0x34, 0x83, 0x22, 0x7d, 0x87, 0x02, 0x71, 0x7a, 0xa5, 0x76, 0xde, 0x15, 0x5f, 0x96, 0x05, 0x15, 0x50, 0x1a, 0xdb, 0x1d, 0x70, 0xe1, 0xc0, 0x4d, 0xe9, 0x1b, 0x75, 0xb1, 0x61, 0xdb, 0xf0, 0x39, 0x83, 0x56, 0x12, 0x7e, 0xde, 0xda, 0x7b, 0xbc, 0x19, 0xa3, 0x2d, 0xc1, 0x62, 0x1c, 0xc9, 0xf5, 0x3c, 0x26, 0x5d, 0x0c, 0xe3, 0x31 } +, + /* q's CRT exponent dQ */ + 65, + { 0x05, 0xf9, 0x84, 0xa1, 0xf2, 0x3c, 0x93, 0x8d, 0x6a, 0x0e, 0x89, 0x72, 0x4b, 0xcf, 0x3d, 0xd9, 0x3f, 0x99, 0x46, 0x92, 0x60, 0x37, 0xfe, 0x7c, 0x6b, 0x13, 0xa2, 0x9e, 0x52, 0x84, 0x85, 0x5f, 0x89, 0x08, 0x95, 0x91, 0xd4, 0x40, 0x97, 0x56, 0x27, 0xbf, 0x5c, 0x9e, 0x3a, 0x8b, 0x5c, 0xa7, 0x9c, 0x77, 0x2a, 0xd2, 0x73, 0xe4, 0x0d, 0x32, 0x1a, 0xf4, 0xa6, 0xc9, 0x7d, 0xfd, 0xed, 0x78, 0xd3 } +, + /* CRT coefficient qInv */ + 64, + { 0xdd, 0xd9, 0x18, 0xad, 0xad, 0xa2, 0x9d, 0xca, 0xb9, 0x81, 0xff, 0x9a, 0xcb, 0xa4, 0x25, 0x70, 0x23, 0xc0, 0x9a, 0x38, 0x01, 0xcc, 0xce, 0x09, 0x8c, 0xe2, 0x68, 0xf8, 0x55, 0xd0, 0xdf, 0x57, 0x0c, 0xd6, 0xe7, 0xb9, 0xb1, 0x4b, 0xd9, 0xa5, 0xa9, 0x25, 0x4c, 0xbc, 0x31, 0x5b, 0xe6, 0xf8, 0xba, 0x1e, 0x25, 0x46, 0xdd, 0xd5, 0x69, 0xc5, 0xea, 0x19, 0xee, 0xd8, 0x35, 0x3b, 0xde, 0x5e } + +} +, +{{ + "RSASSA-PSS Signature Example 7.1", + /* Message to be signed */ + 255, + { 0x9e, 0xad, 0x0e, 0x01, 0x94, 0x56, 0x40, 0x67, 0x4e, 0xb4, 0x1c, 0xad, 0x43, 0x5e, 0x23, 0x74, 0xea, 0xef, 0xa8, 0xad, 0x71, 0x97, 0xd9, 0x79, 0x13, 0xc4, 0x49, 0x57, 0xd8, 0xd8, 0x3f, 0x40, 0xd7, 0x6e, 0xe6, 0x0e, 0x39, 0xbf, 0x9c, 0x0f, 0x9e, 0xaf, 0x30, 0x21, 0x42, 0x1a, 0x07, 0x4d, 0x1a, 0xde, 0x96, 0x2c, 0x6e, 0x9d, 0x3d, 0xc3, 0xbb, 0x17, 0x4f, 0xe4, 0xdf, 0xe6, 0x52, 0xb0, 0x91, 0x15, 0x49, 0x5b, 0x8f, 0xd2, 0x79, 0x41, 0x74, 0x02, 0x0a, 0x06, 0x02, 0xb5, 0xca, 0x51, 0x84, 0x8c, 0xfc, 0x96, 0xce, 0x5e, 0xb5, 0x7f, 0xc0, 0xa2, 0xad, 0xc1, 0xdd, 0xa3, 0x6a, 0x7c, 0xc4, 0x52, 0x64, 0x1a, 0x14, 0x91, 0x1b, 0x37, 0xe4, 0x5b, 0xfa, 0x11, 0xda, 0xa5, 0xc7, 0xec, 0xdb, 0x74, 0xf6, 0xd0, 0x10, 0x0d, 0x1d, 0x3e, 0x39, 0xe7, 0x52, 0x80, 0x0e, 0x20, 0x33, 0x97, 0xde, 0x02, 0x33, 0x07, 0x7b, 0x9a, 0x88, 0x85, 0x55, 0x37, 0xfa, 0xe9, 0x27, 0xf9, 0x24, 0x38, 0x0d, 0x78, 0x0f, 0x98, 0xe1, 0x8d, 0xcf, 0xf3, 0x9c, 0x5e, 0xa7, 0x41, 0xb1, 0x7d, 0x6f, 0xdd, 0x18, 0x85, 0xbc, 0x9d, 0x58, 0x14, 0x82, 0xd7, 0x71, 0xce, 0xb5, 0x62, 0xd7, 0x8a, 0x8b, 0xf8, 0x8f, 0x0c, 0x75, 0xb1, 0x13, 0x63, 0xe5, 0xe3, 0x6c, 0xd4, 0x79, 0xce, 0xb0, 0x54, 0x5f, 0x9d, 0xa8, 0x42, 0x03, 0xe0, 0xe6, 0xe5, 0x08, 0x37, 0x5c, 0xc9, 0xe8, 0x44, 0xb8, 0x8b, 0x7a, 0xc7, 0xa0, 0xa2, 0x01, 0xea, 0x0f, 0x1b, 0xee, 0x9a, 0x2c, 0x57, 0x79, 0x20, 0xca, 0x02, 0xc0, 0x1b, 0x9d, 0x83, 0x20, 0xe9, 0x74, 0xa5, 0x6f, 0x4e, 0xfb, 0x57, 0x63, 0xb9, 0x62, 0x55, 0xab, 0xbf, 0x80, 0x37, 0xbf, 0x18, 0x02, 0xcf, 0x01, 0x8f, 0x56, 0x37, 0x94, 0x93, 0xe5, 0x69, 0xa9 } +, + /* Salt */ + 20, + { 0xb7, 0x86, 0x7a, 0x59, 0x95, 0x8c, 0xb5, 0x43, 0x28, 0xf8, 0x77, 0x5e, 0x65, 0x46, 0xec, 0x06, 0xd2, 0x7e, 0xaa, 0x50 } +, + /* Signature */ + 129, + { 0x18, 0x7f, 0x39, 0x07, 0x23, 0xc8, 0x90, 0x25, 0x91, 0xf0, 0x15, 0x4b, 0xae, 0x6d, 0x4e, 0xcb, 0xff, 0xe0, 0x67, 0xf0, 0xe8, 0xb7, 0x95, 0x47, 0x6e, 0xa4, 0xf4, 0xd5, 0x1c, 0xcc, 0x81, 0x05, 0x20, 0xbb, 0x3c, 0xa9, 0xbc, 0xa7, 0xd0, 0xb1, 0xf2, 0xea, 0x8a, 0x17, 0xd8, 0x73, 0xfa, 0x27, 0x57, 0x0a, 0xcd, 0x64, 0x2e, 0x38, 0x08, 0x56, 0x1c, 0xb9, 0xe9, 0x75, 0xcc, 0xfd, 0x80, 0xb2, 0x3d, 0xc5, 0x77, 0x1c, 0xdb, 0x33, 0x06, 0xa5, 0xf2, 0x31, 0x59, 0xda, 0xcb, 0xd3, 0xaa, 0x2d, 0xb9, 0x3d, 0x46, 0xd7, 0x66, 0xe0, 0x9e, 0xd1, 0x5d, 0x90, 0x0a, 0xd8, 0x97, 0xa8, 0xd2, 0x74, 0xdc, 0x26, 0xb4, 0x7e, 0x99, 0x4a, 0x27, 0xe9, 0x7e, 0x22, 0x68, 0xa7, 0x66, 0x53, 0x3a, 0xe4, 0xb5, 0xe4, 0x2a, 0x2f, 0xca, 0xf7, 0x55, 0xc1, 0xc4, 0x79, 0x4b, 0x29, 0x4c, 0x60, 0x55, 0x58, 0x23 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 7.2", + /* Message to be signed */ + 57, + { 0x8d, 0x80, 0xd2, 0xd0, 0x8d, 0xbd, 0x19, 0xc1, 0x54, 0xdf, 0x3f, 0x14, 0x67, 0x3a, 0x14, 0xbd, 0x03, 0x73, 0x52, 0x31, 0xf2, 0x4e, 0x86, 0xbf, 0x15, 0x3d, 0x0e, 0x69, 0xe7, 0x4c, 0xbf, 0xf7, 0xb1, 0x83, 0x6e, 0x66, 0x4d, 0xe8, 0x3f, 0x68, 0x01, 0x24, 0x37, 0x0f, 0xc0, 0xf9, 0x6c, 0x9b, 0x65, 0xc0, 0x7a, 0x36, 0x6b, 0x64, 0x4c, 0x4a, 0xb3 } +, + /* Salt */ + 20, + { 0x0c, 0x09, 0x58, 0x22, 0x66, 0xdf, 0x08, 0x63, 0x10, 0x82, 0x1b, 0xa7, 0xe1, 0x8d, 0xf6, 0x4d, 0xfe, 0xe6, 0xde, 0x09 } +, + /* Signature */ + 129, + { 0x10, 0xfd, 0x89, 0x76, 0x8a, 0x60, 0xa6, 0x77, 0x88, 0xab, 0xb5, 0x85, 0x6a, 0x78, 0x7c, 0x85, 0x61, 0xf3, 0xed, 0xcf, 0x9a, 0x83, 0xe8, 0x98, 0xf7, 0xdc, 0x87, 0xab, 0x8c, 0xce, 0x79, 0x42, 0x9b, 0x43, 0xe5, 0x69, 0x06, 0x94, 0x1a, 0x88, 0x61, 0x94, 0xf1, 0x37, 0xe5, 0x91, 0xfe, 0x7c, 0x33, 0x95, 0x55, 0x36, 0x1f, 0xbb, 0xe1, 0xf2, 0x4f, 0xeb, 0x2d, 0x4b, 0xcd, 0xb8, 0x06, 0x01, 0xf3, 0x09, 0x6b, 0xc9, 0x13, 0x2d, 0xee, 0xa6, 0x0a, 0xe1, 0x30, 0x82, 0xf4, 0x4f, 0x9a, 0xd4, 0x1c, 0xd6, 0x28, 0x93, 0x6a, 0x4d, 0x51, 0x17, 0x6e, 0x42, 0xfc, 0x59, 0xcb, 0x76, 0xdb, 0x81, 0x5c, 0xe5, 0xab, 0x4d, 0xb9, 0x9a, 0x10, 0x4a, 0xaf, 0xea, 0x68, 0xf5, 0xd3, 0x30, 0x32, 0x9e, 0xbf, 0x25, 0x8d, 0x4e, 0xde, 0x16, 0x06, 0x4b, 0xd1, 0xd0, 0x03, 0x93, 0xd5, 0xe1, 0x57, 0x0e, 0xb8 } + +} +, +{ + "RSASSA-PSS Signature Example 7.3", + /* Message to be signed */ + 92, + { 0x80, 0x84, 0x05, 0xcd, 0xfc, 0x1a, 0x58, 0xb9, 0xbb, 0x03, 0x97, 0xc7, 0x20, 0x72, 0x2a, 0x81, 0xff, 0xfb, 0x76, 0x27, 0x8f, 0x33, 0x59, 0x17, 0xef, 0x9c, 0x47, 0x38, 0x14, 0xb3, 0xe0, 0x16, 0xba, 0x29, 0x73, 0xcd, 0x27, 0x65, 0xf8, 0xf3, 0xf8, 0x2d, 0x6c, 0xc3, 0x8a, 0xa7, 0xf8, 0x55, 0x18, 0x27, 0xfe, 0x8d, 0x1e, 0x38, 0x84, 0xb7, 0xe6, 0x1c, 0x94, 0x68, 0x3b, 0x8f, 0x82, 0xf1, 0x84, 0x3b, 0xda, 0xe2, 0x25, 0x7e, 0xee, 0xc9, 0x81, 0x2a, 0xd4, 0xc2, 0xcf, 0x28, 0x3c, 0x34, 0xe0, 0xb0, 0xae, 0x0f, 0xe3, 0xcb, 0x99, 0x0c, 0xf8, 0x8f, 0x2e, 0xf9 } +, + /* Salt */ + 20, + { 0x28, 0x03, 0x9d, 0xcf, 0xe1, 0x06, 0xd3, 0xb8, 0x29, 0x66, 0x11, 0x25, 0x8c, 0x4a, 0x56, 0x65, 0x1c, 0x9e, 0x92, 0xdd } +, + /* Signature */ + 129, + { 0x2b, 0x31, 0xfd, 0xe9, 0x98, 0x59, 0xb9, 0x77, 0xaa, 0x09, 0x58, 0x6d, 0x8e, 0x27, 0x46, 0x62, 0xb2, 0x5a, 0x2a, 0x64, 0x06, 0x40, 0xb4, 0x57, 0xf5, 0x94, 0x05, 0x1c, 0xb1, 0xe7, 0xf7, 0xa9, 0x11, 0x86, 0x54, 0x55, 0x24, 0x29, 0x26, 0xcf, 0x88, 0xfe, 0x80, 0xdf, 0xa3, 0xa7, 0x5b, 0xa9, 0x68, 0x98, 0x44, 0xa1, 0x1e, 0x63, 0x4a, 0x82, 0xb0, 0x75, 0xaf, 0xbd, 0x69, 0xc1, 0x2a, 0x0d, 0xf9, 0xd2, 0x5f, 0x84, 0xad, 0x49, 0x45, 0xdf, 0x3d, 0xc8, 0xfe, 0x90, 0xc3, 0xce, 0xfd, 0xf2, 0x6e, 0x95, 0xf0, 0x53, 0x43, 0x04, 0xb5, 0xbd, 0xba, 0x20, 0xd3, 0xe5, 0x64, 0x0a, 0x2e, 0xbf, 0xb8, 0x98, 0xaa, 0xc3, 0x5a, 0xe4, 0x0f, 0x26, 0xfc, 0xe5, 0x56, 0x3c, 0x2f, 0x9f, 0x24, 0xf3, 0x04, 0x2a, 0xf7, 0x6f, 0x3c, 0x70, 0x72, 0xd6, 0x87, 0xbb, 0xfb, 0x95, 0x9a, 0x88, 0x46, 0x0a, 0xf1 } + +} +, +{ + "RSASSA-PSS Signature Example 7.4", + /* Message to be signed */ + 231, + { 0xf3, 0x37, 0xb9, 0xba, 0xd9, 0x37, 0xde, 0x22, 0xa1, 0xa0, 0x52, 0xdf, 0xf1, 0x11, 0x34, 0xa8, 0xce, 0x26, 0x97, 0x62, 0x02, 0x98, 0x19, 0x39, 0xb9, 0x1e, 0x07, 0x15, 0xae, 0x5e, 0x60, 0x96, 0x49, 0xda, 0x1a, 0xdf, 0xce, 0xf3, 0xf4, 0xcc, 0xa5, 0x9b, 0x23, 0x83, 0x60, 0xe7, 0xd1, 0xe4, 0x96, 0xc7, 0xbf, 0x4b, 0x20, 0x4b, 0x5a, 0xcf, 0xf9, 0xbb, 0xd6, 0x16, 0x6a, 0x1d, 0x87, 0xa3, 0x6e, 0xf2, 0x24, 0x73, 0x73, 0x75, 0x10, 0x39, 0xf8, 0xa8, 0x00, 0xb8, 0x39, 0x98, 0x07, 0xb3, 0xa8, 0x5f, 0x44, 0x89, 0x34, 0x97, 0xc0, 0xd0, 0x5f, 0xb7, 0x01, 0x7b, 0x82, 0x22, 0x81, 0x52, 0xde, 0x6f, 0x25, 0xe6, 0x11, 0x6d, 0xcc, 0x75, 0x03, 0xc7, 0x86, 0xc8, 0x75, 0xc2, 0x8f, 0x3a, 0xa6, 0x07, 0xe9, 0x4a, 0xb0, 0xf1, 0x98, 0x63, 0xab, 0x1b, 0x50, 0x73, 0x77, 0x0b, 0x0c, 0xd5, 0xf5, 0x33, 0xac, 0xde, 0x30, 0xc6, 0xfb, 0x95, 0x3c, 0xf3, 0xda, 0x68, 0x02, 0x64, 0xe3, 0x0f, 0xc1, 0x1b, 0xff, 0x9a, 0x19, 0xbf, 0xfa, 0xb4, 0x77, 0x9b, 0x62, 0x23, 0xc3, 0xfb, 0x3f, 0xe0, 0xf7, 0x1a, 0xba, 0xde, 0x4e, 0xb7, 0xc0, 0x9c, 0x41, 0xe2, 0x4c, 0x22, 0xd2, 0x3f, 0xa1, 0x48, 0xe6, 0xa1, 0x73, 0xfe, 0xb6, 0x39, 0x84, 0xd1, 0xbc, 0x6e, 0xe3, 0xa0, 0x2d, 0x91, 0x5b, 0x75, 0x2c, 0xea, 0xf9, 0x2a, 0x30, 0x15, 0xec, 0xeb, 0x38, 0xca, 0x58, 0x6c, 0x68, 0x01, 0xb3, 0x7c, 0x34, 0xce, 0xfb, 0x2c, 0xff, 0x25, 0xea, 0x23, 0xc0, 0x86, 0x62, 0xdc, 0xab, 0x26, 0xa7, 0xa9, 0x3a, 0x28, 0x5d, 0x05, 0xd3, 0x04, 0x4c } +, + /* Salt */ + 20, + { 0xa7, 0x78, 0x21, 0xeb, 0xbb, 0xef, 0x24, 0x62, 0x8e, 0x4e, 0x12, 0xe1, 0xd0, 0xea, 0x96, 0xde, 0x39, 0x8f, 0x7b, 0x0f } +, + /* Signature */ + 129, + { 0x32, 0xc7, 0xca, 0x38, 0xff, 0x26, 0x94, 0x9a, 0x15, 0x00, 0x0c, 0x4b, 0xa0, 0x4b, 0x2b, 0x13, 0xb3, 0x5a, 0x38, 0x10, 0xe5, 0x68, 0x18, 0x4d, 0x7e, 0xca, 0xba, 0xa1, 0x66, 0xb7, 0xff, 0xab, 0xdd, 0xf2, 0xb6, 0xcf, 0x4b, 0xa0, 0x71, 0x24, 0x92, 0x37, 0x90, 0xf2, 0xe5, 0xb1, 0xa5, 0xbe, 0x04, 0x0a, 0xea, 0x36, 0xfe, 0x13, 0x2e, 0xc1, 0x30, 0xe1, 0xf1, 0x05, 0x67, 0x98, 0x2d, 0x17, 0xac, 0x3e, 0x89, 0xb8, 0xd2, 0x6c, 0x30, 0x94, 0x03, 0x4e, 0x76, 0x2d, 0x2e, 0x03, 0x12, 0x64, 0xf0, 0x11, 0x70, 0xbe, 0xec, 0xb3, 0xd1, 0x43, 0x9e, 0x05, 0x84, 0x6f, 0x25, 0x45, 0x83, 0x67, 0xa7, 0xd9, 0xc0, 0x20, 0x60, 0x44, 0x46, 0x72, 0x67, 0x1e, 0x64, 0xe8, 0x77, 0x86, 0x45, 0x59, 0xca, 0x19, 0xb2, 0x07, 0x4d, 0x58, 0x8a, 0x28, 0x1b, 0x58, 0x04, 0xd2, 0x37, 0x72, 0xfb, 0xbe, 0x19 } + +} +, +{ + "RSASSA-PSS Signature Example 7.5", + /* Message to be signed */ + 51, + { 0x45, 0x01, 0x3c, 0xeb, 0xaf, 0xd9, 0x60, 0xb2, 0x55, 0x47, 0x6a, 0x8e, 0x25, 0x98, 0xb9, 0xaa, 0x32, 0xef, 0xbe, 0x6d, 0xc1, 0xf3, 0x4f, 0x4a, 0x49, 0x8d, 0x8c, 0xf5, 0xa2, 0xb4, 0x54, 0x8d, 0x08, 0xc5, 0x5d, 0x5f, 0x95, 0xf7, 0xbc, 0xc9, 0x61, 0x91, 0x63, 0x05, 0x6f, 0x2d, 0x58, 0xb5, 0x2f, 0xa0, 0x32 } +, + /* Salt */ + 20, + { 0x9d, 0x5a, 0xd8, 0xeb, 0x45, 0x21, 0x34, 0xb6, 0x5d, 0xc3, 0xa9, 0x8b, 0x6a, 0x73, 0xb5, 0xf7, 0x41, 0x60, 0x9c, 0xd6 } +, + /* Signature */ + 129, + { 0x07, 0xeb, 0x65, 0x1d, 0x75, 0xf1, 0xb5, 0x2b, 0xc2, 0x63, 0xb2, 0xe1, 0x98, 0x33, 0x6e, 0x99, 0xfb, 0xeb, 0xc4, 0xf3, 0x32, 0x04, 0x9a, 0x92, 0x2a, 0x10, 0x81, 0x56, 0x07, 0xee, 0x2d, 0x98, 0x9d, 0xb3, 0xa4, 0x49, 0x5b, 0x7d, 0xcc, 0xd3, 0x8f, 0x58, 0xa2, 0x11, 0xfb, 0x7e, 0x19, 0x31, 0x71, 0xa3, 0xd8, 0x91, 0x13, 0x24, 0x37, 0xeb, 0xca, 0x44, 0xf3, 0x18, 0xb2, 0x80, 0x50, 0x9e, 0x52, 0xb5, 0xfa, 0x98, 0xfc, 0xce, 0x82, 0x05, 0xd9, 0x69, 0x7c, 0x8e, 0xe4, 0xb7, 0xff, 0x59, 0xd4, 0xc5, 0x9c, 0x79, 0x03, 0x8a, 0x19, 0x70, 0xbd, 0x2a, 0x0d, 0x45, 0x1e, 0xcd, 0xc5, 0xef, 0x11, 0xd9, 0x97, 0x9c, 0x9d, 0x35, 0xf8, 0xc7, 0x0a, 0x61, 0x63, 0x71, 0x76, 0x07, 0x89, 0x0d, 0x58, 0x6a, 0x7c, 0x6d, 0xc0, 0x1c, 0x79, 0xf8, 0x6a, 0x8f, 0x28, 0xe8, 0x52, 0x35, 0xf8, 0xc2, 0xf1 } + +} +, +{ + "RSASSA-PSS Signature Example 7.6", + /* Message to be signed */ + 184, + { 0x23, 0x58, 0x09, 0x70, 0x86, 0xc8, 0x99, 0x32, 0x3e, 0x75, 0xd9, 0xc9, 0x0d, 0x0c, 0x09, 0xf1, 0x2d, 0x9d, 0x54, 0xed, 0xfb, 0xdf, 0x70, 0xa9, 0xc2, 0xeb, 0x5a, 0x04, 0xd8, 0xf3, 0x6b, 0x9b, 0x2b, 0xdf, 0x2a, 0xab, 0xe0, 0xa5, 0xbd, 0xa1, 0x96, 0x89, 0x37, 0xf9, 0xd6, 0xeb, 0xd3, 0xb6, 0xb2, 0x57, 0xef, 0xb3, 0x13, 0x6d, 0x41, 0x31, 0xf9, 0xac, 0xb5, 0x9b, 0x85, 0xe2, 0x60, 0x2c, 0x2a, 0x3f, 0xcd, 0xc8, 0x35, 0x49, 0x4a, 0x1f, 0x4e, 0x5e, 0xc1, 0x8b, 0x22, 0x6c, 0x80, 0x23, 0x2b, 0x36, 0xa7, 0x5a, 0x45, 0xfd, 0xf0, 0x9a, 0x7e, 0xa9, 0xe9, 0x8e, 0xfb, 0xde, 0x14, 0x50, 0xd1, 0x19, 0x4b, 0xf1, 0x2e, 0x15, 0xa4, 0xc5, 0xf9, 0xeb, 0x5c, 0x0b, 0xce, 0x52, 0x69, 0xe0, 0xc3, 0xb2, 0x8c, 0xfa, 0xb6, 0x55, 0xd8, 0x1a, 0x61, 0xa2, 0x0b, 0x4b, 0xe2, 0xf5, 0x44, 0x59, 0xbb, 0x25, 0xa0, 0xdb, 0x94, 0xc5, 0x22, 0x18, 0xbe, 0x10, 0x9a, 0x74, 0x26, 0xde, 0x83, 0x01, 0x44, 0x24, 0x78, 0x9a, 0xaa, 0x90, 0xe5, 0x05, 0x6e, 0x63, 0x2a, 0x69, 0x81, 0x15, 0xe2, 0x82, 0xc1, 0xa5, 0x64, 0x10, 0xf2, 0x6c, 0x20, 0x72, 0xf1, 0x93, 0x48, 0x1a, 0x9d, 0xcd, 0x88, 0x05, 0x72, 0x00, 0x5e, 0x64, 0xf4, 0x08, 0x2e, 0xcf } +, + /* Salt */ + 20, + { 0x3f, 0x2e, 0xfc, 0x59, 0x58, 0x80, 0xa7, 0xd4, 0x7f, 0xcf, 0x3c, 0xba, 0x04, 0x98, 0x3e, 0xa5, 0x4c, 0x4b, 0x73, 0xfb } +, + /* Signature */ + 129, + { 0x18, 0xda, 0x3c, 0xdc, 0xfe, 0x79, 0xbf, 0xb7, 0x7f, 0xd9, 0xc3, 0x2f, 0x37, 0x7a, 0xd3, 0x99, 0x14, 0x6f, 0x0a, 0x8e, 0x81, 0x06, 0x20, 0x23, 0x32, 0x71, 0xa6, 0xe3, 0xed, 0x32, 0x48, 0x90, 0x3f, 0x5c, 0xdc, 0x92, 0xdc, 0x79, 0xb5, 0x5d, 0x3e, 0x11, 0x61, 0x5a, 0xa0, 0x56, 0xa7, 0x95, 0x85, 0x37, 0x92, 0xa3, 0x99, 0x8c, 0x34, 0x9c, 0xa5, 0xc4, 0x57, 0xe8, 0xca, 0x7d, 0x29, 0xd7, 0x96, 0xaa, 0x24, 0xf8, 0x34, 0x91, 0x70, 0x9b, 0xef, 0xcf, 0xb1, 0x51, 0x0e, 0xa5, 0x13, 0xc9, 0x28, 0x29, 0xa3, 0xf0, 0x0b, 0x10, 0x4f, 0x65, 0x56, 0x34, 0xf3, 0x20, 0x75, 0x2e, 0x13, 0x0e, 0xc0, 0xcc, 0xf6, 0x75, 0x4f, 0xf8, 0x93, 0xdb, 0x30, 0x29, 0x32, 0xbb, 0x02, 0x5e, 0xb6, 0x0e, 0x87, 0x82, 0x25, 0x98, 0xfc, 0x61, 0x9e, 0x0e, 0x98, 0x17, 0x37, 0xa9, 0xa4, 0xc4, 0x15, 0x2d, 0x33 } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 8: A 1031-bit RSA Key Pair", +{ + /* RSA modulus n */ + 129, + { 0x49, 0x53, 0x70, 0xa1, 0xfb, 0x18, 0x54, 0x3c, 0x16, 0xd3, 0x63, 0x1e, 0x31, 0x63, 0x25, 0x5d, 0xf6, 0x2b, 0xe6, 0xee, 0xe8, 0x90, 0xd5, 0xf2, 0x55, 0x09, 0xe4, 0xf7, 0x78, 0xa8, 0xea, 0x6f, 0xbb, 0xbc, 0xdf, 0x85, 0xdf, 0xf6, 0x4e, 0x0d, 0x97, 0x20, 0x03, 0xab, 0x36, 0x81, 0xfb, 0xba, 0x6d, 0xd4, 0x1f, 0xd5, 0x41, 0x82, 0x9b, 0x2e, 0x58, 0x2d, 0xe9, 0xf2, 0xa4, 0xa4, 0xe0, 0xa2, 0xd0, 0x90, 0x0b, 0xef, 0x47, 0x53, 0xdb, 0x3c, 0xee, 0x0e, 0xe0, 0x6c, 0x7d, 0xfa, 0xe8, 0xb1, 0xd5, 0x3b, 0x59, 0x53, 0x21, 0x8f, 0x9c, 0xce, 0xea, 0x69, 0x5b, 0x08, 0x66, 0x8e, 0xde, 0xaa, 0xdc, 0xed, 0x94, 0x63, 0xb1, 0xd7, 0x90, 0xd5, 0xeb, 0xf2, 0x7e, 0x91, 0x15, 0xb4, 0x6c, 0xad, 0x4d, 0x9a, 0x2b, 0x8e, 0xfa, 0xb0, 0x56, 0x1b, 0x08, 0x10, 0x34, 0x47, 0x39, 0xad, 0xa0, 0x73, 0x3f } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 128, + { 0x6c, 0x66, 0xff, 0xe9, 0x89, 0x80, 0xc3, 0x8f, 0xcd, 0xea, 0xb5, 0x15, 0x98, 0x98, 0x83, 0x61, 0x65, 0xf4, 0xb4, 0xb8, 0x17, 0xc4, 0xf6, 0xa8, 0xd4, 0x86, 0xee, 0x4e, 0xa9, 0x13, 0x0f, 0xe9, 0xb9, 0x09, 0x2b, 0xd1, 0x36, 0xd1, 0x84, 0xf9, 0x5f, 0x50, 0x4a, 0x60, 0x7e, 0xac, 0x56, 0x58, 0x46, 0xd2, 0xfd, 0xd6, 0x59, 0x7a, 0x89, 0x67, 0xc7, 0x39, 0x6e, 0xf9, 0x5a, 0x6e, 0xee, 0xbb, 0x45, 0x78, 0xa6, 0x43, 0x96, 0x6d, 0xca, 0x4d, 0x8e, 0xe3, 0xde, 0x84, 0x2d, 0xe6, 0x32, 0x79, 0xc6, 0x18, 0x15, 0x9c, 0x1a, 0xb5, 0x4a, 0x89, 0x43, 0x7b, 0x6a, 0x61, 0x20, 0xe4, 0x93, 0x0a, 0xfb, 0x52, 0xa4, 0xba, 0x6c, 0xed, 0x8a, 0x49, 0x47, 0xac, 0x64, 0xb3, 0x0a, 0x34, 0x97, 0xcb, 0xe7, 0x01, 0xc2, 0xd6, 0x26, 0x6d, 0x51, 0x72, 0x19, 0xad, 0x0e, 0xc6, 0xd3, 0x47, 0xdb, 0xe9 } +, + /* Prime p */ + 65, + { 0x08, 0xda, 0xd7, 0xf1, 0x13, 0x63, 0xfa, 0xa6, 0x23, 0xd5, 0xd6, 0xd5, 0xe8, 0xa3, 0x19, 0x32, 0x8d, 0x82, 0x19, 0x0d, 0x71, 0x27, 0xd2, 0x84, 0x6c, 0x43, 0x9b, 0x0a, 0xb7, 0x26, 0x19, 0xb0, 0xa4, 0x3a, 0x95, 0x32, 0x0e, 0x4e, 0xc3, 0x4f, 0xc3, 0xa9, 0xce, 0xa8, 0x76, 0x42, 0x23, 0x05, 0xbd, 0x76, 0xc5, 0xba, 0x7b, 0xe9, 0xe2, 0xf4, 0x10, 0xc8, 0x06, 0x06, 0x45, 0xa1, 0xd2, 0x9e, 0xdb } +, + /* Prime q */ + 65, + { 0x08, 0x47, 0xe7, 0x32, 0x37, 0x6f, 0xc7, 0x90, 0x0f, 0x89, 0x8e, 0xa8, 0x2e, 0xb2, 0xb0, 0xfc, 0x41, 0x85, 0x65, 0xfd, 0xae, 0x62, 0xf7, 0xd9, 0xec, 0x4c, 0xe2, 0x21, 0x7b, 0x97, 0x99, 0x0d, 0xd2, 0x72, 0xdb, 0x15, 0x7f, 0x99, 0xf6, 0x3c, 0x0d, 0xcb, 0xb9, 0xfb, 0xac, 0xdb, 0xd4, 0xc4, 0xda, 0xdb, 0x6d, 0xf6, 0x77, 0x56, 0x35, 0x8c, 0xa4, 0x17, 0x48, 0x25, 0xb4, 0x8f, 0x49, 0x70, 0x6d } +, + /* p's CRT exponent dP */ + 65, + { 0x05, 0xc2, 0xa8, 0x3c, 0x12, 0x4b, 0x36, 0x21, 0xa2, 0xaa, 0x57, 0xea, 0x2c, 0x3e, 0xfe, 0x03, 0x5e, 0xff, 0x45, 0x60, 0xf3, 0x3d, 0xde, 0xbb, 0x7a, 0xda, 0xb8, 0x1f, 0xce, 0x69, 0xa0, 0xc8, 0xc2, 0xed, 0xc1, 0x65, 0x20, 0xdd, 0xa8, 0x3d, 0x59, 0xa2, 0x3b, 0xe8, 0x67, 0x96, 0x3a, 0xc6, 0x5f, 0x2c, 0xc7, 0x10, 0xbb, 0xcf, 0xb9, 0x6e, 0xe1, 0x03, 0xde, 0xb7, 0x71, 0xd1, 0x05, 0xfd, 0x85 } +, + /* q's CRT exponent dQ */ + 65, + { 0x04, 0xca, 0xe8, 0xaa, 0x0d, 0x9f, 0xaa, 0x16, 0x5c, 0x87, 0xb6, 0x82, 0xec, 0x14, 0x0b, 0x8e, 0xd3, 0xb5, 0x0b, 0x24, 0x59, 0x4b, 0x7a, 0x3b, 0x2c, 0x22, 0x0b, 0x36, 0x69, 0xbb, 0x81, 0x9f, 0x98, 0x4f, 0x55, 0x31, 0x0a, 0x1a, 0xe7, 0x82, 0x36, 0x51, 0xd4, 0xa0, 0x2e, 0x99, 0x44, 0x79, 0x72, 0x59, 0x51, 0x39, 0x36, 0x34, 0x34, 0xe5, 0xe3, 0x0a, 0x7e, 0x7d, 0x24, 0x15, 0x51, 0xe1, 0xb9 } +, + /* CRT coefficient qInv */ + 65, + { 0x07, 0xd3, 0xe4, 0x7b, 0xf6, 0x86, 0x60, 0x0b, 0x11, 0xac, 0x28, 0x3c, 0xe8, 0x8d, 0xbb, 0x3f, 0x60, 0x51, 0xe8, 0xef, 0xd0, 0x46, 0x80, 0xe4, 0x4c, 0x17, 0x1e, 0xf5, 0x31, 0xb8, 0x0b, 0x2b, 0x7c, 0x39, 0xfc, 0x76, 0x63, 0x20, 0xe2, 0xcf, 0x15, 0xd8, 0xd9, 0x98, 0x20, 0xe9, 0x6f, 0xf3, 0x0d, 0xc6, 0x96, 0x91, 0x83, 0x9c, 0x4b, 0x40, 0xd7, 0xb0, 0x6e, 0x45, 0x30, 0x7d, 0xc9, 0x1f, 0x3f } + +} +, +{{ + "RSASSA-PSS Signature Example 8.1", + /* Message to be signed */ + 172, + { 0x81, 0x33, 0x2f, 0x4b, 0xe6, 0x29, 0x48, 0x41, 0x5e, 0xa1, 0xd8, 0x99, 0x79, 0x2e, 0xea, 0xcf, 0x6c, 0x6e, 0x1d, 0xb1, 0xda, 0x8b, 0xe1, 0x3b, 0x5c, 0xea, 0x41, 0xdb, 0x2f, 0xed, 0x46, 0x70, 0x92, 0xe1, 0xff, 0x39, 0x89, 0x14, 0xc7, 0x14, 0x25, 0x97, 0x75, 0xf5, 0x95, 0xf8, 0x54, 0x7f, 0x73, 0x56, 0x92, 0xa5, 0x75, 0xe6, 0x92, 0x3a, 0xf7, 0x8f, 0x22, 0xc6, 0x99, 0x7d, 0xdb, 0x90, 0xfb, 0x6f, 0x72, 0xd7, 0xbb, 0x0d, 0xd5, 0x74, 0x4a, 0x31, 0xde, 0xcd, 0x3d, 0xc3, 0x68, 0x58, 0x49, 0x83, 0x6e, 0xd3, 0x4a, 0xec, 0x59, 0x63, 0x04, 0xad, 0x11, 0x84, 0x3c, 0x4f, 0x88, 0x48, 0x9f, 0x20, 0x97, 0x35, 0xf5, 0xfb, 0x7f, 0xda, 0xf7, 0xce, 0xc8, 0xad, 0xdc, 0x58, 0x18, 0x16, 0x8f, 0x88, 0x0a, 0xcb, 0xf4, 0x90, 0xd5, 0x10, 0x05, 0xb7, 0xa8, 0xe8, 0x4e, 0x43, 0xe5, 0x42, 0x87, 0x97, 0x75, 0x71, 0xdd, 0x99, 0xee, 0xa4, 0xb1, 0x61, 0xeb, 0x2d, 0xf1, 0xf5, 0x10, 0x8f, 0x12, 0xa4, 0x14, 0x2a, 0x83, 0x32, 0x2e, 0xdb, 0x05, 0xa7, 0x54, 0x87, 0xa3, 0x43, 0x5c, 0x9a, 0x78, 0xce, 0x53, 0xed, 0x93, 0xbc, 0x55, 0x08, 0x57, 0xd7, 0xa9, 0xfb } +, + /* Salt */ + 20, + { 0x1d, 0x65, 0x49, 0x1d, 0x79, 0xc8, 0x64, 0xb3, 0x73, 0x00, 0x9b, 0xe6, 0xf6, 0xf2, 0x46, 0x7b, 0xac, 0x4c, 0x78, 0xfa } +, + /* Signature */ + 129, + { 0x02, 0x62, 0xac, 0x25, 0x4b, 0xfa, 0x77, 0xf3, 0xc1, 0xac, 0xa2, 0x2c, 0x51, 0x79, 0xf8, 0xf0, 0x40, 0x42, 0x2b, 0x3c, 0x5b, 0xaf, 0xd4, 0x0a, 0x8f, 0x21, 0xcf, 0x0f, 0xa5, 0xa6, 0x67, 0xcc, 0xd5, 0x99, 0x3d, 0x42, 0xdb, 0xaf, 0xb4, 0x09, 0xc5, 0x20, 0xe2, 0x5f, 0xce, 0x2b, 0x1e, 0xe1, 0xe7, 0x16, 0x57, 0x7f, 0x1e, 0xfa, 0x17, 0xf3, 0xda, 0x28, 0x05, 0x2f, 0x40, 0xf0, 0x41, 0x9b, 0x23, 0x10, 0x6d, 0x78, 0x45, 0xaa, 0xf0, 0x11, 0x25, 0xb6, 0x98, 0xe7, 0xa4, 0xdf, 0xe9, 0x2d, 0x39, 0x67, 0xbb, 0x00, 0xc4, 0xd0, 0xd3, 0x5b, 0xa3, 0x55, 0x2a, 0xb9, 0xa8, 0xb3, 0xee, 0xf0, 0x7c, 0x7f, 0xec, 0xdb, 0xc5, 0x42, 0x4a, 0xc4, 0xdb, 0x1e, 0x20, 0xcb, 0x37, 0xd0, 0xb2, 0x74, 0x47, 0x69, 0x94, 0x0e, 0xa9, 0x07, 0xe1, 0x7f, 0xbb, 0xca, 0x67, 0x3b, 0x20, 0x52, 0x23, 0x80, 0xc5 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 8.2", + /* Message to be signed */ + 38, + { 0xe2, 0xf9, 0x6e, 0xaf, 0x0e, 0x05, 0xe7, 0xba, 0x32, 0x6e, 0xcc, 0xa0, 0xba, 0x7f, 0xd2, 0xf7, 0xc0, 0x23, 0x56, 0xf3, 0xce, 0xde, 0x9d, 0x0f, 0xaa, 0xbf, 0x4f, 0xcc, 0x8e, 0x60, 0xa9, 0x73, 0xe5, 0x59, 0x5f, 0xd9, 0xea, 0x08 } +, + /* Salt */ + 20, + { 0x43, 0x5c, 0x09, 0x8a, 0xa9, 0x90, 0x9e, 0xb2, 0x37, 0x7f, 0x12, 0x48, 0xb0, 0x91, 0xb6, 0x89, 0x87, 0xff, 0x18, 0x38 } +, + /* Signature */ + 129, + { 0x27, 0x07, 0xb9, 0xad, 0x51, 0x15, 0xc5, 0x8c, 0x94, 0xe9, 0x32, 0xe8, 0xec, 0x0a, 0x28, 0x0f, 0x56, 0x33, 0x9e, 0x44, 0xa1, 0xb5, 0x8d, 0x4d, 0xdc, 0xff, 0x2f, 0x31, 0x2e, 0x5f, 0x34, 0xdc, 0xfe, 0x39, 0xe8, 0x9c, 0x6a, 0x94, 0xdc, 0xee, 0x86, 0xdb, 0xbd, 0xae, 0x5b, 0x79, 0xba, 0x4e, 0x08, 0x19, 0xa9, 0xe7, 0xbf, 0xd9, 0xd9, 0x82, 0xe7, 0xee, 0x6c, 0x86, 0xee, 0x68, 0x39, 0x6e, 0x8b, 0x3a, 0x14, 0xc9, 0xc8, 0xf3, 0x4b, 0x17, 0x8e, 0xb7, 0x41, 0xf9, 0xd3, 0xf1, 0x21, 0x10, 0x9b, 0xf5, 0xc8, 0x17, 0x2f, 0xad, 0xa2, 0xe7, 0x68, 0xf9, 0xea, 0x14, 0x33, 0x03, 0x2c, 0x00, 0x4a, 0x8a, 0xa0, 0x7e, 0xb9, 0x90, 0x00, 0x0a, 0x48, 0xdc, 0x94, 0xc8, 0xba, 0xc8, 0xaa, 0xbe, 0x2b, 0x09, 0xb1, 0xaa, 0x46, 0xc0, 0xa2, 0xaa, 0x0e, 0x12, 0xf6, 0x3f, 0xbb, 0xa7, 0x75, 0xba, 0x7e } + +} +, +{ + "RSASSA-PSS Signature Example 8.3", + /* Message to be signed */ + 151, + { 0xe3, 0x5c, 0x6e, 0xd9, 0x8f, 0x64, 0xa6, 0xd5, 0xa6, 0x48, 0xfc, 0xab, 0x8a, 0xdb, 0x16, 0x33, 0x1d, 0xb3, 0x2e, 0x5d, 0x15, 0xc7, 0x4a, 0x40, 0xed, 0xf9, 0x4c, 0x3d, 0xc4, 0xa4, 0xde, 0x79, 0x2d, 0x19, 0x08, 0x89, 0xf2, 0x0f, 0x1e, 0x24, 0xed, 0x12, 0x05, 0x4a, 0x6b, 0x28, 0x79, 0x8f, 0xcb, 0x42, 0xd1, 0xc5, 0x48, 0x76, 0x9b, 0x73, 0x4c, 0x96, 0x37, 0x31, 0x42, 0x09, 0x2a, 0xed, 0x27, 0x76, 0x03, 0xf4, 0x73, 0x8d, 0xf4, 0xdc, 0x14, 0x46, 0x58, 0x6d, 0x0e, 0xc6, 0x4d, 0xa4, 0xfb, 0x60, 0x53, 0x6d, 0xb2, 0xae, 0x17, 0xfc, 0x7e, 0x3c, 0x04, 0xbb, 0xfb, 0xbb, 0xd9, 0x07, 0xbf, 0x11, 0x7c, 0x08, 0x63, 0x6f, 0xa1, 0x6f, 0x95, 0xf5, 0x1a, 0x62, 0x16, 0x93, 0x4d, 0x3e, 0x34, 0xf8, 0x50, 0x30, 0xf1, 0x7b, 0xbb, 0xc5, 0xba, 0x69, 0x14, 0x40, 0x58, 0xaf, 0xf0, 0x81, 0xe0, 0xb1, 0x9c, 0xf0, 0x3c, 0x17, 0x19, 0x5c, 0x5e, 0x88, 0x8b, 0xa5, 0x8f, 0x6f, 0xe0, 0xa0, 0x2e, 0x5c, 0x3b, 0xda, 0x97, 0x19, 0xa7 } +, + /* Salt */ + 20, + { 0xc6, 0xeb, 0xbe, 0x76, 0xdf, 0x0c, 0x4a, 0xea, 0x32, 0xc4, 0x74, 0x17, 0x5b, 0x2f, 0x13, 0x68, 0x62, 0xd0, 0x45, 0x29 } +, + /* Signature */ + 129, + { 0x2a, 0xd2, 0x05, 0x09, 0xd7, 0x8c, 0xf2, 0x6d, 0x1b, 0x6c, 0x40, 0x61, 0x46, 0x08, 0x6e, 0x4b, 0x0c, 0x91, 0xa9, 0x1c, 0x2b, 0xd1, 0x64, 0xc8, 0x7b, 0x96, 0x6b, 0x8f, 0xaa, 0x42, 0xaa, 0x0c, 0xa4, 0x46, 0x02, 0x23, 0x23, 0xba, 0x4b, 0x1a, 0x1b, 0x89, 0x70, 0x6d, 0x7f, 0x4c, 0x3b, 0xe5, 0x7d, 0x7b, 0x69, 0x70, 0x2d, 0x16, 0x8a, 0xb5, 0x95, 0x5e, 0xe2, 0x90, 0x35, 0x6b, 0x8c, 0x4a, 0x29, 0xed, 0x46, 0x7d, 0x54, 0x7e, 0xc2, 0x3c, 0xba, 0xdf, 0x28, 0x6c, 0xcb, 0x58, 0x63, 0xc6, 0x67, 0x9d, 0xa4, 0x67, 0xfc, 0x93, 0x24, 0xa1, 0x51, 0xc7, 0xec, 0x55, 0xaa, 0xc6, 0xdb, 0x40, 0x84, 0xf8, 0x27, 0x26, 0x82, 0x5c, 0xfe, 0x1a, 0xa4, 0x21, 0xbc, 0x64, 0x04, 0x9f, 0xb4, 0x2f, 0x23, 0x14, 0x8f, 0x9c, 0x25, 0xb2, 0xdc, 0x30, 0x04, 0x37, 0xc3, 0x8d, 0x42, 0x8a, 0xa7, 0x5f, 0x96 } + +} +, +{ + "RSASSA-PSS Signature Example 8.4", + /* Message to be signed */ + 204, + { 0xdb, 0xc5, 0xf7, 0x50, 0xa7, 0xa1, 0x4b, 0xe2, 0xb9, 0x3e, 0x83, 0x8d, 0x18, 0xd1, 0x4a, 0x86, 0x95, 0xe5, 0x2e, 0x8a, 0xdd, 0x9c, 0x0a, 0xc7, 0x33, 0xb8, 0xf5, 0x6d, 0x27, 0x47, 0xe5, 0x29, 0xa0, 0xcc, 0xa5, 0x32, 0xdd, 0x49, 0xb9, 0x02, 0xae, 0xfe, 0xd5, 0x14, 0x44, 0x7f, 0x9e, 0x81, 0xd1, 0x61, 0x95, 0xc2, 0x85, 0x38, 0x68, 0xcb, 0x9b, 0x30, 0xf7, 0xd0, 0xd4, 0x95, 0xc6, 0x9d, 0x01, 0xb5, 0xc5, 0xd5, 0x0b, 0x27, 0x04, 0x5d, 0xb3, 0x86, 0x6c, 0x23, 0x24, 0xa4, 0x4a, 0x11, 0x0b, 0x17, 0x17, 0x74, 0x6d, 0xe4, 0x57, 0xd1, 0xc8, 0xc4, 0x5c, 0x3c, 0xd2, 0xa9, 0x29, 0x70, 0xc3, 0xd5, 0x96, 0x32, 0x05, 0x5d, 0x4c, 0x98, 0xa4, 0x1d, 0x6e, 0x99, 0xe2, 0xa3, 0xdd, 0xd5, 0xf7, 0xf9, 0x97, 0x9a, 0xb3, 0xcd, 0x18, 0xf3, 0x75, 0x05, 0xd2, 0x51, 0x41, 0xde, 0x2a, 0x1b, 0xff, 0x17, 0xb3, 0xa7, 0xdc, 0xe9, 0x41, 0x9e, 0xcc, 0x38, 0x5c, 0xf1, 0x1d, 0x72, 0x84, 0x0f, 0x19, 0x95, 0x3f, 0xd0, 0x50, 0x92, 0x51, 0xf6, 0xca, 0xfd, 0xe2, 0x89, 0x3d, 0x0e, 0x75, 0xc7, 0x81, 0xba, 0x7a, 0x50, 0x12, 0xca, 0x40, 0x1a, 0x4f, 0xa9, 0x9e, 0x04, 0xb3, 0xc3, 0x24, 0x9f, 0x92, 0x6d, 0x5a, 0xfe, 0x82, 0xcc, 0x87, 0xda, 0xb2, 0x2c, 0x3c, 0x1b, 0x10, 0x5d, 0xe4, 0x8e, 0x34, 0xac, 0xe9, 0xc9, 0x12, 0x4e, 0x59, 0x59, 0x7a, 0xc7, 0xeb, 0xf8 } +, + /* Salt */ + 20, + { 0x02, 0x1f, 0xdc, 0xc6, 0xeb, 0xb5, 0xe1, 0x9b, 0x1c, 0xb1, 0x6e, 0x9c, 0x67, 0xf2, 0x76, 0x81, 0x65, 0x7f, 0xe2, 0x0a } +, + /* Signature */ + 129, + { 0x1e, 0x24, 0xe6, 0xe5, 0x86, 0x28, 0xe5, 0x17, 0x50, 0x44, 0xa9, 0xeb, 0x6d, 0x83, 0x7d, 0x48, 0xaf, 0x12, 0x60, 0xb0, 0x52, 0x0e, 0x87, 0x32, 0x7d, 0xe7, 0x89, 0x7e, 0xe4, 0xd5, 0xb9, 0xf0, 0xdf, 0x0b, 0xe3, 0xe0, 0x9e, 0xd4, 0xde, 0xa8, 0xc1, 0x45, 0x4f, 0xf3, 0x42, 0x3b, 0xb0, 0x8e, 0x17, 0x93, 0x24, 0x5a, 0x9d, 0xf8, 0xbf, 0x6a, 0xb3, 0x96, 0x8c, 0x8e, 0xdd, 0xc3, 0xb5, 0x32, 0x85, 0x71, 0xc7, 0x7f, 0x09, 0x1c, 0xc5, 0x78, 0x57, 0x69, 0x12, 0xdf, 0xeb, 0xd1, 0x64, 0xb9, 0xde, 0x54, 0x54, 0xfe, 0x0b, 0xe1, 0xc1, 0xf6, 0x38, 0x5b, 0x32, 0x83, 0x60, 0xce, 0x67, 0xec, 0x7a, 0x05, 0xf6, 0xe3, 0x0e, 0xb4, 0x5c, 0x17, 0xc4, 0x8a, 0xc7, 0x00, 0x41, 0xd2, 0xca, 0xb6, 0x7f, 0x0a, 0x2a, 0xe7, 0xaa, 0xfd, 0xcc, 0x8d, 0x24, 0x5e, 0xa3, 0x44, 0x2a, 0x63, 0x00, 0xcc, 0xc7 } + +} +, +{ + "RSASSA-PSS Signature Example 8.5", + /* Message to be signed */ + 101, + { 0x04, 0xdc, 0x25, 0x1b, 0xe7, 0x2e, 0x88, 0xe5, 0x72, 0x34, 0x85, 0xb6, 0x38, 0x3a, 0x63, 0x7e, 0x2f, 0xef, 0xe0, 0x76, 0x60, 0xc5, 0x19, 0xa5, 0x60, 0xb8, 0xbc, 0x18, 0xbd, 0xed, 0xb8, 0x6e, 0xae, 0x23, 0x64, 0xea, 0x53, 0xba, 0x9d, 0xca, 0x6e, 0xb3, 0xd2, 0xe7, 0xd6, 0xb8, 0x06, 0xaf, 0x42, 0xb3, 0xe8, 0x7f, 0x29, 0x1b, 0x4a, 0x88, 0x81, 0xd5, 0xbf, 0x57, 0x2c, 0xc9, 0xa8, 0x5e, 0x19, 0xc8, 0x6a, 0xcb, 0x28, 0xf0, 0x98, 0xf9, 0xda, 0x03, 0x83, 0xc5, 0x66, 0xd3, 0xc0, 0xf5, 0x8c, 0xfd, 0x8f, 0x39, 0x5d, 0xcf, 0x60, 0x2e, 0x5c, 0xd4, 0x0e, 0x8c, 0x71, 0x83, 0xf7, 0x14, 0x99, 0x6e, 0x22, 0x97, 0xef } +, + /* Salt */ + 20, + { 0xc5, 0x58, 0xd7, 0x16, 0x7c, 0xbb, 0x45, 0x08, 0xad, 0xa0, 0x42, 0x97, 0x1e, 0x71, 0xb1, 0x37, 0x7e, 0xea, 0x42, 0x69 } +, + /* Signature */ + 129, + { 0x33, 0x34, 0x1b, 0xa3, 0x57, 0x6a, 0x13, 0x0a, 0x50, 0xe2, 0xa5, 0xcf, 0x86, 0x79, 0x22, 0x43, 0x88, 0xd5, 0x69, 0x3f, 0x5a, 0xcc, 0xc2, 0x35, 0xac, 0x95, 0xad, 0xd6, 0x8e, 0x5e, 0xb1, 0xee, 0xc3, 0x16, 0x66, 0xd0, 0xca, 0x7a, 0x1c, 0xda, 0x6f, 0x70, 0xa1, 0xaa, 0x76, 0x2c, 0x05, 0x75, 0x2a, 0x51, 0x95, 0x0c, 0xdb, 0x8a, 0xf3, 0xc5, 0x37, 0x9f, 0x18, 0xcf, 0xe6, 0xb5, 0xbc, 0x55, 0xa4, 0x64, 0x82, 0x26, 0xa1, 0x5e, 0x91, 0x2e, 0xf1, 0x9a, 0xd7, 0x7a, 0xde, 0xea, 0x91, 0x1d, 0x67, 0xcf, 0xef, 0xd6, 0x9b, 0xa4, 0x3f, 0xa4, 0x11, 0x91, 0x35, 0xff, 0x64, 0x21, 0x17, 0xba, 0x98, 0x5a, 0x7e, 0x01, 0x00, 0x32, 0x5e, 0x95, 0x19, 0xf1, 0xca, 0x6a, 0x92, 0x16, 0xbd, 0xa0, 0x55, 0xb5, 0x78, 0x50, 0x15, 0x29, 0x11, 0x25, 0xe9, 0x0d, 0xcd, 0x07, 0xa2, 0xca, 0x96, 0x73, 0xee } + +} +, +{ + "RSASSA-PSS Signature Example 8.6", + /* Message to be signed */ + 132, + { 0x0e, 0xa3, 0x7d, 0xf9, 0xa6, 0xfe, 0xa4, 0xa8, 0xb6, 0x10, 0x37, 0x3c, 0x24, 0xcf, 0x39, 0x0c, 0x20, 0xfa, 0x6e, 0x21, 0x35, 0xc4, 0x00, 0xc8, 0xa3, 0x4f, 0x5c, 0x18, 0x3a, 0x7e, 0x8e, 0xa4, 0xc9, 0xae, 0x09, 0x0e, 0xd3, 0x17, 0x59, 0xf4, 0x2d, 0xc7, 0x77, 0x19, 0xcc, 0xa4, 0x00, 0xec, 0xdc, 0xc5, 0x17, 0xac, 0xfc, 0x7a, 0xc6, 0x90, 0x26, 0x75, 0xb2, 0xef, 0x30, 0xc5, 0x09, 0x66, 0x5f, 0x33, 0x21, 0x48, 0x2f, 0xc6, 0x9a, 0x9f, 0xb5, 0x70, 0xd1, 0x5e, 0x01, 0xc8, 0x45, 0xd0, 0xd8, 0xe5, 0x0d, 0x2a, 0x24, 0xcb, 0xf1, 0xcf, 0x0e, 0x71, 0x49, 0x75, 0xa5, 0xdb, 0x7b, 0x18, 0xd9, 0xe9, 0xe9, 0xcb, 0x91, 0xb5, 0xcb, 0x16, 0x86, 0x90, 0x60, 0xed, 0x18, 0xb7, 0xb5, 0x62, 0x45, 0x50, 0x3f, 0x0c, 0xaf, 0x90, 0x35, 0x2b, 0x8d, 0xe8, 0x1c, 0xb5, 0xa1, 0xd9, 0xc6, 0x33, 0x60, 0x92, 0xf0, 0xcd } +, + /* Salt */ + 20, + { 0x76, 0xfd, 0x4e, 0x64, 0xfd, 0xc9, 0x8e, 0xb9, 0x27, 0xa0, 0x40, 0x3e, 0x35, 0xa0, 0x84, 0xe7, 0x6b, 0xa9, 0xf9, 0x2a } +, + /* Signature */ + 129, + { 0x1e, 0xd1, 0xd8, 0x48, 0xfb, 0x1e, 0xdb, 0x44, 0x12, 0x9b, 0xd9, 0xb3, 0x54, 0x79, 0x5a, 0xf9, 0x7a, 0x06, 0x9a, 0x7a, 0x00, 0xd0, 0x15, 0x10, 0x48, 0x59, 0x3e, 0x0c, 0x72, 0xc3, 0x51, 0x7f, 0xf9, 0xff, 0x2a, 0x41, 0xd0, 0xcb, 0x5a, 0x0a, 0xc8, 0x60, 0xd7, 0x36, 0xa1, 0x99, 0x70, 0x4f, 0x7c, 0xb6, 0xa5, 0x39, 0x86, 0xa8, 0x8b, 0xbd, 0x8a, 0xbc, 0xc0, 0x07, 0x6a, 0x2c, 0xe8, 0x47, 0x88, 0x00, 0x31, 0x52, 0x5d, 0x44, 0x9d, 0xa2, 0xac, 0x78, 0x35, 0x63, 0x74, 0xc5, 0x36, 0xe3, 0x43, 0xfa, 0xa7, 0xcb, 0xa4, 0x2a, 0x5a, 0xaa, 0x65, 0x06, 0x08, 0x77, 0x91, 0xc0, 0x6a, 0x8e, 0x98, 0x93, 0x35, 0xae, 0xd1, 0x9b, 0xfa, 0xb2, 0xd5, 0xe6, 0x7e, 0x27, 0xfb, 0x0c, 0x28, 0x75, 0xaf, 0x89, 0x6c, 0x21, 0xb6, 0xe8, 0xe7, 0x30, 0x9d, 0x04, 0xe4, 0xf6, 0x72, 0x7e, 0x69, 0x46, 0x3e } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 9: A 1536-bit RSA Key Pair", +{ + /* RSA modulus n */ + 192, + { 0xe6, 0xbd, 0x69, 0x2a, 0xc9, 0x66, 0x45, 0x79, 0x04, 0x03, 0xfd, 0xd0, 0xf5, 0xbe, 0xb8, 0xb9, 0xbf, 0x92, 0xed, 0x10, 0x00, 0x7f, 0xc3, 0x65, 0x04, 0x64, 0x19, 0xdd, 0x06, 0xc0, 0x5c, 0x5b, 0x5b, 0x2f, 0x48, 0xec, 0xf9, 0x89, 0xe4, 0xce, 0x26, 0x91, 0x09, 0x97, 0x9c, 0xbb, 0x40, 0xb4, 0xa0, 0xad, 0x24, 0xd2, 0x24, 0x83, 0xd1, 0xee, 0x31, 0x5a, 0xd4, 0xcc, 0xb1, 0x53, 0x42, 0x68, 0x35, 0x26, 0x91, 0xc5, 0x24, 0xf6, 0xdd, 0x8e, 0x6c, 0x29, 0xd2, 0x24, 0xcf, 0x24, 0x69, 0x73, 0xae, 0xc8, 0x6c, 0x5b, 0xf6, 0xb1, 0x40, 0x1a, 0x85, 0x0d, 0x1b, 0x9a, 0xd1, 0xbb, 0x8c, 0xbc, 0xec, 0x47, 0xb0, 0x6f, 0x0f, 0x8c, 0x7f, 0x45, 0xd3, 0xfc, 0x8f, 0x31, 0x92, 0x99, 0xc5, 0x43, 0x3d, 0xdb, 0xc2, 0xb3, 0x05, 0x3b, 0x47, 0xde, 0xd2, 0xec, 0xd4, 0xa4, 0xca, 0xef, 0xd6, 0x14, 0x83, 0x3d, 0xc8, 0xbb, 0x62, 0x2f, 0x31, 0x7e, 0xd0, 0x76, 0xb8, 0x05, 0x7f, 0xe8, 0xde, 0x3f, 0x84, 0x48, 0x0a, 0xd5, 0xe8, 0x3e, 0x4a, 0x61, 0x90, 0x4a, 0x4f, 0x24, 0x8f, 0xb3, 0x97, 0x02, 0x73, 0x57, 0xe1, 0xd3, 0x0e, 0x46, 0x31, 0x39, 0x81, 0x5c, 0x6f, 0xd4, 0xfd, 0x5a, 0xc5, 0xb8, 0x17, 0x2a, 0x45, 0x23, 0x0e, 0xcb, 0x63, 0x18, 0xa0, 0x4f, 0x14, 0x55, 0xd8, 0x4e, 0x5a, 0x8b } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 192, + { 0x6a, 0x7f, 0xd8, 0x4f, 0xb8, 0x5f, 0xad, 0x07, 0x3b, 0x34, 0x40, 0x6d, 0xb7, 0x4f, 0x8d, 0x61, 0xa6, 0xab, 0xc1, 0x21, 0x96, 0xa9, 0x61, 0xdd, 0x79, 0x56, 0x5e, 0x9d, 0xa6, 0xe5, 0x18, 0x7b, 0xce, 0x2d, 0x98, 0x02, 0x50, 0xf7, 0x35, 0x95, 0x75, 0x35, 0x92, 0x70, 0xd9, 0x15, 0x90, 0xbb, 0x0e, 0x42, 0x7c, 0x71, 0x46, 0x0b, 0x55, 0xd5, 0x14, 0x10, 0xb1, 0x91, 0xbc, 0xf3, 0x09, 0xfe, 0xa1, 0x31, 0xa9, 0x2c, 0x8e, 0x70, 0x27, 0x38, 0xfa, 0x71, 0x9f, 0x1e, 0x00, 0x41, 0xf5, 0x2e, 0x40, 0xe9, 0x1f, 0x22, 0x9f, 0x4d, 0x96, 0xa1, 0xe6, 0xf1, 0x72, 0xe1, 0x55, 0x96, 0xb4, 0x51, 0x0a, 0x6d, 0xae, 0xc2, 0x61, 0x05, 0xf2, 0xbe, 0xbc, 0x53, 0x31, 0x6b, 0x87, 0xbd, 0xf2, 0x13, 0x11, 0x66, 0x60, 0x70, 0xe8, 0xdf, 0xee, 0x69, 0xd5, 0x2c, 0x71, 0xa9, 0x76, 0xca, 0xae, 0x79, 0xc7, 0x2b, 0x68, 0xd2, 0x85, 0x80, 0xdc, 0x68, 0x6d, 0x9f, 0x51, 0x29, 0xd2, 0x25, 0xf8, 0x2b, 0x3d, 0x61, 0x55, 0x13, 0xa8, 0x82, 0xb3, 0xdb, 0x91, 0x41, 0x6b, 0x48, 0xce, 0x08, 0x88, 0x82, 0x13, 0xe3, 0x7e, 0xeb, 0x9a, 0xf8, 0x00, 0xd8, 0x1c, 0xab, 0x32, 0x8c, 0xe4, 0x20, 0x68, 0x99, 0x03, 0xc0, 0x0c, 0x7b, 0x5f, 0xd3, 0x1b, 0x75, 0x50, 0x3a, 0x6d, 0x41, 0x96, 0x84, 0xd6, 0x29 } +, + /* Prime p */ + 96, + { 0xf8, 0xeb, 0x97, 0xe9, 0x8d, 0xf1, 0x26, 0x64, 0xee, 0xfd, 0xb7, 0x61, 0x59, 0x6a, 0x69, 0xdd, 0xcd, 0x0e, 0x76, 0xda, 0xec, 0xe6, 0xed, 0x4b, 0xf5, 0xa1, 0xb5, 0x0a, 0xc0, 0x86, 0xf7, 0x92, 0x8a, 0x4d, 0x2f, 0x87, 0x26, 0xa7, 0x7e, 0x51, 0x5b, 0x74, 0xda, 0x41, 0x98, 0x8f, 0x22, 0x0b, 0x1c, 0xc8, 0x7a, 0xa1, 0xfc, 0x81, 0x0c, 0xe9, 0x9a, 0x82, 0xf2, 0xd1, 0xce, 0x82, 0x1e, 0xdc, 0xed, 0x79, 0x4c, 0x69, 0x41, 0xf4, 0x2c, 0x7a, 0x1a, 0x0b, 0x8c, 0x4d, 0x28, 0xc7, 0x5e, 0xc6, 0x0b, 0x65, 0x22, 0x79, 0xf6, 0x15, 0x4a, 0x76, 0x2a, 0xed, 0x16, 0x5d, 0x47, 0xde, 0xe3, 0x67 } +, + /* Prime q */ + 96, + { 0xed, 0x4d, 0x71, 0xd0, 0xa6, 0xe2, 0x4b, 0x93, 0xc2, 0xe5, 0xf6, 0xb4, 0xbb, 0xe0, 0x5f, 0x5f, 0xb0, 0xaf, 0xa0, 0x42, 0xd2, 0x04, 0xfe, 0x33, 0x78, 0xd3, 0x65, 0xc2, 0xf2, 0x88, 0xb6, 0xa8, 0xda, 0xd7, 0xef, 0xe4, 0x5d, 0x15, 0x3e, 0xef, 0x40, 0xca, 0xcc, 0x7b, 0x81, 0xff, 0x93, 0x40, 0x02, 0xd1, 0x08, 0x99, 0x4b, 0x94, 0xa5, 0xe4, 0x72, 0x8c, 0xd9, 0xc9, 0x63, 0x37, 0x5a, 0xe4, 0x99, 0x65, 0xbd, 0xa5, 0x5c, 0xbf, 0x0e, 0xfe, 0xd8, 0xd6, 0x55, 0x3b, 0x40, 0x27, 0xf2, 0xd8, 0x62, 0x08, 0xa6, 0xe6, 0xb4, 0x89, 0xc1, 0x76, 0x12, 0x80, 0x92, 0xd6, 0x29, 0xe4, 0x9d, 0x3d } +, + /* p's CRT exponent dP */ + 96, + { 0x2b, 0xb6, 0x8b, 0xdd, 0xfb, 0x0c, 0x4f, 0x56, 0xc8, 0x55, 0x8b, 0xff, 0xaf, 0x89, 0x2d, 0x80, 0x43, 0x03, 0x78, 0x41, 0xe7, 0xfa, 0x81, 0xcf, 0xa6, 0x1a, 0x38, 0xc5, 0xe3, 0x9b, 0x90, 0x1c, 0x8e, 0xe7, 0x11, 0x22, 0xa5, 0xda, 0x22, 0x27, 0xbd, 0x6c, 0xde, 0xeb, 0x48, 0x14, 0x52, 0xc1, 0x2a, 0xd3, 0xd6, 0x1d, 0x5e, 0x4f, 0x77, 0x6a, 0x0a, 0xb5, 0x56, 0x59, 0x1b, 0xef, 0xe3, 0xe5, 0x9e, 0x5a, 0x7f, 0xdd, 0xb8, 0x34, 0x5e, 0x1f, 0x2f, 0x35, 0xb9, 0xf4, 0xce, 0xe5, 0x7c, 0x32, 0x41, 0x4c, 0x08, 0x6a, 0xec, 0x99, 0x3e, 0x93, 0x53, 0xe4, 0x80, 0xd9, 0xee, 0xc6, 0x28, 0x9f } +, + /* q's CRT exponent dQ */ + 96, + { 0x4f, 0xf8, 0x97, 0x70, 0x9f, 0xad, 0x07, 0x97, 0x46, 0x49, 0x45, 0x78, 0xe7, 0x0f, 0xd8, 0x54, 0x61, 0x30, 0xee, 0xab, 0x56, 0x27, 0xc4, 0x9b, 0x08, 0x0f, 0x05, 0xee, 0x4a, 0xd9, 0xf3, 0xe4, 0xb7, 0xcb, 0xa9, 0xd6, 0xa5, 0xdf, 0xf1, 0x13, 0xa4, 0x1c, 0x34, 0x09, 0x33, 0x68, 0x33, 0xf1, 0x90, 0x81, 0x6d, 0x8a, 0x6b, 0xc4, 0x2e, 0x9b, 0xec, 0x56, 0xb7, 0x56, 0x7d, 0x0f, 0x3c, 0x9c, 0x69, 0x6d, 0xb6, 0x19, 0xb2, 0x45, 0xd9, 0x01, 0xdd, 0x85, 0x6d, 0xb7, 0xc8, 0x09, 0x2e, 0x77, 0xe9, 0xa1, 0xcc, 0xcd, 0x56, 0xee, 0x4d, 0xba, 0x42, 0xc5, 0xfd, 0xb6, 0x1a, 0xec, 0x26, 0x69 } +, + /* CRT coefficient qInv */ + 96, + { 0x77, 0xb9, 0xd1, 0x13, 0x7b, 0x50, 0x40, 0x4a, 0x98, 0x27, 0x29, 0x31, 0x6e, 0xfa, 0xfc, 0x7d, 0xfe, 0x66, 0xd3, 0x4e, 0x5a, 0x18, 0x26, 0x00, 0xd5, 0xf3, 0x0a, 0x0a, 0x85, 0x12, 0x05, 0x1c, 0x56, 0x0d, 0x08, 0x1d, 0x4d, 0x0a, 0x18, 0x35, 0xec, 0x3d, 0x25, 0xa6, 0x0f, 0x4e, 0x4d, 0x6a, 0xa9, 0x48, 0xb2, 0xbf, 0x3d, 0xbb, 0x5b, 0x12, 0x4c, 0xbb, 0xc3, 0x48, 0x92, 0x55, 0xa3, 0xa9, 0x48, 0x37, 0x2f, 0x69, 0x78, 0x49, 0x67, 0x45, 0xf9, 0x43, 0xe1, 0xdb, 0x4f, 0x18, 0x38, 0x2c, 0xea, 0xa5, 0x05, 0xdf, 0xc6, 0x57, 0x57, 0xbb, 0x3f, 0x85, 0x7a, 0x58, 0xdc, 0xe5, 0x21, 0x56 } + +} +, +{{ + "RSASSA-PSS Signature Example 9.1", + /* Message to be signed */ + 211, + { 0xa8, 0x8e, 0x26, 0x58, 0x55, 0xe9, 0xd7, 0xca, 0x36, 0xc6, 0x87, 0x95, 0xf0, 0xb3, 0x1b, 0x59, 0x1c, 0xd6, 0x58, 0x7c, 0x71, 0xd0, 0x60, 0xa0, 0xb3, 0xf7, 0xf3, 0xea, 0xef, 0x43, 0x79, 0x59, 0x22, 0x02, 0x8b, 0xc2, 0xb6, 0xad, 0x46, 0x7c, 0xfc, 0x2d, 0x7f, 0x65, 0x9c, 0x53, 0x85, 0xaa, 0x70, 0xba, 0x36, 0x72, 0xcd, 0xde, 0x4c, 0xfe, 0x49, 0x70, 0xcc, 0x79, 0x04, 0x60, 0x1b, 0x27, 0x88, 0x72, 0xbf, 0x51, 0x32, 0x1c, 0x4a, 0x97, 0x2f, 0x3c, 0x95, 0x57, 0x0f, 0x34, 0x45, 0xd4, 0xf5, 0x79, 0x80, 0xe0, 0xf2, 0x0d, 0xf5, 0x48, 0x46, 0xe6, 0xa5, 0x2c, 0x66, 0x8f, 0x12, 0x88, 0xc0, 0x3f, 0x95, 0x00, 0x6e, 0xa3, 0x2f, 0x56, 0x2d, 0x40, 0xd5, 0x2a, 0xf9, 0xfe, 0xb3, 0x2f, 0x0f, 0xa0, 0x6d, 0xb6, 0x5b, 0x58, 0x8a, 0x23, 0x7b, 0x34, 0xe5, 0x92, 0xd5, 0x5c, 0xf9, 0x79, 0xf9, 0x03, 0xa6, 0x42, 0xef, 0x64, 0xd2, 0xed, 0x54, 0x2a, 0xa8, 0xc7, 0x7d, 0xc1, 0xdd, 0x76, 0x2f, 0x45, 0xa5, 0x93, 0x03, 0xed, 0x75, 0xe5, 0x41, 0xca, 0x27, 0x1e, 0x2b, 0x60, 0xca, 0x70, 0x9e, 0x44, 0xfa, 0x06, 0x61, 0x13, 0x1e, 0x8d, 0x5d, 0x41, 0x63, 0xfd, 0x8d, 0x39, 0x85, 0x66, 0xce, 0x26, 0xde, 0x87, 0x30, 0xe7, 0x2f, 0x9c, 0xca, 0x73, 0x76, 0x41, 0xc2, 0x44, 0x15, 0x94, 0x20, 0x63, 0x70, 0x28, 0xdf, 0x0a, 0x18, 0x07, 0x9d, 0x62, 0x08, 0xea, 0x8b, 0x47, 0x11, 0xa2, 0xc7, 0x50, 0xf5 } +, + /* Salt */ + 20, + { 0xc0, 0xa4, 0x25, 0x31, 0x3d, 0xf8, 0xd7, 0x56, 0x4b, 0xd2, 0x43, 0x4d, 0x31, 0x15, 0x23, 0xd5, 0x25, 0x7e, 0xed, 0x80 } +, + /* Signature */ + 192, + { 0x58, 0x61, 0x07, 0x22, 0x6c, 0x3c, 0xe0, 0x13, 0xa7, 0xc8, 0xf0, 0x4d, 0x1a, 0x6a, 0x29, 0x59, 0xbb, 0x4b, 0x8e, 0x20, 0x5b, 0xa4, 0x3a, 0x27, 0xb5, 0x0f, 0x12, 0x41, 0x11, 0xbc, 0x35, 0xef, 0x58, 0x9b, 0x03, 0x9f, 0x59, 0x32, 0x18, 0x7c, 0xb6, 0x96, 0xd7, 0xd9, 0xa3, 0x2c, 0x0c, 0x38, 0x30, 0x0a, 0x5c, 0xdd, 0xa4, 0x83, 0x4b, 0x62, 0xd2, 0xeb, 0x24, 0x0a, 0xf3, 0x3f, 0x79, 0xd1, 0x3d, 0xfb, 0xf0, 0x95, 0xbf, 0x59, 0x9e, 0x0d, 0x96, 0x86, 0x94, 0x8c, 0x19, 0x64, 0x74, 0x7b, 0x67, 0xe8, 0x9c, 0x9a, 0xba, 0x5c, 0xd8, 0x50, 0x16, 0x23, 0x6f, 0x56, 0x6c, 0xc5, 0x80, 0x2c, 0xb1, 0x3e, 0xad, 0x51, 0xbc, 0x7c, 0xa6, 0xbe, 0xf3, 0xb9, 0x4d, 0xcb, 0xdb, 0xb1, 0xd5, 0x70, 0x46, 0x97, 0x71, 0xdf, 0x0e, 0x00, 0xb1, 0xa8, 0xa0, 0x67, 0x77, 0x47, 0x2d, 0x23, 0x16, 0x27, 0x9e, 0xda, 0xe8, 0x64, 0x74, 0x66, 0x8d, 0x4e, 0x1e, 0xff, 0xf9, 0x5f, 0x1d, 0xe6, 0x1c, 0x60, 0x20, 0xda, 0x32, 0xae, 0x92, 0xbb, 0xf1, 0x65, 0x20, 0xfe, 0xf3, 0xcf, 0x4d, 0x88, 0xf6, 0x11, 0x21, 0xf2, 0x4b, 0xbd, 0x9f, 0xe9, 0x1b, 0x59, 0xca, 0xf1, 0x23, 0x5b, 0x2a, 0x93, 0xff, 0x81, 0xfc, 0x40, 0x3a, 0xdd, 0xf4, 0xeb, 0xde, 0xa8, 0x49, 0x34, 0xa9, 0xcd, 0xaf, 0x8e, 0x1a, 0x9e } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 9.2", + /* Message to be signed */ + 107, + { 0xc8, 0xc9, 0xc6, 0xaf, 0x04, 0xac, 0xda, 0x41, 0x4d, 0x22, 0x7e, 0xf2, 0x3e, 0x08, 0x20, 0xc3, 0x73, 0x2c, 0x50, 0x0d, 0xc8, 0x72, 0x75, 0xe9, 0x5b, 0x0d, 0x09, 0x54, 0x13, 0x99, 0x3c, 0x26, 0x58, 0xbc, 0x1d, 0x98, 0x85, 0x81, 0xba, 0x87, 0x9c, 0x2d, 0x20, 0x1f, 0x14, 0xcb, 0x88, 0xce, 0xd1, 0x53, 0xa0, 0x19, 0x69, 0xa7, 0xbf, 0x0a, 0x7b, 0xe7, 0x9c, 0x84, 0xc1, 0x48, 0x6b, 0xc1, 0x2b, 0x3f, 0xa6, 0xc5, 0x98, 0x71, 0xb6, 0x82, 0x7c, 0x8c, 0xe2, 0x53, 0xca, 0x5f, 0xef, 0xa8, 0xa8, 0xc6, 0x90, 0xbf, 0x32, 0x6e, 0x8e, 0x37, 0xcd, 0xb9, 0x6d, 0x90, 0xa8, 0x2e, 0xba, 0xb6, 0x9f, 0x86, 0x35, 0x0e, 0x18, 0x22, 0xe8, 0xbd, 0x53, 0x6a, 0x2e } +, + /* Salt */ + 20, + { 0xb3, 0x07, 0xc4, 0x3b, 0x48, 0x50, 0xa8, 0xda, 0xc2, 0xf1, 0x5f, 0x32, 0xe3, 0x78, 0x39, 0xef, 0x8c, 0x5c, 0x0e, 0x91 } +, + /* Signature */ + 192, + { 0x80, 0xb6, 0xd6, 0x43, 0x25, 0x52, 0x09, 0xf0, 0xa4, 0x56, 0x76, 0x38, 0x97, 0xac, 0x9e, 0xd2, 0x59, 0xd4, 0x59, 0xb4, 0x9c, 0x28, 0x87, 0xe5, 0x88, 0x2e, 0xcb, 0x44, 0x34, 0xcf, 0xd6, 0x6d, 0xd7, 0xe1, 0x69, 0x93, 0x75, 0x38, 0x1e, 0x51, 0xcd, 0x7f, 0x55, 0x4f, 0x2c, 0x27, 0x17, 0x04, 0xb3, 0x99, 0xd4, 0x2b, 0x4b, 0xe2, 0x54, 0x0a, 0x0e, 0xca, 0x61, 0x95, 0x1f, 0x55, 0x26, 0x7f, 0x7c, 0x28, 0x78, 0xc1, 0x22, 0x84, 0x2d, 0xad, 0xb2, 0x8b, 0x01, 0xbd, 0x5f, 0x8c, 0x02, 0x5f, 0x7e, 0x22, 0x84, 0x18, 0xa6, 0x73, 0xc0, 0x3d, 0x6b, 0xc0, 0xc7, 0x36, 0xd0, 0xa2, 0x95, 0x46, 0xbd, 0x67, 0xf7, 0x86, 0xd9, 0xd6, 0x92, 0xcc, 0xea, 0x77, 0x8d, 0x71, 0xd9, 0x8c, 0x20, 0x63, 0xb7, 0xa7, 0x10, 0x92, 0x18, 0x7a, 0x4d, 0x35, 0xaf, 0x10, 0x81, 0x11, 0xd8, 0x3e, 0x83, 0xea, 0xe4, 0x6c, 0x46, 0xaa, 0x34, 0x27, 0x7e, 0x06, 0x04, 0x45, 0x89, 0x90, 0x37, 0x88, 0xf1, 0xd5, 0xe7, 0xce, 0xe2, 0x5f, 0xb4, 0x85, 0xe9, 0x29, 0x49, 0x11, 0x88, 0x14, 0xd6, 0xf2, 0xc3, 0xee, 0x36, 0x14, 0x89, 0x01, 0x6f, 0x32, 0x7f, 0xb5, 0xbc, 0x51, 0x7e, 0xb5, 0x04, 0x70, 0xbf, 0xfa, 0x1a, 0xfa, 0x5f, 0x4c, 0xe9, 0xaa, 0x0c, 0xe5, 0xb8, 0xee, 0x19, 0xbf, 0x55, 0x01, 0xb9, 0x58 } + +} +, +{ + "RSASSA-PSS Signature Example 9.3", + /* Message to be signed */ + 222, + { 0x0a, 0xfa, 0xd4, 0x2c, 0xcd, 0x4f, 0xc6, 0x06, 0x54, 0xa5, 0x50, 0x02, 0xd2, 0x28, 0xf5, 0x2a, 0x4a, 0x5f, 0xe0, 0x3b, 0x8b, 0xbb, 0x08, 0xca, 0x82, 0xda, 0xca, 0x55, 0x8b, 0x44, 0xdb, 0xe1, 0x26, 0x6e, 0x50, 0xc0, 0xe7, 0x45, 0xa3, 0x6d, 0x9d, 0x29, 0x04, 0xe3, 0x40, 0x8a, 0xbc, 0xd1, 0xfd, 0x56, 0x99, 0x94, 0x06, 0x3f, 0x4a, 0x75, 0xcc, 0x72, 0xf2, 0xfe, 0xe2, 0xa0, 0xcd, 0x89, 0x3a, 0x43, 0xaf, 0x1c, 0x5b, 0x8b, 0x48, 0x7d, 0xf0, 0xa7, 0x16, 0x10, 0x02, 0x4e, 0x4f, 0x6d, 0xdf, 0x9f, 0x28, 0xad, 0x08, 0x13, 0xc1, 0xaa, 0xb9, 0x1b, 0xcb, 0x3c, 0x90, 0x64, 0xd5, 0xff, 0x74, 0x2d, 0xef, 0xfe, 0xa6, 0x57, 0x09, 0x41, 0x39, 0x36, 0x9e, 0x5e, 0xa6, 0xf4, 0xa9, 0x63, 0x19, 0xa5, 0xcc, 0x82, 0x24, 0x14, 0x5b, 0x54, 0x50, 0x62, 0x75, 0x8f, 0xef, 0xd1, 0xfe, 0x34, 0x09, 0xae, 0x16, 0x92, 0x59, 0xc6, 0xcd, 0xfd, 0x6b, 0x5f, 0x29, 0x58, 0xe3, 0x14, 0xfa, 0xec, 0xbe, 0x69, 0xd2, 0xca, 0xce, 0x58, 0xee, 0x55, 0x17, 0x9a, 0xb9, 0xb3, 0xe6, 0xd1, 0xec, 0xc1, 0x4a, 0x55, 0x7c, 0x5f, 0xeb, 0xe9, 0x88, 0x59, 0x52, 0x64, 0xfc, 0x5d, 0xa1, 0xc5, 0x71, 0x46, 0x2e, 0xca, 0x79, 0x8a, 0x18, 0xa1, 0xa4, 0x94, 0x0c, 0xda, 0xb4, 0xa3, 0xe9, 0x20, 0x09, 0xcc, 0xd4, 0x2e, 0x1e, 0x94, 0x7b, 0x13, 0x14, 0xe3, 0x22, 0x38, 0xa2, 0xde, 0xce, 0x7d, 0x23, 0xa8, 0x9b, 0x5b, 0x30, 0xc7, 0x51, 0xfd, 0x0a, 0x4a, 0x43, 0x0d, 0x2c, 0x54, 0x85, 0x94 } +, + /* Salt */ + 20, + { 0x9a, 0x2b, 0x00, 0x7e, 0x80, 0x97, 0x8b, 0xbb, 0x19, 0x2c, 0x35, 0x4e, 0xb7, 0xda, 0x9a, 0xed, 0xfc, 0x74, 0xdb, 0xf5 } +, + /* Signature */ + 192, + { 0x48, 0x44, 0x08, 0xf3, 0x89, 0x8c, 0xd5, 0xf5, 0x34, 0x83, 0xf8, 0x08, 0x19, 0xef, 0xbf, 0x27, 0x08, 0xc3, 0x4d, 0x27, 0xa8, 0xb2, 0xa6, 0xfa, 0xe8, 0xb3, 0x22, 0xf9, 0x24, 0x02, 0x37, 0xf9, 0x81, 0x81, 0x7a, 0xca, 0x18, 0x46, 0xf1, 0x08, 0x4d, 0xaa, 0x6d, 0x7c, 0x07, 0x95, 0xf6, 0xe5, 0xbf, 0x1a, 0xf5, 0x9c, 0x38, 0xe1, 0x85, 0x84, 0x37, 0xce, 0x1f, 0x7e, 0xc4, 0x19, 0xb9, 0x8c, 0x87, 0x36, 0xad, 0xf6, 0xdd, 0x9a, 0x00, 0xb1, 0x80, 0x6d, 0x2b, 0xd3, 0xad, 0x0a, 0x73, 0x77, 0x5e, 0x05, 0xf5, 0x2d, 0xfe, 0xf3, 0xa5, 0x9a, 0xb4, 0xb0, 0x81, 0x43, 0xf0, 0xdf, 0x05, 0xcd, 0x1a, 0xd9, 0xd0, 0x4b, 0xec, 0xec, 0xa6, 0xda, 0xa4, 0xa2, 0x12, 0x98, 0x03, 0xe2, 0x00, 0xcb, 0xc7, 0x77, 0x87, 0xca, 0xf4, 0xc1, 0xd0, 0x66, 0x3a, 0x6c, 0x59, 0x87, 0xb6, 0x05, 0x95, 0x20, 0x19, 0x78, 0x2c, 0xaf, 0x2e, 0xc1, 0x42, 0x6d, 0x68, 0xfb, 0x94, 0xed, 0x1d, 0x4b, 0xe8, 0x16, 0xa7, 0xed, 0x08, 0x1b, 0x77, 0xe6, 0xab, 0x33, 0x0b, 0x3f, 0xfc, 0x07, 0x38, 0x20, 0xfe, 0xcd, 0xe3, 0x72, 0x7f, 0xcb, 0xe2, 0x95, 0xee, 0x61, 0xa0, 0x50, 0xa3, 0x43, 0x65, 0x86, 0x37, 0xc3, 0xfd, 0x65, 0x9c, 0xfb, 0x63, 0x73, 0x6d, 0xe3, 0x2d, 0x9f, 0x90, 0xd3, 0xc2, 0xf6, 0x3e, 0xca } + +} +, +{ + "RSASSA-PSS Signature Example 9.4", + /* Message to be signed */ + 248, + { 0x1d, 0xfd, 0x43, 0xb4, 0x6c, 0x93, 0xdb, 0x82, 0x62, 0x9b, 0xda, 0xe2, 0xbd, 0x0a, 0x12, 0xb8, 0x82, 0xea, 0x04, 0xc3, 0xb4, 0x65, 0xf5, 0xcf, 0x93, 0x02, 0x3f, 0x01, 0x05, 0x96, 0x26, 0xdb, 0xbe, 0x99, 0xf2, 0x6b, 0xb1, 0xbe, 0x94, 0x9d, 0xdd, 0xd1, 0x6d, 0xc7, 0xf3, 0xde, 0xbb, 0x19, 0xa1, 0x94, 0x62, 0x7f, 0x0b, 0x22, 0x44, 0x34, 0xdf, 0x7d, 0x87, 0x00, 0xe9, 0xe9, 0x8b, 0x06, 0xe3, 0x60, 0xc1, 0x2f, 0xdb, 0xe3, 0xd1, 0x9f, 0x51, 0xc9, 0x68, 0x4e, 0xb9, 0x08, 0x9e, 0xcb, 0xb0, 0xa2, 0xf0, 0x45, 0x03, 0x99, 0xd3, 0xf5, 0x9e, 0xac, 0x72, 0x94, 0x08, 0x5d, 0x04, 0x4f, 0x53, 0x93, 0xc6, 0xce, 0x73, 0x74, 0x23, 0xd8, 0xb8, 0x6c, 0x41, 0x53, 0x70, 0xd3, 0x89, 0xe3, 0x0b, 0x9f, 0x0a, 0x3c, 0x02, 0xd2, 0x5d, 0x00, 0x82, 0xe8, 0xad, 0x6f, 0x3f, 0x1e, 0xf2, 0x4a, 0x45, 0xc3, 0xcf, 0x82, 0xb3, 0x83, 0x36, 0x70, 0x63, 0xa4, 0xd4, 0x61, 0x3e, 0x42, 0x64, 0xf0, 0x1b, 0x2d, 0xac, 0x2e, 0x5a, 0xa4, 0x20, 0x43, 0xf8, 0xfb, 0x5f, 0x69, 0xfa, 0x87, 0x1d, 0x14, 0xfb, 0x27, 0x3e, 0x76, 0x7a, 0x53, 0x1c, 0x40, 0xf0, 0x2f, 0x34, 0x3b, 0xc2, 0xfb, 0x45, 0xa0, 0xc7, 0xe0, 0xf6, 0xbe, 0x25, 0x61, 0x92, 0x3a, 0x77, 0x21, 0x1d, 0x66, 0xa6, 0xe2, 0xdb, 0xb4, 0x3c, 0x36, 0x63, 0x50, 0xbe, 0xae, 0x22, 0xda, 0x3a, 0xc2, 0xc1, 0xf5, 0x07, 0x70, 0x96, 0xfc, 0xb5, 0xc4, 0xbf, 0x25, 0x5f, 0x75, 0x74, 0x35, 0x1a, 0xe0, 0xb1, 0xe1, 0xf0, 0x36, 0x32, 0x81, 0x7c, 0x08, 0x56, 0xd4, 0xa8, 0xba, 0x97, 0xaf, 0xbd, 0xc8, 0xb8, 0x58, 0x55, 0x40, 0x2b, 0xc5, 0x69, 0x26, 0xfc, 0xec, 0x20, 0x9f, 0x9e, 0xa8 } +, + /* Salt */ + 20, + { 0x70, 0xf3, 0x82, 0xbd, 0xdf, 0x4d, 0x5d, 0x2d, 0xd8, 0x8b, 0x3b, 0xc7, 0xb7, 0x30, 0x8b, 0xe6, 0x32, 0xb8, 0x40, 0x45 } +, + /* Signature */ + 192, + { 0x84, 0xeb, 0xeb, 0x48, 0x1b, 0xe5, 0x98, 0x45, 0xb4, 0x64, 0x68, 0xba, 0xfb, 0x47, 0x1c, 0x01, 0x12, 0xe0, 0x2b, 0x23, 0x5d, 0x84, 0xb5, 0xd9, 0x11, 0xcb, 0xd1, 0x92, 0x6e, 0xe5, 0x07, 0x4a, 0xe0, 0x42, 0x44, 0x95, 0xcb, 0x20, 0xe8, 0x23, 0x08, 0xb8, 0xeb, 0xb6, 0x5f, 0x41, 0x9a, 0x03, 0xfb, 0x40, 0xe7, 0x2b, 0x78, 0x98, 0x1d, 0x88, 0xaa, 0xd1, 0x43, 0x05, 0x36, 0x85, 0x17, 0x2c, 0x97, 0xb2, 0x9c, 0x8b, 0x7b, 0xf0, 0xae, 0x73, 0xb5, 0xb2, 0x26, 0x3c, 0x40, 0x3d, 0xa0, 0xed, 0x2f, 0x80, 0xff, 0x74, 0x50, 0xaf, 0x78, 0x28, 0xeb, 0x8b, 0x86, 0xf0, 0x02, 0x8b, 0xd2, 0xa8, 0xb1, 0x76, 0xa4, 0xd2, 0x28, 0xcc, 0xce, 0xa1, 0x83, 0x94, 0xf2, 0x38, 0xb0, 0x9f, 0xf7, 0x58, 0xcc, 0x00, 0xbc, 0x04, 0x30, 0x11, 0x52, 0x35, 0x57, 0x42, 0xf2, 0x82, 0xb5, 0x4e, 0x66, 0x3a, 0x91, 0x9e, 0x70, 0x9d, 0x8d, 0xa2, 0x4a, 0xde, 0x55, 0x00, 0xa7, 0xb9, 0xaa, 0x50, 0x22, 0x6e, 0x0c, 0xa5, 0x29, 0x23, 0xe6, 0xc2, 0xd8, 0x60, 0xec, 0x50, 0xff, 0x48, 0x0f, 0xa5, 0x74, 0x77, 0xe8, 0x2b, 0x05, 0x65, 0xf4, 0x37, 0x9f, 0x79, 0xc7, 0x72, 0xd5, 0xc2, 0xda, 0x80, 0xaf, 0x9f, 0xbf, 0x32, 0x5e, 0xce, 0x6f, 0xc2, 0x0b, 0x00, 0x96, 0x16, 0x14, 0xbe, 0xe8, 0x9a, 0x18, 0x3e } + +} +, +{ + "RSASSA-PSS Signature Example 9.5", + /* Message to be signed */ + 234, + { 0x1b, 0xdc, 0x6e, 0x7c, 0x98, 0xfb, 0x8c, 0xf5, 0x4e, 0x9b, 0x09, 0x7b, 0x66, 0xa8, 0x31, 0xe9, 0xcf, 0xe5, 0x2d, 0x9d, 0x48, 0x88, 0x44, 0x8e, 0xe4, 0xb0, 0x97, 0x80, 0x93, 0xba, 0x1d, 0x7d, 0x73, 0xae, 0x78, 0xb3, 0xa6, 0x2b, 0xa4, 0xad, 0x95, 0xcd, 0x28, 0x9c, 0xcb, 0x9e, 0x00, 0x52, 0x26, 0xbb, 0x3d, 0x17, 0x8b, 0xcc, 0xaa, 0x82, 0x1f, 0xb0, 0x44, 0xa4, 0xe2, 0x1e, 0xe9, 0x76, 0x96, 0xc1, 0x4d, 0x06, 0x78, 0xc9, 0x4c, 0x2d, 0xae, 0x93, 0xb0, 0xad, 0x73, 0x92, 0x22, 0x18, 0x55, 0x3d, 0xaa, 0x7e, 0x44, 0xeb, 0xe5, 0x77, 0x25, 0xa7, 0xa4, 0x5c, 0xc7, 0x2b, 0x9b, 0x21, 0x38, 0xa6, 0xb1, 0x7c, 0x8d, 0xb4, 0x11, 0xce, 0x82, 0x79, 0xee, 0x12, 0x41, 0xaf, 0xf0, 0xa8, 0xbe, 0xc6, 0xf7, 0x7f, 0x87, 0xed, 0xb0, 0xc6, 0x9c, 0xb2, 0x72, 0x36, 0xe3, 0x43, 0x5a, 0x80, 0x0b, 0x19, 0x2e, 0x4f, 0x11, 0xe5, 0x19, 0xe3, 0xfe, 0x30, 0xfc, 0x30, 0xea, 0xcc, 0xca, 0x4f, 0xbb, 0x41, 0x76, 0x90, 0x29, 0xbf, 0x70, 0x8e, 0x81, 0x7a, 0x9e, 0x68, 0x38, 0x05, 0xbe, 0x67, 0xfa, 0x10, 0x09, 0x84, 0x68, 0x3b, 0x74, 0x83, 0x8e, 0x3b, 0xcf, 0xfa, 0x79, 0x36, 0x6e, 0xed, 0x1d, 0x48, 0x1c, 0x76, 0x72, 0x91, 0x18, 0x83, 0x8f, 0x31, 0xba, 0x8a, 0x04, 0x8a, 0x93, 0xc1, 0xbe, 0x44, 0x24, 0x59, 0x8e, 0x8d, 0xf6, 0x32, 0x8b, 0x7a, 0x77, 0x88, 0x0a, 0x3f, 0x9c, 0x7e, 0x2e, 0x8d, 0xfc, 0xa8, 0xeb, 0x5a, 0x26, 0xfb, 0x86, 0xbd, 0xc5, 0x56, 0xd4, 0x2b, 0xbe, 0x01, 0xd9, 0xfa, 0x6e, 0xd8, 0x06, 0x46, 0x49, 0x1c, 0x93, 0x41 } +, + /* Salt */ + 20, + { 0xd6, 0x89, 0x25, 0x7a, 0x86, 0xef, 0xfa, 0x68, 0x21, 0x2c, 0x5e, 0x0c, 0x61, 0x9e, 0xca, 0x29, 0x5f, 0xb9, 0x1b, 0x67 } +, + /* Signature */ + 192, + { 0x82, 0x10, 0x2d, 0xf8, 0xcb, 0x91, 0xe7, 0x17, 0x99, 0x19, 0xa0, 0x4d, 0x26, 0xd3, 0x35, 0xd6, 0x4f, 0xbc, 0x2f, 0x87, 0x2c, 0x44, 0x83, 0x39, 0x43, 0x24, 0x1d, 0xe8, 0x45, 0x48, 0x10, 0x27, 0x4c, 0xdf, 0x3d, 0xb5, 0xf4, 0x2d, 0x42, 0x3d, 0xb1, 0x52, 0xaf, 0x71, 0x35, 0xf7, 0x01, 0x42, 0x0e, 0x39, 0xb4, 0x94, 0xa6, 0x7c, 0xbf, 0xd1, 0x9f, 0x91, 0x19, 0xda, 0x23, 0x3a, 0x23, 0xda, 0x5c, 0x64, 0x39, 0xb5, 0xba, 0x0d, 0x2b, 0xc3, 0x73, 0xee, 0xe3, 0x50, 0x70, 0x01, 0x37, 0x8d, 0x4a, 0x40, 0x73, 0x85, 0x6b, 0x7f, 0xe2, 0xab, 0xa0, 0xb5, 0xee, 0x93, 0xb2, 0x7f, 0x4a, 0xfe, 0xc7, 0xd4, 0xd1, 0x20, 0x92, 0x1c, 0x83, 0xf6, 0x06, 0x76, 0x5b, 0x02, 0xc1, 0x9e, 0x4d, 0x6a, 0x1a, 0x3b, 0x95, 0xfa, 0x4c, 0x42, 0x29, 0x51, 0xbe, 0x4f, 0x52, 0x13, 0x10, 0x77, 0xef, 0x17, 0x17, 0x97, 0x29, 0xcd, 0xdf, 0xbd, 0xb5, 0x69, 0x50, 0xdb, 0xac, 0xee, 0xfe, 0x78, 0xcb, 0x16, 0x64, 0x0a, 0x09, 0x9e, 0xa5, 0x6d, 0x24, 0x38, 0x9e, 0xef, 0x10, 0xf8, 0xfe, 0xcb, 0x31, 0xba, 0x3e, 0xa3, 0xb2, 0x27, 0xc0, 0xa8, 0x66, 0x98, 0xbb, 0x89, 0xe3, 0xe9, 0x36, 0x39, 0x05, 0xbf, 0x22, 0x77, 0x7b, 0x2a, 0x3a, 0xa5, 0x21, 0xb6, 0x5b, 0x4c, 0xef, 0x76, 0xd8, 0x3b, 0xde, 0x4c } + +} +, +{ + "RSASSA-PSS Signature Example 9.6", + /* Message to be signed */ + 165, + { 0x88, 0xc7, 0xa9, 0xf1, 0x36, 0x04, 0x01, 0xd9, 0x0e, 0x53, 0xb1, 0x01, 0xb6, 0x1c, 0x53, 0x25, 0xc3, 0xc7, 0x5d, 0xb1, 0xb4, 0x11, 0xfb, 0xeb, 0x8e, 0x83, 0x0b, 0x75, 0xe9, 0x6b, 0x56, 0x67, 0x0a, 0xd2, 0x45, 0x40, 0x4e, 0x16, 0x79, 0x35, 0x44, 0xee, 0x35, 0x4b, 0xc6, 0x13, 0xa9, 0x0c, 0xc9, 0x84, 0x87, 0x15, 0xa7, 0x3d, 0xb5, 0x89, 0x3e, 0x7f, 0x6d, 0x27, 0x98, 0x15, 0xc0, 0xc1, 0xde, 0x83, 0xef, 0x8e, 0x29, 0x56, 0xe3, 0xa5, 0x6e, 0xd2, 0x6a, 0x88, 0x8d, 0x7a, 0x9c, 0xdc, 0xd0, 0x42, 0xf4, 0xb1, 0x6b, 0x7f, 0xa5, 0x1e, 0xf1, 0xa0, 0x57, 0x36, 0x62, 0xd1, 0x6a, 0x30, 0x2d, 0x0e, 0xc5, 0xb2, 0x85, 0xd2, 0xe0, 0x3a, 0xd9, 0x65, 0x29, 0xc8, 0x7b, 0x3d, 0x37, 0x4d, 0xb3, 0x72, 0xd9, 0x5b, 0x24, 0x43, 0xd0, 0x61, 0xb6, 0xb1, 0xa3, 0x50, 0xba, 0x87, 0x80, 0x7e, 0xd0, 0x83, 0xaf, 0xd1, 0xeb, 0x05, 0xc3, 0xf5, 0x2f, 0x4e, 0xba, 0x5e, 0xd2, 0x22, 0x77, 0x14, 0xfd, 0xb5, 0x0b, 0x9d, 0x9d, 0x9d, 0xd6, 0x81, 0x4f, 0x62, 0xf6, 0x27, 0x2f, 0xcd, 0x5c, 0xdb, 0xce, 0x7a, 0x9e, 0xf7, 0x97 } +, + /* Salt */ + 20, + { 0xc2, 0x5f, 0x13, 0xbf, 0x67, 0xd0, 0x81, 0x67, 0x1a, 0x04, 0x81, 0xa1, 0xf1, 0x82, 0x0d, 0x61, 0x3b, 0xba, 0x22, 0x76 } +, + /* Signature */ + 192, + { 0xa7, 0xfd, 0xb0, 0xd2, 0x59, 0x16, 0x5c, 0xa2, 0xc8, 0x8d, 0x00, 0xbb, 0xf1, 0x02, 0x8a, 0x86, 0x7d, 0x33, 0x76, 0x99, 0xd0, 0x61, 0x19, 0x3b, 0x17, 0xa9, 0x64, 0x8e, 0x14, 0xcc, 0xbb, 0xaa, 0xde, 0xac, 0xaa, 0xcd, 0xec, 0x81, 0x5e, 0x75, 0x71, 0x29, 0x4e, 0xbb, 0x8a, 0x11, 0x7a, 0xf2, 0x05, 0xfa, 0x07, 0x8b, 0x47, 0xb0, 0x71, 0x2c, 0x19, 0x9e, 0x3a, 0xd0, 0x51, 0x35, 0xc5, 0x04, 0xc2, 0x4b, 0x81, 0x70, 0x51, 0x15, 0x74, 0x08, 0x02, 0x48, 0x79, 0x92, 0xff, 0xd5, 0x11, 0xd4, 0xaf, 0xc6, 0xb8, 0x54, 0x49, 0x1e, 0xb3, 0xf0, 0xdd, 0x52, 0x31, 0x39, 0x54, 0x2f, 0xf1, 0x5c, 0x31, 0x01, 0xee, 0x85, 0x54, 0x35, 0x17, 0xc6, 0xa3, 0xc7, 0x94, 0x17, 0xc6, 0x7e, 0x2d, 0xd9, 0xaa, 0x74, 0x1e, 0x9a, 0x29, 0xb0, 0x6d, 0xcb, 0x59, 0x3c, 0x23, 0x36, 0xb3, 0x67, 0x0a, 0xe3, 0xaf, 0xba, 0xc7, 0xc3, 0xe7, 0x6e, 0x21, 0x54, 0x73, 0xe8, 0x66, 0xe3, 0x38, 0xca, 0x24, 0x4d, 0xe0, 0x0b, 0x62, 0x62, 0x4d, 0x6b, 0x94, 0x26, 0x82, 0x2c, 0xea, 0xe9, 0xf8, 0xcc, 0x46, 0x08, 0x95, 0xf4, 0x12, 0x50, 0x07, 0x3f, 0xd4, 0x5c, 0x5a, 0x1e, 0x7b, 0x42, 0x5c, 0x20, 0x4a, 0x42, 0x3a, 0x69, 0x91, 0x59, 0xf6, 0x90, 0x3e, 0x71, 0x0b, 0x37, 0xa7, 0xbb, 0x2b, 0xc8, 0x04, 0x9f } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +{ + "Example 10: A 2048-bit RSA Key Pair", +{ + /* RSA modulus n */ + 256, + { 0xa5, 0xdd, 0x86, 0x7a, 0xc4, 0xcb, 0x02, 0xf9, 0x0b, 0x94, 0x57, 0xd4, 0x8c, 0x14, 0xa7, 0x70, 0xef, 0x99, 0x1c, 0x56, 0xc3, 0x9c, 0x0e, 0xc6, 0x5f, 0xd1, 0x1a, 0xfa, 0x89, 0x37, 0xce, 0xa5, 0x7b, 0x9b, 0xe7, 0xac, 0x73, 0xb4, 0x5c, 0x00, 0x17, 0x61, 0x5b, 0x82, 0xd6, 0x22, 0xe3, 0x18, 0x75, 0x3b, 0x60, 0x27, 0xc0, 0xfd, 0x15, 0x7b, 0xe1, 0x2f, 0x80, 0x90, 0xfe, 0xe2, 0xa7, 0xad, 0xcd, 0x0e, 0xef, 0x75, 0x9f, 0x88, 0xba, 0x49, 0x97, 0xc7, 0xa4, 0x2d, 0x58, 0xc9, 0xaa, 0x12, 0xcb, 0x99, 0xae, 0x00, 0x1f, 0xe5, 0x21, 0xc1, 0x3b, 0xb5, 0x43, 0x14, 0x45, 0xa8, 0xd5, 0xae, 0x4f, 0x5e, 0x4c, 0x7e, 0x94, 0x8a, 0xc2, 0x27, 0xd3, 0x60, 0x40, 0x71, 0xf2, 0x0e, 0x57, 0x7e, 0x90, 0x5f, 0xbe, 0xb1, 0x5d, 0xfa, 0xf0, 0x6d, 0x1d, 0xe5, 0xae, 0x62, 0x53, 0xd6, 0x3a, 0x6a, 0x21, 0x20, 0xb3, 0x1a, 0x5d, 0xa5, 0xda, 0xbc, 0x95, 0x50, 0x60, 0x0e, 0x20, 0xf2, 0x7d, 0x37, 0x39, 0xe2, 0x62, 0x79, 0x25, 0xfe, 0xa3, 0xcc, 0x50, 0x9f, 0x21, 0xdf, 0xf0, 0x4e, 0x6e, 0xea, 0x45, 0x49, 0xc5, 0x40, 0xd6, 0x80, 0x9f, 0xf9, 0x30, 0x7e, 0xed, 0xe9, 0x1f, 0xff, 0x58, 0x73, 0x3d, 0x83, 0x85, 0xa2, 0x37, 0xd6, 0xd3, 0x70, 0x5a, 0x33, 0xe3, 0x91, 0x90, 0x09, 0x92, 0x07, 0x0d, 0xf7, 0xad, 0xf1, 0x35, 0x7c, 0xf7, 0xe3, 0x70, 0x0c, 0xe3, 0x66, 0x7d, 0xe8, 0x3f, 0x17, 0xb8, 0xdf, 0x17, 0x78, 0xdb, 0x38, 0x1d, 0xce, 0x09, 0xcb, 0x4a, 0xd0, 0x58, 0xa5, 0x11, 0x00, 0x1a, 0x73, 0x81, 0x98, 0xee, 0x27, 0xcf, 0x55, 0xa1, 0x3b, 0x75, 0x45, 0x39, 0x90, 0x65, 0x82, 0xec, 0x8b, 0x17, 0x4b, 0xd5, 0x8d, 0x5d, 0x1f, 0x3d, 0x76, 0x7c, 0x61, 0x37, 0x21, 0xae, 0x05 } +, + /* RSA public exponent e */ + 3, + { 0x01, 0x00, 0x01 } +, + /* RSA private exponent d */ + 256, + { 0x2d, 0x2f, 0xf5, 0x67, 0xb3, 0xfe, 0x74, 0xe0, 0x61, 0x91, 0xb7, 0xfd, 0xed, 0x6d, 0xe1, 0x12, 0x29, 0x0c, 0x67, 0x06, 0x92, 0x43, 0x0d, 0x59, 0x69, 0x18, 0x40, 0x47, 0xda, 0x23, 0x4c, 0x96, 0x93, 0xde, 0xed, 0x16, 0x73, 0xed, 0x42, 0x95, 0x39, 0xc9, 0x69, 0xd3, 0x72, 0xc0, 0x4d, 0x6b, 0x47, 0xe0, 0xf5, 0xb8, 0xce, 0xe0, 0x84, 0x3e, 0x5c, 0x22, 0x83, 0x5d, 0xbd, 0x3b, 0x05, 0xa0, 0x99, 0x79, 0x84, 0xae, 0x60, 0x58, 0xb1, 0x1b, 0xc4, 0x90, 0x7c, 0xbf, 0x67, 0xed, 0x84, 0xfa, 0x9a, 0xe2, 0x52, 0xdf, 0xb0, 0xd0, 0xcd, 0x49, 0xe6, 0x18, 0xe3, 0x5d, 0xfd, 0xfe, 0x59, 0xbc, 0xa3, 0xdd, 0xd6, 0x6c, 0x33, 0xce, 0xbb, 0xc7, 0x7a, 0xd4, 0x41, 0xaa, 0x69, 0x5e, 0x13, 0xe3, 0x24, 0xb5, 0x18, 0xf0, 0x1c, 0x60, 0xf5, 0xa8, 0x5c, 0x99, 0x4a, 0xd1, 0x79, 0xf2, 0xa6, 0xb5, 0xfb, 0xe9, 0x34, 0x02, 0xb1, 0x17, 0x67, 0xbe, 0x01, 0xbf, 0x07, 0x34, 0x44, 0xd6, 0xba, 0x1d, 0xd2, 0xbc, 0xa5, 0xbd, 0x07, 0x4d, 0x4a, 0x5f, 0xae, 0x35, 0x31, 0xad, 0x13, 0x03, 0xd8, 0x4b, 0x30, 0xd8, 0x97, 0x31, 0x8c, 0xbb, 0xba, 0x04, 0xe0, 0x3c, 0x2e, 0x66, 0xde, 0x6d, 0x91, 0xf8, 0x2f, 0x96, 0xea, 0x1d, 0x4b, 0xb5, 0x4a, 0x5a, 0xae, 0x10, 0x2d, 0x59, 0x46, 0x57, 0xf5, 0xc9, 0x78, 0x95, 0x53, 0x51, 0x2b, 0x29, 0x6d, 0xea, 0x29, 0xd8, 0x02, 0x31, 0x96, 0x35, 0x7e, 0x3e, 0x3a, 0x6e, 0x95, 0x8f, 0x39, 0xe3, 0xc2, 0x34, 0x40, 0x38, 0xea, 0x60, 0x4b, 0x31, 0xed, 0xc6, 0xf0, 0xf7, 0xff, 0x6e, 0x71, 0x81, 0xa5, 0x7c, 0x92, 0x82, 0x6a, 0x26, 0x8f, 0x86, 0x76, 0x8e, 0x96, 0xf8, 0x78, 0x56, 0x2f, 0xc7, 0x1d, 0x85, 0xd6, 0x9e, 0x44, 0x86, 0x12, 0xf7, 0x04, 0x8f } +, + /* Prime p */ + 128, + { 0xcf, 0xd5, 0x02, 0x83, 0xfe, 0xee, 0xb9, 0x7f, 0x6f, 0x08, 0xd7, 0x3c, 0xbc, 0x7b, 0x38, 0x36, 0xf8, 0x2b, 0xbc, 0xd4, 0x99, 0x47, 0x9f, 0x5e, 0x6f, 0x76, 0xfd, 0xfc, 0xb8, 0xb3, 0x8c, 0x4f, 0x71, 0xdc, 0x9e, 0x88, 0xbd, 0x6a, 0x6f, 0x76, 0x37, 0x1a, 0xfd, 0x65, 0xd2, 0xaf, 0x18, 0x62, 0xb3, 0x2a, 0xfb, 0x34, 0xa9, 0x5f, 0x71, 0xb8, 0xb1, 0x32, 0x04, 0x3f, 0xfe, 0xbe, 0x3a, 0x95, 0x2b, 0xaf, 0x75, 0x92, 0x44, 0x81, 0x48, 0xc0, 0x3f, 0x9c, 0x69, 0xb1, 0xd6, 0x8e, 0x4c, 0xe5, 0xcf, 0x32, 0xc8, 0x6b, 0xaf, 0x46, 0xfe, 0xd3, 0x01, 0xca, 0x1a, 0xb4, 0x03, 0x06, 0x9b, 0x32, 0xf4, 0x56, 0xb9, 0x1f, 0x71, 0x89, 0x8a, 0xb0, 0x81, 0xcd, 0x8c, 0x42, 0x52, 0xef, 0x52, 0x71, 0x91, 0x5c, 0x97, 0x94, 0xb8, 0xf2, 0x95, 0x85, 0x1d, 0xa7, 0x51, 0x0f, 0x99, 0xcb, 0x73, 0xeb } +, + /* Prime q */ + 128, + { 0xcc, 0x4e, 0x90, 0xd2, 0xa1, 0xb3, 0xa0, 0x65, 0xd3, 0xb2, 0xd1, 0xf5, 0xa8, 0xfc, 0xe3, 0x1b, 0x54, 0x44, 0x75, 0x66, 0x4e, 0xab, 0x56, 0x1d, 0x29, 0x71, 0xb9, 0x9f, 0xb7, 0xbe, 0xf8, 0x44, 0xe8, 0xec, 0x1f, 0x36, 0x0b, 0x8c, 0x2a, 0xc8, 0x35, 0x96, 0x92, 0x97, 0x1e, 0xa6, 0xa3, 0x8f, 0x72, 0x3f, 0xcc, 0x21, 0x1f, 0x5d, 0xbc, 0xb1, 0x77, 0xa0, 0xfd, 0xac, 0x51, 0x64, 0xa1, 0xd4, 0xff, 0x7f, 0xbb, 0x4e, 0x82, 0x99, 0x86, 0x35, 0x3c, 0xb9, 0x83, 0x65, 0x9a, 0x14, 0x8c, 0xdd, 0x42, 0x0c, 0x7d, 0x31, 0xba, 0x38, 0x22, 0xea, 0x90, 0xa3, 0x2b, 0xe4, 0x6c, 0x03, 0x0e, 0x8c, 0x17, 0xe1, 0xfa, 0x0a, 0xd3, 0x78, 0x59, 0xe0, 0x6b, 0x0a, 0xa6, 0xfa, 0x3b, 0x21, 0x6d, 0x9c, 0xbe, 0x6c, 0x0e, 0x22, 0x33, 0x97, 0x69, 0xc0, 0xa6, 0x15, 0x91, 0x3e, 0x5d, 0xa7, 0x19, 0xcf } +, + /* p's CRT exponent dP */ + 128, + { 0x1c, 0x2d, 0x1f, 0xc3, 0x2f, 0x6b, 0xc4, 0x00, 0x4f, 0xd8, 0x5d, 0xfd, 0xe0, 0xfb, 0xbf, 0x9a, 0x4c, 0x38, 0xf9, 0xc7, 0xc4, 0xe4, 0x1d, 0xea, 0x1a, 0xa8, 0x82, 0x34, 0xa2, 0x01, 0xcd, 0x92, 0xf3, 0xb7, 0xda, 0x52, 0x65, 0x83, 0xa9, 0x8a, 0xd8, 0x5b, 0xb3, 0x60, 0xfb, 0x98, 0x3b, 0x71, 0x1e, 0x23, 0x44, 0x9d, 0x56, 0x1d, 0x17, 0x78, 0xd7, 0xa5, 0x15, 0x48, 0x6b, 0xcb, 0xf4, 0x7b, 0x46, 0xc9, 0xe9, 0xe1, 0xa3, 0xa1, 0xf7, 0x70, 0x00, 0xef, 0xbe, 0xb0, 0x9a, 0x8a, 0xfe, 0x47, 0xe5, 0xb8, 0x57, 0xcd, 0xa9, 0x9c, 0xb1, 0x6d, 0x7f, 0xff, 0x9b, 0x71, 0x2e, 0x3b, 0xd6, 0x0c, 0xa9, 0x6d, 0x9c, 0x79, 0x73, 0xd6, 0x16, 0xd4, 0x69, 0x34, 0xa9, 0xc0, 0x50, 0x28, 0x1c, 0x00, 0x43, 0x99, 0xce, 0xff, 0x1d, 0xb7, 0xdd, 0xa7, 0x87, 0x66, 0xa8, 0xa9, 0xb9, 0xcb, 0x08, 0x73 } +, + /* q's CRT exponent dQ */ + 128, + { 0xcb, 0x3b, 0x3c, 0x04, 0xca, 0xa5, 0x8c, 0x60, 0xbe, 0x7d, 0x9b, 0x2d, 0xeb, 0xb3, 0xe3, 0x96, 0x43, 0xf4, 0xf5, 0x73, 0x97, 0xbe, 0x08, 0x23, 0x6a, 0x1e, 0x9e, 0xaf, 0xaa, 0x70, 0x65, 0x36, 0xe7, 0x1c, 0x3a, 0xcf, 0xe0, 0x1c, 0xc6, 0x51, 0xf2, 0x3c, 0x9e, 0x05, 0x85, 0x8f, 0xee, 0x13, 0xbb, 0x6a, 0x8a, 0xfc, 0x47, 0xdf, 0x4e, 0xdc, 0x9a, 0x4b, 0xa3, 0x0b, 0xce, 0xcb, 0x73, 0xd0, 0x15, 0x78, 0x52, 0x32, 0x7e, 0xe7, 0x89, 0x01, 0x5c, 0x2e, 0x8d, 0xee, 0x7b, 0x9f, 0x05, 0xa0, 0xf3, 0x1a, 0xc9, 0x4e, 0xb6, 0x17, 0x31, 0x64, 0x74, 0x0c, 0x5c, 0x95, 0x14, 0x7c, 0xd5, 0xf3, 0xb5, 0xae, 0x2c, 0xb4, 0xa8, 0x37, 0x87, 0xf0, 0x1d, 0x8a, 0xb3, 0x1f, 0x27, 0xc2, 0xd0, 0xee, 0xa2, 0xdd, 0x8a, 0x11, 0xab, 0x90, 0x6a, 0xba, 0x20, 0x7c, 0x43, 0xc6, 0xee, 0x12, 0x53, 0x31 } +, + /* CRT coefficient qInv */ + 128, + { 0x12, 0xf6, 0xb2, 0xcf, 0x13, 0x74, 0xa7, 0x36, 0xfa, 0xd0, 0x56, 0x16, 0x05, 0x0f, 0x96, 0xab, 0x4b, 0x61, 0xd1, 0x17, 0x7c, 0x7f, 0x9d, 0x52, 0x5a, 0x29, 0xf3, 0xd1, 0x80, 0xe7, 0x76, 0x67, 0xe9, 0x9d, 0x99, 0xab, 0xf0, 0x52, 0x5d, 0x07, 0x58, 0x66, 0x0f, 0x37, 0x52, 0x65, 0x5b, 0x0f, 0x25, 0xb8, 0xdf, 0x84, 0x31, 0xd9, 0xa8, 0xff, 0x77, 0xc1, 0x6c, 0x12, 0xa0, 0xa5, 0x12, 0x2a, 0x9f, 0x0b, 0xf7, 0xcf, 0xd5, 0xa2, 0x66, 0xa3, 0x5c, 0x15, 0x9f, 0x99, 0x12, 0x08, 0xb9, 0x03, 0x16, 0xff, 0x44, 0x4f, 0x3e, 0x0b, 0x6b, 0xd0, 0xe9, 0x3b, 0x8a, 0x7a, 0x24, 0x48, 0xe9, 0x57, 0xe3, 0xdd, 0xa6, 0xcf, 0xcf, 0x22, 0x66, 0xb1, 0x06, 0x01, 0x3a, 0xc4, 0x68, 0x08, 0xd3, 0xb3, 0x88, 0x7b, 0x3b, 0x00, 0x34, 0x4b, 0xaa, 0xc9, 0x53, 0x0b, 0x4c, 0xe7, 0x08, 0xfc, 0x32, 0xb6 } + +} +, +{{ + "RSASSA-PSS Signature Example 10.1", + /* Message to be signed */ + 29, + { 0x88, 0x31, 0x77, 0xe5, 0x12, 0x6b, 0x9b, 0xe2, 0xd9, 0xa9, 0x68, 0x03, 0x27, 0xd5, 0x37, 0x0c, 0x6f, 0x26, 0x86, 0x1f, 0x58, 0x20, 0xc4, 0x3d, 0xa6, 0x7a, 0x3a, 0xd6, 0x09 } +, + /* Salt */ + 20, + { 0x04, 0xe2, 0x15, 0xee, 0x6f, 0xf9, 0x34, 0xb9, 0xda, 0x70, 0xd7, 0x73, 0x0c, 0x87, 0x34, 0xab, 0xfc, 0xec, 0xde, 0x89 } +, + /* Signature */ + 256, + { 0x82, 0xc2, 0xb1, 0x60, 0x09, 0x3b, 0x8a, 0xa3, 0xc0, 0xf7, 0x52, 0x2b, 0x19, 0xf8, 0x73, 0x54, 0x06, 0x6c, 0x77, 0x84, 0x7a, 0xbf, 0x2a, 0x9f, 0xce, 0x54, 0x2d, 0x0e, 0x84, 0xe9, 0x20, 0xc5, 0xaf, 0xb4, 0x9f, 0xfd, 0xfd, 0xac, 0xe1, 0x65, 0x60, 0xee, 0x94, 0xa1, 0x36, 0x96, 0x01, 0x14, 0x8e, 0xba, 0xd7, 0xa0, 0xe1, 0x51, 0xcf, 0x16, 0x33, 0x17, 0x91, 0xa5, 0x72, 0x7d, 0x05, 0xf2, 0x1e, 0x74, 0xe7, 0xeb, 0x81, 0x14, 0x40, 0x20, 0x69, 0x35, 0xd7, 0x44, 0x76, 0x5a, 0x15, 0xe7, 0x9f, 0x01, 0x5c, 0xb6, 0x6c, 0x53, 0x2c, 0x87, 0xa6, 0xa0, 0x59, 0x61, 0xc8, 0xbf, 0xad, 0x74, 0x1a, 0x9a, 0x66, 0x57, 0x02, 0x28, 0x94, 0x39, 0x3e, 0x72, 0x23, 0x73, 0x97, 0x96, 0xc0, 0x2a, 0x77, 0x45, 0x5d, 0x0f, 0x55, 0x5b, 0x0e, 0xc0, 0x1d, 0xdf, 0x25, 0x9b, 0x62, 0x07, 0xfd, 0x0f, 0xd5, 0x76, 0x14, 0xce, 0xf1, 0xa5, 0x57, 0x3b, 0xaa, 0xff, 0x4e, 0xc0, 0x00, 0x69, 0x95, 0x16, 0x59, 0xb8, 0x5f, 0x24, 0x30, 0x0a, 0x25, 0x16, 0x0c, 0xa8, 0x52, 0x2d, 0xc6, 0xe6, 0x72, 0x7e, 0x57, 0xd0, 0x19, 0xd7, 0xe6, 0x36, 0x29, 0xb8, 0xfe, 0x5e, 0x89, 0xe2, 0x5c, 0xc1, 0x5b, 0xeb, 0x3a, 0x64, 0x75, 0x77, 0x55, 0x92, 0x99, 0x28, 0x0b, 0x9b, 0x28, 0xf7, 0x9b, 0x04, 0x09, 0x00, 0x0b, 0xe2, 0x5b, 0xbd, 0x96, 0x40, 0x8b, 0xa3, 0xb4, 0x3c, 0xc4, 0x86, 0x18, 0x4d, 0xd1, 0xc8, 0xe6, 0x25, 0x53, 0xfa, 0x1a, 0xf4, 0x04, 0x0f, 0x60, 0x66, 0x3d, 0xe7, 0xf5, 0xe4, 0x9c, 0x04, 0x38, 0x8e, 0x25, 0x7f, 0x1c, 0xe8, 0x9c, 0x95, 0xda, 0xb4, 0x8a, 0x31, 0x5d, 0x9b, 0x66, 0xb1, 0xb7, 0x62, 0x82, 0x33, 0x87, 0x6f, 0xf2, 0x38, 0x52, 0x30, 0xd0, 0x70, 0xd0, 0x7e, 0x16, 0x66 } + +} +, +#ifdef LTC_TEST_EXT +{ + "RSASSA-PSS Signature Example 10.2", + /* Message to be signed */ + 128, + { 0xdd, 0x67, 0x0a, 0x01, 0x46, 0x58, 0x68, 0xad, 0xc9, 0x3f, 0x26, 0x13, 0x19, 0x57, 0xa5, 0x0c, 0x52, 0xfb, 0x77, 0x7c, 0xdb, 0xaa, 0x30, 0x89, 0x2c, 0x9e, 0x12, 0x36, 0x11, 0x64, 0xec, 0x13, 0x97, 0x9d, 0x43, 0x04, 0x81, 0x18, 0xe4, 0x44, 0x5d, 0xb8, 0x7b, 0xee, 0x58, 0xdd, 0x98, 0x7b, 0x34, 0x25, 0xd0, 0x20, 0x71, 0xd8, 0xdb, 0xae, 0x80, 0x70, 0x8b, 0x03, 0x9d, 0xbb, 0x64, 0xdb, 0xd1, 0xde, 0x56, 0x57, 0xd9, 0xfe, 0xd0, 0xc1, 0x18, 0xa5, 0x41, 0x43, 0x74, 0x2e, 0x0f, 0xf3, 0xc8, 0x7f, 0x74, 0xe4, 0x58, 0x57, 0x64, 0x7a, 0xf3, 0xf7, 0x9e, 0xb0, 0xa1, 0x4c, 0x9d, 0x75, 0xea, 0x9a, 0x1a, 0x04, 0xb7, 0xcf, 0x47, 0x8a, 0x89, 0x7a, 0x70, 0x8f, 0xd9, 0x88, 0xf4, 0x8e, 0x80, 0x1e, 0xdb, 0x0b, 0x70, 0x39, 0xdf, 0x8c, 0x23, 0xbb, 0x3c, 0x56, 0xf4, 0xe8, 0x21, 0xac } +, + /* Salt */ + 20, + { 0x8b, 0x2b, 0xdd, 0x4b, 0x40, 0xfa, 0xf5, 0x45, 0xc7, 0x78, 0xdd, 0xf9, 0xbc, 0x1a, 0x49, 0xcb, 0x57, 0xf9, 0xb7, 0x1b } +, + /* Signature */ + 256, + { 0x14, 0xae, 0x35, 0xd9, 0xdd, 0x06, 0xba, 0x92, 0xf7, 0xf3, 0xb8, 0x97, 0x97, 0x8a, 0xed, 0x7c, 0xd4, 0xbf, 0x5f, 0xf0, 0xb5, 0x85, 0xa4, 0x0b, 0xd4, 0x6c, 0xe1, 0xb4, 0x2c, 0xd2, 0x70, 0x30, 0x53, 0xbb, 0x90, 0x44, 0xd6, 0x4e, 0x81, 0x3d, 0x8f, 0x96, 0xdb, 0x2d, 0xd7, 0x00, 0x7d, 0x10, 0x11, 0x8f, 0x6f, 0x8f, 0x84, 0x96, 0x09, 0x7a, 0xd7, 0x5e, 0x1f, 0xf6, 0x92, 0x34, 0x1b, 0x28, 0x92, 0xad, 0x55, 0xa6, 0x33, 0xa1, 0xc5, 0x5e, 0x7f, 0x0a, 0x0a, 0xd5, 0x9a, 0x0e, 0x20, 0x3a, 0x5b, 0x82, 0x78, 0xae, 0xc5, 0x4d, 0xd8, 0x62, 0x2e, 0x28, 0x31, 0xd8, 0x71, 0x74, 0xf8, 0xca, 0xff, 0x43, 0xee, 0x6c, 0x46, 0x44, 0x53, 0x45, 0xd8, 0x4a, 0x59, 0x65, 0x9b, 0xfb, 0x92, 0xec, 0xd4, 0xc8, 0x18, 0x66, 0x86, 0x95, 0xf3, 0x47, 0x06, 0xf6, 0x68, 0x28, 0xa8, 0x99, 0x59, 0x63, 0x7f, 0x2b, 0xf3, 0xe3, 0x25, 0x1c, 0x24, 0xbd, 0xba, 0x4d, 0x4b, 0x76, 0x49, 0xda, 0x00, 0x22, 0x21, 0x8b, 0x11, 0x9c, 0x84, 0xe7, 0x9a, 0x65, 0x27, 0xec, 0x5b, 0x8a, 0x5f, 0x86, 0x1c, 0x15, 0x99, 0x52, 0xe2, 0x3e, 0xc0, 0x5e, 0x1e, 0x71, 0x73, 0x46, 0xfa, 0xef, 0xe8, 0xb1, 0x68, 0x68, 0x25, 0xbd, 0x2b, 0x26, 0x2f, 0xb2, 0x53, 0x10, 0x66, 0xc0, 0xde, 0x09, 0xac, 0xde, 0x2e, 0x42, 0x31, 0x69, 0x07, 0x28, 0xb5, 0xd8, 0x5e, 0x11, 0x5a, 0x2f, 0x6b, 0x92, 0xb7, 0x9c, 0x25, 0xab, 0xc9, 0xbd, 0x93, 0x99, 0xff, 0x8b, 0xcf, 0x82, 0x5a, 0x52, 0xea, 0x1f, 0x56, 0xea, 0x76, 0xdd, 0x26, 0xf4, 0x3b, 0xaa, 0xfa, 0x18, 0xbf, 0xa9, 0x2a, 0x50, 0x4c, 0xbd, 0x35, 0x69, 0x9e, 0x26, 0xd1, 0xdc, 0xc5, 0xa2, 0x88, 0x73, 0x85, 0xf3, 0xc6, 0x32, 0x32, 0xf0, 0x6f, 0x32, 0x44, 0xc3 } + +} +, +{ + "RSASSA-PSS Signature Example 10.3", + /* Message to be signed */ + 110, + { 0x48, 0xb2, 0xb6, 0xa5, 0x7a, 0x63, 0xc8, 0x4c, 0xea, 0x85, 0x9d, 0x65, 0xc6, 0x68, 0x28, 0x4b, 0x08, 0xd9, 0x6b, 0xdc, 0xaa, 0xbe, 0x25, 0x2d, 0xb0, 0xe4, 0xa9, 0x6c, 0xb1, 0xba, 0xc6, 0x01, 0x93, 0x41, 0xdb, 0x6f, 0xbe, 0xfb, 0x8d, 0x10, 0x6b, 0x0e, 0x90, 0xed, 0xa6, 0xbc, 0xc6, 0xc6, 0x26, 0x2f, 0x37, 0xe7, 0xea, 0x9c, 0x7e, 0x5d, 0x22, 0x6b, 0xd7, 0xdf, 0x85, 0xec, 0x5e, 0x71, 0xef, 0xff, 0x2f, 0x54, 0xc5, 0xdb, 0x57, 0x7f, 0xf7, 0x29, 0xff, 0x91, 0xb8, 0x42, 0x49, 0x1d, 0xe2, 0x74, 0x1d, 0x0c, 0x63, 0x16, 0x07, 0xdf, 0x58, 0x6b, 0x90, 0x5b, 0x23, 0xb9, 0x1a, 0xf1, 0x3d, 0xa1, 0x23, 0x04, 0xbf, 0x83, 0xec, 0xa8, 0xa7, 0x3e, 0x87, 0x1f, 0xf9, 0xdb } +, + /* Salt */ + 20, + { 0x4e, 0x96, 0xfc, 0x1b, 0x39, 0x8f, 0x92, 0xb4, 0x46, 0x71, 0x01, 0x0c, 0x0d, 0xc3, 0xef, 0xd6, 0xe2, 0x0c, 0x2d, 0x73 } +, + /* Signature */ + 256, + { 0x6e, 0x3e, 0x4d, 0x7b, 0x6b, 0x15, 0xd2, 0xfb, 0x46, 0x01, 0x3b, 0x89, 0x00, 0xaa, 0x5b, 0xbb, 0x39, 0x39, 0xcf, 0x2c, 0x09, 0x57, 0x17, 0x98, 0x70, 0x42, 0x02, 0x6e, 0xe6, 0x2c, 0x74, 0xc5, 0x4c, 0xff, 0xd5, 0xd7, 0xd5, 0x7e, 0xfb, 0xbf, 0x95, 0x0a, 0x0f, 0x5c, 0x57, 0x4f, 0xa0, 0x9d, 0x3f, 0xc1, 0xc9, 0xf5, 0x13, 0xb0, 0x5b, 0x4f, 0xf5, 0x0d, 0xd8, 0xdf, 0x7e, 0xdf, 0xa2, 0x01, 0x02, 0x85, 0x4c, 0x35, 0xe5, 0x92, 0x18, 0x01, 0x19, 0xa7, 0x0c, 0xe5, 0xb0, 0x85, 0x18, 0x2a, 0xa0, 0x2d, 0x9e, 0xa2, 0xaa, 0x90, 0xd1, 0xdf, 0x03, 0xf2, 0xda, 0xae, 0x88, 0x5b, 0xa2, 0xf5, 0xd0, 0x5a, 0xfd, 0xac, 0x97, 0x47, 0x6f, 0x06, 0xb9, 0x3b, 0x5b, 0xc9, 0x4a, 0x1a, 0x80, 0xaa, 0x91, 0x16, 0xc4, 0xd6, 0x15, 0xf3, 0x33, 0xb0, 0x98, 0x89, 0x2b, 0x25, 0xff, 0xac, 0xe2, 0x66, 0xf5, 0xdb, 0x5a, 0x5a, 0x3b, 0xcc, 0x10, 0xa8, 0x24, 0xed, 0x55, 0xaa, 0xd3, 0x5b, 0x72, 0x78, 0x34, 0xfb, 0x8c, 0x07, 0xda, 0x28, 0xfc, 0xf4, 0x16, 0xa5, 0xd9, 0xb2, 0x22, 0x4f, 0x1f, 0x8b, 0x44, 0x2b, 0x36, 0xf9, 0x1e, 0x45, 0x6f, 0xde, 0xa2, 0xd7, 0xcf, 0xe3, 0x36, 0x72, 0x68, 0xde, 0x03, 0x07, 0xa4, 0xc7, 0x4e, 0x92, 0x41, 0x59, 0xed, 0x33, 0x39, 0x3d, 0x5e, 0x06, 0x55, 0x53, 0x1c, 0x77, 0x32, 0x7b, 0x89, 0x82, 0x1b, 0xde, 0xdf, 0x88, 0x01, 0x61, 0xc7, 0x8c, 0xd4, 0x19, 0x6b, 0x54, 0x19, 0xf7, 0xac, 0xc3, 0xf1, 0x3e, 0x5e, 0xbf, 0x16, 0x1b, 0x6e, 0x7c, 0x67, 0x24, 0x71, 0x6c, 0xa3, 0x3b, 0x85, 0xc2, 0xe2, 0x56, 0x40, 0x19, 0x2a, 0xc2, 0x85, 0x96, 0x51, 0xd5, 0x0b, 0xde, 0x7e, 0xb9, 0x76, 0xe5, 0x1c, 0xec, 0x82, 0x8b, 0x98, 0xb6, 0x56, 0x3b, 0x86, 0xbb } + +} +, +{ + "RSASSA-PSS Signature Example 10.4", + /* Message to be signed */ + 81, + { 0x0b, 0x87, 0x77, 0xc7, 0xf8, 0x39, 0xba, 0xf0, 0xa6, 0x4b, 0xbb, 0xdb, 0xc5, 0xce, 0x79, 0x75, 0x5c, 0x57, 0xa2, 0x05, 0xb8, 0x45, 0xc1, 0x74, 0xe2, 0xd2, 0xe9, 0x05, 0x46, 0xa0, 0x89, 0xc4, 0xe6, 0xec, 0x8a, 0xdf, 0xfa, 0x23, 0xa7, 0xea, 0x97, 0xba, 0xe6, 0xb6, 0x5d, 0x78, 0x2b, 0x82, 0xdb, 0x5d, 0x2b, 0x5a, 0x56, 0xd2, 0x2a, 0x29, 0xa0, 0x5e, 0x7c, 0x44, 0x33, 0xe2, 0xb8, 0x2a, 0x62, 0x1a, 0xbb, 0xa9, 0x0a, 0xdd, 0x05, 0xce, 0x39, 0x3f, 0xc4, 0x8a, 0x84, 0x05, 0x42, 0x45, 0x1a } +, + /* Salt */ + 20, + { 0xc7, 0xcd, 0x69, 0x8d, 0x84, 0xb6, 0x51, 0x28, 0xd8, 0x83, 0x5e, 0x3a, 0x8b, 0x1e, 0xb0, 0xe0, 0x1c, 0xb5, 0x41, 0xec } +, + /* Signature */ + 256, + { 0x34, 0x04, 0x7f, 0xf9, 0x6c, 0x4d, 0xc0, 0xdc, 0x90, 0xb2, 0xd4, 0xff, 0x59, 0xa1, 0xa3, 0x61, 0xa4, 0x75, 0x4b, 0x25, 0x5d, 0x2e, 0xe0, 0xaf, 0x7d, 0x8b, 0xf8, 0x7c, 0x9b, 0xc9, 0xe7, 0xdd, 0xee, 0xde, 0x33, 0x93, 0x4c, 0x63, 0xca, 0x1c, 0x0e, 0x3d, 0x26, 0x2c, 0xb1, 0x45, 0xef, 0x93, 0x2a, 0x1f, 0x2c, 0x0a, 0x99, 0x7a, 0xa6, 0xa3, 0x4f, 0x8e, 0xae, 0xe7, 0x47, 0x7d, 0x82, 0xcc, 0xf0, 0x90, 0x95, 0xa6, 0xb8, 0xac, 0xad, 0x38, 0xd4, 0xee, 0xc9, 0xfb, 0x7e, 0xab, 0x7a, 0xd0, 0x2d, 0xa1, 0xd1, 0x1d, 0x8e, 0x54, 0xc1, 0x82, 0x5e, 0x55, 0xbf, 0x58, 0xc2, 0xa2, 0x32, 0x34, 0xb9, 0x02, 0xbe, 0x12, 0x4f, 0x9e, 0x90, 0x38, 0xa8, 0xf6, 0x8f, 0xa4, 0x5d, 0xab, 0x72, 0xf6, 0x6e, 0x09, 0x45, 0xbf, 0x1d, 0x8b, 0xac, 0xc9, 0x04, 0x4c, 0x6f, 0x07, 0x09, 0x8c, 0x9f, 0xce, 0xc5, 0x8a, 0x3a, 0xab, 0x10, 0x0c, 0x80, 0x51, 0x78, 0x15, 0x5f, 0x03, 0x0a, 0x12, 0x4c, 0x45, 0x0e, 0x5a, 0xcb, 0xda, 0x47, 0xd0, 0xe4, 0xf1, 0x0b, 0x80, 0xa2, 0x3f, 0x80, 0x3e, 0x77, 0x4d, 0x02, 0x3b, 0x00, 0x15, 0xc2, 0x0b, 0x9f, 0x9b, 0xbe, 0x7c, 0x91, 0x29, 0x63, 0x38, 0xd5, 0xec, 0xb4, 0x71, 0xca, 0xfb, 0x03, 0x20, 0x07, 0xb6, 0x7a, 0x60, 0xbe, 0x5f, 0x69, 0x50, 0x4a, 0x9f, 0x01, 0xab, 0xb3, 0xcb, 0x46, 0x7b, 0x26, 0x0e, 0x2b, 0xce, 0x86, 0x0b, 0xe8, 0xd9, 0x5b, 0xf9, 0x2c, 0x0c, 0x8e, 0x14, 0x96, 0xed, 0x1e, 0x52, 0x85, 0x93, 0xa4, 0xab, 0xb6, 0xdf, 0x46, 0x2d, 0xde, 0x8a, 0x09, 0x68, 0xdf, 0xfe, 0x46, 0x83, 0x11, 0x68, 0x57, 0xa2, 0x32, 0xf5, 0xeb, 0xf6, 0xc8, 0x5b, 0xe2, 0x38, 0x74, 0x5a, 0xd0, 0xf3, 0x8f, 0x76, 0x7a, 0x5f, 0xdb, 0xf4, 0x86, 0xfb } + +} +, +{ + "RSASSA-PSS Signature Example 10.5", + /* Message to be signed */ + 81, + { 0xf1, 0x03, 0x6e, 0x00, 0x8e, 0x71, 0xe9, 0x64, 0xda, 0xdc, 0x92, 0x19, 0xed, 0x30, 0xe1, 0x7f, 0x06, 0xb4, 0xb6, 0x8a, 0x95, 0x5c, 0x16, 0xb3, 0x12, 0xb1, 0xed, 0xdf, 0x02, 0x8b, 0x74, 0x97, 0x6b, 0xed, 0x6b, 0x3f, 0x6a, 0x63, 0xd4, 0xe7, 0x78, 0x59, 0x24, 0x3c, 0x9c, 0xcc, 0xdc, 0x98, 0x01, 0x65, 0x23, 0xab, 0xb0, 0x24, 0x83, 0xb3, 0x55, 0x91, 0xc3, 0x3a, 0xad, 0x81, 0x21, 0x3b, 0xb7, 0xc7, 0xbb, 0x1a, 0x47, 0x0a, 0xab, 0xc1, 0x0d, 0x44, 0x25, 0x6c, 0x4d, 0x45, 0x59, 0xd9, 0x16 } +, + /* Salt */ + 20, + { 0xef, 0xa8, 0xbf, 0xf9, 0x62, 0x12, 0xb2, 0xf4, 0xa3, 0xf3, 0x71, 0xa1, 0x0d, 0x57, 0x41, 0x52, 0x65, 0x5f, 0x5d, 0xfb } +, + /* Signature */ + 256, + { 0x7e, 0x09, 0x35, 0xea, 0x18, 0xf4, 0xd6, 0xc1, 0xd1, 0x7c, 0xe8, 0x2e, 0xb2, 0xb3, 0x83, 0x6c, 0x55, 0xb3, 0x84, 0x58, 0x9c, 0xe1, 0x9d, 0xfe, 0x74, 0x33, 0x63, 0xac, 0x99, 0x48, 0xd1, 0xf3, 0x46, 0xb7, 0xbf, 0xdd, 0xfe, 0x92, 0xef, 0xd7, 0x8a, 0xdb, 0x21, 0xfa, 0xef, 0xc8, 0x9a, 0xde, 0x42, 0xb1, 0x0f, 0x37, 0x40, 0x03, 0xfe, 0x12, 0x2e, 0x67, 0x42, 0x9a, 0x1c, 0xb8, 0xcb, 0xd1, 0xf8, 0xd9, 0x01, 0x45, 0x64, 0xc4, 0x4d, 0x12, 0x01, 0x16, 0xf4, 0x99, 0x0f, 0x1a, 0x6e, 0x38, 0x77, 0x4c, 0x19, 0x4b, 0xd1, 0xb8, 0x21, 0x32, 0x86, 0xb0, 0x77, 0xb0, 0x49, 0x9d, 0x2e, 0x7b, 0x3f, 0x43, 0x4a, 0xb1, 0x22, 0x89, 0xc5, 0x56, 0x68, 0x4d, 0xee, 0xd7, 0x81, 0x31, 0x93, 0x4b, 0xb3, 0xdd, 0x65, 0x37, 0x23, 0x6f, 0x7c, 0x6f, 0x3d, 0xcb, 0x09, 0xd4, 0x76, 0xbe, 0x07, 0x72, 0x1e, 0x37, 0xe1, 0xce, 0xed, 0x9b, 0x2f, 0x7b, 0x40, 0x68, 0x87, 0xbd, 0x53, 0x15, 0x73, 0x05, 0xe1, 0xc8, 0xb4, 0xf8, 0x4d, 0x73, 0x3b, 0xc1, 0xe1, 0x86, 0xfe, 0x06, 0xcc, 0x59, 0xb6, 0xed, 0xb8, 0xf4, 0xbd, 0x7f, 0xfe, 0xfd, 0xf4, 0xf7, 0xba, 0x9c, 0xfb, 0x9d, 0x57, 0x06, 0x89, 0xb5, 0xa1, 0xa4, 0x10, 0x9a, 0x74, 0x6a, 0x69, 0x08, 0x93, 0xdb, 0x37, 0x99, 0x25, 0x5a, 0x0c, 0xb9, 0x21, 0x5d, 0x2d, 0x1c, 0xd4, 0x90, 0x59, 0x0e, 0x95, 0x2e, 0x8c, 0x87, 0x86, 0xaa, 0x00, 0x11, 0x26, 0x52, 0x52, 0x47, 0x0c, 0x04, 0x1d, 0xfb, 0xc3, 0xee, 0xc7, 0xc3, 0xcb, 0xf7, 0x1c, 0x24, 0x86, 0x9d, 0x11, 0x5c, 0x0c, 0xb4, 0xa9, 0x56, 0xf5, 0x6d, 0x53, 0x0b, 0x80, 0xab, 0x58, 0x9a, 0xcf, 0xef, 0xc6, 0x90, 0x75, 0x1d, 0xdf, 0x36, 0xe8, 0xd3, 0x83, 0xf8, 0x3c, 0xed, 0xd2, 0xcc } + +} +, +{ + "RSASSA-PSS Signature Example 10.6", + /* Message to be signed */ + 163, + { 0x25, 0xf1, 0x08, 0x95, 0xa8, 0x77, 0x16, 0xc1, 0x37, 0x45, 0x0b, 0xb9, 0x51, 0x9d, 0xfa, 0xa1, 0xf2, 0x07, 0xfa, 0xa9, 0x42, 0xea, 0x88, 0xab, 0xf7, 0x1e, 0x9c, 0x17, 0x98, 0x00, 0x85, 0xb5, 0x55, 0xae, 0xba, 0xb7, 0x62, 0x64, 0xae, 0x2a, 0x3a, 0xb9, 0x3c, 0x2d, 0x12, 0x98, 0x11, 0x91, 0xdd, 0xac, 0x6f, 0xb5, 0x94, 0x9e, 0xb3, 0x6a, 0xee, 0x3c, 0x5d, 0xa9, 0x40, 0xf0, 0x07, 0x52, 0xc9, 0x16, 0xd9, 0x46, 0x08, 0xfa, 0x7d, 0x97, 0xba, 0x6a, 0x29, 0x15, 0xb6, 0x88, 0xf2, 0x03, 0x23, 0xd4, 0xe9, 0xd9, 0x68, 0x01, 0xd8, 0x9a, 0x72, 0xab, 0x58, 0x92, 0xdc, 0x21, 0x17, 0xc0, 0x74, 0x34, 0xfc, 0xf9, 0x72, 0xe0, 0x58, 0xcf, 0x8c, 0x41, 0xca, 0x4b, 0x4f, 0xf5, 0x54, 0xf7, 0xd5, 0x06, 0x8a, 0xd3, 0x15, 0x5f, 0xce, 0xd0, 0xf3, 0x12, 0x5b, 0xc0, 0x4f, 0x91, 0x93, 0x37, 0x8a, 0x8f, 0x5c, 0x4c, 0x3b, 0x8c, 0xb4, 0xdd, 0x6d, 0x1c, 0xc6, 0x9d, 0x30, 0xec, 0xca, 0x6e, 0xaa, 0x51, 0xe3, 0x6a, 0x05, 0x73, 0x0e, 0x9e, 0x34, 0x2e, 0x85, 0x5b, 0xaf, 0x09, 0x9d, 0xef, 0xb8, 0xaf, 0xd7 } +, + /* Salt */ + 20, + { 0xad, 0x8b, 0x15, 0x23, 0x70, 0x36, 0x46, 0x22, 0x4b, 0x66, 0x0b, 0x55, 0x08, 0x85, 0x91, 0x7c, 0xa2, 0xd1, 0xdf, 0x28 } +, + /* Signature */ + 256, + { 0x6d, 0x3b, 0x5b, 0x87, 0xf6, 0x7e, 0xa6, 0x57, 0xaf, 0x21, 0xf7, 0x54, 0x41, 0x97, 0x7d, 0x21, 0x80, 0xf9, 0x1b, 0x2c, 0x5f, 0x69, 0x2d, 0xe8, 0x29, 0x55, 0x69, 0x6a, 0x68, 0x67, 0x30, 0xd9, 0xb9, 0x77, 0x8d, 0x97, 0x07, 0x58, 0xcc, 0xb2, 0x60, 0x71, 0xc2, 0x20, 0x9f, 0xfb, 0xd6, 0x12, 0x5b, 0xe2, 0xe9, 0x6e, 0xa8, 0x1b, 0x67, 0xcb, 0x9b, 0x93, 0x08, 0x23, 0x9f, 0xda, 0x17, 0xf7, 0xb2, 0xb6, 0x4e, 0xcd, 0xa0, 0x96, 0xb6, 0xb9, 0x35, 0x64, 0x0a, 0x5a, 0x1c, 0xb4, 0x2a, 0x91, 0x55, 0xb1, 0xc9, 0xef, 0x7a, 0x63, 0x3a, 0x02, 0xc5, 0x9f, 0x0d, 0x6e, 0xe5, 0x9b, 0x85, 0x2c, 0x43, 0xb3, 0x50, 0x29, 0xe7, 0x3c, 0x94, 0x0f, 0xf0, 0x41, 0x0e, 0x8f, 0x11, 0x4e, 0xed, 0x46, 0xbb, 0xd0, 0xfa, 0xe1, 0x65, 0xe4, 0x2b, 0xe2, 0x52, 0x8a, 0x40, 0x1c, 0x3b, 0x28, 0xfd, 0x81, 0x8e, 0xf3, 0x23, 0x2d, 0xca, 0x9f, 0x4d, 0x2a, 0x0f, 0x51, 0x66, 0xec, 0x59, 0xc4, 0x23, 0x96, 0xd6, 0xc1, 0x1d, 0xbc, 0x12, 0x15, 0xa5, 0x6f, 0xa1, 0x71, 0x69, 0xdb, 0x95, 0x75, 0x34, 0x3e, 0xf3, 0x4f, 0x9d, 0xe3, 0x2a, 0x49, 0xcd, 0xc3, 0x17, 0x49, 0x22, 0xf2, 0x29, 0xc2, 0x3e, 0x18, 0xe4, 0x5d, 0xf9, 0x35, 0x31, 0x19, 0xec, 0x43, 0x19, 0xce, 0xdc, 0xe7, 0xa1, 0x7c, 0x64, 0x08, 0x8c, 0x1f, 0x6f, 0x52, 0xbe, 0x29, 0x63, 0x41, 0x00, 0xb3, 0x91, 0x9d, 0x38, 0xf3, 0xd1, 0xed, 0x94, 0xe6, 0x89, 0x1e, 0x66, 0xa7, 0x3b, 0x8f, 0xb8, 0x49, 0xf5, 0x87, 0x4d, 0xf5, 0x94, 0x59, 0xe2, 0x98, 0xc7, 0xbb, 0xce, 0x2e, 0xee, 0x78, 0x2a, 0x19, 0x5a, 0xa6, 0x6f, 0xe2, 0xd0, 0x73, 0x2b, 0x25, 0xe5, 0x95, 0xf5, 0x7d, 0x3e, 0x06, 0x1b, 0x1f, 0xc3, 0xe4, 0x06, 0x3b, 0xf9, 0x8f } + +} +, +#endif /* LTC_TEST_EXT */ +} +}, +}; + diff --git a/deps/libtomcrypt/notes/rsa-testvectors/pss-vect.txt b/deps/libtomcrypt/notes/rsa-testvectors/pss-vect.txt new file mode 100644 index 0000000..b33e0ec --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/pss-vect.txt @@ -0,0 +1,2581 @@ +# =========================== +# TEST VECTORS FOR RSASSA-PSS +# =========================== +# +# This file contains test vectors for the +# RSASSA-PSS signature scheme with appendix as +# defined in PKCS #1 v2.1. 10 RSA keys of +# different sizes have been generated. For each +# key, 6 random messages of length between 1 +# and 256 octets have been RSASSA-PSS signed +# via a random salt of length 20 octets. +# +# The underlying hash function in the EMSA-PSS +# encoding method is SHA-1; the mask generation +# function is MGF1 with SHA-1 as specified in +# PKCS #1 v2.1. +# +# Integers are represented by strings of octets +# with the leftmost octet being the most +# significant octet. For example, +# +# 9,202,000 = (0x)8c 69 50. +# +# Key lengths: +# +# Key 1: 1024 bits +# Key 2: 1025 bits +# Key 3: 1026 bits +# Key 4: 1027 bits +# Key 5: 1028 bits +# Key 6: 1029 bits +# Key 7: 1030 bits +# Key 8: 1031 bits +# Key 9: 1536 bits +# Key 10: 2048 bits +# +# ============================================= + +# ================================== +# Example 1: A 1024-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 +56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 +d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 +94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df +d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 +c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 +05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 +ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47 +71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8 +94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8 +c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a +e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27 +a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c +31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b +d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25 + +# Prime p: +e7 e8 94 27 20 a8 77 51 72 73 a3 56 05 3e a2 a1 +bc 0c 94 aa 72 d5 5c 6e 86 29 6b 2d fc 96 79 48 +c0 a7 2c bc cc a7 ea cb 35 70 6e 09 a1 df 55 a1 +53 5b d9 b3 cc 34 16 0b 3b 6d cd 3e da 8e 64 43 + +# Prime q: +b6 9d ca 1c f7 d4 d7 ec 81 e7 5b 90 fc ca 87 4a +bc de 12 3f d2 70 01 80 aa 90 47 9b 6e 48 de 8d +67 ed 24 f9 f1 9d 85 ba 27 58 74 f5 42 cd 20 dc +72 3e 69 63 36 4a 1f 94 25 45 2b 26 9a 67 99 fd + +# p's CRT exponent dP: +28 fa 13 93 86 55 be 1f 8a 15 9c ba ca 5a 72 ea +19 0c 30 08 9e 19 cd 27 4a 55 6f 36 c4 f6 e1 9f +55 4b 34 c0 77 79 04 27 bb dd 8d d3 ed e2 44 83 +28 f3 85 d8 1b 30 e8 e4 3b 2f ff a0 27 86 19 79 + +# q's CRT exponent dQ: +1a 8b 38 f3 98 fa 71 20 49 89 8d 7f b7 9e e0 a7 +76 68 79 12 99 cd fa 09 ef c0 e5 07 ac b2 1e d7 +43 01 ef 5b fd 48 be 45 5e ae b6 e1 67 82 55 82 +75 80 a8 e4 e8 e1 41 51 d1 51 0a 82 a3 f2 e7 29 + +# CRT coefficient qInv: +27 15 6a ba 41 26 d2 4a 81 f3 a5 28 cb fb 27 f5 +68 86 f8 40 a9 f6 e8 6e 17 a4 4b 94 fe 93 19 58 +4b 8e 22 fd de 1e 5a 2e 3b d8 aa 5b a8 d8 58 41 +94 eb 21 90 ac f8 32 b8 47 f1 3a 3d 24 a7 9f 4d + +# -------------------------------- +# RSASSA-PSS Signature Example 1.1 +# -------------------------------- + +# Message to be signed: +cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26 +d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6 +23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15 +6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76 +97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3 +d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0 +61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29 +cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61 +93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08 +a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c +29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca +b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16 +be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed +1b 73 31 8b 75 0a 01 67 d0 + +# Salt: +de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f +3e 67 76 af + +# Signature: +90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71 +fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87 +e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2 +26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15 +df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9 +c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65 +98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4 +c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c + +# -------------------------------- +# RSASSA-PSS Signature Example 1.2 +# -------------------------------- + +# Message to be signed: +85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c +f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f +71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13 +22 6b 9e + +# Salt: +ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f +d5 6d f4 2d + +# Signature: +3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce +fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e +f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db +0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45 +17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4 +cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35 +90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14 +18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43 + +# -------------------------------- +# RSASSA-PSS Signature Example 1.3 +# -------------------------------- + +# Message to be signed: +a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5 +aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef +8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d +fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55 +fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db +43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7 +45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29 +c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4 +56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17 +be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c +03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b +79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa +29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61 +8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13 +38 e7 d4 70 + +# Salt: +71 0b 9c 47 47 d8 00 d4 de 87 f1 2a fd ce 6d f1 +81 07 cc 77 + +# Signature: +66 60 26 fb a7 1b d3 e7 cf 13 15 7c c2 c5 1a 8e +4a a6 84 af 97 78 f9 18 49 f3 43 35 d1 41 c0 01 +54 c4 19 76 21 f9 62 4a 67 5b 5a bc 22 ee 7d 5b +aa ff aa e1 c9 ba ca 2c c3 73 b3 f3 3e 78 e6 14 +3c 39 5a 91 aa 7f ac a6 64 eb 73 3a fd 14 d8 82 +72 59 d9 9a 75 50 fa ca 50 1e f2 b0 4e 33 c2 3a +a5 1f 4b 9e 82 82 ef db 72 8c c0 ab 09 40 5a 91 +60 7c 63 69 96 1b c8 27 0d 2d 4f 39 fc e6 12 b1 + +# -------------------------------- +# RSASSA-PSS Signature Example 1.4 +# -------------------------------- + +# Message to be signed: +bc 65 67 47 fa 9e af b3 f0 + +# Salt: +05 6f 00 98 5d e1 4d 8e f5 ce a9 e8 2f 8c 27 be +f7 20 33 5e + +# Signature: +46 09 79 3b 23 e9 d0 93 62 dc 21 bb 47 da 0b 4f +3a 76 22 64 9a 47 d4 64 01 9b 9a ea fe 53 35 9c +17 8c 91 cd 58 ba 6b cb 78 be 03 46 a7 bc 63 7f +4b 87 3d 4b ab 38 ee 66 1f 19 96 34 c5 47 a1 ad +84 42 e0 3d a0 15 b1 36 e5 43 f7 ab 07 c0 c1 3e +42 25 b8 de 8c ce 25 d4 f6 eb 84 00 f8 1f 7e 18 +33 b7 ee 6e 33 4d 37 09 64 ca 79 fd b8 72 b4 d7 +52 23 b5 ee b0 81 01 59 1f b5 32 d1 55 a6 de 87 + +# -------------------------------- +# RSASSA-PSS Signature Example 1.5 +# -------------------------------- + +# Message to be signed: +b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64 +e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76 +c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e +f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75 +48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4 +b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f +32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7 +82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc +5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f +45 5a 69 09 b4 + +# Salt: +80 e7 0f f8 6a 08 de 3e c6 09 72 b3 9b 4f bf dc +ea 67 ae 8e + +# Signature: +1d 2a ad 22 1c a4 d3 1d df 13 50 92 39 01 93 98 +e3 d1 4b 32 dc 34 dc 5a f4 ae ae a3 c0 95 af 73 +47 9c f0 a4 5e 56 29 63 5a 53 a0 18 37 76 15 b1 +6c b9 b1 3b 3e 09 d6 71 eb 71 e3 87 b8 54 5c 59 +60 da 5a 64 77 6e 76 8e 82 b2 c9 35 83 bf 10 4c +3f db 23 51 2b 7b 4e 89 f6 33 dd 00 63 a5 30 db +45 24 b0 1c 3f 38 4c 09 31 0e 31 5a 79 dc d3 d6 +84 02 2a 7f 31 c8 65 a6 64 e3 16 97 8b 75 9f ad + +# -------------------------------- +# RSASSA-PSS Signature Example 1.6 +# -------------------------------- + +# Message to be signed: +10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7 +5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec +74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4 +3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4 +35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90 +9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7 +05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad +b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87 +94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00 +44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73 +d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29 +51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb +3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf +e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6 +13 8d 14 4f 8c e4 e2 da 73 + +# Salt: +a8 ab 69 dd 80 1f 00 74 c2 a1 fc 60 64 98 36 c6 +16 d9 96 81 + +# Signature: +2a 34 f6 12 5e 1f 6b 0b f9 71 e8 4f bd 41 c6 32 +be 8f 2c 2a ce 7d e8 b6 92 6e 31 ff 93 e9 af 98 +7f bc 06 e5 1e 9b e1 4f 51 98 f9 1f 3f 95 3b d6 +7d a6 0a 9d f5 97 64 c3 dc 0f e0 8e 1c be f0 b7 +5f 86 8d 10 ad 3f ba 74 9f ef 59 fb 6d ac 46 a0 +d6 e5 04 36 93 31 58 6f 58 e4 62 8f 39 aa 27 89 +82 54 3b c0 ee b5 37 dc 61 95 80 19 b3 94 fb 27 +3f 21 58 58 a0 a0 1a c4 d6 50 b9 55 c6 7f 4c 58 + +# ============================================= + +# ================================== +# Example 2: A 1025-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +01 d4 0c 1b cf 97 a6 8a e7 cd bd 8a 7b f3 e3 4f +a1 9d cc a4 ef 75 a4 74 54 37 5f 94 51 4d 88 fe +d0 06 fb 82 9f 84 19 ff 87 d6 31 5d a6 8a 1f f3 +a0 93 8e 9a bb 34 64 01 1c 30 3a d9 91 99 cf 0c +7c 7a 8b 47 7d ce 82 9e 88 44 f6 25 b1 15 e5 e9 +c4 a5 9c f8 f8 11 3b 68 34 33 6a 2f d2 68 9b 47 +2c bb 5e 5c ab e6 74 35 0c 59 b6 c1 7e 17 68 74 +fb 42 f8 fc 3d 17 6a 01 7e dc 61 fd 32 6c 4b 33 +c9 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +02 7d 14 7e 46 73 05 73 77 fd 1e a2 01 56 57 72 +17 6a 7d c3 83 58 d3 76 04 56 85 a2 e7 87 c2 3c +15 57 6b c1 6b 9f 44 44 02 d6 bf c5 d9 8a 3e 88 +ea 13 ef 67 c3 53 ec a0 c0 dd ba 92 55 bd 7b 8b +b5 0a 64 4a fd fd 1d d5 16 95 b2 52 d2 2e 73 18 +d1 b6 68 7a 1c 10 ff 75 54 5f 3d b0 fe 60 2d 5f +2b 7f 29 4e 36 01 ea b7 b9 d1 ce cd 76 7f 64 69 +2e 3e 53 6c a2 84 6c b0 c2 dd 48 6a 39 fa 75 b1 + +# Prime p: +01 66 01 e9 26 a0 f8 c9 e2 6e ca b7 69 ea 65 a5 +e7 c5 2c c9 e0 80 ef 51 94 57 c6 44 da 68 91 c5 +a1 04 d3 ea 79 55 92 9a 22 e7 c6 8a 7a f9 fc ad +77 7c 3c cc 2b 9e 3d 36 50 bc e4 04 39 9b 7e 59 +d1 + +# Prime q: +01 4e af a1 d4 d0 18 4d a7 e3 1f 87 7d 12 81 dd +da 62 56 64 86 9e 83 79 e6 7a d3 b7 5e ae 74 a5 +80 e9 82 7a bd 6e b7 a0 02 cb 54 11 f5 26 67 97 +76 8f b8 e9 5a e4 0e 3e 8a 01 f3 5f f8 9e 56 c0 +79 + +# p's CRT exponent dP: +e2 47 cc e5 04 93 9b 8f 0a 36 09 0d e2 00 93 87 +55 e2 44 4b 29 53 9a 7d a7 a9 02 f6 05 68 35 c0 +db 7b 52 55 94 97 cf e2 c6 1a 80 86 d0 21 3c 47 +2c 78 85 18 00 b1 71 f6 40 1d e2 e9 c2 75 6f 31 + +# q's CRT exponent dQ: +b1 2f ba 75 78 55 e5 86 e4 6f 64 c3 8a 70 c6 8b +3f 54 8d 93 d7 87 b3 99 99 9d 4c 8f 0b bd 25 81 +c2 1e 19 ed 00 18 a6 d5 d3 df 86 42 4b 3a bc ad +40 19 9d 31 49 5b 61 30 9f 27 c1 bf 55 d4 87 c1 + +# CRT coefficient qInv: +56 4b 1e 1f a0 03 bd a9 1e 89 09 04 25 aa c0 5b +91 da 9e e2 50 61 e7 62 8d 5f 51 30 4a 84 99 2f +dc 33 76 2b d3 78 a5 9f 03 0a 33 4d 53 2b d0 da +e8 f2 98 ea 9e d8 44 63 6a d5 fb 8c bd c0 3c ad + +# -------------------------------- +# RSASSA-PSS Signature Example 2.1 +# -------------------------------- + +# Message to be signed: +da ba 03 20 66 26 3f ae db 65 98 48 11 52 78 a5 +2c 44 fa a3 a7 6f 37 51 5e d3 36 32 10 72 c4 0a +9d 9b 53 bc 05 01 40 78 ad f5 20 87 51 46 aa e7 +0f f0 60 22 6d cb 7b 1f 1f c2 7e 93 60 + +# Salt: +57 bf 16 0b cb 02 bb 1d c7 28 0c f0 45 85 30 b7 +d2 83 2f f7 + +# Signature: +01 4c 5b a5 33 83 28 cc c6 e7 a9 0b f1 c0 ab 3f +d6 06 ff 47 96 d3 c1 2e 4b 63 9e d9 13 6a 5f ec +6c 16 d8 88 4b dd 99 cf dc 52 14 56 b0 74 2b 73 +68 68 cf 90 de 09 9a db 8d 5f fd 1d ef f3 9b a4 +00 7a b7 46 ce fd b2 2d 7d f0 e2 25 f5 46 27 dc +65 46 61 31 72 1b 90 af 44 53 63 a8 35 8b 9f 60 +76 42 f7 8f ab 0a b0 f4 3b 71 68 d6 4b ae 70 d8 +82 78 48 d8 ef 1e 42 1c 57 54 dd f4 2c 25 89 b5 +b3 + +# -------------------------------- +# RSASSA-PSS Signature Example 2.2 +# -------------------------------- + +# Message to be signed: +e4 f8 60 1a 8a 6d a1 be 34 44 7c 09 59 c0 58 57 +0c 36 68 cf d5 1d d5 f9 cc d6 ad 44 11 fe 82 13 +48 6d 78 a6 c4 9f 93 ef c2 ca 22 88 ce bc 2b 9b +60 bd 04 b1 e2 20 d8 6e 3d 48 48 d7 09 d0 32 d1 +e8 c6 a0 70 c6 af 9a 49 9f cf 95 35 4b 14 ba 61 +27 c7 39 de 1b b0 fd 16 43 1e 46 93 8a ec 0c f8 +ad 9e b7 2e 83 2a 70 35 de 9b 78 07 bd c0 ed 8b +68 eb 0f 5a c2 21 6b e4 0c e9 20 c0 db 0e dd d3 +86 0e d7 88 ef ac ca ca 50 2d 8f 2b d6 d1 a7 c1 +f4 1f f4 6f 16 81 c8 f1 f8 18 e9 c4 f6 d9 1a 0c +78 03 cc c6 3d 76 a6 54 4d 84 3e 08 4e 36 3b 8a +cc 55 aa 53 17 33 ed b5 de e5 b5 19 6e 9f 03 e8 +b7 31 b3 77 64 28 d9 e4 57 fe 3f bc b3 db 72 74 +44 2d 78 58 90 e9 cb 08 54 b6 44 4d ac e7 91 d7 +27 3d e1 88 97 19 33 8a 77 fe + +# Salt: +7f 6d d3 59 e6 04 e6 08 70 e8 98 e4 7b 19 bf 2e +5a 7b 2a 90 + +# Signature: +01 09 91 65 6c ca 18 2b 7f 29 d2 db c0 07 e7 ae +0f ec 15 8e b6 75 9c b9 c4 5c 5f f8 7c 76 35 dd +46 d1 50 88 2f 4d e1 e9 ae 65 e7 f7 d9 01 8f 68 +36 95 4a 47 c0 a8 1a 8a 6b 6f 83 f2 94 4d 60 81 +b1 aa 7c 75 9b 25 4b 2c 34 b6 91 da 67 cc 02 26 +e2 0b 2f 18 b4 22 12 76 1d cd 4b 90 8a 62 b3 71 +b5 91 8c 57 42 af 4b 53 7e 29 69 17 67 4f b9 14 +19 47 61 62 1c c1 9a 41 f6 fb 95 3f bc bb 64 9d +ea + +# -------------------------------- +# RSASSA-PSS Signature Example 2.3 +# -------------------------------- + +# Message to be signed: +52 a1 d9 6c 8a c3 9e 41 e4 55 80 98 01 b9 27 a5 +b4 45 c1 0d 90 2a 0d cd 38 50 d2 2a 66 d2 bb 07 +03 e6 7d 58 67 11 45 95 aa bf 5a 7a eb 5a 8f 87 +03 4b bb 30 e1 3c fd 48 17 a9 be 76 23 00 23 60 +6d 02 86 a3 fa f8 a4 d2 2b 72 8e c5 18 07 9f 9e +64 52 6e 3a 0c c7 94 1a a3 38 c4 37 99 7c 68 0c +ca c6 7c 66 bf a1 + +# Salt: +fc a8 62 06 8b ce 22 46 72 4b 70 8a 05 19 da 17 +e6 48 68 8c + +# Signature: +00 7f 00 30 01 8f 53 cd c7 1f 23 d0 36 59 fd e5 +4d 42 41 f7 58 a7 50 b4 2f 18 5f 87 57 85 20 c3 +07 42 af d8 43 59 b6 e6 e8 d3 ed 95 9d c6 fe 48 +6b ed c8 e2 cf 00 1f 63 a7 ab e1 62 56 a1 b8 4d +f0 d2 49 fc 05 d3 19 4c e5 f0 91 27 42 db bf 80 +dd 17 4f 6c 51 f6 ba d7 f1 6c f3 36 4e ba 09 5a +06 26 7d c3 79 38 03 ac 75 26 ae be 0a 47 5d 38 +b8 c2 24 7a b5 1c 48 98 df 70 47 dc 6a df 52 c6 +c4 + +# -------------------------------- +# RSASSA-PSS Signature Example 2.4 +# -------------------------------- + +# Message to be signed: +a7 18 2c 83 ac 18 be 65 70 a1 06 aa 9d 5c 4e 3d +bb d4 af ae b0 c6 0c 4a 23 e1 96 9d 79 ff + +# Salt: +80 70 ef 2d e9 45 c0 23 87 68 4b a0 d3 30 96 73 +22 35 d4 40 + +# Signature: +00 9c d2 f4 ed be 23 e1 23 46 ae 8c 76 dd 9a d3 +23 0a 62 07 61 41 f1 6c 15 2b a1 85 13 a4 8e f6 +f0 10 e0 e3 7f d3 df 10 a1 ec 62 9a 0c b5 a3 b5 +d2 89 30 07 29 8c 30 93 6a 95 90 3b 6b a8 55 55 +d9 ec 36 73 a0 61 08 fd 62 a2 fd a5 6d 1c e2 e8 +5c 4d b6 b2 4a 81 ca 3b 49 6c 36 d4 fd 06 eb 7c +91 66 d8 e9 48 77 c4 2b ea 62 2b 3b fe 92 51 fd +c2 1d 8d 53 71 ba da d7 8a 48 82 14 79 63 35 b4 +0b + +# -------------------------------- +# RSASSA-PSS Signature Example 2.5 +# -------------------------------- + +# Message to be signed: +86 a8 3d 4a 72 ee 93 2a 4f 56 30 af 65 79 a3 86 +b7 8f e8 89 99 e0 ab d2 d4 90 34 a4 bf c8 54 dd +94 f1 09 4e 2e 8c d7 a1 79 d1 95 88 e4 ae fc 1b +1b d2 5e 95 e3 dd 46 1f + +# Salt: +17 63 9a 4e 88 d7 22 c4 fc a2 4d 07 9a 8b 29 c3 +24 33 b0 c9 + +# Signature: +00 ec 43 08 24 93 1e bd 3b aa 43 03 4d ae 98 ba +64 6b 8c 36 01 3d 16 71 c3 cf 1c f8 26 0c 37 4b +19 f8 e1 cc 8d 96 50 12 40 5e 7e 9b f7 37 86 12 +df cc 85 fc e1 2c da 11 f9 50 bd 0b a8 87 67 40 +43 6c 1d 25 95 a6 4a 1b 32 ef cf b7 4a 21 c8 73 +b3 cc 33 aa f4 e3 dc 39 53 de 67 f0 67 4c 04 53 +b4 fd 9f 60 44 06 d4 41 b8 16 09 8c b1 06 fe 34 +72 bc 25 1f 81 5f 59 db 2e 43 78 a3 ad dc 18 1e +cf + +# -------------------------------- +# RSASSA-PSS Signature Example 2.6 +# -------------------------------- + +# Message to be signed: +04 9f 91 54 d8 71 ac 4a 7c 7a b4 53 25 ba 75 45 +a1 ed 08 f7 05 25 b2 66 7c f1 + +# Salt: +37 81 0d ef 10 55 ed 92 2b 06 3d f7 98 de 5d 0a +ab f8 86 ee + +# Signature: +00 47 5b 16 48 f8 14 a8 dc 0a bd c3 7b 55 27 f5 +43 b6 66 bb 6e 39 d3 0e 5b 49 d3 b8 76 dc cc 58 +ea c1 4e 32 a2 d5 5c 26 16 01 44 56 ad 2f 24 6f +c8 e3 d5 60 da 3d df 37 9a 1c 0b d2 00 f1 02 21 +df 07 8c 21 9a 15 1b c8 d4 ec 9d 2f c2 56 44 67 +81 10 14 ef 15 d8 ea 01 c2 eb bf f8 c2 c8 ef ab +38 09 6e 55 fc be 32 85 c7 aa 55 88 51 25 4f af +fa 92 c1 c7 2b 78 75 86 63 ef 45 82 84 31 39 d7 +a6 + +# ============================================= + +# ================================== +# Example 3: A 1026-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +02 f2 46 ef 45 1e d3 ee bb 9a 31 02 00 cc 25 85 +9c 04 8e 4b e7 98 30 29 91 11 2e b6 8c e6 db 67 +4e 28 0d a2 1f ed ed 1a e7 48 80 ca 52 2b 18 db +24 93 85 01 28 27 c5 15 f0 e4 66 a1 ff a6 91 d9 +81 70 57 4e 9d 0e ad b0 87 58 6c a4 89 33 da 3c +c9 53 d9 5b d0 ed 50 de 10 dd cb 67 36 10 7d 6c +83 1c 7f 66 3e 83 3c a4 c0 97 e7 00 ce 0f b9 45 +f8 8f b8 5f e8 e5 a7 73 17 25 65 b9 14 a4 71 a4 +43 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +65 14 51 73 3b 56 de 5a c0 a6 89 a4 ae b6 e6 89 +4a 69 01 4e 07 6c 88 dd 7a 66 7e ab 32 32 bb cc +d2 fc 44 ba 2f a9 c3 1d b4 6f 21 ed d1 fd b2 3c +5c 12 8a 5d a5 ba b9 1e 7f 95 2b 67 75 9c 7c ff +70 54 15 ac 9f a0 90 7c 7c a6 17 8f 66 8f b9 48 +d8 69 da 4c c3 b7 35 6f 40 08 df d5 44 9d 32 ee +02 d9 a4 77 eb 69 fc 29 26 6e 5d 90 70 51 23 75 +a5 0f bb cc 27 e2 38 ad 98 42 5f 6e bb f8 89 91 + +# Prime p: +01 bd 36 e1 8e ce 4b 0f db 2e 9c 9d 54 8b d1 a7 +d6 e2 c2 1c 6f dc 35 07 4a 1d 05 b1 c6 c8 b3 d5 +58 ea 26 39 c9 a9 a4 21 68 01 69 31 72 52 55 8b +d1 48 ad 21 5a ac 55 0e 2d cf 12 a8 2d 0e bf e8 +53 + +# Prime q: +01 b1 b6 56 ad 86 d8 e1 9d 5d c8 62 92 b3 a1 92 +fd f6 e0 dd 37 87 7b ad 14 82 2f a0 01 90 ca b2 +65 f9 0d 3f 02 05 7b 6f 54 d6 ec b1 44 91 e5 ad +ea ce bc 48 bf 0e bd 2a 2a d2 6d 40 2e 54 f6 16 +51 + +# p's CRT exponent dP: +1f 27 79 fd 2e 3e 5e 6b ae 05 53 95 18 fb a0 cd +0e ad 1a a4 51 3a 7c ba 18 f1 cf 10 e3 f6 81 95 +69 3d 27 8a 0f 0e e7 2f 89 f9 bc 76 0d 80 e2 f9 +d0 26 1d 51 65 01 c6 ae 39 f1 4a 47 6c e2 cc f5 + +# q's CRT exponent dQ: +01 1a 0d 36 79 4b 04 a8 54 aa b4 b2 46 2d 43 9a +50 46 c9 1d 94 0b 2b c6 f7 5b 62 95 6f ef 35 a2 +a6 e6 3c 53 09 81 7f 30 7b bf f9 d5 9e 7e 33 1b +d3 63 f6 d6 68 49 b1 83 46 ad ea 16 9f 0a e9 ae +c1 + +# CRT coefficient qInv: +0b 30 f0 ec f5 58 75 2f b3 a6 ce 4b a2 b8 c6 75 +f6 59 eb a6 c3 76 58 5a 1b 39 71 2d 03 8a e3 d2 +b4 6f cb 41 8a e1 5d 09 05 da 64 40 e1 51 3a 30 +b9 b7 d6 66 8f bc 5e 88 e5 ab 7a 17 5e 73 ba 35 + +# -------------------------------- +# RSASSA-PSS Signature Example 3.1 +# -------------------------------- + +# Message to be signed: +59 4b 37 33 3b bb 2c 84 52 4a 87 c1 a0 1f 75 fc +ec 0e 32 56 f1 08 e3 8d ca 36 d7 0d 00 57 + +# Salt: +f3 1a d6 c8 cf 89 df 78 ed 77 fe ac bc c2 f8 b0 +a8 e4 cf aa + +# Signature: +00 88 b1 35 fb 17 94 b6 b9 6c 4a 3e 67 81 97 f8 +ca c5 2b 64 b2 fe 90 7d 6f 27 de 76 11 24 96 4a +99 a0 1a 88 27 40 ec fa ed 6c 01 a4 74 64 bb 05 +18 23 13 c0 13 38 a8 cd 09 72 14 cd 68 ca 10 3b +d5 7d 3b c9 e8 16 21 3e 61 d7 84 f1 82 46 7a bf +8a 01 cf 25 3e 99 a1 56 ea a8 e3 e1 f9 0e 3c 6e +4e 3a a2 d8 3e d0 34 5b 89 fa fc 9c 26 07 7c 14 +b6 ac 51 45 4f a2 6e 44 6e 3a 2f 15 3b 2b 16 79 +7f + +# -------------------------------- +# RSASSA-PSS Signature Example 3.2 +# -------------------------------- + +# Message to be signed: +8b 76 95 28 88 4a 0d 1f fd 09 0c f1 02 99 3e 79 +6d ad cf bd dd 38 e4 4f f6 32 4c a4 51 + +# Salt: +fc f9 f0 e1 f1 99 a3 d1 d0 da 68 1c 5b 86 06 fc +64 29 39 f7 + +# Signature: +02 a5 f0 a8 58 a0 86 4a 4f 65 01 7a 7d 69 45 4f +3f 97 3a 29 99 83 9b 7b bc 48 bf 78 64 11 69 17 +95 56 f5 95 fa 41 f6 ff 18 e2 86 c2 78 30 79 bc +09 10 ee 9c c3 4f 49 ba 68 11 24 f9 23 df a8 8f +42 61 41 a3 68 a5 f5 a9 30 c6 28 c2 c3 c2 00 e1 +8a 76 44 72 1a 0c be c6 dd 3f 62 79 bd e3 e8 f2 +be 5e 2d 4e e5 6f 97 e7 ce af 33 05 4b e7 04 2b +d9 1a 63 bb 09 f8 97 bd 41 e8 11 97 de e9 9b 11 +af + +# -------------------------------- +# RSASSA-PSS Signature Example 3.3 +# -------------------------------- + +# Message to be signed: +1a bd ba 48 9c 5a da 2f 99 5e d1 6f 19 d5 a9 4d +9e 6e c3 4a 8d 84 f8 45 57 d2 6e 5e f9 b0 2b 22 +88 7e 3f 9a 4b 69 0a d1 14 92 09 c2 0c 61 43 1f +0c 01 7c 36 c2 65 7b 35 d7 b0 7d 3f 5a d8 70 85 +07 a9 c1 b8 31 df 83 5a 56 f8 31 07 18 14 ea 5d +3d 8d 8f 6a de 40 cb a3 8b 42 db 7a 2d 3d 7a 29 +c8 f0 a7 9a 78 38 cf 58 a9 75 7f a2 fe 4c 40 df +9b aa 19 3b fc 6f 92 b1 23 ad 57 b0 7a ce 3e 6a +c0 68 c9 f1 06 af d9 ee b0 3b 4f 37 c2 5d bf bc +fb 30 71 f6 f9 77 17 66 d0 72 f3 bb 07 0a f6 60 +55 32 97 3a e2 50 51 + +# Salt: +98 6e 7c 43 db b6 71 bd 41 b9 a7 f4 b6 af c8 0e +80 5f 24 23 + +# Signature: +02 44 bc d1 c8 c1 69 55 73 6c 80 3b e4 01 27 2e +18 cb 99 08 11 b1 4f 72 db 96 41 24 d5 fa 76 06 +49 cb b5 7a fb 87 55 db b6 2b f5 1f 46 6c f2 3a +0a 16 07 57 6e 98 3d 77 8f ce ff a9 2d f7 54 8a +ea 8e a4 ec ad 2c 29 dd 9f 95 bc 07 fe 91 ec f8 +be e2 55 bf e8 76 2f d7 69 0a a9 bf a4 fa 08 49 +ef 72 8c 2c 42 c4 53 23 64 52 2d f2 ab 7f 9f 8a +03 b6 3f 7a 49 91 75 82 86 68 f5 ef 5a 29 e3 80 +2c + +# -------------------------------- +# RSASSA-PSS Signature Example 3.4 +# -------------------------------- + +# Message to be signed: +8f b4 31 f5 ee 79 2b 6c 2a c7 db 53 cc 42 86 55 +ae b3 2d 03 f4 e8 89 c5 c2 5d e6 83 c4 61 b5 3a +cf 89 f9 f8 d3 aa bd f6 b9 f0 c2 a1 de 12 e1 5b +49 ed b3 91 9a 65 2f e9 49 1c 25 a7 fc e1 f7 22 +c2 54 36 08 b6 9d c3 75 ec + +# Salt: +f8 31 2d 9c 8e ea 13 ec 0a 4c 7b 98 12 0c 87 50 +90 87 c4 78 + +# Signature: +01 96 f1 2a 00 5b 98 12 9c 8d f1 3c 4c b1 6f 8a +a8 87 d3 c4 0d 96 df 3a 88 e7 53 2e f3 9c d9 92 +f2 73 ab c3 70 bc 1b e6 f0 97 cf eb bf 01 18 fd +9e f4 b9 27 15 5f 3d f2 2b 90 4d 90 70 2d 1f 7b +a7 a5 2b ed 8b 89 42 f4 12 cd 7b d6 76 c9 d1 8e +17 03 91 dc d3 45 c0 6a 73 09 64 b3 f3 0b cc e0 +bb 20 ba 10 6f 9a b0 ee b3 9c f8 a6 60 7f 75 c0 +34 7f 0a f7 9f 16 af a0 81 d2 c9 2d 1e e6 f8 36 +b8 + +# -------------------------------- +# RSASSA-PSS Signature Example 3.5 +# -------------------------------- + +# Message to be signed: +fe f4 16 1d fa af 9c 52 95 05 1d fc 1f f3 81 0c +8c 9e c2 e8 66 f7 07 54 22 c8 ec 42 16 a9 c4 ff +49 42 7d 48 3c ae 10 c8 53 4a 41 b2 fd 15 fe e0 +69 60 ec 6f b3 f7 a7 e9 4a 2f 8a 2e 3e 43 dc 4a +40 57 6c 30 97 ac 95 3b 1d e8 6f 0b 4e d3 6d 64 +4f 23 ae 14 42 55 29 62 24 64 ca 0c bf 0b 17 41 +34 72 38 15 7f ab 59 e4 de 55 24 09 6d 62 ba ec +63 ac 64 + +# Salt: +50 32 7e fe c6 29 2f 98 01 9f c6 7a 2a 66 38 56 +3e 9b 6e 2d + +# Signature: +02 1e ca 3a b4 89 22 64 ec 22 41 1a 75 2d 92 22 +10 76 d4 e0 1c 0e 6f 0d de 9a fd 26 ba 5a cf 6d +73 9e f9 87 54 5d 16 68 3e 56 74 c9 e7 0f 1d e6 +49 d7 e6 1d 48 d0 ca eb 4f b4 d8 b2 4f ba 84 a6 +e3 10 8f ee 7d 07 05 97 32 66 ac 52 4b 4a d2 80 +f7 ae 17 dc 59 d9 6d 33 51 58 6b 5a 3b db 89 5d +1e 1f 78 20 ac 61 35 d8 75 34 80 99 83 82 ba 32 +b7 34 95 59 60 8c 38 74 52 90 a8 5e f4 e9 f9 bd +83 + +# -------------------------------- +# RSASSA-PSS Signature Example 3.6 +# -------------------------------- + +# Message to be signed: +ef d2 37 bb 09 8a 44 3a ee b2 bf 6c 3f 8c 81 b8 +c0 1b 7f cb 3f eb + +# Salt: +b0 de 3f c2 5b 65 f5 af 96 b1 d5 cc 3b 27 d0 c6 +05 30 87 b3 + +# Signature: +01 2f af ec 86 2f 56 e9 e9 2f 60 ab 0c 77 82 4f +42 99 a0 ca 73 4e d2 6e 06 44 d5 d2 22 c7 f0 bd +e0 39 64 f8 e7 0a 5c b6 5e d4 4e 44 d5 6a e0 ed +f1 ff 86 ca 03 2c c5 dd 44 04 db b7 6a b8 54 58 +6c 44 ee d8 33 6d 08 d4 57 ce 6c 03 69 3b 45 c0 +f1 ef ef 93 62 4b 95 b8 ec 16 9c 61 6d 20 e5 53 +8e bc 0b 67 37 a6 f8 2b 4b c0 57 09 24 fc 6b 35 +75 9a 33 48 42 62 79 f8 b3 d7 74 4e 2d 22 24 26 +ce + +# ============================================= + +# ================================== +# Example 4: A 1027-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +05 4a db 78 86 44 7e fe 6f 57 e0 36 8f 06 cf 52 +b0 a3 37 07 60 d1 61 ce f1 26 b9 1b e7 f8 9c 42 +1b 62 a6 ec 1d a3 c3 11 d7 5e d5 0e 0a b5 ff f3 +fd 33 8a cc 3a a8 a4 e7 7e e2 63 69 ac b8 1b a9 +00 fa 83 f5 30 0c f9 bb 6c 53 ad 1d c8 a1 78 b8 +15 db 42 35 a9 a9 da 0c 06 de 4e 61 5e a1 27 7c +e5 59 e9 c1 08 de 58 c1 4a 81 aa 77 f5 a6 f8 d1 +33 54 94 49 88 48 c8 b9 59 40 74 0b e7 bf 7c 37 +05 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +fa 04 1f 8c d9 69 7c ee d3 8e c8 ca a2 75 52 3b +4d d7 2b 09 a3 01 d3 54 1d 72 f5 d3 1c 05 cb ce +2d 69 83 b3 61 83 af 10 69 0b d4 6c 46 13 1e 35 +78 94 31 a5 56 77 1d d0 04 9b 57 46 1b f0 60 c1 +f6 84 72 e8 a6 7c 25 f3 57 e5 b6 b4 73 8f a5 41 +a7 30 34 6b 4a 07 64 9a 2d fa 80 6a 69 c9 75 b6 +ab a6 46 78 ac c7 f5 91 3e 89 c6 22 f2 d8 ab b1 +e3 e3 25 54 e3 9d f9 4b a6 0c 00 2e 38 7d 90 11 + +# Prime p: +02 92 32 33 6d 28 38 94 5d ba 9d d7 72 3f 4e 62 +4a 05 f7 37 5b 92 7a 87 ab e6 a8 93 a1 65 8f d4 +9f 47 f6 c7 b0 fa 59 6c 65 fa 68 a2 3f 0a b4 32 +96 2d 18 d4 34 3b d6 fd 67 1a 5e a8 d1 48 41 39 +95 + +# Prime q: +02 0e f5 ef e7 c5 39 4a ed 22 72 f7 e8 1a 74 f4 +c0 2d 14 58 94 cb 1b 3c ab 23 a9 a0 71 0a 2a fc +7e 33 29 ac bb 74 3d 01 f6 80 c4 d0 2a fb 4c 8f +de 7e 20 93 08 11 bb 2b 99 57 88 b5 e8 72 c2 0b +b1 + +# p's CRT exponent dP: +02 6e 7e 28 01 0e cf 24 12 d9 52 3a d7 04 64 7f +b4 fe 9b 66 b1 a6 81 58 1b 0e 15 55 3a 89 b1 54 +28 28 89 8f 27 24 3e ba b4 5f f5 e1 ac b9 d4 df +1b 05 1f bc 62 82 4d bc 6f 6c 93 26 1a 78 b9 a7 +59 + +# q's CRT exponent dQ: +01 2d dc c8 6e f6 55 99 8c 39 dd ae 11 71 86 69 +e5 e4 6c f1 49 5b 07 e1 3b 10 14 cd 69 b3 af 68 +30 4a d2 a6 b6 43 21 e7 8b f3 bb ca 9b b4 94 e9 +1d 45 17 17 e2 d9 75 64 c6 54 94 65 d0 20 5c f4 +21 + +# CRT coefficient qInv: +01 06 00 c4 c2 18 47 45 9f e5 76 70 3e 2e be ca +e8 a5 09 4e e6 3f 53 6b f4 ac 68 d3 c1 3e 5e 4f +12 ac 5c c1 0a b6 a2 d0 5a 19 92 14 d1 82 47 47 +d5 51 90 96 36 b7 74 c2 2c ac 0b 83 75 99 ab cc +75 + +# -------------------------------- +# RSASSA-PSS Signature Example 4.1 +# -------------------------------- + +# Message to be signed: +9f b0 3b 82 7c 82 17 d9 + +# Salt: +ed 7c 98 c9 5f 30 97 4f be 4f bd dc f0 f2 8d 60 +21 c0 e9 1d + +# Signature: +03 23 d5 b7 bf 20 ba 45 39 28 9a e4 52 ae 42 97 +08 0f ef f4 51 84 23 ff 48 11 a8 17 83 7e 7d 82 +f1 83 6c df ab 54 51 4f f0 88 7b dd ee bf 40 bf +99 b0 47 ab c3 ec fa 6a 37 a3 ef 00 f4 a0 c4 a8 +8a ae 09 04 b7 45 c8 46 c4 10 7e 87 97 72 3e 8a +c8 10 d9 e3 d9 5d fa 30 ff 49 66 f4 d7 5d 13 76 +8d 20 85 7f 2b 14 06 f2 64 cf e7 5e 27 d7 65 2f +4b 5e d3 57 5f 28 a7 02 f8 c4 ed 9c f9 b2 d4 49 +48 + +# -------------------------------- +# RSASSA-PSS Signature Example 4.2 +# -------------------------------- + +# Message to be signed: +0c a2 ad 77 79 7e ce 86 de 5b f7 68 75 0d db 5e +d6 a3 11 6a d9 9b bd 17 ed f7 f7 82 f0 db 1c d0 +5b 0f 67 74 68 c5 ea 42 0d c1 16 b1 0e 80 d1 10 +de 2b 04 61 ea 14 a3 8b e6 86 20 39 2e 7e 89 3c +b4 ea 93 93 fb 88 6c 20 ff 79 06 42 30 5b f3 02 +00 38 92 e5 4d f9 f6 67 50 9d c5 39 20 df 58 3f +50 a3 dd 61 ab b6 fa b7 5d 60 03 77 e3 83 e6 ac +a6 71 0e ee a2 71 56 e0 67 52 c9 4c e2 5a e9 9f +cb f8 59 2d be 2d 7e 27 45 3c b4 4d e0 71 00 eb +b1 a2 a1 98 11 a4 78 ad be ab 27 0f 94 e8 fe 36 +9d 90 b3 ca 61 2f 9f + +# Salt: +22 d7 1d 54 36 3a 42 17 aa 55 11 3f 05 9b 33 84 +e3 e5 7e 44 + +# Signature: +04 9d 01 85 84 5a 26 4d 28 fe b1 e6 9e da ec 09 +06 09 e8 e4 6d 93 ab b3 83 71 ce 51 f4 aa 65 a5 +99 bd aa a8 1d 24 fb a6 6a 08 a1 16 cb 64 4f 3f +1e 65 3d 95 c8 9d b8 bb d5 da ac 27 09 c8 98 40 +00 17 84 10 a7 c6 aa 86 67 dd c3 8c 74 1f 71 0e +c8 66 5a a9 05 2b e9 29 d4 e3 b1 67 82 c1 66 21 +14 c5 41 4b b0 35 34 55 c3 92 fc 28 f3 db 59 05 +4b 5f 36 5c 49 e1 d1 56 f8 76 ee 10 cb 4f d7 05 +98 + +# -------------------------------- +# RSASSA-PSS Signature Example 4.3 +# -------------------------------- + +# Message to be signed: +28 80 62 af c0 8f cd b7 c5 f8 65 0b 29 83 73 00 +46 1d d5 67 6c 17 a2 0a 3c 8f b5 14 89 49 e3 f7 +3d 66 b3 ae 82 c7 24 0e 27 c5 b3 ec 43 28 ee 7d +6d df 6a 6a 0c 9b 5b 15 bc da 19 6a 9d 0c 76 b1 +19 d5 34 d8 5a bd 12 39 62 d5 83 b7 6c e9 d1 80 +bc e1 ca + +# Salt: +4a f8 70 fb c6 51 60 12 ca 91 6c 70 ba 86 2a c7 +e8 24 36 17 + +# Signature: +03 fb c4 10 a2 ce d5 95 00 fb 99 f9 e2 af 27 81 +ad a7 4e 13 14 56 24 60 27 82 e2 99 48 13 ee fc +a0 51 9e cd 25 3b 85 5f b6 26 a9 0d 77 1e ae 02 +8b 0c 47 a1 99 cb d9 f8 e3 26 97 34 af 41 63 59 +90 90 71 3a 3f a9 10 fa 09 60 65 27 21 43 2b 97 +10 36 a7 18 1a 2b c0 ca b4 3b 0b 59 8b c6 21 74 +61 d7 db 30 5f f7 e9 54 c5 b5 bb 23 1c 39 e7 91 +af 6b cf a7 6b 14 7b 08 13 21 f7 26 41 48 2a 2a +ad + +# -------------------------------- +# RSASSA-PSS Signature Example 4.4 +# -------------------------------- + +# Message to be signed: +6f 4f 9a b9 50 11 99 ce f5 5c 6c f4 08 fe 7b 36 +c5 57 c4 9d 42 0a 47 63 d2 46 3c 8a d4 4b 3c fc +5b e2 74 2c 0e 7d 9b 0f 66 08 f0 8c 7f 47 b6 93 +ee + +# Salt: +40 d2 e1 80 fa e1 ea c4 39 c1 90 b5 6c 2c 0e 14 +dd f9 a2 26 + +# Signature: +04 86 64 4b c6 6b f7 5d 28 33 5a 61 79 b1 08 51 +f4 3f 09 bd ed 9f ac 1a f3 32 52 bb 99 53 ba 42 +98 cd 64 66 b2 75 39 a7 0a da a3 f8 9b 3d b3 c7 +4a b6 35 d1 22 f4 ee 7c e5 57 a6 1e 59 b8 2f fb +78 66 30 e5 f9 db 53 c7 7d 9a 0c 12 fa b5 95 8d +4c 2c e7 da a8 07 cd 89 ba 2c c7 fc d0 2f f4 70 +ca 67 b2 29 fc ce 81 4c 85 2c 73 cc 93 be a3 5b +e6 84 59 ce 47 8e 9d 46 55 d1 21 c8 47 2f 37 1d +4f + +# -------------------------------- +# RSASSA-PSS Signature Example 4.5 +# -------------------------------- + +# Message to be signed: +e1 7d 20 38 5d 50 19 55 82 3c 3f 66 62 54 c1 d3 +dd 36 ad 51 68 b8 f1 8d 28 6f dc f6 7a 7d ad 94 +09 70 85 fa b7 ed 86 fe 21 42 a2 87 71 71 79 97 +ef 1a 7a 08 88 4e fc 39 35 6d 76 07 7a af 82 45 +9a 7f ad 45 84 88 75 f2 81 9b 09 89 37 fe 92 3b +cc 9d c4 42 d7 2d 75 4d 81 20 25 09 0c 9b c0 3d +b3 08 0c 13 8d d6 3b 35 5d 0b 4b 85 d6 68 8a c1 +9f 4d e1 50 84 a0 ba 4e 37 3b 93 ef 4a 55 50 96 +69 19 15 dc 23 c0 0e 95 4c de b2 0a 47 cd 55 d1 +6c 3d 86 81 d4 6e d7 f2 ed 5e a4 27 95 be 17 ba +ed 25 f0 f4 d1 13 b3 63 6a dd d5 85 f1 6a 8b 5a +ec 0c 8f a9 c5 f0 3c bf 3b 9b 73 + +# Salt: +24 97 dc 2b 46 15 df ae 5a 66 3d 49 ff d5 6b f7 +ef c1 13 04 + +# Signature: +02 2a 80 04 53 53 90 4c b3 0c bb 54 2d 7d 49 90 +42 1a 6e ec 16 a8 02 9a 84 22 ad fd 22 d6 af f8 +c4 cc 02 94 af 11 0a 0c 06 7e c8 6a 7d 36 41 34 +45 9b b1 ae 8f f8 36 d5 a8 a2 57 98 40 99 6b 32 +0b 19 f1 3a 13 fa d3 78 d9 31 a6 56 25 da e2 73 +9f 0c 53 67 0b 35 d9 d3 cb ac 08 e7 33 e4 ec 2b +83 af 4b 91 96 d6 3e 7c 4f f1 dd ea e2 a1 22 79 +1a 12 5b fe a8 de b0 de 8c cf 1f 4f fa f6 e6 fb +0a + +# -------------------------------- +# RSASSA-PSS Signature Example 4.6 +# -------------------------------- + +# Message to be signed: +af bc 19 d4 79 24 90 18 fd f4 e0 9f 61 87 26 44 +04 95 de 11 dd ee e3 88 72 d7 75 fc ea 74 a2 38 +96 b5 34 3c 9c 38 d4 6a f0 db a2 24 d0 47 58 0c +c6 0a 65 e9 39 1c f9 b5 9b 36 a8 60 59 8d 4e 82 +16 72 2f 99 3b 91 cf ae 87 bc 25 5a f8 9a 6a 19 +9b ca 4a 39 1e ad bc 3a 24 90 3c 0b d6 67 36 8f +6b e7 8e 3f ea bf b4 ff d4 63 12 27 63 74 0f fb +be fe ab 9a 25 56 4b c5 d1 c2 4c 93 e4 22 f7 50 +73 e2 ad 72 bf 45 b1 0d f0 0b 52 a1 47 12 8e 73 +fe e3 3f a3 f0 57 7d 77 f8 0f bc 2d f1 be d3 13 +29 0c 12 77 7f 50 + +# Salt: +a3 34 db 6f ae bf 11 08 1a 04 f8 7c 2d 62 1c de +c7 93 0b 9b + +# Signature: +00 93 8d cb 6d 58 30 46 06 5f 69 c7 8d a7 a1 f1 +75 70 66 a7 fa 75 12 5a 9d 29 29 f0 b7 9a 60 b6 +27 b0 82 f1 1f 5b 19 6f 28 eb 9d aa 6f 21 c0 5e +51 40 f6 ae f1 73 7d 20 23 07 5c 05 ec f0 4a 02 +8c 68 6a 2a b3 e7 d5 a0 66 4f 29 5c e1 29 95 e8 +90 90 8b 6a d2 1f 08 39 eb 65 b7 03 93 a7 b5 af +d9 87 1d e0 ca a0 ce de c5 b8 19 62 67 56 20 9d +13 ab 1e 7b b9 54 6a 26 ff 37 e9 a5 1a f9 fd 56 +2e + +# ============================================= + +# ================================== +# Example 5: A 1028-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +0d 10 f6 61 f2 99 40 f5 ed 39 aa 26 09 66 de b4 +78 43 67 9d 2b 6f b2 5b 3d e3 70 f3 ac 7c 19 91 +63 91 fd 25 fb 52 7e bf a6 a4 b4 df 45 a1 75 9d +99 6c 4b b4 eb d1 88 28 c4 4f c5 2d 01 91 87 17 +40 52 5f 47 a4 b0 cc 8d a3 25 ed 8a a6 76 b0 d0 +f6 26 e0 a7 7f 07 69 21 70 ac ac 80 82 f4 2f aa +7d c7 cd 12 3e 73 0e 31 a8 79 85 20 4c ab cb e6 +67 0d 43 a2 dd 2b 2d de f5 e0 53 92 fc 21 3b c5 +07 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +03 ce 08 b1 04 ff f3 96 a9 79 bd 3e 4e 46 92 5b +63 19 dd b6 3a cb cf d8 19 f1 7d 16 b8 07 7b 3a +87 10 1f f3 4b 77 fe 48 b8 b2 05 a9 6e 91 51 ba +8e ce a6 4d 0c ce 7b 23 c3 e6 a6 b8 30 58 bc 49 +da e8 16 ae 73 6d b5 a4 70 8e 2a d4 35 23 2b 56 +7f 90 96 ce 59 ff 28 06 1e 79 ab 1c 02 d7 17 e6 +b2 3c ea 6d b8 eb 51 92 fa 7c 1e ab 22 7d ba 74 +62 1c 45 60 18 96 ee f1 37 92 c8 44 0b eb 15 aa +c1 + +# Prime p: +03 f2 f3 31 f4 14 2d 4f 24 b4 3a a1 02 79 a8 96 +52 d4 e7 53 72 21 a1 a7 b2 a2 5d eb 55 1e 5d e9 +ac 49 74 11 c2 27 a9 4e 45 f9 1c 2d 1c 13 cc 04 +6c f4 ce 14 e3 2d 05 87 34 21 0d 44 a8 7e e1 b7 +3f + +# Prime q: +03 4f 09 0d 73 b5 58 03 03 0c f0 36 1a 5d 80 81 +bf b7 9f 85 15 23 fe ac 0a 21 24 d0 8d 40 13 ff +08 48 77 71 a8 70 d0 47 9d c0 68 6c 62 f7 71 8d +fe cf 02 4b 17 c9 26 76 78 05 91 71 33 9c c0 08 +39 + +# p's CRT exponent dP: +02 aa 66 3a db f5 1a b8 87 a0 18 cb 42 6e 78 bc +2f e1 82 dc b2 f7 bc b5 04 41 d1 7f df 0f 06 79 +8b 50 71 c6 e2 f5 fe b4 d5 4a d8 18 23 11 c1 ef +62 d4 c4 9f 18 d1 f5 1f 54 b2 d2 cf fb a4 da 1b +e5 + +# q's CRT exponent dQ: +02 bb e7 06 07 8b 5c 0b 39 15 12 d4 11 db 1b 19 +9b 5a 56 64 b8 40 42 ea d3 7f e9 94 ae 72 b9 53 +2d fb fb 3e 9e 69 81 a0 fb b8 06 51 31 41 b7 c2 +16 3f e5 6c 39 5e 4b fa ee 57 e3 83 3f 9b 91 8d +f9 + +# CRT coefficient qInv: +02 42 b6 cd 00 d3 0a 76 7a ee 9a 89 8e ad 45 3c +8e ae a6 3d 50 0b 7d 1e 00 71 3e da e5 1c e3 6b +23 b6 64 df 26 e6 3e 26 6e c8 f7 6e 6e 63 ed 1b +a4 1e b0 33 b1 20 f7 ea 52 12 ae 21 a9 8f bc 16 + +# -------------------------------- +# RSASSA-PSS Signature Example 5.1 +# -------------------------------- + +# Message to be signed: +30 c7 d5 57 45 8b 43 6d ec fd c1 4d 06 cb 7b 96 +b0 67 18 c4 8d 7d e5 74 82 a8 68 ae 7f 06 58 70 +a6 21 65 06 d1 1b 77 93 23 df df 04 6c f5 77 51 +29 13 4b 4d 56 89 e4 d9 c0 ce 1e 12 d7 d4 b0 6c +b5 fc 58 20 de cf a4 1b af 59 bf 25 7b 32 f0 25 +b7 67 9b 44 5b 94 99 c9 25 55 14 58 85 99 2f 1b +76 f8 48 91 ee 4d 3b e0 f5 15 0f d5 90 1e 3a 4c +8e d4 3f d3 6b 61 d0 22 e6 5a d5 00 8d bf 33 29 +3c 22 bf bf d0 73 21 f0 f1 d5 fa 9f df 00 14 c2 +fc b0 35 8a ad 0e 35 4b 0d 29 + +# Salt: +08 1b 23 3b 43 56 77 50 bd 6e 78 f3 96 a8 8b 9f +6a 44 51 51 + +# Signature: +0b a3 73 f7 6e 09 21 b7 0a 8f bf e6 22 f0 bf 77 +b2 8a 3d b9 8e 36 10 51 c3 d7 cb 92 ad 04 52 91 +5a 4d e9 c0 17 22 f6 82 3e eb 6a df 7e 0c a8 29 +0f 5d e3 e5 49 89 0a c2 a3 c5 95 0a b2 17 ba 58 +59 08 94 95 2d e9 6f 8d f1 11 b2 57 52 15 da 6c +16 15 90 c7 45 be 61 24 76 ee 57 8e d3 84 ab 33 +e3 ec e9 74 81 a2 52 f5 c7 9a 98 b5 53 2a e0 0c +dd 62 f2 ec c0 cd 1b ae fe 80 d8 0b 96 21 93 ec +1d + +# -------------------------------- +# RSASSA-PSS Signature Example 5.2 +# -------------------------------- + +# Message to be signed: +e7 b3 2e 15 56 ea 1b 27 95 04 6a c6 97 39 d2 2a +c8 96 6b f1 1c 11 6f 61 4b 16 67 40 e9 6b 90 65 +3e 57 50 94 5f cf 77 21 86 c0 37 90 a0 7f da 32 +3e 1a 61 91 6b 06 ee 21 57 db 3d ff 80 d6 7d 5e +39 a5 3a e2 68 c8 f0 9e d9 9a 73 20 05 b0 bc 6a +04 af 4e 08 d5 7a 00 e7 20 1b 30 60 ef aa db 73 +11 3b fc 08 7f d8 37 09 3a a2 52 35 b8 c1 49 f5 +62 15 f0 31 c2 4a d5 bd e7 f2 99 60 df 7d 52 40 +70 f7 44 9c 6f 78 50 84 be 1a 0f 73 30 47 f3 36 +f9 15 47 38 67 45 47 db 02 a9 f4 4d fc 6e 60 30 +10 81 e1 ce 99 84 7f 3b 5b 60 1f f0 6b 4d 57 76 +a9 74 0b 9a a0 d3 40 58 fd 3b 90 6e 4f 78 59 df +b0 7d 71 73 e5 e6 f6 35 0a da c2 1f 27 b2 30 74 +69 + +# Salt: +bd 0c e1 95 49 d0 70 01 20 cb e5 10 77 db bb b0 +0a 8d 8b 09 + +# Signature: +08 18 0d e8 25 e4 b8 b0 14 a3 2d a8 ba 76 15 55 +92 12 04 f2 f9 0d 5f 24 b7 12 90 8f f8 4f 3e 22 +0a d1 79 97 c0 dd 6e 70 66 30 ba 3e 84 ad d4 d5 +e7 ab 00 4e 58 07 4b 54 97 09 56 5d 43 ad 9e 97 +b5 a7 a1 a2 9e 85 b9 f9 0f 4a af cd f5 83 21 de +8c 59 74 ef 9a bf 2d 52 6f 33 c0 f2 f8 2e 95 d1 +58 ea 6b 81 f1 73 6d b8 d1 af 3d 6a c6 a8 3b 32 +d1 8b ae 0f f1 b2 fe 27 de 4c 76 ed 8c 79 80 a3 +4e + +# -------------------------------- +# RSASSA-PSS Signature Example 5.3 +# -------------------------------- + +# Message to be signed: +8d 83 96 e3 65 07 fe 1e f6 a1 90 17 54 8e 0c 71 +66 74 c2 fe c2 33 ad b2 f7 75 66 5e c4 1f 2b d0 +ba 39 6b 06 1a 9d aa 7e 86 6f 7c 23 fd 35 31 95 +43 00 a3 42 f9 24 53 5e a1 49 8c 48 f6 c8 79 93 +28 65 fc 02 00 0c 52 87 23 b7 ad 03 35 74 5b 51 +20 9a 0a fe d9 32 af 8f 08 87 c2 19 00 4d 2a bd +89 4e a9 25 59 ee 31 98 af 3a 73 4f e9 b9 63 8c +26 3a 72 8a d9 5a 5a e8 ce 3e b1 58 39 f3 aa 78 +52 bb 39 07 06 e7 76 0e 43 a7 12 91 a2 e3 f8 27 +23 7d ed a8 51 87 4c 51 76 65 f5 45 f2 72 38 df +86 55 7f 37 5d 09 cc d8 bd 15 d8 cc f6 1f 5d 78 +ca 5c 7f 5c de 78 2e 6b f5 d0 05 70 56 d4 ba d9 +8b 3d 2f 95 75 e8 24 ab 7a 33 ff 57 b0 ac 10 0a +b0 d6 ea d7 aa 0b 50 f6 e4 d3 e5 ec 0b 96 6b + +# Salt: +81 57 79 a9 1b 3a 8b d0 49 bf 2a eb 92 01 42 77 +22 22 c9 ca + +# Signature: +05 e0 fd bd f6 f7 56 ef 73 31 85 cc fa 8c ed 2e +b6 d0 29 d9 d5 6e 35 56 1b 5d b8 e7 02 57 ee 6f +d0 19 d2 f0 bb f6 69 fe 9b 98 21 e7 8d f6 d4 1e +31 60 8d 58 28 0f 31 8e e3 4f 55 99 41 c8 df 13 +28 75 74 ba c0 00 b7 e5 8d c4 f4 14 ba 49 fb 12 +7f 9d 0f 89 36 63 8c 76 e8 53 56 c9 94 f7 97 50 +f7 fa 3c f4 fd 48 2d f7 5e 3f b9 97 8c d0 61 f7 +ab b1 75 72 e6 e6 3e 0b de 12 cb dc f1 8c 68 b9 +79 + +# -------------------------------- +# RSASSA-PSS Signature Example 5.4 +# -------------------------------- + +# Message to be signed: +32 8c 65 9e 0a 64 37 43 3c ce b7 3c 14 + +# Salt: +9a ec 4a 74 80 d5 bb c4 29 20 d7 ca 23 5d b6 74 +98 9c 9a ac + +# Signature: +0b c9 89 85 3b c2 ea 86 87 32 71 ce 18 3a 92 3a +b6 5e 8a 53 10 0e 6d f5 d8 7a 24 c4 19 4e b7 97 +81 3e e2 a1 87 c0 97 dd 87 2d 59 1d a6 0c 56 86 +05 dd 7e 74 2d 5a f4 e3 3b 11 67 8c cb 63 90 32 +04 a3 d0 80 b0 90 2c 89 ab a8 86 8f 00 9c 0f 1c +0c b8 58 10 bb dd 29 12 1a bb 84 71 ff 2d 39 e4 +9f d9 2d 56 c6 55 c8 e0 37 ad 18 fa fb dc 92 c9 +58 63 f7 f6 1e a9 ef a2 8f ea 40 13 69 d1 9d ae +a1 + +# -------------------------------- +# RSASSA-PSS Signature Example 5.5 +# -------------------------------- + +# Message to be signed: +f3 7b 96 23 79 a4 7d 41 5a 37 6e ec 89 73 15 0b +cb 34 ed d5 ab 65 40 41 b6 14 30 56 0c 21 44 58 +2b a1 33 c8 67 d8 52 d6 b8 e2 33 21 90 13 02 ec +b4 5b 09 ec 88 b1 52 71 78 fa 04 32 63 f3 06 7d +9f fe 97 30 32 a9 9f 4c b0 8a d2 c7 e0 a2 45 6c +dd 57 a7 df 56 fe 60 53 52 7a 5a eb 67 d7 e5 52 +06 3c 1c a9 7b 1b ef fa 7b 39 e9 97 ca f2 78 78 +ea 0f 62 cb eb c8 c2 1d f4 c8 89 a2 02 85 1e 94 +90 88 49 0c 24 9b 6e 9a cf 1d 80 63 f5 be 23 43 +98 9b f9 5c 4d a0 1a 2b e7 8b 4a b6 b3 78 01 5b +c3 79 57 f7 69 48 b5 e5 8e 44 0c 28 45 3d 40 d7 +cf d5 7e 7d 69 06 00 47 4a b5 e7 59 73 b1 ea 0c +5f 1e 45 d1 41 90 af e2 f4 eb 6d 3b df 71 f1 d2 +f8 bb 15 6a 1c 29 5d 04 aa eb 9d 68 9d ce 79 ed +62 bc 44 3e + +# Salt: +e2 0c 1e 98 78 51 2c 39 97 0f 58 37 5e 15 49 a6 +8b 64 f3 1d + +# Signature: +0a ef a9 43 b6 98 b9 60 9e df 89 8a d2 27 44 ac +28 dc 23 94 97 ce a3 69 cb bd 84 f6 5c 95 c0 ad +77 6b 59 47 40 16 4b 59 a7 39 c6 ff 7c 2f 07 c7 +c0 77 a8 6d 95 23 8f e5 1e 1f cf 33 57 4a 4a e0 +68 4b 42 a3 f6 bf 67 7d 91 82 0c a8 98 74 46 7b +2c 23 ad d7 79 69 c8 07 17 43 0d 0e fc 1d 36 95 +89 2c e8 55 cb 7f 70 11 63 0f 4d f2 6d ef 8d df +36 fc 23 90 5f 57 fa 62 43 a4 85 c7 70 d5 68 1f +cd + +# -------------------------------- +# RSASSA-PSS Signature Example 5.6 +# -------------------------------- + +# Message to be signed: +c6 10 3c 33 0c 1e f7 18 c1 41 e4 7b 8f a8 59 be +4d 5b 96 25 9e 7d 14 20 70 ec d4 85 83 9d ba 5a +83 69 c1 7c 11 14 03 5e 53 2d 19 5c 74 f4 4a 04 +76 a2 d3 e8 a4 da 21 00 16 ca ce d0 e3 67 cb 86 +77 10 a4 b5 aa 2d f2 b8 e5 da f5 fd c6 47 80 7d +4d 5e bb 6c 56 b9 76 3c cd ae 4d ea 33 08 eb 0a +c2 a8 95 01 cb 20 9d 26 39 fa 5b f8 7c e7 90 74 +7d 3c b2 d2 95 e8 45 64 f2 f6 37 82 4f 0c 13 02 +81 29 b0 aa 4a 42 2d 16 22 82 + +# Salt: +23 29 1e 4a 33 07 e8 bb b7 76 62 3a b3 4e 4a 5f +4c c8 a8 db + +# Signature: +02 80 2d cc fa 8d fa f5 27 9b f0 b4 a2 9b a1 b1 +57 61 1f ae aa f4 19 b8 91 9d 15 94 19 00 c1 33 +9e 7e 92 e6 fa e5 62 c5 3e 6c c8 e8 41 04 b1 10 +bc e0 3a d1 85 25 e3 c4 9a 0e ad ad 5d 3f 28 f2 +44 a8 ed 89 ed ba fb b6 86 27 7c fa 8a e9 09 71 +4d 6b 28 f4 bf 8e 29 3a a0 4c 41 ef e7 c0 a8 12 +66 d5 c0 61 e2 57 5b e0 32 aa 46 46 74 ff 71 62 +62 19 bd 74 cc 45 f0 e7 ed 4e 3f f9 6e ee 75 8e +8f + +# ============================================= + +# ================================== +# Example 6: A 1029-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +16 4c a3 1c ff 60 9f 3a 0e 71 01 b0 39 f2 e4 fe +6d d3 75 19 ab 98 59 8d 17 9e 17 49 96 59 80 71 +f4 7d 3a 04 55 91 58 d7 be 37 3c f1 aa 53 f0 aa +6e f0 90 39 e5 67 8c 2a 4c 63 90 05 14 c8 c4 f8 +aa ed 5d e1 2a 5f 10 b0 9c 31 1a f8 c0 ff b5 b7 +a2 97 f2 ef c6 3b 8d 6b 05 10 93 1f 0b 98 e4 8b +f5 fc 6e c4 e7 b8 db 1f fa eb 08 c3 8e 02 ad b8 +f0 3a 48 22 9c 99 e9 69 43 1f 61 cb 8c 4d c6 98 +d1 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +03 b6 64 ee 3b 75 66 72 3f c6 ea f2 8a bb 43 0a +39 80 f1 12 6c 81 de 8a d7 09 ea b3 9a c9 dc d0 +b1 55 0b 37 29 d8 70 68 e9 52 00 9d f5 44 53 4c +1f 50 82 9a 78 f4 59 1e b8 fd 57 14 04 26 a6 bb +04 05 b6 a6 f5 1a 57 d9 26 7b 7b bc 65 33 91 a6 +99 a2 a9 0d ac 8a e2 26 bc c6 0f a8 cd 93 4c 73 +c7 b0 3b 1f 6b 81 81 58 63 18 38 a8 61 2e 6e 6e +a9 2b e2 4f 83 24 fa f5 b1 fd 85 87 22 52 67 ba +6f + +# Prime p: +04 f0 54 8c 96 26 ab 1e bf 12 44 93 47 41 d9 9a +06 22 0e fa 2a 58 56 aa 0e 75 73 0b 2e c9 6a dc +86 be 89 4f a2 80 3b 53 a5 e8 5d 27 6a cb d2 9a +b8 23 f8 0a 73 91 bb 54 a5 05 16 72 fb 04 ee b5 +43 + +# Prime q: +04 83 e0 ae 47 91 55 87 74 3f f3 45 36 2b 55 5d +39 62 d9 8b b6 f1 5f 84 8b 4c 92 b1 77 1c a8 ed +10 7d 8d 3e e6 5e c4 45 17 dd 0f aa 48 1a 38 7e +90 2f 7a 2e 74 7c 26 9e 7e a4 44 80 bc 53 8b 8e +5b + +# p's CRT exponent dP: +03 a8 e8 ae a9 92 0c 1a a3 b2 f0 d8 46 e4 b8 50 +d8 1c a3 06 a5 1c 83 54 4f 94 9f 64 f9 0d cf 3f +8e 26 61 f0 7e 56 12 20 a1 80 38 8f be 27 3e 70 +e2 e5 dc a8 3a 0e 13 48 dd 64 90 c7 31 d6 ec e1 +ab + +# q's CRT exponent dQ: +01 35 bd cd b6 0b f2 19 7c 43 6e d3 4b 32 cd 8b +4f c7 77 78 83 2b a7 67 03 55 1f b2 42 b3 01 69 +95 93 af 77 fd 8f c3 94 a8 52 6a d2 3c c4 1a 03 +80 6b d8 97 fe 4b 0e a6 46 55 8a ad dc c9 9e 8a +25 + +# CRT coefficient qInv: +03 04 c0 3d 9c 73 65 03 a9 84 ab bd 9b a2 23 01 +40 7c 4a 2a b1 dd 85 76 64 81 b6 0d 45 40 11 52 +e6 92 be 14 f4 12 1d 9a a3 fd 6e 0b 4d 1d 3a 97 +35 38 a3 1d 42 ee 6e 1e 5e f6 20 23 1a 2b ba f3 +5f + +# -------------------------------- +# RSASSA-PSS Signature Example 6.1 +# -------------------------------- + +# Message to be signed: +0a 20 b7 74 ad dc 2f a5 12 45 ed 7c b9 da 60 9e +50 ca c6 63 6a 52 54 3f 97 45 8e ed 73 40 f8 d5 +3f fc 64 91 8f 94 90 78 ee 03 ef 60 d4 2b 5f ec +24 60 50 bd 55 05 cd 8c b5 97 ba d3 c4 e7 13 b0 +ef 30 64 4e 76 ad ab b0 de 01 a1 56 1e fb 25 51 +58 c7 4f c8 01 e6 e9 19 e5 81 b4 6f 0f 0d dd 08 +e4 f3 4c 78 10 b5 ed 83 18 f9 1d 7c 8c + +# Salt: +5b 4e a2 ef 62 9c c2 2f 3b 53 8e 01 69 04 b4 7b +1e 40 bf d5 + +# Signature: +04 c0 cf ac ec 04 e5 ba db ec e1 59 a5 a1 10 3f +69 b3 f3 2b a5 93 cb 4c c4 b1 b7 ab 45 59 16 a9 +6a 27 cd 26 78 ea 0f 46 ba 37 f7 fc 9c 86 32 5f +29 73 3b 38 9f 1d 97 f4 3e 72 01 c0 f3 48 fc 45 +fe 42 89 23 35 36 2e ee 01 8b 5b 16 1f 2f 93 93 +03 12 25 c7 13 01 2a 57 6b c8 8e 23 05 24 89 86 +8d 90 10 cb f0 33 ec c5 68 e8 bc 15 2b dc 59 d5 +60 e4 12 91 91 5d 28 56 52 08 e2 2a ee c9 ef 85 +d1 + +# -------------------------------- +# RSASSA-PSS Signature Example 6.2 +# -------------------------------- + +# Message to be signed: +2a af f6 63 1f 62 1c e6 15 76 0a 9e bc e9 4b b3 +33 07 7a d8 64 88 c8 61 d4 b7 6d 29 c1 f4 87 46 +c6 11 ae 1e 03 ce d4 44 5d 7c fa 1f e5 f6 2e 1b +3f 08 45 2b de 3b 6e f8 19 73 ba fb b5 7f 97 bc +ee f8 73 98 53 95 b8 26 05 89 aa 88 cb 7d b5 0a +b4 69 26 2e 55 1b dc d9 a5 6f 27 5a 0a c4 fe 48 +47 00 c3 5f 3d bf 2b 46 9e de 86 47 41 b8 6f a5 +91 72 a3 60 ba 95 a0 2e 13 9b e5 0d df b7 cf 0b +42 fa ea bb fb ba a8 6a 44 97 69 9c 4f 2d fd 5b +08 40 6a f7 e1 41 44 42 7c 25 3e c0 ef a2 0e af +9a 8b e8 cd 49 ce 1f 1b c4 e9 3e 61 9c f2 aa 8e +d4 fb 39 bc 85 90 d0 f7 b9 64 88 f7 31 7a c9 ab +f7 be e4 e3 a0 e7 15 + +# Salt: +83 14 6a 9e 78 27 22 c2 8b 01 4f 98 b4 26 7b da +2a c9 50 4f + +# Signature: +0a 23 14 25 0c f5 2b 6e 4e 90 8d e5 b3 56 46 bc +aa 24 36 1d a8 16 0f b0 f9 25 75 90 ab 3a ce 42 +b0 dc 3e 77 ad 2d b7 c2 03 a2 0b d9 52 fb b5 6b +15 67 04 6e cf aa 93 3d 7b 10 00 c3 de 9f f0 5b +7d 98 9b a4 6f d4 3b c4 c2 d0 a3 98 6b 7f fa 13 +47 1d 37 eb 5b 47 d6 47 07 bd 29 0c fd 6a 9f 39 +3a d0 8e c1 e3 bd 71 bb 57 92 61 50 35 cd af 2d +89 29 ae d3 be 09 83 79 37 7e 77 7c e7 9a aa 47 +73 + +# -------------------------------- +# RSASSA-PSS Signature Example 6.3 +# -------------------------------- + +# Message to be signed: +0f 61 95 d0 4a 6e 6f c7 e2 c9 60 0d bf 84 0c 39 +ea 8d 4d 62 4f d5 35 07 01 6b 0e 26 85 8a 5e 0a +ec d7 ad a5 43 ae 5c 0a b3 a6 25 99 cb a0 a5 4e +6b f4 46 e2 62 f9 89 97 8f 9d df 5e 9a 41 + +# Salt: +a8 7b 8a ed 07 d7 b8 e2 da f1 4d dc a4 ac 68 c4 +d0 aa bf f8 + +# Signature: +08 6d f6 b5 00 09 8c 12 0f 24 ff 84 23 f7 27 d9 +c6 1a 5c 90 07 d3 b6 a3 1c e7 cf 8f 3c be c1 a2 +6b b2 0e 2b d4 a0 46 79 32 99 e0 3e 37 a2 1b 40 +19 4f b0 45 f9 0b 18 bf 20 a4 79 92 cc d7 99 cf +9c 05 9c 29 9c 05 26 85 49 54 aa de 8a 6a d9 d9 +7e c9 1a 11 45 38 3f 42 46 8b 23 1f 4d 72 f2 37 +06 d9 85 3c 3f a4 3c e8 ac e8 bf e7 48 49 87 a1 +ec 6a 16 c8 da f8 1f 7c 8b f4 27 74 70 7a 9d f4 +56 + +# -------------------------------- +# RSASSA-PSS Signature Example 6.4 +# -------------------------------- + +# Message to be signed: +33 7d 25 fe 98 10 eb ca 0d e4 d4 65 8d 3c eb 8e +0f e4 c0 66 ab a3 bc c4 8b 10 5d 3b f7 e0 25 7d +44 fe ce a6 59 6f 4d 0c 59 a0 84 02 83 36 78 f7 +06 20 f9 13 8d fe b7 de d9 05 e4 a6 d5 f0 5c 47 +3d 55 93 66 52 e2 a5 df 43 c0 cf da 7b ac af 30 +87 f4 52 4b 06 cf 42 15 7d 01 53 97 39 f7 fd de +c9 d5 81 25 df 31 a3 2e ab 06 c1 9b 71 f1 d5 bf + +# Salt: +a3 79 32 f8 a7 49 4a 94 2d 6f 76 74 38 e7 24 d6 +d0 c0 ef 18 + +# Signature: +0b 5b 11 ad 54 98 63 ff a9 c5 1a 14 a1 10 6c 2a +72 cc 8b 64 6e 5c 72 62 50 97 86 10 5a 98 47 76 +53 4c a9 b5 4c 1c c6 4b f2 d5 a4 4f d7 e8 a6 9d +b6 99 d5 ea 52 08 7a 47 48 fd 2a bc 1a fe d1 e5 +d6 f7 c8 90 25 53 0b da a2 21 3d 7e 03 0f a5 5d +f6 f3 4b cf 1c e4 6d 2e df 4e 3a e4 f3 b0 18 91 +a0 68 c9 e3 a4 4b bc 43 13 3e da d6 ec b9 f3 54 +00 c4 25 2a 57 62 d6 57 44 b9 9c b9 f4 c5 59 32 +9f + +# -------------------------------- +# RSASSA-PSS Signature Example 6.5 +# -------------------------------- + +# Message to be signed: +84 ec 50 2b 07 2e 82 87 78 9d 8f 92 35 82 9e a3 +b1 87 af d4 d4 c7 85 61 1b da 5f 9e b3 cb 96 71 +7e fa 70 07 22 7f 1c 08 cb cb 97 2e 66 72 35 e0 +fb 7d 43 1a 65 70 32 6d 2e cc e3 5a db 37 3d c7 +53 b3 be 5f 82 9b 89 17 54 93 19 3f ab 16 ba db +41 37 1b 3a ac 0a e6 70 07 6f 24 be f4 20 c1 35 +ad d7 ce e8 d3 5f bc 94 4d 79 fa fb 9e 30 7a 13 +b0 f5 56 cb 65 4a 06 f9 73 ed 22 67 23 30 19 7e +f5 a7 48 bf 82 6a 5d b2 38 3a 25 36 4b 68 6b 93 +72 bb 23 39 ae b1 ac 9e 98 89 32 7d 01 6f 16 70 +77 6d b0 62 01 ad bd ca f8 a5 e3 b7 4e 10 8b 73 + +# Salt: +7b 79 0c 1d 62 f7 b8 4e 94 df 6a f2 89 17 cf 57 +10 18 11 0e + +# Signature: +02 d7 1f a9 b5 3e 46 54 fe fb 7f 08 38 5c f6 b0 +ae 3a 81 79 42 eb f6 6c 35 ac 67 f0 b0 69 95 2a +3c e9 c7 e1 f1 b0 2e 48 0a 95 00 83 6d e5 d6 4c +db 7e cd e0 45 42 f7 a7 99 88 78 7e 24 c2 ba 05 +f5 fd 48 2c 02 3e d5 c3 0e 04 83 9d c4 4b ed 2a +3a 3a 4f ee 01 11 3c 89 1a 47 d3 2e b8 02 5c 28 +cb 05 0b 5c db 57 6c 70 fe 76 ef 52 34 05 c0 84 +17 fa f3 50 b0 37 a4 3c 37 93 39 fc b1 8d 3a 35 +6b + +# -------------------------------- +# RSASSA-PSS Signature Example 6.6 +# -------------------------------- + +# Message to be signed: +99 06 d8 9f 97 a9 fd ed d3 cc d8 24 db 68 73 26 +f3 0f 00 aa 25 a7 fc a2 af cb 3b 0f 86 cd 41 e7 +3f 0e 8f f7 d2 d8 3f 59 e2 8e d3 1a 5a 0d 55 15 +23 37 4d e2 2e 4c 7e 8f f5 68 b3 86 ee 3d c4 11 +63 f1 0b f6 7b b0 06 26 1c 90 82 f9 af 90 bf 1d +90 49 a6 b9 fa e7 1c 7f 84 fb e6 e5 5f 02 78 9d +e7 74 f2 30 f1 15 02 6a 4b 4e 96 c5 5b 04 a9 5d +a3 aa cb b2 ce ce 8f 81 76 4a 1f 1c 99 51 54 11 +08 7c f7 d3 4a ed ed 09 32 c1 83 + +# Salt: +fb be 05 90 25 b6 9b 89 fb 14 ae 22 89 e7 aa af +e6 0c 0f cd + +# Signature: +0a 40 a1 6e 2f e2 b3 8d 1d f9 05 46 16 7c f9 46 +9c 9e 3c 36 81 a3 44 2b 4b 2c 2f 58 1d eb 38 5c +e9 9f c6 18 8b b0 2a 84 1d 56 e7 6d 30 18 91 e2 +45 60 55 0f cc 2a 26 b5 5f 4c cb 26 d8 37 d3 50 +a1 54 bc ac a8 39 2d 98 fa 67 95 9e 97 27 b7 8c +ad 03 26 9f 56 96 8f c5 6b 68 bd 67 99 26 d8 3c +c9 cb 21 55 50 64 5c cd a3 1c 76 0f f3 58 88 94 +3d 2d 8a 1d 35 1e 81 e5 d0 7b 86 18 2e 75 10 81 +ef + +# ============================================= + +# ================================== +# Example 7: A 1030-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +37 c9 da 4a 66 c8 c4 08 b8 da 27 d0 c9 d7 9f 8c +cb 1e af c1 d2 fe 48 74 6d 94 0b 7c 4e f5 de e1 +8a d1 26 47 ce fa a0 c4 b3 18 8b 22 1c 51 53 86 +75 9b 93 f0 20 24 b2 5a b9 24 2f 83 57 d8 f3 fd +49 64 0e e5 e6 43 ea f6 c6 4d ee fa 70 89 72 7c +8f f0 39 93 33 39 15 c6 ef 21 bf 59 75 b6 e5 0d +11 8b 51 00 8e c3 3e 9f 01 a0 a5 45 a1 0a 83 6a +43 dd bc a9 d8 b5 c5 d3 54 80 22 d7 06 4e a2 9a +b3 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +3b ed 99 90 52 d9 57 bc 06 d6 51 ee f6 e3 a9 80 +94 b1 62 1b d3 8b 54 49 bd 6c 4a ea 3d e7 e0 84 +67 9a 44 84 de d2 5b e0 f0 82 6c f3 37 78 25 41 +4b 14 d4 d6 1d b1 4d e6 26 fb b8 0e 5f 4f ae c9 +56 f9 a0 a2 d2 4f 99 57 63 80 f0 84 eb 62 e4 6a +57 d5 54 27 8b 53 56 26 19 3c e0 20 60 57 5e b6 +6c 57 98 d3 6f 6c 5d 40 fb 00 d8 09 b4 2a 73 10 +2c 1c 74 ee 95 bd 71 42 0f ff ef 63 18 b5 2c 29 + +# Prime p: +07 ee fb 42 4b 0e 3a 40 e4 20 8e e5 af b2 80 b2 +23 17 30 81 14 dd e0 b4 b6 4f 73 01 84 ec 68 da +6c e2 86 7a 9f 48 ed 77 26 d5 e2 61 4e d0 4a 54 +10 73 6c 8c 71 4e e7 02 47 42 98 c6 29 2a f0 75 +35 + +# Prime q: +07 08 30 db f9 47 ea c0 22 8d e2 63 14 b5 9b 66 +99 4c c6 0e 83 60 e7 5d 38 76 29 8f 8f 8a 7d 14 +1d a0 64 e5 ca 02 6a 97 3e 28 f2 54 73 8c ee 66 +9c 72 1b 03 4c b5 f8 e2 44 da dd 7c d1 e1 59 d5 +47 + +# p's CRT exponent dP: +05 24 d2 0c 3d 95 cf f7 5a f2 31 34 83 22 7d 87 +02 71 7a a5 76 de 15 5f 96 05 15 50 1a db 1d 70 +e1 c0 4d e9 1b 75 b1 61 db f0 39 83 56 12 7e de +da 7b bc 19 a3 2d c1 62 1c c9 f5 3c 26 5d 0c e3 +31 + +# q's CRT exponent dQ: +05 f9 84 a1 f2 3c 93 8d 6a 0e 89 72 4b cf 3d d9 +3f 99 46 92 60 37 fe 7c 6b 13 a2 9e 52 84 85 5f +89 08 95 91 d4 40 97 56 27 bf 5c 9e 3a 8b 5c a7 +9c 77 2a d2 73 e4 0d 32 1a f4 a6 c9 7d fd ed 78 +d3 + +# CRT coefficient qInv: +dd d9 18 ad ad a2 9d ca b9 81 ff 9a cb a4 25 70 +23 c0 9a 38 01 cc ce 09 8c e2 68 f8 55 d0 df 57 +0c d6 e7 b9 b1 4b d9 a5 a9 25 4c bc 31 5b e6 f8 +ba 1e 25 46 dd d5 69 c5 ea 19 ee d8 35 3b de 5e + +# -------------------------------- +# RSASSA-PSS Signature Example 7.1 +# -------------------------------- + +# Message to be signed: +9e ad 0e 01 94 56 40 67 4e b4 1c ad 43 5e 23 74 +ea ef a8 ad 71 97 d9 79 13 c4 49 57 d8 d8 3f 40 +d7 6e e6 0e 39 bf 9c 0f 9e af 30 21 42 1a 07 4d +1a de 96 2c 6e 9d 3d c3 bb 17 4f e4 df e6 52 b0 +91 15 49 5b 8f d2 79 41 74 02 0a 06 02 b5 ca 51 +84 8c fc 96 ce 5e b5 7f c0 a2 ad c1 dd a3 6a 7c +c4 52 64 1a 14 91 1b 37 e4 5b fa 11 da a5 c7 ec +db 74 f6 d0 10 0d 1d 3e 39 e7 52 80 0e 20 33 97 +de 02 33 07 7b 9a 88 85 55 37 fa e9 27 f9 24 38 +0d 78 0f 98 e1 8d cf f3 9c 5e a7 41 b1 7d 6f dd +18 85 bc 9d 58 14 82 d7 71 ce b5 62 d7 8a 8b f8 +8f 0c 75 b1 13 63 e5 e3 6c d4 79 ce b0 54 5f 9d +a8 42 03 e0 e6 e5 08 37 5c c9 e8 44 b8 8b 7a c7 +a0 a2 01 ea 0f 1b ee 9a 2c 57 79 20 ca 02 c0 1b +9d 83 20 e9 74 a5 6f 4e fb 57 63 b9 62 55 ab bf +80 37 bf 18 02 cf 01 8f 56 37 94 93 e5 69 a9 + +# Salt: +b7 86 7a 59 95 8c b5 43 28 f8 77 5e 65 46 ec 06 +d2 7e aa 50 + +# Signature: +18 7f 39 07 23 c8 90 25 91 f0 15 4b ae 6d 4e cb +ff e0 67 f0 e8 b7 95 47 6e a4 f4 d5 1c cc 81 05 +20 bb 3c a9 bc a7 d0 b1 f2 ea 8a 17 d8 73 fa 27 +57 0a cd 64 2e 38 08 56 1c b9 e9 75 cc fd 80 b2 +3d c5 77 1c db 33 06 a5 f2 31 59 da cb d3 aa 2d +b9 3d 46 d7 66 e0 9e d1 5d 90 0a d8 97 a8 d2 74 +dc 26 b4 7e 99 4a 27 e9 7e 22 68 a7 66 53 3a e4 +b5 e4 2a 2f ca f7 55 c1 c4 79 4b 29 4c 60 55 58 +23 + +# -------------------------------- +# RSASSA-PSS Signature Example 7.2 +# -------------------------------- + +# Message to be signed: +8d 80 d2 d0 8d bd 19 c1 54 df 3f 14 67 3a 14 bd +03 73 52 31 f2 4e 86 bf 15 3d 0e 69 e7 4c bf f7 +b1 83 6e 66 4d e8 3f 68 01 24 37 0f c0 f9 6c 9b +65 c0 7a 36 6b 64 4c 4a b3 + +# Salt: +0c 09 58 22 66 df 08 63 10 82 1b a7 e1 8d f6 4d +fe e6 de 09 + +# Signature: +10 fd 89 76 8a 60 a6 77 88 ab b5 85 6a 78 7c 85 +61 f3 ed cf 9a 83 e8 98 f7 dc 87 ab 8c ce 79 42 +9b 43 e5 69 06 94 1a 88 61 94 f1 37 e5 91 fe 7c +33 95 55 36 1f bb e1 f2 4f eb 2d 4b cd b8 06 01 +f3 09 6b c9 13 2d ee a6 0a e1 30 82 f4 4f 9a d4 +1c d6 28 93 6a 4d 51 17 6e 42 fc 59 cb 76 db 81 +5c e5 ab 4d b9 9a 10 4a af ea 68 f5 d3 30 32 9e +bf 25 8d 4e de 16 06 4b d1 d0 03 93 d5 e1 57 0e +b8 + +# -------------------------------- +# RSASSA-PSS Signature Example 7.3 +# -------------------------------- + +# Message to be signed: +80 84 05 cd fc 1a 58 b9 bb 03 97 c7 20 72 2a 81 +ff fb 76 27 8f 33 59 17 ef 9c 47 38 14 b3 e0 16 +ba 29 73 cd 27 65 f8 f3 f8 2d 6c c3 8a a7 f8 55 +18 27 fe 8d 1e 38 84 b7 e6 1c 94 68 3b 8f 82 f1 +84 3b da e2 25 7e ee c9 81 2a d4 c2 cf 28 3c 34 +e0 b0 ae 0f e3 cb 99 0c f8 8f 2e f9 + +# Salt: +28 03 9d cf e1 06 d3 b8 29 66 11 25 8c 4a 56 65 +1c 9e 92 dd + +# Signature: +2b 31 fd e9 98 59 b9 77 aa 09 58 6d 8e 27 46 62 +b2 5a 2a 64 06 40 b4 57 f5 94 05 1c b1 e7 f7 a9 +11 86 54 55 24 29 26 cf 88 fe 80 df a3 a7 5b a9 +68 98 44 a1 1e 63 4a 82 b0 75 af bd 69 c1 2a 0d +f9 d2 5f 84 ad 49 45 df 3d c8 fe 90 c3 ce fd f2 +6e 95 f0 53 43 04 b5 bd ba 20 d3 e5 64 0a 2e bf +b8 98 aa c3 5a e4 0f 26 fc e5 56 3c 2f 9f 24 f3 +04 2a f7 6f 3c 70 72 d6 87 bb fb 95 9a 88 46 0a +f1 + +# -------------------------------- +# RSASSA-PSS Signature Example 7.4 +# -------------------------------- + +# Message to be signed: +f3 37 b9 ba d9 37 de 22 a1 a0 52 df f1 11 34 a8 +ce 26 97 62 02 98 19 39 b9 1e 07 15 ae 5e 60 96 +49 da 1a df ce f3 f4 cc a5 9b 23 83 60 e7 d1 e4 +96 c7 bf 4b 20 4b 5a cf f9 bb d6 16 6a 1d 87 a3 +6e f2 24 73 73 75 10 39 f8 a8 00 b8 39 98 07 b3 +a8 5f 44 89 34 97 c0 d0 5f b7 01 7b 82 22 81 52 +de 6f 25 e6 11 6d cc 75 03 c7 86 c8 75 c2 8f 3a +a6 07 e9 4a b0 f1 98 63 ab 1b 50 73 77 0b 0c d5 +f5 33 ac de 30 c6 fb 95 3c f3 da 68 02 64 e3 0f +c1 1b ff 9a 19 bf fa b4 77 9b 62 23 c3 fb 3f e0 +f7 1a ba de 4e b7 c0 9c 41 e2 4c 22 d2 3f a1 48 +e6 a1 73 fe b6 39 84 d1 bc 6e e3 a0 2d 91 5b 75 +2c ea f9 2a 30 15 ec eb 38 ca 58 6c 68 01 b3 7c +34 ce fb 2c ff 25 ea 23 c0 86 62 dc ab 26 a7 a9 +3a 28 5d 05 d3 04 4c + +# Salt: +a7 78 21 eb bb ef 24 62 8e 4e 12 e1 d0 ea 96 de +39 8f 7b 0f + +# Signature: +32 c7 ca 38 ff 26 94 9a 15 00 0c 4b a0 4b 2b 13 +b3 5a 38 10 e5 68 18 4d 7e ca ba a1 66 b7 ff ab +dd f2 b6 cf 4b a0 71 24 92 37 90 f2 e5 b1 a5 be +04 0a ea 36 fe 13 2e c1 30 e1 f1 05 67 98 2d 17 +ac 3e 89 b8 d2 6c 30 94 03 4e 76 2d 2e 03 12 64 +f0 11 70 be ec b3 d1 43 9e 05 84 6f 25 45 83 67 +a7 d9 c0 20 60 44 46 72 67 1e 64 e8 77 86 45 59 +ca 19 b2 07 4d 58 8a 28 1b 58 04 d2 37 72 fb be +19 + +# -------------------------------- +# RSASSA-PSS Signature Example 7.5 +# -------------------------------- + +# Message to be signed: +45 01 3c eb af d9 60 b2 55 47 6a 8e 25 98 b9 aa +32 ef be 6d c1 f3 4f 4a 49 8d 8c f5 a2 b4 54 8d +08 c5 5d 5f 95 f7 bc c9 61 91 63 05 6f 2d 58 b5 +2f a0 32 + +# Salt: +9d 5a d8 eb 45 21 34 b6 5d c3 a9 8b 6a 73 b5 f7 +41 60 9c d6 + +# Signature: +07 eb 65 1d 75 f1 b5 2b c2 63 b2 e1 98 33 6e 99 +fb eb c4 f3 32 04 9a 92 2a 10 81 56 07 ee 2d 98 +9d b3 a4 49 5b 7d cc d3 8f 58 a2 11 fb 7e 19 31 +71 a3 d8 91 13 24 37 eb ca 44 f3 18 b2 80 50 9e +52 b5 fa 98 fc ce 82 05 d9 69 7c 8e e4 b7 ff 59 +d4 c5 9c 79 03 8a 19 70 bd 2a 0d 45 1e cd c5 ef +11 d9 97 9c 9d 35 f8 c7 0a 61 63 71 76 07 89 0d +58 6a 7c 6d c0 1c 79 f8 6a 8f 28 e8 52 35 f8 c2 +f1 + +# -------------------------------- +# RSASSA-PSS Signature Example 7.6 +# -------------------------------- + +# Message to be signed: +23 58 09 70 86 c8 99 32 3e 75 d9 c9 0d 0c 09 f1 +2d 9d 54 ed fb df 70 a9 c2 eb 5a 04 d8 f3 6b 9b +2b df 2a ab e0 a5 bd a1 96 89 37 f9 d6 eb d3 b6 +b2 57 ef b3 13 6d 41 31 f9 ac b5 9b 85 e2 60 2c +2a 3f cd c8 35 49 4a 1f 4e 5e c1 8b 22 6c 80 23 +2b 36 a7 5a 45 fd f0 9a 7e a9 e9 8e fb de 14 50 +d1 19 4b f1 2e 15 a4 c5 f9 eb 5c 0b ce 52 69 e0 +c3 b2 8c fa b6 55 d8 1a 61 a2 0b 4b e2 f5 44 59 +bb 25 a0 db 94 c5 22 18 be 10 9a 74 26 de 83 01 +44 24 78 9a aa 90 e5 05 6e 63 2a 69 81 15 e2 82 +c1 a5 64 10 f2 6c 20 72 f1 93 48 1a 9d cd 88 05 +72 00 5e 64 f4 08 2e cf + +# Salt: +3f 2e fc 59 58 80 a7 d4 7f cf 3c ba 04 98 3e a5 +4c 4b 73 fb + +# Signature: +18 da 3c dc fe 79 bf b7 7f d9 c3 2f 37 7a d3 99 +14 6f 0a 8e 81 06 20 23 32 71 a6 e3 ed 32 48 90 +3f 5c dc 92 dc 79 b5 5d 3e 11 61 5a a0 56 a7 95 +85 37 92 a3 99 8c 34 9c a5 c4 57 e8 ca 7d 29 d7 +96 aa 24 f8 34 91 70 9b ef cf b1 51 0e a5 13 c9 +28 29 a3 f0 0b 10 4f 65 56 34 f3 20 75 2e 13 0e +c0 cc f6 75 4f f8 93 db 30 29 32 bb 02 5e b6 0e +87 82 25 98 fc 61 9e 0e 98 17 37 a9 a4 c4 15 2d +33 + +# ============================================= + +# ================================== +# Example 8: A 1031-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +49 53 70 a1 fb 18 54 3c 16 d3 63 1e 31 63 25 5d +f6 2b e6 ee e8 90 d5 f2 55 09 e4 f7 78 a8 ea 6f +bb bc df 85 df f6 4e 0d 97 20 03 ab 36 81 fb ba +6d d4 1f d5 41 82 9b 2e 58 2d e9 f2 a4 a4 e0 a2 +d0 90 0b ef 47 53 db 3c ee 0e e0 6c 7d fa e8 b1 +d5 3b 59 53 21 8f 9c ce ea 69 5b 08 66 8e de aa +dc ed 94 63 b1 d7 90 d5 eb f2 7e 91 15 b4 6c ad +4d 9a 2b 8e fa b0 56 1b 08 10 34 47 39 ad a0 73 +3f + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +6c 66 ff e9 89 80 c3 8f cd ea b5 15 98 98 83 61 +65 f4 b4 b8 17 c4 f6 a8 d4 86 ee 4e a9 13 0f e9 +b9 09 2b d1 36 d1 84 f9 5f 50 4a 60 7e ac 56 58 +46 d2 fd d6 59 7a 89 67 c7 39 6e f9 5a 6e ee bb +45 78 a6 43 96 6d ca 4d 8e e3 de 84 2d e6 32 79 +c6 18 15 9c 1a b5 4a 89 43 7b 6a 61 20 e4 93 0a +fb 52 a4 ba 6c ed 8a 49 47 ac 64 b3 0a 34 97 cb +e7 01 c2 d6 26 6d 51 72 19 ad 0e c6 d3 47 db e9 + +# Prime p: +08 da d7 f1 13 63 fa a6 23 d5 d6 d5 e8 a3 19 32 +8d 82 19 0d 71 27 d2 84 6c 43 9b 0a b7 26 19 b0 +a4 3a 95 32 0e 4e c3 4f c3 a9 ce a8 76 42 23 05 +bd 76 c5 ba 7b e9 e2 f4 10 c8 06 06 45 a1 d2 9e +db + +# Prime q: +08 47 e7 32 37 6f c7 90 0f 89 8e a8 2e b2 b0 fc +41 85 65 fd ae 62 f7 d9 ec 4c e2 21 7b 97 99 0d +d2 72 db 15 7f 99 f6 3c 0d cb b9 fb ac db d4 c4 +da db 6d f6 77 56 35 8c a4 17 48 25 b4 8f 49 70 +6d + +# p's CRT exponent dP: +05 c2 a8 3c 12 4b 36 21 a2 aa 57 ea 2c 3e fe 03 +5e ff 45 60 f3 3d de bb 7a da b8 1f ce 69 a0 c8 +c2 ed c1 65 20 dd a8 3d 59 a2 3b e8 67 96 3a c6 +5f 2c c7 10 bb cf b9 6e e1 03 de b7 71 d1 05 fd +85 + +# q's CRT exponent dQ: +04 ca e8 aa 0d 9f aa 16 5c 87 b6 82 ec 14 0b 8e +d3 b5 0b 24 59 4b 7a 3b 2c 22 0b 36 69 bb 81 9f +98 4f 55 31 0a 1a e7 82 36 51 d4 a0 2e 99 44 79 +72 59 51 39 36 34 34 e5 e3 0a 7e 7d 24 15 51 e1 +b9 + +# CRT coefficient qInv: +07 d3 e4 7b f6 86 60 0b 11 ac 28 3c e8 8d bb 3f +60 51 e8 ef d0 46 80 e4 4c 17 1e f5 31 b8 0b 2b +7c 39 fc 76 63 20 e2 cf 15 d8 d9 98 20 e9 6f f3 +0d c6 96 91 83 9c 4b 40 d7 b0 6e 45 30 7d c9 1f +3f + +# -------------------------------- +# RSASSA-PSS Signature Example 8.1 +# -------------------------------- + +# Message to be signed: +81 33 2f 4b e6 29 48 41 5e a1 d8 99 79 2e ea cf +6c 6e 1d b1 da 8b e1 3b 5c ea 41 db 2f ed 46 70 +92 e1 ff 39 89 14 c7 14 25 97 75 f5 95 f8 54 7f +73 56 92 a5 75 e6 92 3a f7 8f 22 c6 99 7d db 90 +fb 6f 72 d7 bb 0d d5 74 4a 31 de cd 3d c3 68 58 +49 83 6e d3 4a ec 59 63 04 ad 11 84 3c 4f 88 48 +9f 20 97 35 f5 fb 7f da f7 ce c8 ad dc 58 18 16 +8f 88 0a cb f4 90 d5 10 05 b7 a8 e8 4e 43 e5 42 +87 97 75 71 dd 99 ee a4 b1 61 eb 2d f1 f5 10 8f +12 a4 14 2a 83 32 2e db 05 a7 54 87 a3 43 5c 9a +78 ce 53 ed 93 bc 55 08 57 d7 a9 fb + +# Salt: +1d 65 49 1d 79 c8 64 b3 73 00 9b e6 f6 f2 46 7b +ac 4c 78 fa + +# Signature: +02 62 ac 25 4b fa 77 f3 c1 ac a2 2c 51 79 f8 f0 +40 42 2b 3c 5b af d4 0a 8f 21 cf 0f a5 a6 67 cc +d5 99 3d 42 db af b4 09 c5 20 e2 5f ce 2b 1e e1 +e7 16 57 7f 1e fa 17 f3 da 28 05 2f 40 f0 41 9b +23 10 6d 78 45 aa f0 11 25 b6 98 e7 a4 df e9 2d +39 67 bb 00 c4 d0 d3 5b a3 55 2a b9 a8 b3 ee f0 +7c 7f ec db c5 42 4a c4 db 1e 20 cb 37 d0 b2 74 +47 69 94 0e a9 07 e1 7f bb ca 67 3b 20 52 23 80 +c5 + +# -------------------------------- +# RSASSA-PSS Signature Example 8.2 +# -------------------------------- + +# Message to be signed: +e2 f9 6e af 0e 05 e7 ba 32 6e cc a0 ba 7f d2 f7 +c0 23 56 f3 ce de 9d 0f aa bf 4f cc 8e 60 a9 73 +e5 59 5f d9 ea 08 + +# Salt: +43 5c 09 8a a9 90 9e b2 37 7f 12 48 b0 91 b6 89 +87 ff 18 38 + +# Signature: +27 07 b9 ad 51 15 c5 8c 94 e9 32 e8 ec 0a 28 0f +56 33 9e 44 a1 b5 8d 4d dc ff 2f 31 2e 5f 34 dc +fe 39 e8 9c 6a 94 dc ee 86 db bd ae 5b 79 ba 4e +08 19 a9 e7 bf d9 d9 82 e7 ee 6c 86 ee 68 39 6e +8b 3a 14 c9 c8 f3 4b 17 8e b7 41 f9 d3 f1 21 10 +9b f5 c8 17 2f ad a2 e7 68 f9 ea 14 33 03 2c 00 +4a 8a a0 7e b9 90 00 0a 48 dc 94 c8 ba c8 aa be +2b 09 b1 aa 46 c0 a2 aa 0e 12 f6 3f bb a7 75 ba +7e + +# -------------------------------- +# RSASSA-PSS Signature Example 8.3 +# -------------------------------- + +# Message to be signed: +e3 5c 6e d9 8f 64 a6 d5 a6 48 fc ab 8a db 16 33 +1d b3 2e 5d 15 c7 4a 40 ed f9 4c 3d c4 a4 de 79 +2d 19 08 89 f2 0f 1e 24 ed 12 05 4a 6b 28 79 8f +cb 42 d1 c5 48 76 9b 73 4c 96 37 31 42 09 2a ed +27 76 03 f4 73 8d f4 dc 14 46 58 6d 0e c6 4d a4 +fb 60 53 6d b2 ae 17 fc 7e 3c 04 bb fb bb d9 07 +bf 11 7c 08 63 6f a1 6f 95 f5 1a 62 16 93 4d 3e +34 f8 50 30 f1 7b bb c5 ba 69 14 40 58 af f0 81 +e0 b1 9c f0 3c 17 19 5c 5e 88 8b a5 8f 6f e0 a0 +2e 5c 3b da 97 19 a7 + +# Salt: +c6 eb be 76 df 0c 4a ea 32 c4 74 17 5b 2f 13 68 +62 d0 45 29 + +# Signature: +2a d2 05 09 d7 8c f2 6d 1b 6c 40 61 46 08 6e 4b +0c 91 a9 1c 2b d1 64 c8 7b 96 6b 8f aa 42 aa 0c +a4 46 02 23 23 ba 4b 1a 1b 89 70 6d 7f 4c 3b e5 +7d 7b 69 70 2d 16 8a b5 95 5e e2 90 35 6b 8c 4a +29 ed 46 7d 54 7e c2 3c ba df 28 6c cb 58 63 c6 +67 9d a4 67 fc 93 24 a1 51 c7 ec 55 aa c6 db 40 +84 f8 27 26 82 5c fe 1a a4 21 bc 64 04 9f b4 2f +23 14 8f 9c 25 b2 dc 30 04 37 c3 8d 42 8a a7 5f +96 + +# -------------------------------- +# RSASSA-PSS Signature Example 8.4 +# -------------------------------- + +# Message to be signed: +db c5 f7 50 a7 a1 4b e2 b9 3e 83 8d 18 d1 4a 86 +95 e5 2e 8a dd 9c 0a c7 33 b8 f5 6d 27 47 e5 29 +a0 cc a5 32 dd 49 b9 02 ae fe d5 14 44 7f 9e 81 +d1 61 95 c2 85 38 68 cb 9b 30 f7 d0 d4 95 c6 9d +01 b5 c5 d5 0b 27 04 5d b3 86 6c 23 24 a4 4a 11 +0b 17 17 74 6d e4 57 d1 c8 c4 5c 3c d2 a9 29 70 +c3 d5 96 32 05 5d 4c 98 a4 1d 6e 99 e2 a3 dd d5 +f7 f9 97 9a b3 cd 18 f3 75 05 d2 51 41 de 2a 1b +ff 17 b3 a7 dc e9 41 9e cc 38 5c f1 1d 72 84 0f +19 95 3f d0 50 92 51 f6 ca fd e2 89 3d 0e 75 c7 +81 ba 7a 50 12 ca 40 1a 4f a9 9e 04 b3 c3 24 9f +92 6d 5a fe 82 cc 87 da b2 2c 3c 1b 10 5d e4 8e +34 ac e9 c9 12 4e 59 59 7a c7 eb f8 + +# Salt: +02 1f dc c6 eb b5 e1 9b 1c b1 6e 9c 67 f2 76 81 +65 7f e2 0a + +# Signature: +1e 24 e6 e5 86 28 e5 17 50 44 a9 eb 6d 83 7d 48 +af 12 60 b0 52 0e 87 32 7d e7 89 7e e4 d5 b9 f0 +df 0b e3 e0 9e d4 de a8 c1 45 4f f3 42 3b b0 8e +17 93 24 5a 9d f8 bf 6a b3 96 8c 8e dd c3 b5 32 +85 71 c7 7f 09 1c c5 78 57 69 12 df eb d1 64 b9 +de 54 54 fe 0b e1 c1 f6 38 5b 32 83 60 ce 67 ec +7a 05 f6 e3 0e b4 5c 17 c4 8a c7 00 41 d2 ca b6 +7f 0a 2a e7 aa fd cc 8d 24 5e a3 44 2a 63 00 cc +c7 + +# -------------------------------- +# RSASSA-PSS Signature Example 8.5 +# -------------------------------- + +# Message to be signed: +04 dc 25 1b e7 2e 88 e5 72 34 85 b6 38 3a 63 7e +2f ef e0 76 60 c5 19 a5 60 b8 bc 18 bd ed b8 6e +ae 23 64 ea 53 ba 9d ca 6e b3 d2 e7 d6 b8 06 af +42 b3 e8 7f 29 1b 4a 88 81 d5 bf 57 2c c9 a8 5e +19 c8 6a cb 28 f0 98 f9 da 03 83 c5 66 d3 c0 f5 +8c fd 8f 39 5d cf 60 2e 5c d4 0e 8c 71 83 f7 14 +99 6e 22 97 ef + +# Salt: +c5 58 d7 16 7c bb 45 08 ad a0 42 97 1e 71 b1 37 +7e ea 42 69 + +# Signature: +33 34 1b a3 57 6a 13 0a 50 e2 a5 cf 86 79 22 43 +88 d5 69 3f 5a cc c2 35 ac 95 ad d6 8e 5e b1 ee +c3 16 66 d0 ca 7a 1c da 6f 70 a1 aa 76 2c 05 75 +2a 51 95 0c db 8a f3 c5 37 9f 18 cf e6 b5 bc 55 +a4 64 82 26 a1 5e 91 2e f1 9a d7 7a de ea 91 1d +67 cf ef d6 9b a4 3f a4 11 91 35 ff 64 21 17 ba +98 5a 7e 01 00 32 5e 95 19 f1 ca 6a 92 16 bd a0 +55 b5 78 50 15 29 11 25 e9 0d cd 07 a2 ca 96 73 +ee + +# -------------------------------- +# RSASSA-PSS Signature Example 8.6 +# -------------------------------- + +# Message to be signed: +0e a3 7d f9 a6 fe a4 a8 b6 10 37 3c 24 cf 39 0c +20 fa 6e 21 35 c4 00 c8 a3 4f 5c 18 3a 7e 8e a4 +c9 ae 09 0e d3 17 59 f4 2d c7 77 19 cc a4 00 ec +dc c5 17 ac fc 7a c6 90 26 75 b2 ef 30 c5 09 66 +5f 33 21 48 2f c6 9a 9f b5 70 d1 5e 01 c8 45 d0 +d8 e5 0d 2a 24 cb f1 cf 0e 71 49 75 a5 db 7b 18 +d9 e9 e9 cb 91 b5 cb 16 86 90 60 ed 18 b7 b5 62 +45 50 3f 0c af 90 35 2b 8d e8 1c b5 a1 d9 c6 33 +60 92 f0 cd + +# Salt: +76 fd 4e 64 fd c9 8e b9 27 a0 40 3e 35 a0 84 e7 +6b a9 f9 2a + +# Signature: +1e d1 d8 48 fb 1e db 44 12 9b d9 b3 54 79 5a f9 +7a 06 9a 7a 00 d0 15 10 48 59 3e 0c 72 c3 51 7f +f9 ff 2a 41 d0 cb 5a 0a c8 60 d7 36 a1 99 70 4f +7c b6 a5 39 86 a8 8b bd 8a bc c0 07 6a 2c e8 47 +88 00 31 52 5d 44 9d a2 ac 78 35 63 74 c5 36 e3 +43 fa a7 cb a4 2a 5a aa 65 06 08 77 91 c0 6a 8e +98 93 35 ae d1 9b fa b2 d5 e6 7e 27 fb 0c 28 75 +af 89 6c 21 b6 e8 e7 30 9d 04 e4 f6 72 7e 69 46 +3e + +# ============================================= + +# ================================== +# Example 9: A 1536-bit RSA Key Pair +# ================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +e6 bd 69 2a c9 66 45 79 04 03 fd d0 f5 be b8 b9 +bf 92 ed 10 00 7f c3 65 04 64 19 dd 06 c0 5c 5b +5b 2f 48 ec f9 89 e4 ce 26 91 09 97 9c bb 40 b4 +a0 ad 24 d2 24 83 d1 ee 31 5a d4 cc b1 53 42 68 +35 26 91 c5 24 f6 dd 8e 6c 29 d2 24 cf 24 69 73 +ae c8 6c 5b f6 b1 40 1a 85 0d 1b 9a d1 bb 8c bc +ec 47 b0 6f 0f 8c 7f 45 d3 fc 8f 31 92 99 c5 43 +3d db c2 b3 05 3b 47 de d2 ec d4 a4 ca ef d6 14 +83 3d c8 bb 62 2f 31 7e d0 76 b8 05 7f e8 de 3f +84 48 0a d5 e8 3e 4a 61 90 4a 4f 24 8f b3 97 02 +73 57 e1 d3 0e 46 31 39 81 5c 6f d4 fd 5a c5 b8 +17 2a 45 23 0e cb 63 18 a0 4f 14 55 d8 4e 5a 8b + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +6a 7f d8 4f b8 5f ad 07 3b 34 40 6d b7 4f 8d 61 +a6 ab c1 21 96 a9 61 dd 79 56 5e 9d a6 e5 18 7b +ce 2d 98 02 50 f7 35 95 75 35 92 70 d9 15 90 bb +0e 42 7c 71 46 0b 55 d5 14 10 b1 91 bc f3 09 fe +a1 31 a9 2c 8e 70 27 38 fa 71 9f 1e 00 41 f5 2e +40 e9 1f 22 9f 4d 96 a1 e6 f1 72 e1 55 96 b4 51 +0a 6d ae c2 61 05 f2 be bc 53 31 6b 87 bd f2 13 +11 66 60 70 e8 df ee 69 d5 2c 71 a9 76 ca ae 79 +c7 2b 68 d2 85 80 dc 68 6d 9f 51 29 d2 25 f8 2b +3d 61 55 13 a8 82 b3 db 91 41 6b 48 ce 08 88 82 +13 e3 7e eb 9a f8 00 d8 1c ab 32 8c e4 20 68 99 +03 c0 0c 7b 5f d3 1b 75 50 3a 6d 41 96 84 d6 29 + +# Prime p: +f8 eb 97 e9 8d f1 26 64 ee fd b7 61 59 6a 69 dd +cd 0e 76 da ec e6 ed 4b f5 a1 b5 0a c0 86 f7 92 +8a 4d 2f 87 26 a7 7e 51 5b 74 da 41 98 8f 22 0b +1c c8 7a a1 fc 81 0c e9 9a 82 f2 d1 ce 82 1e dc +ed 79 4c 69 41 f4 2c 7a 1a 0b 8c 4d 28 c7 5e c6 +0b 65 22 79 f6 15 4a 76 2a ed 16 5d 47 de e3 67 + +# Prime q: +ed 4d 71 d0 a6 e2 4b 93 c2 e5 f6 b4 bb e0 5f 5f +b0 af a0 42 d2 04 fe 33 78 d3 65 c2 f2 88 b6 a8 +da d7 ef e4 5d 15 3e ef 40 ca cc 7b 81 ff 93 40 +02 d1 08 99 4b 94 a5 e4 72 8c d9 c9 63 37 5a e4 +99 65 bd a5 5c bf 0e fe d8 d6 55 3b 40 27 f2 d8 +62 08 a6 e6 b4 89 c1 76 12 80 92 d6 29 e4 9d 3d + +# p's CRT exponent dP: +2b b6 8b dd fb 0c 4f 56 c8 55 8b ff af 89 2d 80 +43 03 78 41 e7 fa 81 cf a6 1a 38 c5 e3 9b 90 1c +8e e7 11 22 a5 da 22 27 bd 6c de eb 48 14 52 c1 +2a d3 d6 1d 5e 4f 77 6a 0a b5 56 59 1b ef e3 e5 +9e 5a 7f dd b8 34 5e 1f 2f 35 b9 f4 ce e5 7c 32 +41 4c 08 6a ec 99 3e 93 53 e4 80 d9 ee c6 28 9f + +# q's CRT exponent dQ: +4f f8 97 70 9f ad 07 97 46 49 45 78 e7 0f d8 54 +61 30 ee ab 56 27 c4 9b 08 0f 05 ee 4a d9 f3 e4 +b7 cb a9 d6 a5 df f1 13 a4 1c 34 09 33 68 33 f1 +90 81 6d 8a 6b c4 2e 9b ec 56 b7 56 7d 0f 3c 9c +69 6d b6 19 b2 45 d9 01 dd 85 6d b7 c8 09 2e 77 +e9 a1 cc cd 56 ee 4d ba 42 c5 fd b6 1a ec 26 69 + +# CRT coefficient qInv: +77 b9 d1 13 7b 50 40 4a 98 27 29 31 6e fa fc 7d +fe 66 d3 4e 5a 18 26 00 d5 f3 0a 0a 85 12 05 1c +56 0d 08 1d 4d 0a 18 35 ec 3d 25 a6 0f 4e 4d 6a +a9 48 b2 bf 3d bb 5b 12 4c bb c3 48 92 55 a3 a9 +48 37 2f 69 78 49 67 45 f9 43 e1 db 4f 18 38 2c +ea a5 05 df c6 57 57 bb 3f 85 7a 58 dc e5 21 56 + +# -------------------------------- +# RSASSA-PSS Signature Example 9.1 +# -------------------------------- + +# Message to be signed: +a8 8e 26 58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59 +1c d6 58 7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59 +22 02 8b c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa +70 ba 36 72 cd de 4c fe 49 70 cc 79 04 60 1b 27 +88 72 bf 51 32 1c 4a 97 2f 3c 95 57 0f 34 45 d4 +f5 79 80 e0 f2 0d f5 48 46 e6 a5 2c 66 8f 12 88 +c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe b3 2f +0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c f9 79 +f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 dd 76 +2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 ca 70 +9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 85 66 +ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 15 94 +20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 11 a2 +c7 50 f5 + +# Salt: +c0 a4 25 31 3d f8 d7 56 4b d2 43 4d 31 15 23 d5 +25 7e ed 80 + +# Signature: +58 61 07 22 6c 3c e0 13 a7 c8 f0 4d 1a 6a 29 59 +bb 4b 8e 20 5b a4 3a 27 b5 0f 12 41 11 bc 35 ef +58 9b 03 9f 59 32 18 7c b6 96 d7 d9 a3 2c 0c 38 +30 0a 5c dd a4 83 4b 62 d2 eb 24 0a f3 3f 79 d1 +3d fb f0 95 bf 59 9e 0d 96 86 94 8c 19 64 74 7b +67 e8 9c 9a ba 5c d8 50 16 23 6f 56 6c c5 80 2c +b1 3e ad 51 bc 7c a6 be f3 b9 4d cb db b1 d5 70 +46 97 71 df 0e 00 b1 a8 a0 67 77 47 2d 23 16 27 +9e da e8 64 74 66 8d 4e 1e ff f9 5f 1d e6 1c 60 +20 da 32 ae 92 bb f1 65 20 fe f3 cf 4d 88 f6 11 +21 f2 4b bd 9f e9 1b 59 ca f1 23 5b 2a 93 ff 81 +fc 40 3a dd f4 eb de a8 49 34 a9 cd af 8e 1a 9e + +# -------------------------------- +# RSASSA-PSS Signature Example 9.2 +# -------------------------------- + +# Message to be signed: +c8 c9 c6 af 04 ac da 41 4d 22 7e f2 3e 08 20 c3 +73 2c 50 0d c8 72 75 e9 5b 0d 09 54 13 99 3c 26 +58 bc 1d 98 85 81 ba 87 9c 2d 20 1f 14 cb 88 ce +d1 53 a0 19 69 a7 bf 0a 7b e7 9c 84 c1 48 6b c1 +2b 3f a6 c5 98 71 b6 82 7c 8c e2 53 ca 5f ef a8 +a8 c6 90 bf 32 6e 8e 37 cd b9 6d 90 a8 2e ba b6 +9f 86 35 0e 18 22 e8 bd 53 6a 2e + +# Salt: +b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 ef +8c 5c 0e 91 + +# Signature: +80 b6 d6 43 25 52 09 f0 a4 56 76 38 97 ac 9e d2 +59 d4 59 b4 9c 28 87 e5 88 2e cb 44 34 cf d6 6d +d7 e1 69 93 75 38 1e 51 cd 7f 55 4f 2c 27 17 04 +b3 99 d4 2b 4b e2 54 0a 0e ca 61 95 1f 55 26 7f +7c 28 78 c1 22 84 2d ad b2 8b 01 bd 5f 8c 02 5f +7e 22 84 18 a6 73 c0 3d 6b c0 c7 36 d0 a2 95 46 +bd 67 f7 86 d9 d6 92 cc ea 77 8d 71 d9 8c 20 63 +b7 a7 10 92 18 7a 4d 35 af 10 81 11 d8 3e 83 ea +e4 6c 46 aa 34 27 7e 06 04 45 89 90 37 88 f1 d5 +e7 ce e2 5f b4 85 e9 29 49 11 88 14 d6 f2 c3 ee +36 14 89 01 6f 32 7f b5 bc 51 7e b5 04 70 bf fa +1a fa 5f 4c e9 aa 0c e5 b8 ee 19 bf 55 01 b9 58 + +# -------------------------------- +# RSASSA-PSS Signature Example 9.3 +# -------------------------------- + +# Message to be signed: +0a fa d4 2c cd 4f c6 06 54 a5 50 02 d2 28 f5 2a +4a 5f e0 3b 8b bb 08 ca 82 da ca 55 8b 44 db e1 +26 6e 50 c0 e7 45 a3 6d 9d 29 04 e3 40 8a bc d1 +fd 56 99 94 06 3f 4a 75 cc 72 f2 fe e2 a0 cd 89 +3a 43 af 1c 5b 8b 48 7d f0 a7 16 10 02 4e 4f 6d +df 9f 28 ad 08 13 c1 aa b9 1b cb 3c 90 64 d5 ff +74 2d ef fe a6 57 09 41 39 36 9e 5e a6 f4 a9 63 +19 a5 cc 82 24 14 5b 54 50 62 75 8f ef d1 fe 34 +09 ae 16 92 59 c6 cd fd 6b 5f 29 58 e3 14 fa ec +be 69 d2 ca ce 58 ee 55 17 9a b9 b3 e6 d1 ec c1 +4a 55 7c 5f eb e9 88 59 52 64 fc 5d a1 c5 71 46 +2e ca 79 8a 18 a1 a4 94 0c da b4 a3 e9 20 09 cc +d4 2e 1e 94 7b 13 14 e3 22 38 a2 de ce 7d 23 a8 +9b 5b 30 c7 51 fd 0a 4a 43 0d 2c 54 85 94 + +# Salt: +9a 2b 00 7e 80 97 8b bb 19 2c 35 4e b7 da 9a ed +fc 74 db f5 + +# Signature: +48 44 08 f3 89 8c d5 f5 34 83 f8 08 19 ef bf 27 +08 c3 4d 27 a8 b2 a6 fa e8 b3 22 f9 24 02 37 f9 +81 81 7a ca 18 46 f1 08 4d aa 6d 7c 07 95 f6 e5 +bf 1a f5 9c 38 e1 85 84 37 ce 1f 7e c4 19 b9 8c +87 36 ad f6 dd 9a 00 b1 80 6d 2b d3 ad 0a 73 77 +5e 05 f5 2d fe f3 a5 9a b4 b0 81 43 f0 df 05 cd +1a d9 d0 4b ec ec a6 da a4 a2 12 98 03 e2 00 cb +c7 77 87 ca f4 c1 d0 66 3a 6c 59 87 b6 05 95 20 +19 78 2c af 2e c1 42 6d 68 fb 94 ed 1d 4b e8 16 +a7 ed 08 1b 77 e6 ab 33 0b 3f fc 07 38 20 fe cd +e3 72 7f cb e2 95 ee 61 a0 50 a3 43 65 86 37 c3 +fd 65 9c fb 63 73 6d e3 2d 9f 90 d3 c2 f6 3e ca + +# -------------------------------- +# RSASSA-PSS Signature Example 9.4 +# -------------------------------- + +# Message to be signed: +1d fd 43 b4 6c 93 db 82 62 9b da e2 bd 0a 12 b8 +82 ea 04 c3 b4 65 f5 cf 93 02 3f 01 05 96 26 db +be 99 f2 6b b1 be 94 9d dd d1 6d c7 f3 de bb 19 +a1 94 62 7f 0b 22 44 34 df 7d 87 00 e9 e9 8b 06 +e3 60 c1 2f db e3 d1 9f 51 c9 68 4e b9 08 9e cb +b0 a2 f0 45 03 99 d3 f5 9e ac 72 94 08 5d 04 4f +53 93 c6 ce 73 74 23 d8 b8 6c 41 53 70 d3 89 e3 +0b 9f 0a 3c 02 d2 5d 00 82 e8 ad 6f 3f 1e f2 4a +45 c3 cf 82 b3 83 36 70 63 a4 d4 61 3e 42 64 f0 +1b 2d ac 2e 5a a4 20 43 f8 fb 5f 69 fa 87 1d 14 +fb 27 3e 76 7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0 +c7 e0 f6 be 25 61 92 3a 77 21 1d 66 a6 e2 db b4 +3c 36 63 50 be ae 22 da 3a c2 c1 f5 07 70 96 fc +b5 c4 bf 25 5f 75 74 35 1a e0 b1 e1 f0 36 32 81 +7c 08 56 d4 a8 ba 97 af bd c8 b8 58 55 40 2b c5 +69 26 fc ec 20 9f 9e a8 + +# Salt: +70 f3 82 bd df 4d 5d 2d d8 8b 3b c7 b7 30 8b e6 +32 b8 40 45 + +# Signature: +84 eb eb 48 1b e5 98 45 b4 64 68 ba fb 47 1c 01 +12 e0 2b 23 5d 84 b5 d9 11 cb d1 92 6e e5 07 4a +e0 42 44 95 cb 20 e8 23 08 b8 eb b6 5f 41 9a 03 +fb 40 e7 2b 78 98 1d 88 aa d1 43 05 36 85 17 2c +97 b2 9c 8b 7b f0 ae 73 b5 b2 26 3c 40 3d a0 ed +2f 80 ff 74 50 af 78 28 eb 8b 86 f0 02 8b d2 a8 +b1 76 a4 d2 28 cc ce a1 83 94 f2 38 b0 9f f7 58 +cc 00 bc 04 30 11 52 35 57 42 f2 82 b5 4e 66 3a +91 9e 70 9d 8d a2 4a de 55 00 a7 b9 aa 50 22 6e +0c a5 29 23 e6 c2 d8 60 ec 50 ff 48 0f a5 74 77 +e8 2b 05 65 f4 37 9f 79 c7 72 d5 c2 da 80 af 9f +bf 32 5e ce 6f c2 0b 00 96 16 14 be e8 9a 18 3e + +# -------------------------------- +# RSASSA-PSS Signature Example 9.5 +# -------------------------------- + +# Message to be signed: +1b dc 6e 7c 98 fb 8c f5 4e 9b 09 7b 66 a8 31 e9 +cf e5 2d 9d 48 88 44 8e e4 b0 97 80 93 ba 1d 7d +73 ae 78 b3 a6 2b a4 ad 95 cd 28 9c cb 9e 00 52 +26 bb 3d 17 8b cc aa 82 1f b0 44 a4 e2 1e e9 76 +96 c1 4d 06 78 c9 4c 2d ae 93 b0 ad 73 92 22 18 +55 3d aa 7e 44 eb e5 77 25 a7 a4 5c c7 2b 9b 21 +38 a6 b1 7c 8d b4 11 ce 82 79 ee 12 41 af f0 a8 +be c6 f7 7f 87 ed b0 c6 9c b2 72 36 e3 43 5a 80 +0b 19 2e 4f 11 e5 19 e3 fe 30 fc 30 ea cc ca 4f +bb 41 76 90 29 bf 70 8e 81 7a 9e 68 38 05 be 67 +fa 10 09 84 68 3b 74 83 8e 3b cf fa 79 36 6e ed +1d 48 1c 76 72 91 18 83 8f 31 ba 8a 04 8a 93 c1 +be 44 24 59 8e 8d f6 32 8b 7a 77 88 0a 3f 9c 7e +2e 8d fc a8 eb 5a 26 fb 86 bd c5 56 d4 2b be 01 +d9 fa 6e d8 06 46 49 1c 93 41 + +# Salt: +d6 89 25 7a 86 ef fa 68 21 2c 5e 0c 61 9e ca 29 +5f b9 1b 67 + +# Signature: +82 10 2d f8 cb 91 e7 17 99 19 a0 4d 26 d3 35 d6 +4f bc 2f 87 2c 44 83 39 43 24 1d e8 45 48 10 27 +4c df 3d b5 f4 2d 42 3d b1 52 af 71 35 f7 01 42 +0e 39 b4 94 a6 7c bf d1 9f 91 19 da 23 3a 23 da +5c 64 39 b5 ba 0d 2b c3 73 ee e3 50 70 01 37 8d +4a 40 73 85 6b 7f e2 ab a0 b5 ee 93 b2 7f 4a fe +c7 d4 d1 20 92 1c 83 f6 06 76 5b 02 c1 9e 4d 6a +1a 3b 95 fa 4c 42 29 51 be 4f 52 13 10 77 ef 17 +17 97 29 cd df bd b5 69 50 db ac ee fe 78 cb 16 +64 0a 09 9e a5 6d 24 38 9e ef 10 f8 fe cb 31 ba +3e a3 b2 27 c0 a8 66 98 bb 89 e3 e9 36 39 05 bf +22 77 7b 2a 3a a5 21 b6 5b 4c ef 76 d8 3b de 4c + +# -------------------------------- +# RSASSA-PSS Signature Example 9.6 +# -------------------------------- + +# Message to be signed: +88 c7 a9 f1 36 04 01 d9 0e 53 b1 01 b6 1c 53 25 +c3 c7 5d b1 b4 11 fb eb 8e 83 0b 75 e9 6b 56 67 +0a d2 45 40 4e 16 79 35 44 ee 35 4b c6 13 a9 0c +c9 84 87 15 a7 3d b5 89 3e 7f 6d 27 98 15 c0 c1 +de 83 ef 8e 29 56 e3 a5 6e d2 6a 88 8d 7a 9c dc +d0 42 f4 b1 6b 7f a5 1e f1 a0 57 36 62 d1 6a 30 +2d 0e c5 b2 85 d2 e0 3a d9 65 29 c8 7b 3d 37 4d +b3 72 d9 5b 24 43 d0 61 b6 b1 a3 50 ba 87 80 7e +d0 83 af d1 eb 05 c3 f5 2f 4e ba 5e d2 22 77 14 +fd b5 0b 9d 9d 9d d6 81 4f 62 f6 27 2f cd 5c db +ce 7a 9e f7 97 + +# Salt: +c2 5f 13 bf 67 d0 81 67 1a 04 81 a1 f1 82 0d 61 +3b ba 22 76 + +# Signature: +a7 fd b0 d2 59 16 5c a2 c8 8d 00 bb f1 02 8a 86 +7d 33 76 99 d0 61 19 3b 17 a9 64 8e 14 cc bb aa +de ac aa cd ec 81 5e 75 71 29 4e bb 8a 11 7a f2 +05 fa 07 8b 47 b0 71 2c 19 9e 3a d0 51 35 c5 04 +c2 4b 81 70 51 15 74 08 02 48 79 92 ff d5 11 d4 +af c6 b8 54 49 1e b3 f0 dd 52 31 39 54 2f f1 5c +31 01 ee 85 54 35 17 c6 a3 c7 94 17 c6 7e 2d d9 +aa 74 1e 9a 29 b0 6d cb 59 3c 23 36 b3 67 0a e3 +af ba c7 c3 e7 6e 21 54 73 e8 66 e3 38 ca 24 4d +e0 0b 62 62 4d 6b 94 26 82 2c ea e9 f8 cc 46 08 +95 f4 12 50 07 3f d4 5c 5a 1e 7b 42 5c 20 4a 42 +3a 69 91 59 f6 90 3e 71 0b 37 a7 bb 2b c8 04 9f + +# ============================================= + +# =================================== +# Example 10: A 2048-bit RSA Key Pair +# =================================== + +# ------------------------------ +# Components of the RSA Key Pair +# ------------------------------ + +# RSA modulus n: +a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70 +ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5 +7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18 +75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad +cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12 +cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae +4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e +90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a +21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37 +39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea +45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73 +3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07 +0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17 +b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00 +1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82 +ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 + +# RSA public exponent e: +01 00 01 + +# RSA private exponent d: +2d 2f f5 67 b3 fe 74 e0 61 91 b7 fd ed 6d e1 12 +29 0c 67 06 92 43 0d 59 69 18 40 47 da 23 4c 96 +93 de ed 16 73 ed 42 95 39 c9 69 d3 72 c0 4d 6b +47 e0 f5 b8 ce e0 84 3e 5c 22 83 5d bd 3b 05 a0 +99 79 84 ae 60 58 b1 1b c4 90 7c bf 67 ed 84 fa +9a e2 52 df b0 d0 cd 49 e6 18 e3 5d fd fe 59 bc +a3 dd d6 6c 33 ce bb c7 7a d4 41 aa 69 5e 13 e3 +24 b5 18 f0 1c 60 f5 a8 5c 99 4a d1 79 f2 a6 b5 +fb e9 34 02 b1 17 67 be 01 bf 07 34 44 d6 ba 1d +d2 bc a5 bd 07 4d 4a 5f ae 35 31 ad 13 03 d8 4b +30 d8 97 31 8c bb ba 04 e0 3c 2e 66 de 6d 91 f8 +2f 96 ea 1d 4b b5 4a 5a ae 10 2d 59 46 57 f5 c9 +78 95 53 51 2b 29 6d ea 29 d8 02 31 96 35 7e 3e +3a 6e 95 8f 39 e3 c2 34 40 38 ea 60 4b 31 ed c6 +f0 f7 ff 6e 71 81 a5 7c 92 82 6a 26 8f 86 76 8e +96 f8 78 56 2f c7 1d 85 d6 9e 44 86 12 f7 04 8f + +# Prime p: +cf d5 02 83 fe ee b9 7f 6f 08 d7 3c bc 7b 38 36 +f8 2b bc d4 99 47 9f 5e 6f 76 fd fc b8 b3 8c 4f +71 dc 9e 88 bd 6a 6f 76 37 1a fd 65 d2 af 18 62 +b3 2a fb 34 a9 5f 71 b8 b1 32 04 3f fe be 3a 95 +2b af 75 92 44 81 48 c0 3f 9c 69 b1 d6 8e 4c e5 +cf 32 c8 6b af 46 fe d3 01 ca 1a b4 03 06 9b 32 +f4 56 b9 1f 71 89 8a b0 81 cd 8c 42 52 ef 52 71 +91 5c 97 94 b8 f2 95 85 1d a7 51 0f 99 cb 73 eb + +# Prime q: +cc 4e 90 d2 a1 b3 a0 65 d3 b2 d1 f5 a8 fc e3 1b +54 44 75 66 4e ab 56 1d 29 71 b9 9f b7 be f8 44 +e8 ec 1f 36 0b 8c 2a c8 35 96 92 97 1e a6 a3 8f +72 3f cc 21 1f 5d bc b1 77 a0 fd ac 51 64 a1 d4 +ff 7f bb 4e 82 99 86 35 3c b9 83 65 9a 14 8c dd +42 0c 7d 31 ba 38 22 ea 90 a3 2b e4 6c 03 0e 8c +17 e1 fa 0a d3 78 59 e0 6b 0a a6 fa 3b 21 6d 9c +be 6c 0e 22 33 97 69 c0 a6 15 91 3e 5d a7 19 cf + +# p's CRT exponent dP: +1c 2d 1f c3 2f 6b c4 00 4f d8 5d fd e0 fb bf 9a +4c 38 f9 c7 c4 e4 1d ea 1a a8 82 34 a2 01 cd 92 +f3 b7 da 52 65 83 a9 8a d8 5b b3 60 fb 98 3b 71 +1e 23 44 9d 56 1d 17 78 d7 a5 15 48 6b cb f4 7b +46 c9 e9 e1 a3 a1 f7 70 00 ef be b0 9a 8a fe 47 +e5 b8 57 cd a9 9c b1 6d 7f ff 9b 71 2e 3b d6 0c +a9 6d 9c 79 73 d6 16 d4 69 34 a9 c0 50 28 1c 00 +43 99 ce ff 1d b7 dd a7 87 66 a8 a9 b9 cb 08 73 + +# q's CRT exponent dQ: +cb 3b 3c 04 ca a5 8c 60 be 7d 9b 2d eb b3 e3 96 +43 f4 f5 73 97 be 08 23 6a 1e 9e af aa 70 65 36 +e7 1c 3a cf e0 1c c6 51 f2 3c 9e 05 85 8f ee 13 +bb 6a 8a fc 47 df 4e dc 9a 4b a3 0b ce cb 73 d0 +15 78 52 32 7e e7 89 01 5c 2e 8d ee 7b 9f 05 a0 +f3 1a c9 4e b6 17 31 64 74 0c 5c 95 14 7c d5 f3 +b5 ae 2c b4 a8 37 87 f0 1d 8a b3 1f 27 c2 d0 ee +a2 dd 8a 11 ab 90 6a ba 20 7c 43 c6 ee 12 53 31 + +# CRT coefficient qInv: +12 f6 b2 cf 13 74 a7 36 fa d0 56 16 05 0f 96 ab +4b 61 d1 17 7c 7f 9d 52 5a 29 f3 d1 80 e7 76 67 +e9 9d 99 ab f0 52 5d 07 58 66 0f 37 52 65 5b 0f +25 b8 df 84 31 d9 a8 ff 77 c1 6c 12 a0 a5 12 2a +9f 0b f7 cf d5 a2 66 a3 5c 15 9f 99 12 08 b9 03 +16 ff 44 4f 3e 0b 6b d0 e9 3b 8a 7a 24 48 e9 57 +e3 dd a6 cf cf 22 66 b1 06 01 3a c4 68 08 d3 b3 +88 7b 3b 00 34 4b aa c9 53 0b 4c e7 08 fc 32 b6 + +# --------------------------------- +# RSASSA-PSS Signature Example 10.1 +# --------------------------------- + +# Message to be signed: +88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c +6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 + +# Salt: +04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab +fc ec de 89 + +# Signature: +82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54 +06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5 +af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14 +8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2 +1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7 +9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74 +1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a +77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f +d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16 +59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e +57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb +3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00 +0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8 +e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04 +38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1 +b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 + +# --------------------------------- +# RSASSA-PSS Signature Example 10.2 +# --------------------------------- + +# Message to be signed: +dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c +52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13 +97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b +34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db +d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3 +c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75 +ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e +80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac + +# Salt: +8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb +57 f9 b7 1b + +# Signature: +14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c +d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30 +53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10 +11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28 +92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a +5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca +ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec +d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63 +7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22 +21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15 +99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68 +25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42 +31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab +c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd +26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26 +d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 + +# --------------------------------- +# RSASSA-PSS Signature Example 10.3 +# --------------------------------- + +# Message to be signed: +48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b +08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01 +93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6 +26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71 +ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d +e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1 +3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db + +# Salt: +4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6 +e2 0c 2d 73 + +# Signature: +6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb +39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5 +4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d +3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01 +02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a +a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5 +d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa +91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66 +f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78 +34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b +44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de +03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53 +1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19 +6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24 +71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5 +0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb + +# --------------------------------- +# RSASSA-PSS Signature Example 10.4 +# --------------------------------- + +# Message to be signed: +0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75 +5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4 +e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82 +db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a +62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45 +1a + +# Salt: +c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0 +1c b5 41 ec + +# Signature: +34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61 +a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd +ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93 +2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc +f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0 +2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34 +b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6 +6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce +c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45 +0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d +02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec +b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f +01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9 +2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d +de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6 +c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb + +# --------------------------------- +# RSASSA-PSS Signature Example 10.5 +# --------------------------------- + +# Message to be signed: +f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f +06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97 +6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98 +01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b +b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9 +16 + +# Salt: +ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52 +65 5f 5d fb + +# Signature: +7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c +55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3 +46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de +42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1 +f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38 +77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b +3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b +b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72 +1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05 +e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed +b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5 +a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9 +21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11 +26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24 +86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a +cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc + +# --------------------------------- +# RSASSA-PSS Signature Example 10.6 +# --------------------------------- + +# Message to be signed: +25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1 +f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5 +55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91 +dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52 +c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03 +23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0 +74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7 +d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37 +8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e +aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef +b8 af d7 + +# Salt: +ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c +a2 d1 df 28 + +# Signature: +6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21 +80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9 +b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12 +5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7 +b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91 +55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c +43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46 +bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81 +8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96 +d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e +f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18 +e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08 +8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed +94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59 +e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73 +2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f + +# ============================================= diff --git a/deps/libtomcrypt/notes/rsa-testvectors/readme.txt b/deps/libtomcrypt/notes/rsa-testvectors/readme.txt new file mode 100644 index 0000000..69717ed --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/readme.txt @@ -0,0 +1,22 @@ +==================== +pkcs-1v2-1-vec.zip +==================== + +This directory contains test vectors for RSAES-OAEP and +RSASSA-PSS as defined in PKCS #1 v2.1. + +The files: + +readme.txt This file. + +oaep-vect.txt Test vectors for RSAES-OAEP encryption. + +oaep-int.txt Intermediate values for RSAES-OAEP + encryption and RSA decryption with CRT. + Also, DER-encoded RSAPrivateKey and + RSAPublicKey types. + +pss-vect.txt Test vectors for RSASSA-PSS signing. + +pss-int.txt Intermediate values for RSASSA-PSS + signing. diff --git a/deps/libtomcrypt/notes/rsa-testvectors/rt.py b/deps/libtomcrypt/notes/rsa-testvectors/rt.py new file mode 100644 index 0000000..3f6ab7f --- /dev/null +++ b/deps/libtomcrypt/notes/rsa-testvectors/rt.py @@ -0,0 +1,253 @@ +#!/usr/bin/env python + +import sys +import os +import hashlib + +def md5_for_file(path, block_size=256*128): + ''' + Block size directly depends on the block size of your filesystem + to avoid performances issues + Here I have blocks of 4096 octets (Default NTFS) + ''' + md5 = hashlib.md5() + with open(path,'rb') as f: + for chunk in iter(lambda: f.read(block_size), b''): + md5.update(chunk) + f.close() + return md5.hexdigest() + +def read_until_ends(f, s): + while True: + l = f.readline() + if l.strip().endswith(s): + break + return l + +def read_until_start(f, s): + while True: + l = f.readline() + if l.startswith(s): + break + return l + +def read_hex(f): + t = [] + while True: + l = f.readline() + if l.strip() == '': + break + t.extend(l.strip().split(' ')) + return t + +class NamedData(object): + def __init__(self, name, data): + self.name = name + self.data = data + + def __str__(self): + return " /* {0} */\n {1},\n {{ {2} }}\n".format(self.name, len(self.data), ', '.join('0x' + x for x in self.data)) + +def read_part(f, s): + name = read_until_start(f, s).strip().lstrip('# ').rstrip(':') + data = read_hex(f) + e = NamedData(name, data) + return e + +class RsaKey(object): + def __init__(self, n, e, d, p, q, dP, dQ, qInv): + self.n = n + self.e = e + self.d = d + self.p = p + self.q = q + self.dP = dP + self.dQ = dQ + self.qInv = qInv + + def __str__(self): + return "{{\n{0},\n{1},\n{2},\n{3},\n{4},\n{5},\n{6},\n{7}\n}}\n".format(self.n, self.e, self.d, self.p, self.q, self.dP, self.dQ, self.qInv) + +def read_key(f): + if ftype.version == 1: + read_until_start(f, '# Private key') + n = read_part(f, ftype.n) + e = read_part(f, ftype.e) + d = read_part(f, ftype.d) + p = read_part(f, ftype.p) + q = read_part(f, ftype.q) + dP = read_part(f, ftype.dP) + dQ = read_part(f, ftype.dQ) + qInv = read_part(f, ftype.qInv) + k = RsaKey(n, e, d, p, q, dP, dQ, qInv) + return k + +class Data(object): + def __init__(self, name, obj1, obj2, obj3): + self.name = name + self.obj1 = obj1 + self.obj2 = obj2 + self.obj3 = obj3 + + def __str__(self): + if self.obj3 == None: + return "{{\n \"{0}\",\n{1},\n{2}\n}}\n,".format(self.name, self.obj1, self.obj2) + else: + return "{{\n \"{0}\",\n{1},\n{2},\n{3}\n}}\n,".format(self.name, self.obj1, self.obj2, self.obj3) + +def read_data(f): + name = read_until_start(f, ftype.o).strip().lstrip('# ') + obj1 = read_part(f, ftype.o1) + obj2 = read_part(f, ftype.o2) + if ftype.name == 'emsa': + obj3 = None + else: + obj3 = read_part(f, ftype.o3) + s = Data(name, obj1, obj2, obj3) + return s + +class Example(object): + def __init__(self, name, key, data): + self.name = name + self.key = key + self.data = data + + def __str__(self): + res = "{{\n \"{0}\",\n{1},\n{{".format(self.name, str(self.key)) + for idx, d in enumerate(self.data, 1): + if idx == 2: + res += '#ifdef LTC_TEST_EXT\n' + res += str(d) + '\n' + if idx == ftype.numcases: + res += '#endif /* LTC_TEST_EXT */\n' + res += '}\n},' + return res + +def read_example(f): + name = read_until_start(f, '# Example').strip().lstrip('# ') + key = read_key(f) + l = read_until_start(f, ftype.sod) + d = [] + while l.strip().startswith(ftype.sod): + if ftype.version == 1: + f.seek(-len(l), os.SEEK_CUR) + data = read_data(f) + d.append(data) + l = read_until_start(f, '#') + + e = Example(name, key, d) + f.seek(-len(l), os.SEEK_CUR) + return e + + +class PkcsType(object): + def __init__(self, name): + if name == 'pss': + self.o = '# RSASSA-PSS Signature Example' + self.o1 = '# Message to be signed' + self.o2 = '# Salt' + self.o3 = '# Signature' + elif name == 'oaep': + self.o = '# RSAES-OAEP Encryption Example' + self.o1 = '# Message to be encrypted' + self.o2 = '# Seed' + self.o3 = '# Encryption' + elif name == 'emsa': + self.o = '# PKCS#1 v1.5 Signature Example' + self.o1 = '# Message to be signed' + self.o2 = '# Signature' + elif name == 'eme': + self.o = '# PKCS#1 v1.5 Encryption Example' + self.o1 = '# Message' + self.o2 = '# Seed' + self.o3 = '# Encryption' + else: + raise ValueError('Type unknown: ' + name) + + if name == 'pss' or name == 'oaep': + self.version = 2 + self.numcases = 6 + self.n = '# RSA modulus n' + self.e = '# RSA public exponent e' + self.d = '# RSA private exponent d' + self.p = '# Prime p' + self.q = '# Prime q' + self.dP = '# p\'s CRT exponent dP' + self.dQ = '# q\'s CRT exponent dQ' + self.qInv = '# CRT coefficient qInv' + self.sod = '# --------------------------------' + elif name == 'emsa' or name == 'eme': + self.version = 1 + self.numcases = 20 + self.n = '# Modulus' + self.e = '# Public exponent' + self.d = '# Exponent' + self.p = '# Prime 1' + self.q = '# Prime 2' + self.dP = '# Prime exponent 1' + self.dQ = '# Prime exponent 2' + self.qInv = '# Coefficient' + self.sod = self.o + self.name = name + +ftype = PkcsType(sys.argv[2]) + +print('/* Generated from file: %s\n * with md5 hash: %s\n */\n' % (sys.argv[1], md5_for_file(sys.argv[1]))) +print(''' +typedef struct rsaKey { + int n_l; + unsigned char n[256]; + int e_l; + unsigned char e[256]; + int d_l; + unsigned char d[256]; + int p_l; + unsigned char p[256]; + int q_l; + unsigned char q[256]; + int dP_l; + unsigned char dP[256]; + int dQ_l; + unsigned char dQ[256]; + int qInv_l; + unsigned char qInv[256]; +} rsaKey_t; + +typedef struct rsaData { + const char* name; + int o1_l; + unsigned char o1[256]; + int o2_l; + unsigned char o2[256];''') + +if ftype.name != 'emsa': + print(''' int o3_l; + unsigned char o3[256];''') + +print('''} rsaData_t; + +typedef struct testcase { + const char* name; + rsaKey_t rsa; +#ifdef LTC_TEST_EXT + rsaData_t data[%d]; +#else + rsaData_t data[1]; +#endif /* LTC_TEST_EXT */ +} testcase_t; + +testcase_t testcases_%s[] = + {''' % (ftype.numcases, sys.argv[2])) + +with open(sys.argv[1], 'rb') as f: + ex = [] + while read_until_ends(f, '============================================='): + if f.tell() == os.path.getsize(sys.argv[1]): + break + e = read_example(f) + ex.append(e) + + for i in ex: + print(i) +f.close() +print('};\n') diff --git a/deps/libtomcrypt/notes/tech0001.txt b/deps/libtomcrypt/notes/tech0001.txt new file mode 100644 index 0000000..daf7e57 --- /dev/null +++ b/deps/libtomcrypt/notes/tech0001.txt @@ -0,0 +1,73 @@ +Tech Note 0001 +How to Gather Entropy on Embedded Systems +Tom St Denis + +Introduction +------------ + +This tech note explains a relatively simple way to gather entropy for a PRNG (Yarrow in this case) in embedded systems +where there are few sources of entropy or physical sources. + +When trying to setup a secure random number generator a fresh source of random data (entropy) is required to ensure the +deterministic state of the PRNG is not known or predetermined with respect to an attacker. + +At the very least the system requires one timer and one source of un-timed interrupts. by "un-timed" I mean interrupts +that do not occur at regular intervals [e.g. joypad/keypad input, network packets, etc...]. + +First we shall begin by taking an overview of how the Yarrow PRNG works within libtomcrypt. At the heart of all +PRNGs is the "prng_state" data type. This is a union of structures that hold the PRNG state for the various prngs. The +first thing we require is a state... + + prng_state myPrng; + +Next we must initialize the state once to get the ball rolling + + if (yarrow_start(&myPrng) != CRYPT_OK) { + // error should never happen! + } + +At this point the PRNG is ready to accept fresh entropy which is added with + + int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng) + +This function is **NOT** thread safe which will come under consideration later. To add entropy to our PRNG we must +call this function with fresh data as its sampled. Lets say we have a timer counter called "uTimer" which is a 32-bit +long and say a 32-bit joyPad state called "uPad". An example interrupt handler would look like + + void joypad_interrupt(...) { + unsigned char buf[8]; + + STORE32L(uTimer, buf); + STORE32L(uPad, buf+4) + if (yarrow_add_entropy(buf, 8, &myPrng) != CRYPT_OK) { + // this should never occur either unless you didn't call yarrow_start + } + + // handle interrupt + } + +In this snippet the timer count and state of the joypad are added together into the entropy pool. The timer is important +because with respect to the joypad it is a good source of entropy (on its own its not). For example, the probability of +the user pushing the up arrow is fairly high, but at a specific time is not. + +This method doesn't gather alot of entropy and has to be used to for quite a while. One way to speed it up is to tap +multiple sources. If you have a network adapter and other sources of events (keyboard, mouse, etc...) trapping their +data is ideal as well. Its important to gather the timer along with the event data. + +As mentioned the "yarrow_add_entropy()" function is not thread safe. If your system allows interrupt handlers to be +interrupted themselves then you could have trouble. One simple way is to detect when an interrupt is in progress and +simply not add entropy during the call (jump over the yarrow_add_entropy() call) + +Once you feel that there has been enough entropy added to the pool then within a single thread you can call + + int yarrow_ready(prng_state *prng) + +Now the PRNG is ready to read via the + + unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng) + +It is a very good idea that once you call the yarrow_ready() function that you stop harvesting entropy in your interrupt +functions. This will free up alot of CPU time. Also one more final note. The yarrow_read() function is not thread +safe either. This means if you have multiple threads or processes that read from it you will have to add your own semaphores +around calls to it. + diff --git a/deps/libtomcrypt/notes/tech0002.txt b/deps/libtomcrypt/notes/tech0002.txt new file mode 100644 index 0000000..b9990e0 --- /dev/null +++ b/deps/libtomcrypt/notes/tech0002.txt @@ -0,0 +1,52 @@ +Tech Note 0002 +How to avoid non-intrusive timing attacks with online computations +Tom St Denis + +Introduction +------------ + +A timing attack is when an attacker can observe a side channel of the device (in this case time). In this tech note +we consider only non-intrusive timing attacks with respect to online computations. That is an attacker can +determine when a computation (such as a public key encryption) begins and ends but cannot observe the device +directly. This is specifically important for applications which transmit data via a public network. + +Consider a Diffie-Hellman encryption which requires the sender to make up a public key "y = g^x mod p". Libtomcrypt +uses the MPI bignum library to perform the operation. The time it takes to compute y is controlled by the number +of 1 bits in the exponent 'x'. To a large extent there will be the same number of squaring operations. "1" bits in +the exponent require the sender to perform a multiplication. This means to a certain extent an attacker can +determine not only the magnitude of 'x' but the number of one bits. With this information the attacker cannot directly +learn the key used. However, good cryptography mandates the close scrutiny of any practical side channel. + +Similar logic applies to the other various routines. Fortunately for this case there is a simple solution. First, +determine the maximum time the particular operation can require. For instance, on an Athlon 1.53Ghz XP processor a +DH-768 encryption requires roughly 50 milliseconds. Take that time and round it up. Now place a delay after the call. + +For example, + +void demo(void) { + clock_t t1; + + // get initial clock + t1 = clock(); + + // some PK function + + // now delay + while (clock() < (t1 + 100)); + + // transmit data... + +} + +This code has the effect of taking at least 100 ms always. In effect someone analyzing the traffic will see that the +operations always take a fixed amount of time. Since no two platforms are the same this type of fix has not been +incorporated into libtomcrypt (nor is it desired for many platforms). This requires on the developers part to profile +the code to determine the delays required. + +Note that this "quick" fix has no effect against an intrusive attacker. For example, power consumption will drop +significantly in the loop after the operation. However, this type of fix is more important to secure the user of the +application/device. For example, a user placing an order online won't try to cheat themselves by cracking open their +device and performing side-channel cryptanalysis. An attacker over a network might try to use the timing information +against the user. + + diff --git a/deps/libtomcrypt/notes/tech0003.txt b/deps/libtomcrypt/notes/tech0003.txt new file mode 100644 index 0000000..471378a --- /dev/null +++ b/deps/libtomcrypt/notes/tech0003.txt @@ -0,0 +1,52 @@ +Tech Note 0003 +Minimizing Memory Usage +Tom St Denis + +Introduction +------------ + +For the most part the library can get by with around 20KB of stack and about 32KB of heap even if you use the +public key functions. If all you plan on using are the hashes and ciphers than only about 1KB of stack is required +and no heap. + +To save space all of the symmetric key scheduled keys are stored in a union called "symmetric_key". This means the +size of a symmetric_key is the size of the largest scheduled key. By removing the ciphers you don't use from +the build you can minimize the size of this structure. For instance, by removing both Twofish and Blowfish the +size reduces to 768 bytes from the 4,256 bytes it would have been (on a 32-bit platform). Or if you remove +Blowfish and use Twofish with TWOFISH_SMALL defined its still 768 bytes. Even at its largest the structure is only +4KB which is normally not a problem for any platform. + + +Cipher Name | Size of scheduled key (bytes) | +------------+-------------------------------| +Twofish | 4,256 | +Blowfish | 4,168 | +3DES | 768 | +SAFER+ | 532 | +Serpent | 528 | +Rijndael | 516 | +XTEA | 256 | +RC2 | 256 | +DES | 256 | +SAFER [#] | 217 | +RC5 | 204 | +Twofish [*] | 193 | +RC6 | 176 | +CAST5 | 132 | +Noekeon | 32 | +Skipjack | 10 | +------------+-------------------------------/ +Memory used per cipher on a 32-bit platform. + +[*] For Twofish with TWOFISH_SMALL defined +[#] For all 64-bit SAFER ciphers. + +Noekeon is a fairly fast cipher and uses very little memory. Ideally in low-ram platforms all other ciphers should be +left undefined and Noekeon should remain. While Noekeon is generally considered a secure block cipher (it is insecure +as a hash) CAST5 is perhaps a "runner-up" choice. CAST5 has been around longer (it is also known as CAST-128) and is +fairly fast as well. + +You can easily accomplish this via the "config.pl" script. Simply answer "n" to all of the ciphers except the one you want +and then rebuild the library. [or you can hand edit tomcrypt_custom.h] + + diff --git a/deps/libtomcrypt/notes/tech0004.txt b/deps/libtomcrypt/notes/tech0004.txt new file mode 100644 index 0000000..2acd378 --- /dev/null +++ b/deps/libtomcrypt/notes/tech0004.txt @@ -0,0 +1,91 @@ +Tech Note 0004 +Using Yarrow, Fortuna and SOBER-128 +Tom St Denis + +Introduction +------------ + +This tech note explains how to use three of the more useful pseudo random number generators and their +own little "issues". While all of the PRNGs have the same API and are roughly used in the same +manner their effectiveness really depends on the user knowing how they work. + + +Yarrow +------ + +Yarrow is by far the simplest of the PRNGs. It gathers bits of entropy by hashing the pool state +plus the additional bits storing the message digest back in the pool. E.g. + +pool = hash(pool || newbits) + +Simply dump bits into the PRNG via yarrow_add_entropy() and call yarrow_ready() when you want to +put them to use. This PRNG while simple is not entirely safe. An attacker who learns the state +of the pool and can control future events can control the PRNG. This requires an active attacker but +isn't entire impossible. + +The pool is then used as a key for a cipher that is used in CTR mode. + +Yarrow is mostly meant for short-term programs [e.g. like file utils]. This particular implementation +is not meant for long-term usage. + +Fortuna +------- + +Fortuna was designed by Niels Fergusson and Bruce Schneier [Bruce is also the guy who invented Yarrow]. It +operates on a more defensive level than Yarrow. Instead of 1 entropy pool it has 32 and the new entropy +is spread [round robin] in all of the pools. + +That is, each call to fortuna_add_entropy() puts the bits in the next [in the sequenece] pool of entropy. +Effective bits are added to the pool by sending them through a hash [but not terminating the hash]. + +Here's the main catch though. When the PRNG must be reseeded [so that you can extract bits from it] only +certain pools are used. More precisely the i'th pool is used every 2**i'th reseeding. For example, pool[0] +is always used. pool[1] is used every second reseeding, pool[2] every fourth. + +The pools are hashed together along with the current key and the result is the new key for a cipher which +operates in CTR mode [more about that in a sec]. + +Now this may seem odd at first however there is a good reason behind it. An attacker who learns pool[0] won't +strictly know the other pools. So the recovery rate of is not 0. In fact pool[0] can be completely +compromised and the PRNG will still eventually recover. The value FORTUNA_WD is the "WatchDog" counter. +Every FORTUNA_WD calls to fortuna_read will invoke the reseed operation. By default this is set to 10 which +means after 10 calls the PRNG will reseed itself. + +The pools are combined with the running cipher key [256 bits] so that a cipher in CTR mode can produce +the stream. Unlike Yarrow the cipher is re-keyed after every call to fortuna_read() [so one big call +would be faster than many smaller calls]. This prevents too much data being encrypted under the same +key [and mitigates a flaw in CTR mode that the same block can't be emitted twice under the same key]. + +Fortuna is really meant for a kernel-level PRNG. The more sources [and often] you feed into it the +healthier it will be. It's also meant to be used for long term purposes. Since it can recover from +compromises it is harder to control it. + +SOBER-128 +------ + +SOBER-128 is actually a stream cipher but like most ciphers can easily be modelled in the context of a PRNG. +This PRNG is extremely fast [4 cycles/byte on a P4] and was designed by a well known cryptographer [Greg Rose]. + +SOBER-128 doesn't really "act" like the other two PRNGs. It's meant to be seeded once and then read as +required. In such a sense it isn't a "system PRNG" but useful short term purposes. In particular +the sober128_read() function actually XORs against the input buffer you specify. This allows the +read() function to be used as an "encrypt" function as well. + +You can only key SOBER-128 once [by calling sober128_add_entropy()]. Once it it is keyed subsequent +calls to add_entropy() will be considered a "re-IV" operation. Changing the IV allows you to use same +initial key and not produce the same output stream. It also lets you differentiate packets. E.g. each +packet has it's own IV. + +All inputs to sober128_add_entropy() must have a length that is a multiple of four. + +Overall +------- + +Since SOBER-128 is *much* faster than the other two PRNGs a good setup would be to use Fortuna as your +system-wide PRNG and use SOBER-128 [key'ed from Fortuna] for encrypting streams or as a PRNG for +simulations. + +Yarrow is still a good candidate but only for "short lived" programs. However, since Fortuna is faster +[by about 10 cycles/byte on a P4] I'd use Fortuna anyways... + +Tom \ No newline at end of file diff --git a/deps/libtomcrypt/notes/tech0005.txt b/deps/libtomcrypt/notes/tech0005.txt new file mode 100644 index 0000000..c250220 --- /dev/null +++ b/deps/libtomcrypt/notes/tech0005.txt @@ -0,0 +1,20 @@ +Tech Note 0005 +Minimizing Code Space +Tom St Denis + +Introduction +------------ + +Tweaking... + +You can disable whole classes of algorithms on the command line with the LTC_NO_* defines. From there you can manually turn on what you want to enable. + +The following build with GCC 3.4.4 on an AMD64 box gets you AES, CTR mode, SHA-256, HMAC, Yarrow, full RSA PKCS #1, PKCS #5 and ASN.1 DER in +roughly 40KB of code (49KB on the ARMv4) (both excluding the math library). + +CFLAGS="-DLTC_NO_CIPHERS -DLTC_NO_HASHES -DLTC_NO_PRNGS -DLTC_NO_MACS -DLTC_NO_MODES -DLTC_NO_PK -DLTC_RIJNDAEL -DLTC_CTR_MODE -DSHA256 \ +-DLTC_HMAC -DYARROW -DMRSA -DMPI -DTFM_DESC -DARGTYPE=3 -Os -DLTC_SMALL_CODE -fomit-frame-pointer" make IGNORE_SPEED=1 + +Obviously this won't get you performance but if you need to pack a crypto lib in a device with limited means it's more than enough... + +Neato eh? diff --git a/deps/libtomcrypt/notes/tech0006.txt b/deps/libtomcrypt/notes/tech0006.txt new file mode 100644 index 0000000..ecbe8b0 --- /dev/null +++ b/deps/libtomcrypt/notes/tech0006.txt @@ -0,0 +1,91 @@ +Tech Note 0006 +PK Standards Compliance +Tom St Denis + +RSA +---- + +PKCS #1 compliance. + +Key Format: RSAPublicKey and RSAPrivateKey as per PKCS #1 v2.1 +Encryption: OAEP as per PKCS #1 +Signature : PSS as per PKCS #1 + +DSA +---- + +The NIST DSA algorithm + +Key Format: HomeBrew [see below] +Signature : ANSI X9.62 format [see below]. + +Keys are stored as + +DSAPublicKey ::= SEQUENCE { + publicFlags BIT STRING(1), -- must be 0 + g INTEGER , -- base generator, check that g^q mod p == 1 + -- and that 1 < g < p - 1 + p INTEGER , -- prime modulus + q INTEGER , -- order of sub-group (must be prime) + y INTEGER , -- public key, specifically, g^x mod p, + -- check that y^q mod p == 1 + -- and that 1 < y < p - 1 +} + +DSAPrivateKey ::= SEQUENCE { + publicFlags BIT STRING(1), -- must be 1 + g INTEGER , -- base generator, check that g^q mod p == 1 + -- and that 1 < g < p - 1 + p INTEGER , -- prime modulus + q INTEGER , -- order of sub-group (must be prime) + y INTEGER , -- public key, specifically, g^x mod p, + -- check that y^q mod p == 1 + -- and that 1 < y < p - 1 + x INTEGER -- private key +} + +Signatures are stored as + +DSASignature ::= SEQUENCE { + r, s INTEGER -- signature parameters +} + +ECC +---- + +The ANSI X9.62 and X9.63 algorithms [partial]. Supports all NIST GF(p) curves. + +Key Format : Homebrew [see below, only GF(p) NIST curves supported] +Signature : X9.62 compliant +Encryption : Homebrew [based on X9.63, differs in that the public point is stored as an ECCPublicKey] +Shared Secret: X9.63 compliant + +ECCPublicKey ::= SEQUENCE { + flags BIT STRING(1), -- public/private flag (always zero), + keySize INTEGER, -- Curve size (in bits) divided by eight + -- and rounded down, e.g. 521 => 65 + pubkey.x INTEGER, -- The X co-ordinate of the public key point + pubkey.y INTEGER, -- The Y co-ordinate of the public key point +} + +ECCPrivateKey ::= SEQUENCE { + flags BIT STRING(1), -- public/private flag (always one), + keySize INTEGER, -- Curve size (in bits) divided by eight + -- and rounded down, e.g. 521 => 65 + pubkey.x INTEGER, -- The X co-ordinate of the public key point + pubkey.y INTEGER, -- The Y co-ordinate of the public key point + secret.k INTEGER, -- The secret key scalar +} + +The encryption works by finding the X9.63 shared secret and hashing it. The hash is then simply XOR'ed against the message [which must be at most the size +of the hash digest]. The format of the encrypted text is as follows + +ECCEncrypted ::= SEQUENCE { + hashOID OBJECT IDENTIFIER, -- The OID of the hash used + pubkey OCTET STRING , -- Encapsulation of a random ECCPublicKey + skey OCTET STRING -- The encrypted text (which the hash was XOR'ed against) +} + +% $Source: /cvs/libtom/libtomcrypt/notes/tech0006.txt,v $ +% $Revision: 1.2 $ +% $Date: 2005/06/18 02:26:27 $ diff --git a/deps/libtomcrypt/notes/tech0007.txt b/deps/libtomcrypt/notes/tech0007.txt new file mode 100644 index 0000000..149bd49 --- /dev/null +++ b/deps/libtomcrypt/notes/tech0007.txt @@ -0,0 +1,5 @@ +Tech Note #7 +Quick building for testing with LTM + +EXTRALIBS=-ltommath CFLAGS="-g3 -DLTC_NO_ASM -DUSE_LTM -DLTM_DESC" make -j3 IGNORE_SPEED=1 test + diff --git a/deps/libtomcrypt/sources.cmake b/deps/libtomcrypt/sources.cmake new file mode 100644 index 0000000..6f17242 --- /dev/null +++ b/deps/libtomcrypt/sources.cmake @@ -0,0 +1,525 @@ +set(SOURCES +src/ciphers/aes/aes.c +src/ciphers/aes/aes_tab.c +src/ciphers/anubis.c +src/ciphers/blowfish.c +src/ciphers/camellia.c +src/ciphers/cast5.c +src/ciphers/des.c +src/ciphers/idea.c +src/ciphers/kasumi.c +src/ciphers/khazad.c +src/ciphers/kseed.c +src/ciphers/multi2.c +src/ciphers/noekeon.c +src/ciphers/rc2.c +src/ciphers/rc5.c +src/ciphers/rc6.c +src/ciphers/safer/safer.c +src/ciphers/safer/safer_tab.c +src/ciphers/safer/saferp.c +src/ciphers/serpent.c +src/ciphers/skipjack.c +src/ciphers/tea.c +src/ciphers/twofish/twofish.c +src/ciphers/twofish/twofish_tab.c +src/ciphers/xtea.c +src/encauth/ccm/ccm_add_aad.c +src/encauth/ccm/ccm_add_nonce.c +src/encauth/ccm/ccm_done.c +src/encauth/ccm/ccm_init.c +src/encauth/ccm/ccm_memory.c +src/encauth/ccm/ccm_process.c +src/encauth/ccm/ccm_reset.c +src/encauth/ccm/ccm_test.c +src/encauth/chachapoly/chacha20poly1305_add_aad.c +src/encauth/chachapoly/chacha20poly1305_decrypt.c +src/encauth/chachapoly/chacha20poly1305_done.c +src/encauth/chachapoly/chacha20poly1305_encrypt.c +src/encauth/chachapoly/chacha20poly1305_init.c +src/encauth/chachapoly/chacha20poly1305_memory.c +src/encauth/chachapoly/chacha20poly1305_setiv.c +src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c +src/encauth/chachapoly/chacha20poly1305_test.c +src/encauth/eax/eax_addheader.c +src/encauth/eax/eax_decrypt.c +src/encauth/eax/eax_decrypt_verify_memory.c +src/encauth/eax/eax_done.c +src/encauth/eax/eax_encrypt.c +src/encauth/eax/eax_encrypt_authenticate_memory.c +src/encauth/eax/eax_init.c +src/encauth/eax/eax_test.c +src/encauth/gcm/gcm_add_aad.c +src/encauth/gcm/gcm_add_iv.c +src/encauth/gcm/gcm_done.c +src/encauth/gcm/gcm_gf_mult.c +src/encauth/gcm/gcm_init.c +src/encauth/gcm/gcm_memory.c +src/encauth/gcm/gcm_mult_h.c +src/encauth/gcm/gcm_process.c +src/encauth/gcm/gcm_reset.c +src/encauth/gcm/gcm_test.c +src/encauth/ocb/ocb_decrypt.c +src/encauth/ocb/ocb_decrypt_verify_memory.c +src/encauth/ocb/ocb_done_decrypt.c +src/encauth/ocb/ocb_done_encrypt.c +src/encauth/ocb/ocb_encrypt.c +src/encauth/ocb/ocb_encrypt_authenticate_memory.c +src/encauth/ocb/ocb_init.c +src/encauth/ocb/ocb_ntz.c +src/encauth/ocb/ocb_shift_xor.c +src/encauth/ocb/ocb_test.c +src/encauth/ocb/s_ocb_done.c +src/encauth/ocb3/ocb3_add_aad.c +src/encauth/ocb3/ocb3_decrypt.c +src/encauth/ocb3/ocb3_decrypt_last.c +src/encauth/ocb3/ocb3_decrypt_verify_memory.c +src/encauth/ocb3/ocb3_done.c +src/encauth/ocb3/ocb3_encrypt.c +src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c +src/encauth/ocb3/ocb3_encrypt_last.c +src/encauth/ocb3/ocb3_init.c +src/encauth/ocb3/ocb3_int_ntz.c +src/encauth/ocb3/ocb3_int_xor_blocks.c +src/encauth/ocb3/ocb3_test.c +src/hashes/blake2b.c +src/hashes/blake2s.c +src/hashes/chc/chc.c +src/hashes/helper/hash_file.c +src/hashes/helper/hash_filehandle.c +src/hashes/helper/hash_memory.c +src/hashes/helper/hash_memory_multi.c +src/hashes/md2.c +src/hashes/md4.c +src/hashes/md5.c +src/hashes/rmd128.c +src/hashes/rmd160.c +src/hashes/rmd256.c +src/hashes/rmd320.c +src/hashes/sha1.c +src/hashes/sha2/sha224.c +src/hashes/sha2/sha256.c +src/hashes/sha2/sha384.c +src/hashes/sha2/sha512.c +src/hashes/sha2/sha512_224.c +src/hashes/sha2/sha512_256.c +src/hashes/sha3.c +src/hashes/sha3_test.c +src/hashes/tiger.c +src/hashes/whirl/whirl.c +src/hashes/whirl/whirltab.c +src/headers/tomcrypt.h +src/headers/tomcrypt_argchk.h +src/headers/tomcrypt_cfg.h +src/headers/tomcrypt_cipher.h +src/headers/tomcrypt_custom.h +src/headers/tomcrypt_hash.h +src/headers/tomcrypt_mac.h +src/headers/tomcrypt_macros.h +src/headers/tomcrypt_math.h +src/headers/tomcrypt_misc.h +src/headers/tomcrypt_pk.h +src/headers/tomcrypt_pkcs.h +src/headers/tomcrypt_private.h +src/headers/tomcrypt_prng.h +src/mac/blake2/blake2bmac.c +src/mac/blake2/blake2bmac_file.c +src/mac/blake2/blake2bmac_memory.c +src/mac/blake2/blake2bmac_memory_multi.c +src/mac/blake2/blake2bmac_test.c +src/mac/blake2/blake2smac.c +src/mac/blake2/blake2smac_file.c +src/mac/blake2/blake2smac_memory.c +src/mac/blake2/blake2smac_memory_multi.c +src/mac/blake2/blake2smac_test.c +src/mac/f9/f9_done.c +src/mac/f9/f9_file.c +src/mac/f9/f9_init.c +src/mac/f9/f9_memory.c +src/mac/f9/f9_memory_multi.c +src/mac/f9/f9_process.c +src/mac/f9/f9_test.c +src/mac/hmac/hmac_done.c +src/mac/hmac/hmac_file.c +src/mac/hmac/hmac_init.c +src/mac/hmac/hmac_memory.c +src/mac/hmac/hmac_memory_multi.c +src/mac/hmac/hmac_process.c +src/mac/hmac/hmac_test.c +src/mac/omac/omac_done.c +src/mac/omac/omac_file.c +src/mac/omac/omac_init.c +src/mac/omac/omac_memory.c +src/mac/omac/omac_memory_multi.c +src/mac/omac/omac_process.c +src/mac/omac/omac_test.c +src/mac/pelican/pelican.c +src/mac/pelican/pelican_memory.c +src/mac/pelican/pelican_test.c +src/mac/pmac/pmac_done.c +src/mac/pmac/pmac_file.c +src/mac/pmac/pmac_init.c +src/mac/pmac/pmac_memory.c +src/mac/pmac/pmac_memory_multi.c +src/mac/pmac/pmac_ntz.c +src/mac/pmac/pmac_process.c +src/mac/pmac/pmac_shift_xor.c +src/mac/pmac/pmac_test.c +src/mac/poly1305/poly1305.c +src/mac/poly1305/poly1305_file.c +src/mac/poly1305/poly1305_memory.c +src/mac/poly1305/poly1305_memory_multi.c +src/mac/poly1305/poly1305_test.c +src/mac/xcbc/xcbc_done.c +src/mac/xcbc/xcbc_file.c +src/mac/xcbc/xcbc_init.c +src/mac/xcbc/xcbc_memory.c +src/mac/xcbc/xcbc_memory_multi.c +src/mac/xcbc/xcbc_process.c +src/mac/xcbc/xcbc_test.c +src/math/fp/ltc_ecc_fp_mulmod.c +src/math/gmp_desc.c +src/math/ltm_desc.c +src/math/multi.c +src/math/radix_to_bin.c +src/math/rand_bn.c +src/math/rand_prime.c +src/math/tfm_desc.c +src/misc/adler32.c +src/misc/base16/base16_decode.c +src/misc/base16/base16_encode.c +src/misc/base32/base32_decode.c +src/misc/base32/base32_encode.c +src/misc/base64/base64_decode.c +src/misc/base64/base64_encode.c +src/misc/bcrypt/bcrypt.c +src/misc/burn_stack.c +src/misc/compare_testvector.c +src/misc/copy_or_zeromem.c +src/misc/crc32.c +src/misc/crypt/crypt.c +src/misc/crypt/crypt_argchk.c +src/misc/crypt/crypt_cipher_descriptor.c +src/misc/crypt/crypt_cipher_is_valid.c +src/misc/crypt/crypt_constants.c +src/misc/crypt/crypt_find_cipher.c +src/misc/crypt/crypt_find_cipher_any.c +src/misc/crypt/crypt_find_cipher_id.c +src/misc/crypt/crypt_find_hash.c +src/misc/crypt/crypt_find_hash_any.c +src/misc/crypt/crypt_find_hash_id.c +src/misc/crypt/crypt_find_hash_oid.c +src/misc/crypt/crypt_find_prng.c +src/misc/crypt/crypt_fsa.c +src/misc/crypt/crypt_hash_descriptor.c +src/misc/crypt/crypt_hash_is_valid.c +src/misc/crypt/crypt_inits.c +src/misc/crypt/crypt_ltc_mp_descriptor.c +src/misc/crypt/crypt_prng_descriptor.c +src/misc/crypt/crypt_prng_is_valid.c +src/misc/crypt/crypt_prng_rng_descriptor.c +src/misc/crypt/crypt_register_all_ciphers.c +src/misc/crypt/crypt_register_all_hashes.c +src/misc/crypt/crypt_register_all_prngs.c +src/misc/crypt/crypt_register_cipher.c +src/misc/crypt/crypt_register_hash.c +src/misc/crypt/crypt_register_prng.c +src/misc/crypt/crypt_sizes.c +src/misc/crypt/crypt_unregister_cipher.c +src/misc/crypt/crypt_unregister_hash.c +src/misc/crypt/crypt_unregister_prng.c +src/misc/error_to_string.c +src/misc/hkdf/hkdf.c +src/misc/hkdf/hkdf_test.c +src/misc/mem_neq.c +src/misc/padding/padding_depad.c +src/misc/padding/padding_pad.c +src/misc/pbes/pbes.c +src/misc/pbes/pbes1.c +src/misc/pbes/pbes2.c +src/misc/pkcs12/pkcs12_kdf.c +src/misc/pkcs12/pkcs12_utf8_to_utf16.c +src/misc/pkcs5/pkcs_5_1.c +src/misc/pkcs5/pkcs_5_2.c +src/misc/pkcs5/pkcs_5_test.c +src/misc/ssh/ssh_decode_sequence_multi.c +src/misc/ssh/ssh_encode_sequence_multi.c +src/misc/zeromem.c +src/modes/cbc/cbc_decrypt.c +src/modes/cbc/cbc_done.c +src/modes/cbc/cbc_encrypt.c +src/modes/cbc/cbc_getiv.c +src/modes/cbc/cbc_setiv.c +src/modes/cbc/cbc_start.c +src/modes/cfb/cfb_decrypt.c +src/modes/cfb/cfb_done.c +src/modes/cfb/cfb_encrypt.c +src/modes/cfb/cfb_getiv.c +src/modes/cfb/cfb_setiv.c +src/modes/cfb/cfb_start.c +src/modes/ctr/ctr_decrypt.c +src/modes/ctr/ctr_done.c +src/modes/ctr/ctr_encrypt.c +src/modes/ctr/ctr_getiv.c +src/modes/ctr/ctr_setiv.c +src/modes/ctr/ctr_start.c +src/modes/ctr/ctr_test.c +src/modes/ecb/ecb_decrypt.c +src/modes/ecb/ecb_done.c +src/modes/ecb/ecb_encrypt.c +src/modes/ecb/ecb_start.c +src/modes/f8/f8_decrypt.c +src/modes/f8/f8_done.c +src/modes/f8/f8_encrypt.c +src/modes/f8/f8_getiv.c +src/modes/f8/f8_setiv.c +src/modes/f8/f8_start.c +src/modes/f8/f8_test_mode.c +src/modes/lrw/lrw_decrypt.c +src/modes/lrw/lrw_done.c +src/modes/lrw/lrw_encrypt.c +src/modes/lrw/lrw_getiv.c +src/modes/lrw/lrw_process.c +src/modes/lrw/lrw_setiv.c +src/modes/lrw/lrw_start.c +src/modes/lrw/lrw_test.c +src/modes/ofb/ofb_decrypt.c +src/modes/ofb/ofb_done.c +src/modes/ofb/ofb_encrypt.c +src/modes/ofb/ofb_getiv.c +src/modes/ofb/ofb_setiv.c +src/modes/ofb/ofb_start.c +src/modes/xts/xts_decrypt.c +src/modes/xts/xts_done.c +src/modes/xts/xts_encrypt.c +src/modes/xts/xts_init.c +src/modes/xts/xts_mult_x.c +src/modes/xts/xts_test.c +src/pk/asn1/der/bit/der_decode_bit_string.c +src/pk/asn1/der/bit/der_decode_raw_bit_string.c +src/pk/asn1/der/bit/der_encode_bit_string.c +src/pk/asn1/der/bit/der_encode_raw_bit_string.c +src/pk/asn1/der/bit/der_length_bit_string.c +src/pk/asn1/der/boolean/der_decode_boolean.c +src/pk/asn1/der/boolean/der_encode_boolean.c +src/pk/asn1/der/boolean/der_length_boolean.c +src/pk/asn1/der/choice/der_decode_choice.c +src/pk/asn1/der/custom_type/der_decode_custom_type.c +src/pk/asn1/der/custom_type/der_encode_custom_type.c +src/pk/asn1/der/custom_type/der_length_custom_type.c +src/pk/asn1/der/general/der_asn1_maps.c +src/pk/asn1/der/general/der_decode_asn1_identifier.c +src/pk/asn1/der/general/der_decode_asn1_length.c +src/pk/asn1/der/general/der_encode_asn1_identifier.c +src/pk/asn1/der/general/der_encode_asn1_length.c +src/pk/asn1/der/general/der_length_asn1_identifier.c +src/pk/asn1/der/general/der_length_asn1_length.c +src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c +src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c +src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c +src/pk/asn1/der/ia5/der_decode_ia5_string.c +src/pk/asn1/der/ia5/der_encode_ia5_string.c +src/pk/asn1/der/ia5/der_length_ia5_string.c +src/pk/asn1/der/integer/der_decode_integer.c +src/pk/asn1/der/integer/der_encode_integer.c +src/pk/asn1/der/integer/der_length_integer.c +src/pk/asn1/der/object_identifier/der_decode_object_identifier.c +src/pk/asn1/der/object_identifier/der_encode_object_identifier.c +src/pk/asn1/der/object_identifier/der_length_object_identifier.c +src/pk/asn1/der/octet/der_decode_octet_string.c +src/pk/asn1/der/octet/der_encode_octet_string.c +src/pk/asn1/der/octet/der_length_octet_string.c +src/pk/asn1/der/printable_string/der_decode_printable_string.c +src/pk/asn1/der/printable_string/der_encode_printable_string.c +src/pk/asn1/der/printable_string/der_length_printable_string.c +src/pk/asn1/der/sequence/der_decode_sequence_ex.c +src/pk/asn1/der/sequence/der_decode_sequence_flexi.c +src/pk/asn1/der/sequence/der_decode_sequence_multi.c +src/pk/asn1/der/sequence/der_encode_sequence_ex.c +src/pk/asn1/der/sequence/der_encode_sequence_multi.c +src/pk/asn1/der/sequence/der_length_sequence.c +src/pk/asn1/der/sequence/der_sequence_free.c +src/pk/asn1/der/sequence/der_sequence_shrink.c +src/pk/asn1/der/set/der_encode_set.c +src/pk/asn1/der/set/der_encode_setof.c +src/pk/asn1/der/short_integer/der_decode_short_integer.c +src/pk/asn1/der/short_integer/der_encode_short_integer.c +src/pk/asn1/der/short_integer/der_length_short_integer.c +src/pk/asn1/der/teletex_string/der_decode_teletex_string.c +src/pk/asn1/der/teletex_string/der_length_teletex_string.c +src/pk/asn1/der/utctime/der_decode_utctime.c +src/pk/asn1/der/utctime/der_encode_utctime.c +src/pk/asn1/der/utctime/der_length_utctime.c +src/pk/asn1/der/utf8/der_decode_utf8_string.c +src/pk/asn1/der/utf8/der_encode_utf8_string.c +src/pk/asn1/der/utf8/der_length_utf8_string.c +src/pk/asn1/oid/pk_get_oid.c +src/pk/asn1/oid/pk_oid_cmp.c +src/pk/asn1/oid/pk_oid_str.c +src/pk/asn1/pkcs8/pkcs8_decode_flexi.c +src/pk/asn1/x509/x509_decode_public_key_from_certificate.c +src/pk/asn1/x509/x509_decode_subject_public_key_info.c +src/pk/asn1/x509/x509_encode_subject_public_key_info.c +src/pk/dh/dh.c +src/pk/dh/dh_check_pubkey.c +src/pk/dh/dh_export.c +src/pk/dh/dh_export_key.c +src/pk/dh/dh_free.c +src/pk/dh/dh_generate_key.c +src/pk/dh/dh_import.c +src/pk/dh/dh_set.c +src/pk/dh/dh_set_pg_dhparam.c +src/pk/dh/dh_shared_secret.c +src/pk/dsa/dsa_decrypt_key.c +src/pk/dsa/dsa_encrypt_key.c +src/pk/dsa/dsa_export.c +src/pk/dsa/dsa_free.c +src/pk/dsa/dsa_generate_key.c +src/pk/dsa/dsa_generate_pqg.c +src/pk/dsa/dsa_import.c +src/pk/dsa/dsa_make_key.c +src/pk/dsa/dsa_set.c +src/pk/dsa/dsa_set_pqg_dsaparam.c +src/pk/dsa/dsa_shared_secret.c +src/pk/dsa/dsa_sign_hash.c +src/pk/dsa/dsa_verify_hash.c +src/pk/dsa/dsa_verify_key.c +src/pk/ec25519/ec25519_crypto_ctx.c +src/pk/ec25519/ec25519_export.c +src/pk/ec25519/ec25519_import_pkcs8.c +src/pk/ec25519/tweetnacl.c +src/pk/ecc/ecc.c +src/pk/ecc/ecc_ansi_x963_export.c +src/pk/ecc/ecc_ansi_x963_import.c +src/pk/ecc/ecc_decrypt_key.c +src/pk/ecc/ecc_encrypt_key.c +src/pk/ecc/ecc_export.c +src/pk/ecc/ecc_export_openssl.c +src/pk/ecc/ecc_find_curve.c +src/pk/ecc/ecc_free.c +src/pk/ecc/ecc_get_key.c +src/pk/ecc/ecc_get_oid_str.c +src/pk/ecc/ecc_get_size.c +src/pk/ecc/ecc_import.c +src/pk/ecc/ecc_import_openssl.c +src/pk/ecc/ecc_import_pkcs8.c +src/pk/ecc/ecc_import_x509.c +src/pk/ecc/ecc_make_key.c +src/pk/ecc/ecc_recover_key.c +src/pk/ecc/ecc_set_curve.c +src/pk/ecc/ecc_set_curve_internal.c +src/pk/ecc/ecc_set_key.c +src/pk/ecc/ecc_shared_secret.c +src/pk/ecc/ecc_sign_hash.c +src/pk/ecc/ecc_sizes.c +src/pk/ecc/ecc_ssh_ecdsa_encode_name.c +src/pk/ecc/ecc_verify_hash.c +src/pk/ecc/ltc_ecc_export_point.c +src/pk/ecc/ltc_ecc_import_point.c +src/pk/ecc/ltc_ecc_is_point.c +src/pk/ecc/ltc_ecc_is_point_at_infinity.c +src/pk/ecc/ltc_ecc_map.c +src/pk/ecc/ltc_ecc_mul2add.c +src/pk/ecc/ltc_ecc_mulmod.c +src/pk/ecc/ltc_ecc_mulmod_timing.c +src/pk/ecc/ltc_ecc_points.c +src/pk/ecc/ltc_ecc_projective_add_point.c +src/pk/ecc/ltc_ecc_projective_dbl_point.c +src/pk/ecc/ltc_ecc_verify_key.c +src/pk/ed25519/ed25519_export.c +src/pk/ed25519/ed25519_import.c +src/pk/ed25519/ed25519_import_pkcs8.c +src/pk/ed25519/ed25519_import_raw.c +src/pk/ed25519/ed25519_import_x509.c +src/pk/ed25519/ed25519_make_key.c +src/pk/ed25519/ed25519_sign.c +src/pk/ed25519/ed25519_verify.c +src/pk/pkcs1/pkcs_1_i2osp.c +src/pk/pkcs1/pkcs_1_mgf1.c +src/pk/pkcs1/pkcs_1_oaep_decode.c +src/pk/pkcs1/pkcs_1_oaep_encode.c +src/pk/pkcs1/pkcs_1_os2ip.c +src/pk/pkcs1/pkcs_1_pss_decode.c +src/pk/pkcs1/pkcs_1_pss_encode.c +src/pk/pkcs1/pkcs_1_v1_5_decode.c +src/pk/pkcs1/pkcs_1_v1_5_encode.c +src/pk/rsa/rsa_decrypt_key.c +src/pk/rsa/rsa_encrypt_key.c +src/pk/rsa/rsa_export.c +src/pk/rsa/rsa_exptmod.c +src/pk/rsa/rsa_get_size.c +src/pk/rsa/rsa_import.c +src/pk/rsa/rsa_import_pkcs8.c +src/pk/rsa/rsa_import_x509.c +src/pk/rsa/rsa_key.c +src/pk/rsa/rsa_make_key.c +src/pk/rsa/rsa_set.c +src/pk/rsa/rsa_sign_hash.c +src/pk/rsa/rsa_sign_saltlen_get.c +src/pk/rsa/rsa_verify_hash.c +src/pk/x25519/x25519_export.c +src/pk/x25519/x25519_import.c +src/pk/x25519/x25519_import_pkcs8.c +src/pk/x25519/x25519_import_raw.c +src/pk/x25519/x25519_import_x509.c +src/pk/x25519/x25519_make_key.c +src/pk/x25519/x25519_shared_secret.c +src/prngs/chacha20.c +src/prngs/fortuna.c +src/prngs/rc4.c +src/prngs/rng_get_bytes.c +src/prngs/rng_make_prng.c +src/prngs/sober128.c +src/prngs/sprng.c +src/prngs/yarrow.c +src/stream/chacha/chacha_crypt.c +src/stream/chacha/chacha_done.c +src/stream/chacha/chacha_ivctr32.c +src/stream/chacha/chacha_ivctr64.c +src/stream/chacha/chacha_keystream.c +src/stream/chacha/chacha_memory.c +src/stream/chacha/chacha_setup.c +src/stream/chacha/chacha_test.c +src/stream/rabbit/rabbit.c +src/stream/rabbit/rabbit_memory.c +src/stream/rc4/rc4_stream.c +src/stream/rc4/rc4_stream_memory.c +src/stream/rc4/rc4_test.c +src/stream/salsa20/salsa20_crypt.c +src/stream/salsa20/salsa20_done.c +src/stream/salsa20/salsa20_ivctr64.c +src/stream/salsa20/salsa20_keystream.c +src/stream/salsa20/salsa20_memory.c +src/stream/salsa20/salsa20_setup.c +src/stream/salsa20/salsa20_test.c +src/stream/salsa20/xsalsa20_memory.c +src/stream/salsa20/xsalsa20_setup.c +src/stream/salsa20/xsalsa20_test.c +src/stream/sober128/sober128_stream.c +src/stream/sober128/sober128_stream_memory.c +src/stream/sober128/sober128_test.c +src/stream/sober128/sober128tab.c +src/stream/sosemanuk/sosemanuk.c +src/stream/sosemanuk/sosemanuk_memory.c +src/stream/sosemanuk/sosemanuk_test.c +) + +set(PUBLIC_HEADERS +src/headers/tomcrypt.h +src/headers/tomcrypt_argchk.h +src/headers/tomcrypt_cfg.h +src/headers/tomcrypt_cipher.h +src/headers/tomcrypt_custom.h +src/headers/tomcrypt_hash.h +src/headers/tomcrypt_mac.h +src/headers/tomcrypt_macros.h +src/headers/tomcrypt_math.h +src/headers/tomcrypt_misc.h +src/headers/tomcrypt_pk.h +src/headers/tomcrypt_pkcs.h +src/headers/tomcrypt_prng.h +) + +set(PRIVATE_HEADERS src/headers/tomcrypt_private.h) +set_property(GLOBAL PROPERTY PUBLIC_HEADERS ${PUBLIC_HEADERS}) + diff --git a/deps/libtomcrypt/src/ciphers/aes/aes.c b/deps/libtomcrypt/src/ciphers/aes/aes.c new file mode 100644 index 0000000..dd6f14e --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/aes/aes.c @@ -0,0 +1,744 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* AES implementation by Tom St Denis + * + * Derived from the Public Domain source code by + +--- + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto +--- + */ +/** + @file aes.c + Implementation of AES +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_RIJNDAEL + +#ifndef ENCRYPT_ONLY + +#define SETUP rijndael_setup +#define ECB_ENC rijndael_ecb_encrypt +#define ECB_DEC rijndael_ecb_decrypt +#define ECB_DONE rijndael_done +#define ECB_TEST rijndael_test +#define ECB_KS rijndael_keysize + +const struct ltc_cipher_descriptor rijndael_desc = +{ + "rijndael", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +const struct ltc_cipher_descriptor aes_desc = +{ + "aes", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#else + +#define SETUP rijndael_enc_setup +#define ECB_ENC rijndael_enc_ecb_encrypt +#define ECB_KS rijndael_enc_keysize +#define ECB_DONE rijndael_enc_done + +const struct ltc_cipher_descriptor rijndael_enc_desc = +{ + "rijndael", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +const struct ltc_cipher_descriptor aes_enc_desc = +{ + "aes", + 6, + 16, 32, 16, 10, + SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#endif + +#define LTC_AES_TAB_C +#include "aes_tab.c" + +static ulong32 setup_mix(ulong32 temp) +{ + return (Te4_3[LTC_BYTE(temp, 2)]) ^ + (Te4_2[LTC_BYTE(temp, 1)]) ^ + (Te4_1[LTC_BYTE(temp, 0)]) ^ + (Te4_0[LTC_BYTE(temp, 3)]); +} + +#ifndef ENCRYPT_ONLY +#ifdef LTC_SMALL_CODE +static ulong32 setup_mix2(ulong32 temp) +{ + return Td0(255 & Te4[LTC_BYTE(temp, 3)]) ^ + Td1(255 & Te4[LTC_BYTE(temp, 2)]) ^ + Td2(255 & Te4[LTC_BYTE(temp, 1)]) ^ + Td3(255 & Te4[LTC_BYTE(temp, 0)]); +} +#endif +#endif + + /** + Initialize the AES (Rijndael) block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int i; + ulong32 temp, *rk; +#ifndef ENCRYPT_ONLY + ulong32 *rrk; +#endif + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) { + return CRYPT_INVALID_ROUNDS; + } + + skey->rijndael.Nr = 10 + ((keylen/8)-2)*2; + + /* setup the forward key */ + i = 0; + rk = skey->rijndael.eK; + LOAD32H(rk[0], key ); + LOAD32H(rk[1], key + 4); + LOAD32H(rk[2], key + 8); + LOAD32H(rk[3], key + 12); + if (keylen == 16) { + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + break; + } + rk += 4; + } + } else if (keylen == 24) { + LOAD32H(rk[4], key + 16); + LOAD32H(rk[5], key + 20); + for (;;) { + #ifdef _MSC_VER + temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5]; + #else + temp = rk[5]; + #endif + rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + break; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } else if (keylen == 32) { + LOAD32H(rk[4], key + 16); + LOAD32H(rk[5], key + 20); + LOAD32H(rk[6], key + 24); + LOAD32H(rk[7], key + 28); + for (;;) { + #ifdef _MSC_VER + temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7]; + #else + temp = rk[7]; + #endif + rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + break; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8)); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + rk += 8; + } + } else { + /* this can't happen */ + /* coverity[dead_error_line] */ + return CRYPT_ERROR; + } + +#ifndef ENCRYPT_ONLY + /* setup the inverse key now */ + rk = skey->rijndael.dK; + rrk = skey->rijndael.eK + (28 + keylen) - 4; + + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + /* copy first */ + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + rk -= 3; rrk -= 3; + + for (i = 1; i < skey->rijndael.Nr; i++) { + rrk -= 4; + rk += 4; + #ifdef LTC_SMALL_CODE + temp = rrk[0]; + rk[0] = setup_mix2(temp); + temp = rrk[1]; + rk[1] = setup_mix2(temp); + temp = rrk[2]; + rk[2] = setup_mix2(temp); + temp = rrk[3]; + rk[3] = setup_mix2(temp); + #else + temp = rrk[0]; + rk[0] = + Tks0[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_BYTE(temp, 0)]; + temp = rrk[1]; + rk[1] = + Tks0[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_BYTE(temp, 0)]; + temp = rrk[2]; + rk[2] = + Tks0[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_BYTE(temp, 0)]; + temp = rrk[3]; + rk[3] = + Tks0[LTC_BYTE(temp, 3)] ^ + Tks1[LTC_BYTE(temp, 2)] ^ + Tks2[LTC_BYTE(temp, 1)] ^ + Tks3[LTC_BYTE(temp, 0)]; + #endif + + } + + /* copy last */ + rrk -= 4; + rk += 4; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; +#endif /* ENCRYPT_ONLY */ + + return CRYPT_OK; +} + +/** + Encrypts a block of text with AES + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3; + const ulong32 *rk; + int Nr, r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + + if (Nr < 2 || Nr > 16) + return CRYPT_INVALID_ROUNDS; + + rk = skey->rijndael.eK; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + LOAD32H(s0, pt ); s0 ^= rk[0]; + LOAD32H(s1, pt + 4); s1 ^= rk[1]; + LOAD32H(s2, pt + 8); s2 ^= rk[2]; + LOAD32H(s3, pt + 12); s3 ^= rk[3]; + +#ifdef LTC_SMALL_CODE + + for (r = 0; ; r++) { + rk += 4; + t0 = + Te0(LTC_BYTE(s0, 3)) ^ + Te1(LTC_BYTE(s1, 2)) ^ + Te2(LTC_BYTE(s2, 1)) ^ + Te3(LTC_BYTE(s3, 0)) ^ + rk[0]; + t1 = + Te0(LTC_BYTE(s1, 3)) ^ + Te1(LTC_BYTE(s2, 2)) ^ + Te2(LTC_BYTE(s3, 1)) ^ + Te3(LTC_BYTE(s0, 0)) ^ + rk[1]; + t2 = + Te0(LTC_BYTE(s2, 3)) ^ + Te1(LTC_BYTE(s3, 2)) ^ + Te2(LTC_BYTE(s0, 1)) ^ + Te3(LTC_BYTE(s1, 0)) ^ + rk[2]; + t3 = + Te0(LTC_BYTE(s3, 3)) ^ + Te1(LTC_BYTE(s0, 2)) ^ + Te2(LTC_BYTE(s1, 1)) ^ + Te3(LTC_BYTE(s2, 0)) ^ + rk[3]; + if (r == Nr-2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; + +#else + + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + t0 = + Te0(LTC_BYTE(s0, 3)) ^ + Te1(LTC_BYTE(s1, 2)) ^ + Te2(LTC_BYTE(s2, 1)) ^ + Te3(LTC_BYTE(s3, 0)) ^ + rk[4]; + t1 = + Te0(LTC_BYTE(s1, 3)) ^ + Te1(LTC_BYTE(s2, 2)) ^ + Te2(LTC_BYTE(s3, 1)) ^ + Te3(LTC_BYTE(s0, 0)) ^ + rk[5]; + t2 = + Te0(LTC_BYTE(s2, 3)) ^ + Te1(LTC_BYTE(s3, 2)) ^ + Te2(LTC_BYTE(s0, 1)) ^ + Te3(LTC_BYTE(s1, 0)) ^ + rk[6]; + t3 = + Te0(LTC_BYTE(s3, 3)) ^ + Te1(LTC_BYTE(s0, 2)) ^ + Te2(LTC_BYTE(s1, 1)) ^ + Te3(LTC_BYTE(s2, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0(LTC_BYTE(t0, 3)) ^ + Te1(LTC_BYTE(t1, 2)) ^ + Te2(LTC_BYTE(t2, 1)) ^ + Te3(LTC_BYTE(t3, 0)) ^ + rk[0]; + s1 = + Te0(LTC_BYTE(t1, 3)) ^ + Te1(LTC_BYTE(t2, 2)) ^ + Te2(LTC_BYTE(t3, 1)) ^ + Te3(LTC_BYTE(t0, 0)) ^ + rk[1]; + s2 = + Te0(LTC_BYTE(t2, 3)) ^ + Te1(LTC_BYTE(t3, 2)) ^ + Te2(LTC_BYTE(t0, 1)) ^ + Te3(LTC_BYTE(t1, 0)) ^ + rk[2]; + s3 = + Te0(LTC_BYTE(t3, 3)) ^ + Te1(LTC_BYTE(t0, 2)) ^ + Te2(LTC_BYTE(t1, 1)) ^ + Te3(LTC_BYTE(t2, 0)) ^ + rk[3]; + } + +#endif + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4_3[LTC_BYTE(t0, 3)]) ^ + (Te4_2[LTC_BYTE(t1, 2)]) ^ + (Te4_1[LTC_BYTE(t2, 1)]) ^ + (Te4_0[LTC_BYTE(t3, 0)]) ^ + rk[0]; + STORE32H(s0, ct); + s1 = + (Te4_3[LTC_BYTE(t1, 3)]) ^ + (Te4_2[LTC_BYTE(t2, 2)]) ^ + (Te4_1[LTC_BYTE(t3, 1)]) ^ + (Te4_0[LTC_BYTE(t0, 0)]) ^ + rk[1]; + STORE32H(s1, ct+4); + s2 = + (Te4_3[LTC_BYTE(t2, 3)]) ^ + (Te4_2[LTC_BYTE(t3, 2)]) ^ + (Te4_1[LTC_BYTE(t0, 1)]) ^ + (Te4_0[LTC_BYTE(t1, 0)]) ^ + rk[2]; + STORE32H(s2, ct+8); + s3 = + (Te4_3[LTC_BYTE(t3, 3)]) ^ + (Te4_2[LTC_BYTE(t0, 2)]) ^ + (Te4_1[LTC_BYTE(t1, 1)]) ^ + (Te4_0[LTC_BYTE(t2, 0)]) ^ + rk[3]; + STORE32H(s3, ct+12); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int ECB_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_rijndael_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); + return err; +} +#endif + +#ifndef ENCRYPT_ONLY + +/** + Decrypts a block of text with AES + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3; + const ulong32 *rk; + int Nr, r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + + if (Nr < 2 || Nr > 16) + return CRYPT_INVALID_ROUNDS; + + rk = skey->rijndael.dK; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + LOAD32H(s0, ct ); s0 ^= rk[0]; + LOAD32H(s1, ct + 4); s1 ^= rk[1]; + LOAD32H(s2, ct + 8); s2 ^= rk[2]; + LOAD32H(s3, ct + 12); s3 ^= rk[3]; + +#ifdef LTC_SMALL_CODE + for (r = 0; ; r++) { + rk += 4; + t0 = + Td0(LTC_BYTE(s0, 3)) ^ + Td1(LTC_BYTE(s3, 2)) ^ + Td2(LTC_BYTE(s2, 1)) ^ + Td3(LTC_BYTE(s1, 0)) ^ + rk[0]; + t1 = + Td0(LTC_BYTE(s1, 3)) ^ + Td1(LTC_BYTE(s0, 2)) ^ + Td2(LTC_BYTE(s3, 1)) ^ + Td3(LTC_BYTE(s2, 0)) ^ + rk[1]; + t2 = + Td0(LTC_BYTE(s2, 3)) ^ + Td1(LTC_BYTE(s1, 2)) ^ + Td2(LTC_BYTE(s0, 1)) ^ + Td3(LTC_BYTE(s3, 0)) ^ + rk[2]; + t3 = + Td0(LTC_BYTE(s3, 3)) ^ + Td1(LTC_BYTE(s2, 2)) ^ + Td2(LTC_BYTE(s1, 1)) ^ + Td3(LTC_BYTE(s0, 0)) ^ + rk[3]; + if (r == Nr-2) { + break; + } + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + rk += 4; + +#else + + /* + * Nr - 1 full rounds: + */ + r = Nr >> 1; + for (;;) { + + t0 = + Td0(LTC_BYTE(s0, 3)) ^ + Td1(LTC_BYTE(s3, 2)) ^ + Td2(LTC_BYTE(s2, 1)) ^ + Td3(LTC_BYTE(s1, 0)) ^ + rk[4]; + t1 = + Td0(LTC_BYTE(s1, 3)) ^ + Td1(LTC_BYTE(s0, 2)) ^ + Td2(LTC_BYTE(s3, 1)) ^ + Td3(LTC_BYTE(s2, 0)) ^ + rk[5]; + t2 = + Td0(LTC_BYTE(s2, 3)) ^ + Td1(LTC_BYTE(s1, 2)) ^ + Td2(LTC_BYTE(s0, 1)) ^ + Td3(LTC_BYTE(s3, 0)) ^ + rk[6]; + t3 = + Td0(LTC_BYTE(s3, 3)) ^ + Td1(LTC_BYTE(s2, 2)) ^ + Td2(LTC_BYTE(s1, 1)) ^ + Td3(LTC_BYTE(s0, 0)) ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + + s0 = + Td0(LTC_BYTE(t0, 3)) ^ + Td1(LTC_BYTE(t3, 2)) ^ + Td2(LTC_BYTE(t2, 1)) ^ + Td3(LTC_BYTE(t1, 0)) ^ + rk[0]; + s1 = + Td0(LTC_BYTE(t1, 3)) ^ + Td1(LTC_BYTE(t0, 2)) ^ + Td2(LTC_BYTE(t3, 1)) ^ + Td3(LTC_BYTE(t2, 0)) ^ + rk[1]; + s2 = + Td0(LTC_BYTE(t2, 3)) ^ + Td1(LTC_BYTE(t1, 2)) ^ + Td2(LTC_BYTE(t0, 1)) ^ + Td3(LTC_BYTE(t3, 0)) ^ + rk[2]; + s3 = + Td0(LTC_BYTE(t3, 3)) ^ + Td1(LTC_BYTE(t2, 2)) ^ + Td2(LTC_BYTE(t1, 1)) ^ + Td3(LTC_BYTE(t0, 0)) ^ + rk[3]; + } +#endif + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[LTC_BYTE(t0, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t3, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t2, 1)] & 0x0000ff00) ^ + (Td4[LTC_BYTE(t1, 0)] & 0x000000ff) ^ + rk[0]; + STORE32H(s0, pt); + s1 = + (Td4[LTC_BYTE(t1, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t0, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t3, 1)] & 0x0000ff00) ^ + (Td4[LTC_BYTE(t2, 0)] & 0x000000ff) ^ + rk[1]; + STORE32H(s1, pt+4); + s2 = + (Td4[LTC_BYTE(t2, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t1, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t0, 1)] & 0x0000ff00) ^ + (Td4[LTC_BYTE(t3, 0)] & 0x000000ff) ^ + rk[2]; + STORE32H(s2, pt+8); + s3 = + (Td4[LTC_BYTE(t3, 3)] & 0xff000000) ^ + (Td4[LTC_BYTE(t2, 2)] & 0x00ff0000) ^ + (Td4[LTC_BYTE(t1, 1)] & 0x0000ff00) ^ + (Td4[LTC_BYTE(t0, 0)] & 0x000000ff) ^ + rk[3]; + STORE32H(s3, pt+12); + + return CRYPT_OK; +} + + +#ifdef LTC_CLEAN_STACK +int ECB_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_rijndael_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); + return err; +} +#endif + +/** + Performs a self-test of the AES block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int ECB_TEST(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + int err; + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } + }, { + 24, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } + }, { + 32, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } + } + }; + + symmetric_key key; + unsigned char tmp[2][16]; + int i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&key, sizeof(key)); + if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key); + rijndael_ecb_decrypt(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +#endif /* ENCRYPT_ONLY */ + + +/** Terminate the context + @param skey The scheduled key +*/ +void ECB_DONE(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int ECB_KS(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } + if (*keysize < 32) { + *keysize = 24; + return CRYPT_OK; + } + *keysize = 32; + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/ciphers/aes/aes_tab.c b/deps/libtomcrypt/src/ciphers/aes/aes_tab.c new file mode 100644 index 0000000..5e59004 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/aes/aes_tab.c @@ -0,0 +1,1022 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* The precomputed tables for AES */ +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +#ifdef LTC_AES_TAB_C + +/** + @file aes_tab.c + AES tables +*/ +static const ulong32 TE0[256] = { + 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, + 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, + 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, + 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, + 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, + 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, + 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, + 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, + 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, + 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, + 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, + 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, + 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, + 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, + 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, + 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, + 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, + 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, + 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, + 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, + 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, + 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, + 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, + 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, + 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, + 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, + 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, + 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, + 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, + 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, + 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, + 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, + 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, + 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, + 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, + 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, + 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, + 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, + 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, + 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, + 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, + 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, + 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, + 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, + 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, + 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, + 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, + 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, + 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, + 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, + 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, + 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, + 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, + 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, + 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, + 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, + 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, + 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, + 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, + 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, + 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, + 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, + 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, + 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, +}; + +#if !defined(PELI_TAB) && defined(LTC_SMALL_CODE) +static const ulong32 Te4[256] = { + 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, + 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, + 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL, + 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL, + 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL, + 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL, + 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL, + 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL, + 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL, + 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL, + 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL, + 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL, + 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL, + 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL, + 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL, + 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL, + 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL, + 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL, + 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL, + 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL, + 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL, + 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL, + 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL, + 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL, + 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL, + 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL, + 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL, + 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL, + 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL, + 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL, + 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL, + 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL, + 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL, + 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL, + 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL, + 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL, + 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL, + 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL, + 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL, + 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL, + 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL, + 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL, + 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL, + 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL, + 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL, + 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL, + 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL, + 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL, + 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL, + 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL, + 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL, + 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL, + 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL, + 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL, + 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL, + 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL, + 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL, + 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL, + 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL, + 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL, + 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL, + 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL, + 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL, + 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, +}; +#endif + +#ifndef ENCRYPT_ONLY + +static const ulong32 TD0[256] = { + 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, + 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, + 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, + 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, + 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, + 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, + 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, + 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, + 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, + 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, + 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, + 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, + 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, + 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, + 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, + 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, + 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, + 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, + 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, + 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, + 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, + 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, + 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, + 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, + 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, + 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, + 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, + 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, + 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, + 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, + 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, + 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, + 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, + 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, + 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, + 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, + 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, + 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, + 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, + 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, + 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, + 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, + 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, + 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, + 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, + 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, + 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, + 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, + 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, + 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, + 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, + 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, + 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, + 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, + 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, + 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, + 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, + 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, + 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, + 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, + 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, + 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, + 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, + 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, +}; + +static const ulong32 Td4[256] = { + 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, + 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, + 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, + 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, + 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, + 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, + 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, + 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, + 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, + 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, + 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, + 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, + 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, + 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, + 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, + 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, + 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, + 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, + 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, + 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, + 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, + 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, + 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, + 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, + 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, + 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, + 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, + 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, + 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, + 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, + 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, + 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, + 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, + 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, + 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, + 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, + 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, + 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, + 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, + 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, + 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, + 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, + 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, + 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, + 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, + 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, + 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, + 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, + 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, + 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, + 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, + 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, + 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, + 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, + 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, + 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, + 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, + 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, + 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, + 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, + 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, + 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, + 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, + 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, +}; + +#endif /* ENCRYPT_ONLY */ + +#ifdef LTC_SMALL_CODE + +#define Te0(x) TE0[x] +#define Te1(x) RORc(TE0[x], 8) +#define Te2(x) RORc(TE0[x], 16) +#define Te3(x) RORc(TE0[x], 24) + +#define Td0(x) TD0[x] +#define Td1(x) RORc(TD0[x], 8) +#define Td2(x) RORc(TD0[x], 16) +#define Td3(x) RORc(TD0[x], 24) + +#define Te4_0 0x000000FF & Te4 +#define Te4_1 0x0000FF00 & Te4 +#define Te4_2 0x00FF0000 & Te4 +#define Te4_3 0xFF000000 & Te4 + +#else + +#define Te0(x) TE0[x] +#define Te1(x) TE1[x] +#define Te2(x) TE2[x] +#define Te3(x) TE3[x] + +#define Td0(x) TD0[x] +#define Td1(x) TD1[x] +#define Td2(x) TD2[x] +#define Td3(x) TD3[x] + +static const ulong32 TE1[256] = { + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, + 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, + 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, + 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, + 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, + 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, + 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, + 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, + 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, + 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, + 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, + 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, + 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, + 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, + 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, + 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, + 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, + 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, + 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, + 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, + 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, + 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, + 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, + 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, + 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, + 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, + 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, + 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, + 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, + 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, + 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, + 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, + 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, + 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, + 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, + 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, + 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, + 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, + 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, + 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, + 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, + 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, + 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, + 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, + 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, + 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, + 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, + 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, + 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, + 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, + 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, + 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, + 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, + 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, + 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, + 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, + 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, + 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, +}; +static const ulong32 TE2[256] = { + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, + 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, + 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, + 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, + 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, + 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, + 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, + 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, + 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, + 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, + 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, + 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, + 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, + 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, + 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, + 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, + 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, + 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, + 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, + 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, + 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, + 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, + 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, + 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, + 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, + 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, + 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, + 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, + 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, + 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, + 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, + 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, + 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, + 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, + 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, + 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, + 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, + 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, + 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, + 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, + 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, + 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, + 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, + 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, + 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, + 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, + 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, + 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, + 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, + 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, + 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, + 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, + 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, + 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, + 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, + 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, + 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, + 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, +}; +static const ulong32 TE3[256] = { + + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, + 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, + 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, + 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, + 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, + 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, + 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, + 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, + 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, + 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, + 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, + 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, + 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, + 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, + 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, + 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, + 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, + 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, + 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, + 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, + 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, + 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, + 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, + 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, + 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, + 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, + 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, + 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, + 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, + 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, + 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, + 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, + 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, + 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, + 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, + 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, + 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, + 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, + 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, + 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, + 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, + 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, + 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, + 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, + 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, + 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, + 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, + 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, + 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, + 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, + 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, + 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, + 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, + 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, + 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, + 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, + 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, + 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, +}; + +#ifndef PELI_TAB +static const ulong32 Te4_0[] = { +0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL, 0x0000006bUL, 0x0000006fUL, 0x000000c5UL, +0x00000030UL, 0x00000001UL, 0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL, 0x00000076UL, +0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL, 0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, +0x000000adUL, 0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL, 0x00000072UL, 0x000000c0UL, +0x000000b7UL, 0x000000fdUL, 0x00000093UL, 0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL, +0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL, 0x000000d8UL, 0x00000031UL, 0x00000015UL, +0x00000004UL, 0x000000c7UL, 0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL, 0x0000009aUL, +0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL, 0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, +0x00000009UL, 0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL, 0x0000005aUL, 0x000000a0UL, +0x00000052UL, 0x0000003bUL, 0x000000d6UL, 0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL, +0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL, 0x000000fcUL, 0x000000b1UL, 0x0000005bUL, +0x0000006aUL, 0x000000cbUL, 0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL, 0x000000cfUL, +0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL, 0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, +0x00000045UL, 0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL, 0x0000009fUL, 0x000000a8UL, +0x00000051UL, 0x000000a3UL, 0x00000040UL, 0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL, +0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL, 0x000000ffUL, 0x000000f3UL, 0x000000d2UL, +0x000000cdUL, 0x0000000cUL, 0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL, 0x00000017UL, +0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL, 0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, +0x00000060UL, 0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL, 0x00000090UL, 0x00000088UL, +0x00000046UL, 0x000000eeUL, 0x000000b8UL, 0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL, +0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL, 0x00000006UL, 0x00000024UL, 0x0000005cUL, +0x000000c2UL, 0x000000d3UL, 0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL, 0x00000079UL, +0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL, 0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, +0x0000006cUL, 0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL, 0x000000aeUL, 0x00000008UL, +0x000000baUL, 0x00000078UL, 0x00000025UL, 0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL, +0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL, 0x000000bdUL, 0x0000008bUL, 0x0000008aUL, +0x00000070UL, 0x0000003eUL, 0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL, 0x0000000eUL, +0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL, 0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, +0x000000e1UL, 0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL, 0x0000008eUL, 0x00000094UL, +0x0000009bUL, 0x0000001eUL, 0x00000087UL, 0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL, +0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL, 0x000000e6UL, 0x00000042UL, 0x00000068UL, +0x00000041UL, 0x00000099UL, 0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL, 0x00000016UL +}; + +static const ulong32 Te4_1[] = { +0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL, 0x00006b00UL, 0x00006f00UL, 0x0000c500UL, +0x00003000UL, 0x00000100UL, 0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL, 0x00007600UL, +0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL, 0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, +0x0000ad00UL, 0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL, 0x00007200UL, 0x0000c000UL, +0x0000b700UL, 0x0000fd00UL, 0x00009300UL, 0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL, +0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL, 0x0000d800UL, 0x00003100UL, 0x00001500UL, +0x00000400UL, 0x0000c700UL, 0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL, 0x00009a00UL, +0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL, 0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, +0x00000900UL, 0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL, 0x00005a00UL, 0x0000a000UL, +0x00005200UL, 0x00003b00UL, 0x0000d600UL, 0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL, +0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL, 0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, +0x00006a00UL, 0x0000cb00UL, 0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL, 0x0000cf00UL, +0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL, 0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, +0x00004500UL, 0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL, 0x00009f00UL, 0x0000a800UL, +0x00005100UL, 0x0000a300UL, 0x00004000UL, 0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL, +0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL, 0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, +0x0000cd00UL, 0x00000c00UL, 0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL, 0x00001700UL, +0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL, 0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, +0x00006000UL, 0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL, 0x00009000UL, 0x00008800UL, +0x00004600UL, 0x0000ee00UL, 0x0000b800UL, 0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL, +0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL, 0x00000600UL, 0x00002400UL, 0x00005c00UL, +0x0000c200UL, 0x0000d300UL, 0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL, 0x00007900UL, +0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL, 0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, +0x00006c00UL, 0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL, 0x0000ae00UL, 0x00000800UL, +0x0000ba00UL, 0x00007800UL, 0x00002500UL, 0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL, +0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL, 0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, +0x00007000UL, 0x00003e00UL, 0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL, 0x00000e00UL, +0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL, 0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, +0x0000e100UL, 0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL, 0x00008e00UL, 0x00009400UL, +0x00009b00UL, 0x00001e00UL, 0x00008700UL, 0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL, +0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL, 0x0000e600UL, 0x00004200UL, 0x00006800UL, +0x00004100UL, 0x00009900UL, 0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL, 0x00001600UL +}; + +static const ulong32 Te4_2[] = { +0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL, 0x006b0000UL, 0x006f0000UL, 0x00c50000UL, +0x00300000UL, 0x00010000UL, 0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL, 0x00760000UL, +0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL, 0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, +0x00ad0000UL, 0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL, 0x00720000UL, 0x00c00000UL, +0x00b70000UL, 0x00fd0000UL, 0x00930000UL, 0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL, +0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL, 0x00d80000UL, 0x00310000UL, 0x00150000UL, +0x00040000UL, 0x00c70000UL, 0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL, 0x009a0000UL, +0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL, 0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, +0x00090000UL, 0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL, 0x005a0000UL, 0x00a00000UL, +0x00520000UL, 0x003b0000UL, 0x00d60000UL, 0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL, +0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL, 0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, +0x006a0000UL, 0x00cb0000UL, 0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL, 0x00cf0000UL, +0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL, 0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, +0x00450000UL, 0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL, 0x009f0000UL, 0x00a80000UL, +0x00510000UL, 0x00a30000UL, 0x00400000UL, 0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL, +0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL, 0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, +0x00cd0000UL, 0x000c0000UL, 0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL, 0x00170000UL, +0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL, 0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, +0x00600000UL, 0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL, 0x00900000UL, 0x00880000UL, +0x00460000UL, 0x00ee0000UL, 0x00b80000UL, 0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL, +0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL, 0x00060000UL, 0x00240000UL, 0x005c0000UL, +0x00c20000UL, 0x00d30000UL, 0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL, 0x00790000UL, +0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL, 0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, +0x006c0000UL, 0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL, 0x00ae0000UL, 0x00080000UL, +0x00ba0000UL, 0x00780000UL, 0x00250000UL, 0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL, +0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL, 0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, +0x00700000UL, 0x003e0000UL, 0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL, 0x000e0000UL, +0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL, 0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, +0x00e10000UL, 0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL, 0x008e0000UL, 0x00940000UL, +0x009b0000UL, 0x001e0000UL, 0x00870000UL, 0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL, +0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL, 0x00e60000UL, 0x00420000UL, 0x00680000UL, +0x00410000UL, 0x00990000UL, 0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL, 0x00160000UL +}; + +static const ulong32 Te4_3[] = { +0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL, 0x6b000000UL, 0x6f000000UL, 0xc5000000UL, +0x30000000UL, 0x01000000UL, 0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL, 0x76000000UL, +0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL, 0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, +0xad000000UL, 0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL, 0x72000000UL, 0xc0000000UL, +0xb7000000UL, 0xfd000000UL, 0x93000000UL, 0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL, +0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL, 0xd8000000UL, 0x31000000UL, 0x15000000UL, +0x04000000UL, 0xc7000000UL, 0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL, 0x9a000000UL, +0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL, 0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, +0x09000000UL, 0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL, 0x5a000000UL, 0xa0000000UL, +0x52000000UL, 0x3b000000UL, 0xd6000000UL, 0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL, +0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL, 0xfc000000UL, 0xb1000000UL, 0x5b000000UL, +0x6a000000UL, 0xcb000000UL, 0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL, 0xcf000000UL, +0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL, 0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, +0x45000000UL, 0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL, 0x9f000000UL, 0xa8000000UL, +0x51000000UL, 0xa3000000UL, 0x40000000UL, 0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL, +0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL, 0xff000000UL, 0xf3000000UL, 0xd2000000UL, +0xcd000000UL, 0x0c000000UL, 0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL, 0x17000000UL, +0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL, 0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, +0x60000000UL, 0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL, 0x90000000UL, 0x88000000UL, +0x46000000UL, 0xee000000UL, 0xb8000000UL, 0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL, +0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL, 0x06000000UL, 0x24000000UL, 0x5c000000UL, +0xc2000000UL, 0xd3000000UL, 0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL, 0x79000000UL, +0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL, 0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, +0x6c000000UL, 0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL, 0xae000000UL, 0x08000000UL, +0xba000000UL, 0x78000000UL, 0x25000000UL, 0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL, +0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL, 0xbd000000UL, 0x8b000000UL, 0x8a000000UL, +0x70000000UL, 0x3e000000UL, 0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL, 0x0e000000UL, +0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL, 0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, +0xe1000000UL, 0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL, 0x8e000000UL, 0x94000000UL, +0x9b000000UL, 0x1e000000UL, 0x87000000UL, 0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL, +0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL, 0xe6000000UL, 0x42000000UL, 0x68000000UL, +0x41000000UL, 0x99000000UL, 0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL, 0x16000000UL +}; +#endif /* pelimac */ + +#ifndef ENCRYPT_ONLY + +static const ulong32 TD1[256] = { + 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, + 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, + 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, + 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, + 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, + 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, + 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, + 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, + 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, + 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, + 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, + 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, + 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, + 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, + 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, + 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, + 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, + 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, + 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, + 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, + 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, + 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, + 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, + 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, + 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, + 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, + 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, + 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, + 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, + 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, + 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, + 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, + 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, + 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, + 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, + 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, + 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, + 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, + 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, + 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, + 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, + 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, + 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, + 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, + 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, + 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, + 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, + 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, + 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, + 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, + 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, + 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, + 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, + 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, + 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, + 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, + 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, + 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, + 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, + 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, + 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, + 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, + 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, + 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, +}; +static const ulong32 TD2[256] = { + 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, + 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, + 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, + 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, + 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, + 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, + 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, + 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, + 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, + 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, + 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, + 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, + 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, + 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, + 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, + 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, + 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, + 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, + 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, + 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, + 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, + 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, + 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, + 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, + 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, + 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, + 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, + 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, + 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, + 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, + 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, + 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, + 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, + 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, + 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, + 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, + 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, + 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, + 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, + 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, + 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, + 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, + 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, + 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, + 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, + 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, + 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, + 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, + 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, + 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, + 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, + 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, + 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, + 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, + 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, + 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, + 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, + 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, + 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, + 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, + 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, + 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, + 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, + 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, +}; +static const ulong32 TD3[256] = { + 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, + 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, + 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, + 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, + 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, + 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, + 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, + 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, + 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, + 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, + 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, + 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, + 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, + 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, + 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, + 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, + 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, + 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, + 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, + 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, + 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, + 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, + 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, + 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, + 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, + 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, + 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, + 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, + 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, + 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, + 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, + 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, + 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, + 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, + 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, + 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, + 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, + 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, + 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, + 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, + 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, + 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, + 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, + 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, + 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, + 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, + 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, + 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, + 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, + 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, + 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, + 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, + 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, + 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, + 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, + 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, + 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, + 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, + 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, + 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, + 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, + 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, + 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, + 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, +}; + +static const ulong32 Tks0[] = { +0x00000000UL, 0x0e090d0bUL, 0x1c121a16UL, 0x121b171dUL, 0x3824342cUL, 0x362d3927UL, 0x24362e3aUL, 0x2a3f2331UL, +0x70486858UL, 0x7e416553UL, 0x6c5a724eUL, 0x62537f45UL, 0x486c5c74UL, 0x4665517fUL, 0x547e4662UL, 0x5a774b69UL, +0xe090d0b0UL, 0xee99ddbbUL, 0xfc82caa6UL, 0xf28bc7adUL, 0xd8b4e49cUL, 0xd6bde997UL, 0xc4a6fe8aUL, 0xcaaff381UL, +0x90d8b8e8UL, 0x9ed1b5e3UL, 0x8ccaa2feUL, 0x82c3aff5UL, 0xa8fc8cc4UL, 0xa6f581cfUL, 0xb4ee96d2UL, 0xbae79bd9UL, +0xdb3bbb7bUL, 0xd532b670UL, 0xc729a16dUL, 0xc920ac66UL, 0xe31f8f57UL, 0xed16825cUL, 0xff0d9541UL, 0xf104984aUL, +0xab73d323UL, 0xa57ade28UL, 0xb761c935UL, 0xb968c43eUL, 0x9357e70fUL, 0x9d5eea04UL, 0x8f45fd19UL, 0x814cf012UL, +0x3bab6bcbUL, 0x35a266c0UL, 0x27b971ddUL, 0x29b07cd6UL, 0x038f5fe7UL, 0x0d8652ecUL, 0x1f9d45f1UL, 0x119448faUL, +0x4be30393UL, 0x45ea0e98UL, 0x57f11985UL, 0x59f8148eUL, 0x73c737bfUL, 0x7dce3ab4UL, 0x6fd52da9UL, 0x61dc20a2UL, +0xad766df6UL, 0xa37f60fdUL, 0xb16477e0UL, 0xbf6d7aebUL, 0x955259daUL, 0x9b5b54d1UL, 0x894043ccUL, 0x87494ec7UL, +0xdd3e05aeUL, 0xd33708a5UL, 0xc12c1fb8UL, 0xcf2512b3UL, 0xe51a3182UL, 0xeb133c89UL, 0xf9082b94UL, 0xf701269fUL, +0x4de6bd46UL, 0x43efb04dUL, 0x51f4a750UL, 0x5ffdaa5bUL, 0x75c2896aUL, 0x7bcb8461UL, 0x69d0937cUL, 0x67d99e77UL, +0x3daed51eUL, 0x33a7d815UL, 0x21bccf08UL, 0x2fb5c203UL, 0x058ae132UL, 0x0b83ec39UL, 0x1998fb24UL, 0x1791f62fUL, +0x764dd68dUL, 0x7844db86UL, 0x6a5fcc9bUL, 0x6456c190UL, 0x4e69e2a1UL, 0x4060efaaUL, 0x527bf8b7UL, 0x5c72f5bcUL, +0x0605bed5UL, 0x080cb3deUL, 0x1a17a4c3UL, 0x141ea9c8UL, 0x3e218af9UL, 0x302887f2UL, 0x223390efUL, 0x2c3a9de4UL, +0x96dd063dUL, 0x98d40b36UL, 0x8acf1c2bUL, 0x84c61120UL, 0xaef93211UL, 0xa0f03f1aUL, 0xb2eb2807UL, 0xbce2250cUL, +0xe6956e65UL, 0xe89c636eUL, 0xfa877473UL, 0xf48e7978UL, 0xdeb15a49UL, 0xd0b85742UL, 0xc2a3405fUL, 0xccaa4d54UL, +0x41ecdaf7UL, 0x4fe5d7fcUL, 0x5dfec0e1UL, 0x53f7cdeaUL, 0x79c8eedbUL, 0x77c1e3d0UL, 0x65daf4cdUL, 0x6bd3f9c6UL, +0x31a4b2afUL, 0x3fadbfa4UL, 0x2db6a8b9UL, 0x23bfa5b2UL, 0x09808683UL, 0x07898b88UL, 0x15929c95UL, 0x1b9b919eUL, +0xa17c0a47UL, 0xaf75074cUL, 0xbd6e1051UL, 0xb3671d5aUL, 0x99583e6bUL, 0x97513360UL, 0x854a247dUL, 0x8b432976UL, +0xd134621fUL, 0xdf3d6f14UL, 0xcd267809UL, 0xc32f7502UL, 0xe9105633UL, 0xe7195b38UL, 0xf5024c25UL, 0xfb0b412eUL, +0x9ad7618cUL, 0x94de6c87UL, 0x86c57b9aUL, 0x88cc7691UL, 0xa2f355a0UL, 0xacfa58abUL, 0xbee14fb6UL, 0xb0e842bdUL, +0xea9f09d4UL, 0xe49604dfUL, 0xf68d13c2UL, 0xf8841ec9UL, 0xd2bb3df8UL, 0xdcb230f3UL, 0xcea927eeUL, 0xc0a02ae5UL, +0x7a47b13cUL, 0x744ebc37UL, 0x6655ab2aUL, 0x685ca621UL, 0x42638510UL, 0x4c6a881bUL, 0x5e719f06UL, 0x5078920dUL, +0x0a0fd964UL, 0x0406d46fUL, 0x161dc372UL, 0x1814ce79UL, 0x322bed48UL, 0x3c22e043UL, 0x2e39f75eUL, 0x2030fa55UL, +0xec9ab701UL, 0xe293ba0aUL, 0xf088ad17UL, 0xfe81a01cUL, 0xd4be832dUL, 0xdab78e26UL, 0xc8ac993bUL, 0xc6a59430UL, +0x9cd2df59UL, 0x92dbd252UL, 0x80c0c54fUL, 0x8ec9c844UL, 0xa4f6eb75UL, 0xaaffe67eUL, 0xb8e4f163UL, 0xb6edfc68UL, +0x0c0a67b1UL, 0x02036abaUL, 0x10187da7UL, 0x1e1170acUL, 0x342e539dUL, 0x3a275e96UL, 0x283c498bUL, 0x26354480UL, +0x7c420fe9UL, 0x724b02e2UL, 0x605015ffUL, 0x6e5918f4UL, 0x44663bc5UL, 0x4a6f36ceUL, 0x587421d3UL, 0x567d2cd8UL, +0x37a10c7aUL, 0x39a80171UL, 0x2bb3166cUL, 0x25ba1b67UL, 0x0f853856UL, 0x018c355dUL, 0x13972240UL, 0x1d9e2f4bUL, +0x47e96422UL, 0x49e06929UL, 0x5bfb7e34UL, 0x55f2733fUL, 0x7fcd500eUL, 0x71c45d05UL, 0x63df4a18UL, 0x6dd64713UL, +0xd731dccaUL, 0xd938d1c1UL, 0xcb23c6dcUL, 0xc52acbd7UL, 0xef15e8e6UL, 0xe11ce5edUL, 0xf307f2f0UL, 0xfd0efffbUL, +0xa779b492UL, 0xa970b999UL, 0xbb6bae84UL, 0xb562a38fUL, 0x9f5d80beUL, 0x91548db5UL, 0x834f9aa8UL, 0x8d4697a3UL +}; + +static const ulong32 Tks1[] = { +0x00000000UL, 0x0b0e090dUL, 0x161c121aUL, 0x1d121b17UL, 0x2c382434UL, 0x27362d39UL, 0x3a24362eUL, 0x312a3f23UL, +0x58704868UL, 0x537e4165UL, 0x4e6c5a72UL, 0x4562537fUL, 0x74486c5cUL, 0x7f466551UL, 0x62547e46UL, 0x695a774bUL, +0xb0e090d0UL, 0xbbee99ddUL, 0xa6fc82caUL, 0xadf28bc7UL, 0x9cd8b4e4UL, 0x97d6bde9UL, 0x8ac4a6feUL, 0x81caaff3UL, +0xe890d8b8UL, 0xe39ed1b5UL, 0xfe8ccaa2UL, 0xf582c3afUL, 0xc4a8fc8cUL, 0xcfa6f581UL, 0xd2b4ee96UL, 0xd9bae79bUL, +0x7bdb3bbbUL, 0x70d532b6UL, 0x6dc729a1UL, 0x66c920acUL, 0x57e31f8fUL, 0x5ced1682UL, 0x41ff0d95UL, 0x4af10498UL, +0x23ab73d3UL, 0x28a57adeUL, 0x35b761c9UL, 0x3eb968c4UL, 0x0f9357e7UL, 0x049d5eeaUL, 0x198f45fdUL, 0x12814cf0UL, +0xcb3bab6bUL, 0xc035a266UL, 0xdd27b971UL, 0xd629b07cUL, 0xe7038f5fUL, 0xec0d8652UL, 0xf11f9d45UL, 0xfa119448UL, +0x934be303UL, 0x9845ea0eUL, 0x8557f119UL, 0x8e59f814UL, 0xbf73c737UL, 0xb47dce3aUL, 0xa96fd52dUL, 0xa261dc20UL, +0xf6ad766dUL, 0xfda37f60UL, 0xe0b16477UL, 0xebbf6d7aUL, 0xda955259UL, 0xd19b5b54UL, 0xcc894043UL, 0xc787494eUL, +0xaedd3e05UL, 0xa5d33708UL, 0xb8c12c1fUL, 0xb3cf2512UL, 0x82e51a31UL, 0x89eb133cUL, 0x94f9082bUL, 0x9ff70126UL, +0x464de6bdUL, 0x4d43efb0UL, 0x5051f4a7UL, 0x5b5ffdaaUL, 0x6a75c289UL, 0x617bcb84UL, 0x7c69d093UL, 0x7767d99eUL, +0x1e3daed5UL, 0x1533a7d8UL, 0x0821bccfUL, 0x032fb5c2UL, 0x32058ae1UL, 0x390b83ecUL, 0x241998fbUL, 0x2f1791f6UL, +0x8d764dd6UL, 0x867844dbUL, 0x9b6a5fccUL, 0x906456c1UL, 0xa14e69e2UL, 0xaa4060efUL, 0xb7527bf8UL, 0xbc5c72f5UL, +0xd50605beUL, 0xde080cb3UL, 0xc31a17a4UL, 0xc8141ea9UL, 0xf93e218aUL, 0xf2302887UL, 0xef223390UL, 0xe42c3a9dUL, +0x3d96dd06UL, 0x3698d40bUL, 0x2b8acf1cUL, 0x2084c611UL, 0x11aef932UL, 0x1aa0f03fUL, 0x07b2eb28UL, 0x0cbce225UL, +0x65e6956eUL, 0x6ee89c63UL, 0x73fa8774UL, 0x78f48e79UL, 0x49deb15aUL, 0x42d0b857UL, 0x5fc2a340UL, 0x54ccaa4dUL, +0xf741ecdaUL, 0xfc4fe5d7UL, 0xe15dfec0UL, 0xea53f7cdUL, 0xdb79c8eeUL, 0xd077c1e3UL, 0xcd65daf4UL, 0xc66bd3f9UL, +0xaf31a4b2UL, 0xa43fadbfUL, 0xb92db6a8UL, 0xb223bfa5UL, 0x83098086UL, 0x8807898bUL, 0x9515929cUL, 0x9e1b9b91UL, +0x47a17c0aUL, 0x4caf7507UL, 0x51bd6e10UL, 0x5ab3671dUL, 0x6b99583eUL, 0x60975133UL, 0x7d854a24UL, 0x768b4329UL, +0x1fd13462UL, 0x14df3d6fUL, 0x09cd2678UL, 0x02c32f75UL, 0x33e91056UL, 0x38e7195bUL, 0x25f5024cUL, 0x2efb0b41UL, +0x8c9ad761UL, 0x8794de6cUL, 0x9a86c57bUL, 0x9188cc76UL, 0xa0a2f355UL, 0xabacfa58UL, 0xb6bee14fUL, 0xbdb0e842UL, +0xd4ea9f09UL, 0xdfe49604UL, 0xc2f68d13UL, 0xc9f8841eUL, 0xf8d2bb3dUL, 0xf3dcb230UL, 0xeecea927UL, 0xe5c0a02aUL, +0x3c7a47b1UL, 0x37744ebcUL, 0x2a6655abUL, 0x21685ca6UL, 0x10426385UL, 0x1b4c6a88UL, 0x065e719fUL, 0x0d507892UL, +0x640a0fd9UL, 0x6f0406d4UL, 0x72161dc3UL, 0x791814ceUL, 0x48322bedUL, 0x433c22e0UL, 0x5e2e39f7UL, 0x552030faUL, +0x01ec9ab7UL, 0x0ae293baUL, 0x17f088adUL, 0x1cfe81a0UL, 0x2dd4be83UL, 0x26dab78eUL, 0x3bc8ac99UL, 0x30c6a594UL, +0x599cd2dfUL, 0x5292dbd2UL, 0x4f80c0c5UL, 0x448ec9c8UL, 0x75a4f6ebUL, 0x7eaaffe6UL, 0x63b8e4f1UL, 0x68b6edfcUL, +0xb10c0a67UL, 0xba02036aUL, 0xa710187dUL, 0xac1e1170UL, 0x9d342e53UL, 0x963a275eUL, 0x8b283c49UL, 0x80263544UL, +0xe97c420fUL, 0xe2724b02UL, 0xff605015UL, 0xf46e5918UL, 0xc544663bUL, 0xce4a6f36UL, 0xd3587421UL, 0xd8567d2cUL, +0x7a37a10cUL, 0x7139a801UL, 0x6c2bb316UL, 0x6725ba1bUL, 0x560f8538UL, 0x5d018c35UL, 0x40139722UL, 0x4b1d9e2fUL, +0x2247e964UL, 0x2949e069UL, 0x345bfb7eUL, 0x3f55f273UL, 0x0e7fcd50UL, 0x0571c45dUL, 0x1863df4aUL, 0x136dd647UL, +0xcad731dcUL, 0xc1d938d1UL, 0xdccb23c6UL, 0xd7c52acbUL, 0xe6ef15e8UL, 0xede11ce5UL, 0xf0f307f2UL, 0xfbfd0effUL, +0x92a779b4UL, 0x99a970b9UL, 0x84bb6baeUL, 0x8fb562a3UL, 0xbe9f5d80UL, 0xb591548dUL, 0xa8834f9aUL, 0xa38d4697UL +}; + +static const ulong32 Tks2[] = { +0x00000000UL, 0x0d0b0e09UL, 0x1a161c12UL, 0x171d121bUL, 0x342c3824UL, 0x3927362dUL, 0x2e3a2436UL, 0x23312a3fUL, +0x68587048UL, 0x65537e41UL, 0x724e6c5aUL, 0x7f456253UL, 0x5c74486cUL, 0x517f4665UL, 0x4662547eUL, 0x4b695a77UL, +0xd0b0e090UL, 0xddbbee99UL, 0xcaa6fc82UL, 0xc7adf28bUL, 0xe49cd8b4UL, 0xe997d6bdUL, 0xfe8ac4a6UL, 0xf381caafUL, +0xb8e890d8UL, 0xb5e39ed1UL, 0xa2fe8ccaUL, 0xaff582c3UL, 0x8cc4a8fcUL, 0x81cfa6f5UL, 0x96d2b4eeUL, 0x9bd9bae7UL, +0xbb7bdb3bUL, 0xb670d532UL, 0xa16dc729UL, 0xac66c920UL, 0x8f57e31fUL, 0x825ced16UL, 0x9541ff0dUL, 0x984af104UL, +0xd323ab73UL, 0xde28a57aUL, 0xc935b761UL, 0xc43eb968UL, 0xe70f9357UL, 0xea049d5eUL, 0xfd198f45UL, 0xf012814cUL, +0x6bcb3babUL, 0x66c035a2UL, 0x71dd27b9UL, 0x7cd629b0UL, 0x5fe7038fUL, 0x52ec0d86UL, 0x45f11f9dUL, 0x48fa1194UL, +0x03934be3UL, 0x0e9845eaUL, 0x198557f1UL, 0x148e59f8UL, 0x37bf73c7UL, 0x3ab47dceUL, 0x2da96fd5UL, 0x20a261dcUL, +0x6df6ad76UL, 0x60fda37fUL, 0x77e0b164UL, 0x7aebbf6dUL, 0x59da9552UL, 0x54d19b5bUL, 0x43cc8940UL, 0x4ec78749UL, +0x05aedd3eUL, 0x08a5d337UL, 0x1fb8c12cUL, 0x12b3cf25UL, 0x3182e51aUL, 0x3c89eb13UL, 0x2b94f908UL, 0x269ff701UL, +0xbd464de6UL, 0xb04d43efUL, 0xa75051f4UL, 0xaa5b5ffdUL, 0x896a75c2UL, 0x84617bcbUL, 0x937c69d0UL, 0x9e7767d9UL, +0xd51e3daeUL, 0xd81533a7UL, 0xcf0821bcUL, 0xc2032fb5UL, 0xe132058aUL, 0xec390b83UL, 0xfb241998UL, 0xf62f1791UL, +0xd68d764dUL, 0xdb867844UL, 0xcc9b6a5fUL, 0xc1906456UL, 0xe2a14e69UL, 0xefaa4060UL, 0xf8b7527bUL, 0xf5bc5c72UL, +0xbed50605UL, 0xb3de080cUL, 0xa4c31a17UL, 0xa9c8141eUL, 0x8af93e21UL, 0x87f23028UL, 0x90ef2233UL, 0x9de42c3aUL, +0x063d96ddUL, 0x0b3698d4UL, 0x1c2b8acfUL, 0x112084c6UL, 0x3211aef9UL, 0x3f1aa0f0UL, 0x2807b2ebUL, 0x250cbce2UL, +0x6e65e695UL, 0x636ee89cUL, 0x7473fa87UL, 0x7978f48eUL, 0x5a49deb1UL, 0x5742d0b8UL, 0x405fc2a3UL, 0x4d54ccaaUL, +0xdaf741ecUL, 0xd7fc4fe5UL, 0xc0e15dfeUL, 0xcdea53f7UL, 0xeedb79c8UL, 0xe3d077c1UL, 0xf4cd65daUL, 0xf9c66bd3UL, +0xb2af31a4UL, 0xbfa43fadUL, 0xa8b92db6UL, 0xa5b223bfUL, 0x86830980UL, 0x8b880789UL, 0x9c951592UL, 0x919e1b9bUL, +0x0a47a17cUL, 0x074caf75UL, 0x1051bd6eUL, 0x1d5ab367UL, 0x3e6b9958UL, 0x33609751UL, 0x247d854aUL, 0x29768b43UL, +0x621fd134UL, 0x6f14df3dUL, 0x7809cd26UL, 0x7502c32fUL, 0x5633e910UL, 0x5b38e719UL, 0x4c25f502UL, 0x412efb0bUL, +0x618c9ad7UL, 0x6c8794deUL, 0x7b9a86c5UL, 0x769188ccUL, 0x55a0a2f3UL, 0x58abacfaUL, 0x4fb6bee1UL, 0x42bdb0e8UL, +0x09d4ea9fUL, 0x04dfe496UL, 0x13c2f68dUL, 0x1ec9f884UL, 0x3df8d2bbUL, 0x30f3dcb2UL, 0x27eecea9UL, 0x2ae5c0a0UL, +0xb13c7a47UL, 0xbc37744eUL, 0xab2a6655UL, 0xa621685cUL, 0x85104263UL, 0x881b4c6aUL, 0x9f065e71UL, 0x920d5078UL, +0xd9640a0fUL, 0xd46f0406UL, 0xc372161dUL, 0xce791814UL, 0xed48322bUL, 0xe0433c22UL, 0xf75e2e39UL, 0xfa552030UL, +0xb701ec9aUL, 0xba0ae293UL, 0xad17f088UL, 0xa01cfe81UL, 0x832dd4beUL, 0x8e26dab7UL, 0x993bc8acUL, 0x9430c6a5UL, +0xdf599cd2UL, 0xd25292dbUL, 0xc54f80c0UL, 0xc8448ec9UL, 0xeb75a4f6UL, 0xe67eaaffUL, 0xf163b8e4UL, 0xfc68b6edUL, +0x67b10c0aUL, 0x6aba0203UL, 0x7da71018UL, 0x70ac1e11UL, 0x539d342eUL, 0x5e963a27UL, 0x498b283cUL, 0x44802635UL, +0x0fe97c42UL, 0x02e2724bUL, 0x15ff6050UL, 0x18f46e59UL, 0x3bc54466UL, 0x36ce4a6fUL, 0x21d35874UL, 0x2cd8567dUL, +0x0c7a37a1UL, 0x017139a8UL, 0x166c2bb3UL, 0x1b6725baUL, 0x38560f85UL, 0x355d018cUL, 0x22401397UL, 0x2f4b1d9eUL, +0x642247e9UL, 0x692949e0UL, 0x7e345bfbUL, 0x733f55f2UL, 0x500e7fcdUL, 0x5d0571c4UL, 0x4a1863dfUL, 0x47136dd6UL, +0xdccad731UL, 0xd1c1d938UL, 0xc6dccb23UL, 0xcbd7c52aUL, 0xe8e6ef15UL, 0xe5ede11cUL, 0xf2f0f307UL, 0xfffbfd0eUL, +0xb492a779UL, 0xb999a970UL, 0xae84bb6bUL, 0xa38fb562UL, 0x80be9f5dUL, 0x8db59154UL, 0x9aa8834fUL, 0x97a38d46UL +}; + +static const ulong32 Tks3[] = { +0x00000000UL, 0x090d0b0eUL, 0x121a161cUL, 0x1b171d12UL, 0x24342c38UL, 0x2d392736UL, 0x362e3a24UL, 0x3f23312aUL, +0x48685870UL, 0x4165537eUL, 0x5a724e6cUL, 0x537f4562UL, 0x6c5c7448UL, 0x65517f46UL, 0x7e466254UL, 0x774b695aUL, +0x90d0b0e0UL, 0x99ddbbeeUL, 0x82caa6fcUL, 0x8bc7adf2UL, 0xb4e49cd8UL, 0xbde997d6UL, 0xa6fe8ac4UL, 0xaff381caUL, +0xd8b8e890UL, 0xd1b5e39eUL, 0xcaa2fe8cUL, 0xc3aff582UL, 0xfc8cc4a8UL, 0xf581cfa6UL, 0xee96d2b4UL, 0xe79bd9baUL, +0x3bbb7bdbUL, 0x32b670d5UL, 0x29a16dc7UL, 0x20ac66c9UL, 0x1f8f57e3UL, 0x16825cedUL, 0x0d9541ffUL, 0x04984af1UL, +0x73d323abUL, 0x7ade28a5UL, 0x61c935b7UL, 0x68c43eb9UL, 0x57e70f93UL, 0x5eea049dUL, 0x45fd198fUL, 0x4cf01281UL, +0xab6bcb3bUL, 0xa266c035UL, 0xb971dd27UL, 0xb07cd629UL, 0x8f5fe703UL, 0x8652ec0dUL, 0x9d45f11fUL, 0x9448fa11UL, +0xe303934bUL, 0xea0e9845UL, 0xf1198557UL, 0xf8148e59UL, 0xc737bf73UL, 0xce3ab47dUL, 0xd52da96fUL, 0xdc20a261UL, +0x766df6adUL, 0x7f60fda3UL, 0x6477e0b1UL, 0x6d7aebbfUL, 0x5259da95UL, 0x5b54d19bUL, 0x4043cc89UL, 0x494ec787UL, +0x3e05aeddUL, 0x3708a5d3UL, 0x2c1fb8c1UL, 0x2512b3cfUL, 0x1a3182e5UL, 0x133c89ebUL, 0x082b94f9UL, 0x01269ff7UL, +0xe6bd464dUL, 0xefb04d43UL, 0xf4a75051UL, 0xfdaa5b5fUL, 0xc2896a75UL, 0xcb84617bUL, 0xd0937c69UL, 0xd99e7767UL, +0xaed51e3dUL, 0xa7d81533UL, 0xbccf0821UL, 0xb5c2032fUL, 0x8ae13205UL, 0x83ec390bUL, 0x98fb2419UL, 0x91f62f17UL, +0x4dd68d76UL, 0x44db8678UL, 0x5fcc9b6aUL, 0x56c19064UL, 0x69e2a14eUL, 0x60efaa40UL, 0x7bf8b752UL, 0x72f5bc5cUL, +0x05bed506UL, 0x0cb3de08UL, 0x17a4c31aUL, 0x1ea9c814UL, 0x218af93eUL, 0x2887f230UL, 0x3390ef22UL, 0x3a9de42cUL, +0xdd063d96UL, 0xd40b3698UL, 0xcf1c2b8aUL, 0xc6112084UL, 0xf93211aeUL, 0xf03f1aa0UL, 0xeb2807b2UL, 0xe2250cbcUL, +0x956e65e6UL, 0x9c636ee8UL, 0x877473faUL, 0x8e7978f4UL, 0xb15a49deUL, 0xb85742d0UL, 0xa3405fc2UL, 0xaa4d54ccUL, +0xecdaf741UL, 0xe5d7fc4fUL, 0xfec0e15dUL, 0xf7cdea53UL, 0xc8eedb79UL, 0xc1e3d077UL, 0xdaf4cd65UL, 0xd3f9c66bUL, +0xa4b2af31UL, 0xadbfa43fUL, 0xb6a8b92dUL, 0xbfa5b223UL, 0x80868309UL, 0x898b8807UL, 0x929c9515UL, 0x9b919e1bUL, +0x7c0a47a1UL, 0x75074cafUL, 0x6e1051bdUL, 0x671d5ab3UL, 0x583e6b99UL, 0x51336097UL, 0x4a247d85UL, 0x4329768bUL, +0x34621fd1UL, 0x3d6f14dfUL, 0x267809cdUL, 0x2f7502c3UL, 0x105633e9UL, 0x195b38e7UL, 0x024c25f5UL, 0x0b412efbUL, +0xd7618c9aUL, 0xde6c8794UL, 0xc57b9a86UL, 0xcc769188UL, 0xf355a0a2UL, 0xfa58abacUL, 0xe14fb6beUL, 0xe842bdb0UL, +0x9f09d4eaUL, 0x9604dfe4UL, 0x8d13c2f6UL, 0x841ec9f8UL, 0xbb3df8d2UL, 0xb230f3dcUL, 0xa927eeceUL, 0xa02ae5c0UL, +0x47b13c7aUL, 0x4ebc3774UL, 0x55ab2a66UL, 0x5ca62168UL, 0x63851042UL, 0x6a881b4cUL, 0x719f065eUL, 0x78920d50UL, +0x0fd9640aUL, 0x06d46f04UL, 0x1dc37216UL, 0x14ce7918UL, 0x2bed4832UL, 0x22e0433cUL, 0x39f75e2eUL, 0x30fa5520UL, +0x9ab701ecUL, 0x93ba0ae2UL, 0x88ad17f0UL, 0x81a01cfeUL, 0xbe832dd4UL, 0xb78e26daUL, 0xac993bc8UL, 0xa59430c6UL, +0xd2df599cUL, 0xdbd25292UL, 0xc0c54f80UL, 0xc9c8448eUL, 0xf6eb75a4UL, 0xffe67eaaUL, 0xe4f163b8UL, 0xedfc68b6UL, +0x0a67b10cUL, 0x036aba02UL, 0x187da710UL, 0x1170ac1eUL, 0x2e539d34UL, 0x275e963aUL, 0x3c498b28UL, 0x35448026UL, +0x420fe97cUL, 0x4b02e272UL, 0x5015ff60UL, 0x5918f46eUL, 0x663bc544UL, 0x6f36ce4aUL, 0x7421d358UL, 0x7d2cd856UL, +0xa10c7a37UL, 0xa8017139UL, 0xb3166c2bUL, 0xba1b6725UL, 0x8538560fUL, 0x8c355d01UL, 0x97224013UL, 0x9e2f4b1dUL, +0xe9642247UL, 0xe0692949UL, 0xfb7e345bUL, 0xf2733f55UL, 0xcd500e7fUL, 0xc45d0571UL, 0xdf4a1863UL, 0xd647136dUL, +0x31dccad7UL, 0x38d1c1d9UL, 0x23c6dccbUL, 0x2acbd7c5UL, 0x15e8e6efUL, 0x1ce5ede1UL, 0x07f2f0f3UL, 0x0efffbfdUL, +0x79b492a7UL, 0x70b999a9UL, 0x6bae84bbUL, 0x62a38fb5UL, 0x5d80be9fUL, 0x548db591UL, 0x4f9aa883UL, 0x4697a38dUL +}; + +#endif /* ENCRYPT_ONLY */ + +#endif /* SMALL CODE */ + +#ifndef PELI_TAB +static const ulong32 rcon[] = { + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + 0x1B000000UL, 0x36000000UL, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; +#endif + +#endif /* LTC_AES_TAB_C */ diff --git a/deps/libtomcrypt/src/ciphers/anubis.c b/deps/libtomcrypt/src/ciphers/anubis.c new file mode 100644 index 0000000..f6a1c58 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/anubis.c @@ -0,0 +1,1550 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file anubis.c + Anubis implementation derived from public domain source + Authors: Paulo S.L.M. Barreto and Vincent Rijmen. +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_ANUBIS + +const struct ltc_cipher_descriptor anubis_desc = { + "anubis", + 19, + 16, 40, 16, 12, + &anubis_setup, + &anubis_ecb_encrypt, + &anubis_ecb_decrypt, + &anubis_test, + &anubis_done, + &anubis_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#define MAX_N 10 + +/* + * Though Anubis is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ +#if defined(LTC_ANUBIS_TWEAK) + +static const ulong32 T0[256] = { + 0xba69d2bbU, 0x54a84de5U, 0x2f5ebce2U, 0x74e8cd25U, + 0x53a651f7U, 0xd3bb6bd0U, 0xd2b96fd6U, 0x4d9a29b3U, + 0x50a05dfdU, 0xac458acfU, 0x8d070e09U, 0xbf63c6a5U, + 0x70e0dd3dU, 0x52a455f1U, 0x9a29527bU, 0x4c982db5U, + 0xeac98f46U, 0xd5b773c4U, 0x97336655U, 0xd1bf63dcU, + 0x3366ccaaU, 0x51a259fbU, 0x5bb671c7U, 0xa651a2f3U, + 0xdea15ffeU, 0x48903dadU, 0xa84d9ad7U, 0x992f5e71U, + 0xdbab4be0U, 0x3264c8acU, 0xb773e695U, 0xfce5d732U, + 0xe3dbab70U, 0x9e214263U, 0x913f7e41U, 0x9b2b567dU, + 0xe2d9af76U, 0xbb6bd6bdU, 0x4182199bU, 0x6edca579U, + 0xa557aef9U, 0xcb8b0b80U, 0x6bd6b167U, 0x95376e59U, + 0xa15fbee1U, 0xf3fbeb10U, 0xb17ffe81U, 0x0204080cU, + 0xcc851792U, 0xc49537a2U, 0x1d3a744eU, 0x14285078U, + 0xc39b2bb0U, 0x63c69157U, 0xdaa94fe6U, 0x5dba69d3U, + 0x5fbe61dfU, 0xdca557f2U, 0x7dfae913U, 0xcd871394U, + 0x7ffee11fU, 0x5ab475c1U, 0x6cd8ad75U, 0x5cb86dd5U, + 0xf7f3fb08U, 0x264c98d4U, 0xffe3db38U, 0xedc79354U, + 0xe8cd874aU, 0x9d274e69U, 0x6fdea17fU, 0x8e010203U, + 0x19326456U, 0xa05dbae7U, 0xf0fde71aU, 0x890f1e11U, + 0x0f1e3c22U, 0x070e1c12U, 0xaf4386c5U, 0xfbebcb20U, + 0x08102030U, 0x152a547eU, 0x0d1a342eU, 0x04081018U, + 0x01020406U, 0x64c88d45U, 0xdfa35bf8U, 0x76ecc529U, + 0x79f2f90bU, 0xdda753f4U, 0x3d7af48eU, 0x162c5874U, + 0x3f7efc82U, 0x376edcb2U, 0x6ddaa973U, 0x3870e090U, + 0xb96fdeb1U, 0x73e6d137U, 0xe9cf834cU, 0x356ad4beU, + 0x55aa49e3U, 0x71e2d93bU, 0x7bf6f107U, 0x8c050a0fU, + 0x72e4d531U, 0x880d1a17U, 0xf6f1ff0eU, 0x2a54a8fcU, + 0x3e7cf884U, 0x5ebc65d9U, 0x274e9cd2U, 0x468c0589U, + 0x0c183028U, 0x65ca8943U, 0x68d0bd6dU, 0x61c2995bU, + 0x03060c0aU, 0xc19f23bcU, 0x57ae41efU, 0xd6b17fceU, + 0xd9af43ecU, 0x58b07dcdU, 0xd8ad47eaU, 0x66cc8549U, + 0xd7b37bc8U, 0x3a74e89cU, 0xc88d078aU, 0x3c78f088U, + 0xfae9cf26U, 0x96316253U, 0xa753a6f5U, 0x982d5a77U, + 0xecc59752U, 0xb86ddab7U, 0xc7933ba8U, 0xae4182c3U, + 0x69d2b96bU, 0x4b9631a7U, 0xab4b96ddU, 0xa94f9ed1U, + 0x67ce814fU, 0x0a14283cU, 0x478e018fU, 0xf2f9ef16U, + 0xb577ee99U, 0x224488ccU, 0xe5d7b364U, 0xeec19f5eU, + 0xbe61c2a3U, 0x2b56acfaU, 0x811f3e21U, 0x1224486cU, + 0x831b362dU, 0x1b366c5aU, 0x0e1c3824U, 0x23468ccaU, + 0xf5f7f304U, 0x458a0983U, 0x214284c6U, 0xce811f9eU, + 0x499239abU, 0x2c58b0e8U, 0xf9efc32cU, 0xe6d1bf6eU, + 0xb671e293U, 0x2850a0f0U, 0x172e5c72U, 0x8219322bU, + 0x1a34685cU, 0x8b0b161dU, 0xfee1df3eU, 0x8a09121bU, + 0x09122436U, 0xc98f038cU, 0x87132635U, 0x4e9c25b9U, + 0xe1dfa37cU, 0x2e5cb8e4U, 0xe4d5b762U, 0xe0dda77aU, + 0xebcb8b40U, 0x903d7a47U, 0xa455aaffU, 0x1e3c7844U, + 0x85172e39U, 0x60c09d5dU, 0x00000000U, 0x254a94deU, + 0xf4f5f702U, 0xf1ffe31cU, 0x94356a5fU, 0x0b162c3aU, + 0xe7d3bb68U, 0x75eac923U, 0xefc39b58U, 0x3468d0b8U, + 0x3162c4a6U, 0xd4b577c2U, 0xd0bd67daU, 0x86112233U, + 0x7efce519U, 0xad478ec9U, 0xfde7d334U, 0x2952a4f6U, + 0x3060c0a0U, 0x3b76ec9aU, 0x9f234665U, 0xf8edc72aU, + 0xc6913faeU, 0x13264c6aU, 0x060c1814U, 0x050a141eU, + 0xc59733a4U, 0x11224466U, 0x77eec12fU, 0x7cf8ed15U, + 0x7af4f501U, 0x78f0fd0dU, 0x366cd8b4U, 0x1c387048U, + 0x3972e496U, 0x59b279cbU, 0x18306050U, 0x56ac45e9U, + 0xb37bf68dU, 0xb07dfa87U, 0x244890d8U, 0x204080c0U, + 0xb279f28bU, 0x9239724bU, 0xa35bb6edU, 0xc09d27baU, + 0x44880d85U, 0x62c49551U, 0x10204060U, 0xb475ea9fU, + 0x84152a3fU, 0x43861197U, 0x933b764dU, 0xc2992fb6U, + 0x4a9435a1U, 0xbd67cea9U, 0x8f030605U, 0x2d5ab4eeU, + 0xbc65caafU, 0x9c254a6fU, 0x6ad4b561U, 0x40801d9dU, + 0xcf831b98U, 0xa259b2ebU, 0x801d3a27U, 0x4f9e21bfU, + 0x1f3e7c42U, 0xca890f86U, 0xaa4992dbU, 0x42841591U, +}; + +static const ulong32 T1[256] = { + 0x69babbd2U, 0xa854e54dU, 0x5e2fe2bcU, 0xe87425cdU, + 0xa653f751U, 0xbbd3d06bU, 0xb9d2d66fU, 0x9a4db329U, + 0xa050fd5dU, 0x45accf8aU, 0x078d090eU, 0x63bfa5c6U, + 0xe0703dddU, 0xa452f155U, 0x299a7b52U, 0x984cb52dU, + 0xc9ea468fU, 0xb7d5c473U, 0x33975566U, 0xbfd1dc63U, + 0x6633aaccU, 0xa251fb59U, 0xb65bc771U, 0x51a6f3a2U, + 0xa1defe5fU, 0x9048ad3dU, 0x4da8d79aU, 0x2f99715eU, + 0xabdbe04bU, 0x6432acc8U, 0x73b795e6U, 0xe5fc32d7U, + 0xdbe370abU, 0x219e6342U, 0x3f91417eU, 0x2b9b7d56U, + 0xd9e276afU, 0x6bbbbdd6U, 0x82419b19U, 0xdc6e79a5U, + 0x57a5f9aeU, 0x8bcb800bU, 0xd66b67b1U, 0x3795596eU, + 0x5fa1e1beU, 0xfbf310ebU, 0x7fb181feU, 0x04020c08U, + 0x85cc9217U, 0x95c4a237U, 0x3a1d4e74U, 0x28147850U, + 0x9bc3b02bU, 0xc6635791U, 0xa9dae64fU, 0xba5dd369U, + 0xbe5fdf61U, 0xa5dcf257U, 0xfa7d13e9U, 0x87cd9413U, + 0xfe7f1fe1U, 0xb45ac175U, 0xd86c75adU, 0xb85cd56dU, + 0xf3f708fbU, 0x4c26d498U, 0xe3ff38dbU, 0xc7ed5493U, + 0xcde84a87U, 0x279d694eU, 0xde6f7fa1U, 0x018e0302U, + 0x32195664U, 0x5da0e7baU, 0xfdf01ae7U, 0x0f89111eU, + 0x1e0f223cU, 0x0e07121cU, 0x43afc586U, 0xebfb20cbU, + 0x10083020U, 0x2a157e54U, 0x1a0d2e34U, 0x08041810U, + 0x02010604U, 0xc864458dU, 0xa3dff85bU, 0xec7629c5U, + 0xf2790bf9U, 0xa7ddf453U, 0x7a3d8ef4U, 0x2c167458U, + 0x7e3f82fcU, 0x6e37b2dcU, 0xda6d73a9U, 0x703890e0U, + 0x6fb9b1deU, 0xe67337d1U, 0xcfe94c83U, 0x6a35bed4U, + 0xaa55e349U, 0xe2713bd9U, 0xf67b07f1U, 0x058c0f0aU, + 0xe47231d5U, 0x0d88171aU, 0xf1f60effU, 0x542afca8U, + 0x7c3e84f8U, 0xbc5ed965U, 0x4e27d29cU, 0x8c468905U, + 0x180c2830U, 0xca654389U, 0xd0686dbdU, 0xc2615b99U, + 0x06030a0cU, 0x9fc1bc23U, 0xae57ef41U, 0xb1d6ce7fU, + 0xafd9ec43U, 0xb058cd7dU, 0xadd8ea47U, 0xcc664985U, + 0xb3d7c87bU, 0x743a9ce8U, 0x8dc88a07U, 0x783c88f0U, + 0xe9fa26cfU, 0x31965362U, 0x53a7f5a6U, 0x2d98775aU, + 0xc5ec5297U, 0x6db8b7daU, 0x93c7a83bU, 0x41aec382U, + 0xd2696bb9U, 0x964ba731U, 0x4babdd96U, 0x4fa9d19eU, + 0xce674f81U, 0x140a3c28U, 0x8e478f01U, 0xf9f216efU, + 0x77b599eeU, 0x4422cc88U, 0xd7e564b3U, 0xc1ee5e9fU, + 0x61bea3c2U, 0x562bfaacU, 0x1f81213eU, 0x24126c48U, + 0x1b832d36U, 0x361b5a6cU, 0x1c0e2438U, 0x4623ca8cU, + 0xf7f504f3U, 0x8a458309U, 0x4221c684U, 0x81ce9e1fU, + 0x9249ab39U, 0x582ce8b0U, 0xeff92cc3U, 0xd1e66ebfU, + 0x71b693e2U, 0x5028f0a0U, 0x2e17725cU, 0x19822b32U, + 0x341a5c68U, 0x0b8b1d16U, 0xe1fe3edfU, 0x098a1b12U, + 0x12093624U, 0x8fc98c03U, 0x13873526U, 0x9c4eb925U, + 0xdfe17ca3U, 0x5c2ee4b8U, 0xd5e462b7U, 0xdde07aa7U, + 0xcbeb408bU, 0x3d90477aU, 0x55a4ffaaU, 0x3c1e4478U, + 0x1785392eU, 0xc0605d9dU, 0x00000000U, 0x4a25de94U, + 0xf5f402f7U, 0xfff11ce3U, 0x35945f6aU, 0x160b3a2cU, + 0xd3e768bbU, 0xea7523c9U, 0xc3ef589bU, 0x6834b8d0U, + 0x6231a6c4U, 0xb5d4c277U, 0xbdd0da67U, 0x11863322U, + 0xfc7e19e5U, 0x47adc98eU, 0xe7fd34d3U, 0x5229f6a4U, + 0x6030a0c0U, 0x763b9aecU, 0x239f6546U, 0xedf82ac7U, + 0x91c6ae3fU, 0x26136a4cU, 0x0c061418U, 0x0a051e14U, + 0x97c5a433U, 0x22116644U, 0xee772fc1U, 0xf87c15edU, + 0xf47a01f5U, 0xf0780dfdU, 0x6c36b4d8U, 0x381c4870U, + 0x723996e4U, 0xb259cb79U, 0x30185060U, 0xac56e945U, + 0x7bb38df6U, 0x7db087faU, 0x4824d890U, 0x4020c080U, + 0x79b28bf2U, 0x39924b72U, 0x5ba3edb6U, 0x9dc0ba27U, + 0x8844850dU, 0xc4625195U, 0x20106040U, 0x75b49feaU, + 0x15843f2aU, 0x86439711U, 0x3b934d76U, 0x99c2b62fU, + 0x944aa135U, 0x67bda9ceU, 0x038f0506U, 0x5a2deeb4U, + 0x65bcafcaU, 0x259c6f4aU, 0xd46a61b5U, 0x80409d1dU, + 0x83cf981bU, 0x59a2ebb2U, 0x1d80273aU, 0x9e4fbf21U, + 0x3e1f427cU, 0x89ca860fU, 0x49aadb92U, 0x84429115U, +}; + +static const ulong32 T2[256] = { + 0xd2bbba69U, 0x4de554a8U, 0xbce22f5eU, 0xcd2574e8U, + 0x51f753a6U, 0x6bd0d3bbU, 0x6fd6d2b9U, 0x29b34d9aU, + 0x5dfd50a0U, 0x8acfac45U, 0x0e098d07U, 0xc6a5bf63U, + 0xdd3d70e0U, 0x55f152a4U, 0x527b9a29U, 0x2db54c98U, + 0x8f46eac9U, 0x73c4d5b7U, 0x66559733U, 0x63dcd1bfU, + 0xccaa3366U, 0x59fb51a2U, 0x71c75bb6U, 0xa2f3a651U, + 0x5ffedea1U, 0x3dad4890U, 0x9ad7a84dU, 0x5e71992fU, + 0x4be0dbabU, 0xc8ac3264U, 0xe695b773U, 0xd732fce5U, + 0xab70e3dbU, 0x42639e21U, 0x7e41913fU, 0x567d9b2bU, + 0xaf76e2d9U, 0xd6bdbb6bU, 0x199b4182U, 0xa5796edcU, + 0xaef9a557U, 0x0b80cb8bU, 0xb1676bd6U, 0x6e599537U, + 0xbee1a15fU, 0xeb10f3fbU, 0xfe81b17fU, 0x080c0204U, + 0x1792cc85U, 0x37a2c495U, 0x744e1d3aU, 0x50781428U, + 0x2bb0c39bU, 0x915763c6U, 0x4fe6daa9U, 0x69d35dbaU, + 0x61df5fbeU, 0x57f2dca5U, 0xe9137dfaU, 0x1394cd87U, + 0xe11f7ffeU, 0x75c15ab4U, 0xad756cd8U, 0x6dd55cb8U, + 0xfb08f7f3U, 0x98d4264cU, 0xdb38ffe3U, 0x9354edc7U, + 0x874ae8cdU, 0x4e699d27U, 0xa17f6fdeU, 0x02038e01U, + 0x64561932U, 0xbae7a05dU, 0xe71af0fdU, 0x1e11890fU, + 0x3c220f1eU, 0x1c12070eU, 0x86c5af43U, 0xcb20fbebU, + 0x20300810U, 0x547e152aU, 0x342e0d1aU, 0x10180408U, + 0x04060102U, 0x8d4564c8U, 0x5bf8dfa3U, 0xc52976ecU, + 0xf90b79f2U, 0x53f4dda7U, 0xf48e3d7aU, 0x5874162cU, + 0xfc823f7eU, 0xdcb2376eU, 0xa9736ddaU, 0xe0903870U, + 0xdeb1b96fU, 0xd13773e6U, 0x834ce9cfU, 0xd4be356aU, + 0x49e355aaU, 0xd93b71e2U, 0xf1077bf6U, 0x0a0f8c05U, + 0xd53172e4U, 0x1a17880dU, 0xff0ef6f1U, 0xa8fc2a54U, + 0xf8843e7cU, 0x65d95ebcU, 0x9cd2274eU, 0x0589468cU, + 0x30280c18U, 0x894365caU, 0xbd6d68d0U, 0x995b61c2U, + 0x0c0a0306U, 0x23bcc19fU, 0x41ef57aeU, 0x7fced6b1U, + 0x43ecd9afU, 0x7dcd58b0U, 0x47ead8adU, 0x854966ccU, + 0x7bc8d7b3U, 0xe89c3a74U, 0x078ac88dU, 0xf0883c78U, + 0xcf26fae9U, 0x62539631U, 0xa6f5a753U, 0x5a77982dU, + 0x9752ecc5U, 0xdab7b86dU, 0x3ba8c793U, 0x82c3ae41U, + 0xb96b69d2U, 0x31a74b96U, 0x96ddab4bU, 0x9ed1a94fU, + 0x814f67ceU, 0x283c0a14U, 0x018f478eU, 0xef16f2f9U, + 0xee99b577U, 0x88cc2244U, 0xb364e5d7U, 0x9f5eeec1U, + 0xc2a3be61U, 0xacfa2b56U, 0x3e21811fU, 0x486c1224U, + 0x362d831bU, 0x6c5a1b36U, 0x38240e1cU, 0x8cca2346U, + 0xf304f5f7U, 0x0983458aU, 0x84c62142U, 0x1f9ece81U, + 0x39ab4992U, 0xb0e82c58U, 0xc32cf9efU, 0xbf6ee6d1U, + 0xe293b671U, 0xa0f02850U, 0x5c72172eU, 0x322b8219U, + 0x685c1a34U, 0x161d8b0bU, 0xdf3efee1U, 0x121b8a09U, + 0x24360912U, 0x038cc98fU, 0x26358713U, 0x25b94e9cU, + 0xa37ce1dfU, 0xb8e42e5cU, 0xb762e4d5U, 0xa77ae0ddU, + 0x8b40ebcbU, 0x7a47903dU, 0xaaffa455U, 0x78441e3cU, + 0x2e398517U, 0x9d5d60c0U, 0x00000000U, 0x94de254aU, + 0xf702f4f5U, 0xe31cf1ffU, 0x6a5f9435U, 0x2c3a0b16U, + 0xbb68e7d3U, 0xc92375eaU, 0x9b58efc3U, 0xd0b83468U, + 0xc4a63162U, 0x77c2d4b5U, 0x67dad0bdU, 0x22338611U, + 0xe5197efcU, 0x8ec9ad47U, 0xd334fde7U, 0xa4f62952U, + 0xc0a03060U, 0xec9a3b76U, 0x46659f23U, 0xc72af8edU, + 0x3faec691U, 0x4c6a1326U, 0x1814060cU, 0x141e050aU, + 0x33a4c597U, 0x44661122U, 0xc12f77eeU, 0xed157cf8U, + 0xf5017af4U, 0xfd0d78f0U, 0xd8b4366cU, 0x70481c38U, + 0xe4963972U, 0x79cb59b2U, 0x60501830U, 0x45e956acU, + 0xf68db37bU, 0xfa87b07dU, 0x90d82448U, 0x80c02040U, + 0xf28bb279U, 0x724b9239U, 0xb6eda35bU, 0x27bac09dU, + 0x0d854488U, 0x955162c4U, 0x40601020U, 0xea9fb475U, + 0x2a3f8415U, 0x11974386U, 0x764d933bU, 0x2fb6c299U, + 0x35a14a94U, 0xcea9bd67U, 0x06058f03U, 0xb4ee2d5aU, + 0xcaafbc65U, 0x4a6f9c25U, 0xb5616ad4U, 0x1d9d4080U, + 0x1b98cf83U, 0xb2eba259U, 0x3a27801dU, 0x21bf4f9eU, + 0x7c421f3eU, 0x0f86ca89U, 0x92dbaa49U, 0x15914284U, +}; + +static const ulong32 T3[256] = { + 0xbbd269baU, 0xe54da854U, 0xe2bc5e2fU, 0x25cde874U, + 0xf751a653U, 0xd06bbbd3U, 0xd66fb9d2U, 0xb3299a4dU, + 0xfd5da050U, 0xcf8a45acU, 0x090e078dU, 0xa5c663bfU, + 0x3ddde070U, 0xf155a452U, 0x7b52299aU, 0xb52d984cU, + 0x468fc9eaU, 0xc473b7d5U, 0x55663397U, 0xdc63bfd1U, + 0xaacc6633U, 0xfb59a251U, 0xc771b65bU, 0xf3a251a6U, + 0xfe5fa1deU, 0xad3d9048U, 0xd79a4da8U, 0x715e2f99U, + 0xe04babdbU, 0xacc86432U, 0x95e673b7U, 0x32d7e5fcU, + 0x70abdbe3U, 0x6342219eU, 0x417e3f91U, 0x7d562b9bU, + 0x76afd9e2U, 0xbdd66bbbU, 0x9b198241U, 0x79a5dc6eU, + 0xf9ae57a5U, 0x800b8bcbU, 0x67b1d66bU, 0x596e3795U, + 0xe1be5fa1U, 0x10ebfbf3U, 0x81fe7fb1U, 0x0c080402U, + 0x921785ccU, 0xa23795c4U, 0x4e743a1dU, 0x78502814U, + 0xb02b9bc3U, 0x5791c663U, 0xe64fa9daU, 0xd369ba5dU, + 0xdf61be5fU, 0xf257a5dcU, 0x13e9fa7dU, 0x941387cdU, + 0x1fe1fe7fU, 0xc175b45aU, 0x75add86cU, 0xd56db85cU, + 0x08fbf3f7U, 0xd4984c26U, 0x38dbe3ffU, 0x5493c7edU, + 0x4a87cde8U, 0x694e279dU, 0x7fa1de6fU, 0x0302018eU, + 0x56643219U, 0xe7ba5da0U, 0x1ae7fdf0U, 0x111e0f89U, + 0x223c1e0fU, 0x121c0e07U, 0xc58643afU, 0x20cbebfbU, + 0x30201008U, 0x7e542a15U, 0x2e341a0dU, 0x18100804U, + 0x06040201U, 0x458dc864U, 0xf85ba3dfU, 0x29c5ec76U, + 0x0bf9f279U, 0xf453a7ddU, 0x8ef47a3dU, 0x74582c16U, + 0x82fc7e3fU, 0xb2dc6e37U, 0x73a9da6dU, 0x90e07038U, + 0xb1de6fb9U, 0x37d1e673U, 0x4c83cfe9U, 0xbed46a35U, + 0xe349aa55U, 0x3bd9e271U, 0x07f1f67bU, 0x0f0a058cU, + 0x31d5e472U, 0x171a0d88U, 0x0efff1f6U, 0xfca8542aU, + 0x84f87c3eU, 0xd965bc5eU, 0xd29c4e27U, 0x89058c46U, + 0x2830180cU, 0x4389ca65U, 0x6dbdd068U, 0x5b99c261U, + 0x0a0c0603U, 0xbc239fc1U, 0xef41ae57U, 0xce7fb1d6U, + 0xec43afd9U, 0xcd7db058U, 0xea47add8U, 0x4985cc66U, + 0xc87bb3d7U, 0x9ce8743aU, 0x8a078dc8U, 0x88f0783cU, + 0x26cfe9faU, 0x53623196U, 0xf5a653a7U, 0x775a2d98U, + 0x5297c5ecU, 0xb7da6db8U, 0xa83b93c7U, 0xc38241aeU, + 0x6bb9d269U, 0xa731964bU, 0xdd964babU, 0xd19e4fa9U, + 0x4f81ce67U, 0x3c28140aU, 0x8f018e47U, 0x16eff9f2U, + 0x99ee77b5U, 0xcc884422U, 0x64b3d7e5U, 0x5e9fc1eeU, + 0xa3c261beU, 0xfaac562bU, 0x213e1f81U, 0x6c482412U, + 0x2d361b83U, 0x5a6c361bU, 0x24381c0eU, 0xca8c4623U, + 0x04f3f7f5U, 0x83098a45U, 0xc6844221U, 0x9e1f81ceU, + 0xab399249U, 0xe8b0582cU, 0x2cc3eff9U, 0x6ebfd1e6U, + 0x93e271b6U, 0xf0a05028U, 0x725c2e17U, 0x2b321982U, + 0x5c68341aU, 0x1d160b8bU, 0x3edfe1feU, 0x1b12098aU, + 0x36241209U, 0x8c038fc9U, 0x35261387U, 0xb9259c4eU, + 0x7ca3dfe1U, 0xe4b85c2eU, 0x62b7d5e4U, 0x7aa7dde0U, + 0x408bcbebU, 0x477a3d90U, 0xffaa55a4U, 0x44783c1eU, + 0x392e1785U, 0x5d9dc060U, 0x00000000U, 0xde944a25U, + 0x02f7f5f4U, 0x1ce3fff1U, 0x5f6a3594U, 0x3a2c160bU, + 0x68bbd3e7U, 0x23c9ea75U, 0x589bc3efU, 0xb8d06834U, + 0xa6c46231U, 0xc277b5d4U, 0xda67bdd0U, 0x33221186U, + 0x19e5fc7eU, 0xc98e47adU, 0x34d3e7fdU, 0xf6a45229U, + 0xa0c06030U, 0x9aec763bU, 0x6546239fU, 0x2ac7edf8U, + 0xae3f91c6U, 0x6a4c2613U, 0x14180c06U, 0x1e140a05U, + 0xa43397c5U, 0x66442211U, 0x2fc1ee77U, 0x15edf87cU, + 0x01f5f47aU, 0x0dfdf078U, 0xb4d86c36U, 0x4870381cU, + 0x96e47239U, 0xcb79b259U, 0x50603018U, 0xe945ac56U, + 0x8df67bb3U, 0x87fa7db0U, 0xd8904824U, 0xc0804020U, + 0x8bf279b2U, 0x4b723992U, 0xedb65ba3U, 0xba279dc0U, + 0x850d8844U, 0x5195c462U, 0x60402010U, 0x9fea75b4U, + 0x3f2a1584U, 0x97118643U, 0x4d763b93U, 0xb62f99c2U, + 0xa135944aU, 0xa9ce67bdU, 0x0506038fU, 0xeeb45a2dU, + 0xafca65bcU, 0x6f4a259cU, 0x61b5d46aU, 0x9d1d8040U, + 0x981b83cfU, 0xebb259a2U, 0x273a1d80U, 0xbf219e4fU, + 0x427c3e1fU, 0x860f89caU, 0xdb9249aaU, 0x91158442U, +}; + +static const ulong32 T4[256] = { + 0xbabababaU, 0x54545454U, 0x2f2f2f2fU, 0x74747474U, + 0x53535353U, 0xd3d3d3d3U, 0xd2d2d2d2U, 0x4d4d4d4dU, + 0x50505050U, 0xacacacacU, 0x8d8d8d8dU, 0xbfbfbfbfU, + 0x70707070U, 0x52525252U, 0x9a9a9a9aU, 0x4c4c4c4cU, + 0xeaeaeaeaU, 0xd5d5d5d5U, 0x97979797U, 0xd1d1d1d1U, + 0x33333333U, 0x51515151U, 0x5b5b5b5bU, 0xa6a6a6a6U, + 0xdedededeU, 0x48484848U, 0xa8a8a8a8U, 0x99999999U, + 0xdbdbdbdbU, 0x32323232U, 0xb7b7b7b7U, 0xfcfcfcfcU, + 0xe3e3e3e3U, 0x9e9e9e9eU, 0x91919191U, 0x9b9b9b9bU, + 0xe2e2e2e2U, 0xbbbbbbbbU, 0x41414141U, 0x6e6e6e6eU, + 0xa5a5a5a5U, 0xcbcbcbcbU, 0x6b6b6b6bU, 0x95959595U, + 0xa1a1a1a1U, 0xf3f3f3f3U, 0xb1b1b1b1U, 0x02020202U, + 0xccccccccU, 0xc4c4c4c4U, 0x1d1d1d1dU, 0x14141414U, + 0xc3c3c3c3U, 0x63636363U, 0xdadadadaU, 0x5d5d5d5dU, + 0x5f5f5f5fU, 0xdcdcdcdcU, 0x7d7d7d7dU, 0xcdcdcdcdU, + 0x7f7f7f7fU, 0x5a5a5a5aU, 0x6c6c6c6cU, 0x5c5c5c5cU, + 0xf7f7f7f7U, 0x26262626U, 0xffffffffU, 0xededededU, + 0xe8e8e8e8U, 0x9d9d9d9dU, 0x6f6f6f6fU, 0x8e8e8e8eU, + 0x19191919U, 0xa0a0a0a0U, 0xf0f0f0f0U, 0x89898989U, + 0x0f0f0f0fU, 0x07070707U, 0xafafafafU, 0xfbfbfbfbU, + 0x08080808U, 0x15151515U, 0x0d0d0d0dU, 0x04040404U, + 0x01010101U, 0x64646464U, 0xdfdfdfdfU, 0x76767676U, + 0x79797979U, 0xddddddddU, 0x3d3d3d3dU, 0x16161616U, + 0x3f3f3f3fU, 0x37373737U, 0x6d6d6d6dU, 0x38383838U, + 0xb9b9b9b9U, 0x73737373U, 0xe9e9e9e9U, 0x35353535U, + 0x55555555U, 0x71717171U, 0x7b7b7b7bU, 0x8c8c8c8cU, + 0x72727272U, 0x88888888U, 0xf6f6f6f6U, 0x2a2a2a2aU, + 0x3e3e3e3eU, 0x5e5e5e5eU, 0x27272727U, 0x46464646U, + 0x0c0c0c0cU, 0x65656565U, 0x68686868U, 0x61616161U, + 0x03030303U, 0xc1c1c1c1U, 0x57575757U, 0xd6d6d6d6U, + 0xd9d9d9d9U, 0x58585858U, 0xd8d8d8d8U, 0x66666666U, + 0xd7d7d7d7U, 0x3a3a3a3aU, 0xc8c8c8c8U, 0x3c3c3c3cU, + 0xfafafafaU, 0x96969696U, 0xa7a7a7a7U, 0x98989898U, + 0xececececU, 0xb8b8b8b8U, 0xc7c7c7c7U, 0xaeaeaeaeU, + 0x69696969U, 0x4b4b4b4bU, 0xababababU, 0xa9a9a9a9U, + 0x67676767U, 0x0a0a0a0aU, 0x47474747U, 0xf2f2f2f2U, + 0xb5b5b5b5U, 0x22222222U, 0xe5e5e5e5U, 0xeeeeeeeeU, + 0xbebebebeU, 0x2b2b2b2bU, 0x81818181U, 0x12121212U, + 0x83838383U, 0x1b1b1b1bU, 0x0e0e0e0eU, 0x23232323U, + 0xf5f5f5f5U, 0x45454545U, 0x21212121U, 0xcecececeU, + 0x49494949U, 0x2c2c2c2cU, 0xf9f9f9f9U, 0xe6e6e6e6U, + 0xb6b6b6b6U, 0x28282828U, 0x17171717U, 0x82828282U, + 0x1a1a1a1aU, 0x8b8b8b8bU, 0xfefefefeU, 0x8a8a8a8aU, + 0x09090909U, 0xc9c9c9c9U, 0x87878787U, 0x4e4e4e4eU, + 0xe1e1e1e1U, 0x2e2e2e2eU, 0xe4e4e4e4U, 0xe0e0e0e0U, + 0xebebebebU, 0x90909090U, 0xa4a4a4a4U, 0x1e1e1e1eU, + 0x85858585U, 0x60606060U, 0x00000000U, 0x25252525U, + 0xf4f4f4f4U, 0xf1f1f1f1U, 0x94949494U, 0x0b0b0b0bU, + 0xe7e7e7e7U, 0x75757575U, 0xefefefefU, 0x34343434U, + 0x31313131U, 0xd4d4d4d4U, 0xd0d0d0d0U, 0x86868686U, + 0x7e7e7e7eU, 0xadadadadU, 0xfdfdfdfdU, 0x29292929U, + 0x30303030U, 0x3b3b3b3bU, 0x9f9f9f9fU, 0xf8f8f8f8U, + 0xc6c6c6c6U, 0x13131313U, 0x06060606U, 0x05050505U, + 0xc5c5c5c5U, 0x11111111U, 0x77777777U, 0x7c7c7c7cU, + 0x7a7a7a7aU, 0x78787878U, 0x36363636U, 0x1c1c1c1cU, + 0x39393939U, 0x59595959U, 0x18181818U, 0x56565656U, + 0xb3b3b3b3U, 0xb0b0b0b0U, 0x24242424U, 0x20202020U, + 0xb2b2b2b2U, 0x92929292U, 0xa3a3a3a3U, 0xc0c0c0c0U, + 0x44444444U, 0x62626262U, 0x10101010U, 0xb4b4b4b4U, + 0x84848484U, 0x43434343U, 0x93939393U, 0xc2c2c2c2U, + 0x4a4a4a4aU, 0xbdbdbdbdU, 0x8f8f8f8fU, 0x2d2d2d2dU, + 0xbcbcbcbcU, 0x9c9c9c9cU, 0x6a6a6a6aU, 0x40404040U, + 0xcfcfcfcfU, 0xa2a2a2a2U, 0x80808080U, 0x4f4f4f4fU, + 0x1f1f1f1fU, 0xcacacacaU, 0xaaaaaaaaU, 0x42424242U, +}; + +static const ulong32 T5[256] = { + 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, + 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, + 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, + 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, + 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, + 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, + 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, + 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, + 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, + 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, + 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, + 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, + 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, + 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, + 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, + 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, + 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, + 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, + 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, + 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, + 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, + 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, + 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, + 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, + 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, + 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, + 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, + 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, + 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, + 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, + 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, + 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, + 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, + 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, + 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, + 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, + 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, + 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, + 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, + 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, + 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, + 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, + 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, + 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, + 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, + 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, + 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, + 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, + 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, + 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, + 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, + 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, + 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, + 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, + 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, + 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, + 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, + 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, + 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, + 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, + 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, + 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, + 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, + 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, +}; + +/** + * The round constants. + */ +static const ulong32 rc[] = { + 0xba542f74U, 0x53d3d24dU, 0x50ac8dbfU, 0x70529a4cU, + 0xead597d1U, 0x33515ba6U, 0xde48a899U, 0xdb32b7fcU, + 0xe39e919bU, 0xe2bb416eU, 0xa5cb6b95U, 0xa1f3b102U, + 0xccc41d14U, 0xc363da5dU, 0x5fdc7dcdU, 0x7f5a6c5cU, + 0xf726ffedU, 0xe89d6f8eU, 0x19a0f089U, +}; + + + +#else + + +static const ulong32 T0[256] = { + 0xa753a6f5U, 0xd3bb6bd0U, 0xe6d1bf6eU, 0x71e2d93bU, + 0xd0bd67daU, 0xac458acfU, 0x4d9a29b3U, 0x79f2f90bU, + 0x3a74e89cU, 0xc98f038cU, 0x913f7e41U, 0xfce5d732U, + 0x1e3c7844U, 0x478e018fU, 0x54a84de5U, 0xbd67cea9U, + 0x8c050a0fU, 0xa557aef9U, 0x7af4f501U, 0xfbebcb20U, + 0x63c69157U, 0xb86ddab7U, 0xdda753f4U, 0xd4b577c2U, + 0xe5d7b364U, 0xb37bf68dU, 0xc59733a4U, 0xbe61c2a3U, + 0xa94f9ed1U, 0x880d1a17U, 0x0c183028U, 0xa259b2ebU, + 0x3972e496U, 0xdfa35bf8U, 0x2952a4f6U, 0xdaa94fe6U, + 0x2b56acfaU, 0xa84d9ad7U, 0xcb8b0b80U, 0x4c982db5U, + 0x4b9631a7U, 0x224488ccU, 0xaa4992dbU, 0x244890d8U, + 0x4182199bU, 0x70e0dd3dU, 0xa651a2f3U, 0xf9efc32cU, + 0x5ab475c1U, 0xe2d9af76U, 0xb07dfa87U, 0x366cd8b4U, + 0x7dfae913U, 0xe4d5b762U, 0x3366ccaaU, 0xffe3db38U, + 0x60c09d5dU, 0x204080c0U, 0x08102030U, 0x8b0b161dU, + 0x5ebc65d9U, 0xab4b96ddU, 0x7ffee11fU, 0x78f0fd0dU, + 0x7cf8ed15U, 0x2c58b0e8U, 0x57ae41efU, 0xd2b96fd6U, + 0xdca557f2U, 0x6ddaa973U, 0x7efce519U, 0x0d1a342eU, + 0x53a651f7U, 0x94356a5fU, 0xc39b2bb0U, 0x2850a0f0U, + 0x274e9cd2U, 0x060c1814U, 0x5fbe61dfU, 0xad478ec9U, + 0x67ce814fU, 0x5cb86dd5U, 0x55aa49e3U, 0x48903dadU, + 0x0e1c3824U, 0x52a455f1U, 0xeac98f46U, 0x42841591U, + 0x5bb671c7U, 0x5dba69d3U, 0x3060c0a0U, 0x58b07dcdU, + 0x51a259fbU, 0x59b279cbU, 0x3c78f088U, 0x4e9c25b9U, + 0x3870e090U, 0x8a09121bU, 0x72e4d531U, 0x14285078U, + 0xe7d3bb68U, 0xc6913faeU, 0xdea15ffeU, 0x50a05dfdU, + 0x8e010203U, 0x9239724bU, 0xd1bf63dcU, 0x77eec12fU, + 0x933b764dU, 0x458a0983U, 0x9a29527bU, 0xce811f9eU, + 0x2d5ab4eeU, 0x03060c0aU, 0x62c49551U, 0xb671e293U, + 0xb96fdeb1U, 0xbf63c6a5U, 0x96316253U, 0x6bd6b167U, + 0x3f7efc82U, 0x070e1c12U, 0x1224486cU, 0xae4182c3U, + 0x40801d9dU, 0x3468d0b8U, 0x468c0589U, 0x3e7cf884U, + 0xdbab4be0U, 0xcf831b98U, 0xecc59752U, 0xcc851792U, + 0xc19f23bcU, 0xa15fbee1U, 0xc09d27baU, 0xd6b17fceU, + 0x1d3a744eU, 0xf4f5f702U, 0x61c2995bU, 0x3b76ec9aU, + 0x10204060U, 0xd8ad47eaU, 0x68d0bd6dU, 0xa05dbae7U, + 0xb17ffe81U, 0x0a14283cU, 0x69d2b96bU, 0x6cd8ad75U, + 0x499239abU, 0xfae9cf26U, 0x76ecc529U, 0xc49537a2U, + 0x9e214263U, 0x9b2b567dU, 0x6edca579U, 0x992f5e71U, + 0xc2992fb6U, 0xb773e695U, 0x982d5a77U, 0xbc65caafU, + 0x8f030605U, 0x85172e39U, 0x1f3e7c42U, 0xb475ea9fU, + 0xf8edc72aU, 0x11224466U, 0x2e5cb8e4U, 0x00000000U, + 0x254a94deU, 0x1c387048U, 0x2a54a8fcU, 0x3d7af48eU, + 0x050a141eU, 0x4f9e21bfU, 0x7bf6f107U, 0xb279f28bU, + 0x3264c8acU, 0x903d7a47U, 0xaf4386c5U, 0x19326456U, + 0xa35bb6edU, 0xf7f3fb08U, 0x73e6d137U, 0x9d274e69U, + 0x152a547eU, 0x74e8cd25U, 0xeec19f5eU, 0xca890f86U, + 0x9f234665U, 0x0f1e3c22U, 0x1b366c5aU, 0x75eac923U, + 0x86112233U, 0x84152a3fU, 0x9c254a6fU, 0x4a9435a1U, + 0x97336655U, 0x1a34685cU, 0x65ca8943U, 0xf6f1ff0eU, + 0xedc79354U, 0x09122436U, 0xbb6bd6bdU, 0x264c98d4U, + 0x831b362dU, 0xebcb8b40U, 0x6fdea17fU, 0x811f3e21U, + 0x04081018U, 0x6ad4b561U, 0x43861197U, 0x01020406U, + 0x172e5c72U, 0xe1dfa37cU, 0x87132635U, 0xf5f7f304U, + 0x8d070e09U, 0xe3dbab70U, 0x23468ccaU, 0x801d3a27U, + 0x44880d85U, 0x162c5874U, 0x66cc8549U, 0x214284c6U, + 0xfee1df3eU, 0xd5b773c4U, 0x3162c4a6U, 0xd9af43ecU, + 0x356ad4beU, 0x18306050U, 0x0204080cU, 0x64c88d45U, + 0xf2f9ef16U, 0xf1ffe31cU, 0x56ac45e9U, 0xcd871394U, + 0x8219322bU, 0xc88d078aU, 0xba69d2bbU, 0xf0fde71aU, + 0xefc39b58U, 0xe9cf834cU, 0xe8cd874aU, 0xfde7d334U, + 0x890f1e11U, 0xd7b37bc8U, 0xc7933ba8U, 0xb577ee99U, + 0xa455aaffU, 0x2f5ebce2U, 0x95376e59U, 0x13264c6aU, + 0x0b162c3aU, 0xf3fbeb10U, 0xe0dda77aU, 0x376edcb2U, +}; + +static const ulong32 T1[256] = { + 0x53a7f5a6U, 0xbbd3d06bU, 0xd1e66ebfU, 0xe2713bd9U, + 0xbdd0da67U, 0x45accf8aU, 0x9a4db329U, 0xf2790bf9U, + 0x743a9ce8U, 0x8fc98c03U, 0x3f91417eU, 0xe5fc32d7U, + 0x3c1e4478U, 0x8e478f01U, 0xa854e54dU, 0x67bda9ceU, + 0x058c0f0aU, 0x57a5f9aeU, 0xf47a01f5U, 0xebfb20cbU, + 0xc6635791U, 0x6db8b7daU, 0xa7ddf453U, 0xb5d4c277U, + 0xd7e564b3U, 0x7bb38df6U, 0x97c5a433U, 0x61bea3c2U, + 0x4fa9d19eU, 0x0d88171aU, 0x180c2830U, 0x59a2ebb2U, + 0x723996e4U, 0xa3dff85bU, 0x5229f6a4U, 0xa9dae64fU, + 0x562bfaacU, 0x4da8d79aU, 0x8bcb800bU, 0x984cb52dU, + 0x964ba731U, 0x4422cc88U, 0x49aadb92U, 0x4824d890U, + 0x82419b19U, 0xe0703dddU, 0x51a6f3a2U, 0xeff92cc3U, + 0xb45ac175U, 0xd9e276afU, 0x7db087faU, 0x6c36b4d8U, + 0xfa7d13e9U, 0xd5e462b7U, 0x6633aaccU, 0xe3ff38dbU, + 0xc0605d9dU, 0x4020c080U, 0x10083020U, 0x0b8b1d16U, + 0xbc5ed965U, 0x4babdd96U, 0xfe7f1fe1U, 0xf0780dfdU, + 0xf87c15edU, 0x582ce8b0U, 0xae57ef41U, 0xb9d2d66fU, + 0xa5dcf257U, 0xda6d73a9U, 0xfc7e19e5U, 0x1a0d2e34U, + 0xa653f751U, 0x35945f6aU, 0x9bc3b02bU, 0x5028f0a0U, + 0x4e27d29cU, 0x0c061418U, 0xbe5fdf61U, 0x47adc98eU, + 0xce674f81U, 0xb85cd56dU, 0xaa55e349U, 0x9048ad3dU, + 0x1c0e2438U, 0xa452f155U, 0xc9ea468fU, 0x84429115U, + 0xb65bc771U, 0xba5dd369U, 0x6030a0c0U, 0xb058cd7dU, + 0xa251fb59U, 0xb259cb79U, 0x783c88f0U, 0x9c4eb925U, + 0x703890e0U, 0x098a1b12U, 0xe47231d5U, 0x28147850U, + 0xd3e768bbU, 0x91c6ae3fU, 0xa1defe5fU, 0xa050fd5dU, + 0x018e0302U, 0x39924b72U, 0xbfd1dc63U, 0xee772fc1U, + 0x3b934d76U, 0x8a458309U, 0x299a7b52U, 0x81ce9e1fU, + 0x5a2deeb4U, 0x06030a0cU, 0xc4625195U, 0x71b693e2U, + 0x6fb9b1deU, 0x63bfa5c6U, 0x31965362U, 0xd66b67b1U, + 0x7e3f82fcU, 0x0e07121cU, 0x24126c48U, 0x41aec382U, + 0x80409d1dU, 0x6834b8d0U, 0x8c468905U, 0x7c3e84f8U, + 0xabdbe04bU, 0x83cf981bU, 0xc5ec5297U, 0x85cc9217U, + 0x9fc1bc23U, 0x5fa1e1beU, 0x9dc0ba27U, 0xb1d6ce7fU, + 0x3a1d4e74U, 0xf5f402f7U, 0xc2615b99U, 0x763b9aecU, + 0x20106040U, 0xadd8ea47U, 0xd0686dbdU, 0x5da0e7baU, + 0x7fb181feU, 0x140a3c28U, 0xd2696bb9U, 0xd86c75adU, + 0x9249ab39U, 0xe9fa26cfU, 0xec7629c5U, 0x95c4a237U, + 0x219e6342U, 0x2b9b7d56U, 0xdc6e79a5U, 0x2f99715eU, + 0x99c2b62fU, 0x73b795e6U, 0x2d98775aU, 0x65bcafcaU, + 0x038f0506U, 0x1785392eU, 0x3e1f427cU, 0x75b49feaU, + 0xedf82ac7U, 0x22116644U, 0x5c2ee4b8U, 0x00000000U, + 0x4a25de94U, 0x381c4870U, 0x542afca8U, 0x7a3d8ef4U, + 0x0a051e14U, 0x9e4fbf21U, 0xf67b07f1U, 0x79b28bf2U, + 0x6432acc8U, 0x3d90477aU, 0x43afc586U, 0x32195664U, + 0x5ba3edb6U, 0xf3f708fbU, 0xe67337d1U, 0x279d694eU, + 0x2a157e54U, 0xe87425cdU, 0xc1ee5e9fU, 0x89ca860fU, + 0x239f6546U, 0x1e0f223cU, 0x361b5a6cU, 0xea7523c9U, + 0x11863322U, 0x15843f2aU, 0x259c6f4aU, 0x944aa135U, + 0x33975566U, 0x341a5c68U, 0xca654389U, 0xf1f60effU, + 0xc7ed5493U, 0x12093624U, 0x6bbbbdd6U, 0x4c26d498U, + 0x1b832d36U, 0xcbeb408bU, 0xde6f7fa1U, 0x1f81213eU, + 0x08041810U, 0xd46a61b5U, 0x86439711U, 0x02010604U, + 0x2e17725cU, 0xdfe17ca3U, 0x13873526U, 0xf7f504f3U, + 0x078d090eU, 0xdbe370abU, 0x4623ca8cU, 0x1d80273aU, + 0x8844850dU, 0x2c167458U, 0xcc664985U, 0x4221c684U, + 0xe1fe3edfU, 0xb7d5c473U, 0x6231a6c4U, 0xafd9ec43U, + 0x6a35bed4U, 0x30185060U, 0x04020c08U, 0xc864458dU, + 0xf9f216efU, 0xfff11ce3U, 0xac56e945U, 0x87cd9413U, + 0x19822b32U, 0x8dc88a07U, 0x69babbd2U, 0xfdf01ae7U, + 0xc3ef589bU, 0xcfe94c83U, 0xcde84a87U, 0xe7fd34d3U, + 0x0f89111eU, 0xb3d7c87bU, 0x93c7a83bU, 0x77b599eeU, + 0x55a4ffaaU, 0x5e2fe2bcU, 0x3795596eU, 0x26136a4cU, + 0x160b3a2cU, 0xfbf310ebU, 0xdde07aa7U, 0x6e37b2dcU, +}; + +static const ulong32 T2[256] = { + 0xa6f5a753U, 0x6bd0d3bbU, 0xbf6ee6d1U, 0xd93b71e2U, + 0x67dad0bdU, 0x8acfac45U, 0x29b34d9aU, 0xf90b79f2U, + 0xe89c3a74U, 0x038cc98fU, 0x7e41913fU, 0xd732fce5U, + 0x78441e3cU, 0x018f478eU, 0x4de554a8U, 0xcea9bd67U, + 0x0a0f8c05U, 0xaef9a557U, 0xf5017af4U, 0xcb20fbebU, + 0x915763c6U, 0xdab7b86dU, 0x53f4dda7U, 0x77c2d4b5U, + 0xb364e5d7U, 0xf68db37bU, 0x33a4c597U, 0xc2a3be61U, + 0x9ed1a94fU, 0x1a17880dU, 0x30280c18U, 0xb2eba259U, + 0xe4963972U, 0x5bf8dfa3U, 0xa4f62952U, 0x4fe6daa9U, + 0xacfa2b56U, 0x9ad7a84dU, 0x0b80cb8bU, 0x2db54c98U, + 0x31a74b96U, 0x88cc2244U, 0x92dbaa49U, 0x90d82448U, + 0x199b4182U, 0xdd3d70e0U, 0xa2f3a651U, 0xc32cf9efU, + 0x75c15ab4U, 0xaf76e2d9U, 0xfa87b07dU, 0xd8b4366cU, + 0xe9137dfaU, 0xb762e4d5U, 0xccaa3366U, 0xdb38ffe3U, + 0x9d5d60c0U, 0x80c02040U, 0x20300810U, 0x161d8b0bU, + 0x65d95ebcU, 0x96ddab4bU, 0xe11f7ffeU, 0xfd0d78f0U, + 0xed157cf8U, 0xb0e82c58U, 0x41ef57aeU, 0x6fd6d2b9U, + 0x57f2dca5U, 0xa9736ddaU, 0xe5197efcU, 0x342e0d1aU, + 0x51f753a6U, 0x6a5f9435U, 0x2bb0c39bU, 0xa0f02850U, + 0x9cd2274eU, 0x1814060cU, 0x61df5fbeU, 0x8ec9ad47U, + 0x814f67ceU, 0x6dd55cb8U, 0x49e355aaU, 0x3dad4890U, + 0x38240e1cU, 0x55f152a4U, 0x8f46eac9U, 0x15914284U, + 0x71c75bb6U, 0x69d35dbaU, 0xc0a03060U, 0x7dcd58b0U, + 0x59fb51a2U, 0x79cb59b2U, 0xf0883c78U, 0x25b94e9cU, + 0xe0903870U, 0x121b8a09U, 0xd53172e4U, 0x50781428U, + 0xbb68e7d3U, 0x3faec691U, 0x5ffedea1U, 0x5dfd50a0U, + 0x02038e01U, 0x724b9239U, 0x63dcd1bfU, 0xc12f77eeU, + 0x764d933bU, 0x0983458aU, 0x527b9a29U, 0x1f9ece81U, + 0xb4ee2d5aU, 0x0c0a0306U, 0x955162c4U, 0xe293b671U, + 0xdeb1b96fU, 0xc6a5bf63U, 0x62539631U, 0xb1676bd6U, + 0xfc823f7eU, 0x1c12070eU, 0x486c1224U, 0x82c3ae41U, + 0x1d9d4080U, 0xd0b83468U, 0x0589468cU, 0xf8843e7cU, + 0x4be0dbabU, 0x1b98cf83U, 0x9752ecc5U, 0x1792cc85U, + 0x23bcc19fU, 0xbee1a15fU, 0x27bac09dU, 0x7fced6b1U, + 0x744e1d3aU, 0xf702f4f5U, 0x995b61c2U, 0xec9a3b76U, + 0x40601020U, 0x47ead8adU, 0xbd6d68d0U, 0xbae7a05dU, + 0xfe81b17fU, 0x283c0a14U, 0xb96b69d2U, 0xad756cd8U, + 0x39ab4992U, 0xcf26fae9U, 0xc52976ecU, 0x37a2c495U, + 0x42639e21U, 0x567d9b2bU, 0xa5796edcU, 0x5e71992fU, + 0x2fb6c299U, 0xe695b773U, 0x5a77982dU, 0xcaafbc65U, + 0x06058f03U, 0x2e398517U, 0x7c421f3eU, 0xea9fb475U, + 0xc72af8edU, 0x44661122U, 0xb8e42e5cU, 0x00000000U, + 0x94de254aU, 0x70481c38U, 0xa8fc2a54U, 0xf48e3d7aU, + 0x141e050aU, 0x21bf4f9eU, 0xf1077bf6U, 0xf28bb279U, + 0xc8ac3264U, 0x7a47903dU, 0x86c5af43U, 0x64561932U, + 0xb6eda35bU, 0xfb08f7f3U, 0xd13773e6U, 0x4e699d27U, + 0x547e152aU, 0xcd2574e8U, 0x9f5eeec1U, 0x0f86ca89U, + 0x46659f23U, 0x3c220f1eU, 0x6c5a1b36U, 0xc92375eaU, + 0x22338611U, 0x2a3f8415U, 0x4a6f9c25U, 0x35a14a94U, + 0x66559733U, 0x685c1a34U, 0x894365caU, 0xff0ef6f1U, + 0x9354edc7U, 0x24360912U, 0xd6bdbb6bU, 0x98d4264cU, + 0x362d831bU, 0x8b40ebcbU, 0xa17f6fdeU, 0x3e21811fU, + 0x10180408U, 0xb5616ad4U, 0x11974386U, 0x04060102U, + 0x5c72172eU, 0xa37ce1dfU, 0x26358713U, 0xf304f5f7U, + 0x0e098d07U, 0xab70e3dbU, 0x8cca2346U, 0x3a27801dU, + 0x0d854488U, 0x5874162cU, 0x854966ccU, 0x84c62142U, + 0xdf3efee1U, 0x73c4d5b7U, 0xc4a63162U, 0x43ecd9afU, + 0xd4be356aU, 0x60501830U, 0x080c0204U, 0x8d4564c8U, + 0xef16f2f9U, 0xe31cf1ffU, 0x45e956acU, 0x1394cd87U, + 0x322b8219U, 0x078ac88dU, 0xd2bbba69U, 0xe71af0fdU, + 0x9b58efc3U, 0x834ce9cfU, 0x874ae8cdU, 0xd334fde7U, + 0x1e11890fU, 0x7bc8d7b3U, 0x3ba8c793U, 0xee99b577U, + 0xaaffa455U, 0xbce22f5eU, 0x6e599537U, 0x4c6a1326U, + 0x2c3a0b16U, 0xeb10f3fbU, 0xa77ae0ddU, 0xdcb2376eU, +}; + +static const ulong32 T3[256] = { + 0xf5a653a7U, 0xd06bbbd3U, 0x6ebfd1e6U, 0x3bd9e271U, + 0xda67bdd0U, 0xcf8a45acU, 0xb3299a4dU, 0x0bf9f279U, + 0x9ce8743aU, 0x8c038fc9U, 0x417e3f91U, 0x32d7e5fcU, + 0x44783c1eU, 0x8f018e47U, 0xe54da854U, 0xa9ce67bdU, + 0x0f0a058cU, 0xf9ae57a5U, 0x01f5f47aU, 0x20cbebfbU, + 0x5791c663U, 0xb7da6db8U, 0xf453a7ddU, 0xc277b5d4U, + 0x64b3d7e5U, 0x8df67bb3U, 0xa43397c5U, 0xa3c261beU, + 0xd19e4fa9U, 0x171a0d88U, 0x2830180cU, 0xebb259a2U, + 0x96e47239U, 0xf85ba3dfU, 0xf6a45229U, 0xe64fa9daU, + 0xfaac562bU, 0xd79a4da8U, 0x800b8bcbU, 0xb52d984cU, + 0xa731964bU, 0xcc884422U, 0xdb9249aaU, 0xd8904824U, + 0x9b198241U, 0x3ddde070U, 0xf3a251a6U, 0x2cc3eff9U, + 0xc175b45aU, 0x76afd9e2U, 0x87fa7db0U, 0xb4d86c36U, + 0x13e9fa7dU, 0x62b7d5e4U, 0xaacc6633U, 0x38dbe3ffU, + 0x5d9dc060U, 0xc0804020U, 0x30201008U, 0x1d160b8bU, + 0xd965bc5eU, 0xdd964babU, 0x1fe1fe7fU, 0x0dfdf078U, + 0x15edf87cU, 0xe8b0582cU, 0xef41ae57U, 0xd66fb9d2U, + 0xf257a5dcU, 0x73a9da6dU, 0x19e5fc7eU, 0x2e341a0dU, + 0xf751a653U, 0x5f6a3594U, 0xb02b9bc3U, 0xf0a05028U, + 0xd29c4e27U, 0x14180c06U, 0xdf61be5fU, 0xc98e47adU, + 0x4f81ce67U, 0xd56db85cU, 0xe349aa55U, 0xad3d9048U, + 0x24381c0eU, 0xf155a452U, 0x468fc9eaU, 0x91158442U, + 0xc771b65bU, 0xd369ba5dU, 0xa0c06030U, 0xcd7db058U, + 0xfb59a251U, 0xcb79b259U, 0x88f0783cU, 0xb9259c4eU, + 0x90e07038U, 0x1b12098aU, 0x31d5e472U, 0x78502814U, + 0x68bbd3e7U, 0xae3f91c6U, 0xfe5fa1deU, 0xfd5da050U, + 0x0302018eU, 0x4b723992U, 0xdc63bfd1U, 0x2fc1ee77U, + 0x4d763b93U, 0x83098a45U, 0x7b52299aU, 0x9e1f81ceU, + 0xeeb45a2dU, 0x0a0c0603U, 0x5195c462U, 0x93e271b6U, + 0xb1de6fb9U, 0xa5c663bfU, 0x53623196U, 0x67b1d66bU, + 0x82fc7e3fU, 0x121c0e07U, 0x6c482412U, 0xc38241aeU, + 0x9d1d8040U, 0xb8d06834U, 0x89058c46U, 0x84f87c3eU, + 0xe04babdbU, 0x981b83cfU, 0x5297c5ecU, 0x921785ccU, + 0xbc239fc1U, 0xe1be5fa1U, 0xba279dc0U, 0xce7fb1d6U, + 0x4e743a1dU, 0x02f7f5f4U, 0x5b99c261U, 0x9aec763bU, + 0x60402010U, 0xea47add8U, 0x6dbdd068U, 0xe7ba5da0U, + 0x81fe7fb1U, 0x3c28140aU, 0x6bb9d269U, 0x75add86cU, + 0xab399249U, 0x26cfe9faU, 0x29c5ec76U, 0xa23795c4U, + 0x6342219eU, 0x7d562b9bU, 0x79a5dc6eU, 0x715e2f99U, + 0xb62f99c2U, 0x95e673b7U, 0x775a2d98U, 0xafca65bcU, + 0x0506038fU, 0x392e1785U, 0x427c3e1fU, 0x9fea75b4U, + 0x2ac7edf8U, 0x66442211U, 0xe4b85c2eU, 0x00000000U, + 0xde944a25U, 0x4870381cU, 0xfca8542aU, 0x8ef47a3dU, + 0x1e140a05U, 0xbf219e4fU, 0x07f1f67bU, 0x8bf279b2U, + 0xacc86432U, 0x477a3d90U, 0xc58643afU, 0x56643219U, + 0xedb65ba3U, 0x08fbf3f7U, 0x37d1e673U, 0x694e279dU, + 0x7e542a15U, 0x25cde874U, 0x5e9fc1eeU, 0x860f89caU, + 0x6546239fU, 0x223c1e0fU, 0x5a6c361bU, 0x23c9ea75U, + 0x33221186U, 0x3f2a1584U, 0x6f4a259cU, 0xa135944aU, + 0x55663397U, 0x5c68341aU, 0x4389ca65U, 0x0efff1f6U, + 0x5493c7edU, 0x36241209U, 0xbdd66bbbU, 0xd4984c26U, + 0x2d361b83U, 0x408bcbebU, 0x7fa1de6fU, 0x213e1f81U, + 0x18100804U, 0x61b5d46aU, 0x97118643U, 0x06040201U, + 0x725c2e17U, 0x7ca3dfe1U, 0x35261387U, 0x04f3f7f5U, + 0x090e078dU, 0x70abdbe3U, 0xca8c4623U, 0x273a1d80U, + 0x850d8844U, 0x74582c16U, 0x4985cc66U, 0xc6844221U, + 0x3edfe1feU, 0xc473b7d5U, 0xa6c46231U, 0xec43afd9U, + 0xbed46a35U, 0x50603018U, 0x0c080402U, 0x458dc864U, + 0x16eff9f2U, 0x1ce3fff1U, 0xe945ac56U, 0x941387cdU, + 0x2b321982U, 0x8a078dc8U, 0xbbd269baU, 0x1ae7fdf0U, + 0x589bc3efU, 0x4c83cfe9U, 0x4a87cde8U, 0x34d3e7fdU, + 0x111e0f89U, 0xc87bb3d7U, 0xa83b93c7U, 0x99ee77b5U, + 0xffaa55a4U, 0xe2bc5e2fU, 0x596e3795U, 0x6a4c2613U, + 0x3a2c160bU, 0x10ebfbf3U, 0x7aa7dde0U, 0xb2dc6e37U, +}; + +static const ulong32 T4[256] = { + 0xa7a7a7a7U, 0xd3d3d3d3U, 0xe6e6e6e6U, 0x71717171U, + 0xd0d0d0d0U, 0xacacacacU, 0x4d4d4d4dU, 0x79797979U, + 0x3a3a3a3aU, 0xc9c9c9c9U, 0x91919191U, 0xfcfcfcfcU, + 0x1e1e1e1eU, 0x47474747U, 0x54545454U, 0xbdbdbdbdU, + 0x8c8c8c8cU, 0xa5a5a5a5U, 0x7a7a7a7aU, 0xfbfbfbfbU, + 0x63636363U, 0xb8b8b8b8U, 0xddddddddU, 0xd4d4d4d4U, + 0xe5e5e5e5U, 0xb3b3b3b3U, 0xc5c5c5c5U, 0xbebebebeU, + 0xa9a9a9a9U, 0x88888888U, 0x0c0c0c0cU, 0xa2a2a2a2U, + 0x39393939U, 0xdfdfdfdfU, 0x29292929U, 0xdadadadaU, + 0x2b2b2b2bU, 0xa8a8a8a8U, 0xcbcbcbcbU, 0x4c4c4c4cU, + 0x4b4b4b4bU, 0x22222222U, 0xaaaaaaaaU, 0x24242424U, + 0x41414141U, 0x70707070U, 0xa6a6a6a6U, 0xf9f9f9f9U, + 0x5a5a5a5aU, 0xe2e2e2e2U, 0xb0b0b0b0U, 0x36363636U, + 0x7d7d7d7dU, 0xe4e4e4e4U, 0x33333333U, 0xffffffffU, + 0x60606060U, 0x20202020U, 0x08080808U, 0x8b8b8b8bU, + 0x5e5e5e5eU, 0xababababU, 0x7f7f7f7fU, 0x78787878U, + 0x7c7c7c7cU, 0x2c2c2c2cU, 0x57575757U, 0xd2d2d2d2U, + 0xdcdcdcdcU, 0x6d6d6d6dU, 0x7e7e7e7eU, 0x0d0d0d0dU, + 0x53535353U, 0x94949494U, 0xc3c3c3c3U, 0x28282828U, + 0x27272727U, 0x06060606U, 0x5f5f5f5fU, 0xadadadadU, + 0x67676767U, 0x5c5c5c5cU, 0x55555555U, 0x48484848U, + 0x0e0e0e0eU, 0x52525252U, 0xeaeaeaeaU, 0x42424242U, + 0x5b5b5b5bU, 0x5d5d5d5dU, 0x30303030U, 0x58585858U, + 0x51515151U, 0x59595959U, 0x3c3c3c3cU, 0x4e4e4e4eU, + 0x38383838U, 0x8a8a8a8aU, 0x72727272U, 0x14141414U, + 0xe7e7e7e7U, 0xc6c6c6c6U, 0xdedededeU, 0x50505050U, + 0x8e8e8e8eU, 0x92929292U, 0xd1d1d1d1U, 0x77777777U, + 0x93939393U, 0x45454545U, 0x9a9a9a9aU, 0xcecececeU, + 0x2d2d2d2dU, 0x03030303U, 0x62626262U, 0xb6b6b6b6U, + 0xb9b9b9b9U, 0xbfbfbfbfU, 0x96969696U, 0x6b6b6b6bU, + 0x3f3f3f3fU, 0x07070707U, 0x12121212U, 0xaeaeaeaeU, + 0x40404040U, 0x34343434U, 0x46464646U, 0x3e3e3e3eU, + 0xdbdbdbdbU, 0xcfcfcfcfU, 0xececececU, 0xccccccccU, + 0xc1c1c1c1U, 0xa1a1a1a1U, 0xc0c0c0c0U, 0xd6d6d6d6U, + 0x1d1d1d1dU, 0xf4f4f4f4U, 0x61616161U, 0x3b3b3b3bU, + 0x10101010U, 0xd8d8d8d8U, 0x68686868U, 0xa0a0a0a0U, + 0xb1b1b1b1U, 0x0a0a0a0aU, 0x69696969U, 0x6c6c6c6cU, + 0x49494949U, 0xfafafafaU, 0x76767676U, 0xc4c4c4c4U, + 0x9e9e9e9eU, 0x9b9b9b9bU, 0x6e6e6e6eU, 0x99999999U, + 0xc2c2c2c2U, 0xb7b7b7b7U, 0x98989898U, 0xbcbcbcbcU, + 0x8f8f8f8fU, 0x85858585U, 0x1f1f1f1fU, 0xb4b4b4b4U, + 0xf8f8f8f8U, 0x11111111U, 0x2e2e2e2eU, 0x00000000U, + 0x25252525U, 0x1c1c1c1cU, 0x2a2a2a2aU, 0x3d3d3d3dU, + 0x05050505U, 0x4f4f4f4fU, 0x7b7b7b7bU, 0xb2b2b2b2U, + 0x32323232U, 0x90909090U, 0xafafafafU, 0x19191919U, + 0xa3a3a3a3U, 0xf7f7f7f7U, 0x73737373U, 0x9d9d9d9dU, + 0x15151515U, 0x74747474U, 0xeeeeeeeeU, 0xcacacacaU, + 0x9f9f9f9fU, 0x0f0f0f0fU, 0x1b1b1b1bU, 0x75757575U, + 0x86868686U, 0x84848484U, 0x9c9c9c9cU, 0x4a4a4a4aU, + 0x97979797U, 0x1a1a1a1aU, 0x65656565U, 0xf6f6f6f6U, + 0xededededU, 0x09090909U, 0xbbbbbbbbU, 0x26262626U, + 0x83838383U, 0xebebebebU, 0x6f6f6f6fU, 0x81818181U, + 0x04040404U, 0x6a6a6a6aU, 0x43434343U, 0x01010101U, + 0x17171717U, 0xe1e1e1e1U, 0x87878787U, 0xf5f5f5f5U, + 0x8d8d8d8dU, 0xe3e3e3e3U, 0x23232323U, 0x80808080U, + 0x44444444U, 0x16161616U, 0x66666666U, 0x21212121U, + 0xfefefefeU, 0xd5d5d5d5U, 0x31313131U, 0xd9d9d9d9U, + 0x35353535U, 0x18181818U, 0x02020202U, 0x64646464U, + 0xf2f2f2f2U, 0xf1f1f1f1U, 0x56565656U, 0xcdcdcdcdU, + 0x82828282U, 0xc8c8c8c8U, 0xbabababaU, 0xf0f0f0f0U, + 0xefefefefU, 0xe9e9e9e9U, 0xe8e8e8e8U, 0xfdfdfdfdU, + 0x89898989U, 0xd7d7d7d7U, 0xc7c7c7c7U, 0xb5b5b5b5U, + 0xa4a4a4a4U, 0x2f2f2f2fU, 0x95959595U, 0x13131313U, + 0x0b0b0b0bU, 0xf3f3f3f3U, 0xe0e0e0e0U, 0x37373737U, +}; + +static const ulong32 T5[256] = { + 0x00000000U, 0x01020608U, 0x02040c10U, 0x03060a18U, + 0x04081820U, 0x050a1e28U, 0x060c1430U, 0x070e1238U, + 0x08103040U, 0x09123648U, 0x0a143c50U, 0x0b163a58U, + 0x0c182860U, 0x0d1a2e68U, 0x0e1c2470U, 0x0f1e2278U, + 0x10206080U, 0x11226688U, 0x12246c90U, 0x13266a98U, + 0x142878a0U, 0x152a7ea8U, 0x162c74b0U, 0x172e72b8U, + 0x183050c0U, 0x193256c8U, 0x1a345cd0U, 0x1b365ad8U, + 0x1c3848e0U, 0x1d3a4ee8U, 0x1e3c44f0U, 0x1f3e42f8U, + 0x2040c01dU, 0x2142c615U, 0x2244cc0dU, 0x2346ca05U, + 0x2448d83dU, 0x254ade35U, 0x264cd42dU, 0x274ed225U, + 0x2850f05dU, 0x2952f655U, 0x2a54fc4dU, 0x2b56fa45U, + 0x2c58e87dU, 0x2d5aee75U, 0x2e5ce46dU, 0x2f5ee265U, + 0x3060a09dU, 0x3162a695U, 0x3264ac8dU, 0x3366aa85U, + 0x3468b8bdU, 0x356abeb5U, 0x366cb4adU, 0x376eb2a5U, + 0x387090ddU, 0x397296d5U, 0x3a749ccdU, 0x3b769ac5U, + 0x3c7888fdU, 0x3d7a8ef5U, 0x3e7c84edU, 0x3f7e82e5U, + 0x40809d3aU, 0x41829b32U, 0x4284912aU, 0x43869722U, + 0x4488851aU, 0x458a8312U, 0x468c890aU, 0x478e8f02U, + 0x4890ad7aU, 0x4992ab72U, 0x4a94a16aU, 0x4b96a762U, + 0x4c98b55aU, 0x4d9ab352U, 0x4e9cb94aU, 0x4f9ebf42U, + 0x50a0fdbaU, 0x51a2fbb2U, 0x52a4f1aaU, 0x53a6f7a2U, + 0x54a8e59aU, 0x55aae392U, 0x56ace98aU, 0x57aeef82U, + 0x58b0cdfaU, 0x59b2cbf2U, 0x5ab4c1eaU, 0x5bb6c7e2U, + 0x5cb8d5daU, 0x5dbad3d2U, 0x5ebcd9caU, 0x5fbedfc2U, + 0x60c05d27U, 0x61c25b2fU, 0x62c45137U, 0x63c6573fU, + 0x64c84507U, 0x65ca430fU, 0x66cc4917U, 0x67ce4f1fU, + 0x68d06d67U, 0x69d26b6fU, 0x6ad46177U, 0x6bd6677fU, + 0x6cd87547U, 0x6dda734fU, 0x6edc7957U, 0x6fde7f5fU, + 0x70e03da7U, 0x71e23bafU, 0x72e431b7U, 0x73e637bfU, + 0x74e82587U, 0x75ea238fU, 0x76ec2997U, 0x77ee2f9fU, + 0x78f00de7U, 0x79f20befU, 0x7af401f7U, 0x7bf607ffU, + 0x7cf815c7U, 0x7dfa13cfU, 0x7efc19d7U, 0x7ffe1fdfU, + 0x801d2774U, 0x811f217cU, 0x82192b64U, 0x831b2d6cU, + 0x84153f54U, 0x8517395cU, 0x86113344U, 0x8713354cU, + 0x880d1734U, 0x890f113cU, 0x8a091b24U, 0x8b0b1d2cU, + 0x8c050f14U, 0x8d07091cU, 0x8e010304U, 0x8f03050cU, + 0x903d47f4U, 0x913f41fcU, 0x92394be4U, 0x933b4decU, + 0x94355fd4U, 0x953759dcU, 0x963153c4U, 0x973355ccU, + 0x982d77b4U, 0x992f71bcU, 0x9a297ba4U, 0x9b2b7dacU, + 0x9c256f94U, 0x9d27699cU, 0x9e216384U, 0x9f23658cU, + 0xa05de769U, 0xa15fe161U, 0xa259eb79U, 0xa35bed71U, + 0xa455ff49U, 0xa557f941U, 0xa651f359U, 0xa753f551U, + 0xa84dd729U, 0xa94fd121U, 0xaa49db39U, 0xab4bdd31U, + 0xac45cf09U, 0xad47c901U, 0xae41c319U, 0xaf43c511U, + 0xb07d87e9U, 0xb17f81e1U, 0xb2798bf9U, 0xb37b8df1U, + 0xb4759fc9U, 0xb57799c1U, 0xb67193d9U, 0xb77395d1U, + 0xb86db7a9U, 0xb96fb1a1U, 0xba69bbb9U, 0xbb6bbdb1U, + 0xbc65af89U, 0xbd67a981U, 0xbe61a399U, 0xbf63a591U, + 0xc09dba4eU, 0xc19fbc46U, 0xc299b65eU, 0xc39bb056U, + 0xc495a26eU, 0xc597a466U, 0xc691ae7eU, 0xc793a876U, + 0xc88d8a0eU, 0xc98f8c06U, 0xca89861eU, 0xcb8b8016U, + 0xcc85922eU, 0xcd879426U, 0xce819e3eU, 0xcf839836U, + 0xd0bddaceU, 0xd1bfdcc6U, 0xd2b9d6deU, 0xd3bbd0d6U, + 0xd4b5c2eeU, 0xd5b7c4e6U, 0xd6b1cefeU, 0xd7b3c8f6U, + 0xd8adea8eU, 0xd9afec86U, 0xdaa9e69eU, 0xdbabe096U, + 0xdca5f2aeU, 0xdda7f4a6U, 0xdea1febeU, 0xdfa3f8b6U, + 0xe0dd7a53U, 0xe1df7c5bU, 0xe2d97643U, 0xe3db704bU, + 0xe4d56273U, 0xe5d7647bU, 0xe6d16e63U, 0xe7d3686bU, + 0xe8cd4a13U, 0xe9cf4c1bU, 0xeac94603U, 0xebcb400bU, + 0xecc55233U, 0xedc7543bU, 0xeec15e23U, 0xefc3582bU, + 0xf0fd1ad3U, 0xf1ff1cdbU, 0xf2f916c3U, 0xf3fb10cbU, + 0xf4f502f3U, 0xf5f704fbU, 0xf6f10ee3U, 0xf7f308ebU, + 0xf8ed2a93U, 0xf9ef2c9bU, 0xfae92683U, 0xfbeb208bU, + 0xfce532b3U, 0xfde734bbU, 0xfee13ea3U, 0xffe338abU, +}; + +/** + * The round constants. + */ +static const ulong32 rc[] = { + 0xa7d3e671U, 0xd0ac4d79U, 0x3ac991fcU, 0x1e4754bdU, + 0x8ca57afbU, 0x63b8ddd4U, 0xe5b3c5beU, 0xa9880ca2U, + 0x39df29daU, 0x2ba8cb4cU, 0x4b22aa24U, 0x4170a6f9U, + 0x5ae2b036U, 0x7de433ffU, 0x6020088bU, 0x5eab7f78U, + 0x7c2c57d2U, 0xdc6d7e0dU, 0x5394c328U, +}; + +#endif + + /** + Initialize the Anubis block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +#ifdef LTC_CLEAN_STACK +static int s_anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + int N, R, i, pos, r; + ulong32 kappa[MAX_N]; + ulong32 inter[MAX_N] = { 0 }; /* initialize as all zeroes */ + ulong32 v, K0, K1, K2, K3; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* Valid sizes (in bytes) are 16, 20, 24, 28, 32, 36, and 40. */ + if ((keylen & 3) || (keylen < 16) || (keylen > 40)) { + return CRYPT_INVALID_KEYSIZE; + } + skey->anubis.keyBits = keylen*8; + + /* + * determine the N length parameter: + * (N.B. it is assumed that the key length is valid!) + */ + N = skey->anubis.keyBits >> 5; + + /* + * determine number of rounds from key size: + */ + skey->anubis.R = R = 8 + N; + + if (num_rounds != 0 && num_rounds != skey->anubis.R) { + return CRYPT_INVALID_ROUNDS; + } + + /* + * map cipher key to initial key state (mu): + */ + for (i = 0, pos = 0; i < N; i++, pos += 4) { + kappa[i] = + (((ulong32)key[pos ]) << 24) ^ + (((ulong32)key[pos + 1]) << 16) ^ + (((ulong32)key[pos + 2]) << 8) ^ + (((ulong32)key[pos + 3]) ); + } + + /* + * generate R + 1 round keys: + */ + for (r = 0; r <= R; r++) { + /* + * generate r-th round key K^r: + */ + K0 = T4[(kappa[N - 1] >> 24) & 0xff]; + K1 = T4[(kappa[N - 1] >> 16) & 0xff]; + K2 = T4[(kappa[N - 1] >> 8) & 0xff]; + K3 = T4[(kappa[N - 1] ) & 0xff]; + for (i = N - 2; i >= 0; i--) { + K0 = T4[(kappa[i] >> 24) & 0xff] ^ + (T5[(K0 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K0 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K0 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K0 ) & 0xff] & 0x000000ffU); + K1 = T4[(kappa[i] >> 16) & 0xff] ^ + (T5[(K1 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K1 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K1 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K1 ) & 0xff] & 0x000000ffU); + K2 = T4[(kappa[i] >> 8) & 0xff] ^ + (T5[(K2 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K2 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K2 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K2 ) & 0xff] & 0x000000ffU); + K3 = T4[(kappa[i] ) & 0xff] ^ + (T5[(K3 >> 24) & 0xff] & 0xff000000U) ^ + (T5[(K3 >> 16) & 0xff] & 0x00ff0000U) ^ + (T5[(K3 >> 8) & 0xff] & 0x0000ff00U) ^ + (T5[(K3 ) & 0xff] & 0x000000ffU); + } + /* + -- this is the code to use with the large U tables: + K0 = K1 = K2 = K3 = 0; + for (i = 0; i < N; i++) { + K0 ^= U[i][(kappa[i] >> 24) & 0xff]; + K1 ^= U[i][(kappa[i] >> 16) & 0xff]; + K2 ^= U[i][(kappa[i] >> 8) & 0xff]; + K3 ^= U[i][(kappa[i] ) & 0xff]; + } + */ + skey->anubis.roundKeyEnc[r][0] = K0; + skey->anubis.roundKeyEnc[r][1] = K1; + skey->anubis.roundKeyEnc[r][2] = K2; + skey->anubis.roundKeyEnc[r][3] = K3; + + /* + * compute kappa^{r+1} from kappa^r: + */ + if (r == R) { + break; + } + for (i = 0; i < N; i++) { + int j = i; + inter[i] = T0[(kappa[j--] >> 24) & 0xff]; if (j < 0) j = N - 1; + inter[i] ^= T1[(kappa[j--] >> 16) & 0xff]; if (j < 0) j = N - 1; + inter[i] ^= T2[(kappa[j--] >> 8) & 0xff]; if (j < 0) j = N - 1; + inter[i] ^= T3[(kappa[j ] ) & 0xff]; + } + kappa[0] = inter[0] ^ rc[r]; + for (i = 1; i < N; i++) { + kappa[i] = inter[i]; + } + } + + /* + * generate inverse key schedule: K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}): + */ + for (i = 0; i < 4; i++) { + skey->anubis.roundKeyDec[0][i] = skey->anubis.roundKeyEnc[R][i]; + skey->anubis.roundKeyDec[R][i] = skey->anubis.roundKeyEnc[0][i]; + } + for (r = 1; r < R; r++) { + for (i = 0; i < 4; i++) { + v = skey->anubis.roundKeyEnc[R - r][i]; + skey->anubis.roundKeyDec[r][i] = + T0[T4[(v >> 24) & 0xff] & 0xff] ^ + T1[T4[(v >> 16) & 0xff] & 0xff] ^ + T2[T4[(v >> 8) & 0xff] & 0xff] ^ + T3[T4[(v ) & 0xff] & 0xff]; + } + } + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int err; + err = s_anubis_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(int) * 5 + sizeof(ulong32) * (MAX_N + MAX_N + 5)); + return err; +} +#endif + + +static void anubis_crypt(const unsigned char *plaintext, unsigned char *ciphertext, + const ulong32 roundKey[18 + 1][4], int R) { + int i, pos, r; + ulong32 state[4]; + ulong32 inter[4]; + + /* + * map plaintext block to cipher state (mu) + * and add initial round key (sigma[K^0]): + */ + for (i = 0, pos = 0; i < 4; i++, pos += 4) { + state[i] = + (((ulong32)plaintext[pos ]) << 24) ^ + (((ulong32)plaintext[pos + 1]) << 16) ^ + (((ulong32)plaintext[pos + 2]) << 8) ^ + (((ulong32)plaintext[pos + 3]) ) ^ + roundKey[0][i]; + } + + /* + * R - 1 full rounds: + */ + for (r = 1; r < R; r++) { + inter[0] = + T0[(state[0] >> 24) & 0xff] ^ + T1[(state[1] >> 24) & 0xff] ^ + T2[(state[2] >> 24) & 0xff] ^ + T3[(state[3] >> 24) & 0xff] ^ + roundKey[r][0]; + inter[1] = + T0[(state[0] >> 16) & 0xff] ^ + T1[(state[1] >> 16) & 0xff] ^ + T2[(state[2] >> 16) & 0xff] ^ + T3[(state[3] >> 16) & 0xff] ^ + roundKey[r][1]; + inter[2] = + T0[(state[0] >> 8) & 0xff] ^ + T1[(state[1] >> 8) & 0xff] ^ + T2[(state[2] >> 8) & 0xff] ^ + T3[(state[3] >> 8) & 0xff] ^ + roundKey[r][2]; + inter[3] = + T0[(state[0] ) & 0xff] ^ + T1[(state[1] ) & 0xff] ^ + T2[(state[2] ) & 0xff] ^ + T3[(state[3] ) & 0xff] ^ + roundKey[r][3]; + state[0] = inter[0]; + state[1] = inter[1]; + state[2] = inter[2]; + state[3] = inter[3]; + } + + /* + * last round: + */ + inter[0] = + (T0[(state[0] >> 24) & 0xff] & 0xff000000U) ^ + (T1[(state[1] >> 24) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] >> 24) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] >> 24) & 0xff] & 0x000000ffU) ^ + roundKey[R][0]; + inter[1] = + (T0[(state[0] >> 16) & 0xff] & 0xff000000U) ^ + (T1[(state[1] >> 16) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] >> 16) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] >> 16) & 0xff] & 0x000000ffU) ^ + roundKey[R][1]; + inter[2] = + (T0[(state[0] >> 8) & 0xff] & 0xff000000U) ^ + (T1[(state[1] >> 8) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] >> 8) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] >> 8) & 0xff] & 0x000000ffU) ^ + roundKey[R][2]; + inter[3] = + (T0[(state[0] ) & 0xff] & 0xff000000U) ^ + (T1[(state[1] ) & 0xff] & 0x00ff0000U) ^ + (T2[(state[2] ) & 0xff] & 0x0000ff00U) ^ + (T3[(state[3] ) & 0xff] & 0x000000ffU) ^ + roundKey[R][3]; + + /* + * map cipher state to ciphertext block (mu^{-1}): + */ + for (i = 0, pos = 0; i < 4; i++, pos += 4) { + ulong32 w = inter[i]; + ciphertext[pos ] = (unsigned char)(w >> 24); + ciphertext[pos + 1] = (unsigned char)(w >> 16); + ciphertext[pos + 2] = (unsigned char)(w >> 8); + ciphertext[pos + 3] = (unsigned char)(w ); + } +} + +/** + Encrypts a block of text with Anubis + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->anubis.R < 12 || skey->anubis.R > 18) { + return CRYPT_INVALID_ROUNDS; + } + + anubis_crypt(pt, ct, skey->anubis.roundKeyEnc, skey->anubis.R); + return CRYPT_OK; +} + +/** + Decrypts a block of text with Anubis + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->anubis.R < 12 || skey->anubis.R > 18) { + return CRYPT_INVALID_ROUNDS; + } + + anubis_crypt(ct, pt, skey->anubis.roundKeyDec, skey->anubis.R); + return CRYPT_OK; +} + +/** + Performs a self-test of the Anubis block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int anubis_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct test { + int keylen; + unsigned char pt[16], ct[16], key[40]; + } tests[] = { +#ifndef LTC_ANUBIS_TWEAK + /**** ORIGINAL LTC_ANUBIS ****/ + /* 128 bit keys */ +{ + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xF0, 0x68, 0x60, 0xFC, 0x67, 0x30, 0xE8, 0x18, + 0xF1, 0x32, 0xC7, 0x8A, 0xF4, 0x13, 0x2A, 0xFE }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x66, 0x84, 0x80, 0x07, 0x74, 0x5C, 0x89, + 0xFC, 0x5E, 0xB5, 0xBA, 0xD4, 0xFE, 0x32, 0x6D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 160-bit keys */ +{ + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xBD, 0x5E, 0x32, 0xBE, 0x51, 0x67, 0xA8, 0xE2, + 0x72, 0xD7, 0x95, 0x0F, 0x83, 0xC6, 0x8C, 0x31 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4C, 0x1F, 0x86, 0x2E, 0x11, 0xEB, 0xCE, 0xEB, + 0xFE, 0xB9, 0x73, 0xC9, 0xDF, 0xEF, 0x7A, 0xDB }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 192-bit keys */ +{ + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0xAC, 0x57, 0x44, 0x9D, 0x59, 0x61, 0x66, + 0xD0, 0xC7, 0x9E, 0x04, 0x7C, 0xC7, 0x58, 0xF0 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x71, 0x52, 0xB4, 0xEB, 0x1D, 0xAA, 0x36, 0xFD, + 0x57, 0x14, 0x5F, 0x57, 0x04, 0x9F, 0x70, 0x74 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 224-bit keys */ +{ + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA2, 0xF0, 0xA6, 0xB9, 0x17, 0x93, 0x2A, 0x3B, + 0xEF, 0x08, 0xE8, 0x7A, 0x58, 0xD6, 0xF8, 0x53 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xF0, 0xCA, 0xFC, 0x78, 0x8B, 0x4B, 0x4E, 0x53, + 0x8B, 0xC4, 0x32, 0x6A, 0xF5, 0xB9, 0x1B, 0x5F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 256-bit keys */ +{ + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE0, 0x86, 0xAC, 0x45, 0x6B, 0x3C, 0xE5, 0x13, + 0xED, 0xF5, 0xDF, 0xDD, 0xD6, 0x3B, 0x71, 0x93 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x50, 0x01, 0xB9, 0xF5, 0x21, 0xC1, 0xC1, 0x29, + 0x00, 0xD5, 0xEC, 0x98, 0x2B, 0x9E, 0xE8, 0x21 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 288-bit keys */ +{ + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE8, 0xF4, 0xAF, 0x2B, 0x21, 0xA0, 0x87, 0x9B, + 0x41, 0x95, 0xB9, 0x71, 0x75, 0x79, 0x04, 0x7C }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE6, 0xA6, 0xA5, 0xBC, 0x8B, 0x63, 0x6F, 0xE2, + 0xBD, 0xA7, 0xA7, 0x53, 0xAB, 0x40, 0x22, 0xE0 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 320-bit keys */ +{ + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0x04, 0xD7, 0x2C, 0xC6, 0x85, 0x76, 0x02, + 0x4B, 0xCC, 0x39, 0x80, 0xD8, 0x22, 0xEA, 0xA4 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0x41, 0xE6, 0x7D, 0x4F, 0xD8, 0x64, 0xF0, + 0x44, 0xA8, 0x3C, 0x73, 0x81, 0x7E, 0x53, 0xD8 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +} +#else + /**** Tweaked LTC_ANUBIS ****/ + /* 128 bit keys */ +{ + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB8, 0x35, 0xBD, 0xC3, 0x34, 0x82, 0x9D, 0x83, + 0x71, 0xBF, 0xA3, 0x71, 0xE4, 0xB3, 0xC4, 0xFD }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE6, 0x14, 0x1E, 0xAF, 0xEB, 0xE0, 0x59, 0x3C, + 0x48, 0xE1, 0xCD, 0xF2, 0x1B, 0xBA, 0xA1, 0x89 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 160-bit keys */ +{ + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x97, 0x59, 0x79, 0x4B, 0x5C, 0xA0, 0x70, 0x73, + 0x24, 0xEF, 0xB3, 0x58, 0x67, 0xCA, 0xD4, 0xB3 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 20, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB8, 0x0D, 0xFB, 0x9B, 0xE4, 0xA1, 0x58, 0x87, + 0xB3, 0x76, 0xD5, 0x02, 0x18, 0x95, 0xC1, 0x2E }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 192-bit keys */ +{ + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7D, 0x62, 0x3B, 0x52, 0xC7, 0x4C, 0x64, 0xD8, + 0xEB, 0xC7, 0x2D, 0x57, 0x97, 0x85, 0x43, 0x8F }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB1, 0x0A, 0x59, 0xDD, 0x5D, 0x5D, 0x8D, 0x67, + 0xEC, 0xEE, 0x4A, 0xC4, 0xBE, 0x4F, 0xA8, 0x4F }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 224-bit keys */ +{ + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x68, 0x9E, 0x05, 0x94, 0x6A, 0x94, 0x43, 0x8F, + 0xE7, 0x8E, 0x37, 0x3D, 0x24, 0x97, 0x92, 0xF5 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 28, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDD, 0xB7, 0xB0, 0xB4, 0xE9, 0xB4, 0x9B, 0x9C, + 0x38, 0x20, 0x25, 0x0B, 0x47, 0xC2, 0x1F, 0x89 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 256-bit keys */ +{ + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x96, 0x00, 0xF0, 0x76, 0x91, 0x69, 0x29, 0x87, + 0xF5, 0xE5, 0x97, 0xDB, 0xDB, 0xAF, 0x1B, 0x0A }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x69, 0x9C, 0xAF, 0xDD, 0x94, 0xC7, 0xBC, 0x60, + 0x44, 0xFE, 0x02, 0x05, 0x8A, 0x6E, 0xEF, 0xBD }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, + + /* 288-bit keys */ +{ + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0F, 0xC7, 0xA2, 0xC0, 0x11, 0x17, 0xAC, 0x43, + 0x52, 0x5E, 0xDF, 0x6C, 0xF3, 0x96, 0x33, 0x6C }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 } +}, { + 36, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAD, 0x08, 0x4F, 0xED, 0x55, 0xA6, 0x94, 0x3E, + 0x7E, 0x5E, 0xED, 0x05, 0xA1, 0x9D, 0x41, 0xB4 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 } +}, + + /* 320-bit keys */ +{ + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFE, 0xE2, 0x0E, 0x2A, 0x9D, 0xC5, 0x83, 0xBA, + 0xA3, 0xA6, 0xD6, 0xA6, 0xF2, 0xE8, 0x06, 0xA5 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + 40, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x3D, 0xCC, 0x4A, 0x60, 0x34, 0x9C, 0x28, + 0xA7, 0xDA, 0xA4, 0x3B, 0x0A, 0xD7, 0xFD, 0xC7 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +} +#endif +}; + int x, y; + unsigned char buf[2][16]; + symmetric_key skey; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + anubis_setup(tests[x].key, tests[x].keylen, 0, &skey); + anubis_ecb_encrypt(tests[x].pt, buf[0], &skey); + anubis_ecb_decrypt(buf[0], buf[1], &skey); + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis Encrypt", x) || + compare_testvector(buf[1], 16, tests[x].pt, 16, "Anubis Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + for (y = 0; y < 1000; y++) anubis_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) anubis_ecb_decrypt(buf[0], buf[0], &skey); + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "Anubis 1000", 1000)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void anubis_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int anubis_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 40) { + *keysize = 40; + } else if (*keysize >= 36) { + *keysize = 36; + } else if (*keysize >= 32) { + *keysize = 32; + } else if (*keysize >= 28) { + *keysize = 28; + } else if (*keysize >= 24) { + *keysize = 24; + } else if (*keysize >= 20) { + *keysize = 20; + } else if (*keysize >= 16) { + *keysize = 16; + } else { + return CRYPT_INVALID_KEYSIZE; + } + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/ciphers/blowfish.c b/deps/libtomcrypt/src/ciphers/blowfish.c new file mode 100644 index 0000000..35efc13 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/blowfish.c @@ -0,0 +1,658 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @file blowfish.c + Implementation of the Blowfish block cipher, Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_BLOWFISH + +const struct ltc_cipher_descriptor blowfish_desc = +{ + "blowfish", + 0, + 8, 56, 8, 16, + &blowfish_setup, + &blowfish_ecb_encrypt, + &blowfish_ecb_decrypt, + &blowfish_test, + &blowfish_done, + &blowfish_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 ORIG_P[16 + 2] = { + 0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL, + 0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL, + 0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL, + 0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL, + 0x9216D5D9UL, 0x8979FB1BUL +}; + +static const ulong32 ORIG_S[4][256] = { + { 0xD1310BA6UL, 0x98DFB5ACUL, 0x2FFD72DBUL, 0xD01ADFB7UL, + 0xB8E1AFEDUL, 0x6A267E96UL, 0xBA7C9045UL, 0xF12C7F99UL, + 0x24A19947UL, 0xB3916CF7UL, 0x0801F2E2UL, 0x858EFC16UL, + 0x636920D8UL, 0x71574E69UL, 0xA458FEA3UL, 0xF4933D7EUL, + 0x0D95748FUL, 0x728EB658UL, 0x718BCD58UL, 0x82154AEEUL, + 0x7B54A41DUL, 0xC25A59B5UL, 0x9C30D539UL, 0x2AF26013UL, + 0xC5D1B023UL, 0x286085F0UL, 0xCA417918UL, 0xB8DB38EFUL, + 0x8E79DCB0UL, 0x603A180EUL, 0x6C9E0E8BUL, 0xB01E8A3EUL, + 0xD71577C1UL, 0xBD314B27UL, 0x78AF2FDAUL, 0x55605C60UL, + 0xE65525F3UL, 0xAA55AB94UL, 0x57489862UL, 0x63E81440UL, + 0x55CA396AUL, 0x2AAB10B6UL, 0xB4CC5C34UL, 0x1141E8CEUL, + 0xA15486AFUL, 0x7C72E993UL, 0xB3EE1411UL, 0x636FBC2AUL, + 0x2BA9C55DUL, 0x741831F6UL, 0xCE5C3E16UL, 0x9B87931EUL, + 0xAFD6BA33UL, 0x6C24CF5CUL, 0x7A325381UL, 0x28958677UL, + 0x3B8F4898UL, 0x6B4BB9AFUL, 0xC4BFE81BUL, 0x66282193UL, + 0x61D809CCUL, 0xFB21A991UL, 0x487CAC60UL, 0x5DEC8032UL, + 0xEF845D5DUL, 0xE98575B1UL, 0xDC262302UL, 0xEB651B88UL, + 0x23893E81UL, 0xD396ACC5UL, 0x0F6D6FF3UL, 0x83F44239UL, + 0x2E0B4482UL, 0xA4842004UL, 0x69C8F04AUL, 0x9E1F9B5EUL, + 0x21C66842UL, 0xF6E96C9AUL, 0x670C9C61UL, 0xABD388F0UL, + 0x6A51A0D2UL, 0xD8542F68UL, 0x960FA728UL, 0xAB5133A3UL, + 0x6EEF0B6CUL, 0x137A3BE4UL, 0xBA3BF050UL, 0x7EFB2A98UL, + 0xA1F1651DUL, 0x39AF0176UL, 0x66CA593EUL, 0x82430E88UL, + 0x8CEE8619UL, 0x456F9FB4UL, 0x7D84A5C3UL, 0x3B8B5EBEUL, + 0xE06F75D8UL, 0x85C12073UL, 0x401A449FUL, 0x56C16AA6UL, + 0x4ED3AA62UL, 0x363F7706UL, 0x1BFEDF72UL, 0x429B023DUL, + 0x37D0D724UL, 0xD00A1248UL, 0xDB0FEAD3UL, 0x49F1C09BUL, + 0x075372C9UL, 0x80991B7BUL, 0x25D479D8UL, 0xF6E8DEF7UL, + 0xE3FE501AUL, 0xB6794C3BUL, 0x976CE0BDUL, 0x04C006BAUL, + 0xC1A94FB6UL, 0x409F60C4UL, 0x5E5C9EC2UL, 0x196A2463UL, + 0x68FB6FAFUL, 0x3E6C53B5UL, 0x1339B2EBUL, 0x3B52EC6FUL, + 0x6DFC511FUL, 0x9B30952CUL, 0xCC814544UL, 0xAF5EBD09UL, + 0xBEE3D004UL, 0xDE334AFDUL, 0x660F2807UL, 0x192E4BB3UL, + 0xC0CBA857UL, 0x45C8740FUL, 0xD20B5F39UL, 0xB9D3FBDBUL, + 0x5579C0BDUL, 0x1A60320AUL, 0xD6A100C6UL, 0x402C7279UL, + 0x679F25FEUL, 0xFB1FA3CCUL, 0x8EA5E9F8UL, 0xDB3222F8UL, + 0x3C7516DFUL, 0xFD616B15UL, 0x2F501EC8UL, 0xAD0552ABUL, + 0x323DB5FAUL, 0xFD238760UL, 0x53317B48UL, 0x3E00DF82UL, + 0x9E5C57BBUL, 0xCA6F8CA0UL, 0x1A87562EUL, 0xDF1769DBUL, + 0xD542A8F6UL, 0x287EFFC3UL, 0xAC6732C6UL, 0x8C4F5573UL, + 0x695B27B0UL, 0xBBCA58C8UL, 0xE1FFA35DUL, 0xB8F011A0UL, + 0x10FA3D98UL, 0xFD2183B8UL, 0x4AFCB56CUL, 0x2DD1D35BUL, + 0x9A53E479UL, 0xB6F84565UL, 0xD28E49BCUL, 0x4BFB9790UL, + 0xE1DDF2DAUL, 0xA4CB7E33UL, 0x62FB1341UL, 0xCEE4C6E8UL, + 0xEF20CADAUL, 0x36774C01UL, 0xD07E9EFEUL, 0x2BF11FB4UL, + 0x95DBDA4DUL, 0xAE909198UL, 0xEAAD8E71UL, 0x6B93D5A0UL, + 0xD08ED1D0UL, 0xAFC725E0UL, 0x8E3C5B2FUL, 0x8E7594B7UL, + 0x8FF6E2FBUL, 0xF2122B64UL, 0x8888B812UL, 0x900DF01CUL, + 0x4FAD5EA0UL, 0x688FC31CUL, 0xD1CFF191UL, 0xB3A8C1ADUL, + 0x2F2F2218UL, 0xBE0E1777UL, 0xEA752DFEUL, 0x8B021FA1UL, + 0xE5A0CC0FUL, 0xB56F74E8UL, 0x18ACF3D6UL, 0xCE89E299UL, + 0xB4A84FE0UL, 0xFD13E0B7UL, 0x7CC43B81UL, 0xD2ADA8D9UL, + 0x165FA266UL, 0x80957705UL, 0x93CC7314UL, 0x211A1477UL, + 0xE6AD2065UL, 0x77B5FA86UL, 0xC75442F5UL, 0xFB9D35CFUL, + 0xEBCDAF0CUL, 0x7B3E89A0UL, 0xD6411BD3UL, 0xAE1E7E49UL, + 0x00250E2DUL, 0x2071B35EUL, 0x226800BBUL, 0x57B8E0AFUL, + 0x2464369BUL, 0xF009B91EUL, 0x5563911DUL, 0x59DFA6AAUL, + 0x78C14389UL, 0xD95A537FUL, 0x207D5BA2UL, 0x02E5B9C5UL, + 0x83260376UL, 0x6295CFA9UL, 0x11C81968UL, 0x4E734A41UL, + 0xB3472DCAUL, 0x7B14A94AUL, 0x1B510052UL, 0x9A532915UL, + 0xD60F573FUL, 0xBC9BC6E4UL, 0x2B60A476UL, 0x81E67400UL, + 0x08BA6FB5UL, 0x571BE91FUL, 0xF296EC6BUL, 0x2A0DD915UL, + 0xB6636521UL, 0xE7B9F9B6UL, 0xFF34052EUL, 0xC5855664UL, + 0x53B02D5DUL, 0xA99F8FA1UL, 0x08BA4799UL, 0x6E85076AUL }, + { 0x4B7A70E9UL, 0xB5B32944UL, 0xDB75092EUL, 0xC4192623UL, + 0xAD6EA6B0UL, 0x49A7DF7DUL, 0x9CEE60B8UL, 0x8FEDB266UL, + 0xECAA8C71UL, 0x699A17FFUL, 0x5664526CUL, 0xC2B19EE1UL, + 0x193602A5UL, 0x75094C29UL, 0xA0591340UL, 0xE4183A3EUL, + 0x3F54989AUL, 0x5B429D65UL, 0x6B8FE4D6UL, 0x99F73FD6UL, + 0xA1D29C07UL, 0xEFE830F5UL, 0x4D2D38E6UL, 0xF0255DC1UL, + 0x4CDD2086UL, 0x8470EB26UL, 0x6382E9C6UL, 0x021ECC5EUL, + 0x09686B3FUL, 0x3EBAEFC9UL, 0x3C971814UL, 0x6B6A70A1UL, + 0x687F3584UL, 0x52A0E286UL, 0xB79C5305UL, 0xAA500737UL, + 0x3E07841CUL, 0x7FDEAE5CUL, 0x8E7D44ECUL, 0x5716F2B8UL, + 0xB03ADA37UL, 0xF0500C0DUL, 0xF01C1F04UL, 0x0200B3FFUL, + 0xAE0CF51AUL, 0x3CB574B2UL, 0x25837A58UL, 0xDC0921BDUL, + 0xD19113F9UL, 0x7CA92FF6UL, 0x94324773UL, 0x22F54701UL, + 0x3AE5E581UL, 0x37C2DADCUL, 0xC8B57634UL, 0x9AF3DDA7UL, + 0xA9446146UL, 0x0FD0030EUL, 0xECC8C73EUL, 0xA4751E41UL, + 0xE238CD99UL, 0x3BEA0E2FUL, 0x3280BBA1UL, 0x183EB331UL, + 0x4E548B38UL, 0x4F6DB908UL, 0x6F420D03UL, 0xF60A04BFUL, + 0x2CB81290UL, 0x24977C79UL, 0x5679B072UL, 0xBCAF89AFUL, + 0xDE9A771FUL, 0xD9930810UL, 0xB38BAE12UL, 0xDCCF3F2EUL, + 0x5512721FUL, 0x2E6B7124UL, 0x501ADDE6UL, 0x9F84CD87UL, + 0x7A584718UL, 0x7408DA17UL, 0xBC9F9ABCUL, 0xE94B7D8CUL, + 0xEC7AEC3AUL, 0xDB851DFAUL, 0x63094366UL, 0xC464C3D2UL, + 0xEF1C1847UL, 0x3215D908UL, 0xDD433B37UL, 0x24C2BA16UL, + 0x12A14D43UL, 0x2A65C451UL, 0x50940002UL, 0x133AE4DDUL, + 0x71DFF89EUL, 0x10314E55UL, 0x81AC77D6UL, 0x5F11199BUL, + 0x043556F1UL, 0xD7A3C76BUL, 0x3C11183BUL, 0x5924A509UL, + 0xF28FE6EDUL, 0x97F1FBFAUL, 0x9EBABF2CUL, 0x1E153C6EUL, + 0x86E34570UL, 0xEAE96FB1UL, 0x860E5E0AUL, 0x5A3E2AB3UL, + 0x771FE71CUL, 0x4E3D06FAUL, 0x2965DCB9UL, 0x99E71D0FUL, + 0x803E89D6UL, 0x5266C825UL, 0x2E4CC978UL, 0x9C10B36AUL, + 0xC6150EBAUL, 0x94E2EA78UL, 0xA5FC3C53UL, 0x1E0A2DF4UL, + 0xF2F74EA7UL, 0x361D2B3DUL, 0x1939260FUL, 0x19C27960UL, + 0x5223A708UL, 0xF71312B6UL, 0xEBADFE6EUL, 0xEAC31F66UL, + 0xE3BC4595UL, 0xA67BC883UL, 0xB17F37D1UL, 0x018CFF28UL, + 0xC332DDEFUL, 0xBE6C5AA5UL, 0x65582185UL, 0x68AB9802UL, + 0xEECEA50FUL, 0xDB2F953BUL, 0x2AEF7DADUL, 0x5B6E2F84UL, + 0x1521B628UL, 0x29076170UL, 0xECDD4775UL, 0x619F1510UL, + 0x13CCA830UL, 0xEB61BD96UL, 0x0334FE1EUL, 0xAA0363CFUL, + 0xB5735C90UL, 0x4C70A239UL, 0xD59E9E0BUL, 0xCBAADE14UL, + 0xEECC86BCUL, 0x60622CA7UL, 0x9CAB5CABUL, 0xB2F3846EUL, + 0x648B1EAFUL, 0x19BDF0CAUL, 0xA02369B9UL, 0x655ABB50UL, + 0x40685A32UL, 0x3C2AB4B3UL, 0x319EE9D5UL, 0xC021B8F7UL, + 0x9B540B19UL, 0x875FA099UL, 0x95F7997EUL, 0x623D7DA8UL, + 0xF837889AUL, 0x97E32D77UL, 0x11ED935FUL, 0x16681281UL, + 0x0E358829UL, 0xC7E61FD6UL, 0x96DEDFA1UL, 0x7858BA99UL, + 0x57F584A5UL, 0x1B227263UL, 0x9B83C3FFUL, 0x1AC24696UL, + 0xCDB30AEBUL, 0x532E3054UL, 0x8FD948E4UL, 0x6DBC3128UL, + 0x58EBF2EFUL, 0x34C6FFEAUL, 0xFE28ED61UL, 0xEE7C3C73UL, + 0x5D4A14D9UL, 0xE864B7E3UL, 0x42105D14UL, 0x203E13E0UL, + 0x45EEE2B6UL, 0xA3AAABEAUL, 0xDB6C4F15UL, 0xFACB4FD0UL, + 0xC742F442UL, 0xEF6ABBB5UL, 0x654F3B1DUL, 0x41CD2105UL, + 0xD81E799EUL, 0x86854DC7UL, 0xE44B476AUL, 0x3D816250UL, + 0xCF62A1F2UL, 0x5B8D2646UL, 0xFC8883A0UL, 0xC1C7B6A3UL, + 0x7F1524C3UL, 0x69CB7492UL, 0x47848A0BUL, 0x5692B285UL, + 0x095BBF00UL, 0xAD19489DUL, 0x1462B174UL, 0x23820E00UL, + 0x58428D2AUL, 0x0C55F5EAUL, 0x1DADF43EUL, 0x233F7061UL, + 0x3372F092UL, 0x8D937E41UL, 0xD65FECF1UL, 0x6C223BDBUL, + 0x7CDE3759UL, 0xCBEE7460UL, 0x4085F2A7UL, 0xCE77326EUL, + 0xA6078084UL, 0x19F8509EUL, 0xE8EFD855UL, 0x61D99735UL, + 0xA969A7AAUL, 0xC50C06C2UL, 0x5A04ABFCUL, 0x800BCADCUL, + 0x9E447A2EUL, 0xC3453484UL, 0xFDD56705UL, 0x0E1E9EC9UL, + 0xDB73DBD3UL, 0x105588CDUL, 0x675FDA79UL, 0xE3674340UL, + 0xC5C43465UL, 0x713E38D8UL, 0x3D28F89EUL, 0xF16DFF20UL, + 0x153E21E7UL, 0x8FB03D4AUL, 0xE6E39F2BUL, 0xDB83ADF7UL }, + { 0xE93D5A68UL, 0x948140F7UL, 0xF64C261CUL, 0x94692934UL, + 0x411520F7UL, 0x7602D4F7UL, 0xBCF46B2EUL, 0xD4A20068UL, + 0xD4082471UL, 0x3320F46AUL, 0x43B7D4B7UL, 0x500061AFUL, + 0x1E39F62EUL, 0x97244546UL, 0x14214F74UL, 0xBF8B8840UL, + 0x4D95FC1DUL, 0x96B591AFUL, 0x70F4DDD3UL, 0x66A02F45UL, + 0xBFBC09ECUL, 0x03BD9785UL, 0x7FAC6DD0UL, 0x31CB8504UL, + 0x96EB27B3UL, 0x55FD3941UL, 0xDA2547E6UL, 0xABCA0A9AUL, + 0x28507825UL, 0x530429F4UL, 0x0A2C86DAUL, 0xE9B66DFBUL, + 0x68DC1462UL, 0xD7486900UL, 0x680EC0A4UL, 0x27A18DEEUL, + 0x4F3FFEA2UL, 0xE887AD8CUL, 0xB58CE006UL, 0x7AF4D6B6UL, + 0xAACE1E7CUL, 0xD3375FECUL, 0xCE78A399UL, 0x406B2A42UL, + 0x20FE9E35UL, 0xD9F385B9UL, 0xEE39D7ABUL, 0x3B124E8BUL, + 0x1DC9FAF7UL, 0x4B6D1856UL, 0x26A36631UL, 0xEAE397B2UL, + 0x3A6EFA74UL, 0xDD5B4332UL, 0x6841E7F7UL, 0xCA7820FBUL, + 0xFB0AF54EUL, 0xD8FEB397UL, 0x454056ACUL, 0xBA489527UL, + 0x55533A3AUL, 0x20838D87UL, 0xFE6BA9B7UL, 0xD096954BUL, + 0x55A867BCUL, 0xA1159A58UL, 0xCCA92963UL, 0x99E1DB33UL, + 0xA62A4A56UL, 0x3F3125F9UL, 0x5EF47E1CUL, 0x9029317CUL, + 0xFDF8E802UL, 0x04272F70UL, 0x80BB155CUL, 0x05282CE3UL, + 0x95C11548UL, 0xE4C66D22UL, 0x48C1133FUL, 0xC70F86DCUL, + 0x07F9C9EEUL, 0x41041F0FUL, 0x404779A4UL, 0x5D886E17UL, + 0x325F51EBUL, 0xD59BC0D1UL, 0xF2BCC18FUL, 0x41113564UL, + 0x257B7834UL, 0x602A9C60UL, 0xDFF8E8A3UL, 0x1F636C1BUL, + 0x0E12B4C2UL, 0x02E1329EUL, 0xAF664FD1UL, 0xCAD18115UL, + 0x6B2395E0UL, 0x333E92E1UL, 0x3B240B62UL, 0xEEBEB922UL, + 0x85B2A20EUL, 0xE6BA0D99UL, 0xDE720C8CUL, 0x2DA2F728UL, + 0xD0127845UL, 0x95B794FDUL, 0x647D0862UL, 0xE7CCF5F0UL, + 0x5449A36FUL, 0x877D48FAUL, 0xC39DFD27UL, 0xF33E8D1EUL, + 0x0A476341UL, 0x992EFF74UL, 0x3A6F6EABUL, 0xF4F8FD37UL, + 0xA812DC60UL, 0xA1EBDDF8UL, 0x991BE14CUL, 0xDB6E6B0DUL, + 0xC67B5510UL, 0x6D672C37UL, 0x2765D43BUL, 0xDCD0E804UL, + 0xF1290DC7UL, 0xCC00FFA3UL, 0xB5390F92UL, 0x690FED0BUL, + 0x667B9FFBUL, 0xCEDB7D9CUL, 0xA091CF0BUL, 0xD9155EA3UL, + 0xBB132F88UL, 0x515BAD24UL, 0x7B9479BFUL, 0x763BD6EBUL, + 0x37392EB3UL, 0xCC115979UL, 0x8026E297UL, 0xF42E312DUL, + 0x6842ADA7UL, 0xC66A2B3BUL, 0x12754CCCUL, 0x782EF11CUL, + 0x6A124237UL, 0xB79251E7UL, 0x06A1BBE6UL, 0x4BFB6350UL, + 0x1A6B1018UL, 0x11CAEDFAUL, 0x3D25BDD8UL, 0xE2E1C3C9UL, + 0x44421659UL, 0x0A121386UL, 0xD90CEC6EUL, 0xD5ABEA2AUL, + 0x64AF674EUL, 0xDA86A85FUL, 0xBEBFE988UL, 0x64E4C3FEUL, + 0x9DBC8057UL, 0xF0F7C086UL, 0x60787BF8UL, 0x6003604DUL, + 0xD1FD8346UL, 0xF6381FB0UL, 0x7745AE04UL, 0xD736FCCCUL, + 0x83426B33UL, 0xF01EAB71UL, 0xB0804187UL, 0x3C005E5FUL, + 0x77A057BEUL, 0xBDE8AE24UL, 0x55464299UL, 0xBF582E61UL, + 0x4E58F48FUL, 0xF2DDFDA2UL, 0xF474EF38UL, 0x8789BDC2UL, + 0x5366F9C3UL, 0xC8B38E74UL, 0xB475F255UL, 0x46FCD9B9UL, + 0x7AEB2661UL, 0x8B1DDF84UL, 0x846A0E79UL, 0x915F95E2UL, + 0x466E598EUL, 0x20B45770UL, 0x8CD55591UL, 0xC902DE4CUL, + 0xB90BACE1UL, 0xBB8205D0UL, 0x11A86248UL, 0x7574A99EUL, + 0xB77F19B6UL, 0xE0A9DC09UL, 0x662D09A1UL, 0xC4324633UL, + 0xE85A1F02UL, 0x09F0BE8CUL, 0x4A99A025UL, 0x1D6EFE10UL, + 0x1AB93D1DUL, 0x0BA5A4DFUL, 0xA186F20FUL, 0x2868F169UL, + 0xDCB7DA83UL, 0x573906FEUL, 0xA1E2CE9BUL, 0x4FCD7F52UL, + 0x50115E01UL, 0xA70683FAUL, 0xA002B5C4UL, 0x0DE6D027UL, + 0x9AF88C27UL, 0x773F8641UL, 0xC3604C06UL, 0x61A806B5UL, + 0xF0177A28UL, 0xC0F586E0UL, 0x006058AAUL, 0x30DC7D62UL, + 0x11E69ED7UL, 0x2338EA63UL, 0x53C2DD94UL, 0xC2C21634UL, + 0xBBCBEE56UL, 0x90BCB6DEUL, 0xEBFC7DA1UL, 0xCE591D76UL, + 0x6F05E409UL, 0x4B7C0188UL, 0x39720A3DUL, 0x7C927C24UL, + 0x86E3725FUL, 0x724D9DB9UL, 0x1AC15BB4UL, 0xD39EB8FCUL, + 0xED545578UL, 0x08FCA5B5UL, 0xD83D7CD3UL, 0x4DAD0FC4UL, + 0x1E50EF5EUL, 0xB161E6F8UL, 0xA28514D9UL, 0x6C51133CUL, + 0x6FD5C7E7UL, 0x56E14EC4UL, 0x362ABFCEUL, 0xDDC6C837UL, + 0xD79A3234UL, 0x92638212UL, 0x670EFA8EUL, 0x406000E0UL }, + { 0x3A39CE37UL, 0xD3FAF5CFUL, 0xABC27737UL, 0x5AC52D1BUL, + 0x5CB0679EUL, 0x4FA33742UL, 0xD3822740UL, 0x99BC9BBEUL, + 0xD5118E9DUL, 0xBF0F7315UL, 0xD62D1C7EUL, 0xC700C47BUL, + 0xB78C1B6BUL, 0x21A19045UL, 0xB26EB1BEUL, 0x6A366EB4UL, + 0x5748AB2FUL, 0xBC946E79UL, 0xC6A376D2UL, 0x6549C2C8UL, + 0x530FF8EEUL, 0x468DDE7DUL, 0xD5730A1DUL, 0x4CD04DC6UL, + 0x2939BBDBUL, 0xA9BA4650UL, 0xAC9526E8UL, 0xBE5EE304UL, + 0xA1FAD5F0UL, 0x6A2D519AUL, 0x63EF8CE2UL, 0x9A86EE22UL, + 0xC089C2B8UL, 0x43242EF6UL, 0xA51E03AAUL, 0x9CF2D0A4UL, + 0x83C061BAUL, 0x9BE96A4DUL, 0x8FE51550UL, 0xBA645BD6UL, + 0x2826A2F9UL, 0xA73A3AE1UL, 0x4BA99586UL, 0xEF5562E9UL, + 0xC72FEFD3UL, 0xF752F7DAUL, 0x3F046F69UL, 0x77FA0A59UL, + 0x80E4A915UL, 0x87B08601UL, 0x9B09E6ADUL, 0x3B3EE593UL, + 0xE990FD5AUL, 0x9E34D797UL, 0x2CF0B7D9UL, 0x022B8B51UL, + 0x96D5AC3AUL, 0x017DA67DUL, 0xD1CF3ED6UL, 0x7C7D2D28UL, + 0x1F9F25CFUL, 0xADF2B89BUL, 0x5AD6B472UL, 0x5A88F54CUL, + 0xE029AC71UL, 0xE019A5E6UL, 0x47B0ACFDUL, 0xED93FA9BUL, + 0xE8D3C48DUL, 0x283B57CCUL, 0xF8D56629UL, 0x79132E28UL, + 0x785F0191UL, 0xED756055UL, 0xF7960E44UL, 0xE3D35E8CUL, + 0x15056DD4UL, 0x88F46DBAUL, 0x03A16125UL, 0x0564F0BDUL, + 0xC3EB9E15UL, 0x3C9057A2UL, 0x97271AECUL, 0xA93A072AUL, + 0x1B3F6D9BUL, 0x1E6321F5UL, 0xF59C66FBUL, 0x26DCF319UL, + 0x7533D928UL, 0xB155FDF5UL, 0x03563482UL, 0x8ABA3CBBUL, + 0x28517711UL, 0xC20AD9F8UL, 0xABCC5167UL, 0xCCAD925FUL, + 0x4DE81751UL, 0x3830DC8EUL, 0x379D5862UL, 0x9320F991UL, + 0xEA7A90C2UL, 0xFB3E7BCEUL, 0x5121CE64UL, 0x774FBE32UL, + 0xA8B6E37EUL, 0xC3293D46UL, 0x48DE5369UL, 0x6413E680UL, + 0xA2AE0810UL, 0xDD6DB224UL, 0x69852DFDUL, 0x09072166UL, + 0xB39A460AUL, 0x6445C0DDUL, 0x586CDECFUL, 0x1C20C8AEUL, + 0x5BBEF7DDUL, 0x1B588D40UL, 0xCCD2017FUL, 0x6BB4E3BBUL, + 0xDDA26A7EUL, 0x3A59FF45UL, 0x3E350A44UL, 0xBCB4CDD5UL, + 0x72EACEA8UL, 0xFA6484BBUL, 0x8D6612AEUL, 0xBF3C6F47UL, + 0xD29BE463UL, 0x542F5D9EUL, 0xAEC2771BUL, 0xF64E6370UL, + 0x740E0D8DUL, 0xE75B1357UL, 0xF8721671UL, 0xAF537D5DUL, + 0x4040CB08UL, 0x4EB4E2CCUL, 0x34D2466AUL, 0x0115AF84UL, + 0xE1B00428UL, 0x95983A1DUL, 0x06B89FB4UL, 0xCE6EA048UL, + 0x6F3F3B82UL, 0x3520AB82UL, 0x011A1D4BUL, 0x277227F8UL, + 0x611560B1UL, 0xE7933FDCUL, 0xBB3A792BUL, 0x344525BDUL, + 0xA08839E1UL, 0x51CE794BUL, 0x2F32C9B7UL, 0xA01FBAC9UL, + 0xE01CC87EUL, 0xBCC7D1F6UL, 0xCF0111C3UL, 0xA1E8AAC7UL, + 0x1A908749UL, 0xD44FBD9AUL, 0xD0DADECBUL, 0xD50ADA38UL, + 0x0339C32AUL, 0xC6913667UL, 0x8DF9317CUL, 0xE0B12B4FUL, + 0xF79E59B7UL, 0x43F5BB3AUL, 0xF2D519FFUL, 0x27D9459CUL, + 0xBF97222CUL, 0x15E6FC2AUL, 0x0F91FC71UL, 0x9B941525UL, + 0xFAE59361UL, 0xCEB69CEBUL, 0xC2A86459UL, 0x12BAA8D1UL, + 0xB6C1075EUL, 0xE3056A0CUL, 0x10D25065UL, 0xCB03A442UL, + 0xE0EC6E0EUL, 0x1698DB3BUL, 0x4C98A0BEUL, 0x3278E964UL, + 0x9F1F9532UL, 0xE0D392DFUL, 0xD3A0342BUL, 0x8971F21EUL, + 0x1B0A7441UL, 0x4BA3348CUL, 0xC5BE7120UL, 0xC37632D8UL, + 0xDF359F8DUL, 0x9B992F2EUL, 0xE60B6F47UL, 0x0FE3F11DUL, + 0xE54CDA54UL, 0x1EDAD891UL, 0xCE6279CFUL, 0xCD3E7E6FUL, + 0x1618B166UL, 0xFD2C1D05UL, 0x848FD2C5UL, 0xF6FB2299UL, + 0xF523F357UL, 0xA6327623UL, 0x93A83531UL, 0x56CCCD02UL, + 0xACF08162UL, 0x5A75EBB5UL, 0x6E163697UL, 0x88D273CCUL, + 0xDE966292UL, 0x81B949D0UL, 0x4C50901BUL, 0x71C65614UL, + 0xE6C6C7BDUL, 0x327A140AUL, 0x45E1D006UL, 0xC3F27B9AUL, + 0xC9AA53FDUL, 0x62A80F00UL, 0xBB25BFE2UL, 0x35BDD2F6UL, + 0x71126905UL, 0xB2040222UL, 0xB6CBCF7CUL, 0xCD769C2BUL, + 0x53113EC0UL, 0x1640E3D3UL, 0x38ABBD60UL, 0x2547ADF0UL, + 0xBA38209CUL, 0xF746CE76UL, 0x77AFA1C5UL, 0x20756060UL, + 0x85CBFE4EUL, 0x8AE88DD8UL, 0x7AAAF9B0UL, 0x4CF9AA7EUL, + 0x1948C25CUL, 0x02FB8A8CUL, 0x01C36AE4UL, 0xD6EBE1F9UL, + 0x90D4F869UL, 0xA65CDEA0UL, 0x3F09252DUL, 0xC208E69FUL, + 0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL } +}; + +#ifndef __GNUC__ +#define F(x) ((S1[LTC_BYTE(x,3)] + S2[LTC_BYTE(x,2)]) ^ S3[LTC_BYTE(x,1)]) + S4[LTC_BYTE(x,0)] +#else +#define F(x) ((skey->blowfish.S[0][LTC_BYTE(x,3)] + skey->blowfish.S[1][LTC_BYTE(x,2)]) ^ skey->blowfish.S[2][LTC_BYTE(x,1)]) + skey->blowfish.S[3][LTC_BYTE(x,0)] +#endif + +static void s_blowfish_encipher(ulong32 *L, ulong32 *R, const symmetric_key *skey) +{ + int rounds; + + ulong32 l, r; +#ifndef __GNUC__ + const ulong32 *S1, *S2, *S3, *S4; + + S1 = skey->blowfish.S[0]; + S2 = skey->blowfish.S[1]; + S3 = skey->blowfish.S[2]; + S4 = skey->blowfish.S[3]; +#endif + + l = *L; + r = *R; + + /* do 16 rounds */ + for (rounds = 0; rounds < 16; ) { + l ^= skey->blowfish.K[rounds++]; r ^= F(l); + r ^= skey->blowfish.K[rounds++]; l ^= F(r); + l ^= skey->blowfish.K[rounds++]; r ^= F(l); + r ^= skey->blowfish.K[rounds++]; l ^= F(r); + } + + /* last keying */ + l ^= skey->blowfish.K[16]; + r ^= skey->blowfish.K[17]; + + *L = r; + *R = l; +} + +void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey) +{ + unsigned long i; + ulong32 *d = data; + + for (i = 0; i < blocks; ++i) { + s_blowfish_encipher(d, d + 1, skey); + d += 2; + } +} + +static ulong32 s_blowfish_stream2word(const unsigned char *d, int dlen, int *cur) +{ + unsigned int z; + int y = *cur; + ulong32 ret = 0; + + for (z = 0; z < 4; z++) { + ret = (ret << 8) | ((ulong32)d[y++] & 255); + if (y == dlen) { + y = 0; + } + } + + *cur = y; + return ret; +} + + /** + Expand the Blowfish internal state + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param data The additional data you wish to pass (can be NULL) + @param datalen The additional data length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int blowfish_expand(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey) +{ + ulong32 x, y, A, B[2]; + int i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* load in key bytes (Supplied by David Hopwood) */ + i = 0; + for (x = 0; x < 18; x++) { + A = s_blowfish_stream2word(key, keylen, &i); + skey->blowfish.K[x] ^= A; + } + + + i = 0; + B[0] = 0; + B[1] = 0; + for (x = 0; x < 18; x += 2) { + if (data != NULL) { + B[0] ^= s_blowfish_stream2word(data, datalen, &i); + B[1] ^= s_blowfish_stream2word(data, datalen, &i); + } + /* encrypt it */ + s_blowfish_encipher(&B[0], &B[1], skey); + /* copy it */ + skey->blowfish.K[x] = B[0]; + skey->blowfish.K[x+1] = B[1]; + } + + /* encrypt S array */ + for (x = 0; x < 4; x++) { + for (y = 0; y < 256; y += 2) { + if (data != NULL) { + B[0] ^= s_blowfish_stream2word(data, datalen, &i); + B[1] ^= s_blowfish_stream2word(data, datalen, &i); + } + /* encrypt it */ + s_blowfish_encipher(&B[0], &B[1], skey); + /* copy it */ + skey->blowfish.S[x][y] = B[0]; + skey->blowfish.S[x][y+1] = B[1]; + } + } + +#ifdef LTC_CLEAN_STACK + zeromem(B, sizeof(B)); +#endif + + return CRYPT_OK; +} + +/** + Initialize the Blowfish block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful +*/ +int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, + symmetric_key *skey) +{ + /* check key length */ + if (keylen < 8 || keylen > 56) { + return CRYPT_INVALID_KEYSIZE; + } + /* check rounds */ + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + return blowfish_setup_with_data(key, keylen, NULL, 0, skey); +} + +/** + Alternative initialize of the Blowfish block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param data The additional data you wish to pass (can be NULL) + @param datalen The additional data length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful +*/ + +int blowfish_setup_with_data(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey) +{ + XMEMCPY(skey->blowfish.K, ORIG_P, sizeof(ORIG_P)); + XMEMCPY(skey->blowfish.S, ORIG_S, sizeof(ORIG_S)); + return blowfish_expand(key, keylen, data, datalen, skey); +} + +/** + Encrypts a block of text with Blowfish + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 L, R; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + /* load it */ + LOAD32H(L, &pt[0]); + LOAD32H(R, &pt[4]); + + s_blowfish_encipher(&L, &R, skey); + + /* store */ + STORE32H(L, &ct[0]); + STORE32H(R, &ct[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_blowfish_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with Blowfish + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 L, R; + int r; +#ifndef __GNUC__ + const ulong32 *S1, *S2, *S3, *S4; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + +#ifndef __GNUC__ + S1 = skey->blowfish.S[0]; + S2 = skey->blowfish.S[1]; + S3 = skey->blowfish.S[2]; + S4 = skey->blowfish.S[3]; +#endif + + /* load it */ + LOAD32H(R, &ct[0]); + LOAD32H(L, &ct[4]); + + /* undo last keying */ + R ^= skey->blowfish.K[17]; + L ^= skey->blowfish.K[16]; + + /* do 16 rounds */ + for (r = 15; r > 0; ) { + L ^= F(R); R ^= skey->blowfish.K[r--]; + R ^= F(L); L ^= skey->blowfish.K[r--]; + L ^= F(R); R ^= skey->blowfish.K[r--]; + R ^= F(L); L ^= skey->blowfish.K[r--]; + } + + /* store */ + STORE32H(L, &pt[0]); + STORE32H(R, &pt[4]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_blowfish_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + + +/** + Performs a self-test of the Blowfish block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int blowfish_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + int err; + symmetric_key key; + static const struct { + unsigned char key[8], pt[8], ct[8]; + } tests[] = { + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78} + }, + { + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + { 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A} + }, + { + { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + { 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2} + } + }; + unsigned char tmp[2][8]; + int x, y; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key); + blowfish_ecb_decrypt(tmp[0], tmp[1], &key); + + /* compare */ + if ((compare_testvector(tmp[0], 8, tests[x].ct, 8, "Blowfish Encrypt", x) != 0) || + (compare_testvector(tmp[1], 8, tests[x].pt, 8, "Blowfish Decrypt", x) != 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) blowfish_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void blowfish_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int blowfish_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 56) { + *keysize = 56; + } + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/ciphers/camellia.c b/deps/libtomcrypt/src/ciphers/camellia.c new file mode 100644 index 0000000..733e963 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/camellia.c @@ -0,0 +1,720 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file camellia.c + Implementation by Tom St Denis of Elliptic Semiconductor +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_CAMELLIA + +const struct ltc_cipher_descriptor camellia_desc = { + "camellia", + 23, + 16, 32, 16, 18, + &camellia_setup, + &camellia_ecb_encrypt, + &camellia_ecb_decrypt, + &camellia_test, + &camellia_done, + &camellia_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 SP1110[] = { +0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700, 0xc0c0c000, 0xe5e5e500, +0xe4e4e400, 0x85858500, 0x57575700, 0x35353500, 0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, +0x23232300, 0xefefef00, 0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100, +0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500, 0x92929200, 0xbdbdbd00, +0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00, 0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, +0x3e3e3e00, 0x30303000, 0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00, +0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700, 0x5d5d5d00, 0x3d3d3d00, +0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600, 0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, +0x8b8b8b00, 0x0d0d0d00, 0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00, +0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100, 0x84848400, 0x99999900, +0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200, 0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, +0x6d6d6d00, 0xb7b7b700, 0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700, +0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00, 0x11111100, 0x1c1c1c00, +0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600, 0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, +0xfefefe00, 0x44444400, 0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100, +0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00, 0x69696900, 0x50505000, +0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00, 0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, +0x54545400, 0x5b5b5b00, 0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200, +0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700, 0x75757500, 0xdbdbdb00, +0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00, 0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, +0x87878700, 0x5c5c5c00, 0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300, +0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00, 0xbfbfbf00, 0xe2e2e200, +0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600, 0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, +0x81818100, 0x96969600, 0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00, +0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00, 0xbcbcbc00, 0x8e8e8e00, +0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600, 0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, +0x78787800, 0x98989800, 0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00, +0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200, 0x8d8d8d00, 0xfafafa00, +0x72727200, 0x07070700, 0xb9b9b900, 0x55555500, 0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, +0x36363600, 0x49494900, 0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400, +0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900, 0x43434300, 0xc1c1c100, +0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400, 0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00, +}; + +static const ulong32 SP0222[] = { +0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e, 0x00818181, 0x00cbcbcb, +0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a, 0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, +0x00464646, 0x00dfdfdf, 0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242, +0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca, 0x00252525, 0x007b7b7b, +0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f, 0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, +0x007c7c7c, 0x00606060, 0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434, +0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e, 0x00bababa, 0x007a7a7a, +0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad, 0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, +0x00171717, 0x001a1a1a, 0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a, +0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363, 0x00090909, 0x00333333, +0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585, 0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, +0x00dadada, 0x006f6f6f, 0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf, +0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636, 0x00222222, 0x00383838, +0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c, 0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, +0x00fdfdfd, 0x00888888, 0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323, +0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9, 0x00d2d2d2, 0x00a0a0a0, +0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa, 0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, +0x00a8a8a8, 0x00b6b6b6, 0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5, +0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef, 0x00eaeaea, 0x00b7b7b7, +0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5, 0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, +0x000f0f0f, 0x00b8b8b8, 0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666, +0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe, 0x007f7f7f, 0x00c5c5c5, +0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c, 0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, +0x00030303, 0x002d2d2d, 0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c, +0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc, 0x00797979, 0x001d1d1d, +0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d, 0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, +0x00f0f0f0, 0x00313131, 0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575, +0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545, 0x001b1b1b, 0x00f5f5f5, +0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa, 0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, +0x006c6c6c, 0x00929292, 0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949, +0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393, 0x00868686, 0x00838383, +0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9, 0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d, +}; + +static const ulong32 SP3033[] = { +0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393, 0x60006060, 0xf200f2f2, +0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a, 0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, +0x91009191, 0xf700f7f7, 0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090, +0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2, 0x49004949, 0xde00dede, +0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7, 0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, +0x1f001f1f, 0x18001818, 0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d, +0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3, 0xae00aeae, 0x9e009e9e, +0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b, 0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, +0xc500c5c5, 0x86008686, 0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696, +0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8, 0x42004242, 0xcc00cccc, +0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161, 0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, +0xb600b6b6, 0xdb00dbdb, 0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb, +0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d, 0x88008888, 0x0e000e0e, +0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b, 0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, +0x7f007f7f, 0x22002222, 0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8, +0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e, 0xb400b4b4, 0x28002828, +0x55005555, 0x68006868, 0x50005050, 0xbe00bebe, 0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, +0x2a002a2a, 0xad00adad, 0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969, +0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb, 0xba00baba, 0xed00eded, +0x45004545, 0x81008181, 0x73007373, 0x6d006d6d, 0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, +0xc300c3c3, 0x2e002e2e, 0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999, +0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf, 0xdf00dfdf, 0x71007171, +0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313, 0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, +0xc000c0c0, 0x4b004b4b, 0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717, +0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737, 0x5e005e5e, 0x47004747, +0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b, 0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, +0x3c003c3c, 0x4c004c4c, 0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d, +0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151, 0xc600c6c6, 0x7d007d7d, +0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa, 0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, +0x1b001b1b, 0xa400a4a4, 0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252, +0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4, 0xa100a1a1, 0xe000e0e0, +0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a, 0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f, +}; + +static const ulong32 SP4404[] = { +0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057, 0xeaea00ea, 0xaeae00ae, +0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5, 0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, +0x86860086, 0xafaf00af, 0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b, +0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a, 0x51510051, 0x6c6c006c, +0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0, 0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, +0xdfdf00df, 0xcbcb00cb, 0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004, +0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c, 0x53530053, 0xf2f200f2, +0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a, 0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, +0xaaaa00aa, 0xa0a000a0, 0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064, +0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6, 0x09090009, 0xdddd00dd, +0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090, 0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, +0x52520052, 0xd8d800d8, 0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063, +0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9, 0x2f2f002f, 0xb4b400b4, +0x78780078, 0x06060006, 0xe7e700e7, 0x71710071, 0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, +0x72720072, 0xb9b900b9, 0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1, +0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad, 0x77770077, 0x80800080, +0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5, 0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, +0xefef00ef, 0x93930093, 0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd, +0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f, 0xc5c500c5, 0x1a1a001a, +0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d, 0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, +0x0d0d000d, 0x66660066, 0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099, +0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031, 0x17170017, 0xd7d700d7, +0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c, 0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, +0x44440044, 0xb2b200b2, 0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050, +0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095, 0xffff00ff, 0xd2d200d2, +0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db, 0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, +0x5c5c005c, 0x02020002, 0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2, +0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b, 0xbebe00be, 0x2e2e002e, +0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e, 0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, +0x98980098, 0x6a6a006a, 0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa, +0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068, 0x38380038, 0xa4a400a4, +0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1, 0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e, +}; + +static const ulong64 key_sigma[] = { + CONST64(0xA09E667F3BCC908B), + CONST64(0xB67AE8584CAA73B2), + CONST64(0xC6EF372FE94F82BE), + CONST64(0x54FF53A5F1D36F1C), + CONST64(0x10E527FADE682D1D), + CONST64(0xB05688C2B3E6C1FD) +}; + +static ulong64 F(ulong64 x) +{ + ulong32 D, U; + +#define loc(i) ((8-i)*8) + + D = SP1110[(x >> loc(8)) & 0xFF] ^ SP0222[(x >> loc(5)) & 0xFF] ^ SP3033[(x >> loc(6)) & 0xFF] ^ SP4404[(x >> loc(7)) & 0xFF]; + U = SP1110[(x >> loc(1)) & 0xFF] ^ SP0222[(x >> loc(2)) & 0xFF] ^ SP3033[(x >> loc(3)) & 0xFF] ^ SP4404[(x >> loc(4)) & 0xFF]; + + D ^= U; + U = D ^ RORc(U, 8); + + return ((ulong64)U) | (((ulong64)D) << CONST64(32)); +} + +static void rot_128(const unsigned char *in, unsigned count, unsigned char *out) +{ + unsigned x, w, b; + + w = count >> 3; + b = count & 7; + + for (x = 0; x < 16; x++) { + out[x] = (in[(x+w)&15] << b) | (in[(x+w+1)&15] >> (8 - b)); + } +} + +int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + unsigned char T[48], kA[16], kB[16], kR[16], kL[16]; + int x; + ulong64 A, B; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* Valid sizes (in bytes) are 16, 24, 32 */ + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + /* number of rounds */ + skey->camellia.R = (keylen == 16) ? 18 : 24; + + if (num_rounds != 0 && num_rounds != skey->camellia.R) { + return CRYPT_INVALID_ROUNDS; + } + + /* expand key */ + if (keylen == 16) { + for (x = 0; x < 16; x++) { + T[x] = key[x]; + T[x + 16] = 0; + } + } else if (keylen == 24) { + for (x = 0; x < 24; x++) { + T[x] = key[x]; + } + for (x = 24; x < 32; x++) { + T[x] = key[x-8] ^ 0xFF; + } + } else { + for (x = 0; x < 32; x++) { + T[x] = key[x]; + } + } + + for (x = 0; x < 16; x++) { + kL[x] = T[x]; + kR[x] = T[x + 16]; + } + + for (x = 32; x < 48; x++) { + T[x] = T[x - 32] ^ T[x - 16]; + } + + /* first two rounds */ + LOAD64H(A, T+32); LOAD64H(B, T+40); + B ^= F(A ^ key_sigma[0]); + A ^= F(B ^ key_sigma[1]); + STORE64H(A, T+32); STORE64H(B, T+40); + + /* xor kL in */ + for (x = 0; x < 16; x++) { T[x+32] ^= kL[x]; } + + /* next two rounds */ + LOAD64H(A, T+32); LOAD64H(B, T+40); + B ^= F(A ^ key_sigma[2]); + A ^= F(B ^ key_sigma[3]); + STORE64H(A, T+32); STORE64H(B, T+40); + + /* grab KA */ + for (x = 0; x < 16; x++) { kA[x] = T[x+32]; } + + /* xor kR in */ + for (x = 0; x < 16; x++) { T[x+32] ^= kR[x]; } + + if (keylen == 16) { + /* grab whitening keys kw1 and kw2 */ + LOAD64H(skey->camellia.kw[0], kL); + LOAD64H(skey->camellia.kw[1], kL+8); + + /* k1-k2 */ + LOAD64H(skey->camellia.k[0], kA); + LOAD64H(skey->camellia.k[1], kA+8); + + /* rotate kL by 15, k3/k4 */ + rot_128(kL, 15, T+32); + LOAD64H(skey->camellia.k[2], T+32); + LOAD64H(skey->camellia.k[3], T+40); + + /* rotate kA by 15, k5/k6 */ + rot_128(kA, 15, T+32); + LOAD64H(skey->camellia.k[4], T+32); + LOAD64H(skey->camellia.k[5], T+40); + + /* rotate kA by 30, kl1, kl2 */ + rot_128(kA, 30, T+32); + LOAD64H(skey->camellia.kl[0], T+32); + LOAD64H(skey->camellia.kl[1], T+40); + + /* rotate kL by 45, k7/k8 */ + rot_128(kL, 45, T+32); + LOAD64H(skey->camellia.k[6], T+32); + LOAD64H(skey->camellia.k[7], T+40); + + /* rotate kA by 45, k9/k10 */ + rot_128(kA, 45, T+32); + LOAD64H(skey->camellia.k[8], T+32); + rot_128(kL, 60, T+32); + LOAD64H(skey->camellia.k[9], T+40); + + /* rotate kA by 60, k11/k12 */ + rot_128(kA, 60, T+32); + LOAD64H(skey->camellia.k[10], T+32); + LOAD64H(skey->camellia.k[11], T+40); + + /* rotate kL by 77, kl3, kl4 */ + rot_128(kL, 77, T+32); + LOAD64H(skey->camellia.kl[2], T+32); + LOAD64H(skey->camellia.kl[3], T+40); + + /* rotate kL by 94, k13/k14 */ + rot_128(kL, 94, T+32); + LOAD64H(skey->camellia.k[12], T+32); + LOAD64H(skey->camellia.k[13], T+40); + + /* rotate kA by 94, k15/k16 */ + rot_128(kA, 94, T+32); + LOAD64H(skey->camellia.k[14], T+32); + LOAD64H(skey->camellia.k[15], T+40); + + /* rotate kL by 111, k17/k18 */ + rot_128(kL, 111, T+32); + LOAD64H(skey->camellia.k[16], T+32); + LOAD64H(skey->camellia.k[17], T+40); + + /* rotate kA by 111, kw3/kw4 */ + rot_128(kA, 111, T+32); + LOAD64H(skey->camellia.kw[2], T+32); + LOAD64H(skey->camellia.kw[3], T+40); + } else { + /* last two rounds */ + LOAD64H(A, T+32); LOAD64H(B, T+40); + B ^= F(A ^ key_sigma[4]); + A ^= F(B ^ key_sigma[5]); + STORE64H(A, T+32); STORE64H(B, T+40); + + /* grab kB */ + for (x = 0; x < 16; x++) { kB[x] = T[x+32]; } + + /* kw1/2 from kL*/ + LOAD64H(skey->camellia.kw[0], kL); + LOAD64H(skey->camellia.kw[1], kL+8); + + /* k1/k2 = kB */ + LOAD64H(skey->camellia.k[0], kB); + LOAD64H(skey->camellia.k[1], kB+8); + + /* k3/k4 = kR by 15 */ + rot_128(kR, 15, T+32); + LOAD64H(skey->camellia.k[2], T+32); + LOAD64H(skey->camellia.k[3], T+40); + + /* k5/k7 = kA by 15 */ + rot_128(kA, 15, T+32); + LOAD64H(skey->camellia.k[4], T+32); + LOAD64H(skey->camellia.k[5], T+40); + + /* kl1/2 = kR by 30 */ + rot_128(kR, 30, T+32); + LOAD64H(skey->camellia.kl[0], T+32); + LOAD64H(skey->camellia.kl[1], T+40); + + /* k7/k8 = kB by 30 */ + rot_128(kB, 30, T+32); + LOAD64H(skey->camellia.k[6], T+32); + LOAD64H(skey->camellia.k[7], T+40); + + /* k9/k10 = kL by 45 */ + rot_128(kL, 45, T+32); + LOAD64H(skey->camellia.k[8], T+32); + LOAD64H(skey->camellia.k[9], T+40); + + /* k11/k12 = kA by 45 */ + rot_128(kA, 45, T+32); + LOAD64H(skey->camellia.k[10], T+32); + LOAD64H(skey->camellia.k[11], T+40); + + /* kl3/4 = kL by 60 */ + rot_128(kL, 60, T+32); + LOAD64H(skey->camellia.kl[2], T+32); + LOAD64H(skey->camellia.kl[3], T+40); + + /* k13/k14 = kR by 60 */ + rot_128(kR, 60, T+32); + LOAD64H(skey->camellia.k[12], T+32); + LOAD64H(skey->camellia.k[13], T+40); + + /* k15/k16 = kB by 15 */ + rot_128(kB, 60, T+32); + LOAD64H(skey->camellia.k[14], T+32); + LOAD64H(skey->camellia.k[15], T+40); + + /* k17/k18 = kL by 77 */ + rot_128(kL, 77, T+32); + LOAD64H(skey->camellia.k[16], T+32); + LOAD64H(skey->camellia.k[17], T+40); + + /* kl5/6 = kA by 77 */ + rot_128(kA, 77, T+32); + LOAD64H(skey->camellia.kl[4], T+32); + LOAD64H(skey->camellia.kl[5], T+40); + + /* k19/k20 = kR by 94 */ + rot_128(kR, 94, T+32); + LOAD64H(skey->camellia.k[18], T+32); + LOAD64H(skey->camellia.k[19], T+40); + + /* k21/k22 = kA by 94 */ + rot_128(kA, 94, T+32); + LOAD64H(skey->camellia.k[20], T+32); + LOAD64H(skey->camellia.k[21], T+40); + + /* k23/k24 = kL by 111 */ + rot_128(kL, 111, T+32); + LOAD64H(skey->camellia.k[22], T+32); + LOAD64H(skey->camellia.k[23], T+40); + + /* kw2/kw3 = kB by 111 */ + rot_128(kB, 111, T+32); + LOAD64H(skey->camellia.kw[2], T+32); + LOAD64H(skey->camellia.kw[3], T+40); + } + + return CRYPT_OK; +} + +int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong64 L, R; + ulong32 a, b; + + LOAD64H(L, pt+0); LOAD64H(R, pt+8); + L ^= skey->camellia.kw[0]; + R ^= skey->camellia.kw[1]; + + /* first 6 rounds */ + R ^= F(L ^ skey->camellia.k[0]); + L ^= F(R ^ skey->camellia.k[1]); + R ^= F(L ^ skey->camellia.k[2]); + L ^= F(R ^ skey->camellia.k[3]); + R ^= F(L ^ skey->camellia.k[4]); + L ^= F(R ^ skey->camellia.k[5]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); + a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); + R = (((ulong64)a) << 32) | b; + + /* second 6 rounds */ + R ^= F(L ^ skey->camellia.k[6]); + L ^= F(R ^ skey->camellia.k[7]); + R ^= F(L ^ skey->camellia.k[8]); + L ^= F(R ^ skey->camellia.k[9]); + R ^= F(L ^ skey->camellia.k[10]); + L ^= F(R ^ skey->camellia.k[11]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); + a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); + R = (((ulong64)a) << 32) | b; + + /* third 6 rounds */ + R ^= F(L ^ skey->camellia.k[12]); + L ^= F(R ^ skey->camellia.k[13]); + R ^= F(L ^ skey->camellia.k[14]); + L ^= F(R ^ skey->camellia.k[15]); + R ^= F(L ^ skey->camellia.k[16]); + L ^= F(R ^ skey->camellia.k[17]); + + /* next FL */ + if (skey->camellia.R == 24) { + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); + a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); + R = (((ulong64)a) << 32) | b; + + /* fourth 6 rounds */ + R ^= F(L ^ skey->camellia.k[18]); + L ^= F(R ^ skey->camellia.k[19]); + R ^= F(L ^ skey->camellia.k[20]); + L ^= F(R ^ skey->camellia.k[21]); + R ^= F(L ^ skey->camellia.k[22]); + L ^= F(R ^ skey->camellia.k[23]); + } + + L ^= skey->camellia.kw[3]; + R ^= skey->camellia.kw[2]; + + STORE64H(R, ct+0); STORE64H(L, ct+8); + + return CRYPT_OK; +} + +int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong64 L, R; + ulong32 a, b; + + LOAD64H(R, ct+0); LOAD64H(L, ct+8); + L ^= skey->camellia.kw[3]; + R ^= skey->camellia.kw[2]; + + /* next FL */ + if (skey->camellia.R == 24) { + /* fourth 6 rounds */ + L ^= F(R ^ skey->camellia.k[23]); + R ^= F(L ^ skey->camellia.k[22]); + L ^= F(R ^ skey->camellia.k[21]); + R ^= F(L ^ skey->camellia.k[20]); + L ^= F(R ^ skey->camellia.k[19]); + R ^= F(L ^ skey->camellia.k[18]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[4] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[4] >> 32)), 1); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[5] >> 32)), 1); + a ^= b | (skey->camellia.kl[5] & 0xFFFFFFFFU); + R = (((ulong64)a) << 32) | b; + + } + + /* third 6 rounds */ + L ^= F(R ^ skey->camellia.k[17]); + R ^= F(L ^ skey->camellia.k[16]); + L ^= F(R ^ skey->camellia.k[15]); + R ^= F(L ^ skey->camellia.k[14]); + L ^= F(R ^ skey->camellia.k[13]); + R ^= F(L ^ skey->camellia.k[12]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[2] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[2] >> 32)), 1); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[3] >> 32)), 1); + a ^= b | (skey->camellia.kl[3] & 0xFFFFFFFFU); + R = (((ulong64)a) << 32) | b; + + /* second 6 rounds */ + L ^= F(R ^ skey->camellia.k[11]); + R ^= F(L ^ skey->camellia.k[10]); + L ^= F(R ^ skey->camellia.k[9]); + R ^= F(L ^ skey->camellia.k[8]); + L ^= F(R ^ skey->camellia.k[7]); + R ^= F(L ^ skey->camellia.k[6]); + + /* FL */ + a = (ulong32)(L >> 32); + b = (ulong32)(L & 0xFFFFFFFFUL); + a ^= b | (skey->camellia.kl[0] & 0xFFFFFFFFU); + b ^= ROL((a & (ulong32)(skey->camellia.kl[0] >> 32)), 1); + L = (((ulong64)a) << 32) | b; + + /* FL^-1 */ + a = (ulong32)(R >> 32); + b = (ulong32)(R & 0xFFFFFFFFUL); + b ^= ROL((a & (ulong32)(skey->camellia.kl[1] >> 32)), 1); + a ^= b | (skey->camellia.kl[1] & 0xFFFFFFFFU); + R = (((ulong64)a) << 32) | b; + + /* first 6 rounds */ + L ^= F(R ^ skey->camellia.k[5]); + R ^= F(L ^ skey->camellia.k[4]); + L ^= F(R ^ skey->camellia.k[3]); + R ^= F(L ^ skey->camellia.k[2]); + L ^= F(R ^ skey->camellia.k[1]); + R ^= F(L ^ skey->camellia.k[0]); + + R ^= skey->camellia.kw[1]; + L ^= skey->camellia.kw[0]; + + STORE64H(R, pt+8); STORE64H(L, pt+0); + + return CRYPT_OK; +} + +int camellia_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + +{ + 16, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 } +}, + +{ + 24, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 } +}, + + +{ + 32, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 } +}, + +{ + 32, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }, + { 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 }, + { 0x79, 0x60, 0x10, 0x9F, 0xB6, 0xDC, 0x42, 0x94, + 0x7F, 0xCF, 0xE5, 0x9E, 0xA3, 0xC5, 0xEB, 0x6B } +} +}; + unsigned char buf[2][16]; + symmetric_key skey; + int err; + unsigned int x; + + for (x = 0; x < sizeof(tests)/sizeof(tests[0]); x++) { + zeromem(&skey, sizeof(skey)); + if ((err = camellia_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { + return err; + } + if ((err = camellia_ecb_encrypt(tests[x].pt, buf[0], &skey)) != CRYPT_OK) { + camellia_done(&skey); + return err; + } + if ((err = camellia_ecb_decrypt(tests[x].ct, buf[1], &skey)) != CRYPT_OK) { + camellia_done(&skey); + return err; + } + camellia_done(&skey); + if (compare_testvector(tests[x].ct, 16, buf[0], 16, "Camellia Encrypt", x) || + compare_testvector(tests[x].pt, 16, buf[1], 16, "Camellia Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +void camellia_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int camellia_keysize(int *keysize) +{ + if (*keysize >= 32) { *keysize = 32; } + else if (*keysize >= 24) { *keysize = 24; } + else if (*keysize >= 16) { *keysize = 16; } + else return CRYPT_INVALID_KEYSIZE; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/cast5.c b/deps/libtomcrypt/src/ciphers/cast5.c new file mode 100644 index 0000000..3b401a5 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/cast5.c @@ -0,0 +1,705 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /** + @file cast5.c + Implementation of LTC_CAST5 (RFC 2144) by Tom St Denis + */ +#include "tomcrypt_private.h" + +#ifdef LTC_CAST5 + +const struct ltc_cipher_descriptor cast5_desc = { + "cast5", + 15, + 5, 16, 8, 16, + &cast5_setup, + &cast5_ecb_encrypt, + &cast5_ecb_decrypt, + &cast5_test, + &cast5_done, + &cast5_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 S1[256] = { +0x30fb40d4UL, 0x9fa0ff0bUL, 0x6beccd2fUL, 0x3f258c7aUL, 0x1e213f2fUL, 0x9c004dd3UL, +0x6003e540UL, 0xcf9fc949UL, 0xbfd4af27UL, 0x88bbbdb5UL, 0xe2034090UL, 0x98d09675UL, +0x6e63a0e0UL, 0x15c361d2UL, 0xc2e7661dUL, 0x22d4ff8eUL, 0x28683b6fUL, 0xc07fd059UL, +0xff2379c8UL, 0x775f50e2UL, 0x43c340d3UL, 0xdf2f8656UL, 0x887ca41aUL, 0xa2d2bd2dUL, +0xa1c9e0d6UL, 0x346c4819UL, 0x61b76d87UL, 0x22540f2fUL, 0x2abe32e1UL, 0xaa54166bUL, +0x22568e3aUL, 0xa2d341d0UL, 0x66db40c8UL, 0xa784392fUL, 0x004dff2fUL, 0x2db9d2deUL, +0x97943facUL, 0x4a97c1d8UL, 0x527644b7UL, 0xb5f437a7UL, 0xb82cbaefUL, 0xd751d159UL, +0x6ff7f0edUL, 0x5a097a1fUL, 0x827b68d0UL, 0x90ecf52eUL, 0x22b0c054UL, 0xbc8e5935UL, +0x4b6d2f7fUL, 0x50bb64a2UL, 0xd2664910UL, 0xbee5812dUL, 0xb7332290UL, 0xe93b159fUL, +0xb48ee411UL, 0x4bff345dUL, 0xfd45c240UL, 0xad31973fUL, 0xc4f6d02eUL, 0x55fc8165UL, +0xd5b1caadUL, 0xa1ac2daeUL, 0xa2d4b76dUL, 0xc19b0c50UL, 0x882240f2UL, 0x0c6e4f38UL, +0xa4e4bfd7UL, 0x4f5ba272UL, 0x564c1d2fUL, 0xc59c5319UL, 0xb949e354UL, 0xb04669feUL, +0xb1b6ab8aUL, 0xc71358ddUL, 0x6385c545UL, 0x110f935dUL, 0x57538ad5UL, 0x6a390493UL, +0xe63d37e0UL, 0x2a54f6b3UL, 0x3a787d5fUL, 0x6276a0b5UL, 0x19a6fcdfUL, 0x7a42206aUL, +0x29f9d4d5UL, 0xf61b1891UL, 0xbb72275eUL, 0xaa508167UL, 0x38901091UL, 0xc6b505ebUL, +0x84c7cb8cUL, 0x2ad75a0fUL, 0x874a1427UL, 0xa2d1936bUL, 0x2ad286afUL, 0xaa56d291UL, +0xd7894360UL, 0x425c750dUL, 0x93b39e26UL, 0x187184c9UL, 0x6c00b32dUL, 0x73e2bb14UL, +0xa0bebc3cUL, 0x54623779UL, 0x64459eabUL, 0x3f328b82UL, 0x7718cf82UL, 0x59a2cea6UL, +0x04ee002eUL, 0x89fe78e6UL, 0x3fab0950UL, 0x325ff6c2UL, 0x81383f05UL, 0x6963c5c8UL, +0x76cb5ad6UL, 0xd49974c9UL, 0xca180dcfUL, 0x380782d5UL, 0xc7fa5cf6UL, 0x8ac31511UL, +0x35e79e13UL, 0x47da91d0UL, 0xf40f9086UL, 0xa7e2419eUL, 0x31366241UL, 0x051ef495UL, +0xaa573b04UL, 0x4a805d8dUL, 0x548300d0UL, 0x00322a3cUL, 0xbf64cddfUL, 0xba57a68eUL, +0x75c6372bUL, 0x50afd341UL, 0xa7c13275UL, 0x915a0bf5UL, 0x6b54bfabUL, 0x2b0b1426UL, +0xab4cc9d7UL, 0x449ccd82UL, 0xf7fbf265UL, 0xab85c5f3UL, 0x1b55db94UL, 0xaad4e324UL, +0xcfa4bd3fUL, 0x2deaa3e2UL, 0x9e204d02UL, 0xc8bd25acUL, 0xeadf55b3UL, 0xd5bd9e98UL, +0xe31231b2UL, 0x2ad5ad6cUL, 0x954329deUL, 0xadbe4528UL, 0xd8710f69UL, 0xaa51c90fUL, +0xaa786bf6UL, 0x22513f1eUL, 0xaa51a79bUL, 0x2ad344ccUL, 0x7b5a41f0UL, 0xd37cfbadUL, +0x1b069505UL, 0x41ece491UL, 0xb4c332e6UL, 0x032268d4UL, 0xc9600accUL, 0xce387e6dUL, +0xbf6bb16cUL, 0x6a70fb78UL, 0x0d03d9c9UL, 0xd4df39deUL, 0xe01063daUL, 0x4736f464UL, +0x5ad328d8UL, 0xb347cc96UL, 0x75bb0fc3UL, 0x98511bfbUL, 0x4ffbcc35UL, 0xb58bcf6aUL, +0xe11f0abcUL, 0xbfc5fe4aUL, 0xa70aec10UL, 0xac39570aUL, 0x3f04442fUL, 0x6188b153UL, +0xe0397a2eUL, 0x5727cb79UL, 0x9ceb418fUL, 0x1cacd68dUL, 0x2ad37c96UL, 0x0175cb9dUL, +0xc69dff09UL, 0xc75b65f0UL, 0xd9db40d8UL, 0xec0e7779UL, 0x4744ead4UL, 0xb11c3274UL, +0xdd24cb9eUL, 0x7e1c54bdUL, 0xf01144f9UL, 0xd2240eb1UL, 0x9675b3fdUL, 0xa3ac3755UL, +0xd47c27afUL, 0x51c85f4dUL, 0x56907596UL, 0xa5bb15e6UL, 0x580304f0UL, 0xca042cf1UL, +0x011a37eaUL, 0x8dbfaadbUL, 0x35ba3e4aUL, 0x3526ffa0UL, 0xc37b4d09UL, 0xbc306ed9UL, +0x98a52666UL, 0x5648f725UL, 0xff5e569dUL, 0x0ced63d0UL, 0x7c63b2cfUL, 0x700b45e1UL, +0xd5ea50f1UL, 0x85a92872UL, 0xaf1fbda7UL, 0xd4234870UL, 0xa7870bf3UL, 0x2d3b4d79UL, +0x42e04198UL, 0x0cd0ede7UL, 0x26470db8UL, 0xf881814cUL, 0x474d6ad7UL, 0x7c0c5e5cUL, +0xd1231959UL, 0x381b7298UL, 0xf5d2f4dbUL, 0xab838653UL, 0x6e2f1e23UL, 0x83719c9eUL, +0xbd91e046UL, 0x9a56456eUL, 0xdc39200cUL, 0x20c8c571UL, 0x962bda1cUL, 0xe1e696ffUL, +0xb141ab08UL, 0x7cca89b9UL, 0x1a69e783UL, 0x02cc4843UL, 0xa2f7c579UL, 0x429ef47dUL, +0x427b169cUL, 0x5ac9f049UL, 0xdd8f0f00UL, 0x5c8165bfUL}; + +static const ulong32 S2[256] = { +0x1f201094UL, 0xef0ba75bUL, 0x69e3cf7eUL, 0x393f4380UL, 0xfe61cf7aUL, 0xeec5207aUL, +0x55889c94UL, 0x72fc0651UL, 0xada7ef79UL, 0x4e1d7235UL, 0xd55a63ceUL, 0xde0436baUL, +0x99c430efUL, 0x5f0c0794UL, 0x18dcdb7dUL, 0xa1d6eff3UL, 0xa0b52f7bUL, 0x59e83605UL, +0xee15b094UL, 0xe9ffd909UL, 0xdc440086UL, 0xef944459UL, 0xba83ccb3UL, 0xe0c3cdfbUL, +0xd1da4181UL, 0x3b092ab1UL, 0xf997f1c1UL, 0xa5e6cf7bUL, 0x01420ddbUL, 0xe4e7ef5bUL, +0x25a1ff41UL, 0xe180f806UL, 0x1fc41080UL, 0x179bee7aUL, 0xd37ac6a9UL, 0xfe5830a4UL, +0x98de8b7fUL, 0x77e83f4eUL, 0x79929269UL, 0x24fa9f7bUL, 0xe113c85bUL, 0xacc40083UL, +0xd7503525UL, 0xf7ea615fUL, 0x62143154UL, 0x0d554b63UL, 0x5d681121UL, 0xc866c359UL, +0x3d63cf73UL, 0xcee234c0UL, 0xd4d87e87UL, 0x5c672b21UL, 0x071f6181UL, 0x39f7627fUL, +0x361e3084UL, 0xe4eb573bUL, 0x602f64a4UL, 0xd63acd9cUL, 0x1bbc4635UL, 0x9e81032dUL, +0x2701f50cUL, 0x99847ab4UL, 0xa0e3df79UL, 0xba6cf38cUL, 0x10843094UL, 0x2537a95eUL, +0xf46f6ffeUL, 0xa1ff3b1fUL, 0x208cfb6aUL, 0x8f458c74UL, 0xd9e0a227UL, 0x4ec73a34UL, +0xfc884f69UL, 0x3e4de8dfUL, 0xef0e0088UL, 0x3559648dUL, 0x8a45388cUL, 0x1d804366UL, +0x721d9bfdUL, 0xa58684bbUL, 0xe8256333UL, 0x844e8212UL, 0x128d8098UL, 0xfed33fb4UL, +0xce280ae1UL, 0x27e19ba5UL, 0xd5a6c252UL, 0xe49754bdUL, 0xc5d655ddUL, 0xeb667064UL, +0x77840b4dUL, 0xa1b6a801UL, 0x84db26a9UL, 0xe0b56714UL, 0x21f043b7UL, 0xe5d05860UL, +0x54f03084UL, 0x066ff472UL, 0xa31aa153UL, 0xdadc4755UL, 0xb5625dbfUL, 0x68561be6UL, +0x83ca6b94UL, 0x2d6ed23bUL, 0xeccf01dbUL, 0xa6d3d0baUL, 0xb6803d5cUL, 0xaf77a709UL, +0x33b4a34cUL, 0x397bc8d6UL, 0x5ee22b95UL, 0x5f0e5304UL, 0x81ed6f61UL, 0x20e74364UL, +0xb45e1378UL, 0xde18639bUL, 0x881ca122UL, 0xb96726d1UL, 0x8049a7e8UL, 0x22b7da7bUL, +0x5e552d25UL, 0x5272d237UL, 0x79d2951cUL, 0xc60d894cUL, 0x488cb402UL, 0x1ba4fe5bUL, +0xa4b09f6bUL, 0x1ca815cfUL, 0xa20c3005UL, 0x8871df63UL, 0xb9de2fcbUL, 0x0cc6c9e9UL, +0x0beeff53UL, 0xe3214517UL, 0xb4542835UL, 0x9f63293cUL, 0xee41e729UL, 0x6e1d2d7cUL, +0x50045286UL, 0x1e6685f3UL, 0xf33401c6UL, 0x30a22c95UL, 0x31a70850UL, 0x60930f13UL, +0x73f98417UL, 0xa1269859UL, 0xec645c44UL, 0x52c877a9UL, 0xcdff33a6UL, 0xa02b1741UL, +0x7cbad9a2UL, 0x2180036fUL, 0x50d99c08UL, 0xcb3f4861UL, 0xc26bd765UL, 0x64a3f6abUL, +0x80342676UL, 0x25a75e7bUL, 0xe4e6d1fcUL, 0x20c710e6UL, 0xcdf0b680UL, 0x17844d3bUL, +0x31eef84dUL, 0x7e0824e4UL, 0x2ccb49ebUL, 0x846a3baeUL, 0x8ff77888UL, 0xee5d60f6UL, +0x7af75673UL, 0x2fdd5cdbUL, 0xa11631c1UL, 0x30f66f43UL, 0xb3faec54UL, 0x157fd7faUL, +0xef8579ccUL, 0xd152de58UL, 0xdb2ffd5eUL, 0x8f32ce19UL, 0x306af97aUL, 0x02f03ef8UL, +0x99319ad5UL, 0xc242fa0fUL, 0xa7e3ebb0UL, 0xc68e4906UL, 0xb8da230cUL, 0x80823028UL, +0xdcdef3c8UL, 0xd35fb171UL, 0x088a1bc8UL, 0xbec0c560UL, 0x61a3c9e8UL, 0xbca8f54dUL, +0xc72feffaUL, 0x22822e99UL, 0x82c570b4UL, 0xd8d94e89UL, 0x8b1c34bcUL, 0x301e16e6UL, +0x273be979UL, 0xb0ffeaa6UL, 0x61d9b8c6UL, 0x00b24869UL, 0xb7ffce3fUL, 0x08dc283bUL, +0x43daf65aUL, 0xf7e19798UL, 0x7619b72fUL, 0x8f1c9ba4UL, 0xdc8637a0UL, 0x16a7d3b1UL, +0x9fc393b7UL, 0xa7136eebUL, 0xc6bcc63eUL, 0x1a513742UL, 0xef6828bcUL, 0x520365d6UL, +0x2d6a77abUL, 0x3527ed4bUL, 0x821fd216UL, 0x095c6e2eUL, 0xdb92f2fbUL, 0x5eea29cbUL, +0x145892f5UL, 0x91584f7fUL, 0x5483697bUL, 0x2667a8ccUL, 0x85196048UL, 0x8c4baceaUL, +0x833860d4UL, 0x0d23e0f9UL, 0x6c387e8aUL, 0x0ae6d249UL, 0xb284600cUL, 0xd835731dUL, +0xdcb1c647UL, 0xac4c56eaUL, 0x3ebd81b3UL, 0x230eabb0UL, 0x6438bc87UL, 0xf0b5b1faUL, +0x8f5ea2b3UL, 0xfc184642UL, 0x0a036b7aUL, 0x4fb089bdUL, 0x649da589UL, 0xa345415eUL, +0x5c038323UL, 0x3e5d3bb9UL, 0x43d79572UL, 0x7e6dd07cUL, 0x06dfdf1eUL, 0x6c6cc4efUL, +0x7160a539UL, 0x73bfbe70UL, 0x83877605UL, 0x4523ecf1UL}; + +static const ulong32 S3[256] = { +0x8defc240UL, 0x25fa5d9fUL, 0xeb903dbfUL, 0xe810c907UL, 0x47607fffUL, 0x369fe44bUL, +0x8c1fc644UL, 0xaececa90UL, 0xbeb1f9bfUL, 0xeefbcaeaUL, 0xe8cf1950UL, 0x51df07aeUL, +0x920e8806UL, 0xf0ad0548UL, 0xe13c8d83UL, 0x927010d5UL, 0x11107d9fUL, 0x07647db9UL, +0xb2e3e4d4UL, 0x3d4f285eUL, 0xb9afa820UL, 0xfade82e0UL, 0xa067268bUL, 0x8272792eUL, +0x553fb2c0UL, 0x489ae22bUL, 0xd4ef9794UL, 0x125e3fbcUL, 0x21fffceeUL, 0x825b1bfdUL, +0x9255c5edUL, 0x1257a240UL, 0x4e1a8302UL, 0xbae07fffUL, 0x528246e7UL, 0x8e57140eUL, +0x3373f7bfUL, 0x8c9f8188UL, 0xa6fc4ee8UL, 0xc982b5a5UL, 0xa8c01db7UL, 0x579fc264UL, +0x67094f31UL, 0xf2bd3f5fUL, 0x40fff7c1UL, 0x1fb78dfcUL, 0x8e6bd2c1UL, 0x437be59bUL, +0x99b03dbfUL, 0xb5dbc64bUL, 0x638dc0e6UL, 0x55819d99UL, 0xa197c81cUL, 0x4a012d6eUL, +0xc5884a28UL, 0xccc36f71UL, 0xb843c213UL, 0x6c0743f1UL, 0x8309893cUL, 0x0feddd5fUL, +0x2f7fe850UL, 0xd7c07f7eUL, 0x02507fbfUL, 0x5afb9a04UL, 0xa747d2d0UL, 0x1651192eUL, +0xaf70bf3eUL, 0x58c31380UL, 0x5f98302eUL, 0x727cc3c4UL, 0x0a0fb402UL, 0x0f7fef82UL, +0x8c96fdadUL, 0x5d2c2aaeUL, 0x8ee99a49UL, 0x50da88b8UL, 0x8427f4a0UL, 0x1eac5790UL, +0x796fb449UL, 0x8252dc15UL, 0xefbd7d9bUL, 0xa672597dUL, 0xada840d8UL, 0x45f54504UL, +0xfa5d7403UL, 0xe83ec305UL, 0x4f91751aUL, 0x925669c2UL, 0x23efe941UL, 0xa903f12eUL, +0x60270df2UL, 0x0276e4b6UL, 0x94fd6574UL, 0x927985b2UL, 0x8276dbcbUL, 0x02778176UL, +0xf8af918dUL, 0x4e48f79eUL, 0x8f616ddfUL, 0xe29d840eUL, 0x842f7d83UL, 0x340ce5c8UL, +0x96bbb682UL, 0x93b4b148UL, 0xef303cabUL, 0x984faf28UL, 0x779faf9bUL, 0x92dc560dUL, +0x224d1e20UL, 0x8437aa88UL, 0x7d29dc96UL, 0x2756d3dcUL, 0x8b907ceeUL, 0xb51fd240UL, +0xe7c07ce3UL, 0xe566b4a1UL, 0xc3e9615eUL, 0x3cf8209dUL, 0x6094d1e3UL, 0xcd9ca341UL, +0x5c76460eUL, 0x00ea983bUL, 0xd4d67881UL, 0xfd47572cUL, 0xf76cedd9UL, 0xbda8229cUL, +0x127dadaaUL, 0x438a074eUL, 0x1f97c090UL, 0x081bdb8aUL, 0x93a07ebeUL, 0xb938ca15UL, +0x97b03cffUL, 0x3dc2c0f8UL, 0x8d1ab2ecUL, 0x64380e51UL, 0x68cc7bfbUL, 0xd90f2788UL, +0x12490181UL, 0x5de5ffd4UL, 0xdd7ef86aUL, 0x76a2e214UL, 0xb9a40368UL, 0x925d958fUL, +0x4b39fffaUL, 0xba39aee9UL, 0xa4ffd30bUL, 0xfaf7933bUL, 0x6d498623UL, 0x193cbcfaUL, +0x27627545UL, 0x825cf47aUL, 0x61bd8ba0UL, 0xd11e42d1UL, 0xcead04f4UL, 0x127ea392UL, +0x10428db7UL, 0x8272a972UL, 0x9270c4a8UL, 0x127de50bUL, 0x285ba1c8UL, 0x3c62f44fUL, +0x35c0eaa5UL, 0xe805d231UL, 0x428929fbUL, 0xb4fcdf82UL, 0x4fb66a53UL, 0x0e7dc15bUL, +0x1f081fabUL, 0x108618aeUL, 0xfcfd086dUL, 0xf9ff2889UL, 0x694bcc11UL, 0x236a5caeUL, +0x12deca4dUL, 0x2c3f8cc5UL, 0xd2d02dfeUL, 0xf8ef5896UL, 0xe4cf52daUL, 0x95155b67UL, +0x494a488cUL, 0xb9b6a80cUL, 0x5c8f82bcUL, 0x89d36b45UL, 0x3a609437UL, 0xec00c9a9UL, +0x44715253UL, 0x0a874b49UL, 0xd773bc40UL, 0x7c34671cUL, 0x02717ef6UL, 0x4feb5536UL, +0xa2d02fffUL, 0xd2bf60c4UL, 0xd43f03c0UL, 0x50b4ef6dUL, 0x07478cd1UL, 0x006e1888UL, +0xa2e53f55UL, 0xb9e6d4bcUL, 0xa2048016UL, 0x97573833UL, 0xd7207d67UL, 0xde0f8f3dUL, +0x72f87b33UL, 0xabcc4f33UL, 0x7688c55dUL, 0x7b00a6b0UL, 0x947b0001UL, 0x570075d2UL, +0xf9bb88f8UL, 0x8942019eUL, 0x4264a5ffUL, 0x856302e0UL, 0x72dbd92bUL, 0xee971b69UL, +0x6ea22fdeUL, 0x5f08ae2bUL, 0xaf7a616dUL, 0xe5c98767UL, 0xcf1febd2UL, 0x61efc8c2UL, +0xf1ac2571UL, 0xcc8239c2UL, 0x67214cb8UL, 0xb1e583d1UL, 0xb7dc3e62UL, 0x7f10bdceUL, +0xf90a5c38UL, 0x0ff0443dUL, 0x606e6dc6UL, 0x60543a49UL, 0x5727c148UL, 0x2be98a1dUL, +0x8ab41738UL, 0x20e1be24UL, 0xaf96da0fUL, 0x68458425UL, 0x99833be5UL, 0x600d457dUL, +0x282f9350UL, 0x8334b362UL, 0xd91d1120UL, 0x2b6d8da0UL, 0x642b1e31UL, 0x9c305a00UL, +0x52bce688UL, 0x1b03588aUL, 0xf7baefd5UL, 0x4142ed9cUL, 0xa4315c11UL, 0x83323ec5UL, +0xdfef4636UL, 0xa133c501UL, 0xe9d3531cUL, 0xee353783UL}; + +static const ulong32 S4[256] = { +0x9db30420UL, 0x1fb6e9deUL, 0xa7be7befUL, 0xd273a298UL, 0x4a4f7bdbUL, 0x64ad8c57UL, +0x85510443UL, 0xfa020ed1UL, 0x7e287affUL, 0xe60fb663UL, 0x095f35a1UL, 0x79ebf120UL, +0xfd059d43UL, 0x6497b7b1UL, 0xf3641f63UL, 0x241e4adfUL, 0x28147f5fUL, 0x4fa2b8cdUL, +0xc9430040UL, 0x0cc32220UL, 0xfdd30b30UL, 0xc0a5374fUL, 0x1d2d00d9UL, 0x24147b15UL, +0xee4d111aUL, 0x0fca5167UL, 0x71ff904cUL, 0x2d195ffeUL, 0x1a05645fUL, 0x0c13fefeUL, +0x081b08caUL, 0x05170121UL, 0x80530100UL, 0xe83e5efeUL, 0xac9af4f8UL, 0x7fe72701UL, +0xd2b8ee5fUL, 0x06df4261UL, 0xbb9e9b8aUL, 0x7293ea25UL, 0xce84ffdfUL, 0xf5718801UL, +0x3dd64b04UL, 0xa26f263bUL, 0x7ed48400UL, 0x547eebe6UL, 0x446d4ca0UL, 0x6cf3d6f5UL, +0x2649abdfUL, 0xaea0c7f5UL, 0x36338cc1UL, 0x503f7e93UL, 0xd3772061UL, 0x11b638e1UL, +0x72500e03UL, 0xf80eb2bbUL, 0xabe0502eUL, 0xec8d77deUL, 0x57971e81UL, 0xe14f6746UL, +0xc9335400UL, 0x6920318fUL, 0x081dbb99UL, 0xffc304a5UL, 0x4d351805UL, 0x7f3d5ce3UL, +0xa6c866c6UL, 0x5d5bcca9UL, 0xdaec6feaUL, 0x9f926f91UL, 0x9f46222fUL, 0x3991467dUL, +0xa5bf6d8eUL, 0x1143c44fUL, 0x43958302UL, 0xd0214eebUL, 0x022083b8UL, 0x3fb6180cUL, +0x18f8931eUL, 0x281658e6UL, 0x26486e3eUL, 0x8bd78a70UL, 0x7477e4c1UL, 0xb506e07cUL, +0xf32d0a25UL, 0x79098b02UL, 0xe4eabb81UL, 0x28123b23UL, 0x69dead38UL, 0x1574ca16UL, +0xdf871b62UL, 0x211c40b7UL, 0xa51a9ef9UL, 0x0014377bUL, 0x041e8ac8UL, 0x09114003UL, +0xbd59e4d2UL, 0xe3d156d5UL, 0x4fe876d5UL, 0x2f91a340UL, 0x557be8deUL, 0x00eae4a7UL, +0x0ce5c2ecUL, 0x4db4bba6UL, 0xe756bdffUL, 0xdd3369acUL, 0xec17b035UL, 0x06572327UL, +0x99afc8b0UL, 0x56c8c391UL, 0x6b65811cUL, 0x5e146119UL, 0x6e85cb75UL, 0xbe07c002UL, +0xc2325577UL, 0x893ff4ecUL, 0x5bbfc92dUL, 0xd0ec3b25UL, 0xb7801ab7UL, 0x8d6d3b24UL, +0x20c763efUL, 0xc366a5fcUL, 0x9c382880UL, 0x0ace3205UL, 0xaac9548aUL, 0xeca1d7c7UL, +0x041afa32UL, 0x1d16625aUL, 0x6701902cUL, 0x9b757a54UL, 0x31d477f7UL, 0x9126b031UL, +0x36cc6fdbUL, 0xc70b8b46UL, 0xd9e66a48UL, 0x56e55a79UL, 0x026a4cebUL, 0x52437effUL, +0x2f8f76b4UL, 0x0df980a5UL, 0x8674cde3UL, 0xedda04ebUL, 0x17a9be04UL, 0x2c18f4dfUL, +0xb7747f9dUL, 0xab2af7b4UL, 0xefc34d20UL, 0x2e096b7cUL, 0x1741a254UL, 0xe5b6a035UL, +0x213d42f6UL, 0x2c1c7c26UL, 0x61c2f50fUL, 0x6552daf9UL, 0xd2c231f8UL, 0x25130f69UL, +0xd8167fa2UL, 0x0418f2c8UL, 0x001a96a6UL, 0x0d1526abUL, 0x63315c21UL, 0x5e0a72ecUL, +0x49bafefdUL, 0x187908d9UL, 0x8d0dbd86UL, 0x311170a7UL, 0x3e9b640cUL, 0xcc3e10d7UL, +0xd5cad3b6UL, 0x0caec388UL, 0xf73001e1UL, 0x6c728affUL, 0x71eae2a1UL, 0x1f9af36eUL, +0xcfcbd12fUL, 0xc1de8417UL, 0xac07be6bUL, 0xcb44a1d8UL, 0x8b9b0f56UL, 0x013988c3UL, +0xb1c52fcaUL, 0xb4be31cdUL, 0xd8782806UL, 0x12a3a4e2UL, 0x6f7de532UL, 0x58fd7eb6UL, +0xd01ee900UL, 0x24adffc2UL, 0xf4990fc5UL, 0x9711aac5UL, 0x001d7b95UL, 0x82e5e7d2UL, +0x109873f6UL, 0x00613096UL, 0xc32d9521UL, 0xada121ffUL, 0x29908415UL, 0x7fbb977fUL, +0xaf9eb3dbUL, 0x29c9ed2aUL, 0x5ce2a465UL, 0xa730f32cUL, 0xd0aa3fe8UL, 0x8a5cc091UL, +0xd49e2ce7UL, 0x0ce454a9UL, 0xd60acd86UL, 0x015f1919UL, 0x77079103UL, 0xdea03af6UL, +0x78a8565eUL, 0xdee356dfUL, 0x21f05cbeUL, 0x8b75e387UL, 0xb3c50651UL, 0xb8a5c3efUL, +0xd8eeb6d2UL, 0xe523be77UL, 0xc2154529UL, 0x2f69efdfUL, 0xafe67afbUL, 0xf470c4b2UL, +0xf3e0eb5bUL, 0xd6cc9876UL, 0x39e4460cUL, 0x1fda8538UL, 0x1987832fUL, 0xca007367UL, +0xa99144f8UL, 0x296b299eUL, 0x492fc295UL, 0x9266beabUL, 0xb5676e69UL, 0x9bd3dddaUL, +0xdf7e052fUL, 0xdb25701cUL, 0x1b5e51eeUL, 0xf65324e6UL, 0x6afce36cUL, 0x0316cc04UL, +0x8644213eUL, 0xb7dc59d0UL, 0x7965291fUL, 0xccd6fd43UL, 0x41823979UL, 0x932bcdf6UL, +0xb657c34dUL, 0x4edfd282UL, 0x7ae5290cUL, 0x3cb9536bUL, 0x851e20feUL, 0x9833557eUL, +0x13ecf0b0UL, 0xd3ffb372UL, 0x3f85c5c1UL, 0x0aef7ed2UL}; + +static const ulong32 S5[256] = { +0x7ec90c04UL, 0x2c6e74b9UL, 0x9b0e66dfUL, 0xa6337911UL, 0xb86a7fffUL, 0x1dd358f5UL, +0x44dd9d44UL, 0x1731167fUL, 0x08fbf1faUL, 0xe7f511ccUL, 0xd2051b00UL, 0x735aba00UL, +0x2ab722d8UL, 0x386381cbUL, 0xacf6243aUL, 0x69befd7aUL, 0xe6a2e77fUL, 0xf0c720cdUL, +0xc4494816UL, 0xccf5c180UL, 0x38851640UL, 0x15b0a848UL, 0xe68b18cbUL, 0x4caadeffUL, +0x5f480a01UL, 0x0412b2aaUL, 0x259814fcUL, 0x41d0efe2UL, 0x4e40b48dUL, 0x248eb6fbUL, +0x8dba1cfeUL, 0x41a99b02UL, 0x1a550a04UL, 0xba8f65cbUL, 0x7251f4e7UL, 0x95a51725UL, +0xc106ecd7UL, 0x97a5980aUL, 0xc539b9aaUL, 0x4d79fe6aUL, 0xf2f3f763UL, 0x68af8040UL, +0xed0c9e56UL, 0x11b4958bUL, 0xe1eb5a88UL, 0x8709e6b0UL, 0xd7e07156UL, 0x4e29fea7UL, +0x6366e52dUL, 0x02d1c000UL, 0xc4ac8e05UL, 0x9377f571UL, 0x0c05372aUL, 0x578535f2UL, +0x2261be02UL, 0xd642a0c9UL, 0xdf13a280UL, 0x74b55bd2UL, 0x682199c0UL, 0xd421e5ecUL, +0x53fb3ce8UL, 0xc8adedb3UL, 0x28a87fc9UL, 0x3d959981UL, 0x5c1ff900UL, 0xfe38d399UL, +0x0c4eff0bUL, 0x062407eaUL, 0xaa2f4fb1UL, 0x4fb96976UL, 0x90c79505UL, 0xb0a8a774UL, +0xef55a1ffUL, 0xe59ca2c2UL, 0xa6b62d27UL, 0xe66a4263UL, 0xdf65001fUL, 0x0ec50966UL, +0xdfdd55bcUL, 0x29de0655UL, 0x911e739aUL, 0x17af8975UL, 0x32c7911cUL, 0x89f89468UL, +0x0d01e980UL, 0x524755f4UL, 0x03b63cc9UL, 0x0cc844b2UL, 0xbcf3f0aaUL, 0x87ac36e9UL, +0xe53a7426UL, 0x01b3d82bUL, 0x1a9e7449UL, 0x64ee2d7eUL, 0xcddbb1daUL, 0x01c94910UL, +0xb868bf80UL, 0x0d26f3fdUL, 0x9342ede7UL, 0x04a5c284UL, 0x636737b6UL, 0x50f5b616UL, +0xf24766e3UL, 0x8eca36c1UL, 0x136e05dbUL, 0xfef18391UL, 0xfb887a37UL, 0xd6e7f7d4UL, +0xc7fb7dc9UL, 0x3063fcdfUL, 0xb6f589deUL, 0xec2941daUL, 0x26e46695UL, 0xb7566419UL, +0xf654efc5UL, 0xd08d58b7UL, 0x48925401UL, 0xc1bacb7fUL, 0xe5ff550fUL, 0xb6083049UL, +0x5bb5d0e8UL, 0x87d72e5aUL, 0xab6a6ee1UL, 0x223a66ceUL, 0xc62bf3cdUL, 0x9e0885f9UL, +0x68cb3e47UL, 0x086c010fUL, 0xa21de820UL, 0xd18b69deUL, 0xf3f65777UL, 0xfa02c3f6UL, +0x407edac3UL, 0xcbb3d550UL, 0x1793084dUL, 0xb0d70ebaUL, 0x0ab378d5UL, 0xd951fb0cUL, +0xded7da56UL, 0x4124bbe4UL, 0x94ca0b56UL, 0x0f5755d1UL, 0xe0e1e56eUL, 0x6184b5beUL, +0x580a249fUL, 0x94f74bc0UL, 0xe327888eUL, 0x9f7b5561UL, 0xc3dc0280UL, 0x05687715UL, +0x646c6bd7UL, 0x44904db3UL, 0x66b4f0a3UL, 0xc0f1648aUL, 0x697ed5afUL, 0x49e92ff6UL, +0x309e374fUL, 0x2cb6356aUL, 0x85808573UL, 0x4991f840UL, 0x76f0ae02UL, 0x083be84dUL, +0x28421c9aUL, 0x44489406UL, 0x736e4cb8UL, 0xc1092910UL, 0x8bc95fc6UL, 0x7d869cf4UL, +0x134f616fUL, 0x2e77118dUL, 0xb31b2be1UL, 0xaa90b472UL, 0x3ca5d717UL, 0x7d161bbaUL, +0x9cad9010UL, 0xaf462ba2UL, 0x9fe459d2UL, 0x45d34559UL, 0xd9f2da13UL, 0xdbc65487UL, +0xf3e4f94eUL, 0x176d486fUL, 0x097c13eaUL, 0x631da5c7UL, 0x445f7382UL, 0x175683f4UL, +0xcdc66a97UL, 0x70be0288UL, 0xb3cdcf72UL, 0x6e5dd2f3UL, 0x20936079UL, 0x459b80a5UL, +0xbe60e2dbUL, 0xa9c23101UL, 0xeba5315cUL, 0x224e42f2UL, 0x1c5c1572UL, 0xf6721b2cUL, +0x1ad2fff3UL, 0x8c25404eUL, 0x324ed72fUL, 0x4067b7fdUL, 0x0523138eUL, 0x5ca3bc78UL, +0xdc0fd66eUL, 0x75922283UL, 0x784d6b17UL, 0x58ebb16eUL, 0x44094f85UL, 0x3f481d87UL, +0xfcfeae7bUL, 0x77b5ff76UL, 0x8c2302bfUL, 0xaaf47556UL, 0x5f46b02aUL, 0x2b092801UL, +0x3d38f5f7UL, 0x0ca81f36UL, 0x52af4a8aUL, 0x66d5e7c0UL, 0xdf3b0874UL, 0x95055110UL, +0x1b5ad7a8UL, 0xf61ed5adUL, 0x6cf6e479UL, 0x20758184UL, 0xd0cefa65UL, 0x88f7be58UL, +0x4a046826UL, 0x0ff6f8f3UL, 0xa09c7f70UL, 0x5346aba0UL, 0x5ce96c28UL, 0xe176eda3UL, +0x6bac307fUL, 0x376829d2UL, 0x85360fa9UL, 0x17e3fe2aUL, 0x24b79767UL, 0xf5a96b20UL, +0xd6cd2595UL, 0x68ff1ebfUL, 0x7555442cUL, 0xf19f06beUL, 0xf9e0659aUL, 0xeeb9491dUL, +0x34010718UL, 0xbb30cab8UL, 0xe822fe15UL, 0x88570983UL, 0x750e6249UL, 0xda627e55UL, +0x5e76ffa8UL, 0xb1534546UL, 0x6d47de08UL, 0xefe9e7d4UL}; + +static const ulong32 S6[256] = { +0xf6fa8f9dUL, 0x2cac6ce1UL, 0x4ca34867UL, 0xe2337f7cUL, 0x95db08e7UL, 0x016843b4UL, +0xeced5cbcUL, 0x325553acUL, 0xbf9f0960UL, 0xdfa1e2edUL, 0x83f0579dUL, 0x63ed86b9UL, +0x1ab6a6b8UL, 0xde5ebe39UL, 0xf38ff732UL, 0x8989b138UL, 0x33f14961UL, 0xc01937bdUL, +0xf506c6daUL, 0xe4625e7eUL, 0xa308ea99UL, 0x4e23e33cUL, 0x79cbd7ccUL, 0x48a14367UL, +0xa3149619UL, 0xfec94bd5UL, 0xa114174aUL, 0xeaa01866UL, 0xa084db2dUL, 0x09a8486fUL, +0xa888614aUL, 0x2900af98UL, 0x01665991UL, 0xe1992863UL, 0xc8f30c60UL, 0x2e78ef3cUL, +0xd0d51932UL, 0xcf0fec14UL, 0xf7ca07d2UL, 0xd0a82072UL, 0xfd41197eUL, 0x9305a6b0UL, +0xe86be3daUL, 0x74bed3cdUL, 0x372da53cUL, 0x4c7f4448UL, 0xdab5d440UL, 0x6dba0ec3UL, +0x083919a7UL, 0x9fbaeed9UL, 0x49dbcfb0UL, 0x4e670c53UL, 0x5c3d9c01UL, 0x64bdb941UL, +0x2c0e636aUL, 0xba7dd9cdUL, 0xea6f7388UL, 0xe70bc762UL, 0x35f29adbUL, 0x5c4cdd8dUL, +0xf0d48d8cUL, 0xb88153e2UL, 0x08a19866UL, 0x1ae2eac8UL, 0x284caf89UL, 0xaa928223UL, +0x9334be53UL, 0x3b3a21bfUL, 0x16434be3UL, 0x9aea3906UL, 0xefe8c36eUL, 0xf890cdd9UL, +0x80226daeUL, 0xc340a4a3UL, 0xdf7e9c09UL, 0xa694a807UL, 0x5b7c5eccUL, 0x221db3a6UL, +0x9a69a02fUL, 0x68818a54UL, 0xceb2296fUL, 0x53c0843aUL, 0xfe893655UL, 0x25bfe68aUL, +0xb4628abcUL, 0xcf222ebfUL, 0x25ac6f48UL, 0xa9a99387UL, 0x53bddb65UL, 0xe76ffbe7UL, +0xe967fd78UL, 0x0ba93563UL, 0x8e342bc1UL, 0xe8a11be9UL, 0x4980740dUL, 0xc8087dfcUL, +0x8de4bf99UL, 0xa11101a0UL, 0x7fd37975UL, 0xda5a26c0UL, 0xe81f994fUL, 0x9528cd89UL, +0xfd339fedUL, 0xb87834bfUL, 0x5f04456dUL, 0x22258698UL, 0xc9c4c83bUL, 0x2dc156beUL, +0x4f628daaUL, 0x57f55ec5UL, 0xe2220abeUL, 0xd2916ebfUL, 0x4ec75b95UL, 0x24f2c3c0UL, +0x42d15d99UL, 0xcd0d7fa0UL, 0x7b6e27ffUL, 0xa8dc8af0UL, 0x7345c106UL, 0xf41e232fUL, +0x35162386UL, 0xe6ea8926UL, 0x3333b094UL, 0x157ec6f2UL, 0x372b74afUL, 0x692573e4UL, +0xe9a9d848UL, 0xf3160289UL, 0x3a62ef1dUL, 0xa787e238UL, 0xf3a5f676UL, 0x74364853UL, +0x20951063UL, 0x4576698dUL, 0xb6fad407UL, 0x592af950UL, 0x36f73523UL, 0x4cfb6e87UL, +0x7da4cec0UL, 0x6c152daaUL, 0xcb0396a8UL, 0xc50dfe5dUL, 0xfcd707abUL, 0x0921c42fUL, +0x89dff0bbUL, 0x5fe2be78UL, 0x448f4f33UL, 0x754613c9UL, 0x2b05d08dUL, 0x48b9d585UL, +0xdc049441UL, 0xc8098f9bUL, 0x7dede786UL, 0xc39a3373UL, 0x42410005UL, 0x6a091751UL, +0x0ef3c8a6UL, 0x890072d6UL, 0x28207682UL, 0xa9a9f7beUL, 0xbf32679dUL, 0xd45b5b75UL, +0xb353fd00UL, 0xcbb0e358UL, 0x830f220aUL, 0x1f8fb214UL, 0xd372cf08UL, 0xcc3c4a13UL, +0x8cf63166UL, 0x061c87beUL, 0x88c98f88UL, 0x6062e397UL, 0x47cf8e7aUL, 0xb6c85283UL, +0x3cc2acfbUL, 0x3fc06976UL, 0x4e8f0252UL, 0x64d8314dUL, 0xda3870e3UL, 0x1e665459UL, +0xc10908f0UL, 0x513021a5UL, 0x6c5b68b7UL, 0x822f8aa0UL, 0x3007cd3eUL, 0x74719eefUL, +0xdc872681UL, 0x073340d4UL, 0x7e432fd9UL, 0x0c5ec241UL, 0x8809286cUL, 0xf592d891UL, +0x08a930f6UL, 0x957ef305UL, 0xb7fbffbdUL, 0xc266e96fUL, 0x6fe4ac98UL, 0xb173ecc0UL, +0xbc60b42aUL, 0x953498daUL, 0xfba1ae12UL, 0x2d4bd736UL, 0x0f25faabUL, 0xa4f3fcebUL, +0xe2969123UL, 0x257f0c3dUL, 0x9348af49UL, 0x361400bcUL, 0xe8816f4aUL, 0x3814f200UL, +0xa3f94043UL, 0x9c7a54c2UL, 0xbc704f57UL, 0xda41e7f9UL, 0xc25ad33aUL, 0x54f4a084UL, +0xb17f5505UL, 0x59357cbeUL, 0xedbd15c8UL, 0x7f97c5abUL, 0xba5ac7b5UL, 0xb6f6deafUL, +0x3a479c3aUL, 0x5302da25UL, 0x653d7e6aUL, 0x54268d49UL, 0x51a477eaUL, 0x5017d55bUL, +0xd7d25d88UL, 0x44136c76UL, 0x0404a8c8UL, 0xb8e5a121UL, 0xb81a928aUL, 0x60ed5869UL, +0x97c55b96UL, 0xeaec991bUL, 0x29935913UL, 0x01fdb7f1UL, 0x088e8dfaUL, 0x9ab6f6f5UL, +0x3b4cbf9fUL, 0x4a5de3abUL, 0xe6051d35UL, 0xa0e1d855UL, 0xd36b4cf1UL, 0xf544edebUL, +0xb0e93524UL, 0xbebb8fbdUL, 0xa2d762cfUL, 0x49c92f54UL, 0x38b5f331UL, 0x7128a454UL, +0x48392905UL, 0xa65b1db8UL, 0x851c97bdUL, 0xd675cf2fUL}; + +static const ulong32 S7[256] = { +0x85e04019UL, 0x332bf567UL, 0x662dbfffUL, 0xcfc65693UL, 0x2a8d7f6fUL, 0xab9bc912UL, +0xde6008a1UL, 0x2028da1fUL, 0x0227bce7UL, 0x4d642916UL, 0x18fac300UL, 0x50f18b82UL, +0x2cb2cb11UL, 0xb232e75cUL, 0x4b3695f2UL, 0xb28707deUL, 0xa05fbcf6UL, 0xcd4181e9UL, +0xe150210cUL, 0xe24ef1bdUL, 0xb168c381UL, 0xfde4e789UL, 0x5c79b0d8UL, 0x1e8bfd43UL, +0x4d495001UL, 0x38be4341UL, 0x913cee1dUL, 0x92a79c3fUL, 0x089766beUL, 0xbaeeadf4UL, +0x1286becfUL, 0xb6eacb19UL, 0x2660c200UL, 0x7565bde4UL, 0x64241f7aUL, 0x8248dca9UL, +0xc3b3ad66UL, 0x28136086UL, 0x0bd8dfa8UL, 0x356d1cf2UL, 0x107789beUL, 0xb3b2e9ceUL, +0x0502aa8fUL, 0x0bc0351eUL, 0x166bf52aUL, 0xeb12ff82UL, 0xe3486911UL, 0xd34d7516UL, +0x4e7b3affUL, 0x5f43671bUL, 0x9cf6e037UL, 0x4981ac83UL, 0x334266ceUL, 0x8c9341b7UL, +0xd0d854c0UL, 0xcb3a6c88UL, 0x47bc2829UL, 0x4725ba37UL, 0xa66ad22bUL, 0x7ad61f1eUL, +0x0c5cbafaUL, 0x4437f107UL, 0xb6e79962UL, 0x42d2d816UL, 0x0a961288UL, 0xe1a5c06eUL, +0x13749e67UL, 0x72fc081aUL, 0xb1d139f7UL, 0xf9583745UL, 0xcf19df58UL, 0xbec3f756UL, +0xc06eba30UL, 0x07211b24UL, 0x45c28829UL, 0xc95e317fUL, 0xbc8ec511UL, 0x38bc46e9UL, +0xc6e6fa14UL, 0xbae8584aUL, 0xad4ebc46UL, 0x468f508bUL, 0x7829435fUL, 0xf124183bUL, +0x821dba9fUL, 0xaff60ff4UL, 0xea2c4e6dUL, 0x16e39264UL, 0x92544a8bUL, 0x009b4fc3UL, +0xaba68cedUL, 0x9ac96f78UL, 0x06a5b79aUL, 0xb2856e6eUL, 0x1aec3ca9UL, 0xbe838688UL, +0x0e0804e9UL, 0x55f1be56UL, 0xe7e5363bUL, 0xb3a1f25dUL, 0xf7debb85UL, 0x61fe033cUL, +0x16746233UL, 0x3c034c28UL, 0xda6d0c74UL, 0x79aac56cUL, 0x3ce4e1adUL, 0x51f0c802UL, +0x98f8f35aUL, 0x1626a49fUL, 0xeed82b29UL, 0x1d382fe3UL, 0x0c4fb99aUL, 0xbb325778UL, +0x3ec6d97bUL, 0x6e77a6a9UL, 0xcb658b5cUL, 0xd45230c7UL, 0x2bd1408bUL, 0x60c03eb7UL, +0xb9068d78UL, 0xa33754f4UL, 0xf430c87dUL, 0xc8a71302UL, 0xb96d8c32UL, 0xebd4e7beUL, +0xbe8b9d2dUL, 0x7979fb06UL, 0xe7225308UL, 0x8b75cf77UL, 0x11ef8da4UL, 0xe083c858UL, +0x8d6b786fUL, 0x5a6317a6UL, 0xfa5cf7a0UL, 0x5dda0033UL, 0xf28ebfb0UL, 0xf5b9c310UL, +0xa0eac280UL, 0x08b9767aUL, 0xa3d9d2b0UL, 0x79d34217UL, 0x021a718dUL, 0x9ac6336aUL, +0x2711fd60UL, 0x438050e3UL, 0x069908a8UL, 0x3d7fedc4UL, 0x826d2befUL, 0x4eeb8476UL, +0x488dcf25UL, 0x36c9d566UL, 0x28e74e41UL, 0xc2610acaUL, 0x3d49a9cfUL, 0xbae3b9dfUL, +0xb65f8de6UL, 0x92aeaf64UL, 0x3ac7d5e6UL, 0x9ea80509UL, 0xf22b017dUL, 0xa4173f70UL, +0xdd1e16c3UL, 0x15e0d7f9UL, 0x50b1b887UL, 0x2b9f4fd5UL, 0x625aba82UL, 0x6a017962UL, +0x2ec01b9cUL, 0x15488aa9UL, 0xd716e740UL, 0x40055a2cUL, 0x93d29a22UL, 0xe32dbf9aUL, +0x058745b9UL, 0x3453dc1eUL, 0xd699296eUL, 0x496cff6fUL, 0x1c9f4986UL, 0xdfe2ed07UL, +0xb87242d1UL, 0x19de7eaeUL, 0x053e561aUL, 0x15ad6f8cUL, 0x66626c1cUL, 0x7154c24cUL, +0xea082b2aUL, 0x93eb2939UL, 0x17dcb0f0UL, 0x58d4f2aeUL, 0x9ea294fbUL, 0x52cf564cUL, +0x9883fe66UL, 0x2ec40581UL, 0x763953c3UL, 0x01d6692eUL, 0xd3a0c108UL, 0xa1e7160eUL, +0xe4f2dfa6UL, 0x693ed285UL, 0x74904698UL, 0x4c2b0eddUL, 0x4f757656UL, 0x5d393378UL, +0xa132234fUL, 0x3d321c5dUL, 0xc3f5e194UL, 0x4b269301UL, 0xc79f022fUL, 0x3c997e7eUL, +0x5e4f9504UL, 0x3ffafbbdUL, 0x76f7ad0eUL, 0x296693f4UL, 0x3d1fce6fUL, 0xc61e45beUL, +0xd3b5ab34UL, 0xf72bf9b7UL, 0x1b0434c0UL, 0x4e72b567UL, 0x5592a33dUL, 0xb5229301UL, +0xcfd2a87fUL, 0x60aeb767UL, 0x1814386bUL, 0x30bcc33dUL, 0x38a0c07dUL, 0xfd1606f2UL, +0xc363519bUL, 0x589dd390UL, 0x5479f8e6UL, 0x1cb8d647UL, 0x97fd61a9UL, 0xea7759f4UL, +0x2d57539dUL, 0x569a58cfUL, 0xe84e63adUL, 0x462e1b78UL, 0x6580f87eUL, 0xf3817914UL, +0x91da55f4UL, 0x40a230f3UL, 0xd1988f35UL, 0xb6e318d2UL, 0x3ffa50bcUL, 0x3d40f021UL, +0xc3c0bdaeUL, 0x4958c24cUL, 0x518f36b2UL, 0x84b1d370UL, 0x0fedce83UL, 0x878ddadaUL, +0xf2a279c7UL, 0x94e01be8UL, 0x90716f4bUL, 0x954b8aa3UL}; + +static const ulong32 S8[256] = { +0xe216300dUL, 0xbbddfffcUL, 0xa7ebdabdUL, 0x35648095UL, 0x7789f8b7UL, 0xe6c1121bUL, +0x0e241600UL, 0x052ce8b5UL, 0x11a9cfb0UL, 0xe5952f11UL, 0xece7990aUL, 0x9386d174UL, +0x2a42931cUL, 0x76e38111UL, 0xb12def3aUL, 0x37ddddfcUL, 0xde9adeb1UL, 0x0a0cc32cUL, +0xbe197029UL, 0x84a00940UL, 0xbb243a0fUL, 0xb4d137cfUL, 0xb44e79f0UL, 0x049eedfdUL, +0x0b15a15dUL, 0x480d3168UL, 0x8bbbde5aUL, 0x669ded42UL, 0xc7ece831UL, 0x3f8f95e7UL, +0x72df191bUL, 0x7580330dUL, 0x94074251UL, 0x5c7dcdfaUL, 0xabbe6d63UL, 0xaa402164UL, +0xb301d40aUL, 0x02e7d1caUL, 0x53571daeUL, 0x7a3182a2UL, 0x12a8ddecUL, 0xfdaa335dUL, +0x176f43e8UL, 0x71fb46d4UL, 0x38129022UL, 0xce949ad4UL, 0xb84769adUL, 0x965bd862UL, +0x82f3d055UL, 0x66fb9767UL, 0x15b80b4eUL, 0x1d5b47a0UL, 0x4cfde06fUL, 0xc28ec4b8UL, +0x57e8726eUL, 0x647a78fcUL, 0x99865d44UL, 0x608bd593UL, 0x6c200e03UL, 0x39dc5ff6UL, +0x5d0b00a3UL, 0xae63aff2UL, 0x7e8bd632UL, 0x70108c0cUL, 0xbbd35049UL, 0x2998df04UL, +0x980cf42aUL, 0x9b6df491UL, 0x9e7edd53UL, 0x06918548UL, 0x58cb7e07UL, 0x3b74ef2eUL, +0x522fffb1UL, 0xd24708ccUL, 0x1c7e27cdUL, 0xa4eb215bUL, 0x3cf1d2e2UL, 0x19b47a38UL, +0x424f7618UL, 0x35856039UL, 0x9d17dee7UL, 0x27eb35e6UL, 0xc9aff67bUL, 0x36baf5b8UL, +0x09c467cdUL, 0xc18910b1UL, 0xe11dbf7bUL, 0x06cd1af8UL, 0x7170c608UL, 0x2d5e3354UL, +0xd4de495aUL, 0x64c6d006UL, 0xbcc0c62cUL, 0x3dd00db3UL, 0x708f8f34UL, 0x77d51b42UL, +0x264f620fUL, 0x24b8d2bfUL, 0x15c1b79eUL, 0x46a52564UL, 0xf8d7e54eUL, 0x3e378160UL, +0x7895cda5UL, 0x859c15a5UL, 0xe6459788UL, 0xc37bc75fUL, 0xdb07ba0cUL, 0x0676a3abUL, +0x7f229b1eUL, 0x31842e7bUL, 0x24259fd7UL, 0xf8bef472UL, 0x835ffcb8UL, 0x6df4c1f2UL, +0x96f5b195UL, 0xfd0af0fcUL, 0xb0fe134cUL, 0xe2506d3dUL, 0x4f9b12eaUL, 0xf215f225UL, +0xa223736fUL, 0x9fb4c428UL, 0x25d04979UL, 0x34c713f8UL, 0xc4618187UL, 0xea7a6e98UL, +0x7cd16efcUL, 0x1436876cUL, 0xf1544107UL, 0xbedeee14UL, 0x56e9af27UL, 0xa04aa441UL, +0x3cf7c899UL, 0x92ecbae6UL, 0xdd67016dUL, 0x151682ebUL, 0xa842eedfUL, 0xfdba60b4UL, +0xf1907b75UL, 0x20e3030fUL, 0x24d8c29eUL, 0xe139673bUL, 0xefa63fb8UL, 0x71873054UL, +0xb6f2cf3bUL, 0x9f326442UL, 0xcb15a4ccUL, 0xb01a4504UL, 0xf1e47d8dUL, 0x844a1be5UL, +0xbae7dfdcUL, 0x42cbda70UL, 0xcd7dae0aUL, 0x57e85b7aUL, 0xd53f5af6UL, 0x20cf4d8cUL, +0xcea4d428UL, 0x79d130a4UL, 0x3486ebfbUL, 0x33d3cddcUL, 0x77853b53UL, 0x37effcb5UL, +0xc5068778UL, 0xe580b3e6UL, 0x4e68b8f4UL, 0xc5c8b37eUL, 0x0d809ea2UL, 0x398feb7cUL, +0x132a4f94UL, 0x43b7950eUL, 0x2fee7d1cUL, 0x223613bdUL, 0xdd06caa2UL, 0x37df932bUL, +0xc4248289UL, 0xacf3ebc3UL, 0x5715f6b7UL, 0xef3478ddUL, 0xf267616fUL, 0xc148cbe4UL, +0x9052815eUL, 0x5e410fabUL, 0xb48a2465UL, 0x2eda7fa4UL, 0xe87b40e4UL, 0xe98ea084UL, +0x5889e9e1UL, 0xefd390fcUL, 0xdd07d35bUL, 0xdb485694UL, 0x38d7e5b2UL, 0x57720101UL, +0x730edebcUL, 0x5b643113UL, 0x94917e4fUL, 0x503c2fbaUL, 0x646f1282UL, 0x7523d24aUL, +0xe0779695UL, 0xf9c17a8fUL, 0x7a5b2121UL, 0xd187b896UL, 0x29263a4dUL, 0xba510cdfUL, +0x81f47c9fUL, 0xad1163edUL, 0xea7b5965UL, 0x1a00726eUL, 0x11403092UL, 0x00da6d77UL, +0x4a0cdd61UL, 0xad1f4603UL, 0x605bdfb0UL, 0x9eedc364UL, 0x22ebe6a8UL, 0xcee7d28aUL, +0xa0e736a0UL, 0x5564a6b9UL, 0x10853209UL, 0xc7eb8f37UL, 0x2de705caUL, 0x8951570fUL, +0xdf09822bUL, 0xbd691a6cUL, 0xaa12e4f2UL, 0x87451c0fUL, 0xe0f6a27aUL, 0x3ada4819UL, +0x4cf1764fUL, 0x0d771c2bUL, 0x67cdb156UL, 0x350d8384UL, 0x5938fa0fUL, 0x42399ef3UL, +0x36997b07UL, 0x0e84093dUL, 0x4aa93e61UL, 0x8360d87bUL, 0x1fa98b0cUL, 0x1149382cUL, +0xe97625a5UL, 0x0614d1b7UL, 0x0e25244bUL, 0x0c768347UL, 0x589e8d82UL, 0x0d2059d1UL, +0xa466bb1eUL, 0xf8da0a82UL, 0x04f19130UL, 0xba6e4ec0UL, 0x99265164UL, 0x1ee7230dUL, +0x50b2ad80UL, 0xeaee6801UL, 0x8db2a283UL, 0xea8bf59eUL}; + +/* returns the i'th byte of a variable */ +#ifdef _MSC_VER + #define GB(x, i) ((unsigned char)((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))) +#else + #define GB(x, i) (((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))&255) +#endif + + /** + Initialize the LTC_CAST5 block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +#ifdef LTC_CLEAN_STACK +static int s_cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + ulong32 x[4], z[4]; + unsigned char buf[16]; + int y, i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + if (num_rounds == 12 && keylen > 10) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen < 5 || keylen > 16) { + return CRYPT_INVALID_KEYSIZE; + } + + /* extend the key as required */ + zeromem(buf, sizeof(buf)); + XMEMCPY(buf, key, (size_t)keylen); + + /* load and start the awful looking network */ + for (y = 0; y < 4; y++) { + LOAD32H(x[3-y],buf+4*y); + } + + for (i = y = 0; y < 2; y++) { + z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; + z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; + z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; + z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; + skey->cast5.K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)]; + skey->cast5.K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)]; + skey->cast5.K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)]; + skey->cast5.K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)]; + + x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; + x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; + x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; + x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)]; + skey->cast5.K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)]; + skey->cast5.K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)]; + + /* second half */ + z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)]; + z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)]; + z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)]; + z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)]; + skey->cast5.K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)]; + skey->cast5.K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)]; + skey->cast5.K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)]; + skey->cast5.K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)]; + + x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)]; + x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)]; + x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)]; + x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)]; + skey->cast5.K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)]; + skey->cast5.K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)]; + skey->cast5.K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)]; + } + + skey->cast5.keylen = keylen; + +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); + zeromem(x, sizeof(x)); + zeromem(z, sizeof(z)); +#endif + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int z; + z = s_cast5_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(ulong32)*8 + 16 + sizeof(int)*2); + return z; +} +#endif + +LTC_INLINE static ulong32 FI(ulong32 R, ulong32 Km, ulong32 Kr) +{ + ulong32 I; + I = (Km + R); + I = ROL(I, Kr); + return ((S1[LTC_BYTE(I, 3)] ^ S2[LTC_BYTE(I,2)]) - S3[LTC_BYTE(I,1)]) + S4[LTC_BYTE(I,0)]; +} + +LTC_INLINE static ulong32 FII(ulong32 R, ulong32 Km, ulong32 Kr) +{ + ulong32 I; + I = (Km ^ R); + I = ROL(I, Kr); + return ((S1[LTC_BYTE(I, 3)] - S2[LTC_BYTE(I,2)]) + S3[LTC_BYTE(I,1)]) ^ S4[LTC_BYTE(I,0)]; +} + +LTC_INLINE static ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr) +{ + ulong32 I; + I = (Km - R); + I = ROL(I, Kr); + return ((S1[LTC_BYTE(I, 3)] + S2[LTC_BYTE(I,2)]) ^ S3[LTC_BYTE(I,1)]) - S4[LTC_BYTE(I,0)]; +} + +/** + Encrypts a block of text with LTC_CAST5 + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 R, L; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(L,&pt[0]); + LOAD32H(R,&pt[4]); + L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); + R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); + L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); + R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); + L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); + R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); + L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); + R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); + L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); + R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); + L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); + R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); + if (skey->cast5.keylen > 10) { + L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); + R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); + L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); + R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); + } + STORE32H(R,&ct[0]); + STORE32H(L,&ct[4]); + return CRYPT_OK; +} + + +#ifdef LTC_CLEAN_STACK +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_cast5_ecb_encrypt(pt,ct,skey); + burn_stack(sizeof(ulong32)*3); + return err; +} +#endif + +/** + Decrypts a block of text with LTC_CAST5 + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 R, L; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(R,&ct[0]); + LOAD32H(L,&ct[4]); + if (skey->cast5.keylen > 10) { + R ^= FI(L, skey->cast5.K[15], skey->cast5.K[31]); + L ^= FIII(R, skey->cast5.K[14], skey->cast5.K[30]); + R ^= FII(L, skey->cast5.K[13], skey->cast5.K[29]); + L ^= FI(R, skey->cast5.K[12], skey->cast5.K[28]); + } + R ^= FIII(L, skey->cast5.K[11], skey->cast5.K[27]); + L ^= FII(R, skey->cast5.K[10], skey->cast5.K[26]); + R ^= FI(L, skey->cast5.K[9], skey->cast5.K[25]); + L ^= FIII(R, skey->cast5.K[8], skey->cast5.K[24]); + R ^= FII(L, skey->cast5.K[7], skey->cast5.K[23]); + L ^= FI(R, skey->cast5.K[6], skey->cast5.K[22]); + R ^= FIII(L, skey->cast5.K[5], skey->cast5.K[21]); + L ^= FII(R, skey->cast5.K[4], skey->cast5.K[20]); + R ^= FI(L, skey->cast5.K[3], skey->cast5.K[19]); + L ^= FIII(R, skey->cast5.K[2], skey->cast5.K[18]); + R ^= FII(L, skey->cast5.K[1], skey->cast5.K[17]); + L ^= FI(R, skey->cast5.K[0], skey->cast5.K[16]); + STORE32H(L,&pt[0]); + STORE32H(R,&pt[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_cast5_ecb_decrypt(ct,pt,skey); + burn_stack(sizeof(ulong32)*3); + return err; +} +#endif + +/** + Performs a self-test of the LTC_CAST5 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int cast5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[16]; + unsigned char pt[8]; + unsigned char ct[8]; + } tests[] = { + { 16, + {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, + {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2} + }, + { 10, + {0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, + {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B}, + }, + { 5, + {0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}, + {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E} + } + }; + int i, y, err; + symmetric_key key; + unsigned char tmp[2][8]; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + if ((err = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + cast5_ecb_encrypt(tests[i].pt, tmp[0], &key); + cast5_ecb_decrypt(tmp[0], tmp[1], &key); + if ((compare_testvector(tmp[0], 8, tests[i].ct, 8, "CAST5 Encrypt", i) != 0) || + (compare_testvector(tmp[1], 8, tests[i].pt, 8, "CAST5 Decrypt", i) != 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) cast5_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) cast5_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void cast5_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int cast5_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 5) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 16) { + *keysize = 16; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/des.c b/deps/libtomcrypt/src/ciphers/des.c new file mode 100644 index 0000000..5d00720 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/des.c @@ -0,0 +1,2093 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file des.c + DES code submitted by Dobes Vandermeer +*/ + +#ifdef LTC_DES + +#define EN0 0 +#define DE1 1 + +const struct ltc_cipher_descriptor des_desc = +{ + "des", + 13, + 8, 8, 8, 16, + &des_setup, + &des_ecb_encrypt, + &des_ecb_decrypt, + &des_test, + &des_done, + &des_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +const struct ltc_cipher_descriptor des3_desc = +{ + "3des", + 14, + 16, 24, 8, 16, + &des3_setup, + &des3_ecb_encrypt, + &des3_ecb_decrypt, + &des3_test, + &des3_done, + &des3_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 bytebit[8] = +{ + 0200, 0100, 040, 020, 010, 04, 02, 01 +}; + +static const ulong32 bigbyte[24] = +{ + 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, + 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, + 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, + 0x800UL, 0x400UL, 0x200UL, 0x100UL, + 0x80UL, 0x40UL, 0x20UL, 0x10UL, + 0x8UL, 0x4UL, 0x2UL, 0x1L +}; + +/* Use the key schedule specific in the standard (ANSI X3.92-1981) */ + +static const unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 +}; + +static const unsigned char totrot[16] = { + 1, 2, 4, 6, + 8, 10, 12, 14, + 15, 17, 19, 21, + 23, 25, 27, 28 +}; + +static const unsigned char pc2[48] = { + 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, + 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, + 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, + 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 +}; + + +static const ulong32 SP1[64] = +{ + 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, + 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, + 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, + 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, + 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, + 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, + 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, + 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, + 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, + 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, + 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, + 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, + 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, + 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, + 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL +}; + +static const ulong32 SP2[64] = +{ + 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, + 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, + 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, + 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, + 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, + 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, + 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, + 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, + 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, + 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, + 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, + 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, + 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, + 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, + 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, + 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL +}; + +static const ulong32 SP3[64] = +{ + 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, + 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, + 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, + 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, + 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, + 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, + 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, + 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, + 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, + 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, + 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, + 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, + 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, + 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, + 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, + 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL +}; + +static const ulong32 SP4[64] = +{ + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, + 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, + 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, + 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, + 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, + 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, + 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, + 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, + 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, + 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, + 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, + 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, + 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL +}; + +static const ulong32 SP5[64] = +{ + 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, + 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, + 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, + 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, + 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, + 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, + 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, + 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, + 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, + 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, + 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, + 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, + 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, + 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, + 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, + 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL +}; + +static const ulong32 SP6[64] = +{ + 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, + 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, + 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, + 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, + 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, + 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, + 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, + 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, + 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, + 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, + 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, + 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, + 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, + 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, + 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL +}; + +static const ulong32 SP7[64] = +{ + 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, + 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, + 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, + 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, + 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, + 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, + 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, + 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, + 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, + 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, + 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, + 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, + 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, + 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, + 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, + 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL +}; + +static const ulong32 SP8[64] = +{ + 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, + 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, + 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, + 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, + 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, + 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, + 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, + 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, + 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, + 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, + 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, + 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, + 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, + 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, + 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, + 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL +}; + +#ifndef LTC_SMALL_CODE + +static const ulong64 des_ip[8][256] = { + +{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000000000010), CONST64(0x0000001000000010), + CONST64(0x0000100000000000), CONST64(0x0000101000000000), CONST64(0x0000100000000010), CONST64(0x0000101000000010), + CONST64(0x0000000000001000), CONST64(0x0000001000001000), CONST64(0x0000000000001010), CONST64(0x0000001000001010), + CONST64(0x0000100000001000), CONST64(0x0000101000001000), CONST64(0x0000100000001010), CONST64(0x0000101000001010), + CONST64(0x0010000000000000), CONST64(0x0010001000000000), CONST64(0x0010000000000010), CONST64(0x0010001000000010), + CONST64(0x0010100000000000), CONST64(0x0010101000000000), CONST64(0x0010100000000010), CONST64(0x0010101000000010), + CONST64(0x0010000000001000), CONST64(0x0010001000001000), CONST64(0x0010000000001010), CONST64(0x0010001000001010), + CONST64(0x0010100000001000), CONST64(0x0010101000001000), CONST64(0x0010100000001010), CONST64(0x0010101000001010), + CONST64(0x0000000000100000), CONST64(0x0000001000100000), CONST64(0x0000000000100010), CONST64(0x0000001000100010), + CONST64(0x0000100000100000), CONST64(0x0000101000100000), CONST64(0x0000100000100010), CONST64(0x0000101000100010), + CONST64(0x0000000000101000), CONST64(0x0000001000101000), CONST64(0x0000000000101010), CONST64(0x0000001000101010), + CONST64(0x0000100000101000), CONST64(0x0000101000101000), CONST64(0x0000100000101010), CONST64(0x0000101000101010), + CONST64(0x0010000000100000), CONST64(0x0010001000100000), CONST64(0x0010000000100010), CONST64(0x0010001000100010), + CONST64(0x0010100000100000), CONST64(0x0010101000100000), CONST64(0x0010100000100010), CONST64(0x0010101000100010), + CONST64(0x0010000000101000), CONST64(0x0010001000101000), CONST64(0x0010000000101010), CONST64(0x0010001000101010), + CONST64(0x0010100000101000), CONST64(0x0010101000101000), CONST64(0x0010100000101010), CONST64(0x0010101000101010), + CONST64(0x1000000000000000), CONST64(0x1000001000000000), CONST64(0x1000000000000010), CONST64(0x1000001000000010), + CONST64(0x1000100000000000), CONST64(0x1000101000000000), CONST64(0x1000100000000010), CONST64(0x1000101000000010), + CONST64(0x1000000000001000), CONST64(0x1000001000001000), CONST64(0x1000000000001010), CONST64(0x1000001000001010), + CONST64(0x1000100000001000), CONST64(0x1000101000001000), CONST64(0x1000100000001010), CONST64(0x1000101000001010), + CONST64(0x1010000000000000), CONST64(0x1010001000000000), CONST64(0x1010000000000010), CONST64(0x1010001000000010), + CONST64(0x1010100000000000), CONST64(0x1010101000000000), CONST64(0x1010100000000010), CONST64(0x1010101000000010), + CONST64(0x1010000000001000), CONST64(0x1010001000001000), CONST64(0x1010000000001010), CONST64(0x1010001000001010), + CONST64(0x1010100000001000), CONST64(0x1010101000001000), CONST64(0x1010100000001010), CONST64(0x1010101000001010), + CONST64(0x1000000000100000), CONST64(0x1000001000100000), CONST64(0x1000000000100010), CONST64(0x1000001000100010), + CONST64(0x1000100000100000), CONST64(0x1000101000100000), CONST64(0x1000100000100010), CONST64(0x1000101000100010), + CONST64(0x1000000000101000), CONST64(0x1000001000101000), CONST64(0x1000000000101010), CONST64(0x1000001000101010), + CONST64(0x1000100000101000), CONST64(0x1000101000101000), CONST64(0x1000100000101010), CONST64(0x1000101000101010), + CONST64(0x1010000000100000), CONST64(0x1010001000100000), CONST64(0x1010000000100010), CONST64(0x1010001000100010), + CONST64(0x1010100000100000), CONST64(0x1010101000100000), CONST64(0x1010100000100010), CONST64(0x1010101000100010), + CONST64(0x1010000000101000), CONST64(0x1010001000101000), CONST64(0x1010000000101010), CONST64(0x1010001000101010), + CONST64(0x1010100000101000), CONST64(0x1010101000101000), CONST64(0x1010100000101010), CONST64(0x1010101000101010), + CONST64(0x0000000010000000), CONST64(0x0000001010000000), CONST64(0x0000000010000010), CONST64(0x0000001010000010), + CONST64(0x0000100010000000), CONST64(0x0000101010000000), CONST64(0x0000100010000010), CONST64(0x0000101010000010), + CONST64(0x0000000010001000), CONST64(0x0000001010001000), CONST64(0x0000000010001010), CONST64(0x0000001010001010), + CONST64(0x0000100010001000), CONST64(0x0000101010001000), CONST64(0x0000100010001010), CONST64(0x0000101010001010), + CONST64(0x0010000010000000), CONST64(0x0010001010000000), CONST64(0x0010000010000010), CONST64(0x0010001010000010), + CONST64(0x0010100010000000), CONST64(0x0010101010000000), CONST64(0x0010100010000010), CONST64(0x0010101010000010), + CONST64(0x0010000010001000), CONST64(0x0010001010001000), CONST64(0x0010000010001010), CONST64(0x0010001010001010), + CONST64(0x0010100010001000), CONST64(0x0010101010001000), CONST64(0x0010100010001010), CONST64(0x0010101010001010), + CONST64(0x0000000010100000), CONST64(0x0000001010100000), CONST64(0x0000000010100010), CONST64(0x0000001010100010), + CONST64(0x0000100010100000), CONST64(0x0000101010100000), CONST64(0x0000100010100010), CONST64(0x0000101010100010), + CONST64(0x0000000010101000), CONST64(0x0000001010101000), CONST64(0x0000000010101010), CONST64(0x0000001010101010), + CONST64(0x0000100010101000), CONST64(0x0000101010101000), CONST64(0x0000100010101010), CONST64(0x0000101010101010), + CONST64(0x0010000010100000), CONST64(0x0010001010100000), CONST64(0x0010000010100010), CONST64(0x0010001010100010), + CONST64(0x0010100010100000), CONST64(0x0010101010100000), CONST64(0x0010100010100010), CONST64(0x0010101010100010), + CONST64(0x0010000010101000), CONST64(0x0010001010101000), CONST64(0x0010000010101010), CONST64(0x0010001010101010), + CONST64(0x0010100010101000), CONST64(0x0010101010101000), CONST64(0x0010100010101010), CONST64(0x0010101010101010), + CONST64(0x1000000010000000), CONST64(0x1000001010000000), CONST64(0x1000000010000010), CONST64(0x1000001010000010), + CONST64(0x1000100010000000), CONST64(0x1000101010000000), CONST64(0x1000100010000010), CONST64(0x1000101010000010), + CONST64(0x1000000010001000), CONST64(0x1000001010001000), CONST64(0x1000000010001010), CONST64(0x1000001010001010), + CONST64(0x1000100010001000), CONST64(0x1000101010001000), CONST64(0x1000100010001010), CONST64(0x1000101010001010), + CONST64(0x1010000010000000), CONST64(0x1010001010000000), CONST64(0x1010000010000010), CONST64(0x1010001010000010), + CONST64(0x1010100010000000), CONST64(0x1010101010000000), CONST64(0x1010100010000010), CONST64(0x1010101010000010), + CONST64(0x1010000010001000), CONST64(0x1010001010001000), CONST64(0x1010000010001010), CONST64(0x1010001010001010), + CONST64(0x1010100010001000), CONST64(0x1010101010001000), CONST64(0x1010100010001010), CONST64(0x1010101010001010), + CONST64(0x1000000010100000), CONST64(0x1000001010100000), CONST64(0x1000000010100010), CONST64(0x1000001010100010), + CONST64(0x1000100010100000), CONST64(0x1000101010100000), CONST64(0x1000100010100010), CONST64(0x1000101010100010), + CONST64(0x1000000010101000), CONST64(0x1000001010101000), CONST64(0x1000000010101010), CONST64(0x1000001010101010), + CONST64(0x1000100010101000), CONST64(0x1000101010101000), CONST64(0x1000100010101010), CONST64(0x1000101010101010), + CONST64(0x1010000010100000), CONST64(0x1010001010100000), CONST64(0x1010000010100010), CONST64(0x1010001010100010), + CONST64(0x1010100010100000), CONST64(0x1010101010100000), CONST64(0x1010100010100010), CONST64(0x1010101010100010), + CONST64(0x1010000010101000), CONST64(0x1010001010101000), CONST64(0x1010000010101010), CONST64(0x1010001010101010), + CONST64(0x1010100010101000), CONST64(0x1010101010101000), CONST64(0x1010100010101010), CONST64(0x1010101010101010) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000000000008), CONST64(0x0000000800000008), + CONST64(0x0000080000000000), CONST64(0x0000080800000000), CONST64(0x0000080000000008), CONST64(0x0000080800000008), + CONST64(0x0000000000000800), CONST64(0x0000000800000800), CONST64(0x0000000000000808), CONST64(0x0000000800000808), + CONST64(0x0000080000000800), CONST64(0x0000080800000800), CONST64(0x0000080000000808), CONST64(0x0000080800000808), + CONST64(0x0008000000000000), CONST64(0x0008000800000000), CONST64(0x0008000000000008), CONST64(0x0008000800000008), + CONST64(0x0008080000000000), CONST64(0x0008080800000000), CONST64(0x0008080000000008), CONST64(0x0008080800000008), + CONST64(0x0008000000000800), CONST64(0x0008000800000800), CONST64(0x0008000000000808), CONST64(0x0008000800000808), + CONST64(0x0008080000000800), CONST64(0x0008080800000800), CONST64(0x0008080000000808), CONST64(0x0008080800000808), + CONST64(0x0000000000080000), CONST64(0x0000000800080000), CONST64(0x0000000000080008), CONST64(0x0000000800080008), + CONST64(0x0000080000080000), CONST64(0x0000080800080000), CONST64(0x0000080000080008), CONST64(0x0000080800080008), + CONST64(0x0000000000080800), CONST64(0x0000000800080800), CONST64(0x0000000000080808), CONST64(0x0000000800080808), + CONST64(0x0000080000080800), CONST64(0x0000080800080800), CONST64(0x0000080000080808), CONST64(0x0000080800080808), + CONST64(0x0008000000080000), CONST64(0x0008000800080000), CONST64(0x0008000000080008), CONST64(0x0008000800080008), + CONST64(0x0008080000080000), CONST64(0x0008080800080000), CONST64(0x0008080000080008), CONST64(0x0008080800080008), + CONST64(0x0008000000080800), CONST64(0x0008000800080800), CONST64(0x0008000000080808), CONST64(0x0008000800080808), + CONST64(0x0008080000080800), CONST64(0x0008080800080800), CONST64(0x0008080000080808), CONST64(0x0008080800080808), + CONST64(0x0800000000000000), CONST64(0x0800000800000000), CONST64(0x0800000000000008), CONST64(0x0800000800000008), + CONST64(0x0800080000000000), CONST64(0x0800080800000000), CONST64(0x0800080000000008), CONST64(0x0800080800000008), + CONST64(0x0800000000000800), CONST64(0x0800000800000800), CONST64(0x0800000000000808), CONST64(0x0800000800000808), + CONST64(0x0800080000000800), CONST64(0x0800080800000800), CONST64(0x0800080000000808), CONST64(0x0800080800000808), + CONST64(0x0808000000000000), CONST64(0x0808000800000000), CONST64(0x0808000000000008), CONST64(0x0808000800000008), + CONST64(0x0808080000000000), CONST64(0x0808080800000000), CONST64(0x0808080000000008), CONST64(0x0808080800000008), + CONST64(0x0808000000000800), CONST64(0x0808000800000800), CONST64(0x0808000000000808), CONST64(0x0808000800000808), + CONST64(0x0808080000000800), CONST64(0x0808080800000800), CONST64(0x0808080000000808), CONST64(0x0808080800000808), + CONST64(0x0800000000080000), CONST64(0x0800000800080000), CONST64(0x0800000000080008), CONST64(0x0800000800080008), + CONST64(0x0800080000080000), CONST64(0x0800080800080000), CONST64(0x0800080000080008), CONST64(0x0800080800080008), + CONST64(0x0800000000080800), CONST64(0x0800000800080800), CONST64(0x0800000000080808), CONST64(0x0800000800080808), + CONST64(0x0800080000080800), CONST64(0x0800080800080800), CONST64(0x0800080000080808), CONST64(0x0800080800080808), + CONST64(0x0808000000080000), CONST64(0x0808000800080000), CONST64(0x0808000000080008), CONST64(0x0808000800080008), + CONST64(0x0808080000080000), CONST64(0x0808080800080000), CONST64(0x0808080000080008), CONST64(0x0808080800080008), + CONST64(0x0808000000080800), CONST64(0x0808000800080800), CONST64(0x0808000000080808), CONST64(0x0808000800080808), + CONST64(0x0808080000080800), CONST64(0x0808080800080800), CONST64(0x0808080000080808), CONST64(0x0808080800080808), + CONST64(0x0000000008000000), CONST64(0x0000000808000000), CONST64(0x0000000008000008), CONST64(0x0000000808000008), + CONST64(0x0000080008000000), CONST64(0x0000080808000000), CONST64(0x0000080008000008), CONST64(0x0000080808000008), + CONST64(0x0000000008000800), CONST64(0x0000000808000800), CONST64(0x0000000008000808), CONST64(0x0000000808000808), + CONST64(0x0000080008000800), CONST64(0x0000080808000800), CONST64(0x0000080008000808), CONST64(0x0000080808000808), + CONST64(0x0008000008000000), CONST64(0x0008000808000000), CONST64(0x0008000008000008), CONST64(0x0008000808000008), + CONST64(0x0008080008000000), CONST64(0x0008080808000000), CONST64(0x0008080008000008), CONST64(0x0008080808000008), + CONST64(0x0008000008000800), CONST64(0x0008000808000800), CONST64(0x0008000008000808), CONST64(0x0008000808000808), + CONST64(0x0008080008000800), CONST64(0x0008080808000800), CONST64(0x0008080008000808), CONST64(0x0008080808000808), + CONST64(0x0000000008080000), CONST64(0x0000000808080000), CONST64(0x0000000008080008), CONST64(0x0000000808080008), + CONST64(0x0000080008080000), CONST64(0x0000080808080000), CONST64(0x0000080008080008), CONST64(0x0000080808080008), + CONST64(0x0000000008080800), CONST64(0x0000000808080800), CONST64(0x0000000008080808), CONST64(0x0000000808080808), + CONST64(0x0000080008080800), CONST64(0x0000080808080800), CONST64(0x0000080008080808), CONST64(0x0000080808080808), + CONST64(0x0008000008080000), CONST64(0x0008000808080000), CONST64(0x0008000008080008), CONST64(0x0008000808080008), + CONST64(0x0008080008080000), CONST64(0x0008080808080000), CONST64(0x0008080008080008), CONST64(0x0008080808080008), + CONST64(0x0008000008080800), CONST64(0x0008000808080800), CONST64(0x0008000008080808), CONST64(0x0008000808080808), + CONST64(0x0008080008080800), CONST64(0x0008080808080800), CONST64(0x0008080008080808), CONST64(0x0008080808080808), + CONST64(0x0800000008000000), CONST64(0x0800000808000000), CONST64(0x0800000008000008), CONST64(0x0800000808000008), + CONST64(0x0800080008000000), CONST64(0x0800080808000000), CONST64(0x0800080008000008), CONST64(0x0800080808000008), + CONST64(0x0800000008000800), CONST64(0x0800000808000800), CONST64(0x0800000008000808), CONST64(0x0800000808000808), + CONST64(0x0800080008000800), CONST64(0x0800080808000800), CONST64(0x0800080008000808), CONST64(0x0800080808000808), + CONST64(0x0808000008000000), CONST64(0x0808000808000000), CONST64(0x0808000008000008), CONST64(0x0808000808000008), + CONST64(0x0808080008000000), CONST64(0x0808080808000000), CONST64(0x0808080008000008), CONST64(0x0808080808000008), + CONST64(0x0808000008000800), CONST64(0x0808000808000800), CONST64(0x0808000008000808), CONST64(0x0808000808000808), + CONST64(0x0808080008000800), CONST64(0x0808080808000800), CONST64(0x0808080008000808), CONST64(0x0808080808000808), + CONST64(0x0800000008080000), CONST64(0x0800000808080000), CONST64(0x0800000008080008), CONST64(0x0800000808080008), + CONST64(0x0800080008080000), CONST64(0x0800080808080000), CONST64(0x0800080008080008), CONST64(0x0800080808080008), + CONST64(0x0800000008080800), CONST64(0x0800000808080800), CONST64(0x0800000008080808), CONST64(0x0800000808080808), + CONST64(0x0800080008080800), CONST64(0x0800080808080800), CONST64(0x0800080008080808), CONST64(0x0800080808080808), + CONST64(0x0808000008080000), CONST64(0x0808000808080000), CONST64(0x0808000008080008), CONST64(0x0808000808080008), + CONST64(0x0808080008080000), CONST64(0x0808080808080000), CONST64(0x0808080008080008), CONST64(0x0808080808080008), + CONST64(0x0808000008080800), CONST64(0x0808000808080800), CONST64(0x0808000008080808), CONST64(0x0808000808080808), + CONST64(0x0808080008080800), CONST64(0x0808080808080800), CONST64(0x0808080008080808), CONST64(0x0808080808080808) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000000000004), CONST64(0x0000000400000004), + CONST64(0x0000040000000000), CONST64(0x0000040400000000), CONST64(0x0000040000000004), CONST64(0x0000040400000004), + CONST64(0x0000000000000400), CONST64(0x0000000400000400), CONST64(0x0000000000000404), CONST64(0x0000000400000404), + CONST64(0x0000040000000400), CONST64(0x0000040400000400), CONST64(0x0000040000000404), CONST64(0x0000040400000404), + CONST64(0x0004000000000000), CONST64(0x0004000400000000), CONST64(0x0004000000000004), CONST64(0x0004000400000004), + CONST64(0x0004040000000000), CONST64(0x0004040400000000), CONST64(0x0004040000000004), CONST64(0x0004040400000004), + CONST64(0x0004000000000400), CONST64(0x0004000400000400), CONST64(0x0004000000000404), CONST64(0x0004000400000404), + CONST64(0x0004040000000400), CONST64(0x0004040400000400), CONST64(0x0004040000000404), CONST64(0x0004040400000404), + CONST64(0x0000000000040000), CONST64(0x0000000400040000), CONST64(0x0000000000040004), CONST64(0x0000000400040004), + CONST64(0x0000040000040000), CONST64(0x0000040400040000), CONST64(0x0000040000040004), CONST64(0x0000040400040004), + CONST64(0x0000000000040400), CONST64(0x0000000400040400), CONST64(0x0000000000040404), CONST64(0x0000000400040404), + CONST64(0x0000040000040400), CONST64(0x0000040400040400), CONST64(0x0000040000040404), CONST64(0x0000040400040404), + CONST64(0x0004000000040000), CONST64(0x0004000400040000), CONST64(0x0004000000040004), CONST64(0x0004000400040004), + CONST64(0x0004040000040000), CONST64(0x0004040400040000), CONST64(0x0004040000040004), CONST64(0x0004040400040004), + CONST64(0x0004000000040400), CONST64(0x0004000400040400), CONST64(0x0004000000040404), CONST64(0x0004000400040404), + CONST64(0x0004040000040400), CONST64(0x0004040400040400), CONST64(0x0004040000040404), CONST64(0x0004040400040404), + CONST64(0x0400000000000000), CONST64(0x0400000400000000), CONST64(0x0400000000000004), CONST64(0x0400000400000004), + CONST64(0x0400040000000000), CONST64(0x0400040400000000), CONST64(0x0400040000000004), CONST64(0x0400040400000004), + CONST64(0x0400000000000400), CONST64(0x0400000400000400), CONST64(0x0400000000000404), CONST64(0x0400000400000404), + CONST64(0x0400040000000400), CONST64(0x0400040400000400), CONST64(0x0400040000000404), CONST64(0x0400040400000404), + CONST64(0x0404000000000000), CONST64(0x0404000400000000), CONST64(0x0404000000000004), CONST64(0x0404000400000004), + CONST64(0x0404040000000000), CONST64(0x0404040400000000), CONST64(0x0404040000000004), CONST64(0x0404040400000004), + CONST64(0x0404000000000400), CONST64(0x0404000400000400), CONST64(0x0404000000000404), CONST64(0x0404000400000404), + CONST64(0x0404040000000400), CONST64(0x0404040400000400), CONST64(0x0404040000000404), CONST64(0x0404040400000404), + CONST64(0x0400000000040000), CONST64(0x0400000400040000), CONST64(0x0400000000040004), CONST64(0x0400000400040004), + CONST64(0x0400040000040000), CONST64(0x0400040400040000), CONST64(0x0400040000040004), CONST64(0x0400040400040004), + CONST64(0x0400000000040400), CONST64(0x0400000400040400), CONST64(0x0400000000040404), CONST64(0x0400000400040404), + CONST64(0x0400040000040400), CONST64(0x0400040400040400), CONST64(0x0400040000040404), CONST64(0x0400040400040404), + CONST64(0x0404000000040000), CONST64(0x0404000400040000), CONST64(0x0404000000040004), CONST64(0x0404000400040004), + CONST64(0x0404040000040000), CONST64(0x0404040400040000), CONST64(0x0404040000040004), CONST64(0x0404040400040004), + CONST64(0x0404000000040400), CONST64(0x0404000400040400), CONST64(0x0404000000040404), CONST64(0x0404000400040404), + CONST64(0x0404040000040400), CONST64(0x0404040400040400), CONST64(0x0404040000040404), CONST64(0x0404040400040404), + CONST64(0x0000000004000000), CONST64(0x0000000404000000), CONST64(0x0000000004000004), CONST64(0x0000000404000004), + CONST64(0x0000040004000000), CONST64(0x0000040404000000), CONST64(0x0000040004000004), CONST64(0x0000040404000004), + CONST64(0x0000000004000400), CONST64(0x0000000404000400), CONST64(0x0000000004000404), CONST64(0x0000000404000404), + CONST64(0x0000040004000400), CONST64(0x0000040404000400), CONST64(0x0000040004000404), CONST64(0x0000040404000404), + CONST64(0x0004000004000000), CONST64(0x0004000404000000), CONST64(0x0004000004000004), CONST64(0x0004000404000004), + CONST64(0x0004040004000000), CONST64(0x0004040404000000), CONST64(0x0004040004000004), CONST64(0x0004040404000004), + CONST64(0x0004000004000400), CONST64(0x0004000404000400), CONST64(0x0004000004000404), CONST64(0x0004000404000404), + CONST64(0x0004040004000400), CONST64(0x0004040404000400), CONST64(0x0004040004000404), CONST64(0x0004040404000404), + CONST64(0x0000000004040000), CONST64(0x0000000404040000), CONST64(0x0000000004040004), CONST64(0x0000000404040004), + CONST64(0x0000040004040000), CONST64(0x0000040404040000), CONST64(0x0000040004040004), CONST64(0x0000040404040004), + CONST64(0x0000000004040400), CONST64(0x0000000404040400), CONST64(0x0000000004040404), CONST64(0x0000000404040404), + CONST64(0x0000040004040400), CONST64(0x0000040404040400), CONST64(0x0000040004040404), CONST64(0x0000040404040404), + CONST64(0x0004000004040000), CONST64(0x0004000404040000), CONST64(0x0004000004040004), CONST64(0x0004000404040004), + CONST64(0x0004040004040000), CONST64(0x0004040404040000), CONST64(0x0004040004040004), CONST64(0x0004040404040004), + CONST64(0x0004000004040400), CONST64(0x0004000404040400), CONST64(0x0004000004040404), CONST64(0x0004000404040404), + CONST64(0x0004040004040400), CONST64(0x0004040404040400), CONST64(0x0004040004040404), CONST64(0x0004040404040404), + CONST64(0x0400000004000000), CONST64(0x0400000404000000), CONST64(0x0400000004000004), CONST64(0x0400000404000004), + CONST64(0x0400040004000000), CONST64(0x0400040404000000), CONST64(0x0400040004000004), CONST64(0x0400040404000004), + CONST64(0x0400000004000400), CONST64(0x0400000404000400), CONST64(0x0400000004000404), CONST64(0x0400000404000404), + CONST64(0x0400040004000400), CONST64(0x0400040404000400), CONST64(0x0400040004000404), CONST64(0x0400040404000404), + CONST64(0x0404000004000000), CONST64(0x0404000404000000), CONST64(0x0404000004000004), CONST64(0x0404000404000004), + CONST64(0x0404040004000000), CONST64(0x0404040404000000), CONST64(0x0404040004000004), CONST64(0x0404040404000004), + CONST64(0x0404000004000400), CONST64(0x0404000404000400), CONST64(0x0404000004000404), CONST64(0x0404000404000404), + CONST64(0x0404040004000400), CONST64(0x0404040404000400), CONST64(0x0404040004000404), CONST64(0x0404040404000404), + CONST64(0x0400000004040000), CONST64(0x0400000404040000), CONST64(0x0400000004040004), CONST64(0x0400000404040004), + CONST64(0x0400040004040000), CONST64(0x0400040404040000), CONST64(0x0400040004040004), CONST64(0x0400040404040004), + CONST64(0x0400000004040400), CONST64(0x0400000404040400), CONST64(0x0400000004040404), CONST64(0x0400000404040404), + CONST64(0x0400040004040400), CONST64(0x0400040404040400), CONST64(0x0400040004040404), CONST64(0x0400040404040404), + CONST64(0x0404000004040000), CONST64(0x0404000404040000), CONST64(0x0404000004040004), CONST64(0x0404000404040004), + CONST64(0x0404040004040000), CONST64(0x0404040404040000), CONST64(0x0404040004040004), CONST64(0x0404040404040004), + CONST64(0x0404000004040400), CONST64(0x0404000404040400), CONST64(0x0404000004040404), CONST64(0x0404000404040404), + CONST64(0x0404040004040400), CONST64(0x0404040404040400), CONST64(0x0404040004040404), CONST64(0x0404040404040404) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000000000002), CONST64(0x0000000200000002), + CONST64(0x0000020000000000), CONST64(0x0000020200000000), CONST64(0x0000020000000002), CONST64(0x0000020200000002), + CONST64(0x0000000000000200), CONST64(0x0000000200000200), CONST64(0x0000000000000202), CONST64(0x0000000200000202), + CONST64(0x0000020000000200), CONST64(0x0000020200000200), CONST64(0x0000020000000202), CONST64(0x0000020200000202), + CONST64(0x0002000000000000), CONST64(0x0002000200000000), CONST64(0x0002000000000002), CONST64(0x0002000200000002), + CONST64(0x0002020000000000), CONST64(0x0002020200000000), CONST64(0x0002020000000002), CONST64(0x0002020200000002), + CONST64(0x0002000000000200), CONST64(0x0002000200000200), CONST64(0x0002000000000202), CONST64(0x0002000200000202), + CONST64(0x0002020000000200), CONST64(0x0002020200000200), CONST64(0x0002020000000202), CONST64(0x0002020200000202), + CONST64(0x0000000000020000), CONST64(0x0000000200020000), CONST64(0x0000000000020002), CONST64(0x0000000200020002), + CONST64(0x0000020000020000), CONST64(0x0000020200020000), CONST64(0x0000020000020002), CONST64(0x0000020200020002), + CONST64(0x0000000000020200), CONST64(0x0000000200020200), CONST64(0x0000000000020202), CONST64(0x0000000200020202), + CONST64(0x0000020000020200), CONST64(0x0000020200020200), CONST64(0x0000020000020202), CONST64(0x0000020200020202), + CONST64(0x0002000000020000), CONST64(0x0002000200020000), CONST64(0x0002000000020002), CONST64(0x0002000200020002), + CONST64(0x0002020000020000), CONST64(0x0002020200020000), CONST64(0x0002020000020002), CONST64(0x0002020200020002), + CONST64(0x0002000000020200), CONST64(0x0002000200020200), CONST64(0x0002000000020202), CONST64(0x0002000200020202), + CONST64(0x0002020000020200), CONST64(0x0002020200020200), CONST64(0x0002020000020202), CONST64(0x0002020200020202), + CONST64(0x0200000000000000), CONST64(0x0200000200000000), CONST64(0x0200000000000002), CONST64(0x0200000200000002), + CONST64(0x0200020000000000), CONST64(0x0200020200000000), CONST64(0x0200020000000002), CONST64(0x0200020200000002), + CONST64(0x0200000000000200), CONST64(0x0200000200000200), CONST64(0x0200000000000202), CONST64(0x0200000200000202), + CONST64(0x0200020000000200), CONST64(0x0200020200000200), CONST64(0x0200020000000202), CONST64(0x0200020200000202), + CONST64(0x0202000000000000), CONST64(0x0202000200000000), CONST64(0x0202000000000002), CONST64(0x0202000200000002), + CONST64(0x0202020000000000), CONST64(0x0202020200000000), CONST64(0x0202020000000002), CONST64(0x0202020200000002), + CONST64(0x0202000000000200), CONST64(0x0202000200000200), CONST64(0x0202000000000202), CONST64(0x0202000200000202), + CONST64(0x0202020000000200), CONST64(0x0202020200000200), CONST64(0x0202020000000202), CONST64(0x0202020200000202), + CONST64(0x0200000000020000), CONST64(0x0200000200020000), CONST64(0x0200000000020002), CONST64(0x0200000200020002), + CONST64(0x0200020000020000), CONST64(0x0200020200020000), CONST64(0x0200020000020002), CONST64(0x0200020200020002), + CONST64(0x0200000000020200), CONST64(0x0200000200020200), CONST64(0x0200000000020202), CONST64(0x0200000200020202), + CONST64(0x0200020000020200), CONST64(0x0200020200020200), CONST64(0x0200020000020202), CONST64(0x0200020200020202), + CONST64(0x0202000000020000), CONST64(0x0202000200020000), CONST64(0x0202000000020002), CONST64(0x0202000200020002), + CONST64(0x0202020000020000), CONST64(0x0202020200020000), CONST64(0x0202020000020002), CONST64(0x0202020200020002), + CONST64(0x0202000000020200), CONST64(0x0202000200020200), CONST64(0x0202000000020202), CONST64(0x0202000200020202), + CONST64(0x0202020000020200), CONST64(0x0202020200020200), CONST64(0x0202020000020202), CONST64(0x0202020200020202), + CONST64(0x0000000002000000), CONST64(0x0000000202000000), CONST64(0x0000000002000002), CONST64(0x0000000202000002), + CONST64(0x0000020002000000), CONST64(0x0000020202000000), CONST64(0x0000020002000002), CONST64(0x0000020202000002), + CONST64(0x0000000002000200), CONST64(0x0000000202000200), CONST64(0x0000000002000202), CONST64(0x0000000202000202), + CONST64(0x0000020002000200), CONST64(0x0000020202000200), CONST64(0x0000020002000202), CONST64(0x0000020202000202), + CONST64(0x0002000002000000), CONST64(0x0002000202000000), CONST64(0x0002000002000002), CONST64(0x0002000202000002), + CONST64(0x0002020002000000), CONST64(0x0002020202000000), CONST64(0x0002020002000002), CONST64(0x0002020202000002), + CONST64(0x0002000002000200), CONST64(0x0002000202000200), CONST64(0x0002000002000202), CONST64(0x0002000202000202), + CONST64(0x0002020002000200), CONST64(0x0002020202000200), CONST64(0x0002020002000202), CONST64(0x0002020202000202), + CONST64(0x0000000002020000), CONST64(0x0000000202020000), CONST64(0x0000000002020002), CONST64(0x0000000202020002), + CONST64(0x0000020002020000), CONST64(0x0000020202020000), CONST64(0x0000020002020002), CONST64(0x0000020202020002), + CONST64(0x0000000002020200), CONST64(0x0000000202020200), CONST64(0x0000000002020202), CONST64(0x0000000202020202), + CONST64(0x0000020002020200), CONST64(0x0000020202020200), CONST64(0x0000020002020202), CONST64(0x0000020202020202), + CONST64(0x0002000002020000), CONST64(0x0002000202020000), CONST64(0x0002000002020002), CONST64(0x0002000202020002), + CONST64(0x0002020002020000), CONST64(0x0002020202020000), CONST64(0x0002020002020002), CONST64(0x0002020202020002), + CONST64(0x0002000002020200), CONST64(0x0002000202020200), CONST64(0x0002000002020202), CONST64(0x0002000202020202), + CONST64(0x0002020002020200), CONST64(0x0002020202020200), CONST64(0x0002020002020202), CONST64(0x0002020202020202), + CONST64(0x0200000002000000), CONST64(0x0200000202000000), CONST64(0x0200000002000002), CONST64(0x0200000202000002), + CONST64(0x0200020002000000), CONST64(0x0200020202000000), CONST64(0x0200020002000002), CONST64(0x0200020202000002), + CONST64(0x0200000002000200), CONST64(0x0200000202000200), CONST64(0x0200000002000202), CONST64(0x0200000202000202), + CONST64(0x0200020002000200), CONST64(0x0200020202000200), CONST64(0x0200020002000202), CONST64(0x0200020202000202), + CONST64(0x0202000002000000), CONST64(0x0202000202000000), CONST64(0x0202000002000002), CONST64(0x0202000202000002), + CONST64(0x0202020002000000), CONST64(0x0202020202000000), CONST64(0x0202020002000002), CONST64(0x0202020202000002), + CONST64(0x0202000002000200), CONST64(0x0202000202000200), CONST64(0x0202000002000202), CONST64(0x0202000202000202), + CONST64(0x0202020002000200), CONST64(0x0202020202000200), CONST64(0x0202020002000202), CONST64(0x0202020202000202), + CONST64(0x0200000002020000), CONST64(0x0200000202020000), CONST64(0x0200000002020002), CONST64(0x0200000202020002), + CONST64(0x0200020002020000), CONST64(0x0200020202020000), CONST64(0x0200020002020002), CONST64(0x0200020202020002), + CONST64(0x0200000002020200), CONST64(0x0200000202020200), CONST64(0x0200000002020202), CONST64(0x0200000202020202), + CONST64(0x0200020002020200), CONST64(0x0200020202020200), CONST64(0x0200020002020202), CONST64(0x0200020202020202), + CONST64(0x0202000002020000), CONST64(0x0202000202020000), CONST64(0x0202000002020002), CONST64(0x0202000202020002), + CONST64(0x0202020002020000), CONST64(0x0202020202020000), CONST64(0x0202020002020002), CONST64(0x0202020202020002), + CONST64(0x0202000002020200), CONST64(0x0202000202020200), CONST64(0x0202000002020202), CONST64(0x0202000202020202), + CONST64(0x0202020002020200), CONST64(0x0202020202020200), CONST64(0x0202020002020202), CONST64(0x0202020202020202) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000010000000000), CONST64(0x0000000000000100), CONST64(0x0000010000000100), + CONST64(0x0001000000000000), CONST64(0x0001010000000000), CONST64(0x0001000000000100), CONST64(0x0001010000000100), + CONST64(0x0000000000010000), CONST64(0x0000010000010000), CONST64(0x0000000000010100), CONST64(0x0000010000010100), + CONST64(0x0001000000010000), CONST64(0x0001010000010000), CONST64(0x0001000000010100), CONST64(0x0001010000010100), + CONST64(0x0100000000000000), CONST64(0x0100010000000000), CONST64(0x0100000000000100), CONST64(0x0100010000000100), + CONST64(0x0101000000000000), CONST64(0x0101010000000000), CONST64(0x0101000000000100), CONST64(0x0101010000000100), + CONST64(0x0100000000010000), CONST64(0x0100010000010000), CONST64(0x0100000000010100), CONST64(0x0100010000010100), + CONST64(0x0101000000010000), CONST64(0x0101010000010000), CONST64(0x0101000000010100), CONST64(0x0101010000010100), + CONST64(0x0000000001000000), CONST64(0x0000010001000000), CONST64(0x0000000001000100), CONST64(0x0000010001000100), + CONST64(0x0001000001000000), CONST64(0x0001010001000000), CONST64(0x0001000001000100), CONST64(0x0001010001000100), + CONST64(0x0000000001010000), CONST64(0x0000010001010000), CONST64(0x0000000001010100), CONST64(0x0000010001010100), + CONST64(0x0001000001010000), CONST64(0x0001010001010000), CONST64(0x0001000001010100), CONST64(0x0001010001010100), + CONST64(0x0100000001000000), CONST64(0x0100010001000000), CONST64(0x0100000001000100), CONST64(0x0100010001000100), + CONST64(0x0101000001000000), CONST64(0x0101010001000000), CONST64(0x0101000001000100), CONST64(0x0101010001000100), + CONST64(0x0100000001010000), CONST64(0x0100010001010000), CONST64(0x0100000001010100), CONST64(0x0100010001010100), + CONST64(0x0101000001010000), CONST64(0x0101010001010000), CONST64(0x0101000001010100), CONST64(0x0101010001010100), + CONST64(0x0000000100000000), CONST64(0x0000010100000000), CONST64(0x0000000100000100), CONST64(0x0000010100000100), + CONST64(0x0001000100000000), CONST64(0x0001010100000000), CONST64(0x0001000100000100), CONST64(0x0001010100000100), + CONST64(0x0000000100010000), CONST64(0x0000010100010000), CONST64(0x0000000100010100), CONST64(0x0000010100010100), + CONST64(0x0001000100010000), CONST64(0x0001010100010000), CONST64(0x0001000100010100), CONST64(0x0001010100010100), + CONST64(0x0100000100000000), CONST64(0x0100010100000000), CONST64(0x0100000100000100), CONST64(0x0100010100000100), + CONST64(0x0101000100000000), CONST64(0x0101010100000000), CONST64(0x0101000100000100), CONST64(0x0101010100000100), + CONST64(0x0100000100010000), CONST64(0x0100010100010000), CONST64(0x0100000100010100), CONST64(0x0100010100010100), + CONST64(0x0101000100010000), CONST64(0x0101010100010000), CONST64(0x0101000100010100), CONST64(0x0101010100010100), + CONST64(0x0000000101000000), CONST64(0x0000010101000000), CONST64(0x0000000101000100), CONST64(0x0000010101000100), + CONST64(0x0001000101000000), CONST64(0x0001010101000000), CONST64(0x0001000101000100), CONST64(0x0001010101000100), + CONST64(0x0000000101010000), CONST64(0x0000010101010000), CONST64(0x0000000101010100), CONST64(0x0000010101010100), + CONST64(0x0001000101010000), CONST64(0x0001010101010000), CONST64(0x0001000101010100), CONST64(0x0001010101010100), + CONST64(0x0100000101000000), CONST64(0x0100010101000000), CONST64(0x0100000101000100), CONST64(0x0100010101000100), + CONST64(0x0101000101000000), CONST64(0x0101010101000000), CONST64(0x0101000101000100), CONST64(0x0101010101000100), + CONST64(0x0100000101010000), CONST64(0x0100010101010000), CONST64(0x0100000101010100), CONST64(0x0100010101010100), + CONST64(0x0101000101010000), CONST64(0x0101010101010000), CONST64(0x0101000101010100), CONST64(0x0101010101010100), + CONST64(0x0000000000000001), CONST64(0x0000010000000001), CONST64(0x0000000000000101), CONST64(0x0000010000000101), + CONST64(0x0001000000000001), CONST64(0x0001010000000001), CONST64(0x0001000000000101), CONST64(0x0001010000000101), + CONST64(0x0000000000010001), CONST64(0x0000010000010001), CONST64(0x0000000000010101), CONST64(0x0000010000010101), + CONST64(0x0001000000010001), CONST64(0x0001010000010001), CONST64(0x0001000000010101), CONST64(0x0001010000010101), + CONST64(0x0100000000000001), CONST64(0x0100010000000001), CONST64(0x0100000000000101), CONST64(0x0100010000000101), + CONST64(0x0101000000000001), CONST64(0x0101010000000001), CONST64(0x0101000000000101), CONST64(0x0101010000000101), + CONST64(0x0100000000010001), CONST64(0x0100010000010001), CONST64(0x0100000000010101), CONST64(0x0100010000010101), + CONST64(0x0101000000010001), CONST64(0x0101010000010001), CONST64(0x0101000000010101), CONST64(0x0101010000010101), + CONST64(0x0000000001000001), CONST64(0x0000010001000001), CONST64(0x0000000001000101), CONST64(0x0000010001000101), + CONST64(0x0001000001000001), CONST64(0x0001010001000001), CONST64(0x0001000001000101), CONST64(0x0001010001000101), + CONST64(0x0000000001010001), CONST64(0x0000010001010001), CONST64(0x0000000001010101), CONST64(0x0000010001010101), + CONST64(0x0001000001010001), CONST64(0x0001010001010001), CONST64(0x0001000001010101), CONST64(0x0001010001010101), + CONST64(0x0100000001000001), CONST64(0x0100010001000001), CONST64(0x0100000001000101), CONST64(0x0100010001000101), + CONST64(0x0101000001000001), CONST64(0x0101010001000001), CONST64(0x0101000001000101), CONST64(0x0101010001000101), + CONST64(0x0100000001010001), CONST64(0x0100010001010001), CONST64(0x0100000001010101), CONST64(0x0100010001010101), + CONST64(0x0101000001010001), CONST64(0x0101010001010001), CONST64(0x0101000001010101), CONST64(0x0101010001010101), + CONST64(0x0000000100000001), CONST64(0x0000010100000001), CONST64(0x0000000100000101), CONST64(0x0000010100000101), + CONST64(0x0001000100000001), CONST64(0x0001010100000001), CONST64(0x0001000100000101), CONST64(0x0001010100000101), + CONST64(0x0000000100010001), CONST64(0x0000010100010001), CONST64(0x0000000100010101), CONST64(0x0000010100010101), + CONST64(0x0001000100010001), CONST64(0x0001010100010001), CONST64(0x0001000100010101), CONST64(0x0001010100010101), + CONST64(0x0100000100000001), CONST64(0x0100010100000001), CONST64(0x0100000100000101), CONST64(0x0100010100000101), + CONST64(0x0101000100000001), CONST64(0x0101010100000001), CONST64(0x0101000100000101), CONST64(0x0101010100000101), + CONST64(0x0100000100010001), CONST64(0x0100010100010001), CONST64(0x0100000100010101), CONST64(0x0100010100010101), + CONST64(0x0101000100010001), CONST64(0x0101010100010001), CONST64(0x0101000100010101), CONST64(0x0101010100010101), + CONST64(0x0000000101000001), CONST64(0x0000010101000001), CONST64(0x0000000101000101), CONST64(0x0000010101000101), + CONST64(0x0001000101000001), CONST64(0x0001010101000001), CONST64(0x0001000101000101), CONST64(0x0001010101000101), + CONST64(0x0000000101010001), CONST64(0x0000010101010001), CONST64(0x0000000101010101), CONST64(0x0000010101010101), + CONST64(0x0001000101010001), CONST64(0x0001010101010001), CONST64(0x0001000101010101), CONST64(0x0001010101010101), + CONST64(0x0100000101000001), CONST64(0x0100010101000001), CONST64(0x0100000101000101), CONST64(0x0100010101000101), + CONST64(0x0101000101000001), CONST64(0x0101010101000001), CONST64(0x0101000101000101), CONST64(0x0101010101000101), + CONST64(0x0100000101010001), CONST64(0x0100010101010001), CONST64(0x0100000101010101), CONST64(0x0100010101010101), + CONST64(0x0101000101010001), CONST64(0x0101010101010001), CONST64(0x0101000101010101), CONST64(0x0101010101010101) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000000000080), CONST64(0x0000008000000080), + CONST64(0x0000800000000000), CONST64(0x0000808000000000), CONST64(0x0000800000000080), CONST64(0x0000808000000080), + CONST64(0x0000000000008000), CONST64(0x0000008000008000), CONST64(0x0000000000008080), CONST64(0x0000008000008080), + CONST64(0x0000800000008000), CONST64(0x0000808000008000), CONST64(0x0000800000008080), CONST64(0x0000808000008080), + CONST64(0x0080000000000000), CONST64(0x0080008000000000), CONST64(0x0080000000000080), CONST64(0x0080008000000080), + CONST64(0x0080800000000000), CONST64(0x0080808000000000), CONST64(0x0080800000000080), CONST64(0x0080808000000080), + CONST64(0x0080000000008000), CONST64(0x0080008000008000), CONST64(0x0080000000008080), CONST64(0x0080008000008080), + CONST64(0x0080800000008000), CONST64(0x0080808000008000), CONST64(0x0080800000008080), CONST64(0x0080808000008080), + CONST64(0x0000000000800000), CONST64(0x0000008000800000), CONST64(0x0000000000800080), CONST64(0x0000008000800080), + CONST64(0x0000800000800000), CONST64(0x0000808000800000), CONST64(0x0000800000800080), CONST64(0x0000808000800080), + CONST64(0x0000000000808000), CONST64(0x0000008000808000), CONST64(0x0000000000808080), CONST64(0x0000008000808080), + CONST64(0x0000800000808000), CONST64(0x0000808000808000), CONST64(0x0000800000808080), CONST64(0x0000808000808080), + CONST64(0x0080000000800000), CONST64(0x0080008000800000), CONST64(0x0080000000800080), CONST64(0x0080008000800080), + CONST64(0x0080800000800000), CONST64(0x0080808000800000), CONST64(0x0080800000800080), CONST64(0x0080808000800080), + CONST64(0x0080000000808000), CONST64(0x0080008000808000), CONST64(0x0080000000808080), CONST64(0x0080008000808080), + CONST64(0x0080800000808000), CONST64(0x0080808000808000), CONST64(0x0080800000808080), CONST64(0x0080808000808080), + CONST64(0x8000000000000000), CONST64(0x8000008000000000), CONST64(0x8000000000000080), CONST64(0x8000008000000080), + CONST64(0x8000800000000000), CONST64(0x8000808000000000), CONST64(0x8000800000000080), CONST64(0x8000808000000080), + CONST64(0x8000000000008000), CONST64(0x8000008000008000), CONST64(0x8000000000008080), CONST64(0x8000008000008080), + CONST64(0x8000800000008000), CONST64(0x8000808000008000), CONST64(0x8000800000008080), CONST64(0x8000808000008080), + CONST64(0x8080000000000000), CONST64(0x8080008000000000), CONST64(0x8080000000000080), CONST64(0x8080008000000080), + CONST64(0x8080800000000000), CONST64(0x8080808000000000), CONST64(0x8080800000000080), CONST64(0x8080808000000080), + CONST64(0x8080000000008000), CONST64(0x8080008000008000), CONST64(0x8080000000008080), CONST64(0x8080008000008080), + CONST64(0x8080800000008000), CONST64(0x8080808000008000), CONST64(0x8080800000008080), CONST64(0x8080808000008080), + CONST64(0x8000000000800000), CONST64(0x8000008000800000), CONST64(0x8000000000800080), CONST64(0x8000008000800080), + CONST64(0x8000800000800000), CONST64(0x8000808000800000), CONST64(0x8000800000800080), CONST64(0x8000808000800080), + CONST64(0x8000000000808000), CONST64(0x8000008000808000), CONST64(0x8000000000808080), CONST64(0x8000008000808080), + CONST64(0x8000800000808000), CONST64(0x8000808000808000), CONST64(0x8000800000808080), CONST64(0x8000808000808080), + CONST64(0x8080000000800000), CONST64(0x8080008000800000), CONST64(0x8080000000800080), CONST64(0x8080008000800080), + CONST64(0x8080800000800000), CONST64(0x8080808000800000), CONST64(0x8080800000800080), CONST64(0x8080808000800080), + CONST64(0x8080000000808000), CONST64(0x8080008000808000), CONST64(0x8080000000808080), CONST64(0x8080008000808080), + CONST64(0x8080800000808000), CONST64(0x8080808000808000), CONST64(0x8080800000808080), CONST64(0x8080808000808080), + CONST64(0x0000000080000000), CONST64(0x0000008080000000), CONST64(0x0000000080000080), CONST64(0x0000008080000080), + CONST64(0x0000800080000000), CONST64(0x0000808080000000), CONST64(0x0000800080000080), CONST64(0x0000808080000080), + CONST64(0x0000000080008000), CONST64(0x0000008080008000), CONST64(0x0000000080008080), CONST64(0x0000008080008080), + CONST64(0x0000800080008000), CONST64(0x0000808080008000), CONST64(0x0000800080008080), CONST64(0x0000808080008080), + CONST64(0x0080000080000000), CONST64(0x0080008080000000), CONST64(0x0080000080000080), CONST64(0x0080008080000080), + CONST64(0x0080800080000000), CONST64(0x0080808080000000), CONST64(0x0080800080000080), CONST64(0x0080808080000080), + CONST64(0x0080000080008000), CONST64(0x0080008080008000), CONST64(0x0080000080008080), CONST64(0x0080008080008080), + CONST64(0x0080800080008000), CONST64(0x0080808080008000), CONST64(0x0080800080008080), CONST64(0x0080808080008080), + CONST64(0x0000000080800000), CONST64(0x0000008080800000), CONST64(0x0000000080800080), CONST64(0x0000008080800080), + CONST64(0x0000800080800000), CONST64(0x0000808080800000), CONST64(0x0000800080800080), CONST64(0x0000808080800080), + CONST64(0x0000000080808000), CONST64(0x0000008080808000), CONST64(0x0000000080808080), CONST64(0x0000008080808080), + CONST64(0x0000800080808000), CONST64(0x0000808080808000), CONST64(0x0000800080808080), CONST64(0x0000808080808080), + CONST64(0x0080000080800000), CONST64(0x0080008080800000), CONST64(0x0080000080800080), CONST64(0x0080008080800080), + CONST64(0x0080800080800000), CONST64(0x0080808080800000), CONST64(0x0080800080800080), CONST64(0x0080808080800080), + CONST64(0x0080000080808000), CONST64(0x0080008080808000), CONST64(0x0080000080808080), CONST64(0x0080008080808080), + CONST64(0x0080800080808000), CONST64(0x0080808080808000), CONST64(0x0080800080808080), CONST64(0x0080808080808080), + CONST64(0x8000000080000000), CONST64(0x8000008080000000), CONST64(0x8000000080000080), CONST64(0x8000008080000080), + CONST64(0x8000800080000000), CONST64(0x8000808080000000), CONST64(0x8000800080000080), CONST64(0x8000808080000080), + CONST64(0x8000000080008000), CONST64(0x8000008080008000), CONST64(0x8000000080008080), CONST64(0x8000008080008080), + CONST64(0x8000800080008000), CONST64(0x8000808080008000), CONST64(0x8000800080008080), CONST64(0x8000808080008080), + CONST64(0x8080000080000000), CONST64(0x8080008080000000), CONST64(0x8080000080000080), CONST64(0x8080008080000080), + CONST64(0x8080800080000000), CONST64(0x8080808080000000), CONST64(0x8080800080000080), CONST64(0x8080808080000080), + CONST64(0x8080000080008000), CONST64(0x8080008080008000), CONST64(0x8080000080008080), CONST64(0x8080008080008080), + CONST64(0x8080800080008000), CONST64(0x8080808080008000), CONST64(0x8080800080008080), CONST64(0x8080808080008080), + CONST64(0x8000000080800000), CONST64(0x8000008080800000), CONST64(0x8000000080800080), CONST64(0x8000008080800080), + CONST64(0x8000800080800000), CONST64(0x8000808080800000), CONST64(0x8000800080800080), CONST64(0x8000808080800080), + CONST64(0x8000000080808000), CONST64(0x8000008080808000), CONST64(0x8000000080808080), CONST64(0x8000008080808080), + CONST64(0x8000800080808000), CONST64(0x8000808080808000), CONST64(0x8000800080808080), CONST64(0x8000808080808080), + CONST64(0x8080000080800000), CONST64(0x8080008080800000), CONST64(0x8080000080800080), CONST64(0x8080008080800080), + CONST64(0x8080800080800000), CONST64(0x8080808080800000), CONST64(0x8080800080800080), CONST64(0x8080808080800080), + CONST64(0x8080000080808000), CONST64(0x8080008080808000), CONST64(0x8080000080808080), CONST64(0x8080008080808080), + CONST64(0x8080800080808000), CONST64(0x8080808080808000), CONST64(0x8080800080808080), CONST64(0x8080808080808080) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000000000040), CONST64(0x0000004000000040), + CONST64(0x0000400000000000), CONST64(0x0000404000000000), CONST64(0x0000400000000040), CONST64(0x0000404000000040), + CONST64(0x0000000000004000), CONST64(0x0000004000004000), CONST64(0x0000000000004040), CONST64(0x0000004000004040), + CONST64(0x0000400000004000), CONST64(0x0000404000004000), CONST64(0x0000400000004040), CONST64(0x0000404000004040), + CONST64(0x0040000000000000), CONST64(0x0040004000000000), CONST64(0x0040000000000040), CONST64(0x0040004000000040), + CONST64(0x0040400000000000), CONST64(0x0040404000000000), CONST64(0x0040400000000040), CONST64(0x0040404000000040), + CONST64(0x0040000000004000), CONST64(0x0040004000004000), CONST64(0x0040000000004040), CONST64(0x0040004000004040), + CONST64(0x0040400000004000), CONST64(0x0040404000004000), CONST64(0x0040400000004040), CONST64(0x0040404000004040), + CONST64(0x0000000000400000), CONST64(0x0000004000400000), CONST64(0x0000000000400040), CONST64(0x0000004000400040), + CONST64(0x0000400000400000), CONST64(0x0000404000400000), CONST64(0x0000400000400040), CONST64(0x0000404000400040), + CONST64(0x0000000000404000), CONST64(0x0000004000404000), CONST64(0x0000000000404040), CONST64(0x0000004000404040), + CONST64(0x0000400000404000), CONST64(0x0000404000404000), CONST64(0x0000400000404040), CONST64(0x0000404000404040), + CONST64(0x0040000000400000), CONST64(0x0040004000400000), CONST64(0x0040000000400040), CONST64(0x0040004000400040), + CONST64(0x0040400000400000), CONST64(0x0040404000400000), CONST64(0x0040400000400040), CONST64(0x0040404000400040), + CONST64(0x0040000000404000), CONST64(0x0040004000404000), CONST64(0x0040000000404040), CONST64(0x0040004000404040), + CONST64(0x0040400000404000), CONST64(0x0040404000404000), CONST64(0x0040400000404040), CONST64(0x0040404000404040), + CONST64(0x4000000000000000), CONST64(0x4000004000000000), CONST64(0x4000000000000040), CONST64(0x4000004000000040), + CONST64(0x4000400000000000), CONST64(0x4000404000000000), CONST64(0x4000400000000040), CONST64(0x4000404000000040), + CONST64(0x4000000000004000), CONST64(0x4000004000004000), CONST64(0x4000000000004040), CONST64(0x4000004000004040), + CONST64(0x4000400000004000), CONST64(0x4000404000004000), CONST64(0x4000400000004040), CONST64(0x4000404000004040), + CONST64(0x4040000000000000), CONST64(0x4040004000000000), CONST64(0x4040000000000040), CONST64(0x4040004000000040), + CONST64(0x4040400000000000), CONST64(0x4040404000000000), CONST64(0x4040400000000040), CONST64(0x4040404000000040), + CONST64(0x4040000000004000), CONST64(0x4040004000004000), CONST64(0x4040000000004040), CONST64(0x4040004000004040), + CONST64(0x4040400000004000), CONST64(0x4040404000004000), CONST64(0x4040400000004040), CONST64(0x4040404000004040), + CONST64(0x4000000000400000), CONST64(0x4000004000400000), CONST64(0x4000000000400040), CONST64(0x4000004000400040), + CONST64(0x4000400000400000), CONST64(0x4000404000400000), CONST64(0x4000400000400040), CONST64(0x4000404000400040), + CONST64(0x4000000000404000), CONST64(0x4000004000404000), CONST64(0x4000000000404040), CONST64(0x4000004000404040), + CONST64(0x4000400000404000), CONST64(0x4000404000404000), CONST64(0x4000400000404040), CONST64(0x4000404000404040), + CONST64(0x4040000000400000), CONST64(0x4040004000400000), CONST64(0x4040000000400040), CONST64(0x4040004000400040), + CONST64(0x4040400000400000), CONST64(0x4040404000400000), CONST64(0x4040400000400040), CONST64(0x4040404000400040), + CONST64(0x4040000000404000), CONST64(0x4040004000404000), CONST64(0x4040000000404040), CONST64(0x4040004000404040), + CONST64(0x4040400000404000), CONST64(0x4040404000404000), CONST64(0x4040400000404040), CONST64(0x4040404000404040), + CONST64(0x0000000040000000), CONST64(0x0000004040000000), CONST64(0x0000000040000040), CONST64(0x0000004040000040), + CONST64(0x0000400040000000), CONST64(0x0000404040000000), CONST64(0x0000400040000040), CONST64(0x0000404040000040), + CONST64(0x0000000040004000), CONST64(0x0000004040004000), CONST64(0x0000000040004040), CONST64(0x0000004040004040), + CONST64(0x0000400040004000), CONST64(0x0000404040004000), CONST64(0x0000400040004040), CONST64(0x0000404040004040), + CONST64(0x0040000040000000), CONST64(0x0040004040000000), CONST64(0x0040000040000040), CONST64(0x0040004040000040), + CONST64(0x0040400040000000), CONST64(0x0040404040000000), CONST64(0x0040400040000040), CONST64(0x0040404040000040), + CONST64(0x0040000040004000), CONST64(0x0040004040004000), CONST64(0x0040000040004040), CONST64(0x0040004040004040), + CONST64(0x0040400040004000), CONST64(0x0040404040004000), CONST64(0x0040400040004040), CONST64(0x0040404040004040), + CONST64(0x0000000040400000), CONST64(0x0000004040400000), CONST64(0x0000000040400040), CONST64(0x0000004040400040), + CONST64(0x0000400040400000), CONST64(0x0000404040400000), CONST64(0x0000400040400040), CONST64(0x0000404040400040), + CONST64(0x0000000040404000), CONST64(0x0000004040404000), CONST64(0x0000000040404040), CONST64(0x0000004040404040), + CONST64(0x0000400040404000), CONST64(0x0000404040404000), CONST64(0x0000400040404040), CONST64(0x0000404040404040), + CONST64(0x0040000040400000), CONST64(0x0040004040400000), CONST64(0x0040000040400040), CONST64(0x0040004040400040), + CONST64(0x0040400040400000), CONST64(0x0040404040400000), CONST64(0x0040400040400040), CONST64(0x0040404040400040), + CONST64(0x0040000040404000), CONST64(0x0040004040404000), CONST64(0x0040000040404040), CONST64(0x0040004040404040), + CONST64(0x0040400040404000), CONST64(0x0040404040404000), CONST64(0x0040400040404040), CONST64(0x0040404040404040), + CONST64(0x4000000040000000), CONST64(0x4000004040000000), CONST64(0x4000000040000040), CONST64(0x4000004040000040), + CONST64(0x4000400040000000), CONST64(0x4000404040000000), CONST64(0x4000400040000040), CONST64(0x4000404040000040), + CONST64(0x4000000040004000), CONST64(0x4000004040004000), CONST64(0x4000000040004040), CONST64(0x4000004040004040), + CONST64(0x4000400040004000), CONST64(0x4000404040004000), CONST64(0x4000400040004040), CONST64(0x4000404040004040), + CONST64(0x4040000040000000), CONST64(0x4040004040000000), CONST64(0x4040000040000040), CONST64(0x4040004040000040), + CONST64(0x4040400040000000), CONST64(0x4040404040000000), CONST64(0x4040400040000040), CONST64(0x4040404040000040), + CONST64(0x4040000040004000), CONST64(0x4040004040004000), CONST64(0x4040000040004040), CONST64(0x4040004040004040), + CONST64(0x4040400040004000), CONST64(0x4040404040004000), CONST64(0x4040400040004040), CONST64(0x4040404040004040), + CONST64(0x4000000040400000), CONST64(0x4000004040400000), CONST64(0x4000000040400040), CONST64(0x4000004040400040), + CONST64(0x4000400040400000), CONST64(0x4000404040400000), CONST64(0x4000400040400040), CONST64(0x4000404040400040), + CONST64(0x4000000040404000), CONST64(0x4000004040404000), CONST64(0x4000000040404040), CONST64(0x4000004040404040), + CONST64(0x4000400040404000), CONST64(0x4000404040404000), CONST64(0x4000400040404040), CONST64(0x4000404040404040), + CONST64(0x4040000040400000), CONST64(0x4040004040400000), CONST64(0x4040000040400040), CONST64(0x4040004040400040), + CONST64(0x4040400040400000), CONST64(0x4040404040400000), CONST64(0x4040400040400040), CONST64(0x4040404040400040), + CONST64(0x4040000040404000), CONST64(0x4040004040404000), CONST64(0x4040000040404040), CONST64(0x4040004040404040), + CONST64(0x4040400040404000), CONST64(0x4040404040404000), CONST64(0x4040400040404040), CONST64(0x4040404040404040) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000000000020), CONST64(0x0000002000000020), + CONST64(0x0000200000000000), CONST64(0x0000202000000000), CONST64(0x0000200000000020), CONST64(0x0000202000000020), + CONST64(0x0000000000002000), CONST64(0x0000002000002000), CONST64(0x0000000000002020), CONST64(0x0000002000002020), + CONST64(0x0000200000002000), CONST64(0x0000202000002000), CONST64(0x0000200000002020), CONST64(0x0000202000002020), + CONST64(0x0020000000000000), CONST64(0x0020002000000000), CONST64(0x0020000000000020), CONST64(0x0020002000000020), + CONST64(0x0020200000000000), CONST64(0x0020202000000000), CONST64(0x0020200000000020), CONST64(0x0020202000000020), + CONST64(0x0020000000002000), CONST64(0x0020002000002000), CONST64(0x0020000000002020), CONST64(0x0020002000002020), + CONST64(0x0020200000002000), CONST64(0x0020202000002000), CONST64(0x0020200000002020), CONST64(0x0020202000002020), + CONST64(0x0000000000200000), CONST64(0x0000002000200000), CONST64(0x0000000000200020), CONST64(0x0000002000200020), + CONST64(0x0000200000200000), CONST64(0x0000202000200000), CONST64(0x0000200000200020), CONST64(0x0000202000200020), + CONST64(0x0000000000202000), CONST64(0x0000002000202000), CONST64(0x0000000000202020), CONST64(0x0000002000202020), + CONST64(0x0000200000202000), CONST64(0x0000202000202000), CONST64(0x0000200000202020), CONST64(0x0000202000202020), + CONST64(0x0020000000200000), CONST64(0x0020002000200000), CONST64(0x0020000000200020), CONST64(0x0020002000200020), + CONST64(0x0020200000200000), CONST64(0x0020202000200000), CONST64(0x0020200000200020), CONST64(0x0020202000200020), + CONST64(0x0020000000202000), CONST64(0x0020002000202000), CONST64(0x0020000000202020), CONST64(0x0020002000202020), + CONST64(0x0020200000202000), CONST64(0x0020202000202000), CONST64(0x0020200000202020), CONST64(0x0020202000202020), + CONST64(0x2000000000000000), CONST64(0x2000002000000000), CONST64(0x2000000000000020), CONST64(0x2000002000000020), + CONST64(0x2000200000000000), CONST64(0x2000202000000000), CONST64(0x2000200000000020), CONST64(0x2000202000000020), + CONST64(0x2000000000002000), CONST64(0x2000002000002000), CONST64(0x2000000000002020), CONST64(0x2000002000002020), + CONST64(0x2000200000002000), CONST64(0x2000202000002000), CONST64(0x2000200000002020), CONST64(0x2000202000002020), + CONST64(0x2020000000000000), CONST64(0x2020002000000000), CONST64(0x2020000000000020), CONST64(0x2020002000000020), + CONST64(0x2020200000000000), CONST64(0x2020202000000000), CONST64(0x2020200000000020), CONST64(0x2020202000000020), + CONST64(0x2020000000002000), CONST64(0x2020002000002000), CONST64(0x2020000000002020), CONST64(0x2020002000002020), + CONST64(0x2020200000002000), CONST64(0x2020202000002000), CONST64(0x2020200000002020), CONST64(0x2020202000002020), + CONST64(0x2000000000200000), CONST64(0x2000002000200000), CONST64(0x2000000000200020), CONST64(0x2000002000200020), + CONST64(0x2000200000200000), CONST64(0x2000202000200000), CONST64(0x2000200000200020), CONST64(0x2000202000200020), + CONST64(0x2000000000202000), CONST64(0x2000002000202000), CONST64(0x2000000000202020), CONST64(0x2000002000202020), + CONST64(0x2000200000202000), CONST64(0x2000202000202000), CONST64(0x2000200000202020), CONST64(0x2000202000202020), + CONST64(0x2020000000200000), CONST64(0x2020002000200000), CONST64(0x2020000000200020), CONST64(0x2020002000200020), + CONST64(0x2020200000200000), CONST64(0x2020202000200000), CONST64(0x2020200000200020), CONST64(0x2020202000200020), + CONST64(0x2020000000202000), CONST64(0x2020002000202000), CONST64(0x2020000000202020), CONST64(0x2020002000202020), + CONST64(0x2020200000202000), CONST64(0x2020202000202000), CONST64(0x2020200000202020), CONST64(0x2020202000202020), + CONST64(0x0000000020000000), CONST64(0x0000002020000000), CONST64(0x0000000020000020), CONST64(0x0000002020000020), + CONST64(0x0000200020000000), CONST64(0x0000202020000000), CONST64(0x0000200020000020), CONST64(0x0000202020000020), + CONST64(0x0000000020002000), CONST64(0x0000002020002000), CONST64(0x0000000020002020), CONST64(0x0000002020002020), + CONST64(0x0000200020002000), CONST64(0x0000202020002000), CONST64(0x0000200020002020), CONST64(0x0000202020002020), + CONST64(0x0020000020000000), CONST64(0x0020002020000000), CONST64(0x0020000020000020), CONST64(0x0020002020000020), + CONST64(0x0020200020000000), CONST64(0x0020202020000000), CONST64(0x0020200020000020), CONST64(0x0020202020000020), + CONST64(0x0020000020002000), CONST64(0x0020002020002000), CONST64(0x0020000020002020), CONST64(0x0020002020002020), + CONST64(0x0020200020002000), CONST64(0x0020202020002000), CONST64(0x0020200020002020), CONST64(0x0020202020002020), + CONST64(0x0000000020200000), CONST64(0x0000002020200000), CONST64(0x0000000020200020), CONST64(0x0000002020200020), + CONST64(0x0000200020200000), CONST64(0x0000202020200000), CONST64(0x0000200020200020), CONST64(0x0000202020200020), + CONST64(0x0000000020202000), CONST64(0x0000002020202000), CONST64(0x0000000020202020), CONST64(0x0000002020202020), + CONST64(0x0000200020202000), CONST64(0x0000202020202000), CONST64(0x0000200020202020), CONST64(0x0000202020202020), + CONST64(0x0020000020200000), CONST64(0x0020002020200000), CONST64(0x0020000020200020), CONST64(0x0020002020200020), + CONST64(0x0020200020200000), CONST64(0x0020202020200000), CONST64(0x0020200020200020), CONST64(0x0020202020200020), + CONST64(0x0020000020202000), CONST64(0x0020002020202000), CONST64(0x0020000020202020), CONST64(0x0020002020202020), + CONST64(0x0020200020202000), CONST64(0x0020202020202000), CONST64(0x0020200020202020), CONST64(0x0020202020202020), + CONST64(0x2000000020000000), CONST64(0x2000002020000000), CONST64(0x2000000020000020), CONST64(0x2000002020000020), + CONST64(0x2000200020000000), CONST64(0x2000202020000000), CONST64(0x2000200020000020), CONST64(0x2000202020000020), + CONST64(0x2000000020002000), CONST64(0x2000002020002000), CONST64(0x2000000020002020), CONST64(0x2000002020002020), + CONST64(0x2000200020002000), CONST64(0x2000202020002000), CONST64(0x2000200020002020), CONST64(0x2000202020002020), + CONST64(0x2020000020000000), CONST64(0x2020002020000000), CONST64(0x2020000020000020), CONST64(0x2020002020000020), + CONST64(0x2020200020000000), CONST64(0x2020202020000000), CONST64(0x2020200020000020), CONST64(0x2020202020000020), + CONST64(0x2020000020002000), CONST64(0x2020002020002000), CONST64(0x2020000020002020), CONST64(0x2020002020002020), + CONST64(0x2020200020002000), CONST64(0x2020202020002000), CONST64(0x2020200020002020), CONST64(0x2020202020002020), + CONST64(0x2000000020200000), CONST64(0x2000002020200000), CONST64(0x2000000020200020), CONST64(0x2000002020200020), + CONST64(0x2000200020200000), CONST64(0x2000202020200000), CONST64(0x2000200020200020), CONST64(0x2000202020200020), + CONST64(0x2000000020202000), CONST64(0x2000002020202000), CONST64(0x2000000020202020), CONST64(0x2000002020202020), + CONST64(0x2000200020202000), CONST64(0x2000202020202000), CONST64(0x2000200020202020), CONST64(0x2000202020202020), + CONST64(0x2020000020200000), CONST64(0x2020002020200000), CONST64(0x2020000020200020), CONST64(0x2020002020200020), + CONST64(0x2020200020200000), CONST64(0x2020202020200000), CONST64(0x2020200020200020), CONST64(0x2020202020200020), + CONST64(0x2020000020202000), CONST64(0x2020002020202000), CONST64(0x2020000020202020), CONST64(0x2020002020202020), + CONST64(0x2020200020202000), CONST64(0x2020202020202000), CONST64(0x2020200020202020), CONST64(0x2020202020202020) + }}; + +static const ulong64 des_fp[8][256] = { + +{ CONST64(0x0000000000000000), CONST64(0x0000008000000000), CONST64(0x0000000002000000), CONST64(0x0000008002000000), + CONST64(0x0000000000020000), CONST64(0x0000008000020000), CONST64(0x0000000002020000), CONST64(0x0000008002020000), + CONST64(0x0000000000000200), CONST64(0x0000008000000200), CONST64(0x0000000002000200), CONST64(0x0000008002000200), + CONST64(0x0000000000020200), CONST64(0x0000008000020200), CONST64(0x0000000002020200), CONST64(0x0000008002020200), + CONST64(0x0000000000000002), CONST64(0x0000008000000002), CONST64(0x0000000002000002), CONST64(0x0000008002000002), + CONST64(0x0000000000020002), CONST64(0x0000008000020002), CONST64(0x0000000002020002), CONST64(0x0000008002020002), + CONST64(0x0000000000000202), CONST64(0x0000008000000202), CONST64(0x0000000002000202), CONST64(0x0000008002000202), + CONST64(0x0000000000020202), CONST64(0x0000008000020202), CONST64(0x0000000002020202), CONST64(0x0000008002020202), + CONST64(0x0200000000000000), CONST64(0x0200008000000000), CONST64(0x0200000002000000), CONST64(0x0200008002000000), + CONST64(0x0200000000020000), CONST64(0x0200008000020000), CONST64(0x0200000002020000), CONST64(0x0200008002020000), + CONST64(0x0200000000000200), CONST64(0x0200008000000200), CONST64(0x0200000002000200), CONST64(0x0200008002000200), + CONST64(0x0200000000020200), CONST64(0x0200008000020200), CONST64(0x0200000002020200), CONST64(0x0200008002020200), + CONST64(0x0200000000000002), CONST64(0x0200008000000002), CONST64(0x0200000002000002), CONST64(0x0200008002000002), + CONST64(0x0200000000020002), CONST64(0x0200008000020002), CONST64(0x0200000002020002), CONST64(0x0200008002020002), + CONST64(0x0200000000000202), CONST64(0x0200008000000202), CONST64(0x0200000002000202), CONST64(0x0200008002000202), + CONST64(0x0200000000020202), CONST64(0x0200008000020202), CONST64(0x0200000002020202), CONST64(0x0200008002020202), + CONST64(0x0002000000000000), CONST64(0x0002008000000000), CONST64(0x0002000002000000), CONST64(0x0002008002000000), + CONST64(0x0002000000020000), CONST64(0x0002008000020000), CONST64(0x0002000002020000), CONST64(0x0002008002020000), + CONST64(0x0002000000000200), CONST64(0x0002008000000200), CONST64(0x0002000002000200), CONST64(0x0002008002000200), + CONST64(0x0002000000020200), CONST64(0x0002008000020200), CONST64(0x0002000002020200), CONST64(0x0002008002020200), + CONST64(0x0002000000000002), CONST64(0x0002008000000002), CONST64(0x0002000002000002), CONST64(0x0002008002000002), + CONST64(0x0002000000020002), CONST64(0x0002008000020002), CONST64(0x0002000002020002), CONST64(0x0002008002020002), + CONST64(0x0002000000000202), CONST64(0x0002008000000202), CONST64(0x0002000002000202), CONST64(0x0002008002000202), + CONST64(0x0002000000020202), CONST64(0x0002008000020202), CONST64(0x0002000002020202), CONST64(0x0002008002020202), + CONST64(0x0202000000000000), CONST64(0x0202008000000000), CONST64(0x0202000002000000), CONST64(0x0202008002000000), + CONST64(0x0202000000020000), CONST64(0x0202008000020000), CONST64(0x0202000002020000), CONST64(0x0202008002020000), + CONST64(0x0202000000000200), CONST64(0x0202008000000200), CONST64(0x0202000002000200), CONST64(0x0202008002000200), + CONST64(0x0202000000020200), CONST64(0x0202008000020200), CONST64(0x0202000002020200), CONST64(0x0202008002020200), + CONST64(0x0202000000000002), CONST64(0x0202008000000002), CONST64(0x0202000002000002), CONST64(0x0202008002000002), + CONST64(0x0202000000020002), CONST64(0x0202008000020002), CONST64(0x0202000002020002), CONST64(0x0202008002020002), + CONST64(0x0202000000000202), CONST64(0x0202008000000202), CONST64(0x0202000002000202), CONST64(0x0202008002000202), + CONST64(0x0202000000020202), CONST64(0x0202008000020202), CONST64(0x0202000002020202), CONST64(0x0202008002020202), + CONST64(0x0000020000000000), CONST64(0x0000028000000000), CONST64(0x0000020002000000), CONST64(0x0000028002000000), + CONST64(0x0000020000020000), CONST64(0x0000028000020000), CONST64(0x0000020002020000), CONST64(0x0000028002020000), + CONST64(0x0000020000000200), CONST64(0x0000028000000200), CONST64(0x0000020002000200), CONST64(0x0000028002000200), + CONST64(0x0000020000020200), CONST64(0x0000028000020200), CONST64(0x0000020002020200), CONST64(0x0000028002020200), + CONST64(0x0000020000000002), CONST64(0x0000028000000002), CONST64(0x0000020002000002), CONST64(0x0000028002000002), + CONST64(0x0000020000020002), CONST64(0x0000028000020002), CONST64(0x0000020002020002), CONST64(0x0000028002020002), + CONST64(0x0000020000000202), CONST64(0x0000028000000202), CONST64(0x0000020002000202), CONST64(0x0000028002000202), + CONST64(0x0000020000020202), CONST64(0x0000028000020202), CONST64(0x0000020002020202), CONST64(0x0000028002020202), + CONST64(0x0200020000000000), CONST64(0x0200028000000000), CONST64(0x0200020002000000), CONST64(0x0200028002000000), + CONST64(0x0200020000020000), CONST64(0x0200028000020000), CONST64(0x0200020002020000), CONST64(0x0200028002020000), + CONST64(0x0200020000000200), CONST64(0x0200028000000200), CONST64(0x0200020002000200), CONST64(0x0200028002000200), + CONST64(0x0200020000020200), CONST64(0x0200028000020200), CONST64(0x0200020002020200), CONST64(0x0200028002020200), + CONST64(0x0200020000000002), CONST64(0x0200028000000002), CONST64(0x0200020002000002), CONST64(0x0200028002000002), + CONST64(0x0200020000020002), CONST64(0x0200028000020002), CONST64(0x0200020002020002), CONST64(0x0200028002020002), + CONST64(0x0200020000000202), CONST64(0x0200028000000202), CONST64(0x0200020002000202), CONST64(0x0200028002000202), + CONST64(0x0200020000020202), CONST64(0x0200028000020202), CONST64(0x0200020002020202), CONST64(0x0200028002020202), + CONST64(0x0002020000000000), CONST64(0x0002028000000000), CONST64(0x0002020002000000), CONST64(0x0002028002000000), + CONST64(0x0002020000020000), CONST64(0x0002028000020000), CONST64(0x0002020002020000), CONST64(0x0002028002020000), + CONST64(0x0002020000000200), CONST64(0x0002028000000200), CONST64(0x0002020002000200), CONST64(0x0002028002000200), + CONST64(0x0002020000020200), CONST64(0x0002028000020200), CONST64(0x0002020002020200), CONST64(0x0002028002020200), + CONST64(0x0002020000000002), CONST64(0x0002028000000002), CONST64(0x0002020002000002), CONST64(0x0002028002000002), + CONST64(0x0002020000020002), CONST64(0x0002028000020002), CONST64(0x0002020002020002), CONST64(0x0002028002020002), + CONST64(0x0002020000000202), CONST64(0x0002028000000202), CONST64(0x0002020002000202), CONST64(0x0002028002000202), + CONST64(0x0002020000020202), CONST64(0x0002028000020202), CONST64(0x0002020002020202), CONST64(0x0002028002020202), + CONST64(0x0202020000000000), CONST64(0x0202028000000000), CONST64(0x0202020002000000), CONST64(0x0202028002000000), + CONST64(0x0202020000020000), CONST64(0x0202028000020000), CONST64(0x0202020002020000), CONST64(0x0202028002020000), + CONST64(0x0202020000000200), CONST64(0x0202028000000200), CONST64(0x0202020002000200), CONST64(0x0202028002000200), + CONST64(0x0202020000020200), CONST64(0x0202028000020200), CONST64(0x0202020002020200), CONST64(0x0202028002020200), + CONST64(0x0202020000000002), CONST64(0x0202028000000002), CONST64(0x0202020002000002), CONST64(0x0202028002000002), + CONST64(0x0202020000020002), CONST64(0x0202028000020002), CONST64(0x0202020002020002), CONST64(0x0202028002020002), + CONST64(0x0202020000000202), CONST64(0x0202028000000202), CONST64(0x0202020002000202), CONST64(0x0202028002000202), + CONST64(0x0202020000020202), CONST64(0x0202028000020202), CONST64(0x0202020002020202), CONST64(0x0202028002020202) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000200000000), CONST64(0x0000000008000000), CONST64(0x0000000208000000), + CONST64(0x0000000000080000), CONST64(0x0000000200080000), CONST64(0x0000000008080000), CONST64(0x0000000208080000), + CONST64(0x0000000000000800), CONST64(0x0000000200000800), CONST64(0x0000000008000800), CONST64(0x0000000208000800), + CONST64(0x0000000000080800), CONST64(0x0000000200080800), CONST64(0x0000000008080800), CONST64(0x0000000208080800), + CONST64(0x0000000000000008), CONST64(0x0000000200000008), CONST64(0x0000000008000008), CONST64(0x0000000208000008), + CONST64(0x0000000000080008), CONST64(0x0000000200080008), CONST64(0x0000000008080008), CONST64(0x0000000208080008), + CONST64(0x0000000000000808), CONST64(0x0000000200000808), CONST64(0x0000000008000808), CONST64(0x0000000208000808), + CONST64(0x0000000000080808), CONST64(0x0000000200080808), CONST64(0x0000000008080808), CONST64(0x0000000208080808), + CONST64(0x0800000000000000), CONST64(0x0800000200000000), CONST64(0x0800000008000000), CONST64(0x0800000208000000), + CONST64(0x0800000000080000), CONST64(0x0800000200080000), CONST64(0x0800000008080000), CONST64(0x0800000208080000), + CONST64(0x0800000000000800), CONST64(0x0800000200000800), CONST64(0x0800000008000800), CONST64(0x0800000208000800), + CONST64(0x0800000000080800), CONST64(0x0800000200080800), CONST64(0x0800000008080800), CONST64(0x0800000208080800), + CONST64(0x0800000000000008), CONST64(0x0800000200000008), CONST64(0x0800000008000008), CONST64(0x0800000208000008), + CONST64(0x0800000000080008), CONST64(0x0800000200080008), CONST64(0x0800000008080008), CONST64(0x0800000208080008), + CONST64(0x0800000000000808), CONST64(0x0800000200000808), CONST64(0x0800000008000808), CONST64(0x0800000208000808), + CONST64(0x0800000000080808), CONST64(0x0800000200080808), CONST64(0x0800000008080808), CONST64(0x0800000208080808), + CONST64(0x0008000000000000), CONST64(0x0008000200000000), CONST64(0x0008000008000000), CONST64(0x0008000208000000), + CONST64(0x0008000000080000), CONST64(0x0008000200080000), CONST64(0x0008000008080000), CONST64(0x0008000208080000), + CONST64(0x0008000000000800), CONST64(0x0008000200000800), CONST64(0x0008000008000800), CONST64(0x0008000208000800), + CONST64(0x0008000000080800), CONST64(0x0008000200080800), CONST64(0x0008000008080800), CONST64(0x0008000208080800), + CONST64(0x0008000000000008), CONST64(0x0008000200000008), CONST64(0x0008000008000008), CONST64(0x0008000208000008), + CONST64(0x0008000000080008), CONST64(0x0008000200080008), CONST64(0x0008000008080008), CONST64(0x0008000208080008), + CONST64(0x0008000000000808), CONST64(0x0008000200000808), CONST64(0x0008000008000808), CONST64(0x0008000208000808), + CONST64(0x0008000000080808), CONST64(0x0008000200080808), CONST64(0x0008000008080808), CONST64(0x0008000208080808), + CONST64(0x0808000000000000), CONST64(0x0808000200000000), CONST64(0x0808000008000000), CONST64(0x0808000208000000), + CONST64(0x0808000000080000), CONST64(0x0808000200080000), CONST64(0x0808000008080000), CONST64(0x0808000208080000), + CONST64(0x0808000000000800), CONST64(0x0808000200000800), CONST64(0x0808000008000800), CONST64(0x0808000208000800), + CONST64(0x0808000000080800), CONST64(0x0808000200080800), CONST64(0x0808000008080800), CONST64(0x0808000208080800), + CONST64(0x0808000000000008), CONST64(0x0808000200000008), CONST64(0x0808000008000008), CONST64(0x0808000208000008), + CONST64(0x0808000000080008), CONST64(0x0808000200080008), CONST64(0x0808000008080008), CONST64(0x0808000208080008), + CONST64(0x0808000000000808), CONST64(0x0808000200000808), CONST64(0x0808000008000808), CONST64(0x0808000208000808), + CONST64(0x0808000000080808), CONST64(0x0808000200080808), CONST64(0x0808000008080808), CONST64(0x0808000208080808), + CONST64(0x0000080000000000), CONST64(0x0000080200000000), CONST64(0x0000080008000000), CONST64(0x0000080208000000), + CONST64(0x0000080000080000), CONST64(0x0000080200080000), CONST64(0x0000080008080000), CONST64(0x0000080208080000), + CONST64(0x0000080000000800), CONST64(0x0000080200000800), CONST64(0x0000080008000800), CONST64(0x0000080208000800), + CONST64(0x0000080000080800), CONST64(0x0000080200080800), CONST64(0x0000080008080800), CONST64(0x0000080208080800), + CONST64(0x0000080000000008), CONST64(0x0000080200000008), CONST64(0x0000080008000008), CONST64(0x0000080208000008), + CONST64(0x0000080000080008), CONST64(0x0000080200080008), CONST64(0x0000080008080008), CONST64(0x0000080208080008), + CONST64(0x0000080000000808), CONST64(0x0000080200000808), CONST64(0x0000080008000808), CONST64(0x0000080208000808), + CONST64(0x0000080000080808), CONST64(0x0000080200080808), CONST64(0x0000080008080808), CONST64(0x0000080208080808), + CONST64(0x0800080000000000), CONST64(0x0800080200000000), CONST64(0x0800080008000000), CONST64(0x0800080208000000), + CONST64(0x0800080000080000), CONST64(0x0800080200080000), CONST64(0x0800080008080000), CONST64(0x0800080208080000), + CONST64(0x0800080000000800), CONST64(0x0800080200000800), CONST64(0x0800080008000800), CONST64(0x0800080208000800), + CONST64(0x0800080000080800), CONST64(0x0800080200080800), CONST64(0x0800080008080800), CONST64(0x0800080208080800), + CONST64(0x0800080000000008), CONST64(0x0800080200000008), CONST64(0x0800080008000008), CONST64(0x0800080208000008), + CONST64(0x0800080000080008), CONST64(0x0800080200080008), CONST64(0x0800080008080008), CONST64(0x0800080208080008), + CONST64(0x0800080000000808), CONST64(0x0800080200000808), CONST64(0x0800080008000808), CONST64(0x0800080208000808), + CONST64(0x0800080000080808), CONST64(0x0800080200080808), CONST64(0x0800080008080808), CONST64(0x0800080208080808), + CONST64(0x0008080000000000), CONST64(0x0008080200000000), CONST64(0x0008080008000000), CONST64(0x0008080208000000), + CONST64(0x0008080000080000), CONST64(0x0008080200080000), CONST64(0x0008080008080000), CONST64(0x0008080208080000), + CONST64(0x0008080000000800), CONST64(0x0008080200000800), CONST64(0x0008080008000800), CONST64(0x0008080208000800), + CONST64(0x0008080000080800), CONST64(0x0008080200080800), CONST64(0x0008080008080800), CONST64(0x0008080208080800), + CONST64(0x0008080000000008), CONST64(0x0008080200000008), CONST64(0x0008080008000008), CONST64(0x0008080208000008), + CONST64(0x0008080000080008), CONST64(0x0008080200080008), CONST64(0x0008080008080008), CONST64(0x0008080208080008), + CONST64(0x0008080000000808), CONST64(0x0008080200000808), CONST64(0x0008080008000808), CONST64(0x0008080208000808), + CONST64(0x0008080000080808), CONST64(0x0008080200080808), CONST64(0x0008080008080808), CONST64(0x0008080208080808), + CONST64(0x0808080000000000), CONST64(0x0808080200000000), CONST64(0x0808080008000000), CONST64(0x0808080208000000), + CONST64(0x0808080000080000), CONST64(0x0808080200080000), CONST64(0x0808080008080000), CONST64(0x0808080208080000), + CONST64(0x0808080000000800), CONST64(0x0808080200000800), CONST64(0x0808080008000800), CONST64(0x0808080208000800), + CONST64(0x0808080000080800), CONST64(0x0808080200080800), CONST64(0x0808080008080800), CONST64(0x0808080208080800), + CONST64(0x0808080000000008), CONST64(0x0808080200000008), CONST64(0x0808080008000008), CONST64(0x0808080208000008), + CONST64(0x0808080000080008), CONST64(0x0808080200080008), CONST64(0x0808080008080008), CONST64(0x0808080208080008), + CONST64(0x0808080000000808), CONST64(0x0808080200000808), CONST64(0x0808080008000808), CONST64(0x0808080208000808), + CONST64(0x0808080000080808), CONST64(0x0808080200080808), CONST64(0x0808080008080808), CONST64(0x0808080208080808) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000800000000), CONST64(0x0000000020000000), CONST64(0x0000000820000000), + CONST64(0x0000000000200000), CONST64(0x0000000800200000), CONST64(0x0000000020200000), CONST64(0x0000000820200000), + CONST64(0x0000000000002000), CONST64(0x0000000800002000), CONST64(0x0000000020002000), CONST64(0x0000000820002000), + CONST64(0x0000000000202000), CONST64(0x0000000800202000), CONST64(0x0000000020202000), CONST64(0x0000000820202000), + CONST64(0x0000000000000020), CONST64(0x0000000800000020), CONST64(0x0000000020000020), CONST64(0x0000000820000020), + CONST64(0x0000000000200020), CONST64(0x0000000800200020), CONST64(0x0000000020200020), CONST64(0x0000000820200020), + CONST64(0x0000000000002020), CONST64(0x0000000800002020), CONST64(0x0000000020002020), CONST64(0x0000000820002020), + CONST64(0x0000000000202020), CONST64(0x0000000800202020), CONST64(0x0000000020202020), CONST64(0x0000000820202020), + CONST64(0x2000000000000000), CONST64(0x2000000800000000), CONST64(0x2000000020000000), CONST64(0x2000000820000000), + CONST64(0x2000000000200000), CONST64(0x2000000800200000), CONST64(0x2000000020200000), CONST64(0x2000000820200000), + CONST64(0x2000000000002000), CONST64(0x2000000800002000), CONST64(0x2000000020002000), CONST64(0x2000000820002000), + CONST64(0x2000000000202000), CONST64(0x2000000800202000), CONST64(0x2000000020202000), CONST64(0x2000000820202000), + CONST64(0x2000000000000020), CONST64(0x2000000800000020), CONST64(0x2000000020000020), CONST64(0x2000000820000020), + CONST64(0x2000000000200020), CONST64(0x2000000800200020), CONST64(0x2000000020200020), CONST64(0x2000000820200020), + CONST64(0x2000000000002020), CONST64(0x2000000800002020), CONST64(0x2000000020002020), CONST64(0x2000000820002020), + CONST64(0x2000000000202020), CONST64(0x2000000800202020), CONST64(0x2000000020202020), CONST64(0x2000000820202020), + CONST64(0x0020000000000000), CONST64(0x0020000800000000), CONST64(0x0020000020000000), CONST64(0x0020000820000000), + CONST64(0x0020000000200000), CONST64(0x0020000800200000), CONST64(0x0020000020200000), CONST64(0x0020000820200000), + CONST64(0x0020000000002000), CONST64(0x0020000800002000), CONST64(0x0020000020002000), CONST64(0x0020000820002000), + CONST64(0x0020000000202000), CONST64(0x0020000800202000), CONST64(0x0020000020202000), CONST64(0x0020000820202000), + CONST64(0x0020000000000020), CONST64(0x0020000800000020), CONST64(0x0020000020000020), CONST64(0x0020000820000020), + CONST64(0x0020000000200020), CONST64(0x0020000800200020), CONST64(0x0020000020200020), CONST64(0x0020000820200020), + CONST64(0x0020000000002020), CONST64(0x0020000800002020), CONST64(0x0020000020002020), CONST64(0x0020000820002020), + CONST64(0x0020000000202020), CONST64(0x0020000800202020), CONST64(0x0020000020202020), CONST64(0x0020000820202020), + CONST64(0x2020000000000000), CONST64(0x2020000800000000), CONST64(0x2020000020000000), CONST64(0x2020000820000000), + CONST64(0x2020000000200000), CONST64(0x2020000800200000), CONST64(0x2020000020200000), CONST64(0x2020000820200000), + CONST64(0x2020000000002000), CONST64(0x2020000800002000), CONST64(0x2020000020002000), CONST64(0x2020000820002000), + CONST64(0x2020000000202000), CONST64(0x2020000800202000), CONST64(0x2020000020202000), CONST64(0x2020000820202000), + CONST64(0x2020000000000020), CONST64(0x2020000800000020), CONST64(0x2020000020000020), CONST64(0x2020000820000020), + CONST64(0x2020000000200020), CONST64(0x2020000800200020), CONST64(0x2020000020200020), CONST64(0x2020000820200020), + CONST64(0x2020000000002020), CONST64(0x2020000800002020), CONST64(0x2020000020002020), CONST64(0x2020000820002020), + CONST64(0x2020000000202020), CONST64(0x2020000800202020), CONST64(0x2020000020202020), CONST64(0x2020000820202020), + CONST64(0x0000200000000000), CONST64(0x0000200800000000), CONST64(0x0000200020000000), CONST64(0x0000200820000000), + CONST64(0x0000200000200000), CONST64(0x0000200800200000), CONST64(0x0000200020200000), CONST64(0x0000200820200000), + CONST64(0x0000200000002000), CONST64(0x0000200800002000), CONST64(0x0000200020002000), CONST64(0x0000200820002000), + CONST64(0x0000200000202000), CONST64(0x0000200800202000), CONST64(0x0000200020202000), CONST64(0x0000200820202000), + CONST64(0x0000200000000020), CONST64(0x0000200800000020), CONST64(0x0000200020000020), CONST64(0x0000200820000020), + CONST64(0x0000200000200020), CONST64(0x0000200800200020), CONST64(0x0000200020200020), CONST64(0x0000200820200020), + CONST64(0x0000200000002020), CONST64(0x0000200800002020), CONST64(0x0000200020002020), CONST64(0x0000200820002020), + CONST64(0x0000200000202020), CONST64(0x0000200800202020), CONST64(0x0000200020202020), CONST64(0x0000200820202020), + CONST64(0x2000200000000000), CONST64(0x2000200800000000), CONST64(0x2000200020000000), CONST64(0x2000200820000000), + CONST64(0x2000200000200000), CONST64(0x2000200800200000), CONST64(0x2000200020200000), CONST64(0x2000200820200000), + CONST64(0x2000200000002000), CONST64(0x2000200800002000), CONST64(0x2000200020002000), CONST64(0x2000200820002000), + CONST64(0x2000200000202000), CONST64(0x2000200800202000), CONST64(0x2000200020202000), CONST64(0x2000200820202000), + CONST64(0x2000200000000020), CONST64(0x2000200800000020), CONST64(0x2000200020000020), CONST64(0x2000200820000020), + CONST64(0x2000200000200020), CONST64(0x2000200800200020), CONST64(0x2000200020200020), CONST64(0x2000200820200020), + CONST64(0x2000200000002020), CONST64(0x2000200800002020), CONST64(0x2000200020002020), CONST64(0x2000200820002020), + CONST64(0x2000200000202020), CONST64(0x2000200800202020), CONST64(0x2000200020202020), CONST64(0x2000200820202020), + CONST64(0x0020200000000000), CONST64(0x0020200800000000), CONST64(0x0020200020000000), CONST64(0x0020200820000000), + CONST64(0x0020200000200000), CONST64(0x0020200800200000), CONST64(0x0020200020200000), CONST64(0x0020200820200000), + CONST64(0x0020200000002000), CONST64(0x0020200800002000), CONST64(0x0020200020002000), CONST64(0x0020200820002000), + CONST64(0x0020200000202000), CONST64(0x0020200800202000), CONST64(0x0020200020202000), CONST64(0x0020200820202000), + CONST64(0x0020200000000020), CONST64(0x0020200800000020), CONST64(0x0020200020000020), CONST64(0x0020200820000020), + CONST64(0x0020200000200020), CONST64(0x0020200800200020), CONST64(0x0020200020200020), CONST64(0x0020200820200020), + CONST64(0x0020200000002020), CONST64(0x0020200800002020), CONST64(0x0020200020002020), CONST64(0x0020200820002020), + CONST64(0x0020200000202020), CONST64(0x0020200800202020), CONST64(0x0020200020202020), CONST64(0x0020200820202020), + CONST64(0x2020200000000000), CONST64(0x2020200800000000), CONST64(0x2020200020000000), CONST64(0x2020200820000000), + CONST64(0x2020200000200000), CONST64(0x2020200800200000), CONST64(0x2020200020200000), CONST64(0x2020200820200000), + CONST64(0x2020200000002000), CONST64(0x2020200800002000), CONST64(0x2020200020002000), CONST64(0x2020200820002000), + CONST64(0x2020200000202000), CONST64(0x2020200800202000), CONST64(0x2020200020202000), CONST64(0x2020200820202000), + CONST64(0x2020200000000020), CONST64(0x2020200800000020), CONST64(0x2020200020000020), CONST64(0x2020200820000020), + CONST64(0x2020200000200020), CONST64(0x2020200800200020), CONST64(0x2020200020200020), CONST64(0x2020200820200020), + CONST64(0x2020200000002020), CONST64(0x2020200800002020), CONST64(0x2020200020002020), CONST64(0x2020200820002020), + CONST64(0x2020200000202020), CONST64(0x2020200800202020), CONST64(0x2020200020202020), CONST64(0x2020200820202020) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000002000000000), CONST64(0x0000000080000000), CONST64(0x0000002080000000), + CONST64(0x0000000000800000), CONST64(0x0000002000800000), CONST64(0x0000000080800000), CONST64(0x0000002080800000), + CONST64(0x0000000000008000), CONST64(0x0000002000008000), CONST64(0x0000000080008000), CONST64(0x0000002080008000), + CONST64(0x0000000000808000), CONST64(0x0000002000808000), CONST64(0x0000000080808000), CONST64(0x0000002080808000), + CONST64(0x0000000000000080), CONST64(0x0000002000000080), CONST64(0x0000000080000080), CONST64(0x0000002080000080), + CONST64(0x0000000000800080), CONST64(0x0000002000800080), CONST64(0x0000000080800080), CONST64(0x0000002080800080), + CONST64(0x0000000000008080), CONST64(0x0000002000008080), CONST64(0x0000000080008080), CONST64(0x0000002080008080), + CONST64(0x0000000000808080), CONST64(0x0000002000808080), CONST64(0x0000000080808080), CONST64(0x0000002080808080), + CONST64(0x8000000000000000), CONST64(0x8000002000000000), CONST64(0x8000000080000000), CONST64(0x8000002080000000), + CONST64(0x8000000000800000), CONST64(0x8000002000800000), CONST64(0x8000000080800000), CONST64(0x8000002080800000), + CONST64(0x8000000000008000), CONST64(0x8000002000008000), CONST64(0x8000000080008000), CONST64(0x8000002080008000), + CONST64(0x8000000000808000), CONST64(0x8000002000808000), CONST64(0x8000000080808000), CONST64(0x8000002080808000), + CONST64(0x8000000000000080), CONST64(0x8000002000000080), CONST64(0x8000000080000080), CONST64(0x8000002080000080), + CONST64(0x8000000000800080), CONST64(0x8000002000800080), CONST64(0x8000000080800080), CONST64(0x8000002080800080), + CONST64(0x8000000000008080), CONST64(0x8000002000008080), CONST64(0x8000000080008080), CONST64(0x8000002080008080), + CONST64(0x8000000000808080), CONST64(0x8000002000808080), CONST64(0x8000000080808080), CONST64(0x8000002080808080), + CONST64(0x0080000000000000), CONST64(0x0080002000000000), CONST64(0x0080000080000000), CONST64(0x0080002080000000), + CONST64(0x0080000000800000), CONST64(0x0080002000800000), CONST64(0x0080000080800000), CONST64(0x0080002080800000), + CONST64(0x0080000000008000), CONST64(0x0080002000008000), CONST64(0x0080000080008000), CONST64(0x0080002080008000), + CONST64(0x0080000000808000), CONST64(0x0080002000808000), CONST64(0x0080000080808000), CONST64(0x0080002080808000), + CONST64(0x0080000000000080), CONST64(0x0080002000000080), CONST64(0x0080000080000080), CONST64(0x0080002080000080), + CONST64(0x0080000000800080), CONST64(0x0080002000800080), CONST64(0x0080000080800080), CONST64(0x0080002080800080), + CONST64(0x0080000000008080), CONST64(0x0080002000008080), CONST64(0x0080000080008080), CONST64(0x0080002080008080), + CONST64(0x0080000000808080), CONST64(0x0080002000808080), CONST64(0x0080000080808080), CONST64(0x0080002080808080), + CONST64(0x8080000000000000), CONST64(0x8080002000000000), CONST64(0x8080000080000000), CONST64(0x8080002080000000), + CONST64(0x8080000000800000), CONST64(0x8080002000800000), CONST64(0x8080000080800000), CONST64(0x8080002080800000), + CONST64(0x8080000000008000), CONST64(0x8080002000008000), CONST64(0x8080000080008000), CONST64(0x8080002080008000), + CONST64(0x8080000000808000), CONST64(0x8080002000808000), CONST64(0x8080000080808000), CONST64(0x8080002080808000), + CONST64(0x8080000000000080), CONST64(0x8080002000000080), CONST64(0x8080000080000080), CONST64(0x8080002080000080), + CONST64(0x8080000000800080), CONST64(0x8080002000800080), CONST64(0x8080000080800080), CONST64(0x8080002080800080), + CONST64(0x8080000000008080), CONST64(0x8080002000008080), CONST64(0x8080000080008080), CONST64(0x8080002080008080), + CONST64(0x8080000000808080), CONST64(0x8080002000808080), CONST64(0x8080000080808080), CONST64(0x8080002080808080), + CONST64(0x0000800000000000), CONST64(0x0000802000000000), CONST64(0x0000800080000000), CONST64(0x0000802080000000), + CONST64(0x0000800000800000), CONST64(0x0000802000800000), CONST64(0x0000800080800000), CONST64(0x0000802080800000), + CONST64(0x0000800000008000), CONST64(0x0000802000008000), CONST64(0x0000800080008000), CONST64(0x0000802080008000), + CONST64(0x0000800000808000), CONST64(0x0000802000808000), CONST64(0x0000800080808000), CONST64(0x0000802080808000), + CONST64(0x0000800000000080), CONST64(0x0000802000000080), CONST64(0x0000800080000080), CONST64(0x0000802080000080), + CONST64(0x0000800000800080), CONST64(0x0000802000800080), CONST64(0x0000800080800080), CONST64(0x0000802080800080), + CONST64(0x0000800000008080), CONST64(0x0000802000008080), CONST64(0x0000800080008080), CONST64(0x0000802080008080), + CONST64(0x0000800000808080), CONST64(0x0000802000808080), CONST64(0x0000800080808080), CONST64(0x0000802080808080), + CONST64(0x8000800000000000), CONST64(0x8000802000000000), CONST64(0x8000800080000000), CONST64(0x8000802080000000), + CONST64(0x8000800000800000), CONST64(0x8000802000800000), CONST64(0x8000800080800000), CONST64(0x8000802080800000), + CONST64(0x8000800000008000), CONST64(0x8000802000008000), CONST64(0x8000800080008000), CONST64(0x8000802080008000), + CONST64(0x8000800000808000), CONST64(0x8000802000808000), CONST64(0x8000800080808000), CONST64(0x8000802080808000), + CONST64(0x8000800000000080), CONST64(0x8000802000000080), CONST64(0x8000800080000080), CONST64(0x8000802080000080), + CONST64(0x8000800000800080), CONST64(0x8000802000800080), CONST64(0x8000800080800080), CONST64(0x8000802080800080), + CONST64(0x8000800000008080), CONST64(0x8000802000008080), CONST64(0x8000800080008080), CONST64(0x8000802080008080), + CONST64(0x8000800000808080), CONST64(0x8000802000808080), CONST64(0x8000800080808080), CONST64(0x8000802080808080), + CONST64(0x0080800000000000), CONST64(0x0080802000000000), CONST64(0x0080800080000000), CONST64(0x0080802080000000), + CONST64(0x0080800000800000), CONST64(0x0080802000800000), CONST64(0x0080800080800000), CONST64(0x0080802080800000), + CONST64(0x0080800000008000), CONST64(0x0080802000008000), CONST64(0x0080800080008000), CONST64(0x0080802080008000), + CONST64(0x0080800000808000), CONST64(0x0080802000808000), CONST64(0x0080800080808000), CONST64(0x0080802080808000), + CONST64(0x0080800000000080), CONST64(0x0080802000000080), CONST64(0x0080800080000080), CONST64(0x0080802080000080), + CONST64(0x0080800000800080), CONST64(0x0080802000800080), CONST64(0x0080800080800080), CONST64(0x0080802080800080), + CONST64(0x0080800000008080), CONST64(0x0080802000008080), CONST64(0x0080800080008080), CONST64(0x0080802080008080), + CONST64(0x0080800000808080), CONST64(0x0080802000808080), CONST64(0x0080800080808080), CONST64(0x0080802080808080), + CONST64(0x8080800000000000), CONST64(0x8080802000000000), CONST64(0x8080800080000000), CONST64(0x8080802080000000), + CONST64(0x8080800000800000), CONST64(0x8080802000800000), CONST64(0x8080800080800000), CONST64(0x8080802080800000), + CONST64(0x8080800000008000), CONST64(0x8080802000008000), CONST64(0x8080800080008000), CONST64(0x8080802080008000), + CONST64(0x8080800000808000), CONST64(0x8080802000808000), CONST64(0x8080800080808000), CONST64(0x8080802080808000), + CONST64(0x8080800000000080), CONST64(0x8080802000000080), CONST64(0x8080800080000080), CONST64(0x8080802080000080), + CONST64(0x8080800000800080), CONST64(0x8080802000800080), CONST64(0x8080800080800080), CONST64(0x8080802080800080), + CONST64(0x8080800000008080), CONST64(0x8080802000008080), CONST64(0x8080800080008080), CONST64(0x8080802080008080), + CONST64(0x8080800000808080), CONST64(0x8080802000808080), CONST64(0x8080800080808080), CONST64(0x8080802080808080) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000004000000000), CONST64(0x0000000001000000), CONST64(0x0000004001000000), + CONST64(0x0000000000010000), CONST64(0x0000004000010000), CONST64(0x0000000001010000), CONST64(0x0000004001010000), + CONST64(0x0000000000000100), CONST64(0x0000004000000100), CONST64(0x0000000001000100), CONST64(0x0000004001000100), + CONST64(0x0000000000010100), CONST64(0x0000004000010100), CONST64(0x0000000001010100), CONST64(0x0000004001010100), + CONST64(0x0000000000000001), CONST64(0x0000004000000001), CONST64(0x0000000001000001), CONST64(0x0000004001000001), + CONST64(0x0000000000010001), CONST64(0x0000004000010001), CONST64(0x0000000001010001), CONST64(0x0000004001010001), + CONST64(0x0000000000000101), CONST64(0x0000004000000101), CONST64(0x0000000001000101), CONST64(0x0000004001000101), + CONST64(0x0000000000010101), CONST64(0x0000004000010101), CONST64(0x0000000001010101), CONST64(0x0000004001010101), + CONST64(0x0100000000000000), CONST64(0x0100004000000000), CONST64(0x0100000001000000), CONST64(0x0100004001000000), + CONST64(0x0100000000010000), CONST64(0x0100004000010000), CONST64(0x0100000001010000), CONST64(0x0100004001010000), + CONST64(0x0100000000000100), CONST64(0x0100004000000100), CONST64(0x0100000001000100), CONST64(0x0100004001000100), + CONST64(0x0100000000010100), CONST64(0x0100004000010100), CONST64(0x0100000001010100), CONST64(0x0100004001010100), + CONST64(0x0100000000000001), CONST64(0x0100004000000001), CONST64(0x0100000001000001), CONST64(0x0100004001000001), + CONST64(0x0100000000010001), CONST64(0x0100004000010001), CONST64(0x0100000001010001), CONST64(0x0100004001010001), + CONST64(0x0100000000000101), CONST64(0x0100004000000101), CONST64(0x0100000001000101), CONST64(0x0100004001000101), + CONST64(0x0100000000010101), CONST64(0x0100004000010101), CONST64(0x0100000001010101), CONST64(0x0100004001010101), + CONST64(0x0001000000000000), CONST64(0x0001004000000000), CONST64(0x0001000001000000), CONST64(0x0001004001000000), + CONST64(0x0001000000010000), CONST64(0x0001004000010000), CONST64(0x0001000001010000), CONST64(0x0001004001010000), + CONST64(0x0001000000000100), CONST64(0x0001004000000100), CONST64(0x0001000001000100), CONST64(0x0001004001000100), + CONST64(0x0001000000010100), CONST64(0x0001004000010100), CONST64(0x0001000001010100), CONST64(0x0001004001010100), + CONST64(0x0001000000000001), CONST64(0x0001004000000001), CONST64(0x0001000001000001), CONST64(0x0001004001000001), + CONST64(0x0001000000010001), CONST64(0x0001004000010001), CONST64(0x0001000001010001), CONST64(0x0001004001010001), + CONST64(0x0001000000000101), CONST64(0x0001004000000101), CONST64(0x0001000001000101), CONST64(0x0001004001000101), + CONST64(0x0001000000010101), CONST64(0x0001004000010101), CONST64(0x0001000001010101), CONST64(0x0001004001010101), + CONST64(0x0101000000000000), CONST64(0x0101004000000000), CONST64(0x0101000001000000), CONST64(0x0101004001000000), + CONST64(0x0101000000010000), CONST64(0x0101004000010000), CONST64(0x0101000001010000), CONST64(0x0101004001010000), + CONST64(0x0101000000000100), CONST64(0x0101004000000100), CONST64(0x0101000001000100), CONST64(0x0101004001000100), + CONST64(0x0101000000010100), CONST64(0x0101004000010100), CONST64(0x0101000001010100), CONST64(0x0101004001010100), + CONST64(0x0101000000000001), CONST64(0x0101004000000001), CONST64(0x0101000001000001), CONST64(0x0101004001000001), + CONST64(0x0101000000010001), CONST64(0x0101004000010001), CONST64(0x0101000001010001), CONST64(0x0101004001010001), + CONST64(0x0101000000000101), CONST64(0x0101004000000101), CONST64(0x0101000001000101), CONST64(0x0101004001000101), + CONST64(0x0101000000010101), CONST64(0x0101004000010101), CONST64(0x0101000001010101), CONST64(0x0101004001010101), + CONST64(0x0000010000000000), CONST64(0x0000014000000000), CONST64(0x0000010001000000), CONST64(0x0000014001000000), + CONST64(0x0000010000010000), CONST64(0x0000014000010000), CONST64(0x0000010001010000), CONST64(0x0000014001010000), + CONST64(0x0000010000000100), CONST64(0x0000014000000100), CONST64(0x0000010001000100), CONST64(0x0000014001000100), + CONST64(0x0000010000010100), CONST64(0x0000014000010100), CONST64(0x0000010001010100), CONST64(0x0000014001010100), + CONST64(0x0000010000000001), CONST64(0x0000014000000001), CONST64(0x0000010001000001), CONST64(0x0000014001000001), + CONST64(0x0000010000010001), CONST64(0x0000014000010001), CONST64(0x0000010001010001), CONST64(0x0000014001010001), + CONST64(0x0000010000000101), CONST64(0x0000014000000101), CONST64(0x0000010001000101), CONST64(0x0000014001000101), + CONST64(0x0000010000010101), CONST64(0x0000014000010101), CONST64(0x0000010001010101), CONST64(0x0000014001010101), + CONST64(0x0100010000000000), CONST64(0x0100014000000000), CONST64(0x0100010001000000), CONST64(0x0100014001000000), + CONST64(0x0100010000010000), CONST64(0x0100014000010000), CONST64(0x0100010001010000), CONST64(0x0100014001010000), + CONST64(0x0100010000000100), CONST64(0x0100014000000100), CONST64(0x0100010001000100), CONST64(0x0100014001000100), + CONST64(0x0100010000010100), CONST64(0x0100014000010100), CONST64(0x0100010001010100), CONST64(0x0100014001010100), + CONST64(0x0100010000000001), CONST64(0x0100014000000001), CONST64(0x0100010001000001), CONST64(0x0100014001000001), + CONST64(0x0100010000010001), CONST64(0x0100014000010001), CONST64(0x0100010001010001), CONST64(0x0100014001010001), + CONST64(0x0100010000000101), CONST64(0x0100014000000101), CONST64(0x0100010001000101), CONST64(0x0100014001000101), + CONST64(0x0100010000010101), CONST64(0x0100014000010101), CONST64(0x0100010001010101), CONST64(0x0100014001010101), + CONST64(0x0001010000000000), CONST64(0x0001014000000000), CONST64(0x0001010001000000), CONST64(0x0001014001000000), + CONST64(0x0001010000010000), CONST64(0x0001014000010000), CONST64(0x0001010001010000), CONST64(0x0001014001010000), + CONST64(0x0001010000000100), CONST64(0x0001014000000100), CONST64(0x0001010001000100), CONST64(0x0001014001000100), + CONST64(0x0001010000010100), CONST64(0x0001014000010100), CONST64(0x0001010001010100), CONST64(0x0001014001010100), + CONST64(0x0001010000000001), CONST64(0x0001014000000001), CONST64(0x0001010001000001), CONST64(0x0001014001000001), + CONST64(0x0001010000010001), CONST64(0x0001014000010001), CONST64(0x0001010001010001), CONST64(0x0001014001010001), + CONST64(0x0001010000000101), CONST64(0x0001014000000101), CONST64(0x0001010001000101), CONST64(0x0001014001000101), + CONST64(0x0001010000010101), CONST64(0x0001014000010101), CONST64(0x0001010001010101), CONST64(0x0001014001010101), + CONST64(0x0101010000000000), CONST64(0x0101014000000000), CONST64(0x0101010001000000), CONST64(0x0101014001000000), + CONST64(0x0101010000010000), CONST64(0x0101014000010000), CONST64(0x0101010001010000), CONST64(0x0101014001010000), + CONST64(0x0101010000000100), CONST64(0x0101014000000100), CONST64(0x0101010001000100), CONST64(0x0101014001000100), + CONST64(0x0101010000010100), CONST64(0x0101014000010100), CONST64(0x0101010001010100), CONST64(0x0101014001010100), + CONST64(0x0101010000000001), CONST64(0x0101014000000001), CONST64(0x0101010001000001), CONST64(0x0101014001000001), + CONST64(0x0101010000010001), CONST64(0x0101014000010001), CONST64(0x0101010001010001), CONST64(0x0101014001010001), + CONST64(0x0101010000000101), CONST64(0x0101014000000101), CONST64(0x0101010001000101), CONST64(0x0101014001000101), + CONST64(0x0101010000010101), CONST64(0x0101014000010101), CONST64(0x0101010001010101), CONST64(0x0101014001010101) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000100000000), CONST64(0x0000000004000000), CONST64(0x0000000104000000), + CONST64(0x0000000000040000), CONST64(0x0000000100040000), CONST64(0x0000000004040000), CONST64(0x0000000104040000), + CONST64(0x0000000000000400), CONST64(0x0000000100000400), CONST64(0x0000000004000400), CONST64(0x0000000104000400), + CONST64(0x0000000000040400), CONST64(0x0000000100040400), CONST64(0x0000000004040400), CONST64(0x0000000104040400), + CONST64(0x0000000000000004), CONST64(0x0000000100000004), CONST64(0x0000000004000004), CONST64(0x0000000104000004), + CONST64(0x0000000000040004), CONST64(0x0000000100040004), CONST64(0x0000000004040004), CONST64(0x0000000104040004), + CONST64(0x0000000000000404), CONST64(0x0000000100000404), CONST64(0x0000000004000404), CONST64(0x0000000104000404), + CONST64(0x0000000000040404), CONST64(0x0000000100040404), CONST64(0x0000000004040404), CONST64(0x0000000104040404), + CONST64(0x0400000000000000), CONST64(0x0400000100000000), CONST64(0x0400000004000000), CONST64(0x0400000104000000), + CONST64(0x0400000000040000), CONST64(0x0400000100040000), CONST64(0x0400000004040000), CONST64(0x0400000104040000), + CONST64(0x0400000000000400), CONST64(0x0400000100000400), CONST64(0x0400000004000400), CONST64(0x0400000104000400), + CONST64(0x0400000000040400), CONST64(0x0400000100040400), CONST64(0x0400000004040400), CONST64(0x0400000104040400), + CONST64(0x0400000000000004), CONST64(0x0400000100000004), CONST64(0x0400000004000004), CONST64(0x0400000104000004), + CONST64(0x0400000000040004), CONST64(0x0400000100040004), CONST64(0x0400000004040004), CONST64(0x0400000104040004), + CONST64(0x0400000000000404), CONST64(0x0400000100000404), CONST64(0x0400000004000404), CONST64(0x0400000104000404), + CONST64(0x0400000000040404), CONST64(0x0400000100040404), CONST64(0x0400000004040404), CONST64(0x0400000104040404), + CONST64(0x0004000000000000), CONST64(0x0004000100000000), CONST64(0x0004000004000000), CONST64(0x0004000104000000), + CONST64(0x0004000000040000), CONST64(0x0004000100040000), CONST64(0x0004000004040000), CONST64(0x0004000104040000), + CONST64(0x0004000000000400), CONST64(0x0004000100000400), CONST64(0x0004000004000400), CONST64(0x0004000104000400), + CONST64(0x0004000000040400), CONST64(0x0004000100040400), CONST64(0x0004000004040400), CONST64(0x0004000104040400), + CONST64(0x0004000000000004), CONST64(0x0004000100000004), CONST64(0x0004000004000004), CONST64(0x0004000104000004), + CONST64(0x0004000000040004), CONST64(0x0004000100040004), CONST64(0x0004000004040004), CONST64(0x0004000104040004), + CONST64(0x0004000000000404), CONST64(0x0004000100000404), CONST64(0x0004000004000404), CONST64(0x0004000104000404), + CONST64(0x0004000000040404), CONST64(0x0004000100040404), CONST64(0x0004000004040404), CONST64(0x0004000104040404), + CONST64(0x0404000000000000), CONST64(0x0404000100000000), CONST64(0x0404000004000000), CONST64(0x0404000104000000), + CONST64(0x0404000000040000), CONST64(0x0404000100040000), CONST64(0x0404000004040000), CONST64(0x0404000104040000), + CONST64(0x0404000000000400), CONST64(0x0404000100000400), CONST64(0x0404000004000400), CONST64(0x0404000104000400), + CONST64(0x0404000000040400), CONST64(0x0404000100040400), CONST64(0x0404000004040400), CONST64(0x0404000104040400), + CONST64(0x0404000000000004), CONST64(0x0404000100000004), CONST64(0x0404000004000004), CONST64(0x0404000104000004), + CONST64(0x0404000000040004), CONST64(0x0404000100040004), CONST64(0x0404000004040004), CONST64(0x0404000104040004), + CONST64(0x0404000000000404), CONST64(0x0404000100000404), CONST64(0x0404000004000404), CONST64(0x0404000104000404), + CONST64(0x0404000000040404), CONST64(0x0404000100040404), CONST64(0x0404000004040404), CONST64(0x0404000104040404), + CONST64(0x0000040000000000), CONST64(0x0000040100000000), CONST64(0x0000040004000000), CONST64(0x0000040104000000), + CONST64(0x0000040000040000), CONST64(0x0000040100040000), CONST64(0x0000040004040000), CONST64(0x0000040104040000), + CONST64(0x0000040000000400), CONST64(0x0000040100000400), CONST64(0x0000040004000400), CONST64(0x0000040104000400), + CONST64(0x0000040000040400), CONST64(0x0000040100040400), CONST64(0x0000040004040400), CONST64(0x0000040104040400), + CONST64(0x0000040000000004), CONST64(0x0000040100000004), CONST64(0x0000040004000004), CONST64(0x0000040104000004), + CONST64(0x0000040000040004), CONST64(0x0000040100040004), CONST64(0x0000040004040004), CONST64(0x0000040104040004), + CONST64(0x0000040000000404), CONST64(0x0000040100000404), CONST64(0x0000040004000404), CONST64(0x0000040104000404), + CONST64(0x0000040000040404), CONST64(0x0000040100040404), CONST64(0x0000040004040404), CONST64(0x0000040104040404), + CONST64(0x0400040000000000), CONST64(0x0400040100000000), CONST64(0x0400040004000000), CONST64(0x0400040104000000), + CONST64(0x0400040000040000), CONST64(0x0400040100040000), CONST64(0x0400040004040000), CONST64(0x0400040104040000), + CONST64(0x0400040000000400), CONST64(0x0400040100000400), CONST64(0x0400040004000400), CONST64(0x0400040104000400), + CONST64(0x0400040000040400), CONST64(0x0400040100040400), CONST64(0x0400040004040400), CONST64(0x0400040104040400), + CONST64(0x0400040000000004), CONST64(0x0400040100000004), CONST64(0x0400040004000004), CONST64(0x0400040104000004), + CONST64(0x0400040000040004), CONST64(0x0400040100040004), CONST64(0x0400040004040004), CONST64(0x0400040104040004), + CONST64(0x0400040000000404), CONST64(0x0400040100000404), CONST64(0x0400040004000404), CONST64(0x0400040104000404), + CONST64(0x0400040000040404), CONST64(0x0400040100040404), CONST64(0x0400040004040404), CONST64(0x0400040104040404), + CONST64(0x0004040000000000), CONST64(0x0004040100000000), CONST64(0x0004040004000000), CONST64(0x0004040104000000), + CONST64(0x0004040000040000), CONST64(0x0004040100040000), CONST64(0x0004040004040000), CONST64(0x0004040104040000), + CONST64(0x0004040000000400), CONST64(0x0004040100000400), CONST64(0x0004040004000400), CONST64(0x0004040104000400), + CONST64(0x0004040000040400), CONST64(0x0004040100040400), CONST64(0x0004040004040400), CONST64(0x0004040104040400), + CONST64(0x0004040000000004), CONST64(0x0004040100000004), CONST64(0x0004040004000004), CONST64(0x0004040104000004), + CONST64(0x0004040000040004), CONST64(0x0004040100040004), CONST64(0x0004040004040004), CONST64(0x0004040104040004), + CONST64(0x0004040000000404), CONST64(0x0004040100000404), CONST64(0x0004040004000404), CONST64(0x0004040104000404), + CONST64(0x0004040000040404), CONST64(0x0004040100040404), CONST64(0x0004040004040404), CONST64(0x0004040104040404), + CONST64(0x0404040000000000), CONST64(0x0404040100000000), CONST64(0x0404040004000000), CONST64(0x0404040104000000), + CONST64(0x0404040000040000), CONST64(0x0404040100040000), CONST64(0x0404040004040000), CONST64(0x0404040104040000), + CONST64(0x0404040000000400), CONST64(0x0404040100000400), CONST64(0x0404040004000400), CONST64(0x0404040104000400), + CONST64(0x0404040000040400), CONST64(0x0404040100040400), CONST64(0x0404040004040400), CONST64(0x0404040104040400), + CONST64(0x0404040000000004), CONST64(0x0404040100000004), CONST64(0x0404040004000004), CONST64(0x0404040104000004), + CONST64(0x0404040000040004), CONST64(0x0404040100040004), CONST64(0x0404040004040004), CONST64(0x0404040104040004), + CONST64(0x0404040000000404), CONST64(0x0404040100000404), CONST64(0x0404040004000404), CONST64(0x0404040104000404), + CONST64(0x0404040000040404), CONST64(0x0404040100040404), CONST64(0x0404040004040404), CONST64(0x0404040104040404) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000000400000000), CONST64(0x0000000010000000), CONST64(0x0000000410000000), + CONST64(0x0000000000100000), CONST64(0x0000000400100000), CONST64(0x0000000010100000), CONST64(0x0000000410100000), + CONST64(0x0000000000001000), CONST64(0x0000000400001000), CONST64(0x0000000010001000), CONST64(0x0000000410001000), + CONST64(0x0000000000101000), CONST64(0x0000000400101000), CONST64(0x0000000010101000), CONST64(0x0000000410101000), + CONST64(0x0000000000000010), CONST64(0x0000000400000010), CONST64(0x0000000010000010), CONST64(0x0000000410000010), + CONST64(0x0000000000100010), CONST64(0x0000000400100010), CONST64(0x0000000010100010), CONST64(0x0000000410100010), + CONST64(0x0000000000001010), CONST64(0x0000000400001010), CONST64(0x0000000010001010), CONST64(0x0000000410001010), + CONST64(0x0000000000101010), CONST64(0x0000000400101010), CONST64(0x0000000010101010), CONST64(0x0000000410101010), + CONST64(0x1000000000000000), CONST64(0x1000000400000000), CONST64(0x1000000010000000), CONST64(0x1000000410000000), + CONST64(0x1000000000100000), CONST64(0x1000000400100000), CONST64(0x1000000010100000), CONST64(0x1000000410100000), + CONST64(0x1000000000001000), CONST64(0x1000000400001000), CONST64(0x1000000010001000), CONST64(0x1000000410001000), + CONST64(0x1000000000101000), CONST64(0x1000000400101000), CONST64(0x1000000010101000), CONST64(0x1000000410101000), + CONST64(0x1000000000000010), CONST64(0x1000000400000010), CONST64(0x1000000010000010), CONST64(0x1000000410000010), + CONST64(0x1000000000100010), CONST64(0x1000000400100010), CONST64(0x1000000010100010), CONST64(0x1000000410100010), + CONST64(0x1000000000001010), CONST64(0x1000000400001010), CONST64(0x1000000010001010), CONST64(0x1000000410001010), + CONST64(0x1000000000101010), CONST64(0x1000000400101010), CONST64(0x1000000010101010), CONST64(0x1000000410101010), + CONST64(0x0010000000000000), CONST64(0x0010000400000000), CONST64(0x0010000010000000), CONST64(0x0010000410000000), + CONST64(0x0010000000100000), CONST64(0x0010000400100000), CONST64(0x0010000010100000), CONST64(0x0010000410100000), + CONST64(0x0010000000001000), CONST64(0x0010000400001000), CONST64(0x0010000010001000), CONST64(0x0010000410001000), + CONST64(0x0010000000101000), CONST64(0x0010000400101000), CONST64(0x0010000010101000), CONST64(0x0010000410101000), + CONST64(0x0010000000000010), CONST64(0x0010000400000010), CONST64(0x0010000010000010), CONST64(0x0010000410000010), + CONST64(0x0010000000100010), CONST64(0x0010000400100010), CONST64(0x0010000010100010), CONST64(0x0010000410100010), + CONST64(0x0010000000001010), CONST64(0x0010000400001010), CONST64(0x0010000010001010), CONST64(0x0010000410001010), + CONST64(0x0010000000101010), CONST64(0x0010000400101010), CONST64(0x0010000010101010), CONST64(0x0010000410101010), + CONST64(0x1010000000000000), CONST64(0x1010000400000000), CONST64(0x1010000010000000), CONST64(0x1010000410000000), + CONST64(0x1010000000100000), CONST64(0x1010000400100000), CONST64(0x1010000010100000), CONST64(0x1010000410100000), + CONST64(0x1010000000001000), CONST64(0x1010000400001000), CONST64(0x1010000010001000), CONST64(0x1010000410001000), + CONST64(0x1010000000101000), CONST64(0x1010000400101000), CONST64(0x1010000010101000), CONST64(0x1010000410101000), + CONST64(0x1010000000000010), CONST64(0x1010000400000010), CONST64(0x1010000010000010), CONST64(0x1010000410000010), + CONST64(0x1010000000100010), CONST64(0x1010000400100010), CONST64(0x1010000010100010), CONST64(0x1010000410100010), + CONST64(0x1010000000001010), CONST64(0x1010000400001010), CONST64(0x1010000010001010), CONST64(0x1010000410001010), + CONST64(0x1010000000101010), CONST64(0x1010000400101010), CONST64(0x1010000010101010), CONST64(0x1010000410101010), + CONST64(0x0000100000000000), CONST64(0x0000100400000000), CONST64(0x0000100010000000), CONST64(0x0000100410000000), + CONST64(0x0000100000100000), CONST64(0x0000100400100000), CONST64(0x0000100010100000), CONST64(0x0000100410100000), + CONST64(0x0000100000001000), CONST64(0x0000100400001000), CONST64(0x0000100010001000), CONST64(0x0000100410001000), + CONST64(0x0000100000101000), CONST64(0x0000100400101000), CONST64(0x0000100010101000), CONST64(0x0000100410101000), + CONST64(0x0000100000000010), CONST64(0x0000100400000010), CONST64(0x0000100010000010), CONST64(0x0000100410000010), + CONST64(0x0000100000100010), CONST64(0x0000100400100010), CONST64(0x0000100010100010), CONST64(0x0000100410100010), + CONST64(0x0000100000001010), CONST64(0x0000100400001010), CONST64(0x0000100010001010), CONST64(0x0000100410001010), + CONST64(0x0000100000101010), CONST64(0x0000100400101010), CONST64(0x0000100010101010), CONST64(0x0000100410101010), + CONST64(0x1000100000000000), CONST64(0x1000100400000000), CONST64(0x1000100010000000), CONST64(0x1000100410000000), + CONST64(0x1000100000100000), CONST64(0x1000100400100000), CONST64(0x1000100010100000), CONST64(0x1000100410100000), + CONST64(0x1000100000001000), CONST64(0x1000100400001000), CONST64(0x1000100010001000), CONST64(0x1000100410001000), + CONST64(0x1000100000101000), CONST64(0x1000100400101000), CONST64(0x1000100010101000), CONST64(0x1000100410101000), + CONST64(0x1000100000000010), CONST64(0x1000100400000010), CONST64(0x1000100010000010), CONST64(0x1000100410000010), + CONST64(0x1000100000100010), CONST64(0x1000100400100010), CONST64(0x1000100010100010), CONST64(0x1000100410100010), + CONST64(0x1000100000001010), CONST64(0x1000100400001010), CONST64(0x1000100010001010), CONST64(0x1000100410001010), + CONST64(0x1000100000101010), CONST64(0x1000100400101010), CONST64(0x1000100010101010), CONST64(0x1000100410101010), + CONST64(0x0010100000000000), CONST64(0x0010100400000000), CONST64(0x0010100010000000), CONST64(0x0010100410000000), + CONST64(0x0010100000100000), CONST64(0x0010100400100000), CONST64(0x0010100010100000), CONST64(0x0010100410100000), + CONST64(0x0010100000001000), CONST64(0x0010100400001000), CONST64(0x0010100010001000), CONST64(0x0010100410001000), + CONST64(0x0010100000101000), CONST64(0x0010100400101000), CONST64(0x0010100010101000), CONST64(0x0010100410101000), + CONST64(0x0010100000000010), CONST64(0x0010100400000010), CONST64(0x0010100010000010), CONST64(0x0010100410000010), + CONST64(0x0010100000100010), CONST64(0x0010100400100010), CONST64(0x0010100010100010), CONST64(0x0010100410100010), + CONST64(0x0010100000001010), CONST64(0x0010100400001010), CONST64(0x0010100010001010), CONST64(0x0010100410001010), + CONST64(0x0010100000101010), CONST64(0x0010100400101010), CONST64(0x0010100010101010), CONST64(0x0010100410101010), + CONST64(0x1010100000000000), CONST64(0x1010100400000000), CONST64(0x1010100010000000), CONST64(0x1010100410000000), + CONST64(0x1010100000100000), CONST64(0x1010100400100000), CONST64(0x1010100010100000), CONST64(0x1010100410100000), + CONST64(0x1010100000001000), CONST64(0x1010100400001000), CONST64(0x1010100010001000), CONST64(0x1010100410001000), + CONST64(0x1010100000101000), CONST64(0x1010100400101000), CONST64(0x1010100010101000), CONST64(0x1010100410101000), + CONST64(0x1010100000000010), CONST64(0x1010100400000010), CONST64(0x1010100010000010), CONST64(0x1010100410000010), + CONST64(0x1010100000100010), CONST64(0x1010100400100010), CONST64(0x1010100010100010), CONST64(0x1010100410100010), + CONST64(0x1010100000001010), CONST64(0x1010100400001010), CONST64(0x1010100010001010), CONST64(0x1010100410001010), + CONST64(0x1010100000101010), CONST64(0x1010100400101010), CONST64(0x1010100010101010), CONST64(0x1010100410101010) + }, +{ CONST64(0x0000000000000000), CONST64(0x0000001000000000), CONST64(0x0000000040000000), CONST64(0x0000001040000000), + CONST64(0x0000000000400000), CONST64(0x0000001000400000), CONST64(0x0000000040400000), CONST64(0x0000001040400000), + CONST64(0x0000000000004000), CONST64(0x0000001000004000), CONST64(0x0000000040004000), CONST64(0x0000001040004000), + CONST64(0x0000000000404000), CONST64(0x0000001000404000), CONST64(0x0000000040404000), CONST64(0x0000001040404000), + CONST64(0x0000000000000040), CONST64(0x0000001000000040), CONST64(0x0000000040000040), CONST64(0x0000001040000040), + CONST64(0x0000000000400040), CONST64(0x0000001000400040), CONST64(0x0000000040400040), CONST64(0x0000001040400040), + CONST64(0x0000000000004040), CONST64(0x0000001000004040), CONST64(0x0000000040004040), CONST64(0x0000001040004040), + CONST64(0x0000000000404040), CONST64(0x0000001000404040), CONST64(0x0000000040404040), CONST64(0x0000001040404040), + CONST64(0x4000000000000000), CONST64(0x4000001000000000), CONST64(0x4000000040000000), CONST64(0x4000001040000000), + CONST64(0x4000000000400000), CONST64(0x4000001000400000), CONST64(0x4000000040400000), CONST64(0x4000001040400000), + CONST64(0x4000000000004000), CONST64(0x4000001000004000), CONST64(0x4000000040004000), CONST64(0x4000001040004000), + CONST64(0x4000000000404000), CONST64(0x4000001000404000), CONST64(0x4000000040404000), CONST64(0x4000001040404000), + CONST64(0x4000000000000040), CONST64(0x4000001000000040), CONST64(0x4000000040000040), CONST64(0x4000001040000040), + CONST64(0x4000000000400040), CONST64(0x4000001000400040), CONST64(0x4000000040400040), CONST64(0x4000001040400040), + CONST64(0x4000000000004040), CONST64(0x4000001000004040), CONST64(0x4000000040004040), CONST64(0x4000001040004040), + CONST64(0x4000000000404040), CONST64(0x4000001000404040), CONST64(0x4000000040404040), CONST64(0x4000001040404040), + CONST64(0x0040000000000000), CONST64(0x0040001000000000), CONST64(0x0040000040000000), CONST64(0x0040001040000000), + CONST64(0x0040000000400000), CONST64(0x0040001000400000), CONST64(0x0040000040400000), CONST64(0x0040001040400000), + CONST64(0x0040000000004000), CONST64(0x0040001000004000), CONST64(0x0040000040004000), CONST64(0x0040001040004000), + CONST64(0x0040000000404000), CONST64(0x0040001000404000), CONST64(0x0040000040404000), CONST64(0x0040001040404000), + CONST64(0x0040000000000040), CONST64(0x0040001000000040), CONST64(0x0040000040000040), CONST64(0x0040001040000040), + CONST64(0x0040000000400040), CONST64(0x0040001000400040), CONST64(0x0040000040400040), CONST64(0x0040001040400040), + CONST64(0x0040000000004040), CONST64(0x0040001000004040), CONST64(0x0040000040004040), CONST64(0x0040001040004040), + CONST64(0x0040000000404040), CONST64(0x0040001000404040), CONST64(0x0040000040404040), CONST64(0x0040001040404040), + CONST64(0x4040000000000000), CONST64(0x4040001000000000), CONST64(0x4040000040000000), CONST64(0x4040001040000000), + CONST64(0x4040000000400000), CONST64(0x4040001000400000), CONST64(0x4040000040400000), CONST64(0x4040001040400000), + CONST64(0x4040000000004000), CONST64(0x4040001000004000), CONST64(0x4040000040004000), CONST64(0x4040001040004000), + CONST64(0x4040000000404000), CONST64(0x4040001000404000), CONST64(0x4040000040404000), CONST64(0x4040001040404000), + CONST64(0x4040000000000040), CONST64(0x4040001000000040), CONST64(0x4040000040000040), CONST64(0x4040001040000040), + CONST64(0x4040000000400040), CONST64(0x4040001000400040), CONST64(0x4040000040400040), CONST64(0x4040001040400040), + CONST64(0x4040000000004040), CONST64(0x4040001000004040), CONST64(0x4040000040004040), CONST64(0x4040001040004040), + CONST64(0x4040000000404040), CONST64(0x4040001000404040), CONST64(0x4040000040404040), CONST64(0x4040001040404040), + CONST64(0x0000400000000000), CONST64(0x0000401000000000), CONST64(0x0000400040000000), CONST64(0x0000401040000000), + CONST64(0x0000400000400000), CONST64(0x0000401000400000), CONST64(0x0000400040400000), CONST64(0x0000401040400000), + CONST64(0x0000400000004000), CONST64(0x0000401000004000), CONST64(0x0000400040004000), CONST64(0x0000401040004000), + CONST64(0x0000400000404000), CONST64(0x0000401000404000), CONST64(0x0000400040404000), CONST64(0x0000401040404000), + CONST64(0x0000400000000040), CONST64(0x0000401000000040), CONST64(0x0000400040000040), CONST64(0x0000401040000040), + CONST64(0x0000400000400040), CONST64(0x0000401000400040), CONST64(0x0000400040400040), CONST64(0x0000401040400040), + CONST64(0x0000400000004040), CONST64(0x0000401000004040), CONST64(0x0000400040004040), CONST64(0x0000401040004040), + CONST64(0x0000400000404040), CONST64(0x0000401000404040), CONST64(0x0000400040404040), CONST64(0x0000401040404040), + CONST64(0x4000400000000000), CONST64(0x4000401000000000), CONST64(0x4000400040000000), CONST64(0x4000401040000000), + CONST64(0x4000400000400000), CONST64(0x4000401000400000), CONST64(0x4000400040400000), CONST64(0x4000401040400000), + CONST64(0x4000400000004000), CONST64(0x4000401000004000), CONST64(0x4000400040004000), CONST64(0x4000401040004000), + CONST64(0x4000400000404000), CONST64(0x4000401000404000), CONST64(0x4000400040404000), CONST64(0x4000401040404000), + CONST64(0x4000400000000040), CONST64(0x4000401000000040), CONST64(0x4000400040000040), CONST64(0x4000401040000040), + CONST64(0x4000400000400040), CONST64(0x4000401000400040), CONST64(0x4000400040400040), CONST64(0x4000401040400040), + CONST64(0x4000400000004040), CONST64(0x4000401000004040), CONST64(0x4000400040004040), CONST64(0x4000401040004040), + CONST64(0x4000400000404040), CONST64(0x4000401000404040), CONST64(0x4000400040404040), CONST64(0x4000401040404040), + CONST64(0x0040400000000000), CONST64(0x0040401000000000), CONST64(0x0040400040000000), CONST64(0x0040401040000000), + CONST64(0x0040400000400000), CONST64(0x0040401000400000), CONST64(0x0040400040400000), CONST64(0x0040401040400000), + CONST64(0x0040400000004000), CONST64(0x0040401000004000), CONST64(0x0040400040004000), CONST64(0x0040401040004000), + CONST64(0x0040400000404000), CONST64(0x0040401000404000), CONST64(0x0040400040404000), CONST64(0x0040401040404000), + CONST64(0x0040400000000040), CONST64(0x0040401000000040), CONST64(0x0040400040000040), CONST64(0x0040401040000040), + CONST64(0x0040400000400040), CONST64(0x0040401000400040), CONST64(0x0040400040400040), CONST64(0x0040401040400040), + CONST64(0x0040400000004040), CONST64(0x0040401000004040), CONST64(0x0040400040004040), CONST64(0x0040401040004040), + CONST64(0x0040400000404040), CONST64(0x0040401000404040), CONST64(0x0040400040404040), CONST64(0x0040401040404040), + CONST64(0x4040400000000000), CONST64(0x4040401000000000), CONST64(0x4040400040000000), CONST64(0x4040401040000000), + CONST64(0x4040400000400000), CONST64(0x4040401000400000), CONST64(0x4040400040400000), CONST64(0x4040401040400000), + CONST64(0x4040400000004000), CONST64(0x4040401000004000), CONST64(0x4040400040004000), CONST64(0x4040401040004000), + CONST64(0x4040400000404000), CONST64(0x4040401000404000), CONST64(0x4040400040404000), CONST64(0x4040401040404000), + CONST64(0x4040400000000040), CONST64(0x4040401000000040), CONST64(0x4040400040000040), CONST64(0x4040401040000040), + CONST64(0x4040400000400040), CONST64(0x4040401000400040), CONST64(0x4040400040400040), CONST64(0x4040401040400040), + CONST64(0x4040400000004040), CONST64(0x4040401000004040), CONST64(0x4040400040004040), CONST64(0x4040401040004040), + CONST64(0x4040400000404040), CONST64(0x4040401000404040), CONST64(0x4040400040404040), CONST64(0x4040401040404040) + }}; + +#endif + + +static void cookey(const ulong32 *raw1, ulong32 *keyout); + +#ifdef LTC_CLEAN_STACK +static void s_deskey(const unsigned char *key, short edf, ulong32 *keyout) +#else +static void deskey(const unsigned char *key, short edf, ulong32 *keyout) +#endif +{ + ulong32 i, j, l, m, n, kn[32]; + unsigned char pc1m[56], pcr[56]; + + for (j=0; j < 56; j++) { + l = (ulong32)pc1[j]; + m = l & 7; + pc1m[j] = (unsigned char)((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); + } + + for (i=0; i < 16; i++) { + if (edf == DE1) { + m = (15 - i) << 1; + } else { + m = i << 1; + } + n = m + 1; + kn[m] = kn[n] = 0L; + for (j=0; j < 28; j++) { + l = j + (ulong32)totrot[i]; + if (l < 28) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (/*j = 28*/; j < 56; j++) { + l = j + (ulong32)totrot[i]; + if (l < 56) { + pcr[j] = pc1m[l]; + } else { + pcr[j] = pc1m[l - 28]; + } + } + for (j=0; j < 24; j++) { + if ((int)pcr[(int)pc2[j]] != 0) { + kn[m] |= bigbyte[j]; + } + if ((int)pcr[(int)pc2[j+24]] != 0) { + kn[n] |= bigbyte[j]; + } + } + } + + cookey(kn, keyout); +} + +#ifdef LTC_CLEAN_STACK +static void deskey(const unsigned char *key, short edf, ulong32 *keyout) +{ + s_deskey(key, edf, keyout); + burn_stack(sizeof(int)*5 + sizeof(ulong32)*32 + sizeof(unsigned char)*112); +} +#endif + +#ifdef LTC_CLEAN_STACK +static void s_cookey(const ulong32 *raw1, ulong32 *keyout) +#else +static void cookey(const ulong32 *raw1, ulong32 *keyout) +#endif +{ + ulong32 *cook; + const ulong32 *raw0; + ulong32 dough[32]; + int i; + + cook = dough; + for(i=0; i < 16; i++, raw1++) + { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + + XMEMCPY(keyout, dough, sizeof(dough)); +} + +#ifdef LTC_CLEAN_STACK +static void cookey(const ulong32 *raw1, ulong32 *keyout) +{ + s_cookey(raw1, keyout); + burn_stack(sizeof(ulong32 *) * 2 + sizeof(ulong32)*32 + sizeof(int)); +} +#endif + +#ifndef LTC_CLEAN_STACK +static void desfunc(ulong32 *block, const ulong32 *keys) +#else +static void s_desfunc(ulong32 *block, const ulong32 *keys) +#endif +{ + ulong32 work, right, leftt; + int cur_round; + + leftt = block[0]; + right = block[1]; + +#ifdef LTC_SMALL_CODE + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + + right = ROLc(right, 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + + leftt ^= work; + right ^= work; + leftt = ROLc(leftt, 1); +#else + { + ulong64 tmp; + tmp = des_ip[0][LTC_BYTE(leftt, 0)] ^ + des_ip[1][LTC_BYTE(leftt, 1)] ^ + des_ip[2][LTC_BYTE(leftt, 2)] ^ + des_ip[3][LTC_BYTE(leftt, 3)] ^ + des_ip[4][LTC_BYTE(right, 0)] ^ + des_ip[5][LTC_BYTE(right, 1)] ^ + des_ip[6][LTC_BYTE(right, 2)] ^ + des_ip[7][LTC_BYTE(right, 3)]; + leftt = (ulong32)(tmp >> 32); + right = (ulong32)(tmp & 0xFFFFFFFFUL); + } +#endif + + for (cur_round = 0; cur_round < 8; cur_round++) { + work = RORc(right, 4) ^ *keys++; + leftt ^= SP7[work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + leftt ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + + work = RORc(leftt, 4) ^ *keys++; + right ^= SP7[ work & 0x3fL] + ^ SP5[(work >> 8) & 0x3fL] + ^ SP3[(work >> 16) & 0x3fL] + ^ SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + right ^= SP8[ work & 0x3fL] + ^ SP6[(work >> 8) & 0x3fL] + ^ SP4[(work >> 16) & 0x3fL] + ^ SP2[(work >> 24) & 0x3fL]; + } + +#ifdef LTC_SMALL_CODE + right = RORc(right, 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = RORc(leftt, 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + /* -- */ + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); +#else + { + ulong64 tmp; + tmp = des_fp[0][LTC_BYTE(leftt, 0)] ^ + des_fp[1][LTC_BYTE(leftt, 1)] ^ + des_fp[2][LTC_BYTE(leftt, 2)] ^ + des_fp[3][LTC_BYTE(leftt, 3)] ^ + des_fp[4][LTC_BYTE(right, 0)] ^ + des_fp[5][LTC_BYTE(right, 1)] ^ + des_fp[6][LTC_BYTE(right, 2)] ^ + des_fp[7][LTC_BYTE(right, 3)]; + leftt = (ulong32)(tmp >> 32); + right = (ulong32)(tmp & 0xFFFFFFFFUL); + } +#endif + + block[0] = right; + block[1] = leftt; +} + +#ifdef LTC_CLEAN_STACK +static void desfunc(ulong32 *block, const ulong32 *keys) +{ + s_desfunc(block, keys); + burn_stack(sizeof(ulong32) * 4 + sizeof(int)); +} +#endif + + /** + Initialize the LTC_DES block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 8) { + return CRYPT_INVALID_KEYSIZE; + } + + deskey(key, EN0, skey->des.ek); + deskey(key, DE1, skey->des.dk); + + return CRYPT_OK; +} + + /** + Initialize the 3LTC_DES-EDE block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if(num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 24 && keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + deskey(key, EN0, skey->des3.ek[0]); + deskey(key+8, DE1, skey->des3.ek[1]); + if (keylen == 24) { + deskey(key+16, EN0, skey->des3.ek[2]); + } else { + /* two-key 3DES: K3=K1 */ + deskey(key, EN0, skey->des3.ek[2]); + } + + deskey(key, DE1, skey->des3.dk[2]); + deskey(key+8, EN0, skey->des3.dk[1]); + if (keylen == 24) { + deskey(key+16, DE1, skey->des3.dk[0]); + } else { + /* two-key 3DES: K3=K1 */ + deskey(key, DE1, skey->des3.dk[0]); + } + + return CRYPT_OK; +} + +/** + Encrypts a block of text with LTC_DES + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 work[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], pt+0); + LOAD32H(work[1], pt+4); + desfunc(work, skey->des.ek); + STORE32H(work[0],ct+0); + STORE32H(work[1],ct+4); + return CRYPT_OK; +} + +/** + Decrypts a block of text with LTC_DES + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 work[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], ct+0); + LOAD32H(work[1], ct+4); + desfunc(work, skey->des.dk); + STORE32H(work[0],pt+0); + STORE32H(work[1],pt+4); + return CRYPT_OK; +} + +/** + Encrypts a block of text with 3LTC_DES-EDE + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 work[2]; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], pt+0); + LOAD32H(work[1], pt+4); + desfunc(work, skey->des3.ek[0]); + desfunc(work, skey->des3.ek[1]); + desfunc(work, skey->des3.ek[2]); + STORE32H(work[0],ct+0); + STORE32H(work[1],ct+4); + return CRYPT_OK; +} + +/** + Decrypts a block of text with 3LTC_DES-EDE + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 work[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(work[0], ct+0); + LOAD32H(work[1], ct+4); + desfunc(work, skey->des3.dk[0]); + desfunc(work, skey->des3.dk[1]); + desfunc(work, skey->des3.dk[2]); + STORE32H(work[0],pt+0); + STORE32H(work[1],pt+4); + return CRYPT_OK; +} + +/** + Performs a self-test of the LTC_DES block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int des_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct des_test_case { + unsigned char key[8], txt[8], out[8]; + } cases[] = { + { { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 }, + { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA }, + { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 }, + { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF }, + { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F }, + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A }, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + + { { 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x95, 0xA8, 0xD7, 0x28, 0x13, 0xDA, 0xA9, 0x4D } }, + { { 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x0E, 0xEC, 0x14, 0x87, 0xDD, 0x8C, 0x26, 0xD5 } }, + { { 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0xD1, 0x6F, 0xFB, 0x79, 0xC4, 0x59, 0x26 } }, + { { 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD3, 0x74, 0x62, 0x94, 0xCA, 0x6A, 0x6C, 0xF3 } }, + { { 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x80, 0x9F, 0x5F, 0x87, 0x3C, 0x1F, 0xD7, 0x61 } }, + { { 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC0, 0x2F, 0xAF, 0xFE, 0xC9, 0x89, 0xD1, 0xFC } }, + { { 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x46, 0x15, 0xAA, 0x1D, 0x33, 0xE7, 0x2F, 0x10 } }, + { { 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x20, 0x55, 0x12, 0x33, 0x50, 0xC0, 0x08, 0x58 } }, + { { 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDF, 0x3B, 0x99, 0xD6, 0x57, 0x73, 0x97, 0xC8 } }, + { { 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x31, 0xFE, 0x17, 0x36, 0x9B, 0x52, 0x88, 0xC9 } }, + { { 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDF, 0xDD, 0x3C, 0xC6, 0x4D, 0xAE, 0x16, 0x42 } }, + { { 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0x8C, 0x83, 0xCE, 0x2B, 0x39, 0x9D, 0x94 } }, + { { 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x50, 0xF6, 0x36, 0x32, 0x4A, 0x9B, 0x7F, 0x80 } }, + { { 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x46, 0x8E, 0xE3, 0xBC, 0x18, 0xF0, 0x6D } }, + { { 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA2, 0xDC, 0x9E, 0x92, 0xFD, 0x3C, 0xDE, 0x92 } }, + { { 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCA, 0xC0, 0x9F, 0x79, 0x7D, 0x03, 0x12, 0x87 } }, + { { 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x90, 0xBA, 0x68, 0x0B, 0x22, 0xAE, 0xB5, 0x25 } }, + { { 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xCE, 0x7A, 0x24, 0xF3, 0x50, 0xE2, 0x80, 0xB6 } }, + { { 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x88, 0x2B, 0xFF, 0x0A, 0xA0, 0x1A, 0x0B, 0x87 } }, + { { 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x25, 0x61, 0x02, 0x88, 0x92, 0x45, 0x11, 0xC2 } }, + { { 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC7, 0x15, 0x16, 0xC2, 0x9C, 0x75, 0xD1, 0x70 } }, + { { 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x51, 0x99, 0xC2, 0x9A, 0x52, 0xC9, 0xF0, 0x59 } }, + { { 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xC2, 0x2F, 0x0A, 0x29, 0x4A, 0x71, 0xF2, 0x9F } }, + { { 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xEE, 0x37, 0x14, 0x83, 0x71, 0x4C, 0x02, 0xEA } }, + { { 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA8, 0x1F, 0xBD, 0x44, 0x8F, 0x9E, 0x52, 0x2F } }, + { { 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4F, 0x64, 0x4C, 0x92, 0xE1, 0x92, 0xDF, 0xED } }, + { { 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1A, 0xFA, 0x9A, 0x66, 0xA6, 0xDF, 0x92, 0xAE } }, + { { 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB3, 0xC1, 0xCC, 0x71, 0x5C, 0xB8, 0x79, 0xD8 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x19, 0xD0, 0x32, 0xE6, 0x4A, 0xB0, 0xBD, 0x8B } }, + { { 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x3C, 0xFA, 0xA7, 0xA7, 0xDC, 0x87, 0x20, 0xDC } }, + { { 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB7, 0x26, 0x5F, 0x7F, 0x44, 0x7A, 0xC6, 0xF3 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9D, 0xB7, 0x3B, 0x3C, 0x0D, 0x16, 0x3F, 0x54 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x81, 0x81, 0xB6, 0x5B, 0xAB, 0xF4, 0xA9, 0x75 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x93, 0xC9, 0xB6, 0x40, 0x42, 0xEA, 0xA2, 0x40 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x55, 0x70, 0x53, 0x08, 0x29, 0x70, 0x55, 0x92 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x38, 0x80, 0x9E, 0x87, 0x87, 0x87, 0xA0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x41, 0xB9, 0xA7, 0x9A, 0xF7, 0x9A, 0xC2, 0x08 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7A, 0x9B, 0xE4, 0x2F, 0x20, 0x09, 0xA8, 0x92 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x29, 0x03, 0x8D, 0x56, 0xBA, 0x6D, 0x27, 0x45 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x54, 0x95, 0xC6, 0xAB, 0xF1, 0xE5, 0xDF, 0x51 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0x13, 0xDB, 0xD5, 0x61, 0x48, 0x89, 0x33 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x4D, 0x1F, 0xFA, 0x89, 0x04, 0xE3, 0x89 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD1, 0x39, 0x97, 0x12, 0xF9, 0x9B, 0xF0, 0x2E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x14, 0xC1, 0xD7, 0xC1, 0xCF, 0xFE, 0xC7, 0x9E } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1D, 0xE5, 0x27, 0x9D, 0xAE, 0x3B, 0xED, 0x6F } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xE9, 0x41, 0xA3, 0x3F, 0x85, 0x50, 0x13, 0x03 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xDA, 0x99, 0xDB, 0xBC, 0x9A, 0x03, 0xF3, 0x79 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB7, 0xFC, 0x92, 0xF9, 0x1D, 0x8E, 0x92, 0xE9 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xAE, 0x8E, 0x5C, 0xAA, 0x3C, 0xA0, 0x4E, 0x85 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x80 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9C, 0xC6, 0x2D, 0xF4, 0x3B, 0x6E, 0xED, 0x74 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x40 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xD8, 0x63, 0xDB, 0xB5, 0xC5, 0x9A, 0x91, 0xA0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x20 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xA1, 0xAB, 0x21, 0x90, 0x54, 0x5B, 0x91, 0xD7 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x08, 0x75, 0x04, 0x1E, 0x64, 0xC5, 0x70, 0xF7 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x5A, 0x59, 0x45, 0x28, 0xBE, 0xBE, 0xF1, 0xCC } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFC, 0xDB, 0x32, 0x91, 0xDE, 0x21, 0xF0, 0xC0 } }, + { { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x86, 0x9E, 0xFD, 0x7F, 0x9F, 0x26, 0x5A, 0x09 } }, + + /*** more test cases you could add if you are not convinced (the above test cases aren't really too good): + + key plaintext ciphertext + 0000000000000000 0000000000000000 8CA64DE9C1B123A7 + FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58 + 3000000000000000 1000000000000001 958E6E627A05557B + 1111111111111111 1111111111111111 F40379AB9E0EC533 + 0123456789ABCDEF 1111111111111111 17668DFC7292532D + 1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD + 0000000000000000 0000000000000000 8CA64DE9C1B123A7 + FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4 + 7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B + 0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 + 07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A + 3849674C2602319E 51454B582DDF440A 7178876E01F19B2A + 04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 + 0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B + 0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 + 43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A + 07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F + 04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 + 37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 + 1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A + 584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 + 025816164629B007 480D39006EE762F2 A1F9915541020B56 + 49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 + 4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC + 49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A + 018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 + 1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 + 0101010101010101 0123456789ABCDEF 617B3A0CE8F07100 + 1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606 + E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7 + 0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451 + FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE + 0123456789ABCDEF 0000000000000000 D5D44FF720683D0D + FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2 + + http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt + ***/ + }; + unsigned char key[8], pt[8], ct[8], tmp[8]; + symmetric_key skey; + int i, err; + + for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) + { + if ((err = des_setup(cases[i].key, 8, 0, &skey)) != CRYPT_OK) { + return err; + } + + des_ecb_encrypt(cases[i].txt, ct, &skey); + + if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "DES Encrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + des_ecb_decrypt(ct, pt, &skey); + + if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "DES Decrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ + + for (i = 0; i < 8; i++) key[i] = i; + + if ((err = des_setup(key, 8, 0, &skey)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; + for (i = 0; i < 1000; i++) des_ecb_encrypt(tmp, tmp, &skey); + for (i = 0; i < 1000; i++) des_ecb_decrypt(tmp, tmp, &skey); + + if (compare_testvector(tmp, 8, pt, 8, "DES", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +int des3_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct des3_test_case { + unsigned char key[16], txt[8], out[8]; + } cases[] = { + /* + https://www.cosic.esat.kuleuven.be/nessie/testvectors/bc/des/Triple-Des-2-Key-128-64.unverified.test-vectors + */ + { { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xFA, 0xFD, 0x50, 0x84, 0x37, 0x4F, 0xCE, 0x34 } }, + { { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x60, 0xCC, 0x37, 0xB7, 0xB5, 0x37, 0xA1, 0xDC } }, + { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xBE, 0x3E, 0x73, 0x04, 0xFE, 0x92, 0xC2, 0xBC } }, + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00 }, + { 0xE5, 0xA9, 0xE3, 0x80, 0x03, 0xA5, 0xA0, 0xFD }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, + { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0xE4, 0xFC, 0x19, 0xD6, 0x94, 0x63, 0xB7, 0x83 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 } }, + }; + unsigned char key[24], pt[8], ct[8], tmp[8]; + symmetric_key skey; + int i, err; + + if ((err = des_test()) != CRYPT_OK) { + return err; + } + + for (i = 0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++) + { + if ((err = des3_setup(cases[i].key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + + des3_ecb_encrypt(cases[i].txt, ct, &skey); + + if (compare_testvector(ct, sizeof(ct), cases[i].out, 8, "3DES Encrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + des3_ecb_decrypt(ct, pt, &skey); + + if (compare_testvector(pt, sizeof(pt), cases[i].txt, 8, "3DES Decrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* See if we can encrypt all zero bytes 1000 times, decrypt and come back to where we started */ + + for (i = 0; i < 24; i++) key[i] = i; + + if ((err = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < 8; i++) pt[i] = tmp[i] = 0; + for (i = 0; i < 1000; i++) des3_ecb_encrypt(tmp, tmp, &skey); + for (i = 0; i < 1000; i++) des3_ecb_decrypt(tmp, tmp, &skey); + + if (compare_testvector(tmp, 8, pt, 8, "3DES", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void des_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** Terminate the context + @param skey The scheduled key +*/ +void des3_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int des_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if(*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 8; + return CRYPT_OK; +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int des3_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } + *keysize = 24; + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/ciphers/idea.c b/deps/libtomcrypt/src/ciphers/idea.c new file mode 100644 index 0000000..b195a4c --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/idea.c @@ -0,0 +1,250 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Based on idea.cpp - originally written and placed in the public domain by Wei Dai + https://github.com/weidai11/cryptopp/blob/master/idea.cpp + + Patents should be expired. On 2017-10-16 wikipedia says: + https://en.wikipedia.org/wiki/International_Data_Encryption_Algorithm + + A patent application for IDEA was first filed in Switzerland (CH A 1690/90) on May 18, 1990, + then an international patent application was filed under the Patent Cooperation Treaty on + May 16, 1991. Patents were eventually granted in Austria, France, Germany, Italy, the Netherlands, + Spain, Sweden, Switzerland, the United Kingdom, (European Patent Register entry for European + patent no. 0482154, filed May 16, 1991, issued June 22, 1994 and expired May 16, 2011), + the United States (U.S. Patent 5,214,703, issued May 25, 1993 and expired January 7, 2012) + and Japan (JP 3225440) (expired May 16, 2011). + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_IDEA + +const struct ltc_cipher_descriptor idea_desc = { + "idea", + 24, /* cipher_ID */ + 16, 16, 8, 8, /* min_key_len, max_key_len, block_len, default_rounds */ + &idea_setup, + &idea_ecb_encrypt, + &idea_ecb_decrypt, + &idea_test, + &idea_done, + &idea_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +typedef unsigned short int ushort16; + +#define LOW16(x) ((x)&0xffff) /* compiler should be able to optimize this away if x is 16 bits */ +#define HIGH16(x) ((x)>>16) +#define MUL(a,b) { \ + ulong32 p = (ulong32)LOW16(a) * b; \ + if (p) { \ + p = LOW16(p) - HIGH16(p); \ + a = (ushort16)p - (ushort16)HIGH16(p); \ + } \ + else \ + a = 1 - a - b; \ + } +#define STORE16(x,y) { (y)[0] = (unsigned char)(((x)>>8)&255); (y)[1] = (unsigned char)((x)&255); } +#define LOAD16(x,y) { x = ((ushort16)((y)[0] & 255)<<8) | ((ushort16)((y)[1] & 255)); } + +static ushort16 s_mul_inv(ushort16 x) +{ + ushort16 y = x; + unsigned i; + + for (i = 0; i < 15; i++) { + MUL(y, LOW16(y)); + MUL(y, x); + } + return LOW16(y); +} + +static ushort16 s_add_inv(ushort16 x) +{ + return LOW16(0 - x); +} + +static int s_setup_key(const unsigned char *key, symmetric_key *skey) +{ + int i, j; + ushort16 *e_key = skey->idea.ek; + ushort16 *d_key = skey->idea.dk; + + /* prepare enc key */ + for (i = 0; i < 8; i++) { + LOAD16(e_key[i], key + 2 * i); + } + for (; i < LTC_IDEA_KEYLEN; i++) { + j = (i - i % 8) - 8; + e_key[i] = LOW16((e_key[j+(i+1)%8] << 9) | (e_key[j+(i+2)%8] >> 7)); + } + + /* prepare dec key */ + for (i = 0; i < LTC_IDEA_ROUNDS; i++) { + d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); + d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1+(i>0 ? 1 : 0)]); + d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2-(i>0 ? 1 : 0)]); + d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); + d_key[i*6+4] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+4]; + d_key[i*6+5] = e_key[(LTC_IDEA_ROUNDS-1-i)*6+5]; + } + d_key[i*6+0] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+0]); + d_key[i*6+1] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+1]); + d_key[i*6+2] = s_add_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+2]); + d_key[i*6+3] = s_mul_inv(e_key[(LTC_IDEA_ROUNDS-i)*6+3]); + + return CRYPT_OK; +} + +static int s_process_block(const unsigned char *in, unsigned char *out, const ushort16 *m_key) +{ + int i; + ushort16 x0, x1, x2, x3, t0, t1; + + LOAD16(x0, in + 0); + LOAD16(x1, in + 2); + LOAD16(x2, in + 4); + LOAD16(x3, in + 6); + + for (i = 0; i < LTC_IDEA_ROUNDS; i++) { + MUL(x0, m_key[i*6+0]); + x1 += m_key[i*6+1]; + x2 += m_key[i*6+2]; + MUL(x3, m_key[i*6+3]); + t0 = x0^x2; + MUL(t0, m_key[i*6+4]); + t1 = t0 + (x1^x3); + MUL(t1, m_key[i*6+5]); + t0 += t1; + x0 ^= t1; + x3 ^= t0; + t0 ^= x1; + x1 = x2^t1; + x2 = t0; + } + + MUL(x0, m_key[LTC_IDEA_ROUNDS*6+0]); + x2 += m_key[LTC_IDEA_ROUNDS*6+1]; + x1 += m_key[LTC_IDEA_ROUNDS*6+2]; + MUL(x3, m_key[LTC_IDEA_ROUNDS*6+3]); + + STORE16(x0, out + 0); + STORE16(x2, out + 2); + STORE16(x1, out + 4); + STORE16(x3, out + 6); + + return CRYPT_OK; +} + +int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && num_rounds != 8) return CRYPT_INVALID_ROUNDS; + if (keylen != 16) return CRYPT_INVALID_KEYSIZE; + + return s_setup_key(key, skey); +} + +int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_process_block(pt, ct, skey->idea.ek); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ushort16) * 6 + sizeof(int)); +#endif + return err; +} + +int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_process_block(ct, pt, skey->idea.dk); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ushort16) * 6 + sizeof(int)); +#endif + return err; +} + +void idea_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int idea_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +int idea_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + { + /* key */ { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xB1, 0xF5, 0xF7, 0xF8, 0x79, 0x01, 0x37, 0x0F } + }, + { + /* key */ { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xB3, 0x92, 0x7D, 0xFF, 0xB6, 0x35, 0x86, 0x26 } + }, + { + /* key */ { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xE9, 0x87, 0xE0, 0x02, 0x9F, 0xB9, 0x97, 0x85 } + }, + { + /* key */ { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0x75, 0x4A, 0x03, 0xCE, 0x08, 0xDB, 0x7D, 0xAA } + }, + { + /* key */ { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* pt */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* ct */ { 0xF0, 0x15, 0xF9, 0xFB, 0x0C, 0xFC, 0x7E, 0x1C } + }, + }; + + unsigned char buf[2][8]; + symmetric_key key; + int err, x; + + if (sizeof(ushort16) != 2) { + return CRYPT_FAIL_TESTVECTOR; + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = idea_setup(tests[x].key, 16, 8, &key)) != CRYPT_OK) { + return err; + } + if ((err = idea_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "IDEA Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = idea_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[1], 8, tests[x].pt, 8, "IDEA Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/kasumi.c b/deps/libtomcrypt/src/ciphers/kasumi.c new file mode 100644 index 0000000..1ade9d6 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/kasumi.c @@ -0,0 +1,307 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file kasumi.c + Implementation of the 3GPP Kasumi block cipher + Derived from the 3GPP standard source code +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_KASUMI + +typedef unsigned u16; + +#define ROL16(x, y) ((((x)<<(y)) | ((x)>>(16-(y)))) & 0xFFFF) + +const struct ltc_cipher_descriptor kasumi_desc = { + "kasumi", + 21, + 16, 16, 8, 8, + &kasumi_setup, + &kasumi_ecb_encrypt, + &kasumi_ecb_decrypt, + &kasumi_test, + &kasumi_done, + &kasumi_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static u16 FI( u16 in, u16 subkey ) +{ + u16 nine, seven; + static const u16 S7[128] = { + 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,123, 33, + 55,113, 39,114, 21, 67, 65, 12, 47, 73, 46, 27, 25,111,124, 81, + 53, 9,121, 79, 52, 60, 58, 48,101,127, 40,120,104, 70, 71, 43, + 20,122, 72, 61, 23,109, 13,100, 77, 1, 16, 7, 82, 10,105, 98, + 117,116, 76, 11, 89,106, 0,125,118, 99, 86, 69, 30, 57,126, 87, + 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66, + 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29,115, 44, + 64,107,108, 24,110, 83, 36, 78, 42, 19, 15, 41, 88,119, 59, 3 }; + static const u16 S9[512] = { + 167,239,161,379,391,334, 9,338, 38,226, 48,358,452,385, 90,397, + 183,253,147,331,415,340, 51,362,306,500,262, 82,216,159,356,177, + 175,241,489, 37,206, 17, 0,333, 44,254,378, 58,143,220, 81,400, + 95, 3,315,245, 54,235,218,405,472,264,172,494,371,290,399, 76, + 165,197,395,121,257,480,423,212,240, 28,462,176,406,507,288,223, + 501,407,249,265, 89,186,221,428,164, 74,440,196,458,421,350,163, + 232,158,134,354, 13,250,491,142,191, 69,193,425,152,227,366,135, + 344,300,276,242,437,320,113,278, 11,243, 87,317, 36, 93,496, 27, + 487,446,482, 41, 68,156,457,131,326,403,339, 20, 39,115,442,124, + 475,384,508, 53,112,170,479,151,126,169, 73,268,279,321,168,364, + 363,292, 46,499,393,327,324, 24,456,267,157,460,488,426,309,229, + 439,506,208,271,349,401,434,236, 16,209,359, 52, 56,120,199,277, + 465,416,252,287,246, 6, 83,305,420,345,153,502, 65, 61,244,282, + 173,222,418, 67,386,368,261,101,476,291,195,430, 49, 79,166,330, + 280,383,373,128,382,408,155,495,367,388,274,107,459,417, 62,454, + 132,225,203,316,234, 14,301, 91,503,286,424,211,347,307,140,374, + 35,103,125,427, 19,214,453,146,498,314,444,230,256,329,198,285, + 50,116, 78,410, 10,205,510,171,231, 45,139,467, 29, 86,505, 32, + 72, 26,342,150,313,490,431,238,411,325,149,473, 40,119,174,355, + 185,233,389, 71,448,273,372, 55,110,178,322, 12,469,392,369,190, + 1,109,375,137,181, 88, 75,308,260,484, 98,272,370,275,412,111, + 336,318, 4,504,492,259,304, 77,337,435, 21,357,303,332,483, 18, + 47, 85, 25,497,474,289,100,269,296,478,270,106, 31,104,433, 84, + 414,486,394, 96, 99,154,511,148,413,361,409,255,162,215,302,201, + 266,351,343,144,441,365,108,298,251, 34,182,509,138,210,335,133, + 311,352,328,141,396,346,123,319,450,281,429,228,443,481, 92,404, + 485,422,248,297, 23,213,130,466, 22,217,283, 70,294,360,419,127, + 312,377, 7,468,194, 2,117,295,463,258,224,447,247,187, 80,398, + 284,353,105,390,299,471,470,184, 57,200,348, 63,204,188, 33,451, + 97, 30,310,219, 94,160,129,493, 64,179,263,102,189,207,114,402, + 438,477,387,122,192, 42,381, 5,145,118,180,449,293,323,136,380, + 43, 66, 60,455,341,445,202,432, 8,237, 15,376,436,464, 59,461}; + + /* The sixteen bit input is split into two unequal halves, * + * nine bits and seven bits - as is the subkey */ + + nine = (u16)(in>>7)&0x1FF; + seven = (u16)(in&0x7F); + + /* Now run the various operations */ + nine = (u16)(S9[nine] ^ seven); + seven = (u16)(S7[seven] ^ (nine & 0x7F)); + seven ^= (subkey>>9); + nine ^= (subkey&0x1FF); + nine = (u16)(S9[nine] ^ seven); + seven = (u16)(S7[seven] ^ (nine & 0x7F)); + return (u16)(seven<<9) + nine; +} + +static ulong32 FO( ulong32 in, int round_no, const symmetric_key *key) +{ + u16 left, right; + + /* Split the input into two 16-bit words */ + left = (u16)(in>>16); + right = (u16) in&0xFFFF; + + /* Now apply the same basic transformation three times */ + left ^= key->kasumi.KOi1[round_no]; + left = FI( left, key->kasumi.KIi1[round_no] ); + left ^= right; + + right ^= key->kasumi.KOi2[round_no]; + right = FI( right, key->kasumi.KIi2[round_no] ); + right ^= left; + + left ^= key->kasumi.KOi3[round_no]; + left = FI( left, key->kasumi.KIi3[round_no] ); + left ^= right; + + return (((ulong32)right)<<16)+left; +} + +static ulong32 FL( ulong32 in, int round_no, const symmetric_key *key ) +{ + u16 l, r, a, b; + /* split out the left and right halves */ + l = (u16)(in>>16); + r = (u16)(in)&0xFFFF; + /* do the FL() operations */ + a = (u16) (l & key->kasumi.KLi1[round_no]); + r ^= ROL16(a,1); + b = (u16)(r | key->kasumi.KLi2[round_no]); + l ^= ROL16(b,1); + /* put the two halves back together */ + + return (((ulong32)l)<<16) + r; +} + +int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 left, right, temp; + int n; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(left, pt); + LOAD32H(right, pt+4); + + for (n = 0; n <= 7; ) { + temp = FL(left, n, skey); + temp = FO(temp, n++, skey); + right ^= temp; + temp = FO(right, n, skey); + temp = FL(temp, n++, skey); + left ^= temp; + } + + STORE32H(left, ct); + STORE32H(right, ct+4); + + return CRYPT_OK; +} + +int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 left, right, temp; + int n; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(left, ct); + LOAD32H(right, ct+4); + + for (n = 7; n >= 0; ) { + temp = FO(right, n, skey); + temp = FL(temp, n--, skey); + left ^= temp; + temp = FL(left, n, skey); + temp = FO(temp, n--, skey); + right ^= temp; + } + + STORE32H(left, pt); + STORE32H(right, pt+4); + + return CRYPT_OK; +} + +int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + static const u16 C[8] = { 0x0123,0x4567,0x89AB,0xCDEF, 0xFEDC,0xBA98,0x7654,0x3210 }; + u16 ukey[8], Kprime[8]; + int n; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != 8) { + return CRYPT_INVALID_ROUNDS; + } + + /* Start by ensuring the subkeys are endian correct on a 16-bit basis */ + for (n = 0; n < 8; n++ ) { + ukey[n] = (((u16)key[2*n]) << 8) | key[2*n+1]; + } + + /* Now build the K'[] keys */ + for (n = 0; n < 8; n++) { + Kprime[n] = ukey[n] ^ C[n]; + } + + /* Finally construct the various sub keys */ + for(n = 0; n < 8; n++) { + skey->kasumi.KLi1[n] = ROL16(ukey[n],1); + skey->kasumi.KLi2[n] = Kprime[(n+2)&0x7]; + skey->kasumi.KOi1[n] = ROL16(ukey[(n+1)&0x7],5); + skey->kasumi.KOi2[n] = ROL16(ukey[(n+5)&0x7],8); + skey->kasumi.KOi3[n] = ROL16(ukey[(n+6)&0x7],13); + skey->kasumi.KIi1[n] = Kprime[(n+4)&0x7]; + skey->kasumi.KIi2[n] = Kprime[(n+3)&0x7]; + skey->kasumi.KIi3[n] = Kprime[(n+7)&0x7]; + } + + return CRYPT_OK; +} + +void kasumi_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int kasumi_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 16) { + *keysize = 16; + return CRYPT_OK; + } + return CRYPT_INVALID_KEYSIZE; +} + +int kasumi_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + +{ + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x4B, 0x58, 0xA7, 0x71, 0xAF, 0xC7, 0xE5, 0xE8 } +}, + +{ + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x7E, 0xEF, 0x11, 0x3C, 0x95, 0xBB, 0x5A, 0x77 } +}, + +{ + { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x5F, 0x14, 0x06, 0x86, 0xD7, 0xAD, 0x5A, 0x39 }, +}, + +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x2E, 0x14, 0x91, 0xCF, 0x70, 0xAA, 0x46, 0x5D } +}, + +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xB5, 0x45, 0x86, 0xF4, 0xAB, 0x9A, 0xE5, 0x46 } +}, + +}; + unsigned char buf[2][8]; + symmetric_key key; + int err, x; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = kasumi_setup(tests[x].key, 16, 0, &key)) != CRYPT_OK) { + return err; + } + if ((err = kasumi_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { + return err; + } + if ((err = kasumi_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[1], 8, tests[x].pt, 8, "Kasumi Decrypt", x) || + compare_testvector(buf[0], 8, tests[x].ct, 8, "Kasumi Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/khazad.c b/deps/libtomcrypt/src/ciphers/khazad.c new file mode 100644 index 0000000..72cbda8 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/khazad.c @@ -0,0 +1,840 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file khazad.c + Khazad implementation derived from public domain source + Authors: Paulo S.L.M. Barreto and Vincent Rijmen. +*/ + +#ifdef LTC_KHAZAD + +const struct ltc_cipher_descriptor khazad_desc = { + "khazad", + 18, + 16, 16, 8, 8, + &khazad_setup, + &khazad_ecb_encrypt, + &khazad_ecb_decrypt, + &khazad_test, + &khazad_done, + &khazad_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#define R 8 + +static const ulong64 T0[256] = { + CONST64(0xbad3d268bbb96a01), CONST64(0x54fc4d19e59a66b1), CONST64(0x2f71bc93e26514cd), CONST64(0x749ccdb925871b51), + CONST64(0x53f55102f7a257a4), CONST64(0xd3686bb8d0d6be03), CONST64(0xd26b6fbdd6deb504), CONST64(0x4dd72964b35285fe), + CONST64(0x50f05d0dfdba4aad), CONST64(0xace98a26cf09e063), CONST64(0x8d8a0e83091c9684), CONST64(0xbfdcc679a5914d1a), + CONST64(0x7090ddad3da7374d), CONST64(0x52f65507f1aa5ca3), CONST64(0x9ab352c87ba417e1), CONST64(0x4cd42d61b55a8ef9), + CONST64(0xea238f65460320ac), CONST64(0xd56273a6c4e68411), CONST64(0x97a466f155cc68c2), CONST64(0xd16e63b2dcc6a80d), + CONST64(0x3355ccffaa85d099), CONST64(0x51f35908fbb241aa), CONST64(0x5bed712ac7e20f9c), CONST64(0xa6f7a204f359ae55), + CONST64(0xde7f5f81febec120), CONST64(0x48d83d75ad7aa2e5), CONST64(0xa8e59a32d729cc7f), CONST64(0x99b65ec771bc0ae8), + CONST64(0xdb704b90e096e63b), CONST64(0x3256c8faac8ddb9e), CONST64(0xb7c4e65195d11522), CONST64(0xfc19d72b32b3aace), + CONST64(0xe338ab48704b7393), CONST64(0x9ebf42dc63843bfd), CONST64(0x91ae7eef41fc52d0), CONST64(0x9bb056cd7dac1ce6), + CONST64(0xe23baf4d76437894), CONST64(0xbbd0d66dbdb16106), CONST64(0x41c319589b32f1da), CONST64(0x6eb2a5cb7957e517), + CONST64(0xa5f2ae0bf941b35c), CONST64(0xcb400bc08016564b), CONST64(0x6bbdb1da677fc20c), CONST64(0x95a26efb59dc7ecc), + CONST64(0xa1febe1fe1619f40), CONST64(0xf308eb1810cbc3e3), CONST64(0xb1cefe4f81e12f30), CONST64(0x0206080a0c10160e), + CONST64(0xcc4917db922e675e), CONST64(0xc45137f3a26e3f66), CONST64(0x1d2774694ee8cf53), CONST64(0x143c504478a09c6c), + CONST64(0xc3582be8b0560e73), CONST64(0x63a591f2573f9a34), CONST64(0xda734f95e69eed3c), CONST64(0x5de76934d3d2358e), + CONST64(0x5fe1613edfc22380), CONST64(0xdc79578bf2aed72e), CONST64(0x7d87e99413cf486e), CONST64(0xcd4a13de94266c59), + CONST64(0x7f81e19e1fdf5e60), CONST64(0x5aee752fc1ea049b), CONST64(0x6cb4adc17547f319), CONST64(0x5ce46d31d5da3e89), + CONST64(0xf704fb0c08ebefff), CONST64(0x266a98bed42d47f2), CONST64(0xff1cdb2438abb7c7), CONST64(0xed2a937e543b11b9), + CONST64(0xe825876f4a1336a2), CONST64(0x9dba4ed3699c26f4), CONST64(0x6fb1a1ce7f5fee10), CONST64(0x8e8f028c03048b8d), + CONST64(0x192b647d56c8e34f), CONST64(0xa0fdba1ae7699447), CONST64(0xf00de7171ad3deea), CONST64(0x89861e97113cba98), + CONST64(0x0f113c332278692d), CONST64(0x07091c1b12383115), CONST64(0xafec8629c511fd6a), CONST64(0xfb10cb30208b9bdb), + CONST64(0x0818202830405838), CONST64(0x153f54417ea8976b), CONST64(0x0d1734392e687f23), CONST64(0x040c101418202c1c), + CONST64(0x0103040506080b07), CONST64(0x64ac8de94507ab21), CONST64(0xdf7c5b84f8b6ca27), CONST64(0x769ac5b329970d5f), + CONST64(0x798bf9800bef6472), CONST64(0xdd7a538ef4a6dc29), CONST64(0x3d47f4c98ef5b2b3), CONST64(0x163a584e74b08a62), + CONST64(0x3f41fcc382e5a4bd), CONST64(0x3759dcebb2a5fc85), CONST64(0x6db7a9c4734ff81e), CONST64(0x3848e0d890dd95a8), + CONST64(0xb9d6de67b1a17708), CONST64(0x7395d1a237bf2a44), CONST64(0xe926836a4c1b3da5), CONST64(0x355fd4e1beb5ea8b), + CONST64(0x55ff491ce3926db6), CONST64(0x7193d9a83baf3c4a), CONST64(0x7b8df18a07ff727c), CONST64(0x8c890a860f149d83), + CONST64(0x7296d5a731b72143), CONST64(0x88851a921734b19f), CONST64(0xf607ff090ee3e4f8), CONST64(0x2a7ea882fc4d33d6), + CONST64(0x3e42f8c684edafba), CONST64(0x5ee2653bd9ca2887), CONST64(0x27699cbbd2254cf5), CONST64(0x46ca0543890ac0cf), + CONST64(0x0c14303c28607424), CONST64(0x65af89ec430fa026), CONST64(0x68b8bdd56d67df05), CONST64(0x61a399f85b2f8c3a), + CONST64(0x03050c0f0a181d09), CONST64(0xc15e23e2bc46187d), CONST64(0x57f94116ef827bb8), CONST64(0xd6677fa9cefe9918), + CONST64(0xd976439aec86f035), CONST64(0x58e87d25cdfa1295), CONST64(0xd875479fea8efb32), CONST64(0x66aa85e34917bd2f), + CONST64(0xd7647bacc8f6921f), CONST64(0x3a4ee8d29ccd83a6), CONST64(0xc84507cf8a0e4b42), CONST64(0x3c44f0cc88fdb9b4), + CONST64(0xfa13cf35268390dc), CONST64(0x96a762f453c463c5), CONST64(0xa7f4a601f551a552), CONST64(0x98b55ac277b401ef), + CONST64(0xec29977b52331abe), CONST64(0xb8d5da62b7a97c0f), CONST64(0xc7543bfca876226f), CONST64(0xaeef822cc319f66d), + CONST64(0x69bbb9d06b6fd402), CONST64(0x4bdd317aa762bfec), CONST64(0xabe0963ddd31d176), CONST64(0xa9e69e37d121c778), + CONST64(0x67a981e64f1fb628), CONST64(0x0a1e28223c504e36), CONST64(0x47c901468f02cbc8), CONST64(0xf20bef1d16c3c8e4), + CONST64(0xb5c2ee5b99c1032c), CONST64(0x226688aacc0d6bee), CONST64(0xe532b356647b4981), CONST64(0xee2f9f715e230cb0), + CONST64(0xbedfc27ca399461d), CONST64(0x2b7dac87fa4538d1), CONST64(0x819e3ebf217ce2a0), CONST64(0x1236485a6c90a67e), + CONST64(0x839836b52d6cf4ae), CONST64(0x1b2d6c775ad8f541), CONST64(0x0e1238362470622a), CONST64(0x23658cafca0560e9), + CONST64(0xf502f30604fbf9f1), CONST64(0x45cf094c8312ddc6), CONST64(0x216384a5c61576e7), CONST64(0xce4f1fd19e3e7150), + CONST64(0x49db3970ab72a9e2), CONST64(0x2c74b09ce87d09c4), CONST64(0xf916c33a2c9b8dd5), CONST64(0xe637bf596e635488), + CONST64(0xb6c7e25493d91e25), CONST64(0x2878a088f05d25d8), CONST64(0x17395c4b72b88165), CONST64(0x829b32b02b64ffa9), + CONST64(0x1a2e68725cd0fe46), CONST64(0x8b80169d1d2cac96), CONST64(0xfe1fdf213ea3bcc0), CONST64(0x8a8312981b24a791), + CONST64(0x091b242d3648533f), CONST64(0xc94603ca8c064045), CONST64(0x879426a1354cd8b2), CONST64(0x4ed2256bb94a98f7), + CONST64(0xe13ea3427c5b659d), CONST64(0x2e72b896e46d1fca), CONST64(0xe431b75362734286), CONST64(0xe03da7477a536e9a), + CONST64(0xeb208b60400b2bab), CONST64(0x90ad7aea47f459d7), CONST64(0xa4f1aa0eff49b85b), CONST64(0x1e22786644f0d25a), + CONST64(0x85922eab395ccebc), CONST64(0x60a09dfd5d27873d), CONST64(0x0000000000000000), CONST64(0x256f94b1de355afb), + CONST64(0xf401f70302f3f2f6), CONST64(0xf10ee3121cdbd5ed), CONST64(0x94a16afe5fd475cb), CONST64(0x0b1d2c273a584531), + CONST64(0xe734bb5c686b5f8f), CONST64(0x759fc9bc238f1056), CONST64(0xef2c9b74582b07b7), CONST64(0x345cd0e4b8bde18c), + CONST64(0x3153c4f5a695c697), CONST64(0xd46177a3c2ee8f16), CONST64(0xd06d67b7dacea30a), CONST64(0x869722a43344d3b5), + CONST64(0x7e82e59b19d75567), CONST64(0xadea8e23c901eb64), CONST64(0xfd1ad32e34bba1c9), CONST64(0x297ba48df6552edf), + CONST64(0x3050c0f0a09dcd90), CONST64(0x3b4decd79ac588a1), CONST64(0x9fbc46d9658c30fa), CONST64(0xf815c73f2a9386d2), + CONST64(0xc6573ff9ae7e2968), CONST64(0x13354c5f6a98ad79), CONST64(0x060a181e14303a12), CONST64(0x050f14111e28271b), + CONST64(0xc55233f6a4663461), CONST64(0x113344556688bb77), CONST64(0x7799c1b62f9f0658), CONST64(0x7c84ed9115c74369), + CONST64(0x7a8ef58f01f7797b), CONST64(0x7888fd850de76f75), CONST64(0x365ad8eeb4adf782), CONST64(0x1c24706c48e0c454), + CONST64(0x394be4dd96d59eaf), CONST64(0x59eb7920cbf21992), CONST64(0x1828607850c0e848), CONST64(0x56fa4513e98a70bf), + CONST64(0xb3c8f6458df1393e), CONST64(0xb0cdfa4a87e92437), CONST64(0x246c90b4d83d51fc), CONST64(0x206080a0c01d7de0), + CONST64(0xb2cbf2408bf93239), CONST64(0x92ab72e04be44fd9), CONST64(0xa3f8b615ed71894e), CONST64(0xc05d27e7ba4e137a), + CONST64(0x44cc0d49851ad6c1), CONST64(0x62a695f751379133), CONST64(0x103040506080b070), CONST64(0xb4c1ea5e9fc9082b), + CONST64(0x84912aae3f54c5bb), CONST64(0x43c511529722e7d4), CONST64(0x93a876e54dec44de), CONST64(0xc25b2fedb65e0574), + CONST64(0x4ade357fa16ab4eb), CONST64(0xbddace73a9815b14), CONST64(0x8f8c0689050c808a), CONST64(0x2d77b499ee7502c3), + CONST64(0xbcd9ca76af895013), CONST64(0x9cb94ad66f942df3), CONST64(0x6abeb5df6177c90b), CONST64(0x40c01d5d9d3afadd), + CONST64(0xcf4c1bd498367a57), CONST64(0xa2fbb210eb798249), CONST64(0x809d3aba2774e9a7), CONST64(0x4fd1216ebf4293f0), + CONST64(0x1f217c6342f8d95d), CONST64(0xca430fc5861e5d4c), CONST64(0xaae39238db39da71), CONST64(0x42c61557912aecd3), +}; + +static const ulong64 T1[256] = { + CONST64(0xd3ba68d2b9bb016a), CONST64(0xfc54194d9ae5b166), CONST64(0x712f93bc65e2cd14), CONST64(0x9c74b9cd8725511b), + CONST64(0xf5530251a2f7a457), CONST64(0x68d3b86bd6d003be), CONST64(0x6bd2bd6fded604b5), CONST64(0xd74d642952b3fe85), + CONST64(0xf0500d5dbafdad4a), CONST64(0xe9ac268a09cf63e0), CONST64(0x8a8d830e1c098496), CONST64(0xdcbf79c691a51a4d), + CONST64(0x9070addda73d4d37), CONST64(0xf6520755aaf1a35c), CONST64(0xb39ac852a47be117), CONST64(0xd44c612d5ab5f98e), + CONST64(0x23ea658f0346ac20), CONST64(0x62d5a673e6c41184), CONST64(0xa497f166cc55c268), CONST64(0x6ed1b263c6dc0da8), + CONST64(0x5533ffcc85aa99d0), CONST64(0xf3510859b2fbaa41), CONST64(0xed5b2a71e2c79c0f), CONST64(0xf7a604a259f355ae), + CONST64(0x7fde815fbefe20c1), CONST64(0xd848753d7aade5a2), CONST64(0xe5a8329a29d77fcc), CONST64(0xb699c75ebc71e80a), + CONST64(0x70db904b96e03be6), CONST64(0x5632fac88dac9edb), CONST64(0xc4b751e6d1952215), CONST64(0x19fc2bd7b332ceaa), + CONST64(0x38e348ab4b709373), CONST64(0xbf9edc428463fd3b), CONST64(0xae91ef7efc41d052), CONST64(0xb09bcd56ac7de61c), + CONST64(0x3be24daf43769478), CONST64(0xd0bb6dd6b1bd0661), CONST64(0xc3415819329bdaf1), CONST64(0xb26ecba5577917e5), + CONST64(0xf2a50bae41f95cb3), CONST64(0x40cbc00b16804b56), CONST64(0xbd6bdab17f670cc2), CONST64(0xa295fb6edc59cc7e), + CONST64(0xfea11fbe61e1409f), CONST64(0x08f318ebcb10e3c3), CONST64(0xceb14ffee181302f), CONST64(0x06020a08100c0e16), + CONST64(0x49ccdb172e925e67), CONST64(0x51c4f3376ea2663f), CONST64(0x271d6974e84e53cf), CONST64(0x3c144450a0786c9c), + CONST64(0x58c3e82b56b0730e), CONST64(0xa563f2913f57349a), CONST64(0x73da954f9ee63ced), CONST64(0xe75d3469d2d38e35), + CONST64(0xe15f3e61c2df8023), CONST64(0x79dc8b57aef22ed7), CONST64(0x877d94e9cf136e48), CONST64(0x4acdde132694596c), + CONST64(0x817f9ee1df1f605e), CONST64(0xee5a2f75eac19b04), CONST64(0xb46cc1ad477519f3), CONST64(0xe45c316ddad5893e), + CONST64(0x04f70cfbeb08ffef), CONST64(0x6a26be982dd4f247), CONST64(0x1cff24dbab38c7b7), CONST64(0x2aed7e933b54b911), + CONST64(0x25e86f87134aa236), CONST64(0xba9dd34e9c69f426), CONST64(0xb16fcea15f7f10ee), CONST64(0x8f8e8c0204038d8b), + CONST64(0x2b197d64c8564fe3), CONST64(0xfda01aba69e74794), CONST64(0x0df017e7d31aeade), CONST64(0x8689971e3c1198ba), + CONST64(0x110f333c78222d69), CONST64(0x09071b1c38121531), CONST64(0xecaf298611c56afd), CONST64(0x10fb30cb8b20db9b), + CONST64(0x1808282040303858), CONST64(0x3f154154a87e6b97), CONST64(0x170d3934682e237f), CONST64(0x0c04141020181c2c), + CONST64(0x030105040806070b), CONST64(0xac64e98d074521ab), CONST64(0x7cdf845bb6f827ca), CONST64(0x9a76b3c597295f0d), + CONST64(0x8b7980f9ef0b7264), CONST64(0x7add8e53a6f429dc), CONST64(0x473dc9f4f58eb3b2), CONST64(0x3a164e58b074628a), + CONST64(0x413fc3fce582bda4), CONST64(0x5937ebdca5b285fc), CONST64(0xb76dc4a94f731ef8), CONST64(0x4838d8e0dd90a895), + CONST64(0xd6b967dea1b10877), CONST64(0x9573a2d1bf37442a), CONST64(0x26e96a831b4ca53d), CONST64(0x5f35e1d4b5be8bea), + CONST64(0xff551c4992e3b66d), CONST64(0x9371a8d9af3b4a3c), CONST64(0x8d7b8af1ff077c72), CONST64(0x898c860a140f839d), + CONST64(0x9672a7d5b7314321), CONST64(0x8588921a34179fb1), CONST64(0x07f609ffe30ef8e4), CONST64(0x7e2a82a84dfcd633), + CONST64(0x423ec6f8ed84baaf), CONST64(0xe25e3b65cad98728), CONST64(0x6927bb9c25d2f54c), CONST64(0xca4643050a89cfc0), + CONST64(0x140c3c3060282474), CONST64(0xaf65ec890f4326a0), CONST64(0xb868d5bd676d05df), CONST64(0xa361f8992f5b3a8c), + CONST64(0x05030f0c180a091d), CONST64(0x5ec1e22346bc7d18), CONST64(0xf957164182efb87b), CONST64(0x67d6a97ffece1899), + CONST64(0x76d99a4386ec35f0), CONST64(0xe858257dfacd9512), CONST64(0x75d89f478eea32fb), CONST64(0xaa66e38517492fbd), + CONST64(0x64d7ac7bf6c81f92), CONST64(0x4e3ad2e8cd9ca683), CONST64(0x45c8cf070e8a424b), CONST64(0x443cccf0fd88b4b9), + CONST64(0x13fa35cf8326dc90), CONST64(0xa796f462c453c563), CONST64(0xf4a701a651f552a5), CONST64(0xb598c25ab477ef01), + CONST64(0x29ec7b973352be1a), CONST64(0xd5b862daa9b70f7c), CONST64(0x54c7fc3b76a86f22), CONST64(0xefae2c8219c36df6), + CONST64(0xbb69d0b96f6b02d4), CONST64(0xdd4b7a3162a7ecbf), CONST64(0xe0ab3d9631dd76d1), CONST64(0xe6a9379e21d178c7), + CONST64(0xa967e6811f4f28b6), CONST64(0x1e0a2228503c364e), CONST64(0xc9474601028fc8cb), CONST64(0x0bf21defc316e4c8), + CONST64(0xc2b55beec1992c03), CONST64(0x6622aa880dccee6b), CONST64(0x32e556b37b648149), CONST64(0x2fee719f235eb00c), + CONST64(0xdfbe7cc299a31d46), CONST64(0x7d2b87ac45fad138), CONST64(0x9e81bf3e7c21a0e2), CONST64(0x36125a48906c7ea6), + CONST64(0x9883b5366c2daef4), CONST64(0x2d1b776cd85a41f5), CONST64(0x120e363870242a62), CONST64(0x6523af8c05cae960), + CONST64(0x02f506f3fb04f1f9), CONST64(0xcf454c091283c6dd), CONST64(0x6321a58415c6e776), CONST64(0x4fced11f3e9e5071), + CONST64(0xdb49703972abe2a9), CONST64(0x742c9cb07de8c409), CONST64(0x16f93ac39b2cd58d), CONST64(0x37e659bf636e8854), + CONST64(0xc7b654e2d993251e), CONST64(0x782888a05df0d825), CONST64(0x39174b5cb8726581), CONST64(0x9b82b032642ba9ff), + CONST64(0x2e1a7268d05c46fe), CONST64(0x808b9d162c1d96ac), CONST64(0x1ffe21dfa33ec0bc), CONST64(0x838a9812241b91a7), + CONST64(0x1b092d2448363f53), CONST64(0x46c9ca03068c4540), CONST64(0x9487a1264c35b2d8), CONST64(0xd24e6b254ab9f798), + CONST64(0x3ee142a35b7c9d65), CONST64(0x722e96b86de4ca1f), CONST64(0x31e453b773628642), CONST64(0x3de047a7537a9a6e), + CONST64(0x20eb608b0b40ab2b), CONST64(0xad90ea7af447d759), CONST64(0xf1a40eaa49ff5bb8), CONST64(0x221e6678f0445ad2), + CONST64(0x9285ab2e5c39bcce), CONST64(0xa060fd9d275d3d87), CONST64(0x0000000000000000), CONST64(0x6f25b19435defb5a), + CONST64(0x01f403f7f302f6f2), CONST64(0x0ef112e3db1cedd5), CONST64(0xa194fe6ad45fcb75), CONST64(0x1d0b272c583a3145), + CONST64(0x34e75cbb6b688f5f), CONST64(0x9f75bcc98f235610), CONST64(0x2cef749b2b58b707), CONST64(0x5c34e4d0bdb88ce1), + CONST64(0x5331f5c495a697c6), CONST64(0x61d4a377eec2168f), CONST64(0x6dd0b767ceda0aa3), CONST64(0x9786a4224433b5d3), + CONST64(0x827e9be5d7196755), CONST64(0xeaad238e01c964eb), CONST64(0x1afd2ed3bb34c9a1), CONST64(0x7b298da455f6df2e), + CONST64(0x5030f0c09da090cd), CONST64(0x4d3bd7ecc59aa188), CONST64(0xbc9fd9468c65fa30), CONST64(0x15f83fc7932ad286), + CONST64(0x57c6f93f7eae6829), CONST64(0x35135f4c986a79ad), CONST64(0x0a061e183014123a), CONST64(0x0f051114281e1b27), + CONST64(0x52c5f63366a46134), CONST64(0x33115544886677bb), CONST64(0x9977b6c19f2f5806), CONST64(0x847c91edc7156943), + CONST64(0x8e7a8ff5f7017b79), CONST64(0x887885fde70d756f), CONST64(0x5a36eed8adb482f7), CONST64(0x241c6c70e04854c4), + CONST64(0x4b39dde4d596af9e), CONST64(0xeb592079f2cb9219), CONST64(0x28187860c05048e8), CONST64(0xfa5613458ae9bf70), + CONST64(0xc8b345f6f18d3e39), CONST64(0xcdb04afae9873724), CONST64(0x6c24b4903dd8fc51), CONST64(0x6020a0801dc0e07d), + CONST64(0xcbb240f2f98b3932), CONST64(0xab92e072e44bd94f), CONST64(0xf8a315b671ed4e89), CONST64(0x5dc0e7274eba7a13), + CONST64(0xcc44490d1a85c1d6), CONST64(0xa662f79537513391), CONST64(0x30105040806070b0), CONST64(0xc1b45eeac99f2b08), + CONST64(0x9184ae2a543fbbc5), CONST64(0xc54352112297d4e7), CONST64(0xa893e576ec4dde44), CONST64(0x5bc2ed2f5eb67405), + CONST64(0xde4a7f356aa1ebb4), CONST64(0xdabd73ce81a9145b), CONST64(0x8c8f89060c058a80), CONST64(0x772d99b475eec302), + CONST64(0xd9bc76ca89af1350), CONST64(0xb99cd64a946ff32d), CONST64(0xbe6adfb577610bc9), CONST64(0xc0405d1d3a9dddfa), + CONST64(0x4ccfd41b3698577a), CONST64(0xfba210b279eb4982), CONST64(0x9d80ba3a7427a7e9), CONST64(0xd14f6e2142bff093), + CONST64(0x211f637cf8425dd9), CONST64(0x43cac50f1e864c5d), CONST64(0xe3aa389239db71da), CONST64(0xc64257152a91d3ec), +}; + +static const ulong64 T2[256] = { + CONST64(0xd268bad36a01bbb9), CONST64(0x4d1954fc66b1e59a), CONST64(0xbc932f7114cde265), CONST64(0xcdb9749c1b512587), + CONST64(0x510253f557a4f7a2), CONST64(0x6bb8d368be03d0d6), CONST64(0x6fbdd26bb504d6de), CONST64(0x29644dd785feb352), + CONST64(0x5d0d50f04aadfdba), CONST64(0x8a26ace9e063cf09), CONST64(0x0e838d8a9684091c), CONST64(0xc679bfdc4d1aa591), + CONST64(0xddad7090374d3da7), CONST64(0x550752f65ca3f1aa), CONST64(0x52c89ab317e17ba4), CONST64(0x2d614cd48ef9b55a), + CONST64(0x8f65ea2320ac4603), CONST64(0x73a6d5628411c4e6), CONST64(0x66f197a468c255cc), CONST64(0x63b2d16ea80ddcc6), + CONST64(0xccff3355d099aa85), CONST64(0x590851f341aafbb2), CONST64(0x712a5bed0f9cc7e2), CONST64(0xa204a6f7ae55f359), + CONST64(0x5f81de7fc120febe), CONST64(0x3d7548d8a2e5ad7a), CONST64(0x9a32a8e5cc7fd729), CONST64(0x5ec799b60ae871bc), + CONST64(0x4b90db70e63be096), CONST64(0xc8fa3256db9eac8d), CONST64(0xe651b7c4152295d1), CONST64(0xd72bfc19aace32b3), + CONST64(0xab48e3387393704b), CONST64(0x42dc9ebf3bfd6384), CONST64(0x7eef91ae52d041fc), CONST64(0x56cd9bb01ce67dac), + CONST64(0xaf4de23b78947643), CONST64(0xd66dbbd06106bdb1), CONST64(0x195841c3f1da9b32), CONST64(0xa5cb6eb2e5177957), + CONST64(0xae0ba5f2b35cf941), CONST64(0x0bc0cb40564b8016), CONST64(0xb1da6bbdc20c677f), CONST64(0x6efb95a27ecc59dc), + CONST64(0xbe1fa1fe9f40e161), CONST64(0xeb18f308c3e310cb), CONST64(0xfe4fb1ce2f3081e1), CONST64(0x080a0206160e0c10), + CONST64(0x17dbcc49675e922e), CONST64(0x37f3c4513f66a26e), CONST64(0x74691d27cf534ee8), CONST64(0x5044143c9c6c78a0), + CONST64(0x2be8c3580e73b056), CONST64(0x91f263a59a34573f), CONST64(0x4f95da73ed3ce69e), CONST64(0x69345de7358ed3d2), + CONST64(0x613e5fe12380dfc2), CONST64(0x578bdc79d72ef2ae), CONST64(0xe9947d87486e13cf), CONST64(0x13decd4a6c599426), + CONST64(0xe19e7f815e601fdf), CONST64(0x752f5aee049bc1ea), CONST64(0xadc16cb4f3197547), CONST64(0x6d315ce43e89d5da), + CONST64(0xfb0cf704efff08eb), CONST64(0x98be266a47f2d42d), CONST64(0xdb24ff1cb7c738ab), CONST64(0x937eed2a11b9543b), + CONST64(0x876fe82536a24a13), CONST64(0x4ed39dba26f4699c), CONST64(0xa1ce6fb1ee107f5f), CONST64(0x028c8e8f8b8d0304), + CONST64(0x647d192be34f56c8), CONST64(0xba1aa0fd9447e769), CONST64(0xe717f00ddeea1ad3), CONST64(0x1e978986ba98113c), + CONST64(0x3c330f11692d2278), CONST64(0x1c1b070931151238), CONST64(0x8629afecfd6ac511), CONST64(0xcb30fb109bdb208b), + CONST64(0x2028081858383040), CONST64(0x5441153f976b7ea8), CONST64(0x34390d177f232e68), CONST64(0x1014040c2c1c1820), + CONST64(0x040501030b070608), CONST64(0x8de964acab214507), CONST64(0x5b84df7cca27f8b6), CONST64(0xc5b3769a0d5f2997), + CONST64(0xf980798b64720bef), CONST64(0x538edd7adc29f4a6), CONST64(0xf4c93d47b2b38ef5), CONST64(0x584e163a8a6274b0), + CONST64(0xfcc33f41a4bd82e5), CONST64(0xdceb3759fc85b2a5), CONST64(0xa9c46db7f81e734f), CONST64(0xe0d8384895a890dd), + CONST64(0xde67b9d67708b1a1), CONST64(0xd1a273952a4437bf), CONST64(0x836ae9263da54c1b), CONST64(0xd4e1355fea8bbeb5), + CONST64(0x491c55ff6db6e392), CONST64(0xd9a871933c4a3baf), CONST64(0xf18a7b8d727c07ff), CONST64(0x0a868c899d830f14), + CONST64(0xd5a77296214331b7), CONST64(0x1a928885b19f1734), CONST64(0xff09f607e4f80ee3), CONST64(0xa8822a7e33d6fc4d), + CONST64(0xf8c63e42afba84ed), CONST64(0x653b5ee22887d9ca), CONST64(0x9cbb27694cf5d225), CONST64(0x054346cac0cf890a), + CONST64(0x303c0c1474242860), CONST64(0x89ec65afa026430f), CONST64(0xbdd568b8df056d67), CONST64(0x99f861a38c3a5b2f), + CONST64(0x0c0f03051d090a18), CONST64(0x23e2c15e187dbc46), CONST64(0x411657f97bb8ef82), CONST64(0x7fa9d6679918cefe), + CONST64(0x439ad976f035ec86), CONST64(0x7d2558e81295cdfa), CONST64(0x479fd875fb32ea8e), CONST64(0x85e366aabd2f4917), + CONST64(0x7bacd764921fc8f6), CONST64(0xe8d23a4e83a69ccd), CONST64(0x07cfc8454b428a0e), CONST64(0xf0cc3c44b9b488fd), + CONST64(0xcf35fa1390dc2683), CONST64(0x62f496a763c553c4), CONST64(0xa601a7f4a552f551), CONST64(0x5ac298b501ef77b4), + CONST64(0x977bec291abe5233), CONST64(0xda62b8d57c0fb7a9), CONST64(0x3bfcc754226fa876), CONST64(0x822caeeff66dc319), + CONST64(0xb9d069bbd4026b6f), CONST64(0x317a4bddbfeca762), CONST64(0x963dabe0d176dd31), CONST64(0x9e37a9e6c778d121), + CONST64(0x81e667a9b6284f1f), CONST64(0x28220a1e4e363c50), CONST64(0x014647c9cbc88f02), CONST64(0xef1df20bc8e416c3), + CONST64(0xee5bb5c2032c99c1), CONST64(0x88aa22666beecc0d), CONST64(0xb356e5324981647b), CONST64(0x9f71ee2f0cb05e23), + CONST64(0xc27cbedf461da399), CONST64(0xac872b7d38d1fa45), CONST64(0x3ebf819ee2a0217c), CONST64(0x485a1236a67e6c90), + CONST64(0x36b58398f4ae2d6c), CONST64(0x6c771b2df5415ad8), CONST64(0x38360e12622a2470), CONST64(0x8caf236560e9ca05), + CONST64(0xf306f502f9f104fb), CONST64(0x094c45cfddc68312), CONST64(0x84a5216376e7c615), CONST64(0x1fd1ce4f71509e3e), + CONST64(0x397049dba9e2ab72), CONST64(0xb09c2c7409c4e87d), CONST64(0xc33af9168dd52c9b), CONST64(0xbf59e63754886e63), + CONST64(0xe254b6c71e2593d9), CONST64(0xa088287825d8f05d), CONST64(0x5c4b1739816572b8), CONST64(0x32b0829bffa92b64), + CONST64(0x68721a2efe465cd0), CONST64(0x169d8b80ac961d2c), CONST64(0xdf21fe1fbcc03ea3), CONST64(0x12988a83a7911b24), + CONST64(0x242d091b533f3648), CONST64(0x03cac94640458c06), CONST64(0x26a18794d8b2354c), CONST64(0x256b4ed298f7b94a), + CONST64(0xa342e13e659d7c5b), CONST64(0xb8962e721fcae46d), CONST64(0xb753e43142866273), CONST64(0xa747e03d6e9a7a53), + CONST64(0x8b60eb202bab400b), CONST64(0x7aea90ad59d747f4), CONST64(0xaa0ea4f1b85bff49), CONST64(0x78661e22d25a44f0), + CONST64(0x2eab8592cebc395c), CONST64(0x9dfd60a0873d5d27), CONST64(0x0000000000000000), CONST64(0x94b1256f5afbde35), + CONST64(0xf703f401f2f602f3), CONST64(0xe312f10ed5ed1cdb), CONST64(0x6afe94a175cb5fd4), CONST64(0x2c270b1d45313a58), + CONST64(0xbb5ce7345f8f686b), CONST64(0xc9bc759f1056238f), CONST64(0x9b74ef2c07b7582b), CONST64(0xd0e4345ce18cb8bd), + CONST64(0xc4f53153c697a695), CONST64(0x77a3d4618f16c2ee), CONST64(0x67b7d06da30adace), CONST64(0x22a48697d3b53344), + CONST64(0xe59b7e82556719d7), CONST64(0x8e23adeaeb64c901), CONST64(0xd32efd1aa1c934bb), CONST64(0xa48d297b2edff655), + CONST64(0xc0f03050cd90a09d), CONST64(0xecd73b4d88a19ac5), CONST64(0x46d99fbc30fa658c), CONST64(0xc73ff81586d22a93), + CONST64(0x3ff9c6572968ae7e), CONST64(0x4c5f1335ad796a98), CONST64(0x181e060a3a121430), CONST64(0x1411050f271b1e28), + CONST64(0x33f6c5523461a466), CONST64(0x44551133bb776688), CONST64(0xc1b6779906582f9f), CONST64(0xed917c84436915c7), + CONST64(0xf58f7a8e797b01f7), CONST64(0xfd8578886f750de7), CONST64(0xd8ee365af782b4ad), CONST64(0x706c1c24c45448e0), + CONST64(0xe4dd394b9eaf96d5), CONST64(0x792059eb1992cbf2), CONST64(0x60781828e84850c0), CONST64(0x451356fa70bfe98a), + CONST64(0xf645b3c8393e8df1), CONST64(0xfa4ab0cd243787e9), CONST64(0x90b4246c51fcd83d), CONST64(0x80a020607de0c01d), + CONST64(0xf240b2cb32398bf9), CONST64(0x72e092ab4fd94be4), CONST64(0xb615a3f8894eed71), CONST64(0x27e7c05d137aba4e), + CONST64(0x0d4944ccd6c1851a), CONST64(0x95f762a691335137), CONST64(0x40501030b0706080), CONST64(0xea5eb4c1082b9fc9), + CONST64(0x2aae8491c5bb3f54), CONST64(0x115243c5e7d49722), CONST64(0x76e593a844de4dec), CONST64(0x2fedc25b0574b65e), + CONST64(0x357f4adeb4eba16a), CONST64(0xce73bdda5b14a981), CONST64(0x06898f8c808a050c), CONST64(0xb4992d7702c3ee75), + CONST64(0xca76bcd95013af89), CONST64(0x4ad69cb92df36f94), CONST64(0xb5df6abec90b6177), CONST64(0x1d5d40c0fadd9d3a), + CONST64(0x1bd4cf4c7a579836), CONST64(0xb210a2fb8249eb79), CONST64(0x3aba809de9a72774), CONST64(0x216e4fd193f0bf42), + CONST64(0x7c631f21d95d42f8), CONST64(0x0fc5ca435d4c861e), CONST64(0x9238aae3da71db39), CONST64(0x155742c6ecd3912a), +}; + +static const ulong64 T3[256] = { + CONST64(0x68d2d3ba016ab9bb), CONST64(0x194dfc54b1669ae5), CONST64(0x93bc712fcd1465e2), CONST64(0xb9cd9c74511b8725), + CONST64(0x0251f553a457a2f7), CONST64(0xb86b68d303bed6d0), CONST64(0xbd6f6bd204b5ded6), CONST64(0x6429d74dfe8552b3), + CONST64(0x0d5df050ad4abafd), CONST64(0x268ae9ac63e009cf), CONST64(0x830e8a8d84961c09), CONST64(0x79c6dcbf1a4d91a5), + CONST64(0xaddd90704d37a73d), CONST64(0x0755f652a35caaf1), CONST64(0xc852b39ae117a47b), CONST64(0x612dd44cf98e5ab5), + CONST64(0x658f23eaac200346), CONST64(0xa67362d51184e6c4), CONST64(0xf166a497c268cc55), CONST64(0xb2636ed10da8c6dc), + CONST64(0xffcc553399d085aa), CONST64(0x0859f351aa41b2fb), CONST64(0x2a71ed5b9c0fe2c7), CONST64(0x04a2f7a655ae59f3), + CONST64(0x815f7fde20c1befe), CONST64(0x753dd848e5a27aad), CONST64(0x329ae5a87fcc29d7), CONST64(0xc75eb699e80abc71), + CONST64(0x904b70db3be696e0), CONST64(0xfac856329edb8dac), CONST64(0x51e6c4b72215d195), CONST64(0x2bd719fcceaab332), + CONST64(0x48ab38e393734b70), CONST64(0xdc42bf9efd3b8463), CONST64(0xef7eae91d052fc41), CONST64(0xcd56b09be61cac7d), + CONST64(0x4daf3be294784376), CONST64(0x6dd6d0bb0661b1bd), CONST64(0x5819c341daf1329b), CONST64(0xcba5b26e17e55779), + CONST64(0x0baef2a55cb341f9), CONST64(0xc00b40cb4b561680), CONST64(0xdab1bd6b0cc27f67), CONST64(0xfb6ea295cc7edc59), + CONST64(0x1fbefea1409f61e1), CONST64(0x18eb08f3e3c3cb10), CONST64(0x4ffeceb1302fe181), CONST64(0x0a0806020e16100c), + CONST64(0xdb1749cc5e672e92), CONST64(0xf33751c4663f6ea2), CONST64(0x6974271d53cfe84e), CONST64(0x44503c146c9ca078), + CONST64(0xe82b58c3730e56b0), CONST64(0xf291a563349a3f57), CONST64(0x954f73da3ced9ee6), CONST64(0x3469e75d8e35d2d3), + CONST64(0x3e61e15f8023c2df), CONST64(0x8b5779dc2ed7aef2), CONST64(0x94e9877d6e48cf13), CONST64(0xde134acd596c2694), + CONST64(0x9ee1817f605edf1f), CONST64(0x2f75ee5a9b04eac1), CONST64(0xc1adb46c19f34775), CONST64(0x316de45c893edad5), + CONST64(0x0cfb04f7ffefeb08), CONST64(0xbe986a26f2472dd4), CONST64(0x24db1cffc7b7ab38), CONST64(0x7e932aedb9113b54), + CONST64(0x6f8725e8a236134a), CONST64(0xd34eba9df4269c69), CONST64(0xcea1b16f10ee5f7f), CONST64(0x8c028f8e8d8b0403), + CONST64(0x7d642b194fe3c856), CONST64(0x1abafda0479469e7), CONST64(0x17e70df0eaded31a), CONST64(0x971e868998ba3c11), + CONST64(0x333c110f2d697822), CONST64(0x1b1c090715313812), CONST64(0x2986ecaf6afd11c5), CONST64(0x30cb10fbdb9b8b20), + CONST64(0x2820180838584030), CONST64(0x41543f156b97a87e), CONST64(0x3934170d237f682e), CONST64(0x14100c041c2c2018), + CONST64(0x05040301070b0806), CONST64(0xe98dac6421ab0745), CONST64(0x845b7cdf27cab6f8), CONST64(0xb3c59a765f0d9729), + CONST64(0x80f98b797264ef0b), CONST64(0x8e537add29dca6f4), CONST64(0xc9f4473db3b2f58e), CONST64(0x4e583a16628ab074), + CONST64(0xc3fc413fbda4e582), CONST64(0xebdc593785fca5b2), CONST64(0xc4a9b76d1ef84f73), CONST64(0xd8e04838a895dd90), + CONST64(0x67ded6b90877a1b1), CONST64(0xa2d19573442abf37), CONST64(0x6a8326e9a53d1b4c), CONST64(0xe1d45f358beab5be), + CONST64(0x1c49ff55b66d92e3), CONST64(0xa8d993714a3caf3b), CONST64(0x8af18d7b7c72ff07), CONST64(0x860a898c839d140f), + CONST64(0xa7d596724321b731), CONST64(0x921a85889fb13417), CONST64(0x09ff07f6f8e4e30e), CONST64(0x82a87e2ad6334dfc), + CONST64(0xc6f8423ebaafed84), CONST64(0x3b65e25e8728cad9), CONST64(0xbb9c6927f54c25d2), CONST64(0x4305ca46cfc00a89), + CONST64(0x3c30140c24746028), CONST64(0xec89af6526a00f43), CONST64(0xd5bdb86805df676d), CONST64(0xf899a3613a8c2f5b), + CONST64(0x0f0c0503091d180a), CONST64(0xe2235ec17d1846bc), CONST64(0x1641f957b87b82ef), CONST64(0xa97f67d61899fece), + CONST64(0x9a4376d935f086ec), CONST64(0x257de8589512facd), CONST64(0x9f4775d832fb8eea), CONST64(0xe385aa662fbd1749), + CONST64(0xac7b64d71f92f6c8), CONST64(0xd2e84e3aa683cd9c), CONST64(0xcf0745c8424b0e8a), CONST64(0xccf0443cb4b9fd88), + CONST64(0x35cf13fadc908326), CONST64(0xf462a796c563c453), CONST64(0x01a6f4a752a551f5), CONST64(0xc25ab598ef01b477), + CONST64(0x7b9729ecbe1a3352), CONST64(0x62dad5b80f7ca9b7), CONST64(0xfc3b54c76f2276a8), CONST64(0x2c82efae6df619c3), + CONST64(0xd0b9bb6902d46f6b), CONST64(0x7a31dd4becbf62a7), CONST64(0x3d96e0ab76d131dd), CONST64(0x379ee6a978c721d1), + CONST64(0xe681a96728b61f4f), CONST64(0x22281e0a364e503c), CONST64(0x4601c947c8cb028f), CONST64(0x1def0bf2e4c8c316), + CONST64(0x5beec2b52c03c199), CONST64(0xaa886622ee6b0dcc), CONST64(0x56b332e581497b64), CONST64(0x719f2feeb00c235e), + CONST64(0x7cc2dfbe1d4699a3), CONST64(0x87ac7d2bd13845fa), CONST64(0xbf3e9e81a0e27c21), CONST64(0x5a4836127ea6906c), + CONST64(0xb5369883aef46c2d), CONST64(0x776c2d1b41f5d85a), CONST64(0x3638120e2a627024), CONST64(0xaf8c6523e96005ca), + CONST64(0x06f302f5f1f9fb04), CONST64(0x4c09cf45c6dd1283), CONST64(0xa5846321e77615c6), CONST64(0xd11f4fce50713e9e), + CONST64(0x7039db49e2a972ab), CONST64(0x9cb0742cc4097de8), CONST64(0x3ac316f9d58d9b2c), CONST64(0x59bf37e68854636e), + CONST64(0x54e2c7b6251ed993), CONST64(0x88a07828d8255df0), CONST64(0x4b5c39176581b872), CONST64(0xb0329b82a9ff642b), + CONST64(0x72682e1a46fed05c), CONST64(0x9d16808b96ac2c1d), CONST64(0x21df1ffec0bca33e), CONST64(0x9812838a91a7241b), + CONST64(0x2d241b093f534836), CONST64(0xca0346c94540068c), CONST64(0xa1269487b2d84c35), CONST64(0x6b25d24ef7984ab9), + CONST64(0x42a33ee19d655b7c), CONST64(0x96b8722eca1f6de4), CONST64(0x53b731e486427362), CONST64(0x47a73de09a6e537a), + CONST64(0x608b20ebab2b0b40), CONST64(0xea7aad90d759f447), CONST64(0x0eaaf1a45bb849ff), CONST64(0x6678221e5ad2f044), + CONST64(0xab2e9285bcce5c39), CONST64(0xfd9da0603d87275d), CONST64(0x0000000000000000), CONST64(0xb1946f25fb5a35de), + CONST64(0x03f701f4f6f2f302), CONST64(0x12e30ef1edd5db1c), CONST64(0xfe6aa194cb75d45f), CONST64(0x272c1d0b3145583a), + CONST64(0x5cbb34e78f5f6b68), CONST64(0xbcc99f7556108f23), CONST64(0x749b2cefb7072b58), CONST64(0xe4d05c348ce1bdb8), + CONST64(0xf5c4533197c695a6), CONST64(0xa37761d4168feec2), CONST64(0xb7676dd00aa3ceda), CONST64(0xa4229786b5d34433), + CONST64(0x9be5827e6755d719), CONST64(0x238eeaad64eb01c9), CONST64(0x2ed31afdc9a1bb34), CONST64(0x8da47b29df2e55f6), + CONST64(0xf0c0503090cd9da0), CONST64(0xd7ec4d3ba188c59a), CONST64(0xd946bc9ffa308c65), CONST64(0x3fc715f8d286932a), + CONST64(0xf93f57c668297eae), CONST64(0x5f4c351379ad986a), CONST64(0x1e180a06123a3014), CONST64(0x11140f051b27281e), + CONST64(0xf63352c5613466a4), CONST64(0x5544331177bb8866), CONST64(0xb6c1997758069f2f), CONST64(0x91ed847c6943c715), + CONST64(0x8ff58e7a7b79f701), CONST64(0x85fd8878756fe70d), CONST64(0xeed85a3682f7adb4), CONST64(0x6c70241c54c4e048), + CONST64(0xdde44b39af9ed596), CONST64(0x2079eb599219f2cb), CONST64(0x7860281848e8c050), CONST64(0x1345fa56bf708ae9), + CONST64(0x45f6c8b33e39f18d), CONST64(0x4afacdb03724e987), CONST64(0xb4906c24fc513dd8), CONST64(0xa0806020e07d1dc0), + CONST64(0x40f2cbb23932f98b), CONST64(0xe072ab92d94fe44b), CONST64(0x15b6f8a34e8971ed), CONST64(0xe7275dc07a134eba), + CONST64(0x490dcc44c1d61a85), CONST64(0xf795a66233913751), CONST64(0x5040301070b08060), CONST64(0x5eeac1b42b08c99f), + CONST64(0xae2a9184bbc5543f), CONST64(0x5211c543d4e72297), CONST64(0xe576a893de44ec4d), CONST64(0xed2f5bc274055eb6), + CONST64(0x7f35de4aebb46aa1), CONST64(0x73cedabd145b81a9), CONST64(0x89068c8f8a800c05), CONST64(0x99b4772dc30275ee), + CONST64(0x76cad9bc135089af), CONST64(0xd64ab99cf32d946f), CONST64(0xdfb5be6a0bc97761), CONST64(0x5d1dc040ddfa3a9d), + CONST64(0xd41b4ccf577a3698), CONST64(0x10b2fba2498279eb), CONST64(0xba3a9d80a7e97427), CONST64(0x6e21d14ff09342bf), + CONST64(0x637c211f5dd9f842), CONST64(0xc50f43ca4c5d1e86), CONST64(0x3892e3aa71da39db), CONST64(0x5715c642d3ec2a91), +}; + +static const ulong64 T4[256] = { + CONST64(0xbbb96a01bad3d268), CONST64(0xe59a66b154fc4d19), CONST64(0xe26514cd2f71bc93), CONST64(0x25871b51749ccdb9), + CONST64(0xf7a257a453f55102), CONST64(0xd0d6be03d3686bb8), CONST64(0xd6deb504d26b6fbd), CONST64(0xb35285fe4dd72964), + CONST64(0xfdba4aad50f05d0d), CONST64(0xcf09e063ace98a26), CONST64(0x091c96848d8a0e83), CONST64(0xa5914d1abfdcc679), + CONST64(0x3da7374d7090ddad), CONST64(0xf1aa5ca352f65507), CONST64(0x7ba417e19ab352c8), CONST64(0xb55a8ef94cd42d61), + CONST64(0x460320acea238f65), CONST64(0xc4e68411d56273a6), CONST64(0x55cc68c297a466f1), CONST64(0xdcc6a80dd16e63b2), + CONST64(0xaa85d0993355ccff), CONST64(0xfbb241aa51f35908), CONST64(0xc7e20f9c5bed712a), CONST64(0xf359ae55a6f7a204), + CONST64(0xfebec120de7f5f81), CONST64(0xad7aa2e548d83d75), CONST64(0xd729cc7fa8e59a32), CONST64(0x71bc0ae899b65ec7), + CONST64(0xe096e63bdb704b90), CONST64(0xac8ddb9e3256c8fa), CONST64(0x95d11522b7c4e651), CONST64(0x32b3aacefc19d72b), + CONST64(0x704b7393e338ab48), CONST64(0x63843bfd9ebf42dc), CONST64(0x41fc52d091ae7eef), CONST64(0x7dac1ce69bb056cd), + CONST64(0x76437894e23baf4d), CONST64(0xbdb16106bbd0d66d), CONST64(0x9b32f1da41c31958), CONST64(0x7957e5176eb2a5cb), + CONST64(0xf941b35ca5f2ae0b), CONST64(0x8016564bcb400bc0), CONST64(0x677fc20c6bbdb1da), CONST64(0x59dc7ecc95a26efb), + CONST64(0xe1619f40a1febe1f), CONST64(0x10cbc3e3f308eb18), CONST64(0x81e12f30b1cefe4f), CONST64(0x0c10160e0206080a), + CONST64(0x922e675ecc4917db), CONST64(0xa26e3f66c45137f3), CONST64(0x4ee8cf531d277469), CONST64(0x78a09c6c143c5044), + CONST64(0xb0560e73c3582be8), CONST64(0x573f9a3463a591f2), CONST64(0xe69eed3cda734f95), CONST64(0xd3d2358e5de76934), + CONST64(0xdfc223805fe1613e), CONST64(0xf2aed72edc79578b), CONST64(0x13cf486e7d87e994), CONST64(0x94266c59cd4a13de), + CONST64(0x1fdf5e607f81e19e), CONST64(0xc1ea049b5aee752f), CONST64(0x7547f3196cb4adc1), CONST64(0xd5da3e895ce46d31), + CONST64(0x08ebeffff704fb0c), CONST64(0xd42d47f2266a98be), CONST64(0x38abb7c7ff1cdb24), CONST64(0x543b11b9ed2a937e), + CONST64(0x4a1336a2e825876f), CONST64(0x699c26f49dba4ed3), CONST64(0x7f5fee106fb1a1ce), CONST64(0x03048b8d8e8f028c), + CONST64(0x56c8e34f192b647d), CONST64(0xe7699447a0fdba1a), CONST64(0x1ad3deeaf00de717), CONST64(0x113cba9889861e97), + CONST64(0x2278692d0f113c33), CONST64(0x1238311507091c1b), CONST64(0xc511fd6aafec8629), CONST64(0x208b9bdbfb10cb30), + CONST64(0x3040583808182028), CONST64(0x7ea8976b153f5441), CONST64(0x2e687f230d173439), CONST64(0x18202c1c040c1014), + CONST64(0x06080b0701030405), CONST64(0x4507ab2164ac8de9), CONST64(0xf8b6ca27df7c5b84), CONST64(0x29970d5f769ac5b3), + CONST64(0x0bef6472798bf980), CONST64(0xf4a6dc29dd7a538e), CONST64(0x8ef5b2b33d47f4c9), CONST64(0x74b08a62163a584e), + CONST64(0x82e5a4bd3f41fcc3), CONST64(0xb2a5fc853759dceb), CONST64(0x734ff81e6db7a9c4), CONST64(0x90dd95a83848e0d8), + CONST64(0xb1a17708b9d6de67), CONST64(0x37bf2a447395d1a2), CONST64(0x4c1b3da5e926836a), CONST64(0xbeb5ea8b355fd4e1), + CONST64(0xe3926db655ff491c), CONST64(0x3baf3c4a7193d9a8), CONST64(0x07ff727c7b8df18a), CONST64(0x0f149d838c890a86), + CONST64(0x31b721437296d5a7), CONST64(0x1734b19f88851a92), CONST64(0x0ee3e4f8f607ff09), CONST64(0xfc4d33d62a7ea882), + CONST64(0x84edafba3e42f8c6), CONST64(0xd9ca28875ee2653b), CONST64(0xd2254cf527699cbb), CONST64(0x890ac0cf46ca0543), + CONST64(0x286074240c14303c), CONST64(0x430fa02665af89ec), CONST64(0x6d67df0568b8bdd5), CONST64(0x5b2f8c3a61a399f8), + CONST64(0x0a181d0903050c0f), CONST64(0xbc46187dc15e23e2), CONST64(0xef827bb857f94116), CONST64(0xcefe9918d6677fa9), + CONST64(0xec86f035d976439a), CONST64(0xcdfa129558e87d25), CONST64(0xea8efb32d875479f), CONST64(0x4917bd2f66aa85e3), + CONST64(0xc8f6921fd7647bac), CONST64(0x9ccd83a63a4ee8d2), CONST64(0x8a0e4b42c84507cf), CONST64(0x88fdb9b43c44f0cc), + CONST64(0x268390dcfa13cf35), CONST64(0x53c463c596a762f4), CONST64(0xf551a552a7f4a601), CONST64(0x77b401ef98b55ac2), + CONST64(0x52331abeec29977b), CONST64(0xb7a97c0fb8d5da62), CONST64(0xa876226fc7543bfc), CONST64(0xc319f66daeef822c), + CONST64(0x6b6fd40269bbb9d0), CONST64(0xa762bfec4bdd317a), CONST64(0xdd31d176abe0963d), CONST64(0xd121c778a9e69e37), + CONST64(0x4f1fb62867a981e6), CONST64(0x3c504e360a1e2822), CONST64(0x8f02cbc847c90146), CONST64(0x16c3c8e4f20bef1d), + CONST64(0x99c1032cb5c2ee5b), CONST64(0xcc0d6bee226688aa), CONST64(0x647b4981e532b356), CONST64(0x5e230cb0ee2f9f71), + CONST64(0xa399461dbedfc27c), CONST64(0xfa4538d12b7dac87), CONST64(0x217ce2a0819e3ebf), CONST64(0x6c90a67e1236485a), + CONST64(0x2d6cf4ae839836b5), CONST64(0x5ad8f5411b2d6c77), CONST64(0x2470622a0e123836), CONST64(0xca0560e923658caf), + CONST64(0x04fbf9f1f502f306), CONST64(0x8312ddc645cf094c), CONST64(0xc61576e7216384a5), CONST64(0x9e3e7150ce4f1fd1), + CONST64(0xab72a9e249db3970), CONST64(0xe87d09c42c74b09c), CONST64(0x2c9b8dd5f916c33a), CONST64(0x6e635488e637bf59), + CONST64(0x93d91e25b6c7e254), CONST64(0xf05d25d82878a088), CONST64(0x72b8816517395c4b), CONST64(0x2b64ffa9829b32b0), + CONST64(0x5cd0fe461a2e6872), CONST64(0x1d2cac968b80169d), CONST64(0x3ea3bcc0fe1fdf21), CONST64(0x1b24a7918a831298), + CONST64(0x3648533f091b242d), CONST64(0x8c064045c94603ca), CONST64(0x354cd8b2879426a1), CONST64(0xb94a98f74ed2256b), + CONST64(0x7c5b659de13ea342), CONST64(0xe46d1fca2e72b896), CONST64(0x62734286e431b753), CONST64(0x7a536e9ae03da747), + CONST64(0x400b2babeb208b60), CONST64(0x47f459d790ad7aea), CONST64(0xff49b85ba4f1aa0e), CONST64(0x44f0d25a1e227866), + CONST64(0x395ccebc85922eab), CONST64(0x5d27873d60a09dfd), CONST64(0x0000000000000000), CONST64(0xde355afb256f94b1), + CONST64(0x02f3f2f6f401f703), CONST64(0x1cdbd5edf10ee312), CONST64(0x5fd475cb94a16afe), CONST64(0x3a5845310b1d2c27), + CONST64(0x686b5f8fe734bb5c), CONST64(0x238f1056759fc9bc), CONST64(0x582b07b7ef2c9b74), CONST64(0xb8bde18c345cd0e4), + CONST64(0xa695c6973153c4f5), CONST64(0xc2ee8f16d46177a3), CONST64(0xdacea30ad06d67b7), CONST64(0x3344d3b5869722a4), + CONST64(0x19d755677e82e59b), CONST64(0xc901eb64adea8e23), CONST64(0x34bba1c9fd1ad32e), CONST64(0xf6552edf297ba48d), + CONST64(0xa09dcd903050c0f0), CONST64(0x9ac588a13b4decd7), CONST64(0x658c30fa9fbc46d9), CONST64(0x2a9386d2f815c73f), + CONST64(0xae7e2968c6573ff9), CONST64(0x6a98ad7913354c5f), CONST64(0x14303a12060a181e), CONST64(0x1e28271b050f1411), + CONST64(0xa4663461c55233f6), CONST64(0x6688bb7711334455), CONST64(0x2f9f06587799c1b6), CONST64(0x15c743697c84ed91), + CONST64(0x01f7797b7a8ef58f), CONST64(0x0de76f757888fd85), CONST64(0xb4adf782365ad8ee), CONST64(0x48e0c4541c24706c), + CONST64(0x96d59eaf394be4dd), CONST64(0xcbf2199259eb7920), CONST64(0x50c0e84818286078), CONST64(0xe98a70bf56fa4513), + CONST64(0x8df1393eb3c8f645), CONST64(0x87e92437b0cdfa4a), CONST64(0xd83d51fc246c90b4), CONST64(0xc01d7de0206080a0), + CONST64(0x8bf93239b2cbf240), CONST64(0x4be44fd992ab72e0), CONST64(0xed71894ea3f8b615), CONST64(0xba4e137ac05d27e7), + CONST64(0x851ad6c144cc0d49), CONST64(0x5137913362a695f7), CONST64(0x6080b07010304050), CONST64(0x9fc9082bb4c1ea5e), + CONST64(0x3f54c5bb84912aae), CONST64(0x9722e7d443c51152), CONST64(0x4dec44de93a876e5), CONST64(0xb65e0574c25b2fed), + CONST64(0xa16ab4eb4ade357f), CONST64(0xa9815b14bddace73), CONST64(0x050c808a8f8c0689), CONST64(0xee7502c32d77b499), + CONST64(0xaf895013bcd9ca76), CONST64(0x6f942df39cb94ad6), CONST64(0x6177c90b6abeb5df), CONST64(0x9d3afadd40c01d5d), + CONST64(0x98367a57cf4c1bd4), CONST64(0xeb798249a2fbb210), CONST64(0x2774e9a7809d3aba), CONST64(0xbf4293f04fd1216e), + CONST64(0x42f8d95d1f217c63), CONST64(0x861e5d4cca430fc5), CONST64(0xdb39da71aae39238), CONST64(0x912aecd342c61557), +}; + +static const ulong64 T5[256] = { + CONST64(0xb9bb016ad3ba68d2), CONST64(0x9ae5b166fc54194d), CONST64(0x65e2cd14712f93bc), CONST64(0x8725511b9c74b9cd), + CONST64(0xa2f7a457f5530251), CONST64(0xd6d003be68d3b86b), CONST64(0xded604b56bd2bd6f), CONST64(0x52b3fe85d74d6429), + CONST64(0xbafdad4af0500d5d), CONST64(0x09cf63e0e9ac268a), CONST64(0x1c0984968a8d830e), CONST64(0x91a51a4ddcbf79c6), + CONST64(0xa73d4d379070addd), CONST64(0xaaf1a35cf6520755), CONST64(0xa47be117b39ac852), CONST64(0x5ab5f98ed44c612d), + CONST64(0x0346ac2023ea658f), CONST64(0xe6c4118462d5a673), CONST64(0xcc55c268a497f166), CONST64(0xc6dc0da86ed1b263), + CONST64(0x85aa99d05533ffcc), CONST64(0xb2fbaa41f3510859), CONST64(0xe2c79c0fed5b2a71), CONST64(0x59f355aef7a604a2), + CONST64(0xbefe20c17fde815f), CONST64(0x7aade5a2d848753d), CONST64(0x29d77fcce5a8329a), CONST64(0xbc71e80ab699c75e), + CONST64(0x96e03be670db904b), CONST64(0x8dac9edb5632fac8), CONST64(0xd1952215c4b751e6), CONST64(0xb332ceaa19fc2bd7), + CONST64(0x4b70937338e348ab), CONST64(0x8463fd3bbf9edc42), CONST64(0xfc41d052ae91ef7e), CONST64(0xac7de61cb09bcd56), + CONST64(0x437694783be24daf), CONST64(0xb1bd0661d0bb6dd6), CONST64(0x329bdaf1c3415819), CONST64(0x577917e5b26ecba5), + CONST64(0x41f95cb3f2a50bae), CONST64(0x16804b5640cbc00b), CONST64(0x7f670cc2bd6bdab1), CONST64(0xdc59cc7ea295fb6e), + CONST64(0x61e1409ffea11fbe), CONST64(0xcb10e3c308f318eb), CONST64(0xe181302fceb14ffe), CONST64(0x100c0e1606020a08), + CONST64(0x2e925e6749ccdb17), CONST64(0x6ea2663f51c4f337), CONST64(0xe84e53cf271d6974), CONST64(0xa0786c9c3c144450), + CONST64(0x56b0730e58c3e82b), CONST64(0x3f57349aa563f291), CONST64(0x9ee63ced73da954f), CONST64(0xd2d38e35e75d3469), + CONST64(0xc2df8023e15f3e61), CONST64(0xaef22ed779dc8b57), CONST64(0xcf136e48877d94e9), CONST64(0x2694596c4acdde13), + CONST64(0xdf1f605e817f9ee1), CONST64(0xeac19b04ee5a2f75), CONST64(0x477519f3b46cc1ad), CONST64(0xdad5893ee45c316d), + CONST64(0xeb08ffef04f70cfb), CONST64(0x2dd4f2476a26be98), CONST64(0xab38c7b71cff24db), CONST64(0x3b54b9112aed7e93), + CONST64(0x134aa23625e86f87), CONST64(0x9c69f426ba9dd34e), CONST64(0x5f7f10eeb16fcea1), CONST64(0x04038d8b8f8e8c02), + CONST64(0xc8564fe32b197d64), CONST64(0x69e74794fda01aba), CONST64(0xd31aeade0df017e7), CONST64(0x3c1198ba8689971e), + CONST64(0x78222d69110f333c), CONST64(0x3812153109071b1c), CONST64(0x11c56afdecaf2986), CONST64(0x8b20db9b10fb30cb), + CONST64(0x4030385818082820), CONST64(0xa87e6b973f154154), CONST64(0x682e237f170d3934), CONST64(0x20181c2c0c041410), + CONST64(0x0806070b03010504), CONST64(0x074521abac64e98d), CONST64(0xb6f827ca7cdf845b), CONST64(0x97295f0d9a76b3c5), + CONST64(0xef0b72648b7980f9), CONST64(0xa6f429dc7add8e53), CONST64(0xf58eb3b2473dc9f4), CONST64(0xb074628a3a164e58), + CONST64(0xe582bda4413fc3fc), CONST64(0xa5b285fc5937ebdc), CONST64(0x4f731ef8b76dc4a9), CONST64(0xdd90a8954838d8e0), + CONST64(0xa1b10877d6b967de), CONST64(0xbf37442a9573a2d1), CONST64(0x1b4ca53d26e96a83), CONST64(0xb5be8bea5f35e1d4), + CONST64(0x92e3b66dff551c49), CONST64(0xaf3b4a3c9371a8d9), CONST64(0xff077c728d7b8af1), CONST64(0x140f839d898c860a), + CONST64(0xb73143219672a7d5), CONST64(0x34179fb18588921a), CONST64(0xe30ef8e407f609ff), CONST64(0x4dfcd6337e2a82a8), + CONST64(0xed84baaf423ec6f8), CONST64(0xcad98728e25e3b65), CONST64(0x25d2f54c6927bb9c), CONST64(0x0a89cfc0ca464305), + CONST64(0x60282474140c3c30), CONST64(0x0f4326a0af65ec89), CONST64(0x676d05dfb868d5bd), CONST64(0x2f5b3a8ca361f899), + CONST64(0x180a091d05030f0c), CONST64(0x46bc7d185ec1e223), CONST64(0x82efb87bf9571641), CONST64(0xfece189967d6a97f), + CONST64(0x86ec35f076d99a43), CONST64(0xfacd9512e858257d), CONST64(0x8eea32fb75d89f47), CONST64(0x17492fbdaa66e385), + CONST64(0xf6c81f9264d7ac7b), CONST64(0xcd9ca6834e3ad2e8), CONST64(0x0e8a424b45c8cf07), CONST64(0xfd88b4b9443cccf0), + CONST64(0x8326dc9013fa35cf), CONST64(0xc453c563a796f462), CONST64(0x51f552a5f4a701a6), CONST64(0xb477ef01b598c25a), + CONST64(0x3352be1a29ec7b97), CONST64(0xa9b70f7cd5b862da), CONST64(0x76a86f2254c7fc3b), CONST64(0x19c36df6efae2c82), + CONST64(0x6f6b02d4bb69d0b9), CONST64(0x62a7ecbfdd4b7a31), CONST64(0x31dd76d1e0ab3d96), CONST64(0x21d178c7e6a9379e), + CONST64(0x1f4f28b6a967e681), CONST64(0x503c364e1e0a2228), CONST64(0x028fc8cbc9474601), CONST64(0xc316e4c80bf21def), + CONST64(0xc1992c03c2b55bee), CONST64(0x0dccee6b6622aa88), CONST64(0x7b64814932e556b3), CONST64(0x235eb00c2fee719f), + CONST64(0x99a31d46dfbe7cc2), CONST64(0x45fad1387d2b87ac), CONST64(0x7c21a0e29e81bf3e), CONST64(0x906c7ea636125a48), + CONST64(0x6c2daef49883b536), CONST64(0xd85a41f52d1b776c), CONST64(0x70242a62120e3638), CONST64(0x05cae9606523af8c), + CONST64(0xfb04f1f902f506f3), CONST64(0x1283c6ddcf454c09), CONST64(0x15c6e7766321a584), CONST64(0x3e9e50714fced11f), + CONST64(0x72abe2a9db497039), CONST64(0x7de8c409742c9cb0), CONST64(0x9b2cd58d16f93ac3), CONST64(0x636e885437e659bf), + CONST64(0xd993251ec7b654e2), CONST64(0x5df0d825782888a0), CONST64(0xb872658139174b5c), CONST64(0x642ba9ff9b82b032), + CONST64(0xd05c46fe2e1a7268), CONST64(0x2c1d96ac808b9d16), CONST64(0xa33ec0bc1ffe21df), CONST64(0x241b91a7838a9812), + CONST64(0x48363f531b092d24), CONST64(0x068c454046c9ca03), CONST64(0x4c35b2d89487a126), CONST64(0x4ab9f798d24e6b25), + CONST64(0x5b7c9d653ee142a3), CONST64(0x6de4ca1f722e96b8), CONST64(0x7362864231e453b7), CONST64(0x537a9a6e3de047a7), + CONST64(0x0b40ab2b20eb608b), CONST64(0xf447d759ad90ea7a), CONST64(0x49ff5bb8f1a40eaa), CONST64(0xf0445ad2221e6678), + CONST64(0x5c39bcce9285ab2e), CONST64(0x275d3d87a060fd9d), CONST64(0x0000000000000000), CONST64(0x35defb5a6f25b194), + CONST64(0xf302f6f201f403f7), CONST64(0xdb1cedd50ef112e3), CONST64(0xd45fcb75a194fe6a), CONST64(0x583a31451d0b272c), + CONST64(0x6b688f5f34e75cbb), CONST64(0x8f2356109f75bcc9), CONST64(0x2b58b7072cef749b), CONST64(0xbdb88ce15c34e4d0), + CONST64(0x95a697c65331f5c4), CONST64(0xeec2168f61d4a377), CONST64(0xceda0aa36dd0b767), CONST64(0x4433b5d39786a422), + CONST64(0xd7196755827e9be5), CONST64(0x01c964ebeaad238e), CONST64(0xbb34c9a11afd2ed3), CONST64(0x55f6df2e7b298da4), + CONST64(0x9da090cd5030f0c0), CONST64(0xc59aa1884d3bd7ec), CONST64(0x8c65fa30bc9fd946), CONST64(0x932ad28615f83fc7), + CONST64(0x7eae682957c6f93f), CONST64(0x986a79ad35135f4c), CONST64(0x3014123a0a061e18), CONST64(0x281e1b270f051114), + CONST64(0x66a4613452c5f633), CONST64(0x886677bb33115544), CONST64(0x9f2f58069977b6c1), CONST64(0xc7156943847c91ed), + CONST64(0xf7017b798e7a8ff5), CONST64(0xe70d756f887885fd), CONST64(0xadb482f75a36eed8), CONST64(0xe04854c4241c6c70), + CONST64(0xd596af9e4b39dde4), CONST64(0xf2cb9219eb592079), CONST64(0xc05048e828187860), CONST64(0x8ae9bf70fa561345), + CONST64(0xf18d3e39c8b345f6), CONST64(0xe9873724cdb04afa), CONST64(0x3dd8fc516c24b490), CONST64(0x1dc0e07d6020a080), + CONST64(0xf98b3932cbb240f2), CONST64(0xe44bd94fab92e072), CONST64(0x71ed4e89f8a315b6), CONST64(0x4eba7a135dc0e727), + CONST64(0x1a85c1d6cc44490d), CONST64(0x37513391a662f795), CONST64(0x806070b030105040), CONST64(0xc99f2b08c1b45eea), + CONST64(0x543fbbc59184ae2a), CONST64(0x2297d4e7c5435211), CONST64(0xec4dde44a893e576), CONST64(0x5eb674055bc2ed2f), + CONST64(0x6aa1ebb4de4a7f35), CONST64(0x81a9145bdabd73ce), CONST64(0x0c058a808c8f8906), CONST64(0x75eec302772d99b4), + CONST64(0x89af1350d9bc76ca), CONST64(0x946ff32db99cd64a), CONST64(0x77610bc9be6adfb5), CONST64(0x3a9dddfac0405d1d), + CONST64(0x3698577a4ccfd41b), CONST64(0x79eb4982fba210b2), CONST64(0x7427a7e99d80ba3a), CONST64(0x42bff093d14f6e21), + CONST64(0xf8425dd9211f637c), CONST64(0x1e864c5d43cac50f), CONST64(0x39db71dae3aa3892), CONST64(0x2a91d3ecc6425715), +}; + +static const ulong64 T6[256] = { + CONST64(0x6a01bbb9d268bad3), CONST64(0x66b1e59a4d1954fc), CONST64(0x14cde265bc932f71), CONST64(0x1b512587cdb9749c), + CONST64(0x57a4f7a2510253f5), CONST64(0xbe03d0d66bb8d368), CONST64(0xb504d6de6fbdd26b), CONST64(0x85feb35229644dd7), + CONST64(0x4aadfdba5d0d50f0), CONST64(0xe063cf098a26ace9), CONST64(0x9684091c0e838d8a), CONST64(0x4d1aa591c679bfdc), + CONST64(0x374d3da7ddad7090), CONST64(0x5ca3f1aa550752f6), CONST64(0x17e17ba452c89ab3), CONST64(0x8ef9b55a2d614cd4), + CONST64(0x20ac46038f65ea23), CONST64(0x8411c4e673a6d562), CONST64(0x68c255cc66f197a4), CONST64(0xa80ddcc663b2d16e), + CONST64(0xd099aa85ccff3355), CONST64(0x41aafbb2590851f3), CONST64(0x0f9cc7e2712a5bed), CONST64(0xae55f359a204a6f7), + CONST64(0xc120febe5f81de7f), CONST64(0xa2e5ad7a3d7548d8), CONST64(0xcc7fd7299a32a8e5), CONST64(0x0ae871bc5ec799b6), + CONST64(0xe63be0964b90db70), CONST64(0xdb9eac8dc8fa3256), CONST64(0x152295d1e651b7c4), CONST64(0xaace32b3d72bfc19), + CONST64(0x7393704bab48e338), CONST64(0x3bfd638442dc9ebf), CONST64(0x52d041fc7eef91ae), CONST64(0x1ce67dac56cd9bb0), + CONST64(0x78947643af4de23b), CONST64(0x6106bdb1d66dbbd0), CONST64(0xf1da9b32195841c3), CONST64(0xe5177957a5cb6eb2), + CONST64(0xb35cf941ae0ba5f2), CONST64(0x564b80160bc0cb40), CONST64(0xc20c677fb1da6bbd), CONST64(0x7ecc59dc6efb95a2), + CONST64(0x9f40e161be1fa1fe), CONST64(0xc3e310cbeb18f308), CONST64(0x2f3081e1fe4fb1ce), CONST64(0x160e0c10080a0206), + CONST64(0x675e922e17dbcc49), CONST64(0x3f66a26e37f3c451), CONST64(0xcf534ee874691d27), CONST64(0x9c6c78a05044143c), + CONST64(0x0e73b0562be8c358), CONST64(0x9a34573f91f263a5), CONST64(0xed3ce69e4f95da73), CONST64(0x358ed3d269345de7), + CONST64(0x2380dfc2613e5fe1), CONST64(0xd72ef2ae578bdc79), CONST64(0x486e13cfe9947d87), CONST64(0x6c59942613decd4a), + CONST64(0x5e601fdfe19e7f81), CONST64(0x049bc1ea752f5aee), CONST64(0xf3197547adc16cb4), CONST64(0x3e89d5da6d315ce4), + CONST64(0xefff08ebfb0cf704), CONST64(0x47f2d42d98be266a), CONST64(0xb7c738abdb24ff1c), CONST64(0x11b9543b937eed2a), + CONST64(0x36a24a13876fe825), CONST64(0x26f4699c4ed39dba), CONST64(0xee107f5fa1ce6fb1), CONST64(0x8b8d0304028c8e8f), + CONST64(0xe34f56c8647d192b), CONST64(0x9447e769ba1aa0fd), CONST64(0xdeea1ad3e717f00d), CONST64(0xba98113c1e978986), + CONST64(0x692d22783c330f11), CONST64(0x311512381c1b0709), CONST64(0xfd6ac5118629afec), CONST64(0x9bdb208bcb30fb10), + CONST64(0x5838304020280818), CONST64(0x976b7ea85441153f), CONST64(0x7f232e6834390d17), CONST64(0x2c1c18201014040c), + CONST64(0x0b07060804050103), CONST64(0xab2145078de964ac), CONST64(0xca27f8b65b84df7c), CONST64(0x0d5f2997c5b3769a), + CONST64(0x64720beff980798b), CONST64(0xdc29f4a6538edd7a), CONST64(0xb2b38ef5f4c93d47), CONST64(0x8a6274b0584e163a), + CONST64(0xa4bd82e5fcc33f41), CONST64(0xfc85b2a5dceb3759), CONST64(0xf81e734fa9c46db7), CONST64(0x95a890dde0d83848), + CONST64(0x7708b1a1de67b9d6), CONST64(0x2a4437bfd1a27395), CONST64(0x3da54c1b836ae926), CONST64(0xea8bbeb5d4e1355f), + CONST64(0x6db6e392491c55ff), CONST64(0x3c4a3bafd9a87193), CONST64(0x727c07fff18a7b8d), CONST64(0x9d830f140a868c89), + CONST64(0x214331b7d5a77296), CONST64(0xb19f17341a928885), CONST64(0xe4f80ee3ff09f607), CONST64(0x33d6fc4da8822a7e), + CONST64(0xafba84edf8c63e42), CONST64(0x2887d9ca653b5ee2), CONST64(0x4cf5d2259cbb2769), CONST64(0xc0cf890a054346ca), + CONST64(0x74242860303c0c14), CONST64(0xa026430f89ec65af), CONST64(0xdf056d67bdd568b8), CONST64(0x8c3a5b2f99f861a3), + CONST64(0x1d090a180c0f0305), CONST64(0x187dbc4623e2c15e), CONST64(0x7bb8ef82411657f9), CONST64(0x9918cefe7fa9d667), + CONST64(0xf035ec86439ad976), CONST64(0x1295cdfa7d2558e8), CONST64(0xfb32ea8e479fd875), CONST64(0xbd2f491785e366aa), + CONST64(0x921fc8f67bacd764), CONST64(0x83a69ccde8d23a4e), CONST64(0x4b428a0e07cfc845), CONST64(0xb9b488fdf0cc3c44), + CONST64(0x90dc2683cf35fa13), CONST64(0x63c553c462f496a7), CONST64(0xa552f551a601a7f4), CONST64(0x01ef77b45ac298b5), + CONST64(0x1abe5233977bec29), CONST64(0x7c0fb7a9da62b8d5), CONST64(0x226fa8763bfcc754), CONST64(0xf66dc319822caeef), + CONST64(0xd4026b6fb9d069bb), CONST64(0xbfeca762317a4bdd), CONST64(0xd176dd31963dabe0), CONST64(0xc778d1219e37a9e6), + CONST64(0xb6284f1f81e667a9), CONST64(0x4e363c5028220a1e), CONST64(0xcbc88f02014647c9), CONST64(0xc8e416c3ef1df20b), + CONST64(0x032c99c1ee5bb5c2), CONST64(0x6beecc0d88aa2266), CONST64(0x4981647bb356e532), CONST64(0x0cb05e239f71ee2f), + CONST64(0x461da399c27cbedf), CONST64(0x38d1fa45ac872b7d), CONST64(0xe2a0217c3ebf819e), CONST64(0xa67e6c90485a1236), + CONST64(0xf4ae2d6c36b58398), CONST64(0xf5415ad86c771b2d), CONST64(0x622a247038360e12), CONST64(0x60e9ca058caf2365), + CONST64(0xf9f104fbf306f502), CONST64(0xddc68312094c45cf), CONST64(0x76e7c61584a52163), CONST64(0x71509e3e1fd1ce4f), + CONST64(0xa9e2ab72397049db), CONST64(0x09c4e87db09c2c74), CONST64(0x8dd52c9bc33af916), CONST64(0x54886e63bf59e637), + CONST64(0x1e2593d9e254b6c7), CONST64(0x25d8f05da0882878), CONST64(0x816572b85c4b1739), CONST64(0xffa92b6432b0829b), + CONST64(0xfe465cd068721a2e), CONST64(0xac961d2c169d8b80), CONST64(0xbcc03ea3df21fe1f), CONST64(0xa7911b2412988a83), + CONST64(0x533f3648242d091b), CONST64(0x40458c0603cac946), CONST64(0xd8b2354c26a18794), CONST64(0x98f7b94a256b4ed2), + CONST64(0x659d7c5ba342e13e), CONST64(0x1fcae46db8962e72), CONST64(0x42866273b753e431), CONST64(0x6e9a7a53a747e03d), + CONST64(0x2bab400b8b60eb20), CONST64(0x59d747f47aea90ad), CONST64(0xb85bff49aa0ea4f1), CONST64(0xd25a44f078661e22), + CONST64(0xcebc395c2eab8592), CONST64(0x873d5d279dfd60a0), CONST64(0x0000000000000000), CONST64(0x5afbde3594b1256f), + CONST64(0xf2f602f3f703f401), CONST64(0xd5ed1cdbe312f10e), CONST64(0x75cb5fd46afe94a1), CONST64(0x45313a582c270b1d), + CONST64(0x5f8f686bbb5ce734), CONST64(0x1056238fc9bc759f), CONST64(0x07b7582b9b74ef2c), CONST64(0xe18cb8bdd0e4345c), + CONST64(0xc697a695c4f53153), CONST64(0x8f16c2ee77a3d461), CONST64(0xa30adace67b7d06d), CONST64(0xd3b5334422a48697), + CONST64(0x556719d7e59b7e82), CONST64(0xeb64c9018e23adea), CONST64(0xa1c934bbd32efd1a), CONST64(0x2edff655a48d297b), + CONST64(0xcd90a09dc0f03050), CONST64(0x88a19ac5ecd73b4d), CONST64(0x30fa658c46d99fbc), CONST64(0x86d22a93c73ff815), + CONST64(0x2968ae7e3ff9c657), CONST64(0xad796a984c5f1335), CONST64(0x3a121430181e060a), CONST64(0x271b1e281411050f), + CONST64(0x3461a46633f6c552), CONST64(0xbb77668844551133), CONST64(0x06582f9fc1b67799), CONST64(0x436915c7ed917c84), + CONST64(0x797b01f7f58f7a8e), CONST64(0x6f750de7fd857888), CONST64(0xf782b4add8ee365a), CONST64(0xc45448e0706c1c24), + CONST64(0x9eaf96d5e4dd394b), CONST64(0x1992cbf2792059eb), CONST64(0xe84850c060781828), CONST64(0x70bfe98a451356fa), + CONST64(0x393e8df1f645b3c8), CONST64(0x243787e9fa4ab0cd), CONST64(0x51fcd83d90b4246c), CONST64(0x7de0c01d80a02060), + CONST64(0x32398bf9f240b2cb), CONST64(0x4fd94be472e092ab), CONST64(0x894eed71b615a3f8), CONST64(0x137aba4e27e7c05d), + CONST64(0xd6c1851a0d4944cc), CONST64(0x9133513795f762a6), CONST64(0xb070608040501030), CONST64(0x082b9fc9ea5eb4c1), + CONST64(0xc5bb3f542aae8491), CONST64(0xe7d49722115243c5), CONST64(0x44de4dec76e593a8), CONST64(0x0574b65e2fedc25b), + CONST64(0xb4eba16a357f4ade), CONST64(0x5b14a981ce73bdda), CONST64(0x808a050c06898f8c), CONST64(0x02c3ee75b4992d77), + CONST64(0x5013af89ca76bcd9), CONST64(0x2df36f944ad69cb9), CONST64(0xc90b6177b5df6abe), CONST64(0xfadd9d3a1d5d40c0), + CONST64(0x7a5798361bd4cf4c), CONST64(0x8249eb79b210a2fb), CONST64(0xe9a727743aba809d), CONST64(0x93f0bf42216e4fd1), + CONST64(0xd95d42f87c631f21), CONST64(0x5d4c861e0fc5ca43), CONST64(0xda71db399238aae3), CONST64(0xecd3912a155742c6), +}; + +static const ulong64 T7[256] = { + CONST64(0x016ab9bb68d2d3ba), CONST64(0xb1669ae5194dfc54), CONST64(0xcd1465e293bc712f), CONST64(0x511b8725b9cd9c74), + CONST64(0xa457a2f70251f553), CONST64(0x03bed6d0b86b68d3), CONST64(0x04b5ded6bd6f6bd2), CONST64(0xfe8552b36429d74d), + CONST64(0xad4abafd0d5df050), CONST64(0x63e009cf268ae9ac), CONST64(0x84961c09830e8a8d), CONST64(0x1a4d91a579c6dcbf), + CONST64(0x4d37a73daddd9070), CONST64(0xa35caaf10755f652), CONST64(0xe117a47bc852b39a), CONST64(0xf98e5ab5612dd44c), + CONST64(0xac200346658f23ea), CONST64(0x1184e6c4a67362d5), CONST64(0xc268cc55f166a497), CONST64(0x0da8c6dcb2636ed1), + CONST64(0x99d085aaffcc5533), CONST64(0xaa41b2fb0859f351), CONST64(0x9c0fe2c72a71ed5b), CONST64(0x55ae59f304a2f7a6), + CONST64(0x20c1befe815f7fde), CONST64(0xe5a27aad753dd848), CONST64(0x7fcc29d7329ae5a8), CONST64(0xe80abc71c75eb699), + CONST64(0x3be696e0904b70db), CONST64(0x9edb8dacfac85632), CONST64(0x2215d19551e6c4b7), CONST64(0xceaab3322bd719fc), + CONST64(0x93734b7048ab38e3), CONST64(0xfd3b8463dc42bf9e), CONST64(0xd052fc41ef7eae91), CONST64(0xe61cac7dcd56b09b), + CONST64(0x947843764daf3be2), CONST64(0x0661b1bd6dd6d0bb), CONST64(0xdaf1329b5819c341), CONST64(0x17e55779cba5b26e), + CONST64(0x5cb341f90baef2a5), CONST64(0x4b561680c00b40cb), CONST64(0x0cc27f67dab1bd6b), CONST64(0xcc7edc59fb6ea295), + CONST64(0x409f61e11fbefea1), CONST64(0xe3c3cb1018eb08f3), CONST64(0x302fe1814ffeceb1), CONST64(0x0e16100c0a080602), + CONST64(0x5e672e92db1749cc), CONST64(0x663f6ea2f33751c4), CONST64(0x53cfe84e6974271d), CONST64(0x6c9ca07844503c14), + CONST64(0x730e56b0e82b58c3), CONST64(0x349a3f57f291a563), CONST64(0x3ced9ee6954f73da), CONST64(0x8e35d2d33469e75d), + CONST64(0x8023c2df3e61e15f), CONST64(0x2ed7aef28b5779dc), CONST64(0x6e48cf1394e9877d), CONST64(0x596c2694de134acd), + CONST64(0x605edf1f9ee1817f), CONST64(0x9b04eac12f75ee5a), CONST64(0x19f34775c1adb46c), CONST64(0x893edad5316de45c), + CONST64(0xffefeb080cfb04f7), CONST64(0xf2472dd4be986a26), CONST64(0xc7b7ab3824db1cff), CONST64(0xb9113b547e932aed), + CONST64(0xa236134a6f8725e8), CONST64(0xf4269c69d34eba9d), CONST64(0x10ee5f7fcea1b16f), CONST64(0x8d8b04038c028f8e), + CONST64(0x4fe3c8567d642b19), CONST64(0x479469e71abafda0), CONST64(0xeaded31a17e70df0), CONST64(0x98ba3c11971e8689), + CONST64(0x2d697822333c110f), CONST64(0x153138121b1c0907), CONST64(0x6afd11c52986ecaf), CONST64(0xdb9b8b2030cb10fb), + CONST64(0x3858403028201808), CONST64(0x6b97a87e41543f15), CONST64(0x237f682e3934170d), CONST64(0x1c2c201814100c04), + CONST64(0x070b080605040301), CONST64(0x21ab0745e98dac64), CONST64(0x27cab6f8845b7cdf), CONST64(0x5f0d9729b3c59a76), + CONST64(0x7264ef0b80f98b79), CONST64(0x29dca6f48e537add), CONST64(0xb3b2f58ec9f4473d), CONST64(0x628ab0744e583a16), + CONST64(0xbda4e582c3fc413f), CONST64(0x85fca5b2ebdc5937), CONST64(0x1ef84f73c4a9b76d), CONST64(0xa895dd90d8e04838), + CONST64(0x0877a1b167ded6b9), CONST64(0x442abf37a2d19573), CONST64(0xa53d1b4c6a8326e9), CONST64(0x8beab5bee1d45f35), + CONST64(0xb66d92e31c49ff55), CONST64(0x4a3caf3ba8d99371), CONST64(0x7c72ff078af18d7b), CONST64(0x839d140f860a898c), + CONST64(0x4321b731a7d59672), CONST64(0x9fb13417921a8588), CONST64(0xf8e4e30e09ff07f6), CONST64(0xd6334dfc82a87e2a), + CONST64(0xbaafed84c6f8423e), CONST64(0x8728cad93b65e25e), CONST64(0xf54c25d2bb9c6927), CONST64(0xcfc00a894305ca46), + CONST64(0x247460283c30140c), CONST64(0x26a00f43ec89af65), CONST64(0x05df676dd5bdb868), CONST64(0x3a8c2f5bf899a361), + CONST64(0x091d180a0f0c0503), CONST64(0x7d1846bce2235ec1), CONST64(0xb87b82ef1641f957), CONST64(0x1899fecea97f67d6), + CONST64(0x35f086ec9a4376d9), CONST64(0x9512facd257de858), CONST64(0x32fb8eea9f4775d8), CONST64(0x2fbd1749e385aa66), + CONST64(0x1f92f6c8ac7b64d7), CONST64(0xa683cd9cd2e84e3a), CONST64(0x424b0e8acf0745c8), CONST64(0xb4b9fd88ccf0443c), + CONST64(0xdc90832635cf13fa), CONST64(0xc563c453f462a796), CONST64(0x52a551f501a6f4a7), CONST64(0xef01b477c25ab598), + CONST64(0xbe1a33527b9729ec), CONST64(0x0f7ca9b762dad5b8), CONST64(0x6f2276a8fc3b54c7), CONST64(0x6df619c32c82efae), + CONST64(0x02d46f6bd0b9bb69), CONST64(0xecbf62a77a31dd4b), CONST64(0x76d131dd3d96e0ab), CONST64(0x78c721d1379ee6a9), + CONST64(0x28b61f4fe681a967), CONST64(0x364e503c22281e0a), CONST64(0xc8cb028f4601c947), CONST64(0xe4c8c3161def0bf2), + CONST64(0x2c03c1995beec2b5), CONST64(0xee6b0dccaa886622), CONST64(0x81497b6456b332e5), CONST64(0xb00c235e719f2fee), + CONST64(0x1d4699a37cc2dfbe), CONST64(0xd13845fa87ac7d2b), CONST64(0xa0e27c21bf3e9e81), CONST64(0x7ea6906c5a483612), + CONST64(0xaef46c2db5369883), CONST64(0x41f5d85a776c2d1b), CONST64(0x2a6270243638120e), CONST64(0xe96005caaf8c6523), + CONST64(0xf1f9fb0406f302f5), CONST64(0xc6dd12834c09cf45), CONST64(0xe77615c6a5846321), CONST64(0x50713e9ed11f4fce), + CONST64(0xe2a972ab7039db49), CONST64(0xc4097de89cb0742c), CONST64(0xd58d9b2c3ac316f9), CONST64(0x8854636e59bf37e6), + CONST64(0x251ed99354e2c7b6), CONST64(0xd8255df088a07828), CONST64(0x6581b8724b5c3917), CONST64(0xa9ff642bb0329b82), + CONST64(0x46fed05c72682e1a), CONST64(0x96ac2c1d9d16808b), CONST64(0xc0bca33e21df1ffe), CONST64(0x91a7241b9812838a), + CONST64(0x3f5348362d241b09), CONST64(0x4540068cca0346c9), CONST64(0xb2d84c35a1269487), CONST64(0xf7984ab96b25d24e), + CONST64(0x9d655b7c42a33ee1), CONST64(0xca1f6de496b8722e), CONST64(0x8642736253b731e4), CONST64(0x9a6e537a47a73de0), + CONST64(0xab2b0b40608b20eb), CONST64(0xd759f447ea7aad90), CONST64(0x5bb849ff0eaaf1a4), CONST64(0x5ad2f0446678221e), + CONST64(0xbcce5c39ab2e9285), CONST64(0x3d87275dfd9da060), CONST64(0x0000000000000000), CONST64(0xfb5a35deb1946f25), + CONST64(0xf6f2f30203f701f4), CONST64(0xedd5db1c12e30ef1), CONST64(0xcb75d45ffe6aa194), CONST64(0x3145583a272c1d0b), + CONST64(0x8f5f6b685cbb34e7), CONST64(0x56108f23bcc99f75), CONST64(0xb7072b58749b2cef), CONST64(0x8ce1bdb8e4d05c34), + CONST64(0x97c695a6f5c45331), CONST64(0x168feec2a37761d4), CONST64(0x0aa3cedab7676dd0), CONST64(0xb5d34433a4229786), + CONST64(0x6755d7199be5827e), CONST64(0x64eb01c9238eeaad), CONST64(0xc9a1bb342ed31afd), CONST64(0xdf2e55f68da47b29), + CONST64(0x90cd9da0f0c05030), CONST64(0xa188c59ad7ec4d3b), CONST64(0xfa308c65d946bc9f), CONST64(0xd286932a3fc715f8), + CONST64(0x68297eaef93f57c6), CONST64(0x79ad986a5f4c3513), CONST64(0x123a30141e180a06), CONST64(0x1b27281e11140f05), + CONST64(0x613466a4f63352c5), CONST64(0x77bb886655443311), CONST64(0x58069f2fb6c19977), CONST64(0x6943c71591ed847c), + CONST64(0x7b79f7018ff58e7a), CONST64(0x756fe70d85fd8878), CONST64(0x82f7adb4eed85a36), CONST64(0x54c4e0486c70241c), + CONST64(0xaf9ed596dde44b39), CONST64(0x9219f2cb2079eb59), CONST64(0x48e8c05078602818), CONST64(0xbf708ae91345fa56), + CONST64(0x3e39f18d45f6c8b3), CONST64(0x3724e9874afacdb0), CONST64(0xfc513dd8b4906c24), CONST64(0xe07d1dc0a0806020), + CONST64(0x3932f98b40f2cbb2), CONST64(0xd94fe44be072ab92), CONST64(0x4e8971ed15b6f8a3), CONST64(0x7a134ebae7275dc0), + CONST64(0xc1d61a85490dcc44), CONST64(0x33913751f795a662), CONST64(0x70b0806050403010), CONST64(0x2b08c99f5eeac1b4), + CONST64(0xbbc5543fae2a9184), CONST64(0xd4e722975211c543), CONST64(0xde44ec4de576a893), CONST64(0x74055eb6ed2f5bc2), + CONST64(0xebb46aa17f35de4a), CONST64(0x145b81a973cedabd), CONST64(0x8a800c0589068c8f), CONST64(0xc30275ee99b4772d), + CONST64(0x135089af76cad9bc), CONST64(0xf32d946fd64ab99c), CONST64(0x0bc97761dfb5be6a), CONST64(0xddfa3a9d5d1dc040), + CONST64(0x577a3698d41b4ccf), CONST64(0x498279eb10b2fba2), CONST64(0xa7e97427ba3a9d80), CONST64(0xf09342bf6e21d14f), + CONST64(0x5dd9f842637c211f), CONST64(0x4c5d1e86c50f43ca), CONST64(0x71da39db3892e3aa), CONST64(0xd3ec2a915715c642), +}; + +static const ulong64 c[R + 1] = { + CONST64(0xba542f7453d3d24d), + CONST64(0x50ac8dbf70529a4c), + CONST64(0xead597d133515ba6), + CONST64(0xde48a899db32b7fc), + CONST64(0xe39e919be2bb416e), + CONST64(0xa5cb6b95a1f3b102), + CONST64(0xccc41d14c363da5d), + CONST64(0x5fdc7dcd7f5a6c5c), + CONST64(0xf726ffede89d6f8e), +}; + + /** + Initialize the Khazad block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int r; + const ulong64 *S; + ulong64 K2, K1; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (num_rounds != 8 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + /* use 7th table */ + S = T7; + + /* + * map unsigned char array cipher key to initial key state (mu): + */ + K2 = + ((ulong64)key[ 0] << 56) ^ + ((ulong64)key[ 1] << 48) ^ + ((ulong64)key[ 2] << 40) ^ + ((ulong64)key[ 3] << 32) ^ + ((ulong64)key[ 4] << 24) ^ + ((ulong64)key[ 5] << 16) ^ + ((ulong64)key[ 6] << 8) ^ + ((ulong64)key[ 7] ); + K1 = + ((ulong64)key[ 8] << 56) ^ + ((ulong64)key[ 9] << 48) ^ + ((ulong64)key[10] << 40) ^ + ((ulong64)key[11] << 32) ^ + ((ulong64)key[12] << 24) ^ + ((ulong64)key[13] << 16) ^ + ((ulong64)key[14] << 8) ^ + ((ulong64)key[15] ); + + /* + * compute the round keys: + */ + for (r = 0; r <= R; r++) { + /* + * K[r] = rho(c[r], K1) ^ K2; + */ + skey->khazad.roundKeyEnc[r] = + T0[(int)(K1 >> 56) ] ^ + T1[(int)(K1 >> 48) & 0xff] ^ + T2[(int)(K1 >> 40) & 0xff] ^ + T3[(int)(K1 >> 32) & 0xff] ^ + T4[(int)(K1 >> 24) & 0xff] ^ + T5[(int)(K1 >> 16) & 0xff] ^ + T6[(int)(K1 >> 8) & 0xff] ^ + T7[(int)(K1 ) & 0xff] ^ + c[r] ^ K2; + K2 = K1; K1 = skey->khazad.roundKeyEnc[r]; + } + /* + * compute the inverse key schedule: + * K'^0 = K^R, K'^R = K^0, K'^r = theta(K^{R-r}) + */ + skey->khazad.roundKeyDec[0] = skey->khazad.roundKeyEnc[R]; + for (r = 1; r < R; r++) { + K1 = skey->khazad.roundKeyEnc[R - r]; + skey->khazad.roundKeyDec[r] = + T0[(int)S[(int)(K1 >> 56) ] & 0xff] ^ + T1[(int)S[(int)(K1 >> 48) & 0xff] & 0xff] ^ + T2[(int)S[(int)(K1 >> 40) & 0xff] & 0xff] ^ + T3[(int)S[(int)(K1 >> 32) & 0xff] & 0xff] ^ + T4[(int)S[(int)(K1 >> 24) & 0xff] & 0xff] ^ + T5[(int)S[(int)(K1 >> 16) & 0xff] & 0xff] ^ + T6[(int)S[(int)(K1 >> 8) & 0xff] & 0xff] ^ + T7[(int)S[(int)(K1 ) & 0xff] & 0xff]; + } + skey->khazad.roundKeyDec[R] = skey->khazad.roundKeyEnc[0]; + + return CRYPT_OK; +} + +static void khazad_crypt(const unsigned char *plaintext, unsigned char *ciphertext, + const ulong64 *roundKey) { + int r; + ulong64 state; + /* + * map plaintext block to cipher state (mu) + * and add initial round key (sigma[K^0]): + */ + state = + ((ulong64)plaintext[0] << 56) ^ + ((ulong64)plaintext[1] << 48) ^ + ((ulong64)plaintext[2] << 40) ^ + ((ulong64)plaintext[3] << 32) ^ + ((ulong64)plaintext[4] << 24) ^ + ((ulong64)plaintext[5] << 16) ^ + ((ulong64)plaintext[6] << 8) ^ + ((ulong64)plaintext[7] ) ^ + roundKey[0]; + + /* + * R - 1 full rounds: + */ + for (r = 1; r < R; r++) { + state = + T0[(int)(state >> 56) ] ^ + T1[(int)(state >> 48) & 0xff] ^ + T2[(int)(state >> 40) & 0xff] ^ + T3[(int)(state >> 32) & 0xff] ^ + T4[(int)(state >> 24) & 0xff] ^ + T5[(int)(state >> 16) & 0xff] ^ + T6[(int)(state >> 8) & 0xff] ^ + T7[(int)(state ) & 0xff] ^ + roundKey[r]; + } + + /* + * last round: + */ + state = + (T0[(int)(state >> 56) ] & CONST64(0xff00000000000000)) ^ + (T1[(int)(state >> 48) & 0xff] & CONST64(0x00ff000000000000)) ^ + (T2[(int)(state >> 40) & 0xff] & CONST64(0x0000ff0000000000)) ^ + (T3[(int)(state >> 32) & 0xff] & CONST64(0x000000ff00000000)) ^ + (T4[(int)(state >> 24) & 0xff] & CONST64(0x00000000ff000000)) ^ + (T5[(int)(state >> 16) & 0xff] & CONST64(0x0000000000ff0000)) ^ + (T6[(int)(state >> 8) & 0xff] & CONST64(0x000000000000ff00)) ^ + (T7[(int)(state ) & 0xff] & CONST64(0x00000000000000ff)) ^ + roundKey[R]; + + /* + * map cipher state to ciphertext block (mu^{-1}): + */ + ciphertext[0] = (unsigned char)(state >> 56); + ciphertext[1] = (unsigned char)(state >> 48); + ciphertext[2] = (unsigned char)(state >> 40); + ciphertext[3] = (unsigned char)(state >> 32); + ciphertext[4] = (unsigned char)(state >> 24); + ciphertext[5] = (unsigned char)(state >> 16); + ciphertext[6] = (unsigned char)(state >> 8); + ciphertext[7] = (unsigned char)(state ); +} + +/** + Encrypts a block of text with Khazad + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + khazad_crypt(pt, ct, skey->khazad.roundKeyEnc); + return CRYPT_OK; +} + +/** + Decrypts a block of text with Khazad + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + khazad_crypt(ct, pt, skey->khazad.roundKeyDec); + return CRYPT_OK; +} + +/** + Performs a self-test of the Khazad block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int khazad_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct test { + unsigned char pt[8], ct[8], key[16]; + } tests[] = { +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x49, 0xA4, 0xCE, 0x32, 0xAC, 0x19, 0x0E, 0x3F }, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x64, 0x5D, 0x77, 0x3E, 0x40, 0xAB, 0xDD, 0x53 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } +}, { + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9E, 0x39, 0x98, 0x64, 0xF7, 0x8E, 0xCA, 0x02 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0xA9, 0xDF, 0x3D, 0x2C, 0x64, 0xD3, 0xEA, 0x28 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +} +}; + int x, y; + unsigned char buf[2][8]; + symmetric_key skey; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + khazad_setup(tests[x].key, 16, 0, &skey); + khazad_ecb_encrypt(tests[x].pt, buf[0], &skey); + khazad_ecb_decrypt(buf[0], buf[1], &skey); + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad Encrypt", x) || + compare_testvector(buf[1], 8, tests[x].pt, 8, "Khazad Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + for (y = 0; y < 1000; y++) khazad_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) khazad_ecb_decrypt(buf[0], buf[0], &skey); + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Khazad 1000", 1000)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void khazad_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int khazad_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 16) { + *keysize = 16; + return CRYPT_OK; + } + return CRYPT_INVALID_KEYSIZE; +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/kseed.c b/deps/libtomcrypt/src/ciphers/kseed.c new file mode 100644 index 0000000..1e63aec --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/kseed.c @@ -0,0 +1,366 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file kseed.c + seed implementation of SEED derived from RFC4269 + Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_KSEED + +const struct ltc_cipher_descriptor kseed_desc = { + "seed", + 20, + 16, 16, 16, 16, + &kseed_setup, + &kseed_ecb_encrypt, + &kseed_ecb_decrypt, + &kseed_test, + &kseed_done, + &kseed_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 SS0[256] = { +0x2989A1A8UL,0x05858184UL,0x16C6D2D4UL,0x13C3D3D0UL,0x14445054UL,0x1D0D111CUL,0x2C8CA0ACUL,0x25052124UL, +0x1D4D515CUL,0x03434340UL,0x18081018UL,0x1E0E121CUL,0x11415150UL,0x3CCCF0FCUL,0x0ACAC2C8UL,0x23436360UL, +0x28082028UL,0x04444044UL,0x20002020UL,0x1D8D919CUL,0x20C0E0E0UL,0x22C2E2E0UL,0x08C8C0C8UL,0x17071314UL, +0x2585A1A4UL,0x0F8F838CUL,0x03030300UL,0x3B4B7378UL,0x3B8BB3B8UL,0x13031310UL,0x12C2D2D0UL,0x2ECEE2ECUL, +0x30407070UL,0x0C8C808CUL,0x3F0F333CUL,0x2888A0A8UL,0x32023230UL,0x1DCDD1DCUL,0x36C6F2F4UL,0x34447074UL, +0x2CCCE0ECUL,0x15859194UL,0x0B0B0308UL,0x17475354UL,0x1C4C505CUL,0x1B4B5358UL,0x3D8DB1BCUL,0x01010100UL, +0x24042024UL,0x1C0C101CUL,0x33437370UL,0x18889098UL,0x10001010UL,0x0CCCC0CCUL,0x32C2F2F0UL,0x19C9D1D8UL, +0x2C0C202CUL,0x27C7E3E4UL,0x32427270UL,0x03838380UL,0x1B8B9398UL,0x11C1D1D0UL,0x06868284UL,0x09C9C1C8UL, +0x20406060UL,0x10405050UL,0x2383A3A0UL,0x2BCBE3E8UL,0x0D0D010CUL,0x3686B2B4UL,0x1E8E929CUL,0x0F4F434CUL, +0x3787B3B4UL,0x1A4A5258UL,0x06C6C2C4UL,0x38487078UL,0x2686A2A4UL,0x12021210UL,0x2F8FA3ACUL,0x15C5D1D4UL, +0x21416160UL,0x03C3C3C0UL,0x3484B0B4UL,0x01414140UL,0x12425250UL,0x3D4D717CUL,0x0D8D818CUL,0x08080008UL, +0x1F0F131CUL,0x19899198UL,0x00000000UL,0x19091118UL,0x04040004UL,0x13435350UL,0x37C7F3F4UL,0x21C1E1E0UL, +0x3DCDF1FCUL,0x36467274UL,0x2F0F232CUL,0x27072324UL,0x3080B0B0UL,0x0B8B8388UL,0x0E0E020CUL,0x2B8BA3A8UL, +0x2282A2A0UL,0x2E4E626CUL,0x13839390UL,0x0D4D414CUL,0x29496168UL,0x3C4C707CUL,0x09090108UL,0x0A0A0208UL, +0x3F8FB3BCUL,0x2FCFE3ECUL,0x33C3F3F0UL,0x05C5C1C4UL,0x07878384UL,0x14041014UL,0x3ECEF2FCUL,0x24446064UL, +0x1ECED2DCUL,0x2E0E222CUL,0x0B4B4348UL,0x1A0A1218UL,0x06060204UL,0x21012120UL,0x2B4B6368UL,0x26466264UL, +0x02020200UL,0x35C5F1F4UL,0x12829290UL,0x0A8A8288UL,0x0C0C000CUL,0x3383B3B0UL,0x3E4E727CUL,0x10C0D0D0UL, +0x3A4A7278UL,0x07474344UL,0x16869294UL,0x25C5E1E4UL,0x26062224UL,0x00808080UL,0x2D8DA1ACUL,0x1FCFD3DCUL, +0x2181A1A0UL,0x30003030UL,0x37073334UL,0x2E8EA2ACUL,0x36063234UL,0x15051114UL,0x22022220UL,0x38083038UL, +0x34C4F0F4UL,0x2787A3A4UL,0x05454144UL,0x0C4C404CUL,0x01818180UL,0x29C9E1E8UL,0x04848084UL,0x17879394UL, +0x35053134UL,0x0BCBC3C8UL,0x0ECEC2CCUL,0x3C0C303CUL,0x31417170UL,0x11011110UL,0x07C7C3C4UL,0x09898188UL, +0x35457174UL,0x3BCBF3F8UL,0x1ACAD2D8UL,0x38C8F0F8UL,0x14849094UL,0x19495158UL,0x02828280UL,0x04C4C0C4UL, +0x3FCFF3FCUL,0x09494148UL,0x39093138UL,0x27476364UL,0x00C0C0C0UL,0x0FCFC3CCUL,0x17C7D3D4UL,0x3888B0B8UL, +0x0F0F030CUL,0x0E8E828CUL,0x02424240UL,0x23032320UL,0x11819190UL,0x2C4C606CUL,0x1BCBD3D8UL,0x2484A0A4UL, +0x34043034UL,0x31C1F1F0UL,0x08484048UL,0x02C2C2C0UL,0x2F4F636CUL,0x3D0D313CUL,0x2D0D212CUL,0x00404040UL, +0x3E8EB2BCUL,0x3E0E323CUL,0x3C8CB0BCUL,0x01C1C1C0UL,0x2A8AA2A8UL,0x3A8AB2B8UL,0x0E4E424CUL,0x15455154UL, +0x3B0B3338UL,0x1CCCD0DCUL,0x28486068UL,0x3F4F737CUL,0x1C8C909CUL,0x18C8D0D8UL,0x0A4A4248UL,0x16465254UL, +0x37477374UL,0x2080A0A0UL,0x2DCDE1ECUL,0x06464244UL,0x3585B1B4UL,0x2B0B2328UL,0x25456164UL,0x3ACAF2F8UL, +0x23C3E3E0UL,0x3989B1B8UL,0x3181B1B0UL,0x1F8F939CUL,0x1E4E525CUL,0x39C9F1F8UL,0x26C6E2E4UL,0x3282B2B0UL, +0x31013130UL,0x2ACAE2E8UL,0x2D4D616CUL,0x1F4F535CUL,0x24C4E0E4UL,0x30C0F0F0UL,0x0DCDC1CCUL,0x08888088UL, +0x16061214UL,0x3A0A3238UL,0x18485058UL,0x14C4D0D4UL,0x22426260UL,0x29092128UL,0x07070304UL,0x33033330UL, +0x28C8E0E8UL,0x1B0B1318UL,0x05050104UL,0x39497178UL,0x10809090UL,0x2A4A6268UL,0x2A0A2228UL,0x1A8A9298UL +}; + +static const ulong32 SS1[256] = { +0x38380830UL,0xE828C8E0UL,0x2C2D0D21UL,0xA42686A2UL,0xCC0FCFC3UL,0xDC1ECED2UL,0xB03383B3UL,0xB83888B0UL, +0xAC2F8FA3UL,0x60204060UL,0x54154551UL,0xC407C7C3UL,0x44044440UL,0x6C2F4F63UL,0x682B4B63UL,0x581B4B53UL, +0xC003C3C3UL,0x60224262UL,0x30330333UL,0xB43585B1UL,0x28290921UL,0xA02080A0UL,0xE022C2E2UL,0xA42787A3UL, +0xD013C3D3UL,0x90118191UL,0x10110111UL,0x04060602UL,0x1C1C0C10UL,0xBC3C8CB0UL,0x34360632UL,0x480B4B43UL, +0xEC2FCFE3UL,0x88088880UL,0x6C2C4C60UL,0xA82888A0UL,0x14170713UL,0xC404C4C0UL,0x14160612UL,0xF434C4F0UL, +0xC002C2C2UL,0x44054541UL,0xE021C1E1UL,0xD416C6D2UL,0x3C3F0F33UL,0x3C3D0D31UL,0x8C0E8E82UL,0x98188890UL, +0x28280820UL,0x4C0E4E42UL,0xF436C6F2UL,0x3C3E0E32UL,0xA42585A1UL,0xF839C9F1UL,0x0C0D0D01UL,0xDC1FCFD3UL, +0xD818C8D0UL,0x282B0B23UL,0x64264662UL,0x783A4A72UL,0x24270723UL,0x2C2F0F23UL,0xF031C1F1UL,0x70324272UL, +0x40024242UL,0xD414C4D0UL,0x40014141UL,0xC000C0C0UL,0x70334373UL,0x64274763UL,0xAC2C8CA0UL,0x880B8B83UL, +0xF437C7F3UL,0xAC2D8DA1UL,0x80008080UL,0x1C1F0F13UL,0xC80ACAC2UL,0x2C2C0C20UL,0xA82A8AA2UL,0x34340430UL, +0xD012C2D2UL,0x080B0B03UL,0xEC2ECEE2UL,0xE829C9E1UL,0x5C1D4D51UL,0x94148490UL,0x18180810UL,0xF838C8F0UL, +0x54174753UL,0xAC2E8EA2UL,0x08080800UL,0xC405C5C1UL,0x10130313UL,0xCC0DCDC1UL,0x84068682UL,0xB83989B1UL, +0xFC3FCFF3UL,0x7C3D4D71UL,0xC001C1C1UL,0x30310131UL,0xF435C5F1UL,0x880A8A82UL,0x682A4A62UL,0xB03181B1UL, +0xD011C1D1UL,0x20200020UL,0xD417C7D3UL,0x00020202UL,0x20220222UL,0x04040400UL,0x68284860UL,0x70314171UL, +0x04070703UL,0xD81BCBD3UL,0x9C1D8D91UL,0x98198991UL,0x60214161UL,0xBC3E8EB2UL,0xE426C6E2UL,0x58194951UL, +0xDC1DCDD1UL,0x50114151UL,0x90108090UL,0xDC1CCCD0UL,0x981A8A92UL,0xA02383A3UL,0xA82B8BA3UL,0xD010C0D0UL, +0x80018181UL,0x0C0F0F03UL,0x44074743UL,0x181A0A12UL,0xE023C3E3UL,0xEC2CCCE0UL,0x8C0D8D81UL,0xBC3F8FB3UL, +0x94168692UL,0x783B4B73UL,0x5C1C4C50UL,0xA02282A2UL,0xA02181A1UL,0x60234363UL,0x20230323UL,0x4C0D4D41UL, +0xC808C8C0UL,0x9C1E8E92UL,0x9C1C8C90UL,0x383A0A32UL,0x0C0C0C00UL,0x2C2E0E22UL,0xB83A8AB2UL,0x6C2E4E62UL, +0x9C1F8F93UL,0x581A4A52UL,0xF032C2F2UL,0x90128292UL,0xF033C3F3UL,0x48094941UL,0x78384870UL,0xCC0CCCC0UL, +0x14150511UL,0xF83BCBF3UL,0x70304070UL,0x74354571UL,0x7C3F4F73UL,0x34350531UL,0x10100010UL,0x00030303UL, +0x64244460UL,0x6C2D4D61UL,0xC406C6C2UL,0x74344470UL,0xD415C5D1UL,0xB43484B0UL,0xE82ACAE2UL,0x08090901UL, +0x74364672UL,0x18190911UL,0xFC3ECEF2UL,0x40004040UL,0x10120212UL,0xE020C0E0UL,0xBC3D8DB1UL,0x04050501UL, +0xF83ACAF2UL,0x00010101UL,0xF030C0F0UL,0x282A0A22UL,0x5C1E4E52UL,0xA82989A1UL,0x54164652UL,0x40034343UL, +0x84058581UL,0x14140410UL,0x88098981UL,0x981B8B93UL,0xB03080B0UL,0xE425C5E1UL,0x48084840UL,0x78394971UL, +0x94178793UL,0xFC3CCCF0UL,0x1C1E0E12UL,0x80028282UL,0x20210121UL,0x8C0C8C80UL,0x181B0B13UL,0x5C1F4F53UL, +0x74374773UL,0x54144450UL,0xB03282B2UL,0x1C1D0D11UL,0x24250521UL,0x4C0F4F43UL,0x00000000UL,0x44064642UL, +0xEC2DCDE1UL,0x58184850UL,0x50124252UL,0xE82BCBE3UL,0x7C3E4E72UL,0xD81ACAD2UL,0xC809C9C1UL,0xFC3DCDF1UL, +0x30300030UL,0x94158591UL,0x64254561UL,0x3C3C0C30UL,0xB43686B2UL,0xE424C4E0UL,0xB83B8BB3UL,0x7C3C4C70UL, +0x0C0E0E02UL,0x50104050UL,0x38390931UL,0x24260622UL,0x30320232UL,0x84048480UL,0x68294961UL,0x90138393UL, +0x34370733UL,0xE427C7E3UL,0x24240420UL,0xA42484A0UL,0xC80BCBC3UL,0x50134353UL,0x080A0A02UL,0x84078783UL, +0xD819C9D1UL,0x4C0C4C40UL,0x80038383UL,0x8C0F8F83UL,0xCC0ECEC2UL,0x383B0B33UL,0x480A4A42UL,0xB43787B3UL +}; + +static const ulong32 SS2[256] = { +0xA1A82989UL,0x81840585UL,0xD2D416C6UL,0xD3D013C3UL,0x50541444UL,0x111C1D0DUL,0xA0AC2C8CUL,0x21242505UL, +0x515C1D4DUL,0x43400343UL,0x10181808UL,0x121C1E0EUL,0x51501141UL,0xF0FC3CCCUL,0xC2C80ACAUL,0x63602343UL, +0x20282808UL,0x40440444UL,0x20202000UL,0x919C1D8DUL,0xE0E020C0UL,0xE2E022C2UL,0xC0C808C8UL,0x13141707UL, +0xA1A42585UL,0x838C0F8FUL,0x03000303UL,0x73783B4BUL,0xB3B83B8BUL,0x13101303UL,0xD2D012C2UL,0xE2EC2ECEUL, +0x70703040UL,0x808C0C8CUL,0x333C3F0FUL,0xA0A82888UL,0x32303202UL,0xD1DC1DCDUL,0xF2F436C6UL,0x70743444UL, +0xE0EC2CCCUL,0x91941585UL,0x03080B0BUL,0x53541747UL,0x505C1C4CUL,0x53581B4BUL,0xB1BC3D8DUL,0x01000101UL, +0x20242404UL,0x101C1C0CUL,0x73703343UL,0x90981888UL,0x10101000UL,0xC0CC0CCCUL,0xF2F032C2UL,0xD1D819C9UL, +0x202C2C0CUL,0xE3E427C7UL,0x72703242UL,0x83800383UL,0x93981B8BUL,0xD1D011C1UL,0x82840686UL,0xC1C809C9UL, +0x60602040UL,0x50501040UL,0xA3A02383UL,0xE3E82BCBUL,0x010C0D0DUL,0xB2B43686UL,0x929C1E8EUL,0x434C0F4FUL, +0xB3B43787UL,0x52581A4AUL,0xC2C406C6UL,0x70783848UL,0xA2A42686UL,0x12101202UL,0xA3AC2F8FUL,0xD1D415C5UL, +0x61602141UL,0xC3C003C3UL,0xB0B43484UL,0x41400141UL,0x52501242UL,0x717C3D4DUL,0x818C0D8DUL,0x00080808UL, +0x131C1F0FUL,0x91981989UL,0x00000000UL,0x11181909UL,0x00040404UL,0x53501343UL,0xF3F437C7UL,0xE1E021C1UL, +0xF1FC3DCDUL,0x72743646UL,0x232C2F0FUL,0x23242707UL,0xB0B03080UL,0x83880B8BUL,0x020C0E0EUL,0xA3A82B8BUL, +0xA2A02282UL,0x626C2E4EUL,0x93901383UL,0x414C0D4DUL,0x61682949UL,0x707C3C4CUL,0x01080909UL,0x02080A0AUL, +0xB3BC3F8FUL,0xE3EC2FCFUL,0xF3F033C3UL,0xC1C405C5UL,0x83840787UL,0x10141404UL,0xF2FC3ECEUL,0x60642444UL, +0xD2DC1ECEUL,0x222C2E0EUL,0x43480B4BUL,0x12181A0AUL,0x02040606UL,0x21202101UL,0x63682B4BUL,0x62642646UL, +0x02000202UL,0xF1F435C5UL,0x92901282UL,0x82880A8AUL,0x000C0C0CUL,0xB3B03383UL,0x727C3E4EUL,0xD0D010C0UL, +0x72783A4AUL,0x43440747UL,0x92941686UL,0xE1E425C5UL,0x22242606UL,0x80800080UL,0xA1AC2D8DUL,0xD3DC1FCFUL, +0xA1A02181UL,0x30303000UL,0x33343707UL,0xA2AC2E8EUL,0x32343606UL,0x11141505UL,0x22202202UL,0x30383808UL, +0xF0F434C4UL,0xA3A42787UL,0x41440545UL,0x404C0C4CUL,0x81800181UL,0xE1E829C9UL,0x80840484UL,0x93941787UL, +0x31343505UL,0xC3C80BCBUL,0xC2CC0ECEUL,0x303C3C0CUL,0x71703141UL,0x11101101UL,0xC3C407C7UL,0x81880989UL, +0x71743545UL,0xF3F83BCBUL,0xD2D81ACAUL,0xF0F838C8UL,0x90941484UL,0x51581949UL,0x82800282UL,0xC0C404C4UL, +0xF3FC3FCFUL,0x41480949UL,0x31383909UL,0x63642747UL,0xC0C000C0UL,0xC3CC0FCFUL,0xD3D417C7UL,0xB0B83888UL, +0x030C0F0FUL,0x828C0E8EUL,0x42400242UL,0x23202303UL,0x91901181UL,0x606C2C4CUL,0xD3D81BCBUL,0xA0A42484UL, +0x30343404UL,0xF1F031C1UL,0x40480848UL,0xC2C002C2UL,0x636C2F4FUL,0x313C3D0DUL,0x212C2D0DUL,0x40400040UL, +0xB2BC3E8EUL,0x323C3E0EUL,0xB0BC3C8CUL,0xC1C001C1UL,0xA2A82A8AUL,0xB2B83A8AUL,0x424C0E4EUL,0x51541545UL, +0x33383B0BUL,0xD0DC1CCCUL,0x60682848UL,0x737C3F4FUL,0x909C1C8CUL,0xD0D818C8UL,0x42480A4AUL,0x52541646UL, +0x73743747UL,0xA0A02080UL,0xE1EC2DCDUL,0x42440646UL,0xB1B43585UL,0x23282B0BUL,0x61642545UL,0xF2F83ACAUL, +0xE3E023C3UL,0xB1B83989UL,0xB1B03181UL,0x939C1F8FUL,0x525C1E4EUL,0xF1F839C9UL,0xE2E426C6UL,0xB2B03282UL, +0x31303101UL,0xE2E82ACAUL,0x616C2D4DUL,0x535C1F4FUL,0xE0E424C4UL,0xF0F030C0UL,0xC1CC0DCDUL,0x80880888UL, +0x12141606UL,0x32383A0AUL,0x50581848UL,0xD0D414C4UL,0x62602242UL,0x21282909UL,0x03040707UL,0x33303303UL, +0xE0E828C8UL,0x13181B0BUL,0x01040505UL,0x71783949UL,0x90901080UL,0x62682A4AUL,0x22282A0AUL,0x92981A8AUL +}; + +static const ulong32 SS3[256] = { +0x08303838UL,0xC8E0E828UL,0x0D212C2DUL,0x86A2A426UL,0xCFC3CC0FUL,0xCED2DC1EUL,0x83B3B033UL,0x88B0B838UL, +0x8FA3AC2FUL,0x40606020UL,0x45515415UL,0xC7C3C407UL,0x44404404UL,0x4F636C2FUL,0x4B63682BUL,0x4B53581BUL, +0xC3C3C003UL,0x42626022UL,0x03333033UL,0x85B1B435UL,0x09212829UL,0x80A0A020UL,0xC2E2E022UL,0x87A3A427UL, +0xC3D3D013UL,0x81919011UL,0x01111011UL,0x06020406UL,0x0C101C1CUL,0x8CB0BC3CUL,0x06323436UL,0x4B43480BUL, +0xCFE3EC2FUL,0x88808808UL,0x4C606C2CUL,0x88A0A828UL,0x07131417UL,0xC4C0C404UL,0x06121416UL,0xC4F0F434UL, +0xC2C2C002UL,0x45414405UL,0xC1E1E021UL,0xC6D2D416UL,0x0F333C3FUL,0x0D313C3DUL,0x8E828C0EUL,0x88909818UL, +0x08202828UL,0x4E424C0EUL,0xC6F2F436UL,0x0E323C3EUL,0x85A1A425UL,0xC9F1F839UL,0x0D010C0DUL,0xCFD3DC1FUL, +0xC8D0D818UL,0x0B23282BUL,0x46626426UL,0x4A72783AUL,0x07232427UL,0x0F232C2FUL,0xC1F1F031UL,0x42727032UL, +0x42424002UL,0xC4D0D414UL,0x41414001UL,0xC0C0C000UL,0x43737033UL,0x47636427UL,0x8CA0AC2CUL,0x8B83880BUL, +0xC7F3F437UL,0x8DA1AC2DUL,0x80808000UL,0x0F131C1FUL,0xCAC2C80AUL,0x0C202C2CUL,0x8AA2A82AUL,0x04303434UL, +0xC2D2D012UL,0x0B03080BUL,0xCEE2EC2EUL,0xC9E1E829UL,0x4D515C1DUL,0x84909414UL,0x08101818UL,0xC8F0F838UL, +0x47535417UL,0x8EA2AC2EUL,0x08000808UL,0xC5C1C405UL,0x03131013UL,0xCDC1CC0DUL,0x86828406UL,0x89B1B839UL, +0xCFF3FC3FUL,0x4D717C3DUL,0xC1C1C001UL,0x01313031UL,0xC5F1F435UL,0x8A82880AUL,0x4A62682AUL,0x81B1B031UL, +0xC1D1D011UL,0x00202020UL,0xC7D3D417UL,0x02020002UL,0x02222022UL,0x04000404UL,0x48606828UL,0x41717031UL, +0x07030407UL,0xCBD3D81BUL,0x8D919C1DUL,0x89919819UL,0x41616021UL,0x8EB2BC3EUL,0xC6E2E426UL,0x49515819UL, +0xCDD1DC1DUL,0x41515011UL,0x80909010UL,0xCCD0DC1CUL,0x8A92981AUL,0x83A3A023UL,0x8BA3A82BUL,0xC0D0D010UL, +0x81818001UL,0x0F030C0FUL,0x47434407UL,0x0A12181AUL,0xC3E3E023UL,0xCCE0EC2CUL,0x8D818C0DUL,0x8FB3BC3FUL, +0x86929416UL,0x4B73783BUL,0x4C505C1CUL,0x82A2A022UL,0x81A1A021UL,0x43636023UL,0x03232023UL,0x4D414C0DUL, +0xC8C0C808UL,0x8E929C1EUL,0x8C909C1CUL,0x0A32383AUL,0x0C000C0CUL,0x0E222C2EUL,0x8AB2B83AUL,0x4E626C2EUL, +0x8F939C1FUL,0x4A52581AUL,0xC2F2F032UL,0x82929012UL,0xC3F3F033UL,0x49414809UL,0x48707838UL,0xCCC0CC0CUL, +0x05111415UL,0xCBF3F83BUL,0x40707030UL,0x45717435UL,0x4F737C3FUL,0x05313435UL,0x00101010UL,0x03030003UL, +0x44606424UL,0x4D616C2DUL,0xC6C2C406UL,0x44707434UL,0xC5D1D415UL,0x84B0B434UL,0xCAE2E82AUL,0x09010809UL, +0x46727436UL,0x09111819UL,0xCEF2FC3EUL,0x40404000UL,0x02121012UL,0xC0E0E020UL,0x8DB1BC3DUL,0x05010405UL, +0xCAF2F83AUL,0x01010001UL,0xC0F0F030UL,0x0A22282AUL,0x4E525C1EUL,0x89A1A829UL,0x46525416UL,0x43434003UL, +0x85818405UL,0x04101414UL,0x89818809UL,0x8B93981BUL,0x80B0B030UL,0xC5E1E425UL,0x48404808UL,0x49717839UL, +0x87939417UL,0xCCF0FC3CUL,0x0E121C1EUL,0x82828002UL,0x01212021UL,0x8C808C0CUL,0x0B13181BUL,0x4F535C1FUL, +0x47737437UL,0x44505414UL,0x82B2B032UL,0x0D111C1DUL,0x05212425UL,0x4F434C0FUL,0x00000000UL,0x46424406UL, +0xCDE1EC2DUL,0x48505818UL,0x42525012UL,0xCBE3E82BUL,0x4E727C3EUL,0xCAD2D81AUL,0xC9C1C809UL,0xCDF1FC3DUL, +0x00303030UL,0x85919415UL,0x45616425UL,0x0C303C3CUL,0x86B2B436UL,0xC4E0E424UL,0x8BB3B83BUL,0x4C707C3CUL, +0x0E020C0EUL,0x40505010UL,0x09313839UL,0x06222426UL,0x02323032UL,0x84808404UL,0x49616829UL,0x83939013UL, +0x07333437UL,0xC7E3E427UL,0x04202424UL,0x84A0A424UL,0xCBC3C80BUL,0x43535013UL,0x0A02080AUL,0x87838407UL, +0xC9D1D819UL,0x4C404C0CUL,0x83838003UL,0x8F838C0FUL,0xCEC2CC0EUL,0x0B33383BUL,0x4A42480AUL,0x87B3B437UL +}; + +static const ulong32 KCi[16] = { +0x9E3779B9,0x3C6EF373, +0x78DDE6E6,0xF1BBCDCC, +0xE3779B99,0xC6EF3733, +0x8DDE6E67,0x1BBCDCCF, +0x3779B99E,0x6EF3733C, +0xDDE6E678,0xBBCDCCF1, +0x779B99E3,0xEF3733C6, +0xDE6E678D,0xBCDCCF1B +}; + +#define G(x) (SS3[((x)>>24)&255] ^ SS2[((x)>>16)&255] ^ SS1[((x)>>8)&255] ^ SS0[(x)&255]) + +#define F(L1, L2, R1, R2, K1, K2) \ + T2 = G((R1 ^ K1) ^ (R2 ^ K2)); \ + T = G( G(T2 + (R1 ^ K1)) + T2); \ + L2 ^= T; \ + L1 ^= (T + G(T2 + (R1 ^ K1))); \ + + /** + Initialize the SEED block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int i; + ulong32 tmp, k1, k2, k3, k4; + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + /* load key */ + LOAD32H(k1, key); + LOAD32H(k2, key+4); + LOAD32H(k3, key+8); + LOAD32H(k4, key+12); + + for (i = 0; i < 16; i++) { + skey->kseed.K[2*i+0] = G(k1 + k3 - KCi[i]); + skey->kseed.K[2*i+1] = G(k2 - k4 + KCi[i]); + if (i&1) { + tmp = k3; + k3 = ((k3 << 8) | (k4 >> 24)) & 0xFFFFFFFF; + k4 = ((k4 << 8) | (tmp >> 24)) & 0xFFFFFFFF; + } else { + tmp = k1; + k1 = ((k1 >> 8) | (k2 << 24)) & 0xFFFFFFFF; + k2 = ((k2 >> 8) | (tmp << 24)) & 0xFFFFFFFF; + } + /* reverse keys for decrypt */ + skey->kseed.dK[2*(15-i)+0] = skey->kseed.K[2*i+0]; + skey->kseed.dK[2*(15-i)+1] = skey->kseed.K[2*i+1]; + } + + return CRYPT_OK; +} + +static void rounds(ulong32 *P, const ulong32 *K) +{ + ulong32 T, T2; + int i; + for (i = 0; i < 16; i += 2) { + F(P[0], P[1], P[2], P[3], K[0], K[1]); + F(P[2], P[3], P[0], P[1], K[2], K[3]); + K += 4; + } +} + +/** + Encrypts a block of text with SEED + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 P[4]; + LOAD32H(P[0], pt); + LOAD32H(P[1], pt+4); + LOAD32H(P[2], pt+8); + LOAD32H(P[3], pt+12); + rounds(P, skey->kseed.K); + STORE32H(P[2], ct); + STORE32H(P[3], ct+4); + STORE32H(P[0], ct+8); + STORE32H(P[1], ct+12); + return CRYPT_OK; +} + +/** + Decrypts a block of text with SEED + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 P[4]; + LOAD32H(P[0], ct); + LOAD32H(P[1], ct+4); + LOAD32H(P[2], ct+8); + LOAD32H(P[3], ct+12); + rounds(P, skey->kseed.dK); + STORE32H(P[2], pt); + STORE32H(P[3], pt+4); + STORE32H(P[0], pt+8); + STORE32H(P[1], pt+12); + return CRYPT_OK; +} + +/** Terminate the context + @param skey The scheduled key +*/ +void kseed_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Performs a self-test of the SEED block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int kseed_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct test { + unsigned char pt[16], ct[16], key[16]; + } tests[] = { + +{ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, + { 0x5E,0xBA,0xC6,0xE0,0x05,0x4E,0x16,0x68,0x19,0xAF,0xF1,0xCC,0x6D,0x34,0x6C,0xDB }, + { 0 }, +}, + +{ + { 0 }, + { 0xC1,0x1F,0x22,0xF2,0x01,0x40,0x50,0x50,0x84,0x48,0x35,0x97,0xE4,0x37,0x0F,0x43 }, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }, +}, + +{ + { 0x83,0xA2,0xF8,0xA2,0x88,0x64,0x1F,0xB9,0xA4,0xE9,0xA5,0xCC,0x2F,0x13,0x1C,0x7D }, + { 0xEE,0x54,0xD1,0x3E,0xBC,0xAE,0x70,0x6D,0x22,0x6B,0xC3,0x14,0x2C,0xD4,0x0D,0x4A }, + { 0x47,0x06,0x48,0x08,0x51,0xE6,0x1B,0xE8,0x5D,0x74,0xBF,0xB3,0xFD,0x95,0x61,0x85 }, +}, + +{ + { 0xB4,0x1E,0x6B,0xE2,0xEB,0xA8,0x4A,0x14,0x8E,0x2E,0xED,0x84,0x59,0x3C,0x5E,0xC7 }, + { 0x9B,0x9B,0x7B,0xFC,0xD1,0x81,0x3C,0xB9,0x5D,0x0B,0x36,0x18,0xF4,0x0F,0x51,0x22 }, + { 0x28,0xDB,0xC3,0xBC,0x49,0xFF,0xD8,0x7D,0xCF,0xA5,0x09,0xB1,0x1D,0x42,0x2B,0xE7 }, +} +}; + int x; + unsigned char buf[2][16]; + symmetric_key skey; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + kseed_setup(tests[x].key, 16, 0, &skey); + kseed_ecb_encrypt(tests[x].pt, buf[0], &skey); + kseed_ecb_decrypt(buf[0], buf[1], &skey); + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "KSEED Encrypt", x) || + compare_testvector(buf[1], 16, tests[x].pt, 16, "KSEED Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int kseed_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 16) { + *keysize = 16; + } else { + return CRYPT_INVALID_KEYSIZE; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/multi2.c b/deps/libtomcrypt/src/ciphers/multi2.c new file mode 100644 index 0000000..e1a84ac --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/multi2.c @@ -0,0 +1,309 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file multi2.c + Multi-2 implementation (not public domain, hence the default disable) +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_MULTI2 + +static void s_pi1(ulong32 *p) +{ + p[1] ^= p[0]; +} + +static void s_pi2(ulong32 *p, const ulong32 *k) +{ + ulong32 t; + t = (p[1] + k[0]) & 0xFFFFFFFFUL; + t = (ROL(t, 1) + t - 1) & 0xFFFFFFFFUL; + t = (ROL(t, 4) ^ t) & 0xFFFFFFFFUL; + p[0] ^= t; +} + +static void s_pi3(ulong32 *p, const ulong32 *k) +{ + ulong32 t; + t = p[0] + k[1]; + t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; + t = (ROL(t, 8) ^ t) & 0xFFFFFFFFUL; + t = (t + k[2]) & 0xFFFFFFFFUL; + t = (ROL(t, 1) - t) & 0xFFFFFFFFUL; + t = ROL(t, 16) ^ (p[0] | t); + p[1] ^= t; +} + +static void s_pi4(ulong32 *p, const ulong32 *k) +{ + ulong32 t; + t = (p[1] + k[3]) & 0xFFFFFFFFUL; + t = (ROL(t, 2) + t + 1) & 0xFFFFFFFFUL; + p[0] ^= t; +} + +static void s_setup(const ulong32 *dk, const ulong32 *k, ulong32 *uk) +{ + int n, t; + ulong32 p[2]; + + p[0] = dk[0]; p[1] = dk[1]; + + t = 4; + n = 0; + s_pi1(p); + s_pi2(p, k); + uk[n++] = p[0]; + s_pi3(p, k); + uk[n++] = p[1]; + s_pi4(p, k); + uk[n++] = p[0]; + s_pi1(p); + uk[n++] = p[1]; + s_pi2(p, k+t); + uk[n++] = p[0]; + s_pi3(p, k+t); + uk[n++] = p[1]; + s_pi4(p, k+t); + uk[n++] = p[0]; + s_pi1(p); + uk[n++] = p[1]; +} + +static void s_encrypt(ulong32 *p, int N, const ulong32 *uk) +{ + int n, t; + for (t = n = 0; ; ) { + s_pi1(p); if (++n == N) break; + s_pi2(p, uk+t); if (++n == N) break; + s_pi3(p, uk+t); if (++n == N) break; + s_pi4(p, uk+t); if (++n == N) break; + t ^= 4; + } +} + +static void s_decrypt(ulong32 *p, int N, const ulong32 *uk) +{ + int n, t; + for (t = 4*(((N-1)>>2)&1), n = N; ; ) { + switch (n<=4 ? n : ((n-1)%4)+1) { + case 4: s_pi4(p, uk+t); --n; /* FALLTHROUGH */ + case 3: s_pi3(p, uk+t); --n; /* FALLTHROUGH */ + case 2: s_pi2(p, uk+t); --n; /* FALLTHROUGH */ + case 1: s_pi1(p); --n; break; + case 0: return; + } + t ^= 4; + } +} + +const struct ltc_cipher_descriptor multi2_desc = { + "multi2", + 22, + 40, 40, 8, 128, + &multi2_setup, + &multi2_ecb_encrypt, + &multi2_ecb_decrypt, + &multi2_test, + &multi2_done, + &multi2_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + ulong32 sk[8], dk[2]; + int x; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 40) return CRYPT_INVALID_KEYSIZE; + if (num_rounds == 0) num_rounds = 128; + + skey->multi2.N = num_rounds; + for (x = 0; x < 8; x++) { + LOAD32H(sk[x], key + x*4); + } + LOAD32H(dk[0], key + 32); + LOAD32H(dk[1], key + 36); + s_setup(dk, sk, skey->multi2.uk); + + zeromem(sk, sizeof(sk)); + zeromem(dk, sizeof(dk)); + return CRYPT_OK; +} + +/** + Encrypts a block of text with multi2 + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 p[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(p[0], pt); + LOAD32H(p[1], pt+4); + s_encrypt(p, skey->multi2.N, skey->multi2.uk); + STORE32H(p[0], ct); + STORE32H(p[1], ct+4); + return CRYPT_OK; +} + +/** + Decrypts a block of text with multi2 + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 p[2]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + LOAD32H(p[0], ct); + LOAD32H(p[1], ct+4); + s_decrypt(p, skey->multi2.N, skey->multi2.uk); + STORE32H(p[0], pt); + STORE32H(p[1], pt+4); + return CRYPT_OK; +} + +/** + Performs a self-test of the multi2 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int multi2_test(void) +{ + static const struct { + unsigned char key[40]; + unsigned char pt[8], ct[8]; + int rounds; + } tests[] = { +{ + { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + + 0x01, 0x23, 0x45, 0x67, + 0x89, 0xAB, 0xCD, 0xEF + }, + { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, + }, + { + 0xf8, 0x94, 0x40, 0x84, + 0x5e, 0x11, 0xcf, 0x89 + }, + 128, +}, +{ + { + 0x35, 0x91, 0x9d, 0x96, + 0x07, 0x02, 0xe2, 0xce, + 0x8d, 0x0b, 0x58, 0x3c, + 0xc9, 0xc8, 0x9d, 0x59, + 0xa2, 0xae, 0x96, 0x4e, + 0x87, 0x82, 0x45, 0xed, + 0x3f, 0x2e, 0x62, 0xd6, + 0x36, 0x35, 0xd0, 0x67, + + 0xb1, 0x27, 0xb9, 0x06, + 0xe7, 0x56, 0x22, 0x38, + }, + { + 0x1f, 0xb4, 0x60, 0x60, + 0xd0, 0xb3, 0x4f, 0xa5 + }, + { + 0xca, 0x84, 0xa9, 0x34, + 0x75, 0xc8, 0x60, 0xe5 + }, + 216, +} +}; + unsigned char buf[8]; + symmetric_key skey; + int err, x; + + for (x = 1; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = multi2_setup(tests[x].key, 40, tests[x].rounds, &skey)) != CRYPT_OK) { + return err; + } + if ((err = multi2_ecb_encrypt(tests[x].pt, buf, &skey)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(buf, 8, tests[x].ct, 8, "Multi2 Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = multi2_ecb_decrypt(buf, buf, &skey)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf, 8, tests[x].pt, 8, "Multi2 Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + for (x = 128; x < 256; ++x) { + unsigned char ct[8]; + + if ((err = multi2_setup(tests[0].key, 40, x, &skey)) != CRYPT_OK) { + return err; + } + if ((err = multi2_ecb_encrypt(tests[0].pt, ct, &skey)) != CRYPT_OK) { + return err; + } + if ((err = multi2_ecb_decrypt(ct, buf, &skey)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf, 8, tests[0].pt, 8, "Multi2 Rounds", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +} + +/** Terminate the context + @param skey The scheduled key +*/ +void multi2_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int multi2_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize >= 40) { + *keysize = 40; + } else { + return CRYPT_INVALID_KEYSIZE; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/noekeon.c b/deps/libtomcrypt/src/ciphers/noekeon.c new file mode 100644 index 0000000..58d73ae --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/noekeon.c @@ -0,0 +1,317 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @file noekeon.c + Implementation of the Noekeon block cipher by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_NOEKEON + +const struct ltc_cipher_descriptor noekeon_desc = +{ + "noekeon", + 16, + 16, 16, 16, 16, + &noekeon_setup, + &noekeon_ecb_encrypt, + &noekeon_ecb_decrypt, + &noekeon_test, + &noekeon_done, + &noekeon_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 RC[] = { + 0x00000080UL, 0x0000001bUL, 0x00000036UL, 0x0000006cUL, + 0x000000d8UL, 0x000000abUL, 0x0000004dUL, 0x0000009aUL, + 0x0000002fUL, 0x0000005eUL, 0x000000bcUL, 0x00000063UL, + 0x000000c6UL, 0x00000097UL, 0x00000035UL, 0x0000006aUL, + 0x000000d4UL +}; + +#define kTHETA(a, b, c, d) \ + temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + b ^= temp; d ^= temp; \ + temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + a ^= temp; c ^= temp; + +#define THETA(k, a, b, c, d) \ + temp = a^c; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + b ^= temp ^ k[1]; d ^= temp ^ k[3]; \ + temp = b^d; temp = temp ^ ROLc(temp, 8) ^ RORc(temp, 8); \ + a ^= temp ^ k[0]; c ^= temp ^ k[2]; + +#define GAMMA(a, b, c, d) \ + b ^= ~(d|c); \ + a ^= c&b; \ + temp = d; d = a; a = temp;\ + c ^= a ^ b ^ d; \ + b ^= ~(d|c); \ + a ^= c&b; + +#define PI1(a, b, c, d) \ + b = ROLc(b, 1); c = ROLc(c, 5); d = ROLc(d, 2); + +#define PI2(a, b, c, d) \ + b = RORc(b, 1); c = RORc(c, 5); d = RORc(d, 2); + + /** + Initialize the Noekeon block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + ulong32 temp; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + LOAD32H(skey->noekeon.K[0],&key[0]); + LOAD32H(skey->noekeon.K[1],&key[4]); + LOAD32H(skey->noekeon.K[2],&key[8]); + LOAD32H(skey->noekeon.K[3],&key[12]); + + LOAD32H(skey->noekeon.dK[0],&key[0]); + LOAD32H(skey->noekeon.dK[1],&key[4]); + LOAD32H(skey->noekeon.dK[2],&key[8]); + LOAD32H(skey->noekeon.dK[3],&key[12]); + + kTHETA(skey->noekeon.dK[0], skey->noekeon.dK[1], skey->noekeon.dK[2], skey->noekeon.dK[3]); + + return CRYPT_OK; +} + +/** + Encrypts a block of text with Noekeon + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,temp; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + LOAD32H(a,&pt[0]); LOAD32H(b,&pt[4]); + LOAD32H(c,&pt[8]); LOAD32H(d,&pt[12]); + +#define ROUND(i) \ + a ^= RC[i]; \ + THETA(skey->noekeon.K, a,b,c,d); \ + PI1(a,b,c,d); \ + GAMMA(a,b,c,d); \ + PI2(a,b,c,d); + + for (r = 0; r < 16; ++r) { + ROUND(r); + } + +#undef ROUND + + a ^= RC[16]; + THETA(skey->noekeon.K, a, b, c, d); + + STORE32H(a,&ct[0]); STORE32H(b,&ct[4]); + STORE32H(c,&ct[8]); STORE32H(d,&ct[12]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_noekeon_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with Noekeon + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d, temp; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + LOAD32H(a,&ct[0]); LOAD32H(b,&ct[4]); + LOAD32H(c,&ct[8]); LOAD32H(d,&ct[12]); + + +#define ROUND(i) \ + THETA(skey->noekeon.dK, a,b,c,d); \ + a ^= RC[i]; \ + PI1(a,b,c,d); \ + GAMMA(a,b,c,d); \ + PI2(a,b,c,d); + + for (r = 16; r > 0; --r) { + ROUND(r); + } + +#undef ROUND + + THETA(skey->noekeon.dK, a,b,c,d); + a ^= RC[0]; + STORE32H(a,&pt[0]); STORE32H(b, &pt[4]); + STORE32H(c,&pt[8]); STORE32H(d, &pt[12]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_noekeon_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the Noekeon block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int noekeon_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[16], pt[16], ct[16]; + } tests[] = { + { + 16, + { 0xAA, 0x3C, 0x8C, 0x86, 0xD9, 0x8B, 0xF8, 0xBE, 0x21, 0xE0, 0x36, 0x09, 0x78, 0xFB, 0xE4, 0x90 }, + { 0xE4, 0x96, 0x6C, 0xD3, 0x13, 0xA0, 0x6C, 0xAF, 0xD0, 0x23, 0xC9, 0xFD, 0x45, 0x32, 0x23, 0x16 }, + { 0xA6, 0xEC, 0xB8, 0xA8, 0x61, 0xFD, 0x62, 0xD9, 0x13, 0x02, 0xFE, 0x9E, 0x47, 0x01, 0x3F, 0xC3 } + }, + { + 16, + { 0xED, 0x43, 0xD1, 0x87, 0x21, 0x7E, 0xE0, 0x97, 0x3D, 0x76, 0xC3, 0x37, 0x2E, 0x7D, 0xAE, 0xD3 }, + { 0xE3, 0x38, 0x32, 0xCC, 0xF2, 0x2F, 0x2F, 0x0A, 0x4A, 0x8B, 0x8F, 0x18, 0x12, 0x20, 0x17, 0xD3 }, + { 0x94, 0xA5, 0xDF, 0xF5, 0xAE, 0x1C, 0xBB, 0x22, 0xAD, 0xEB, 0xA7, 0x0D, 0xB7, 0x82, 0x90, 0xA0 } + }, + { + 16, + { 0x6F, 0xDC, 0x23, 0x38, 0xF2, 0x10, 0xFB, 0xD3, 0xC1, 0x8C, 0x02, 0xF6, 0xB4, 0x6A, 0xD5, 0xA8 }, + { 0xDB, 0x29, 0xED, 0xB5, 0x5F, 0xB3, 0x60, 0x3A, 0x92, 0xA8, 0xEB, 0x9C, 0x6D, 0x9D, 0x3E, 0x8F }, + { 0x78, 0xF3, 0x6F, 0xF8, 0x9E, 0xBB, 0x8C, 0x6A, 0xE8, 0x10, 0xF7, 0x00, 0x22, 0x15, 0x30, 0x3D } + }, + { + 16, + { 0x2C, 0x0C, 0x02, 0xEF, 0x6B, 0xC4, 0xF2, 0x0B, 0x2E, 0xB9, 0xE0, 0xBF, 0xD9, 0x36, 0xC2, 0x4E }, + { 0x84, 0xE2, 0xFE, 0x64, 0xB1, 0xB9, 0xFE, 0x76, 0xA8, 0x3F, 0x45, 0xC7, 0x40, 0x7A, 0xAF, 0xEE }, + { 0x2A, 0x08, 0xD6, 0xA2, 0x1C, 0x63, 0x08, 0xB0, 0xF8, 0xBC, 0xB3, 0xA1, 0x66, 0xF7, 0xAE, 0xCF } + }, + { + 16, + { 0x6F, 0x30, 0xF8, 0x9F, 0xDA, 0x6E, 0xA0, 0x91, 0x04, 0x0F, 0x6C, 0x8B, 0x7D, 0xF7, 0x2A, 0x4B }, + { 0x65, 0xB6, 0xA6, 0xD0, 0x42, 0x14, 0x08, 0x60, 0x34, 0x8D, 0x37, 0x2F, 0x01, 0xF0, 0x46, 0xBE }, + { 0x66, 0xAC, 0x0B, 0x62, 0x1D, 0x68, 0x11, 0xF5, 0x27, 0xB1, 0x13, 0x5D, 0xF3, 0x2A, 0xE9, 0x18 } + }, + { + 16, + { 0xCA, 0xA4, 0x16, 0xB7, 0x1C, 0x92, 0x2E, 0xAD, 0xEB, 0xA7, 0xDB, 0x69, 0x92, 0xCB, 0x35, 0xEF }, + { 0x81, 0x6F, 0x8E, 0x4D, 0x96, 0xC6, 0xB3, 0x67, 0x83, 0xF5, 0x63, 0xC7, 0x20, 0x6D, 0x40, 0x23 }, + { 0x44, 0xF7, 0x63, 0x62, 0xF0, 0x43, 0xBB, 0x67, 0x4A, 0x75, 0x12, 0x42, 0x46, 0x29, 0x28, 0x19 } + }, + { + 16, + { 0x6B, 0xCF, 0x22, 0x2F, 0xE0, 0x1B, 0xB0, 0xAA, 0xD8, 0x3C, 0x91, 0x99, 0x18, 0xB2, 0x28, 0xE8 }, + { 0x7C, 0x37, 0xC7, 0xD0, 0xAC, 0x92, 0x29, 0xF1, 0x60, 0x82, 0x93, 0x89, 0xAA, 0x61, 0xAA, 0xA9 }, + { 0xE5, 0x89, 0x1B, 0xB3, 0xFE, 0x8B, 0x0C, 0xA1, 0xA6, 0xC7, 0xBE, 0x12, 0x73, 0x0F, 0xC1, 0x19 } + }, + { + 16, + { 0xE6, 0xD0, 0xF1, 0x03, 0x2E, 0xDE, 0x70, 0x8D, 0xD8, 0x9E, 0x36, 0x5C, 0x05, 0x52, 0xE7, 0x0D }, + { 0xE2, 0x42, 0xE7, 0x92, 0x0E, 0xF7, 0x82, 0xA2, 0xB8, 0x21, 0x8D, 0x26, 0xBA, 0x2D, 0xE6, 0x32 }, + { 0x1E, 0xDD, 0x75, 0x22, 0xB9, 0x36, 0x8A, 0x0F, 0x32, 0xFD, 0xD4, 0x48, 0x65, 0x12, 0x5A, 0x2F } + } + }; + symmetric_key key; + unsigned char tmp[2][16]; + int err, i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&key, sizeof(key)); + if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key); + noekeon_ecb_decrypt(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Noekeon Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "Noekeon Decrypt", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) noekeon_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void noekeon_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int noekeon_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/ciphers/rc2.c b/deps/libtomcrypt/src/ciphers/rc2.c new file mode 100644 index 0000000..4832424 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/rc2.c @@ -0,0 +1,408 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/**********************************************************************\ +* To commemorate the 1996 RSA Data Security Conference, the following * +* code is released into the public domain by its author. Prost! * +* * +* This cipher uses 16-bit words and little-endian byte ordering. * +* I wonder which processor it was optimized for? * +* * +* Thanks to CodeView, SoftIce, and D86 for helping bring this code to * +* the public. * +\**********************************************************************/ +#include "tomcrypt_private.h" + +/** + @file rc2.c + Implementation of RC2 with fixed effective key length of 64bits +*/ + +#ifdef LTC_RC2 + +const struct ltc_cipher_descriptor rc2_desc = { + "rc2", + 12, 8, 128, 8, 16, + &rc2_setup, + &rc2_ecb_encrypt, + &rc2_ecb_decrypt, + &rc2_test, + &rc2_done, + &rc2_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* 256-entry permutation table, probably derived somehow from pi */ +static const unsigned char permute[256] = { + 217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157, + 198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162, + 23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50, + 189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130, + 84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220, + 18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38, + 111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3, + 248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215, + 8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42, + 150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236, + 194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57, + 153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49, + 45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201, + 211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169, + 13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46, + 197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173 +}; + + /** + Initialize the RC2 block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param bits The effective key length in bits + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey) +{ + unsigned *xkey = skey->rc2.xkey; + unsigned char tmp[128]; + unsigned T8, TM; + int i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen == 0 || keylen > 128 || bits > 1024) { + return CRYPT_INVALID_KEYSIZE; + } + if (bits == 0) { + bits = 1024; + } + + if (num_rounds != 0 && num_rounds != 16) { + return CRYPT_INVALID_ROUNDS; + } + + for (i = 0; i < keylen; i++) { + tmp[i] = key[i] & 255; + } + + /* Phase 1: Expand input key to 128 bytes */ + if (keylen < 128) { + for (i = keylen; i < 128; i++) { + tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255]; + } + } + + /* Phase 2 - reduce effective key size to "bits" */ + T8 = (unsigned)(bits+7)>>3; + TM = (255 >> (unsigned)(7 & -bits)); + tmp[128 - T8] = permute[tmp[128 - T8] & TM]; + for (i = 127 - T8; i >= 0; i--) { + tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]]; + } + + /* Phase 3 - copy to xkey in little-endian order */ + for (i = 0; i < 64; i++) { + xkey[i] = (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8); + } + +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + + return CRYPT_OK; +} + +/** + Initialize the RC2 block cipher + + The effective key length is here always keylen * 8 + + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful +*/ +int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + return rc2_setup_ex(key, keylen, keylen * 8, num_rounds, skey); +} + +/**********************************************************************\ +* Encrypt an 8-byte block of plaintext using the given key. * +\**********************************************************************/ +/** + Encrypts a block of text with RC2 + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc2_ecb_encrypt( const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#else +int rc2_ecb_encrypt( const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#endif +{ + const unsigned *xkey; + unsigned x76, x54, x32, x10, i; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + xkey = skey->rc2.xkey; + + x76 = ((unsigned)pt[7] << 8) + (unsigned)pt[6]; + x54 = ((unsigned)pt[5] << 8) + (unsigned)pt[4]; + x32 = ((unsigned)pt[3] << 8) + (unsigned)pt[2]; + x10 = ((unsigned)pt[1] << 8) + (unsigned)pt[0]; + + for (i = 0; i < 16; i++) { + x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF; + x10 = ((x10 << 1) | (x10 >> 15)); + + x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF; + x32 = ((x32 << 2) | (x32 >> 14)); + + x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF; + x54 = ((x54 << 3) | (x54 >> 13)); + + x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF; + x76 = ((x76 << 5) | (x76 >> 11)); + + if (i == 4 || i == 10) { + x10 = (x10 + xkey[x76 & 63]) & 0xFFFF; + x32 = (x32 + xkey[x10 & 63]) & 0xFFFF; + x54 = (x54 + xkey[x32 & 63]) & 0xFFFF; + x76 = (x76 + xkey[x54 & 63]) & 0xFFFF; + } + } + + ct[0] = (unsigned char)x10; + ct[1] = (unsigned char)(x10 >> 8); + ct[2] = (unsigned char)x32; + ct[3] = (unsigned char)(x32 >> 8); + ct[4] = (unsigned char)x54; + ct[5] = (unsigned char)(x54 >> 8); + ct[6] = (unsigned char)x76; + ct[7] = (unsigned char)(x76 >> 8); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc2_ecb_encrypt( const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +{ + int err = s_rc2_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5); + return err; +} +#endif + +/**********************************************************************\ +* Decrypt an 8-byte block of ciphertext using the given key. * +\**********************************************************************/ +/** + Decrypts a block of text with RC2 + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc2_ecb_decrypt( const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#else +int rc2_ecb_decrypt( const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#endif +{ + unsigned x76, x54, x32, x10; + const unsigned *xkey; + int i; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + xkey = skey->rc2.xkey; + + x76 = ((unsigned)ct[7] << 8) + (unsigned)ct[6]; + x54 = ((unsigned)ct[5] << 8) + (unsigned)ct[4]; + x32 = ((unsigned)ct[3] << 8) + (unsigned)ct[2]; + x10 = ((unsigned)ct[1] << 8) + (unsigned)ct[0]; + + for (i = 15; i >= 0; i--) { + if (i == 4 || i == 10) { + x76 = (x76 - xkey[x54 & 63]) & 0xFFFF; + x54 = (x54 - xkey[x32 & 63]) & 0xFFFF; + x32 = (x32 - xkey[x10 & 63]) & 0xFFFF; + x10 = (x10 - xkey[x76 & 63]) & 0xFFFF; + } + + x76 = ((x76 << 11) | (x76 >> 5)); + x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF; + + x54 = ((x54 << 13) | (x54 >> 3)); + x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF; + + x32 = ((x32 << 14) | (x32 >> 2)); + x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF; + + x10 = ((x10 << 15) | (x10 >> 1)); + x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF; + } + + pt[0] = (unsigned char)x10; + pt[1] = (unsigned char)(x10 >> 8); + pt[2] = (unsigned char)x32; + pt[3] = (unsigned char)(x32 >> 8); + pt[4] = (unsigned char)x54; + pt[5] = (unsigned char)(x54 >> 8); + pt[6] = (unsigned char)x76; + pt[7] = (unsigned char)(x76 >> 8); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc2_ecb_decrypt( const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +{ + int err = s_rc2_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the RC2 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int rc2_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen, bits; + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + + { 8, 63, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff } + }, + { 8, 64, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49 } + }, + { 8, 64, + { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 } + }, + { 1, 64, + { 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0 } + }, + { 7, 64, + { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f } + }, + { 16, 64, + { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, + 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1 } + }, + { 16, 128, + { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f, + 0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 } + } + }; + int x, y, err; + symmetric_key skey; + unsigned char tmp[2][8]; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + zeromem(tmp, sizeof(tmp)); + if (tests[x].bits == (tests[x].keylen * 8)) { + if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) { + return err; + } + } + else { + if ((err = rc2_setup_ex(tests[x].key, tests[x].keylen, tests[x].bits, 0, &skey)) != CRYPT_OK) { + return err; + } + } + + rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey); + rc2_ecb_decrypt(tmp[0], tmp[1], &skey); + + if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC2 CT", x) || + compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC2 PT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void rc2_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int rc2_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 1) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 128) { + *keysize = 128; + } + return CRYPT_OK; +} + +#endif + + + diff --git a/deps/libtomcrypt/src/ciphers/rc5.c b/deps/libtomcrypt/src/ciphers/rc5.c new file mode 100644 index 0000000..f21ba4f --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/rc5.c @@ -0,0 +1,323 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file rc5.c + LTC_RC5 code by Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC5 + +const struct ltc_cipher_descriptor rc5_desc = +{ + "rc5", + 2, + 8, 128, 8, 12, + &rc5_setup, + &rc5_ecb_encrypt, + &rc5_ecb_decrypt, + &rc5_test, + &rc5_done, + &rc5_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 stab[50] = { +0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, +0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, +0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, +0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, +0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, +0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL, 0xe96a3d2fUL, 0x87a1b6e8UL, 0x25d930a1UL, 0xc410aa5aUL, +0x62482413UL, 0x007f9dccUL +}; + + /** + Initialize the LTC_RC5 block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +#ifdef LTC_CLEAN_STACK +static int s_rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + ulong32 L[64], *S, A, B, i, j, v, s, t, l; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(key != NULL); + + /* test parameters */ + if (num_rounds == 0) { + num_rounds = rc5_desc.default_rounds; + } + + if (num_rounds < 12 || num_rounds > 24) { + return CRYPT_INVALID_ROUNDS; + } + + /* key must be between 64 and 1024 bits */ + if (keylen < 8 || keylen > 128) { + return CRYPT_INVALID_KEYSIZE; + } + + skey->rc5.rounds = num_rounds; + S = skey->rc5.K; + + /* copy the key into the L array */ + for (A = i = j = 0; i < (ulong32)keylen; ) { + A = (A << 8) | ((ulong32)(key[i++] & 255)); + if ((i & 3) == 0) { + L[j++] = BSWAP(A); + A = 0; + } + } + + if ((keylen & 3) != 0) { + A <<= (ulong32)((8 * (4 - (keylen&3)))); + L[j++] = BSWAP(A); + } + + /* setup the S array */ + t = (ulong32)(2 * (num_rounds + 1)); + XMEMCPY(S, stab, t * sizeof(*S)); + + /* mix buffer */ + s = 3 * MAX(t, j); + l = j; + for (A = B = i = j = v = 0; v < s; v++) { + A = S[i] = ROLc(S[i] + A + B, 3); + B = L[j] = ROL(L[j] + A + B, (A+B)); + if (++i == t) { i = 0; } + if (++j == l) { j = 0; } + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + x = s_rc5_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(ulong32) * 122 + sizeof(int)); + return x; +} +#endif + +/** + Encrypts a block of text with LTC_RC5 + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 A, B; + const ulong32 *K; + int r; + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { + return CRYPT_INVALID_ROUNDS; + } + + LOAD32L(A, &pt[0]); + LOAD32L(B, &pt[4]); + A += skey->rc5.K[0]; + B += skey->rc5.K[1]; + K = skey->rc5.K + 2; + + if ((skey->rc5.rounds & 1) == 0) { + for (r = 0; r < skey->rc5.rounds; r += 2) { + A = ROL(A ^ B, B) + K[0]; + B = ROL(B ^ A, A) + K[1]; + A = ROL(A ^ B, B) + K[2]; + B = ROL(B ^ A, A) + K[3]; + K += 4; + } + } else { + for (r = 0; r < skey->rc5.rounds; r++) { + A = ROL(A ^ B, B) + K[0]; + B = ROL(B ^ A, A) + K[1]; + K += 2; + } + } + STORE32L(A, &ct[0]); + STORE32L(B, &ct[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_rc5_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with LTC_RC5 + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 A, B; + const ulong32 *K; + int r; + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + if (skey->rc5.rounds < 12 || skey->rc5.rounds > 24) { + return CRYPT_INVALID_ROUNDS; + } + + LOAD32L(A, &ct[0]); + LOAD32L(B, &ct[4]); + K = skey->rc5.K + (skey->rc5.rounds << 1); + + if ((skey->rc5.rounds & 1) == 0) { + K -= 2; + for (r = skey->rc5.rounds - 1; r >= 0; r -= 2) { + B = ROR(B - K[3], A) ^ A; + A = ROR(A - K[2], B) ^ B; + B = ROR(B - K[1], A) ^ A; + A = ROR(A - K[0], B) ^ B; + K -= 4; + } + } else { + for (r = skey->rc5.rounds - 1; r >= 0; r--) { + B = ROR(B - K[1], A) ^ A; + A = ROR(A - K[0], B) ^ B; + K -= 2; + } + } + A -= skey->rc5.K[0]; + B -= skey->rc5.K[1]; + STORE32L(A, &pt[0]); + STORE32L(B, &pt[4]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_rc5_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 2 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the LTC_RC5 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int rc5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + { + { 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51, + 0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 }, + { 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d }, + { 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 } + }, + { + { 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f, + 0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 }, + { 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 }, + { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 } + }, + { + { 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f, + 0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf }, + { 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }, + { 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc } + } + }; + unsigned char tmp[2][8]; + int x, y, err; + symmetric_key key; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + rc5_ecb_encrypt(tests[x].pt, tmp[0], &key); + rc5_ecb_decrypt(tmp[0], tmp[1], &key); + + /* compare */ + if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC5 Encrypt", x) != 0 || + compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC5 Decrypt", x) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void rc5_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int rc5_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 128) { + *keysize = 128; + } + return CRYPT_OK; +} + +#endif + + + diff --git a/deps/libtomcrypt/src/ciphers/rc6.c b/deps/libtomcrypt/src/ciphers/rc6.c new file mode 100644 index 0000000..d1341d3 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/rc6.c @@ -0,0 +1,324 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file rc6.c + LTC_RC6 code by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_RC6 + +const struct ltc_cipher_descriptor rc6_desc = +{ + "rc6", + 3, + 8, 128, 16, 20, + &rc6_setup, + &rc6_ecb_encrypt, + &rc6_ecb_decrypt, + &rc6_test, + &rc6_done, + &rc6_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const ulong32 stab[44] = { +0xb7e15163UL, 0x5618cb1cUL, 0xf45044d5UL, 0x9287be8eUL, 0x30bf3847UL, 0xcef6b200UL, 0x6d2e2bb9UL, 0x0b65a572UL, +0xa99d1f2bUL, 0x47d498e4UL, 0xe60c129dUL, 0x84438c56UL, 0x227b060fUL, 0xc0b27fc8UL, 0x5ee9f981UL, 0xfd21733aUL, +0x9b58ecf3UL, 0x399066acUL, 0xd7c7e065UL, 0x75ff5a1eUL, 0x1436d3d7UL, 0xb26e4d90UL, 0x50a5c749UL, 0xeedd4102UL, +0x8d14babbUL, 0x2b4c3474UL, 0xc983ae2dUL, 0x67bb27e6UL, 0x05f2a19fUL, 0xa42a1b58UL, 0x42619511UL, 0xe0990ecaUL, +0x7ed08883UL, 0x1d08023cUL, 0xbb3f7bf5UL, 0x5976f5aeUL, 0xf7ae6f67UL, 0x95e5e920UL, 0x341d62d9UL, 0xd254dc92UL, +0x708c564bUL, 0x0ec3d004UL, 0xacfb49bdUL, 0x4b32c376UL }; + + /** + Initialize the LTC_RC6 block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +#ifdef LTC_CLEAN_STACK +static int s_rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + ulong32 L[64], S[50], A, B, i, j, v, s, l; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* test parameters */ + if (num_rounds != 0 && num_rounds != 20) { + return CRYPT_INVALID_ROUNDS; + } + + /* key must be between 64 and 1024 bits */ + if (keylen < 8 || keylen > 128) { + return CRYPT_INVALID_KEYSIZE; + } + + /* copy the key into the L array */ + for (A = i = j = 0; i < (ulong32)keylen; ) { + A = (A << 8) | ((ulong32)(key[i++] & 255)); + if (!(i & 3)) { + L[j++] = BSWAP(A); + A = 0; + } + } + + /* handle odd sized keys */ + if (keylen & 3) { + A <<= (8 * (4 - (keylen&3))); + L[j++] = BSWAP(A); + } + + /* setup the S array */ + XMEMCPY(S, stab, 44 * sizeof(stab[0])); + + /* mix buffer */ + s = 3 * MAX(44, j); + l = j; + for (A = B = i = j = v = 0; v < s; v++) { + A = S[i] = ROLc(S[i] + A + B, 3); + B = L[j] = ROL(L[j] + A + B, (A+B)); + if (++i == 44) { i = 0; } + if (++j == l) { j = 0; } + } + + /* copy to key */ + for (i = 0; i < 44; i++) { + skey->rc6.K[i] = S[i]; + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + x = s_rc6_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(ulong32) * 122); + return x; +} +#endif + +/** + Encrypts a block of text with LTC_RC6 + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,t,u; + const ulong32 *K; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]); + + b += skey->rc6.K[0]; + d += skey->rc6.K[1]; + +#define RND(a,b,c,d) \ + t = (b * (b + b + 1)); t = ROLc(t, 5); \ + u = (d * (d + d + 1)); u = ROLc(u, 5); \ + a = ROL(a^t,u) + K[0]; \ + c = ROL(c^u,t) + K[1]; K += 2; + + K = skey->rc6.K + 2; + for (r = 0; r < 20; r += 4) { + RND(a,b,c,d); + RND(b,c,d,a); + RND(c,d,a,b); + RND(d,a,b,c); + } + +#undef RND + + a += skey->rc6.K[42]; + c += skey->rc6.K[43]; + STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_rc6_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 6 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with LTC_RC6 + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled +*/ +#ifdef LTC_CLEAN_STACK +static int s_rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,t,u; + const ulong32 *K; + int r; + + LTC_ARGCHK(skey != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]); + a -= skey->rc6.K[42]; + c -= skey->rc6.K[43]; + +#define RND(a,b,c,d) \ + t = (b * (b + b + 1)); t = ROLc(t, 5); \ + u = (d * (d + d + 1)); u = ROLc(u, 5); \ + c = ROR(c - K[1], t) ^ u; \ + a = ROR(a - K[0], u) ^ t; K -= 2; + + K = skey->rc6.K + 40; + + for (r = 0; r < 20; r += 4) { + RND(d,a,b,c); + RND(c,d,a,b); + RND(b,c,d,a); + RND(a,b,c,d); + } + +#undef RND + + b -= skey->rc6.K[0]; + d -= skey->rc6.K[1]; + STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_rc6_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 6 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the LTC_RC6 block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int rc6_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { + 16, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, + 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, + { 0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23, + 0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18 } + }, + { + 24, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, + 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, + { 0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04, + 0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4 } + }, + { + 32, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, + 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }, + { 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, + 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 }, + { 0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89, + 0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 } + } + }; + unsigned char tmp[2][16]; + int x, y, err; + symmetric_key key; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = rc6_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + rc6_ecb_encrypt(tests[x].pt, tmp[0], &key); + rc6_ecb_decrypt(tmp[0], tmp[1], &key); + + /* compare */ + if (compare_testvector(tmp[0], 16, tests[x].ct, 16, "RC6 Encrypt", x) || + compare_testvector(tmp[1], 16, tests[x].pt, 16, "RC6 Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) rc6_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) rc6_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void rc6_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int rc6_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 128) { + *keysize = 128; + } + return CRYPT_OK; +} + +#endif /*LTC_RC6*/ + + diff --git a/deps/libtomcrypt/src/ciphers/safer/safer.c b/deps/libtomcrypt/src/ciphers/safer/safer.c new file mode 100644 index 0000000..84cc2d0 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/safer/safer.c @@ -0,0 +1,484 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/******************************************************************************* +* +* FILE: safer.c +* +* LTC_DESCRIPTION: block-cipher algorithm LTC_SAFER (Secure And Fast Encryption +* Routine) in its four versions: LTC_SAFER K-64, LTC_SAFER K-128, +* LTC_SAFER SK-64 and LTC_SAFER SK-128. +* +* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch) +* Signal and Information Processing Laboratory +* Swiss Federal Institute of Technology +* CH-8092 Zuerich, Switzerland +* +* DATE: September 9, 1995 +* +* CHANGE HISTORY: +* +*******************************************************************************/ + +#include "tomcrypt_private.h" + +#ifdef LTC_SAFER + +#define LTC_SAFER_TAB_C +#include "safer_tab.c" + +const struct ltc_cipher_descriptor safer_k64_desc = { + "safer-k64", + 8, 8, 8, 8, LTC_SAFER_K64_DEFAULT_NOF_ROUNDS, + &safer_k64_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_k64_test, + &safer_done, + &safer_64_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + + safer_sk64_desc = { + "safer-sk64", + 9, 8, 8, 8, LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS, + &safer_sk64_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_sk64_test, + &safer_done, + &safer_64_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + + safer_k128_desc = { + "safer-k128", + 10, 16, 16, 8, LTC_SAFER_K128_DEFAULT_NOF_ROUNDS, + &safer_k128_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_sk128_test, + &safer_done, + &safer_128_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }, + + safer_sk128_desc = { + "safer-sk128", + 11, 16, 16, 8, LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS, + &safer_sk128_setup, + &safer_ecb_encrypt, + &safer_ecb_decrypt, + &safer_sk128_test, + &safer_done, + &safer_128_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + }; + +/******************* Constants ************************************************/ +/* #define TAB_LEN 256 */ + +/******************* Assertions ***********************************************/ + +/******************* Macros ***************************************************/ +#define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\ + |(unsigned int)((x) & 0xFF) >> (8 - (n)))) +#define EXP(x) safer_ebox[(x) & 0xFF] +#define LOG(x) safer_lbox[(x) & 0xFF] +#define PHT(x, y) { y += x; x += y; } +#define IPHT(x, y) { x -= y; y -= x; } + +/******************* Types ****************************************************/ + +#ifdef LTC_CLEAN_STACK +static void s_safer_expand_userkey(const unsigned char *userkey_1, + const unsigned char *userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key) +#else +static void safer_expand_userkey(const unsigned char *userkey_1, + const unsigned char *userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key) +#endif +{ unsigned int i, j, k; + unsigned char ka[LTC_SAFER_BLOCK_LEN + 1]; + unsigned char kb[LTC_SAFER_BLOCK_LEN + 1]; + + if (LTC_SAFER_MAX_NOF_ROUNDS < nof_rounds) { + nof_rounds = LTC_SAFER_MAX_NOF_ROUNDS; + } + *key++ = (unsigned char)nof_rounds; + ka[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; + kb[LTC_SAFER_BLOCK_LEN] = (unsigned char)0; + k = 0; + for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { + ka[j] = ROL8(userkey_1[j], 5); + ka[LTC_SAFER_BLOCK_LEN] ^= ka[j]; + kb[j] = *key++ = userkey_2[j]; + kb[LTC_SAFER_BLOCK_LEN] ^= kb[j]; + } + for (i = 1; i <= nof_rounds; i++) { + for (j = 0; j < LTC_SAFER_BLOCK_LEN + 1; j++) { + ka[j] = ROL8(ka[j], 6); + kb[j] = ROL8(kb[j], 6); + } + if (strengthened) { + k = 2 * i - 1; + while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } + } + for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { + if (strengthened) { + *key++ = (ka[k] + + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; + if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } + } else { + *key++ = (ka[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 1)&0xFF)]]) & 0xFF; + } + } + if (strengthened) { + k = 2 * i; + while (k >= (LTC_SAFER_BLOCK_LEN + 1)) { k -= LTC_SAFER_BLOCK_LEN + 1; } + } + for (j = 0; j < LTC_SAFER_BLOCK_LEN; j++) { + if (strengthened) { + *key++ = (kb[k] + + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; + if (++k == (LTC_SAFER_BLOCK_LEN + 1)) { k = 0; } + } else { + *key++ = (kb[j] + safer_ebox[(int)safer_ebox[(int)((18 * i + j + 10)&0xFF)]]) & 0xFF; + } + } + } + +#ifdef LTC_CLEAN_STACK + zeromem(ka, sizeof(ka)); + zeromem(kb, sizeof(kb)); +#endif +} + +#ifdef LTC_CLEAN_STACK +static void safer_expand_userkey(const unsigned char *userkey_1, + const unsigned char *userkey_2, + unsigned int nof_rounds, + int strengthened, + safer_key_t key) +{ + s_safer_expand_userkey(userkey_1, userkey_2, nof_rounds, strengthened, key); + burn_stack(sizeof(unsigned char) * (2 * (LTC_SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2); +} +#endif + +int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 8) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K64_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); + return CRYPT_OK; +} + +int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 8) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); + return CRYPT_OK; +} + +int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0 ?num_rounds:LTC_SAFER_K128_DEFAULT_NOF_ROUNDS), 0, skey->safer.key); + return CRYPT_OK; +} + +int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && (num_rounds < 6 || num_rounds > LTC_SAFER_MAX_NOF_ROUNDS)) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + safer_expand_userkey(key, key+8, (unsigned int)(num_rounds != 0?num_rounds:LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS), 1, skey->safer.key); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_safer_ecb_encrypt(const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#else +int safer_ecb_encrypt(const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +#endif +{ unsigned char a, b, c, d, e, f, g, h, t; + unsigned int round; + const unsigned char *key; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + key = skey->safer.key; + a = pt[0]; b = pt[1]; c = pt[2]; d = pt[3]; + e = pt[4]; f = pt[5]; g = pt[6]; h = pt[7]; + if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; + while(round-- > 0) + { + a ^= *++key; b += *++key; c += *++key; d ^= *++key; + e ^= *++key; f += *++key; g += *++key; h ^= *++key; + a = EXP(a) + *++key; b = LOG(b) ^ *++key; + c = LOG(c) ^ *++key; d = EXP(d) + *++key; + e = EXP(e) + *++key; f = LOG(f) ^ *++key; + g = LOG(g) ^ *++key; h = EXP(h) + *++key; + PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h); + PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h); + PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h); + t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t; + } + a ^= *++key; b += *++key; c += *++key; d ^= *++key; + e ^= *++key; f += *++key; g += *++key; h ^= *++key; + ct[0] = a & 0xFF; ct[1] = b & 0xFF; + ct[2] = c & 0xFF; ct[3] = d & 0xFF; + ct[4] = e & 0xFF; ct[5] = f & 0xFF; + ct[6] = g & 0xFF; ct[7] = h & 0xFF; + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int safer_ecb_encrypt(const unsigned char *pt, + unsigned char *ct, + const symmetric_key *skey) +{ + int err = s_safer_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); + return err; +} +#endif + +#ifdef LTC_CLEAN_STACK +static int s_safer_ecb_decrypt(const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#else +int safer_ecb_decrypt(const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +#endif +{ unsigned char a, b, c, d, e, f, g, h, t; + unsigned int round; + const unsigned char *key; + + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(skey != NULL); + + key = skey->safer.key; + a = ct[0]; b = ct[1]; c = ct[2]; d = ct[3]; + e = ct[4]; f = ct[5]; g = ct[6]; h = ct[7]; + if (LTC_SAFER_MAX_NOF_ROUNDS < (round = *key)) round = LTC_SAFER_MAX_NOF_ROUNDS; + key += LTC_SAFER_BLOCK_LEN * (1 + 2 * round); + h ^= *key; g -= *--key; f -= *--key; e ^= *--key; + d ^= *--key; c -= *--key; b -= *--key; a ^= *--key; + while (round--) + { + t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t; + IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h); + IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h); + IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h); + h -= *--key; g ^= *--key; f ^= *--key; e -= *--key; + d -= *--key; c ^= *--key; b ^= *--key; a -= *--key; + h = LOG(h) ^ *--key; g = EXP(g) - *--key; + f = EXP(f) - *--key; e = LOG(e) ^ *--key; + d = LOG(d) ^ *--key; c = EXP(c) - *--key; + b = EXP(b) - *--key; a = LOG(a) ^ *--key; + } + pt[0] = a & 0xFF; pt[1] = b & 0xFF; + pt[2] = c & 0xFF; pt[3] = d & 0xFF; + pt[4] = e & 0xFF; pt[5] = f & 0xFF; + pt[6] = g & 0xFF; pt[7] = h & 0xFF; + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int safer_ecb_decrypt(const unsigned char *ct, + unsigned char *pt, + const symmetric_key *skey) +{ + int err = s_safer_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *)); + return err; +} +#endif + +int safer_64_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 8) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 8; + return CRYPT_OK; +} + +int safer_128_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +int safer_k64_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 }, + k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 }; + + symmetric_key skey; + unsigned char buf[2][8]; + int err; + + /* test K64 */ + if ((err = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) { + return err; + } + safer_ecb_encrypt(k64_pt, buf[0], &skey); + safer_ecb_decrypt(buf[0], buf[1], &skey); + + if (compare_testvector(buf[0], 8, k64_ct, 8, "Safer K64 Encrypt", 0) != 0 || + compare_testvector(buf[1], 8, k64_pt, 8, "Safer K64 Decrypt", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + + +int safer_sk64_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 }; + + symmetric_key skey; + unsigned char buf[2][8]; + int err, y; + + /* test SK64 */ + if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) { + return err; + } + + safer_ecb_encrypt(sk64_pt, buf[0], &skey); + safer_ecb_decrypt(buf[0], buf[1], &skey); + + if (compare_testvector(buf[0], 8, sk64_ct, 8, "Safer SK64 Encrypt", 0) != 0 || + compare_testvector(buf[1], 8, sk64_pt, 8, "Safer SK64 Decrypt", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) buf[0][y] = 0; + for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); + for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void safer_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int safer_sk128_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, + sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8, + 0, 0, 0, 0, 0, 0, 0, 0 }, + sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 }; + + symmetric_key skey; + unsigned char buf[2][8]; + int err, y; + + /* test SK128 */ + if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + safer_ecb_encrypt(sk128_pt, buf[0], &skey); + safer_ecb_decrypt(buf[0], buf[1], &skey); + + if (compare_testvector(buf[0], 8, sk128_ct, 8, "Safer SK128 Encrypt", 0) != 0 || + compare_testvector(buf[1], 8, sk128_pt, 8, "Safer SK128 Decrypt", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) buf[0][y] = 0; + for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey); + for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey); + for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; + #endif +} + +#endif + + + diff --git a/deps/libtomcrypt/src/ciphers/safer/safer_tab.c b/deps/libtomcrypt/src/ciphers/safer/safer_tab.c new file mode 100644 index 0000000..4cc0e47 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/safer/safer_tab.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file safer_tab.c + Tables for LTC_SAFER block ciphers +*/ + +#ifdef LTC_SAFER_TAB_C + +/* This is the box defined by ebox[x] = 45^x mod 257. + * Its assumed that the value "256" corresponds to zero. */ +static const unsigned char safer_ebox[256] = { + 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63, + 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247, + 64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, +255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, +241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, +129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, + 4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, + 32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217, + 0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194, +249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10, +193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80, + 2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126, + 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237, +128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97, +253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5, +225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40 +}; + +/* This is the inverse of ebox or the base 45 logarithm */ +static const unsigned char safer_lbox[256] = { +128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248, +192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130, +112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37, +201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15, + 32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198, +175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84, +121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188, +189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217, +208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158, +210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42, + 95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219, +164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29, + 41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14, +122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104, +109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66, +184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48 +}; + +#endif /* LTC_SAFER_TAB_C */ + + diff --git a/deps/libtomcrypt/src/ciphers/safer/saferp.c b/deps/libtomcrypt/src/ciphers/safer/saferp.c new file mode 100644 index 0000000..86cc708 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/safer/saferp.c @@ -0,0 +1,567 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file saferp.c + LTC_SAFER+ Implementation by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_SAFERP + +#define LTC_SAFER_TAB_C +#include "safer_tab.c" + +const struct ltc_cipher_descriptor saferp_desc = +{ + "safer+", + 4, + 16, 32, 16, 8, + &saferp_setup, + &saferp_ecb_encrypt, + &saferp_ecb_decrypt, + &saferp_test, + &saferp_done, + &saferp_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* ROUND(b,i) + * + * This is one forward key application. Note the basic form is + * key addition, substitution, key addition. The safer_ebox and safer_lbox + * are the exponentiation box and logarithm boxes respectively. + * The value of 'i' is the current round number which allows this + * function to be unrolled massively. Most of LTC_SAFER+'s speed + * comes from not having to compute indirect accesses into the + * array of 16 bytes b[0..15] which is the block of data +*/ + +#define ROUND(b, i) do { \ + b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \ + b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \ + b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \ + b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \ + b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \ + b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \ + b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \ + b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \ + b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \ + b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \ + b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \ + b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \ + b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \ + b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \ + b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \ + b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255; \ +} while (0) + +/* This is one inverse key application */ +#define iROUND(b, i) do { \ + b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \ + b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \ + b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \ + b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \ + b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \ + b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \ + b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \ + b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \ + b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \ + b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \ + b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \ + b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \ + b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \ + b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \ + b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \ + b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15]; \ +} while (0) + +/* This is a forward single layer PHT transform. */ +#define PHT(b) do { \ + b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \ + b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \ + b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \ + b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \ + b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \ + b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \ + b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \ + b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255; \ +} while (0) + +/* This is an inverse single layer PHT transform */ +#define iPHT(b) do { \ + b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \ + b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \ + b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \ + b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \ + b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \ + b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \ + b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \ + b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \ + } while (0) + +/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */ +#define SHUF(b, b2) do { \ + b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \ + b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \ + b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \ + b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3]; \ +} while (0) + +/* This is the inverse shuffle. It takes from b and gives to b2 */ +#define iSHUF(b, b2) do { \ + b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \ + b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \ + b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \ + b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3]; \ +} while (0) + +/* The complete forward Linear Transform layer. + * Note that alternating usage of b and b2. + * Each round of LT starts in 'b' and ends in 'b2'. + */ +#define LT(b, b2) do { \ + PHT(b); SHUF(b, b2); \ + PHT(b2); SHUF(b2, b); \ + PHT(b); SHUF(b, b2); \ + PHT(b2); \ +} while (0) + +/* This is the inverse linear transform layer. */ +#define iLT(b, b2) do { \ + iPHT(b); \ + iSHUF(b, b2); iPHT(b2); \ + iSHUF(b2, b); iPHT(b); \ + iSHUF(b, b2); iPHT(b2); \ +} while (0) + +#ifdef LTC_SMALL_CODE + +static void s_round(unsigned char *b, int i, const symmetric_key *skey) +{ + ROUND(b, i); +} + +static void s_iround(unsigned char *b, int i, const symmetric_key *skey) +{ + iROUND(b, i); +} + +static void s_lt(unsigned char *b, unsigned char *b2) +{ + LT(b, b2); +} + +static void s_ilt(unsigned char *b, unsigned char *b2) +{ + iLT(b, b2); +} + +#undef ROUND +#define ROUND(b, i) s_round(b, i, skey) + +#undef iROUND +#define iROUND(b, i) s_iround(b, i, skey) + +#undef LT +#define LT(b, b2) s_lt(b, b2) + +#undef iLT +#define iLT(b, b2) s_ilt(b, b2) + +#endif + +/* These are the 33, 128-bit bias words for the key schedule */ +static const unsigned char safer_bias[33][16] = { +{ 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100}, +{ 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61}, +{ 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160}, +{ 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148}, +{ 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143}, +{ 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202}, +{ 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44}, +{ 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51}, +{ 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56}, +{ 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215}, +{ 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210}, +{ 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53}, +{ 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244}, +{ 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131}, +{ 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241}, +{ 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172}, +{ 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239}, +{ 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202}, +{ 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246}, +{ 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152}, +{ 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236}, +{ 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150}, +{ 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30}, +{ 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6}, +{ 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104}, +{ 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175}, +{ 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35}, +{ 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7}, +{ 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207}, +{ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247}, +{ 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255}, +{ 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}}; + + /** + Initialize the LTC_SAFER+ block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + unsigned x, y, z; + unsigned char t[33]; + static const int rounds[3] = { 8, 12, 16 }; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* check arguments */ + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + /* Is the number of rounds valid? Either use zero for default or + * 8,12,16 rounds for 16,24,32 byte keys + */ + if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) { + return CRYPT_INVALID_ROUNDS; + } + + /* 128 bit key version */ + if (keylen == 16) { + /* copy key into t */ + for (x = y = 0; x < 16; x++) { + t[x] = key[x]; + y ^= key[x]; + } + t[16] = y; + + /* make round keys */ + for (x = 0; x < 16; x++) { + skey->saferp.K[0][x] = t[x]; + } + + /* make the 16 other keys as a transformation of the first key */ + for (x = 1; x < 17; x++) { + /* rotate 3 bits each */ + for (y = 0; y < 17; y++) { + t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; + } + + /* select and add */ + z = x; + for (y = 0; y < 16; y++) { + skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; + if (++z == 17) { z = 0; } + } + } + skey->saferp.rounds = 8; + } else if (keylen == 24) { + /* copy key into t */ + for (x = y = 0; x < 24; x++) { + t[x] = key[x]; + y ^= key[x]; + } + t[24] = y; + + /* make round keys */ + for (x = 0; x < 16; x++) { + skey->saferp.K[0][x] = t[x]; + } + + for (x = 1; x < 25; x++) { + /* rotate 3 bits each */ + for (y = 0; y < 25; y++) { + t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; + } + + /* select and add */ + z = x; + for (y = 0; y < 16; y++) { + skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; + if (++z == 25) { z = 0; } + } + } + skey->saferp.rounds = 12; + } else { + /* copy key into t */ + for (x = y = 0; x < 32; x++) { + t[x] = key[x]; + y ^= key[x]; + } + t[32] = y; + + /* make round keys */ + for (x = 0; x < 16; x++) { + skey->saferp.K[0][x] = t[x]; + } + + for (x = 1; x < 33; x++) { + /* rotate 3 bits each */ + for (y = 0; y < 33; y++) { + t[y] = ((t[y]<<3)|(t[y]>>5)) & 255; + } + + /* select and add */ + z = x; + for (y = 0; y < 16; y++) { + skey->saferp.K[x][y] = (t[z] + safer_bias[x-1][y]) & 255; + if (++z == 33) { z = 0; } + } + } + skey->saferp.rounds = 16; + } +#ifdef LTC_CLEAN_STACK + zeromem(t, sizeof(t)); +#endif + return CRYPT_OK; +} + +/** + Encrypts a block of text with LTC_SAFER+ + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + unsigned char b[16]; + int x; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { + return CRYPT_INVALID_ROUNDS; + } + + /* do eight rounds */ + for (x = 0; x < 16; x++) { + b[x] = pt[x]; + } + ROUND(b, 0); LT(b, ct); + ROUND(ct, 2); LT(ct, b); + ROUND(b, 4); LT(b, ct); + ROUND(ct, 6); LT(ct, b); + ROUND(b, 8); LT(b, ct); + ROUND(ct, 10); LT(ct, b); + ROUND(b, 12); LT(b, ct); + ROUND(ct, 14); LT(ct, b); + /* 192-bit key? */ + if (skey->saferp.rounds > 8) { + ROUND(b, 16); LT(b, ct); + ROUND(ct, 18); LT(ct, b); + ROUND(b, 20); LT(b, ct); + ROUND(ct, 22); LT(ct, b); + } + /* 256-bit key? */ + if (skey->saferp.rounds > 12) { + ROUND(b, 24); LT(b, ct); + ROUND(ct, 26); LT(ct, b); + ROUND(b, 28); LT(b, ct); + ROUND(ct, 30); LT(ct, b); + } + ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; + ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255; + ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255; + ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; + ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; + ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255; + ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255; + ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; + ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; + ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255; + ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255; + ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; + ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; + ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255; + ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255; + ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; +#ifdef LTC_CLEAN_STACK + zeromem(b, sizeof(b)); +#endif + return CRYPT_OK; +} + +/** + Decrypts a block of text with LTC_SAFER+ + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + unsigned char b[16]; + int x; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + if (skey->saferp.rounds < 8 || skey->saferp.rounds > 16) { + return CRYPT_INVALID_ROUNDS; + } + + /* do eight rounds */ + b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0]; + b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255; + b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255; + b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3]; + b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4]; + b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255; + b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255; + b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7]; + b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8]; + b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255; + b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255; + b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11]; + b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12]; + b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255; + b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255; + b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15]; + /* 256-bit key? */ + if (skey->saferp.rounds > 12) { + iLT(b, pt); iROUND(pt, 30); + iLT(pt, b); iROUND(b, 28); + iLT(b, pt); iROUND(pt, 26); + iLT(pt, b); iROUND(b, 24); + } + /* 192-bit key? */ + if (skey->saferp.rounds > 8) { + iLT(b, pt); iROUND(pt, 22); + iLT(pt, b); iROUND(b, 20); + iLT(b, pt); iROUND(pt, 18); + iLT(pt, b); iROUND(b, 16); + } + iLT(b, pt); iROUND(pt, 14); + iLT(pt, b); iROUND(b, 12); + iLT(b, pt); iROUND(pt,10); + iLT(pt, b); iROUND(b, 8); + iLT(b, pt); iROUND(pt,6); + iLT(pt, b); iROUND(b, 4); + iLT(b, pt); iROUND(pt,2); + iLT(pt, b); iROUND(b, 0); + for (x = 0; x < 16; x++) { + pt[x] = b[x]; + } +#ifdef LTC_CLEAN_STACK + zeromem(b, sizeof(b)); +#endif + return CRYPT_OK; +} + +/** + Performs a self-test of the LTC_SAFER+ block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int saferp_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { + 16, + { 41, 35, 190, 132, 225, 108, 214, 174, + 82, 144, 73, 241, 241, 187, 233, 235 }, + { 179, 166, 219, 60, 135, 12, 62, 153, + 36, 94, 13, 28, 6, 183, 71, 222 }, + { 224, 31, 182, 10, 12, 255, 84, 70, + 127, 13, 89, 249, 9, 57, 165, 220 } + }, { + 24, + { 72, 211, 143, 117, 230, 217, 29, 42, + 229, 192, 247, 43, 120, 129, 135, 68, + 14, 95, 80, 0, 212, 97, 141, 190 }, + { 123, 5, 21, 7, 59, 51, 130, 31, + 24, 112, 146, 218, 100, 84, 206, 177 }, + { 92, 136, 4, 63, 57, 95, 100, 0, + 150, 130, 130, 16, 193, 111, 219, 133 } + }, { + 32, + { 243, 168, 141, 254, 190, 242, 235, 113, + 255, 160, 208, 59, 117, 6, 140, 126, + 135, 120, 115, 77, 208, 190, 130, 190, + 219, 194, 70, 65, 43, 140, 250, 48 }, + { 127, 112, 240, 167, 84, 134, 50, 149, + 170, 91, 104, 19, 11, 230, 252, 245 }, + { 88, 11, 25, 36, 172, 229, 202, 213, + 170, 65, 105, 153, 220, 104, 153, 138 } + } + }; + + unsigned char tmp[2][16]; + symmetric_key skey; + int err, i, y; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) { + return err; + } + saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey); + saferp_ecb_decrypt(tmp[0], tmp[1], &skey); + + /* compare */ + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Safer+ Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "Safer+ Decrypt", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void saferp_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int saferp_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + } else if (*keysize < 32) { + *keysize = 24; + } else { + *keysize = 32; + } + return CRYPT_OK; +} + +#endif + + diff --git a/deps/libtomcrypt/src/ciphers/serpent.c b/deps/libtomcrypt/src/ciphers/serpent.c new file mode 100644 index 0000000..dbb999e --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/serpent.c @@ -0,0 +1,717 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Based on serpent.cpp - originally written and placed in the public domain by Wei Dai + https://github.com/weidai11/cryptopp/blob/master/serpent.cpp + + On 2017-10-16 wikipedia says: + "The Serpent cipher algorithm is in the public domain and has not been patented." + https://en.wikipedia.org/wiki/Serpent_(cipher) + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SERPENT + +const struct ltc_cipher_descriptor serpent_desc = { + "serpent", + 25, /* cipher_ID */ + 16, 32, 16, 32, /* min_key_len, max_key_len, block_len, default_rounds */ + &serpent_setup, + &serpent_ecb_encrypt, + &serpent_ecb_decrypt, + &serpent_test, + &serpent_done, + &serpent_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* linear transformation */ +#define s_lt(i,a,b,c,d,e) { \ + a = ROLc(a, 13); \ + c = ROLc(c, 3); \ + d = ROLc(d ^ c ^ (a << 3), 7); \ + b = ROLc(b ^ a ^ c, 1); \ + a = ROLc(a ^ b ^ d, 5); \ + c = ROLc(c ^ d ^ (b << 7), 22); \ + } + +/* inverse linear transformation */ +#define s_ilt(i,a,b,c,d,e) { \ + c = RORc(c, 22); \ + a = RORc(a, 5); \ + c ^= d ^ (b << 7); \ + a ^= b ^ d; \ + b = RORc(b, 1); \ + d = RORc(d, 7) ^ c ^ (a << 3); \ + b ^= a ^ c; \ + c = RORc(c, 3); \ + a = RORc(a, 13); \ + } + +/* order of output from S-box functions */ +#define s_beforeS0(f) f(0,a,b,c,d,e) +#define s_afterS0(f) f(1,b,e,c,a,d) +#define s_afterS1(f) f(2,c,b,a,e,d) +#define s_afterS2(f) f(3,a,e,b,d,c) +#define s_afterS3(f) f(4,e,b,d,c,a) +#define s_afterS4(f) f(5,b,a,e,c,d) +#define s_afterS5(f) f(6,a,c,b,e,d) +#define s_afterS6(f) f(7,a,c,d,b,e) +#define s_afterS7(f) f(8,d,e,b,a,c) + +/* order of output from inverse S-box functions */ +#define s_beforeI7(f) f(8,a,b,c,d,e) +#define s_afterI7(f) f(7,d,a,b,e,c) +#define s_afterI6(f) f(6,a,b,c,e,d) +#define s_afterI5(f) f(5,b,d,e,c,a) +#define s_afterI4(f) f(4,b,c,e,a,d) +#define s_afterI3(f) f(3,a,b,e,c,d) +#define s_afterI2(f) f(2,b,d,e,c,a) +#define s_afterI1(f) f(1,a,b,c,e,d) +#define s_afterI0(f) f(0,a,d,b,e,c) + +/* The instruction sequences for the S-box functions + * come from Dag Arne Osvik's paper "Speeding up Serpent". + */ + +#define s_s0(i, r0, r1, r2, r3, r4) { \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r4 ^= r2; \ + r1 ^= r0; \ + r0 |= r3; \ + r0 ^= r4; \ + r4 ^= r3; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 ^= r4; \ + r4 = ~r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r1 ^= r4; \ + r3 |= r0; \ + r1 ^= r3; \ + r4 ^= r3; \ +} + +#define s_i0(i, r0, r1, r2, r3, r4) { \ + r2 = ~r2; \ + r4 = r1; \ + r1 |= r0; \ + r4 = ~r4; \ + r1 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 &= r3; \ + r4 ^= r0; \ + r0 |= r1; \ + r0 ^= r2; \ + r3 ^= r4; \ + r2 ^= r1; \ + r3 ^= r0; \ + r3 ^= r1; \ + r2 &= r3; \ + r4 ^= r2; \ +} + +#define s_s1(i, r0, r1, r2, r3, r4) { \ + r0 = ~r0; \ + r2 = ~r2; \ + r4 = r0; \ + r0 &= r1; \ + r2 ^= r0; \ + r0 |= r3; \ + r3 ^= r2; \ + r1 ^= r0; \ + r0 ^= r4; \ + r4 |= r1; \ + r1 ^= r3; \ + r2 |= r0; \ + r2 &= r4; \ + r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r2; \ + r0 ^= r4; \ +} + +#define s_i1(i, r0, r1, r2, r3, r4) { \ + r4 = r1; \ + r1 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r3 ^= r0; \ + r0 |= r1; \ + r2 ^= r3; \ + r0 ^= r4; \ + r0 |= r2; \ + r1 ^= r3; \ + r0 ^= r1; \ + r1 |= r3; \ + r1 ^= r0; \ + r4 = ~r4; \ + r4 ^= r1; \ + r1 |= r0; \ + r1 ^= r0; \ + r1 |= r4; \ + r3 ^= r1; \ +} + +#define s_s2(i, r0, r1, r2, r3, r4) { \ + r4 = r0; \ + r0 &= r2; \ + r0 ^= r3; \ + r2 ^= r1; \ + r2 ^= r0; \ + r3 |= r4; \ + r3 ^= r1; \ + r4 ^= r2; \ + r1 = r3; \ + r3 |= r4; \ + r3 ^= r0; \ + r0 &= r1; \ + r4 ^= r0; \ + r1 ^= r3; \ + r1 ^= r4; \ + r4 = ~r4; \ +} + +#define s_i2(i, r0, r1, r2, r3, r4) { \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r3; \ + r3 &= r2; \ + r3 ^= r1; \ + r1 |= r2; \ + r1 ^= r4; \ + r4 &= r3; \ + r2 ^= r3; \ + r4 &= r0; \ + r4 ^= r2; \ + r2 &= r1; \ + r2 |= r0; \ + r3 = ~r3; \ + r2 ^= r3; \ + r0 ^= r3; \ + r0 &= r1; \ + r3 ^= r4; \ + r3 ^= r0; \ +} + +#define s_s3(i, r0, r1, r2, r3, r4) { \ + r4 = r0; \ + r0 |= r3; \ + r3 ^= r1; \ + r1 &= r4; \ + r4 ^= r2; \ + r2 ^= r3; \ + r3 &= r0; \ + r4 |= r1; \ + r3 ^= r4; \ + r0 ^= r1; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r2; \ + r1 |= r0; \ + r1 ^= r2; \ + r0 ^= r3; \ + r2 = r1; \ + r1 |= r3; \ + r1 ^= r0; \ +} + +#define s_i3(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; \ + r0 &= r4; \ + r4 ^= r3; \ + r3 |= r1; \ + r3 ^= r2; \ + r0 ^= r4; \ + r2 ^= r0; \ + r0 |= r3; \ + r0 ^= r1; \ + r4 ^= r2; \ + r2 &= r3; \ + r1 |= r3; \ + r1 ^= r2; \ + r4 ^= r0; \ + r2 ^= r4; \ +} + +#define s_s4(i, r0, r1, r2, r3, r4) { \ + r1 ^= r3; \ + r3 = ~r3; \ + r2 ^= r3; \ + r3 ^= r0; \ + r4 = r1; \ + r1 &= r3; \ + r1 ^= r2; \ + r4 ^= r3; \ + r0 ^= r4; \ + r2 &= r4; \ + r2 ^= r0; \ + r0 &= r1; \ + r3 ^= r0; \ + r4 |= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r2 &= r3; \ + r0 = ~r0; \ + r4 ^= r2; \ +} + +#define s_i4(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 &= r3; \ + r2 ^= r1; \ + r1 |= r3; \ + r1 &= r0; \ + r4 ^= r2; \ + r4 ^= r1; \ + r1 &= r2; \ + r0 = ~r0; \ + r3 ^= r4; \ + r1 ^= r3; \ + r3 &= r0; \ + r3 ^= r2; \ + r0 ^= r1; \ + r2 &= r0; \ + r3 ^= r0; \ + r2 ^= r4; \ + r2 |= r3; \ + r3 ^= r0; \ + r2 ^= r1; \ +} + +#define s_s5(i, r0, r1, r2, r3, r4) { \ + r0 ^= r1; \ + r1 ^= r3; \ + r3 = ~r3; \ + r4 = r1; \ + r1 &= r0; \ + r2 ^= r3; \ + r1 ^= r2; \ + r2 |= r4; \ + r4 ^= r3; \ + r3 &= r1; \ + r3 ^= r0; \ + r4 ^= r1; \ + r4 ^= r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r0 ^= r4; \ + r4 |= r3; \ + r2 ^= r4; \ +} + +#define s_i5(i, r0, r1, r2, r3, r4) { \ + r1 = ~r1; \ + r4 = r3; \ + r2 ^= r1; \ + r3 |= r0; \ + r3 ^= r2; \ + r2 |= r1; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 ^= r4; \ + r4 |= r0; \ + r4 ^= r1; \ + r1 &= r2; \ + r1 ^= r3; \ + r4 ^= r2; \ + r3 &= r4; \ + r4 ^= r1; \ + r3 ^= r0; \ + r3 ^= r4; \ + r4 = ~r4; \ +} + +#define s_s6(i, r0, r1, r2, r3, r4) { \ + r2 = ~r2; \ + r4 = r3; \ + r3 &= r0; \ + r0 ^= r4; \ + r3 ^= r2; \ + r2 |= r4; \ + r1 ^= r3; \ + r2 ^= r0; \ + r0 |= r1; \ + r2 ^= r1; \ + r4 ^= r0; \ + r0 |= r3; \ + r0 ^= r2; \ + r4 ^= r3; \ + r4 ^= r0; \ + r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ +} + +#define s_i6(i, r0, r1, r2, r3, r4) { \ + r0 ^= r2; \ + r4 = r2; \ + r2 &= r0; \ + r4 ^= r3; \ + r2 = ~r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r4 |= r0; \ + r0 ^= r2; \ + r3 ^= r4; \ + r4 ^= r1; \ + r1 &= r3; \ + r1 ^= r0; \ + r0 ^= r3; \ + r0 |= r2; \ + r3 ^= r1; \ + r4 ^= r0; \ +} + +#define s_s7(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 &= r1; \ + r2 ^= r3; \ + r3 &= r1; \ + r4 ^= r2; \ + r2 ^= r1; \ + r1 ^= r0; \ + r0 |= r4; \ + r0 ^= r2; \ + r3 ^= r1; \ + r2 ^= r3; \ + r3 &= r0; \ + r3 ^= r4; \ + r4 ^= r2; \ + r2 &= r0; \ + r4 = ~r4; \ + r2 ^= r4; \ + r4 &= r0; \ + r1 ^= r3; \ + r4 ^= r1; \ +} + +#define s_i7(i, r0, r1, r2, r3, r4) { \ + r4 = r2; \ + r2 ^= r0; \ + r0 &= r3; \ + r2 = ~r2; \ + r4 |= r3; \ + r3 ^= r1; \ + r1 |= r0; \ + r0 ^= r2; \ + r2 &= r4; \ + r1 ^= r2; \ + r2 ^= r0; \ + r0 |= r2; \ + r3 &= r4; \ + r0 ^= r3; \ + r4 ^= r1; \ + r3 ^= r4; \ + r4 |= r0; \ + r3 ^= r2; \ + r4 ^= r2; \ +} + +/* key xor */ +#define s_kx(r, a, b, c, d, e) { \ + a ^= k[4 * r + 0]; \ + b ^= k[4 * r + 1]; \ + c ^= k[4 * r + 2]; \ + d ^= k[4 * r + 3]; \ +} + +#define s_lk(r, a, b, c, d, e) { \ + a = k[(8-r)*4 + 0]; \ + b = k[(8-r)*4 + 1]; \ + c = k[(8-r)*4 + 2]; \ + d = k[(8-r)*4 + 3]; \ +} + +#define s_sk(r, a, b, c, d, e) { \ + k[(8-r)*4 + 4] = a; \ + k[(8-r)*4 + 5] = b; \ + k[(8-r)*4 + 6] = c; \ + k[(8-r)*4 + 7] = d; \ +} + +static int s_setup_key(const unsigned char *key, int keylen, int rounds, ulong32 *k) +{ + int i; + ulong32 t; + ulong32 k0[8] = { 0 }; /* zero-initialize */ + ulong32 a, b, c, d, e; + + for (i = 0; i < 8 && i < keylen/4; ++i) { + LOAD32L(k0[i], key + i * 4); + } + if (keylen < 32) { + k0[keylen/4] |= (ulong32)1 << ((keylen%4)*8); + } + + t = k0[7]; + for (i = 0; i < 8; ++i) { + k[i] = k0[i] = t = ROLc(k0[i] ^ k0[(i+3)%8] ^ k0[(i+5)%8] ^ t ^ 0x9e3779b9 ^ i, 11); + } + for (i = 8; i < 4*(rounds+1); ++i) { + k[i] = t = ROLc(k[i-8] ^ k[i-5] ^ k[i-3] ^ t ^ 0x9e3779b9 ^ i, 11); + } + k -= 20; + + for (i = 0; i < rounds/8; i++) { + s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); + s_afterS1(s_lk); s_afterS1(s_s2); s_afterS2(s_sk); + s_afterS0(s_lk); s_afterS0(s_s1); s_afterS1(s_sk); + s_beforeS0(s_lk); s_beforeS0(s_s0); s_afterS0(s_sk); + k += 8*4; + s_afterS6(s_lk); s_afterS6(s_s7); s_afterS7(s_sk); + s_afterS5(s_lk); s_afterS5(s_s6); s_afterS6(s_sk); + s_afterS4(s_lk); s_afterS4(s_s5); s_afterS5(s_sk); + s_afterS3(s_lk); s_afterS3(s_s4); s_afterS4(s_sk); + } + s_afterS2(s_lk); s_afterS2(s_s3); s_afterS3(s_sk); + + return CRYPT_OK; +} + +static int s_enc_block(const unsigned char *in, unsigned char *out, const ulong32 *k) +{ + ulong32 a, b, c, d, e; + unsigned int i = 1; + + LOAD32L(a, in + 0); + LOAD32L(b, in + 4); + LOAD32L(c, in + 8); + LOAD32L(d, in + 12); + + do { + s_beforeS0(s_kx); s_beforeS0(s_s0); s_afterS0(s_lt); + s_afterS0(s_kx); s_afterS0(s_s1); s_afterS1(s_lt); + s_afterS1(s_kx); s_afterS1(s_s2); s_afterS2(s_lt); + s_afterS2(s_kx); s_afterS2(s_s3); s_afterS3(s_lt); + s_afterS3(s_kx); s_afterS3(s_s4); s_afterS4(s_lt); + s_afterS4(s_kx); s_afterS4(s_s5); s_afterS5(s_lt); + s_afterS5(s_kx); s_afterS5(s_s6); s_afterS6(s_lt); + s_afterS6(s_kx); s_afterS6(s_s7); + + if (i == 4) break; + + ++i; + c = b; + b = e; + e = d; + d = a; + a = e; + k += 32; + s_beforeS0(s_lt); + } while (1); + + s_afterS7(s_kx); + + STORE32L(d, out + 0); + STORE32L(e, out + 4); + STORE32L(b, out + 8); + STORE32L(a, out + 12); + + return CRYPT_OK; +} + +static int s_dec_block(const unsigned char *in, unsigned char *out, const ulong32 *k) +{ + ulong32 a, b, c, d, e; + unsigned int i; + + LOAD32L(a, in + 0); + LOAD32L(b, in + 4); + LOAD32L(c, in + 8); + LOAD32L(d, in + 12); + e = 0; LTC_UNUSED_PARAM(e); /* avoid scan-build warning */ + i = 4; + k += 96; + + s_beforeI7(s_kx); + goto start; + + do { + c = b; + b = d; + d = e; + k -= 32; + s_beforeI7(s_ilt); +start: + s_beforeI7(s_i7); s_afterI7(s_kx); + s_afterI7(s_ilt); s_afterI7(s_i6); s_afterI6(s_kx); + s_afterI6(s_ilt); s_afterI6(s_i5); s_afterI5(s_kx); + s_afterI5(s_ilt); s_afterI5(s_i4); s_afterI4(s_kx); + s_afterI4(s_ilt); s_afterI4(s_i3); s_afterI3(s_kx); + s_afterI3(s_ilt); s_afterI3(s_i2); s_afterI2(s_kx); + s_afterI2(s_ilt); s_afterI2(s_i1); s_afterI1(s_kx); + s_afterI1(s_ilt); s_afterI1(s_i0); s_afterI0(s_kx); + } while (--i != 0); + + STORE32L(a, out + 0); + STORE32L(d, out + 4); + STORE32L(b, out + 8); + STORE32L(e, out + 12); + + return CRYPT_OK; +} + +int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (num_rounds != 0 && num_rounds != 32) return CRYPT_INVALID_ROUNDS; + if (keylen != 16 && keylen != 24 && keylen != 32) return CRYPT_INVALID_KEYSIZE; + + err = s_setup_key(key, keylen, 32, skey->serpent.k); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ulong32) * 14 + sizeof(int)); +#endif + return err; +} + +int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_enc_block(pt, ct, skey->serpent.k); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); +#endif + return err; +} + +int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_dec_block(ct, pt, skey->serpent.k); +#ifdef LTC_CLEAN_STACK + burn_stack(sizeof(ulong32) * 5 + sizeof(int)); +#endif + return err; +} + +void serpent_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +int serpent_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize >= 32) { *keysize = 32; } + else if (*keysize >= 24) { *keysize = 24; } + else if (*keysize >= 16) { *keysize = 16; } + else return CRYPT_INVALID_KEYSIZE; + return CRYPT_OK; +} + +int serpent_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[32]; + int keylen; + unsigned char pt[16], ct[16]; + } tests[] = { + { + /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 32, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0xA2,0x23,0xAA,0x12,0x88,0x46,0x3C,0x0E,0x2B,0xE3,0x8E,0xBD,0x82,0x56,0x16,0xC0} + }, + { + /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 32, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0xEA,0xE1,0xD4,0x05,0x57,0x01,0x74,0xDF,0x7D,0xF2,0xF9,0x96,0x6D,0x50,0x91,0x59} + }, + { + /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 32, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x65,0xF3,0x76,0x84,0x47,0x1E,0x92,0x1D,0xC8,0xA3,0x0F,0x45,0xB4,0x3C,0x44,0x99} + }, + { + /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 24, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x9E,0x27,0x4E,0xAD,0x9B,0x73,0x7B,0xB2,0x1E,0xFC,0xFC,0xA5,0x48,0x60,0x26,0x89} + }, + { + /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 24, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x92,0xFC,0x8E,0x51,0x03,0x99,0xE4,0x6A,0x04,0x1B,0xF3,0x65,0xE7,0xB3,0xAE,0x82} + }, + { + /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 24, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x5E,0x0D,0xA3,0x86,0xC4,0x6A,0xD4,0x93,0xDE,0xA2,0x03,0xFD,0xC6,0xF5,0x7D,0x70} + }, + { + /* key */ {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 16, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x26,0x4E,0x54,0x81,0xEF,0xF4,0x2A,0x46,0x06,0xAB,0xDA,0x06,0xC0,0xBF,0xDA,0x3D} + }, + { + /* key */ {0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 16, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0x4A,0x23,0x1B,0x3B,0xC7,0x27,0x99,0x34,0x07,0xAC,0x6E,0xC8,0x35,0x0E,0x85,0x24} + }, + { + /* key */ {0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* keylen */ 16, + /* pt */ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + /* ct */ {0xE0,0x32,0x69,0xF9,0xE9,0xFD,0x85,0x3C,0x7D,0x81,0x56,0xDF,0x14,0xB9,0x8D,0x56} + } + }; + + unsigned char buf[2][16]; + symmetric_key key; + int err, x; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + if ((err = serpent_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[0], 16, tests[x].ct, 16, "SERPENT Encrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = serpent_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) { + return err; + } + if (compare_testvector(buf[1], 16, tests[x].pt, 16, "SERPENT Decrypt", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/skipjack.c b/deps/libtomcrypt/src/ciphers/skipjack.c new file mode 100644 index 0000000..0251946 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/skipjack.c @@ -0,0 +1,334 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file skipjack.c + Skipjack Implementation by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_SKIPJACK + +const struct ltc_cipher_descriptor skipjack_desc = +{ + "skipjack", + 17, + 10, 10, 8, 32, + &skipjack_setup, + &skipjack_ecb_encrypt, + &skipjack_ecb_decrypt, + &skipjack_test, + &skipjack_done, + &skipjack_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +static const unsigned char sbox[256] = { + 0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9, + 0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28, + 0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53, + 0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2, + 0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8, + 0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90, + 0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76, + 0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d, + 0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18, + 0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4, + 0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40, + 0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5, + 0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2, + 0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8, + 0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac, + 0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46 +}; + +/* simple x + 1 (mod 10) in one step. */ +static const int keystep[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + +/* simple x - 1 (mod 10) in one step */ +static const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + + /** + Initialize the Skipjack block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 10) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 32 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + /* make sure the key is in range for platforms where CHAR_BIT != 8 */ + for (x = 0; x < 10; x++) { + skey->skipjack.key[x] = key[x] & 255; + } + + return CRYPT_OK; +} + +#define RULE_A \ + tmp = g_func(w1, &kp, skey->skipjack.key); \ + w1 = tmp ^ w4 ^ x; \ + w4 = w3; w3 = w2; \ + w2 = tmp; + +#define RULE_B \ + tmp = g_func(w1, &kp, skey->skipjack.key); \ + tmp1 = w4; w4 = w3; \ + w3 = w1 ^ w2 ^ x; \ + w1 = tmp1; w2 = tmp; + +#define RULE_A1 \ + tmp = w1 ^ w2 ^ x; \ + w1 = ig_func(w2, &kp, skey->skipjack.key); \ + w2 = w3; w3 = w4; w4 = tmp; + +#define RULE_B1 \ + tmp = ig_func(w2, &kp, skey->skipjack.key); \ + w2 = tmp ^ w3 ^ x; \ + w3 = w4; w4 = w1; w1 = tmp; + +static unsigned g_func(unsigned w, int *kp, const unsigned char *key) +{ + unsigned char g1,g2; + + g1 = (w >> 8) & 255; g2 = w & 255; + g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; + g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; + g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp]; + g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp]; + return ((unsigned)g1<<8)|(unsigned)g2; +} + +static unsigned ig_func(unsigned w, int *kp, const unsigned char *key) +{ + unsigned char g1,g2; + + g1 = (w >> 8) & 255; g2 = w & 255; + *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; + *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; + *kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]]; + *kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]]; + return ((unsigned)g1<<8)|(unsigned)g2; +} + +/** + Encrypts a block of text with Skipjack + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + unsigned w1,w2,w3,w4,tmp,tmp1; + int x, kp; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + /* load block */ + w1 = ((unsigned)pt[0]<<8)|pt[1]; + w2 = ((unsigned)pt[2]<<8)|pt[3]; + w3 = ((unsigned)pt[4]<<8)|pt[5]; + w4 = ((unsigned)pt[6]<<8)|pt[7]; + + /* 8 rounds of RULE A */ + for (x = 1, kp = 0; x < 9; x++) { + RULE_A; + } + + /* 8 rounds of RULE B */ + for (; x < 17; x++) { + RULE_B; + } + + /* 8 rounds of RULE A */ + for (; x < 25; x++) { + RULE_A; + } + + /* 8 rounds of RULE B */ + for (; x < 33; x++) { + RULE_B; + } + + /* store block */ + ct[0] = (w1>>8)&255; ct[1] = w1&255; + ct[2] = (w2>>8)&255; ct[3] = w2&255; + ct[4] = (w3>>8)&255; ct[5] = w3&255; + ct[6] = (w4>>8)&255; ct[7] = w4&255; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_skipjack_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2); + return err; +} +#endif + +/** + Decrypts a block of text with Skipjack + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + unsigned w1,w2,w3,w4,tmp; + int x, kp; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + /* load block */ + w1 = ((unsigned)ct[0]<<8)|ct[1]; + w2 = ((unsigned)ct[2]<<8)|ct[3]; + w3 = ((unsigned)ct[4]<<8)|ct[5]; + w4 = ((unsigned)ct[6]<<8)|ct[7]; + + /* 8 rounds of RULE B^-1 + + Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8 + */ + for (x = 32, kp = 8; x > 24; x--) { + RULE_B1; + } + + /* 8 rounds of RULE A^-1 */ + for (; x > 16; x--) { + RULE_A1; + } + + + /* 8 rounds of RULE B^-1 */ + for (; x > 8; x--) { + RULE_B1; + } + + /* 8 rounds of RULE A^-1 */ + for (; x > 0; x--) { + RULE_A1; + } + + /* store block */ + pt[0] = (w1>>8)&255; pt[1] = w1&255; + pt[2] = (w2>>8)&255; pt[3] = w2&255; + pt[4] = (w3>>8)&255; pt[5] = w3&255; + pt[6] = (w4>>8)&255; pt[7] = w4&255; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_skipjack_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2); + return err; +} +#endif + +/** + Performs a self-test of the Skipjack block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int skipjack_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + unsigned char key[10], pt[8], ct[8]; + } tests[] = { + { + { 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, + { 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa }, + { 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 } + } + }; + unsigned char buf[2][8]; + int x, y, err; + symmetric_key key; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + skipjack_ecb_encrypt(tests[x].pt, buf[0], &key); + skipjack_ecb_decrypt(buf[0], buf[1], &key); + + /* compare */ + if (compare_testvector(buf[0], 8, tests[x].ct, 8, "Skipjack Encrypt", x) != 0 || + compare_testvector(buf[1], 8, tests[x].pt, 8, "Skipjack Decrypt", x) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) buf[0][y] = 0; + for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key); + for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key); + for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void skipjack_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int skipjack_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 10) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize > 10) { + *keysize = 10; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/ciphers/tea.c b/deps/libtomcrypt/src/ciphers/tea.c new file mode 100644 index 0000000..fc413d4 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/tea.c @@ -0,0 +1,209 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file tea.c + Implementation of TEA, Steffen Jaeckel +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_TEA + +const struct ltc_cipher_descriptor tea_desc = +{ + "tea", + 26, + 16, 16, 8, 32, + &tea_setup, + &tea_ecb_encrypt, + &tea_ecb_decrypt, + &tea_test, + &tea_done, + &tea_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#define DELTA 0x9E3779B9uL +#define SUM 0xC6EF3720uL + +int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* check arguments */ + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != 32) { + return CRYPT_INVALID_ROUNDS; + } + + /* load key */ + LOAD32H(skey->tea.k[0], key+0); + LOAD32H(skey->tea.k[1], key+4); + LOAD32H(skey->tea.k[2], key+8); + LOAD32H(skey->tea.k[3], key+12); + + return CRYPT_OK; +} + +/** + Encrypts a block of text with TEA + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 y, z, sum = 0; + const ulong32 delta = DELTA; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(y, &pt[0]); + LOAD32H(z, &pt[4]); + for (r = 0; r < 32; r++) { + sum += delta; + y += ((z<<4) + skey->tea.k[0]) ^ (z + sum) ^ ((z>>5) + skey->tea.k[1]); + z += ((y<<4) + skey->tea.k[2]) ^ (y + sum) ^ ((y>>5) + skey->tea.k[3]); + } + STORE32H(y, &ct[0]); + STORE32H(z, &ct[4]); + return CRYPT_OK; +} + +/** + Decrypts a block of text with TEA + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 v0, v1, sum = SUM; + const ulong32 delta = DELTA; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(v0, &ct[0]); + LOAD32H(v1, &ct[4]); + + for (r = 0; r < 32; r++) { + v1 -= ((v0 << 4) + skey->tea.k[2]) ^ (v0 + sum) ^ ((v0 >> 5) + skey->tea.k[3]); + v0 -= ((v1 << 4) + skey->tea.k[0]) ^ (v1 + sum) ^ ((v1 >> 5) + skey->tea.k[1]); + sum -= delta; + } + + STORE32H(v0, &pt[0]); + STORE32H(v1, &pt[4]); + return CRYPT_OK; +} + +/** + Performs a self-test of the TEA block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int tea_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *key, *pt, *ct; + } tests[] = { + { + "00000000000000000000000000000000", + "0000000000000000", + "41ea3a0a94baa940" + }, { + "32a1e65408b63bb9214105744ec5d2e2", + "5ada1d89a9c3801a", + "dd46249e28aa0b4b" + }, { + "60388adadf70a1f5d9cb4e097d2c6c57", + "7a6adb4d69c53e0f", + "44b71215cf25368a" + }, { + "4368d2249bd0321eb7c56d5b63a1bfac", + "5a5d7ca2e186c41a", + "91f56dff7281794f" + }, { + "5c60bff27072d01c4513c5eb8f3a38ab", + "80d9c4adcf899635", + "2bb0f1b3c023ed11" + } + }; + unsigned char ptct[2][8]; + unsigned char tmp[2][8]; + unsigned char key[16]; + unsigned long l; + symmetric_key skey; + size_t i; + int err, y; + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + zeromem(&skey, sizeof(skey)); + + l = sizeof(key); + if ((err = base16_decode(tests[i].key, XSTRLEN(tests[i].key), key, &l)) != CRYPT_OK) return err; + l = sizeof(ptct[0]); + if ((err = base16_decode(tests[i].pt, XSTRLEN(tests[i].pt), ptct[0], &l)) != CRYPT_OK) return err; + l = sizeof(ptct[1]); + if ((err = base16_decode(tests[i].ct, XSTRLEN(tests[i].ct), ptct[1], &l)) != CRYPT_OK) return err; + + if ((err = tea_setup(key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + tea_ecb_encrypt(ptct[0], tmp[0], &skey); + tea_ecb_decrypt(tmp[0], tmp[1], &skey); + + if (compare_testvector(tmp[0], 8, ptct[1], 8, "TEA Encrypt", i) != 0 || + compare_testvector(tmp[1], 8, ptct[0], 8, "TEA Decrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) tea_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) tea_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } /* for */ + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void tea_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int tea_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/ciphers/twofish/twofish.c b/deps/libtomcrypt/src/ciphers/twofish/twofish.c new file mode 100644 index 0000000..c006361 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/twofish/twofish.c @@ -0,0 +1,706 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /** + @file twofish.c + Implementation of Twofish by Tom St Denis + */ +#include "tomcrypt_private.h" + +#ifdef LTC_TWOFISH + +/* first LTC_TWOFISH_ALL_TABLES must ensure LTC_TWOFISH_TABLES is defined */ +#ifdef LTC_TWOFISH_ALL_TABLES +#ifndef LTC_TWOFISH_TABLES +#define LTC_TWOFISH_TABLES +#endif +#endif + +const struct ltc_cipher_descriptor twofish_desc = +{ + "twofish", + 7, + 16, 32, 16, 16, + &twofish_setup, + &twofish_ecb_encrypt, + &twofish_ecb_decrypt, + &twofish_test, + &twofish_done, + &twofish_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* the two polynomials */ +#ifndef LTC_TWOFISH_TABLES +#define MDS_POLY 0x169 +#endif +#ifndef LTC_TWOFISH_ALL_TABLES +#define RS_POLY 0x14D +#endif + +/* The 4x8 RS Linear Transform */ +static const unsigned char RS[4][8] = { + { 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E }, + { 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 }, + { 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 }, + { 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 } +}; + +#ifdef LTC_TWOFISH_SMALL +/* sbox usage orderings */ +static const unsigned char qord[4][5] = { + { 1, 1, 0, 0, 1 }, + { 0, 1, 1, 0, 0 }, + { 0, 0, 0, 1, 1 }, + { 1, 0, 1, 1, 0 } +}; +#endif /* LTC_TWOFISH_SMALL */ + +#ifdef LTC_TWOFISH_TABLES + +#define LTC_TWOFISH_TAB_C +#include "twofish_tab.c" + +#define sbox(i, x) ((ulong32)SBOX[i][(x)&255]) + +#else + +/* The Q-box tables */ +static const unsigned char qbox[2][4][16] = { +{ + { 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 }, + { 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD }, + { 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 }, + { 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA } +}, +{ + { 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 }, + { 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 }, + { 0X4, 0XC, 0X7, 0X5, 0X1, 0X6, 0X9, 0XA, 0X0, 0XE, 0XD, 0X8, 0X2, 0XB, 0X3, 0XF }, + { 0xB, 0X9, 0X5, 0X1, 0XC, 0X3, 0XD, 0XE, 0X6, 0X4, 0X7, 0XF, 0X2, 0X0, 0X8, 0XA } +} +}; + +/* computes S_i[x] */ +#ifdef LTC_CLEAN_STACK +static ulong32 s_sbox(int i, ulong32 x) +#else +static ulong32 sbox(int i, ulong32 x) +#endif +{ + unsigned char a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,y; + + /* a0,b0 = [x/16], x mod 16 */ + a0 = (unsigned char)((x>>4)&15); + b0 = (unsigned char)((x)&15); + + /* a1 = a0 ^ b0 */ + a1 = a0 ^ b0; + + /* b1 = a0 ^ ROR(b0, 1) ^ 8a0 */ + b1 = (a0 ^ ((b0<<3)|(b0>>1)) ^ (a0<<3)) & 15; + + /* a2,b2 = t0[a1], t1[b1] */ + a2 = qbox[i][0][(int)a1]; + b2 = qbox[i][1][(int)b1]; + + /* a3 = a2 ^ b2 */ + a3 = a2 ^ b2; + + /* b3 = a2 ^ ROR(b2, 1) ^ 8a2 */ + b3 = (a2 ^ ((b2<<3)|(b2>>1)) ^ (a2<<3)) & 15; + + /* a4,b4 = t2[a3], t3[b3] */ + a4 = qbox[i][2][(int)a3]; + b4 = qbox[i][3][(int)b3]; + + /* y = 16b4 + a4 */ + y = (b4 << 4) + a4; + + /* return result */ + return (ulong32)y; +} + +#ifdef LTC_CLEAN_STACK +static ulong32 sbox(int i, ulong32 x) +{ + ulong32 y; + y = s_sbox(i, x); + burn_stack(sizeof(unsigned char) * 11); + return y; +} +#endif /* LTC_CLEAN_STACK */ + +#endif /* LTC_TWOFISH_TABLES */ + +/* computes ab mod p */ +static ulong32 gf_mult(ulong32 a, ulong32 b, ulong32 p) +{ + ulong32 result, B[2], P[2]; + + P[1] = p; + B[1] = b; + result = P[0] = B[0] = 0; + + /* unrolled branchless GF multiplier */ + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1); + result ^= B[a&1]; + + return result; +} + +/* computes [y0 y1 y2 y3] = MDS . [x0] */ +#ifndef LTC_TWOFISH_TABLES +static ulong32 mds_column_mult(unsigned char in, int col) +{ + ulong32 x01, x5B, xEF; + + x01 = in; + x5B = gf_mult(in, 0x5B, MDS_POLY); + xEF = gf_mult(in, 0xEF, MDS_POLY); + + switch (col) { + case 0: + return (x01 << 0 ) | + (x5B << 8 ) | + (xEF << 16) | + (xEF << 24); + case 1: + return (xEF << 0 ) | + (xEF << 8 ) | + (x5B << 16) | + (x01 << 24); + case 2: + return (x5B << 0 ) | + (xEF << 8 ) | + (x01 << 16) | + (xEF << 24); + case 3: + return (x5B << 0 ) | + (x01 << 8 ) | + (xEF << 16) | + (x5B << 24); + } + /* avoid warnings, we'd never get here normally but just to calm compiler warnings... */ + return 0; +} + +#else /* !LTC_TWOFISH_TABLES */ + +#define mds_column_mult(x, i) mds_tab[i][x] + +#endif /* LTC_TWOFISH_TABLES */ + +/* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */ +static void mds_mult(const unsigned char *in, unsigned char *out) +{ + int x; + ulong32 tmp; + for (tmp = x = 0; x < 4; x++) { + tmp ^= mds_column_mult(in[x], x); + } + STORE32L(tmp, out); +} + +#ifdef LTC_TWOFISH_ALL_TABLES +/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ +static void rs_mult(const unsigned char *in, unsigned char *out) +{ + ulong32 tmp; + tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^ + rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]]; + STORE32L(tmp, out); +} + +#else /* !LTC_TWOFISH_ALL_TABLES */ + +/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */ +static void rs_mult(const unsigned char *in, unsigned char *out) +{ + int x, y; + for (x = 0; x < 4; x++) { + out[x] = 0; + for (y = 0; y < 8; y++) { + out[x] ^= gf_mult(in[y], RS[x][y], RS_POLY); + } + } +} + +#endif + +/* computes h(x) */ +static void h_func(const unsigned char *in, unsigned char *out, const unsigned char *M, int k, int offset) +{ + int x; + unsigned char y[4]; + for (x = 0; x < 4; x++) { + y[x] = in[x]; + } + switch (k) { + case 4: + y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (6 + offset) + 0]); + y[1] = (unsigned char)(sbox(0, (ulong32)y[1]) ^ M[4 * (6 + offset) + 1]); + y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (6 + offset) + 2]); + y[3] = (unsigned char)(sbox(1, (ulong32)y[3]) ^ M[4 * (6 + offset) + 3]); + /* FALLTHROUGH */ + case 3: + y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (4 + offset) + 0]); + y[1] = (unsigned char)(sbox(1, (ulong32)y[1]) ^ M[4 * (4 + offset) + 1]); + y[2] = (unsigned char)(sbox(0, (ulong32)y[2]) ^ M[4 * (4 + offset) + 2]); + y[3] = (unsigned char)(sbox(0, (ulong32)y[3]) ^ M[4 * (4 + offset) + 3]); + /* FALLTHROUGH */ + case 2: + y[0] = (unsigned char)(sbox(1, sbox(0, sbox(0, (ulong32)y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0])); + y[1] = (unsigned char)(sbox(0, sbox(0, sbox(1, (ulong32)y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1])); + y[2] = (unsigned char)(sbox(1, sbox(1, sbox(0, (ulong32)y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2])); + y[3] = (unsigned char)(sbox(0, sbox(1, sbox(1, (ulong32)y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3])); + /* FALLTHROUGH */ + } + mds_mult(y, out); +} + +#ifndef LTC_TWOFISH_SMALL + +/* for GCC we don't use pointer aliases */ +#if defined(__GNUC__) + #define S1 skey->twofish.S[0] + #define S2 skey->twofish.S[1] + #define S3 skey->twofish.S[2] + #define S4 skey->twofish.S[3] +#endif + +/* the G function */ +#define g_func(x, dum) (S1[LTC_BYTE(x,0)] ^ S2[LTC_BYTE(x,1)] ^ S3[LTC_BYTE(x,2)] ^ S4[LTC_BYTE(x,3)]) +#define g1_func(x, dum) (S2[LTC_BYTE(x,0)] ^ S3[LTC_BYTE(x,1)] ^ S4[LTC_BYTE(x,2)] ^ S1[LTC_BYTE(x,3)]) + +#else + +#ifdef LTC_CLEAN_STACK +static ulong32 s_g_func(ulong32 x, const symmetric_key *key) +#else +static ulong32 g_func(ulong32 x, const symmetric_key *key) +#endif +{ + unsigned char g, i, y, z; + ulong32 res; + + res = 0; + for (y = 0; y < 4; y++) { + z = key->twofish.start; + + /* do unkeyed substitution */ + g = sbox(qord[y][z++], (x >> (8*y)) & 255); + + /* first subkey */ + i = 0; + + /* do key mixing+sbox until z==5 */ + while (z != 5) { + g = g ^ key->twofish.S[4*i++ + y]; + g = sbox(qord[y][z++], g); + } + + /* multiply g by a column of the MDS */ + res ^= mds_column_mult(g, y); + } + return res; +} + +#define g1_func(x, key) g_func(ROLc(x, 8), key) + +#ifdef LTC_CLEAN_STACK +static ulong32 g_func(ulong32 x, const symmetric_key *key) +{ + ulong32 y; + y = s_g_func(x, key); + burn_stack(sizeof(unsigned char) * 4 + sizeof(ulong32)); + return y; +} +#endif /* LTC_CLEAN_STACK */ + +#endif /* LTC_TWOFISH_SMALL */ + + /** + Initialize the Twofish block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +#ifdef LTC_CLEAN_STACK +static int s_twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ +#ifndef LTC_TWOFISH_SMALL + unsigned char S[4*4], tmpx0, tmpx1; +#endif + int k, x, y; + unsigned char tmp[4], tmp2[4], M[8*4]; + ulong32 A, B; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* invalid arguments? */ + if (num_rounds != 16 && num_rounds != 0) { + return CRYPT_INVALID_ROUNDS; + } + + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + /* k = keysize/64 [but since our keysize is in bytes...] */ + k = keylen / 8; + + /* copy the key into M */ + for (x = 0; x < keylen; x++) { + M[x] = key[x] & 255; + } + + /* create the S[..] words */ +#ifndef LTC_TWOFISH_SMALL + for (x = 0; x < k; x++) { + rs_mult(M+(x*8), S+(x*4)); + } +#else + for (x = 0; x < k; x++) { + rs_mult(M+(x*8), skey->twofish.S+(x*4)); + } +#endif + + /* make subkeys */ + for (x = 0; x < 20; x++) { + /* A = h(p * 2x, Me) */ + for (y = 0; y < 4; y++) { + tmp[y] = x+x; + } + h_func(tmp, tmp2, M, k, 0); + LOAD32L(A, tmp2); + + /* B = ROL(h(p * (2x + 1), Mo), 8) */ + for (y = 0; y < 4; y++) { + tmp[y] = (unsigned char)(x+x+1); + } + h_func(tmp, tmp2, M, k, 1); + LOAD32L(B, tmp2); + B = ROLc(B, 8); + + /* K[2i] = A + B */ + skey->twofish.K[x+x] = (A + B) & 0xFFFFFFFFUL; + + /* K[2i+1] = (A + 2B) <<< 9 */ + skey->twofish.K[x+x+1] = ROLc(B + B + A, 9); + } + +#ifndef LTC_TWOFISH_SMALL + /* make the sboxes (large ram variant) */ + if (k == 2) { + for (x = 0; x < 256; x++) { + tmpx0 = (unsigned char)sbox(0, x); + tmpx1 = (unsigned char)sbox(1, x); + skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0); + skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1); + skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2); + skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3); + } + } else if (k == 3) { + for (x = 0; x < 256; x++) { + tmpx0 = (unsigned char)sbox(0, x); + tmpx1 = (unsigned char)sbox(1, x); + skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0); + skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1); + skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2); + skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3); + } + } else { + for (x = 0; x < 256; x++) { + tmpx0 = (unsigned char)sbox(0, x); + tmpx1 = (unsigned char)sbox(1, x); + skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0); + skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1); + skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2); + skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3); + } + } +#else + /* where to start in the sbox layers */ + /* small ram variant */ + switch (k) { + case 4 : skey->twofish.start = 0; break; + case 3 : skey->twofish.start = 1; break; + default: skey->twofish.start = 2; break; + } +#endif + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + x = s_twofish_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(int) * 7 + sizeof(unsigned char) * 56 + sizeof(ulong32) * 2); + return x; +} +#endif + +/** + Encrypts a block of text with Twofish + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; + const ulong32 *k; + int r; +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + const ulong32 *S1, *S2, *S3, *S4; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + S1 = skey->twofish.S[0]; + S2 = skey->twofish.S[1]; + S3 = skey->twofish.S[2]; + S4 = skey->twofish.S[3]; +#endif + + LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]); + LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]); + a ^= skey->twofish.K[0]; + b ^= skey->twofish.K[1]; + c ^= skey->twofish.K[2]; + d ^= skey->twofish.K[3]; + + k = skey->twofish.K + 8; + for (r = 8; r != 0; --r) { + t2 = g1_func(b, skey); + t1 = g_func(a, skey) + t2; + c = RORc(c ^ (t1 + k[0]), 1); + d = ROLc(d, 1) ^ (t2 + t1 + k[1]); + + t2 = g1_func(d, skey); + t1 = g_func(c, skey) + t2; + a = RORc(a ^ (t1 + k[2]), 1); + b = ROLc(b, 1) ^ (t2 + t1 + k[3]); + k += 4; + } + + /* output with "undo last swap" */ + ta = c ^ skey->twofish.K[4]; + tb = d ^ skey->twofish.K[5]; + tc = a ^ skey->twofish.K[6]; + td = b ^ skey->twofish.K[7]; + + /* store output */ + STORE32L(ta,&ct[0]); STORE32L(tb,&ct[4]); + STORE32L(tc,&ct[8]); STORE32L(td,&ct[12]); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_twofish_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(ulong32) * 10 + sizeof(int)); + return err; +} +#endif + +/** + Decrypts a block of text with Twofish + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + ulong32 a,b,c,d,ta,tb,tc,td,t1,t2; + const ulong32 *k; + int r; +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + const ulong32 *S1, *S2, *S3, *S4; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + +#if !defined(LTC_TWOFISH_SMALL) && !defined(__GNUC__) + S1 = skey->twofish.S[0]; + S2 = skey->twofish.S[1]; + S3 = skey->twofish.S[2]; + S4 = skey->twofish.S[3]; +#endif + + /* load input */ + LOAD32L(ta,&ct[0]); LOAD32L(tb,&ct[4]); + LOAD32L(tc,&ct[8]); LOAD32L(td,&ct[12]); + + /* undo undo final swap */ + a = tc ^ skey->twofish.K[6]; + b = td ^ skey->twofish.K[7]; + c = ta ^ skey->twofish.K[4]; + d = tb ^ skey->twofish.K[5]; + + k = skey->twofish.K + 36; + for (r = 8; r != 0; --r) { + t2 = g1_func(d, skey); + t1 = g_func(c, skey) + t2; + a = ROLc(a, 1) ^ (t1 + k[2]); + b = RORc(b ^ (t2 + t1 + k[3]), 1); + + t2 = g1_func(b, skey); + t1 = g_func(a, skey) + t2; + c = ROLc(c, 1) ^ (t1 + k[0]); + d = RORc(d ^ (t2 + t1 + k[1]), 1); + k -= 4; + } + + /* pre-white */ + a ^= skey->twofish.K[0]; + b ^= skey->twofish.K[1]; + c ^= skey->twofish.K[2]; + d ^= skey->twofish.K[3]; + + /* store */ + STORE32L(a, &pt[0]); STORE32L(b, &pt[4]); + STORE32L(c, &pt[8]); STORE32L(d, &pt[12]); + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_twofish_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(ulong32) * 10 + sizeof(int)); + return err; +} +#endif + +/** + Performs a self-test of the Twofish block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int twofish_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, + 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }, + { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, + 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 }, + { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, + 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 } + }, { + 24, + { 0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36, + 0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88, + 0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 }, + { 0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5, + 0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 }, + { 0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45, + 0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 } + }, { + 32, + { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, + 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, + 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, + 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F }, + { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, + 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 }, + { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, + 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA } + } +}; + + + symmetric_key key; + unsigned char tmp[2][16]; + int err, i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + if ((err = twofish_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + twofish_ecb_encrypt(tests[i].pt, tmp[0], &key); + twofish_ecb_decrypt(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "Twofish Encrypt", i) != 0 || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "Twofish Decrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) twofish_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) twofish_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void twofish_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int twofish_keysize(int *keysize) +{ + LTC_ARGCHK(keysize); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } + if (*keysize < 32) { + *keysize = 24; + return CRYPT_OK; + } + *keysize = 32; + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/ciphers/twofish/twofish_tab.c b/deps/libtomcrypt/src/ciphers/twofish/twofish_tab.c new file mode 100644 index 0000000..e52d284 --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/twofish/twofish_tab.c @@ -0,0 +1,486 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /** + @file twofish_tab.c + Twofish tables, Tom St Denis + */ +#ifdef LTC_TWOFISH_TABLES +#ifdef LTC_TWOFISH_TAB_C + +/* pre generated 8x8 tables from the four 4x4s */ +static const unsigned char SBOX[2][256] = { +{ + 0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92, + 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98, + 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, + 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, + 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01, + 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, + 0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, + 0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, + 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, + 0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, + 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, + 0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8, + 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d, + 0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, + 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, + 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef, + 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, + 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, + 0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e, + 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02, + 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, + 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, + 0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, + 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, + 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d, + 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0}, +{ + 0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, + 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd, + 0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa, + 0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d, + 0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, + 0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, + 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, + 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, + 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff, + 0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7, + 0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, + 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, + 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c, + 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, + 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, + 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23, + 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, + 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, + 0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, + 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, + 0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34, + 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, + 0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9, + 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25, + 0x86, 0x56, 0x55, 0x09, 0xbe, 0x91} +}; + +/* the 4x4 MDS in a nicer format */ +static const ulong32 mds_tab[4][256] = { +{ +0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL, +0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL, +0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL, +0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL, +0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL, +0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL, +0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL, +0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL, +0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL, +0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL, +0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL, +0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL, +0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL, +0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL, +0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL, +0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL, +0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL, +0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL, +0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL, +0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL, +0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL, +0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL, +0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL, +0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL, +0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL, +0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL, +0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL, +0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL, +0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL, +0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL, +0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL, +0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL +}, +{ +0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL, +0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL, +0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL, +0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL, +0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL, +0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL, +0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL, +0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL, +0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL, +0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL, +0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL, +0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL, +0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL, +0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL, +0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL, +0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL, +0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL, +0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL, +0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL, +0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL, +0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL, +0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL, +0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL, +0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL, +0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL, +0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL, +0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL, +0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL, +0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL, +0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL, +0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL, +0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL +}, +{ +0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL, +0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL, +0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL, +0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL, +0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL, +0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL, +0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL, +0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL, +0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL, +0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL, +0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL, +0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL, +0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL, +0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL, +0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL, +0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL, +0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL, +0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL, +0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL, +0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL, +0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL, +0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL, +0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL, +0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL, +0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL, +0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL, +0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL, +0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL, +0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL, +0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL, +0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL, +0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL +}, +{ +0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL, +0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL, +0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL, +0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL, +0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL, +0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL, +0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL, +0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL, +0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL, +0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL, +0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL, +0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL, +0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL, +0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL, +0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL, +0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL, +0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL, +0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL, +0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL, +0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL, +0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL, +0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL, +0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL, +0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL, +0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL, +0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL, +0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL, +0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL, +0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL, +0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL, +0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL, +0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL +}}; + +#ifdef LTC_TWOFISH_ALL_TABLES + +/* the 4x8 RS transform */ +static const ulong32 rs_tab0[256] = { +0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU, +0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU, +0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU, +0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU, +0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU, +0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU, +0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU, +0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU, +0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU, +0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU, +0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU, +0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU, +0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU, +0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU, +0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU, +0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU, +0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU, +0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU, +0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU, +0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU, +0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU, +0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU, +0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU, +0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU, +0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU, +0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU, +0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU, +0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU, +0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU, +0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU, +0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU, +0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU }; + +static const ulong32 rs_tab1[256] = { +0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU, +0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU, +0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU, +0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU, +0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU, +0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU, +0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU, +0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU, +0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU, +0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU, +0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU, +0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU, +0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU, +0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU, +0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU, +0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU, +0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU, +0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU, +0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU, +0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU, +0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU, +0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU, +0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU, +0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU, +0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU, +0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU, +0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU, +0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU, +0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU, +0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU, +0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU, +0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU }; + +static const ulong32 rs_tab2[256] = { +0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU, +0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU, +0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU, +0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU, +0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU, +0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU, +0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU, +0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU, +0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU, +0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU, +0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU, +0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU, +0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU, +0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU, +0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU, +0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU, +0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU, +0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU, +0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU, +0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU, +0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU, +0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU, +0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU, +0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU, +0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU, +0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU, +0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU, +0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU, +0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU, +0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU, +0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU, +0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU }; + +static const ulong32 rs_tab3[256] = { +0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU, +0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU, +0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU, +0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU, +0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU, +0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU, +0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU, +0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU, +0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU, +0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU, +0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU, +0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU, +0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU, +0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU, +0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU, +0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU, +0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU, +0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU, +0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU, +0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU, +0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU, +0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU, +0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU, +0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU, +0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU, +0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU, +0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU, +0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU, +0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU, +0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU, +0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU, +0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU }; + +static const ulong32 rs_tab4[256] = { +0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU, +0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU, +0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU, +0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU, +0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU, +0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU, +0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU, +0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU, +0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU, +0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU, +0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU, +0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU, +0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU, +0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU, +0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU, +0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU, +0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU, +0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU, +0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU, +0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU, +0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU, +0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU, +0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU, +0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU, +0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU, +0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU, +0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU, +0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU, +0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU, +0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU, +0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU, +0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU }; + +static const ulong32 rs_tab5[256] = { +0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU, +0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU, +0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU, +0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU, +0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU, +0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU, +0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU, +0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU, +0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU, +0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU, +0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU, +0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU, +0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU, +0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU, +0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU, +0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU, +0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU, +0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU, +0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU, +0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU, +0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU, +0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU, +0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU, +0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU, +0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU, +0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU, +0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU, +0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU, +0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU, +0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU, +0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU, +0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU }; + +static const ulong32 rs_tab6[256] = { +0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU, +0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU, +0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU, +0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU, +0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU, +0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU, +0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU, +0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU, +0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU, +0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU, +0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU, +0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU, +0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU, +0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU, +0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU, +0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU, +0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU, +0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU, +0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU, +0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU, +0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU, +0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU, +0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU, +0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU, +0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU, +0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU, +0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU, +0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU, +0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU, +0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU, +0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU, +0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU }; + +static const ulong32 rs_tab7[256] = { +0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU, +0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU, +0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU, +0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU, +0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU, +0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU, +0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU, +0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU, +0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU, +0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU, +0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU, +0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU, +0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU, +0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU, +0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU, +0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU, +0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU, +0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU, +0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU, +0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU, +0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU, +0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU, +0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU, +0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU, +0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU, +0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU, +0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU, +0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU, +0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU, +0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU, +0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU, +0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU }; + +#endif /* LTC_TWOFISH_ALL_TABLES */ + +#endif /* LTC_TWOFISH_TAB_C */ +#endif diff --git a/deps/libtomcrypt/src/ciphers/xtea.c b/deps/libtomcrypt/src/ciphers/xtea.c new file mode 100644 index 0000000..95aaa1a --- /dev/null +++ b/deps/libtomcrypt/src/ciphers/xtea.c @@ -0,0 +1,251 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file xtea.c + Implementation of eXtended TEA, Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_XTEA + +const struct ltc_cipher_descriptor xtea_desc = +{ + "xtea", + 1, + 16, 16, 8, 32, + &xtea_setup, + &xtea_ecb_encrypt, + &xtea_ecb_decrypt, + &xtea_test, + &xtea_done, + &xtea_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + ulong32 x, sum, K[4]; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + /* check arguments */ + if (keylen != 16) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != 32) { + return CRYPT_INVALID_ROUNDS; + } + + /* load key */ + LOAD32H(K[0], key+0); + LOAD32H(K[1], key+4); + LOAD32H(K[2], key+8); + LOAD32H(K[3], key+12); + + for (x = sum = 0; x < 32; x++) { + skey->xtea.A[x] = (sum + K[sum&3]) & 0xFFFFFFFFUL; + sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL; + skey->xtea.B[x] = (sum + K[(sum>>11)&3]) & 0xFFFFFFFFUL; + } + +#ifdef LTC_CLEAN_STACK + zeromem(&K, sizeof(K)); +#endif + + return CRYPT_OK; +} + +/** + Encrypts a block of text with LTC_XTEA + @param pt The input plaintext (8 bytes) + @param ct The output ciphertext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + ulong32 y, z; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(y, &pt[0]); + LOAD32H(z, &pt[4]); + for (r = 0; r < 32; r += 4) { + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; + + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+1])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+1])) & 0xFFFFFFFFUL; + + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+2])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+2])) & 0xFFFFFFFFUL; + + y = (y + ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r+3])) & 0xFFFFFFFFUL; + z = (z + ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r+3])) & 0xFFFFFFFFUL; + } + STORE32H(y, &ct[0]); + STORE32H(z, &ct[4]); + return CRYPT_OK; +} + +/** + Decrypts a block of text with LTC_XTEA + @param ct The input ciphertext (8 bytes) + @param pt The output plaintext (8 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + ulong32 y, z; + int r; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + LOAD32H(y, &ct[0]); + LOAD32H(z, &ct[4]); + for (r = 31; r >= 0; r -= 4) { + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r])) & 0xFFFFFFFFUL; + + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-1])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-1])) & 0xFFFFFFFFUL; + + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-2])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-2])) & 0xFFFFFFFFUL; + + z = (z - ((((y<<4)^(y>>5)) + y) ^ skey->xtea.B[r-3])) & 0xFFFFFFFFUL; + y = (y - ((((z<<4)^(z>>5)) + z) ^ skey->xtea.A[r-3])) & 0xFFFFFFFFUL; + } + STORE32H(y, &pt[0]); + STORE32H(z, &pt[4]); + return CRYPT_OK; +} + +/** + Performs a self-test of the LTC_XTEA block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int xtea_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + unsigned char key[16], pt[8], ct[8]; + } tests[] = { + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xde, 0xe9, 0xd4, 0xd8, 0xf7, 0x13, 0x1e, 0xd9 } + }, { + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xa5, 0x97, 0xab, 0x41, 0x76, 0x01, 0x4d, 0x72 } + }, { + { 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 }, + { 0xb1, 0xfd, 0x5d, 0xa9, 0xcc, 0x6d, 0xc9, 0xdc } + }, { + { 0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, + 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 }, + { 0x70, 0x4b, 0x31, 0x34, 0x47, 0x44, 0xdf, 0xab } + }, { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 } + }, { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 } + }, { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } + }, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, + { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 } + }, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, + { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d } + }, { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 }, + { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } + } + }; + unsigned char tmp[2][8]; + symmetric_key skey; + int i, err, y; + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&skey, sizeof(skey)); + if ((err = xtea_setup(tests[i].key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + xtea_ecb_encrypt(tests[i].pt, tmp[0], &skey); + xtea_ecb_decrypt(tmp[0], tmp[1], &skey); + + if (compare_testvector(tmp[0], 8, tests[i].ct, 8, "XTEA Encrypt", i) != 0 || + compare_testvector(tmp[1], 8, tests[i].pt, 8, "XTEA Decrypt", i) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 8; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey); + for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } /* for */ + + return CRYPT_OK; + #endif +} + +/** Terminate the context + @param skey The scheduled key +*/ +void xtea_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int xtea_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + *keysize = 16; + return CRYPT_OK; +} + + +#endif + + + diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_add_aad.c b/deps/libtomcrypt/src/encauth/ccm/ccm_add_aad.c new file mode 100644 index 0000000..130d304 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_add_aad.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Add AAD to the CCM state + @param ccm The CCM state + @param adata The additional authentication data to add to the CCM state + @param adatalen The length of the AAD data. + @return CRYPT_OK on success + */ +int ccm_add_aad(ccm_state *ccm, + const unsigned char *adata, unsigned long adatalen) +{ + unsigned long y; + int err; + + LTC_ARGCHK(ccm != NULL); + LTC_ARGCHK(adata != NULL); + + if (ccm->aadlen < ccm->current_aadlen + adatalen) { + return CRYPT_INVALID_ARG; + } + ccm->current_aadlen += adatalen; + + /* now add the data */ + for (y = 0; y < adatalen; y++) { + if (ccm->x == 16) { + /* full block so let's encrypt it */ + if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->x = 0; + } + ccm->PAD[ccm->x++] ^= adata[y]; + } + + /* remainder? */ + if (ccm->aadlen == ccm->current_aadlen) { + if (ccm->x != 0) { + if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + } + ccm->x = 0; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c b/deps/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c new file mode 100644 index 0000000..a48d48d --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_add_nonce.c @@ -0,0 +1,106 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Add nonce data to the CCM state + @param ccm The CCM state + @param nonce The nonce data to add + @param noncelen The length of the nonce + @return CRYPT_OK on success + */ +int ccm_add_nonce(ccm_state *ccm, + const unsigned char *nonce, unsigned long noncelen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(ccm != NULL); + LTC_ARGCHK(nonce != NULL); + + /* increase L to match the nonce len */ + ccm->noncelen = (noncelen > 13) ? 13 : noncelen; + if ((15 - ccm->noncelen) > ccm->L) { + ccm->L = 15 - ccm->noncelen; + } + if (ccm->L > 8) { + return CRYPT_INVALID_ARG; + } + + /* decrease noncelen to match L */ + if ((ccm->noncelen + ccm->L) > 15) { + ccm->noncelen = 15 - ccm->L; + } + + /* form B_0 == flags | Nonce N | l(m) */ + x = 0; + ccm->PAD[x++] = (unsigned char)(((ccm->aadlen > 0) ? (1<<6) : 0) | + (((ccm->taglen - 2)>>1)<<3) | + (ccm->L-1)); + + /* nonce */ + for (y = 0; y < 15 - ccm->L; y++) { + ccm->PAD[x++] = nonce[y]; + } + + /* store len */ + len = ccm->ptlen; + + /* shift len so the upper bytes of len are the contents of the length */ + for (y = ccm->L; y < 4; y++) { + len <<= 8; + } + + /* store l(m) (only store 32-bits) */ + for (y = 0; ccm->L > 4 && (ccm->L-y)>4; y++) { + ccm->PAD[x++] = 0; + } + for (; y < ccm->L; y++) { + ccm->PAD[x++] = (unsigned char)((len >> 24) & 255); + len <<= 8; + } + + /* encrypt PAD */ + if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + + /* handle header */ + ccm->x = 0; + if (ccm->aadlen > 0) { + /* store length */ + if (ccm->aadlen < ((1UL<<16) - (1UL<<8))) { + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; + ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; + } else { + ccm->PAD[ccm->x++] ^= 0xFF; + ccm->PAD[ccm->x++] ^= 0xFE; + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>24) & 255; + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>16) & 255; + ccm->PAD[ccm->x++] ^= (ccm->aadlen>>8) & 255; + ccm->PAD[ccm->x++] ^= ccm->aadlen & 255; + } + } + + /* setup the ctr counter */ + x = 0; + + /* flags */ + ccm->ctr[x++] = (unsigned char)ccm->L-1; + + /* nonce */ + for (y = 0; y < (16 - (ccm->L+1)); ++y) { + ccm->ctr[x++] = nonce[y]; + } + /* offset */ + while (x < 16) { + ccm->ctr[x++] = 0; + } + + ccm->CTRlen = 16; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_done.c b/deps/libtomcrypt/src/encauth/ccm/ccm_done.c new file mode 100644 index 0000000..965121d --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_done.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Terminate a CCM stream + @param ccm The CCM state + @param tag [out] The destination for the MAC tag + @param taglen [in/out] The length of the MAC tag + @return CRYPT_OK on success + */ +int ccm_done(ccm_state *ccm, + unsigned char *tag, unsigned long *taglen) +{ + unsigned long x, y; + int err; + + LTC_ARGCHK(ccm != NULL); + + /* Check all data have been processed */ + if (ccm->ptlen != ccm->current_ptlen) { + return CRYPT_ERROR; + } + + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + if (ccm->x != 0) { + if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + } + + /* setup CTR for the TAG (zero the count) */ + for (y = 15; y > 15 - ccm->L; y--) { + ccm->ctr[y] = 0x00; + } + if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { + return err; + } + + cipher_descriptor[ccm->cipher].done(&ccm->K); + + /* store the TAG */ + for (x = 0; x < 16 && x < *taglen; x++) { + tag[x] = ccm->PAD[x] ^ ccm->CTRPAD[x]; + } + *taglen = x; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_init.c b/deps/libtomcrypt/src/encauth/ccm/ccm_init.c new file mode 100644 index 0000000..527c6af --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_init.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Initialize a CCM state + @param ccm The CCM state to initialize + @param cipher The index of the cipher to use + @param key The secret key + @param keylen The length of the secret key + @param ptlen The length of the plain/cipher text that will be processed + @param taglen The max length of the MAC tag + @param aadlen The length of the AAD + + @return CRYPT_OK on success + */ +int ccm_init(ccm_state *ccm, int cipher, + const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen) +{ + int err; + + LTC_ARGCHK(ccm != NULL); + LTC_ARGCHK(key != NULL); + + XMEMSET(ccm, 0, sizeof(ccm_state)); + + /* check cipher input */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_CIPHER; + } + + /* make sure the taglen is valid */ + if (taglen < 4 || taglen > 16 || (taglen % 2) == 1 || aadlen < 0 || ptlen < 0) { + return CRYPT_INVALID_ARG; + } + ccm->taglen = taglen; + + /* schedule key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->cipher = cipher; + + /* let's get the L value */ + ccm->ptlen = ptlen; + ccm->L = 0; + while (ptlen) { + ++ccm->L; + ptlen >>= 8; + } + if (ccm->L <= 1) { + ccm->L = 2; + } + + ccm->aadlen = aadlen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_memory.c b/deps/libtomcrypt/src/encauth/ccm/ccm_memory.c new file mode 100644 index 0000000..fdb5172 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_memory.c @@ -0,0 +1,372 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ccm_memory.c + CCM support, process a block of memory, Tom St Denis +*/ + +#ifdef LTC_CCM_MODE + +/** + CCM encrypt/decrypt and produce an authentication tag + + *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction' + + @param cipher The index of the cipher desired + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param uskey A previously scheduled key [optional can be NULL] + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt [*1] The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [*1] The ciphertext + @param tag [*1] The destination tag + @param taglen The max size and resulting size of the authentication tag + @param direction Encrypt or Decrypt direction (0 or 1) + @return CRYPT_OK if successful +*/ +int ccm_memory(int cipher, + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction) +{ + unsigned char PAD[16], ctr[16], CTRPAD[16], ptTag[16], b, *pt_real; + unsigned char *pt_work = NULL; + symmetric_key *skey; + int err; + unsigned long len, L, x, y, z, CTRlen; + + if (uskey == NULL) { + LTC_ARGCHK(key != NULL); + } + LTC_ARGCHK(nonce != NULL); + if (headerlen > 0) { + LTC_ARGCHK(header != NULL); + } + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + pt_real = pt; + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* check cipher input */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_CIPHER; + } + + /* make sure the taglen is valid */ + if (*taglen < 4 || *taglen > 16 || (*taglen % 2) == 1 || headerlen > 0x7fffffffu) { + return CRYPT_INVALID_ARG; + } + + /* is there an accelerator? */ + if (cipher_descriptor[cipher].accel_ccm_memory != NULL) { + return cipher_descriptor[cipher].accel_ccm_memory( + key, keylen, + uskey, + nonce, noncelen, + header, headerlen, + pt, ptlen, + ct, + tag, taglen, + direction); + } + + /* let's get the L value */ + len = ptlen; + L = 0; + while (len) { + ++L; + len >>= 8; + } + if (L <= 1) { + L = 2; + } + + /* increase L to match the nonce len */ + noncelen = (noncelen > 13) ? 13 : noncelen; + if ((15 - noncelen) > L) { + L = 15 - noncelen; + } + if (L > 8) { + return CRYPT_INVALID_ARG; + } + + /* allocate mem for the symmetric key */ + if (uskey == NULL) { + skey = XMALLOC(sizeof(*skey)); + if (skey == NULL) { + return CRYPT_MEM; + } + + /* initialize the cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) { + XFREE(skey); + return err; + } + } else { + skey = uskey; + } + + /* initialize buffer for pt */ + if (direction == CCM_DECRYPT && ptlen > 0) { + pt_work = XMALLOC(ptlen); + if (pt_work == NULL) { + goto error; + } + pt = pt_work; + } + + /* form B_0 == flags | Nonce N | l(m) */ + x = 0; + PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | + (((*taglen - 2)>>1)<<3) | + (L-1)); + + /* nonce */ + for (y = 0; y < 15 - L; y++) { + PAD[x++] = nonce[y]; + } + + /* store len */ + len = ptlen; + + /* shift len so the upper bytes of len are the contents of the length */ + for (y = L; y < 4; y++) { + len <<= 8; + } + + /* store l(m) (only store 32-bits) */ + for (y = 0; L > 4 && (L-y)>4; y++) { + PAD[x++] = 0; + } + for (; y < L; y++) { + PAD[x++] = (unsigned char)((len >> 24) & 255); + len <<= 8; + } + + /* encrypt PAD */ + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + + /* handle header */ + if (headerlen > 0) { + x = 0; + + /* store length */ + if (headerlen < ((1UL<<16) - (1UL<<8))) { + PAD[x++] ^= (headerlen>>8) & 255; + PAD[x++] ^= headerlen & 255; + } else { + PAD[x++] ^= 0xFF; + PAD[x++] ^= 0xFE; + PAD[x++] ^= (headerlen>>24) & 255; + PAD[x++] ^= (headerlen>>16) & 255; + PAD[x++] ^= (headerlen>>8) & 255; + PAD[x++] ^= headerlen & 255; + } + + /* now add the data */ + for (y = 0; y < headerlen; y++) { + if (x == 16) { + /* full block so let's encrypt it */ + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + x = 0; + } + PAD[x++] ^= header[y]; + } + + /* remainder */ + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + + /* setup the ctr counter */ + x = 0; + + /* flags */ + ctr[x++] = (unsigned char)L-1; + + /* nonce */ + for (y = 0; y < (16 - (L+1)); ++y) { + ctr[x++] = nonce[y]; + } + /* offset */ + while (x < 16) { + ctr[x++] = 0; + } + + x = 0; + CTRlen = 16; + + /* now handle the PT */ + if (ptlen > 0) { + y = 0; +#ifdef LTC_FAST + if (ptlen & ~15) { + if (direction == CCM_ENCRYPT) { + for (; y < (ptlen & ~15); y += 16) { + /* increment the ctr? */ + for (z = 15; z > 15-L; z--) { + ctr[z] = (ctr[z] + 1) & 255; + if (ctr[z]) break; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + + /* xor the PT against the pad first */ + for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); + *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } else { /* direction == CCM_DECRYPT */ + for (; y < (ptlen & ~15); y += 16) { + /* increment the ctr? */ + for (z = 15; z > 15-L; z--) { + ctr[z] = (ctr[z] + 1) & 255; + if (ctr[z]) break; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + + /* xor the PT against the pad last */ + for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); + *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } + } +#endif + + for (; y < ptlen; y++) { + /* increment the ctr? */ + if (CTRlen == 16) { + for (z = 15; z > 15-L; z--) { + ctr[z] = (ctr[z] + 1) & 255; + if (ctr[z]) break; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + CTRlen = 0; + } + + /* if we encrypt we add the bytes to the MAC first */ + if (direction == CCM_ENCRYPT) { + b = pt[y]; + ct[y] = b ^ CTRPAD[CTRlen++]; + } else { + b = ct[y] ^ CTRPAD[CTRlen++]; + pt[y] = b; + } + + if (x == 16) { + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + x = 0; + } + PAD[x++] ^= b; + } + + if (x != 0) { + if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { + goto error; + } + } + } + + /* setup CTR for the TAG (zero the count) */ + for (y = 15; y > 15 - L; y--) { + ctr[y] = 0x00; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { + goto error; + } + + if (skey != uskey) { + cipher_descriptor[cipher].done(skey); +#ifdef LTC_CLEAN_STACK + zeromem(skey, sizeof(*skey)); +#endif + } + + if (direction == CCM_ENCRYPT) { + /* store the TAG */ + for (x = 0; x < 16 && x < *taglen; x++) { + tag[x] = PAD[x] ^ CTRPAD[x]; + } + *taglen = x; + } else { /* direction == CCM_DECRYPT */ + /* decrypt the tag */ + for (x = 0; x < 16 && x < *taglen; x++) { + ptTag[x] = tag[x] ^ CTRPAD[x]; + } + *taglen = x; + + /* check validity of the decrypted tag against the computed PAD (in constant time) */ + /* HACK: the boolean value of XMEM_NEQ becomes either 0 (CRYPT_OK) or 1 (CRYPT_ERR). + * there should be a better way of setting the correct error code in constant + * time. + */ + err = XMEM_NEQ(ptTag, PAD, *taglen); + + /* Zero the plaintext if the tag was invalid (in constant time) */ + if (ptlen > 0) { + copy_or_zeromem(pt, pt_real, ptlen, err); + } + } + +#ifdef LTC_CLEAN_STACK + zeromem(PAD, sizeof(PAD)); + zeromem(CTRPAD, sizeof(CTRPAD)); + if (pt_work != NULL) { + zeromem(pt_work, ptlen); + } +#endif +error: + if (pt_work) { + XFREE(pt_work); + } + if (skey != uskey) { + XFREE(skey); + } + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_process.c b/deps/libtomcrypt/src/encauth/ccm/ccm_process.c new file mode 100644 index 0000000..3d22480 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_process.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Process plaintext/ciphertext through CCM + @param ccm The CCM state + @param pt The plaintext + @param ptlen The plaintext length (ciphertext length is the same) + @param ct The ciphertext + @param direction Encrypt or Decrypt mode (CCM_ENCRYPT or CCM_DECRYPT) + @return CRYPT_OK on success + */ +int ccm_process(ccm_state *ccm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction) +{ + unsigned char z, b; + unsigned long y; + int err; + + LTC_ARGCHK(ccm != NULL); + + /* Check aad has been correctly added */ + if (ccm->aadlen != ccm->current_aadlen) { + return CRYPT_ERROR; + } + + /* Check we do not process too much data */ + if (ccm->ptlen < ccm->current_ptlen + ptlen) { + return CRYPT_ERROR; + } + ccm->current_ptlen += ptlen; + + /* now handle the PT */ + if (ptlen > 0) { + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + for (y = 0; y < ptlen; y++) { + /* increment the ctr? */ + if (ccm->CTRlen == 16) { + for (z = 15; z > 15-ccm->L; z--) { + ccm->ctr[z] = (ccm->ctr[z] + 1) & 255; + if (ccm->ctr[z]) break; + } + if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->ctr, ccm->CTRPAD, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->CTRlen = 0; + } + + /* if we encrypt we add the bytes to the MAC first */ + if (direction == CCM_ENCRYPT) { + b = pt[y]; + ct[y] = b ^ ccm->CTRPAD[ccm->CTRlen++]; + } else { + b = ct[y] ^ ccm->CTRPAD[ccm->CTRlen++]; + pt[y] = b; + } + + if (ccm->x == 16) { + if ((err = cipher_descriptor[ccm->cipher].ecb_encrypt(ccm->PAD, ccm->PAD, &ccm->K)) != CRYPT_OK) { + return err; + } + ccm->x = 0; + } + ccm->PAD[ccm->x++] ^= b; + } + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_reset.c b/deps/libtomcrypt/src/encauth/ccm/ccm_reset.c new file mode 100644 index 0000000..93b8fec --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_reset.c @@ -0,0 +1,25 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_CCM_MODE + +/** + Reset a CCM state to as if you just called ccm_init(). This saves the initialization time. + @param ccm The CCM state to reset + @return CRYPT_OK on success +*/ +int ccm_reset(ccm_state *ccm) +{ + LTC_ARGCHK(ccm != NULL); + zeromem(ccm->PAD, sizeof(ccm->PAD)); + zeromem(ccm->ctr, sizeof(ccm->ctr)); + zeromem(ccm->CTRPAD, sizeof(ccm->CTRPAD)); + ccm->CTRlen = 0; + ccm->current_ptlen = 0; + ccm->current_aadlen = 0; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ccm/ccm_test.c b/deps/libtomcrypt/src/encauth/ccm/ccm_test.c new file mode 100644 index 0000000..04d97b1 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ccm/ccm_test.c @@ -0,0 +1,274 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ccm_test.c + CCM support, process a block of memory, Tom St Denis +*/ + +#ifdef LTC_CCM_MODE + +int ccm_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16]; + unsigned char nonce[16]; + int noncelen; + unsigned char header[64]; + int headerlen; + unsigned char pt[64]; + int ptlen; + unsigned char ct[64]; + unsigned char tag[16]; + unsigned long taglen; + } tests[] = { + +/* 13 byte nonce, 8 byte auth, 23 byte pt */ +{ + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, + { 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, + 13, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, + 8, + { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E }, + 23, + { 0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2, + 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80, + 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84 }, + { 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 }, + 8 +}, + +/* 13 byte nonce, 12 byte header, 19 byte pt */ +{ + { 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF }, + { 0x00, 0x00, 0x00, 0x06, 0x05, 0x04, 0x03, 0xA0, + 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 }, + 13, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B }, + 12, + { 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E }, + 19, + { 0xA2, 0x8C, 0x68, 0x65, 0x93, 0x9A, 0x9A, 0x79, + 0xFA, 0xAA, 0x5C, 0x4C, 0x2A, 0x9D, 0x4A, 0x91, + 0xCD, 0xAC, 0x8C }, + { 0x96, 0xC8, 0x61, 0xB9, 0xC9, 0xE6, 0x1E, 0xF1 }, + 8 +}, + +/* supplied by Brian Gladman */ +{ + { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }, + { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }, + 7, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }, + 8, + { 0x20, 0x21, 0x22, 0x23 }, + 4, + { 0x71, 0x62, 0x01, 0x5b }, + { 0x4d, 0xac, 0x25, 0x5d }, + 4 +}, + +{ + { 0xc9, 0x7c, 0x1f, 0x67, 0xce, 0x37, 0x11, 0x85, + 0x51, 0x4a, 0x8a, 0x19, 0xf2, 0xbd, 0xd5, 0x2f }, + { 0x00, 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xb5, + 0x03, 0x97, 0x76, 0xe7, 0x0c }, + 13, + { 0x08, 0x40, 0x0f, 0xd2, 0xe1, 0x28, 0xa5, 0x7c, + 0x50, 0x30, 0xf1, 0x84, 0x44, 0x08, 0xab, 0xae, + 0xa5, 0xb8, 0xfc, 0xba, 0x00, 0x00 }, + 22, + { 0xf8, 0xba, 0x1a, 0x55, 0xd0, 0x2f, 0x85, 0xae, + 0x96, 0x7b, 0xb6, 0x2f, 0xb6, 0xcd, 0xa8, 0xeb, + 0x7e, 0x78, 0xa0, 0x50 }, + 20, + { 0xf3, 0xd0, 0xa2, 0xfe, 0x9a, 0x3d, 0xbf, 0x23, + 0x42, 0xa6, 0x43, 0xe4, 0x32, 0x46, 0xe8, 0x0c, + 0x3c, 0x04, 0xd0, 0x19 }, + { 0x78, 0x45, 0xce, 0x0b, 0x16, 0xf9, 0x76, 0x23 }, + 8 +}, + +}; + unsigned long taglen, x, y; + unsigned char buf[64], buf2[64], tag[16], tag2[16], tag3[16], zero[64]; + int err, idx; + symmetric_key skey; + ccm_state ccm; + + zeromem(zero, 64); + + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (sizeof(tests)/sizeof(tests[0])); x++) { + for (y = 0; y < 2; y++) { + taglen = tests[x].taglen; + if (y == 0) { + if ((err = cipher_descriptor[idx].setup(tests[x].key, 16, 0, &skey)) != CRYPT_OK) { + return err; + } + + if ((err = ccm_memory(idx, + tests[x].key, 16, + &skey, + tests[x].nonce, tests[x].noncelen, + tests[x].header, tests[x].headerlen, + (unsigned char*)tests[x].pt, tests[x].ptlen, + buf, + tag, &taglen, 0)) != CRYPT_OK) { + return err; + } + /* run a second time to make sure skey is not touched */ + if ((err = ccm_memory(idx, + tests[x].key, 16, + &skey, + tests[x].nonce, tests[x].noncelen, + tests[x].header, tests[x].headerlen, + (unsigned char*)tests[x].pt, tests[x].ptlen, + buf, + tag, &taglen, 0)) != CRYPT_OK) { + return err; + } + } else { + if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_process(&ccm, (unsigned char*)tests[x].pt, tests[x].ptlen, buf, CCM_ENCRYPT)) != CRYPT_OK) { + return err; + } + if ((err = ccm_done(&ccm, tag, &taglen)) != CRYPT_OK) { + return err; + } + } + + if (compare_testvector(buf, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "CCM encrypt data", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if (compare_testvector(tag, taglen, tests[x].tag, tests[x].taglen, "CCM encrypt tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if (y == 0) { + XMEMCPY(tag3, tests[x].tag, tests[x].taglen); + taglen = tests[x].taglen; + if ((err = ccm_memory(idx, + tests[x].key, 16, + NULL, + tests[x].nonce, tests[x].noncelen, + tests[x].header, tests[x].headerlen, + buf2, tests[x].ptlen, + buf, + tag3, &taglen, 1 )) != CRYPT_OK) { + return err; + } + } else { + if ((err = ccm_init(&ccm, idx, tests[x].key, 16, tests[x].ptlen, tests[x].taglen, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_nonce(&ccm, tests[x].nonce, tests[x].noncelen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_add_aad(&ccm, tests[x].header, tests[x].headerlen)) != CRYPT_OK) { + return err; + } + if ((err = ccm_process(&ccm, buf2, tests[x].ptlen, buf, CCM_DECRYPT)) != CRYPT_OK) { + return err; + } + if ((err = ccm_done(&ccm, tag2, &taglen)) != CRYPT_OK) { + return err; + } + } + + + if (compare_testvector(buf2, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "CCM decrypt data", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + if (y == 0) { + /* check if decryption with the wrong tag does not reveal the plaintext */ + XMEMCPY(tag3, tests[x].tag, tests[x].taglen); + tag3[0] ^= 0xff; /* set the tag to the wrong value */ + taglen = tests[x].taglen; + if ((err = ccm_memory(idx, + tests[x].key, 16, + NULL, + tests[x].nonce, tests[x].noncelen, + tests[x].header, tests[x].headerlen, + buf2, tests[x].ptlen, + buf, + tag3, &taglen, 1 )) != CRYPT_ERROR) { + return CRYPT_FAIL_TESTVECTOR; + } + if (compare_testvector(buf2, tests[x].ptlen, zero, tests[x].ptlen, "CCM decrypt wrong tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } else { + if (compare_testvector(tag2, taglen, tests[x].tag, tests[x].taglen, "CCM decrypt tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + if (y == 0) { + cipher_descriptor[idx].done(&skey); + } + } + } + + /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/452 */ + { + unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; + unsigned char iv[] = { 0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51 }; + unsigned char valid_tag[] = { 0x23,0x1a,0x2d,0x8f }; + unsigned char invalid_tag[] = { 0x23,0x1a,0x2d,0x8f,0x6a }; + unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; + unsigned char ct[] = { 0xd3,0xda,0xb1,0xee,0x49,0x4c,0xc2,0x29,0x09,0x9d,0x6c,0xac,0x7d,0xf1,0x4a,0xdd }; + unsigned char pt[20] = { 0 }; + + /* VALID tag */ + taglen = sizeof(valid_tag); + err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, valid_tag, &taglen, CCM_DECRYPT); + if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* INVALID tag */ + taglen = sizeof(invalid_tag); + err = ccm_memory(idx, key, sizeof(key), NULL, iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, invalid_tag, &taglen, CCM_DECRYPT); + if (err == CRYPT_OK) { + return CRYPT_FAIL_TESTVECTOR; /* should fail */ + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c new file mode 100644 index 0000000..dc6b5bb --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_add_aad.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Add AAD to the ChaCha20Poly1305 state + @param st The ChaCha20Poly1305 state + @param in The additional authentication data to add to the ChaCha20Poly1305 state + @param inlen The length of the ChaCha20Poly1305 data. + @return CRYPT_OK on success + */ +int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen) +{ + int err; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + + if (st->aadflg == 0) return CRYPT_ERROR; + if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; + st->aadlen += (ulong64)inlen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c new file mode 100644 index 0000000..e51322a --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_decrypt.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Decrypt bytes of ciphertext with ChaCha20Poly1305 + @param st The ChaCha20Poly1305 state + @param in The ciphertext + @param inlen The length of the input (octets) + @param out [out] The plaintext (length inlen) + @return CRYPT_OK if successful +*/ +int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char padzero[16] = { 0 }; + unsigned long padlen; + int err; + + LTC_ARGCHK(st != NULL); + + if (st->aadflg) { + padlen = 16 - (unsigned long)(st->aadlen % 16); + if (padlen < 16) { + if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; + } + st->aadflg = 0; /* no more AAD */ + } + if (st->aadflg) st->aadflg = 0; /* no more AAD */ + if ((err = poly1305_process(&st->poly, in, inlen)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; + st->ctlen += (ulong64)inlen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c new file mode 100644 index 0000000..19d1640 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_done.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Terminate a ChaCha20Poly1305 stream + @param st The ChaCha20Poly1305 state + @param tag [out] The destination for the MAC tag + @param taglen [in/out] The length of the MAC tag + @return CRYPT_OK on success + */ +int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen) +{ + unsigned char padzero[16] = { 0 }; + unsigned long padlen; + unsigned char buf[16]; + int err; + + LTC_ARGCHK(st != NULL); + + padlen = 16 - (unsigned long)(st->ctlen % 16); + if (padlen < 16) { + if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; + } + STORE64L(st->aadlen, buf); + STORE64L(st->ctlen, buf + 8); + if ((err = poly1305_process(&st->poly, buf, 16)) != CRYPT_OK) return err; + if ((err = poly1305_done(&st->poly, tag, taglen)) != CRYPT_OK) return err; + if ((err = chacha_done(&st->chacha)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c new file mode 100644 index 0000000..2a4208e --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_encrypt.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Encrypt bytes of ciphertext with ChaCha20Poly1305 + @param st The ChaCha20Poly1305 state + @param in The plaintext + @param inlen The length of the input (octets) + @param out [out] The ciphertext (length inlen) + @return CRYPT_OK if successful +*/ +int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char padzero[16] = { 0 }; + unsigned long padlen; + int err; + + LTC_ARGCHK(st != NULL); + + if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK) return err; + if (st->aadflg) { + padlen = 16 - (unsigned long)(st->aadlen % 16); + if (padlen < 16) { + if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err; + } + st->aadflg = 0; /* no more AAD */ + } + if ((err = poly1305_process(&st->poly, out, inlen)) != CRYPT_OK) return err; + st->ctlen += (ulong64)inlen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c new file mode 100644 index 0000000..2654f4d --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_init.c @@ -0,0 +1,20 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Initialize an ChaCha20Poly1305 context (only the key) + @param st [out] The destination of the ChaCha20Poly1305 state + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen) +{ + return chacha_setup(&st->chacha, key, keylen, 20); +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c new file mode 100644 index 0000000..6e3bf24 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_memory.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Process an entire GCM packet in one call. + @param key The secret key + @param keylen The length of the secret key + @param iv The initialization vector + @param ivlen The length of the initialization vector + @param aad The additional authentication data (header) + @param aadlen The length of the aad + @param in The plaintext + @param inlen The length of the plaintext (ciphertext length is the same) + @param out The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (CHACHA20POLY1305_ENCRYPT or CHACHA20POLY1305_DECRYPT) + @return CRYPT_OK on success + */ +int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *aad, unsigned long aadlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, + unsigned char *tag, unsigned long *taglen, + int direction) +{ + chacha20poly1305_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + if ((err = chacha20poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = chacha20poly1305_setiv(&st, iv, ivlen)) != CRYPT_OK) { goto LBL_ERR; } + if (aad && aadlen > 0) { + if ((err = chacha20poly1305_add_aad(&st, aad, aadlen)) != CRYPT_OK) { goto LBL_ERR; } + } + if (direction == CHACHA20POLY1305_ENCRYPT) { + if ((err = chacha20poly1305_encrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = chacha20poly1305_done(&st, tag, taglen)) != CRYPT_OK) { goto LBL_ERR; } + } + else if (direction == CHACHA20POLY1305_DECRYPT) { + unsigned char buf[MAXBLOCKSIZE]; + unsigned long buflen = sizeof(buf); + if ((err = chacha20poly1305_decrypt(&st, in, inlen, out)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = chacha20poly1305_done(&st, buf, &buflen)) != CRYPT_OK) { goto LBL_ERR; } + if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { + err = CRYPT_ERROR; + goto LBL_ERR; + } + } + else { + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(chacha20poly1305_state)); +#endif + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c new file mode 100644 index 0000000..d5ec3e6 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv.c @@ -0,0 +1,58 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Set IV + counter data to the ChaCha20Poly1305 state and reset the context + @param st The ChaCha20Poly1305 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12 or 8) + @return CRYPT_OK on success + */ +int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen) +{ + chacha_state tmp_st; + int i, err; + unsigned char polykey[32]; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(ivlen == 12 || ivlen == 8); + + /* set IV for chacha20 */ + if (ivlen == 12) { + /* IV 96bit */ + if ((err = chacha_ivctr32(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; + } + else { + /* IV 64bit */ + if ((err = chacha_ivctr64(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err; + } + + /* copy chacha20 key to temporary state */ + for(i = 0; i < 12; i++) tmp_st.input[i] = st->chacha.input[i]; + tmp_st.rounds = 20; + /* set IV */ + if (ivlen == 12) { + /* IV 32bit */ + if ((err = chacha_ivctr32(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; + } + else { + /* IV 64bit */ + if ((err = chacha_ivctr64(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err; + } + /* (re)generate new poly1305 key */ + if ((err = chacha_keystream(&tmp_st, polykey, 32)) != CRYPT_OK) return err; + /* (re)initialise poly1305 */ + if ((err = poly1305_init(&st->poly, polykey, 32)) != CRYPT_OK) return err; + st->ctlen = 0; + st->aadlen = 0; + st->aadflg = 1; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c new file mode 100644 index 0000000..75da634 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_setiv_rfc7905.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +/** + Set IV + counter data (with RFC7905-magic) to the ChaCha20Poly1305 state and reset the context + @param st The ChaCha20Poly1305 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12 or 8) + @param sequence_number 64bit sequence number which is incorporated into IV as described in RFC7905 + @return CRYPT_OK on success + */ +int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number) +{ + int i; + unsigned char combined_iv[12] = { 0 }; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(ivlen == 12); + + STORE64L(sequence_number, combined_iv + 4); + for (i = 0; i < 12; i++) combined_iv[i] = iv[i] ^ combined_iv[i]; + return chacha20poly1305_setiv(st, combined_iv, 12); +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c new file mode 100644 index 0000000..30d4973 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/chachapoly/chacha20poly1305_test.c @@ -0,0 +1,159 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20POLY1305_MODE + +int chacha20poly1305_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + chacha20poly1305_state st1, st2; + unsigned char k[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }; + unsigned char i12[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 }; + unsigned char i8[] = { 0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43 }; + unsigned char aad[] = { 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7 }; + unsigned char enc[] = { 0xD3, 0x1A, 0x8D, 0x34, 0x64, 0x8E, 0x60, 0xDB, 0x7B, 0x86, 0xAF, 0xBC, 0x53, 0xEF, 0x7E, 0xC2, + 0xA4, 0xAD, 0xED, 0x51, 0x29, 0x6E, 0x08, 0xFE, 0xA9, 0xE2, 0xB5, 0xA7, 0x36, 0xEE, 0x62, 0xD6, + 0x3D, 0xBE, 0xA4, 0x5E, 0x8C, 0xA9, 0x67, 0x12, 0x82, 0xFA, 0xFB, 0x69, 0xDA, 0x92, 0x72, 0x8B, + 0x1A, 0x71, 0xDE, 0x0A, 0x9E, 0x06, 0x0B, 0x29, 0x05, 0xD6, 0xA5, 0xB6, 0x7E, 0xCD, 0x3B, 0x36, + 0x92, 0xDD, 0xBD, 0x7F, 0x2D, 0x77, 0x8B, 0x8C, 0x98, 0x03, 0xAE, 0xE3, 0x28, 0x09, 0x1B, 0x58, + 0xFA, 0xB3, 0x24, 0xE4, 0xFA, 0xD6, 0x75, 0x94, 0x55, 0x85, 0x80, 0x8B, 0x48, 0x31, 0xD7, 0xBC, + 0x3F, 0xF4, 0xDE, 0xF0, 0x8E, 0x4B, 0x7A, 0x9D, 0xE5, 0x76, 0xD2, 0x65, 0x86, 0xCE, 0xC6, 0x4B, + 0x61, 0x16 }; + unsigned char tag[] = { 0x1A, 0xE1, 0x0B, 0x59, 0x4F, 0x09, 0xE2, 0x6A, 0x7E, 0x90, 0x2E, 0xCB, 0xD0, 0x60, 0x06, 0x91 }; + char m[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + unsigned long mlen = XSTRLEN(m); + unsigned long len; + unsigned char rfc7905_pt[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; + unsigned char rfc7905_enc[] = { 0xE4, 0x62, 0x85, 0xB4, 0x29, 0x95, 0x34, 0x96, 0xAB, 0xFB, 0x67, 0xCD, 0xAE, 0xAC, 0x94, 0x1E }; + unsigned char rfc7905_tag[] = { 0x16, 0x2C, 0x92, 0x48, 0x2A, 0xDB, 0xD3, 0x5D, 0x48, 0xBE, 0xC6, 0xFF, 0x10, 0x9C, 0xBA, 0xE4 }; + unsigned char ct[1000], pt[1000], emac[16], dmac[16]; + int err; + + /* encrypt IV 96bit */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st1, i12, sizeof(i12))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + /* encrypt piece by piece */ + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, 25, ct)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 25, 10, ct + 25)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 35, 35, ct + 35)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 70, 5, ct + 70)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 75, 5, ct + 75)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m + 80, mlen - 80, ct + 80)) != CRYPT_OK) return err; + len = sizeof(emac); + if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* decrypt IV 96bit */ + if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st2, i12, sizeof(i12))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st2, ct, 21, pt)) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st2, ct + 21, mlen - 21, pt + 21)) != CRYPT_OK) return err; + len = sizeof(dmac); + if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(pt, mlen, m, mlen, "DEC-PT", 3) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(dmac, len, tag, sizeof(tag), "DEC-TAG", 4) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* chacha20poly1305_memory - encrypt */ + len = sizeof(emac); + if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), (unsigned char *)m, + mlen, ct, emac, &len, CHACHA20POLY1305_ENCRYPT)) != CRYPT_OK) return err; + if (compare_testvector(ct, mlen, enc, sizeof(enc), "ENC-CT2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(emac, len, tag, sizeof(tag), "ENC-TAG2", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* chacha20poly1305_memory - decrypt */ + len = sizeof(dmac); + XMEMCPY(dmac, tag, sizeof(tag)); + if ((err = chacha20poly1305_memory(k, sizeof(k), i12, sizeof(i12), aad, sizeof(aad), + ct, mlen, pt, dmac, &len, CHACHA20POLY1305_DECRYPT)) != CRYPT_OK) return err; + if (compare_testvector(pt, mlen, m, mlen, "DEC-PT2", 3) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* encrypt - rfc7905 */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, rfc7905_pt, 16, ct)) != CRYPT_OK) return err; + len = sizeof(emac); + if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(ct, 16, rfc7905_enc, 16, "ENC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(emac, len, rfc7905_tag, 16, "ENC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* decrypt - rfc7905 */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv_rfc7905(&st1, i12, sizeof(i12), CONST64(0x1122334455667788))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st1, ct, 16, pt)) != CRYPT_OK) return err; + len = sizeof(dmac); + if ((err = chacha20poly1305_done(&st1, dmac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(pt, 16, rfc7905_pt, 16, "DEC-CT3", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(dmac, len, rfc7905_tag, 16, "DEC-TAG3", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* encrypt IV 64bit */ + if ((err = chacha20poly1305_init(&st1, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st1, i8, sizeof(i8))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st1, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_encrypt(&st1, (unsigned char *)m, mlen, ct)) != CRYPT_OK) return err; + len = sizeof(emac); + if ((err = chacha20poly1305_done(&st1, emac, &len)) != CRYPT_OK) return err; + + /* decrypt IV 64bit */ + if ((err = chacha20poly1305_init(&st2, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_setiv(&st2, i8, sizeof(i8))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_add_aad(&st2, aad, sizeof(aad))) != CRYPT_OK) return err; + if ((err = chacha20poly1305_decrypt(&st2, ct, mlen, pt)) != CRYPT_OK) return err; + len = sizeof(dmac); + if ((err = chacha20poly1305_done(&st2, dmac, &len)) != CRYPT_OK) return err; + + if (compare_testvector(pt, mlen, m, mlen, "DEC-PT4", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(dmac, len, emac, len, "DEC-TAG4", 2) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ + { + unsigned char key[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff, + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; + unsigned char iv[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b }; + unsigned char valid_tag[] = { 0xa3,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; + unsigned char invalid_tag[] = { 0xa2,0xe3,0xfd,0xf9,0xfb,0xa6,0x86,0x1b,0x5a,0xd2,0x60,0x7f,0x40,0xb7,0xf4,0x47 }; + unsigned char waad[] = { 0x61,0x61,0x64 }; + unsigned char wct[] = { 0x00 }; + unsigned char wpt[20] = { 0 }; + unsigned char wtag[20] = { 0 }; + unsigned long taglen; + + /* encrypt */ + taglen = sizeof(wtag); + err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), + wpt, 0, wct, wtag, &taglen, CHACHA20POLY1305_ENCRYPT); + if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(wtag, taglen, valid_tag, sizeof(valid_tag), "WYCH", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* VALID tag */ + taglen = sizeof(valid_tag); + err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), + wpt, 0, wct, valid_tag, &taglen, CHACHA20POLY1305_DECRYPT); + if (err != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; + + /* INVALID tag */ + taglen = sizeof(invalid_tag); + err = chacha20poly1305_memory(key, sizeof(key), iv, sizeof(iv), waad, sizeof(waad), + wpt, 0, wct, invalid_tag, &taglen, CHACHA20POLY1305_DECRYPT); + if (err == CRYPT_OK) { + return CRYPT_FAIL_TESTVECTOR; /* should fail */ + } + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/eax/eax_addheader.c b/deps/libtomcrypt/src/encauth/eax/eax_addheader.c new file mode 100644 index 0000000..a6b8f76 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_addheader.c @@ -0,0 +1,26 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @file eax_addheader.c + EAX implementation, add meta-data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + add header (metadata) to the stream + @param eax The current EAX state + @param header The header (meta-data) data you wish to add to the state + @param length The length of the header data + @return CRYPT_OK if successful +*/ +int eax_addheader(eax_state *eax, const unsigned char *header, + unsigned long length) +{ + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(header != NULL); + return omac_process(&eax->headeromac, header, length); +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/eax/eax_decrypt.c b/deps/libtomcrypt/src/encauth/eax/eax_decrypt.c new file mode 100644 index 0000000..cc03c5c --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_decrypt.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_decrypt.c + EAX implementation, decrypt block, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + Decrypt data with the EAX protocol + @param eax The EAX state + @param ct The ciphertext + @param pt [out] The plaintext + @param length The length (octets) of the ciphertext + @return CRYPT_OK if successful +*/ +int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, + unsigned long length) +{ + int err; + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + /* omac ciphertext */ + if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) { + return err; + } + + /* decrypt */ + return ctr_decrypt(ct, pt, length, &eax->ctr); +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c b/deps/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c new file mode 100644 index 0000000..5429d4a --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_decrypt_verify_memory.c @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_decrypt_verify_memory.c + EAX implementation, decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + Decrypt a block of memory and verify the provided MAC tag with EAX + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the key (octets) + @param nonce The nonce data (use once) for the session + @param noncelen The length of the nonce data. + @param header The session header data + @param headerlen The length of the header (octets) + @param ct The ciphertext + @param ctlen The length of the ciphertext (octets) + @param pt [out] The plaintext + @param tag The authentication tag provided by the encoder + @param taglen [in/out] The length of the tag (octets) + @param stat [out] The result of the decryption (1==valid tag, 0==invalid) + @return CRYPT_OK if successful regardless of the resulting tag comparison +*/ +int eax_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat) +{ + int err; + eax_state *eax; + unsigned char *buf; + unsigned long buflen; + + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + + /* default to zero */ + *stat = 0; + + /* limit taglen */ + taglen = MIN(taglen, MAXBLOCKSIZE); + + /* allocate ram */ + buf = XMALLOC(taglen); + eax = XMALLOC(sizeof(*eax)); + if (eax == NULL || buf == NULL) { + if (eax != NULL) { + XFREE(eax); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = eax_decrypt(eax, ct, pt, ctlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + buflen = taglen; + if ((err = eax_done(eax, buf, &buflen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compare tags */ + if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) { + *stat = 1; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, taglen); + zeromem(eax, sizeof(*eax)); +#endif + + XFREE(eax); + XFREE(buf); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/eax/eax_done.c b/deps/libtomcrypt/src/encauth/eax/eax_done.c new file mode 100644 index 0000000..f2362cf --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_done.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_done.c + EAX implementation, terminate session, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + Terminate an EAX session and get the tag. + @param eax The EAX state + @param tag [out] The destination of the authentication tag + @param taglen [in/out] The max length and resulting length of the authentication tag + @return CRYPT_OK if successful +*/ +int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen) +{ + int err; + unsigned char *headermac, *ctmac; + unsigned long x, len; + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + /* allocate ram */ + headermac = XMALLOC(MAXBLOCKSIZE); + ctmac = XMALLOC(MAXBLOCKSIZE); + + if (headermac == NULL || ctmac == NULL) { + if (headermac != NULL) { + XFREE(headermac); + } + if (ctmac != NULL) { + XFREE(ctmac); + } + return CRYPT_MEM; + } + + /* finish ctomac */ + len = MAXBLOCKSIZE; + if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* finish headeromac */ + + /* note we specifically don't reset len so the two lens are minimal */ + + if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* terminate the CTR chain */ + if ((err = ctr_done(&eax->ctr)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compute N xor H xor C */ + for (x = 0; x < len && x < *taglen; x++) { + tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x]; + } + *taglen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ctmac, MAXBLOCKSIZE); + zeromem(headermac, MAXBLOCKSIZE); + zeromem(eax, sizeof(*eax)); +#endif + + XFREE(ctmac); + XFREE(headermac); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/eax/eax_encrypt.c b/deps/libtomcrypt/src/encauth/eax/eax_encrypt.c new file mode 100644 index 0000000..dba3239 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_encrypt.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_encrypt.c + EAX implementation, encrypt block by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + Encrypt with EAX a block of data. + @param eax The EAX state + @param pt The plaintext to encrypt + @param ct [out] The ciphertext as encrypted + @param length The length of the plaintext (octets) + @return CRYPT_OK if successful +*/ +int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, + unsigned long length) +{ + int err; + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + /* encrypt */ + if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) { + return err; + } + + /* omac ciphertext */ + return omac_process(&eax->ctomac, ct, length); +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c b/deps/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c new file mode 100644 index 0000000..76aeec2 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_encrypt_authenticate_memory.c @@ -0,0 +1,70 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_encrypt_authenticate_memory.c + EAX implementation, encrypt a block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + EAX encrypt and produce an authentication tag + @param cipher The index of the cipher desired + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The destination tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int eax_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + eax_state *eax; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + eax = XMALLOC(sizeof(*eax)); + + if ((err = eax_init(eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = eax_encrypt(eax, pt, ct, ptlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = eax_done(eax, tag, taglen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(eax, sizeof(*eax)); +#endif + + XFREE(eax); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/eax/eax_init.c b/deps/libtomcrypt/src/encauth/eax/eax_init.c new file mode 100644 index 0000000..153c427 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_init.c @@ -0,0 +1,132 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_init.c + EAX implementation, initialized EAX state, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + Initialized an EAX state + @param eax [out] The EAX state to initialize + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The use-once nonce for the session + @param noncelen The length of the nonce (octets) + @param header The header for the EAX state + @param headerlen The header length (octets) + @return CRYPT_OK if successful +*/ +int eax_init(eax_state *eax, int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen) +{ + unsigned char *buf; + int err, blklen; + omac_state *omac; + unsigned long len; + + + LTC_ARGCHK(eax != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + if (headerlen > 0) { + LTC_ARGCHK(header != NULL); + } + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + blklen = cipher_descriptor[cipher].block_length; + + /* allocate ram */ + buf = XMALLOC(MAXBLOCKSIZE); + omac = XMALLOC(sizeof(*omac)); + + if (buf == NULL || omac == NULL) { + if (buf != NULL) { + XFREE(buf); + } + if (omac != NULL) { + XFREE(omac); + } + return CRYPT_MEM; + } + + /* N = LTC_OMAC_0K(nonce) */ + zeromem(buf, MAXBLOCKSIZE); + if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* omac the [0]_n */ + if ((err = omac_process(omac, buf, blklen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* omac the nonce */ + if ((err = omac_process(omac, nonce, noncelen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* store result */ + len = sizeof(eax->N); + if ((err = omac_done(omac, eax->N, &len)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* H = LTC_OMAC_1K(header) */ + zeromem(buf, MAXBLOCKSIZE); + buf[blklen - 1] = 1; + + if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* omac the [1]_n */ + if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* omac the header */ + if (headerlen != 0) { + if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* note we don't finish the headeromac, this allows us to add more header later */ + + /* setup the CTR mode */ + if ((err = ctr_start(cipher, eax->N, key, keylen, 0, CTR_COUNTER_BIG_ENDIAN, &eax->ctr)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* setup the LTC_OMAC for the ciphertext */ + if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* omac [2]_n */ + zeromem(buf, MAXBLOCKSIZE); + buf[blklen-1] = 2; + if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, MAXBLOCKSIZE); + zeromem(omac, sizeof(*omac)); +#endif + + XFREE(omac); + XFREE(buf); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/eax/eax_test.c b/deps/libtomcrypt/src/encauth/eax/eax_test.c new file mode 100644 index 0000000..c613e0d --- /dev/null +++ b/deps/libtomcrypt/src/encauth/eax/eax_test.c @@ -0,0 +1,249 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file eax_test.c + EAX implementation, self-test, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_EAX_MODE + +/** + Test the EAX implementation + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int eax_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen, + noncelen, + headerlen, + msglen; + + unsigned char key[MAXBLOCKSIZE], + nonce[MAXBLOCKSIZE], + header[MAXBLOCKSIZE], + plaintext[MAXBLOCKSIZE], + ciphertext[MAXBLOCKSIZE], + tag[MAXBLOCKSIZE]; + } tests[] = { + +/* NULL message */ +{ + 16, 0, 0, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0 }, + /* header */ + { 0 }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5, + 0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff } +}, + +/* test with nonce */ +{ + 16, 16, 0, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* header */ + { 0 }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb, + 0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec } +}, + +/* test with header [no nonce] */ +{ + 16, 0, 16, 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0 }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* plaintext */ + { 0 }, + /* ciphertext */ + { 0 }, + /* tag */ + { 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0, + 0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff } +}, + +/* test with header + nonce + plaintext */ +{ + 16, 16, 16, 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* plaintext */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* ciphertext */ + { 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b, + 0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78, + 0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f, + 0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc }, + /* tag */ + { 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e, + 0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 } +}, + +/* test with header + nonce + plaintext [not even sizes!] */ +{ + 16, 15, 14, 29, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e }, + /* header */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d }, + /* plaintext */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c }, + /* ciphertext */ + { 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59, + 0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8, + 0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c, + 0x8a, 0x24, 0xdb, 0x86, 0x8b }, + /* tag */ + { 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2, + 0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda } +}, + +/* Vectors from Brian Gladman */ + +{ + 16, 16, 8, 0, + /* key */ + { 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f, + 0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 }, + /* nonce */ + { 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07, + 0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 }, + /* header */ + { 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b }, + /* PT */ + { 0x00 }, + /* CT */ + { 0x00 }, + /* tag */ + { 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b, + 0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 } +}, + +{ + 16, 16, 8, 2, + /* key */ + { 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b, + 0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 }, + /* nonce */ + { 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84, + 0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd }, + /* header */ + { 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa }, + /* PT */ + { 0xf7, 0xfb }, + /* CT */ + { 0x19, 0xdd }, + /* tag */ + { 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda, + 0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 } +}, + +{ + 16, 16, 8, 5, + /* key */ + { 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7, + 0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 }, + /* nonce */ + { 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84, + 0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e }, + /* header */ + { 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 }, + /* PT */ + { 0x1a, 0x47, 0xcb, 0x49, 0x33 }, + /* CT */ + { 0xd8, 0x51, 0xd5, 0xba, 0xe0 }, + /* Tag */ + { 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19, + 0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 } +} + +}; + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen, + tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, + tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) { + return err; + } + if (compare_testvector(outtag, len, tests[x].tag, len, "EAX Tag", x) || + compare_testvector(outct, tests[x].msglen, tests[x].ciphertext, tests[x].msglen, "EAX CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* test decrypt */ + if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen, + tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen, + outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || compare_testvector(outct, tests[x].msglen, tests[x].plaintext, tests[x].msglen, "EAX", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nEAX: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* LTC_EAX_MODE */ diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_add_aad.c b/deps/libtomcrypt/src/encauth/gcm/gcm_add_aad.c new file mode 100644 index 0000000..5c3793e --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_add_aad.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_add_aad.c + GCM implementation, Add AAD data to the stream, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Add AAD to the GCM state + @param gcm The GCM state + @param adata The additional authentication data to add to the GCM state + @param adatalen The length of the AAD data. + @return CRYPT_OK on success + */ +int gcm_add_aad(gcm_state *gcm, + const unsigned char *adata, unsigned long adatalen) +{ + unsigned long x; + int err; +#ifdef LTC_FAST + unsigned long y; +#endif + + LTC_ARGCHK(gcm != NULL); + if (adatalen > 0) { + LTC_ARGCHK(adata != NULL); + } + + if (gcm->buflen > 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + /* in IV mode? */ + if (gcm->mode == LTC_GCM_MODE_IV) { + /* IV length must be > 0 */ + if (gcm->buflen == 0 && gcm->totlen == 0) return CRYPT_ERROR; + /* let's process the IV */ + if (gcm->ivmode || gcm->buflen != 12) { + for (x = 0; x < (unsigned long)gcm->buflen; x++) { + gcm->X[x] ^= gcm->buf[x]; + } + if (gcm->buflen) { + gcm->totlen += gcm->buflen * CONST64(8); + gcm_mult_h(gcm, gcm->X); + } + + /* mix in the length */ + zeromem(gcm->buf, 8); + STORE64H(gcm->totlen, gcm->buf+8); + for (x = 0; x < 16; x++) { + gcm->X[x] ^= gcm->buf[x]; + } + gcm_mult_h(gcm, gcm->X); + + /* copy counter out */ + XMEMCPY(gcm->Y, gcm->X, 16); + zeromem(gcm->X, 16); + } else { + XMEMCPY(gcm->Y, gcm->buf, 12); + gcm->Y[12] = 0; + gcm->Y[13] = 0; + gcm->Y[14] = 0; + gcm->Y[15] = 1; + } + XMEMCPY(gcm->Y_0, gcm->Y, 16); + zeromem(gcm->buf, 16); + gcm->buflen = 0; + gcm->totlen = 0; + gcm->mode = LTC_GCM_MODE_AAD; + } + + if (gcm->mode != LTC_GCM_MODE_AAD || gcm->buflen >= 16) { + return CRYPT_INVALID_ARG; + } + + x = 0; +#ifdef LTC_FAST + if (gcm->buflen == 0 && adatalen > 15) { + for (x = 0; x < (adatalen & ~15); x += 16) { + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&adata[x + y])); + } + gcm_mult_h(gcm, gcm->X); + gcm->totlen += 128; + } + adata += x; + } +#endif + + + /* start adding AAD data to the state */ + for (; x < adatalen; x++) { + gcm->X[gcm->buflen++] ^= *adata++; + + if (gcm->buflen == 16) { + /* GF mult it */ + gcm_mult_h(gcm, gcm->X); + gcm->buflen = 0; + gcm->totlen += 128; + } + } + + return CRYPT_OK; +} +#endif + diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_add_iv.c b/deps/libtomcrypt/src/encauth/gcm/gcm_add_iv.c new file mode 100644 index 0000000..33a2444 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_add_iv.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_add_iv.c + GCM implementation, add IV data to the state, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Add IV data to the GCM state + @param gcm The GCM state + @param IV The initial value data to add + @param IVlen The length of the IV + @return CRYPT_OK on success + */ +int gcm_add_iv(gcm_state *gcm, + const unsigned char *IV, unsigned long IVlen) +{ + unsigned long x, y; + int err; + + LTC_ARGCHK(gcm != NULL); + if (IVlen > 0) { + LTC_ARGCHK(IV != NULL); + } + + /* must be in IV mode */ + if (gcm->mode != LTC_GCM_MODE_IV) { + return CRYPT_INVALID_ARG; + } + + if (gcm->buflen >= 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + + /* trip the ivmode flag */ + if (IVlen + gcm->buflen > 12) { + gcm->ivmode |= 1; + } + + x = 0; +#ifdef LTC_FAST + if (gcm->buflen == 0) { + for (x = 0; x < (IVlen & ~15); x += 16) { + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&IV[x + y])); + } + gcm_mult_h(gcm, gcm->X); + gcm->totlen += 128; + } + IV += x; + } +#endif + + /* start adding IV data to the state */ + for (; x < IVlen; x++) { + gcm->buf[gcm->buflen++] = *IV++; + + if (gcm->buflen == 16) { + /* GF mult it */ + for (y = 0; y < 16; y++) { + gcm->X[y] ^= gcm->buf[y]; + } + gcm_mult_h(gcm, gcm->X); + gcm->buflen = 0; + gcm->totlen += 128; + } + } + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_done.c b/deps/libtomcrypt/src/encauth/gcm/gcm_done.c new file mode 100644 index 0000000..464f87a --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_done.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_done.c + GCM implementation, Terminate the stream, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Terminate a GCM stream + @param gcm The GCM state + @param tag [out] The destination for the MAC tag + @param taglen [in/out] The length of the MAC tag + @return CRYPT_OK on success + */ +int gcm_done(gcm_state *gcm, + unsigned char *tag, unsigned long *taglen) +{ + unsigned long x; + int err; + + LTC_ARGCHK(gcm != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + if (gcm->buflen > 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + if (gcm->mode == LTC_GCM_MODE_IV) { + /* let's process the IV */ + if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err; + } + + if (gcm->mode == LTC_GCM_MODE_AAD) { + /* let's process the AAD */ + if ((err = gcm_process(gcm, NULL, 0, NULL, 0)) != CRYPT_OK) return err; + } + + if (gcm->mode != LTC_GCM_MODE_TEXT) { + return CRYPT_INVALID_ARG; + } + + /* handle remaining ciphertext */ + if (gcm->buflen) { + gcm->pttotlen += gcm->buflen * CONST64(8); + gcm_mult_h(gcm, gcm->X); + } + + /* length */ + STORE64H(gcm->totlen, gcm->buf); + STORE64H(gcm->pttotlen, gcm->buf+8); + for (x = 0; x < 16; x++) { + gcm->X[x] ^= gcm->buf[x]; + } + gcm_mult_h(gcm, gcm->X); + + /* encrypt original counter */ + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y_0, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + for (x = 0; x < 16 && x < *taglen; x++) { + tag[x] = gcm->buf[x] ^ gcm->X[x]; + } + *taglen = x; + + cipher_descriptor[gcm->cipher].done(&gcm->K); + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c b/deps/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c new file mode 100644 index 0000000..10cd3c9 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_gf_mult.c @@ -0,0 +1,209 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_gf_mult.c + GCM implementation, do the GF mult, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || (defined(LTC_GCM_MODE) && defined(LTC_FAST)) + +/* this is x*2^128 mod p(x) ... the results are 16 bytes each stored in a packed format. Since only the + * lower 16 bits are not zero'ed I removed the upper 14 bytes */ +const unsigned char gcm_shift_table[256*2] = { +0x00, 0x00, 0x01, 0xc2, 0x03, 0x84, 0x02, 0x46, 0x07, 0x08, 0x06, 0xca, 0x04, 0x8c, 0x05, 0x4e, +0x0e, 0x10, 0x0f, 0xd2, 0x0d, 0x94, 0x0c, 0x56, 0x09, 0x18, 0x08, 0xda, 0x0a, 0x9c, 0x0b, 0x5e, +0x1c, 0x20, 0x1d, 0xe2, 0x1f, 0xa4, 0x1e, 0x66, 0x1b, 0x28, 0x1a, 0xea, 0x18, 0xac, 0x19, 0x6e, +0x12, 0x30, 0x13, 0xf2, 0x11, 0xb4, 0x10, 0x76, 0x15, 0x38, 0x14, 0xfa, 0x16, 0xbc, 0x17, 0x7e, +0x38, 0x40, 0x39, 0x82, 0x3b, 0xc4, 0x3a, 0x06, 0x3f, 0x48, 0x3e, 0x8a, 0x3c, 0xcc, 0x3d, 0x0e, +0x36, 0x50, 0x37, 0x92, 0x35, 0xd4, 0x34, 0x16, 0x31, 0x58, 0x30, 0x9a, 0x32, 0xdc, 0x33, 0x1e, +0x24, 0x60, 0x25, 0xa2, 0x27, 0xe4, 0x26, 0x26, 0x23, 0x68, 0x22, 0xaa, 0x20, 0xec, 0x21, 0x2e, +0x2a, 0x70, 0x2b, 0xb2, 0x29, 0xf4, 0x28, 0x36, 0x2d, 0x78, 0x2c, 0xba, 0x2e, 0xfc, 0x2f, 0x3e, +0x70, 0x80, 0x71, 0x42, 0x73, 0x04, 0x72, 0xc6, 0x77, 0x88, 0x76, 0x4a, 0x74, 0x0c, 0x75, 0xce, +0x7e, 0x90, 0x7f, 0x52, 0x7d, 0x14, 0x7c, 0xd6, 0x79, 0x98, 0x78, 0x5a, 0x7a, 0x1c, 0x7b, 0xde, +0x6c, 0xa0, 0x6d, 0x62, 0x6f, 0x24, 0x6e, 0xe6, 0x6b, 0xa8, 0x6a, 0x6a, 0x68, 0x2c, 0x69, 0xee, +0x62, 0xb0, 0x63, 0x72, 0x61, 0x34, 0x60, 0xf6, 0x65, 0xb8, 0x64, 0x7a, 0x66, 0x3c, 0x67, 0xfe, +0x48, 0xc0, 0x49, 0x02, 0x4b, 0x44, 0x4a, 0x86, 0x4f, 0xc8, 0x4e, 0x0a, 0x4c, 0x4c, 0x4d, 0x8e, +0x46, 0xd0, 0x47, 0x12, 0x45, 0x54, 0x44, 0x96, 0x41, 0xd8, 0x40, 0x1a, 0x42, 0x5c, 0x43, 0x9e, +0x54, 0xe0, 0x55, 0x22, 0x57, 0x64, 0x56, 0xa6, 0x53, 0xe8, 0x52, 0x2a, 0x50, 0x6c, 0x51, 0xae, +0x5a, 0xf0, 0x5b, 0x32, 0x59, 0x74, 0x58, 0xb6, 0x5d, 0xf8, 0x5c, 0x3a, 0x5e, 0x7c, 0x5f, 0xbe, +0xe1, 0x00, 0xe0, 0xc2, 0xe2, 0x84, 0xe3, 0x46, 0xe6, 0x08, 0xe7, 0xca, 0xe5, 0x8c, 0xe4, 0x4e, +0xef, 0x10, 0xee, 0xd2, 0xec, 0x94, 0xed, 0x56, 0xe8, 0x18, 0xe9, 0xda, 0xeb, 0x9c, 0xea, 0x5e, +0xfd, 0x20, 0xfc, 0xe2, 0xfe, 0xa4, 0xff, 0x66, 0xfa, 0x28, 0xfb, 0xea, 0xf9, 0xac, 0xf8, 0x6e, +0xf3, 0x30, 0xf2, 0xf2, 0xf0, 0xb4, 0xf1, 0x76, 0xf4, 0x38, 0xf5, 0xfa, 0xf7, 0xbc, 0xf6, 0x7e, +0xd9, 0x40, 0xd8, 0x82, 0xda, 0xc4, 0xdb, 0x06, 0xde, 0x48, 0xdf, 0x8a, 0xdd, 0xcc, 0xdc, 0x0e, +0xd7, 0x50, 0xd6, 0x92, 0xd4, 0xd4, 0xd5, 0x16, 0xd0, 0x58, 0xd1, 0x9a, 0xd3, 0xdc, 0xd2, 0x1e, +0xc5, 0x60, 0xc4, 0xa2, 0xc6, 0xe4, 0xc7, 0x26, 0xc2, 0x68, 0xc3, 0xaa, 0xc1, 0xec, 0xc0, 0x2e, +0xcb, 0x70, 0xca, 0xb2, 0xc8, 0xf4, 0xc9, 0x36, 0xcc, 0x78, 0xcd, 0xba, 0xcf, 0xfc, 0xce, 0x3e, +0x91, 0x80, 0x90, 0x42, 0x92, 0x04, 0x93, 0xc6, 0x96, 0x88, 0x97, 0x4a, 0x95, 0x0c, 0x94, 0xce, +0x9f, 0x90, 0x9e, 0x52, 0x9c, 0x14, 0x9d, 0xd6, 0x98, 0x98, 0x99, 0x5a, 0x9b, 0x1c, 0x9a, 0xde, +0x8d, 0xa0, 0x8c, 0x62, 0x8e, 0x24, 0x8f, 0xe6, 0x8a, 0xa8, 0x8b, 0x6a, 0x89, 0x2c, 0x88, 0xee, +0x83, 0xb0, 0x82, 0x72, 0x80, 0x34, 0x81, 0xf6, 0x84, 0xb8, 0x85, 0x7a, 0x87, 0x3c, 0x86, 0xfe, +0xa9, 0xc0, 0xa8, 0x02, 0xaa, 0x44, 0xab, 0x86, 0xae, 0xc8, 0xaf, 0x0a, 0xad, 0x4c, 0xac, 0x8e, +0xa7, 0xd0, 0xa6, 0x12, 0xa4, 0x54, 0xa5, 0x96, 0xa0, 0xd8, 0xa1, 0x1a, 0xa3, 0x5c, 0xa2, 0x9e, +0xb5, 0xe0, 0xb4, 0x22, 0xb6, 0x64, 0xb7, 0xa6, 0xb2, 0xe8, 0xb3, 0x2a, 0xb1, 0x6c, 0xb0, 0xae, +0xbb, 0xf0, 0xba, 0x32, 0xb8, 0x74, 0xb9, 0xb6, 0xbc, 0xf8, 0xbd, 0x3a, 0xbf, 0x7c, 0xbe, 0xbe }; + +#endif + + +#if defined(LTC_GCM_MODE) || defined(LRW_MODE) + +#ifndef LTC_FAST +/* right shift */ +static void s_gcm_rightshift(unsigned char *a) +{ + int x; + for (x = 15; x > 0; x--) { + a[x] = (a[x]>>1) | ((a[x-1]<<7)&0x80); + } + a[0] >>= 1; +} + +/* c = b*a */ +static const unsigned char mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; +static const unsigned char poly[] = { 0x00, 0xE1 }; + + +/** + GCM GF multiplier (internal use only) bitserial + @param a First value + @param b Second value + @param c Destination for a * b + */ +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) +{ + unsigned char Z[16], V[16]; + unsigned char x, y, z; + + zeromem(Z, 16); + XMEMCPY(V, a, 16); + for (x = 0; x < 128; x++) { + if (b[x>>3] & mask[x&7]) { + for (y = 0; y < 16; y++) { + Z[y] ^= V[y]; + } + } + z = V[15] & 0x01; + s_gcm_rightshift(V); + V[0] ^= poly[z]; + } + XMEMCPY(c, Z, 16); +} + +#else + +/* map normal numbers to "ieee" way ... e.g. bit reversed */ +#define M(x) ( ((x&8)>>3) | ((x&4)>>1) | ((x&2)<<1) | ((x&1)<<3) ) + +#define BPD (sizeof(LTC_FAST_TYPE) * 8) +#define WPV (1 + (16 / sizeof(LTC_FAST_TYPE))) + +/** + GCM GF multiplier (internal use only) word oriented + @param a First value + @param b Second value + @param c Destination for a * b + */ +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c) +{ + int i, j, k, u; + LTC_FAST_TYPE B[16][WPV], tmp[32 / sizeof(LTC_FAST_TYPE)], pB[16 / sizeof(LTC_FAST_TYPE)], zz, z; + unsigned char pTmp[32]; + + /* create simple tables */ + zeromem(B[0], sizeof(B[0])); + zeromem(B[M(1)], sizeof(B[M(1)])); + +#ifdef ENDIAN_32BITWORD + for (i = 0; i < 4; i++) { + LOAD32H(B[M(1)][i], a + (i<<2)); + LOAD32L(pB[i], b + (i<<2)); + } +#else + for (i = 0; i < 2; i++) { + LOAD64H(B[M(1)][i], a + (i<<3)); + LOAD64L(pB[i], b + (i<<3)); + } +#endif + + /* now create 2, 4 and 8 */ + B[M(2)][0] = B[M(1)][0] >> 1; + B[M(4)][0] = B[M(1)][0] >> 2; + B[M(8)][0] = B[M(1)][0] >> 3; + for (i = 1; i < (int)WPV; i++) { + B[M(2)][i] = (B[M(1)][i-1] << (BPD-1)) | (B[M(1)][i] >> 1); + B[M(4)][i] = (B[M(1)][i-1] << (BPD-2)) | (B[M(1)][i] >> 2); + B[M(8)][i] = (B[M(1)][i-1] << (BPD-3)) | (B[M(1)][i] >> 3); + } + + /* now all values with two bits which are 3, 5, 6, 9, 10, 12 */ + for (i = 0; i < (int)WPV; i++) { + B[M(3)][i] = B[M(1)][i] ^ B[M(2)][i]; + B[M(5)][i] = B[M(1)][i] ^ B[M(4)][i]; + B[M(6)][i] = B[M(2)][i] ^ B[M(4)][i]; + B[M(9)][i] = B[M(1)][i] ^ B[M(8)][i]; + B[M(10)][i] = B[M(2)][i] ^ B[M(8)][i]; + B[M(12)][i] = B[M(8)][i] ^ B[M(4)][i]; + + /* now all 3 bit values and the only 4 bit value: 7, 11, 13, 14, 15 */ + B[M(7)][i] = B[M(3)][i] ^ B[M(4)][i]; + B[M(11)][i] = B[M(3)][i] ^ B[M(8)][i]; + B[M(13)][i] = B[M(1)][i] ^ B[M(12)][i]; + B[M(14)][i] = B[M(6)][i] ^ B[M(8)][i]; + B[M(15)][i] = B[M(7)][i] ^ B[M(8)][i]; + } + + zeromem(tmp, sizeof(tmp)); + + /* compute product four bits of each word at a time */ + /* for each nibble */ + for (i = (BPD/4)-1; i >= 0; i--) { + /* for each word */ + for (j = 0; j < (int)(WPV-1); j++) { + /* grab the 4 bits recall the nibbles are backwards so it's a shift by (i^1)*4 */ + u = (pB[j] >> ((i^1)<<2)) & 15; + + /* add offset by the word count the table looked up value to the result */ + for (k = 0; k < (int)WPV; k++) { + tmp[k+j] ^= B[u][k]; + } + } + /* shift result up by 4 bits */ + if (i != 0) { + for (z = j = 0; j < (int)(32 / sizeof(LTC_FAST_TYPE)); j++) { + zz = tmp[j] << (BPD-4); + tmp[j] = (tmp[j] >> 4) | z; + z = zz; + } + } + } + + /* store product */ +#ifdef ENDIAN_32BITWORD + for (i = 0; i < 8; i++) { + STORE32H(tmp[i], pTmp + (i<<2)); + } +#else + for (i = 0; i < 4; i++) { + STORE64H(tmp[i], pTmp + (i<<3)); + } +#endif + + /* reduce by taking most significant byte and adding the appropriate two byte sequence 16 bytes down */ + for (i = 31; i >= 16; i--) { + pTmp[i-16] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)]; + pTmp[i-15] ^= gcm_shift_table[((unsigned)pTmp[i]<<1)+1]; + } + + for (i = 0; i < 16; i++) { + c[i] = pTmp[i]; + } + +} + +#endif + +#endif + diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_init.c b/deps/libtomcrypt/src/encauth/gcm/gcm_init.c new file mode 100644 index 0000000..1822bdc --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_init.c @@ -0,0 +1,95 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_init.c + GCM implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Initialize a GCM state + @param gcm The GCM state to initialize + @param cipher The index of the cipher to use + @param key The secret key + @param keylen The length of the secret key + @return CRYPT_OK on success + */ +int gcm_init(gcm_state *gcm, int cipher, + const unsigned char *key, int keylen) +{ + int err; + unsigned char B[16]; +#ifdef LTC_GCM_TABLES + int x, y, z, t; +#endif + + LTC_ARGCHK(gcm != NULL); + LTC_ARGCHK(key != NULL); + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* is cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_CIPHER; + } + + /* schedule key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &gcm->K)) != CRYPT_OK) { + return err; + } + + /* H = E(0) */ + zeromem(B, 16); + if ((err = cipher_descriptor[cipher].ecb_encrypt(B, gcm->H, &gcm->K)) != CRYPT_OK) { + return err; + } + + /* setup state */ + zeromem(gcm->buf, sizeof(gcm->buf)); + zeromem(gcm->X, sizeof(gcm->X)); + gcm->cipher = cipher; + gcm->mode = LTC_GCM_MODE_IV; + gcm->ivmode = 0; + gcm->buflen = 0; + gcm->totlen = 0; + gcm->pttotlen = 0; + +#ifdef LTC_GCM_TABLES + /* setup tables */ + + /* generate the first table as it has no shifting (from which we make the other tables) */ + zeromem(B, 16); + for (y = 0; y < 256; y++) { + B[0] = y; + gcm_gf_mult(gcm->H, B, &gcm->PC[0][y][0]); + } + + /* now generate the rest of the tables based the previous table */ + for (x = 1; x < 16; x++) { + for (y = 0; y < 256; y++) { + /* now shift it right by 8 bits */ + t = gcm->PC[x-1][y][15]; + for (z = 15; z > 0; z--) { + gcm->PC[x][y][z] = gcm->PC[x-1][y][z-1]; + } + gcm->PC[x][y][0] = gcm_shift_table[t<<1]; + gcm->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; + } + } + +#endif + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_memory.c b/deps/libtomcrypt/src/encauth/gcm/gcm_memory.c new file mode 100644 index 0000000..4da5d54 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_memory.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_memory.c + GCM implementation, process a packet, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Process an entire GCM packet in one call. + @param cipher Index of cipher to use + @param key The secret key + @param keylen The length of the secret key + @param IV The initialization vector + @param IVlen The length of the initialization vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param pt The plaintext + @param ptlen The length of the plaintext (ciphertext length is the same) + @param ct The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ +int gcm_memory( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction) +{ + void *orig; + gcm_state *gcm; + int err; + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[cipher].accel_gcm_memory != NULL) { + return cipher_descriptor[cipher].accel_gcm_memory + (key, keylen, + IV, IVlen, + adata, adatalen, + pt, ptlen, + ct, + tag, taglen, + direction); + } + + + +#ifndef LTC_GCM_TABLES_SSE2 + orig = gcm = XMALLOC(sizeof(*gcm)); +#else + orig = gcm = XMALLOC(sizeof(*gcm) + 16); +#endif + if (gcm == NULL) { + return CRYPT_MEM; + } + + /* Force GCM to be on a multiple of 16 so we can use 128-bit aligned operations + * note that we only modify gcm and keep orig intact. This code is not portable + * but again it's only for SSE2 anyways, so who cares? + */ +#ifdef LTC_GCM_TABLES_SSE2 + if ((unsigned long)gcm & 15) { + gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15))); + } +#endif + + if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) { + goto LTC_ERR; + } + if ((err = gcm_add_iv(gcm, IV, IVlen)) != CRYPT_OK) { + goto LTC_ERR; + } + if ((err = gcm_add_aad(gcm, adata, adatalen)) != CRYPT_OK) { + goto LTC_ERR; + } + if ((err = gcm_process(gcm, pt, ptlen, ct, direction)) != CRYPT_OK) { + goto LTC_ERR; + } + if (direction == GCM_ENCRYPT) { + if ((err = gcm_done(gcm, tag, taglen)) != CRYPT_OK) { + goto LTC_ERR; + } + } + else if (direction == GCM_DECRYPT) { + unsigned char buf[MAXBLOCKSIZE]; + unsigned long buflen = sizeof(buf); + if ((err = gcm_done(gcm, buf, &buflen)) != CRYPT_OK) { + goto LTC_ERR; + } + if (buflen != *taglen || XMEM_NEQ(buf, tag, buflen) != 0) { + err = CRYPT_ERROR; + } + } + else { + err = CRYPT_INVALID_ARG; + } +LTC_ERR: + gcm_reset(gcm); + XFREE(orig); + return err; +} +#endif + diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_mult_h.c b/deps/libtomcrypt/src/encauth/gcm/gcm_mult_h.c new file mode 100644 index 0000000..fcf3226 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_mult_h.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_mult_h.c + GCM implementation, do the GF mult, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#if defined(LTC_GCM_MODE) +/** + GCM multiply by H + @param gcm The GCM state which holds the H value + @param I The value to multiply H by + */ +void gcm_mult_h(const gcm_state *gcm, unsigned char *I) +{ + unsigned char T[16]; +#ifdef LTC_GCM_TABLES + int x; +#ifdef LTC_GCM_TABLES_SSE2 + asm("movdqa (%0),%%xmm0"::"r"(&gcm->PC[0][I[0]][0])); + for (x = 1; x < 16; x++) { + asm("pxor (%0),%%xmm0"::"r"(&gcm->PC[x][I[x]][0])); + } + asm("movdqa %%xmm0,(%0)"::"r"(&T)); +#else + int y; + XMEMCPY(T, &gcm->PC[0][I[0]][0], 16); + for (x = 1; x < 16; x++) { +#ifdef LTC_FAST + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&gcm->PC[x][I[x]][y])); + } +#else + for (y = 0; y < 16; y++) { + T[y] ^= gcm->PC[x][I[x]][y]; + } +#endif /* LTC_FAST */ + } +#endif /* LTC_GCM_TABLES_SSE2 */ +#else + gcm_gf_mult(gcm->H, I, T); +#endif + XMEMCPY(I, T, 16); +} +#endif diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_process.c b/deps/libtomcrypt/src/encauth/gcm/gcm_process.c new file mode 100644 index 0000000..e3c956c --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_process.c @@ -0,0 +1,150 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_process.c + GCM implementation, process message data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Process plaintext/ciphertext through GCM + @param gcm The GCM state + @param pt The plaintext + @param ptlen The plaintext length (ciphertext length is the same) + @param ct The ciphertext + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ +int gcm_process(gcm_state *gcm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction) +{ + unsigned long x; + int y, err; + unsigned char b; + + LTC_ARGCHK(gcm != NULL); + if (ptlen > 0) { + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + } + + if (gcm->buflen > 16 || gcm->buflen < 0) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(gcm->cipher)) != CRYPT_OK) { + return err; + } + + /* 0xFFFFFFFE0 = ((2^39)-256)/8 */ + if (gcm->pttotlen / 8 + (ulong64)gcm->buflen + (ulong64)ptlen >= CONST64(0xFFFFFFFE0)) { + return CRYPT_INVALID_ARG; + } + + if (gcm->mode == LTC_GCM_MODE_IV) { + /* let's process the IV */ + if ((err = gcm_add_aad(gcm, NULL, 0)) != CRYPT_OK) return err; + } + + /* in AAD mode? */ + if (gcm->mode == LTC_GCM_MODE_AAD) { + /* let's process the AAD */ + if (gcm->buflen) { + gcm->totlen += gcm->buflen * CONST64(8); + gcm_mult_h(gcm, gcm->X); + } + + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + /* encrypt the counter */ + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + + gcm->buflen = 0; + gcm->mode = LTC_GCM_MODE_TEXT; + } + + if (gcm->mode != LTC_GCM_MODE_TEXT) { + return CRYPT_INVALID_ARG; + } + + x = 0; +#ifdef LTC_FAST + if (gcm->buflen == 0) { + if (direction == GCM_ENCRYPT) { + for (x = 0; x < (ptlen & ~15); x += 16) { + /* ctr encrypt */ + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&ct[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y])); + *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])); + } + /* GMAC it */ + gcm->pttotlen += 128; + gcm_mult_h(gcm, gcm->X); + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + } + } else { + for (x = 0; x < (ptlen & ~15); x += 16) { + /* ctr encrypt */ + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])); + *(LTC_FAST_TYPE_PTR_CAST(&pt[x + y])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[x+y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&gcm->buf[y])); + } + /* GMAC it */ + gcm->pttotlen += 128; + gcm_mult_h(gcm, gcm->X); + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + } + } + } +#endif + + /* process text */ + for (; x < ptlen; x++) { + if (gcm->buflen == 16) { + gcm->pttotlen += 128; + gcm_mult_h(gcm, gcm->X); + + /* increment counter */ + for (y = 15; y >= 12; y--) { + if (++gcm->Y[y] & 255) { break; } + } + if ((err = cipher_descriptor[gcm->cipher].ecb_encrypt(gcm->Y, gcm->buf, &gcm->K)) != CRYPT_OK) { + return err; + } + gcm->buflen = 0; + } + + if (direction == GCM_ENCRYPT) { + b = ct[x] = pt[x] ^ gcm->buf[gcm->buflen]; + } else { + b = ct[x]; + pt[x] = ct[x] ^ gcm->buf[gcm->buflen]; + } + gcm->X[gcm->buflen++] ^= b; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_reset.c b/deps/libtomcrypt/src/encauth/gcm/gcm_reset.c new file mode 100644 index 0000000..a071dcd --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_reset.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_reset.c + GCM implementation, reset a used state so it can accept IV data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Reset a GCM state to as if you just called gcm_init(). This saves the initialization time. + @param gcm The GCM state to reset + @return CRYPT_OK on success +*/ +int gcm_reset(gcm_state *gcm) +{ + LTC_ARGCHK(gcm != NULL); + + zeromem(gcm->buf, sizeof(gcm->buf)); + zeromem(gcm->X, sizeof(gcm->X)); + gcm->mode = LTC_GCM_MODE_IV; + gcm->ivmode = 0; + gcm->buflen = 0; + gcm->totlen = 0; + gcm->pttotlen = 0; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/gcm/gcm_test.c b/deps/libtomcrypt/src/encauth/gcm/gcm_test.c new file mode 100644 index 0000000..228db57 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/gcm/gcm_test.c @@ -0,0 +1,407 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file gcm_test.c + GCM implementation, testing, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_GCM_MODE + +/** + Test the GCM code + @return CRYPT_OK on success + */ +int gcm_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char K[32]; + int keylen; + unsigned char P[128]; + unsigned long ptlen; + unsigned char A[128]; + unsigned long alen; + unsigned char IV[128]; + unsigned long IVlen; + unsigned char C[128]; + unsigned char T[16]; + } tests[] = { + +/* test case #1 */ +{ + /* key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* plaintext */ + { 0 }, + 0, + + /* AAD data */ + { 0 }, + 0, + + /* IV */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + 12, + + /* ciphertext */ + { 0 }, + + /* tag */ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a } +}, + +/* test case #2 */ +{ + /* key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* PT */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* ADATA */ + { 0 }, + 0, + + /* IV */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + 12, + + /* CT */ + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + + /* TAG */ + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf } +}, + +/* test case #3 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55, }, + 64, + + /* ADATA */ + { 0 }, + 0, + + /* IV */ + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, }, + 12, + + /* CT */ + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85, }, + + /* TAG */ + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4, } +}, + +/* test case #4 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, }, + 60, + + /* ADATA */ + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, }, + 20, + + /* IV */ + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88, }, + 12, + + /* CT */ + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, }, + + /* TAG */ + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47, } + +}, + +/* test case #5 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, }, + 60, + + /* ADATA */ + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, }, + 20, + + /* IV */ + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, }, + 8, + + /* CT */ + { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98, }, + + /* TAG */ + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb, } +}, + +/* test case #6 */ +{ + /* key */ + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, }, + 16, + + /* PT */ + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, }, + 60, + + /* ADATA */ + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2, }, + 20, + + /* IV */ + { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b, }, + 60, + + /* CT */ + { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5, }, + + /* TAG */ + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50, } +}, + +/* test case #46 from BG (catches the LTC bug of v1.15) */ +{ + /* key */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 16, + + /* PT */ + { 0xa2, 0xaa, 0xb3, 0xad, 0x8b, 0x17, 0xac, 0xdd, + 0xa2, 0x88, 0x42, 0x6c, 0xd7, 0xc4, 0x29, 0xb7, + 0xca, 0x86, 0xb7, 0xac, 0xa0, 0x58, 0x09, 0xc7, + 0x0c, 0xe8, 0x2d, 0xb2, 0x57, 0x11, 0xcb, 0x53, + 0x02, 0xeb, 0x27, 0x43, 0xb0, 0x36, 0xf3, 0xd7, + 0x50, 0xd6, 0xcf, 0x0d, 0xc0, 0xac, 0xb9, 0x29, + 0x50, 0xd5, 0x46, 0xdb, 0x30, 0x8f, 0x93, 0xb4, + 0xff, 0x24, 0x4a, 0xfa, 0x9d, 0xc7, 0x2b, 0xcd, + 0x75, 0x8d, 0x2c }, + 67, + + /* ADATA */ + { 0x68, 0x8e, 0x1a, 0xa9, 0x84, 0xde, 0x92, 0x6d, + 0xc7, 0xb4, 0xc4, 0x7f, 0x44 }, + 13, + + /* IV */ + { 0xb7, 0x21, 0x38, 0xb5, 0xa0, 0x5f, 0xf5, 0x07, + 0x0e, 0x8c, 0xd9, 0x41, 0x83, 0xf7, 0x61, 0xd8 }, + 16, + + /* CT */ + { 0xcb, 0xc8, 0xd2, 0xf1, 0x54, 0x81, 0xa4, 0xcc, + 0x7d, 0xd1, 0xe1, 0x9a, 0xaa, 0x83, 0xde, 0x56, + 0x78, 0x48, 0x3e, 0xc3, 0x59, 0xae, 0x7d, 0xec, + 0x2a, 0xb8, 0xd5, 0x34, 0xe0, 0x90, 0x6f, 0x4b, + 0x46, 0x63, 0xfa, 0xff, 0x58, 0xa8, 0xb2, 0xd7, + 0x33, 0xb8, 0x45, 0xee, 0xf7, 0xc9, 0xb3, 0x31, + 0xe9, 0xe1, 0x0e, 0xb2, 0x61, 0x2c, 0x99, 0x5f, + 0xeb, 0x1a, 0xc1, 0x5a, 0x62, 0x86, 0xcc, 0xe8, + 0xb2, 0x97, 0xa8 }, + + /* TAG */ + { 0x8d, 0x2d, 0x2a, 0x93, 0x72, 0x62, 0x6f, 0x6b, + 0xee, 0x85, 0x80, 0x27, 0x6a, 0x63, 0x66, 0xbf } +} + +/* rest of test cases are the same except AES key size changes... ignored... */ +}; + int idx, err; + unsigned long x, y; + unsigned char out[2][128], T[2][16]; + gcm_state gcm; + + /* find aes */ + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) { + return CRYPT_NOP; + } + } + + /* Special test case for empty AAD + empty PT */ + y = sizeof(T[0]); + if ((err = gcm_init(&gcm, idx, tests[0].K, tests[0].keylen)) != CRYPT_OK) return err; + if ((err = gcm_add_iv(&gcm, tests[0].IV, tests[0].IVlen)) != CRYPT_OK) return err; + /* intentionally skip gcm_add_aad + gcm_process */ + if ((err = gcm_done(&gcm, T[0], &y)) != CRYPT_OK) return err; + if (compare_testvector(T[0], y, tests[0].T, 16, "GCM Encrypt Tag-special", 0)) return CRYPT_FAIL_TESTVECTOR; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + y = sizeof(T[0]); + if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, + tests[x].IV, tests[x].IVlen, + tests[x].A, tests[x].alen, + (unsigned char*)tests[x].P, tests[x].ptlen, + out[0], T[0], &y, GCM_ENCRYPT)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(out[0], tests[x].ptlen, tests[x].C, tests[x].ptlen, "GCM CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if (compare_testvector(T[0], y, tests[x].T, 16, "GCM Encrypt Tag", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + y = sizeof(T[1]); + XMEMCPY(T[1], tests[x].T, 16); + if ((err = gcm_memory(idx, tests[x].K, tests[x].keylen, + tests[x].IV, tests[x].IVlen, + tests[x].A, tests[x].alen, + out[1], tests[x].ptlen, + out[0], T[1], &y, GCM_DECRYPT)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(out[1], tests[x].ptlen, tests[x].P, tests[x].ptlen, "GCM PT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/451 */ + { + unsigned char key[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; + unsigned char iv[] = { 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b }; + unsigned char valid_tag[] = { 0xd8,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; + unsigned char invalid_tag[] = { 0xd9,0x84,0x7d,0xbc,0x32,0x6a,0x06,0xe9,0x88,0xc7,0x7a,0xd3,0x86,0x3e,0x60,0x83 }; + unsigned char msg[] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f }; + unsigned char ct[] = { 0xeb,0x15,0x6d,0x08,0x1e,0xd6,0xb6,0xb5,0x5f,0x46,0x12,0xf0,0x21,0xd8,0x7b,0x39 }; + unsigned char pt[20] = { 0 }; + unsigned long taglen; + + /* VALID tag */ + taglen = sizeof(valid_tag); + err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, valid_tag, &taglen, GCM_DECRYPT); + if ((err != CRYPT_OK) || (XMEMCMP(msg, pt, sizeof(msg)) != 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* INVALID tag */ + taglen = sizeof(invalid_tag); + err = gcm_memory(idx, key, sizeof(key), iv, sizeof(iv), NULL, 0, + pt, sizeof(ct), ct, invalid_tag, &taglen, GCM_DECRYPT); + if (err == CRYPT_OK) { + return CRYPT_FAIL_TESTVECTOR; /* should fail */ + } + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_decrypt.c b/deps/libtomcrypt/src/encauth/ocb/ocb_decrypt.c new file mode 100644 index 0000000..dd512ce --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_decrypt.c @@ -0,0 +1,67 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_decrypt.c + OCB implementation, decrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Decrypt a block with OCB. + @param ocb The OCB state + @param ct The ciphertext (length of the block size of the block cipher) + @param pt [out] The plaintext (length of ct) + @return CRYPT_OK if successful +*/ +int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt) +{ + unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + /* check if valid cipher */ + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + LTC_ARGCHK(cipher_descriptor[ocb->cipher].ecb_decrypt != NULL); + + /* check length */ + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* Get Z[i] value */ + ocb_shift_xor(ocb, Z); + + /* xor ct in, encrypt, xor Z out */ + for (x = 0; x < ocb->block_len; x++) { + tmp[x] = ct[x] ^ Z[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, pt, &ocb->key)) != CRYPT_OK) { + return err; + } + for (x = 0; x < ocb->block_len; x++) { + pt[x] ^= Z[x]; + } + + /* compute checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= pt[x]; + } + + +#ifdef LTC_CLEAN_STACK + zeromem(Z, sizeof(Z)); + zeromem(tmp, sizeof(tmp)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c b/deps/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c new file mode 100644 index 0000000..0f4dcb7 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_decrypt_verify_memory.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_decrypt_verify_memory.c + OCB implementation, helper to decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Decrypt and compare the tag with OCB. + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block size of the block cipher) + @param ct The ciphertext + @param ctlen The length of the ciphertext (octets) + @param pt [out] The plaintext + @param tag The tag to compare against + @param taglen The length of the tag (octets) + @param stat [out] The result of the tag comparison (1==valid, 0==invalid) + @return CRYPT_OK if successful regardless of the tag comparison +*/ +int ocb_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat) +{ + int err; + ocb_state *ocb; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(stat != NULL); + + /* allocate memory */ + ocb = XMALLOC(sizeof(ocb_state)); + if (ocb == NULL) { + return CRYPT_MEM; + } + + if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { + goto LBL_ERR; + } + + while (ctlen > (unsigned long)ocb->block_len) { + if ((err = ocb_decrypt(ocb, ct, pt)) != CRYPT_OK) { + goto LBL_ERR; + } + ctlen -= ocb->block_len; + pt += ocb->block_len; + ct += ocb->block_len; + } + + err = ocb_done_decrypt(ocb, ct, ctlen, pt, tag, taglen, stat); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb_state)); +#endif + + XFREE(ocb); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c b/deps/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c new file mode 100644 index 0000000..3d516c9 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_done_decrypt.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_done_decrypt.c + OCB implementation, terminate decryption, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Terminate a decrypting OCB state + @param ocb The OCB state + @param ct The ciphertext (if any) + @param ctlen The length of the ciphertext (octets) + @param pt [out] The plaintext + @param tag The authentication tag (to compare against) + @param taglen The length of the authentication tag provided + @param stat [out] The result of the tag comparison + @return CRYPT_OK if the process was successful regardless if the tag is valid +*/ +int ocb_done_decrypt(ocb_state *ocb, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, int *stat) +{ + int err; + unsigned char *tagbuf; + unsigned long tagbuflen; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(stat != NULL); + + /* default to failed */ + *stat = 0; + + /* allocate memory */ + tagbuf = XMALLOC(MAXBLOCKSIZE); + if (tagbuf == NULL) { + return CRYPT_MEM; + } + + tagbuflen = MAXBLOCKSIZE; + if ((err = s_ocb_done(ocb, ct, ctlen, pt, tagbuf, &tagbuflen, 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (taglen <= tagbuflen && XMEM_NEQ(tagbuf, tag, taglen) == 0) { + *stat = 1; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tagbuf, MAXBLOCKSIZE); +#endif + + XFREE(tagbuf); + + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c b/deps/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c new file mode 100644 index 0000000..5cd39ad --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_done_encrypt.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_done_encrypt.c + OCB implementation, terminate encryption, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Terminate an encryption OCB state + @param ocb The OCB state + @param pt Remaining plaintext (if any) + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext (if any) + @param tag [out] The tag for the OCB stream + @param taglen [in/out] The max size and resulting size of the tag + @return CRYPT_OK if successful +*/ +int ocb_done_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen) +{ + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + return s_ocb_done(ocb, pt, ptlen, ct, tag, taglen, 0); +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_encrypt.c b/deps/libtomcrypt/src/encauth/ocb/ocb_encrypt.c new file mode 100644 index 0000000..ad6260f --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_encrypt.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_encrypt.c + OCB implementation, encrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Encrypt a block of data with OCB. + @param ocb The OCB state + @param pt The plaintext (length of the block size of the block cipher) + @param ct [out] The ciphertext (same size as the pt) + @return CRYPT_OK if successful +*/ +int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct) +{ + unsigned char Z[MAXBLOCKSIZE], tmp[MAXBLOCKSIZE]; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* compute checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= pt[x]; + } + + /* Get Z[i] value */ + ocb_shift_xor(ocb, Z); + + /* xor pt in, encrypt, xor Z out */ + for (x = 0; x < ocb->block_len; x++) { + tmp[x] = pt[x] ^ Z[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, ct, &ocb->key)) != CRYPT_OK) { + return err; + } + for (x = 0; x < ocb->block_len; x++) { + ct[x] ^= Z[x]; + } + +#ifdef LTC_CLEAN_STACK + zeromem(Z, sizeof(Z)); + zeromem(tmp, sizeof(tmp)); +#endif + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c b/deps/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c new file mode 100644 index 0000000..7560a6e --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_encrypt_authenticate_memory.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_encrypt_authenticate_memory.c + OCB implementation, encrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Encrypt and generate an authentication code for a buffer of memory + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block ciphers block size) + @param pt The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The authentication tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int ocb_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + ocb_state *ocb; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + + /* allocate ram */ + ocb = XMALLOC(sizeof(ocb_state)); + if (ocb == NULL) { + return CRYPT_MEM; + } + + if ((err = ocb_init(ocb, cipher, key, keylen, nonce)) != CRYPT_OK) { + goto LBL_ERR; + } + + while (ptlen > (unsigned long)ocb->block_len) { + if ((err = ocb_encrypt(ocb, pt, ct)) != CRYPT_OK) { + goto LBL_ERR; + } + ptlen -= ocb->block_len; + pt += ocb->block_len; + ct += ocb->block_len; + } + + err = ocb_done_encrypt(ocb, pt, ptlen, ct, tag, taglen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb_state)); +#endif + + XFREE(ocb); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_init.c b/deps/libtomcrypt/src/encauth/ocb/ocb_init.c new file mode 100644 index 0000000..1ae58b6 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_init.c @@ -0,0 +1,129 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_init.c + OCB implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +static const struct { + int len; + unsigned char poly_div[MAXBLOCKSIZE], + poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } +} +}; + +/** + Initialize an OCB context. + @param ocb [out] The destination of the OCB state + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block size of the cipher) + @return CRYPT_OK if successful +*/ +int ocb_init(ocb_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, const unsigned char *nonce) +{ + int poly, x, y, m, err; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* determine which polys to use */ + ocb->block_len = cipher_descriptor[cipher].block_length; + x = (int)(sizeof(polys)/sizeof(polys[0])); + for (poly = 0; poly < x; poly++) { + if (polys[poly].len == ocb->block_len) { + break; + } + } + if (poly == x) { + return CRYPT_INVALID_ARG; /* block_len not found in polys */ + } + if (polys[poly].len != ocb->block_len) { + return CRYPT_INVALID_ARG; + } + + /* schedule the key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* find L = E[0] */ + zeromem(ocb->L, ocb->block_len); + if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->L, ocb->L, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* find R = E[N xor L] */ + for (x = 0; x < ocb->block_len; x++) { + ocb->R[x] = ocb->L[x] ^ nonce[x]; + } + if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->R, ocb->R, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* find Ls[i] = L << i for i == 0..31 */ + XMEMCPY(ocb->Ls[0], ocb->L, ocb->block_len); + for (x = 1; x < 32; x++) { + m = ocb->Ls[x-1][0] >> 7; + for (y = 0; y < ocb->block_len-1; y++) { + ocb->Ls[x][y] = ((ocb->Ls[x-1][y] << 1) | (ocb->Ls[x-1][y+1] >> 7)) & 255; + } + ocb->Ls[x][ocb->block_len-1] = (ocb->Ls[x-1][ocb->block_len-1] << 1) & 255; + + if (m == 1) { + for (y = 0; y < ocb->block_len; y++) { + ocb->Ls[x][y] ^= polys[poly].poly_mul[y]; + } + } + } + + /* find Lr = L / x */ + m = ocb->L[ocb->block_len-1] & 1; + + /* shift right */ + for (x = ocb->block_len - 1; x > 0; x--) { + ocb->Lr[x] = ((ocb->L[x] >> 1) | (ocb->L[x-1] << 7)) & 255; + } + ocb->Lr[0] = ocb->L[0] >> 1; + + if (m == 1) { + for (x = 0; x < ocb->block_len; x++) { + ocb->Lr[x] ^= polys[poly].poly_div[x]; + } + } + + /* set Li, checksum */ + zeromem(ocb->Li, ocb->block_len); + zeromem(ocb->checksum, ocb->block_len); + + /* set other params */ + ocb->block_index = 1; + ocb->cipher = cipher; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_ntz.c b/deps/libtomcrypt/src/encauth/ocb/ocb_ntz.c new file mode 100644 index 0000000..b0f5570 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_ntz.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_ntz.c + OCB implementation, internal function, by Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Returns the number of leading zero bits [from lsb up] + @param x The 32-bit value to observe + @return The number of bits [from the lsb up] that are zero +*/ +int ocb_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c b/deps/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c new file mode 100644 index 0000000..2f7bb3b --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_shift_xor.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_shift_xor.c + OCB implementation, internal function, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Compute the shift/xor for OCB (internal function) + @param ocb The OCB state + @param Z The destination of the shift +*/ +void ocb_shift_xor(ocb_state *ocb, unsigned char *Z) +{ + int x, y; + y = ocb_ntz(ocb->block_index++); + for (x = 0; x < ocb->block_len; x++) { + ocb->Li[x] ^= ocb->Ls[y][x]; + Z[x] = ocb->Li[x] ^ ocb->R[x]; + } +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb/ocb_test.c b/deps/libtomcrypt/src/encauth/ocb/ocb_test.c new file mode 100644 index 0000000..b03c2fd --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/ocb_test.c @@ -0,0 +1,205 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb_test.c + OCB implementation, self-test by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/** + Test the OCB protocol + @return CRYPT_OK if successful +*/ +int ocb_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int ptlen; + unsigned char key[16], nonce[16], pt[34], ct[34], tag[16]; + } tests[] = { + + /* OCB-AES-128-0B */ +{ + 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0 }, + /* ct */ + { 0 }, + /* tag */ + { 0x15, 0xd3, 0x7d, 0xd7, 0xc8, 0x90, 0xd5, 0xd6, + 0xac, 0xab, 0x92, 0x7b, 0xc0, 0xdc, 0x60, 0xee }, +}, + + + /* OCB-AES-128-3B */ +{ + 3, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02 }, + /* ct */ + { 0xfc, 0xd3, 0x7d }, + /* tag */ + { 0x02, 0x25, 0x47, 0x39, 0xa5, 0xe3, 0x56, 0x5a, + 0xe2, 0xdc, 0xd6, 0x2c, 0x65, 0x97, 0x46, 0xba }, +}, + + /* OCB-AES-128-16B */ +{ + 16, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* ct */ + { 0x37, 0xdf, 0x8c, 0xe1, 0x5b, 0x48, 0x9b, 0xf3, + 0x1d, 0x0f, 0xc4, 0x4d, 0xa1, 0xfa, 0xf6, 0xd6 }, + /* tag */ + { 0xdf, 0xb7, 0x63, 0xeb, 0xdb, 0x5f, 0x0e, 0x71, + 0x9c, 0x7b, 0x41, 0x61, 0x80, 0x80, 0x04, 0xdf }, +}, + + /* OCB-AES-128-20B */ +{ + 20, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0x70, 0x03, 0xeb, 0x55}, + /* tag */ + { 0x75, 0x30, 0x84, 0x14, 0x4e, 0xb6, 0x3b, 0x77, + 0x0b, 0x06, 0x3c, 0x2e, 0x23, 0xcd, 0xa0, 0xbb }, +}, + + /* OCB-AES-128-32B */ +{ + 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0x4a, 0xfc, 0xbb, 0x7f, 0xed, 0xc0, 0x8c, 0xa8, + 0x65, 0x4c, 0x6d, 0x30, 0x4d, 0x16, 0x12, 0xfa }, + + /* tag */ + { 0xc1, 0x4c, 0xbf, 0x2c, 0x1a, 0x1f, 0x1c, 0x3c, + 0x13, 0x7e, 0xad, 0xea, 0x1f, 0x2f, 0x2f, 0xcf }, +}, + + /* OCB-AES-128-34B */ +{ + 34, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* nonce */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + /* pt */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + /* ct */ + { 0x01, 0xa0, 0x75, 0xf0, 0xd8, 0x15, 0xb1, 0xa4, + 0xe9, 0xc8, 0x81, 0xa1, 0xbc, 0xff, 0xc3, 0xeb, + 0xd4, 0x90, 0x3d, 0xd0, 0x02, 0x5b, 0xa4, 0xaa, + 0x83, 0x7c, 0x74, 0xf1, 0x21, 0xb0, 0x26, 0x0f, + 0xa9, 0x5d }, + + /* tag */ + { 0xcf, 0x83, 0x41, 0xbb, 0x10, 0x82, 0x0c, 0xcf, + 0x14, 0xbd, 0xec, 0x56, 0xb8, 0xd7, 0xd6, 0xab }, +}, + +}; + + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = ocb_encrypt_authenticate_memory(idx, tests[x].key, 16, + tests[x].nonce, tests[x].pt, tests[x].ptlen, outct, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB Tag", x) || + compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ocb_decrypt_verify_memory(idx, tests[x].key, 16, tests[x].nonce, outct, tests[x].ptlen, + outct, tests[x].tag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nOCB: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* LTC_OCB_MODE */ + + +/* some comments + + -- it's hard to seek + -- hard to stream [you can't emit ciphertext until full block] + -- The setup is somewhat complicated... +*/ diff --git a/deps/libtomcrypt/src/encauth/ocb/s_ocb_done.c b/deps/libtomcrypt/src/encauth/ocb/s_ocb_done.c new file mode 100644 index 0000000..c5987b9 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb/s_ocb_done.c @@ -0,0 +1,136 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file s_ocb_done.c + OCB implementation, internal helper, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB_MODE + +/* Since the last block is encrypted in CTR mode the same code can + * be used to finish a decrypt or encrypt stream. The only difference + * is we XOR the final ciphertext into the checksum so we have to xor it + * before we CTR [decrypt] or after [encrypt] + * + * the names pt/ptlen/ct really just mean in/inlen/out but this is the way I wrote it... + */ + +/** + Shared code to finish an OCB stream + @param ocb The OCB state + @param pt The remaining plaintext [or input] + @param ptlen The length of the input (octets) + @param ct [out] The output buffer + @param tag [out] The destination for the authentication tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @param mode The mode we are terminating, 0==encrypt, 1==decrypt + @return CRYPT_OK if successful +*/ +int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode) + +{ + unsigned char *Z, *Y, *X; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length || + (int)ptlen > ocb->block_len || (int)ptlen < 0) { + return CRYPT_INVALID_ARG; + } + + /* allocate ram */ + Z = XMALLOC(MAXBLOCKSIZE); + Y = XMALLOC(MAXBLOCKSIZE); + X = XMALLOC(MAXBLOCKSIZE); + if (X == NULL || Y == NULL || Z == NULL) { + if (X != NULL) { + XFREE(X); + } + if (Y != NULL) { + XFREE(Y); + } + if (Z != NULL) { + XFREE(Z); + } + return CRYPT_MEM; + } + + /* compute X[m] = len(pt[m]) XOR Lr XOR Z[m] */ + ocb_shift_xor(ocb, X); + XMEMCPY(Z, X, ocb->block_len); + + X[ocb->block_len-1] ^= (ptlen*8)&255; + X[ocb->block_len-2] ^= ((ptlen*8)>>8)&255; + for (x = 0; x < ocb->block_len; x++) { + X[x] ^= ocb->Lr[x]; + } + + /* Y[m] = E(X[m])) */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(X, Y, &ocb->key)) != CRYPT_OK) { + goto error; + } + + if (mode == 1) { + /* decrypt mode, so let's xor it first */ + /* xor C[m] into checksum */ + for (x = 0; x < (int)ptlen; x++) { + ocb->checksum[x] ^= ct[x]; + } + } + + /* C[m] = P[m] xor Y[m] */ + for (x = 0; x < (int)ptlen; x++) { + ct[x] = pt[x] ^ Y[x]; + } + + if (mode == 0) { + /* encrypt mode */ + /* xor C[m] into checksum */ + for (x = 0; x < (int)ptlen; x++) { + ocb->checksum[x] ^= ct[x]; + } + } + + /* xor Y[m] and Z[m] into checksum */ + for (x = 0; x < ocb->block_len; x++) { + ocb->checksum[x] ^= Y[x] ^ Z[x]; + } + + /* encrypt checksum, er... tag!! */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->checksum, X, &ocb->key)) != CRYPT_OK) { + goto error; + } + cipher_descriptor[ocb->cipher].done(&ocb->key); + + /* now store it */ + for (x = 0; x < ocb->block_len && x < (int)*taglen; x++) { + tag[x] = X[x]; + } + *taglen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(X, MAXBLOCKSIZE); + zeromem(Y, MAXBLOCKSIZE); + zeromem(Z, MAXBLOCKSIZE); + zeromem(ocb, sizeof(*ocb)); +#endif +error: + XFREE(X); + XFREE(Y); + XFREE(Z); + + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c new file mode 100644 index 0000000..fd09aba --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_add_aad.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_add_aad.c + OCB implementation, add AAD data, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Add one block of AAD data (internal function) + @param ocb The OCB state + @param aad_block [in] AAD data (block_len size) + @return CRYPT_OK if successful +*/ +static int s_ocb3_int_aad_add_block(ocb3_state *ocb, const unsigned char *aad_block) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err; + + /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */ + ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_[ocb3_int_ntz(ocb->ablock_index)], ocb->block_len); + + /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */ + ocb3_int_xor_blocks(tmp, aad_block, ocb->aOffset_current, ocb->block_len); + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + return err; + } + ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); + + ocb->ablock_index++; + + return CRYPT_OK; +} + +/** + Add AAD - additional associated data + @param ocb The OCB state + @param aad The AAD data + @param aadlen The size of AAD data (octets) + @return CRYPT_OK if successful +*/ +int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen) +{ + int err, x, full_blocks, full_blocks_len, last_block_len; + unsigned char *data; + unsigned long datalen, l; + + LTC_ARGCHK(ocb != NULL); + if (aadlen == 0) return CRYPT_OK; + LTC_ARGCHK(aad != NULL); + + if (ocb->adata_buffer_bytes > 0) { + l = ocb->block_len - ocb->adata_buffer_bytes; + if (l > aadlen) l = aadlen; + XMEMCPY(ocb->adata_buffer+ocb->adata_buffer_bytes, aad, l); + ocb->adata_buffer_bytes += l; + + if (ocb->adata_buffer_bytes == ocb->block_len) { + if ((err = s_ocb3_int_aad_add_block(ocb, ocb->adata_buffer)) != CRYPT_OK) { + return err; + } + ocb->adata_buffer_bytes = 0; + } + + data = (unsigned char *)aad + l; + datalen = aadlen - l; + } + else { + data = (unsigned char *)aad; + datalen = aadlen; + } + + if (datalen == 0) return CRYPT_OK; + + full_blocks = datalen/ocb->block_len; + full_blocks_len = full_blocks * ocb->block_len; + last_block_len = datalen - full_blocks_len; + + for (x=0; xblock_len)) != CRYPT_OK) { + return err; + } + } + + if (last_block_len>0) { + XMEMCPY(ocb->adata_buffer, data+full_blocks_len, last_block_len); + ocb->adata_buffer_bytes = last_block_len; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c new file mode 100644 index 0000000..5261518 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_decrypt.c + OCB implementation, decrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Decrypt blocks of ciphertext with OCB + @param ocb The OCB state + @param ct The ciphertext (length multiple of the block size of the block cipher) + @param ctlen The length of the input (octets) + @param pt [out] The plaintext (length of ct) + @return CRYPT_OK if successful +*/ +int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err, i, full_blocks; + unsigned char *pt_b, *ct_b; + + LTC_ARGCHK(ocb != NULL); + if (ctlen == 0) return CRYPT_OK; /* no data, nothing to do */ + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(pt != NULL); + + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + if (ctlen % ocb->block_len) { /* ctlen has to bu multiple of block_len */ + return CRYPT_INVALID_ARG; + } + + full_blocks = ctlen/ocb->block_len; + for(i=0; iblock_len; + ct_b = (unsigned char *)ct+i*ocb->block_len; + + /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ + ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); + + /* tmp[] = ct[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(tmp, ct_b, ocb->Offset_current, ocb->block_len); + + /* decrypt */ + if ((err = cipher_descriptor[ocb->cipher].ecb_decrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* pt[] = tmp[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(pt_b, tmp, ocb->Offset_current, ocb->block_len); + + /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); + + ocb->block_index++; + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c new file mode 100644 index 0000000..f69e34b --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_last.c @@ -0,0 +1,101 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_decrypt_last.c + OCB implementation, internal helper, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Finish an OCB (decryption) stream + @param ocb The OCB state + @param ct The remaining ciphertext + @param ctlen The length of the ciphertext (octets) + @param pt [out] The output buffer + @return CRYPT_OK if successful +*/ +int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt) +{ + unsigned char iOffset_star[MAXBLOCKSIZE]; + unsigned char iPad[MAXBLOCKSIZE]; + int err, x, full_blocks, full_blocks_len, last_block_len; + + LTC_ARGCHK(ocb != NULL); + if (ct == NULL) LTC_ARGCHK(ctlen == 0); + if (ctlen != 0) { + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(pt != NULL); + } + + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + goto LBL_ERR; + } + + full_blocks = ctlen/ocb->block_len; + full_blocks_len = full_blocks * ocb->block_len; + last_block_len = ctlen - full_blocks_len; + + /* process full blocks first */ + if (full_blocks>0) { + if ((err = ocb3_decrypt(ocb, ct, full_blocks_len, pt)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + if (last_block_len>0) { + /* Offset_* = Offset_m xor L_* */ + ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); + + /* Pad = ENCIPHER(K, Offset_*) */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* P_* = C_* xor Pad[1..bitlen(C_*)] */ + ocb3_int_xor_blocks(pt+full_blocks_len, (unsigned char *)ct+full_blocks_len, iPad, last_block_len); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); + for(x=last_block_len; xblock_len; x++) { + if (x == last_block_len) { + ocb->checksum[x] ^= 0x80; + } else { + ocb->checksum[x] ^= 0x00; + } + } + + /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } + else { + /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(iOffset_star, MAXBLOCKSIZE); + zeromem(iPad, MAXBLOCKSIZE); +#endif + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c new file mode 100644 index 0000000..03d33b2 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_decrypt_verify_memory.c @@ -0,0 +1,100 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_decrypt_verify_memory.c + OCB implementation, helper to decrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Decrypt and compare the tag with OCB + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block size of the block cipher) + @param noncelen The length of the nonce (octets) + @param adata The AAD - additional associated data + @param adatalen The length of AAD (octets) + @param ct The ciphertext + @param ctlen The length of the ciphertext (octets) + @param pt [out] The plaintext + @param tag The tag to compare against + @param taglen The length of the tag (octets) + @param stat [out] The result of the tag comparison (1==valid, 0==invalid) + @return CRYPT_OK if successful regardless of the tag comparison +*/ +int ocb3_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat) +{ + int err; + ocb3_state *ocb; + unsigned char *buf; + unsigned long buflen; + + LTC_ARGCHK(stat != NULL); + + /* default to zero */ + *stat = 0; + + /* limit taglen */ + taglen = MIN(taglen, MAXBLOCKSIZE); + + /* allocate memory */ + buf = XMALLOC(taglen); + ocb = XMALLOC(sizeof(ocb3_state)); + if (ocb == NULL || buf == NULL) { + if (ocb != NULL) { + XFREE(ocb); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, taglen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (adata != NULL || adatalen != 0) { + if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + if ((err = ocb3_decrypt_last(ocb, ct, ctlen, pt)) != CRYPT_OK) { + goto LBL_ERR; + } + + buflen = taglen; + if ((err = ocb3_done(ocb, buf, &buflen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compare tags */ + if (buflen >= taglen && XMEM_NEQ(buf, tag, taglen) == 0) { + *stat = 1; + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb3_state)); +#endif + + XFREE(ocb); + XFREE(buf); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_done.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_done.c new file mode 100644 index 0000000..688aa80 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_done.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_done.c + OCB implementation, INTERNAL ONLY helper, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Finish OCB processing and compute the tag + @param ocb The OCB state + @param tag [out] The destination for the authentication tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err, x; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(tag != NULL); + LTC_ARGCHK(taglen != NULL); + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* check taglen */ + if ((int)*taglen < ocb->tag_len) { + *taglen = (unsigned long)ocb->tag_len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* finalize AAD processing */ + + if (ocb->adata_buffer_bytes>0) { + /* Offset_* = Offset_m xor L_* */ + ocb3_int_xor_blocks(ocb->aOffset_current, ocb->aOffset_current, ocb->L_star, ocb->block_len); + + /* CipherInput = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */ + ocb3_int_xor_blocks(tmp, ocb->adata_buffer, ocb->aOffset_current, ocb->adata_buffer_bytes); + for(x=ocb->adata_buffer_bytes; xblock_len; x++) { + if (x == ocb->adata_buffer_bytes) { + tmp[x] = 0x80 ^ ocb->aOffset_current[x]; + } + else { + tmp[x] = 0x00 ^ ocb->aOffset_current[x]; + } + } + + /* Sum = Sum_m xor ENCIPHER(K, CipherInput) */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + ocb3_int_xor_blocks(ocb->aSum_current, ocb->aSum_current, tmp, ocb->block_len); + } + + /* finalize TAG computing */ + + /* at this point ocb->aSum_current = HASH(K, A) */ + /* tag = tag ^ HASH(K, A) */ + ocb3_int_xor_blocks(tmp, ocb->tag_part, ocb->aSum_current, ocb->block_len); + + /* copy tag bytes */ + for(x = 0; x < ocb->tag_len; x++) tag[x] = tmp[x]; + *taglen = (unsigned long)ocb->tag_len; + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, MAXBLOCKSIZE); + zeromem(ocb, sizeof(*ocb)); +#endif + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c new file mode 100644 index 0000000..45ba8a9 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_encrypt.c + OCB implementation, encrypt data, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Encrypt blocks of data with OCB + @param ocb The OCB state + @param pt The plaintext (length multiple of the block size of the block cipher) + @param ptlen The length of the input (octets) + @param ct [out] The ciphertext (same size as the pt) + @return CRYPT_OK if successful +*/ +int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) +{ + unsigned char tmp[MAXBLOCKSIZE]; + int err, i, full_blocks; + unsigned char *pt_b, *ct_b; + + LTC_ARGCHK(ocb != NULL); + if (ptlen == 0) return CRYPT_OK; /* no data, nothing to do */ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + return err; + } + if (ocb->block_len != cipher_descriptor[ocb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + if (ptlen % ocb->block_len) { /* ptlen has to bu multiple of block_len */ + return CRYPT_INVALID_ARG; + } + + full_blocks = ptlen/ocb->block_len; + for(i=0; iblock_len; + ct_b = (unsigned char *)ct+i*ocb->block_len; + + /* ocb->Offset_current[] = ocb->Offset_current[] ^ Offset_{ntz(block_index)} */ + ocb3_int_xor_blocks(ocb->Offset_current, ocb->Offset_current, ocb->L_[ocb3_int_ntz(ocb->block_index)], ocb->block_len); + + /* tmp[] = pt[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(tmp, pt_b, ocb->Offset_current, ocb->block_len); + + /* encrypt */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(tmp, tmp, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* ct[] = tmp[] XOR ocb->Offset_current[] */ + ocb3_int_xor_blocks(ct_b, tmp, ocb->Offset_current, ocb->block_len); + + /* ocb->checksum[] = ocb->checksum[] XOR pt[] */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt_b, ocb->block_len); + + ocb->block_index++; + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c new file mode 100644 index 0000000..b118925 --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_authenticate_memory.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_encrypt_authenticate_memory.c + OCB implementation, encrypt block of memory, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Encrypt and generate an authentication code for a buffer of memory + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce (length of the block ciphers block size) + @param noncelen The length of the nonce (octets) + @param adata The AAD - additional associated data + @param adatalen The length of AAD (octets) + @param pt The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The authentication tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int ocb3_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen) +{ + int err; + ocb3_state *ocb; + + LTC_ARGCHK(taglen != NULL); + + /* allocate memory */ + ocb = XMALLOC(sizeof(ocb3_state)); + if (ocb == NULL) { + return CRYPT_MEM; + } + + if ((err = ocb3_init(ocb, cipher, key, keylen, nonce, noncelen, *taglen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (adata != NULL || adatalen != 0) { + if ((err = ocb3_add_aad(ocb, adata, adatalen)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + if ((err = ocb3_encrypt_last(ocb, pt, ptlen, ct)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = ocb3_done(ocb, tag, taglen); + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(ocb, sizeof(ocb3_state)); +#endif + + XFREE(ocb); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c new file mode 100644 index 0000000..76bd1ed --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_encrypt_last.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_encrypt_last.c + OCB implementation, internal helper, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Finish an OCB (encryption) stream + @param ocb The OCB state + @param pt The remaining plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The output buffer + @return CRYPT_OK if successful +*/ +int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct) +{ + unsigned char iOffset_star[MAXBLOCKSIZE]; + unsigned char iPad[MAXBLOCKSIZE]; + int err, x, full_blocks, full_blocks_len, last_block_len; + + LTC_ARGCHK(ocb != NULL); + if (pt == NULL) LTC_ARGCHK(ptlen == 0); + if (ptlen != 0) { + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + } + + if ((err = cipher_is_valid(ocb->cipher)) != CRYPT_OK) { + goto LBL_ERR; + } + + full_blocks = ptlen/ocb->block_len; + full_blocks_len = full_blocks * ocb->block_len; + last_block_len = ptlen - full_blocks_len; + + /* process full blocks first */ + if (full_blocks>0) { + if ((err = ocb3_encrypt(ocb, pt, full_blocks_len, ct)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* at this point: m = ocb->block_index (last block index), Offset_m = ocb->Offset_current */ + + if (last_block_len>0) { + /* Offset_* = Offset_m xor L_* */ + ocb3_int_xor_blocks(iOffset_star, ocb->Offset_current, ocb->L_star, ocb->block_len); + + /* Pad = ENCIPHER(K, Offset_*) */ + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(iOffset_star, iPad, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* C_* = P_* xor Pad[1..bitlen(P_*)] */ + ocb3_int_xor_blocks(ct+full_blocks_len, pt+full_blocks_len, iPad, last_block_len); + + /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */ + ocb3_int_xor_blocks(ocb->checksum, ocb->checksum, pt+full_blocks_len, last_block_len); + for(x=last_block_len; xblock_len; x++) { + if (x == last_block_len) { + ocb->checksum[x] ^= 0x80; + } else { + ocb->checksum[x] ^= 0x00; + } + } + + /* Tag = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_* xor Offset_* xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ iOffset_star[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + /* Tag = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) xor HASH(K,A) */ + /* at this point we calculate only: Tag_part = ENCIPHER(K, Checksum_m xor Offset_m xor L_$) */ + for(x=0; xblock_len; x++) { + ocb->tag_part[x] = (ocb->checksum[x] ^ ocb->Offset_current[x]) ^ ocb->L_dollar[x]; + } + if ((err = cipher_descriptor[ocb->cipher].ecb_encrypt(ocb->tag_part, ocb->tag_part, &ocb->key)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(iOffset_star, MAXBLOCKSIZE); + zeromem(iPad, MAXBLOCKSIZE); +#endif + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_init.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_init.c new file mode 100644 index 0000000..09493ac --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_init.c @@ -0,0 +1,186 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_init.c + OCB implementation, initialize state, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +static void s_ocb3_int_calc_offset_zero(ocb3_state *ocb, const unsigned char *nonce, unsigned long noncelen, unsigned long taglen) +{ + int x, y, bottom; + int idx, shift; + unsigned char iNonce[MAXBLOCKSIZE]; + unsigned char iKtop[MAXBLOCKSIZE]; + unsigned char iStretch[MAXBLOCKSIZE+8]; + + /* Nonce = zeros(127-bitlen(N)) || 1 || N */ + zeromem(iNonce, sizeof(iNonce)); + for (x = ocb->block_len-1, y=0; y<(int)noncelen; x--, y++) { + iNonce[x] = nonce[noncelen-y-1]; + } + iNonce[x] = 0x01; + iNonce[0] |= ((taglen*8) % 128) << 1; + + /* bottom = str2num(Nonce[123..128]) */ + bottom = iNonce[ocb->block_len-1] & 0x3F; + + /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */ + iNonce[ocb->block_len-1] = iNonce[ocb->block_len-1] & 0xC0; + if ((cipher_descriptor[ocb->cipher].ecb_encrypt(iNonce, iKtop, &ocb->key)) != CRYPT_OK) { + zeromem(ocb->Offset_current, ocb->block_len); + return; + } + + /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */ + for (x = 0; x < ocb->block_len; x++) { + iStretch[x] = iKtop[x]; + } + for (y = 0; y < 8; y++) { + iStretch[x+y] = iKtop[y] ^ iKtop[y+1]; + } + + /* Offset_0 = Stretch[1+bottom..128+bottom] */ + idx = bottom / 8; + shift = (bottom % 8); + for (x = 0; x < ocb->block_len; x++) { + ocb->Offset_current[x] = iStretch[idx+x] << shift; + if (shift > 0) { + ocb->Offset_current[x] |= iStretch[idx+x+1] >> (8-shift); + } + } +} + +static const struct { + int len; + unsigned char poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } +} +}; + +/** + Initialize an OCB context + @param ocb [out] The destination of the OCB state + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param nonce The session nonce + @param noncelen The length of the session nonce (octets, up to 15) + @param taglen The length of the tag (octets, up to 16) + @return CRYPT_OK if successful +*/ +int ocb3_init(ocb3_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + unsigned long taglen) +{ + int poly, x, y, m, err; + unsigned char *previous, *current; + + LTC_ARGCHK(ocb != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(nonce != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + ocb->cipher = cipher; + + /* Valid Nonce? + * As of RFC7253: "string of no more than 120 bits" */ + if (noncelen > (120/8)) { + return CRYPT_INVALID_ARG; + } + + /* The blockcipher must have a 128-bit blocksize */ + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_ARG; + } + + /* The TAGLEN may be any value up to 128 (bits) */ + if (taglen > 16) { + return CRYPT_INVALID_ARG; + } + ocb->tag_len = taglen; + + /* determine which polys to use */ + ocb->block_len = cipher_descriptor[cipher].block_length; + x = (int)(sizeof(polys)/sizeof(polys[0])); + for (poly = 0; poly < x; poly++) { + if (polys[poly].len == ocb->block_len) { + break; + } + } + if (poly == x) { + return CRYPT_INVALID_ARG; /* block_len not found in polys */ + } + if (polys[poly].len != ocb->block_len) { + return CRYPT_INVALID_ARG; + } + + /* schedule the key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* L_* = ENCIPHER(K, zeros(128)) */ + zeromem(ocb->L_star, ocb->block_len); + if ((err = cipher_descriptor[cipher].ecb_encrypt(ocb->L_star, ocb->L_star, &ocb->key)) != CRYPT_OK) { + return err; + } + + /* compute L_$, L_0, L_1, ... */ + for (x = -1; x < 32; x++) { + if (x == -1) { /* gonna compute: L_$ = double(L_*) */ + current = ocb->L_dollar; + previous = ocb->L_star; + } + else if (x == 0) { /* gonna compute: L_0 = double(L_$) */ + current = ocb->L_[0]; + previous = ocb->L_dollar; + } + else { /* gonna compute: L_i = double(L_{i-1}) for every integer i > 0 */ + current = ocb->L_[x]; + previous = ocb->L_[x-1]; + } + m = previous[0] >> 7; + for (y = 0; y < ocb->block_len-1; y++) { + current[y] = ((previous[y] << 1) | (previous[y+1] >> 7)) & 255; + } + current[ocb->block_len-1] = (previous[ocb->block_len-1] << 1) & 255; + if (m == 1) { + /* current[] = current[] XOR polys[poly].poly_mul[]*/ + ocb3_int_xor_blocks(current, current, polys[poly].poly_mul, ocb->block_len); + } + } + + /* initialize ocb->Offset_current = Offset_0 */ + s_ocb3_int_calc_offset_zero(ocb, nonce, noncelen, taglen); + + /* initialize checksum to all zeros */ + zeromem(ocb->checksum, ocb->block_len); + + /* set block index */ + ocb->block_index = 1; + + /* initialize AAD related stuff */ + ocb->ablock_index = 1; + ocb->adata_buffer_bytes = 0; + zeromem(ocb->aOffset_current, ocb->block_len); + zeromem(ocb->aSum_current, ocb->block_len); + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c new file mode 100644 index 0000000..86942ce --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_int_ntz.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_int_ntz.c + OCB implementation, INTERNAL ONLY helper, by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Returns the number of leading zero bits [from lsb up] (internal function) + @param x The 32-bit value to observe + @return The number of bits [from the lsb up] that are zero +*/ +int ocb3_int_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c new file mode 100644 index 0000000..f9f342a --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_int_xor_blocks.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_int_xor_blocks.c + OCB implementation, INTERNAL ONLY helper, by Karel Miko +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Compute xor for two blocks of bytes 'out = block_a XOR block_b' (internal function) + @param out The block of bytes (output) + @param block_a The block of bytes (input) + @param block_b The block of bytes (input) + @param block_len The size of block_a, block_b, out +*/ +void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len) +{ + int x; + if (out == block_a) { + for (x = 0; x < (int)block_len; x++) out[x] ^= block_b[x]; + } + else { + for (x = 0; x < (int)block_len; x++) out[x] = block_a[x] ^ block_b[x]; + } +} + +#endif diff --git a/deps/libtomcrypt/src/encauth/ocb3/ocb3_test.c b/deps/libtomcrypt/src/encauth/ocb3/ocb3_test.c new file mode 100644 index 0000000..3a9816e --- /dev/null +++ b/deps/libtomcrypt/src/encauth/ocb3/ocb3_test.c @@ -0,0 +1,299 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file ocb3_test.c + OCB implementation, self-test by Tom St Denis +*/ +#include "tomcrypt_private.h" + +#ifdef LTC_OCB3_MODE + +/** + Test the OCB protocol + @return CRYPT_OK if successful +*/ +int ocb3_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + /* test vectors from: http://tools.ietf.org/html/draft-krovetz-ocb-03 */ + unsigned char key[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; + unsigned char nonce[12] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B }; + const struct { + int ptlen; + int aadlen; + unsigned char pt[64], aad[64], ct[64], tag[16]; + } tests[] = { + + { /* index:0 */ + 0, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x19,0x7b,0x9c,0x3c,0x44,0x1d,0x3c,0x83,0xea,0xfb,0x2b,0xef,0x63,0x3b,0x91,0x82 }, /* TAG */ + }, + { /* index:1 */ + 8, /* PLAINTEXT length */ + 8, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ + { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ + { 0x16,0xdc,0x76,0xa4,0x6d,0x47,0xe1,0xea,0xd5,0x37,0x20,0x9e,0x8a,0x96,0xd1,0x4e }, /* TAG */ + }, + { /* index:2 */ + 0, /* PLAINTEXT length */ + 8, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x98,0xb9,0x15,0x52,0xc8,0xc0,0x09,0x18,0x50,0x44,0xe3,0x0a,0x6e,0xb2,0xfe,0x21 }, /* TAG */ + }, + { /* index:3 */ + 8, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0x92,0xb6,0x57,0x13,0x0a,0x74,0xb8,0x5a }, /* CIPHERTEXT */ + { 0x97,0x1e,0xff,0xca,0xe1,0x9a,0xd4,0x71,0x6f,0x88,0xe8,0x7b,0x87,0x1f,0xbe,0xed }, /* TAG */ + }, + { /* index:4 */ + 16, /* PLAINTEXT length */ + 16, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ + { 0x77,0x6c,0x99,0x24,0xd6,0x72,0x3a,0x1f,0xc4,0x52,0x45,0x32,0xac,0x3e,0x5b,0xeb }, /* TAG */ + }, + { /* index:5 */ + 0, /* PLAINTEXT length */ + 16, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x7d,0xdb,0x8e,0x6c,0xea,0x68,0x14,0x86,0x62,0x12,0x50,0x96,0x19,0xb1,0x9c,0xc6 }, /* TAG */ + }, + { /* index:6 */ + 16, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22 }, /* CIPHERTEXT */ + { 0x13,0xcc,0x8b,0x74,0x78,0x07,0x12,0x1a,0x4c,0xbb,0x3e,0x4b,0xd6,0xb4,0x56,0xaf }, /* TAG */ + }, + { /* index:7 */ + 24, /* PLAINTEXT length */ + 24, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ + { 0x5f,0xa9,0x4f,0xc3,0xf3,0x88,0x20,0xf1,0xdc,0x3f,0x3d,0x1f,0xd4,0xe5,0x5e,0x1c }, /* TAG */ + }, + { /* index:8 */ + 0, /* PLAINTEXT length */ + 24, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x28,0x20,0x26,0xda,0x30,0x68,0xbc,0x9f,0xa1,0x18,0x68,0x1d,0x55,0x9f,0x10,0xf6 }, /* TAG */ + }, + { /* index:9 */ + 24, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xfc,0xfc,0xee,0x7a,0x2a,0x8d,0x4d,0x48 }, /* CIPHERTEXT */ + { 0x6e,0xf2,0xf5,0x25,0x87,0xfd,0xa0,0xed,0x97,0xdc,0x7e,0xed,0xe2,0x41,0xdf,0x68 }, /* TAG */ + }, + { /* index:10 */ + 32, /* PLAINTEXT length */ + 32, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ + { 0xb2,0xa0,0x40,0xdd,0x3b,0xd5,0x16,0x43,0x72,0xd7,0x6d,0x7b,0xb6,0x82,0x42,0x40 }, /* TAG */ + }, + { /* index:11 */ + 0, /* PLAINTEXT length */ + 32, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0xe1,0xe0,0x72,0x63,0x3b,0xad,0xe5,0x1a,0x60,0xe8,0x59,0x51,0xd9,0xc4,0x2a,0x1b }, /* TAG */ + }, + { /* index:12 */ + 32, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb }, /* CIPHERTEXT */ + { 0x4a,0x3b,0xae,0x82,0x44,0x65,0xcf,0xda,0xf8,0xc4,0x1f,0xc5,0x0c,0x7d,0xf9,0xd9 }, /* TAG */ + }, + { /* index:13 */ + 40, /* PLAINTEXT length */ + 40, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ + { 0x65,0x9c,0x62,0x32,0x11,0xde,0xea,0x0d,0xe3,0x0d,0x2c,0x38,0x18,0x79,0xf4,0xc8 }, /* TAG */ + }, + { /* index:14 */ + 0, /* PLAINTEXT length */ + 40, /* AAD length */ + { 0 }, /* PLAINTEXT */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* AAD */ + { 0 }, /* CIPHERTEXT */ + { 0x7a,0xeb,0x7a,0x69,0xa1,0x68,0x7d,0xd0,0x82,0xca,0x27,0xb0,0xd9,0xa3,0x70,0x96 }, /* TAG */ + }, + { /* index:15 */ + 40, /* PLAINTEXT length */ + 0, /* AAD length */ + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }, /* PLAINTEXT */ + { 0 }, /* AAD */ + { 0xbe,0xa5,0xe8,0x79,0x8d,0xbe,0x71,0x10,0x03,0x1c,0x14,0x4d,0xa0,0xb2,0x61,0x22,0xce,0xaa,0xb9,0xb0,0x5d,0xf7,0x71,0xa6,0x57,0x14,0x9d,0x53,0x77,0x34,0x63,0xcb,0x68,0xc6,0x57,0x78,0xb0,0x58,0xa6,0x35 }, /* CIPHERTEXT */ + { 0x06,0x0c,0x84,0x67,0xf4,0xab,0xab,0x5e,0x8b,0x3c,0x20,0x67,0xa2,0xe1,0x15,0xdc }, /* TAG */ + }, + +}; + /* As of RFC 7253 - 'Appendix A. Sample Results' + * The next tuple shows a result with a tag length of 96 bits and a + different key. + + K: 0F0E0D0C0B0A09080706050403020100 + + N: BBAA9988776655443322110D + A: 000102030405060708090A0B0C0D0E0F1011121314151617 + 18191A1B1C1D1E1F2021222324252627 + P: 000102030405060708090A0B0C0D0E0F1011121314151617 + 18191A1B1C1D1E1F2021222324252627 + C: 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1 + A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FD + AC4F02AA + + The C has been split up in C and T (tag) + */ + const unsigned char K[] = { 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08, + 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 }; + const unsigned char N[] = { 0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44, + 0x33,0x22,0x11,0x0D }; + const unsigned char A[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }; + const unsigned char P[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 }; + const unsigned char C[] = { 0x17,0x92,0xA4,0xE3,0x1E,0x07,0x55,0xFB, + 0x03,0xE3,0x1B,0x22,0x11,0x6E,0x6C,0x2D, + 0xDF,0x9E,0xFD,0x6E,0x33,0xD5,0x36,0xF1, + 0xA0,0x12,0x4B,0x0A,0x55,0xBA,0xE8,0x84, + 0xED,0x93,0x48,0x15,0x29,0xC7,0x6B,0x6A }; + const unsigned char T[] = { 0xD0,0xC5,0x15,0xF4,0xD1,0xCD,0xD4,0xFD, + 0xAC,0x4F,0x02,0xAA }; + + int err, x, idx, res; + unsigned long len; + unsigned char outct[MAXBLOCKSIZE] = { 0 }; + unsigned char outtag[MAXBLOCKSIZE] = { 0 }; + ocb3_state ocb; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = 16; /* must be the same as the required taglen */ + if ((err = ocb3_encrypt_authenticate_memory(idx, + key, sizeof(key), + nonce, sizeof(nonce), + tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, + tests[x].ptlen != 0 ? tests[x].pt : NULL, tests[x].ptlen, + tests[x].ptlen != 0 ? outct : NULL, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "OCB3 Tag", x) || + compare_testvector(outct, tests[x].ptlen, tests[x].ct, tests[x].ptlen, "OCB3 CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ocb3_decrypt_verify_memory(idx, + key, sizeof(key), + nonce, sizeof(nonce), + tests[x].aadlen != 0 ? tests[x].aad : NULL, tests[x].aadlen, + tests[x].ptlen != 0 ? outct : NULL, tests[x].ptlen, + tests[x].ptlen != 0 ? outct : NULL, tests[x].tag, len, &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || compare_testvector(outct, tests[x].ptlen, tests[x].pt, tests[x].ptlen, "OCB3", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + + /* RFC 7253 - test vector with a tag length of 96 bits - part 1 */ + x = 99; + len = 12; + if ((err = ocb3_encrypt_authenticate_memory(idx, + K, sizeof(K), + N, sizeof(N), + A, sizeof(A), + P, sizeof(P), + outct, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag", x) || + compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + + if ((err = ocb3_decrypt_verify_memory(idx, + K, sizeof(K), + N, sizeof(N), + A, sizeof(A), + C, sizeof(C), + outct, T, sizeof(T), &res)) != CRYPT_OK) { + return err; + } + if ((res != 1) || compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3", x)) { +#ifdef LTC_TEST_DBG + printf("\n\nOCB3: Failure-decrypt - res = %d\n", res); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + + /* RFC 7253 - test vector with a tag length of 96 bits - part 2 */ + x = 100; + if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; + if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; + if ((err = ocb3_encrypt(&ocb, P, 32, outct)) != CRYPT_OK) return err; + if ((err = ocb3_encrypt_last(&ocb, P+32, sizeof(P)-32, outct+32)) != CRYPT_OK) return err; + len = sizeof(outtag); /* intentionally more than 12 */ + if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; + if (compare_testvector(outct, sizeof(P), C, sizeof(C), "OCB3 CT", x)) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.enc", x)) return CRYPT_FAIL_TESTVECTOR; + if ((err = ocb3_init(&ocb, idx, K, sizeof(K), N, sizeof(N), 12)) != CRYPT_OK) return err; + if ((err = ocb3_add_aad(&ocb, A, sizeof(A))) != CRYPT_OK) return err; + if ((err = ocb3_decrypt(&ocb, C, 32, outct)) != CRYPT_OK) return err; + if ((err = ocb3_decrypt_last(&ocb, C+32, sizeof(C)-32, outct+32)) != CRYPT_OK) return err; + len = sizeof(outtag); /* intentionally more than 12 */ + if ((err = ocb3_done(&ocb, outtag, &len)) != CRYPT_OK) return err; + if (compare_testvector(outct, sizeof(C), P, sizeof(P), "OCB3 PT", x)) return CRYPT_FAIL_TESTVECTOR; + if (compare_testvector(outtag, len, T, sizeof(T), "OCB3 Tag.dec", x)) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* LTC_OCB3_MODE */ diff --git a/deps/libtomcrypt/src/hashes/blake2b.c b/deps/libtomcrypt/src/hashes/blake2b.c new file mode 100644 index 0000000..8cbeac2 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/blake2b.c @@ -0,0 +1,628 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ +/* see also https://www.ietf.org/rfc/rfc7693.txt */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2B + +enum blake2b_constant { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16, + BLAKE2B_PARAM_SIZE = 64 +}; + +/* param offsets */ +enum { + O_DIGEST_LENGTH = 0, + O_KEY_LENGTH = 1, + O_FANOUT = 2, + O_DEPTH = 3, + O_LEAF_LENGTH = 4, + O_NODE_OFFSET = 8, + O_XOF_LENGTH = 12, + O_NODE_DEPTH = 16, + O_INNER_LENGTH = 17, + O_RESERVED = 18, + O_SALT = 32, + O_PERSONAL = 48 +}; + +/* +struct blake2b_param { + unsigned char digest_length; + unsigned char key_length; + unsigned char fanout; + unsigned char depth; + ulong32 leaf_length; + ulong32 node_offset; + ulong32 xof_length; + unsigned char node_depth; + unsigned char inner_length; + unsigned char reserved[14]; + unsigned char salt[BLAKE2B_SALTBYTES]; + unsigned char personal[BLAKE2B_PERSONALBYTES]; +}; +*/ + +const struct ltc_hash_descriptor blake2b_160_desc = +{ + "blake2b-160", + 25, + 20, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 5 }, + 11, + &blake2b_160_init, + &blake2b_process, + &blake2b_done, + &blake2b_160_test, + NULL +}; + +const struct ltc_hash_descriptor blake2b_256_desc = +{ + "blake2b-256", + 26, + 32, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 8 }, + 11, + &blake2b_256_init, + &blake2b_process, + &blake2b_done, + &blake2b_256_test, + NULL +}; + +const struct ltc_hash_descriptor blake2b_384_desc = +{ + "blake2b-384", + 27, + 48, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 12 }, + 11, + &blake2b_384_init, + &blake2b_process, + &blake2b_done, + &blake2b_384_test, + NULL +}; + +const struct ltc_hash_descriptor blake2b_512_desc = +{ + "blake2b-512", + 28, + 64, + 128, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 1, 16 }, + 11, + &blake2b_512_init, + &blake2b_process, + &blake2b_done, + &blake2b_512_test, + NULL +}; + +static const ulong64 blake2b_IV[8] = +{ + CONST64(0x6a09e667f3bcc908), CONST64(0xbb67ae8584caa73b), + CONST64(0x3c6ef372fe94f82b), CONST64(0xa54ff53a5f1d36f1), + CONST64(0x510e527fade682d1), CONST64(0x9b05688c2b3e6c1f), + CONST64(0x1f83d9abfb41bd6b), CONST64(0x5be0cd19137e2179) +}; + +static const unsigned char blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + +static void s_blake2b_set_lastnode(hash_state *md) { md->blake2b.f[1] = CONST64(0xffffffffffffffff); } + +/* Some helper functions, not necessarily useful */ +static int s_blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; } + +static void s_blake2b_set_lastblock(hash_state *md) +{ + if (md->blake2b.last_node) { + s_blake2b_set_lastnode(md); + } + md->blake2b.f[0] = CONST64(0xffffffffffffffff); +} + +static void s_blake2b_increment_counter(hash_state *md, ulong64 inc) +{ + md->blake2b.t[0] += inc; + if (md->blake2b.t[0] < inc) md->blake2b.t[1]++; +} + +static void s_blake2b_init0(hash_state *md) +{ + unsigned long i; + XMEMSET(&md->blake2b, 0, sizeof(md->blake2b)); + + for (i = 0; i < 8; ++i) { + md->blake2b.h[i] = blake2b_IV[i]; + } +} + +/* init xors IV with input parameter block */ +static int s_blake2b_init_param(hash_state *md, const unsigned char *P) +{ + unsigned long i; + + s_blake2b_init0(md); + + /* IV XOR ParamBlock */ + for (i = 0; i < 8; ++i) { + ulong64 tmp; + LOAD64L(tmp, P + i * 8); + md->blake2b.h[i] ^= tmp; + } + + md->blake2b.outlen = P[O_DIGEST_LENGTH]; + return CRYPT_OK; +} + +/** + Initialize the hash/MAC state + + Use this function to init for arbitrary sizes. + + Give a key and keylen to init for MAC mode. + + @param md The hash state you wish to initialize + @param outlen The desired output-length + @param key The key of the MAC + @param keylen The length of the key + @return CRYPT_OK if successful +*/ +int blake2b_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + unsigned char P[BLAKE2B_PARAM_SIZE]; + int err; + + LTC_ARGCHK(md != NULL); + + if ((!outlen) || (outlen > BLAKE2B_OUTBYTES)) { + return CRYPT_INVALID_ARG; + } + if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2B_KEYBYTES)) { + return CRYPT_INVALID_ARG; + } + + XMEMSET(P, 0, sizeof(P)); + + P[O_DIGEST_LENGTH] = (unsigned char)outlen; + P[O_KEY_LENGTH] = (unsigned char)keylen; + P[O_FANOUT] = 1; + P[O_DEPTH] = 1; + + err = s_blake2b_init_param(md, P); + if (err != CRYPT_OK) return err; + + if (key) { + unsigned char block[BLAKE2B_BLOCKBYTES]; + + XMEMSET(block, 0, BLAKE2B_BLOCKBYTES); + XMEMCPY(block, key, keylen); + blake2b_process(md, block, BLAKE2B_BLOCKBYTES); + +#ifdef LTC_CLEAN_STACK + zeromem(block, sizeof(block)); +#endif + } + + return CRYPT_OK; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_256_init(hash_state *md) { return blake2b_init(md, 32, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_384_init(hash_state *md) { return blake2b_init(md, 48, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2b_512_init(hash_state *md) { return blake2b_init(md, 64, NULL, 0); } + +#define G(r, i, a, b, c, d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \ + d = ROR64(d ^ a, 32); \ + c = c + d; \ + b = ROR64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \ + d = ROR64(d ^ a, 16); \ + c = c + d; \ + b = ROR64(b ^ c, 63); \ + } while (0) + +#define ROUND(r) \ + do { \ + G(r, 0, v[0], v[4], v[8], v[12]); \ + G(r, 1, v[1], v[5], v[9], v[13]); \ + G(r, 2, v[2], v[6], v[10], v[14]); \ + G(r, 3, v[3], v[7], v[11], v[15]); \ + G(r, 4, v[0], v[5], v[10], v[15]); \ + G(r, 5, v[1], v[6], v[11], v[12]); \ + G(r, 6, v[2], v[7], v[8], v[13]); \ + G(r, 7, v[3], v[4], v[9], v[14]); \ + } while (0) + +#ifdef LTC_CLEAN_STACK +static int ss_blake2b_compress(hash_state *md, const unsigned char *buf) +#else +static int s_blake2b_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong64 m[16]; + ulong64 v[16]; + unsigned long i; + + for (i = 0; i < 16; ++i) { + LOAD64L(m[i], buf + i * sizeof(m[i])); + } + + for (i = 0; i < 8; ++i) { + v[i] = md->blake2b.h[i]; + } + + v[8] = blake2b_IV[0]; + v[9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = blake2b_IV[4] ^ md->blake2b.t[0]; + v[13] = blake2b_IV[5] ^ md->blake2b.t[1]; + v[14] = blake2b_IV[6] ^ md->blake2b.f[0]; + v[15] = blake2b_IV[7] ^ md->blake2b.f[1]; + + ROUND(0); + ROUND(1); + ROUND(2); + ROUND(3); + ROUND(4); + ROUND(5); + ROUND(6); + ROUND(7); + ROUND(8); + ROUND(9); + ROUND(10); + ROUND(11); + + for (i = 0; i < 8; ++i) { + md->blake2b.h[i] = md->blake2b.h[i] ^ v[i] ^ v[i + 8]; + } + return CRYPT_OK; +} + +#undef G +#undef ROUND + +#ifdef LTC_CLEAN_STACK +static int s_blake2b_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_blake2b_compress(md, buf); + burn_stack(sizeof(ulong64) * 32 + sizeof(unsigned long)); + return err; +} +#endif + +/** + Process a block of memory through the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +int blake2b_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + if (md->blake2b.curlen > sizeof(md->blake2b.buf)) { + return CRYPT_INVALID_ARG; + } + + if (inlen > 0) { + unsigned long left = md->blake2b.curlen; + unsigned long fill = BLAKE2B_BLOCKBYTES - left; + if (inlen > fill) { + md->blake2b.curlen = 0; + XMEMCPY(md->blake2b.buf + (left % sizeof(md->blake2b.buf)), in, fill); /* Fill buffer */ + s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); + s_blake2b_compress(md, md->blake2b.buf); /* Compress */ + in += fill; + inlen -= fill; + while (inlen > BLAKE2B_BLOCKBYTES) { + s_blake2b_increment_counter(md, BLAKE2B_BLOCKBYTES); + s_blake2b_compress(md, in); + in += BLAKE2B_BLOCKBYTES; + inlen -= BLAKE2B_BLOCKBYTES; + } + } + XMEMCPY(md->blake2b.buf + md->blake2b.curlen, in, inlen); + md->blake2b.curlen += inlen; + } + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (size depending on the length used on init) + @return CRYPT_OK if successful +*/ +int blake2b_done(hash_state *md, unsigned char *out) +{ + unsigned char buffer[BLAKE2B_OUTBYTES] = { 0 }; + unsigned long i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + /* if(md->blakebs.outlen != outlen) return CRYPT_INVALID_ARG; */ + + if (s_blake2b_is_lastblock(md)) { + return CRYPT_ERROR; + } + + s_blake2b_increment_counter(md, md->blake2b.curlen); + s_blake2b_set_lastblock(md); + XMEMSET(md->blake2b.buf + md->blake2b.curlen, 0, BLAKE2B_BLOCKBYTES - md->blake2b.curlen); /* Padding */ + s_blake2b_compress(md, md->blake2b.buf); + + for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ + STORE64L(md->blake2b.h[i], buffer + i * 8); + } + + XMEMCPY(out, buffer, md->blake2b.outlen); + zeromem(md, sizeof(hash_state)); +#ifdef LTC_CLEAN_STACK + zeromem(buffer, sizeof(buffer)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_512_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[64]; + } tests[] = { + { "", + { 0x78, 0x6a, 0x02, 0xf7, 0x42, 0x01, 0x59, 0x03, + 0xc6, 0xc6, 0xfd, 0x85, 0x25, 0x52, 0xd2, 0x72, + 0x91, 0x2f, 0x47, 0x40, 0xe1, 0x58, 0x47, 0x61, + 0x8a, 0x86, 0xe2, 0x17, 0xf7, 0x1f, 0x54, 0x19, + 0xd2, 0x5e, 0x10, 0x31, 0xaf, 0xee, 0x58, 0x53, + 0x13, 0x89, 0x64, 0x44, 0x93, 0x4e, 0xb0, 0x4b, + 0x90, 0x3a, 0x68, 0x5b, 0x14, 0x48, 0xb7, 0x55, + 0xd5, 0x6f, 0x70, 0x1a, 0xfe, 0x9b, 0xe2, 0xce } }, + { "abc", + { 0xba, 0x80, 0xa5, 0x3f, 0x98, 0x1c, 0x4d, 0x0d, + 0x6a, 0x27, 0x97, 0xb6, 0x9f, 0x12, 0xf6, 0xe9, + 0x4c, 0x21, 0x2f, 0x14, 0x68, 0x5a, 0xc4, 0xb7, + 0x4b, 0x12, 0xbb, 0x6f, 0xdb, 0xff, 0xa2, 0xd1, + 0x7d, 0x87, 0xc5, 0x39, 0x2a, 0xab, 0x79, 0x2d, + 0xc2, 0x52, 0xd5, 0xde, 0x45, 0x33, 0xcc, 0x95, + 0x18, 0xd3, 0x8a, 0xa8, 0xdb, 0xf1, 0x92, 0x5a, + 0xb9, 0x23, 0x86, 0xed, 0xd4, 0x00, 0x99, 0x23 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_512_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_512", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_384_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[48]; + } tests[] = { + { "", + { 0xb3, 0x28, 0x11, 0x42, 0x33, 0x77, 0xf5, 0x2d, + 0x78, 0x62, 0x28, 0x6e, 0xe1, 0xa7, 0x2e, 0xe5, + 0x40, 0x52, 0x43, 0x80, 0xfd, 0xa1, 0x72, 0x4a, + 0x6f, 0x25, 0xd7, 0x97, 0x8c, 0x6f, 0xd3, 0x24, + 0x4a, 0x6c, 0xaf, 0x04, 0x98, 0x81, 0x26, 0x73, + 0xc5, 0xe0, 0x5e, 0xf5, 0x83, 0x82, 0x51, 0x00 } }, + { "abc", + { 0x6f, 0x56, 0xa8, 0x2c, 0x8e, 0x7e, 0xf5, 0x26, + 0xdf, 0xe1, 0x82, 0xeb, 0x52, 0x12, 0xf7, 0xdb, + 0x9d, 0xf1, 0x31, 0x7e, 0x57, 0x81, 0x5d, 0xbd, + 0xa4, 0x60, 0x83, 0xfc, 0x30, 0xf5, 0x4e, 0xe6, + 0xc6, 0x6b, 0xa8, 0x3b, 0xe6, 0x4b, 0x30, 0x2d, + 0x7c, 0xba, 0x6c, 0xe1, 0x5b, 0xb5, 0x56, 0xf4 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[48]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_384_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_384", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "", + { 0x0e, 0x57, 0x51, 0xc0, 0x26, 0xe5, 0x43, 0xb2, + 0xe8, 0xab, 0x2e, 0xb0, 0x60, 0x99, 0xda, 0xa1, + 0xd1, 0xe5, 0xdf, 0x47, 0x77, 0x8f, 0x77, 0x87, + 0xfa, 0xab, 0x45, 0xcd, 0xf1, 0x2f, 0xe3, 0xa8 } }, + { "abc", + { 0xbd, 0xdd, 0x81, 0x3c, 0x63, 0x42, 0x39, 0x72, + 0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b, + 0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42, + 0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } }, + { "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890", + { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08, + 0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41, + 0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3, + 0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_256_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2b_160_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "", + { 0x33, 0x45, 0x52, 0x4a, 0xbf, 0x6b, 0xbe, 0x18, + 0x09, 0x44, 0x92, 0x24, 0xb5, 0x97, 0x2c, 0x41, + 0x79, 0x0b, 0x6c, 0xf2 } }, + { "abc", + { 0x38, 0x42, 0x64, 0xf6, 0x76, 0xf3, 0x95, 0x36, + 0x84, 0x05, 0x23, 0xf2, 0x84, 0x92, 0x1c, 0xdc, + 0x68, 0xb6, 0x84, 0x6b } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2b_160_init(&md); + blake2b_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2b_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2B_160", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/hashes/blake2s.c b/deps/libtomcrypt/src/hashes/blake2s.c new file mode 100644 index 0000000..e8cd6eb --- /dev/null +++ b/deps/libtomcrypt/src/hashes/blake2s.c @@ -0,0 +1,603 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + BLAKE2 reference source code package - reference C implementations + + Copyright 2012, Samuel Neves . You may use this under the + terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at + your option. The terms of these licenses can be found at: + + - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 + - OpenSSL license : https://www.openssl.org/source/license.html + - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 + + More information about the BLAKE2 hash function can be found at + https://blake2.net. +*/ +/* see also https://www.ietf.org/rfc/rfc7693.txt */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2S + +enum blake2s_constant { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8, + BLAKE2S_PARAM_SIZE = 32 +}; + +/* param offsets */ +enum { + O_DIGEST_LENGTH = 0, + O_KEY_LENGTH = 1, + O_FANOUT = 2, + O_DEPTH = 3, + O_LEAF_LENGTH = 4, + O_NODE_OFFSET = 8, + O_XOF_LENGTH = 12, + O_NODE_DEPTH = 14, + O_INNER_LENGTH = 15, + O_SALT = 16, + O_PERSONAL = 24 +}; + +/* +struct blake2s_param { + unsigned char digest_length; + unsigned char key_length; + unsigned char fanout; + unsigned char depth; + ulong32 leaf_length; + ulong32 node_offset; + ushort16 xof_length; + unsigned char node_depth; + unsigned char inner_length; + unsigned char salt[BLAKE2S_SALTBYTES]; + unsigned char personal[BLAKE2S_PERSONALBYTES]; +}; +*/ + +const struct ltc_hash_descriptor blake2s_128_desc = +{ + "blake2s-128", + 21, + 16, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 }, + 11, + &blake2s_128_init, + &blake2s_process, + &blake2s_done, + &blake2s_128_test, + NULL +}; + +const struct ltc_hash_descriptor blake2s_160_desc = +{ + "blake2s-160", + 22, + 20, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 }, + 11, + &blake2s_160_init, + &blake2s_process, + &blake2s_done, + &blake2s_160_test, + NULL +}; + +const struct ltc_hash_descriptor blake2s_224_desc = +{ + "blake2s-224", + 23, + 28, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 }, + 11, + &blake2s_224_init, + &blake2s_process, + &blake2s_done, + &blake2s_224_test, + NULL +}; + +const struct ltc_hash_descriptor blake2s_256_desc = +{ + "blake2s-256", + 24, + 32, + 64, + { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 }, + 11, + &blake2s_256_init, + &blake2s_process, + &blake2s_done, + &blake2s_256_test, + NULL +}; + +static const ulong32 blake2s_IV[8] = { + 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, + 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL +}; + +static const unsigned char blake2s_sigma[10][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, +}; + +static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; } + +/* Some helper functions, not necessarily useful */ +static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; } + +static void s_blake2s_set_lastblock(hash_state *md) +{ + if (md->blake2s.last_node) { + s_blake2s_set_lastnode(md); + } + md->blake2s.f[0] = 0xffffffffUL; +} + +static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc) +{ + md->blake2s.t[0] += inc; + if (md->blake2s.t[0] < inc) md->blake2s.t[1]++; +} + +static int s_blake2s_init0(hash_state *md) +{ + int i; + XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state)); + + for (i = 0; i < 8; ++i) { + md->blake2s.h[i] = blake2s_IV[i]; + } + + return CRYPT_OK; +} + +/* init2 xors IV with input parameter block */ +static int s_blake2s_init_param(hash_state *md, const unsigned char *P) +{ + unsigned long i; + + s_blake2s_init0(md); + + /* IV XOR ParamBlock */ + for (i = 0; i < 8; ++i) { + ulong32 tmp; + LOAD32L(tmp, P + i * 4); + md->blake2s.h[i] ^= tmp; + } + + md->blake2s.outlen = P[O_DIGEST_LENGTH]; + return CRYPT_OK; +} + +/** + Initialize the hash/MAC state + + Use this function to init for arbitrary sizes. + + Give a key and keylen to init for MAC mode. + + @param md The hash state you wish to initialize + @param outlen The desired output-length + @param key The key of the MAC + @param keylen The length of the key + @return CRYPT_OK if successful +*/ +int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + unsigned char P[BLAKE2S_PARAM_SIZE]; + int err; + + LTC_ARGCHK(md != NULL); + + if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) { + return CRYPT_INVALID_ARG; + } + if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) { + return CRYPT_INVALID_ARG; + } + + XMEMSET(P, 0, sizeof(P)); + + P[O_DIGEST_LENGTH] = (unsigned char)outlen; + P[O_KEY_LENGTH] = (unsigned char)keylen; + P[O_FANOUT] = 1; + P[O_DEPTH] = 1; + + err = s_blake2s_init_param(md, P); + if (err != CRYPT_OK) return err; + + if (key) { + unsigned char block[BLAKE2S_BLOCKBYTES]; + + XMEMSET(block, 0, BLAKE2S_BLOCKBYTES); + XMEMCPY(block, key, keylen); + blake2s_process(md, block, BLAKE2S_BLOCKBYTES); + +#ifdef LTC_CLEAN_STACK + zeromem(block, sizeof(block)); +#endif + } + return CRYPT_OK; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); } + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); } + +#define G(r, i, a, b, c, d) \ + do { \ + a = a + b + m[blake2s_sigma[r][2 * i + 0]]; \ + d = ROR(d ^ a, 16); \ + c = c + d; \ + b = ROR(b ^ c, 12); \ + a = a + b + m[blake2s_sigma[r][2 * i + 1]]; \ + d = ROR(d ^ a, 8); \ + c = c + d; \ + b = ROR(b ^ c, 7); \ + } while (0) +#define ROUND(r) \ + do { \ + G(r, 0, v[0], v[4], v[8], v[12]); \ + G(r, 1, v[1], v[5], v[9], v[13]); \ + G(r, 2, v[2], v[6], v[10], v[14]); \ + G(r, 3, v[3], v[7], v[11], v[15]); \ + G(r, 4, v[0], v[5], v[10], v[15]); \ + G(r, 5, v[1], v[6], v[11], v[12]); \ + G(r, 6, v[2], v[7], v[8], v[13]); \ + G(r, 7, v[3], v[4], v[9], v[14]); \ + } while (0) + +#ifdef LTC_CLEAN_STACK +static int ss_blake2s_compress(hash_state *md, const unsigned char *buf) +#else +static int s_blake2s_compress(hash_state *md, const unsigned char *buf) +#endif +{ + unsigned long i; + ulong32 m[16]; + ulong32 v[16]; + + for (i = 0; i < 16; ++i) { + LOAD32L(m[i], buf + i * sizeof(m[i])); + } + + for (i = 0; i < 8; ++i) { + v[i] = md->blake2s.h[i]; + } + + v[8] = blake2s_IV[0]; + v[9] = blake2s_IV[1]; + v[10] = blake2s_IV[2]; + v[11] = blake2s_IV[3]; + v[12] = md->blake2s.t[0] ^ blake2s_IV[4]; + v[13] = md->blake2s.t[1] ^ blake2s_IV[5]; + v[14] = md->blake2s.f[0] ^ blake2s_IV[6]; + v[15] = md->blake2s.f[1] ^ blake2s_IV[7]; + + ROUND(0); + ROUND(1); + ROUND(2); + ROUND(3); + ROUND(4); + ROUND(5); + ROUND(6); + ROUND(7); + ROUND(8); + ROUND(9); + + for (i = 0; i < 8; ++i) { + md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8]; + } + return CRYPT_OK; +} +#undef G +#undef ROUND + +#ifdef LTC_CLEAN_STACK +static int s_blake2s_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_blake2s_compress(md, buf); + burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long)); + return err; +} +#endif + +/** + Process a block of memory through the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + if (md->blake2s.curlen > sizeof(md->blake2s.buf)) { + return CRYPT_INVALID_ARG; + } + + if (inlen > 0) { + unsigned long left = md->blake2s.curlen; + unsigned long fill = BLAKE2S_BLOCKBYTES - left; + if (inlen > fill) { + md->blake2s.curlen = 0; + XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */ + s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); + s_blake2s_compress(md, md->blake2s.buf); /* Compress */ + in += fill; + inlen -= fill; + while (inlen > BLAKE2S_BLOCKBYTES) { + s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES); + s_blake2s_compress(md, in); + in += BLAKE2S_BLOCKBYTES; + inlen -= BLAKE2S_BLOCKBYTES; + } + } + XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen); + md->blake2s.curlen += inlen; + } + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (size depending on the length used on init) + @return CRYPT_OK if successful +*/ +int blake2s_done(hash_state *md, unsigned char *out) +{ + unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 }; + unsigned long i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */ + + if (s_blake2s_is_lastblock(md)) { + return CRYPT_ERROR; + } + s_blake2s_increment_counter(md, md->blake2s.curlen); + s_blake2s_set_lastblock(md); + XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */ + s_blake2s_compress(md, md->blake2s.buf); + + for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */ + STORE32L(md->blake2s.h[i], buffer + i * 4); + } + + XMEMCPY(out, buffer, md->blake2s.outlen); + zeromem(md, sizeof(hash_state)); +#ifdef LTC_CLEAN_STACK + zeromem(buffer, sizeof(buffer)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "", + { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94, + 0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c, + 0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e, + 0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } }, + { "abc", + { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2, + 0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f, + 0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29, + 0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } }, + { "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890", + { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41, + 0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41, + 0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70, + 0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_256_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_224_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[28]; + } tests[] = { + { "", + { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37, + 0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63, + 0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34, + 0xe7, 0xbc, 0x1e, 0xf4 } }, + { "abc", + { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd, + 0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c, + 0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87, + 0x40, 0x7f, 0xbd, 0x55 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[28]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_224_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_160_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "", + { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24, + 0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42, + 0x9c, 0x34, 0x91, 0x6f} }, + { "abc", + { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83, + 0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04, + 0x38, 0xf8, 0xde, 0x17 } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_160_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; +#endif +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int blake2s_128_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01, + 0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } }, + { "abc", + { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8, + 0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } }, + + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + blake2s_128_init(&md); + blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + blake2s_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/hashes/chc/chc.c b/deps/libtomcrypt/src/hashes/chc/chc.c new file mode 100644 index 0000000..e82b2b3 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/chc/chc.c @@ -0,0 +1,302 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file chc.c + CHC support. (Tom St Denis) +*/ + +#ifdef LTC_CHC_HASH + +#define UNDEFED_HASH -17 + +/* chc settings */ +static int cipher_idx=UNDEFED_HASH, /* which cipher */ + cipher_blocksize; /* blocksize of cipher */ + + +const struct ltc_hash_descriptor chc_desc = { + "chc_hash", 12, 0, 0, { 0 }, 0, + &chc_init, + &chc_process, + &chc_done, + &chc_test, + NULL +}; + +/** + Initialize the CHC state with a given cipher + @param cipher The index of the cipher you wish to bind + @return CRYPT_OK if successful +*/ +int chc_register(int cipher) +{ + int err, kl, idx; + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* will it be valid? */ + kl = cipher_descriptor[cipher].block_length; + + /* must be >64 bit block */ + if (kl <= 8) { + return CRYPT_INVALID_CIPHER; + } + + /* can we use the ideal keysize? */ + if ((err = cipher_descriptor[cipher].keysize(&kl)) != CRYPT_OK) { + return err; + } + /* we require that key size == block size be a valid choice */ + if (kl != cipher_descriptor[cipher].block_length) { + return CRYPT_INVALID_CIPHER; + } + + /* determine if chc_hash has been register_hash'ed already */ + if ((err = hash_is_valid(idx = find_hash("chc_hash"))) != CRYPT_OK) { + return err; + } + + /* store into descriptor */ + hash_descriptor[idx].hashsize = + hash_descriptor[idx].blocksize = cipher_descriptor[cipher].block_length; + + /* store the idx and block size */ + cipher_idx = cipher; + cipher_blocksize = cipher_descriptor[cipher].block_length; + return CRYPT_OK; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int chc_init(hash_state *md) +{ + symmetric_key *key; + unsigned char buf[MAXBLOCKSIZE]; + int err; + + LTC_ARGCHK(md != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { + return err; + } + + if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) { + return CRYPT_INVALID_CIPHER; + } + + if ((key = XMALLOC(sizeof(*key))) == NULL) { + return CRYPT_MEM; + } + + /* zero key and what not */ + zeromem(buf, cipher_blocksize); + if ((err = cipher_descriptor[cipher_idx].setup(buf, cipher_blocksize, 0, key)) != CRYPT_OK) { + XFREE(key); + return err; + } + + /* encrypt zero block */ + cipher_descriptor[cipher_idx].ecb_encrypt(buf, md->chc.state, key); + + /* zero other members */ + md->chc.length = 0; + md->chc.curlen = 0; + zeromem(md->chc.buf, sizeof(md->chc.buf)); + XFREE(key); + return CRYPT_OK; +} + +/* + key <= state + T0,T1 <= block + T0 <= encrypt T0 + state <= state xor T0 xor T1 +*/ +static int s_chc_compress(hash_state *md, const unsigned char *buf) +{ + unsigned char T[2][MAXBLOCKSIZE]; + symmetric_key *key; + int err, x; + + if ((key = XMALLOC(sizeof(*key))) == NULL) { + return CRYPT_MEM; + } + if ((err = cipher_descriptor[cipher_idx].setup(md->chc.state, cipher_blocksize, 0, key)) != CRYPT_OK) { + XFREE(key); + return err; + } + XMEMCPY(T[1], buf, cipher_blocksize); + cipher_descriptor[cipher_idx].ecb_encrypt(buf, T[0], key); + for (x = 0; x < cipher_blocksize; x++) { + md->chc.state[x] ^= T[0][x] ^ T[1][x]; + } +#ifdef LTC_CLEAN_STACK + zeromem(T, sizeof(T)); + zeromem(key, sizeof(*key)); +#endif + XFREE(key); + return CRYPT_OK; +} + +/** + Function for processing blocks + @param md The hash state + @param buf The data to hash + @param len The length of the data (octets) + @return CRYPT_OK if successful +*/ +static int ss_chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); +static HASH_PROCESS(ss_chc_process, s_chc_compress, chc, (unsigned long)cipher_blocksize) + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen) +{ + int err; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { + return err; + } + if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) { + return CRYPT_INVALID_CIPHER; + } + + return ss_chc_process(md, in, inlen); +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (length of the block size of the block cipher) + @return CRYPT_OK if successful +*/ +int chc_done(hash_state *md, unsigned char *out) +{ + int err; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher_idx)) != CRYPT_OK) { + return err; + } + if (cipher_blocksize != cipher_descriptor[cipher_idx].block_length) { + return CRYPT_INVALID_CIPHER; + } + + if (md->chc.curlen >= sizeof(md->chc.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->chc.length += md->chc.curlen * 8; + + /* append the '1' bit */ + md->chc.buf[md->chc.curlen++] = (unsigned char)0x80; + + /* if the length is currently above l-8 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->chc.curlen > (unsigned long)(cipher_blocksize - 8)) { + while (md->chc.curlen < (unsigned long)cipher_blocksize) { + md->chc.buf[md->chc.curlen++] = (unsigned char)0; + } + s_chc_compress(md, md->chc.buf); + md->chc.curlen = 0; + } + + /* pad upto l-8 bytes of zeroes */ + while (md->chc.curlen < (unsigned long)(cipher_blocksize - 8)) { + md->chc.buf[md->chc.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->chc.length, md->chc.buf+(cipher_blocksize-8)); + s_chc_compress(md, md->chc.buf); + + /* copy output */ + XMEMCPY(out, md->chc.state, cipher_blocksize); + +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int chc_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char *msg, + hash[MAXBLOCKSIZE]; + int len; + } tests[] = { +{ + (unsigned char *)"hello world", + { 0xcf, 0x57, 0x9d, 0xc3, 0x0a, 0x0e, 0xea, 0x61, + 0x0d, 0x54, 0x47, 0xc4, 0x3c, 0x06, 0xf5, 0x4e }, + 16 +} +}; + int i, oldhashidx, idx, err; + unsigned char tmp[MAXBLOCKSIZE]; + hash_state md; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + oldhashidx = cipher_idx; + chc_register(idx); + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + if ((err = chc_init(&md)) != CRYPT_OK) { + return err; + } + if ((err = chc_process(&md, tests[i].msg, XSTRLEN((char *)tests[i].msg))) != CRYPT_OK) { + return err; + } + if ((err = chc_done(&md, tmp)) != CRYPT_OK) { + return err; + } + if (compare_testvector(tmp, tests[i].len, tests[i].hash, tests[i].len, "CHC", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + if (oldhashidx != UNDEFED_HASH) { + chc_register(oldhashidx); + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/hashes/helper/hash_file.c b/deps/libtomcrypt/src/hashes/helper/hash_file.c new file mode 100644 index 0000000..d2711db --- /dev/null +++ b/deps/libtomcrypt/src/hashes/helper/hash_file.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifndef LTC_NO_FILE +/** + @file hash_file.c + Hash a file, Tom St Denis +*/ + +/** + @param hash The index of the hash desired + @param fname The name of the file you wish to hash + @param out [out] The destination of the digest + @param outlen [in/out] The max size and resulting size of the message digest + @result CRYPT_OK if successful +*/ +int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen) +{ + FILE *in; + int err; + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + return CRYPT_FILE_NOTFOUND; + } + + err = hash_filehandle(hash, in, out, outlen); + if (fclose(in) != 0) { + return CRYPT_ERROR; + } + + return err; +} +#endif /* #ifndef LTC_NO_FILE */ + diff --git a/deps/libtomcrypt/src/hashes/helper/hash_filehandle.c b/deps/libtomcrypt/src/hashes/helper/hash_filehandle.c new file mode 100644 index 0000000..f4eee7f --- /dev/null +++ b/deps/libtomcrypt/src/hashes/helper/hash_filehandle.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifndef LTC_NO_FILE +/** + @file hash_filehandle.c + Hash open files, Tom St Denis +*/ + +/** + Hash data from an open file handle. + @param hash The index of the hash you want to use + @param in The FILE* handle of the file you want to hash + @param out [out] The destination of the digest + @param outlen [in/out] The max size and resulting size of the digest + @result CRYPT_OK if successful +*/ +int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen) +{ + hash_state md; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(in != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + *outlen = hash_descriptor[hash].hashsize; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].init(&md)) != CRYPT_OK) { + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = hash_descriptor[hash].process(&md, buf, (unsigned long)x)) != CRYPT_OK) { + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + if ((err = hash_descriptor[hash].done(&md, out)) == CRYPT_OK) { + *outlen = hash_descriptor[hash].hashsize; + } + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: + XFREE(buf); + return err; +} +#endif /* #ifndef LTC_NO_FILE */ + diff --git a/deps/libtomcrypt/src/hashes/helper/hash_memory.c b/deps/libtomcrypt/src/hashes/helper/hash_memory.c new file mode 100644 index 0000000..f38f51c --- /dev/null +++ b/deps/libtomcrypt/src/hashes/helper/hash_memory.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_HASH_HELPERS +/** + @file hash_memory.c + Hash memory helper, Tom St Denis +*/ + +/** + Hash a block of memory and store the digest. + @param hash The index of the hash you wish to use + @param in The data you wish to hash + @param inlen The length of the data to hash (octets) + @param out [out] Where to store the digest + @param outlen [in/out] Max size and resulting size of the digest + @return CRYPT_OK if successful +*/ +int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) +{ + hash_state *md; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + *outlen = hash_descriptor[hash].hashsize; + return CRYPT_BUFFER_OVERFLOW; + } + + md = XMALLOC(sizeof(hash_state)); + if (md == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(md, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + err = hash_descriptor[hash].done(md, out); + *outlen = hash_descriptor[hash].hashsize; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + XFREE(md); + + return err; +} +#endif /* #ifdef LTC_HASH_HELPERS */ diff --git a/deps/libtomcrypt/src/hashes/helper/hash_memory_multi.c b/deps/libtomcrypt/src/hashes/helper/hash_memory_multi.c new file mode 100644 index 0000000..88630ff --- /dev/null +++ b/deps/libtomcrypt/src/hashes/helper/hash_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +#ifdef LTC_HASH_HELPERS +/** + @file hash_memory_multi.c + Hash (multiple buffers) memory helper, Tom St Denis +*/ + +/** + Hash multiple (non-adjacent) blocks of memory at once. + @param hash The index of the hash you wish to use + @param out [out] Where to store the digest + @param outlen [in/out] Max size and resulting size of the digest + @param in The data you wish to hash + @param inlen The length of the data to hash (octets) + @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + hash_state *md; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (*outlen < hash_descriptor[hash].hashsize) { + *outlen = hash_descriptor[hash].hashsize; + return CRYPT_BUFFER_OVERFLOW; + } + + md = XMALLOC(sizeof(hash_state)); + if (md == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_descriptor[hash].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = hash_descriptor[hash].process(md, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + err = hash_descriptor[hash].done(md, out); + *outlen = hash_descriptor[hash].hashsize; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + XFREE(md); + va_end(args); + return err; +} +#endif /* #ifdef LTC_HASH_HELPERS */ diff --git a/deps/libtomcrypt/src/hashes/md2.c b/deps/libtomcrypt/src/hashes/md2.c new file mode 100644 index 0000000..6cf0a65 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/md2.c @@ -0,0 +1,240 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param md2.c + LTC_MD2 (RFC 1319) hash function implementation by Tom St Denis +*/ + +#ifdef LTC_MD2 + +const struct ltc_hash_descriptor md2_desc = +{ + "md2", + 7, + 16, + 16, + + /* OID */ + { 1, 2, 840, 113549, 2, 2, }, + 6, + + &md2_init, + &md2_process, + &md2_done, + &md2_test, + NULL +}; + +static const unsigned char PI_SUBST[256] = { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 +}; + +/* adds 16 bytes to the checksum */ +static void s_md2_update_chksum(hash_state *md) +{ + int j; + unsigned char L; + L = md->md2.chksum[15]; + for (j = 0; j < 16; j++) { + +/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say + otherwise. +*/ + L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255); + } +} + +static void s_md2_compress(hash_state *md) +{ + int j, k; + unsigned char t; + + /* copy block */ + for (j = 0; j < 16; j++) { + md->md2.X[16+j] = md->md2.buf[j]; + md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j]; + } + + t = (unsigned char)0; + + /* do 18 rounds */ + for (j = 0; j < 18; j++) { + for (k = 0; k < 48; k++) { + t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]); + } + t = (t + (unsigned char)j) & 255; + } +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md2_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + + /* LTC_MD2 uses a zero'ed state... */ + zeromem(md->md2.X, sizeof(md->md2.X)); + zeromem(md->md2.chksum, sizeof(md->md2.chksum)); + zeromem(md->md2.buf, sizeof(md->md2.buf)); + md->md2.curlen = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +int md2_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + if (md-> md2 .curlen > sizeof(md-> md2 .buf)) { + return CRYPT_INVALID_ARG; + } + while (inlen > 0) { + n = MIN(inlen, (16 - md->md2.curlen)); + XMEMCPY(md->md2.buf + md->md2.curlen, in, (size_t)n); + md->md2.curlen += n; + in += n; + inlen -= n; + + /* is 16 bytes full? */ + if (md->md2.curlen == 16) { + s_md2_compress(md); + s_md2_update_chksum(md); + md->md2.curlen = 0; + } + } + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int md2_done(hash_state * md, unsigned char *out) +{ + unsigned long i, k; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md2.curlen >= sizeof(md->md2.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* pad the message */ + k = 16 - md->md2.curlen; + for (i = md->md2.curlen; i < 16; i++) { + md->md2.buf[i] = (unsigned char)k; + } + + /* hash and update */ + s_md2_compress(md); + s_md2_update_chksum(md); + + /* hash checksum */ + XMEMCPY(md->md2.buf, md->md2.chksum, 16); + s_md2_compress(md); + + /* output is lower 16 bytes of X */ + XMEMCPY(out, md->md2.X, 16); + +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int md2_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d, + 0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73 + } + }, + { "a", + {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72, + 0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1 + } + }, + { "message digest", + {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b, + 0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0 + } + }, + { "abcdefghijklmnopqrstuvwxyz", + {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab, + 0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b + } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39, + 0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd + } + }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d, + 0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8 + } + } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + md2_init(&md); + md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + md2_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD2", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + diff --git a/deps/libtomcrypt/src/hashes/md4.c b/deps/libtomcrypt/src/hashes/md4.c new file mode 100644 index 0000000..aadad5f --- /dev/null +++ b/deps/libtomcrypt/src/hashes/md4.c @@ -0,0 +1,296 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param md4.c + Submitted by Dobes Vandermeer (dobes@smartt.com) +*/ + +#ifdef LTC_MD4 + +const struct ltc_hash_descriptor md4_desc = +{ + "md4", + 6, + 16, + 64, + + /* OID */ + { 1, 2, 840, 113549, 2, 4, }, + 6, + + &md4_init, + &md4_process, + &md4_done, + &md4_test, + NULL +}; + +#define S11 3 +#define S12 7 +#define S13 11 +#define S14 19 +#define S21 3 +#define S22 5 +#define S23 9 +#define S24 13 +#define S31 3 +#define S32 9 +#define S33 11 +#define S34 15 + +/* F, G and H are basic LTC_MD4 functions. */ +#define F(x, y, z) (z ^ (x & (y ^ z))) +#define G(x, y, z) ((x & y) | (z & (x | y))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) ROLc(x, n) + +/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ + +#define FF(a, b, c, d, x, s) { \ + (a) += F ((b), (c), (d)) + (x); \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define GG(a, b, c, d, x, s) { \ + (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } +#define HH(a, b, c, d, x, s) { \ + (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \ + (a) = ROTATE_LEFT ((a), (s)); \ + } + +#ifdef LTC_CLEAN_STACK +static int ss_md4_compress(hash_state *md, const unsigned char *buf) +#else +static int s_md4_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 x[16], a, b, c, d; + int i; + + /* copy state */ + a = md->md4.state[0]; + b = md->md4.state[1]; + c = md->md4.state[2]; + d = md->md4.state[3]; + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(x[i], buf + (4*i)); + } + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11); /* 1 */ + FF (d, a, b, c, x[ 1], S12); /* 2 */ + FF (c, d, a, b, x[ 2], S13); /* 3 */ + FF (b, c, d, a, x[ 3], S14); /* 4 */ + FF (a, b, c, d, x[ 4], S11); /* 5 */ + FF (d, a, b, c, x[ 5], S12); /* 6 */ + FF (c, d, a, b, x[ 6], S13); /* 7 */ + FF (b, c, d, a, x[ 7], S14); /* 8 */ + FF (a, b, c, d, x[ 8], S11); /* 9 */ + FF (d, a, b, c, x[ 9], S12); /* 10 */ + FF (c, d, a, b, x[10], S13); /* 11 */ + FF (b, c, d, a, x[11], S14); /* 12 */ + FF (a, b, c, d, x[12], S11); /* 13 */ + FF (d, a, b, c, x[13], S12); /* 14 */ + FF (c, d, a, b, x[14], S13); /* 15 */ + FF (b, c, d, a, x[15], S14); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 0], S21); /* 17 */ + GG (d, a, b, c, x[ 4], S22); /* 18 */ + GG (c, d, a, b, x[ 8], S23); /* 19 */ + GG (b, c, d, a, x[12], S24); /* 20 */ + GG (a, b, c, d, x[ 1], S21); /* 21 */ + GG (d, a, b, c, x[ 5], S22); /* 22 */ + GG (c, d, a, b, x[ 9], S23); /* 23 */ + GG (b, c, d, a, x[13], S24); /* 24 */ + GG (a, b, c, d, x[ 2], S21); /* 25 */ + GG (d, a, b, c, x[ 6], S22); /* 26 */ + GG (c, d, a, b, x[10], S23); /* 27 */ + GG (b, c, d, a, x[14], S24); /* 28 */ + GG (a, b, c, d, x[ 3], S21); /* 29 */ + GG (d, a, b, c, x[ 7], S22); /* 30 */ + GG (c, d, a, b, x[11], S23); /* 31 */ + GG (b, c, d, a, x[15], S24); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 0], S31); /* 33 */ + HH (d, a, b, c, x[ 8], S32); /* 34 */ + HH (c, d, a, b, x[ 4], S33); /* 35 */ + HH (b, c, d, a, x[12], S34); /* 36 */ + HH (a, b, c, d, x[ 2], S31); /* 37 */ + HH (d, a, b, c, x[10], S32); /* 38 */ + HH (c, d, a, b, x[ 6], S33); /* 39 */ + HH (b, c, d, a, x[14], S34); /* 40 */ + HH (a, b, c, d, x[ 1], S31); /* 41 */ + HH (d, a, b, c, x[ 9], S32); /* 42 */ + HH (c, d, a, b, x[ 5], S33); /* 43 */ + HH (b, c, d, a, x[13], S34); /* 44 */ + HH (a, b, c, d, x[ 3], S31); /* 45 */ + HH (d, a, b, c, x[11], S32); /* 46 */ + HH (c, d, a, b, x[ 7], S33); /* 47 */ + HH (b, c, d, a, x[15], S34); /* 48 */ + + + /* Update our state */ + md->md4.state[0] = md->md4.state[0] + a; + md->md4.state[1] = md->md4.state[1] + b; + md->md4.state[2] = md->md4.state[2] + c; + md->md4.state[3] = md->md4.state[3] + d; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_md4_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_md4_compress(md, buf); + burn_stack(sizeof(ulong32) * 20 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md4_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->md4.state[0] = 0x67452301UL; + md->md4.state[1] = 0xefcdab89UL; + md->md4.state[2] = 0x98badcfeUL; + md->md4.state[3] = 0x10325476UL; + md->md4.length = 0; + md->md4.curlen = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(md4_process, s_md4_compress, md4, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int md4_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md4.curlen >= sizeof(md->md4.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->md4.length += md->md4.curlen * 8; + + /* append the '1' bit */ + md->md4.buf[md->md4.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->md4.curlen > 56) { + while (md->md4.curlen < 64) { + md->md4.buf[md->md4.curlen++] = (unsigned char)0; + } + s_md4_compress(md, md->md4.buf); + md->md4.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->md4.curlen < 56) { + md->md4.buf[md->md4.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->md4.length, md->md4.buf+56); + s_md4_compress(md, md->md4.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->md4.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int md4_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct md4_test_case { + const char *input; + unsigned char hash[16]; + } tests[] = { + { "", + {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, + 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} }, + { "a", + {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, + 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} }, + { "abc", + {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, + 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} }, + { "message digest", + {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, + 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} }, + { "abcdefghijklmnopqrstuvwxyz", + {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, + 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, + 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, + 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} }, + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for(i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + md4_init(&md); + md4_process(&md, (unsigned char *)tests[i].input, (unsigned long)XSTRLEN(tests[i].input)); + md4_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD4", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/deps/libtomcrypt/src/hashes/md5.c b/deps/libtomcrypt/src/hashes/md5.c new file mode 100644 index 0000000..ad404e1 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/md5.c @@ -0,0 +1,356 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @file md5.c + LTC_MD5 hash function by Tom St Denis +*/ + +#ifdef LTC_MD5 + +const struct ltc_hash_descriptor md5_desc = +{ + "md5", + 3, + 16, + 64, + + /* OID */ + { 1, 2, 840, 113549, 2, 5, }, + 6, + + &md5_init, + &md5_process, + &md5_done, + &md5_test, + NULL +}; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define G(x,y,z) (y ^ (z & (y ^ x))) +#define H(x,y,z) (x^y^z) +#define I(x,y,z) (y^(x|(~z))) + +#ifdef LTC_SMALL_CODE + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b; + +static const unsigned char Worder[64] = { + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, + 1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12, + 5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2, + 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 +}; + +static const unsigned char Rorder[64] = { + 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22, + 5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20, + 4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23, + 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21 +}; + +static const ulong32 Korder[64] = { +0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL, 0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL, +0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL, 0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL, +0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL, 0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL, +0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL, 0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL, +0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL, 0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL, +0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL, 0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL, +0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL, 0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL, +0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL, 0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL +}; + +#else + +#define FF(a,b,c,d,M,s,t) \ + a = (a + F(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define GG(a,b,c,d,M,s,t) \ + a = (a + G(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define HH(a,b,c,d,M,s,t) \ + a = (a + H(b,c,d) + M + t); a = ROLc(a, s) + b; + +#define II(a,b,c,d,M,s,t) \ + a = (a + I(b,c,d) + M + t); a = ROLc(a, s) + b; + + +#endif + +#ifdef LTC_CLEAN_STACK +static int ss_md5_compress(hash_state *md, const unsigned char *buf) +#else +static int s_md5_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 i, W[16], a, b, c, d; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32L(W[i], buf + (4*i)); + } + + /* copy state */ + a = md->md5.state[0]; + b = md->md5.state[1]; + c = md->md5.state[2]; + d = md->md5.state[3]; + +#ifdef LTC_SMALL_CODE + for (i = 0; i < 16; ++i) { + FF(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 32; ++i) { + GG(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 48; ++i) { + HH(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + + for (; i < 64; ++i) { + II(a,b,c,d,W[Worder[i]],Rorder[i],Korder[i]); + t = d; d = c; c = b; b = a; a = t; + } + +#else + FF(a,b,c,d,W[0],7,0xd76aa478UL) + FF(d,a,b,c,W[1],12,0xe8c7b756UL) + FF(c,d,a,b,W[2],17,0x242070dbUL) + FF(b,c,d,a,W[3],22,0xc1bdceeeUL) + FF(a,b,c,d,W[4],7,0xf57c0fafUL) + FF(d,a,b,c,W[5],12,0x4787c62aUL) + FF(c,d,a,b,W[6],17,0xa8304613UL) + FF(b,c,d,a,W[7],22,0xfd469501UL) + FF(a,b,c,d,W[8],7,0x698098d8UL) + FF(d,a,b,c,W[9],12,0x8b44f7afUL) + FF(c,d,a,b,W[10],17,0xffff5bb1UL) + FF(b,c,d,a,W[11],22,0x895cd7beUL) + FF(a,b,c,d,W[12],7,0x6b901122UL) + FF(d,a,b,c,W[13],12,0xfd987193UL) + FF(c,d,a,b,W[14],17,0xa679438eUL) + FF(b,c,d,a,W[15],22,0x49b40821UL) + GG(a,b,c,d,W[1],5,0xf61e2562UL) + GG(d,a,b,c,W[6],9,0xc040b340UL) + GG(c,d,a,b,W[11],14,0x265e5a51UL) + GG(b,c,d,a,W[0],20,0xe9b6c7aaUL) + GG(a,b,c,d,W[5],5,0xd62f105dUL) + GG(d,a,b,c,W[10],9,0x02441453UL) + GG(c,d,a,b,W[15],14,0xd8a1e681UL) + GG(b,c,d,a,W[4],20,0xe7d3fbc8UL) + GG(a,b,c,d,W[9],5,0x21e1cde6UL) + GG(d,a,b,c,W[14],9,0xc33707d6UL) + GG(c,d,a,b,W[3],14,0xf4d50d87UL) + GG(b,c,d,a,W[8],20,0x455a14edUL) + GG(a,b,c,d,W[13],5,0xa9e3e905UL) + GG(d,a,b,c,W[2],9,0xfcefa3f8UL) + GG(c,d,a,b,W[7],14,0x676f02d9UL) + GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) + HH(a,b,c,d,W[5],4,0xfffa3942UL) + HH(d,a,b,c,W[8],11,0x8771f681UL) + HH(c,d,a,b,W[11],16,0x6d9d6122UL) + HH(b,c,d,a,W[14],23,0xfde5380cUL) + HH(a,b,c,d,W[1],4,0xa4beea44UL) + HH(d,a,b,c,W[4],11,0x4bdecfa9UL) + HH(c,d,a,b,W[7],16,0xf6bb4b60UL) + HH(b,c,d,a,W[10],23,0xbebfbc70UL) + HH(a,b,c,d,W[13],4,0x289b7ec6UL) + HH(d,a,b,c,W[0],11,0xeaa127faUL) + HH(c,d,a,b,W[3],16,0xd4ef3085UL) + HH(b,c,d,a,W[6],23,0x04881d05UL) + HH(a,b,c,d,W[9],4,0xd9d4d039UL) + HH(d,a,b,c,W[12],11,0xe6db99e5UL) + HH(c,d,a,b,W[15],16,0x1fa27cf8UL) + HH(b,c,d,a,W[2],23,0xc4ac5665UL) + II(a,b,c,d,W[0],6,0xf4292244UL) + II(d,a,b,c,W[7],10,0x432aff97UL) + II(c,d,a,b,W[14],15,0xab9423a7UL) + II(b,c,d,a,W[5],21,0xfc93a039UL) + II(a,b,c,d,W[12],6,0x655b59c3UL) + II(d,a,b,c,W[3],10,0x8f0ccc92UL) + II(c,d,a,b,W[10],15,0xffeff47dUL) + II(b,c,d,a,W[1],21,0x85845dd1UL) + II(a,b,c,d,W[8],6,0x6fa87e4fUL) + II(d,a,b,c,W[15],10,0xfe2ce6e0UL) + II(c,d,a,b,W[6],15,0xa3014314UL) + II(b,c,d,a,W[13],21,0x4e0811a1UL) + II(a,b,c,d,W[4],6,0xf7537e82UL) + II(d,a,b,c,W[11],10,0xbd3af235UL) + II(c,d,a,b,W[2],15,0x2ad7d2bbUL) + II(b,c,d,a,W[9],21,0xeb86d391UL) +#endif + + md->md5.state[0] = md->md5.state[0] + a; + md->md5.state[1] = md->md5.state[1] + b; + md->md5.state[2] = md->md5.state[2] + c; + md->md5.state[3] = md->md5.state[3] + d; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_md5_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_md5_compress(md, buf); + burn_stack(sizeof(ulong32) * 21); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int md5_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->md5.state[0] = 0x67452301UL; + md->md5.state[1] = 0xefcdab89UL; + md->md5.state[2] = 0x98badcfeUL; + md->md5.state[3] = 0x10325476UL; + md->md5.curlen = 0; + md->md5.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(md5_process, s_md5_compress, md5, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int md5_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->md5.curlen >= sizeof(md->md5.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->md5.length += md->md5.curlen * 8; + + /* append the '1' bit */ + md->md5.buf[md->md5.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->md5.curlen > 56) { + while (md->md5.curlen < 64) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + s_md5_compress(md, md->md5.buf); + md->md5.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->md5.curlen < 56) { + md->md5.buf[md->md5.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->md5.length, md->md5.buf+56); + s_md5_compress(md, md->md5.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->md5.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int md5_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } }, + { "a", + {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } }, + { "abc", + { 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } }, + { "message digest", + { 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + { 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } }, + { NULL, { 0 } } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; tests[i].msg != NULL; i++) { + md5_init(&md); + md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + md5_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD5", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/deps/libtomcrypt/src/hashes/rmd128.c b/deps/libtomcrypt/src/hashes/rmd128.c new file mode 100644 index 0000000..e8f63e1 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/rmd128.c @@ -0,0 +1,396 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param rmd128.c + RMD128 Hash function +*/ + +/* Implementation of LTC_RIPEMD-128 based on the source by Antoon Bosselaers, ESAT-COSIC + * + * This source has been radically overhauled to be portable and work within + * the LibTomCrypt API by Tom St Denis + */ + +#ifdef LTC_RIPEMD128 + +const struct ltc_hash_descriptor rmd128_desc = +{ + "rmd128", + 8, + 16, + 64, + + /* OID */ + { 1, 0, 10118, 3, 0, 50 }, + 6, + + &rmd128_init, + &rmd128_process, + &rmd128_done, + &rmd128_test, + NULL +}; + +/* the four basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) + +/* the eight basic operations FF() through III() */ +#define FF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)); + +#define HH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)); + +#define II(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)); + +#define FFF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GGG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)); + +#define HHH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)); + +#define III(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)); + +#ifdef LTC_CLEAN_STACK +static int ss_rmd128_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd128_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = aaa = md->rmd128.state[0]; + bb = bbb = md->rmd128.state[1]; + cc = ccc = md->rmd128.state[2]; + dd = ddd = md->rmd128.state[3]; + + /* round 1 */ + FF(aa, bb, cc, dd, X[ 0], 11); + FF(dd, aa, bb, cc, X[ 1], 14); + FF(cc, dd, aa, bb, X[ 2], 15); + FF(bb, cc, dd, aa, X[ 3], 12); + FF(aa, bb, cc, dd, X[ 4], 5); + FF(dd, aa, bb, cc, X[ 5], 8); + FF(cc, dd, aa, bb, X[ 6], 7); + FF(bb, cc, dd, aa, X[ 7], 9); + FF(aa, bb, cc, dd, X[ 8], 11); + FF(dd, aa, bb, cc, X[ 9], 13); + FF(cc, dd, aa, bb, X[10], 14); + FF(bb, cc, dd, aa, X[11], 15); + FF(aa, bb, cc, dd, X[12], 6); + FF(dd, aa, bb, cc, X[13], 7); + FF(cc, dd, aa, bb, X[14], 9); + FF(bb, cc, dd, aa, X[15], 8); + + /* round 2 */ + GG(aa, bb, cc, dd, X[ 7], 7); + GG(dd, aa, bb, cc, X[ 4], 6); + GG(cc, dd, aa, bb, X[13], 8); + GG(bb, cc, dd, aa, X[ 1], 13); + GG(aa, bb, cc, dd, X[10], 11); + GG(dd, aa, bb, cc, X[ 6], 9); + GG(cc, dd, aa, bb, X[15], 7); + GG(bb, cc, dd, aa, X[ 3], 15); + GG(aa, bb, cc, dd, X[12], 7); + GG(dd, aa, bb, cc, X[ 0], 12); + GG(cc, dd, aa, bb, X[ 9], 15); + GG(bb, cc, dd, aa, X[ 5], 9); + GG(aa, bb, cc, dd, X[ 2], 11); + GG(dd, aa, bb, cc, X[14], 7); + GG(cc, dd, aa, bb, X[11], 13); + GG(bb, cc, dd, aa, X[ 8], 12); + + /* round 3 */ + HH(aa, bb, cc, dd, X[ 3], 11); + HH(dd, aa, bb, cc, X[10], 13); + HH(cc, dd, aa, bb, X[14], 6); + HH(bb, cc, dd, aa, X[ 4], 7); + HH(aa, bb, cc, dd, X[ 9], 14); + HH(dd, aa, bb, cc, X[15], 9); + HH(cc, dd, aa, bb, X[ 8], 13); + HH(bb, cc, dd, aa, X[ 1], 15); + HH(aa, bb, cc, dd, X[ 2], 14); + HH(dd, aa, bb, cc, X[ 7], 8); + HH(cc, dd, aa, bb, X[ 0], 13); + HH(bb, cc, dd, aa, X[ 6], 6); + HH(aa, bb, cc, dd, X[13], 5); + HH(dd, aa, bb, cc, X[11], 12); + HH(cc, dd, aa, bb, X[ 5], 7); + HH(bb, cc, dd, aa, X[12], 5); + + /* round 4 */ + II(aa, bb, cc, dd, X[ 1], 11); + II(dd, aa, bb, cc, X[ 9], 12); + II(cc, dd, aa, bb, X[11], 14); + II(bb, cc, dd, aa, X[10], 15); + II(aa, bb, cc, dd, X[ 0], 14); + II(dd, aa, bb, cc, X[ 8], 15); + II(cc, dd, aa, bb, X[12], 9); + II(bb, cc, dd, aa, X[ 4], 8); + II(aa, bb, cc, dd, X[13], 9); + II(dd, aa, bb, cc, X[ 3], 14); + II(cc, dd, aa, bb, X[ 7], 5); + II(bb, cc, dd, aa, X[15], 6); + II(aa, bb, cc, dd, X[14], 8); + II(dd, aa, bb, cc, X[ 5], 6); + II(cc, dd, aa, bb, X[ 6], 5); + II(bb, cc, dd, aa, X[ 2], 12); + + /* parallel round 1 */ + III(aaa, bbb, ccc, ddd, X[ 5], 8); + III(ddd, aaa, bbb, ccc, X[14], 9); + III(ccc, ddd, aaa, bbb, X[ 7], 9); + III(bbb, ccc, ddd, aaa, X[ 0], 11); + III(aaa, bbb, ccc, ddd, X[ 9], 13); + III(ddd, aaa, bbb, ccc, X[ 2], 15); + III(ccc, ddd, aaa, bbb, X[11], 15); + III(bbb, ccc, ddd, aaa, X[ 4], 5); + III(aaa, bbb, ccc, ddd, X[13], 7); + III(ddd, aaa, bbb, ccc, X[ 6], 7); + III(ccc, ddd, aaa, bbb, X[15], 8); + III(bbb, ccc, ddd, aaa, X[ 8], 11); + III(aaa, bbb, ccc, ddd, X[ 1], 14); + III(ddd, aaa, bbb, ccc, X[10], 14); + III(ccc, ddd, aaa, bbb, X[ 3], 12); + III(bbb, ccc, ddd, aaa, X[12], 6); + + /* parallel round 2 */ + HHH(aaa, bbb, ccc, ddd, X[ 6], 9); + HHH(ddd, aaa, bbb, ccc, X[11], 13); + HHH(ccc, ddd, aaa, bbb, X[ 3], 15); + HHH(bbb, ccc, ddd, aaa, X[ 7], 7); + HHH(aaa, bbb, ccc, ddd, X[ 0], 12); + HHH(ddd, aaa, bbb, ccc, X[13], 8); + HHH(ccc, ddd, aaa, bbb, X[ 5], 9); + HHH(bbb, ccc, ddd, aaa, X[10], 11); + HHH(aaa, bbb, ccc, ddd, X[14], 7); + HHH(ddd, aaa, bbb, ccc, X[15], 7); + HHH(ccc, ddd, aaa, bbb, X[ 8], 12); + HHH(bbb, ccc, ddd, aaa, X[12], 7); + HHH(aaa, bbb, ccc, ddd, X[ 4], 6); + HHH(ddd, aaa, bbb, ccc, X[ 9], 15); + HHH(ccc, ddd, aaa, bbb, X[ 1], 13); + HHH(bbb, ccc, ddd, aaa, X[ 2], 11); + + /* parallel round 3 */ + GGG(aaa, bbb, ccc, ddd, X[15], 9); + GGG(ddd, aaa, bbb, ccc, X[ 5], 7); + GGG(ccc, ddd, aaa, bbb, X[ 1], 15); + GGG(bbb, ccc, ddd, aaa, X[ 3], 11); + GGG(aaa, bbb, ccc, ddd, X[ 7], 8); + GGG(ddd, aaa, bbb, ccc, X[14], 6); + GGG(ccc, ddd, aaa, bbb, X[ 6], 6); + GGG(bbb, ccc, ddd, aaa, X[ 9], 14); + GGG(aaa, bbb, ccc, ddd, X[11], 12); + GGG(ddd, aaa, bbb, ccc, X[ 8], 13); + GGG(ccc, ddd, aaa, bbb, X[12], 5); + GGG(bbb, ccc, ddd, aaa, X[ 2], 14); + GGG(aaa, bbb, ccc, ddd, X[10], 13); + GGG(ddd, aaa, bbb, ccc, X[ 0], 13); + GGG(ccc, ddd, aaa, bbb, X[ 4], 7); + GGG(bbb, ccc, ddd, aaa, X[13], 5); + + /* parallel round 4 */ + FFF(aaa, bbb, ccc, ddd, X[ 8], 15); + FFF(ddd, aaa, bbb, ccc, X[ 6], 5); + FFF(ccc, ddd, aaa, bbb, X[ 4], 8); + FFF(bbb, ccc, ddd, aaa, X[ 1], 11); + FFF(aaa, bbb, ccc, ddd, X[ 3], 14); + FFF(ddd, aaa, bbb, ccc, X[11], 14); + FFF(ccc, ddd, aaa, bbb, X[15], 6); + FFF(bbb, ccc, ddd, aaa, X[ 0], 14); + FFF(aaa, bbb, ccc, ddd, X[ 5], 6); + FFF(ddd, aaa, bbb, ccc, X[12], 9); + FFF(ccc, ddd, aaa, bbb, X[ 2], 12); + FFF(bbb, ccc, ddd, aaa, X[13], 9); + FFF(aaa, bbb, ccc, ddd, X[ 9], 12); + FFF(ddd, aaa, bbb, ccc, X[ 7], 5); + FFF(ccc, ddd, aaa, bbb, X[10], 15); + FFF(bbb, ccc, ddd, aaa, X[14], 8); + + /* combine results */ + ddd += cc + md->rmd128.state[1]; /* final result for MDbuf[0] */ + md->rmd128.state[1] = md->rmd128.state[2] + dd + aaa; + md->rmd128.state[2] = md->rmd128.state[3] + aa + bbb; + md->rmd128.state[3] = md->rmd128.state[0] + bb + ccc; + md->rmd128.state[0] = ddd; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd128_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd128_compress(md, buf); + burn_stack(sizeof(ulong32) * 24 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd128_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd128.state[0] = 0x67452301UL; + md->rmd128.state[1] = 0xefcdab89UL; + md->rmd128.state[2] = 0x98badcfeUL; + md->rmd128.state[3] = 0x10325476UL; + md->rmd128.curlen = 0; + md->rmd128.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(rmd128_process, s_rmd128_compress, rmd128, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int rmd128_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd128.length += md->rmd128.curlen * 8; + + /* append the '1' bit */ + md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->rmd128.curlen > 56) { + while (md->rmd128.curlen < 64) { + md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; + } + s_rmd128_compress(md, md->rmd128.buf); + md->rmd128.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd128.curlen < 56) { + md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd128.length, md->rmd128.buf+56); + s_rmd128_compress(md, md->rmd128.buf); + + /* copy output */ + for (i = 0; i < 4; i++) { + STORE32L(md->rmd128.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int rmd128_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[16]; + } tests[] = { + { "", + { 0xcd, 0xf2, 0x62, 0x13, 0xa1, 0x50, 0xdc, 0x3e, + 0xcb, 0x61, 0x0f, 0x18, 0xf6, 0xb3, 0x8b, 0x46 } + }, + { "a", + { 0x86, 0xbe, 0x7a, 0xfa, 0x33, 0x9d, 0x0f, 0xc7, + 0xcf, 0xc7, 0x85, 0xe7, 0x2f, 0x57, 0x8d, 0x33 } + }, + { "abc", + { 0xc1, 0x4a, 0x12, 0x19, 0x9c, 0x66, 0xe4, 0xba, + 0x84, 0x63, 0x6b, 0x0f, 0x69, 0x14, 0x4c, 0x77 } + }, + { "message digest", + { 0x9e, 0x32, 0x7b, 0x3d, 0x6e, 0x52, 0x30, 0x62, + 0xaf, 0xc1, 0x13, 0x2d, 0x7d, 0xf9, 0xd1, 0xb8 } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xfd, 0x2a, 0xa6, 0x07, 0xf7, 0x1d, 0xc8, 0xf5, + 0x10, 0x71, 0x49, 0x22, 0xb3, 0x71, 0x83, 0x4e } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0xd1, 0xe9, 0x59, 0xeb, 0x17, 0x9c, 0x91, 0x1f, + 0xae, 0xa4, 0x62, 0x4c, 0x60, 0xc5, 0xc7, 0x02 } + } + }; + + int i; + unsigned char tmp[16]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd128_init(&md); + rmd128_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd128_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD128", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + diff --git a/deps/libtomcrypt/src/hashes/rmd160.c b/deps/libtomcrypt/src/hashes/rmd160.c new file mode 100644 index 0000000..1eba20a --- /dev/null +++ b/deps/libtomcrypt/src/hashes/rmd160.c @@ -0,0 +1,455 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rmd160.c + RMD160 hash function +*/ + +/* Implementation of LTC_RIPEMD-160 based on the source by Antoon Bosselaers, ESAT-COSIC + * + * This source has been radically overhauled to be portable and work within + * the LibTomCrypt API by Tom St Denis + */ + +#ifdef LTC_RIPEMD160 + +const struct ltc_hash_descriptor rmd160_desc = +{ + "rmd160", + 9, + 20, + 64, + + /* OID */ + { 1, 3, 36, 3, 2, 1, }, + 6, + + &rmd160_init, + &rmd160_process, + &rmd160_done, + &rmd160_test, + NULL +}; + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define II(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define FFF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GGG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HHH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define III(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + +#ifdef LTC_CLEAN_STACK +static int ss_rmd160_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd160_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = aaa = md->rmd160.state[0]; + bb = bbb = md->rmd160.state[1]; + cc = ccc = md->rmd160.state[2]; + dd = ddd = md->rmd160.state[3]; + ee = eee = md->rmd160.state[4]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + /* combine results */ + ddd += cc + md->rmd160.state[1]; /* final result for md->rmd160.state[0] */ + md->rmd160.state[1] = md->rmd160.state[2] + dd + eee; + md->rmd160.state[2] = md->rmd160.state[3] + ee + aaa; + md->rmd160.state[3] = md->rmd160.state[4] + aa + bbb; + md->rmd160.state[4] = md->rmd160.state[0] + bb + ccc; + md->rmd160.state[0] = ddd; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd160_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd160_compress(md, buf); + burn_stack(sizeof(ulong32) * 26 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd160_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd160.state[0] = 0x67452301UL; + md->rmd160.state[1] = 0xefcdab89UL; + md->rmd160.state[2] = 0x98badcfeUL; + md->rmd160.state[3] = 0x10325476UL; + md->rmd160.state[4] = 0xc3d2e1f0UL; + md->rmd160.curlen = 0; + md->rmd160.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(rmd160_process, s_rmd160_compress, rmd160, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return CRYPT_OK if successful +*/ +int rmd160_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd160.curlen >= sizeof(md->rmd160.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd160.length += md->rmd160.curlen * 8; + + /* append the '1' bit */ + md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->rmd160.curlen > 56) { + while (md->rmd160.curlen < 64) { + md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; + } + s_rmd160_compress(md, md->rmd160.buf); + md->rmd160.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd160.curlen < 56) { + md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd160.length, md->rmd160.buf+56); + s_rmd160_compress(md, md->rmd160.buf); + + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32L(md->rmd160.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int rmd160_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "", + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 } + }, + { "a", + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe } + }, + { "abc", + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc } + }, + { "message digest", + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b } + } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd160_init(&md); + rmd160_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd160_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD160", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + diff --git a/deps/libtomcrypt/src/hashes/rmd256.c b/deps/libtomcrypt/src/hashes/rmd256.c new file mode 100644 index 0000000..0097198 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/rmd256.c @@ -0,0 +1,420 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param rmd256.c + RLTC_MD256 Hash function +*/ + +#ifdef LTC_RIPEMD256 + +const struct ltc_hash_descriptor rmd256_desc = +{ + "rmd256", + 13, + 32, + 64, + + /* OID */ + { 1, 3, 36, 3, 2, 3 }, + 6, + + &rmd256_init, + &rmd256_process, + &rmd256_done, + &rmd256_test, + NULL +}; + +/* the four basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) + +/* the eight basic operations FF() through III() */ +#define FF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)); + +#define HH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)); + +#define II(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)); + +#define FFF(a, b, c, d, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)); + +#define GGG(a, b, c, d, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)); + +#define HHH(a, b, c, d, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)); + +#define III(a, b, c, d, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)); + +#ifdef LTC_CLEAN_STACK +static int ss_rmd256_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd256_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,tmp,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = md->rmd256.state[0]; + bb = md->rmd256.state[1]; + cc = md->rmd256.state[2]; + dd = md->rmd256.state[3]; + aaa = md->rmd256.state[4]; + bbb = md->rmd256.state[5]; + ccc = md->rmd256.state[6]; + ddd = md->rmd256.state[7]; + + /* round 1 */ + FF(aa, bb, cc, dd, X[ 0], 11); + FF(dd, aa, bb, cc, X[ 1], 14); + FF(cc, dd, aa, bb, X[ 2], 15); + FF(bb, cc, dd, aa, X[ 3], 12); + FF(aa, bb, cc, dd, X[ 4], 5); + FF(dd, aa, bb, cc, X[ 5], 8); + FF(cc, dd, aa, bb, X[ 6], 7); + FF(bb, cc, dd, aa, X[ 7], 9); + FF(aa, bb, cc, dd, X[ 8], 11); + FF(dd, aa, bb, cc, X[ 9], 13); + FF(cc, dd, aa, bb, X[10], 14); + FF(bb, cc, dd, aa, X[11], 15); + FF(aa, bb, cc, dd, X[12], 6); + FF(dd, aa, bb, cc, X[13], 7); + FF(cc, dd, aa, bb, X[14], 9); + FF(bb, cc, dd, aa, X[15], 8); + + /* parallel round 1 */ + III(aaa, bbb, ccc, ddd, X[ 5], 8); + III(ddd, aaa, bbb, ccc, X[14], 9); + III(ccc, ddd, aaa, bbb, X[ 7], 9); + III(bbb, ccc, ddd, aaa, X[ 0], 11); + III(aaa, bbb, ccc, ddd, X[ 9], 13); + III(ddd, aaa, bbb, ccc, X[ 2], 15); + III(ccc, ddd, aaa, bbb, X[11], 15); + III(bbb, ccc, ddd, aaa, X[ 4], 5); + III(aaa, bbb, ccc, ddd, X[13], 7); + III(ddd, aaa, bbb, ccc, X[ 6], 7); + III(ccc, ddd, aaa, bbb, X[15], 8); + III(bbb, ccc, ddd, aaa, X[ 8], 11); + III(aaa, bbb, ccc, ddd, X[ 1], 14); + III(ddd, aaa, bbb, ccc, X[10], 14); + III(ccc, ddd, aaa, bbb, X[ 3], 12); + III(bbb, ccc, ddd, aaa, X[12], 6); + + tmp = aa; aa = aaa; aaa = tmp; + + /* round 2 */ + GG(aa, bb, cc, dd, X[ 7], 7); + GG(dd, aa, bb, cc, X[ 4], 6); + GG(cc, dd, aa, bb, X[13], 8); + GG(bb, cc, dd, aa, X[ 1], 13); + GG(aa, bb, cc, dd, X[10], 11); + GG(dd, aa, bb, cc, X[ 6], 9); + GG(cc, dd, aa, bb, X[15], 7); + GG(bb, cc, dd, aa, X[ 3], 15); + GG(aa, bb, cc, dd, X[12], 7); + GG(dd, aa, bb, cc, X[ 0], 12); + GG(cc, dd, aa, bb, X[ 9], 15); + GG(bb, cc, dd, aa, X[ 5], 9); + GG(aa, bb, cc, dd, X[ 2], 11); + GG(dd, aa, bb, cc, X[14], 7); + GG(cc, dd, aa, bb, X[11], 13); + GG(bb, cc, dd, aa, X[ 8], 12); + + /* parallel round 2 */ + HHH(aaa, bbb, ccc, ddd, X[ 6], 9); + HHH(ddd, aaa, bbb, ccc, X[11], 13); + HHH(ccc, ddd, aaa, bbb, X[ 3], 15); + HHH(bbb, ccc, ddd, aaa, X[ 7], 7); + HHH(aaa, bbb, ccc, ddd, X[ 0], 12); + HHH(ddd, aaa, bbb, ccc, X[13], 8); + HHH(ccc, ddd, aaa, bbb, X[ 5], 9); + HHH(bbb, ccc, ddd, aaa, X[10], 11); + HHH(aaa, bbb, ccc, ddd, X[14], 7); + HHH(ddd, aaa, bbb, ccc, X[15], 7); + HHH(ccc, ddd, aaa, bbb, X[ 8], 12); + HHH(bbb, ccc, ddd, aaa, X[12], 7); + HHH(aaa, bbb, ccc, ddd, X[ 4], 6); + HHH(ddd, aaa, bbb, ccc, X[ 9], 15); + HHH(ccc, ddd, aaa, bbb, X[ 1], 13); + HHH(bbb, ccc, ddd, aaa, X[ 2], 11); + + tmp = bb; bb = bbb; bbb = tmp; + + /* round 3 */ + HH(aa, bb, cc, dd, X[ 3], 11); + HH(dd, aa, bb, cc, X[10], 13); + HH(cc, dd, aa, bb, X[14], 6); + HH(bb, cc, dd, aa, X[ 4], 7); + HH(aa, bb, cc, dd, X[ 9], 14); + HH(dd, aa, bb, cc, X[15], 9); + HH(cc, dd, aa, bb, X[ 8], 13); + HH(bb, cc, dd, aa, X[ 1], 15); + HH(aa, bb, cc, dd, X[ 2], 14); + HH(dd, aa, bb, cc, X[ 7], 8); + HH(cc, dd, aa, bb, X[ 0], 13); + HH(bb, cc, dd, aa, X[ 6], 6); + HH(aa, bb, cc, dd, X[13], 5); + HH(dd, aa, bb, cc, X[11], 12); + HH(cc, dd, aa, bb, X[ 5], 7); + HH(bb, cc, dd, aa, X[12], 5); + + /* parallel round 3 */ + GGG(aaa, bbb, ccc, ddd, X[15], 9); + GGG(ddd, aaa, bbb, ccc, X[ 5], 7); + GGG(ccc, ddd, aaa, bbb, X[ 1], 15); + GGG(bbb, ccc, ddd, aaa, X[ 3], 11); + GGG(aaa, bbb, ccc, ddd, X[ 7], 8); + GGG(ddd, aaa, bbb, ccc, X[14], 6); + GGG(ccc, ddd, aaa, bbb, X[ 6], 6); + GGG(bbb, ccc, ddd, aaa, X[ 9], 14); + GGG(aaa, bbb, ccc, ddd, X[11], 12); + GGG(ddd, aaa, bbb, ccc, X[ 8], 13); + GGG(ccc, ddd, aaa, bbb, X[12], 5); + GGG(bbb, ccc, ddd, aaa, X[ 2], 14); + GGG(aaa, bbb, ccc, ddd, X[10], 13); + GGG(ddd, aaa, bbb, ccc, X[ 0], 13); + GGG(ccc, ddd, aaa, bbb, X[ 4], 7); + GGG(bbb, ccc, ddd, aaa, X[13], 5); + + tmp = cc; cc = ccc; ccc = tmp; + + /* round 4 */ + II(aa, bb, cc, dd, X[ 1], 11); + II(dd, aa, bb, cc, X[ 9], 12); + II(cc, dd, aa, bb, X[11], 14); + II(bb, cc, dd, aa, X[10], 15); + II(aa, bb, cc, dd, X[ 0], 14); + II(dd, aa, bb, cc, X[ 8], 15); + II(cc, dd, aa, bb, X[12], 9); + II(bb, cc, dd, aa, X[ 4], 8); + II(aa, bb, cc, dd, X[13], 9); + II(dd, aa, bb, cc, X[ 3], 14); + II(cc, dd, aa, bb, X[ 7], 5); + II(bb, cc, dd, aa, X[15], 6); + II(aa, bb, cc, dd, X[14], 8); + II(dd, aa, bb, cc, X[ 5], 6); + II(cc, dd, aa, bb, X[ 6], 5); + II(bb, cc, dd, aa, X[ 2], 12); + + /* parallel round 4 */ + FFF(aaa, bbb, ccc, ddd, X[ 8], 15); + FFF(ddd, aaa, bbb, ccc, X[ 6], 5); + FFF(ccc, ddd, aaa, bbb, X[ 4], 8); + FFF(bbb, ccc, ddd, aaa, X[ 1], 11); + FFF(aaa, bbb, ccc, ddd, X[ 3], 14); + FFF(ddd, aaa, bbb, ccc, X[11], 14); + FFF(ccc, ddd, aaa, bbb, X[15], 6); + FFF(bbb, ccc, ddd, aaa, X[ 0], 14); + FFF(aaa, bbb, ccc, ddd, X[ 5], 6); + FFF(ddd, aaa, bbb, ccc, X[12], 9); + FFF(ccc, ddd, aaa, bbb, X[ 2], 12); + FFF(bbb, ccc, ddd, aaa, X[13], 9); + FFF(aaa, bbb, ccc, ddd, X[ 9], 12); + FFF(ddd, aaa, bbb, ccc, X[ 7], 5); + FFF(ccc, ddd, aaa, bbb, X[10], 15); + FFF(bbb, ccc, ddd, aaa, X[14], 8); + + tmp = dd; dd = ddd; ddd = tmp; + + /* combine results */ + md->rmd256.state[0] += aa; + md->rmd256.state[1] += bb; + md->rmd256.state[2] += cc; + md->rmd256.state[3] += dd; + md->rmd256.state[4] += aaa; + md->rmd256.state[5] += bbb; + md->rmd256.state[6] += ccc; + md->rmd256.state[7] += ddd; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd256_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd256_compress(md, buf); + burn_stack(sizeof(ulong32) * 25 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd256.state[0] = 0x67452301UL; + md->rmd256.state[1] = 0xefcdab89UL; + md->rmd256.state[2] = 0x98badcfeUL; + md->rmd256.state[3] = 0x10325476UL; + md->rmd256.state[4] = 0x76543210UL; + md->rmd256.state[5] = 0xfedcba98UL; + md->rmd256.state[6] = 0x89abcdefUL; + md->rmd256.state[7] = 0x01234567UL; + md->rmd256.curlen = 0; + md->rmd256.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(rmd256_process, s_rmd256_compress, rmd256, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (16 bytes) + @return CRYPT_OK if successful +*/ +int rmd256_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd256.curlen >= sizeof(md->rmd256.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd256.length += md->rmd256.curlen * 8; + + /* append the '1' bit */ + md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->rmd256.curlen > 56) { + while (md->rmd256.curlen < 64) { + md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; + } + s_rmd256_compress(md, md->rmd256.buf); + md->rmd256.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd256.curlen < 56) { + md->rmd256.buf[md->rmd256.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd256.length, md->rmd256.buf+56); + s_rmd256_compress(md, md->rmd256.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32L(md->rmd256.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int rmd256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "", + { 0x02, 0xba, 0x4c, 0x4e, 0x5f, 0x8e, 0xcd, 0x18, + 0x77, 0xfc, 0x52, 0xd6, 0x4d, 0x30, 0xe3, 0x7a, + 0x2d, 0x97, 0x74, 0xfb, 0x1e, 0x5d, 0x02, 0x63, + 0x80, 0xae, 0x01, 0x68, 0xe3, 0xc5, 0x52, 0x2d } + }, + { "a", + { 0xf9, 0x33, 0x3e, 0x45, 0xd8, 0x57, 0xf5, 0xd9, + 0x0a, 0x91, 0xba, 0xb7, 0x0a, 0x1e, 0xba, 0x0c, + 0xfb, 0x1b, 0xe4, 0xb0, 0x78, 0x3c, 0x9a, 0xcf, + 0xcd, 0x88, 0x3a, 0x91, 0x34, 0x69, 0x29, 0x25 } + }, + { "abc", + { 0xaf, 0xbd, 0x6e, 0x22, 0x8b, 0x9d, 0x8c, 0xbb, + 0xce, 0xf5, 0xca, 0x2d, 0x03, 0xe6, 0xdb, 0xa1, + 0x0a, 0xc0, 0xbc, 0x7d, 0xcb, 0xe4, 0x68, 0x0e, + 0x1e, 0x42, 0xd2, 0xe9, 0x75, 0x45, 0x9b, 0x65 } + }, + { "message digest", + { 0x87, 0xe9, 0x71, 0x75, 0x9a, 0x1c, 0xe4, 0x7a, + 0x51, 0x4d, 0x5c, 0x91, 0x4c, 0x39, 0x2c, 0x90, + 0x18, 0xc7, 0xc4, 0x6b, 0xc1, 0x44, 0x65, 0x55, + 0x4a, 0xfc, 0xdf, 0x54, 0xa5, 0x07, 0x0c, 0x0e } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0x64, 0x9d, 0x30, 0x34, 0x75, 0x1e, 0xa2, 0x16, + 0x77, 0x6b, 0xf9, 0xa1, 0x8a, 0xcc, 0x81, 0xbc, + 0x78, 0x96, 0x11, 0x8a, 0x51, 0x97, 0x96, 0x87, + 0x82, 0xdd, 0x1f, 0xd9, 0x7d, 0x8d, 0x51, 0x33 } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0x57, 0x40, 0xa4, 0x08, 0xac, 0x16, 0xb7, 0x20, + 0xb8, 0x44, 0x24, 0xae, 0x93, 0x1c, 0xbb, 0x1f, + 0xe3, 0x63, 0xd1, 0xd0, 0xbf, 0x40, 0x17, 0xf1, + 0xa8, 0x9f, 0x7e, 0xa6, 0xde, 0x77, 0xa0, 0xb8 } + } + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd256_init(&md); + rmd256_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd256_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/hashes/rmd320.c b/deps/libtomcrypt/src/hashes/rmd320.c new file mode 100644 index 0000000..0021d67 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/rmd320.c @@ -0,0 +1,485 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rmd320.c + RMD320 hash function +*/ + +#ifdef LTC_RIPEMD320 + +const struct ltc_hash_descriptor rmd320_desc = +{ + "rmd320", + 14, + 40, + 64, + + /* OID ... does not exist + * http://oid-info.com/get/1.3.36.3.2 */ + { 0 }, + 0, + + &rmd320_init, + &rmd320_process, + &rmd320_done, + &rmd320_test, + NULL +}; + +/* the five basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the ten basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define II(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define FFF(a, b, c, d, e, x, s) \ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define GGG(a, b, c, d, e, x, s) \ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define HHH(a, b, c, d, e, x, s) \ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define III(a, b, c, d, e, x, s) \ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + +#define JJJ(a, b, c, d, e, x, s) \ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROLc((a), (s)) + (e);\ + (c) = ROLc((c), 10); + + +#ifdef LTC_CLEAN_STACK +static int ss_rmd320_compress(hash_state *md, const unsigned char *buf) +#else +static int s_rmd320_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,tmp,X[16]; + int i; + + /* load words X */ + for (i = 0; i < 16; i++){ + LOAD32L(X[i], buf + (4 * i)); + } + + /* load state */ + aa = md->rmd320.state[0]; + bb = md->rmd320.state[1]; + cc = md->rmd320.state[2]; + dd = md->rmd320.state[3]; + ee = md->rmd320.state[4]; + aaa = md->rmd320.state[5]; + bbb = md->rmd320.state[6]; + ccc = md->rmd320.state[7]; + ddd = md->rmd320.state[8]; + eee = md->rmd320.state[9]; + + /* round 1 */ + FF(aa, bb, cc, dd, ee, X[ 0], 11); + FF(ee, aa, bb, cc, dd, X[ 1], 14); + FF(dd, ee, aa, bb, cc, X[ 2], 15); + FF(cc, dd, ee, aa, bb, X[ 3], 12); + FF(bb, cc, dd, ee, aa, X[ 4], 5); + FF(aa, bb, cc, dd, ee, X[ 5], 8); + FF(ee, aa, bb, cc, dd, X[ 6], 7); + FF(dd, ee, aa, bb, cc, X[ 7], 9); + FF(cc, dd, ee, aa, bb, X[ 8], 11); + FF(bb, cc, dd, ee, aa, X[ 9], 13); + FF(aa, bb, cc, dd, ee, X[10], 14); + FF(ee, aa, bb, cc, dd, X[11], 15); + FF(dd, ee, aa, bb, cc, X[12], 6); + FF(cc, dd, ee, aa, bb, X[13], 7); + FF(bb, cc, dd, ee, aa, X[14], 9); + FF(aa, bb, cc, dd, ee, X[15], 8); + + /* parallel round 1 */ + JJJ(aaa, bbb, ccc, ddd, eee, X[ 5], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 7], 9); + JJJ(ccc, ddd, eee, aaa, bbb, X[ 0], 11); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 9], 13); + JJJ(aaa, bbb, ccc, ddd, eee, X[ 2], 15); + JJJ(eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 4], 5); + JJJ(ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 6], 7); + JJJ(aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ(eee, aaa, bbb, ccc, ddd, X[ 8], 11); + JJJ(ddd, eee, aaa, bbb, ccc, X[ 1], 14); + JJJ(ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ(bbb, ccc, ddd, eee, aaa, X[ 3], 12); + JJJ(aaa, bbb, ccc, ddd, eee, X[12], 6); + + tmp = aa; aa = aaa; aaa = tmp; + + /* round 2 */ + GG(ee, aa, bb, cc, dd, X[ 7], 7); + GG(dd, ee, aa, bb, cc, X[ 4], 6); + GG(cc, dd, ee, aa, bb, X[13], 8); + GG(bb, cc, dd, ee, aa, X[ 1], 13); + GG(aa, bb, cc, dd, ee, X[10], 11); + GG(ee, aa, bb, cc, dd, X[ 6], 9); + GG(dd, ee, aa, bb, cc, X[15], 7); + GG(cc, dd, ee, aa, bb, X[ 3], 15); + GG(bb, cc, dd, ee, aa, X[12], 7); + GG(aa, bb, cc, dd, ee, X[ 0], 12); + GG(ee, aa, bb, cc, dd, X[ 9], 15); + GG(dd, ee, aa, bb, cc, X[ 5], 9); + GG(cc, dd, ee, aa, bb, X[ 2], 11); + GG(bb, cc, dd, ee, aa, X[14], 7); + GG(aa, bb, cc, dd, ee, X[11], 13); + GG(ee, aa, bb, cc, dd, X[ 8], 12); + + /* parallel round 2 */ + III(eee, aaa, bbb, ccc, ddd, X[ 6], 9); + III(ddd, eee, aaa, bbb, ccc, X[11], 13); + III(ccc, ddd, eee, aaa, bbb, X[ 3], 15); + III(bbb, ccc, ddd, eee, aaa, X[ 7], 7); + III(aaa, bbb, ccc, ddd, eee, X[ 0], 12); + III(eee, aaa, bbb, ccc, ddd, X[13], 8); + III(ddd, eee, aaa, bbb, ccc, X[ 5], 9); + III(ccc, ddd, eee, aaa, bbb, X[10], 11); + III(bbb, ccc, ddd, eee, aaa, X[14], 7); + III(aaa, bbb, ccc, ddd, eee, X[15], 7); + III(eee, aaa, bbb, ccc, ddd, X[ 8], 12); + III(ddd, eee, aaa, bbb, ccc, X[12], 7); + III(ccc, ddd, eee, aaa, bbb, X[ 4], 6); + III(bbb, ccc, ddd, eee, aaa, X[ 9], 15); + III(aaa, bbb, ccc, ddd, eee, X[ 1], 13); + III(eee, aaa, bbb, ccc, ddd, X[ 2], 11); + + tmp = bb; bb = bbb; bbb = tmp; + + /* round 3 */ + HH(dd, ee, aa, bb, cc, X[ 3], 11); + HH(cc, dd, ee, aa, bb, X[10], 13); + HH(bb, cc, dd, ee, aa, X[14], 6); + HH(aa, bb, cc, dd, ee, X[ 4], 7); + HH(ee, aa, bb, cc, dd, X[ 9], 14); + HH(dd, ee, aa, bb, cc, X[15], 9); + HH(cc, dd, ee, aa, bb, X[ 8], 13); + HH(bb, cc, dd, ee, aa, X[ 1], 15); + HH(aa, bb, cc, dd, ee, X[ 2], 14); + HH(ee, aa, bb, cc, dd, X[ 7], 8); + HH(dd, ee, aa, bb, cc, X[ 0], 13); + HH(cc, dd, ee, aa, bb, X[ 6], 6); + HH(bb, cc, dd, ee, aa, X[13], 5); + HH(aa, bb, cc, dd, ee, X[11], 12); + HH(ee, aa, bb, cc, dd, X[ 5], 7); + HH(dd, ee, aa, bb, cc, X[12], 5); + + /* parallel round 3 */ + HHH(ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH(ccc, ddd, eee, aaa, bbb, X[ 5], 7); + HHH(bbb, ccc, ddd, eee, aaa, X[ 1], 15); + HHH(aaa, bbb, ccc, ddd, eee, X[ 3], 11); + HHH(eee, aaa, bbb, ccc, ddd, X[ 7], 8); + HHH(ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH(ccc, ddd, eee, aaa, bbb, X[ 6], 6); + HHH(bbb, ccc, ddd, eee, aaa, X[ 9], 14); + HHH(aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH(eee, aaa, bbb, ccc, ddd, X[ 8], 13); + HHH(ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH(ccc, ddd, eee, aaa, bbb, X[ 2], 14); + HHH(bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH(aaa, bbb, ccc, ddd, eee, X[ 0], 13); + HHH(eee, aaa, bbb, ccc, ddd, X[ 4], 7); + HHH(ddd, eee, aaa, bbb, ccc, X[13], 5); + + tmp = cc; cc = ccc; ccc = tmp; + + /* round 4 */ + II(cc, dd, ee, aa, bb, X[ 1], 11); + II(bb, cc, dd, ee, aa, X[ 9], 12); + II(aa, bb, cc, dd, ee, X[11], 14); + II(ee, aa, bb, cc, dd, X[10], 15); + II(dd, ee, aa, bb, cc, X[ 0], 14); + II(cc, dd, ee, aa, bb, X[ 8], 15); + II(bb, cc, dd, ee, aa, X[12], 9); + II(aa, bb, cc, dd, ee, X[ 4], 8); + II(ee, aa, bb, cc, dd, X[13], 9); + II(dd, ee, aa, bb, cc, X[ 3], 14); + II(cc, dd, ee, aa, bb, X[ 7], 5); + II(bb, cc, dd, ee, aa, X[15], 6); + II(aa, bb, cc, dd, ee, X[14], 8); + II(ee, aa, bb, cc, dd, X[ 5], 6); + II(dd, ee, aa, bb, cc, X[ 6], 5); + II(cc, dd, ee, aa, bb, X[ 2], 12); + + /* parallel round 4 */ + GGG(ccc, ddd, eee, aaa, bbb, X[ 8], 15); + GGG(bbb, ccc, ddd, eee, aaa, X[ 6], 5); + GGG(aaa, bbb, ccc, ddd, eee, X[ 4], 8); + GGG(eee, aaa, bbb, ccc, ddd, X[ 1], 11); + GGG(ddd, eee, aaa, bbb, ccc, X[ 3], 14); + GGG(ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG(bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG(aaa, bbb, ccc, ddd, eee, X[ 0], 14); + GGG(eee, aaa, bbb, ccc, ddd, X[ 5], 6); + GGG(ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG(ccc, ddd, eee, aaa, bbb, X[ 2], 12); + GGG(bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG(aaa, bbb, ccc, ddd, eee, X[ 9], 12); + GGG(eee, aaa, bbb, ccc, ddd, X[ 7], 5); + GGG(ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG(ccc, ddd, eee, aaa, bbb, X[14], 8); + + tmp = dd; dd = ddd; ddd = tmp; + + /* round 5 */ + JJ(bb, cc, dd, ee, aa, X[ 4], 9); + JJ(aa, bb, cc, dd, ee, X[ 0], 15); + JJ(ee, aa, bb, cc, dd, X[ 5], 5); + JJ(dd, ee, aa, bb, cc, X[ 9], 11); + JJ(cc, dd, ee, aa, bb, X[ 7], 6); + JJ(bb, cc, dd, ee, aa, X[12], 8); + JJ(aa, bb, cc, dd, ee, X[ 2], 13); + JJ(ee, aa, bb, cc, dd, X[10], 12); + JJ(dd, ee, aa, bb, cc, X[14], 5); + JJ(cc, dd, ee, aa, bb, X[ 1], 12); + JJ(bb, cc, dd, ee, aa, X[ 3], 13); + JJ(aa, bb, cc, dd, ee, X[ 8], 14); + JJ(ee, aa, bb, cc, dd, X[11], 11); + JJ(dd, ee, aa, bb, cc, X[ 6], 8); + JJ(cc, dd, ee, aa, bb, X[15], 5); + JJ(bb, cc, dd, ee, aa, X[13], 6); + + /* parallel round 5 */ + FFF(bbb, ccc, ddd, eee, aaa, X[12] , 8); + FFF(aaa, bbb, ccc, ddd, eee, X[15] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[10] , 12); + FFF(ddd, eee, aaa, bbb, ccc, X[ 4] , 9); + FFF(ccc, ddd, eee, aaa, bbb, X[ 1] , 12); + FFF(bbb, ccc, ddd, eee, aaa, X[ 5] , 5); + FFF(aaa, bbb, ccc, ddd, eee, X[ 8] , 14); + FFF(eee, aaa, bbb, ccc, ddd, X[ 7] , 6); + FFF(ddd, eee, aaa, bbb, ccc, X[ 6] , 8); + FFF(ccc, ddd, eee, aaa, bbb, X[ 2] , 13); + FFF(bbb, ccc, ddd, eee, aaa, X[13] , 6); + FFF(aaa, bbb, ccc, ddd, eee, X[14] , 5); + FFF(eee, aaa, bbb, ccc, ddd, X[ 0] , 15); + FFF(ddd, eee, aaa, bbb, ccc, X[ 3] , 13); + FFF(ccc, ddd, eee, aaa, bbb, X[ 9] , 11); + FFF(bbb, ccc, ddd, eee, aaa, X[11] , 11); + + tmp = ee; ee = eee; eee = tmp; + + /* combine results */ + md->rmd320.state[0] += aa; + md->rmd320.state[1] += bb; + md->rmd320.state[2] += cc; + md->rmd320.state[3] += dd; + md->rmd320.state[4] += ee; + md->rmd320.state[5] += aaa; + md->rmd320.state[6] += bbb; + md->rmd320.state[7] += ccc; + md->rmd320.state[8] += ddd; + md->rmd320.state[9] += eee; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_rmd320_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_rmd320_compress(md, buf); + burn_stack(sizeof(ulong32) * 27 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int rmd320_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->rmd320.state[0] = 0x67452301UL; + md->rmd320.state[1] = 0xefcdab89UL; + md->rmd320.state[2] = 0x98badcfeUL; + md->rmd320.state[3] = 0x10325476UL; + md->rmd320.state[4] = 0xc3d2e1f0UL; + md->rmd320.state[5] = 0x76543210UL; + md->rmd320.state[6] = 0xfedcba98UL; + md->rmd320.state[7] = 0x89abcdefUL; + md->rmd320.state[8] = 0x01234567UL; + md->rmd320.state[9] = 0x3c2d1e0fUL; + md->rmd320.curlen = 0; + md->rmd320.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(rmd320_process, s_rmd320_compress, rmd320, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return CRYPT_OK if successful +*/ +int rmd320_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->rmd320.curlen >= sizeof(md->rmd320.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->rmd320.length += md->rmd320.curlen * 8; + + /* append the '1' bit */ + md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->rmd320.curlen > 56) { + while (md->rmd320.curlen < 64) { + md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; + } + s_rmd320_compress(md, md->rmd320.buf); + md->rmd320.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->rmd320.curlen < 56) { + md->rmd320.buf[md->rmd320.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->rmd320.length, md->rmd320.buf+56); + s_rmd320_compress(md, md->rmd320.buf); + + /* copy output */ + for (i = 0; i < 10; i++) { + STORE32L(md->rmd320.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int rmd320_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[40]; + } tests[] = { + { "", + { 0x22, 0xd6, 0x5d, 0x56, 0x61, 0x53, 0x6c, 0xdc, 0x75, 0xc1, + 0xfd, 0xf5, 0xc6, 0xde, 0x7b, 0x41, 0xb9, 0xf2, 0x73, 0x25, + 0xeb, 0xc6, 0x1e, 0x85, 0x57, 0x17, 0x7d, 0x70, 0x5a, 0x0e, + 0xc8, 0x80, 0x15, 0x1c, 0x3a, 0x32, 0xa0, 0x08, 0x99, 0xb8 } + }, + { "a", + { 0xce, 0x78, 0x85, 0x06, 0x38, 0xf9, 0x26, 0x58, 0xa5, 0xa5, + 0x85, 0x09, 0x75, 0x79, 0x92, 0x6d, 0xda, 0x66, 0x7a, 0x57, + 0x16, 0x56, 0x2c, 0xfc, 0xf6, 0xfb, 0xe7, 0x7f, 0x63, 0x54, + 0x2f, 0x99, 0xb0, 0x47, 0x05, 0xd6, 0x97, 0x0d, 0xff, 0x5d } + }, + { "abc", + { 0xde, 0x4c, 0x01, 0xb3, 0x05, 0x4f, 0x89, 0x30, 0xa7, 0x9d, + 0x09, 0xae, 0x73, 0x8e, 0x92, 0x30, 0x1e, 0x5a, 0x17, 0x08, + 0x5b, 0xef, 0xfd, 0xc1, 0xb8, 0xd1, 0x16, 0x71, 0x3e, 0x74, + 0xf8, 0x2f, 0xa9, 0x42, 0xd6, 0x4c, 0xdb, 0xc4, 0x68, 0x2d } + }, + { "message digest", + { 0x3a, 0x8e, 0x28, 0x50, 0x2e, 0xd4, 0x5d, 0x42, 0x2f, 0x68, + 0x84, 0x4f, 0x9d, 0xd3, 0x16, 0xe7, 0xb9, 0x85, 0x33, 0xfa, + 0x3f, 0x2a, 0x91, 0xd2, 0x9f, 0x84, 0xd4, 0x25, 0xc8, 0x8d, + 0x6b, 0x4e, 0xff, 0x72, 0x7d, 0xf6, 0x6a, 0x7c, 0x01, 0x97 } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xca, 0xbd, 0xb1, 0x81, 0x0b, 0x92, 0x47, 0x0a, 0x20, 0x93, + 0xaa, 0x6b, 0xce, 0x05, 0x95, 0x2c, 0x28, 0x34, 0x8c, 0xf4, + 0x3f, 0xf6, 0x08, 0x41, 0x97, 0x51, 0x66, 0xbb, 0x40, 0xed, + 0x23, 0x40, 0x04, 0xb8, 0x82, 0x44, 0x63, 0xe6, 0xb0, 0x09 } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0xd0, 0x34, 0xa7, 0x95, 0x0c, 0xf7, 0x22, 0x02, 0x1b, 0xa4, + 0xb8, 0x4d, 0xf7, 0x69, 0xa5, 0xde, 0x20, 0x60, 0xe2, 0x59, + 0xdf, 0x4c, 0x9b, 0xb4, 0xa4, 0x26, 0x8c, 0x0e, 0x93, 0x5b, + 0xbc, 0x74, 0x70, 0xa9, 0x69, 0xc9, 0xd0, 0x72, 0xa1, 0xac } + } + }; + + int i; + unsigned char tmp[40]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + rmd320_init(&md); + rmd320_process(&md, (unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + rmd320_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "RIPEMD320", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/hashes/sha1.c b/deps/libtomcrypt/src/hashes/sha1.c new file mode 100644 index 0000000..40709db --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha1.c @@ -0,0 +1,276 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file sha1.c + LTC_SHA1 code by Tom St Denis +*/ + + +#ifdef LTC_SHA1 + +const struct ltc_hash_descriptor sha1_desc = +{ + "sha1", + 2, + 20, + 64, + + /* OID */ + { 1, 3, 14, 3, 2, 26, }, + 6, + + &sha1_init, + &sha1_process, + &sha1_done, + &sha1_test, + NULL +}; + +#define F0(x,y,z) (z ^ (x & (y ^ z))) +#define F1(x,y,z) (x ^ y ^ z) +#define F2(x,y,z) ((x & y) | (z & (x | y))) +#define F3(x,y,z) (x ^ y ^ z) + +#ifdef LTC_CLEAN_STACK +static int ss_sha1_compress(hash_state *md, const unsigned char *buf) +#else +static int s_sha1_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong32 a,b,c,d,e,W[80],i; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* copy state */ + a = md->sha1.state[0]; + b = md->sha1.state[1]; + c = md->sha1.state[2]; + d = md->sha1.state[3]; + e = md->sha1.state[4]; + + /* expand it */ + for (i = 16; i < 80; i++) { + W[i] = ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); + } + + /* compress */ + /* round one */ + #define FF0(a,b,c,d,e,i) e = (ROLc(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL); b = ROLc(b, 30); + #define FF1(a,b,c,d,e,i) e = (ROLc(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = ROLc(b, 30); + #define FF2(a,b,c,d,e,i) e = (ROLc(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = ROLc(b, 30); + #define FF3(a,b,c,d,e,i) e = (ROLc(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = ROLc(b, 30); + +#ifdef LTC_SMALL_CODE + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + +#else + + for (i = 0; i < 20; ) { + FF0(a,b,c,d,e,i++); + FF0(e,a,b,c,d,i++); + FF0(d,e,a,b,c,i++); + FF0(c,d,e,a,b,i++); + FF0(b,c,d,e,a,i++); + } + + /* round two */ + for (; i < 40; ) { + FF1(a,b,c,d,e,i++); + FF1(e,a,b,c,d,i++); + FF1(d,e,a,b,c,i++); + FF1(c,d,e,a,b,i++); + FF1(b,c,d,e,a,i++); + } + + /* round three */ + for (; i < 60; ) { + FF2(a,b,c,d,e,i++); + FF2(e,a,b,c,d,i++); + FF2(d,e,a,b,c,i++); + FF2(c,d,e,a,b,i++); + FF2(b,c,d,e,a,i++); + } + + /* round four */ + for (; i < 80; ) { + FF3(a,b,c,d,e,i++); + FF3(e,a,b,c,d,i++); + FF3(d,e,a,b,c,i++); + FF3(c,d,e,a,b,i++); + FF3(b,c,d,e,a,i++); + } +#endif + + #undef FF0 + #undef FF1 + #undef FF2 + #undef FF3 + + /* store */ + md->sha1.state[0] = md->sha1.state[0] + a; + md->sha1.state[1] = md->sha1.state[1] + b; + md->sha1.state[2] = md->sha1.state[2] + c; + md->sha1.state[3] = md->sha1.state[3] + d; + md->sha1.state[4] = md->sha1.state[4] + e; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_sha1_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_sha1_compress(md, buf); + burn_stack(sizeof(ulong32) * 87); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha1_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->sha1.state[0] = 0x67452301UL; + md->sha1.state[1] = 0xefcdab89UL; + md->sha1.state[2] = 0x98badcfeUL; + md->sha1.state[3] = 0x10325476UL; + md->sha1.state[4] = 0xc3d2e1f0UL; + md->sha1.curlen = 0; + md->sha1.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha1_process, s_sha1_compress, sha1, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (20 bytes) + @return CRYPT_OK if successful +*/ +int sha1_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha1.curlen >= sizeof(md->sha1.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->sha1.length += md->sha1.curlen * 8; + + /* append the '1' bit */ + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha1.curlen > 56) { + while (md->sha1.curlen < 64) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + s_sha1_compress(md, md->sha1.buf); + md->sha1.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sha1.curlen < 56) { + md->sha1.buf[md->sha1.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha1.length, md->sha1.buf+56); + s_sha1_compress(md, md->sha1.buf); + + /* copy output */ + for (i = 0; i < 5; i++) { + STORE32H(md->sha1.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha1_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[20]; + } tests[] = { + { "abc", + { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, + 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, + 0x9c, 0xd0, 0xd8, 0x9d } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, + 0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, + 0xE5, 0x46, 0x70, 0xF1 } + } + }; + + int i; + unsigned char tmp[20]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha1_init(&md); + sha1_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha1_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA1", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/deps/libtomcrypt/src/hashes/sha2/sha224.c b/deps/libtomcrypt/src/hashes/sha2/sha224.c new file mode 100644 index 0000000..1e2f295 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha2/sha224.c @@ -0,0 +1,119 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha224.c + LTC_SHA-224 new NIST standard based off of LTC_SHA-256 truncated to 224 bits (Tom St Denis) +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA224) && defined(LTC_SHA256) + +const struct ltc_hash_descriptor sha224_desc = +{ + "sha224", + 10, + 28, + 64, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 4, }, + 9, + + &sha224_init, + &sha256_process, + &sha224_done, + &sha224_test, + NULL +}; + +/* init the sha256 er... sha224 state ;-) */ +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha224_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha256.curlen = 0; + md->sha256.length = 0; + md->sha256.state[0] = 0xc1059ed8UL; + md->sha256.state[1] = 0x367cd507UL; + md->sha256.state[2] = 0x3070dd17UL; + md->sha256.state[3] = 0xf70e5939UL; + md->sha256.state[4] = 0xffc00b31UL; + md->sha256.state[5] = 0x68581511UL; + md->sha256.state[6] = 0x64f98fa7UL; + md->sha256.state[7] = 0xbefa4fa4UL; + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (28 bytes) + @return CRYPT_OK if successful +*/ +int sha224_done(hash_state * md, unsigned char *out) +{ + unsigned char buf[32]; + int err; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + err = sha256_done(md, buf); + XMEMCPY(out, buf, 28); +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return err; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha224_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[28]; + } tests[] = { + { "abc", + { 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8, + 0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2, + 0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd, + 0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76, + 0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89, + 0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4, + 0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 } + }, + }; + + int i; + unsigned char tmp[28]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha224_init(&md); + sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha224_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA224", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA224) && defined(LTC_SHA256) */ + diff --git a/deps/libtomcrypt/src/hashes/sha2/sha256.c b/deps/libtomcrypt/src/hashes/sha2/sha256.c new file mode 100644 index 0000000..ff20068 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha2/sha256.c @@ -0,0 +1,322 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file sha256.c + LTC_SHA256 by Tom St Denis +*/ + +#ifdef LTC_SHA256 + +const struct ltc_hash_descriptor sha256_desc = +{ + "sha256", + 0, + 32, + 64, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 1, }, + 9, + + &sha256_init, + &sha256_process, + &sha256_done, + &sha256_test, + NULL +}; + +#ifdef LTC_SMALL_CODE +/* the K array */ +static const ulong32 K[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, + 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, + 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, + 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, + 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, + 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, + 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, + 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, + 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, + 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; +#endif + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +#ifdef LTC_CLEAN_STACK +static int ss_sha256_compress(hash_state * md, const unsigned char *buf) +#else +static int s_sha256_compress(hash_state * md, const unsigned char *buf) +#endif +{ + ulong32 S[8], W[64], t0, t1; +#ifdef LTC_SMALL_CODE + ulong32 t; +#endif + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha256.state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 64; ++i) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); + t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } +#else +#define RND(a,b,c,d,e,f,g,h,i,ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); +#endif +#undef RND + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha256.state[i] = md->sha256.state[i] + S[i]; + } + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_sha256_compress(hash_state * md, const unsigned char *buf) +{ + int err; + err = ss_sha256_compress(md, buf); + burn_stack(sizeof(ulong32) * 74); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha256.curlen = 0; + md->sha256.length = 0; + md->sha256.state[0] = 0x6A09E667UL; + md->sha256.state[1] = 0xBB67AE85UL; + md->sha256.state[2] = 0x3C6EF372UL; + md->sha256.state[3] = 0xA54FF53AUL; + md->sha256.state[4] = 0x510E527FUL; + md->sha256.state[5] = 0x9B05688CUL; + md->sha256.state[6] = 0x1F83D9ABUL; + md->sha256.state[7] = 0x5BE0CD19UL; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha256_process,s_sha256_compress, sha256, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +int sha256_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha256.curlen >= sizeof(md->sha256.buf)) { + return CRYPT_INVALID_ARG; + } + + + /* increase the length of the message */ + md->sha256.length += md->sha256.curlen * 8; + + /* append the '1' bit */ + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha256.curlen > 56) { + while (md->sha256.curlen < 64) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + s_sha256_compress(md, md->sha256.buf); + md->sha256.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sha256.curlen < 56) { + md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha256.length, md->sha256.buf+56); + s_sha256_compress(md, md->sha256.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(md->sha256.state[i], out+(4*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha256_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "abc", + { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } + }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } + }, + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha256_init(&md); + sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha256_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA256", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + diff --git a/deps/libtomcrypt/src/hashes/sha2/sha384.c b/deps/libtomcrypt/src/hashes/sha2/sha384.c new file mode 100644 index 0000000..cb3391a --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha2/sha384.c @@ -0,0 +1,124 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha384.c + LTC_SHA384 hash included in sha512.c, Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA384) && defined(LTC_SHA512) + +const struct ltc_hash_descriptor sha384_desc = +{ + "sha384", + 4, + 48, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 2, }, + 9, + + &sha384_init, + &sha512_process, + &sha384_done, + &sha384_test, + NULL +}; + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha384_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8); + md->sha512.state[1] = CONST64(0x629a292a367cd507); + md->sha512.state[2] = CONST64(0x9159015a3070dd17); + md->sha512.state[3] = CONST64(0x152fecd8f70e5939); + md->sha512.state[4] = CONST64(0x67332667ffc00b31); + md->sha512.state[5] = CONST64(0x8eb44a8768581511); + md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7); + md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4); + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (48 bytes) + @return CRYPT_OK if successful +*/ +int sha384_done(hash_state * md, unsigned char *out) +{ + unsigned char buf[64]; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha512.curlen >= sizeof(md->sha512.buf)) { + return CRYPT_INVALID_ARG; + } + + sha512_done(md, buf); + XMEMCPY(out, buf, 48); +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha384_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[48]; + } tests[] = { + { "abc", + { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, + 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07, + 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, + 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, + 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, + 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8, + 0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47, + 0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2, + 0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12, + 0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9, + 0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 } + }, + }; + + int i; + unsigned char tmp[48]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha384_init(&md); + sha384_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha384_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA384", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/deps/libtomcrypt/src/hashes/sha2/sha512.c b/deps/libtomcrypt/src/hashes/sha2/sha512.c new file mode 100644 index 0000000..ef3a8c8 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha2/sha512.c @@ -0,0 +1,303 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @param sha512.c + LTC_SHA512 by Tom St Denis +*/ + +#ifdef LTC_SHA512 + +const struct ltc_hash_descriptor sha512_desc = +{ + "sha512", + 5, + 64, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, + 9, + + &sha512_init, + &sha512_process, + &sha512_done, + &sha512_test, + NULL +}; + +/* the K array */ +static const ulong64 K[80] = { +CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd), +CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc), +CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019), +CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118), +CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe), +CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2), +CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1), +CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694), +CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3), +CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65), +CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483), +CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5), +CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210), +CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4), +CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725), +CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70), +CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926), +CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df), +CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8), +CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b), +CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001), +CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30), +CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910), +CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8), +CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53), +CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8), +CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb), +CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3), +CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60), +CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec), +CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9), +CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b), +CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207), +CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178), +CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6), +CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b), +CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493), +CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c), +CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a), +CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817) +}; + +/* Various logical functions */ +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) ROR64c(x, n) +#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n)) +#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39)) +#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41)) +#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7)) +#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6)) + +/* compress 1024-bits */ +#ifdef LTC_CLEAN_STACK +static int ss_sha512_compress(hash_state * md, const unsigned char *buf) +#else +static int s_sha512_compress(hash_state * md, const unsigned char *buf) +#endif +{ + ulong64 S[8], W[80], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->sha512.state[i]; + } + + /* copy the state into 1024-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD64H(W[i], buf + (8*i)); + } + + /* fill W[16..79] */ + for (i = 16; i < 80; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#ifdef LTC_SMALL_CODE + for (i = 0; i < 80; i++) { + t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i]; + t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]); + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3] + t0; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t0 + t1; + } +#else +#define RND(a,b,c,d,e,f,g,h,i) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + for (i = 0; i < 80; i += 8) { + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7); + } +#endif + + + /* feedback */ + for (i = 0; i < 8; i++) { + md->sha512.state[i] = md->sha512.state[i] + S[i]; + } + + return CRYPT_OK; +} + +/* compress 1024-bits */ +#ifdef LTC_CLEAN_STACK +static int s_sha512_compress(hash_state * md, const unsigned char *buf) +{ + int err; + err = ss_sha512_compress(md, buf); + burn_stack(sizeof(ulong64) * 90 + sizeof(int)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha512_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x6a09e667f3bcc908); + md->sha512.state[1] = CONST64(0xbb67ae8584caa73b); + md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b); + md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1); + md->sha512.state[4] = CONST64(0x510e527fade682d1); + md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f); + md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b); + md->sha512.state[7] = CONST64(0x5be0cd19137e2179); + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sha512_process, s_sha512_compress, sha512, 128) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (64 bytes) + @return CRYPT_OK if successful +*/ +int sha512_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha512.curlen >= sizeof(md->sha512.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->sha512.length += md->sha512.curlen * CONST64(8); + + /* append the '1' bit */ + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 112 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sha512.curlen > 112) { + while (md->sha512.curlen < 128) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + s_sha512_compress(md, md->sha512.buf); + md->sha512.curlen = 0; + } + + /* pad upto 120 bytes of zeroes + * note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash + * > 2^64 bits of data... :-) + */ + while (md->sha512.curlen < 120) { + md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->sha512.length, md->sha512.buf+120); + s_sha512_compress(md, md->sha512.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(md->sha512.state[i], out+(8*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha512_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[64]; + } tests[] = { + { "abc", + { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, + 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31, + 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, + 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, + 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, + 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, + 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, + 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda, + 0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f, + 0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1, + 0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18, + 0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4, + 0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a, + 0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54, + 0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 } + }, + }; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha512_init(&md); + sha512_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha512_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + + + diff --git a/deps/libtomcrypt/src/hashes/sha2/sha512_224.c b/deps/libtomcrypt/src/hashes/sha2/sha512_224.c new file mode 100644 index 0000000..861852e --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha2/sha512_224.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha512_224.c + SHA512/224 hash included in sha512.c +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA512_224) && defined(LTC_SHA512) + +const struct ltc_hash_descriptor sha512_224_desc = +{ + "sha512-224", + 15, + 28, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 5, }, + 9, + + &sha512_224_init, + &sha512_process, + &sha512_224_done, + &sha512_224_test, + NULL +}; + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha512_224_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x8C3D37C819544DA2); + md->sha512.state[1] = CONST64(0x73E1996689DCD4D6); + md->sha512.state[2] = CONST64(0x1DFAB7AE32FF9C82); + md->sha512.state[3] = CONST64(0x679DD514582F9FCF); + md->sha512.state[4] = CONST64(0x0F6D2B697BD44DA8); + md->sha512.state[5] = CONST64(0x77E36F7304C48942); + md->sha512.state[6] = CONST64(0x3F9D85A86A1D36C8); + md->sha512.state[7] = CONST64(0x1112E6AD91D692A1); + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (48 bytes) + @return CRYPT_OK if successful +*/ +int sha512_224_done(hash_state * md, unsigned char *out) +{ + unsigned char buf[64]; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha512.curlen >= sizeof(md->sha512.buf)) { + return CRYPT_INVALID_ARG; + } + + sha512_done(md, buf); + XMEMCPY(out, buf, 28); +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha512_224_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[28]; + } tests[] = { + { "abc", + { 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54, + 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2, + 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4, + 0x3E, 0x89, 0x24, 0xAA } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23, + 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33, + 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72, + 0x68, 0x67, 0x4A, 0xF9 } + }, + }; + + int i; + unsigned char tmp[28]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha512_224_init(&md); + sha512_224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha512_224_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-224", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/deps/libtomcrypt/src/hashes/sha2/sha512_256.c b/deps/libtomcrypt/src/hashes/sha2/sha512_256.c new file mode 100644 index 0000000..1f04154 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha2/sha512_256.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/** + @param sha512_256.c + SHA512/256 hash included in sha512.c +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_SHA512_256) && defined(LTC_SHA512) + +const struct ltc_hash_descriptor sha512_256_desc = +{ + "sha512-256", + 16, + 32, + 128, + + /* OID */ + { 2, 16, 840, 1, 101, 3, 4, 2, 6, }, + 9, + + &sha512_256_init, + &sha512_process, + &sha512_256_done, + &sha512_256_test, + NULL +}; + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sha512_256_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + + md->sha512.curlen = 0; + md->sha512.length = 0; + md->sha512.state[0] = CONST64(0x22312194FC2BF72C); + md->sha512.state[1] = CONST64(0x9F555FA3C84C64C2); + md->sha512.state[2] = CONST64(0x2393B86B6F53B151); + md->sha512.state[3] = CONST64(0x963877195940EABD); + md->sha512.state[4] = CONST64(0x96283EE2A88EFFE3); + md->sha512.state[5] = CONST64(0xBE5E1E2553863992); + md->sha512.state[6] = CONST64(0x2B0199FC2C85B8AA); + md->sha512.state[7] = CONST64(0x0EB72DDC81C52CA2); + return CRYPT_OK; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (48 bytes) + @return CRYPT_OK if successful +*/ +int sha512_256_done(hash_state * md, unsigned char *out) +{ + unsigned char buf[64]; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sha512.curlen >= sizeof(md->sha512.buf)) { + return CRYPT_INVALID_ARG; + } + + sha512_done(md, buf); + XMEMCPY(out, buf, 32); +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sha512_256_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + { "abc", + { 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9, + 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB, + 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46, + 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23 } + }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8, + 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE, + 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14, + 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A } + }, + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + sha512_256_init(&md); + sha512_256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + sha512_256_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SHA512-265", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif /* defined(LTC_SHA384) && defined(LTC_SHA512) */ diff --git a/deps/libtomcrypt/src/hashes/sha3.c b/deps/libtomcrypt/src/hashes/sha3.c new file mode 100644 index 0000000..4758e34 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha3.c @@ -0,0 +1,378 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on https://github.com/brainhub/SHA3IUF (public domain) */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SHA3 + +const struct ltc_hash_descriptor sha3_224_desc = +{ + "sha3-224", /* name of hash */ + 17, /* internal ID */ + 28, /* Size of digest in octets */ + 144, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_224_init, + &sha3_process, + &sha3_done, + &sha3_224_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_256_desc = +{ + "sha3-256", /* name of hash */ + 18, /* internal ID */ + 32, /* Size of digest in octets */ + 136, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_256_init, + &sha3_process, + &sha3_done, + &sha3_256_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_384_desc = +{ + "sha3-384", /* name of hash */ + 19, /* internal ID */ + 48, /* Size of digest in octets */ + 104, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_384_init, + &sha3_process, + &sha3_done, + &sha3_384_test, + NULL +}; + +const struct ltc_hash_descriptor sha3_512_desc = +{ + "sha3-512", /* name of hash */ + 20, /* internal ID */ + 64, /* Size of digest in octets */ + 72, /* Input block size in octets */ + { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */ + 9, /* Length OID */ + &sha3_512_init, + &sha3_process, + &sha3_done, + &sha3_512_test, + NULL +}; +#endif + +#ifdef LTC_KECCAK +const struct ltc_hash_descriptor keccak_224_desc = +{ + "keccak224", /* name of hash */ + 29, /* internal ID */ + 28, /* Size of digest in octets */ + 144, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_224_init, + &sha3_process, + &keccak_done, + &keccak_224_test, + NULL +}; + +const struct ltc_hash_descriptor keccak_256_desc = +{ + "keccak256", /* name of hash */ + 30, /* internal ID */ + 32, /* Size of digest in octets */ + 136, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_256_init, + &sha3_process, + &keccak_done, + &keccak_256_test, + NULL +}; + +const struct ltc_hash_descriptor keccak_384_desc = +{ + "keccak384", /* name of hash */ + 31, /* internal ID */ + 48, /* Size of digest in octets */ + 104, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_384_init, + &sha3_process, + &keccak_done, + &keccak_384_test, + NULL +}; + +const struct ltc_hash_descriptor keccak_512_desc = +{ + "keccak512", /* name of hash */ + 32, /* internal ID */ + 64, /* Size of digest in octets */ + 72, /* Input block size in octets */ + { 0 }, 0, /* no ASN.1 OID */ + &sha3_512_init, + &sha3_process, + &keccak_done, + &keccak_512_test, + NULL +}; +#endif + +#if defined(LTC_SHA3) || defined(LTC_KECCAK) + +#define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */ +#define SHA3_KECCAK_ROUNDS 24 + +static const ulong64 s_keccakf_rndc[24] = { + CONST64(0x0000000000000001), CONST64(0x0000000000008082), + CONST64(0x800000000000808a), CONST64(0x8000000080008000), + CONST64(0x000000000000808b), CONST64(0x0000000080000001), + CONST64(0x8000000080008081), CONST64(0x8000000000008009), + CONST64(0x000000000000008a), CONST64(0x0000000000000088), + CONST64(0x0000000080008009), CONST64(0x000000008000000a), + CONST64(0x000000008000808b), CONST64(0x800000000000008b), + CONST64(0x8000000000008089), CONST64(0x8000000000008003), + CONST64(0x8000000000008002), CONST64(0x8000000000000080), + CONST64(0x000000000000800a), CONST64(0x800000008000000a), + CONST64(0x8000000080008081), CONST64(0x8000000000008080), + CONST64(0x0000000080000001), CONST64(0x8000000080008008) +}; + +static const unsigned s_keccakf_rotc[24] = { + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +}; + +static const unsigned s_keccakf_piln[24] = { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +}; + +static void s_keccakf(ulong64 s[25]) +{ + int i, j, round; + ulong64 t, bc[5]; + + for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) { + /* Theta */ + for(i = 0; i < 5; i++) { + bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; + } + for(i = 0; i < 5; i++) { + t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1); + for(j = 0; j < 25; j += 5) { + s[j + i] ^= t; + } + } + /* Rho Pi */ + t = s[1]; + for(i = 0; i < 24; i++) { + j = s_keccakf_piln[i]; + bc[0] = s[j]; + s[j] = ROL64(t, s_keccakf_rotc[i]); + t = bc[0]; + } + /* Chi */ + for(j = 0; j < 25; j += 5) { + for(i = 0; i < 5; i++) { + bc[i] = s[j + i]; + } + for(i = 0; i < 5; i++) { + s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + } + /* Iota */ + s[0] ^= s_keccakf_rndc[round]; + } +} + +static LTC_INLINE int ss_done(hash_state *md, unsigned char *hash, ulong64 pad) +{ + unsigned i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(hash != NULL); + + md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (pad << (md->sha3.byte_index * 8))); + md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); + s_keccakf(md->sha3.s); + + /* store sha3.s[] as little-endian bytes into sha3.sb */ + for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { + STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); + } + + XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4); + return CRYPT_OK; +} + +/* Public Inteface */ + +int sha3_224_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_256_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_384_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +int sha3_512_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64)); + return CRYPT_OK; +} + +#ifdef LTC_SHA3 +int sha3_shake_init(hash_state *md, int num) +{ + LTC_ARGCHK(md != NULL); + if (num != 128 && num != 256) return CRYPT_INVALID_ARG; + XMEMSET(&md->sha3, 0, sizeof(md->sha3)); + md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64))); + return CRYPT_OK; +} +#endif + +int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen) +{ + /* 0...7 -- how much is needed to have a word */ + unsigned old_tail = (8 - md->sha3.byte_index) & 7; + + unsigned long words; + unsigned tail; + unsigned long i; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(in != NULL); + + if(inlen < old_tail) { /* have no complete word or haven't started the word yet */ + while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); + return CRYPT_OK; + } + + if(old_tail) { /* will have one word to process */ + inlen -= old_tail; + while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); + /* now ready to add saved to the sponge */ + md->sha3.s[md->sha3.word_index] ^= md->sha3.saved; + md->sha3.byte_index = 0; + md->sha3.saved = 0; + if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { + s_keccakf(md->sha3.s); + md->sha3.word_index = 0; + } + } + + /* now work in full words directly from input */ + words = inlen / sizeof(ulong64); + tail = inlen - words * sizeof(ulong64); + + for(i = 0; i < words; i++, in += sizeof(ulong64)) { + ulong64 t; + LOAD64L(t, in); + md->sha3.s[md->sha3.word_index] ^= t; + if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) { + s_keccakf(md->sha3.s); + md->sha3.word_index = 0; + } + } + + /* finally, save the partial word */ + while (tail--) { + md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8); + } + return CRYPT_OK; +} + +#ifdef LTC_SHA3 +int sha3_done(hash_state *md, unsigned char *out) +{ + return ss_done(md, out, CONST64(0x06)); +} +#endif + +#ifdef LTC_KECCAK +int keccak_done(hash_state *md, unsigned char *out) +{ + return ss_done(md, out, CONST64(0x01)); +} +#endif + +#ifdef LTC_SHA3 +int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen) +{ + /* IMPORTANT NOTE: sha3_shake_done can be called many times */ + unsigned long idx; + unsigned i; + + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (!md->sha3.xof_flag) { + /* shake_xof operation must be done only once */ + md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8))); + md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000); + s_keccakf(md->sha3.s); + /* store sha3.s[] as little-endian bytes into sha3.sb */ + for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { + STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); + } + md->sha3.byte_index = 0; + md->sha3.xof_flag = 1; + } + + for (idx = 0; idx < outlen; idx++) { + if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) { + s_keccakf(md->sha3.s); + /* store sha3.s[] as little-endian bytes into sha3.sb */ + for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { + STORE64L(md->sha3.s[i], md->sha3.sb + i * 8); + } + md->sha3.byte_index = 0; + } + out[idx] = md->sha3.sb[md->sha3.byte_index++]; + } + return CRYPT_OK; +} + +int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen) +{ + hash_state md; + int err; + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err; + if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err; + if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err; + return CRYPT_OK; +} +#endif + +#endif diff --git a/deps/libtomcrypt/src/hashes/sha3_test.c b/deps/libtomcrypt/src/hashes/sha3_test.c new file mode 100644 index 0000000..95fcfcb --- /dev/null +++ b/deps/libtomcrypt/src/hashes/sha3_test.c @@ -0,0 +1,719 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* based on https://github.com/brainhub/SHA3IUF (public domain) */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SHA3 + +int sha3_224_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[224 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_224_empty[224 / 8] = { + 0x6b, 0x4e, 0x03, 0x42, 0x36, 0x67, 0xdb, 0xb7, + 0x3b, 0x6e, 0x15, 0x45, 0x4f, 0x0e, 0xb1, 0xab, + 0xd4, 0x59, 0x7f, 0x9a, 0x1b, 0x07, 0x8e, 0x3f, + 0x5b, 0x5a, 0x6b, 0xc7 + }; + + const unsigned char sha3_224_0xa3_200_times[224 / 8] = { + 0x93, 0x76, 0x81, 0x6a, 0xba, 0x50, 0x3f, 0x72, + 0xf9, 0x6c, 0xe7, 0xeb, 0x65, 0xac, 0x09, 0x5d, + 0xee, 0xe3, 0xbe, 0x4b, 0xf9, 0xbb, 0xc2, 0xa1, + 0xcb, 0x7e, 0x11, 0xe0 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-224 on an empty buffer */ + sha3_224_init(&c); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_224_empty, sizeof(sha3_224_empty), "SHA3-224", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-224 in two steps. [FIPS 202] */ + sha3_224_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-224 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_224_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_224_0xa3_200_times, sizeof(sha3_224_0xa3_200_times), "SHA3-224", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[256 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_256_empty[256 / 8] = { + 0xa7, 0xff, 0xc6, 0xf8, 0xbf, 0x1e, 0xd7, 0x66, + 0x51, 0xc1, 0x47, 0x56, 0xa0, 0x61, 0xd6, 0x62, + 0xf5, 0x80, 0xff, 0x4d, 0xe4, 0x3b, 0x49, 0xfa, + 0x82, 0xd8, 0x0a, 0x4b, 0x80, 0xf8, 0x43, 0x4a + }; + const unsigned char sha3_256_0xa3_200_times[256 / 8] = { + 0x79, 0xf3, 0x8a, 0xde, 0xc5, 0xc2, 0x03, 0x07, + 0xa9, 0x8e, 0xf7, 0x6e, 0x83, 0x24, 0xaf, 0xbf, + 0xd4, 0x6c, 0xfd, 0x81, 0xb2, 0x2e, 0x39, 0x73, + 0xc6, 0x5f, 0xa1, 0xbd, 0x9d, 0xe3, 0x17, 0x87 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-256 on an empty buffer */ + sha3_256_init(&c); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_empty, sizeof(sha3_256_empty), "SHA3-256", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 as a single buffer. [FIPS 202] */ + sha3_256_init(&c); + sha3_process(&c, buf, sizeof(buf)); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 in two steps. [FIPS 202] */ + sha3_256_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_256_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_256_0xa3_200_times, sizeof(sha3_256_0xa3_200_times), "SHA3-256", 3)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-256 byte-by-byte: 135 bytes. Input from [Keccak]. Output + * matched with sha3sum. */ + sha3_256_init(&c); + sha3_process(&c, (unsigned char*) + "\xb7\x71\xd5\xce\xf5\xd1\xa4\x1a" + "\x93\xd1\x56\x43\xd7\x18\x1d\x2a" + "\x2e\xf0\xa8\xe8\x4d\x91\x81\x2f" + "\x20\xed\x21\xf1\x47\xbe\xf7\x32" + "\xbf\x3a\x60\xef\x40\x67\xc3\x73" + "\x4b\x85\xbc\x8c\xd4\x71\x78\x0f" + "\x10\xdc\x9e\x82\x91\xb5\x83\x39" + "\xa6\x77\xb9\x60\x21\x8f\x71\xe7" + "\x93\xf2\x79\x7a\xea\x34\x94\x06" + "\x51\x28\x29\x06\x5d\x37\xbb\x55" + "\xea\x79\x6f\xa4\xf5\x6f\xd8\x89" + "\x6b\x49\xb2\xcd\x19\xb4\x32\x15" + "\xad\x96\x7c\x71\x2b\x24\xe5\x03" + "\x2d\x06\x52\x32\xe0\x2c\x12\x74" + "\x09\xd2\xed\x41\x46\xb9\xd7\x5d" + "\x76\x3d\x52\xdb\x98\xd9\x49\xd3" + "\xb0\xfe\xd6\xa8\x05\x2f\xbb", 1080 / 8); + sha3_done(&c, hash); + if(compare_testvector(hash, sizeof(hash), + "\xa1\x9e\xee\x92\xbb\x20\x97\xb6" + "\x4e\x82\x3d\x59\x77\x98\xaa\x18" + "\xbe\x9b\x7c\x73\x6b\x80\x59\xab" + "\xfd\x67\x79\xac\x35\xac\x81\xb5", 256 / 8, "SHA3-256", 4)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_384_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[384 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_384_0xa3_200_times[384 / 8] = { + 0x18, 0x81, 0xde, 0x2c, 0xa7, 0xe4, 0x1e, 0xf9, + 0x5d, 0xc4, 0x73, 0x2b, 0x8f, 0x5f, 0x00, 0x2b, + 0x18, 0x9c, 0xc1, 0xe4, 0x2b, 0x74, 0x16, 0x8e, + 0xd1, 0x73, 0x26, 0x49, 0xce, 0x1d, 0xbc, 0xdd, + 0x76, 0x19, 0x7a, 0x31, 0xfd, 0x55, 0xee, 0x98, + 0x9f, 0x2d, 0x70, 0x50, 0xdd, 0x47, 0x3e, 0x8f + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-384 as a single buffer. [FIPS 202] */ + sha3_384_init(&c); + sha3_process(&c, buf, sizeof(buf)); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-384 in two steps. [FIPS 202] */ + sha3_384_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-384 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_384_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_384_0xa3_200_times, sizeof(sha3_384_0xa3_200_times), "SHA3-384", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_512_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[512 / 8]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + + const unsigned char sha3_512_0xa3_200_times[512 / 8] = { + 0xe7, 0x6d, 0xfa, 0xd2, 0x20, 0x84, 0xa8, 0xb1, + 0x46, 0x7f, 0xcf, 0x2f, 0xfa, 0x58, 0x36, 0x1b, + 0xec, 0x76, 0x28, 0xed, 0xf5, 0xf3, 0xfd, 0xc0, + 0xe4, 0x80, 0x5d, 0xc4, 0x8c, 0xae, 0xec, 0xa8, + 0x1b, 0x7c, 0x13, 0xc3, 0x0a, 0xdf, 0x52, 0xa3, + 0x65, 0x95, 0x84, 0x73, 0x9a, 0x2d, 0xf4, 0x6b, + 0xe5, 0x89, 0xc5, 0x1c, 0xa1, 0xa4, 0xa8, 0x41, + 0x6d, 0xf6, 0x54, 0x5a, 0x1c, 0xe8, 0xba, 0x00 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHA3-512 as a single buffer. [FIPS 202] */ + sha3_512_init(&c); + sha3_process(&c, buf, sizeof(buf)); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-512 in two steps. [FIPS 202] */ + sha3_512_init(&c); + sha3_process(&c, buf, sizeof(buf) / 2); + sha3_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHA3-512 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_512_init(&c); + while (i--) { + sha3_process(&c, &c1, 1); + } + sha3_done(&c, hash); + if (compare_testvector(hash, sizeof(hash), sha3_512_0xa3_200_times, sizeof(sha3_512_0xa3_200_times), "SHA3-512", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int sha3_shake_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char buf[200], hash[512]; + int i; + hash_state c; + const unsigned char c1 = 0xa3; + unsigned long len; + + const unsigned char shake256_empty[32] = { + 0xab, 0x0b, 0xae, 0x31, 0x63, 0x39, 0x89, 0x43, + 0x04, 0xe3, 0x58, 0x77, 0xb0, 0xc2, 0x8a, 0x9b, + 0x1f, 0xd1, 0x66, 0xc7, 0x96, 0xb9, 0xcc, 0x25, + 0x8a, 0x06, 0x4a, 0x8f, 0x57, 0xe2, 0x7f, 0x2a + }; + const unsigned char shake256_0xa3_200_times[32] = { + 0x6a, 0x1a, 0x9d, 0x78, 0x46, 0x43, 0x6e, 0x4d, + 0xca, 0x57, 0x28, 0xb6, 0xf7, 0x60, 0xee, 0xf0, + 0xca, 0x92, 0xbf, 0x0b, 0xe5, 0x61, 0x5e, 0x96, + 0x95, 0x9d, 0x76, 0x71, 0x97, 0xa0, 0xbe, 0xeb + }; + const unsigned char shake128_empty[32] = { + 0x43, 0xe4, 0x1b, 0x45, 0xa6, 0x53, 0xf2, 0xa5, + 0xc4, 0x49, 0x2c, 0x1a, 0xdd, 0x54, 0x45, 0x12, + 0xdd, 0xa2, 0x52, 0x98, 0x33, 0x46, 0x2b, 0x71, + 0xa4, 0x1a, 0x45, 0xbe, 0x97, 0x29, 0x0b, 0x6f + }; + const unsigned char shake128_0xa3_200_times[32] = { + 0x44, 0xc9, 0xfb, 0x35, 0x9f, 0xd5, 0x6a, 0xc0, + 0xa9, 0xa7, 0x5a, 0x74, 0x3c, 0xff, 0x68, 0x62, + 0xf1, 0x7d, 0x72, 0x59, 0xab, 0x07, 0x52, 0x16, + 0xc0, 0x69, 0x95, 0x11, 0x64, 0x3b, 0x64, 0x39 + }; + + XMEMSET(buf, c1, sizeof(buf)); + + /* SHAKE256 on an empty buffer */ + sha3_shake_init(&c, 256); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_empty), shake256_empty, sizeof(shake256_empty), "SHAKE256", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 via sha3_shake_memory [FIPS 202] */ + len = 512; + sha3_shake_memory(256, buf, sizeof(buf), hash, &len); + if (compare_testvector(hash + 480, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 as a single buffer. [FIPS 202] */ + sha3_shake_init(&c, 256); + sha3_shake_process(&c, buf, sizeof(buf)); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 in two steps. [FIPS 202] */ + sha3_shake_init(&c, 256); + sha3_shake_process(&c, buf, sizeof(buf) / 2); + sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 3)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE256 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_shake_init(&c, 256); + while (i--) sha3_shake_process(&c, &c1, 1); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake256_0xa3_200_times), shake256_0xa3_200_times, sizeof(shake256_0xa3_200_times), "SHAKE256", 4)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 on an empty buffer */ + sha3_shake_init(&c, 128); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_empty), shake128_empty, sizeof(shake128_empty), "SHAKE128", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 via sha3_shake_memory [FIPS 202] */ + len = 512; + sha3_shake_memory(128, buf, sizeof(buf), hash, &len); + if (compare_testvector(hash + 480, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 1)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 as a single buffer. [FIPS 202] */ + sha3_shake_init(&c, 128); + sha3_shake_process(&c, buf, sizeof(buf)); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 2)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 in two steps. [FIPS 202] */ + sha3_shake_init(&c, 128); + sha3_shake_process(&c, buf, sizeof(buf) / 2); + sha3_shake_process(&c, buf + sizeof(buf) / 2, sizeof(buf) / 2); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 3)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* SHAKE128 byte-by-byte: 200 steps. [FIPS 202] */ + i = 200; + sha3_shake_init(&c, 128); + while (i--) sha3_shake_process(&c, &c1, 1); + for (i = 0; i < 16; i++) sha3_shake_done(&c, hash, 32); /* get 512 bytes, keep in hash the last 32 */ + if (compare_testvector(hash, sizeof(shake128_0xa3_200_times), shake128_0xa3_200_times, sizeof(shake128_0xa3_200_times), "SHAKE128", 4)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif + +#ifdef LTC_KECCAK + +int keccak_224_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\xa9\xca\xb5\x9e\xb4\x0a\x10\xb2" + "\x46\x29\x0f\x2d\x60\x86\xe3\x2e" + "\x36\x89\xfa\xf1\xd2\x6b\x47\x0c" + "\x89\x9f\x28\x02", 28, + "KECCAK-224", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\x61\x5b\xa3\x67\xaf\xdc\x35\xaa" + "\xc3\x97\xbc\x7e\xb5\xd5\x8d\x10" + "\x6a\x73\x4b\x24\x98\x6d\x5d\x97" + "\x8f\xef\xd6\x2c", 28, + "KECCAK-224", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\x56\x79\xcd\x50\x9c\x51\x20\xaf" + "\x54\x79\x5c\xf4\x77\x14\x96\x41" + "\xcf\x27\xb2\xeb\xb6\xa5\xf9\x03" + "\x40\x70\x4e\x57", 28, + "KECCAK-224", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_224_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 28, + "\x62\xb1\x0f\x1b\x62\x36\xeb\xc2" + "\xda\x72\x95\x77\x42\xa8\xd4\xe4" + "\x8e\x21\x3b\x5f\x89\x34\x60\x4b" + "\xfd\x4d\x2c\x3a", 28, + "KECCAK-224", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int keccak_256_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\xee\xad\x6d\xbf\xc7\x34\x0a\x56" + "\xca\xed\xc0\x44\x69\x6a\x16\x88" + "\x70\x54\x9a\x6a\x7f\x6f\x56\x96" + "\x1e\x84\xa5\x4b\xd9\x97\x0b\x8a", 32, + "KECCAK-256", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\xa8\xea\xce\xda\x4d\x47\xb3\x28" + "\x1a\x79\x5a\xd9\xe1\xea\x21\x22" + "\xb4\x07\xba\xf9\xaa\xbc\xb9\xe1" + "\x8b\x57\x17\xb7\x87\x35\x37\xd2", 32, + "KECCAK-256", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\x0e\x32\xde\xfa\x20\x71\xf0\xb5" + "\xac\x0e\x6a\x10\x8b\x84\x2e\xd0" + "\xf1\xd3\x24\x97\x12\xf5\x8e\xe0" + "\xdd\xf9\x56\xfe\x33\x2a\x5f\x95", 32, + "KECCAK-256", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_256_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 32, + "\xce\x87\xa5\x17\x3b\xff\xd9\x23" + "\x99\x22\x16\x58\xf8\x01\xd4\x5c" + "\x29\x4d\x90\x06\xee\x9f\x3f\x9d" + "\x41\x9c\x8d\x42\x77\x48\xdc\x41", 32, + "KECCAK-256", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int keccak_384_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x1b\x84\xe6\x2a\x46\xe5\xa2\x01" + "\x86\x17\x54\xaf\x5d\xc9\x5c\x4a" + "\x1a\x69\xca\xf4\xa7\x96\xae\x40" + "\x56\x80\x16\x1e\x29\x57\x26\x41" + "\xf5\xfa\x1e\x86\x41\xd7\x95\x83" + "\x36\xee\x7b\x11\xc5\x8f\x73\xe9", 48, + "KECCAK-384", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x49\x5c\xce\x27\x14\xcd\x72\xc8" + "\xc5\x3c\x33\x63\xd2\x2c\x58\xb5" + "\x59\x60\xfe\x26\xbe\x0b\xf3\xbb" + "\xc7\xa3\x31\x6d\xd5\x63\xad\x1d" + "\xb8\x41\x0e\x75\xee\xfe\xa6\x55" + "\xe3\x9d\x46\x70\xec\x0b\x17\x92", 48, + "KECCAK-384", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x18\x42\x2a\xc1\xd3\xa1\xe5\x4b" + "\xad\x87\x68\x83\xd2\xd6\xdd\x65" + "\xf6\x5c\x1d\x5f\x33\xa7\x12\x5c" + "\xc4\xc1\x86\x40\x5a\x12\xed\x64" + "\xba\x96\x67\x2e\xed\xda\x8c\x5a" + "\x63\x31\xd2\x86\x83\xf4\x88\xeb", 48, + "KECCAK-384", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_384_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 48, + "\x13\x51\x14\x50\x8d\xd6\x3e\x27" + "\x9e\x70\x9c\x26\xf7\x81\x7c\x04" + "\x82\x76\x6c\xde\x49\x13\x2e\x3e" + "\xdf\x2e\xed\xd8\x99\x6f\x4e\x35" + "\x96\xd1\x84\x10\x0b\x38\x48\x68" + "\x24\x9f\x1d\x8b\x8f\xda\xa2\xc9", 48, + "KECCAK-384", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +int keccak_512_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + hash_state c; + unsigned char hash[MAXBLOCKSIZE]; + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*) "\xcc", 1); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x86\x30\xc1\x3c\xbd\x06\x6e\xa7" + "\x4b\xbe\x7f\xe4\x68\xfe\xc1\xde" + "\xe1\x0e\xdc\x12\x54\xfb\x4c\x1b" + "\x7c\x5f\xd6\x9b\x64\x6e\x44\x16" + "\x0b\x8c\xe0\x1d\x05\xa0\x90\x8c" + "\xa7\x90\xdf\xb0\x80\xf4\xb5\x13" + "\xbc\x3b\x62\x25\xec\xe7\xa8\x10" + "\x37\x14\x41\xa5\xac\x66\x6e\xb9", 64, + "KECCAK-512", 0) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*)"\x41\xfb", 2); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x55\x1d\xa6\x23\x6f\x8b\x96\xfc" + "\xe9\xf9\x7f\x11\x90\xe9\x01\x32" + "\x4f\x0b\x45\xe0\x6d\xbb\xb5\xcd" + "\xb8\x35\x5d\x6e\xd1\xdc\x34\xb3" + "\xf0\xea\xe7\xdc\xb6\x86\x22\xff" + "\x23\x2f\xa3\xce\xce\x0d\x46\x16" + "\xcd\xeb\x39\x31\xf9\x38\x03\x66" + "\x2a\x28\xdf\x1c\xd5\x35\xb7\x31", 64, + "KECCAK-512", 1) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*) + "\x52\xa6\x08\xab\x21\xcc\xdd\x8a" + "\x44\x57\xa5\x7e\xde\x78\x21\x76", 16); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x4b\x39\xd3\xda\x5b\xcd\xf4\xd9" + "\xb7\x69\x01\x59\x95\x64\x43\x11" + "\xc1\x4c\x43\x5b\xf7\x2b\x10\x09" + "\xd6\xdd\x71\xb0\x1a\x63\xb9\x7c" + "\xfb\x59\x64\x18\xe8\xe4\x23\x42" + "\xd1\x17\xe0\x74\x71\xa8\x91\x43" + "\x14\xba\x7b\x0e\x26\x4d\xad\xf0" + "\xce\xa3\x81\x86\x8c\xbd\x43\xd1", 64, + "KECCAK-512", 2) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + keccak_512_init(&c); + keccak_process(&c, (unsigned char*) + "\x43\x3c\x53\x03\x13\x16\x24\xc0" + "\x02\x1d\x86\x8a\x30\x82\x54\x75" + "\xe8\xd0\xbd\x30\x52\xa0\x22\x18" + "\x03\x98\xf4\xca\x44\x23\xb9\x82" + "\x14\xb6\xbe\xaa\xc2\x1c\x88\x07" + "\xa2\xc3\x3f\x8c\x93\xbd\x42\xb0" + "\x92\xcc\x1b\x06\xce\xdf\x32\x24" + "\xd5\xed\x1e\xc2\x97\x84\x44\x4f" + "\x22\xe0\x8a\x55\xaa\x58\x54\x2b" + "\x52\x4b\x02\xcd\x3d\x5d\x5f\x69" + "\x07\xaf\xe7\x1c\x5d\x74\x62\x22" + "\x4a\x3f\x9d\x9e\x53\xe7\xe0\x84" + "\x6d\xcb\xb4\xce", 100); + keccak_done(&c, hash); + if(compare_testvector(hash, 64, + "\x52\x7d\x28\xe3\x41\xe6\xb1\x4f" + "\x46\x84\xad\xb4\xb8\x24\xc4\x96" + "\xc6\x48\x2e\x51\x14\x95\x65\xd3" + "\xd1\x72\x26\x82\x88\x84\x30\x6b" + "\x51\xd6\x14\x8a\x72\x62\x2c\x2b" + "\x75\xf5\xd3\x51\x0b\x79\x9d\x8b" + "\xdc\x03\xea\xed\xe4\x53\x67\x6a" + "\x6e\xc8\xfe\x03\xa1\xad\x0e\xab", 64, + "KECCAK-512", 3) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/hashes/tiger.c b/deps/libtomcrypt/src/hashes/tiger.c new file mode 100644 index 0000000..8ca2d54 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/tiger.c @@ -0,0 +1,796 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file tiger.c + Tiger hash function, Tom St Denis +*/ + +#ifdef LTC_TIGER + +const struct ltc_hash_descriptor tiger_desc = +{ + "tiger", + 1, + 24, + 64, + + /* OID */ + { 1, 3, 6, 1, 4, 1, 11591, 12, 2, }, + 9, + + &tiger_init, + &tiger_process, + &tiger_done, + &tiger_test, + NULL +}; + +#define t1 (table) +#define t2 (table+256) +#define t3 (table+256*2) +#define t4 (table+256*3) + +static const ulong64 table[4*256] = { + CONST64(0x02AAB17CF7E90C5E) /* 0 */, CONST64(0xAC424B03E243A8EC) /* 1 */, + CONST64(0x72CD5BE30DD5FCD3) /* 2 */, CONST64(0x6D019B93F6F97F3A) /* 3 */, + CONST64(0xCD9978FFD21F9193) /* 4 */, CONST64(0x7573A1C9708029E2) /* 5 */, + CONST64(0xB164326B922A83C3) /* 6 */, CONST64(0x46883EEE04915870) /* 7 */, + CONST64(0xEAACE3057103ECE6) /* 8 */, CONST64(0xC54169B808A3535C) /* 9 */, + CONST64(0x4CE754918DDEC47C) /* 10 */, CONST64(0x0AA2F4DFDC0DF40C) /* 11 */, + CONST64(0x10B76F18A74DBEFA) /* 12 */, CONST64(0xC6CCB6235AD1AB6A) /* 13 */, + CONST64(0x13726121572FE2FF) /* 14 */, CONST64(0x1A488C6F199D921E) /* 15 */, + CONST64(0x4BC9F9F4DA0007CA) /* 16 */, CONST64(0x26F5E6F6E85241C7) /* 17 */, + CONST64(0x859079DBEA5947B6) /* 18 */, CONST64(0x4F1885C5C99E8C92) /* 19 */, + CONST64(0xD78E761EA96F864B) /* 20 */, CONST64(0x8E36428C52B5C17D) /* 21 */, + CONST64(0x69CF6827373063C1) /* 22 */, CONST64(0xB607C93D9BB4C56E) /* 23 */, + CONST64(0x7D820E760E76B5EA) /* 24 */, CONST64(0x645C9CC6F07FDC42) /* 25 */, + CONST64(0xBF38A078243342E0) /* 26 */, CONST64(0x5F6B343C9D2E7D04) /* 27 */, + CONST64(0xF2C28AEB600B0EC6) /* 28 */, CONST64(0x6C0ED85F7254BCAC) /* 29 */, + CONST64(0x71592281A4DB4FE5) /* 30 */, CONST64(0x1967FA69CE0FED9F) /* 31 */, + CONST64(0xFD5293F8B96545DB) /* 32 */, CONST64(0xC879E9D7F2A7600B) /* 33 */, + CONST64(0x860248920193194E) /* 34 */, CONST64(0xA4F9533B2D9CC0B3) /* 35 */, + CONST64(0x9053836C15957613) /* 36 */, CONST64(0xDB6DCF8AFC357BF1) /* 37 */, + CONST64(0x18BEEA7A7A370F57) /* 38 */, CONST64(0x037117CA50B99066) /* 39 */, + CONST64(0x6AB30A9774424A35) /* 40 */, CONST64(0xF4E92F02E325249B) /* 41 */, + CONST64(0x7739DB07061CCAE1) /* 42 */, CONST64(0xD8F3B49CECA42A05) /* 43 */, + CONST64(0xBD56BE3F51382F73) /* 44 */, CONST64(0x45FAED5843B0BB28) /* 45 */, + CONST64(0x1C813D5C11BF1F83) /* 46 */, CONST64(0x8AF0E4B6D75FA169) /* 47 */, + CONST64(0x33EE18A487AD9999) /* 48 */, CONST64(0x3C26E8EAB1C94410) /* 49 */, + CONST64(0xB510102BC0A822F9) /* 50 */, CONST64(0x141EEF310CE6123B) /* 51 */, + CONST64(0xFC65B90059DDB154) /* 52 */, CONST64(0xE0158640C5E0E607) /* 53 */, + CONST64(0x884E079826C3A3CF) /* 54 */, CONST64(0x930D0D9523C535FD) /* 55 */, + CONST64(0x35638D754E9A2B00) /* 56 */, CONST64(0x4085FCCF40469DD5) /* 57 */, + CONST64(0xC4B17AD28BE23A4C) /* 58 */, CONST64(0xCAB2F0FC6A3E6A2E) /* 59 */, + CONST64(0x2860971A6B943FCD) /* 60 */, CONST64(0x3DDE6EE212E30446) /* 61 */, + CONST64(0x6222F32AE01765AE) /* 62 */, CONST64(0x5D550BB5478308FE) /* 63 */, + CONST64(0xA9EFA98DA0EDA22A) /* 64 */, CONST64(0xC351A71686C40DA7) /* 65 */, + CONST64(0x1105586D9C867C84) /* 66 */, CONST64(0xDCFFEE85FDA22853) /* 67 */, + CONST64(0xCCFBD0262C5EEF76) /* 68 */, CONST64(0xBAF294CB8990D201) /* 69 */, + CONST64(0xE69464F52AFAD975) /* 70 */, CONST64(0x94B013AFDF133E14) /* 71 */, + CONST64(0x06A7D1A32823C958) /* 72 */, CONST64(0x6F95FE5130F61119) /* 73 */, + CONST64(0xD92AB34E462C06C0) /* 74 */, CONST64(0xED7BDE33887C71D2) /* 75 */, + CONST64(0x79746D6E6518393E) /* 76 */, CONST64(0x5BA419385D713329) /* 77 */, + CONST64(0x7C1BA6B948A97564) /* 78 */, CONST64(0x31987C197BFDAC67) /* 79 */, + CONST64(0xDE6C23C44B053D02) /* 80 */, CONST64(0x581C49FED002D64D) /* 81 */, + CONST64(0xDD474D6338261571) /* 82 */, CONST64(0xAA4546C3E473D062) /* 83 */, + CONST64(0x928FCE349455F860) /* 84 */, CONST64(0x48161BBACAAB94D9) /* 85 */, + CONST64(0x63912430770E6F68) /* 86 */, CONST64(0x6EC8A5E602C6641C) /* 87 */, + CONST64(0x87282515337DDD2B) /* 88 */, CONST64(0x2CDA6B42034B701B) /* 89 */, + CONST64(0xB03D37C181CB096D) /* 90 */, CONST64(0xE108438266C71C6F) /* 91 */, + CONST64(0x2B3180C7EB51B255) /* 92 */, CONST64(0xDF92B82F96C08BBC) /* 93 */, + CONST64(0x5C68C8C0A632F3BA) /* 94 */, CONST64(0x5504CC861C3D0556) /* 95 */, + CONST64(0xABBFA4E55FB26B8F) /* 96 */, CONST64(0x41848B0AB3BACEB4) /* 97 */, + CONST64(0xB334A273AA445D32) /* 98 */, CONST64(0xBCA696F0A85AD881) /* 99 */, + CONST64(0x24F6EC65B528D56C) /* 100 */, CONST64(0x0CE1512E90F4524A) /* 101 */, + CONST64(0x4E9DD79D5506D35A) /* 102 */, CONST64(0x258905FAC6CE9779) /* 103 */, + CONST64(0x2019295B3E109B33) /* 104 */, CONST64(0xF8A9478B73A054CC) /* 105 */, + CONST64(0x2924F2F934417EB0) /* 106 */, CONST64(0x3993357D536D1BC4) /* 107 */, + CONST64(0x38A81AC21DB6FF8B) /* 108 */, CONST64(0x47C4FBF17D6016BF) /* 109 */, + CONST64(0x1E0FAADD7667E3F5) /* 110 */, CONST64(0x7ABCFF62938BEB96) /* 111 */, + CONST64(0xA78DAD948FC179C9) /* 112 */, CONST64(0x8F1F98B72911E50D) /* 113 */, + CONST64(0x61E48EAE27121A91) /* 114 */, CONST64(0x4D62F7AD31859808) /* 115 */, + CONST64(0xECEBA345EF5CEAEB) /* 116 */, CONST64(0xF5CEB25EBC9684CE) /* 117 */, + CONST64(0xF633E20CB7F76221) /* 118 */, CONST64(0xA32CDF06AB8293E4) /* 119 */, + CONST64(0x985A202CA5EE2CA4) /* 120 */, CONST64(0xCF0B8447CC8A8FB1) /* 121 */, + CONST64(0x9F765244979859A3) /* 122 */, CONST64(0xA8D516B1A1240017) /* 123 */, + CONST64(0x0BD7BA3EBB5DC726) /* 124 */, CONST64(0xE54BCA55B86ADB39) /* 125 */, + CONST64(0x1D7A3AFD6C478063) /* 126 */, CONST64(0x519EC608E7669EDD) /* 127 */, + CONST64(0x0E5715A2D149AA23) /* 128 */, CONST64(0x177D4571848FF194) /* 129 */, + CONST64(0xEEB55F3241014C22) /* 130 */, CONST64(0x0F5E5CA13A6E2EC2) /* 131 */, + CONST64(0x8029927B75F5C361) /* 132 */, CONST64(0xAD139FABC3D6E436) /* 133 */, + CONST64(0x0D5DF1A94CCF402F) /* 134 */, CONST64(0x3E8BD948BEA5DFC8) /* 135 */, + CONST64(0xA5A0D357BD3FF77E) /* 136 */, CONST64(0xA2D12E251F74F645) /* 137 */, + CONST64(0x66FD9E525E81A082) /* 138 */, CONST64(0x2E0C90CE7F687A49) /* 139 */, + CONST64(0xC2E8BCBEBA973BC5) /* 140 */, CONST64(0x000001BCE509745F) /* 141 */, + CONST64(0x423777BBE6DAB3D6) /* 142 */, CONST64(0xD1661C7EAEF06EB5) /* 143 */, + CONST64(0xA1781F354DAACFD8) /* 144 */, CONST64(0x2D11284A2B16AFFC) /* 145 */, + CONST64(0xF1FC4F67FA891D1F) /* 146 */, CONST64(0x73ECC25DCB920ADA) /* 147 */, + CONST64(0xAE610C22C2A12651) /* 148 */, CONST64(0x96E0A810D356B78A) /* 149 */, + CONST64(0x5A9A381F2FE7870F) /* 150 */, CONST64(0xD5AD62EDE94E5530) /* 151 */, + CONST64(0xD225E5E8368D1427) /* 152 */, CONST64(0x65977B70C7AF4631) /* 153 */, + CONST64(0x99F889B2DE39D74F) /* 154 */, CONST64(0x233F30BF54E1D143) /* 155 */, + CONST64(0x9A9675D3D9A63C97) /* 156 */, CONST64(0x5470554FF334F9A8) /* 157 */, + CONST64(0x166ACB744A4F5688) /* 158 */, CONST64(0x70C74CAAB2E4AEAD) /* 159 */, + CONST64(0xF0D091646F294D12) /* 160 */, CONST64(0x57B82A89684031D1) /* 161 */, + CONST64(0xEFD95A5A61BE0B6B) /* 162 */, CONST64(0x2FBD12E969F2F29A) /* 163 */, + CONST64(0x9BD37013FEFF9FE8) /* 164 */, CONST64(0x3F9B0404D6085A06) /* 165 */, + CONST64(0x4940C1F3166CFE15) /* 166 */, CONST64(0x09542C4DCDF3DEFB) /* 167 */, + CONST64(0xB4C5218385CD5CE3) /* 168 */, CONST64(0xC935B7DC4462A641) /* 169 */, + CONST64(0x3417F8A68ED3B63F) /* 170 */, CONST64(0xB80959295B215B40) /* 171 */, + CONST64(0xF99CDAEF3B8C8572) /* 172 */, CONST64(0x018C0614F8FCB95D) /* 173 */, + CONST64(0x1B14ACCD1A3ACDF3) /* 174 */, CONST64(0x84D471F200BB732D) /* 175 */, + CONST64(0xC1A3110E95E8DA16) /* 176 */, CONST64(0x430A7220BF1A82B8) /* 177 */, + CONST64(0xB77E090D39DF210E) /* 178 */, CONST64(0x5EF4BD9F3CD05E9D) /* 179 */, + CONST64(0x9D4FF6DA7E57A444) /* 180 */, CONST64(0xDA1D60E183D4A5F8) /* 181 */, + CONST64(0xB287C38417998E47) /* 182 */, CONST64(0xFE3EDC121BB31886) /* 183 */, + CONST64(0xC7FE3CCC980CCBEF) /* 184 */, CONST64(0xE46FB590189BFD03) /* 185 */, + CONST64(0x3732FD469A4C57DC) /* 186 */, CONST64(0x7EF700A07CF1AD65) /* 187 */, + CONST64(0x59C64468A31D8859) /* 188 */, CONST64(0x762FB0B4D45B61F6) /* 189 */, + CONST64(0x155BAED099047718) /* 190 */, CONST64(0x68755E4C3D50BAA6) /* 191 */, + CONST64(0xE9214E7F22D8B4DF) /* 192 */, CONST64(0x2ADDBF532EAC95F4) /* 193 */, + CONST64(0x32AE3909B4BD0109) /* 194 */, CONST64(0x834DF537B08E3450) /* 195 */, + CONST64(0xFA209DA84220728D) /* 196 */, CONST64(0x9E691D9B9EFE23F7) /* 197 */, + CONST64(0x0446D288C4AE8D7F) /* 198 */, CONST64(0x7B4CC524E169785B) /* 199 */, + CONST64(0x21D87F0135CA1385) /* 200 */, CONST64(0xCEBB400F137B8AA5) /* 201 */, + CONST64(0x272E2B66580796BE) /* 202 */, CONST64(0x3612264125C2B0DE) /* 203 */, + CONST64(0x057702BDAD1EFBB2) /* 204 */, CONST64(0xD4BABB8EACF84BE9) /* 205 */, + CONST64(0x91583139641BC67B) /* 206 */, CONST64(0x8BDC2DE08036E024) /* 207 */, + CONST64(0x603C8156F49F68ED) /* 208 */, CONST64(0xF7D236F7DBEF5111) /* 209 */, + CONST64(0x9727C4598AD21E80) /* 210 */, CONST64(0xA08A0896670A5FD7) /* 211 */, + CONST64(0xCB4A8F4309EBA9CB) /* 212 */, CONST64(0x81AF564B0F7036A1) /* 213 */, + CONST64(0xC0B99AA778199ABD) /* 214 */, CONST64(0x959F1EC83FC8E952) /* 215 */, + CONST64(0x8C505077794A81B9) /* 216 */, CONST64(0x3ACAAF8F056338F0) /* 217 */, + CONST64(0x07B43F50627A6778) /* 218 */, CONST64(0x4A44AB49F5ECCC77) /* 219 */, + CONST64(0x3BC3D6E4B679EE98) /* 220 */, CONST64(0x9CC0D4D1CF14108C) /* 221 */, + CONST64(0x4406C00B206BC8A0) /* 222 */, CONST64(0x82A18854C8D72D89) /* 223 */, + CONST64(0x67E366B35C3C432C) /* 224 */, CONST64(0xB923DD61102B37F2) /* 225 */, + CONST64(0x56AB2779D884271D) /* 226 */, CONST64(0xBE83E1B0FF1525AF) /* 227 */, + CONST64(0xFB7C65D4217E49A9) /* 228 */, CONST64(0x6BDBE0E76D48E7D4) /* 229 */, + CONST64(0x08DF828745D9179E) /* 230 */, CONST64(0x22EA6A9ADD53BD34) /* 231 */, + CONST64(0xE36E141C5622200A) /* 232 */, CONST64(0x7F805D1B8CB750EE) /* 233 */, + CONST64(0xAFE5C7A59F58E837) /* 234 */, CONST64(0xE27F996A4FB1C23C) /* 235 */, + CONST64(0xD3867DFB0775F0D0) /* 236 */, CONST64(0xD0E673DE6E88891A) /* 237 */, + CONST64(0x123AEB9EAFB86C25) /* 238 */, CONST64(0x30F1D5D5C145B895) /* 239 */, + CONST64(0xBB434A2DEE7269E7) /* 240 */, CONST64(0x78CB67ECF931FA38) /* 241 */, + CONST64(0xF33B0372323BBF9C) /* 242 */, CONST64(0x52D66336FB279C74) /* 243 */, + CONST64(0x505F33AC0AFB4EAA) /* 244 */, CONST64(0xE8A5CD99A2CCE187) /* 245 */, + CONST64(0x534974801E2D30BB) /* 246 */, CONST64(0x8D2D5711D5876D90) /* 247 */, + CONST64(0x1F1A412891BC038E) /* 248 */, CONST64(0xD6E2E71D82E56648) /* 249 */, + CONST64(0x74036C3A497732B7) /* 250 */, CONST64(0x89B67ED96361F5AB) /* 251 */, + CONST64(0xFFED95D8F1EA02A2) /* 252 */, CONST64(0xE72B3BD61464D43D) /* 253 */, + CONST64(0xA6300F170BDC4820) /* 254 */, CONST64(0xEBC18760ED78A77A) /* 255 */, + CONST64(0xE6A6BE5A05A12138) /* 256 */, CONST64(0xB5A122A5B4F87C98) /* 257 */, + CONST64(0x563C6089140B6990) /* 258 */, CONST64(0x4C46CB2E391F5DD5) /* 259 */, + CONST64(0xD932ADDBC9B79434) /* 260 */, CONST64(0x08EA70E42015AFF5) /* 261 */, + CONST64(0xD765A6673E478CF1) /* 262 */, CONST64(0xC4FB757EAB278D99) /* 263 */, + CONST64(0xDF11C6862D6E0692) /* 264 */, CONST64(0xDDEB84F10D7F3B16) /* 265 */, + CONST64(0x6F2EF604A665EA04) /* 266 */, CONST64(0x4A8E0F0FF0E0DFB3) /* 267 */, + CONST64(0xA5EDEEF83DBCBA51) /* 268 */, CONST64(0xFC4F0A2A0EA4371E) /* 269 */, + CONST64(0xE83E1DA85CB38429) /* 270 */, CONST64(0xDC8FF882BA1B1CE2) /* 271 */, + CONST64(0xCD45505E8353E80D) /* 272 */, CONST64(0x18D19A00D4DB0717) /* 273 */, + CONST64(0x34A0CFEDA5F38101) /* 274 */, CONST64(0x0BE77E518887CAF2) /* 275 */, + CONST64(0x1E341438B3C45136) /* 276 */, CONST64(0xE05797F49089CCF9) /* 277 */, + CONST64(0xFFD23F9DF2591D14) /* 278 */, CONST64(0x543DDA228595C5CD) /* 279 */, + CONST64(0x661F81FD99052A33) /* 280 */, CONST64(0x8736E641DB0F7B76) /* 281 */, + CONST64(0x15227725418E5307) /* 282 */, CONST64(0xE25F7F46162EB2FA) /* 283 */, + CONST64(0x48A8B2126C13D9FE) /* 284 */, CONST64(0xAFDC541792E76EEA) /* 285 */, + CONST64(0x03D912BFC6D1898F) /* 286 */, CONST64(0x31B1AAFA1B83F51B) /* 287 */, + CONST64(0xF1AC2796E42AB7D9) /* 288 */, CONST64(0x40A3A7D7FCD2EBAC) /* 289 */, + CONST64(0x1056136D0AFBBCC5) /* 290 */, CONST64(0x7889E1DD9A6D0C85) /* 291 */, + CONST64(0xD33525782A7974AA) /* 292 */, CONST64(0xA7E25D09078AC09B) /* 293 */, + CONST64(0xBD4138B3EAC6EDD0) /* 294 */, CONST64(0x920ABFBE71EB9E70) /* 295 */, + CONST64(0xA2A5D0F54FC2625C) /* 296 */, CONST64(0xC054E36B0B1290A3) /* 297 */, + CONST64(0xF6DD59FF62FE932B) /* 298 */, CONST64(0x3537354511A8AC7D) /* 299 */, + CONST64(0xCA845E9172FADCD4) /* 300 */, CONST64(0x84F82B60329D20DC) /* 301 */, + CONST64(0x79C62CE1CD672F18) /* 302 */, CONST64(0x8B09A2ADD124642C) /* 303 */, + CONST64(0xD0C1E96A19D9E726) /* 304 */, CONST64(0x5A786A9B4BA9500C) /* 305 */, + CONST64(0x0E020336634C43F3) /* 306 */, CONST64(0xC17B474AEB66D822) /* 307 */, + CONST64(0x6A731AE3EC9BAAC2) /* 308 */, CONST64(0x8226667AE0840258) /* 309 */, + CONST64(0x67D4567691CAECA5) /* 310 */, CONST64(0x1D94155C4875ADB5) /* 311 */, + CONST64(0x6D00FD985B813FDF) /* 312 */, CONST64(0x51286EFCB774CD06) /* 313 */, + CONST64(0x5E8834471FA744AF) /* 314 */, CONST64(0xF72CA0AEE761AE2E) /* 315 */, + CONST64(0xBE40E4CDAEE8E09A) /* 316 */, CONST64(0xE9970BBB5118F665) /* 317 */, + CONST64(0x726E4BEB33DF1964) /* 318 */, CONST64(0x703B000729199762) /* 319 */, + CONST64(0x4631D816F5EF30A7) /* 320 */, CONST64(0xB880B5B51504A6BE) /* 321 */, + CONST64(0x641793C37ED84B6C) /* 322 */, CONST64(0x7B21ED77F6E97D96) /* 323 */, + CONST64(0x776306312EF96B73) /* 324 */, CONST64(0xAE528948E86FF3F4) /* 325 */, + CONST64(0x53DBD7F286A3F8F8) /* 326 */, CONST64(0x16CADCE74CFC1063) /* 327 */, + CONST64(0x005C19BDFA52C6DD) /* 328 */, CONST64(0x68868F5D64D46AD3) /* 329 */, + CONST64(0x3A9D512CCF1E186A) /* 330 */, CONST64(0x367E62C2385660AE) /* 331 */, + CONST64(0xE359E7EA77DCB1D7) /* 332 */, CONST64(0x526C0773749ABE6E) /* 333 */, + CONST64(0x735AE5F9D09F734B) /* 334 */, CONST64(0x493FC7CC8A558BA8) /* 335 */, + CONST64(0xB0B9C1533041AB45) /* 336 */, CONST64(0x321958BA470A59BD) /* 337 */, + CONST64(0x852DB00B5F46C393) /* 338 */, CONST64(0x91209B2BD336B0E5) /* 339 */, + CONST64(0x6E604F7D659EF19F) /* 340 */, CONST64(0xB99A8AE2782CCB24) /* 341 */, + CONST64(0xCCF52AB6C814C4C7) /* 342 */, CONST64(0x4727D9AFBE11727B) /* 343 */, + CONST64(0x7E950D0C0121B34D) /* 344 */, CONST64(0x756F435670AD471F) /* 345 */, + CONST64(0xF5ADD442615A6849) /* 346 */, CONST64(0x4E87E09980B9957A) /* 347 */, + CONST64(0x2ACFA1DF50AEE355) /* 348 */, CONST64(0xD898263AFD2FD556) /* 349 */, + CONST64(0xC8F4924DD80C8FD6) /* 350 */, CONST64(0xCF99CA3D754A173A) /* 351 */, + CONST64(0xFE477BACAF91BF3C) /* 352 */, CONST64(0xED5371F6D690C12D) /* 353 */, + CONST64(0x831A5C285E687094) /* 354 */, CONST64(0xC5D3C90A3708A0A4) /* 355 */, + CONST64(0x0F7F903717D06580) /* 356 */, CONST64(0x19F9BB13B8FDF27F) /* 357 */, + CONST64(0xB1BD6F1B4D502843) /* 358 */, CONST64(0x1C761BA38FFF4012) /* 359 */, + CONST64(0x0D1530C4E2E21F3B) /* 360 */, CONST64(0x8943CE69A7372C8A) /* 361 */, + CONST64(0xE5184E11FEB5CE66) /* 362 */, CONST64(0x618BDB80BD736621) /* 363 */, + CONST64(0x7D29BAD68B574D0B) /* 364 */, CONST64(0x81BB613E25E6FE5B) /* 365 */, + CONST64(0x071C9C10BC07913F) /* 366 */, CONST64(0xC7BEEB7909AC2D97) /* 367 */, + CONST64(0xC3E58D353BC5D757) /* 368 */, CONST64(0xEB017892F38F61E8) /* 369 */, + CONST64(0xD4EFFB9C9B1CC21A) /* 370 */, CONST64(0x99727D26F494F7AB) /* 371 */, + CONST64(0xA3E063A2956B3E03) /* 372 */, CONST64(0x9D4A8B9A4AA09C30) /* 373 */, + CONST64(0x3F6AB7D500090FB4) /* 374 */, CONST64(0x9CC0F2A057268AC0) /* 375 */, + CONST64(0x3DEE9D2DEDBF42D1) /* 376 */, CONST64(0x330F49C87960A972) /* 377 */, + CONST64(0xC6B2720287421B41) /* 378 */, CONST64(0x0AC59EC07C00369C) /* 379 */, + CONST64(0xEF4EAC49CB353425) /* 380 */, CONST64(0xF450244EEF0129D8) /* 381 */, + CONST64(0x8ACC46E5CAF4DEB6) /* 382 */, CONST64(0x2FFEAB63989263F7) /* 383 */, + CONST64(0x8F7CB9FE5D7A4578) /* 384 */, CONST64(0x5BD8F7644E634635) /* 385 */, + CONST64(0x427A7315BF2DC900) /* 386 */, CONST64(0x17D0C4AA2125261C) /* 387 */, + CONST64(0x3992486C93518E50) /* 388 */, CONST64(0xB4CBFEE0A2D7D4C3) /* 389 */, + CONST64(0x7C75D6202C5DDD8D) /* 390 */, CONST64(0xDBC295D8E35B6C61) /* 391 */, + CONST64(0x60B369D302032B19) /* 392 */, CONST64(0xCE42685FDCE44132) /* 393 */, + CONST64(0x06F3DDB9DDF65610) /* 394 */, CONST64(0x8EA4D21DB5E148F0) /* 395 */, + CONST64(0x20B0FCE62FCD496F) /* 396 */, CONST64(0x2C1B912358B0EE31) /* 397 */, + CONST64(0xB28317B818F5A308) /* 398 */, CONST64(0xA89C1E189CA6D2CF) /* 399 */, + CONST64(0x0C6B18576AAADBC8) /* 400 */, CONST64(0xB65DEAA91299FAE3) /* 401 */, + CONST64(0xFB2B794B7F1027E7) /* 402 */, CONST64(0x04E4317F443B5BEB) /* 403 */, + CONST64(0x4B852D325939D0A6) /* 404 */, CONST64(0xD5AE6BEEFB207FFC) /* 405 */, + CONST64(0x309682B281C7D374) /* 406 */, CONST64(0xBAE309A194C3B475) /* 407 */, + CONST64(0x8CC3F97B13B49F05) /* 408 */, CONST64(0x98A9422FF8293967) /* 409 */, + CONST64(0x244B16B01076FF7C) /* 410 */, CONST64(0xF8BF571C663D67EE) /* 411 */, + CONST64(0x1F0D6758EEE30DA1) /* 412 */, CONST64(0xC9B611D97ADEB9B7) /* 413 */, + CONST64(0xB7AFD5887B6C57A2) /* 414 */, CONST64(0x6290AE846B984FE1) /* 415 */, + CONST64(0x94DF4CDEACC1A5FD) /* 416 */, CONST64(0x058A5BD1C5483AFF) /* 417 */, + CONST64(0x63166CC142BA3C37) /* 418 */, CONST64(0x8DB8526EB2F76F40) /* 419 */, + CONST64(0xE10880036F0D6D4E) /* 420 */, CONST64(0x9E0523C9971D311D) /* 421 */, + CONST64(0x45EC2824CC7CD691) /* 422 */, CONST64(0x575B8359E62382C9) /* 423 */, + CONST64(0xFA9E400DC4889995) /* 424 */, CONST64(0xD1823ECB45721568) /* 425 */, + CONST64(0xDAFD983B8206082F) /* 426 */, CONST64(0xAA7D29082386A8CB) /* 427 */, + CONST64(0x269FCD4403B87588) /* 428 */, CONST64(0x1B91F5F728BDD1E0) /* 429 */, + CONST64(0xE4669F39040201F6) /* 430 */, CONST64(0x7A1D7C218CF04ADE) /* 431 */, + CONST64(0x65623C29D79CE5CE) /* 432 */, CONST64(0x2368449096C00BB1) /* 433 */, + CONST64(0xAB9BF1879DA503BA) /* 434 */, CONST64(0xBC23ECB1A458058E) /* 435 */, + CONST64(0x9A58DF01BB401ECC) /* 436 */, CONST64(0xA070E868A85F143D) /* 437 */, + CONST64(0x4FF188307DF2239E) /* 438 */, CONST64(0x14D565B41A641183) /* 439 */, + CONST64(0xEE13337452701602) /* 440 */, CONST64(0x950E3DCF3F285E09) /* 441 */, + CONST64(0x59930254B9C80953) /* 442 */, CONST64(0x3BF299408930DA6D) /* 443 */, + CONST64(0xA955943F53691387) /* 444 */, CONST64(0xA15EDECAA9CB8784) /* 445 */, + CONST64(0x29142127352BE9A0) /* 446 */, CONST64(0x76F0371FFF4E7AFB) /* 447 */, + CONST64(0x0239F450274F2228) /* 448 */, CONST64(0xBB073AF01D5E868B) /* 449 */, + CONST64(0xBFC80571C10E96C1) /* 450 */, CONST64(0xD267088568222E23) /* 451 */, + CONST64(0x9671A3D48E80B5B0) /* 452 */, CONST64(0x55B5D38AE193BB81) /* 453 */, + CONST64(0x693AE2D0A18B04B8) /* 454 */, CONST64(0x5C48B4ECADD5335F) /* 455 */, + CONST64(0xFD743B194916A1CA) /* 456 */, CONST64(0x2577018134BE98C4) /* 457 */, + CONST64(0xE77987E83C54A4AD) /* 458 */, CONST64(0x28E11014DA33E1B9) /* 459 */, + CONST64(0x270CC59E226AA213) /* 460 */, CONST64(0x71495F756D1A5F60) /* 461 */, + CONST64(0x9BE853FB60AFEF77) /* 462 */, CONST64(0xADC786A7F7443DBF) /* 463 */, + CONST64(0x0904456173B29A82) /* 464 */, CONST64(0x58BC7A66C232BD5E) /* 465 */, + CONST64(0xF306558C673AC8B2) /* 466 */, CONST64(0x41F639C6B6C9772A) /* 467 */, + CONST64(0x216DEFE99FDA35DA) /* 468 */, CONST64(0x11640CC71C7BE615) /* 469 */, + CONST64(0x93C43694565C5527) /* 470 */, CONST64(0xEA038E6246777839) /* 471 */, + CONST64(0xF9ABF3CE5A3E2469) /* 472 */, CONST64(0x741E768D0FD312D2) /* 473 */, + CONST64(0x0144B883CED652C6) /* 474 */, CONST64(0xC20B5A5BA33F8552) /* 475 */, + CONST64(0x1AE69633C3435A9D) /* 476 */, CONST64(0x97A28CA4088CFDEC) /* 477 */, + CONST64(0x8824A43C1E96F420) /* 478 */, CONST64(0x37612FA66EEEA746) /* 479 */, + CONST64(0x6B4CB165F9CF0E5A) /* 480 */, CONST64(0x43AA1C06A0ABFB4A) /* 481 */, + CONST64(0x7F4DC26FF162796B) /* 482 */, CONST64(0x6CBACC8E54ED9B0F) /* 483 */, + CONST64(0xA6B7FFEFD2BB253E) /* 484 */, CONST64(0x2E25BC95B0A29D4F) /* 485 */, + CONST64(0x86D6A58BDEF1388C) /* 486 */, CONST64(0xDED74AC576B6F054) /* 487 */, + CONST64(0x8030BDBC2B45805D) /* 488 */, CONST64(0x3C81AF70E94D9289) /* 489 */, + CONST64(0x3EFF6DDA9E3100DB) /* 490 */, CONST64(0xB38DC39FDFCC8847) /* 491 */, + CONST64(0x123885528D17B87E) /* 492 */, CONST64(0xF2DA0ED240B1B642) /* 493 */, + CONST64(0x44CEFADCD54BF9A9) /* 494 */, CONST64(0x1312200E433C7EE6) /* 495 */, + CONST64(0x9FFCC84F3A78C748) /* 496 */, CONST64(0xF0CD1F72248576BB) /* 497 */, + CONST64(0xEC6974053638CFE4) /* 498 */, CONST64(0x2BA7B67C0CEC4E4C) /* 499 */, + CONST64(0xAC2F4DF3E5CE32ED) /* 500 */, CONST64(0xCB33D14326EA4C11) /* 501 */, + CONST64(0xA4E9044CC77E58BC) /* 502 */, CONST64(0x5F513293D934FCEF) /* 503 */, + CONST64(0x5DC9645506E55444) /* 504 */, CONST64(0x50DE418F317DE40A) /* 505 */, + CONST64(0x388CB31A69DDE259) /* 506 */, CONST64(0x2DB4A83455820A86) /* 507 */, + CONST64(0x9010A91E84711AE9) /* 508 */, CONST64(0x4DF7F0B7B1498371) /* 509 */, + CONST64(0xD62A2EABC0977179) /* 510 */, CONST64(0x22FAC097AA8D5C0E) /* 511 */, + CONST64(0xF49FCC2FF1DAF39B) /* 512 */, CONST64(0x487FD5C66FF29281) /* 513 */, + CONST64(0xE8A30667FCDCA83F) /* 514 */, CONST64(0x2C9B4BE3D2FCCE63) /* 515 */, + CONST64(0xDA3FF74B93FBBBC2) /* 516 */, CONST64(0x2FA165D2FE70BA66) /* 517 */, + CONST64(0xA103E279970E93D4) /* 518 */, CONST64(0xBECDEC77B0E45E71) /* 519 */, + CONST64(0xCFB41E723985E497) /* 520 */, CONST64(0xB70AAA025EF75017) /* 521 */, + CONST64(0xD42309F03840B8E0) /* 522 */, CONST64(0x8EFC1AD035898579) /* 523 */, + CONST64(0x96C6920BE2B2ABC5) /* 524 */, CONST64(0x66AF4163375A9172) /* 525 */, + CONST64(0x2174ABDCCA7127FB) /* 526 */, CONST64(0xB33CCEA64A72FF41) /* 527 */, + CONST64(0xF04A4933083066A5) /* 528 */, CONST64(0x8D970ACDD7289AF5) /* 529 */, + CONST64(0x8F96E8E031C8C25E) /* 530 */, CONST64(0xF3FEC02276875D47) /* 531 */, + CONST64(0xEC7BF310056190DD) /* 532 */, CONST64(0xF5ADB0AEBB0F1491) /* 533 */, + CONST64(0x9B50F8850FD58892) /* 534 */, CONST64(0x4975488358B74DE8) /* 535 */, + CONST64(0xA3354FF691531C61) /* 536 */, CONST64(0x0702BBE481D2C6EE) /* 537 */, + CONST64(0x89FB24057DEDED98) /* 538 */, CONST64(0xAC3075138596E902) /* 539 */, + CONST64(0x1D2D3580172772ED) /* 540 */, CONST64(0xEB738FC28E6BC30D) /* 541 */, + CONST64(0x5854EF8F63044326) /* 542 */, CONST64(0x9E5C52325ADD3BBE) /* 543 */, + CONST64(0x90AA53CF325C4623) /* 544 */, CONST64(0xC1D24D51349DD067) /* 545 */, + CONST64(0x2051CFEEA69EA624) /* 546 */, CONST64(0x13220F0A862E7E4F) /* 547 */, + CONST64(0xCE39399404E04864) /* 548 */, CONST64(0xD9C42CA47086FCB7) /* 549 */, + CONST64(0x685AD2238A03E7CC) /* 550 */, CONST64(0x066484B2AB2FF1DB) /* 551 */, + CONST64(0xFE9D5D70EFBF79EC) /* 552 */, CONST64(0x5B13B9DD9C481854) /* 553 */, + CONST64(0x15F0D475ED1509AD) /* 554 */, CONST64(0x0BEBCD060EC79851) /* 555 */, + CONST64(0xD58C6791183AB7F8) /* 556 */, CONST64(0xD1187C5052F3EEE4) /* 557 */, + CONST64(0xC95D1192E54E82FF) /* 558 */, CONST64(0x86EEA14CB9AC6CA2) /* 559 */, + CONST64(0x3485BEB153677D5D) /* 560 */, CONST64(0xDD191D781F8C492A) /* 561 */, + CONST64(0xF60866BAA784EBF9) /* 562 */, CONST64(0x518F643BA2D08C74) /* 563 */, + CONST64(0x8852E956E1087C22) /* 564 */, CONST64(0xA768CB8DC410AE8D) /* 565 */, + CONST64(0x38047726BFEC8E1A) /* 566 */, CONST64(0xA67738B4CD3B45AA) /* 567 */, + CONST64(0xAD16691CEC0DDE19) /* 568 */, CONST64(0xC6D4319380462E07) /* 569 */, + CONST64(0xC5A5876D0BA61938) /* 570 */, CONST64(0x16B9FA1FA58FD840) /* 571 */, + CONST64(0x188AB1173CA74F18) /* 572 */, CONST64(0xABDA2F98C99C021F) /* 573 */, + CONST64(0x3E0580AB134AE816) /* 574 */, CONST64(0x5F3B05B773645ABB) /* 575 */, + CONST64(0x2501A2BE5575F2F6) /* 576 */, CONST64(0x1B2F74004E7E8BA9) /* 577 */, + CONST64(0x1CD7580371E8D953) /* 578 */, CONST64(0x7F6ED89562764E30) /* 579 */, + CONST64(0xB15926FF596F003D) /* 580 */, CONST64(0x9F65293DA8C5D6B9) /* 581 */, + CONST64(0x6ECEF04DD690F84C) /* 582 */, CONST64(0x4782275FFF33AF88) /* 583 */, + CONST64(0xE41433083F820801) /* 584 */, CONST64(0xFD0DFE409A1AF9B5) /* 585 */, + CONST64(0x4325A3342CDB396B) /* 586 */, CONST64(0x8AE77E62B301B252) /* 587 */, + CONST64(0xC36F9E9F6655615A) /* 588 */, CONST64(0x85455A2D92D32C09) /* 589 */, + CONST64(0xF2C7DEA949477485) /* 590 */, CONST64(0x63CFB4C133A39EBA) /* 591 */, + CONST64(0x83B040CC6EBC5462) /* 592 */, CONST64(0x3B9454C8FDB326B0) /* 593 */, + CONST64(0x56F56A9E87FFD78C) /* 594 */, CONST64(0x2DC2940D99F42BC6) /* 595 */, + CONST64(0x98F7DF096B096E2D) /* 596 */, CONST64(0x19A6E01E3AD852BF) /* 597 */, + CONST64(0x42A99CCBDBD4B40B) /* 598 */, CONST64(0xA59998AF45E9C559) /* 599 */, + CONST64(0x366295E807D93186) /* 600 */, CONST64(0x6B48181BFAA1F773) /* 601 */, + CONST64(0x1FEC57E2157A0A1D) /* 602 */, CONST64(0x4667446AF6201AD5) /* 603 */, + CONST64(0xE615EBCACFB0F075) /* 604 */, CONST64(0xB8F31F4F68290778) /* 605 */, + CONST64(0x22713ED6CE22D11E) /* 606 */, CONST64(0x3057C1A72EC3C93B) /* 607 */, + CONST64(0xCB46ACC37C3F1F2F) /* 608 */, CONST64(0xDBB893FD02AAF50E) /* 609 */, + CONST64(0x331FD92E600B9FCF) /* 610 */, CONST64(0xA498F96148EA3AD6) /* 611 */, + CONST64(0xA8D8426E8B6A83EA) /* 612 */, CONST64(0xA089B274B7735CDC) /* 613 */, + CONST64(0x87F6B3731E524A11) /* 614 */, CONST64(0x118808E5CBC96749) /* 615 */, + CONST64(0x9906E4C7B19BD394) /* 616 */, CONST64(0xAFED7F7E9B24A20C) /* 617 */, + CONST64(0x6509EADEEB3644A7) /* 618 */, CONST64(0x6C1EF1D3E8EF0EDE) /* 619 */, + CONST64(0xB9C97D43E9798FB4) /* 620 */, CONST64(0xA2F2D784740C28A3) /* 621 */, + CONST64(0x7B8496476197566F) /* 622 */, CONST64(0x7A5BE3E6B65F069D) /* 623 */, + CONST64(0xF96330ED78BE6F10) /* 624 */, CONST64(0xEEE60DE77A076A15) /* 625 */, + CONST64(0x2B4BEE4AA08B9BD0) /* 626 */, CONST64(0x6A56A63EC7B8894E) /* 627 */, + CONST64(0x02121359BA34FEF4) /* 628 */, CONST64(0x4CBF99F8283703FC) /* 629 */, + CONST64(0x398071350CAF30C8) /* 630 */, CONST64(0xD0A77A89F017687A) /* 631 */, + CONST64(0xF1C1A9EB9E423569) /* 632 */, CONST64(0x8C7976282DEE8199) /* 633 */, + CONST64(0x5D1737A5DD1F7ABD) /* 634 */, CONST64(0x4F53433C09A9FA80) /* 635 */, + CONST64(0xFA8B0C53DF7CA1D9) /* 636 */, CONST64(0x3FD9DCBC886CCB77) /* 637 */, + CONST64(0xC040917CA91B4720) /* 638 */, CONST64(0x7DD00142F9D1DCDF) /* 639 */, + CONST64(0x8476FC1D4F387B58) /* 640 */, CONST64(0x23F8E7C5F3316503) /* 641 */, + CONST64(0x032A2244E7E37339) /* 642 */, CONST64(0x5C87A5D750F5A74B) /* 643 */, + CONST64(0x082B4CC43698992E) /* 644 */, CONST64(0xDF917BECB858F63C) /* 645 */, + CONST64(0x3270B8FC5BF86DDA) /* 646 */, CONST64(0x10AE72BB29B5DD76) /* 647 */, + CONST64(0x576AC94E7700362B) /* 648 */, CONST64(0x1AD112DAC61EFB8F) /* 649 */, + CONST64(0x691BC30EC5FAA427) /* 650 */, CONST64(0xFF246311CC327143) /* 651 */, + CONST64(0x3142368E30E53206) /* 652 */, CONST64(0x71380E31E02CA396) /* 653 */, + CONST64(0x958D5C960AAD76F1) /* 654 */, CONST64(0xF8D6F430C16DA536) /* 655 */, + CONST64(0xC8FFD13F1BE7E1D2) /* 656 */, CONST64(0x7578AE66004DDBE1) /* 657 */, + CONST64(0x05833F01067BE646) /* 658 */, CONST64(0xBB34B5AD3BFE586D) /* 659 */, + CONST64(0x095F34C9A12B97F0) /* 660 */, CONST64(0x247AB64525D60CA8) /* 661 */, + CONST64(0xDCDBC6F3017477D1) /* 662 */, CONST64(0x4A2E14D4DECAD24D) /* 663 */, + CONST64(0xBDB5E6D9BE0A1EEB) /* 664 */, CONST64(0x2A7E70F7794301AB) /* 665 */, + CONST64(0xDEF42D8A270540FD) /* 666 */, CONST64(0x01078EC0A34C22C1) /* 667 */, + CONST64(0xE5DE511AF4C16387) /* 668 */, CONST64(0x7EBB3A52BD9A330A) /* 669 */, + CONST64(0x77697857AA7D6435) /* 670 */, CONST64(0x004E831603AE4C32) /* 671 */, + CONST64(0xE7A21020AD78E312) /* 672 */, CONST64(0x9D41A70C6AB420F2) /* 673 */, + CONST64(0x28E06C18EA1141E6) /* 674 */, CONST64(0xD2B28CBD984F6B28) /* 675 */, + CONST64(0x26B75F6C446E9D83) /* 676 */, CONST64(0xBA47568C4D418D7F) /* 677 */, + CONST64(0xD80BADBFE6183D8E) /* 678 */, CONST64(0x0E206D7F5F166044) /* 679 */, + CONST64(0xE258A43911CBCA3E) /* 680 */, CONST64(0x723A1746B21DC0BC) /* 681 */, + CONST64(0xC7CAA854F5D7CDD3) /* 682 */, CONST64(0x7CAC32883D261D9C) /* 683 */, + CONST64(0x7690C26423BA942C) /* 684 */, CONST64(0x17E55524478042B8) /* 685 */, + CONST64(0xE0BE477656A2389F) /* 686 */, CONST64(0x4D289B5E67AB2DA0) /* 687 */, + CONST64(0x44862B9C8FBBFD31) /* 688 */, CONST64(0xB47CC8049D141365) /* 689 */, + CONST64(0x822C1B362B91C793) /* 690 */, CONST64(0x4EB14655FB13DFD8) /* 691 */, + CONST64(0x1ECBBA0714E2A97B) /* 692 */, CONST64(0x6143459D5CDE5F14) /* 693 */, + CONST64(0x53A8FBF1D5F0AC89) /* 694 */, CONST64(0x97EA04D81C5E5B00) /* 695 */, + CONST64(0x622181A8D4FDB3F3) /* 696 */, CONST64(0xE9BCD341572A1208) /* 697 */, + CONST64(0x1411258643CCE58A) /* 698 */, CONST64(0x9144C5FEA4C6E0A4) /* 699 */, + CONST64(0x0D33D06565CF620F) /* 700 */, CONST64(0x54A48D489F219CA1) /* 701 */, + CONST64(0xC43E5EAC6D63C821) /* 702 */, CONST64(0xA9728B3A72770DAF) /* 703 */, + CONST64(0xD7934E7B20DF87EF) /* 704 */, CONST64(0xE35503B61A3E86E5) /* 705 */, + CONST64(0xCAE321FBC819D504) /* 706 */, CONST64(0x129A50B3AC60BFA6) /* 707 */, + CONST64(0xCD5E68EA7E9FB6C3) /* 708 */, CONST64(0xB01C90199483B1C7) /* 709 */, + CONST64(0x3DE93CD5C295376C) /* 710 */, CONST64(0xAED52EDF2AB9AD13) /* 711 */, + CONST64(0x2E60F512C0A07884) /* 712 */, CONST64(0xBC3D86A3E36210C9) /* 713 */, + CONST64(0x35269D9B163951CE) /* 714 */, CONST64(0x0C7D6E2AD0CDB5FA) /* 715 */, + CONST64(0x59E86297D87F5733) /* 716 */, CONST64(0x298EF221898DB0E7) /* 717 */, + CONST64(0x55000029D1A5AA7E) /* 718 */, CONST64(0x8BC08AE1B5061B45) /* 719 */, + CONST64(0xC2C31C2B6C92703A) /* 720 */, CONST64(0x94CC596BAF25EF42) /* 721 */, + CONST64(0x0A1D73DB22540456) /* 722 */, CONST64(0x04B6A0F9D9C4179A) /* 723 */, + CONST64(0xEFFDAFA2AE3D3C60) /* 724 */, CONST64(0xF7C8075BB49496C4) /* 725 */, + CONST64(0x9CC5C7141D1CD4E3) /* 726 */, CONST64(0x78BD1638218E5534) /* 727 */, + CONST64(0xB2F11568F850246A) /* 728 */, CONST64(0xEDFABCFA9502BC29) /* 729 */, + CONST64(0x796CE5F2DA23051B) /* 730 */, CONST64(0xAAE128B0DC93537C) /* 731 */, + CONST64(0x3A493DA0EE4B29AE) /* 732 */, CONST64(0xB5DF6B2C416895D7) /* 733 */, + CONST64(0xFCABBD25122D7F37) /* 734 */, CONST64(0x70810B58105DC4B1) /* 735 */, + CONST64(0xE10FDD37F7882A90) /* 736 */, CONST64(0x524DCAB5518A3F5C) /* 737 */, + CONST64(0x3C9E85878451255B) /* 738 */, CONST64(0x4029828119BD34E2) /* 739 */, + CONST64(0x74A05B6F5D3CECCB) /* 740 */, CONST64(0xB610021542E13ECA) /* 741 */, + CONST64(0x0FF979D12F59E2AC) /* 742 */, CONST64(0x6037DA27E4F9CC50) /* 743 */, + CONST64(0x5E92975A0DF1847D) /* 744 */, CONST64(0xD66DE190D3E623FE) /* 745 */, + CONST64(0x5032D6B87B568048) /* 746 */, CONST64(0x9A36B7CE8235216E) /* 747 */, + CONST64(0x80272A7A24F64B4A) /* 748 */, CONST64(0x93EFED8B8C6916F7) /* 749 */, + CONST64(0x37DDBFF44CCE1555) /* 750 */, CONST64(0x4B95DB5D4B99BD25) /* 751 */, + CONST64(0x92D3FDA169812FC0) /* 752 */, CONST64(0xFB1A4A9A90660BB6) /* 753 */, + CONST64(0x730C196946A4B9B2) /* 754 */, CONST64(0x81E289AA7F49DA68) /* 755 */, + CONST64(0x64669A0F83B1A05F) /* 756 */, CONST64(0x27B3FF7D9644F48B) /* 757 */, + CONST64(0xCC6B615C8DB675B3) /* 758 */, CONST64(0x674F20B9BCEBBE95) /* 759 */, + CONST64(0x6F31238275655982) /* 760 */, CONST64(0x5AE488713E45CF05) /* 761 */, + CONST64(0xBF619F9954C21157) /* 762 */, CONST64(0xEABAC46040A8EAE9) /* 763 */, + CONST64(0x454C6FE9F2C0C1CD) /* 764 */, CONST64(0x419CF6496412691C) /* 765 */, + CONST64(0xD3DC3BEF265B0F70) /* 766 */, CONST64(0x6D0E60F5C3578A9E) /* 767 */, + CONST64(0x5B0E608526323C55) /* 768 */, CONST64(0x1A46C1A9FA1B59F5) /* 769 */, + CONST64(0xA9E245A17C4C8FFA) /* 770 */, CONST64(0x65CA5159DB2955D7) /* 771 */, + CONST64(0x05DB0A76CE35AFC2) /* 772 */, CONST64(0x81EAC77EA9113D45) /* 773 */, + CONST64(0x528EF88AB6AC0A0D) /* 774 */, CONST64(0xA09EA253597BE3FF) /* 775 */, + CONST64(0x430DDFB3AC48CD56) /* 776 */, CONST64(0xC4B3A67AF45CE46F) /* 777 */, + CONST64(0x4ECECFD8FBE2D05E) /* 778 */, CONST64(0x3EF56F10B39935F0) /* 779 */, + CONST64(0x0B22D6829CD619C6) /* 780 */, CONST64(0x17FD460A74DF2069) /* 781 */, + CONST64(0x6CF8CC8E8510ED40) /* 782 */, CONST64(0xD6C824BF3A6ECAA7) /* 783 */, + CONST64(0x61243D581A817049) /* 784 */, CONST64(0x048BACB6BBC163A2) /* 785 */, + CONST64(0xD9A38AC27D44CC32) /* 786 */, CONST64(0x7FDDFF5BAAF410AB) /* 787 */, + CONST64(0xAD6D495AA804824B) /* 788 */, CONST64(0xE1A6A74F2D8C9F94) /* 789 */, + CONST64(0xD4F7851235DEE8E3) /* 790 */, CONST64(0xFD4B7F886540D893) /* 791 */, + CONST64(0x247C20042AA4BFDA) /* 792 */, CONST64(0x096EA1C517D1327C) /* 793 */, + CONST64(0xD56966B4361A6685) /* 794 */, CONST64(0x277DA5C31221057D) /* 795 */, + CONST64(0x94D59893A43ACFF7) /* 796 */, CONST64(0x64F0C51CCDC02281) /* 797 */, + CONST64(0x3D33BCC4FF6189DB) /* 798 */, CONST64(0xE005CB184CE66AF1) /* 799 */, + CONST64(0xFF5CCD1D1DB99BEA) /* 800 */, CONST64(0xB0B854A7FE42980F) /* 801 */, + CONST64(0x7BD46A6A718D4B9F) /* 802 */, CONST64(0xD10FA8CC22A5FD8C) /* 803 */, + CONST64(0xD31484952BE4BD31) /* 804 */, CONST64(0xC7FA975FCB243847) /* 805 */, + CONST64(0x4886ED1E5846C407) /* 806 */, CONST64(0x28CDDB791EB70B04) /* 807 */, + CONST64(0xC2B00BE2F573417F) /* 808 */, CONST64(0x5C9590452180F877) /* 809 */, + CONST64(0x7A6BDDFFF370EB00) /* 810 */, CONST64(0xCE509E38D6D9D6A4) /* 811 */, + CONST64(0xEBEB0F00647FA702) /* 812 */, CONST64(0x1DCC06CF76606F06) /* 813 */, + CONST64(0xE4D9F28BA286FF0A) /* 814 */, CONST64(0xD85A305DC918C262) /* 815 */, + CONST64(0x475B1D8732225F54) /* 816 */, CONST64(0x2D4FB51668CCB5FE) /* 817 */, + CONST64(0xA679B9D9D72BBA20) /* 818 */, CONST64(0x53841C0D912D43A5) /* 819 */, + CONST64(0x3B7EAA48BF12A4E8) /* 820 */, CONST64(0x781E0E47F22F1DDF) /* 821 */, + CONST64(0xEFF20CE60AB50973) /* 822 */, CONST64(0x20D261D19DFFB742) /* 823 */, + CONST64(0x16A12B03062A2E39) /* 824 */, CONST64(0x1960EB2239650495) /* 825 */, + CONST64(0x251C16FED50EB8B8) /* 826 */, CONST64(0x9AC0C330F826016E) /* 827 */, + CONST64(0xED152665953E7671) /* 828 */, CONST64(0x02D63194A6369570) /* 829 */, + CONST64(0x5074F08394B1C987) /* 830 */, CONST64(0x70BA598C90B25CE1) /* 831 */, + CONST64(0x794A15810B9742F6) /* 832 */, CONST64(0x0D5925E9FCAF8C6C) /* 833 */, + CONST64(0x3067716CD868744E) /* 834 */, CONST64(0x910AB077E8D7731B) /* 835 */, + CONST64(0x6A61BBDB5AC42F61) /* 836 */, CONST64(0x93513EFBF0851567) /* 837 */, + CONST64(0xF494724B9E83E9D5) /* 838 */, CONST64(0xE887E1985C09648D) /* 839 */, + CONST64(0x34B1D3C675370CFD) /* 840 */, CONST64(0xDC35E433BC0D255D) /* 841 */, + CONST64(0xD0AAB84234131BE0) /* 842 */, CONST64(0x08042A50B48B7EAF) /* 843 */, + CONST64(0x9997C4EE44A3AB35) /* 844 */, CONST64(0x829A7B49201799D0) /* 845 */, + CONST64(0x263B8307B7C54441) /* 846 */, CONST64(0x752F95F4FD6A6CA6) /* 847 */, + CONST64(0x927217402C08C6E5) /* 848 */, CONST64(0x2A8AB754A795D9EE) /* 849 */, + CONST64(0xA442F7552F72943D) /* 850 */, CONST64(0x2C31334E19781208) /* 851 */, + CONST64(0x4FA98D7CEAEE6291) /* 852 */, CONST64(0x55C3862F665DB309) /* 853 */, + CONST64(0xBD0610175D53B1F3) /* 854 */, CONST64(0x46FE6CB840413F27) /* 855 */, + CONST64(0x3FE03792DF0CFA59) /* 856 */, CONST64(0xCFE700372EB85E8F) /* 857 */, + CONST64(0xA7BE29E7ADBCE118) /* 858 */, CONST64(0xE544EE5CDE8431DD) /* 859 */, + CONST64(0x8A781B1B41F1873E) /* 860 */, CONST64(0xA5C94C78A0D2F0E7) /* 861 */, + CONST64(0x39412E2877B60728) /* 862 */, CONST64(0xA1265EF3AFC9A62C) /* 863 */, + CONST64(0xBCC2770C6A2506C5) /* 864 */, CONST64(0x3AB66DD5DCE1CE12) /* 865 */, + CONST64(0xE65499D04A675B37) /* 866 */, CONST64(0x7D8F523481BFD216) /* 867 */, + CONST64(0x0F6F64FCEC15F389) /* 868 */, CONST64(0x74EFBE618B5B13C8) /* 869 */, + CONST64(0xACDC82B714273E1D) /* 870 */, CONST64(0xDD40BFE003199D17) /* 871 */, + CONST64(0x37E99257E7E061F8) /* 872 */, CONST64(0xFA52626904775AAA) /* 873 */, + CONST64(0x8BBBF63A463D56F9) /* 874 */, CONST64(0xF0013F1543A26E64) /* 875 */, + CONST64(0xA8307E9F879EC898) /* 876 */, CONST64(0xCC4C27A4150177CC) /* 877 */, + CONST64(0x1B432F2CCA1D3348) /* 878 */, CONST64(0xDE1D1F8F9F6FA013) /* 879 */, + CONST64(0x606602A047A7DDD6) /* 880 */, CONST64(0xD237AB64CC1CB2C7) /* 881 */, + CONST64(0x9B938E7225FCD1D3) /* 882 */, CONST64(0xEC4E03708E0FF476) /* 883 */, + CONST64(0xFEB2FBDA3D03C12D) /* 884 */, CONST64(0xAE0BCED2EE43889A) /* 885 */, + CONST64(0x22CB8923EBFB4F43) /* 886 */, CONST64(0x69360D013CF7396D) /* 887 */, + CONST64(0x855E3602D2D4E022) /* 888 */, CONST64(0x073805BAD01F784C) /* 889 */, + CONST64(0x33E17A133852F546) /* 890 */, CONST64(0xDF4874058AC7B638) /* 891 */, + CONST64(0xBA92B29C678AA14A) /* 892 */, CONST64(0x0CE89FC76CFAADCD) /* 893 */, + CONST64(0x5F9D4E0908339E34) /* 894 */, CONST64(0xF1AFE9291F5923B9) /* 895 */, + CONST64(0x6E3480F60F4A265F) /* 896 */, CONST64(0xEEBF3A2AB29B841C) /* 897 */, + CONST64(0xE21938A88F91B4AD) /* 898 */, CONST64(0x57DFEFF845C6D3C3) /* 899 */, + CONST64(0x2F006B0BF62CAAF2) /* 900 */, CONST64(0x62F479EF6F75EE78) /* 901 */, + CONST64(0x11A55AD41C8916A9) /* 902 */, CONST64(0xF229D29084FED453) /* 903 */, + CONST64(0x42F1C27B16B000E6) /* 904 */, CONST64(0x2B1F76749823C074) /* 905 */, + CONST64(0x4B76ECA3C2745360) /* 906 */, CONST64(0x8C98F463B91691BD) /* 907 */, + CONST64(0x14BCC93CF1ADE66A) /* 908 */, CONST64(0x8885213E6D458397) /* 909 */, + CONST64(0x8E177DF0274D4711) /* 910 */, CONST64(0xB49B73B5503F2951) /* 911 */, + CONST64(0x10168168C3F96B6B) /* 912 */, CONST64(0x0E3D963B63CAB0AE) /* 913 */, + CONST64(0x8DFC4B5655A1DB14) /* 914 */, CONST64(0xF789F1356E14DE5C) /* 915 */, + CONST64(0x683E68AF4E51DAC1) /* 916 */, CONST64(0xC9A84F9D8D4B0FD9) /* 917 */, + CONST64(0x3691E03F52A0F9D1) /* 918 */, CONST64(0x5ED86E46E1878E80) /* 919 */, + CONST64(0x3C711A0E99D07150) /* 920 */, CONST64(0x5A0865B20C4E9310) /* 921 */, + CONST64(0x56FBFC1FE4F0682E) /* 922 */, CONST64(0xEA8D5DE3105EDF9B) /* 923 */, + CONST64(0x71ABFDB12379187A) /* 924 */, CONST64(0x2EB99DE1BEE77B9C) /* 925 */, + CONST64(0x21ECC0EA33CF4523) /* 926 */, CONST64(0x59A4D7521805C7A1) /* 927 */, + CONST64(0x3896F5EB56AE7C72) /* 928 */, CONST64(0xAA638F3DB18F75DC) /* 929 */, + CONST64(0x9F39358DABE9808E) /* 930 */, CONST64(0xB7DEFA91C00B72AC) /* 931 */, + CONST64(0x6B5541FD62492D92) /* 932 */, CONST64(0x6DC6DEE8F92E4D5B) /* 933 */, + CONST64(0x353F57ABC4BEEA7E) /* 934 */, CONST64(0x735769D6DA5690CE) /* 935 */, + CONST64(0x0A234AA642391484) /* 936 */, CONST64(0xF6F9508028F80D9D) /* 937 */, + CONST64(0xB8E319A27AB3F215) /* 938 */, CONST64(0x31AD9C1151341A4D) /* 939 */, + CONST64(0x773C22A57BEF5805) /* 940 */, CONST64(0x45C7561A07968633) /* 941 */, + CONST64(0xF913DA9E249DBE36) /* 942 */, CONST64(0xDA652D9B78A64C68) /* 943 */, + CONST64(0x4C27A97F3BC334EF) /* 944 */, CONST64(0x76621220E66B17F4) /* 945 */, + CONST64(0x967743899ACD7D0B) /* 946 */, CONST64(0xF3EE5BCAE0ED6782) /* 947 */, + CONST64(0x409F753600C879FC) /* 948 */, CONST64(0x06D09A39B5926DB6) /* 949 */, + CONST64(0x6F83AEB0317AC588) /* 950 */, CONST64(0x01E6CA4A86381F21) /* 951 */, + CONST64(0x66FF3462D19F3025) /* 952 */, CONST64(0x72207C24DDFD3BFB) /* 953 */, + CONST64(0x4AF6B6D3E2ECE2EB) /* 954 */, CONST64(0x9C994DBEC7EA08DE) /* 955 */, + CONST64(0x49ACE597B09A8BC4) /* 956 */, CONST64(0xB38C4766CF0797BA) /* 957 */, + CONST64(0x131B9373C57C2A75) /* 958 */, CONST64(0xB1822CCE61931E58) /* 959 */, + CONST64(0x9D7555B909BA1C0C) /* 960 */, CONST64(0x127FAFDD937D11D2) /* 961 */, + CONST64(0x29DA3BADC66D92E4) /* 962 */, CONST64(0xA2C1D57154C2ECBC) /* 963 */, + CONST64(0x58C5134D82F6FE24) /* 964 */, CONST64(0x1C3AE3515B62274F) /* 965 */, + CONST64(0xE907C82E01CB8126) /* 966 */, CONST64(0xF8ED091913E37FCB) /* 967 */, + CONST64(0x3249D8F9C80046C9) /* 968 */, CONST64(0x80CF9BEDE388FB63) /* 969 */, + CONST64(0x1881539A116CF19E) /* 970 */, CONST64(0x5103F3F76BD52457) /* 971 */, + CONST64(0x15B7E6F5AE47F7A8) /* 972 */, CONST64(0xDBD7C6DED47E9CCF) /* 973 */, + CONST64(0x44E55C410228BB1A) /* 974 */, CONST64(0xB647D4255EDB4E99) /* 975 */, + CONST64(0x5D11882BB8AAFC30) /* 976 */, CONST64(0xF5098BBB29D3212A) /* 977 */, + CONST64(0x8FB5EA14E90296B3) /* 978 */, CONST64(0x677B942157DD025A) /* 979 */, + CONST64(0xFB58E7C0A390ACB5) /* 980 */, CONST64(0x89D3674C83BD4A01) /* 981 */, + CONST64(0x9E2DA4DF4BF3B93B) /* 982 */, CONST64(0xFCC41E328CAB4829) /* 983 */, + CONST64(0x03F38C96BA582C52) /* 984 */, CONST64(0xCAD1BDBD7FD85DB2) /* 985 */, + CONST64(0xBBB442C16082AE83) /* 986 */, CONST64(0xB95FE86BA5DA9AB0) /* 987 */, + CONST64(0xB22E04673771A93F) /* 988 */, CONST64(0x845358C9493152D8) /* 989 */, + CONST64(0xBE2A488697B4541E) /* 990 */, CONST64(0x95A2DC2DD38E6966) /* 991 */, + CONST64(0xC02C11AC923C852B) /* 992 */, CONST64(0x2388B1990DF2A87B) /* 993 */, + CONST64(0x7C8008FA1B4F37BE) /* 994 */, CONST64(0x1F70D0C84D54E503) /* 995 */, + CONST64(0x5490ADEC7ECE57D4) /* 996 */, CONST64(0x002B3C27D9063A3A) /* 997 */, + CONST64(0x7EAEA3848030A2BF) /* 998 */, CONST64(0xC602326DED2003C0) /* 999 */, + CONST64(0x83A7287D69A94086) /* 1000 */, CONST64(0xC57A5FCB30F57A8A) /* 1001 */, + CONST64(0xB56844E479EBE779) /* 1002 */, CONST64(0xA373B40F05DCBCE9) /* 1003 */, + CONST64(0xD71A786E88570EE2) /* 1004 */, CONST64(0x879CBACDBDE8F6A0) /* 1005 */, + CONST64(0x976AD1BCC164A32F) /* 1006 */, CONST64(0xAB21E25E9666D78B) /* 1007 */, + CONST64(0x901063AAE5E5C33C) /* 1008 */, CONST64(0x9818B34448698D90) /* 1009 */, + CONST64(0xE36487AE3E1E8ABB) /* 1010 */, CONST64(0xAFBDF931893BDCB4) /* 1011 */, + CONST64(0x6345A0DC5FBBD519) /* 1012 */, CONST64(0x8628FE269B9465CA) /* 1013 */, + CONST64(0x1E5D01603F9C51EC) /* 1014 */, CONST64(0x4DE44006A15049B7) /* 1015 */, + CONST64(0xBF6C70E5F776CBB1) /* 1016 */, CONST64(0x411218F2EF552BED) /* 1017 */, + CONST64(0xCB0C0708705A36A3) /* 1018 */, CONST64(0xE74D14754F986044) /* 1019 */, + CONST64(0xCD56D9430EA8280E) /* 1020 */, CONST64(0xC12591D7535F5065) /* 1021 */, + CONST64(0xC83223F1720AEF96) /* 1022 */, CONST64(0xC3A0396F7363A51F) /* 1023 */}; + +/* one round of the hash function */ +LTC_INLINE static void tiger_round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, int mul) +{ + ulong64 tmp; + tmp = (*c ^= x); + *a -= t1[LTC_BYTE(tmp, 0)] ^ t2[LTC_BYTE(tmp, 2)] ^ t3[LTC_BYTE(tmp, 4)] ^ t4[LTC_BYTE(tmp, 6)]; + tmp = (*b += t4[LTC_BYTE(tmp, 1)] ^ t3[LTC_BYTE(tmp, 3)] ^ t2[LTC_BYTE(tmp,5)] ^ t1[LTC_BYTE(tmp,7)]); + switch (mul) { + case 5: *b = (tmp << 2) + tmp; break; + case 7: *b = (tmp << 3) - tmp; break; + case 9: *b = (tmp << 3) + tmp; break; + } +} + +/* one complete pass */ +static void s_pass(ulong64 *a, ulong64 *b, ulong64 *c, const ulong64 *x, int mul) +{ + tiger_round(a,b,c,x[0],mul); + tiger_round(b,c,a,x[1],mul); + tiger_round(c,a,b,x[2],mul); + tiger_round(a,b,c,x[3],mul); + tiger_round(b,c,a,x[4],mul); + tiger_round(c,a,b,x[5],mul); + tiger_round(a,b,c,x[6],mul); + tiger_round(b,c,a,x[7],mul); +} + +/* The key mixing schedule */ +static void s_key_schedule(ulong64 *x) +{ + x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5); + x[1] ^= x[0]; + x[2] += x[1]; + x[3] -= x[2] ^ ((~x[1])<<19); + x[4] ^= x[3]; + x[5] += x[4]; + x[6] -= x[5] ^ ((~x[4])>>23); + x[7] ^= x[6]; + x[0] += x[7]; + x[1] -= x[0] ^ ((~x[7])<<19); + x[2] ^= x[1]; + x[3] += x[2]; + x[4] -= x[3] ^ ((~x[2])>>23); + x[5] ^= x[4]; + x[6] += x[5]; + x[7] -= x[6] ^ CONST64(0x0123456789ABCDEF); +} + +#ifdef LTC_CLEAN_STACK +static int ss_tiger_compress(hash_state *md, const unsigned char *buf) +#else +static int s_tiger_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong64 a, b, c, x[8]; + unsigned long i; + + /* load words */ + for (i = 0; i < 8; i++) { + LOAD64L(x[i],&buf[8*i]); + } + a = md->tiger.state[0]; + b = md->tiger.state[1]; + c = md->tiger.state[2]; + + s_pass(&a,&b,&c,x,5); + s_key_schedule(x); + s_pass(&c,&a,&b,x,7); + s_key_schedule(x); + s_pass(&b,&c,&a,x,9); + + /* store state */ + md->tiger.state[0] = a ^ md->tiger.state[0]; + md->tiger.state[1] = b - md->tiger.state[1]; + md->tiger.state[2] = c + md->tiger.state[2]; + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +static int s_tiger_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_tiger_compress(md, buf); + burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long)); + return err; +} +#endif + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int tiger_init(hash_state *md) +{ + LTC_ARGCHK(md != NULL); + md->tiger.state[0] = CONST64(0x0123456789ABCDEF); + md->tiger.state[1] = CONST64(0xFEDCBA9876543210); + md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187); + md->tiger.curlen = 0; + md->tiger.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(tiger_process, s_tiger_compress, tiger, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (24 bytes) + @return CRYPT_OK if successful +*/ +int tiger_done(hash_state * md, unsigned char *out) +{ + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->tiger.curlen >= sizeof(md->tiger.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->tiger.length += md->tiger.curlen * 8; + + /* append the '1' bit */ + md->tiger.buf[md->tiger.curlen++] = (unsigned char)0x01; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. */ + if (md->tiger.curlen > 56) { + while (md->tiger.curlen < 64) { + md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; + } + s_tiger_compress(md, md->tiger.buf); + md->tiger.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->tiger.curlen < 56) { + md->tiger.buf[md->tiger.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64L(md->tiger.length, md->tiger.buf+56); + s_tiger_compress(md, md->tiger.buf); + + /* copy output */ + STORE64L(md->tiger.state[0], &out[0]); + STORE64L(md->tiger.state[1], &out[8]); + STORE64L(md->tiger.state[2], &out[16]); +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(hash_state)); +#endif + + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int tiger_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + const char *msg; + unsigned char hash[24]; + } tests[] = { + { "", + { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24, + 0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16, + 0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 } + }, + { "abc", + { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2, + 0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52, + 0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 } + }, + { "Tiger", + { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f, + 0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27, + 0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87, + 0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47, + 0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-", + { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00, + 0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76, + 0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 } + }, + }; + + int i; + unsigned char tmp[24]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + tiger_init(&md); + tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg)); + tiger_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "TIGER", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + +#endif + +/* +Hash of "": + 24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A +Hash of "abc": + F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951 +Hash of "Tiger": + 9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF +Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": + 87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386 +Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789": + 467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197 +Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham": + 0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303 +Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.": + EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193 +Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.": + 3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC +Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-": + 00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4 +*/ + + + diff --git a/deps/libtomcrypt/src/hashes/whirl/whirl.c b/deps/libtomcrypt/src/hashes/whirl/whirl.c new file mode 100644 index 0000000..da7db9c --- /dev/null +++ b/deps/libtomcrypt/src/hashes/whirl/whirl.c @@ -0,0 +1,296 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file whirl.c + LTC_WHIRLPOOL (using their new sbox) hash function by Tom St Denis +*/ + +#include "tomcrypt_private.h" + +#ifdef LTC_WHIRLPOOL + +const struct ltc_hash_descriptor whirlpool_desc = +{ + "whirlpool", + 11, + 64, + 64, + + /* OID */ + { 1, 0, 10118, 3, 0, 55 }, + 6, + + &whirlpool_init, + &whirlpool_process, + &whirlpool_done, + &whirlpool_test, + NULL +}; + +/* the sboxes */ +#define LTC_WHIRLTAB_C +#include "whirltab.c" + +/* get a_{i,j} */ +#define GB(a,i,j) ((a[(i) & 7] >> (8 * (j))) & 255) + +/* shortcut macro to perform three functions at once */ +#define theta_pi_gamma(a, i) \ + (SB0(GB(a, i-0, 7)) ^ \ + SB1(GB(a, i-1, 6)) ^ \ + SB2(GB(a, i-2, 5)) ^ \ + SB3(GB(a, i-3, 4)) ^ \ + SB4(GB(a, i-4, 3)) ^ \ + SB5(GB(a, i-5, 2)) ^ \ + SB6(GB(a, i-6, 1)) ^ \ + SB7(GB(a, i-7, 0))) + +#ifdef LTC_CLEAN_STACK +static int ss_whirlpool_compress(hash_state *md, const unsigned char *buf) +#else +static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) +#endif +{ + ulong64 K[2][8], T[3][8]; + int x, y; + + /* load the block/state */ + for (x = 0; x < 8; x++) { + K[0][x] = md->whirlpool.state[x]; + + LOAD64H(T[0][x], buf + (8 * x)); + T[2][x] = T[0][x]; + T[0][x] ^= K[0][x]; + } + + /* do rounds 1..10 */ + for (x = 0; x < 10; x += 2) { + /* odd round */ + /* apply main transform to K[0] into K[1] */ + for (y = 0; y < 8; y++) { + K[1][y] = theta_pi_gamma(K[0], y); + } + /* xor the constant */ + K[1][0] ^= cont[x]; + + /* apply main transform to T[0] into T[1] */ + for (y = 0; y < 8; y++) { + T[1][y] = theta_pi_gamma(T[0], y) ^ K[1][y]; + } + + /* even round */ + /* apply main transform to K[1] into K[0] */ + for (y = 0; y < 8; y++) { + K[0][y] = theta_pi_gamma(K[1], y); + } + /* xor the constant */ + K[0][0] ^= cont[x+1]; + + /* apply main transform to T[1] into T[0] */ + for (y = 0; y < 8; y++) { + T[0][y] = theta_pi_gamma(T[1], y) ^ K[0][y]; + } + } + + /* store state */ + for (x = 0; x < 8; x++) { + md->whirlpool.state[x] ^= T[0][x] ^ T[2][x]; + } + + return CRYPT_OK; +} + + +#ifdef LTC_CLEAN_STACK +static int s_whirlpool_compress(hash_state *md, const unsigned char *buf) +{ + int err; + err = ss_whirlpool_compress(md, buf); + burn_stack((5 * 8 * sizeof(ulong64)) + (2 * sizeof(int))); + return err; +} +#endif + + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int whirlpool_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + zeromem(&md->whirlpool, sizeof(md->whirlpool)); + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(whirlpool_process, s_whirlpool_compress, whirlpool, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (64 bytes) + @return CRYPT_OK if successful +*/ +int whirlpool_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->whirlpool.curlen >= sizeof(md->whirlpool.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->whirlpool.length += md->whirlpool.curlen * 8; + + /* append the '1' bit */ + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 32 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->whirlpool.curlen > 32) { + while (md->whirlpool.curlen < 64) { + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; + } + s_whirlpool_compress(md, md->whirlpool.buf); + md->whirlpool.curlen = 0; + } + + /* pad upto 56 bytes of zeroes (should be 32 but we only support 64-bit lengths) */ + while (md->whirlpool.curlen < 56) { + md->whirlpool.buf[md->whirlpool.curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->whirlpool.length, md->whirlpool.buf+56); + s_whirlpool_compress(md, md->whirlpool.buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE64H(md->whirlpool.state[i], out+(8*i)); + } +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(*md)); +#endif + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int whirlpool_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + static const struct { + int len; + unsigned char msg[128], hash[64]; + } tests[] = { + + /* NULL Message */ +{ + 0, + { 0x00 }, + { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, + 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, + 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 } +}, + + + /* 448-bits of 0 bits */ +{ + + 56, + { 0x00 }, + { 0x0B, 0x3F, 0x53, 0x78, 0xEB, 0xED, 0x2B, 0xF4, 0xD7, 0xBE, 0x3C, 0xFD, 0x81, 0x8C, 0x1B, 0x03, + 0xB6, 0xBB, 0x03, 0xD3, 0x46, 0x94, 0x8B, 0x04, 0xF4, 0xF4, 0x0C, 0x72, 0x6F, 0x07, 0x58, 0x70, + 0x2A, 0x0F, 0x1E, 0x22, 0x58, 0x80, 0xE3, 0x8D, 0xD5, 0xF6, 0xED, 0x6D, 0xE9, 0xB1, 0xE9, 0x61, + 0xE4, 0x9F, 0xC1, 0x31, 0x8D, 0x7C, 0xB7, 0x48, 0x22, 0xF3, 0xD0, 0xE2, 0xE9, 0xA7, 0xE7, 0xB0 } +}, + + /* 520-bits of 0 bits */ +{ + 65, + { 0x00 }, + { 0x85, 0xE1, 0x24, 0xC4, 0x41, 0x5B, 0xCF, 0x43, 0x19, 0x54, 0x3E, 0x3A, 0x63, 0xFF, 0x57, 0x1D, + 0x09, 0x35, 0x4C, 0xEE, 0xBE, 0xE1, 0xE3, 0x25, 0x30, 0x8C, 0x90, 0x69, 0xF4, 0x3E, 0x2A, 0xE4, + 0xD0, 0xE5, 0x1D, 0x4E, 0xB1, 0xE8, 0x64, 0x28, 0x70, 0x19, 0x4E, 0x95, 0x30, 0xD8, 0xD8, 0xAF, + 0x65, 0x89, 0xD1, 0xBF, 0x69, 0x49, 0xDD, 0xF9, 0x0A, 0x7F, 0x12, 0x08, 0x62, 0x37, 0x95, 0xB9 } +}, + + /* 512-bits, leading set */ +{ + 64, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x10, 0x3E, 0x00, 0x55, 0xA9, 0xB0, 0x90, 0xE1, 0x1C, 0x8F, 0xDD, 0xEB, 0xBA, 0x06, 0xC0, 0x5A, + 0xCE, 0x8B, 0x64, 0xB8, 0x96, 0x12, 0x8F, 0x6E, 0xED, 0x30, 0x71, 0xFC, 0xF3, 0xDC, 0x16, 0x94, + 0x67, 0x78, 0xE0, 0x72, 0x23, 0x23, 0x3F, 0xD1, 0x80, 0xFC, 0x40, 0xCC, 0xDB, 0x84, 0x30, 0xA6, + 0x40, 0xE3, 0x76, 0x34, 0x27, 0x1E, 0x65, 0x5C, 0xA1, 0x67, 0x4E, 0xBF, 0xF5, 0x07, 0xF8, 0xCB } +}, + + /* 512-bits, leading set of second byte */ +{ + 64, + { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x35, 0x7B, 0x42, 0xEA, 0x79, 0xBC, 0x97, 0x86, 0x97, 0x5A, 0x3C, 0x44, 0x70, 0xAA, 0xB2, 0x3E, + 0x62, 0x29, 0x79, 0x7B, 0xAD, 0xBD, 0x54, 0x36, 0x5B, 0x54, 0x96, 0xE5, 0x5D, 0x9D, 0xD7, 0x9F, + 0xE9, 0x62, 0x4F, 0xB4, 0x22, 0x66, 0x93, 0x0A, 0x62, 0x8E, 0xD4, 0xDB, 0x08, 0xF9, 0xDD, 0x35, + 0xEF, 0x1B, 0xE1, 0x04, 0x53, 0xFC, 0x18, 0xF4, 0x2C, 0x7F, 0x5E, 0x1F, 0x9B, 0xAE, 0x55, 0xE0 } +}, + + /* 512-bits, leading set of last byte */ +{ + 64, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0x8B, 0x39, 0x04, 0xDD, 0x19, 0x81, 0x41, 0x26, 0xFD, 0x02, 0x74, 0xAB, 0x49, 0xC5, 0x97, 0xF6, + 0xD7, 0x75, 0x33, 0x52, 0xA2, 0xDD, 0x91, 0xFD, 0x8F, 0x9F, 0x54, 0x05, 0x4C, 0x54, 0xBF, 0x0F, + 0x06, 0xDB, 0x4F, 0xF7, 0x08, 0xA3, 0xA2, 0x8B, 0xC3, 0x7A, 0x92, 0x1E, 0xEE, 0x11, 0xED, 0x7B, + 0x6A, 0x53, 0x79, 0x32, 0xCC, 0x5E, 0x94, 0xEE, 0x1E, 0xA6, 0x57, 0x60, 0x7E, 0x36, 0xC9, 0xF7 } +}, + +}; + + int i; + unsigned char tmp[64]; + hash_state md; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + whirlpool_init(&md); + whirlpool_process(&md, (unsigned char *)tests[i].msg, tests[i].len); + whirlpool_done(&md, tmp); + if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "WHIRLPOOL", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; + #endif +} + + +#endif + diff --git a/deps/libtomcrypt/src/hashes/whirl/whirltab.c b/deps/libtomcrypt/src/hashes/whirl/whirltab.c new file mode 100644 index 0000000..42ecae4 --- /dev/null +++ b/deps/libtomcrypt/src/hashes/whirl/whirltab.c @@ -0,0 +1,586 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file whirltab.c + LTC_WHIRLPOOL tables, Tom St Denis +*/ + +#ifdef LTC_WHIRLTAB_C + +static const ulong64 sbox0[] = { +CONST64(0x18186018c07830d8), CONST64(0x23238c2305af4626), CONST64(0xc6c63fc67ef991b8), CONST64(0xe8e887e8136fcdfb), +CONST64(0x878726874ca113cb), CONST64(0xb8b8dab8a9626d11), CONST64(0x0101040108050209), CONST64(0x4f4f214f426e9e0d), +CONST64(0x3636d836adee6c9b), CONST64(0xa6a6a2a6590451ff), CONST64(0xd2d26fd2debdb90c), CONST64(0xf5f5f3f5fb06f70e), +CONST64(0x7979f979ef80f296), CONST64(0x6f6fa16f5fcede30), CONST64(0x91917e91fcef3f6d), CONST64(0x52525552aa07a4f8), +CONST64(0x60609d6027fdc047), CONST64(0xbcbccabc89766535), CONST64(0x9b9b569baccd2b37), CONST64(0x8e8e028e048c018a), +CONST64(0xa3a3b6a371155bd2), CONST64(0x0c0c300c603c186c), CONST64(0x7b7bf17bff8af684), CONST64(0x3535d435b5e16a80), +CONST64(0x1d1d741de8693af5), CONST64(0xe0e0a7e05347ddb3), CONST64(0xd7d77bd7f6acb321), CONST64(0xc2c22fc25eed999c), +CONST64(0x2e2eb82e6d965c43), CONST64(0x4b4b314b627a9629), CONST64(0xfefedffea321e15d), CONST64(0x575741578216aed5), +CONST64(0x15155415a8412abd), CONST64(0x7777c1779fb6eee8), CONST64(0x3737dc37a5eb6e92), CONST64(0xe5e5b3e57b56d79e), +CONST64(0x9f9f469f8cd92313), CONST64(0xf0f0e7f0d317fd23), CONST64(0x4a4a354a6a7f9420), CONST64(0xdada4fda9e95a944), +CONST64(0x58587d58fa25b0a2), CONST64(0xc9c903c906ca8fcf), CONST64(0x2929a429558d527c), CONST64(0x0a0a280a5022145a), +CONST64(0xb1b1feb1e14f7f50), CONST64(0xa0a0baa0691a5dc9), CONST64(0x6b6bb16b7fdad614), CONST64(0x85852e855cab17d9), +CONST64(0xbdbdcebd8173673c), CONST64(0x5d5d695dd234ba8f), CONST64(0x1010401080502090), CONST64(0xf4f4f7f4f303f507), +CONST64(0xcbcb0bcb16c08bdd), CONST64(0x3e3ef83eedc67cd3), CONST64(0x0505140528110a2d), CONST64(0x676781671fe6ce78), +CONST64(0xe4e4b7e47353d597), CONST64(0x27279c2725bb4e02), CONST64(0x4141194132588273), CONST64(0x8b8b168b2c9d0ba7), +CONST64(0xa7a7a6a7510153f6), CONST64(0x7d7de97dcf94fab2), CONST64(0x95956e95dcfb3749), CONST64(0xd8d847d88e9fad56), +CONST64(0xfbfbcbfb8b30eb70), CONST64(0xeeee9fee2371c1cd), CONST64(0x7c7ced7cc791f8bb), CONST64(0x6666856617e3cc71), +CONST64(0xdddd53dda68ea77b), CONST64(0x17175c17b84b2eaf), CONST64(0x4747014702468e45), CONST64(0x9e9e429e84dc211a), +CONST64(0xcaca0fca1ec589d4), CONST64(0x2d2db42d75995a58), CONST64(0xbfbfc6bf9179632e), CONST64(0x07071c07381b0e3f), +CONST64(0xadad8ead012347ac), CONST64(0x5a5a755aea2fb4b0), CONST64(0x838336836cb51bef), CONST64(0x3333cc3385ff66b6), +CONST64(0x636391633ff2c65c), CONST64(0x02020802100a0412), CONST64(0xaaaa92aa39384993), CONST64(0x7171d971afa8e2de), +CONST64(0xc8c807c80ecf8dc6), CONST64(0x19196419c87d32d1), CONST64(0x494939497270923b), CONST64(0xd9d943d9869aaf5f), +CONST64(0xf2f2eff2c31df931), CONST64(0xe3e3abe34b48dba8), CONST64(0x5b5b715be22ab6b9), CONST64(0x88881a8834920dbc), +CONST64(0x9a9a529aa4c8293e), CONST64(0x262698262dbe4c0b), CONST64(0x3232c8328dfa64bf), CONST64(0xb0b0fab0e94a7d59), +CONST64(0xe9e983e91b6acff2), CONST64(0x0f0f3c0f78331e77), CONST64(0xd5d573d5e6a6b733), CONST64(0x80803a8074ba1df4), +CONST64(0xbebec2be997c6127), CONST64(0xcdcd13cd26de87eb), CONST64(0x3434d034bde46889), CONST64(0x48483d487a759032), +CONST64(0xffffdbffab24e354), CONST64(0x7a7af57af78ff48d), CONST64(0x90907a90f4ea3d64), CONST64(0x5f5f615fc23ebe9d), +CONST64(0x202080201da0403d), CONST64(0x6868bd6867d5d00f), CONST64(0x1a1a681ad07234ca), CONST64(0xaeae82ae192c41b7), +CONST64(0xb4b4eab4c95e757d), CONST64(0x54544d549a19a8ce), CONST64(0x93937693ece53b7f), CONST64(0x222288220daa442f), +CONST64(0x64648d6407e9c863), CONST64(0xf1f1e3f1db12ff2a), CONST64(0x7373d173bfa2e6cc), CONST64(0x12124812905a2482), +CONST64(0x40401d403a5d807a), CONST64(0x0808200840281048), CONST64(0xc3c32bc356e89b95), CONST64(0xecec97ec337bc5df), +CONST64(0xdbdb4bdb9690ab4d), CONST64(0xa1a1bea1611f5fc0), CONST64(0x8d8d0e8d1c830791), CONST64(0x3d3df43df5c97ac8), +CONST64(0x97976697ccf1335b), CONST64(0x0000000000000000), CONST64(0xcfcf1bcf36d483f9), CONST64(0x2b2bac2b4587566e), +CONST64(0x7676c57697b3ece1), CONST64(0x8282328264b019e6), CONST64(0xd6d67fd6fea9b128), CONST64(0x1b1b6c1bd87736c3), +CONST64(0xb5b5eeb5c15b7774), CONST64(0xafaf86af112943be), CONST64(0x6a6ab56a77dfd41d), CONST64(0x50505d50ba0da0ea), +CONST64(0x45450945124c8a57), CONST64(0xf3f3ebf3cb18fb38), CONST64(0x3030c0309df060ad), CONST64(0xefef9bef2b74c3c4), +CONST64(0x3f3ffc3fe5c37eda), CONST64(0x55554955921caac7), CONST64(0xa2a2b2a2791059db), CONST64(0xeaea8fea0365c9e9), +CONST64(0x656589650fecca6a), CONST64(0xbabad2bab9686903), CONST64(0x2f2fbc2f65935e4a), CONST64(0xc0c027c04ee79d8e), +CONST64(0xdede5fdebe81a160), CONST64(0x1c1c701ce06c38fc), CONST64(0xfdfdd3fdbb2ee746), CONST64(0x4d4d294d52649a1f), +CONST64(0x92927292e4e03976), CONST64(0x7575c9758fbceafa), CONST64(0x06061806301e0c36), CONST64(0x8a8a128a249809ae), +CONST64(0xb2b2f2b2f940794b), CONST64(0xe6e6bfe66359d185), CONST64(0x0e0e380e70361c7e), CONST64(0x1f1f7c1ff8633ee7), +CONST64(0x6262956237f7c455), CONST64(0xd4d477d4eea3b53a), CONST64(0xa8a89aa829324d81), CONST64(0x96966296c4f43152), +CONST64(0xf9f9c3f99b3aef62), CONST64(0xc5c533c566f697a3), CONST64(0x2525942535b14a10), CONST64(0x59597959f220b2ab), +CONST64(0x84842a8454ae15d0), CONST64(0x7272d572b7a7e4c5), CONST64(0x3939e439d5dd72ec), CONST64(0x4c4c2d4c5a619816), +CONST64(0x5e5e655eca3bbc94), CONST64(0x7878fd78e785f09f), CONST64(0x3838e038ddd870e5), CONST64(0x8c8c0a8c14860598), +CONST64(0xd1d163d1c6b2bf17), CONST64(0xa5a5aea5410b57e4), CONST64(0xe2e2afe2434dd9a1), CONST64(0x616199612ff8c24e), +CONST64(0xb3b3f6b3f1457b42), CONST64(0x2121842115a54234), CONST64(0x9c9c4a9c94d62508), CONST64(0x1e1e781ef0663cee), +CONST64(0x4343114322528661), CONST64(0xc7c73bc776fc93b1), CONST64(0xfcfcd7fcb32be54f), CONST64(0x0404100420140824), +CONST64(0x51515951b208a2e3), CONST64(0x99995e99bcc72f25), CONST64(0x6d6da96d4fc4da22), CONST64(0x0d0d340d68391a65), +CONST64(0xfafacffa8335e979), CONST64(0xdfdf5bdfb684a369), CONST64(0x7e7ee57ed79bfca9), CONST64(0x242490243db44819), +CONST64(0x3b3bec3bc5d776fe), CONST64(0xabab96ab313d4b9a), CONST64(0xcece1fce3ed181f0), CONST64(0x1111441188552299), +CONST64(0x8f8f068f0c890383), CONST64(0x4e4e254e4a6b9c04), CONST64(0xb7b7e6b7d1517366), CONST64(0xebeb8beb0b60cbe0), +CONST64(0x3c3cf03cfdcc78c1), CONST64(0x81813e817cbf1ffd), CONST64(0x94946a94d4fe3540), CONST64(0xf7f7fbf7eb0cf31c), +CONST64(0xb9b9deb9a1676f18), CONST64(0x13134c13985f268b), CONST64(0x2c2cb02c7d9c5851), CONST64(0xd3d36bd3d6b8bb05), +CONST64(0xe7e7bbe76b5cd38c), CONST64(0x6e6ea56e57cbdc39), CONST64(0xc4c437c46ef395aa), CONST64(0x03030c03180f061b), +CONST64(0x565645568a13acdc), CONST64(0x44440d441a49885e), CONST64(0x7f7fe17fdf9efea0), CONST64(0xa9a99ea921374f88), +CONST64(0x2a2aa82a4d825467), CONST64(0xbbbbd6bbb16d6b0a), CONST64(0xc1c123c146e29f87), CONST64(0x53535153a202a6f1), +CONST64(0xdcdc57dcae8ba572), CONST64(0x0b0b2c0b58271653), CONST64(0x9d9d4e9d9cd32701), CONST64(0x6c6cad6c47c1d82b), +CONST64(0x3131c43195f562a4), CONST64(0x7474cd7487b9e8f3), CONST64(0xf6f6fff6e309f115), CONST64(0x464605460a438c4c), +CONST64(0xacac8aac092645a5), CONST64(0x89891e893c970fb5), CONST64(0x14145014a04428b4), CONST64(0xe1e1a3e15b42dfba), +CONST64(0x16165816b04e2ca6), CONST64(0x3a3ae83acdd274f7), CONST64(0x6969b9696fd0d206), CONST64(0x09092409482d1241), +CONST64(0x7070dd70a7ade0d7), CONST64(0xb6b6e2b6d954716f), CONST64(0xd0d067d0ceb7bd1e), CONST64(0xeded93ed3b7ec7d6), +CONST64(0xcccc17cc2edb85e2), CONST64(0x424215422a578468), CONST64(0x98985a98b4c22d2c), CONST64(0xa4a4aaa4490e55ed), +CONST64(0x2828a0285d885075), CONST64(0x5c5c6d5cda31b886), CONST64(0xf8f8c7f8933fed6b), CONST64(0x8686228644a411c2) +}; + +#ifdef LTC_SMALL_CODE + +#define SB0(x) sbox0[x] +#define SB1(x) ROR64c(sbox0[x], 8) +#define SB2(x) ROR64c(sbox0[x], 16) +#define SB3(x) ROR64c(sbox0[x], 24) +#define SB4(x) ROR64c(sbox0[x], 32) +#define SB5(x) ROR64c(sbox0[x], 40) +#define SB6(x) ROR64c(sbox0[x], 48) +#define SB7(x) ROR64c(sbox0[x], 56) + +#else + +#define SB0(x) sbox0[x] +#define SB1(x) sbox1[x] +#define SB2(x) sbox2[x] +#define SB3(x) sbox3[x] +#define SB4(x) sbox4[x] +#define SB5(x) sbox5[x] +#define SB6(x) sbox6[x] +#define SB7(x) sbox7[x] + + +static const ulong64 sbox1[] = { +CONST64(0xd818186018c07830), CONST64(0x2623238c2305af46), CONST64(0xb8c6c63fc67ef991), CONST64(0xfbe8e887e8136fcd), +CONST64(0xcb878726874ca113), CONST64(0x11b8b8dab8a9626d), CONST64(0x0901010401080502), CONST64(0x0d4f4f214f426e9e), +CONST64(0x9b3636d836adee6c), CONST64(0xffa6a6a2a6590451), CONST64(0x0cd2d26fd2debdb9), CONST64(0x0ef5f5f3f5fb06f7), +CONST64(0x967979f979ef80f2), CONST64(0x306f6fa16f5fcede), CONST64(0x6d91917e91fcef3f), CONST64(0xf852525552aa07a4), +CONST64(0x4760609d6027fdc0), CONST64(0x35bcbccabc897665), CONST64(0x379b9b569baccd2b), CONST64(0x8a8e8e028e048c01), +CONST64(0xd2a3a3b6a371155b), CONST64(0x6c0c0c300c603c18), CONST64(0x847b7bf17bff8af6), CONST64(0x803535d435b5e16a), +CONST64(0xf51d1d741de8693a), CONST64(0xb3e0e0a7e05347dd), CONST64(0x21d7d77bd7f6acb3), CONST64(0x9cc2c22fc25eed99), +CONST64(0x432e2eb82e6d965c), CONST64(0x294b4b314b627a96), CONST64(0x5dfefedffea321e1), CONST64(0xd5575741578216ae), +CONST64(0xbd15155415a8412a), CONST64(0xe87777c1779fb6ee), CONST64(0x923737dc37a5eb6e), CONST64(0x9ee5e5b3e57b56d7), +CONST64(0x139f9f469f8cd923), CONST64(0x23f0f0e7f0d317fd), CONST64(0x204a4a354a6a7f94), CONST64(0x44dada4fda9e95a9), +CONST64(0xa258587d58fa25b0), CONST64(0xcfc9c903c906ca8f), CONST64(0x7c2929a429558d52), CONST64(0x5a0a0a280a502214), +CONST64(0x50b1b1feb1e14f7f), CONST64(0xc9a0a0baa0691a5d), CONST64(0x146b6bb16b7fdad6), CONST64(0xd985852e855cab17), +CONST64(0x3cbdbdcebd817367), CONST64(0x8f5d5d695dd234ba), CONST64(0x9010104010805020), CONST64(0x07f4f4f7f4f303f5), +CONST64(0xddcbcb0bcb16c08b), CONST64(0xd33e3ef83eedc67c), CONST64(0x2d0505140528110a), CONST64(0x78676781671fe6ce), +CONST64(0x97e4e4b7e47353d5), CONST64(0x0227279c2725bb4e), CONST64(0x7341411941325882), CONST64(0xa78b8b168b2c9d0b), +CONST64(0xf6a7a7a6a7510153), CONST64(0xb27d7de97dcf94fa), CONST64(0x4995956e95dcfb37), CONST64(0x56d8d847d88e9fad), +CONST64(0x70fbfbcbfb8b30eb), CONST64(0xcdeeee9fee2371c1), CONST64(0xbb7c7ced7cc791f8), CONST64(0x716666856617e3cc), +CONST64(0x7bdddd53dda68ea7), CONST64(0xaf17175c17b84b2e), CONST64(0x454747014702468e), CONST64(0x1a9e9e429e84dc21), +CONST64(0xd4caca0fca1ec589), CONST64(0x582d2db42d75995a), CONST64(0x2ebfbfc6bf917963), CONST64(0x3f07071c07381b0e), +CONST64(0xacadad8ead012347), CONST64(0xb05a5a755aea2fb4), CONST64(0xef838336836cb51b), CONST64(0xb63333cc3385ff66), +CONST64(0x5c636391633ff2c6), CONST64(0x1202020802100a04), CONST64(0x93aaaa92aa393849), CONST64(0xde7171d971afa8e2), +CONST64(0xc6c8c807c80ecf8d), CONST64(0xd119196419c87d32), CONST64(0x3b49493949727092), CONST64(0x5fd9d943d9869aaf), +CONST64(0x31f2f2eff2c31df9), CONST64(0xa8e3e3abe34b48db), CONST64(0xb95b5b715be22ab6), CONST64(0xbc88881a8834920d), +CONST64(0x3e9a9a529aa4c829), CONST64(0x0b262698262dbe4c), CONST64(0xbf3232c8328dfa64), CONST64(0x59b0b0fab0e94a7d), +CONST64(0xf2e9e983e91b6acf), CONST64(0x770f0f3c0f78331e), CONST64(0x33d5d573d5e6a6b7), CONST64(0xf480803a8074ba1d), +CONST64(0x27bebec2be997c61), CONST64(0xebcdcd13cd26de87), CONST64(0x893434d034bde468), CONST64(0x3248483d487a7590), +CONST64(0x54ffffdbffab24e3), CONST64(0x8d7a7af57af78ff4), CONST64(0x6490907a90f4ea3d), CONST64(0x9d5f5f615fc23ebe), +CONST64(0x3d202080201da040), CONST64(0x0f6868bd6867d5d0), CONST64(0xca1a1a681ad07234), CONST64(0xb7aeae82ae192c41), +CONST64(0x7db4b4eab4c95e75), CONST64(0xce54544d549a19a8), CONST64(0x7f93937693ece53b), CONST64(0x2f222288220daa44), +CONST64(0x6364648d6407e9c8), CONST64(0x2af1f1e3f1db12ff), CONST64(0xcc7373d173bfa2e6), CONST64(0x8212124812905a24), +CONST64(0x7a40401d403a5d80), CONST64(0x4808082008402810), CONST64(0x95c3c32bc356e89b), CONST64(0xdfecec97ec337bc5), +CONST64(0x4ddbdb4bdb9690ab), CONST64(0xc0a1a1bea1611f5f), CONST64(0x918d8d0e8d1c8307), CONST64(0xc83d3df43df5c97a), +CONST64(0x5b97976697ccf133), CONST64(0x0000000000000000), CONST64(0xf9cfcf1bcf36d483), CONST64(0x6e2b2bac2b458756), +CONST64(0xe17676c57697b3ec), CONST64(0xe68282328264b019), CONST64(0x28d6d67fd6fea9b1), CONST64(0xc31b1b6c1bd87736), +CONST64(0x74b5b5eeb5c15b77), CONST64(0xbeafaf86af112943), CONST64(0x1d6a6ab56a77dfd4), CONST64(0xea50505d50ba0da0), +CONST64(0x5745450945124c8a), CONST64(0x38f3f3ebf3cb18fb), CONST64(0xad3030c0309df060), CONST64(0xc4efef9bef2b74c3), +CONST64(0xda3f3ffc3fe5c37e), CONST64(0xc755554955921caa), CONST64(0xdba2a2b2a2791059), CONST64(0xe9eaea8fea0365c9), +CONST64(0x6a656589650fecca), CONST64(0x03babad2bab96869), CONST64(0x4a2f2fbc2f65935e), CONST64(0x8ec0c027c04ee79d), +CONST64(0x60dede5fdebe81a1), CONST64(0xfc1c1c701ce06c38), CONST64(0x46fdfdd3fdbb2ee7), CONST64(0x1f4d4d294d52649a), +CONST64(0x7692927292e4e039), CONST64(0xfa7575c9758fbcea), CONST64(0x3606061806301e0c), CONST64(0xae8a8a128a249809), +CONST64(0x4bb2b2f2b2f94079), CONST64(0x85e6e6bfe66359d1), CONST64(0x7e0e0e380e70361c), CONST64(0xe71f1f7c1ff8633e), +CONST64(0x556262956237f7c4), CONST64(0x3ad4d477d4eea3b5), CONST64(0x81a8a89aa829324d), CONST64(0x5296966296c4f431), +CONST64(0x62f9f9c3f99b3aef), CONST64(0xa3c5c533c566f697), CONST64(0x102525942535b14a), CONST64(0xab59597959f220b2), +CONST64(0xd084842a8454ae15), CONST64(0xc57272d572b7a7e4), CONST64(0xec3939e439d5dd72), CONST64(0x164c4c2d4c5a6198), +CONST64(0x945e5e655eca3bbc), CONST64(0x9f7878fd78e785f0), CONST64(0xe53838e038ddd870), CONST64(0x988c8c0a8c148605), +CONST64(0x17d1d163d1c6b2bf), CONST64(0xe4a5a5aea5410b57), CONST64(0xa1e2e2afe2434dd9), CONST64(0x4e616199612ff8c2), +CONST64(0x42b3b3f6b3f1457b), CONST64(0x342121842115a542), CONST64(0x089c9c4a9c94d625), CONST64(0xee1e1e781ef0663c), +CONST64(0x6143431143225286), CONST64(0xb1c7c73bc776fc93), CONST64(0x4ffcfcd7fcb32be5), CONST64(0x2404041004201408), +CONST64(0xe351515951b208a2), CONST64(0x2599995e99bcc72f), CONST64(0x226d6da96d4fc4da), CONST64(0x650d0d340d68391a), +CONST64(0x79fafacffa8335e9), CONST64(0x69dfdf5bdfb684a3), CONST64(0xa97e7ee57ed79bfc), CONST64(0x19242490243db448), +CONST64(0xfe3b3bec3bc5d776), CONST64(0x9aabab96ab313d4b), CONST64(0xf0cece1fce3ed181), CONST64(0x9911114411885522), +CONST64(0x838f8f068f0c8903), CONST64(0x044e4e254e4a6b9c), CONST64(0x66b7b7e6b7d15173), CONST64(0xe0ebeb8beb0b60cb), +CONST64(0xc13c3cf03cfdcc78), CONST64(0xfd81813e817cbf1f), CONST64(0x4094946a94d4fe35), CONST64(0x1cf7f7fbf7eb0cf3), +CONST64(0x18b9b9deb9a1676f), CONST64(0x8b13134c13985f26), CONST64(0x512c2cb02c7d9c58), CONST64(0x05d3d36bd3d6b8bb), +CONST64(0x8ce7e7bbe76b5cd3), CONST64(0x396e6ea56e57cbdc), CONST64(0xaac4c437c46ef395), CONST64(0x1b03030c03180f06), +CONST64(0xdc565645568a13ac), CONST64(0x5e44440d441a4988), CONST64(0xa07f7fe17fdf9efe), CONST64(0x88a9a99ea921374f), +CONST64(0x672a2aa82a4d8254), CONST64(0x0abbbbd6bbb16d6b), CONST64(0x87c1c123c146e29f), CONST64(0xf153535153a202a6), +CONST64(0x72dcdc57dcae8ba5), CONST64(0x530b0b2c0b582716), CONST64(0x019d9d4e9d9cd327), CONST64(0x2b6c6cad6c47c1d8), +CONST64(0xa43131c43195f562), CONST64(0xf37474cd7487b9e8), CONST64(0x15f6f6fff6e309f1), CONST64(0x4c464605460a438c), +CONST64(0xa5acac8aac092645), CONST64(0xb589891e893c970f), CONST64(0xb414145014a04428), CONST64(0xbae1e1a3e15b42df), +CONST64(0xa616165816b04e2c), CONST64(0xf73a3ae83acdd274), CONST64(0x066969b9696fd0d2), CONST64(0x4109092409482d12), +CONST64(0xd77070dd70a7ade0), CONST64(0x6fb6b6e2b6d95471), CONST64(0x1ed0d067d0ceb7bd), CONST64(0xd6eded93ed3b7ec7), +CONST64(0xe2cccc17cc2edb85), CONST64(0x68424215422a5784), CONST64(0x2c98985a98b4c22d), CONST64(0xeda4a4aaa4490e55), +CONST64(0x752828a0285d8850), CONST64(0x865c5c6d5cda31b8), CONST64(0x6bf8f8c7f8933fed), CONST64(0xc28686228644a411) +}; + +static const ulong64 sbox2[] = { +CONST64(0x30d818186018c078), CONST64(0x462623238c2305af), CONST64(0x91b8c6c63fc67ef9), CONST64(0xcdfbe8e887e8136f), +CONST64(0x13cb878726874ca1), CONST64(0x6d11b8b8dab8a962), CONST64(0x0209010104010805), CONST64(0x9e0d4f4f214f426e), +CONST64(0x6c9b3636d836adee), CONST64(0x51ffa6a6a2a65904), CONST64(0xb90cd2d26fd2debd), CONST64(0xf70ef5f5f3f5fb06), +CONST64(0xf2967979f979ef80), CONST64(0xde306f6fa16f5fce), CONST64(0x3f6d91917e91fcef), CONST64(0xa4f852525552aa07), +CONST64(0xc04760609d6027fd), CONST64(0x6535bcbccabc8976), CONST64(0x2b379b9b569baccd), CONST64(0x018a8e8e028e048c), +CONST64(0x5bd2a3a3b6a37115), CONST64(0x186c0c0c300c603c), CONST64(0xf6847b7bf17bff8a), CONST64(0x6a803535d435b5e1), +CONST64(0x3af51d1d741de869), CONST64(0xddb3e0e0a7e05347), CONST64(0xb321d7d77bd7f6ac), CONST64(0x999cc2c22fc25eed), +CONST64(0x5c432e2eb82e6d96), CONST64(0x96294b4b314b627a), CONST64(0xe15dfefedffea321), CONST64(0xaed5575741578216), +CONST64(0x2abd15155415a841), CONST64(0xeee87777c1779fb6), CONST64(0x6e923737dc37a5eb), CONST64(0xd79ee5e5b3e57b56), +CONST64(0x23139f9f469f8cd9), CONST64(0xfd23f0f0e7f0d317), CONST64(0x94204a4a354a6a7f), CONST64(0xa944dada4fda9e95), +CONST64(0xb0a258587d58fa25), CONST64(0x8fcfc9c903c906ca), CONST64(0x527c2929a429558d), CONST64(0x145a0a0a280a5022), +CONST64(0x7f50b1b1feb1e14f), CONST64(0x5dc9a0a0baa0691a), CONST64(0xd6146b6bb16b7fda), CONST64(0x17d985852e855cab), +CONST64(0x673cbdbdcebd8173), CONST64(0xba8f5d5d695dd234), CONST64(0x2090101040108050), CONST64(0xf507f4f4f7f4f303), +CONST64(0x8bddcbcb0bcb16c0), CONST64(0x7cd33e3ef83eedc6), CONST64(0x0a2d050514052811), CONST64(0xce78676781671fe6), +CONST64(0xd597e4e4b7e47353), CONST64(0x4e0227279c2725bb), CONST64(0x8273414119413258), CONST64(0x0ba78b8b168b2c9d), +CONST64(0x53f6a7a7a6a75101), CONST64(0xfab27d7de97dcf94), CONST64(0x374995956e95dcfb), CONST64(0xad56d8d847d88e9f), +CONST64(0xeb70fbfbcbfb8b30), CONST64(0xc1cdeeee9fee2371), CONST64(0xf8bb7c7ced7cc791), CONST64(0xcc716666856617e3), +CONST64(0xa77bdddd53dda68e), CONST64(0x2eaf17175c17b84b), CONST64(0x8e45474701470246), CONST64(0x211a9e9e429e84dc), +CONST64(0x89d4caca0fca1ec5), CONST64(0x5a582d2db42d7599), CONST64(0x632ebfbfc6bf9179), CONST64(0x0e3f07071c07381b), +CONST64(0x47acadad8ead0123), CONST64(0xb4b05a5a755aea2f), CONST64(0x1bef838336836cb5), CONST64(0x66b63333cc3385ff), +CONST64(0xc65c636391633ff2), CONST64(0x041202020802100a), CONST64(0x4993aaaa92aa3938), CONST64(0xe2de7171d971afa8), +CONST64(0x8dc6c8c807c80ecf), CONST64(0x32d119196419c87d), CONST64(0x923b494939497270), CONST64(0xaf5fd9d943d9869a), +CONST64(0xf931f2f2eff2c31d), CONST64(0xdba8e3e3abe34b48), CONST64(0xb6b95b5b715be22a), CONST64(0x0dbc88881a883492), +CONST64(0x293e9a9a529aa4c8), CONST64(0x4c0b262698262dbe), CONST64(0x64bf3232c8328dfa), CONST64(0x7d59b0b0fab0e94a), +CONST64(0xcff2e9e983e91b6a), CONST64(0x1e770f0f3c0f7833), CONST64(0xb733d5d573d5e6a6), CONST64(0x1df480803a8074ba), +CONST64(0x6127bebec2be997c), CONST64(0x87ebcdcd13cd26de), CONST64(0x68893434d034bde4), CONST64(0x903248483d487a75), +CONST64(0xe354ffffdbffab24), CONST64(0xf48d7a7af57af78f), CONST64(0x3d6490907a90f4ea), CONST64(0xbe9d5f5f615fc23e), +CONST64(0x403d202080201da0), CONST64(0xd00f6868bd6867d5), CONST64(0x34ca1a1a681ad072), CONST64(0x41b7aeae82ae192c), +CONST64(0x757db4b4eab4c95e), CONST64(0xa8ce54544d549a19), CONST64(0x3b7f93937693ece5), CONST64(0x442f222288220daa), +CONST64(0xc86364648d6407e9), CONST64(0xff2af1f1e3f1db12), CONST64(0xe6cc7373d173bfa2), CONST64(0x248212124812905a), +CONST64(0x807a40401d403a5d), CONST64(0x1048080820084028), CONST64(0x9b95c3c32bc356e8), CONST64(0xc5dfecec97ec337b), +CONST64(0xab4ddbdb4bdb9690), CONST64(0x5fc0a1a1bea1611f), CONST64(0x07918d8d0e8d1c83), CONST64(0x7ac83d3df43df5c9), +CONST64(0x335b97976697ccf1), CONST64(0x0000000000000000), CONST64(0x83f9cfcf1bcf36d4), CONST64(0x566e2b2bac2b4587), +CONST64(0xece17676c57697b3), CONST64(0x19e68282328264b0), CONST64(0xb128d6d67fd6fea9), CONST64(0x36c31b1b6c1bd877), +CONST64(0x7774b5b5eeb5c15b), CONST64(0x43beafaf86af1129), CONST64(0xd41d6a6ab56a77df), CONST64(0xa0ea50505d50ba0d), +CONST64(0x8a5745450945124c), CONST64(0xfb38f3f3ebf3cb18), CONST64(0x60ad3030c0309df0), CONST64(0xc3c4efef9bef2b74), +CONST64(0x7eda3f3ffc3fe5c3), CONST64(0xaac755554955921c), CONST64(0x59dba2a2b2a27910), CONST64(0xc9e9eaea8fea0365), +CONST64(0xca6a656589650fec), CONST64(0x6903babad2bab968), CONST64(0x5e4a2f2fbc2f6593), CONST64(0x9d8ec0c027c04ee7), +CONST64(0xa160dede5fdebe81), CONST64(0x38fc1c1c701ce06c), CONST64(0xe746fdfdd3fdbb2e), CONST64(0x9a1f4d4d294d5264), +CONST64(0x397692927292e4e0), CONST64(0xeafa7575c9758fbc), CONST64(0x0c3606061806301e), CONST64(0x09ae8a8a128a2498), +CONST64(0x794bb2b2f2b2f940), CONST64(0xd185e6e6bfe66359), CONST64(0x1c7e0e0e380e7036), CONST64(0x3ee71f1f7c1ff863), +CONST64(0xc4556262956237f7), CONST64(0xb53ad4d477d4eea3), CONST64(0x4d81a8a89aa82932), CONST64(0x315296966296c4f4), +CONST64(0xef62f9f9c3f99b3a), CONST64(0x97a3c5c533c566f6), CONST64(0x4a102525942535b1), CONST64(0xb2ab59597959f220), +CONST64(0x15d084842a8454ae), CONST64(0xe4c57272d572b7a7), CONST64(0x72ec3939e439d5dd), CONST64(0x98164c4c2d4c5a61), +CONST64(0xbc945e5e655eca3b), CONST64(0xf09f7878fd78e785), CONST64(0x70e53838e038ddd8), CONST64(0x05988c8c0a8c1486), +CONST64(0xbf17d1d163d1c6b2), CONST64(0x57e4a5a5aea5410b), CONST64(0xd9a1e2e2afe2434d), CONST64(0xc24e616199612ff8), +CONST64(0x7b42b3b3f6b3f145), CONST64(0x42342121842115a5), CONST64(0x25089c9c4a9c94d6), CONST64(0x3cee1e1e781ef066), +CONST64(0x8661434311432252), CONST64(0x93b1c7c73bc776fc), CONST64(0xe54ffcfcd7fcb32b), CONST64(0x0824040410042014), +CONST64(0xa2e351515951b208), CONST64(0x2f2599995e99bcc7), CONST64(0xda226d6da96d4fc4), CONST64(0x1a650d0d340d6839), +CONST64(0xe979fafacffa8335), CONST64(0xa369dfdf5bdfb684), CONST64(0xfca97e7ee57ed79b), CONST64(0x4819242490243db4), +CONST64(0x76fe3b3bec3bc5d7), CONST64(0x4b9aabab96ab313d), CONST64(0x81f0cece1fce3ed1), CONST64(0x2299111144118855), +CONST64(0x03838f8f068f0c89), CONST64(0x9c044e4e254e4a6b), CONST64(0x7366b7b7e6b7d151), CONST64(0xcbe0ebeb8beb0b60), +CONST64(0x78c13c3cf03cfdcc), CONST64(0x1ffd81813e817cbf), CONST64(0x354094946a94d4fe), CONST64(0xf31cf7f7fbf7eb0c), +CONST64(0x6f18b9b9deb9a167), CONST64(0x268b13134c13985f), CONST64(0x58512c2cb02c7d9c), CONST64(0xbb05d3d36bd3d6b8), +CONST64(0xd38ce7e7bbe76b5c), CONST64(0xdc396e6ea56e57cb), CONST64(0x95aac4c437c46ef3), CONST64(0x061b03030c03180f), +CONST64(0xacdc565645568a13), CONST64(0x885e44440d441a49), CONST64(0xfea07f7fe17fdf9e), CONST64(0x4f88a9a99ea92137), +CONST64(0x54672a2aa82a4d82), CONST64(0x6b0abbbbd6bbb16d), CONST64(0x9f87c1c123c146e2), CONST64(0xa6f153535153a202), +CONST64(0xa572dcdc57dcae8b), CONST64(0x16530b0b2c0b5827), CONST64(0x27019d9d4e9d9cd3), CONST64(0xd82b6c6cad6c47c1), +CONST64(0x62a43131c43195f5), CONST64(0xe8f37474cd7487b9), CONST64(0xf115f6f6fff6e309), CONST64(0x8c4c464605460a43), +CONST64(0x45a5acac8aac0926), CONST64(0x0fb589891e893c97), CONST64(0x28b414145014a044), CONST64(0xdfbae1e1a3e15b42), +CONST64(0x2ca616165816b04e), CONST64(0x74f73a3ae83acdd2), CONST64(0xd2066969b9696fd0), CONST64(0x124109092409482d), +CONST64(0xe0d77070dd70a7ad), CONST64(0x716fb6b6e2b6d954), CONST64(0xbd1ed0d067d0ceb7), CONST64(0xc7d6eded93ed3b7e), +CONST64(0x85e2cccc17cc2edb), CONST64(0x8468424215422a57), CONST64(0x2d2c98985a98b4c2), CONST64(0x55eda4a4aaa4490e), +CONST64(0x50752828a0285d88), CONST64(0xb8865c5c6d5cda31), CONST64(0xed6bf8f8c7f8933f), CONST64(0x11c28686228644a4) +}; + +static const ulong64 sbox3[] = { +CONST64(0x7830d818186018c0), CONST64(0xaf462623238c2305), CONST64(0xf991b8c6c63fc67e), CONST64(0x6fcdfbe8e887e813), +CONST64(0xa113cb878726874c), CONST64(0x626d11b8b8dab8a9), CONST64(0x0502090101040108), CONST64(0x6e9e0d4f4f214f42), +CONST64(0xee6c9b3636d836ad), CONST64(0x0451ffa6a6a2a659), CONST64(0xbdb90cd2d26fd2de), CONST64(0x06f70ef5f5f3f5fb), +CONST64(0x80f2967979f979ef), CONST64(0xcede306f6fa16f5f), CONST64(0xef3f6d91917e91fc), CONST64(0x07a4f852525552aa), +CONST64(0xfdc04760609d6027), CONST64(0x766535bcbccabc89), CONST64(0xcd2b379b9b569bac), CONST64(0x8c018a8e8e028e04), +CONST64(0x155bd2a3a3b6a371), CONST64(0x3c186c0c0c300c60), CONST64(0x8af6847b7bf17bff), CONST64(0xe16a803535d435b5), +CONST64(0x693af51d1d741de8), CONST64(0x47ddb3e0e0a7e053), CONST64(0xacb321d7d77bd7f6), CONST64(0xed999cc2c22fc25e), +CONST64(0x965c432e2eb82e6d), CONST64(0x7a96294b4b314b62), CONST64(0x21e15dfefedffea3), CONST64(0x16aed55757415782), +CONST64(0x412abd15155415a8), CONST64(0xb6eee87777c1779f), CONST64(0xeb6e923737dc37a5), CONST64(0x56d79ee5e5b3e57b), +CONST64(0xd923139f9f469f8c), CONST64(0x17fd23f0f0e7f0d3), CONST64(0x7f94204a4a354a6a), CONST64(0x95a944dada4fda9e), +CONST64(0x25b0a258587d58fa), CONST64(0xca8fcfc9c903c906), CONST64(0x8d527c2929a42955), CONST64(0x22145a0a0a280a50), +CONST64(0x4f7f50b1b1feb1e1), CONST64(0x1a5dc9a0a0baa069), CONST64(0xdad6146b6bb16b7f), CONST64(0xab17d985852e855c), +CONST64(0x73673cbdbdcebd81), CONST64(0x34ba8f5d5d695dd2), CONST64(0x5020901010401080), CONST64(0x03f507f4f4f7f4f3), +CONST64(0xc08bddcbcb0bcb16), CONST64(0xc67cd33e3ef83eed), CONST64(0x110a2d0505140528), CONST64(0xe6ce78676781671f), +CONST64(0x53d597e4e4b7e473), CONST64(0xbb4e0227279c2725), CONST64(0x5882734141194132), CONST64(0x9d0ba78b8b168b2c), +CONST64(0x0153f6a7a7a6a751), CONST64(0x94fab27d7de97dcf), CONST64(0xfb374995956e95dc), CONST64(0x9fad56d8d847d88e), +CONST64(0x30eb70fbfbcbfb8b), CONST64(0x71c1cdeeee9fee23), CONST64(0x91f8bb7c7ced7cc7), CONST64(0xe3cc716666856617), +CONST64(0x8ea77bdddd53dda6), CONST64(0x4b2eaf17175c17b8), CONST64(0x468e454747014702), CONST64(0xdc211a9e9e429e84), +CONST64(0xc589d4caca0fca1e), CONST64(0x995a582d2db42d75), CONST64(0x79632ebfbfc6bf91), CONST64(0x1b0e3f07071c0738), +CONST64(0x2347acadad8ead01), CONST64(0x2fb4b05a5a755aea), CONST64(0xb51bef838336836c), CONST64(0xff66b63333cc3385), +CONST64(0xf2c65c636391633f), CONST64(0x0a04120202080210), CONST64(0x384993aaaa92aa39), CONST64(0xa8e2de7171d971af), +CONST64(0xcf8dc6c8c807c80e), CONST64(0x7d32d119196419c8), CONST64(0x70923b4949394972), CONST64(0x9aaf5fd9d943d986), +CONST64(0x1df931f2f2eff2c3), CONST64(0x48dba8e3e3abe34b), CONST64(0x2ab6b95b5b715be2), CONST64(0x920dbc88881a8834), +CONST64(0xc8293e9a9a529aa4), CONST64(0xbe4c0b262698262d), CONST64(0xfa64bf3232c8328d), CONST64(0x4a7d59b0b0fab0e9), +CONST64(0x6acff2e9e983e91b), CONST64(0x331e770f0f3c0f78), CONST64(0xa6b733d5d573d5e6), CONST64(0xba1df480803a8074), +CONST64(0x7c6127bebec2be99), CONST64(0xde87ebcdcd13cd26), CONST64(0xe468893434d034bd), CONST64(0x75903248483d487a), +CONST64(0x24e354ffffdbffab), CONST64(0x8ff48d7a7af57af7), CONST64(0xea3d6490907a90f4), CONST64(0x3ebe9d5f5f615fc2), +CONST64(0xa0403d202080201d), CONST64(0xd5d00f6868bd6867), CONST64(0x7234ca1a1a681ad0), CONST64(0x2c41b7aeae82ae19), +CONST64(0x5e757db4b4eab4c9), CONST64(0x19a8ce54544d549a), CONST64(0xe53b7f93937693ec), CONST64(0xaa442f222288220d), +CONST64(0xe9c86364648d6407), CONST64(0x12ff2af1f1e3f1db), CONST64(0xa2e6cc7373d173bf), CONST64(0x5a24821212481290), +CONST64(0x5d807a40401d403a), CONST64(0x2810480808200840), CONST64(0xe89b95c3c32bc356), CONST64(0x7bc5dfecec97ec33), +CONST64(0x90ab4ddbdb4bdb96), CONST64(0x1f5fc0a1a1bea161), CONST64(0x8307918d8d0e8d1c), CONST64(0xc97ac83d3df43df5), +CONST64(0xf1335b97976697cc), CONST64(0x0000000000000000), CONST64(0xd483f9cfcf1bcf36), CONST64(0x87566e2b2bac2b45), +CONST64(0xb3ece17676c57697), CONST64(0xb019e68282328264), CONST64(0xa9b128d6d67fd6fe), CONST64(0x7736c31b1b6c1bd8), +CONST64(0x5b7774b5b5eeb5c1), CONST64(0x2943beafaf86af11), CONST64(0xdfd41d6a6ab56a77), CONST64(0x0da0ea50505d50ba), +CONST64(0x4c8a574545094512), CONST64(0x18fb38f3f3ebf3cb), CONST64(0xf060ad3030c0309d), CONST64(0x74c3c4efef9bef2b), +CONST64(0xc37eda3f3ffc3fe5), CONST64(0x1caac75555495592), CONST64(0x1059dba2a2b2a279), CONST64(0x65c9e9eaea8fea03), +CONST64(0xecca6a656589650f), CONST64(0x686903babad2bab9), CONST64(0x935e4a2f2fbc2f65), CONST64(0xe79d8ec0c027c04e), +CONST64(0x81a160dede5fdebe), CONST64(0x6c38fc1c1c701ce0), CONST64(0x2ee746fdfdd3fdbb), CONST64(0x649a1f4d4d294d52), +CONST64(0xe0397692927292e4), CONST64(0xbceafa7575c9758f), CONST64(0x1e0c360606180630), CONST64(0x9809ae8a8a128a24), +CONST64(0x40794bb2b2f2b2f9), CONST64(0x59d185e6e6bfe663), CONST64(0x361c7e0e0e380e70), CONST64(0x633ee71f1f7c1ff8), +CONST64(0xf7c4556262956237), CONST64(0xa3b53ad4d477d4ee), CONST64(0x324d81a8a89aa829), CONST64(0xf4315296966296c4), +CONST64(0x3aef62f9f9c3f99b), CONST64(0xf697a3c5c533c566), CONST64(0xb14a102525942535), CONST64(0x20b2ab59597959f2), +CONST64(0xae15d084842a8454), CONST64(0xa7e4c57272d572b7), CONST64(0xdd72ec3939e439d5), CONST64(0x6198164c4c2d4c5a), +CONST64(0x3bbc945e5e655eca), CONST64(0x85f09f7878fd78e7), CONST64(0xd870e53838e038dd), CONST64(0x8605988c8c0a8c14), +CONST64(0xb2bf17d1d163d1c6), CONST64(0x0b57e4a5a5aea541), CONST64(0x4dd9a1e2e2afe243), CONST64(0xf8c24e616199612f), +CONST64(0x457b42b3b3f6b3f1), CONST64(0xa542342121842115), CONST64(0xd625089c9c4a9c94), CONST64(0x663cee1e1e781ef0), +CONST64(0x5286614343114322), CONST64(0xfc93b1c7c73bc776), CONST64(0x2be54ffcfcd7fcb3), CONST64(0x1408240404100420), +CONST64(0x08a2e351515951b2), CONST64(0xc72f2599995e99bc), CONST64(0xc4da226d6da96d4f), CONST64(0x391a650d0d340d68), +CONST64(0x35e979fafacffa83), CONST64(0x84a369dfdf5bdfb6), CONST64(0x9bfca97e7ee57ed7), CONST64(0xb44819242490243d), +CONST64(0xd776fe3b3bec3bc5), CONST64(0x3d4b9aabab96ab31), CONST64(0xd181f0cece1fce3e), CONST64(0x5522991111441188), +CONST64(0x8903838f8f068f0c), CONST64(0x6b9c044e4e254e4a), CONST64(0x517366b7b7e6b7d1), CONST64(0x60cbe0ebeb8beb0b), +CONST64(0xcc78c13c3cf03cfd), CONST64(0xbf1ffd81813e817c), CONST64(0xfe354094946a94d4), CONST64(0x0cf31cf7f7fbf7eb), +CONST64(0x676f18b9b9deb9a1), CONST64(0x5f268b13134c1398), CONST64(0x9c58512c2cb02c7d), CONST64(0xb8bb05d3d36bd3d6), +CONST64(0x5cd38ce7e7bbe76b), CONST64(0xcbdc396e6ea56e57), CONST64(0xf395aac4c437c46e), CONST64(0x0f061b03030c0318), +CONST64(0x13acdc565645568a), CONST64(0x49885e44440d441a), CONST64(0x9efea07f7fe17fdf), CONST64(0x374f88a9a99ea921), +CONST64(0x8254672a2aa82a4d), CONST64(0x6d6b0abbbbd6bbb1), CONST64(0xe29f87c1c123c146), CONST64(0x02a6f153535153a2), +CONST64(0x8ba572dcdc57dcae), CONST64(0x2716530b0b2c0b58), CONST64(0xd327019d9d4e9d9c), CONST64(0xc1d82b6c6cad6c47), +CONST64(0xf562a43131c43195), CONST64(0xb9e8f37474cd7487), CONST64(0x09f115f6f6fff6e3), CONST64(0x438c4c464605460a), +CONST64(0x2645a5acac8aac09), CONST64(0x970fb589891e893c), CONST64(0x4428b414145014a0), CONST64(0x42dfbae1e1a3e15b), +CONST64(0x4e2ca616165816b0), CONST64(0xd274f73a3ae83acd), CONST64(0xd0d2066969b9696f), CONST64(0x2d12410909240948), +CONST64(0xade0d77070dd70a7), CONST64(0x54716fb6b6e2b6d9), CONST64(0xb7bd1ed0d067d0ce), CONST64(0x7ec7d6eded93ed3b), +CONST64(0xdb85e2cccc17cc2e), CONST64(0x578468424215422a), CONST64(0xc22d2c98985a98b4), CONST64(0x0e55eda4a4aaa449), +CONST64(0x8850752828a0285d), CONST64(0x31b8865c5c6d5cda), CONST64(0x3fed6bf8f8c7f893), CONST64(0xa411c28686228644) +}; + +static const ulong64 sbox4[] = { +CONST64(0xc07830d818186018), CONST64(0x05af462623238c23), CONST64(0x7ef991b8c6c63fc6), CONST64(0x136fcdfbe8e887e8), +CONST64(0x4ca113cb87872687), CONST64(0xa9626d11b8b8dab8), CONST64(0x0805020901010401), CONST64(0x426e9e0d4f4f214f), +CONST64(0xadee6c9b3636d836), CONST64(0x590451ffa6a6a2a6), CONST64(0xdebdb90cd2d26fd2), CONST64(0xfb06f70ef5f5f3f5), +CONST64(0xef80f2967979f979), CONST64(0x5fcede306f6fa16f), CONST64(0xfcef3f6d91917e91), CONST64(0xaa07a4f852525552), +CONST64(0x27fdc04760609d60), CONST64(0x89766535bcbccabc), CONST64(0xaccd2b379b9b569b), CONST64(0x048c018a8e8e028e), +CONST64(0x71155bd2a3a3b6a3), CONST64(0x603c186c0c0c300c), CONST64(0xff8af6847b7bf17b), CONST64(0xb5e16a803535d435), +CONST64(0xe8693af51d1d741d), CONST64(0x5347ddb3e0e0a7e0), CONST64(0xf6acb321d7d77bd7), CONST64(0x5eed999cc2c22fc2), +CONST64(0x6d965c432e2eb82e), CONST64(0x627a96294b4b314b), CONST64(0xa321e15dfefedffe), CONST64(0x8216aed557574157), +CONST64(0xa8412abd15155415), CONST64(0x9fb6eee87777c177), CONST64(0xa5eb6e923737dc37), CONST64(0x7b56d79ee5e5b3e5), +CONST64(0x8cd923139f9f469f), CONST64(0xd317fd23f0f0e7f0), CONST64(0x6a7f94204a4a354a), CONST64(0x9e95a944dada4fda), +CONST64(0xfa25b0a258587d58), CONST64(0x06ca8fcfc9c903c9), CONST64(0x558d527c2929a429), CONST64(0x5022145a0a0a280a), +CONST64(0xe14f7f50b1b1feb1), CONST64(0x691a5dc9a0a0baa0), CONST64(0x7fdad6146b6bb16b), CONST64(0x5cab17d985852e85), +CONST64(0x8173673cbdbdcebd), CONST64(0xd234ba8f5d5d695d), CONST64(0x8050209010104010), CONST64(0xf303f507f4f4f7f4), +CONST64(0x16c08bddcbcb0bcb), CONST64(0xedc67cd33e3ef83e), CONST64(0x28110a2d05051405), CONST64(0x1fe6ce7867678167), +CONST64(0x7353d597e4e4b7e4), CONST64(0x25bb4e0227279c27), CONST64(0x3258827341411941), CONST64(0x2c9d0ba78b8b168b), +CONST64(0x510153f6a7a7a6a7), CONST64(0xcf94fab27d7de97d), CONST64(0xdcfb374995956e95), CONST64(0x8e9fad56d8d847d8), +CONST64(0x8b30eb70fbfbcbfb), CONST64(0x2371c1cdeeee9fee), CONST64(0xc791f8bb7c7ced7c), CONST64(0x17e3cc7166668566), +CONST64(0xa68ea77bdddd53dd), CONST64(0xb84b2eaf17175c17), CONST64(0x02468e4547470147), CONST64(0x84dc211a9e9e429e), +CONST64(0x1ec589d4caca0fca), CONST64(0x75995a582d2db42d), CONST64(0x9179632ebfbfc6bf), CONST64(0x381b0e3f07071c07), +CONST64(0x012347acadad8ead), CONST64(0xea2fb4b05a5a755a), CONST64(0x6cb51bef83833683), CONST64(0x85ff66b63333cc33), +CONST64(0x3ff2c65c63639163), CONST64(0x100a041202020802), CONST64(0x39384993aaaa92aa), CONST64(0xafa8e2de7171d971), +CONST64(0x0ecf8dc6c8c807c8), CONST64(0xc87d32d119196419), CONST64(0x7270923b49493949), CONST64(0x869aaf5fd9d943d9), +CONST64(0xc31df931f2f2eff2), CONST64(0x4b48dba8e3e3abe3), CONST64(0xe22ab6b95b5b715b), CONST64(0x34920dbc88881a88), +CONST64(0xa4c8293e9a9a529a), CONST64(0x2dbe4c0b26269826), CONST64(0x8dfa64bf3232c832), CONST64(0xe94a7d59b0b0fab0), +CONST64(0x1b6acff2e9e983e9), CONST64(0x78331e770f0f3c0f), CONST64(0xe6a6b733d5d573d5), CONST64(0x74ba1df480803a80), +CONST64(0x997c6127bebec2be), CONST64(0x26de87ebcdcd13cd), CONST64(0xbde468893434d034), CONST64(0x7a75903248483d48), +CONST64(0xab24e354ffffdbff), CONST64(0xf78ff48d7a7af57a), CONST64(0xf4ea3d6490907a90), CONST64(0xc23ebe9d5f5f615f), +CONST64(0x1da0403d20208020), CONST64(0x67d5d00f6868bd68), CONST64(0xd07234ca1a1a681a), CONST64(0x192c41b7aeae82ae), +CONST64(0xc95e757db4b4eab4), CONST64(0x9a19a8ce54544d54), CONST64(0xece53b7f93937693), CONST64(0x0daa442f22228822), +CONST64(0x07e9c86364648d64), CONST64(0xdb12ff2af1f1e3f1), CONST64(0xbfa2e6cc7373d173), CONST64(0x905a248212124812), +CONST64(0x3a5d807a40401d40), CONST64(0x4028104808082008), CONST64(0x56e89b95c3c32bc3), CONST64(0x337bc5dfecec97ec), +CONST64(0x9690ab4ddbdb4bdb), CONST64(0x611f5fc0a1a1bea1), CONST64(0x1c8307918d8d0e8d), CONST64(0xf5c97ac83d3df43d), +CONST64(0xccf1335b97976697), CONST64(0x0000000000000000), CONST64(0x36d483f9cfcf1bcf), CONST64(0x4587566e2b2bac2b), +CONST64(0x97b3ece17676c576), CONST64(0x64b019e682823282), CONST64(0xfea9b128d6d67fd6), CONST64(0xd87736c31b1b6c1b), +CONST64(0xc15b7774b5b5eeb5), CONST64(0x112943beafaf86af), CONST64(0x77dfd41d6a6ab56a), CONST64(0xba0da0ea50505d50), +CONST64(0x124c8a5745450945), CONST64(0xcb18fb38f3f3ebf3), CONST64(0x9df060ad3030c030), CONST64(0x2b74c3c4efef9bef), +CONST64(0xe5c37eda3f3ffc3f), CONST64(0x921caac755554955), CONST64(0x791059dba2a2b2a2), CONST64(0x0365c9e9eaea8fea), +CONST64(0x0fecca6a65658965), CONST64(0xb9686903babad2ba), CONST64(0x65935e4a2f2fbc2f), CONST64(0x4ee79d8ec0c027c0), +CONST64(0xbe81a160dede5fde), CONST64(0xe06c38fc1c1c701c), CONST64(0xbb2ee746fdfdd3fd), CONST64(0x52649a1f4d4d294d), +CONST64(0xe4e0397692927292), CONST64(0x8fbceafa7575c975), CONST64(0x301e0c3606061806), CONST64(0x249809ae8a8a128a), +CONST64(0xf940794bb2b2f2b2), CONST64(0x6359d185e6e6bfe6), CONST64(0x70361c7e0e0e380e), CONST64(0xf8633ee71f1f7c1f), +CONST64(0x37f7c45562629562), CONST64(0xeea3b53ad4d477d4), CONST64(0x29324d81a8a89aa8), CONST64(0xc4f4315296966296), +CONST64(0x9b3aef62f9f9c3f9), CONST64(0x66f697a3c5c533c5), CONST64(0x35b14a1025259425), CONST64(0xf220b2ab59597959), +CONST64(0x54ae15d084842a84), CONST64(0xb7a7e4c57272d572), CONST64(0xd5dd72ec3939e439), CONST64(0x5a6198164c4c2d4c), +CONST64(0xca3bbc945e5e655e), CONST64(0xe785f09f7878fd78), CONST64(0xddd870e53838e038), CONST64(0x148605988c8c0a8c), +CONST64(0xc6b2bf17d1d163d1), CONST64(0x410b57e4a5a5aea5), CONST64(0x434dd9a1e2e2afe2), CONST64(0x2ff8c24e61619961), +CONST64(0xf1457b42b3b3f6b3), CONST64(0x15a5423421218421), CONST64(0x94d625089c9c4a9c), CONST64(0xf0663cee1e1e781e), +CONST64(0x2252866143431143), CONST64(0x76fc93b1c7c73bc7), CONST64(0xb32be54ffcfcd7fc), CONST64(0x2014082404041004), +CONST64(0xb208a2e351515951), CONST64(0xbcc72f2599995e99), CONST64(0x4fc4da226d6da96d), CONST64(0x68391a650d0d340d), +CONST64(0x8335e979fafacffa), CONST64(0xb684a369dfdf5bdf), CONST64(0xd79bfca97e7ee57e), CONST64(0x3db4481924249024), +CONST64(0xc5d776fe3b3bec3b), CONST64(0x313d4b9aabab96ab), CONST64(0x3ed181f0cece1fce), CONST64(0x8855229911114411), +CONST64(0x0c8903838f8f068f), CONST64(0x4a6b9c044e4e254e), CONST64(0xd1517366b7b7e6b7), CONST64(0x0b60cbe0ebeb8beb), +CONST64(0xfdcc78c13c3cf03c), CONST64(0x7cbf1ffd81813e81), CONST64(0xd4fe354094946a94), CONST64(0xeb0cf31cf7f7fbf7), +CONST64(0xa1676f18b9b9deb9), CONST64(0x985f268b13134c13), CONST64(0x7d9c58512c2cb02c), CONST64(0xd6b8bb05d3d36bd3), +CONST64(0x6b5cd38ce7e7bbe7), CONST64(0x57cbdc396e6ea56e), CONST64(0x6ef395aac4c437c4), CONST64(0x180f061b03030c03), +CONST64(0x8a13acdc56564556), CONST64(0x1a49885e44440d44), CONST64(0xdf9efea07f7fe17f), CONST64(0x21374f88a9a99ea9), +CONST64(0x4d8254672a2aa82a), CONST64(0xb16d6b0abbbbd6bb), CONST64(0x46e29f87c1c123c1), CONST64(0xa202a6f153535153), +CONST64(0xae8ba572dcdc57dc), CONST64(0x582716530b0b2c0b), CONST64(0x9cd327019d9d4e9d), CONST64(0x47c1d82b6c6cad6c), +CONST64(0x95f562a43131c431), CONST64(0x87b9e8f37474cd74), CONST64(0xe309f115f6f6fff6), CONST64(0x0a438c4c46460546), +CONST64(0x092645a5acac8aac), CONST64(0x3c970fb589891e89), CONST64(0xa04428b414145014), CONST64(0x5b42dfbae1e1a3e1), +CONST64(0xb04e2ca616165816), CONST64(0xcdd274f73a3ae83a), CONST64(0x6fd0d2066969b969), CONST64(0x482d124109092409), +CONST64(0xa7ade0d77070dd70), CONST64(0xd954716fb6b6e2b6), CONST64(0xceb7bd1ed0d067d0), CONST64(0x3b7ec7d6eded93ed), +CONST64(0x2edb85e2cccc17cc), CONST64(0x2a57846842421542), CONST64(0xb4c22d2c98985a98), CONST64(0x490e55eda4a4aaa4), +CONST64(0x5d8850752828a028), CONST64(0xda31b8865c5c6d5c), CONST64(0x933fed6bf8f8c7f8), CONST64(0x44a411c286862286) +}; + +static const ulong64 sbox5[] = { +CONST64(0x18c07830d8181860), CONST64(0x2305af462623238c), CONST64(0xc67ef991b8c6c63f), CONST64(0xe8136fcdfbe8e887), +CONST64(0x874ca113cb878726), CONST64(0xb8a9626d11b8b8da), CONST64(0x0108050209010104), CONST64(0x4f426e9e0d4f4f21), +CONST64(0x36adee6c9b3636d8), CONST64(0xa6590451ffa6a6a2), CONST64(0xd2debdb90cd2d26f), CONST64(0xf5fb06f70ef5f5f3), +CONST64(0x79ef80f2967979f9), CONST64(0x6f5fcede306f6fa1), CONST64(0x91fcef3f6d91917e), CONST64(0x52aa07a4f8525255), +CONST64(0x6027fdc04760609d), CONST64(0xbc89766535bcbcca), CONST64(0x9baccd2b379b9b56), CONST64(0x8e048c018a8e8e02), +CONST64(0xa371155bd2a3a3b6), CONST64(0x0c603c186c0c0c30), CONST64(0x7bff8af6847b7bf1), CONST64(0x35b5e16a803535d4), +CONST64(0x1de8693af51d1d74), CONST64(0xe05347ddb3e0e0a7), CONST64(0xd7f6acb321d7d77b), CONST64(0xc25eed999cc2c22f), +CONST64(0x2e6d965c432e2eb8), CONST64(0x4b627a96294b4b31), CONST64(0xfea321e15dfefedf), CONST64(0x578216aed5575741), +CONST64(0x15a8412abd151554), CONST64(0x779fb6eee87777c1), CONST64(0x37a5eb6e923737dc), CONST64(0xe57b56d79ee5e5b3), +CONST64(0x9f8cd923139f9f46), CONST64(0xf0d317fd23f0f0e7), CONST64(0x4a6a7f94204a4a35), CONST64(0xda9e95a944dada4f), +CONST64(0x58fa25b0a258587d), CONST64(0xc906ca8fcfc9c903), CONST64(0x29558d527c2929a4), CONST64(0x0a5022145a0a0a28), +CONST64(0xb1e14f7f50b1b1fe), CONST64(0xa0691a5dc9a0a0ba), CONST64(0x6b7fdad6146b6bb1), CONST64(0x855cab17d985852e), +CONST64(0xbd8173673cbdbdce), CONST64(0x5dd234ba8f5d5d69), CONST64(0x1080502090101040), CONST64(0xf4f303f507f4f4f7), +CONST64(0xcb16c08bddcbcb0b), CONST64(0x3eedc67cd33e3ef8), CONST64(0x0528110a2d050514), CONST64(0x671fe6ce78676781), +CONST64(0xe47353d597e4e4b7), CONST64(0x2725bb4e0227279c), CONST64(0x4132588273414119), CONST64(0x8b2c9d0ba78b8b16), +CONST64(0xa7510153f6a7a7a6), CONST64(0x7dcf94fab27d7de9), CONST64(0x95dcfb374995956e), CONST64(0xd88e9fad56d8d847), +CONST64(0xfb8b30eb70fbfbcb), CONST64(0xee2371c1cdeeee9f), CONST64(0x7cc791f8bb7c7ced), CONST64(0x6617e3cc71666685), +CONST64(0xdda68ea77bdddd53), CONST64(0x17b84b2eaf17175c), CONST64(0x4702468e45474701), CONST64(0x9e84dc211a9e9e42), +CONST64(0xca1ec589d4caca0f), CONST64(0x2d75995a582d2db4), CONST64(0xbf9179632ebfbfc6), CONST64(0x07381b0e3f07071c), +CONST64(0xad012347acadad8e), CONST64(0x5aea2fb4b05a5a75), CONST64(0x836cb51bef838336), CONST64(0x3385ff66b63333cc), +CONST64(0x633ff2c65c636391), CONST64(0x02100a0412020208), CONST64(0xaa39384993aaaa92), CONST64(0x71afa8e2de7171d9), +CONST64(0xc80ecf8dc6c8c807), CONST64(0x19c87d32d1191964), CONST64(0x497270923b494939), CONST64(0xd9869aaf5fd9d943), +CONST64(0xf2c31df931f2f2ef), CONST64(0xe34b48dba8e3e3ab), CONST64(0x5be22ab6b95b5b71), CONST64(0x8834920dbc88881a), +CONST64(0x9aa4c8293e9a9a52), CONST64(0x262dbe4c0b262698), CONST64(0x328dfa64bf3232c8), CONST64(0xb0e94a7d59b0b0fa), +CONST64(0xe91b6acff2e9e983), CONST64(0x0f78331e770f0f3c), CONST64(0xd5e6a6b733d5d573), CONST64(0x8074ba1df480803a), +CONST64(0xbe997c6127bebec2), CONST64(0xcd26de87ebcdcd13), CONST64(0x34bde468893434d0), CONST64(0x487a75903248483d), +CONST64(0xffab24e354ffffdb), CONST64(0x7af78ff48d7a7af5), CONST64(0x90f4ea3d6490907a), CONST64(0x5fc23ebe9d5f5f61), +CONST64(0x201da0403d202080), CONST64(0x6867d5d00f6868bd), CONST64(0x1ad07234ca1a1a68), CONST64(0xae192c41b7aeae82), +CONST64(0xb4c95e757db4b4ea), CONST64(0x549a19a8ce54544d), CONST64(0x93ece53b7f939376), CONST64(0x220daa442f222288), +CONST64(0x6407e9c86364648d), CONST64(0xf1db12ff2af1f1e3), CONST64(0x73bfa2e6cc7373d1), CONST64(0x12905a2482121248), +CONST64(0x403a5d807a40401d), CONST64(0x0840281048080820), CONST64(0xc356e89b95c3c32b), CONST64(0xec337bc5dfecec97), +CONST64(0xdb9690ab4ddbdb4b), CONST64(0xa1611f5fc0a1a1be), CONST64(0x8d1c8307918d8d0e), CONST64(0x3df5c97ac83d3df4), +CONST64(0x97ccf1335b979766), CONST64(0x0000000000000000), CONST64(0xcf36d483f9cfcf1b), CONST64(0x2b4587566e2b2bac), +CONST64(0x7697b3ece17676c5), CONST64(0x8264b019e6828232), CONST64(0xd6fea9b128d6d67f), CONST64(0x1bd87736c31b1b6c), +CONST64(0xb5c15b7774b5b5ee), CONST64(0xaf112943beafaf86), CONST64(0x6a77dfd41d6a6ab5), CONST64(0x50ba0da0ea50505d), +CONST64(0x45124c8a57454509), CONST64(0xf3cb18fb38f3f3eb), CONST64(0x309df060ad3030c0), CONST64(0xef2b74c3c4efef9b), +CONST64(0x3fe5c37eda3f3ffc), CONST64(0x55921caac7555549), CONST64(0xa2791059dba2a2b2), CONST64(0xea0365c9e9eaea8f), +CONST64(0x650fecca6a656589), CONST64(0xbab9686903babad2), CONST64(0x2f65935e4a2f2fbc), CONST64(0xc04ee79d8ec0c027), +CONST64(0xdebe81a160dede5f), CONST64(0x1ce06c38fc1c1c70), CONST64(0xfdbb2ee746fdfdd3), CONST64(0x4d52649a1f4d4d29), +CONST64(0x92e4e03976929272), CONST64(0x758fbceafa7575c9), CONST64(0x06301e0c36060618), CONST64(0x8a249809ae8a8a12), +CONST64(0xb2f940794bb2b2f2), CONST64(0xe66359d185e6e6bf), CONST64(0x0e70361c7e0e0e38), CONST64(0x1ff8633ee71f1f7c), +CONST64(0x6237f7c455626295), CONST64(0xd4eea3b53ad4d477), CONST64(0xa829324d81a8a89a), CONST64(0x96c4f43152969662), +CONST64(0xf99b3aef62f9f9c3), CONST64(0xc566f697a3c5c533), CONST64(0x2535b14a10252594), CONST64(0x59f220b2ab595979), +CONST64(0x8454ae15d084842a), CONST64(0x72b7a7e4c57272d5), CONST64(0x39d5dd72ec3939e4), CONST64(0x4c5a6198164c4c2d), +CONST64(0x5eca3bbc945e5e65), CONST64(0x78e785f09f7878fd), CONST64(0x38ddd870e53838e0), CONST64(0x8c148605988c8c0a), +CONST64(0xd1c6b2bf17d1d163), CONST64(0xa5410b57e4a5a5ae), CONST64(0xe2434dd9a1e2e2af), CONST64(0x612ff8c24e616199), +CONST64(0xb3f1457b42b3b3f6), CONST64(0x2115a54234212184), CONST64(0x9c94d625089c9c4a), CONST64(0x1ef0663cee1e1e78), +CONST64(0x4322528661434311), CONST64(0xc776fc93b1c7c73b), CONST64(0xfcb32be54ffcfcd7), CONST64(0x0420140824040410), +CONST64(0x51b208a2e3515159), CONST64(0x99bcc72f2599995e), CONST64(0x6d4fc4da226d6da9), CONST64(0x0d68391a650d0d34), +CONST64(0xfa8335e979fafacf), CONST64(0xdfb684a369dfdf5b), CONST64(0x7ed79bfca97e7ee5), CONST64(0x243db44819242490), +CONST64(0x3bc5d776fe3b3bec), CONST64(0xab313d4b9aabab96), CONST64(0xce3ed181f0cece1f), CONST64(0x1188552299111144), +CONST64(0x8f0c8903838f8f06), CONST64(0x4e4a6b9c044e4e25), CONST64(0xb7d1517366b7b7e6), CONST64(0xeb0b60cbe0ebeb8b), +CONST64(0x3cfdcc78c13c3cf0), CONST64(0x817cbf1ffd81813e), CONST64(0x94d4fe354094946a), CONST64(0xf7eb0cf31cf7f7fb), +CONST64(0xb9a1676f18b9b9de), CONST64(0x13985f268b13134c), CONST64(0x2c7d9c58512c2cb0), CONST64(0xd3d6b8bb05d3d36b), +CONST64(0xe76b5cd38ce7e7bb), CONST64(0x6e57cbdc396e6ea5), CONST64(0xc46ef395aac4c437), CONST64(0x03180f061b03030c), +CONST64(0x568a13acdc565645), CONST64(0x441a49885e44440d), CONST64(0x7fdf9efea07f7fe1), CONST64(0xa921374f88a9a99e), +CONST64(0x2a4d8254672a2aa8), CONST64(0xbbb16d6b0abbbbd6), CONST64(0xc146e29f87c1c123), CONST64(0x53a202a6f1535351), +CONST64(0xdcae8ba572dcdc57), CONST64(0x0b582716530b0b2c), CONST64(0x9d9cd327019d9d4e), CONST64(0x6c47c1d82b6c6cad), +CONST64(0x3195f562a43131c4), CONST64(0x7487b9e8f37474cd), CONST64(0xf6e309f115f6f6ff), CONST64(0x460a438c4c464605), +CONST64(0xac092645a5acac8a), CONST64(0x893c970fb589891e), CONST64(0x14a04428b4141450), CONST64(0xe15b42dfbae1e1a3), +CONST64(0x16b04e2ca6161658), CONST64(0x3acdd274f73a3ae8), CONST64(0x696fd0d2066969b9), CONST64(0x09482d1241090924), +CONST64(0x70a7ade0d77070dd), CONST64(0xb6d954716fb6b6e2), CONST64(0xd0ceb7bd1ed0d067), CONST64(0xed3b7ec7d6eded93), +CONST64(0xcc2edb85e2cccc17), CONST64(0x422a578468424215), CONST64(0x98b4c22d2c98985a), CONST64(0xa4490e55eda4a4aa), +CONST64(0x285d8850752828a0), CONST64(0x5cda31b8865c5c6d), CONST64(0xf8933fed6bf8f8c7), CONST64(0x8644a411c2868622) +}; + +static const ulong64 sbox6[] = { +CONST64(0x6018c07830d81818), CONST64(0x8c2305af46262323), CONST64(0x3fc67ef991b8c6c6), CONST64(0x87e8136fcdfbe8e8), +CONST64(0x26874ca113cb8787), CONST64(0xdab8a9626d11b8b8), CONST64(0x0401080502090101), CONST64(0x214f426e9e0d4f4f), +CONST64(0xd836adee6c9b3636), CONST64(0xa2a6590451ffa6a6), CONST64(0x6fd2debdb90cd2d2), CONST64(0xf3f5fb06f70ef5f5), +CONST64(0xf979ef80f2967979), CONST64(0xa16f5fcede306f6f), CONST64(0x7e91fcef3f6d9191), CONST64(0x5552aa07a4f85252), +CONST64(0x9d6027fdc0476060), CONST64(0xcabc89766535bcbc), CONST64(0x569baccd2b379b9b), CONST64(0x028e048c018a8e8e), +CONST64(0xb6a371155bd2a3a3), CONST64(0x300c603c186c0c0c), CONST64(0xf17bff8af6847b7b), CONST64(0xd435b5e16a803535), +CONST64(0x741de8693af51d1d), CONST64(0xa7e05347ddb3e0e0), CONST64(0x7bd7f6acb321d7d7), CONST64(0x2fc25eed999cc2c2), +CONST64(0xb82e6d965c432e2e), CONST64(0x314b627a96294b4b), CONST64(0xdffea321e15dfefe), CONST64(0x41578216aed55757), +CONST64(0x5415a8412abd1515), CONST64(0xc1779fb6eee87777), CONST64(0xdc37a5eb6e923737), CONST64(0xb3e57b56d79ee5e5), +CONST64(0x469f8cd923139f9f), CONST64(0xe7f0d317fd23f0f0), CONST64(0x354a6a7f94204a4a), CONST64(0x4fda9e95a944dada), +CONST64(0x7d58fa25b0a25858), CONST64(0x03c906ca8fcfc9c9), CONST64(0xa429558d527c2929), CONST64(0x280a5022145a0a0a), +CONST64(0xfeb1e14f7f50b1b1), CONST64(0xbaa0691a5dc9a0a0), CONST64(0xb16b7fdad6146b6b), CONST64(0x2e855cab17d98585), +CONST64(0xcebd8173673cbdbd), CONST64(0x695dd234ba8f5d5d), CONST64(0x4010805020901010), CONST64(0xf7f4f303f507f4f4), +CONST64(0x0bcb16c08bddcbcb), CONST64(0xf83eedc67cd33e3e), CONST64(0x140528110a2d0505), CONST64(0x81671fe6ce786767), +CONST64(0xb7e47353d597e4e4), CONST64(0x9c2725bb4e022727), CONST64(0x1941325882734141), CONST64(0x168b2c9d0ba78b8b), +CONST64(0xa6a7510153f6a7a7), CONST64(0xe97dcf94fab27d7d), CONST64(0x6e95dcfb37499595), CONST64(0x47d88e9fad56d8d8), +CONST64(0xcbfb8b30eb70fbfb), CONST64(0x9fee2371c1cdeeee), CONST64(0xed7cc791f8bb7c7c), CONST64(0x856617e3cc716666), +CONST64(0x53dda68ea77bdddd), CONST64(0x5c17b84b2eaf1717), CONST64(0x014702468e454747), CONST64(0x429e84dc211a9e9e), +CONST64(0x0fca1ec589d4caca), CONST64(0xb42d75995a582d2d), CONST64(0xc6bf9179632ebfbf), CONST64(0x1c07381b0e3f0707), +CONST64(0x8ead012347acadad), CONST64(0x755aea2fb4b05a5a), CONST64(0x36836cb51bef8383), CONST64(0xcc3385ff66b63333), +CONST64(0x91633ff2c65c6363), CONST64(0x0802100a04120202), CONST64(0x92aa39384993aaaa), CONST64(0xd971afa8e2de7171), +CONST64(0x07c80ecf8dc6c8c8), CONST64(0x6419c87d32d11919), CONST64(0x39497270923b4949), CONST64(0x43d9869aaf5fd9d9), +CONST64(0xeff2c31df931f2f2), CONST64(0xabe34b48dba8e3e3), CONST64(0x715be22ab6b95b5b), CONST64(0x1a8834920dbc8888), +CONST64(0x529aa4c8293e9a9a), CONST64(0x98262dbe4c0b2626), CONST64(0xc8328dfa64bf3232), CONST64(0xfab0e94a7d59b0b0), +CONST64(0x83e91b6acff2e9e9), CONST64(0x3c0f78331e770f0f), CONST64(0x73d5e6a6b733d5d5), CONST64(0x3a8074ba1df48080), +CONST64(0xc2be997c6127bebe), CONST64(0x13cd26de87ebcdcd), CONST64(0xd034bde468893434), CONST64(0x3d487a7590324848), +CONST64(0xdbffab24e354ffff), CONST64(0xf57af78ff48d7a7a), CONST64(0x7a90f4ea3d649090), CONST64(0x615fc23ebe9d5f5f), +CONST64(0x80201da0403d2020), CONST64(0xbd6867d5d00f6868), CONST64(0x681ad07234ca1a1a), CONST64(0x82ae192c41b7aeae), +CONST64(0xeab4c95e757db4b4), CONST64(0x4d549a19a8ce5454), CONST64(0x7693ece53b7f9393), CONST64(0x88220daa442f2222), +CONST64(0x8d6407e9c8636464), CONST64(0xe3f1db12ff2af1f1), CONST64(0xd173bfa2e6cc7373), CONST64(0x4812905a24821212), +CONST64(0x1d403a5d807a4040), CONST64(0x2008402810480808), CONST64(0x2bc356e89b95c3c3), CONST64(0x97ec337bc5dfecec), +CONST64(0x4bdb9690ab4ddbdb), CONST64(0xbea1611f5fc0a1a1), CONST64(0x0e8d1c8307918d8d), CONST64(0xf43df5c97ac83d3d), +CONST64(0x6697ccf1335b9797), CONST64(0x0000000000000000), CONST64(0x1bcf36d483f9cfcf), CONST64(0xac2b4587566e2b2b), +CONST64(0xc57697b3ece17676), CONST64(0x328264b019e68282), CONST64(0x7fd6fea9b128d6d6), CONST64(0x6c1bd87736c31b1b), +CONST64(0xeeb5c15b7774b5b5), CONST64(0x86af112943beafaf), CONST64(0xb56a77dfd41d6a6a), CONST64(0x5d50ba0da0ea5050), +CONST64(0x0945124c8a574545), CONST64(0xebf3cb18fb38f3f3), CONST64(0xc0309df060ad3030), CONST64(0x9bef2b74c3c4efef), +CONST64(0xfc3fe5c37eda3f3f), CONST64(0x4955921caac75555), CONST64(0xb2a2791059dba2a2), CONST64(0x8fea0365c9e9eaea), +CONST64(0x89650fecca6a6565), CONST64(0xd2bab9686903baba), CONST64(0xbc2f65935e4a2f2f), CONST64(0x27c04ee79d8ec0c0), +CONST64(0x5fdebe81a160dede), CONST64(0x701ce06c38fc1c1c), CONST64(0xd3fdbb2ee746fdfd), CONST64(0x294d52649a1f4d4d), +CONST64(0x7292e4e039769292), CONST64(0xc9758fbceafa7575), CONST64(0x1806301e0c360606), CONST64(0x128a249809ae8a8a), +CONST64(0xf2b2f940794bb2b2), CONST64(0xbfe66359d185e6e6), CONST64(0x380e70361c7e0e0e), CONST64(0x7c1ff8633ee71f1f), +CONST64(0x956237f7c4556262), CONST64(0x77d4eea3b53ad4d4), CONST64(0x9aa829324d81a8a8), CONST64(0x6296c4f431529696), +CONST64(0xc3f99b3aef62f9f9), CONST64(0x33c566f697a3c5c5), CONST64(0x942535b14a102525), CONST64(0x7959f220b2ab5959), +CONST64(0x2a8454ae15d08484), CONST64(0xd572b7a7e4c57272), CONST64(0xe439d5dd72ec3939), CONST64(0x2d4c5a6198164c4c), +CONST64(0x655eca3bbc945e5e), CONST64(0xfd78e785f09f7878), CONST64(0xe038ddd870e53838), CONST64(0x0a8c148605988c8c), +CONST64(0x63d1c6b2bf17d1d1), CONST64(0xaea5410b57e4a5a5), CONST64(0xafe2434dd9a1e2e2), CONST64(0x99612ff8c24e6161), +CONST64(0xf6b3f1457b42b3b3), CONST64(0x842115a542342121), CONST64(0x4a9c94d625089c9c), CONST64(0x781ef0663cee1e1e), +CONST64(0x1143225286614343), CONST64(0x3bc776fc93b1c7c7), CONST64(0xd7fcb32be54ffcfc), CONST64(0x1004201408240404), +CONST64(0x5951b208a2e35151), CONST64(0x5e99bcc72f259999), CONST64(0xa96d4fc4da226d6d), CONST64(0x340d68391a650d0d), +CONST64(0xcffa8335e979fafa), CONST64(0x5bdfb684a369dfdf), CONST64(0xe57ed79bfca97e7e), CONST64(0x90243db448192424), +CONST64(0xec3bc5d776fe3b3b), CONST64(0x96ab313d4b9aabab), CONST64(0x1fce3ed181f0cece), CONST64(0x4411885522991111), +CONST64(0x068f0c8903838f8f), CONST64(0x254e4a6b9c044e4e), CONST64(0xe6b7d1517366b7b7), CONST64(0x8beb0b60cbe0ebeb), +CONST64(0xf03cfdcc78c13c3c), CONST64(0x3e817cbf1ffd8181), CONST64(0x6a94d4fe35409494), CONST64(0xfbf7eb0cf31cf7f7), +CONST64(0xdeb9a1676f18b9b9), CONST64(0x4c13985f268b1313), CONST64(0xb02c7d9c58512c2c), CONST64(0x6bd3d6b8bb05d3d3), +CONST64(0xbbe76b5cd38ce7e7), CONST64(0xa56e57cbdc396e6e), CONST64(0x37c46ef395aac4c4), CONST64(0x0c03180f061b0303), +CONST64(0x45568a13acdc5656), CONST64(0x0d441a49885e4444), CONST64(0xe17fdf9efea07f7f), CONST64(0x9ea921374f88a9a9), +CONST64(0xa82a4d8254672a2a), CONST64(0xd6bbb16d6b0abbbb), CONST64(0x23c146e29f87c1c1), CONST64(0x5153a202a6f15353), +CONST64(0x57dcae8ba572dcdc), CONST64(0x2c0b582716530b0b), CONST64(0x4e9d9cd327019d9d), CONST64(0xad6c47c1d82b6c6c), +CONST64(0xc43195f562a43131), CONST64(0xcd7487b9e8f37474), CONST64(0xfff6e309f115f6f6), CONST64(0x05460a438c4c4646), +CONST64(0x8aac092645a5acac), CONST64(0x1e893c970fb58989), CONST64(0x5014a04428b41414), CONST64(0xa3e15b42dfbae1e1), +CONST64(0x5816b04e2ca61616), CONST64(0xe83acdd274f73a3a), CONST64(0xb9696fd0d2066969), CONST64(0x2409482d12410909), +CONST64(0xdd70a7ade0d77070), CONST64(0xe2b6d954716fb6b6), CONST64(0x67d0ceb7bd1ed0d0), CONST64(0x93ed3b7ec7d6eded), +CONST64(0x17cc2edb85e2cccc), CONST64(0x15422a5784684242), CONST64(0x5a98b4c22d2c9898), CONST64(0xaaa4490e55eda4a4), +CONST64(0xa0285d8850752828), CONST64(0x6d5cda31b8865c5c), CONST64(0xc7f8933fed6bf8f8), CONST64(0x228644a411c28686) +}; + +static const ulong64 sbox7[] = { +CONST64(0x186018c07830d818), CONST64(0x238c2305af462623), CONST64(0xc63fc67ef991b8c6), CONST64(0xe887e8136fcdfbe8), +CONST64(0x8726874ca113cb87), CONST64(0xb8dab8a9626d11b8), CONST64(0x0104010805020901), CONST64(0x4f214f426e9e0d4f), +CONST64(0x36d836adee6c9b36), CONST64(0xa6a2a6590451ffa6), CONST64(0xd26fd2debdb90cd2), CONST64(0xf5f3f5fb06f70ef5), +CONST64(0x79f979ef80f29679), CONST64(0x6fa16f5fcede306f), CONST64(0x917e91fcef3f6d91), CONST64(0x525552aa07a4f852), +CONST64(0x609d6027fdc04760), CONST64(0xbccabc89766535bc), CONST64(0x9b569baccd2b379b), CONST64(0x8e028e048c018a8e), +CONST64(0xa3b6a371155bd2a3), CONST64(0x0c300c603c186c0c), CONST64(0x7bf17bff8af6847b), CONST64(0x35d435b5e16a8035), +CONST64(0x1d741de8693af51d), CONST64(0xe0a7e05347ddb3e0), CONST64(0xd77bd7f6acb321d7), CONST64(0xc22fc25eed999cc2), +CONST64(0x2eb82e6d965c432e), CONST64(0x4b314b627a96294b), CONST64(0xfedffea321e15dfe), CONST64(0x5741578216aed557), +CONST64(0x155415a8412abd15), CONST64(0x77c1779fb6eee877), CONST64(0x37dc37a5eb6e9237), CONST64(0xe5b3e57b56d79ee5), +CONST64(0x9f469f8cd923139f), CONST64(0xf0e7f0d317fd23f0), CONST64(0x4a354a6a7f94204a), CONST64(0xda4fda9e95a944da), +CONST64(0x587d58fa25b0a258), CONST64(0xc903c906ca8fcfc9), CONST64(0x29a429558d527c29), CONST64(0x0a280a5022145a0a), +CONST64(0xb1feb1e14f7f50b1), CONST64(0xa0baa0691a5dc9a0), CONST64(0x6bb16b7fdad6146b), CONST64(0x852e855cab17d985), +CONST64(0xbdcebd8173673cbd), CONST64(0x5d695dd234ba8f5d), CONST64(0x1040108050209010), CONST64(0xf4f7f4f303f507f4), +CONST64(0xcb0bcb16c08bddcb), CONST64(0x3ef83eedc67cd33e), CONST64(0x05140528110a2d05), CONST64(0x6781671fe6ce7867), +CONST64(0xe4b7e47353d597e4), CONST64(0x279c2725bb4e0227), CONST64(0x4119413258827341), CONST64(0x8b168b2c9d0ba78b), +CONST64(0xa7a6a7510153f6a7), CONST64(0x7de97dcf94fab27d), CONST64(0x956e95dcfb374995), CONST64(0xd847d88e9fad56d8), +CONST64(0xfbcbfb8b30eb70fb), CONST64(0xee9fee2371c1cdee), CONST64(0x7ced7cc791f8bb7c), CONST64(0x66856617e3cc7166), +CONST64(0xdd53dda68ea77bdd), CONST64(0x175c17b84b2eaf17), CONST64(0x47014702468e4547), CONST64(0x9e429e84dc211a9e), +CONST64(0xca0fca1ec589d4ca), CONST64(0x2db42d75995a582d), CONST64(0xbfc6bf9179632ebf), CONST64(0x071c07381b0e3f07), +CONST64(0xad8ead012347acad), CONST64(0x5a755aea2fb4b05a), CONST64(0x8336836cb51bef83), CONST64(0x33cc3385ff66b633), +CONST64(0x6391633ff2c65c63), CONST64(0x020802100a041202), CONST64(0xaa92aa39384993aa), CONST64(0x71d971afa8e2de71), +CONST64(0xc807c80ecf8dc6c8), CONST64(0x196419c87d32d119), CONST64(0x4939497270923b49), CONST64(0xd943d9869aaf5fd9), +CONST64(0xf2eff2c31df931f2), CONST64(0xe3abe34b48dba8e3), CONST64(0x5b715be22ab6b95b), CONST64(0x881a8834920dbc88), +CONST64(0x9a529aa4c8293e9a), CONST64(0x2698262dbe4c0b26), CONST64(0x32c8328dfa64bf32), CONST64(0xb0fab0e94a7d59b0), +CONST64(0xe983e91b6acff2e9), CONST64(0x0f3c0f78331e770f), CONST64(0xd573d5e6a6b733d5), CONST64(0x803a8074ba1df480), +CONST64(0xbec2be997c6127be), CONST64(0xcd13cd26de87ebcd), CONST64(0x34d034bde4688934), CONST64(0x483d487a75903248), +CONST64(0xffdbffab24e354ff), CONST64(0x7af57af78ff48d7a), CONST64(0x907a90f4ea3d6490), CONST64(0x5f615fc23ebe9d5f), +CONST64(0x2080201da0403d20), CONST64(0x68bd6867d5d00f68), CONST64(0x1a681ad07234ca1a), CONST64(0xae82ae192c41b7ae), +CONST64(0xb4eab4c95e757db4), CONST64(0x544d549a19a8ce54), CONST64(0x937693ece53b7f93), CONST64(0x2288220daa442f22), +CONST64(0x648d6407e9c86364), CONST64(0xf1e3f1db12ff2af1), CONST64(0x73d173bfa2e6cc73), CONST64(0x124812905a248212), +CONST64(0x401d403a5d807a40), CONST64(0x0820084028104808), CONST64(0xc32bc356e89b95c3), CONST64(0xec97ec337bc5dfec), +CONST64(0xdb4bdb9690ab4ddb), CONST64(0xa1bea1611f5fc0a1), CONST64(0x8d0e8d1c8307918d), CONST64(0x3df43df5c97ac83d), +CONST64(0x976697ccf1335b97), CONST64(0x0000000000000000), CONST64(0xcf1bcf36d483f9cf), CONST64(0x2bac2b4587566e2b), +CONST64(0x76c57697b3ece176), CONST64(0x82328264b019e682), CONST64(0xd67fd6fea9b128d6), CONST64(0x1b6c1bd87736c31b), +CONST64(0xb5eeb5c15b7774b5), CONST64(0xaf86af112943beaf), CONST64(0x6ab56a77dfd41d6a), CONST64(0x505d50ba0da0ea50), +CONST64(0x450945124c8a5745), CONST64(0xf3ebf3cb18fb38f3), CONST64(0x30c0309df060ad30), CONST64(0xef9bef2b74c3c4ef), +CONST64(0x3ffc3fe5c37eda3f), CONST64(0x554955921caac755), CONST64(0xa2b2a2791059dba2), CONST64(0xea8fea0365c9e9ea), +CONST64(0x6589650fecca6a65), CONST64(0xbad2bab9686903ba), CONST64(0x2fbc2f65935e4a2f), CONST64(0xc027c04ee79d8ec0), +CONST64(0xde5fdebe81a160de), CONST64(0x1c701ce06c38fc1c), CONST64(0xfdd3fdbb2ee746fd), CONST64(0x4d294d52649a1f4d), +CONST64(0x927292e4e0397692), CONST64(0x75c9758fbceafa75), CONST64(0x061806301e0c3606), CONST64(0x8a128a249809ae8a), +CONST64(0xb2f2b2f940794bb2), CONST64(0xe6bfe66359d185e6), CONST64(0x0e380e70361c7e0e), CONST64(0x1f7c1ff8633ee71f), +CONST64(0x62956237f7c45562), CONST64(0xd477d4eea3b53ad4), CONST64(0xa89aa829324d81a8), CONST64(0x966296c4f4315296), +CONST64(0xf9c3f99b3aef62f9), CONST64(0xc533c566f697a3c5), CONST64(0x25942535b14a1025), CONST64(0x597959f220b2ab59), +CONST64(0x842a8454ae15d084), CONST64(0x72d572b7a7e4c572), CONST64(0x39e439d5dd72ec39), CONST64(0x4c2d4c5a6198164c), +CONST64(0x5e655eca3bbc945e), CONST64(0x78fd78e785f09f78), CONST64(0x38e038ddd870e538), CONST64(0x8c0a8c148605988c), +CONST64(0xd163d1c6b2bf17d1), CONST64(0xa5aea5410b57e4a5), CONST64(0xe2afe2434dd9a1e2), CONST64(0x6199612ff8c24e61), +CONST64(0xb3f6b3f1457b42b3), CONST64(0x21842115a5423421), CONST64(0x9c4a9c94d625089c), CONST64(0x1e781ef0663cee1e), +CONST64(0x4311432252866143), CONST64(0xc73bc776fc93b1c7), CONST64(0xfcd7fcb32be54ffc), CONST64(0x0410042014082404), +CONST64(0x515951b208a2e351), CONST64(0x995e99bcc72f2599), CONST64(0x6da96d4fc4da226d), CONST64(0x0d340d68391a650d), +CONST64(0xfacffa8335e979fa), CONST64(0xdf5bdfb684a369df), CONST64(0x7ee57ed79bfca97e), CONST64(0x2490243db4481924), +CONST64(0x3bec3bc5d776fe3b), CONST64(0xab96ab313d4b9aab), CONST64(0xce1fce3ed181f0ce), CONST64(0x1144118855229911), +CONST64(0x8f068f0c8903838f), CONST64(0x4e254e4a6b9c044e), CONST64(0xb7e6b7d1517366b7), CONST64(0xeb8beb0b60cbe0eb), +CONST64(0x3cf03cfdcc78c13c), CONST64(0x813e817cbf1ffd81), CONST64(0x946a94d4fe354094), CONST64(0xf7fbf7eb0cf31cf7), +CONST64(0xb9deb9a1676f18b9), CONST64(0x134c13985f268b13), CONST64(0x2cb02c7d9c58512c), CONST64(0xd36bd3d6b8bb05d3), +CONST64(0xe7bbe76b5cd38ce7), CONST64(0x6ea56e57cbdc396e), CONST64(0xc437c46ef395aac4), CONST64(0x030c03180f061b03), +CONST64(0x5645568a13acdc56), CONST64(0x440d441a49885e44), CONST64(0x7fe17fdf9efea07f), CONST64(0xa99ea921374f88a9), +CONST64(0x2aa82a4d8254672a), CONST64(0xbbd6bbb16d6b0abb), CONST64(0xc123c146e29f87c1), CONST64(0x535153a202a6f153), +CONST64(0xdc57dcae8ba572dc), CONST64(0x0b2c0b582716530b), CONST64(0x9d4e9d9cd327019d), CONST64(0x6cad6c47c1d82b6c), +CONST64(0x31c43195f562a431), CONST64(0x74cd7487b9e8f374), CONST64(0xf6fff6e309f115f6), CONST64(0x4605460a438c4c46), +CONST64(0xac8aac092645a5ac), CONST64(0x891e893c970fb589), CONST64(0x145014a04428b414), CONST64(0xe1a3e15b42dfbae1), +CONST64(0x165816b04e2ca616), CONST64(0x3ae83acdd274f73a), CONST64(0x69b9696fd0d20669), CONST64(0x092409482d124109), +CONST64(0x70dd70a7ade0d770), CONST64(0xb6e2b6d954716fb6), CONST64(0xd067d0ceb7bd1ed0), CONST64(0xed93ed3b7ec7d6ed), +CONST64(0xcc17cc2edb85e2cc), CONST64(0x4215422a57846842), CONST64(0x985a98b4c22d2c98), CONST64(0xa4aaa4490e55eda4), +CONST64(0x28a0285d88507528), CONST64(0x5c6d5cda31b8865c), CONST64(0xf8c7f8933fed6bf8), CONST64(0x86228644a411c286) +}; + +#endif + +static const ulong64 cont[] = { +CONST64(0x1823c6e887b8014f), +CONST64(0x36a6d2f5796f9152), +CONST64(0x60bc9b8ea30c7b35), +CONST64(0x1de0d7c22e4bfe57), +CONST64(0x157737e59ff04ada), +CONST64(0x58c9290ab1a06b85), +CONST64(0xbd5d10f4cb3e0567), +CONST64(0xe427418ba77d95d8), +CONST64(0xfbee7c66dd17479e), +CONST64(0xca2dbf07ad5a8333), +CONST64(0x6302aa71c81949d9), +}; + +#endif /* LTC_WHIRLTAB_C */ diff --git a/deps/libtomcrypt/src/headers/tomcrypt.h b/deps/libtomcrypt/src/headers/tomcrypt.h new file mode 100644 index 0000000..c310a8c --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt.h @@ -0,0 +1,95 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMCRYPT_H_ +#define TOMCRYPT_H_ +#include +#include +#include +#include +#include +#include +#include +#include + +/* use configuration data */ +#include "tomcrypt_custom.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* version */ +#define CRYPT 0x0118 +#define SCRYPT "1.18.2-develop" + +/* max size of either a cipher/hash block or symmetric key [largest of the two] */ +#define MAXBLOCKSIZE 144 + +#ifndef TAB_SIZE +/* descriptor table size */ +#define TAB_SIZE 34 +#endif + +/* error codes [will be expanded in future releases] */ +enum { + CRYPT_OK=0, /* Result OK */ + CRYPT_ERROR, /* Generic Error */ + CRYPT_NOP, /* Not a failure but no operation was performed */ + + CRYPT_INVALID_KEYSIZE, /* Invalid key size given */ + CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */ + CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */ + + CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */ + CRYPT_INVALID_PACKET, /* Invalid input packet given */ + + CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */ + CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */ + + CRYPT_INVALID_CIPHER, /* Invalid cipher specified */ + CRYPT_INVALID_HASH, /* Invalid hash specified */ + CRYPT_INVALID_PRNG, /* Invalid PRNG specified */ + + CRYPT_MEM, /* Out of memory */ + + CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */ + CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */ + + CRYPT_INVALID_ARG, /* Generic invalid argument */ + CRYPT_FILE_NOTFOUND, /* File Not Found */ + + CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */ + + CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */ + + CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */ + + CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */ + + CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */ + + CRYPT_INVALID_PRIME_SIZE,/* Invalid size of prime requested */ + CRYPT_PK_INVALID_PADDING, /* Invalid padding on input */ + + CRYPT_HASH_OVERFLOW /* Hash applied to too many bits */ +}; + +#include "tomcrypt_cfg.h" +#include "tomcrypt_macros.h" +#include "tomcrypt_cipher.h" +#include "tomcrypt_hash.h" +#include "tomcrypt_mac.h" +#include "tomcrypt_prng.h" +#include "tomcrypt_pk.h" +#include "tomcrypt_math.h" +#include "tomcrypt_misc.h" +#include "tomcrypt_argchk.h" +#include "tomcrypt_pkcs.h" + +#ifdef __cplusplus + } +#endif + +#endif /* TOMCRYPT_H_ */ + diff --git a/deps/libtomcrypt/src/headers/tomcrypt_argchk.h b/deps/libtomcrypt/src/headers/tomcrypt_argchk.h new file mode 100644 index 0000000..f3884e9 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_argchk.h @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Defines the LTC_ARGCHK macro used within the library */ +/* ARGTYPE is defined in tomcrypt_cfg.h */ + +/* ARGTYPE is per default defined to 0 */ +#if ARGTYPE == 0 + +#include + +LTC_NORETURN void crypt_argchk(const char *v, const char *s, int d); +#define LTC_ARGCHK(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) +#define LTC_ARGCHKVD(x) do { if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); } }while(0) + +#elif ARGTYPE == 1 + +/* fatal type of error */ +#define LTC_ARGCHK(x) assert((x)) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 2 + +#define LTC_ARGCHK(x) if (!(x)) { fprintf(stderr, "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); } +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 3 + +#define LTC_ARGCHK(x) LTC_UNUSED_PARAM(x) +#define LTC_ARGCHKVD(x) LTC_ARGCHK(x) + +#elif ARGTYPE == 4 + +#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; +#define LTC_ARGCHKVD(x) if (!(x)) return; + +#endif + diff --git a/deps/libtomcrypt/src/headers/tomcrypt_cfg.h b/deps/libtomcrypt/src/headers/tomcrypt_cfg.h new file mode 100644 index 0000000..3dad466 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_cfg.h @@ -0,0 +1,323 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* This is the build config file. + * + * With this you can setup what to include/exclude automatically during any build. Just comment + * out the line that #define's the word for the thing you want to remove. phew! + */ + +#ifndef TOMCRYPT_CFG_H +#define TOMCRYPT_CFG_H + +#if defined(_WIN32) || defined(_MSC_VER) + #define LTC_CALL __cdecl +#elif !defined(LTC_CALL) + #define LTC_CALL +#endif + +#ifndef LTC_EXPORT + #define LTC_EXPORT +#endif + +/* certain platforms use macros for these, making the prototypes broken */ +#ifndef LTC_NO_PROTOTYPES + +/* you can change how memory allocation works ... */ +LTC_EXPORT void * LTC_CALL XMALLOC(size_t n); +LTC_EXPORT void * LTC_CALL XREALLOC(void *p, size_t n); +LTC_EXPORT void * LTC_CALL XCALLOC(size_t n, size_t s); +LTC_EXPORT void LTC_CALL XFREE(void *p); + +LTC_EXPORT void LTC_CALL XQSORT(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); + + +/* change the clock function too */ +LTC_EXPORT clock_t LTC_CALL XCLOCK(void); + +/* various other functions */ +LTC_EXPORT void * LTC_CALL XMEMCPY(void *dest, const void *src, size_t n); +LTC_EXPORT int LTC_CALL XMEMCMP(const void *s1, const void *s2, size_t n); +LTC_EXPORT void * LTC_CALL XMEMSET(void *s, int c, size_t n); + +LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); + +#endif + +/* some compilers do not like "inline" (or maybe "static inline"), namely: HP cc, IBM xlc */ +#if defined(__GNUC__) || defined(__xlc__) + #define LTC_INLINE __inline__ +#elif defined(_MSC_VER) || defined(__HP_cc) + #define LTC_INLINE __inline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define LTC_INLINE inline +#else + #define LTC_INLINE +#endif + +#if defined(__clang__) || defined(__GNUC_MINOR__) +#define LTC_NORETURN __attribute__ ((noreturn)) +#elif defined(_MSC_VER) +#define LTC_NORETURN __declspec(noreturn) +#else +#define LTC_NORETURN +#endif + +/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ +#ifndef ARGTYPE + #define ARGTYPE 0 +#endif + +#undef LTC_ENCRYPT +#define LTC_ENCRYPT 0 +#undef LTC_DECRYPT +#define LTC_DECRYPT 1 + +/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code + * + * Note: in order to use the optimized macros your platform must support unaligned 32 and 64 bit read/writes. + * The x86 platforms allow this but some others [ARM for instance] do not. On those platforms you **MUST** + * use the portable [slower] macros. + */ +/* detect x86/i386 32bit */ +#if defined(__i386__) || defined(__i386) || defined(_M_IX86) + #define ENDIAN_LITTLE + #define ENDIAN_32BITWORD + #define LTC_FAST +#endif + +/* detect amd64/x64 */ +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) + #define ENDIAN_LITTLE + #define ENDIAN_64BITWORD + #define LTC_FAST +#endif + +/* detect PPC32 */ +#if defined(LTC_PPC32) + #define ENDIAN_BIG + #define ENDIAN_32BITWORD + #define LTC_FAST +#endif + +/* detects MIPS R5900 processors (PS2) */ +#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips)) + #define ENDIAN_64BITWORD + #if defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) + #define ENDIAN_BIG + #else + #define ENDIAN_LITTLE + #endif +#endif + +/* detect AIX */ +#if defined(_AIX) && defined(_BIG_ENDIAN) + #define ENDIAN_BIG + #if defined(__LP64__) || defined(_ARCH_PPC64) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect HP-UX */ +#if defined(__hpux) || defined(__hpux__) + #define ENDIAN_BIG + #if defined(__ia64) || defined(__ia64__) || defined(__LP64__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect Apple OS X */ +#if defined(__APPLE__) && defined(__MACH__) + #if defined(__LITTLE_ENDIAN__) || defined(__x86_64__) + #define ENDIAN_LITTLE + #else + #define ENDIAN_BIG + #endif + #if defined(__LP64__) || defined(__x86_64__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect SPARC and SPARC64 */ +#if defined(__sparc__) || defined(__sparc) + #define ENDIAN_BIG + #if defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect IBM S390(x) */ +#if defined(__s390x__) || defined(__s390__) + #define ENDIAN_BIG + #if defined(__s390x__) + #define ENDIAN_64BITWORD + #else + #define ENDIAN_32BITWORD + #endif +#endif + +/* detect PPC64 */ +#if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) + #define ENDIAN_64BITWORD + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + #define ENDIAN_BIG + #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define ENDIAN_LITTLE + #endif + #define LTC_FAST +#endif + +/* endianness fallback */ +#if !defined(ENDIAN_BIG) && !defined(ENDIAN_LITTLE) + #if defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN || \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \ + defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \ + defined(__BIG_ENDIAN__) || \ + defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \ + defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ + defined(__m68k__) + #define ENDIAN_BIG + #elif defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN || \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \ + defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \ + defined(__LITTLE_ENDIAN__) || \ + defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \ + defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) + #define ENDIAN_LITTLE + #else + #error Cannot detect endianness + #endif +#endif + +/* ulong64: 64-bit data type */ +#ifdef _MSC_VER + #define CONST64(n) n ## ui64 + typedef unsigned __int64 ulong64; + typedef __int64 long64; +#else + #define CONST64(n) n ## ULL + typedef unsigned long long ulong64; + typedef long long long64; +#endif + +/* ulong32: "32-bit at least" data type */ +#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || \ + defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \ + defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \ + defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \ + defined(__LP64__) || defined(_LP64) || defined(__64BIT__) + typedef unsigned ulong32; + #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) + #define ENDIAN_64BITWORD + #endif +#else + typedef unsigned long ulong32; + #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD) + #define ENDIAN_32BITWORD + #endif +#endif + +#if defined(ENDIAN_64BITWORD) && !defined(_MSC_VER) +typedef unsigned long long ltc_mp_digit; +#else +typedef unsigned long ltc_mp_digit; +#endif + +/* No asm is a quick way to disable anything "not portable" */ +#ifdef LTC_NO_ASM + #define ENDIAN_NEUTRAL + #undef ENDIAN_32BITWORD + #undef ENDIAN_64BITWORD + #undef LTC_FAST + #define LTC_NO_BSWAP + #define LTC_NO_ROLC + #define LTC_NO_ROTATE +#endif + +/* No LTC_FAST if: explicitly disabled OR non-gcc/non-clang compiler OR old gcc OR using -ansi -std=c99 */ +#if defined(LTC_NO_FAST) || (__GNUC__ < 4) || defined(__STRICT_ANSI__) + #undef LTC_FAST +#endif + +#ifdef LTC_FAST + #define LTC_FAST_TYPE_PTR_CAST(x) ((LTC_FAST_TYPE*)(void*)(x)) + #ifdef ENDIAN_64BITWORD + typedef ulong64 __attribute__((__may_alias__)) LTC_FAST_TYPE; + #else + typedef ulong32 __attribute__((__may_alias__)) LTC_FAST_TYPE; + #endif +#endif + +#if !defined(ENDIAN_NEUTRAL) && (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD)) + #error You must specify a word size as well as endianess in tomcrypt_cfg.h +#endif + +#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) + #define ENDIAN_NEUTRAL +#endif + +#if (defined(ENDIAN_32BITWORD) && defined(ENDIAN_64BITWORD)) + #error Cannot be 32 and 64 bit words... +#endif + +/* gcc 4.3 and up has a bswap builtin; detect it by gcc version. + * clang also supports the bswap builtin, and although clang pretends + * to be gcc (macro-wise, anyway), clang pretends to be a version + * prior to gcc 4.3, so we can't detect bswap that way. Instead, + * clang has a __has_builtin mechanism that can be used to check + * for builtins: + * http://clang.llvm.org/docs/LanguageExtensions.html#feature_check */ +#ifndef __has_builtin + #define __has_builtin(x) 0 +#endif +#if !defined(LTC_NO_BSWAP) && defined(__GNUC__) && \ + ((__GNUC__ * 100 + __GNUC_MINOR__ >= 403) || \ + (__has_builtin(__builtin_bswap32) && __has_builtin(__builtin_bswap64))) + #define LTC_HAVE_BSWAP_BUILTIN +#endif + +#if !defined(LTC_NO_ROTATE) && (__has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateright32)) + #define LTC_HAVE_ROTATE_BUILTIN +#endif + +#if defined(__GNUC__) + #define LTC_ALIGN(n) __attribute__((aligned(n))) +#else + #define LTC_ALIGN(n) +#endif + +/* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code + * before including `tomcrypt.h` to disable this functionality. + */ +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(LTC_NO_NULL_TERMINATION_CHECK) +# define LTC_NULL_TERMINATED __attribute__((sentinel)) +#else +# define LTC_NULL_TERMINATED +#endif + +#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) +# define LTC_DEPRECATED(s) __attribute__((deprecated("replaced by " #s))) +# define PRIVATE_LTC_DEPRECATED_PRAGMA(s) _Pragma(#s) +# define LTC_DEPRECATED_PRAGMA(s) PRIVATE_LTC_DEPRECATED_PRAGMA(GCC warning s) +#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 301) +# define LTC_DEPRECATED(s) __attribute__((deprecated)) +# define LTC_DEPRECATED_PRAGMA(s) +#elif defined(_MSC_VER) && _MSC_VER >= 1500 + /* supported since Visual Studio 2008 */ +# define LTC_DEPRECATED(s) __declspec(deprecated("replaced by " #s)) +# define LTC_DEPRECATED_PRAGMA(s) __pragma(message(s)) +#else +# define LTC_DEPRECATED(s) +# define LTC_DEPRECATED_PRAGMA(s) +#endif + +#endif /* TOMCRYPT_CFG_H */ diff --git a/deps/libtomcrypt/src/headers/tomcrypt_cipher.h b/deps/libtomcrypt/src/headers/tomcrypt_cipher.h new file mode 100644 index 0000000..a3ba8f3 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_cipher.h @@ -0,0 +1,1160 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- SYMMETRIC KEY STUFF ----- + * + * We put each of the ciphers scheduled keys in their own structs then we put all of + * the key formats in one union. This makes the function prototypes easier to use. + */ +#ifdef LTC_BLOWFISH +struct blowfish_key { + ulong32 S[4][256]; + ulong32 K[18]; +}; +#endif + +#ifdef LTC_RC5 +struct rc5_key { + int rounds; + ulong32 K[50]; +}; +#endif + +#ifdef LTC_RC6 +struct rc6_key { + ulong32 K[44]; +}; +#endif + +#ifdef LTC_SAFERP +struct saferp_key { + unsigned char K[33][16]; + long rounds; +}; +#endif + +#ifdef LTC_RIJNDAEL +struct rijndael_key { + ulong32 eK[60], dK[60]; + int Nr; +}; +#endif + +#ifdef LTC_KSEED +struct kseed_key { + ulong32 K[32], dK[32]; +}; +#endif + +#ifdef LTC_KASUMI +struct kasumi_key { + ulong32 KLi1[8], KLi2[8], + KOi1[8], KOi2[8], KOi3[8], + KIi1[8], KIi2[8], KIi3[8]; +}; +#endif + +#ifdef LTC_XTEA +struct xtea_key { + unsigned long A[32], B[32]; +}; +#endif + +#ifdef LTC_TWOFISH +#ifndef LTC_TWOFISH_SMALL + struct twofish_key { + ulong32 S[4][256], K[40]; + }; +#else + struct twofish_key { + ulong32 K[40]; + unsigned char S[32], start; + }; +#endif +#endif + +#ifdef LTC_SAFER +#define LTC_SAFER_K64_DEFAULT_NOF_ROUNDS 6 +#define LTC_SAFER_K128_DEFAULT_NOF_ROUNDS 10 +#define LTC_SAFER_SK64_DEFAULT_NOF_ROUNDS 8 +#define LTC_SAFER_SK128_DEFAULT_NOF_ROUNDS 10 +#define LTC_SAFER_MAX_NOF_ROUNDS 13 +#define LTC_SAFER_BLOCK_LEN 8 +#define LTC_SAFER_KEY_LEN (1 + LTC_SAFER_BLOCK_LEN * (1 + 2 * LTC_SAFER_MAX_NOF_ROUNDS)) +typedef unsigned char safer_block_t[LTC_SAFER_BLOCK_LEN]; +typedef unsigned char safer_key_t[LTC_SAFER_KEY_LEN]; +struct safer_key { safer_key_t key; }; +#endif + +#ifdef LTC_RC2 +struct rc2_key { unsigned xkey[64]; }; +#endif + +#ifdef LTC_DES +struct des_key { + ulong32 ek[32], dk[32]; +}; + +struct des3_key { + ulong32 ek[3][32], dk[3][32]; +}; +#endif + +#ifdef LTC_CAST5 +struct cast5_key { + ulong32 K[32], keylen; +}; +#endif + +#ifdef LTC_NOEKEON +struct noekeon_key { + ulong32 K[4], dK[4]; +}; +#endif + +#ifdef LTC_SKIPJACK +struct skipjack_key { + unsigned char key[10]; +}; +#endif + +#ifdef LTC_KHAZAD +struct khazad_key { + ulong64 roundKeyEnc[8 + 1]; + ulong64 roundKeyDec[8 + 1]; +}; +#endif + +#ifdef LTC_ANUBIS +struct anubis_key { + int keyBits; + int R; + ulong32 roundKeyEnc[18 + 1][4]; + ulong32 roundKeyDec[18 + 1][4]; +}; +#endif + +#ifdef LTC_MULTI2 +struct multi2_key { + int N; + ulong32 uk[8]; +}; +#endif + +#ifdef LTC_CAMELLIA +struct camellia_key { + int R; + ulong64 kw[4], k[24], kl[6]; +}; +#endif + +#ifdef LTC_IDEA +/* rounds */ +#define LTC_IDEA_ROUNDS 8 +/* key schedule length in # of unsigned shorts */ +#define LTC_IDEA_KEYLEN 6*LTC_IDEA_ROUNDS+4 +struct idea_key { + unsigned short int ek[LTC_IDEA_KEYLEN]; /* enc key */ + unsigned short int dk[LTC_IDEA_KEYLEN]; /* dec key */ +}; +#endif + +#ifdef LTC_SERPENT +struct serpent_key { + ulong32 k[33*4]; +}; +#endif + +#ifdef LTC_TEA +struct tea_key { + ulong32 k[4]; +}; +#endif + +typedef union Symmetric_key { +#ifdef LTC_DES + struct des_key des; + struct des3_key des3; +#endif +#ifdef LTC_RC2 + struct rc2_key rc2; +#endif +#ifdef LTC_SAFER + struct safer_key safer; +#endif +#ifdef LTC_TWOFISH + struct twofish_key twofish; +#endif +#ifdef LTC_BLOWFISH + struct blowfish_key blowfish; +#endif +#ifdef LTC_RC5 + struct rc5_key rc5; +#endif +#ifdef LTC_RC6 + struct rc6_key rc6; +#endif +#ifdef LTC_SAFERP + struct saferp_key saferp; +#endif +#ifdef LTC_RIJNDAEL + struct rijndael_key rijndael; +#endif +#ifdef LTC_XTEA + struct xtea_key xtea; +#endif +#ifdef LTC_CAST5 + struct cast5_key cast5; +#endif +#ifdef LTC_NOEKEON + struct noekeon_key noekeon; +#endif +#ifdef LTC_SKIPJACK + struct skipjack_key skipjack; +#endif +#ifdef LTC_KHAZAD + struct khazad_key khazad; +#endif +#ifdef LTC_ANUBIS + struct anubis_key anubis; +#endif +#ifdef LTC_KSEED + struct kseed_key kseed; +#endif +#ifdef LTC_KASUMI + struct kasumi_key kasumi; +#endif +#ifdef LTC_MULTI2 + struct multi2_key multi2; +#endif +#ifdef LTC_CAMELLIA + struct camellia_key camellia; +#endif +#ifdef LTC_IDEA + struct idea_key idea; +#endif +#ifdef LTC_SERPENT + struct serpent_key serpent; +#endif +#ifdef LTC_TEA + struct tea_key tea; +#endif + void *data; +} symmetric_key; + +#ifdef LTC_ECB_MODE +/** A block cipher ECB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The scheduled key */ + symmetric_key key; +} symmetric_ECB; +#endif + +#ifdef LTC_CFB_MODE +/** A block cipher CFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + /** The pad used to encrypt/decrypt */ + pad[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CFB; +#endif + +#ifdef LTC_OFB_MODE +/** A block cipher OFB structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_OFB; +#endif + +#ifdef LTC_CBC_MODE +/** A block cipher CBC structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE]; + /** The scheduled key */ + symmetric_key key; +} symmetric_CBC; +#endif + + +#ifdef LTC_CTR_MODE +/** A block cipher CTR structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen, + /** The mode (endianess) of the CTR, 0==little, 1==big */ + mode, + /** counter width */ + ctrlen; + + /** The counter */ + unsigned char ctr[MAXBLOCKSIZE]; + /** The pad used to encrypt/decrypt */ + unsigned char pad[MAXBLOCKSIZE] LTC_ALIGN(16); + /** The scheduled key */ + symmetric_key key; +} symmetric_CTR; +#endif + + +#ifdef LTC_LRW_MODE +/** A LRW structure */ +typedef struct { + /** The index of the cipher chosen (must be a 128-bit block cipher) */ + int cipher; + + /** The current IV */ + unsigned char IV[16], + + /** the tweak key */ + tweak[16], + + /** The current pad, it's the product of the first 15 bytes against the tweak key */ + pad[16]; + + /** The scheduled symmetric key */ + symmetric_key key; + +#ifdef LTC_LRW_TABLES + /** The pre-computed multiplication table */ + unsigned char PC[16][256][16]; +#endif +} symmetric_LRW; +#endif + +#ifdef LTC_F8_MODE +/** A block cipher F8 structure */ +typedef struct { + /** The index of the cipher chosen */ + int cipher, + /** The block size of the given cipher */ + blocklen, + /** The padding offset */ + padlen; + /** The current IV */ + unsigned char IV[MAXBLOCKSIZE], + MIV[MAXBLOCKSIZE]; + /** Current block count */ + ulong32 blockcnt; + /** The scheduled key */ + symmetric_key key; +} symmetric_F8; +#endif + + +/** cipher descriptor table, last entry has "name == NULL" to mark the end of table */ +extern struct ltc_cipher_descriptor { + /** name of cipher */ + const char *name; + /** internal ID */ + unsigned char ID; + /** min keysize (octets) */ + int min_key_length, + /** max keysize (octets) */ + max_key_length, + /** block size (octets) */ + block_length, + /** default number of rounds */ + default_rounds; + /** Setup the cipher + @param key The input symmetric key + @param keylen The length of the input key (octets) + @param num_rounds The requested number of rounds (0==default) + @param skey [out] The destination of the scheduled key + @return CRYPT_OK if successful + */ + int (*setup)(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); + /** Encrypt a block + @param pt The plaintext + @param ct [out] The ciphertext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); + /** Decrypt a block + @param ct The ciphertext + @param pt [out] The plaintext + @param skey The scheduled key + @return CRYPT_OK if successful + */ + int (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); + /** Test the block cipher + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); + + /** Terminate the context + @param skey The scheduled key + */ + void (*done)(symmetric_key *skey); + + /** Determine a key size + @param keysize [in/out] The size of the key desired and the suggested size + @return CRYPT_OK if successful + */ + int (*keysize)(int *keysize); + +/** Accelerators **/ + /** Accelerated ECB encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, symmetric_key *skey); + + /** Accelerated ECB decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ecb_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, symmetric_key *skey); + + /** Accelerated CBC encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CBC decryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_cbc_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, symmetric_key *skey); + + /** Accelerated CTR encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param mode little or big endian counter (mode=0 or mode=1) + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_ctr_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, int mode, symmetric_key *skey); + + /** Accelerated LRW + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_encrypt)(const unsigned char *pt, unsigned char *ct, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated LRW + @param ct Ciphertext + @param pt Plaintext + @param blocks The number of complete blocks to process + @param IV The initial value (input/output) + @param tweak The LRW tweak + @param skey The scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_lrw_decrypt)(const unsigned char *ct, unsigned char *pt, unsigned long blocks, unsigned char *IV, const unsigned char *tweak, symmetric_key *skey); + + /** Accelerated CCM packet (one-shot) + @param key The secret key to use + @param keylen The length of the secret key (octets) + @param uskey A previously scheduled key [optional can be NULL] + @param nonce The session nonce [use once] + @param noncelen The length of the nonce + @param header The header for the session + @param headerlen The length of the header (octets) + @param pt [out] The plaintext + @param ptlen The length of the plaintext (octets) + @param ct [out] The ciphertext + @param tag [out] The destination tag + @param taglen [in/out] The max size and resulting size of the authentication tag + @param direction Encrypt or Decrypt direction (0 or 1) + @return CRYPT_OK if successful + */ + int (*accel_ccm_memory)( + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated GCM packet (one shot) + @param key The secret key + @param keylen The length of the secret key + @param IV The initialization vector + @param IVlen The length of the initialization vector + @param adata The additional authentication data (header) + @param adatalen The length of the adata + @param pt The plaintext + @param ptlen The length of the plaintext (ciphertext length is the same) + @param ct The ciphertext + @param tag [out] The MAC tag + @param taglen [in/out] The MAC tag length + @param direction Encrypt or Decrypt mode (GCM_ENCRYPT or GCM_DECRYPT) + @return CRYPT_OK on success + */ + int (*accel_gcm_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + + /** Accelerated one shot LTC_OMAC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*omac_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot XCBC + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + */ + int (*xcbc_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated one shot F9 + @param key The secret key + @param keylen The key length (octets) + @param in The message + @param inlen Length of message (octets) + @param out [out] Destination for tag + @param outlen [in/out] Initial and final size of out + @return CRYPT_OK on success + @remark Requires manual padding + */ + int (*f9_memory)( + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + + /** Accelerated XTS encryption + @param pt Plaintext + @param ct Ciphertext + @param blocks The number of complete blocks to process + @param tweak The 128-bit encryption tweak (input/output). + The tweak should not be encrypted on input, but + next tweak will be copied encrypted on output. + @param skey1 The first scheduled key context + @param skey2 The second scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_xts_encrypt)(const unsigned char *pt, unsigned char *ct, + unsigned long blocks, unsigned char *tweak, + const symmetric_key *skey1, const symmetric_key *skey2); + + /** Accelerated XTS decryption + @param ct Ciphertext + @param pt Plaintext + @param blocks The number of complete blocks to process + @param tweak The 128-bit encryption tweak (input/output). + The tweak should not be encrypted on input, but + next tweak will be copied encrypted on output. + @param skey1 The first scheduled key context + @param skey2 The second scheduled key context + @return CRYPT_OK if successful + */ + int (*accel_xts_decrypt)(const unsigned char *ct, unsigned char *pt, + unsigned long blocks, unsigned char *tweak, + const symmetric_key *skey1, const symmetric_key *skey2); +} cipher_descriptor[]; + +#ifdef LTC_BLOWFISH +int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int blowfish_test(void); +void blowfish_done(symmetric_key *skey); +int blowfish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor blowfish_desc; +#endif + +#ifdef LTC_RC5 +int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int rc5_test(void); +void rc5_done(symmetric_key *skey); +int rc5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc5_desc; +#endif + +#ifdef LTC_RC6 +int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int rc6_test(void); +void rc6_done(symmetric_key *skey); +int rc6_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc6_desc; +#endif + +#ifdef LTC_RC2 +int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey); +int rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int rc2_test(void); +void rc2_done(symmetric_key *skey); +int rc2_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rc2_desc; +#endif + +#ifdef LTC_SAFERP +int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int saferp_test(void); +void saferp_done(symmetric_key *skey); +int saferp_keysize(int *keysize); +extern const struct ltc_cipher_descriptor saferp_desc; +#endif + +#ifdef LTC_SAFER +int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int safer_k64_test(void); +int safer_sk64_test(void); +int safer_sk128_test(void); +void safer_done(symmetric_key *skey); +int safer_64_keysize(int *keysize); +int safer_128_keysize(int *keysize); +extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc; +#endif + +#ifdef LTC_RIJNDAEL + +/* make aes an alias */ +#define aes_setup rijndael_setup +#define aes_ecb_encrypt rijndael_ecb_encrypt +#define aes_ecb_decrypt rijndael_ecb_decrypt +#define aes_test rijndael_test +#define aes_done rijndael_done +#define aes_keysize rijndael_keysize + +#define aes_enc_setup rijndael_enc_setup +#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt +#define aes_enc_keysize rijndael_enc_keysize + +int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int rijndael_test(void); +void rijndael_done(symmetric_key *skey); +int rijndael_keysize(int *keysize); +int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +void rijndael_enc_done(symmetric_key *skey); +int rijndael_enc_keysize(int *keysize); +extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc; +extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc; +#endif + +#ifdef LTC_XTEA +int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int xtea_test(void); +void xtea_done(symmetric_key *skey); +int xtea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor xtea_desc; +#endif + +#ifdef LTC_TWOFISH +int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int twofish_test(void); +void twofish_done(symmetric_key *skey); +int twofish_keysize(int *keysize); +extern const struct ltc_cipher_descriptor twofish_desc; +#endif + +#ifdef LTC_DES +int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int des_test(void); +void des_done(symmetric_key *skey); +int des_keysize(int *keysize); +int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int des3_test(void); +void des3_done(symmetric_key *skey); +int des3_keysize(int *keysize); +extern const struct ltc_cipher_descriptor des_desc, des3_desc; +#endif + +#ifdef LTC_CAST5 +int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int cast5_test(void); +void cast5_done(symmetric_key *skey); +int cast5_keysize(int *keysize); +extern const struct ltc_cipher_descriptor cast5_desc; +#endif + +#ifdef LTC_NOEKEON +int noekeon_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int noekeon_test(void); +void noekeon_done(symmetric_key *skey); +int noekeon_keysize(int *keysize); +extern const struct ltc_cipher_descriptor noekeon_desc; +#endif + +#ifdef LTC_SKIPJACK +int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int skipjack_test(void); +void skipjack_done(symmetric_key *skey); +int skipjack_keysize(int *keysize); +extern const struct ltc_cipher_descriptor skipjack_desc; +#endif + +#ifdef LTC_KHAZAD +int khazad_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int khazad_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int khazad_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int khazad_test(void); +void khazad_done(symmetric_key *skey); +int khazad_keysize(int *keysize); +extern const struct ltc_cipher_descriptor khazad_desc; +#endif + +#ifdef LTC_ANUBIS +int anubis_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int anubis_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int anubis_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int anubis_test(void); +void anubis_done(symmetric_key *skey); +int anubis_keysize(int *keysize); +extern const struct ltc_cipher_descriptor anubis_desc; +#endif + +#ifdef LTC_KSEED +int kseed_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kseed_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int kseed_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int kseed_test(void); +void kseed_done(symmetric_key *skey); +int kseed_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kseed_desc; +#endif + +#ifdef LTC_KASUMI +int kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int kasumi_test(void); +void kasumi_done(symmetric_key *skey); +int kasumi_keysize(int *keysize); +extern const struct ltc_cipher_descriptor kasumi_desc; +#endif + + +#ifdef LTC_MULTI2 +int multi2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int multi2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int multi2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int multi2_test(void); +void multi2_done(symmetric_key *skey); +int multi2_keysize(int *keysize); +extern const struct ltc_cipher_descriptor multi2_desc; +#endif + +#ifdef LTC_CAMELLIA +int camellia_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int camellia_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int camellia_test(void); +void camellia_done(symmetric_key *skey); +int camellia_keysize(int *keysize); +extern const struct ltc_cipher_descriptor camellia_desc; +#endif + +#ifdef LTC_IDEA +int idea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int idea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int idea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int idea_test(void); +void idea_done(symmetric_key *skey); +int idea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor idea_desc; +#endif + +#ifdef LTC_SERPENT +int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int serpent_test(void); +void serpent_done(symmetric_key *skey); +int serpent_keysize(int *keysize); +extern const struct ltc_cipher_descriptor serpent_desc; +#endif + +#ifdef LTC_TEA +int tea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int tea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int tea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int tea_test(void); +void tea_done(symmetric_key *skey); +int tea_keysize(int *keysize); +extern const struct ltc_cipher_descriptor tea_desc; +#endif + +#ifdef LTC_ECB_MODE +int ecb_start(int cipher, const unsigned char *key, + int keylen, int num_rounds, symmetric_ECB *ecb); +int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb); +int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb); +int ecb_done(symmetric_ECB *ecb); +#endif + +#ifdef LTC_CFB_MODE +int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CFB *cfb); +int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb); +int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb); +int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb); +int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb); +int cfb_done(symmetric_CFB *cfb); +#endif + +#ifdef LTC_OFB_MODE +int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_OFB *ofb); +int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb); +int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb); +int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb); +int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb); +int ofb_done(symmetric_OFB *ofb); +#endif + +#ifdef LTC_CBC_MODE +int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CBC *cbc); +int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc); +int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc); +int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc); +int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc); +int cbc_done(symmetric_CBC *cbc); +#endif + +#ifdef LTC_CTR_MODE + +#define CTR_COUNTER_LITTLE_ENDIAN 0x0000 +#define CTR_COUNTER_BIG_ENDIAN 0x1000 +#define LTC_CTR_RFC3686 0x2000 + +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr); +int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr); +int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr); +int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr); +int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr); +int ctr_done(symmetric_CTR *ctr); +int ctr_test(void); +#endif + +#ifdef LTC_LRW_MODE + +#define LRW_ENCRYPT LTC_ENCRYPT +#define LRW_DECRYPT LTC_DECRYPT + +int lrw_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *tweak, + int num_rounds, + symmetric_LRW *lrw); +int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw); +int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw); +int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw); +int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw); +int lrw_done(symmetric_LRW *lrw); +int lrw_test(void); + +/* don't call */ +int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw); +#endif + +#ifdef LTC_F8_MODE +int f8_start( int cipher, const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *salt_key, int skeylen, + int num_rounds, symmetric_F8 *f8); +int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8); +int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8); +int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8); +int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8); +int f8_done(symmetric_F8 *f8); +int f8_test_mode(void); +#endif + +#ifdef LTC_XTS_MODE +typedef struct { + symmetric_key key1, key2; + int cipher; +} symmetric_xts; + +int xts_start( int cipher, + const unsigned char *key1, + const unsigned char *key2, + unsigned long keylen, + int num_rounds, + symmetric_xts *xts); + +int xts_encrypt( + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tweak, + const symmetric_xts *xts); +int xts_decrypt( + const unsigned char *ct, unsigned long ptlen, + unsigned char *pt, + unsigned char *tweak, + const symmetric_xts *xts); + +void xts_done(symmetric_xts *xts); +int xts_test(void); +void xts_mult_x(unsigned char *I); +#endif + +int find_cipher(const char *name); +int find_cipher_any(const char *name, int blocklen, int keylen); +int find_cipher_id(unsigned char ID); +int register_cipher(const struct ltc_cipher_descriptor *cipher); +int unregister_cipher(const struct ltc_cipher_descriptor *cipher); +int register_all_ciphers(void); +int cipher_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_cipher_mutex) + +/* ---- stream ciphers ---- */ + +#ifdef LTC_CHACHA + +typedef struct { + ulong32 input[16]; + unsigned char kstream[64]; + unsigned long ksleft; + unsigned long ivlen; + int rounds; +} chacha_state; + +int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds); +int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter); +int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); +int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen); +int chacha_done(chacha_state *st); +int chacha_test(void); +int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout); + +#endif /* LTC_CHACHA */ + +#ifdef LTC_SALSA20 + +typedef struct { + ulong32 input[16]; + unsigned char kstream[64]; + unsigned long ksleft; + unsigned long ivlen; + int rounds; +} salsa20_state; + +int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds); +int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter); +int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen); +int salsa20_done(salsa20_state *st); +int salsa20_test(void); +int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout); + +#endif /* LTC_SALSA20 */ + +#ifdef LTC_XSALSA20 + +int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + int rounds); +int xsalsa20_test(void); +int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout); + +#endif /* LTC_XSALSA20 */ + +#ifdef LTC_SOSEMANUK + +typedef struct { + ulong32 kc[100]; /* key_context */ + ulong32 s00, s01, s02, s03, s04, s05, s06, s07, s08, s09; + ulong32 r1, r2; + /* + * Buffering: the stream cipher produces output data by + * blocks of 640 bits. buf[] contains such a block, and + * "ptr" is the index of the next output byte. + */ + unsigned char buf[80]; + unsigned ptr; +} sosemanuk_state; + +int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen); +int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen); +int sosemanuk_crypt(sosemanuk_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen); +int sosemanuk_done(sosemanuk_state *st); +int sosemanuk_test(void); +int sosemanuk_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_SOSEMANUK */ + +#ifdef LTC_RABBIT + +typedef struct { + ulong32 x[8]; + ulong32 c[8]; + ulong32 carry; +} rabbit_ctx; + +typedef struct { + rabbit_ctx master_ctx; + rabbit_ctx work_ctx; + unsigned char block[16]; /* last keystream block containing unused bytes */ + ulong32 unused; /* count fm right */ +} rabbit_state; + +int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen); +int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen); +int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int rabbit_keystream(rabbit_state* st, unsigned char *out, unsigned long outlen); +int rabbit_done(rabbit_state *st); +int rabbit_test(void); +int rabbit_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_RABBIT */ + +#ifdef LTC_RC4_STREAM + +typedef struct { + unsigned int x, y; + unsigned char buf[256]; +} rc4_state; + +int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen); +int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen); +int rc4_stream_done(rc4_state *st); +int rc4_stream_test(void); +int rc4_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_RC4_STREAM */ + +#ifdef LTC_SOBER128_STREAM + +typedef struct { + ulong32 R[17], /* Working storage for the shift register */ + initR[17], /* saved register contents */ + konst, /* key dependent constant */ + sbuf; /* partial word encryption buffer */ + int nbuf; /* number of part-word stream bits buffered */ +} sober128_state; + +int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen); +int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen); +int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen); +int sober128_stream_done(sober128_state *st); +int sober128_stream_test(void); +int sober128_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout); + +#endif /* LTC_SOBER128_STREAM */ diff --git a/deps/libtomcrypt/src/headers/tomcrypt_custom.h b/deps/libtomcrypt/src/headers/tomcrypt_custom.h new file mode 100644 index 0000000..95c56c7 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_custom.h @@ -0,0 +1,741 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMCRYPT_CUSTOM_H_ +#define TOMCRYPT_CUSTOM_H_ + +/* macros for various libc functions you can change for embedded targets */ +#ifndef XMALLOC +#define XMALLOC malloc +#endif +#ifndef XREALLOC +#define XREALLOC realloc +#endif +#ifndef XCALLOC +#define XCALLOC calloc +#endif +#ifndef XFREE +#define XFREE free +#endif + +#ifndef XMEMSET +#define XMEMSET memset +#endif +#ifndef XMEMCPY +#define XMEMCPY memcpy +#endif +#ifndef XMEMMOVE +#define XMEMMOVE memmove +#endif +#ifndef XMEMCMP +#define XMEMCMP memcmp +#endif +/* A memory compare function that has to run in constant time, + * c.f. mem_neq() API summary. + */ +#ifndef XMEM_NEQ +#define XMEM_NEQ mem_neq +#endif +#ifndef XSTRCMP +#define XSTRCMP strcmp +#endif +#ifndef XSTRLEN +#define XSTRLEN strlen +#endif +#ifndef XSTRNCPY +#define XSTRNCPY strncpy +#endif + +#ifndef XCLOCK +#define XCLOCK clock +#endif + +#ifndef XQSORT +#define XQSORT qsort +#endif + +#if ( defined(malloc) || defined(realloc) || defined(calloc) || defined(free) || \ + defined(memset) || defined(memcpy) || defined(memcmp) || defined(strcmp) || \ + defined(strlen) || defined(strncpy) || defined(clock) || defined(qsort) ) \ + && !defined(LTC_NO_PROTOTYPES) +#define LTC_NO_PROTOTYPES +#endif + +/* shortcut to disable automatic inclusion */ +#if defined LTC_NOTHING && !defined LTC_EASY + #define LTC_NO_CIPHERS + #define LTC_NO_MODES + #define LTC_NO_HASHES + #define LTC_NO_MACS + #define LTC_NO_PRNGS + #define LTC_NO_PK + #define LTC_NO_PKCS + #define LTC_NO_MISC +#endif /* LTC_NOTHING */ + +/* Easy button? */ +#ifdef LTC_EASY + #define LTC_NO_CIPHERS + #define LTC_RIJNDAEL + #define LTC_BLOWFISH + #define LTC_DES + #define LTC_CAST5 + + #define LTC_NO_MODES + #define LTC_ECB_MODE + #define LTC_CBC_MODE + #define LTC_CTR_MODE + + #define LTC_NO_HASHES + #define LTC_SHA1 + #define LTC_SHA3 + #define LTC_SHA512 + #define LTC_SHA384 + #define LTC_SHA256 + #define LTC_SHA224 + #define LTC_HASH_HELPERS + + #define LTC_NO_MACS + #define LTC_HMAC + #define LTC_OMAC + #define LTC_CCM_MODE + + #define LTC_NO_PRNGS + #define LTC_SPRNG + #define LTC_YARROW + #define LTC_DEVRANDOM + #define LTC_TRY_URANDOM_FIRST + #define LTC_RNG_GET_BYTES + #define LTC_RNG_MAKE_PRNG + + #define LTC_NO_PK + #define LTC_MRSA + #define LTC_MECC + + #define LTC_NO_MISC + #define LTC_BASE64 +#endif /* LTC_EASY */ + +/* The minimal set of functionality to run the tests */ +#ifdef LTC_MINIMAL + #define LTC_RIJNDAEL + #define LTC_SHA256 + #define LTC_YARROW + #define LTC_CTR_MODE + + #define LTC_RNG_MAKE_PRNG + #define LTC_RNG_GET_BYTES + #define LTC_DEVRANDOM + #define LTC_TRY_URANDOM_FIRST + + #undef LTC_NO_FILE +#endif /* LTC_MINIMAL */ + +/* Enable self-test test vector checking */ +#ifndef LTC_NO_TEST + #define LTC_TEST +#endif +/* Enable extended self-tests */ +/* #define LTC_TEST_EXT */ + +/* Use small code where possible */ +/* #define LTC_SMALL_CODE */ + +/* clean the stack of functions which put private information on stack */ +/* #define LTC_CLEAN_STACK */ + +/* disable all file related functions */ +/* #define LTC_NO_FILE */ + +/* disable all forms of ASM */ +/* #define LTC_NO_ASM */ + +/* disable FAST mode */ +/* #define LTC_NO_FAST */ + +/* disable BSWAP on x86 */ +/* #define LTC_NO_BSWAP */ + +/* ---> math provider? <--- */ +#ifndef LTC_NO_MATH + +/* LibTomMath */ +/* #define LTM_DESC */ + +/* TomsFastMath */ +/* #define TFM_DESC */ + +/* GNU Multiple Precision Arithmetic Library */ +/* #define GMP_DESC */ + +#endif /* LTC_NO_MATH */ + +/* ---> Symmetric Block Ciphers <--- */ +#ifndef LTC_NO_CIPHERS + +#define LTC_BLOWFISH +#define LTC_RC2 +#define LTC_RC5 +#define LTC_RC6 +#define LTC_SAFERP +#define LTC_RIJNDAEL +#define LTC_XTEA +/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format + * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ +#define LTC_TWOFISH +#ifndef LTC_NO_TABLES + #define LTC_TWOFISH_TABLES + /* #define LTC_TWOFISH_ALL_TABLES */ +#else + #define LTC_TWOFISH_SMALL +#endif +/* #define LTC_TWOFISH_SMALL */ +/* LTC_DES includes EDE triple-DES */ +#define LTC_DES +#define LTC_CAST5 +#define LTC_NOEKEON +#define LTC_SKIPJACK +#define LTC_SAFER +#define LTC_KHAZAD +#define LTC_ANUBIS +#define LTC_ANUBIS_TWEAK +#define LTC_KSEED +#define LTC_KASUMI +#define LTC_MULTI2 +#define LTC_CAMELLIA +#define LTC_IDEA +#define LTC_SERPENT +#define LTC_TEA + +/* stream ciphers */ +#define LTC_CHACHA +#define LTC_SALSA20 +#define LTC_XSALSA20 +#define LTC_SOSEMANUK +#define LTC_RABBIT +#define LTC_RC4_STREAM +#define LTC_SOBER128_STREAM + +#endif /* LTC_NO_CIPHERS */ + + +/* ---> Block Cipher Modes of Operation <--- */ +#ifndef LTC_NO_MODES + +#define LTC_CFB_MODE +#define LTC_OFB_MODE +#define LTC_ECB_MODE +#define LTC_CBC_MODE +#define LTC_CTR_MODE + +/* F8 chaining mode */ +#define LTC_F8_MODE + +/* LRW mode */ +#define LTC_LRW_MODE +#ifndef LTC_NO_TABLES + /* like GCM mode this will enable 16 8x128 tables [64KB] that make + * seeking very fast. + */ + #define LTC_LRW_TABLES +#endif + +/* XTS mode */ +#define LTC_XTS_MODE + +#endif /* LTC_NO_MODES */ + +/* ---> One-Way Hash Functions <--- */ +#ifndef LTC_NO_HASHES + +#define LTC_CHC_HASH +#define LTC_WHIRLPOOL +#define LTC_SHA3 +#define LTC_KECCAK +#define LTC_SHA512 +#define LTC_SHA512_256 +#define LTC_SHA512_224 +#define LTC_SHA384 +#define LTC_SHA256 +#define LTC_SHA224 +#define LTC_TIGER +#define LTC_SHA1 +#define LTC_MD5 +#define LTC_MD4 +#define LTC_MD2 +#define LTC_RIPEMD128 +#define LTC_RIPEMD160 +#define LTC_RIPEMD256 +#define LTC_RIPEMD320 +#define LTC_BLAKE2S +#define LTC_BLAKE2B + +#define LTC_HASH_HELPERS + +#endif /* LTC_NO_HASHES */ + + +/* ---> MAC functions <--- */ +#ifndef LTC_NO_MACS + +#define LTC_HMAC +#define LTC_OMAC +#define LTC_PMAC +#define LTC_XCBC +#define LTC_F9_MODE +#define LTC_PELICAN +#define LTC_POLY1305 +#define LTC_BLAKE2SMAC +#define LTC_BLAKE2BMAC + +/* ---> Encrypt + Authenticate Modes <--- */ + +#define LTC_EAX_MODE + +#define LTC_OCB_MODE +#define LTC_OCB3_MODE +#define LTC_CCM_MODE +#define LTC_GCM_MODE +#define LTC_CHACHA20POLY1305_MODE + +/* Use 64KiB tables */ +#ifndef LTC_NO_TABLES + #define LTC_GCM_TABLES +#endif + +/* USE SSE2? requires GCC works on x86_32 and x86_64*/ +#ifdef LTC_GCM_TABLES +/* #define LTC_GCM_TABLES_SSE2 */ +#endif + +#endif /* LTC_NO_MACS */ + + +/* --> Pseudo Random Number Generators <--- */ +#ifndef LTC_NO_PRNGS + +/* Yarrow */ +#define LTC_YARROW + +/* a PRNG that simply reads from an available system source */ +#define LTC_SPRNG + +/* The RC4 stream cipher based PRNG */ +#define LTC_RC4 + +/* The ChaCha20 stream cipher based PRNG */ +#define LTC_CHACHA20_PRNG + +/* Fortuna PRNG */ +#define LTC_FORTUNA + +/* Greg's SOBER128 stream cipher based PRNG */ +#define LTC_SOBER128 + +/* the *nix style /dev/random device */ +#define LTC_DEVRANDOM +/* try /dev/urandom before trying /dev/random + * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */ +#define LTC_TRY_URANDOM_FIRST +/* rng_get_bytes() */ +#define LTC_RNG_GET_BYTES +/* rng_make_prng() */ +#define LTC_RNG_MAKE_PRNG + +/* enable the ltc_rng hook to integrate e.g. embedded hardware RNG's easily */ +/* #define LTC_PRNG_ENABLE_LTC_RNG */ + +#endif /* LTC_NO_PRNGS */ + +#ifdef LTC_YARROW + +/* which descriptor of AES to use? */ +/* 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] */ +#ifdef ENCRYPT_ONLY + #define LTC_YARROW_AES 0 +#else + #define LTC_YARROW_AES 2 +#endif + +#endif /* LTC_YARROW */ + +#ifdef LTC_FORTUNA + +#if !defined(LTC_FORTUNA_RESEED_RATELIMIT_STATIC) && \ + ((defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || defined(_WIN32)) + +/* time-based rate limit of the reseeding */ +#define LTC_FORTUNA_RESEED_RATELIMIT_TIMED + +/* with non-glibc or glibc 2.17+ prefer clock_gettime over gettimeofday */ +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2, 17) + #define LTC_CLOCK_GETTIME +#endif +#elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L + #define LTC_CLOCK_GETTIME +#endif + +#else + +#ifndef LTC_FORTUNA_WD +/* reseed every N calls to the read function */ +#define LTC_FORTUNA_WD 10 +#endif + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +/* make sure only one of + * LTC_FORTUNA_RESEED_RATELIMIT_STATIC + * and + * LTC_FORTUNA_RESEED_RATELIMIT_TIMED + * is defined. + */ +#undef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +#warning "undef'ed LTC_FORTUNA_RESEED_RATELIMIT_TIMED, looks like your architecture doesn't support it" +#endif + +#endif + +#ifndef LTC_FORTUNA_POOLS +/* number of pools (4..32) can save a bit of ram by lowering the count */ +#define LTC_FORTUNA_POOLS 32 +#endif + +#endif /* LTC_FORTUNA */ + + +/* ---> Public Key Crypto <--- */ +#ifndef LTC_NO_PK + +/* Include RSA support */ +#define LTC_MRSA + +/* Include Diffie-Hellman support */ +/* is_prime fails for GMP */ +#define LTC_MDH +/* Supported Key Sizes */ +#define LTC_DH768 +#define LTC_DH1024 +#define LTC_DH1536 +#define LTC_DH2048 + +#if defined(LTM_DESC) || defined(GMP_DESC) +/* tfm has a problem in fp_isprime for larger key sizes */ +#define LTC_DH3072 +#define LTC_DH4096 +#define LTC_DH6144 +#define LTC_DH8192 +#endif + +/* Digital Signature Algorithm */ +#define LTC_MDSA + +/* Ed25519 & X25519 */ +#define LTC_CURVE25519 + +/* ECC */ +#define LTC_MECC + +/* use Shamir's trick for point mul (speeds up signature verification) */ +#define LTC_ECC_SHAMIR + +#if defined(TFM_DESC) && defined(LTC_MECC) + #define LTC_MECC_ACCEL +#endif + +/* do we want fixed point ECC */ +/* #define LTC_MECC_FP */ + +#endif /* LTC_NO_PK */ + +#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_BLINDING) +/* Enable RSA blinding when doing private key operations by default */ +#define LTC_RSA_BLINDING +#endif /* LTC_NO_RSA_BLINDING */ + +#if defined(LTC_MRSA) && !defined(LTC_NO_RSA_CRT_HARDENING) +/* Enable RSA CRT hardening when doing private key operations by default */ +#define LTC_RSA_CRT_HARDENING +#endif /* LTC_NO_RSA_CRT_HARDENING */ + +#if defined(LTC_MECC) && !defined(LTC_NO_ECC_TIMING_RESISTANT) +/* Enable ECC timing resistant version by default */ +#define LTC_ECC_TIMING_RESISTANT +#endif + +/* PKCS #1 (RSA) and #5 (Password Handling) stuff */ +#ifndef LTC_NO_PKCS + +#define LTC_PKCS_1 +#define LTC_PKCS_5 +#define LTC_PKCS_8 +#define LTC_PKCS_12 + +/* Include ASN.1 DER (required by DSA/RSA) */ +#define LTC_DER + +#endif /* LTC_NO_PKCS */ + +/* misc stuff */ +#ifndef LTC_NO_MISC + +/* Various tidbits of modern neatoness */ +#define LTC_BASE64 +/* ... and it's URL safe version */ +#define LTC_BASE64_URL +/* Base32 encoding/decoding */ +#define LTC_BASE32 +/* Base16/hex encoding/decoding */ +#define LTC_BASE16 + +#define LTC_BCRYPT + +#ifndef LTC_BCRYPT_DEFAULT_ROUNDS +#define LTC_BCRYPT_DEFAULT_ROUNDS 10 +#endif + +/* Keep LTC_NO_HKDF for compatibility reasons + * superseeded by LTC_NO_MISC*/ +#ifndef LTC_NO_HKDF +/* HKDF Key Derivation/Expansion stuff */ +#define LTC_HKDF +#endif /* LTC_NO_HKDF */ + +#define LTC_ADLER32 + +#define LTC_CRC32 + +#define LTC_SSH + +#define LTC_PADDING + +#define LTC_PBES + +#endif /* LTC_NO_MISC */ + +/* cleanup */ + +#ifdef LTC_MECC +/* Supported ECC Key Sizes */ +#ifndef LTC_NO_CURVES + #define LTC_ECC_BRAINPOOLP160R1 + #define LTC_ECC_BRAINPOOLP160T1 + #define LTC_ECC_BRAINPOOLP192R1 + #define LTC_ECC_BRAINPOOLP192T1 + #define LTC_ECC_BRAINPOOLP224R1 + #define LTC_ECC_BRAINPOOLP224T1 + #define LTC_ECC_BRAINPOOLP256R1 + #define LTC_ECC_BRAINPOOLP256T1 + #define LTC_ECC_BRAINPOOLP320R1 + #define LTC_ECC_BRAINPOOLP320T1 + #define LTC_ECC_BRAINPOOLP384R1 + #define LTC_ECC_BRAINPOOLP384T1 + #define LTC_ECC_BRAINPOOLP512R1 + #define LTC_ECC_BRAINPOOLP512T1 + #define LTC_ECC_PRIME192V2 + #define LTC_ECC_PRIME192V3 + #define LTC_ECC_PRIME239V1 + #define LTC_ECC_PRIME239V2 + #define LTC_ECC_PRIME239V3 + #define LTC_ECC_SECP112R1 + #define LTC_ECC_SECP112R2 + #define LTC_ECC_SECP128R1 + #define LTC_ECC_SECP128R2 + #define LTC_ECC_SECP160K1 + #define LTC_ECC_SECP160R1 + #define LTC_ECC_SECP160R2 + #define LTC_ECC_SECP192K1 + #define LTC_ECC_SECP192R1 + #define LTC_ECC_SECP224K1 + #define LTC_ECC_SECP224R1 + #define LTC_ECC_SECP256K1 + #define LTC_ECC_SECP256R1 + #define LTC_ECC_SECP384R1 + #define LTC_ECC_SECP521R1 +#endif +#endif /* LTC_MECC */ + +#if defined(LTC_DER) + #ifndef LTC_DER_MAX_RECURSION + /* Maximum recursion limit when processing nested ASN.1 types. */ + #define LTC_DER_MAX_RECURSION 30 + #endif +#endif + +#if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH) + /* Include the MPI functionality? (required by the PK algorithms) */ + #define LTC_MPI + + #ifndef LTC_PK_MAX_RETRIES + /* iterations limit for retry-loops */ + #define LTC_PK_MAX_RETRIES 20 + #endif +#endif + +#ifdef LTC_MRSA + #define LTC_PKCS_1 +#endif + +#if defined(LTC_MRSA) || defined(LTC_MECC) + #define LTC_PKCS_8 +#endif + +#ifdef LTC_PKCS_8 + #define LTC_PADDING + #define LTC_PBES +#endif + +#if defined(LTC_CLEAN_STACK) +/* if you're sure that you want to use it, remove the line below */ + #error LTC_CLEAN_STACK is considered as broken +#endif + +#if defined(LTC_PBES) && !defined(LTC_PKCS_5) + #error LTC_PBES requires LTC_PKCS_5 +#endif + +#if defined(LTC_PBES) && !defined(LTC_PKCS_12) + #error LTC_PBES requires LTC_PKCS_12 +#endif + +#if defined(LTC_PKCS_5) && !defined(LTC_HMAC) + #error LTC_PKCS_5 requires LTC_HMAC +#endif + +#if defined(LTC_PKCS_5) && !defined(LTC_HASH_HELPERS) + #error LTC_PKCS_5 requires LTC_HASH_HELPERS +#endif + +#if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL) + #error Pelican-MAC requires LTC_RIJNDAEL +#endif + +#if defined(LTC_EAX_MODE) && !(defined(LTC_CTR_MODE) && defined(LTC_OMAC)) + #error LTC_EAX_MODE requires CTR and LTC_OMAC mode +#endif + +#if defined(LTC_YARROW) && !defined(LTC_CTR_MODE) + #error LTC_YARROW requires LTC_CTR_MODE chaining mode to be defined! +#endif + +#if defined(LTC_DER) && !defined(LTC_MPI) + #error ASN.1 DER requires MPI functionality +#endif + +#if (defined(LTC_MDSA) || defined(LTC_MRSA) || defined(LTC_MECC)) && !defined(LTC_DER) + #error PK requires ASN.1 DER functionality, make sure LTC_DER is enabled +#endif + +#if defined(LTC_BCRYPT) && !defined(LTC_BLOWFISH) + #error LTC_BCRYPT requires LTC_BLOWFISH +#endif + +#if defined(LTC_CHACHA20POLY1305_MODE) && (!defined(LTC_CHACHA) || !defined(LTC_POLY1305)) + #error LTC_CHACHA20POLY1305_MODE requires LTC_CHACHA + LTC_POLY1305 +#endif + +#if defined(LTC_CHACHA20_PRNG) && !defined(LTC_CHACHA) + #error LTC_CHACHA20_PRNG requires LTC_CHACHA +#endif + +#if defined(LTC_XSALSA20) && !defined(LTC_SALSA20) + #error LTC_XSALSA20 requires LTC_SALSA20 +#endif + +#if defined(LTC_RC4) && !defined(LTC_RC4_STREAM) + #error LTC_RC4 requires LTC_RC4_STREAM +#endif + +#if defined(LTC_SOBER128) && !defined(LTC_SOBER128_STREAM) + #error LTC_SOBER128 requires LTC_SOBER128_STREAM +#endif + +#if defined(LTC_BLAKE2SMAC) && !defined(LTC_BLAKE2S) + #error LTC_BLAKE2SMAC requires LTC_BLAKE2S +#endif + +#if defined(LTC_BLAKE2BMAC) && !defined(LTC_BLAKE2B) + #error LTC_BLAKE2BMAC requires LTC_BLAKE2B +#endif + +#if defined(LTC_SPRNG) && !defined(LTC_RNG_GET_BYTES) + #error LTC_SPRNG requires LTC_RNG_GET_BYTES +#endif + +#if defined(LTC_NO_MATH) && (defined(LTM_DESC) || defined(TFM_DESC) || defined(GMP_DESC)) + #error LTC_NO_MATH defined, but also a math descriptor +#endif + +/* THREAD management */ +#ifdef LTC_PTHREAD + +#include + +#define LTC_MUTEX_GLOBAL(x) pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; +#define LTC_MUTEX_PROTO(x) extern pthread_mutex_t x; +#define LTC_MUTEX_TYPE(x) pthread_mutex_t x; +#define LTC_MUTEX_INIT(x) LTC_ARGCHK(pthread_mutex_init(x, NULL) == 0); +#define LTC_MUTEX_LOCK(x) LTC_ARGCHK(pthread_mutex_lock(x) == 0); +#define LTC_MUTEX_UNLOCK(x) LTC_ARGCHK(pthread_mutex_unlock(x) == 0); +#define LTC_MUTEX_DESTROY(x) LTC_ARGCHK(pthread_mutex_destroy(x) == 0); + +#else + +/* default no functions */ +#define LTC_MUTEX_GLOBAL(x) +#define LTC_MUTEX_PROTO(x) +#define LTC_MUTEX_TYPE(x) +#define LTC_MUTEX_INIT(x) +#define LTC_MUTEX_LOCK(x) +#define LTC_MUTEX_UNLOCK(x) +#define LTC_MUTEX_DESTROY(x) + +#endif /* LTC_PTHREAD */ + +/* Debuggers */ + +/* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */ +/* #define LTC_VALGRIND */ + +#ifndef LTC_NO_FILE + /* buffer size for reading from a file via fread(..) */ + #ifndef LTC_FILE_READ_BUFSIZE + #define LTC_FILE_READ_BUFSIZE 8192 + #endif +#endif + +/* ECC backwards compatibility */ +#if !defined(LTC_ECC_SECP112R1) && defined(LTC_ECC112) +#define LTC_ECC_SECP112R1 +#undef LTC_ECC112 +#endif +#if !defined(LTC_ECC_SECP128R1) && defined(LTC_ECC128) +#define LTC_ECC_SECP128R1 +#undef LTC_ECC128 +#endif +#if !defined(LTC_ECC_SECP160R1) && defined(LTC_ECC160) +#define LTC_ECC_SECP160R1 +#undef LTC_ECC160 +#endif +#if !defined(LTC_ECC_SECP192R1) && defined(LTC_ECC192) +#define LTC_ECC_SECP192R1 +#undef LTC_ECC192 +#endif +#if !defined(LTC_ECC_SECP224R1) && defined(LTC_ECC224) +#define LTC_ECC_SECP224R1 +#undef LTC_ECC224 +#endif +#if !defined(LTC_ECC_SECP256R1) && defined(LTC_ECC256) +#define LTC_ECC_SECP256R1 +#undef LTC_ECC256 +#endif +#if !defined(LTC_ECC_SECP384R1) && defined(LTC_ECC384) +#define LTC_ECC_SECP384R1 +#undef LTC_ECC384 +#endif +#if !defined(LTC_ECC_SECP512R1) && defined(LTC_ECC521) +#define LTC_ECC_SECP521R1 +#undef LTC_ECC521 +#endif + +#endif /* TOMCRYPT_CUSTOM_H_ */ diff --git a/deps/libtomcrypt/src/headers/tomcrypt_hash.h b/deps/libtomcrypt/src/headers/tomcrypt_hash.h new file mode 100644 index 0000000..3c4bcf5 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_hash.h @@ -0,0 +1,503 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- HASH FUNCTIONS ---- */ +#if defined(LTC_SHA3) || defined(LTC_KECCAK) +struct sha3_state { + ulong64 saved; /* the portion of the input message that we didn't consume yet */ + ulong64 s[25]; + unsigned char sb[25 * 8]; /* used for storing `ulong64 s[25]` as little-endian bytes */ + unsigned short byte_index; /* 0..7--the next byte after the set one (starts from 0; 0--none are buffered) */ + unsigned short word_index; /* 0..24--the next word to integrate input (starts from 0) */ + unsigned short capacity_words; /* the double size of the hash output in words (e.g. 16 for Keccak 512) */ + unsigned short xof_flag; +}; +#endif + +#ifdef LTC_SHA512 +struct sha512_state { + ulong64 length, state[8]; + unsigned long curlen; + unsigned char buf[128]; +}; +#endif + +#ifdef LTC_SHA256 +struct sha256_state { + ulong64 length; + ulong32 state[8], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_SHA1 +struct sha1_state { + ulong64 length; + ulong32 state[5], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD5 +struct md5_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD4 +struct md4_state { + ulong64 length; + ulong32 state[4], curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_TIGER +struct tiger_state { + ulong64 state[3], length; + unsigned long curlen; + unsigned char buf[64]; +}; +#endif + +#ifdef LTC_MD2 +struct md2_state { + unsigned char chksum[16], X[48], buf[16]; + unsigned long curlen; +}; +#endif + +#ifdef LTC_RIPEMD128 +struct rmd128_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[4]; +}; +#endif + +#ifdef LTC_RIPEMD160 +struct rmd160_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[5]; +}; +#endif + +#ifdef LTC_RIPEMD256 +struct rmd256_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[8]; +}; +#endif + +#ifdef LTC_RIPEMD320 +struct rmd320_state { + ulong64 length; + unsigned char buf[64]; + ulong32 curlen, state[10]; +}; +#endif + +#ifdef LTC_WHIRLPOOL +struct whirlpool_state { + ulong64 length, state[8]; + unsigned char buf[64]; + ulong32 curlen; +}; +#endif + +#ifdef LTC_CHC_HASH +struct chc_state { + ulong64 length; + unsigned char state[MAXBLOCKSIZE], buf[MAXBLOCKSIZE]; + ulong32 curlen; +}; +#endif + +#ifdef LTC_BLAKE2S +struct blake2s_state { + ulong32 h[8]; + ulong32 t[2]; + ulong32 f[2]; + unsigned char buf[64]; + unsigned long curlen; + unsigned long outlen; + unsigned char last_node; +}; +#endif + +#ifdef LTC_BLAKE2B +struct blake2b_state { + ulong64 h[8]; + ulong64 t[2]; + ulong64 f[2]; + unsigned char buf[128]; + unsigned long curlen; + unsigned long outlen; + unsigned char last_node; +}; +#endif + +typedef union Hash_state { + char dummy[1]; +#ifdef LTC_CHC_HASH + struct chc_state chc; +#endif +#ifdef LTC_WHIRLPOOL + struct whirlpool_state whirlpool; +#endif +#if defined(LTC_SHA3) || defined(LTC_KECCAK) + struct sha3_state sha3; +#endif +#ifdef LTC_SHA512 + struct sha512_state sha512; +#endif +#ifdef LTC_SHA256 + struct sha256_state sha256; +#endif +#ifdef LTC_SHA1 + struct sha1_state sha1; +#endif +#ifdef LTC_MD5 + struct md5_state md5; +#endif +#ifdef LTC_MD4 + struct md4_state md4; +#endif +#ifdef LTC_MD2 + struct md2_state md2; +#endif +#ifdef LTC_TIGER + struct tiger_state tiger; +#endif +#ifdef LTC_RIPEMD128 + struct rmd128_state rmd128; +#endif +#ifdef LTC_RIPEMD160 + struct rmd160_state rmd160; +#endif +#ifdef LTC_RIPEMD256 + struct rmd256_state rmd256; +#endif +#ifdef LTC_RIPEMD320 + struct rmd320_state rmd320; +#endif +#ifdef LTC_BLAKE2S + struct blake2s_state blake2s; +#endif +#ifdef LTC_BLAKE2B + struct blake2b_state blake2b; +#endif + + void *data; +} hash_state; + +/** hash descriptor */ +extern struct ltc_hash_descriptor { + /** name of hash */ + const char *name; + /** internal ID */ + unsigned char ID; + /** Size of digest in octets */ + unsigned long hashsize; + /** Input block size in octets */ + unsigned long blocksize; + /** ASN.1 OID */ + unsigned long OID[16]; + /** Length of DER encoding */ + unsigned long OIDlen; + + /** Init a hash state + @param hash The hash to initialize + @return CRYPT_OK if successful + */ + int (*init)(hash_state *hash); + /** Process a block of data + @param hash The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful + */ + int (*process)(hash_state *hash, const unsigned char *in, unsigned long inlen); + /** Produce the digest and store it + @param hash The hash state + @param out [out] The destination of the digest + @return CRYPT_OK if successful + */ + int (*done)(hash_state *hash, unsigned char *out); + /** Self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled + */ + int (*test)(void); + + /* accelerated hmac callback: if you need to-do multiple packets just use the generic hmac_memory and provide a hash callback */ + int (*hmac_block)(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +} hash_descriptor[]; + +#ifdef LTC_CHC_HASH +int chc_register(int cipher); +int chc_init(hash_state * md); +int chc_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int chc_done(hash_state * md, unsigned char *out); +int chc_test(void); +extern const struct ltc_hash_descriptor chc_desc; +#endif + +#ifdef LTC_WHIRLPOOL +int whirlpool_init(hash_state * md); +int whirlpool_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int whirlpool_done(hash_state * md, unsigned char *out); +int whirlpool_test(void); +extern const struct ltc_hash_descriptor whirlpool_desc; +#endif + +#if defined(LTC_SHA3) || defined(LTC_KECCAK) +/* sha3_NNN_init are shared by SHA3 and KECCAK */ +int sha3_512_init(hash_state * md); +int sha3_384_init(hash_state * md); +int sha3_256_init(hash_state * md); +int sha3_224_init(hash_state * md); +/* sha3_process is the same for all variants of SHA3 + KECCAK */ +int sha3_process(hash_state * md, const unsigned char *in, unsigned long inlen); +#endif + +#ifdef LTC_SHA3 +int sha3_512_test(void); +extern const struct ltc_hash_descriptor sha3_512_desc; +int sha3_384_test(void); +extern const struct ltc_hash_descriptor sha3_384_desc; +int sha3_256_test(void); +extern const struct ltc_hash_descriptor sha3_256_desc; +int sha3_224_test(void); +extern const struct ltc_hash_descriptor sha3_224_desc; +int sha3_done(hash_state *md, unsigned char *out); +/* SHAKE128 + SHAKE256 */ +int sha3_shake_init(hash_state *md, int num); +#define sha3_shake_process(a,b,c) sha3_process(a,b,c) +int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen); +int sha3_shake_test(void); +int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, const unsigned long *outlen); +#endif + +#ifdef LTC_KECCAK +#define keccak_512_init(a) sha3_512_init(a) +#define keccak_384_init(a) sha3_384_init(a) +#define keccak_256_init(a) sha3_256_init(a) +#define keccak_224_init(a) sha3_224_init(a) +#define keccak_process(a,b,c) sha3_process(a,b,c) +extern const struct ltc_hash_descriptor keccak_512_desc; +int keccak_512_test(void); +extern const struct ltc_hash_descriptor keccak_384_desc; +int keccak_384_test(void); +extern const struct ltc_hash_descriptor keccak_256_desc; +int keccak_256_test(void); +extern const struct ltc_hash_descriptor keccak_224_desc; +int keccak_224_test(void); +int keccak_done(hash_state *md, unsigned char *out); +#endif + +#ifdef LTC_SHA512 +int sha512_init(hash_state * md); +int sha512_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha512_done(hash_state * md, unsigned char *out); +int sha512_test(void); +extern const struct ltc_hash_descriptor sha512_desc; +#endif + +#ifdef LTC_SHA384 +#ifndef LTC_SHA512 + #error LTC_SHA512 is required for LTC_SHA384 +#endif +int sha384_init(hash_state * md); +#define sha384_process sha512_process +int sha384_done(hash_state * md, unsigned char *out); +int sha384_test(void); +extern const struct ltc_hash_descriptor sha384_desc; +#endif + +#ifdef LTC_SHA512_256 +#ifndef LTC_SHA512 + #error LTC_SHA512 is required for LTC_SHA512_256 +#endif +int sha512_256_init(hash_state * md); +#define sha512_256_process sha512_process +int sha512_256_done(hash_state * md, unsigned char *out); +int sha512_256_test(void); +extern const struct ltc_hash_descriptor sha512_256_desc; +#endif + +#ifdef LTC_SHA512_224 +#ifndef LTC_SHA512 + #error LTC_SHA512 is required for LTC_SHA512_224 +#endif +int sha512_224_init(hash_state * md); +#define sha512_224_process sha512_process +int sha512_224_done(hash_state * md, unsigned char *out); +int sha512_224_test(void); +extern const struct ltc_hash_descriptor sha512_224_desc; +#endif + +#ifdef LTC_SHA256 +int sha256_init(hash_state * md); +int sha256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha256_done(hash_state * md, unsigned char *out); +int sha256_test(void); +extern const struct ltc_hash_descriptor sha256_desc; + +#ifdef LTC_SHA224 +#ifndef LTC_SHA256 + #error LTC_SHA256 is required for LTC_SHA224 +#endif +int sha224_init(hash_state * md); +#define sha224_process sha256_process +int sha224_done(hash_state * md, unsigned char *out); +int sha224_test(void); +extern const struct ltc_hash_descriptor sha224_desc; +#endif +#endif + +#ifdef LTC_SHA1 +int sha1_init(hash_state * md); +int sha1_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sha1_done(hash_state * md, unsigned char *out); +int sha1_test(void); +extern const struct ltc_hash_descriptor sha1_desc; +#endif + +#ifdef LTC_BLAKE2S +extern const struct ltc_hash_descriptor blake2s_256_desc; +int blake2s_256_init(hash_state * md); +int blake2s_256_test(void); + +extern const struct ltc_hash_descriptor blake2s_224_desc; +int blake2s_224_init(hash_state * md); +int blake2s_224_test(void); + +extern const struct ltc_hash_descriptor blake2s_160_desc; +int blake2s_160_init(hash_state * md); +int blake2s_160_test(void); + +extern const struct ltc_hash_descriptor blake2s_128_desc; +int blake2s_128_init(hash_state * md); +int blake2s_128_test(void); + +int blake2s_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2s_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int blake2s_done(hash_state * md, unsigned char *out); +#endif + +#ifdef LTC_BLAKE2B +extern const struct ltc_hash_descriptor blake2b_512_desc; +int blake2b_512_init(hash_state * md); +int blake2b_512_test(void); + +extern const struct ltc_hash_descriptor blake2b_384_desc; +int blake2b_384_init(hash_state * md); +int blake2b_384_test(void); + +extern const struct ltc_hash_descriptor blake2b_256_desc; +int blake2b_256_init(hash_state * md); +int blake2b_256_test(void); + +extern const struct ltc_hash_descriptor blake2b_160_desc; +int blake2b_160_init(hash_state * md); +int blake2b_160_test(void); + +int blake2b_init(hash_state * md, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int blake2b_done(hash_state * md, unsigned char *out); +#endif + +#ifdef LTC_MD5 +int md5_init(hash_state * md); +int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md5_done(hash_state * md, unsigned char *out); +int md5_test(void); +extern const struct ltc_hash_descriptor md5_desc; +#endif + +#ifdef LTC_MD4 +int md4_init(hash_state * md); +int md4_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md4_done(hash_state * md, unsigned char *out); +int md4_test(void); +extern const struct ltc_hash_descriptor md4_desc; +#endif + +#ifdef LTC_MD2 +int md2_init(hash_state * md); +int md2_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int md2_done(hash_state * md, unsigned char *out); +int md2_test(void); +extern const struct ltc_hash_descriptor md2_desc; +#endif + +#ifdef LTC_TIGER +int tiger_init(hash_state * md); +int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int tiger_done(hash_state * md, unsigned char *out); +int tiger_test(void); +extern const struct ltc_hash_descriptor tiger_desc; +#endif + +#ifdef LTC_RIPEMD128 +int rmd128_init(hash_state * md); +int rmd128_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd128_done(hash_state * md, unsigned char *out); +int rmd128_test(void); +extern const struct ltc_hash_descriptor rmd128_desc; +#endif + +#ifdef LTC_RIPEMD160 +int rmd160_init(hash_state * md); +int rmd160_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd160_done(hash_state * md, unsigned char *out); +int rmd160_test(void); +extern const struct ltc_hash_descriptor rmd160_desc; +#endif + +#ifdef LTC_RIPEMD256 +int rmd256_init(hash_state * md); +int rmd256_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd256_done(hash_state * md, unsigned char *out); +int rmd256_test(void); +extern const struct ltc_hash_descriptor rmd256_desc; +#endif + +#ifdef LTC_RIPEMD320 +int rmd320_init(hash_state * md); +int rmd320_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int rmd320_done(hash_state * md, unsigned char *out); +int rmd320_test(void); +extern const struct ltc_hash_descriptor rmd320_desc; +#endif + + +int find_hash(const char *name); +int find_hash_id(unsigned char ID); +int find_hash_oid(const unsigned long *ID, unsigned long IDlen); +int find_hash_any(const char *name, int digestlen); +int register_hash(const struct ltc_hash_descriptor *hash); +int unregister_hash(const struct ltc_hash_descriptor *hash); +int register_all_hashes(void); +int hash_is_valid(int idx); + +LTC_MUTEX_PROTO(ltc_hash_mutex) + +int hash_memory(int hash, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; + +#ifndef LTC_NO_FILE +int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); +int hash_file(int hash, const char *fname, unsigned char *out, unsigned long *outlen); +#endif diff --git a/deps/libtomcrypt/src/headers/tomcrypt_mac.h b/deps/libtomcrypt/src/headers/tomcrypt_mac.h new file mode 100644 index 0000000..c8f4a32 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_mac.h @@ -0,0 +1,567 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifdef LTC_HMAC +typedef struct Hmac_state { + hash_state md; + int hash; + unsigned char key[MAXBLOCKSIZE]; +} hmac_state; + +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen); +int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen); +int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen); +int hmac_test(void); +int hmac_memory(int hash, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int hmac_memory_multi(int hash, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int hmac_file(int hash, const char *fname, const unsigned char *key, + unsigned long keylen, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_OMAC + +typedef struct { + int cipher_idx, + buflen, + blklen; + unsigned char block[MAXBLOCKSIZE], + prev[MAXBLOCKSIZE], + Lu[2][MAXBLOCKSIZE]; + symmetric_key key; +} omac_state; + +int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen); +int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen); +int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen); +int omac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int omac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int omac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int omac_test(void); +#endif /* LTC_OMAC */ + +#ifdef LTC_PMAC + +typedef struct { + unsigned char Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + block[MAXBLOCKSIZE], /* currently accumulated block */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher_idx, /* cipher idx */ + block_len, /* length of block */ + buflen; /* number of bytes in the buffer */ +} pmac_state; + +int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen); +int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen); +int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen); + +int pmac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int pmac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; + +int pmac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); + +int pmac_test(void); + +/* internal functions */ +int pmac_ntz(unsigned long x); +void pmac_shift_xor(pmac_state *pmac); + +#endif /* PMAC */ + +#ifdef LTC_POLY1305 +typedef struct { + ulong32 r[5]; + ulong32 h[5]; + ulong32 pad[4]; + unsigned long leftover; + unsigned char buffer[16]; + int final; +} poly1305_state; + +int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen); +int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen); +int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen); +int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); +int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); +int poly1305_test(void); +#endif /* LTC_POLY1305 */ + +#ifdef LTC_BLAKE2SMAC +typedef hash_state blake2smac_state; +int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen); +int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen); +int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); +int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); +int blake2smac_test(void); +#endif /* LTC_BLAKE2SMAC */ + +#ifdef LTC_BLAKE2BMAC +typedef hash_state blake2bmac_state; +int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen); +int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen); +int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen); +int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); +int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); +int blake2bmac_test(void); +#endif /* LTC_BLAKE2BMAC */ + + +#ifdef LTC_PELICAN + +typedef struct pelican_state +{ + symmetric_key K; + unsigned char state[16]; + int buflen; +} pelican_state; + +int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen); +int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen); +int pelican_done(pelican_state *pelmac, unsigned char *out); +int pelican_test(void); + +int pelican_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out); + +#endif + +#ifdef LTC_XCBC + +/* add this to "keylen" to xcbc_init to use a pure three-key XCBC MAC */ +#define LTC_XCBC_PURE 0x8000UL + +typedef struct { + unsigned char K[3][MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + blocksize; +} xcbc_state; + +int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen); +int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen); +int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen); +int xcbc_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int xcbc_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int xcbc_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen); +int xcbc_test(void); + +#endif + +#ifdef LTC_F9_MODE + +typedef struct { + unsigned char akey[MAXBLOCKSIZE], + ACC[MAXBLOCKSIZE], + IV[MAXBLOCKSIZE]; + + symmetric_key key; + + int cipher, + buflen, + keylen, + blocksize; +} f9_state; + +int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen); +int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen); +int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen); +int f9_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int f9_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; +int f9_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *fname, + unsigned char *out, unsigned long *outlen); +int f9_test(void); + +#endif + +/* + * ENC+AUTH modes + */ + +#ifdef LTC_EAX_MODE + +#if !(defined(LTC_OMAC) && defined(LTC_CTR_MODE)) + #error LTC_EAX_MODE requires LTC_OMAC and CTR +#endif + +typedef struct { + unsigned char N[MAXBLOCKSIZE]; + symmetric_CTR ctr; + omac_state headeromac, ctomac; +} eax_state; + +int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen); + +int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length); +int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length); +int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length); +int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen); + +int eax_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int eax_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat); + + int eax_test(void); +#endif /* EAX MODE */ + +#ifdef LTC_OCB_MODE +typedef struct { + unsigned char L[MAXBLOCKSIZE], /* L value */ + Ls[32][MAXBLOCKSIZE], /* L shifted by i bits to the left */ + Li[MAXBLOCKSIZE], /* value of Li [current value, we calc from previous recall] */ + Lr[MAXBLOCKSIZE], /* L * x^-1 */ + R[MAXBLOCKSIZE], /* R value */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current block */ + int cipher, /* cipher idx */ + block_len; /* length of block */ +} ocb_state; + +int ocb_init(ocb_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, const unsigned char *nonce); + +int ocb_encrypt(ocb_state *ocb, const unsigned char *pt, unsigned char *ct); +int ocb_decrypt(ocb_state *ocb, const unsigned char *ct, unsigned char *pt); + +int ocb_done_encrypt(ocb_state *ocb, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_done_decrypt(ocb_state *ocb, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, int *stat); + +int ocb_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat); + +int ocb_test(void); + +/* internal functions */ +void ocb_shift_xor(ocb_state *ocb, unsigned char *Z); +int ocb_ntz(unsigned long x); +int s_ocb_done(ocb_state *ocb, const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, unsigned char *tag, unsigned long *taglen, int mode); + +#endif /* LTC_OCB_MODE */ + +#ifdef LTC_OCB3_MODE +typedef struct { + unsigned char Offset_0[MAXBLOCKSIZE], /* Offset_0 value */ + Offset_current[MAXBLOCKSIZE], /* Offset_{current_block_index} value */ + L_dollar[MAXBLOCKSIZE], /* L_$ value */ + L_star[MAXBLOCKSIZE], /* L_* value */ + L_[32][MAXBLOCKSIZE], /* L_{i} values */ + tag_part[MAXBLOCKSIZE], /* intermediate result of tag calculation */ + checksum[MAXBLOCKSIZE]; /* current checksum */ + + /* AAD related members */ + unsigned char aSum_current[MAXBLOCKSIZE], /* AAD related helper variable */ + aOffset_current[MAXBLOCKSIZE], /* AAD related helper variable */ + adata_buffer[MAXBLOCKSIZE]; /* AAD buffer */ + int adata_buffer_bytes; /* bytes in AAD buffer */ + unsigned long ablock_index; /* index # for current adata (AAD) block */ + + symmetric_key key; /* scheduled key for cipher */ + unsigned long block_index; /* index # for current data block */ + int cipher, /* cipher idx */ + tag_len, /* length of tag */ + block_len; /* length of block */ +} ocb3_state; + +int ocb3_init(ocb3_state *ocb, int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + unsigned long taglen); + +int ocb3_encrypt(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); +int ocb3_decrypt(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); +int ocb3_encrypt_last(ocb3_state *ocb, const unsigned char *pt, unsigned long ptlen, unsigned char *ct); +int ocb3_decrypt_last(ocb3_state *ocb, const unsigned char *ct, unsigned long ctlen, unsigned char *pt); +int ocb3_add_aad(ocb3_state *ocb, const unsigned char *aad, unsigned long aadlen); +int ocb3_done(ocb3_state *ocb, unsigned char *tag, unsigned long *taglen); + +int ocb3_encrypt_authenticate_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen); + +int ocb3_decrypt_verify_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *adata, unsigned long adatalen, + const unsigned char *ct, unsigned long ctlen, + unsigned char *pt, + const unsigned char *tag, unsigned long taglen, + int *stat); + +int ocb3_test(void); + +#endif /* LTC_OCB3_MODE */ + +#ifdef LTC_CCM_MODE + +#define CCM_ENCRYPT LTC_ENCRYPT +#define CCM_DECRYPT LTC_DECRYPT + +typedef struct { + symmetric_key K; + int cipher, /* which cipher */ + taglen, /* length of the tag (encoded in M value) */ + x; /* index in PAD */ + + unsigned long L, /* L value */ + ptlen, /* length that will be enc / dec */ + current_ptlen, /* current processed length */ + aadlen, /* length of the aad */ + current_aadlen, /* length of the currently provided add */ + noncelen; /* length of the nonce */ + + unsigned char PAD[16], /* flags | Nonce N | l(m) */ + ctr[16], + CTRPAD[16], + CTRlen; +} ccm_state; + +int ccm_init(ccm_state *ccm, int cipher, + const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen); + +int ccm_reset(ccm_state *ccm); + +int ccm_add_nonce(ccm_state *ccm, + const unsigned char *nonce, unsigned long noncelen); + +int ccm_add_aad(ccm_state *ccm, + const unsigned char *adata, unsigned long adatalen); + +int ccm_process(ccm_state *ccm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction); + +int ccm_done(ccm_state *ccm, + unsigned char *tag, unsigned long *taglen); + +int ccm_memory(int cipher, + const unsigned char *key, unsigned long keylen, + symmetric_key *uskey, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *header, unsigned long headerlen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); + +int ccm_test(void); + +#endif /* LTC_CCM_MODE */ + +#if defined(LRW_MODE) || defined(LTC_GCM_MODE) +void gcm_gf_mult(const unsigned char *a, const unsigned char *b, unsigned char *c); +#endif + + +/* table shared between GCM and LRW */ +#if defined(LTC_GCM_TABLES) || defined(LTC_LRW_TABLES) || ((defined(LTC_GCM_MODE) || defined(LTC_GCM_MODE)) && defined(LTC_FAST)) +extern const unsigned char gcm_shift_table[]; +#endif + +#ifdef LTC_GCM_MODE + +#define GCM_ENCRYPT LTC_ENCRYPT +#define GCM_DECRYPT LTC_DECRYPT + +#define LTC_GCM_MODE_IV 0 +#define LTC_GCM_MODE_AAD 1 +#define LTC_GCM_MODE_TEXT 2 + +typedef struct { + symmetric_key K; + unsigned char H[16], /* multiplier */ + X[16], /* accumulator */ + Y[16], /* counter */ + Y_0[16], /* initial counter */ + buf[16]; /* buffer for stuff */ + + int cipher, /* which cipher */ + ivmode, /* Which mode is the IV in? */ + mode, /* mode the GCM code is in */ + buflen; /* length of data in buf */ + + ulong64 totlen, /* 64-bit counter used for IV and AAD */ + pttotlen; /* 64-bit counter for the PT */ + +#ifdef LTC_GCM_TABLES + unsigned char PC[16][256][16] /* 16 tables of 8x128 */ +#ifdef LTC_GCM_TABLES_SSE2 +LTC_ALIGN(16) +#endif +; +#endif +} gcm_state; + +void gcm_mult_h(const gcm_state *gcm, unsigned char *I); + +int gcm_init(gcm_state *gcm, int cipher, + const unsigned char *key, int keylen); + +int gcm_reset(gcm_state *gcm); + +int gcm_add_iv(gcm_state *gcm, + const unsigned char *IV, unsigned long IVlen); + +int gcm_add_aad(gcm_state *gcm, + const unsigned char *adata, unsigned long adatalen); + +int gcm_process(gcm_state *gcm, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + int direction); + +int gcm_done(gcm_state *gcm, + unsigned char *tag, unsigned long *taglen); + +int gcm_memory( int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *IV, unsigned long IVlen, + const unsigned char *adata, unsigned long adatalen, + unsigned char *pt, unsigned long ptlen, + unsigned char *ct, + unsigned char *tag, unsigned long *taglen, + int direction); +int gcm_test(void); + +#endif /* LTC_GCM_MODE */ + +#ifdef LTC_CHACHA20POLY1305_MODE + +typedef struct { + poly1305_state poly; + chacha_state chacha; + ulong64 aadlen; + ulong64 ctlen; + int aadflg; +} chacha20poly1305_state; + +#define CHACHA20POLY1305_ENCRYPT LTC_ENCRYPT +#define CHACHA20POLY1305_DECRYPT LTC_DECRYPT + +int chacha20poly1305_init(chacha20poly1305_state *st, const unsigned char *key, unsigned long keylen); +int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen); +int chacha20poly1305_setiv_rfc7905(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 sequence_number); +int chacha20poly1305_add_aad(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen); +int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int chacha20poly1305_decrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out); +int chacha20poly1305_done(chacha20poly1305_state *st, unsigned char *tag, unsigned long *taglen); +int chacha20poly1305_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *aad, unsigned long aadlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, + unsigned char *tag, unsigned long *taglen, + int direction); +int chacha20poly1305_test(void); + +#endif /* LTC_CHACHA20POLY1305_MODE */ diff --git a/deps/libtomcrypt/src/headers/tomcrypt_macros.h b/deps/libtomcrypt/src/headers/tomcrypt_macros.h new file mode 100644 index 0000000..94aa7c3 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_macros.h @@ -0,0 +1,454 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- HELPER MACROS ---- */ +#ifdef ENDIAN_NEUTRAL + +#define STORE32L(x, y) \ + do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) + +#define LOAD32L(x, y) \ + do { x = ((ulong32)((y)[3] & 255)<<24) | \ + ((ulong32)((y)[2] & 255)<<16) | \ + ((ulong32)((y)[1] & 255)<<8) | \ + ((ulong32)((y)[0] & 255)); } while(0) + +#define STORE64L(x, y) \ + do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) + +#define LOAD64L(x, y) \ + do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) + +#define STORE32H(x, y) \ + do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) + +#define LOAD32H(x, y) \ + do { x = ((ulong32)((y)[0] & 255)<<24) | \ + ((ulong32)((y)[1] & 255)<<16) | \ + ((ulong32)((y)[2] & 255)<<8) | \ + ((ulong32)((y)[3] & 255)); } while(0) + +#define STORE64H(x, y) \ +do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) + +#define LOAD64H(x, y) \ +do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0) + + +#elif defined(ENDIAN_LITTLE) + +#ifdef LTC_HAVE_BSWAP_BUILTIN + +#define STORE32H(x, y) \ +do { ulong32 ttt = __builtin_bswap32 ((x)); \ + XMEMCPY ((y), &ttt, 4); } while(0) + +#define LOAD32H(x, y) \ +do { XMEMCPY (&(x), (y), 4); \ + (x) = __builtin_bswap32 ((x)); } while(0) + +#elif !defined(LTC_NO_BSWAP) && (defined(INTEL_CC) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__) || defined(__x86_64__)))) + +#define STORE32H(x, y) \ +asm __volatile__ ( \ + "bswapl %0 \n\t" \ + "movl %0,(%1)\n\t" \ + "bswapl %0 \n\t" \ + ::"r"(x), "r"(y): "memory"); + +#define LOAD32H(x, y) \ +asm __volatile__ ( \ + "movl (%1),%0\n\t" \ + "bswapl %0\n\t" \ + :"=r"(x): "r"(y): "memory"); + +#else + +#define STORE32H(x, y) \ + do { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } while(0) + +#define LOAD32H(x, y) \ + do { x = ((ulong32)((y)[0] & 255)<<24) | \ + ((ulong32)((y)[1] & 255)<<16) | \ + ((ulong32)((y)[2] & 255)<<8) | \ + ((ulong32)((y)[3] & 255)); } while(0) + +#endif + +#ifdef LTC_HAVE_BSWAP_BUILTIN + +#define STORE64H(x, y) \ +do { ulong64 ttt = __builtin_bswap64 ((x)); \ + XMEMCPY ((y), &ttt, 8); } while(0) + +#define LOAD64H(x, y) \ +do { XMEMCPY (&(x), (y), 8); \ + (x) = __builtin_bswap64 ((x)); } while(0) + +/* x86_64 processor */ +#elif !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__)) + +#define STORE64H(x, y) \ +asm __volatile__ ( \ + "bswapq %0 \n\t" \ + "movq %0,(%1)\n\t" \ + "bswapq %0 \n\t" \ + ::"r"(x), "r"(y): "memory"); + +#define LOAD64H(x, y) \ +asm __volatile__ ( \ + "movq (%1),%0\n\t" \ + "bswapq %0\n\t" \ + :"=r"(x): "r"(y): "memory"); + +#else + +#define STORE64H(x, y) \ +do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) + +#define LOAD64H(x, y) \ +do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \ + (((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); } while(0) + +#endif + +#ifdef ENDIAN_32BITWORD + +#define STORE32L(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32L(x, y) \ + do { XMEMCPY(&(x), y, 4); } while(0) + +#define STORE64L(x, y) \ + do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) + +#define LOAD64L(x, y) \ + do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) + +#else /* 64-bit words then */ + +#define STORE32L(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32L(x, y) \ + do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) + +#define STORE64L(x, y) \ + do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) + +#define LOAD64L(x, y) \ + do { XMEMCPY(&(x), y, 8); } while(0) + +#endif /* ENDIAN_64BITWORD */ + +#elif defined(ENDIAN_BIG) + +#define STORE32L(x, y) \ + do { (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) + +#define LOAD32L(x, y) \ + do { x = ((ulong32)((y)[3] & 255)<<24) | \ + ((ulong32)((y)[2] & 255)<<16) | \ + ((ulong32)((y)[1] & 255)<<8) | \ + ((ulong32)((y)[0] & 255)); } while(0) + +#define STORE64L(x, y) \ +do { (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \ + (y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \ + (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \ + (y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); } while(0) + +#define LOAD64L(x, y) \ +do { x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48) | \ + (((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32) | \ + (((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16) | \ + (((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); } while(0) + +#ifdef ENDIAN_32BITWORD + +#define STORE32H(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32H(x, y) \ + do { XMEMCPY(&(x), y, 4); } while(0) + +#define STORE64H(x, y) \ + do { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } while(0) + +#define LOAD64H(x, y) \ + do { x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48)| \ + (((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32)| \ + (((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16)| \ + (((ulong64)((y)[6] & 255))<<8)| (((ulong64)((y)[7] & 255))); } while(0) + +#else /* 64-bit words then */ + +#define STORE32H(x, y) \ + do { ulong32 ttt = (x); XMEMCPY(y, &ttt, 4); } while(0) + +#define LOAD32H(x, y) \ + do { XMEMCPY(&(x), y, 4); x &= 0xFFFFFFFF; } while(0) + +#define STORE64H(x, y) \ + do { ulong64 ttt = (x); XMEMCPY(y, &ttt, 8); } while(0) + +#define LOAD64H(x, y) \ + do { XMEMCPY(&(x), y, 8); } while(0) + +#endif /* ENDIAN_64BITWORD */ +#endif /* ENDIAN_BIG */ + +#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \ + ((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) ) + + +/* 32-bit Rotates */ +#if defined(_MSC_VER) +#define LTC_ROx_BUILTIN + +/* instrinsic rotate */ +#include +#pragma intrinsic(_rotr,_rotl) +#define ROR(x,n) _rotr(x,n) +#define ROL(x,n) _rotl(x,n) +#define RORc(x,n) ROR(x,n) +#define ROLc(x,n) ROL(x,n) + +#elif defined(LTC_HAVE_ROTATE_BUILTIN) +#define LTC_ROx_BUILTIN + +#define ROR(x,n) __builtin_rotateright32(x,n) +#define ROL(x,n) __builtin_rotateleft32(x,n) +#define ROLc(x,n) ROL(x,n) +#define RORc(x,n) ROR(x,n) + +#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) +#define LTC_ROx_ASM + +static inline ulong32 ROL(ulong32 word, int i) +{ + asm ("roll %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline ulong32 ROR(ulong32 word, int i) +{ + asm ("rorl %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +#define ROLc(word,i) ({ \ + ulong32 ROLc_tmp = (word); \ + __asm__ ("roll %2, %0" : \ + "=r" (ROLc_tmp) : \ + "0" (ROLc_tmp), \ + "I" (i)); \ + ROLc_tmp; \ + }) +#define RORc(word,i) ({ \ + ulong32 RORc_tmp = (word); \ + __asm__ ("rorl %2, %0" : \ + "=r" (RORc_tmp) : \ + "0" (RORc_tmp), \ + "I" (i)); \ + RORc_tmp; \ + }) + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + +#elif !defined(__STRICT_ANSI__) && defined(LTC_PPC32) +#define LTC_ROx_ASM + +static inline ulong32 ROL(ulong32 word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (i)); + return word; +} + +static inline ulong32 ROR(ulong32 word, int i) +{ + asm ("rotlw %0,%0,%2" + :"=r" (word) + :"0" (word),"r" (32-i)); + return word; +} + +#ifndef LTC_NO_ROLC + +static inline ulong32 ROLc(ulong32 word, const int i) +{ + asm ("rotlwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +static inline ulong32 RORc(ulong32 word, const int i) +{ + asm ("rotrwi %0,%0,%2" + :"=r" (word) + :"0" (word),"I" (i)); + return word; +} + +#else + +#define ROLc ROL +#define RORc ROR + +#endif + + +#else + +/* rotates the hard way */ +#define ROL(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define ROR(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define ROLc(x, y) ( (((ulong32)(x)<<(ulong32)((y)&31)) | (((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) +#define RORc(x, y) ( ((((ulong32)(x)&0xFFFFFFFFUL)>>(ulong32)((y)&31)) | ((ulong32)(x)<<(ulong32)((32-((y)&31))&31))) & 0xFFFFFFFFUL) + +#endif + + +/* 64-bit Rotates */ +#if defined(_MSC_VER) + +/* instrinsic rotate */ +#include +#pragma intrinsic(_rotr64,_rotr64) +#define ROR64(x,n) _rotr64(x,n) +#define ROL64(x,n) _rotl64(x,n) +#define ROR64c(x,n) ROR64(x,n) +#define ROL64c(x,n) ROL64(x,n) + +#elif defined(LTC_HAVE_ROTATE_BUILTIN) + +#define ROR64(x,n) __builtin_rotateright64(x,n) +#define ROL64(x,n) __builtin_rotateleft64(x,n) +#define ROR64c(x,n) ROR64(x,n) +#define ROL64c(x,n) ROL64(x,n) + +#elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && defined(__x86_64__) && !defined(INTEL_CC) && !defined(LTC_NO_ASM) + +static inline ulong64 ROL64(ulong64 word, int i) +{ + asm("rolq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +static inline ulong64 ROR64(ulong64 word, int i) +{ + asm("rorq %%cl,%0" + :"=r" (word) + :"0" (word),"c" (i)); + return word; +} + +#ifndef LTC_NO_ROLC + +#define ROL64c(word,i) ({ \ + ulong64 ROL64c_tmp = word; \ + __asm__ ("rolq %2, %0" : \ + "=r" (ROL64c_tmp) : \ + "0" (ROL64c_tmp), \ + "J" (i)); \ + ROL64c_tmp; \ + }) +#define ROR64c(word,i) ({ \ + ulong64 ROR64c_tmp = word; \ + __asm__ ("rorq %2, %0" : \ + "=r" (ROR64c_tmp) : \ + "0" (ROR64c_tmp), \ + "J" (i)); \ + ROR64c_tmp; \ + }) + +#else /* LTC_NO_ROLC */ + +#define ROL64c ROL64 +#define ROR64c ROR64 + +#endif + +#else /* Not x86_64 */ + +#define ROL64(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROL64c(x, y) \ + ( (((x)<<((ulong64)(y)&63)) | \ + (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#define ROR64c(x, y) \ + ( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \ + ((x)<<(((ulong64)64-((y)&63))&63))) & CONST64(0xFFFFFFFFFFFFFFFF)) + +#endif + +#ifndef MAX + #define MAX(x, y) ( ((x)>(y))?(x):(y) ) +#endif + +#ifndef MIN + #define MIN(x, y) ( ((x)<(y))?(x):(y) ) +#endif + +#ifndef LTC_UNUSED_PARAM + #define LTC_UNUSED_PARAM(x) (void)(x) +#endif + +/* there is no snprintf before Visual C++ 2015 */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#endif diff --git a/deps/libtomcrypt/src/headers/tomcrypt_math.h b/deps/libtomcrypt/src/headers/tomcrypt_math.h new file mode 100644 index 0000000..b7dedf6 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_math.h @@ -0,0 +1,519 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** math functions **/ + +#define LTC_MP_LT -1 +#define LTC_MP_EQ 0 +#define LTC_MP_GT 1 + +#define LTC_MP_NO 0 +#define LTC_MP_YES 1 + +#ifndef LTC_MECC + typedef void ecc_point; +#endif + +#ifndef LTC_MRSA + typedef void rsa_key; +#endif + +#ifndef LTC_MILLER_RABIN_REPS + /* Number of rounds of the Miller-Rabin test + * "Reasonable values of reps are between 15 and 50." c.f. gmp doc of mpz_probab_prime_p() + * As of https://security.stackexchange.com/a/4546 we should use 40 rounds */ + #define LTC_MILLER_RABIN_REPS 40 +#endif + +int radix_to_bin(const void *in, int radix, void *out, unsigned long *len); + +/** math descriptor */ +typedef struct { + /** Name of the math provider */ + const char *name; + + /** Bits per digit, amount of bits must fit in an unsigned long */ + int bits_per_digit; + +/* ---- init/deinit functions ---- */ + + /** initialize a bignum + @param a The number to initialize + @return CRYPT_OK on success + */ + int (*init)(void **a); + + /** init copy + @param dst The number to initialize and write to + @param src The number to copy from + @return CRYPT_OK on success + */ + int (*init_copy)(void **dst, void *src); + + /** deinit + @param a The number to free + @return CRYPT_OK on success + */ + void (*deinit)(void *a); + +/* ---- data movement ---- */ + + /** negate + @param src The number to negate + @param dst The destination + @return CRYPT_OK on success + */ + int (*neg)(void *src, void *dst); + + /** copy + @param src The number to copy from + @param dst The number to write to + @return CRYPT_OK on success + */ + int (*copy)(void *src, void *dst); + +/* ---- trivial low level functions ---- */ + + /** set small constant + @param a Number to write to + @param n Source upto bits_per_digit (actually meant for very small constants) + @return CRYPT_OK on success + */ + int (*set_int)(void *a, ltc_mp_digit n); + + /** get small constant + @param a Small number to read, + only fetches up to bits_per_digit from the number + @return The lower bits_per_digit of the integer (unsigned) + */ + unsigned long (*get_int)(void *a); + + /** get digit n + @param a The number to read from + @param n The number of the digit to fetch + @return The bits_per_digit sized n'th digit of a + */ + ltc_mp_digit (*get_digit)(void *a, int n); + + /** Get the number of digits that represent the number + @param a The number to count + @return The number of digits used to represent the number + */ + int (*get_digit_count)(void *a); + + /** compare two integers + @param a The left side integer + @param b The right side integer + @return LTC_MP_LT if a < b, + LTC_MP_GT if a > b and + LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare)(void *a, void *b); + + /** compare against int + @param a The left side integer + @param b The right side integer (upto bits_per_digit) + @return LTC_MP_LT if a < b, + LTC_MP_GT if a > b and + LTC_MP_EQ otherwise. (signed comparison) + */ + int (*compare_d)(void *a, ltc_mp_digit n); + + /** Count the number of bits used to represent the integer + @param a The integer to count + @return The number of bits required to represent the integer + */ + int (*count_bits)(void * a); + + /** Count the number of LSB bits which are zero + @param a The integer to count + @return The number of contiguous zero LSB bits + */ + int (*count_lsb_bits)(void *a); + + /** Compute a power of two + @param a The integer to store the power in + @param n The power of two you want to store (a = 2^n) + @return CRYPT_OK on success + */ + int (*twoexpt)(void *a , int n); + +/* ---- radix conversions ---- */ + + /** read ascii string + @param a The integer to store into + @param str The string to read + @param radix The radix the integer has been represented in (2-64) + @return CRYPT_OK on success + */ + int (*read_radix)(void *a, const char *str, int radix); + + /** write number to string + @param a The integer to store + @param str The destination for the string + @param radix The radix the integer is to be represented in (2-64) + @return CRYPT_OK on success + */ + int (*write_radix)(void *a, char *str, int radix); + + /** get size as unsigned char string + @param a The integer to get the size (when stored in array of octets) + @return The length of the integer in octets + */ + unsigned long (*unsigned_size)(void *a); + + /** store an integer as an array of octets + @param src The integer to store + @param dst The buffer to store the integer in + @return CRYPT_OK on success + */ + int (*unsigned_write)(void *src, unsigned char *dst); + + /** read an array of octets and store as integer + @param dst The integer to load + @param src The array of octets + @param len The number of octets + @return CRYPT_OK on success + */ + int (*unsigned_read)( void *dst, + unsigned char *src, + unsigned long len); + +/* ---- basic math ---- */ + + /** add two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*add)(void *a, void *b, void *c); + + /** add two integers + @param a The first source integer + @param b The second source integer + (single digit of upto bits_per_digit in length) + @param c The destination of "a + b" + @return CRYPT_OK on success + */ + int (*addi)(void *a, ltc_mp_digit b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*sub)(void *a, void *b, void *c); + + /** subtract two integers + @param a The first source integer + @param b The second source integer + (single digit of upto bits_per_digit in length) + @param c The destination of "a - b" + @return CRYPT_OK on success + */ + int (*subi)(void *a, ltc_mp_digit b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer + (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*mul)(void *a, void *b, void *c); + + /** multiply two integers + @param a The first source integer + @param b The second source integer + (single digit of upto bits_per_digit in length) + @param c The destination of "a * b" + @return CRYPT_OK on success + */ + int (*muli)(void *a, ltc_mp_digit b, void *c); + + /** Square an integer + @param a The integer to square + @param b The destination + @return CRYPT_OK on success + */ + int (*sqr)(void *a, void *b); + + /** Square root (mod prime) + @param a The integer to compute square root mod prime from + @param b The prime + @param c The destination + @return CRYPT_OK on success + */ + int (*sqrtmod_prime)(void *a, void *b, void *c); + + /** Divide an integer + @param a The dividend + @param b The divisor + @param c The quotient (can be NULL to signify don't care) + @param d The remainder (can be NULL to signify don't care) + @return CRYPT_OK on success + */ + int (*mpdiv)(void *a, void *b, void *c, void *d); + + /** divide by two + @param a The integer to divide (shift right) + @param b The destination + @return CRYPT_OK on success + */ + int (*div_2)(void *a, void *b); + + /** Get remainder (small value) + @param a The integer to reduce + @param b The modulus (upto bits_per_digit in length) + @param c The destination for the residue + @return CRYPT_OK on success + */ + int (*modi)(void *a, ltc_mp_digit b, ltc_mp_digit *c); + + /** gcd + @param a The first integer + @param b The second integer + @param c The destination for (a, b) + @return CRYPT_OK on success + */ + int (*gcd)(void *a, void *b, void *c); + + /** lcm + @param a The first integer + @param b The second integer + @param c The destination for [a, b] + @return CRYPT_OK on success + */ + int (*lcm)(void *a, void *b, void *c); + + /** Modular multiplication + @param a The first source + @param b The second source + @param c The modulus + @param d The destination (a*b mod c) + @return CRYPT_OK on success + */ + int (*mulmod)(void *a, void *b, void *c, void *d); + + /** Modular squaring + @param a The first source + @param b The modulus + @param c The destination (a*a mod b) + @return CRYPT_OK on success + */ + int (*sqrmod)(void *a, void *b, void *c); + + /** Modular inversion + @param a The value to invert + @param b The modulus + @param c The destination (1/a mod b) + @return CRYPT_OK on success + */ + int (*invmod)(void *, void *, void *); + +/* ---- reduction ---- */ + + /** setup Montgomery + @param a The modulus + @param b The destination for the reduction digit + @return CRYPT_OK on success + */ + int (*montgomery_setup)(void *a, void **b); + + /** get normalization value + @param a The destination for the normalization value + @param b The modulus + @return CRYPT_OK on success + */ + int (*montgomery_normalization)(void *a, void *b); + + /** reduce a number + @param a The number [and dest] to reduce + @param b The modulus + @param c The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + int (*montgomery_reduce)(void *a, void *b, void *c); + + /** clean up (frees memory) + @param a The value "b" from montgomery_setup() + @return CRYPT_OK on success + */ + void (*montgomery_deinit)(void *a); + +/* ---- exponentiation ---- */ + + /** Modular exponentiation + @param a The base integer + @param b The power (can be negative) integer + @param c The modulus integer + @param d The destination + @return CRYPT_OK on success + */ + int (*exptmod)(void *a, void *b, void *c, void *d); + + /** Primality testing + @param a The integer to test + @param b The number of Miller-Rabin tests that shall be executed + @param c The destination of the result (FP_YES if prime) + @return CRYPT_OK on success + */ + int (*isprime)(void *a, int b, int *c); + +/* ---- (optional) ecc point math ---- */ + + /** ECC GF(p) point multiplication (from the NIST curves) + @param k The integer to multiply the point by + @param G The point to multiply + @param R The destination for kG + @param a ECC curve parameter a + @param modulus The modulus for the field + @param map Boolean indicated whether to map back to affine or not + (can be ignored if you work in affine only) + @return CRYPT_OK on success + */ + int (*ecc_ptmul)( void *k, + const ecc_point *G, + ecc_point *R, + void *a, + void *modulus, + int map); + + /** ECC GF(p) point addition + @param P The first point + @param Q The second point + @param R The destination of P + Q + @param ma The curve parameter "a" in montgomery form + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptadd)(const ecc_point *P, + const ecc_point *Q, + ecc_point *R, + void *ma, + void *modulus, + void *mp); + + /** ECC GF(p) point double + @param P The first point + @param R The destination of 2P + @param ma The curve parameter "a" in montgomery form + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + */ + int (*ecc_ptdbl)(const ecc_point *P, + ecc_point *R, + void *ma, + void *modulus, + void *mp); + + /** ECC mapping from projective to affine, + currently uses (x,y,z) => (x/z^2, y/z^3, 1) + @param P The point to map + @param modulus The modulus + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success + @remark The mapping can be different but keep in mind a + ecc_point only has three integers (x,y,z) so if + you use a different mapping you have to make it fit. + */ + int (*ecc_map)(ecc_point *P, void *modulus, void *mp); + + /** Computes kA*A + kB*B = C using Shamir's Trick + @param A First point to multiply + @param kA What to multiple A by + @param B Second point to multiply + @param kB What to multiple B by + @param C [out] Destination point (can overlap with A or B) + @param ma The curve parameter "a" in montgomery form + @param modulus Modulus for curve + @return CRYPT_OK on success + */ + int (*ecc_mul2add)(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); + +/* ---- (optional) rsa optimized math (for internal CRT) ---- */ + + /** RSA Key Generation + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the key in octets + @param e The "e" value (public key). + e==65537 is a good choice + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed + */ + int (*rsa_keygen)(prng_state *prng, + int wprng, + int size, + long e, + rsa_key *key); + + /** RSA exponentiation + @param in The octet array representing the base + @param inlen The length of the input + @param out The destination (to be stored in an octet array format) + @param outlen The length of the output buffer and the resulting size + (zero padded to the size of the modulus) + @param which PK_PUBLIC for public RSA and PK_PRIVATE for private RSA + @param key The RSA key to use + @return CRYPT_OK on success + */ + int (*rsa_me)(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + const rsa_key *key); + +/* ---- basic math continued ---- */ + + /** Modular addition + @param a The first source + @param b The second source + @param c The modulus + @param d The destination (a + b mod c) + @return CRYPT_OK on success + */ + int (*addmod)(void *a, void *b, void *c, void *d); + + /** Modular substraction + @param a The first source + @param b The second source + @param c The modulus + @param d The destination (a - b mod c) + @return CRYPT_OK on success + */ + int (*submod)(void *a, void *b, void *c, void *d); + +/* ---- misc stuff ---- */ + + /** Make a pseudo-random mpi + @param a The mpi to make random + @param size The desired length + @return CRYPT_OK on success + */ + int (*rand)(void *a, int size); +} ltc_math_descriptor; + +extern ltc_math_descriptor ltc_mp; + +int ltc_init_multi(void **a, ...) LTC_NULL_TERMINATED; +void ltc_deinit_multi(void *a, ...) LTC_NULL_TERMINATED; +void ltc_cleanup_multi(void **a, ...) LTC_NULL_TERMINATED; + +#ifdef LTM_DESC +extern const ltc_math_descriptor ltm_desc; +#endif + +#ifdef TFM_DESC +extern const ltc_math_descriptor tfm_desc; +#endif + +#ifdef GMP_DESC +extern const ltc_math_descriptor gmp_desc; +#endif diff --git a/deps/libtomcrypt/src/headers/tomcrypt_misc.h b/deps/libtomcrypt/src/headers/tomcrypt_misc.h new file mode 100644 index 0000000..3a2b7b1 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_misc.h @@ -0,0 +1,179 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- LTC_BASE64 Routines ---- */ +#ifdef LTC_BASE64 +int base64_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen); + +int base64_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_BASE64_URL +int base64url_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen); +int base64url_strict_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen); + +int base64url_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64url_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int base64url_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +#endif + +/* ---- BASE32 Routines ---- */ +#ifdef LTC_BASE32 +typedef enum { + BASE32_RFC4648 = 0, + BASE32_BASE32HEX = 1, + BASE32_ZBASE32 = 2, + BASE32_CROCKFORD = 3 +} base32_alphabet; +int base32_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + base32_alphabet id); +int base32_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + base32_alphabet id); +#endif + +/* ---- BASE16 Routines ---- */ +#ifdef LTC_BASE16 +int base16_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int options); +int base16_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +#endif + +#ifdef LTC_BCRYPT +int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, + const unsigned char *salt, unsigned long salt_len, + unsigned int rounds, int hash_idx, + unsigned char *out, unsigned long *outlen); +#endif + +/* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ +#ifdef LTC_HKDF + +int hkdf_test(void); + +int hkdf_extract(int hash_idx, + const unsigned char *salt, unsigned long saltlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int hkdf_expand(int hash_idx, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen); + +int hkdf(int hash_idx, + const unsigned char *salt, unsigned long saltlen, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen); + +#endif /* LTC_HKDF */ + +/* ---- MEM routines ---- */ +int mem_neq(const void *a, const void *b, size_t len); +void zeromem(volatile void *out, size_t outlen); +void burn_stack(unsigned long len); + +const char *error_to_string(int err); + +extern const char *crypt_build_settings; + +/* ---- HMM ---- */ +int crypt_fsa(void *mp, ...) LTC_NULL_TERMINATED; + +/* ---- Dynamic language support ---- */ +int crypt_get_constant(const char* namein, int *valueout); +int crypt_list_all_constants(char *names_list, unsigned int *names_list_size); + +int crypt_get_size(const char* namein, unsigned int *sizeout); +int crypt_list_all_sizes(char *names_list, unsigned int *names_list_size); + +#ifdef LTM_DESC +LTC_DEPRECATED(crypt_mp_init) void init_LTM(void); +#endif +#ifdef TFM_DESC +LTC_DEPRECATED(crypt_mp_init) void init_TFM(void); +#endif +#ifdef GMP_DESC +LTC_DEPRECATED(crypt_mp_init) void init_GMP(void); +#endif +int crypt_mp_init(const char* mpi); + +#ifdef LTC_ADLER32 +typedef struct adler32_state_s +{ + unsigned short s[2]; +} adler32_state; + +void adler32_init(adler32_state *ctx); +void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length); +void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size); +int adler32_test(void); +#endif + +#ifdef LTC_CRC32 +typedef struct crc32_state_s +{ + ulong32 crc; +} crc32_state; + +void crc32_init(crc32_state *ctx); +void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length); +void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size); +int crc32_test(void); +#endif + + +#ifdef LTC_PADDING + +enum padding_type { + LTC_PAD_PKCS7 = 0x0000U, +#ifdef LTC_RNG_GET_BYTES + LTC_PAD_ISO_10126 = 0x1000U, +#endif + LTC_PAD_ANSI_X923 = 0x2000U, + LTC_PAD_SSH = 0x3000U, + /* The following padding modes don't contain the padding + * length as last byte of the padding. + */ + LTC_PAD_ONE_AND_ZERO = 0x8000U, + LTC_PAD_ZERO = 0x9000U, + LTC_PAD_ZERO_ALWAYS = 0xA000U, +}; + +int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode); +int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode); +#endif /* LTC_PADDING */ + +#ifdef LTC_SSH +typedef enum ssh_data_type_ { + LTC_SSHDATA_EOL, + LTC_SSHDATA_BYTE, + LTC_SSHDATA_BOOLEAN, + LTC_SSHDATA_UINT32, + LTC_SSHDATA_UINT64, + LTC_SSHDATA_STRING, + LTC_SSHDATA_MPINT, + LTC_SSHDATA_NAMELIST, +} ssh_data_type; + +/* VA list handy helpers with tuples of */ +int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) LTC_NULL_TERMINATED; +#endif /* LTC_SSH */ + +int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); diff --git a/deps/libtomcrypt/src/headers/tomcrypt_pk.h b/deps/libtomcrypt/src/headers/tomcrypt_pk.h new file mode 100644 index 0000000..132fc74 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_pk.h @@ -0,0 +1,803 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- NUMBER THEORY ---- */ + +enum public_key_type { + /* Refers to the public key */ + PK_PUBLIC = 0x0000, + /* Refers to the private key */ + PK_PRIVATE = 0x0001, + + /* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */ + PK_STD = 0x1000, + /* Indicates compressed public ECC key */ + PK_COMPRESSED = 0x2000, + /* Indicates ECC key with the curve specified by OID */ + PK_CURVEOID = 0x4000 +}; + +int rand_prime(void *N, long len, prng_state *prng, int wprng); + +/* ---- RSA ---- */ +#ifdef LTC_MRSA + +/** RSA PKCS style key */ +typedef struct Rsa_key { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + /** The public exponent */ + void *e; + /** The private exponent */ + void *d; + /** The modulus */ + void *N; + /** The p factor of N */ + void *p; + /** The q factor of N */ + void *q; + /** The 1/q mod p CRT param */ + void *qP; + /** The d mod (p - 1) CRT param */ + void *dP; + /** The d mod (q - 1) CRT param */ + void *dQ; +} rsa_key; + +int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key); +int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size, + const unsigned char *e, unsigned long elen, rsa_key *key); +int rsa_get_size(const rsa_key *key); + +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + const rsa_key *key); + +void rsa_free(rsa_key *key); + +/* These use PKCS #1 v2.0 padding */ +#define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \ + rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, LTC_PKCS_1_OAEP, key) + +#define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \ + rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, LTC_PKCS_1_OAEP, stat, key) + +#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \ + rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key) + +#define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \ + rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key) + +#define rsa_sign_saltlen_get_max(hash_idx, key) \ + rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) + +/* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */ +int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, + int hash_idx, int padding, + const rsa_key *key); + +int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int padding, + int *stat, const rsa_key *key); + +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + const rsa_key *key); + +int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int padding, + int hash_idx, unsigned long saltlen, + int *stat, const rsa_key *key); + +int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key); + +/* PKCS #1 import/export */ +int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key); +int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key); + +int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key); +int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *passwd, unsigned long passwdlen, rsa_key *key); + +int rsa_set_key(const unsigned char *N, unsigned long Nlen, + const unsigned char *e, unsigned long elen, + const unsigned char *d, unsigned long dlen, + rsa_key *key); +int rsa_set_factors(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + rsa_key *key); +int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, + const unsigned char *dQ, unsigned long dQlen, + const unsigned char *qP, unsigned long qPlen, + rsa_key *key); +#endif + +/* ---- DH Routines ---- */ +#ifdef LTC_MDH + +typedef struct { + int type; + void *x; + void *y; + void *base; + void *prime; +} dh_key; + +int dh_get_groupsize(const dh_key *key); + +int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key); +int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key); + +int dh_set_pg(const unsigned char *p, unsigned long plen, + const unsigned char *g, unsigned long glen, + dh_key *key); +int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key); +int dh_set_pg_groupsize(int groupsize, dh_key *key); + +int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key); +int dh_generate_key(prng_state *prng, int wprng, dh_key *key); + +int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, + unsigned char *out, unsigned long *outlen); + +void dh_free(dh_key *key); + +int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key); +#endif /* LTC_MDH */ + + +/* ---- ECC Routines ---- */ +#ifdef LTC_MECC + +/* size of our temp buffers for exported keys */ +#define ECC_BUF_SIZE 256 + +/* max private key size */ +#define ECC_MAXSIZE 66 + +/** Structure defines a GF(p) curve */ +typedef struct { + /** The prime that defines the field the curve is in (encoded in hex) */ + const char *prime; + + /** The fields A param (hex) */ + const char *A; + + /** The fields B param (hex) */ + const char *B; + + /** The order of the curve (hex) */ + const char *order; + + /** The x co-ordinate of the base point on the curve (hex) */ + const char *Gx; + + /** The y co-ordinate of the base point on the curve (hex) */ + const char *Gy; + + /** The co-factor */ + unsigned long cofactor; + + /** The OID */ + const char *OID; +} ltc_ecc_curve; + +/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */ +typedef struct { + /** The x co-ordinate */ + void *x; + + /** The y co-ordinate */ + void *y; + + /** The z co-ordinate */ + void *z; +} ecc_point; + +/** ECC key's domain parameters */ +typedef struct { + /** The size of the curve in octets */ + int size; + /** The prime that defines the field the curve is in */ + void *prime; + /** The fields A param */ + void *A; + /** The fields B param */ + void *B; + /** The order of the curve */ + void *order; + /** The base point G on the curve */ + ecc_point base; + /** The co-factor */ + unsigned long cofactor; + /** The OID */ + unsigned long oid[16]; + unsigned long oidlen; +} ltc_ecc_dp; + +/** An ECC key */ +typedef struct { + /** Type of key, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** Structure with domain parameters */ + ltc_ecc_dp dp; + + /** Structure with the public key */ + ecc_point pubkey; + + /** The private key */ + void *k; +} ecc_key; + +/** Formats of ECC signatures */ +typedef enum ecc_signature_type_ { + /* ASN.1 encoded, ANSI X9.62 */ + LTC_ECCSIG_ANSIX962 = 0x0, + /* raw R, S values */ + LTC_ECCSIG_RFC7518 = 0x1, + /* raw R, S, V (+27) values */ + LTC_ECCSIG_ETH27 = 0x2, + /* SSH + ECDSA signature format defined by RFC5656 */ + LTC_ECCSIG_RFC5656 = 0x3, +} ecc_signature_type; + +/** the ECC params provided */ +extern const ltc_ecc_curve ltc_ecc_curves[]; + +void ecc_sizes(int *low, int *high); +int ecc_get_size(const ecc_key *key); + +int ecc_find_curve(const char* name_or_oid, const ltc_ecc_curve** cu); +int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key); +int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key); +int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); +int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); +int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key); + +int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key); +int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu); +void ecc_free(ecc_key *key); + +int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); +int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu); + +int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen); +int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu); + +int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key); +int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, ecc_key *key); +int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key); + +int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key, + unsigned char *out, unsigned long *outlen); + +int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + const ecc_key *key); + +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const ecc_key *key); + +#define ecc_sign_hash_rfc7518(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \ + ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_RFC7518, NULL, key_) + +#define ecc_sign_hash(in_, inlen_, out_, outlen_, prng_, wprng_, key_) \ + ecc_sign_hash_ex(in_, inlen_, out_, outlen_, prng_, wprng_, LTC_ECCSIG_ANSIX962, NULL, key_) + +#define ecc_verify_hash_rfc7518(sig_, siglen_, hash_, hashlen_, stat_, key_) \ + ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_RFC7518, stat_, key_) + +#define ecc_verify_hash(sig_, siglen_, hash_, hashlen_, stat_, key_) \ + ecc_verify_hash_ex(sig_, siglen_, hash_, hashlen_, LTC_ECCSIG_ANSIX962, stat_, key_) + +int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_signature_type sigformat, + int *recid, const ecc_key *key); + +int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + ecc_signature_type sigformat, int *stat, const ecc_key *key); + +int ecc_recover_key(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int recid, ecc_signature_type sigformat, ecc_key *key); + +#endif + +#ifdef LTC_CURVE25519 + +typedef struct { + /** The key type, PK_PRIVATE or PK_PUBLIC */ + enum public_key_type type; + + /** The PK-algorithm, PKA_ED25519 or PKA_X25519 */ + /** This was supposed to be: + * enum public_key_algorithms algo; + * but that enum is now in tomcrypt_private.h + */ + int algo; + + /** The private key */ + unsigned char priv[32]; + + /** The public key */ + unsigned char pub[32]; +} curve25519_key; + + +/** Ed25519 Signature API */ +int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key); + +int ed25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key); + +int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); +int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key); + +int ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const curve25519_key *private_key); +int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key); +int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key); +int ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int *stat, + const curve25519_key *public_key); +int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key); +int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key); + +/** X25519 Key-Exchange API */ +int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key); + +int x25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key); + +int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key); +int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key); +int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key); + +int x25519_shared_secret(const curve25519_key *private_key, + const curve25519_key *public_key, + unsigned char *out, unsigned long *outlen); + +#endif /* LTC_CURVE25519 */ + +#ifdef LTC_MDSA + +/* Max diff between group and modulus size in bytes (max case: L=8192bits, N=256bits) */ +#define LTC_MDSA_DELTA 992 + +/* Max DSA group size in bytes */ +#define LTC_MDSA_MAX_GROUP 64 + +/* Max DSA modulus size in bytes (the actual DSA size, max 8192 bits) */ +#define LTC_MDSA_MAX_MODULUS 1024 + +/** DSA key structure */ +typedef struct { + /** The key type, PK_PRIVATE or PK_PUBLIC */ + int type; + + /** The order of the sub-group used in octets */ + int qord; + + /** The generator */ + void *g; + + /** The prime used to generate the sub-group */ + void *q; + + /** The large prime that generats the field the contains the sub-group */ + void *p; + + /** The private key */ + void *x; + + /** The public key */ + void *y; +} dsa_key; + +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); + +int dsa_set_pqg(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + const unsigned char *g, unsigned long glen, + dsa_key *key); +int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, dsa_key *key); +int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key); + +int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key); +int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key); + +void dsa_free(dsa_key *key); + +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + void *r, void *s, + prng_state *prng, int wprng, const dsa_key *key); + +int dsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, const dsa_key *key); + +int dsa_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, const dsa_key *key); + +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const dsa_key *key); + +int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + const dsa_key *key); + +int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const dsa_key *key); + +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key); +int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key); +int dsa_verify_key(const dsa_key *key, int *stat); +int dsa_shared_secret(void *private_key, void *base, + const dsa_key *public_key, + unsigned char *out, unsigned long *outlen); +#endif /* LTC_MDSA */ + +#ifdef LTC_DER +/* DER handling */ + +typedef enum ltc_asn1_type_ { + /* 0 */ + LTC_ASN1_EOL, + LTC_ASN1_BOOLEAN, + LTC_ASN1_INTEGER, + LTC_ASN1_SHORT_INTEGER, + LTC_ASN1_BIT_STRING, + /* 5 */ + LTC_ASN1_OCTET_STRING, + LTC_ASN1_NULL, + LTC_ASN1_OBJECT_IDENTIFIER, + LTC_ASN1_IA5_STRING, + LTC_ASN1_PRINTABLE_STRING, + /* 10 */ + LTC_ASN1_UTF8_STRING, + LTC_ASN1_UTCTIME, + LTC_ASN1_CHOICE, + LTC_ASN1_SEQUENCE, + LTC_ASN1_SET, + /* 15 */ + LTC_ASN1_SETOF, + LTC_ASN1_RAW_BIT_STRING, + LTC_ASN1_TELETEX_STRING, + LTC_ASN1_GENERALIZEDTIME, + LTC_ASN1_CUSTOM_TYPE, +} ltc_asn1_type; + +typedef enum { + LTC_ASN1_CL_UNIVERSAL = 0x0, + LTC_ASN1_CL_APPLICATION = 0x1, + LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2, + LTC_ASN1_CL_PRIVATE = 0x3, +} ltc_asn1_class; + +typedef enum { + LTC_ASN1_PC_PRIMITIVE = 0x0, + LTC_ASN1_PC_CONSTRUCTED = 0x1, +} ltc_asn1_pc; + +/** A LTC ASN.1 list type */ +typedef struct ltc_asn1_list_ { + /** The LTC ASN.1 enumerated type identifier */ + ltc_asn1_type type; + /** The data to encode or place for decoding */ + void *data; + /** The size of the input or resulting output */ + unsigned long size; + /** The used flag + * 1. This is used by the CHOICE ASN.1 type to indicate which choice was made + * 2. This is used by the ASN.1 decoder to indicate if an element is used + * 3. This is used by the flexi-decoder to indicate the first byte of the identifier */ + int used; + /** Flag used to indicate optional items in ASN.1 sequences */ + int optional; + /** ASN.1 identifier */ + ltc_asn1_class klass; + ltc_asn1_pc pc; + ulong64 tag; + /** prev/next entry in the list */ + struct ltc_asn1_list_ *prev, *next, *child, *parent; +} ltc_asn1_list; + +#define LTC_SET_ASN1(list, index, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \ + LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \ + LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \ + LTC_MACRO_list[LTC_MACRO_temp].used = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].optional = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].klass = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].pc = 0; \ + LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \ + } while (0) + +#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \ + do { \ + int LTC_MACRO_temp = (index); \ + ltc_asn1_list *LTC_MACRO_list = (list); \ + LTC_MACRO_list[LTC_MACRO_temp].type = LTC_ASN1_CUSTOM_TYPE; \ + LTC_MACRO_list[LTC_MACRO_temp].klass = (Class); \ + LTC_MACRO_list[LTC_MACRO_temp].pc = (Pc); \ + LTC_MACRO_list[LTC_MACRO_temp].tag = (Tag); \ + } while (0) + +#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \ + do { \ + int LTC_MACRO_temp##__LINE__ = (index); \ + LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, 1); \ + LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \ + } while (0) + +#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \ + do { \ + int LTC_MACRO_temp##__LINE__ = (index); \ + LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, Size); \ + LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_PRIMITIVE, Tag); \ + list[LTC_MACRO_temp##__LINE__].used = (int)(Type); \ + } while (0) + +extern const char* der_asn1_class_to_string_map[]; +extern const unsigned long der_asn1_class_to_string_map_sz; + +extern const char* der_asn1_pc_to_string_map[]; +extern const unsigned long der_asn1_pc_to_string_map_sz; + +extern const char* der_asn1_tag_to_string_map[]; +extern const unsigned long der_asn1_tag_to_string_map_sz; + +/* SEQUENCE */ +int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int type_of); + +#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE) + +/** The supported bitmap for all the + * decoders with a `flags` argument. + */ +enum ltc_der_seq { + LTC_DER_SEQ_ZERO = 0x0u, + + /** Bit0 - [0]=Unordered (SET or SETOF) + * [1]=Ordered (SEQUENCE) */ + LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO, + LTC_DER_SEQ_ORDERED = 0x1u, + + /** Bit1 - [0]=Relaxed + * [1]=Strict */ + LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO, + LTC_DER_SEQ_STRICT = 0x2u, + + /** Alternative naming */ + LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED, + LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED, +}; + +int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen, unsigned int flags); + +#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED) +#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT) + +int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen); + + +/* Custom-types */ +int der_encode_custom_type(const ltc_asn1_list *root, + unsigned char *out, unsigned long *outlen); + +int der_decode_custom_type(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root); + +int der_length_custom_type(const ltc_asn1_list *root, + unsigned long *outlen, + unsigned long *payloadlen); + +/* SET */ +#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET) +#define der_length_set der_length_sequence +int der_encode_set(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +/* VA list handy helpers with triplets of */ +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; + +/* FLEXI DECODER handle unknown list decoder */ +int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); +#define der_free_sequence_flexi der_sequence_free +void der_sequence_free(ltc_asn1_list *in); +void der_sequence_shrink(ltc_asn1_list *in); + +/* BOOLEAN */ +int der_length_boolean(unsigned long *outlen); +int der_encode_boolean(int in, + unsigned char *out, unsigned long *outlen); +int der_decode_boolean(const unsigned char *in, unsigned long inlen, + int *out); +/* INTEGER */ +int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen); +int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num); +int der_length_integer(void *num, unsigned long *outlen); + +/* INTEGER -- handy for 0..2^32-1 values */ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num); +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen); +int der_length_short_integer(unsigned long num, unsigned long *outlen); + +/* BIT STRING */ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_bit_string(unsigned long nbits, unsigned long *outlen); + +/* OCTET STRING */ +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_octet_string(unsigned long noctets, unsigned long *outlen); + +/* OBJECT IDENTIFIER */ +int der_encode_object_identifier(const unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen); +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen); +int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen); +unsigned long der_object_identifier_bits(unsigned long x); + +/* IA5 STRING */ +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_ia5_char_encode(int c); +int der_ia5_value_decode(int v); + +/* TELETEX STRING */ +int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +/* PRINTABLE STRING */ +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen); + +int der_printable_char_encode(int c); +int der_printable_value_decode(int v); + +/* UTF-8 */ +#if (defined(SIZE_MAX) || __STDC_VERSION__ >= 199901L || defined(WCHAR_MAX) || defined(__WCHAR_MAX__) || defined(_WCHAR_T) || defined(_WCHAR_T_DEFINED) || defined (__WCHAR_TYPE__)) && !defined(LTC_NO_WCHAR) + #if defined(__WCHAR_MAX__) + #define LTC_WCHAR_MAX __WCHAR_MAX__ + #else + #include + #define LTC_WCHAR_MAX WCHAR_MAX + #endif +/* please note that it might happen that LTC_WCHAR_MAX is undefined */ +#else + typedef ulong32 wchar_t; + #define LTC_WCHAR_MAX 0xFFFFFFFF +#endif + +int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, + wchar_t *out, unsigned long *outlen); +unsigned long der_utf8_charsize(const wchar_t c); +int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen); + + +/* CHOICE */ +int der_decode_choice(const unsigned char *in, unsigned long *inlen, + ltc_asn1_list *list, unsigned long outlen); + +/* UTCTime */ +typedef struct { + unsigned YY, /* year */ + MM, /* month */ + DD, /* day */ + hh, /* hour */ + mm, /* minute */ + ss, /* second */ + off_dir, /* timezone offset direction 0 == +, 1 == - */ + off_hh, /* timezone offset hours */ + off_mm; /* timezone offset minutes */ +} ltc_utctime; + +int der_encode_utctime(const ltc_utctime *utctime, + unsigned char *out, unsigned long *outlen); + +int der_decode_utctime(const unsigned char *in, unsigned long *inlen, + ltc_utctime *out); + +int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen); + +/* GeneralizedTime */ +typedef struct { + unsigned YYYY, /* year */ + MM, /* month */ + DD, /* day */ + hh, /* hour */ + mm, /* minute */ + ss, /* second */ + fs, /* fractional seconds */ + off_dir, /* timezone offset direction 0 == +, 1 == - */ + off_hh, /* timezone offset hours */ + off_mm; /* timezone offset minutes */ +} ltc_generalizedtime; + +int der_encode_generalizedtime(const ltc_generalizedtime *gtime, + unsigned char *out, unsigned long *outlen); + +int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, + ltc_generalizedtime *out); + +int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen); + +#endif diff --git a/deps/libtomcrypt/src/headers/tomcrypt_pkcs.h b/deps/libtomcrypt/src/headers/tomcrypt_pkcs.h new file mode 100644 index 0000000..a0aa892 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_pkcs.h @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* PKCS Header Info */ + +/* ===> PKCS #1 -- RSA Cryptography <=== */ +#ifdef LTC_PKCS_1 + +enum ltc_pkcs_1_v1_5_blocks +{ + LTC_PKCS_1_EMSA = 1, /* Block type 1 (PKCS #1 v1.5 signature padding) */ + LTC_PKCS_1_EME = 2 /* Block type 2 (PKCS #1 v1.5 encryption padding) */ +}; + +enum ltc_pkcs_1_paddings +{ + LTC_PKCS_1_V1_5 = 1, /* PKCS #1 v1.5 padding (\sa ltc_pkcs_1_v1_5_blocks) */ + LTC_PKCS_1_OAEP = 2, /* PKCS #1 v2.0 encryption padding */ + LTC_PKCS_1_PSS = 3, /* PKCS #1 v2.1 signature padding */ + LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */ +}; + +int pkcs_1_mgf1( int hash_idx, + const unsigned char *seed, unsigned long seedlen, + unsigned char *mask, unsigned long masklen); + +int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); +int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); + +/* *** v1.5 padding */ +int pkcs_1_v1_5_encode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + prng_state *prng, + int prng_idx, + unsigned char *out, + unsigned long *outlen); + +int pkcs_1_v1_5_decode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + unsigned char *out, + unsigned long *outlen, + int *is_valid); + +/* *** v2.1 padding */ +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen, + int *res); + +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); + +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res); + +#endif /* LTC_PKCS_1 */ + +/* ===> PKCS #5 -- Password Based Cryptography <=== */ +#ifdef LTC_PKCS_5 + +/* Algorithm #1 (PBKDF1) */ +int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +/* Algorithm #1 (PBKDF1) - OpenSSL-compatible variant for arbitrarily-long keys. + Compatible with EVP_BytesToKey() */ +int pkcs_5_alg1_openssl(const unsigned char *password, + unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +/* Algorithm #2 (PBKDF2) */ +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +int pkcs_5_test (void); +#endif /* LTC_PKCS_5 */ + diff --git a/deps/libtomcrypt/src/headers/tomcrypt_private.h b/deps/libtomcrypt/src/headers/tomcrypt_private.h new file mode 100644 index 0000000..cbeea74 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_private.h @@ -0,0 +1,477 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt.h" + +/* + * Internal Macros + */ + +#define LTC_PAD_MASK (0xF000U) + +/* `NULL` as defined by the standard is not guaranteed to be of a pointer + * type. In order to make sure that in vararg API's a pointer type is used, + * define our own version and use that one internally. + */ +#ifndef LTC_NULL + #define LTC_NULL ((void *)0) +#endif + +/* + * Internal Enums + */ + +enum ltc_oid_id { + LTC_OID_RSA, + LTC_OID_DSA, + LTC_OID_EC, + LTC_OID_EC_PRIMEF, + LTC_OID_X25519, + LTC_OID_ED25519, +}; + +/* + * Internal Types + */ + +typedef struct { + int size; + const char *name, *base, *prime; +} ltc_dh_set_type; + + +typedef int (*fn_kdf_t)(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen); + +typedef struct { + /* KDF */ + fn_kdf_t kdf; + /* Hash or HMAC */ + const char* h; + /* cipher */ + const char* c; + unsigned long keylen; + /* not used for pbkdf2 */ + unsigned long blocklen; +} pbes_properties; + +typedef struct +{ + pbes_properties type; + const void *pwd; + unsigned long pwdlen; + ltc_asn1_list *enc_data; + ltc_asn1_list *salt; + ltc_asn1_list *iv; + unsigned long iterations; + /* only used for RC2 */ + unsigned long key_bits; +} pbes_arg; + +/* + * Internal functions + */ + + +/* tomcrypt_cipher.h */ + +void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey); +int blowfish_expand(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey); +int blowfish_setup_with_data(const unsigned char *key, int keylen, + const unsigned char *data, int datalen, + symmetric_key *skey); + +/* tomcrypt_hash.h */ + +/* a simple macro for making hash "process" functions */ +#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ +int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) \ +{ \ + unsigned long n; \ + int err; \ + LTC_ARGCHK(md != NULL); \ + LTC_ARGCHK(in != NULL); \ + if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ + return CRYPT_INVALID_ARG; \ + } \ + if (((md-> state_var .length + inlen * 8) < md-> state_var .length) \ + || ((inlen * 8) < inlen)) { \ + return CRYPT_HASH_OVERFLOW; \ + } \ + while (inlen > 0) { \ + if (md-> state_var .curlen == 0 && inlen >= block_size) { \ + if ((err = compress_name (md, in)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += block_size * 8; \ + in += block_size; \ + inlen -= block_size; \ + } else { \ + n = MIN(inlen, (block_size - md-> state_var .curlen)); \ + XMEMCPY(md-> state_var .buf + md-> state_var.curlen, in, (size_t)n); \ + md-> state_var .curlen += n; \ + in += n; \ + inlen -= n; \ + if (md-> state_var .curlen == block_size) { \ + if ((err = compress_name (md, md-> state_var .buf)) != CRYPT_OK) { \ + return err; \ + } \ + md-> state_var .length += 8*block_size; \ + md-> state_var .curlen = 0; \ + } \ + } \ + } \ + return CRYPT_OK; \ +} + + +/* tomcrypt_mac.h */ + +int ocb3_int_ntz(unsigned long x); +void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const unsigned char *block_b, unsigned long block_len); + + +/* tomcrypt_math.h */ + +#if !defined(DESC_DEF_ONLY) + +#define MP_DIGIT_BIT ltc_mp.bits_per_digit + +/* some handy macros */ +#define mp_init(a) ltc_mp.init(a) +#define mp_init_multi ltc_init_multi +#define mp_clear(a) ltc_mp.deinit(a) +#define mp_clear_multi ltc_deinit_multi +#define mp_cleanup_multi ltc_cleanup_multi +#define mp_init_copy(a, b) ltc_mp.init_copy(a, b) + +#define mp_neg(a, b) ltc_mp.neg(a, b) +#define mp_copy(a, b) ltc_mp.copy(a, b) + +#define mp_set(a, b) ltc_mp.set_int(a, b) +#define mp_set_int(a, b) ltc_mp.set_int(a, b) +#define mp_get_int(a) ltc_mp.get_int(a) +#define mp_get_digit(a, n) ltc_mp.get_digit(a, n) +#define mp_get_digit_count(a) ltc_mp.get_digit_count(a) +#define mp_cmp(a, b) ltc_mp.compare(a, b) +#define mp_cmp_d(a, b) ltc_mp.compare_d(a, b) +#define mp_count_bits(a) ltc_mp.count_bits(a) +#define mp_cnt_lsb(a) ltc_mp.count_lsb_bits(a) +#define mp_2expt(a, b) ltc_mp.twoexpt(a, b) + +#define mp_read_radix(a, b, c) ltc_mp.read_radix(a, b, c) +#define mp_toradix(a, b, c) ltc_mp.write_radix(a, b, c) +#define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) +#define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) +#define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) + +#define mp_add(a, b, c) ltc_mp.add(a, b, c) +#define mp_add_d(a, b, c) ltc_mp.addi(a, b, c) +#define mp_sub(a, b, c) ltc_mp.sub(a, b, c) +#define mp_sub_d(a, b, c) ltc_mp.subi(a, b, c) +#define mp_mul(a, b, c) ltc_mp.mul(a, b, c) +#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c) +#define mp_sqr(a, b) ltc_mp.sqr(a, b) +#define mp_sqrtmod_prime(a, b, c) ltc_mp.sqrtmod_prime(a, b, c) +#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d) +#define mp_div_2(a, b) ltc_mp.div_2(a, b) +#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c) +#define mp_mod_d(a, b, c) ltc_mp.modi(a, b, c) +#define mp_gcd(a, b, c) ltc_mp.gcd(a, b, c) +#define mp_lcm(a, b, c) ltc_mp.lcm(a, b, c) + +#define mp_addmod(a, b, c, d) ltc_mp.addmod(a, b, c, d) +#define mp_submod(a, b, c, d) ltc_mp.submod(a, b, c, d) +#define mp_mulmod(a, b, c, d) ltc_mp.mulmod(a, b, c, d) +#define mp_sqrmod(a, b, c) ltc_mp.sqrmod(a, b, c) +#define mp_invmod(a, b, c) ltc_mp.invmod(a, b, c) + +#define mp_montgomery_setup(a, b) ltc_mp.montgomery_setup(a, b) +#define mp_montgomery_normalization(a, b) ltc_mp.montgomery_normalization(a, b) +#define mp_montgomery_reduce(a, b, c) ltc_mp.montgomery_reduce(a, b, c) +#define mp_montgomery_free(a) ltc_mp.montgomery_deinit(a) + +#define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) +#define mp_prime_is_prime(a, b, c) ltc_mp.isprime(a, b, c) + +#define mp_iszero(a) (mp_cmp_d(a, 0) == LTC_MP_EQ ? LTC_MP_YES : LTC_MP_NO) +#define mp_isodd(a) (mp_get_digit_count(a) > 0 ? (mp_get_digit(a, 0) & 1 ? LTC_MP_YES : LTC_MP_NO) : LTC_MP_NO) +#define mp_exch(a, b) do { void *ABC__tmp = a; a = b; b = ABC__tmp; } while(0) + +#define mp_tohex(a, b) mp_toradix(a, b, 16) + +#define mp_rand(a, b) ltc_mp.rand(a, b) + +#endif + + +/* tomcrypt_misc.h */ + +typedef enum { + /** Use `\r\n` as line separator */ + BASE64_PEM_CRLF = 1, + /** Create output with 72 chars line length */ + BASE64_PEM_SSH = 2, +} base64_pem_flags; + +int base64_encode_pem(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int flags); + +void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz); + +int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size); + +int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res); +int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res); + + +/* tomcrypt_pk.h */ + +int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng); +int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng); + +int pk_get_oid(enum ltc_oid_id id, const char **st); +int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen); +int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen); + +/* ---- DH Routines ---- */ +#ifdef LTC_MRSA +int rsa_init(rsa_key *key); +void rsa_shrink_key(rsa_key *key); +int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, + rsa_key *key); /* used by op-tee */ +int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key); +#endif /* LTC_MRSA */ + +/* ---- DH Routines ---- */ +#ifdef LTC_MDH +extern const ltc_dh_set_type ltc_dh_sets[]; + +int dh_check_pubkey(const dh_key *key); +#endif /* LTC_MDH */ + +/* ---- ECC Routines ---- */ +#ifdef LTC_MECC +int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key); +int ecc_copy_curve(const ecc_key *srckey, ecc_key *key); +int ecc_set_curve_by_size(int size, ecc_key *key); +int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key); + +#ifdef LTC_SSH +int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key); +#endif + +/* low level functions */ +ecc_point *ltc_ecc_new_point(void); +void ltc_ecc_del_point(ecc_point *p); +int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p); +int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst); +int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y); +int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval); +int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y); +int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed); +int ltc_ecc_verify_key(const ecc_key *key); + +/* point ops (mp == montgomery digit) */ +#if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC) +/* R = 2P */ +int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp); + +/* R = P + Q */ +int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp); +#endif + +#if defined(LTC_MECC_FP) +/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */ +int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map); + +/* functions for saving/loading/freeing/adding to fixed point cache */ +int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen); +int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen); +void ltc_ecc_fp_free(void); +int ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock); + +/* lock/unlock all points currently in fixed point cache */ +void ltc_ecc_fp_tablelock(int lock); +#endif + +/* R = kG */ +int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map); + +#ifdef LTC_ECC_SHAMIR +/* kA*A + kB*B = C */ +int ltc_ecc_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); + +#ifdef LTC_MECC_FP +/* Shamir's trick with optimized point multiplication using fixed point cache */ +int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus); +#endif + +#endif + + +/* map P to affine from projective */ +int ltc_ecc_map(ecc_point *P, void *modulus, void *mp); +#endif /* LTC_MECC */ + +#ifdef LTC_MDSA +int dsa_int_validate_xy(const dsa_key *key, int *stat); +int dsa_int_validate_pqg(const dsa_key *key, int *stat); +int dsa_int_validate_primes(const dsa_key *key, int *stat); +#endif /* LTC_MDSA */ + + +#ifdef LTC_CURVE25519 + +int tweetnacl_crypto_sign( + unsigned char *sm,unsigned long long *smlen, + const unsigned char *m,unsigned long long mlen, + const unsigned char *sk,const unsigned char *pk, + const unsigned char *ctx,unsigned long long cs); +int tweetnacl_crypto_sign_open( + int *stat, + unsigned char *m,unsigned long long *mlen, + const unsigned char *sm,unsigned long long smlen, + const unsigned char *ctx, unsigned long long cs, + const unsigned char *pk); +int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, unsigned char *pk,unsigned char *sk); +int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk); +int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); +int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n); +int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long long msglen); + +typedef int (*sk_to_pk)(unsigned char *pk ,const unsigned char *sk); +int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + enum ltc_oid_id id, sk_to_pk fp, + curve25519_key *key); +int ec25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key); +int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen, + unsigned char flag, + const unsigned char *ctx, unsigned long ctxlen); +#endif /* LTC_CURVE25519 */ + +#ifdef LTC_DER + +#define LTC_ASN1_IS_TYPE(e, t) (((e) != NULL) && ((e)->type == (t))) + +/* DER handling */ +int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root, + ltc_asn1_list *list, unsigned long outlen, unsigned int flags); + +int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen); +int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id); +int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen); + +int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen); +int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen); +int der_length_asn1_length(unsigned long len, unsigned long *outlen); + +int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen, unsigned long *payloadlen); + +extern const ltc_asn1_type der_asn1_tag_to_type_map[]; +extern const unsigned long der_asn1_tag_to_type_map_sz; + +extern const int der_asn1_type_to_identifier_map[]; +extern const unsigned long der_asn1_type_to_identifier_map_sz; + +int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) + LTC_NULL_TERMINATED; + +int der_teletex_char_encode(int c); +int der_teletex_value_decode(int v); + +int der_utf8_valid_char(const wchar_t c); + +typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *ctx); + +int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, + enum ltc_oid_id algorithm, ltc_asn1_type param_type, + ltc_asn1_list* parameters, unsigned long *parameters_len, + public_key_decode_cb callback, void *ctx); + +/* SUBJECT PUBLIC KEY INFO */ +int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, + unsigned int algorithm, const void* public_key, unsigned long public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len); + +int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, + unsigned int algorithm, void* public_key, unsigned long* public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len); + +int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size); +int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); + +#endif /* LTC_DER */ + +/* tomcrypt_pkcs.h */ + +#ifdef LTC_PKCS_8 + +int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + ltc_asn1_list **decoded_list); + +#endif /* LTC_PKCS_8 */ + + +#ifdef LTC_PKCS_12 + +int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int pkcs12_kdf( int hash_id, + const unsigned char *pw, unsigned long pwlen, + const unsigned char *salt, unsigned long saltlen, + unsigned int iterations, unsigned char purpose, + unsigned char *out, unsigned long outlen); + +#endif /* LTC_PKCS_12 */ + +/* tomcrypt_prng.h */ + +#define LTC_PRNG_EXPORT(which) \ +int which ## _export(unsigned char *out, unsigned long *outlen, prng_state *prng) \ +{ \ + unsigned long len = which ## _desc.export_size; \ + \ + LTC_ARGCHK(prng != NULL); \ + LTC_ARGCHK(out != NULL); \ + LTC_ARGCHK(outlen != NULL); \ + \ + if (*outlen < len) { \ + *outlen = len; \ + return CRYPT_BUFFER_OVERFLOW; \ + } \ + \ + if (which ## _read(out, len, prng) != len) { \ + return CRYPT_ERROR_READPRNG; \ + } \ + \ + *outlen = len; \ + return CRYPT_OK; \ +} + +/* extract a byte portably */ +#ifdef _MSC_VER + #define LTC_BYTE(x, n) ((unsigned char)((x) >> (8 * (n)))) +#else + #define LTC_BYTE(x, n) (((x) >> (8 * (n))) & 255) +#endif diff --git a/deps/libtomcrypt/src/headers/tomcrypt_prng.h b/deps/libtomcrypt/src/headers/tomcrypt_prng.h new file mode 100644 index 0000000..b8fa585 --- /dev/null +++ b/deps/libtomcrypt/src/headers/tomcrypt_prng.h @@ -0,0 +1,223 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* ---- PRNG Stuff ---- */ +#ifdef LTC_YARROW +struct yarrow_prng { + int cipher, hash; + unsigned char pool[MAXBLOCKSIZE]; + symmetric_CTR ctr; +}; +#endif + +#ifdef LTC_RC4 +struct rc4_prng { + rc4_state s; +}; +#endif + +#ifdef LTC_CHACHA20_PRNG +struct chacha20_prng { + chacha_state s; /* chacha state */ + unsigned char ent[40]; /* entropy buffer */ + unsigned long idx; /* entropy counter */ +}; +#endif + +#ifdef LTC_FORTUNA +struct fortuna_prng { + hash_state pool[LTC_FORTUNA_POOLS]; /* the pools */ + + symmetric_key skey; + + unsigned char K[32], /* the current key */ + IV[16]; /* IV for CTR mode */ + + unsigned long pool_idx, /* current pool we will add to */ + pool0_len; /* length of 0'th pool */ + ulong64 wd; + ulong64 reset_cnt; /* number of times we have reseeded */ +}; +#endif + +#ifdef LTC_SOBER128 +struct sober128_prng { + sober128_state s; /* sober128 state */ + unsigned char ent[40]; /* entropy buffer */ + unsigned long idx; /* entropy counter */ +}; +#endif + +typedef struct { + union { + char dummy[1]; +#ifdef LTC_YARROW + struct yarrow_prng yarrow; +#endif +#ifdef LTC_RC4 + struct rc4_prng rc4; +#endif +#ifdef LTC_CHACHA20_PRNG + struct chacha20_prng chacha; +#endif +#ifdef LTC_FORTUNA + struct fortuna_prng fortuna; +#endif +#ifdef LTC_SOBER128 + struct sober128_prng sober128; +#endif + } u; + short ready; /* ready flag 0-1 */ + LTC_MUTEX_TYPE(lock) /* lock */ +} prng_state; + +/** PRNG descriptor */ +extern struct ltc_prng_descriptor { + /** Name of the PRNG */ + const char *name; + /** size in bytes of exported state */ + int export_size; + /** Start a PRNG state + @param prng [out] The state to initialize + @return CRYPT_OK if successful + */ + int (*start)(prng_state *prng); + /** Add entropy to the PRNG + @param in The entropy + @param inlen Length of the entropy (octets)\ + @param prng The PRNG state + @return CRYPT_OK if successful + */ + int (*add_entropy)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Ready a PRNG state to read from + @param prng The PRNG state to ready + @return CRYPT_OK if successful + */ + int (*ready)(prng_state *prng); + /** Read from the PRNG + @param out [out] Where to store the data + @param outlen Length of data desired (octets) + @param prng The PRNG state to read from + @return Number of octets read + */ + unsigned long (*read)(unsigned char *out, unsigned long outlen, prng_state *prng); + /** Terminate a PRNG state + @param prng The PRNG state to terminate + @return CRYPT_OK if successful + */ + int (*done)(prng_state *prng); + /** Export a PRNG state + @param out [out] The destination for the state + @param outlen [in/out] The max size and resulting size of the PRNG state + @param prng The PRNG to export + @return CRYPT_OK if successful + */ + int (*pexport)(unsigned char *out, unsigned long *outlen, prng_state *prng); + /** Import a PRNG state + @param in The data to import + @param inlen The length of the data to import (octets) + @param prng The PRNG to initialize/import + @return CRYPT_OK if successful + */ + int (*pimport)(const unsigned char *in, unsigned long inlen, prng_state *prng); + /** Self-test the PRNG + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled + */ + int (*test)(void); +} prng_descriptor[]; + +#ifdef LTC_YARROW +int yarrow_start(prng_state *prng); +int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_ready(prng_state *prng); +unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int yarrow_done(prng_state *prng); +int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int yarrow_test(void); +extern const struct ltc_prng_descriptor yarrow_desc; +#endif + +#ifdef LTC_FORTUNA +int fortuna_start(prng_state *prng); +int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_ready(prng_state *prng); +unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int fortuna_done(prng_state *prng); +int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng); +int fortuna_test(void); +extern const struct ltc_prng_descriptor fortuna_desc; +#endif + +#ifdef LTC_RC4 +int rc4_start(prng_state *prng); +int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_ready(prng_state *prng); +unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int rc4_done(prng_state *prng); +int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int rc4_test(void); +extern const struct ltc_prng_descriptor rc4_desc; +#endif + +#ifdef LTC_CHACHA20_PRNG +int chacha20_prng_start(prng_state *prng); +int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int chacha20_prng_ready(prng_state *prng); +unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int chacha20_prng_done(prng_state *prng); +int chacha20_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int chacha20_prng_test(void); +extern const struct ltc_prng_descriptor chacha20_prng_desc; +#endif + +#ifdef LTC_SPRNG +int sprng_start(prng_state *prng); +int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_ready(prng_state *prng); +unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sprng_done(prng_state *prng); +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sprng_test(void); +extern const struct ltc_prng_descriptor sprng_desc; +#endif + +#ifdef LTC_SOBER128 +int sober128_start(prng_state *prng); +int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_ready(prng_state *prng); +unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng); +int sober128_done(prng_state *prng); +int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng); +int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng); +int sober128_test(void); +extern const struct ltc_prng_descriptor sober128_desc; +#endif + +int find_prng(const char *name); +int register_prng(const struct ltc_prng_descriptor *prng); +int unregister_prng(const struct ltc_prng_descriptor *prng); +int register_all_prngs(void); +int prng_is_valid(int idx); +LTC_MUTEX_PROTO(ltc_prng_mutex) + +/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this + * might not work on all platforms as planned + */ +unsigned long rng_get_bytes(unsigned char *out, + unsigned long outlen, + void (*callback)(void)); + +int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void)); + +#ifdef LTC_PRNG_ENABLE_LTC_RNG +extern unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, + void (*callback)(void)); +#endif + diff --git a/deps/libtomcrypt/src/mac/blake2/blake2bmac.c b/deps/libtomcrypt/src/mac/blake2/blake2bmac.c new file mode 100644 index 0000000..ac26e10 --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2bmac.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +/** + Initialize an BLAKE2B MAC context. + @param st The BLAKE2B MAC state + @param outlen The size of the MAC output (octets) + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + return blake2b_init(st, outlen, key, keylen); +} + +/** + Process data through BLAKE2B MAC + @param st The BLAKE2B MAC state + @param in The data to send through HMAC + @param inlen The length of the data to HMAC (octets) + @return CRYPT_OK if successful +*/ +int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen) +{ + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + return blake2b_process(st, in, inlen); +} + +/** + Terminate a BLAKE2B MAC session + @param st The BLAKE2B MAC state + @param mac [out] The destination of the BLAKE2B MAC authentication tag + @param maclen [in/out] The max size and resulting size of the BLAKE2B MAC authentication tag + @return CRYPT_OK if successful +*/ +int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + LTC_ARGCHK(*maclen >= st->blake2b.outlen); + + *maclen = st->blake2b.outlen; + return blake2b_done(st, mac); +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2bmac_file.c b/deps/libtomcrypt/src/mac/blake2/blake2bmac_file.c new file mode 100644 index 0000000..831e845 --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2bmac_file.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +/** + BLAKE2B MAC a file + @param fname The name of the file you wish to BLAKE2B MAC + @param key The secret key + @param keylen The length of the secret key + @param mac [out] The BLAKE2B MAC authentication tag + @param maclen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); + return CRYPT_NOP; +#else + blake2bmac_state st; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = blake2bmac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = blake2bmac_done(&st, mac, maclen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2bmac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2bmac_memory.c b/deps/libtomcrypt/src/mac/blake2/blake2bmac_memory.c new file mode 100644 index 0000000..3f5e309 --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2bmac_memory.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +/** + BLAKE2B MAC a block of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to BLAKE2B MAC + @param inlen The length of the data to BLAKE2B MAC (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) +{ + blake2bmac_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = blake2bmac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + err = blake2bmac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2bmac_state)); +#endif + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c b/deps/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c new file mode 100644 index 0000000..403fba3 --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2bmac_memory_multi.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" +#include + +#ifdef LTC_BLAKE2BMAC + +/** + BLAKE2B MAC multiple blocks of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @param in The data to BLAKE2B MAC + @param inlen The length of the data to BLAKE2B MAC (octets) + @param ... tuples of (data,len) pairs to BLAKE2B MAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) +{ + blake2bmac_state st; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + va_start(args, inlen); + curptr = in; + curlen = inlen; + if ((err = blake2bmac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + for (;;) { + if ((err = blake2bmac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) break; + curlen = va_arg(args, unsigned long); + } + err = blake2bmac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2bmac_state)); +#endif + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2bmac_test.c b/deps/libtomcrypt/src/mac/blake2/blake2bmac_test.c new file mode 100644 index 0000000..b2651cc --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2bmac_test.c @@ -0,0 +1,304 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2BMAC + +int blake2bmac_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const unsigned char tests[256][64] = { + /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2b-kat.txt */ + { 0x10, 0xeb, 0xb6, 0x77, 0x00, 0xb1, 0x86, 0x8e, 0xfb, 0x44, 0x17, 0x98, 0x7a, 0xcf, 0x46, 0x90, 0xae, 0x9d, 0x97, 0x2f, 0xb7, 0xa5, 0x90, 0xc2, 0xf0, 0x28, 0x71, 0x79, 0x9a, 0xaa, 0x47, 0x86, 0xb5, 0xe9, 0x96, 0xe8, 0xf0, 0xf4, 0xeb, 0x98, 0x1f, 0xc2, 0x14, 0xb0, 0x05, 0xf4, 0x2d, 0x2f, 0xf4, 0x23, 0x34, 0x99, 0x39, 0x16, 0x53, 0xdf, 0x7a, 0xef, 0xcb, 0xc1, 0x3f, 0xc5, 0x15, 0x68 }, + { 0x96, 0x1f, 0x6d, 0xd1, 0xe4, 0xdd, 0x30, 0xf6, 0x39, 0x01, 0x69, 0x0c, 0x51, 0x2e, 0x78, 0xe4, 0xb4, 0x5e, 0x47, 0x42, 0xed, 0x19, 0x7c, 0x3c, 0x5e, 0x45, 0xc5, 0x49, 0xfd, 0x25, 0xf2, 0xe4, 0x18, 0x7b, 0x0b, 0xc9, 0xfe, 0x30, 0x49, 0x2b, 0x16, 0xb0, 0xd0, 0xbc, 0x4e, 0xf9, 0xb0, 0xf3, 0x4c, 0x70, 0x03, 0xfa, 0xc0, 0x9a, 0x5e, 0xf1, 0x53, 0x2e, 0x69, 0x43, 0x02, 0x34, 0xce, 0xbd }, + { 0xda, 0x2c, 0xfb, 0xe2, 0xd8, 0x40, 0x9a, 0x0f, 0x38, 0x02, 0x61, 0x13, 0x88, 0x4f, 0x84, 0xb5, 0x01, 0x56, 0x37, 0x1a, 0xe3, 0x04, 0xc4, 0x43, 0x01, 0x73, 0xd0, 0x8a, 0x99, 0xd9, 0xfb, 0x1b, 0x98, 0x31, 0x64, 0xa3, 0x77, 0x07, 0x06, 0xd5, 0x37, 0xf4, 0x9e, 0x0c, 0x91, 0x6d, 0x9f, 0x32, 0xb9, 0x5c, 0xc3, 0x7a, 0x95, 0xb9, 0x9d, 0x85, 0x74, 0x36, 0xf0, 0x23, 0x2c, 0x88, 0xa9, 0x65 }, + { 0x33, 0xd0, 0x82, 0x5d, 0xdd, 0xf7, 0xad, 0xa9, 0x9b, 0x0e, 0x7e, 0x30, 0x71, 0x04, 0xad, 0x07, 0xca, 0x9c, 0xfd, 0x96, 0x92, 0x21, 0x4f, 0x15, 0x61, 0x35, 0x63, 0x15, 0xe7, 0x84, 0xf3, 0xe5, 0xa1, 0x7e, 0x36, 0x4a, 0xe9, 0xdb, 0xb1, 0x4c, 0xb2, 0x03, 0x6d, 0xf9, 0x32, 0xb7, 0x7f, 0x4b, 0x29, 0x27, 0x61, 0x36, 0x5f, 0xb3, 0x28, 0xde, 0x7a, 0xfd, 0xc6, 0xd8, 0x99, 0x8f, 0x5f, 0xc1 }, + { 0xbe, 0xaa, 0x5a, 0x3d, 0x08, 0xf3, 0x80, 0x71, 0x43, 0xcf, 0x62, 0x1d, 0x95, 0xcd, 0x69, 0x05, 0x14, 0xd0, 0xb4, 0x9e, 0xff, 0xf9, 0xc9, 0x1d, 0x24, 0xb5, 0x92, 0x41, 0xec, 0x0e, 0xef, 0xa5, 0xf6, 0x01, 0x96, 0xd4, 0x07, 0x04, 0x8b, 0xba, 0x8d, 0x21, 0x46, 0x82, 0x8e, 0xbc, 0xb0, 0x48, 0x8d, 0x88, 0x42, 0xfd, 0x56, 0xbb, 0x4f, 0x6d, 0xf8, 0xe1, 0x9c, 0x4b, 0x4d, 0xaa, 0xb8, 0xac }, + { 0x09, 0x80, 0x84, 0xb5, 0x1f, 0xd1, 0x3d, 0xea, 0xe5, 0xf4, 0x32, 0x0d, 0xe9, 0x4a, 0x68, 0x8e, 0xe0, 0x7b, 0xae, 0xa2, 0x80, 0x04, 0x86, 0x68, 0x9a, 0x86, 0x36, 0x11, 0x7b, 0x46, 0xc1, 0xf4, 0xc1, 0xf6, 0xaf, 0x7f, 0x74, 0xae, 0x7c, 0x85, 0x76, 0x00, 0x45, 0x6a, 0x58, 0xa3, 0xaf, 0x25, 0x1d, 0xc4, 0x72, 0x3a, 0x64, 0xcc, 0x7c, 0x0a, 0x5a, 0xb6, 0xd9, 0xca, 0xc9, 0x1c, 0x20, 0xbb }, + { 0x60, 0x44, 0x54, 0x0d, 0x56, 0x08, 0x53, 0xeb, 0x1c, 0x57, 0xdf, 0x00, 0x77, 0xdd, 0x38, 0x10, 0x94, 0x78, 0x1c, 0xdb, 0x90, 0x73, 0xe5, 0xb1, 0xb3, 0xd3, 0xf6, 0xc7, 0x82, 0x9e, 0x12, 0x06, 0x6b, 0xba, 0xca, 0x96, 0xd9, 0x89, 0xa6, 0x90, 0xde, 0x72, 0xca, 0x31, 0x33, 0xa8, 0x36, 0x52, 0xba, 0x28, 0x4a, 0x6d, 0x62, 0x94, 0x2b, 0x27, 0x1f, 0xfa, 0x26, 0x20, 0xc9, 0xe7, 0x5b, 0x1f }, + { 0x7a, 0x8c, 0xfe, 0x9b, 0x90, 0xf7, 0x5f, 0x7e, 0xcb, 0x3a, 0xcc, 0x05, 0x3a, 0xae, 0xd6, 0x19, 0x31, 0x12, 0xb6, 0xf6, 0xa4, 0xae, 0xeb, 0x3f, 0x65, 0xd3, 0xde, 0x54, 0x19, 0x42, 0xde, 0xb9, 0xe2, 0x22, 0x81, 0x52, 0xa3, 0xc4, 0xbb, 0xbe, 0x72, 0xfc, 0x3b, 0x12, 0x62, 0x95, 0x28, 0xcf, 0xbb, 0x09, 0xfe, 0x63, 0x0f, 0x04, 0x74, 0x33, 0x9f, 0x54, 0xab, 0xf4, 0x53, 0xe2, 0xed, 0x52 }, + { 0x38, 0x0b, 0xea, 0xf6, 0xea, 0x7c, 0xc9, 0x36, 0x5e, 0x27, 0x0e, 0xf0, 0xe6, 0xf3, 0xa6, 0x4f, 0xb9, 0x02, 0xac, 0xae, 0x51, 0xdd, 0x55, 0x12, 0xf8, 0x42, 0x59, 0xad, 0x2c, 0x91, 0xf4, 0xbc, 0x41, 0x08, 0xdb, 0x73, 0x19, 0x2a, 0x5b, 0xbf, 0xb0, 0xcb, 0xcf, 0x71, 0xe4, 0x6c, 0x3e, 0x21, 0xae, 0xe1, 0xc5, 0xe8, 0x60, 0xdc, 0x96, 0xe8, 0xeb, 0x0b, 0x7b, 0x84, 0x26, 0xe6, 0xab, 0xe9 }, + { 0x60, 0xfe, 0x3c, 0x45, 0x35, 0xe1, 0xb5, 0x9d, 0x9a, 0x61, 0xea, 0x85, 0x00, 0xbf, 0xac, 0x41, 0xa6, 0x9d, 0xff, 0xb1, 0xce, 0xad, 0xd9, 0xac, 0xa3, 0x23, 0xe9, 0xa6, 0x25, 0xb6, 0x4d, 0xa5, 0x76, 0x3b, 0xad, 0x72, 0x26, 0xda, 0x02, 0xb9, 0xc8, 0xc4, 0xf1, 0xa5, 0xde, 0x14, 0x0a, 0xc5, 0xa6, 0xc1, 0x12, 0x4e, 0x4f, 0x71, 0x8c, 0xe0, 0xb2, 0x8e, 0xa4, 0x73, 0x93, 0xaa, 0x66, 0x37 }, + { 0x4f, 0xe1, 0x81, 0xf5, 0x4a, 0xd6, 0x3a, 0x29, 0x83, 0xfe, 0xaa, 0xf7, 0x7d, 0x1e, 0x72, 0x35, 0xc2, 0xbe, 0xb1, 0x7f, 0xa3, 0x28, 0xb6, 0xd9, 0x50, 0x5b, 0xda, 0x32, 0x7d, 0xf1, 0x9f, 0xc3, 0x7f, 0x02, 0xc4, 0xb6, 0xf0, 0x36, 0x8c, 0xe2, 0x31, 0x47, 0x31, 0x3a, 0x8e, 0x57, 0x38, 0xb5, 0xfa, 0x2a, 0x95, 0xb2, 0x9d, 0xe1, 0xc7, 0xf8, 0x26, 0x4e, 0xb7, 0x7b, 0x69, 0xf5, 0x85, 0xcd }, + { 0xf2, 0x28, 0x77, 0x3c, 0xe3, 0xf3, 0xa4, 0x2b, 0x5f, 0x14, 0x4d, 0x63, 0x23, 0x7a, 0x72, 0xd9, 0x96, 0x93, 0xad, 0xb8, 0x83, 0x7d, 0x0e, 0x11, 0x2a, 0x8a, 0x0f, 0x8f, 0xff, 0xf2, 0xc3, 0x62, 0x85, 0x7a, 0xc4, 0x9c, 0x11, 0xec, 0x74, 0x0d, 0x15, 0x00, 0x74, 0x9d, 0xac, 0x9b, 0x1f, 0x45, 0x48, 0x10, 0x8b, 0xf3, 0x15, 0x57, 0x94, 0xdc, 0xc9, 0xe4, 0x08, 0x28, 0x49, 0xe2, 0xb8, 0x5b }, + { 0x96, 0x24, 0x52, 0xa8, 0x45, 0x5c, 0xc5, 0x6c, 0x85, 0x11, 0x31, 0x7e, 0x3b, 0x1f, 0x3b, 0x2c, 0x37, 0xdf, 0x75, 0xf5, 0x88, 0xe9, 0x43, 0x25, 0xfd, 0xd7, 0x70, 0x70, 0x35, 0x9c, 0xf6, 0x3a, 0x9a, 0xe6, 0xe9, 0x30, 0x93, 0x6f, 0xdf, 0x8e, 0x1e, 0x08, 0xff, 0xca, 0x44, 0x0c, 0xfb, 0x72, 0xc2, 0x8f, 0x06, 0xd8, 0x9a, 0x21, 0x51, 0xd1, 0xc4, 0x6c, 0xd5, 0xb2, 0x68, 0xef, 0x85, 0x63 }, + { 0x43, 0xd4, 0x4b, 0xfa, 0x18, 0x76, 0x8c, 0x59, 0x89, 0x6b, 0xf7, 0xed, 0x17, 0x65, 0xcb, 0x2d, 0x14, 0xaf, 0x8c, 0x26, 0x02, 0x66, 0x03, 0x90, 0x99, 0xb2, 0x5a, 0x60, 0x3e, 0x4d, 0xdc, 0x50, 0x39, 0xd6, 0xef, 0x3a, 0x91, 0x84, 0x7d, 0x10, 0x88, 0xd4, 0x01, 0xc0, 0xc7, 0xe8, 0x47, 0x78, 0x1a, 0x8a, 0x59, 0x0d, 0x33, 0xa3, 0xc6, 0xcb, 0x4d, 0xf0, 0xfa, 0xb1, 0xc2, 0xf2, 0x23, 0x55 }, + { 0xdc, 0xff, 0xa9, 0xd5, 0x8c, 0x2a, 0x4c, 0xa2, 0xcd, 0xbb, 0x0c, 0x7a, 0xa4, 0xc4, 0xc1, 0xd4, 0x51, 0x65, 0x19, 0x00, 0x89, 0xf4, 0xe9, 0x83, 0xbb, 0x1c, 0x2c, 0xab, 0x4a, 0xae, 0xff, 0x1f, 0xa2, 0xb5, 0xee, 0x51, 0x6f, 0xec, 0xd7, 0x80, 0x54, 0x02, 0x40, 0xbf, 0x37, 0xe5, 0x6c, 0x8b, 0xcc, 0xa7, 0xfa, 0xb9, 0x80, 0xe1, 0xe6, 0x1c, 0x94, 0x00, 0xd8, 0xa9, 0xa5, 0xb1, 0x4a, 0xc6 }, + { 0x6f, 0xbf, 0x31, 0xb4, 0x5a, 0xb0, 0xc0, 0xb8, 0xda, 0xd1, 0xc0, 0xf5, 0xf4, 0x06, 0x13, 0x79, 0x91, 0x2d, 0xde, 0x5a, 0xa9, 0x22, 0x09, 0x9a, 0x03, 0x0b, 0x72, 0x5c, 0x73, 0x34, 0x6c, 0x52, 0x42, 0x91, 0xad, 0xef, 0x89, 0xd2, 0xf6, 0xfd, 0x8d, 0xfc, 0xda, 0x6d, 0x07, 0xda, 0xd8, 0x11, 0xa9, 0x31, 0x45, 0x36, 0xc2, 0x91, 0x5e, 0xd4, 0x5d, 0xa3, 0x49, 0x47, 0xe8, 0x3d, 0xe3, 0x4e }, + { 0xa0, 0xc6, 0x5b, 0xdd, 0xde, 0x8a, 0xde, 0xf5, 0x72, 0x82, 0xb0, 0x4b, 0x11, 0xe7, 0xbc, 0x8a, 0xab, 0x10, 0x5b, 0x99, 0x23, 0x1b, 0x75, 0x0c, 0x02, 0x1f, 0x4a, 0x73, 0x5c, 0xb1, 0xbc, 0xfa, 0xb8, 0x75, 0x53, 0xbb, 0xa3, 0xab, 0xb0, 0xc3, 0xe6, 0x4a, 0x0b, 0x69, 0x55, 0x28, 0x51, 0x85, 0xa0, 0xbd, 0x35, 0xfb, 0x8c, 0xfd, 0xe5, 0x57, 0x32, 0x9b, 0xeb, 0xb1, 0xf6, 0x29, 0xee, 0x93 }, + { 0xf9, 0x9d, 0x81, 0x55, 0x50, 0x55, 0x8e, 0x81, 0xec, 0xa2, 0xf9, 0x67, 0x18, 0xae, 0xd1, 0x0d, 0x86, 0xf3, 0xf1, 0xcf, 0xb6, 0x75, 0xcc, 0xe0, 0x6b, 0x0e, 0xff, 0x02, 0xf6, 0x17, 0xc5, 0xa4, 0x2c, 0x5a, 0xa7, 0x60, 0x27, 0x0f, 0x26, 0x79, 0xda, 0x26, 0x77, 0xc5, 0xae, 0xb9, 0x4f, 0x11, 0x42, 0x27, 0x7f, 0x21, 0xc7, 0xf7, 0x9f, 0x3c, 0x4f, 0x0c, 0xce, 0x4e, 0xd8, 0xee, 0x62, 0xb1 }, + { 0x95, 0x39, 0x1d, 0xa8, 0xfc, 0x7b, 0x91, 0x7a, 0x20, 0x44, 0xb3, 0xd6, 0xf5, 0x37, 0x4e, 0x1c, 0xa0, 0x72, 0xb4, 0x14, 0x54, 0xd5, 0x72, 0xc7, 0x35, 0x6c, 0x05, 0xfd, 0x4b, 0xc1, 0xe0, 0xf4, 0x0b, 0x8b, 0xb8, 0xb4, 0xa9, 0xf6, 0xbc, 0xe9, 0xbe, 0x2c, 0x46, 0x23, 0xc3, 0x99, 0xb0, 0xdc, 0xa0, 0xda, 0xb0, 0x5c, 0xb7, 0x28, 0x1b, 0x71, 0xa2, 0x1b, 0x0e, 0xbc, 0xd9, 0xe5, 0x56, 0x70 }, + { 0x04, 0xb9, 0xcd, 0x3d, 0x20, 0xd2, 0x21, 0xc0, 0x9a, 0xc8, 0x69, 0x13, 0xd3, 0xdc, 0x63, 0x04, 0x19, 0x89, 0xa9, 0xa1, 0xe6, 0x94, 0xf1, 0xe6, 0x39, 0xa3, 0xba, 0x7e, 0x45, 0x18, 0x40, 0xf7, 0x50, 0xc2, 0xfc, 0x19, 0x1d, 0x56, 0xad, 0x61, 0xf2, 0xe7, 0x93, 0x6b, 0xc0, 0xac, 0x8e, 0x09, 0x4b, 0x60, 0xca, 0xee, 0xd8, 0x78, 0xc1, 0x87, 0x99, 0x04, 0x54, 0x02, 0xd6, 0x1c, 0xea, 0xf9 }, + { 0xec, 0x0e, 0x0e, 0xf7, 0x07, 0xe4, 0xed, 0x6c, 0x0c, 0x66, 0xf9, 0xe0, 0x89, 0xe4, 0x95, 0x4b, 0x05, 0x80, 0x30, 0xd2, 0xdd, 0x86, 0x39, 0x8f, 0xe8, 0x40, 0x59, 0x63, 0x1f, 0x9e, 0xe5, 0x91, 0xd9, 0xd7, 0x73, 0x75, 0x35, 0x51, 0x49, 0x17, 0x8c, 0x0c, 0xf8, 0xf8, 0xe7, 0xc4, 0x9e, 0xd2, 0xa5, 0xe4, 0xf9, 0x54, 0x88, 0xa2, 0x24, 0x70, 0x67, 0xc2, 0x08, 0x51, 0x0f, 0xad, 0xc4, 0x4c }, + { 0x9a, 0x37, 0xcc, 0xe2, 0x73, 0xb7, 0x9c, 0x09, 0x91, 0x36, 0x77, 0x51, 0x0e, 0xaf, 0x76, 0x88, 0xe8, 0x9b, 0x33, 0x14, 0xd3, 0x53, 0x2f, 0xd2, 0x76, 0x4c, 0x39, 0xde, 0x02, 0x2a, 0x29, 0x45, 0xb5, 0x71, 0x0d, 0x13, 0x51, 0x7a, 0xf8, 0xdd, 0xc0, 0x31, 0x66, 0x24, 0xe7, 0x3b, 0xec, 0x1c, 0xe6, 0x7d, 0xf1, 0x52, 0x28, 0x30, 0x20, 0x36, 0xf3, 0x30, 0xab, 0x0c, 0xb4, 0xd2, 0x18, 0xdd }, + { 0x4c, 0xf9, 0xbb, 0x8f, 0xb3, 0xd4, 0xde, 0x8b, 0x38, 0xb2, 0xf2, 0x62, 0xd3, 0xc4, 0x0f, 0x46, 0xdf, 0xe7, 0x47, 0xe8, 0xfc, 0x0a, 0x41, 0x4c, 0x19, 0x3d, 0x9f, 0xcf, 0x75, 0x31, 0x06, 0xce, 0x47, 0xa1, 0x8f, 0x17, 0x2f, 0x12, 0xe8, 0xa2, 0xf1, 0xc2, 0x67, 0x26, 0x54, 0x53, 0x58, 0xe5, 0xee, 0x28, 0xc9, 0xe2, 0x21, 0x3a, 0x87, 0x87, 0xaa, 0xfb, 0xc5, 0x16, 0xd2, 0x34, 0x31, 0x52 }, + { 0x64, 0xe0, 0xc6, 0x3a, 0xf9, 0xc8, 0x08, 0xfd, 0x89, 0x31, 0x37, 0x12, 0x98, 0x67, 0xfd, 0x91, 0x93, 0x9d, 0x53, 0xf2, 0xaf, 0x04, 0xbe, 0x4f, 0xa2, 0x68, 0x00, 0x61, 0x00, 0x06, 0x9b, 0x2d, 0x69, 0xda, 0xa5, 0xc5, 0xd8, 0xed, 0x7f, 0xdd, 0xcb, 0x2a, 0x70, 0xee, 0xec, 0xdf, 0x2b, 0x10, 0x5d, 0xd4, 0x6a, 0x1e, 0x3b, 0x73, 0x11, 0x72, 0x8f, 0x63, 0x9a, 0xb4, 0x89, 0x32, 0x6b, 0xc9 }, + { 0x5e, 0x9c, 0x93, 0x15, 0x8d, 0x65, 0x9b, 0x2d, 0xef, 0x06, 0xb0, 0xc3, 0xc7, 0x56, 0x50, 0x45, 0x54, 0x26, 0x62, 0xd6, 0xee, 0xe8, 0xa9, 0x6a, 0x89, 0xb7, 0x8a, 0xde, 0x09, 0xfe, 0x8b, 0x3d, 0xcc, 0x09, 0x6d, 0x4f, 0xe4, 0x88, 0x15, 0xd8, 0x8d, 0x8f, 0x82, 0x62, 0x01, 0x56, 0x60, 0x2a, 0xf5, 0x41, 0x95, 0x5e, 0x1f, 0x6c, 0xa3, 0x0d, 0xce, 0x14, 0xe2, 0x54, 0xc3, 0x26, 0xb8, 0x8f }, + { 0x77, 0x75, 0xdf, 0xf8, 0x89, 0x45, 0x8d, 0xd1, 0x1a, 0xef, 0x41, 0x72, 0x76, 0x85, 0x3e, 0x21, 0x33, 0x5e, 0xb8, 0x8e, 0x4d, 0xec, 0x9c, 0xfb, 0x4e, 0x9e, 0xdb, 0x49, 0x82, 0x00, 0x88, 0x55, 0x1a, 0x2c, 0xa6, 0x03, 0x39, 0xf1, 0x20, 0x66, 0x10, 0x11, 0x69, 0xf0, 0xdf, 0xe8, 0x4b, 0x09, 0x8f, 0xdd, 0xb1, 0x48, 0xd9, 0xda, 0x6b, 0x3d, 0x61, 0x3d, 0xf2, 0x63, 0x88, 0x9a, 0xd6, 0x4b }, + { 0xf0, 0xd2, 0x80, 0x5a, 0xfb, 0xb9, 0x1f, 0x74, 0x39, 0x51, 0x35, 0x1a, 0x6d, 0x02, 0x4f, 0x93, 0x53, 0xa2, 0x3c, 0x7c, 0xe1, 0xfc, 0x2b, 0x05, 0x1b, 0x3a, 0x8b, 0x96, 0x8c, 0x23, 0x3f, 0x46, 0xf5, 0x0f, 0x80, 0x6e, 0xcb, 0x15, 0x68, 0xff, 0xaa, 0x0b, 0x60, 0x66, 0x1e, 0x33, 0x4b, 0x21, 0xdd, 0xe0, 0x4f, 0x8f, 0xa1, 0x55, 0xac, 0x74, 0x0e, 0xeb, 0x42, 0xe2, 0x0b, 0x60, 0xd7, 0x64 }, + { 0x86, 0xa2, 0xaf, 0x31, 0x6e, 0x7d, 0x77, 0x54, 0x20, 0x1b, 0x94, 0x2e, 0x27, 0x53, 0x64, 0xac, 0x12, 0xea, 0x89, 0x62, 0xab, 0x5b, 0xd8, 0xd7, 0xfb, 0x27, 0x6d, 0xc5, 0xfb, 0xff, 0xc8, 0xf9, 0xa2, 0x8c, 0xae, 0x4e, 0x48, 0x67, 0xdf, 0x67, 0x80, 0xd9, 0xb7, 0x25, 0x24, 0x16, 0x09, 0x27, 0xc8, 0x55, 0xda, 0x5b, 0x60, 0x78, 0xe0, 0xb5, 0x54, 0xaa, 0x91, 0xe3, 0x1c, 0xb9, 0xca, 0x1d }, + { 0x10, 0xbd, 0xf0, 0xca, 0xa0, 0x80, 0x27, 0x05, 0xe7, 0x06, 0x36, 0x9b, 0xaf, 0x8a, 0x3f, 0x79, 0xd7, 0x2c, 0x0a, 0x03, 0xa8, 0x06, 0x75, 0xa7, 0xbb, 0xb0, 0x0b, 0xe3, 0xa4, 0x5e, 0x51, 0x64, 0x24, 0xd1, 0xee, 0x88, 0xef, 0xb5, 0x6f, 0x6d, 0x57, 0x77, 0x54, 0x5a, 0xe6, 0xe2, 0x77, 0x65, 0xc3, 0xa8, 0xf5, 0xe4, 0x93, 0xfc, 0x30, 0x89, 0x15, 0x63, 0x89, 0x33, 0xa1, 0xdf, 0xee, 0x55 }, + { 0xb0, 0x17, 0x81, 0x09, 0x2b, 0x17, 0x48, 0x45, 0x9e, 0x2e, 0x4e, 0xc1, 0x78, 0x69, 0x66, 0x27, 0xbf, 0x4e, 0xba, 0xfe, 0xbb, 0xa7, 0x74, 0xec, 0xf0, 0x18, 0xb7, 0x9a, 0x68, 0xae, 0xb8, 0x49, 0x17, 0xbf, 0x0b, 0x84, 0xbb, 0x79, 0xd1, 0x7b, 0x74, 0x31, 0x51, 0x14, 0x4c, 0xd6, 0x6b, 0x7b, 0x33, 0xa4, 0xb9, 0xe5, 0x2c, 0x76, 0xc4, 0xe1, 0x12, 0x05, 0x0f, 0xf5, 0x38, 0x5b, 0x7f, 0x0b }, + { 0xc6, 0xdb, 0xc6, 0x1d, 0xec, 0x6e, 0xae, 0xac, 0x81, 0xe3, 0xd5, 0xf7, 0x55, 0x20, 0x3c, 0x8e, 0x22, 0x05, 0x51, 0x53, 0x4a, 0x0b, 0x2f, 0xd1, 0x05, 0xa9, 0x18, 0x89, 0x94, 0x5a, 0x63, 0x85, 0x50, 0x20, 0x4f, 0x44, 0x09, 0x3d, 0xd9, 0x98, 0xc0, 0x76, 0x20, 0x5d, 0xff, 0xad, 0x70, 0x3a, 0x0e, 0x5c, 0xd3, 0xc7, 0xf4, 0x38, 0xa7, 0xe6, 0x34, 0xcd, 0x59, 0xfe, 0xde, 0xdb, 0x53, 0x9e }, + { 0xeb, 0xa5, 0x1a, 0xcf, 0xfb, 0x4c, 0xea, 0x31, 0xdb, 0x4b, 0x8d, 0x87, 0xe9, 0xbf, 0x7d, 0xd4, 0x8f, 0xe9, 0x7b, 0x02, 0x53, 0xae, 0x67, 0xaa, 0x58, 0x0f, 0x9a, 0xc4, 0xa9, 0xd9, 0x41, 0xf2, 0xbe, 0xa5, 0x18, 0xee, 0x28, 0x68, 0x18, 0xcc, 0x9f, 0x63, 0x3f, 0x2a, 0x3b, 0x9f, 0xb6, 0x8e, 0x59, 0x4b, 0x48, 0xcd, 0xd6, 0xd5, 0x15, 0xbf, 0x1d, 0x52, 0xba, 0x6c, 0x85, 0xa2, 0x03, 0xa7 }, + { 0x86, 0x22, 0x1f, 0x3a, 0xda, 0x52, 0x03, 0x7b, 0x72, 0x22, 0x4f, 0x10, 0x5d, 0x79, 0x99, 0x23, 0x1c, 0x5e, 0x55, 0x34, 0xd0, 0x3d, 0xa9, 0xd9, 0xc0, 0xa1, 0x2a, 0xcb, 0x68, 0x46, 0x0c, 0xd3, 0x75, 0xda, 0xf8, 0xe2, 0x43, 0x86, 0x28, 0x6f, 0x96, 0x68, 0xf7, 0x23, 0x26, 0xdb, 0xf9, 0x9b, 0xa0, 0x94, 0x39, 0x24, 0x37, 0xd3, 0x98, 0xe9, 0x5b, 0xb8, 0x16, 0x1d, 0x71, 0x7f, 0x89, 0x91 }, + { 0x55, 0x95, 0xe0, 0x5c, 0x13, 0xa7, 0xec, 0x4d, 0xc8, 0xf4, 0x1f, 0xb7, 0x0c, 0xb5, 0x0a, 0x71, 0xbc, 0xe1, 0x7c, 0x02, 0x4f, 0xf6, 0xde, 0x7a, 0xf6, 0x18, 0xd0, 0xcc, 0x4e, 0x9c, 0x32, 0xd9, 0x57, 0x0d, 0x6d, 0x3e, 0xa4, 0x5b, 0x86, 0x52, 0x54, 0x91, 0x03, 0x0c, 0x0d, 0x8f, 0x2b, 0x18, 0x36, 0xd5, 0x77, 0x8c, 0x1c, 0xe7, 0x35, 0xc1, 0x77, 0x07, 0xdf, 0x36, 0x4d, 0x05, 0x43, 0x47 }, + { 0xce, 0x0f, 0x4f, 0x6a, 0xca, 0x89, 0x59, 0x0a, 0x37, 0xfe, 0x03, 0x4d, 0xd7, 0x4d, 0xd5, 0xfa, 0x65, 0xeb, 0x1c, 0xbd, 0x0a, 0x41, 0x50, 0x8a, 0xad, 0xdc, 0x09, 0x35, 0x1a, 0x3c, 0xea, 0x6d, 0x18, 0xcb, 0x21, 0x89, 0xc5, 0x4b, 0x70, 0x0c, 0x00, 0x9f, 0x4c, 0xbf, 0x05, 0x21, 0xc7, 0xea, 0x01, 0xbe, 0x61, 0xc5, 0xae, 0x09, 0xcb, 0x54, 0xf2, 0x7b, 0xc1, 0xb4, 0x4d, 0x65, 0x8c, 0x82 }, + { 0x7e, 0xe8, 0x0b, 0x06, 0xa2, 0x15, 0xa3, 0xbc, 0xa9, 0x70, 0xc7, 0x7c, 0xda, 0x87, 0x61, 0x82, 0x2b, 0xc1, 0x03, 0xd4, 0x4f, 0xa4, 0xb3, 0x3f, 0x4d, 0x07, 0xdc, 0xb9, 0x97, 0xe3, 0x6d, 0x55, 0x29, 0x8b, 0xce, 0xae, 0x12, 0x24, 0x1b, 0x3f, 0xa0, 0x7f, 0xa6, 0x3b, 0xe5, 0x57, 0x60, 0x68, 0xda, 0x38, 0x7b, 0x8d, 0x58, 0x59, 0xae, 0xab, 0x70, 0x13, 0x69, 0x84, 0x8b, 0x17, 0x6d, 0x42 }, + { 0x94, 0x0a, 0x84, 0xb6, 0xa8, 0x4d, 0x10, 0x9a, 0xab, 0x20, 0x8c, 0x02, 0x4c, 0x6c, 0xe9, 0x64, 0x76, 0x76, 0xba, 0x0a, 0xaa, 0x11, 0xf8, 0x6d, 0xbb, 0x70, 0x18, 0xf9, 0xfd, 0x22, 0x20, 0xa6, 0xd9, 0x01, 0xa9, 0x02, 0x7f, 0x9a, 0xbc, 0xf9, 0x35, 0x37, 0x27, 0x27, 0xcb, 0xf0, 0x9e, 0xbd, 0x61, 0xa2, 0xa2, 0xee, 0xb8, 0x76, 0x53, 0xe8, 0xec, 0xad, 0x1b, 0xab, 0x85, 0xdc, 0x83, 0x27 }, + { 0x20, 0x20, 0xb7, 0x82, 0x64, 0xa8, 0x2d, 0x9f, 0x41, 0x51, 0x14, 0x1a, 0xdb, 0xa8, 0xd4, 0x4b, 0xf2, 0x0c, 0x5e, 0xc0, 0x62, 0xee, 0xe9, 0xb5, 0x95, 0xa1, 0x1f, 0x9e, 0x84, 0x90, 0x1b, 0xf1, 0x48, 0xf2, 0x98, 0xe0, 0xc9, 0xf8, 0x77, 0x7d, 0xcd, 0xbc, 0x7c, 0xc4, 0x67, 0x0a, 0xac, 0x35, 0x6c, 0xc2, 0xad, 0x8c, 0xcb, 0x16, 0x29, 0xf1, 0x6f, 0x6a, 0x76, 0xbc, 0xef, 0xbe, 0xe7, 0x60 }, + { 0xd1, 0xb8, 0x97, 0xb0, 0xe0, 0x75, 0xba, 0x68, 0xab, 0x57, 0x2a, 0xdf, 0x9d, 0x9c, 0x43, 0x66, 0x63, 0xe4, 0x3e, 0xb3, 0xd8, 0xe6, 0x2d, 0x92, 0xfc, 0x49, 0xc9, 0xbe, 0x21, 0x4e, 0x6f, 0x27, 0x87, 0x3f, 0xe2, 0x15, 0xa6, 0x51, 0x70, 0xe6, 0xbe, 0xa9, 0x02, 0x40, 0x8a, 0x25, 0xb4, 0x95, 0x06, 0xf4, 0x7b, 0xab, 0xd0, 0x7c, 0xec, 0xf7, 0x11, 0x3e, 0xc1, 0x0c, 0x5d, 0xd3, 0x12, 0x52 }, + { 0xb1, 0x4d, 0x0c, 0x62, 0xab, 0xfa, 0x46, 0x9a, 0x35, 0x71, 0x77, 0xe5, 0x94, 0xc1, 0x0c, 0x19, 0x42, 0x43, 0xed, 0x20, 0x25, 0xab, 0x8a, 0xa5, 0xad, 0x2f, 0xa4, 0x1a, 0xd3, 0x18, 0xe0, 0xff, 0x48, 0xcd, 0x5e, 0x60, 0xbe, 0xc0, 0x7b, 0x13, 0x63, 0x4a, 0x71, 0x1d, 0x23, 0x26, 0xe4, 0x88, 0xa9, 0x85, 0xf3, 0x1e, 0x31, 0x15, 0x33, 0x99, 0xe7, 0x30, 0x88, 0xef, 0xc8, 0x6a, 0x5c, 0x55 }, + { 0x41, 0x69, 0xc5, 0xcc, 0x80, 0x8d, 0x26, 0x97, 0xdc, 0x2a, 0x82, 0x43, 0x0d, 0xc2, 0x3e, 0x3c, 0xd3, 0x56, 0xdc, 0x70, 0xa9, 0x45, 0x66, 0x81, 0x05, 0x02, 0xb8, 0xd6, 0x55, 0xb3, 0x9a, 0xbf, 0x9e, 0x7f, 0x90, 0x2f, 0xe7, 0x17, 0xe0, 0x38, 0x92, 0x19, 0x85, 0x9e, 0x19, 0x45, 0xdf, 0x1a, 0xf6, 0xad, 0xa4, 0x2e, 0x4c, 0xcd, 0xa5, 0x5a, 0x19, 0x7b, 0x71, 0x00, 0xa3, 0x0c, 0x30, 0xa1 }, + { 0x25, 0x8a, 0x4e, 0xdb, 0x11, 0x3d, 0x66, 0xc8, 0x39, 0xc8, 0xb1, 0xc9, 0x1f, 0x15, 0xf3, 0x5a, 0xde, 0x60, 0x9f, 0x11, 0xcd, 0x7f, 0x86, 0x81, 0xa4, 0x04, 0x5b, 0x9f, 0xef, 0x7b, 0x0b, 0x24, 0xc8, 0x2c, 0xda, 0x06, 0xa5, 0xf2, 0x06, 0x7b, 0x36, 0x88, 0x25, 0xe3, 0x91, 0x4e, 0x53, 0xd6, 0x94, 0x8e, 0xde, 0x92, 0xef, 0xd6, 0xe8, 0x38, 0x7f, 0xa2, 0xe5, 0x37, 0x23, 0x9b, 0x5b, 0xee }, + { 0x79, 0xd2, 0xd8, 0x69, 0x6d, 0x30, 0xf3, 0x0f, 0xb3, 0x46, 0x57, 0x76, 0x11, 0x71, 0xa1, 0x1e, 0x6c, 0x3f, 0x1e, 0x64, 0xcb, 0xe7, 0xbe, 0xbe, 0xe1, 0x59, 0xcb, 0x95, 0xbf, 0xaf, 0x81, 0x2b, 0x4f, 0x41, 0x1e, 0x2f, 0x26, 0xd9, 0xc4, 0x21, 0xdc, 0x2c, 0x28, 0x4a, 0x33, 0x42, 0xd8, 0x23, 0xec, 0x29, 0x38, 0x49, 0xe4, 0x2d, 0x1e, 0x46, 0xb0, 0xa4, 0xac, 0x1e, 0x3c, 0x86, 0xab, 0xaa }, + { 0x8b, 0x94, 0x36, 0x01, 0x0d, 0xc5, 0xde, 0xe9, 0x92, 0xae, 0x38, 0xae, 0xa9, 0x7f, 0x2c, 0xd6, 0x3b, 0x94, 0x6d, 0x94, 0xfe, 0xdd, 0x2e, 0xc9, 0x67, 0x1d, 0xcd, 0xe3, 0xbd, 0x4c, 0xe9, 0x56, 0x4d, 0x55, 0x5c, 0x66, 0xc1, 0x5b, 0xb2, 0xb9, 0x00, 0xdf, 0x72, 0xed, 0xb6, 0xb8, 0x91, 0xeb, 0xca, 0xdf, 0xef, 0xf6, 0x3c, 0x9e, 0xa4, 0x03, 0x6a, 0x99, 0x8b, 0xe7, 0x97, 0x39, 0x81, 0xe7 }, + { 0xc8, 0xf6, 0x8e, 0x69, 0x6e, 0xd2, 0x82, 0x42, 0xbf, 0x99, 0x7f, 0x5b, 0x3b, 0x34, 0x95, 0x95, 0x08, 0xe4, 0x2d, 0x61, 0x38, 0x10, 0xf1, 0xe2, 0xa4, 0x35, 0xc9, 0x6e, 0xd2, 0xff, 0x56, 0x0c, 0x70, 0x22, 0xf3, 0x61, 0xa9, 0x23, 0x4b, 0x98, 0x37, 0xfe, 0xee, 0x90, 0xbf, 0x47, 0x92, 0x2e, 0xe0, 0xfd, 0x5f, 0x8d, 0xdf, 0x82, 0x37, 0x18, 0xd8, 0x6d, 0x1e, 0x16, 0xc6, 0x09, 0x00, 0x71 }, + { 0xb0, 0x2d, 0x3e, 0xee, 0x48, 0x60, 0xd5, 0x86, 0x8b, 0x2c, 0x39, 0xce, 0x39, 0xbf, 0xe8, 0x10, 0x11, 0x29, 0x05, 0x64, 0xdd, 0x67, 0x8c, 0x85, 0xe8, 0x78, 0x3f, 0x29, 0x30, 0x2d, 0xfc, 0x13, 0x99, 0xba, 0x95, 0xb6, 0xb5, 0x3c, 0xd9, 0xeb, 0xbf, 0x40, 0x0c, 0xca, 0x1d, 0xb0, 0xab, 0x67, 0xe1, 0x9a, 0x32, 0x5f, 0x2d, 0x11, 0x58, 0x12, 0xd2, 0x5d, 0x00, 0x97, 0x8a, 0xd1, 0xbc, 0xa4 }, + { 0x76, 0x93, 0xea, 0x73, 0xaf, 0x3a, 0xc4, 0xda, 0xd2, 0x1c, 0xa0, 0xd8, 0xda, 0x85, 0xb3, 0x11, 0x8a, 0x7d, 0x1c, 0x60, 0x24, 0xcf, 0xaf, 0x55, 0x76, 0x99, 0x86, 0x82, 0x17, 0xbc, 0x0c, 0x2f, 0x44, 0xa1, 0x99, 0xbc, 0x6c, 0x0e, 0xdd, 0x51, 0x97, 0x98, 0xba, 0x05, 0xbd, 0x5b, 0x1b, 0x44, 0x84, 0x34, 0x6a, 0x47, 0xc2, 0xca, 0xdf, 0x6b, 0xf3, 0x0b, 0x78, 0x5c, 0xc8, 0x8b, 0x2b, 0xaf }, + { 0xa0, 0xe5, 0xc1, 0xc0, 0x03, 0x1c, 0x02, 0xe4, 0x8b, 0x7f, 0x09, 0xa5, 0xe8, 0x96, 0xee, 0x9a, 0xef, 0x2f, 0x17, 0xfc, 0x9e, 0x18, 0xe9, 0x97, 0xd7, 0xf6, 0xca, 0xc7, 0xae, 0x31, 0x64, 0x22, 0xc2, 0xb1, 0xe7, 0x79, 0x84, 0xe5, 0xf3, 0xa7, 0x3c, 0xb4, 0x5d, 0xee, 0xd5, 0xd3, 0xf8, 0x46, 0x00, 0x10, 0x5e, 0x6e, 0xe3, 0x8f, 0x2d, 0x09, 0x0c, 0x7d, 0x04, 0x42, 0xea, 0x34, 0xc4, 0x6d }, + { 0x41, 0xda, 0xa6, 0xad, 0xcf, 0xdb, 0x69, 0xf1, 0x44, 0x0c, 0x37, 0xb5, 0x96, 0x44, 0x01, 0x65, 0xc1, 0x5a, 0xda, 0x59, 0x68, 0x13, 0xe2, 0xe2, 0x2f, 0x06, 0x0f, 0xcd, 0x55, 0x1f, 0x24, 0xde, 0xe8, 0xe0, 0x4b, 0xa6, 0x89, 0x03, 0x87, 0x88, 0x6c, 0xee, 0xc4, 0xa7, 0xa0, 0xd7, 0xfc, 0x6b, 0x44, 0x50, 0x63, 0x92, 0xec, 0x38, 0x22, 0xc0, 0xd8, 0xc1, 0xac, 0xfc, 0x7d, 0x5a, 0xeb, 0xe8 }, + { 0x14, 0xd4, 0xd4, 0x0d, 0x59, 0x84, 0xd8, 0x4c, 0x5c, 0xf7, 0x52, 0x3b, 0x77, 0x98, 0xb2, 0x54, 0xe2, 0x75, 0xa3, 0xa8, 0xcc, 0x0a, 0x1b, 0xd0, 0x6e, 0xbc, 0x0b, 0xee, 0x72, 0x68, 0x56, 0xac, 0xc3, 0xcb, 0xf5, 0x16, 0xff, 0x66, 0x7c, 0xda, 0x20, 0x58, 0xad, 0x5c, 0x34, 0x12, 0x25, 0x44, 0x60, 0xa8, 0x2c, 0x92, 0x18, 0x70, 0x41, 0x36, 0x3c, 0xc7, 0x7a, 0x4d, 0xc2, 0x15, 0xe4, 0x87 }, + { 0xd0, 0xe7, 0xa1, 0xe2, 0xb9, 0xa4, 0x47, 0xfe, 0xe8, 0x3e, 0x22, 0x77, 0xe9, 0xff, 0x80, 0x10, 0xc2, 0xf3, 0x75, 0xae, 0x12, 0xfa, 0x7a, 0xaa, 0x8c, 0xa5, 0xa6, 0x31, 0x78, 0x68, 0xa2, 0x6a, 0x36, 0x7a, 0x0b, 0x69, 0xfb, 0xc1, 0xcf, 0x32, 0xa5, 0x5d, 0x34, 0xeb, 0x37, 0x06, 0x63, 0x01, 0x6f, 0x3d, 0x21, 0x10, 0x23, 0x0e, 0xba, 0x75, 0x40, 0x28, 0xa5, 0x6f, 0x54, 0xac, 0xf5, 0x7c }, + { 0xe7, 0x71, 0xaa, 0x8d, 0xb5, 0xa3, 0xe0, 0x43, 0xe8, 0x17, 0x8f, 0x39, 0xa0, 0x85, 0x7b, 0xa0, 0x4a, 0x3f, 0x18, 0xe4, 0xaa, 0x05, 0x74, 0x3c, 0xf8, 0xd2, 0x22, 0xb0, 0xb0, 0x95, 0x82, 0x53, 0x50, 0xba, 0x42, 0x2f, 0x63, 0x38, 0x2a, 0x23, 0xd9, 0x2e, 0x41, 0x49, 0x07, 0x4e, 0x81, 0x6a, 0x36, 0xc1, 0xcd, 0x28, 0x28, 0x4d, 0x14, 0x62, 0x67, 0x94, 0x0b, 0x31, 0xf8, 0x81, 0x8e, 0xa2 }, + { 0xfe, 0xb4, 0xfd, 0x6f, 0x9e, 0x87, 0xa5, 0x6b, 0xef, 0x39, 0x8b, 0x32, 0x84, 0xd2, 0xbd, 0xa5, 0xb5, 0xb0, 0xe1, 0x66, 0x58, 0x3a, 0x66, 0xb6, 0x1e, 0x53, 0x84, 0x57, 0xff, 0x05, 0x84, 0x87, 0x2c, 0x21, 0xa3, 0x29, 0x62, 0xb9, 0x92, 0x8f, 0xfa, 0xb5, 0x8d, 0xe4, 0xaf, 0x2e, 0xdd, 0x4e, 0x15, 0xd8, 0xb3, 0x55, 0x70, 0x52, 0x32, 0x07, 0xff, 0x4e, 0x2a, 0x5a, 0xa7, 0x75, 0x4c, 0xaa }, + { 0x46, 0x2f, 0x17, 0xbf, 0x00, 0x5f, 0xb1, 0xc1, 0xb9, 0xe6, 0x71, 0x77, 0x9f, 0x66, 0x52, 0x09, 0xec, 0x28, 0x73, 0xe3, 0xe4, 0x11, 0xf9, 0x8d, 0xab, 0xf2, 0x40, 0xa1, 0xd5, 0xec, 0x3f, 0x95, 0xce, 0x67, 0x96, 0xb6, 0xfc, 0x23, 0xfe, 0x17, 0x19, 0x03, 0xb5, 0x02, 0x02, 0x34, 0x67, 0xde, 0xc7, 0x27, 0x3f, 0xf7, 0x48, 0x79, 0xb9, 0x29, 0x67, 0xa2, 0xa4, 0x3a, 0x5a, 0x18, 0x3d, 0x33 }, + { 0xd3, 0x33, 0x81, 0x93, 0xb6, 0x45, 0x53, 0xdb, 0xd3, 0x8d, 0x14, 0x4b, 0xea, 0x71, 0xc5, 0x91, 0x5b, 0xb1, 0x10, 0xe2, 0xd8, 0x81, 0x80, 0xdb, 0xc5, 0xdb, 0x36, 0x4f, 0xd6, 0x17, 0x1d, 0xf3, 0x17, 0xfc, 0x72, 0x68, 0x83, 0x1b, 0x5a, 0xef, 0x75, 0xe4, 0x34, 0x2b, 0x2f, 0xad, 0x87, 0x97, 0xba, 0x39, 0xed, 0xdc, 0xef, 0x80, 0xe6, 0xec, 0x08, 0x15, 0x93, 0x50, 0xb1, 0xad, 0x69, 0x6d }, + { 0xe1, 0x59, 0x0d, 0x58, 0x5a, 0x3d, 0x39, 0xf7, 0xcb, 0x59, 0x9a, 0xbd, 0x47, 0x90, 0x70, 0x96, 0x64, 0x09, 0xa6, 0x84, 0x6d, 0x43, 0x77, 0xac, 0xf4, 0x47, 0x1d, 0x06, 0x5d, 0x5d, 0xb9, 0x41, 0x29, 0xcc, 0x9b, 0xe9, 0x25, 0x73, 0xb0, 0x5e, 0xd2, 0x26, 0xbe, 0x1e, 0x9b, 0x7c, 0xb0, 0xca, 0xbe, 0x87, 0x91, 0x85, 0x89, 0xf8, 0x0d, 0xad, 0xd4, 0xef, 0x5e, 0xf2, 0x5a, 0x93, 0xd2, 0x8e }, + { 0xf8, 0xf3, 0x72, 0x6a, 0xc5, 0xa2, 0x6c, 0xc8, 0x01, 0x32, 0x49, 0x3a, 0x6f, 0xed, 0xcb, 0x0e, 0x60, 0x76, 0x0c, 0x09, 0xcf, 0xc8, 0x4c, 0xad, 0x17, 0x81, 0x75, 0x98, 0x68, 0x19, 0x66, 0x5e, 0x76, 0x84, 0x2d, 0x7b, 0x9f, 0xed, 0xf7, 0x6d, 0xdd, 0xeb, 0xf5, 0xd3, 0xf5, 0x6f, 0xaa, 0xad, 0x44, 0x77, 0x58, 0x7a, 0xf2, 0x16, 0x06, 0xd3, 0x96, 0xae, 0x57, 0x0d, 0x8e, 0x71, 0x9a, 0xf2 }, + { 0x30, 0x18, 0x60, 0x55, 0xc0, 0x79, 0x49, 0x94, 0x81, 0x83, 0xc8, 0x50, 0xe9, 0xa7, 0x56, 0xcc, 0x09, 0x93, 0x7e, 0x24, 0x7d, 0x9d, 0x92, 0x8e, 0x86, 0x9e, 0x20, 0xba, 0xfc, 0x3c, 0xd9, 0x72, 0x17, 0x19, 0xd3, 0x4e, 0x04, 0xa0, 0x89, 0x9b, 0x92, 0xc7, 0x36, 0x08, 0x45, 0x50, 0x18, 0x68, 0x86, 0xef, 0xba, 0x2e, 0x79, 0x0d, 0x8b, 0xe6, 0xeb, 0xf0, 0x40, 0xb2, 0x09, 0xc4, 0x39, 0xa4 }, + { 0xf3, 0xc4, 0x27, 0x6c, 0xb8, 0x63, 0x63, 0x77, 0x12, 0xc2, 0x41, 0xc4, 0x44, 0xc5, 0xcc, 0x1e, 0x35, 0x54, 0xe0, 0xfd, 0xdb, 0x17, 0x4d, 0x03, 0x58, 0x19, 0xdd, 0x83, 0xeb, 0x70, 0x0b, 0x4c, 0xe8, 0x8d, 0xf3, 0xab, 0x38, 0x41, 0xba, 0x02, 0x08, 0x5e, 0x1a, 0x99, 0xb4, 0xe1, 0x73, 0x10, 0xc5, 0x34, 0x10, 0x75, 0xc0, 0x45, 0x8b, 0xa3, 0x76, 0xc9, 0x5a, 0x68, 0x18, 0xfb, 0xb3, 0xe2 }, + { 0x0a, 0xa0, 0x07, 0xc4, 0xdd, 0x9d, 0x58, 0x32, 0x39, 0x30, 0x40, 0xa1, 0x58, 0x3c, 0x93, 0x0b, 0xca, 0x7d, 0xc5, 0xe7, 0x7e, 0xa5, 0x3a, 0xdd, 0x7e, 0x2b, 0x3f, 0x7c, 0x8e, 0x23, 0x13, 0x68, 0x04, 0x35, 0x20, 0xd4, 0xa3, 0xef, 0x53, 0xc9, 0x69, 0xb6, 0xbb, 0xfd, 0x02, 0x59, 0x46, 0xf6, 0x32, 0xbd, 0x7f, 0x76, 0x5d, 0x53, 0xc2, 0x10, 0x03, 0xb8, 0xf9, 0x83, 0xf7, 0x5e, 0x2a, 0x6a }, + { 0x08, 0xe9, 0x46, 0x47, 0x20, 0x53, 0x3b, 0x23, 0xa0, 0x4e, 0xc2, 0x4f, 0x7a, 0xe8, 0xc1, 0x03, 0x14, 0x5f, 0x76, 0x53, 0x87, 0xd7, 0x38, 0x77, 0x7d, 0x3d, 0x34, 0x34, 0x77, 0xfd, 0x1c, 0x58, 0xdb, 0x05, 0x21, 0x42, 0xca, 0xb7, 0x54, 0xea, 0x67, 0x43, 0x78, 0xe1, 0x87, 0x66, 0xc5, 0x35, 0x42, 0xf7, 0x19, 0x70, 0x17, 0x1c, 0xc4, 0xf8, 0x16, 0x94, 0x24, 0x6b, 0x71, 0x7d, 0x75, 0x64 }, + { 0xd3, 0x7f, 0xf7, 0xad, 0x29, 0x79, 0x93, 0xe7, 0xec, 0x21, 0xe0, 0xf1, 0xb4, 0xb5, 0xae, 0x71, 0x9c, 0xdc, 0x83, 0xc5, 0xdb, 0x68, 0x75, 0x27, 0xf2, 0x75, 0x16, 0xcb, 0xff, 0xa8, 0x22, 0x88, 0x8a, 0x68, 0x10, 0xee, 0x5c, 0x1c, 0xa7, 0xbf, 0xe3, 0x32, 0x11, 0x19, 0xbe, 0x1a, 0xb7, 0xbf, 0xa0, 0xa5, 0x02, 0x67, 0x1c, 0x83, 0x29, 0x49, 0x4d, 0xf7, 0xad, 0x6f, 0x52, 0x2d, 0x44, 0x0f }, + { 0xdd, 0x90, 0x42, 0xf6, 0xe4, 0x64, 0xdc, 0xf8, 0x6b, 0x12, 0x62, 0xf6, 0xac, 0xcf, 0xaf, 0xbd, 0x8c, 0xfd, 0x90, 0x2e, 0xd3, 0xed, 0x89, 0xab, 0xf7, 0x8f, 0xfa, 0x48, 0x2d, 0xbd, 0xee, 0xb6, 0x96, 0x98, 0x42, 0x39, 0x4c, 0x9a, 0x11, 0x68, 0xae, 0x3d, 0x48, 0x1a, 0x01, 0x78, 0x42, 0xf6, 0x60, 0x00, 0x2d, 0x42, 0x44, 0x7c, 0x6b, 0x22, 0xf7, 0xb7, 0x2f, 0x21, 0xaa, 0xe0, 0x21, 0xc9 }, + { 0xbd, 0x96, 0x5b, 0xf3, 0x1e, 0x87, 0xd7, 0x03, 0x27, 0x53, 0x6f, 0x2a, 0x34, 0x1c, 0xeb, 0xc4, 0x76, 0x8e, 0xca, 0x27, 0x5f, 0xa0, 0x5e, 0xf9, 0x8f, 0x7f, 0x1b, 0x71, 0xa0, 0x35, 0x12, 0x98, 0xde, 0x00, 0x6f, 0xba, 0x73, 0xfe, 0x67, 0x33, 0xed, 0x01, 0xd7, 0x58, 0x01, 0xb4, 0xa9, 0x28, 0xe5, 0x42, 0x31, 0xb3, 0x8e, 0x38, 0xc5, 0x62, 0xb2, 0xe3, 0x3e, 0xa1, 0x28, 0x49, 0x92, 0xfa }, + { 0x65, 0x67, 0x6d, 0x80, 0x06, 0x17, 0x97, 0x2f, 0xbd, 0x87, 0xe4, 0xb9, 0x51, 0x4e, 0x1c, 0x67, 0x40, 0x2b, 0x7a, 0x33, 0x10, 0x96, 0xd3, 0xbf, 0xac, 0x22, 0xf1, 0xab, 0xb9, 0x53, 0x74, 0xab, 0xc9, 0x42, 0xf1, 0x6e, 0x9a, 0xb0, 0xea, 0xd3, 0x3b, 0x87, 0xc9, 0x19, 0x68, 0xa6, 0xe5, 0x09, 0xe1, 0x19, 0xff, 0x07, 0x78, 0x7b, 0x3e, 0xf4, 0x83, 0xe1, 0xdc, 0xdc, 0xcf, 0x6e, 0x30, 0x22 }, + { 0x93, 0x9f, 0xa1, 0x89, 0x69, 0x9c, 0x5d, 0x2c, 0x81, 0xdd, 0xd1, 0xff, 0xc1, 0xfa, 0x20, 0x7c, 0x97, 0x0b, 0x6a, 0x36, 0x85, 0xbb, 0x29, 0xce, 0x1d, 0x3e, 0x99, 0xd4, 0x2f, 0x2f, 0x74, 0x42, 0xda, 0x53, 0xe9, 0x5a, 0x72, 0x90, 0x73, 0x14, 0xf4, 0x58, 0x83, 0x99, 0xa3, 0xff, 0x5b, 0x0a, 0x92, 0xbe, 0xb3, 0xf6, 0xbe, 0x26, 0x94, 0xf9, 0xf8, 0x6e, 0xcf, 0x29, 0x52, 0xd5, 0xb4, 0x1c }, + { 0xc5, 0x16, 0x54, 0x17, 0x01, 0x86, 0x3f, 0x91, 0x00, 0x5f, 0x31, 0x41, 0x08, 0xce, 0xec, 0xe3, 0xc6, 0x43, 0xe0, 0x4f, 0xc8, 0xc4, 0x2f, 0xd2, 0xff, 0x55, 0x62, 0x20, 0xe6, 0x16, 0xaa, 0xa6, 0xa4, 0x8a, 0xeb, 0x97, 0xa8, 0x4b, 0xad, 0x74, 0x78, 0x2e, 0x8d, 0xff, 0x96, 0xa1, 0xa2, 0xfa, 0x94, 0x93, 0x39, 0xd7, 0x22, 0xed, 0xca, 0xa3, 0x2b, 0x57, 0x06, 0x70, 0x41, 0xdf, 0x88, 0xcc }, + { 0x98, 0x7f, 0xd6, 0xe0, 0xd6, 0x85, 0x7c, 0x55, 0x3e, 0xae, 0xbb, 0x3d, 0x34, 0x97, 0x0a, 0x2c, 0x2f, 0x6e, 0x89, 0xa3, 0x54, 0x8f, 0x49, 0x25, 0x21, 0x72, 0x2b, 0x80, 0xa1, 0xc2, 0x1a, 0x15, 0x38, 0x92, 0x34, 0x6d, 0x2c, 0xba, 0x64, 0x44, 0x21, 0x2d, 0x56, 0xda, 0x9a, 0x26, 0xe3, 0x24, 0xdc, 0xcb, 0xc0, 0xdc, 0xde, 0x85, 0xd4, 0xd2, 0xee, 0x43, 0x99, 0xee, 0xc5, 0xa6, 0x4e, 0x8f }, + { 0xae, 0x56, 0xde, 0xb1, 0xc2, 0x32, 0x8d, 0x9c, 0x40, 0x17, 0x70, 0x6b, 0xce, 0x6e, 0x99, 0xd4, 0x13, 0x49, 0x05, 0x3b, 0xa9, 0xd3, 0x36, 0xd6, 0x77, 0xc4, 0xc2, 0x7d, 0x9f, 0xd5, 0x0a, 0xe6, 0xae, 0xe1, 0x7e, 0x85, 0x31, 0x54, 0xe1, 0xf4, 0xfe, 0x76, 0x72, 0x34, 0x6d, 0xa2, 0xea, 0xa3, 0x1e, 0xea, 0x53, 0xfc, 0xf2, 0x4a, 0x22, 0x80, 0x4f, 0x11, 0xd0, 0x3d, 0xa6, 0xab, 0xfc, 0x2b }, + { 0x49, 0xd6, 0xa6, 0x08, 0xc9, 0xbd, 0xe4, 0x49, 0x18, 0x70, 0x49, 0x85, 0x72, 0xac, 0x31, 0xaa, 0xc3, 0xfa, 0x40, 0x93, 0x8b, 0x38, 0xa7, 0x81, 0x8f, 0x72, 0x38, 0x3e, 0xb0, 0x40, 0xad, 0x39, 0x53, 0x2b, 0xc0, 0x65, 0x71, 0xe1, 0x3d, 0x76, 0x7e, 0x69, 0x45, 0xab, 0x77, 0xc0, 0xbd, 0xc3, 0xb0, 0x28, 0x42, 0x53, 0x34, 0x3f, 0x9f, 0x6c, 0x12, 0x44, 0xeb, 0xf2, 0xff, 0x0d, 0xf8, 0x66 }, + { 0xda, 0x58, 0x2a, 0xd8, 0xc5, 0x37, 0x0b, 0x44, 0x69, 0xaf, 0x86, 0x2a, 0xa6, 0x46, 0x7a, 0x22, 0x93, 0xb2, 0xb2, 0x8b, 0xd8, 0x0a, 0xe0, 0xe9, 0x1f, 0x42, 0x5a, 0xd3, 0xd4, 0x72, 0x49, 0xfd, 0xf9, 0x88, 0x25, 0xcc, 0x86, 0xf1, 0x40, 0x28, 0xc3, 0x30, 0x8c, 0x98, 0x04, 0xc7, 0x8b, 0xfe, 0xee, 0xee, 0x46, 0x14, 0x44, 0xce, 0x24, 0x36, 0x87, 0xe1, 0xa5, 0x05, 0x22, 0x45, 0x6a, 0x1d }, + { 0xd5, 0x26, 0x6a, 0xa3, 0x33, 0x11, 0x94, 0xae, 0xf8, 0x52, 0xee, 0xd8, 0x6d, 0x7b, 0x5b, 0x26, 0x33, 0xa0, 0xaf, 0x1c, 0x73, 0x59, 0x06, 0xf2, 0xe1, 0x32, 0x79, 0xf1, 0x49, 0x31, 0xa9, 0xfc, 0x3b, 0x0e, 0xac, 0x5c, 0xe9, 0x24, 0x52, 0x73, 0xbd, 0x1a, 0xa9, 0x29, 0x05, 0xab, 0xe1, 0x62, 0x78, 0xef, 0x7e, 0xfd, 0x47, 0x69, 0x47, 0x89, 0xa7, 0x28, 0x3b, 0x77, 0xda, 0x3c, 0x70, 0xf8 }, + { 0x29, 0x62, 0x73, 0x4c, 0x28, 0x25, 0x21, 0x86, 0xa9, 0xa1, 0x11, 0x1c, 0x73, 0x2a, 0xd4, 0xde, 0x45, 0x06, 0xd4, 0xb4, 0x48, 0x09, 0x16, 0x30, 0x3e, 0xb7, 0x99, 0x1d, 0x65, 0x9c, 0xcd, 0xa0, 0x7a, 0x99, 0x11, 0x91, 0x4b, 0xc7, 0x5c, 0x41, 0x8a, 0xb7, 0xa4, 0x54, 0x17, 0x57, 0xad, 0x05, 0x47, 0x96, 0xe2, 0x67, 0x97, 0xfe, 0xaf, 0x36, 0xe9, 0xf6, 0xad, 0x43, 0xf1, 0x4b, 0x35, 0xa4 }, + { 0xe8, 0xb7, 0x9e, 0xc5, 0xd0, 0x6e, 0x11, 0x1b, 0xdf, 0xaf, 0xd7, 0x1e, 0x9f, 0x57, 0x60, 0xf0, 0x0a, 0xc8, 0xac, 0x5d, 0x8b, 0xf7, 0x68, 0xf9, 0xff, 0x6f, 0x08, 0xb8, 0xf0, 0x26, 0x09, 0x6b, 0x1c, 0xc3, 0xa4, 0xc9, 0x73, 0x33, 0x30, 0x19, 0xf1, 0xe3, 0x55, 0x3e, 0x77, 0xda, 0x3f, 0x98, 0xcb, 0x9f, 0x54, 0x2e, 0x0a, 0x90, 0xe5, 0xf8, 0xa9, 0x40, 0xcc, 0x58, 0xe5, 0x98, 0x44, 0xb3 }, + { 0xdf, 0xb3, 0x20, 0xc4, 0x4f, 0x9d, 0x41, 0xd1, 0xef, 0xdc, 0xc0, 0x15, 0xf0, 0x8d, 0xd5, 0x53, 0x9e, 0x52, 0x6e, 0x39, 0xc8, 0x7d, 0x50, 0x9a, 0xe6, 0x81, 0x2a, 0x96, 0x9e, 0x54, 0x31, 0xbf, 0x4f, 0xa7, 0xd9, 0x1f, 0xfd, 0x03, 0xb9, 0x81, 0xe0, 0xd5, 0x44, 0xcf, 0x72, 0xd7, 0xb1, 0xc0, 0x37, 0x4f, 0x88, 0x01, 0x48, 0x2e, 0x6d, 0xea, 0x2e, 0xf9, 0x03, 0x87, 0x7e, 0xba, 0x67, 0x5e }, + { 0xd8, 0x86, 0x75, 0x11, 0x8f, 0xdb, 0x55, 0xa5, 0xfb, 0x36, 0x5a, 0xc2, 0xaf, 0x1d, 0x21, 0x7b, 0xf5, 0x26, 0xce, 0x1e, 0xe9, 0xc9, 0x4b, 0x2f, 0x00, 0x90, 0xb2, 0xc5, 0x8a, 0x06, 0xca, 0x58, 0x18, 0x7d, 0x7f, 0xe5, 0x7c, 0x7b, 0xed, 0x9d, 0x26, 0xfc, 0xa0, 0x67, 0xb4, 0x11, 0x0e, 0xef, 0xcd, 0x9a, 0x0a, 0x34, 0x5d, 0xe8, 0x72, 0xab, 0xe2, 0x0d, 0xe3, 0x68, 0x00, 0x1b, 0x07, 0x45 }, + { 0xb8, 0x93, 0xf2, 0xfc, 0x41, 0xf7, 0xb0, 0xdd, 0x6e, 0x2f, 0x6a, 0xa2, 0xe0, 0x37, 0x0c, 0x0c, 0xff, 0x7d, 0xf0, 0x9e, 0x3a, 0xcf, 0xcc, 0x0e, 0x92, 0x0b, 0x6e, 0x6f, 0xad, 0x0e, 0xf7, 0x47, 0xc4, 0x06, 0x68, 0x41, 0x7d, 0x34, 0x2b, 0x80, 0xd2, 0x35, 0x1e, 0x8c, 0x17, 0x5f, 0x20, 0x89, 0x7a, 0x06, 0x2e, 0x97, 0x65, 0xe6, 0xc6, 0x7b, 0x53, 0x9b, 0x6b, 0xa8, 0xb9, 0x17, 0x05, 0x45 }, + { 0x6c, 0x67, 0xec, 0x56, 0x97, 0xac, 0xcd, 0x23, 0x5c, 0x59, 0xb4, 0x86, 0xd7, 0xb7, 0x0b, 0xae, 0xed, 0xcb, 0xd4, 0xaa, 0x64, 0xeb, 0xd4, 0xee, 0xf3, 0xc7, 0xea, 0xc1, 0x89, 0x56, 0x1a, 0x72, 0x62, 0x50, 0xae, 0xc4, 0xd4, 0x8c, 0xad, 0xca, 0xfb, 0xbe, 0x2c, 0xe3, 0xc1, 0x6c, 0xe2, 0xd6, 0x91, 0xa8, 0xcc, 0xe0, 0x6e, 0x88, 0x79, 0x55, 0x6d, 0x44, 0x83, 0xed, 0x71, 0x65, 0xc0, 0x63 }, + { 0xf1, 0xaa, 0x2b, 0x04, 0x4f, 0x8f, 0x0c, 0x63, 0x8a, 0x3f, 0x36, 0x2e, 0x67, 0x7b, 0x5d, 0x89, 0x1d, 0x6f, 0xd2, 0xab, 0x07, 0x65, 0xf6, 0xee, 0x1e, 0x49, 0x87, 0xde, 0x05, 0x7e, 0xad, 0x35, 0x78, 0x83, 0xd9, 0xb4, 0x05, 0xb9, 0xd6, 0x09, 0xee, 0xa1, 0xb8, 0x69, 0xd9, 0x7f, 0xb1, 0x6d, 0x9b, 0x51, 0x01, 0x7c, 0x55, 0x3f, 0x3b, 0x93, 0xc0, 0xa1, 0xe0, 0xf1, 0x29, 0x6f, 0xed, 0xcd }, + { 0xcb, 0xaa, 0x25, 0x95, 0x72, 0xd4, 0xae, 0xbf, 0xc1, 0x91, 0x7a, 0xcd, 0xdc, 0x58, 0x2b, 0x9f, 0x8d, 0xfa, 0xa9, 0x28, 0xa1, 0x98, 0xca, 0x7a, 0xcd, 0x0f, 0x2a, 0xa7, 0x6a, 0x13, 0x4a, 0x90, 0x25, 0x2e, 0x62, 0x98, 0xa6, 0x5b, 0x08, 0x18, 0x6a, 0x35, 0x0d, 0x5b, 0x76, 0x26, 0x69, 0x9f, 0x8c, 0xb7, 0x21, 0xa3, 0xea, 0x59, 0x21, 0xb7, 0x53, 0xae, 0x3a, 0x2d, 0xce, 0x24, 0xba, 0x3a }, + { 0xfa, 0x15, 0x49, 0xc9, 0x79, 0x6c, 0xd4, 0xd3, 0x03, 0xdc, 0xf4, 0x52, 0xc1, 0xfb, 0xd5, 0x74, 0x4f, 0xd9, 0xb9, 0xb4, 0x70, 0x03, 0xd9, 0x20, 0xb9, 0x2d, 0xe3, 0x48, 0x39, 0xd0, 0x7e, 0xf2, 0xa2, 0x9d, 0xed, 0x68, 0xf6, 0xfc, 0x9e, 0x6c, 0x45, 0xe0, 0x71, 0xa2, 0xe4, 0x8b, 0xd5, 0x0c, 0x50, 0x84, 0xe9, 0x6b, 0x65, 0x7d, 0xd0, 0x40, 0x40, 0x45, 0xa1, 0xdd, 0xef, 0xe2, 0x82, 0xed }, + { 0x5c, 0xf2, 0xac, 0x89, 0x7a, 0xb4, 0x44, 0xdc, 0xb5, 0xc8, 0xd8, 0x7c, 0x49, 0x5d, 0xbd, 0xb3, 0x4e, 0x18, 0x38, 0xb6, 0xb6, 0x29, 0x42, 0x7c, 0xaa, 0x51, 0x70, 0x2a, 0xd0, 0xf9, 0x68, 0x85, 0x25, 0xf1, 0x3b, 0xec, 0x50, 0x3a, 0x3c, 0x3a, 0x2c, 0x80, 0xa6, 0x5e, 0x0b, 0x57, 0x15, 0xe8, 0xaf, 0xab, 0x00, 0xff, 0xa5, 0x6e, 0xc4, 0x55, 0xa4, 0x9a, 0x1a, 0xd3, 0x0a, 0xa2, 0x4f, 0xcd }, + { 0x9a, 0xaf, 0x80, 0x20, 0x7b, 0xac, 0xe1, 0x7b, 0xb7, 0xab, 0x14, 0x57, 0x57, 0xd5, 0x69, 0x6b, 0xde, 0x32, 0x40, 0x6e, 0xf2, 0x2b, 0x44, 0x29, 0x2e, 0xf6, 0x5d, 0x45, 0x19, 0xc3, 0xbb, 0x2a, 0xd4, 0x1a, 0x59, 0xb6, 0x2c, 0xc3, 0xe9, 0x4b, 0x6f, 0xa9, 0x6d, 0x32, 0xa7, 0xfa, 0xad, 0xae, 0x28, 0xaf, 0x7d, 0x35, 0x09, 0x72, 0x19, 0xaa, 0x3f, 0xd8, 0xcd, 0xa3, 0x1e, 0x40, 0xc2, 0x75 }, + { 0xaf, 0x88, 0xb1, 0x63, 0x40, 0x2c, 0x86, 0x74, 0x5c, 0xb6, 0x50, 0xc2, 0x98, 0x8f, 0xb9, 0x52, 0x11, 0xb9, 0x4b, 0x03, 0xef, 0x29, 0x0e, 0xed, 0x96, 0x62, 0x03, 0x42, 0x41, 0xfd, 0x51, 0xcf, 0x39, 0x8f, 0x80, 0x73, 0xe3, 0x69, 0x35, 0x4c, 0x43, 0xea, 0xe1, 0x05, 0x2f, 0x9b, 0x63, 0xb0, 0x81, 0x91, 0xca, 0xa1, 0x38, 0xaa, 0x54, 0xfe, 0xa8, 0x89, 0xcc, 0x70, 0x24, 0x23, 0x68, 0x97 }, + { 0x48, 0xfa, 0x7d, 0x64, 0xe1, 0xce, 0xee, 0x27, 0xb9, 0x86, 0x4d, 0xb5, 0xad, 0xa4, 0xb5, 0x3d, 0x00, 0xc9, 0xbc, 0x76, 0x26, 0x55, 0x58, 0x13, 0xd3, 0xcd, 0x67, 0x30, 0xab, 0x3c, 0xc0, 0x6f, 0xf3, 0x42, 0xd7, 0x27, 0x90, 0x5e, 0x33, 0x17, 0x1b, 0xde, 0x6e, 0x84, 0x76, 0xe7, 0x7f, 0xb1, 0x72, 0x08, 0x61, 0xe9, 0x4b, 0x73, 0xa2, 0xc5, 0x38, 0xd2, 0x54, 0x74, 0x62, 0x85, 0xf4, 0x30 }, + { 0x0e, 0x6f, 0xd9, 0x7a, 0x85, 0xe9, 0x04, 0xf8, 0x7b, 0xfe, 0x85, 0xbb, 0xeb, 0x34, 0xf6, 0x9e, 0x1f, 0x18, 0x10, 0x5c, 0xf4, 0xed, 0x4f, 0x87, 0xae, 0xc3, 0x6c, 0x6e, 0x8b, 0x5f, 0x68, 0xbd, 0x2a, 0x6f, 0x3d, 0xc8, 0xa9, 0xec, 0xb2, 0xb6, 0x1d, 0xb4, 0xee, 0xdb, 0x6b, 0x2e, 0xa1, 0x0b, 0xf9, 0xcb, 0x02, 0x51, 0xfb, 0x0f, 0x8b, 0x34, 0x4a, 0xbf, 0x7f, 0x36, 0x6b, 0x6d, 0xe5, 0xab }, + { 0x06, 0x62, 0x2d, 0xa5, 0x78, 0x71, 0x76, 0x28, 0x7f, 0xdc, 0x8f, 0xed, 0x44, 0x0b, 0xad, 0x18, 0x7d, 0x83, 0x00, 0x99, 0xc9, 0x4e, 0x6d, 0x04, 0xc8, 0xe9, 0xc9, 0x54, 0xcd, 0xa7, 0x0c, 0x8b, 0xb9, 0xe1, 0xfc, 0x4a, 0x6d, 0x0b, 0xaa, 0x83, 0x1b, 0x9b, 0x78, 0xef, 0x66, 0x48, 0x68, 0x1a, 0x48, 0x67, 0xa1, 0x1d, 0xa9, 0x3e, 0xe3, 0x6e, 0x5e, 0x6a, 0x37, 0xd8, 0x7f, 0xc6, 0x3f, 0x6f }, + { 0x1d, 0xa6, 0x77, 0x2b, 0x58, 0xfa, 0xbf, 0x9c, 0x61, 0xf6, 0x8d, 0x41, 0x2c, 0x82, 0xf1, 0x82, 0xc0, 0x23, 0x6d, 0x7d, 0x57, 0x5e, 0xf0, 0xb5, 0x8d, 0xd2, 0x24, 0x58, 0xd6, 0x43, 0xcd, 0x1d, 0xfc, 0x93, 0xb0, 0x38, 0x71, 0xc3, 0x16, 0xd8, 0x43, 0x0d, 0x31, 0x29, 0x95, 0xd4, 0x19, 0x7f, 0x08, 0x74, 0xc9, 0x91, 0x72, 0xba, 0x00, 0x4a, 0x01, 0xee, 0x29, 0x5a, 0xba, 0xc2, 0x4e, 0x46 }, + { 0x3c, 0xd2, 0xd9, 0x32, 0x0b, 0x7b, 0x1d, 0x5f, 0xb9, 0xaa, 0xb9, 0x51, 0xa7, 0x60, 0x23, 0xfa, 0x66, 0x7b, 0xe1, 0x4a, 0x91, 0x24, 0xe3, 0x94, 0x51, 0x39, 0x18, 0xa3, 0xf4, 0x40, 0x96, 0xae, 0x49, 0x04, 0xba, 0x0f, 0xfc, 0x15, 0x0b, 0x63, 0xbc, 0x7a, 0xb1, 0xee, 0xb9, 0xa6, 0xe2, 0x57, 0xe5, 0xc8, 0xf0, 0x00, 0xa7, 0x03, 0x94, 0xa5, 0xaf, 0xd8, 0x42, 0x71, 0x5d, 0xe1, 0x5f, 0x29 }, + { 0x04, 0xcd, 0xc1, 0x4f, 0x74, 0x34, 0xe0, 0xb4, 0xbe, 0x70, 0xcb, 0x41, 0xdb, 0x4c, 0x77, 0x9a, 0x88, 0xea, 0xef, 0x6a, 0xcc, 0xeb, 0xcb, 0x41, 0xf2, 0xd4, 0x2f, 0xff, 0xe7, 0xf3, 0x2a, 0x8e, 0x28, 0x1b, 0x5c, 0x10, 0x3a, 0x27, 0x02, 0x1d, 0x0d, 0x08, 0x36, 0x22, 0x50, 0x75, 0x3c, 0xdf, 0x70, 0x29, 0x21, 0x95, 0xa5, 0x3a, 0x48, 0x72, 0x8c, 0xeb, 0x58, 0x44, 0xc2, 0xd9, 0x8b, 0xab }, + { 0x90, 0x71, 0xb7, 0xa8, 0xa0, 0x75, 0xd0, 0x09, 0x5b, 0x8f, 0xb3, 0xae, 0x51, 0x13, 0x78, 0x57, 0x35, 0xab, 0x98, 0xe2, 0xb5, 0x2f, 0xaf, 0x91, 0xd5, 0xb8, 0x9e, 0x44, 0xaa, 0xc5, 0xb5, 0xd4, 0xeb, 0xbf, 0x91, 0x22, 0x3b, 0x0f, 0xf4, 0xc7, 0x19, 0x05, 0xda, 0x55, 0x34, 0x2e, 0x64, 0x65, 0x5d, 0x6e, 0xf8, 0xc8, 0x9a, 0x47, 0x68, 0xc3, 0xf9, 0x3a, 0x6d, 0xc0, 0x36, 0x6b, 0x5b, 0xc8 }, + { 0xeb, 0xb3, 0x02, 0x40, 0xdd, 0x96, 0xc7, 0xbc, 0x8d, 0x0a, 0xbe, 0x49, 0xaa, 0x4e, 0xdc, 0xbb, 0x4a, 0xfd, 0xc5, 0x1f, 0xf9, 0xaa, 0xf7, 0x20, 0xd3, 0xf9, 0xe7, 0xfb, 0xb0, 0xf9, 0xc6, 0xd6, 0x57, 0x13, 0x50, 0x50, 0x17, 0x69, 0xfc, 0x4e, 0xbd, 0x0b, 0x21, 0x41, 0x24, 0x7f, 0xf4, 0x00, 0xd4, 0xfd, 0x4b, 0xe4, 0x14, 0xed, 0xf3, 0x77, 0x57, 0xbb, 0x90, 0xa3, 0x2a, 0xc5, 0xc6, 0x5a }, + { 0x85, 0x32, 0xc5, 0x8b, 0xf3, 0xc8, 0x01, 0x5d, 0x9d, 0x1c, 0xbe, 0x00, 0xee, 0xf1, 0xf5, 0x08, 0x2f, 0x8f, 0x36, 0x32, 0xfb, 0xe9, 0xf1, 0xed, 0x4f, 0x9d, 0xfb, 0x1f, 0xa7, 0x9e, 0x82, 0x83, 0x06, 0x6d, 0x77, 0xc4, 0x4c, 0x4a, 0xf9, 0x43, 0xd7, 0x6b, 0x30, 0x03, 0x64, 0xae, 0xcb, 0xd0, 0x64, 0x8c, 0x8a, 0x89, 0x39, 0xbd, 0x20, 0x41, 0x23, 0xf4, 0xb5, 0x62, 0x60, 0x42, 0x2d, 0xec }, + { 0xfe, 0x98, 0x46, 0xd6, 0x4f, 0x7c, 0x77, 0x08, 0x69, 0x6f, 0x84, 0x0e, 0x2d, 0x76, 0xcb, 0x44, 0x08, 0xb6, 0x59, 0x5c, 0x2f, 0x81, 0xec, 0x6a, 0x28, 0xa7, 0xf2, 0xf2, 0x0c, 0xb8, 0x8c, 0xfe, 0x6a, 0xc0, 0xb9, 0xe9, 0xb8, 0x24, 0x4f, 0x08, 0xbd, 0x70, 0x95, 0xc3, 0x50, 0xc1, 0xd0, 0x84, 0x2f, 0x64, 0xfb, 0x01, 0xbb, 0x7f, 0x53, 0x2d, 0xfc, 0xd4, 0x73, 0x71, 0xb0, 0xae, 0xeb, 0x79 }, + { 0x28, 0xf1, 0x7e, 0xa6, 0xfb, 0x6c, 0x42, 0x09, 0x2d, 0xc2, 0x64, 0x25, 0x7e, 0x29, 0x74, 0x63, 0x21, 0xfb, 0x5b, 0xda, 0xea, 0x98, 0x73, 0xc2, 0xa7, 0xfa, 0x9d, 0x8f, 0x53, 0x81, 0x8e, 0x89, 0x9e, 0x16, 0x1b, 0xc7, 0x7d, 0xfe, 0x80, 0x90, 0xaf, 0xd8, 0x2b, 0xf2, 0x26, 0x6c, 0x5c, 0x1b, 0xc9, 0x30, 0xa8, 0xd1, 0x54, 0x76, 0x24, 0x43, 0x9e, 0x66, 0x2e, 0xf6, 0x95, 0xf2, 0x6f, 0x24 }, + { 0xec, 0x6b, 0x7d, 0x7f, 0x03, 0x0d, 0x48, 0x50, 0xac, 0xae, 0x3c, 0xb6, 0x15, 0xc2, 0x1d, 0xd2, 0x52, 0x06, 0xd6, 0x3e, 0x84, 0xd1, 0xdb, 0x8d, 0x95, 0x73, 0x70, 0x73, 0x7b, 0xa0, 0xe9, 0x84, 0x67, 0xea, 0x0c, 0xe2, 0x74, 0xc6, 0x61, 0x99, 0x90, 0x1e, 0xae, 0xc1, 0x8a, 0x08, 0x52, 0x57, 0x15, 0xf5, 0x3b, 0xfd, 0xb0, 0xaa, 0xcb, 0x61, 0x3d, 0x34, 0x2e, 0xbd, 0xce, 0xed, 0xdc, 0x3b }, + { 0xb4, 0x03, 0xd3, 0x69, 0x1c, 0x03, 0xb0, 0xd3, 0x41, 0x8d, 0xf3, 0x27, 0xd5, 0x86, 0x0d, 0x34, 0xbb, 0xfc, 0xc4, 0x51, 0x9b, 0xfb, 0xce, 0x36, 0xbf, 0x33, 0xb2, 0x08, 0x38, 0x5f, 0xad, 0xb9, 0x18, 0x6b, 0xc7, 0x8a, 0x76, 0xc4, 0x89, 0xd8, 0x9f, 0xd5, 0x7e, 0x7d, 0xc7, 0x54, 0x12, 0xd2, 0x3b, 0xcd, 0x1d, 0xae, 0x84, 0x70, 0xce, 0x92, 0x74, 0x75, 0x4b, 0xb8, 0x58, 0x5b, 0x13, 0xc5 }, + { 0x31, 0xfc, 0x79, 0x73, 0x8b, 0x87, 0x72, 0xb3, 0xf5, 0x5c, 0xd8, 0x17, 0x88, 0x13, 0xb3, 0xb5, 0x2d, 0x0d, 0xb5, 0xa4, 0x19, 0xd3, 0x0b, 0xa9, 0x49, 0x5c, 0x4b, 0x9d, 0xa0, 0x21, 0x9f, 0xac, 0x6d, 0xf8, 0xe7, 0xc2, 0x3a, 0x81, 0x15, 0x51, 0xa6, 0x2b, 0x82, 0x7f, 0x25, 0x6e, 0xcd, 0xb8, 0x12, 0x4a, 0xc8, 0xa6, 0x79, 0x2c, 0xcf, 0xec, 0xc3, 0xb3, 0x01, 0x27, 0x22, 0xe9, 0x44, 0x63 }, + { 0xbb, 0x20, 0x39, 0xec, 0x28, 0x70, 0x91, 0xbc, 0xc9, 0x64, 0x2f, 0xc9, 0x00, 0x49, 0xe7, 0x37, 0x32, 0xe0, 0x2e, 0x57, 0x7e, 0x28, 0x62, 0xb3, 0x22, 0x16, 0xae, 0x9b, 0xed, 0xcd, 0x73, 0x0c, 0x4c, 0x28, 0x4e, 0xf3, 0x96, 0x8c, 0x36, 0x8b, 0x7d, 0x37, 0x58, 0x4f, 0x97, 0xbd, 0x4b, 0x4d, 0xc6, 0xef, 0x61, 0x27, 0xac, 0xfe, 0x2e, 0x6a, 0xe2, 0x50, 0x91, 0x24, 0xe6, 0x6c, 0x8a, 0xf4 }, + { 0xf5, 0x3d, 0x68, 0xd1, 0x3f, 0x45, 0xed, 0xfc, 0xb9, 0xbd, 0x41, 0x5e, 0x28, 0x31, 0xe9, 0x38, 0x35, 0x0d, 0x53, 0x80, 0xd3, 0x43, 0x22, 0x78, 0xfc, 0x1c, 0x0c, 0x38, 0x1f, 0xcb, 0x7c, 0x65, 0xc8, 0x2d, 0xaf, 0xe0, 0x51, 0xd8, 0xc8, 0xb0, 0xd4, 0x4e, 0x09, 0x74, 0xa0, 0xe5, 0x9e, 0xc7, 0xbf, 0x7e, 0xd0, 0x45, 0x9f, 0x86, 0xe9, 0x6f, 0x32, 0x9f, 0xc7, 0x97, 0x52, 0x51, 0x0f, 0xd3 }, + { 0x8d, 0x56, 0x8c, 0x79, 0x84, 0xf0, 0xec, 0xdf, 0x76, 0x40, 0xfb, 0xc4, 0x83, 0xb5, 0xd8, 0xc9, 0xf8, 0x66, 0x34, 0xf6, 0xf4, 0x32, 0x91, 0x84, 0x1b, 0x30, 0x9a, 0x35, 0x0a, 0xb9, 0xc1, 0x13, 0x7d, 0x24, 0x06, 0x6b, 0x09, 0xda, 0x99, 0x44, 0xba, 0xc5, 0x4d, 0x5b, 0xb6, 0x58, 0x0d, 0x83, 0x60, 0x47, 0xaa, 0xc7, 0x4a, 0xb7, 0x24, 0xb8, 0x87, 0xeb, 0xf9, 0x3d, 0x4b, 0x32, 0xec, 0xa9 }, + { 0xc0, 0xb6, 0x5c, 0xe5, 0xa9, 0x6f, 0xf7, 0x74, 0xc4, 0x56, 0xca, 0xc3, 0xb5, 0xf2, 0xc4, 0xcd, 0x35, 0x9b, 0x4f, 0xf5, 0x3e, 0xf9, 0x3a, 0x3d, 0xa0, 0x77, 0x8b, 0xe4, 0x90, 0x0d, 0x1e, 0x8d, 0xa1, 0x60, 0x1e, 0x76, 0x9e, 0x8f, 0x1b, 0x02, 0xd2, 0xa2, 0xf8, 0xc5, 0xb9, 0xfa, 0x10, 0xb4, 0x4f, 0x1c, 0x18, 0x69, 0x85, 0x46, 0x8f, 0xee, 0xb0, 0x08, 0x73, 0x02, 0x83, 0xa6, 0x65, 0x7d }, + { 0x49, 0x00, 0xbb, 0xa6, 0xf5, 0xfb, 0x10, 0x3e, 0xce, 0x8e, 0xc9, 0x6a, 0xda, 0x13, 0xa5, 0xc3, 0xc8, 0x54, 0x88, 0xe0, 0x55, 0x51, 0xda, 0x6b, 0x6b, 0x33, 0xd9, 0x88, 0xe6, 0x11, 0xec, 0x0f, 0xe2, 0xe3, 0xc2, 0xaa, 0x48, 0xea, 0x6a, 0xe8, 0x98, 0x6a, 0x3a, 0x23, 0x1b, 0x22, 0x3c, 0x5d, 0x27, 0xce, 0xc2, 0xea, 0xdd, 0xe9, 0x1c, 0xe0, 0x79, 0x81, 0xee, 0x65, 0x28, 0x62, 0xd1, 0xe4 }, + { 0xc7, 0xf5, 0xc3, 0x7c, 0x72, 0x85, 0xf9, 0x27, 0xf7, 0x64, 0x43, 0x41, 0x4d, 0x43, 0x57, 0xff, 0x78, 0x96, 0x47, 0xd7, 0xa0, 0x05, 0xa5, 0xa7, 0x87, 0xe0, 0x3c, 0x34, 0x6b, 0x57, 0xf4, 0x9f, 0x21, 0xb6, 0x4f, 0xa9, 0xcf, 0x4b, 0x7e, 0x45, 0x57, 0x3e, 0x23, 0x04, 0x90, 0x17, 0x56, 0x71, 0x21, 0xa9, 0xc3, 0xd4, 0xb2, 0xb7, 0x3e, 0xc5, 0xe9, 0x41, 0x35, 0x77, 0x52, 0x5d, 0xb4, 0x5a }, + { 0xec, 0x70, 0x96, 0x33, 0x07, 0x36, 0xfd, 0xb2, 0xd6, 0x4b, 0x56, 0x53, 0xe7, 0x47, 0x5d, 0xa7, 0x46, 0xc2, 0x3a, 0x46, 0x13, 0xa8, 0x26, 0x87, 0xa2, 0x80, 0x62, 0xd3, 0x23, 0x63, 0x64, 0x28, 0x4a, 0xc0, 0x17, 0x20, 0xff, 0xb4, 0x06, 0xcf, 0xe2, 0x65, 0xc0, 0xdf, 0x62, 0x6a, 0x18, 0x8c, 0x9e, 0x59, 0x63, 0xac, 0xe5, 0xd3, 0xd5, 0xbb, 0x36, 0x3e, 0x32, 0xc3, 0x8c, 0x21, 0x90, 0xa6 }, + { 0x82, 0xe7, 0x44, 0xc7, 0x5f, 0x46, 0x49, 0xec, 0x52, 0xb8, 0x07, 0x71, 0xa7, 0x7d, 0x47, 0x5a, 0x3b, 0xc0, 0x91, 0x98, 0x95, 0x56, 0x96, 0x0e, 0x27, 0x6a, 0x5f, 0x9e, 0xad, 0x92, 0xa0, 0x3f, 0x71, 0x87, 0x42, 0xcd, 0xcf, 0xea, 0xee, 0x5c, 0xb8, 0x5c, 0x44, 0xaf, 0x19, 0x8a, 0xdc, 0x43, 0xa4, 0xa4, 0x28, 0xf5, 0xf0, 0xc2, 0xdd, 0xb0, 0xbe, 0x36, 0x05, 0x9f, 0x06, 0xd7, 0xdf, 0x73 }, + { 0x28, 0x34, 0xb7, 0xa7, 0x17, 0x0f, 0x1f, 0x5b, 0x68, 0x55, 0x9a, 0xb7, 0x8c, 0x10, 0x50, 0xec, 0x21, 0xc9, 0x19, 0x74, 0x0b, 0x78, 0x4a, 0x90, 0x72, 0xf6, 0xe5, 0xd6, 0x9f, 0x82, 0x8d, 0x70, 0xc9, 0x19, 0xc5, 0x03, 0x9f, 0xb1, 0x48, 0xe3, 0x9e, 0x2c, 0x8a, 0x52, 0x11, 0x83, 0x78, 0xb0, 0x64, 0xca, 0x8d, 0x50, 0x01, 0xcd, 0x10, 0xa5, 0x47, 0x83, 0x87, 0xb9, 0x66, 0x71, 0x5e, 0xd6 }, + { 0x16, 0xb4, 0xad, 0xa8, 0x83, 0xf7, 0x2f, 0x85, 0x3b, 0xb7, 0xef, 0x25, 0x3e, 0xfc, 0xab, 0x0c, 0x3e, 0x21, 0x61, 0x68, 0x7a, 0xd6, 0x15, 0x43, 0xa0, 0xd2, 0x82, 0x4f, 0x91, 0xc1, 0xf8, 0x13, 0x47, 0xd8, 0x6b, 0xe7, 0x09, 0xb1, 0x69, 0x96, 0xe1, 0x7f, 0x2d, 0xd4, 0x86, 0x92, 0x7b, 0x02, 0x88, 0xad, 0x38, 0xd1, 0x30, 0x63, 0xc4, 0xa9, 0x67, 0x2c, 0x39, 0x39, 0x7d, 0x37, 0x89, 0xb6 }, + { 0x78, 0xd0, 0x48, 0xf3, 0xa6, 0x9d, 0x8b, 0x54, 0xae, 0x0e, 0xd6, 0x3a, 0x57, 0x3a, 0xe3, 0x50, 0xd8, 0x9f, 0x7c, 0x6c, 0xf1, 0xf3, 0x68, 0x89, 0x30, 0xde, 0x89, 0x9a, 0xfa, 0x03, 0x76, 0x97, 0x62, 0x9b, 0x31, 0x4e, 0x5c, 0xd3, 0x03, 0xaa, 0x62, 0xfe, 0xea, 0x72, 0xa2, 0x5b, 0xf4, 0x2b, 0x30, 0x4b, 0x6c, 0x6b, 0xcb, 0x27, 0xfa, 0xe2, 0x1c, 0x16, 0xd9, 0x25, 0xe1, 0xfb, 0xda, 0xc3 }, + { 0x0f, 0x74, 0x6a, 0x48, 0x74, 0x92, 0x87, 0xad, 0xa7, 0x7a, 0x82, 0x96, 0x1f, 0x05, 0xa4, 0xda, 0x4a, 0xbd, 0xb7, 0xd7, 0x7b, 0x12, 0x20, 0xf8, 0x36, 0xd0, 0x9e, 0xc8, 0x14, 0x35, 0x9c, 0x0e, 0xc0, 0x23, 0x9b, 0x8c, 0x7b, 0x9f, 0xf9, 0xe0, 0x2f, 0x56, 0x9d, 0x1b, 0x30, 0x1e, 0xf6, 0x7c, 0x46, 0x12, 0xd1, 0xde, 0x4f, 0x73, 0x0f, 0x81, 0xc1, 0x2c, 0x40, 0xcc, 0x06, 0x3c, 0x5c, 0xaa }, + { 0xf0, 0xfc, 0x85, 0x9d, 0x3b, 0xd1, 0x95, 0xfb, 0xdc, 0x2d, 0x59, 0x1e, 0x4c, 0xda, 0xc1, 0x51, 0x79, 0xec, 0x0f, 0x1d, 0xc8, 0x21, 0xc1, 0x1d, 0xf1, 0xf0, 0xc1, 0xd2, 0x6e, 0x62, 0x60, 0xaa, 0xa6, 0x5b, 0x79, 0xfa, 0xfa, 0xca, 0xfd, 0x7d, 0x3a, 0xd6, 0x1e, 0x60, 0x0f, 0x25, 0x09, 0x05, 0xf5, 0x87, 0x8c, 0x87, 0x45, 0x28, 0x97, 0x64, 0x7a, 0x35, 0xb9, 0x95, 0xbc, 0xad, 0xc3, 0xa3 }, + { 0x26, 0x20, 0xf6, 0x87, 0xe8, 0x62, 0x5f, 0x6a, 0x41, 0x24, 0x60, 0xb4, 0x2e, 0x2c, 0xef, 0x67, 0x63, 0x42, 0x08, 0xce, 0x10, 0xa0, 0xcb, 0xd4, 0xdf, 0xf7, 0x04, 0x4a, 0x41, 0xb7, 0x88, 0x00, 0x77, 0xe9, 0xf8, 0xdc, 0x3b, 0x8d, 0x12, 0x16, 0xd3, 0x37, 0x6a, 0x21, 0xe0, 0x15, 0xb5, 0x8f, 0xb2, 0x79, 0xb5, 0x21, 0xd8, 0x3f, 0x93, 0x88, 0xc7, 0x38, 0x2c, 0x85, 0x05, 0x59, 0x0b, 0x9b }, + { 0x22, 0x7e, 0x3a, 0xed, 0x8d, 0x2c, 0xb1, 0x0b, 0x91, 0x8f, 0xcb, 0x04, 0xf9, 0xde, 0x3e, 0x6d, 0x0a, 0x57, 0xe0, 0x84, 0x76, 0xd9, 0x37, 0x59, 0xcd, 0x7b, 0x2e, 0xd5, 0x4a, 0x1c, 0xbf, 0x02, 0x39, 0xc5, 0x28, 0xfb, 0x04, 0xbb, 0xf2, 0x88, 0x25, 0x3e, 0x60, 0x1d, 0x3b, 0xc3, 0x8b, 0x21, 0x79, 0x4a, 0xfe, 0xf9, 0x0b, 0x17, 0x09, 0x4a, 0x18, 0x2c, 0xac, 0x55, 0x77, 0x45, 0xe7, 0x5f }, + { 0x1a, 0x92, 0x99, 0x01, 0xb0, 0x9c, 0x25, 0xf2, 0x7d, 0x6b, 0x35, 0xbe, 0x7b, 0x2f, 0x1c, 0x47, 0x45, 0x13, 0x1f, 0xde, 0xbc, 0xa7, 0xf3, 0xe2, 0x45, 0x19, 0x26, 0x72, 0x04, 0x34, 0xe0, 0xdb, 0x6e, 0x74, 0xfd, 0x69, 0x3a, 0xd2, 0x9b, 0x77, 0x7d, 0xc3, 0x35, 0x5c, 0x59, 0x2a, 0x36, 0x1c, 0x48, 0x73, 0xb0, 0x11, 0x33, 0xa5, 0x7c, 0x2e, 0x3b, 0x70, 0x75, 0xcb, 0xdb, 0x86, 0xf4, 0xfc }, + { 0x5f, 0xd7, 0x96, 0x8b, 0xc2, 0xfe, 0x34, 0xf2, 0x20, 0xb5, 0xe3, 0xdc, 0x5a, 0xf9, 0x57, 0x17, 0x42, 0xd7, 0x3b, 0x7d, 0x60, 0x81, 0x9f, 0x28, 0x88, 0xb6, 0x29, 0x07, 0x2b, 0x96, 0xa9, 0xd8, 0xab, 0x2d, 0x91, 0xb8, 0x2d, 0x0a, 0x9a, 0xab, 0xa6, 0x1b, 0xbd, 0x39, 0x95, 0x81, 0x32, 0xfc, 0xc4, 0x25, 0x70, 0x23, 0xd1, 0xec, 0xa5, 0x91, 0xb3, 0x05, 0x4e, 0x2d, 0xc8, 0x1c, 0x82, 0x00 }, + { 0xdf, 0xcc, 0xe8, 0xcf, 0x32, 0x87, 0x0c, 0xc6, 0xa5, 0x03, 0xea, 0xda, 0xfc, 0x87, 0xfd, 0x6f, 0x78, 0x91, 0x8b, 0x9b, 0x4d, 0x07, 0x37, 0xdb, 0x68, 0x10, 0xbe, 0x99, 0x6b, 0x54, 0x97, 0xe7, 0xe5, 0xcc, 0x80, 0xe3, 0x12, 0xf6, 0x1e, 0x71, 0xff, 0x3e, 0x96, 0x24, 0x43, 0x60, 0x73, 0x15, 0x64, 0x03, 0xf7, 0x35, 0xf5, 0x6b, 0x0b, 0x01, 0x84, 0x5c, 0x18, 0xf6, 0xca, 0xf7, 0x72, 0xe6 }, + { 0x02, 0xf7, 0xef, 0x3a, 0x9c, 0xe0, 0xff, 0xf9, 0x60, 0xf6, 0x70, 0x32, 0xb2, 0x96, 0xef, 0xca, 0x30, 0x61, 0xf4, 0x93, 0x4d, 0x69, 0x07, 0x49, 0xf2, 0xd0, 0x1c, 0x35, 0xc8, 0x1c, 0x14, 0xf3, 0x9a, 0x67, 0xfa, 0x35, 0x0b, 0xc8, 0xa0, 0x35, 0x9b, 0xf1, 0x72, 0x4b, 0xff, 0xc3, 0xbc, 0xa6, 0xd7, 0xc7, 0xbb, 0xa4, 0x79, 0x1f, 0xd5, 0x22, 0xa3, 0xad, 0x35, 0x3c, 0x02, 0xec, 0x5a, 0xa8 }, + { 0x64, 0xbe, 0x5c, 0x6a, 0xba, 0x65, 0xd5, 0x94, 0x84, 0x4a, 0xe7, 0x8b, 0xb0, 0x22, 0xe5, 0xbe, 0xbe, 0x12, 0x7f, 0xd6, 0xb6, 0xff, 0xa5, 0xa1, 0x37, 0x03, 0x85, 0x5a, 0xb6, 0x3b, 0x62, 0x4d, 0xcd, 0x1a, 0x36, 0x3f, 0x99, 0x20, 0x3f, 0x63, 0x2e, 0xc3, 0x86, 0xf3, 0xea, 0x76, 0x7f, 0xc9, 0x92, 0xe8, 0xed, 0x96, 0x86, 0x58, 0x6a, 0xa2, 0x75, 0x55, 0xa8, 0x59, 0x9d, 0x5b, 0x80, 0x8f }, + { 0xf7, 0x85, 0x85, 0x50, 0x5c, 0x4e, 0xaa, 0x54, 0xa8, 0xb5, 0xbe, 0x70, 0xa6, 0x1e, 0x73, 0x5e, 0x0f, 0xf9, 0x7a, 0xf9, 0x44, 0xdd, 0xb3, 0x00, 0x1e, 0x35, 0xd8, 0x6c, 0x4e, 0x21, 0x99, 0xd9, 0x76, 0x10, 0x4b, 0x6a, 0xe3, 0x17, 0x50, 0xa3, 0x6a, 0x72, 0x6e, 0xd2, 0x85, 0x06, 0x4f, 0x59, 0x81, 0xb5, 0x03, 0x88, 0x9f, 0xef, 0x82, 0x2f, 0xcd, 0xc2, 0x89, 0x8d, 0xdd, 0xb7, 0x88, 0x9a }, + { 0xe4, 0xb5, 0x56, 0x60, 0x33, 0x86, 0x95, 0x72, 0xed, 0xfd, 0x87, 0x47, 0x9a, 0x5b, 0xb7, 0x3c, 0x80, 0xe8, 0x75, 0x9b, 0x91, 0x23, 0x28, 0x79, 0xd9, 0x6b, 0x1d, 0xda, 0x36, 0xc0, 0x12, 0x07, 0x6e, 0xe5, 0xa2, 0xed, 0x7a, 0xe2, 0xde, 0x63, 0xef, 0x84, 0x06, 0xa0, 0x6a, 0xea, 0x82, 0xc1, 0x88, 0x03, 0x1b, 0x56, 0x0b, 0xea, 0xfb, 0x58, 0x3f, 0xb3, 0xde, 0x9e, 0x57, 0x95, 0x2a, 0x7e }, + { 0xe1, 0xb3, 0xe7, 0xed, 0x86, 0x7f, 0x6c, 0x94, 0x84, 0xa2, 0xa9, 0x7f, 0x77, 0x15, 0xf2, 0x5e, 0x25, 0x29, 0x4e, 0x99, 0x2e, 0x41, 0xf6, 0xa7, 0xc1, 0x61, 0xff, 0xc2, 0xad, 0xc6, 0xda, 0xae, 0xb7, 0x11, 0x31, 0x02, 0xd5, 0xe6, 0x09, 0x02, 0x87, 0xfe, 0x6a, 0xd9, 0x4c, 0xe5, 0xd6, 0xb7, 0x39, 0xc6, 0xca, 0x24, 0x0b, 0x05, 0xc7, 0x6f, 0xb7, 0x3f, 0x25, 0xdd, 0x02, 0x4b, 0xf9, 0x35 }, + { 0x85, 0xfd, 0x08, 0x5f, 0xdc, 0x12, 0xa0, 0x80, 0x98, 0x3d, 0xf0, 0x7b, 0xd7, 0x01, 0x2b, 0x0d, 0x40, 0x2a, 0x0f, 0x40, 0x43, 0xfc, 0xb2, 0x77, 0x5a, 0xdf, 0x0b, 0xad, 0x17, 0x4f, 0x9b, 0x08, 0xd1, 0x67, 0x6e, 0x47, 0x69, 0x85, 0x78, 0x5c, 0x0a, 0x5d, 0xcc, 0x41, 0xdb, 0xff, 0x6d, 0x95, 0xef, 0x4d, 0x66, 0xa3, 0xfb, 0xdc, 0x4a, 0x74, 0xb8, 0x2b, 0xa5, 0x2d, 0xa0, 0x51, 0x2b, 0x74 }, + { 0xae, 0xd8, 0xfa, 0x76, 0x4b, 0x0f, 0xbf, 0xf8, 0x21, 0xe0, 0x52, 0x33, 0xd2, 0xf7, 0xb0, 0x90, 0x0e, 0xc4, 0x4d, 0x82, 0x6f, 0x95, 0xe9, 0x3c, 0x34, 0x3c, 0x1b, 0xc3, 0xba, 0x5a, 0x24, 0x37, 0x4b, 0x1d, 0x61, 0x6e, 0x7e, 0x7a, 0xba, 0x45, 0x3a, 0x0a, 0xda, 0x5e, 0x4f, 0xab, 0x53, 0x82, 0x40, 0x9e, 0x0d, 0x42, 0xce, 0x9c, 0x2b, 0xc7, 0xfb, 0x39, 0xa9, 0x9c, 0x34, 0x0c, 0x20, 0xf0 }, + { 0x7b, 0xa3, 0xb2, 0xe2, 0x97, 0x23, 0x35, 0x22, 0xee, 0xb3, 0x43, 0xbd, 0x3e, 0xbc, 0xfd, 0x83, 0x5a, 0x04, 0x00, 0x77, 0x35, 0xe8, 0x7f, 0x0c, 0xa3, 0x00, 0xcb, 0xee, 0x6d, 0x41, 0x65, 0x65, 0x16, 0x21, 0x71, 0x58, 0x1e, 0x40, 0x20, 0xff, 0x4c, 0xf1, 0x76, 0x45, 0x0f, 0x12, 0x91, 0xea, 0x22, 0x85, 0xcb, 0x9e, 0xbf, 0xfe, 0x4c, 0x56, 0x66, 0x06, 0x27, 0x68, 0x51, 0x45, 0x05, 0x1c }, + { 0xde, 0x74, 0x8b, 0xcf, 0x89, 0xec, 0x88, 0x08, 0x47, 0x21, 0xe1, 0x6b, 0x85, 0xf3, 0x0a, 0xdb, 0x1a, 0x61, 0x34, 0xd6, 0x64, 0xb5, 0x84, 0x35, 0x69, 0xba, 0xbc, 0x5b, 0xbd, 0x1a, 0x15, 0xca, 0x9b, 0x61, 0x80, 0x3c, 0x90, 0x1a, 0x4f, 0xef, 0x32, 0x96, 0x5a, 0x17, 0x49, 0xc9, 0xf3, 0xa4, 0xe2, 0x43, 0xe1, 0x73, 0x93, 0x9d, 0xc5, 0xa8, 0xdc, 0x49, 0x5c, 0x67, 0x1a, 0xb5, 0x21, 0x45 }, + { 0xaa, 0xf4, 0xd2, 0xbd, 0xf2, 0x00, 0xa9, 0x19, 0x70, 0x6d, 0x98, 0x42, 0xdc, 0xe1, 0x6c, 0x98, 0x14, 0x0d, 0x34, 0xbc, 0x43, 0x3d, 0xf3, 0x20, 0xab, 0xa9, 0xbd, 0x42, 0x9e, 0x54, 0x9a, 0xa7, 0xa3, 0x39, 0x76, 0x52, 0xa4, 0xd7, 0x68, 0x27, 0x77, 0x86, 0xcf, 0x99, 0x3c, 0xde, 0x23, 0x38, 0x67, 0x3e, 0xd2, 0xe6, 0xb6, 0x6c, 0x96, 0x1f, 0xef, 0xb8, 0x2c, 0xd2, 0x0c, 0x93, 0x33, 0x8f }, + { 0xc4, 0x08, 0x21, 0x89, 0x68, 0xb7, 0x88, 0xbf, 0x86, 0x4f, 0x09, 0x97, 0xe6, 0xbc, 0x4c, 0x3d, 0xba, 0x68, 0xb2, 0x76, 0xe2, 0x12, 0x5a, 0x48, 0x43, 0x29, 0x60, 0x52, 0xff, 0x93, 0xbf, 0x57, 0x67, 0xb8, 0xcd, 0xce, 0x71, 0x31, 0xf0, 0x87, 0x64, 0x30, 0xc1, 0x16, 0x5f, 0xec, 0x6c, 0x4f, 0x47, 0xad, 0xaa, 0x4f, 0xd8, 0xbc, 0xfa, 0xce, 0xf4, 0x63, 0xb5, 0xd3, 0xd0, 0xfa, 0x61, 0xa0 }, + { 0x76, 0xd2, 0xd8, 0x19, 0xc9, 0x2b, 0xce, 0x55, 0xfa, 0x8e, 0x09, 0x2a, 0xb1, 0xbf, 0x9b, 0x9e, 0xab, 0x23, 0x7a, 0x25, 0x26, 0x79, 0x86, 0xca, 0xcf, 0x2b, 0x8e, 0xe1, 0x4d, 0x21, 0x4d, 0x73, 0x0d, 0xc9, 0xa5, 0xaa, 0x2d, 0x7b, 0x59, 0x6e, 0x86, 0xa1, 0xfd, 0x8f, 0xa0, 0x80, 0x4c, 0x77, 0x40, 0x2d, 0x2f, 0xcd, 0x45, 0x08, 0x36, 0x88, 0xb2, 0x18, 0xb1, 0xcd, 0xfa, 0x0d, 0xcb, 0xcb }, + { 0x72, 0x06, 0x5e, 0xe4, 0xdd, 0x91, 0xc2, 0xd8, 0x50, 0x9f, 0xa1, 0xfc, 0x28, 0xa3, 0x7c, 0x7f, 0xc9, 0xfa, 0x7d, 0x5b, 0x3f, 0x8a, 0xd3, 0xd0, 0xd7, 0xa2, 0x56, 0x26, 0xb5, 0x7b, 0x1b, 0x44, 0x78, 0x8d, 0x4c, 0xaf, 0x80, 0x62, 0x90, 0x42, 0x5f, 0x98, 0x90, 0xa3, 0xa2, 0xa3, 0x5a, 0x90, 0x5a, 0xb4, 0xb3, 0x7a, 0xcf, 0xd0, 0xda, 0x6e, 0x45, 0x17, 0xb2, 0x52, 0x5c, 0x96, 0x51, 0xe4 }, + { 0x64, 0x47, 0x5d, 0xfe, 0x76, 0x00, 0xd7, 0x17, 0x1b, 0xea, 0x0b, 0x39, 0x4e, 0x27, 0xc9, 0xb0, 0x0d, 0x8e, 0x74, 0xdd, 0x1e, 0x41, 0x6a, 0x79, 0x47, 0x36, 0x82, 0xad, 0x3d, 0xfd, 0xbb, 0x70, 0x66, 0x31, 0x55, 0x80, 0x55, 0xcf, 0xc8, 0xa4, 0x0e, 0x07, 0xbd, 0x01, 0x5a, 0x45, 0x40, 0xdc, 0xde, 0xa1, 0x58, 0x83, 0xcb, 0xbf, 0x31, 0x41, 0x2d, 0xf1, 0xde, 0x1c, 0xd4, 0x15, 0x2b, 0x91 }, + { 0x12, 0xcd, 0x16, 0x74, 0xa4, 0x48, 0x8a, 0x5d, 0x7c, 0x2b, 0x31, 0x60, 0xd2, 0xe2, 0xc4, 0xb5, 0x83, 0x71, 0xbe, 0xda, 0xd7, 0x93, 0x41, 0x8d, 0x6f, 0x19, 0xc6, 0xee, 0x38, 0x5d, 0x70, 0xb3, 0xe0, 0x67, 0x39, 0x36, 0x9d, 0x4d, 0xf9, 0x10, 0xed, 0xb0, 0xb0, 0xa5, 0x4c, 0xbf, 0xf4, 0x3d, 0x54, 0x54, 0x4c, 0xd3, 0x7a, 0xb3, 0xa0, 0x6c, 0xfa, 0x0a, 0x3d, 0xda, 0xc8, 0xb6, 0x6c, 0x89 }, + { 0x60, 0x75, 0x69, 0x66, 0x47, 0x9d, 0xed, 0xc6, 0xdd, 0x4b, 0xcf, 0xf8, 0xea, 0x7d, 0x1d, 0x4c, 0xe4, 0xd4, 0xaf, 0x2e, 0x7b, 0x09, 0x7e, 0x32, 0xe3, 0x76, 0x35, 0x18, 0x44, 0x11, 0x47, 0xcc, 0x12, 0xb3, 0xc0, 0xee, 0x6d, 0x2e, 0xca, 0xbf, 0x11, 0x98, 0xce, 0xc9, 0x2e, 0x86, 0xa3, 0x61, 0x6f, 0xba, 0x4f, 0x4e, 0x87, 0x2f, 0x58, 0x25, 0x33, 0x0a, 0xdb, 0xb4, 0xc1, 0xde, 0xe4, 0x44 }, + { 0xa7, 0x80, 0x3b, 0xcb, 0x71, 0xbc, 0x1d, 0x0f, 0x43, 0x83, 0xdd, 0xe1, 0xe0, 0x61, 0x2e, 0x04, 0xf8, 0x72, 0xb7, 0x15, 0xad, 0x30, 0x81, 0x5c, 0x22, 0x49, 0xcf, 0x34, 0xab, 0xb8, 0xb0, 0x24, 0x91, 0x5c, 0xb2, 0xfc, 0x9f, 0x4e, 0x7c, 0xc4, 0xc8, 0xcf, 0xd4, 0x5b, 0xe2, 0xd5, 0xa9, 0x1e, 0xab, 0x09, 0x41, 0xc7, 0xd2, 0x70, 0xe2, 0xda, 0x4c, 0xa4, 0xa9, 0xf7, 0xac, 0x68, 0x66, 0x3a }, + { 0xb8, 0x4e, 0xf6, 0xa7, 0x22, 0x9a, 0x34, 0xa7, 0x50, 0xd9, 0xa9, 0x8e, 0xe2, 0x52, 0x98, 0x71, 0x81, 0x6b, 0x87, 0xfb, 0xe3, 0xbc, 0x45, 0xb4, 0x5f, 0xa5, 0xae, 0x82, 0xd5, 0x14, 0x15, 0x40, 0x21, 0x11, 0x65, 0xc3, 0xc5, 0xd7, 0xa7, 0x47, 0x6b, 0xa5, 0xa4, 0xaa, 0x06, 0xd6, 0x64, 0x76, 0xf0, 0xd9, 0xdc, 0x49, 0xa3, 0xf1, 0xee, 0x72, 0xc3, 0xac, 0xab, 0xd4, 0x98, 0x96, 0x74, 0x14 }, + { 0xfa, 0xe4, 0xb6, 0xd8, 0xef, 0xc3, 0xf8, 0xc8, 0xe6, 0x4d, 0x00, 0x1d, 0xab, 0xec, 0x3a, 0x21, 0xf5, 0x44, 0xe8, 0x27, 0x14, 0x74, 0x52, 0x51, 0xb2, 0xb4, 0xb3, 0x93, 0xf2, 0xf4, 0x3e, 0x0d, 0xa3, 0xd4, 0x03, 0xc6, 0x4d, 0xb9, 0x5a, 0x2c, 0xb6, 0xe2, 0x3e, 0xbb, 0x7b, 0x9e, 0x94, 0xcd, 0xd5, 0xdd, 0xac, 0x54, 0xf0, 0x7c, 0x4a, 0x61, 0xbd, 0x3c, 0xb1, 0x0a, 0xa6, 0xf9, 0x3b, 0x49 }, + { 0x34, 0xf7, 0x28, 0x66, 0x05, 0xa1, 0x22, 0x36, 0x95, 0x40, 0x14, 0x1d, 0xed, 0x79, 0xb8, 0x95, 0x72, 0x55, 0xda, 0x2d, 0x41, 0x55, 0xab, 0xbf, 0x5a, 0x8d, 0xbb, 0x89, 0xc8, 0xeb, 0x7e, 0xde, 0x8e, 0xee, 0xf1, 0xda, 0xa4, 0x6d, 0xc2, 0x9d, 0x75, 0x1d, 0x04, 0x5d, 0xc3, 0xb1, 0xd6, 0x58, 0xbb, 0x64, 0xb8, 0x0f, 0xf8, 0x58, 0x9e, 0xdd, 0xb3, 0x82, 0x4b, 0x13, 0xda, 0x23, 0x5a, 0x6b }, + { 0x3b, 0x3b, 0x48, 0x43, 0x4b, 0xe2, 0x7b, 0x9e, 0xab, 0xab, 0xba, 0x43, 0xbf, 0x6b, 0x35, 0xf1, 0x4b, 0x30, 0xf6, 0xa8, 0x8d, 0xc2, 0xe7, 0x50, 0xc3, 0x58, 0x47, 0x0d, 0x6b, 0x3a, 0xa3, 0xc1, 0x8e, 0x47, 0xdb, 0x40, 0x17, 0xfa, 0x55, 0x10, 0x6d, 0x82, 0x52, 0xf0, 0x16, 0x37, 0x1a, 0x00, 0xf5, 0xf8, 0xb0, 0x70, 0xb7, 0x4b, 0xa5, 0xf2, 0x3c, 0xff, 0xc5, 0x51, 0x1c, 0x9f, 0x09, 0xf0 }, + { 0xba, 0x28, 0x9e, 0xbd, 0x65, 0x62, 0xc4, 0x8c, 0x3e, 0x10, 0xa8, 0xad, 0x6c, 0xe0, 0x2e, 0x73, 0x43, 0x3d, 0x1e, 0x93, 0xd7, 0xc9, 0x27, 0x9d, 0x4d, 0x60, 0xa7, 0xe8, 0x79, 0xee, 0x11, 0xf4, 0x41, 0xa0, 0x00, 0xf4, 0x8e, 0xd9, 0xf7, 0xc4, 0xed, 0x87, 0xa4, 0x51, 0x36, 0xd7, 0xdc, 0xcd, 0xca, 0x48, 0x21, 0x09, 0xc7, 0x8a, 0x51, 0x06, 0x2b, 0x3b, 0xa4, 0x04, 0x4a, 0xda, 0x24, 0x69 }, + { 0x02, 0x29, 0x39, 0xe2, 0x38, 0x6c, 0x5a, 0x37, 0x04, 0x98, 0x56, 0xc8, 0x50, 0xa2, 0xbb, 0x10, 0xa1, 0x3d, 0xfe, 0xa4, 0x21, 0x2b, 0x4c, 0x73, 0x2a, 0x88, 0x40, 0xa9, 0xff, 0xa5, 0xfa, 0xf5, 0x48, 0x75, 0xc5, 0x44, 0x88, 0x16, 0xb2, 0x78, 0x5a, 0x00, 0x7d, 0xa8, 0xa8, 0xd2, 0xbc, 0x7d, 0x71, 0xa5, 0x4e, 0x4e, 0x65, 0x71, 0xf1, 0x0b, 0x60, 0x0c, 0xbd, 0xb2, 0x5d, 0x13, 0xed, 0xe3 }, + { 0xe6, 0xfe, 0xc1, 0x9d, 0x89, 0xce, 0x87, 0x17, 0xb1, 0xa0, 0x87, 0x02, 0x46, 0x70, 0xfe, 0x02, 0x6f, 0x6c, 0x7c, 0xbd, 0xa1, 0x1c, 0xae, 0xf9, 0x59, 0xbb, 0x2d, 0x35, 0x1b, 0xf8, 0x56, 0xf8, 0x05, 0x5d, 0x1c, 0x0e, 0xbd, 0xaa, 0xa9, 0xd1, 0xb1, 0x78, 0x86, 0xfc, 0x2c, 0x56, 0x2b, 0x5e, 0x99, 0x64, 0x2f, 0xc0, 0x64, 0x71, 0x0c, 0x0d, 0x34, 0x88, 0xa0, 0x2b, 0x5e, 0xd7, 0xf6, 0xfd }, + { 0x94, 0xc9, 0x6f, 0x02, 0xa8, 0xf5, 0x76, 0xac, 0xa3, 0x2b, 0xa6, 0x1c, 0x2b, 0x20, 0x6f, 0x90, 0x72, 0x85, 0xd9, 0x29, 0x9b, 0x83, 0xac, 0x17, 0x5c, 0x20, 0x9a, 0x8d, 0x43, 0xd5, 0x3b, 0xfe, 0x68, 0x3d, 0xd1, 0xd8, 0x3e, 0x75, 0x49, 0xcb, 0x90, 0x6c, 0x28, 0xf5, 0x9a, 0xb7, 0xc4, 0x6f, 0x87, 0x51, 0x36, 0x6a, 0x28, 0xc3, 0x9d, 0xd5, 0xfe, 0x26, 0x93, 0xc9, 0x01, 0x96, 0x66, 0xc8 }, + { 0x31, 0xa0, 0xcd, 0x21, 0x5e, 0xbd, 0x2c, 0xb6, 0x1d, 0xe5, 0xb9, 0xed, 0xc9, 0x1e, 0x61, 0x95, 0xe3, 0x1c, 0x59, 0xa5, 0x64, 0x8d, 0x5c, 0x9f, 0x73, 0x7e, 0x12, 0x5b, 0x26, 0x05, 0x70, 0x8f, 0x2e, 0x32, 0x5a, 0xb3, 0x38, 0x1c, 0x8d, 0xce, 0x1a, 0x3e, 0x95, 0x88, 0x86, 0xf1, 0xec, 0xdc, 0x60, 0x31, 0x8f, 0x88, 0x2c, 0xfe, 0x20, 0xa2, 0x41, 0x91, 0x35, 0x2e, 0x61, 0x7b, 0x0f, 0x21 }, + { 0x91, 0xab, 0x50, 0x4a, 0x52, 0x2d, 0xce, 0x78, 0x77, 0x9f, 0x4c, 0x6c, 0x6b, 0xa2, 0xe6, 0xb6, 0xdb, 0x55, 0x65, 0xc7, 0x6d, 0x3e, 0x7e, 0x7c, 0x92, 0x0c, 0xaf, 0x7f, 0x75, 0x7e, 0xf9, 0xdb, 0x7c, 0x8f, 0xcf, 0x10, 0xe5, 0x7f, 0x03, 0x37, 0x9e, 0xa9, 0xbf, 0x75, 0xeb, 0x59, 0x89, 0x5d, 0x96, 0xe1, 0x49, 0x80, 0x0b, 0x6a, 0xae, 0x01, 0xdb, 0x77, 0x8b, 0xb9, 0x0a, 0xfb, 0xc9, 0x89 }, + { 0xd8, 0x5c, 0xab, 0xc6, 0xbd, 0x5b, 0x1a, 0x01, 0xa5, 0xaf, 0xd8, 0xc6, 0x73, 0x47, 0x40, 0xda, 0x9f, 0xd1, 0xc1, 0xac, 0xc6, 0xdb, 0x29, 0xbf, 0xc8, 0xa2, 0xe5, 0xb6, 0x68, 0xb0, 0x28, 0xb6, 0xb3, 0x15, 0x4b, 0xfb, 0x87, 0x03, 0xfa, 0x31, 0x80, 0x25, 0x1d, 0x58, 0x9a, 0xd3, 0x80, 0x40, 0xce, 0xb7, 0x07, 0xc4, 0xba, 0xd1, 0xb5, 0x34, 0x3c, 0xb4, 0x26, 0xb6, 0x1e, 0xaa, 0x49, 0xc1 }, + { 0xd6, 0x2e, 0xfb, 0xec, 0x2c, 0xa9, 0xc1, 0xf8, 0xbd, 0x66, 0xce, 0x8b, 0x3f, 0x6a, 0x89, 0x8c, 0xb3, 0xf7, 0x56, 0x6b, 0xa6, 0x56, 0x8c, 0x61, 0x8a, 0xd1, 0xfe, 0xb2, 0xb6, 0x5b, 0x76, 0xc3, 0xce, 0x1d, 0xd2, 0x0f, 0x73, 0x95, 0x37, 0x2f, 0xaf, 0x28, 0x42, 0x7f, 0x61, 0xc9, 0x27, 0x80, 0x49, 0xcf, 0x01, 0x40, 0xdf, 0x43, 0x4f, 0x56, 0x33, 0x04, 0x8c, 0x86, 0xb8, 0x1e, 0x03, 0x99 }, + { 0x7c, 0x8f, 0xdc, 0x61, 0x75, 0x43, 0x9e, 0x2c, 0x3d, 0xb1, 0x5b, 0xaf, 0xa7, 0xfb, 0x06, 0x14, 0x3a, 0x6a, 0x23, 0xbc, 0x90, 0xf4, 0x49, 0xe7, 0x9d, 0xee, 0xf7, 0x3c, 0x3d, 0x49, 0x2a, 0x67, 0x17, 0x15, 0xc1, 0x93, 0xb6, 0xfe, 0xa9, 0xf0, 0x36, 0x05, 0x0b, 0x94, 0x60, 0x69, 0x85, 0x6b, 0x89, 0x7e, 0x08, 0xc0, 0x07, 0x68, 0xf5, 0xee, 0x5d, 0xdc, 0xf7, 0x0b, 0x7c, 0xd6, 0xd0, 0xe0 }, + { 0x58, 0x60, 0x2e, 0xe7, 0x46, 0x8e, 0x6b, 0xc9, 0xdf, 0x21, 0xbd, 0x51, 0xb2, 0x3c, 0x00, 0x5f, 0x72, 0xd6, 0xcb, 0x01, 0x3f, 0x0a, 0x1b, 0x48, 0xcb, 0xec, 0x5e, 0xca, 0x29, 0x92, 0x99, 0xf9, 0x7f, 0x09, 0xf5, 0x4a, 0x9a, 0x01, 0x48, 0x3e, 0xae, 0xb3, 0x15, 0xa6, 0x47, 0x8b, 0xad, 0x37, 0xba, 0x47, 0xca, 0x13, 0x47, 0xc7, 0xc8, 0xfc, 0x9e, 0x66, 0x95, 0x59, 0x2c, 0x91, 0xd7, 0x23 }, + { 0x27, 0xf5, 0xb7, 0x9e, 0xd2, 0x56, 0xb0, 0x50, 0x99, 0x3d, 0x79, 0x34, 0x96, 0xed, 0xf4, 0x80, 0x7c, 0x1d, 0x85, 0xa7, 0xb0, 0xa6, 0x7c, 0x9c, 0x4f, 0xa9, 0x98, 0x60, 0x75, 0x0b, 0x0a, 0xe6, 0x69, 0x89, 0x67, 0x0a, 0x8f, 0xfd, 0x78, 0x56, 0xd7, 0xce, 0x41, 0x15, 0x99, 0xe5, 0x8c, 0x4d, 0x77, 0xb2, 0x32, 0xa6, 0x2b, 0xef, 0x64, 0xd1, 0x52, 0x75, 0xbe, 0x46, 0xa6, 0x82, 0x35, 0xff }, + { 0x39, 0x57, 0xa9, 0x76, 0xb9, 0xf1, 0x88, 0x7b, 0xf0, 0x04, 0xa8, 0xdc, 0xa9, 0x42, 0xc9, 0x2d, 0x2b, 0x37, 0xea, 0x52, 0x60, 0x0f, 0x25, 0xe0, 0xc9, 0xbc, 0x57, 0x07, 0xd0, 0x27, 0x9c, 0x00, 0xc6, 0xe8, 0x5a, 0x83, 0x9b, 0x0d, 0x2d, 0x8e, 0xb5, 0x9c, 0x51, 0xd9, 0x47, 0x88, 0xeb, 0xe6, 0x24, 0x74, 0xa7, 0x91, 0xca, 0xdf, 0x52, 0xcc, 0xcf, 0x20, 0xf5, 0x07, 0x0b, 0x65, 0x73, 0xfc }, + { 0xea, 0xa2, 0x37, 0x6d, 0x55, 0x38, 0x0b, 0xf7, 0x72, 0xec, 0xca, 0x9c, 0xb0, 0xaa, 0x46, 0x68, 0xc9, 0x5c, 0x70, 0x71, 0x62, 0xfa, 0x86, 0xd5, 0x18, 0xc8, 0xce, 0x0c, 0xa9, 0xbf, 0x73, 0x62, 0xb9, 0xf2, 0xa0, 0xad, 0xc3, 0xff, 0x59, 0x92, 0x2d, 0xf9, 0x21, 0xb9, 0x45, 0x67, 0xe8, 0x1e, 0x45, 0x2f, 0x6c, 0x1a, 0x07, 0xfc, 0x81, 0x7c, 0xeb, 0xe9, 0x96, 0x04, 0xb3, 0x50, 0x5d, 0x38 }, + { 0xc1, 0xe2, 0xc7, 0x8b, 0x6b, 0x27, 0x34, 0xe2, 0x48, 0x0e, 0xc5, 0x50, 0x43, 0x4c, 0xb5, 0xd6, 0x13, 0x11, 0x1a, 0xdc, 0xc2, 0x1d, 0x47, 0x55, 0x45, 0xc3, 0xb1, 0xb7, 0xe6, 0xff, 0x12, 0x44, 0x44, 0x76, 0xe5, 0xc0, 0x55, 0x13, 0x2e, 0x22, 0x29, 0xdc, 0x0f, 0x80, 0x70, 0x44, 0xbb, 0x91, 0x9b, 0x1a, 0x56, 0x62, 0xdd, 0x38, 0xa9, 0xee, 0x65, 0xe2, 0x43, 0xa3, 0x91, 0x1a, 0xed, 0x1a }, + { 0x8a, 0xb4, 0x87, 0x13, 0x38, 0x9d, 0xd0, 0xfc, 0xf9, 0xf9, 0x65, 0xd3, 0xce, 0x66, 0xb1, 0xe5, 0x59, 0xa1, 0xf8, 0xc5, 0x87, 0x41, 0xd6, 0x76, 0x83, 0xcd, 0x97, 0x13, 0x54, 0xf4, 0x52, 0xe6, 0x2d, 0x02, 0x07, 0xa6, 0x5e, 0x43, 0x6c, 0x5d, 0x5d, 0x8f, 0x8e, 0xe7, 0x1c, 0x6a, 0xbf, 0xe5, 0x0e, 0x66, 0x90, 0x04, 0xc3, 0x02, 0xb3, 0x1a, 0x7e, 0xa8, 0x31, 0x1d, 0x4a, 0x91, 0x60, 0x51 }, + { 0x24, 0xce, 0x0a, 0xdd, 0xaa, 0x4c, 0x65, 0x03, 0x8b, 0xd1, 0xb1, 0xc0, 0xf1, 0x45, 0x2a, 0x0b, 0x12, 0x87, 0x77, 0xaa, 0xbc, 0x94, 0xa2, 0x9d, 0xf2, 0xfd, 0x6c, 0x7e, 0x2f, 0x85, 0xf8, 0xab, 0x9a, 0xc7, 0xef, 0xf5, 0x16, 0xb0, 0xe0, 0xa8, 0x25, 0xc8, 0x4a, 0x24, 0xcf, 0xe4, 0x92, 0xea, 0xad, 0x0a, 0x63, 0x08, 0xe4, 0x6d, 0xd4, 0x2f, 0xe8, 0x33, 0x3a, 0xb9, 0x71, 0xbb, 0x30, 0xca }, + { 0x51, 0x54, 0xf9, 0x29, 0xee, 0x03, 0x04, 0x5b, 0x6b, 0x0c, 0x00, 0x04, 0xfa, 0x77, 0x8e, 0xde, 0xe1, 0xd1, 0x39, 0x89, 0x32, 0x67, 0xcc, 0x84, 0x82, 0x5a, 0xd7, 0xb3, 0x6c, 0x63, 0xde, 0x32, 0x79, 0x8e, 0x4a, 0x16, 0x6d, 0x24, 0x68, 0x65, 0x61, 0x35, 0x4f, 0x63, 0xb0, 0x07, 0x09, 0xa1, 0x36, 0x4b, 0x3c, 0x24, 0x1d, 0xe3, 0xfe, 0xbf, 0x07, 0x54, 0x04, 0x58, 0x97, 0x46, 0x7c, 0xd4 }, + { 0xe7, 0x4e, 0x90, 0x79, 0x20, 0xfd, 0x87, 0xbd, 0x5a, 0xd6, 0x36, 0xdd, 0x11, 0x08, 0x5e, 0x50, 0xee, 0x70, 0x45, 0x9c, 0x44, 0x3e, 0x1c, 0xe5, 0x80, 0x9a, 0xf2, 0xbc, 0x2e, 0xba, 0x39, 0xf9, 0xe6, 0xd7, 0x12, 0x8e, 0x0e, 0x37, 0x12, 0xc3, 0x16, 0xda, 0x06, 0xf4, 0x70, 0x5d, 0x78, 0xa4, 0x83, 0x8e, 0x28, 0x12, 0x1d, 0x43, 0x44, 0xa2, 0xc7, 0x9c, 0x5e, 0x0d, 0xb3, 0x07, 0xa6, 0x77 }, + { 0xbf, 0x91, 0xa2, 0x23, 0x34, 0xba, 0xc2, 0x0f, 0x3f, 0xd8, 0x06, 0x63, 0xb3, 0xcd, 0x06, 0xc4, 0xe8, 0x80, 0x2f, 0x30, 0xe6, 0xb5, 0x9f, 0x90, 0xd3, 0x03, 0x5c, 0xc9, 0x79, 0x8a, 0x21, 0x7e, 0xd5, 0xa3, 0x1a, 0xbb, 0xda, 0x7f, 0xa6, 0x84, 0x28, 0x27, 0xbd, 0xf2, 0xa7, 0xa1, 0xc2, 0x1f, 0x6f, 0xcf, 0xcc, 0xbb, 0x54, 0xc6, 0xc5, 0x29, 0x26, 0xf3, 0x2d, 0xa8, 0x16, 0x26, 0x9b, 0xe1 }, + { 0xd9, 0xd5, 0xc7, 0x4b, 0xe5, 0x12, 0x1b, 0x0b, 0xd7, 0x42, 0xf2, 0x6b, 0xff, 0xb8, 0xc8, 0x9f, 0x89, 0x17, 0x1f, 0x3f, 0x93, 0x49, 0x13, 0x49, 0x2b, 0x09, 0x03, 0xc2, 0x71, 0xbb, 0xe2, 0xb3, 0x39, 0x5e, 0xf2, 0x59, 0x66, 0x9b, 0xef, 0x43, 0xb5, 0x7f, 0x7f, 0xcc, 0x30, 0x27, 0xdb, 0x01, 0x82, 0x3f, 0x6b, 0xae, 0xe6, 0x6e, 0x4f, 0x9f, 0xea, 0xd4, 0xd6, 0x72, 0x6c, 0x74, 0x1f, 0xce }, + { 0x50, 0xc8, 0xb8, 0xcf, 0x34, 0xcd, 0x87, 0x9f, 0x80, 0xe2, 0xfa, 0xab, 0x32, 0x30, 0xb0, 0xc0, 0xe1, 0xcc, 0x3e, 0x9d, 0xca, 0xde, 0xb1, 0xb9, 0xd9, 0x7a, 0xb9, 0x23, 0x41, 0x5d, 0xd9, 0xa1, 0xfe, 0x38, 0xad, 0xdd, 0x5c, 0x11, 0x75, 0x6c, 0x67, 0x99, 0x0b, 0x25, 0x6e, 0x95, 0xad, 0x6d, 0x8f, 0x9f, 0xed, 0xce, 0x10, 0xbf, 0x1c, 0x90, 0x67, 0x9c, 0xde, 0x0e, 0xcf, 0x1b, 0xe3, 0x47 }, + { 0x0a, 0x38, 0x6e, 0x7c, 0xd5, 0xdd, 0x9b, 0x77, 0xa0, 0x35, 0xe0, 0x9f, 0xe6, 0xfe, 0xe2, 0xc8, 0xce, 0x61, 0xb5, 0x38, 0x3c, 0x87, 0xea, 0x43, 0x20, 0x50, 0x59, 0xc5, 0xe4, 0xcd, 0x4f, 0x44, 0x08, 0x31, 0x9b, 0xb0, 0xa8, 0x23, 0x60, 0xf6, 0xa5, 0x8e, 0x6c, 0x9c, 0xe3, 0xf4, 0x87, 0xc4, 0x46, 0x06, 0x3b, 0xf8, 0x13, 0xbc, 0x6b, 0xa5, 0x35, 0xe1, 0x7f, 0xc1, 0x82, 0x6c, 0xfc, 0x91 }, + { 0x1f, 0x14, 0x59, 0xcb, 0x6b, 0x61, 0xcb, 0xac, 0x5f, 0x0e, 0xfe, 0x8f, 0xc4, 0x87, 0x53, 0x8f, 0x42, 0x54, 0x89, 0x87, 0xfc, 0xd5, 0x62, 0x21, 0xcf, 0xa7, 0xbe, 0xb2, 0x25, 0x04, 0x76, 0x9e, 0x79, 0x2c, 0x45, 0xad, 0xfb, 0x1d, 0x6b, 0x3d, 0x60, 0xd7, 0xb7, 0x49, 0xc8, 0xa7, 0x5b, 0x0b, 0xdf, 0x14, 0xe8, 0xea, 0x72, 0x1b, 0x95, 0xdc, 0xa5, 0x38, 0xca, 0x6e, 0x25, 0x71, 0x12, 0x09 }, + { 0xe5, 0x8b, 0x38, 0x36, 0xb7, 0xd8, 0xfe, 0xdb, 0xb5, 0x0c, 0xa5, 0x72, 0x5c, 0x65, 0x71, 0xe7, 0x4c, 0x07, 0x85, 0xe9, 0x78, 0x21, 0xda, 0xb8, 0xb6, 0x29, 0x8c, 0x10, 0xe4, 0xc0, 0x79, 0xd4, 0xa6, 0xcd, 0xf2, 0x2f, 0x0f, 0xed, 0xb5, 0x50, 0x32, 0x92, 0x5c, 0x16, 0x74, 0x81, 0x15, 0xf0, 0x1a, 0x10, 0x5e, 0x77, 0xe0, 0x0c, 0xee, 0x3d, 0x07, 0x92, 0x4d, 0xc0, 0xd8, 0xf9, 0x06, 0x59 }, + { 0xb9, 0x29, 0xcc, 0x65, 0x05, 0xf0, 0x20, 0x15, 0x86, 0x72, 0xde, 0xda, 0x56, 0xd0, 0xdb, 0x08, 0x1a, 0x2e, 0xe3, 0x4c, 0x00, 0xc1, 0x10, 0x00, 0x29, 0xbd, 0xf8, 0xea, 0x98, 0x03, 0x4f, 0xa4, 0xbf, 0x3e, 0x86, 0x55, 0xec, 0x69, 0x7f, 0xe3, 0x6f, 0x40, 0x55, 0x3c, 0x5b, 0xb4, 0x68, 0x01, 0x64, 0x4a, 0x62, 0x7d, 0x33, 0x42, 0xf4, 0xfc, 0x92, 0xb6, 0x1f, 0x03, 0x29, 0x0f, 0xb3, 0x81 }, + { 0x72, 0xd3, 0x53, 0x99, 0x4b, 0x49, 0xd3, 0xe0, 0x31, 0x53, 0x92, 0x9a, 0x1e, 0x4d, 0x4f, 0x18, 0x8e, 0xe5, 0x8a, 0xb9, 0xe7, 0x2e, 0xe8, 0xe5, 0x12, 0xf2, 0x9b, 0xc7, 0x73, 0x91, 0x38, 0x19, 0xce, 0x05, 0x7d, 0xdd, 0x70, 0x02, 0xc0, 0x43, 0x3e, 0xe0, 0xa1, 0x61, 0x14, 0xe3, 0xd1, 0x56, 0xdd, 0x2c, 0x4a, 0x7e, 0x80, 0xee, 0x53, 0x37, 0x8b, 0x86, 0x70, 0xf2, 0x3e, 0x33, 0xef, 0x56 }, + { 0xc7, 0x0e, 0xf9, 0xbf, 0xd7, 0x75, 0xd4, 0x08, 0x17, 0x67, 0x37, 0xa0, 0x73, 0x6d, 0x68, 0x51, 0x7c, 0xe1, 0xaa, 0xad, 0x7e, 0x81, 0xa9, 0x3c, 0x8c, 0x1e, 0xd9, 0x67, 0xea, 0x21, 0x4f, 0x56, 0xc8, 0xa3, 0x77, 0xb1, 0x76, 0x3e, 0x67, 0x66, 0x15, 0xb6, 0x0f, 0x39, 0x88, 0x24, 0x1e, 0xae, 0x6e, 0xab, 0x96, 0x85, 0xa5, 0x12, 0x49, 0x29, 0xd2, 0x81, 0x88, 0xf2, 0x9e, 0xab, 0x06, 0xf7 }, + { 0xc2, 0x30, 0xf0, 0x80, 0x26, 0x79, 0xcb, 0x33, 0x82, 0x2e, 0xf8, 0xb3, 0xb2, 0x1b, 0xf7, 0xa9, 0xa2, 0x89, 0x42, 0x09, 0x29, 0x01, 0xd7, 0xda, 0xc3, 0x76, 0x03, 0x00, 0x83, 0x10, 0x26, 0xcf, 0x35, 0x4c, 0x92, 0x32, 0xdf, 0x3e, 0x08, 0x4d, 0x99, 0x03, 0x13, 0x0c, 0x60, 0x1f, 0x63, 0xc1, 0xf4, 0xa4, 0xa4, 0xb8, 0x10, 0x6e, 0x46, 0x8c, 0xd4, 0x43, 0xbb, 0xe5, 0xa7, 0x34, 0xf4, 0x5f }, + { 0x6f, 0x43, 0x09, 0x4c, 0xaf, 0xb5, 0xeb, 0xf1, 0xf7, 0xa4, 0x93, 0x7e, 0xc5, 0x0f, 0x56, 0xa4, 0xc9, 0xda, 0x30, 0x3c, 0xbb, 0x55, 0xac, 0x1f, 0x27, 0xf1, 0xf1, 0x97, 0x6c, 0xd9, 0x6b, 0xed, 0xa9, 0x46, 0x4f, 0x0e, 0x7b, 0x9c, 0x54, 0x62, 0x0b, 0x8a, 0x9f, 0xba, 0x98, 0x31, 0x64, 0xb8, 0xbe, 0x35, 0x78, 0x42, 0x5a, 0x02, 0x4f, 0x5f, 0xe1, 0x99, 0xc3, 0x63, 0x56, 0xb8, 0x89, 0x72 }, + { 0x37, 0x45, 0x27, 0x3f, 0x4c, 0x38, 0x22, 0x5d, 0xb2, 0x33, 0x73, 0x81, 0x87, 0x1a, 0x0c, 0x6a, 0xaf, 0xd3, 0xaf, 0x9b, 0x01, 0x8c, 0x88, 0xaa, 0x02, 0x02, 0x58, 0x50, 0xa5, 0xdc, 0x3a, 0x42, 0xa1, 0xa3, 0xe0, 0x3e, 0x56, 0xcb, 0xf1, 0xb0, 0x87, 0x6d, 0x63, 0xa4, 0x41, 0xf1, 0xd2, 0x85, 0x6a, 0x39, 0xb8, 0x80, 0x1e, 0xb5, 0xaf, 0x32, 0x52, 0x01, 0xc4, 0x15, 0xd6, 0x5e, 0x97, 0xfe }, + { 0xc5, 0x0c, 0x44, 0xcc, 0xa3, 0xec, 0x3e, 0xda, 0xae, 0x77, 0x9a, 0x7e, 0x17, 0x94, 0x50, 0xeb, 0xdd, 0xa2, 0xf9, 0x70, 0x67, 0xc6, 0x90, 0xaa, 0x6c, 0x5a, 0x4a, 0xc7, 0xc3, 0x01, 0x39, 0xbb, 0x27, 0xc0, 0xdf, 0x4d, 0xb3, 0x22, 0x0e, 0x63, 0xcb, 0x11, 0x0d, 0x64, 0xf3, 0x7f, 0xfe, 0x07, 0x8d, 0xb7, 0x26, 0x53, 0xe2, 0xda, 0xac, 0xf9, 0x3a, 0xe3, 0xf0, 0xa2, 0xd1, 0xa7, 0xeb, 0x2e }, + { 0x8a, 0xef, 0x26, 0x3e, 0x38, 0x5c, 0xbc, 0x61, 0xe1, 0x9b, 0x28, 0x91, 0x42, 0x43, 0x26, 0x2a, 0xf5, 0xaf, 0xe8, 0x72, 0x6a, 0xf3, 0xce, 0x39, 0xa7, 0x9c, 0x27, 0x02, 0x8c, 0xf3, 0xec, 0xd3, 0xf8, 0xd2, 0xdf, 0xd9, 0xcf, 0xc9, 0xad, 0x91, 0xb5, 0x8f, 0x6f, 0x20, 0x77, 0x8f, 0xd5, 0xf0, 0x28, 0x94, 0xa3, 0xd9, 0x1c, 0x7d, 0x57, 0xd1, 0xe4, 0xb8, 0x66, 0xa7, 0xf3, 0x64, 0xb6, 0xbe }, + { 0x28, 0x69, 0x61, 0x41, 0xde, 0x6e, 0x2d, 0x9b, 0xcb, 0x32, 0x35, 0x57, 0x8a, 0x66, 0x16, 0x6c, 0x14, 0x48, 0xd3, 0xe9, 0x05, 0xa1, 0xb4, 0x82, 0xd4, 0x23, 0xbe, 0x4b, 0xc5, 0x36, 0x9b, 0xc8, 0xc7, 0x4d, 0xae, 0x0a, 0xcc, 0x9c, 0xc1, 0x23, 0xe1, 0xd8, 0xdd, 0xce, 0x9f, 0x97, 0x91, 0x7e, 0x8c, 0x01, 0x9c, 0x55, 0x2d, 0xa3, 0x2d, 0x39, 0xd2, 0x21, 0x9b, 0x9a, 0xbf, 0x0f, 0xa8, 0xc8 }, + { 0x2f, 0xb9, 0xeb, 0x20, 0x85, 0x83, 0x01, 0x81, 0x90, 0x3a, 0x9d, 0xaf, 0xe3, 0xdb, 0x42, 0x8e, 0xe1, 0x5b, 0xe7, 0x66, 0x22, 0x24, 0xef, 0xd6, 0x43, 0x37, 0x1f, 0xb2, 0x56, 0x46, 0xae, 0xe7, 0x16, 0xe5, 0x31, 0xec, 0xa6, 0x9b, 0x2b, 0xdc, 0x82, 0x33, 0xf1, 0xa8, 0x08, 0x1f, 0xa4, 0x3d, 0xa1, 0x50, 0x03, 0x02, 0x97, 0x5a, 0x77, 0xf4, 0x2f, 0xa5, 0x92, 0x13, 0x67, 0x10, 0xe9, 0xdc }, + { 0x66, 0xf9, 0xa7, 0x14, 0x3f, 0x7a, 0x33, 0x14, 0xa6, 0x69, 0xbf, 0x2e, 0x24, 0xbb, 0xb3, 0x50, 0x14, 0x26, 0x1d, 0x63, 0x9f, 0x49, 0x5b, 0x6c, 0x9c, 0x1f, 0x10, 0x4f, 0xe8, 0xe3, 0x20, 0xac, 0xa6, 0x0d, 0x45, 0x50, 0xd6, 0x9d, 0x52, 0xed, 0xbd, 0x5a, 0x3c, 0xde, 0xb4, 0x01, 0x4a, 0xe6, 0x5b, 0x1d, 0x87, 0xaa, 0x77, 0x0b, 0x69, 0xae, 0x5c, 0x15, 0xf4, 0x33, 0x0b, 0x0b, 0x0a, 0xd8 }, + { 0xf4, 0xc4, 0xdd, 0x1d, 0x59, 0x4c, 0x35, 0x65, 0xe3, 0xe2, 0x5c, 0xa4, 0x3d, 0xad, 0x82, 0xf6, 0x2a, 0xbe, 0xa4, 0x83, 0x5e, 0xd4, 0xcd, 0x81, 0x1b, 0xcd, 0x97, 0x5e, 0x46, 0x27, 0x98, 0x28, 0xd4, 0x4d, 0x4c, 0x62, 0xc3, 0x67, 0x9f, 0x1b, 0x7f, 0x7b, 0x9d, 0xd4, 0x57, 0x1d, 0x7b, 0x49, 0x55, 0x73, 0x47, 0xb8, 0xc5, 0x46, 0x0c, 0xbd, 0xc1, 0xbe, 0xf6, 0x90, 0xfb, 0x2a, 0x08, 0xc0 }, + { 0x8f, 0x1d, 0xc9, 0x64, 0x9c, 0x3a, 0x84, 0x55, 0x1f, 0x8f, 0x6e, 0x91, 0xca, 0xc6, 0x82, 0x42, 0xa4, 0x3b, 0x1f, 0x8f, 0x32, 0x8e, 0xe9, 0x22, 0x80, 0x25, 0x73, 0x87, 0xfa, 0x75, 0x59, 0xaa, 0x6d, 0xb1, 0x2e, 0x4a, 0xea, 0xdc, 0x2d, 0x26, 0x09, 0x91, 0x78, 0x74, 0x9c, 0x68, 0x64, 0xb3, 0x57, 0xf3, 0xf8, 0x3b, 0x2f, 0xb3, 0xef, 0xa8, 0xd2, 0xa8, 0xdb, 0x05, 0x6b, 0xed, 0x6b, 0xcc }, + { 0x31, 0x39, 0xc1, 0xa7, 0xf9, 0x7a, 0xfd, 0x16, 0x75, 0xd4, 0x60, 0xeb, 0xbc, 0x07, 0xf2, 0x72, 0x8a, 0xa1, 0x50, 0xdf, 0x84, 0x96, 0x24, 0x51, 0x1e, 0xe0, 0x4b, 0x74, 0x3b, 0xa0, 0xa8, 0x33, 0x09, 0x2f, 0x18, 0xc1, 0x2d, 0xc9, 0x1b, 0x4d, 0xd2, 0x43, 0xf3, 0x33, 0x40, 0x2f, 0x59, 0xfe, 0x28, 0xab, 0xdb, 0xbb, 0xae, 0x30, 0x1e, 0x7b, 0x65, 0x9c, 0x7a, 0x26, 0xd5, 0xc0, 0xf9, 0x79 }, + { 0x06, 0xf9, 0x4a, 0x29, 0x96, 0x15, 0x8a, 0x81, 0x9f, 0xe3, 0x4c, 0x40, 0xde, 0x3c, 0xf0, 0x37, 0x9f, 0xd9, 0xfb, 0x85, 0xb3, 0xe3, 0x63, 0xba, 0x39, 0x26, 0xa0, 0xe7, 0xd9, 0x60, 0xe3, 0xf4, 0xc2, 0xe0, 0xc7, 0x0c, 0x7c, 0xe0, 0xcc, 0xb2, 0xa6, 0x4f, 0xc2, 0x98, 0x69, 0xf6, 0xe7, 0xab, 0x12, 0xbd, 0x4d, 0x3f, 0x14, 0xfc, 0xe9, 0x43, 0x27, 0x90, 0x27, 0xe7, 0x85, 0xfb, 0x5c, 0x29 }, + { 0xc2, 0x9c, 0x39, 0x9e, 0xf3, 0xee, 0xe8, 0x96, 0x1e, 0x87, 0x56, 0x5c, 0x1c, 0xe2, 0x63, 0x92, 0x5f, 0xc3, 0xd0, 0xce, 0x26, 0x7d, 0x13, 0xe4, 0x8d, 0xd9, 0xe7, 0x32, 0xee, 0x67, 0xb0, 0xf6, 0x9f, 0xad, 0x56, 0x40, 0x1b, 0x0f, 0x10, 0xfc, 0xaa, 0xc1, 0x19, 0x20, 0x10, 0x46, 0xcc, 0xa2, 0x8c, 0x5b, 0x14, 0xab, 0xde, 0xa3, 0x21, 0x2a, 0xe6, 0x55, 0x62, 0xf7, 0xf1, 0x38, 0xdb, 0x3d }, + { 0x4c, 0xec, 0x4c, 0x9d, 0xf5, 0x2e, 0xef, 0x05, 0xc3, 0xf6, 0xfa, 0xaa, 0x97, 0x91, 0xbc, 0x74, 0x45, 0x93, 0x71, 0x83, 0x22, 0x4e, 0xcc, 0x37, 0xa1, 0xe5, 0x8d, 0x01, 0x32, 0xd3, 0x56, 0x17, 0x53, 0x1d, 0x7e, 0x79, 0x5f, 0x52, 0xaf, 0x7b, 0x1e, 0xb9, 0xd1, 0x47, 0xde, 0x12, 0x92, 0xd3, 0x45, 0xfe, 0x34, 0x18, 0x23, 0xf8, 0xe6, 0xbc, 0x1e, 0x5b, 0xad, 0xca, 0x5c, 0x65, 0x61, 0x08 }, + { 0x89, 0x8b, 0xfb, 0xae, 0x93, 0xb3, 0xe1, 0x8d, 0x00, 0x69, 0x7e, 0xab, 0x7d, 0x97, 0x04, 0xfa, 0x36, 0xec, 0x33, 0x9d, 0x07, 0x61, 0x31, 0xce, 0xfd, 0xf3, 0x0e, 0xdb, 0xe8, 0xd9, 0xcc, 0x81, 0xc3, 0xa8, 0x0b, 0x12, 0x96, 0x59, 0xb1, 0x63, 0xa3, 0x23, 0xba, 0xb9, 0x79, 0x3d, 0x4f, 0xee, 0xd9, 0x2d, 0x54, 0xda, 0xe9, 0x66, 0xc7, 0x75, 0x29, 0x76, 0x4a, 0x09, 0xbe, 0x88, 0xdb, 0x45 }, + { 0xee, 0x9b, 0xd0, 0x46, 0x9d, 0x3a, 0xaf, 0x4f, 0x14, 0x03, 0x5b, 0xe4, 0x8a, 0x2c, 0x3b, 0x84, 0xd9, 0xb4, 0xb1, 0xff, 0xf1, 0xd9, 0x45, 0xe1, 0xf1, 0xc1, 0xd3, 0x89, 0x80, 0xa9, 0x51, 0xbe, 0x19, 0x7b, 0x25, 0xfe, 0x22, 0xc7, 0x31, 0xf2, 0x0a, 0xea, 0xcc, 0x93, 0x0b, 0xa9, 0xc4, 0xa1, 0xf4, 0x76, 0x22, 0x27, 0x61, 0x7a, 0xd3, 0x50, 0xfd, 0xab, 0xb4, 0xe8, 0x02, 0x73, 0xa0, 0xf4 }, + { 0x3d, 0x4d, 0x31, 0x13, 0x30, 0x05, 0x81, 0xcd, 0x96, 0xac, 0xbf, 0x09, 0x1c, 0x3d, 0x0f, 0x3c, 0x31, 0x01, 0x38, 0xcd, 0x69, 0x79, 0xe6, 0x02, 0x6c, 0xde, 0x62, 0x3e, 0x2d, 0xd1, 0xb2, 0x4d, 0x4a, 0x86, 0x38, 0xbe, 0xd1, 0x07, 0x33, 0x44, 0x78, 0x3a, 0xd0, 0x64, 0x9c, 0xc6, 0x30, 0x5c, 0xce, 0xc0, 0x4b, 0xeb, 0x49, 0xf3, 0x1c, 0x63, 0x30, 0x88, 0xa9, 0x9b, 0x65, 0x13, 0x02, 0x67 }, + { 0x95, 0xc0, 0x59, 0x1a, 0xd9, 0x1f, 0x92, 0x1a, 0xc7, 0xbe, 0x6d, 0x9c, 0xe3, 0x7e, 0x06, 0x63, 0xed, 0x80, 0x11, 0xc1, 0xcf, 0xd6, 0xd0, 0x16, 0x2a, 0x55, 0x72, 0xe9, 0x43, 0x68, 0xba, 0xc0, 0x20, 0x24, 0x48, 0x5e, 0x6a, 0x39, 0x85, 0x4a, 0xa4, 0x6f, 0xe3, 0x8e, 0x97, 0xd6, 0xc6, 0xb1, 0x94, 0x7c, 0xd2, 0x72, 0xd8, 0x6b, 0x06, 0xbb, 0x5b, 0x2f, 0x78, 0xb9, 0xb6, 0x8d, 0x55, 0x9d }, + { 0x22, 0x7b, 0x79, 0xde, 0xd3, 0x68, 0x15, 0x3b, 0xf4, 0x6c, 0x0a, 0x3c, 0xa9, 0x78, 0xbf, 0xdb, 0xef, 0x31, 0xf3, 0x02, 0x4a, 0x56, 0x65, 0x84, 0x24, 0x68, 0x49, 0x0b, 0x0f, 0xf7, 0x48, 0xae, 0x04, 0xe7, 0x83, 0x2e, 0xd4, 0xc9, 0xf4, 0x9d, 0xe9, 0xb1, 0x70, 0x67, 0x09, 0xd6, 0x23, 0xe5, 0xc8, 0xc1, 0x5e, 0x3c, 0xae, 0xca, 0xe8, 0xd5, 0xe4, 0x33, 0x43, 0x0f, 0xf7, 0x2f, 0x20, 0xeb }, + { 0x5d, 0x34, 0xf3, 0x95, 0x2f, 0x01, 0x05, 0xee, 0xf8, 0x8a, 0xe8, 0xb6, 0x4c, 0x6c, 0xe9, 0x5e, 0xbf, 0xad, 0xe0, 0xe0, 0x2c, 0x69, 0xb0, 0x87, 0x62, 0xa8, 0x71, 0x2d, 0x2e, 0x49, 0x11, 0xad, 0x3f, 0x94, 0x1f, 0xc4, 0x03, 0x4d, 0xc9, 0xb2, 0xe4, 0x79, 0xfd, 0xbc, 0xd2, 0x79, 0xb9, 0x02, 0xfa, 0xf5, 0xd8, 0x38, 0xbb, 0x2e, 0x0c, 0x64, 0x95, 0xd3, 0x72, 0xb5, 0xb7, 0x02, 0x98, 0x13 }, + { 0x7f, 0x93, 0x9b, 0xf8, 0x35, 0x3a, 0xbc, 0xe4, 0x9e, 0x77, 0xf1, 0x4f, 0x37, 0x50, 0xaf, 0x20, 0xb7, 0xb0, 0x39, 0x02, 0xe1, 0xa1, 0xe7, 0xfb, 0x6a, 0xaf, 0x76, 0xd0, 0x25, 0x9c, 0xd4, 0x01, 0xa8, 0x31, 0x90, 0xf1, 0x56, 0x40, 0xe7, 0x4f, 0x3e, 0x6c, 0x5a, 0x90, 0xe8, 0x39, 0xc7, 0x82, 0x1f, 0x64, 0x74, 0x75, 0x7f, 0x75, 0xc7, 0xbf, 0x90, 0x02, 0x08, 0x4d, 0xdc, 0x7a, 0x62, 0xdc }, + { 0x06, 0x2b, 0x61, 0xa2, 0xf9, 0xa3, 0x3a, 0x71, 0xd7, 0xd0, 0xa0, 0x61, 0x19, 0x64, 0x4c, 0x70, 0xb0, 0x71, 0x6a, 0x50, 0x4d, 0xe7, 0xe5, 0xe1, 0xbe, 0x49, 0xbd, 0x7b, 0x86, 0xe7, 0xed, 0x68, 0x17, 0x71, 0x4f, 0x9f, 0x0f, 0xc3, 0x13, 0xd0, 0x61, 0x29, 0x59, 0x7e, 0x9a, 0x22, 0x35, 0xec, 0x85, 0x21, 0xde, 0x36, 0xf7, 0x29, 0x0a, 0x90, 0xcc, 0xfc, 0x1f, 0xfa, 0x6d, 0x0a, 0xee, 0x29 }, + { 0xf2, 0x9e, 0x01, 0xee, 0xae, 0x64, 0x31, 0x1e, 0xb7, 0xf1, 0xc6, 0x42, 0x2f, 0x94, 0x6b, 0xf7, 0xbe, 0xa3, 0x63, 0x79, 0x52, 0x3e, 0x7b, 0x2b, 0xba, 0xba, 0x7d, 0x1d, 0x34, 0xa2, 0x2d, 0x5e, 0xa5, 0xf1, 0xc5, 0xa0, 0x9d, 0x5c, 0xe1, 0xfe, 0x68, 0x2c, 0xce, 0xd9, 0xa4, 0x79, 0x8d, 0x1a, 0x05, 0xb4, 0x6c, 0xd7, 0x2d, 0xff, 0x5c, 0x1b, 0x35, 0x54, 0x40, 0xb2, 0xa2, 0xd4, 0x76, 0xbc }, + { 0xec, 0x38, 0xcd, 0x3b, 0xba, 0xb3, 0xef, 0x35, 0xd7, 0xcb, 0x6d, 0x5c, 0x91, 0x42, 0x98, 0x35, 0x1d, 0x8a, 0x9d, 0xc9, 0x7f, 0xce, 0xe0, 0x51, 0xa8, 0xa0, 0x2f, 0x58, 0xe3, 0xed, 0x61, 0x84, 0xd0, 0xb7, 0x81, 0x0a, 0x56, 0x15, 0x41, 0x1a, 0xb1, 0xb9, 0x52, 0x09, 0xc3, 0xc8, 0x10, 0x11, 0x4f, 0xde, 0xb2, 0x24, 0x52, 0x08, 0x4e, 0x77, 0xf3, 0xf8, 0x47, 0xc6, 0xdb, 0xaa, 0xfe, 0x16 }, + { 0xc2, 0xae, 0xf5, 0xe0, 0xca, 0x43, 0xe8, 0x26, 0x41, 0x56, 0x5b, 0x8c, 0xb9, 0x43, 0xaa, 0x8b, 0xa5, 0x35, 0x50, 0xca, 0xef, 0x79, 0x3b, 0x65, 0x32, 0xfa, 0xfa, 0xd9, 0x4b, 0x81, 0x60, 0x82, 0xf0, 0x11, 0x3a, 0x3e, 0xa2, 0xf6, 0x36, 0x08, 0xab, 0x40, 0x43, 0x7e, 0xcc, 0x0f, 0x02, 0x29, 0xcb, 0x8f, 0xa2, 0x24, 0xdc, 0xf1, 0xc4, 0x78, 0xa6, 0x7d, 0x9b, 0x64, 0x16, 0x2b, 0x92, 0xd1 }, + { 0x15, 0xf5, 0x34, 0xef, 0xff, 0x71, 0x05, 0xcd, 0x1c, 0x25, 0x4d, 0x07, 0x4e, 0x27, 0xd5, 0x89, 0x8b, 0x89, 0x31, 0x3b, 0x7d, 0x36, 0x6d, 0xc2, 0xd7, 0xd8, 0x71, 0x13, 0xfa, 0x7d, 0x53, 0xaa, 0xe1, 0x3f, 0x6d, 0xba, 0x48, 0x7a, 0xd8, 0x10, 0x3d, 0x5e, 0x85, 0x4c, 0x91, 0xfd, 0xb6, 0xe1, 0xe7, 0x4b, 0x2e, 0xf6, 0xd1, 0x43, 0x17, 0x69, 0xc3, 0x07, 0x67, 0xdd, 0xe0, 0x67, 0xa3, 0x5c }, + { 0x89, 0xac, 0xbc, 0xa0, 0xb1, 0x69, 0x89, 0x7a, 0x0a, 0x27, 0x14, 0xc2, 0xdf, 0x8c, 0x95, 0xb5, 0xb7, 0x9c, 0xb6, 0x93, 0x90, 0x14, 0x2b, 0x7d, 0x60, 0x18, 0xbb, 0x3e, 0x30, 0x76, 0xb0, 0x99, 0xb7, 0x9a, 0x96, 0x41, 0x52, 0xa9, 0xd9, 0x12, 0xb1, 0xb8, 0x64, 0x12, 0xb7, 0xe3, 0x72, 0xe9, 0xce, 0xca, 0xd7, 0xf2, 0x5d, 0x4c, 0xba, 0xb8, 0xa3, 0x17, 0xbe, 0x36, 0x49, 0x2a, 0x67, 0xd7 }, + { 0xe3, 0xc0, 0x73, 0x91, 0x90, 0xed, 0x84, 0x9c, 0x9c, 0x96, 0x2f, 0xd9, 0xdb, 0xb5, 0x5e, 0x20, 0x7e, 0x62, 0x4f, 0xca, 0xc1, 0xeb, 0x41, 0x76, 0x91, 0x51, 0x54, 0x99, 0xee, 0xa8, 0xd8, 0x26, 0x7b, 0x7e, 0x8f, 0x12, 0x87, 0xa6, 0x36, 0x33, 0xaf, 0x50, 0x11, 0xfd, 0xe8, 0xc4, 0xdd, 0xf5, 0x5b, 0xfd, 0xf7, 0x22, 0xed, 0xf8, 0x88, 0x31, 0x41, 0x4f, 0x2c, 0xfa, 0xed, 0x59, 0xcb, 0x9a }, + { 0x8d, 0x6c, 0xf8, 0x7c, 0x08, 0x38, 0x0d, 0x2d, 0x15, 0x06, 0xee, 0xe4, 0x6f, 0xd4, 0x22, 0x2d, 0x21, 0xd8, 0xc0, 0x4e, 0x58, 0x5f, 0xbf, 0xd0, 0x82, 0x69, 0xc9, 0x8f, 0x70, 0x28, 0x33, 0xa1, 0x56, 0x32, 0x6a, 0x07, 0x24, 0x65, 0x64, 0x00, 0xee, 0x09, 0x35, 0x1d, 0x57, 0xb4, 0x40, 0x17, 0x5e, 0x2a, 0x5d, 0xe9, 0x3c, 0xc5, 0xf8, 0x0d, 0xb6, 0xda, 0xf8, 0x35, 0x76, 0xcf, 0x75, 0xfa }, + { 0xda, 0x24, 0xbe, 0xde, 0x38, 0x36, 0x66, 0xd5, 0x63, 0xee, 0xed, 0x37, 0xf6, 0x31, 0x9b, 0xaf, 0x20, 0xd5, 0xc7, 0x5d, 0x16, 0x35, 0xa6, 0xba, 0x5e, 0xf4, 0xcf, 0xa1, 0xac, 0x95, 0x48, 0x7e, 0x96, 0xf8, 0xc0, 0x8a, 0xf6, 0x00, 0xaa, 0xb8, 0x7c, 0x98, 0x6e, 0xba, 0xd4, 0x9f, 0xc7, 0x0a, 0x58, 0xb4, 0x89, 0x0b, 0x9c, 0x87, 0x6e, 0x09, 0x10, 0x16, 0xda, 0xf4, 0x9e, 0x1d, 0x32, 0x2e }, + { 0xf9, 0xd1, 0xd1, 0xb1, 0xe8, 0x7e, 0xa7, 0xae, 0x75, 0x3a, 0x02, 0x97, 0x50, 0xcc, 0x1c, 0xf3, 0xd0, 0x15, 0x7d, 0x41, 0x80, 0x5e, 0x24, 0x5c, 0x56, 0x17, 0xbb, 0x93, 0x4e, 0x73, 0x2f, 0x0a, 0xe3, 0x18, 0x0b, 0x78, 0xe0, 0x5b, 0xfe, 0x76, 0xc7, 0xc3, 0x05, 0x1e, 0x3e, 0x3a, 0xc7, 0x8b, 0x9b, 0x50, 0xc0, 0x51, 0x42, 0x65, 0x7e, 0x1e, 0x03, 0x21, 0x5d, 0x6e, 0xc7, 0xbf, 0xd0, 0xfc }, + { 0x11, 0xb7, 0xbc, 0x16, 0x68, 0x03, 0x20, 0x48, 0xaa, 0x43, 0x34, 0x3d, 0xe4, 0x76, 0x39, 0x5e, 0x81, 0x4b, 0xbb, 0xc2, 0x23, 0x67, 0x8d, 0xb9, 0x51, 0xa1, 0xb0, 0x3a, 0x02, 0x1e, 0xfa, 0xc9, 0x48, 0xcf, 0xbe, 0x21, 0x5f, 0x97, 0xfe, 0x9a, 0x72, 0xa2, 0xf6, 0xbc, 0x03, 0x9e, 0x39, 0x56, 0xbf, 0xa4, 0x17, 0xc1, 0xa9, 0xf1, 0x0d, 0x6d, 0x7b, 0xa5, 0xd3, 0xd3, 0x2f, 0xf3, 0x23, 0xe5 }, + { 0xb8, 0xd9, 0x00, 0x0e, 0x4f, 0xc2, 0xb0, 0x66, 0xed, 0xb9, 0x1a, 0xfe, 0xe8, 0xe7, 0xeb, 0x0f, 0x24, 0xe3, 0xa2, 0x01, 0xdb, 0x8b, 0x67, 0x93, 0xc0, 0x60, 0x85, 0x81, 0xe6, 0x28, 0xed, 0x0b, 0xcc, 0x4e, 0x5a, 0xa6, 0x78, 0x79, 0x92, 0xa4, 0xbc, 0xc4, 0x4e, 0x28, 0x80, 0x93, 0xe6, 0x3e, 0xe8, 0x3a, 0xbd, 0x0b, 0xc3, 0xec, 0x6d, 0x09, 0x34, 0xa6, 0x74, 0xa4, 0xda, 0x13, 0x83, 0x8a }, + { 0xce, 0x32, 0x5e, 0x29, 0x4f, 0x9b, 0x67, 0x19, 0xd6, 0xb6, 0x12, 0x78, 0x27, 0x6a, 0xe0, 0x6a, 0x25, 0x64, 0xc0, 0x3b, 0xb0, 0xb7, 0x83, 0xfa, 0xfe, 0x78, 0x5b, 0xdf, 0x89, 0xc7, 0xd5, 0xac, 0xd8, 0x3e, 0x78, 0x75, 0x6d, 0x30, 0x1b, 0x44, 0x56, 0x99, 0x02, 0x4e, 0xae, 0xb7, 0x7b, 0x54, 0xd4, 0x77, 0x33, 0x6e, 0xc2, 0xa4, 0xf3, 0x32, 0xf2, 0xb3, 0xf8, 0x87, 0x65, 0xdd, 0xb0, 0xc3 }, + { 0x29, 0xac, 0xc3, 0x0e, 0x96, 0x03, 0xae, 0x2f, 0xcc, 0xf9, 0x0b, 0xf9, 0x7e, 0x6c, 0xc4, 0x63, 0xeb, 0xe2, 0x8c, 0x1b, 0x2f, 0x9b, 0x4b, 0x76, 0x5e, 0x70, 0x53, 0x7c, 0x25, 0xc7, 0x02, 0xa2, 0x9d, 0xcb, 0xfb, 0xf1, 0x4c, 0x99, 0xc5, 0x43, 0x45, 0xba, 0x2b, 0x51, 0xf1, 0x7b, 0x77, 0xb5, 0xf1, 0x5d, 0xb9, 0x2b, 0xba, 0xd8, 0xfa, 0x95, 0xc4, 0x71, 0xf5, 0xd0, 0x70, 0xa1, 0x37, 0xcc }, + { 0x33, 0x79, 0xcb, 0xaa, 0xe5, 0x62, 0xa8, 0x7b, 0x4c, 0x04, 0x25, 0x55, 0x0f, 0xfd, 0xd6, 0xbf, 0xe1, 0x20, 0x3f, 0x0d, 0x66, 0x6c, 0xc7, 0xea, 0x09, 0x5b, 0xe4, 0x07, 0xa5, 0xdf, 0xe6, 0x1e, 0xe9, 0x14, 0x41, 0xcd, 0x51, 0x54, 0xb3, 0xe5, 0x3b, 0x4f, 0x5f, 0xb3, 0x1a, 0xd4, 0xc7, 0xa9, 0xad, 0x5c, 0x7a, 0xf4, 0xae, 0x67, 0x9a, 0xa5, 0x1a, 0x54, 0x00, 0x3a, 0x54, 0xca, 0x6b, 0x2d }, + { 0x30, 0x95, 0xa3, 0x49, 0xd2, 0x45, 0x70, 0x8c, 0x7c, 0xf5, 0x50, 0x11, 0x87, 0x03, 0xd7, 0x30, 0x2c, 0x27, 0xb6, 0x0a, 0xf5, 0xd4, 0xe6, 0x7f, 0xc9, 0x78, 0xf8, 0xa4, 0xe6, 0x09, 0x53, 0xc7, 0xa0, 0x4f, 0x92, 0xfc, 0xf4, 0x1a, 0xee, 0x64, 0x32, 0x1c, 0xcb, 0x70, 0x7a, 0x89, 0x58, 0x51, 0x55, 0x2b, 0x1e, 0x37, 0xb0, 0x0b, 0xc5, 0xe6, 0xb7, 0x2f, 0xa5, 0xbc, 0xef, 0x9e, 0x3f, 0xff }, + { 0x07, 0x26, 0x2d, 0x73, 0x8b, 0x09, 0x32, 0x1f, 0x4d, 0xbc, 0xce, 0xc4, 0xbb, 0x26, 0xf4, 0x8c, 0xb0, 0xf0, 0xed, 0x24, 0x6c, 0xe0, 0xb3, 0x1b, 0x9a, 0x6e, 0x7b, 0xc6, 0x83, 0x04, 0x9f, 0x1f, 0x3e, 0x55, 0x45, 0xf2, 0x8c, 0xe9, 0x32, 0xdd, 0x98, 0x5c, 0x5a, 0xb0, 0xf4, 0x3b, 0xd6, 0xde, 0x07, 0x70, 0x56, 0x0a, 0xf3, 0x29, 0x06, 0x5e, 0xd2, 0xe4, 0x9d, 0x34, 0x62, 0x4c, 0x2c, 0xbb }, + { 0xb6, 0x40, 0x5e, 0xca, 0x8e, 0xe3, 0x31, 0x6c, 0x87, 0x06, 0x1c, 0xc6, 0xec, 0x18, 0xdb, 0xa5, 0x3e, 0x6c, 0x25, 0x0c, 0x63, 0xba, 0x1f, 0x3b, 0xae, 0x9e, 0x55, 0xdd, 0x34, 0x98, 0x03, 0x6a, 0xf0, 0x8c, 0xd2, 0x72, 0xaa, 0x24, 0xd7, 0x13, 0xc6, 0x02, 0x0d, 0x77, 0xab, 0x2f, 0x39, 0x19, 0xaf, 0x1a, 0x32, 0xf3, 0x07, 0x42, 0x06, 0x18, 0xab, 0x97, 0xe7, 0x39, 0x53, 0x99, 0x4f, 0xb4 }, + { 0x7e, 0xe6, 0x82, 0xf6, 0x31, 0x48, 0xee, 0x45, 0xf6, 0xe5, 0x31, 0x5d, 0xa8, 0x1e, 0x5c, 0x6e, 0x55, 0x7c, 0x2c, 0x34, 0x64, 0x1f, 0xc5, 0x09, 0xc7, 0xa5, 0x70, 0x10, 0x88, 0xc3, 0x8a, 0x74, 0x75, 0x61, 0x68, 0xe2, 0xcd, 0x8d, 0x35, 0x1e, 0x88, 0xfd, 0x1a, 0x45, 0x1f, 0x36, 0x0a, 0x01, 0xf5, 0xb2, 0x58, 0x0f, 0x9b, 0x5a, 0x2e, 0x8c, 0xfc, 0x13, 0x8f, 0x3d, 0xd5, 0x9a, 0x3f, 0xfc }, + { 0x1d, 0x26, 0x3c, 0x17, 0x9d, 0x6b, 0x26, 0x8f, 0x6f, 0xa0, 0x16, 0xf3, 0xa4, 0xf2, 0x9e, 0x94, 0x38, 0x91, 0x12, 0x5e, 0xd8, 0x59, 0x3c, 0x81, 0x25, 0x60, 0x59, 0xf5, 0xa7, 0xb4, 0x4a, 0xf2, 0xdc, 0xb2, 0x03, 0x0d, 0x17, 0x5c, 0x00, 0xe6, 0x2e, 0xca, 0xf7, 0xee, 0x96, 0x68, 0x2a, 0xa0, 0x7a, 0xb2, 0x0a, 0x61, 0x10, 0x24, 0xa2, 0x85, 0x32, 0xb1, 0xc2, 0x5b, 0x86, 0x65, 0x79, 0x02 }, + { 0x10, 0x6d, 0x13, 0x2c, 0xbd, 0xb4, 0xcd, 0x25, 0x97, 0x81, 0x28, 0x46, 0xe2, 0xbc, 0x1b, 0xf7, 0x32, 0xfe, 0xc5, 0xf0, 0xa5, 0xf6, 0x5d, 0xbb, 0x39, 0xec, 0x4e, 0x6d, 0xc6, 0x4a, 0xb2, 0xce, 0x6d, 0x24, 0x63, 0x0d, 0x0f, 0x15, 0xa8, 0x05, 0xc3, 0x54, 0x00, 0x25, 0xd8, 0x4a, 0xfa, 0x98, 0xe3, 0x67, 0x03, 0xc3, 0xdb, 0xee, 0x71, 0x3e, 0x72, 0xdd, 0xe8, 0x46, 0x5b, 0xc1, 0xbe, 0x7e }, + { 0x0e, 0x79, 0x96, 0x82, 0x26, 0x65, 0x06, 0x67, 0xa8, 0xd8, 0x62, 0xea, 0x8d, 0xa4, 0x89, 0x1a, 0xf5, 0x6a, 0x4e, 0x3a, 0x8b, 0x6d, 0x17, 0x50, 0xe3, 0x94, 0xf0, 0xde, 0xa7, 0x6d, 0x64, 0x0d, 0x85, 0x07, 0x7b, 0xce, 0xc2, 0xcc, 0x86, 0x88, 0x6e, 0x50, 0x67, 0x51, 0xb4, 0xf6, 0xa5, 0x83, 0x8f, 0x7f, 0x0b, 0x5f, 0xef, 0x76, 0x5d, 0x9d, 0xc9, 0x0d, 0xcd, 0xcb, 0xaf, 0x07, 0x9f, 0x08 }, + { 0x52, 0x11, 0x56, 0xa8, 0x2a, 0xb0, 0xc4, 0xe5, 0x66, 0xe5, 0x84, 0x4d, 0x5e, 0x31, 0xad, 0x9a, 0xaf, 0x14, 0x4b, 0xbd, 0x5a, 0x46, 0x4f, 0xdc, 0xa3, 0x4d, 0xbd, 0x57, 0x17, 0xe8, 0xff, 0x71, 0x1d, 0x3f, 0xfe, 0xbb, 0xfa, 0x08, 0x5d, 0x67, 0xfe, 0x99, 0x6a, 0x34, 0xf6, 0xd3, 0xe4, 0xe6, 0x0b, 0x13, 0x96, 0xbf, 0x4b, 0x16, 0x10, 0xc2, 0x63, 0xbd, 0xbb, 0x83, 0x4d, 0x56, 0x08, 0x16 }, + { 0x1a, 0xba, 0x88, 0xbe, 0xfc, 0x55, 0xbc, 0x25, 0xef, 0xbc, 0xe0, 0x2d, 0xb8, 0xb9, 0x93, 0x3e, 0x46, 0xf5, 0x76, 0x61, 0xba, 0xea, 0xbe, 0xb2, 0x1c, 0xc2, 0x57, 0x4d, 0x2a, 0x51, 0x8a, 0x3c, 0xba, 0x5d, 0xc5, 0xa3, 0x8e, 0x49, 0x71, 0x34, 0x40, 0xb2, 0x5f, 0x9c, 0x74, 0x4e, 0x75, 0xf6, 0xb8, 0x5c, 0x9d, 0x8f, 0x46, 0x81, 0xf6, 0x76, 0x16, 0x0f, 0x61, 0x05, 0x35, 0x7b, 0x84, 0x06 }, + { 0x5a, 0x99, 0x49, 0xfc, 0xb2, 0xc4, 0x73, 0xcd, 0xa9, 0x68, 0xac, 0x1b, 0x5d, 0x08, 0x56, 0x6d, 0xc2, 0xd8, 0x16, 0xd9, 0x60, 0xf5, 0x7e, 0x63, 0xb8, 0x98, 0xfa, 0x70, 0x1c, 0xf8, 0xeb, 0xd3, 0xf5, 0x9b, 0x12, 0x4d, 0x95, 0xbf, 0xbb, 0xed, 0xc5, 0xf1, 0xcf, 0x0e, 0x17, 0xd5, 0xea, 0xed, 0x0c, 0x02, 0xc5, 0x0b, 0x69, 0xd8, 0xa4, 0x02, 0xca, 0xbc, 0xca, 0x44, 0x33, 0xb5, 0x1f, 0xd4 }, + { 0xb0, 0xce, 0xad, 0x09, 0x80, 0x7c, 0x67, 0x2a, 0xf2, 0xeb, 0x2b, 0x0f, 0x06, 0xdd, 0xe4, 0x6c, 0xf5, 0x37, 0x0e, 0x15, 0xa4, 0x09, 0x6b, 0x1a, 0x7d, 0x7c, 0xbb, 0x36, 0xec, 0x31, 0xc2, 0x05, 0xfb, 0xef, 0xca, 0x00, 0xb7, 0xa4, 0x16, 0x2f, 0xa8, 0x9f, 0xb4, 0xfb, 0x3e, 0xb7, 0x8d, 0x79, 0x77, 0x0c, 0x23, 0xf4, 0x4e, 0x72, 0x06, 0x66, 0x4c, 0xe3, 0xcd, 0x93, 0x1c, 0x29, 0x1e, 0x5d }, + { 0xbb, 0x66, 0x64, 0x93, 0x1e, 0xc9, 0x70, 0x44, 0xe4, 0x5b, 0x2a, 0xe4, 0x20, 0xae, 0x1c, 0x55, 0x1a, 0x88, 0x74, 0xbc, 0x93, 0x7d, 0x08, 0xe9, 0x69, 0x39, 0x9c, 0x39, 0x64, 0xeb, 0xdb, 0xa8, 0x34, 0x6c, 0xdd, 0x5d, 0x09, 0xca, 0xaf, 0xe4, 0xc2, 0x8b, 0xa7, 0xec, 0x78, 0x81, 0x91, 0xce, 0xca, 0x65, 0xdd, 0xd6, 0xf9, 0x5f, 0x18, 0x58, 0x3e, 0x04, 0x0d, 0x0f, 0x30, 0xd0, 0x36, 0x4d }, + { 0x65, 0xbc, 0x77, 0x0a, 0x5f, 0xaa, 0x37, 0x92, 0x36, 0x98, 0x03, 0x68, 0x3e, 0x84, 0x4b, 0x0b, 0xe7, 0xee, 0x96, 0xf2, 0x9f, 0x6d, 0x6a, 0x35, 0x56, 0x80, 0x06, 0xbd, 0x55, 0x90, 0xf9, 0xa4, 0xef, 0x63, 0x9b, 0x7a, 0x80, 0x61, 0xc7, 0xb0, 0x42, 0x4b, 0x66, 0xb6, 0x0a, 0xc3, 0x4a, 0xf3, 0x11, 0x99, 0x05, 0xf3, 0x3a, 0x9d, 0x8c, 0x3a, 0xe1, 0x83, 0x82, 0xca, 0x9b, 0x68, 0x99, 0x00 }, + { 0xea, 0x9b, 0x4d, 0xca, 0x33, 0x33, 0x36, 0xaa, 0xf8, 0x39, 0xa4, 0x5c, 0x6e, 0xaa, 0x48, 0xb8, 0xcb, 0x4c, 0x7d, 0xda, 0xbf, 0xfe, 0xa4, 0xf6, 0x43, 0xd6, 0x35, 0x7e, 0xa6, 0x62, 0x8a, 0x48, 0x0a, 0x5b, 0x45, 0xf2, 0xb0, 0x52, 0xc1, 0xb0, 0x7d, 0x1f, 0xed, 0xca, 0x91, 0x8b, 0x6f, 0x11, 0x39, 0xd8, 0x0f, 0x74, 0xc2, 0x45, 0x10, 0xdc, 0xba, 0xa4, 0xbe, 0x70, 0xea, 0xcc, 0x1b, 0x06 }, + { 0xe6, 0x34, 0x2f, 0xb4, 0xa7, 0x80, 0xad, 0x97, 0x5d, 0x0e, 0x24, 0xbc, 0xe1, 0x49, 0x98, 0x9b, 0x91, 0xd3, 0x60, 0x55, 0x7e, 0x87, 0x99, 0x4f, 0x6b, 0x45, 0x7b, 0x89, 0x55, 0x75, 0xcc, 0x02, 0xd0, 0xc1, 0x5b, 0xad, 0x3c, 0xe7, 0x57, 0x7f, 0x4c, 0x63, 0x92, 0x7f, 0xf1, 0x3f, 0x3e, 0x38, 0x1f, 0xf7, 0xe7, 0x2b, 0xdb, 0xe7, 0x45, 0x32, 0x48, 0x44, 0xa9, 0xd2, 0x7e, 0x3f, 0x1c, 0x01 }, + { 0x3e, 0x20, 0x9c, 0x9b, 0x33, 0xe8, 0xe4, 0x61, 0x17, 0x8a, 0xb4, 0x6b, 0x1c, 0x64, 0xb4, 0x9a, 0x07, 0xfb, 0x74, 0x5f, 0x1c, 0x8b, 0xc9, 0x5f, 0xbf, 0xb9, 0x4c, 0x6b, 0x87, 0xc6, 0x95, 0x16, 0x65, 0x1b, 0x26, 0x4e, 0xf9, 0x80, 0x93, 0x7f, 0xad, 0x41, 0x23, 0x8b, 0x91, 0xdd, 0xc0, 0x11, 0xa5, 0xdd, 0x77, 0x7c, 0x7e, 0xfd, 0x44, 0x94, 0xb4, 0xb6, 0xec, 0xd3, 0xa9, 0xc2, 0x2a, 0xc0 }, + { 0xfd, 0x6a, 0x3d, 0x5b, 0x18, 0x75, 0xd8, 0x04, 0x86, 0xd6, 0xe6, 0x96, 0x94, 0xa5, 0x6d, 0xbb, 0x04, 0xa9, 0x9a, 0x4d, 0x05, 0x1f, 0x15, 0xdb, 0x26, 0x89, 0x77, 0x6b, 0xa1, 0xc4, 0x88, 0x2e, 0x6d, 0x46, 0x2a, 0x60, 0x3b, 0x70, 0x15, 0xdc, 0x9f, 0x4b, 0x74, 0x50, 0xf0, 0x53, 0x94, 0x30, 0x3b, 0x86, 0x52, 0xcf, 0xb4, 0x04, 0xa2, 0x66, 0x96, 0x2c, 0x41, 0xba, 0xe6, 0xe1, 0x8a, 0x94 }, + { 0x95, 0x1e, 0x27, 0x51, 0x7e, 0x6b, 0xad, 0x9e, 0x41, 0x95, 0xfc, 0x86, 0x71, 0xde, 0xe3, 0xe7, 0xe9, 0xbe, 0x69, 0xce, 0xe1, 0x42, 0x2c, 0xb9, 0xfe, 0xcf, 0xce, 0x0d, 0xba, 0x87, 0x5f, 0x7b, 0x31, 0x0b, 0x93, 0xee, 0x3a, 0x3d, 0x55, 0x8f, 0x94, 0x1f, 0x63, 0x5f, 0x66, 0x8f, 0xf8, 0x32, 0xd2, 0xc1, 0xd0, 0x33, 0xc5, 0xe2, 0xf0, 0x99, 0x7e, 0x4c, 0x66, 0xf1, 0x47, 0x34, 0x4e, 0x02 }, + { 0x8e, 0xba, 0x2f, 0x87, 0x4f, 0x1a, 0xe8, 0x40, 0x41, 0x90, 0x3c, 0x7c, 0x42, 0x53, 0xc8, 0x22, 0x92, 0x53, 0x0f, 0xc8, 0x50, 0x95, 0x50, 0xbf, 0xdc, 0x34, 0xc9, 0x5c, 0x7e, 0x28, 0x89, 0xd5, 0x65, 0x0b, 0x0a, 0xd8, 0xcb, 0x98, 0x8e, 0x5c, 0x48, 0x94, 0xcb, 0x87, 0xfb, 0xfb, 0xb1, 0x96, 0x12, 0xea, 0x93, 0xcc, 0xc4, 0xc5, 0xca, 0xd1, 0x71, 0x58, 0xb9, 0x76, 0x34, 0x64, 0xb4, 0x92 }, + { 0x16, 0xf7, 0x12, 0xea, 0xa1, 0xb7, 0xc6, 0x35, 0x47, 0x19, 0xa8, 0xe7, 0xdb, 0xdf, 0xaf, 0x55, 0xe4, 0x06, 0x3a, 0x4d, 0x27, 0x7d, 0x94, 0x75, 0x50, 0x01, 0x9b, 0x38, 0xdf, 0xb5, 0x64, 0x83, 0x09, 0x11, 0x05, 0x7d, 0x50, 0x50, 0x61, 0x36, 0xe2, 0x39, 0x4c, 0x3b, 0x28, 0x94, 0x5c, 0xc9, 0x64, 0x96, 0x7d, 0x54, 0xe3, 0x00, 0x0c, 0x21, 0x81, 0x62, 0x6c, 0xfb, 0x9b, 0x73, 0xef, 0xd2 }, + { 0xc3, 0x96, 0x39, 0xe7, 0xd5, 0xc7, 0xfb, 0x8c, 0xdd, 0x0f, 0xd3, 0xe6, 0xa5, 0x20, 0x96, 0x03, 0x94, 0x37, 0x12, 0x2f, 0x21, 0xc7, 0x8f, 0x16, 0x79, 0xce, 0xa9, 0xd7, 0x8a, 0x73, 0x4c, 0x56, 0xec, 0xbe, 0xb2, 0x86, 0x54, 0xb4, 0xf1, 0x8e, 0x34, 0x2c, 0x33, 0x1f, 0x6f, 0x72, 0x29, 0xec, 0x4b, 0x4b, 0xc2, 0x81, 0xb2, 0xd8, 0x0a, 0x6e, 0xb5, 0x00, 0x43, 0xf3, 0x17, 0x96, 0xc8, 0x8c }, + { 0x72, 0xd0, 0x81, 0xaf, 0x99, 0xf8, 0xa1, 0x73, 0xdc, 0xc9, 0xa0, 0xac, 0x4e, 0xb3, 0x55, 0x74, 0x05, 0x63, 0x9a, 0x29, 0x08, 0x4b, 0x54, 0xa4, 0x01, 0x72, 0x91, 0x2a, 0x2f, 0x8a, 0x39, 0x51, 0x29, 0xd5, 0x53, 0x6f, 0x09, 0x18, 0xe9, 0x02, 0xf9, 0xe8, 0xfa, 0x60, 0x00, 0x99, 0x5f, 0x41, 0x68, 0xdd, 0xc5, 0xf8, 0x93, 0x01, 0x1b, 0xe6, 0xa0, 0xdb, 0xc9, 0xb8, 0xa1, 0xa3, 0xf5, 0xbb }, + { 0xc1, 0x1a, 0xa8, 0x1e, 0x5e, 0xfd, 0x24, 0xd5, 0xfc, 0x27, 0xee, 0x58, 0x6c, 0xfd, 0x88, 0x47, 0xfb, 0xb0, 0xe2, 0x76, 0x01, 0xcc, 0xec, 0xe5, 0xec, 0xca, 0x01, 0x98, 0xe3, 0xc7, 0x76, 0x53, 0x93, 0xbb, 0x74, 0x45, 0x7c, 0x7e, 0x7a, 0x27, 0xeb, 0x91, 0x70, 0x35, 0x0e, 0x1f, 0xb5, 0x38, 0x57, 0x17, 0x75, 0x06, 0xbe, 0x3e, 0x76, 0x2c, 0xc0, 0xf1, 0x4d, 0x8c, 0x3a, 0xfe, 0x90, 0x77 }, + { 0xc2, 0x8f, 0x21, 0x50, 0xb4, 0x52, 0xe6, 0xc0, 0xc4, 0x24, 0xbc, 0xde, 0x6f, 0x8d, 0x72, 0x00, 0x7f, 0x93, 0x10, 0xfe, 0xd7, 0xf2, 0xf8, 0x7d, 0xe0, 0xdb, 0xb6, 0x4f, 0x44, 0x79, 0xd6, 0xc1, 0x44, 0x1b, 0xa6, 0x6f, 0x44, 0xb2, 0xac, 0xce, 0xe6, 0x16, 0x09, 0x17, 0x7e, 0xd3, 0x40, 0x12, 0x8b, 0x40, 0x7e, 0xce, 0xc7, 0xc6, 0x4b, 0xbe, 0x50, 0xd6, 0x3d, 0x22, 0xd8, 0x62, 0x77, 0x27 }, + { 0xf6, 0x3d, 0x88, 0x12, 0x28, 0x77, 0xec, 0x30, 0xb8, 0xc8, 0xb0, 0x0d, 0x22, 0xe8, 0x90, 0x00, 0xa9, 0x66, 0x42, 0x61, 0x12, 0xbd, 0x44, 0x16, 0x6e, 0x2f, 0x52, 0x5b, 0x76, 0x9c, 0xcb, 0xe9, 0xb2, 0x86, 0xd4, 0x37, 0xa0, 0x12, 0x91, 0x30, 0xdd, 0xe1, 0xa8, 0x6c, 0x43, 0xe0, 0x4b, 0xed, 0xb5, 0x94, 0xe6, 0x71, 0xd9, 0x82, 0x83, 0xaf, 0xe6, 0x4c, 0xe3, 0x31, 0xde, 0x98, 0x28, 0xfd }, + { 0x34, 0x8b, 0x05, 0x32, 0x88, 0x0b, 0x88, 0xa6, 0x61, 0x4a, 0x8d, 0x74, 0x08, 0xc3, 0xf9, 0x13, 0x35, 0x7f, 0xbb, 0x60, 0xe9, 0x95, 0xc6, 0x02, 0x05, 0xbe, 0x91, 0x39, 0xe7, 0x49, 0x98, 0xae, 0xde, 0x7f, 0x45, 0x81, 0xe4, 0x2f, 0x6b, 0x52, 0x69, 0x8f, 0x7f, 0xa1, 0x21, 0x97, 0x08, 0xc1, 0x44, 0x98, 0x06, 0x7f, 0xd1, 0xe0, 0x95, 0x02, 0xde, 0x83, 0xa7, 0x7d, 0xd2, 0x81, 0x15, 0x0c }, + { 0x51, 0x33, 0xdc, 0x8b, 0xef, 0x72, 0x53, 0x59, 0xdf, 0xf5, 0x97, 0x92, 0xd8, 0x5e, 0xaf, 0x75, 0xb7, 0xe1, 0xdc, 0xd1, 0x97, 0x8b, 0x01, 0xc3, 0x5b, 0x1b, 0x85, 0xfc, 0xeb, 0xc6, 0x33, 0x88, 0xad, 0x99, 0xa1, 0x7b, 0x63, 0x46, 0xa2, 0x17, 0xdc, 0x1a, 0x96, 0x22, 0xeb, 0xd1, 0x22, 0xec, 0xf6, 0x91, 0x3c, 0x4d, 0x31, 0xa6, 0xb5, 0x2a, 0x69, 0x5b, 0x86, 0xaf, 0x00, 0xd7, 0x41, 0xa0 }, + { 0x27, 0x53, 0xc4, 0xc0, 0xe9, 0x8e, 0xca, 0xd8, 0x06, 0xe8, 0x87, 0x80, 0xec, 0x27, 0xfc, 0xcd, 0x0f, 0x5c, 0x1a, 0xb5, 0x47, 0xf9, 0xe4, 0xbf, 0x16, 0x59, 0xd1, 0x92, 0xc2, 0x3a, 0xa2, 0xcc, 0x97, 0x1b, 0x58, 0xb6, 0x80, 0x25, 0x80, 0xba, 0xef, 0x8a, 0xdc, 0x3b, 0x77, 0x6e, 0xf7, 0x08, 0x6b, 0x25, 0x45, 0xc2, 0x98, 0x7f, 0x34, 0x8e, 0xe3, 0x71, 0x9c, 0xde, 0xf2, 0x58, 0xc4, 0x03 }, + { 0xb1, 0x66, 0x35, 0x73, 0xce, 0x4b, 0x9d, 0x8c, 0xae, 0xfc, 0x86, 0x50, 0x12, 0xf3, 0xe3, 0x97, 0x14, 0xb9, 0x89, 0x8a, 0x5d, 0xa6, 0xce, 0x17, 0xc2, 0x5a, 0x6a, 0x47, 0x93, 0x1a, 0x9d, 0xdb, 0x9b, 0xbe, 0x98, 0xad, 0xaa, 0x55, 0x3b, 0xee, 0xd4, 0x36, 0xe8, 0x95, 0x78, 0x45, 0x54, 0x16, 0xc2, 0xa5, 0x2a, 0x52, 0x5c, 0xf2, 0x86, 0x2b, 0x8d, 0x1d, 0x49, 0xa2, 0x53, 0x1b, 0x73, 0x91 }, + { 0x64, 0xf5, 0x8b, 0xd6, 0xbf, 0xc8, 0x56, 0xf5, 0xe8, 0x73, 0xb2, 0xa2, 0x95, 0x6e, 0xa0, 0xed, 0xa0, 0xd6, 0xdb, 0x0d, 0xa3, 0x9c, 0x8c, 0x7f, 0xc6, 0x7c, 0x9f, 0x9f, 0xee, 0xfc, 0xff, 0x30, 0x72, 0xcd, 0xf9, 0xe6, 0xea, 0x37, 0xf6, 0x9a, 0x44, 0xf0, 0xc6, 0x1a, 0xa0, 0xda, 0x36, 0x93, 0xc2, 0xdb, 0x5b, 0x54, 0x96, 0x0c, 0x02, 0x81, 0xa0, 0x88, 0x15, 0x1d, 0xb4, 0x2b, 0x11, 0xe8 }, + { 0x07, 0x64, 0xc7, 0xbe, 0x28, 0x12, 0x5d, 0x90, 0x65, 0xc4, 0xb9, 0x8a, 0x69, 0xd6, 0x0a, 0xed, 0xe7, 0x03, 0x54, 0x7c, 0x66, 0xa1, 0x2e, 0x17, 0xe1, 0xc6, 0x18, 0x99, 0x41, 0x32, 0xf5, 0xef, 0x82, 0x48, 0x2c, 0x1e, 0x3f, 0xe3, 0x14, 0x6c, 0xc6, 0x53, 0x76, 0xcc, 0x10, 0x9f, 0x01, 0x38, 0xed, 0x9a, 0x80, 0xe4, 0x9f, 0x1f, 0x3c, 0x7d, 0x61, 0x0d, 0x2f, 0x24, 0x32, 0xf2, 0x06, 0x05 }, + { 0xf7, 0x48, 0x78, 0x43, 0x98, 0xa2, 0xff, 0x03, 0xeb, 0xeb, 0x07, 0xe1, 0x55, 0xe6, 0x61, 0x16, 0xa8, 0x39, 0x74, 0x1a, 0x33, 0x6e, 0x32, 0xda, 0x71, 0xec, 0x69, 0x60, 0x01, 0xf0, 0xad, 0x1b, 0x25, 0xcd, 0x48, 0xc6, 0x9c, 0xfc, 0xa7, 0x26, 0x5e, 0xca, 0x1d, 0xd7, 0x19, 0x04, 0xa0, 0xce, 0x74, 0x8a, 0xc4, 0x12, 0x4f, 0x35, 0x71, 0x07, 0x6d, 0xfa, 0x71, 0x16, 0xa9, 0xcf, 0x00, 0xe9 }, + { 0x3f, 0x0d, 0xbc, 0x01, 0x86, 0xbc, 0xeb, 0x6b, 0x78, 0x5b, 0xa7, 0x8d, 0x2a, 0x2a, 0x01, 0x3c, 0x91, 0x0b, 0xe1, 0x57, 0xbd, 0xaf, 0xfa, 0xe8, 0x1b, 0xb6, 0x66, 0x3b, 0x1a, 0x73, 0x72, 0x2f, 0x7f, 0x12, 0x28, 0x79, 0x5f, 0x3e, 0xca, 0xda, 0x87, 0xcf, 0x6e, 0xf0, 0x07, 0x84, 0x74, 0xaf, 0x73, 0xf3, 0x1e, 0xca, 0x0c, 0xc2, 0x00, 0xed, 0x97, 0x5b, 0x68, 0x93, 0xf7, 0x61, 0xcb, 0x6d }, + { 0xd4, 0x76, 0x2c, 0xd4, 0x59, 0x98, 0x76, 0xca, 0x75, 0xb2, 0xb8, 0xfe, 0x24, 0x99, 0x44, 0xdb, 0xd2, 0x7a, 0xce, 0x74, 0x1f, 0xda, 0xb9, 0x36, 0x16, 0xcb, 0xc6, 0xe4, 0x25, 0x46, 0x0f, 0xeb, 0x51, 0xd4, 0xe7, 0xad, 0xcc, 0x38, 0x18, 0x0e, 0x7f, 0xc4, 0x7c, 0x89, 0x02, 0x4a, 0x7f, 0x56, 0x19, 0x1a, 0xdb, 0x87, 0x8d, 0xfd, 0xe4, 0xea, 0xd6, 0x22, 0x23, 0xf5, 0xa2, 0x61, 0x0e, 0xfe }, + { 0xcd, 0x36, 0xb3, 0xd5, 0xb4, 0xc9, 0x1b, 0x90, 0xfc, 0xbb, 0xa7, 0x95, 0x13, 0xcf, 0xee, 0x19, 0x07, 0xd8, 0x64, 0x5a, 0x16, 0x2a, 0xfd, 0x0c, 0xd4, 0xcf, 0x41, 0x92, 0xd4, 0xa5, 0xf4, 0xc8, 0x92, 0x18, 0x3a, 0x8e, 0xac, 0xdb, 0x2b, 0x6b, 0x6a, 0x9d, 0x9a, 0xa8, 0xc1, 0x1a, 0xc1, 0xb2, 0x61, 0xb3, 0x80, 0xdb, 0xee, 0x24, 0xca, 0x46, 0x8f, 0x1b, 0xfd, 0x04, 0x3c, 0x58, 0xee, 0xfe }, + { 0x98, 0x59, 0x34, 0x52, 0x28, 0x16, 0x61, 0xa5, 0x3c, 0x48, 0xa9, 0xd8, 0xcd, 0x79, 0x08, 0x26, 0xc1, 0xa1, 0xce, 0x56, 0x77, 0x38, 0x05, 0x3d, 0x0b, 0xee, 0x4a, 0x91, 0xa3, 0xd5, 0xbd, 0x92, 0xee, 0xfd, 0xba, 0xbe, 0xbe, 0x32, 0x04, 0xf2, 0x03, 0x1c, 0xa5, 0xf7, 0x81, 0xbd, 0xa9, 0x9e, 0xf5, 0xd8, 0xae, 0x56, 0xe5, 0xb0, 0x4a, 0x9e, 0x1e, 0xcd, 0x21, 0xb0, 0xeb, 0x05, 0xd3, 0xe1 }, + { 0x77, 0x1f, 0x57, 0xdd, 0x27, 0x75, 0xcc, 0xda, 0xb5, 0x59, 0x21, 0xd3, 0xe8, 0xe3, 0x0c, 0xcf, 0x48, 0x4d, 0x61, 0xfe, 0x1c, 0x1b, 0x9c, 0x2a, 0xe8, 0x19, 0xd0, 0xfb, 0x2a, 0x12, 0xfa, 0xb9, 0xbe, 0x70, 0xc4, 0xa7, 0xa1, 0x38, 0xda, 0x84, 0xe8, 0x28, 0x04, 0x35, 0xda, 0xad, 0xe5, 0xbb, 0xe6, 0x6a, 0xf0, 0x83, 0x6a, 0x15, 0x4f, 0x81, 0x7f, 0xb1, 0x7f, 0x33, 0x97, 0xe7, 0x25, 0xa3 }, + { 0xc6, 0x08, 0x97, 0xc6, 0xf8, 0x28, 0xe2, 0x1f, 0x16, 0xfb, 0xb5, 0xf1, 0x5b, 0x32, 0x3f, 0x87, 0xb6, 0xc8, 0x95, 0x5e, 0xab, 0xf1, 0xd3, 0x80, 0x61, 0xf7, 0x07, 0xf6, 0x08, 0xab, 0xdd, 0x99, 0x3f, 0xac, 0x30, 0x70, 0x63, 0x3e, 0x28, 0x6c, 0xf8, 0x33, 0x9c, 0xe2, 0x95, 0xdd, 0x35, 0x2d, 0xf4, 0xb4, 0xb4, 0x0b, 0x2f, 0x29, 0xda, 0x1d, 0xd5, 0x0b, 0x3a, 0x05, 0xd0, 0x79, 0xe6, 0xbb }, + { 0x82, 0x10, 0xcd, 0x2c, 0x2d, 0x3b, 0x13, 0x5c, 0x2c, 0xf0, 0x7f, 0xa0, 0xd1, 0x43, 0x3c, 0xd7, 0x71, 0xf3, 0x25, 0xd0, 0x75, 0xc6, 0x46, 0x9d, 0x9c, 0x7f, 0x1b, 0xa0, 0x94, 0x3c, 0xd4, 0xab, 0x09, 0x80, 0x8c, 0xab, 0xf4, 0xac, 0xb9, 0xce, 0x5b, 0xb8, 0x8b, 0x49, 0x89, 0x29, 0xb4, 0xb8, 0x47, 0xf6, 0x81, 0xad, 0x2c, 0x49, 0x0d, 0x04, 0x2d, 0xb2, 0xae, 0xc9, 0x42, 0x14, 0xb0, 0x6b }, + { 0x1d, 0x4e, 0xdf, 0xff, 0xd8, 0xfd, 0x80, 0xf7, 0xe4, 0x10, 0x78, 0x40, 0xfa, 0x3a, 0xa3, 0x1e, 0x32, 0x59, 0x84, 0x91, 0xe4, 0xaf, 0x70, 0x13, 0xc1, 0x97, 0xa6, 0x5b, 0x7f, 0x36, 0xdd, 0x3a, 0xc4, 0xb4, 0x78, 0x45, 0x61, 0x11, 0xcd, 0x43, 0x09, 0xd9, 0x24, 0x35, 0x10, 0x78, 0x2f, 0xa3, 0x1b, 0x7c, 0x4c, 0x95, 0xfa, 0x95, 0x15, 0x20, 0xd0, 0x20, 0xeb, 0x7e, 0x5c, 0x36, 0xe4, 0xef }, + { 0xaf, 0x8e, 0x6e, 0x91, 0xfa, 0xb4, 0x6c, 0xe4, 0x87, 0x3e, 0x1a, 0x50, 0xa8, 0xef, 0x44, 0x8c, 0xc2, 0x91, 0x21, 0xf7, 0xf7, 0x4d, 0xee, 0xf3, 0x4a, 0x71, 0xef, 0x89, 0xcc, 0x00, 0xd9, 0x27, 0x4b, 0xc6, 0xc2, 0x45, 0x4b, 0xbb, 0x32, 0x30, 0xd8, 0xb2, 0xec, 0x94, 0xc6, 0x2b, 0x1d, 0xec, 0x85, 0xf3, 0x59, 0x3b, 0xfa, 0x30, 0xea, 0x6f, 0x7a, 0x44, 0xd7, 0xc0, 0x94, 0x65, 0xa2, 0x53 }, + { 0x29, 0xfd, 0x38, 0x4e, 0xd4, 0x90, 0x6f, 0x2d, 0x13, 0xaa, 0x9f, 0xe7, 0xaf, 0x90, 0x59, 0x90, 0x93, 0x8b, 0xed, 0x80, 0x7f, 0x18, 0x32, 0x45, 0x4a, 0x37, 0x2a, 0xb4, 0x12, 0xee, 0xa1, 0xf5, 0x62, 0x5a, 0x1f, 0xcc, 0x9a, 0xc8, 0x34, 0x3b, 0x7c, 0x67, 0xc5, 0xab, 0xa6, 0xe0, 0xb1, 0xcc, 0x46, 0x44, 0x65, 0x49, 0x13, 0x69, 0x2c, 0x6b, 0x39, 0xeb, 0x91, 0x87, 0xce, 0xac, 0xd3, 0xec }, + { 0xa2, 0x68, 0xc7, 0x88, 0x5d, 0x98, 0x74, 0xa5, 0x1c, 0x44, 0xdf, 0xfe, 0xd8, 0xea, 0x53, 0xe9, 0x4f, 0x78, 0x45, 0x6e, 0x0b, 0x2e, 0xd9, 0x9f, 0xf5, 0xa3, 0x92, 0x47, 0x60, 0x81, 0x38, 0x26, 0xd9, 0x60, 0xa1, 0x5e, 0xdb, 0xed, 0xbb, 0x5d, 0xe5, 0x22, 0x6b, 0xa4, 0xb0, 0x74, 0xe7, 0x1b, 0x05, 0xc5, 0x5b, 0x97, 0x56, 0xbb, 0x79, 0xe5, 0x5c, 0x02, 0x75, 0x4c, 0x2c, 0x7b, 0x6c, 0x8a }, + { 0x0c, 0xf8, 0x54, 0x54, 0x88, 0xd5, 0x6a, 0x86, 0x81, 0x7c, 0xd7, 0xec, 0xb1, 0x0f, 0x71, 0x16, 0xb7, 0xea, 0x53, 0x0a, 0x45, 0xb6, 0xea, 0x49, 0x7b, 0x6c, 0x72, 0xc9, 0x97, 0xe0, 0x9e, 0x3d, 0x0d, 0xa8, 0x69, 0x8f, 0x46, 0xbb, 0x00, 0x6f, 0xc9, 0x77, 0xc2, 0xcd, 0x3d, 0x11, 0x77, 0x46, 0x3a, 0xc9, 0x05, 0x7f, 0xdd, 0x16, 0x62, 0xc8, 0x5d, 0x0c, 0x12, 0x64, 0x43, 0xc1, 0x04, 0x73 }, + { 0xb3, 0x96, 0x14, 0x26, 0x8f, 0xdd, 0x87, 0x81, 0x51, 0x5e, 0x2c, 0xfe, 0xbf, 0x89, 0xb4, 0xd5, 0x40, 0x2b, 0xab, 0x10, 0xc2, 0x26, 0xe6, 0x34, 0x4e, 0x6b, 0x9a, 0xe0, 0x00, 0xfb, 0x0d, 0x6c, 0x79, 0xcb, 0x2f, 0x3e, 0xc8, 0x0e, 0x80, 0xea, 0xeb, 0x19, 0x80, 0xd2, 0xf8, 0x69, 0x89, 0x16, 0xbd, 0x2e, 0x9f, 0x74, 0x72, 0x36, 0x65, 0x51, 0x16, 0x64, 0x9c, 0xd3, 0xca, 0x23, 0xa8, 0x37 }, + { 0x74, 0xbe, 0xf0, 0x92, 0xfc, 0x6f, 0x1e, 0x5d, 0xba, 0x36, 0x63, 0xa3, 0xfb, 0x00, 0x3b, 0x2a, 0x5b, 0xa2, 0x57, 0x49, 0x65, 0x36, 0xd9, 0x9f, 0x62, 0xb9, 0xd7, 0x3f, 0x8f, 0x9e, 0xb3, 0xce, 0x9f, 0xf3, 0xee, 0xc7, 0x09, 0xeb, 0x88, 0x36, 0x55, 0xec, 0x9e, 0xb8, 0x96, 0xb9, 0x12, 0x8f, 0x2a, 0xfc, 0x89, 0xcf, 0x7d, 0x1a, 0xb5, 0x8a, 0x72, 0xf4, 0xa3, 0xbf, 0x03, 0x4d, 0x2b, 0x4a }, + { 0x3a, 0x98, 0x8d, 0x38, 0xd7, 0x56, 0x11, 0xf3, 0xef, 0x38, 0xb8, 0x77, 0x49, 0x80, 0xb3, 0x3e, 0x57, 0x3b, 0x6c, 0x57, 0xbe, 0xe0, 0x46, 0x9b, 0xa5, 0xee, 0xd9, 0xb4, 0x4f, 0x29, 0x94, 0x5e, 0x73, 0x47, 0x96, 0x7f, 0xba, 0x2c, 0x16, 0x2e, 0x1c, 0x3b, 0xe7, 0xf3, 0x10, 0xf2, 0xf7, 0x5e, 0xe2, 0x38, 0x1e, 0x7b, 0xfd, 0x6b, 0x3f, 0x0b, 0xae, 0xa8, 0xd9, 0x5d, 0xfb, 0x1d, 0xaf, 0xb1 }, + { 0x58, 0xae, 0xdf, 0xce, 0x6f, 0x67, 0xdd, 0xc8, 0x5a, 0x28, 0xc9, 0x92, 0xf1, 0xc0, 0xbd, 0x09, 0x69, 0xf0, 0x41, 0xe6, 0x6f, 0x1e, 0xe8, 0x80, 0x20, 0xa1, 0x25, 0xcb, 0xfc, 0xfe, 0xbc, 0xd6, 0x17, 0x09, 0xc9, 0xc4, 0xeb, 0xa1, 0x92, 0xc1, 0x5e, 0x69, 0xf0, 0x20, 0xd4, 0x62, 0x48, 0x60, 0x19, 0xfa, 0x8d, 0xea, 0x0c, 0xd7, 0xa4, 0x29, 0x21, 0xa1, 0x9d, 0x2f, 0xe5, 0x46, 0xd4, 0x3d }, + { 0x93, 0x47, 0xbd, 0x29, 0x14, 0x73, 0xe6, 0xb4, 0xe3, 0x68, 0x43, 0x7b, 0x8e, 0x56, 0x1e, 0x06, 0x5f, 0x64, 0x9a, 0x6d, 0x8a, 0xda, 0x47, 0x9a, 0xd0, 0x9b, 0x19, 0x99, 0xa8, 0xf2, 0x6b, 0x91, 0xcf, 0x61, 0x20, 0xfd, 0x3b, 0xfe, 0x01, 0x4e, 0x83, 0xf2, 0x3a, 0xcf, 0xa4, 0xc0, 0xad, 0x7b, 0x37, 0x12, 0xb2, 0xc3, 0xc0, 0x73, 0x32, 0x70, 0x66, 0x31, 0x12, 0xcc, 0xd9, 0x28, 0x5c, 0xd9 }, + { 0xb3, 0x21, 0x63, 0xe7, 0xc5, 0xdb, 0xb5, 0xf5, 0x1f, 0xdc, 0x11, 0xd2, 0xea, 0xc8, 0x75, 0xef, 0xbb, 0xcb, 0x7e, 0x76, 0x99, 0x09, 0x0a, 0x7e, 0x7f, 0xf8, 0xa8, 0xd5, 0x07, 0x95, 0xaf, 0x5d, 0x74, 0xd9, 0xff, 0x98, 0x54, 0x3e, 0xf8, 0xcd, 0xf8, 0x9a, 0xc1, 0x3d, 0x04, 0x85, 0x27, 0x87, 0x56, 0xe0, 0xef, 0x00, 0xc8, 0x17, 0x74, 0x56, 0x61, 0xe1, 0xd5, 0x9f, 0xe3, 0x8e, 0x75, 0x37 }, + { 0x10, 0x85, 0xd7, 0x83, 0x07, 0xb1, 0xc4, 0xb0, 0x08, 0xc5, 0x7a, 0x2e, 0x7e, 0x5b, 0x23, 0x46, 0x58, 0xa0, 0xa8, 0x2e, 0x4f, 0xf1, 0xe4, 0xaa, 0xac, 0x72, 0xb3, 0x12, 0xfd, 0xa0, 0xfe, 0x27, 0xd2, 0x33, 0xbc, 0x5b, 0x10, 0xe9, 0xcc, 0x17, 0xfd, 0xc7, 0x69, 0x7b, 0x54, 0x0c, 0x7d, 0x95, 0xeb, 0x21, 0x5a, 0x19, 0xa1, 0xa0, 0xe2, 0x0e, 0x1a, 0xbf, 0xa1, 0x26, 0xef, 0xd5, 0x68, 0xc7 }, + { 0x4e, 0x5c, 0x73, 0x4c, 0x7d, 0xde, 0x01, 0x1d, 0x83, 0xea, 0xc2, 0xb7, 0x34, 0x7b, 0x37, 0x35, 0x94, 0xf9, 0x2d, 0x70, 0x91, 0xb9, 0xca, 0x34, 0xcb, 0x9c, 0x6f, 0x39, 0xbd, 0xf5, 0xa8, 0xd2, 0xf1, 0x34, 0x37, 0x9e, 0x16, 0xd8, 0x22, 0xf6, 0x52, 0x21, 0x70, 0xcc, 0xf2, 0xdd, 0xd5, 0x5c, 0x84, 0xb9, 0xe6, 0xc6, 0x4f, 0xc9, 0x27, 0xac, 0x4c, 0xf8, 0xdf, 0xb2, 0xa1, 0x77, 0x01, 0xf2 }, + { 0x69, 0x5d, 0x83, 0xbd, 0x99, 0x0a, 0x11, 0x17, 0xb3, 0xd0, 0xce, 0x06, 0xcc, 0x88, 0x80, 0x27, 0xd1, 0x2a, 0x05, 0x4c, 0x26, 0x77, 0xfd, 0x82, 0xf0, 0xd4, 0xfb, 0xfc, 0x93, 0x57, 0x55, 0x23, 0xe7, 0x99, 0x1a, 0x5e, 0x35, 0xa3, 0x75, 0x2e, 0x9b, 0x70, 0xce, 0x62, 0x99, 0x2e, 0x26, 0x8a, 0x87, 0x77, 0x44, 0xcd, 0xd4, 0x35, 0xf5, 0xf1, 0x30, 0x86, 0x9c, 0x9a, 0x20, 0x74, 0xb3, 0x38 }, + { 0xa6, 0x21, 0x37, 0x43, 0x56, 0x8e, 0x3b, 0x31, 0x58, 0xb9, 0x18, 0x43, 0x01, 0xf3, 0x69, 0x08, 0x47, 0x55, 0x4c, 0x68, 0x45, 0x7c, 0xb4, 0x0f, 0xc9, 0xa4, 0xb8, 0xcf, 0xd8, 0xd4, 0xa1, 0x18, 0xc3, 0x01, 0xa0, 0x77, 0x37, 0xae, 0xda, 0x0f, 0x92, 0x9c, 0x68, 0x91, 0x3c, 0x5f, 0x51, 0xc8, 0x03, 0x94, 0xf5, 0x3b, 0xff, 0x1c, 0x3e, 0x83, 0xb2, 0xe4, 0x0c, 0xa9, 0x7e, 0xba, 0x9e, 0x15 }, + { 0xd4, 0x44, 0xbf, 0xa2, 0x36, 0x2a, 0x96, 0xdf, 0x21, 0x3d, 0x07, 0x0e, 0x33, 0xfa, 0x84, 0x1f, 0x51, 0x33, 0x4e, 0x4e, 0x76, 0x86, 0x6b, 0x81, 0x39, 0xe8, 0xaf, 0x3b, 0xb3, 0x39, 0x8b, 0xe2, 0xdf, 0xad, 0xdc, 0xbc, 0x56, 0xb9, 0x14, 0x6d, 0xe9, 0xf6, 0x81, 0x18, 0xdc, 0x58, 0x29, 0xe7, 0x4b, 0x0c, 0x28, 0xd7, 0x71, 0x19, 0x07, 0xb1, 0x21, 0xf9, 0x16, 0x1c, 0xb9, 0x2b, 0x69, 0xa9 }, + { 0x14, 0x27, 0x09, 0xd6, 0x2e, 0x28, 0xfc, 0xcc, 0xd0, 0xaf, 0x97, 0xfa, 0xd0, 0xf8, 0x46, 0x5b, 0x97, 0x1e, 0x82, 0x20, 0x1d, 0xc5, 0x10, 0x70, 0xfa, 0xa0, 0x37, 0x2a, 0xa4, 0x3e, 0x92, 0x48, 0x4b, 0xe1, 0xc1, 0xe7, 0x3b, 0xa1, 0x09, 0x06, 0xd5, 0xd1, 0x85, 0x3d, 0xb6, 0xa4, 0x10, 0x6e, 0x0a, 0x7b, 0xf9, 0x80, 0x0d, 0x37, 0x3d, 0x6d, 0xee, 0x2d, 0x46, 0xd6, 0x2e, 0xf2, 0xa4, 0x61 }, + }; + unsigned char inp[1000], out[1000]; + unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f }; + unsigned long ilen, klen = sizeof(key), mlen = 64; + blake2bmac_state st; + + for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; + + for (ilen = 0; ilen < 256; ilen++) { + const unsigned char *mac = tests[ilen]; + unsigned long olen = mlen; + /* process piece by piece */ + if (ilen > 15) { + blake2bmac_init(&st, olen, key, klen); + blake2bmac_process(&st, (unsigned char*)inp, 5); + blake2bmac_process(&st, (unsigned char*)inp + 5, 4); + blake2bmac_process(&st, (unsigned char*)inp + 9, 3); + blake2bmac_process(&st, (unsigned char*)inp + 12, 2); + blake2bmac_process(&st, (unsigned char*)inp + 14, 1); + blake2bmac_process(&st, (unsigned char*)inp + 15, ilen - 15); + blake2bmac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + /* process in one go */ + blake2bmac_init(&st, olen, key, klen); + blake2bmac_process(&st, (unsigned char*)inp, ilen); + blake2bmac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2B MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2smac.c b/deps/libtomcrypt/src/mac/blake2/blake2smac.c new file mode 100644 index 0000000..f42c7ae --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2smac.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +/** + Initialize an BLAKE2S MAC context. + @param st The BLAKE2S MAC state + @param outlen The size of the MAC output (octets) + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + return blake2s_init(st, outlen, key, keylen); +} + +/** + Process data through BLAKE2S MAC + @param st The BLAKE2S MAC state + @param in The data to send through HMAC + @param inlen The length of the data to HMAC (octets) + @return CRYPT_OK if successful +*/ +int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen) +{ + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + return blake2s_process(st, in, inlen); +} + +/** + Terminate a BLAKE2S MAC session + @param st The BLAKE2S MAC state + @param mac [out] The destination of the BLAKE2S MAC authentication tag + @param maclen [in/out] The max size and resulting size of the BLAKE2S MAC authentication tag + @return CRYPT_OK if successful +*/ +int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + LTC_ARGCHK(*maclen >= st->blake2s.outlen); + + *maclen = st->blake2s.outlen; + return blake2s_done(st, mac); +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2smac_file.c b/deps/libtomcrypt/src/mac/blake2/blake2smac_file.c new file mode 100644 index 0000000..bcfbe06 --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2smac_file.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +/** + BLAKE2S MAC a file + @param fname The name of the file you wish to BLAKE2S MAC + @param key The secret key + @param keylen The length of the secret key + @param mac [out] The BLAKE2S MAC authentication tag + @param maclen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); + return CRYPT_NOP; +#else + blake2smac_state st; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = blake2smac_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = blake2smac_done(&st, mac, maclen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2smac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2smac_memory.c b/deps/libtomcrypt/src/mac/blake2/blake2smac_memory.c new file mode 100644 index 0000000..755267b --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2smac_memory.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +/** + BLAKE2S MAC a block of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to BLAKE2S MAC + @param inlen The length of the data to BLAKE2S MAC (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) +{ + blake2smac_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = blake2smac_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + err = blake2smac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2smac_state)); +#endif + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c b/deps/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c new file mode 100644 index 0000000..34fb5e1 --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2smac_memory_multi.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" +#include + +#ifdef LTC_BLAKE2SMAC + +/** + BLAKE2S MAC multiple blocks of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @param in The data to BLAKE2S MAC + @param inlen The length of the data to BLAKE2S MAC (octets) + @param ... tuples of (data,len) pairs to BLAKE2S MAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) +{ + blake2smac_state st; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + va_start(args, inlen); + curptr = in; + curlen = inlen; + if ((err = blake2smac_init(&st, *maclen, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + for (;;) { + if ((err = blake2smac_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) break; + curlen = va_arg(args, unsigned long); + } + err = blake2smac_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(blake2smac_state)); +#endif + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/blake2/blake2smac_test.c b/deps/libtomcrypt/src/mac/blake2/blake2smac_test.c new file mode 100644 index 0000000..acfb030 --- /dev/null +++ b/deps/libtomcrypt/src/mac/blake2/blake2smac_test.c @@ -0,0 +1,304 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BLAKE2SMAC + +int blake2smac_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const unsigned char tests[256][32] = { + /* source: https://github.com/BLAKE2/BLAKE2/blob/master/testvectors/blake2s-kat.txt */ + { 0x48, 0xa8, 0x99, 0x7d, 0xa4, 0x07, 0x87, 0x6b, 0x3d, 0x79, 0xc0, 0xd9, 0x23, 0x25, 0xad, 0x3b, 0x89, 0xcb, 0xb7, 0x54, 0xd8, 0x6a, 0xb7, 0x1a, 0xee, 0x04, 0x7a, 0xd3, 0x45, 0xfd, 0x2c, 0x49 }, + { 0x40, 0xd1, 0x5f, 0xee, 0x7c, 0x32, 0x88, 0x30, 0x16, 0x6a, 0xc3, 0xf9, 0x18, 0x65, 0x0f, 0x80, 0x7e, 0x7e, 0x01, 0xe1, 0x77, 0x25, 0x8c, 0xdc, 0x0a, 0x39, 0xb1, 0x1f, 0x59, 0x80, 0x66, 0xf1 }, + { 0x6b, 0xb7, 0x13, 0x00, 0x64, 0x4c, 0xd3, 0x99, 0x1b, 0x26, 0xcc, 0xd4, 0xd2, 0x74, 0xac, 0xd1, 0xad, 0xea, 0xb8, 0xb1, 0xd7, 0x91, 0x45, 0x46, 0xc1, 0x19, 0x8b, 0xbe, 0x9f, 0xc9, 0xd8, 0x03 }, + { 0x1d, 0x22, 0x0d, 0xbe, 0x2e, 0xe1, 0x34, 0x66, 0x1f, 0xdf, 0x6d, 0x9e, 0x74, 0xb4, 0x17, 0x04, 0x71, 0x05, 0x56, 0xf2, 0xf6, 0xe5, 0xa0, 0x91, 0xb2, 0x27, 0x69, 0x74, 0x45, 0xdb, 0xea, 0x6b }, + { 0xf6, 0xc3, 0xfb, 0xad, 0xb4, 0xcc, 0x68, 0x7a, 0x00, 0x64, 0xa5, 0xbe, 0x6e, 0x79, 0x1b, 0xec, 0x63, 0xb8, 0x68, 0xad, 0x62, 0xfb, 0xa6, 0x1b, 0x37, 0x57, 0xef, 0x9c, 0xa5, 0x2e, 0x05, 0xb2 }, + { 0x49, 0xc1, 0xf2, 0x11, 0x88, 0xdf, 0xd7, 0x69, 0xae, 0xa0, 0xe9, 0x11, 0xdd, 0x6b, 0x41, 0xf1, 0x4d, 0xab, 0x10, 0x9d, 0x2b, 0x85, 0x97, 0x7a, 0xa3, 0x08, 0x8b, 0x5c, 0x70, 0x7e, 0x85, 0x98 }, + { 0xfd, 0xd8, 0x99, 0x3d, 0xcd, 0x43, 0xf6, 0x96, 0xd4, 0x4f, 0x3c, 0xea, 0x0f, 0xf3, 0x53, 0x45, 0x23, 0x4e, 0xc8, 0xee, 0x08, 0x3e, 0xb3, 0xca, 0xda, 0x01, 0x7c, 0x7f, 0x78, 0xc1, 0x71, 0x43 }, + { 0xe6, 0xc8, 0x12, 0x56, 0x37, 0x43, 0x8d, 0x09, 0x05, 0xb7, 0x49, 0xf4, 0x65, 0x60, 0xac, 0x89, 0xfd, 0x47, 0x1c, 0xf8, 0x69, 0x2e, 0x28, 0xfa, 0xb9, 0x82, 0xf7, 0x3f, 0x01, 0x9b, 0x83, 0xa9 }, + { 0x19, 0xfc, 0x8c, 0xa6, 0x97, 0x9d, 0x60, 0xe6, 0xed, 0xd3, 0xb4, 0x54, 0x1e, 0x2f, 0x96, 0x7c, 0xed, 0x74, 0x0d, 0xf6, 0xec, 0x1e, 0xae, 0xbb, 0xfe, 0x81, 0x38, 0x32, 0xe9, 0x6b, 0x29, 0x74 }, + { 0xa6, 0xad, 0x77, 0x7c, 0xe8, 0x81, 0xb5, 0x2b, 0xb5, 0xa4, 0x42, 0x1a, 0xb6, 0xcd, 0xd2, 0xdf, 0xba, 0x13, 0xe9, 0x63, 0x65, 0x2d, 0x4d, 0x6d, 0x12, 0x2a, 0xee, 0x46, 0x54, 0x8c, 0x14, 0xa7 }, + { 0xf5, 0xc4, 0xb2, 0xba, 0x1a, 0x00, 0x78, 0x1b, 0x13, 0xab, 0xa0, 0x42, 0x52, 0x42, 0xc6, 0x9c, 0xb1, 0x55, 0x2f, 0x3f, 0x71, 0xa9, 0xa3, 0xbb, 0x22, 0xb4, 0xa6, 0xb4, 0x27, 0x7b, 0x46, 0xdd }, + { 0xe3, 0x3c, 0x4c, 0x9b, 0xd0, 0xcc, 0x7e, 0x45, 0xc8, 0x0e, 0x65, 0xc7, 0x7f, 0xa5, 0x99, 0x7f, 0xec, 0x70, 0x02, 0x73, 0x85, 0x41, 0x50, 0x9e, 0x68, 0xa9, 0x42, 0x38, 0x91, 0xe8, 0x22, 0xa3 }, + { 0xfb, 0xa1, 0x61, 0x69, 0xb2, 0xc3, 0xee, 0x10, 0x5b, 0xe6, 0xe1, 0xe6, 0x50, 0xe5, 0xcb, 0xf4, 0x07, 0x46, 0xb6, 0x75, 0x3d, 0x03, 0x6a, 0xb5, 0x51, 0x79, 0x01, 0x4a, 0xd7, 0xef, 0x66, 0x51 }, + { 0xf5, 0xc4, 0xbe, 0xc6, 0xd6, 0x2f, 0xc6, 0x08, 0xbf, 0x41, 0xcc, 0x11, 0x5f, 0x16, 0xd6, 0x1c, 0x7e, 0xfd, 0x3f, 0xf6, 0xc6, 0x56, 0x92, 0xbb, 0xe0, 0xaf, 0xff, 0xb1, 0xfe, 0xde, 0x74, 0x75 }, + { 0xa4, 0x86, 0x2e, 0x76, 0xdb, 0x84, 0x7f, 0x05, 0xba, 0x17, 0xed, 0xe5, 0xda, 0x4e, 0x7f, 0x91, 0xb5, 0x92, 0x5c, 0xf1, 0xad, 0x4b, 0xa1, 0x27, 0x32, 0xc3, 0x99, 0x57, 0x42, 0xa5, 0xcd, 0x6e }, + { 0x65, 0xf4, 0xb8, 0x60, 0xcd, 0x15, 0xb3, 0x8e, 0xf8, 0x14, 0xa1, 0xa8, 0x04, 0x31, 0x4a, 0x55, 0xbe, 0x95, 0x3c, 0xaa, 0x65, 0xfd, 0x75, 0x8a, 0xd9, 0x89, 0xff, 0x34, 0xa4, 0x1c, 0x1e, 0xea }, + { 0x19, 0xba, 0x23, 0x4f, 0x0a, 0x4f, 0x38, 0x63, 0x7d, 0x18, 0x39, 0xf9, 0xd9, 0xf7, 0x6a, 0xd9, 0x1c, 0x85, 0x22, 0x30, 0x71, 0x43, 0xc9, 0x7d, 0x5f, 0x93, 0xf6, 0x92, 0x74, 0xce, 0xc9, 0xa7 }, + { 0x1a, 0x67, 0x18, 0x6c, 0xa4, 0xa5, 0xcb, 0x8e, 0x65, 0xfc, 0xa0, 0xe2, 0xec, 0xbc, 0x5d, 0xdc, 0x14, 0xae, 0x38, 0x1b, 0xb8, 0xbf, 0xfe, 0xb9, 0xe0, 0xa1, 0x03, 0x44, 0x9e, 0x3e, 0xf0, 0x3c }, + { 0xaf, 0xbe, 0xa3, 0x17, 0xb5, 0xa2, 0xe8, 0x9c, 0x0b, 0xd9, 0x0c, 0xcf, 0x5d, 0x7f, 0xd0, 0xed, 0x57, 0xfe, 0x58, 0x5e, 0x4b, 0xe3, 0x27, 0x1b, 0x0a, 0x6b, 0xf0, 0xf5, 0x78, 0x6b, 0x0f, 0x26 }, + { 0xf1, 0xb0, 0x15, 0x58, 0xce, 0x54, 0x12, 0x62, 0xf5, 0xec, 0x34, 0x29, 0x9d, 0x6f, 0xb4, 0x09, 0x00, 0x09, 0xe3, 0x43, 0x4b, 0xe2, 0xf4, 0x91, 0x05, 0xcf, 0x46, 0xaf, 0x4d, 0x2d, 0x41, 0x24 }, + { 0x13, 0xa0, 0xa0, 0xc8, 0x63, 0x35, 0x63, 0x5e, 0xaa, 0x74, 0xca, 0x2d, 0x5d, 0x48, 0x8c, 0x79, 0x7b, 0xbb, 0x4f, 0x47, 0xdc, 0x07, 0x10, 0x50, 0x15, 0xed, 0x6a, 0x1f, 0x33, 0x09, 0xef, 0xce }, + { 0x15, 0x80, 0xaf, 0xee, 0xbe, 0xbb, 0x34, 0x6f, 0x94, 0xd5, 0x9f, 0xe6, 0x2d, 0xa0, 0xb7, 0x92, 0x37, 0xea, 0xd7, 0xb1, 0x49, 0x1f, 0x56, 0x67, 0xa9, 0x0e, 0x45, 0xed, 0xf6, 0xca, 0x8b, 0x03 }, + { 0x20, 0xbe, 0x1a, 0x87, 0x5b, 0x38, 0xc5, 0x73, 0xdd, 0x7f, 0xaa, 0xa0, 0xde, 0x48, 0x9d, 0x65, 0x5c, 0x11, 0xef, 0xb6, 0xa5, 0x52, 0x69, 0x8e, 0x07, 0xa2, 0xd3, 0x31, 0xb5, 0xf6, 0x55, 0xc3 }, + { 0xbe, 0x1f, 0xe3, 0xc4, 0xc0, 0x40, 0x18, 0xc5, 0x4c, 0x4a, 0x0f, 0x6b, 0x9a, 0x2e, 0xd3, 0xc5, 0x3a, 0xbe, 0x3a, 0x9f, 0x76, 0xb4, 0xd2, 0x6d, 0xe5, 0x6f, 0xc9, 0xae, 0x95, 0x05, 0x9a, 0x99 }, + { 0xe3, 0xe3, 0xac, 0xe5, 0x37, 0xeb, 0x3e, 0xdd, 0x84, 0x63, 0xd9, 0xad, 0x35, 0x82, 0xe1, 0x3c, 0xf8, 0x65, 0x33, 0xff, 0xde, 0x43, 0xd6, 0x68, 0xdd, 0x2e, 0x93, 0xbb, 0xdb, 0xd7, 0x19, 0x5a }, + { 0x11, 0x0c, 0x50, 0xc0, 0xbf, 0x2c, 0x6e, 0x7a, 0xeb, 0x7e, 0x43, 0x5d, 0x92, 0xd1, 0x32, 0xab, 0x66, 0x55, 0x16, 0x8e, 0x78, 0xa2, 0xde, 0xcd, 0xec, 0x33, 0x30, 0x77, 0x76, 0x84, 0xd9, 0xc1 }, + { 0xe9, 0xba, 0x8f, 0x50, 0x5c, 0x9c, 0x80, 0xc0, 0x86, 0x66, 0xa7, 0x01, 0xf3, 0x36, 0x7e, 0x6c, 0xc6, 0x65, 0xf3, 0x4b, 0x22, 0xe7, 0x3c, 0x3c, 0x04, 0x17, 0xeb, 0x1c, 0x22, 0x06, 0x08, 0x2f }, + { 0x26, 0xcd, 0x66, 0xfc, 0xa0, 0x23, 0x79, 0xc7, 0x6d, 0xf1, 0x23, 0x17, 0x05, 0x2b, 0xca, 0xfd, 0x6c, 0xd8, 0xc3, 0xa7, 0xb8, 0x90, 0xd8, 0x05, 0xf3, 0x6c, 0x49, 0x98, 0x97, 0x82, 0x43, 0x3a }, + { 0x21, 0x3f, 0x35, 0x96, 0xd6, 0xe3, 0xa5, 0xd0, 0xe9, 0x93, 0x2c, 0xd2, 0x15, 0x91, 0x46, 0x01, 0x5e, 0x2a, 0xbc, 0x94, 0x9f, 0x47, 0x29, 0xee, 0x26, 0x32, 0xfe, 0x1e, 0xdb, 0x78, 0xd3, 0x37 }, + { 0x10, 0x15, 0xd7, 0x01, 0x08, 0xe0, 0x3b, 0xe1, 0xc7, 0x02, 0xfe, 0x97, 0x25, 0x36, 0x07, 0xd1, 0x4a, 0xee, 0x59, 0x1f, 0x24, 0x13, 0xea, 0x67, 0x87, 0x42, 0x7b, 0x64, 0x59, 0xff, 0x21, 0x9a }, + { 0x3c, 0xa9, 0x89, 0xde, 0x10, 0xcf, 0xe6, 0x09, 0x90, 0x94, 0x72, 0xc8, 0xd3, 0x56, 0x10, 0x80, 0x5b, 0x2f, 0x97, 0x77, 0x34, 0xcf, 0x65, 0x2c, 0xc6, 0x4b, 0x3b, 0xfc, 0x88, 0x2d, 0x5d, 0x89 }, + { 0xb6, 0x15, 0x6f, 0x72, 0xd3, 0x80, 0xee, 0x9e, 0xa6, 0xac, 0xd1, 0x90, 0x46, 0x4f, 0x23, 0x07, 0xa5, 0xc1, 0x79, 0xef, 0x01, 0xfd, 0x71, 0xf9, 0x9f, 0x2d, 0x0f, 0x7a, 0x57, 0x36, 0x0a, 0xea }, + { 0xc0, 0x3b, 0xc6, 0x42, 0xb2, 0x09, 0x59, 0xcb, 0xe1, 0x33, 0xa0, 0x30, 0x3e, 0x0c, 0x1a, 0xbf, 0xf3, 0xe3, 0x1e, 0xc8, 0xe1, 0xa3, 0x28, 0xec, 0x85, 0x65, 0xc3, 0x6d, 0xec, 0xff, 0x52, 0x65 }, + { 0x2c, 0x3e, 0x08, 0x17, 0x6f, 0x76, 0x0c, 0x62, 0x64, 0xc3, 0xa2, 0xcd, 0x66, 0xfe, 0xc6, 0xc3, 0xd7, 0x8d, 0xe4, 0x3f, 0xc1, 0x92, 0x45, 0x7b, 0x2a, 0x4a, 0x66, 0x0a, 0x1e, 0x0e, 0xb2, 0x2b }, + { 0xf7, 0x38, 0xc0, 0x2f, 0x3c, 0x1b, 0x19, 0x0c, 0x51, 0x2b, 0x1a, 0x32, 0xde, 0xab, 0xf3, 0x53, 0x72, 0x8e, 0x0e, 0x9a, 0xb0, 0x34, 0x49, 0x0e, 0x3c, 0x34, 0x09, 0x94, 0x6a, 0x97, 0xae, 0xec }, + { 0x8b, 0x18, 0x80, 0xdf, 0x30, 0x1c, 0xc9, 0x63, 0x41, 0x88, 0x11, 0x08, 0x89, 0x64, 0x83, 0x92, 0x87, 0xff, 0x7f, 0xe3, 0x1c, 0x49, 0xea, 0x6e, 0xbd, 0x9e, 0x48, 0xbd, 0xee, 0xe4, 0x97, 0xc5 }, + { 0x1e, 0x75, 0xcb, 0x21, 0xc6, 0x09, 0x89, 0x02, 0x03, 0x75, 0xf1, 0xa7, 0xa2, 0x42, 0x83, 0x9f, 0x0b, 0x0b, 0x68, 0x97, 0x3a, 0x4c, 0x2a, 0x05, 0xcf, 0x75, 0x55, 0xed, 0x5a, 0xae, 0xc4, 0xc1 }, + { 0x62, 0xbf, 0x8a, 0x9c, 0x32, 0xa5, 0xbc, 0xcf, 0x29, 0x0b, 0x6c, 0x47, 0x4d, 0x75, 0xb2, 0xa2, 0xa4, 0x09, 0x3f, 0x1a, 0x9e, 0x27, 0x13, 0x94, 0x33, 0xa8, 0xf2, 0xb3, 0xbc, 0xe7, 0xb8, 0xd7 }, + { 0x16, 0x6c, 0x83, 0x50, 0xd3, 0x17, 0x3b, 0x5e, 0x70, 0x2b, 0x78, 0x3d, 0xfd, 0x33, 0xc6, 0x6e, 0xe0, 0x43, 0x27, 0x42, 0xe9, 0xb9, 0x2b, 0x99, 0x7f, 0xd2, 0x3c, 0x60, 0xdc, 0x67, 0x56, 0xca }, + { 0x04, 0x4a, 0x14, 0xd8, 0x22, 0xa9, 0x0c, 0xac, 0xf2, 0xf5, 0xa1, 0x01, 0x42, 0x8a, 0xdc, 0x8f, 0x41, 0x09, 0x38, 0x6c, 0xcb, 0x15, 0x8b, 0xf9, 0x05, 0xc8, 0x61, 0x8b, 0x8e, 0xe2, 0x4e, 0xc3 }, + { 0x38, 0x7d, 0x39, 0x7e, 0xa4, 0x3a, 0x99, 0x4b, 0xe8, 0x4d, 0x2d, 0x54, 0x4a, 0xfb, 0xe4, 0x81, 0xa2, 0x00, 0x0f, 0x55, 0x25, 0x26, 0x96, 0xbb, 0xa2, 0xc5, 0x0c, 0x8e, 0xbd, 0x10, 0x13, 0x47 }, + { 0x56, 0xf8, 0xcc, 0xf1, 0xf8, 0x64, 0x09, 0xb4, 0x6c, 0xe3, 0x61, 0x66, 0xae, 0x91, 0x65, 0x13, 0x84, 0x41, 0x57, 0x75, 0x89, 0xdb, 0x08, 0xcb, 0xc5, 0xf6, 0x6c, 0xa2, 0x97, 0x43, 0xb9, 0xfd }, + { 0x97, 0x06, 0xc0, 0x92, 0xb0, 0x4d, 0x91, 0xf5, 0x3d, 0xff, 0x91, 0xfa, 0x37, 0xb7, 0x49, 0x3d, 0x28, 0xb5, 0x76, 0xb5, 0xd7, 0x10, 0x46, 0x9d, 0xf7, 0x94, 0x01, 0x66, 0x22, 0x36, 0xfc, 0x03 }, + { 0x87, 0x79, 0x68, 0x68, 0x6c, 0x06, 0x8c, 0xe2, 0xf7, 0xe2, 0xad, 0xcf, 0xf6, 0x8b, 0xf8, 0x74, 0x8e, 0xdf, 0x3c, 0xf8, 0x62, 0xcf, 0xb4, 0xd3, 0x94, 0x7a, 0x31, 0x06, 0x95, 0x80, 0x54, 0xe3 }, + { 0x88, 0x17, 0xe5, 0x71, 0x98, 0x79, 0xac, 0xf7, 0x02, 0x47, 0x87, 0xec, 0xcd, 0xb2, 0x71, 0x03, 0x55, 0x66, 0xcf, 0xa3, 0x33, 0xe0, 0x49, 0x40, 0x7c, 0x01, 0x78, 0xcc, 0xc5, 0x7a, 0x5b, 0x9f }, + { 0x89, 0x38, 0x24, 0x9e, 0x4b, 0x50, 0xca, 0xda, 0xcc, 0xdf, 0x5b, 0x18, 0x62, 0x13, 0x26, 0xcb, 0xb1, 0x52, 0x53, 0xe3, 0x3a, 0x20, 0xf5, 0x63, 0x6e, 0x99, 0x5d, 0x72, 0x47, 0x8d, 0xe4, 0x72 }, + { 0xf1, 0x64, 0xab, 0xba, 0x49, 0x63, 0xa4, 0x4d, 0x10, 0x72, 0x57, 0xe3, 0x23, 0x2d, 0x90, 0xac, 0xa5, 0xe6, 0x6a, 0x14, 0x08, 0x24, 0x8c, 0x51, 0x74, 0x1e, 0x99, 0x1d, 0xb5, 0x22, 0x77, 0x56 }, + { 0xd0, 0x55, 0x63, 0xe2, 0xb1, 0xcb, 0xa0, 0xc4, 0xa2, 0xa1, 0xe8, 0xbd, 0xe3, 0xa1, 0xa0, 0xd9, 0xf5, 0xb4, 0x0c, 0x85, 0xa0, 0x70, 0xd6, 0xf5, 0xfb, 0x21, 0x06, 0x6e, 0xad, 0x5d, 0x06, 0x01 }, + { 0x03, 0xfb, 0xb1, 0x63, 0x84, 0xf0, 0xa3, 0x86, 0x6f, 0x4c, 0x31, 0x17, 0x87, 0x76, 0x66, 0xef, 0xbf, 0x12, 0x45, 0x97, 0x56, 0x4b, 0x29, 0x3d, 0x4a, 0xab, 0x0d, 0x26, 0x9f, 0xab, 0xdd, 0xfa }, + { 0x5f, 0xa8, 0x48, 0x6a, 0xc0, 0xe5, 0x29, 0x64, 0xd1, 0x88, 0x1b, 0xbe, 0x33, 0x8e, 0xb5, 0x4b, 0xe2, 0xf7, 0x19, 0x54, 0x92, 0x24, 0x89, 0x20, 0x57, 0xb4, 0xda, 0x04, 0xba, 0x8b, 0x34, 0x75 }, + { 0xcd, 0xfa, 0xbc, 0xee, 0x46, 0x91, 0x11, 0x11, 0x23, 0x6a, 0x31, 0x70, 0x8b, 0x25, 0x39, 0xd7, 0x1f, 0xc2, 0x11, 0xd9, 0xb0, 0x9c, 0x0d, 0x85, 0x30, 0xa1, 0x1e, 0x1d, 0xbf, 0x6e, 0xed, 0x01 }, + { 0x4f, 0x82, 0xde, 0x03, 0xb9, 0x50, 0x47, 0x93, 0xb8, 0x2a, 0x07, 0xa0, 0xbd, 0xcd, 0xff, 0x31, 0x4d, 0x75, 0x9e, 0x7b, 0x62, 0xd2, 0x6b, 0x78, 0x49, 0x46, 0xb0, 0xd3, 0x6f, 0x91, 0x6f, 0x52 }, + { 0x25, 0x9e, 0xc7, 0xf1, 0x73, 0xbc, 0xc7, 0x6a, 0x09, 0x94, 0xc9, 0x67, 0xb4, 0xf5, 0xf0, 0x24, 0xc5, 0x60, 0x57, 0xfb, 0x79, 0xc9, 0x65, 0xc4, 0xfa, 0xe4, 0x18, 0x75, 0xf0, 0x6a, 0x0e, 0x4c }, + { 0x19, 0x3c, 0xc8, 0xe7, 0xc3, 0xe0, 0x8b, 0xb3, 0x0f, 0x54, 0x37, 0xaa, 0x27, 0xad, 0xe1, 0xf1, 0x42, 0x36, 0x9b, 0x24, 0x6a, 0x67, 0x5b, 0x23, 0x83, 0xe6, 0xda, 0x9b, 0x49, 0xa9, 0x80, 0x9e }, + { 0x5c, 0x10, 0x89, 0x6f, 0x0e, 0x28, 0x56, 0xb2, 0xa2, 0xee, 0xe0, 0xfe, 0x4a, 0x2c, 0x16, 0x33, 0x56, 0x5d, 0x18, 0xf0, 0xe9, 0x3e, 0x1f, 0xab, 0x26, 0xc3, 0x73, 0xe8, 0xf8, 0x29, 0x65, 0x4d }, + { 0xf1, 0x60, 0x12, 0xd9, 0x3f, 0x28, 0x85, 0x1a, 0x1e, 0xb9, 0x89, 0xf5, 0xd0, 0xb4, 0x3f, 0x3f, 0x39, 0xca, 0x73, 0xc9, 0xa6, 0x2d, 0x51, 0x81, 0xbf, 0xf2, 0x37, 0x53, 0x6b, 0xd3, 0x48, 0xc3 }, + { 0x29, 0x66, 0xb3, 0xcf, 0xae, 0x1e, 0x44, 0xea, 0x99, 0x6d, 0xc5, 0xd6, 0x86, 0xcf, 0x25, 0xfa, 0x05, 0x3f, 0xb6, 0xf6, 0x72, 0x01, 0xb9, 0xe4, 0x6e, 0xad, 0xe8, 0x5d, 0x0a, 0xd6, 0xb8, 0x06 }, + { 0xdd, 0xb8, 0x78, 0x24, 0x85, 0xe9, 0x00, 0xbc, 0x60, 0xbc, 0xf4, 0xc3, 0x3a, 0x6f, 0xd5, 0x85, 0x68, 0x0c, 0xc6, 0x83, 0xd5, 0x16, 0xef, 0xa0, 0x3e, 0xb9, 0x98, 0x5f, 0xad, 0x87, 0x15, 0xfb }, + { 0x4c, 0x4d, 0x6e, 0x71, 0xae, 0xa0, 0x57, 0x86, 0x41, 0x31, 0x48, 0xfc, 0x7a, 0x78, 0x6b, 0x0e, 0xca, 0xf5, 0x82, 0xcf, 0xf1, 0x20, 0x9f, 0x5a, 0x80, 0x9f, 0xba, 0x85, 0x04, 0xce, 0x66, 0x2c }, + { 0xfb, 0x4c, 0x5e, 0x86, 0xd7, 0xb2, 0x22, 0x9b, 0x99, 0xb8, 0xba, 0x6d, 0x94, 0xc2, 0x47, 0xef, 0x96, 0x4a, 0xa3, 0xa2, 0xba, 0xe8, 0xed, 0xc7, 0x75, 0x69, 0xf2, 0x8d, 0xbb, 0xff, 0x2d, 0x4e }, + { 0xe9, 0x4f, 0x52, 0x6d, 0xe9, 0x01, 0x96, 0x33, 0xec, 0xd5, 0x4a, 0xc6, 0x12, 0x0f, 0x23, 0x95, 0x8d, 0x77, 0x18, 0xf1, 0xe7, 0x71, 0x7b, 0xf3, 0x29, 0x21, 0x1a, 0x4f, 0xae, 0xed, 0x4e, 0x6d }, + { 0xcb, 0xd6, 0x66, 0x0a, 0x10, 0xdb, 0x3f, 0x23, 0xf7, 0xa0, 0x3d, 0x4b, 0x9d, 0x40, 0x44, 0xc7, 0x93, 0x2b, 0x28, 0x01, 0xac, 0x89, 0xd6, 0x0b, 0xc9, 0xeb, 0x92, 0xd6, 0x5a, 0x46, 0xc2, 0xa0 }, + { 0x88, 0x18, 0xbb, 0xd3, 0xdb, 0x4d, 0xc1, 0x23, 0xb2, 0x5c, 0xbb, 0xa5, 0xf5, 0x4c, 0x2b, 0xc4, 0xb3, 0xfc, 0xf9, 0xbf, 0x7d, 0x7a, 0x77, 0x09, 0xf4, 0xae, 0x58, 0x8b, 0x26, 0x7c, 0x4e, 0xce }, + { 0xc6, 0x53, 0x82, 0x51, 0x3f, 0x07, 0x46, 0x0d, 0xa3, 0x98, 0x33, 0xcb, 0x66, 0x6c, 0x5e, 0xd8, 0x2e, 0x61, 0xb9, 0xe9, 0x98, 0xf4, 0xb0, 0xc4, 0x28, 0x7c, 0xee, 0x56, 0xc3, 0xcc, 0x9b, 0xcd }, + { 0x89, 0x75, 0xb0, 0x57, 0x7f, 0xd3, 0x55, 0x66, 0xd7, 0x50, 0xb3, 0x62, 0xb0, 0x89, 0x7a, 0x26, 0xc3, 0x99, 0x13, 0x6d, 0xf0, 0x7b, 0xab, 0xab, 0xbd, 0xe6, 0x20, 0x3f, 0xf2, 0x95, 0x4e, 0xd4 }, + { 0x21, 0xfe, 0x0c, 0xeb, 0x00, 0x52, 0xbe, 0x7f, 0xb0, 0xf0, 0x04, 0x18, 0x7c, 0xac, 0xd7, 0xde, 0x67, 0xfa, 0x6e, 0xb0, 0x93, 0x8d, 0x92, 0x76, 0x77, 0xf2, 0x39, 0x8c, 0x13, 0x23, 0x17, 0xa8 }, + { 0x2e, 0xf7, 0x3f, 0x3c, 0x26, 0xf1, 0x2d, 0x93, 0x88, 0x9f, 0x3c, 0x78, 0xb6, 0xa6, 0x6c, 0x1d, 0x52, 0xb6, 0x49, 0xdc, 0x9e, 0x85, 0x6e, 0x2c, 0x17, 0x2e, 0xa7, 0xc5, 0x8a, 0xc2, 0xb5, 0xe3 }, + { 0x38, 0x8a, 0x3c, 0xd5, 0x6d, 0x73, 0x86, 0x7a, 0xbb, 0x5f, 0x84, 0x01, 0x49, 0x2b, 0x6e, 0x26, 0x81, 0xeb, 0x69, 0x85, 0x1e, 0x76, 0x7f, 0xd8, 0x42, 0x10, 0xa5, 0x60, 0x76, 0xfb, 0x3d, 0xd3 }, + { 0xaf, 0x53, 0x3e, 0x02, 0x2f, 0xc9, 0x43, 0x9e, 0x4e, 0x3c, 0xb8, 0x38, 0xec, 0xd1, 0x86, 0x92, 0x23, 0x2a, 0xdf, 0x6f, 0xe9, 0x83, 0x95, 0x26, 0xd3, 0xc3, 0xdd, 0x1b, 0x71, 0x91, 0x0b, 0x1a }, + { 0x75, 0x1c, 0x09, 0xd4, 0x1a, 0x93, 0x43, 0x88, 0x2a, 0x81, 0xcd, 0x13, 0xee, 0x40, 0x81, 0x8d, 0x12, 0xeb, 0x44, 0xc6, 0xc7, 0xf4, 0x0d, 0xf1, 0x6e, 0x4a, 0xea, 0x8f, 0xab, 0x91, 0x97, 0x2a }, + { 0x5b, 0x73, 0xdd, 0xb6, 0x8d, 0x9d, 0x2b, 0x0a, 0xa2, 0x65, 0xa0, 0x79, 0x88, 0xd6, 0xb8, 0x8a, 0xe9, 0xaa, 0xc5, 0x82, 0xaf, 0x83, 0x03, 0x2f, 0x8a, 0x9b, 0x21, 0xa2, 0xe1, 0xb7, 0xbf, 0x18 }, + { 0x3d, 0xa2, 0x91, 0x26, 0xc7, 0xc5, 0xd7, 0xf4, 0x3e, 0x64, 0x24, 0x2a, 0x79, 0xfe, 0xaa, 0x4e, 0xf3, 0x45, 0x9c, 0xde, 0xcc, 0xc8, 0x98, 0xed, 0x59, 0xa9, 0x7f, 0x6e, 0xc9, 0x3b, 0x9d, 0xab }, + { 0x56, 0x6d, 0xc9, 0x20, 0x29, 0x3d, 0xa5, 0xcb, 0x4f, 0xe0, 0xaa, 0x8a, 0xbd, 0xa8, 0xbb, 0xf5, 0x6f, 0x55, 0x23, 0x13, 0xbf, 0xf1, 0x90, 0x46, 0x64, 0x1e, 0x36, 0x15, 0xc1, 0xe3, 0xed, 0x3f }, + { 0x41, 0x15, 0xbe, 0xa0, 0x2f, 0x73, 0xf9, 0x7f, 0x62, 0x9e, 0x5c, 0x55, 0x90, 0x72, 0x0c, 0x01, 0xe7, 0xe4, 0x49, 0xae, 0x2a, 0x66, 0x97, 0xd4, 0xd2, 0x78, 0x33, 0x21, 0x30, 0x36, 0x92, 0xf9 }, + { 0x4c, 0xe0, 0x8f, 0x47, 0x62, 0x46, 0x8a, 0x76, 0x70, 0x01, 0x21, 0x64, 0x87, 0x8d, 0x68, 0x34, 0x0c, 0x52, 0xa3, 0x5e, 0x66, 0xc1, 0x88, 0x4d, 0x5c, 0x86, 0x48, 0x89, 0xab, 0xc9, 0x66, 0x77 }, + { 0x81, 0xea, 0x0b, 0x78, 0x04, 0x12, 0x4e, 0x0c, 0x22, 0xea, 0x5f, 0xc7, 0x11, 0x04, 0xa2, 0xaf, 0xcb, 0x52, 0xa1, 0xfa, 0x81, 0x6f, 0x3e, 0xcb, 0x7d, 0xcb, 0x5d, 0x9d, 0xea, 0x17, 0x86, 0xd0 }, + { 0xfe, 0x36, 0x27, 0x33, 0xb0, 0x5f, 0x6b, 0xed, 0xaf, 0x93, 0x79, 0xd7, 0xf7, 0x93, 0x6e, 0xde, 0x20, 0x9b, 0x1f, 0x83, 0x23, 0xc3, 0x92, 0x25, 0x49, 0xd9, 0xe7, 0x36, 0x81, 0xb5, 0xdb, 0x7b }, + { 0xef, 0xf3, 0x7d, 0x30, 0xdf, 0xd2, 0x03, 0x59, 0xbe, 0x4e, 0x73, 0xfd, 0xf4, 0x0d, 0x27, 0x73, 0x4b, 0x3d, 0xf9, 0x0a, 0x97, 0xa5, 0x5e, 0xd7, 0x45, 0x29, 0x72, 0x94, 0xca, 0x85, 0xd0, 0x9f }, + { 0x17, 0x2f, 0xfc, 0x67, 0x15, 0x3d, 0x12, 0xe0, 0xca, 0x76, 0xa8, 0xb6, 0xcd, 0x5d, 0x47, 0x31, 0x88, 0x5b, 0x39, 0xce, 0x0c, 0xac, 0x93, 0xa8, 0x97, 0x2a, 0x18, 0x00, 0x6c, 0x8b, 0x8b, 0xaf }, + { 0xc4, 0x79, 0x57, 0xf1, 0xcc, 0x88, 0xe8, 0x3e, 0xf9, 0x44, 0x58, 0x39, 0x70, 0x9a, 0x48, 0x0a, 0x03, 0x6b, 0xed, 0x5f, 0x88, 0xac, 0x0f, 0xcc, 0x8e, 0x1e, 0x70, 0x3f, 0xfa, 0xac, 0x13, 0x2c }, + { 0x30, 0xf3, 0x54, 0x83, 0x70, 0xcf, 0xdc, 0xed, 0xa5, 0xc3, 0x7b, 0x56, 0x9b, 0x61, 0x75, 0xe7, 0x99, 0xee, 0xf1, 0xa6, 0x2a, 0xaa, 0x94, 0x32, 0x45, 0xae, 0x76, 0x69, 0xc2, 0x27, 0xa7, 0xb5 }, + { 0xc9, 0x5d, 0xcb, 0x3c, 0xf1, 0xf2, 0x7d, 0x0e, 0xef, 0x2f, 0x25, 0xd2, 0x41, 0x38, 0x70, 0x90, 0x4a, 0x87, 0x7c, 0x4a, 0x56, 0xc2, 0xde, 0x1e, 0x83, 0xe2, 0xbc, 0x2a, 0xe2, 0xe4, 0x68, 0x21 }, + { 0xd5, 0xd0, 0xb5, 0xd7, 0x05, 0x43, 0x4c, 0xd4, 0x6b, 0x18, 0x57, 0x49, 0xf6, 0x6b, 0xfb, 0x58, 0x36, 0xdc, 0xdf, 0x6e, 0xe5, 0x49, 0xa2, 0xb7, 0xa4, 0xae, 0xe7, 0xf5, 0x80, 0x07, 0xca, 0xaf }, + { 0xbb, 0xc1, 0x24, 0xa7, 0x12, 0xf1, 0x5d, 0x07, 0xc3, 0x00, 0xe0, 0x5b, 0x66, 0x83, 0x89, 0xa4, 0x39, 0xc9, 0x17, 0x77, 0xf7, 0x21, 0xf8, 0x32, 0x0c, 0x1c, 0x90, 0x78, 0x06, 0x6d, 0x2c, 0x7e }, + { 0xa4, 0x51, 0xb4, 0x8c, 0x35, 0xa6, 0xc7, 0x85, 0x4c, 0xfa, 0xae, 0x60, 0x26, 0x2e, 0x76, 0x99, 0x08, 0x16, 0x38, 0x2a, 0xc0, 0x66, 0x7e, 0x5a, 0x5c, 0x9e, 0x1b, 0x46, 0xc4, 0x34, 0x2d, 0xdf }, + { 0xb0, 0xd1, 0x50, 0xfb, 0x55, 0xe7, 0x78, 0xd0, 0x11, 0x47, 0xf0, 0xb5, 0xd8, 0x9d, 0x99, 0xec, 0xb2, 0x0f, 0xf0, 0x7e, 0x5e, 0x67, 0x60, 0xd6, 0xb6, 0x45, 0xeb, 0x5b, 0x65, 0x4c, 0x62, 0x2b }, + { 0x34, 0xf7, 0x37, 0xc0, 0xab, 0x21, 0x99, 0x51, 0xee, 0xe8, 0x9a, 0x9f, 0x8d, 0xac, 0x29, 0x9c, 0x9d, 0x4c, 0x38, 0xf3, 0x3f, 0xa4, 0x94, 0xc5, 0xc6, 0xee, 0xfc, 0x92, 0xb6, 0xdb, 0x08, 0xbc }, + { 0x1a, 0x62, 0xcc, 0x3a, 0x00, 0x80, 0x0d, 0xcb, 0xd9, 0x98, 0x91, 0x08, 0x0c, 0x1e, 0x09, 0x84, 0x58, 0x19, 0x3a, 0x8c, 0xc9, 0xf9, 0x70, 0xea, 0x99, 0xfb, 0xef, 0xf0, 0x03, 0x18, 0xc2, 0x89 }, + { 0xcf, 0xce, 0x55, 0xeb, 0xaf, 0xc8, 0x40, 0xd7, 0xae, 0x48, 0x28, 0x1c, 0x7f, 0xd5, 0x7e, 0xc8, 0xb4, 0x82, 0xd4, 0xb7, 0x04, 0x43, 0x74, 0x95, 0x49, 0x5a, 0xc4, 0x14, 0xcf, 0x4a, 0x37, 0x4b }, + { 0x67, 0x46, 0xfa, 0xcf, 0x71, 0x14, 0x6d, 0x99, 0x9d, 0xab, 0xd0, 0x5d, 0x09, 0x3a, 0xe5, 0x86, 0x64, 0x8d, 0x1e, 0xe2, 0x8e, 0x72, 0x61, 0x7b, 0x99, 0xd0, 0xf0, 0x08, 0x6e, 0x1e, 0x45, 0xbf }, + { 0x57, 0x1c, 0xed, 0x28, 0x3b, 0x3f, 0x23, 0xb4, 0xe7, 0x50, 0xbf, 0x12, 0xa2, 0xca, 0xf1, 0x78, 0x18, 0x47, 0xbd, 0x89, 0x0e, 0x43, 0x60, 0x3c, 0xdc, 0x59, 0x76, 0x10, 0x2b, 0x7b, 0xb1, 0x1b }, + { 0xcf, 0xcb, 0x76, 0x5b, 0x04, 0x8e, 0x35, 0x02, 0x2c, 0x5d, 0x08, 0x9d, 0x26, 0xe8, 0x5a, 0x36, 0xb0, 0x05, 0xa2, 0xb8, 0x04, 0x93, 0xd0, 0x3a, 0x14, 0x4e, 0x09, 0xf4, 0x09, 0xb6, 0xaf, 0xd1 }, + { 0x40, 0x50, 0xc7, 0xa2, 0x77, 0x05, 0xbb, 0x27, 0xf4, 0x20, 0x89, 0xb2, 0x99, 0xf3, 0xcb, 0xe5, 0x05, 0x4e, 0xad, 0x68, 0x72, 0x7e, 0x8e, 0xf9, 0x31, 0x8c, 0xe6, 0xf2, 0x5c, 0xd6, 0xf3, 0x1d }, + { 0x18, 0x40, 0x70, 0xbd, 0x5d, 0x26, 0x5f, 0xbd, 0xc1, 0x42, 0xcd, 0x1c, 0x5c, 0xd0, 0xd7, 0xe4, 0x14, 0xe7, 0x03, 0x69, 0xa2, 0x66, 0xd6, 0x27, 0xc8, 0xfb, 0xa8, 0x4f, 0xa5, 0xe8, 0x4c, 0x34 }, + { 0x9e, 0xdd, 0xa9, 0xa4, 0x44, 0x39, 0x02, 0xa9, 0x58, 0x8c, 0x0d, 0x0c, 0xcc, 0x62, 0xb9, 0x30, 0x21, 0x84, 0x79, 0xa6, 0x84, 0x1e, 0x6f, 0xe7, 0xd4, 0x30, 0x03, 0xf0, 0x4b, 0x1f, 0xd6, 0x43 }, + { 0xe4, 0x12, 0xfe, 0xef, 0x79, 0x08, 0x32, 0x4a, 0x6d, 0xa1, 0x84, 0x16, 0x29, 0xf3, 0x5d, 0x3d, 0x35, 0x86, 0x42, 0x01, 0x93, 0x10, 0xec, 0x57, 0xc6, 0x14, 0x83, 0x6b, 0x63, 0xd3, 0x07, 0x63 }, + { 0x1a, 0x2b, 0x8e, 0xdf, 0xf3, 0xf9, 0xac, 0xc1, 0x55, 0x4f, 0xcb, 0xae, 0x3c, 0xf1, 0xd6, 0x29, 0x8c, 0x64, 0x62, 0xe2, 0x2e, 0x5e, 0xb0, 0x25, 0x96, 0x84, 0xf8, 0x35, 0x01, 0x2b, 0xd1, 0x3f }, + { 0x28, 0x8c, 0x4a, 0xd9, 0xb9, 0x40, 0x97, 0x62, 0xea, 0x07, 0xc2, 0x4a, 0x41, 0xf0, 0x4f, 0x69, 0xa7, 0xd7, 0x4b, 0xee, 0x2d, 0x95, 0x43, 0x53, 0x74, 0xbd, 0xe9, 0x46, 0xd7, 0x24, 0x1c, 0x7b }, + { 0x80, 0x56, 0x91, 0xbb, 0x28, 0x67, 0x48, 0xcf, 0xb5, 0x91, 0xd3, 0xae, 0xbe, 0x7e, 0x6f, 0x4e, 0x4d, 0xc6, 0xe2, 0x80, 0x8c, 0x65, 0x14, 0x3c, 0xc0, 0x04, 0xe4, 0xeb, 0x6f, 0xd0, 0x9d, 0x43 }, + { 0xd4, 0xac, 0x8d, 0x3a, 0x0a, 0xfc, 0x6c, 0xfa, 0x7b, 0x46, 0x0a, 0xe3, 0x00, 0x1b, 0xae, 0xb3, 0x6d, 0xad, 0xb3, 0x7d, 0xa0, 0x7d, 0x2e, 0x8a, 0xc9, 0x18, 0x22, 0xdf, 0x34, 0x8a, 0xed, 0x3d }, + { 0xc3, 0x76, 0x61, 0x70, 0x14, 0xd2, 0x01, 0x58, 0xbc, 0xed, 0x3d, 0x3b, 0xa5, 0x52, 0xb6, 0xec, 0xcf, 0x84, 0xe6, 0x2a, 0xa3, 0xeb, 0x65, 0x0e, 0x90, 0x02, 0x9c, 0x84, 0xd1, 0x3e, 0xea, 0x69 }, + { 0xc4, 0x1f, 0x09, 0xf4, 0x3c, 0xec, 0xae, 0x72, 0x93, 0xd6, 0x00, 0x7c, 0xa0, 0xa3, 0x57, 0x08, 0x7d, 0x5a, 0xe5, 0x9b, 0xe5, 0x00, 0xc1, 0xcd, 0x5b, 0x28, 0x9e, 0xe8, 0x10, 0xc7, 0xb0, 0x82 }, + { 0x03, 0xd1, 0xce, 0xd1, 0xfb, 0xa5, 0xc3, 0x91, 0x55, 0xc4, 0x4b, 0x77, 0x65, 0xcb, 0x76, 0x0c, 0x78, 0x70, 0x8d, 0xcf, 0xc8, 0x0b, 0x0b, 0xd8, 0xad, 0xe3, 0xa5, 0x6d, 0xa8, 0x83, 0x0b, 0x29 }, + { 0x09, 0xbd, 0xe6, 0xf1, 0x52, 0x21, 0x8d, 0xc9, 0x2c, 0x41, 0xd7, 0xf4, 0x53, 0x87, 0xe6, 0x3e, 0x58, 0x69, 0xd8, 0x07, 0xec, 0x70, 0xb8, 0x21, 0x40, 0x5d, 0xbd, 0x88, 0x4b, 0x7f, 0xcf, 0x4b }, + { 0x71, 0xc9, 0x03, 0x6e, 0x18, 0x17, 0x9b, 0x90, 0xb3, 0x7d, 0x39, 0xe9, 0xf0, 0x5e, 0xb8, 0x9c, 0xc5, 0xfc, 0x34, 0x1f, 0xd7, 0xc4, 0x77, 0xd0, 0xd7, 0x49, 0x32, 0x85, 0xfa, 0xca, 0x08, 0xa4 }, + { 0x59, 0x16, 0x83, 0x3e, 0xbb, 0x05, 0xcd, 0x91, 0x9c, 0xa7, 0xfe, 0x83, 0xb6, 0x92, 0xd3, 0x20, 0x5b, 0xef, 0x72, 0x39, 0x2b, 0x2c, 0xf6, 0xbb, 0x0a, 0x6d, 0x43, 0xf9, 0x94, 0xf9, 0x5f, 0x11 }, + { 0xf6, 0x3a, 0xab, 0x3e, 0xc6, 0x41, 0xb3, 0xb0, 0x24, 0x96, 0x4c, 0x2b, 0x43, 0x7c, 0x04, 0xf6, 0x04, 0x3c, 0x4c, 0x7e, 0x02, 0x79, 0x23, 0x99, 0x95, 0x40, 0x19, 0x58, 0xf8, 0x6b, 0xbe, 0x54 }, + { 0xf1, 0x72, 0xb1, 0x80, 0xbf, 0xb0, 0x97, 0x40, 0x49, 0x31, 0x20, 0xb6, 0x32, 0x6c, 0xbd, 0xc5, 0x61, 0xe4, 0x77, 0xde, 0xf9, 0xbb, 0xcf, 0xd2, 0x8c, 0xc8, 0xc1, 0xc5, 0xe3, 0x37, 0x9a, 0x31 }, + { 0xcb, 0x9b, 0x89, 0xcc, 0x18, 0x38, 0x1d, 0xd9, 0x14, 0x1a, 0xde, 0x58, 0x86, 0x54, 0xd4, 0xe6, 0xa2, 0x31, 0xd5, 0xbf, 0x49, 0xd4, 0xd5, 0x9a, 0xc2, 0x7d, 0x86, 0x9c, 0xbe, 0x10, 0x0c, 0xf3 }, + { 0x7b, 0xd8, 0x81, 0x50, 0x46, 0xfd, 0xd8, 0x10, 0xa9, 0x23, 0xe1, 0x98, 0x4a, 0xae, 0xbd, 0xcd, 0xf8, 0x4d, 0x87, 0xc8, 0x99, 0x2d, 0x68, 0xb5, 0xee, 0xb4, 0x60, 0xf9, 0x3e, 0xb3, 0xc8, 0xd7 }, + { 0x60, 0x7b, 0xe6, 0x68, 0x62, 0xfd, 0x08, 0xee, 0x5b, 0x19, 0xfa, 0xca, 0xc0, 0x9d, 0xfd, 0xbc, 0xd4, 0x0c, 0x31, 0x21, 0x01, 0xd6, 0x6e, 0x6e, 0xbd, 0x2b, 0x84, 0x1f, 0x1b, 0x9a, 0x93, 0x25 }, + { 0x9f, 0xe0, 0x3b, 0xbe, 0x69, 0xab, 0x18, 0x34, 0xf5, 0x21, 0x9b, 0x0d, 0xa8, 0x8a, 0x08, 0xb3, 0x0a, 0x66, 0xc5, 0x91, 0x3f, 0x01, 0x51, 0x96, 0x3c, 0x36, 0x05, 0x60, 0xdb, 0x03, 0x87, 0xb3 }, + { 0x90, 0xa8, 0x35, 0x85, 0x71, 0x7b, 0x75, 0xf0, 0xe9, 0xb7, 0x25, 0xe0, 0x55, 0xee, 0xee, 0xb9, 0xe7, 0xa0, 0x28, 0xea, 0x7e, 0x6c, 0xbc, 0x07, 0xb2, 0x09, 0x17, 0xec, 0x03, 0x63, 0xe3, 0x8c }, + { 0x33, 0x6e, 0xa0, 0x53, 0x0f, 0x4a, 0x74, 0x69, 0x12, 0x6e, 0x02, 0x18, 0x58, 0x7e, 0xbb, 0xde, 0x33, 0x58, 0xa0, 0xb3, 0x1c, 0x29, 0xd2, 0x00, 0xf7, 0xdc, 0x7e, 0xb1, 0x5c, 0x6a, 0xad, 0xd8 }, + { 0xa7, 0x9e, 0x76, 0xdc, 0x0a, 0xbc, 0xa4, 0x39, 0x6f, 0x07, 0x47, 0xcd, 0x7b, 0x74, 0x8d, 0xf9, 0x13, 0x00, 0x76, 0x26, 0xb1, 0xd6, 0x59, 0xda, 0x0c, 0x1f, 0x78, 0xb9, 0x30, 0x3d, 0x01, 0xa3 }, + { 0x44, 0xe7, 0x8a, 0x77, 0x37, 0x56, 0xe0, 0x95, 0x15, 0x19, 0x50, 0x4d, 0x70, 0x38, 0xd2, 0x8d, 0x02, 0x13, 0xa3, 0x7e, 0x0c, 0xe3, 0x75, 0x37, 0x17, 0x57, 0xbc, 0x99, 0x63, 0x11, 0xe3, 0xb8 }, + { 0x77, 0xac, 0x01, 0x2a, 0x3f, 0x75, 0x4d, 0xcf, 0xea, 0xb5, 0xeb, 0x99, 0x6b, 0xe9, 0xcd, 0x2d, 0x1f, 0x96, 0x11, 0x1b, 0x6e, 0x49, 0xf3, 0x99, 0x4d, 0xf1, 0x81, 0xf2, 0x85, 0x69, 0xd8, 0x25 }, + { 0xce, 0x5a, 0x10, 0xdb, 0x6f, 0xcc, 0xda, 0xf1, 0x40, 0xaa, 0xa4, 0xde, 0xd6, 0x25, 0x0a, 0x9c, 0x06, 0xe9, 0x22, 0x2b, 0xc9, 0xf9, 0xf3, 0x65, 0x8a, 0x4a, 0xff, 0x93, 0x5f, 0x2b, 0x9f, 0x3a }, + { 0xec, 0xc2, 0x03, 0xa7, 0xfe, 0x2b, 0xe4, 0xab, 0xd5, 0x5b, 0xb5, 0x3e, 0x6e, 0x67, 0x35, 0x72, 0xe0, 0x07, 0x8d, 0xa8, 0xcd, 0x37, 0x5e, 0xf4, 0x30, 0xcc, 0x97, 0xf9, 0xf8, 0x00, 0x83, 0xaf }, + { 0x14, 0xa5, 0x18, 0x6d, 0xe9, 0xd7, 0xa1, 0x8b, 0x04, 0x12, 0xb8, 0x56, 0x3e, 0x51, 0xcc, 0x54, 0x33, 0x84, 0x0b, 0x4a, 0x12, 0x9a, 0x8f, 0xf9, 0x63, 0xb3, 0x3a, 0x3c, 0x4a, 0xfe, 0x8e, 0xbb }, + { 0x13, 0xf8, 0xef, 0x95, 0xcb, 0x86, 0xe6, 0xa6, 0x38, 0x93, 0x1c, 0x8e, 0x10, 0x76, 0x73, 0xeb, 0x76, 0xba, 0x10, 0xd7, 0xc2, 0xcd, 0x70, 0xb9, 0xd9, 0x92, 0x0b, 0xbe, 0xed, 0x92, 0x94, 0x09 }, + { 0x0b, 0x33, 0x8f, 0x4e, 0xe1, 0x2f, 0x2d, 0xfc, 0xb7, 0x87, 0x13, 0x37, 0x79, 0x41, 0xe0, 0xb0, 0x63, 0x21, 0x52, 0x58, 0x1d, 0x13, 0x32, 0x51, 0x6e, 0x4a, 0x2c, 0xab, 0x19, 0x42, 0xcc, 0xa4 }, + { 0xea, 0xab, 0x0e, 0xc3, 0x7b, 0x3b, 0x8a, 0xb7, 0x96, 0xe9, 0xf5, 0x72, 0x38, 0xde, 0x14, 0xa2, 0x64, 0xa0, 0x76, 0xf3, 0x88, 0x7d, 0x86, 0xe2, 0x9b, 0xb5, 0x90, 0x6d, 0xb5, 0xa0, 0x0e, 0x02 }, + { 0x23, 0xcb, 0x68, 0xb8, 0xc0, 0xe6, 0xdc, 0x26, 0xdc, 0x27, 0x76, 0x6d, 0xdc, 0x0a, 0x13, 0xa9, 0x94, 0x38, 0xfd, 0x55, 0x61, 0x7a, 0xa4, 0x09, 0x5d, 0x8f, 0x96, 0x97, 0x20, 0xc8, 0x72, 0xdf }, + { 0x09, 0x1d, 0x8e, 0xe3, 0x0d, 0x6f, 0x29, 0x68, 0xd4, 0x6b, 0x68, 0x7d, 0xd6, 0x52, 0x92, 0x66, 0x57, 0x42, 0xde, 0x0b, 0xb8, 0x3d, 0xcc, 0x00, 0x04, 0xc7, 0x2c, 0xe1, 0x00, 0x07, 0xa5, 0x49 }, + { 0x7f, 0x50, 0x7a, 0xbc, 0x6d, 0x19, 0xba, 0x00, 0xc0, 0x65, 0xa8, 0x76, 0xec, 0x56, 0x57, 0x86, 0x88, 0x82, 0xd1, 0x8a, 0x22, 0x1b, 0xc4, 0x6c, 0x7a, 0x69, 0x12, 0x54, 0x1f, 0x5b, 0xc7, 0xba }, + { 0xa0, 0x60, 0x7c, 0x24, 0xe1, 0x4e, 0x8c, 0x22, 0x3d, 0xb0, 0xd7, 0x0b, 0x4d, 0x30, 0xee, 0x88, 0x01, 0x4d, 0x60, 0x3f, 0x43, 0x7e, 0x9e, 0x02, 0xaa, 0x7d, 0xaf, 0xa3, 0xcd, 0xfb, 0xad, 0x94 }, + { 0xdd, 0xbf, 0xea, 0x75, 0xcc, 0x46, 0x78, 0x82, 0xeb, 0x34, 0x83, 0xce, 0x5e, 0x2e, 0x75, 0x6a, 0x4f, 0x47, 0x01, 0xb7, 0x6b, 0x44, 0x55, 0x19, 0xe8, 0x9f, 0x22, 0xd6, 0x0f, 0xa8, 0x6e, 0x06 }, + { 0x0c, 0x31, 0x1f, 0x38, 0xc3, 0x5a, 0x4f, 0xb9, 0x0d, 0x65, 0x1c, 0x28, 0x9d, 0x48, 0x68, 0x56, 0xcd, 0x14, 0x13, 0xdf, 0x9b, 0x06, 0x77, 0xf5, 0x3e, 0xce, 0x2c, 0xd9, 0xe4, 0x77, 0xc6, 0x0a }, + { 0x46, 0xa7, 0x3a, 0x8d, 0xd3, 0xe7, 0x0f, 0x59, 0xd3, 0x94, 0x2c, 0x01, 0xdf, 0x59, 0x9d, 0xef, 0x78, 0x3c, 0x9d, 0xa8, 0x2f, 0xd8, 0x32, 0x22, 0xcd, 0x66, 0x2b, 0x53, 0xdc, 0xe7, 0xdb, 0xdf }, + { 0xad, 0x03, 0x8f, 0xf9, 0xb1, 0x4d, 0xe8, 0x4a, 0x80, 0x1e, 0x4e, 0x62, 0x1c, 0xe5, 0xdf, 0x02, 0x9d, 0xd9, 0x35, 0x20, 0xd0, 0xc2, 0xfa, 0x38, 0xbf, 0xf1, 0x76, 0xa8, 0xb1, 0xd1, 0x69, 0x8c }, + { 0xab, 0x70, 0xc5, 0xdf, 0xbd, 0x1e, 0xa8, 0x17, 0xfe, 0xd0, 0xcd, 0x06, 0x72, 0x93, 0xab, 0xf3, 0x19, 0xe5, 0xd7, 0x90, 0x1c, 0x21, 0x41, 0xd5, 0xd9, 0x9b, 0x23, 0xf0, 0x3a, 0x38, 0xe7, 0x48 }, + { 0x1f, 0xff, 0xda, 0x67, 0x93, 0x2b, 0x73, 0xc8, 0xec, 0xaf, 0x00, 0x9a, 0x34, 0x91, 0xa0, 0x26, 0x95, 0x3b, 0xab, 0xfe, 0x1f, 0x66, 0x3b, 0x06, 0x97, 0xc3, 0xc4, 0xae, 0x8b, 0x2e, 0x7d, 0xcb }, + { 0xb0, 0xd2, 0xcc, 0x19, 0x47, 0x2d, 0xd5, 0x7f, 0x2b, 0x17, 0xef, 0xc0, 0x3c, 0x8d, 0x58, 0xc2, 0x28, 0x3d, 0xbb, 0x19, 0xda, 0x57, 0x2f, 0x77, 0x55, 0x85, 0x5a, 0xa9, 0x79, 0x43, 0x17, 0xa0 }, + { 0xa0, 0xd1, 0x9a, 0x6e, 0xe3, 0x39, 0x79, 0xc3, 0x25, 0x51, 0x0e, 0x27, 0x66, 0x22, 0xdf, 0x41, 0xf7, 0x15, 0x83, 0xd0, 0x75, 0x01, 0xb8, 0x70, 0x71, 0x12, 0x9a, 0x0a, 0xd9, 0x47, 0x32, 0xa5 }, + { 0x72, 0x46, 0x42, 0xa7, 0x03, 0x2d, 0x10, 0x62, 0xb8, 0x9e, 0x52, 0xbe, 0xa3, 0x4b, 0x75, 0xdf, 0x7d, 0x8f, 0xe7, 0x72, 0xd9, 0xfe, 0x3c, 0x93, 0xdd, 0xf3, 0xc4, 0x54, 0x5a, 0xb5, 0xa9, 0x9b }, + { 0xad, 0xe5, 0xea, 0xa7, 0xe6, 0x1f, 0x67, 0x2d, 0x58, 0x7e, 0xa0, 0x3d, 0xae, 0x7d, 0x7b, 0x55, 0x22, 0x9c, 0x01, 0xd0, 0x6b, 0xc0, 0xa5, 0x70, 0x14, 0x36, 0xcb, 0xd1, 0x83, 0x66, 0xa6, 0x26 }, + { 0x01, 0x3b, 0x31, 0xeb, 0xd2, 0x28, 0xfc, 0xdd, 0xa5, 0x1f, 0xab, 0xb0, 0x3b, 0xb0, 0x2d, 0x60, 0xac, 0x20, 0xca, 0x21, 0x5a, 0xaf, 0xa8, 0x3b, 0xdd, 0x85, 0x5e, 0x37, 0x55, 0xa3, 0x5f, 0x0b }, + { 0x33, 0x2e, 0xd4, 0x0b, 0xb1, 0x0d, 0xde, 0x3c, 0x95, 0x4a, 0x75, 0xd7, 0xb8, 0x99, 0x9d, 0x4b, 0x26, 0xa1, 0xc0, 0x63, 0xc1, 0xdc, 0x6e, 0x32, 0xc1, 0xd9, 0x1b, 0xab, 0x7b, 0xbb, 0x7d, 0x16 }, + { 0xc7, 0xa1, 0x97, 0xb3, 0xa0, 0x5b, 0x56, 0x6b, 0xcc, 0x9f, 0xac, 0xd2, 0x0e, 0x44, 0x1d, 0x6f, 0x6c, 0x28, 0x60, 0xac, 0x96, 0x51, 0xcd, 0x51, 0xd6, 0xb9, 0xd2, 0xcd, 0xee, 0xea, 0x03, 0x90 }, + { 0xbd, 0x9c, 0xf6, 0x4e, 0xa8, 0x95, 0x3c, 0x03, 0x71, 0x08, 0xe6, 0xf6, 0x54, 0x91, 0x4f, 0x39, 0x58, 0xb6, 0x8e, 0x29, 0xc1, 0x67, 0x00, 0xdc, 0x18, 0x4d, 0x94, 0xa2, 0x17, 0x08, 0xff, 0x60 }, + { 0x88, 0x35, 0xb0, 0xac, 0x02, 0x11, 0x51, 0xdf, 0x71, 0x64, 0x74, 0xce, 0x27, 0xce, 0x4d, 0x3c, 0x15, 0xf0, 0xb2, 0xda, 0xb4, 0x80, 0x03, 0xcf, 0x3f, 0x3e, 0xfd, 0x09, 0x45, 0x10, 0x6b, 0x9a }, + { 0x3b, 0xfe, 0xfa, 0x33, 0x01, 0xaa, 0x55, 0xc0, 0x80, 0x19, 0x0c, 0xff, 0xda, 0x8e, 0xae, 0x51, 0xd9, 0xaf, 0x48, 0x8b, 0x4c, 0x1f, 0x24, 0xc3, 0xd9, 0xa7, 0x52, 0x42, 0xfd, 0x8e, 0xa0, 0x1d }, + { 0x08, 0x28, 0x4d, 0x14, 0x99, 0x3c, 0xd4, 0x7d, 0x53, 0xeb, 0xae, 0xcf, 0x0d, 0xf0, 0x47, 0x8c, 0xc1, 0x82, 0xc8, 0x9c, 0x00, 0xe1, 0x85, 0x9c, 0x84, 0x85, 0x16, 0x86, 0xdd, 0xf2, 0xc1, 0xb7 }, + { 0x1e, 0xd7, 0xef, 0x9f, 0x04, 0xc2, 0xac, 0x8d, 0xb6, 0xa8, 0x64, 0xdb, 0x13, 0x10, 0x87, 0xf2, 0x70, 0x65, 0x09, 0x8e, 0x69, 0xc3, 0xfe, 0x78, 0x71, 0x8d, 0x9b, 0x94, 0x7f, 0x4a, 0x39, 0xd0 }, + { 0xc1, 0x61, 0xf2, 0xdc, 0xd5, 0x7e, 0x9c, 0x14, 0x39, 0xb3, 0x1a, 0x9d, 0xd4, 0x3d, 0x8f, 0x3d, 0x7d, 0xd8, 0xf0, 0xeb, 0x7c, 0xfa, 0xc6, 0xfb, 0x25, 0xa0, 0xf2, 0x8e, 0x30, 0x6f, 0x06, 0x61 }, + { 0xc0, 0x19, 0x69, 0xad, 0x34, 0xc5, 0x2c, 0xaf, 0x3d, 0xc4, 0xd8, 0x0d, 0x19, 0x73, 0x5c, 0x29, 0x73, 0x1a, 0xc6, 0xe7, 0xa9, 0x20, 0x85, 0xab, 0x92, 0x50, 0xc4, 0x8d, 0xea, 0x48, 0xa3, 0xfc }, + { 0x17, 0x20, 0xb3, 0x65, 0x56, 0x19, 0xd2, 0xa5, 0x2b, 0x35, 0x21, 0xae, 0x0e, 0x49, 0xe3, 0x45, 0xcb, 0x33, 0x89, 0xeb, 0xd6, 0x20, 0x8a, 0xca, 0xf9, 0xf1, 0x3f, 0xda, 0xcc, 0xa8, 0xbe, 0x49 }, + { 0x75, 0x62, 0x88, 0x36, 0x1c, 0x83, 0xe2, 0x4c, 0x61, 0x7c, 0xf9, 0x5c, 0x90, 0x5b, 0x22, 0xd0, 0x17, 0xcd, 0xc8, 0x6f, 0x0b, 0xf1, 0xd6, 0x58, 0xf4, 0x75, 0x6c, 0x73, 0x79, 0x87, 0x3b, 0x7f }, + { 0xe7, 0xd0, 0xed, 0xa3, 0x45, 0x26, 0x93, 0xb7, 0x52, 0xab, 0xcd, 0xa1, 0xb5, 0x5e, 0x27, 0x6f, 0x82, 0x69, 0x8f, 0x5f, 0x16, 0x05, 0x40, 0x3e, 0xff, 0x83, 0x0b, 0xea, 0x00, 0x71, 0xa3, 0x94 }, + { 0x2c, 0x82, 0xec, 0xaa, 0x6b, 0x84, 0x80, 0x3e, 0x04, 0x4a, 0xf6, 0x31, 0x18, 0xaf, 0xe5, 0x44, 0x68, 0x7c, 0xb6, 0xe6, 0xc7, 0xdf, 0x49, 0xed, 0x76, 0x2d, 0xfd, 0x7c, 0x86, 0x93, 0xa1, 0xbc }, + { 0x61, 0x36, 0xcb, 0xf4, 0xb4, 0x41, 0x05, 0x6f, 0xa1, 0xe2, 0x72, 0x24, 0x98, 0x12, 0x5d, 0x6d, 0xed, 0x45, 0xe1, 0x7b, 0x52, 0x14, 0x39, 0x59, 0xc7, 0xf4, 0xd4, 0xe3, 0x95, 0x21, 0x8a, 0xc2 }, + { 0x72, 0x1d, 0x32, 0x45, 0xaa, 0xfe, 0xf2, 0x7f, 0x6a, 0x62, 0x4f, 0x47, 0x95, 0x4b, 0x6c, 0x25, 0x50, 0x79, 0x52, 0x6f, 0xfa, 0x25, 0xe9, 0xff, 0x77, 0xe5, 0xdc, 0xff, 0x47, 0x3b, 0x15, 0x97 }, + { 0x9d, 0xd2, 0xfb, 0xd8, 0xce, 0xf1, 0x6c, 0x35, 0x3c, 0x0a, 0xc2, 0x11, 0x91, 0xd5, 0x09, 0xeb, 0x28, 0xdd, 0x9e, 0x3e, 0x0d, 0x8c, 0xea, 0x5d, 0x26, 0xca, 0x83, 0x93, 0x93, 0x85, 0x1c, 0x3a }, + { 0xb2, 0x39, 0x4c, 0xea, 0xcd, 0xeb, 0xf2, 0x1b, 0xf9, 0xdf, 0x2c, 0xed, 0x98, 0xe5, 0x8f, 0x1c, 0x3a, 0x4b, 0xbb, 0xff, 0x66, 0x0d, 0xd9, 0x00, 0xf6, 0x22, 0x02, 0xd6, 0x78, 0x5c, 0xc4, 0x6e }, + { 0x57, 0x08, 0x9f, 0x22, 0x27, 0x49, 0xad, 0x78, 0x71, 0x76, 0x5f, 0x06, 0x2b, 0x11, 0x4f, 0x43, 0xba, 0x20, 0xec, 0x56, 0x42, 0x2a, 0x8b, 0x1e, 0x3f, 0x87, 0x19, 0x2c, 0x0e, 0xa7, 0x18, 0xc6 }, + { 0xe4, 0x9a, 0x94, 0x59, 0x96, 0x1c, 0xd3, 0x3c, 0xdf, 0x4a, 0xae, 0x1b, 0x10, 0x78, 0xa5, 0xde, 0xa7, 0xc0, 0x40, 0xe0, 0xfe, 0xa3, 0x40, 0xc9, 0x3a, 0x72, 0x48, 0x72, 0xfc, 0x4a, 0xf8, 0x06 }, + { 0xed, 0xe6, 0x7f, 0x72, 0x0e, 0xff, 0xd2, 0xca, 0x9c, 0x88, 0x99, 0x41, 0x52, 0xd0, 0x20, 0x1d, 0xee, 0x6b, 0x0a, 0x2d, 0x2c, 0x07, 0x7a, 0xca, 0x6d, 0xae, 0x29, 0xf7, 0x3f, 0x8b, 0x63, 0x09 }, + { 0xe0, 0xf4, 0x34, 0xbf, 0x22, 0xe3, 0x08, 0x80, 0x39, 0xc2, 0x1f, 0x71, 0x9f, 0xfc, 0x67, 0xf0, 0xf2, 0xcb, 0x5e, 0x98, 0xa7, 0xa0, 0x19, 0x4c, 0x76, 0xe9, 0x6b, 0xf4, 0xe8, 0xe1, 0x7e, 0x61 }, + { 0x27, 0x7c, 0x04, 0xe2, 0x85, 0x34, 0x84, 0xa4, 0xeb, 0xa9, 0x10, 0xad, 0x33, 0x6d, 0x01, 0xb4, 0x77, 0xb6, 0x7c, 0xc2, 0x00, 0xc5, 0x9f, 0x3c, 0x8d, 0x77, 0xee, 0xf8, 0x49, 0x4f, 0x29, 0xcd }, + { 0x15, 0x6d, 0x57, 0x47, 0xd0, 0xc9, 0x9c, 0x7f, 0x27, 0x09, 0x7d, 0x7b, 0x7e, 0x00, 0x2b, 0x2e, 0x18, 0x5c, 0xb7, 0x2d, 0x8d, 0xd7, 0xeb, 0x42, 0x4a, 0x03, 0x21, 0x52, 0x81, 0x61, 0x21, 0x9f }, + { 0x20, 0xdd, 0xd1, 0xed, 0x9b, 0x1c, 0xa8, 0x03, 0x94, 0x6d, 0x64, 0xa8, 0x3a, 0xe4, 0x65, 0x9d, 0xa6, 0x7f, 0xba, 0x7a, 0x1a, 0x3e, 0xdd, 0xb1, 0xe1, 0x03, 0xc0, 0xf5, 0xe0, 0x3e, 0x3a, 0x2c }, + { 0xf0, 0xaf, 0x60, 0x4d, 0x3d, 0xab, 0xbf, 0x9a, 0x0f, 0x2a, 0x7d, 0x3d, 0xda, 0x6b, 0xd3, 0x8b, 0xba, 0x72, 0xc6, 0xd0, 0x9b, 0xe4, 0x94, 0xfc, 0xef, 0x71, 0x3f, 0xf1, 0x01, 0x89, 0xb6, 0xe6 }, + { 0x98, 0x02, 0xbb, 0x87, 0xde, 0xf4, 0xcc, 0x10, 0xc4, 0xa5, 0xfd, 0x49, 0xaa, 0x58, 0xdf, 0xe2, 0xf3, 0xfd, 0xdb, 0x46, 0xb4, 0x70, 0x88, 0x14, 0xea, 0xd8, 0x1d, 0x23, 0xba, 0x95, 0x13, 0x9b }, + { 0x4f, 0x8c, 0xe1, 0xe5, 0x1d, 0x2f, 0xe7, 0xf2, 0x40, 0x43, 0xa9, 0x04, 0xd8, 0x98, 0xeb, 0xfc, 0x91, 0x97, 0x54, 0x18, 0x75, 0x34, 0x13, 0xaa, 0x09, 0x9b, 0x79, 0x5e, 0xcb, 0x35, 0xce, 0xdb }, + { 0xbd, 0xdc, 0x65, 0x14, 0xd7, 0xee, 0x6a, 0xce, 0x0a, 0x4a, 0xc1, 0xd0, 0xe0, 0x68, 0x11, 0x22, 0x88, 0xcb, 0xcf, 0x56, 0x04, 0x54, 0x64, 0x27, 0x05, 0x63, 0x01, 0x77, 0xcb, 0xa6, 0x08, 0xbd }, + { 0xd6, 0x35, 0x99, 0x4f, 0x62, 0x91, 0x51, 0x7b, 0x02, 0x81, 0xff, 0xdd, 0x49, 0x6a, 0xfa, 0x86, 0x27, 0x12, 0xe5, 0xb3, 0xc4, 0xe5, 0x2e, 0x4c, 0xd5, 0xfd, 0xae, 0x8c, 0x0e, 0x72, 0xfb, 0x08 }, + { 0x87, 0x8d, 0x9c, 0xa6, 0x00, 0xcf, 0x87, 0xe7, 0x69, 0xcc, 0x30, 0x5c, 0x1b, 0x35, 0x25, 0x51, 0x86, 0x61, 0x5a, 0x73, 0xa0, 0xda, 0x61, 0x3b, 0x5f, 0x1c, 0x98, 0xdb, 0xf8, 0x12, 0x83, 0xea }, + { 0xa6, 0x4e, 0xbe, 0x5d, 0xc1, 0x85, 0xde, 0x9f, 0xdd, 0xe7, 0x60, 0x7b, 0x69, 0x98, 0x70, 0x2e, 0xb2, 0x34, 0x56, 0x18, 0x49, 0x57, 0x30, 0x7d, 0x2f, 0xa7, 0x2e, 0x87, 0xa4, 0x77, 0x02, 0xd6 }, + { 0xce, 0x50, 0xea, 0xb7, 0xb5, 0xeb, 0x52, 0xbd, 0xc9, 0xad, 0x8e, 0x5a, 0x48, 0x0a, 0xb7, 0x80, 0xca, 0x93, 0x20, 0xe4, 0x43, 0x60, 0xb1, 0xfe, 0x37, 0xe0, 0x3f, 0x2f, 0x7a, 0xd7, 0xde, 0x01 }, + { 0xee, 0xdd, 0xb7, 0xc0, 0xdb, 0x6e, 0x30, 0xab, 0xe6, 0x6d, 0x79, 0xe3, 0x27, 0x51, 0x1e, 0x61, 0xfc, 0xeb, 0xbc, 0x29, 0xf1, 0x59, 0xb4, 0x0a, 0x86, 0xb0, 0x46, 0xec, 0xf0, 0x51, 0x38, 0x23 }, + { 0x78, 0x7f, 0xc9, 0x34, 0x40, 0xc1, 0xec, 0x96, 0xb5, 0xad, 0x01, 0xc1, 0x6c, 0xf7, 0x79, 0x16, 0xa1, 0x40, 0x5f, 0x94, 0x26, 0x35, 0x6e, 0xc9, 0x21, 0xd8, 0xdf, 0xf3, 0xea, 0x63, 0xb7, 0xe0 }, + { 0x7f, 0x0d, 0x5e, 0xab, 0x47, 0xee, 0xfd, 0xa6, 0x96, 0xc0, 0xbf, 0x0f, 0xbf, 0x86, 0xab, 0x21, 0x6f, 0xce, 0x46, 0x1e, 0x93, 0x03, 0xab, 0xa6, 0xac, 0x37, 0x41, 0x20, 0xe8, 0x90, 0xe8, 0xdf }, + { 0xb6, 0x80, 0x04, 0xb4, 0x2f, 0x14, 0xad, 0x02, 0x9f, 0x4c, 0x2e, 0x03, 0xb1, 0xd5, 0xeb, 0x76, 0xd5, 0x71, 0x60, 0xe2, 0x64, 0x76, 0xd2, 0x11, 0x31, 0xbe, 0xf2, 0x0a, 0xda, 0x7d, 0x27, 0xf4 }, + { 0xb0, 0xc4, 0xeb, 0x18, 0xae, 0x25, 0x0b, 0x51, 0xa4, 0x13, 0x82, 0xea, 0xd9, 0x2d, 0x0d, 0xc7, 0x45, 0x5f, 0x93, 0x79, 0xfc, 0x98, 0x84, 0x42, 0x8e, 0x47, 0x70, 0x60, 0x8d, 0xb0, 0xfa, 0xec }, + { 0xf9, 0x2b, 0x7a, 0x87, 0x0c, 0x05, 0x9f, 0x4d, 0x46, 0x46, 0x4c, 0x82, 0x4e, 0xc9, 0x63, 0x55, 0x14, 0x0b, 0xdc, 0xe6, 0x81, 0x32, 0x2c, 0xc3, 0xa9, 0x92, 0xff, 0x10, 0x3e, 0x3f, 0xea, 0x52 }, + { 0x53, 0x64, 0x31, 0x26, 0x14, 0x81, 0x33, 0x98, 0xcc, 0x52, 0x5d, 0x4c, 0x4e, 0x14, 0x6e, 0xde, 0xb3, 0x71, 0x26, 0x5f, 0xba, 0x19, 0x13, 0x3a, 0x2c, 0x3d, 0x21, 0x59, 0x29, 0x8a, 0x17, 0x42 }, + { 0xf6, 0x62, 0x0e, 0x68, 0xd3, 0x7f, 0xb2, 0xaf, 0x50, 0x00, 0xfc, 0x28, 0xe2, 0x3b, 0x83, 0x22, 0x97, 0xec, 0xd8, 0xbc, 0xe9, 0x9e, 0x8b, 0xe4, 0xd0, 0x4e, 0x85, 0x30, 0x9e, 0x3d, 0x33, 0x74 }, + { 0x53, 0x16, 0xa2, 0x79, 0x69, 0xd7, 0xfe, 0x04, 0xff, 0x27, 0xb2, 0x83, 0x96, 0x1b, 0xff, 0xc3, 0xbf, 0x5d, 0xfb, 0x32, 0xfb, 0x6a, 0x89, 0xd1, 0x01, 0xc6, 0xc3, 0xb1, 0x93, 0x7c, 0x28, 0x71 }, + { 0x81, 0xd1, 0x66, 0x4f, 0xdf, 0x3c, 0xb3, 0x3c, 0x24, 0xee, 0xba, 0xc0, 0xbd, 0x64, 0x24, 0x4b, 0x77, 0xc4, 0xab, 0xea, 0x90, 0xbb, 0xe8, 0xb5, 0xee, 0x0b, 0x2a, 0xaf, 0xcf, 0x2d, 0x6a, 0x53 }, + { 0x34, 0x57, 0x82, 0xf2, 0x95, 0xb0, 0x88, 0x03, 0x52, 0xe9, 0x24, 0xa0, 0x46, 0x7b, 0x5f, 0xbc, 0x3e, 0x8f, 0x3b, 0xfb, 0xc3, 0xc7, 0xe4, 0x8b, 0x67, 0x09, 0x1f, 0xb5, 0xe8, 0x0a, 0x94, 0x42 }, + { 0x79, 0x41, 0x11, 0xea, 0x6c, 0xd6, 0x5e, 0x31, 0x1f, 0x74, 0xee, 0x41, 0xd4, 0x76, 0xcb, 0x63, 0x2c, 0xe1, 0xe4, 0xb0, 0x51, 0xdc, 0x1d, 0x9e, 0x9d, 0x06, 0x1a, 0x19, 0xe1, 0xd0, 0xbb, 0x49 }, + { 0x2a, 0x85, 0xda, 0xf6, 0x13, 0x88, 0x16, 0xb9, 0x9b, 0xf8, 0xd0, 0x8b, 0xa2, 0x11, 0x4b, 0x7a, 0xb0, 0x79, 0x75, 0xa7, 0x84, 0x20, 0xc1, 0xa3, 0xb0, 0x6a, 0x77, 0x7c, 0x22, 0xdd, 0x8b, 0xcb }, + { 0x89, 0xb0, 0xd5, 0xf2, 0x89, 0xec, 0x16, 0x40, 0x1a, 0x06, 0x9a, 0x96, 0x0d, 0x0b, 0x09, 0x3e, 0x62, 0x5d, 0xa3, 0xcf, 0x41, 0xee, 0x29, 0xb5, 0x9b, 0x93, 0x0c, 0x58, 0x20, 0x14, 0x54, 0x55 }, + { 0xd0, 0xfd, 0xcb, 0x54, 0x39, 0x43, 0xfc, 0x27, 0xd2, 0x08, 0x64, 0xf5, 0x21, 0x81, 0x47, 0x1b, 0x94, 0x2c, 0xc7, 0x7c, 0xa6, 0x75, 0xbc, 0xb3, 0x0d, 0xf3, 0x1d, 0x35, 0x8e, 0xf7, 0xb1, 0xeb }, + { 0xb1, 0x7e, 0xa8, 0xd7, 0x70, 0x63, 0xc7, 0x09, 0xd4, 0xdc, 0x6b, 0x87, 0x94, 0x13, 0xc3, 0x43, 0xe3, 0x79, 0x0e, 0x9e, 0x62, 0xca, 0x85, 0xb7, 0x90, 0x0b, 0x08, 0x6f, 0x6b, 0x75, 0xc6, 0x72 }, + { 0xe7, 0x1a, 0x3e, 0x2c, 0x27, 0x4d, 0xb8, 0x42, 0xd9, 0x21, 0x14, 0xf2, 0x17, 0xe2, 0xc0, 0xea, 0xc8, 0xb4, 0x50, 0x93, 0xfd, 0xfd, 0x9d, 0xf4, 0xca, 0x71, 0x62, 0x39, 0x48, 0x62, 0xd5, 0x01 }, + { 0xc0, 0x47, 0x67, 0x59, 0xab, 0x7a, 0xa3, 0x33, 0x23, 0x4f, 0x6b, 0x44, 0xf5, 0xfd, 0x85, 0x83, 0x90, 0xec, 0x23, 0x69, 0x4c, 0x62, 0x2c, 0xb9, 0x86, 0xe7, 0x69, 0xc7, 0x8e, 0xdd, 0x73, 0x3e }, + { 0x9a, 0xb8, 0xea, 0xbb, 0x14, 0x16, 0x43, 0x4d, 0x85, 0x39, 0x13, 0x41, 0xd5, 0x69, 0x93, 0xc5, 0x54, 0x58, 0x16, 0x7d, 0x44, 0x18, 0xb1, 0x9a, 0x0f, 0x2a, 0xd8, 0xb7, 0x9a, 0x83, 0xa7, 0x5b }, + { 0x79, 0x92, 0xd0, 0xbb, 0xb1, 0x5e, 0x23, 0x82, 0x6f, 0x44, 0x3e, 0x00, 0x50, 0x5d, 0x68, 0xd3, 0xed, 0x73, 0x72, 0x99, 0x5a, 0x5c, 0x3e, 0x49, 0x86, 0x54, 0x10, 0x2f, 0xbc, 0xd0, 0x96, 0x4e }, + { 0xc0, 0x21, 0xb3, 0x00, 0x85, 0x15, 0x14, 0x35, 0xdf, 0x33, 0xb0, 0x07, 0xcc, 0xec, 0xc6, 0x9d, 0xf1, 0x26, 0x9f, 0x39, 0xba, 0x25, 0x09, 0x2b, 0xed, 0x59, 0xd9, 0x32, 0xac, 0x0f, 0xdc, 0x28 }, + { 0x91, 0xa2, 0x5e, 0xc0, 0xec, 0x0d, 0x9a, 0x56, 0x7f, 0x89, 0xc4, 0xbf, 0xe1, 0xa6, 0x5a, 0x0e, 0x43, 0x2d, 0x07, 0x06, 0x4b, 0x41, 0x90, 0xe2, 0x7d, 0xfb, 0x81, 0x90, 0x1f, 0xd3, 0x13, 0x9b }, + { 0x59, 0x50, 0xd3, 0x9a, 0x23, 0xe1, 0x54, 0x5f, 0x30, 0x12, 0x70, 0xaa, 0x1a, 0x12, 0xf2, 0xe6, 0xc4, 0x53, 0x77, 0x6e, 0x4d, 0x63, 0x55, 0xde, 0x42, 0x5c, 0xc1, 0x53, 0xf9, 0x81, 0x88, 0x67 }, + { 0xd7, 0x9f, 0x14, 0x72, 0x0c, 0x61, 0x0a, 0xf1, 0x79, 0xa3, 0x76, 0x5d, 0x4b, 0x7c, 0x09, 0x68, 0xf9, 0x77, 0x96, 0x2d, 0xbf, 0x65, 0x5b, 0x52, 0x12, 0x72, 0xb6, 0xf1, 0xe1, 0x94, 0x48, 0x8e }, + { 0xe9, 0x53, 0x1b, 0xfc, 0x8b, 0x02, 0x99, 0x5a, 0xea, 0xa7, 0x5b, 0xa2, 0x70, 0x31, 0xfa, 0xdb, 0xcb, 0xf4, 0xa0, 0xda, 0xb8, 0x96, 0x1d, 0x92, 0x96, 0xcd, 0x7e, 0x84, 0xd2, 0x5d, 0x60, 0x06 }, + { 0x34, 0xe9, 0xc2, 0x6a, 0x01, 0xd7, 0xf1, 0x61, 0x81, 0xb4, 0x54, 0xa9, 0xd1, 0x62, 0x3c, 0x23, 0x3c, 0xb9, 0x9d, 0x31, 0xc6, 0x94, 0x65, 0x6e, 0x94, 0x13, 0xac, 0xa3, 0xe9, 0x18, 0x69, 0x2f }, + { 0xd9, 0xd7, 0x42, 0x2f, 0x43, 0x7b, 0xd4, 0x39, 0xdd, 0xd4, 0xd8, 0x83, 0xda, 0xe2, 0xa0, 0x83, 0x50, 0x17, 0x34, 0x14, 0xbe, 0x78, 0x15, 0x51, 0x33, 0xff, 0xf1, 0x96, 0x4c, 0x3d, 0x79, 0x72 }, + { 0x4a, 0xee, 0x0c, 0x7a, 0xaf, 0x07, 0x54, 0x14, 0xff, 0x17, 0x93, 0xea, 0xd7, 0xea, 0xca, 0x60, 0x17, 0x75, 0xc6, 0x15, 0xdb, 0xd6, 0x0b, 0x64, 0x0b, 0x0a, 0x9f, 0x0c, 0xe5, 0x05, 0xd4, 0x35 }, + { 0x6b, 0xfd, 0xd1, 0x54, 0x59, 0xc8, 0x3b, 0x99, 0xf0, 0x96, 0xbf, 0xb4, 0x9e, 0xe8, 0x7b, 0x06, 0x3d, 0x69, 0xc1, 0x97, 0x4c, 0x69, 0x28, 0xac, 0xfc, 0xfb, 0x40, 0x99, 0xf8, 0xc4, 0xef, 0x67 }, + { 0x9f, 0xd1, 0xc4, 0x08, 0xfd, 0x75, 0xc3, 0x36, 0x19, 0x3a, 0x2a, 0x14, 0xd9, 0x4f, 0x6a, 0xf5, 0xad, 0xf0, 0x50, 0xb8, 0x03, 0x87, 0xb4, 0xb0, 0x10, 0xfb, 0x29, 0xf4, 0xcc, 0x72, 0x70, 0x7c }, + { 0x13, 0xc8, 0x84, 0x80, 0xa5, 0xd0, 0x0d, 0x6c, 0x8c, 0x7a, 0xd2, 0x11, 0x0d, 0x76, 0xa8, 0x2d, 0x9b, 0x70, 0xf4, 0xfa, 0x66, 0x96, 0xd4, 0xe5, 0xdd, 0x42, 0xa0, 0x66, 0xdc, 0xaf, 0x99, 0x20 }, + { 0x82, 0x0e, 0x72, 0x5e, 0xe2, 0x5f, 0xe8, 0xfd, 0x3a, 0x8d, 0x5a, 0xbe, 0x4c, 0x46, 0xc3, 0xba, 0x88, 0x9d, 0xe6, 0xfa, 0x91, 0x91, 0xaa, 0x22, 0xba, 0x67, 0xd5, 0x70, 0x54, 0x21, 0x54, 0x2b }, + { 0x32, 0xd9, 0x3a, 0x0e, 0xb0, 0x2f, 0x42, 0xfb, 0xbc, 0xaf, 0x2b, 0xad, 0x00, 0x85, 0xb2, 0x82, 0xe4, 0x60, 0x46, 0xa4, 0xdf, 0x7a, 0xd1, 0x06, 0x57, 0xc9, 0xd6, 0x47, 0x63, 0x75, 0xb9, 0x3e }, + { 0xad, 0xc5, 0x18, 0x79, 0x05, 0xb1, 0x66, 0x9c, 0xd8, 0xec, 0x9c, 0x72, 0x1e, 0x19, 0x53, 0x78, 0x6b, 0x9d, 0x89, 0xa9, 0xba, 0xe3, 0x07, 0x80, 0xf1, 0xe1, 0xea, 0xb2, 0x4a, 0x00, 0x52, 0x3c }, + { 0xe9, 0x07, 0x56, 0xff, 0x7f, 0x9a, 0xd8, 0x10, 0xb2, 0x39, 0xa1, 0x0c, 0xed, 0x2c, 0xf9, 0xb2, 0x28, 0x43, 0x54, 0xc1, 0xf8, 0xc7, 0xe0, 0xac, 0xcc, 0x24, 0x61, 0xdc, 0x79, 0x6d, 0x6e, 0x89 }, + { 0x12, 0x51, 0xf7, 0x6e, 0x56, 0x97, 0x84, 0x81, 0x87, 0x53, 0x59, 0x80, 0x1d, 0xb5, 0x89, 0xa0, 0xb2, 0x2f, 0x86, 0xd8, 0xd6, 0x34, 0xdc, 0x04, 0x50, 0x6f, 0x32, 0x2e, 0xd7, 0x8f, 0x17, 0xe8 }, + { 0x3a, 0xfa, 0x89, 0x9f, 0xd9, 0x80, 0xe7, 0x3e, 0xcb, 0x7f, 0x4d, 0x8b, 0x8f, 0x29, 0x1d, 0xc9, 0xaf, 0x79, 0x6b, 0xc6, 0x5d, 0x27, 0xf9, 0x74, 0xc6, 0xf1, 0x93, 0xc9, 0x19, 0x1a, 0x09, 0xfd }, + { 0xaa, 0x30, 0x5b, 0xe2, 0x6e, 0x5d, 0xed, 0xdc, 0x3c, 0x10, 0x10, 0xcb, 0xc2, 0x13, 0xf9, 0x5f, 0x05, 0x1c, 0x78, 0x5c, 0x5b, 0x43, 0x1e, 0x6a, 0x7c, 0xd0, 0x48, 0xf1, 0x61, 0x78, 0x75, 0x28 }, + { 0x8e, 0xa1, 0x88, 0x4f, 0xf3, 0x2e, 0x9d, 0x10, 0xf0, 0x39, 0xb4, 0x07, 0xd0, 0xd4, 0x4e, 0x7e, 0x67, 0x0a, 0xbd, 0x88, 0x4a, 0xee, 0xe0, 0xfb, 0x75, 0x7a, 0xe9, 0x4e, 0xaa, 0x97, 0x37, 0x3d }, + { 0xd4, 0x82, 0xb2, 0x15, 0x5d, 0x4d, 0xec, 0x6b, 0x47, 0x36, 0xa1, 0xf1, 0x61, 0x7b, 0x53, 0xaa, 0xa3, 0x73, 0x10, 0x27, 0x7d, 0x3f, 0xef, 0x0c, 0x37, 0xad, 0x41, 0x76, 0x8f, 0xc2, 0x35, 0xb4 }, + { 0x4d, 0x41, 0x39, 0x71, 0x38, 0x7e, 0x7a, 0x88, 0x98, 0xa8, 0xdc, 0x2a, 0x27, 0x50, 0x07, 0x78, 0x53, 0x9e, 0xa2, 0x14, 0xa2, 0xdf, 0xe9, 0xb3, 0xd7, 0xe8, 0xeb, 0xdc, 0xe5, 0xcf, 0x3d, 0xb3 }, + { 0x69, 0x6e, 0x5d, 0x46, 0xe6, 0xc5, 0x7e, 0x87, 0x96, 0xe4, 0x73, 0x5d, 0x08, 0x91, 0x6e, 0x0b, 0x79, 0x29, 0xb3, 0xcf, 0x29, 0x8c, 0x29, 0x6d, 0x22, 0xe9, 0xd3, 0x01, 0x96, 0x53, 0x37, 0x1c }, + { 0x1f, 0x56, 0x47, 0xc1, 0xd3, 0xb0, 0x88, 0x22, 0x88, 0x85, 0x86, 0x5c, 0x89, 0x40, 0x90, 0x8b, 0xf4, 0x0d, 0x1a, 0x82, 0x72, 0x82, 0x19, 0x73, 0xb1, 0x60, 0x00, 0x8e, 0x7a, 0x3c, 0xe2, 0xeb }, + { 0xb6, 0xe7, 0x6c, 0x33, 0x0f, 0x02, 0x1a, 0x5b, 0xda, 0x65, 0x87, 0x50, 0x10, 0xb0, 0xed, 0xf0, 0x91, 0x26, 0xc0, 0xf5, 0x10, 0xea, 0x84, 0x90, 0x48, 0x19, 0x20, 0x03, 0xae, 0xf4, 0xc6, 0x1c }, + { 0x3c, 0xd9, 0x52, 0xa0, 0xbe, 0xad, 0xa4, 0x1a, 0xbb, 0x42, 0x4c, 0xe4, 0x7f, 0x94, 0xb4, 0x2b, 0xe6, 0x4e, 0x1f, 0xfb, 0x0f, 0xd0, 0x78, 0x22, 0x76, 0x80, 0x79, 0x46, 0xd0, 0xd0, 0xbc, 0x55 }, + { 0x98, 0xd9, 0x26, 0x77, 0x43, 0x9b, 0x41, 0xb7, 0xbb, 0x51, 0x33, 0x12, 0xaf, 0xb9, 0x2b, 0xcc, 0x8e, 0xe9, 0x68, 0xb2, 0xe3, 0xb2, 0x38, 0xce, 0xcb, 0x9b, 0x0f, 0x34, 0xc9, 0xbb, 0x63, 0xd0 }, + { 0xec, 0xbc, 0xa2, 0xcf, 0x08, 0xae, 0x57, 0xd5, 0x17, 0xad, 0x16, 0x15, 0x8a, 0x32, 0xbf, 0xa7, 0xdc, 0x03, 0x82, 0xea, 0xed, 0xa1, 0x28, 0xe9, 0x18, 0x86, 0x73, 0x4c, 0x24, 0xa0, 0xb2, 0x9d }, + { 0x94, 0x2c, 0xc7, 0xc0, 0xb5, 0x2e, 0x2b, 0x16, 0xa4, 0xb8, 0x9f, 0xa4, 0xfc, 0x7e, 0x0b, 0xf6, 0x09, 0xe2, 0x9a, 0x08, 0xc1, 0xa8, 0x54, 0x34, 0x52, 0xb7, 0x7c, 0x7b, 0xfd, 0x11, 0xbb, 0x28 }, + { 0x8a, 0x06, 0x5d, 0x8b, 0x61, 0xa0, 0xdf, 0xfb, 0x17, 0x0d, 0x56, 0x27, 0x73, 0x5a, 0x76, 0xb0, 0xe9, 0x50, 0x60, 0x37, 0x80, 0x8c, 0xba, 0x16, 0xc3, 0x45, 0x00, 0x7c, 0x9f, 0x79, 0xcf, 0x8f }, + { 0x1b, 0x9f, 0xa1, 0x97, 0x14, 0x65, 0x9c, 0x78, 0xff, 0x41, 0x38, 0x71, 0x84, 0x92, 0x15, 0x36, 0x10, 0x29, 0xac, 0x80, 0x2b, 0x1c, 0xbc, 0xd5, 0x4e, 0x40, 0x8b, 0xd8, 0x72, 0x87, 0xf8, 0x1f }, + { 0x8d, 0xab, 0x07, 0x1b, 0xcd, 0x6c, 0x72, 0x92, 0xa9, 0xef, 0x72, 0x7b, 0x4a, 0xe0, 0xd8, 0x67, 0x13, 0x30, 0x1d, 0xa8, 0x61, 0x8d, 0x9a, 0x48, 0xad, 0xce, 0x55, 0xf3, 0x03, 0xa8, 0x69, 0xa1 }, + { 0x82, 0x53, 0xe3, 0xe7, 0xc7, 0xb6, 0x84, 0xb9, 0xcb, 0x2b, 0xeb, 0x01, 0x4c, 0xe3, 0x30, 0xff, 0x3d, 0x99, 0xd1, 0x7a, 0xbb, 0xdb, 0xab, 0xe4, 0xf4, 0xd6, 0x74, 0xde, 0xd5, 0x3f, 0xfc, 0x6b }, + { 0xf1, 0x95, 0xf3, 0x21, 0xe9, 0xe3, 0xd6, 0xbd, 0x7d, 0x07, 0x45, 0x04, 0xdd, 0x2a, 0xb0, 0xe6, 0x24, 0x1f, 0x92, 0xe7, 0x84, 0xb1, 0xaa, 0x27, 0x1f, 0xf6, 0x48, 0xb1, 0xca, 0xb6, 0xd7, 0xf6 }, + { 0x27, 0xe4, 0xcc, 0x72, 0x09, 0x0f, 0x24, 0x12, 0x66, 0x47, 0x6a, 0x7c, 0x09, 0x49, 0x5f, 0x2d, 0xb1, 0x53, 0xd5, 0xbc, 0xbd, 0x76, 0x19, 0x03, 0xef, 0x79, 0x27, 0x5e, 0xc5, 0x6b, 0x2e, 0xd8 }, + { 0x89, 0x9c, 0x24, 0x05, 0x78, 0x8e, 0x25, 0xb9, 0x9a, 0x18, 0x46, 0x35, 0x5e, 0x64, 0x6d, 0x77, 0xcf, 0x40, 0x00, 0x83, 0x41, 0x5f, 0x7d, 0xc5, 0xaf, 0xe6, 0x9d, 0x6e, 0x17, 0xc0, 0x00, 0x23 }, + { 0xa5, 0x9b, 0x78, 0xc4, 0x90, 0x57, 0x44, 0x07, 0x6b, 0xfe, 0xe8, 0x94, 0xde, 0x70, 0x7d, 0x4f, 0x12, 0x0b, 0x5c, 0x68, 0x93, 0xea, 0x04, 0x00, 0x29, 0x7d, 0x0b, 0xb8, 0x34, 0x72, 0x76, 0x32 }, + { 0x59, 0xdc, 0x78, 0xb1, 0x05, 0x64, 0x97, 0x07, 0xa2, 0xbb, 0x44, 0x19, 0xc4, 0x8f, 0x00, 0x54, 0x00, 0xd3, 0x97, 0x3d, 0xe3, 0x73, 0x66, 0x10, 0x23, 0x04, 0x35, 0xb1, 0x04, 0x24, 0xb2, 0x4f }, + { 0xc0, 0x14, 0x9d, 0x1d, 0x7e, 0x7a, 0x63, 0x53, 0xa6, 0xd9, 0x06, 0xef, 0xe7, 0x28, 0xf2, 0xf3, 0x29, 0xfe, 0x14, 0xa4, 0x14, 0x9a, 0x3e, 0xa7, 0x76, 0x09, 0xbc, 0x42, 0xb9, 0x75, 0xdd, 0xfa }, + { 0xa3, 0x2f, 0x24, 0x14, 0x74, 0xa6, 0xc1, 0x69, 0x32, 0xe9, 0x24, 0x3b, 0xe0, 0xcf, 0x09, 0xbc, 0xdc, 0x7e, 0x0c, 0xa0, 0xe7, 0xa6, 0xa1, 0xb9, 0xb1, 0xa0, 0xf0, 0x1e, 0x41, 0x50, 0x23, 0x77 }, + { 0xb2, 0x39, 0xb2, 0xe4, 0xf8, 0x18, 0x41, 0x36, 0x1c, 0x13, 0x39, 0xf6, 0x8e, 0x2c, 0x35, 0x9f, 0x92, 0x9a, 0xf9, 0xad, 0x9f, 0x34, 0xe0, 0x1a, 0xab, 0x46, 0x31, 0xad, 0x6d, 0x55, 0x00, 0xb0 }, + { 0x85, 0xfb, 0x41, 0x9c, 0x70, 0x02, 0xa3, 0xe0, 0xb4, 0xb6, 0xea, 0x09, 0x3b, 0x4c, 0x1a, 0xc6, 0x93, 0x66, 0x45, 0xb6, 0x5d, 0xac, 0x5a, 0xc1, 0x5a, 0x85, 0x28, 0xb7, 0xb9, 0x4c, 0x17, 0x54 }, + { 0x96, 0x19, 0x72, 0x06, 0x25, 0xf1, 0x90, 0xb9, 0x3a, 0x3f, 0xad, 0x18, 0x6a, 0xb3, 0x14, 0x18, 0x96, 0x33, 0xc0, 0xd3, 0xa0, 0x1e, 0x6f, 0x9b, 0xc8, 0xc4, 0xa8, 0xf8, 0x2f, 0x38, 0x3d, 0xbf }, + { 0x7d, 0x62, 0x0d, 0x90, 0xfe, 0x69, 0xfa, 0x46, 0x9a, 0x65, 0x38, 0x38, 0x89, 0x70, 0xa1, 0xaa, 0x09, 0xbb, 0x48, 0xa2, 0xd5, 0x9b, 0x34, 0x7b, 0x97, 0xe8, 0xce, 0x71, 0xf4, 0x8c, 0x7f, 0x46 }, + { 0x29, 0x43, 0x83, 0x56, 0x85, 0x96, 0xfb, 0x37, 0xc7, 0x5b, 0xba, 0xcd, 0x97, 0x9c, 0x5f, 0xf6, 0xf2, 0x0a, 0x55, 0x6b, 0xf8, 0x87, 0x9c, 0xc7, 0x29, 0x24, 0x85, 0x5d, 0xf9, 0xb8, 0x24, 0x0e }, + { 0x16, 0xb1, 0x8a, 0xb3, 0x14, 0x35, 0x9c, 0x2b, 0x83, 0x3c, 0x1c, 0x69, 0x86, 0xd4, 0x8c, 0x55, 0xa9, 0xfc, 0x97, 0xcd, 0xe9, 0xa3, 0xc1, 0xf1, 0x0a, 0x31, 0x77, 0x14, 0x0f, 0x73, 0xf7, 0x38 }, + { 0x8c, 0xbb, 0xdd, 0x14, 0xbc, 0x33, 0xf0, 0x4c, 0xf4, 0x58, 0x13, 0xe4, 0xa1, 0x53, 0xa2, 0x73, 0xd3, 0x6a, 0xda, 0xd5, 0xce, 0x71, 0xf4, 0x99, 0xee, 0xb8, 0x7f, 0xb8, 0xac, 0x63, 0xb7, 0x29 }, + { 0x69, 0xc9, 0xa4, 0x98, 0xdb, 0x17, 0x4e, 0xca, 0xef, 0xcc, 0x5a, 0x3a, 0xc9, 0xfd, 0xed, 0xf0, 0xf8, 0x13, 0xa5, 0xbe, 0xc7, 0x27, 0xf1, 0xe7, 0x75, 0xba, 0xbd, 0xec, 0x77, 0x18, 0x81, 0x6e }, + { 0xb4, 0x62, 0xc3, 0xbe, 0x40, 0x44, 0x8f, 0x1d, 0x4f, 0x80, 0x62, 0x62, 0x54, 0xe5, 0x35, 0xb0, 0x8b, 0xc9, 0xcd, 0xcf, 0xf5, 0x99, 0xa7, 0x68, 0x57, 0x8d, 0x4b, 0x28, 0x81, 0xa8, 0xe3, 0xf0 }, + { 0x55, 0x3e, 0x9d, 0x9c, 0x5f, 0x36, 0x0a, 0xc0, 0xb7, 0x4a, 0x7d, 0x44, 0xe5, 0xa3, 0x91, 0xda, 0xd4, 0xce, 0xd0, 0x3e, 0x0c, 0x24, 0x18, 0x3b, 0x7e, 0x8e, 0xca, 0xbd, 0xf1, 0x71, 0x5a, 0x64 }, + { 0x7a, 0x7c, 0x55, 0xa5, 0x6f, 0xa9, 0xae, 0x51, 0xe6, 0x55, 0xe0, 0x19, 0x75, 0xd8, 0xa6, 0xff, 0x4a, 0xe9, 0xe4, 0xb4, 0x86, 0xfc, 0xbe, 0x4e, 0xac, 0x04, 0x45, 0x88, 0xf2, 0x45, 0xeb, 0xea }, + { 0x2a, 0xfd, 0xf3, 0xc8, 0x2a, 0xbc, 0x48, 0x67, 0xf5, 0xde, 0x11, 0x12, 0x86, 0xc2, 0xb3, 0xbe, 0x7d, 0x6e, 0x48, 0x65, 0x7b, 0xa9, 0x23, 0xcf, 0xbf, 0x10, 0x1a, 0x6d, 0xfc, 0xf9, 0xdb, 0x9a }, + { 0x41, 0x03, 0x7d, 0x2e, 0xdc, 0xdc, 0xe0, 0xc4, 0x9b, 0x7f, 0xb4, 0xa6, 0xaa, 0x09, 0x99, 0xca, 0x66, 0x97, 0x6c, 0x74, 0x83, 0xaf, 0xe6, 0x31, 0xd4, 0xed, 0xa2, 0x83, 0x14, 0x4f, 0x6d, 0xfc }, + { 0xc4, 0x46, 0x6f, 0x84, 0x97, 0xca, 0x2e, 0xeb, 0x45, 0x83, 0xa0, 0xb0, 0x8e, 0x9d, 0x9a, 0xc7, 0x43, 0x95, 0x70, 0x9f, 0xda, 0x10, 0x9d, 0x24, 0xf2, 0xe4, 0x46, 0x21, 0x96, 0x77, 0x9c, 0x5d }, + { 0x75, 0xf6, 0x09, 0x33, 0x8a, 0xa6, 0x7d, 0x96, 0x9a, 0x2a, 0xe2, 0xa2, 0x36, 0x2b, 0x2d, 0xa9, 0xd7, 0x7c, 0x69, 0x5d, 0xfd, 0x1d, 0xf7, 0x22, 0x4a, 0x69, 0x01, 0xdb, 0x93, 0x2c, 0x33, 0x64 }, + { 0x68, 0x60, 0x6c, 0xeb, 0x98, 0x9d, 0x54, 0x88, 0xfc, 0x7c, 0xf6, 0x49, 0xf3, 0xd7, 0xc2, 0x72, 0xef, 0x05, 0x5d, 0xa1, 0xa9, 0x3f, 0xae, 0xcd, 0x55, 0xfe, 0x06, 0xf6, 0x96, 0x70, 0x98, 0xca }, + { 0x44, 0x34, 0x6b, 0xde, 0xb7, 0xe0, 0x52, 0xf6, 0x25, 0x50, 0x48, 0xf0, 0xd9, 0xb4, 0x2c, 0x42, 0x5b, 0xab, 0x9c, 0x3d, 0xd2, 0x41, 0x68, 0x21, 0x2c, 0x3e, 0xcf, 0x1e, 0xbf, 0x34, 0xe6, 0xae }, + { 0x8e, 0x9c, 0xf6, 0xe1, 0xf3, 0x66, 0x47, 0x1f, 0x2a, 0xc7, 0xd2, 0xee, 0x9b, 0x5e, 0x62, 0x66, 0xfd, 0xa7, 0x1f, 0x8f, 0x2e, 0x41, 0x09, 0xf2, 0x23, 0x7e, 0xd5, 0xf8, 0x81, 0x3f, 0xc7, 0x18 }, + { 0x84, 0xbb, 0xeb, 0x84, 0x06, 0xd2, 0x50, 0x95, 0x1f, 0x8c, 0x1b, 0x3e, 0x86, 0xa7, 0xc0, 0x10, 0x08, 0x29, 0x21, 0x83, 0x3d, 0xfd, 0x95, 0x55, 0xa2, 0xf9, 0x09, 0xb1, 0x08, 0x6e, 0xb4, 0xb8 }, + { 0xee, 0x66, 0x6f, 0x3e, 0xef, 0x0f, 0x7e, 0x2a, 0x9c, 0x22, 0x29, 0x58, 0xc9, 0x7e, 0xaf, 0x35, 0xf5, 0x1c, 0xed, 0x39, 0x3d, 0x71, 0x44, 0x85, 0xab, 0x09, 0xa0, 0x69, 0x34, 0x0f, 0xdf, 0x88 }, + { 0xc1, 0x53, 0xd3, 0x4a, 0x65, 0xc4, 0x7b, 0x4a, 0x62, 0xc5, 0xca, 0xcf, 0x24, 0x01, 0x09, 0x75, 0xd0, 0x35, 0x6b, 0x2f, 0x32, 0xc8, 0xf5, 0xda, 0x53, 0x0d, 0x33, 0x88, 0x16, 0xad, 0x5d, 0xe6 }, + { 0x9f, 0xc5, 0x45, 0x01, 0x09, 0xe1, 0xb7, 0x79, 0xf6, 0xc7, 0xae, 0x79, 0xd5, 0x6c, 0x27, 0x63, 0x5c, 0x8d, 0xd4, 0x26, 0xc5, 0xa9, 0xd5, 0x4e, 0x25, 0x78, 0xdb, 0x98, 0x9b, 0x8c, 0x3b, 0x4e }, + { 0xd1, 0x2b, 0xf3, 0x73, 0x2e, 0xf4, 0xaf, 0x5c, 0x22, 0xfa, 0x90, 0x35, 0x6a, 0xf8, 0xfc, 0x50, 0xfc, 0xb4, 0x0f, 0x8f, 0x2e, 0xa5, 0xc8, 0x59, 0x47, 0x37, 0xa3, 0xb3, 0xd5, 0xab, 0xdb, 0xd7 }, + { 0x11, 0x03, 0x0b, 0x92, 0x89, 0xbb, 0xa5, 0xaf, 0x65, 0x26, 0x06, 0x72, 0xab, 0x6f, 0xee, 0x88, 0xb8, 0x74, 0x20, 0xac, 0xef, 0x4a, 0x17, 0x89, 0xa2, 0x07, 0x3b, 0x7e, 0xc2, 0xf2, 0xa0, 0x9e }, + { 0x69, 0xcb, 0x19, 0x2b, 0x84, 0x44, 0x00, 0x5c, 0x8c, 0x0c, 0xeb, 0x12, 0xc8, 0x46, 0x86, 0x07, 0x68, 0x18, 0x8c, 0xda, 0x0a, 0xec, 0x27, 0xa9, 0xc8, 0xa5, 0x5c, 0xde, 0xe2, 0x12, 0x36, 0x32 }, + { 0xdb, 0x44, 0x4c, 0x15, 0x59, 0x7b, 0x5f, 0x1a, 0x03, 0xd1, 0xf9, 0xed, 0xd1, 0x6e, 0x4a, 0x9f, 0x43, 0xa6, 0x67, 0xcc, 0x27, 0x51, 0x75, 0xdf, 0xa2, 0xb7, 0x04, 0xe3, 0xbb, 0x1a, 0x9b, 0x83 }, + { 0x3f, 0xb7, 0x35, 0x06, 0x1a, 0xbc, 0x51, 0x9d, 0xfe, 0x97, 0x9e, 0x54, 0xc1, 0xee, 0x5b, 0xfa, 0xd0, 0xa9, 0xd8, 0x58, 0xb3, 0x31, 0x5b, 0xad, 0x34, 0xbd, 0xe9, 0x99, 0xef, 0xd7, 0x24, 0xdd }, + }; + unsigned char inp[1000], out[1000]; + unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; + unsigned long ilen, klen = sizeof(key), mlen = 32; + blake2smac_state st; + + for (ilen = 0; ilen < 256; ilen++) inp[ilen] = (unsigned char)ilen; + + for (ilen = 0; ilen < 256; ilen++) { + const unsigned char *mac = tests[ilen]; + unsigned long olen = mlen; + /* process piece by piece */ + if (ilen > 15) { + blake2smac_init(&st, olen, key, klen); + blake2smac_process(&st, (unsigned char*)inp, 5); + blake2smac_process(&st, (unsigned char*)inp + 5, 4); + blake2smac_process(&st, (unsigned char*)inp + 9, 3); + blake2smac_process(&st, (unsigned char*)inp + 12, 2); + blake2smac_process(&st, (unsigned char*)inp + 14, 1); + blake2smac_process(&st, (unsigned char*)inp + 15, ilen - 15); + blake2smac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC multi", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + /* process in one go */ + blake2smac_init(&st, olen, key, klen); + blake2smac_process(&st, (unsigned char*)inp, ilen); + blake2smac_done(&st, out, &olen); + if (compare_testvector(out, olen, mac, mlen, "BLAKE2S MAC single", ilen) != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/f9/f9_done.c b/deps/libtomcrypt/src/mac/f9/f9_done.c new file mode 100644 index 0000000..38d1371 --- /dev/null +++ b/deps/libtomcrypt/src/mac/f9/f9_done.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_done.c + f9 Support, terminate the state +*/ + +#ifdef LTC_F9_MODE + +/** Terminate the f9-MAC state + @param f9 f9 state to terminate + @param out [out] Destination for the MAC tag + @param outlen [in/out] Destination size and final tag size + Return CRYPT_OK on success +*/ +int f9_done(f9_state *f9, unsigned char *out, unsigned long *outlen) +{ + int err, x; + LTC_ARGCHK(f9 != NULL); + LTC_ARGCHK(out != NULL); + + /* check structure */ + if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { + return err; + } + + if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) || + (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + + if (f9->buflen != 0) { + /* encrypt */ + cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key); + f9->buflen = 0; + for (x = 0; x < f9->blocksize; x++) { + f9->ACC[x] ^= f9->IV[x]; + } + } + + /* schedule modified key */ + if ((err = cipher_descriptor[f9->cipher].setup(f9->akey, f9->keylen, 0, &f9->key)) != CRYPT_OK) { + return err; + } + + /* encrypt the ACC */ + cipher_descriptor[f9->cipher].ecb_encrypt(f9->ACC, f9->ACC, &f9->key); + cipher_descriptor[f9->cipher].done(&f9->key); + + /* extract tag */ + for (x = 0; x < f9->blocksize && (unsigned long)x < *outlen; x++) { + out[x] = f9->ACC[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(f9, sizeof(*f9)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/f9/f9_file.c b/deps/libtomcrypt/src/mac/f9/f9_file.c new file mode 100644 index 0000000..c06f548 --- /dev/null +++ b/deps/libtomcrypt/src/mac/f9/f9_file.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_file.c + f9 support, process a file, Tom St Denis +*/ + +#ifdef LTC_F9_MODE + +/** + f9 a file + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param fname The name of the file you wish to f9 + @param out [out] Where the authentication tag is to be stored + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int f9_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *fname, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + f9_state f9; + FILE *in; + unsigned char *buf; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = f9_init(&f9, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = f9_process(&f9, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = f9_done(&f9, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&f9, sizeof(f9_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/f9/f9_init.c b/deps/libtomcrypt/src/mac/f9/f9_init.c new file mode 100644 index 0000000..0bd599e --- /dev/null +++ b/deps/libtomcrypt/src/mac/f9/f9_init.c @@ -0,0 +1,58 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_init.c + F9 Support, start an F9 state +*/ + +#ifdef LTC_F9_MODE + +/** Initialize F9-MAC state + @param f9 [out] f9 state to initialize + @param cipher Index of cipher to use + @param key [in] Secret key + @param keylen Length of secret key in octets + Return CRYPT_OK on success +*/ +int f9_init(f9_state *f9, int cipher, const unsigned char *key, unsigned long keylen) +{ + int x, err; + + LTC_ARGCHK(f9 != NULL); + LTC_ARGCHK(key != NULL); + + /* schedule the key */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &f9->key)) != CRYPT_OK) { + goto done; + } + + /* make the second key */ + for (x = 0; (unsigned)x < keylen; x++) { + f9->akey[x] = key[x] ^ 0xAA; + } + + /* setup struct */ + zeromem(f9->IV, cipher_descriptor[cipher].block_length); + zeromem(f9->ACC, cipher_descriptor[cipher].block_length); + f9->blocksize = cipher_descriptor[cipher].block_length; + f9->cipher = cipher; + f9->buflen = 0; + f9->keylen = keylen; +done: + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/f9/f9_memory.c b/deps/libtomcrypt/src/mac/f9/f9_memory.c new file mode 100644 index 0000000..5f05209 --- /dev/null +++ b/deps/libtomcrypt/src/mac/f9/f9_memory.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_process.c + f9 Support, Process a block through F9-MAC +*/ + +#ifdef LTC_F9_MODE + +/** f9-MAC a block of memory + @param cipher Index of cipher to use + @param key [in] Secret key + @param keylen Length of key in octets + @param in [in] Message to MAC + @param inlen Length of input in octets + @param out [out] Destination for the MAC tag + @param outlen [in/out] Output size and final tag size + Return CRYPT_OK on success. +*/ +int f9_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + f9_state *f9; + int err; + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* Use accelerator if found */ + if (cipher_descriptor[cipher].f9_memory != NULL) { + return cipher_descriptor[cipher].f9_memory(key, keylen, in, inlen, out, outlen); + } + + f9 = XCALLOC(1, sizeof(*f9)); + if (f9 == NULL) { + return CRYPT_MEM; + } + + if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { + goto done; + } + + if ((err = f9_process(f9, in, inlen)) != CRYPT_OK) { + goto done; + } + + err = f9_done(f9, out, outlen); +done: + XFREE(f9); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/f9/f9_memory_multi.c b/deps/libtomcrypt/src/mac/f9/f9_memory_multi.c new file mode 100644 index 0000000..c97ffd3 --- /dev/null +++ b/deps/libtomcrypt/src/mac/f9/f9_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file f9_memory_multi.c + f9 support, process multiple blocks of memory, Tom St Denis +*/ + +#ifdef LTC_F9_MODE + +/** + f9 multiple blocks of memory + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] The destination of the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag (octets) + @param in The data to send through f9 + @param inlen The length of the data to send through f9 (octets) + @param ... tuples of (data,len) pairs to f9, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int f9_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + int err; + f9_state *f9; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for f9 state */ + f9 = XMALLOC(sizeof(f9_state)); + if (f9 == NULL) { + return CRYPT_MEM; + } + + /* f9 process the message */ + if ((err = f9_init(f9, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = f9_process(f9, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = f9_done(f9, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(f9, sizeof(f9_state)); +#endif + XFREE(f9); + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/f9/f9_process.c b/deps/libtomcrypt/src/mac/f9/f9_process.c new file mode 100644 index 0000000..e416b54 --- /dev/null +++ b/deps/libtomcrypt/src/mac/f9/f9_process.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_process.c + f9 Support, process blocks with f9 +*/ + +#ifdef LTC_F9_MODE + +/** Process data through f9-MAC + @param f9 The f9-MAC state + @param in Input data to process + @param inlen Length of input in octets + Return CRYPT_OK on success +*/ +int f9_process(f9_state *f9, const unsigned char *in, unsigned long inlen) +{ + int err, x; + + LTC_ARGCHK(f9 != NULL); + LTC_ARGCHK(in != NULL); + + /* check structure */ + if ((err = cipher_is_valid(f9->cipher)) != CRYPT_OK) { + return err; + } + + if ((f9->blocksize > cipher_descriptor[f9->cipher].block_length) || (f9->blocksize < 0) || + (f9->buflen > f9->blocksize) || (f9->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (f9->buflen == 0) { + while (inlen >= (unsigned long)f9->blocksize) { + for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x]))); + } + cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key); + for (x = 0; x < f9->blocksize; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&(f9->ACC[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(f9->IV[x]))); + } + in += f9->blocksize; + inlen -= f9->blocksize; + } + } +#endif + + while (inlen) { + if (f9->buflen == f9->blocksize) { + cipher_descriptor[f9->cipher].ecb_encrypt(f9->IV, f9->IV, &f9->key); + for (x = 0; x < f9->blocksize; x++) { + f9->ACC[x] ^= f9->IV[x]; + } + f9->buflen = 0; + } + f9->IV[f9->buflen++] ^= *in++; + --inlen; + } + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/f9/f9_test.c b/deps/libtomcrypt/src/mac/f9/f9_test.c new file mode 100644 index 0000000..779fdf1 --- /dev/null +++ b/deps/libtomcrypt/src/mac/f9/f9_test.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f9_test.c + f9 Support, Test F9 mode +*/ + +#ifdef LTC_F9_MODE + +/** Test f9-MAC mode + Return CRYPT_OK on success +*/ +int f9_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct { + int msglen; + unsigned char K[16], M[128], T[4]; + } tests[] = { +{ + 20, + { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }, + { 0x38, 0xA6, 0xF0, 0x56, 0xB8, 0xAE, 0xFD, 0xA9, 0x33, 0x32, 0x34, 0x62, 0x63, 0x39, 0x38, 0x61, 0x37, 0x34, 0x79, 0x40 }, + { 0x46, 0xE0, 0x0D, 0x4B } +}, + +{ + 105, + { 0x83, 0xFD, 0x23, 0xA2, 0x44, 0xA7, 0x4C, 0xF3, 0x58, 0xDA, 0x30, 0x19, 0xF1, 0x72, 0x26, 0x35 }, + { 0x36, 0xAF, 0x61, 0x44, 0x4F, 0x30, 0x2A, 0xD2, + 0x35, 0xC6, 0x87, 0x16, 0x63, 0x3C, 0x66, 0xFB, 0x75, 0x0C, 0x26, 0x68, 0x65, 0xD5, 0x3C, 0x11, 0xEA, 0x05, 0xB1, 0xE9, 0xFA, 0x49, 0xC8, 0x39, 0x8D, 0x48, 0xE1, 0xEF, 0xA5, 0x90, 0x9D, 0x39, + 0x47, 0x90, 0x28, 0x37, 0xF5, 0xAE, 0x96, 0xD5, 0xA0, 0x5B, 0xC8, 0xD6, 0x1C, 0xA8, 0xDB, 0xEF, 0x1B, 0x13, 0xA4, 0xB4, 0xAB, 0xFE, 0x4F, 0xB1, 0x00, 0x60, 0x45, 0xB6, 0x74, 0xBB, 0x54, 0x72, + 0x93, 0x04, 0xC3, 0x82, 0xBE, 0x53, 0xA5, 0xAF, 0x05, 0x55, 0x61, 0x76, 0xF6, 0xEA, 0xA2, 0xEF, 0x1D, 0x05, 0xE4, 0xB0, 0x83, 0x18, 0x1E, 0xE6, 0x74, 0xCD, 0xA5, 0xA4, 0x85, 0xF7, 0x4D, 0x7A, + 0x40|0x80 }, + { 0x95, 0xAE, 0x41, 0xBA }, +} +}; + unsigned char T[16]; + unsigned long taglen; + int err, x, idx; + + /* find kasumi */ + if ((idx = find_cipher("kasumi")) == -1) { + return CRYPT_NOP; + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + taglen = 4; + if ((err = f9_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { + return err; + } + if (compare_testvector(T, taglen, tests[x].T, 4, "F9", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/hmac/hmac_done.c b/deps/libtomcrypt/src/mac/hmac/hmac_done.c new file mode 100644 index 0000000..a3d3c38 --- /dev/null +++ b/deps/libtomcrypt/src/mac/hmac/hmac_done.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_done.c + HMAC support, terminate stream, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/** + Terminate an HMAC session + @param hmac The HMAC state + @param out [out] The destination of the HMAC authentication tag + @param outlen [in/out] The max size and resulting size of the HMAC authentication tag + @return CRYPT_OK if successful +*/ +int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen) +{ + unsigned char *buf, *isha; + unsigned long hashsize, i; + int hash, err; + + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(out != NULL); + + /* test hash */ + hash = hmac->hash; + if((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* get the hash message digest size */ + hashsize = hash_descriptor[hash].hashsize; + + /* allocate buffers */ + buf = XMALLOC(LTC_HMAC_BLOCKSIZE); + isha = XMALLOC(hashsize); + if (buf == NULL || isha == NULL) { + if (buf != NULL) { + XFREE(buf); + } + if (isha != NULL) { + XFREE(isha); + } + return CRYPT_MEM; + } + + /* Get the hash of the first HMAC vector plus the data */ + if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Create the second HMAC vector vector for step (3) */ + for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x5C; + } + + /* Now calculate the "outer" hash for step (5), (6), and (7) */ + if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].process(&hmac->md, isha, hashsize)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash].done(&hmac->md, buf)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* copy to output */ + for (i = 0; i < hashsize && i < *outlen; i++) { + out[i] = buf[i]; + } + *outlen = i; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(isha, hashsize); + zeromem(buf, hashsize); + zeromem(hmac, sizeof(*hmac)); +#endif + + XFREE(isha); + XFREE(buf); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/hmac/hmac_file.c b/deps/libtomcrypt/src/mac/hmac/hmac_file.c new file mode 100644 index 0000000..c944a28 --- /dev/null +++ b/deps/libtomcrypt/src/mac/hmac/hmac_file.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_file.c + HMAC support, process a file, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + HMAC a file + @param hash The index of the hash you wish to use + @param fname The name of the file you wish to HMAC + @param key The secret key + @param keylen The length of the secret key + @param out [out] The HMAC authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int hmac_file(int hash, const char *fname, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(hash); + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + hmac_state hmac; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); /* we don't trap this error since we're already returning an error! */ + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = hmac_done(&hmac, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&hmac, sizeof(hmac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/hmac/hmac_init.c b/deps/libtomcrypt/src/mac/hmac/hmac_init.c new file mode 100644 index 0000000..50c5bcc --- /dev/null +++ b/deps/libtomcrypt/src/mac/hmac/hmac_init.c @@ -0,0 +1,94 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_init.c + HMAC support, initialize state, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +#define LTC_HMAC_BLOCKSIZE hash_descriptor[hash].blocksize + +/** + Initialize an HMAC context. + @param hmac The HMAC state + @param hash The index of the hash you want to use + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen) +{ + unsigned char *buf; + unsigned long hashsize; + unsigned long i, z; + int err; + + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(key != NULL); + + /* valid hash? */ + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + hmac->hash = hash; + hashsize = hash_descriptor[hash].hashsize; + + /* valid key length? */ + if (keylen == 0) { + return CRYPT_INVALID_KEYSIZE; + } + + /* allocate ram for buf */ + buf = XMALLOC(LTC_HMAC_BLOCKSIZE); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* check hash block fits */ + if (sizeof(hmac->key) < LTC_HMAC_BLOCKSIZE) { + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* (1) make sure we have a large enough key */ + if(keylen > LTC_HMAC_BLOCKSIZE) { + z = LTC_HMAC_BLOCKSIZE; + if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + keylen = hashsize; + } else { + XMEMCPY(hmac->key, key, (size_t)keylen); + } + + if(keylen < LTC_HMAC_BLOCKSIZE) { + zeromem((hmac->key) + keylen, (size_t)(LTC_HMAC_BLOCKSIZE - keylen)); + } + + /* Create the initialization vector for step (3) */ + for(i=0; i < LTC_HMAC_BLOCKSIZE; i++) { + buf[i] = hmac->key[i] ^ 0x36; + } + + /* Pre-pend that to the hash data */ + if ((err = hash_descriptor[hash].init(&hmac->md)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hash_descriptor[hash].process(&hmac->md, buf, LTC_HMAC_BLOCKSIZE)) != CRYPT_OK) { + goto LBL_ERR; + } + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, LTC_HMAC_BLOCKSIZE); +#endif + + XFREE(buf); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/hmac/hmac_memory.c b/deps/libtomcrypt/src/mac/hmac/hmac_memory.c new file mode 100644 index 0000000..221be58 --- /dev/null +++ b/deps/libtomcrypt/src/mac/hmac/hmac_memory.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_memory.c + HMAC support, process a block of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + HMAC a block of memory to produce the authentication tag + @param hash The index of the hash to use + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to HMAC + @param inlen The length of the data to HMAC (octets) + @param out [out] Destination of the authentication tag + @param outlen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int hmac_memory(int hash, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + hmac_state *hmac; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + /* is there a descriptor? */ + if (hash_descriptor[hash].hmac_block != NULL) { + return hash_descriptor[hash].hmac_block(key, keylen, in, inlen, out, outlen); + } + + /* nope, so call the hmac functions */ + /* allocate ram for hmac state */ + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL) { + return CRYPT_MEM; + } + + if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_process(hmac, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(hmac, sizeof(hmac_state)); +#endif + + XFREE(hmac); + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/hmac/hmac_memory_multi.c b/deps/libtomcrypt/src/mac/hmac/hmac_memory_multi.c new file mode 100644 index 0000000..2809d71 --- /dev/null +++ b/deps/libtomcrypt/src/mac/hmac/hmac_memory_multi.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file hmac_memory_multi.c + HMAC support, process multiple blocks of memory, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + HMAC multiple blocks of memory to produce the authentication tag + @param hash The index of the hash to use + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] Destination of the authentication tag + @param outlen [in/out] Max size and resulting size of authentication tag + @param in The data to HMAC + @param inlen The length of the data to HMAC (octets) + @param ... tuples of (data,len) pairs to HMAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int hmac_memory_multi(int hash, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) + +{ + hmac_state *hmac; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for hmac state */ + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL) { + return CRYPT_MEM; + } + + if ((err = hmac_init(hmac, hash, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = hmac_process(hmac, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = hmac_done(hmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(hmac, sizeof(hmac_state)); +#endif + XFREE(hmac); + va_end(args); + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/hmac/hmac_process.c b/deps/libtomcrypt/src/mac/hmac/hmac_process.c new file mode 100644 index 0000000..14738b6 --- /dev/null +++ b/deps/libtomcrypt/src/mac/hmac/hmac_process.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_process.c + HMAC support, process data, Tom St Denis/Dobes Vandermeer +*/ + +#ifdef LTC_HMAC + +/** + Process data through HMAC + @param hmac The hmac state + @param in The data to send through HMAC + @param inlen The length of the data to HMAC (octets) + @return CRYPT_OK if successful +*/ +int hmac_process(hmac_state *hmac, const unsigned char *in, unsigned long inlen) +{ + int err; + LTC_ARGCHK(hmac != NULL); + LTC_ARGCHK(in != NULL); + if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) { + return err; + } + return hash_descriptor[hmac->hash].process(&hmac->md, in, inlen); +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/hmac/hmac_test.c b/deps/libtomcrypt/src/mac/hmac/hmac_test.c new file mode 100644 index 0000000..b097003 --- /dev/null +++ b/deps/libtomcrypt/src/mac/hmac/hmac_test.c @@ -0,0 +1,618 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hmac_test.c + HMAC support, self-test, Tom St Denis/Dobes Vandermeer/Steffen Jaeckel +*/ + +#ifdef LTC_HMAC + +/* + TEST CASES SOURCE: + +Network Working Group P. Cheng +Request for Comments: 2202 IBM +Category: Informational R. Glenn + NIST + September 1997 + + Test Cases for HMAC-MD5 and HMAC-SHA-1 + +******************************************************************************* + +Network Working Group J. Kapp +Request for Comments: 2286 Reaper Technologies +Category: Informational February 1998 + + Test Cases for HMAC-RIPEMD160 and HMAC-RIPEMD128 + +******************************************************************************* + +Network Working Group M. Nystrom +Request for Comments: 4231 RSA Security +Category: Standards Track December 2005 + + Identifiers and Test Vectors for HMAC-SHA-224, HMAC-SHA-256, + HMAC-SHA-384, and HMAC-SHA-512 +*/ + +/** + HMAC self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int hmac_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + unsigned char digest[MAXBLOCKSIZE]; + int i; + + static const unsigned char hmac_test_case_keys[][136] = { + { /* 1 */ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b + }, +#ifdef LTC_TEST_EXT + { /* 2 */ + 0x4a, 0x65, 0x66, 0x65 + }, + { /* 4 */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19 + }, + { /* 5 */ + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c + }, + { /* 3, 6, 7 */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + } +#endif /* LTC_TEST_EXT */ + }; + + + static const unsigned char hmac_test_case_data[][153] = { + { + "Hi There" + }, +#ifdef LTC_TEST_EXT + { + "what do ya want for nothing?" + }, + { + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd + }, + { + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd + }, + { + "Test With Truncation" + }, + { + "Test Using Larger Than Block-Size Key - Hash Key First" + }, + { + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" + }, + { + "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm." + } +#endif /* LTC_TEST_EXT */ + }; + + static const struct hmac_test_case { + const char *num; + const char *algo; + const unsigned char *key; + unsigned long keylen; + const unsigned char *data; + unsigned long datalen; + unsigned char digest[MAXBLOCKSIZE]; + } cases[] = { + /* + RFC 2202 3. Test Cases for HMAC-SHA-1 + */ + { "rfc2202 3.1", "sha1", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, + 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, + 0xf1, 0x46, 0xbe, 0x00} }, + +#ifdef LTC_TEST_EXT + { "rfc2202 3.2", "sha1", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, + 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, + 0x25, 0x9a, 0x7c, 0x79} }, + + { "rfc2202 3.3", "sha1", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, + 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, + 0x63, 0xf1, 0x75, 0xd3} }, + + { "rfc2202 3.4", "sha1", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, + 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, + 0x2d, 0x72, 0x35, 0xda} }, + + { "rfc2202 3.5", "sha1", + hmac_test_case_keys[3], 20, + hmac_test_case_data[4], 20, + {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, + 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} }, + + { "rfc2202 3.6", "sha1", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, + 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, + 0xed, 0x40, 0x21, 0x12} }, + + { "rfc2202 3.7", "sha1", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, + 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 2202 2. Test Cases for HMAC-MD5 + */ + { "rfc2202 2.1", "md5", + hmac_test_case_keys[0], 16, + hmac_test_case_data[0], 8, + {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, + 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} }, + +#ifdef LTC_TEST_EXT + { "rfc2202 2.2", "md5", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, + 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} }, + + { "rfc2202 2.3", "md5", + hmac_test_case_keys[4], 16, + hmac_test_case_data[2], 50, + {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, + 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} }, + + { "rfc2202 2.4", "md5", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, + 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} }, + + { "rfc2202 2.5", "md5", + hmac_test_case_keys[3], 16, + hmac_test_case_data[4], 20, + {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, + 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} }, + + { "rfc2202 2.6", "md5", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, + 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} }, + + { "rfc2202 2.7", "md5", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, + 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 2286 2. Test Cases for HMAC-RIPEMD160 + */ + { "rfc2286 2.1", "rmd160", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0x24, 0xcb, 0x4b, 0xd6, 0x7d, 0x20, 0xfc, 0x1a, + 0x5d, 0x2e, 0xd7, 0x73, 0x2d, 0xcc, 0x39, 0x37, + 0x7f, 0x0a, 0x56, 0x68} }, + +#ifdef LTC_TEST_EXT + { "rfc2286 2.2", "rmd160", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xdd, 0xa6, 0xc0, 0x21, 0x3a, 0x48, 0x5a, 0x9e, + 0x24, 0xf4, 0x74, 0x20, 0x64, 0xa7, 0xf0, 0x33, + 0xb4, 0x3c, 0x40, 0x69} }, + + { "rfc2286 2.3", "rmd160", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0xb0, 0xb1, 0x05, 0x36, 0x0d, 0xe7, 0x59, 0x96, + 0x0a, 0xb4, 0xf3, 0x52, 0x98, 0xe1, 0x16, 0xe2, + 0x95, 0xd8, 0xe7, 0xc1} }, + + { "rfc2286 2.4", "rmd160", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0xd5, 0xca, 0x86, 0x2f, 0x4d, 0x21, 0xd5, 0xe6, + 0x10, 0xe1, 0x8b, 0x4c, 0xf1, 0xbe, 0xb9, 0x7a, + 0x43, 0x65, 0xec, 0xf4} }, + + { "rfc2286 2.5", "rmd160", + hmac_test_case_keys[3], 20, + hmac_test_case_data[4], 20, + {0x76, 0x19, 0x69, 0x39, 0x78, 0xf9, 0x1d, 0x90, + 0x53, 0x9a, 0xe7, 0x86, 0x50, 0x0f, 0xf3, 0xd8, + 0xe0, 0x51, 0x8e, 0x39} }, + + { "rfc2286 2.6", "rmd160", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0x64, 0x66, 0xca, 0x07, 0xac, 0x5e, 0xac, 0x29, + 0xe1, 0xbd, 0x52, 0x3e, 0x5a, 0xda, 0x76, 0x05, + 0xb7, 0x91, 0xfd, 0x8b} }, + + { "rfc2286 2.7", "rmd160", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0x69, 0xea, 0x60, 0x79, 0x8d, 0x71, 0x61, 0x6c, + 0xce, 0x5f, 0xd0, 0x87, 0x1e, 0x23, 0x75, 0x4c, + 0xd7, 0x5d, 0x5a, 0x0a} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 2286 3. Test Cases for HMAC-RIPEMD128 + */ + { "rfc2286 3.1", "rmd128", + hmac_test_case_keys[0], 16, + hmac_test_case_data[0], 8, + {0xfb, 0xf6, 0x1f, 0x94, 0x92, 0xaa, 0x4b, 0xbf, + 0x81, 0xc1, 0x72, 0xe8, 0x4e, 0x07, 0x34, 0xdb} }, + +#ifdef LTC_TEST_EXT + { "rfc2286 3.2", "rmd128", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x87, 0x5f, 0x82, 0x88, 0x62, 0xb6, 0xb3, 0x34, + 0xb4, 0x27, 0xc5, 0x5f, 0x9f, 0x7f, 0xf0, 0x9b} }, + + { "rfc2286 3.3", "rmd128", + hmac_test_case_keys[4], 16, + hmac_test_case_data[2], 50, + {0x09, 0xf0, 0xb2, 0x84, 0x6d, 0x2f, 0x54, 0x3d, + 0xa3, 0x63, 0xcb, 0xec, 0x8d, 0x62, 0xa3, 0x8d} }, + + { "rfc2286 3.4", "rmd128", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0xbd, 0xbb, 0xd7, 0xcf, 0x03, 0xe4, 0x4b, 0x5a, + 0xa6, 0x0a, 0xf8, 0x15, 0xbe, 0x4d, 0x22, 0x94} }, + + { "rfc2286 3.5", "rmd128", + hmac_test_case_keys[3], 16, + hmac_test_case_data[4], 20, + {0xe7, 0x98, 0x08, 0xf2, 0x4b, 0x25, 0xfd, 0x03, + 0x1c, 0x15, 0x5f, 0x0d, 0x55, 0x1d, 0x9a, 0x3a} }, + + { "rfc2286 3.6", "rmd128", + hmac_test_case_keys[4], 80, + hmac_test_case_data[5], 54, + {0xdc, 0x73, 0x29, 0x28, 0xde, 0x98, 0x10, 0x4a, + 0x1f, 0x59, 0xd3, 0x73, 0xc1, 0x50, 0xac, 0xbb} }, + + { "rfc2286 3.7", "rmd128", + hmac_test_case_keys[4], 80, + hmac_test_case_data[6], 73, + {0x5c, 0x6b, 0xec, 0x96, 0x79, 0x3e, 0x16, 0xd4, + 0x06, 0x90, 0xc2, 0x37, 0x63, 0x5f, 0x30, 0xc5} }, +#endif /* LTC_TEST_EXT */ + + /* + RFC 4231 4. Test Vectors + Ch. 4.6 with truncated output left out to simplify tests + */ + { "rfc4231 4.2", "sha224", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, + 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f, + 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, + 0x53, 0x68, 0x4b, 0x22} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha224", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, + 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, + 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, + 0x8f, 0xd0, 0x5e, 0x44} }, + + { "rfc4231 4.4", "sha224", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, + 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64, + 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, + 0xec, 0x83, 0x33, 0xea} }, + + { "rfc4231 4.5", "sha224", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, + 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c, + 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, + 0xe7, 0xaf, 0xec, 0x5a} }, + + { "rfc4231 4.7", "sha224", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, + 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2, + 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, + 0x3f, 0xa6, 0x87, 0x0e} }, + + { "rfc4231 4.8", "sha224", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, + 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd, + 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, + 0xf6, 0xf5, 0x65, 0xd1} }, +#endif /* LTC_TEST_EXT */ + + { "rfc4231 4.2", "sha256", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, + 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, + 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, + 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha256", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43} }, + + { "rfc4231 4.4", "sha256", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, + 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, + 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, + 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe} }, + + { "rfc4231 4.5", "sha256", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, + 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, + 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, + 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b} }, + + { "rfc4231 4.7", "sha256", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, + 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, + 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, + 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54} }, + + { "rfc4231 4.8", "sha256", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, + 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, + 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, + 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2} }, +#endif /* LTC_TEST_EXT */ + + { "rfc4231 4.2", "sha384", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, + 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, + 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, + 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, + 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, + 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha384", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, + 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, + 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, + 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, + 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, + 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49} }, + + { "rfc4231 4.4", "sha384", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, + 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f, + 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, + 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, + 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, + 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27} }, + + { "rfc4231 4.5", "sha384", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, + 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7, + 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, + 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, + 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, + 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb} }, + + { "rfc4231 4.7", "sha384", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, + 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4, + 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, + 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, + 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, + 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52} }, + + { "rfc4231 4.8", "sha384", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, + 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c, + 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, + 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, + 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, + 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e} }, +#endif /* LTC_TEST_EXT */ + + { "rfc4231 4.2", "sha512", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, + 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, + 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, + 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, + 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, + 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, + 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, + 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54} }, + +#ifdef LTC_TEST_EXT + { "rfc4231 4.3", "sha512", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, + 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, + 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, + 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, + 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, + 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, + 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, + 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37} }, + + { "rfc4231 4.4", "sha512", + hmac_test_case_keys[4], 20, + hmac_test_case_data[2], 50, + {0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, + 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, + 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, + 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, + 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, + 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, + 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, + 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb} }, + + { "rfc4231 4.5", "sha512", + hmac_test_case_keys[2], 25, + hmac_test_case_data[3], 50, + {0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, + 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, + 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, + 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, + 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, + 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, + 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, + 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd} }, + + { "rfc4231 4.7", "sha512", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, + 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4, + 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, + 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, + 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, + 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, + 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, + 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98} }, + + { "rfc4231 4.8", "sha512", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, + 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd, + 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, + 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, + 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, + 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, + 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, + 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58} }, +#endif /* LTC_TEST_EXT */ + + }; + + unsigned long outlen; + int err; + int tested=0,failed=0; + for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { + int hash = find_hash(cases[i].algo); + if (hash == -1) continue; + ++tested; + outlen = sizeof(digest); + if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) { +#ifdef LTC_TEST_DBG + printf("HMAC-%s test %s, %s\n", cases[i].algo, cases[i].num, error_to_string(err)); +#endif + return err; + } + + if(compare_testvector(digest, outlen, cases[i].digest, (size_t)hash_descriptor[hash].hashsize, cases[i].num, i)) { + failed++; + } + } + + if (failed != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + if (tested == 0) { + return CRYPT_NOP; + } + return CRYPT_OK; + #endif +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/omac/omac_done.c b/deps/libtomcrypt/src/mac/omac/omac_done.c new file mode 100644 index 0000000..c60067f --- /dev/null +++ b/deps/libtomcrypt/src/mac/omac/omac_done.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_done.c + OMAC1 support, terminate a stream, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + Terminate an OMAC stream + @param omac The OMAC state + @param out [out] Destination for the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int omac_done(omac_state *omac, unsigned char *out, unsigned long *outlen) +{ + int err, mode; + unsigned x; + + LTC_ARGCHK(omac != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || + (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { + return CRYPT_INVALID_ARG; + } + + /* figure out mode */ + if (omac->buflen != omac->blklen) { + /* add the 0x80 byte */ + omac->block[omac->buflen++] = 0x80; + + /* pad with 0x00 */ + while (omac->buflen < omac->blklen) { + omac->block[omac->buflen++] = 0x00; + } + mode = 1; + } else { + mode = 0; + } + + /* now xor prev + Lu[mode] */ + for (x = 0; x < (unsigned)omac->blklen; x++) { + omac->block[x] ^= omac->prev[x] ^ omac->Lu[mode][x]; + } + + /* encrypt it */ + if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->block, &omac->key)) != CRYPT_OK) { + return err; + } + cipher_descriptor[omac->cipher_idx].done(&omac->key); + + /* output it */ + for (x = 0; x < (unsigned)omac->blklen && x < *outlen; x++) { + out[x] = omac->block[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(omac, sizeof(*omac)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/omac/omac_file.c b/deps/libtomcrypt/src/mac/omac/omac_file.c new file mode 100644 index 0000000..012958a --- /dev/null +++ b/deps/libtomcrypt/src/mac/omac/omac_file.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_file.c + OMAC1 support, process a file, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + OMAC a file + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param filename The name of the file you wish to OMAC + @param out [out] Where the authentication tag is to be stored + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int omac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + omac_state omac; + FILE *in; + unsigned char *buf; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(filename, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = omac_process(&omac, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = omac_done(&omac, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&omac, sizeof(omac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/omac/omac_init.c b/deps/libtomcrypt/src/mac/omac/omac_init.c new file mode 100644 index 0000000..f527701 --- /dev/null +++ b/deps/libtomcrypt/src/mac/omac/omac_init.c @@ -0,0 +1,89 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_init.c + OMAC1 support, initialize state, by Tom St Denis +*/ + + +#ifdef LTC_OMAC + +/** + Initialize an OMAC state + @param omac The OMAC state to initialize + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen) +{ + int err, x, y, mask, msb, len; + + LTC_ARGCHK(omac != NULL); + LTC_ARGCHK(key != NULL); + + /* schedule the key */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* now setup the system */ + switch (cipher_descriptor[cipher].block_length) { + case 8: mask = 0x1B; + len = 8; + break; + case 16: mask = 0x87; + len = 16; + break; + default: return CRYPT_INVALID_ARG; + } + + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &omac->key)) != CRYPT_OK) { + return err; + } + + /* ok now we need Lu and Lu^2 [calc one from the other] */ + + /* first calc L which is Ek(0) */ + zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length); + if ((err = cipher_descriptor[cipher].ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key)) != CRYPT_OK) { + return err; + } + + /* now do the mults, whoopy! */ + for (x = 0; x < 2; x++) { + /* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */ + msb = omac->Lu[x][0] >> 7; + + /* shift left */ + for (y = 0; y < (len - 1); y++) { + omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255; + } + omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255; + + /* copy up as require */ + if (x == 0) { + XMEMCPY(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0])); + } + } + + /* setup state */ + omac->cipher_idx = cipher; + omac->buflen = 0; + omac->blklen = len; + zeromem(omac->prev, sizeof(omac->prev)); + zeromem(omac->block, sizeof(omac->block)); + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/omac/omac_memory.c b/deps/libtomcrypt/src/mac/omac/omac_memory.c new file mode 100644 index 0000000..56ac137 --- /dev/null +++ b/deps/libtomcrypt/src/mac/omac/omac_memory.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_memory.c + OMAC1 support, process a block of memory, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + OMAC a block of memory + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to send through OMAC + @param inlen The length of the data to send through OMAC (octets) + @param out [out] The destination of the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag (octets) + @return CRYPT_OK if successful +*/ +int omac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + int err; + omac_state *omac; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* Use accelerator if found */ + if (cipher_descriptor[cipher].omac_memory != NULL) { + return cipher_descriptor[cipher].omac_memory(key, keylen, in, inlen, out, outlen); + } + + /* allocate ram for omac state */ + omac = XMALLOC(sizeof(omac_state)); + if (omac == NULL) { + return CRYPT_MEM; + } + + /* omac process the message */ + if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = omac_process(omac, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(omac, sizeof(omac_state)); +#endif + + XFREE(omac); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/omac/omac_memory_multi.c b/deps/libtomcrypt/src/mac/omac/omac_memory_multi.c new file mode 100644 index 0000000..4f3b708 --- /dev/null +++ b/deps/libtomcrypt/src/mac/omac/omac_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file omac_memory_multi.c + OMAC1 support, process multiple blocks of memory, Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + OMAC multiple blocks of memory + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] The destination of the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag (octets) + @param in The data to send through OMAC + @param inlen The length of the data to send through OMAC (octets) + @param ... tuples of (data,len) pairs to OMAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int omac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + int err; + omac_state *omac; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for omac state */ + omac = XMALLOC(sizeof(omac_state)); + if (omac == NULL) { + return CRYPT_MEM; + } + + /* omac process the message */ + if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = omac_process(omac, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(omac, sizeof(omac_state)); +#endif + XFREE(omac); + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/omac/omac_process.c b/deps/libtomcrypt/src/mac/omac/omac_process.c new file mode 100644 index 0000000..b8e3160 --- /dev/null +++ b/deps/libtomcrypt/src/mac/omac/omac_process.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_process.c + OMAC1 support, process data, Tom St Denis +*/ + + +#ifdef LTC_OMAC + +/** + Process data through OMAC + @param omac The OMAC state + @param in The input data to send through OMAC + @param inlen The length of the input (octets) + @return CRYPT_OK if successful +*/ +int omac_process(omac_state *omac, const unsigned char *in, unsigned long inlen) +{ + unsigned long n, x; + int err; + + LTC_ARGCHK(omac != NULL); + LTC_ARGCHK(in != NULL); + if ((err = cipher_is_valid(omac->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((omac->buflen > (int)sizeof(omac->block)) || (omac->buflen < 0) || + (omac->blklen > (int)sizeof(omac->block)) || (omac->buflen > omac->blklen)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + { + unsigned long blklen = cipher_descriptor[omac->cipher_idx].block_length; + + if (omac->buflen == 0 && inlen > blklen) { + unsigned long y; + for (x = 0; x < (inlen - blklen); x += blklen) { + for (y = 0; y < blklen; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&omac->prev[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&in[y])); + } + in += blklen; + if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->prev, omac->prev, &omac->key)) != CRYPT_OK) { + return err; + } + } + inlen -= x; + } + } +#endif + + while (inlen != 0) { + /* ok if the block is full we xor in prev, encrypt and replace prev */ + if (omac->buflen == omac->blklen) { + for (x = 0; x < (unsigned long)omac->blklen; x++) { + omac->block[x] ^= omac->prev[x]; + } + if ((err = cipher_descriptor[omac->cipher_idx].ecb_encrypt(omac->block, omac->prev, &omac->key)) != CRYPT_OK) { + return err; + } + omac->buflen = 0; + } + + /* add bytes */ + n = MIN(inlen, (unsigned long)(omac->blklen - omac->buflen)); + XMEMCPY(omac->block + omac->buflen, in, n); + omac->buflen += n; + inlen -= n; + in += n; + } + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/omac/omac_test.c b/deps/libtomcrypt/src/mac/omac/omac_test.c new file mode 100644 index 0000000..bca6d9c --- /dev/null +++ b/deps/libtomcrypt/src/mac/omac/omac_test.c @@ -0,0 +1,93 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file omac_test.c + OMAC1 support, self-test, by Tom St Denis +*/ + +#ifdef LTC_OMAC + +/** + Test the OMAC setup + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled +*/ +int omac_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct { + int keylen, msglen; + unsigned char key[16], msg[64], tag[16]; + } tests[] = { + { 16, 0, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x00 }, + { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } + }, + { 16, 16, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a }, + { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } + }, + { 16, 40, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, + { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } + }, + { 16, 64, + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, + { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } + } + + }; + unsigned char out[16]; + int x, err, idx; + unsigned long len; + + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(out); + if ((err = omac_memory(idx, tests[x].key, tests[x].keylen, tests[x].msg, tests[x].msglen, out, &len)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(out, len, tests[x].tag, sizeof(tests[x].tag), "OMAC", x) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pelican/pelican.c b/deps/libtomcrypt/src/mac/pelican/pelican.c new file mode 100644 index 0000000..25592cc --- /dev/null +++ b/deps/libtomcrypt/src/mac/pelican/pelican.c @@ -0,0 +1,154 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pelican.c + Pelican MAC, initialize state, by Tom St Denis +*/ + +#ifdef LTC_PELICAN + +#define LTC_AES_TAB_C +#define ENCRYPT_ONLY +#define PELI_TAB +#include "../../ciphers/aes/aes_tab.c" + +/** + Initialize a Pelican state + @param pelmac The Pelican state to initialize + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int pelican_init(pelican_state *pelmac, const unsigned char *key, unsigned long keylen) +{ + int err; + + LTC_ARGCHK(pelmac != NULL); + LTC_ARGCHK(key != NULL); + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + if ((err = aes_setup(key, keylen, 0, &pelmac->K)) != CRYPT_OK) { + return err; + } + + zeromem(pelmac->state, 16); + aes_ecb_encrypt(pelmac->state, pelmac->state, &pelmac->K); + pelmac->buflen = 0; + + return CRYPT_OK; +} + +static void s_four_rounds(pelican_state *pelmac) +{ + ulong32 s0, s1, s2, s3, t0, t1, t2, t3; + int r; + + LOAD32H(s0, pelmac->state ); + LOAD32H(s1, pelmac->state + 4); + LOAD32H(s2, pelmac->state + 8); + LOAD32H(s3, pelmac->state + 12); + for (r = 0; r < 4; r++) { + t0 = + Te0(LTC_BYTE(s0, 3)) ^ + Te1(LTC_BYTE(s1, 2)) ^ + Te2(LTC_BYTE(s2, 1)) ^ + Te3(LTC_BYTE(s3, 0)); + t1 = + Te0(LTC_BYTE(s1, 3)) ^ + Te1(LTC_BYTE(s2, 2)) ^ + Te2(LTC_BYTE(s3, 1)) ^ + Te3(LTC_BYTE(s0, 0)); + t2 = + Te0(LTC_BYTE(s2, 3)) ^ + Te1(LTC_BYTE(s3, 2)) ^ + Te2(LTC_BYTE(s0, 1)) ^ + Te3(LTC_BYTE(s1, 0)); + t3 = + Te0(LTC_BYTE(s3, 3)) ^ + Te1(LTC_BYTE(s0, 2)) ^ + Te2(LTC_BYTE(s1, 1)) ^ + Te3(LTC_BYTE(s2, 0)); + s0 = t0; s1 = t1; s2 = t2; s3 = t3; + } + STORE32H(s0, pelmac->state ); + STORE32H(s1, pelmac->state + 4); + STORE32H(s2, pelmac->state + 8); + STORE32H(s3, pelmac->state + 12); +} + +/** + Process a block of text through Pelican + @param pelmac The Pelican MAC state + @param in The input + @param inlen The length input (octets) + @return CRYPT_OK on success + */ +int pelican_process(pelican_state *pelmac, const unsigned char *in, unsigned long inlen) +{ + + LTC_ARGCHK(pelmac != NULL); + LTC_ARGCHK(in != NULL); + + /* check range */ + if (pelmac->buflen < 0 || pelmac->buflen > 15) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (pelmac->buflen == 0) { + while (inlen & ~15) { + int x; + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pelmac->state + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)in + x)); + } + s_four_rounds(pelmac); + in += 16; + inlen -= 16; + } + } +#endif + + while (inlen--) { + pelmac->state[pelmac->buflen++] ^= *in++; + if (pelmac->buflen == 16) { + s_four_rounds(pelmac); + pelmac->buflen = 0; + } + } + return CRYPT_OK; +} + +/** + Terminate Pelican MAC + @param pelmac The Pelican MAC state + @param out [out] The TAG + @return CRYPT_OK on sucess +*/ +int pelican_done(pelican_state *pelmac, unsigned char *out) +{ + LTC_ARGCHK(pelmac != NULL); + LTC_ARGCHK(out != NULL); + + /* check range */ + if (pelmac->buflen < 0 || pelmac->buflen > 16) { + return CRYPT_INVALID_ARG; + } + + if (pelmac->buflen == 16) { + s_four_rounds(pelmac); + pelmac->buflen = 0; + } + pelmac->state[pelmac->buflen++] ^= 0x80; + aes_ecb_encrypt(pelmac->state, out, &pelmac->K); + aes_done(&pelmac->K); + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pelican/pelican_memory.c b/deps/libtomcrypt/src/mac/pelican/pelican_memory.c new file mode 100644 index 0000000..f67eaee --- /dev/null +++ b/deps/libtomcrypt/src/mac/pelican/pelican_memory.c @@ -0,0 +1,47 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pelican_memory.c + Pelican MAC, MAC a block of memory, by Tom St Denis +*/ + +#ifdef LTC_PELICAN + +/** + Pelican block of memory + @param key The key for the MAC + @param keylen The length of the key (octets) + @param in The input to MAC + @param inlen The length of the input (octets) + @param out [out] The output TAG + @return CRYPT_OK on success +*/ +int pelican_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out) +{ + pelican_state *pel; + int err; + + pel = XMALLOC(sizeof(*pel)); + if (pel == NULL) { + return CRYPT_MEM; + } + + if ((err = pelican_init(pel, key, keylen)) != CRYPT_OK) { + XFREE(pel); + return err; + } + if ((err = pelican_process(pel, in ,inlen)) != CRYPT_OK) { + XFREE(pel); + return err; + } + err = pelican_done(pel, out); + XFREE(pel); + return err; +} + + +#endif diff --git a/deps/libtomcrypt/src/mac/pelican/pelican_test.c b/deps/libtomcrypt/src/mac/pelican/pelican_test.c new file mode 100644 index 0000000..2ec696a --- /dev/null +++ b/deps/libtomcrypt/src/mac/pelican/pelican_test.c @@ -0,0 +1,103 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pelican_test.c + Pelican MAC, test, by Tom St Denis +*/ + +#ifdef LTC_PELICAN + +int pelican_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char K[32], MSG[64], T[16]; + int keylen, ptlen; + } tests[] = { +/* K=16, M=0 */ +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0 }, + { 0xeb, 0x58, 0x37, 0x15, 0xf8, 0x34, 0xde, 0xe5, + 0xa4, 0xd1, 0x6e, 0xe4, 0xb9, 0xd7, 0x76, 0x0e, }, + 16, 0 +}, + +/* K=16, M=3 */ +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x00, 0x01, 0x02 }, + { 0x1c, 0x97, 0x40, 0x60, 0x6c, 0x58, 0x17, 0x2d, + 0x03, 0x94, 0x19, 0x70, 0x81, 0xc4, 0x38, 0x54, }, + 16, 3 +}, + +/* K=16, M=16 */ +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x03, 0xcc, 0x46, 0xb8, 0xac, 0xa7, 0x9c, 0x36, + 0x1e, 0x8c, 0x6e, 0xa6, 0x7b, 0x89, 0x32, 0x49, }, + 16, 16 +}, + +/* K=16, M=32 */ +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + { 0x89, 0xcc, 0x36, 0x58, 0x1b, 0xdd, 0x4d, 0xb5, + 0x78, 0xbb, 0xac, 0xf0, 0xff, 0x8b, 0x08, 0x15, }, + 16, 32 +}, + +/* K=16, M=35 */ +{ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x23 }, + { 0x4a, 0x7d, 0x45, 0x4d, 0xcd, 0xb5, 0xda, 0x8d, + 0x48, 0x78, 0x16, 0x48, 0x5d, 0x45, 0x95, 0x99, }, + 16, 35 +}, +}; + int x, err; + unsigned char out[16]; + pelican_state pel; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = pelican_init(&pel, tests[x].K, tests[x].keylen)) != CRYPT_OK) { + return err; + } + if ((err = pelican_process(&pel, tests[x].MSG, tests[x].ptlen)) != CRYPT_OK) { + return err; + } + if ((err = pelican_done(&pel, out)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(out, 16, tests[x].T, 16, "PELICAN", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_done.c b/deps/libtomcrypt/src/mac/pmac/pmac_done.c new file mode 100644 index 0000000..222790d --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_done.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_done.c + PMAC implementation, terminate a session, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +int pmac_done(pmac_state *pmac, unsigned char *out, unsigned long *outlen) +{ + int err, x; + + LTC_ARGCHK(pmac != NULL); + LTC_ARGCHK(out != NULL); + if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) || + (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) { + return CRYPT_INVALID_ARG; + } + + + /* handle padding. If multiple xor in L/x */ + + if (pmac->buflen == pmac->block_len) { + /* xor Lr against the checksum */ + for (x = 0; x < pmac->block_len; x++) { + pmac->checksum[x] ^= pmac->block[x] ^ pmac->Lr[x]; + } + } else { + /* otherwise xor message bytes then the 0x80 byte */ + for (x = 0; x < pmac->buflen; x++) { + pmac->checksum[x] ^= pmac->block[x]; + } + pmac->checksum[x] ^= 0x80; + } + + /* encrypt it */ + if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(pmac->checksum, pmac->checksum, &pmac->key)) != CRYPT_OK) { + return err; + } + cipher_descriptor[pmac->cipher_idx].done(&pmac->key); + + /* store it */ + for (x = 0; x < pmac->block_len && x < (int)*outlen; x++) { + out[x] = pmac->checksum[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(pmac, sizeof(*pmac)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_file.c b/deps/libtomcrypt/src/mac/pmac/pmac_file.c new file mode 100644 index 0000000..fca9b00 --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_file.c @@ -0,0 +1,88 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_file.c + PMAC implementation, process a file, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + PMAC a file + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param filename The name of the file to send through PMAC + @param out [out] Destination for the authentication tag + @param outlen [in/out] Max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int pmac_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + pmac_state pmac; + FILE *in; + unsigned char *buf; + + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = pmac_init(&pmac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(filename, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = pmac_process(&pmac, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = pmac_done(&pmac, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&pmac, sizeof(pmac_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_init.c b/deps/libtomcrypt/src/mac/pmac/pmac_init.c new file mode 100644 index 0000000..1af9c29 --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_init.c @@ -0,0 +1,138 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_init.c + PMAC implementation, initialize state, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +static const struct { + int len; + unsigned char poly_div[MAXBLOCKSIZE], + poly_mul[MAXBLOCKSIZE]; +} polys[] = { +{ + 8, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B } +}, { + 16, + { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 } +} +}; + +/** + Initialize a PMAC state + @param pmac The PMAC state to initialize + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int pmac_init(pmac_state *pmac, int cipher, const unsigned char *key, unsigned long keylen) +{ + int poly, x, y, m, err; + unsigned char *L; + + LTC_ARGCHK(pmac != NULL); + LTC_ARGCHK(key != NULL); + + /* valid cipher? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* determine which polys to use */ + pmac->block_len = cipher_descriptor[cipher].block_length; + for (poly = 0; poly < (int)(sizeof(polys)/sizeof(polys[0])); poly++) { + if (polys[poly].len == pmac->block_len) { + break; + } + } + if (poly >= (int)(sizeof(polys)/sizeof(polys[0]))) { + return CRYPT_INVALID_ARG; + } + if (polys[poly].len != pmac->block_len) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (pmac->block_len % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + + /* schedule the key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &pmac->key)) != CRYPT_OK) { + return err; + } + + /* allocate L */ + L = XMALLOC(pmac->block_len); + if (L == NULL) { + return CRYPT_MEM; + } + + /* find L = E[0] */ + zeromem(L, pmac->block_len); + if ((err = cipher_descriptor[cipher].ecb_encrypt(L, L, &pmac->key)) != CRYPT_OK) { + goto error; + } + + /* find Ls[i] = L << i for i == 0..31 */ + XMEMCPY(pmac->Ls[0], L, pmac->block_len); + for (x = 1; x < 32; x++) { + m = pmac->Ls[x-1][0] >> 7; + for (y = 0; y < pmac->block_len-1; y++) { + pmac->Ls[x][y] = ((pmac->Ls[x-1][y] << 1) | (pmac->Ls[x-1][y+1] >> 7)) & 255; + } + pmac->Ls[x][pmac->block_len-1] = (pmac->Ls[x-1][pmac->block_len-1] << 1) & 255; + + if (m == 1) { + for (y = 0; y < pmac->block_len; y++) { + pmac->Ls[x][y] ^= polys[poly].poly_mul[y]; + } + } + } + + /* find Lr = L / x */ + m = L[pmac->block_len-1] & 1; + + /* shift right */ + for (x = pmac->block_len - 1; x > 0; x--) { + pmac->Lr[x] = ((L[x] >> 1) | (L[x-1] << 7)) & 255; + } + pmac->Lr[0] = L[0] >> 1; + + if (m == 1) { + for (x = 0; x < pmac->block_len; x++) { + pmac->Lr[x] ^= polys[poly].poly_div[x]; + } + } + + /* zero buffer, counters, etc... */ + pmac->block_index = 1; + pmac->cipher_idx = cipher; + pmac->buflen = 0; + zeromem(pmac->block, sizeof(pmac->block)); + zeromem(pmac->Li, sizeof(pmac->Li)); + zeromem(pmac->checksum, sizeof(pmac->checksum)); + err = CRYPT_OK; +error: +#ifdef LTC_CLEAN_STACK + zeromem(L, pmac->block_len); +#endif + + XFREE(L); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_memory.c b/deps/libtomcrypt/src/mac/pmac/pmac_memory.c new file mode 100644 index 0000000..4671547 --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_memory.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_memory.c + PMAC implementation, process a block of memory, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + PMAC a block of memory + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data you wish to send through PMAC + @param inlen The length of data you wish to send through PMAC (octets) + @param out [out] Destination for the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful +*/ +int pmac_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + int err; + pmac_state *pmac; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for pmac state */ + pmac = XMALLOC(sizeof(pmac_state)); + if (pmac == NULL) { + return CRYPT_MEM; + } + + if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = pmac_process(pmac, in, inlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(pmac, sizeof(pmac_state)); +#endif + + XFREE(pmac); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_memory_multi.c b/deps/libtomcrypt/src/mac/pmac/pmac_memory_multi.c new file mode 100644 index 0000000..94d450c --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_memory_multi.c @@ -0,0 +1,77 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file pmac_memory_multi.c + PMAC implementation, process multiple blocks of memory, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + PMAC multiple blocks of memory + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] Destination for the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag + @param in The data you wish to send through PMAC + @param inlen The length of data you wish to send through PMAC (octets) + @param ... tuples of (data,len) pairs to PMAC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int pmac_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + int err; + pmac_state *pmac; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for pmac state */ + pmac = XMALLOC(sizeof(pmac_state)); + if (pmac == NULL) { + return CRYPT_MEM; + } + + if ((err = pmac_init(pmac, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = pmac_process(pmac, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = pmac_done(pmac, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(pmac, sizeof(pmac_state)); +#endif + XFREE(pmac); + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_ntz.c b/deps/libtomcrypt/src/mac/pmac/pmac_ntz.c new file mode 100644 index 0000000..ed71f33 --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_ntz.c @@ -0,0 +1,27 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_ntz.c + PMAC implementation, internal function, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + Internal PMAC function +*/ +int pmac_ntz(unsigned long x) +{ + int c; + x &= 0xFFFFFFFFUL; + c = 0; + while ((x & 1) == 0) { + ++c; + x >>= 1; + } + return c; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_process.c b/deps/libtomcrypt/src/mac/pmac/pmac_process.c new file mode 100644 index 0000000..3f38e8a --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_process.c @@ -0,0 +1,88 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_process.c + PMAC implementation, process data, by Tom St Denis +*/ + + +#ifdef LTC_PMAC + +/** + Process data in a PMAC stream + @param pmac The PMAC state + @param in The data to send through PMAC + @param inlen The length of the data to send through PMAC + @return CRYPT_OK if successful +*/ +int pmac_process(pmac_state *pmac, const unsigned char *in, unsigned long inlen) +{ + int err, n; + unsigned long x; + unsigned char Z[MAXBLOCKSIZE]; + + LTC_ARGCHK(pmac != NULL); + LTC_ARGCHK(in != NULL); + if ((err = cipher_is_valid(pmac->cipher_idx)) != CRYPT_OK) { + return err; + } + + if ((pmac->buflen > (int)sizeof(pmac->block)) || (pmac->buflen < 0) || + (pmac->block_len > (int)sizeof(pmac->block)) || (pmac->buflen > pmac->block_len)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (pmac->buflen == 0 && inlen > 16) { + unsigned long y; + for (x = 0; x < (inlen - 16); x += 16) { + pmac_shift_xor(pmac); + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&Z[y])) = *(LTC_FAST_TYPE_PTR_CAST(&in[y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&pmac->Li[y])); + } + if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) { + return err; + } + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&pmac->checksum[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&Z[y])); + } + in += 16; + } + inlen -= x; + } +#endif + + while (inlen != 0) { + /* ok if the block is full we xor in prev, encrypt and replace prev */ + if (pmac->buflen == pmac->block_len) { + pmac_shift_xor(pmac); + for (x = 0; x < (unsigned long)pmac->block_len; x++) { + Z[x] = pmac->Li[x] ^ pmac->block[x]; + } + if ((err = cipher_descriptor[pmac->cipher_idx].ecb_encrypt(Z, Z, &pmac->key)) != CRYPT_OK) { + return err; + } + for (x = 0; x < (unsigned long)pmac->block_len; x++) { + pmac->checksum[x] ^= Z[x]; + } + pmac->buflen = 0; + } + + /* add bytes */ + n = MIN(inlen, (unsigned long)(pmac->block_len - pmac->buflen)); + XMEMCPY(pmac->block + pmac->buflen, in, n); + pmac->buflen += n; + inlen -= n; + in += n; + } + +#ifdef LTC_CLEAN_STACK + zeromem(Z, sizeof(Z)); +#endif + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_shift_xor.c b/deps/libtomcrypt/src/mac/pmac/pmac_shift_xor.c new file mode 100644 index 0000000..ad97fa8 --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_shift_xor.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_shift_xor.c + PMAC implementation, internal function, by Tom St Denis +*/ + +#ifdef LTC_PMAC + +/** + Internal function. Performs the state update (adding correct multiple) + @param pmac The PMAC state. +*/ +void pmac_shift_xor(pmac_state *pmac) +{ + int x, y; + y = pmac_ntz(pmac->block_index++); +#ifdef LTC_FAST + for (x = 0; x < pmac->block_len; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Li + x)) ^= + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pmac->Ls[y] + x)); + } +#else + for (x = 0; x < pmac->block_len; x++) { + pmac->Li[x] ^= pmac->Ls[y][x]; + } +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/pmac/pmac_test.c b/deps/libtomcrypt/src/mac/pmac/pmac_test.c new file mode 100644 index 0000000..3ccf06e --- /dev/null +++ b/deps/libtomcrypt/src/mac/pmac/pmac_test.c @@ -0,0 +1,144 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pmac_test.c + PMAC implementation, self-test, by Tom St Denis +*/ + + +#ifdef LTC_PMAC + +/** + Test the LTC_OMAC implementation + @return CRYPT_OK if successful, CRYPT_NOP if testing has been disabled +*/ +int pmac_test(void) +{ +#if !defined(LTC_TEST) + return CRYPT_NOP; +#else + static const struct { + int msglen; + unsigned char key[16], msg[34], tag[16]; + } tests[] = { + + /* PMAC-AES-128-0B */ +{ + 0, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00 }, + /* tag */ + { 0x43, 0x99, 0x57, 0x2c, 0xd6, 0xea, 0x53, 0x41, + 0xb8, 0xd3, 0x58, 0x76, 0xa7, 0x09, 0x8a, 0xf7 } +}, + + /* PMAC-AES-128-3B */ +{ + 3, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02 }, + /* tag */ + { 0x25, 0x6b, 0xa5, 0x19, 0x3c, 0x1b, 0x99, 0x1b, + 0x4d, 0xf0, 0xc5, 0x1f, 0x38, 0x8a, 0x9e, 0x27 } +}, + + /* PMAC-AES-128-16B */ +{ + 16, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* tag */ + { 0xeb, 0xbd, 0x82, 0x2f, 0xa4, 0x58, 0xda, 0xf6, + 0xdf, 0xda, 0xd7, 0xc2, 0x7d, 0xa7, 0x63, 0x38 } +}, + + /* PMAC-AES-128-20B */ +{ + 20, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 }, + /* tag */ + { 0x04, 0x12, 0xca, 0x15, 0x0b, 0xbf, 0x79, 0x05, + 0x8d, 0x8c, 0x75, 0xa5, 0x8c, 0x99, 0x3f, 0x55 } +}, + + /* PMAC-AES-128-32B */ +{ + 32, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + /* tag */ + { 0xe9, 0x7a, 0xc0, 0x4e, 0x9e, 0x5e, 0x33, 0x99, + 0xce, 0x53, 0x55, 0xcd, 0x74, 0x07, 0xbc, 0x75 } +}, + + /* PMAC-AES-128-34B */ +{ + 34, + /* key */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + /* msg */ + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + /* tag */ + { 0x5c, 0xba, 0x7d, 0x5e, 0xb2, 0x4f, 0x7c, 0x86, + 0xcc, 0xc5, 0x46, 0x04, 0xe5, 0x3d, 0x55, 0x12 } +} + +}; + int err, x, idx; + unsigned long len; + unsigned char outtag[MAXBLOCKSIZE]; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + len = sizeof(outtag); + if ((err = pmac_memory(idx, tests[x].key, 16, tests[x].msg, tests[x].msglen, outtag, &len)) != CRYPT_OK) { + return err; + } + + if (compare_testvector(outtag, len, tests[x].tag, sizeof(tests[x].tag), "PMAC", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif /* LTC_TEST */ +} + +#endif /* PMAC_MODE */ + + + diff --git a/deps/libtomcrypt/src/mac/poly1305/poly1305.c b/deps/libtomcrypt/src/mac/poly1305/poly1305.c new file mode 100644 index 0000000..32cdb55 --- /dev/null +++ b/deps/libtomcrypt/src/mac/poly1305/poly1305.c @@ -0,0 +1,258 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +/* internal only */ +static void s_poly1305_block(poly1305_state *st, const unsigned char *in, unsigned long inlen) +{ + const unsigned long hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */ + ulong32 r0,r1,r2,r3,r4; + ulong32 s1,s2,s3,s4; + ulong32 h0,h1,h2,h3,h4; + ulong32 tmp; + ulong64 d0,d1,d2,d3,d4; + ulong32 c; + + r0 = st->r[0]; + r1 = st->r[1]; + r2 = st->r[2]; + r3 = st->r[3]; + r4 = st->r[4]; + + s1 = r1 * 5; + s2 = r2 * 5; + s3 = r3 * 5; + s4 = r4 * 5; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + while (inlen >= 16) { + /* h += in[i] */ + LOAD32L(tmp, in+ 0); h0 += (tmp ) & 0x3ffffff; + LOAD32L(tmp, in+ 3); h1 += (tmp >> 2) & 0x3ffffff; + LOAD32L(tmp, in+ 6); h2 += (tmp >> 4) & 0x3ffffff; + LOAD32L(tmp, in+ 9); h3 += (tmp >> 6) & 0x3ffffff; + LOAD32L(tmp, in+12); h4 += (tmp >> 8) | hibit; + + /* h *= r */ + d0 = ((ulong64)h0 * r0) + ((ulong64)h1 * s4) + ((ulong64)h2 * s3) + ((ulong64)h3 * s2) + ((ulong64)h4 * s1); + d1 = ((ulong64)h0 * r1) + ((ulong64)h1 * r0) + ((ulong64)h2 * s4) + ((ulong64)h3 * s3) + ((ulong64)h4 * s2); + d2 = ((ulong64)h0 * r2) + ((ulong64)h1 * r1) + ((ulong64)h2 * r0) + ((ulong64)h3 * s4) + ((ulong64)h4 * s3); + d3 = ((ulong64)h0 * r3) + ((ulong64)h1 * r2) + ((ulong64)h2 * r1) + ((ulong64)h3 * r0) + ((ulong64)h4 * s4); + d4 = ((ulong64)h0 * r4) + ((ulong64)h1 * r3) + ((ulong64)h2 * r2) + ((ulong64)h3 * r1) + ((ulong64)h4 * r0); + + /* (partial) h %= p */ + c = (ulong32)(d0 >> 26); h0 = (ulong32)d0 & 0x3ffffff; + d1 += c; c = (ulong32)(d1 >> 26); h1 = (ulong32)d1 & 0x3ffffff; + d2 += c; c = (ulong32)(d2 >> 26); h2 = (ulong32)d2 & 0x3ffffff; + d3 += c; c = (ulong32)(d3 >> 26); h3 = (ulong32)d3 & 0x3ffffff; + d4 += c; c = (ulong32)(d4 >> 26); h4 = (ulong32)d4 & 0x3ffffff; + h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; + h1 += c; + + in += 16; + inlen -= 16; + } + + st->h[0] = h0; + st->h[1] = h1; + st->h[2] = h2; + st->h[3] = h3; + st->h[4] = h4; +} + +/** + Initialize an POLY1305 context. + @param st The POLY1305 state + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long keylen) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32); + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + LOAD32L(st->r[0], key + 0); st->r[0] = (st->r[0] ) & 0x3ffffff; + LOAD32L(st->r[1], key + 3); st->r[1] = (st->r[1] >> 2) & 0x3ffff03; + LOAD32L(st->r[2], key + 6); st->r[2] = (st->r[2] >> 4) & 0x3ffc0ff; + LOAD32L(st->r[3], key + 9); st->r[3] = (st->r[3] >> 6) & 0x3f03fff; + LOAD32L(st->r[4], key + 12); st->r[4] = (st->r[4] >> 8) & 0x00fffff; + + /* h = 0 */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + st->h[3] = 0; + st->h[4] = 0; + + /* save pad for later */ + LOAD32L(st->pad[0], key + 16); + LOAD32L(st->pad[1], key + 20); + LOAD32L(st->pad[2], key + 24); + LOAD32L(st->pad[3], key + 28); + + st->leftover = 0; + st->final = 0; + return CRYPT_OK; +} + +/** + Process data through POLY1305 + @param st The POLY1305 state + @param in The data to send through HMAC + @param inlen The length of the data to HMAC (octets) + @return CRYPT_OK if successful +*/ +int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen) +{ + unsigned long i; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + + /* handle leftover */ + if (st->leftover) { + unsigned long want = (16 - st->leftover); + if (want > inlen) want = inlen; + for (i = 0; i < want; i++) st->buffer[st->leftover + i] = in[i]; + inlen -= want; + in += want; + st->leftover += want; + if (st->leftover < 16) return CRYPT_OK; + s_poly1305_block(st, st->buffer, 16); + st->leftover = 0; + } + + /* process full blocks */ + if (inlen >= 16) { + unsigned long want = (inlen & ~(16 - 1)); + s_poly1305_block(st, in, want); + in += want; + inlen -= want; + } + + /* store leftover */ + if (inlen) { + for (i = 0; i < inlen; i++) st->buffer[st->leftover + i] = in[i]; + st->leftover += inlen; + } + return CRYPT_OK; +} + +/** + Terminate a POLY1305 session + @param st The POLY1305 state + @param mac [out] The destination of the POLY1305 authentication tag + @param maclen [in/out] The max size and resulting size of the POLY1305 authentication tag + @return CRYPT_OK if successful +*/ +int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen) +{ + ulong32 h0,h1,h2,h3,h4,c; + ulong32 g0,g1,g2,g3,g4; + ulong64 f; + ulong32 mask; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + LTC_ARGCHK(*maclen >= 16); + + /* process the remaining block */ + if (st->leftover) { + unsigned long i = st->leftover; + st->buffer[i++] = 1; + for (; i < 16; i++) st->buffer[i] = 0; + st->final = 1; + s_poly1305_block(st, st->buffer, 16); + } + + /* fully carry h */ + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + c = h1 >> 26; h1 = h1 & 0x3ffffff; + h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; + h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; + h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; + h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; + h1 += c; + + /* compute h + -p */ + g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; + g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; + g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; + g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; + g4 = h4 + c - (1UL << 26); + + /* select h if h < p, or h + -p if h >= p */ + mask = (g4 >> 31) - 1; + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + g4 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + h4 = (h4 & mask) | g4; + + /* h = h % (2^128) */ + h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; + h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; + h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; + h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; + + /* mac = (h + pad) % (2^128) */ + f = (ulong64)h0 + st->pad[0] ; h0 = (ulong32)f; + f = (ulong64)h1 + st->pad[1] + (f >> 32); h1 = (ulong32)f; + f = (ulong64)h2 + st->pad[2] + (f >> 32); h2 = (ulong32)f; + f = (ulong64)h3 + st->pad[3] + (f >> 32); h3 = (ulong32)f; + + STORE32L(h0, mac + 0); + STORE32L(h1, mac + 4); + STORE32L(h2, mac + 8); + STORE32L(h3, mac + 12); + + /* zero out the state */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + st->h[3] = 0; + st->h[4] = 0; + st->r[0] = 0; + st->r[1] = 0; + st->r[2] = 0; + st->r[3] = 0; + st->r[4] = 0; + st->pad[0] = 0; + st->pad[1] = 0; + st->pad[2] = 0; + st->pad[3] = 0; + + *maclen = 16; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/poly1305/poly1305_file.c b/deps/libtomcrypt/src/mac/poly1305/poly1305_file.c new file mode 100644 index 0000000..e09c994 --- /dev/null +++ b/deps/libtomcrypt/src/mac/poly1305/poly1305_file.c @@ -0,0 +1,83 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +/** + POLY1305 a file + @param fname The name of the file you wish to POLY1305 + @param key The secret key + @param keylen The length of the secret key + @param mac [out] The POLY1305 authentication tag + @param maclen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(fname); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(mac); + LTC_UNUSED_PARAM(maclen); + return CRYPT_NOP; +#else + poly1305_state st; + FILE *in; + unsigned char *buf; + size_t x; + int err; + + LTC_ARGCHK(fname != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(fname, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = poly1305_process(&st, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = poly1305_done(&st, mac, maclen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(poly1305_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/poly1305/poly1305_memory.c b/deps/libtomcrypt/src/mac/poly1305/poly1305_memory.c new file mode 100644 index 0000000..8a9fea6 --- /dev/null +++ b/deps/libtomcrypt/src/mac/poly1305/poly1305_memory.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +/** + POLY1305 a block of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param in The data to POLY1305 + @param inlen The length of the data to POLY1305 (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @return CRYPT_OK if successful +*/ +int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen) +{ + poly1305_state st; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = poly1305_process(&st, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + err = poly1305_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(poly1305_state)); +#endif + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c b/deps/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c new file mode 100644 index 0000000..6bd61df --- /dev/null +++ b/deps/libtomcrypt/src/mac/poly1305/poly1305_memory_multi.c @@ -0,0 +1,57 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" +#include + +#ifdef LTC_POLY1305 + +/** + POLY1305 multiple blocks of memory to produce the authentication tag + @param key The secret key + @param keylen The length of the secret key (octets) + @param mac [out] Destination of the authentication tag + @param maclen [in/out] Max size and resulting size of authentication tag + @param in The data to POLY1305 + @param inlen The length of the data to POLY1305 (octets) + @param ... tuples of (data,len) pairs to POLY1305, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...) +{ + poly1305_state st; + int err; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(mac != NULL); + LTC_ARGCHK(maclen != NULL); + + va_start(args, inlen); + curptr = in; + curlen = inlen; + if ((err = poly1305_init(&st, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } + for (;;) { + if ((err = poly1305_process(&st, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) break; + curlen = va_arg(args, unsigned long); + } + err = poly1305_done(&st, mac, maclen); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&st, sizeof(poly1305_state)); +#endif + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/poly1305/poly1305_test.c b/deps/libtomcrypt/src/mac/poly1305/poly1305_test.c new file mode 100644 index 0000000..f9b3f75 --- /dev/null +++ b/deps/libtomcrypt/src/mac/poly1305/poly1305_test.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * Public Domain poly1305 from Andrew Moon + * https://github.com/floodyberry/poly1305-donna + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_POLY1305 + +int poly1305_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + /* https://tools.ietf.org/html/rfc7539#section-2.5.2 */ + unsigned char k[] = { 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b }; + unsigned char tag[] = { 0xA8, 0x06, 0x1D, 0xC1, 0x30, 0x51, 0x36, 0xC6, 0xC2, 0x2B, 0x8B, 0xAF, 0x0C, 0x01, 0x27, 0xA9 }; + char m[] = "Cryptographic Forum Research Group"; + unsigned long len = 16, mlen = XSTRLEN(m); + unsigned char out[1000]; + poly1305_state st; + int err; + + /* process piece by piece */ + if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m, 5)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 5, 4)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 9, 3)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 12, 2)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 14, 1)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m + 15, mlen - 15)) != CRYPT_OK) return err; + if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; + if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV1", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + /* process in one go */ + if ((err = poly1305_init(&st, k, 32)) != CRYPT_OK) return err; + if ((err = poly1305_process(&st, (unsigned char*)m, mlen)) != CRYPT_OK) return err; + if ((err = poly1305_done(&st, out, &len)) != CRYPT_OK) return err; + if (compare_testvector(out, len, tag, sizeof(tag), "POLY1305-TV2", 1) != 0) return CRYPT_FAIL_TESTVECTOR; + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/xcbc/xcbc_done.c b/deps/libtomcrypt/src/mac/xcbc/xcbc_done.c new file mode 100644 index 0000000..7da72f3 --- /dev/null +++ b/deps/libtomcrypt/src/mac/xcbc/xcbc_done.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file xcbc_done.c + XCBC Support, terminate the state +*/ + +#ifdef LTC_XCBC + +/** Terminate the XCBC-MAC state + @param xcbc XCBC state to terminate + @param out [out] Destination for the MAC tag + @param outlen [in/out] Destination size and final tag size + Return CRYPT_OK on success +*/ +int xcbc_done(xcbc_state *xcbc, unsigned char *out, unsigned long *outlen) +{ + int err, x; + LTC_ARGCHK(xcbc != NULL); + LTC_ARGCHK(out != NULL); + + /* check structure */ + if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) { + return err; + } + + if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) || + (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + + /* which key do we use? */ + if (xcbc->buflen == xcbc->blocksize) { + /* k2 */ + for (x = 0; x < xcbc->blocksize; x++) { + xcbc->IV[x] ^= xcbc->K[1][x]; + } + } else { + xcbc->IV[xcbc->buflen] ^= 0x80; + /* k3 */ + for (x = 0; x < xcbc->blocksize; x++) { + xcbc->IV[x] ^= xcbc->K[2][x]; + } + } + + /* encrypt */ + cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); + cipher_descriptor[xcbc->cipher].done(&xcbc->key); + + /* extract tag */ + for (x = 0; x < xcbc->blocksize && (unsigned long)x < *outlen; x++) { + out[x] = xcbc->IV[x]; + } + *outlen = x; + +#ifdef LTC_CLEAN_STACK + zeromem(xcbc, sizeof(*xcbc)); +#endif + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/xcbc/xcbc_file.c b/deps/libtomcrypt/src/mac/xcbc/xcbc_file.c new file mode 100644 index 0000000..d8612df --- /dev/null +++ b/deps/libtomcrypt/src/mac/xcbc/xcbc_file.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file xcbc_file.c + XCBC support, process a file, Tom St Denis +*/ + +#ifdef LTC_XCBC + +/** + XCBC a file + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param filename The name of the file you wish to XCBC + @param out [out] Where the authentication tag is to be stored + @param outlen [in/out] The max size and resulting size of the authentication tag + @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled +*/ +int xcbc_file(int cipher, + const unsigned char *key, unsigned long keylen, + const char *filename, + unsigned char *out, unsigned long *outlen) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(cipher); + LTC_UNUSED_PARAM(key); + LTC_UNUSED_PARAM(keylen); + LTC_UNUSED_PARAM(filename); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + return CRYPT_NOP; +#else + size_t x; + int err; + xcbc_state xcbc; + FILE *in; + unsigned char *buf; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(filename != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((buf = XMALLOC(LTC_FILE_READ_BUFSIZE)) == NULL) { + return CRYPT_MEM; + } + + if ((err = xcbc_init(&xcbc, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + + in = fopen(filename, "rb"); + if (in == NULL) { + err = CRYPT_FILE_NOTFOUND; + goto LBL_ERR; + } + + do { + x = fread(buf, 1, LTC_FILE_READ_BUFSIZE, in); + if ((err = xcbc_process(&xcbc, buf, (unsigned long)x)) != CRYPT_OK) { + fclose(in); + goto LBL_CLEANBUF; + } + } while (x == LTC_FILE_READ_BUFSIZE); + + if (fclose(in) != 0) { + err = CRYPT_ERROR; + goto LBL_CLEANBUF; + } + + err = xcbc_done(&xcbc, out, outlen); + +LBL_CLEANBUF: + zeromem(buf, LTC_FILE_READ_BUFSIZE); +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(&xcbc, sizeof(xcbc_state)); +#endif + XFREE(buf); + return err; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/mac/xcbc/xcbc_init.c b/deps/libtomcrypt/src/mac/xcbc/xcbc_init.c new file mode 100644 index 0000000..3e4044a --- /dev/null +++ b/deps/libtomcrypt/src/mac/xcbc/xcbc_init.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file xcbc_init.c + XCBC Support, start an XCBC state +*/ + +#ifdef LTC_XCBC + +/** Initialize XCBC-MAC state + @param xcbc [out] XCBC state to initialize + @param cipher Index of cipher to use + @param key [in] Secret key + @param keylen Length of secret key in octets + Return CRYPT_OK on success +*/ +int xcbc_init(xcbc_state *xcbc, int cipher, const unsigned char *key, unsigned long keylen) +{ + int x, y, err; + symmetric_key *skey; + unsigned long k1; + + LTC_ARGCHK(xcbc != NULL); + LTC_ARGCHK(key != NULL); + + /* schedule the key */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + skey = NULL; + + /* are we in pure XCBC mode with three keys? */ + if (keylen & LTC_XCBC_PURE) { + keylen &= ~LTC_XCBC_PURE; + + if (keylen < 2UL*cipher_descriptor[cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + k1 = keylen - 2*cipher_descriptor[cipher].block_length; + XMEMCPY(xcbc->K[0], key, k1); + XMEMCPY(xcbc->K[1], key+k1, cipher_descriptor[cipher].block_length); + XMEMCPY(xcbc->K[2], key+k1 + cipher_descriptor[cipher].block_length, cipher_descriptor[cipher].block_length); + } else { + /* use the key expansion */ + k1 = cipher_descriptor[cipher].block_length; + + /* schedule the user key */ + skey = XCALLOC(1, sizeof(*skey)); + if (skey == NULL) { + return CRYPT_MEM; + } + + if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) { + goto done; + } + + /* make the three keys */ + for (y = 0; y < 3; y++) { + for (x = 0; x < cipher_descriptor[cipher].block_length; x++) { + xcbc->K[y][x] = y + 1; + } + cipher_descriptor[cipher].ecb_encrypt(xcbc->K[y], xcbc->K[y], skey); + } + } + + /* setup K1 */ + err = cipher_descriptor[cipher].setup(xcbc->K[0], k1, 0, &xcbc->key); + + /* setup struct */ + zeromem(xcbc->IV, cipher_descriptor[cipher].block_length); + xcbc->blocksize = cipher_descriptor[cipher].block_length; + xcbc->cipher = cipher; + xcbc->buflen = 0; +done: + cipher_descriptor[cipher].done(skey); + if (skey != NULL) { +#ifdef LTC_CLEAN_STACK + zeromem(skey, sizeof(*skey)); +#endif + XFREE(skey); + } + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/xcbc/xcbc_memory.c b/deps/libtomcrypt/src/mac/xcbc/xcbc_memory.c new file mode 100644 index 0000000..bd7f388 --- /dev/null +++ b/deps/libtomcrypt/src/mac/xcbc/xcbc_memory.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file xcbc_process.c + XCBC Support, XCBC-MAC a block of memory +*/ + +#ifdef LTC_XCBC + +/** XCBC-MAC a block of memory + @param cipher Index of cipher to use + @param key [in] Secret key + @param keylen Length of key in octets + @param in [in] Message to MAC + @param inlen Length of input in octets + @param out [out] Destination for the MAC tag + @param outlen [in/out] Output size and final tag size + Return CRYPT_OK on success. +*/ +int xcbc_memory(int cipher, + const unsigned char *key, unsigned long keylen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + xcbc_state *xcbc; + int err; + + /* is the cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* Use accelerator if found */ + if (cipher_descriptor[cipher].xcbc_memory != NULL) { + return cipher_descriptor[cipher].xcbc_memory(key, keylen, in, inlen, out, outlen); + } + + xcbc = XCALLOC(1, sizeof(*xcbc)); + if (xcbc == NULL) { + return CRYPT_MEM; + } + + if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { + goto done; + } + + if ((err = xcbc_process(xcbc, in, inlen)) != CRYPT_OK) { + goto done; + } + + err = xcbc_done(xcbc, out, outlen); +done: + XFREE(xcbc); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c b/deps/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c new file mode 100644 index 0000000..d9e48d9 --- /dev/null +++ b/deps/libtomcrypt/src/mac/xcbc/xcbc_memory_multi.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file xcbc_memory_multi.c + XCBC support, process multiple blocks of memory, Tom St Denis +*/ + +#ifdef LTC_XCBC + +/** + XCBC multiple blocks of memory + @param cipher The index of the desired cipher + @param key The secret key + @param keylen The length of the secret key (octets) + @param out [out] The destination of the authentication tag + @param outlen [in/out] The max size and resulting size of the authentication tag (octets) + @param in The data to send through XCBC + @param inlen The length of the data to send through XCBC (octets) + @param ... tuples of (data,len) pairs to XCBC, terminated with a (NULL,x) (x=don't care) + @return CRYPT_OK if successful +*/ +int xcbc_memory_multi(int cipher, + const unsigned char *key, unsigned long keylen, + unsigned char *out, unsigned long *outlen, + const unsigned char *in, unsigned long inlen, ...) +{ + int err; + xcbc_state *xcbc; + va_list args; + const unsigned char *curptr; + unsigned long curlen; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* allocate ram for xcbc state */ + xcbc = XMALLOC(sizeof(xcbc_state)); + if (xcbc == NULL) { + return CRYPT_MEM; + } + + /* xcbc process the message */ + if ((err = xcbc_init(xcbc, cipher, key, keylen)) != CRYPT_OK) { + goto LBL_ERR; + } + va_start(args, inlen); + curptr = in; + curlen = inlen; + for (;;) { + /* process buf */ + if ((err = xcbc_process(xcbc, curptr, curlen)) != CRYPT_OK) { + goto LBL_ERR; + } + /* step to next */ + curptr = va_arg(args, const unsigned char*); + if (curptr == NULL) { + break; + } + curlen = va_arg(args, unsigned long); + } + if ((err = xcbc_done(xcbc, out, outlen)) != CRYPT_OK) { + goto LBL_ERR; + } +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(xcbc, sizeof(xcbc_state)); +#endif + XFREE(xcbc); + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/mac/xcbc/xcbc_process.c b/deps/libtomcrypt/src/mac/xcbc/xcbc_process.c new file mode 100644 index 0000000..3cb0c46 --- /dev/null +++ b/deps/libtomcrypt/src/mac/xcbc/xcbc_process.c @@ -0,0 +1,63 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file xcbc_process.c + XCBC Support, process blocks with XCBC +*/ + +#ifdef LTC_XCBC + +/** Process data through XCBC-MAC + @param xcbc The XCBC-MAC state + @param in Input data to process + @param inlen Length of input in octets + Return CRYPT_OK on success +*/ +int xcbc_process(xcbc_state *xcbc, const unsigned char *in, unsigned long inlen) +{ + int err; +#ifdef LTC_FAST + int x; +#endif + + LTC_ARGCHK(xcbc != NULL); + LTC_ARGCHK(in != NULL); + + /* check structure */ + if ((err = cipher_is_valid(xcbc->cipher)) != CRYPT_OK) { + return err; + } + + if ((xcbc->blocksize > cipher_descriptor[xcbc->cipher].block_length) || (xcbc->blocksize < 0) || + (xcbc->buflen > xcbc->blocksize) || (xcbc->buflen < 0)) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (xcbc->buflen == 0) { + while (inlen > (unsigned long)xcbc->blocksize) { + for (x = 0; x < xcbc->blocksize; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&(xcbc->IV[x]))) ^= *(LTC_FAST_TYPE_PTR_CAST(&(in[x]))); + } + cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); + in += xcbc->blocksize; + inlen -= xcbc->blocksize; + } + } +#endif + + while (inlen) { + if (xcbc->buflen == xcbc->blocksize) { + cipher_descriptor[xcbc->cipher].ecb_encrypt(xcbc->IV, xcbc->IV, &xcbc->key); + xcbc->buflen = 0; + } + xcbc->IV[xcbc->buflen++] ^= *in++; + --inlen; + } + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/mac/xcbc/xcbc_test.c b/deps/libtomcrypt/src/mac/xcbc/xcbc_test.c new file mode 100644 index 0000000..23555de --- /dev/null +++ b/deps/libtomcrypt/src/mac/xcbc/xcbc_test.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file xcbc_test.c + XCBC Support, Test XCBC-MAC mode +*/ + +#ifdef LTC_XCBC + +/** Test XCBC-MAC mode + Return CRYPT_OK on success +*/ +int xcbc_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct { + int msglen; + unsigned char K[16], M[34], T[16]; + } tests[] = { +{ + 0, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0 }, + + { 0x75, 0xf0, 0x25, 0x1d, 0x52, 0x8a, 0xc0, 0x1c, + 0x45, 0x73, 0xdf, 0xd5, 0x84, 0xd7, 0x9f, 0x29 } +}, + +{ + 3, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02 }, + + { 0x5b, 0x37, 0x65, 0x80, 0xae, 0x2f, 0x19, 0xaf, + 0xe7, 0x21, 0x9c, 0xee, 0xf1, 0x72, 0x75, 0x6f } +}, + +{ + 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0xd2, 0xa2, 0x46, 0xfa, 0x34, 0x9b, 0x68, 0xa7, + 0x99, 0x98, 0xa4, 0x39, 0x4f, 0xf7, 0xa2, 0x63 } +}, + +{ + 32, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + + { 0xf5, 0x4f, 0x0e, 0xc8, 0xd2, 0xb9, 0xf3, 0xd3, + 0x68, 0x07, 0x73, 0x4b, 0xd5, 0x28, 0x3f, 0xd4 } +}, + +{ + 34, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21 }, + + { 0xbe, 0xcb, 0xb3, 0xbc, 0xcd, 0xb5, 0x18, 0xa3, + 0x06, 0x77, 0xd5, 0x48, 0x1f, 0xb6, 0xb4, 0xd8 }, +}, + + + +}; + unsigned char T[16]; + unsigned long taglen; + int err, x, idx; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + taglen = 16; + if ((err = xcbc_memory(idx, tests[x].K, 16, tests[x].M, tests[x].msglen, T, &taglen)) != CRYPT_OK) { + return err; + } + if (compare_testvector(T, taglen, tests[x].T, 16, "XCBC", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/deps/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c b/deps/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c new file mode 100644 index 0000000..5827bf3 --- /dev/null +++ b/deps/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c @@ -0,0 +1,1578 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_fp_mulmod.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && defined(LTC_MECC_FP) +#include + +/* number of entries in the cache */ +#ifndef FP_ENTRIES +#define FP_ENTRIES 16 +#endif + +/* number of bits in LUT */ +#ifndef FP_LUT +#define FP_LUT 8U +#endif + +#if (FP_LUT > 12) || (FP_LUT < 2) + #error FP_LUT must be between 2 and 12 inclusively +#endif + +/** Our FP cache */ +static struct { + ecc_point *g, /* cached COPY of base point */ + *LUT[1U< 6 + { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, + { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, + { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, + { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, + { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, + { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, + { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, + { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, +#if FP_LUT > 7 + { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, + { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, + { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, + { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, + { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, + { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, + { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, + { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, + { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, + { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, + { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, + { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, + { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, + { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, + { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, + { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, +#if FP_LUT > 8 + { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, + { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, + { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, + { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, + { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, + { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, + { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, + { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, + { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, + { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, + { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, + { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, + { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, + { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, + { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, + { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, + { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, + { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, + { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, + { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, + { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, + { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, + { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, + { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, + { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, + { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, + { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, + { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, + { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, + { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, + { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, + { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, +#if FP_LUT > 9 + { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, + { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, + { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, + { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, + { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, + { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, + { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, + { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, + { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, + { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, + { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, + { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, + { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, + { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, + { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, + { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, + { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, + { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, + { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, + { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, + { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, + { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, + { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, + { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, + { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, + { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, + { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, + { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, + { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, + { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, + { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, + { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, + { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, + { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, + { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, + { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, + { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, + { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, + { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, + { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, + { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, + { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, + { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, + { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, + { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, + { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, + { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, + { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, + { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, + { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, + { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, + { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, + { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, + { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, + { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, + { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, + { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, + { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, + { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, + { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, + { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, + { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, + { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, + { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, +#if FP_LUT > 10 + { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, + { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, + { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, + { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, + { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, + { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, + { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, + { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, + { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, + { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, + { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, + { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, + { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, + { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, + { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, + { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, + { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, + { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, + { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, + { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, + { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, + { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, + { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, + { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, + { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, + { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, + { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, + { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, + { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, + { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, + { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, + { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, + { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, + { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, + { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, + { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, + { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, + { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, + { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, + { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, + { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, + { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, + { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, + { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, + { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, + { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, + { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, + { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, + { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, + { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, + { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, + { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, + { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, + { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, + { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, + { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, + { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, + { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, + { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, + { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, + { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, + { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, + { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, + { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, + { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, + { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, + { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, + { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, + { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, + { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, + { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, + { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, + { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, + { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, + { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, + { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, + { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, + { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, + { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, + { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, + { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, + { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, + { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, + { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, + { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, + { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, + { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, + { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, + { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, + { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, + { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, + { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, + { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, + { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, + { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, + { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, + { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, + { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, + { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, + { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, + { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, + { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, + { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, + { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, + { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, + { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, + { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, + { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, + { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, + { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, + { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, + { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, + { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, + { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, + { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, + { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, + { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, + { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, + { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, + { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, + { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, + { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, + { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, + { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, + { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, + { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, + { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, + { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, +#if FP_LUT > 11 + { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, + { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, + { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, + { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, + { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, + { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, + { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, + { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, + { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, + { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, + { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, + { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, + { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, + { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, + { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, + { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, + { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, + { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, + { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, + { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, + { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, + { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, + { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, + { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, + { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, + { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, + { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, + { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, + { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, + { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, + { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, + { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, + { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, + { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, + { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, + { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, + { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, + { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, + { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, + { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, + { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, + { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, + { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, + { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, + { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, + { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, + { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, + { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, + { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, + { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, + { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, + { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, + { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, + { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, + { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, + { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, + { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, + { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, + { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, + { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, + { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, + { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, + { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, + { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, + { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, + { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, + { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, + { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, + { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, + { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, + { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, + { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, + { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, + { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, + { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, + { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, + { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, + { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, + { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, + { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, + { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, + { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, + { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, + { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, + { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, + { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, + { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, + { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, + { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, + { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, + { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, + { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, + { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, + { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, + { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, + { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, + { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, + { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, + { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, + { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, + { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, + { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, + { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, + { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, + { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, + { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, + { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, + { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, + { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, + { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, + { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, + { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, + { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, + { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, + { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, + { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, + { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, + { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, + { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, + { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, + { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, + { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, + { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, + { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, + { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, + { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, + { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, + { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, + { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, + { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, + { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, + { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, + { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, + { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, + { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, + { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, + { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, + { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, + { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, + { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, + { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, + { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, + { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, + { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, + { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, + { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, + { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, + { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, + { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, + { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, + { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, + { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, + { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, + { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, + { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, + { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, + { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, + { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, + { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, + { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, + { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, + { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, + { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, + { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, + { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, + { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, + { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, + { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, + { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, + { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, + { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, + { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, + { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, + { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, + { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, + { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, + { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, + { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, + { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, + { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, + { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, + { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, + { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, + { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, + { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, + { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, + { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, + { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, + { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, + { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, + { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, + { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, + { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, + { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, + { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, + { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, + { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, + { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, + { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, + { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, + { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, + { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, + { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, + { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, + { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, + { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, + { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, + { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, + { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, + { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, + { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, + { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, + { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, + { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, + { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, + { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, + { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, + { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, + { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, + { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, + { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, + { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, + { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, + { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, + { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, + { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, + { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, + { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, + { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, + { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, + { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, + { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, + { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, + { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, + { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, + { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, + { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, + { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, + { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, + { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, + { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, + { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, + { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, + { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, + { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, + { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, + { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, + { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, + { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, + { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, + { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, + { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, + { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, + { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, + { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, + { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, +#endif +#endif +#endif +#endif +#endif +#endif +}; + +/* find a hole and free as required, return -1 if no hole found */ +static int s_find_hole(void) +{ + unsigned x; + int y, z; + for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) { + z = x; + y = fp_cache[x].lru_count; + } + } + + /* decrease all */ + for (x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].lru_count > 3) { + --(fp_cache[x].lru_count); + } + } + + /* free entry z */ + if (z >= 0 && fp_cache[z].g) { + if (fp_cache[z].mu != NULL) { + mp_clear(fp_cache[z].mu); + fp_cache[z].mu = NULL; + } + ltc_ecc_del_point(fp_cache[z].g); + fp_cache[z].g = NULL; + for (x = 0; x < (1U<x, g->x) == LTC_MP_EQ && + mp_cmp(fp_cache[x].g->y, g->y) == LTC_MP_EQ && + mp_cmp(fp_cache[x].g->z, g->z) == LTC_MP_EQ) { + break; + } + } + if (x == FP_ENTRIES) { + x = -1; + } + return x; +} + +/* add a new base to the cache */ +static int s_add_entry(int idx, ecc_point *g) +{ + unsigned x, y; + + /* allocate base and LUT */ + fp_cache[idx].g = ltc_ecc_new_point(); + if (fp_cache[idx].g == NULL) { + return CRYPT_MEM; + } + + /* copy x and y */ + if ((mp_copy(g->x, fp_cache[idx].g->x) != CRYPT_OK) || + (mp_copy(g->y, fp_cache[idx].g->y) != CRYPT_OK) || + (mp_copy(g->z, fp_cache[idx].g->z) != CRYPT_OK)) { + ltc_ecc_del_point(fp_cache[idx].g); + fp_cache[idx].g = NULL; + return CRYPT_MEM; + } + + for (x = 0; x < (1U<x, mu, modulus, fp_cache[idx].LUT[1]->x) != CRYPT_OK) || + (mp_mulmod(fp_cache[idx].g->y, mu, modulus, fp_cache[idx].LUT[1]->y) != CRYPT_OK) || + (mp_mulmod(fp_cache[idx].g->z, mu, modulus, fp_cache[idx].LUT[1]->z) != CRYPT_OK)) { goto ERR; } + + /* make all single bit entries */ + for (x = 1; x < FP_LUT; x++) { + if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, fp_cache[idx].LUT[1<x) != CRYPT_OK) || + (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, fp_cache[idx].LUT[1<y) != CRYPT_OK) || + (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, fp_cache[idx].LUT[1<z) != CRYPT_OK)) { goto ERR; } + + /* now double it bitlen/FP_LUT times */ + for (y = 0; y < lut_gap; y++) { + if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<z, modulus, mp)) != CRYPT_OK) { goto ERR; } + + /* invert it */ + if ((err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus, fp_cache[idx].LUT[x]->z)) != CRYPT_OK) { goto ERR; } + + /* now square it */ + if ((err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } + + /* fix x */ + if ((err = mp_mulmod(fp_cache[idx].LUT[x]->x, tmp, modulus, fp_cache[idx].LUT[x]->x)) != CRYPT_OK) { goto ERR; } + + /* get 1/z^3 */ + if ((err = mp_mulmod(tmp, fp_cache[idx].LUT[x]->z, modulus, tmp)) != CRYPT_OK) { goto ERR; } + + /* fix y */ + if ((err = mp_mulmod(fp_cache[idx].LUT[x]->y, tmp, modulus, fp_cache[idx].LUT[x]->y)) != CRYPT_OK) { goto ERR; } + + /* free z */ + mp_clear(fp_cache[idx].LUT[x]->z); + fp_cache[idx].LUT[x]->z = NULL; + } + mp_clear(tmp); + + return CRYPT_OK; +ERR: + err = CRYPT_MEM; +DONE: + for (y = 0; y < (1U< mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ltc_ecc_sets[x].size; x++) { + if (y <= (unsigned)ltc_ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_init(&order)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { + mp_clear(&order); + return err; + } + + /* k must be less than modulus */ + if (mp_cmp(k, order) != LTC_MP_LT) { + if ((err = mp_init(&tk)) != CRYPT_OK) { + mp_clear(order); + return err; + } + if ((err = mp_mod(k, order, tk)) != CRYPT_OK) { + mp_clear(tk); + mp_clear(order); + return err; + } + } else { + tk = k; + } + mp_clear(order); + } else { + tk = k; + } + + /* get bitlen and round up to next multiple of FP_LUT */ + bitlen = mp_unsigned_bin_size(modulus) << 3; + x = bitlen % FP_LUT; + if (x) { + bitlen += FP_LUT - x; + } + lut_gap = bitlen / FP_LUT; + + /* get the k value */ + if (mp_unsigned_bin_size(tk) > (sizeof(kb) - 2)) { + if (tk != k) { + mp_clear(tk); + } + return CRYPT_BUFFER_OVERFLOW; + } + + /* store k */ + zeromem(kb, sizeof(kb)); + if ((err = mp_to_unsigned_bin(tk, kb)) != CRYPT_OK) { + if (tk != k) { + mp_clear(tk); + } + return err; + } + + /* let's reverse kb so it's little endian */ + x = 0; + y = mp_unsigned_bin_size(tk) - 1; + if (tk != k) { + mp_clear(tk); + } + while ((unsigned)x < y) { + z = kb[x]; kb[x] = kb[y]; kb[y] = z; + ++x; --y; + } + + /* at this point we can start, yipee */ + first = 1; + for (x = lut_gap-1; x >= 0; x--) { + /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ + bitpos = x; + for (y = z = 0; y < FP_LUT; y++) { + z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y; + bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ + } + + /* double if not first */ + if (!first) { + if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + + /* add if not first, otherwise copy */ + if (!first && z) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } else if (z) { + if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != CRYPT_OK) || + (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != CRYPT_OK) || + (mp_copy(fp_cache[idx].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } + first = 0; + } + } + z = 0; + zeromem(kb, sizeof(kb)); + /* map R back from projective space */ + if (map) { + err = ltc_ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } + return err; +} + +#ifdef LTC_ECC_SHAMIR +/* perform a fixed point ECC mulmod */ +static int ss_accel_fp_mul2add(int idx1, int idx2, + void *kA, void *kB, + ecc_point *R, void *a, void *modulus, void *mp) +{ + unsigned char kb[2][128]; + int x; + unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; + void *tka, *tkb, *order; + + /* if it's smaller than modulus we fine */ + if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ltc_ecc_sets[x].size; x++) { + if (y <= (unsigned)ltc_ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_init(&order)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { + mp_clear(&order); + return err; + } + + /* kA must be less than modulus */ + if (mp_cmp(kA, order) != LTC_MP_LT) { + if ((err = mp_init(&tka)) != CRYPT_OK) { + mp_clear(order); + return err; + } + if ((err = mp_mod(kA, order, tka)) != CRYPT_OK) { + mp_clear(tka); + mp_clear(order); + return err; + } + } else { + tka = kA; + } + mp_clear(order); + } else { + tka = kA; + } + + /* if it's smaller than modulus we fine */ + if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ltc_ecc_sets[x].size; x++) { + if (y <= (unsigned)ltc_ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_init(&order)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(order, ltc_ecc_sets[x].order, 16)) != CRYPT_OK) { + mp_clear(&order); + return err; + } + + /* kB must be less than modulus */ + if (mp_cmp(kB, order) != LTC_MP_LT) { + if ((err = mp_init(&tkb)) != CRYPT_OK) { + mp_clear(order); + return err; + } + if ((err = mp_mod(kB, order, tkb)) != CRYPT_OK) { + mp_clear(tkb); + mp_clear(order); + return err; + } + } else { + tkb = kB; + } + mp_clear(order); + } else { + tkb = kB; + } + + /* get bitlen and round up to next multiple of FP_LUT */ + bitlen = mp_unsigned_bin_size(modulus) << 3; + x = bitlen % FP_LUT; + if (x) { + bitlen += FP_LUT - x; + } + lut_gap = bitlen / FP_LUT; + + /* get the k value */ + if ((mp_unsigned_bin_size(tka) > (sizeof(kb[0]) - 2)) || (mp_unsigned_bin_size(tkb) > (sizeof(kb[0]) - 2)) ) { + if (tka != kA) { + mp_clear(tka); + } + if (tkb != kB) { + mp_clear(tkb); + } + return CRYPT_BUFFER_OVERFLOW; + } + + /* store k */ + zeromem(kb, sizeof(kb)); + if ((err = mp_to_unsigned_bin(tka, kb[0])) != CRYPT_OK) { + if (tka != kA) { + mp_clear(tka); + } + if (tkb != kB) { + mp_clear(tkb); + } + return err; + } + + /* let's reverse kb so it's little endian */ + x = 0; + y = mp_unsigned_bin_size(tka) - 1; + if (tka != kA) { + mp_clear(tka); + } + while ((unsigned)x < y) { + z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z; + ++x; --y; + } + + /* store b */ + if ((err = mp_to_unsigned_bin(tkb, kb[1])) != CRYPT_OK) { + if (tkb != kB) { + mp_clear(tkb); + } + return err; + } + + x = 0; + y = mp_unsigned_bin_size(tkb) - 1; + if (tkb != kB) { + mp_clear(tkb); + } + while ((unsigned)x < y) { + z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z; + ++x; --y; + } + + /* at this point we can start, yipee */ + first = 1; + for (x = lut_gap-1; x >= 0; x--) { + /* extract FP_LUT bits from kb spread out by lut_gap bits and offset by x bits from the start */ + bitpos = x; + for (y = zA = zB = 0; y < FP_LUT; y++) { + zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y; + zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y; + bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid the mult in each loop */ + } + + /* double if not first */ + if (!first) { + if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + + /* add if not first, otherwise copy */ + if (!first) { + if (zA) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + if (zB) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + } else { + if (zA) { + if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != CRYPT_OK) || + (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != CRYPT_OK) || + (mp_copy(fp_cache[idx1].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } + first = 0; + } + if (zB && first == 0) { + if (zB) { + if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) { + return err; + } + } + } else if (zB && first == 1) { + if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != CRYPT_OK) || + (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != CRYPT_OK) || + (mp_copy(fp_cache[idx2].mu, R->z) != CRYPT_OK)) { return CRYPT_MEM; } + first = 0; + } + } + } + zeromem(kb, sizeof(kb)); + return ltc_ecc_map(R, modulus, mp); +} + +/** ECC Fixed Point mulmod global + Computes kA*A + kB*B = C using Shamir's Trick + @param A First point to multiply + @param kA What to multiple A by + @param B Second point to multiply + @param kB What to multiple B by + @param C [out] Destination point (can overlap with A or B) + @param modulus Modulus for curve + @return CRYPT_OK on success +*/ +int ltc_ecc_fp_mul2add(ecc_point *A, void *kA, + ecc_point *B, void *kB, + ecc_point *C, + void *a, + void *modulus) +{ + int idx1, idx2, err; + void *mp, *mu; + + mp = NULL; + mu = NULL; + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* find point */ + idx1 = s_find_base(A); + + /* no entry? */ + if (idx1 == -1) { + /* find hole and add it */ + if ((idx1 = s_find_hole()) >= 0) { + if ((err = s_add_entry(idx1, A)) != CRYPT_OK) { + goto LBL_ERR; + } + } + } + if (idx1 != -1) { + /* increment LRU */ + ++(fp_cache[idx1].lru_count); + } + + /* find point */ + idx2 = s_find_base(B); + + /* no entry? */ + if (idx2 == -1) { + /* find hole and add it */ + if ((idx2 = s_find_hole()) >= 0) { + if ((err = s_add_entry(idx2, B)) != CRYPT_OK) { + goto LBL_ERR; + } + } + } + if (idx2 != -1) { + /* increment LRU */ + ++(fp_cache[idx2].lru_count); + } + + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* build the LUT */ + if ((err = s_build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR;; + } + } + + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) { + if (mp == NULL) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* build the LUT */ + if ((err = s_build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR;; + } + } + + + if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 && fp_cache[idx2].lru_count >= 2) { + if (mp == NULL) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + } + err = ss_accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); + } else { + err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus); + } +LBL_ERR: + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + if (mp != NULL) { + mp_montgomery_free(mp); + } + if (mu != NULL) { + mp_clear(mu); + } + return err; +} +#endif + +/** ECC Fixed Point mulmod global + @param k The multiplicand + @param G Base point to multiply + @param R [out] Destination of product + @param a ECC curve parameter a + @param modulus The modulus for the curve + @param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form + @return CRYPT_OK if successful +*/ +int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map) +{ + int idx, err; + void *mp, *mu; + + mp = NULL; + mu = NULL; + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* find point */ + idx = s_find_base(G); + + /* no entry? */ + if (idx == -1) { + /* find hole and add it */ + idx = s_find_hole(); + + if (idx >= 0) { + if ((err = s_add_entry(idx, G)) != CRYPT_OK) { + goto LBL_ERR; + } + } + } + if (idx != -1) { + /* increment LRU */ + ++(fp_cache[idx].lru_count); + } + + + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx >= 0 && fp_cache[idx].lru_count == 2) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* build the LUT */ + if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR;; + } + } + + if (idx >= 0 && fp_cache[idx].lru_count >= 2) { + if (mp == NULL) { + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; } + } + err = s_accel_fp_mul(idx, k, R, a, modulus, mp, map); + } else { + err = ltc_ecc_mulmod(k, G, R, a, modulus, map); + } +LBL_ERR: + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + if (mp != NULL) { + mp_montgomery_free(mp); + } + if (mu != NULL) { + mp_clear(mu); + } + return err; +} + +/* helper function for freeing the cache ... must be called with the cache mutex locked */ +static void s_ltc_ecc_fp_free_cache(void) +{ + unsigned x, y; + for (x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].g != NULL) { + for (y = 0; y < (1U<= 0) { + /* it is already in the cache ... just check that the LUT is initialized */ + if(fp_cache[idx].lru_count >= 2) { + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return CRYPT_OK; + } + } + + if(idx == -1 && (idx = s_find_hole()) == -1) { + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + if ((err = s_add_entry(idx, g)) != CRYPT_OK) { + goto LBL_ERR; + } + /* compute mp */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compute mu */ + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* build the LUT */ + if ((err = s_build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) { + goto LBL_ERR; + } + fp_cache[idx].lru_count = 2; + fp_cache[idx].lock = lock; +LBL_ERR: + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + if (mp != NULL) { + mp_montgomery_free(mp); + } + if (mu != NULL) { + mp_clear(mu); + } + return err; +} + +/** Prevent/permit the FP cache from being updated + @param flag If flag is 0, remove cache lock (unlock), otherwise lock it +*/ +void ltc_ecc_fp_tablelock(int lock) +{ + int i; + + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + for (i = 0; i < FP_ENTRIES; i++) { + fp_cache[i].lock = lock; + } + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); +} + +/** Export the current cache as a binary packet + @param out [out] pointer to malloc'ed space containing the packet + @param outlen [out] size of exported packet + @return CRYPT_OK if successful +*/ +int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen) +{ + ltc_asn1_list *cache_entry; + unsigned int i, j, k; + unsigned long fp_entries, fp_lut, num_entries; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + fp_entries = FP_ENTRIES; + fp_lut = FP_LUT; + num_entries = 0; + + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* + * build the list; + Cache DEFINITIONS ::= + BEGIN + CacheDump ::= SEQUENCE { + numEntries SHORTINTEGER, + maxEntries SHORTINTEGER, + numLUT SHORTINTEGER, + cache SEQUENCE OF INTEGER + } + END + * + */ + /* + * The cache itself is a point (3 INTEGERS), + * the LUT as pairs of INTEGERS (2 * 1<x, 1); + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); + for (k = 0; k < (1U<x, 1); + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].LUT[k]->y, 1); + } + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); + } + LTC_SET_ASN1(cache_entry, j++, LTC_ASN1_EOL, 0, 0); + + LTC_SET_ASN1(cache_entry, 0, LTC_ASN1_SHORT_INTEGER, &num_entries, 1); + + if ((err = der_length_sequence(cache_entry, j, outlen)) != CRYPT_OK) { + goto save_err; + } + if ((*out = XMALLOC(*outlen)) == NULL) { + err = CRYPT_MEM; + goto save_err; + } + err = der_encode_sequence(cache_entry, j, *out, outlen); +save_err: + XFREE(cache_entry); + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return err; +} + +/** Import a binary packet into the current cache + @param in [in] pointer to packet + @param inlen [in] size of packet (bytes) + @return CRYPT_OK if successful +*/ +int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) +{ + int err; + ltc_asn1_list *asn1_list; + unsigned long num_entries, fp_entries, fp_lut; + unsigned long i, j; + unsigned int x; + + LTC_ARGCHK(in != NULL); + if (inlen == 0) { + return CRYPT_INVALID_ARG; + } + + /* zero indecies */ + i = 0; + j = 0; + asn1_list = NULL; + + LTC_MUTEX_LOCK(<c_ecc_fp_lock); + /* + * start with an empty cache + */ + s_ltc_ecc_fp_free_cache(); + + /* + * decode the input packet: It consists of a sequence with a few + * integers (including the FP_ENTRIES and FP_LUT sizes), followed by a + * SEQUENCE which is the cache itself. + * + * use standard decoding for the first part, then flexible for the second + */ + if((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1, &num_entries, + LTC_ASN1_SHORT_INTEGER, 1, &fp_entries, + LTC_ASN1_SHORT_INTEGER, 1, &fp_lut, + LTC_ASN1_EOL, 0, 0)) != CRYPT_OK) { + goto ERR_OUT; + } + if (fp_entries != FP_ENTRIES || fp_lut != FP_LUT || num_entries > fp_entries) { + err = CRYPT_INVALID_PACKET; + goto ERR_OUT; + } + if ((asn1_list = XCALLOC(3+num_entries*(4+2*(1<x, 1); + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->y, 1); + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].g->z, 1); + for (x = 0; x < (1U<x, &p->y, LTC_NULL)) != CRYPT_OK) { + goto ERR_OUT; + } + p->z = NULL; + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->x, 1); + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, p->y, 1); + } + if((err = mp_init(&fp_cache[i].mu)) != CRYPT_OK) { + goto ERR_OUT; + } + LTC_SET_ASN1(asn1_list, j++, LTC_ASN1_INTEGER, fp_cache[i].mu, 1); + fp_cache[i].lru_count = 3; + fp_cache[i].lock = 1; + } + + if ((err = der_decode_sequence(in, inlen, asn1_list, j)) != CRYPT_OK) { + goto ERR_OUT; + } + XFREE(asn1_list); + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return CRYPT_OK; +ERR_OUT: + if(asn1_list) + XFREE(asn1_list); + s_ltc_ecc_fp_free_cache(); + LTC_MUTEX_UNLOCK(<c_ecc_fp_lock); + return err; +} + +#endif + + diff --git a/deps/libtomcrypt/src/math/gmp_desc.c b/deps/libtomcrypt/src/math/gmp_desc.c new file mode 100644 index 0000000..2db699d --- /dev/null +++ b/deps/libtomcrypt/src/math/gmp_desc.c @@ -0,0 +1,658 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define DESC_DEF_ONLY +#include "tomcrypt_private.h" + +#ifdef GMP_DESC + +#include +#include + +static int init(void **a) +{ + LTC_ARGCHK(a != NULL); + + *a = XCALLOC(1, sizeof(__mpz_struct)); + if (*a == NULL) { + return CRYPT_MEM; + } + mpz_init(((__mpz_struct *)*a)); + return CRYPT_OK; +} + +static void deinit(void *a) +{ + LTC_ARGCHKVD(a != NULL); + mpz_clear(a); + XFREE(a); +} + +static int neg(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_neg(b, a); + return CRYPT_OK; +} + +static int copy(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_set(b, a); + return CRYPT_OK; +} + +static int init_copy(void **a, void *b) +{ + if (init(a) != CRYPT_OK) { + return CRYPT_MEM; + } + return copy(b, *a); +} + +/* ---- trivial ---- */ +static int set_int(void *a, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); + mpz_set_ui(((__mpz_struct *)a), b); + return CRYPT_OK; +} + +static unsigned long get_int(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpz_get_ui(a); +} + +static ltc_mp_digit get_digit(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + return mpz_getlimbn(a, n); +} + +static int get_digit_count(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpz_size(a); +} + +static int compare(void *a, void *b) +{ + int ret; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + ret = mpz_cmp(a, b); + if (ret < 0) { + return LTC_MP_LT; + } else if (ret > 0) { + return LTC_MP_GT; + } else { + return LTC_MP_EQ; + } +} + +static int compare_d(void *a, ltc_mp_digit b) +{ + int ret; + LTC_ARGCHK(a != NULL); + ret = mpz_cmp_ui(((__mpz_struct *)a), b); + if (ret < 0) { + return LTC_MP_LT; + } else if (ret > 0) { + return LTC_MP_GT; + } else { + return LTC_MP_EQ; + } +} + +static int count_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpz_sizeinbase(a, 2); +} + +static int count_lsb_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return mpz_scan1(a, 0); +} + + +static int twoexpt(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + mpz_set_ui(a, 0); + mpz_setbit(a, n); + return CRYPT_OK; +} + +/* ---- conversions ---- */ + +static const char rmap[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + +/* read ascii string */ +static int read_radix(void *a, const char *b, int radix) +{ + int ret; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (radix == 64) { + /* Sadly, GMP only supports radixes up to 62, but we need 64. + * So, although this is not the most elegant or efficient way, + * let's just convert the base 64 string (6 bits per digit) to + * an octal string (3 bits per digit) that's twice as long. */ + char c, *tmp, *q; + const char *p; + int i; + tmp = XMALLOC (1 + 2 * XSTRLEN (b)); + if (tmp == NULL) { + return CRYPT_MEM; + } + p = b; + q = tmp; + while ((c = *p++) != 0) { + for (i = 0; i < 64; i++) { + if (c == rmap[i]) + break; + } + if (i == 64) { + XFREE (tmp); + /* printf ("c = '%c'\n", c); */ + return CRYPT_ERROR; + } + *q++ = '0' + (i / 8); + *q++ = '0' + (i % 8); + } + *q = 0; + ret = mpz_set_str(a, tmp, 8); + /* printf ("ret = %d for '%s'\n", ret, tmp); */ + XFREE (tmp); + } else { + ret = mpz_set_str(a, b, radix); + } + return (ret == 0 ? CRYPT_OK : CRYPT_ERROR); +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (radix >= 11 && radix <= 36) + /* If radix is positive, GMP uses lowercase, and if negative, uppercase. + * We want it to use uppercase, to match the test vectors (presumably + * generated with LibTomMath). */ + radix = -radix; + mpz_get_str(b, radix, a); + return CRYPT_OK; +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + unsigned long t; + LTC_ARGCHK(a != NULL); + t = mpz_sizeinbase(a, 2); + if (mpz_cmp_ui(((__mpz_struct *)a), 0) == 0) return 0; + return (t>>3) + ((t&7)?1:0); +} + +/* store */ +static int unsigned_write(void *a, unsigned char *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_export(b, NULL, 1, 1, 1, 0, ((__mpz_struct*)a)); + return CRYPT_OK; +} + +/* read */ +static int unsigned_read(void *a, unsigned char *b, unsigned long len) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_import(a, len, 1, 1, 1, 0, b); + return CRYPT_OK; +} + +/* add */ +static int add(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_add(c, a, b); + return CRYPT_OK; +} + +static int addi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + mpz_add_ui(c, a, b); + return CRYPT_OK; +} + +/* sub */ +static int sub(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_sub(c, a, b); + return CRYPT_OK; +} + +static int subi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + mpz_sub_ui(c, a, b); + return CRYPT_OK; +} + +/* mul */ +static int mul(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_mul(c, a, b); + return CRYPT_OK; +} + +static int muli(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + mpz_mul_ui(c, a, b); + return CRYPT_OK; +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_mul(b, a, a); + return CRYPT_OK; +} + +/* sqrtmod_prime */ +static int sqrtmod_prime(void *n, void *prime, void *ret) +{ + int res, legendre, i; + mpz_t t1, C, Q, S, Z, M, T, R, two; + + LTC_ARGCHK(n != NULL); + LTC_ARGCHK(prime != NULL); + LTC_ARGCHK(ret != NULL); + + /* first handle the simple cases */ + if (mpz_cmp_ui(((__mpz_struct *)n), 0) == 0) { + mpz_set_ui(ret, 0); + return CRYPT_OK; + } + if (mpz_cmp_ui(((__mpz_struct *)prime), 2) == 0) return CRYPT_ERROR; /* prime must be odd */ + legendre = mpz_legendre(n, prime); + if (legendre == -1) return CRYPT_ERROR; /* quadratic non-residue mod prime */ + + mpz_init(t1); mpz_init(C); mpz_init(Q); + mpz_init(S); mpz_init(Z); mpz_init(M); + mpz_init(T); mpz_init(R); mpz_init(two); + + /* SPECIAL CASE: if prime mod 4 == 3 + * compute directly: res = n^(prime+1)/4 mod prime + * Handbook of Applied Cryptography algorithm 3.36 + */ + i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */ + if (i == 3) { + mpz_add_ui(t1, prime, 1); + mpz_fdiv_q_2exp(t1, t1, 2); + mpz_powm(ret, n, t1, prime); + res = CRYPT_OK; + goto cleanup; + } + + /* NOW: Tonelli-Shanks algorithm */ + + /* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */ + mpz_set(Q, prime); + mpz_sub_ui(Q, Q, 1); + /* Q = prime - 1 */ + mpz_set_ui(S, 0); + /* S = 0 */ + while (mpz_even_p(Q)) { + mpz_fdiv_q_2exp(Q, Q, 1); + /* Q = Q / 2 */ + mpz_add_ui(S, S, 1); + /* S = S + 1 */ + } + + /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + mpz_set_ui(Z, 2); + /* Z = 2 */ + while(1) { + legendre = mpz_legendre(Z, prime); + if (legendre == -1) break; + mpz_add_ui(Z, Z, 1); + /* Z = Z + 1 */ + } + + mpz_powm(C, Z, Q, prime); + /* C = Z ^ Q mod prime */ + mpz_add_ui(t1, Q, 1); + mpz_fdiv_q_2exp(t1, t1, 1); + /* t1 = (Q + 1) / 2 */ + mpz_powm(R, n, t1, prime); + /* R = n ^ ((Q + 1) / 2) mod prime */ + mpz_powm(T, n, Q, prime); + /* T = n ^ Q mod prime */ + mpz_set(M, S); + /* M = S */ + mpz_set_ui(two, 2); + + while (1) { + mpz_set(t1, T); + i = 0; + while (1) { + if (mpz_cmp_ui(((__mpz_struct *)t1), 1) == 0) break; + mpz_powm(t1, t1, two, prime); + i++; + } + if (i == 0) { + mpz_set(ret, R); + res = CRYPT_OK; + goto cleanup; + } + mpz_sub_ui(t1, M, i); + mpz_sub_ui(t1, t1, 1); + mpz_powm(t1, two, t1, prime); + /* t1 = 2 ^ (M - i - 1) */ + mpz_powm(t1, C, t1, prime); + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ + mpz_mul(C, t1, t1); + mpz_mod(C, C, prime); + /* C = (t1 * t1) mod prime */ + mpz_mul(R, R, t1); + mpz_mod(R, R, prime); + /* R = (R * t1) mod prime */ + mpz_mul(T, T, C); + mpz_mod(T, T, prime); + /* T = (T * C) mod prime */ + mpz_set_ui(M, i); + /* M = i */ + } + +cleanup: + mpz_clear(t1); mpz_clear(C); mpz_clear(Q); + mpz_clear(S); mpz_clear(Z); mpz_clear(M); + mpz_clear(T); mpz_clear(R); mpz_clear(two); + return res; +} + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + mpz_t tmp; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if (c != NULL) { + mpz_init(tmp); + mpz_divexact(tmp, a, b); + } + if (d != NULL) { + mpz_mod(d, a, b); + } + if (c != NULL) { + mpz_set(c, tmp); + mpz_clear(tmp); + } + return CRYPT_OK; +} + +static int div_2(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_divexact_ui(b, a, 2); + return CRYPT_OK; +} + +/* modi */ +static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + + *c = mpz_fdiv_ui(a, b); + return CRYPT_OK; +} + +/* gcd */ +static int gcd(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_gcd(c, a, b); + return CRYPT_OK; +} + +/* lcm */ +static int lcm(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_lcm(c, a, b); + return CRYPT_OK; +} + +static int addmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + mpz_add(d, a, b); + mpz_mod(d, d, c); + return CRYPT_OK; +} + +static int submod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + mpz_sub(d, a, b); + mpz_mod(d, d, c); + return CRYPT_OK; +} + +static int mulmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + mpz_mul(d, a, b); + mpz_mod(d, d, c); + return CRYPT_OK; +} + +static int sqrmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_mul(c, a, a); + mpz_mod(c, c, b); + return CRYPT_OK; +} + +/* invmod */ +static int invmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_invert(c, a, b); + return CRYPT_OK; +} + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + *b = (void *)1; + return CRYPT_OK; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + mpz_set_ui(a, 1); + return CRYPT_OK; +} + +/* reduce */ +static int montgomery_reduce(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + mpz_mod(a, a, b); + return CRYPT_OK; +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + LTC_UNUSED_PARAM(a); +} + +static int exptmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + mpz_powm(d, a, b, c); + return CRYPT_OK; +} + +static int isprime(void *a, int b, int *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b == 0) { + b = LTC_MILLER_RABIN_REPS; + } /* if */ + *c = mpz_probab_prime_p(a, b) > 0 ? LTC_MP_YES : LTC_MP_NO; + return CRYPT_OK; +} + +static int set_rand(void *a, int size) +{ + LTC_ARGCHK(a != NULL); + mpz_random(a, size); + return CRYPT_OK; +} + +const ltc_math_descriptor gmp_desc = { + "GNU MP", + sizeof(mp_limb_t) * CHAR_BIT - GMP_NAIL_BITS, + + &init, + &init_copy, + &deinit, + + &neg, + ©, + + &set_int, + &get_int, + &get_digit, + &get_digit_count, + &compare, + &compare_d, + &count_bits, + &count_lsb_bits, + &twoexpt, + + &read_radix, + &write_radix, + &unsigned_size, + &unsigned_write, + &unsigned_read, + + &add, + &addi, + &sub, + &subi, + &mul, + &muli, + &sqr, + &sqrtmod_prime, + ÷, + &div_2, + &modi, + &gcd, + &lcm, + + &mulmod, + &sqrmod, + &invmod, + + &montgomery_setup, + &montgomery_normalization, + &montgomery_reduce, + &montgomery_deinit, + + &exptmod, + &isprime, + +#ifdef LTC_MECC +#ifdef LTC_MECC_FP + <c_ecc_fp_mulmod, +#else + <c_ecc_mulmod, +#endif /* LTC_MECC_FP */ + <c_ecc_projective_add_point, + <c_ecc_projective_dbl_point, + <c_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + <c_ecc_fp_mul2add, +#else + <c_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#else + NULL, +#endif /* LTC_ECC_SHAMIR */ +#else + NULL, NULL, NULL, NULL, NULL, +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + &rsa_make_key, + &rsa_exptmod, +#else + NULL, NULL, +#endif + &addmod, + &submod, + + &set_rand, + +}; + + +#endif diff --git a/deps/libtomcrypt/src/math/ltm_desc.c b/deps/libtomcrypt/src/math/ltm_desc.c new file mode 100644 index 0000000..b49b30e --- /dev/null +++ b/deps/libtomcrypt/src/math/ltm_desc.c @@ -0,0 +1,560 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define DESC_DEF_ONLY +#include "tomcrypt_private.h" + +#ifdef LTM_DESC + +#include +#if !defined(PRIVATE_MP_WARRAY) && !defined(BN_MP_PRIME_IS_PRIME_C) +#include +#endif + +static const struct { + mp_err mpi_code; + int ltc_code; +} mpi_to_ltc_codes[] = { + { MP_OKAY , CRYPT_OK}, + { MP_MEM , CRYPT_MEM}, + { MP_VAL , CRYPT_INVALID_ARG}, +#if defined(MP_BUF) || defined(MP_USE_ENUMS) + { MP_ITER , CRYPT_INVALID_PACKET}, + { MP_BUF , CRYPT_BUFFER_OVERFLOW}, +#endif +}; + +/** + Convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) + @param err The error to convert + @return The equivalent LTC error code or CRYPT_ERROR if none found +*/ +static int mpi_to_ltc_error(mp_err err) +{ + size_t x; + + for (x = 0; x < sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0]); x++) { + if (err == mpi_to_ltc_codes[x].mpi_code) { + return mpi_to_ltc_codes[x].ltc_code; + } + } + return CRYPT_ERROR; +} + +static int init_mpi(void **a) +{ + LTC_ARGCHK(a != NULL); + + *a = XCALLOC(1, sizeof(mp_int)); + if (*a == NULL) { + return CRYPT_MEM; + } else { + return CRYPT_OK; + } +} + +static int init(void **a) +{ + int err; + + LTC_ARGCHK(a != NULL); + + if ((err = init_mpi(a)) != CRYPT_OK) { + return err; + } + if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) { + XFREE(*a); + } + return err; +} + +static void deinit(void *a) +{ + LTC_ARGCHKVD(a != NULL); + mp_clear(a); + XFREE(a); +} + +static int neg(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_neg(a, b)); +} + +static int copy(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_copy(a, b)); +} + +static int init_copy(void **a, void *b) +{ + int err; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + if ((err = init_mpi(a)) != CRYPT_OK) return err; + return mpi_to_ltc_error(mp_init_copy(*a, b)); +} + +/* ---- trivial ---- */ +static int set_int(void *a, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); +#ifdef BN_MP_SET_INT_C + return mpi_to_ltc_error(mp_set_int(a, b)); +#else + mp_set_u32(a, b); + return CRYPT_OK; +#endif +} + +static unsigned long get_int(void *a) +{ + LTC_ARGCHK(a != NULL); +#ifdef BN_MP_GET_INT_C + return mp_get_int(a); +#else + return mp_get_ul(a); +#endif +} + +static ltc_mp_digit get_digit(void *a, int n) +{ + mp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return (n >= A->used || n < 0) ? 0 : A->dp[n]; +} + +static int get_digit_count(void *a) +{ + mp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return A->used; +} + +static int compare(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + switch (mp_cmp(a, b)) { + case MP_LT: return LTC_MP_LT; + case MP_EQ: return LTC_MP_EQ; + case MP_GT: return LTC_MP_GT; + default: return 0; + } +} + +static int compare_d(void *a, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); + switch (mp_cmp_d(a, b)) { + case MP_LT: return LTC_MP_LT; + case MP_EQ: return LTC_MP_EQ; + case MP_GT: return LTC_MP_GT; + default: return 0; + } +} + +static int count_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return mp_count_bits(a); +} + +static int count_lsb_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return mp_cnt_lsb(a); +} + + +static int twoexpt(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + return mpi_to_ltc_error(mp_2expt(a, n)); +} + +/* ---- conversions ---- */ + +/* read ascii string */ +static int read_radix(void *a, const char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_read_radix(a, b, radix)); +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); +#ifdef BN_MP_TORADIX_C + return mpi_to_ltc_error(mp_toradix(a, b, radix)); +#else + return mpi_to_ltc_error(mp_to_radix(a, b, SIZE_MAX, NULL, radix)); +#endif +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + LTC_ARGCHK(a != NULL); +#ifdef BN_MP_UNSIGNED_BIN_SIZE_C + return mp_unsigned_bin_size(a); +#else + return (unsigned long)mp_ubin_size(a); +#endif +} + +/* store */ +static int unsigned_write(void *a, unsigned char *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); +#ifdef BN_MP_TO_UNSIGNED_BIN_C + return mpi_to_ltc_error(mp_to_unsigned_bin(a, b)); +#else + return mpi_to_ltc_error(mp_to_ubin(a, b, SIZE_MAX, NULL)); +#endif +} + +/* read */ +static int unsigned_read(void *a, unsigned char *b, unsigned long len) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); +#ifdef BN_MP_READ_UNSIGNED_BIN_C + return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len)); +#else + return mpi_to_ltc_error(mp_from_ubin(a, b, (size_t)len)); +#endif +} + +/* add */ +static int add(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_add(a, b, c)); +} + +static int addi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_add_d(a, b, c)); +} + +/* sub */ +static int sub(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sub(a, b, c)); +} + +static int subi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sub_d(a, b, c)); +} + +/* mul */ +static int mul(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_mul(a, b, c)); +} + +static int muli(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_mul_d(a, b, c)); +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_sqr(a, b)); +} + +/* sqrtmod_prime */ +static int sqrtmod_prime(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sqrtmod_prime(a, b, c)); +} + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_div(a, b, c, d)); +} + +static int div_2(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_div_2(a, b)); +} + +/* modi */ +static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) +{ + mp_digit tmp; + int err; + + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + + if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) { + return err; + } + *c = tmp; + return CRYPT_OK; +} + +/* gcd */ +static int gcd(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_gcd(a, b, c)); +} + +/* lcm */ +static int lcm(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_lcm(a, b, c)); +} + +static int addmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return mpi_to_ltc_error(mp_addmod(a,b,c,d)); +} + +static int submod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return mpi_to_ltc_error(mp_submod(a,b,c,d)); +} + +static int mulmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return mpi_to_ltc_error(mp_mulmod(a,b,c,d)); +} + +static int sqrmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_sqrmod(a,b,c)); +} + +/* invmod */ +static int invmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_invmod(a, b, c)); +} + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + int err; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + *b = XCALLOC(1, sizeof(mp_digit)); + if (*b == NULL) { + return CRYPT_MEM; + } + if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) { + XFREE(*b); + } + return err; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b)); +} + +/* reduce */ +static int montgomery_reduce(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c))); +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + XFREE(a); +} + +static int exptmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return mpi_to_ltc_error(mp_exptmod(a,b,c,d)); +} + +static int isprime(void *a, int b, int *c) +{ + int err; +#if defined(PRIVATE_MP_WARRAY) || defined(BN_MP_PRIME_IS_PRIME_C) + int res; +#else + bool res; +#endif + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + b = mp_prime_rabin_miller_trials(mp_count_bits(a)); + err = mpi_to_ltc_error(mp_prime_is_prime(a, b, &res)); + *c = res ? LTC_MP_YES : LTC_MP_NO; + return err; +} + +static int set_rand(void *a, int size) +{ + LTC_ARGCHK(a != NULL); + return mpi_to_ltc_error(mp_rand(a, size)); +} + +#ifndef MP_DIGIT_BIT +#define MP_DIGIT_BIT DIGIT_BIT +#endif + +const ltc_math_descriptor ltm_desc = { + + "LibTomMath", + (int)MP_DIGIT_BIT, + + &init, + &init_copy, + &deinit, + + &neg, + ©, + + &set_int, + &get_int, + &get_digit, + &get_digit_count, + &compare, + &compare_d, + &count_bits, + &count_lsb_bits, + &twoexpt, + + &read_radix, + &write_radix, + &unsigned_size, + &unsigned_write, + &unsigned_read, + + &add, + &addi, + &sub, + &subi, + &mul, + &muli, + &sqr, + &sqrtmod_prime, + ÷, + &div_2, + &modi, + &gcd, + &lcm, + + &mulmod, + &sqrmod, + &invmod, + + &montgomery_setup, + &montgomery_normalization, + &montgomery_reduce, + &montgomery_deinit, + + &exptmod, + &isprime, + +#ifdef LTC_MECC +#ifdef LTC_MECC_FP + <c_ecc_fp_mulmod, +#else + <c_ecc_mulmod, +#endif + <c_ecc_projective_add_point, + <c_ecc_projective_dbl_point, + <c_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + <c_ecc_fp_mul2add, +#else + <c_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#else + NULL, +#endif /* LTC_ECC_SHAMIR */ +#else + NULL, NULL, NULL, NULL, NULL, +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + &rsa_make_key, + &rsa_exptmod, +#else + NULL, NULL, +#endif + &addmod, + &submod, + + &set_rand, + +}; + + +#endif diff --git a/deps/libtomcrypt/src/math/multi.c b/deps/libtomcrypt/src/math/multi.c new file mode 100644 index 0000000..a88497b --- /dev/null +++ b/deps/libtomcrypt/src/math/multi.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_MPI +#include + +int ltc_init_multi(void **a, ...) +{ + void **cur = a; + int np = 0; + va_list args; + + va_start(args, a); + while (cur != NULL) { + if (mp_init(cur) != CRYPT_OK) { + /* failed */ + va_list clean_list; + + va_start(clean_list, a); + cur = a; + while (np--) { + mp_clear(*cur); + cur = va_arg(clean_list, void**); + } + va_end(clean_list); + va_end(args); + return CRYPT_MEM; + } + ++np; + cur = va_arg(args, void**); + } + va_end(args); + return CRYPT_OK; +} + +void ltc_deinit_multi(void *a, ...) +{ + void *cur = a; + va_list args; + + va_start(args, a); + while (cur != NULL) { + mp_clear(cur); + cur = va_arg(args, void *); + } + va_end(args); +} + +void ltc_cleanup_multi(void **a, ...) +{ + void **cur = a; + va_list args; + + va_start(args, a); + while (cur != NULL) { + if (*cur != NULL) { + mp_clear(*cur); + *cur = NULL; + } + cur = va_arg(args, void**); + } + va_end(args); +} + +#endif diff --git a/deps/libtomcrypt/src/math/radix_to_bin.c b/deps/libtomcrypt/src/math/radix_to_bin.c new file mode 100644 index 0000000..5c17f0d --- /dev/null +++ b/deps/libtomcrypt/src/math/radix_to_bin.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file radix_to_bin.c + Convert data from a specific radix to binary. + Steffen Jaeckel +*/ + +/** + Convert data from a specific radix to binary + + The default MPI descriptors #ltm_desc, #tfm_desc and #gmp_desc + have the following restrictions on parameters: + + \p in - NUL-terminated char buffer + + \p radix - 2..64 + + @param in The input + @param radix The radix of the input + @param out The output buffer + @param len [in/out] The length of the output buffer + + @return CRYPT_OK on success. +*/ +int radix_to_bin(const void *in, int radix, void *out, unsigned long *len) +{ + unsigned long l; + void* mpi; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(len != NULL); + + if ((err = mp_init(&mpi)) != CRYPT_OK) return err; + if ((err = mp_read_radix(mpi, in, radix)) != CRYPT_OK) goto LBL_ERR; + + if ((l = mp_unsigned_bin_size(mpi)) > *len) { + *len = l; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + *len = l; + + if ((err = mp_to_unsigned_bin(mpi, out)) != CRYPT_OK) goto LBL_ERR; + +LBL_ERR: + mp_clear(mpi); + return err; +} diff --git a/deps/libtomcrypt/src/math/rand_bn.c b/deps/libtomcrypt/src/math/rand_bn.c new file mode 100644 index 0000000..03a81b7 --- /dev/null +++ b/deps/libtomcrypt/src/math/rand_bn.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#if defined(LTC_MDSA) || defined(LTC_MECC) +/** + Generate a random number N with given bitlength (note: MSB can be 0) +*/ + +int rand_bn_bits(void *N, int bits, prng_state *prng, int wprng) +{ + int res, bytes; + unsigned char *buf, mask; + + LTC_ARGCHK(N != NULL); + LTC_ARGCHK(bits > 1); + + /* check PRNG */ + if ((res = prng_is_valid(wprng)) != CRYPT_OK) return res; + + bytes = (bits+7) >> 3; + mask = 0xff >> (bits % 8 == 0 ? 0 : 8 - bits % 8); + + /* allocate buffer */ + if ((buf = XCALLOC(1, bytes)) == NULL) return CRYPT_MEM; + + /* generate random bytes */ + if (prng_descriptor[wprng].read(buf, bytes, prng) != (unsigned long)bytes) { + res = CRYPT_ERROR_READPRNG; + goto cleanup; + } + /* mask bits */ + buf[0] &= mask; + /* load value */ + if ((res = mp_read_unsigned_bin(N, buf, bytes)) != CRYPT_OK) goto cleanup; + + res = CRYPT_OK; + +cleanup: +#ifdef LTC_CLEAN_STACK + zeromem(buf, bytes); +#endif + XFREE(buf); + return res; +} + +/** + Generate a random number N in a range: 1 <= N < limit +*/ +int rand_bn_upto(void *N, void *limit, prng_state *prng, int wprng) +{ + int res, bits; + + LTC_ARGCHK(N != NULL); + LTC_ARGCHK(limit != NULL); + + bits = mp_count_bits(limit); + do { + res = rand_bn_bits(N, bits, prng, wprng); + if (res != CRYPT_OK) return res; + } while (mp_cmp_d(N, 0) != LTC_MP_GT || mp_cmp(N, limit) != LTC_MP_LT); + + return CRYPT_OK; +} +#endif diff --git a/deps/libtomcrypt/src/math/rand_prime.c b/deps/libtomcrypt/src/math/rand_prime.c new file mode 100644 index 0000000..498912c --- /dev/null +++ b/deps/libtomcrypt/src/math/rand_prime.c @@ -0,0 +1,78 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#if defined(LTC_MRSA) || (!defined(LTC_NO_MATH) && !defined(LTC_NO_PRNGS)) + +/** + @file rand_prime.c + Generate a random prime, Tom St Denis +*/ + +#define USE_BBS 1 + +int rand_prime(void *N, long len, prng_state *prng, int wprng) +{ + int err, res, type; + unsigned char *buf; + + LTC_ARGCHK(N != NULL); + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } else { + type = 0; + } + + /* allow sizes between 2 and 512 bytes for a prime size */ + if (len < 2 || len > 512) { + return CRYPT_INVALID_PRIME_SIZE; + } + + /* valid PRNG? Better be! */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + /* allocate buffer to work with */ + buf = XCALLOC(1, len); + if (buf == NULL) { + return CRYPT_MEM; + } + + do { + /* generate value */ + if (prng_descriptor[wprng].read(buf, len, prng) != (unsigned long)len) { + XFREE(buf); + return CRYPT_ERROR_READPRNG; + } + + /* munge bits */ + buf[0] |= 0x80 | 0x40; + buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* load value */ + if ((err = mp_read_unsigned_bin(N, buf, len)) != CRYPT_OK) { + XFREE(buf); + return err; + } + + /* test */ + if ((err = mp_prime_is_prime(N, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { + XFREE(buf); + return err; + } + } while (res == LTC_MP_NO); + +#ifdef LTC_CLEAN_STACK + zeromem(buf, len); +#endif + + XFREE(buf); + return CRYPT_OK; +} + +#endif /* LTC_NO_MATH */ + diff --git a/deps/libtomcrypt/src/math/tfm_desc.c b/deps/libtomcrypt/src/math/tfm_desc.c new file mode 100644 index 0000000..cee753a --- /dev/null +++ b/deps/libtomcrypt/src/math/tfm_desc.c @@ -0,0 +1,857 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define DESC_DEF_ONLY +#include "tomcrypt_private.h" + +#ifdef TFM_DESC + +#include + +static const struct { + int tfm_code, ltc_code; +} tfm_to_ltc_codes[] = { + { FP_OKAY , CRYPT_OK}, + { FP_MEM , CRYPT_MEM}, + { FP_VAL , CRYPT_INVALID_ARG}, +}; + +/** + Convert a tfm error to a LTC error (Possibly the most powerful function ever! Oh wait... no) + @param err The error to convert + @return The equivalent LTC error code or CRYPT_ERROR if none found +*/ +static int tfm_to_ltc_error(int err) +{ + int x; + + for (x = 0; x < (int)(sizeof(tfm_to_ltc_codes)/sizeof(tfm_to_ltc_codes[0])); x++) { + if (err == tfm_to_ltc_codes[x].tfm_code) { + return tfm_to_ltc_codes[x].ltc_code; + } + } + return CRYPT_ERROR; +} + +static int init(void **a) +{ + LTC_ARGCHK(a != NULL); + + *a = XCALLOC(1, sizeof(fp_int)); + if (*a == NULL) { + return CRYPT_MEM; + } + fp_init(*a); + return CRYPT_OK; +} + +static void deinit(void *a) +{ + LTC_ARGCHKVD(a != NULL); + XFREE(a); +} + +static int neg(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_neg(((fp_int*)a), ((fp_int*)b)); + return CRYPT_OK; +} + +static int copy(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_copy(a, b); + return CRYPT_OK; +} + +static int init_copy(void **a, void *b) +{ + if (init(a) != CRYPT_OK) { + return CRYPT_MEM; + } + return copy(b, *a); +} + +/* ---- trivial ---- */ +static int set_int(void *a, ltc_mp_digit b) +{ + LTC_ARGCHK(a != NULL); + fp_set(a, b); + return CRYPT_OK; +} + +static unsigned long get_int(void *a) +{ + fp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return A->used > 0 ? A->dp[0] : 0; +} + +static ltc_mp_digit get_digit(void *a, int n) +{ + fp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return (n >= A->used || n < 0) ? 0 : A->dp[n]; +} + +static int get_digit_count(void *a) +{ + fp_int *A; + LTC_ARGCHK(a != NULL); + A = a; + return A->used; +} + +static int compare(void *a, void *b) +{ + int ret; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + ret = fp_cmp(a, b); + switch (ret) { + case FP_LT: return LTC_MP_LT; + case FP_EQ: return LTC_MP_EQ; + case FP_GT: return LTC_MP_GT; + } + return 0; +} + +static int compare_d(void *a, ltc_mp_digit b) +{ + int ret; + LTC_ARGCHK(a != NULL); + ret = fp_cmp_d(a, b); + switch (ret) { + case FP_LT: return LTC_MP_LT; + case FP_EQ: return LTC_MP_EQ; + case FP_GT: return LTC_MP_GT; + } + return 0; +} + +static int count_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return fp_count_bits(a); +} + +static int count_lsb_bits(void *a) +{ + LTC_ARGCHK(a != NULL); + return fp_cnt_lsb(a); +} + +static int twoexpt(void *a, int n) +{ + LTC_ARGCHK(a != NULL); + fp_2expt(a, n); + return CRYPT_OK; +} + +/* ---- conversions ---- */ + +/* read ascii string */ +static int read_radix(void *a, const char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return tfm_to_ltc_error(fp_read_radix(a, (char *)b, radix)); +} + +/* write one */ +static int write_radix(void *a, char *b, int radix) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return tfm_to_ltc_error(fp_toradix(a, b, radix)); +} + +/* get size as unsigned char string */ +static unsigned long unsigned_size(void *a) +{ + LTC_ARGCHK(a != NULL); + return fp_unsigned_bin_size(a); +} + +/* store */ +static int unsigned_write(void *a, unsigned char *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_to_unsigned_bin(a, b); + return CRYPT_OK; +} + +/* read */ +static int unsigned_read(void *a, unsigned char *b, unsigned long len) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_read_unsigned_bin(a, b, len); + return CRYPT_OK; +} + +/* add */ +static int add(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + fp_add(a, b, c); + return CRYPT_OK; +} + +static int addi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + fp_add_d(a, b, c); + return CRYPT_OK; +} + +/* sub */ +static int sub(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + fp_sub(a, b, c); + return CRYPT_OK; +} + +static int subi(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + fp_sub_d(a, b, c); + return CRYPT_OK; +} + +/* mul */ +static int mul(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + fp_mul(a, b, c); + return CRYPT_OK; +} + +static int muli(void *a, ltc_mp_digit b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + fp_mul_d(a, b, c); + return CRYPT_OK; +} + +/* sqr */ +static int sqr(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_sqr(a, b); + return CRYPT_OK; +} + +/* sqrtmod_prime - NOT SUPPORTED */ + +/* div */ +static int divide(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + return tfm_to_ltc_error(fp_div(a, b, c, d)); +} + +static int div_2(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_div_2(a, b); + return CRYPT_OK; +} + +/* modi */ +static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c) +{ + fp_digit tmp; + int err; + + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + + if ((err = tfm_to_ltc_error(fp_mod_d(a, b, &tmp))) != CRYPT_OK) { + return err; + } + *c = tmp; + return CRYPT_OK; +} + +/* gcd */ +static int gcd(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + fp_gcd(a, b, c); + return CRYPT_OK; +} + +/* lcm */ +static int lcm(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + fp_lcm(a, b, c); + return CRYPT_OK; +} + +static int addmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return tfm_to_ltc_error(fp_addmod(a,b,c,d)); +} + +static int submod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return tfm_to_ltc_error(fp_submod(a,b,c,d)); +} + +static int mulmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return tfm_to_ltc_error(fp_mulmod(a,b,c,d)); +} + +static int sqrmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return tfm_to_ltc_error(fp_sqrmod(a,b,c)); +} + +/* invmod */ +static int invmod(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + return tfm_to_ltc_error(fp_invmod(a, b, c)); +} + +/* setup */ +static int montgomery_setup(void *a, void **b) +{ + int err; + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + *b = XCALLOC(1, sizeof(fp_digit)); + if (*b == NULL) { + return CRYPT_MEM; + } + if ((err = tfm_to_ltc_error(fp_montgomery_setup(a, (fp_digit *)*b))) != CRYPT_OK) { + XFREE(*b); + } + return err; +} + +/* get normalization value */ +static int montgomery_normalization(void *a, void *b) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + fp_montgomery_calc_normalization(a, b); + return CRYPT_OK; +} + +/* reduce */ +static int montgomery_reduce(void *a, void *b, void *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + fp_montgomery_reduce(a, b, *((fp_digit *)c)); + return CRYPT_OK; +} + +/* clean up */ +static void montgomery_deinit(void *a) +{ + XFREE(a); +} + +static int exptmod(void *a, void *b, void *c, void *d) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(c != NULL); + LTC_ARGCHK(d != NULL); + return tfm_to_ltc_error(fp_exptmod(a,b,c,d)); +} + +static int isprime(void *a, int b, int *c) +{ + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(c != NULL); + if (b == 0) { + b = LTC_MILLER_RABIN_REPS; + } /* if */ + *c = (fp_isprime_ex(a, b) == FP_YES) ? LTC_MP_YES : LTC_MP_NO; + return CRYPT_OK; +} + +#if defined(LTC_MECC) && defined(LTC_MECC_ACCEL) + +static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp) +{ + fp_int t1, t2; + fp_digit mp; + int err, inf; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(Mp != NULL); + + mp = *((fp_digit*)Mp); + + fp_init(&t1); + fp_init(&t2); + + if (P != R) { + fp_copy(P->x, R->x); + fp_copy(P->y, R->y); + fp_copy(P->z, R->z); + } + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* if P is point at infinity >> Result = point at infinity */ + ltc_mp.set_int(R->x, 1); + ltc_mp.set_int(R->y, 1); + ltc_mp.set_int(R->z, 0); + return CRYPT_OK; + } + + /* t1 = Z * Z */ + fp_sqr(R->z, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* Z = Y * Z */ + fp_mul(R->z, R->y, R->z); + fp_montgomery_reduce(R->z, modulus, mp); + /* Z = 2Z */ + fp_add(R->z, R->z, R->z); + if (fp_cmp(R->z, modulus) != FP_LT) { + fp_sub(R->z, modulus, R->z); + } + + if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ + /* T2 = X - T1 */ + fp_sub(R->x, &t1, &t2); + if (fp_cmp_d(&t2, 0) == LTC_MP_LT) { + fp_add(&t2, modulus, &t2); + } + /* T1 = X + T1 */ + fp_add(&t1, R->x, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T2 = T1 * T2 */ + fp_mul(&t1, &t2, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = 2T2 */ + fp_add(&t2, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + } + else { + /* T2 = T1 * T1 */ + fp_sqr(&t1, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T2 * a */ + fp_mul(&t2, ma, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* T2 = X * X */ + fp_sqr(R->x, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = T1 + T2 */ + fp_add(&t1, &t2, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + } + + /* Y = 2Y */ + fp_add(R->y, R->y, R->y); + if (fp_cmp(R->y, modulus) != FP_LT) { + fp_sub(R->y, modulus, R->y); + } + /* Y = Y * Y */ + fp_sqr(R->y, R->y); + fp_montgomery_reduce(R->y, modulus, mp); + /* T2 = Y * Y */ + fp_sqr(R->y, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T2 = T2/2 */ + if (fp_isodd(&t2)) { + fp_add(&t2, modulus, &t2); + } + fp_div_2(&t2, &t2); + /* Y = Y * X */ + fp_mul(R->y, R->x, R->y); + fp_montgomery_reduce(R->y, modulus, mp); + + /* X = T1 * T1 */ + fp_sqr(&t1, R->x); + fp_montgomery_reduce(R->x, modulus, mp); + /* X = X - Y */ + fp_sub(R->x, R->y, R->x); + if (fp_cmp_d(R->x, 0) == FP_LT) { + fp_add(R->x, modulus, R->x); + } + /* X = X - Y */ + fp_sub(R->x, R->y, R->x); + if (fp_cmp_d(R->x, 0) == FP_LT) { + fp_add(R->x, modulus, R->x); + } + + /* Y = Y - X */ + fp_sub(R->y, R->x, R->y); + if (fp_cmp_d(R->y, 0) == FP_LT) { + fp_add(R->y, modulus, R->y); + } + /* Y = Y * T1 */ + fp_mul(R->y, &t1, R->y); + fp_montgomery_reduce(R->y, modulus, mp); + /* Y = Y - T2 */ + fp_sub(R->y, &t2, R->y); + if (fp_cmp_d(R->y, 0) == FP_LT) { + fp_add(R->y, modulus, R->y); + } + + return CRYPT_OK; +} + +/** + Add two ECC points + @param P The point to add + @param Q The point to add + @param R [out] The destination of the double + @param modulus The modulus of the field the ECC curve is in + @param Mp The "b" value from montgomery_setup() + @return CRYPT_OK on success +*/ +static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp) +{ + fp_int t1, t2, x, y, z; + fp_digit mp; + int err, inf; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(Q != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(Mp != NULL); + + mp = *((fp_digit*)Mp); + + fp_init(&t1); + fp_init(&t2); + fp_init(&x); + fp_init(&y); + fp_init(&z); + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* P is point at infinity >> Result = Q */ + ltc_mp.copy(Q->x, R->x); + ltc_mp.copy(Q->y, R->y); + ltc_mp.copy(Q->z, R->z); + return CRYPT_OK; + } + + if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* Q is point at infinity >> Result = P */ + ltc_mp.copy(P->x, R->x); + ltc_mp.copy(P->y, R->y); + ltc_mp.copy(P->z, R->z); + return CRYPT_OK; + } + + /* should we dbl instead? */ + fp_sub(modulus, Q->y, &t1); + if ( (fp_cmp(P->x, Q->x) == FP_EQ) && + (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) && + (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) { + return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp); + } + + fp_copy(P->x, &x); + fp_copy(P->y, &y); + fp_copy(P->z, &z); + + /* if Z is one then these are no-operations */ + if (Q->z != NULL) { + /* T1 = Z' * Z' */ + fp_sqr(Q->z, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* X = X * T1 */ + fp_mul(&t1, &x, &x); + fp_montgomery_reduce(&x, modulus, mp); + /* T1 = Z' * T1 */ + fp_mul(Q->z, &t1, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* Y = Y * T1 */ + fp_mul(&t1, &y, &y); + fp_montgomery_reduce(&y, modulus, mp); + } + + /* T1 = Z*Z */ + fp_sqr(&z, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* T2 = X' * T1 */ + fp_mul(Q->x, &t1, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = Z * T1 */ + fp_mul(&z, &t1, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* T1 = Y' * T1 */ + fp_mul(Q->y, &t1, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + + /* Y = Y - T1 */ + fp_sub(&y, &t1, &y); + if (fp_cmp_d(&y, 0) == FP_LT) { + fp_add(&y, modulus, &y); + } + /* T1 = 2T1 */ + fp_add(&t1, &t1, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* T1 = Y + T1 */ + fp_add(&t1, &y, &t1); + if (fp_cmp(&t1, modulus) != FP_LT) { + fp_sub(&t1, modulus, &t1); + } + /* X = X - T2 */ + fp_sub(&x, &t2, &x); + if (fp_cmp_d(&x, 0) == FP_LT) { + fp_add(&x, modulus, &x); + } + /* T2 = 2T2 */ + fp_add(&t2, &t2, &t2); + if (fp_cmp(&t2, modulus) != FP_LT) { + fp_sub(&t2, modulus, &t2); + } + /* T2 = X + T2 */ + fp_add(&t2, &x, &t2); + if (fp_cmp(&t2, modulus) != FP_LT) { + fp_sub(&t2, modulus, &t2); + } + + /* if Z' != 1 */ + if (Q->z != NULL) { + /* Z = Z * Z' */ + fp_mul(&z, Q->z, &z); + fp_montgomery_reduce(&z, modulus, mp); + } + + /* Z = Z * X */ + fp_mul(&z, &x, &z); + fp_montgomery_reduce(&z, modulus, mp); + + /* T1 = T1 * X */ + fp_mul(&t1, &x, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + /* X = X * X */ + fp_sqr(&x, &x); + fp_montgomery_reduce(&x, modulus, mp); + /* T2 = T2 * x */ + fp_mul(&t2, &x, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T1 * X */ + fp_mul(&t1, &x, &t1); + fp_montgomery_reduce(&t1, modulus, mp); + + /* X = Y*Y */ + fp_sqr(&y, &x); + fp_montgomery_reduce(&x, modulus, mp); + /* X = X - T2 */ + fp_sub(&x, &t2, &x); + if (fp_cmp_d(&x, 0) == FP_LT) { + fp_add(&x, modulus, &x); + } + + /* T2 = T2 - X */ + fp_sub(&t2, &x, &t2); + if (fp_cmp_d(&t2, 0) == FP_LT) { + fp_add(&t2, modulus, &t2); + } + /* T2 = T2 - X */ + fp_sub(&t2, &x, &t2); + if (fp_cmp_d(&t2, 0) == FP_LT) { + fp_add(&t2, modulus, &t2); + } + /* T2 = T2 * Y */ + fp_mul(&t2, &y, &t2); + fp_montgomery_reduce(&t2, modulus, mp); + /* Y = T2 - T1 */ + fp_sub(&t2, &t1, &y); + if (fp_cmp_d(&y, 0) == FP_LT) { + fp_add(&y, modulus, &y); + } + /* Y = Y/2 */ + if (fp_isodd(&y)) { + fp_add(&y, modulus, &y); + } + fp_div_2(&y, &y); + + fp_copy(&x, R->x); + fp_copy(&y, R->y); + fp_copy(&z, R->z); + + return CRYPT_OK; +} + + +#endif + +static int set_rand(void *a, int size) +{ + LTC_ARGCHK(a != NULL); + fp_rand(a, size); + return CRYPT_OK; +} + +const ltc_math_descriptor tfm_desc = { + + "TomsFastMath", + (int)DIGIT_BIT, + + &init, + &init_copy, + &deinit, + + &neg, + ©, + + &set_int, + &get_int, + &get_digit, + &get_digit_count, + &compare, + &compare_d, + &count_bits, + &count_lsb_bits, + &twoexpt, + + &read_radix, + &write_radix, + &unsigned_size, + &unsigned_write, + &unsigned_read, + + &add, + &addi, + &sub, + &subi, + &mul, + &muli, + &sqr, + NULL, /* TODO: &sqrtmod_prime */ + ÷, + &div_2, + &modi, + &gcd, + &lcm, + + &mulmod, + &sqrmod, + &invmod, + + &montgomery_setup, + &montgomery_normalization, + &montgomery_reduce, + &montgomery_deinit, + + &exptmod, + &isprime, + +#ifdef LTC_MECC +#ifdef LTC_MECC_FP + <c_ecc_fp_mulmod, +#else + <c_ecc_mulmod, +#endif /* LTC_MECC_FP */ +#ifdef LTC_MECC_ACCEL + &tfm_ecc_projective_add_point, + &tfm_ecc_projective_dbl_point, +#else + <c_ecc_projective_add_point, + <c_ecc_projective_dbl_point, +#endif /* LTC_MECC_ACCEL */ + <c_ecc_map, +#ifdef LTC_ECC_SHAMIR +#ifdef LTC_MECC_FP + <c_ecc_fp_mul2add, +#else + <c_ecc_mul2add, +#endif /* LTC_MECC_FP */ +#else + NULL, +#endif /* LTC_ECC_SHAMIR */ +#else + NULL, NULL, NULL, NULL, NULL, +#endif /* LTC_MECC */ + +#ifdef LTC_MRSA + &rsa_make_key, + &rsa_exptmod, +#else + NULL, NULL, +#endif + &addmod, + &submod, + + set_rand, + +}; + + +#endif diff --git a/deps/libtomcrypt/src/misc/adler32.c b/deps/libtomcrypt/src/misc/adler32.c new file mode 100644 index 0000000..8c2953d --- /dev/null +++ b/deps/libtomcrypt/src/misc/adler32.c @@ -0,0 +1,123 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file adler32.c + Adler-32 checksum algorithm + Written and placed in the public domain by Wei Dai + Adapted for libtomcrypt by Steffen Jaeckel +*/ +#ifdef LTC_ADLER32 + +static const unsigned long s_adler32_base = 65521; + +void adler32_init(adler32_state *ctx) +{ + LTC_ARGCHKVD(ctx != NULL); + ctx->s[0] = 1; + ctx->s[1] = 0; +} + +void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length) +{ + unsigned long s1, s2; + + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(input != NULL); + s1 = ctx->s[0]; + s2 = ctx->s[1]; + + if (length % 8 != 0) { + do { + s1 += *input++; + s2 += s1; + length--; + } while (length % 8 != 0); + + if (s1 >= s_adler32_base) { + s1 -= s_adler32_base; + } + s2 %= s_adler32_base; + } + + while (length > 0) { + s1 += input[0]; + s2 += s1; + s1 += input[1]; + s2 += s1; + s1 += input[2]; + s2 += s1; + s1 += input[3]; + s2 += s1; + s1 += input[4]; + s2 += s1; + s1 += input[5]; + s2 += s1; + s1 += input[6]; + s2 += s1; + s1 += input[7]; + s2 += s1; + + length -= 8; + input += 8; + + if (s1 >= s_adler32_base) { + s1 -= s_adler32_base; + } + s2 %= s_adler32_base; + } + + LTC_ARGCHKVD(s1 < s_adler32_base); + LTC_ARGCHKVD(s2 < s_adler32_base); + + ctx->s[0] = (unsigned short)s1; + ctx->s[1] = (unsigned short)s2; +} + +void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size) +{ + unsigned char* h; + + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(hash != NULL); + + h = hash; + + switch (size) { + default: + h[3] = ctx->s[0] & 0x0ff; + /* FALLTHROUGH */ + case 3: + h[2] = (ctx->s[0] >> 8) & 0x0ff; + /* FALLTHROUGH */ + case 2: + h[1] = ctx->s[1] & 0x0ff; + /* FALLTHROUGH */ + case 1: + h[0] = (ctx->s[1] >> 8) & 0x0ff; + /* FALLTHROUGH */ + case 0: + ; + } +} + +int adler32_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + const void* in = "libtomcrypt"; + const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba }; + unsigned char out[4]; + adler32_state ctx; + adler32_init(&ctx); + adler32_update(&ctx, in, XSTRLEN(in)); + adler32_finish(&ctx, out, 4); + if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} +#endif diff --git a/deps/libtomcrypt/src/misc/base16/base16_decode.c b/deps/libtomcrypt/src/misc/base16/base16_decode.c new file mode 100644 index 0000000..8ebc9ea --- /dev/null +++ b/deps/libtomcrypt/src/misc/base16/base16_decode.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file base16_decode.c + Base16/Hex decode a string. + Based on https://stackoverflow.com/a/23898449 + Adapted for libtomcrypt by Steffen Jaeckel +*/ + +#ifdef LTC_BASE16 + +/** + Base16 decode a string + @param in The Base16 string to decode + @param inlen The length of the Base16 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base16_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long pos, out_len; + unsigned char idx0, idx1; + char in0, in1; + + const unsigned char hashmap[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ + 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 89:;<=>? */ + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* @ABCDEFG */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* HIJKLMNO */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* PQRSTUVW */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* XYZ[\]^_ */ + 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, /* `abcdefg */ + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((inlen % 2) == 1) return CRYPT_INVALID_PACKET; + out_len = *outlen * 2; + for (pos = 0; ((pos + 1 < out_len) && (pos + 1 < inlen)); pos += 2) { + in0 = in[pos + 0]; + in1 = in[pos + 1]; + + if ((in0 < '0') || (in0 > 'g')) return CRYPT_INVALID_PACKET; + if ((in1 < '0') || (in1 > 'g')) return CRYPT_INVALID_PACKET; + + idx0 = (unsigned char) (in0 & 0x1F) ^ 0x10; + idx1 = (unsigned char) (in1 & 0x1F) ^ 0x10; + + if (hashmap[idx0] == 0xff) return CRYPT_INVALID_PACKET; + if (hashmap[idx1] == 0xff) return CRYPT_INVALID_PACKET; + + out[pos / 2] = (unsigned char) (hashmap[idx0] << 4) | hashmap[idx1]; + } + *outlen = pos / 2; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/base16/base16_encode.c b/deps/libtomcrypt/src/misc/base16/base16_encode.c new file mode 100644 index 0000000..649a4d8 --- /dev/null +++ b/deps/libtomcrypt/src/misc/base16/base16_encode.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file base16_encode.c + Base16/Hex encode a string, Steffen Jaeckel +*/ + +#ifdef LTC_BASE16 + +/** + Base16 encode a buffer + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the Base16 encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @param options Output 'a-f' on 0 and 'A-F' otherwise. + @return CRYPT_OK if successful +*/ +int base16_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int options) +{ + unsigned long i, x; + const char *alphabet; + const char *alphabets[2] = { + "0123456789abcdef", + "0123456789ABCDEF", + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* check the sizes */ + x = inlen * 2 + 1; + + if (x < inlen) return CRYPT_OVERFLOW; + + if (*outlen < x) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + x--; + *outlen = x; /* returning the length without terminating NUL */ + + if (options == 0) { + alphabet = alphabets[0]; + } else { + alphabet = alphabets[1]; + } + + for (i = 0; i < x; i += 2) { + out[i] = alphabet[(in[i/2] >> 4) & 0x0f]; + out[i+1] = alphabet[in[i/2] & 0x0f]; + } + out[x] = '\0'; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/base32/base32_decode.c b/deps/libtomcrypt/src/misc/base32/base32_decode.c new file mode 100644 index 0000000..fc98cce --- /dev/null +++ b/deps/libtomcrypt/src/misc/base32/base32_decode.c @@ -0,0 +1,111 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BASE32 + +/** + Base32 decode a buffer + @param in The Base32 data to decode + @param inlen The length of the Base32 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD + @return CRYPT_OK if successful +*/ +int base32_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + base32_alphabet id) +{ + unsigned long x; + int y = 0; + ulong64 t = 0; + char c; + const unsigned char *map; + const unsigned char tables[4][43] = { + { /* id = BASE32_RFC4648 : ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 */ + 99/*0*/,99/*1*/,26/*2*/,27/*3*/,28/*4*/,29/*5*/,30/*6*/,31/*7*/,99/*8*/,99/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, 7/*H*/, 8/*I*/, 9/*J*/,10/*K*/,11/*L*/,12/*M*/, + 13/*N*/,14/*O*/,15/*P*/,16/*Q*/,17/*R*/,18/*S*/,19/*T*/,20/*U*/,21/*V*/,22/*W*/,23/*X*/,24/*Y*/,25/*Z*/ + }, + { /* id = BASE32_BASE32HEX : 0123456789ABCDEFGHIJKLMNOPQRSTUV */ + 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/,18/*I*/,19/*J*/,20/*K*/,21/*L*/,22/*M*/, + 23/*N*/,24/*O*/,25/*P*/,26/*Q*/,27/*R*/,28/*S*/,29/*T*/,30/*U*/,31/*V*/,99/*W*/,99/*X*/,99/*Y*/,99/*Z*/ + }, + { /* id = BASE32_ZBASE32 : YBNDRFG8EJKMCPQXOT1UWISZA345H769 */ + 99/*0*/,18/*1*/,99/*2*/,25/*3*/,26/*4*/,27/*5*/,30/*6*/,29/*7*/, 7/*8*/,31/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 24/*A*/, 1/*B*/,12/*C*/, 3/*D*/, 8/*E*/, 5/*F*/, 6/*G*/,28/*H*/,21/*I*/, 9/*J*/,10/*K*/,99/*L*/,11/*M*/, + 2/*N*/,16/*O*/,13/*P*/,14/*Q*/, 4/*R*/,22/*S*/,17/*T*/,19/*U*/,99/*V*/,20/*W*/,15/*X*/, 0/*Y*/,23/*Z*/ + }, + { /* id = BASE32_CROCKFORD : 0123456789ABCDEFGHJKMNPQRSTVWXYZ + O=>0 + IL=>1 */ + 0/*0*/, 1/*1*/, 2/*2*/, 3/*3*/, 4/*4*/, 5/*5*/, 6/*6*/, 7/*7*/, 8/*8*/, 9/*9*/, + 99/*:*/,99/*;*/,99/*<*/,99/*=*/,99/*>*/,99/*?*/,99/*@*/, + 10/*A*/,11/*B*/,12/*C*/,13/*D*/,14/*E*/,15/*F*/,16/*G*/,17/*H*/, 1/*I*/,18/*J*/,19/*K*/, 1/*L*/,20/*M*/, + 21/*N*/, 0/*O*/,22/*P*/,23/*Q*/,24/*R*/,25/*S*/,26/*T*/,99/*U*/,27/*V*/,28/*W*/,29/*X*/,30/*Y*/,31/*Z*/ + } + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(id >= BASE32_RFC4648); + LTC_ARGCHK(id <= BASE32_CROCKFORD); + + /* ignore all trailing = */ + while (inlen > 0 && in[inlen-1] == '=') inlen--; + + /* no input, nothing to do */ + if (inlen == 0) { + *outlen = 0; + return CRYPT_OK; + } + + /* check the size of output buffer */ + x = (inlen * 5) / 8; + if (*outlen < x) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = x; + + /* check input data length */ + x = inlen % 8; + if (x == 1 || x == 3 || x == 6) { + return CRYPT_INVALID_PACKET; + } + + map = tables[id]; + for (x = 0; x < inlen; x++) { + c = in[x]; + /* convert to upper case */ + if ((c >= 'a') && (c <= 'z')) c -= 32; + if (c < '0' || c > 'Z' || map[c-'0'] > 31) { + return CRYPT_INVALID_PACKET; + } + t = (t<<5) | map[c-'0']; + if (++y == 8) { + *out++ = (unsigned char)((t>>32) & 255); + *out++ = (unsigned char)((t>>24) & 255); + *out++ = (unsigned char)((t>>16) & 255); + *out++ = (unsigned char)((t>> 8) & 255); + *out++ = (unsigned char)( t & 255); + y = 0; + t = 0; + } + } + if (y > 0) { + t = t << (5 * (8 - y)); + if (y >= 2) *out++ = (unsigned char)((t>>32) & 255); + if (y >= 4) *out++ = (unsigned char)((t>>24) & 255); + if (y >= 5) *out++ = (unsigned char)((t>>16) & 255); + if (y >= 7) *out++ = (unsigned char)((t>> 8) & 255); + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/base32/base32_encode.c b/deps/libtomcrypt/src/misc/base32/base32_encode.c new file mode 100644 index 0000000..29519bf --- /dev/null +++ b/deps/libtomcrypt/src/misc/base32/base32_encode.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_BASE32 + +/** + Base32 encode a buffer + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the Base32 encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @param id Alphabet to use BASE32_RFC4648, BASE32_BASE32HEX, BASE32_ZBASE32 or BASE32_CROCKFORD + @return CRYPT_OK if successful +*/ +int base32_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + base32_alphabet id) +{ + unsigned long i, x; + const char *codes; + const char *alphabet[4] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", /* id = BASE32_RFC4648 */ + "0123456789ABCDEFGHIJKLMNOPQRSTUV", /* id = BASE32_BASE32HEX */ + "ybndrfg8ejkmcpqxot1uwisza345h769", /* id = BASE32_ZBASE32 */ + "0123456789ABCDEFGHJKMNPQRSTVWXYZ" /* id = BASE32_CROCKFORD */ + }; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(id >= BASE32_RFC4648); + LTC_ARGCHK(id <= BASE32_CROCKFORD); + + /* check the size of output buffer +1 byte for terminating NUL */ + x = (8 * inlen + 4) / 5 + 1; + if (*outlen < x) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = x - 1; /* returning the length without terminating NUL */ + + /* no input, nothing to do */ + if (inlen == 0) { + *out = '\0'; + return CRYPT_OK; + } + + codes = alphabet[id]; + x = 5 * (inlen / 5); + for (i = 0; i < x; i += 5) { + *out++ = codes[(in[0] >> 3) & 0x1F]; + *out++ = codes[(((in[0] & 0x7) << 2) + (in[1] >> 6)) & 0x1F]; + *out++ = codes[(in[1] >> 1) & 0x1F]; + *out++ = codes[(((in[1] & 0x1) << 4) + (in[2] >> 4)) & 0x1F]; + *out++ = codes[(((in[2] & 0xF) << 1) + (in[3] >> 7)) & 0x1F]; + *out++ = codes[(in[3] >> 2) & 0x1F]; + *out++ = codes[(((in[3] & 0x3) << 3) + (in[4] >> 5)) & 0x1F]; + *out++ = codes[in[4] & 0x1F]; + in += 5; + } + if (i < inlen) { + unsigned a = in[0]; + unsigned b = (i+1 < inlen) ? in[1] : 0; + unsigned c = (i+2 < inlen) ? in[2] : 0; + unsigned d = (i+3 < inlen) ? in[3] : 0; + *out++ = codes[(a >> 3) & 0x1F]; + *out++ = codes[(((a & 0x7) << 2) + (b >> 6)) & 0x1F]; + if (i+1 < inlen) { + *out++ = codes[(b >> 1) & 0x1F]; + *out++ = codes[(((b & 0x1) << 4) + (c >> 4)) & 0x1F]; + } + if (i+2 < inlen) { + *out++ = codes[(((c & 0xF) << 1) + (d >> 7)) & 0x1F]; + } + if (i+3 < inlen) { + *out++ = codes[(d >> 2) & 0x1F]; + *out++ = codes[((d & 0x3) << 3) & 0x1F]; + } + } + *out = '\0'; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/base64/base64_decode.c b/deps/libtomcrypt/src/misc/base64/base64_decode.c new file mode 100644 index 0000000..5859111 --- /dev/null +++ b/deps/libtomcrypt/src/misc/base64/base64_decode.c @@ -0,0 +1,229 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file base64_decode.c + Compliant base64 code donated by Wayne Scott (wscott@bitmover.com) + base64 URL Safe variant (RFC 4648 section 5) by Karel Miko +*/ + + +#if defined(LTC_BASE64) || defined (LTC_BASE64_URL) + +/* 253 - ignored in "relaxed" + "insane" mode: TAB(9), CR(13), LF(10), space(32) + * 254 - padding character '=' (allowed only at the end) + * 255 - ignored in "insane" mode, but not allowed in "relaxed" + "strict" mode + */ + +#if defined(LTC_BASE64) +static const unsigned char map_base64[256] = { +255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, +255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, +255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, +255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255 }; +#endif /* LTC_BASE64 */ + +static const unsigned char map_base64url[] = { +#if defined(LTC_BASE64_URL) +255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 255, +255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, +255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 63, +255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255 +#endif /* LTC_BASE64_URL */ +}; + +enum { + insane = 0, + strict = 1, + relaxed = 2 +}; + +static int s_base64_decode_internal(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *map, int mode) +{ + unsigned long t, x, y, z; + unsigned char c; + int g; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + g = 0; /* '=' counter */ + for (x = y = z = t = 0; x < inlen; x++) { + if ((in[x] == 0) && (x == (inlen - 1)) && (mode != strict)) { + continue; /* allow the last byte to be NUL (relaxed+insane) */ + } + c = map[(unsigned char)in[x]&0xFF]; + if (c == 254) { + g++; + continue; + } + if (c == 253) { + if (mode == strict) { + return CRYPT_INVALID_PACKET; + } + continue; /* allow to ignore white-spaces (relaxed+insane) */ + } + if (c == 255) { + if (mode == insane) { + continue; /* allow to ignore invalid garbage (insane) */ + } + return CRYPT_INVALID_PACKET; + } + if ((g > 0) && (mode != insane)) { + /* we only allow '=' to be at the end (strict+relaxed) */ + return CRYPT_INVALID_PACKET; + } + + t = (t<<6)|c; + + if (++y == 4) { + if (z + 3 > *outlen) return CRYPT_BUFFER_OVERFLOW; + out[z++] = (unsigned char)((t>>16)&255); + out[z++] = (unsigned char)((t>>8)&255); + out[z++] = (unsigned char)(t&255); + y = t = 0; + } + } + + if (y != 0) { + if (y == 1) return CRYPT_INVALID_PACKET; + if (((y + g) != 4) && (mode == strict) && (map != map_base64url)) return CRYPT_INVALID_PACKET; + t = t << (6 * (4 - y)); + if (z + y - 1 > *outlen) return CRYPT_BUFFER_OVERFLOW; + if (y >= 2) out[z++] = (unsigned char) ((t >> 16) & 255); + if (y == 3) out[z++] = (unsigned char) ((t >> 8) & 255); + } + *outlen = z; + return CRYPT_OK; +} + +#if defined(LTC_BASE64) +/** + Dangerously relaxed base64 decode a block of memory + @param in The base64 data to decode + @param inlen The length of the base64 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base64_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64, insane); +} + +/** + Strict base64 decode a block of memory + @param in The base64 data to decode + @param inlen The length of the base64 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base64_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64, strict); +} + +/** + Sane base64 decode a block of memory + @param in The base64 data to decode + @param inlen The length of the base64 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base64_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64, relaxed); +} +#endif /* LTC_BASE64 */ + +#if defined(LTC_BASE64_URL) +/** + Dangerously relaxed base64 (URL Safe, RFC 4648 section 5) decode a block of memory + @param in The base64 data to decode + @param inlen The length of the base64 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base64url_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, insane); +} + +/** + Strict base64 (URL Safe, RFC 4648 section 5) decode a block of memory + @param in The base64 data to decode + @param inlen The length of the base64 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base64url_strict_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, strict); +} + +/** + Sane base64 (URL Safe, RFC 4648 section 5) decode a block of memory + @param in The base64 data to decode + @param inlen The length of the base64 data + @param out [out] The destination of the binary decoded data + @param outlen [in/out] The max size and resulting size of the decoded data + @return CRYPT_OK if successful +*/ +int base64url_sane_decode(const char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + return s_base64_decode_internal(in, inlen, out, outlen, map_base64url, relaxed); +} +#endif /* LTC_BASE64_URL */ + +#endif + diff --git a/deps/libtomcrypt/src/misc/base64/base64_encode.c b/deps/libtomcrypt/src/misc/base64/base64_encode.c new file mode 100644 index 0000000..ef8aee9 --- /dev/null +++ b/deps/libtomcrypt/src/misc/base64/base64_encode.c @@ -0,0 +1,159 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file base64_encode.c + Compliant base64 encoder donated by Wayne Scott (wscott@bitmover.com) + base64 URL Safe variant (RFC 4648 section 5) by Karel Miko +*/ + + +#if defined(LTC_BASE64) || defined (LTC_BASE64_URL) + +#if defined(LTC_BASE64) +static const char * const codes_base64 = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +#endif /* LTC_BASE64 */ + +#if defined(LTC_BASE64_URL) +static const char * const codes_base64url = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +#endif /* LTC_BASE64_URL */ + +enum mode { + nopad = 0, + pad = 1, + lf = 2, + cr = 4, + ssh = 8, + crlf = lf | cr, +}; + +static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + const char *codes, unsigned int mode) +{ + unsigned long i, len2, leven, linelen; + char *p; + + LTC_ARGCHK(outlen != NULL); + + linelen = (mode & ssh) ? 72 : 64; + + /* valid output size ? */ + len2 = 4 * ((inlen + 2) / 3); + if ((mode & crlf) == lf) { + len2 += len2 / linelen; + } else if ((mode & crlf) == crlf) { + len2 += (len2 / linelen) * 2; + } + if (*outlen < len2 + 1) { + *outlen = len2 + 1; + return CRYPT_BUFFER_OVERFLOW; + } + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if ((void*)in == out) { + return CRYPT_INVALID_ARG; + } + + p = out; + leven = 3*(inlen / 3); + for (i = 0; i < leven; i += 3) { + *p++ = codes[(in[0] >> 2) & 0x3F]; + *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F]; + *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F]; + *p++ = codes[in[2] & 0x3F]; + in += 3; + if ((p - out) % linelen == 0) { + if (mode & cr) *p++ = '\r'; + if (mode & lf) *p++ = '\n'; + } + } + /* Pad it if necessary... */ + if (i < inlen) { + unsigned a = in[0]; + unsigned b = (i+1 < inlen) ? in[1] : 0; + + *p++ = codes[(a >> 2) & 0x3F]; + *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F]; + if (mode & pad) { + *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='; + *p++ = '='; + } + else { + if (i+1 < inlen) *p++ = codes[(((b & 0xf) << 2)) & 0x3F]; + } + } + + /* append a NULL byte */ + *p = '\0'; + + /* return ok */ + *outlen = (unsigned long)(p - out); /* the length without terminating NUL */ + return CRYPT_OK; +} + +#if defined(LTC_BASE64) +/** + base64 Encode a buffer (NUL terminated) + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the base64 encoded data + @param outlen [in/out] The max size and resulting size + @return CRYPT_OK if successful +*/ +int base64_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen) +{ + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad); +} + +/** + base64 Encode a buffer for PEM output + (NUL terminated with line-break at 64 chars) + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the base64 encoded data + @param outlen [in/out] The max size and resulting size + @param flags \ref base64_pem_flags + @return CRYPT_OK if successful +*/ +int base64_encode_pem(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int flags) +{ + int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf; + int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0; + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf); +} +#endif /* LTC_BASE64 */ + + +#if defined(LTC_BASE64_URL) +/** + base64 (URL Safe, RFC 4648 section 5) Encode a buffer (NUL terminated) + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the base64 encoded data + @param outlen [in/out] The max size and resulting size + @return CRYPT_OK if successful +*/ +int base64url_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen) +{ + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad); +} + +int base64url_strict_encode(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen) +{ + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad); +} +#endif /* LTC_BASE64_URL */ + +#endif + diff --git a/deps/libtomcrypt/src/misc/bcrypt/bcrypt.c b/deps/libtomcrypt/src/misc/bcrypt/bcrypt.c new file mode 100644 index 0000000..1bebdff --- /dev/null +++ b/deps/libtomcrypt/src/misc/bcrypt/bcrypt.c @@ -0,0 +1,191 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file bcrypt.c + bcrypt pbkdf, Steffen Jaeckel +*/ +#ifdef LTC_BCRYPT + +#define BCRYPT_WORDS 8 +#define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4) + +static int s_bcrypt_hash(const unsigned char *pt, + const unsigned char *pass, unsigned long passlen, + const unsigned char *salt, unsigned long saltlen, + unsigned char *out, unsigned long *outlen) +{ + symmetric_key key; + int err, n; + ulong32 ct[BCRYPT_WORDS]; + + if ((err = blowfish_setup_with_data(pass, passlen, salt, saltlen, &key)) != CRYPT_OK) { + return err; + } + for (n = 0; n < 64; ++n) { + if ((err = blowfish_expand(salt, saltlen, NULL, 0, &key)) != CRYPT_OK) { + return err; + } + if ((err = blowfish_expand(pass, passlen, NULL, 0, &key)) != CRYPT_OK) { + return err; + } + } + + for (n = 0; n < BCRYPT_WORDS; ++n) { + LOAD32H(ct[n], &pt[n*4]); + } + + for (n = 0; n < 64; ++n) { + blowfish_enc(ct, BCRYPT_WORDS/2, &key); + } + + for (n = 0; n < BCRYPT_WORDS; ++n) { + STORE32L(ct[n], &out[4 * n]); + } + *outlen = sizeof(ct); +#ifdef LTC_CLEAN_STACK + zeromem(&key, sizeof(key)); + zeromem(ct, sizeof(ct)); +#endif + + return CRYPT_OK; +} + +static int s_bcrypt_pbkdf_hash(const unsigned char *pass, unsigned long passlen, + const unsigned char *salt, unsigned long saltlen, + unsigned char *out, unsigned long *outlen) +{ + const unsigned char pt[] = "OxychromaticBlowfishSwatDynamite"; + return s_bcrypt_hash(pt, pass, passlen, salt, saltlen, out, outlen); +} + +/** + Compatible to bcrypt_pbkdf() as provided in OpenBSD + @param password The input password (or key) + @param password_len The length of the password (octets) + @param salt The salt (or nonce) + @param salt_len The length of the salt (octets) + @param rounds # of iterations desired [read specs for more] + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The desired size of the algorithm output + @return CRYPT_OK if successful +*/ +int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, + const unsigned char *salt, unsigned long salt_len, + unsigned int rounds, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err; + ulong32 blkno; + unsigned long left, itts, x, y, hashed_pass_len, step_size, steps, dest, used_rounds; + unsigned char *buf[3], blkbuf[4]; + unsigned char *hashed_pass; + + LTC_ARGCHK(secret != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((secret_len == 0) || (salt_len == 0) || (*outlen == 0)) { + return CRYPT_INVALID_ARG; + } + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + /* set default value for rounds if not given */ + if (rounds == 0) { + used_rounds = LTC_BCRYPT_DEFAULT_ROUNDS; + } else { + used_rounds = rounds; + } + + buf[0] = XMALLOC(MAXBLOCKSIZE * 3); + hashed_pass = XMALLOC(MAXBLOCKSIZE); + if (buf[0] == NULL || hashed_pass == NULL) { + if (hashed_pass != NULL) { + XFREE(hashed_pass); + } + if (buf[0] != NULL) { + XFREE(buf[0]); + } + return CRYPT_MEM; + } + /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ + buf[1] = buf[0] + MAXBLOCKSIZE; + buf[2] = buf[1] + MAXBLOCKSIZE; + + step_size = (*outlen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE; + steps = (*outlen + step_size - 1) / step_size; + + hashed_pass_len = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, (unsigned char*)secret, secret_len, hashed_pass, &hashed_pass_len)) != CRYPT_OK) { + goto LBL_ERR; + } + + left = *outlen; + blkno = 0; + while (left != 0) { + /* increment and store current block number */ + ++blkno; + STORE32H(blkno, blkbuf); + + /* process block number blkno */ + zeromem(buf[0], MAXBLOCKSIZE*2); + + x = MAXBLOCKSIZE; + if ((err = hash_memory_multi(hash_idx, buf[0], &x, + salt, salt_len, + blkbuf, 4uL, + LTC_NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + y = MAXBLOCKSIZE; + if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + XMEMCPY(buf[2], buf[1], y); + + /* now compute repeated and XOR it in buf[2] */ + for (itts = 1; itts < used_rounds; ++itts) { + x = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, buf[1], y, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y = MAXBLOCKSIZE; + if ((err = s_bcrypt_pbkdf_hash(hashed_pass, hashed_pass_len, buf[0], x, buf[1], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + for (x = 0; x < y; x++) { + buf[2][x] ^= buf[1][x]; + } + } + + /* now emit upto `steps` bytes of buf[2] to output */ + steps = MIN(steps, left); + for (y = 0; y < steps; ++y) { + dest = y * step_size + (blkno - 1); + if (dest >= *outlen) + break; + out[dest] = buf[2][y]; + } + left -= y; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf[0], MAXBLOCKSIZE*3); + zeromem(hashed_pass, MAXBLOCKSIZE); +#endif + + XFREE(hashed_pass); + XFREE(buf[0]); + + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/misc/burn_stack.c b/deps/libtomcrypt/src/misc/burn_stack.c new file mode 100644 index 0000000..5d276a4 --- /dev/null +++ b/deps/libtomcrypt/src/misc/burn_stack.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file burn_stack.c + Burn stack, Tom St Denis +*/ + +/** + Burn some stack memory + @param len amount of stack to burn in bytes +*/ +void burn_stack(unsigned long len) +{ + unsigned char buf[32]; + zeromem(buf, sizeof(buf)); + if (len > (unsigned long)sizeof(buf)) { + burn_stack(len - sizeof(buf)); + } +} + + diff --git a/deps/libtomcrypt/src/misc/compare_testvector.c b/deps/libtomcrypt/src/misc/compare_testvector.c new file mode 100644 index 0000000..bb3c8cb --- /dev/null +++ b/deps/libtomcrypt/src/misc/compare_testvector.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file compare_testvector.c + Function to compare two testvectors and print a (detailed) error-message if required, Steffen Jaeckel +*/ + +#if defined(LTC_TEST) && defined(LTC_TEST_DBG) +static void s_print_hex(const char* what, const void* v, const unsigned long l) +{ + const unsigned char* p = v; + unsigned long x, y = 0, z; + fprintf(stderr, "%s contents: \n", what); + for (x = 0; x < l; ) { + fprintf(stderr, "%02X ", p[x]); + if (!(++x % 16) || x == l) { + if((x % 16) != 0) { + z = 16 - (x % 16); + if(z >= 8) + fprintf(stderr, " "); + for (; z != 0; --z) { + fprintf(stderr, " "); + } + } + fprintf(stderr, " | "); + for(; y < x; y++) { + if((y % 8) == 0) + fprintf(stderr, " "); + if(isgraph(p[y])) + fprintf(stderr, "%c", p[y]); + else + fprintf(stderr, "."); + } + fprintf(stderr, "\n"); + } + else if((x % 8) == 0) { + fprintf(stderr, " "); + } + } +} +#endif + +/** + Compare two test-vectors + + @param is The data as it is + @param is_len The length of is + @param should The data as it should + @param should_len The length of should + @param what The type of the data + @param which The iteration count + @return 0 on equality, -1 or 1 on difference +*/ +int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which) +{ + int res = 0; + if(is_len != should_len) { + res = is_len > should_len ? -1 : 1; + } else { + res = XMEMCMP(is, should, is_len); + } +#if defined(LTC_TEST) && defined(LTC_TEST_DBG) + if (res != 0) { + fprintf(stderr, "Testvector #%i(0x%x) of %s failed:\n", which, which, what); + s_print_hex("SHOULD", should, should_len); + s_print_hex("IS ", is, is_len); +#if LTC_TEST_DBG > 1 + } else { + fprintf(stderr, "Testvector #%i(0x%x) of %s passed!\n", which, which, what); +#endif + } +#else + LTC_UNUSED_PARAM(which); + LTC_UNUSED_PARAM(what); +#endif + + return res; +} diff --git a/deps/libtomcrypt/src/misc/copy_or_zeromem.c b/deps/libtomcrypt/src/misc/copy_or_zeromem.c new file mode 100644 index 0000000..a05eac6 --- /dev/null +++ b/deps/libtomcrypt/src/misc/copy_or_zeromem.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file copy_or_zeromem.c + Either copy or zero a block of memory in constant time, Steffen Jaeckel +*/ + +/** + Either copy or zero a block of memory in constant time + @param src The source where to read from + @param dest The destination where to write to + @param len The length of the area to process (octets) + @param coz Copy (on 0) Or Zero (> 0) +*/ +void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz) +{ + unsigned long y; +#ifdef LTC_FAST + unsigned long z; + LTC_FAST_TYPE fastMask = ~(LTC_FAST_TYPE)0; /* initialize fastMask at all ones */ +#endif + unsigned char mask = 0xff; /* initialize mask at all ones */ + + LTC_ARGCHKVD(src != NULL); + LTC_ARGCHKVD(dest != NULL); + + if (coz != 0) coz = 1; + y = 0; + mask *= 1 - coz; /* mask = ( coz ? 0 : 0xff ) */ +#ifdef LTC_FAST + fastMask *= 1 - coz; + if (len & ~15) { + for (; y < (len & ~15); y += 16) { + for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&dest[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&src[y+z])) & fastMask; + } + } + } +#endif + for (; y < len; y++) { + dest[y] = src[y] & mask; + } +#ifdef LTC_CLEAN_STACK +#ifdef LTC_FAST + fastMask = 0; +#endif + mask = 0; +#endif +} diff --git a/deps/libtomcrypt/src/misc/crc32.c b/deps/libtomcrypt/src/misc/crc32.c new file mode 100644 index 0000000..d90e830 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crc32.c @@ -0,0 +1,193 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crc32.c + CRC-32 checksum algorithm + Written and placed in the public domain by Wei Dai + Adapted for libtomcrypt by Steffen Jaeckel +*/ +#ifdef LTC_CRC32 + +static const ulong32 CRC32_NEGL = 0xffffffffUL; + +#if defined(ENDIAN_LITTLE) +#define CRC32_INDEX(c) (c & 0xff) +#define CRC32_SHIFTED(c) (c >> 8) +#elif defined(ENDIAN_BIG) +#define CRC32_INDEX(c) (c >> 24) +#define CRC32_SHIFTED(c) (c << 8) +#else +#error The existing CRC32 implementation only works properly when the endianness of the target platform is known. +#endif + +/* Table of CRC-32's of all single byte values (made by makecrc.c) */ +static const ulong32 crc32_m_tab[] = +{ +#if defined(ENDIAN_LITTLE) + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +#else + 0x00000000L, 0x96300777L, 0x2c610eeeL, 0xba510999L, 0x19c46d07L, + 0x8ff46a70L, 0x35a563e9L, 0xa395649eL, 0x3288db0eL, 0xa4b8dc79L, + 0x1ee9d5e0L, 0x88d9d297L, 0x2b4cb609L, 0xbd7cb17eL, 0x072db8e7L, + 0x911dbf90L, 0x6410b71dL, 0xf220b06aL, 0x4871b9f3L, 0xde41be84L, + 0x7dd4da1aL, 0xebe4dd6dL, 0x51b5d4f4L, 0xc785d383L, 0x56986c13L, + 0xc0a86b64L, 0x7af962fdL, 0xecc9658aL, 0x4f5c0114L, 0xd96c0663L, + 0x633d0ffaL, 0xf50d088dL, 0xc8206e3bL, 0x5e10694cL, 0xe44160d5L, + 0x727167a2L, 0xd1e4033cL, 0x47d4044bL, 0xfd850dd2L, 0x6bb50aa5L, + 0xfaa8b535L, 0x6c98b242L, 0xd6c9bbdbL, 0x40f9bcacL, 0xe36cd832L, + 0x755cdf45L, 0xcf0dd6dcL, 0x593dd1abL, 0xac30d926L, 0x3a00de51L, + 0x8051d7c8L, 0x1661d0bfL, 0xb5f4b421L, 0x23c4b356L, 0x9995bacfL, + 0x0fa5bdb8L, 0x9eb80228L, 0x0888055fL, 0xb2d90cc6L, 0x24e90bb1L, + 0x877c6f2fL, 0x114c6858L, 0xab1d61c1L, 0x3d2d66b6L, 0x9041dc76L, + 0x0671db01L, 0xbc20d298L, 0x2a10d5efL, 0x8985b171L, 0x1fb5b606L, + 0xa5e4bf9fL, 0x33d4b8e8L, 0xa2c90778L, 0x34f9000fL, 0x8ea80996L, + 0x18980ee1L, 0xbb0d6a7fL, 0x2d3d6d08L, 0x976c6491L, 0x015c63e6L, + 0xf4516b6bL, 0x62616c1cL, 0xd8306585L, 0x4e0062f2L, 0xed95066cL, + 0x7ba5011bL, 0xc1f40882L, 0x57c40ff5L, 0xc6d9b065L, 0x50e9b712L, + 0xeab8be8bL, 0x7c88b9fcL, 0xdf1ddd62L, 0x492dda15L, 0xf37cd38cL, + 0x654cd4fbL, 0x5861b24dL, 0xce51b53aL, 0x7400bca3L, 0xe230bbd4L, + 0x41a5df4aL, 0xd795d83dL, 0x6dc4d1a4L, 0xfbf4d6d3L, 0x6ae96943L, + 0xfcd96e34L, 0x468867adL, 0xd0b860daL, 0x732d0444L, 0xe51d0333L, + 0x5f4c0aaaL, 0xc97c0dddL, 0x3c710550L, 0xaa410227L, 0x10100bbeL, + 0x86200cc9L, 0x25b56857L, 0xb3856f20L, 0x09d466b9L, 0x9fe461ceL, + 0x0ef9de5eL, 0x98c9d929L, 0x2298d0b0L, 0xb4a8d7c7L, 0x173db359L, + 0x810db42eL, 0x3b5cbdb7L, 0xad6cbac0L, 0x2083b8edL, 0xb6b3bf9aL, + 0x0ce2b603L, 0x9ad2b174L, 0x3947d5eaL, 0xaf77d29dL, 0x1526db04L, + 0x8316dc73L, 0x120b63e3L, 0x843b6494L, 0x3e6a6d0dL, 0xa85a6a7aL, + 0x0bcf0ee4L, 0x9dff0993L, 0x27ae000aL, 0xb19e077dL, 0x44930ff0L, + 0xd2a30887L, 0x68f2011eL, 0xfec20669L, 0x5d5762f7L, 0xcb676580L, + 0x71366c19L, 0xe7066b6eL, 0x761bd4feL, 0xe02bd389L, 0x5a7ada10L, + 0xcc4add67L, 0x6fdfb9f9L, 0xf9efbe8eL, 0x43beb717L, 0xd58eb060L, + 0xe8a3d6d6L, 0x7e93d1a1L, 0xc4c2d838L, 0x52f2df4fL, 0xf167bbd1L, + 0x6757bca6L, 0xdd06b53fL, 0x4b36b248L, 0xda2b0dd8L, 0x4c1b0aafL, + 0xf64a0336L, 0x607a0441L, 0xc3ef60dfL, 0x55df67a8L, 0xef8e6e31L, + 0x79be6946L, 0x8cb361cbL, 0x1a8366bcL, 0xa0d26f25L, 0x36e26852L, + 0x95770cccL, 0x03470bbbL, 0xb9160222L, 0x2f260555L, 0xbe3bbac5L, + 0x280bbdb2L, 0x925ab42bL, 0x046ab35cL, 0xa7ffd7c2L, 0x31cfd0b5L, + 0x8b9ed92cL, 0x1daede5bL, 0xb0c2649bL, 0x26f263ecL, 0x9ca36a75L, + 0x0a936d02L, 0xa906099cL, 0x3f360eebL, 0x85670772L, 0x13570005L, + 0x824abf95L, 0x147ab8e2L, 0xae2bb17bL, 0x381bb60cL, 0x9b8ed292L, + 0x0dbed5e5L, 0xb7efdc7cL, 0x21dfdb0bL, 0xd4d2d386L, 0x42e2d4f1L, + 0xf8b3dd68L, 0x6e83da1fL, 0xcd16be81L, 0x5b26b9f6L, 0xe177b06fL, + 0x7747b718L, 0xe65a0888L, 0x706a0fffL, 0xca3b0666L, 0x5c0b0111L, + 0xff9e658fL, 0x69ae62f8L, 0xd3ff6b61L, 0x45cf6c16L, 0x78e20aa0L, + 0xeed20dd7L, 0x5483044eL, 0xc2b30339L, 0x612667a7L, 0xf71660d0L, + 0x4d476949L, 0xdb776e3eL, 0x4a6ad1aeL, 0xdc5ad6d9L, 0x660bdf40L, + 0xf03bd837L, 0x53aebca9L, 0xc59ebbdeL, 0x7fcfb247L, 0xe9ffb530L, + 0x1cf2bdbdL, 0x8ac2bacaL, 0x3093b353L, 0xa6a3b424L, 0x0536d0baL, + 0x9306d7cdL, 0x2957de54L, 0xbf67d923L, 0x2e7a66b3L, 0xb84a61c4L, + 0x021b685dL, 0x942b6f2aL, 0x37be0bb4L, 0xa18e0cc3L, 0x1bdf055aL, + 0x8def022dL +#endif +}; + +void crc32_init(crc32_state *ctx) +{ + LTC_ARGCHKVD(ctx != NULL); + ctx->crc = CRC32_NEGL; +} + +void crc32_update(crc32_state *ctx, const unsigned char *input, unsigned long length) +{ + ulong32 crc; + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(input != NULL); + crc = ctx->crc; + + while (length--) { + crc = crc32_m_tab[CRC32_INDEX(crc) ^ *input++] ^ CRC32_SHIFTED(crc); + } + + ctx->crc = crc; +} + +void crc32_finish(const crc32_state *ctx, void *hash, unsigned long size) +{ + unsigned long i; + unsigned char* h; + ulong32 crc; + LTC_ARGCHKVD(ctx != NULL); + LTC_ARGCHKVD(hash != NULL); + + h = hash; + crc = ctx->crc; + crc ^= CRC32_NEGL; + + if (size > 4) size = 4; + for (i = 0; i < size; i++) { + h[i] = ((unsigned char*)&(crc))[size-i-1]; + } +} + +int crc32_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + const void* in = "libtomcrypt"; + const unsigned char crc32[] = { 0xb3, 0x73, 0x76, 0xef }; + unsigned char out[4]; + crc32_state ctx; + crc32_init(&ctx); + crc32_update(&ctx, in, XSTRLEN(in)); + crc32_finish(&ctx, out, 4); + if (compare_testvector(crc32, 4, out, 4, "CRC32", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; +#endif +} +#endif diff --git a/deps/libtomcrypt/src/misc/crypt/crypt.c b/deps/libtomcrypt/src/misc/crypt/crypt.c new file mode 100644 index 0000000..14576fa --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt.c @@ -0,0 +1,552 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt.c + Build strings, Tom St Denis +*/ +#define NAME_VALUE(s) #s"="NAME(s) +#define NAME(s) #s + +const char *crypt_build_settings = + "LibTomCrypt " SCRYPT " (www.libtom.net)\n" + "LibTomCrypt is public domain software.\n" +#if defined(INCLUDE_BUILD_DATE) + "Built on " __DATE__ " at " __TIME__ "\n" +#endif + "\n\nEndianness: " +#if defined(ENDIAN_NEUTRAL) + "neutral/" +#endif +#if defined(ENDIAN_LITTLE) + "little" +#elif defined(ENDIAN_BIG) + "big" +#endif + #if defined(ENDIAN_32BITWORD) + " (32-bit words)\n" + #elif defined(ENDIAN_64BITWORD) + " (64-bit words)\n" + #else + " (no wordsize defined)\n" + #endif + "Clean stack: " +#if defined(LTC_CLEAN_STACK) + "enabled\n" +#else + "disabled\n" +#endif + "\nCiphers built-in:\n" +#if defined(LTC_BLOWFISH) + " Blowfish\n" +#endif +#if defined(LTC_RC2) + " RC2\n" +#endif +#if defined(LTC_RC5) + " RC5\n" +#endif +#if defined(LTC_RC6) + " RC6\n" +#endif +#if defined(LTC_SAFERP) + " Safer+\n" +#endif +#if defined(LTC_SAFER) + " Safer\n" +#endif +#if defined(LTC_RIJNDAEL) + " Rijndael\n" +#endif +#if defined(LTC_XTEA) + " XTEA\n" +#endif +#if defined(LTC_TWOFISH) + " Twofish " + #if defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) + "(small, tables, all_tables)\n" + #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_TABLES) + "(small, tables)\n" + #elif defined(LTC_TWOFISH_SMALL) && defined(LTC_TWOFISH_ALL_TABLES) + "(small, all_tables)\n" + #elif defined(LTC_TWOFISH_TABLES) && defined(LTC_TWOFISH_ALL_TABLES) + "(tables, all_tables)\n" + #elif defined(LTC_TWOFISH_SMALL) + "(small)\n" + #elif defined(LTC_TWOFISH_TABLES) + "(tables)\n" + #elif defined(LTC_TWOFISH_ALL_TABLES) + "(all_tables)\n" + #else + "\n" + #endif +#endif +#if defined(LTC_DES) + " DES\n" +#endif +#if defined(LTC_CAST5) + " CAST5\n" +#endif +#if defined(LTC_NOEKEON) + " Noekeon\n" +#endif +#if defined(LTC_SKIPJACK) + " Skipjack\n" +#endif +#if defined(LTC_KHAZAD) + " Khazad\n" +#endif +#if defined(LTC_ANUBIS) + " Anubis " +#endif +#if defined(LTC_ANUBIS_TWEAK) + " (tweaked)" +#endif + "\n" +#if defined(LTC_KSEED) + " KSEED\n" +#endif +#if defined(LTC_KASUMI) + " KASUMI\n" +#endif +#if defined(LTC_MULTI2) + " MULTI2\n" +#endif +#if defined(LTC_CAMELLIA) + " Camellia\n" +#endif +#if defined(LTC_IDEA) + " IDEA\n" +#endif +#if defined(LTC_SERPENT) + " Serpent\n" +#endif +#if defined(LTC_TEA) + " TEA\n" +#endif + "Stream ciphers built-in:\n" +#if defined(LTC_CHACHA) + " ChaCha\n" +#endif +#if defined(LTC_SALSA20) + " Salsa20\n" +#endif +#if defined(LTC_XSALSA20) + " XSalsa20\n" +#endif +#if defined(LTC_SOSEMANUK) + " Sosemanuk\n" +#endif +#if defined(LTC_RABBIT) + " Rabbit\n" +#endif +#if defined(LTC_RC4_STREAM) + " RC4\n" +#endif +#if defined(LTC_SOBER128_STREAM) + " SOBER128\n" +#endif + + "\nHashes built-in:\n" +#if defined(LTC_SHA3) + " SHA3\n" +#endif +#if defined(LTC_KECCAK) + " KECCAK\n" +#endif +#if defined(LTC_SHA512) + " SHA-512\n" +#endif +#if defined(LTC_SHA384) + " SHA-384\n" +#endif +#if defined(LTC_SHA512_256) + " SHA-512/256\n" +#endif +#if defined(LTC_SHA256) + " SHA-256\n" +#endif +#if defined(LTC_SHA512_224) + " SHA-512/224\n" +#endif +#if defined(LTC_SHA224) + " SHA-224\n" +#endif +#if defined(LTC_TIGER) + " TIGER\n" +#endif +#if defined(LTC_SHA1) + " SHA1\n" +#endif +#if defined(LTC_MD5) + " MD5\n" +#endif +#if defined(LTC_MD4) + " MD4\n" +#endif +#if defined(LTC_MD2) + " MD2\n" +#endif +#if defined(LTC_RIPEMD128) + " RIPEMD128\n" +#endif +#if defined(LTC_RIPEMD160) + " RIPEMD160\n" +#endif +#if defined(LTC_RIPEMD256) + " RIPEMD256\n" +#endif +#if defined(LTC_RIPEMD320) + " RIPEMD320\n" +#endif +#if defined(LTC_WHIRLPOOL) + " WHIRLPOOL\n" +#endif +#if defined(LTC_BLAKE2S) + " BLAKE2S\n" +#endif +#if defined(LTC_BLAKE2B) + " BLAKE2B\n" +#endif +#if defined(LTC_CHC_HASH) + " CHC_HASH\n" +#endif + + "\nBlock Chaining Modes:\n" +#if defined(LTC_CFB_MODE) + " CFB\n" +#endif +#if defined(LTC_OFB_MODE) + " OFB\n" +#endif +#if defined(LTC_ECB_MODE) + " ECB\n" +#endif +#if defined(LTC_CBC_MODE) + " CBC\n" +#endif +#if defined(LTC_CTR_MODE) + " CTR\n" +#endif +#if defined(LTC_LRW_MODE) + " LRW" +#if defined(LTC_LRW_TABLES) + " (tables) " +#endif + "\n" +#endif +#if defined(LTC_F8_MODE) + " F8\n" +#endif +#if defined(LTC_XTS_MODE) + " XTS\n" +#endif + + "\nMACs:\n" +#if defined(LTC_HMAC) + " HMAC\n" +#endif +#if defined(LTC_OMAC) + " OMAC\n" +#endif +#if defined(LTC_PMAC) + " PMAC\n" +#endif +#if defined(LTC_PELICAN) + " PELICAN\n" +#endif +#if defined(LTC_XCBC) + " XCBC\n" +#endif +#if defined(LTC_F9_MODE) + " F9\n" +#endif +#if defined(LTC_POLY1305) + " POLY1305\n" +#endif +#if defined(LTC_BLAKE2SMAC) + " BLAKE2S MAC\n" +#endif +#if defined(LTC_BLAKE2BMAC) + " BLAKE2B MAC\n" +#endif + + "\nENC + AUTH modes:\n" +#if defined(LTC_EAX_MODE) + " EAX\n" +#endif +#if defined(LTC_OCB_MODE) + " OCB\n" +#endif +#if defined(LTC_OCB3_MODE) + " OCB3\n" +#endif +#if defined(LTC_CCM_MODE) + " CCM\n" +#endif +#if defined(LTC_GCM_MODE) + " GCM" +#if defined(LTC_GCM_TABLES) + " (tables) " +#endif +#if defined(LTC_GCM_TABLES_SSE2) + " (SSE2) " +#endif + "\n" +#endif +#if defined(LTC_CHACHA20POLY1305_MODE) + " CHACHA20POLY1305\n" +#endif + + "\nPRNG:\n" +#if defined(LTC_YARROW) + " Yarrow ("NAME_VALUE(LTC_YARROW_AES)")\n" +#endif +#if defined(LTC_SPRNG) + " SPRNG\n" +#endif +#if defined(LTC_RC4) + " RC4\n" +#endif +#if defined(LTC_CHACHA20_PRNG) + " ChaCha20\n" +#endif +#if defined(LTC_FORTUNA) + " Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", " +#if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED) + "LTC_FORTUNA_RESEED_RATELIMIT_TIMED, " +#else + "LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD) +#endif + ")\n" +#endif +#if defined(LTC_SOBER128) + " SOBER128\n" +#endif + + "\nPK Crypto:\n" +#if defined(LTC_MRSA) + " RSA" +#if defined(LTC_RSA_BLINDING) && defined(LTC_RSA_CRT_HARDENING) + " (with blinding and CRT hardening)" +#elif defined(LTC_RSA_BLINDING) + " (with blinding)" +#elif defined(LTC_RSA_CRT_HARDENING) + " (with CRT hardening)" +#endif + "\n" +#endif +#if defined(LTC_MDH) + " DH\n" +#endif +#if defined(LTC_MECC) + " ECC" +#if defined(LTC_ECC_TIMING_RESISTANT) + " (with blinding)" +#endif + "\n" +#endif +#if defined(LTC_MDSA) + " DSA\n" +#endif +#if defined(LTC_CURVE25519) +#if defined(LTC_CURVE25519) + " Ed25519\n" +#endif +#if defined(LTC_CURVE25519) + " X25519\n" +#endif +#endif +#if defined(LTC_PK_MAX_RETRIES) + " "NAME_VALUE(LTC_PK_MAX_RETRIES)"\n" +#endif + + "\nMPI (Math):\n" +#if defined(LTC_MPI) + " LTC_MPI\n" +#endif +#if defined(LTM_DESC) + " LTM_DESC\n" +#endif +#if defined(TFM_DESC) + " TFM_DESC\n" +#endif +#if defined(GMP_DESC) + " GMP_DESC\n" +#endif +#if defined(LTC_MILLER_RABIN_REPS) + " "NAME_VALUE(LTC_MILLER_RABIN_REPS)"\n" +#endif + + "\nCompiler:\n" +#if defined(_WIN64) + " WIN64 platform detected.\n" +#elif defined(_WIN32) + " WIN32 platform detected.\n" +#endif +#if defined(__CYGWIN__) + " CYGWIN Detected.\n" +#endif +#if defined(__DJGPP__) + " DJGPP Detected.\n" +#endif +#if defined(_MSC_VER) + " MSVC compiler detected.\n" +#endif +#if defined(__clang_version__) + " Clang compiler " __clang_version__ ".\n" +#elif defined(INTEL_CC) + " Intel C Compiler " __VERSION__ ".\n" +#elif defined(__GNUC__) /* clang and icc also define __GNUC__ */ + " GCC compiler " __VERSION__ ".\n" +#endif + +#if defined(__x86_64__) + " x86-64 detected.\n" +#endif +#if defined(LTC_PPC32) + " PPC32 detected.\n" +#endif + + "\nVarious others: " +#if defined(ARGTYPE) + " " NAME_VALUE(ARGTYPE) " " +#endif +#if defined(LTC_ADLER32) + " ADLER32 " +#endif +#if defined(LTC_BASE64) + " BASE64 " +#endif +#if defined(LTC_BASE64_URL) + " BASE64-URL-SAFE " +#endif +#if defined(LTC_BASE32) + " BASE32 " +#endif +#if defined(LTC_BASE16) + " BASE16 " +#endif +#if defined(LTC_BCRYPT) + " BCRYPT " + " " NAME_VALUE(LTC_BCRYPT_DEFAULT_ROUNDS) " " +#endif +#if defined(LTC_CRC32) + " CRC32 " +#endif +#if defined(LTC_DER) + " DER " + " " NAME_VALUE(LTC_DER_MAX_RECURSION) " " +#endif +#if defined(LTC_PKCS_1) + " PKCS#1 " +#endif +#if defined(LTC_PKCS_5) + " PKCS#5 " +#endif +#if defined(LTC_PKCS_8) + " PKCS#8 " +#endif +#if defined(LTC_PKCS_12) + " PKCS#12 " +#endif +#if defined(LTC_PADDING) + " PADDING " +#endif +#if defined(LTC_HKDF) + " HKDF " +#endif +#if defined(LTC_PBES) + " PBES1 " + " PBES2 " +#endif +#if defined(LTC_SSH) + " SSH " +#endif +#if defined(LTC_DEVRANDOM) + " LTC_DEVRANDOM " +#endif +#if defined(LTC_TRY_URANDOM_FIRST) + " LTC_TRY_URANDOM_FIRST " +#endif +#if defined(LTC_RNG_GET_BYTES) + " LTC_RNG_GET_BYTES " +#endif +#if defined(LTC_RNG_MAKE_PRNG) + " LTC_RNG_MAKE_PRNG " +#endif +#if defined(LTC_PRNG_ENABLE_LTC_RNG) + " LTC_PRNG_ENABLE_LTC_RNG " +#endif +#if defined(LTC_HASH_HELPERS) + " LTC_HASH_HELPERS " +#endif +#if defined(LTC_VALGRIND) + " LTC_VALGRIND " +#endif +#if defined(LTC_TEST) + " LTC_TEST " +#endif +#if defined(LTC_TEST_DBG) + " " NAME_VALUE(LTC_TEST_DBG) " " +#endif +#if defined(LTC_TEST_EXT) + " LTC_TEST_EXT " +#endif +#if defined(LTC_SMALL_CODE) + " LTC_SMALL_CODE " +#endif +#if defined(LTC_NO_FILE) + " LTC_NO_FILE " +#endif +#if defined(LTC_FILE_READ_BUFSIZE) + " " NAME_VALUE(LTC_FILE_READ_BUFSIZE) " " +#endif +#if defined(LTC_FAST) + " LTC_FAST " +#endif +#if defined(LTC_NO_FAST) + " LTC_NO_FAST " +#endif +#if defined(LTC_NO_BSWAP) + " LTC_NO_BSWAP " +#endif +#if defined(LTC_NO_ASM) + " LTC_NO_ASM " +#endif +#if defined(LTC_ROx_BUILTIN) + " LTC_ROx_BUILTIN " +#elif defined(LTC_ROx_ASM) + " LTC_ROx_ASM " +#if defined(LTC_NO_ROLC) + " LTC_NO_ROLC " +#endif +#endif +#if defined(LTC_NO_TEST) + " LTC_NO_TEST " +#endif +#if defined(LTC_NO_TABLES) + " LTC_NO_TABLES " +#endif +#if defined(LTC_PTHREAD) + " LTC_PTHREAD " +#endif +#if defined(LTC_EASY) + " LTC_EASY " +#endif +#if defined(LTC_MECC_ACCEL) + " LTC_MECC_ACCEL " +#endif +#if defined(LTC_MECC_FP) + " LTC_MECC_FP " +#endif +#if defined(LTC_ECC_SHAMIR) + " LTC_ECC_SHAMIR " +#endif +#if defined(LTC_CLOCK_GETTIME) + " LTC_CLOCK_GETTIME " +#endif + "\n" + ; + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_argchk.c b/deps/libtomcrypt/src/misc/crypt/crypt_argchk.c new file mode 100644 index 0000000..85b562a --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_argchk.c @@ -0,0 +1,17 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_argchk.c + Perform argument checking, Tom St Denis +*/ + +#if (ARGTYPE == 0) +void crypt_argchk(const char *v, const char *s, int d) +{ + fprintf(stderr, "LTC_ARGCHK '%s' failure on line %d of file %s\n", + v, d, s); + abort(); +} +#endif diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c b/deps/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c new file mode 100644 index 0000000..b79ff33 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_cipher_descriptor.c @@ -0,0 +1,15 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_cipher_descriptor.c + Stores the cipher descriptor table, Tom St Denis +*/ + +struct ltc_cipher_descriptor cipher_descriptor[TAB_SIZE] = { +{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }; + +LTC_MUTEX_GLOBAL(ltc_cipher_mutex) + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c b/deps/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c new file mode 100644 index 0000000..8745ace --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_cipher_is_valid.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_cipher_is_valid.c + Determine if cipher is valid, Tom St Denis +*/ + +/* + Test if a cipher index is valid + @param idx The index of the cipher to search for + @return CRYPT_OK if valid +*/ +int cipher_is_valid(int idx) +{ + LTC_MUTEX_LOCK(<c_cipher_mutex); + if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_INVALID_CIPHER; + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_constants.c b/deps/libtomcrypt/src/misc/crypt/crypt_constants.c new file mode 100644 index 0000000..eac6dae --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_constants.c @@ -0,0 +1,290 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_constants.c + + Make various constants available to dynamic languages + like Python - Larry Bugbee, February 2013 + + LB - Dec 2013 - revised to include compiler define options + LB - Mar 2014 - added endianness and word size +*/ + +typedef struct { + const char *name; + const int value; +} crypt_constant; + +#define C_STRINGIFY(s) { #s, s } + +static const crypt_constant s_crypt_constants[] = { + + C_STRINGIFY(CRYPT_OK), + C_STRINGIFY(CRYPT_ERROR), + C_STRINGIFY(CRYPT_NOP), + C_STRINGIFY(CRYPT_INVALID_KEYSIZE), + C_STRINGIFY(CRYPT_INVALID_ROUNDS), + C_STRINGIFY(CRYPT_FAIL_TESTVECTOR), + C_STRINGIFY(CRYPT_BUFFER_OVERFLOW), + C_STRINGIFY(CRYPT_INVALID_PACKET), + C_STRINGIFY(CRYPT_INVALID_PRNGSIZE), + C_STRINGIFY(CRYPT_ERROR_READPRNG), + C_STRINGIFY(CRYPT_INVALID_CIPHER), + C_STRINGIFY(CRYPT_INVALID_HASH), + C_STRINGIFY(CRYPT_INVALID_PRNG), + C_STRINGIFY(CRYPT_MEM), + C_STRINGIFY(CRYPT_PK_TYPE_MISMATCH), + C_STRINGIFY(CRYPT_PK_NOT_PRIVATE), + C_STRINGIFY(CRYPT_INVALID_ARG), + C_STRINGIFY(CRYPT_FILE_NOTFOUND), + C_STRINGIFY(CRYPT_PK_INVALID_TYPE), + C_STRINGIFY(CRYPT_OVERFLOW), + C_STRINGIFY(CRYPT_PK_ASN1_ERROR), + C_STRINGIFY(CRYPT_INPUT_TOO_LONG), + C_STRINGIFY(CRYPT_PK_INVALID_SIZE), + C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE), + C_STRINGIFY(CRYPT_PK_INVALID_PADDING), + C_STRINGIFY(CRYPT_HASH_OVERFLOW), + + C_STRINGIFY(PK_PUBLIC), + C_STRINGIFY(PK_PRIVATE), + + C_STRINGIFY(LTC_ENCRYPT), + C_STRINGIFY(LTC_DECRYPT), + +#ifdef LTC_PKCS_1 + {"LTC_PKCS_1", 1}, + /* Block types */ + C_STRINGIFY(LTC_PKCS_1_EMSA), + C_STRINGIFY(LTC_PKCS_1_EME), + + /* Padding types */ + C_STRINGIFY(LTC_PKCS_1_V1_5), + C_STRINGIFY(LTC_PKCS_1_OAEP), + C_STRINGIFY(LTC_PKCS_1_PSS), + C_STRINGIFY(LTC_PKCS_1_V1_5_NA1), +#else + {"LTC_PKCS_1", 0}, +#endif + +#ifdef LTC_PADDING + {"LTC_PADDING", 1}, + + C_STRINGIFY(LTC_PAD_PKCS7), +#ifdef LTC_RNG_GET_BYTES + C_STRINGIFY(LTC_PAD_ISO_10126), +#endif + C_STRINGIFY(LTC_PAD_ANSI_X923), + C_STRINGIFY(LTC_PAD_ONE_AND_ZERO), + C_STRINGIFY(LTC_PAD_ZERO), + C_STRINGIFY(LTC_PAD_ZERO_ALWAYS), +#else + {"LTC_PADDING", 0}, +#endif + +#ifdef LTC_MRSA + {"LTC_MRSA", 1}, +#else + {"LTC_MRSA", 0}, +#endif + +#ifdef LTC_MECC + {"LTC_MECC", 1}, + C_STRINGIFY(ECC_BUF_SIZE), + C_STRINGIFY(ECC_MAXSIZE), +#else + {"LTC_MECC", 0}, +#endif + +#ifdef LTC_MDSA + {"LTC_MDSA", 1}, + C_STRINGIFY(LTC_MDSA_DELTA), + C_STRINGIFY(LTC_MDSA_MAX_GROUP), + C_STRINGIFY(LTC_MDSA_MAX_MODULUS), +#else + {"LTC_MDSA", 0}, +#endif + +#ifdef LTC_MILLER_RABIN_REPS + C_STRINGIFY(LTC_MILLER_RABIN_REPS), +#endif + +#ifdef LTC_DER +/* DER handling */ + {"LTC_DER", 1}, + C_STRINGIFY(LTC_ASN1_EOL), + C_STRINGIFY(LTC_ASN1_BOOLEAN), + C_STRINGIFY(LTC_ASN1_INTEGER), + C_STRINGIFY(LTC_ASN1_SHORT_INTEGER), + C_STRINGIFY(LTC_ASN1_BIT_STRING), + C_STRINGIFY(LTC_ASN1_OCTET_STRING), + C_STRINGIFY(LTC_ASN1_NULL), + C_STRINGIFY(LTC_ASN1_OBJECT_IDENTIFIER), + C_STRINGIFY(LTC_ASN1_IA5_STRING), + C_STRINGIFY(LTC_ASN1_PRINTABLE_STRING), + C_STRINGIFY(LTC_ASN1_UTF8_STRING), + C_STRINGIFY(LTC_ASN1_UTCTIME), + C_STRINGIFY(LTC_ASN1_CHOICE), + C_STRINGIFY(LTC_ASN1_SEQUENCE), + C_STRINGIFY(LTC_ASN1_SET), + C_STRINGIFY(LTC_ASN1_SETOF), + C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING), + C_STRINGIFY(LTC_ASN1_TELETEX_STRING), + C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME), + C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE), + C_STRINGIFY(LTC_DER_MAX_RECURSION), +#else + {"LTC_DER", 0}, +#endif + +#ifdef LTC_CTR_MODE + {"LTC_CTR_MODE", 1}, + C_STRINGIFY(CTR_COUNTER_LITTLE_ENDIAN), + C_STRINGIFY(CTR_COUNTER_BIG_ENDIAN), + C_STRINGIFY(LTC_CTR_RFC3686), +#else + {"LTC_CTR_MODE", 0}, +#endif +#ifdef LTC_GCM_MODE + C_STRINGIFY(LTC_GCM_MODE_IV), + C_STRINGIFY(LTC_GCM_MODE_AAD), + C_STRINGIFY(LTC_GCM_MODE_TEXT), +#endif + + C_STRINGIFY(LTC_MP_LT), + C_STRINGIFY(LTC_MP_EQ), + C_STRINGIFY(LTC_MP_GT), + + C_STRINGIFY(LTC_MP_NO), + C_STRINGIFY(LTC_MP_YES), + + C_STRINGIFY(MAXBLOCKSIZE), + C_STRINGIFY(TAB_SIZE), + C_STRINGIFY(ARGTYPE), + +#ifdef LTM_DESC + {"LTM_DESC", 1}, +#else + {"LTM_DESC", 0}, +#endif +#ifdef TFM_DESC + {"TFM_DESC", 1}, +#else + {"TFM_DESC", 0}, +#endif +#ifdef GMP_DESC + {"GMP_DESC", 1}, +#else + {"GMP_DESC", 0}, +#endif + +#ifdef LTC_FAST + {"LTC_FAST", 1}, +#else + {"LTC_FAST", 0}, +#endif + +#ifdef LTC_NO_FILE + {"LTC_NO_FILE", 1}, +#else + {"LTC_NO_FILE", 0}, +#endif + +#ifdef ENDIAN_LITTLE + {"ENDIAN_LITTLE", 1}, +#else + {"ENDIAN_LITTLE", 0}, +#endif + +#ifdef ENDIAN_BIG + {"ENDIAN_BIG", 1}, +#else + {"ENDIAN_BIG", 0}, +#endif + +#ifdef ENDIAN_32BITWORD + {"ENDIAN_32BITWORD", 1}, +#else + {"ENDIAN_32BITWORD", 0}, +#endif + +#ifdef ENDIAN_64BITWORD + {"ENDIAN_64BITWORD", 1}, +#else + {"ENDIAN_64BITWORD", 0}, +#endif + +#ifdef ENDIAN_NEUTRAL + {"ENDIAN_NEUTRAL", 1}, +#else + {"ENDIAN_NEUTRAL", 0}, +#endif +}; + + +/* crypt_get_constant() + * valueout will be the value of the named constant + * return -1 if named item not found + */ +int crypt_get_constant(const char* namein, int *valueout) { + int i; + int count = sizeof(s_crypt_constants) / sizeof(s_crypt_constants[0]); + for (i=0; i *names_list_size) { + return -1; + } + /* build the names list */ + ptr = names_list; + for (i=0; i total_len) return -1; + total_len -= number_len; + ptr += number_len; + } + /* to remove the trailing new-line */ + ptr -= 1; + *ptr = 0; + } + return 0; +} + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher.c new file mode 100644 index 0000000..e45da9c --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_cipher.c + Find a cipher in the descriptor tables, Tom St Denis +*/ + +/** + Find a registered cipher by name + @param name The name of the cipher to look for + @return >= 0 if found, -1 if not present +*/ +int find_cipher(const char *name) +{ + int x; + LTC_ARGCHK(name != NULL); + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name != NULL && !XSTRCMP(cipher_descriptor[x].name, name)) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c new file mode 100644 index 0000000..5089733 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_any.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_cipher_any.c + Find a cipher in the descriptor tables, Tom St Denis +*/ + +/** + Find a cipher flexibly. First by name then if not present by block and key size + @param name The name of the cipher desired + @param blocklen The minimum length of the block cipher desired (octets) + @param keylen The minimum length of the key size desired (octets) + @return >= 0 if found, -1 if not present +*/ +int find_cipher_any(const char *name, int blocklen, int keylen) +{ + int x; + + if(name != NULL) { + x = find_cipher(name); + if (x != -1) return x; + } + + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name == NULL) { + continue; + } + if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c new file mode 100644 index 0000000..4876e4a --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_cipher_id.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_cipher_id.c + Find cipher by ID, Tom St Denis +*/ + +/** + Find a cipher by ID number + @param ID The ID (not same as index) of the cipher to find + @return >= 0 if found, -1 if not present +*/ +int find_cipher_id(unsigned char ID) +{ + int x; + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].ID == ID) { + x = (cipher_descriptor[x].name == NULL) ? -1 : x; + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_hash.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash.c new file mode 100644 index 0000000..4d8ae49 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_hash.c + Find a hash, Tom St Denis +*/ + +/** + Find a registered hash by name + @param name The name of the hash to look for + @return >= 0 if found, -1 if not present +*/ +int find_hash(const char *name) +{ + int x; + LTC_ARGCHK(name != NULL); + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name != NULL && XSTRCMP(hash_descriptor[x].name, name) == 0) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c new file mode 100644 index 0000000..a225737 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_any.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_hash_any.c + Find a hash, Tom St Denis +*/ + +/** + Find a hash flexibly. First by name then if not present by digest size + @param name The name of the hash desired + @param digestlen The minimum length of the digest size (octets) + @return >= 0 if found, -1 if not present +*/int find_hash_any(const char *name, int digestlen) +{ + int x, y, z; + LTC_ARGCHK(name != NULL); + + x = find_hash(name); + if (x != -1) return x; + + LTC_MUTEX_LOCK(<c_hash_mutex); + y = MAXBLOCKSIZE+1; + z = -1; + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name == NULL) { + continue; + } + if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) { + z = x; + y = hash_descriptor[x].hashsize; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return z; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c new file mode 100644 index 0000000..5de4095 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_id.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_hash_id.c + Find hash by ID, Tom St Denis +*/ + +/** + Find a hash by ID number + @param ID The ID (not same as index) of the hash to find + @return >= 0 if found, -1 if not present +*/ +int find_hash_id(unsigned char ID) +{ + int x; + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].ID == ID) { + x = (hash_descriptor[x].name == NULL) ? -1 : x; + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c new file mode 100644 index 0000000..0e10235 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_hash_oid.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_hash_oid.c + Find a hash, Tom St Denis +*/ + +int find_hash_oid(const unsigned long *ID, unsigned long IDlen) +{ + int x; + LTC_ARGCHK(ID != NULL); + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name != NULL && hash_descriptor[x].OIDlen == IDlen && !XMEMCMP(hash_descriptor[x].OID, ID, sizeof(unsigned long) * IDlen)) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_find_prng.c b/deps/libtomcrypt/src/misc/crypt/crypt_find_prng.c new file mode 100644 index 0000000..7297982 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_find_prng.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_find_prng.c + Find a PRNG, Tom St Denis +*/ + +/** + Find a registered PRNG by name + @param name The name of the PRNG to look for + @return >= 0 if found, -1 if not present +*/ +int find_prng(const char *name) +{ + int x; + LTC_ARGCHK(name != NULL); + LTC_MUTEX_LOCK(<c_prng_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if ((prng_descriptor[x].name != NULL) && XSTRCMP(prng_descriptor[x].name, name) == 0) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return -1; +} + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_fsa.c b/deps/libtomcrypt/src/misc/crypt/crypt_fsa.c new file mode 100644 index 0000000..a23216d --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_fsa.c @@ -0,0 +1,46 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file crypt_fsa.c + LibTomCrypt FULL SPEED AHEAD!, Tom St Denis +*/ + +/* format is ltc_mp, cipher_desc, [cipher_desc], NULL, hash_desc, [hash_desc], NULL, prng_desc, [prng_desc], NULL */ +int crypt_fsa(void *mp, ...) +{ + va_list args; + void *p; + + va_start(args, mp); + if (mp != NULL) { + XMEMCPY(<c_mp, mp, sizeof(ltc_mp)); + } + + while ((p = va_arg(args, void*)) != NULL) { + if (register_cipher(p) == -1) { + va_end(args); + return CRYPT_INVALID_CIPHER; + } + } + + while ((p = va_arg(args, void*)) != NULL) { + if (register_hash(p) == -1) { + va_end(args); + return CRYPT_INVALID_HASH; + } + } + + while ((p = va_arg(args, void*)) != NULL) { + if (register_prng(p) == -1) { + va_end(args); + return CRYPT_INVALID_PRNG; + } + } + + va_end(args); + return CRYPT_OK; +} + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c b/deps/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c new file mode 100644 index 0000000..08e0238 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_hash_descriptor.c @@ -0,0 +1,15 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_hash_descriptor.c + Stores the hash descriptor table, Tom St Denis +*/ + +struct ltc_hash_descriptor hash_descriptor[TAB_SIZE] = { +{ NULL, 0, 0, 0, { 0 }, 0, NULL, NULL, NULL, NULL, NULL } +}; + +LTC_MUTEX_GLOBAL(ltc_hash_mutex) + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c b/deps/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c new file mode 100644 index 0000000..c2d9fd9 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_hash_is_valid.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_hash_is_valid.c + Determine if hash is valid, Tom St Denis +*/ + +/* + Test if a hash index is valid + @param idx The index of the hash to search for + @return CRYPT_OK if valid +*/ +int hash_is_valid(int idx) +{ + LTC_MUTEX_LOCK(<c_hash_mutex); + if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_INVALID_HASH; + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_inits.c b/deps/libtomcrypt/src/misc/crypt/crypt_inits.c new file mode 100644 index 0000000..f7af2b8 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_inits.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_inits.c + + Provide math library functions for dynamic languages + like Python - Larry Bugbee, February 2013 +*/ + + +#ifdef LTM_DESC +void init_LTM(void) +{ + ltc_mp = ltm_desc; +} +#endif + +#ifdef TFM_DESC +void init_TFM(void) +{ + ltc_mp = tfm_desc; +} +#endif + +#ifdef GMP_DESC +void init_GMP(void) +{ + ltc_mp = gmp_desc; +} +#endif + +int crypt_mp_init(const char* mpi) +{ + if (mpi == NULL) return CRYPT_ERROR; + switch (mpi[0]) { +#ifdef LTM_DESC + case 'l': + case 'L': + ltc_mp = ltm_desc; + return CRYPT_OK; +#endif +#ifdef TFM_DESC + case 't': + case 'T': + ltc_mp = tfm_desc; + return CRYPT_OK; +#endif +#ifdef GMP_DESC + case 'g': + case 'G': + ltc_mp = gmp_desc; + return CRYPT_OK; +#endif +#ifdef EXT_MATH_LIB + case 'e': + case 'E': + { + extern ltc_math_descriptor EXT_MATH_LIB; + ltc_mp = EXT_MATH_LIB; + } + +#if defined(LTC_TEST_DBG) +#define NAME_VALUE(s) #s"="NAME(s) +#define NAME(s) #s + printf("EXT_MATH_LIB = %s\n", NAME_VALUE(EXT_MATH_LIB)); +#undef NAME_VALUE +#undef NAME +#endif + + return CRYPT_OK; +#endif + default: +#if defined(LTC_TEST_DBG) + printf("Unknown/Invalid MPI provider: %s\n", mpi); +#endif + return CRYPT_ERROR; + } +} + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c b/deps/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c new file mode 100644 index 0000000..760ba63 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_ltc_mp_descriptor.c @@ -0,0 +1,6 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/* Initialize ltc_mp to nulls, to force allocation on all platforms, including macOS. */ +ltc_math_descriptor ltc_mp = { 0 }; diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c b/deps/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c new file mode 100644 index 0000000..94c26b8 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_prng_descriptor.c @@ -0,0 +1,14 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_prng_descriptor.c + Stores the PRNG descriptors, Tom St Denis +*/ +struct ltc_prng_descriptor prng_descriptor[TAB_SIZE] = { +{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; + +LTC_MUTEX_GLOBAL(ltc_prng_mutex) + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c b/deps/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c new file mode 100644 index 0000000..f1ba67b --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_prng_is_valid.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_prng_is_valid.c + Determine if PRNG is valid, Tom St Denis +*/ + +/* + Test if a PRNG index is valid + @param idx The index of the PRNG to search for + @return CRYPT_OK if valid +*/ +int prng_is_valid(int idx) +{ + LTC_MUTEX_LOCK(<c_prng_mutex); + if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_INVALID_PRNG; + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c b/deps/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c new file mode 100644 index 0000000..49a456f --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_prng_rng_descriptor.c @@ -0,0 +1,7 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PRNG_ENABLE_LTC_RNG +unsigned long (*ltc_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); +#endif diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c new file mode 100644 index 0000000..bb2b873 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c @@ -0,0 +1,99 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file crypt_register_all_ciphers.c + + Steffen Jaeckel +*/ + +#define REGISTER_CIPHER(h) do {\ + LTC_ARGCHK(register_cipher(h) != -1); \ +} while(0) + +int register_all_ciphers(void) +{ +#ifdef LTC_RIJNDAEL +#ifdef ENCRYPT_ONLY + /* alternative would be + * register_cipher(&rijndael_enc_desc); + */ + REGISTER_CIPHER(&aes_enc_desc); +#else + /* alternative would be + * register_cipher(&rijndael_desc); + */ + REGISTER_CIPHER(&aes_desc); +#endif +#endif +#ifdef LTC_BLOWFISH + REGISTER_CIPHER(&blowfish_desc); +#endif +#ifdef LTC_XTEA + REGISTER_CIPHER(&xtea_desc); +#endif +#ifdef LTC_RC5 + REGISTER_CIPHER(&rc5_desc); +#endif +#ifdef LTC_RC6 + REGISTER_CIPHER(&rc6_desc); +#endif +#ifdef LTC_SAFERP + REGISTER_CIPHER(&saferp_desc); +#endif +#ifdef LTC_TWOFISH + REGISTER_CIPHER(&twofish_desc); +#endif +#ifdef LTC_SAFER + REGISTER_CIPHER(&safer_k64_desc); + REGISTER_CIPHER(&safer_sk64_desc); + REGISTER_CIPHER(&safer_k128_desc); + REGISTER_CIPHER(&safer_sk128_desc); +#endif +#ifdef LTC_RC2 + REGISTER_CIPHER(&rc2_desc); +#endif +#ifdef LTC_DES + REGISTER_CIPHER(&des_desc); + REGISTER_CIPHER(&des3_desc); +#endif +#ifdef LTC_CAST5 + REGISTER_CIPHER(&cast5_desc); +#endif +#ifdef LTC_NOEKEON + REGISTER_CIPHER(&noekeon_desc); +#endif +#ifdef LTC_SKIPJACK + REGISTER_CIPHER(&skipjack_desc); +#endif +#ifdef LTC_ANUBIS + REGISTER_CIPHER(&anubis_desc); +#endif +#ifdef LTC_KHAZAD + REGISTER_CIPHER(&khazad_desc); +#endif +#ifdef LTC_KSEED + REGISTER_CIPHER(&kseed_desc); +#endif +#ifdef LTC_KASUMI + REGISTER_CIPHER(&kasumi_desc); +#endif +#ifdef LTC_MULTI2 + REGISTER_CIPHER(&multi2_desc); +#endif +#ifdef LTC_CAMELLIA + REGISTER_CIPHER(&camellia_desc); +#endif +#ifdef LTC_IDEA + REGISTER_CIPHER(&idea_desc); +#endif +#ifdef LTC_SERPENT + REGISTER_CIPHER(&serpent_desc); +#endif +#ifdef LTC_TEA + REGISTER_CIPHER(&tea_desc); +#endif + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c new file mode 100644 index 0000000..68a64ae --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c @@ -0,0 +1,95 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file crypt_register_all_hashes.c + + Steffen Jaeckel +*/ + +#define REGISTER_HASH(h) do {\ + LTC_ARGCHK(register_hash(h) != -1); \ +} while(0) + +int register_all_hashes(void) +{ +#ifdef LTC_TIGER + REGISTER_HASH(&tiger_desc); +#endif +#ifdef LTC_MD2 + REGISTER_HASH(&md2_desc); +#endif +#ifdef LTC_MD4 + REGISTER_HASH(&md4_desc); +#endif +#ifdef LTC_MD5 + REGISTER_HASH(&md5_desc); +#endif +#ifdef LTC_SHA1 + REGISTER_HASH(&sha1_desc); +#endif +#ifdef LTC_SHA224 + REGISTER_HASH(&sha224_desc); +#endif +#ifdef LTC_SHA256 + REGISTER_HASH(&sha256_desc); +#endif +#ifdef LTC_SHA384 + REGISTER_HASH(&sha384_desc); +#endif +#ifdef LTC_SHA512 + REGISTER_HASH(&sha512_desc); +#endif +#ifdef LTC_SHA512_224 + REGISTER_HASH(&sha512_224_desc); +#endif +#ifdef LTC_SHA512_256 + REGISTER_HASH(&sha512_256_desc); +#endif +#ifdef LTC_SHA3 + REGISTER_HASH(&sha3_224_desc); + REGISTER_HASH(&sha3_256_desc); + REGISTER_HASH(&sha3_384_desc); + REGISTER_HASH(&sha3_512_desc); +#endif +#ifdef LTC_KECCAK + REGISTER_HASH(&keccak_224_desc); + REGISTER_HASH(&keccak_256_desc); + REGISTER_HASH(&keccak_384_desc); + REGISTER_HASH(&keccak_512_desc); +#endif +#ifdef LTC_RIPEMD128 + REGISTER_HASH(&rmd128_desc); +#endif +#ifdef LTC_RIPEMD160 + REGISTER_HASH(&rmd160_desc); +#endif +#ifdef LTC_RIPEMD256 + REGISTER_HASH(&rmd256_desc); +#endif +#ifdef LTC_RIPEMD320 + REGISTER_HASH(&rmd320_desc); +#endif +#ifdef LTC_WHIRLPOOL + REGISTER_HASH(&whirlpool_desc); +#endif +#ifdef LTC_BLAKE2S + REGISTER_HASH(&blake2s_128_desc); + REGISTER_HASH(&blake2s_160_desc); + REGISTER_HASH(&blake2s_224_desc); + REGISTER_HASH(&blake2s_256_desc); +#endif +#ifdef LTC_BLAKE2S + REGISTER_HASH(&blake2b_160_desc); + REGISTER_HASH(&blake2b_256_desc); + REGISTER_HASH(&blake2b_384_desc); + REGISTER_HASH(&blake2b_512_desc); +#endif +#ifdef LTC_CHC_HASH + REGISTER_HASH(&chc_desc); + LTC_ARGCHK(chc_register(find_cipher_any("aes", 8, 16)) == CRYPT_OK); +#endif + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c new file mode 100644 index 0000000..4a2e2ef --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_register_all_prngs.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file crypt_register_all_prngs.c + + Steffen Jaeckel +*/ + +#define REGISTER_PRNG(h) do {\ + LTC_ARGCHK(register_prng(h) != -1); \ +} while(0) + +int register_all_prngs(void) +{ +#ifdef LTC_YARROW + REGISTER_PRNG(&yarrow_desc); +#endif +#ifdef LTC_FORTUNA + REGISTER_PRNG(&fortuna_desc); +#endif +#ifdef LTC_RC4 + REGISTER_PRNG(&rc4_desc); +#endif +#ifdef LTC_CHACHA20_PRNG + REGISTER_PRNG(&chacha20_prng_desc); +#endif +#ifdef LTC_SOBER128 + REGISTER_PRNG(&sober128_desc); +#endif +#ifdef LTC_SPRNG + REGISTER_PRNG(&sprng_desc); +#endif + + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_register_cipher.c b/deps/libtomcrypt/src/misc/crypt/crypt_register_cipher.c new file mode 100644 index 0000000..33c8696 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_register_cipher.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_register_cipher.c + Register a cipher, Tom St Denis +*/ + +/** + Register a cipher with the descriptor table + @param cipher The cipher you wish to register + @return value >= 0 if successfully added (or already present), -1 if unsuccessful +*/ +int register_cipher(const struct ltc_cipher_descriptor *cipher) +{ + int x; + + LTC_ARGCHK(cipher != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) { + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (cipher_descriptor[x].name == NULL) { + XMEMCPY(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)); + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_register_hash.c b/deps/libtomcrypt/src/misc/crypt/crypt_register_hash.c new file mode 100644 index 0000000..1668de3 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_register_hash.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_register_hash.c + Register a HASH, Tom St Denis +*/ + +/** + Register a hash with the descriptor table + @param hash The hash you wish to register + @return value >= 0 if successfully added (or already present), -1 if unsuccessful +*/ +int register_hash(const struct ltc_hash_descriptor *hash) +{ + int x; + + LTC_ARGCHK(hash != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (hash_descriptor[x].name == NULL) { + XMEMCPY(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)); + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_register_prng.c b/deps/libtomcrypt/src/misc/crypt/crypt_register_prng.c new file mode 100644 index 0000000..08e056b --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_register_prng.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_register_prng.c + Register a PRNG, Tom St Denis +*/ + +/** + Register a PRNG with the descriptor table + @param prng The PRNG you wish to register + @return value >= 0 if successfully added (or already present), -1 if unsuccessful +*/ +int register_prng(const struct ltc_prng_descriptor *prng) +{ + int x; + + LTC_ARGCHK(prng != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_prng_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + + /* find a blank spot */ + for (x = 0; x < TAB_SIZE; x++) { + if (prng_descriptor[x].name == NULL) { + XMEMCPY(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)); + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return x; + } + } + + /* no spot */ + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return -1; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_sizes.c b/deps/libtomcrypt/src/misc/crypt/crypt_sizes.c new file mode 100644 index 0000000..7545aa8 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_sizes.c @@ -0,0 +1,351 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_sizes.c + + Make various struct sizes available to dynamic languages + like Python - Larry Bugbee, February 2013 + + LB - Dec 2013 - revised to include compiler define options +*/ + + +typedef struct { + const char *name; + const unsigned int size; +} crypt_size; + +#define SZ_STRINGIFY_S(s) { #s, sizeof(struct s) } +#define SZ_STRINGIFY_T(s) { #s, sizeof(s) } + +static const crypt_size s_crypt_sizes[] = { + /* hash state sizes */ + SZ_STRINGIFY_S(ltc_hash_descriptor), + SZ_STRINGIFY_T(hash_state), +#ifdef LTC_CHC_HASH + SZ_STRINGIFY_S(chc_state), +#endif +#ifdef LTC_WHIRLPOOL + SZ_STRINGIFY_S(whirlpool_state), +#endif +#ifdef LTC_SHA3 + SZ_STRINGIFY_S(sha3_state), +#endif +#ifdef LTC_SHA512 + SZ_STRINGIFY_S(sha512_state), +#endif +#ifdef LTC_SHA256 + SZ_STRINGIFY_S(sha256_state), +#endif +#ifdef LTC_SHA1 + SZ_STRINGIFY_S(sha1_state), +#endif +#ifdef LTC_MD5 + SZ_STRINGIFY_S(md5_state), +#endif +#ifdef LTC_MD4 + SZ_STRINGIFY_S(md4_state), +#endif +#ifdef LTC_MD2 + SZ_STRINGIFY_S(md2_state), +#endif +#ifdef LTC_TIGER + SZ_STRINGIFY_S(tiger_state), +#endif +#ifdef LTC_RIPEMD128 + SZ_STRINGIFY_S(rmd128_state), +#endif +#ifdef LTC_RIPEMD160 + SZ_STRINGIFY_S(rmd160_state), +#endif +#ifdef LTC_RIPEMD256 + SZ_STRINGIFY_S(rmd256_state), +#endif +#ifdef LTC_RIPEMD320 + SZ_STRINGIFY_S(rmd320_state), +#endif +#ifdef LTC_BLAKE2S + SZ_STRINGIFY_S(blake2s_state), +#endif +#ifdef LTC_BLAKE2B + SZ_STRINGIFY_S(blake2b_state), +#endif + + /* block cipher key sizes */ + SZ_STRINGIFY_S(ltc_cipher_descriptor), + SZ_STRINGIFY_T(symmetric_key), +#ifdef LTC_ANUBIS + SZ_STRINGIFY_S(anubis_key), +#endif +#ifdef LTC_CAMELLIA + SZ_STRINGIFY_S(camellia_key), +#endif +#ifdef LTC_BLOWFISH + SZ_STRINGIFY_S(blowfish_key), +#endif +#ifdef LTC_CAST5 + SZ_STRINGIFY_S(cast5_key), +#endif +#ifdef LTC_DES + SZ_STRINGIFY_S(des_key), + SZ_STRINGIFY_S(des3_key), +#endif +#ifdef LTC_IDEA + SZ_STRINGIFY_S(idea_key), +#endif +#ifdef LTC_KASUMI + SZ_STRINGIFY_S(kasumi_key), +#endif +#ifdef LTC_KHAZAD + SZ_STRINGIFY_S(khazad_key), +#endif +#ifdef LTC_KSEED + SZ_STRINGIFY_S(kseed_key), +#endif +#ifdef LTC_MULTI2 + SZ_STRINGIFY_S(multi2_key), +#endif +#ifdef LTC_NOEKEON + SZ_STRINGIFY_S(noekeon_key), +#endif +#ifdef LTC_RC2 + SZ_STRINGIFY_S(rc2_key), +#endif +#ifdef LTC_RC5 + SZ_STRINGIFY_S(rc5_key), +#endif +#ifdef LTC_RC6 + SZ_STRINGIFY_S(rc6_key), +#endif +#ifdef LTC_SERPENT + SZ_STRINGIFY_S(serpent_key), +#endif +#ifdef LTC_SKIPJACK + SZ_STRINGIFY_S(skipjack_key), +#endif +#ifdef LTC_XTEA + SZ_STRINGIFY_S(xtea_key), +#endif +#ifdef LTC_RIJNDAEL + SZ_STRINGIFY_S(rijndael_key), +#endif +#ifdef LTC_SAFER + SZ_STRINGIFY_S(safer_key), +#endif +#ifdef LTC_SAFERP + SZ_STRINGIFY_S(saferp_key), +#endif +#ifdef LTC_TWOFISH + SZ_STRINGIFY_S(twofish_key), +#endif + + /* mode sizes */ +#ifdef LTC_ECB_MODE + SZ_STRINGIFY_T(symmetric_ECB), +#endif +#ifdef LTC_CFB_MODE + SZ_STRINGIFY_T(symmetric_CFB), +#endif +#ifdef LTC_OFB_MODE + SZ_STRINGIFY_T(symmetric_OFB), +#endif +#ifdef LTC_CBC_MODE + SZ_STRINGIFY_T(symmetric_CBC), +#endif +#ifdef LTC_CTR_MODE + SZ_STRINGIFY_T(symmetric_CTR), +#endif +#ifdef LTC_LRW_MODE + SZ_STRINGIFY_T(symmetric_LRW), +#endif +#ifdef LTC_F8_MODE + SZ_STRINGIFY_T(symmetric_F8), +#endif +#ifdef LTC_XTS_MODE + SZ_STRINGIFY_T(symmetric_xts), +#endif + + /* stream cipher sizes */ +#ifdef LTC_CHACHA + SZ_STRINGIFY_T(chacha_state), +#endif +#ifdef LTC_SALSA20 + SZ_STRINGIFY_T(salsa20_state), +#endif +#ifdef LTC_SOSEMANUK + SZ_STRINGIFY_T(sosemanuk_state), +#endif +#ifdef LTC_RABBIT + SZ_STRINGIFY_T(rabbit_state), +#endif +#ifdef LTC_RC4_STREAM + SZ_STRINGIFY_T(rc4_state), +#endif +#ifdef LTC_SOBER128_STREAM + SZ_STRINGIFY_T(sober128_state), +#endif + + /* MAC sizes -- no states for ccm, lrw */ +#ifdef LTC_HMAC + SZ_STRINGIFY_T(hmac_state), +#endif +#ifdef LTC_OMAC + SZ_STRINGIFY_T(omac_state), +#endif +#ifdef LTC_PMAC + SZ_STRINGIFY_T(pmac_state), +#endif +#ifdef LTC_POLY1305 + SZ_STRINGIFY_T(poly1305_state), +#endif +#ifdef LTC_EAX_MODE + SZ_STRINGIFY_T(eax_state), +#endif +#ifdef LTC_OCB_MODE + SZ_STRINGIFY_T(ocb_state), +#endif +#ifdef LTC_OCB3_MODE + SZ_STRINGIFY_T(ocb3_state), +#endif +#ifdef LTC_CCM_MODE + SZ_STRINGIFY_T(ccm_state), +#endif +#ifdef LTC_GCM_MODE + SZ_STRINGIFY_T(gcm_state), +#endif +#ifdef LTC_PELICAN + SZ_STRINGIFY_T(pelican_state), +#endif +#ifdef LTC_XCBC + SZ_STRINGIFY_T(xcbc_state), +#endif +#ifdef LTC_F9_MODE + SZ_STRINGIFY_T(f9_state), +#endif +#ifdef LTC_CHACHA20POLY1305_MODE + SZ_STRINGIFY_T(chacha20poly1305_state), +#endif + + /* asymmetric keys */ +#ifdef LTC_MRSA + SZ_STRINGIFY_T(rsa_key), +#endif +#ifdef LTC_MDSA + SZ_STRINGIFY_T(dsa_key), +#endif +#ifdef LTC_MDH + SZ_STRINGIFY_T(dh_key), +#endif +#ifdef LTC_MECC + SZ_STRINGIFY_T(ltc_ecc_curve), + SZ_STRINGIFY_T(ecc_point), + SZ_STRINGIFY_T(ecc_key), +#endif + + /* DER handling */ +#ifdef LTC_DER + SZ_STRINGIFY_T(ltc_asn1_list), /* a list entry */ + SZ_STRINGIFY_T(ltc_utctime), + SZ_STRINGIFY_T(ltc_generalizedtime), +#endif + + /* prng state sizes */ + SZ_STRINGIFY_S(ltc_prng_descriptor), + SZ_STRINGIFY_T(prng_state), +#ifdef LTC_FORTUNA + SZ_STRINGIFY_S(fortuna_prng), +#endif +#ifdef LTC_CHACHA20_PRNG + SZ_STRINGIFY_S(chacha20_prng), +#endif +#ifdef LTC_RC4 + SZ_STRINGIFY_S(rc4_prng), +#endif +#ifdef LTC_SOBER128 + SZ_STRINGIFY_S(sober128_prng), +#endif +#ifdef LTC_YARROW + SZ_STRINGIFY_S(yarrow_prng), +#endif + /* sprng has no state as it uses other potentially available sources */ + /* like /dev/random. See Developers Guide for more info. */ + +#ifdef LTC_ADLER32 + SZ_STRINGIFY_T(adler32_state), +#endif +#ifdef LTC_CRC32 + SZ_STRINGIFY_T(crc32_state), +#endif + + SZ_STRINGIFY_T(ltc_mp_digit), + SZ_STRINGIFY_T(ltc_math_descriptor) + +}; + +/* crypt_get_size() + * sizeout will be the size (bytes) of the named struct or union + * return -1 if named item not found + */ +int crypt_get_size(const char* namein, unsigned int *sizeout) { + int i; + int count = sizeof(s_crypt_sizes) / sizeof(s_crypt_sizes[0]); + for (i=0; i *names_list_size) { + return -1; + } + /* build the names list */ + ptr = names_list; + for (i=0; i total_len) return -1; + total_len -= number_len; + ptr += number_len; + } + /* to remove the trailing new-line */ + ptr -= 1; + *ptr = 0; + } + return 0; +} + diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c b/deps/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c new file mode 100644 index 0000000..bebf920 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_unregister_cipher.c @@ -0,0 +1,33 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_unregister_cipher.c + Unregister a cipher, Tom St Denis +*/ + +/** + Unregister a cipher from the descriptor table + @param cipher The cipher descriptor to remove + @return CRYPT_OK on success +*/ +int unregister_cipher(const struct ltc_cipher_descriptor *cipher) +{ + int x; + + LTC_ARGCHK(cipher != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_cipher_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&cipher_descriptor[x], cipher, sizeof(struct ltc_cipher_descriptor)) == 0) { + cipher_descriptor[x].name = NULL; + cipher_descriptor[x].ID = 255; + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_cipher_mutex); + return CRYPT_ERROR; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c b/deps/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c new file mode 100644 index 0000000..c2374d0 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_unregister_hash.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_unregister_hash.c + Unregister a hash, Tom St Denis +*/ + +/** + Unregister a hash from the descriptor table + @param hash The hash descriptor to remove + @return CRYPT_OK on success +*/ +int unregister_hash(const struct ltc_hash_descriptor *hash) +{ + int x; + + LTC_ARGCHK(hash != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_hash_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&hash_descriptor[x], hash, sizeof(struct ltc_hash_descriptor)) == 0) { + hash_descriptor[x].name = NULL; + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_hash_mutex); + return CRYPT_ERROR; +} diff --git a/deps/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c b/deps/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c new file mode 100644 index 0000000..1aa11e0 --- /dev/null +++ b/deps/libtomcrypt/src/misc/crypt/crypt_unregister_prng.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file crypt_unregister_prng.c + Unregister a PRNG, Tom St Denis +*/ + +/** + Unregister a PRNG from the descriptor table + @param prng The PRNG descriptor to remove + @return CRYPT_OK on success +*/ +int unregister_prng(const struct ltc_prng_descriptor *prng) +{ + int x; + + LTC_ARGCHK(prng != NULL); + + /* is it already registered? */ + LTC_MUTEX_LOCK(<c_prng_mutex); + for (x = 0; x < TAB_SIZE; x++) { + if (XMEMCMP(&prng_descriptor[x], prng, sizeof(struct ltc_prng_descriptor)) == 0) { + prng_descriptor[x].name = NULL; + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_OK; + } + } + LTC_MUTEX_UNLOCK(<c_prng_mutex); + return CRYPT_ERROR; +} diff --git a/deps/libtomcrypt/src/misc/error_to_string.c b/deps/libtomcrypt/src/misc/error_to_string.c new file mode 100644 index 0000000..5afac84 --- /dev/null +++ b/deps/libtomcrypt/src/misc/error_to_string.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file error_to_string.c + Convert error codes to ASCII strings, Tom St Denis +*/ + +static const char * const err_2_str[] = +{ + "CRYPT_OK", + "CRYPT_ERROR", + "Non-fatal 'no-operation' requested.", + + "Invalid key size.", + "Invalid number of rounds for block cipher.", + "Algorithm failed test vectors.", + + "Buffer overflow.", + "Invalid input packet.", + + "Invalid number of bits for a PRNG.", + "Error reading the PRNG.", + + "Invalid cipher specified.", + "Invalid hash specified.", + "Invalid PRNG specified.", + + "Out of memory.", + + "Invalid PK key or key type specified for function.", + "A private PK key is required.", + + "Invalid argument provided.", + "File Not Found", + + "Invalid PK type.", + + "An overflow of a value was detected/prevented.", + + "An ASN.1 decoding error occurred.", + + "The input was longer than expected.", + + "Invalid sized parameter.", + + "Invalid size for prime.", + + "Invalid padding.", + + "Hash applied to too many bits.", +}; + +/** + Convert an LTC error code to ASCII + @param err The error code + @return A pointer to the ASCII NUL terminated string for the error or "Invalid error code." if the err code was not valid. +*/ +const char *error_to_string(int err) +{ + if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) { + return "Invalid error code."; + } + return err_2_str[err]; +} + diff --git a/deps/libtomcrypt/src/misc/hkdf/hkdf.c b/deps/libtomcrypt/src/misc/hkdf/hkdf.c new file mode 100644 index 0000000..86b4ee8 --- /dev/null +++ b/deps/libtomcrypt/src/misc/hkdf/hkdf.c @@ -0,0 +1,135 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include +#include +#include + +#include "tomcrypt_private.h" + +#ifdef LTC_HKDF + +/* This is mostly just a wrapper around hmac_memory */ +int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + /* libtomcrypt chokes on a zero length HMAC key, so we need to check for + that. HMAC specifies that keys shorter than the hash's blocksize are + 0 padded to the block size. HKDF specifies that a NULL salt is to be + substituted with a salt comprised of hashLen 0 bytes. HMAC's padding + means that in either case the HMAC is actually using a blocksize long + zero filled key. Unless blocksize < hashLen (which wouldn't make any + sense), we can use a single 0 byte as the HMAC key and still generate + valid results for HKDF. */ + if (salt == NULL || saltlen == 0) { + return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen); + } + return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen); +} + +int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen) +{ + unsigned long hashsize; + int err; + unsigned char N; + unsigned long Noutlen, outoff; + + unsigned char *T, *dat; + unsigned long Tlen, datlen; + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hashsize = hash_descriptor[hash_idx].hashsize; + + /* RFC5869 parameter restrictions */ + if (inlen < hashsize || outlen > hashsize * 255) { + return CRYPT_INVALID_ARG; + } + if (info == NULL && infolen != 0) { + return CRYPT_INVALID_ARG; + } + LTC_ARGCHK(out != NULL); + + Tlen = hashsize + infolen + 1; + T = XMALLOC(Tlen); /* Replace with static buffer? */ + if (T == NULL) { + return CRYPT_MEM; + } + if (info != NULL) { + XMEMCPY(T + hashsize, info, infolen); + } + + /* HMAC data T(1) doesn't include a previous hash value */ + dat = T + hashsize; + datlen = Tlen - hashsize; + + N = 0; + outoff = 0; /* offset in out to write to */ + while (1) { /* an exit condition breaks mid-loop */ + Noutlen = MIN(hashsize, outlen - outoff); + T[Tlen - 1] = ++N; + if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen, + out + outoff, &Noutlen)) != CRYPT_OK) { + zeromem(T, Tlen); + XFREE(T); + return err; + } + outoff += Noutlen; + + if (outoff >= outlen) { /* loop exit condition */ + break; + } + + /* All subsequent HMAC data T(N) DOES include the previous hash value */ + XMEMCPY(T, out + hashsize * (N-1), hashsize); + if (N == 1) { + dat = T; + datlen = Tlen; + } + } + zeromem(T, Tlen); + XFREE(T); + return CRYPT_OK; +} + +/* all in one step */ +int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen) +{ + unsigned long hashsize; + int err; + unsigned char *extracted; + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hashsize = hash_descriptor[hash_idx].hashsize; + + extracted = XMALLOC(hashsize); /* replace with static buffer? */ + if (extracted == NULL) { + return CRYPT_MEM; + } + if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) { + zeromem(extracted, hashsize); + XFREE(extracted); + return err; + } + err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen); + zeromem(extracted, hashsize); + XFREE(extracted); + return err; +} +#endif /* LTC_HKDF */ + + +/* vim: set ts=2 sw=2 et ai si: */ diff --git a/deps/libtomcrypt/src/misc/hkdf/hkdf_test.c b/deps/libtomcrypt/src/misc/hkdf/hkdf_test.c new file mode 100644 index 0000000..99a970c --- /dev/null +++ b/deps/libtomcrypt/src/misc/hkdf/hkdf_test.c @@ -0,0 +1,284 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hkdf_test.c + LTC_HKDF support, self-test, Steffen Jaeckel +*/ + +#ifdef LTC_HKDF + +/* + TEST CASES SOURCE: + +Internet Engineering Task Force (IETF) H. Krawczyk +Request for Comments: 5869 IBM Research +Category: Informational P. Eronen +ISSN: 2070-1721 Nokia + May 2010 +Appendix A. Test Vectors +*/ + +/** + LTC_HKDF self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int hkdf_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + unsigned char OKM[82]; + int i; + + static const struct hkdf_test_case { + int num; + const char* Hash; + unsigned char IKM[80]; + unsigned long IKM_l; + unsigned char salt[80]; + unsigned long salt_l; + unsigned char info[80]; + unsigned long info_l; + unsigned char PRK[32]; + unsigned long PRK_l; + unsigned char OKM[82]; + unsigned long OKM_l; + } cases[] = { +#ifdef LTC_SHA256 + /* + Basic test case with SHA-256 + + Hash = SHA-256 + IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) + salt = 0x000102030405060708090a0b0c (13 octets) + info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets) + L = 42 + + PRK = 0x077709362c2e32df0ddc3f0dc47bba63 + 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets) + OKM = 0x3cb25f25faacd57a90434f64d0362f2a + 2d2d0a90cf1a5a4c5db02d56ecc4c5bf + 34007208d5b887185865 (42 octets) + */ + {1, "sha256", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, + {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9}, 10, + {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, + 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, + 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, 32, + {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, + 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, + 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, + 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, + 0x58, 0x65}, 42}, +#ifdef LTC_TEST_EXT + /* Test with SHA-256 and longer inputs/outputs */ + {2, "sha256", + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, + {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, + {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, + {0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, + 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, + 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, + 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44}, 32, + {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, + 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, + 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, + 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, + 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, + 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, + 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, + 0x1d, 0x87}, 82}, + /* Test with SHA-256 and zero length salt/info */ + {3, "sha256", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0}, 0, + {0}, 0, + {0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, + 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, + 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}, 32, + {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, + 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, + 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, + 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, + 0x96, 0xc8}, 42}, +#endif /* LTC_TEST_EXT */ +#endif /* LTC_SHA256 */ +#ifdef LTC_SHA1 + /* Basic test case with SHA-1 */ + {4, "sha1", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b}, 11, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, + {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9}, 10, + {0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, + 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, + 0xaa, 0x2b, 0xa2, 0x43}, 20, + {0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, + 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, + 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, + 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, + 0xf8, 0x96}, 42}, +#ifdef LTC_TEST_EXT + /* Test with SHA-1 and longer inputs/outputs */ + {5, "sha1", + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, + {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, + {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, + {0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, + 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, + 0x22, 0x4c, 0xfa, 0xf6}, 20, + {0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, + 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, + 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, + 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, + 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, + 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, + 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, + 0xd3, 0xb4}, 82}, + /* Test with SHA-1 and zero-length salt/info */ + {6, "sha1", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0}, 0, + {0}, 0, + {0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, + 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, + 0xa0, 0xd3, 0x2d, 0x01}, 20, + {0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, + 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, + 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, + 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, + 0x49, 0x18}, 42}, + /* Test with SHA-1, salt not provided (defaults to HashLen zero octets), + zero-length info */ + {7, "sha1", + {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 22, + {0}, 0, /* pass a null pointer */ + {0}, 0, + {0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, + 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, + 0x73, 0x13, 0x85, 0xdd}, 20, + {0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, + 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, + 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, + 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, + 0xfc, 0x48}, 42}, +#endif /* LTC_TEST_EXT */ +#endif /* LTC_SHA1 */ + }; + + int err; + int tested=0,failed=0; + for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { + int hash = find_hash(cases[i].Hash); + if (hash == -1) continue; + ++tested; + if((err = hkdf(hash, cases[i].salt, cases[i].salt_l, + cases[i].info, cases[i].info_l, + cases[i].IKM, cases[i].IKM_l, + OKM, cases[i].OKM_l)) != CRYPT_OK) { +#if defined(LTC_TEST_DBG) && (LTC_TEST_DBG > 1) + printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err)); +#endif + return err; + } + + if(compare_testvector(OKM, cases[i].OKM_l, cases[i].OKM, (size_t)cases[i].OKM_l, "HKDF", cases[i].num)) { + failed++; + } + } + + if (failed != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + if (tested == 0) { + return CRYPT_NOP; + } + return CRYPT_OK; + #endif +} + +#endif + diff --git a/deps/libtomcrypt/src/misc/mem_neq.c b/deps/libtomcrypt/src/misc/mem_neq.c new file mode 100644 index 0000000..8078a0a --- /dev/null +++ b/deps/libtomcrypt/src/misc/mem_neq.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file mem_neq.c + Compare two blocks of memory for inequality in constant time. + Steffen Jaeckel +*/ + +/** + Compare two blocks of memory for inequality in constant time. + + The usage is similar to that of standard memcmp, but you can only test + if the memory is equal or not - you can not determine by how much the + first different byte differs. + + This function shall be used to compare results of cryptographic + operations where inequality means most likely usage of a wrong key. + The execution time has therefore to be constant as otherwise + timing attacks could be possible. + + @param a The first memory region + @param b The second memory region + @param len The length of the area to compare (octets) + + @return 0 when a and b are equal for len bytes, 1 they are not equal. +*/ +int mem_neq(const void *a, const void *b, size_t len) +{ + unsigned char ret = 0; + const unsigned char* pa; + const unsigned char* pb; + + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + + pa = a; + pb = b; + + while (len-- > 0) { + ret |= *pa ^ *pb; + ++pa; + ++pb; + } + + ret |= ret >> 4; + ret |= ret >> 2; + ret |= ret >> 1; + ret &= 1; + + return ret; +} diff --git a/deps/libtomcrypt/src/misc/padding/padding_depad.c b/deps/libtomcrypt/src/misc/padding/padding_depad.c new file mode 100644 index 0000000..e3f7151 --- /dev/null +++ b/deps/libtomcrypt/src/misc/padding/padding_depad.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PADDING + +/** + Remove padding from your data + + This depads your data. + + @param data The data to depad + @param length [in/out] The size of the data before/after (removing padding) + @param mode One of the LTC_PAD_xx flags + @return CRYPT_OK on success +*/ +int padding_depad(const unsigned char *data, unsigned long *length, unsigned long mode) +{ + unsigned long padded_length, unpadded_length, n; + unsigned char pad; + enum padding_type type; + + LTC_ARGCHK(data != NULL); + LTC_ARGCHK(length != NULL); + + padded_length = *length; + + type = mode & LTC_PAD_MASK; + + if (type < LTC_PAD_ONE_AND_ZERO) { + pad = data[padded_length - 1]; + + if (pad > padded_length || pad == 0) return CRYPT_INVALID_ARG; + + unpadded_length = padded_length - pad; + } else { + /* init pad to calm old compilers */ + pad = 0x0; + unpadded_length = padded_length; + } + + switch (type) { + case LTC_PAD_ANSI_X923: + pad = 0x0; + /* FALLTHROUGH */ + case LTC_PAD_PKCS7: + for (n = unpadded_length; n < padded_length - 1; ++n) { + if (data[n] != pad) return CRYPT_INVALID_PACKET; + } + break; +#ifdef LTC_RNG_GET_BYTES + case LTC_PAD_ISO_10126: + /* nop */ + break; +#endif + case LTC_PAD_SSH: + pad = 0x1; + for (n = unpadded_length; n < padded_length; ++n) { + if (data[n] != pad++) return CRYPT_INVALID_PACKET; + } + break; + case LTC_PAD_ONE_AND_ZERO: + while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) { + if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET; + unpadded_length--; + } + if (unpadded_length == 0) return CRYPT_INVALID_PACKET; + unpadded_length--; + if (data[unpadded_length] != 0x80) return CRYPT_INVALID_PACKET; + break; + case LTC_PAD_ZERO: + case LTC_PAD_ZERO_ALWAYS: + while (unpadded_length > 0 && data[unpadded_length - 1] == 0x0) { + unpadded_length--; + } + if (type == LTC_PAD_ZERO_ALWAYS) { + if (unpadded_length == padded_length) return CRYPT_INVALID_PACKET; + if (data[unpadded_length] != 0x0) return CRYPT_INVALID_PACKET; + } + break; + default: + return CRYPT_INVALID_ARG; + } + + *length = unpadded_length; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/padding/padding_pad.c b/deps/libtomcrypt/src/misc/padding/padding_pad.c new file mode 100644 index 0000000..7d8bbba --- /dev/null +++ b/deps/libtomcrypt/src/misc/padding/padding_pad.c @@ -0,0 +1,151 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PADDING + +/** + Determine the to-be-padded length. + + @param length [in/out] The size of the data before/after padding + @param mode Mask of (LTC_PAD_xxx | block_length) + @return CRYPT_OK on success +*/ +static int s_padding_padded_length(unsigned long *length, unsigned long mode) +{ + enum padding_type padding; + unsigned char pad, block_length, r, t; + + LTC_ARGCHK(length != NULL); + + block_length = mode & 0xff; + padding = mode & LTC_PAD_MASK; + r = *length % block_length; + + switch (padding) { + case LTC_PAD_ZERO: + if (r == 0) { + t = 0; + break; + } + /* FALLTHROUGH */ + case LTC_PAD_PKCS7: + case LTC_PAD_ONE_AND_ZERO: + case LTC_PAD_ZERO_ALWAYS: + case LTC_PAD_SSH: + t = 1; + break; +#ifdef LTC_RNG_GET_BYTES + case LTC_PAD_ISO_10126: + do { + if (rng_get_bytes(&t, sizeof(t), NULL) != sizeof(t)) { + return CRYPT_ERROR_READPRNG; + } + t %= (256 / block_length); + } while (t == 0); + break; +#endif + case LTC_PAD_ANSI_X923: + if (block_length != 16) { + return CRYPT_INVALID_ARG; + } + t = 1; + break; + default: + return CRYPT_INVALID_ARG; + } + + pad = (t * block_length) - r; + + if ((pad == 0) && (padding != LTC_PAD_ZERO)) { + pad = block_length; + } + + *length += pad; + + return CRYPT_OK; +} + +/** + Add padding to data. + + This pads your data. + + @param data The data to depad + @param length The size of the data before padding + @param padded_length [in/out] The size of the data available/after padding + @param mode One of the LTC_PAD_xx flags + @return CRYPT_OK on success +*/ +int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode) +{ + unsigned long l, n; + enum padding_type type; + int err; + unsigned char diff, pad; + + LTC_ARGCHK(data != NULL); + LTC_ARGCHK(padded_length != NULL); + + l = length; + if ((err = s_padding_padded_length(&l, mode)) != CRYPT_OK) { + return err; + } + + type = mode & LTC_PAD_MASK; + + if (*padded_length < l) { +#ifdef LTC_RNG_GET_BYTES + if (type != LTC_PAD_ISO_10126) { + *padded_length = l; + } else { + *padded_length = length + 256; + } +#else + *padded_length = l; +#endif + return CRYPT_BUFFER_OVERFLOW; + } + + if (l - length > 255) return CRYPT_INVALID_ARG; + diff = (unsigned char)(l - length); + + switch (type) { + case LTC_PAD_PKCS7: + XMEMSET(&data[length], diff, diff); + break; +#ifdef LTC_RNG_GET_BYTES + case LTC_PAD_ISO_10126: + if (rng_get_bytes(&data[length], diff-1u, NULL) != diff-1u) { + return CRYPT_ERROR_READPRNG; + } + data[l-1] = diff; + break; +#endif + case LTC_PAD_ANSI_X923: + XMEMSET(&data[length], 0, diff-1); + data[l-1] = diff; + break; + case LTC_PAD_SSH: + pad = 0x1; + for (n = length; n < l; ++n) { + data[n] = pad++; + } + break; + case LTC_PAD_ONE_AND_ZERO: + XMEMSET(&data[length + 1], 0, diff); + data[length] = 0x80; + break; + case LTC_PAD_ZERO: + case LTC_PAD_ZERO_ALWAYS: + XMEMSET(&data[length], 0, diff); + break; + default: + return CRYPT_INVALID_ARG; + } + *padded_length = l; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/pbes/pbes.c b/deps/libtomcrypt/src/misc/pbes/pbes.c new file mode 100644 index 0000000..34be01c --- /dev/null +++ b/deps/libtomcrypt/src/misc/pbes/pbes.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PBES + +/** + Decrypt Data encrypted via either PBES1 or PBES2 + + @param arg The according PBES parameters + @param dec_data [out] The decrypted data + @param dec_size [in/out] The length of the encrypted resp. decrypted data + @return CRYPT_OK on success +*/ +int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size) +{ + int err, hid, cid; + unsigned char k[32], *iv; + unsigned long klen, keylen, dlen; + long diff; + symmetric_CBC cbc; + + LTC_ARGCHK(arg != NULL); + LTC_ARGCHK(arg->type.kdf != NULL); + LTC_ARGCHK(dec_data != NULL); + LTC_ARGCHK(dec_size != NULL); + + hid = find_hash(arg->type.h); + if (hid == -1) return CRYPT_INVALID_HASH; + cid = find_cipher(arg->type.c); + if (cid == -1) return CRYPT_INVALID_CIPHER; + + klen = arg->type.keylen; + + /* RC2 special case */ + if (arg->key_bits != 0) { + /* We can't handle odd lengths of Key Bits */ + if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE; + /* Internally we use bytes, not bits */ + klen = arg->key_bits / 8; + } + keylen = klen; + + if (arg->iv != NULL) { + iv = arg->iv->data; + } else { + iv = k + klen; + klen += arg->type.blocklen; + } + + if (klen > sizeof(k)) return CRYPT_INVALID_ARG; + + if ((err = arg->type.kdf(arg->pwd, arg->pwdlen, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR; + if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR; + if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR; + if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR; + dlen = arg->enc_data->size; + if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR; + diff = (long)arg->enc_data->size - (long)dlen; + if ((diff <= 0) || (diff > cipher_descriptor[cid].block_length)) { + err = CRYPT_PK_INVALID_PADDING; + goto LBL_ERROR; + } + *dec_size = dlen; + return CRYPT_OK; + +LBL_ERROR: + zeromem(k, sizeof(k)); + zeromem(dec_data, *dec_size); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/pbes/pbes1.c b/deps/libtomcrypt/src/misc/pbes/pbes1.c new file mode 100644 index 0000000..f33a009 --- /dev/null +++ b/deps/libtomcrypt/src/misc/pbes/pbes1.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PBES + +static int s_pkcs_5_alg1_wrap(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + LTC_UNUSED_PARAM(salt_len); + return pkcs_5_alg1(password, password_len, salt, iteration_count, hash_idx, out, outlen); +} + +static int s_pkcs_12_wrap(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err; + /* convert password to unicode/utf16-be */ + unsigned long pwlen = password_len * 2; + unsigned char* pw; + if (*outlen < 32) return CRYPT_INVALID_ARG; + pw = XMALLOC(pwlen + 2); + if (pw == NULL) return CRYPT_MEM; + if ((err = pkcs12_utf8_to_utf16(password, password_len, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR; + pw[pwlen++] = 0; + pw[pwlen++] = 0; + /* derive KEY */ + if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR; + /* derive IV */ + if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR; + + *outlen = 32; +LBL_ERROR: + zeromem(pw, pwlen); + XFREE(pw); + return err; +} + +static const pbes_properties s_pbes1_types[] = { + { s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 }, + { s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 }, + { s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 }, + { s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 }, + { s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 }, + { s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 }, + { s_pkcs_12_wrap, "sha1", "3des", 24, 8 }, +}; + +typedef struct { + const pbes_properties *data; + const char *oid; +} oid_to_pbes; + +static const oid_to_pbes s_pbes1_list[] = { + { &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */ + { &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */ + { &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */ + { &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */ + { &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */ + { &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */ + { &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */ + { 0 }, +}; + +static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res) +{ + unsigned int i; + for (i = 0; s_pbes1_list[i].data != NULL; ++i) { + if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) { + if (res != NULL) *res = *s_pbes1_list[i].data; + return CRYPT_OK; + } + } + return CRYPT_INVALID_ARG; +} + +/** + Extract PBES1 parameters + + @param s The start of the sequence with potential PBES1 parameters + @param res Pointer to where the extracted parameters should be stored + @return CRYPT_OK on success +*/ +int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res) +{ + int err; + + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(res != NULL); + + if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err; + + if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) || + !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) { + return CRYPT_INVALID_PACKET; + } + /* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC: + * 0:d=0 hl=4 l= 329 cons: SEQUENCE + * 4:d=1 hl=2 l= 27 cons: SEQUENCE + * 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s) + * 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam) + * 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt) + * 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations) + * 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) + */ + res->salt = s->next->child; + res->iterations = mp_get_int(s->next->child->next->data); + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/pbes/pbes2.c b/deps/libtomcrypt/src/misc/pbes/pbes2.c new file mode 100644 index 0000000..3378cd6 --- /dev/null +++ b/deps/libtomcrypt/src/misc/pbes/pbes2.c @@ -0,0 +1,198 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PBES + +static const char * const s_oid_pbes2 = "1.2.840.113549.1.5.13"; +static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12"; + +typedef struct { + const char *oid; + const char *id; +} oid_id_st; + +static const oid_id_st s_hmac_oid_names[] = { + { "1.2.840.113549.2.7", "sha1" }, + { "1.2.840.113549.2.8", "sha224" }, + { "1.2.840.113549.2.9", "sha256" }, + { "1.2.840.113549.2.10", "sha384" }, + { "1.2.840.113549.2.11", "sha512" }, + { "1.2.840.113549.2.12", "sha512-224" }, + { "1.2.840.113549.2.13", "sha512-256" }, +}; + +static const pbes_properties s_pbes2_default_types[] = { + { pkcs_5_alg2, "sha1", "des", 8, 0 }, + { pkcs_5_alg2, "sha1", "rc2", 4, 0 }, + { pkcs_5_alg2, "sha1", "3des", 24, 0 }, + { pkcs_5_alg2, "sha1", "aes", 16, 0 }, + { pkcs_5_alg2, "sha1", "aes", 24, 0 }, + { pkcs_5_alg2, "sha1", "aes", 32, 0 }, +}; + +typedef struct { + const pbes_properties *data; + const char* oid; +} oid_to_pbes; + +static const oid_to_pbes s_pbes2_list[] = { + { &s_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */ + { &s_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */ + { &s_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */ + { &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */ + { &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */ + { &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */ +}; + +static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res) +{ + unsigned int i; + for (i = 0; i < sizeof(s_pbes2_list)/sizeof(s_pbes2_list[0]); ++i) { + if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) { + *res = *s_pbes2_list[i].data; + break; + } + } + if (res->c == NULL) return CRYPT_INVALID_CIPHER; + if (hmac_oid != NULL) { + for (i = 0; i < sizeof(s_hmac_oid_names)/sizeof(s_hmac_oid_names[0]); ++i) { + if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) { + res->h = s_hmac_oid_names[i].id; + return CRYPT_OK; + } + } + return CRYPT_INVALID_HASH; + } + return CRYPT_OK; +} + + +/** + Extract PBES2 parameters + + @param s The start of the sequence with potential PBES2 parameters + @param res Pointer to where the extracted parameters should be stored + @return CRYPT_OK on success +*/ +int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res) +{ + unsigned long klen; + ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac; + int err; + + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(res != NULL); + + if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err; + + if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) || + !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) { + return CRYPT_INVALID_PACKET; + } + /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc: + * 0:d=0 hl=4 l= 380 cons: SEQUENCE + * 4:d=1 hl=2 l= 78 cons: SEQUENCE + * 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s) + * 17:d=2 hl=2 l= 65 cons: SEQUENCE + * 19:d=3 hl=2 l= 41 cons: SEQUENCE + * 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf) + * 32:d=4 hl=2 l= 28 cons: SEQUENCE + * 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt) + * 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter) + * 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing) + * 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac) + * 60:d=6 hl=2 l= 0 prim: NULL + * 62:d=3 hl=2 l= 20 cons: SEQUENCE + * 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc) + * 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A + * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) + */ + lkdf = s->next->child->child; + lenc = s->next->child->next->child; + + if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err; + + if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) || + !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) || + !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) { + return CRYPT_INVALID_PACKET; + } + + liter = lkdf->next->child->next; + loptseq = liter->next; + res->salt = lkdf->next->child; + res->iterations = mp_get_int(liter->data); + + /* There's an optional INTEGER keyLength after the iterations, skip that if it's there. + * c.f. RFC 2898 A.2 PBKDF2 */ + if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) { + loptseq = loptseq->next; + } + + /* this sequence is optional */ + lhmac = NULL; + if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) && + LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) { + lhmac = loptseq->child; + } + if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err; + + if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) { + /* 'NON-RC2'-CBC */ + res->iv = lenc->next; + } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) { + /* RC2-CBC is a bit special ... + * + * RC2-CBC-Parameter ::= SEQUENCE { + * rc2ParameterVersion INTEGER OPTIONAL, + * iv OCTET STRING (SIZE(8)) } + */ + if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) && + LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) { + klen = mp_get_int(lenc->next->child->data); + res->iv = lenc->next->child->next; + /* + * Effective Key Bits Encoding + * 40 160 + * 64 120 + * 128 58 + * b >= 256 b + */ + switch (klen) { + case 160: + res->key_bits = 40; + break; + case 120: + res->key_bits = 64; + break; + case 58: + res->key_bits = 128; + break; + default: + /* We don't handle undefined Key Bits */ + if (klen < 256) return CRYPT_INVALID_KEYSIZE; + + res->key_bits = klen; + break; + } + } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) { + res->iv = lenc->next->child; + /* + * If the rc2ParameterVersion field is omitted, the "effective key bits" + * defaults to 32. + */ + res->key_bits = 32; + } else { + return CRYPT_INVALID_PACKET; + } + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c b/deps/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c new file mode 100644 index 0000000..1739af7 --- /dev/null +++ b/deps/libtomcrypt/src/misc/pkcs12/pkcs12_kdf.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_PKCS_12 + +int pkcs12_kdf( int hash_id, + const unsigned char *pw, unsigned long pwlen, + const unsigned char *salt, unsigned long saltlen, + unsigned int iterations, unsigned char purpose, + unsigned char *out, unsigned long outlen) +{ + unsigned long u = hash_descriptor[hash_id].hashsize; + unsigned long v = hash_descriptor[hash_id].blocksize; + unsigned long c = (outlen + u - 1) / u; + unsigned long Slen = ((saltlen + v - 1) / v) * v; + unsigned long Plen = ((pwlen + v - 1) / v) * v; + unsigned long k = (Plen + Slen) / v; + unsigned long Alen, keylen = 0; + unsigned int tmp, i, j, n; + unsigned char ch; + unsigned char D[MAXBLOCKSIZE], A[MAXBLOCKSIZE], B[MAXBLOCKSIZE]; + unsigned char *I, *key; + int err = CRYPT_ERROR; + + LTC_ARGCHK(pw != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + + key = XMALLOC(u * c); + I = XMALLOC(Plen + Slen); + if (key == NULL || I == NULL) goto DONE; + zeromem(key, u * c); + + for (i = 0; i < v; i++) D[i] = purpose; /* D - diversifier */ + for (i = 0; i < Slen; i++) I[i] = salt[i % saltlen]; + for (i = 0; i < Plen; i++) I[Slen + i] = pw[i % pwlen]; /* I = Salt || Pass */ + + for (i = 0; i < c; i++) { + Alen = sizeof(A); + err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */ + if (err != CRYPT_OK) goto DONE; + for (j = 1; j < iterations; j++) { + err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */ + if (err != CRYPT_OK) goto DONE; + } + /* fill buffer B with A */ + for (j = 0; j < v; j++) B[j] = A[j % Alen]; + /* B += 1 */ + for (j = v; j > 0; j--) { + if (++B[j - 1] != 0) break; + } + /* I_n += B */ + for (n = 0; n < k; n++) { + ch = 0; + for (j = v; j > 0; j--) { + tmp = I[n * v + j - 1] + B[j - 1] + ch; + ch = (unsigned char)((tmp >> 8) & 0xFF); + I[n * v + j - 1] = (unsigned char)(tmp & 0xFF); + } + } + /* store derived key block */ + XMEMCPY(&key[keylen], A, Alen); + keylen += Alen; + } + + XMEMCPY(out, key, outlen); + err = CRYPT_OK; +DONE: + if (I) { + zeromem(I, Plen + Slen); + XFREE(I); + } + if (key) { + zeromem(key, u * c); + XFREE(key); + } + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c b/deps/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c new file mode 100644 index 0000000..bcf2023 --- /dev/null +++ b/deps/libtomcrypt/src/misc/pkcs12/pkcs12_utf8_to_utf16.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_PKCS_12 + +int pkcs12_utf8_to_utf16(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) { + unsigned long len = 0; + const unsigned char* in_end = in + inlen; + const ulong32 offset[6] = { + 0x00000000UL, 0x00003080UL, 0x000E2080UL, + 0x03C82080UL, 0xFA082080UL, 0x82082080UL + }; + int err = CRYPT_ERROR; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + while (in < in_end) { + ulong32 ch = 0; + unsigned short extra = 0; /* 0 */ + if (*in >= 192) extra++; /* 1 */ + if (*in >= 224) extra++; /* 2 */ + if (*in >= 240) extra++; /* 3 */ + if (*in >= 248) extra++; /* 4 */ + if (*in >= 252) extra++; /* 5 */ + if (in + extra >= in_end) goto ERROR; + switch (extra) { + case 5: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 4: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 3: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 2: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 1: ch += *in++; ch <<= 6; + /* FALLTHROUGH */ + case 0: ch += *in++; + } + ch -= offset[extra]; + if (ch > 0xFFFF) goto ERROR; + if (*outlen >= len + 2) { + out[len] = (unsigned short)((ch >> 8) & 0xFF); + out[len + 1] = (unsigned char)(ch & 0xFF); + } + len += 2; + } + + err = len > *outlen ? CRYPT_BUFFER_OVERFLOW : CRYPT_OK; + *outlen = len; +ERROR: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c b/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c new file mode 100644 index 0000000..ea9c19c --- /dev/null +++ b/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_1.c @@ -0,0 +1,185 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_5_1.c + PKCS #5, Algorithm #1, Tom St Denis +*/ +#ifdef LTC_PKCS_5 +/** + Execute PKCS #5 v1 in strict or OpenSSL EVP_BytesToKey()-compat mode. + + PKCS#5 v1 specifies that the output key length can be no larger than + the hash output length. OpenSSL unilaterally extended that by repeating + the hash process on a block-by-block basis for as long as needed to make + bigger keys. If you want to be compatible with KDF for e.g. "openssl enc", + you'll want that. + + If you want strict PKCS behavior, turn openssl_compat off. Or (more + likely), use one of the convenience functions below. + + @param password The password (or key) + @param password_len The length of the password (octet) + @param salt The salt (or nonce) which is 8 octets long + @param iteration_count The PKCS #5 v1 iteration count + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @param openssl_compat [in] Whether or not to grow the key to the buffer size ala OpenSSL + @return CRYPT_OK if successful +*/ +static int s_pkcs_5_alg1_common(const unsigned char *password, + unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen, + int openssl_compat) +{ + int err; + unsigned long x; + hash_state *md; + unsigned char *buf; + /* Storage vars in case we need to support > hashsize (OpenSSL compat) */ + unsigned long block = 0, iter; + /* How many bytes to put in the outbut buffer (convenience calc) */ + unsigned long outidx = 0, nb = 0; + + LTC_ARGCHK(password != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if (iteration_count <= 0) { + return CRYPT_INVALID_ARG; + } + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* allocate memory */ + md = XMALLOC(sizeof(hash_state)); + buf = XMALLOC(MAXBLOCKSIZE); + if (md == NULL || buf == NULL) { + if (md != NULL) { + XFREE(md); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + while(block * hash_descriptor[hash_idx].hashsize < *outlen) { + + /* hash initial (maybe previous hash) + password + salt */ + if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + /* in OpenSSL mode, we first hash the previous result for blocks 2-n */ + if (openssl_compat && block) { + if ((err = hash_descriptor[hash_idx].process(md, buf, hash_descriptor[hash_idx].hashsize)) != CRYPT_OK) { + goto LBL_ERR; + } + } + if ((err = hash_descriptor[hash_idx].process(md, password, password_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(md, salt, 8)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { + goto LBL_ERR; + } + + iter = iteration_count; + while (--iter) { + /* code goes here. */ + x = MAXBLOCKSIZE; + if ((err = hash_memory(hash_idx, buf, hash_descriptor[hash_idx].hashsize, buf, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* limit the size of the copy to however many bytes we have left in + the output buffer (and how many bytes we have to copy) */ + outidx = block*hash_descriptor[hash_idx].hashsize; + nb = hash_descriptor[hash_idx].hashsize; + if(outidx+nb > *outlen) { + nb = *outlen - outidx; + } + if(nb > 0) { + XMEMCPY(out+outidx, buf, nb); + } + + block++; + if (!openssl_compat) { + break; + } + } + /* In strict mode, we always return the hashsize, in compat we filled it + as much as was requested, so we leave it alone. */ + if(!openssl_compat) { + *outlen = hash_descriptor[hash_idx].hashsize; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, MAXBLOCKSIZE); + zeromem(md, sizeof(hash_state)); +#endif + + XFREE(buf); + XFREE(md); + + return err; +} + +/** + Execute PKCS #5 v1 - Strict mode (no OpenSSL-compatible extension) + @param password The password (or key) + @param password_len The length of the password (octet) + @param salt The salt (or nonce) which is 8 octets long + @param iteration_count The PKCS #5 v1 iteration count + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @return CRYPT_OK if successful +*/ +int pkcs_5_alg1(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, + hash_idx, out, outlen, 0); +} + +/** + Execute PKCS #5 v1 - OpenSSL-extension-compatible mode + + Use this one if you need to derive keys as "openssl enc" does by default. + OpenSSL (for better or worse), uses MD5 as the hash and iteration_count=1. + @param password The password (or key) + @param password_len The length of the password (octet) + @param salt The salt (or nonce) which is 8 octets long + @param iteration_count The PKCS #5 v1 iteration count + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @return CRYPT_OK if successful +*/ +int pkcs_5_alg1_openssl(const unsigned char *password, + unsigned long password_len, + const unsigned char *salt, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + return s_pkcs_5_alg1_common(password, password_len, salt, iteration_count, + hash_idx, out, outlen, 1); +} + +#endif diff --git a/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c b/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c new file mode 100644 index 0000000..61ebd00 --- /dev/null +++ b/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_2.c @@ -0,0 +1,121 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_5_2.c + PKCS #5, Algorithm #2, Tom St Denis +*/ +#ifdef LTC_PKCS_5 + +/** + Execute PKCS #5 v2 + @param password The input password (or key) + @param password_len The length of the password (octets) + @param salt The salt (or nonce) + @param salt_len The length of the salt (octets) + @param iteration_count # of iterations desired for PKCS #5 v2 [read specs for more] + @param hash_idx The index of the hash desired + @param out [out] The destination for this algorithm + @param outlen [in/out] The max size and resulting size of the algorithm output + @return CRYPT_OK if successful +*/ +int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, + const unsigned char *salt, unsigned long salt_len, + int iteration_count, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err, itts; + ulong32 blkno; + unsigned long stored, left, x, y; + unsigned char *buf[2]; + hmac_state *hmac; + + LTC_ARGCHK(password != NULL); + LTC_ARGCHK(salt != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if (iteration_count <= 0) { + return CRYPT_INVALID_ARG; + } + + /* test hash IDX */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + buf[0] = XMALLOC(MAXBLOCKSIZE * 2); + hmac = XMALLOC(sizeof(hmac_state)); + if (hmac == NULL || buf[0] == NULL) { + if (hmac != NULL) { + XFREE(hmac); + } + if (buf[0] != NULL) { + XFREE(buf[0]); + } + return CRYPT_MEM; + } + /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ + buf[1] = buf[0] + MAXBLOCKSIZE; + + left = *outlen; + blkno = 1; + stored = 0; + while (left != 0) { + /* process block number blkno */ + zeromem(buf[0], MAXBLOCKSIZE*2); + + /* store current block number and increment for next pass */ + STORE32H(blkno, buf[1]); + ++blkno; + + /* get PRF(P, S||int(blkno)) */ + if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { + goto LBL_ERR; + } + x = MAXBLOCKSIZE; + if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* now compute repeated and XOR it in buf[1] */ + XMEMCPY(buf[1], buf[0], x); + for (itts = 1; itts < iteration_count; ++itts) { + if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { + goto LBL_ERR; + } + for (y = 0; y < x; y++) { + buf[1][y] ^= buf[0][y]; + } + } + + /* now emit upto x bytes of buf[1] to output */ + for (y = 0; y < x && left != 0; ++y) { + out[stored++] = buf[1][y]; + --left; + } + } + *outlen = stored; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf[0], MAXBLOCKSIZE*2); + zeromem(hmac, sizeof(hmac_state)); +#endif + + XFREE(hmac); + XFREE(buf[0]); + + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c b/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c new file mode 100644 index 0000000..73bc4a1 --- /dev/null +++ b/deps/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c @@ -0,0 +1,221 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file hkdf_test.c + PKCS #5 support, self-test, Steffen Jaeckel +*/ + +#ifdef LTC_PKCS_5 + +/* + TEST CASES SOURCE: + +Internet Engineering Task Force (IETF) S. Josefsson +Request for Comments: 6070 SJD AB +Category: Informational January 2011 +ISSN: 2070-1721 +*/ + +/** + PKCS #5 self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int pkcs_5_test (void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + + typedef struct { + const char* P; + unsigned long P_len; + const char* S; + unsigned long S_len; + int c; + unsigned long dkLen; + unsigned char DK[40]; + } case_item; + + static const case_item cases_5_2[] = { + { + "password", + 8, + "salt", + 4, + 1, + 20, + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 } + }, + { + "password", + 8, + "salt", + 4, + 2, + 20, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 } + }, +#ifdef LTC_TEST_EXT + { + "password", + 8, + "salt", + 4, + 4096, + 20, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 } + }, + { + "password", + 8, + "salt", + 4, + 16777216, + 20, + { 0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4, + 0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c, + 0x26, 0x34, 0xe9, 0x84 } + }, + { + "passwordPASSWORDpassword", + 25, + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + 36, + 4096, + 25, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 } + }, + { + "pass\0word", + 9, + "sa\0lt", + 5, + 4096, + 16, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 } + }, +#endif /* LTC_TEST_EXT */ + }; + + static const case_item cases_5_1[] = { + { + "password", + 8, + "saltsalt", /* must be 8 octects */ + 8, /* ignored by alg1 */ + 1, + 20, + { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, + 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } + }, + }; + + static const case_item cases_5_1o[] = { + { + "password", + 8, + "saltsalt", /* must be 8 octects */ + 8, /* ignored by alg1_openssl */ + 1, + 20, + { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, + 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44 } + + }, + { + "password", + 8, + "saltsalt", /* must be 8 octects */ + 8, /* ignored by alg1_openssl */ + 1, + 30, + { 0xca, 0xb8, 0x6d, 0xd6, 0x26, 0x17, 0x10, 0x89, 0x1e, 0x8c, + 0xb5, 0x6e, 0xe3, 0x62, 0x56, 0x91, 0xa7, 0x5d, 0xf3, 0x44, + 0xf0, 0xbf, 0xf4, 0xc1, 0x2c, 0xf3, 0x59, 0x6f, 0xc0, 0x0b } + + } + }; + + unsigned char DK[40]; + unsigned long dkLen; + int i, err; + int tested=0, failed=0; + int hash = find_hash("sha1"); + if (hash == -1) + { +#ifdef LTC_TEST_DBG + printf("PKCS#5 test failed: 'sha1' hash not found\n"); +#endif + return CRYPT_ERROR; + } + + /* testing alg 2 */ + for(i=0; i < (int)(sizeof(cases_5_2) / sizeof(cases_5_2[0])); i++) { + ++tested; + dkLen = cases_5_2[i].dkLen; + if((err = pkcs_5_alg2((unsigned char*)cases_5_2[i].P, cases_5_2[i].P_len, + (unsigned char*)cases_5_2[i].S, cases_5_2[i].S_len, + cases_5_2[i].c, hash, + DK, &dkLen)) != CRYPT_OK) { +#ifdef LTC_TEST_DBG + printf("\npkcs_5_alg2() #%d: Failed/1 (%s)\n", i, error_to_string(err)); +#endif + ++failed; + } + else if (compare_testvector(DK, dkLen, cases_5_2[i].DK, cases_5_2[i].dkLen, "PKCS#5_2", i)) { + ++failed; + } + } + + /* testing alg 1 */ + for(i=0; i < (int)(sizeof(cases_5_1) / sizeof(case_item)); i++, tested++) { + dkLen = cases_5_1[i].dkLen; + if((err = pkcs_5_alg1((unsigned char*)cases_5_1[i].P, cases_5_1[i].P_len, + (unsigned char*)cases_5_1[i].S, + cases_5_1[i].c, hash, + DK, &dkLen)) != CRYPT_OK) { +#ifdef LTC_TEST_DBG + printf("\npkcs_5_alg1() #%d: Failed/1 (%s)\n", i, error_to_string(err)); +#endif + ++failed; + } + else if (compare_testvector(DK, dkLen, cases_5_1[i].DK, cases_5_1[i].dkLen, "PKCS#5_1", i)) { + ++failed; + } + } + + /* testing alg 1_openssl */ + for(i = 0; i < (int)(sizeof(cases_5_1o) / sizeof(cases_5_1o[0])); i++, tested++) { + dkLen = cases_5_1o[i].dkLen; + if ((err = pkcs_5_alg1_openssl((unsigned char*)cases_5_1o[i].P, cases_5_1o[i].P_len, + (unsigned char*)cases_5_1o[i].S, + cases_5_1o[i].c, hash, + DK, &dkLen)) != CRYPT_OK) { +#ifdef LTC_TEST_DBG + printf("\npkcs_5_alg1_openssl() #%d: Failed/1 (%s)\n", i, error_to_string(err)); +#endif + ++failed; + } + else if (compare_testvector(DK, dkLen, cases_5_1o[i].DK, cases_5_1o[i].dkLen, "PKCS#5_1o", i)) { + ++failed; + } + } + + return (failed != 0) ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK; + #endif +} + +#endif + diff --git a/deps/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c b/deps/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c new file mode 100644 index 0000000..3aa0e08 --- /dev/null +++ b/deps/libtomcrypt/src/misc/ssh/ssh_decode_sequence_multi.c @@ -0,0 +1,165 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file ssh_decode_sequence_multi.c + SSH data type representation as per RFC4251, Russ Williams +*/ + +#ifdef LTC_SSH + +/** + Decode a SSH sequence using a VA list + @param in The input buffer + @param inlen [in/out] The length of the input buffer and on output the amount of decoded data + @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long*) + @return CRYPT_OK on success +*/ +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) +{ + int err; + va_list args; + ssh_data_type type; + void *vdata; + unsigned char *cdata; + char *sdata; + ulong32 *u32data; + ulong64 *u64data; + unsigned long *bufsize; + ulong32 size; + unsigned long remaining; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + + remaining = *inlen; + /* Decode values from buffer */ + va_start(args, inlen); + while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { + /* Size of length field */ + if (type == LTC_SSHDATA_STRING || + type == LTC_SSHDATA_NAMELIST || + type == LTC_SSHDATA_MPINT) + { + /* Check we'll not read too far */ + if (remaining < 4) { + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + } + + /* Calculate (or read) length of data */ + size = 0xFFFFFFFFU; + switch (type) { + case LTC_SSHDATA_BYTE: + case LTC_SSHDATA_BOOLEAN: + size = 1; + break; + case LTC_SSHDATA_UINT32: + size = 4; + break; + case LTC_SSHDATA_UINT64: + size = 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + case LTC_SSHDATA_MPINT: + LOAD32H(size, in); + in += 4; + remaining -= 4; + break; + + case LTC_SSHDATA_EOL: + /* Should never get here */ + err = CRYPT_INVALID_ARG; + goto error; + } + + /* Check we'll not read too far */ + if (remaining < size) { + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } else { + remaining -= size; + } + + vdata = va_arg(args, void*); + if (vdata == NULL) { + err = CRYPT_INVALID_ARG; + goto error; + } + + /* Read data */ + switch (type) { + case LTC_SSHDATA_BYTE: + cdata = vdata; + *cdata = *in++; + break; + case LTC_SSHDATA_BOOLEAN: + cdata = vdata; + /* + The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be + interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. + */ + *cdata = (*in++)?1:0; + break; + case LTC_SSHDATA_UINT32: + u32data = vdata; + LOAD32H(*u32data, in); + in += 4; + break; + case LTC_SSHDATA_UINT64: + u64data = vdata; + LOAD64H(*u64data, in); + in += 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + sdata = vdata; + bufsize = va_arg(args, unsigned long*); + if (bufsize == NULL) { + err = CRYPT_INVALID_ARG; + goto error; + } + if (size + 1 >= *bufsize) { + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + if (size > 0) { + XMEMCPY(sdata, (const char *)in, size); + } + sdata[size] = '\0'; + *bufsize = size; + in += size; + break; + case LTC_SSHDATA_MPINT: + if (size == 0) { + if ((err = mp_set(vdata, 0)) != CRYPT_OK) { goto error; } + } else if ((in[0] & 0x80) != 0) { + /* Negative number - not supported */ + err = CRYPT_INVALID_PACKET; + goto error; + } else { + if ((err = mp_read_unsigned_bin(vdata, (unsigned char *)in, size)) != CRYPT_OK) { goto error; } + } + in += size; + break; + + case LTC_SSHDATA_EOL: + /* Should never get here */ + err = CRYPT_INVALID_ARG; + goto error; + } + } + err = CRYPT_OK; + + *inlen -= remaining; + +error: + va_end(args); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c b/deps/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c new file mode 100644 index 0000000..d2be689 --- /dev/null +++ b/deps/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c @@ -0,0 +1,158 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + +/** + @file ssh_encode_sequence_multi.c + SSH data type representation as per RFC4251, Russ Williams +*/ + +#ifdef LTC_SSH + +/** + Encode a SSH sequence using a VA list + @param out [out] Destination for data + @param outlen [in/out] Length of buffer and resulting length of output + @remark <...> is of the form (int, ) except for string&name-list (int, void*, unsigned long) + @return CRYPT_OK on success +*/ +int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) +{ + int err; + va_list args; + ulong32 size; + ssh_data_type type; + void *vdata; + const char *sdata; + int idata; + ulong32 u32data; + ulong64 u64data; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* Check values and calculate output size */ + size = 0; + va_start(args, outlen); + while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { + switch (type) { + case LTC_SSHDATA_BYTE: + case LTC_SSHDATA_BOOLEAN: /* Both stored as 1 byte */ + LTC_UNUSED_PARAM( va_arg(args, int) ); + size++; + break; + case LTC_SSHDATA_UINT32: + LTC_UNUSED_PARAM( va_arg(args, ulong32) ); + size += 4; + break; + case LTC_SSHDATA_UINT64: + LTC_UNUSED_PARAM( va_arg(args, ulong64) ); + size += 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + LTC_UNUSED_PARAM( va_arg(args, char*) ); + size += va_arg(args, unsigned long); + size += 4; + break; + case LTC_SSHDATA_MPINT: + vdata = va_arg(args, void*); + /* Calculate size */ + size += 4; + if (mp_iszero(vdata) != LTC_MP_YES) { + size += mp_unsigned_bin_size(vdata); + if ((mp_count_bits(vdata) & 7) == 0) size++; /* Zero padding if high bit set */ + } + break; + + case LTC_SSHDATA_EOL: /* Should never get here */ + err = CRYPT_INVALID_ARG; + goto error; + } + } + va_end(args); + + /* Check we have sufficient space */ + if (*outlen < size) { + *outlen = size; + err = CRYPT_BUFFER_OVERFLOW; + goto errornoargs; + } + *outlen = size; + + /* Encode values into buffer */ + va_start(args, outlen); + while ((type = (ssh_data_type)va_arg(args, int)) != LTC_SSHDATA_EOL) { + switch (type) { + case LTC_SSHDATA_BYTE: + idata = va_arg(args, int); + + *out++ = (unsigned char)(idata & 255); + break; + case LTC_SSHDATA_BOOLEAN: + idata = va_arg(args, int); + + /* + The value 0 represents FALSE, and the value 1 represents TRUE. All non-zero values MUST be + interpreted as TRUE; however, applications MUST NOT store values other than 0 and 1. + */ + *out++ = (idata)?1:0; + break; + case LTC_SSHDATA_UINT32: + u32data = va_arg(args, ulong32); + STORE32H(u32data, out); + out += 4; + break; + case LTC_SSHDATA_UINT64: + u64data = va_arg(args, ulong64); + STORE64H(u64data, out); + out += 8; + break; + case LTC_SSHDATA_STRING: + case LTC_SSHDATA_NAMELIST: + sdata = va_arg(args, char*); + size = va_arg(args, unsigned long); + STORE32H(size, out); + out += 4; + XMEMCPY(out, sdata, size); + out += size; + break; + case LTC_SSHDATA_MPINT: + vdata = va_arg(args, void*); + if (mp_iszero(vdata) == LTC_MP_YES) { + STORE32H(0, out); + out += 4; + } else { + size = mp_unsigned_bin_size(vdata); + if ((mp_count_bits(vdata) & 7) == 0) { + /* Zero padding if high bit set */ + STORE32H(size+1, out); + out += 4; + *out++ = 0; + } else { + STORE32H(size, out); + out += 4; + } + if ((err = mp_to_unsigned_bin(vdata, out)) != CRYPT_OK) { + err = CRYPT_ERROR; + goto error; + } + out += size; + } + break; + + case LTC_SSHDATA_EOL: /* Should never get here */ + err = CRYPT_INVALID_ARG; + goto error; + } + } + err = CRYPT_OK; + +error: + va_end(args); +errornoargs: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/misc/zeromem.c b/deps/libtomcrypt/src/misc/zeromem.c new file mode 100644 index 0000000..7d14994 --- /dev/null +++ b/deps/libtomcrypt/src/misc/zeromem.c @@ -0,0 +1,22 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file zeromem.c + Zero a block of memory, Tom St Denis +*/ + +/** + Zero a block of memory + @param out The destination of the area to zero + @param outlen The length of the area to zero (octets) +*/ +void zeromem(volatile void *out, size_t outlen) +{ + volatile char *mem = out; + LTC_ARGCHKVD(out != NULL); + while (outlen-- > 0) { + *mem++ = '\0'; + } +} diff --git a/deps/libtomcrypt/src/modes/cbc/cbc_decrypt.c b/deps/libtomcrypt/src/modes/cbc/cbc_decrypt.c new file mode 100644 index 0000000..5fa3ee3 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cbc/cbc_decrypt.c @@ -0,0 +1,84 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_decrypt.c + CBC implementation, encrypt block, Tom St Denis +*/ + + +#ifdef LTC_CBC_MODE + +/** + CBC decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len The number of bytes to process (must be multiple of block length) + @param cbc CBC state + @return CRYPT_OK if successful +*/ +int cbc_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CBC *cbc) +{ + int x, err; + unsigned char tmp[16]; +#ifdef LTC_FAST + LTC_FAST_TYPE tmpy; +#else + unsigned char tmpy; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cbc != NULL); + + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen valid? */ + if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV) || cbc->blocklen > (int)sizeof(tmp)) { + return CRYPT_INVALID_ARG; + } + + if (len % cbc->blocklen) { + return CRYPT_INVALID_ARG; + } +#ifdef LTC_FAST + if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + if (cipher_descriptor[cbc->cipher].accel_cbc_decrypt != NULL) { + return cipher_descriptor[cbc->cipher].accel_cbc_decrypt(ct, pt, len / cbc->blocklen, cbc->IV, &cbc->key); + } + while (len) { + /* decrypt */ + if ((err = cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key)) != CRYPT_OK) { + return err; + } + + /* xor IV against plaintext */ +#if defined(LTC_FAST) + for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { + tmpy = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^ *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)tmp + x)); + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) = tmpy; + } +#else + for (x = 0; x < cbc->blocklen; x++) { + tmpy = tmp[x] ^ cbc->IV[x]; + cbc->IV[x] = ct[x]; + pt[x] = tmpy; + } +#endif + + ct += cbc->blocklen; + pt += cbc->blocklen; + len -= cbc->blocklen; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/cbc/cbc_done.c b/deps/libtomcrypt/src/modes/cbc/cbc_done.c new file mode 100644 index 0000000..985551f --- /dev/null +++ b/deps/libtomcrypt/src/modes/cbc/cbc_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_done.c + CBC implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_CBC_MODE + +/** Terminate the chain + @param cbc The CBC chain to terminate + @return CRYPT_OK on success +*/ +int cbc_done(symmetric_CBC *cbc) +{ + int err; + LTC_ARGCHK(cbc != NULL); + + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[cbc->cipher].done(&cbc->key); + return CRYPT_OK; +} + + + +#endif diff --git a/deps/libtomcrypt/src/modes/cbc/cbc_encrypt.c b/deps/libtomcrypt/src/modes/cbc/cbc_encrypt.c new file mode 100644 index 0000000..50d91c4 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cbc/cbc_encrypt.c @@ -0,0 +1,85 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_encrypt.c + CBC implementation, encrypt block, Tom St Denis +*/ + + +#ifdef LTC_CBC_MODE + +/** + CBC encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len The number of bytes to process (must be multiple of block length) + @param cbc CBC state + @return CRYPT_OK if successful +*/ +int cbc_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CBC *cbc) +{ + int x, err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cbc != NULL); + + if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen valid? */ + if (cbc->blocklen < 1 || cbc->blocklen > (int)sizeof(cbc->IV)) { + return CRYPT_INVALID_ARG; + } + + if (len % cbc->blocklen) { + return CRYPT_INVALID_ARG; + } +#ifdef LTC_FAST + if (cbc->blocklen % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + if (cipher_descriptor[cbc->cipher].accel_cbc_encrypt != NULL) { + return cipher_descriptor[cbc->cipher].accel_cbc_encrypt(pt, ct, len / cbc->blocklen, cbc->IV, &cbc->key); + } + while (len) { + /* xor IV against plaintext */ +#if defined(LTC_FAST) + for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) ^= *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)); + } +#else + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] ^= pt[x]; + } +#endif + + /* encrypt */ + if ((err = cipher_descriptor[cbc->cipher].ecb_encrypt(cbc->IV, ct, &cbc->key)) != CRYPT_OK) { + return err; + } + + /* store IV [ciphertext] for a future block */ +#if defined(LTC_FAST) + for (x = 0; x < cbc->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)cbc->IV + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)); + } +#else + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] = ct[x]; + } +#endif + + ct += cbc->blocklen; + pt += cbc->blocklen; + len -= cbc->blocklen; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/cbc/cbc_getiv.c b/deps/libtomcrypt/src/modes/cbc/cbc_getiv.c new file mode 100644 index 0000000..7af2cf1 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cbc/cbc_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_getiv.c + CBC implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CBC_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param cbc The CBC state + @return CRYPT_OK if successful +*/ +int cbc_getiv(unsigned char *IV, unsigned long *len, const symmetric_CBC *cbc) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(cbc != NULL); + if ((unsigned long)cbc->blocklen > *len) { + *len = cbc->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, cbc->IV, cbc->blocklen); + *len = cbc->blocklen; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/cbc/cbc_setiv.c b/deps/libtomcrypt/src/modes/cbc/cbc_setiv.c new file mode 100644 index 0000000..a9e91c3 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cbc/cbc_setiv.c @@ -0,0 +1,32 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_setiv.c + CBC implementation, set IV, Tom St Denis +*/ + + +#ifdef LTC_CBC_MODE + +/** + Set an initialization vector + @param IV The initialization vector + @param len The length of the vector (in octets) + @param cbc The CBC state + @return CRYPT_OK if successful +*/ +int cbc_setiv(const unsigned char *IV, unsigned long len, symmetric_CBC *cbc) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(cbc != NULL); + if (len != (unsigned long)cbc->blocklen) { + return CRYPT_INVALID_ARG; + } + XMEMCPY(cbc->IV, IV, len); + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/modes/cbc/cbc_start.c b/deps/libtomcrypt/src/modes/cbc/cbc_start.c new file mode 100644 index 0000000..4156739 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cbc/cbc_start.c @@ -0,0 +1,50 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cbc_start.c + CBC implementation, start chain, Tom St Denis +*/ + +#ifdef LTC_CBC_MODE + +/** + Initialize a CBC context + @param cipher The index of the cipher desired + @param IV The initialization vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param cbc The CBC state to initialize + @return CRYPT_OK if successful +*/ +int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CBC *cbc) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(cbc != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* setup cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) { + return err; + } + + /* copy IV */ + cbc->blocklen = cipher_descriptor[cipher].block_length; + cbc->cipher = cipher; + for (x = 0; x < cbc->blocklen; x++) { + cbc->IV[x] = IV[x]; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/cfb/cfb_decrypt.c b/deps/libtomcrypt/src/modes/cfb/cfb_decrypt.c new file mode 100644 index 0000000..b61dc03 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cfb/cfb_decrypt.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_decrypt.c + CFB implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + CFB decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param cfb CFB state + @return CRYPT_OK if successful +*/ +int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || + cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (cfb->padlen == cfb->blocklen) { + if ((err = cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) { + return err; + } + cfb->padlen = 0; + } + cfb->pad[cfb->padlen] = *ct; + *pt = *ct ^ cfb->IV[cfb->padlen]; + ++pt; + ++ct; + ++(cfb->padlen); + } + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/modes/cfb/cfb_done.c b/deps/libtomcrypt/src/modes/cfb/cfb_done.c new file mode 100644 index 0000000..8f8f9cd --- /dev/null +++ b/deps/libtomcrypt/src/modes/cfb/cfb_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_done.c + CFB implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** Terminate the chain + @param cfb The CFB chain to terminate + @return CRYPT_OK on success +*/ +int cfb_done(symmetric_CFB *cfb) +{ + int err; + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[cfb->cipher].done(&cfb->key); + return CRYPT_OK; +} + + + +#endif diff --git a/deps/libtomcrypt/src/modes/cfb/cfb_encrypt.c b/deps/libtomcrypt/src/modes/cfb/cfb_encrypt.c new file mode 100644 index 0000000..315a4f7 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cfb/cfb_encrypt.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_encrypt.c + CFB implementation, encrypt data, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + CFB encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param cfb CFB state + @return CRYPT_OK if successful +*/ +int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) || + cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (cfb->padlen == cfb->blocklen) { + if ((err = cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key)) != CRYPT_OK) { + return err; + } + cfb->padlen = 0; + } + cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]); + ++pt; + ++ct; + ++(cfb->padlen); + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/cfb/cfb_getiv.c b/deps/libtomcrypt/src/modes/cfb/cfb_getiv.c new file mode 100644 index 0000000..9dc2e86 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cfb/cfb_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_getiv.c + CFB implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param cfb The CFB state + @return CRYPT_OK if successful +*/ +int cfb_getiv(unsigned char *IV, unsigned long *len, const symmetric_CFB *cfb) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(cfb != NULL); + if ((unsigned long)cfb->blocklen > *len) { + *len = cfb->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, cfb->IV, cfb->blocklen); + *len = cfb->blocklen; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/cfb/cfb_setiv.c b/deps/libtomcrypt/src/modes/cfb/cfb_setiv.c new file mode 100644 index 0000000..c5481ad --- /dev/null +++ b/deps/libtomcrypt/src/modes/cfb/cfb_setiv.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_setiv.c + CFB implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_CFB_MODE + +/** + Set an initialization vector + @param IV The initialization vector + @param len The length of the vector (in octets) + @param cfb The CFB state + @return CRYPT_OK if successful +*/ +int cfb_setiv(const unsigned char *IV, unsigned long len, symmetric_CFB *cfb) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)cfb->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* force next block */ + cfb->padlen = 0; + return cipher_descriptor[cfb->cipher].ecb_encrypt(IV, cfb->IV, &cfb->key); +} + +#endif + diff --git a/deps/libtomcrypt/src/modes/cfb/cfb_start.c b/deps/libtomcrypt/src/modes/cfb/cfb_start.c new file mode 100644 index 0000000..cd5ffe7 --- /dev/null +++ b/deps/libtomcrypt/src/modes/cfb/cfb_start.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file cfb_start.c + CFB implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_CFB_MODE + +/** + Initialize a CFB context + @param cipher The index of the cipher desired + @param IV The initialization vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param cfb The CFB state to initialize + @return CRYPT_OK if successful +*/ +int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_CFB *cfb) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(cfb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + + /* copy data */ + cfb->cipher = cipher; + cfb->blocklen = cipher_descriptor[cipher].block_length; + for (x = 0; x < cfb->blocklen; x++) { + cfb->IV[x] = IV[x]; + } + + /* init the cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) { + return err; + } + + /* encrypt the IV */ + cfb->padlen = 0; + return cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->IV, cfb->IV, &cfb->key); +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ctr/ctr_decrypt.c b/deps/libtomcrypt/src/modes/ctr/ctr_decrypt.c new file mode 100644 index 0000000..a55a08f --- /dev/null +++ b/deps/libtomcrypt/src/modes/ctr/ctr_decrypt.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_decrypt.c + CTR implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + CTR decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param ctr CTR state + @return CRYPT_OK if successful +*/ +int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ctr != NULL); + + return ctr_encrypt(ct, pt, len, ctr); +} + +#endif + diff --git a/deps/libtomcrypt/src/modes/ctr/ctr_done.c b/deps/libtomcrypt/src/modes/ctr/ctr_done.c new file mode 100644 index 0000000..f93d971 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ctr/ctr_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_done.c + CTR implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** Terminate the chain + @param ctr The CTR chain to terminate + @return CRYPT_OK on success +*/ +int ctr_done(symmetric_CTR *ctr) +{ + int err; + LTC_ARGCHK(ctr != NULL); + + if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ctr->cipher].done(&ctr->key); + return CRYPT_OK; +} + + + +#endif diff --git a/deps/libtomcrypt/src/modes/ctr/ctr_encrypt.c b/deps/libtomcrypt/src/modes/ctr/ctr_encrypt.c new file mode 100644 index 0000000..b8c08f7 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ctr/ctr_encrypt.c @@ -0,0 +1,129 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_encrypt.c + CTR implementation, encrypt data, Tom St Denis +*/ + + +#ifdef LTC_CTR_MODE + +/** + CTR encrypt software implementation + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param ctr CTR state + @return CRYPT_OK if successful +*/ +static int s_ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) +{ + int x, err; + + while (len) { + /* is the pad empty? */ + if (ctr->padlen == ctr->blocklen) { + /* increment counter */ + if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { + /* little-endian */ + for (x = 0; x < ctr->ctrlen; x++) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } else { + /* big-endian */ + for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } + + /* encrypt it */ + if ((err = cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key)) != CRYPT_OK) { + return err; + } + ctr->padlen = 0; + } +#ifdef LTC_FAST + if ((ctr->padlen == 0) && (len >= (unsigned long)ctr->blocklen)) { + for (x = 0; x < ctr->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ct + x)) = *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)pt + x)) ^ + *(LTC_FAST_TYPE_PTR_CAST((unsigned char *)ctr->pad + x)); + } + pt += ctr->blocklen; + ct += ctr->blocklen; + len -= ctr->blocklen; + ctr->padlen = ctr->blocklen; + continue; + } +#endif + *ct++ = *pt++ ^ ctr->pad[ctr->padlen++]; + --len; + } + return CRYPT_OK; +} + +/** + CTR encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param ctr CTR state + @return CRYPT_OK if successful +*/ +int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr) +{ + int err, fr; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ctr != NULL); + + if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if ((ctr->blocklen < 1) || (ctr->blocklen > (int)sizeof(ctr->ctr)) || + (ctr->padlen < 0) || (ctr->padlen > (int)sizeof(ctr->pad))) { + return CRYPT_INVALID_ARG; + } + +#ifdef LTC_FAST + if (ctr->blocklen % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* handle acceleration only if pad is empty, accelerator is present and length is >= a block size */ + if ((cipher_descriptor[ctr->cipher].accel_ctr_encrypt != NULL) && (len >= (unsigned long)ctr->blocklen)) { + if (ctr->padlen < ctr->blocklen) { + fr = ctr->blocklen - ctr->padlen; + if ((err = s_ctr_encrypt(pt, ct, fr, ctr)) != CRYPT_OK) { + return err; + } + pt += fr; + ct += fr; + len -= fr; + } + + if (len >= (unsigned long)ctr->blocklen) { + if ((err = cipher_descriptor[ctr->cipher].accel_ctr_encrypt(pt, ct, len/ctr->blocklen, ctr->ctr, ctr->mode, &ctr->key)) != CRYPT_OK) { + return err; + } + pt += (len / ctr->blocklen) * ctr->blocklen; + ct += (len / ctr->blocklen) * ctr->blocklen; + len %= ctr->blocklen; + } + } + + return s_ctr_encrypt(pt, ct, len, ctr); +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ctr/ctr_getiv.c b/deps/libtomcrypt/src/modes/ctr/ctr_getiv.c new file mode 100644 index 0000000..05277fa --- /dev/null +++ b/deps/libtomcrypt/src/modes/ctr/ctr_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_getiv.c + CTR implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param ctr The CTR state + @return CRYPT_OK if successful +*/ +int ctr_getiv(unsigned char *IV, unsigned long *len, const symmetric_CTR *ctr) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(ctr != NULL); + if ((unsigned long)ctr->blocklen > *len) { + *len = ctr->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, ctr->ctr, ctr->blocklen); + *len = ctr->blocklen; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ctr/ctr_setiv.c b/deps/libtomcrypt/src/modes/ctr/ctr_setiv.c new file mode 100644 index 0000000..be80f1a --- /dev/null +++ b/deps/libtomcrypt/src/modes/ctr/ctr_setiv.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_setiv.c + CTR implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +/** + Set an initialization vector + @param IV The initialization vector + @param len The length of the vector (in octets) + @param ctr The CTR state + @return CRYPT_OK if successful +*/ +int ctr_setiv(const unsigned char *IV, unsigned long len, symmetric_CTR *ctr) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(ctr != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)ctr->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* set IV */ + XMEMCPY(ctr->ctr, IV, len); + + /* force next block */ + ctr->padlen = 0; + return cipher_descriptor[ctr->cipher].ecb_encrypt(IV, ctr->pad, &ctr->key); +} + +#endif + diff --git a/deps/libtomcrypt/src/modes/ctr/ctr_start.c b/deps/libtomcrypt/src/modes/ctr/ctr_start.c new file mode 100644 index 0000000..0ccdfd2 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ctr/ctr_start.c @@ -0,0 +1,89 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_start.c + CTR implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_CTR_MODE + +/** + Initialize a CTR context + @param cipher The index of the cipher desired + @param IV The initialization vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param ctr_mode The counter mode (CTR_COUNTER_LITTLE_ENDIAN or CTR_COUNTER_BIG_ENDIAN) + @param ctr The CTR state to initialize + @return CRYPT_OK if successful +*/ +int ctr_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + int num_rounds, int ctr_mode, + symmetric_CTR *ctr) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ctr != NULL); + + /* bad param? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* ctrlen == counter width */ + ctr->ctrlen = (ctr_mode & 255) ? (ctr_mode & 255) : cipher_descriptor[cipher].block_length; + if (ctr->ctrlen > cipher_descriptor[cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) { + ctr->ctrlen = cipher_descriptor[cipher].block_length - ctr->ctrlen; + } + + /* setup cipher */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) { + return err; + } + + /* copy ctr */ + ctr->blocklen = cipher_descriptor[cipher].block_length; + ctr->cipher = cipher; + ctr->padlen = 0; + ctr->mode = ctr_mode & 0x1000; + for (x = 0; x < ctr->blocklen; x++) { + ctr->ctr[x] = IV[x]; + } + + if (ctr_mode & LTC_CTR_RFC3686) { + /* increment the IV as per RFC 3686 */ + if (ctr->mode == CTR_COUNTER_LITTLE_ENDIAN) { + /* little-endian */ + for (x = 0; x < ctr->ctrlen; x++) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } else { + /* big-endian */ + for (x = ctr->blocklen-1; x >= ctr->ctrlen; x--) { + ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255; + if (ctr->ctr[x] != (unsigned char)0) { + break; + } + } + } + } + + return cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key); +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ctr/ctr_test.c b/deps/libtomcrypt/src/modes/ctr/ctr_test.c new file mode 100644 index 0000000..df7e649 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ctr/ctr_test.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ctr_test.c + CTR implementation, Tests again RFC 3686, Tom St Denis +*/ + +#ifdef LTC_CTR_MODE + +int ctr_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen, msglen; + unsigned char key[32], IV[16], pt[64], ct[64]; + } tests[] = { +/* 128-bit key, 16-byte pt */ +{ + 16, 16, + {0xAE,0x68,0x52,0xF8,0x12,0x10,0x67,0xCC,0x4B,0xF7,0xA5,0x76,0x55,0x77,0xF3,0x9E }, + {0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + {0x53,0x69,0x6E,0x67,0x6C,0x65,0x20,0x62,0x6C,0x6F,0x63,0x6B,0x20,0x6D,0x73,0x67 }, + {0xE4,0x09,0x5D,0x4F,0xB7,0xA7,0xB3,0x79,0x2D,0x61,0x75,0xA3,0x26,0x13,0x11,0xB8 }, +}, + +/* 128-bit key, 36-byte pt */ +{ + 16, 36, + {0x76,0x91,0xBE,0x03,0x5E,0x50,0x20,0xA8,0xAC,0x6E,0x61,0x85,0x29,0xF9,0xA0,0xDC }, + {0x00,0xE0,0x01,0x7B,0x27,0x77,0x7F,0x3F,0x4A,0x17,0x86,0xF0,0x00,0x00,0x00,0x00 }, + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, + 0x20,0x21,0x22,0x23}, + {0xC1,0xCF,0x48,0xA8,0x9F,0x2F,0xFD,0xD9,0xCF,0x46,0x52,0xE9,0xEF,0xDB,0x72,0xD7, + 0x45,0x40,0xA4,0x2B,0xDE,0x6D,0x78,0x36,0xD5,0x9A,0x5C,0xEA,0xAE,0xF3,0x10,0x53, + 0x25,0xB2,0x07,0x2F }, +}, +}; + int idx, err, x; + unsigned char buf[64]; + symmetric_CTR ctr; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = ctr_start(idx, tests[x].IV, tests[x].key, tests[x].keylen, 0, CTR_COUNTER_BIG_ENDIAN|LTC_CTR_RFC3686, &ctr)) != CRYPT_OK) { + return err; + } + if ((err = ctr_encrypt(tests[x].pt, buf, tests[x].msglen, &ctr)) != CRYPT_OK) { + return err; + } + ctr_done(&ctr); + if (compare_testvector(buf, tests[x].msglen, tests[x].ct, tests[x].msglen, "CTR", x)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + + + diff --git a/deps/libtomcrypt/src/modes/ecb/ecb_decrypt.c b/deps/libtomcrypt/src/modes/ecb/ecb_decrypt.c new file mode 100644 index 0000000..3069779 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ecb/ecb_decrypt.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ecb_decrypt.c + ECB implementation, decrypt a block, Tom St Denis +*/ + +#ifdef LTC_ECB_MODE + +/** + ECB decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len The number of octets to process (must be multiple of the cipher block size) + @param ecb ECB state + @return CRYPT_OK if successful +*/ +int ecb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ecb != NULL); + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + if (len % cipher_descriptor[ecb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* check for accel */ + if (cipher_descriptor[ecb->cipher].accel_ecb_decrypt != NULL) { + return cipher_descriptor[ecb->cipher].accel_ecb_decrypt(ct, pt, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key); + } + while (len) { + if ((err = cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key)) != CRYPT_OK) { + return err; + } + pt += cipher_descriptor[ecb->cipher].block_length; + ct += cipher_descriptor[ecb->cipher].block_length; + len -= cipher_descriptor[ecb->cipher].block_length; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ecb/ecb_done.c b/deps/libtomcrypt/src/modes/ecb/ecb_done.c new file mode 100644 index 0000000..e1c0c59 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ecb/ecb_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ecb_done.c + ECB implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_ECB_MODE + +/** Terminate the chain + @param ecb The ECB chain to terminate + @return CRYPT_OK on success +*/ +int ecb_done(symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(ecb != NULL); + + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ecb->cipher].done(&ecb->key); + return CRYPT_OK; +} + + + +#endif diff --git a/deps/libtomcrypt/src/modes/ecb/ecb_encrypt.c b/deps/libtomcrypt/src/modes/ecb/ecb_encrypt.c new file mode 100644 index 0000000..661d994 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ecb/ecb_encrypt.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ecb_encrypt.c + ECB implementation, encrypt a block, Tom St Denis +*/ + +#ifdef LTC_ECB_MODE + +/** + ECB encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len The number of octets to process (must be multiple of the cipher block size) + @param ecb ECB state + @return CRYPT_OK if successful +*/ +int ecb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ecb != NULL); + if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) { + return err; + } + if (len % cipher_descriptor[ecb->cipher].block_length) { + return CRYPT_INVALID_ARG; + } + + /* check for accel */ + if (cipher_descriptor[ecb->cipher].accel_ecb_encrypt != NULL) { + return cipher_descriptor[ecb->cipher].accel_ecb_encrypt(pt, ct, len / cipher_descriptor[ecb->cipher].block_length, &ecb->key); + } + while (len) { + if ((err = cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key)) != CRYPT_OK) { + return err; + } + pt += cipher_descriptor[ecb->cipher].block_length; + ct += cipher_descriptor[ecb->cipher].block_length; + len -= cipher_descriptor[ecb->cipher].block_length; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ecb/ecb_start.c b/deps/libtomcrypt/src/modes/ecb/ecb_start.c new file mode 100644 index 0000000..d5bc28e --- /dev/null +++ b/deps/libtomcrypt/src/modes/ecb/ecb_start.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ecb_start.c + ECB implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_ECB_MODE + +/** + Initialize a ECB context + @param cipher The index of the cipher desired + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param ecb The ECB state to initialize + @return CRYPT_OK if successful +*/ +int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb) +{ + int err; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ecb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + ecb->cipher = cipher; + ecb->blocklen = cipher_descriptor[cipher].block_length; + return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key); +} + +#endif diff --git a/deps/libtomcrypt/src/modes/f8/f8_decrypt.c b/deps/libtomcrypt/src/modes/f8/f8_decrypt.c new file mode 100644 index 0000000..f9e3a54 --- /dev/null +++ b/deps/libtomcrypt/src/modes/f8/f8_decrypt.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f8_decrypt.c + F8 implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + F8 decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param f8 F8 state + @return CRYPT_OK if successful +*/ +int f8_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_F8 *f8) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(f8 != NULL); + return f8_encrypt(ct, pt, len, f8); +} + + +#endif + + diff --git a/deps/libtomcrypt/src/modes/f8/f8_done.c b/deps/libtomcrypt/src/modes/f8/f8_done.c new file mode 100644 index 0000000..7d25b04 --- /dev/null +++ b/deps/libtomcrypt/src/modes/f8/f8_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f8_done.c + F8 implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** Terminate the chain + @param f8 The F8 chain to terminate + @return CRYPT_OK on success +*/ +int f8_done(symmetric_F8 *f8) +{ + int err; + LTC_ARGCHK(f8 != NULL); + + if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[f8->cipher].done(&f8->key); + return CRYPT_OK; +} + + + +#endif diff --git a/deps/libtomcrypt/src/modes/f8/f8_encrypt.c b/deps/libtomcrypt/src/modes/f8/f8_encrypt.c new file mode 100644 index 0000000..671c904 --- /dev/null +++ b/deps/libtomcrypt/src/modes/f8/f8_encrypt.c @@ -0,0 +1,91 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f8_encrypt.c + F8 implementation, encrypt data, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + F8 encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param f8 F8 state + @return CRYPT_OK if successful +*/ +int f8_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_F8 *f8) +{ + int err, x; + unsigned char buf[MAXBLOCKSIZE]; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(f8 != NULL); + if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (f8->blocklen < 0 || f8->blocklen > (int)sizeof(f8->IV) || + f8->padlen < 0 || f8->padlen > (int)sizeof(f8->IV)) { + return CRYPT_INVALID_ARG; + } + + zeromem(buf, sizeof(buf)); + + /* make sure the pad is empty */ + if (f8->padlen == f8->blocklen) { + /* xor of IV, MIV and blockcnt == what goes into cipher */ + STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); + ++(f8->blockcnt); + for (x = 0; x < f8->blocklen; x++) { + f8->IV[x] ^= f8->MIV[x] ^ buf[x]; + } + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { + return err; + } + f8->padlen = 0; + } + +#ifdef LTC_FAST + if (f8->padlen == 0) { + while (len >= (unsigned long)f8->blocklen) { + STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); + ++(f8->blockcnt); + for (x = 0; x < f8->blocklen; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&ct[x])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])); + *(LTC_FAST_TYPE_PTR_CAST(&f8->IV[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&f8->MIV[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&buf[x])); + } + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { + return err; + } + len -= x; + pt += x; + ct += x; + } + } +#endif + + while (len > 0) { + if (f8->padlen == f8->blocklen) { + /* xor of IV, MIV and blockcnt == what goes into cipher */ + STORE32H(f8->blockcnt, (buf+(f8->blocklen-4))); + ++(f8->blockcnt); + for (x = 0; x < f8->blocklen; x++) { + f8->IV[x] ^= f8->MIV[x] ^ buf[x]; + } + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(f8->IV, f8->IV, &f8->key)) != CRYPT_OK) { + return err; + } + f8->padlen = 0; + } + *ct++ = *pt++ ^ f8->IV[f8->padlen++]; + --len; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/f8/f8_getiv.c b/deps/libtomcrypt/src/modes/f8/f8_getiv.c new file mode 100644 index 0000000..1a4e53f --- /dev/null +++ b/deps/libtomcrypt/src/modes/f8/f8_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_getiv.c + F8 implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param f8 The F8 state + @return CRYPT_OK if successful +*/ +int f8_getiv(unsigned char *IV, unsigned long *len, const symmetric_F8 *f8) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(f8 != NULL); + if ((unsigned long)f8->blocklen > *len) { + *len = f8->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, f8->IV, f8->blocklen); + *len = f8->blocklen; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/f8/f8_setiv.c b/deps/libtomcrypt/src/modes/f8/f8_setiv.c new file mode 100644 index 0000000..51a80ab --- /dev/null +++ b/deps/libtomcrypt/src/modes/f8/f8_setiv.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f8_setiv.c + F8 implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_F8_MODE + +/** + Set an initialization vector + @param IV The initialization vector + @param len The length of the vector (in octets) + @param f8 The F8 state + @return CRYPT_OK if successful +*/ +int f8_setiv(const unsigned char *IV, unsigned long len, symmetric_F8 *f8) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(f8 != NULL); + + if ((err = cipher_is_valid(f8->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)f8->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* force next block */ + f8->padlen = 0; + return cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->IV, &f8->key); +} + +#endif + diff --git a/deps/libtomcrypt/src/modes/f8/f8_start.c b/deps/libtomcrypt/src/modes/f8/f8_start.c new file mode 100644 index 0000000..58f126f --- /dev/null +++ b/deps/libtomcrypt/src/modes/f8/f8_start.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f8_start.c + F8 implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_F8_MODE + +/** + Initialize an F8 context + @param cipher The index of the cipher desired + @param IV The initialization vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param salt_key The salting key for the IV + @param skeylen The length of the salting key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param f8 The F8 state to initialize + @return CRYPT_OK if successful +*/ +int f8_start( int cipher, const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *salt_key, int skeylen, + int num_rounds, symmetric_F8 *f8) +{ + int x, err; + unsigned char tkey[MAXBLOCKSIZE]; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(salt_key != NULL); + LTC_ARGCHK(f8 != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + if (cipher_descriptor[cipher].block_length % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* copy details */ + f8->blockcnt = 0; + f8->cipher = cipher; + f8->blocklen = cipher_descriptor[cipher].block_length; + f8->padlen = f8->blocklen; + + /* now get key ^ salt_key [extend salt_ket with 0x55 as required to match length] */ + zeromem(tkey, sizeof(tkey)); + for (x = 0; x < keylen && x < (int)sizeof(tkey); x++) { + tkey[x] = key[x]; + } + for (x = 0; x < skeylen && x < (int)sizeof(tkey); x++) { + tkey[x] ^= salt_key[x]; + } + for (; x < keylen && x < (int)sizeof(tkey); x++) { + tkey[x] ^= 0x55; + } + + /* now encrypt with tkey[0..keylen-1] the IV and use that as the IV */ + if ((err = cipher_descriptor[cipher].setup(tkey, keylen, num_rounds, &f8->key)) != CRYPT_OK) { + return err; + } + + /* encrypt IV */ + if ((err = cipher_descriptor[f8->cipher].ecb_encrypt(IV, f8->MIV, &f8->key)) != CRYPT_OK) { + cipher_descriptor[f8->cipher].done(&f8->key); + return err; + } + zeromem(tkey, sizeof(tkey)); + zeromem(f8->IV, sizeof(f8->IV)); + + /* terminate this cipher */ + cipher_descriptor[f8->cipher].done(&f8->key); + + /* init the cipher */ + return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &f8->key); +} + +#endif diff --git a/deps/libtomcrypt/src/modes/f8/f8_test_mode.c b/deps/libtomcrypt/src/modes/f8/f8_test_mode.c new file mode 100644 index 0000000..7b25175 --- /dev/null +++ b/deps/libtomcrypt/src/modes/f8/f8_test_mode.c @@ -0,0 +1,64 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file f8_test_mode.c + F8 implementation, test, Tom St Denis +*/ + + +#ifdef LTC_F8_MODE + +int f8_test_mode(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const unsigned char key[16] = { 0x23, 0x48, 0x29, 0x00, 0x84, 0x67, 0xbe, 0x18, + 0x6c, 0x3d, 0xe1, 0x4a, 0xae, 0x72, 0xd6, 0x2c }; + static const unsigned char salt[4] = { 0x32, 0xf2, 0x87, 0x0d }; + static const unsigned char IV[16] = { 0x00, 0x6e, 0x5c, 0xba, 0x50, 0x68, 0x1d, 0xe5, + 0x5c, 0x62, 0x15, 0x99, 0xd4, 0x62, 0x56, 0x4a }; + static const unsigned char pt[39] = { 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x72, 0x61, + 0x6e, 0x64, 0x6f, 0x6d, 0x6e, 0x65, 0x73, 0x73, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x6e, 0x65, 0x78, 0x74, 0x20, 0x62, 0x65, 0x73, + 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67 }; + static const unsigned char ct[39] = { 0x01, 0x9c, 0xe7, 0xa2, 0x6e, 0x78, 0x54, 0x01, + 0x4a, 0x63, 0x66, 0xaa, 0x95, 0xd4, 0xee, 0xfd, + 0x1a, 0xd4, 0x17, 0x2a, 0x14, 0xf9, 0xfa, 0xf4, + 0x55, 0xb7, 0xf1, 0xd4, 0xb6, 0x2b, 0xd0, 0x8f, + 0x56, 0x2c, 0x0e, 0xef, 0x7c, 0x48, 0x02 }; + unsigned char buf[39]; + symmetric_F8 f8; + int err, idx; + + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) return CRYPT_NOP; + } + + /* initialize the context */ + if ((err = f8_start(idx, IV, key, sizeof(key), salt, sizeof(salt), 0, &f8)) != CRYPT_OK) { + return err; + } + + /* encrypt block */ + if ((err = f8_encrypt(pt, buf, sizeof(pt), &f8)) != CRYPT_OK) { + f8_done(&f8); + return err; + } + f8_done(&f8); + + /* compare */ + if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "f8", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_decrypt.c b/deps/libtomcrypt/src/modes/lrw/lrw_decrypt.c new file mode 100644 index 0000000..ba3b38a --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_decrypt.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_decrypt.c + LRW_MODE implementation, Decrypt blocks, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + LRW decrypt blocks + @param ct The ciphertext + @param pt [out] The plaintext + @param len The length in octets, must be a multiple of 16 + @param lrw The LRW state +*/ +int lrw_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_LRW *lrw) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(lrw != NULL); + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) { + return cipher_descriptor[lrw->cipher].accel_lrw_decrypt(ct, pt, len, lrw->IV, lrw->tweak, &lrw->key); + } + + return lrw_process(ct, pt, len, LRW_DECRYPT, lrw); +} + + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_done.c b/deps/libtomcrypt/src/modes/lrw/lrw_done.c new file mode 100644 index 0000000..dc649a0 --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_done.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_done.c + LRW_MODE implementation, Free resources, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Terminate a LRW state + @param lrw The state to terminate + @return CRYPT_OK if successful +*/ +int lrw_done(symmetric_LRW *lrw) +{ + int err; + + LTC_ARGCHK(lrw != NULL); + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[lrw->cipher].done(&lrw->key); + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_encrypt.c b/deps/libtomcrypt/src/modes/lrw/lrw_encrypt.c new file mode 100644 index 0000000..fde442b --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_encrypt.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_encrypt.c + LRW_MODE implementation, Encrypt blocks, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + LRW encrypt blocks + @param pt The plaintext + @param ct [out] The ciphertext + @param len The length in octets, must be a multiple of 16 + @param lrw The LRW state +*/ +int lrw_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_LRW *lrw) +{ + int err; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(lrw != NULL); + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL) { + return cipher_descriptor[lrw->cipher].accel_lrw_encrypt(pt, ct, len, lrw->IV, lrw->tweak, &lrw->key); + } + + return lrw_process(pt, ct, len, LRW_ENCRYPT, lrw); +} + + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_getiv.c b/deps/libtomcrypt/src/modes/lrw/lrw_getiv.c new file mode 100644 index 0000000..9da1aab --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_getiv.c + LRW_MODE implementation, Retrieve the current IV, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Get the IV for LRW + @param IV [out] The IV, must be 16 octets + @param len Length ... must be at least 16 :-) + @param lrw The LRW state to read + @return CRYPT_OK if successful +*/ +int lrw_getiv(unsigned char *IV, unsigned long *len, const symmetric_LRW *lrw) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(lrw != NULL); + if (*len < 16) { + *len = 16; + return CRYPT_BUFFER_OVERFLOW; + } + + XMEMCPY(IV, lrw->IV, 16); + *len = 16; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_process.c b/deps/libtomcrypt/src/modes/lrw/lrw_process.c new file mode 100644 index 0000000..d9a3edd --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_process.c @@ -0,0 +1,109 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_process.c + LRW_MODE implementation, Encrypt/decrypt blocks, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Process blocks with LRW, since decrypt/encrypt are largely the same they share this code. + @param pt The "input" data + @param ct [out] The "output" data + @param len The length of the input, must be a multiple of 128-bits (16 octets) + @param mode LRW_ENCRYPT or LRW_DECRYPT + @param lrw The LRW state + @return CRYPT_OK if successful +*/ +int lrw_process(const unsigned char *pt, unsigned char *ct, unsigned long len, int mode, symmetric_LRW *lrw) +{ + unsigned char prod[16]; + int x, err; +#ifdef LTC_LRW_TABLES + int y; +#endif + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(lrw != NULL); + + if (len & 15) { + return CRYPT_INVALID_ARG; + } + + while (len) { + /* copy pad */ + XMEMCPY(prod, lrw->pad, 16); + + /* increment IV */ + for (x = 15; x >= 0; x--) { + lrw->IV[x] = (lrw->IV[x] + 1) & 255; + if (lrw->IV[x]) { + break; + } + } + + /* update pad */ +#ifdef LTC_LRW_TABLES + /* for each byte changed we undo it's affect on the pad then add the new product */ + for (; x < 16; x++) { +#ifdef LTC_FAST + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(lrw->pad + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][lrw->IV[x]][y])) ^ *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][(lrw->IV[x]-1)&255][y])); + } +#else + for (y = 0; y < 16; y++) { + lrw->pad[y] ^= lrw->PC[x][lrw->IV[x]][y] ^ lrw->PC[x][(lrw->IV[x]-1)&255][y]; + } +#endif + } +#else + gcm_gf_mult(lrw->tweak, lrw->IV, lrw->pad); +#endif + + /* xor prod */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(pt + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x)); + } +#else + for (x = 0; x < 16; x++) { + ct[x] = pt[x] ^ prod[x]; + } +#endif + + /* send through cipher */ + if (mode == LRW_ENCRYPT) { + if ((err = cipher_descriptor[lrw->cipher].ecb_encrypt(ct, ct, &lrw->key)) != CRYPT_OK) { + return err; + } + } else { + if ((err = cipher_descriptor[lrw->cipher].ecb_decrypt(ct, ct, &lrw->key)) != CRYPT_OK) { + return err; + } + } + + /* xor prod */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(ct + x)) = *(LTC_FAST_TYPE_PTR_CAST(ct + x)) ^ *(LTC_FAST_TYPE_PTR_CAST(prod + x)); + } +#else + for (x = 0; x < 16; x++) { + ct[x] = ct[x] ^ prod[x]; + } +#endif + + /* move to next */ + pt += 16; + ct += 16; + len -= 16; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_setiv.c b/deps/libtomcrypt/src/modes/lrw/lrw_setiv.c new file mode 100644 index 0000000..efb4412 --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_setiv.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_setiv.c + LRW_MODE implementation, Set the current IV, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Set the IV for LRW + @param IV The IV, must be 16 octets + @param len Length ... must be 16 :-) + @param lrw The LRW state to update + @return CRYPT_OK if successful +*/ +int lrw_setiv(const unsigned char *IV, unsigned long len, symmetric_LRW *lrw) +{ + int err; +#ifdef LTC_LRW_TABLES + unsigned char T[16]; + int x, y; +#endif + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(lrw != NULL); + + if (len != 16) { + return CRYPT_INVALID_ARG; + } + + if ((err = cipher_is_valid(lrw->cipher)) != CRYPT_OK) { + return err; + } + + /* copy the IV */ + XMEMCPY(lrw->IV, IV, 16); + + /* check if we have to actually do work */ + if (cipher_descriptor[lrw->cipher].accel_lrw_encrypt != NULL && cipher_descriptor[lrw->cipher].accel_lrw_decrypt != NULL) { + /* we have accelerators, let's bail since they don't use lrw->pad anyways */ + return CRYPT_OK; + } + +#ifdef LTC_LRW_TABLES + XMEMCPY(T, &lrw->PC[0][IV[0]][0], 16); + for (x = 1; x < 16; x++) { +#ifdef LTC_FAST + for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(T + y)) ^= *(LTC_FAST_TYPE_PTR_CAST(&lrw->PC[x][IV[x]][y])); + } +#else + for (y = 0; y < 16; y++) { + T[y] ^= lrw->PC[x][IV[x]][y]; + } +#endif + } + XMEMCPY(lrw->pad, T, 16); +#else + gcm_gf_mult(lrw->tweak, IV, lrw->pad); +#endif + + return CRYPT_OK; +} + + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_start.c b/deps/libtomcrypt/src/modes/lrw/lrw_start.c new file mode 100644 index 0000000..2095685 --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_start.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_start.c + LRW_MODE implementation, start mode, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Initialize the LRW context + @param cipher The cipher desired, must be a 128-bit block cipher + @param IV The index value, must be 128-bits + @param key The cipher key + @param keylen The length of the cipher key in octets + @param tweak The tweak value (second key), must be 128-bits + @param num_rounds The number of rounds for the cipher (0 == default) + @param lrw [out] The LRW state + @return CRYPT_OK on success. +*/ +int lrw_start( int cipher, + const unsigned char *IV, + const unsigned char *key, int keylen, + const unsigned char *tweak, + int num_rounds, + symmetric_LRW *lrw) +{ + int err; +#ifdef LTC_LRW_TABLES + unsigned char B[16]; + int x, y, z, t; +#endif + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(tweak != NULL); + LTC_ARGCHK(lrw != NULL); + +#ifdef LTC_FAST + if (16 % sizeof(LTC_FAST_TYPE)) { + return CRYPT_INVALID_ARG; + } +#endif + + /* is cipher valid? */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_CIPHER; + } + + /* schedule key */ + if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &lrw->key)) != CRYPT_OK) { + return err; + } + lrw->cipher = cipher; + + /* copy the IV and tweak */ + XMEMCPY(lrw->tweak, tweak, 16); + +#ifdef LTC_LRW_TABLES + /* setup tables */ + /* generate the first table as it has no shifting (from which we make the other tables) */ + zeromem(B, 16); + for (y = 0; y < 256; y++) { + B[0] = y; + gcm_gf_mult(tweak, B, &lrw->PC[0][y][0]); + } + + /* now generate the rest of the tables based the previous table */ + for (x = 1; x < 16; x++) { + for (y = 0; y < 256; y++) { + /* now shift it right by 8 bits */ + t = lrw->PC[x-1][y][15]; + for (z = 15; z > 0; z--) { + lrw->PC[x][y][z] = lrw->PC[x-1][y][z-1]; + } + lrw->PC[x][y][0] = gcm_shift_table[t<<1]; + lrw->PC[x][y][1] ^= gcm_shift_table[(t<<1)+1]; + } + } +#endif + + /* generate first pad */ + return lrw_setiv(IV, 16, lrw); +} + + +#endif diff --git a/deps/libtomcrypt/src/modes/lrw/lrw_test.c b/deps/libtomcrypt/src/modes/lrw/lrw_test.c new file mode 100644 index 0000000..3d9015b --- /dev/null +++ b/deps/libtomcrypt/src/modes/lrw/lrw_test.c @@ -0,0 +1,124 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file lrw_test.c + LRW_MODE implementation, test LRW, Tom St Denis +*/ + +#ifdef LTC_LRW_MODE + +/** + Test LRW against specs + @return CRYPT_OK if goodly +*/ +int lrw_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + unsigned char key[16], tweak[16], IV[16], P[16], expected_tweak[16], C[16]; + } tests[] = { + +{ +{ 0x45, 0x62, 0xac, 0x25, 0xf8, 0x28, 0x17, 0x6d, 0x4c, 0x26, 0x84, 0x14, 0xb5, 0x68, 0x01, 0x85 }, +{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, +{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x25, 0x8e, 0x2a, 0x05, 0xe7, 0x3e, 0x9d, 0x03, 0xee, 0x5a, 0x83, 0x0c, 0xcc, 0x09, 0x4c, 0x87 }, +{ 0xf1, 0xb2, 0x73, 0xcd, 0x65, 0xa3, 0xdf, 0x5f, 0xe9, 0x5d, 0x48, 0x92, 0x54, 0x63, 0x4e, 0xb8 } +}, + +{ +{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, +{ 0x35, 0x23, 0xc2, 0xde, 0xc5, 0x69, 0x4f, 0xa8, 0x72, 0xa9, 0xac, 0xa7, 0x0b, 0x2b, 0xee, 0xbc }, +{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, +{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, +}, + +{ +{ 0x59, 0x70, 0x47, 0x14, 0xf5, 0x57, 0x47, 0x8c, 0xd7, 0x79, 0xe8, 0x0f, 0x54, 0x88, 0x79, 0x44 }, +{ 0x67, 0x53, 0xc9, 0x0c, 0xb7, 0xd8, 0xcd, 0xe5, 0x06, 0xa0, 0x47, 0x78, 0x1a, 0xad, 0x85, 0x11 }, +{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x1a, 0x91, 0xe1, 0x6f, 0x62, 0xb4, 0xa7, 0xd4, 0x39, 0x54, 0xd6, 0x53, 0x85, 0x95, 0xf7, 0x5e }, +{ 0x00, 0xc8, 0x2b, 0xae, 0x95, 0xbb, 0xcd, 0xe5, 0x27, 0x4f, 0x07, 0x69, 0xb2, 0x60, 0xe1, 0x36 }, +}, + +{ + +{ 0xd8, 0x2a, 0x91, 0x34, 0xb2, 0x6a, 0x56, 0x50, 0x30, 0xfe, 0x69, 0xe2, 0x37, 0x7f, 0x98, 0x47 }, +{ 0x4e, 0xb5, 0x5d, 0x31, 0x05, 0x97, 0x3a, 0x3f, 0x5e, 0x23, 0xda, 0xfb, 0x5a, 0x45, 0xd6, 0xc0 }, +{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00 }, +{ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }, +{ 0x18, 0xc9, 0x1f, 0x6d, 0x60, 0x1a, 0x1a, 0x37, 0x5d, 0x0b, 0x0e, 0xf7, 0x3a, 0xd5, 0x74, 0xc4 }, +{ 0x76, 0x32, 0x21, 0x83, 0xed, 0x8f, 0xf1, 0x82, 0xf9, 0x59, 0x62, 0x03, 0x69, 0x0e, 0x5e, 0x01 }, + +} +}; + + int idx, err, x; + symmetric_LRW lrw; + unsigned char buf[2][16]; + + idx = find_cipher("aes"); + if (idx == -1) { + idx = find_cipher("rijndael"); + if (idx == -1) { + return CRYPT_NOP; + } + } + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + /* schedule it */ + if ((err = lrw_start(idx, tests[x].IV, tests[x].key, 16, tests[x].tweak, 0, &lrw)) != CRYPT_OK) { + return err; + } + + /* check pad against expected tweak */ + if (compare_testvector(tests[x].expected_tweak, 16, lrw.pad, 16, "LRW Tweak", x)) { + lrw_done(&lrw); + return CRYPT_FAIL_TESTVECTOR; + } + + /* process block */ + if ((err = lrw_encrypt(tests[x].P, buf[0], 16, &lrw)) != CRYPT_OK) { + lrw_done(&lrw); + return err; + } + + if (compare_testvector(buf[0], 16, tests[x].C, 16, "LRW Encrypt", x)) { + lrw_done(&lrw); + return CRYPT_FAIL_TESTVECTOR; + } + + /* process block */ + if ((err = lrw_setiv(tests[x].IV, 16, &lrw)) != CRYPT_OK) { + lrw_done(&lrw); + return err; + } + + if ((err = lrw_decrypt(buf[0], buf[1], 16, &lrw)) != CRYPT_OK) { + lrw_done(&lrw); + return err; + } + + if (compare_testvector(buf[1], 16, tests[x].P, 16, "LRW Decrypt", x)) { + lrw_done(&lrw); + return CRYPT_FAIL_TESTVECTOR; + } + if ((err = lrw_done(&lrw)) != CRYPT_OK) { + return err; + } + } + return CRYPT_OK; +#endif +} + +#endif + + diff --git a/deps/libtomcrypt/src/modes/ofb/ofb_decrypt.c b/deps/libtomcrypt/src/modes/ofb/ofb_decrypt.c new file mode 100644 index 0000000..cebcd7b --- /dev/null +++ b/deps/libtomcrypt/src/modes/ofb/ofb_decrypt.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_decrypt.c + OFB implementation, decrypt data, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + OFB decrypt + @param ct Ciphertext + @param pt [out] Plaintext + @param len Length of ciphertext (octets) + @param ofb OFB state + @return CRYPT_OK if successful +*/ +int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb) +{ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ofb != NULL); + return ofb_encrypt(ct, pt, len, ofb); +} + + +#endif + + diff --git a/deps/libtomcrypt/src/modes/ofb/ofb_done.c b/deps/libtomcrypt/src/modes/ofb/ofb_done.c new file mode 100644 index 0000000..c4a0184 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ofb/ofb_done.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_done.c + OFB implementation, finish chain, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** Terminate the chain + @param ofb The OFB chain to terminate + @return CRYPT_OK on success +*/ +int ofb_done(symmetric_OFB *ofb) +{ + int err; + LTC_ARGCHK(ofb != NULL); + + if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { + return err; + } + cipher_descriptor[ofb->cipher].done(&ofb->key); + return CRYPT_OK; +} + + + +#endif diff --git a/deps/libtomcrypt/src/modes/ofb/ofb_encrypt.c b/deps/libtomcrypt/src/modes/ofb/ofb_encrypt.c new file mode 100644 index 0000000..63f1e18 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ofb/ofb_encrypt.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_encrypt.c + OFB implementation, encrypt data, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + OFB encrypt + @param pt Plaintext + @param ct [out] Ciphertext + @param len Length of plaintext (octets) + @param ofb OFB state + @return CRYPT_OK if successful +*/ +int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb) +{ + int err; + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(ofb != NULL); + if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { + return err; + } + + /* is blocklen/padlen valid? */ + if (ofb->blocklen < 0 || ofb->blocklen > (int)sizeof(ofb->IV) || + ofb->padlen < 0 || ofb->padlen > (int)sizeof(ofb->IV)) { + return CRYPT_INVALID_ARG; + } + + while (len-- > 0) { + if (ofb->padlen == ofb->blocklen) { + if ((err = cipher_descriptor[ofb->cipher].ecb_encrypt(ofb->IV, ofb->IV, &ofb->key)) != CRYPT_OK) { + return err; + } + ofb->padlen = 0; + } + *ct++ = *pt++ ^ ofb->IV[(ofb->padlen)++]; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ofb/ofb_getiv.c b/deps/libtomcrypt/src/modes/ofb/ofb_getiv.c new file mode 100644 index 0000000..0a799f0 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ofb/ofb_getiv.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_getiv.c + OFB implementation, get IV, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + Get the current initialization vector + @param IV [out] The destination of the initialization vector + @param len [in/out] The max size and resulting size of the initialization vector + @param ofb The OFB state + @return CRYPT_OK if successful +*/ +int ofb_getiv(unsigned char *IV, unsigned long *len, const symmetric_OFB *ofb) +{ + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(len != NULL); + LTC_ARGCHK(ofb != NULL); + if ((unsigned long)ofb->blocklen > *len) { + *len = ofb->blocklen; + return CRYPT_BUFFER_OVERFLOW; + } + XMEMCPY(IV, ofb->IV, ofb->blocklen); + *len = ofb->blocklen; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/ofb/ofb_setiv.c b/deps/libtomcrypt/src/modes/ofb/ofb_setiv.c new file mode 100644 index 0000000..1fdec7f --- /dev/null +++ b/deps/libtomcrypt/src/modes/ofb/ofb_setiv.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_setiv.c + OFB implementation, set IV, Tom St Denis +*/ + +#ifdef LTC_OFB_MODE + +/** + Set an initialization vector + @param IV The initialization vector + @param len The length of the vector (in octets) + @param ofb The OFB state + @return CRYPT_OK if successful +*/ +int ofb_setiv(const unsigned char *IV, unsigned long len, symmetric_OFB *ofb) +{ + int err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(ofb != NULL); + + if ((err = cipher_is_valid(ofb->cipher)) != CRYPT_OK) { + return err; + } + + if (len != (unsigned long)ofb->blocklen) { + return CRYPT_INVALID_ARG; + } + + /* force next block */ + ofb->padlen = 0; + return cipher_descriptor[ofb->cipher].ecb_encrypt(IV, ofb->IV, &ofb->key); +} + +#endif + diff --git a/deps/libtomcrypt/src/modes/ofb/ofb_start.c b/deps/libtomcrypt/src/modes/ofb/ofb_start.c new file mode 100644 index 0000000..179fe57 --- /dev/null +++ b/deps/libtomcrypt/src/modes/ofb/ofb_start.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ofb_start.c + OFB implementation, start chain, Tom St Denis +*/ + + +#ifdef LTC_OFB_MODE + +/** + Initialize a OFB context + @param cipher The index of the cipher desired + @param IV The initialization vector + @param key The secret key + @param keylen The length of the secret key (octets) + @param num_rounds Number of rounds in the cipher desired (0 for default) + @param ofb The OFB state to initialize + @return CRYPT_OK if successful +*/ +int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key, + int keylen, int num_rounds, symmetric_OFB *ofb) +{ + int x, err; + + LTC_ARGCHK(IV != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ofb != NULL); + + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + /* copy details */ + ofb->cipher = cipher; + ofb->blocklen = cipher_descriptor[cipher].block_length; + for (x = 0; x < ofb->blocklen; x++) { + ofb->IV[x] = IV[x]; + } + + /* init the cipher */ + ofb->padlen = ofb->blocklen; + return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ofb->key); +} + +#endif diff --git a/deps/libtomcrypt/src/modes/xts/xts_decrypt.c b/deps/libtomcrypt/src/modes/xts/xts_decrypt.c new file mode 100644 index 0000000..f1747d5 --- /dev/null +++ b/deps/libtomcrypt/src/modes/xts/xts_decrypt.c @@ -0,0 +1,146 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects + */ + +#ifdef LTC_XTS_MODE + +static int s_tweak_uncrypt(const unsigned char *C, unsigned char *P, unsigned char *T, const symmetric_xts *xts) +{ + unsigned long x; + int err; + + /* tweak encrypt block i */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&P[x])) = *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x])); + } +#else + for (x = 0; x < 16; x++) { + P[x] = C[x] ^ T[x]; + } +#endif + + err = cipher_descriptor[xts->cipher].ecb_decrypt(P, P, &xts->key1); + +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x])); + } +#else + for (x = 0; x < 16; x++) { + P[x] = P[x] ^ T[x]; + } +#endif + + /* LFSR the tweak */ + xts_mult_x(T); + + return err; +} + +/** XTS Decryption + @param ct [in] Ciphertext + @param ptlen Length of plaintext (and ciphertext) + @param pt [out] Plaintext + @param tweak [in] The 128--bit encryption tweak (e.g. sector number) + @param xts The XTS structure + Returns CRYPT_OK upon success + */ +int xts_decrypt(const unsigned char *ct, unsigned long ptlen, unsigned char *pt, unsigned char *tweak, + const symmetric_xts *xts) +{ + unsigned char PP[16], CC[16], T[16]; + unsigned long i, m, mo, lim; + int err; + + /* check inputs */ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tweak != NULL); + LTC_ARGCHK(xts != NULL); + + /* check if valid */ + if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { + return err; + } + + /* get number of blocks */ + m = ptlen >> 4; + mo = ptlen & 15; + + /* must have at least one full block */ + if (m == 0) { + return CRYPT_INVALID_ARG; + } + + if (mo == 0) { + lim = m; + } else { + lim = m - 1; + } + + if (cipher_descriptor[xts->cipher].accel_xts_decrypt && lim > 0) { + + /* use accelerated decryption for whole blocks */ + if ((err = cipher_descriptor[xts->cipher].accel_xts_decrypt(ct, pt, lim, tweak, &xts->key1, &xts->key2)) != + CRYPT_OK) { + return err; + } + ct += lim * 16; + pt += lim * 16; + + /* tweak is encrypted on output */ + XMEMCPY(T, tweak, sizeof(T)); + } else { + /* encrypt the tweak */ + if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < lim; i++) { + if ((err = s_tweak_uncrypt(ct, pt, T, xts)) != CRYPT_OK) { + return err; + } + ct += 16; + pt += 16; + } + } + + /* if ptlen not divide 16 then */ + if (mo > 0) { + XMEMCPY(CC, T, 16); + xts_mult_x(CC); + + /* PP = tweak decrypt block m-1 */ + if ((err = s_tweak_uncrypt(ct, PP, CC, xts)) != CRYPT_OK) { + return err; + } + + /* Pm = first ptlen % 16 bytes of PP */ + for (i = 0; i < mo; i++) { + CC[i] = ct[16 + i]; + pt[16 + i] = PP[i]; + } + for (; i < 16; i++) { + CC[i] = PP[i]; + } + + /* Pm-1 = Tweak uncrypt CC */ + if ((err = s_tweak_uncrypt(CC, pt, T, xts)) != CRYPT_OK) { + return err; + } + } + + /* Decrypt the tweak back */ + if ((err = cipher_descriptor[xts->cipher].ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/xts/xts_done.c b/deps/libtomcrypt/src/modes/xts/xts_done.c new file mode 100644 index 0000000..4f77521 --- /dev/null +++ b/deps/libtomcrypt/src/modes/xts/xts_done.c @@ -0,0 +1,21 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + +/** Terminate XTS state + @param xts The state to terminate +*/ +void xts_done(symmetric_xts *xts) +{ + LTC_ARGCHKVD(xts != NULL); + cipher_descriptor[xts->cipher].done(&xts->key1); + cipher_descriptor[xts->cipher].done(&xts->key2); +} + +#endif diff --git a/deps/libtomcrypt/src/modes/xts/xts_encrypt.c b/deps/libtomcrypt/src/modes/xts/xts_encrypt.c new file mode 100644 index 0000000..c269b7c --- /dev/null +++ b/deps/libtomcrypt/src/modes/xts/xts_encrypt.c @@ -0,0 +1,147 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects + */ + +#ifdef LTC_XTS_MODE + +static int s_tweak_crypt(const unsigned char *P, unsigned char *C, unsigned char *T, const symmetric_xts *xts) +{ + unsigned long x; + int err; + + /* tweak encrypt block i */ +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&C[x])) = *(LTC_FAST_TYPE_PTR_CAST(&P[x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&T[x])); + } +#else + for (x = 0; x < 16; x++) { + C[x] = P[x] ^ T[x]; + } +#endif + + if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(C, C, &xts->key1)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_FAST + for (x = 0; x < 16; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&C[x])) ^= *(LTC_FAST_TYPE_PTR_CAST(&T[x])); + } +#else + for (x = 0; x < 16; x++) { + C[x] = C[x] ^ T[x]; + } +#endif + + /* LFSR the tweak */ + xts_mult_x(T); + + return CRYPT_OK; +} + +/** XTS Encryption + @param pt [in] Plaintext + @param ptlen Length of plaintext (and ciphertext) + @param ct [out] Ciphertext + @param tweak [in] The 128--bit encryption tweak (e.g. sector number) + @param xts The XTS structure + Returns CRYPT_OK upon success + */ +int xts_encrypt(const unsigned char *pt, unsigned long ptlen, unsigned char *ct, unsigned char *tweak, + const symmetric_xts *xts) +{ + unsigned char PP[16], CC[16], T[16]; + unsigned long i, m, mo, lim; + int err; + + /* check inputs */ + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(tweak != NULL); + LTC_ARGCHK(xts != NULL); + + /* check if valid */ + if ((err = cipher_is_valid(xts->cipher)) != CRYPT_OK) { + return err; + } + + /* get number of blocks */ + m = ptlen >> 4; + mo = ptlen & 15; + + /* must have at least one full block */ + if (m == 0) { + return CRYPT_INVALID_ARG; + } + + if (mo == 0) { + lim = m; + } else { + lim = m - 1; + } + + if (cipher_descriptor[xts->cipher].accel_xts_encrypt && lim > 0) { + + /* use accelerated encryption for whole blocks */ + if ((err = cipher_descriptor[xts->cipher].accel_xts_encrypt(pt, ct, lim, tweak, &xts->key1, &xts->key2)) != + CRYPT_OK) { + return err; + } + ct += lim * 16; + pt += lim * 16; + + /* tweak is encrypted on output */ + XMEMCPY(T, tweak, sizeof(T)); + } else { + + /* encrypt the tweak */ + if ((err = cipher_descriptor[xts->cipher].ecb_encrypt(tweak, T, &xts->key2)) != CRYPT_OK) { + return err; + } + + for (i = 0; i < lim; i++) { + if ((err = s_tweak_crypt(pt, ct, T, xts)) != CRYPT_OK) { + return err; + } + ct += 16; + pt += 16; + } + } + + /* if ptlen not divide 16 then */ + if (mo > 0) { + /* CC = tweak encrypt block m-1 */ + if ((err = s_tweak_crypt(pt, CC, T, xts)) != CRYPT_OK) { + return err; + } + + /* Cm = first ptlen % 16 bytes of CC */ + for (i = 0; i < mo; i++) { + PP[i] = pt[16 + i]; + ct[16 + i] = CC[i]; + } + + for (; i < 16; i++) { + PP[i] = CC[i]; + } + + /* Cm-1 = Tweak encrypt PP */ + if ((err = s_tweak_crypt(PP, ct, T, xts)) != CRYPT_OK) { + return err; + } + } + + /* Decrypt the tweak back */ + if ((err = cipher_descriptor[xts->cipher].ecb_decrypt(T, tweak, &xts->key2)) != CRYPT_OK) { + return err; + } + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/xts/xts_init.c b/deps/libtomcrypt/src/modes/xts/xts_init.c new file mode 100644 index 0000000..cec3a32 --- /dev/null +++ b/deps/libtomcrypt/src/modes/xts/xts_init.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + +/** Start XTS mode + @param cipher The index of the cipher to use + @param key1 The encrypt key + @param key2 The tweak encrypt key + @param keylen The length of the keys (each) in octets + @param num_rounds The number of rounds for the cipher (0 == default) + @param xts [out] XTS structure + Returns CRYPT_OK upon success. +*/ +int xts_start(int cipher, const unsigned char *key1, const unsigned char *key2, unsigned long keylen, int num_rounds, + symmetric_xts *xts) +{ + int err; + + /* check inputs */ + LTC_ARGCHK(key1 != NULL); + LTC_ARGCHK(key2 != NULL); + LTC_ARGCHK(xts != NULL); + + /* check if valid */ + if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { + return err; + } + + if (cipher_descriptor[cipher].block_length != 16) { + return CRYPT_INVALID_ARG; + } + + /* schedule the two ciphers */ + if ((err = cipher_descriptor[cipher].setup(key1, keylen, num_rounds, &xts->key1)) != CRYPT_OK) { + return err; + } + if ((err = cipher_descriptor[cipher].setup(key2, keylen, num_rounds, &xts->key2)) != CRYPT_OK) { + return err; + } + xts->cipher = cipher; + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/modes/xts/xts_mult_x.c b/deps/libtomcrypt/src/modes/xts/xts_mult_x.c new file mode 100644 index 0000000..20947a5 --- /dev/null +++ b/deps/libtomcrypt/src/modes/xts/xts_mult_x.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects +*/ + +#ifdef LTC_XTS_MODE + +/** multiply by x + @param I The value to multiply by x (LFSR shift) +*/ +void xts_mult_x(unsigned char *I) +{ + int x; + unsigned char t, tt; + + for (x = t = 0; x < 16; x++) { + tt = I[x] >> 7; + I[x] = ((I[x] << 1) | t) & 0xFF; + t = tt; + } + if (tt) { + I[0] ^= 0x87; + } +} + +#endif diff --git a/deps/libtomcrypt/src/modes/xts/xts_test.c b/deps/libtomcrypt/src/modes/xts/xts_test.c new file mode 100644 index 0000000..ad92735 --- /dev/null +++ b/deps/libtomcrypt/src/modes/xts/xts_test.c @@ -0,0 +1,296 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_XTS_MODE + +#ifndef LTC_NO_TEST +static int s_xts_test_accel_xts_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long blocks, + unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) +{ + int ret; + symmetric_xts xts; + int (*orig)(const unsigned char *, unsigned char *, + unsigned long , unsigned char *, + const symmetric_key *, const symmetric_key *); + + /* AES can be under rijndael or aes... try to find it */ + if ((xts.cipher = find_cipher("aes")) == -1) { + if ((xts.cipher = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + orig = cipher_descriptor[xts.cipher].accel_xts_encrypt; + cipher_descriptor[xts.cipher].accel_xts_encrypt = NULL; + + XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key)); + XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key)); + + ret = xts_encrypt(pt, blocks << 4, ct, tweak, &xts); + cipher_descriptor[xts.cipher].accel_xts_encrypt = orig; + + return ret; +} + +static int s_xts_test_accel_xts_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long blocks, + unsigned char *tweak, const symmetric_key *skey1, const symmetric_key *skey2) +{ + int ret; + symmetric_xts xts; + int (*orig)(const unsigned char *, unsigned char *, + unsigned long , unsigned char *, + const symmetric_key *, const symmetric_key *); + + /* AES can be under rijndael or aes... try to find it */ + if ((xts.cipher = find_cipher("aes")) == -1) { + if ((xts.cipher = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + orig = cipher_descriptor[xts.cipher].accel_xts_decrypt; + cipher_descriptor[xts.cipher].accel_xts_decrypt = NULL; + + XMEMCPY(&xts.key1, skey1, sizeof(symmetric_key)); + XMEMCPY(&xts.key2, skey2, sizeof(symmetric_key)); + + ret = xts_decrypt(ct, blocks << 4, pt, tweak, &xts); + cipher_descriptor[xts.cipher].accel_xts_decrypt = orig; + + return ret; +} +#endif + +/** + Source donated by Elliptic Semiconductor Inc (www.ellipticsemi.com) to the LibTom Projects + + Returns CRYPT_OK upon success. +*/ +int xts_test(void) +{ +#ifdef LTC_NO_TEST + return CRYPT_NOP; +#else + static const struct + { + int keylen; + unsigned char key1[32]; + unsigned char key2[32]; + ulong64 seqnum; + unsigned long PTLEN; + unsigned char PTX[512], CTX[512]; + } tests[] = { + +/* #1 32 byte key, 32 byte PTX */ +{ + 32, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + 0, + 32, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x91,0x7c,0xf6,0x9e,0xbd,0x68,0xb2,0xec,0x9b,0x9f,0xe9,0xa3,0xea,0xdd,0xa6,0x92,0xcd,0x43,0xd2,0xf5,0x95,0x98,0xed,0x85,0x8c,0x02,0xc2,0x65,0x2f,0xbf,0x92,0x2e }, +}, + +/* #2, 32 byte key, 32 byte PTX */ +{ + 32, + { 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11 }, + { 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22 }, + CONST64(0x3333333333), + 32, + { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, + { 0xc4,0x54,0x18,0x5e,0x6a,0x16,0x93,0x6e,0x39,0x33,0x40,0x38,0xac,0xef,0x83,0x8b,0xfb,0x18,0x6f,0xff,0x74,0x80,0xad,0xc4,0x28,0x93,0x82,0xec,0xd6,0xd3,0x94,0xf0 }, +}, + +/* #5 from xts.7, 32 byte key, 32 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 32, + { 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44 }, + { 0xb0,0x1f,0x86,0xf8,0xed,0xc1,0x86,0x37,0x06,0xfa,0x8a,0x42,0x53,0xe3,0x4f,0x28,0xaf,0x31,0x9d,0xe3,0x83,0x34,0x87,0x0f,0x4d,0xd1,0xf9,0x4c,0xbe,0x98,0x32,0xf1 }, +}, + +/* #4, 32 byte key, 512 byte PTX */ +{ + 32, + { 0x27,0x18,0x28,0x18,0x28,0x45,0x90,0x45,0x23,0x53,0x60,0x28,0x74,0x71,0x35,0x26 }, + { 0x31,0x41,0x59,0x26,0x53,0x58,0x97,0x93,0x23,0x84,0x62,0x64,0x33,0x83,0x27,0x95 }, + 0, + 512, + { +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, +0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, +0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, +0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, +0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, +0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, +0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, +0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, +0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, +0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, +0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, + }, + { +0x27,0xa7,0x47,0x9b,0xef,0xa1,0xd4,0x76,0x48,0x9f,0x30,0x8c,0xd4,0xcf,0xa6,0xe2,0xa9,0x6e,0x4b,0xbe,0x32,0x08,0xff,0x25,0x28,0x7d,0xd3,0x81,0x96,0x16,0xe8,0x9c, +0xc7,0x8c,0xf7,0xf5,0xe5,0x43,0x44,0x5f,0x83,0x33,0xd8,0xfa,0x7f,0x56,0x00,0x00,0x05,0x27,0x9f,0xa5,0xd8,0xb5,0xe4,0xad,0x40,0xe7,0x36,0xdd,0xb4,0xd3,0x54,0x12, +0x32,0x80,0x63,0xfd,0x2a,0xab,0x53,0xe5,0xea,0x1e,0x0a,0x9f,0x33,0x25,0x00,0xa5,0xdf,0x94,0x87,0xd0,0x7a,0x5c,0x92,0xcc,0x51,0x2c,0x88,0x66,0xc7,0xe8,0x60,0xce, +0x93,0xfd,0xf1,0x66,0xa2,0x49,0x12,0xb4,0x22,0x97,0x61,0x46,0xae,0x20,0xce,0x84,0x6b,0xb7,0xdc,0x9b,0xa9,0x4a,0x76,0x7a,0xae,0xf2,0x0c,0x0d,0x61,0xad,0x02,0x65, +0x5e,0xa9,0x2d,0xc4,0xc4,0xe4,0x1a,0x89,0x52,0xc6,0x51,0xd3,0x31,0x74,0xbe,0x51,0xa1,0x0c,0x42,0x11,0x10,0xe6,0xd8,0x15,0x88,0xed,0xe8,0x21,0x03,0xa2,0x52,0xd8, +0xa7,0x50,0xe8,0x76,0x8d,0xef,0xff,0xed,0x91,0x22,0x81,0x0a,0xae,0xb9,0x9f,0x91,0x72,0xaf,0x82,0xb6,0x04,0xdc,0x4b,0x8e,0x51,0xbc,0xb0,0x82,0x35,0xa6,0xf4,0x34, +0x13,0x32,0xe4,0xca,0x60,0x48,0x2a,0x4b,0xa1,0xa0,0x3b,0x3e,0x65,0x00,0x8f,0xc5,0xda,0x76,0xb7,0x0b,0xf1,0x69,0x0d,0xb4,0xea,0xe2,0x9c,0x5f,0x1b,0xad,0xd0,0x3c, +0x5c,0xcf,0x2a,0x55,0xd7,0x05,0xdd,0xcd,0x86,0xd4,0x49,0x51,0x1c,0xeb,0x7e,0xc3,0x0b,0xf1,0x2b,0x1f,0xa3,0x5b,0x91,0x3f,0x9f,0x74,0x7a,0x8a,0xfd,0x1b,0x13,0x0e, +0x94,0xbf,0xf9,0x4e,0xff,0xd0,0x1a,0x91,0x73,0x5c,0xa1,0x72,0x6a,0xcd,0x0b,0x19,0x7c,0x4e,0x5b,0x03,0x39,0x36,0x97,0xe1,0x26,0x82,0x6f,0xb6,0xbb,0xde,0x8e,0xcc, +0x1e,0x08,0x29,0x85,0x16,0xe2,0xc9,0xed,0x03,0xff,0x3c,0x1b,0x78,0x60,0xf6,0xde,0x76,0xd4,0xce,0xcd,0x94,0xc8,0x11,0x98,0x55,0xef,0x52,0x97,0xca,0x67,0xe9,0xf3, +0xe7,0xff,0x72,0xb1,0xe9,0x97,0x85,0xca,0x0a,0x7e,0x77,0x20,0xc5,0xb3,0x6d,0xc6,0xd7,0x2c,0xac,0x95,0x74,0xc8,0xcb,0xbc,0x2f,0x80,0x1e,0x23,0xe5,0x6f,0xd3,0x44, +0xb0,0x7f,0x22,0x15,0x4b,0xeb,0xa0,0xf0,0x8c,0xe8,0x89,0x1e,0x64,0x3e,0xd9,0x95,0xc9,0x4d,0x9a,0x69,0xc9,0xf1,0xb5,0xf4,0x99,0x02,0x7a,0x78,0x57,0x2a,0xee,0xbd, +0x74,0xd2,0x0c,0xc3,0x98,0x81,0xc2,0x13,0xee,0x77,0x0b,0x10,0x10,0xe4,0xbe,0xa7,0x18,0x84,0x69,0x77,0xae,0x11,0x9f,0x7a,0x02,0x3a,0xb5,0x8c,0xca,0x0a,0xd7,0x52, +0xaf,0xe6,0x56,0xbb,0x3c,0x17,0x25,0x6a,0x9f,0x6e,0x9b,0xf1,0x9f,0xdd,0x5a,0x38,0xfc,0x82,0xbb,0xe8,0x72,0xc5,0x53,0x9e,0xdb,0x60,0x9e,0xf4,0xf7,0x9c,0x20,0x3e, +0xbb,0x14,0x0f,0x2e,0x58,0x3c,0xb2,0xad,0x15,0xb4,0xaa,0x5b,0x65,0x50,0x16,0xa8,0x44,0x92,0x77,0xdb,0xd4,0x77,0xef,0x2c,0x8d,0x6c,0x01,0x7d,0xb7,0x38,0xb1,0x8d, +0xeb,0x4a,0x42,0x7d,0x19,0x23,0xce,0x3f,0xf2,0x62,0x73,0x57,0x79,0xa4,0x18,0xf2,0x0a,0x28,0x2d,0xf9,0x20,0x14,0x7b,0xea,0xbe,0x42,0x1e,0xe5,0x31,0x9d,0x05,0x68, + } +}, + +/* #7, 32 byte key, 17 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 17, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10 }, + { 0x6c,0x16,0x25,0xdb,0x46,0x71,0x52,0x2d,0x3d,0x75,0x99,0x60,0x1d,0xe7,0xca,0x09,0xed }, +}, + +/* #15, 32 byte key, 25 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 25, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18 }, + { 0x8f,0x4d,0xcb,0xad,0x55,0x55,0x8d,0x7b,0x4e,0x01,0xd9,0x37,0x9c,0xd4,0xea,0x22,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73 }, +}, + +/* #21, 32 byte key, 31 byte PTX */ +{ + 32, + { 0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0 }, + { 0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0 }, + CONST64(0x123456789a), + 31, + { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e }, + { 0xd0,0x5b,0xc0,0x90,0xa8,0xe0,0x4f,0x1b,0x3d,0x3e,0xcd,0xd5,0xba,0xec,0x0f,0xd4,0xed,0xbf,0x9d,0xac,0xe4,0x5d,0x6f,0x6a,0x73,0x06,0xe6,0x4b,0xe5,0xdd,0x82 }, +}, + +}; + unsigned char OUT[512], Torg[16], T[16]; + ulong64 seq; + symmetric_xts xts; + int i, j, k, err, idx; + unsigned long len; + + /* AES can be under rijndael or aes... try to find it */ + if ((idx = find_cipher("aes")) == -1) { + if ((idx = find_cipher("rijndael")) == -1) { + return CRYPT_NOP; + } + } + for (k = 0; k < 4; ++k) { + cipher_descriptor[idx].accel_xts_encrypt = NULL; + cipher_descriptor[idx].accel_xts_decrypt = NULL; + if (k & 0x1) { + cipher_descriptor[idx].accel_xts_encrypt = s_xts_test_accel_xts_encrypt; + } + if (k & 0x2) { + cipher_descriptor[idx].accel_xts_decrypt = s_xts_test_accel_xts_decrypt; + } + for (j = 0; j < 2; j++) { + for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { + /* skip the cases where + * the length is smaller than 2*blocklen + * or the length is not a multiple of 32 + */ + if ((j == 1) && ((tests[i].PTLEN < 32) || (tests[i].PTLEN % 32))) { + continue; + } + if ((k > 0) && (j == 1)) { + continue; + } + len = tests[i].PTLEN / 2; + + err = xts_start(idx, tests[i].key1, tests[i].key2, tests[i].keylen / 2, 0, &xts); + if (err != CRYPT_OK) { + return err; + } + + seq = tests[i].seqnum; + STORE64L(seq, Torg); + XMEMSET(Torg + 8, 0, 8); + + XMEMCPY(T, Torg, sizeof(T)); + if (j == 0) { + err = xts_encrypt(tests[i].PTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } else { + err = xts_encrypt(tests[i].PTX, len, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + err = xts_encrypt(&tests[i].PTX[len], len, &OUT[len], T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } + + if (compare_testvector(OUT, tests[i].PTLEN, tests[i].CTX, tests[i].PTLEN, "XTS encrypt", i)) { + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + + XMEMCPY(T, Torg, sizeof(T)); + if (j == 0) { + err = xts_decrypt(tests[i].CTX, tests[i].PTLEN, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } else { + err = xts_decrypt(tests[i].CTX, len, OUT, T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + err = xts_decrypt(&tests[i].CTX[len], len, &OUT[len], T, &xts); + if (err != CRYPT_OK) { + xts_done(&xts); + return err; + } + } + + if (compare_testvector(OUT, tests[i].PTLEN, tests[i].PTX, tests[i].PTLEN, "XTS decrypt", i)) { + xts_done(&xts); + return CRYPT_FAIL_TESTVECTOR; + } + xts_done(&xts); + } + } + } + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c b/deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c new file mode 100644 index 0000000..83c915d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c @@ -0,0 +1,77 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BIT STRING + @param in The DER encoded BIT STRING + @param inlen The size of the DER BIT STRING + @param out [out] The array of bits stored (one per char) + @param outlen [in/out] The number of bits stored + @return CRYPT_OK if successful +*/ +int der_decode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long dlen, blen, x, y; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* packet must be at least 4 bytes */ + if (inlen < 4) { + return CRYPT_INVALID_ARG; + } + + /* check for 0x03 */ + if ((in[0]&0x1F) != 0x03) { + return CRYPT_INVALID_PACKET; + } + + /* offset in the data */ + x = 1; + + /* get the length of the data */ + y = inlen - 1; + if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { + return err; + } + x += y; + /* is the data len too long or too short? */ + if ((dlen == 0) || (dlen > (inlen - x))) { + return CRYPT_INVALID_PACKET; + } + + /* get padding count */ + blen = ((dlen - 1) << 3) - (in[x++] & 7); + + /* too many bits? */ + if (blen > *outlen) { + *outlen = blen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode/store the bits */ + for (y = 0; y < blen; y++) { + out[y] = (in[x] & (1 << (7 - (y & 7)))) ? 1 : 0; + if ((y & 7) == 7) { + ++x; + } + } + + /* we done */ + *outlen = blen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c b/deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c new file mode 100644 index 0000000..1bc74f6 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/bit/der_decode_raw_bit_string.c @@ -0,0 +1,84 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +#define SETBIT(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n)))) +#define CLRBIT(v, n) (v=((unsigned char)(v) & ~(1U << (unsigned char)(n)))) + +/** + Store a BIT STRING + @param in The DER encoded BIT STRING + @param inlen The size of the DER BIT STRING + @param out [out] The array of bits stored (8 per char) + @param outlen [in/out] The number of bits stored + @return CRYPT_OK if successful +*/ +int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long dlen, blen, x, y; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* packet must be at least 4 bytes */ + if (inlen < 4) { + return CRYPT_INVALID_ARG; + } + + /* check for 0x03 */ + if ((in[0]&0x1F) != 0x03) { + return CRYPT_INVALID_PACKET; + } + + /* offset in the data */ + x = 1; + + /* get the length of the data */ + y = inlen - 1; + if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) { + return err; + } + x += y; + /* is the data len too long or too short? */ + if ((dlen == 0) || (dlen > (inlen - x))) { + return CRYPT_INVALID_PACKET; + } + + /* get padding count */ + blen = ((dlen - 1) << 3) - (in[x++] & 7); + + /* too many bits? */ + if (blen > *outlen) { + *outlen = blen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode/store the bits */ + for (y = 0; y < blen; y++) { + if (in[x] & (1 << (7 - (y & 7)))) { + SETBIT(out[y/8], 7-(y%8)); + } else { + CLRBIT(out[y/8], 7-(y%8)); + } + if ((y & 7) == 7) { + ++x; + } + } + + /* we done */ + *outlen = blen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c b/deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c new file mode 100644 index 0000000..0c2cd16 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BIT STRING + @param in The array of bits to store (one per char) + @param inlen The number of bits tostore + @param out [out] The destination for the DER encoded BIT STRING + @param outlen [in/out] The max size and resulting size of the DER BIT STRING + @return CRYPT_OK if successful +*/ +int der_encode_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y; + unsigned char buf; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* avoid overflows */ + if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header (include bit padding count in length) */ + x = 0; + y = ((inlen + 7) >> 3) + 1; + + out[x++] = 0x03; + len = *outlen - x; + if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store number of zero padding bits */ + out[x++] = (unsigned char)((8 - inlen) & 7); + + /* store the bits in big endian format */ + for (y = buf = 0; y < inlen; y++) { + buf |= (in[y] ? 1 : 0) << (7 - (y & 7)); + if ((y & 7) == 7) { + out[x++] = buf; + buf = 0; + } + } + /* store last byte */ + if (inlen & 7) { + out[x++] = buf; + } + *outlen = x; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c b/deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c new file mode 100644 index 0000000..9cc23ae --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/bit/der_encode_raw_bit_string.c @@ -0,0 +1,75 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_bit_string.c + ASN.1 DER, encode a BIT STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k)) + +/** + Store a BIT STRING + @param in The array of bits to store (8 per char) + @param inlen The number of bits to store + @param out [out] The destination for the DER encoded BIT STRING + @param outlen [in/out] The max size and resulting size of the DER BIT STRING + @return CRYPT_OK if successful +*/ +int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y; + unsigned char buf; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* avoid overflows */ + if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header (include bit padding count in length) */ + x = 0; + y = ((inlen + 7) >> 3) + 1; + + out[x++] = 0x03; + len = *outlen - x; + if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store number of zero padding bits */ + out[x++] = (unsigned char)((8 - inlen) & 7); + + /* store the bits in big endian format */ + for (y = buf = 0; y < inlen; y++) { + buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7)); + if ((y & 7) == 7) { + out[x++] = buf; + buf = 0; + } + } + /* store last byte */ + if (inlen & 7) { + out[x++] = buf; + } + + *outlen = x; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c b/deps/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c new file mode 100644 index 0000000..4554a80 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/bit/der_length_bit_string.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_bit_string.c + ASN.1 DER, get length of BIT STRING, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of BIT STRING + @param nbits The number of bits in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_bit_string(unsigned long nbits, unsigned long *outlen) +{ + unsigned long nbytes, x; + int err; + + LTC_ARGCHK(outlen != NULL); + + /* get the number of the bytes */ + nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1; + + if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + nbytes; + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c b/deps/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c new file mode 100644 index 0000000..35ac7ec --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/boolean/der_decode_boolean.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_boolean.c + ASN.1 DER, decode a BOOLEAN, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Read a BOOLEAN + @param in The destination for the DER encoded BOOLEAN + @param inlen The size of the DER BOOLEAN + @param out [out] The boolean to decode + @return CRYPT_OK if successful +*/ +int der_decode_boolean(const unsigned char *in, unsigned long inlen, + int *out) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if (inlen < 3 || in[0] != 0x01 || in[1] != 0x01 || (in[2] != 0x00 && in[2] != 0xFF)) { + return CRYPT_INVALID_ARG; + } + + *out = (in[2]==0xFF) ? 1 : 0; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c b/deps/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c new file mode 100644 index 0000000..a77aefb --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/boolean/der_encode_boolean.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_boolean.c + ASN.1 DER, encode a BOOLEAN, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a BOOLEAN + @param in The boolean to encode + @param out [out] The destination for the DER encoded BOOLEAN + @param outlen [in/out] The max size and resulting size of the DER BOOLEAN + @return CRYPT_OK if successful +*/ +int der_encode_boolean(int in, + unsigned char *out, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(out != NULL); + + if (*outlen < 3) { + *outlen = 3; + return CRYPT_BUFFER_OVERFLOW; + } + + *outlen = 3; + out[0] = 0x01; + out[1] = 0x01; + out[2] = in ? 0xFF : 0x00; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c b/deps/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c new file mode 100644 index 0000000..f1b9e57 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/boolean/der_length_boolean.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_boolean.c + ASN.1 DER, get length of a BOOLEAN, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of a BOOLEAN + @param outlen [out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_length_boolean(unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + *outlen = 3; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c b/deps/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c new file mode 100644 index 0000000..76437f6 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c @@ -0,0 +1,221 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_choice.c + ASN.1 DER, decode a CHOICE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Decode a CHOICE + @param in The DER encoded input + @param inlen [in/out] The size of the input and resulting size of read type + @param list The list of items to decode + @param outlen The number of items in the list + @return CRYPT_OK on success +*/ +int der_decode_choice(const unsigned char *in, unsigned long *inlen, + ltc_asn1_list *list, unsigned long outlen) +{ + unsigned long size, x, z; + void *data; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(list != NULL); + + /* get blk size */ + if (*inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* set all of the "used" flags to zero */ + for (x = 0; x < outlen; x++) { + list[x].used = 0; + } + + /* now scan until we have a winner */ + for (x = 0; x < outlen; x++) { + size = list[x].size; + data = list[x].data; + + switch (list[x].type) { + case LTC_ASN1_BOOLEAN: + if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) { + if (der_length_boolean(&z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_INTEGER: + if (der_decode_integer(in, *inlen, data) == CRYPT_OK) { + if (der_length_integer(data, &z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_SHORT_INTEGER: + if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) { + if (der_length_short_integer(size, &z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_BIT_STRING: + if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_bit_string(size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_RAW_BIT_STRING: + if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_bit_string(size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_OCTET_STRING: + if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_octet_string(size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_NULL: + if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) { + *inlen = 2; + list[x].used = 1; + return CRYPT_OK; + } + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_object_identifier(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_TELETEX_STRING: + if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_teletex_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_IA5_STRING: + if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_ia5_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_PRINTABLE_STRING: + if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_printable_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_UTF8_STRING: + if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) { + if (der_length_utf8_string(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + list[x].size = size; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_UTCTIME: + z = *inlen; + if (der_decode_utctime(in, &z, data) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = *inlen; + if (der_decode_generalizedtime(in, &z, data) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + break; + + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) { + if (der_length_sequence(data, size, &z) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_CUSTOM_TYPE: + if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) { + if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) { + list[x].used = 1; + *inlen = z; + return CRYPT_OK; + } + } + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + return CRYPT_INVALID_ARG; + } + } + + return CRYPT_INVALID_PACKET; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c b/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c new file mode 100644 index 0000000..4c4d52d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_decode_custom_type.c @@ -0,0 +1,426 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @file der_decode_custom_type.c + ASN.1 DER, decode a Custom type, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Decode a Custom type + @param in The DER encoded input + @param inlen The size of the input + @param root The item that defines the custom type to decode + @return CRYPT_OK on success +*/ +int der_decode_custom_type(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root) +{ + LTC_ARGCHK(root != NULL); + return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED); +} + +/** + Extended-decode a Custom type + + This function is used to decode custom types and sequences/sets + For custom types root is used + For sequences/sets list and outlen are used + + @param in The DER encoded input + @param inlen The size of the input + @param root The item that defines the custom type to decode + @param list The list of items to decode + @param outlen The number of items in the list + @param flags c.f. enum ltc_der_seq + @return CRYPT_OK on success +*/ +int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *root, + ltc_asn1_list *list, unsigned long outlen, + unsigned int flags) +{ + int err, seq_err, i, ordered; + ltc_asn1_type type; + ltc_asn1_list ident; + unsigned long size, x, y, z, blksize; + unsigned char* in_new = NULL; + void *data; + + LTC_ARGCHK(in != NULL); + + /* get blk size */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + x = 0; + + if (root == NULL) { + LTC_ARGCHK(list != NULL); + + /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */ + if (in[x] != 0x30 && in[x] != 0x31) { + return CRYPT_INVALID_PACKET; + } + ++x; + } else { + if (root->type != LTC_ASN1_CUSTOM_TYPE) { + return CRYPT_INVALID_PACKET; + } + + /* Alloc a copy of the data for primitive handling. */ + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + in_new = XMALLOC(inlen); + if (in_new == NULL) { + return CRYPT_MEM; + } + XMEMCPY(in_new, in, inlen); + in = in_new; + } + + y = inlen; + if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((ident.type != root->type) || + (ident.klass != root->klass) || + (ident.pc != root->pc) || + (ident.tag != root->tag)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + x += y; + + list = root->data; + outlen = root->size; + } + + if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) { + if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) || + (der_asn1_type_to_identifier_map[root->used] == -1)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + root->type = (ltc_asn1_type)root->used; + list = root; + outlen = 1; + + x -= 1; + in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type]; + blksize = inlen - x; + } else { + + y = inlen - x; + if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) { + goto LBL_ERR; + } + x += y; + } + + /* would this blksize overflow? */ + if (blksize > (inlen - x)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* mark all as unused */ + for (i = 0; i < (int)outlen; i++) { + list[i].used = 0; + } + ordered = flags & LTC_DER_SEQ_ORDERED; + + /* ok read data */ + seq_err = CRYPT_OK; + blksize += x; + inlen -= x; + for (i = 0; i < (int)outlen; i++) { + z = 0; + type = list[i].type; + size = list[i].size; + data = list[i].data; + if (!ordered && list[i].used == 1) { continue; } + + if (type == LTC_ASN1_EOL) { + break; + } + + if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) { + err = CRYPT_PK_ASN1_ERROR; + goto LBL_ERR; + } + + switch (type) { + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + break; + default: + /* Verify that all basic types are indeed UNIVERSAL&PRIMITIVE */ + if (((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT) && (inlen > 0)) { + if (in[x] & 0xE0u) { + err = CRYPT_PK_ASN1_ERROR; + goto LBL_ERR; + } + } + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + z = inlen; + if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_boolean(&z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_INTEGER: + z = inlen; + if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_integer(data, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SHORT_INTEGER: + z = inlen; + if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { + goto LBL_ERR; + } + + break; + + case LTC_ASN1_BIT_STRING: + z = inlen; + if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_RAW_BIT_STRING: + z = inlen; + if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_OCTET_STRING: + z = inlen; + if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_NULL: + if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) { + if (!ordered || list[i].optional) { continue; } + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + z = 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = inlen; + if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_TELETEX_STRING: + z = inlen; + if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_IA5_STRING: + z = inlen; + if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = inlen; + if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTF8_STRING: + z = inlen; + if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + list[i].size = size; + if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTCTIME: + z = inlen; + if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = inlen; + if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + break; + + case LTC_ASN1_SET: + z = inlen; + if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + /* detect if we have the right type */ + if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + z = inlen; + err = der_decode_sequence_ex(in + x, z, data, size, flags); + if (err == CRYPT_INPUT_TOO_LONG) { + seq_err = CRYPT_INPUT_TOO_LONG; + err = CRYPT_OK; + } + if (err != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CUSTOM_TYPE: + z = inlen; + err = der_decode_custom_type(in + x, z, &list[i]); + if (err == CRYPT_INPUT_TOO_LONG) { + seq_err = CRYPT_INPUT_TOO_LONG; + err = CRYPT_OK; + } + if (err != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CHOICE: + z = inlen; + if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) { + if (!ordered || list[i].optional) { continue; } + goto LBL_ERR; + } + break; + + case LTC_ASN1_EOL: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + x += z; + inlen -= z; + list[i].used = 1; + if (!ordered) { + /* restart the decoder */ + i = -1; + } + } + + for (i = 0; i < (int)outlen; i++) { + if (list[i].used == 0 && list[i].optional == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } + + if (blksize == x && seq_err == CRYPT_OK && inlen == 0) { + /* everything decoded and no errors in nested sequences */ + err = CRYPT_OK; + } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) { + /* a sequence reported too-long input, but now we've decoded everything */ + err = CRYPT_OK; + } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) { + err = CRYPT_INVALID_PACKET; + } else { + err = CRYPT_INPUT_TOO_LONG; + } + +LBL_ERR: + if (in_new != NULL) { + XFREE(in_new); + } + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c b/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c new file mode 100644 index 0000000..2e21b4a --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c @@ -0,0 +1,228 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @file der_encode_custom_type.c + ASN.1 DER, encode a Custom Type, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Encode a Custom Type + + This function is a bit special compared to the others, as it requires the + root-ltc_asn1_list where the type is defined. + + @param root The root of the list of items to encode + @param out [out] The destination + @param outlen [in/out] The size of the output + @return CRYPT_OK on success +*/ +int der_encode_custom_type(const ltc_asn1_list *root, + unsigned char *out, unsigned long *outlen) +{ + int err; + ltc_asn1_type type; + const ltc_asn1_list *list; + unsigned long size, x, y, z, i, inlen, id_len; + void *data; + + LTC_ARGCHK(root != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; z = 0; + if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG; + + /* too big ? */ + if (*outlen < y) { + *outlen = y; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* get length of the identifier, so we know the offset where to start writing */ + if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG; + x = id_len; + + + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + list = root; + inlen = 1; + /* In case it's a PRIMITIVE type we encode directly to the output + * but leave space for a potentially longer identifier as it will + * simply be replaced afterwards. + */ + x -= 1; + } else { + list = root->data; + inlen = root->size; + /* store length, identifier will be added later */ + y = *outlen - x; + if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + x += y; + } + + /* store data */ + *outlen -= x; + for (i = 0; i < inlen; i++) { + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + type = (ltc_asn1_type)list[i].used; + } else { + type = list[i].type; + } + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + z = *outlen; + if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_INTEGER: + z = *outlen; + if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SHORT_INTEGER: + z = *outlen; + if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_BIT_STRING: + z = *outlen; + if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_RAW_BIT_STRING: + z = *outlen; + if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_OCTET_STRING: + z = *outlen; + if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_NULL: + out[x] = 0x05; + out[x+1] = 0x00; + z = 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = *outlen; + if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_IA5_STRING: + z = *outlen; + if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = *outlen; + if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTF8_STRING: + z = *outlen; + if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTCTIME: + z = *outlen; + if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = *outlen; + if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SET: + z = *outlen; + if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SETOF: + z = *outlen; + if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SEQUENCE: + z = *outlen; + if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CUSTOM_TYPE: + z = *outlen; + if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + + + x += z; + *outlen -= z; + } + + if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) { + goto LBL_ERR; + } + *outlen = x; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c b/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c new file mode 100644 index 0000000..01e58ec --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/custom_type/der_length_custom_type.c @@ -0,0 +1,203 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_custom_type.c + ASN.1 DER, length of a custom type, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Get the length of a DER custom type + + This function is a bit special compared to the others, as it requires the + root-ltc_asn1_list where the type is defined. + + @param root The root of the struct to encode + @param outlen [out] The length required in octets to store it + @param payloadlen [out] The length of the payload in octets + @return CRYPT_OK on success +*/ +int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen) +{ + int err; + const ltc_asn1_list *list; + ltc_asn1_type type; + unsigned long size, x, y, i, inlen, id_len; + void *data; + + LTC_ARGCHK(root != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) { + return err; + } + y = id_len; + + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + list = root; + inlen = 1; + } else { + list = root->data; + inlen = root->size; + } + for (i = 0; i < inlen; i++) { + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + type = (ltc_asn1_type)list[i].used; + } else { + type = list[i].type; + } + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + /* some items may be optional during import */ + if (!list[i].used && list[i].optional) continue; + + switch (type) { + case LTC_ASN1_BOOLEAN: + if ((err = der_length_boolean(&x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_INTEGER: + if ((err = der_length_integer(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SHORT_INTEGER: + if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_RAW_BIT_STRING: + if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_OCTET_STRING: + if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_NULL: + y += 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_IA5_STRING: + if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_TELETEX_STRING: + if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_PRINTABLE_STRING: + if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTCTIME: + if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_GENERALIZEDTIME: + if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTF8_STRING: + if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CUSTOM_TYPE: + if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + + if (root->pc == LTC_ASN1_PC_PRIMITIVE) { + /* In case it's a PRIMITIVE element we're going + * to only replace the identifier of the one element + * by the custom identifier. + */ + y -= 1; + if (payloadlen != NULL) { + *payloadlen = y - id_len; + } + } else { + /* calc length of length */ + if ((err = der_length_asn1_length(y - id_len, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + if (payloadlen != NULL) { + *payloadlen = y - id_len; + } + y += x; + } + + /* store size */ + *outlen = y; + +LBL_ERR: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c b/deps/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c new file mode 100644 index 0000000..8f54f09 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/general/der_asn1_maps.c @@ -0,0 +1,157 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_asn1_maps.c + ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + A Map from ltc_asn1_type to the regularly used ASN.1 identifier +*/ +const int der_asn1_type_to_identifier_map[] = +{ + /* 0 */ + -1, /* LTC_ASN1_EOL, */ + 1, /* LTC_ASN1_BOOLEAN, */ + 2, /* LTC_ASN1_INTEGER, */ + 2, /* LTC_ASN1_SHORT_INTEGER, */ + 3, /* LTC_ASN1_BIT_STRING, */ + /* 5 */ + 4, /* LTC_ASN1_OCTET_STRING, */ + 5, /* LTC_ASN1_NULL, */ + 6, /* LTC_ASN1_OBJECT_IDENTIFIER, */ + 22, /* LTC_ASN1_IA5_STRING, */ + 19, /* LTC_ASN1_PRINTABLE_STRING, */ + /* 10 */ + 12, /* LTC_ASN1_UTF8_STRING, */ + 23, /* LTC_ASN1_UTCTIME, */ + -1, /* LTC_ASN1_CHOICE, */ + 48, /* LTC_ASN1_SEQUENCE, */ + 49, /* LTC_ASN1_SET, */ + /* 15 */ + 49, /* LTC_ASN1_SETOF, */ + 3, /* LTC_ASN1_RAW_BIT_STRING, */ + 20, /* LTC_ASN1_TELETEX_STRING, */ + 24, /* LTC_ASN1_GENERALIZEDTIME, */ + -1, /* LTC_ASN1_CUSTOM_TYPE, */ +}; +const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]); + +/** + A Map from the ASN.1 Class to its string +*/ +const char* der_asn1_class_to_string_map[] = +{ + "UNIVERSAL", + "APPLICATION", + "CONTEXT-SPECIFIC", + "PRIVATE", +}; +const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]); + +/** + A Map from the ASN.1 P/C-bit to its string +*/ +const char* der_asn1_pc_to_string_map[] = +{ + "PRIMITIVE", + "CONSTRUCTED", +}; +const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]); + +/** + A Map from the ASN.1 tag to its string +*/ +const char* der_asn1_tag_to_string_map[] = +{ + "Reserved for use by the encoding rules", + "Boolean type", + "Integer type", + "Bitstring type", + "Octetstring type", + "Null type", + "Object identifier type", + "Object descriptor type", + "External type and Instance-of type", + "Real type", + "Enumerated type", + "Embedded-pdv type", + "UTF8String type", + "Relative object identifier type", + "The time type", + "Reserved for future editions of this Recommendation | International Standard", + "Sequence and Sequence-of types", + "Set and Set-of types", + "NumericString type", + "PrintableString type", + "TeletexString (T61String) type", + "VideotexString type", + "IA5String type", + "UTCTime type", + "GeneralizedTime type", + "GraphicString type", + "VisibleString (ISO646String) type", + "GeneralString type", + "UniversalString type", + "UnrestrictedCharacterString type", + "BMPString type", + "Date type", + "TimeOfDay type", + "DateTime type", + "Duration type", + "OID internationalized resource identifier type", + "Relative OID internationalized resource identifier type", +}; +const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]); + +/** + A Map from ASN.1 Tags to ltc_asn1_type +*/ +const ltc_asn1_type der_asn1_tag_to_type_map[] = +{ + /* 0 */ + LTC_ASN1_EOL, /* Reserved for use by the encoding rules */ + LTC_ASN1_BOOLEAN, /* Boolean type */ + LTC_ASN1_INTEGER, /* Integer type */ + LTC_ASN1_BIT_STRING, /* Bitstring type */ + LTC_ASN1_OCTET_STRING, /* Octetstring type */ + /* 5 */ + LTC_ASN1_NULL, /* Null type */ + LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */ + LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */ + LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */ + LTC_ASN1_CUSTOM_TYPE, /* Real type */ + /* 10 */ + LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */ + LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */ + LTC_ASN1_UTF8_STRING, /* UTF8String type */ + LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */ + LTC_ASN1_CUSTOM_TYPE, /* The time type */ + /* 15 */ + LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */ + LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */ + LTC_ASN1_SET, /* Set and Set-of types */ + LTC_ASN1_CUSTOM_TYPE, /* NumericString types */ + LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */ + /* 20 */ + LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */ + LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */ + LTC_ASN1_IA5_STRING, /* IA5String types */ + LTC_ASN1_UTCTIME, /* UTCTime types */ + LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */ + /* 25 */ + LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */ + LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */ + LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */ + LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */ + LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */ + /* 30 */ + LTC_ASN1_CUSTOM_TYPE, /* BMPString types */ +}; +const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]); + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c b/deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c new file mode 100644 index 0000000..ad4dc7b --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_identifier.c @@ -0,0 +1,123 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_asn1_identifier.c + ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */ +static const unsigned char tag_constructed_map[] = +{ + /* 0 */ + 255, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 5 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 10 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 15 */ + 255, + LTC_ASN1_PC_CONSTRUCTED, + LTC_ASN1_PC_CONSTRUCTED, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 20 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + /* 25 */ + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, + LTC_ASN1_PC_PRIMITIVE, +}; + static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]); + +/** + Decode the ASN.1 Identifier + @param id Where to store the decoded Identifier + @param in Where to read the Identifier from + @param inlen [in/out] The size of in available/read + @return CRYPT_OK if successful +*/ +int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id) +{ + ulong64 tmp; + unsigned long tag_len; + int err; + + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + + if (*inlen == 0) { + return CRYPT_BUFFER_OVERFLOW; + } + + tag_len = 1; + id->klass = (in[0] >> 6) & 0x3; + id->pc = (in[0] >> 5) & 0x1; + id->tag = in[0] & 0x1f; + + err = CRYPT_OK; + if (id->tag == 0x1f) { + id->tag = 0; + do { + if (*inlen < tag_len) { + /* break the loop and trigger the BOF error-code */ + tmp = 0xff; + break; + } + id->tag <<= 7; + id->tag |= in[tag_len] & 0x7f; + tmp = in[tag_len] & 0x80; + tag_len++; + } while ((tmp != 0) && (tag_len < 10)); + + if (tmp != 0) { + err = CRYPT_BUFFER_OVERFLOW; + } else if (id->tag < 0x1f) { + err = CRYPT_PK_ASN1_ERROR; + } + } + + if (err != CRYPT_OK) { + id->pc = 0; + id->klass = 0; + id->tag = 0; + } else { + *inlen = tag_len; + if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && + (id->tag < der_asn1_tag_to_type_map_sz) && + (id->tag < tag_constructed_map_sz) && + (id->pc == tag_constructed_map[id->tag])) { + id->type = der_asn1_tag_to_type_map[id->tag]; + } else { + if ((id->klass == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) { + id->type = LTC_ASN1_EOL; + } else { + id->type = LTC_ASN1_CUSTOM_TYPE; + } + } + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c b/deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c new file mode 100644 index 0000000..0e5a393 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/general/der_decode_asn1_length.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_asn1_length.c + ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Decode the ASN.1 Length field + @param in Where to read the length field from + @param inlen [in/out] The size of in available/read + @param outlen [out] The decoded ASN.1 length + @return CRYPT_OK if successful +*/ +int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen) +{ + unsigned long real_len, decoded_len, offset, i; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + + if (*inlen < 1) { + return CRYPT_BUFFER_OVERFLOW; + } + + real_len = in[0]; + + if (real_len < 128) { + decoded_len = real_len; + offset = 1; + } else { + real_len &= 0x7F; + if (real_len == 0) { + return CRYPT_PK_ASN1_ERROR; + } + if (real_len > sizeof(decoded_len)) { + return CRYPT_OVERFLOW; + } + if (real_len > (*inlen - 1)) { + return CRYPT_BUFFER_OVERFLOW; + } + decoded_len = 0; + offset = 1 + real_len; + for (i = 0; i < real_len; i++) { + decoded_len = (decoded_len << 8) | in[1 + i]; + } + } + + if (outlen != NULL) *outlen = decoded_len; + if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW; + *inlen = offset; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c b/deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c new file mode 100644 index 0000000..51d57ec --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_identifier.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_asn1_identifier.c + ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Encode the ASN.1 Identifier + @param id The ASN.1 Identifer to encode + @param out Where to write the identifier to + @param outlen [in/out] The size of out available/written + @return CRYPT_OK if successful +*/ +int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen) +{ + ulong64 tmp; + unsigned long tag_len; + + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(outlen != NULL); + + if (id->type != LTC_ASN1_CUSTOM_TYPE) { + if ((unsigned)id->type >= der_asn1_type_to_identifier_map_sz) { + return CRYPT_INVALID_ARG; + } + if (der_asn1_type_to_identifier_map[id->type] == -1) { + return CRYPT_INVALID_ARG; + } + if (out != NULL) { + *out = der_asn1_type_to_identifier_map[id->type]; + } + *outlen = 1; + return CRYPT_OK; + } + if (id->klass < LTC_ASN1_CL_UNIVERSAL || id->klass > LTC_ASN1_CL_PRIVATE) { + return CRYPT_INVALID_ARG; + } + if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) { + return CRYPT_INVALID_ARG; + } + if (id->tag > (ULONG_MAX >> (8 + 7))) { + return CRYPT_INVALID_ARG; + } + + if (out != NULL) { + if (*outlen < 1) { + return CRYPT_BUFFER_OVERFLOW; + } + + out[0] = id->klass << 6 | id->pc << 5; + } + + if (id->tag < 0x1f) { + if (out != NULL) { + out[0] |= id->tag & 0x1f; + } + *outlen = 1; + } else { + tag_len = 0; + tmp = id->tag; + do { + tag_len++; + tmp >>= 7; + } while (tmp); + + if (out != NULL) { + if (*outlen < tag_len + 1) { + return CRYPT_BUFFER_OVERFLOW; + } + out[0] |= 0x1f; + for (tmp = 1; tmp <= tag_len; ++tmp) { + out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80; + } + out[tag_len] &= ~0x80; + } + *outlen = tag_len + 1; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c b/deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c new file mode 100644 index 0000000..7892eea --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/general/der_encode_asn1_length.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_asn1_length.c + ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Encode the ASN.1 length field + @param len The length to encode + @param out Where to write the length field to + @param outlen [in/out] The size of out available/written + @return CRYPT_OK if successful +*/ +int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y; + + LTC_ARGCHK(outlen != NULL); + + x = len; + y = 0; + + while(x != 0) { + y++; + x >>= 8; + } + if (y == 0) { + return CRYPT_PK_ASN1_ERROR; + } + + if (out == NULL) { + if (len < 128) { + x = y; + } else { + x = y + 1; + } + } else { + if (*outlen < y) { + return CRYPT_BUFFER_OVERFLOW; + } + x = 0; + if (len < 128) { + out[x++] = (unsigned char)len; + } else if (len <= 0xffUL) { + out[x++] = 0x81; + out[x++] = (unsigned char)len; + } else if (len <= 0xffffUL) { + out[x++] = 0x82; + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffUL) { + out[x++] = 0x83; + out[x++] = (unsigned char)((len>>16UL)&255); + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + #if ULONG_MAX != ULLONG_MAX + } else { + out[x++] = 0x84; + out[x++] = (unsigned char)((len>>24UL)&255); + out[x++] = (unsigned char)((len>>16UL)&255); + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + } + #else + } else if (len <= 0xffffffffUL) { + out[x++] = 0x84; + out[x++] = (unsigned char)((len>>24UL)&255); + out[x++] = (unsigned char)((len>>16UL)&255); + out[x++] = (unsigned char)((len>>8UL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffffffULL) { + out[x++] = 0x85; + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffffffffULL) { + out[x++] = 0x86; + out[x++] = (unsigned char)((len>>40ULL)&255); + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } else if (len <= 0xffffffffffffffULL) { + out[x++] = 0x87; + out[x++] = (unsigned char)((len>>48ULL)&255); + out[x++] = (unsigned char)((len>>40ULL)&255); + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } else { + out[x++] = 0x88; + out[x++] = (unsigned char)((len>>56ULL)&255); + out[x++] = (unsigned char)((len>>48ULL)&255); + out[x++] = (unsigned char)((len>>40ULL)&255); + out[x++] = (unsigned char)((len>>32ULL)&255); + out[x++] = (unsigned char)((len>>24ULL)&255); + out[x++] = (unsigned char)((len>>16ULL)&255); + out[x++] = (unsigned char)((len>>8ULL)&255); + out[x++] = (unsigned char)(len&255); + } + #endif + } + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c b/deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c new file mode 100644 index 0000000..63e6bdd --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_identifier.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_asn1_identifier.c + ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Determine the length required when encoding the ASN.1 Identifier + @param id The ASN.1 identifier to encode + @param idlen [out] The required length to encode list + @return CRYPT_OK if successful +*/ + +int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen) +{ + return der_encode_asn1_identifier(id, NULL, idlen); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c b/deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c new file mode 100644 index 0000000..1c81adb --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/general/der_length_asn1_length.c @@ -0,0 +1,22 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_asn1_length.c + ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel +*/ + +#ifdef LTC_DER +/** + Determine the length required to encode len in the ASN.1 length field + @param len The length to encode + @param outlen [out] The length that's required to store len + @return CRYPT_OK if successful +*/ +int der_length_asn1_length(unsigned long len, unsigned long *outlen) +{ + return der_encode_asn1_length(len, NULL, outlen); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c b/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c new file mode 100644 index 0000000..7d2f296 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c @@ -0,0 +1,135 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_generalizedtime.c + ASN.1 DER, decode a GeneralizedTime, Steffen Jaeckel + Based on der_decode_utctime.c +*/ + +#ifdef LTC_DER + +static int s_char_to_int(unsigned char x) +{ + switch (x) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + default: return 100; + } +} + +#define DECODE_V(y, max) do {\ + y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 2; \ +} while(0) + +#define DECODE_V4(y, max) do {\ + y = s_char_to_int(buf[x])*1000 + s_char_to_int(buf[x+1])*100 + s_char_to_int(buf[x+2])*10 + s_char_to_int(buf[x+3]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 4; \ +} while(0) + +/** + Decodes a Generalized time structure in DER format (reads all 6 valid encoding formats) + @param in Input buffer + @param inlen Length of input buffer in octets + @param out [out] Destination of Generalized time structure + @return CRYPT_OK if successful +*/ +int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen, + ltc_generalizedtime *out) +{ + unsigned char buf[32]; + unsigned long x; + int y; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(out != NULL); + + /* check header */ + if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* decode the string */ + for (x = 0; x < in[1]; x++) { + y = der_ia5_value_decode(in[x+2]); + if (y == -1) { + return CRYPT_INVALID_PACKET; + } + if (!((y >= '0' && y <= '9') + || y == 'Z' || y == '.' + || y == '+' || y == '-')) { + return CRYPT_INVALID_PACKET; + } + buf[x] = y; + } + *inlen = 2 + x; + + if (x < 15) { + return CRYPT_INVALID_PACKET; + } + + /* possible encodings are +YYYYMMDDhhmmssZ +YYYYMMDDhhmmss+hh'mm' +YYYYMMDDhhmmss-hh'mm' +YYYYMMDDhhmmss.fsZ +YYYYMMDDhhmmss.fs+hh'mm' +YYYYMMDDhhmmss.fs-hh'mm' + + So let's do a trivial decode upto [including] ss + */ + + x = 0; + DECODE_V4(out->YYYY, 10000); + DECODE_V(out->MM, 13); + DECODE_V(out->DD, 32); + DECODE_V(out->hh, 24); + DECODE_V(out->mm, 60); + DECODE_V(out->ss, 60); + + /* clear fractional seconds info */ + out->fs = 0; + + /* now is it Z or . */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } + if (buf[x] == '.') { + x++; + while (buf[x] >= '0' && buf[x] <= '9') { + unsigned fs = out->fs; + if (x >= sizeof(buf)) return CRYPT_INVALID_PACKET; + out->fs *= 10; + out->fs += s_char_to_int(buf[x]); + if (fs > out->fs) return CRYPT_OVERFLOW; + x++; + } + } + + /* now is it Z, +, - */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } + if (buf[x] == '+' || buf[x] == '-') { + out->off_dir = (buf[x++] == '+') ? 0 : 1; + DECODE_V(out->off_hh, 24); + DECODE_V(out->off_mm, 60); + return CRYPT_OK; + } + return CRYPT_INVALID_PACKET; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c b/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c new file mode 100644 index 0000000..2378eeb --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c @@ -0,0 +1,98 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_utctime.c + ASN.1 DER, encode a GeneralizedTime, Steffen Jaeckel + Based on der_encode_utctime.c +*/ + +#ifdef LTC_DER + +static const char * const baseten = "0123456789"; + +#define STORE_V(y) do {\ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); \ +} while(0) + +#define STORE_V4(y) do {\ + out[x++] = der_ia5_char_encode(baseten[(y/1000) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[(y/100) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); \ +} while(0) + +/** + Encodes a Generalized time structure in DER format + @param gtime The GeneralizedTime structure to encode + @param out The destination of the DER encoding of the GeneralizedTime structure + @param outlen [in/out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_encode_generalizedtime(const ltc_generalizedtime *gtime, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, tmplen; + int err; + + LTC_ARGCHK(gtime != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = der_length_generalizedtime(gtime, &tmplen)) != CRYPT_OK) { + return err; + } + if (tmplen > *outlen) { + *outlen = tmplen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header */ + out[0] = 0x18; + + /* store values */ + x = 2; + STORE_V4(gtime->YYYY); + STORE_V(gtime->MM); + STORE_V(gtime->DD); + STORE_V(gtime->hh); + STORE_V(gtime->mm); + STORE_V(gtime->ss); + + if (gtime->fs) { + unsigned long divisor; + unsigned fs = gtime->fs; + unsigned len = 0; + out[x++] = der_ia5_char_encode('.'); + divisor = 1; + do { + fs /= 10; + divisor *= 10; + len++; + } while(fs != 0); + while (len-- > 1) { + divisor /= 10; + out[x++] = der_ia5_char_encode(baseten[(gtime->fs/divisor) % 10]); + } + out[x++] = der_ia5_char_encode(baseten[gtime->fs % 10]); + } + + if (gtime->off_mm || gtime->off_hh) { + out[x++] = der_ia5_char_encode(gtime->off_dir ? '-' : '+'); + STORE_V(gtime->off_hh); + STORE_V(gtime->off_mm); + } else { + out[x++] = der_ia5_char_encode('Z'); + } + + /* store length */ + out[1] = (unsigned char)(x - 2); + + /* all good let's return */ + *outlen = x; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c b/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c new file mode 100644 index 0000000..dc237d3 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_utctime.c + ASN.1 DER, get length of GeneralizedTime, Steffen Jaeckel + Based on der_length_utctime.c +*/ + +#ifdef LTC_DER + +/** + Gets length of DER encoding of GeneralizedTime + @param gtime The GeneralizedTime structure to get the size of + @param outlen [out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_length_generalizedtime(const ltc_generalizedtime *gtime, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(gtime != NULL); + + if (gtime->fs == 0) { + /* we encode as YYYYMMDDhhmmssZ */ + *outlen = 2 + 14 + 1; + } else { + unsigned long len = 2 + 14 + 1; + unsigned fs = gtime->fs; + do { + fs /= 10; + len++; + } while(fs != 0); + if (gtime->off_hh == 0 && gtime->off_mm == 0) { + /* we encode as YYYYMMDDhhmmss.fsZ */ + len += 1; + } + else { + /* we encode as YYYYMMDDhhmmss.fs{+|-}hh'mm' */ + len += 5; + } + *outlen = len; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c b/deps/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c new file mode 100644 index 0000000..8fd80cf --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/ia5/der_decode_ia5_string.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_ia5_string.c + ASN.1 DER, encode a IA5 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a IA5 STRING + @param in The DER encoded IA5 STRING + @param inlen The size of the DER IA5 STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t, err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x16 */ + if ((in[0] & 0x1F) != 0x16) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_ia5_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c b/deps/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c new file mode 100644 index 0000000..8b8bd36 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/ia5/der_encode_ia5_string.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_ia5_string.c + ASN.1 DER, encode a IA5 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Store an IA5 STRING + @param in The array of IA5 to store (one per char) + @param inlen The number of IA5 to store + @param out [out] The destination for the DER encoded IA5 STRING + @param outlen [in/out] The max size and resulting size of the DER IA5 STRING + @return CRYPT_OK if successful +*/ +int der_encode_ia5_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_ia5_string(in, inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x16; + len = *outlen - x; + if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_ia5_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c b/deps/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c new file mode 100644 index 0000000..e397b1c --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/ia5/der_length_ia5_string.c @@ -0,0 +1,172 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_ia5_string.c + ASN.1 DER, get length of IA5 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} ia5_table[] = { +{ '\0', 0 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '#', 35 }, +{ '$', 36 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '*', 42 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ ';', 59 }, +{ '<', 60 }, +{ '=', 61 }, +{ '>', 62 }, +{ '?', 63 }, +{ '@', 64 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ '[', 91 }, +{ '\\', 92 }, +{ ']', 93 }, +{ '^', 94 }, +{ '_', 95 }, +{ '`', 96 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +{ '{', 123 }, +{ '|', 124 }, +{ '}', 125 }, +{ '~', 126 } +}; + +int der_ia5_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { + if (ia5_table[x].code == c) { + return ia5_table[x].value; + } + } + return -1; +} + +int der_ia5_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(ia5_table)/sizeof(ia5_table[0])); x++) { + if (ia5_table[x].value == v) { + return ia5_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of IA5 STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + int err; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_ia5_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c b/deps/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c new file mode 100644 index 0000000..2c9bf7b --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/integer/der_decode_integer.c @@ -0,0 +1,68 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_integer.c + ASN.1 DER, decode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Read a mp_int integer + @param in The DER encoded data + @param inlen Size of DER encoded data + @param num The first mp_int to decode + @return CRYPT_OK if successful +*/ +int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num) +{ + unsigned long x, y; + int err; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(in != NULL); + + /* min DER INTEGER is 0x02 01 00 == 0 */ + if (inlen < (1 + 1 + 1)) { + return CRYPT_INVALID_PACKET; + } + + /* ok expect 0x02 when we AND with 0001 1111 [1F] */ + x = 0; + if ((in[x++] & 0x1F) != 0x02) { + return CRYPT_INVALID_PACKET; + } + + /* get the length of the data */ + inlen -= x; + if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) { + return err; + } + x += inlen; + + if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) { + return err; + } + + /* see if it's negative */ + if (in[x] & 0x80) { + void *tmp; + if (mp_init(&tmp) != CRYPT_OK) { + return CRYPT_MEM; + } + + if (mp_2expt(tmp, mp_count_bits(num)) != CRYPT_OK || mp_sub(num, tmp, num) != CRYPT_OK) { + mp_clear(tmp); + return CRYPT_MEM; + } + mp_clear(tmp); + } + + return CRYPT_OK; + +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c b/deps/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c new file mode 100644 index 0000000..7261149 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c @@ -0,0 +1,105 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_integer.c + ASN.1 DER, encode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/* Exports a positive bignum as DER format (upto 2^32 bytes in size) */ +/** + Store a mp_int integer + @param num The first mp_int to encode + @param out [out] The destination for the DER encoded integers + @param outlen [in/out] The max size and resulting size of the DER encoded integers + @return CRYPT_OK if successful +*/ +int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen) +{ + unsigned long tmplen, y, len; + int err, leading_zero; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* find out how big this will be */ + if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) { + return err; + } + + if (*outlen < tmplen) { + *outlen = tmplen; + return CRYPT_BUFFER_OVERFLOW; + } + + if (mp_cmp_d(num, 0) != LTC_MP_LT) { + /* we only need a leading zero if the msb of the first byte is one */ + if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) { + leading_zero = 1; + } else { + leading_zero = 0; + } + + /* get length of num in bytes (plus 1 since we force the msbyte to zero) */ + y = mp_unsigned_bin_size(num) + leading_zero; + } else { + leading_zero = 0; + y = mp_count_bits(num); + y = y + (8 - (y & 7)); + y = y >> 3; + if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --y; + } + + /* now store initial data */ + *out++ = 0x02; + len = *outlen - 1; + if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) { + return err; + } + out += len; + + /* now store msbyte of zero if num is non-zero */ + if (leading_zero) { + *out++ = 0x00; + } + + /* if it's not zero store it as big endian */ + if (mp_cmp_d(num, 0) == LTC_MP_GT) { + /* now store the mpint */ + if ((err = mp_to_unsigned_bin(num, out)) != CRYPT_OK) { + return err; + } + } else if (mp_iszero(num) != LTC_MP_YES) { + void *tmp; + + /* negative */ + if (mp_init(&tmp) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* 2^roundup and subtract */ + y = mp_count_bits(num); + y = y + (8 - (y & 7)); + if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) y -= 8; + if (mp_2expt(tmp, y) != CRYPT_OK || mp_add(tmp, num, tmp) != CRYPT_OK) { + mp_clear(tmp); + return CRYPT_MEM; + } + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { + mp_clear(tmp); + return err; + } + mp_clear(tmp); + } + + /* we good */ + *outlen = tmplen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c b/deps/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c new file mode 100644 index 0000000..90e2de3 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/integer/der_length_integer.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_integer.c + ASN.1 DER, get length of encoding, Tom St Denis +*/ + + +#ifdef LTC_DER +/** + Gets length of DER encoding of num + @param num The int to get the size of + @param outlen [out] The length of the DER encoding for the given integer + @return CRYPT_OK if successful +*/ +int der_length_integer(void *num, unsigned long *outlen) +{ + unsigned long z, len; + int leading_zero, err; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(outlen != NULL); + + if (mp_cmp_d(num, 0) != LTC_MP_LT) { + /* positive */ + + /* we only need a leading zero if the msb of the first byte is one */ + if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == LTC_MP_YES) { + leading_zero = 1; + } else { + leading_zero = 0; + } + + /* size for bignum */ + len = leading_zero + mp_unsigned_bin_size(num); + } else { + /* it's negative */ + /* find power of 2 that is a multiple of eight and greater than count bits */ + z = mp_count_bits(num); + z = z + (8 - (z & 7)); + if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z; + len = z >> 3; + } + + if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) { + return err; + } + *outlen = 1 + z + len; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c b/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c new file mode 100644 index 0000000..7251247 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_decode_object_identifier.c @@ -0,0 +1,94 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_object_identifier.c + ASN.1 DER, Decode Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Decode OID data and store the array of integers in words + @param in The OID DER encoded data + @param inlen The length of the OID data + @param words [out] The destination of the OID words + @param outlen [in/out] The number of OID words + @return CRYPT_OK if successful +*/ +int der_decode_object_identifier(const unsigned char *in, unsigned long inlen, + unsigned long *words, unsigned long *outlen) +{ + unsigned long x, y, t, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(outlen != NULL); + + /* header is at least 3 bytes */ + if (inlen < 3) { + return CRYPT_INVALID_PACKET; + } + + /* must be room for at least two words */ + if (*outlen < 2) { + *outlen = 2; + return CRYPT_BUFFER_OVERFLOW; + } + + /* decode the packet header */ + x = 0; + if ((in[x++] & 0x1F) != 0x06) { + return CRYPT_INVALID_PACKET; + } + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + if ((len == 0) || (len > (inlen - x))) { + return CRYPT_INVALID_PACKET; + } + + /* decode words */ + y = 0; + t = 0; + while (len--) { + t = (t << 7) | (in[x] & 0x7F); + if (!(in[x++] & 0x80)) { + /* store t */ + if (y >= *outlen) { + y++; + } else { + if (y == 0) { + if (t <= 79) { + words[0] = t / 40; + words[1] = t % 40; + } else { + words[0] = 2; + words[1] = t - 80; + } + y = 2; + } else { + words[y++] = t; + } + } + t = 0; + } + } + + if (y > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; + } + + *outlen = y; + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c b/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c new file mode 100644 index 0000000..9a9c62d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_encode_object_identifier.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_object_identifier.c + ASN.1 DER, Encode Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Encode an OID + @param words The words to encode (upto 32-bits each) + @param nwords The number of words in the OID + @param out [out] Destination of OID data + @param outlen [in/out] The max and resulting size of the OID + @return CRYPT_OK if successful +*/ +int der_encode_object_identifier(const unsigned long *words, unsigned long nwords, + unsigned char *out, unsigned long *outlen) +{ + unsigned long i, x, y, z, t, mask, wordbuf; + int err; + + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* check length */ + if ((err = der_length_object_identifier(words, nwords, &x)) != CRYPT_OK) { + return err; + } + if (x > *outlen) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + + /* compute length to store OID data */ + z = 0; + wordbuf = words[0] * 40 + words[1]; + for (y = 1; y < nwords; y++) { + t = der_object_identifier_bits(wordbuf); + z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0); + if (y < nwords - 1) { + wordbuf = words[y + 1]; + } + } + + /* store header + length */ + x = 0; + out[x++] = 0x06; + y = *outlen - x; + if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) { + return err; + } + x += y; + + /* store first byte */ + wordbuf = words[0] * 40 + words[1]; + for (i = 1; i < nwords; i++) { + /* store 7 bit words in little endian */ + t = wordbuf & 0xFFFFFFFF; + if (t) { + y = x; + mask = 0; + while (t) { + out[x++] = (unsigned char)((t & 0x7F) | mask); + t >>= 7; + mask |= 0x80; /* upper bit is set on all but the last byte */ + } + /* now swap bytes y...x-1 */ + z = x - 1; + while (y < z) { + t = out[y]; out[y] = out[z]; out[z] = (unsigned char)t; + ++y; + --z; + } + } else { + /* zero word */ + out[x++] = 0x00; + } + + if (i < nwords - 1) { + wordbuf = words[i + 1]; + } + } + + *outlen = x; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c b/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c new file mode 100644 index 0000000..d9ded02 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/object_identifier/der_length_object_identifier.c @@ -0,0 +1,77 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_object_identifier.c + ASN.1 DER, get length of Object Identifier, Tom St Denis +*/ + +#ifdef LTC_DER + +unsigned long der_object_identifier_bits(unsigned long x) +{ + unsigned long c; + x &= 0xFFFFFFFF; + c = 0; + while (x) { + ++c; + x >>= 1; + } + return c; +} + + +/** + Gets length of DER encoding of Object Identifier + @param nwords The number of OID words + @param words The actual OID words to get the size of + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_object_identifier(const unsigned long *words, unsigned long nwords, unsigned long *outlen) +{ + unsigned long y, z, t, wordbuf; + + LTC_ARGCHK(words != NULL); + LTC_ARGCHK(outlen != NULL); + + + /* must be >= 2 words */ + if (nwords < 2) { + return CRYPT_INVALID_ARG; + } + + /* word1 = 0,1,2 and word2 0..39 */ + if (words[0] > 2 || (words[0] < 2 && words[1] > 39)) { + return CRYPT_INVALID_ARG; + } + + /* leading word is the first two */ + z = 0; + wordbuf = words[0] * 40 + words[1]; + for (y = 1; y < nwords; y++) { + t = der_object_identifier_bits(wordbuf); + z += t/7 + ((t%7) ? 1 : 0) + (wordbuf == 0 ? 1 : 0); + if (y < nwords - 1) { + /* grab next word */ + wordbuf = words[y+1]; + } + } + + /* now depending on the length our length encoding changes */ + if (z < 128) { + z += 2; + } else if (z < 256) { + z += 3; + } else if (z < 65536UL) { + z += 4; + } else { + return CRYPT_INVALID_ARG; + } + + *outlen = z; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c b/deps/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c new file mode 100644 index 0000000..df84721 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/octet/der_decode_octet_string.c @@ -0,0 +1,69 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_octet_string.c + ASN.1 DER, encode a OCTET STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a OCTET STRING + @param in The DER encoded OCTET STRING + @param inlen The size of the DER OCTET STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x04 */ + if ((in[0] & 0x1F) != 0x04) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + out[y] = in[x++]; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c b/deps/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c new file mode 100644 index 0000000..73f1ee7 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/octet/der_encode_octet_string.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_octet_string.c + ASN.1 DER, encode a OCTET STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store an OCTET STRING + @param in The array of OCTETS to store (one per char) + @param inlen The number of OCTETS to store + @param out [out] The destination for the DER encoded OCTET STRING + @param outlen [in/out] The max size and resulting size of the DER OCTET STRING + @return CRYPT_OK if successful +*/ +int der_encode_octet_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_octet_string(inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x04; + len = *outlen - x; + if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = in[y]; + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c b/deps/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c new file mode 100644 index 0000000..67b071e --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/octet/der_length_octet_string.c @@ -0,0 +1,33 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_octet_string.c + ASN.1 DER, get length of OCTET STRING, Tom St Denis +*/ + +#ifdef LTC_DER +/** + Gets length of DER encoding of OCTET STRING + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_octet_string(unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + int err; + + LTC_ARGCHK(outlen != NULL); + + if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c b/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c new file mode 100644 index 0000000..3f9b533 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_decode_printable_string.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_printable_string.c + ASN.1 DER, encode a printable STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a printable STRING + @param in The DER encoded printable STRING + @param inlen The size of the DER printable STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t, err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x13 */ + if ((in[0] & 0x1F) != 0x13) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_printable_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c b/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c new file mode 100644 index 0000000..7b3aefd --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_encode_printable_string.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_printable_string.c + ASN.1 DER, encode a printable STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Store an printable STRING + @param in The array of printable to store (one per char) + @param inlen The number of printable to store + @param out [out] The destination for the DER encoded printable STRING + @param outlen [in/out] The max size and resulting size of the DER printable STRING + @return CRYPT_OK if successful +*/ +int der_encode_printable_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + if ((err = der_length_printable_string(in, inlen, &len)) != CRYPT_OK) { + return err; + } + + /* too big? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x13; + len = *outlen - x; + if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) { + return err; + } + x += len; + + /* store octets */ + for (y = 0; y < inlen; y++) { + out[x++] = der_printable_char_encode(in[y]); + } + + /* retun length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c b/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c new file mode 100644 index 0000000..c52e36d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/printable_string/der_length_printable_string.c @@ -0,0 +1,144 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_printable_string.c + ASN.1 DER, get length of Printable STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} printable_table[] = { +{ ' ', 32 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ '=', 61 }, +{ '?', 63 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +}; + +int der_printable_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { + if (printable_table[x].code == c) { + return printable_table[x].value; + } + } + return -1; +} + +int der_printable_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(printable_table)/sizeof(printable_table[0])); x++) { + if (printable_table[x].value == v) { + return printable_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of Printable STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + int err; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_printable_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c new file mode 100644 index 0000000..6d7f846 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @file der_decode_sequence_ex.c + ASN.1 DER, decode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Decode a SEQUENCE + @param in The DER encoded input + @param inlen The size of the input + @param list The list of items to decode + @param outlen The number of items in the list + @param flags c.f. enum ltc_der_seq + @return CRYPT_OK on success +*/ +int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, + ltc_asn1_list *list, unsigned long outlen, unsigned int flags) +{ + return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c new file mode 100644 index 0000000..2a0841d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @@ -0,0 +1,541 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_sequence_flexi.c + ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis +*/ + +#ifdef LTC_DER + +static int s_new_element(ltc_asn1_list **l) +{ + /* alloc new link */ + if (*l == NULL) { + *l = XCALLOC(1, sizeof(ltc_asn1_list)); + if (*l == NULL) { + return CRYPT_MEM; + } + } else { + (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list)); + if ((*l)->next == NULL) { + return CRYPT_MEM; + } + (*l)->next->prev = *l; + *l = (*l)->next; + } + return CRYPT_OK; +} + +/** + ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. + @param in The input buffer + @param inlen [in/out] The length of the input buffer and on output the amount of decoded data + @param out [out] A pointer to the linked list + @param depth The depth/level of decoding recursion we've already reached + @return CRYPT_OK on success. +*/ +static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth) +{ + ltc_asn1_list *l; + unsigned long err, identifier, len, totlen, data_offset, id_len, len_len; + void *realloc_tmp; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(out != NULL); + + l = NULL; + totlen = 0; + + if (*inlen == 0) { + /* alloc new link */ + if ((err = s_new_element(&l)) != CRYPT_OK) { + goto error; + } + } + + /* scan the input and and get lengths and what not */ + while (*inlen) { + /* alloc new link */ + if ((err = s_new_element(&l)) != CRYPT_OK) { + goto error; + } + + id_len = *inlen; + if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) { + goto error; + } + /* read the type byte */ + identifier = *in; + + if (l->type != LTC_ASN1_EOL) { + /* fetch length */ + len_len = *inlen - id_len; +#if defined(LTC_TEST_DBG) + data_offset = 666; + len = 0; +#endif + if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) { +#if defined(LTC_TEST_DBG) + fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err)); +#endif + goto error; + } else if (len > (*inlen - id_len - len_len)) { + err = CRYPT_INVALID_PACKET; +#if defined(LTC_TEST_DBG) + fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err)); +#endif + goto error; + } + data_offset = id_len + len_len; +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + if (l->type == LTC_ASN1_CUSTOM_TYPE && l->klass == LTC_ASN1_CL_CONTEXT_SPECIFIC) { + fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag); + } else { + fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]); + } +#endif + len += data_offset; + + if (l->type == LTC_ASN1_CUSTOM_TYPE) { + /* Custom type, use the 'used' field to store the original identifier */ + l->used = identifier; + if (l->pc == LTC_ASN1_PC_CONSTRUCTED) { + /* treat constructed elements like SEQUENCEs */ + identifier = 0x20; + } else { + /* primitive elements are treated as opaque data */ + identifier = 0x80; + } + } + } else { + /* Init this so gcc won't complain, + * as this case will only be hit when we + * can't decode the identifier so the + * switch-case should go to default anyway... + */ + data_offset = 0; + len = 0; + } + + /* now switch on type */ + switch (identifier) { + case 0x01: /* BOOLEAN */ + if (l->type != LTC_ASN1_BOOLEAN) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = 1; + l->data = XCALLOC(1, sizeof(int)); + + if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_boolean(&len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x02: /* INTEGER */ + if (l->type != LTC_ASN1_INTEGER) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = 1; + if ((err = mp_init(&l->data)) != CRYPT_OK) { + goto error; + } + + /* decode field */ + if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) { + goto error; + } + + /* calc length of object */ + if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x03: /* BIT */ + if (l->type != LTC_ASN1_BIT_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */ + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x04: /* OCTET */ + if (l->type != LTC_ASN1_OCTET_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x05: /* NULL */ + if (l->type != LTC_ASN1_NULL) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* valid NULL is 0x05 0x00 */ + if (in[0] != 0x05 || in[1] != 0x00) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* simple to store ;-) */ + l->data = NULL; + l->size = 0; + len = 2; + + break; + + case 0x06: /* OID */ + if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + + /* resize it to save a bunch of mem */ + if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) { + /* out of heap but this is not an error */ + break; + } + l->data = realloc_tmp; + break; + + case 0x0C: /* UTF8 */ + + /* init field */ + if (l->type != LTC_ASN1_UTF8_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + l->size = len; + + if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x13: /* PRINTABLE */ + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x14: /* TELETEXT */ + if (l->type != LTC_ASN1_TELETEX_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x16: /* IA5 */ + if (l->type != LTC_ASN1_IA5_STRING) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(1, l->size)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x17: /* UTC TIME */ + if (l->type != LTC_ASN1_UTCTIME) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = 1; + + if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) { + err = CRYPT_MEM; + goto error; + } + + len = *inlen; + if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) { + goto error; + } + break; + + case 0x18: + if (l->type != LTC_ASN1_GENERALIZEDTIME) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* init field */ + l->size = len; + + if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) { + err = CRYPT_MEM; + goto error; + } + + if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) { + goto error; + } + + if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) { + goto error; + } + + break; + + case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */ + case 0x30: /* SEQUENCE */ + case 0x31: /* SET */ + + /* init field */ + if (identifier == 0x20) { + if (l->type != LTC_ASN1_CUSTOM_TYPE) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + } + else if (identifier == 0x30) { + if (l->type != LTC_ASN1_SEQUENCE) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + } + else { + if (l->type != LTC_ASN1_SET) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + } + + /* check that we don't go over the recursion limit */ + if (depth > LTC_DER_MAX_RECURSION) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + if ((l->data = XMALLOC(len)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + XMEMCPY(l->data, in, len); + l->size = len; + + + /* jump to the start of the data */ + in += data_offset; + *inlen -= data_offset; + len -= data_offset; + + /* save the decoded ASN.1 len */ + len_len = len; + + /* Sequence elements go as child */ + if ((err = s_der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) { + goto error; + } + if (len_len != len) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + /* len update */ + totlen += data_offset; + + /* the flexi decoder can also do nothing, so make sure a child has been allocated */ + if (l->child) { + /* link them up y0 */ + l->child->parent = l; + } + + break; + + case 0x80: /* Context-specific */ + if (l->type != LTC_ASN1_CUSTOM_TYPE) { + err = CRYPT_PK_ASN1_ERROR; + goto error; + } + + if ((l->data = XCALLOC(1, len - data_offset)) == NULL) { + err = CRYPT_MEM; + goto error; + } + + XMEMCPY(l->data, in + data_offset, len - data_offset); + l->size = len - data_offset; + + break; + + default: + /* invalid byte ... this is a soft error */ + /* remove link */ + if (l->prev) { + l = l->prev; + XFREE(l->next); + l->next = NULL; + } + goto outside; + } + + /* advance pointers */ + totlen += len; + in += len; + *inlen -= len; + } + +outside: + + /* in case we processed anything */ + if (totlen) { + /* rewind l please */ + while (l->prev != NULL || l->parent != NULL) { + if (l->parent != NULL) { + l = l->parent; + } else { + l = l->prev; + } + } + } + + /* return */ + *out = l; + *inlen = totlen; + return CRYPT_OK; + +error: + /* free list */ + der_sequence_free(l); + + return err; +} + +/** + ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements. + @param in The input buffer + @param inlen [in/out] The length of the input buffer and on output the amount of decoded data + @param out [out] A pointer to the linked list + @return CRYPT_OK on success. +*/ +int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out) +{ + return s_der_decode_sequence_flexi(in, inlen, out, 0); +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c new file mode 100644 index 0000000..776c2ed --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c @@ -0,0 +1,181 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + + +/** + @file der_decode_sequence_multi.c + ASN.1 DER, decode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Decode a SEQUENCE type using a VA list + @param in Input buffer + @param inlen Length of input in octets + @param a1 Initialized argument list #1 + @param a2 Initialized argument list #2 (copy of #1) + @param flags c.f. enum ltc_der_seq + @return CRYPT_OK on success +*/ +static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags) +{ + int err; + ltc_asn1_type type; + unsigned long size, x; + void *data; + ltc_asn1_list *list; + + LTC_ARGCHK(in != NULL); + + /* get size of output that will be required */ + x = 0; + for (;;) { + type = (ltc_asn1_type)va_arg(a1, int); + + if (type == LTC_ASN1_EOL) { + break; + } + + size = va_arg(a1, unsigned long); + data = va_arg(a1, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_CHOICE: + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_TELETEX_STRING: + case LTC_ASN1_GENERALIZEDTIME: + ++x; + break; + + case LTC_ASN1_EOL: + case LTC_ASN1_CUSTOM_TYPE: + return CRYPT_INVALID_ARG; + } + } + + /* allocate structure for x elements */ + if (x == 0) { + return CRYPT_NOP; + } + + list = XCALLOC(sizeof(*list), x); + if (list == NULL) { + return CRYPT_MEM; + } + + /* fill in the structure */ + x = 0; + for (;;) { + type = (ltc_asn1_type)va_arg(a2, int); + size = va_arg(a2, unsigned long); + data = va_arg(a2, void*); + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_CHOICE: + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_TELETEX_STRING: + case LTC_ASN1_GENERALIZEDTIME: + LTC_SET_ASN1(list, x++, type, data, size); + break; + /* coverity[dead_error_line] */ + case LTC_ASN1_EOL: + case LTC_ASN1_CUSTOM_TYPE: + break; + } + } + + err = der_decode_sequence_ex(in, inlen, list, x, flags); + XFREE(list); + return err; +} + +/** + Decode a SEQUENCE type using a VA list + @param in Input buffer + @param inlen Length of input in octets + @remark <...> is of the form (int, unsigned long, void*) + @return CRYPT_OK on success +*/ +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) +{ + va_list a1, a2; + int err; + + LTC_ARGCHK(in != NULL); + + va_start(a1, inlen); + va_start(a2, inlen); + + err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED); + + va_end(a2); + va_end(a1); + + return err; +} + +/** + Decode a SEQUENCE type using a VA list + @param in Input buffer + @param inlen Length of input in octets + @param flags c.f. enum ltc_der_seq + @remark <...> is of the form (int, unsigned long, void*) + @return CRYPT_OK on success +*/ +int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) +{ + va_list a1, a2; + int err; + + LTC_ARGCHK(in != NULL); + + va_start(a1, flags); + va_start(a2, flags); + + err = s_der_decode_sequence_va(in, inlen, a1, a2, flags); + + va_end(a2); + va_end(a1); + + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c new file mode 100644 index 0000000..d5c81bb --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c @@ -0,0 +1,202 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +/** + @file der_encode_sequence_ex.c + ASN.1 DER, encode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Encode a SEQUENCE + @param list The list of items to encode + @param inlen The number of items in the list + @param out [out] The destination + @param outlen [in/out] The size of the output + @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF + @return CRYPT_OK on success +*/ +int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int type_of) +{ + int err; + ltc_asn1_type type; + unsigned long size, x, y, z, i; + void *data; + + LTC_ARGCHK(list != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; z = 0; + if ((err = der_length_sequence_ex(list, inlen, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG; + + /* too big ? */ + if (*outlen < y) { + *outlen = y; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* store header */ + x = 0; + out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31; + + y = *outlen - x; + if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) { + goto LBL_ERR; + } + x += y; + + /* store data */ + *outlen -= x; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + switch (type) { + case LTC_ASN1_BOOLEAN: + z = *outlen; + if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_INTEGER: + z = *outlen; + if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SHORT_INTEGER: + z = *outlen; + if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_BIT_STRING: + z = *outlen; + if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_RAW_BIT_STRING: + z = *outlen; + if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_OCTET_STRING: + z = *outlen; + if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_NULL: + out[x] = 0x05; + out[x+1] = 0x00; + z = 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + z = *outlen; + if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_IA5_STRING: + z = *outlen; + if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_PRINTABLE_STRING: + z = *outlen; + if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTF8_STRING: + z = *outlen; + if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_UTCTIME: + z = *outlen; + if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_GENERALIZEDTIME: + z = *outlen; + if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SET: + z = *outlen; + if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SETOF: + z = *outlen; + if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_SEQUENCE: + z = *outlen; + if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CUSTOM_TYPE: + z = *outlen; + if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) { + goto LBL_ERR; + } + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + + x += z; + *outlen -= z; + } + *outlen = x; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c new file mode 100644 index 0000000..615488d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c @@ -0,0 +1,139 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" +#include + + +/** + @file der_encode_sequence_multi.c + ASN.1 DER, encode a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Encode a SEQUENCE type using a VA list + @param out [out] Destination for data + @param outlen [in/out] Length of buffer and resulting length of output + @remark <...> is of the form (int, unsigned long, void*) + @return CRYPT_OK on success +*/ +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) +{ + int err; + ltc_asn1_type type; + unsigned long size, x; + void *data; + va_list args; + ltc_asn1_list *list; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + va_start(args, outlen); + x = 0; + for (;;) { + type = (ltc_asn1_type)va_arg(args, int); + + if (type == LTC_ASN1_EOL) { + break; + } + + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_GENERALIZEDTIME: + ++x; + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + va_end(args); + return CRYPT_INVALID_ARG; + } + } + va_end(args); + + /* allocate structure for x elements */ + if (x == 0) { + return CRYPT_NOP; + } + + list = XCALLOC(sizeof(*list), x); + if (list == NULL) { + return CRYPT_MEM; + } + + /* fill in the structure */ + va_start(args, outlen); + x = 0; + for (;;) { + type = (ltc_asn1_type)va_arg(args, int); + + if (type == LTC_ASN1_EOL) { + break; + } + + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + + switch (type) { + case LTC_ASN1_BOOLEAN: + case LTC_ASN1_INTEGER: + case LTC_ASN1_SHORT_INTEGER: + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_OCTET_STRING: + case LTC_ASN1_NULL: + case LTC_ASN1_OBJECT_IDENTIFIER: + case LTC_ASN1_IA5_STRING: + case LTC_ASN1_PRINTABLE_STRING: + case LTC_ASN1_UTF8_STRING: + case LTC_ASN1_UTCTIME: + case LTC_ASN1_SEQUENCE: + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_RAW_BIT_STRING: + case LTC_ASN1_GENERALIZEDTIME: + LTC_SET_ASN1(list, x++, type, data, size); + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_EOL: + case LTC_ASN1_TELETEX_STRING: + va_end(args); + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + va_end(args); + + err = der_encode_sequence(list, x, out, outlen); +LBL_ERR: + XFREE(list); + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c new file mode 100644 index 0000000..6d25391 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_length_sequence.c @@ -0,0 +1,179 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_sequence.c + ASN.1 DER, length a SEQUENCE, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Get the length of a DER sequence + @param list The sequences of items in the SEQUENCE + @param inlen The number of items + @param outlen [out] The length required in octets to store it + @return CRYPT_OK on success +*/ +int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen) +{ + return der_length_sequence_ex(list, inlen, outlen, NULL); +} + +int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, + unsigned long *outlen, unsigned long *payloadlen) +{ + int err; + ltc_asn1_type type; + unsigned long size, x, y, i; + void *data; + + LTC_ARGCHK(list != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get size of output that will be required */ + y = 0; + for (i = 0; i < inlen; i++) { + type = list[i].type; + size = list[i].size; + data = list[i].data; + + if (type == LTC_ASN1_EOL) { + break; + } + + /* some items may be optional during import */ + if (!list[i].used && list[i].optional) continue; + + switch (type) { + case LTC_ASN1_BOOLEAN: + if ((err = der_length_boolean(&x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_INTEGER: + if ((err = der_length_integer(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SHORT_INTEGER: + if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_BIT_STRING: + case LTC_ASN1_RAW_BIT_STRING: + if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_OCTET_STRING: + if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_NULL: + y += 2; + break; + + case LTC_ASN1_OBJECT_IDENTIFIER: + if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_IA5_STRING: + if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_TELETEX_STRING: + if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_PRINTABLE_STRING: + if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTCTIME: + if ((err = der_length_utctime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_GENERALIZEDTIME: + if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_UTF8_STRING: + if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CUSTOM_TYPE: + if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_SET: + case LTC_ASN1_SETOF: + case LTC_ASN1_SEQUENCE: + if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + y += x; + break; + + case LTC_ASN1_CHOICE: + case LTC_ASN1_EOL: + err = CRYPT_INVALID_ARG; + goto LBL_ERR; + } + } + + if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + if (payloadlen != NULL) { + *payloadlen = y; + } + + /* store size */ + *outlen = y + x + 1; + err = CRYPT_OK; + +LBL_ERR: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c new file mode 100644 index 0000000..b7cbd07 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_free.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_sequence_free.c + ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Free memory allocated by der_decode_sequence_flexi() + @param in The list to free +*/ +void der_sequence_free(ltc_asn1_list *in) +{ + ltc_asn1_list *l; + + if (!in) return; + + /* walk to the start of the chain */ + while (in->prev != NULL || in->parent != NULL) { + if (in->parent != NULL) { + in = in->parent; + } else { + in = in->prev; + } + } + + /* now walk the list and free stuff */ + while (in != NULL) { + /* is there a child? */ + if (in->child) { + /* disconnect */ + in->child->parent = NULL; + der_sequence_free(in->child); + } + + switch (in->type) { + case LTC_ASN1_SETOF: break; + case LTC_ASN1_INTEGER : if (in->data != NULL) { mp_clear(in->data); } break; + default : if (in->data != NULL) { XFREE(in->data); } + } + + /* move to next and free current */ + l = in->next; + XFREE(in); + in = l; + } +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c new file mode 100644 index 0000000..22634a3 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/sequence/der_sequence_shrink.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_sequence_shrink.c + Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi(), Steffen Jaeckel +*/ + +#ifdef LTC_DER + +/** + Free memory allocated for CONSTRUCTED, + SET or SEQUENCE elements by der_decode_sequence_flexi() + @param in The list to shrink +*/ +void der_sequence_shrink(ltc_asn1_list *in) +{ + if (!in) return; + + /* now walk the list and free stuff */ + while (in != NULL) { + /* is there a child? */ + if (in->child) { + der_sequence_shrink(in->child); + } + + switch (in->type) { + case LTC_ASN1_CUSTOM_TYPE: + case LTC_ASN1_SET: + case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break; + default: break; + } + + /* move to next and free current */ + in = in->next; + } +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c b/deps/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c new file mode 100644 index 0000000..1e90a1f --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/set/der_encode_set.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_set.c + ASN.1 DER, Encode a SET, Tom St Denis +*/ + +#ifdef LTC_DER + +/* LTC define to ASN.1 TAG */ +static int s_ltc_to_asn1(ltc_asn1_type v) +{ + return der_asn1_type_to_identifier_map[v]; +} + + +static int s_qsort_helper(const void *a, const void *b) +{ + ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b; + int r; + + r = s_ltc_to_asn1(A->type) - s_ltc_to_asn1(B->type); + + /* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */ + if (r == 0) { + /* their order in the original list now determines the position */ + return A->used - B->used; + } + return r; +} + +/* + Encode a SET type + @param list The list of items to encode + @param inlen The number of items in the list + @param out [out] The destination + @param outlen [in/out] The size of the output + @return CRYPT_OK on success +*/ +int der_encode_set(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + ltc_asn1_list *copy; + unsigned long x; + int err; + + /* make copy of list */ + copy = XCALLOC(inlen, sizeof(*copy)); + if (copy == NULL) { + return CRYPT_MEM; + } + + /* fill in used member with index so we can fully sort it */ + for (x = 0; x < inlen; x++) { + copy[x] = list[x]; + copy[x].used = x; + } + + /* sort it by the "type" field */ + XQSORT(copy, inlen, sizeof(*copy), &s_qsort_helper); + + /* call der_encode_sequence_ex() */ + err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET); + + /* free list */ + XFREE(copy); + + return err; +} + + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c b/deps/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c new file mode 100644 index 0000000..184b6ec --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c @@ -0,0 +1,151 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_setof.c + ASN.1 DER, Encode SET OF, Tom St Denis +*/ + +#ifdef LTC_DER + +struct edge { + unsigned char *start; + unsigned long size; +}; + +static int s_qsort_helper(const void *a, const void *b) +{ + struct edge *A = (struct edge *)a, *B = (struct edge *)b; + int r; + unsigned long x; + + /* compare min length */ + r = XMEMCMP(A->start, B->start, MIN(A->size, B->size)); + + if (r == 0 && A->size != B->size) { + if (A->size > B->size) { + for (x = B->size; x < A->size; x++) { + if (A->start[x]) { + return 1; + } + } + } else { + for (x = A->size; x < B->size; x++) { + if (B->start[x]) { + return -1; + } + } + } + } + + return r; +} + +/** + Encode a SETOF stucture + @param list The list of items to encode + @param inlen The number of items in the list + @param out [out] The destination + @param outlen [in/out] The size of the output + @return CRYPT_OK on success +*/ +int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, z; + ptrdiff_t hdrlen; + int err; + struct edge *edges; + unsigned char *ptr, *buf; + + /* check that they're all the same type */ + for (x = 1; x < inlen; x++) { + if (list[x].type != list[x-1].type) { + return CRYPT_INVALID_ARG; + } + } + + /* alloc buffer to store copy of output */ + buf = XCALLOC(1, *outlen); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* encode list */ + if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) { + XFREE(buf); + return err; + } + + /* allocate edges */ + edges = XCALLOC(inlen, sizeof(*edges)); + if (edges == NULL) { + XFREE(buf); + return CRYPT_MEM; + } + + /* skip header */ + ptr = buf + 1; + + /* now skip length data */ + x = *ptr++; + if (x >= 0x80) { + ptr += (x & 0x7F); + } + + /* get the size of the static header */ + hdrlen = ptr - buf; + + + /* scan for edges */ + x = 0; + while (ptr < (buf + *outlen)) { + /* store start */ + edges[x].start = ptr; + + /* skip type */ + z = 1; + + /* parse length */ + y = ptr[z++]; + if (y < 128) { + edges[x].size = y; + } else { + y &= 0x7F; + edges[x].size = 0; + while (y--) { + edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]); + } + } + + /* skip content */ + edges[x].size += z; + ptr += edges[x].size; + ++x; + } + + /* sort based on contents (using edges) */ + XQSORT(edges, inlen, sizeof(*edges), &s_qsort_helper); + + /* copy static header */ + XMEMCPY(out, buf, hdrlen); + + /* copy+sort using edges+indecies to output from buffer */ + for (y = (unsigned long)hdrlen, x = 0; x < inlen; x++) { + XMEMCPY(out+y, edges[x].start, edges[x].size); + y += edges[x].size; + } + +#ifdef LTC_CLEAN_STACK + zeromem(buf, *outlen); +#endif + + /* free buffers */ + XFREE(edges); + XFREE(buf); + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c b/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c new file mode 100644 index 0000000..e00702d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_decode_short_integer.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_short_integer.c + ASN.1 DER, decode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Read a short integer + @param in The DER encoded data + @param inlen Size of data + @param num [out] The integer to decode + @return CRYPT_OK if successful +*/ +int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsigned long *num) +{ + unsigned long len, x, y; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(in != NULL); + + /* check length */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check header */ + x = 0; + if ((in[x++] & 0x1F) != 0x02) { + return CRYPT_INVALID_PACKET; + } + + /* get the packet len */ + len = in[x++]; + + if (x + len > inlen) { + return CRYPT_INVALID_PACKET; + } + + if (len > sizeof(unsigned long)) { + return CRYPT_OVERFLOW; + } + + /* read number */ + y = 0; + while (len--) { + y = (y<<8) | (unsigned long)in[x++]; + } + *num = y; + + return CRYPT_OK; + +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c b/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c new file mode 100644 index 0000000..3af47c5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_encode_short_integer.c @@ -0,0 +1,85 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_short_integer.c + ASN.1 DER, encode an integer, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store a short integer in the range (0,2^32-1) + @param num The integer to encode + @param out [out] The destination for the DER encoded integers + @param outlen [in/out] The max size and resulting size of the DER encoded integers + @return CRYPT_OK if successful +*/ +int der_encode_short_integer(unsigned long num, unsigned char *out, unsigned long *outlen) +{ + unsigned long len, x, y, z; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* force to 32 bits */ + num &= 0xFFFFFFFFUL; + + /* find out how big this will be */ + if ((err = der_length_short_integer(num, &len)) != CRYPT_OK) { + return err; + } + + if (*outlen < len) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + /* get len of output */ + z = 0; + y = num; + while (y) { + ++z; + y >>= 8; + } + + /* handle zero */ + if (z == 0) { + z = 1; + } + + /* see if msb is set */ + z += (num&(1UL<<((z<<3) - 1))) ? 1 : 0; + + /* adjust the number so the msB is non-zero */ + for (x = 0; (z <= 4) && (x < (4 - z)); x++) { + num <<= 8; + } + + /* store header */ + x = 0; + out[x++] = 0x02; + out[x++] = (unsigned char)z; + + /* if 31st bit is set output a leading zero and decrement count */ + if (z == 5) { + out[x++] = 0; + --z; + } + + /* store values */ + for (y = 0; y < z; y++) { + out[x++] = (unsigned char)((num >> 24) & 0xFF); + num <<= 8; + } + + /* we good */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c b/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c new file mode 100644 index 0000000..aeee948 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/short_integer/der_length_short_integer.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_short_integer.c + ASN.1 DER, get length of encoding, Tom St Denis +*/ + + +#ifdef LTC_DER +/** + Gets length of DER encoding of num + @param num The integer to get the size of + @param outlen [out] The length of the DER encoding for the given integer + @return CRYPT_OK if successful +*/ +int der_length_short_integer(unsigned long num, unsigned long *outlen) +{ + unsigned long z, y; + int err; + + LTC_ARGCHK(outlen != NULL); + + /* force to 32 bits */ + num &= 0xFFFFFFFFUL; + + /* get the number of bytes */ + z = 0; + y = num; + while (y) { + ++z; + y >>= 8; + } + + /* handle zero */ + if (z == 0) { + z = 1; + } else if ((num&(1UL<<((z<<3) - 1))) != 0) { + /* in case msb is set */ + ++z; + } + + if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) { + return err; + } + *outlen = 1 + y + z; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c new file mode 100644 index 0000000..6779cd5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c @@ -0,0 +1,72 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_teletex_string.c + ASN.1 DER, encode a teletex STRING +*/ + +#ifdef LTC_DER + +/** + Store a teletex STRING + @param in The DER encoded teletex STRING + @param inlen The size of the DER teletex STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t, err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x14 */ + if ((in[0] & 0x1F) != 0x14) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_teletex_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c b/deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c new file mode 100644 index 0000000..05dc4b0 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/teletex_string/der_length_teletex_string.c @@ -0,0 +1,188 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_teletex_string.c + ASN.1 DER, get length of teletex STRING +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} teletex_table[] = { +{ '\0', 0 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\v', 11 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ ';', 59 }, +{ '<', 60 }, +{ '=', 61 }, +{ '>', 62 }, +{ '?', 63 }, +{ '@', 64 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ '[', 91 }, +{ ']', 93 }, +{ '_', 95 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +{ '|', 124 }, +{ ' ', 160 }, +{ 0xa1, 161 }, +{ 0xa2, 162 }, +{ 0xa3, 163 }, +{ '$', 164 }, +{ 0xa5, 165 }, +{ '#', 166 }, +{ 0xa7, 167 }, +{ 0xa4, 168 }, +{ 0xab, 171 }, +{ 0xb0, 176 }, +{ 0xb1, 177 }, +{ 0xb2, 178 }, +{ 0xb3, 179 }, +{ 0xd7, 180 }, +{ 0xb5, 181 }, +{ 0xb6, 182 }, +{ 0xb7, 183 }, +{ 0xf7, 184 }, +{ 0xbb, 187 }, +{ 0xbc, 188 }, +{ 0xbd, 189 }, +{ 0xbe, 190 }, +{ 0xbf, 191 }, +}; + +int der_teletex_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].code == c) { + return teletex_table[x].value; + } + } + return -1; +} + +int der_teletex_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].value == v) { + return teletex_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of teletex STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + int err; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_teletex_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + noctets; + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c b/deps/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c new file mode 100644 index 0000000..6149bfe --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/utctime/der_decode_utctime.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_utctime.c + ASN.1 DER, decode a UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +static int s_char_to_int(unsigned char x) +{ + switch (x) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + default: return 100; + } +} + +#define DECODE_V(y, max) \ + y = s_char_to_int(buf[x])*10 + s_char_to_int(buf[x+1]); \ + if (y >= max) return CRYPT_INVALID_PACKET; \ + x += 2; + +/** + Decodes a UTC time structure in DER format (reads all 6 valid encoding formats) + @param in Input buffer + @param inlen Length of input buffer in octets + @param out [out] Destination of UTC time structure + @return CRYPT_OK if successful +*/ +int der_decode_utctime(const unsigned char *in, unsigned long *inlen, + ltc_utctime *out) +{ + unsigned char buf[32] = { 0 }; /* initialize as all zeroes */ + unsigned long x; + int y; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != NULL); + LTC_ARGCHK(out != NULL); + + /* check header */ + if (*inlen < 2UL || (in[1] >= sizeof(buf)) || ((in[1] + 2UL) > *inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* decode the string */ + for (x = 0; x < in[1]; x++) { + y = der_ia5_value_decode(in[x+2]); + if (y == -1) { + return CRYPT_INVALID_PACKET; + } + buf[x] = y; + } + *inlen = 2 + x; + + + /* possible encodings are +YYMMDDhhmmZ +YYMMDDhhmm+hh'mm' +YYMMDDhhmm-hh'mm' +YYMMDDhhmmssZ +YYMMDDhhmmss+hh'mm' +YYMMDDhhmmss-hh'mm' + + So let's do a trivial decode upto [including] mm + */ + + x = 0; + DECODE_V(out->YY, 100); + DECODE_V(out->MM, 13); + DECODE_V(out->DD, 32); + DECODE_V(out->hh, 24); + DECODE_V(out->mm, 60); + + /* clear timezone and seconds info */ + out->off_dir = out->off_hh = out->off_mm = out->ss = 0; + + /* now is it Z, +, - or 0-9 */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } + if (buf[x] == '+' || buf[x] == '-') { + out->off_dir = (buf[x++] == '+') ? 0 : 1; + DECODE_V(out->off_hh, 24); + DECODE_V(out->off_mm, 60); + return CRYPT_OK; + } + + /* decode seconds */ + DECODE_V(out->ss, 60); + + /* now is it Z, +, - */ + if (buf[x] == 'Z') { + return CRYPT_OK; + } + if (buf[x] == '+' || buf[x] == '-') { + out->off_dir = (buf[x++] == '+') ? 0 : 1; + DECODE_V(out->off_hh, 24); + DECODE_V(out->off_mm, 60); + return CRYPT_OK; + } + return CRYPT_INVALID_PACKET; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c b/deps/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c new file mode 100644 index 0000000..b1c6fbe --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/utctime/der_encode_utctime.c @@ -0,0 +1,71 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_utctime.c + ASN.1 DER, encode a UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +static const char * const baseten = "0123456789"; + +#define STORE_V(y) \ + out[x++] = der_ia5_char_encode(baseten[(y/10) % 10]); \ + out[x++] = der_ia5_char_encode(baseten[y % 10]); + +/** + Encodes a UTC time structure in DER format + @param utctime The UTC time structure to encode + @param out The destination of the DER encoding of the UTC time structure + @param outlen [in/out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_encode_utctime(const ltc_utctime *utctime, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, tmplen; + int err; + + LTC_ARGCHK(utctime != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = der_length_utctime(utctime, &tmplen)) != CRYPT_OK) { + return err; + } + if (tmplen > *outlen) { + *outlen = tmplen; + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header */ + out[0] = 0x17; + + /* store values */ + x = 2; + STORE_V(utctime->YY); + STORE_V(utctime->MM); + STORE_V(utctime->DD); + STORE_V(utctime->hh); + STORE_V(utctime->mm); + STORE_V(utctime->ss); + + if (utctime->off_mm || utctime->off_hh) { + out[x++] = der_ia5_char_encode(utctime->off_dir ? '-' : '+'); + STORE_V(utctime->off_hh); + STORE_V(utctime->off_mm); + } else { + out[x++] = der_ia5_char_encode('Z'); + } + + /* store length */ + out[1] = (unsigned char)(x - 2); + + /* all good let's return */ + *outlen = x; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c b/deps/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c new file mode 100644 index 0000000..b93c25f --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/utctime/der_length_utctime.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_utctime.c + ASN.1 DER, get length of UTCTIME, Tom St Denis +*/ + +#ifdef LTC_DER + +/** + Gets length of DER encoding of UTCTIME + @param utctime The UTC time structure to get the size of + @param outlen [out] The length of the DER encoding + @return CRYPT_OK if successful +*/ +int der_length_utctime(const ltc_utctime *utctime, unsigned long *outlen) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(utctime != NULL); + + if (utctime->off_hh == 0 && utctime->off_mm == 0) { + /* we encode as YYMMDDhhmmssZ */ + *outlen = 2 + 13; + } else { + /* we encode as YYMMDDhhmmss{+|-}hh'mm' */ + *outlen = 2 + 17; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c b/deps/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c new file mode 100644 index 0000000..93a5e5e --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c @@ -0,0 +1,117 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_decode_utf8_string.c + ASN.1 DER, encode a UTF8 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Decode a UTF8 STRING and recover an array of unicode characters. + @param in The DER encoded UTF8 STRING + @param inlen The size of the DER UTF8 STRING + @param out [out] The array of unicode characters (wchar_t*) + @param outlen [in/out] The number of unicode characters in the array + @return CRYPT_OK if successful +*/ +int der_decode_utf8_string(const unsigned char *in, unsigned long inlen, + wchar_t *out, unsigned long *outlen) +{ + wchar_t tmp; + unsigned long x, y, z, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x0C */ + if ((in[0] & 0x1F) != 0x0C) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* get the length of the data */ + y = inlen - x; + if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) { + return err; + } + x += y; + + if (len > (inlen - x)) { + return CRYPT_INVALID_PACKET; + } + + /* proceed to recover unicode characters from utf8 data. + for reference see Section 3 of RFC 3629: + + https://tools.ietf.org/html/rfc3629#section-3 + */ + for (y = 0; x < inlen; ) { + /* read first byte */ + tmp = in[x++]; + + /* a unicode character is recovered from a sequence of 1 to 4 utf8 bytes. + the form of those bytes must match a row in the following table: + + 0xxxxxxx + 110xxxxx 10xxxxxx + 1110xxxx 10xxxxxx 10xxxxxx + 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + the number of leading ones in the first byte (0,2,3,4) determines the + number of remaining bytes to read (0,1,2,3) + */ + + /* determine z, the number of leading ones. + this is done by left-shifting tmp, which clears the ms-bits */ + for (z = 0; (tmp & 0x80) && (z <= 4); z++, tmp = (tmp << 1) & 0xFF); + + /* z should be in {0,2,3,4} */ + if (z == 1 || z > 4) { + return CRYPT_INVALID_PACKET; + } + + /* right-shift tmp to restore least-sig bits */ + tmp >>= z; + + /* now update z so it equals the number of additional bytes to read */ + if (z > 0) { --z; } + + if (x + z > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read remaining bytes */ + while (z-- != 0) { + if ((in[x] & 0xC0) != 0x80) { + return CRYPT_INVALID_PACKET; + } + tmp = (tmp << 6) | ((wchar_t)in[x++] & 0x3F); + } + + if (y < *outlen) { + out[y] = tmp; + } + y++; + } + if (y > *outlen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; + } + *outlen = y; + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c b/deps/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c new file mode 100644 index 0000000..f2c07c2 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/utf8/der_encode_utf8_string.c @@ -0,0 +1,75 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_encode_utf8_string.c + ASN.1 DER, encode a UTF8 STRING, Tom St Denis +*/ + + +#ifdef LTC_DER + +/** + Store an UTF8 STRING + @param in The array of UTF8 to store (one per wchar_t) + @param inlen The number of UTF8 to store + @param out [out] The destination for the DER encoded UTF8 STRING + @param outlen [in/out] The max size and resulting size of the DER UTF8 STRING + @return CRYPT_OK if successful +*/ +int der_encode_utf8_string(const wchar_t *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* get the size */ + for (x = len = 0; x < inlen; x++) { + if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; + len += der_utf8_charsize(in[x]); + } + if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { + return err; + } + x += len + 1; + + /* too big? */ + if (x > *outlen) { + *outlen = x; + return CRYPT_BUFFER_OVERFLOW; + } + + /* encode the header+len */ + x = 0; + out[x++] = 0x0C; + + y = *outlen - x; + if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) { + return err; + } + x += y; + + /* store UTF8 */ + for (y = 0; y < inlen; y++) { + switch (der_utf8_charsize(in[y])) { + case 1: out[x++] = (unsigned char)in[y]; break; + case 2: out[x++] = 0xC0 | ((in[y] >> 6) & 0x1F); out[x++] = 0x80 | (in[y] & 0x3F); break; + case 3: out[x++] = 0xE0 | ((in[y] >> 12) & 0x0F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; +#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF + case 4: out[x++] = 0xF0 | ((in[y] >> 18) & 0x07); out[x++] = 0x80 | ((in[y] >> 12) & 0x3F); out[x++] = 0x80 | ((in[y] >> 6) & 0x3F); out[x++] = 0x80 | (in[y] & 0x3F); break; +#endif + } + } + + /* return length */ + *outlen = x; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c b/deps/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c new file mode 100644 index 0000000..424002b --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/der/utf8/der_length_utf8_string.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file der_length_utf8_string.c + ASN.1 DER, get length of UTF8 STRING, Tom St Denis +*/ + +#ifdef LTC_DER + +/** Return the size in bytes of a UTF-8 character + @param c The UTF-8 character to measure + @return The size in bytes +*/ +unsigned long der_utf8_charsize(const wchar_t c) +{ + if (c <= 0x7F) { + return 1; + } + if (c <= 0x7FF) { + return 2; + } +#if LTC_WCHAR_MAX == 0xFFFF + return 3; +#else + if (c <= 0xFFFF) { + return 3; + } + return 4; +#endif +} + +/** + Test whether the given code point is valid character + @param c The UTF-8 character to test + @return 1 - valid, 0 - invalid +*/ +int der_utf8_valid_char(const wchar_t c) +{ + LTC_UNUSED_PARAM(c); +#if !defined(LTC_WCHAR_MAX) || LTC_WCHAR_MAX > 0xFFFF + if (c > 0x10FFFF) return 0; +#endif +#if LTC_WCHAR_MAX != 0xFFFF && LTC_WCHAR_MAX != 0xFFFFFFFF + if (c < 0) return 0; +#endif + return 1; +} + +/** + Gets length of DER encoding of UTF8 STRING + @param in The characters to measure the length of + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x, len; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(outlen != NULL); + + len = 0; + for (x = 0; x < noctets; x++) { + if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG; + len += der_utf8_charsize(in[x]); + } + + if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) { + return err; + } + *outlen = 1 + x + len; + + return CRYPT_OK; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c b/deps/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c new file mode 100644 index 0000000..b3e1ee2 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/oid/pk_get_oid.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_DER + +typedef struct { + enum ltc_oid_id id; + const char* oid; +} oid_table_entry; + +static const oid_table_entry pka_oids[] = { + { LTC_OID_RSA, "1.2.840.113549.1.1.1" }, + { LTC_OID_DSA, "1.2.840.10040.4.1" }, + { LTC_OID_EC, "1.2.840.10045.2.1" }, + { LTC_OID_EC_PRIMEF, "1.2.840.10045.1.1" }, + { LTC_OID_X25519, "1.3.101.110" }, + { LTC_OID_ED25519, "1.3.101.112" }, +}; + +/* + Returns the OID requested. + @return CRYPT_OK if valid +*/ +int pk_get_oid(enum ltc_oid_id id, const char **st) +{ + unsigned int i; + LTC_ARGCHK(st != NULL); + for (i = 0; i < sizeof(pka_oids)/sizeof(pka_oids[0]); ++i) { + if (pka_oids[i].id == id) { + *st = pka_oids[i].oid; + return CRYPT_OK; + } + } + return CRYPT_INVALID_ARG; +} +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c b/deps/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c new file mode 100644 index 0000000..f842bc5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/oid/pk_oid_cmp.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_DER + +/* + Compare an OID string to an array of `unsigned long`. + @return CRYPT_OK if equal +*/ +int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long o2size) +{ + unsigned long i; + char tmp[256] = { 0 }; + int err; + + if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; + + i = sizeof(tmp); + if ((err = pk_oid_num_to_str(o2, o2size, tmp, &i)) != CRYPT_OK) { + return err; + } + + if (XSTRCMP(o1, tmp) != 0) { + return CRYPT_PK_INVALID_TYPE; + } + + return CRYPT_OK; +} + +/* + Compare an OID string to an OID element decoded from ASN.1. + @return CRYPT_OK if equal +*/ +int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2) +{ + if (o1 == NULL || o2 == NULL) return CRYPT_ERROR; + + if (o2->type != LTC_ASN1_OBJECT_IDENTIFIER) return CRYPT_INVALID_ARG; + + return pk_oid_cmp_with_ulong(o1, o2->data, o2->size); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c b/deps/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c new file mode 100644 index 0000000..bc21a6f --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/oid/pk_oid_str.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen) +{ + unsigned long i, j, limit, oid_j; + size_t OID_len; + + LTC_ARGCHK(oidlen != NULL); + + limit = *oidlen; + *oidlen = 0; /* make sure that we return zero oidlen on error */ + for (i = 0; i < limit; i++) oid[i] = 0; + + if (OID == NULL) return CRYPT_OK; + + OID_len = XSTRLEN(OID); + if (OID_len == 0) return CRYPT_OK; + + for (i = 0, j = 0; i < OID_len; i++) { + if (OID[i] == '.') { + if (++j >= limit) continue; + } + else if ((OID[i] >= '0') && (OID[i] <= '9')) { + if ((j >= limit) || (oid == NULL)) continue; + oid_j = oid[j]; + oid[j] = oid[j] * 10 + (OID[i] - '0'); + if (oid[j] < oid_j) return CRYPT_OVERFLOW; + } + else { + return CRYPT_ERROR; + } + } + if (j == 0) return CRYPT_ERROR; + if (j >= limit) { + *oidlen = j; + return CRYPT_BUFFER_OVERFLOW; + } + *oidlen = j + 1; + return CRYPT_OK; +} + +int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen) +{ + int i; + unsigned long j, k; + char tmp[256] = { 0 }; + + LTC_ARGCHK(oid != NULL); + LTC_ARGCHK(oidlen < INT_MAX); + LTC_ARGCHK(outlen != NULL); + + for (i = oidlen - 1, k = 0; i >= 0; i--) { + j = oid[i]; + if (j == 0) { + tmp[k] = '0'; + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + } + else { + while (j > 0) { + tmp[k] = '0' + (j % 10); + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + j /= 10; + } + } + if (i > 0) { + tmp[k] = '.'; + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + } + } + if (*outlen < k + 1) { + *outlen = k + 1; + return CRYPT_BUFFER_OVERFLOW; + } + LTC_ARGCHK(OID != NULL); + for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1]; + OID[k] = '\0'; + *outlen = k; /* the length without terminating NUL byte */ + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c b/deps/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c new file mode 100644 index 0000000..e715f11 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/pkcs8/pkcs8_decode_flexi.c @@ -0,0 +1,97 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_PKCS_8 + +/** + PKCS#8 decrypt if necessary & flexi-decode + + @param in Pointer to the ASN.1 encoded input data + @param inlen Length of the input data + @param pwd Pointer to the password that was used when encrypting + @param pwdlen Length of the password + @param decoded_list Pointer to a pointer for the flexi-decoded list + @return CRYPT_OK on success +*/ +int pkcs8_decode_flexi(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + ltc_asn1_list **decoded_list) +{ + unsigned long len = inlen; + unsigned long dec_size; + unsigned char *dec_data = NULL; + ltc_asn1_list *l = NULL; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(decoded_list != NULL); + + *decoded_list = NULL; + if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) { + /* the following "if" detects whether it is encrypted or not */ + /* PKCS8 Setup + * 0:d=0 hl=4 l= 380 cons: SEQUENCE + * 4:d=1 hl=2 l= 78 cons: SEQUENCE + * 6:d=2 hl=2 l= 9 prim: OBJECT :OID indicating PBES1 or PBES2 (== *lalgoid) + * 17:d=2 hl=2 l= 65 cons: SEQUENCE + * Stuff in between is dependent on whether it's PBES1 or PBES2 + * 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data) + */ + if (l->type == LTC_ASN1_SEQUENCE && + LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) && + LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) && + LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) && + LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) { + ltc_asn1_list *lalgoid = l->child->child; + pbes_arg pbes; + + XMEMSET(&pbes, 0, sizeof(pbes)); + + if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) { + /* Successfully extracted PBES1 parameters */ + } else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) { + /* Successfully extracted PBES2 parameters */ + } else { + /* unsupported encryption */ + err = CRYPT_INVALID_PACKET; + goto LBL_DONE; + } + + pbes.enc_data = l->child->next; + pbes.pwd = pwd; + pbes.pwdlen = pwdlen; + + dec_size = pbes.enc_data->size; + if ((dec_data = XMALLOC(dec_size)) == NULL) { + err = CRYPT_MEM; + goto LBL_DONE; + } + + if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE; + + der_free_sequence_flexi(l); + l = NULL; + err = der_decode_sequence_flexi(dec_data, &dec_size, &l); + if (err != CRYPT_OK) goto LBL_DONE; + *decoded_list = l; + } + else { + /* not encrypted */ + err = CRYPT_OK; + *decoded_list = l; + } + /* Set l to NULL so it won't be free'd */ + l = NULL; + } + +LBL_DONE: + if (l) der_free_sequence_flexi(l); + if (dec_data) { + zeromem(dec_data, dec_size); + XFREE(dec_data); + } + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c b/deps/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c new file mode 100644 index 0000000..feff868 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c @@ -0,0 +1,109 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_decode_public_key_from_certificate.c + ASN.1 DER/X.509, decode a certificate +*/ + +#ifdef LTC_DER + +/* Check if it looks like a SubjectPublicKeyInfo */ +#define LOOKS_LIKE_SPKI(l) ((l) != NULL) \ +&& ((l)->type == LTC_ASN1_SEQUENCE) \ +&& ((l)->child != NULL) \ +&& ((l)->child->type == LTC_ASN1_OBJECT_IDENTIFIER) \ +&& ((l)->next != NULL) \ +&& ((l)->next->type == LTC_ASN1_BIT_STRING) + +/** + Try to decode the public key from a X.509 certificate + @param in The input buffer + @param inlen The length of the input buffer + @param algorithm One out of the enum #public_key_algorithms + @param param_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len [in/out] The number of parameters to include + @param callback The callback + @param ctx The context passed to the callback + @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found +*/ +int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, + enum ltc_oid_id algorithm, ltc_asn1_type param_type, + ltc_asn1_list* parameters, unsigned long *parameters_len, + public_key_decode_cb callback, void *ctx) +{ + int err; + unsigned char *tmpbuf; + unsigned long tmpbuf_len, tmp_inlen; + ltc_asn1_list *decoded_list = NULL, *l; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != 0); + LTC_ARGCHK(callback != NULL); + + tmpbuf_len = inlen; + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_OUT; + } + + tmp_inlen = inlen; + if ((err = der_decode_sequence_flexi(in, &tmp_inlen, &decoded_list)) == CRYPT_OK) { + l = decoded_list; + + err = CRYPT_NOP; + + /* Move 2 levels up in the tree + SEQUENCE + SEQUENCE + ... + */ + if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { + l = l->child; + if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { + l = l->child; + + /* Move forward in the tree until we find this combination + ... + SEQUENCE + SEQUENCE + OBJECT IDENTIFIER + NULL + BIT STRING + */ + do { + /* The additional check for l->data is there to make sure + * we won't try to decode a list that has been 'shrunk' + */ + if ((l->type == LTC_ASN1_SEQUENCE) + && (l->data != NULL) + && LOOKS_LIKE_SPKI(l->child)) { + if (algorithm == LTC_OID_EC) { + err = callback(l->data, l->size, ctx); + } else { + err = x509_decode_subject_public_key_info(l->data, l->size, + algorithm, tmpbuf, &tmpbuf_len, + param_type, parameters, parameters_len); + if (err == CRYPT_OK) { + err = callback(tmpbuf, tmpbuf_len, ctx); + goto LBL_OUT; + } + } + } + l = l->next; + } while(l); + } + } + } + +LBL_OUT: + if (decoded_list) der_free_sequence_flexi(decoded_list); + if (tmpbuf != NULL) XFREE(tmpbuf); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c b/deps/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c new file mode 100644 index 0000000..a94362d --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/x509/x509_decode_subject_public_key_info.c @@ -0,0 +1,119 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_decode_subject_public_key_info.c + ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav +*/ + +#ifdef LTC_DER + +/* AlgorithmIdentifier := SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm + * } + * + * SubjectPublicKeyInfo := SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ +/** + Decode a SubjectPublicKeyInfo + @param in The input buffer + @param inlen The length of the input buffer + @param algorithm One out of the enum #public_key_algorithms + @param public_key The buffer for the public key + @param public_key_len [in/out] The length of the public key buffer and the written length + @param parameters_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len [in/out] The number of parameters to include + @return CRYPT_OK on success +*/ +int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen, + unsigned int algorithm, void* public_key, unsigned long* public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len) +{ + int err; + unsigned long len, alg_id_num, tmplen; + const char* oid; + unsigned char *tmpbuf; + unsigned long tmpoid[16]; + unsigned long *_parameters_len; + ltc_asn1_list alg_id[2]; + ltc_asn1_list subject_pubkey[2]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != 0); + LTC_ARGCHK(public_key_len != NULL); + + if (parameters_type != LTC_ASN1_EOL) { + if ((parameters == NULL) || (parameters_len == NULL)) { + tmplen = 0; + _parameters_len = &tmplen; + } else { + _parameters_len = parameters_len; + } + } + + err = pk_get_oid(algorithm, &oid); + if (err != CRYPT_OK) { + return err; + } + + /* see if the OpenSSL DER format RSA public key will work */ + tmpbuf = XCALLOC(1, inlen); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + /* this includes the internal hash ID and optional params (NULL in this case) */ + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0])); + if (parameters_type == LTC_ASN1_EOL) { + alg_id_num = 1; + } else { + LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, *_parameters_len); + alg_id_num = 2; + } + + /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey + * in a **BIT** string ... so we have to extract it then proceed to convert bit to octet + */ + LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, alg_id_num); + LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, inlen*8U); + + err=der_decode_sequence(in, inlen, subject_pubkey, 2UL); + if (err != CRYPT_OK) { + goto LBL_ERR; + } + if (parameters_type != LTC_ASN1_EOL) { + *_parameters_len = alg_id[1].size; + } + + if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { + /* OID mismatch */ + goto LBL_ERR; + } + + len = subject_pubkey[1].size/8; + if (*public_key_len >= len) { + XMEMCPY(public_key, subject_pubkey[1].data, len); + *public_key_len = len; + } else { + *public_key_len = len; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + err = CRYPT_OK; + +LBL_ERR: + + XFREE(tmpbuf); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c b/deps/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c new file mode 100644 index 0000000..fd0a5d0 --- /dev/null +++ b/deps/libtomcrypt/src/pk/asn1/x509/x509_encode_subject_public_key_info.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_encode_subject_public_key_info.c + ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav +*/ + +#ifdef LTC_DER + +/* AlgorithmIdentifier := SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm + * } + * + * SubjectPublicKeyInfo := SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ +/** + Encode a SubjectPublicKeyInfo + @param out The output buffer + @param outlen [in/out] Length of buffer and resulting length of output + @param algorithm One out of the enum #public_key_algorithms + @param public_key The buffer for the public key + @param public_key_len The length of the public key buffer + @param parameters_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len The number of parameters to include + @return CRYPT_OK on success +*/ +int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, + unsigned int algorithm, const void* public_key, unsigned long public_key_len, + ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len) +{ + int err; + ltc_asn1_list alg_id[2]; + const char *OID; + unsigned long oid[16], oidlen; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = pk_get_oid(algorithm, &OID)) != CRYPT_OK) { + return err; + } + + oidlen = sizeof(oid)/sizeof(oid[0]); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + return err; + } + + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len); + + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id, + LTC_ASN1_RAW_BIT_STRING, public_key_len*8U, public_key, + LTC_ASN1_EOL, 0UL, NULL); + +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/dh/dh.c b/deps/libtomcrypt/src/pk/dh/dh.c new file mode 100644 index 0000000..277ce30 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh.c @@ -0,0 +1,227 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */ +const ltc_dh_set_type ltc_dh_sets[] = { +#ifdef LTC_DH768 +{ /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */ + 96, + "DH-768", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH1024 +{ /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */ + 128, + "DH-1024", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" + "FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH1536 +{ /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */ + 192, + "DH-1536", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH2048 +{ /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */ + 256, + "DH-2048", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH3072 +{ /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */ + 384, + "DH-3072", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH4096 +{ /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */ + 512, + "DH-4096", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" + "FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH6144 +{ /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */ + 768, + "DH-6144", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF" +}, +#endif +#ifdef LTC_DH8192 +{ /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */ + 1024, + "DH-8192", + "2", + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" +}, +#endif +{ + 0, + NULL, + NULL, + NULL +} +}; + +/** + Returns the DH group size (octets) for given key + @param key The DH key to get the size of + @return The group size in octets (0 on error) + */ +int dh_get_groupsize(const dh_key *key) +{ + if (key == NULL) return 0; + return mp_unsigned_bin_size(key->prime); +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_check_pubkey.c b/deps/libtomcrypt/src/pk/dh/dh_check_pubkey.c new file mode 100644 index 0000000..7dd128e --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_check_pubkey.c @@ -0,0 +1,55 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Check DH public key (INTERNAL ONLY, not part of public API) + @param key The key you wish to test + @return CRYPT_OK if successful +*/ +int dh_check_pubkey(const dh_key *key) +{ + void *p_minus1; + ltc_mp_digit digit; + int i, digit_count, bits_set = 0, err; + + LTC_ARGCHK(key != NULL); + + if ((err = mp_init(&p_minus1)) != CRYPT_OK) { + return err; + } + + /* avoid: y <= 1 OR y >= p-1 */ + if ((err = mp_sub_d(key->prime, 1, p_minus1)) != CRYPT_OK) { + goto error; + } + if (mp_cmp(key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(key->y, 1) != LTC_MP_GT) { + err = CRYPT_INVALID_ARG; + goto error; + } + + /* public key must have more than one bit set */ + digit_count = mp_get_digit_count(key->y); + for (i = 0; i < digit_count && bits_set < 2; i++) { + digit = mp_get_digit(key->y, i); + while (digit > 0) { + if (digit & 1) bits_set++; + digit >>= 1; + } + } + if (bits_set > 1) { + err = CRYPT_OK; + } + else { + err = CRYPT_INVALID_ARG; + } + +error: + mp_clear(p_minus1); + return err; +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_export.c b/deps/libtomcrypt/src/pk/dh/dh_export.c new file mode 100644 index 0000000..19112c4 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_export.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Export a DH key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the DH key + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int dh_export(unsigned char *out, unsigned long *outlen, int type, const dh_key *key) +{ + unsigned char flags[1]; + int err; + unsigned long version = 0; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (type == PK_PRIVATE) { + /* export x - private key */ + flags[0] = 1; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } + else { + /* export y - public key */ + flags[0] = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL); + } + + return err; +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_export_key.c b/deps/libtomcrypt/src/pk/dh/dh_export_key.c new file mode 100644 index 0000000..374635c --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_export_key.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Binary export a DH key to a buffer + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the DH key + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int dh_export_key(void *out, unsigned long *outlen, int type, const dh_key *key) +{ + unsigned long len; + void *k; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + k = (type == PK_PRIVATE) ? key->x : key->y; + len = mp_unsigned_bin_size(k); + + if (*outlen < len) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + *outlen = len; + + return mp_to_unsigned_bin(k, out); +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_free.c b/deps/libtomcrypt/src/pk/dh/dh_free.c new file mode 100644 index 0000000..ff56b00 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_free.c @@ -0,0 +1,18 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Free the allocated ram for a DH key + @param key The key which you wish to free +*/ +void dh_free(dh_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, LTC_NULL); +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_generate_key.c b/deps/libtomcrypt/src/pk/dh/dh_generate_key.c new file mode 100644 index 0000000..39ef8e1 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_generate_key.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +static int s_dh_groupsize_to_keysize(int groupsize) +{ + /* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8 + * We use "Estimate 2" to get an appropriate private key (exponent) size. + */ + if (groupsize <= 0) { + return 0; + } + if (groupsize <= 192) { + return 30; /* 1536-bit => key size 240-bit */ + } + if (groupsize <= 256) { + return 40; /* 2048-bit => key size 320-bit */ + } + if (groupsize <= 384) { + return 52; /* 3072-bit => key size 416-bit */ + } + if (groupsize <= 512) { + return 60; /* 4096-bit => key size 480-bit */ + } + if (groupsize <= 768) { + return 67; /* 6144-bit => key size 536-bit */ + } + if (groupsize <= 1024) { + return 77; /* 8192-bit => key size 616-bit */ + } + return 0; +} + +int dh_generate_key(prng_state *prng, int wprng, dh_key *key) +{ + unsigned char *buf; + unsigned long keysize; + int err, max_iterations = LTC_PK_MAX_RETRIES; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* good prng? */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + keysize = s_dh_groupsize_to_keysize(mp_unsigned_bin_size(key->prime)); + if (keysize == 0) { + err = CRYPT_INVALID_KEYSIZE; + goto freemp; + } + + /* allocate buffer */ + buf = XMALLOC(keysize); + if (buf == NULL) { + err = CRYPT_MEM; + goto freemp; + } + + key->type = PK_PRIVATE; + do { + /* make up random buf */ + if (prng_descriptor[wprng].read(buf, keysize, prng) != keysize) { + err = CRYPT_ERROR_READPRNG; + goto freebuf; + } + /* load the x value - private key */ + if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { + goto freebuf; + } + /* compute the y value - public key */ + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { + goto freebuf; + } + err = dh_check_pubkey(key); + } while (err != CRYPT_OK && max_iterations-- > 0); + +freebuf: + zeromem(buf, keysize); + XFREE(buf); +freemp: + if (err != CRYPT_OK) dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_import.c b/deps/libtomcrypt/src/pk/dh/dh_import.c new file mode 100644 index 0000000..a067a32 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_import.c @@ -0,0 +1,89 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Import a DH key from a binary packet + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) +{ + unsigned char flags[1]; + int err; + unsigned long version; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + /* init */ + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* find out what type of key it is */ + err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, &flags, + LTC_ASN1_EOL, 0UL, NULL); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + goto error; + } + + if (version == 0) { + if (flags[0] == 1) { + key->type = PK_PRIVATE; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + /* compute public key: y = (base ^ x) mod prime */ + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { + goto error; + } + } + else if (flags[0] == 0) { + key->type = PK_PUBLIC; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto error; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* check public key */ + if ((err = dh_check_pubkey(key)) != CRYPT_OK) { + goto error; + } + + return CRYPT_OK; + +error: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_set.c b/deps/libtomcrypt/src/pk/dh/dh_set.c new file mode 100644 index 0000000..e25db08 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_set.c @@ -0,0 +1,114 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Import DH key parts p and g from raw numbers + + @param p DH's p (prime) + @param plen DH's p's length + @param g DH's g (group) + @param glen DH's g's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int dh_set_pg(const unsigned char *p, unsigned long plen, + const unsigned char *g, unsigned long glen, + dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(g != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + + if ((err = mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK) { goto LBL_ERR; } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +/** + Import DH key parts p and g from built-in DH groups + + @param groupsize The size of the DH group to use + @param key [out] Where the newly created DH key will be stored + @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. +*/ +int dh_set_pg_groupsize(int groupsize, dh_key *key) +{ + int err, i; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(groupsize > 0); + + for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++); + if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE; + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +/** + Import DH public or private key part from raw numbers + + NB: The p & g parts must be set beforehand + + @param in The key-part to import, either public or private. + @param inlen The key-part's length + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int dh_set_key(const unsigned char *in, unsigned long inlen, int type, dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (type == PK_PRIVATE) { + key->type = PK_PRIVATE; + if ((err = mp_read_unsigned_bin(key->x, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto LBL_ERR; } + } + else { + key->type = PK_PUBLIC; + if ((err = mp_read_unsigned_bin(key->y, (unsigned char*)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + } + + /* check public key */ + if ((err = dh_check_pubkey(key)) != CRYPT_OK) { + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c b/deps/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c new file mode 100644 index 0000000..1f2fb3b --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_set_pg_dhparam.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Import DH key parts p and g from dhparam + + dhparam data: openssl dhparam -outform DER -out dhparam.der 2048 + + @param dhparam The DH param DER encoded data + @param dhparamlen The length of dhparam data + @param key [out] Where the newly created DH key will be stored + @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically. +*/ +int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(dhparam != NULL); + LTC_ARGCHK(dhparamlen > 0); + + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { + return err; + } + if ((err = der_decode_sequence_multi(dhparam, dhparamlen, + LTC_ASN1_INTEGER, 1UL, key->prime, + LTC_ASN1_INTEGER, 1UL, key->base, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dh_free(key); + return err; +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dh/dh_shared_secret.c b/deps/libtomcrypt/src/pk/dh/dh_shared_secret.c new file mode 100644 index 0000000..0c4dfc9 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dh/dh_shared_secret.c @@ -0,0 +1,70 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MDH + +/** + Create a DH shared secret. + @param private_key The private DH key in the pair + @param public_key The public DH key in the pair + @param out [out] The destination of the shared data + @param outlen [in/out] The max size and resulting size of the shared data. + @return CRYPT_OK if successful +*/ +int dh_shared_secret(const dh_key *private_key, const dh_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + void *tmp; + unsigned long x; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* types valid? */ + if (private_key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* same DH group? */ + if (mp_cmp(private_key->prime, public_key->prime) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } + if (mp_cmp(private_key->base, public_key->base) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; } + + /* init big numbers */ + if ((err = mp_init(&tmp)) != CRYPT_OK) { + return err; + } + + /* check public key */ + if ((err = dh_check_pubkey(public_key)) != CRYPT_OK) { + goto error; + } + + /* compute tmp = y^x mod p */ + if ((err = mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) { + goto error; + } + + /* enough space for output? */ + x = (unsigned long)mp_unsigned_bin_size(tmp); + if (*outlen < x) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { + goto error; + } + *outlen = x; + err = CRYPT_OK; + +error: + mp_clear(tmp); + return err; +} + +#endif /* LTC_MDH */ diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c b/deps/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c new file mode 100644 index 0000000..c897023 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_decrypt_key.c @@ -0,0 +1,129 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_decrypt_key.c + DSA Crypto, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Decrypt an DSA encrypted key + @param in The ciphertext + @param inlen The length of the ciphertext (octets) + @param out [out] The plaintext + @param outlen [in/out] The max size and resulting size of the plaintext + @param key The corresponding private DSA key + @return CRYPT_OK if successful +*/ +int dsa_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const dsa_key *key) +{ + unsigned char *skey, *expt; + void *g_pub; + unsigned long x, y; + unsigned long hashOID[32] = { 0 }; + int hash, err; + ltc_asn1_list decode[3]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* right key type? */ + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* decode to find out hash */ + LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); + err = der_decode_sequence(in, inlen, decode, 1); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + return err; + } + + hash = find_hash_oid(hashOID, decode[0].size); + if (hash_is_valid(hash) != CRYPT_OK) { + return CRYPT_INVALID_PACKET; + } + + /* we now have the hash! */ + + if ((err = mp_init(&g_pub)) != CRYPT_OK) { + return err; + } + + /* allocate memory */ + expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1); + skey = XMALLOC(MAXBLOCKSIZE); + if (expt == NULL || skey == NULL) { + if (expt != NULL) { + XFREE(expt); + } + if (skey != NULL) { + XFREE(skey); + } + mp_clear(g_pub); + return CRYPT_MEM; + } + + LTC_SET_ASN1(decode, 1, LTC_ASN1_INTEGER, g_pub, 1UL); + LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); + + /* read the structure in now */ + if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* make shared key */ + x = mp_unsigned_bin_size(key->p) + 1; + if ((err = dsa_shared_secret(key->x, g_pub, key, expt, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + y = mp_unsigned_bin_size(key->p) + 1; + y = MIN(y, MAXBLOCKSIZE); + if ((err = hash_memory(hash, expt, x, expt, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* ensure the hash of the shared secret is at least as big as the encrypt itself */ + if (decode[2].size > y) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* avoid buffer overflow */ + if (*outlen < decode[2].size) { + *outlen = decode[2].size; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* Decrypt the key */ + for (x = 0; x < decode[2].size; x++) { + out[x] = expt[x] ^ skey[x]; + } + *outlen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(expt, mp_unsigned_bin_size(key->p) + 1); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(expt); + XFREE(skey); + + mp_clear(g_pub); + + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c b/deps/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c new file mode 100644 index 0000000..2f46092 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_encrypt_key.c @@ -0,0 +1,118 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_encrypt_key.c + DSA Crypto, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Encrypt a symmetric key with DSA + @param in The symmetric key you want to encrypt + @param inlen The length of the key to encrypt (octets) + @param out [out] The destination for the ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param hash The index of the hash you want to use + @param key The DSA key you want to encrypt to + @return CRYPT_OK if successful +*/ +int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + const dsa_key *key) +{ + unsigned char *expt, *skey; + void *g_pub, *g_priv; + unsigned long x, y; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* check that wprng/cipher/hash are not invalid */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (inlen > hash_descriptor[hash].hashsize) { + return CRYPT_INVALID_HASH; + } + + /* make a random key and export the public copy */ + if ((err = mp_init_multi(&g_pub, &g_priv, LTC_NULL)) != CRYPT_OK) { + return err; + } + + expt = XMALLOC(mp_unsigned_bin_size(key->p) + 1); + skey = XMALLOC(MAXBLOCKSIZE); + if (expt == NULL || skey == NULL) { + if (expt != NULL) { + XFREE(expt); + } + if (skey != NULL) { + XFREE(skey); + } + mp_clear_multi(g_pub, g_priv, LTC_NULL); + return CRYPT_MEM; + } + + /* make a random g_priv, g_pub = g^x pair + private key x should be in range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) + */ + if ((err = rand_bn_upto(g_priv, key->q, prng, wprng)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* compute y */ + if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* make random key */ + x = mp_unsigned_bin_size(key->p) + 1; + if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + + y = MAXBLOCKSIZE; + if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Encrypt key */ + for (x = 0; x < inlen; x++) { + skey[x] ^= in[x]; + } + + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, + LTC_ASN1_INTEGER, 1UL, g_pub, + LTC_ASN1_OCTET_STRING, inlen, skey, + LTC_ASN1_EOL, 0UL, NULL); + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + /* clean up */ + zeromem(expt, mp_unsigned_bin_size(key->p) + 1); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(skey); + XFREE(expt); + + mp_clear_multi(g_pub, g_priv, LTC_NULL); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_export.c b/deps/libtomcrypt/src/pk/dsa/dsa_export.c new file mode 100644 index 0000000..3550cbe --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_export.c @@ -0,0 +1,100 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_export.c + DSA implementation, export key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Export a DSA key to a binary packet + @param out [out] Where to store the packet + @param outlen [in/out] The max size and resulting size of the packet + @param type The type of key to export (PK_PRIVATE or PK_PUBLIC) + @param key The key to export + @return CRYPT_OK if successful +*/ +int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_key *key) +{ + unsigned long zero=0; + unsigned char flags[1]; + int err, std; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = type & PK_STD; + type &= ~PK_STD; + + if (type == PK_PRIVATE && key->type != PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; + } + + if (type == PK_PRIVATE) { + if (std) { + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } + flags[0] = 1; + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL); + } + + if (type == PK_PUBLIC) { + if (std) { + unsigned long tmplen = (unsigned long)(mp_count_bits(key->y) / 8) + 8; + unsigned char* tmp = XMALLOC(tmplen); + ltc_asn1_list int_list[3]; + + if (tmp == NULL) { + return CRYPT_MEM; + } + + err = der_encode_integer(key->y, tmp, &tmplen); + if (err != CRYPT_OK) { + goto error; + } + + LTC_SET_ASN1(int_list, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL); + + err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_DSA, tmp, + tmplen, LTC_ASN1_SEQUENCE, int_list, + sizeof(int_list) / sizeof(int_list[0])); + +error: + XFREE(tmp); + return err; + } + flags[0] = 0; + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL); + } + + return CRYPT_INVALID_ARG; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_free.c b/deps/libtomcrypt/src/pk/dsa/dsa_free.c new file mode 100644 index 0000000..dbe8625 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_free.c @@ -0,0 +1,23 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_free.c + DSA implementation, free a DSA key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Free a DSA key + @param key The key to free from memory +*/ +void dsa_free(dsa_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, LTC_NULL); + key->type = key->qord = 0; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_generate_key.c b/deps/libtomcrypt/src/pk/dsa/dsa_generate_key.c new file mode 100644 index 0000000..bc83c0e --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_generate_key.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_make_key.c + DSA implementation, generate a DSA key +*/ + +#ifdef LTC_MDSA + +/** + Create a DSA key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key [in/out] Where to store the created key + @return CRYPT_OK if successful. +*/ +int dsa_generate_key(prng_state *prng, int wprng, dsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* so now we have our DH structure, generator g, order q, modulus p + Now we need a random exponent [mod q] and it's power g^x mod p + */ + /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */ + if ((err = rand_bn_upto(key->x, key->q, prng, wprng)) != CRYPT_OK) { return err; } + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { return err; } + key->type = PK_PRIVATE; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c b/deps/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c new file mode 100644 index 0000000..22f4852 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_generate_pqg.c @@ -0,0 +1,234 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_generate_pqg.c + DSA implementation - generate DSA parameters p, q & g +*/ + +#ifdef LTC_MDSA + +/** + Create DSA parameters (INTERNAL ONLY, not part of public API) + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param group_size Size of the multiplicative group (octets) + @param modulus_size Size of the modulus (octets) + @param p [out] bignum where generated 'p' is stored (must be initialized by caller) + @param q [out] bignum where generated 'q' is stored (must be initialized by caller) + @param g [out] bignum where generated 'g' is stored (must be initialized by caller) + @return CRYPT_OK if successful, upon error this function will free all allocated memory +*/ +static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g) +{ + unsigned long L, N, n, outbytes, seedbytes, counter, j, i; + int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash; + unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE]; + void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc; + const char *accepted_hashes[] = { "sha3-512", "sha512", "sha3-384", "sha384", "sha3-256", "sha256" }; + + /* check size */ + if (group_size > LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size || modulus_size > LTC_MDSA_MAX_MODULUS) { + return CRYPT_INVALID_ARG; + } + + /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function + * + * L = The desired length of the prime p (in bits e.g. L = 1024) + * N = The desired length of the prime q (in bits e.g. N = 160) + * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N + * outlen = The bit length of Hash function + * + * 1. Check that the (L, N) + * 2. If (seedlen = 2^(L-1)) { + * Test whether or not p is prime as specified in Appendix C.3. + * If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter + * } + * offset = offset + n + 1 Comment: Increment offset + * } + */ + + seedbytes = group_size; + L = (unsigned long)modulus_size * 8; + N = (unsigned long)group_size * 8; + + /* XXX-TODO no Lucas test */ +#ifdef LTC_MPI_HAS_LUCAS_TEST + /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ + mr_tests_p = (L <= 2048) ? 3 : 2; + if (N <= 160) { mr_tests_q = 19; } + else if (N <= 224) { mr_tests_q = 24; } + else { mr_tests_q = 27; } +#else + /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */ + if (L <= 1024) { mr_tests_p = 40; } + else if (L <= 2048) { mr_tests_p = 56; } + else { mr_tests_p = 64; } + + if (N <= 160) { mr_tests_q = 40; } + else if (N <= 224) { mr_tests_q = 56; } + else { mr_tests_q = 64; } +#endif + + hash = -1; + for (i = 0; i < sizeof(accepted_hashes)/sizeof(accepted_hashes[0]); ++i) { + hash = find_hash(accepted_hashes[i]); + if (hash != -1) break; + } + if (hash == -1) { + return CRYPT_INVALID_ARG; /* no appropriate hash function found */ + } + if (N > hash_descriptor[hash].hashsize * 8) { + return CRYPT_INVALID_ARG; /* group_size too big */ + } + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } + outbytes = hash_descriptor[hash].hashsize; + + n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1; + + if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } + if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } + + err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, LTC_NULL); + if (err != CRYPT_OK) { goto cleanup1; } + + if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } + /* t2L1 = 2^(L-1) */ + if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK) { goto cleanup; } + /* t2N1 = 2^(N-1) */ + if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK) { goto cleanup; } + /* t2seedlen = 2^seedlen */ + + for(found_p=0; !found_p;) { + /* q */ + for(found_q=0; !found_q;) { + if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes) { err = CRYPT_ERROR_READPRNG; goto cleanup; } + i = outbytes; + if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(t2N1, U, q)) != CRYPT_OK) { goto cleanup; } + if (!mp_isodd(q)) mp_add_d(q, 1, q); + if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK) { goto cleanup; } + if (res == LTC_MP_YES) found_q = 1; + } + + /* p */ + if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(q, q, t2q)) != CRYPT_OK) { goto cleanup; } + for(counter=0; counter < 4*L && !found_p; counter++) { + for(j=0; j<=n; j++) { + if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK) { goto cleanup; } + /* seedinc = (seedinc+1) % 2^seed_bitlen */ + if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes) { err = CRYPT_INVALID_ARG; goto cleanup; } + zeromem(sbuf, seedbytes); + if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; } + i = outbytes; + err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i); + if (err != CRYPT_OK) { goto cleanup; } + } + if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(W, t2L1, X)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mod(X, t2q, c)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d(c, 1, p)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub(X, p, p)) != CRYPT_OK) { goto cleanup; } + if (mp_cmp(p, t2L1) != LTC_MP_LT) { + /* p >= 2^(L-1) */ + if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK) { goto cleanup; } + if (res == LTC_MP_YES) { + found_p = 1; + } + } + } + } + + /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g + * 1. e = (p - 1)/q + * 2. h = any integer satisfying: 1 < h < (p - 1) + * h could be obtained from a random number generator or from a counter that changes after each use + * 3. g = h^e mod p + * 4. if (g == 1), then go to step 2. + * + */ + + if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_div(e, q, e, c)) != CRYPT_OK) { goto cleanup; } + /* e = (p - 1)/q */ + i = mp_count_bits(p); + do { + do { + if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK) { goto cleanup; } + } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT); + if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK) { goto cleanup; } + /* h is randon and 1 < h < (p-1) */ + if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK) { goto cleanup; } + } while (mp_cmp_d(g, 1) == LTC_MP_EQ); + + err = CRYPT_OK; +cleanup: + mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, LTC_NULL); +cleanup1: + XFREE(sbuf); +cleanup2: + XFREE(wbuf); +cleanup3: + return err; +} + +/** + Generate DSA parameters p, q & g + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param group_size Size of the multiplicative group (octets) + @param modulus_size Size of the modulus (octets) + @param key [out] Where to store the created key + @return CRYPT_OK if successful. +*/ +int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init mp_ints */ + if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL)) != CRYPT_OK) { + return err; + } + /* generate params */ + err = s_dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g); + if (err != CRYPT_OK) { + goto cleanup; + } + + key->qord = group_size; + + return CRYPT_OK; + +cleanup: + dsa_free(key); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_import.c b/deps/libtomcrypt/src/pk/dsa/dsa_import.c new file mode 100644 index 0000000..995e0d2 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_import.c @@ -0,0 +1,143 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_import.c + DSA implementation, import a DSA key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Import a DSA key + @param in The binary packet to import from + @param inlen The length of the binary packet + @param key [out] Where to store the imported key + @return CRYPT_OK if successful, upon error this function will free all allocated memory +*/ +int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + int err, stat; + unsigned long zero = 0, len; + unsigned char* tmpbuf = NULL; + unsigned char flags[1]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + /* try to match the old libtomcrypt format */ + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_EOL, 0UL, NULL); + + if (err == CRYPT_OK || err == CRYPT_INPUT_TOO_LONG) { + /* private key */ + if (flags[0] == 1) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PRIVATE; + goto LBL_OK; + } + /* public key */ + else if (flags[0] == 0) { + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PUBLIC; + goto LBL_OK; + } + else { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } + /* get key type */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + + key->type = PK_PRIVATE; + } else { /* public */ + ltc_asn1_list params[3]; + unsigned long tmpbuf_len = inlen; + + LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); + + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + len = 3; + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_DSA, + tmpbuf, &tmpbuf_len, + LTC_ASN1_SEQUENCE, params, &len); + if (err != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; + } + + if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) { + XFREE(tmpbuf); + goto LBL_ERR; + } + + XFREE(tmpbuf); + key->type = PK_PUBLIC; + } + +LBL_OK: + key->qord = mp_unsigned_bin_size(key->q); + + /* quick p, q, g validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + /* validate x, y */ + if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; +LBL_ERR: + dsa_free(key); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_make_key.c b/deps/libtomcrypt/src/pk/dsa/dsa_make_key.c new file mode 100644 index 0000000..5a205b2 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_make_key.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_make_key.c + DSA implementation, generate a DSA key +*/ + +#ifdef LTC_MDSA + +/** + Old-style creation of a DSA key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param group_size Size of the multiplicative group (octets) + @param modulus_size Size of the modulus (octets) + @param key [out] Where to store the created key + @return CRYPT_OK if successful. +*/ +int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key) +{ + int err; + + if ((err = dsa_generate_pqg(prng, wprng, group_size, modulus_size, key)) != CRYPT_OK) { return err; } + if ((err = dsa_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_set.c b/deps/libtomcrypt/src/pk/dsa/dsa_set.c new file mode 100644 index 0000000..82b6033 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_set.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +#ifdef LTC_MDSA + +/** + Import DSA's p, q & g from raw numbers + @param p DSA's p in binary representation + @param plen The length of p + @param q DSA's q in binary representation + @param qlen The length of q + @param g DSA's g in binary representation + @param glen The length of g + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_pqg(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + const unsigned char *g, unsigned long glen, + dsa_key *key) +{ + int err, stat; + + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(q != NULL); + LTC_ARGCHK(g != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); + if (err != CRYPT_OK) return err; + + if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } + + key->qord = mp_unsigned_bin_size(key->q); + + /* do only a quick validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +/** + Import DSA public or private key-part from raw numbers + + NB: The p, q & g parts must be set beforehand + + @param in The key-part to import, either public or private. + @param inlen The key-part's length + @param type Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_key(const unsigned char *in, unsigned long inlen, int type, dsa_key *key) +{ + int err, stat = 0; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->x != NULL); + LTC_ARGCHK(key->y != NULL); + LTC_ARGCHK(key->p != NULL); + LTC_ARGCHK(key->g != NULL); + LTC_ARGCHK(key->q != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (type == PK_PRIVATE) { + key->type = PK_PRIVATE; + if ((err = mp_read_unsigned_bin(key->x, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { goto LBL_ERR; } + } + else { + key->type = PK_PUBLIC; + if ((err = mp_read_unsigned_bin(key->y, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; } + } + + if ((err = dsa_int_validate_xy(key, &stat)) != CRYPT_OK) { goto LBL_ERR; } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c b/deps/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c new file mode 100644 index 0000000..97c71f1 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_set_pqg_dsaparam.c @@ -0,0 +1,57 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +#ifdef LTC_MDSA + +/** + Import DSA's p, q & g from dsaparam + + dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048 + + @param dsaparam The DSA param DER encoded data + @param dsaparamlen The length of dhparam data + @param key [out] the destination for the imported key + @return CRYPT_OK if successful. +*/ +int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen, + dsa_key *key) +{ + int err, stat; + + LTC_ARGCHK(dsaparam != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); + if (err != CRYPT_OK) return err; + + if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + + key->qord = mp_unsigned_bin_size(key->q); + + /* quick p, q, g validation, without primality testing */ + if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) { + goto LBL_ERR; + } + if (stat == 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + return CRYPT_OK; + +LBL_ERR: + dsa_free(key); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_shared_secret.c b/deps/libtomcrypt/src/pk/dsa/dsa_shared_secret.c new file mode 100644 index 0000000..df11c17 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_shared_secret.c @@ -0,0 +1,60 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_shared_secret.c + DSA Crypto, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Create a DSA shared secret between two keys + @param private_key The private DSA key (the exponent) + @param base The base of the exponentiation (allows this to be used for both encrypt and decrypt) + @param public_key The public key + @param out [out] Destination of the shared secret + @param outlen [in/out] The max size and resulting size of the shared secret + @return CRYPT_OK if successful +*/ +int dsa_shared_secret(void *private_key, void *base, + const dsa_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x; + void *res; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* make new point */ + if ((err = mp_init(&res)) != CRYPT_OK) { + return err; + } + + if ((err = mp_exptmod(base, private_key, public_key->p, res)) != CRYPT_OK) { + mp_clear(res); + return err; + } + + x = (unsigned long)mp_unsigned_bin_size(res); + if (*outlen < x) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto done; + } + zeromem(out, x); + if ((err = mp_to_unsigned_bin(res, out + (x - mp_unsigned_bin_size(res)))) != CRYPT_OK) { goto done; } + + err = CRYPT_OK; + *outlen = x; +done: + mp_clear(res); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_sign_hash.c b/deps/libtomcrypt/src/pk/dsa/dsa_sign_hash.c new file mode 100644 index 0000000..56baa80 --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_sign_hash.c @@ -0,0 +1,142 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_sign_hash.c + DSA implementation, sign a hash, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Sign a hash with DSA + @param in The hash to sign + @param inlen The length of the hash to sign + @param r The "r" integer of the signature (caller must initialize with mp_init() first) + @param s The "s" integer of the signature (caller must initialize with mp_init() first) + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key A private DSA key + @return CRYPT_OK if successful +*/ +int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, + void *r, void *s, + prng_state *prng, int wprng, const dsa_key *key) +{ + void *k, *kinv, *tmp; + unsigned char *buf; + int err, qbits; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* check group order size */ + if (key->qord >= LTC_MDSA_MAX_GROUP) { + return CRYPT_INVALID_ARG; + } + + buf = XMALLOC(LTC_MDSA_MAX_GROUP); + if (buf == NULL) { + return CRYPT_MEM; + } + + /* Init our temps */ + if ((err = mp_init_multi(&k, &kinv, &tmp, LTC_NULL)) != CRYPT_OK) { goto ERRBUF; } + + qbits = mp_count_bits(key->q); +retry: + + do { + /* gen random k */ + if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK) { goto error; } + + /* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */ + if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT) { goto retry; } + + /* test gcd */ + if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK) { goto error; } + } while (mp_cmp_d(tmp, 1) != LTC_MP_EQ); + + /* now find 1/k mod q */ + if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK) { goto error; } + + /* now find r = g^k mod p mod q */ + if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK) { goto error; } + if ((err = mp_mod(r, key->q, r)) != CRYPT_OK) { goto error; } + + if (mp_iszero(r) == LTC_MP_YES) { goto retry; } + + /* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/ + inlen = MIN(inlen, (unsigned long)(key->qord)); + + /* now find s = (in + xr)/k mod q */ + if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK) { goto error; } + if ((err = mp_mul(key->x, r, s)) != CRYPT_OK) { goto error; } + if ((err = mp_add(s, tmp, s)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK) { goto error; } + + if (mp_iszero(s) == LTC_MP_YES) { goto retry; } + + err = CRYPT_OK; +error: + mp_clear_multi(k, kinv, tmp, LTC_NULL); +ERRBUF: +#ifdef LTC_CLEAN_STACK + zeromem(buf, LTC_MDSA_MAX_GROUP); +#endif + XFREE(buf); + return err; +} + +/** + Sign a hash with DSA + @param in The hash to sign + @param inlen The length of the hash to sign + @param out [out] Where to store the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key A private DSA key + @return CRYPT_OK if successful +*/ +int dsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, const dsa_key *key) +{ + void *r, *s; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (mp_init_multi(&r, &s, LTC_NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + if ((err = dsa_sign_hash_raw(in, inlen, r, s, prng, wprng, key)) != CRYPT_OK) { + goto error; + } + + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, NULL); + +error: + mp_clear_multi(r, s, LTC_NULL); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_verify_hash.c b/deps/libtomcrypt/src/pk/dsa/dsa_verify_hash.c new file mode 100644 index 0000000..500feda --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_verify_hash.c @@ -0,0 +1,127 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_verify_hash.c + DSA implementation, verify a signature, Tom St Denis +*/ + + +#ifdef LTC_MDSA + +/** + Verify a DSA signature + @param r DSA "r" parameter + @param s DSA "s" parameter + @param hash The hash that was signed + @param hashlen The length of the hash that was signed + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param key The corresponding public DSA key + @return CRYPT_OK if successful (even if the signature is invalid) +*/ +int dsa_verify_hash_raw( void *r, void *s, + const unsigned char *hash, unsigned long hashlen, + int *stat, const dsa_key *key) +{ + void *w, *v, *u1, *u2; + int err; + + LTC_ARGCHK(r != NULL); + LTC_ARGCHK(s != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid signature */ + *stat = 0; + + /* init our variables */ + if ((err = mp_init_multi(&w, &v, &u1, &u2, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* neither r or s can be null or >q*/ + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || mp_cmp(r, key->q) != LTC_MP_LT || mp_cmp(s, key->q) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* FIPS 186-4 4.7: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash' */ + hashlen = MIN(hashlen, (unsigned long)(key->qord)); + + /* w = 1/s mod q */ + if ((err = mp_invmod(s, key->q, w)) != CRYPT_OK) { goto error; } + + /* u1 = m * w mod q */ + if ((err = mp_read_unsigned_bin(u1, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(u1, w, key->q, u1)) != CRYPT_OK) { goto error; } + + /* u2 = r*w mod q */ + if ((err = mp_mulmod(r, w, key->q, u2)) != CRYPT_OK) { goto error; } + + /* v = g^u1 * y^u2 mod p mod q */ + if ((err = mp_exptmod(key->g, u1, key->p, u1)) != CRYPT_OK) { goto error; } + if ((err = mp_exptmod(key->y, u2, key->p, u2)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(u1, u2, key->p, v)) != CRYPT_OK) { goto error; } + if ((err = mp_mod(v, key->q, v)) != CRYPT_OK) { goto error; } + + /* if r = v then we're set */ + if (mp_cmp(r, v) == LTC_MP_EQ) { + *stat = 1; + } + + err = CRYPT_OK; +error: + mp_clear_multi(w, v, u1, u2, LTC_NULL); + return err; +} + +/** + Verify a DSA signature + @param sig The signature + @param siglen The length of the signature (octets) + @param hash The hash that was signed + @param hashlen The length of the hash that was signed + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param key The corresponding public DSA key + @return CRYPT_OK if successful (even if the signature is invalid) +*/ +int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const dsa_key *key) +{ + int err; + void *r, *s; + ltc_asn1_list sig_seq[2]; + unsigned long reallen = 0; + + LTC_ARGCHK(stat != NULL); + *stat = 0; /* must be set before the first return */ + + if ((err = mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) { + return err; + } + + LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL); + LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL); + + err = der_decode_sequence_strict(sig, siglen, sig_seq, 2); + if (err != CRYPT_OK) { + goto LBL_ERR; + } + + err = der_length_sequence(sig_seq, 2, &reallen); + if (err != CRYPT_OK || reallen != siglen) { + goto LBL_ERR; + } + + /* do the op */ + err = dsa_verify_hash_raw(r, s, hash, hashlen, stat, key); + +LBL_ERR: + mp_clear_multi(r, s, LTC_NULL); + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/dsa/dsa_verify_key.c b/deps/libtomcrypt/src/pk/dsa/dsa_verify_key.c new file mode 100644 index 0000000..50d566a --- /dev/null +++ b/deps/libtomcrypt/src/pk/dsa/dsa_verify_key.c @@ -0,0 +1,189 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file dsa_verify_key.c + DSA implementation, verify a key, Tom St Denis +*/ + +#ifdef LTC_MDSA + +/** + Validate a DSA key + + Yeah, this function should've been called dsa_validate_key() + in the first place and for compat-reasons we keep it + as it was (for now). + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_verify_key(const dsa_key *key, int *stat) +{ + int err; + + err = dsa_int_validate_primes(key, stat); + if (err != CRYPT_OK || *stat == 0) return err; + + err = dsa_int_validate_pqg(key, stat); + if (err != CRYPT_OK || *stat == 0) return err; + + return dsa_int_validate_xy(key, stat); +} + +/** + Non-complex part (no primality testing) of the validation + of DSA params (p, q, g) + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_pqg(const dsa_key *key, int *stat) +{ + void *tmp1, *tmp2; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + *stat = 0; + + /* check q-order */ + if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 || + (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || + (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) { + return CRYPT_OK; + } + + /* FIPS 186-4 chapter 4.1: 1 < g < p */ + if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) { + return CRYPT_OK; + } + + if ((err = mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; } + + /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */ + if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; } + if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK) { goto error; } + if (mp_iszero(tmp2) != LTC_MP_YES) { + err = CRYPT_OK; + goto error; + } + + /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in + * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1 + */ + if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; } + if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + + err = CRYPT_OK; + *stat = 1; +error: + mp_clear_multi(tmp2, tmp1, LTC_NULL); + return err; +} + +/** + Primality testing of DSA params p and q + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_primes(const dsa_key *key, int *stat) +{ + int err, res; + + *stat = 0; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* key->q prime? */ + if ((err = mp_prime_is_prime(key->q, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { + return err; + } + if (res == LTC_MP_NO) { + return CRYPT_OK; + } + + /* key->p prime? */ + if ((err = mp_prime_is_prime(key->p, LTC_MILLER_RABIN_REPS, &res)) != CRYPT_OK) { + return err; + } + if (res == LTC_MP_NO) { + return CRYPT_OK; + } + + *stat = 1; + return CRYPT_OK; +} + +/** + Validation of a DSA key (x and y values) + + @param key The key to validate + @param stat [out] Result of test, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int dsa_int_validate_xy(const dsa_key *key, int *stat) +{ + void *tmp; + int err; + + *stat = 0; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* 1 < y < p-1 */ + if ((err = mp_init(&tmp)) != CRYPT_OK) { + return err; + } + if ((err = mp_sub_d(key->p, 1, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp_d(key->y, 1) != LTC_MP_GT || mp_cmp(key->y, tmp) != LTC_MP_LT) { + err = CRYPT_OK; + goto error; + } + + if (key->type == PK_PRIVATE) { + /* FIPS 186-4 chapter 4.1: 0 < x < q */ + if (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT) { + err = CRYPT_OK; + goto error; + } + /* FIPS 186-4 chapter 4.1: y = g^x mod p */ + if ((err = mp_exptmod(key->g, key->x, key->p, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp(tmp, key->y) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + } + else { + /* with just a public key we cannot test y = g^x mod p therefore we + * only test that y^q mod p = 1, which makes sure y is in g^x mod p + */ + if ((err = mp_exptmod(key->y, key->q, key->p, tmp)) != CRYPT_OK) { + goto error; + } + if (mp_cmp_d(tmp, 1) != LTC_MP_EQ) { + err = CRYPT_OK; + goto error; + } + } + + err = CRYPT_OK; + *stat = 1; +error: + mp_clear(tmp); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c b/deps/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c new file mode 100644 index 0000000..e1efb30 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ec25519/ec25519_crypto_ctx.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ec25519_crypto_ctx.c + curve25519 crypto context helper +*/ + +#ifdef LTC_CURVE25519 + +int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen) +{ + unsigned char *buf = out; + + const char *prefix = "SigEd25519 no Ed25519 collisions"; + const unsigned long prefix_len = XSTRLEN(prefix); + const unsigned char ctxlen8 = (unsigned char)ctxlen; + + if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG; + if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW; + + XMEMCPY(buf, prefix, prefix_len); + buf += prefix_len; + XMEMCPY(buf, &flag, 1); + buf++; + XMEMCPY(buf, &ctxlen8, 1); + buf++; + + if (ctxlen > 0u) { + LTC_ARGCHK(ctx != NULL); + XMEMCPY(buf, ctx, ctxlen); + buf += ctxlen; + } + + *outlen = buf-out; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ec25519/ec25519_export.c b/deps/libtomcrypt/src/pk/ec25519/ec25519_export.c new file mode 100644 index 0000000..42f4c4b --- /dev/null +++ b/deps/libtomcrypt/src/pk/ec25519/ec25519_export.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ec25519_export.c + Generic export of a Curve/Ed25519 key to a binary packet, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Generic export of a Curve/Ed25519 key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the Ed25519 key + @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int ec25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key) +{ + int err, std; + const char* OID; + unsigned long oid[16], oidlen; + ltc_asn1_list alg_id[1]; + unsigned char private_key[34]; + unsigned long version, private_key_len = sizeof(private_key); + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = which & PK_STD; + which &= ~PK_STD; + + if (which == PK_PRIVATE) { + if(key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + if (std == PK_STD) { + if ((err = pk_get_oid(key->algo, &OID)) != CRYPT_OK) { + return err; + } + oidlen = sizeof(oid)/sizeof(oid[0]); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + return err; + } + + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + + /* encode private key as PKCS#8 */ + if ((err = der_encode_octet_string(key->priv, 32uL, private_key, &private_key_len)) != CRYPT_OK) { + return err; + } + + version = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1uL, &version, + LTC_ASN1_SEQUENCE, 1uL, alg_id, + LTC_ASN1_OCTET_STRING, private_key_len, private_key, + LTC_ASN1_EOL, 0uL, NULL); + } else { + if (*outlen < sizeof(key->priv)) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + XMEMCPY(out, key->priv, sizeof(key->priv)); + err = CRYPT_OK; + } + *outlen = sizeof(key->priv); + } + } else { + if (std == PK_STD) { + /* encode public key as SubjectPublicKeyInfo */ + err = x509_encode_subject_public_key_info(out, outlen, key->algo, key->pub, 32uL, LTC_ASN1_EOL, NULL, 0); + } else { + if (*outlen < sizeof(key->pub)) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + XMEMCPY(out, key->pub, sizeof(key->pub)); + err = CRYPT_OK; + } + *outlen = sizeof(key->pub); + } + } + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c b/deps/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c new file mode 100644 index 0000000..13807ab --- /dev/null +++ b/deps/libtomcrypt/src/pk/ec25519/ec25519_import_pkcs8.c @@ -0,0 +1,87 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ec25519_import_pkcs8.c + Generic import of a Curve/Ed25519 private key in PKCS#8 format, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Generic import of a Curve/Ed25519 private key in PKCS#8 format + @param in The DER-encoded PKCS#8-formatted private key + @param inlen The length of the input data + @param passwd The password to decrypt the private key + @param passwdlen Password's length (octets) + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + enum ltc_oid_id id, sk_to_pk fp, + curve25519_key *key) +{ + int err; + ltc_asn1_list *l = NULL; + const char *oid; + ltc_asn1_list alg_id[1]; + unsigned char private_key[34]; + unsigned long version, key_len; + unsigned long tmpoid[16]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(fp != NULL); + + if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) { + + LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid) / sizeof(tmpoid[0])); + + key_len = sizeof(private_key); + if ((err = der_decode_sequence_multi(l->data, l->size, + LTC_ASN1_SHORT_INTEGER, 1uL, &version, + LTC_ASN1_SEQUENCE, 1uL, alg_id, + LTC_ASN1_OCTET_STRING, key_len, private_key, + LTC_ASN1_EOL, 0uL, NULL)) + != CRYPT_OK) { + /* If there are attributes added after the private_key it is tagged with version 1 and + * we get an 'input too long' error but the rest is already decoded and can be + * handled the same as for version 0 + */ + if ((err == CRYPT_INPUT_TOO_LONG) && (version == 1)) { + version = 0; + } else { + goto out; + } + } + + if ((err = pk_get_oid(id, &oid)) != CRYPT_OK) { + goto out; + } + if ((err = pk_oid_cmp_with_asn1(oid, &alg_id[0])) != CRYPT_OK) { + goto out; + } + + if (version == 0) { + key_len = sizeof(key->priv); + if ((err = der_decode_octet_string(private_key, sizeof(private_key), key->priv, &key_len)) == CRYPT_OK) { + fp(key->pub, key->priv); + key->type = PK_PRIVATE; + key->algo = id; + } + } else { + err = CRYPT_PK_INVALID_TYPE; + } + } +out: + if (l) der_free_sequence_flexi(l); +#ifdef LTC_CLEAN_STACK + zeromem(private_key, sizeof(private_key)); +#endif + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ec25519/tweetnacl.c b/deps/libtomcrypt/src/pk/ec25519/tweetnacl.c new file mode 100644 index 0000000..9db0dcd --- /dev/null +++ b/deps/libtomcrypt/src/pk/ec25519/tweetnacl.c @@ -0,0 +1,491 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/* automatically generated file, do not edit */ + +#define FOR(i,n) for (i = 0;i < n;++i) +#define sv static void + +typedef unsigned char u8; +typedef ulong32 u32; +typedef ulong64 u64; +typedef long64 i64; +typedef i64 gf[16]; + +static const u8 + nine[32] = {9}; +static const gf + gf0, + gf1 = {1}, + gf121665 = {0xDB41,1}, + D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203}, + D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406}, + X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169}, + Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666}, + I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83}; + +static int vn(const u8 *x,const u8 *y,int n) +{ + int i; + u32 d = 0; + FOR(i,n) d |= x[i]^y[i]; + return (1 & ((d - 1) >> 8)) - 1; +} + +static int tweetnacl_crypto_verify_32(const u8 *x,const u8 *y) +{ + return vn(x,y,32); +} + +sv set25519(gf r, const gf a) +{ + int i; + FOR(i,16) r[i]=a[i]; +} + +sv car25519(gf o) +{ + int i; + i64 c; + FOR(i,16) { + o[i]+=(1LL<<16); + c=o[i]>>16; + o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15); + o[i]-=c<<16; + } +} + +sv sel25519(gf p,gf q,int b) +{ + i64 t,i,c=~(b-1); + FOR(i,16) { + t= c&(p[i]^q[i]); + p[i]^=t; + q[i]^=t; + } +} + +sv pack25519(u8 *o,const gf n) +{ + int i,j,b; + gf m,t; + FOR(i,16) t[i]=n[i]; + car25519(t); + car25519(t); + car25519(t); + FOR(j,2) { + m[0]=t[0]-0xffed; + for(i=1;i<15;i++) { + m[i]=t[i]-0xffff-((m[i-1]>>16)&1); + m[i-1]&=0xffff; + } + m[15]=t[15]-0x7fff-((m[14]>>16)&1); + b=(m[15]>>16)&1; + m[14]&=0xffff; + sel25519(t,m,1-b); + } + FOR(i,16) { + o[2*i]=t[i]&0xff; + o[2*i+1]=t[i]>>8; + } +} + +static int neq25519(const gf a, const gf b) +{ + u8 c[32],d[32]; + pack25519(c,a); + pack25519(d,b); + return tweetnacl_crypto_verify_32(c,d); +} + +static u8 par25519(const gf a) +{ + u8 d[32]; + pack25519(d,a); + return d[0]&1; +} + +sv unpack25519(gf o, const u8 *n) +{ + int i; + FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8); + o[15]&=0x7fff; +} + +sv A(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]+b[i]; +} + +sv Z(gf o,const gf a,const gf b) +{ + int i; + FOR(i,16) o[i]=a[i]-b[i]; +} + +sv M(gf o,const gf a,const gf b) +{ + i64 i,j,t[31]; + FOR(i,31) t[i]=0; + FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j]; + FOR(i,15) t[i]+=38*t[i+16]; + FOR(i,16) o[i]=t[i]; + car25519(o); + car25519(o); +} + +sv S(gf o,const gf a) +{ + M(o,a,a); +} + +sv inv25519(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=253;a>=0;a--) { + S(c,c); + if(a!=2&&a!=4) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +sv pow2523(gf o,const gf i) +{ + gf c; + int a; + FOR(a,16) c[a]=i[a]; + for(a=250;a>=0;a--) { + S(c,c); + if(a!=1) M(c,c,i); + } + FOR(a,16) o[a]=c[a]; +} + +int tweetnacl_crypto_scalarmult(u8 *q,const u8 *n,const u8 *p) +{ + u8 z[32]; + i64 x[80],r,i; + gf a,b,c,d,e,f; + FOR(i,31) z[i]=n[i]; + z[31]=(n[31]&127)|64; + z[0]&=248; + unpack25519(x,p); + FOR(i,16) { + b[i]=x[i]; + d[i]=a[i]=c[i]=0; + } + a[0]=d[0]=1; + for(i=254;i>=0;--i) { + r=(z[i>>3]>>(i&7))&1; + sel25519(a,b,r); + sel25519(c,d,r); + A(e,a,c); + Z(a,a,c); + A(c,b,d); + Z(b,b,d); + S(d,e); + S(f,a); + M(a,c,a); + M(c,b,e); + A(e,a,c); + Z(a,a,c); + S(b,a); + Z(c,d,f); + M(a,c,gf121665); + A(a,a,d); + M(c,c,a); + M(a,d,f); + M(d,b,x); + S(b,e); + sel25519(a,b,r); + sel25519(c,d,r); + } + FOR(i,16) { + x[i+16]=a[i]; + x[i+32]=c[i]; + x[i+48]=b[i]; + x[i+64]=d[i]; + } + inv25519(x+32,x+32); + M(x+16,x+16,x+32); + pack25519(q,x+16); + return 0; +} + +int tweetnacl_crypto_scalarmult_base(u8 *q,const u8 *n) +{ + return tweetnacl_crypto_scalarmult(q,n,nine); +} + +static LTC_INLINE int tweetnacl_crypto_hash_ctx(u8 *out,const u8 *m,u64 n,const u8 *ctx,u32 cs) +{ + unsigned long len = 64; + int hash_idx = find_hash("sha512"); + + if (n > ULONG_MAX) return CRYPT_OVERFLOW; + + if(cs == 0) + return hash_memory(hash_idx, m, n, out, &len); + + return hash_memory_multi(hash_idx, out, &len, ctx, cs, m, n, LTC_NULL); +} + +static LTC_INLINE int tweetnacl_crypto_hash(u8 *out,const u8 *m,u64 n) +{ + return tweetnacl_crypto_hash_ctx(out, m, n, NULL, 0); +} + +sv add(gf p[4],gf q[4]) +{ + gf a,b,c,d,t,e,f,g,h; + + Z(a, p[1], p[0]); + Z(t, q[1], q[0]); + M(a, a, t); + A(b, p[0], p[1]); + A(t, q[0], q[1]); + M(b, b, t); + M(c, p[3], q[3]); + M(c, c, D2); + M(d, p[2], q[2]); + A(d, d, d); + Z(e, b, a); + Z(f, d, c); + A(g, d, c); + A(h, b, a); + + M(p[0], e, f); + M(p[1], h, g); + M(p[2], g, f); + M(p[3], e, h); +} + +sv cswap(gf p[4],gf q[4],u8 b) +{ + int i; + FOR(i,4) + sel25519(p[i],q[i],b); +} + +sv pack(u8 *r,gf p[4]) +{ + gf tx, ty, zi; + inv25519(zi, p[2]); + M(tx, p[0], zi); + M(ty, p[1], zi); + pack25519(r, ty); + r[31] ^= par25519(tx) << 7; +} + +sv scalarmult(gf p[4],gf q[4],const u8 *s) +{ + int i; + set25519(p[0],gf0); + set25519(p[1],gf1); + set25519(p[2],gf1); + set25519(p[3],gf0); + for (i = 255;i >= 0;--i) { + u8 b = (s[i/8]>>(i&7))&1; + cswap(p,q,b); + add(q,p); + add(p,p); + cswap(p,q,b); + } +} + +sv scalarbase(gf p[4],const u8 *s) +{ + gf q[4]; + set25519(q[0],X); + set25519(q[1],Y); + set25519(q[2],gf1); + M(q[3],X,Y); + scalarmult(p,q,s); +} + +int tweetnacl_crypto_sk_to_pk(u8 *pk, const u8 *sk) +{ + u8 d[64]; + gf p[4]; + tweetnacl_crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + scalarbase(p,d); + pack(pk,p); + + return 0; +} + +int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, u8 *pk, u8 *sk) +{ + int err; + + /* randombytes(sk,32); */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (prng_descriptor[wprng].read(sk,32, prng) != 32) { + return CRYPT_ERROR_READPRNG; + } + + if ((err = tweetnacl_crypto_sk_to_pk(pk, sk)) != CRYPT_OK) { + return err; + } + + /* FOR(i,32) sk[32 + i] = pk[i]; + * we don't copy the pk in the sk */ + return CRYPT_OK; +} + +static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10}; + +sv modL(u8 *r,i64 x[64]) +{ + i64 carry,i,j; + for (i = 63;i >= 32;--i) { + carry = 0; + for (j = i - 32;j < i - 12;++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)]; + carry = (x[j] + 128) >> 8; + x[j] -= carry << 8; + } + x[j] += carry; + x[i] = 0; + } + carry = 0; + FOR(j,32) { + x[j] += carry - (x[31] >> 4) * L[j]; + carry = x[j] >> 8; + x[j] &= 255; + } + FOR(j,32) x[j] -= carry * L[j]; + FOR(i,32) { + x[i+1] += x[i] >> 8; + r[i] = x[i] & 255; + } +} + +sv reduce(u8 *r) +{ + i64 x[64],i; + FOR(i,64) x[i] = (u64) r[i]; + FOR(i,64) r[i] = 0; + modL(r,x); +} + +int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,const u8 *pk, const u8 *ctx, u64 cs) +{ + u8 d[64],h[64],r[64]; + i64 i,j,x[64]; + gf p[4]; + + tweetnacl_crypto_hash(d, sk, 32); + d[0] &= 248; + d[31] &= 127; + d[31] |= 64; + + *smlen = mlen+64; + FOR(i,(i64)mlen) sm[64 + i] = m[i]; + FOR(i,32) sm[32 + i] = d[32 + i]; + + tweetnacl_crypto_hash_ctx(r, sm+32, mlen+32,ctx,cs); + reduce(r); + scalarbase(p,r); + pack(sm,p); + + FOR(i,32) sm[i+32] = pk[i]; + tweetnacl_crypto_hash_ctx(h,sm,mlen + 64,ctx,cs); + reduce(h); + + FOR(i,64) x[i] = 0; + FOR(i,32) x[i] = (u64) r[i]; + FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j]; + modL(sm + 32,x); + + return 0; +} + +static int unpackneg(gf r[4],const u8 p[32]) +{ + gf t, chk, num, den, den2, den4, den6; + set25519(r[2],gf1); + unpack25519(r[1],p); + S(num,r[1]); + M(den,num,D); + Z(num,num,r[2]); + A(den,r[2],den); + + S(den2,den); + S(den4,den2); + M(den6,den4,den2); + M(t,den6,num); + M(t,t,den); + + pow2523(t,t); + M(t,t,num); + M(t,t,den); + M(t,t,den); + M(r[0],t,den); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) M(r[0],r[0],I); + + S(chk,r[0]); + M(chk,chk,den); + if (neq25519(chk, num)) return -1; + + if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]); + + M(r[3],r[0],r[1]); + return 0; +} + +int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen,const u8 *ctx,u64 cs,const u8 *pk) +{ + u64 i; + u8 s[32],t[32],h[64]; + gf p[4],q[4]; + + *stat = 0; + if (*mlen < smlen) return CRYPT_BUFFER_OVERFLOW; + *mlen = -1; + if (smlen < 64) return CRYPT_INVALID_ARG; + + if (unpackneg(q,pk)) return CRYPT_ERROR; + + XMEMMOVE(m,sm,smlen); + XMEMMOVE(s,m + 32,32); + XMEMMOVE(m + 32,pk,32); + tweetnacl_crypto_hash_ctx(h,m,smlen,ctx,cs); + reduce(h); + scalarmult(p,q,h); + + scalarbase(q,s); + add(p,q); + pack(t,p); + + smlen -= 64; + if (tweetnacl_crypto_verify_32(sm, t)) { + FOR(i,smlen) m[i] = 0; + zeromem(m, smlen); + return CRYPT_OK; + } + + *stat = 1; + XMEMMOVE(m,m + 64,smlen); + *mlen = smlen; + return CRYPT_OK; +} + +int tweetnacl_crypto_ph(u8 *out,const u8 *msg,u64 msglen) +{ + return tweetnacl_crypto_hash(out, msg, msglen); +} diff --git a/deps/libtomcrypt/src/pk/ecc/ecc.c b/deps/libtomcrypt/src/pk/ecc/ecc.c new file mode 100644 index 0000000..84068a9 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc.c @@ -0,0 +1,435 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/* This array holds the curve parameters. + * Curves (prime field only) are taken from: + * - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*) + * - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*) + * - ANS X9.62 (named: PRIMEP*) + * - http://www.ecc-brainpool.org/download/Domain-parameters.pdf (named: BRAINPOOLP*) + */ +const ltc_ecc_curve ltc_ecc_curves[] = { +#ifdef LTC_ECC_SECP112R1 +{ + /* prime */ "DB7C2ABF62E35E668076BEAD208B", + /* A */ "DB7C2ABF62E35E668076BEAD2088", + /* B */ "659EF8BA043916EEDE8911702B22", + /* order */ "DB7C2ABF62E35E7628DFAC6561C5", + /* Gx */ "09487239995A5EE76B55F9C2F098", + /* Gy */ "A89CE5AF8724C0A23E0E0FF77500", + /* cofactor */ 1, + /* OID */ "1.3.132.0.6" +}, +#endif +#ifdef LTC_ECC_SECP112R2 +{ + /* prime */ "DB7C2ABF62E35E668076BEAD208B", + /* A */ "6127C24C05F38A0AAAF65C0EF02C", + /* B */ "51DEF1815DB5ED74FCC34C85D709", + /* order */ "36DF0AAFD8B8D7597CA10520D04B", + /* Gx */ "4BA30AB5E892B4E1649DD0928643", + /* Gy */ "ADCD46F5882E3747DEF36E956E97", + /* cofactor */ 4, + /* OID */ "1.3.132.0.7" +}, +#endif +#ifdef LTC_ECC_SECP128R1 +{ + /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", + /* B */ "E87579C11079F43DD824993C2CEE5ED3", + /* order */ "FFFFFFFE0000000075A30D1B9038A115", + /* Gx */ "161FF7528B899B2D0C28607CA52C5B86", + /* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83", + /* cofactor */ 1, + /* OID */ "1.3.132.0.28" +}, +#endif +#ifdef LTC_ECC_SECP128R2 +{ + /* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1", + /* B */ "5EEEFCA380D02919DC2C6558BB6D8A5D", + /* order */ "3FFFFFFF7FFFFFFFBE0024720613B5A3", + /* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140", + /* Gy */ "27B6916A894D3AEE7106FE805FC34B44", + /* cofactor */ 4, + /* OID */ "1.3.132.0.29" +}, +#endif +#ifdef LTC_ECC_SECP160R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", + /* B */ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", + /* order */ "0100000000000000000001F4C8F927AED3CA752257", + /* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82", + /* Gy */ "23A628553168947D59DCC912042351377AC5FB32", + /* cofactor */ 1, + /* OID */ "1.3.132.0.8" +}, +#endif +#ifdef LTC_ECC_SECP160R2 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", + /* B */ "B4E134D3FB59EB8BAB57274904664D5AF50388BA", + /* order */ "0100000000000000000000351EE786A818F3A1A16B", + /* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D", + /* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", + /* cofactor */ 1, + /* OID */ "1.3.132.0.30" +}, +#endif +#ifdef LTC_ECC_SECP160K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + /* A */ "0000000000000000000000000000000000000000", + /* B */ "0000000000000000000000000000000000000007", + /* order */ "0100000000000000000001B8FA16DFAB9ACA16B6B3", + /* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", + /* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE", + /* cofactor */ 1, + /* OID */ "1.3.132.0.9" +}, +#endif +#ifdef LTC_ECC_SECP192R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + /* B */ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + /* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", + /* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.1" +}, +#endif +#ifdef LTC_ECC_PRIME192V2 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + /* B */ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", + /* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", + /* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.2" +}, +#endif +#ifdef LTC_ECC_PRIME192V3 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + /* B */ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", + /* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", + /* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.3" +}, +#endif +#ifdef LTC_ECC_SECP192K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", + /* A */ "000000000000000000000000000000000000000000000000", + /* B */ "000000000000000000000000000000000000000000000003", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", + /* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", + /* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", + /* cofactor */ 1, + /* OID */ "1.3.132.0.31" +}, +#endif +#ifdef LTC_ECC_SECP224R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + /* B */ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + /* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + /* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + /* cofactor */ 1, + /* OID */ "1.3.132.0.33" +}, +#endif +#ifdef LTC_ECC_SECP224K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", + /* A */ "00000000000000000000000000000000000000000000000000000000", + /* B */ "00000000000000000000000000000000000000000000000000000005", + /* order */ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", + /* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", + /* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", + /* cofactor */ 1, + /* OID */ "1.3.132.0.32" +}, +#endif +#ifdef LTC_ECC_SECP256R1 +{ + /* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + /* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + /* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + /* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + /* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.7" +}, +#endif +#ifdef LTC_ECC_SECP256K1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + /* A */ "0000000000000000000000000000000000000000000000000000000000000000", + /* B */ "0000000000000000000000000000000000000000000000000000000000000007", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + /* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + /* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + /* cofactor */ 1, + /* OID */ "1.3.132.0.10" +}, +#endif +#ifdef LTC_ECC_SECP384R1 +{ + /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + /* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + /* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + /* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + /* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + /* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + /* cofactor */ 1, + /* OID */ "1.3.132.0.34" +}, +#endif +#ifdef LTC_ECC_SECP521R1 +{ + /* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + /* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + /* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + /* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + /* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + /* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + /* cofactor */ 1, + /* OID */ "1.3.132.0.35" +}, +#endif +#ifdef LTC_ECC_PRIME239V1 +{ + /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + /* B */ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", + /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", + /* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", + /* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.4" +}, +#endif +#ifdef LTC_ECC_PRIME239V2 +{ + /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + /* B */ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", + /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", + /* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", + /* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.5" +}, +#endif +#ifdef LTC_ECC_PRIME239V3 +{ + /* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + /* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + /* B */ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", + /* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", + /* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", + /* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", + /* cofactor */ 1, + /* OID */ "1.2.840.10045.3.1.6" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP160R1 +{ + /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + /* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", + /* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58", + /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", + /* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", + /* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.1" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP192R1 +{ + /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + /* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", + /* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", + /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + /* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", + /* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.3" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP224R1 +{ + /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + /* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", + /* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", + /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + /* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", + /* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.5" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP256R1 +{ + /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + /* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", + /* B */ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", + /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + /* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", + /* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.7" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP320R1 +{ + /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + /* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", + /* B */ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", + /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + /* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", + /* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.9" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP384R1 +{ + /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + /* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", + /* B */ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", + /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + /* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", + /* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.11" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP512R1 +{ + /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + /* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", + /* B */ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", + /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + /* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", + /* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.13" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP160T1 +{ + /* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F", + /* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C", + /* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", + /* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09", + /* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378", + /* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.2" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP192T1 +{ + /* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", + /* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", + /* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", + /* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", + /* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129", + /* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.4" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP224T1 +{ + /* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", + /* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", + /* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", + /* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", + /* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580", + /* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.6" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP256T1 +{ + /* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", + /* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", + /* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", + /* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", + /* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", + /* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.8" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP320T1 +{ + /* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", + /* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", + /* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", + /* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", + /* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52", + /* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.10" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP384T1 +{ + /* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", + /* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", + /* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", + /* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", + /* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", + /* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.12" +}, +#endif +#ifdef LTC_ECC_BRAINPOOLP512T1 +{ + /* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", + /* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", + /* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", + /* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", + /* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", + /* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", + /* cofactor */ 1, + /* OID */ "1.3.36.3.3.2.8.1.1.14" +}, +#endif +{ + NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL +} +}; + +#endif + diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c b/deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c new file mode 100644 index 0000000..472e1b5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_export.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_ansi_x963_export.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** ECC X9.63 (Sec. 4.3.6) uncompressed export + @param key Key to export + @param out [out] destination of export + @param outlen [in/out] Length of destination and final output size + Return CRYPT_OK on success +*/ +int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen) +{ + return ecc_get_key(out, outlen, PK_PUBLIC, key); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c b/deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c new file mode 100644 index 0000000..58eb27d --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_ansi_x963_import.c @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_ansi_x963_import.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** Import an ANSI X9.63 format public key + @param in The input data to read + @param inlen The length of the input data + @param key [out] destination to store imported key \ +*/ +int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + return ecc_ansi_x963_import_ex(in, inlen, key, NULL); +} + +int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + /* must be odd */ + if ((inlen & 1) == 0) { + return CRYPT_INVALID_ARG; + } + + /* initialize key->dp */ + if (cu == NULL) { + /* this case works only for uncompressed public keys */ + if ((err = ecc_set_curve_by_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; } + } + else { + /* this one works for both compressed / uncompressed pubkeys */ + if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } + } + + /* load public key */ + if ((err = ecc_set_key((unsigned char *)in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; } + + /* we're done */ + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c b/deps/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c new file mode 100644 index 0000000..ad2d9b1 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_decrypt_key.c @@ -0,0 +1,133 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_decrypt_key.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Decrypt an ECC encrypted key + @param in The ciphertext + @param inlen The length of the ciphertext (octets) + @param out [out] The plaintext + @param outlen [in/out] The max size and resulting size of the plaintext + @param key The corresponding private ECC key + @return CRYPT_OK if successful +*/ +int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const ecc_key *key) +{ + unsigned char *ecc_shared, *skey, *pub_expt; + unsigned long x, y; + unsigned long hashOID[32] = { 0 }; + int hash, err; + ecc_key pubkey; + ltc_asn1_list decode[3]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* right key type? */ + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* decode to find out hash */ + LTC_SET_ASN1(decode, 0, LTC_ASN1_OBJECT_IDENTIFIER, hashOID, sizeof(hashOID)/sizeof(hashOID[0])); + err = der_decode_sequence(in, inlen, decode, 1); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + return err; + } + + hash = find_hash_oid(hashOID, decode[0].size); + if (hash_is_valid(hash) != CRYPT_OK) { + return CRYPT_INVALID_PACKET; + } + + /* we now have the hash! */ + + /* allocate memory */ + pub_expt = XMALLOC(ECC_BUF_SIZE); + ecc_shared = XMALLOC(ECC_BUF_SIZE); + skey = XMALLOC(MAXBLOCKSIZE); + if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { + if (pub_expt != NULL) { + XFREE(pub_expt); + } + if (ecc_shared != NULL) { + XFREE(ecc_shared); + } + if (skey != NULL) { + XFREE(skey); + } + return CRYPT_MEM; + } + LTC_SET_ASN1(decode, 1, LTC_ASN1_OCTET_STRING, pub_expt, ECC_BUF_SIZE); + LTC_SET_ASN1(decode, 2, LTC_ASN1_OCTET_STRING, skey, MAXBLOCKSIZE); + + /* read the structure in now */ + if ((err = der_decode_sequence(in, inlen, decode, 3)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* import ECC key from packet */ + if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; } + + /* make shared key */ + x = ECC_BUF_SIZE; + if ((err = ecc_shared_secret(key, &pubkey, ecc_shared, &x)) != CRYPT_OK) { + ecc_free(&pubkey); + goto LBL_ERR; + } + ecc_free(&pubkey); + + y = MIN(ECC_BUF_SIZE, MAXBLOCKSIZE); + if ((err = hash_memory(hash, ecc_shared, x, ecc_shared, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* ensure the hash of the shared secret is at least as big as the encrypt itself */ + if (decode[2].size > y) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* avoid buffer overflow */ + if (*outlen < decode[2].size) { + *outlen = decode[2].size; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* Decrypt the key */ + for (x = 0; x < decode[2].size; x++) { + out[x] = skey[x] ^ ecc_shared[x]; + } + *outlen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(pub_expt, ECC_BUF_SIZE); + zeromem(ecc_shared, ECC_BUF_SIZE); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(pub_expt); + XFREE(ecc_shared); + XFREE(skey); + + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c b/deps/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c new file mode 100644 index 0000000..9929ff5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_encrypt_key.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_encrypt_key.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Encrypt a symmetric key with ECC + @param in The symmetric key you want to encrypt + @param inlen The length of the key to encrypt (octets) + @param out [out] The destination for the ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param hash The index of the hash you want to use + @param key The ECC key you want to encrypt to + @return CRYPT_OK if successful +*/ +int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash, + const ecc_key *key) +{ + unsigned char *pub_expt, *ecc_shared, *skey; + ecc_key pubkey; + unsigned long x, y, pubkeysize; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + if (inlen > hash_descriptor[hash].hashsize) { + return CRYPT_INVALID_HASH; + } + + /* make a random key and export the public copy */ + if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { return err; } + if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; } + + pub_expt = XMALLOC(ECC_BUF_SIZE); + ecc_shared = XMALLOC(ECC_BUF_SIZE); + skey = XMALLOC(MAXBLOCKSIZE); + if (pub_expt == NULL || ecc_shared == NULL || skey == NULL) { + if (pub_expt != NULL) { + XFREE(pub_expt); + } + if (ecc_shared != NULL) { + XFREE(ecc_shared); + } + if (skey != NULL) { + XFREE(skey); + } + ecc_free(&pubkey); + return CRYPT_MEM; + } + + pubkeysize = ECC_BUF_SIZE; + if (ltc_mp.sqrtmod_prime != NULL) { + /* PK_COMPRESSED requires sqrtmod_prime */ + err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey); + } + else { + err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey); + } + if (err != CRYPT_OK) { + ecc_free(&pubkey); + goto LBL_ERR; + } + + /* make random key */ + x = ECC_BUF_SIZE; + if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) { + ecc_free(&pubkey); + goto LBL_ERR; + } + ecc_free(&pubkey); + y = MAXBLOCKSIZE; + if ((err = hash_memory(hash, ecc_shared, x, skey, &y)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* Encrypt key */ + for (x = 0; x < inlen; x++) { + skey[x] ^= in[x]; + } + + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash].OIDlen, hash_descriptor[hash].OID, + LTC_ASN1_OCTET_STRING, pubkeysize, pub_expt, + LTC_ASN1_OCTET_STRING, inlen, skey, + LTC_ASN1_EOL, 0UL, NULL); + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + /* clean up */ + zeromem(pub_expt, ECC_BUF_SIZE); + zeromem(ecc_shared, ECC_BUF_SIZE); + zeromem(skey, MAXBLOCKSIZE); +#endif + + XFREE(skey); + XFREE(ecc_shared); + XFREE(pub_expt); + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_export.c b/deps/libtomcrypt/src/pk/ecc/ecc_export.c new file mode 100644 index 0000000..edbe4c3 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_export.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_export.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Export an ECC key as a binary packet + @param out [out] Destination for the key + @param outlen [in/out] Max size and resulting size of the exported key + @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) + @param key The key to export + @return CRYPT_OK if successful +*/ +int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) +{ + int err; + unsigned char flags[1]; + unsigned long key_size; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* type valid? */ + if (key->type != PK_PRIVATE && type == PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; + } + + /* we store the NIST byte size */ + key_size = key->dp.size; + + if (type == PK_PRIVATE) { + flags[0] = 1; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_INTEGER, 1UL, key->k, + LTC_ASN1_EOL, 0UL, NULL); + } else { + flags[0] = 0; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_EOL, 0UL, NULL); + } + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_export_openssl.c b/deps/libtomcrypt/src/pk/ecc/ecc_export_openssl.c new file mode 100644 index 0000000..2e89996 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_export_openssl.c @@ -0,0 +1,167 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** + Export an ECC key as a binary packet + @param out [out] Destination for the key + @param outlen [in/out] Max size and resulting size of the exported key + @param type The type of key you want to export (PK_PRIVATE or PK_PUBLIC) + @param key The key to export + @return CRYPT_OK if successful +*/ + +int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) +{ + int err; + void *prime, *order, *a, *b, *gx, *gy; + unsigned char bin_a[256], bin_b[256], bin_k[256], bin_g[512], bin_xy[512]; + unsigned long len_a, len_b, len_k, len_g, len_xy; + unsigned long cofactor, one = 1; + const char *OID; + unsigned long oid[16], oidlen; + ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4], pub_xy, ecparams; + int flag_oid = type & PK_CURVEOID ? 1 : 0; + int flag_com = type & PK_COMPRESSED ? 1 : 0; + int flag_pri = type & PK_PRIVATE ? 1 : 0; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH; + + if (flag_oid) { + /* http://tools.ietf.org/html/rfc5912 + ECParameters ::= CHOICE { + namedCurve CURVE.&id({NamedCurve}) # OBJECT + } + */ + if (key->dp.oidlen == 0) { err = CRYPT_INVALID_ARG; goto error; } + LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen); + } + else { + prime = key->dp.prime; + order = key->dp.order; + a = key->dp.A; + b = key->dp.B; + gx = key->dp.base.x; + gy = key->dp.base.y; + cofactor = key->dp.cofactor; + + /* curve param a */ + len_a = mp_unsigned_bin_size(a); + if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) { goto error; } + if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */ + + /* curve param b */ + len_b = mp_unsigned_bin_size(b); + if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) { goto error; } + if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */ + + /* base point - (un)compressed based on flag_com */ + len_g = sizeof(bin_g); + err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com); + if (err != CRYPT_OK) { goto error; } + + /* we support only prime-field EC */ + if ((err = pk_get_oid(LTC_OID_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; } + + /* http://tools.ietf.org/html/rfc3279 + ECParameters ::= SEQUENCE { # SEQUENCE + version INTEGER { ecpVer1(1) } (ecpVer1) # INTEGER :01 + FieldID ::= SEQUENCE { # SEQUENCE + fieldType FIELD-ID.&id({IOSet}), # OBJECT :prime-field + parameters FIELD-ID.&Type({IOSet}{@fieldType}) # INTEGER + } + Curve ::= SEQUENCE { # SEQUENCE + a FieldElement ::= OCTET STRING # OCTET STRING + b FieldElement ::= OCTET STRING # OCTET STRING + seed BIT STRING OPTIONAL + } + base ECPoint ::= OCTET STRING # OCTET STRING + order INTEGER, # INTEGER + cofactor INTEGER OPTIONAL # INTEGER + } + */ + + oidlen = sizeof(oid)/sizeof(oid[0]); + if ((err = pk_oid_str_to_num(OID, oid, &oidlen)) != CRYPT_OK) { + goto error; + } + + /* FieldID SEQUENCE */ + LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, oidlen); + LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); + + /* Curve SEQUENCE */ + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, len_a); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, len_b); + + /* ECParameters SEQUENCE */ + LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &one, 1UL); + LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); + LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 2UL); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, len_g); + LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); + LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); + + /* ECParameters used by ECPrivateKey or SubjectPublicKeyInfo below */ + LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); + } + + /* public key - (un)compressed based on flag_com */ + len_xy = sizeof(bin_xy); + err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com); + if (err != CRYPT_OK) { + goto error; + } + + if (flag_pri) { + + /* http://tools.ietf.org/html/rfc5915 + ECPrivateKey ::= SEQUENCE { # SEQUENCE + version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1) # INTEGER :01 + privateKey OCTET STRING, # OCTET STRING + [0] ECParameters # see above + [1] publicKey # BIT STRING + } + */ + + /* private key */ + len_k = mp_unsigned_bin_size(key->k); + if (len_k > sizeof(bin_k)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK) { goto error; } + + LTC_SET_ASN1(&pub_xy, 0, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8*len_xy); + LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &one, 1); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, len_k); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, &ecparams); /* context specific 0 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, &pub_xy); /* context specific 1 */ + + err = der_encode_sequence(seq_priv, 4, out, outlen); + } + else { + /* http://tools.ietf.org/html/rfc5480 + SubjectPublicKeyInfo ::= SEQUENCE { # SEQUENCE + AlgorithmIdentifier ::= SEQUENCE { # SEQUENCE + algorithm OBJECT IDENTIFIER # OBJECT :id-ecPublicKey + ECParameters # see above + } + subjectPublicKey BIT STRING # BIT STRING + } + */ + err = x509_encode_subject_public_key_info( out, outlen, LTC_OID_EC, bin_xy, len_xy, + ecparams.type, ecparams.data, ecparams.size ); + } + +error: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_find_curve.c b/deps/libtomcrypt/src/pk/ecc/ecc_find_curve.c new file mode 100644 index 0000000..0279c7a --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_find_curve.c @@ -0,0 +1,242 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static const struct { + const char *OID; + const char *names[6]; +} s_curve_names[] = { +#ifdef LTC_ECC_SECP112R1 + { + "1.3.132.0.6", { "SECP112R1", "ECC-112", NULL } + }, +#endif +#ifdef LTC_ECC_SECP112R2 + { + "1.3.132.0.7", { "SECP112R2", NULL } + }, +#endif +#ifdef LTC_ECC_SECP128R1 + { + "1.3.132.0.28", { "SECP128R1", "ECC-128", NULL } + }, +#endif +#ifdef LTC_ECC_SECP128R2 + { + "1.3.132.0.29", { "SECP128R2", NULL } + }, +#endif +#ifdef LTC_ECC_SECP160R1 + { + "1.3.132.0.8", { "SECP160R1", "ECC-160", NULL } + }, +#endif +#ifdef LTC_ECC_SECP160R2 + { + "1.3.132.0.30", { "SECP160R2", NULL } + }, +#endif +#ifdef LTC_ECC_SECP160K1 + { + "1.3.132.0.9", { "SECP160K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP192R1 + { + "1.2.840.10045.3.1.1", { "SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME192V2 + { + "1.2.840.10045.3.1.2", { "PRIME192V2", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME192V3 + { + "1.2.840.10045.3.1.3", { "PRIME192V3", NULL } + }, +#endif +#ifdef LTC_ECC_SECP192K1 + { + "1.3.132.0.31", { "SECP192K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP224R1 + { + "1.3.132.0.33", { "SECP224R1", "NISTP224", "ECC-224", "P-224", NULL } + }, +#endif +#ifdef LTC_ECC_SECP224K1 + { + "1.3.132.0.32", { "SECP224K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP256R1 + { + "1.2.840.10045.3.1.7", { "SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256", NULL } + }, +#endif +#ifdef LTC_ECC_SECP256K1 + { + "1.3.132.0.10", { "SECP256K1", NULL } + }, +#endif +#ifdef LTC_ECC_SECP384R1 + { + "1.3.132.0.34", { "SECP384R1", "NISTP384", "ECC-384", "P-384", NULL } + }, +#endif +#ifdef LTC_ECC_SECP521R1 + { + "1.3.132.0.35", { "SECP521R1", "NISTP521", "ECC-521", "P-521", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME239V1 + { + "1.2.840.10045.3.1.4", { "PRIME239V1", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME239V2 + { + "1.2.840.10045.3.1.5", { "PRIME239V2", NULL } + }, +#endif +#ifdef LTC_ECC_PRIME239V3 + { + "1.2.840.10045.3.1.6", { "PRIME239V3", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP160R1 + { + "1.3.36.3.3.2.8.1.1.1", { "BRAINPOOLP160R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP192R1 + { + "1.3.36.3.3.2.8.1.1.3", { "BRAINPOOLP192R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP224R1 + { + "1.3.36.3.3.2.8.1.1.5", { "BRAINPOOLP224R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP256R1 + { + "1.3.36.3.3.2.8.1.1.7", { "BRAINPOOLP256R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP320R1 + { + "1.3.36.3.3.2.8.1.1.9", { "BRAINPOOLP320R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP384R1 + { + "1.3.36.3.3.2.8.1.1.11", { "BRAINPOOLP384R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP512R1 + { + "1.3.36.3.3.2.8.1.1.13", { "BRAINPOOLP512R1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP160T1 + { + "1.3.36.3.3.2.8.1.1.2", { "BRAINPOOLP160T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP192T1 + { + "1.3.36.3.3.2.8.1.1.4", { "BRAINPOOLP192T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP224T1 + { + "1.3.36.3.3.2.8.1.1.6", { "BRAINPOOLP224T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP256T1 + { + "1.3.36.3.3.2.8.1.1.8", { "BRAINPOOLP256T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP320T1 + { + "1.3.36.3.3.2.8.1.1.10", { "BRAINPOOLP320T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP384T1 + { + "1.3.36.3.3.2.8.1.1.12", { "BRAINPOOLP384T1", NULL } + }, +#endif +#ifdef LTC_ECC_BRAINPOOLP512T1 + { + "1.3.36.3.3.2.8.1.1.14", { "BRAINPOOLP512T1", NULL } + }, +#endif + { + NULL, { NULL } + } +}; + +/* case-insensitive match + ignore '-', '_', ' ' */ +static int s_name_match(const char *left, const char *right) +{ + char lc_r, lc_l; + + while ((*left != '\0') && (*right != '\0')) { + while ((*left == ' ') || (*left == '-') || (*left == '_')) left++; + while ((*right == ' ') || (*right == '-') || (*right == '_')) right++; + if (*left == '\0' || *right == '\0') break; + lc_r = *right; + lc_l = *left; + if ((lc_r >= 'A') && (lc_r <= 'Z')) lc_r += 32; + if ((lc_l >= 'A') && (lc_l <= 'Z')) lc_l += 32; + if (lc_l != lc_r) return 0; + left++; + right++; + } + + if ((*left == '\0') && (*right == '\0')) return 1; + return 0; +} + +int ecc_find_curve(const char *name_or_oid, const ltc_ecc_curve **cu) +{ + int i, j; + const char *OID = NULL; + + LTC_ARGCHK(cu != NULL); + LTC_ARGCHK(name_or_oid != NULL); + + *cu = NULL; + + for (i = 0; s_curve_names[i].OID != NULL && !OID; i++) { + if (XSTRCMP(s_curve_names[i].OID, name_or_oid) == 0) { + OID = s_curve_names[i].OID; + } + for (j = 0; s_curve_names[i].names[j] != NULL && !OID; j++) { + if (s_name_match(s_curve_names[i].names[j], name_or_oid)) { + OID = s_curve_names[i].OID; + } + } + } + + if (OID != NULL) { + for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { + if (XSTRCMP(ltc_ecc_curves[i].OID, OID) == 0) { + *cu = <c_ecc_curves[i]; + return CRYPT_OK; + } + } + } + + return CRYPT_INVALID_ARG; /* not found */ +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_free.c b/deps/libtomcrypt/src/pk/ecc/ecc_free.c new file mode 100644 index 0000000..6133109 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_free.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_free.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Free an ECC key from memory + @param key The key you wish to free +*/ +void ecc_free(ecc_key *key) +{ + LTC_ARGCHKVD(key != NULL); + + mp_cleanup_multi(&key->dp.prime, &key->dp.order, + &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, + &key->k, NULL); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_get_key.c b/deps/libtomcrypt/src/pk/ecc/ecc_get_key.c new file mode 100644 index 0000000..d30fd06 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_get_key.c @@ -0,0 +1,50 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** Export raw public or private key (public keys = ANS X9.63 compressed or uncompressed; private keys = raw bytes) + @param out [out] destination of export + @param outlen [in/out] Length of destination and final output size + @param type PK_PRIVATE, PK_PUBLIC or PK_PUBLIC|PK_COMPRESSED + @param key Key to export + Return CRYPT_OK on success +*/ + +int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key) +{ + unsigned long size, ksize; + int err, compressed; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + size = key->dp.size; + compressed = type & PK_COMPRESSED ? 1 : 0; + type &= ~PK_COMPRESSED; + + if (type == PK_PUBLIC) { + if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) { + return err; + } + } + else if (type == PK_PRIVATE) { + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + *outlen = size; + if (size > *outlen) return CRYPT_BUFFER_OVERFLOW; + if ((ksize = mp_unsigned_bin_size(key->k)) > size) return CRYPT_BUFFER_OVERFLOW; + /* pad and store k */ + if ((err = mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK) return err; + zeromem(out, size - ksize); + } + else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c b/deps/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c new file mode 100644 index 0000000..756f641 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_get_oid_str.c @@ -0,0 +1,22 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** Extract OID as a string from ECC key + @param out [out] destination buffer + @param outlen [in/out] Length of destination buffer and final output size (without terminating NUL byte) + @param key The ECC key + Return CRYPT_OK on success +*/ + +int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key) +{ + LTC_ARGCHK(key != NULL); + + return pk_oid_num_to_str(key->dp.oid, key->dp.oidlen, out, outlen); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_get_size.c b/deps/libtomcrypt/src/pk/ecc/ecc_get_size.c new file mode 100644 index 0000000..e563339 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_get_size.c @@ -0,0 +1,26 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_get_size.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Get the size of an ECC key + @param key The key to get the size of + @return The size (octets) of the key or INT_MAX on error +*/ +int ecc_get_size(const ecc_key *key) +{ + if (key == NULL) { + return INT_MAX; + } + return key->dp.size; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_import.c b/deps/libtomcrypt/src/pk/ecc/ecc_import.c new file mode 100644 index 0000000..64bed21 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_import.c @@ -0,0 +1,100 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_import.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Import an ECC key from a binary packet + @param in The packet to import + @param inlen The length of the packet + @param key [out] The destination of the import + @return CRYPT_OK if successful, upon error all allocated memory will be freed +*/ +int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + return ecc_import_ex(in, inlen, key, NULL); +} + +/** + Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones + @param in The packet to import + @param inlen The length of the packet + @param key [out] The destination of the import + @param cu pointer to user supplied params; must be the same as the params used when exporting + @return CRYPT_OK if successful, upon error all allocated memory will be freed +*/ +int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu) +{ + unsigned long key_size; + unsigned char flags[1]; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* find out what type of key it is */ + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_EOL, 0UL, NULL); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + return err; + } + + /* allocate & initialize the key */ + if (cu == NULL) { + if ((err = ecc_set_curve_by_size(key_size, key)) != CRYPT_OK) { goto done; } + } else { + if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { goto done; } + } + + if (flags[0] == 1) { + /* private key */ + key->type = PK_PRIVATE; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_INTEGER, 1UL, key->k, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto done; + } + } else if (flags[0] == 0) { + /* public key */ + key->type = PK_PUBLIC; + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_BIT_STRING, 1UL, flags, + LTC_ASN1_SHORT_INTEGER, 1UL, &key_size, + LTC_ASN1_INTEGER, 1UL, key->pubkey.x, + LTC_ASN1_INTEGER, 1UL, key->pubkey.y, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto done; + } + } + else { + err = CRYPT_INVALID_PACKET; + goto done; + } + + /* set z */ + if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; } + + /* point on the curve + other checks */ + if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; } + + /* we're good */ + return CRYPT_OK; + +done: + ecc_free(key); + return err; +} +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_import_openssl.c b/deps/libtomcrypt/src/pk/ecc/ecc_import_openssl.c new file mode 100644 index 0000000..325b0b0 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_import_openssl.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static int s_ecc_import_private_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + ltc_asn1_list seq_priv[4], custom[2]; + unsigned char bin_xy[2*ECC_MAXSIZE+2], bin_k[ECC_MAXSIZE]; + unsigned long len, pkver = 0, curveoid[16]; + char OID[256]; + const ltc_ecc_curve *curve; + int err; + + /* ### try to load private key - no curve parameters just curve OID */ + + /* ECPrivateKey SEQUENCE */ + LTC_SET_ASN1(custom, 0, LTC_ASN1_OBJECT_IDENTIFIER, curveoid, 16UL); + LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); + LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ + + /* try to load private key */ + err = der_decode_sequence(in, inlen, seq_priv, 4); + if (err == CRYPT_OK) { + /* load curve parameters for given curve OID */ + len = sizeof(OID); + if ((err = pk_oid_num_to_str(curveoid, custom[0].size, OID, &len)) != CRYPT_OK) { goto error; } + if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } + if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; } + /* load private+public key */ + err = ecc_set_key(bin_k, seq_priv[1].size, PK_PRIVATE, key); + } +error: + return err; +} + +static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + void *prime, *order, *a, *b, *gx, *gy; + ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6], seq_priv[4], custom[2]; + unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE], bin_k[ECC_MAXSIZE]; + unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; + unsigned long len_a, len_b, len_k, len_g; + unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16]; + int err; + + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* ### try to load private key - curve parameters included */ + + /* ECPrivateKey SEQUENCE */ + LTC_SET_ASN1(custom, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); + LTC_SET_ASN1(custom, 1, LTC_ASN1_RAW_BIT_STRING, bin_xy, 8UL*sizeof(bin_xy)); + LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER, &pkver, 1UL); + LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING, bin_k, sizeof(bin_k)); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); /* context specific 0 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(seq_priv, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, custom + 1); /* context specific 1 */ + /* ECParameters SEQUENCE */ + LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); + LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); + LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); + LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); + LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); + seq_ecparams[5].optional = 1; + /* FieldID SEQUENCE */ + LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); + LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); + /* Curve SEQUENCE */ + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); + LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8UL*sizeof(bin_seed)); + seq_curve[2].optional = 1; + /* try to load private key */ + err = der_decode_sequence(in, inlen, seq_priv, 4); + if (err == CRYPT_OK) { + len_k = seq_priv[1].size; + len_a = seq_curve[0].size; + len_b = seq_curve[1].size; + len_g = seq_ecparams[3].size; + /* create bignums */ + if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } + /* load curve parameters */ + if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } + /* load private+public key */ + err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key); + } +error: + mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); + return err; +} + +int ecc_import_openssl(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + int err; + + if ((err = ecc_import_subject_public_key_info(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + if ((err = s_ecc_import_private_with_oid(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + err = s_ecc_import_private_with_curve(in, inlen, key); + +success: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c b/deps/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c new file mode 100644 index 0000000..a6fd7bf --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c @@ -0,0 +1,186 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +typedef struct { + ltc_asn1_type t; + ltc_asn1_list **pp; +} der_flexi_check; + +#define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) \ + do { \ + int LTC_SDFC_temp##__LINE__ = (index); \ + list[LTC_SDFC_temp##__LINE__].t = Type; \ + list[LTC_SDFC_temp##__LINE__].pp = P; \ + } while (0) + +static int s_der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check) +{ + const ltc_asn1_list *cur; + if (flexi->type != LTC_ASN1_SEQUENCE) { + return CRYPT_INVALID_PACKET; + } + cur = flexi->child; + while(check->t != LTC_ASN1_EOL) { + if (!LTC_ASN1_IS_TYPE(cur, check->t)) { + return CRYPT_INVALID_PACKET; + } + if (check->pp != NULL) *check->pp = (ltc_asn1_list*)cur; + cur = cur->next; + check++; + } + return CRYPT_OK; +} + +/* NOTE: s_der_decode_pkcs8_flexi & related stuff can be shared with rsa_import_pkcs8() */ + +int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + ecc_key *key) +{ + void *a, *b, *gx, *gy; + unsigned long len, cofactor, n; + const char *pka_ec_oid; + int err; + char OID[256]; + const ltc_ecc_curve *curve; + ltc_asn1_list *p = NULL, *l = NULL; + der_flexi_check flexi_should[7]; + ltc_asn1_list *seq, *priv_key; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* get EC alg oid */ + err = pk_get_oid(LTC_OID_EC, &pka_ec_oid); + if (err != CRYPT_OK) return err; + + /* init key */ + err = mp_init_multi(&a, &b, &gx, &gy, LTC_NULL); + if (err != CRYPT_OK) return err; + + + if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) { + + /* Setup for basic structure */ + n=0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, NULL); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seq); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &priv_key); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + + if (((err = s_der_flexi_sequence_cmp(l, flexi_should)) == CRYPT_OK) && + (pk_oid_cmp_with_asn1(pka_ec_oid, seq->child) == CRYPT_OK)) { + ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor; + + /* Setup for CASE 2 */ + n=0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &version); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &field); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &point); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &point_g); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &order); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_INTEGER, &p_cofactor); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + + if (LTC_ASN1_IS_TYPE(seq->child->next, LTC_ASN1_OBJECT_IDENTIFIER)) { + /* CASE 1: curve by OID (AKA short variant): + * 0:d=0 hl=2 l= 100 cons: SEQUENCE + * 2:d=1 hl=2 l= 1 prim: INTEGER :00 + * 5:d=1 hl=2 l= 16 cons: SEQUENCE (== *seq) + * 7:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey + * 16:d=2 hl=2 l= 5 prim: OBJECT :(== *curve_oid (e.g. secp256k1 (== 1.3.132.0.10))) + * 23:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) + */ + ltc_asn1_list *curve_oid = seq->child->next; + len = sizeof(OID); + if ((err = pk_oid_num_to_str(curve_oid->data, curve_oid->size, OID, &len)) != CRYPT_OK) { goto LBL_DONE; } + if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto LBL_DONE; } + if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto LBL_DONE; } + } + else if ((err = s_der_flexi_sequence_cmp(seq->child->next, flexi_should)) == CRYPT_OK) { + /* CASE 2: explicit curve parameters (AKA long variant): + * 0:d=0 hl=3 l= 227 cons: SEQUENCE + * 3:d=1 hl=2 l= 1 prim: INTEGER :00 + * 6:d=1 hl=3 l= 142 cons: SEQUENCE (== *seq) + * 9:d=2 hl=2 l= 7 prim: OBJECT :id-ecPublicKey + * 18:d=2 hl=3 l= 130 cons: SEQUENCE + * 21:d=3 hl=2 l= 1 prim: INTEGER :01 + * 24:d=3 hl=2 l= 44 cons: SEQUENCE (== *field) + * 26:d=4 hl=2 l= 7 prim: OBJECT :prime-field + * 35:d=4 hl=2 l= 33 prim: INTEGER :(== *prime / curve.prime) + * 70:d=3 hl=2 l= 6 cons: SEQUENCE (== *point) + * 72:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.A) + * 75:d=4 hl=2 l= 1 prim: OCTET STRING :bytes (== curve.B) + * 78:d=3 hl=2 l= 33 prim: OCTET STRING :bytes (== *g_point / curve.G-point) + * 113:d=3 hl=2 l= 33 prim: INTEGER :(== *order / curve.order) + * 148:d=3 hl=2 l= 1 prim: INTEGER :(== curve.cofactor) + * 151:d=1 hl=2 l= 77 prim: OCTET STRING :bytes (== *priv_key) + */ + + if (mp_get_int(version->data) != 1) { + goto LBL_DONE; + } + cofactor = mp_get_int(p_cofactor->data); + + if (LTC_ASN1_IS_TYPE(field->child, LTC_ASN1_OBJECT_IDENTIFIER) && + LTC_ASN1_IS_TYPE(field->child->next, LTC_ASN1_INTEGER) && + LTC_ASN1_IS_TYPE(point->child, LTC_ASN1_OCTET_STRING) && + LTC_ASN1_IS_TYPE(point->child->next, LTC_ASN1_OCTET_STRING)) { + + ltc_asn1_list *prime = field->child->next; + if ((err = mp_read_unsigned_bin(a, point->child->data, point->child->size)) != CRYPT_OK) { + goto LBL_DONE; + } + if ((err = mp_read_unsigned_bin(b, point->child->next->data, point->child->next->size)) != CRYPT_OK) { + goto LBL_DONE; + } + if ((err = ltc_ecc_import_point(point_g->data, point_g->size, prime->data, a, b, gx, gy)) != CRYPT_OK) { + goto LBL_DONE; + } + if ((err = ecc_set_curve_from_mpis(a, b, prime->data, order->data, gx, gy, cofactor, key)) != CRYPT_OK) { + goto LBL_DONE; + } + } + } + else { + err = CRYPT_INVALID_PACKET; + goto LBL_DONE; + } + + /* load private key value 'k' */ + len = priv_key->size; + if ((err = der_decode_sequence_flexi(priv_key->data, &len, &p)) == CRYPT_OK) { + if (p->type == LTC_ASN1_SEQUENCE && + LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) && + LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) { + ltc_asn1_list *lk = p->child->next; + if (mp_cmp_d(p->child->data, 1) != LTC_MP_EQ) { + err = CRYPT_INVALID_PACKET; + goto LBL_ECCFREE; + } + if ((err = ecc_set_key(lk->data, lk->size, PK_PRIVATE, key)) != CRYPT_OK) { + goto LBL_ECCFREE; + } + goto LBL_DONE; /* success */ + } + } + } + } + err = CRYPT_INVALID_PACKET; + goto LBL_DONE; + +LBL_ECCFREE: + ecc_free(key); +LBL_DONE: + mp_clear_multi(a, b, gx, gy, LTC_NULL); + if (l) der_free_sequence_flexi(l); + if (p) der_free_sequence_flexi(p); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_import_x509.c b/deps/libtomcrypt/src/pk/ecc/ecc_import_x509.c new file mode 100644 index 0000000..e4ba5e3 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_import_x509.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + unsigned char bin_xy[2*ECC_MAXSIZE+2]; + unsigned long curveoid[16]; + unsigned long len_xy, len_oid, len; + char OID[256]; + const ltc_ecc_curve *curve; + int err; + + len_xy = sizeof(bin_xy); + len_oid = 16; + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, + LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid); + if (err == CRYPT_OK) { + /* load curve parameters for given curve OID */ + len = sizeof(OID); + if ((err = pk_oid_num_to_str(curveoid, len_oid, OID, &len)) != CRYPT_OK) { goto error; } + if ((err = ecc_find_curve(OID, &curve)) != CRYPT_OK) { goto error; } + if ((err = ecc_set_curve(curve, key)) != CRYPT_OK) { goto error; } + /* load public key */ + err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); + } +error: + return err; +} + +static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + void *prime, *order, *a, *b, *gx, *gy; + ltc_asn1_list seq_fieldid[2], seq_curve[3], seq_ecparams[6]; + unsigned char bin_a[ECC_MAXSIZE], bin_b[ECC_MAXSIZE]; + unsigned char bin_g[2*ECC_MAXSIZE+1], bin_xy[2*ECC_MAXSIZE+2], bin_seed[128]; + unsigned long len_a, len_b, len_g, len_xy, len; + unsigned long cofactor = 0, ecver = 0, tmpoid[16]; + int err; + + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* ECParameters SEQUENCE */ + LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER, &ecver, 1UL); + LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE, seq_fieldid, 2UL); + LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE, seq_curve, 3UL); + LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING, bin_g, sizeof(bin_g)); + LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER, order, 1UL); + LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER, &cofactor, 1UL); + seq_ecparams[5].optional = 1; + /* FieldID SEQUENCE */ + LTC_SET_ASN1(seq_fieldid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, 16UL); + LTC_SET_ASN1(seq_fieldid, 1, LTC_ASN1_INTEGER, prime, 1UL); + /* Curve SEQUENCE */ + LTC_SET_ASN1(seq_curve, 0, LTC_ASN1_OCTET_STRING, bin_a, sizeof(bin_a)); + LTC_SET_ASN1(seq_curve, 1, LTC_ASN1_OCTET_STRING, bin_b, sizeof(bin_b)); + LTC_SET_ASN1(seq_curve, 2, LTC_ASN1_RAW_BIT_STRING, bin_seed, 8u*sizeof(bin_seed)); + seq_curve[2].optional = 1; + /* try to load public key */ + len_xy = sizeof(bin_xy); + len = 6; + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); + + if (err == CRYPT_OK) { + len_a = seq_curve[0].size; + len_b = seq_curve[1].size; + len_g = seq_ecparams[3].size; + /* create bignums */ + if ((err = mp_read_unsigned_bin(a, bin_a, len_a)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(b, bin_b, len_b)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_import_point(bin_g, len_g, prime, a, b, gx, gy)) != CRYPT_OK) { goto error; } + /* load curve parameters */ + if ((err = ecc_set_curve_from_mpis(a, b, prime, order, gx, gy, cofactor, key)) != CRYPT_OK) { goto error; } + /* load public key */ + err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); + } +error: + mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); + return err; +} + +int ecc_import_subject_public_key_info(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + int err; + + if ((err = s_ecc_import_x509_with_oid(in, inlen, key)) == CRYPT_OK) { + goto success; + } + + err = s_ecc_import_x509_with_curve(in, inlen, key); + +success: + return err; +} + +/** + Import an ECC key from a X.509 certificate + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key) +{ + return x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_EC, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)ecc_import_subject_public_key_info, key); +} + +#endif /* LTC_MECC */ + diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_make_key.c b/deps/libtomcrypt/src/pk/ecc/ecc_make_key.c new file mode 100644 index 0000000..1b04741 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_make_key.c @@ -0,0 +1,73 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_make_key.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Make a new ECC key + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param keysize The keysize for the new key (in octets from 20 to 65 bytes) + @param key [out] Destination of the newly created key + @return CRYPT_OK if successful, upon error all allocated memory will be freed +*/ +int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) +{ + int err; + + if ((err = ecc_set_curve_by_size(keysize, key)) != CRYPT_OK) { return err; } + if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } + return CRYPT_OK; +} + +int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu) +{ + int err; + if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { return err; } + if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; } + return CRYPT_OK; +} + +int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key) +{ + int err; + + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(key->dp.size > 0); + + /* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates): + * the generated private key k should be the range [1, order-1] + * a/ N = bitlen(order) + * b/ generate N random bits and convert them into big integer k + * c/ if k not in [1, order-1] go to b/ + * e/ Q = k*G + */ + if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) { + goto error; + } + + /* make the public key */ + if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) { + goto error; + } + key->type = PK_PRIVATE; + + /* success */ + err = CRYPT_OK; + goto cleanup; + +error: + ecc_free(key); +cleanup: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_recover_key.c b/deps/libtomcrypt/src/pk/ecc/ecc_recover_key.c new file mode 100644 index 0000000..b6ae644 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_recover_key.c @@ -0,0 +1,260 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +#ifdef LTC_ECC_SHAMIR + +/** + @file ecc_recover_key.c + ECC Crypto, Russ Williams +*/ + +/** + Recover ECC public key from signature and hash + @param sig The signature to verify + @param siglen The length of the signature (octets) + @param hash The hash (message digest) that was signed + @param hashlen The length of the hash (octets) + @param recid The recovery ID ("v"), can be -1 if signature contains it + @param sigformat The format of the signature (ecc_signature_type) + @param key The recovered public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_recover_key(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int recid, ecc_signature_type sigformat, ecc_key *key) +{ + ecc_point *mG = NULL, *mQ = NULL, *mR = NULL; + void *p, *m, *a, *b; + void *r, *s, *v, *w, *t1, *t2, *u1, *u2, *v1, *v2, *e, *x, *y, *a_plus3; + void *mu = NULL, *ma = NULL; + void *mp = NULL; + int err; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(key != NULL); + + /* BEWARE: requires sqrtmod_prime */ + if (ltc_mp.sqrtmod_prime == NULL) { + return CRYPT_ERROR; + } + + /* allocate ints */ + if ((err = mp_init_multi(&r, &s, &v, &w, &t1, &t2, &u1, &u2, &v1, &v2, &e, &x, &y, &a_plus3, LTC_NULL)) != CRYPT_OK) { + return err; + } + + p = key->dp.order; + m = key->dp.prime; + a = key->dp.A; + b = key->dp.B; + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { + goto error; + } + + /* allocate points */ + mG = ltc_ecc_new_point(); + mQ = ltc_ecc_new_point(); + mR = ltc_ecc_new_point(); + if (mR == NULL || mQ == NULL || mG == NULL) { + err = CRYPT_MEM; + goto error; + } + + if (sigformat == LTC_ECCSIG_ANSIX962) { + /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ + if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_RFC7518) { + /* RFC7518 format - raw (r,s) */ + i = mp_unsigned_bin_size(key->dp.order); + if (siglen != (2*i)) { + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_ETH27) { + /* Ethereum (v,r,s) format */ + if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { + /* Only valid for secp256k1 - OID 1.3.132.0.10 */ + err = CRYPT_ERROR; goto error; + } + if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ + err = CRYPT_INVALID_PACKET; + goto error; + } + i = (unsigned long)sig[64]; + if ((i>=27) && (i<31)) i -= 27; /* Ethereum adds 27 to recovery ID */ + if (recid >= 0 && ((unsigned long)recid != i)) { + /* Recovery ID specified, but doesn't match signature */ + err = CRYPT_INVALID_PACKET; + goto error; + } + recid = i; + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; } + } +#ifdef LTC_SSH + else if (sigformat == LTC_ECCSIG_RFC5656) { + char name[64], name2[64]; + unsigned long namelen = sizeof(name); + unsigned long name2len = sizeof(name2); + + /* Decode as SSH data sequence, per RFC4251 */ + if ((err = ssh_decode_sequence_multi(sig, &siglen, + LTC_SSHDATA_STRING, name, &namelen, + LTC_SSHDATA_MPINT, r, + LTC_SSHDATA_MPINT, s, + LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } + + + /* Check curve matches identifier string */ + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { + err = CRYPT_INVALID_ARG; + goto error; + } + } +#endif + else { + /* Unknown signature format */ + err = CRYPT_ERROR; + goto error; + } + + if (recid < 0 || (unsigned long)recid >= 2*(key->dp.cofactor+1)) { + /* Recovery ID is out of range, reject it */ + err = CRYPT_INVALID_ARG; + goto error; + } + + /* check for zero */ + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || + mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* read hash - truncate if needed */ + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > hashlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } + } + + /* decompress point from r=(x mod p) - BEWARE: requires sqrtmod_prime */ + /* x = r + p*(recid/2) */ + if ((err = mp_set(x, recid/2)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(p, x, m, x)) != CRYPT_OK) { goto error; } + if ((err = mp_add(x, r, x)) != CRYPT_OK) { goto error; } + /* compute x^3 */ + if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(t1, x, m, t1)) != CRYPT_OK) { goto error; } + /* compute x^3 + a*x */ + if ((err = mp_mulmod(a, x, m, t2)) != CRYPT_OK) { goto error; } + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto error; } + /* compute x^3 + a*x + b */ + if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto error; } + /* compute sqrt(x^3 + a*x + b) */ + if ((err = mp_sqrtmod_prime(t1, m, t2)) != CRYPT_OK) { goto error; } + + /* fill in mR */ + if ((err = mp_copy(x, mR->x)) != CRYPT_OK) { goto error; } + if ((mp_isodd(t2) && (recid%2)) || (!mp_isodd(t2) && !(recid%2))) { + if ((err = mp_mod(t2, m, mR->y)) != CRYPT_OK) { goto error; } + } + else { + if ((err = mp_submod(m, t2, m, mR->y)) != CRYPT_OK) { goto error; } + } + if ((err = mp_set(mR->z, 1)) != CRYPT_OK) { goto error; } + + /* w = r^-1 mod n */ + if ((err = mp_invmod(r, p, w)) != CRYPT_OK) { goto error; } + /* v1 = sw */ + if ((err = mp_mulmod(s, w, p, v1)) != CRYPT_OK) { goto error; } + /* v2 = -ew */ + if ((err = mp_mulmod(e, w, p, v2)) != CRYPT_OK) { goto error; } + if ((err = mp_submod(p, v2, p, v2)) != CRYPT_OK) { goto error; } + + /* w = s^-1 mod n */ + if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } + /* u1 = ew */ + if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } + /* u2 = rw */ + if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } + + /* find mG */ + if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } + + /* find the montgomery mp */ + if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { + if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } + } + + /* recover mQ from mR */ + /* compute v1*mR + v2*mG = mQ using Shamir's trick */ + if ((err = ltc_mp.ecc_mul2add(mR, v1, mG, v2, mQ, ma, m)) != CRYPT_OK) { goto error; } + + /* compute u1*mG + u2*mQ = mG using Shamir's trick */ + if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } + + /* v = X_x1 mod n */ + if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } + + /* does v == r */ + if (mp_cmp(v, r) == LTC_MP_EQ) { + /* found public key which verifies signature */ + if ((err = ltc_ecc_copy_point(mQ, &key->pubkey)) != CRYPT_OK) { goto error; } + /* point on the curve + other checks */ + if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto error; } + + key->type = PK_PUBLIC; + + err = CRYPT_OK; + } + else { + /* not found - recid is wrong or we're unable to calculate public key for some other reason */ + err = CRYPT_INVALID_ARG; + } + +error: + if (ma != NULL) mp_clear(ma); + if (mu != NULL) mp_clear(mu); + if (mp != NULL) mp_montgomery_free(mp); + if (mR != NULL) ltc_ecc_del_point(mR); + if (mQ != NULL) ltc_ecc_del_point(mQ); + if (mG != NULL) ltc_ecc_del_point(mG); + mp_clear_multi(a_plus3, y, x, e, v2, v1, u2, u1, t2, t1, w, v, s, r, LTC_NULL); + return err; +} + +#endif +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_set_curve.c b/deps/libtomcrypt/src/pk/ecc/ecc_set_curve.c new file mode 100644 index 0000000..427a593 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_set_curve.c @@ -0,0 +1,80 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(cu != NULL); + + if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, + NULL)) != CRYPT_OK) { + return err; + } + + /* A, B, order, prime, Gx, Gy */ + if ((err = mp_read_radix(key->dp.prime, cu->prime, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.order, cu->order, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.A, cu->A, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.B, cu->B, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.base.x, cu->Gx, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(key->dp.base.y, cu->Gy, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } + /* cofactor & size */ + key->dp.cofactor = cu->cofactor; + key->dp.size = mp_unsigned_bin_size(key->dp.prime); + /* OID string >> unsigned long oid[16] + oidlen */ + key->dp.oidlen = 16; + if ((err = pk_oid_str_to_num(cu->OID, key->dp.oid, &key->dp.oidlen)) != CRYPT_OK) { goto error; } + /* success */ + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +int ecc_set_curve_by_size(int size, ecc_key *key) +{ + const ltc_ecc_curve *cu = NULL; + int err = CRYPT_ERROR; + + /* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */ + if (size <= 14) { + err = ecc_find_curve("SECP112R1", &cu); + } + else if (size <= 16) { + err = ecc_find_curve("SECP128R1", &cu); + } + else if (size <= 20) { + err = ecc_find_curve("SECP160R1", &cu); + } + else if (size <= 24) { + err = ecc_find_curve("SECP192R1", &cu); + } + else if (size <= 28) { + err = ecc_find_curve("SECP224R1", &cu); + } + else if (size <= 32) { + err = ecc_find_curve("SECP256R1", &cu); + } + else if (size <= 48) { + err = ecc_find_curve("SECP384R1", &cu); + } + else if (size <= 66) { + err = ecc_find_curve("SECP521R1", &cu); + } + + if (err == CRYPT_OK && cu != NULL) return ecc_set_curve(cu, key); + + return CRYPT_INVALID_ARG; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c b/deps/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c new file mode 100644 index 0000000..4f43914 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_set_curve_internal.c @@ -0,0 +1,119 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +static int s_ecc_cmp_hex_bn(const char *left_hex, void *right_bn, void *tmp_bn) +{ + if (mp_read_radix(tmp_bn, left_hex, 16) != CRYPT_OK) return 0; + if (mp_cmp(tmp_bn, right_bn) != LTC_MP_EQ) return 0; + return 1; +} + +static void s_ecc_oid_lookup(ecc_key *key) +{ + void *bn; + const ltc_ecc_curve *curve; + + key->dp.oidlen = 0; + if (mp_init(&bn) != CRYPT_OK) return; + for (curve = ltc_ecc_curves; curve->prime != NULL; curve++) { + if (s_ecc_cmp_hex_bn(curve->prime, key->dp.prime, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->order, key->dp.order, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->A, key->dp.A, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->B, key->dp.B, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->Gx, key->dp.base.x, bn) != 1) continue; + if (s_ecc_cmp_hex_bn(curve->Gy, key->dp.base.y, bn) != 1) continue; + if (key->dp.cofactor != curve->cofactor) continue; + break; /* found */ + } + mp_clear(bn); + if (curve->prime && curve->OID) { + key->dp.oidlen = 16; /* size of key->dp.oid */ + pk_oid_str_to_num(curve->OID, key->dp.oid, &key->dp.oidlen); + } +} + +int ecc_copy_curve(const ecc_key *srckey, ecc_key *key) +{ + unsigned long i; + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(srckey != NULL); + + if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, + NULL)) != CRYPT_OK) { + return err; + } + + /* A, B, order, prime, Gx, Gy */ + if ((err = mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_copy_point(&srckey->dp.base, &key->dp.base)) != CRYPT_OK) { goto error; } + /* cofactor & size */ + key->dp.cofactor = srckey->dp.cofactor; + key->dp.size = srckey->dp.size; + /* OID */ + if (srckey->dp.oidlen > 0) { + key->dp.oidlen = srckey->dp.oidlen; + for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i]; + } + else { + s_ecc_oid_lookup(key); /* try to find OID in ltc_ecc_curves */ + } + /* success */ + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +int ecc_set_curve_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(a != NULL); + LTC_ARGCHK(b != NULL); + LTC_ARGCHK(prime != NULL); + LTC_ARGCHK(order != NULL); + LTC_ARGCHK(gx != NULL); + LTC_ARGCHK(gy != NULL); + + if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B, + &key->dp.base.x, &key->dp.base.y, &key->dp.base.z, + &key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, + NULL)) != CRYPT_OK) { + return err; + } + + /* A, B, order, prime, Gx, Gy */ + if ((err = mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; } + if ((err = mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; } + if ((err = mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; } + if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; } + /* cofactor & size */ + key->dp.cofactor = cofactor; + key->dp.size = mp_unsigned_bin_size(prime); + /* try to find OID in ltc_ecc_curves */ + s_ecc_oid_lookup(key); + /* success */ + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_set_key.c b/deps/libtomcrypt/src/pk/ecc/ecc_set_key.c new file mode 100644 index 0000000..3cf5488 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_set_key.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key) +{ + int err; + void *prime, *a, *b; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + prime = key->dp.prime; + a = key->dp.A; + b = key->dp.B; + + if (type == PK_PRIVATE) { + /* load private key */ + if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, inlen)) != CRYPT_OK) { + goto error; + } + if (mp_iszero(key->k) || (mp_cmp(key->k, key->dp.order) != LTC_MP_LT)) { + err = CRYPT_INVALID_PACKET; + goto error; + } + /* compute public key */ + if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; } + } + else if (type == PK_PUBLIC) { + /* load public key */ + if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; } + if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; } + } + else { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* point on the curve + other checks */ + if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { + goto error; + } + + key->type = type; + return CRYPT_OK; + +error: + ecc_free(key); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_shared_secret.c b/deps/libtomcrypt/src/pk/ecc/ecc_shared_secret.c new file mode 100644 index 0000000..21ac913 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_shared_secret.c @@ -0,0 +1,66 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_shared_secret.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Create an ECC shared secret between two keys + @param private_key The private ECC key + @param public_key The public key + @param out [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63) + @param outlen [in/out] The max size and resulting size of the shared secret + @return CRYPT_OK if successful +*/ +int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x; + ecc_point *result; + void *prime, *a; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* type valid? */ + if (private_key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* make new point */ + result = ltc_ecc_new_point(); + if (result == NULL) { + return CRYPT_MEM; + } + + prime = private_key->dp.prime; + a = private_key->dp.A; + + if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; } + + x = (unsigned long)mp_unsigned_bin_size(prime); + if (*outlen < x) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto done; + } + zeromem(out, x); + if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; } + + err = CRYPT_OK; + *outlen = x; +done: + ltc_ecc_del_point(result); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_sign_hash.c b/deps/libtomcrypt/src/pk/ecc/ecc_sign_hash.c new file mode 100644 index 0000000..229ced1 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_sign_hash.c @@ -0,0 +1,181 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** + @file ecc_sign_hash.c + ECC Crypto, Tom St Denis +*/ + +/** + Sign a message digest + @param in The message digest to sign + @param inlen The length of the digest + @param out [out] The destination for the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param sigformat The format of the signature to generate (ecc_signature_type) + @param recid [out] The recovery ID for this signature (optional) + @param key A private ECC key + @return CRYPT_OK if successful +*/ +int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, ecc_signature_type sigformat, + int *recid, const ecc_key *key) +{ + ecc_key pubkey; + void *r, *s, *e, *p, *b; + int v = 0; + int err, max_iterations = LTC_PK_MAX_RETRIES; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* is this a private key? */ + if (key->type != PK_PRIVATE) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* init the bignums */ + if ((err = mp_init_multi(&r, &s, &e, &b, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* get the hash and load it as a bignum into 'e' */ + p = key->dp.order; + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > inlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, inlen)) != CRYPT_OK) { goto errnokey; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)in, pbytes)) != CRYPT_OK) { goto errnokey; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto errnokey; } + } + + /* make up a key and export the public copy */ + do { + if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; } + if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } + + /* find r = x1 mod n */ + if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; } + + if (recid || sigformat==LTC_ECCSIG_ETH27) { + /* find recovery ID (if needed) */ + v = 0; + if (mp_copy(pubkey.pubkey.x, s) != CRYPT_OK) { goto error; } + while (mp_cmp_d(s, 0) == LTC_MP_GT && mp_cmp(s, p) != LTC_MP_LT) { + /* Compute x1 div n... this will almost never be reached for curves with order 1 */ + v += 2; + if ((err = mp_sub(s, p, s)) != CRYPT_OK) { goto error; } + } + if (mp_isodd(pubkey.pubkey.y)) v += 1; + } + + if (mp_iszero(r) == LTC_MP_YES) { + ecc_free(&pubkey); + } else { + if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ + /* find s = (e + xr)/k */ + if ((err = mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */ + if ((err = mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */ + if ((err = mp_mulmod(key->k, r, p, s)) != CRYPT_OK) { goto error; } /* s = xr */ + if ((err = mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK) { goto error; } /* s = xr/kb */ + if ((err = mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK) { goto error; } /* e = e/kb */ + if ((err = mp_add(e, s, s)) != CRYPT_OK) { goto error; } /* s = e/kb + xr/kb */ + if ((err = mp_mulmod(s, b, p, s)) != CRYPT_OK) { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */ + ecc_free(&pubkey); + if (mp_iszero(s) == LTC_MP_NO) { + break; + } + } + } while (--max_iterations > 0); + + if (max_iterations == 0) { + goto errnokey; + } + + if (recid) *recid = v; + + if (sigformat == LTC_ECCSIG_ANSIX962) { + /* store as ASN.1 SEQUENCE { r, s -- integer } */ + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, NULL); + } + else if (sigformat == LTC_ECCSIG_RFC7518) { + /* RFC7518 format - raw (r,s) */ + if (*outlen < 2*pbytes) { err = CRYPT_MEM; goto errnokey; } + zeromem(out, 2*pbytes); + i = mp_unsigned_bin_size(r); + if ((err = mp_to_unsigned_bin(r, out + (pbytes - i))) != CRYPT_OK) { goto errnokey; } + i = mp_unsigned_bin_size(s); + if ((err = mp_to_unsigned_bin(s, out + (2*pbytes - i))) != CRYPT_OK) { goto errnokey; } + *outlen = 2*pbytes; + err = CRYPT_OK; + } + else if (sigformat == LTC_ECCSIG_ETH27) { + /* Ethereum (v,r,s) format */ + if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { + /* Only valid for secp256k1 - OID 1.3.132.0.10 */ + err = CRYPT_ERROR; goto errnokey; + } + if (*outlen < 65) { err = CRYPT_MEM; goto errnokey; } + zeromem(out, 65); + i = mp_unsigned_bin_size(r); + if ((err = mp_to_unsigned_bin(r, out + 32 - i)) != CRYPT_OK) { goto errnokey; } + i = mp_unsigned_bin_size(s); + if ((err = mp_to_unsigned_bin(s, out + 64 - i)) != CRYPT_OK) { goto errnokey; } + out[64] = (unsigned char)(v + 27); /* Recovery ID is 27/28 for Ethereum */ + *outlen = 65; + err = CRYPT_OK; + } +#ifdef LTC_SSH + else if (sigformat == LTC_ECCSIG_RFC5656) { + /* Get identifier string */ + char name[64]; + unsigned long namelen = sizeof(name); + if ((err = ecc_ssh_ecdsa_encode_name(name, &namelen, key)) != CRYPT_OK) { goto errnokey; } + + /* Store as SSH data sequence, per RFC4251 */ + err = ssh_encode_sequence_multi(out, outlen, + LTC_SSHDATA_STRING, name, namelen, + LTC_SSHDATA_MPINT, r, + LTC_SSHDATA_MPINT, s, + LTC_SSHDATA_EOL, NULL); + } +#endif + else { + /* Unknown signature format */ + err = CRYPT_ERROR; + goto error; + } + + goto errnokey; +error: + ecc_free(&pubkey); +errnokey: + mp_clear_multi(r, s, e, b, LTC_NULL); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_sizes.c b/deps/libtomcrypt/src/pk/ecc/ecc_sizes.c new file mode 100644 index 0000000..07379b6 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_sizes.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_sizes.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +void ecc_sizes(int *low, int *high) +{ + int i, size; + void *prime; + + LTC_ARGCHKVD(low != NULL); + LTC_ARGCHKVD(high != NULL); + + *low = INT_MAX; + *high = 0; + + if (mp_init(&prime) == CRYPT_OK) { + for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { + if (mp_read_radix(prime, ltc_ecc_curves[i].prime, 16) == CRYPT_OK) { + size = mp_unsigned_bin_size(prime); + if (size < *low) *low = size; + if (size > *high) *high = size; + } + } + mp_clear(prime); + } +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c b/deps/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c new file mode 100644 index 0000000..4b8d554 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_ssh_ecdsa_encode_name.c @@ -0,0 +1,65 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ecc_ssh_ecdsa_encode_name.c + Curve/OID to SSH+ECDSA name string mapping per RFC5656 + Russ Williams +*/ + +#ifdef LTC_SSH + +/** + Curve/OID to SSH+ECDSA name string mapping + @param buffer [out] The destination for the name + @param buflen [in/out] The max size and resulting size (including terminator) of the name + @param key A public or private ECC key + @return CRYPT_OK if successful +*/ +int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key) +{ + char oidstr[64] = {0}; + unsigned long oidlen = sizeof(oidstr); + int err, size = 0; + + LTC_ARGCHK(buffer != NULL); + LTC_ARGCHK(buflen != NULL); + LTC_ARGCHK(key != NULL); + + /* Get the OID of the curve */ + if ((err = ecc_get_oid_str(oidstr, &oidlen, key)) != CRYPT_OK) goto error; + + /* Check for three named curves: nistp256, nistp384, nistp521 */ + if (XSTRCMP("1.2.840.10045.3.1.7", oidstr) == 0) { + /* nistp256 - secp256r1 - OID 1.2.840.10045.3.1.7 */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp256"); + } + else if (XSTRCMP("1.3.132.0.34", oidstr) == 0) { + /* nistp384 - secp384r1 - OID 1.3.132.0.34 */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp384"); + } + else if (XSTRCMP("1.3.132.0.35", oidstr) == 0) { + /* nistp521 - secp521r1 - OID 1.3.132.0.35 */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-nistp521"); + } else { + /* Otherwise we use the OID... */ + size = snprintf(buffer, *buflen, "ecdsa-sha2-%s", oidstr); + } + + /* snprintf returns a negative value on error + * or the size that would have been written, but limits to buflen-1 chars plus terminator */ + if (size < 0) { + err = CRYPT_ERROR; + } else if ((unsigned)size >= *buflen) { + err = CRYPT_BUFFER_OVERFLOW; + } else { + err = CRYPT_OK; + } + *buflen = size + 1; /* the string length + NUL byte */ + +error: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ecc_verify_hash.c b/deps/libtomcrypt/src/pk/ecc/ecc_verify_hash.c new file mode 100644 index 0000000..4480ff4 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ecc_verify_hash.c @@ -0,0 +1,206 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** + @file ecc_verify_hash.c + ECC Crypto, Tom St Denis +*/ + +/** + Verify an ECC signature in RFC7518 format + @param sig The signature to verify + @param siglen The length of the signature (octets) + @param hash The hash (message digest) that was signed + @param hashlen The length of the hash (octets) + @param sigformat The format of the signature (ecc_signature_type) + @param stat Result of signature, 1==valid, 0==invalid + @param key The corresponding public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + ecc_signature_type sigformat, int *stat, const ecc_key *key) +{ + ecc_point *mG = NULL, *mQ = NULL; + void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3; + void *mu = NULL, *ma = NULL; + void *mp = NULL; + int err; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid signature */ + *stat = 0; + + /* allocate ints */ + if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, LTC_NULL)) != CRYPT_OK) { + return err; + } + + p = key->dp.order; + m = key->dp.prime; + a = key->dp.A; + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { + goto error; + } + + /* allocate points */ + mG = ltc_ecc_new_point(); + mQ = ltc_ecc_new_point(); + if (mQ == NULL || mG == NULL) { + err = CRYPT_MEM; + goto error; + } + + if (sigformat == LTC_ECCSIG_ANSIX962) { + /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ + if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_RFC7518) { + /* RFC7518 format - raw (r,s) */ + i = mp_unsigned_bin_size(key->dp.order); + if (siglen != (2 * i)) { + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, i)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+i, i)) != CRYPT_OK) { goto error; } + } + else if (sigformat == LTC_ECCSIG_ETH27) { + /* Ethereum (v,r,s) format */ + if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { + /* Only valid for secp256k1 - OID 1.3.132.0.10 */ + err = CRYPT_ERROR; goto error; + } + if (siglen != 65) { /* Only secp256k1 curves use this format, so must be 65 bytes long */ + err = CRYPT_INVALID_PACKET; + goto error; + } + if ((err = mp_read_unsigned_bin(r, (unsigned char *)sig, 32)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(s, (unsigned char *)sig+32, 32)) != CRYPT_OK) { goto error; } + } +#ifdef LTC_SSH + else if (sigformat == LTC_ECCSIG_RFC5656) { + char name[64], name2[64]; + unsigned long namelen = sizeof(name); + unsigned long name2len = sizeof(name2); + + /* Decode as SSH data sequence, per RFC4251 */ + if ((err = ssh_decode_sequence_multi(sig, &siglen, + LTC_SSHDATA_STRING, name, &namelen, + LTC_SSHDATA_MPINT, r, + LTC_SSHDATA_MPINT, s, + LTC_SSHDATA_EOL, NULL)) != CRYPT_OK) { goto error; } + + + /* Check curve matches identifier string */ + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { + err = CRYPT_INVALID_ARG; + goto error; + } + } +#endif + else { + /* Unknown signature format */ + err = CRYPT_ERROR; + goto error; + } + + /* check for zero */ + if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT || + mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto error; + } + + /* read hash - truncate if needed */ + pbits = mp_count_bits(p); + pbytes = (pbits+7) >> 3; + if (pbits > hashlen*8) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error; } + } + else if (pbits % 8 == 0) { + if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, pbytes)) != CRYPT_OK) { goto error; } + } + else { + shift_right = 8 - pbits % 8; + for (i=0, ch=0; i> shift_right); + } + if ((err = mp_read_unsigned_bin(e, (unsigned char *)buf, pbytes)) != CRYPT_OK) { goto error; } + } + + /* w = s^-1 mod n */ + if ((err = mp_invmod(s, p, w)) != CRYPT_OK) { goto error; } + + /* u1 = ew */ + if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK) { goto error; } + + /* u2 = rw */ + if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; } + + /* find mG and mQ */ + if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; } + if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; } + + /* find the montgomery mp */ + if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { + if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } + } + + /* compute u1*mG + u2*mQ = mG */ + if (ltc_mp.ecc_mul2add == NULL) { + if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; } + if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; } + + /* add them */ + if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; } + + /* reduce */ + if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; } + } else { + /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */ + if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; } + } + + /* v = X_x1 mod n */ + if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK) { goto error; } + + /* does v == r */ + if (mp_cmp(v, r) == LTC_MP_EQ) { + *stat = 1; + } + + /* clear up and return */ + err = CRYPT_OK; +error: + if (mG != NULL) ltc_ecc_del_point(mG); + if (mQ != NULL) ltc_ecc_del_point(mQ); + if (mu != NULL) mp_clear(mu); + if (ma != NULL) mp_clear(ma); + mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, LTC_NULL); + if (mp != NULL) mp_montgomery_free(mp); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c new file mode 100644 index 0000000..022c6bc --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_export_point.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed) +{ + int err; + unsigned char buf[ECC_BUF_SIZE]; + unsigned long xsize, ysize; + + if (size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW; + if ((xsize = mp_unsigned_bin_size(x)) > size) return CRYPT_BUFFER_OVERFLOW; + if ((ysize = mp_unsigned_bin_size(y)) > size) return CRYPT_BUFFER_OVERFLOW; + + if(compressed) { + if (*outlen < (1 + size)) { + *outlen = 1 + size; + return CRYPT_BUFFER_OVERFLOW; + } + /* store first byte */ + out[0] = mp_isodd(y) ? 0x03 : 0x02; + /* pad and store x */ + zeromem(buf, sizeof(buf)); + if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; + XMEMCPY(out+1, buf, size); + /* adjust outlen */ + *outlen = 1 + size; + } + else { + if (*outlen < (1 + 2*size)) { + *outlen = 1 + 2*size; + return CRYPT_BUFFER_OVERFLOW; + } + /* store byte 0x04 */ + out[0] = 0x04; + /* pad and store x */ + zeromem(buf, sizeof(buf)); + if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err; + XMEMCPY(out+1, buf, size); + /* pad and store y */ + zeromem(buf, sizeof(buf)); + if ((err = mp_to_unsigned_bin(y, buf + (size - ysize))) != CRYPT_OK) return err; + XMEMCPY(out+1+size, buf, size); + /* adjust outlen */ + *outlen = 1 + 2*size; + } + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c new file mode 100644 index 0000000..6250fca --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_import_point.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y) +{ + int err; + unsigned long size; + void *t1, *t2; + + /* init key + temporary numbers */ + if (mp_init_multi(&t1, &t2, LTC_NULL) != CRYPT_OK) { + return CRYPT_MEM; + } + + size = mp_unsigned_bin_size(prime); + + if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) { + /* read uncompressed point */ + /* load x */ + if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; } + /* load y */ + if ((err = mp_read_unsigned_bin(y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { goto cleanup; } + } + else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size && ltc_mp.sqrtmod_prime != NULL) { + /* read compressed point - BEWARE: requires sqrtmod_prime */ + /* load x */ + if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; } + /* compute x^3 */ + if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; } + /* compute x^3 + a*x */ + if ((err = mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; } + /* compute x^3 + a*x + b */ + if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; } + /* compute sqrt(x^3 + a*x + b) */ + if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; } + /* adjust y */ + if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) { + if ((err = mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; } + } + else { + if ((err = mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; } + } + } + else { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + + err = CRYPT_OK; +cleanup: + mp_clear_multi(t1, t2, LTC_NULL); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c new file mode 100644 index 0000000..56a9537 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point.c @@ -0,0 +1,62 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/** Returns whether [x,y] is a point on curve defined by dp + @param dp curve parameters + @param x x point coordinate + @param y y point coordinate + @return CRYPT_OK if valid +*/ + +int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y) +{ + void *prime, *a, *b, *t1, *t2; + int err; + + prime = dp->prime; + b = dp->B; + a = dp->A; + + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) return err; + + /* compute y^2 */ + if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; + + /* compute x^3 */ + if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup; + + /* compute y^2 - x^3 */ + if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup; + + /* compute y^2 - x^3 - a*x */ + if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup; + if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup; + + /* adjust range (0, prime) */ + while (mp_cmp_d(t1, 0) == LTC_MP_LT) { + if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup; + } + while (mp_cmp(t1, prime) != LTC_MP_LT) { + if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup; + } + + /* compare to b */ + if (mp_cmp(t1, b) != LTC_MP_EQ) { + err = CRYPT_INVALID_PACKET; + } else { + err = CRYPT_OK; + } + +cleanup: + mp_clear_multi(t1, t2, LTC_NULL); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c new file mode 100644 index 0000000..2afc4d4 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_is_point_at_infinity.c @@ -0,0 +1,53 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_MECC + +/* http://crypto.stackexchange.com/questions/41468/point-at-infinity-for-jacobian-coordinates + * a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0) + */ + +int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval) +{ + int err; + void *x3, *y2; + + /* trivial case */ + if (!mp_iszero(P->z)) { + *retval = 0; + return CRYPT_OK; + } + + /* point (0,0,0) is not at infinity */ + if (mp_iszero(P->x) && mp_iszero(P->y)) { + *retval = 0; + return CRYPT_OK; + } + + /* initialize */ + if ((err = mp_init_multi(&x3, &y2, LTC_NULL)) != CRYPT_OK) goto done; + + /* compute y^2 */ + if ((err = mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK) goto cleanup; + + /* compute x^3 */ + if ((err = mp_mulmod(P->x, P->x, modulus, x3)) != CRYPT_OK) goto cleanup; + if ((err = mp_mulmod(P->x, x3, modulus, x3)) != CRYPT_OK) goto cleanup; + + /* test y^2 == x^3 */ + err = CRYPT_OK; + if ((mp_cmp(x3, y2) == LTC_MP_EQ) && !mp_iszero(y2)) { + *retval = 1; + } else { + *retval = 0; + } + +cleanup: + mp_clear_multi(x3, y2, LTC_NULL); +done: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_map.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_map.c new file mode 100644 index 0000000..163fb41 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_map.c @@ -0,0 +1,63 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_map.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Map a projective jacbobian point back to affine space + @param P [in/out] The point to map + @param modulus The modulus of the field the ECC curve is in + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success +*/ +int ltc_ecc_map(ecc_point *P, void *modulus, void *mp) +{ + void *t1, *t2; + int err; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(mp != NULL); + + if (mp_iszero(P->z)) { + return ltc_ecc_set_point_xyz(0, 0, 1, P); + } + + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* first map z back to normal */ + if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; } + + /* get 1/z */ + if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; } + + /* get 1/z^2 and 1/z^3 */ + if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; } + + /* multiply against x/y */ + if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = mp_set(P->z, 1)) != CRYPT_OK) { goto done; } + + err = CRYPT_OK; +done: + mp_clear_multi(t1, t2, LTC_NULL); + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c new file mode 100644 index 0000000..a0188e3 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c @@ -0,0 +1,192 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_mul2add.c + ECC Crypto, Shamir's Trick, Tom St Denis +*/ + +#ifdef LTC_MECC + +#ifdef LTC_ECC_SHAMIR + +/** Computes kA*A + kB*B = C using Shamir's Trick + @param A First point to multiply + @param kA What to multiple A by + @param B Second point to multiply + @param kB What to multiple B by + @param C [out] Destination point (can overlap with A or B) + @param ma ECC curve parameter a in montgomery form + @param modulus Modulus for curve + @return CRYPT_OK on success +*/ +int ltc_ecc_mul2add(const ecc_point *A, void *kA, + const ecc_point *B, void *kB, + ecc_point *C, + void *ma, + void *modulus) +{ + ecc_point *precomp[16]; + unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; + unsigned x, y; + unsigned char *tA, *tB; + int err, first; + void *mp, *mu; + + /* argchks */ + LTC_ARGCHK(A != NULL); + LTC_ARGCHK(B != NULL); + LTC_ARGCHK(C != NULL); + LTC_ARGCHK(kA != NULL); + LTC_ARGCHK(kB != NULL); + LTC_ARGCHK(modulus != NULL); + + /* allocate memory */ + tA = XCALLOC(1, ECC_BUF_SIZE); + if (tA == NULL) { + return CRYPT_MEM; + } + tB = XCALLOC(1, ECC_BUF_SIZE); + if (tB == NULL) { + XFREE(tA); + return CRYPT_MEM; + } + + /* get sizes */ + lenA = mp_unsigned_bin_size(kA); + lenB = mp_unsigned_bin_size(kB); + len = MAX(lenA, lenB); + + /* sanity check */ + if ((lenA > ECC_BUF_SIZE) || (lenB > ECC_BUF_SIZE)) { + err = CRYPT_INVALID_ARG; + goto ERR_T; + } + + /* extract and justify kA */ + mp_to_unsigned_bin(kA, (len - lenA) + tA); + + /* extract and justify kB */ + mp_to_unsigned_bin(kB, (len - lenB) + tB); + + /* allocate the table */ + for (x = 0; x < 16; x++) { + precomp[x] = ltc_ecc_new_point(); + if (precomp[x] == NULL) { + for (y = 0; y < x; ++y) { + ltc_ecc_del_point(precomp[y]); + } + err = CRYPT_MEM; + goto ERR_T; + } + } + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { + goto ERR_P; + } + if ((err = mp_init(&mu)) != CRYPT_OK) { + goto ERR_MP; + } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { + goto ERR_MU; + } + + /* copy ones ... */ + if ((err = mp_mulmod(A->x, mu, modulus, precomp[1]->x)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(A->y, mu, modulus, precomp[1]->y)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(A->z, mu, modulus, precomp[1]->z)) != CRYPT_OK) { goto ERR_MU; } + + if ((err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y)) != CRYPT_OK) { goto ERR_MU; } + if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; } + + /* precomp [i,0](A + B) table */ + if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + + /* precomp [0,i](A + B) table */ + if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + + /* precomp [i,j](A + B) table (i != 0, j != 0) */ + for (x = 1; x < 4; x++) { + for (y = 1; y < 4; y++) { + if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + } + } + + nibble = 3; + first = 1; + bitbufA = tA[0]; + bitbufB = tB[0]; + + /* for every byte of the multiplicands */ + for (x = 0;; ) { + /* grab a nibble */ + if (++nibble == 4) { + if (x == len) break; + bitbufA = tA[x]; + bitbufB = tB[x]; + nibble = 0; + ++x; + } + + /* extract two bits from both, shift/update */ + nA = (bitbufA >> 6) & 0x03; + nB = (bitbufB >> 6) & 0x03; + bitbufA = (bitbufA << 2) & 0xFF; + bitbufB = (bitbufB << 2) & 0xFF; + + /* if both zero, if first, continue */ + if ((nA == 0) && (nB == 0) && (first == 1)) { + continue; + } + + /* double twice, only if this isn't the first */ + if (first == 0) { + /* double twice */ + if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + } + + /* if not both zero */ + if ((nA != 0) || (nB != 0)) { + if (first == 1) { + /* if first, copy from table */ + first = 0; + if ((err = ltc_ecc_copy_point(precomp[nA + (nB<<2)], C)) != CRYPT_OK) { goto ERR_MU; } + } else { + /* if not first, add from table */ + if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; } + } + } + } + + /* reduce to affine */ + err = ltc_ecc_map(C, modulus, mp); + + /* clean up */ +ERR_MU: + mp_clear(mu); +ERR_MP: + mp_montgomery_free(mp); +ERR_P: + for (x = 0; x < 16; x++) { + ltc_ecc_del_point(precomp[x]); + } +ERR_T: +#ifdef LTC_CLEAN_STACK + zeromem(tA, ECC_BUF_SIZE); + zeromem(tB, ECC_BUF_SIZE); +#endif + XFREE(tA); + XFREE(tB); + + return err; +} + +#endif +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c new file mode 100644 index 0000000..cabe266 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c @@ -0,0 +1,204 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_mulmod.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC +#ifndef LTC_ECC_TIMING_RESISTANT + +/* size of sliding window, don't change this! */ +#define WINSIZE 4 + +/** + Perform a point multiplication + @param k The scalar to multiply by + @param G The base point + @param R [out] Destination for kG + @param modulus The modulus of the field the ECC curve is in + @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) + @return CRYPT_OK on success +*/ +int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map) +{ + ecc_point *tG, *M[8]; + int i, j, err, inf; + void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; + ltc_mp_digit buf; + int first, bitbuf, bitcpy, bitcnt, mode, digidx; + + LTC_ARGCHK(k != NULL); + LTC_ARGCHK(G != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + + if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* return the point at infinity */ + return ltc_ecc_set_point_xyz(1, 1, 0, R); + } + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } + if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; } + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } + if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { + if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } + } + + /* alloc ram for window temps */ + for (i = 0; i < 8; i++) { + M[i] = ltc_ecc_new_point(); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + ltc_ecc_del_point(M[j]); + } + err = CRYPT_MEM; + goto error; + } + } + + /* make a copy of G incase R==G */ + tG = ltc_ecc_new_point(); + if (tG == NULL) { err = CRYPT_MEM; goto done; } + + /* tG = G and convert to montgomery */ + if (mp_cmp_d(mu, 1) == LTC_MP_EQ) { + if ((err = ltc_ecc_copy_point(G, tG)) != CRYPT_OK) { goto done; } + } else { + if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } + } + mp_clear(mu); + mu = NULL; + + /* calc the M tab, which holds kG for k==8..15 */ + /* M[0] == 8G */ + if ((err = ltc_mp.ecc_ptdbl(tG, M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; } + + /* now find (8+k)G for k=1..7 */ + for (j = 9; j < 16; j++) { + if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = mp_get_digit_count(k) - 1; + bitcpy = bitbuf = 0; + first = 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = mp_get_digit(k, digidx); + bitcnt = (int) ltc_mp.bits_per_digit; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1; + buf <<= 1; + + /* skip leading zero bits */ + if (mode == 0 && i == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we double */ + if (mode == 1 && i == 0) { + if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + /* else we add it to the window */ + bitbuf |= (i << (WINSIZE - ++bitcpy)); + mode = 2; + + if (bitcpy == WINSIZE) { + /* if this is the first window we do a simple copy */ + if (first == 1) { + /* R = kG [k = first window] */ + if ((err = ltc_ecc_copy_point(M[bitbuf-8], R)) != CRYPT_OK) { goto done; } + first = 0; + } else { + /* normal window */ + /* ok window is filled so double as required and add */ + /* double first */ + for (j = 0; j < WINSIZE; j++) { + if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + /* empty window and reset */ + bitcpy = bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then double/add */ + if (mode == 2 && bitcpy > 0) { + /* double then add */ + for (j = 0; j < bitcpy; j++) { + /* only double if we have had at least one add first */ + if (first == 0) { + if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + + bitbuf <<= 1; + if ((bitbuf & (1 << WINSIZE)) != 0) { + if (first == 1){ + /* first add, so copy */ + if ((err = ltc_ecc_copy_point(tG, R)) != CRYPT_OK) { goto done; } + first = 0; + } else { + /* then add */ + if ((err = ltc_mp.ecc_ptadd(R, tG, R, ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + } + } + } + + /* map R back from projective space */ + if (map) { + err = ltc_ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } +done: + ltc_ecc_del_point(tG); + for (i = 0; i < 8; i++) { + ltc_ecc_del_point(M[i]); + } +error: + if (ma != NULL) mp_clear(ma); + if (a_plus3 != NULL) mp_clear(a_plus3); + if (mu != NULL) mp_clear(mu); + if (mp != NULL) mp_montgomery_free(mp); + return err; +} + +#endif + +#undef WINSIZE + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c new file mode 100644 index 0000000..96f50f9 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod_timing.c @@ -0,0 +1,151 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_mulmod_timing.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +#ifdef LTC_ECC_TIMING_RESISTANT + +/** + Perform a point multiplication (timing resistant) + @param k The scalar to multiply by + @param G The base point + @param R [out] Destination for kG + @param a ECC curve parameter a + @param modulus The modulus of the field the ECC curve is in + @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) + @return CRYPT_OK on success +*/ +int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map) +{ + ecc_point *tG, *M[3]; + int i, j, err, inf; + void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL; + ltc_mp_digit buf; + int bitcnt, mode, digidx; + + LTC_ARGCHK(k != NULL); + LTC_ARGCHK(G != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + + if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* return the point at infinity */ + return ltc_ecc_set_point_xyz(1, 1, 0, R); + } + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; } + if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; } + if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; } + + /* for curves with a == -3 keep ma == NULL */ + if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; } + if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; } + if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) { + if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; } + } + + /* alloc ram for window temps */ + for (i = 0; i < 3; i++) { + M[i] = ltc_ecc_new_point(); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + ltc_ecc_del_point(M[j]); + } + mp_clear(mu); + mp_montgomery_free(mp); + return CRYPT_MEM; + } + } + + /* make a copy of G incase R==G */ + tG = ltc_ecc_new_point(); + if (tG == NULL) { err = CRYPT_MEM; goto done; } + + /* tG = G and convert to montgomery */ + if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; } + if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK) { goto done; } + mp_clear(mu); + mu = NULL; + + /* calc the M tab */ + /* M[0] == G */ + if ((err = ltc_ecc_copy_point(tG, M[0])) != CRYPT_OK) { goto done; } + /* M[1] == 2G */ + if ((err = ltc_mp.ecc_ptdbl(tG, M[1], ma, modulus, mp)) != CRYPT_OK) { goto done; } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = mp_get_digit_count(k) - 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = mp_get_digit(k, digidx); + bitcnt = (int) MP_DIGIT_BIT; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (int)((buf >> (MP_DIGIT_BIT - 1)) & 1); + buf <<= 1; + + if (mode == 0 && i == 0) { + /* dummy operations */ + if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + if (mode == 0 && i == 1) { + mode = 1; + /* dummy operations */ + if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; } + continue; + } + + if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], ma, modulus, mp)) != CRYPT_OK) { goto done; } + if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], ma, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* copy result out */ + if ((err = ltc_ecc_copy_point(M[0], R)) != CRYPT_OK) { goto done; } + + /* map R back from projective space */ + if (map) { + err = ltc_ecc_map(R, modulus, mp); + } else { + err = CRYPT_OK; + } +done: + ltc_ecc_del_point(tG); + for (i = 0; i < 3; i++) { + ltc_ecc_del_point(M[i]); + } +error: + if (ma != NULL) mp_clear(ma); + if (a_plus3 != NULL) mp_clear(a_plus3); + if (mu != NULL) mp_clear(mu); + if (mp != NULL) mp_montgomery_free(mp); + return err; +} + +#endif +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_points.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_points.c new file mode 100644 index 0000000..b762db5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_points.c @@ -0,0 +1,61 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_points.c + ECC Crypto, Tom St Denis +*/ + +#ifdef LTC_MECC + +/** + Allocate a new ECC point + @return A newly allocated point or NULL on error +*/ +ecc_point *ltc_ecc_new_point(void) +{ + ecc_point *p; + p = XCALLOC(1, sizeof(*p)); + if (p == NULL) { + return NULL; + } + if (mp_init_multi(&p->x, &p->y, &p->z, LTC_NULL) != CRYPT_OK) { + XFREE(p); + return NULL; + } + return p; +} + +/** Free an ECC point from memory + @param p The point to free +*/ +void ltc_ecc_del_point(ecc_point *p) +{ + /* prevents free'ing null arguments */ + if (p != NULL) { + mp_clear_multi(p->x, p->y, p->z, LTC_NULL); /* note: p->z may be NULL but that's ok with this function anyways */ + XFREE(p); + } +} + +int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p) +{ + int err; + if ((err = ltc_mp.set_int(p->x, x)) != CRYPT_OK) return err; + if ((err = ltc_mp.set_int(p->y, y)) != CRYPT_OK) return err; + if ((err = ltc_mp.set_int(p->z, z)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst) +{ + int err; + if ((err = ltc_mp.copy(src->x, dst->x)) != CRYPT_OK) return err; + if ((err = ltc_mp.copy(src->y, dst->y)) != CRYPT_OK) return err; + if ((err = ltc_mp.copy(src->z, dst->z)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c new file mode 100644 index 0000000..448c2bb --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c @@ -0,0 +1,198 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ltc_ecc_projective_add_point.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) + +/** + Add two ECC points + @param P The point to add + @param Q The point to add + @param R [out] The destination of the double + @param ma ECC curve parameter a in montgomery form + @param modulus The modulus of the field the ECC curve is in + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success +*/ +int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp) +{ + void *t1, *t2, *x, *y, *z; + int err, inf; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(Q != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(mp != NULL); + + if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, LTC_NULL)) != CRYPT_OK) { + return err; + } + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* P is point at infinity >> Result = Q */ + err = ltc_ecc_copy_point(Q, R); + goto done; + } + + if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* Q is point at infinity >> Result = P */ + err = ltc_ecc_copy_point(P, R); + goto done; + } + + if ((mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (mp_cmp(P->z, Q->z) == LTC_MP_EQ)) { + if (mp_cmp(P->y, Q->y) == LTC_MP_EQ) { + /* here P = Q >> Result = 2 * P (use doubling) */ + mp_clear_multi(t1, t2, x, y, z, LTC_NULL); + return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp); + } + if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(P->y, t1) == LTC_MP_EQ) { + /* here Q = -P >>> Result = the point at infinity */ + err = ltc_ecc_set_point_xyz(1, 1, 0, R); + goto done; + } + } + + if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(P->y, y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(P->z, z)) != CRYPT_OK) { goto done; } + + /* if Z is one then these are no-operations */ + if (Q->z != NULL) { + /* T1 = Z' * Z' */ + if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X * T1 */ + if ((err = mp_mul(t1, x, x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = Z' * T1 */ + if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* Y = Y * T1 */ + if ((err = mp_mul(t1, y, y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* T1 = Z*Z */ + if ((err = mp_sqr(z, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = X' * T1 */ + if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = Z * T1 */ + if ((err = mp_mul(z, t1, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = Y' * T1 */ + if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + + /* Y = Y - T1 */ + if ((err = mp_sub(y, t1, y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(y, 0) == LTC_MP_LT) { + if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } + } + /* T1 = 2T1 */ + if ((err = mp_add(t1, t1, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T1 = Y + T1 */ + if ((err = mp_add(t1, y, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* X = X - T2 */ + if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(x, 0) == LTC_MP_LT) { + if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } + } + /* T2 = 2T2 */ + if ((err = mp_add(t2, t2, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp(t2, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T2 = X + T2 */ + if ((err = mp_add(t2, x, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp(t2, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + + /* if Z' != 1 */ + if (Q->z != NULL) { + /* Z = Z * Z' */ + if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } + } + + /* Z = Z * X */ + if ((err = mp_mul(z, x, z)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK) { goto done; } + + /* T1 = T1 * X */ + if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X * X */ + if ((err = mp_sqr(x, x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = T2 * x */ + if ((err = mp_mul(t2, x, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = T1 * X */ + if ((err = mp_mul(t1, x, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + + /* X = Y*Y */ + if ((err = mp_sqr(y, x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X - T2 */ + if ((err = mp_sub(x, t2, x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(x, 0) == LTC_MP_LT) { + if ((err = mp_add(x, modulus, x)) != CRYPT_OK) { goto done; } + } + + /* T2 = T2 - X */ + if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(t2, 0) == LTC_MP_LT) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T2 = T2 - X */ + if ((err = mp_sub(t2, x, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(t2, 0) == LTC_MP_LT) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T2 = T2 * Y */ + if ((err = mp_mul(t2, y, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* Y = T2 - T1 */ + if ((err = mp_sub(t2, t1, y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(y, 0) == LTC_MP_LT) { + if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } + } + /* Y = Y/2 */ + if (mp_isodd(y)) { + if ((err = mp_add(y, modulus, y)) != CRYPT_OK) { goto done; } + } + if ((err = mp_div_2(y, y)) != CRYPT_OK) { goto done; } + + if ((err = mp_copy(x, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_copy(z, R->z)) != CRYPT_OK) { goto done; } + + err = CRYPT_OK; +done: + mp_clear_multi(t1, t2, x, y, z, LTC_NULL); + return err; +} + +#endif + diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c new file mode 100644 index 0000000..c99a267 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c @@ -0,0 +1,182 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/* ### Point doubling in Jacobian coordinate system ### + * + * let us have a curve: y^2 = x^3 + a*x + b + * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 + * + * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: + * Xr = M^2 - 2*S + * Yr = M * (S - Xr) - 8*T + * Zr = 2 * Yp * Zp + * + * M = 3 * Xp^2 + a*Zp^4 + * T = Yp^4 + * S = 4 * Xp * Yp^2 + * + * SPECIAL CASE: when a == -3 we can compute M as + * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) + */ + +/** + @file ltc_ecc_projective_dbl_point.c + ECC Crypto, Tom St Denis +*/ + +#if defined(LTC_MECC) && (!defined(LTC_MECC_ACCEL) || defined(LTM_DESC)) + +/** + Double an ECC point + @param P The point to double + @param R [out] The destination of the double + @param ma ECC curve parameter a in montgomery form + @param modulus The modulus of the field the ECC curve is in + @param mp The "b" value from montgomery_setup() + @return CRYPT_OK on success +*/ +int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp) +{ + void *t1, *t2; + int err, inf; + + LTC_ARGCHK(P != NULL); + LTC_ARGCHK(R != NULL); + LTC_ARGCHK(modulus != NULL); + LTC_ARGCHK(mp != NULL); + + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { + return err; + } + + if (P != R) { + if ((err = ltc_ecc_copy_point(P, R)) != CRYPT_OK) { goto done; } + } + + if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err; + if (inf) { + /* if P is point at infinity >> Result = point at infinity */ + err = ltc_ecc_set_point_xyz(1, 1, 0, R); + goto done; + } + + /* t1 = Z * Z */ + if ((err = mp_sqr(R->z, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* Z = Y * Z */ + if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK) { goto done; } + /* Z = 2Z */ + if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK) { goto done; } + if (mp_cmp(R->z, modulus) != LTC_MP_LT) { + if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; } + } + + if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */ + /* T2 = X - T1 */ + if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(t2, 0) == LTC_MP_LT) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + /* T1 = X + T1 */ + if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T2 = T1 * T2 */ + if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = 2T2 */ + if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T1 = T1 + T2 */ + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + } + else { + /* T2 = T1 * T1 */ + if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = T2 * a */ + if ((err = mp_mul(t2, ma, t1)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = X * X */ + if ((err = mp_sqr(R->x, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T1 = T2 + T1 */ + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T1 = T2 + T1 */ + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + /* T1 = T2 + T1 */ + if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; } + if (mp_cmp(t1, modulus) != LTC_MP_LT) { + if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; } + } + } + + /* Y = 2Y */ + if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK) { goto done; } + if (mp_cmp(R->y, modulus) != LTC_MP_LT) { + if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } + } + /* Y = Y * Y */ + if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = Y * Y */ + if ((err = mp_sqr(R->y, t2)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; } + /* T2 = T2/2 */ + if (mp_isodd(t2)) { + if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; } + } + if ((err = mp_div_2(t2, t2)) != CRYPT_OK) { goto done; } + /* Y = Y * X */ + if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } + + /* X = T1 * T1 */ + if ((err = mp_sqr(t1, R->x)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK) { goto done; } + /* X = X - Y */ + if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->x, 0) == LTC_MP_LT) { + if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } + } + /* X = X - Y */ + if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->x, 0) == LTC_MP_LT) { + if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK) { goto done; } + } + + /* Y = Y - X */ + if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { + if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } + } + /* Y = Y * T1 */ + if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK) { goto done; } + if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK) { goto done; } + /* Y = Y - T2 */ + if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK) { goto done; } + if (mp_cmp_d(R->y, 0) == LTC_MP_LT) { + if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK) { goto done; } + } + + err = CRYPT_OK; +done: + mp_clear_multi(t2, t1, LTC_NULL); + return err; +} +#endif diff --git a/deps/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c new file mode 100644 index 0000000..26c8383 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ecc/ltc_ecc_verify_key.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/* origin of this code - OLPC */ + +#ifdef LTC_MECC + +/** + Verify a key according to ANSI spec + @param key The key to validate + @return CRYPT_OK if successful +*/ + +int ltc_ecc_verify_key(const ecc_key *key) +{ + int err, inf; + ecc_point *point; + void *prime = key->dp.prime; + void *order = key->dp.order; + void *a = key->dp.A; + + /* Test 1: Are the x and y points of the public key in the field? */ + if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) { + if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) || + (ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) || + (ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) || + (ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) || + (mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y)) + ) + { + err = CRYPT_INVALID_PACKET; + goto done2; + } + } + + /* Test 2: is the public key on the curve? */ + if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; } + + /* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */ + point = ltc_ecc_new_point(); + if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; } + + err = ltc_ecc_is_point_at_infinity(point, prime, &inf); + if (err != CRYPT_OK || inf) { + err = CRYPT_ERROR; + } + else { + err = CRYPT_OK; + } + +done1: + ltc_ecc_del_point(point); +done2: + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_export.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_export.c new file mode 100644 index 0000000..2b710e5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_export.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_export.c + Export an Ed25519 key to a binary packet, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Export an Ed25519 key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the Ed25519 key + @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int ed25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key) +{ + LTC_ARGCHK(key != NULL); + + if (key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; + + return ec25519_export(out, outlen, which, key); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_import.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_import.c new file mode 100644 index 0000000..f197d59 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_import.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import.c + Import a Ed25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import an Ed25519 public key + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + unsigned long key_len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + key_len = sizeof(key->pub); + if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { + key->type = PK_PUBLIC; + key->algo = LTC_OID_ED25519; + } + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c new file mode 100644 index 0000000..71f12de --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_import_pkcs8.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import_pkcs8.c + Import an Ed25519 key in PKCS#8 format, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import an Ed25519 private key in PKCS#8 format + @param in The DER-encoded PKCS#8-formatted private key + @param inlen The length of the input data + @param passwd The password to decrypt the private key + @param passwdlen Password's length (octets) + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key) +{ + return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_ED25519, tweetnacl_crypto_sk_to_pk, key); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c new file mode 100644 index 0000000..19955d1 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_import_raw.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import_raw.c + Set the parameters of an Ed25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Set the parameters of an Ed25519 key + + @param in The key + @param inlen The length of the key + @param which Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] Destination of the key + @return CRYPT_OK if successful +*/ +int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen == 32uL); + LTC_ARGCHK(key != NULL); + + if (which == PK_PRIVATE) { + XMEMCPY(key->priv, in, sizeof(key->priv)); + tweetnacl_crypto_sk_to_pk(key->pub, key->priv); + } else if (which == PK_PUBLIC) { + XMEMCPY(key->pub, in, sizeof(key->pub)); + } else { + return CRYPT_INVALID_ARG; + } + key->algo = LTC_OID_ED25519; + key->type = which; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c new file mode 100644 index 0000000..44978ac --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_import_x509.c @@ -0,0 +1,45 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_import_x509.c + Import an Ed25519 key from a X.509 certificate, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_ed25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; + XMEMCPY(key->pub, in, sizeof(key->pub)); + return CRYPT_OK; +} + +/** + Import an Ed25519 public key from a X.509 certificate + @param in The DER encoded X.509 certificate + @param inlen The length of the certificate + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_ED25519, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)s_ed25519_decode, key)) != CRYPT_OK) { + return err; + } + key->type = PK_PUBLIC; + key->algo = LTC_OID_ED25519; + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_make_key.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_make_key.c new file mode 100644 index 0000000..7cec195 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_make_key.c @@ -0,0 +1,36 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_make_key.c + Create an Ed25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Create an Ed25519 key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful +*/ +int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = tweetnacl_crypto_sign_keypair(prng, wprng, key->pub, key->priv)) != CRYPT_OK) { + return err; + } + + key->type = PK_PRIVATE; + key->algo = LTC_OID_ED25519; + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_sign.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_sign.c new file mode 100644 index 0000000..d5bf364 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_sign.c @@ -0,0 +1,126 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_shared_secret.c + Create an Ed25519 signature, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + unsigned char *s; + unsigned long long smlen; + int err; + + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(siglen != NULL); + LTC_ARGCHK(private_key != NULL); + + if (private_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; + if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + if (*siglen < 64uL) { + *siglen = 64uL; + return CRYPT_BUFFER_OVERFLOW; + } + + smlen = msglen + 64; + s = XMALLOC(smlen); + if (s == NULL) return CRYPT_MEM; + + err = tweetnacl_crypto_sign(s, &smlen, + msg, msglen, + private_key->priv, private_key->pub, + ctx, ctxlen); + + XMEMCPY(sig, s, 64uL); + *siglen = 64uL; + +#ifdef LTC_CLEAN_STACK + zeromem(s, smlen); +#endif + XFREE(s); + + return err; +} + +/** + Create an Ed25519ctx signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param ctx [in] The context is a constant null terminated string + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + int err; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + LTC_ARGCHK(ctx != NULL); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK) + return err; + + return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key); +} + +/** + Create an Ed25519ph signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param ctx [in] The context is a constant null terminated string + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + int err; + unsigned char msg_hash[64]; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) + return err; + + if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) + return err; + + return s_ed25519_sign(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, private_key); +} + +/** + Create an Ed25519 signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const curve25519_key *private_key) +{ + return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/ed25519/ed25519_verify.c b/deps/libtomcrypt/src/pk/ed25519/ed25519_verify.c new file mode 100644 index 0000000..e7dcc30 --- /dev/null +++ b/deps/libtomcrypt/src/pk/ed25519/ed25519_verify.c @@ -0,0 +1,134 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ed25519_verify.c + Verify an Ed25519 signature, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + unsigned char* m; + unsigned long long mlen; + int err; + + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(public_key != NULL); + + *stat = 0; + + if (siglen != 64uL) return CRYPT_INVALID_ARG; + if (public_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; + + mlen = msglen + siglen; + if ((mlen < msglen) || (mlen < siglen)) return CRYPT_OVERFLOW; + + m = XMALLOC(mlen); + if (m == NULL) return CRYPT_MEM; + + XMEMCPY(m, sig, siglen); + XMEMCPY(m + siglen, msg, msglen); + + err = tweetnacl_crypto_sign_open(stat, + m, &mlen, + m, mlen, + ctx, ctxlen, + public_key->pub); + +#ifdef LTC_CLEAN_STACK + zeromem(m, msglen + siglen); +#endif + XFREE(m); + + return err; +} + +/** + Verify an Ed25519ctx signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param ctx [in] The context + @param ctxlen [in] The size of the context + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + LTC_ARGCHK(ctx != NULL); + + if (ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen) != CRYPT_OK) + return CRYPT_INVALID_ARG; + + return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); +} + +/** + Verify an Ed25519ph signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param ctx [in] The context + @param ctxlen [in] The size of the context + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + int err; + unsigned char msg_hash[64]; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) + return err; + + if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) + return err; + + return s_ed25519_verify(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); +} + +/** + Verify an Ed25519 signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int *stat, + const curve25519_key *public_key) +{ + return s_ed25519_verify(msg, msglen, sig, siglen, NULL, 0, stat, public_key); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c new file mode 100644 index 0000000..a62dd86 --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_i2osp.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_i2osp.c + Integer to Octet I2OSP, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/* always stores the same # of bytes, pads with leading zero bytes + as required + */ + +/** + PKCS #1 Integer to binary + @param n The integer to store + @param modulus_len The length of the RSA modulus + @param out [out] The destination for the integer + @return CRYPT_OK if successful +*/ +int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out) +{ + unsigned long size; + + size = mp_unsigned_bin_size(n); + + if (size > modulus_len) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* store it */ + zeromem(out, modulus_len); + return mp_to_unsigned_bin(n, out+(modulus_len-size)); +} + +#endif /* LTC_PKCS_1 */ + diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c new file mode 100644 index 0000000..7a68e72 --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_mgf1.c + The Mask Generation Function (MGF1) for PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + Perform PKCS #1 MGF1 (internal) + @param hash_idx The index of the hash desired + @param seed The seed for MGF1 + @param seedlen The length of the seed + @param mask [out] The destination + @param masklen The length of the mask desired + @return CRYPT_OK if successful +*/ +int pkcs_1_mgf1(int hash_idx, + const unsigned char *seed, unsigned long seedlen, + unsigned char *mask, unsigned long masklen) +{ + unsigned long hLen, x; + ulong32 counter; + int err; + hash_state *md; + unsigned char *buf; + + LTC_ARGCHK(seed != NULL); + LTC_ARGCHK(mask != NULL); + + /* ensure valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* get hash output size */ + hLen = hash_descriptor[hash_idx].hashsize; + + /* allocate memory */ + md = XMALLOC(sizeof(hash_state)); + buf = XMALLOC(hLen); + if (md == NULL || buf == NULL) { + if (md != NULL) { + XFREE(md); + } + if (buf != NULL) { + XFREE(buf); + } + return CRYPT_MEM; + } + + /* start counter */ + counter = 0; + + while (masklen > 0) { + /* handle counter */ + STORE32H(counter, buf); + ++counter; + + /* get hash of seed || counter */ + if ((err = hash_descriptor[hash_idx].init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(md, seed, seedlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(md, buf, 4)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(md, buf)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* store it */ + for (x = 0; x < hLen && masklen > 0; x++, masklen--) { + *mask++ = buf[x]; + } + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(buf, hLen); + zeromem(md, sizeof(hash_state)); +#endif + + XFREE(buf); + XFREE(md); + + return err; +} + +#endif /* LTC_PKCS_1 */ diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c new file mode 100644 index 0000000..a5d5a95 --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c @@ -0,0 +1,175 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_oaep_decode.c + OAEP Padding for PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + PKCS #1 v2.00 OAEP decode + @param msg The encoded data to decode + @param msglen The length of the encoded data (octets) + @param lparam The session or system data (can be NULL) + @param lparamlen The length of the lparam + @param modulus_bitlen The bit length of the RSA modulus + @param hash_idx The index of the hash desired + @param out [out] Destination of decoding + @param outlen [in/out] The max size and resulting size of the decoding + @param res [out] Result of decoding, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen, + int *res) +{ + unsigned char *DB, *seed, *mask; + unsigned long hLen, x, y, modulus_len; + int err, ret; + + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(res != NULL); + + /* default to invalid packet */ + *res = 0; + + /* test valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test hash/message size */ + if ((2*hLen >= (modulus_len - 2)) || (msglen != modulus_len)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + seed = XMALLOC(hLen); + if (DB == NULL || mask == NULL || seed == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (seed != NULL) { + XFREE(seed); + } + return CRYPT_MEM; + } + + /* ok so it's now in the form + + 0x00 || maskedseed || maskedDB + + 1 || hLen || modulus_len - hLen - 1 + + */ + + ret = CRYPT_OK; + + /* must have leading 0x00 byte */ + if (msg[0] != 0x00) { + ret = CRYPT_INVALID_PACKET; + } + + /* now read the masked seed */ + x = 1; + XMEMCPY(seed, msg + x, hLen); + x += hLen; + + /* now read the masked DB */ + XMEMCPY(DB, msg + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + /* compute MGF1 of maskedDB (hLen) */ + if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* XOR against seed */ + for (y = 0; y < hLen; y++) { + seed[y] ^= mask[y]; + } + + /* compute MGF1 of seed (k - hlen - 1) */ + if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* now DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ + + /* compute lhash and store it in seed [reuse temps!] */ + x = modulus_len; + if (lparam != NULL) { + if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + /* can't pass hash_memory a NULL so use DB with zero length */ + if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* compare the lhash'es */ + if (XMEM_NEQ(seed, DB, hLen) != 0) { + ret = CRYPT_INVALID_PACKET; + } + + /* now zeroes before a 0x01 */ + for (x = hLen; x < (modulus_len - hLen - 1) && DB[x] == 0x00; x++) { + /* step... */ + } + + /* error if wasn't 0x01 */ + if (x == (modulus_len - hLen - 1) || DB[x] != 0x01) { + ret = CRYPT_INVALID_PACKET; + } + + /* rest is the message (and skip 0x01) */ + if ((modulus_len - hLen - 1 - ++x) > *outlen) { + ret = CRYPT_INVALID_PACKET; + } + + if (ret == CRYPT_OK) { + /* copy message */ + *outlen = modulus_len - hLen - 1 - x; + XMEMCPY(out, DB + x, modulus_len - hLen - 1 - x); + + /* valid packet */ + *res = 1; + } + err = ret; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(seed, hLen); + zeromem(mask, modulus_len); +#endif + + XFREE(seed); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c new file mode 100644 index 0000000..171df05 --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c @@ -0,0 +1,163 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_oaep_encode.c + OAEP Padding for PKCS #1, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + PKCS #1 v2.00 OAEP encode + @param msg The data to encode + @param msglen The length of the data to encode (octets) + @param lparam A session or system parameter (can be NULL) + @param lparamlen The length of the lparam data + @param modulus_bitlen The bit length of the RSA modulus + @param prng An active PRNG state + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param out [out] The destination for the encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + unsigned char *DB, *seed, *mask; + unsigned long hLen, x, y, modulus_len; + int err; + + LTC_ARGCHK((msglen == 0) || (msg != NULL)); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* test valid hash */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + /* valid prng */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + if ((2*hLen >= (modulus_len - 2)) || (msglen > (modulus_len - 2*hLen - 2))) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + seed = XMALLOC(hLen); + if (DB == NULL || mask == NULL || seed == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (seed != NULL) { + XFREE(seed); + } + return CRYPT_MEM; + } + + /* get lhash */ + /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ + x = modulus_len; + if (lparam != NULL) { + if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + /* can't pass hash_memory a NULL so use DB with zero length */ + if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) { + goto LBL_ERR; + } + } + + /* append PS then 0x01 (to lhash) */ + x = hLen; + y = modulus_len - msglen - 2*hLen - 2; + XMEMSET(DB+x, 0, y); + x += y; + + /* 0x01 byte */ + DB[x++] = 0x01; + + if (msglen != 0) { + /* message (length = msglen) */ + XMEMCPY(DB+x, msg, msglen); + x += msglen; + } + + /* now choose a random seed */ + if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { + err = CRYPT_ERROR_READPRNG; + goto LBL_ERR; + } + + /* compute MGF1 of seed (k - hlen - 1) */ + if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* compute MGF1 of maskedDB (hLen) */ + if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* XOR against seed */ + for (y = 0; y < hLen; y++) { + seed[y] ^= mask[y]; + } + + /* create string of length modulus_len */ + if (*outlen < modulus_len) { + *outlen = modulus_len; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* start output which is 0x00 || maskedSeed || maskedDB */ + x = 0; + out[x++] = 0x00; + XMEMCPY(out+x, seed, hLen); + x += hLen; + XMEMCPY(out+x, DB, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + *outlen = x; + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(seed, hLen); + zeromem(mask, modulus_len); +#endif + + XFREE(seed); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ + diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c new file mode 100644 index 0000000..438030e --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_os2ip.c @@ -0,0 +1,24 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_os2ip.c + Octet to Integer OS2IP, Tom St Denis +*/ +#ifdef LTC_PKCS_1 + +/** + Read a binary string into an mp_int + @param n [out] The mp_int destination + @param in The binary string to read + @param inlen The length of the binary string + @return CRYPT_OK if successful +*/ +int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen) +{ + return mp_read_unsigned_bin(n, in, inlen); +} + +#endif /* LTC_PKCS_1 */ + diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c new file mode 100644 index 0000000..fad401d --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -0,0 +1,166 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_pss_decode.c + PKCS #1 PSS Signature Padding, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + PKCS #1 v2.00 PSS decode + @param msghash The hash to verify + @param msghashlen The length of the hash (octets) + @param sig The signature data (encoded data) + @param siglen The length of the signature data (octets) + @param saltlen The length of the salt used (octets) + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param res [out] The result of the comparison, 1==valid, 0==invalid + @return CRYPT_OK if successful (even if the comparison failed) +*/ +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res) +{ + unsigned char *DB, *mask, *salt, *hash; + unsigned long x, y, hLen, modulus_len; + int err; + hash_state md; + + LTC_ARGCHK(msghash != NULL); + LTC_ARGCHK(res != NULL); + + /* default to invalid */ + *res = 0; + + /* ensure hash is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_bitlen--; + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > modulus_len) || + (modulus_len < hLen + saltlen + 2)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt/hash of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + salt = XMALLOC(modulus_len); + hash = XMALLOC(modulus_len); + if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (salt != NULL) { + XFREE(salt); + } + if (hash != NULL) { + XFREE(hash); + } + return CRYPT_MEM; + } + + /* ensure the 0xBC byte */ + if (sig[siglen-1] != 0xBC) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* copy out the DB */ + x = 0; + XMEMCPY(DB, sig + x, modulus_len - hLen - 1); + x += modulus_len - hLen - 1; + + /* copy out the hash */ + XMEMCPY(hash, sig + x, hLen); + /* x += hLen; */ + + /* check the MSB */ + if ((sig[0] & ~(0xFF >> ((modulus_len<<3) - (modulus_bitlen)))) != 0) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* now clear the first byte [make sure smaller than modulus] */ + DB[0] &= 0xFF >> ((modulus_len<<3) - (modulus_bitlen)); + + /* DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ + + /* check for zeroes and 0x01 */ + for (x = 0; x < modulus_len - saltlen - hLen - 2; x++) { + if (DB[x] != 0x00) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + } + + /* check for the 0x01 */ + if (DB[x++] != 0x01) { + err = CRYPT_INVALID_PACKET; + goto LBL_ERR; + } + + /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { + goto LBL_ERR; + } + zeromem(mask, 8); + if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* mask == hash means valid signature */ + if (XMEM_NEQ(mask, hash, hLen) == 0) { + *res = 1; + } + + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(mask, modulus_len); + zeromem(salt, modulus_len); + zeromem(hash, modulus_len); +#endif + + XFREE(hash); + XFREE(salt); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c new file mode 100644 index 0000000..2a4e372 --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -0,0 +1,164 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file pkcs_1_pss_encode.c + PKCS #1 PSS Signature Padding, Tom St Denis +*/ + +#ifdef LTC_PKCS_1 + +/** + PKCS #1 v2.00 Signature Encoding + @param msghash The hash to encode + @param msghashlen The length of the hash (octets) + @param saltlen The length of the salt desired (octets) + @param prng An active PRNG context + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param out [out] The destination of the encoding + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned char *DB, *mask, *salt, *hash; + unsigned long x, y, hLen, modulus_len; + int err; + hash_state md; + + LTC_ARGCHK(msghash != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* ensure hash and PRNG are valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + hLen = hash_descriptor[hash_idx].hashsize; + modulus_bitlen--; + modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); + + /* check sizes */ + if ((saltlen > modulus_len) || (modulus_len < hLen + saltlen + 2)) { + return CRYPT_PK_INVALID_SIZE; + } + + /* allocate ram for DB/mask/salt/hash of size modulus_len */ + DB = XMALLOC(modulus_len); + mask = XMALLOC(modulus_len); + salt = XMALLOC(modulus_len); + hash = XMALLOC(modulus_len); + if (DB == NULL || mask == NULL || salt == NULL || hash == NULL) { + if (DB != NULL) { + XFREE(DB); + } + if (mask != NULL) { + XFREE(mask); + } + if (salt != NULL) { + XFREE(salt); + } + if (hash != NULL) { + XFREE(hash); + } + return CRYPT_MEM; + } + + + /* generate random salt */ + if (saltlen > 0) { + if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { + err = CRYPT_ERROR_READPRNG; + goto LBL_ERR; + } + } + + /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { + goto LBL_ERR; + } + zeromem(DB, 8); + if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2 zero bytes */ + x = 0; + XMEMSET(DB + x, 0, modulus_len - saltlen - hLen - 2); + x += modulus_len - saltlen - hLen - 2; + DB[x++] = 0x01; + XMEMCPY(DB + x, salt, saltlen); + /* x += saltlen; */ + + /* generate mask of length modulus_len - hLen - 1 from hash */ + if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* xor against DB */ + for (y = 0; y < (modulus_len - hLen - 1); y++) { + DB[y] ^= mask[y]; + } + + /* output is DB || hash || 0xBC */ + if (*outlen < modulus_len) { + *outlen = modulus_len; + err = CRYPT_BUFFER_OVERFLOW; + goto LBL_ERR; + } + + /* DB len = modulus_len - hLen - 1 */ + y = 0; + XMEMCPY(out + y, DB, modulus_len - hLen - 1); + y += modulus_len - hLen - 1; + + /* hash */ + XMEMCPY(out + y, hash, hLen); + y += hLen; + + /* 0xBC */ + out[y] = 0xBC; + + /* now clear the 8*modulus_len - modulus_bitlen most significant bits */ + out[0] &= 0xFF >> ((modulus_len<<3) - modulus_bitlen); + + /* store output size */ + *outlen = modulus_len; + err = CRYPT_OK; +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(DB, modulus_len); + zeromem(mask, modulus_len); + zeromem(salt, modulus_len); + zeromem(hash, modulus_len); +#endif + + XFREE(hash); + XFREE(salt); + XFREE(mask); + XFREE(DB); + + return err; +} + +#endif /* LTC_PKCS_1 */ diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c new file mode 100644 index 0000000..e988060 --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c @@ -0,0 +1,102 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** @file pkcs_1_v1_5_decode.c + * + * PKCS #1 v1.5 Padding. (Andreas Lange) + */ + +#ifdef LTC_PKCS_1 + +/** @brief PKCS #1 v1.5 decode. + * + * @param msg The encoded data to decode + * @param msglen The length of the encoded data (octets) + * @param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) + * @param modulus_bitlen The bit length of the RSA modulus + * @param out [out] Destination of decoding + * @param outlen [in/out] The max size and resulting size of the decoding + * @param is_valid [out] Boolean whether the padding was valid + * + * @return CRYPT_OK if successful + */ +int pkcs_1_v1_5_decode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + unsigned char *out, + unsigned long *outlen, + int *is_valid) +{ + unsigned long modulus_len, ps_len, i; + int result; + + /* default to invalid packet */ + *is_valid = 0; + + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + + if ((msglen > modulus_len) || (modulus_len < 11)) { + return CRYPT_PK_INVALID_SIZE; + } + + result = CRYPT_OK; + + /* separate encoded message */ + + if ((msg[0] != 0x00) || (msg[1] != (unsigned char)block_type)) { + result = CRYPT_INVALID_PACKET; + } + + if (block_type == LTC_PKCS_1_EME) { + for (i = 2; i < modulus_len; i++) { + /* separator */ + if (msg[i] == 0x00) { break; } + } + ps_len = i++ - 2; + + if (i > modulus_len) { + /* There was no octet with hexadecimal value 0x00 to separate ps from m. + */ + result = CRYPT_INVALID_PACKET; + } + } else { + for (i = 2; i < modulus_len - 1; i++) { + if (msg[i] != 0xFF) { break; } + } + + /* separator check */ + if (msg[i] != 0) { + /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ + result = CRYPT_INVALID_PACKET; + } + + ps_len = i - 2; + } + + if (ps_len < 8) + { + /* The length of ps is less than 8 octets. + */ + result = CRYPT_INVALID_PACKET; + } + + if (*outlen < (msglen - (2 + ps_len + 1))) { + result = CRYPT_INVALID_PACKET; + } + + if (result == CRYPT_OK) { + *outlen = (msglen - (2 + ps_len + 1)); + XMEMCPY(out, &msg[2 + ps_len + 1], *outlen); + + /* valid packet */ + *is_valid = 1; + } + + return result; +} /* pkcs_1_v1_5_decode */ + +#endif /* #ifdef LTC_PKCS_1 */ diff --git a/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c new file mode 100644 index 0000000..a21df4b --- /dev/null +++ b/deps/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c @@ -0,0 +1,105 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/*! \file pkcs_1_v1_5_encode.c + * + * PKCS #1 v1.5 Padding (Andreas Lange) + */ + +#ifdef LTC_PKCS_1 + +/*! \brief PKCS #1 v1.5 encode. + * + * \param msg The data to encode + * \param msglen The length of the data to encode (octets) + * \param block_type Block type to use in padding (\sa ltc_pkcs_1_v1_5_blocks) + * \param modulus_bitlen The bit length of the RSA modulus + * \param prng An active PRNG state (only for LTC_PKCS_1_EME) + * \param prng_idx The index of the PRNG desired (only for LTC_PKCS_1_EME) + * \param out [out] The destination for the encoded data + * \param outlen [in/out] The max size and resulting size of the encoded data + * + * \return CRYPT_OK if successful + */ +int pkcs_1_v1_5_encode(const unsigned char *msg, + unsigned long msglen, + int block_type, + unsigned long modulus_bitlen, + prng_state *prng, + int prng_idx, + unsigned char *out, + unsigned long *outlen) +{ + unsigned long modulus_len, ps_len, i; + unsigned char *ps; + int result; + + LTC_ARGCHK((msglen == 0) || (msg != NULL)); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* valid block_type? */ + if ((block_type != LTC_PKCS_1_EMSA) && + (block_type != LTC_PKCS_1_EME)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (block_type == LTC_PKCS_1_EME) { /* encryption padding, we need a valid PRNG */ + if ((result = prng_is_valid(prng_idx)) != CRYPT_OK) { + return result; + } + } + + modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); + + /* test message size */ + if ((msglen + 11) > modulus_len) { + return CRYPT_PK_INVALID_SIZE; + } + + if (*outlen < modulus_len) { + *outlen = modulus_len; + result = CRYPT_BUFFER_OVERFLOW; + goto bail; + } + + /* generate an octets string PS */ + ps = &out[2]; + ps_len = modulus_len - msglen - 3; + + if (block_type == LTC_PKCS_1_EME) { + /* now choose a random ps */ + if (prng_descriptor[prng_idx].read(ps, ps_len, prng) != ps_len) { + result = CRYPT_ERROR_READPRNG; + goto bail; + } + + /* transform zero bytes (if any) to non-zero random bytes */ + for (i = 0; i < ps_len; i++) { + while (ps[i] == 0) { + if (prng_descriptor[prng_idx].read(&ps[i], 1, prng) != 1) { + result = CRYPT_ERROR_READPRNG; + goto bail; + } + } + } + } else { + XMEMSET(ps, 0xFF, ps_len); + } + + /* create string of length modulus_len */ + out[0] = 0x00; + out[1] = (unsigned char)block_type; /* block_type 1 or 2 */ + out[2 + ps_len] = 0x00; + if (msglen != 0) { + XMEMCPY(&out[2 + ps_len + 1], msg, msglen); + } + *outlen = modulus_len; + + result = CRYPT_OK; +bail: + return result; +} /* pkcs_1_v1_5_encode */ + +#endif /* #ifdef LTC_PKCS_1 */ diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c b/deps/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c new file mode 100644 index 0000000..8c6ca3d --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c @@ -0,0 +1,94 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_decrypt_key.c + RSA PKCS #1 Decryption, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + PKCS #1 decrypt then v1.5 or OAEP depad + @param in The ciphertext + @param inlen The length of the ciphertext (octets) + @param out [out] The plaintext + @param outlen [in/out] The max size and resulting size of the plaintext (octets) + @param lparam The system "lparam" value + @param lparamlen The length of the lparam value (octets) + @param hash_idx The index of the hash desired + @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) + @param stat [out] Result of the decryption, 1==valid, 0==invalid + @param key The corresponding private RSA key + @return CRYPT_OK if succcessul (even if invalid) +*/ +int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int padding, + int *stat, const rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x; + int err; + unsigned char *tmp; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(stat != NULL); + + /* default to invalid */ + *stat = 0; + + /* valid padding? */ + + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_OAEP)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_PKCS_1_OAEP) { + /* valid hash ? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits( (key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size( (key->N)); + if (modulus_bytelen != inlen) { + return CRYPT_INVALID_PACKET; + } + + /* allocate ram */ + tmp = XMALLOC(inlen); + if (tmp == NULL) { + return CRYPT_MEM; + } + + /* rsa decode the packet */ + x = inlen; + if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) { + XFREE(tmp); + return err; + } + + if (padding == LTC_PKCS_1_OAEP) { + /* now OAEP decode the packet */ + err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx, + out, outlen, stat); + } else { + /* now PKCS #1 v1.5 depad the packet */ + err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); + } + + XFREE(tmp); + return err; +} + +#endif /* LTC_MRSA */ diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c b/deps/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c new file mode 100644 index 0000000..e0f91e1 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c @@ -0,0 +1,92 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_encrypt_key.c + RSA PKCS #1 encryption, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + (PKCS #1 v2.0) OAEP pad then encrypt + @param in The plaintext + @param inlen The length of the plaintext (octets) + @param out [out] The ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param lparam The system "lparam" for the encryption + @param lparamlen The length of lparam (octets) + @param prng An active PRNG + @param prng_idx The index of the desired prng + @param hash_idx The index of the desired hash + @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) + @param key The RSA key to encrypt to + @return CRYPT_OK if successful +*/ +int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, + int hash_idx, int padding, + const rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x; + int err; + + LTC_ARGCHK((inlen == 0) || (in != NULL)); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* valid padding? */ + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_OAEP)) { + return CRYPT_PK_INVALID_PADDING; + } + + /* valid prng? */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + + if (padding == LTC_PKCS_1_OAEP) { + /* valid hash? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits( (key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size( (key->N)); + if (modulus_bytelen > *outlen) { + *outlen = modulus_bytelen; + return CRYPT_BUFFER_OVERFLOW; + } + + if (padding == LTC_PKCS_1_OAEP) { + /* OAEP pad the key */ + x = *outlen; + if ((err = pkcs_1_oaep_encode(in, inlen, lparam, + lparamlen, modulus_bitlen, prng, prng_idx, hash_idx, + out, &x)) != CRYPT_OK) { + return err; + } + } else { + /* PKCS #1 v1.5 pad the key */ + x = *outlen; + if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME, + modulus_bitlen, prng, prng_idx, + out, &x)) != CRYPT_OK) { + return err; + } + } + + /* rsa exptmod the OAEP or PKCS #1 v1.5 pad */ + return ltc_mp.rsa_me(out, x, out, outlen, PK_PUBLIC, key); +} + +#endif /* LTC_MRSA */ diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_export.c b/deps/libtomcrypt/src/pk/rsa/rsa_export.c new file mode 100644 index 0000000..225224d --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_export.c @@ -0,0 +1,91 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_export.c + Export RSA PKCS keys, Tom St Denis +*/ + +#ifdef LTC_MRSA + +/** + This will export either an RSAPublicKey or RSAPrivateKey [defined in PKCS #1 v2.1] + @param out [out] Destination of the packet + @param outlen [in/out] The max size and resulting size of the packet + @param type The type of exported key (PK_PRIVATE or PK_PUBLIC) + @param key The RSA key to export + @return CRYPT_OK if successful +*/ +int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_key *key) +{ + unsigned long zero=0; + int err, std; + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + std = type & PK_STD; + type &= ~PK_STD; + + if (type == PK_PRIVATE && key->type != PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; + } + + if (type == PK_PRIVATE) { + /* private key */ + /* output is + Version, n, e, d, p, q, d mod (p-1), d mod (q - 1), 1/q mod p + */ + return der_encode_sequence_multi(out, outlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->dP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_EOL, 0UL, NULL); + } + + if (type == PK_PUBLIC) { + /* public key */ + unsigned long tmplen, *ptmplen; + unsigned char* tmp = NULL; + + if (std) { + tmplen = (unsigned long)(mp_count_bits(key->N) / 8) * 2 + 8; + tmp = XMALLOC(tmplen); + ptmplen = &tmplen; + if (tmp == NULL) { + return CRYPT_MEM; + } + } + else { + tmp = out; + ptmplen = outlen; + } + + err = der_encode_sequence_multi(tmp, ptmplen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL); + + if ((err != CRYPT_OK) || !std) { + goto finish; + } + + err = x509_encode_subject_public_key_info(out, outlen, + LTC_OID_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0); + +finish: + if (tmp != out) XFREE(tmp); + return err; + } + + return CRYPT_INVALID_ARG; +} + +#endif /* LTC_MRSA */ diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_exptmod.c b/deps/libtomcrypt/src/pk/rsa/rsa_exptmod.c new file mode 100644 index 0000000..73daee5 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_exptmod.c @@ -0,0 +1,172 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_exptmod.c + RSA PKCS exptmod, Tom St Denis + Added RSA blinding --nmav +*/ + +#ifdef LTC_MRSA + +/** + Compute an RSA modular exponentiation + @param in The input data to send into RSA + @param inlen The length of the input (octets) + @param out [out] The destination + @param outlen [in/out] The max size and resulting size of the output + @param which Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC + @param key The RSA key to use + @return CRYPT_OK if successful +*/ +int rsa_exptmod(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int which, + const rsa_key *key) +{ + void *tmp, *tmpa, *tmpb; + #ifdef LTC_RSA_BLINDING + void *rnd, *rndi /* inverse of rnd */; + #endif + unsigned long x; + int err, has_crt_parameters; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* is the key of the right type for the operation? */ + if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* must be a private or public operation */ + if (which != PK_PRIVATE && which != PK_PUBLIC) { + return CRYPT_PK_INVALID_TYPE; + } + + /* init and copy into tmp */ + if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, +#ifdef LTC_RSA_BLINDING + &rnd, &rndi, +#endif /* LTC_RSA_BLINDING */ + NULL)) != CRYPT_OK) + { return err; } + if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK) + { goto error; } + + + /* sanity check on the input */ + if (mp_cmp(key->N, tmp) == LTC_MP_LT) { + err = CRYPT_PK_INVALID_SIZE; + goto error; + } + + /* are we using the private exponent and is the key optimized? */ + if (which == PK_PRIVATE) { + #ifdef LTC_RSA_BLINDING + /* do blinding */ + err = mp_rand(rnd, mp_get_digit_count(key->N)); + if (err != CRYPT_OK) { + goto error; + } + + /* rndi = 1/rnd mod N */ + err = mp_invmod(rnd, key->N, rndi); + if (err != CRYPT_OK) { + goto error; + } + + /* rnd = rnd^e */ + err = mp_exptmod( rnd, key->e, key->N, rnd); + if (err != CRYPT_OK) { + goto error; + } + + /* tmp = tmp*rnd mod N */ + err = mp_mulmod( tmp, rnd, key->N, tmp); + if (err != CRYPT_OK) { + goto error; + } + #endif /* LTC_RSA_BLINDING */ + + has_crt_parameters = (key->p != NULL) && (mp_get_digit_count(key->p) != 0) && + (key->q != NULL) && (mp_get_digit_count(key->q) != 0) && + (key->dP != NULL) && (mp_get_digit_count(key->dP) != 0) && + (key->dQ != NULL) && (mp_get_digit_count(key->dQ) != 0) && + (key->qP != NULL) && (mp_get_digit_count(key->qP) != 0); + + if (!has_crt_parameters) { + /* + * In case CRT optimization parameters are not provided, + * the private key is directly used to exptmod it + */ + if ((err = mp_exptmod(tmp, key->d, key->N, tmp)) != CRYPT_OK) { goto error; } + } else { + /* tmpa = tmp^dP mod p */ + if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK) { goto error; } + + /* tmpb = tmp^dQ mod q */ + if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK) { goto error; } + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK) { goto error; } + if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK) { goto error; } + + /* tmp = tmpb + q * tmp */ + if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK) { goto error; } + if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK) { goto error; } + } + + #ifdef LTC_RSA_BLINDING + /* unblind */ + err = mp_mulmod( tmp, rndi, key->N, tmp); + if (err != CRYPT_OK) { + goto error; + } + #endif + + #ifdef LTC_RSA_CRT_HARDENING + if (has_crt_parameters) { + if ((err = mp_exptmod(tmp, key->e, key->N, tmpa)) != CRYPT_OK) { goto error; } + if ((err = mp_read_unsigned_bin(tmpb, (unsigned char *)in, (int)inlen)) != CRYPT_OK) { goto error; } + if (mp_cmp(tmpa, tmpb) != LTC_MP_EQ) { err = CRYPT_ERROR; goto error; } + } + #endif + } else { + /* exptmod it */ + if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK) { goto error; } + } + + /* read it back */ + x = (unsigned long)mp_unsigned_bin_size(key->N); + if (x > *outlen) { + *outlen = x; + err = CRYPT_BUFFER_OVERFLOW; + goto error; + } + + /* this should never happen ... */ + if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) { + err = CRYPT_ERROR; + goto error; + } + *outlen = x; + + /* convert it */ + zeromem(out, x); + if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK) { goto error; } + + /* clean up and return */ + err = CRYPT_OK; +error: + mp_clear_multi( +#ifdef LTC_RSA_BLINDING + rndi, rnd, +#endif /* LTC_RSA_BLINDING */ + tmpb, tmpa, tmp, NULL); + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_get_size.c b/deps/libtomcrypt/src/pk/rsa/rsa_get_size.c new file mode 100644 index 0000000..72d3f7a --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_get_size.c @@ -0,0 +1,30 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_get_size.c + Retrieve the size of an RSA key, Steffen Jaeckel. +*/ + +#ifdef LTC_MRSA + +/** + Retrieve the size in bytes of an RSA key. + @param key The RSA key + @return The size in bytes of the RSA key or INT_MAX on error. +*/ +int rsa_get_size(const rsa_key *key) +{ + int ret = INT_MAX; + LTC_ARGCHK(key != NULL); + + if (key) + { + ret = mp_unsigned_bin_size(key->N); + } /* if */ + + return ret; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_import.c b/deps/libtomcrypt/src/pk/rsa/rsa_import.c new file mode 100644 index 0000000..1240a77 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_import.c @@ -0,0 +1,143 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_import.c + Import a PKCS RSA key, Tom St Denis +*/ + +#ifdef LTC_MRSA + + +/** + Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] + + The `key` passed into this function has to be already initialized and will + NOT be free'd on error! + + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful +*/ +int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + unsigned long version = -1; + + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_EOL, 0UL, NULL); + + if (err == CRYPT_OVERFLOW) { + /* the version would fit into an LTC_ASN1_SHORT_INTEGER + * so we try to decode as a public key + */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + key->type = PK_PUBLIC; + } + goto LBL_OUT; + } else if (err != CRYPT_INPUT_TOO_LONG) { + /* couldn't decode the version, so error out */ + goto LBL_OUT; + } + + if (version == 0) { + /* it's a private key */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->dP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_OUT; + } + key->type = PK_PRIVATE; + } else if (version == 1) { + /* we don't support multi-prime RSA */ + err = CRYPT_PK_INVALID_TYPE; + goto LBL_OUT; + } + err = CRYPT_OK; +LBL_OUT: + return err; +} + +/** + Import multiple formats of RSA public and private keys. + + RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] + SubjectPublicKeyInfo formatted public keys + + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + unsigned char *tmpbuf=NULL; + unsigned long tmpbuf_len, len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if ((err = rsa_init(key)) != CRYPT_OK) { + return err; + } + + /* see if the OpenSSL DER format RSA public key will work */ + tmpbuf_len = inlen; + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + err = CRYPT_MEM; + goto LBL_ERR; + } + + len = 0; + err = x509_decode_subject_public_key_info(in, inlen, + LTC_OID_RSA, tmpbuf, &tmpbuf_len, + LTC_ASN1_NULL, NULL, &len); + + if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */ + + /* now it should be SEQUENCE { INTEGER, INTEGER } */ + if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PUBLIC; + err = CRYPT_OK; + goto LBL_FREE; + } + + /* not SSL public key, try to match against PKCS #1 standards */ + if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) { + goto LBL_FREE; + } + +LBL_ERR: + rsa_free(key); + +LBL_FREE: + if (tmpbuf != NULL) { + XFREE(tmpbuf); + } + return err; +} + +#endif /* LTC_MRSA */ + diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c b/deps/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c new file mode 100644 index 0000000..9e02585 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_import_pkcs8.c @@ -0,0 +1,116 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_import_pkcs8.c + Import a PKCS RSA key +*/ + +#ifdef LTC_MRSA + +/* Public-Key Cryptography Standards (PKCS) #8: + * Private-Key Information Syntax Specification Version 1.2 + * https://tools.ietf.org/html/rfc5208 + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * where: + * - Version ::= INTEGER + * - PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * - PrivateKey ::= OCTET STRING + * - Attributes ::= SET OF Attribute + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData } + * where: + * - EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * - EncryptedData ::= OCTET STRING + */ + +/** + Import an RSAPrivateKey in PKCS#8 format + @param in The packet to import from + @param inlen It's length (octets) + @param passwd The password for decrypting privkey + @param passwdlen Password's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *passwd, unsigned long passwdlen, + rsa_key *key) +{ + int err; + unsigned char *buf1 = NULL, *buf2 = NULL; + unsigned long buf1len, buf2len; + unsigned long oid[16], version; + const char *rsaoid; + ltc_asn1_list alg_seq[2], top_seq[3]; + ltc_asn1_list *l = NULL; + unsigned char *decrypted = NULL; + unsigned long decryptedlen; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* get RSA alg oid */ + err = pk_get_oid(LTC_OID_RSA, &rsaoid); + if (err != CRYPT_OK) { goto LBL_NOFREE; } + + /* alloc buffers */ + buf1len = inlen; /* approx. */ + buf1 = XMALLOC(buf1len); + if (buf1 == NULL) { err = CRYPT_MEM; goto LBL_NOFREE; } + buf2len = inlen; /* approx. */ + buf2 = XMALLOC(buf2len); + if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; } + + /* init key */ + if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE2; } + + /* try to decode encrypted priv key */ + if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) { + goto LBL_ERR; + } + decrypted = l->data; + decryptedlen = l->size; + + /* try to decode unencrypted priv key */ + LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL); + LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL); + LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_INTEGER, &version, 1UL); + LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL); + LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len); + err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL); + if (err != CRYPT_OK) { goto LBL_ERR; } + + /* check alg oid */ + if ((err = pk_oid_cmp_with_asn1(rsaoid, &alg_seq[0])) != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = rsa_import_pkcs1(buf1, top_seq[2].size, key)) != CRYPT_OK) { + goto LBL_ERR; + } + key->type = PK_PRIVATE; + err = CRYPT_OK; + goto LBL_FREE2; + +LBL_ERR: + rsa_free(key); +LBL_FREE2: + if (l) der_free_sequence_flexi(l); + XFREE(buf2); +LBL_FREE1: + XFREE(buf1); +LBL_NOFREE: + return err; +} + +#endif /* LTC_MRSA */ diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_import_x509.c b/deps/libtomcrypt/src/pk/rsa/rsa_import_x509.c new file mode 100644 index 0000000..e921aae --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_import_x509.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_import.c + Import an RSA key from a X.509 certificate, Steffen Jaeckel +*/ + +#ifdef LTC_MRSA + +static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + /* now it should be SEQUENCE { INTEGER, INTEGER } */ + return der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL); +} + +/** + Import an RSA key from a X.509 certificate + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if ((err = rsa_init(key)) != CRYPT_OK) { + return err; + } + + if ((err = x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_RSA, LTC_ASN1_NULL, + NULL, NULL, + (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { + rsa_free(key); + } else { + key->type = PK_PUBLIC; + } + + return err; +} + +#endif /* LTC_MRSA */ + diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_key.c b/deps/libtomcrypt/src/pk/rsa/rsa_key.c new file mode 100644 index 0000000..2d0712f --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_key.c @@ -0,0 +1,103 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_key.c + Free an RSA key, Tom St Denis + Basic operations on an RSA key, Steffen Jaeckel +*/ + +#ifdef LTC_MRSA +#include + +static void s_mpi_shrink_multi(void **a, ...) +{ + void **cur; + unsigned n; + int err; + va_list args; + void *tmp[10] = { 0 }; + void **arg[10] = { 0 }; + + /* We re-allocate in the order that we received the varargs */ + n = 0; + err = CRYPT_ERROR; + cur = a; + va_start(args, a); + while (cur != NULL) { + if (n >= sizeof(tmp)/sizeof(tmp[0])) { + goto out; + } + if (*cur != NULL) { + arg[n] = cur; + if ((err = mp_init_copy(&tmp[n], *arg[n])) != CRYPT_OK) { + goto out; + } + n++; + } + cur = va_arg(args, void**); + } + va_end(args); + + /* but we clear the old values in the reverse order */ + while (n != 0 && arg[--n] != NULL) { + mp_clear(*arg[n]); + *arg[n] = tmp[n]; + } +out: + va_end(args); + /* clean-up after an error + * or after this was called with too many args + */ + if ((err != CRYPT_OK) || + (n >= sizeof(tmp)/sizeof(tmp[0]))) { + for (n = 0; n < sizeof(tmp)/sizeof(tmp[0]); ++n) { + if (tmp[n] != NULL) { + mp_clear(tmp[n]); + } + } + } +} + +/** + This shrinks the allocated memory of a RSA key + + It will use up some more memory temporarily, + but then it will free-up the entire sequence that + was once allocated when the key was created/populated. + + This only works with libtommath >= 1.2.0 in earlier versions + it has the inverse effect due to the way it worked internally. + Also works for GNU MP, tomsfastmath naturally shows no effect. + + @param key The RSA key to shrink +*/ +void rsa_shrink_key(rsa_key *key) +{ + LTC_ARGCHKVD(key != NULL); + s_mpi_shrink_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL); +} + +/** + Init an RSA key + @param key The RSA key to free + @return CRYPT_OK if successful +*/ +int rsa_init(rsa_key *key) +{ + LTC_ARGCHK(key != NULL); + return mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL); +} + +/** + Free an RSA key from memory + @param key The RSA key to free +*/ +void rsa_free(rsa_key *key) +{ + LTC_ARGCHKVD(key != NULL); + mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_make_key.c b/deps/libtomcrypt/src/pk/rsa/rsa_make_key.c new file mode 100644 index 0000000..6bfc041 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_make_key.c @@ -0,0 +1,165 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_make_key.c + RSA key generation, Tom St Denis +*/ + +#ifdef LTC_MRSA + +static int s_rsa_make_key(prng_state *prng, int wprng, int size, void *e, rsa_key *key) +{ + void *p, *q, *tmp1, *tmp2; + int err; + + LTC_ARGCHK(ltc_mp.name != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(size > 0); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { + return err; + } + + /* make primes p and q (optimization provided by Wayne Scott) */ + + /* make prime "p" */ + do { + if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = p-1 */ + if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(p-1, e) */ + } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides p-1 */ + + /* make prime "q" */ + do { + if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) { goto cleanup; } + if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = q-1 */ + if ((err = mp_gcd( tmp1, e, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = gcd(q-1, e) */ + } while (mp_cmp_d( tmp2, 1) != 0); /* while e divides q-1 */ + + /* tmp1 = lcm(p-1, q-1) */ + if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) { goto cleanup; } /* tmp2 = p-1 */ + /* tmp1 = q-1 (previous do/while loop) */ + if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) { goto cleanup; } /* tmp1 = lcm(p-1, q-1) */ + + /* make key */ + if ((err = rsa_init(key)) != CRYPT_OK) { + goto errkey; + } + + if ((err = mp_copy( e, key->e)) != CRYPT_OK) { goto errkey; } /* key->e = e */ + if ((err = mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) { goto errkey; } /* key->d = 1/e mod lcm(p-1,q-1) */ + if ((err = mp_mul( p, q, key->N)) != CRYPT_OK) { goto errkey; } /* key->N = pq */ + + /* optimize for CRT now */ + /* find d mod q-1 and d mod p-1 */ + if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) { goto errkey; } /* tmp1 = p-1 */ + if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) { goto errkey; } /* tmp2 = q-1 */ + if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) { goto errkey; } /* dP = d mod p-1 */ + if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) { goto errkey; } /* dQ = d mod q-1 */ + if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) { goto errkey; } /* qP = 1/q mod p */ + + if ((err = mp_copy( p, key->p)) != CRYPT_OK) { goto errkey; } + if ((err = mp_copy( q, key->q)) != CRYPT_OK) { goto errkey; } + + /* set key type (in this case it's CRT optimized) */ + key->type = PK_PRIVATE; + + /* return ok and free temps */ + err = CRYPT_OK; + goto cleanup; +errkey: + rsa_free(key); +cleanup: + mp_clear_multi(tmp2, tmp1, q, p, LTC_NULL); + return err; +} + +/** + Create an RSA key based on a long public exponent type + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the modulus (key size) desired (octets) + @param e The "e" value (public key). e==65537 is a good choice + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed +*/ +int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) +{ + void *tmp_e; + int err; + + if ((e < 3) || ((e & 1) == 0)) { + return CRYPT_INVALID_ARG; + } + + if ((err = mp_init(&tmp_e)) != CRYPT_OK) { + return err; + } + + if ((err = mp_set_int(tmp_e, e)) == CRYPT_OK) + err = s_rsa_make_key(prng, wprng, size, tmp_e, key); + + mp_clear(tmp_e); + + return err; +} + +/** + Create an RSA key based on a hexadecimal public exponent type + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the modulus (key size) desired (octets) + @param e The "e" value (public key). e==65537 is a good choice + @param elen The length of e (octets) + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed +*/ +int rsa_make_key_ubin_e(prng_state *prng, int wprng, int size, + const unsigned char *e, unsigned long elen, rsa_key *key) +{ + int err; + void *tmp_e; + + if ((err = mp_init(&tmp_e)) != CRYPT_OK) { + return err; + } + + if ((err = mp_read_unsigned_bin(tmp_e, (unsigned char *)e, elen)) == CRYPT_OK) + err = rsa_make_key_bn_e(prng, wprng, size, tmp_e, key); + + mp_clear(tmp_e); + + return err; +} + +/** + Create an RSA key based on a bignumber public exponent type + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param size The size of the modulus (key size) desired (octets) + @param e The "e" value (public key). e==65537 is a good choice + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful, upon error all allocated ram is freed +*/ +int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key) +{ + int err; + int e_bits; + + e_bits = mp_count_bits(e); + if ((e_bits > 1 && e_bits < 256) && (mp_get_digit(e, 0) & 1)) { + err = s_rsa_make_key(prng, wprng, size, e, key); + } else { + err = CRYPT_INVALID_ARG; + } + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_set.c b/deps/libtomcrypt/src/pk/rsa/rsa_set.c new file mode 100644 index 0000000..d4dc6ed --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_set.c @@ -0,0 +1,123 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + + +#ifdef LTC_MRSA + +/** + Import RSA key from raw numbers + + @param N RSA's N + @param Nlen RSA's N's length + @param e RSA's e + @param elen RSA's e's length + @param d RSA's d (only private key, NULL for public key) + @param dlen RSA's d's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_key(const unsigned char *N, unsigned long Nlen, + const unsigned char *e, unsigned long elen, + const unsigned char *d, unsigned long dlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(N != NULL); + LTC_ARGCHK(e != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if ((err = rsa_init(key)) != CRYPT_OK) return err; + + if ((err = mp_read_unsigned_bin(key->N , (unsigned char *)N , Nlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->e , (unsigned char *)e , elen)) != CRYPT_OK) { goto LBL_ERR; } + if (d && dlen) { + if ((err = mp_read_unsigned_bin(key->d , (unsigned char *)d , dlen)) != CRYPT_OK) { goto LBL_ERR; } + key->type = PK_PRIVATE; + } + else { + key->type = PK_PUBLIC; + } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +/** + Import factors of an RSA key from raw numbers + + Only for private keys. + + @param p RSA's p + @param plen RSA's p's length + @param q RSA's q + @param qlen RSA's q's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_factors(const unsigned char *p, unsigned long plen, + const unsigned char *q, unsigned long qlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(p != NULL); + LTC_ARGCHK(q != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + + if ((err = mp_read_unsigned_bin(key->p , (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->q , (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +/** + Import CRT parameters of an RSA key from raw numbers + + Only for private keys. + + @param dP RSA's dP + @param dPlen RSA's dP's length + @param dQ RSA's dQ + @param dQlen RSA's dQ's length + @param qP RSA's qP + @param qPlen RSA's qP's length + @param key [out] the destination for the imported key + @return CRYPT_OK if successful +*/ +int rsa_set_crt_params(const unsigned char *dP, unsigned long dPlen, + const unsigned char *dQ, unsigned long dQlen, + const unsigned char *qP, unsigned long qPlen, + rsa_key *key) +{ + int err; + + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(dP != NULL); + LTC_ARGCHK(dQ != NULL); + LTC_ARGCHK(qP != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH; + + if ((err = mp_read_unsigned_bin(key->dP, (unsigned char *)dP, dPlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->dQ, (unsigned char *)dQ, dQlen)) != CRYPT_OK) { goto LBL_ERR; } + if ((err = mp_read_unsigned_bin(key->qP, (unsigned char *)qP, qPlen)) != CRYPT_OK) { goto LBL_ERR; } + return CRYPT_OK; + +LBL_ERR: + rsa_free(key); + return err; +} + +#endif /* LTC_MRSA */ diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_sign_hash.c b/deps/libtomcrypt/src/pk/rsa/rsa_sign_hash.c new file mode 100644 index 0000000..aec30e2 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_sign_hash.c @@ -0,0 +1,136 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_sign_hash.c + RSA PKCS #1 v1.5 and v2 PSS sign hash, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + PKCS #1 pad then sign + @param in The hash to sign + @param inlen The length of the hash to sign (octets) + @param out [out] The signature + @param outlen [in/out] The max size and resulting size of the signature + @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) + @param prng An active PRNG state + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param saltlen The length of the salt desired (octets) + @param key The private RSA key to use + @return CRYPT_OK if successful +*/ +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + const rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x, y; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + /* valid padding? */ + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_PSS) && + (padding != LTC_PKCS_1_V1_5_NA1)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_PKCS_1_PSS) { + /* valid prng ? */ + if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + return err; + } + } + + if (padding != LTC_PKCS_1_V1_5_NA1) { + /* valid hash ? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits((key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size((key->N)); + if (modulus_bytelen > *outlen) { + *outlen = modulus_bytelen; + return CRYPT_BUFFER_OVERFLOW; + } + + if (padding == LTC_PKCS_1_PSS) { + /* PSS pad the key */ + x = *outlen; + if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, + hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { + return err; + } + } else { + /* PKCS #1 v1.5 pad the hash */ + unsigned char *tmpin; + + if (padding == LTC_PKCS_1_V1_5) { + ltc_asn1_list digestinfo[2], siginfo[2]; + /* not all hashes have OIDs... so sad */ + if (hash_descriptor[hash_idx].OIDlen == 0) { + return CRYPT_INVALID_ARG; + } + + /* construct the SEQUENCE + SEQUENCE { + SEQUENCE {hashoid OID + blah NULL + } + hash OCTET STRING + } + */ + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); + LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); + LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); + + /* allocate memory for the encoding */ + y = mp_unsigned_bin_size(key->N); + tmpin = XMALLOC(y); + if (tmpin == NULL) { + return CRYPT_MEM; + } + + if ((err = der_encode_sequence(siginfo, 2, tmpin, &y)) != CRYPT_OK) { + XFREE(tmpin); + return err; + } + } else { + /* set the pointer and data-length to the input values */ + tmpin = (unsigned char *)in; + y = inlen; + } + + x = *outlen; + err = pkcs_1_v1_5_encode(tmpin, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); + + if (padding == LTC_PKCS_1_V1_5) { + XFREE(tmpin); + } + + if (err != CRYPT_OK) { + return err; + } + } + + /* RSA encode it */ + return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); +} + +#endif /* LTC_MRSA */ diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c b/deps/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c new file mode 100644 index 0000000..f1ae263 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_sign_saltlen_get.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_sign_saltlen_get.c + Retrieve the maximum size of the salt, Steffen Jaeckel. +*/ + +#ifdef LTC_MRSA + +/** + Retrieve the maximum possible size of the salt when creating a PKCS#1 PSS signature. + @param padding Type of padding (LTC_PKCS_1_PSS only) + @param hash_idx The index of the desired hash + @param key The RSA key + @return The maximum salt length in bytes or INT_MAX on error. +*/ +int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key) +{ + int ret = INT_MAX; + LTC_ARGCHK(key != NULL); + + if ((hash_is_valid(hash_idx) == CRYPT_OK) && + (padding == LTC_PKCS_1_PSS)) + { + ret = rsa_get_size(key); + if (ret < INT_MAX) + { + ret -= (hash_descriptor[hash_idx].hashsize + 2); + } /* if */ + } /* if */ + + return ret; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/deps/libtomcrypt/src/pk/rsa/rsa_verify_hash.c new file mode 100644 index 0000000..ca4cdf9 --- /dev/null +++ b/deps/libtomcrypt/src/pk/rsa/rsa_verify_hash.c @@ -0,0 +1,183 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file rsa_verify_hash.c + RSA PKCS #1 v1.5 or v2 PSS signature verification, Tom St Denis and Andreas Lange +*/ + +#ifdef LTC_MRSA + +/** + PKCS #1 de-sign then v1.5 or PSS depad + @param sig The signature data + @param siglen The length of the signature data (octets) + @param hash The hash of the message that was signed + @param hashlen The length of the hash of the message that was signed (octets) + @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) + @param hash_idx The index of the desired hash + @param saltlen The length of the salt used during signature + @param stat [out] The result of the signature comparison, 1==valid, 0==invalid + @param key The public RSA key corresponding to the key that performed the signature + @return CRYPT_OK on success (even if the signature is invalid) +*/ +int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int padding, + int hash_idx, unsigned long saltlen, + int *stat, const rsa_key *key) +{ + unsigned long modulus_bitlen, modulus_bytelen, x; + int err; + unsigned char *tmpbuf; + + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + /* default to invalid */ + *stat = 0; + + /* valid padding? */ + + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_PSS) && + (padding != LTC_PKCS_1_V1_5_NA1)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding != LTC_PKCS_1_V1_5_NA1) { + /* valid hash ? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + + /* get modulus len in bits */ + modulus_bitlen = mp_count_bits( (key->N)); + + /* outlen must be at least the size of the modulus */ + modulus_bytelen = mp_unsigned_bin_size( (key->N)); + if (modulus_bytelen != siglen) { + return CRYPT_INVALID_PACKET; + } + + /* allocate temp buffer for decoded sig */ + tmpbuf = XMALLOC(siglen); + if (tmpbuf == NULL) { + return CRYPT_MEM; + } + + /* RSA decode it */ + x = siglen; + if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { + XFREE(tmpbuf); + return err; + } + + /* make sure the output is the right size */ + if (x != siglen) { + XFREE(tmpbuf); + return CRYPT_INVALID_PACKET; + } + + if (padding == LTC_PKCS_1_PSS) { + /* PSS decode and verify it */ + + if(modulus_bitlen%8 == 1){ + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat); + } + else{ + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); + } + + } else { + /* PKCS #1 v1.5 decode it */ + unsigned char *out; + unsigned long outlen; + int decoded; + + /* allocate temp buffer for decoded hash */ + outlen = ((modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0)) - 3; + out = XMALLOC(outlen); + if (out == NULL) { + err = CRYPT_MEM; + goto bail_2; + } + + if ((err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &outlen, &decoded)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + + if (padding == LTC_PKCS_1_V1_5) { + unsigned long loid[16], reallen; + ltc_asn1_list digestinfo[2], siginfo[2]; + + /* not all hashes have OIDs... so sad */ + if (hash_descriptor[hash_idx].OIDlen == 0) { + err = CRYPT_INVALID_ARG; + goto bail_2; + } + + /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ + /* construct the SEQUENCE + SEQUENCE { + SEQUENCE {hashoid OID + blah NULL + } + hash OCTET STRING + } + */ + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, sizeof(loid)/sizeof(loid[0])); + LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); + LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); + + if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { + /* fallback to Legacy:missing NULL */ + LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1); + if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + } + + if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) { + XFREE(out); + goto bail_2; + } + + /* test OID */ + if ((reallen == outlen) && + (digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) && + (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) && + (siginfo[1].size == hashlen) && + (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) { + *stat = 1; + } + } else { + /* only check if the hash is equal */ + if ((hashlen == outlen) && + (XMEMCMP(out, hash, hashlen) == 0)) { + *stat = 1; + } + } + +#ifdef LTC_CLEAN_STACK + zeromem(out, outlen); +#endif + XFREE(out); + } + +bail_2: +#ifdef LTC_CLEAN_STACK + zeromem(tmpbuf, siglen); +#endif + XFREE(tmpbuf); + return err; +} + +#endif /* LTC_MRSA */ diff --git a/deps/libtomcrypt/src/pk/x25519/x25519_export.c b/deps/libtomcrypt/src/pk/x25519/x25519_export.c new file mode 100644 index 0000000..0687c13 --- /dev/null +++ b/deps/libtomcrypt/src/pk/x25519/x25519_export.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_export.c + Export a X25519 key to a binary packet, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Export a X25519 key to a binary packet + @param out [out] The destination for the key + @param outlen [in/out] The max size and resulting size of the X25519 key + @param type Which type of key (PK_PRIVATE, PK_PUBLIC|PK_STD or PK_PUBLIC) + @param key The key you wish to export + @return CRYPT_OK if successful +*/ +int x25519_export( unsigned char *out, unsigned long *outlen, + int which, + const curve25519_key *key) +{ + LTC_ARGCHK(key != NULL); + + if (key->algo != LTC_OID_X25519) return CRYPT_PK_INVALID_TYPE; + + return ec25519_export(out, outlen, which, key); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/x25519/x25519_import.c b/deps/libtomcrypt/src/pk/x25519/x25519_import.c new file mode 100644 index 0000000..247885f --- /dev/null +++ b/deps/libtomcrypt/src/pk/x25519/x25519_import.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import.c + Import a X25519 key from a SubjectPublicKeyInfo, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import a X25519 key + @param in The packet to read + @param inlen The length of the input packet + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + unsigned long key_len; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + key_len = sizeof(key->pub); + if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { + key->type = PK_PUBLIC; + key->algo = LTC_OID_X25519; + } + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c b/deps/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c new file mode 100644 index 0000000..8b577c3 --- /dev/null +++ b/deps/libtomcrypt/src/pk/x25519/x25519_import_pkcs8.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import_pkcs8.c + Import a X25519 key in PKCS#8 format, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Import a X25519 private key in PKCS#8 format + @param in The DER-encoded PKCS#8-formatted private key + @param inlen The length of the input data + @param passwd The password to decrypt the private key + @param passwdlen Password's length (octets) + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, + const void *pwd, unsigned long pwdlen, + curve25519_key *key) +{ + return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_X25519, tweetnacl_crypto_scalarmult_base, key); +} + +#endif diff --git a/deps/libtomcrypt/src/pk/x25519/x25519_import_raw.c b/deps/libtomcrypt/src/pk/x25519/x25519_import_raw.c new file mode 100644 index 0000000..e86e8c6 --- /dev/null +++ b/deps/libtomcrypt/src/pk/x25519/x25519_import_raw.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import_raw.c + Set the parameters of a X25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Set the parameters of a X25519 key + + @param in The key + @param inlen The length of the key + @param which Which type of key (PK_PRIVATE or PK_PUBLIC) + @param key [out] Destination of the key + @return CRYPT_OK if successful +*/ +int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, curve25519_key *key) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen == 32uL); + LTC_ARGCHK(key != NULL); + + if (which == PK_PRIVATE) { + XMEMCPY(key->priv, in, sizeof(key->priv)); + tweetnacl_crypto_scalarmult_base(key->pub, key->priv); + } else if (which == PK_PUBLIC) { + XMEMCPY(key->pub, in, sizeof(key->pub)); + } else { + return CRYPT_INVALID_ARG; + } + key->algo = LTC_OID_X25519; + key->type = which; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/x25519/x25519_import_x509.c b/deps/libtomcrypt/src/pk/x25519/x25519_import_x509.c new file mode 100644 index 0000000..043b6ad --- /dev/null +++ b/deps/libtomcrypt/src/pk/x25519/x25519_import_x509.c @@ -0,0 +1,45 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_import_x509.c + Import a X25519 key from a X.509 certificate, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_x25519_decode(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + if (inlen != sizeof(key->pub)) return CRYPT_PK_INVALID_SIZE; + XMEMCPY(key->pub, in, sizeof(key->pub)); + return CRYPT_OK; +} + +/** + Import a X25519 public key from a X.509 certificate + @param in The DER encoded X.509 certificate + @param inlen The length of the certificate + @param key [out] Where to import the key to + @return CRYPT_OK if successful, on error all allocated memory is freed automatically +*/ +int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_X25519, + LTC_ASN1_EOL, NULL, NULL, + (public_key_decode_cb)s_x25519_decode, key)) != CRYPT_OK) { + return err; + } + key->type = PK_PUBLIC; + key->algo = LTC_OID_X25519; + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/x25519/x25519_make_key.c b/deps/libtomcrypt/src/pk/x25519/x25519_make_key.c new file mode 100644 index 0000000..40276fe --- /dev/null +++ b/deps/libtomcrypt/src/pk/x25519/x25519_make_key.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_make_key.c + Create a X25519 key, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Create a X25519 key + @param prng An active PRNG state + @param wprng The index of the PRNG desired + @param key [out] Destination of a newly created private key pair + @return CRYPT_OK if successful +*/ +int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (prng_descriptor[wprng].read(key->priv, sizeof(key->priv), prng) != sizeof(key->priv)) { + return CRYPT_ERROR_READPRNG; + } + + tweetnacl_crypto_scalarmult_base(key->pub, key->priv); + + key->type = PK_PRIVATE; + key->algo = LTC_OID_X25519; + + return err; +} + +#endif diff --git a/deps/libtomcrypt/src/pk/x25519/x25519_shared_secret.c b/deps/libtomcrypt/src/pk/x25519/x25519_shared_secret.c new file mode 100644 index 0000000..eaea1c0 --- /dev/null +++ b/deps/libtomcrypt/src/pk/x25519/x25519_shared_secret.c @@ -0,0 +1,42 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x25519_shared_secret.c + Create a X25519 shared secret, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +/** + Create a X25519 shared secret. + @param private_key The private X25519 key in the pair + @param public_key The public X25519 key in the pair + @param out [out] The destination of the shared data + @param outlen [in/out] The max size and resulting size of the shared data. + @return CRYPT_OK if successful +*/ +int x25519_shared_secret(const curve25519_key *private_key, + const curve25519_key *public_key, + unsigned char *out, unsigned long *outlen) +{ + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if(private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + if(*outlen < 32uL) { + *outlen = 32uL; + return CRYPT_BUFFER_OVERFLOW; + } + + tweetnacl_crypto_scalarmult(out, private_key->priv, public_key->pub); + *outlen = 32uL; + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/prngs/chacha20.c b/deps/libtomcrypt/src/prngs/chacha20.c new file mode 100644 index 0000000..d9bd7b0 --- /dev/null +++ b/deps/libtomcrypt/src/prngs/chacha20.c @@ -0,0 +1,218 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + + /* the idea of re-keying loosely follows the approach used in: + * http://bxr.su/OpenBSD/lib/libc/crypt/arc4random.c + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA20_PRNG + +const struct ltc_prng_descriptor chacha20_prng_desc = +{ + "chacha20", + 40, + &chacha20_prng_start, + &chacha20_prng_add_entropy, + &chacha20_prng_ready, + &chacha20_prng_read, + &chacha20_prng_done, + &chacha20_prng_export, + &chacha20_prng_import, + &chacha20_prng_test +}; + +/** + Start the PRNG + @param prng The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int chacha20_prng_start(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); + prng->u.chacha.idx = 0; + LTC_MUTEX_INIT(&prng->lock) + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int chacha20_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char buf[40]; + unsigned long i; + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { + /* chacha20_prng_ready() was already called, do "rekey" operation */ + if ((err = chacha_keystream(&prng->u.chacha.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; + /* key 32 bytes, 20 rounds */ + if ((err = chacha_setup(&prng->u.chacha.s, buf, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = chacha_ivctr64(&prng->u.chacha.s, buf + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; + /* clear KEY + IV */ + zeromem(buf, sizeof(buf)); + } + else { + /* chacha20_prng_ready() was not called yet, add entropy to ent buffer */ + while (inlen--) prng->u.chacha.ent[prng->u.chacha.idx++ % sizeof(prng->u.chacha.ent)] ^= *in++; + } + err = CRYPT_OK; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int chacha20_prng_ready(prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } + /* key 32 bytes, 20 rounds */ + if ((err = chacha_setup(&prng->u.chacha.s, prng->u.chacha.ent, 32, 20)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = chacha_ivctr64(&prng->u.chacha.s, prng->u.chacha.ent + 32, 8, 0)) != CRYPT_OK) goto LBL_UNLOCK; + XMEMSET(&prng->u.chacha.ent, 0, sizeof(prng->u.chacha.ent)); + prng->u.chacha.idx = 0; + prng->ready = 1; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long chacha20_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + LTC_MUTEX_LOCK(&prng->lock); + if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } + if (chacha_keystream(&prng->u.chacha.s, out, outlen) != CRYPT_OK) outlen = 0; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int chacha20_prng_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + err = chacha_done(&prng->u.chacha.s); + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&prng->lock); + return err; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +LTC_PRNG_EXPORT(chacha20_prng) + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int chacha20_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + if (inlen < (unsigned long)chacha20_prng_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = chacha20_prng_start(prng)) != CRYPT_OK) return err; + if ((err = chacha20_prng_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int chacha20_prng_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; + unsigned char dmp[300]; + unsigned long dmplen = sizeof(dmp); + unsigned char out[500]; + unsigned char t1[] = { 0x59, 0xB2, 0x26, 0x95, 0x2B, 0x01, 0x8F, 0x05, 0xBE, 0xD8 }; + unsigned char t2[] = { 0x47, 0xC9, 0x0D, 0x03, 0xE4, 0x75, 0x34, 0x27, 0xBD, 0xDE }; + unsigned char t3[] = { 0xBC, 0xFA, 0xEF, 0x59, 0x37, 0x7F, 0x1A, 0x91, 0x1A, 0xA6 }; + int err; + + if ((err = chacha20_prng_start(&st)) != CRYPT_OK) return err; + /* add entropy to uninitialized prng */ + if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t1, sizeof(t1), "CHACHA-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + /* add entropy to already initialized prng */ + if ((err = chacha20_prng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = chacha20_prng_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t2, sizeof(t2), "CHACHA-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; + if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; + if ((err = chacha20_prng_import(dmp, dmplen, &st)) != CRYPT_OK) return err; + if ((err = chacha20_prng_ready(&st)) != CRYPT_OK) return err; + if (chacha20_prng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (chacha20_prng_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t3, sizeof(t3), "CHACHA-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; + if ((err = chacha20_prng_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/prngs/fortuna.c b/deps/libtomcrypt/src/prngs/fortuna.c new file mode 100644 index 0000000..6f50098 --- /dev/null +++ b/deps/libtomcrypt/src/prngs/fortuna.c @@ -0,0 +1,520 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +#if defined(_WIN32) + #include +#elif defined(LTC_CLOCK_GETTIME) + #include /* struct timespec + clock_gettime */ +#else + #include /* struct timeval + gettimeofday */ +#endif +#endif + +/** + @file fortuna.c + Fortuna PRNG, Tom St Denis +*/ + +/* Implementation of Fortuna by Tom St Denis + +We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources" +in the AddEntropy function are fixed to 0. Second since no reliable timer is provided +we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to the read function */ + +#ifdef LTC_FORTUNA + +/* requries LTC_SHA256 and AES */ +#if !(defined(LTC_RIJNDAEL) && defined(LTC_SHA256)) + #error LTC_FORTUNA requires LTC_SHA256 and LTC_RIJNDAEL (AES) +#endif + +#ifndef LTC_FORTUNA_POOLS + #warning LTC_FORTUNA_POOLS was not previously defined (old headers?) + #define LTC_FORTUNA_POOLS 32 +#endif + +#if LTC_FORTUNA_POOLS < 4 || LTC_FORTUNA_POOLS > 32 + #error LTC_FORTUNA_POOLS must be in [4..32] +#endif + +const struct ltc_prng_descriptor fortuna_desc = { + "fortuna", + 64, + &fortuna_start, + &fortuna_add_entropy, + &fortuna_ready, + &fortuna_read, + &fortuna_done, + &fortuna_export, + &fortuna_import, + &fortuna_test +}; + +/* update the IV */ +static void s_fortuna_update_iv(prng_state *prng) +{ + int x; + unsigned char *IV; + /* update IV */ + IV = prng->u.fortuna.IV; + for (x = 0; x < 16; x++) { + IV[x] = (IV[x] + 1) & 255; + if (IV[x] != 0) break; + } +} + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED +/* get the current time in 100ms steps */ +static ulong64 s_fortuna_current_time(void) +{ + ulong64 cur_time; +#if defined(_WIN32) + FILETIME CurrentTime; + ULARGE_INTEGER ul; + GetSystemTimeAsFileTime(&CurrentTime); + ul.LowPart = CurrentTime.dwLowDateTime; + ul.HighPart = CurrentTime.dwHighDateTime; + cur_time = ul.QuadPart; /* now we have 100ns intervals since 1 January 1601 */ + cur_time -= CONST64(116444736000000000); /* subtract 100ns intervals between 1601-1970 */ + cur_time /= 10; /* 100ns intervals > microseconds */ +#elif defined(LTC_CLOCK_GETTIME) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + cur_time = (ulong64)(ts.tv_sec) * 1000000 + (ulong64)(ts.tv_nsec) / 1000; /* get microseconds */ +#else + struct timeval tv; + gettimeofday(&tv, NULL); + cur_time = (ulong64)(tv.tv_sec) * 1000000 + (ulong64)(tv.tv_usec); /* get microseconds */ +#endif + return cur_time / 100; +} +#endif + +/* reseed the PRNG */ +static int s_fortuna_reseed(prng_state *prng) +{ + unsigned char tmp[MAXBLOCKSIZE]; + hash_state md; + ulong64 reset_cnt; + int err, x; + +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED + ulong64 now = s_fortuna_current_time(); + if (now == prng->u.fortuna.wd) { + return CRYPT_OK; + } +#else + if (++prng->u.fortuna.wd < LTC_FORTUNA_WD) { + return CRYPT_OK; + } +#endif + + /* new K == LTC_SHA256(K || s) where s == LTC_SHA256(P0) || LTC_SHA256(P1) ... */ + sha256_init(&md); + if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + + reset_cnt = prng->u.fortuna.reset_cnt + 1; + + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + if (x == 0 || ((reset_cnt >> (x-1)) & 1) == 0) { + /* terminate this hash */ + if ((err = sha256_done(&prng->u.fortuna.pool[x], tmp)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + /* add it to the string */ + if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + /* reset this pool */ + if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + } else { + break; + } + } + + /* finish key */ + if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { + return err; + } + if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { + return err; + } + s_fortuna_update_iv(prng); + + /* reset/update internals */ + prng->u.fortuna.pool0_len = 0; +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED + prng->u.fortuna.wd = now; +#else + prng->u.fortuna.wd = 0; +#endif + prng->u.fortuna.reset_cnt = reset_cnt; + + +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + zeromem(tmp, sizeof(tmp)); +#endif + + return CRYPT_OK; +} + +/** + "Update Seed File"-compliant update of K + + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int fortuna_update_seed(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + unsigned char tmp[MAXBLOCKSIZE]; + hash_state md; + + LTC_MUTEX_LOCK(&prng->lock); + /* new K = LTC_SHA256(K || in) */ + sha256_init(&md); + if ((err = sha256_process(&md, prng->u.fortuna.K, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + goto LBL_UNLOCK; + } + if ((err = sha256_process(&md, in, inlen)) != CRYPT_OK) { + sha256_done(&md, tmp); + goto LBL_UNLOCK; + } + /* finish key */ + if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + s_fortuna_update_iv(prng); + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); +#endif + + return err; +} + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int fortuna_start(prng_state *prng) +{ + int err, x, y; + unsigned char tmp[MAXBLOCKSIZE]; + + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + + /* initialize the pools */ + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + if ((err = sha256_init(&prng->u.fortuna.pool[x])) != CRYPT_OK) { + for (y = 0; y < x; y++) { + sha256_done(&prng->u.fortuna.pool[y], tmp); + } + return err; + } + } + prng->u.fortuna.pool_idx = prng->u.fortuna.pool0_len = 0; + prng->u.fortuna.reset_cnt = prng->u.fortuna.wd = 0; + + /* reset bufs */ + zeromem(prng->u.fortuna.K, 32); + if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) { + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + sha256_done(&prng->u.fortuna.pool[x], tmp); + } + return err; + } + zeromem(prng->u.fortuna.IV, 16); + + LTC_MUTEX_INIT(&prng->lock) + + return CRYPT_OK; +} + +static int s_fortuna_add(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char tmp[2]; + int err; + + /* ensure inlen <= 32 */ + if (inlen > 32) { + inlen = 32; + } + + /* add s || length(in) || in to pool[pool_idx] */ + tmp[0] = (unsigned char)source; + tmp[1] = (unsigned char)inlen; + + if ((err = sha256_process(&prng->u.fortuna.pool[pool], tmp, 2)) != CRYPT_OK) { + return err; + } + if ((err = sha256_process(&prng->u.fortuna.pool[pool], in, inlen)) != CRYPT_OK) { + return err; + } + if (pool == 0) { + prng->u.fortuna.pool0_len += inlen; + } + return CRYPT_OK; /* success */ +} + +/** + Add random event to the PRNG state as proposed by the original paper. + @param source The source this random event comes from (0 .. 255) + @param pool The pool where to add the data to (0 .. LTC_FORTUNA_POOLS) + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int fortuna_add_random_event(unsigned long source, unsigned long pool, const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + LTC_ARGCHK(source <= 255); + LTC_ARGCHK(pool < LTC_FORTUNA_POOLS); + + LTC_MUTEX_LOCK(&prng->lock); + + err = s_fortuna_add(source, pool, in, inlen, prng); + + LTC_MUTEX_UNLOCK(&prng->lock); + + return err; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + + err = s_fortuna_add(0, prng->u.fortuna.pool_idx, in, inlen, prng); + + if (err == CRYPT_OK) { + ++(prng->u.fortuna.pool_idx); + prng->u.fortuna.pool_idx %= LTC_FORTUNA_POOLS; + } + + LTC_MUTEX_UNLOCK(&prng->lock); + + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int fortuna_ready(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + /* make sure the reseed doesn't fail because + * of the chosen rate limit */ +#ifdef LTC_FORTUNA_RESEED_RATELIMIT_TIMED + prng->u.fortuna.wd = s_fortuna_current_time() - 1; +#else + prng->u.fortuna.wd = LTC_FORTUNA_WD; +#endif + err = s_fortuna_reseed(prng); + prng->ready = (err == CRYPT_OK) ? 1 : 0; + + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + unsigned char tmp[16]; + unsigned long tlen = 0; + + if (outlen == 0 || prng == NULL || out == NULL) return 0; + + LTC_MUTEX_LOCK(&prng->lock); + + if (!prng->ready) { + goto LBL_UNLOCK; + } + + /* do we have to reseed? */ + if (prng->u.fortuna.pool0_len >= 64) { + if (s_fortuna_reseed(prng) != CRYPT_OK) { + goto LBL_UNLOCK; + } + } + + /* ensure that one reseed happened before allowing to read */ + if (prng->u.fortuna.reset_cnt == 0) { + goto LBL_UNLOCK; + } + + /* now generate the blocks required */ + tlen = outlen; + + /* handle whole blocks without the extra XMEMCPY */ + while (outlen >= 16) { + /* encrypt the IV and store it */ + rijndael_ecb_encrypt(prng->u.fortuna.IV, out, &prng->u.fortuna.skey); + out += 16; + outlen -= 16; + s_fortuna_update_iv(prng); + } + + /* left over bytes? */ + if (outlen > 0) { + rijndael_ecb_encrypt(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey); + XMEMCPY(out, tmp, outlen); + s_fortuna_update_iv(prng); + } + + /* generate new key */ + rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K , &prng->u.fortuna.skey); + s_fortuna_update_iv(prng); + + rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey); + s_fortuna_update_iv(prng); + + if (rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) { + tlen = 0; + } + +LBL_UNLOCK: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + LTC_MUTEX_UNLOCK(&prng->lock); + return tlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int fortuna_done(prng_state *prng) +{ + int err, x; + unsigned char tmp[32]; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + + /* terminate all the hashes */ + for (x = 0; x < LTC_FORTUNA_POOLS; x++) { + if ((err = sha256_done(&(prng->u.fortuna.pool[x]), tmp)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + } + /* call cipher done when we invent one ;-) */ + err = CRYPT_OK; /* success */ + +LBL_UNLOCK: +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&prng->lock); + return err; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +LTC_PRNG_EXPORT(fortuna) + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + if (inlen < (unsigned long)fortuna_desc.export_size) { + return CRYPT_INVALID_ARG; + } + + if ((err = fortuna_start(prng)) != CRYPT_OK) { + return err; + } + + if ((err = fortuna_update_seed(in, inlen, prng)) != CRYPT_OK) { + return err; + } + + return err; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int fortuna_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + int err; + + if ((err = sha256_test()) != CRYPT_OK) { + return err; + } + return rijndael_test(); +#endif +} + +#endif + diff --git a/deps/libtomcrypt/src/prngs/rc4.c b/deps/libtomcrypt/src/prngs/rc4.c new file mode 100644 index 0000000..edcd73f --- /dev/null +++ b/deps/libtomcrypt/src/prngs/rc4.c @@ -0,0 +1,221 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file prngs/rc4.c + RC4 PRNG, Tom St Denis +*/ + +#ifdef LTC_RC4 + +const struct ltc_prng_descriptor rc4_desc = +{ + "rc4", + 32, + &rc4_start, + &rc4_add_entropy, + &rc4_ready, + &rc4_read, + &rc4_done, + &rc4_export, + &rc4_import, + &rc4_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int rc4_start(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + /* set entropy (key) size to zero */ + prng->u.rc4.s.x = 0; + /* clear entropy (key) buffer */ + XMEMSET(&prng->u.rc4.s.buf, 0, sizeof(prng->u.rc4.s.buf)); + LTC_MUTEX_INIT(&prng->lock) + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char buf[256]; + unsigned long i; + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { + /* rc4_ready() was already called, do "rekey" operation */ + if ((err = rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; + /* initialize RC4 */ + if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ + for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); + zeromem(buf, sizeof(buf)); + } + else { + /* rc4_ready() was not called yet, add entropy to the buffer */ + while (inlen--) prng->u.rc4.s.buf[prng->u.rc4.s.x++ % sizeof(prng->u.rc4.s.buf)] ^= *in++; + } + err = CRYPT_OK; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int rc4_ready(prng_state *prng) +{ + unsigned char buf[256] = { 0 }; + unsigned long len; + int err, i; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } + XMEMCPY(buf, prng->u.rc4.s.buf, sizeof(buf)); + /* initialize RC4 */ + len = MIN(prng->u.rc4.s.x, 256); /* TODO: we can perhaps always use all 256 bytes */ + if ((err = rc4_stream_setup(&prng->u.rc4.s, buf, len)) != CRYPT_OK) goto LBL_UNLOCK; + /* drop first 3072 bytes - https://en.wikipedia.org/wiki/RC4#Fluhrer.2C_Mantin_and_Shamir_attack */ + for (i = 0; i < 12; i++) rc4_stream_keystream(&prng->u.rc4.s, buf, sizeof(buf)); + prng->ready = 1; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + LTC_MUTEX_LOCK(&prng->lock); + if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } + if (rc4_stream_keystream(&prng->u.rc4.s, out, outlen) != CRYPT_OK) outlen = 0; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int rc4_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + err = rc4_stream_done(&prng->u.rc4.s); + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&prng->lock); + return err; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +LTC_PRNG_EXPORT(rc4) + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + if (inlen < (unsigned long)rc4_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = rc4_start(prng)) != CRYPT_OK) return err; + if ((err = rc4_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int rc4_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; + unsigned char dmp[500]; + unsigned long dmplen = sizeof(dmp); + unsigned char out[1000]; + unsigned char t1[] = { 0xE0, 0x4D, 0x9A, 0xF6, 0xA8, 0x9D, 0x77, 0x53, 0xAE, 0x09 }; + unsigned char t2[] = { 0xEF, 0x80, 0xA2, 0xE6, 0x50, 0x91, 0xF3, 0x17, 0x4A, 0x8A }; + unsigned char t3[] = { 0x4B, 0xD6, 0x5C, 0x67, 0x99, 0x03, 0x56, 0x12, 0x80, 0x48 }; + int err; + + if ((err = rc4_start(&st)) != CRYPT_OK) return err; + /* add entropy to uninitialized prng */ + if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = rc4_ready(&st)) != CRYPT_OK) return err; + if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t1, sizeof(t1), "RC4-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + /* add entropy to already initialized prng */ + if ((err = rc4_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = rc4_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t2, sizeof(t2), "RC4-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; + if ((err = rc4_done(&st)) != CRYPT_OK) return err; + if ((err = rc4_import(dmp, dmplen, &st)) != CRYPT_OK) return err; + if ((err = rc4_ready(&st)) != CRYPT_OK) return err; + if (rc4_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (rc4_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t3, sizeof(t3), "RC4-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; + if ((err = rc4_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/prngs/rng_get_bytes.c b/deps/libtomcrypt/src/prngs/rng_get_bytes.c new file mode 100644 index 0000000..b07238e --- /dev/null +++ b/deps/libtomcrypt/src/prngs/rng_get_bytes.c @@ -0,0 +1,152 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_RNG_GET_BYTES +/** + @file rng_get_bytes.c + portable way to get secure random bits to feed a PRNG (Tom St Denis) +*/ + +#if defined(LTC_DEVRANDOM) && !defined(_WIN32) +/* on *NIX read /dev/random */ +static unsigned long s_rng_nix(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ +#ifdef LTC_NO_FILE + LTC_UNUSED_PARAM(callback); + LTC_UNUSED_PARAM(buf); + LTC_UNUSED_PARAM(len); + return 0; +#else + FILE *f; + unsigned long x; + LTC_UNUSED_PARAM(callback); +#ifdef LTC_TRY_URANDOM_FIRST + f = fopen("/dev/urandom", "rb"); + if (f == NULL) { + f = fopen("/dev/random", "rb"); + } +#else + f = fopen("/dev/random", "rb"); +#endif /* LTC_TRY_URANDOM_FIRST */ + + if (f == NULL) { + return 0; + } + + /* disable buffering */ + if (setvbuf(f, NULL, _IONBF, 0) != 0) { + fclose(f); + return 0; + } + + x = (unsigned long)fread(buf, 1, (size_t)len, f); + fclose(f); + return x; +#endif /* LTC_NO_FILE */ +} + +#endif /* LTC_DEVRANDOM */ + +#if !defined(_WIN32_WCE) + +#define ANSI_RNG + +static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + clock_t t1; + int l, acc, bits, a, b; + + l = len; + bits = 8; + acc = a = b = 0; + while (len--) { + if (callback != NULL) callback(); + while (bits--) { + do { + t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; + t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; + } while (a == b); + acc = (acc << 1) | a; + } + *buf++ = acc; + acc = 0; + bits = 8; + } + return l; +} + +#endif + +/* Try the Microsoft CSP */ +#if defined(_WIN32) || defined(_WIN32_WCE) +#ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0400 +#endif +#ifdef _WIN32_WCE + #define UNDER_CE + #define ARM +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static unsigned long s_rng_win32(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + HCRYPTPROV hProv = 0; + LTC_UNUSED_PARAM(callback); + if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && + !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) + return 0; + + if (CryptGenRandom(hProv, len, buf) == TRUE) { + CryptReleaseContext(hProv, 0); + return len; + } else { + CryptReleaseContext(hProv, 0); + return 0; + } +} + +#endif /* WIN32 */ + +/** + Read the system RNG + @param out Destination + @param outlen Length desired (octets) + @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL + @return Number of octets read +*/ +unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, + void (*callback)(void)) +{ + unsigned long x; + + LTC_ARGCHK(out != NULL); + +#ifdef LTC_PRNG_ENABLE_LTC_RNG + if (ltc_rng) { + x = ltc_rng(out, outlen, callback); + if (x != 0) { + return x; + } + } +#endif + +#if defined(_WIN32) || defined(_WIN32_WCE) + x = s_rng_win32(out, outlen, callback); if (x != 0) { return x; } +#elif defined(LTC_DEVRANDOM) + x = s_rng_nix(out, outlen, callback); if (x != 0) { return x; } +#endif +#ifdef ANSI_RNG + x = s_rng_ansic(out, outlen, callback); if (x != 0) { return x; } +#endif + return 0; +} +#endif /* #ifdef LTC_RNG_GET_BYTES */ diff --git a/deps/libtomcrypt/src/prngs/rng_make_prng.c b/deps/libtomcrypt/src/prngs/rng_make_prng.c new file mode 100644 index 0000000..a7b726c --- /dev/null +++ b/deps/libtomcrypt/src/prngs/rng_make_prng.c @@ -0,0 +1,81 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +#ifdef LTC_RNG_MAKE_PRNG +/** + @file rng_make_prng.c + portable way to get secure random bits to feed a PRNG (Tom St Denis) +*/ + +/** + Create a PRNG from a RNG + + In case you pass bits as '-1' the PRNG will be setup + as if the export/import functionality has been used, + but the imported data comes directly from the RNG. + + @param bits Number of bits of entropy desired (-1 or 64 ... 1024) + @param wprng Index of which PRNG to setup + @param prng [out] PRNG state to initialize + @param callback A pointer to a void function for when the RNG is slow, this can be NULL + @return CRYPT_OK if successful +*/ +int rng_make_prng(int bits, int wprng, prng_state *prng, + void (*callback)(void)) +{ + unsigned char* buf; + unsigned long bytes; + int err; + + LTC_ARGCHK(prng != NULL); + + /* check parameter */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (bits == -1) { + bytes = prng_descriptor[wprng].export_size; + } else if (bits < 64 || bits > 1024) { + return CRYPT_INVALID_PRNGSIZE; + } else { + bytes = (unsigned long)((bits+7)/8) * 2; + } + + if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { + return err; + } + + buf = XMALLOC(bytes); + if (buf == NULL) { + return CRYPT_MEM; + } + + if (rng_get_bytes(buf, bytes, callback) != bytes) { + err = CRYPT_ERROR_READPRNG; + goto LBL_ERR; + } + + if (bits == -1) { + if ((err = prng_descriptor[wprng].pimport(buf, bytes, prng)) != CRYPT_OK) { + goto LBL_ERR; + } + } else { + if ((err = prng_descriptor[wprng].add_entropy(buf, bytes, prng)) != CRYPT_OK) { + goto LBL_ERR; + } + } + if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { + goto LBL_ERR; + } + +LBL_ERR: + #ifdef LTC_CLEAN_STACK + zeromem(buf, bytes); + #endif + XFREE(buf); + return err; +} +#endif /* #ifdef LTC_RNG_MAKE_PRNG */ + diff --git a/deps/libtomcrypt/src/prngs/sober128.c b/deps/libtomcrypt/src/prngs/sober128.c new file mode 100644 index 0000000..6454578 --- /dev/null +++ b/deps/libtomcrypt/src/prngs/sober128.c @@ -0,0 +1,220 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file prngs/sober128.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +const struct ltc_prng_descriptor sober128_desc = +{ + "sober128", + 40, + &sober128_start, + &sober128_add_entropy, + &sober128_ready, + &sober128_read, + &sober128_done, + &sober128_export, + &sober128_import, + &sober128_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int sober128_start(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); + prng->u.sober128.idx = 0; + LTC_MUTEX_INIT(&prng->lock) + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char buf[40]; + unsigned long i; + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { + /* sober128_ready() was already called, do "rekey" operation */ + if ((err = sober128_stream_keystream(&prng->u.sober128.s, buf, sizeof(buf))) != CRYPT_OK) goto LBL_UNLOCK; + for(i = 0; i < inlen; i++) buf[i % sizeof(buf)] ^= in[i]; + /* key 32 bytes, 20 rounds */ + if ((err = sober128_stream_setup(&prng->u.sober128.s, buf, 32)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = sober128_stream_setiv(&prng->u.sober128.s, buf + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; + /* clear KEY + IV */ + zeromem(buf, sizeof(buf)); + } + else { + /* sober128_ready() was not called yet, add entropy to ent buffer */ + while (inlen--) prng->u.sober128.ent[prng->u.sober128.idx++ % sizeof(prng->u.sober128.ent)] ^= *in++; + } + err = CRYPT_OK; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int sober128_ready(prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + if (prng->ready) { err = CRYPT_OK; goto LBL_UNLOCK; } + /* key 32 bytes, 20 rounds */ + if ((err = sober128_stream_setup(&prng->u.sober128.s, prng->u.sober128.ent, 32)) != CRYPT_OK) goto LBL_UNLOCK; + /* iv 8 bytes */ + if ((err = sober128_stream_setiv(&prng->u.sober128.s, prng->u.sober128.ent + 32, 8)) != CRYPT_OK) goto LBL_UNLOCK; + XMEMSET(&prng->u.sober128.ent, 0, sizeof(prng->u.sober128.ent)); + prng->u.sober128.idx = 0; + prng->ready = 1; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + LTC_MUTEX_LOCK(&prng->lock); + if (!prng->ready) { outlen = 0; goto LBL_UNLOCK; } + if (sober128_stream_keystream(&prng->u.sober128.s, out, outlen) != CRYPT_OK) outlen = 0; +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int sober128_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + err = sober128_stream_done(&prng->u.sober128.s); + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&prng->lock); + return err; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +LTC_PRNG_EXPORT(sober128) + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + if (inlen < (unsigned long)sober128_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = sober128_start(prng)) != CRYPT_OK) return err; + if ((err = sober128_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int sober128_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32 }; + unsigned char dmp[300]; + unsigned long dmplen = sizeof(dmp); + unsigned char out[500]; + unsigned char t1[] = { 0x31, 0x82, 0xA7, 0xA5, 0x8B, 0xD7, 0xCB, 0x39, 0x86, 0x1A }; + unsigned char t2[] = { 0x6B, 0x43, 0x9E, 0xBC, 0xE7, 0x62, 0x9B, 0xE6, 0x9B, 0x83 }; + unsigned char t3[] = { 0x4A, 0x0E, 0x6C, 0xC1, 0xCF, 0xB4, 0x73, 0x49, 0x99, 0x05 }; + int err; + + if ((err = sober128_start(&st)) != CRYPT_OK) return err; + /* add entropy to uninitialized prng */ + if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = sober128_ready(&st)) != CRYPT_OK) return err; + if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t1, sizeof(t1), "SOBER128-PRNG", 1)) return CRYPT_FAIL_TESTVECTOR; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + /* add entropy to already initialized prng */ + if ((err = sober128_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = sober128_export(dmp, &dmplen, &st)) != CRYPT_OK) return err; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t2, sizeof(t2), "SOBER128-PRNG", 2)) return CRYPT_FAIL_TESTVECTOR; + if ((err = sober128_done(&st)) != CRYPT_OK) return err; + if ((err = sober128_import(dmp, dmplen, &st)) != CRYPT_OK) return err; + if ((err = sober128_ready(&st)) != CRYPT_OK) return err; + if (sober128_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if (sober128_read(out, 10, &st) != 10) return CRYPT_ERROR_READPRNG; /* 10 bytes for testing */ + if (compare_testvector(out, 10, t3, sizeof(t3), "SOBER128-PRNG", 3)) return CRYPT_FAIL_TESTVECTOR; + if ((err = sober128_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/prngs/sprng.c b/deps/libtomcrypt/src/prngs/sprng.c new file mode 100644 index 0000000..e404718 --- /dev/null +++ b/deps/libtomcrypt/src/prngs/sprng.c @@ -0,0 +1,152 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file sprng.c + Secure PRNG, Tom St Denis +*/ + +/* A secure PRNG using the RNG functions. Basically this is a + * wrapper that allows you to use a secure RNG as a PRNG + * in the various other functions. + */ + +#ifdef LTC_SPRNG + +const struct ltc_prng_descriptor sprng_desc = +{ + "sprng", 0, + &sprng_start, + &sprng_add_entropy, + &sprng_ready, + &sprng_read, + &sprng_done, + &sprng_export, + &sprng_import, + &sprng_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int sprng_start(prng_state *prng) +{ + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + LTC_UNUSED_PARAM(in); + LTC_UNUSED_PARAM(inlen); + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int sprng_ready(prng_state *prng) +{ + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + LTC_ARGCHK(out != NULL); + LTC_UNUSED_PARAM(prng); + return rng_get_bytes(out, outlen, NULL); +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int sprng_done(prng_state *prng) +{ + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +/* NOLINTNEXTLINE(readability-non-const-parameter) - silence clang-tidy warning */ +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(outlen != NULL); + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(prng); + + *outlen = 0; + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + LTC_UNUSED_PARAM(in); + LTC_UNUSED_PARAM(inlen); + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int sprng_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + prng_state st; + unsigned char en[] = { 0x01, 0x02, 0x03, 0x04 }; + unsigned char out[1000]; + int err; + + if ((err = sprng_start(&st)) != CRYPT_OK) return err; + if ((err = sprng_add_entropy(en, sizeof(en), &st)) != CRYPT_OK) return err; + if ((err = sprng_ready(&st)) != CRYPT_OK) return err; + if (sprng_read(out, 500, &st) != 500) return CRYPT_ERROR_READPRNG; /* skip 500 bytes */ + if ((err = sprng_done(&st)) != CRYPT_OK) return err; + + return CRYPT_OK; +#endif +} + +#endif + + + diff --git a/deps/libtomcrypt/src/prngs/yarrow.c b/deps/libtomcrypt/src/prngs/yarrow.c new file mode 100644 index 0000000..40cb46a --- /dev/null +++ b/deps/libtomcrypt/src/prngs/yarrow.c @@ -0,0 +1,323 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file yarrow.c + Yarrow PRNG, Tom St Denis +*/ + +#ifdef LTC_YARROW + +const struct ltc_prng_descriptor yarrow_desc = +{ + "yarrow", 64, + &yarrow_start, + &yarrow_add_entropy, + &yarrow_ready, + &yarrow_read, + &yarrow_done, + &yarrow_export, + &yarrow_import, + &yarrow_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int yarrow_start(prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + prng->ready = 0; + + /* these are the default hash/cipher combo used */ +#ifdef LTC_RIJNDAEL +#if LTC_YARROW_AES==0 + prng->u.yarrow.cipher = register_cipher(&rijndael_enc_desc); +#elif LTC_YARROW_AES==1 + prng->u.yarrow.cipher = register_cipher(&aes_enc_desc); +#elif LTC_YARROW_AES==2 + prng->u.yarrow.cipher = register_cipher(&rijndael_desc); +#elif LTC_YARROW_AES==3 + prng->u.yarrow.cipher = register_cipher(&aes_desc); +#endif +#elif defined(LTC_BLOWFISH) + prng->u.yarrow.cipher = register_cipher(&blowfish_desc); +#elif defined(LTC_TWOFISH) + prng->u.yarrow.cipher = register_cipher(&twofish_desc); +#elif defined(LTC_RC6) + prng->u.yarrow.cipher = register_cipher(&rc6_desc); +#elif defined(LTC_RC5) + prng->u.yarrow.cipher = register_cipher(&rc5_desc); +#elif defined(LTC_SAFERP) + prng->u.yarrow.cipher = register_cipher(&saferp_desc); +#elif defined(LTC_RC2) + prng->u.yarrow.cipher = register_cipher(&rc2_desc); +#elif defined(LTC_NOEKEON) + prng->u.yarrow.cipher = register_cipher(&noekeon_desc); +#elif defined(LTC_ANUBIS) + prng->u.yarrow.cipher = register_cipher(&anubis_desc); +#elif defined(LTC_KSEED) + prng->u.yarrow.cipher = register_cipher(&kseed_desc); +#elif defined(LTC_KHAZAD) + prng->u.yarrow.cipher = register_cipher(&khazad_desc); +#elif defined(LTC_CAST5) + prng->u.yarrow.cipher = register_cipher(&cast5_desc); +#elif defined(LTC_XTEA) + prng->u.yarrow.cipher = register_cipher(&xtea_desc); +#elif defined(LTC_SAFER) + prng->u.yarrow.cipher = register_cipher(&safer_sk128_desc); +#elif defined(LTC_DES) + prng->u.yarrow.cipher = register_cipher(&des3_desc); +#else + #error LTC_YARROW needs at least one CIPHER +#endif + if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { + return err; + } + +#ifdef LTC_SHA256 + prng->u.yarrow.hash = register_hash(&sha256_desc); +#elif defined(LTC_SHA512) + prng->u.yarrow.hash = register_hash(&sha512_desc); +#elif defined(LTC_TIGER) + prng->u.yarrow.hash = register_hash(&tiger_desc); +#elif defined(LTC_SHA1) + prng->u.yarrow.hash = register_hash(&sha1_desc); +#elif defined(LTC_RIPEMD320) + prng->u.yarrow.hash = register_hash(&rmd320_desc); +#elif defined(LTC_RIPEMD256) + prng->u.yarrow.hash = register_hash(&rmd256_desc); +#elif defined(LTC_RIPEMD160) + prng->u.yarrow.hash = register_hash(&rmd160_desc); +#elif defined(LTC_RIPEMD128) + prng->u.yarrow.hash = register_hash(&rmd128_desc); +#elif defined(LTC_MD5) + prng->u.yarrow.hash = register_hash(&md5_desc); +#elif defined(LTC_MD4) + prng->u.yarrow.hash = register_hash(&md4_desc); +#elif defined(LTC_MD2) + prng->u.yarrow.hash = register_hash(&md2_desc); +#elif defined(LTC_WHIRLPOOL) + prng->u.yarrow.hash = register_hash(&whirlpool_desc); +#else + #error LTC_YARROW needs at least one HASH +#endif + if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { + return err; + } + + /* zero the memory used */ + zeromem(prng->u.yarrow.pool, sizeof(prng->u.yarrow.pool)); + LTC_MUTEX_INIT(&prng->lock) + + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + hash_state md; + int err; + + LTC_ARGCHK(prng != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen > 0); + + LTC_MUTEX_LOCK(&prng->lock); + + if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* start the hash */ + if ((err = hash_descriptor[prng->u.yarrow.hash].init(&md)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* hash the current pool */ + if ((err = hash_descriptor[prng->u.yarrow.hash].process(&md, prng->u.yarrow.pool, + hash_descriptor[prng->u.yarrow.hash].hashsize)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* add the new entropy */ + if ((err = hash_descriptor[prng->u.yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* store result */ + err = hash_descriptor[prng->u.yarrow.hash].done(&md, prng->u.yarrow.pool); + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int yarrow_ready(prng_state *prng) +{ + int ks, err; + + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + + if ((err = hash_is_valid(prng->u.yarrow.hash)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + if ((err = cipher_is_valid(prng->u.yarrow.cipher)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + /* setup CTR mode using the "pool" as the key */ + ks = (int)hash_descriptor[prng->u.yarrow.hash].hashsize; + if ((err = cipher_descriptor[prng->u.yarrow.cipher].keysize(&ks)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + + if ((err = ctr_start(prng->u.yarrow.cipher, /* what cipher to use */ + prng->u.yarrow.pool, /* IV */ + prng->u.yarrow.pool, ks, /* KEY and key size */ + 0, /* number of rounds */ + CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ + &prng->u.yarrow.ctr)) != CRYPT_OK) { + goto LBL_UNLOCK; + } + prng->ready = 1; + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return err; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + if (outlen == 0 || prng == NULL || out == NULL) return 0; + + LTC_MUTEX_LOCK(&prng->lock); + + if (!prng->ready) { + outlen = 0; + goto LBL_UNLOCK; + } + + /* put out in predictable state first */ + zeromem(out, outlen); + + /* now randomize it */ + if (ctr_encrypt(out, out, outlen, &prng->u.yarrow.ctr) != CRYPT_OK) { + outlen = 0; + } + +LBL_UNLOCK: + LTC_MUTEX_UNLOCK(&prng->lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int yarrow_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->lock); + prng->ready = 0; + + /* call cipher done when we invent one ;-) */ + + /* we invented one */ + err = ctr_done(&prng->u.yarrow.ctr); + + LTC_MUTEX_UNLOCK(&prng->lock); + LTC_MUTEX_DESTROY(&prng->lock); + return err; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +LTC_PRNG_EXPORT(yarrow) + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + if (inlen < (unsigned long)yarrow_desc.export_size) return CRYPT_INVALID_ARG; + + if ((err = yarrow_start(prng)) != CRYPT_OK) return err; + if ((err = yarrow_add_entropy(in, inlen, prng)) != CRYPT_OK) return err; + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int yarrow_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + int err; + prng_state prng; + + if ((err = yarrow_start(&prng)) != CRYPT_OK) { + return err; + } + + /* now let's test the hash/cipher that was chosen */ + if (cipher_descriptor[prng.u.yarrow.cipher].test && + ((err = cipher_descriptor[prng.u.yarrow.cipher].test()) != CRYPT_OK)) { + return err; + } + if (hash_descriptor[prng.u.yarrow.hash].test && + ((err = hash_descriptor[prng.u.yarrow.hash].test()) != CRYPT_OK)) { + return err; + } + + return CRYPT_OK; +#endif +} + +#endif + diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_crypt.c b/deps/libtomcrypt/src/stream/chacha/chacha_crypt.c new file mode 100644 index 0000000..2798800 --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_crypt.c @@ -0,0 +1,91 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +#define QUARTERROUND(a,b,c,d) \ + x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 16); \ + x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 12); \ + x[a] += x[b]; x[d] = ROL(x[d] ^ x[a], 8); \ + x[c] += x[d]; x[b] = ROL(x[b] ^ x[c], 7); + +static void s_chacha_block(unsigned char *output, const ulong32 *input, int rounds) +{ + ulong32 x[16]; + int i; + XMEMCPY(x, input, sizeof(x)); + for (i = rounds; i > 0; i -= 2) { + QUARTERROUND(0, 4, 8,12) + QUARTERROUND(1, 5, 9,13) + QUARTERROUND(2, 6,10,14) + QUARTERROUND(3, 7,11,15) + QUARTERROUND(0, 5,10,15) + QUARTERROUND(1, 6,11,12) + QUARTERROUND(2, 7, 8,13) + QUARTERROUND(3, 4, 9,14) + } + for (i = 0; i < 16; ++i) { + x[i] += input[i]; + STORE32L(x[i], output + 4 * i); + } +} + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha + @param st The ChaCha state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int chacha_crypt(chacha_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char buf[64]; + unsigned long i, j; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(st->ivlen != 0); + + if (st->ksleft > 0) { + j = MIN(st->ksleft, inlen); + for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; + inlen -= j; + if (inlen == 0) return CRYPT_OK; + out += j; + in += j; + } + for (;;) { + s_chacha_block(buf, st->input, st->rounds); + if (st->ivlen == 8) { + /* IV-64bit, increment 64bit counter */ + if (0 == ++st->input[12] && 0 == ++st->input[13]) return CRYPT_OVERFLOW; + } + else { + /* IV-96bit, increment 32bit counter */ + if (0 == ++st->input[12]) return CRYPT_OVERFLOW; + } + if (inlen <= 64) { + for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; + st->ksleft = 64 - inlen; + for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; + return CRYPT_OK; + } + for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; + inlen -= 64; + out += 64; + in += 64; + } +} + +#endif diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_done.c b/deps/libtomcrypt/src/stream/chacha/chacha_done.c new file mode 100644 index 0000000..1dc641e --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_done.c @@ -0,0 +1,20 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Terminate and clear ChaCha state + @param st The ChaCha state + @return CRYPT_OK on success +*/ +int chacha_done(chacha_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(chacha_state)); + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_ivctr32.c b/deps/libtomcrypt/src/stream/chacha/chacha_ivctr32.c new file mode 100644 index 0000000..08416f5 --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_ivctr32.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Set IV + counter data to the ChaCha state + @param st The ChaCha20 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12) + @param counter 32bit (unsigned) initial counter value + @return CRYPT_OK on success + */ +int chacha_ivctr32(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong32 counter) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + /* 96bit IV + 32bit counter */ + LTC_ARGCHK(ivlen == 12); + + st->input[12] = counter; + LOAD32L(st->input[13], iv + 0); + LOAD32L(st->input[14], iv + 4); + LOAD32L(st->input[15], iv + 8); + st->ksleft = 0; + st->ivlen = ivlen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_ivctr64.c b/deps/libtomcrypt/src/stream/chacha/chacha_ivctr64.c new file mode 100644 index 0000000..49c5459 --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_ivctr64.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Set IV + counter data to the ChaCha state + @param st The ChaCha20 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 8) + @param counter 64bit (unsigned) initial counter value + @return CRYPT_OK on success + */ +int chacha_ivctr64(chacha_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + /* 64bit IV + 64bit counter */ + LTC_ARGCHK(ivlen == 8); + + st->input[12] = (ulong32)(counter & 0xFFFFFFFF); + st->input[13] = (ulong32)(counter >> 32); + LOAD32L(st->input[14], iv + 0); + LOAD32L(st->input[15], iv + 4); + st->ksleft = 0; + st->ivlen = ivlen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_keystream.c b/deps/libtomcrypt/src/stream/chacha/chacha_keystream.c new file mode 100644 index 0000000..b7fe688 --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_keystream.c @@ -0,0 +1,28 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Generate a stream of random bytes via ChaCha + @param st The ChaCha20 state + @param out [out] The output buffer + @param outlen The output length + @return CRYPT_OK on success + */ +int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return chacha_crypt(st, out, outlen, out); +} + +#endif diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_memory.c b/deps/libtomcrypt/src/stream/chacha/chacha_memory.c new file mode 100644 index 0000000..e73a038 --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_memory.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with ChaCha + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param rounds The number of rounds + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int chacha_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout) +{ + chacha_state st; + int err; + + LTC_ARGCHK(ivlen <= 8 || counter < 4294967296); /* 2**32 */ + + if ((err = chacha_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; + if (ivlen > 8) { + if ((err = chacha_ivctr32(&st, iv, ivlen, (ulong32)counter)) != CRYPT_OK) goto WIPE_KEY; + } else { + if ((err = chacha_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY; + } + err = chacha_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + chacha_done(&st); + return err; +} + +#endif /* LTC_CHACHA */ diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_setup.c b/deps/libtomcrypt/src/stream/chacha/chacha_setup.c new file mode 100644 index 0000000..6089607 --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_setup.c @@ -0,0 +1,57 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +static const char * const sigma = "expand 32-byte k"; +static const char * const tau = "expand 16-byte k"; + +/** + Initialize an ChaCha context (only the key) + @param st [out] The destination of the ChaCha state + @param key The secret key + @param keylen The length of the secret key (octets) + @param rounds Number of rounds (e.g. 20 for ChaCha20) + @return CRYPT_OK if successful +*/ +int chacha_setup(chacha_state *st, const unsigned char *key, unsigned long keylen, int rounds) +{ + const char *constants; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32 || keylen == 16); + + if (rounds == 0) rounds = 20; + + LOAD32L(st->input[4], key + 0); + LOAD32L(st->input[5], key + 4); + LOAD32L(st->input[6], key + 8); + LOAD32L(st->input[7], key + 12); + if (keylen == 32) { /* 256bit */ + key += 16; + constants = sigma; + } else { /* 128bit */ + constants = tau; + } + LOAD32L(st->input[8], key + 0); + LOAD32L(st->input[9], key + 4); + LOAD32L(st->input[10], key + 8); + LOAD32L(st->input[11], key + 12); + LOAD32L(st->input[0], constants + 0); + LOAD32L(st->input[1], constants + 4); + LOAD32L(st->input[2], constants + 8); + LOAD32L(st->input[3], constants + 12); + st->rounds = rounds; /* e.g. 20 for chacha20 */ + st->ivlen = 0; /* will be set later by chacha_ivctr(32|64) */ + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/chacha/chacha_test.c b/deps/libtomcrypt/src/stream/chacha/chacha_test.c new file mode 100644 index 0000000..cdd5f4f --- /dev/null +++ b/deps/libtomcrypt/src/stream/chacha/chacha_test.c @@ -0,0 +1,74 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_CHACHA + +int chacha_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned long len; + unsigned char out[1000]; + /* https://tools.ietf.org/html/rfc7539#section-2.4.2 */ + unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; + unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 }; + unsigned char ct[] = { 0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80, 0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81, + 0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2, 0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B, + 0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB, 0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57, + 0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB, 0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8, + 0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61, 0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E, + 0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06, 0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36, + 0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6, 0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42, + 0x87, 0x4D }; + char pt[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it."; + chacha_state st; + int err; + + len = XSTRLEN(pt); + + /* crypt piece by piece - using chacha_ivctr32() */ + if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; + if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt, 35, out )) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 35, 35, out + 35)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 70, 5, out + 70)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 75, 5, out + 75)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt + 80, len - 80, out + 80)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using chacha_ivctr32() */ + if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; + if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using chacha_ivctr64() */ + if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK) return err; + if ((err = chacha_ivctr64(&st, n + 4, sizeof(n) - 4, 1)) != CRYPT_OK) return err; + if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call using 32-bit counter with a value of 1 */ + if ((err = chacha_memory(k, sizeof(k), 20, + n, sizeof(n), 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call using 64-bit counter with a value of 1 */ + if ((err = chacha_memory(k, sizeof(k), 20, + n + 4, sizeof(n) - 4, 1, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/stream/rabbit/rabbit.c b/deps/libtomcrypt/src/stream/rabbit/rabbit.c new file mode 100644 index 0000000..075f4c0 --- /dev/null +++ b/deps/libtomcrypt/src/stream/rabbit/rabbit.c @@ -0,0 +1,447 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/****************************************************************************** + * This Rabbit C source code was morphed fm the EU eSTREAM ECRYPT submission + * and should run on any conforming C implementation (C90 or later). + * + * This implementation supports any key length up to 128 bits (16 bytes) and + * works in increments of 8-bit bytes. Keys must be submitted as whole bytes + * and shorter keys will be right-null-padded to 16 bytes. Likewise, an iv + * may be any length up to 8 bytes and will be padded out to 8 bytes. + * + * The eSTREAM submission was rather picky about the calling sequence of + * ECRYPT_process_blocks() and ECRYPT_process_bytes(). That version allowed + * calling ECRYPT_process_blocks() multiple times for a multiple of whole + * 16-byte blocks, but once ECRYPT_process_bytes() was called. no more calls + * were supported correctly. This implementation handles the keystream + * differently and rabbit_crypt() may be called as many times as desired, + * crypting any number of bytes each time. + * + * http://www.ecrypt.eu.org/stream/e2-rabbit.html + * + * NB: One of the test vectors distributed by the eSTREAM site in the file + * "rabbit_p3source.zip" is in error. Referring to "test-vectors.txt" + * in that ZIP file, the 3rd line in "out1" should be + * "96 D6 73 16 88 D1 68 DA 51 D4 0C 70 C3 A1 16 F4". + * + * Here is the original legal notice accompanying the Rabbit submission + * to the EU eSTREAM competition. + *--------------------------------------------------------------------------- + * Copyright (C) Cryptico A/S. All rights reserved. + * + * YOU SHOULD CAREFULLY READ THIS LEGAL NOTICE BEFORE USING THIS SOFTWARE. + * + * This software is developed by Cryptico A/S and/or its suppliers. + * All title and intellectual property rights in and to the software, + * including but not limited to patent rights and copyrights, are owned + * by Cryptico A/S and/or its suppliers. + * + * The software may be used solely for non-commercial purposes + * without the prior written consent of Cryptico A/S. For further + * information on licensing terms and conditions please contact + * Cryptico A/S at info@cryptico.com + * + * Cryptico, CryptiCore, the Cryptico logo and "Re-thinking encryption" + * are either trademarks or registered trademarks of Cryptico A/S. + * + * Cryptico A/S shall not in any way be liable for any use of this + * software. The software is provided "as is" without any express or + * implied warranty. + *--------------------------------------------------------------------------- + * On October 6, 2008, Rabbit was "released into the public domain and + * may be used freely for any purpose." + * http://www.ecrypt.eu.org/stream/rabbitpf.html + * https://web.archive.org/web/20090630021733/http://www.ecrypt.eu.org/stream/phorum/read.php?1,1244 + ******************************************************************************/ + + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +/* local/private prototypes (NB: rabbit_ctx and rabbit_state are different) */ +static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x); +static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance); +static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out); + +/* -------------------------------------------------------------------------- */ + +/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ +/* the upper 32 bits XOR the lower 32 bits */ +static LTC_INLINE ulong32 ss_rabbit_g_func(ulong32 x) +{ + ulong32 a, b, h, l; + + /* Construct high and low argument for squaring */ + a = x & 0xFFFF; + b = x >> 16; + + /* Calculate high and low result of squaring */ + h = ((((ulong32)(a*a)>>17) + (ulong32)(a*b))>>15) + b*b; + l = x * x; + + /* Return high XOR low */ + return (ulong32)(h^l); +} + +/* -------------------------------------------------------------------------- */ + +/* Calculate the next internal state */ +static LTC_INLINE void ss_rabbit_next_state(rabbit_ctx *p_instance) +{ + ulong32 g[8], c_old[8], i; + + /* Save old counter values */ + for (i=0; i<8; i++) { + c_old[i] = p_instance->c[i]; + } + + /* Calculate new counter values */ + p_instance->c[0] = (ulong32)(p_instance->c[0] + 0x4D34D34D + p_instance->carry); + p_instance->c[1] = (ulong32)(p_instance->c[1] + 0xD34D34D3 + (p_instance->c[0] < c_old[0])); + p_instance->c[2] = (ulong32)(p_instance->c[2] + 0x34D34D34 + (p_instance->c[1] < c_old[1])); + p_instance->c[3] = (ulong32)(p_instance->c[3] + 0x4D34D34D + (p_instance->c[2] < c_old[2])); + p_instance->c[4] = (ulong32)(p_instance->c[4] + 0xD34D34D3 + (p_instance->c[3] < c_old[3])); + p_instance->c[5] = (ulong32)(p_instance->c[5] + 0x34D34D34 + (p_instance->c[4] < c_old[4])); + p_instance->c[6] = (ulong32)(p_instance->c[6] + 0x4D34D34D + (p_instance->c[5] < c_old[5])); + p_instance->c[7] = (ulong32)(p_instance->c[7] + 0xD34D34D3 + (p_instance->c[6] < c_old[6])); + p_instance->carry = (p_instance->c[7] < c_old[7]); + + /* Calculate the g-values */ + for (i=0;i<8;i++) { + g[i] = ss_rabbit_g_func((ulong32)(p_instance->x[i] + p_instance->c[i])); + } + + /* Calculate new state values */ + p_instance->x[0] = (ulong32)(g[0] + ROLc(g[7],16) + ROLc(g[6], 16)); + p_instance->x[1] = (ulong32)(g[1] + ROLc(g[0], 8) + g[7]); + p_instance->x[2] = (ulong32)(g[2] + ROLc(g[1],16) + ROLc(g[0], 16)); + p_instance->x[3] = (ulong32)(g[3] + ROLc(g[2], 8) + g[1]); + p_instance->x[4] = (ulong32)(g[4] + ROLc(g[3],16) + ROLc(g[2], 16)); + p_instance->x[5] = (ulong32)(g[5] + ROLc(g[4], 8) + g[3]); + p_instance->x[6] = (ulong32)(g[6] + ROLc(g[5],16) + ROLc(g[4], 16)); + p_instance->x[7] = (ulong32)(g[7] + ROLc(g[6], 8) + g[5]); +} + +/* ------------------------------------------------------------------------- */ + +static LTC_INLINE void ss_rabbit_gen_1_block(rabbit_state* st, unsigned char *out) +{ + ulong32 *ptr; + + /* Iterate the work context once */ + ss_rabbit_next_state(&(st->work_ctx)); + + /* Generate 16 bytes of pseudo-random data */ + ptr = (ulong32*)&(st->work_ctx.x); + STORE32L((ptr[0] ^ (ptr[5]>>16) ^ (ulong32)(ptr[3]<<16)), out+ 0); + STORE32L((ptr[2] ^ (ptr[7]>>16) ^ (ulong32)(ptr[5]<<16)), out+ 4); + STORE32L((ptr[4] ^ (ptr[1]>>16) ^ (ulong32)(ptr[7]<<16)), out+ 8); + STORE32L((ptr[6] ^ (ptr[3]>>16) ^ (ulong32)(ptr[1]<<16)), out+12); +} + +/* -------------------------------------------------------------------------- */ + +/* Key setup */ +int rabbit_setup(rabbit_state* st, const unsigned char *key, unsigned long keylen) +{ + ulong32 k0, k1, k2, k3, i; + unsigned char tmpkey[16] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen <= 16); + + /* init state */ + XMEMSET(st, 0, sizeof(rabbit_state)); + + /* pad key in tmpkey */ + XMEMCPY(tmpkey, key, keylen); + + /* Generate four subkeys */ + LOAD32L(k0, tmpkey+ 0); + LOAD32L(k1, tmpkey+ 4); + LOAD32L(k2, tmpkey+ 8); + LOAD32L(k3, tmpkey+12); + +#ifdef LTC_CLEAN_STACK + /* done with tmpkey, wipe it */ + zeromem(tmpkey, sizeof(tmpkey)); +#endif + + /* Generate initial state variables */ + st->master_ctx.x[0] = k0; + st->master_ctx.x[2] = k1; + st->master_ctx.x[4] = k2; + st->master_ctx.x[6] = k3; + st->master_ctx.x[1] = (ulong32)(k3<<16) | (k2>>16); + st->master_ctx.x[3] = (ulong32)(k0<<16) | (k3>>16); + st->master_ctx.x[5] = (ulong32)(k1<<16) | (k0>>16); + st->master_ctx.x[7] = (ulong32)(k2<<16) | (k1>>16); + + /* Generate initial counter values */ + st->master_ctx.c[0] = ROLc(k2, 16); + st->master_ctx.c[2] = ROLc(k3, 16); + st->master_ctx.c[4] = ROLc(k0, 16); + st->master_ctx.c[6] = ROLc(k1, 16); + st->master_ctx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); + st->master_ctx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); + st->master_ctx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); + st->master_ctx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); + + /* Clear carry bit */ + st->master_ctx.carry = 0; + + /* Iterate the master context four times */ + for (i=0; i<4; i++) { + ss_rabbit_next_state(&(st->master_ctx)); + } + + /* Modify the counters */ + for (i=0; i<8; i++) { + st->master_ctx.c[i] ^= st->master_ctx.x[(i+4)&0x7]; + } + + /* Copy master instance to work instance */ + for (i=0; i<8; i++) { + st->work_ctx.x[i] = st->master_ctx.x[i]; + st->work_ctx.c[i] = st->master_ctx.c[i]; + } + st->work_ctx.carry = st->master_ctx.carry; + /* ...and prepare block for crypt() */ + XMEMSET(&(st->block), 0, sizeof(st->block)); + st->unused = 0; + + return CRYPT_OK; +} + +/* -------------------------------------------------------------------------- */ + +/* IV setup */ +int rabbit_setiv(rabbit_state* st, const unsigned char *iv, unsigned long ivlen) +{ + ulong32 i0, i1, i2, i3, i; + unsigned char tmpiv[8] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL || ivlen == 0); + LTC_ARGCHK(ivlen <= 8); + + /* pad iv in tmpiv */ + if (iv && ivlen > 0) XMEMCPY(tmpiv, iv, ivlen); + + /* Generate four subvectors */ + LOAD32L(i0, tmpiv+0); + LOAD32L(i2, tmpiv+4); + i1 = (i0>>16) | (i2&0xFFFF0000); + i3 = (i2<<16) | (i0&0x0000FFFF); + + /* Modify counter values */ + st->work_ctx.c[0] = st->master_ctx.c[0] ^ i0; + st->work_ctx.c[1] = st->master_ctx.c[1] ^ i1; + st->work_ctx.c[2] = st->master_ctx.c[2] ^ i2; + st->work_ctx.c[3] = st->master_ctx.c[3] ^ i3; + st->work_ctx.c[4] = st->master_ctx.c[4] ^ i0; + st->work_ctx.c[5] = st->master_ctx.c[5] ^ i1; + st->work_ctx.c[6] = st->master_ctx.c[6] ^ i2; + st->work_ctx.c[7] = st->master_ctx.c[7] ^ i3; + + /* Copy state variables */ + for (i=0; i<8; i++) { + st->work_ctx.x[i] = st->master_ctx.x[i]; + } + st->work_ctx.carry = st->master_ctx.carry; + + /* Iterate the work context four times */ + for (i=0; i<4; i++) { + ss_rabbit_next_state(&(st->work_ctx)); + } + + /* reset keystream buffer and unused count */ + XMEMSET(&(st->block), 0, sizeof(st->block)); + st->unused = 0; + + return CRYPT_OK; +} + +/* ------------------------------------------------------------------------- */ + +/* Crypt a chunk of any size (encrypt/decrypt) */ +int rabbit_crypt(rabbit_state* st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char buf[16]; + unsigned long i, j; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if (st->unused > 0) { + j = MIN(st->unused, inlen); + for (i = 0; i < j; ++i, st->unused--) out[i] = in[i] ^ st->block[16 - st->unused]; + inlen -= j; + if (inlen == 0) return CRYPT_OK; + out += j; + in += j; + } + for (;;) { + /* gen a block for buf */ + ss_rabbit_gen_1_block(st, buf); + if (inlen <= 16) { + /* XOR and send to out */ + for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; + st->unused = 16 - inlen; + /* copy remainder to block */ + for (i = inlen; i < 16; ++i) st->block[i] = buf[i]; + return CRYPT_OK; + } + /* XOR entire buf and send to out */ + for (i = 0; i < 16; ++i) out[i] = in[i] ^ buf[i]; + inlen -= 16; + out += 16; + in += 16; + } +} + +/* ------------------------------------------------------------------------- */ + +int rabbit_keystream(rabbit_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(out != NULL); + + XMEMSET(out, 0, outlen); + return rabbit_crypt(st, out, outlen, out); +} + +/* -------------------------------------------------------------------------- */ + +int rabbit_done(rabbit_state *st) +{ + LTC_ARGCHK(st != NULL); + + zeromem(st, sizeof(rabbit_state)); + return CRYPT_OK; +} + +/* -------------------------------------------------------------------------- */ + +int rabbit_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + rabbit_state st; + int err; + unsigned char out[1000] = { 0 }; + { + /* all 3 tests use key and iv fm set 6, vector 3, the last vector in: + http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/rabbit/verified.test-vectors?rev=210&view=log + */ + + /* --- Test 1 (generate whole blocks) --------------------------------- */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[64] = { 0 }; + unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, + 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, + 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, + 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, + 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D, 0x7C, + 0x0C, 0x10, 0x9B, 0x79, 0xD5, 0x74, 0x94, 0x39, + 0xB7, 0xEF, 0xA4, 0xC4, 0xC9, 0xC8, 0xD2, 0x9D, + 0xC5, 0xB3, 0x88, 0x83, 0x14, 0xA6, 0x81, 0x6F }; + unsigned long ptlen = sizeof(pt); + + /* crypt 64 nulls */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, ptlen, out)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + /* --- Test 2 (generate unusual number of bytes each time) ------------ */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[39] = { 0 }; + unsigned char ct[] = { 0x61, 0x3C, 0xB0, 0xBA, 0x96, 0xAF, 0xF6, 0xCA, + 0xCF, 0x2A, 0x45, 0x9A, 0x10, 0x2A, 0x7F, 0x78, + 0xCA, 0x98, 0x5C, 0xF8, 0xFD, 0xD1, 0x47, 0x40, + 0x18, 0x75, 0x8E, 0x36, 0xAE, 0x99, 0x23, 0xF5, + 0x19, 0xD1, 0x3D, 0x71, 0x8D, 0xAF, 0x8D }; + unsigned long ptlen = sizeof(pt); + + /* crypt piece by piece (hit at least one 16-byte boundary) */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 11, out + 5)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 16, 14, out + 16)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 30, 2, out + 30)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 32, 7, out + 32)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + /* --- Test 3 (use non-null data) ------------------------------------- */ + + { + unsigned char k[] = { 0x0F, 0x62, 0xB5, 0x08, 0x5B, 0xAE, 0x01, 0x54, + 0xA7, 0xFA, 0x4D, 0xA0, 0xF3, 0x46, 0x99, 0xEC }; + unsigned char iv[] = { 0x28, 0x8F, 0xF6, 0x5D, 0xC4, 0x2B, 0x92, 0xF9 }; + char pt[] = "Kilroy was here, there, and everywhere!"; + unsigned char ct[] = { 0x2a, 0x55, 0xdc, 0xc8, 0xf9, 0xd6, 0xd6, 0xbd, + 0xae, 0x59, 0x65, 0xf2, 0x75, 0x58, 0x1a, 0x54, + 0xea, 0xec, 0x34, 0x9d, 0x8f, 0xb4, 0x6b, 0x60, + 0x79, 0x1b, 0xea, 0x16, 0xcb, 0xef, 0x46, 0x87, + 0x60, 0xa6, 0x55, 0x14, 0xff, 0xca, 0xac }; + unsigned long ptlen = XSTRLEN(pt); + unsigned char out2[1000] = { 0 }; + unsigned char nulls[1000] = { 0 }; + + /* crypt piece by piece */ + if ((err = rabbit_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 5, 29, out + 5)) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, (unsigned char*)pt + 34, 5, out + 34)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* --- Test 4 (crypt in a single call) ------------------------------------ */ + + if ((err = rabbit_memory(k, sizeof(k), iv, sizeof(iv), + (unsigned char*)pt, sizeof(pt), out)) != CRYPT_OK) return err; + if (compare_testvector(out, ptlen, ct, ptlen, "RABBIT-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + /* use 'out' (ciphertext) in the next decryption test */ + + /* --- Test 5 (decrypt ciphertext) ------------------------------------ */ + + /* decrypt ct (out) and compare with pt (start with only setiv() to reset) */ + if ((err = rabbit_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = rabbit_crypt(&st, out, ptlen, out2)) != CRYPT_OK) return err; + if (compare_testvector(out2, ptlen, pt, ptlen, "RABBIT-TV5", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* --- Test 6 (wipe state, incl key) ---------------------------------- */ + + if ((err = rabbit_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(&st, sizeof(st), nulls, sizeof(st), "RABBIT-TV6", 1)) return CRYPT_FAIL_TESTVECTOR; + + } + + return CRYPT_OK; + } +#endif +} + +/* -------------------------------------------------------------------------- */ + +#endif diff --git a/deps/libtomcrypt/src/stream/rabbit/rabbit_memory.c b/deps/libtomcrypt/src/stream/rabbit/rabbit_memory.c new file mode 100644 index 0000000..fee0234 --- /dev/null +++ b/deps/libtomcrypt/src/stream/rabbit/rabbit_memory.c @@ -0,0 +1,40 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * chacha-ref.c version 20080118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RABBIT + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Rabbit + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int rabbit_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + rabbit_state st; + int err; + + if ((err = rabbit_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + if ((err = rabbit_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; + err = rabbit_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + rabbit_done(&st); + return err; +} + +#endif /* LTC_RABBIT */ diff --git a/deps/libtomcrypt/src/stream/rc4/rc4_stream.c b/deps/libtomcrypt/src/stream/rc4/rc4_stream.c new file mode 100644 index 0000000..2587764 --- /dev/null +++ b/deps/libtomcrypt/src/stream/rc4/rc4_stream.c @@ -0,0 +1,101 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +/** + Initialize an RC4 context (only the key) + @param st [out] The destination of the RC4 state + @param key The secret key + @param keylen The length of the secret key (8 - 256 bytes) + @return CRYPT_OK if successful +*/ +int rc4_stream_setup(rc4_state *st, const unsigned char *key, unsigned long keylen) +{ + unsigned char tmp, *s; + int x, y; + unsigned long j; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen >= 5); /* 40-2048 bits */ + + s = st->buf; + for (x = 0; x < 256; x++) { + s[x] = x; + } + + for (j = x = y = 0; x < 256; x++) { + y = (y + s[x] + key[j++]) & 255; + if (j == keylen) { + j = 0; + } + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + } + st->x = 0; + st->y = 0; + + return CRYPT_OK; +} + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 + @param st The RC4 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int rc4_stream_crypt(rc4_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char x, y, *s, tmp; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + x = st->x; + y = st->y; + s = st->buf; + while (inlen--) { + x = (x + 1) & 255; + y = (y + s[x]) & 255; + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + tmp = (s[x] + s[y]) & 255; + *out++ = *in++ ^ s[tmp]; + } + st->x = x; + st->y = y; + return CRYPT_OK; +} + +/** + Generate a stream of random bytes via RC4 + @param st The RC420 state + @param out [out] The output buffer + @param outlen The output length + @return CRYPT_OK on success + */ +int rc4_stream_keystream(rc4_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return rc4_stream_crypt(st, out, outlen, out); +} + +/** + Terminate and clear RC4 state + @param st The RC4 state + @return CRYPT_OK on success +*/ +int rc4_stream_done(rc4_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(rc4_state)); + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/rc4/rc4_stream_memory.c b/deps/libtomcrypt/src/stream/rc4/rc4_stream_memory.c new file mode 100644 index 0000000..efe4888 --- /dev/null +++ b/deps/libtomcrypt/src/stream/rc4/rc4_stream_memory.c @@ -0,0 +1,31 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with RC4 + @param key The key + @param keylen The key length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int rc4_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + rc4_state st; + int err; + + if ((err = rc4_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + err = rc4_stream_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + rc4_stream_done(&st); + return err; +} + +#endif /* LTC_RC4_STREAM */ diff --git a/deps/libtomcrypt/src/stream/rc4/rc4_test.c b/deps/libtomcrypt/src/stream/rc4/rc4_test.c new file mode 100644 index 0000000..d78022b --- /dev/null +++ b/deps/libtomcrypt/src/stream/rc4/rc4_test.c @@ -0,0 +1,33 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_RC4_STREAM + +int rc4_stream_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + rc4_state st; + int err; + const unsigned char key[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + const unsigned char pt[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + const unsigned char ct[] = { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 }; + unsigned char buf[10]; + + if ((err = rc4_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; + if ((err = rc4_stream_crypt(&st, pt, sizeof(pt), buf)) != CRYPT_OK) return err; + if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV1", 0)) return CRYPT_FAIL_TESTVECTOR; + if ((err = rc4_stream_done(&st)) != CRYPT_OK) return err; + + /* crypt in a single call */ + if ((err = rc4_stream_memory(key, sizeof(key), pt, sizeof(pt), buf)) != CRYPT_OK) return err; + if (compare_testvector(buf, sizeof(ct), ct, sizeof(ct), "RC4-TV2", 0)) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/salsa20_crypt.c b/deps/libtomcrypt/src/stream/salsa20/salsa20_crypt.c new file mode 100644 index 0000000..3058372 --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/salsa20_crypt.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +#define QUARTERROUND(a,b,c,d) \ + x[b] ^= (ROL((x[a] + x[d]), 7)); \ + x[c] ^= (ROL((x[b] + x[a]), 9)); \ + x[d] ^= (ROL((x[c] + x[b]), 13)); \ + x[a] ^= (ROL((x[d] + x[c]), 18)); + +static void s_salsa20_block(unsigned char *output, const ulong32 *input, int rounds) +{ + ulong32 x[16]; + int i; + XMEMCPY(x, input, sizeof(x)); + for (i = rounds; i > 0; i -= 2) { + QUARTERROUND( 0, 4, 8,12) + QUARTERROUND( 5, 9,13, 1) + QUARTERROUND(10,14, 2, 6) + QUARTERROUND(15, 3, 7,11) + QUARTERROUND( 0, 1, 2, 3) + QUARTERROUND( 5, 6, 7, 4) + QUARTERROUND(10,11, 8, 9) + QUARTERROUND(15,12,13,14) + } + for (i = 0; i < 16; ++i) { + x[i] += input[i]; + STORE32L(x[i], output + 4 * i); + } +} + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 + @param st The Salsa20 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int salsa20_crypt(salsa20_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + unsigned char buf[64]; + unsigned long i, j; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(st->ivlen == 8 || st->ivlen == 24); + + if (st->ksleft > 0) { + j = MIN(st->ksleft, inlen); + for (i = 0; i < j; ++i, st->ksleft--) out[i] = in[i] ^ st->kstream[64 - st->ksleft]; + inlen -= j; + if (inlen == 0) return CRYPT_OK; + out += j; + in += j; + } + for (;;) { + s_salsa20_block(buf, st->input, st->rounds); + /* Salsa20: 64-bit IV, increment 64-bit counter */ + if (0 == ++st->input[8] && 0 == ++st->input[9]) return CRYPT_OVERFLOW; + if (inlen <= 64) { + for (i = 0; i < inlen; ++i) out[i] = in[i] ^ buf[i]; + st->ksleft = 64 - inlen; + for (i = inlen; i < 64; ++i) st->kstream[i] = buf[i]; + return CRYPT_OK; + } + for (i = 0; i < 64; ++i) out[i] = in[i] ^ buf[i]; + inlen -= 64; + out += 64; + in += 64; + } +} + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/salsa20_done.c b/deps/libtomcrypt/src/stream/salsa20/salsa20_done.c new file mode 100644 index 0000000..9b8cbb6 --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/salsa20_done.c @@ -0,0 +1,20 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Terminate and clear Salsa20 state + @param st The Salsa20 state + @return CRYPT_OK on success +*/ +int salsa20_done(salsa20_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(salsa20_state)); + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c b/deps/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c new file mode 100644 index 0000000..8b25dfb --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/salsa20_ivctr64.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Set IV + counter data to the Salsa20 state + @param st The Salsa20 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 8) + @param counter 64bit (unsigned) initial counter value + @return CRYPT_OK on success + */ +int salsa20_ivctr64(salsa20_state *st, const unsigned char *iv, unsigned long ivlen, ulong64 counter) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + /* Salsa20: 64-bit IV (nonce) + 64-bit counter */ + LTC_ARGCHK(ivlen == 8); + + LOAD32L(st->input[6], iv + 0); + LOAD32L(st->input[7], iv + 4); + st->input[8] = (ulong32)(counter & 0xFFFFFFFF); + st->input[9] = (ulong32)(counter >> 32); + st->ksleft = 0; + st->ivlen = ivlen; + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/salsa20_keystream.c b/deps/libtomcrypt/src/stream/salsa20/salsa20_keystream.c new file mode 100644 index 0000000..c51d0d6 --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/salsa20_keystream.c @@ -0,0 +1,29 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Generate a stream of random bytes via Salsa20 + @param st The Salsa20 state + @param out [out] The output buffer + @param outlen The output length + @return CRYPT_OK on success + */ +int salsa20_keystream(salsa20_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return salsa20_crypt(st, out, outlen, out); +} + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/salsa20_memory.c b/deps/libtomcrypt/src/stream/salsa20/salsa20_memory.c new file mode 100644 index 0000000..9408eb2 --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/salsa20_memory.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Salsa20 + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param rounds The number of rounds + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int salsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *iv, unsigned long ivlen, ulong64 counter, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout) +{ + salsa20_state st; + int err; + + if ((err = salsa20_setup(&st, key, keylen, rounds)) != CRYPT_OK) goto WIPE_KEY; + if ((err = salsa20_ivctr64(&st, iv, ivlen, counter)) != CRYPT_OK) goto WIPE_KEY; + err = salsa20_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + salsa20_done(&st); + return err; +} + +#endif /* LTC_SALSA20 */ diff --git a/deps/libtomcrypt/src/stream/salsa20/salsa20_setup.c b/deps/libtomcrypt/src/stream/salsa20/salsa20_setup.c new file mode 100644 index 0000000..012dc95 --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/salsa20_setup.c @@ -0,0 +1,59 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +static const char * const sigma = "expand 32-byte k"; +static const char * const tau = "expand 16-byte k"; + +/** + Initialize an Salsa20 context (only the key) + @param st [out] The destination of the Salsa20 state + @param key The secret key + @param keylen The length of the secret key (octets) + @param rounds Number of rounds (e.g. 20 for Salsa20) + @return CRYPT_OK if successful +*/ +int salsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, int rounds) +{ + const char *constants; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32 || keylen == 16); + + if (rounds == 0) rounds = 20; + LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ + + LOAD32L(st->input[1], key + 0); + LOAD32L(st->input[2], key + 4); + LOAD32L(st->input[3], key + 8); + LOAD32L(st->input[4], key + 12); + if (keylen == 32) { /* 256bit */ + key += 16; + constants = sigma; + } else { /* 128bit */ + constants = tau; + } + LOAD32L(st->input[11], key + 0); + LOAD32L(st->input[12], key + 4); + LOAD32L(st->input[13], key + 8); + LOAD32L(st->input[14], key + 12); + LOAD32L(st->input[ 0], constants + 0); + LOAD32L(st->input[ 5], constants + 4); + LOAD32L(st->input[10], constants + 8); + LOAD32L(st->input[15], constants + 12); + st->rounds = rounds; /* default is 20 for salsa20 */ + st->ivlen = 0; /* will be set later by salsa20_ivctr(32|64) */ + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/salsa20_test.c b/deps/libtomcrypt/src/stream/salsa20/salsa20_test.c new file mode 100644 index 0000000..c924dbe --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/salsa20_test.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SALSA20 + +int salsa20_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + salsa20_state st; + unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; + unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a }; + unsigned char ct[] = { 0x37, 0x37, 0x2e, 0x60, 0xb8, 0xae, 0x88, 0x1f, 0xf8, 0xdf, 0x00, 0x26, 0x6c, 0x30, 0x34, 0x2d, + 0xa1, 0xd7, 0x79, 0x60, 0x67, 0x72, 0xe0, 0x67, 0x26, 0x22, 0xad, 0x00, 0x9e, 0xd5, 0x59, 0x44, + 0x51, 0xd9, 0xe6, 0xaa, 0xc9, 0x59, 0x9e, 0x60, 0xff, 0x87, 0x90, 0xc1, 0xc9, 0x1e }; + unsigned char ct2[] = { 0xec, 0x06, 0x32, 0xb3, 0x83, 0x5c, 0xae, 0x91, 0x01, 0x82, 0x7a, 0x71, 0xd9, 0x7d, 0x45, 0xd7, + 0xa6, 0x5b, 0xa0, 0x89, 0x9d, 0xd2, 0x6c, 0xaa, 0xbb, 0x2f, 0x5f, 0x30, 0x89, 0x54, 0xff, 0x3e, + 0x83, 0xc3, 0x34, 0x10, 0xb6, 0xe1, 0xab, 0xe7, 0xf5, 0xab, 0xab, 0xed, 0xa4, 0xff }; + char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ + unsigned long len; + unsigned char out[1000]; + int counter; + int rounds; + int err; + len = XSTRLEN(pt); + + /* crypt piece by piece */ + counter = 0; + rounds = 12; + if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; + if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using salsa20_ivctr64() */ + counter = 0; + rounds = 20; + if ((err = salsa20_setup(&st, k, sizeof(k), rounds)) != CRYPT_OK) return err; + if ((err = salsa20_ivctr64(&st, n, sizeof(n), counter)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call */ + if ((err = salsa20_memory(k, sizeof(k), rounds, n, sizeof(n), counter, + (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct2, sizeof(ct2), "SALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + { + /* keystream + * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?rev=161&view=markup + * Set 6, vector 0 + */ + unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, + 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; + unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE }; + unsigned char ct3[] = { 0xF5, 0xFA, 0xD5, 0x3F, 0x79, 0xF9, 0xDF, 0x58, 0xC4, 0xAE, 0xA0, 0xD0, 0xED, 0x9A, 0x96, 0x01, + 0xF2, 0x78, 0x11, 0x2C, 0xA7, 0x18, 0x0D, 0x56, 0x5B, 0x42, 0x0A, 0x48, 0x01, 0x96, 0x70, 0xEA, + 0xF2, 0x4C, 0xE4, 0x93, 0xA8, 0x62, 0x63, 0xF6, 0x77, 0xB4, 0x6A, 0xCE, 0x19, 0x24, 0x77, 0x3D, + 0x2B, 0xB2, 0x55, 0x71, 0xE1, 0xAA, 0x85, 0x93, 0x75, 0x8F, 0xC3, 0x82, 0xB1, 0x28, 0x0B, 0x71 }; + int counter3 = 0; + int rounds3 = 20; + if ((err = salsa20_setup(&st, k3, sizeof(k3), rounds3)) != CRYPT_OK) return err; + if ((err = salsa20_ivctr64(&st, n3, sizeof(n3), counter3)) != CRYPT_OK) return err; + if ((err = salsa20_keystream(&st, out, 64)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(out, 64, ct3, sizeof(ct3), "SALSA20-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c b/deps/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c new file mode 100644 index 0000000..1908cd5 --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/xsalsa20_memory.c @@ -0,0 +1,34 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_XSALSA20 + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with XSalsa20 + @param key The key + @param keylen The key length + @param nonce The initial vector + @param noncelen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param rounds The number of rounds + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int xsalsa20_memory(const unsigned char *key, unsigned long keylen, unsigned long rounds, + const unsigned char *nonce, unsigned long noncelen, + const unsigned char *datain, unsigned long datalen, unsigned char *dataout) +{ + salsa20_state st; + int err; + + if ((err = xsalsa20_setup(&st, key, keylen, nonce, noncelen, rounds)) != CRYPT_OK) goto WIPE_KEY; + err = salsa20_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + salsa20_done(&st); + return err; +} + +#endif /* LTC_XSALSA20 */ diff --git a/deps/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c b/deps/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c new file mode 100644 index 0000000..6bfac09 --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/xsalsa20_setup.c @@ -0,0 +1,127 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt.h" + +#ifdef LTC_XSALSA20 + +static const char * const constants = "expand 32-byte k"; + +#define QUARTERROUND(a,b,c,d) \ + x[b] ^= (ROL((x[a] + x[d]), 7)); \ + x[c] ^= (ROL((x[b] + x[a]), 9)); \ + x[d] ^= (ROL((x[c] + x[b]), 13)); \ + x[a] ^= (ROL((x[d] + x[c]), 18)); + +/* use modified salsa20 doubleround (no final addition as in salsa20) */ +static void s_xsalsa20_doubleround(ulong32 *x, int rounds) +{ + int i; + + for (i = rounds; i > 0; i -= 2) { + /* columnround */ + QUARTERROUND( 0, 4, 8,12) + QUARTERROUND( 5, 9,13, 1) + QUARTERROUND(10,14, 2, 6) + QUARTERROUND(15, 3, 7,11) + /* rowround */ + QUARTERROUND( 0, 1, 2, 3) + QUARTERROUND( 5, 6, 7, 4) + QUARTERROUND(10,11, 8, 9) + QUARTERROUND(15,12,13,14) + } +} + +#undef QUARTERROUND + +/** + Initialize an XSalsa20 context + @param st [out] The destination of the XSalsa20 state + @param key The secret key + @param keylen The length of the secret key, must be 32 (octets) + @param nonce The nonce + @param noncelen The length of the nonce, must be 24 (octets) + @param rounds Number of rounds (must be evenly divisible by 2, default is 20) + @return CRYPT_OK if successful +*/ +int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long keylen, + const unsigned char *nonce, unsigned long noncelen, + int rounds) +{ + const int sti[] = {0, 5, 10, 15, 6, 7, 8, 9}; /* indices used to build subkey fm x */ + ulong32 x[64]; /* input to & output fm doubleround */ + unsigned char subkey[32]; + int i; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen == 32); + LTC_ARGCHK(nonce != NULL); + LTC_ARGCHK(noncelen == 24); + if (rounds == 0) rounds = 20; + LTC_ARGCHK(rounds % 2 == 0); /* number of rounds must be evenly divisible by 2 */ + + /* load the state to "hash" the key */ + LOAD32L(x[ 0], constants + 0); + LOAD32L(x[ 5], constants + 4); + LOAD32L(x[10], constants + 8); + LOAD32L(x[15], constants + 12); + LOAD32L(x[ 1], key + 0); + LOAD32L(x[ 2], key + 4); + LOAD32L(x[ 3], key + 8); + LOAD32L(x[ 4], key + 12); + LOAD32L(x[11], key + 16); + LOAD32L(x[12], key + 20); + LOAD32L(x[13], key + 24); + LOAD32L(x[14], key + 28); + LOAD32L(x[ 6], nonce + 0); + LOAD32L(x[ 7], nonce + 4); + LOAD32L(x[ 8], nonce + 8); + LOAD32L(x[ 9], nonce + 12); + + /* use modified salsa20 doubleround (no final addition) */ + s_xsalsa20_doubleround(x, rounds); + + /* extract the subkey */ + for (i = 0; i < 8; ++i) { + STORE32L(x[sti[i]], subkey + 4 * i); + } + + /* load the final initial state */ + LOAD32L(st->input[ 0], constants + 0); + LOAD32L(st->input[ 5], constants + 4); + LOAD32L(st->input[10], constants + 8); + LOAD32L(st->input[15], constants + 12); + LOAD32L(st->input[ 1], subkey + 0); + LOAD32L(st->input[ 2], subkey + 4); + LOAD32L(st->input[ 3], subkey + 8); + LOAD32L(st->input[ 4], subkey + 12); + LOAD32L(st->input[11], subkey + 16); + LOAD32L(st->input[12], subkey + 20); + LOAD32L(st->input[13], subkey + 24); + LOAD32L(st->input[14], subkey + 28); + LOAD32L(st->input[ 6], &(nonce[16]) + 0); + LOAD32L(st->input[ 7], &(nonce[16]) + 4); + st->input[ 8] = 0; + st->input[ 9] = 0; + st->rounds = rounds; + st->ksleft = 0; + st->ivlen = 24; /* set switch to say nonce/IV has been loaded */ + +#ifdef LTC_CLEAN_STACK + zeromem(x, sizeof(x)); + zeromem(subkey, sizeof(subkey)); +#endif + + return CRYPT_OK; +} + + +#endif diff --git a/deps/libtomcrypt/src/stream/salsa20/xsalsa20_test.c b/deps/libtomcrypt/src/stream/salsa20/xsalsa20_test.c new file mode 100644 index 0000000..31522fe --- /dev/null +++ b/deps/libtomcrypt/src/stream/salsa20/xsalsa20_test.c @@ -0,0 +1,90 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* The implementation is based on: + * "Extending the Salsa20 nonce", https://cr.yp.to/snuffle/xsalsa-20081128.pdf + * "Salsa20 specification", http://cr.yp.to/snuffle/spec.pdf + * and salsa20-ref.c version 20051118 + * Public domain from D. J. Bernstein + */ + +#include "tomcrypt.h" + +#ifdef LTC_XSALSA20 + +#if defined(LTC_SHA256) && defined(LTC_TEST) +static int s_sha256(unsigned char *hash, const unsigned char *data, const int datalen) { + hash_state md; + sha256_init(&md); + sha256_process(&md, data, datalen); + sha256_done(&md, hash); + return CRYPT_OK; +} +#endif + +int xsalsa20_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + + /*************************************************************************** + * verify a round trip: + */ + { + const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; + const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; + const void *msg = "Kilroy was here!"; + unsigned char msglen = 17; /* includes trailing NULL */ + int rounds = 20; + unsigned char ciphertext[17]; + unsigned char msg2[17]; + salsa20_state st; + int err; + + if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, msg, msglen, ciphertext)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + + if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; + if ((err = salsa20_crypt(&st, ciphertext, msglen, msg2)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + + if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + + /* round trip with two single function calls */ + if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), msg, msglen, ciphertext)) != CRYPT_OK) return err; + if ((err = xsalsa20_memory(key, sizeof(key), 20, nonce, sizeof(nonce), ciphertext, msglen, msg2)) != CRYPT_OK) return err; + if (compare_testvector(msg, msglen, msg2, msglen, "XSALSA20-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + } + +#ifdef LTC_SHA256 + /*************************************************************************** + * verify correct generation of a keystream + */ + { + const unsigned char key[] = {0x1b,0x27,0x55,0x64,0x73,0xe9,0x85,0xd4,0x62,0xcd,0x51,0x19,0x7a,0x9a,0x46,0xc7,0x60,0x09,0x54,0x9e,0xac,0x64,0x74,0xf2,0x06,0xc4,0xee,0x08,0x44,0xf6,0x83,0x89}; + const unsigned char nonce[] = {0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73,0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6,0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37}; + const unsigned char expecthash[] = {0x6a,0x60,0x57,0x65,0x27,0xe0,0x00,0x51,0x6d,0xb0,0xda,0x60,0x46,0x20,0xf6,0xd0,0x95,0x65,0x45,0x39,0xf4,0x86,0x83,0x43,0x64,0xdf,0xd9,0x5a,0x6f,0x3f,0xbe,0xb7}; + int rounds = 20; + unsigned char keystream[91101]; + unsigned long keystreamlen = 91101; + unsigned char hash[32]; + salsa20_state st; + int err; + + if ((err = xsalsa20_setup(&st, key, 32, nonce, 24, rounds)) != CRYPT_OK) return err; + if ((err = salsa20_keystream(&st, keystream, keystreamlen)) != CRYPT_OK) return err; + if ((err = salsa20_done(&st)) != CRYPT_OK) return err; + if ((err = s_sha256(hash, keystream, keystreamlen)) != CRYPT_OK) return err; + if (compare_testvector(hash, sizeof(hash), expecthash, sizeof(expecthash), "XSALSA20-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + } +#endif + + return CRYPT_OK; + +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/stream/sober128/sober128_stream.c b/deps/libtomcrypt/src/stream/sober128/sober128_stream.c new file mode 100644 index 0000000..4445151 --- /dev/null +++ b/deps/libtomcrypt/src/stream/sober128/sober128_stream.c @@ -0,0 +1,333 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file sober128_stream.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef LTC_SOBER128 + +#define LTC_SOBER128TAB_C +#include "sober128tab.c" + +/* don't change these... */ +#define N 17 +#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ +#define KEYP 15 /* where to insert key words */ +#define FOLDP 4 /* where to insert non-linear feedback */ + +static ulong32 BYTE2WORD(const unsigned char *b) +{ + ulong32 t; + LOAD32L(t, b); + return t; +} + +static void XORWORD(ulong32 w, const unsigned char *in, unsigned char *out) +{ + ulong32 t; + LOAD32L(t, in); + t ^= w; + STORE32L(t, out); +} + +/* give correct offset for the current position of the register, + * where logically R[0] is at position "zero". + */ +#define OFF(zero, i) (((zero)+(i)) % N) + +/* step the LFSR */ +/* After stepping, "zero" moves right one place */ +#define STEP(R,z) \ + R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; + +static void cycle(ulong32 *R) +{ + ulong32 t; + int i; + + STEP(R,0); + t = R[0]; + for (i = 1; i < N; ++i) { + R[i-1] = R[i]; + } + R[N-1] = t; +} + +/* Return a non-linear function of some parts of the register. + */ +#define NLFUNC(st,z) \ +{ \ + t = st->R[OFF(z,0)] + st->R[OFF(z,16)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = RORc(t, 8); \ + t = ((t + st->R[OFF(z,1)]) ^ st->konst) + st->R[OFF(z,6)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = t + st->R[OFF(z,13)]; \ +} + +static ulong32 nltap(const sober128_state *st) +{ + ulong32 t; + NLFUNC(st, 0); + return t; +} + +/* Save the current register state + */ +static void s128_savestate(sober128_state *st) +{ + int i; + for (i = 0; i < N; ++i) { + st->initR[i] = st->R[i]; + } +} + +/* initialise to previously saved register state + */ +static void s128_reloadstate(sober128_state *st) +{ + int i; + + for (i = 0; i < N; ++i) { + st->R[i] = st->initR[i]; + } +} + +/* Initialise "konst" + */ +static void s128_genkonst(sober128_state *st) +{ + ulong32 newkonst; + + do { + cycle(st->R); + newkonst = nltap(st); + } while ((newkonst & 0xFF000000) == 0); + st->konst = newkonst; +} + +/* Load key material into the register + */ +#define ADDKEY(k) \ + st->R[KEYP] += (k); + +#define XORNL(nl) \ + st->R[FOLDP] ^= (nl); + +/* nonlinear diffusion of register for key */ +#define DROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); st->R[OFF((z+1),FOLDP)] ^= t; +static void s128_diffuse(sober128_state *st) +{ + ulong32 t; + /* relies on FOLD == N == 17! */ + DROUND(0); + DROUND(1); + DROUND(2); + DROUND(3); + DROUND(4); + DROUND(5); + DROUND(6); + DROUND(7); + DROUND(8); + DROUND(9); + DROUND(10); + DROUND(11); + DROUND(12); + DROUND(13); + DROUND(14); + DROUND(15); + DROUND(16); +} + +/** + Initialize an Sober128 context (only the key) + @param st [out] The destination of the Sober128 state + @param key The secret key + @param keylen The length of the secret key (octets) + @return CRYPT_OK if successful +*/ +int sober128_stream_setup(sober128_state *st, const unsigned char *key, unsigned long keylen) +{ + ulong32 i, k; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen > 0); + + /* keylen must be multiple of 4 bytes */ + if ((keylen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + /* Register initialised to Fibonacci numbers */ + st->R[0] = 1; + st->R[1] = 1; + for (i = 2; i < N; ++i) { + st->R[i] = st->R[i-1] + st->R[i-2]; + } + st->konst = INITKONST; + + for (i = 0; i < keylen; i += 4) { + k = BYTE2WORD((unsigned char *)&key[i]); + ADDKEY(k); + cycle(st->R); + XORNL(nltap(st)); + } + + /* also fold in the length of the key */ + ADDKEY(keylen); + + /* now diffuse */ + s128_diffuse(st); + s128_genkonst(st); + s128_savestate(st); + st->nbuf = 0; + + return CRYPT_OK; +} + +/** + Set IV to the Sober128 state + @param st The Sober12820 state + @param iv The IV data to add + @param ivlen The length of the IV (must be 12) + @return CRYPT_OK on success + */ +int sober128_stream_setiv(sober128_state *st, const unsigned char *iv, unsigned long ivlen) +{ + ulong32 i, k; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(iv != NULL); + LTC_ARGCHK(ivlen > 0); + + /* ok we are adding an IV then... */ + s128_reloadstate(st); + + /* ivlen must be multiple of 4 bytes */ + if ((ivlen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + for (i = 0; i < ivlen; i += 4) { + k = BYTE2WORD((unsigned char *)&iv[i]); + ADDKEY(k); + cycle(st->R); + XORNL(nltap(st)); + } + + /* also fold in the length of the key */ + ADDKEY(ivlen); + + /* now diffuse */ + s128_diffuse(st); + st->nbuf = 0; + + return CRYPT_OK; +} + +/* XOR pseudo-random bytes into buffer + */ +#define SROUND(z) STEP(st->R,z); NLFUNC(st,(z+1)); XORWORD(t, in+(z*4), out+(z*4)); + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sober128 + @param st The Sober128 state + @param in The plaintext (or ciphertext) + @param inlen The length of the input (octets) + @param out [out] The ciphertext (or plaintext), length inlen + @return CRYPT_OK if successful +*/ +int sober128_stream_crypt(sober128_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + ulong32 t; + + if (inlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(st != NULL); + + /* handle any previously buffered bytes */ + while (st->nbuf != 0 && inlen != 0) { + *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); + st->sbuf >>= 8; + st->nbuf -= 8; + --inlen; + } + +#ifndef LTC_SMALL_CODE + /* do lots at a time, if there's enough to do */ + while (inlen >= N*4) { + SROUND(0); + SROUND(1); + SROUND(2); + SROUND(3); + SROUND(4); + SROUND(5); + SROUND(6); + SROUND(7); + SROUND(8); + SROUND(9); + SROUND(10); + SROUND(11); + SROUND(12); + SROUND(13); + SROUND(14); + SROUND(15); + SROUND(16); + out += 4*N; + in += 4*N; + inlen -= 4*N; + } +#endif + + /* do small or odd size buffers the slow way */ + while (4 <= inlen) { + cycle(st->R); + t = nltap(st); + XORWORD(t, in, out); + out += 4; + in += 4; + inlen -= 4; + } + + /* handle any trailing bytes */ + if (inlen != 0) { + cycle(st->R); + st->sbuf = nltap(st); + st->nbuf = 32; + while (st->nbuf != 0 && inlen != 0) { + *out++ = *in++ ^ (unsigned char)(st->sbuf & 0xFF); + st->sbuf >>= 8; + st->nbuf -= 8; + --inlen; + } + } + + return CRYPT_OK; +} + +int sober128_stream_keystream(sober128_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return sober128_stream_crypt(st, out, outlen, out); +} + +/** + Terminate and clear Sober128 state + @param st The Sober128 state + @return CRYPT_OK on success +*/ +int sober128_stream_done(sober128_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(sober128_state)); + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/src/stream/sober128/sober128_stream_memory.c b/deps/libtomcrypt/src/stream/sober128/sober128_stream_memory.c new file mode 100644 index 0000000..5150b82 --- /dev/null +++ b/deps/libtomcrypt/src/stream/sober128/sober128_stream_memory.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOBER128_STREAM + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with SOBER128 + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int sober128_stream_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + sober128_state st; + int err; + + if ((err = sober128_stream_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + if ((err = sober128_stream_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; + err = sober128_stream_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + sober128_stream_done(&st); + return err; +} + +#endif /* LTC_SOBER128_STREAM */ diff --git a/deps/libtomcrypt/src/stream/sober128/sober128_test.c b/deps/libtomcrypt/src/stream/sober128/sober128_test.c new file mode 100644 index 0000000..52ea3a8 --- /dev/null +++ b/deps/libtomcrypt/src/stream/sober128/sober128_test.c @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOBER128 + +int sober128_stream_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + unsigned char key[16] = { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79, + 0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 }; + unsigned char iv[4] = { 0x00, 0x00, 0x00, 0x00 }; + unsigned char out[20] = { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d, + 0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2, + 0x40, 0x37, 0x8b, 0xbb }; + int err, len = 20; + unsigned char src[20], dst[20]; + sober128_state st; + + XMEMSET(src, 0, len); /* input */ + if ((err = sober128_stream_setup(&st, key, sizeof(key))) != CRYPT_OK) return err; + if ((err = sober128_stream_setiv(&st, iv, sizeof(iv))) != CRYPT_OK) return err; + if ((err = sober128_stream_crypt(&st, src, len, dst)) != CRYPT_OK) return err; + if ((err = sober128_stream_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(dst, len, out, len, "SOBER-128-TV1", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* crypt in a single call */ + if ((err = sober128_stream_memory(key, sizeof(key), iv, sizeof(iv), + src, len, dst)) != CRYPT_OK) return err; + if (compare_testvector(dst, len, out, len, "SOBER-128-TV2", 0)) { + return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/src/stream/sober128/sober128tab.c b/deps/libtomcrypt/src/stream/sober128/sober128tab.c new file mode 100644 index 0000000..e067bb6 --- /dev/null +++ b/deps/libtomcrypt/src/stream/sober128/sober128tab.c @@ -0,0 +1,166 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/** + @file sober128tab.c + SOBER-128 Tables +*/ + +#ifdef LTC_SOBER128TAB_C + +/* $ID$ */ +/* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */ +/* Multiplication table for Turing using 0xD02B4367 */ +static const ulong32 Multab[256] = { + 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, + 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478, + 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746, + 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, + 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A, + 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB, + 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, + 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04, + 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2, + 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, + 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D, + 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC, + 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, + 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80, + 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE, + 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, + 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F, + 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE, + 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, + 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41, + 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC, + 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, + 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703, + 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2, + 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, + 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5, + 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB, + 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, + 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787, + 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656, + 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, + 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9, + 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748, + 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, + 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7, + 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476, + 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, + 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A, + 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34, + 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, + 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523, + 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2, + 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, + 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D, + 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0, + 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, + 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F, + 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E, + 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, + 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F, + 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71, + 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, + 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D, + 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC, + 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, + 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433, + 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5, + 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, + 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A, + 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB, + 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, + 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7, + 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789, + 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658, +}; + +/* $ID$ */ +/* Sbox for SOBER-128 */ +/* + * This is really the combination of two SBoxes; the least significant + * 24 bits comes from: + * 8->32 Sbox generated by Millan et. al. at Queensland University of + * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter, + * "On the Design of 8*32 S-boxes". Unpublished report, by the + * Information Systems Research Centre, + * Queensland University of Technology, 1999. + * + * The most significant 8 bits are the Skipjack "F table", which can be + * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf . + * In this optimised table, though, the intent is to XOR the word from + * the table selected by the high byte with the input word. Thus, the + * high byte is actually the Skipjack F-table entry XORED with its + * table index. + */ +static const ulong32 Sbox[256] = { + 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4, + 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae, + 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c, + 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35, + 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e, + 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b, + 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f, + 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1, + 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd, + 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3, + 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f, + 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36, + 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf, + 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816, + 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d, + 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af, + 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6, + 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418, + 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0, + 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd, + 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088, + 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759, + 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895, + 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66, + 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc, + 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1, + 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911, + 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e, + 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515, + 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133, + 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226, + 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084, + 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb, + 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184, + 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420, + 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02, + 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655, + 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c, + 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418, + 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473, + 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a, + 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0, + 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21, + 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36, + 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5, + 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6, + 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0, + 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795, + 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0, + 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78, + 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da, + 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a, + 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118, + 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed, + 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd, + 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b, + 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921, + 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e, + 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5, + 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8, + 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376, + 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a, + 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, + 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, +}; + +#endif /* LTC_SOBER128TAB_C */ diff --git a/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk.c b/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk.c new file mode 100644 index 0000000..6733450 --- /dev/null +++ b/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk.c @@ -0,0 +1,807 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* + * This LTC implementation was adapted from: + * http://www.ecrypt.eu.org/stream/e2-sosemanuk.html + */ + +/* + * SOSEMANUK reference implementation. + * + * This code is supposed to run on any conforming C implementation (C90 + * or later). + * + * (c) 2005 X-CRYPT project. This software is provided 'as-is', without + * any express or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to no restriction. + * + * Technical remarks and questions can be addressed to + * + */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +/* ======================================================================== */ + +/* + * We want (and sometimes need) to perform explicit truncations to 32 bits. + */ +#define T32(x) ((x) & (ulong32)0xFFFFFFFF) + +/* + * Some of our functions will be tagged as "inline" to help the compiler + * optimize things. We use "inline" only if the compiler is advanced + * enough to understand it; C99 compilers, and pre-C99 versions of gcc, + * understand enough "inline" for our purposes. + */ + +/* ======================================================================== */ + +/* + * Serpent S-boxes, implemented in bitslice mode. These circuits have + * been published by Dag Arne Osvik ("Speeding up Serpent", published in + * the 3rd AES Candidate Conference) and work on five 32-bit registers: + * the four inputs, and a fifth scratch register. There are meant to be + * quite fast on Pentium-class processors. These are not the fastest + * published, but they are "fast enough" and they are unencumbered as + * far as intellectual property is concerned (note: these are rewritten + * from the article itself, and hence are not covered by the GPL on + * Dag's code, which was not used here). + * + * The output bits are permuted. Here is the correspondance: + * S0: 1420 + * S1: 2031 + * S2: 2314 + * S3: 1234 + * S4: 1403 + * S5: 1302 + * S6: 0142 + * S7: 4310 + * (for instance, the output of S0 is in "r1, r4, r2, r0"). + */ + +#define S0(r0, r1, r2, r3, r4) do { \ + r3 ^= r0; r4 = r1; \ + r1 &= r3; r4 ^= r2; \ + r1 ^= r0; r0 |= r3; \ + r0 ^= r4; r4 ^= r3; \ + r3 ^= r2; r2 |= r1; \ + r2 ^= r4; r4 = ~r4; \ + r4 |= r1; r1 ^= r3; \ + r1 ^= r4; r3 |= r0; \ + r1 ^= r3; r4 ^= r3; \ + } while (0) + +#define S1(r0, r1, r2, r3, r4) do { \ + r0 = ~r0; r2 = ~r2; \ + r4 = r0; r0 &= r1; \ + r2 ^= r0; r0 |= r3; \ + r3 ^= r2; r1 ^= r0; \ + r0 ^= r4; r4 |= r1; \ + r1 ^= r3; r2 |= r0; \ + r2 &= r4; r0 ^= r1; \ + r1 &= r2; \ + r1 ^= r0; r0 &= r2; \ + r0 ^= r4; \ + } while (0) + +#define S2(r0, r1, r2, r3, r4) do { \ + r4 = r0; r0 &= r2; \ + r0 ^= r3; r2 ^= r1; \ + r2 ^= r0; r3 |= r4; \ + r3 ^= r1; r4 ^= r2; \ + r1 = r3; r3 |= r4; \ + r3 ^= r0; r0 &= r1; \ + r4 ^= r0; r1 ^= r3; \ + r1 ^= r4; r4 = ~r4; \ + } while (0) + +#define S3(r0, r1, r2, r3, r4) do { \ + r4 = r0; r0 |= r3; \ + r3 ^= r1; r1 &= r4; \ + r4 ^= r2; r2 ^= r3; \ + r3 &= r0; r4 |= r1; \ + r3 ^= r4; r0 ^= r1; \ + r4 &= r0; r1 ^= r3; \ + r4 ^= r2; r1 |= r0; \ + r1 ^= r2; r0 ^= r3; \ + r2 = r1; r1 |= r3; \ + r1 ^= r0; \ + } while (0) + +#define S4(r0, r1, r2, r3, r4) do { \ + r1 ^= r3; r3 = ~r3; \ + r2 ^= r3; r3 ^= r0; \ + r4 = r1; r1 &= r3; \ + r1 ^= r2; r4 ^= r3; \ + r0 ^= r4; r2 &= r4; \ + r2 ^= r0; r0 &= r1; \ + r3 ^= r0; r4 |= r1; \ + r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r2 &= r3; \ + r0 = ~r0; r4 ^= r2; \ + } while (0) + +#define S5(r0, r1, r2, r3, r4) do { \ + r0 ^= r1; r1 ^= r3; \ + r3 = ~r3; r4 = r1; \ + r1 &= r0; r2 ^= r3; \ + r1 ^= r2; r2 |= r4; \ + r4 ^= r3; r3 &= r1; \ + r3 ^= r0; r4 ^= r1; \ + r4 ^= r2; r2 ^= r0; \ + r0 &= r3; r2 = ~r2; \ + r0 ^= r4; r4 |= r3; \ + r2 ^= r4; \ + } while (0) + +#define S6(r0, r1, r2, r3, r4) do { \ + r2 = ~r2; r4 = r3; \ + r3 &= r0; r0 ^= r4; \ + r3 ^= r2; r2 |= r4; \ + r1 ^= r3; r2 ^= r0; \ + r0 |= r1; r2 ^= r1; \ + r4 ^= r0; r0 |= r3; \ + r0 ^= r2; r4 ^= r3; \ + r4 ^= r0; r3 = ~r3; \ + r2 &= r4; \ + r2 ^= r3; \ + } while (0) + +#define S7(r0, r1, r2, r3, r4) do { \ + r4 = r1; r1 |= r2; \ + r1 ^= r3; r4 ^= r2; \ + r2 ^= r1; r3 |= r4; \ + r3 &= r0; r4 ^= r2; \ + r3 ^= r1; r1 |= r4; \ + r1 ^= r0; r0 |= r4; \ + r0 ^= r2; r1 ^= r4; \ + r2 ^= r1; r1 &= r0; \ + r1 ^= r4; r2 = ~r2; \ + r2 |= r0; \ + r4 ^= r2; \ + } while (0) + +/* + * The Serpent linear transform. + */ +#define SERPENT_LT(x0, x1, x2, x3) do { \ + x0 = ROLc(x0, 13); \ + x2 = ROLc(x2, 3); \ + x1 = x1 ^ x0 ^ x2; \ + x3 = x3 ^ x2 ^ T32(x0 << 3); \ + x1 = ROLc(x1, 1); \ + x3 = ROLc(x3, 7); \ + x0 = x0 ^ x1 ^ x3; \ + x2 = x2 ^ x3 ^ T32(x1 << 7); \ + x0 = ROLc(x0, 5); \ + x2 = ROLc(x2, 22); \ + } while (0) + +/* ======================================================================== */ + +/* + * Initialize Sosemanuk's state by providing a key. The key is an array of + * 1 to 32 bytes. + * @param st The Sosemanuk state + * @param key Key + * @param keylen Length of key in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_setup(sosemanuk_state *st, const unsigned char *key, unsigned long keylen) +{ + /* + * This key schedule is actually a truncated Serpent key schedule. + * The key-derived words (w_i) are computed within the eight + * local variables w0 to w7, which are reused again and again. + */ + +#define SKS(S, o0, o1, o2, o3, d0, d1, d2, d3) do { \ + ulong32 r0, r1, r2, r3, r4; \ + r0 = w ## o0; \ + r1 = w ## o1; \ + r2 = w ## o2; \ + r3 = w ## o3; \ + S(r0, r1, r2, r3, r4); \ + st->kc[i ++] = r ## d0; \ + st->kc[i ++] = r ## d1; \ + st->kc[i ++] = r ## d2; \ + st->kc[i ++] = r ## d3; \ + } while (0) + +#define SKS0 SKS(S0, 4, 5, 6, 7, 1, 4, 2, 0) +#define SKS1 SKS(S1, 0, 1, 2, 3, 2, 0, 3, 1) +#define SKS2 SKS(S2, 4, 5, 6, 7, 2, 3, 1, 4) +#define SKS3 SKS(S3, 0, 1, 2, 3, 1, 2, 3, 4) +#define SKS4 SKS(S4, 4, 5, 6, 7, 1, 4, 0, 3) +#define SKS5 SKS(S5, 0, 1, 2, 3, 1, 3, 0, 2) +#define SKS6 SKS(S6, 4, 5, 6, 7, 0, 1, 4, 2) +#define SKS7 SKS(S7, 0, 1, 2, 3, 4, 3, 1, 0) + +#define WUP(wi, wi5, wi3, wi1, cc) do { \ + ulong32 tt = (wi) ^ (wi5) ^ (wi3) \ + ^ (wi1) ^ (0x9E3779B9 ^ (ulong32)(cc)); \ + (wi) = ROLc(tt, 11); \ + } while (0) + +#define WUP0(cc) do { \ + WUP(w0, w3, w5, w7, cc); \ + WUP(w1, w4, w6, w0, cc + 1); \ + WUP(w2, w5, w7, w1, cc + 2); \ + WUP(w3, w6, w0, w2, cc + 3); \ + } while (0) + +#define WUP1(cc) do { \ + WUP(w4, w7, w1, w3, cc); \ + WUP(w5, w0, w2, w4, cc + 1); \ + WUP(w6, w1, w3, w5, cc + 2); \ + WUP(w7, w2, w4, w6, cc + 3); \ + } while (0) + + unsigned char wbuf[32]; + ulong32 w0, w1, w2, w3, w4, w5, w6, w7; + int i = 0; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(keylen > 0 && keylen <= 32); + + /* + * The key is copied into the wbuf[] buffer and padded to 256 bits + * as described in the Serpent specification. + */ + XMEMCPY(wbuf, key, keylen); + if (keylen < 32) { + wbuf[keylen] = 0x01; + if (keylen < 31) { + XMEMSET(wbuf + keylen + 1, 0, 31 - keylen); + } + } + + LOAD32L(w0, wbuf); + LOAD32L(w1, wbuf + 4); + LOAD32L(w2, wbuf + 8); + LOAD32L(w3, wbuf + 12); + LOAD32L(w4, wbuf + 16); + LOAD32L(w5, wbuf + 20); + LOAD32L(w6, wbuf + 24); + LOAD32L(w7, wbuf + 28); + + WUP0(0); SKS3; + WUP1(4); SKS2; + WUP0(8); SKS1; + WUP1(12); SKS0; + WUP0(16); SKS7; + WUP1(20); SKS6; + WUP0(24); SKS5; + WUP1(28); SKS4; + WUP0(32); SKS3; + WUP1(36); SKS2; + WUP0(40); SKS1; + WUP1(44); SKS0; + WUP0(48); SKS7; + WUP1(52); SKS6; + WUP0(56); SKS5; + WUP1(60); SKS4; + WUP0(64); SKS3; + WUP1(68); SKS2; + WUP0(72); SKS1; + WUP1(76); SKS0; + WUP0(80); SKS7; + WUP1(84); SKS6; + WUP0(88); SKS5; + WUP1(92); SKS4; + WUP0(96); SKS3; + +#undef SKS +#undef SKS0 +#undef SKS1 +#undef SKS2 +#undef SKS3 +#undef SKS4 +#undef SKS5 +#undef SKS6 +#undef SKS7 +#undef WUP +#undef WUP0 +#undef WUP1 + + return CRYPT_OK; +} + + +/* + * Initialization continues by setting the IV. The IV length is up to 16 bytes. + * If "ivlen" is 0 (no IV), then the "iv" parameter can be NULL. If multiple + * encryptions/decryptions are to be performed with the same key and + * sosemanuk_done() has not been called, only sosemanuk_setiv() need be called + * to set the state. + * @param st The Sosemanuk state + * @param iv Initialization vector + * @param ivlen Length of iv in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_setiv(sosemanuk_state *st, const unsigned char *iv, unsigned long ivlen) +{ + + /* + * The Serpent key addition step. + */ +#define KA(zc, x0, x1, x2, x3) do { \ + x0 ^= st->kc[(zc)]; \ + x1 ^= st->kc[(zc) + 1]; \ + x2 ^= st->kc[(zc) + 2]; \ + x3 ^= st->kc[(zc) + 3]; \ + } while (0) + + /* + * One Serpent round. + * zc = current subkey counter + * S = S-box macro for this round + * i0 to i4 = input register numbers (the fifth is a scratch register) + * o0 to o3 = output register numbers + */ +#define FSS(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ + KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ + S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ + SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ + } while (0) + + /* + * Last Serpent round. Contrary to the "true" Serpent, we keep + * the linear transformation for that last round. + */ +#define FSF(zc, S, i0, i1, i2, i3, i4, o0, o1, o2, o3) do { \ + KA(zc, r ## i0, r ## i1, r ## i2, r ## i3); \ + S(r ## i0, r ## i1, r ## i2, r ## i3, r ## i4); \ + SERPENT_LT(r ## o0, r ## o1, r ## o2, r ## o3); \ + KA(zc + 4, r ## o0, r ## o1, r ## o2, r ## o3); \ + } while (0) + + ulong32 r0, r1, r2, r3, r4; + unsigned char ivtmp[16] = {0}; + + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(ivlen <= 16); + LTC_ARGCHK(iv != NULL || ivlen == 0); + + if (ivlen > 0) XMEMCPY(ivtmp, iv, ivlen); + + /* + * Decode IV into four 32-bit words (little-endian). + */ + LOAD32L(r0, ivtmp); + LOAD32L(r1, ivtmp + 4); + LOAD32L(r2, ivtmp + 8); + LOAD32L(r3, ivtmp + 12); + + /* + * Encrypt IV with Serpent24. Some values are extracted from the + * output of the twelfth, eighteenth and twenty-fourth rounds. + */ + FSS(0, S0, 0, 1, 2, 3, 4, 1, 4, 2, 0); + FSS(4, S1, 1, 4, 2, 0, 3, 2, 1, 0, 4); + FSS(8, S2, 2, 1, 0, 4, 3, 0, 4, 1, 3); + FSS(12, S3, 0, 4, 1, 3, 2, 4, 1, 3, 2); + FSS(16, S4, 4, 1, 3, 2, 0, 1, 0, 4, 2); + FSS(20, S5, 1, 0, 4, 2, 3, 0, 2, 1, 4); + FSS(24, S6, 0, 2, 1, 4, 3, 0, 2, 3, 1); + FSS(28, S7, 0, 2, 3, 1, 4, 4, 1, 2, 0); + FSS(32, S0, 4, 1, 2, 0, 3, 1, 3, 2, 4); + FSS(36, S1, 1, 3, 2, 4, 0, 2, 1, 4, 3); + FSS(40, S2, 2, 1, 4, 3, 0, 4, 3, 1, 0); + FSS(44, S3, 4, 3, 1, 0, 2, 3, 1, 0, 2); + st->s09 = r3; + st->s08 = r1; + st->s07 = r0; + st->s06 = r2; + + FSS(48, S4, 3, 1, 0, 2, 4, 1, 4, 3, 2); + FSS(52, S5, 1, 4, 3, 2, 0, 4, 2, 1, 3); + FSS(56, S6, 4, 2, 1, 3, 0, 4, 2, 0, 1); + FSS(60, S7, 4, 2, 0, 1, 3, 3, 1, 2, 4); + FSS(64, S0, 3, 1, 2, 4, 0, 1, 0, 2, 3); + FSS(68, S1, 1, 0, 2, 3, 4, 2, 1, 3, 0); + st->r1 = r2; + st->s04 = r1; + st->r2 = r3; + st->s05 = r0; + + FSS(72, S2, 2, 1, 3, 0, 4, 3, 0, 1, 4); + FSS(76, S3, 3, 0, 1, 4, 2, 0, 1, 4, 2); + FSS(80, S4, 0, 1, 4, 2, 3, 1, 3, 0, 2); + FSS(84, S5, 1, 3, 0, 2, 4, 3, 2, 1, 0); + FSS(88, S6, 3, 2, 1, 0, 4, 3, 2, 4, 1); + FSF(92, S7, 3, 2, 4, 1, 0, 0, 1, 2, 3); + st->s03 = r0; + st->s02 = r1; + st->s01 = r2; + st->s00 = r3; + + st->ptr = sizeof(st->buf); + +#undef KA +#undef FSS +#undef FSF + + return CRYPT_OK; +} + +/* + * Multiplication by alpha: alpha * x = T32(x << 8) ^ mul_a[x >> 24] + */ +static const ulong32 mul_a[] = { + 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, + 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, + 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, + 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, + 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, + 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, + 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, + 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, + 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, + 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, + 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, + 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, + 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, + 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, + 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, + 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, + 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, + 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, + 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, + 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, + 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, + 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, + 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, + 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, + 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, + 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, + 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, + 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, + 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, + 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, + 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, + 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, + 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, + 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, + 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, + 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, + 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, + 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, + 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, + 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, + 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, + 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, + 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, + 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, + 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, + 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, + 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, + 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, + 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, + 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, + 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, + 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, + 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, + 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, + 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, + 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, + 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, + 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, + 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, + 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, + 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, + 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, + 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, + 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB +}; + +/* + * Multiplication by 1/alpha: 1/alpha * x = (x >> 8) ^ mul_ia[x & 0xFF] + */ +static const ulong32 mul_ia[] = { + 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, + 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, + 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, + 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, + 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, + 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, + 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, + 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, + 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, + 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, + 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, + 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, + 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, + 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, + 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, + 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, + 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, + 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, + 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, + 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, + 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, + 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, + 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, + 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, + 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, + 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, + 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, + 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, + 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, + 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, + 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, + 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, + 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, + 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, + 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, + 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, + 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, + 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, + 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, + 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, + 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, + 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, + 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, + 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, + 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, + 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, + 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, + 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, + 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, + 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, + 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, + 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, + 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, + 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, + 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, + 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, + 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, + 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, + 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, + 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, + 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, + 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, + 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, + 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2 +}; + + +/* + * Compute the next block of bits of output stream. This is equivalent + * to one full rotation of the shift register. + */ +static LTC_INLINE void s_sosemanuk_internal(sosemanuk_state *st) +{ + /* + * MUL_A(x) computes alpha * x (in F_{2^32}). + * MUL_G(x) computes 1/alpha * x (in F_{2^32}). + */ +#define MUL_A(x) (T32((x) << 8) ^ mul_a[(x) >> 24]) +#define MUL_G(x) (((x) >> 8) ^ mul_ia[(x) & 0xFF]) + + /* + * This macro computes the special multiplexer, which chooses + * between "x" and "x xor y", depending on the least significant + * bit of the control word. We use the C "?:" selection operator + * (which most compilers know how to optimise) except for Alpha, + * where the manual sign extension seems to perform equally well + * with DEC/Compaq/HP compiler, and much better with gcc. + */ +#ifdef __alpha +#define XMUX(c, x, y) ((((signed int)((c) << 31) >> 31) & (y)) ^ (x)) +#else +#define XMUX(c, x, y) (((c) & 0x1) ? ((x) ^ (y)) : (x)) +#endif + + /* + * FSM() updates the finite state machine. + */ +#define FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) do { \ + ulong32 tt, or1; \ + tt = XMUX(r1, s ## x1, s ## x8); \ + or1 = r1; \ + r1 = T32(r2 + tt); \ + tt = T32(or1 * 0x54655307); \ + r2 = ROLc(tt, 7); \ + } while (0) + + /* + * LRU updates the shift register; the dropped value is stored + * in variable "dd". + */ +#define LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd) do { \ + dd = s ## x0; \ + s ## x0 = MUL_A(s ## x0) ^ MUL_G(s ## x3) ^ s ## x9; \ + } while (0) + + /* + * CC1 stores into variable "ee" the next intermediate word + * (combination of the new states of the LFSR and the FSM). + */ +#define CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee) do { \ + ee = T32(s ## x9 + r1) ^ r2; \ + } while (0) + + /* + * STEP computes one internal round. "dd" receives the "s_t" + * value (dropped from the LFSR) and "ee" gets the value computed + * from the LFSR and FSM. + */ +#define STEP(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd, ee) do { \ + FSM(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9); \ + LRU(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, dd); \ + CC1(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, ee); \ + } while (0) + + /* + * Apply one Serpent round (with the provided S-box macro), XOR + * the result with the "v" values, and encode the result into + * the destination buffer, at the provided offset. The "x*" + * arguments encode the output permutation of the "S" macro. + */ +#define SRD(S, x0, x1, x2, x3, ooff) do { \ + S(u0, u1, u2, u3, u4); \ + STORE32L(u ## x0 ^ v0, st->buf + ooff); \ + STORE32L(u ## x1 ^ v1, st->buf + ooff + 4); \ + STORE32L(u ## x2 ^ v2, st->buf + ooff + 8); \ + STORE32L(u ## x3 ^ v3, st->buf + ooff + 12); \ + } while (0) + + ulong32 s00 = st->s00; + ulong32 s01 = st->s01; + ulong32 s02 = st->s02; + ulong32 s03 = st->s03; + ulong32 s04 = st->s04; + ulong32 s05 = st->s05; + ulong32 s06 = st->s06; + ulong32 s07 = st->s07; + ulong32 s08 = st->s08; + ulong32 s09 = st->s09; + ulong32 r1 = st->r1; + ulong32 r2 = st->r2; + ulong32 u0, u1, u2, u3, u4; + ulong32 v0, v1, v2, v3; + + STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v0, u0); + STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v1, u1); + STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v2, u2); + STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v3, u3); + SRD(S2, 2, 3, 1, 4, 0); + STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v0, u0); + STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v1, u1); + STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v2, u2); + STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v3, u3); + SRD(S2, 2, 3, 1, 4, 16); + STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v0, u0); + STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v1, u1); + STEP(00, 01, 02, 03, 04, 05, 06, 07, 08, 09, v2, u2); + STEP(01, 02, 03, 04, 05, 06, 07, 08, 09, 00, v3, u3); + SRD(S2, 2, 3, 1, 4, 32); + STEP(02, 03, 04, 05, 06, 07, 08, 09, 00, 01, v0, u0); + STEP(03, 04, 05, 06, 07, 08, 09, 00, 01, 02, v1, u1); + STEP(04, 05, 06, 07, 08, 09, 00, 01, 02, 03, v2, u2); + STEP(05, 06, 07, 08, 09, 00, 01, 02, 03, 04, v3, u3); + SRD(S2, 2, 3, 1, 4, 48); + STEP(06, 07, 08, 09, 00, 01, 02, 03, 04, 05, v0, u0); + STEP(07, 08, 09, 00, 01, 02, 03, 04, 05, 06, v1, u1); + STEP(08, 09, 00, 01, 02, 03, 04, 05, 06, 07, v2, u2); + STEP(09, 00, 01, 02, 03, 04, 05, 06, 07, 08, v3, u3); + SRD(S2, 2, 3, 1, 4, 64); + + st->s00 = s00; + st->s01 = s01; + st->s02 = s02; + st->s03 = s03; + st->s04 = s04; + st->s05 = s05; + st->s06 = s06; + st->s07 = s07; + st->s08 = s08; + st->s09 = s09; + st->r1 = r1; + st->r2 = r2; +} + +/* + * Combine buffers in1[] and in2[] by XOR, result in out[]. The length + * is "datalen" (in bytes). Partial overlap of out[] with either in1[] + * or in2[] is not allowed. Total overlap (out == in1 and/or out == in2) + * is allowed. + */ +static LTC_INLINE void s_xorbuf(const unsigned char *in1, const unsigned char *in2, + unsigned char *out, unsigned long datalen) +{ + while (datalen -- > 0) { + *out ++ = *in1 ++ ^ *in2 ++; + } +} + + +/* + * Cipher operation, as a stream cipher: data is read from the "in" + * buffer, combined by XOR with the stream, and the result is written + * in the "out" buffer. "in" and "out" must be either equal, or + * reference distinct buffers (no partial overlap is allowed). + * @param st The Sosemanuk state + * @param in Data in + * @param inlen Length of data in bytes + * @param out Data out + * @return CRYPT_OK on success + */ +int sosemanuk_crypt(sosemanuk_state *st, + const unsigned char *in, unsigned long inlen, unsigned char *out) +{ + LTC_ARGCHK(st != NULL); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if (st->ptr < (sizeof(st->buf))) { + unsigned long rlen = (sizeof(st->buf)) - st->ptr; + + if (rlen > inlen) { + rlen = inlen; + } + s_xorbuf(st->buf + st->ptr, in, out, rlen); + in += rlen; + out += rlen; + inlen -= rlen; + st->ptr += rlen; + } + while (inlen > 0) { + s_sosemanuk_internal(st); + if (inlen >= sizeof(st->buf)) { + s_xorbuf(st->buf, in, out, sizeof(st->buf)); + in += sizeof(st->buf); + out += sizeof(st->buf); + inlen -= sizeof(st->buf); + } else { + s_xorbuf(st->buf, in, out, inlen); + st->ptr = inlen; + inlen = 0; + } + } + return CRYPT_OK; +} + + + +/* + * Cipher operation, as a PRNG: the provided output buffer is filled with + * pseudo-random bytes as output from the stream cipher. + * @param st The Sosemanuk state + * @param out Data out + * @param outlen Length of output in bytes + * @return CRYPT_OK on success + */ +int sosemanuk_keystream(sosemanuk_state *st, unsigned char *out, unsigned long outlen) +{ + if (outlen == 0) return CRYPT_OK; /* nothing to do */ + LTC_ARGCHK(out != NULL); + XMEMSET(out, 0, outlen); + return sosemanuk_crypt(st, out, outlen, out); +} + + +/* + * Terminate and clear Sosemanuk key context + * @param st The Sosemanuk state + * @return CRYPT_OK on success + */ +int sosemanuk_done(sosemanuk_state *st) +{ + LTC_ARGCHK(st != NULL); + zeromem(st, sizeof(sosemanuk_state)); + return CRYPT_OK; +} + + +#endif diff --git a/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c b/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c new file mode 100644 index 0000000..c0fac25 --- /dev/null +++ b/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_memory.c @@ -0,0 +1,35 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK + +/** + Encrypt (or decrypt) bytes of ciphertext (or plaintext) with Sosemanuk + @param key The key + @param keylen The key length + @param iv The initial vector + @param ivlen The initial vector length + @param datain The plaintext (or ciphertext) + @param datalen The length of the input and output (octets) + @param dataout [out] The ciphertext (or plaintext) + @return CRYPT_OK if successful +*/ +int sosemanuk_memory(const unsigned char *key, unsigned long keylen, + const unsigned char *iv, unsigned long ivlen, + const unsigned char *datain, unsigned long datalen, + unsigned char *dataout) +{ + sosemanuk_state st; + int err; + + if ((err = sosemanuk_setup(&st, key, keylen)) != CRYPT_OK) goto WIPE_KEY; + if ((err = sosemanuk_setiv(&st, iv, ivlen)) != CRYPT_OK) goto WIPE_KEY; + err = sosemanuk_crypt(&st, datain, datalen, dataout); +WIPE_KEY: + sosemanuk_done(&st); + return err; +} + +#endif /* LTC_SOSEMANUK */ diff --git a/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c b/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c new file mode 100644 index 0000000..2c0a887 --- /dev/null +++ b/deps/libtomcrypt/src/stream/sosemanuk/sosemanuk_test.c @@ -0,0 +1,79 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifdef LTC_SOSEMANUK +int sosemanuk_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + sosemanuk_state st; + int err; + unsigned char out[1000]; + + { + unsigned char k[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; + unsigned char n[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + unsigned char ct[] = { 0x7e, 0xfe, 0x2e, 0x6f, 0x8f, 0x77, 0x15, 0x72, 0x6a, 0x88, 0x14, 0xa6, 0x56, 0x88, 0x29, 0x9a, + 0x86, 0x32, 0x7f, 0x14, 0xd6, 0xb1, 0x94, 0x90, 0x25, 0xbc, 0x73, 0xfd, 0x02, 0x6c, 0x6a, 0xb8, + 0xda, 0x8e, 0x7f, 0x61, 0x70, 0x81, 0xe3, 0xbb, 0x99, 0xaf, 0x19, 0x9f, 0x20, 0x45 }; + char pt[] = "Kilroy was here, and there. ...and everywhere!"; /* len = 46 bytes */ + unsigned long len; + len = XSTRLEN(pt); + /* crypt piece by piece */ + if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, 5, out)) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 5, 25, out + 5)) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 30, 10, out + 30)) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt + 40, len - 40, out + 40)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV1", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in one go - using sosemanuk_ivctr64() */ + if ((err = sosemanuk_setup(&st, k, sizeof(k))) != CRYPT_OK) return err; + if ((err = sosemanuk_setiv(&st, n, sizeof(n))) != CRYPT_OK) return err; + if ((err = sosemanuk_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV2", 1)) return CRYPT_FAIL_TESTVECTOR; + + /* crypt in a single call */ + if ((err = sosemanuk_memory(k, sizeof(k), n, sizeof(n), + (unsigned char*)pt, len, out)) != CRYPT_OK) return err; + if (compare_testvector(out, len, ct, sizeof(ct), "SOSEMANUK-TV3", 1)) return CRYPT_FAIL_TESTVECTOR; + + } + { + /* keystream + * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/sosemanuk/unverified.test-vectors?rev=210&view=auto + * Set 6, vector 0 + * key = 0053A6F94C9FF24598EB3E91E4378ADD + * 3083D6297CCF2275C81B6EC11467BA0D + * IV = 0D74DB42A91077DE45AC137AE148AF16 + * stream[0..63] = 55EB8D174C2E0351E5A53C90E84740EB + * 0F5A24AAFEC8E0C9F9D2CE48B2ADB0A3 + * 4D2E8C4E016102607368FFA43A0F9155 + * 0706E3548AD9E5EA15A53EB6F0EDE9DC + * + */ + + unsigned char k3[] = { 0x00, 0x53, 0xA6, 0xF9, 0x4C, 0x9F, 0xF2, 0x45, 0x98, 0xEB, 0x3E, 0x91, 0xE4, 0x37, 0x8A, 0xDD, + 0x30, 0x83, 0xD6, 0x29, 0x7C, 0xCF, 0x22, 0x75, 0xC8, 0x1B, 0x6E, 0xC1, 0x14, 0x67, 0xBA, 0x0D }; + unsigned char n3[] = { 0x0D, 0x74, 0xDB, 0x42, 0xA9, 0x10, 0x77, 0xDE, 0x45, 0xAC, 0x13, 0x7A, 0xE1, 0x48, 0xAF, 0x16 }; + unsigned char ct3[] = { 0x55, 0xEB, 0x8D, 0x17, 0x4C, 0x2E, 0x03, 0x51, 0xE5, 0xA5, 0x3C, 0x90, 0xE8, 0x47, 0x40, 0xEB, + 0x0F, 0x5A, 0x24, 0xAA, 0xFE, 0xC8, 0xE0, 0xC9, 0xF9, 0xD2, 0xCE, 0x48, 0xB2, 0xAD, 0xB0, 0xA3, + 0x4D, 0x2E, 0x8C, 0x4E, 0x01, 0x61, 0x02, 0x60, 0x73, 0x68, 0xFF, 0xA4, 0x3A, 0x0F, 0x91, 0x55, + 0x07, 0x06, 0xE3, 0x54, 0x8A, 0xD9, 0xE5, 0xEA, 0x15, 0xA5, 0x3E, 0xB6, 0xF0, 0xED, 0xE9, 0xDC }; + if ((err = sosemanuk_setup(&st, k3, sizeof(k3))) != CRYPT_OK) return err; + if ((err = sosemanuk_setiv(&st, n3, sizeof(n3))) != CRYPT_OK) return err; + if ((err = sosemanuk_keystream(&st, out, 64)) != CRYPT_OK) return err; + if ((err = sosemanuk_done(&st)) != CRYPT_OK) return err; + if (compare_testvector(out, 64, ct3, sizeof(ct3), "SOSEMANUK-TV4", 1)) return CRYPT_FAIL_TESTVECTOR; + } + + return CRYPT_OK; +#endif +} + +#endif diff --git a/deps/libtomcrypt/testme.sh b/deps/libtomcrypt/testme.sh new file mode 100644 index 0000000..e497161 --- /dev/null +++ b/deps/libtomcrypt/testme.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +if [ $# -lt 3 ] +then + echo "usage is: ${0##*/} " + echo "e.g. \"${0##*/} \"makefile -j9\" \"-DUSE_LTM -DLTM_DESC -I../libtommath\" ../libtommath/libtommath.a\"" + echo "to create aggregate coverage: pre-pend with LTC_COVERAGE=1" + exit -1 +fi + +# date +echo "date="`date` + +# check sources +bash .ci/check_source.sh "CHECK_SOURCES" " " "$1" "$2" "$3" || exit 1 + +mk="$1" + +[ "$LTC_COVERAGE" != "" ] && mk="$mk COVERAGE=1" + +# meta builds +bash .ci/meta_builds.sh "META_BUILS" " " "$mk" "$2" "$3" || exit 1 + +# valgrind build +bash .ci/valgrind.sh "VALGRIND" " " "$mk" "$2" "$3" || exit 1 + +# stock build +bash .ci/run.sh "STOCK" " " "$mk" "$2" "$3" || exit 1 + +# EASY build +bash .ci/run.sh "EASY" "-DLTC_EASY" "$mk" "$2" "$3" || exit 1 + +# SMALL code +bash .ci/run.sh "SMALL" "-DLTC_SMALL_CODE" "$mk" "$2" "$3" || exit 1 + +# NOTABLES +bash .ci/run.sh "NOTABLES" "-DLTC_NO_TABLES" "$mk" "$2" "$3" || exit 1 + +# SMALL+NOTABLES +bash .ci/run.sh "SMALL+NOTABLES" "-DLTC_SMALL_CODE -DLTC_NO_TABLES" "$mk" "$2" "$3" || exit 1 + +# CLEANSTACK +bash .ci/run.sh "CLEANSTACK" "-DLTC_CLEAN_STACK" "$mk" "$2" "$3" || exit 1 + +# CLEANSTACK + SMALL +bash .ci/run.sh "CLEANSTACK+SMALL" "-DLTC_SMALL_CODE -DLTC_CLEAN_STACK" "$mk" "$2" "$3" || exit 1 + +# CLEANSTACK + NOTABLES +bash .ci/run.sh "CLEANSTACK+NOTABLES" "-DLTC_NO_TABLES -DLTC_CLEAN_STACK" "$mk" "$2" "$3" || exit 1 + +# CLEANSTACK + NOTABLES + SMALL +bash .ci/run.sh "CLEANSTACK+NOTABLES+SMALL" "-DLTC_NO_TABLES -DLTC_CLEAN_STACK -DLTC_SMALL_CODE" "$mk" "$2" "$3" || exit 1 + +# NO_FAST +bash .ci/run.sh "NO_FAST" "-DLTC_NO_FAST" "$mk" "$2" "$3" || exit 1 + +# NO_FAST + NOTABLES +bash .ci/run.sh "NO_FAST+NOTABLES" "-DLTC_NO_FAST -DLTC_NO_TABLES" "$mk" "$2" "$3" || exit 1 + +# NO_ASM +bash .ci/run.sh "NO_ASM" "-DLTC_NO_ASM" "$mk" "$2" "$3" || exit 1 + +# NO_TIMING_RESISTANCE +bash .ci/run.sh "NO_TIMING_RESISTANCE" "-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING" "$mk" "$2" "$3" || exit 1 + +# CLEANSTACK+NOTABLES+SMALL+NO_ASM+NO_TIMING_RESISTANCE +bash .ci/run.sh "CLEANSTACK+NOTABLES+SMALL+NO_ASM+NO_TIMING_RESISTANCE" "-DLTC_CLEAN_STACK -DLTC_NO_TABLES -DLTC_SMALL_CODE -DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING" "$mk" "$2" "$3" || exit 1 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtomcrypt/tests/CMakeLists.txt b/deps/libtomcrypt/tests/CMakeLists.txt new file mode 100644 index 0000000..2be451b --- /dev/null +++ b/deps/libtomcrypt/tests/CMakeLists.txt @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: Unlicense +# +# LibTomCrypt, modular cryptographic library -- Tom St Denis +# + +cmake_minimum_required(VERSION 3.10) + +set(LTC_TEST test-ltc) + +# This file can be included from the top level or used stand-alone +if(PROJECT_NAME) + set(LIBRARY_NAME ${PROJECT_NAME}) +else() + # Define an independent project and all the necessary stuff around + project(${LTC_TEST} + LANGUAGES C) + set(LIBRARY_NAME libtomcrypt) + find_package(${LIBRARY_NAME}) + include(CTest) + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Release") + endif() +endif() + +#----------------------------------------------------------------------------- +# Compose CFLAGS etc. +#----------------------------------------------------------------------------- + +if(NOT MSVC) + set(CMAKE_C_FLAGS_DEBUG "-g3 -O1") +endif() + +#----------------------------------------------------------------------------- +# demo target +#----------------------------------------------------------------------------- +include(sources.cmake) +set(PRIVATE_HEADERS + common.h + tomcrypt_test.h +) + +add_executable(${LTC_TEST} + ${SOURCES} + ${PRIVATE_HEADERS} +) + +target_include_directories(${LTC_TEST} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + $<$:${CMAKE_CURRENT_SOURCE_DIR}/..> +) + +target_link_libraries(${LTC_TEST} PRIVATE + ${LIBRARY_NAME} +) + +target_compile_options(${LTC_TEST} PRIVATE + $<$,SHARED_LIBRARY>:-DLTC_TEST_DYNAMIC> + -DCMAKE_SOURCE_DIR=\"${CMAKE_SOURCE_DIR}\" + ${LTC_C_FLAGS} +) +target_link_options(${LTC_TEST} BEFORE PUBLIC + ${LTC_LD_FLAGS} +) + +#----------------------------------------------------------------------------- +# CTest +#----------------------------------------------------------------------------- +add_test(NAME ${LTC_TEST} COMMAND ${LTC_TEST}) + +find_program(MEMORYCHECK_COMMAND valgrind) +set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full") \ No newline at end of file diff --git a/deps/libtomcrypt/tests/asn1/0x00.crt b/deps/libtomcrypt/tests/asn1/0x00.crt new file mode 100644 index 0000000000000000000000000000000000000000..d7eec225c7e10f2f5c0b1cdc47bab557e150daa7 GIT binary patch literal 3298 zcmXqL;<;zg#M8mV$*^d8dioRTmpcu3**LY@JlekVGBUEVG8iN=V`C7O@+-~B(FH2f!T^Ty2C{7I9p?T2 z|NpNS7BV(caLO!E@b&Zy4OTEz0BSK5HxLCWn9$JBz#zf}RREHZGmwEvFp3C5B?5fl z8bQwE=`e2unhXZ@!u)0?VBG~D;zGC*91NgNBU3ZD&RBzJHXkJWap)pi7-+nyAtVSv4r^R# z(724PaVj=H5N#%n6fy|&7#bKs;sfN?CPrI>CPquPCPpHIl1A5H-mu(lOw~X{6oGf|NDPS zKRI>cffx7MN5L;te}tyja+*3^-YF^b;>g{)Q+e|}O5aUwm@t!JVa~ZteCM{^)6Y9` zz9`xAOYcJ_W<~}^WV3;t4`xROu8bcV-zJ<`vg*`zG3C++x<0Qql{IxPxOBK|{)`{z oJNz=DZ)l$JlishPS(El}KRaKN=V`~tWGN`aH&;=^e!T^Ty2C{7I9p?T2 z|NpNS7BV(caLO!E@b&Zy4OTEz0BSK5HxLCWn9$JBz#zf}RREHZGmwEvFp3C5B?5fl z8bQwE=`e2unhXZ@!u)0?VBG~D;zGC*91NgNBU3ZD&RBzJHXkJWap)pi7-+nyAtVSv4r^R# z(724PaVj=H5N#%n6fy|&7#bKs;sfN?CPrI>CPquPCPpHIl1A5H-mu(lOw~X{6oGf|NDPS zKRI>cffx7MN5L;te}tyja+*3^-YF^b;>g{)Q+e|}O5aUwm@t!JVa~ZteCM{^)6Y9` zz9`xAOYcJ_W<~}^WV3;t4`xROu8bcV-zJ<`vg*`zG3C++x<0Qql{IxPxOBK|{)`{z oJNz=DZ)l$JlishPS(El}KRaKN=WBV^GWl)iprVCW0g#irZ4P@EaJIwq4 z|NmbvEM#n?;FMXS;OprZ8mwTb0MueAZXgO$FrlHLfkA`|ssJP*XCMQUU=$IAN(A`8 zHG-VS(_!8SG#L!)h55})z{YFn8ft>gmNAe5DQNz-3)Bo$*hD+bTVS$q znn9S`(8vO86iA(gff<`R#D#DrI2b^kMy6(Pov{YdY(7Z#1268ikAh#Q{s>L4WYwwbV#=itbbVfJDr@RoaOrT_{24#a oclc#Q-_ShcC%s=ovnK7|es;cyO#xO@l>e-HGI64IQAXuq07T!WAOHXW literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/asn1/illegal_padding1.crt b/deps/libtomcrypt/tests/asn1/illegal_padding1.crt new file mode 100644 index 0000000000000000000000000000000000000000..5e1315ae9b17147f06b78c81cbdbd9890fbc624a GIT binary patch literal 17651 zcmeHPdu$X%7~fa7y}P}GvXqw;7O_;sUT3cN=n>Jj6s1y-&=$)>^k}c#X=x32Qj`GQ zEtC?dJc5(}MiAs75HZ9DQPfBx8c_r-i1J4hAc}(0#3Je+ID6OIyKCCGO}M))&i>PH zX1|&5yWdP^=a>0SfmHZAkP6Fp(iBNisl?Z#8g7<K4pg6=XNcs z@W5=4C0Eh>m`G3IiK4=+67NfHq15g33lrUo{N5^Wh0E^_GzbOPk%NRvSB=+Qowd-l z$XDTURafUN_PYFXL?4Q1u5?2Ij9{rI2R{V$DJXqbM07b4q_fFnz5J};2b7nW3jhka zKrqXX;CK`c25D?^lVbyNAb5R_MJVw4-YS0y-T*DRN+P+y&SnNP zR9t#6P)m!=uC#m#%wdZo;`h)>bv5eV2Ez!62Y|Sj6<_J@H>mD2Mver}L0}1vhYYqv zP5=_=WF=B1lrhSy&vc6bv;b>(7E087AW`#JiMo?Bs?WfI6O9Q1XqH)lGrVGDf(&*@ zlY{K`;dRCCngxE3V0A(}u*!>Kw|-qKm39s%tOn1rb5*wM+K;L-ukTC}=GvgR0f^1) zide=|k(82>#io&zxQLYOP}~Q^J%R6tiXRhimvE*|r=~LvW10g1l&FDdx$cj?cefKf z`{F%dI9?P29B&9MNN7KV=0zHs7pdqoPT+YF1=Rnp5IHeyV8mb}guss04yP4bb7u#N z4gfogm#$o#rrZSiZ_8RUmc$f$F8a&(} z;Rs+JnD8OcXadnZP<$=&1dvQ3Xt9|9;u=a6i8t?ERXs~AurJ)%a{0)%qK{8a%C9^0 z$I8*on@-Q)J9NStx^&;g$Fi<&-ulAYwzF?o51rkY-vYlqd85Pp>bhI~kGE~iXsrDH z=E2pAEm`e#?Z=KS_~-4{ceEZcofG}v_Xp$gzOPSk&l-Ys~_UN*76Elbzn6rM#$aS;N*nYTn@w?QVbK}o1 zoB9!uOk-q+(TrqDM}?vF-Ma0PjMw%^#-HyBe%s_&j}9ZzIcMi-<%x~kc`3X}r%x`-QcNjd(Z+i_MZjf*UFuzUs5NI@kD1Iw- zqj;5ttLZ#R-e!^jjs5_WT+vUiV310d1rk>z*JQ{w5{HC@oRdu%$0B`fGEFKLrC79L zF^ZMK>QM`ZlpGY97GV!kY(45LMrWFAhsFHM&2HTUuxeVAW;Z(AH=mP%Bf3RK^3U#Q(hD)>z>2`=9rX&(5x^t21}G z{g%DF>;1TFm#@YQvunMTPgl7r{64eCzpy$Oa6lXbN`}AX-zYGWp&dwu>wuA|3c5oW zA}c{NaOEy+l8AOi-KPtd!?lulH7!{k%fD5|l zN=?TsMlD>}PXz)5y8heaWwzj=rRpOE=EauF08vadn;Mi86~x?kFO;@^(aN7l-g5d3_n>>}j29oj)Rr>W_vPBsE3H?4 NJUpy@(~~us{{ls4N#Xzi literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/asn1/illegal_padding2.crt b/deps/libtomcrypt/tests/asn1/illegal_padding2.crt new file mode 100644 index 0000000000000000000000000000000000000000..e5fbb6a5e59ad2c9ce8797740a12963c29dbc8ed GIT binary patch literal 17651 zcmeHPdu$X%7~fa7y}P}GvXqw;7O_;sUT3cN=n>JjmPn-_p)Hn&=+R!e)6yF5q$mMy z7bqoAc?2l|j3CHEAYzCQqNtHXG@=Mv5ao|1KokX~iAB^u>g-)_@2+X%)^K-=&i>Px z*>C3i?l+U!`DK1zfmHk}kcumJ(iBNi>BN_#R@|(7&m6c^@$OyCZAG5|BdfcwaZ=;& zMv_cPA%JAO3=KfX(iIHLQ^gZu2H@q2p66zGUF9Bc-7{tNHGY^5`pL}(K5e?&=XNcu z^1xh>BRA3fm}pDkv6AAPGVcp+q1^5B3lF;&`n@&YDwp3K>=1UYBL@l9t~#%~HfMor zp|8s0s;wW@+1a_A zACPAeioAYdO3BoUG6Bkwz`-CxHrNmd1PET=Wgx#80fvWPkbHXAi)p1w$5CJ;%QZPf zG;;7+&iAuhgTvpO1IGr(9u9`dCK4Ju_#g*eCbEMu;2t)k$+0s0R{2Zt2589-4kg>= z13Q}?icm4>rGR=`Y<8vR6JR!58s)#2UaFhX@HQBNP!3Ey0K~nl_)<^5LG_q%G9-8o z0!wH<>-B$5B=1^<6>2 zd>a%u0I``}9#4NNf>J`V*fbIn7Zs8niu-`LC-@yv@naHg5{cC5)O4f~O!EMM5;YKQ z*ZtA=t~1H2FVPc*{ly@_@rLk*gw8`~U1Xqjk&Zs&1YQ?0K>hD3(F?-{MhrGW2<&L@ za9W`?e^#*S0I;iyc_2FfU>+Dc1Y#Z-m&33o2gN*4lhg7a3kvhV1ROsiR0i|FKEoXW z5A(o2gNHjL9RbV(lRgC+4Iq{Wimyc90Fo&LEjANCTtkT>@%r7XYG;Z?_60jzE+5%e z^5Ln8g$;*(TRFOU)9HD8hfY{Sm+!myNY2>c2CocJ?*vp|kr6Tj19xZ*-VnUU#ei z@wSawjn&`YJh*z1C8xci{n)Yjf4%wYj@BclbE5yN!uO{iDShA_R$TV+{*x~T&i~QT z@#&5myU!oBJ+zJ8cC=wv!KpHeCJA!4l)W8D*)8Z|kFLlxF@uz{fTfN22`Ltfsy*crSQe@lDr~0$0it&isA|<`d}W?V7j-5( z08XodO^wFIVJW6Y&xZ*M3oQYxx=a|_8g&HfWh#-*ctDN#j|py#MIOKZS>O2F+=hk* zbGPib+-2SK<8ocTIy20z_f|hyD0Hi%|;~wo`!sfzp3_O=b&iTB<%$U~YW53=qX+vk6iIF>v9{T-Br`)=0ad zacJYDF}F$Va?qYPc^NR6-)L`Q5*<;rdJz5p5E{t_SI?f@f3j|=>4cryJkzjf@lX4W z2aGpevuciCJy+53py0j!L&1g_UzjJ9z4g)I>)Bh@k1xpDb*b)+UuLZEtXs0xc2Ixo z=M|>Z`sST2g^QP_T&Ub=-@dANVihsx?F;3tpSAKQQn#Ew!`<&*GX42SFSVu3@qNCw R{7UPU?+*`a-}HE0_TQ6AMTP(X literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/asn1/illegal_padding3.crt b/deps/libtomcrypt/tests/asn1/illegal_padding3.crt new file mode 100644 index 0000000000000000000000000000000000000000..1a9b098e152b713e933ac7c2b851e39a5a38bfc3 GIT binary patch literal 17651 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 KH+)(H&#l4gaX=mb literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/asn1/type0x08.crt b/deps/libtomcrypt/tests/asn1/type0x08.crt new file mode 100644 index 0000000000000000000000000000000000000000..35b516ca882c18888bb8145ca1671f2dfe157aeb GIT binary patch literal 3298 zcmXqL;<;zg#M8mV$*^d8dioRTmpcu3**LY@JlekVGBUEVG8iN=<6vYGmJF#ZNL4VfP|$FV2yqSabM(>F zf&fE#16elq4)gy1|Nqwu3mF?JIAxY7_G~D;zGC*91NgNBU3ZD&RBzJHXkJWap)pi z7-+nyAtVSv4r^R#(724PaVj=H5N#%n6fy|&7#bKs;sfN?CPrI>CPquPCPpHIl1A5H-mu( zlOw~X{6oGf|NDPSKRI>cffx7MN5L;te}tyja+*3^-YF^b;>g{)Q+e|}O5aUwm@t!J zVa~ZteCM{^)6Y9`z9`xAOYcJ_W<~}^WV3;t4`xROu8bcV-zJ<`vg*`zG3C++x<0Qq zl{IxPxOBK|{)`{zJNz=DZ)l$JlishPS(El}KRaK + +#ifdef LTC_BASE16 + +int base16_test(void) +{ + unsigned char in[100], tmp[100]; + char out[201]; + unsigned char testin[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + const char *testout[2] = { + "0123456789abcdef", + "0123456789ABCDEF", + }; + const char *failing_decode = "test"; + unsigned long x, l1, l2; + int idx; + + for (idx = 0; idx < 2; idx++) { + for (x = 0; x < 100; x++) { + ENSURE(yarrow_read(in, x, &yarrow_prng) == x); + l1 = sizeof(out); + DO(base16_encode(in, x, out, &l1, idx)); + l2 = sizeof(tmp); + DO(base16_decode(out, l1, tmp, &l2)); + DO(do_compare_testvector(tmp, l2, in, x, "random base16", idx * 100 + x)); + } + } + + for (idx = 0; idx < 2; idx++) { + l1 = sizeof(out); + DO(base16_encode(testin, sizeof(testin), out, &l1, idx)); + DO(do_compare_testvector(out, XSTRLEN(out), testout[idx], XSTRLEN(testout[idx]), "testout base16", idx)); + l2 = sizeof(tmp); + DO(base16_decode(out, l1, tmp, &l2)); + DO(do_compare_testvector(tmp, l2, testin, sizeof(testin), "testin base16", idx)); + } + + l1 = 4; + l2 = sizeof(tmp); + SHOULD_FAIL(base16_decode(failing_decode, l1, tmp, &l2)); + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/tests/base32_test.c b/deps/libtomcrypt/tests/base32_test.c new file mode 100644 index 0000000..365f608 --- /dev/null +++ b/deps/libtomcrypt/tests/base32_test.c @@ -0,0 +1,51 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +#ifdef LTC_BASE32 + +int base32_test(void) +{ + unsigned char in[100], tmp[100]; + char out[160]; + unsigned char testin[] = { 0x61,0xc2,0xcb,0xbc,0x5e,0x6d,0x2a,0x7a,0x1a,0x19,0x1a,0xae,0xc9,0x02,0xd4,0xbf,0x7d }; + const int testid[4] = { + BASE32_RFC4648, + BASE32_BASE32HEX, + BASE32_ZBASE32, + BASE32_CROCKFORD + }; + const char *testout[4] = { + "MHBMXPC6NUVHUGQZDKXMSAWUX56Q", + "C71CNF2UDKL7K6GP3ANCI0MKNTUG", + "c8bczxn6pwi8wgo3dkzc1yswz76o", + "C71CQF2YDMN7M6GS3AQCJ0PMQXYG" + }; + unsigned long x, l1, l2; + int idx; + + for (idx = 0; idx < 4; idx++) { + for (x = 0; x < 100; x++) { + ENSURE(yarrow_read(in, x, &yarrow_prng) == x); + l1 = sizeof(out); + DO(base32_encode(in, x, out, &l1, testid[idx])); + l2 = sizeof(tmp); + DO(base32_decode(out, l1, tmp, &l2, testid[idx])); + DO(do_compare_testvector(tmp, l2, in, x, "random base32", idx * 100 + x)); + } + } + + for (idx = 0; idx < 4; idx++) { + l1 = sizeof(out); + DO(base32_encode(testin, sizeof(testin), out, &l1, testid[idx])); + DO(do_compare_testvector(out, l1, testout[idx], XSTRLEN(testout[idx]), "testout base32", idx)); + l2 = sizeof(tmp); + DO(base32_decode(out, l1, tmp, &l2, testid[idx])); + DO(do_compare_testvector(tmp, l2, testin, sizeof(testin), "testin base32", idx)); + } + + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/tests/base64_test.c b/deps/libtomcrypt/tests/base64_test.c new file mode 100644 index 0000000..2be927a --- /dev/null +++ b/deps/libtomcrypt/tests/base64_test.c @@ -0,0 +1,178 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_BASE64) || defined(LTC_BASE64_URL) +enum { insane = 0, strict = 1, relaxed = 2, invalid = 666 }; + +int base64_test(void) +{ + unsigned char in[64], tmp[64]; + char out[256]; + unsigned long x, l1, l2, slen1; + + const unsigned char special_case[] = { + 0xbe, 0xe8, 0x92, 0x3c, 0xa2, 0x25, 0xf0, 0xf8, + 0x91, 0xe4, 0xef, 0xab, 0x0b, 0x8c, 0xfd, 0xff, + 0x14, 0xd0, 0x29, 0x9d, 0x00 }; + /* 3 A's are encoded as QUFB */ + const char *As_lf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\nQUFB"; + const char *As_crlf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\r\nQUFB"; + const char *As_ssh_lf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\nQUFB"; + const char *As_ssh_crlf = "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB\r\nQUFB"; + +#if defined(LTC_BASE64) + /* + TEST CASES SOURCE: + + Network Working Group S. Josefsson + Request for Comments: 4648 SJD + Obsoletes: 3548 October 2006 + Category: Standards Track + */ + const struct { + const char* s; + const char* b64; + } cases[] = { + {"", "" }, + {"f", "Zg==" }, + {"fo", "Zm8=" }, + {"foo", "Zm9v" }, + {"foob", "Zm9vYg==" }, + {"fooba", "Zm9vYmE=" }, + {"foobar", "Zm9vYmFy"}, + {(char*)special_case,"vuiSPKIl8PiR5O+rC4z9/xTQKZ0="} + }; +#endif + +#ifdef LTC_BASE64_URL + const struct { + const char* s; + int flag; + } url_cases[] = { + {"vuiSPKIl8PiR5O-rC4z9_xTQKZ0", strict}, /* 0 */ + {"vuiSPKIl8PiR5O-rC4z9_xTQKZ0=", strict}, + {"vuiS*PKIl8P*iR5O-rC4*z9_xTQKZ0", insane}, + {"vuiS*PKIl8P*iR5O-rC4*z9_xTQKZ0=", insane}, + {"vuiS*PKIl8P*iR5O-rC4*z9_xTQKZ0==", insane}, + {"vuiS*PKIl8P*iR5O-rC4*z9_xTQKZ0===", insane}, /* 5 */ + {"vuiS*PKIl8P*iR5O-rC4*z9_xTQKZ0====", insane}, + {"vuiS*=PKIl8P*iR5O-rC4*z9_xTQKZ0=", insane}, + {"vuiS*==PKIl8P*iR5O-rC4*z9_xTQKZ0=", insane}, + {"vuiS*==\xffPKIl8P*iR5O-rC4*z9_xTQKZ0=", insane}, + {"vuiS PKIl8P\niR5O-rC4\tz9_xTQKZ0", relaxed}, /* 10 */ + {"vuiS PKIl8P\niR5O-rC4\tz9_xTQKZ0=", relaxed}, + {"vuiS PKIl8P\niR5O-rC4\tz9_xTQKZ0==", relaxed}, + {"vuiS PKIl8P\niR5O-rC4\tz9_xTQKZ0===", relaxed}, + {"vuiS PKIl8P\niR5O-rC4\tz9_xTQKZ0====", relaxed}, + {"vuiS\rPKIl8P\niR5O-rC4\tz9_xTQKZ0=", relaxed}, /* 15 */ + {"vuiS\rPKIl8P\niR5O-rC4\tz9_xTQKZ0= = =\x00", relaxed}, + {"\nvuiS\rPKIl8P\niR5O-rC4\tz9_xTQKZ0=\n", relaxed}, + {"vuiSPKIl8PiR5O-rC4z9_xTQK", invalid}, + }; + + for (x = 0; x < sizeof(url_cases)/sizeof(url_cases[0]); ++x) { + slen1 = XSTRLEN(url_cases[x].s); + l1 = sizeof(tmp); + if(url_cases[x].flag == strict) { + DO(base64url_strict_decode(url_cases[x].s, slen1, tmp, &l1)); + DO(do_compare_testvector(tmp, l1, special_case, sizeof(special_case) - 1, "base64url_strict_decode", x)); + DO(base64url_sane_decode(url_cases[x].s, slen1, tmp, &l1)); + DO(do_compare_testvector(tmp, l1, special_case, sizeof(special_case) - 1, "base64url_sane_decode/strict", x)); + DO(base64url_decode(url_cases[x].s, slen1, tmp, &l1)); + DO(do_compare_testvector(tmp, l1, special_case, sizeof(special_case) - 1, "base64url_decode/strict", x)); + } + else if(url_cases[x].flag == relaxed) { + DO(base64url_strict_decode(url_cases[x].s, slen1, tmp, &l1) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR); + DO(base64url_sane_decode(url_cases[x].s, slen1, tmp, &l1)); + DO(do_compare_testvector(tmp, l1, special_case, sizeof(special_case) - 1, "base64url_sane_decode/relaxed", x)); + DO(base64url_decode(url_cases[x].s, slen1, tmp, &l1)); + DO(do_compare_testvector(tmp, l1, special_case, sizeof(special_case) - 1, "base64url_decode/relaxed", x)); + } + else if(url_cases[x].flag == insane) { + DO(base64url_strict_decode(url_cases[x].s, slen1, tmp, &l1) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR); + DO(base64url_sane_decode(url_cases[x].s, slen1, tmp, &l1) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR); + DO(base64url_decode(url_cases[x].s, slen1, tmp, &l1)); + DO(do_compare_testvector(tmp, l1, special_case, sizeof(special_case) - 1, "base64url_decode/insane", x)); + } + else { /* invalid */ + DO(base64url_strict_decode(url_cases[x].s, slen1, tmp, &l1) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR); + DO(base64url_sane_decode(url_cases[x].s, slen1, tmp, &l1) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR); + DO(base64url_decode(url_cases[x].s, slen1, tmp, &l1) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR); + } + l2 = sizeof(out); + if(x == 0) { + DO(base64url_encode(tmp, l1, out, &l2)); + DO(do_compare_testvector(out, l2, url_cases[x].s, XSTRLEN(url_cases[x].s), "base64url_encode", x)); + } + if(x == 1) { + DO(base64url_strict_encode(tmp, l1, out, &l2)); + DO(do_compare_testvector(out, l2, url_cases[x].s, XSTRLEN(url_cases[x].s), "base64url_strict_encode", x)); + } + } +#endif + +#if defined(LTC_BASE64) + for (x = 0; x < sizeof(cases)/sizeof(cases[0]); ++x) { + memset(out, 0, sizeof(out)); + memset(tmp, 0, sizeof(tmp)); + slen1 = XSTRLEN(cases[x].s); + l1 = sizeof(out); + DO(base64_encode((unsigned char*)cases[x].s, slen1, out, &l1)); + DO(do_compare_testvector(out, l1, cases[x].b64, XSTRLEN(cases[x].b64), "base64_encode", x)); + l2 = sizeof(tmp); + DO(base64_strict_decode(out, l1, tmp, &l2)); + DO(do_compare_testvector(tmp, l2, cases[x].s, slen1, "base64_strict_decode", x)); + DO(base64_sane_decode(out, l1, tmp, &l2)); + DO(do_compare_testvector(tmp, l2, cases[x].s, slen1, "base64_sane_decode", x)); + DO(base64_decode(out, l1, tmp, &l2)); + DO(do_compare_testvector(tmp, l2, cases[x].s, slen1, "base64_decode", x)); + } + + for (x = 0; x < 64; x++) { + ENSURE(yarrow_read(in, x, &yarrow_prng) == x); + l1 = sizeof(out); + DO(base64_encode(in, x, out, &l1)); + l2 = sizeof(tmp); + DO(base64_decode(out, l1, tmp, &l2)); + DO(do_compare_testvector(tmp, x, in, x, "random base64", x)); + } + + x--; + memmove(&out[11], &out[10], l1 - 10); + l1++; + l2 = sizeof(tmp); + + out[10] = 0; + DO(base64_decode(out, l1, tmp, &l2)); + DO(compare_testvector(tmp, l2, in, l2, "insane base64 decoding (NUL)", 0)); + DO(base64_sane_decode(out, l1, tmp, &l2) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET); + DO(base64_strict_decode(out, l1, tmp, &l2) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET); + + out[10] = 9; /* tab */ + DO(base64_decode(out, l1, tmp, &l2)); + DO(compare_testvector(tmp, l2, in, l2, "insane base64 decoding (TAB)", 0)); + DO(base64_sane_decode(out, l1, tmp, &l2)); + DO(compare_testvector(tmp, l2, in, l2, "relaxed base64 decoding (TAB)", 0)); + DO(base64_strict_decode(out, l1, tmp, &l2) == CRYPT_INVALID_PACKET ? CRYPT_OK : CRYPT_INVALID_PACKET); + + memset(in, 'A', sizeof(in)); + l1 = strlen(As_lf); + SHOULD_FAIL(base64_encode_pem(in, 51, out, &l1, 0)); + l1++; + DO(base64_encode_pem(in, 51, out, &l1, 0)); + DO(compare_testvector(out, l1, As_lf, strlen(As_lf), "PEM output with \\n", 0)); + l1 = strlen(As_crlf) + 1; + DO(base64_encode_pem(in, 51, out, &l1, BASE64_PEM_CRLF)); + DO(compare_testvector(out, l1, As_crlf, strlen(As_crlf), "PEM output with \\r\\n", 0)); + l1 = strlen(As_ssh_lf) + 1; + DO(base64_encode_pem(in, 57, out, &l1, BASE64_PEM_SSH)); + DO(compare_testvector(out, l1, As_ssh_lf, strlen(As_ssh_lf), "PEM SSH-style output with \\n", 0)); + l1 = strlen(As_ssh_crlf) + 1; + DO(base64_encode_pem(in, 57, out, &l1, BASE64_PEM_SSH | BASE64_PEM_CRLF)); + DO(compare_testvector(out, l1, As_ssh_crlf, strlen(As_ssh_crlf), "PEM SSH-style output with \\r\\n", 0)); +#endif + + return 0; +} +#endif diff --git a/deps/libtomcrypt/tests/bcrypt_test.c b/deps/libtomcrypt/tests/bcrypt_test.c new file mode 100644 index 0000000..e14c4de --- /dev/null +++ b/deps/libtomcrypt/tests/bcrypt_test.c @@ -0,0 +1,146 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +#ifdef LTC_BCRYPT + +/** These tests were shamelessly c&p'ed from the OpenBSD sources + * https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/regress/lib/libutil/bcrypt_pbkdf/bcrypt_pbkdf_test.c */ + +struct test { + unsigned int rounds; + unsigned long passlen; + const char *password; + unsigned long saltlen; + const char *salt; + unsigned long keylen; + const char *key; +}; + +struct test tests[] = { + /* basic */ + { 4, 8, "password", 4, "salt", 32, + "\x5b\xbf\x0c\xc2\x93\x58\x7f\x1c\x36\x35\x55\x5c\x27\x79\x65\x98" + "\xd4\x7e\x57\x90\x71\xbf\x42\x7e\x9d\x8f\xbe\x84\x2a\xba\x34\xd9" + }, + { 4, 8, "password", 1, "", 16, + "\xc1\x2b\x56\x62\x35\xee\xe0\x4c\x21\x25\x98\x97\x0a\x57\x9a\x67" + }, + { 4, 1, "", 4, "salt", 16, + "\x60\x51\xbe\x18\xc2\xf4\xf8\x2c\xbf\x0e\xfe\xe5\x47\x1b\x4b\xb9" + }, + /* nul bytes in password and string */ + { 4, 9, "password", 5, "salt", 32, + "\x74\x10\xe4\x4c\xf4\xfa\x07\xbf\xaa\xc8\xa9\x28\xb1\x72\x7f\xac" + "\x00\x13\x75\xe7\xbf\x73\x84\x37\x0f\x48\xef\xd1\x21\x74\x30\x50" + }, + { 4, 8, "pass\0word", 4, "sa\0lt", 16, + "\xc2\xbf\xfd\x9d\xb3\x8f\x65\x69\xef\xef\x43\x72\xf4\xde\x83\xc0" + }, + { 4, 9, "pass\0word", 5, "sa\0lt", 16, + "\x4b\xa4\xac\x39\x25\xc0\xe8\xd7\xf0\xcd\xb6\xbb\x16\x84\xa5\x6f" + }, + /* bigger key */ + { 8, 8, "password", 4, "salt", 64, + "\xe1\x36\x7e\xc5\x15\x1a\x33\xfa\xac\x4c\xc1\xc1\x44\xcd\x23\xfa" + "\x15\xd5\x54\x84\x93\xec\xc9\x9b\x9b\x5d\x9c\x0d\x3b\x27\xbe\xc7" + "\x62\x27\xea\x66\x08\x8b\x84\x9b\x20\xab\x7a\xa4\x78\x01\x02\x46" + "\xe7\x4b\xba\x51\x72\x3f\xef\xa9\xf9\x47\x4d\x65\x08\x84\x5e\x8d" + }, + /* more rounds */ + { 42, 8, "password", 4, "salt", 16, + "\x83\x3c\xf0\xdc\xf5\x6d\xb6\x56\x08\xe8\xf0\xdc\x0c\xe8\x82\xbd" + }, + /* longer password */ + { 8, 446, + "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do " + "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut " + "enim ad minim veniam, quis nostrud exercitation ullamco laboris " + "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor " + "in reprehenderit in voluptate velit esse cillum dolore eu fugiat " + "nulla pariatur. Excepteur sint occaecat cupidatat non proident, " + "sunt in culpa qui officia deserunt mollit anim id est laborum.", + 6, "salis", 16, + "\x10\x97\x8b\x07\x25\x3d\xf5\x7f\x71\xa1\x62\xeb\x0e\x8a\xd3\x0a" + }, + /* "unicode" */ + { 8, + 16, "\x0d\xb3\xac\x94\xb3\xee\x53\x28\x4f\x4a\x22\x89\x3b\x3c\x24\xae", + 16, "\x3a\x62\xf0\xf0\xdb\xce\xf8\x23\xcf\xcc\x85\x48\x56\xea\x10\x28", + 16, "\x20\x44\x38\x17\x5e\xee\x7c\xe1\x36\xc9\x1b\x49\xa6\x79\x23\xff" + }, + /* very large key */ + { 8, + 16, "\x0d\xb3\xac\x94\xb3\xee\x53\x28\x4f\x4a\x22\x89\x3b\x3c\x24\xae", + 16, "\x3a\x62\xf0\xf0\xdb\xce\xf8\x23\xcf\xcc\x85\x48\x56\xea\x10\x28", + 256, + "\x20\x54\xb9\xff\xf3\x4e\x37\x21\x44\x03\x34\x74\x68\x28\xe9\xed" + "\x38\xde\x4b\x72\xe0\xa6\x9a\xdc\x17\x0a\x13\xb5\xe8\xd6\x46\x38" + "\x5e\xa4\x03\x4a\xe6\xd2\x66\x00\xee\x23\x32\xc5\xed\x40\xad\x55" + "\x7c\x86\xe3\x40\x3f\xbb\x30\xe4\xe1\xdc\x1a\xe0\x6b\x99\xa0\x71" + "\x36\x8f\x51\x8d\x2c\x42\x66\x51\xc9\xe7\xe4\x37\xfd\x6c\x91\x5b" + "\x1b\xbf\xc3\xa4\xce\xa7\x14\x91\x49\x0e\xa7\xaf\xb7\xdd\x02\x90" + "\xa6\x78\xa4\xf4\x41\x12\x8d\xb1\x79\x2e\xab\x27\x76\xb2\x1e\xb4" + "\x23\x8e\x07\x15\xad\xd4\x12\x7d\xff\x44\xe4\xb3\xe4\xcc\x4c\x4f" + "\x99\x70\x08\x3f\x3f\x74\xbd\x69\x88\x73\xfd\xf6\x48\x84\x4f\x75" + "\xc9\xbf\x7f\x9e\x0c\x4d\x9e\x5d\x89\xa7\x78\x39\x97\x49\x29\x66" + "\x61\x67\x07\x61\x1c\xb9\x01\xde\x31\xa1\x97\x26\xb6\xe0\x8c\x3a" + "\x80\x01\x66\x1f\x2d\x5c\x9d\xcc\x33\xb4\xaa\x07\x2f\x90\xdd\x0b" + "\x3f\x54\x8d\x5e\xeb\xa4\x21\x13\x97\xe2\xfb\x06\x2e\x52\x6e\x1d" + "\x68\xf4\x6a\x4c\xe2\x56\x18\x5b\x4b\xad\xc2\x68\x5f\xbe\x78\xe1" + "\xc7\x65\x7b\x59\xf8\x3a\xb9\xab\x80\xcf\x93\x18\xd6\xad\xd1\xf5" + "\x93\x3f\x12\xd6\xf3\x61\x82\xc8\xe8\x11\x5f\x68\x03\x0a\x12\x44" + }, +}; + +int bcrypt_test(void) +{ + unsigned long l; + unsigned char key[1024]; + unsigned int i; + int idx; + struct test *t; + + idx = find_hash("sha512"); + + XMEMSET(key, 0, sizeof(key)); + l = 88; + DO(bcrypt_pbkdf_openbsd("password", 8, (unsigned char*)"salt", 4, 0, idx, key, &l)); + for (i = 1; i < 88; ++i) { + key[0] |= key[i]; + } + if (key[0] == 0) { + return CRYPT_FAIL_TESTVECTOR; + } + if (key[88] || key[89] || key[90]) { + return CRYPT_BUFFER_OVERFLOW; + } +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + printf("BCRYPT overflow-test OK\n"); +#endif + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + t = &tests[i]; + l = t->keylen; + XMEMSET(key, 0, sizeof(key)); + DO(bcrypt_pbkdf_openbsd(t->password, t->passlen, (unsigned char*)t->salt, t->saltlen, t->rounds, idx, key, &l)); + DO(do_compare_testvector(key, l, (unsigned char*)t->key, t->keylen, "OpenBSD testvectors", i)); + +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + printf("BCRYPT test #%d OK\n", i); +#endif + } + + return CRYPT_OK; +} + +#else + + +int bcrypt_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/deps/libtomcrypt/tests/cipher_hash_test.c b/deps/libtomcrypt/tests/cipher_hash_test.c new file mode 100644 index 0000000..ba4041d --- /dev/null +++ b/deps/libtomcrypt/tests/cipher_hash_test.c @@ -0,0 +1,50 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* test the ciphers and hashes using their built-in self-tests */ + +#include + +int cipher_hash_test(void) +{ + int x; + + /* test block ciphers */ + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + DOX(cipher_descriptor[x].test(), cipher_descriptor[x].name); + } + + /* test stream ciphers */ +#ifdef LTC_CHACHA + DO(chacha_test()); +#endif +#ifdef LTC_SALSA20 + DO(salsa20_test()); +#endif +#ifdef LTC_XSALSA20 + DO(xsalsa20_test()); +#endif +#ifdef LTC_SOSEMANUK + DO(sosemanuk_test()); +#endif +#ifdef LTC_RABBIT + DO(rabbit_test()); +#endif +#ifdef LTC_RC4_STREAM + DO(rc4_stream_test()); +#endif +#ifdef LTC_SOBER128_STREAM + DO(sober128_stream_test()); +#endif + + /* test hashes */ + for (x = 0; hash_descriptor[x].name != NULL; x++) { + DOX(hash_descriptor[x].test(), hash_descriptor[x].name); + } + +#ifdef LTC_SHA3 + /* SHAKE128 + SHAKE256 tests are a bit special */ + DOX(sha3_shake_test(), "sha3_shake"); +#endif + + return 0; +} diff --git a/deps/libtomcrypt/tests/common.c b/deps/libtomcrypt/tests/common.c new file mode 100644 index 0000000..41ac7d0 --- /dev/null +++ b/deps/libtomcrypt/tests/common.c @@ -0,0 +1,166 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "common.h" + +/** + @file common.c + + Steffen Jaeckel +*/ + +void run_cmd(int res, int line, const char *file, const char *cmd, const char *algorithm) +{ + if (res != CRYPT_OK) { + fprintf(stderr, "%s (%d)%s%s\n%s:%d:%s\n", + error_to_string(res), res, + (algorithm ? " - " : ""), (algorithm ? algorithm : ""), + file, line, cmd); + if (res != CRYPT_NOP) { + exit(EXIT_FAILURE); + } + } +} + +void print_hex(const char* what, const void* v, const unsigned long l) +{ + const unsigned char* p = v; + unsigned long x, y = 0, z; + fprintf(stderr, "%s contents: \n", what); + for (x = 0; x < l; ) { + fprintf(stderr, "%02X ", p[x]); + if (!(++x % 16) || x == l) { + if((x % 16) != 0) { + z = 16 - (x % 16); + if(z >= 8) + fprintf(stderr, " "); + for (; z != 0; --z) { + fprintf(stderr, " "); + } + } + fprintf(stderr, " | "); + for(; y < x; y++) { + if((y % 8) == 0) + fprintf(stderr, " "); + if(isgraph(p[y])) + fprintf(stderr, "%c", p[y]); + else + fprintf(stderr, "."); + } + fprintf(stderr, "\n"); + } + else if((x % 8) == 0) { + fprintf(stderr, " "); + } + } +} + +int do_compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which) +{ + if (compare_testvector(is, is_len, should, should_len, what, which) == 0) { + return CRYPT_OK; + } else { + return CRYPT_FAIL_TESTVECTOR; + } +} + + +#ifdef LTC_TEST_READDIR + +#include +#include +#include + +static off_t fsize(const char *filename) +{ + struct stat st; + + if (stat(filename, &st) == 0) return st.st_size; + + return -1; +} +static DIR *s_opendir(const char *path, char *mypath, unsigned long l) +{ +#ifdef CMAKE_SOURCE_DIR +#define SOURCE_PREFIX CMAKE_SOURCE_DIR "/" +#else +#define SOURCE_PREFIX "" +#endif + DIR *d = NULL; + int r = snprintf(mypath, l, "%s%s", SOURCE_PREFIX, path); + if (r > 0 && (unsigned int)r < l) { + d = opendir(mypath); + } + + return d; +} + +int test_process_dir(const char *path, void *ctx, dir_iter_cb process, dir_cleanup_cb cleanup, const char *test) +{ + char mypath[PATH_MAX]; + DIR *d = s_opendir(path, mypath, sizeof(mypath)); + struct dirent *de; + char fname[PATH_MAX]; + void* buf = NULL; + FILE *f = NULL; + off_t fsz; + unsigned long sz; + int err = CRYPT_FILE_NOTFOUND; + if (d == NULL) + return CRYPT_FILE_NOTFOUND; + while((de = readdir(d)) != NULL) { + fname[0] = '\0'; + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0 || strcmp(de->d_name, "README.txt") == 0) + continue; + strcat(fname, mypath); + strcat(fname, "/"); + strcat(fname, de->d_name); + fsz = fsize(fname); + if (fsz == -1) { + err = CRYPT_FILE_NOTFOUND; + break; + } +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + fprintf(stderr, "%s: Try to process %s\n", test, fname); +#endif + f = fopen(fname, "rb"); + sz = fsz; + buf = XMALLOC(fsz); + if (fread(buf, 1, sz, f) != sz) { + err = CRYPT_ERROR; + break; + } + + err = process(buf, sz, ctx); + if (err == CRYPT_NOP) { +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + fprintf(stderr, "%s: Skip: %s\n", test, fname); +#endif + goto continue_loop; + } else if (err != CRYPT_OK) { +#if defined(LTC_TEST_DBG) + fprintf(stderr, "%s: Test %s failed (cause: %s).\n\n", test, fname, error_to_string(err)); +#else + LTC_UNUSED_PARAM(test); +#endif + break; + } + if ((err != CRYPT_NOP) && (cleanup != NULL)) { + cleanup(ctx); + } + +continue_loop: + XFREE(buf); + buf = NULL; + fclose(f); + f = NULL; + } + if (buf != NULL) XFREE(buf); + if (f != NULL) fclose(f); + closedir(d); + return err; +} +#endif + + +prng_state yarrow_prng; diff --git a/deps/libtomcrypt/tests/common.h b/deps/libtomcrypt/tests/common.h new file mode 100644 index 0000000..66c0f95 --- /dev/null +++ b/deps/libtomcrypt/tests/common.h @@ -0,0 +1,43 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#ifndef DEMOS_COMMON_H_ +#define DEMOS_COMMON_H_ + +#include + +extern prng_state yarrow_prng; + +#ifdef LTC_VERBOSE +#define DO(x) do { fprintf(stderr, "%s:\n", #x); run_cmd((x), __LINE__, __FILE__, #x, NULL); } while (0) +#define DOX(x, str) do { fprintf(stderr, "%s - %s:\n", #x, (str)); run_cmd((x), __LINE__, __FILE__, #x, (str)); } while (0) +#define SHOULD_FAIL(x) do { fprintf(stderr, "%s:\n", #x); run_cmd((x) != CRYPT_OK ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define SHOULD_FAIL_WITH(x, e) do { fprintf(stderr, "%s:\n", #x); run_cmd((x) == (e) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define ENSURE(x) do { fprintf(stderr, "%s:\n", #x); run_cmd(((x)) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define ENSUREX(x, str) do { fprintf(stderr, "%s:\n", #x); run_cmd(((x)) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, (str)); } while (0) +#else +#define DO(x) do { run_cmd((x), __LINE__, __FILE__, #x, NULL); } while (0) +#define DOX(x, str) do { run_cmd((x), __LINE__, __FILE__, #x, (str)); } while (0) +#define SHOULD_FAIL(x) do { run_cmd((x) != CRYPT_OK ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define SHOULD_FAIL_WITH(x, e) do { run_cmd((x) == (e) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define ENSURE(x) do { run_cmd(((x)) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, NULL); } while (0) +#define ENSUREX(x, str) do { run_cmd(((x)) ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR, __LINE__, __FILE__, #x, (str)); } while (0) +#endif + +#define COMPARE_TESTVECTOR(i, il, s, sl, wa, wi) do { DO(do_compare_testvector((i), (il), (s), (sl), (wa), (wi))); } while(0) + +#if !((defined(_WIN32) || defined(_WIN32_WCE)) && !defined(__GNUC__)) +#define LTC_TEST_READDIR + +typedef int (*dir_iter_cb)(const void *d, unsigned long l, void* ctx); +typedef void (*dir_cleanup_cb)(void* ctx); + +int test_process_dir(const char *path, void *ctx, dir_iter_cb iter, dir_cleanup_cb cleanup, const char *test); +#endif + +void run_cmd(int res, int line, const char *file, const char *cmd, const char *algorithm); + +void print_hex(const char* what, const void* v, const unsigned long l); + +int do_compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); + +#endif /* DEMOS_COMMON_H_ */ diff --git a/deps/libtomcrypt/tests/der_test.c b/deps/libtomcrypt/tests/der_test.c new file mode 100644 index 0000000..3b8354b --- /dev/null +++ b/deps/libtomcrypt/tests/der_test.c @@ -0,0 +1,2024 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if !defined(LTC_DER) + +int der_test(void) +{ + return CRYPT_NOP; +} + +#else + +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 2 +#define LTC_DER_TESTS_PRINT_FLEXI +#endif + +static const char s_der_tests_stinky_root_cert[] = + "MIIFETCCA/mgAwIBAgIQbv53JNmv518t5lkCHE272jANBgkqhkiG9w0BAQUFADCB" + "lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug" + "Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho" + "dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt" + "T2JqZWN0MB4XDTA4MDQyOTAwMDAwMFoXDTEwMDQyOTIzNTk1OVowgbUxCzAJBgNV" + "BAYTAlVTMQ4wDAYDVQQRDAU0NDE0MzELMAkGA1UECAwCT0gxGTAXBgNVBAcMEE1h" + "eWZpZWxkIFZpbGxhZ2UxEDAOBgNVBAkMB1N1aXRlIEExFDASBgNVBAkMCzc2NyBC" + "ZXRhIERyMSIwIAYDVQQKDBlQcmVlbXB0aXZlIFNvbHV0aW9ucywgTExDMSIwIAYD" + "VQQDDBlQcmVlbXB0aXZlIFNvbHV0aW9ucywgTExDMIIBIjANBgkqhkiG9w0BAQEF" + "AAOCAQ8AMIIBCgKCAQEAzH7ZBkMcBuHx8d2f10RGTHAf7gzzVteGbOihJGH2BwlS" + "ZvNp6WEE4DfL+s1vp0wzk1XeLN5tRjg2qum9YqyCk7okh7pXGy46f5mWbLQiefGA" + "j5UXRcr6WJ3xeACdbXxKrYMV0REia+4Jb2UbFA8S81PjhRon6vcRz76ziUWwt8NC" + "igX+4ZC0skhhKzKszel6KGL7bJCtLG7ukw9DZCrvPCRcKFeM/GwQ6ACMgP88CSCL" + "t1fbIXDH1vd/x2XM3QlaSDN6hYDbef8m1T+9TCkXVKeqG1GYjSUrHzYnCZUmTRrR" + "38jgC3qXxiIpDKW105uM0nlXe2XF9c+ot2MdWvV4TwIDAQABo4IBOTCCATUwHwYD" + "VR0jBBgwFoAU2u1kdBScFDyr3ZmpvVsoTYs8ydgwHQYDVR0OBBYEFK+1HzZE4i28" + "oLIzuqlFR9SspiCIMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1Ud" + "JQQMMAoGCCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIEEDBGBgNVHSAEPzA9MDsG" + "DCsGAQQBsjEBAgEDAjArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21v" + "ZG8ubmV0L0NQUzBCBgNVHR8EOzA5MDegNaAzhjFodHRwOi8vY3JsLnVzZXJ0cnVz" + "dC5jb20vVVROLVVTRVJGaXJzdC1PYmplY3QuY3JsMCEGA1UdEQQaMBiBFnN1cHBv" + "cnRAcHJlZW1wdGl2ZS5jb20wDQYJKoZIhvcNAQEFBQADggEBAC+JM26Dokvonudl" + "JXe/Yun7IBhimkagZUjbk9l/GQWN6i+v1o95UJ1wGJtBdm2+MxbSaPoNTDZR4B+2" + "lYL9MW57UVmePrnfUPXQKZZG+8gTRDz8+7ol/CEAKmS3MLKCRcH5oe+J5345sGxi" + "FC/KWNKedTNraW95xlg8NTlL2yRP7TMsjvBxgLmkbaFUoXzPTbQWmtovIagIT8GC" + "JeXwdFaRjbamiz3Irl+u7x/mhxdza6RvgBYylXRFMudANpeGsV7gDXlnfzpFDKHQ" + "niVwB7P5sbPFIlmIc+4/xRItkLIRjCVXaepgN9KYu3VOgiSDI6wXiTwP44/LUXQM" + "hetwa7s="; +const char ltc_der_tests_cacert_root_cert[] = + "MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290" + "IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB" + "IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA" + "Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO" + "BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi" + "MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ" + "ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC" + "CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ" + "8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6" + "zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y" + "fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7" + "w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc" + "G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k" + "epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q" + "laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ" + "QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU" + "fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826" + "YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w" + "ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY" + "gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe" + "MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0" + "IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy" + "dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw" + "czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0" + "dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl" + "aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC" + "AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg" + "b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB" + "ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc" + "nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg" + "18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c" + "gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl" + "Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY" + "sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T" + "SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF" + "CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum" + "GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk" + "zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW" + "omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD"; +const unsigned long ltc_der_tests_cacert_root_cert_size = sizeof(ltc_der_tests_cacert_root_cert); + +/* +SEQUENCE(3 elem) + SEQUENCE(8 elem) + [0](1) + INTEGER 2 + INTEGER 0 + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.1.4 + NULL + SEQUENCE(4 elem) + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.10 + PrintableString Root CA + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.11 + PrintableString http://www.cacert.org + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.3 + PrintableString CA Cert Signing Authority + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.9.1 + IA5String support@cacert.org + SEQUENCE(2 elem) + UTCTime03-03-30 12:29:49 UTC + UTCTime33-03-29 12:29:49 UTC + SEQUENCE(4 elem) + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.10 + PrintableString Root CA + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.11 + PrintableString http://www.cacert.org + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.3 + PrintableString CA Cert Signing Authority + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.9.1 + IA5String support@cacert.org + SEQUENCE(2 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.1.1 + NULL + BIT STRING(1 elem) + SEQUENCE(2 elem) + INTEGER (4096 bit) + INTEGER 65537 + [3](1) + SEQUENCE(7 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.29.14 + OCTET STRING(1 elem) + OCTET STRING(20 byte) 16B5321BD4C7F3E0E68EF3BDD2B03AEEB23918D1 + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.29.35 + OCTET STRING(1 elem) + SEQUENCE(3 elem) + [0] + [1](1) + [4](1) + SEQUENCE(4 elem) + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.10 + PrintableString Root CA + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.11 + PrintableString http://www.cacert.org + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.3 + PrintableString CA Cert Signing Authority + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.9.1 + IA5String support@cacert.org + [2] + SEQUENCE(3 elem) + OBJECT IDENTIFIER 2.5.29.19 + BOOLEAN true + OCTET STRING(1 elem) + SEQUENCE(1 elem) + BOOLEAN true + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.29.31 + OCTET STRING(1 elem) + SEQUENCE(1 elem) + SEQUENCE(1 elem) + [0](1) + [0](1) + [6] + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.16.840.1.113730.1.4 + OCTET STRING(1 elem) + IA5String https://www.cacert.org/revoke.crl + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.16.840.1.113730.1.8 + OCTET STRING(1 elem) + IA5String http://www.cacert.org/index.php?id=10 + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.16.840.1.113730.1.13 + OCTET STRING(1 elem) + IA5String To get your own certificate for FREE head over to http://www.cacert.org + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.1.4 + NULL + BIT STRING(4096 bit) + */ + +#define ASN1_FMTSTRING_FMT "line: %d, type=%d, size=%lu, data=%p, self=%p, next=%p, prev=%p, parent=%p, child=%p" +#define ASN1_FMTSTRING_VAL(l) __LINE__, (l)->type, (l)->size, (l)->data, (l), (l)->next, (l)->prev, (l)->parent, (l)->child + +#define ASN1_ERR(l) fprintf(stderr, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l)); \ + exit(EXIT_FAILURE) + +#define CHECK_ASN1_HAS(l, w) do { if ((l)->w == NULL) { \ + ASN1_ERR(l);\ +} } while(0) + +#define CHECK_ASN1_HAS_NO(l, w) do { if ((l)->w != NULL) { \ + ASN1_ERR(l);\ +} } while(0) + +#define CHECK_ASN1_TYPE(l, t) do { if ((l)->type != (t)) { \ + ASN1_ERR(l);\ +} } while(0) + +#define CHECK_ASN1_HAS_CHILD(l) CHECK_ASN1_HAS(l, child) +#define CHECK_ASN1_HAS_NO_CHILD(l) CHECK_ASN1_HAS_NO(l, child) +#define CHECK_ASN1_HAS_NEXT(l) CHECK_ASN1_HAS(l, next) +#define CHECK_ASN1_HAS_NO_NEXT(l) CHECK_ASN1_HAS_NO(l, next) +#define CHECK_ASN1_HAS_DATA(l) CHECK_ASN1_HAS(l, data) +#define CHECK_ASN1_HAS_NO_DATA(l) CHECK_ASN1_HAS_NO(l, data) + +#ifdef LTC_DER_TESTS_PRINT_FLEXI + +static void* s_xmalloc(int l) +{ + void *r = XMALLOC(l); + +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3 + fprintf(stderr, "ALLOC %9d to %p\n", l, r); +#endif + if (!r) { + fprintf(stderr, "Could not allocate %d bytes of memory\n", l); + exit(EXIT_FAILURE); + } + return r; +} + +static void s_free(void *p) +{ +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3 + fprintf(stderr, "FREE %p\n", p); +#endif + XFREE(p); +} + +static void s_der_tests_print_flexi(ltc_asn1_list* l, unsigned int level) +{ + char *buf = NULL; + const char* name = NULL; + const char* text = NULL; + ltc_asn1_list* ostring = NULL; + unsigned int n; + int slen; + + switch (l->type) + { + case LTC_ASN1_EOL: + name = "EOL"; + slen = snprintf(NULL, 0, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l)); + buf = s_xmalloc(slen); + slen = snprintf(buf, slen, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l)); + text = buf; + break; + case LTC_ASN1_BOOLEAN: + name = "BOOLEAN"; + { + if (*(int*)l->data) + text = "true"; + else + text = "false"; + } + break; + case LTC_ASN1_INTEGER: + name = "INTEGER"; + buf = s_xmalloc(((mp_get_digit_count(l->data) + 1) * ltc_mp.bits_per_digit) / 3); + mp_toradix(l->data, buf, 10); + text = buf; + break; + case LTC_ASN1_SHORT_INTEGER: + name = "SHORT INTEGER"; + break; + case LTC_ASN1_BIT_STRING: + name = "BIT STRING"; + break; + case LTC_ASN1_OCTET_STRING: + name = "OCTET STRING"; + { + unsigned long ostring_l = l->size; + /* sometimes there's another sequence in an octet string... + * try to decode that... if it fails print out the octet string + */ + if (der_decode_sequence_flexi(l->data, &ostring_l, &ostring) == CRYPT_OK) { + text = ""; + } else { + int r; + int sz = l->size * 2 + 1; + char* s = buf = s_xmalloc(sz); + for (n = 0; n < l->size; ++n) { + r = snprintf(s, sz, "%02X", ((unsigned char*)l->data)[n]); + if (r < 0 || r >= sz) { + fprintf(stderr, "%s boom\n", name); + exit(EXIT_FAILURE); + } + s += r; + sz -= r; + } + text = buf; + } + } + break; + case LTC_ASN1_NULL: + name = "NULL"; + text = ""; + break; + case LTC_ASN1_OBJECT_IDENTIFIER: + name = "OBJECT IDENTIFIER"; + { + unsigned long len = 0; + if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_BUFFER_OVERFLOW) { + fprintf(stderr, "%s WTF\n", name); + exit(EXIT_FAILURE); + } + buf = s_xmalloc(len); + if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_OK) { + fprintf(stderr, "%s boom\n", name); + exit(EXIT_FAILURE); + } + text = buf; + } + break; + case LTC_ASN1_IA5_STRING: + name = "IA5 STRING"; + text = l->data; + break; + case LTC_ASN1_PRINTABLE_STRING: + name = "PRINTABLE STRING"; + text = l->data; + break; + case LTC_ASN1_UTF8_STRING: + name = "UTF8 STRING"; + break; + case LTC_ASN1_UTCTIME: + name = "UTCTIME"; + { + ltc_utctime* ut = l->data; + slen = 32; + buf = s_xmalloc(slen); + snprintf(buf, slen, "%02d-%02d-%02d %02d:%02d:%02d %c%02d:%02d", + ut->YY, ut->MM, ut->DD, ut->hh, ut->mm, ut->ss, + ut->off_dir ? '-' : '+', ut->off_hh, ut->off_mm); + text = buf; + } + break; + case LTC_ASN1_GENERALIZEDTIME: + name = "GENERALIZED TIME"; + { + ltc_generalizedtime* gt = l->data; + slen = 32; + buf = s_xmalloc(slen); + if(gt->fs) + snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02d.%02dZ", + gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm, gt->ss, gt->fs); + else + snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02dZ", + gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm, gt->ss); + text = buf; + } + break; + case LTC_ASN1_CHOICE: + name = "CHOICE"; + break; + case LTC_ASN1_SEQUENCE: + name = "SEQUENCE"; + text = ""; + break; + case LTC_ASN1_SET: + name = "SET"; + text = ""; + break; + case LTC_ASN1_SETOF: + name = "SETOF"; + text = ""; + break; + case LTC_ASN1_RAW_BIT_STRING: + name = "RAW BIT STRING"; + break; + case LTC_ASN1_TELETEX_STRING: + name = "TELETEX STRING"; + text = l->data; + break; + case LTC_ASN1_CUSTOM_TYPE: + name = "NON STANDARD"; + { + int r; + int sz = 128; + char* s = buf = s_xmalloc(sz); + + r = snprintf(s, sz, "[%s %s %llu]", der_asn1_class_to_string_map[l->klass], der_asn1_pc_to_string_map[l->pc], l->tag); + if (r < 0 || r >= sz) { + fprintf(stderr, "%s boom\n", name); + exit(EXIT_FAILURE); + } + s += r; + sz -= r; + + text = buf; + } + break; + } + + for (n = 0; n < level; ++n) { + fprintf(stderr, " "); + } + if (name) { + if (text) + fprintf(stderr, "%s %s\n", name, text); + else + fprintf(stderr, "%s \n", name); + } + else + fprintf(stderr, "WTF type=%i\n", l->type); + + if (buf) { + s_free(buf); + buf = NULL; + } + + if (ostring) { + s_der_tests_print_flexi(ostring, level + 1); + der_free_sequence_flexi(ostring); + } + + if (l->child) + s_der_tests_print_flexi(l->child, level + 1); + + if (l->next) + s_der_tests_print_flexi(l->next, level); +} +#endif + +static void der_cacert_test(void) +{ + unsigned char buf[sizeof(ltc_der_tests_cacert_root_cert)]; + unsigned long len1 = sizeof(buf), len2; + + ltc_asn1_list *decoded_list, *l, *l1, *l2; + + DO(base64_decode(s_der_tests_stinky_root_cert, sizeof(s_der_tests_stinky_root_cert), buf, &len1)); + len2 = len1; + DO(der_decode_sequence_flexi(buf, &len2, &decoded_list)); + der_free_sequence_flexi(decoded_list); + + len1 = sizeof(buf); + DO(base64_decode(ltc_der_tests_cacert_root_cert, sizeof(ltc_der_tests_cacert_root_cert), buf, &len1)); + len2 = len1; + DO(der_decode_sequence_flexi(buf, &len2, &decoded_list)); + CHECK_ASN1_TYPE(decoded_list, LTC_ASN1_SEQUENCE); + CHECK_ASN1_HAS_DATA(decoded_list); + + der_sequence_shrink(decoded_list); + + CHECK_ASN1_TYPE(decoded_list, LTC_ASN1_SEQUENCE); + CHECK_ASN1_HAS_NO_DATA(decoded_list); + +#ifdef LTC_DER_TESTS_PRINT_FLEXI + printf("\n\n--- test print start ---\n\n"); + s_der_tests_print_flexi(decoded_list, 0); + printf("\n\n--- test print end ---\n\n"); +#endif + + l = decoded_list; + + /* +SEQUENCE(3 elem) + SEQUENCE(8 elem) + */ + + CHECK_ASN1_TYPE(l, LTC_ASN1_SEQUENCE); + CHECK_ASN1_HAS_CHILD(l); + CHECK_ASN1_HAS_NO_NEXT(l); + + l = l->child; + + CHECK_ASN1_TYPE(l, LTC_ASN1_SEQUENCE); + CHECK_ASN1_HAS_CHILD(l); + CHECK_ASN1_HAS_NEXT(l); + + l1 = l->child; + + /* + [0](1) + INTEGER 2 + */ + + CHECK_ASN1_TYPE(l1, LTC_ASN1_CUSTOM_TYPE); + CHECK_ASN1_HAS_CHILD(l1); + CHECK_ASN1_HAS_NEXT(l1); + + l2 = l1->child; + + CHECK_ASN1_TYPE(l2, LTC_ASN1_INTEGER); + CHECK_ASN1_HAS_NO_CHILD(l2); + CHECK_ASN1_HAS_NO_NEXT(l2); + + l1 = l1->next; + + /* + INTEGER 0 + */ + + CHECK_ASN1_TYPE(l1, LTC_ASN1_INTEGER); + CHECK_ASN1_HAS_NO_CHILD(l1); + CHECK_ASN1_HAS_NEXT(l1); + + l1 = l1->next; + + /* + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.1.4 + NULL + */ + + CHECK_ASN1_TYPE(l1, LTC_ASN1_SEQUENCE); + CHECK_ASN1_HAS_CHILD(l1); + CHECK_ASN1_HAS_NEXT(l1); + + l2 = l1->child; + + CHECK_ASN1_TYPE(l2, LTC_ASN1_OBJECT_IDENTIFIER); + CHECK_ASN1_HAS_NO_CHILD(l2); + CHECK_ASN1_HAS_NEXT(l2); + + l2 = l2->next; + + CHECK_ASN1_TYPE(l2, LTC_ASN1_NULL); + CHECK_ASN1_HAS_NO_CHILD(l2); + CHECK_ASN1_HAS_NO_NEXT(l2); + + /* + SEQUENCE(4 elem) + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.10 + PrintableString Root CA + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.11 + PrintableString http://www.cacert.org + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 2.5.4.3 + PrintableString CA Cert Signing Authority + SET(1 elem) + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.9.1 + IA5String support@cacert.org + */ + + l = l->next; + + /* + SEQUENCE(2 elem) + OBJECT IDENTIFIER 1.2.840.113549.1.1.4 + NULL + */ + + CHECK_ASN1_TYPE(l, LTC_ASN1_SEQUENCE); + CHECK_ASN1_HAS_CHILD(l); + CHECK_ASN1_HAS_NEXT(l); + + l1 = l->child; + + CHECK_ASN1_TYPE(l1, LTC_ASN1_OBJECT_IDENTIFIER); + CHECK_ASN1_HAS_NO_CHILD(l1); + CHECK_ASN1_HAS_NEXT(l1); + + l1 = l1->next; + + CHECK_ASN1_TYPE(l1, LTC_ASN1_NULL); + CHECK_ASN1_HAS_NO_CHILD(l1); + CHECK_ASN1_HAS_NO_NEXT(l1); + + l = l->next; + + /* + BIT STRING(4096 bit) + */ + + CHECK_ASN1_TYPE(l, LTC_ASN1_BIT_STRING); + CHECK_ASN1_HAS_NO_CHILD(l); + CHECK_ASN1_HAS_NO_NEXT(l); + + der_free_sequence_flexi(decoded_list); +} + +static void der_set_test(void) +{ + ltc_asn1_list list[10]; + static const unsigned char oct_str[] = { 1, 2, 3, 4 }; + static const unsigned char bin_str[] = { 1, 0, 0, 1 }; + static const unsigned long int_val = 12345678UL; + + unsigned char strs[10][10], outbuf[128]; + unsigned long x, val, outlen; + + /* make structure and encode it */ + LTC_SET_ASN1(list, 0, LTC_ASN1_OCTET_STRING, oct_str, sizeof(oct_str)); + LTC_SET_ASN1(list, 1, LTC_ASN1_BIT_STRING, bin_str, sizeof(bin_str)); + LTC_SET_ASN1(list, 2, LTC_ASN1_SHORT_INTEGER, &int_val, 1); + + /* encode it */ + outlen = sizeof(outbuf); + DO(der_encode_set(list, 3, outbuf, &outlen)); + + /* first let's test the set_decoder out of order to see what happens, we should get all the fields we expect even though they're in a diff order */ + LTC_SET_ASN1(list, 0, LTC_ASN1_BIT_STRING, strs[1], sizeof(strs[1])); + LTC_SET_ASN1(list, 1, LTC_ASN1_SHORT_INTEGER, &val, 1); + LTC_SET_ASN1(list, 2, LTC_ASN1_OCTET_STRING, strs[0], sizeof(strs[0])); + + DO(der_decode_set(outbuf, outlen, list, 3)); + + /* now compare the items */ + if (memcmp(strs[0], oct_str, sizeof(oct_str))) { + fprintf(stderr, "error decoding set using der_decode_set (oct_str is wrong):\n"); + exit(EXIT_FAILURE); + } + + if (memcmp(strs[1], bin_str, sizeof(bin_str))) { + fprintf(stderr, "error decoding set using der_decode_set (bin_str is wrong):\n"); + exit(EXIT_FAILURE); + } + + if (val != int_val) { + fprintf(stderr, "error decoding set using der_decode_set (int_val is wrong):\n"); + exit(EXIT_FAILURE); + } + + strcpy((char*)strs[0], "one"); + strcpy((char*)strs[1], "one2"); + strcpy((char*)strs[2], "two"); + strcpy((char*)strs[3], "aaa"); + strcpy((char*)strs[4], "aaaa"); + strcpy((char*)strs[5], "aab"); + strcpy((char*)strs[6], "aaab"); + strcpy((char*)strs[7], "bbb"); + strcpy((char*)strs[8], "bbba"); + strcpy((char*)strs[9], "bbbb"); + + for (x = 0; x < 10; x++) { + LTC_SET_ASN1(list, x, LTC_ASN1_PRINTABLE_STRING, strs[x], XSTRLEN((char*)strs[x])); + } + + outlen = sizeof(outbuf); + DO(der_encode_setof(list, 10, outbuf, &outlen)); + + for (x = 0; x < 10; x++) { + LTC_SET_ASN1(list, x, LTC_ASN1_PRINTABLE_STRING, strs[x], sizeof(strs[x]) - 1); + } + XMEMSET(strs, 0, sizeof(strs)); + + DO(der_decode_set(outbuf, outlen, list, 10)); + + /* now compare */ + for (x = 1; x < 10; x++) { + if (!(XSTRLEN((char*)strs[x-1]) <= XSTRLEN((char*)strs[x])) && strcmp((char*)strs[x-1], (char*)strs[x]) >= 0) { + fprintf(stderr, "error SET OF order at %lu is wrong\n", x); + exit(EXIT_FAILURE); + } + } + +} + + +/* we are encoding + + SEQUENCE { + PRINTABLE "printable" + IA5 "ia5" + SEQUENCE { + INTEGER 12345678 + UTCTIME { 91, 5, 6, 16, 45, 40, 1, 7, 0 } + GENERALIZEDTIME { 2017, 03, 21, 10, 21, 12, 4, 1, 2, 0 } + SEQUENCE { + OCTET STRING { 1, 2, 3, 4 } + BIT STRING { 1, 0, 0, 1 } + SEQUENCE { + OID { 1, 2, 840, 113549 } + NULL + SET OF { + PRINTABLE "333" -- WILL GET SORTED + PRINTABLE "222" + } + } + } + } + +*/ + +static void s_der_oid_test(void) +{ + static const unsigned char oid_x690_8_19_5_example[] = { 0x06, 0x03, 0x88, 0x37, 0x03 }; + unsigned long len, oid[3]; + unsigned char buf[64]; + + ltc_asn1_list *decoded_list, static_list[1]; + + len = sizeof(oid_x690_8_19_5_example); + DO(der_decode_sequence_flexi(oid_x690_8_19_5_example, &len, &decoded_list)); + + LTC_SET_ASN1(static_list, 0, LTC_ASN1_OBJECT_IDENTIFIER, (void *)decoded_list->data, decoded_list->size); + len = sizeof(buf); + DO(der_encode_object_identifier(decoded_list->data, decoded_list->size, buf, &len)); + der_sequence_free(decoded_list); + + DO(do_compare_testvector(buf, len, oid_x690_8_19_5_example, sizeof(oid_x690_8_19_5_example), "OID X6.90 Ch. 8.19.5 Example", 0)); + + oid[0] = 3; + oid[1] = 4; + oid[2] = 5; + + len = sizeof(buf); + SHOULD_FAIL(der_encode_object_identifier(oid, 3, buf, &len)); + len = sizeof(buf); + SHOULD_FAIL(der_length_object_identifier(oid, 3, &len)); +} + +static void der_flexi_test(void) +{ + static const char printable_str[] = "printable"; + static const char set1_str[] = "333"; + static const char set2_str[] = "222"; + static const char ia5_str[] = "ia5"; + static const unsigned long int_val = 12345678UL; + static const ltc_utctime utctime = { 91, 5, 6, 16, 45, 40, 1, 7, 0 }; + static const ltc_generalizedtime gtime = { 2017, 03, 21, 10, 21, 12, 421, 1, 2, 0 }; + static const unsigned char oct_str[] = { 1, 2, 3, 4 }; + static const unsigned char bit_str[] = { 1, 0, 0, 1 }; + static const unsigned long oid_str[] = { 1, 2, 840, 113549 }; + + unsigned char encode_buf[192]; + unsigned long encode_buf_len, decode_len; + + ltc_asn1_list static_list[5][4], *decoded_list, *l; + + /* build list */ + LTC_SET_ASN1(static_list[0], 0, LTC_ASN1_PRINTABLE_STRING, (void *)printable_str, XSTRLEN(printable_str)); + LTC_SET_ASN1(static_list[0], 1, LTC_ASN1_IA5_STRING, (void *)ia5_str, XSTRLEN(ia5_str)); + LTC_SET_ASN1(static_list[0], 2, LTC_ASN1_SEQUENCE, static_list[1], 4); + + LTC_SET_ASN1(static_list[1], 0, LTC_ASN1_SHORT_INTEGER, (void *)&int_val, 1); + LTC_SET_ASN1(static_list[1], 1, LTC_ASN1_UTCTIME, (void *)&utctime, 1); + LTC_SET_ASN1(static_list[1], 2, LTC_ASN1_GENERALIZEDTIME, (void *)>ime, 1); + LTC_SET_ASN1(static_list[1], 3, LTC_ASN1_SEQUENCE, static_list[2], 3); + + LTC_SET_ASN1(static_list[2], 0, LTC_ASN1_OCTET_STRING, (void *)oct_str, 4); + LTC_SET_ASN1(static_list[2], 1, LTC_ASN1_BIT_STRING, (void *)bit_str, 4); + LTC_SET_ASN1(static_list[2], 2, LTC_ASN1_SEQUENCE, static_list[3], 3); + + LTC_SET_ASN1(static_list[3], 0, LTC_ASN1_OBJECT_IDENTIFIER,(void *)oid_str, 4); + LTC_SET_ASN1(static_list[3], 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(static_list[3], 2, LTC_ASN1_SETOF, static_list[4], 2); + + LTC_SET_ASN1(static_list[4], 0, LTC_ASN1_PRINTABLE_STRING, set1_str, XSTRLEN(set1_str)); + LTC_SET_ASN1(static_list[4], 1, LTC_ASN1_PRINTABLE_STRING, set2_str, XSTRLEN(set2_str)); + + /* encode it */ + encode_buf_len = sizeof(encode_buf); + DO(der_encode_sequence(&static_list[0][0], 3, encode_buf, &encode_buf_len)); + +#if 0 + { + FILE *f; + f = fopen("t.bin", "wb"); + fwrite(encode_buf, 1, encode_buf_len, f); + fclose(f); + } +#endif + + /* decode with flexi */ + decode_len = encode_buf_len; + DO(der_decode_sequence_flexi(encode_buf, &decode_len, &decoded_list)); + + if (decode_len != encode_buf_len) { + fprintf(stderr, "Decode len of %lu does not match encode len of %lu \n", decode_len, encode_buf_len); + exit(EXIT_FAILURE); + } + + /* we expect l->next to be NULL and l->child to not be */ + l = decoded_list; + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* we expect a SEQUENCE */ + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + /* PRINTABLE STRING */ + /* we expect printable_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != XSTRLEN(printable_str) || memcmp(printable_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* IA5 STRING */ + /* we expect ia5_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_IA5_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != XSTRLEN(ia5_str) || memcmp(ia5_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + + /* INTEGER */ + + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_INTEGER) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (mp_cmp_d(l->data, 12345678UL) != LTC_MP_EQ) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* UTCTIME */ + + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_UTCTIME) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (memcmp(l->data, &utctime, sizeof(utctime))) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* GeneralizedTime */ + + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_GENERALIZEDTIME) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (memcmp(l->data, >ime, sizeof(gtime))) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + + /* OCTET STRING */ + /* we expect oct_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_OCTET_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != sizeof(oct_str) || memcmp(oct_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* BIT STRING */ + /* we expect oct_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_BIT_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != sizeof(bit_str) || memcmp(bit_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SEQUENCE) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + + /* OID STRING */ + /* we expect oid_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != sizeof(oid_str)/sizeof(oid_str[0]) || memcmp(oid_str, l->data, l->size*sizeof(oid_str[0]))) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* NULL */ + if (l->type != LTC_ASN1_NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* expect child anve move down */ + if (l->next != NULL || l->child == NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_SET) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + l = l->child; + + /* PRINTABLE STRING */ + /* we expect printable_str */ + if (l->next == NULL || l->child != NULL) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + +/* note we compare set2_str FIRST because the SET OF is sorted and "222" comes before "333" */ + if (l->size != XSTRLEN(set2_str) || memcmp(set2_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + /* move to next */ + l = l->next; + + /* PRINTABLE STRING */ + /* we expect printable_str */ + if (l->type != LTC_ASN1_PRINTABLE_STRING) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + if (l->size != XSTRLEN(set1_str) || memcmp(set1_str, l->data, l->size)) { + fprintf(stderr, "(%d), %d, %lu, next=%p, prev=%p, parent=%p, child=%p\n", __LINE__, l->type, l->size, l->next, l->prev, l->parent, l->child); + exit(EXIT_FAILURE); + } + + + der_sequence_free(l); + +} + +static int der_choice_n_custom_test(void) +{ + ltc_asn1_list types[10], host[1], custom[1], root[1], child[1]; + int boolean[1]; + unsigned char bitbuf[10], octetbuf[10], ia5buf[10], printbuf[10], outbuf[256], custbuf[256], x, y; + wchar_t utf8buf[10]; + unsigned long integer, oidbuf[10], outlen, custlen, inlen, n; + void *mpinteger; + ltc_utctime utctime = { 91, 5, 6, 16, 45, 40, 1, 7, 0 }; + ltc_generalizedtime gtime = { 2038, 01, 19, 3, 14, 8, 0, 0, 0, 0 }; + + /* setup variables */ + for (x = 0; x < sizeof(bitbuf); x++) { bitbuf[x] = x & 1; } + for (x = 0; x < sizeof(octetbuf); x++) { octetbuf[x] = x; } + for (x = 0; x < sizeof(ia5buf); x++) { ia5buf[x] = 'a'; } + for (x = 0; x < sizeof(printbuf); x++) { printbuf[x] = 'a'; } + for (x = 0; x < sizeof(utf8buf)/sizeof(utf8buf[0]); x++) { utf8buf[x] = L'a'; } + integer = 1; + boolean[0] = 1; + for (x = 0; x < sizeof(oidbuf)/sizeof(oidbuf[0]); x++) { oidbuf[x] = x + 1; } + DO(mp_init(&mpinteger)); + + n = sizeof(types)/sizeof(types[0]); + for (x = 0; x < n * 2; x++) { + /* setup list */ + y = 0; + LTC_SET_ASN1(types, y++, LTC_ASN1_PRINTABLE_STRING, printbuf, sizeof(printbuf)); + if (x > n) { + LTC_SET_ASN1(types, y++, LTC_ASN1_BIT_STRING, bitbuf, sizeof(bitbuf)); + } else { + LTC_SET_ASN1(types, y++, LTC_ASN1_RAW_BIT_STRING, bitbuf, sizeof(bitbuf)); + } + LTC_SET_ASN1(types, y++, LTC_ASN1_OCTET_STRING, octetbuf, sizeof(octetbuf)); + LTC_SET_ASN1(types, y++, LTC_ASN1_IA5_STRING, ia5buf, sizeof(ia5buf)); + LTC_SET_ASN1(types, y++, LTC_ASN1_BOOLEAN, boolean, sizeof(boolean)/sizeof(boolean[0])); + if (x > n) { + LTC_SET_ASN1(types, y++, LTC_ASN1_SHORT_INTEGER, &integer, 1); + } else { + LTC_SET_ASN1(types, y++, LTC_ASN1_INTEGER, mpinteger, 1); + } + LTC_SET_ASN1(types, y++, LTC_ASN1_OBJECT_IDENTIFIER, oidbuf, sizeof(oidbuf)/sizeof(oidbuf[0])); + if (x > n) { + LTC_SET_ASN1(types, y++, LTC_ASN1_UTCTIME, &utctime, 1); + } else { + LTC_SET_ASN1(types, y++, LTC_ASN1_GENERALIZEDTIME, >ime, 1); + } + + LTC_SET_ASN1(custom, 0, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(types, y++, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom); + + LTC_SET_ASN1(types, y++, LTC_ASN1_UTF8_STRING, utf8buf, sizeof(utf8buf)/sizeof(utf8buf[0])); + + LTC_SET_ASN1(host, 0, LTC_ASN1_CHOICE, types, n); + + + /* encode */ + outlen = sizeof(outbuf); + DO(der_encode_sequence(&types[x % n], 1, outbuf, &outlen)); + + /* custom encode */ + child[0] = types[x % n]; + if (x < n) { + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(root, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1uLL << (x % n), child); + } else { + LTC_SET_ASN1_CUSTOM_PRIMITIVE(root, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1uLL << (x % n), child->type, child->data, child->size); + } + custlen = sizeof(custbuf); + /* don't try to custom-encode a primitive custom-type */ + if (child[0].type != LTC_ASN1_CUSTOM_TYPE || root->pc != LTC_ASN1_PC_PRIMITIVE) { + DO(der_encode_custom_type(root, custbuf, &custlen)); + } + + /* decode it */ + inlen = outlen; + DO(der_decode_sequence(outbuf, inlen, host, 1)); + + for (y = 0; y < n; y++) { + if (types[y].used && y != (x % n)) { + fprintf(stderr, "CHOICE, flag %u in trial %u was incorrectly set to one\n", y, x); + return 1; + } + if (!types[y].used && y == (x % n)) { + fprintf(stderr, "CHOICE, flag %u in trial %u was incorrectly set to zero\n", y, x); + return 1; + } + } + + /* custom decode */ + if (child[0].type != LTC_ASN1_CUSTOM_TYPE || root->pc != LTC_ASN1_PC_PRIMITIVE) { + DO(der_decode_custom_type(custbuf, custlen, root)); + } + } + mp_clear(mpinteger); + return 0; +} + +static void s_der_decode_print(const void* p, unsigned long* plen) +{ + ltc_asn1_list *list; + DO(der_decode_sequence_flexi(p, plen, &list)); +#ifdef LTC_DER_TESTS_PRINT_FLEXI + fprintf(stderr, "\n\n"); + s_der_tests_print_flexi(list, 0); + fprintf(stderr, "\n\n"); +#endif + der_sequence_free(list); +} + +static const unsigned char eckey_privc_der[] = { + 0x30, 0x81, 0xf0, 0x02, 0x01, 0x01, 0x04, 0x18, 0x96, 0x9d, 0x28, 0xf2, 0x40, 0x48, 0x19, 0x11, + 0x79, 0xb0, 0x47, 0x8e, 0x8c, 0x6b, 0x3d, 0x9b, 0xf2, 0x31, 0x16, 0x10, 0x08, 0x72, 0xb1, 0x86, + 0xa0, 0x81, 0xb2, 0x30, 0x81, 0xaf, 0x02, 0x01, 0x01, 0x30, 0x24, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x01, 0x01, 0x02, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, + 0x4b, 0x04, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x18, 0x22, 0x12, 0x3d, + 0xc2, 0x39, 0x5a, 0x05, 0xca, 0xa7, 0x42, 0x3d, 0xae, 0xcc, 0xc9, 0x47, 0x60, 0xa7, 0xd4, 0x62, + 0x25, 0x6b, 0xd5, 0x69, 0x16, 0x03, 0x15, 0x00, 0xc4, 0x69, 0x68, 0x44, 0x35, 0xde, 0xb3, 0x78, + 0xc4, 0xb6, 0x5c, 0xa9, 0x59, 0x1e, 0x2a, 0x57, 0x63, 0x05, 0x9a, 0x2e, 0x04, 0x19, 0x02, 0x7d, + 0x29, 0x77, 0x81, 0x00, 0xc6, 0x5a, 0x1d, 0xa1, 0x78, 0x37, 0x16, 0x58, 0x8d, 0xce, 0x2b, 0x8b, + 0x4a, 0xee, 0x8e, 0x22, 0x8f, 0x18, 0x96, 0x02, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7a, 0x62, 0xd0, 0x31, 0xc8, 0x3f, 0x42, 0x94, 0xf6, 0x40, + 0xec, 0x13, 0x02, 0x01, 0x01, 0xa1, 0x1c, 0x03, 0x1a, 0x00, 0x02, 0x55, 0x2c, 0xb8, 0x73, 0x5c, + 0x9d, 0x98, 0xe4, 0x57, 0xfe, 0xd5, 0x96, 0x0a, 0x73, 0x8d, 0x82, 0xd7, 0xce, 0x05, 0xa9, 0x79, + 0x91, 0x5c, 0xf9 +}; + +static const unsigned char eckey_privs_der[] = { + 0x30, 0x50, 0x02, 0x01, 0x01, 0x04, 0x14, 0x82, 0xef, 0x42, 0x0b, 0xc7, 0xe2, 0x9f, 0x3a, 0x84, + 0xe5, 0x74, 0xec, 0x9c, 0xc5, 0x10, 0x26, 0x63, 0x8d, 0xb5, 0x46, 0xa0, 0x07, 0x06, 0x05, 0x2b, + 0x81, 0x04, 0x00, 0x09, 0xa1, 0x2c, 0x03, 0x2a, 0x00, 0x04, 0xb5, 0xb1, 0x5a, 0xb0, 0x2a, 0x10, + 0xd1, 0xf5, 0x4d, 0x6a, 0x41, 0xde, 0xcd, 0x69, 0x09, 0xb3, 0x5f, 0x26, 0xb0, 0xa2, 0xaf, 0xd3, + 0x02, 0x89, 0x5e, 0xd4, 0x96, 0x5c, 0xbc, 0x2a, 0x7e, 0x75, 0x85, 0x86, 0x29, 0xb3, 0x29, 0x13, + 0x77, 0xc3 +}; +static void der_custom_test(void) +{ + ltc_asn1_list bool_ean[1], seq1[1], custom[1]; + int boolean; + unsigned long len; + unsigned char buf[1024]; + unsigned char buf1[] = { 0xbf, 0xa0, 0x00, 0x04, 0x30, 0x02, 0x05, 0x00 }; + unsigned char buf2[] = { 0x30, 0x08, 0xbf, 0xa0, 0x00, 0x04, 0x30, 0x02, 0x05, 0x00 }; + + boolean = 0x1; + LTC_SET_ASN1(bool_ean, 0, LTC_ASN1_BOOLEAN, &boolean, 1); + LTC_SET_ASN1(seq1, 0, LTC_ASN1_SEQUENCE, bool_ean, 1); + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(custom, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0x1000, seq1); + + DO(der_length_custom_type(custom, &len, NULL)); + len = sizeof(buf); + DO(der_encode_custom_type(custom, buf, &len)); + s_der_decode_print(buf, &len); + + boolean = 0x0; + DO(der_decode_custom_type(buf, len, custom)); + + DO(der_length_sequence(custom, 1, &len)); + len = sizeof(buf); + DO(der_encode_sequence(custom, 1, buf, &len)); + s_der_decode_print(buf, &len); + + boolean = 0x0; + DO(der_decode_sequence(buf, len, custom, 1)); + + LTC_SET_ASN1_CUSTOM_PRIMITIVE(bool_ean, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0x8000, LTC_ASN1_BOOLEAN, &boolean, 1); + DO(der_length_custom_type(bool_ean, &len, NULL)); + len = sizeof(buf); + DO(der_encode_custom_type(bool_ean, buf, &len)); + s_der_decode_print(buf, &len); + + LTC_SET_ASN1_CUSTOM_PRIMITIVE(bool_ean, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0x8000, LTC_ASN1_BOOLEAN, &boolean, 1); + DO(der_decode_custom_type(buf, len, bool_ean)); + + len = sizeof(buf1); + s_der_decode_print(buf1, &len); + + len = sizeof(buf2); + s_der_decode_print(buf2, &len); + + len = sizeof(eckey_privc_der); + s_der_decode_print(eckey_privc_der, &len); + + len = sizeof(eckey_privs_der); + s_der_decode_print(eckey_privs_der, &len); +} + +typedef int (*s_der_Xcode)(const void*, unsigned long, void*, unsigned long*); + +typedef struct { + s_der_Xcode encode; + s_der_Xcode decode; + const void* in; + size_t in_sz; + size_t factor; + size_t type_sz; + const char* what; +} der_Xcode_t; + +static void der_Xcode_run(const der_Xcode_t* x) +{ + unsigned long l1, l2, sz; + void *d1, *d2; + int err; + + l1 = 1; + d1 = XMALLOC(l1 * x->type_sz); + sz = (x->in_sz * x->factor)/x->type_sz; + + if ((err = x->encode(x->in, sz, d1, &l1)) == CRYPT_BUFFER_OVERFLOW) { + d1 = XREALLOC(d1, l1 * x->type_sz); + } + DO(x->encode(x->in, sz, d1, &l1)); + l2 = 1; + d2 = XMALLOC(l2 * x->type_sz); + while ((err = x->decode(d1, l1, d2, &l2)) == CRYPT_BUFFER_OVERFLOW) { + d2 = XREALLOC(d2, l2 * x->type_sz); + } + DO(x->decode(d1, l1, d2, &l2)); + DO(do_compare_testvector(d2, (l2/x->factor) * x->type_sz, x->in, x->in_sz, x->what, __LINE__)); + XFREE(d2); + XFREE(d1); +} + +#if defined(_MSC_VER) +#define typeof(x) x +#endif + +#define DER_XCODE_X(n, b, x) { \ + (s_der_Xcode)der_encode_ ## n, \ + (s_der_Xcode)der_decode_ ## n, \ + b, \ + sizeof(b), \ + x, \ + sizeof(typeof(b[0])),\ + #n \ +} + +#define DER_XCODE(n, b) DER_XCODE_X(n, b, 1) + +static void der_Xcode_test(void) +{ + unsigned long i; + ltc_asn1_list *list; + ltc_asn1_list ttex_neg_int[2]; + unsigned char buf[128]; + void* mpinteger; + const unsigned long oid[3] = { 1, 23, 42 }; + const unsigned char bit_string[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; + const unsigned char multi_buf[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + const char multi_string[] = {'l','i','b','t','o','m','c','r','y','p','t'}; + const wchar_t wchar_string[] = L"libtomcrypt"; + + const unsigned char teletex_neg_int[] = { 0x30, 0x11, 0x14, 0x0b, 0x6c, 0x69, 0x62, 0x74, + 0x6f, 0x6d, 0x63, 0x72, 0x79, 0x70, 0x74, 0x02, + 0x02, 0xfc, 0x19 }; + + const der_Xcode_t xcode_tests[] = + { + DER_XCODE(bit_string, bit_string), + DER_XCODE_X(raw_bit_string, multi_buf, 8), + DER_XCODE(octet_string, multi_buf), + DER_XCODE(object_identifier, oid), + DER_XCODE(ia5_string, multi_string), + DER_XCODE(printable_string, multi_string), + DER_XCODE(utf8_string, wchar_string), + }; + + for (i = 0; i < sizeof(xcode_tests)/sizeof(xcode_tests[0]); ++i) { + der_Xcode_run(&xcode_tests[i]); + } + + i = sizeof(teletex_neg_int); + DO(der_decode_sequence_flexi(teletex_neg_int, &i, &list)); +#ifdef LTC_DER_TESTS_PRINT_FLEXI + fprintf(stderr, "\n\n"); + s_der_tests_print_flexi(list, 0); + fprintf(stderr, "\n\n"); +#endif + if (list->child == NULL || list->child->next == NULL) + exit(EXIT_FAILURE); + ttex_neg_int[0] = *list->child->next; + i = sizeof(buf); + DO(der_encode_sequence(ttex_neg_int, 1, buf, &i)); + der_sequence_free(list); + + DO(mp_init(&mpinteger)); + LTC_SET_ASN1(ttex_neg_int, 0, LTC_ASN1_TELETEX_STRING, buf, sizeof(buf)); + LTC_SET_ASN1(ttex_neg_int, 1, LTC_ASN1_INTEGER, mpinteger, 1); + + DO(der_decode_sequence(teletex_neg_int, sizeof(teletex_neg_int), ttex_neg_int, 2)); + + mp_clear(mpinteger); +} + +#ifdef LTC_TEST_READDIR +static int s_der_decode_sequence_flexi(const void *in, unsigned long inlen, void* ctx) +{ + ltc_asn1_list** list = ctx; + if (der_decode_sequence_flexi(in, &inlen, list) == CRYPT_OK) { +#ifdef LTC_DER_TESTS_PRINT_FLEXI + fprintf(stderr, "\n\n"); + s_der_tests_print_flexi(*list, 0); + fprintf(stderr, "\n\n"); +#endif + der_sequence_free(*list); + } + return CRYPT_OK; +} +#endif + + +static void s_der_regression_test(void) +{ + static const unsigned char s_broken_sequence[] = { + 0x30,0x41,0x02,0x84,0x7f,0xff,0xff,0xff,0x1e,0x41,0xb4,0x79,0xad,0x57,0x69, + 0x05,0xb9,0x60,0xfe,0x14,0xea,0xdb,0x91,0xb0,0xcc,0xf3,0x48,0x43,0xda,0xb9, + 0x16,0x17,0x3b,0xb8,0xc9,0xcd,0x02,0x1d,0x00,0xad,0xe6,0x59,0x88,0xd2,0x37, + 0xd3,0x0f,0x9e,0xf4,0x1d,0xd4,0x24,0xa4,0xe1,0xc8,0xf1,0x69,0x67,0xcf,0x33, + 0x65,0x81,0x3f,0xe8,0x78,0x62,0x36 + }; + static const unsigned char s_addtl_bytes[] = { + 0x30,0x45,0x02,0x21,0x00,0xb7,0xba,0xba,0xe9,0x33,0x2b,0x54,0xb8,0xa3,0xa0,0x5b,0x70,0x04,0x57, + 0x98,0x21,0xa8,0x87,0xa1,0xb2,0x14,0x65,0xf7,0xdb,0x8a,0x3d,0x49,0x1b,0x39,0xfd,0x2c,0x3f,0x02, + 0x20,0x74,0x72,0x91,0xdd,0x2f,0x3f,0x44,0xaf,0x7a,0xce,0x68,0xea,0x33,0x43,0x1d,0x6f,0x94,0xe4, + 0x18,0xc1,0x06,0xa6,0xe7,0x62,0x85,0xcd,0x59,0xf4,0x32,0x60,0xec,0xce,0x00,0x00 + }; + static const unsigned char issue_507[] = "\x30\x04" /* Start DER-sequence of length 4 */ + "\x0c\x02\xbf\xbf" /* Start UTF8 string of actual length 2 and evaluated length 3 */ + "\xaa" /* One byte padding */ + "\x04\x82\xff\xff"; /* Start OCTET sequence of length 0xffff */ + /* (this will include the adjacent data into the decoded certificate) */ + unsigned long len; + void *x, *y; + ltc_asn1_list seq[2]; + ltc_asn1_list *l; + mp_init_multi(&x, &y, LTC_NULL); + LTC_SET_ASN1(seq, 0, LTC_ASN1_INTEGER, x, 1UL); + LTC_SET_ASN1(seq, 1, LTC_ASN1_INTEGER, y, 1UL); + SHOULD_FAIL(der_decode_sequence(s_broken_sequence, sizeof(s_broken_sequence), seq, 2)); + mp_cleanup_multi(&y, &x, LTC_NULL); + len = sizeof(s_broken_sequence); + + mp_init_multi(&x, &y, LTC_NULL); + LTC_SET_ASN1(seq, 0, LTC_ASN1_INTEGER, x, 1UL); + LTC_SET_ASN1(seq, 1, LTC_ASN1_INTEGER, y, 1UL); + SHOULD_FAIL_WITH(der_decode_sequence(s_addtl_bytes, sizeof(s_addtl_bytes), seq, 2), CRYPT_INPUT_TOO_LONG); + mp_cleanup_multi(&y, &x, LTC_NULL); + len = sizeof(s_addtl_bytes); + s_der_decode_print(s_addtl_bytes, &len); + + len = sizeof(issue_507); + SHOULD_FAIL(der_decode_sequence_flexi(issue_507, &len, &l)); +} + +static void der_toolong_test(void) +{ + int n, err, failed = 0; + ltc_asn1_list *list; + unsigned long len, oid[16]; + unsigned char buf5[5], buf12[12], buf32[32]; + static const unsigned char invalid1[] = { + 0x30,0x19, /* SEQUENCE len=25 bytes */ + 0x30,0x0a, /* SEQUENCE len=10 bytes (which is wrong, should be 9) */ + 0x04,0x05, /* OCTET STRING len=5 */ 0x2b,0x0e,0x03,0x02,0x1a, + 0x05,0x00, /* NULL */ + 0x04,0x0c, /* OCTET STRING len=12 */ 0xf7,0xff,0x9e,0x8b,0x7b,0xb2,0xe0,0x9b,0x70,0x93,0x5a,0x5d, + }; + static const unsigned char invalid2[] = { + 0x30,0x0d, /* SEQUENCE len=13 bytes*/ + 0x02,0x05, /* INTEGER len=5 */ 0x00,0xb7,0xba,0xba,0xe9, + 0x02,0x04, /* INTEGER len=4 */ 0x74,0x72,0x91,0xdd, + 0x00,0x00 /* garbage after the sequence, der_decode_sequence_flexi should ignore this */ + }; + static const unsigned char invalid3[] = { + 0x30,0x0f, /* SEQUENCE len=15 bytes*/ + 0x02,0x05, /* INTEGER len=5 */ 0x00,0xb7,0xba,0xba,0xe9, + 0x02,0x04, /* INTEGER len=4 */ 0x74,0x72,0x91,0xdd, + 0x00,0x00 /* garbage inside the sequence */ + }; + static const unsigned char invalid4[] = { + 0x30, 0x30, + 0x30, 0x0d, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, + 0x04, 0x20, 0x53, 0x2e, 0xaa, 0xbd, 0x95, 0x74, 0x88, 0x0d, 0xbf, 0x76, 0xb9, 0xb8, 0xcc, 0x00, 0x83, 0x2c, + 0x20, 0xa6, 0xec, 0x11, 0x3d, 0x68, 0x22, 0x99, 0x55, 0x0d, 0x7a, 0x6e, 0x0f, 0x34, 0x5e, 0x25 + + }; + static const unsigned char invalid5[] = { + 0x30, 0x31, + 0x30, 0x0e, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, + 0x04, 0x20, 0x53, 0x2e, 0xaa, 0xbd, 0x95,0x74, 0x88, 0x0d, 0xbf, 0x76, 0xb9, 0xb8, 0xcc,0x00, 0x83, 0x2c, + 0x20, 0xa6, 0xec, 0x11, 0x3d,0x68, 0x22, 0x99, 0x55, 0x0d, 0x7a, 0x6e, 0x0f,0x34, 0x5e, 0x25 + + }; + static const unsigned char invalid6[] = { + 0x30, 0x31, + 0x30, 0x0c, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x05, 0x00, + 0x04, 0x20, 0x53, 0x2e, 0xaa, 0xbd, 0x95,0x74, 0x88, 0x0d, 0xbf, 0x76, 0xb9, 0xb8, 0xcc,0x00, 0x83, 0x2c, + 0x20, 0xa6, 0xec, 0x11, 0x3d,0x68, 0x22, 0x99, 0x55, 0x0d, 0x7a, 0x6e, 0x0f,0x34, 0x5e, 0x25 + + }; + + ltc_asn1_list seqsub[2], seqoid[2], seqmain[2], seqint[2]; + void *int1, *int2; + + LTC_SET_ASN1(seqsub, 0, LTC_ASN1_OCTET_STRING, buf5, 5); + LTC_SET_ASN1(seqsub, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(seqmain, 0, LTC_ASN1_SEQUENCE, seqsub, 2); + LTC_SET_ASN1(seqmain, 1, LTC_ASN1_OCTET_STRING, buf12, 12); + + n = 1; + len = sizeof(invalid1); + err = der_decode_sequence_strict(invalid1, len, seqmain, 2); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n); + failed = 1; + } + len = sizeof(invalid1); + err = der_decode_sequence_flexi(invalid1, &len, &list); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n); + failed = 1; + der_sequence_free(list); + } + + mp_init_multi(&int1, &int2, LTC_NULL); + LTC_SET_ASN1(seqint, 0, LTC_ASN1_INTEGER, int1, 1); + LTC_SET_ASN1(seqint, 1, LTC_ASN1_INTEGER, int2, 1); + + n++; + len = sizeof(invalid2); + err = der_decode_sequence_strict(invalid2, len, seqint, 2); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n); + failed = 1; + } + len = sizeof(invalid2); + err = der_decode_sequence_flexi(invalid2, &len, &list); + /* flexi parser should decode this; however returning "len" shorter than "sizeof(invalid2)" */ + if (err != CRYPT_OK || len != 15) { + fprintf(stderr,"der_decode_sequence_flexi failed, err=%d (expected 0) len=%lu (expected 15)\n", err, len); + failed = 1; + } + if (err == CRYPT_OK) + der_sequence_free(list); + + n++; + len = sizeof(invalid3); + err = der_decode_sequence_strict(invalid3, len, seqint, 2); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n); + failed = 1; + } + len = sizeof(invalid3); + err = der_decode_sequence_flexi(invalid3, &len, &list); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n); + failed = 1; + der_sequence_free(list); + } + + mp_clear_multi(int1, int2, LTC_NULL); + + LTC_SET_ASN1(seqoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, sizeof(oid)/sizeof(oid[0])); + LTC_SET_ASN1(seqoid, 1, LTC_ASN1_NULL, NULL, 0); + LTC_SET_ASN1(seqmain, 0, LTC_ASN1_SEQUENCE, seqoid, 2); + LTC_SET_ASN1(seqmain, 1, LTC_ASN1_OCTET_STRING, buf32, 32); + + n++; + len = sizeof(invalid4); + err = der_decode_sequence_strict(invalid4, len, seqmain, 2); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n); + failed = 1; + } + len = sizeof(invalid4); + err = der_decode_sequence_flexi(invalid4, &len, &list); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n); + failed = 1; + der_sequence_free(list); + } + + n++; + len = sizeof(invalid5); + err = der_decode_sequence_strict(invalid5, len, seqmain, 2); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n); + failed = 1; + } + len = sizeof(invalid5); + err = der_decode_sequence_flexi(invalid5, &len, &list); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n); + failed = 1; + der_sequence_free(list); + } + n++; + len = sizeof(invalid6); + err = der_decode_sequence_strict(invalid6, len, seqmain, 2); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n); + failed = 1; + } + len = sizeof(invalid6); + err = der_decode_sequence_flexi(invalid6, &len, &list); + if (err == CRYPT_OK) { + fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n); + failed = 1; + der_sequence_free(list); + } + + if (failed) exit(EXIT_FAILURE); +} + +static void s_der_recursion_limit(void) +{ + unsigned int n, m; + unsigned long integer = 123, s; + ltc_asn1_list seqs[LTC_DER_MAX_RECURSION + 2], dummy[1], *flexi; + unsigned char buf[2048]; + for (m = 0; m < 3; ++m) { + LTC_SET_ASN1(dummy, 0, LTC_ASN1_SHORT_INTEGER, &integer, 1); + LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION + 1, LTC_ASN1_SEQUENCE, dummy, 1); + for (n = m; n < LTC_DER_MAX_RECURSION + 1; ++n) { + LTC_SET_ASN1(seqs, LTC_DER_MAX_RECURSION - n, LTC_ASN1_SEQUENCE, &seqs[LTC_DER_MAX_RECURSION - n + 1], 1); + } + s = sizeof(buf); + DO(der_encode_sequence(&seqs[m], 1, buf, &s)); + DO(der_decode_sequence(buf, s, &seqs[m], 1)); + if (m < 2) { + SHOULD_FAIL(der_decode_sequence_flexi(buf, &s, &flexi)); + } + else { + DO(der_decode_sequence_flexi(buf, &s, &flexi)); + der_free_sequence_flexi(flexi); + } + } +} + +int der_test(void) +{ + unsigned long x, y, z, zz, oid[2][32]; + unsigned char buf[3][2048]; + void *a, *b, *c, *d, *e, *f, *g; + + static const unsigned char rsa_oid_der[] = { 0x06, 0x06, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d }; + static const unsigned long rsa_oid[] = { 1, 2, 840, 113549 }; + + static const unsigned char rsa_ia5[] = "test1@rsa.com"; + static const unsigned char rsa_ia5_der[] = { 0x16, 0x0d, 0x74, 0x65, 0x73, 0x74, 0x31, + 0x40, 0x72, 0x73, 0x61, 0x2e, 0x63, 0x6f, 0x6d }; + + static const unsigned char rsa_printable[] = "Test User 1"; + static const unsigned char rsa_printable_der[] = { 0x13, 0x0b, 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, + 0x73, 0x65, 0x72, 0x20, 0x31 }; + + static const ltc_utctime rsa_time1 = { 91, 5, 6, 16, 45, 40, 1, 7, 0 }; + static const ltc_utctime rsa_time2 = { 91, 5, 6, 23, 45, 40, 0, 0, 0 }; + ltc_utctime tmp_time; + + static const unsigned char rsa_time1_der[] = { 0x17, 0x11, 0x39, 0x31, 0x30, 0x35, 0x30, 0x36, 0x31, 0x36, 0x34, 0x35, 0x34, 0x30, 0x2D, 0x30, 0x37, 0x30, 0x30 }; + static const unsigned char rsa_time2_der[] = { 0x17, 0x0d, 0x39, 0x31, 0x30, 0x35, 0x30, 0x36, 0x32, 0x33, 0x34, 0x35, 0x34, 0x30, 0x5a }; + + static const wchar_t utf8_1[] = { 0x0041, 0x2262, 0x0391, 0x002E }; + static const unsigned char utf8_1_der[] = { 0x0C, 0x07, 0x41, 0xE2, 0x89, 0xA2, 0xCE, 0x91, 0x2E }; + static const wchar_t utf8_2[] = { 0xD55C, 0xAD6D, 0xC5B4 }; + static const unsigned char utf8_2_der[] = { 0x0C, 0x09, 0xED, 0x95, 0x9C, 0xEA, 0xB5, 0xAD, 0xEC, 0x96, 0xB4 }; + static const wchar_t utf8_3[] = { 0x05E9, 0x05DC, 0x05D5, 0x05DD }; + static const unsigned char utf8_3_der[] = { 0x0C, 0x08, 0xD7, 0xA9, 0xD7, 0x9C, 0xD7, 0x95, 0xD7, 0x9D }; + + unsigned char utf8_buf[32]; + wchar_t utf8_out[32]; +#ifdef LTC_TEST_READDIR + ltc_asn1_list *list; +#endif + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + s_der_recursion_limit(); + + der_Xcode_test(); + +#ifdef LTC_TEST_READDIR + DO(test_process_dir("tests/asn1", &list, s_der_decode_sequence_flexi, NULL, "DER ASN.1 special cases")); +#endif + + der_custom_test(); + + s_der_regression_test(); + + der_toolong_test(); + + der_cacert_test(); + + s_der_oid_test(); + + y = 0xffffff00; +#if ULONG_MAX == ULLONG_MAX + y <<= 32; +#endif + while (y != 0) { + /* we have to modify x to be larger than the encoded + * length as der_decode_asn1_length() checks also if + * the encoded length is reasonable in regards to the + * available buffer size. + */ + x = sizeof(buf[0]); + DO(der_encode_asn1_length(y, buf[0], &x)); + x = y + x; + DO(der_decode_asn1_length(buf[0], &x, &z)); + if (y != z) { + fprintf(stderr, "Failed to en- or decode length correctly! %lu != %lu\n", y, z); + return 1; + } + y >>= 3; + } + + DO(mp_init_multi(&a, &b, &c, &d, &e, &f, &g, LTC_NULL)); + for (zz = 0; zz < 16; zz++) { +#ifdef USE_TFM + for (z = 0; z < 256; z++) { +#else + for (z = 0; z < 1024; z++) { +#endif + ENSURE(yarrow_read(buf[0], z, &yarrow_prng) == z); + DO(mp_read_unsigned_bin(a, buf[0], z)); +/* if (mp_iszero(a) == LTC_MP_NO) { a.sign = buf[0][0] & 1 ? LTC_MP_ZPOS : LTC_MP_NEG; } */ + x = sizeof(buf[0]); + DO(der_encode_integer(a, buf[0], &x)); + DO(der_length_integer(a, &y)); + if (y != x) { fprintf(stderr, "DER INTEGER size mismatch %lu != %lu\n", y, x); return 1; } + mp_set_int(b, 0); + DO(der_decode_integer(buf[0], y, b)); + if (y != x || mp_cmp(a, b) != LTC_MP_EQ) { + fprintf(stderr, "%lu: %lu vs %lu\n", z, x, y); + mp_clear_multi(a, b, c, d, e, f, g, LTC_NULL); + return 1; + } + } + } + +/* test short integer */ + for (zz = 0; zz < 256; zz++) { + for (z = 1; z < 4; z++) { + ENSURE(yarrow_read(buf[2], z, &yarrow_prng) == z); + /* encode with normal */ + DO(mp_read_unsigned_bin(a, buf[2], z)); + + x = sizeof(buf[0]); + DO(der_encode_integer(a, buf[0], &x)); + + /* encode with short */ + y = sizeof(buf[1]); + DO(der_encode_short_integer(mp_get_int(a), buf[1], &y)); + if (x != y || memcmp(buf[0], buf[1], x)) { + fprintf(stderr, "DER INTEGER short encoding failed, %lu, %lu, 0x%lX\n", x, y, mp_get_int(a)); + for (zz = 0; zz < z; zz++) fprintf(stderr, "%02x ", buf[2][zz]); + fprintf(stderr, "\n"); + for (z = 0; z < x; z++) fprintf(stderr, "%02x ", buf[0][z]); + fprintf(stderr, "\n"); + for (z = 0; z < y; z++) fprintf(stderr, "%02x ", buf[1][z]); + fprintf(stderr, "\n"); + mp_clear_multi(a, b, c, d, e, f, g, LTC_NULL); + return 1; + } + + /* decode it */ + x = 0; + DO(der_decode_short_integer(buf[1], y, &x)); + if (x != mp_get_int(a)) { + fprintf(stderr, "DER INTEGER short decoding failed, %lu, %lu\n", x, mp_get_int(a)); + mp_clear_multi(a, b, c, d, e, f, g, LTC_NULL); + return 1; + } + } + } + mp_clear_multi(a, b, c, d, e, f, g, LTC_NULL); + + +/* Test bit string */ + for (zz = 1; zz < 1536; zz++) { + ENSURE(yarrow_read(buf[0], zz, &yarrow_prng) == zz); + for (z = 0; z < zz; z++) { + buf[0][z] &= 0x01; + } + x = sizeof(buf[1]); + DO(der_encode_bit_string(buf[0], zz, buf[1], &x)); + DO(der_length_bit_string(zz, &y)); + if (y != x) { + fprintf(stderr, "\nDER BIT STRING length of encoded not match expected : %lu, %lu, %lu\n", z, x, y); + return 1; + } + + y = sizeof(buf[2]); + DO(der_decode_bit_string(buf[1], x, buf[2], &y)); + if (y != zz || memcmp(buf[0], buf[2], zz)) { + fprintf(stderr, "%lu, %lu, %d\n", y, zz, memcmp(buf[0], buf[2], zz)); + return 1; + } + } + +/* Test octet string */ + for (zz = 1; zz < 1536; zz++) { + ENSURE(yarrow_read(buf[0], zz, &yarrow_prng) == zz); + x = sizeof(buf[1]); + DO(der_encode_octet_string(buf[0], zz, buf[1], &x)); + DO(der_length_octet_string(zz, &y)); + if (y != x) { + fprintf(stderr, "\nDER OCTET STRING length of encoded not match expected : %lu, %lu, %lu\n", z, x, y); + return 1; + } + y = sizeof(buf[2]); + DO(der_decode_octet_string(buf[1], x, buf[2], &y)); + if (y != zz || memcmp(buf[0], buf[2], zz)) { + fprintf(stderr, "%lu, %lu, %d\n", y, zz, memcmp(buf[0], buf[2], zz)); + return 1; + } + } + +/* test OID */ + x = sizeof(buf[0]); + DO(der_encode_object_identifier((unsigned long*)rsa_oid, sizeof(rsa_oid)/sizeof(rsa_oid[0]), buf[0], &x)); + if (x != sizeof(rsa_oid_der) || memcmp(rsa_oid_der, buf[0], x)) { + fprintf(stderr, "rsa_oid_der encode failed to match, %lu, ", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); + fprintf(stderr, "\n"); + return 1; + } + + y = sizeof(oid[0])/sizeof(oid[0][0]); + DO(der_decode_object_identifier(buf[0], x, oid[0], &y)); + if (y != sizeof(rsa_oid)/sizeof(rsa_oid[0]) || memcmp(rsa_oid, oid[0], sizeof(rsa_oid))) { + fprintf(stderr, "rsa_oid_der decode failed to match, %lu, ", y); + for (z = 0; z < y; z++) fprintf(stderr, "%lu ", oid[0][z]); + fprintf(stderr, "\n"); + return 1; + } + + /* do random strings */ + for (zz = 0; zz < 5000; zz++) { + /* pick a random number of words */ + ENSURE(yarrow_read(buf[0], 4, &yarrow_prng) == 4); + LOAD32L(z, buf[0]); + z = 2 + (z % ((sizeof(oid[0])/sizeof(oid[0][0])) - 2)); + + /* fill them in */ + oid[0][0] = buf[0][0] % 3; + oid[0][1] = buf[0][1] % 40; + + for (y = 2; y < z; y++) { + ENSURE(yarrow_read(buf[0], 4, &yarrow_prng) == 4); + LOAD32L(oid[0][y], buf[0]); + } + + /* encode it */ + x = sizeof(buf[0]); + DO(der_encode_object_identifier(oid[0], z, buf[0], &x)); + DO(der_length_object_identifier(oid[0], z, &y)); + if (x != y) { + fprintf(stderr, "Random OID %lu test failed, length mismatch: %lu, %lu\n", z, x, y); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[0][x]); + return 1; + } + + /* decode it */ + y = sizeof(oid[0])/sizeof(oid[0][0]); + DO(der_decode_object_identifier(buf[0], x, oid[1], &y)); + if (y != z) { + fprintf(stderr, "Random OID %lu test failed, decode length mismatch: %lu, %lu\n", z, x, y); + return 1; + } + if (memcmp(oid[0], oid[1], sizeof(oid[0][0]) * z)) { + fprintf(stderr, "Random OID %lu test failed, decoded values wrong\n", z); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[0][x]); + fprintf(stderr, "\n\n Got \n\n"); + for (x = 0; x < z; x++) fprintf(stderr, "%lu\n", oid[1][x]); + return 1; + } + } + +/* IA5 string */ + x = sizeof(buf[0]); + DO(der_encode_ia5_string(rsa_ia5, XSTRLEN((char*)rsa_ia5), buf[0], &x)); + if (x != sizeof(rsa_ia5_der) || memcmp(buf[0], rsa_ia5_der, x)) { + fprintf(stderr, "IA5 encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_ia5_der)); + return 1; + } + DO(der_length_ia5_string(rsa_ia5, XSTRLEN((char*)rsa_ia5), &y)); + if (y != x) { + fprintf(stderr, "IA5 length failed to match: %lu, %lu\n", x, y); + return 1; + } + y = sizeof(buf[1]); + DO(der_decode_ia5_string(buf[0], x, buf[1], &y)); + if (y != XSTRLEN((char*)rsa_ia5) || memcmp(buf[1], rsa_ia5, XSTRLEN((char*)rsa_ia5))) { + fprintf(stderr, "DER IA5 failed test vector\n"); + return 1; + } + +/* Printable string */ + x = sizeof(buf[0]); + DO(der_encode_printable_string(rsa_printable, XSTRLEN((char*)rsa_printable), buf[0], &x)); + if (x != sizeof(rsa_printable_der) || memcmp(buf[0], rsa_printable_der, x)) { + fprintf(stderr, "PRINTABLE encode failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_printable_der)); + return 1; + } + DO(der_length_printable_string(rsa_printable, XSTRLEN((char*)rsa_printable), &y)); + if (y != x) { + fprintf(stderr, "printable length failed to match: %lu, %lu\n", x, y); + return 1; + } + y = sizeof(buf[1]); + DO(der_decode_printable_string(buf[0], x, buf[1], &y)); + if (y != XSTRLEN((char*)rsa_printable) || memcmp(buf[1], rsa_printable, XSTRLEN((char*)rsa_printable))) { + fprintf(stderr, "DER printable failed test vector\n"); + return 1; + } + +/* Test UTC time */ + x = sizeof(buf[0]); + DO(der_encode_utctime((ltc_utctime*)&rsa_time1, buf[0], &x)); + if (x != sizeof(rsa_time1_der) || memcmp(buf[0], rsa_time1_der, x)) { + fprintf(stderr, "UTCTIME encode of rsa_time1 failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_time1_der)); + fprintf(stderr, "\n\n"); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); + fprintf(stderr, "\n"); + return 1; + } + DO(der_length_utctime((ltc_utctime*)&rsa_time1, &y)); + if (y != x) { + fprintf(stderr, "UTCTIME length failed to match for rsa_time1: %lu, %lu\n", x, y); + return 1; + } + DO(der_decode_utctime(buf[0], &y, &tmp_time)); + if (y != x || memcmp(&rsa_time1, &tmp_time, sizeof(ltc_utctime))) { + fprintf(stderr, "UTCTIME decode failed for rsa_time1: %lu %lu\n", x, y); +fprintf(stderr, "\n\n%u %u %u %u %u %u %u %u %u\n\n", +tmp_time.YY, +tmp_time.MM, +tmp_time.DD, +tmp_time.hh, +tmp_time.mm, +tmp_time.ss, +tmp_time.off_dir, +tmp_time.off_mm, +tmp_time.off_hh); + return 1; + } + + x = sizeof(buf[0]); + DO(der_encode_utctime((ltc_utctime*)&rsa_time2, buf[0], &x)); + if (x != sizeof(rsa_time2_der) || memcmp(buf[0], rsa_time2_der, x)) { + fprintf(stderr, "UTCTIME encode of rsa_time2 failed: %lu, %lu\n", x, (unsigned long)sizeof(rsa_time1_der)); + fprintf(stderr, "\n\n"); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", buf[0][y]); + fprintf(stderr, "\n"); + return 1; + } + DO(der_length_utctime((ltc_utctime*)&rsa_time2, &y)); + if (y != x) { + fprintf(stderr, "UTCTIME length failed to match for rsa_time2: %lu, %lu\n", x, y); + return 1; + } + DO(der_decode_utctime(buf[0], &y, &tmp_time)); + if (y != x || memcmp(&rsa_time2, &tmp_time, sizeof(ltc_utctime))) { + fprintf(stderr, "UTCTIME decode failed for rsa_time2: %lu %lu\n", x, y); +fprintf(stderr, "\n\n%u %u %u %u %u %u %u %u %u\n\n", +tmp_time.YY, +tmp_time.MM, +tmp_time.DD, +tmp_time.hh, +tmp_time.mm, +tmp_time.ss, +tmp_time.off_dir, +tmp_time.off_mm, +tmp_time.off_hh); + + + return 1; + } + + /* UTF 8 */ + /* encode it */ + x = sizeof(utf8_buf); + DO(der_encode_utf8_string(utf8_1, sizeof(utf8_1) / sizeof(utf8_1[0]), utf8_buf, &x)); + DO(der_length_utf8_string(utf8_1, sizeof(utf8_1) / sizeof(utf8_1[0]), &y)); + if (x != sizeof(utf8_1_der) || memcmp(utf8_buf, utf8_1_der, x) || x != y) { + fprintf(stderr, "DER UTF8_1 encoded to %lu bytes\n", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", (unsigned)utf8_buf[y]); + fprintf(stderr, "\n"); + return 1; + } + /* decode it */ + y = sizeof(utf8_out) / sizeof(utf8_out[0]); + DO(der_decode_utf8_string(utf8_buf, x, utf8_out, &y)); + if (y != (sizeof(utf8_1) / sizeof(utf8_1[0])) || memcmp(utf8_1, utf8_out, y * sizeof(wchar_t))) { + fprintf(stderr, "DER UTF8_1 decoded to %lu wchar_t\n", y); + for (x = 0; x < y; x++) fprintf(stderr, "%04lx ", (unsigned long)utf8_out[x]); + fprintf(stderr, "\n"); + return 1; + } + + /* encode it */ + x = sizeof(utf8_buf); + DO(der_encode_utf8_string(utf8_2, sizeof(utf8_2) / sizeof(utf8_2[0]), utf8_buf, &x)); + if (x != sizeof(utf8_2_der) || memcmp(utf8_buf, utf8_2_der, x)) { + fprintf(stderr, "DER UTF8_2 encoded to %lu bytes\n", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", (unsigned)utf8_buf[y]); + fprintf(stderr, "\n"); + return 1; + } + /* decode it */ + y = sizeof(utf8_out) / sizeof(utf8_out[0]); + DO(der_decode_utf8_string(utf8_buf, x, utf8_out, &y)); + if (y != (sizeof(utf8_2) / sizeof(utf8_2[0])) || memcmp(utf8_2, utf8_out, y * sizeof(wchar_t))) { + fprintf(stderr, "DER UTF8_2 decoded to %lu wchar_t\n", y); + for (x = 0; x < y; x++) fprintf(stderr, "%04lx ", (unsigned long)utf8_out[x]); + fprintf(stderr, "\n"); + return 1; + } + + /* encode it */ + x = sizeof(utf8_buf); + DO(der_encode_utf8_string(utf8_3, sizeof(utf8_3) / sizeof(utf8_3[0]), utf8_buf, &x)); + if (x != sizeof(utf8_3_der) || memcmp(utf8_buf, utf8_3_der, x)) { + fprintf(stderr, "DER UTF8_3 encoded to %lu bytes\n", x); + for (y = 0; y < x; y++) fprintf(stderr, "%02x ", (unsigned)utf8_buf[y]); + fprintf(stderr, "\n"); + return 1; + } + /* decode it */ + y = sizeof(utf8_out) / sizeof(utf8_out[0]); + DO(der_decode_utf8_string(utf8_buf, x, utf8_out, &y)); + if (y != (sizeof(utf8_3) / sizeof(utf8_3[0])) || memcmp(utf8_3, utf8_out, y * sizeof(wchar_t))) { + fprintf(stderr, "DER UTF8_3 decoded to %lu wchar_t\n", y); + for (x = 0; x < y; x++) fprintf(stderr, "%04lx ", (unsigned long)utf8_out[x]); + fprintf(stderr, "\n"); + return 1; + } + + der_set_test(); + der_flexi_test(); + return der_choice_n_custom_test(); +} + +#endif diff --git a/deps/libtomcrypt/tests/dh_test.c b/deps/libtomcrypt/tests/dh_test.c new file mode 100644 index 0000000..08f3802 --- /dev/null +++ b/deps/libtomcrypt/tests/dh_test.c @@ -0,0 +1,406 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_MDH) + +static int s_prime_test(void) +{ + void *p, *g, *tmp; + int x, err, primality; + + if ((err = mp_init_multi(&p, &g, &tmp, LTC_NULL)) != CRYPT_OK) { goto error; } + + for (x = 0; ltc_dh_sets[x].size != 0; x++) { + /* tfm has a problem with larger sizes */ + if ((strcmp(ltc_mp.name, "TomsFastMath") == 0) && (ltc_dh_sets[x].size > 256)) break; + + if ((err = mp_read_radix(g, ltc_dh_sets[x].base, 16)) != CRYPT_OK) { goto error; } + if ((err = mp_read_radix(p, ltc_dh_sets[x].prime, 16)) != CRYPT_OK) { goto error; } + + /* ensure p is prime */ + if ((err = mp_prime_is_prime(p, 8, &primality)) != CRYPT_OK) { goto done; } + if (primality != LTC_MP_YES ) { + err = CRYPT_FAIL_TESTVECTOR; + goto done; + } + + if ((err = mp_sub_d(p, 1, tmp)) != CRYPT_OK) { goto error; } + if ((err = mp_div_2(tmp, tmp)) != CRYPT_OK) { goto error; } + + /* ensure (p-1)/2 is prime */ + if ((err = mp_prime_is_prime(tmp, 8, &primality)) != CRYPT_OK) { goto done; } + if (primality == 0) { + err = CRYPT_FAIL_TESTVECTOR; + goto done; + } + + /* now see if g^((p-1)/2) mod p is in fact 1 */ + if ((err = mp_exptmod(g, tmp, p, tmp)) != CRYPT_OK) { goto error; } + if (mp_cmp_d(tmp, 1)) { + err = CRYPT_FAIL_TESTVECTOR; + goto done; + } + } + err = CRYPT_OK; +error: +done: + mp_clear_multi(tmp, g, p, LTC_NULL); + return err; +} + +static int s_dhparam_test(void) +{ + dh_key k; + unsigned char buf[1024]; + /* generated by: openssl dhparam -outform der -out dhparam.der 2048 */ + unsigned char dhparam_der[] = { + 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0xfe, 0x78, 0xce, 0x80, 0xd5, 0xd7, + 0x8e, 0xcc, 0x4f, 0x0c, 0x1b, 0xb0, 0x95, 0x10, 0xe1, 0x41, 0x15, 0x53, 0x4d, 0x0e, 0x68, 0xb0, + 0xf8, 0x5a, 0x41, 0x0e, 0x65, 0x2f, 0x9f, 0xac, 0x9c, 0x30, 0xb0, 0x76, 0xec, 0x02, 0xe9, 0x43, + 0x55, 0x08, 0xb4, 0x20, 0x60, 0xd9, 0x52, 0xda, 0x2d, 0xab, 0x9a, 0xba, 0xe6, 0xcf, 0x11, 0xa7, + 0x00, 0x44, 0xc2, 0x5e, 0xd1, 0xba, 0x9b, 0xaa, 0xfe, 0x03, 0xdd, 0xdc, 0xef, 0x41, 0x89, 0x9c, + 0xac, 0x64, 0x13, 0xd9, 0x6a, 0x8a, 0x55, 0xa0, 0x5b, 0xff, 0x12, 0x92, 0x37, 0x52, 0x6a, 0x91, + 0xa4, 0x6e, 0x9e, 0x61, 0xb7, 0xfe, 0xb0, 0x17, 0x8e, 0x67, 0x0f, 0x88, 0x46, 0xa7, 0x9e, 0xb1, + 0xdb, 0x68, 0x77, 0x70, 0xb5, 0x77, 0xf2, 0x7e, 0x33, 0xb1, 0x3e, 0x10, 0xc4, 0x63, 0x36, 0xd0, + 0x13, 0x27, 0xd3, 0x29, 0xc3, 0xb6, 0x5d, 0xf6, 0x5d, 0xa7, 0xd8, 0x25, 0x5c, 0x0b, 0x65, 0x99, + 0xfa, 0xf9, 0x5f, 0x1d, 0xee, 0xd1, 0x86, 0x64, 0x7c, 0x44, 0xcb, 0xa0, 0x12, 0x52, 0x4c, 0xd4, + 0x46, 0x81, 0xae, 0x07, 0xdb, 0xc7, 0x13, 0x29, 0xce, 0x9b, 0xcf, 0x1c, 0x06, 0xd2, 0x0f, 0x2d, + 0xbb, 0x12, 0x33, 0xb9, 0xb1, 0x0f, 0x67, 0x5d, 0x3f, 0x0c, 0xe4, 0xfa, 0x67, 0x26, 0xe2, 0x89, + 0xa2, 0xd5, 0x66, 0x29, 0x1c, 0xe2, 0x8e, 0xbb, 0x7b, 0xcb, 0xcc, 0x70, 0x7e, 0x4f, 0x0e, 0xd3, + 0x5d, 0x64, 0x64, 0x1b, 0x27, 0xbb, 0xda, 0xa9, 0x08, 0x2b, 0x62, 0xd4, 0xca, 0xc3, 0x3a, 0x23, + 0x39, 0x58, 0x57, 0xaf, 0x7b, 0x8b, 0x0c, 0x5b, 0x2e, 0xfc, 0x42, 0x57, 0x59, 0x39, 0x2e, 0x6d, + 0x39, 0x97, 0xdb, 0x5b, 0x5c, 0xb9, 0x59, 0x71, 0x42, 0xf3, 0xcd, 0xea, 0xda, 0x86, 0x54, 0x86, + 0x61, 0x8d, 0x93, 0x66, 0xc7, 0x65, 0xd1, 0x98, 0xcb, 0x02, 0x01, 0x02 + }; + /* text dump: openssl dh -inform DER -in dhparam.der -text + DH Parameters: (2048 bit) + prime: + 00:ae:fe:78:ce:80:d5:d7:8e:cc:4f:0c:1b:b0:95: + 10:e1:41:15:53:4d:0e:68:b0:f8:5a:41:0e:65:2f: + 9f:ac:9c:30:b0:76:ec:02:e9:43:55:08:b4:20:60: + d9:52:da:2d:ab:9a:ba:e6:cf:11:a7:00:44:c2:5e: + d1:ba:9b:aa:fe:03:dd:dc:ef:41:89:9c:ac:64:13: + d9:6a:8a:55:a0:5b:ff:12:92:37:52:6a:91:a4:6e: + 9e:61:b7:fe:b0:17:8e:67:0f:88:46:a7:9e:b1:db: + 68:77:70:b5:77:f2:7e:33:b1:3e:10:c4:63:36:d0: + 13:27:d3:29:c3:b6:5d:f6:5d:a7:d8:25:5c:0b:65: + 99:fa:f9:5f:1d:ee:d1:86:64:7c:44:cb:a0:12:52: + 4c:d4:46:81:ae:07:db:c7:13:29:ce:9b:cf:1c:06: + d2:0f:2d:bb:12:33:b9:b1:0f:67:5d:3f:0c:e4:fa: + 67:26:e2:89:a2:d5:66:29:1c:e2:8e:bb:7b:cb:cc: + 70:7e:4f:0e:d3:5d:64:64:1b:27:bb:da:a9:08:2b: + 62:d4:ca:c3:3a:23:39:58:57:af:7b:8b:0c:5b:2e: + fc:42:57:59:39:2e:6d:39:97:db:5b:5c:b9:59:71: + 42:f3:cd:ea:da:86:54:86:61:8d:93:66:c7:65:d1: + 98:cb + generator: 2 (0x2) + */ + unsigned char prime[] = { + 0xae, 0xfe, 0x78, 0xce, 0x80, 0xd5, 0xd7, 0x8e, 0xcc, 0x4f, 0x0c, 0x1b, 0xb0, 0x95, + 0x10, 0xe1, 0x41, 0x15, 0x53, 0x4d, 0x0e, 0x68, 0xb0, 0xf8, 0x5a, 0x41, 0x0e, 0x65, 0x2f, + 0x9f, 0xac, 0x9c, 0x30, 0xb0, 0x76, 0xec, 0x02, 0xe9, 0x43, 0x55, 0x08, 0xb4, 0x20, 0x60, + 0xd9, 0x52, 0xda, 0x2d, 0xab, 0x9a, 0xba, 0xe6, 0xcf, 0x11, 0xa7, 0x00, 0x44, 0xc2, 0x5e, + 0xd1, 0xba, 0x9b, 0xaa, 0xfe, 0x03, 0xdd, 0xdc, 0xef, 0x41, 0x89, 0x9c, 0xac, 0x64, 0x13, + 0xd9, 0x6a, 0x8a, 0x55, 0xa0, 0x5b, 0xff, 0x12, 0x92, 0x37, 0x52, 0x6a, 0x91, 0xa4, 0x6e, + 0x9e, 0x61, 0xb7, 0xfe, 0xb0, 0x17, 0x8e, 0x67, 0x0f, 0x88, 0x46, 0xa7, 0x9e, 0xb1, 0xdb, + 0x68, 0x77, 0x70, 0xb5, 0x77, 0xf2, 0x7e, 0x33, 0xb1, 0x3e, 0x10, 0xc4, 0x63, 0x36, 0xd0, + 0x13, 0x27, 0xd3, 0x29, 0xc3, 0xb6, 0x5d, 0xf6, 0x5d, 0xa7, 0xd8, 0x25, 0x5c, 0x0b, 0x65, + 0x99, 0xfa, 0xf9, 0x5f, 0x1d, 0xee, 0xd1, 0x86, 0x64, 0x7c, 0x44, 0xcb, 0xa0, 0x12, 0x52, + 0x4c, 0xd4, 0x46, 0x81, 0xae, 0x07, 0xdb, 0xc7, 0x13, 0x29, 0xce, 0x9b, 0xcf, 0x1c, 0x06, + 0xd2, 0x0f, 0x2d, 0xbb, 0x12, 0x33, 0xb9, 0xb1, 0x0f, 0x67, 0x5d, 0x3f, 0x0c, 0xe4, 0xfa, + 0x67, 0x26, 0xe2, 0x89, 0xa2, 0xd5, 0x66, 0x29, 0x1c, 0xe2, 0x8e, 0xbb, 0x7b, 0xcb, 0xcc, + 0x70, 0x7e, 0x4f, 0x0e, 0xd3, 0x5d, 0x64, 0x64, 0x1b, 0x27, 0xbb, 0xda, 0xa9, 0x08, 0x2b, + 0x62, 0xd4, 0xca, 0xc3, 0x3a, 0x23, 0x39, 0x58, 0x57, 0xaf, 0x7b, 0x8b, 0x0c, 0x5b, 0x2e, + 0xfc, 0x42, 0x57, 0x59, 0x39, 0x2e, 0x6d, 0x39, 0x97, 0xdb, 0x5b, 0x5c, 0xb9, 0x59, 0x71, + 0x42, 0xf3, 0xcd, 0xea, 0xda, 0x86, 0x54, 0x86, 0x61, 0x8d, 0x93, 0x66, 0xc7, 0x65, 0xd1, + 0x98, 0xcb + }; + + DO(dh_set_pg_dhparam(dhparam_der, sizeof(dhparam_der), &k)); + DO(dh_generate_key(&yarrow_prng, find_prng ("yarrow"), &k)); + if (mp_unsigned_bin_size(k.prime) > sizeof(buf)) { + printf("dhparam_test: short buf\n"); + dh_free(&k); + return CRYPT_ERROR; + } + DO(mp_to_unsigned_bin(k.prime, buf)); + DO(do_compare_testvector(buf, sizeof(prime), prime, sizeof(prime), "dhparam_test: prime mismatch", 1)); + if (mp_cmp_d(k.base, 2) != LTC_MP_EQ) { + printf("dhparam_test: base mismatch\n"); + dh_free(&k); + return CRYPT_ERROR; + } + dh_free(&k); + return CRYPT_OK; +} + +static int s_set_test(void) +{ + dh_key k1, k2, k3; + unsigned char buf[4096]; + unsigned long len; + int i; + unsigned char gbin[] = { 0x02 }; + unsigned char pbin[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + unsigned char xbin[] = { + 0xA6, 0x68, 0x1A, 0xDC, 0x38, 0x6C, 0xE9, 0x44, 0xC3, 0xDE, 0xD9, 0xA7, 0x30, 0x1D, 0xCC, 0x9C, + 0x51, 0x82, 0x50, 0xE3, 0xED, 0xB6, 0x2F, 0x95, 0x91, 0x98, 0xF8, 0xDC, 0x00, 0x57, 0xDD, 0x6F, + 0xB5, 0x7A, 0xBA, 0xFD, 0x78, 0x81, 0x98, 0xB1 + }; + unsigned char ybin[] = { + 0x39, 0x04, 0x66, 0x32, 0xC8, 0x34, 0x41, 0x8D, 0xFA, 0x07, 0xB3, 0x09, 0x15, 0x38, 0xB6, 0x14, + 0xD1, 0xFB, 0x5D, 0xBB, 0x78, 0x5C, 0x0F, 0xBE, 0xA3, 0xB9, 0x8B, 0x29, 0x5B, 0xC0, 0xCD, 0x07, + 0x6A, 0x88, 0xD9, 0x45, 0x21, 0x41, 0xA2, 0x69, 0xE8, 0xBA, 0xEB, 0x1D, 0xD6, 0x54, 0xEB, 0xA0, + 0x3A, 0x57, 0x05, 0x31, 0x8D, 0x12, 0x97, 0x54, 0xCD, 0xF4, 0x00, 0x3A, 0x8C, 0x39, 0x92, 0x40, + 0xFB, 0xB8, 0xF1, 0x62, 0x49, 0x0F, 0x6F, 0x0D, 0xC7, 0x0E, 0x41, 0x4B, 0x6F, 0xEE, 0x88, 0x08, + 0x6A, 0xFA, 0xA4, 0x8E, 0x9F, 0x3A, 0x24, 0x8E, 0xDC, 0x09, 0x34, 0x52, 0x66, 0x3D, 0x34, 0xE0, + 0xE8, 0x09, 0xD4, 0xF6, 0xBA, 0xDB, 0xB3, 0x6F, 0x80, 0xB6, 0x81, 0x3E, 0xBF, 0x7C, 0x32, 0x81, + 0xB8, 0x62, 0x20, 0x9E, 0x56, 0x04, 0xBD, 0xEA, 0x8B, 0x8F, 0x5F, 0x7B, 0xFD, 0xC3, 0xEE, 0xB7, + 0xAD, 0xB7, 0x30, 0x48, 0x28, 0x9B, 0xCE, 0xA0, 0xF5, 0xA5, 0xCD, 0xEE, 0x7D, 0xF9, 0x1C, 0xD1, + 0xF0, 0xBA, 0x63, 0x2F, 0x06, 0xDB, 0xE9, 0xBA, 0x7E, 0xF0, 0x14, 0xB8, 0x4B, 0x02, 0xD4, 0x97, + 0xCA, 0x7D, 0x0C, 0x60, 0xF7, 0x34, 0x75, 0x2A, 0x64, 0x9D, 0xA4, 0x96, 0x94, 0x6B, 0x4E, 0x53, + 0x1B, 0x30, 0xD9, 0xF8, 0x2E, 0xDD, 0x85, 0x56, 0x36, 0xC0, 0xB0, 0xF2, 0xAE, 0x23, 0x2E, 0x41, + 0x86, 0x45, 0x4E, 0x88, 0x87, 0xBB, 0x42, 0x3E, 0x32, 0xA5, 0xA2, 0x49, 0x5E, 0xAC, 0xBA, 0x99, + 0x62, 0x0A, 0xCD, 0x03, 0xA3, 0x83, 0x45, 0xEB, 0xB6, 0x73, 0x5E, 0x62, 0x33, 0x0A, 0x8E, 0xE9, + 0xAA, 0x6C, 0x83, 0x70, 0x41, 0x0F, 0x5C, 0xD4, 0x5A, 0xF3, 0x7E, 0xE9, 0x0A, 0x0D, 0xA9, 0x5B, + 0xE9, 0x6F, 0xC9, 0x39, 0xE8, 0x8F, 0xE0, 0xBD, 0x2C, 0xD0, 0x9F, 0xC8, 0xF5, 0x24, 0x20, 0x8C + }; + + struct { + int radix; + void* g; int glen; + void* p; int plen; + void* x; int xlen; + void* y; int ylen; + } test[1] = { + { 256, gbin, sizeof(gbin), pbin, sizeof(pbin), xbin, sizeof(xbin), ybin, sizeof(ybin) } + }; + + unsigned char export_private[] = { + 0x30, 0x82, 0x01, 0x3A, 0x02, 0x01, 0x00, 0x03, 0x02, 0x07, 0x80, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x02, 0x01, 0x02, 0x02, 0x29, 0x00, 0xA6, 0x68, 0x1A, 0xDC, 0x38, 0x6C, 0xE9, 0x44, 0xC3, 0xDE, + 0xD9, 0xA7, 0x30, 0x1D, 0xCC, 0x9C, 0x51, 0x82, 0x50, 0xE3, 0xED, 0xB6, 0x2F, 0x95, 0x91, 0x98, + 0xF8, 0xDC, 0x00, 0x57, 0xDD, 0x6F, 0xB5, 0x7A, 0xBA, 0xFD, 0x78, 0x81, 0x98, 0xB1 + }; + unsigned char export_public[] = { + 0x30, 0x82, 0x02, 0x13, 0x02, 0x01, 0x00, 0x03, 0x02, 0x07, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x02, 0x01, 0x02, 0x02, 0x82, 0x01, 0x00, 0x39, 0x04, 0x66, 0x32, 0xC8, 0x34, 0x41, 0x8D, 0xFA, + 0x07, 0xB3, 0x09, 0x15, 0x38, 0xB6, 0x14, 0xD1, 0xFB, 0x5D, 0xBB, 0x78, 0x5C, 0x0F, 0xBE, 0xA3, + 0xB9, 0x8B, 0x29, 0x5B, 0xC0, 0xCD, 0x07, 0x6A, 0x88, 0xD9, 0x45, 0x21, 0x41, 0xA2, 0x69, 0xE8, + 0xBA, 0xEB, 0x1D, 0xD6, 0x54, 0xEB, 0xA0, 0x3A, 0x57, 0x05, 0x31, 0x8D, 0x12, 0x97, 0x54, 0xCD, + 0xF4, 0x00, 0x3A, 0x8C, 0x39, 0x92, 0x40, 0xFB, 0xB8, 0xF1, 0x62, 0x49, 0x0F, 0x6F, 0x0D, 0xC7, + 0x0E, 0x41, 0x4B, 0x6F, 0xEE, 0x88, 0x08, 0x6A, 0xFA, 0xA4, 0x8E, 0x9F, 0x3A, 0x24, 0x8E, 0xDC, + 0x09, 0x34, 0x52, 0x66, 0x3D, 0x34, 0xE0, 0xE8, 0x09, 0xD4, 0xF6, 0xBA, 0xDB, 0xB3, 0x6F, 0x80, + 0xB6, 0x81, 0x3E, 0xBF, 0x7C, 0x32, 0x81, 0xB8, 0x62, 0x20, 0x9E, 0x56, 0x04, 0xBD, 0xEA, 0x8B, + 0x8F, 0x5F, 0x7B, 0xFD, 0xC3, 0xEE, 0xB7, 0xAD, 0xB7, 0x30, 0x48, 0x28, 0x9B, 0xCE, 0xA0, 0xF5, + 0xA5, 0xCD, 0xEE, 0x7D, 0xF9, 0x1C, 0xD1, 0xF0, 0xBA, 0x63, 0x2F, 0x06, 0xDB, 0xE9, 0xBA, 0x7E, + 0xF0, 0x14, 0xB8, 0x4B, 0x02, 0xD4, 0x97, 0xCA, 0x7D, 0x0C, 0x60, 0xF7, 0x34, 0x75, 0x2A, 0x64, + 0x9D, 0xA4, 0x96, 0x94, 0x6B, 0x4E, 0x53, 0x1B, 0x30, 0xD9, 0xF8, 0x2E, 0xDD, 0x85, 0x56, 0x36, + 0xC0, 0xB0, 0xF2, 0xAE, 0x23, 0x2E, 0x41, 0x86, 0x45, 0x4E, 0x88, 0x87, 0xBB, 0x42, 0x3E, 0x32, + 0xA5, 0xA2, 0x49, 0x5E, 0xAC, 0xBA, 0x99, 0x62, 0x0A, 0xCD, 0x03, 0xA3, 0x83, 0x45, 0xEB, 0xB6, + 0x73, 0x5E, 0x62, 0x33, 0x0A, 0x8E, 0xE9, 0xAA, 0x6C, 0x83, 0x70, 0x41, 0x0F, 0x5C, 0xD4, 0x5A, + 0xF3, 0x7E, 0xE9, 0x0A, 0x0D, 0xA9, 0x5B, 0xE9, 0x6F, 0xC9, 0x39, 0xE8, 0x8F, 0xE0, 0xBD, 0x2C, + 0xD0, 0x9F, 0xC8, 0xF5, 0x24, 0x20, 0x8C + }; + + for (i = 0; i < 1; i++) { + DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k1)); + DO(dh_set_key(test[i].x, test[i].xlen, PK_PRIVATE, &k1)); + + len = sizeof(buf); + DO(dh_export(buf, &len, PK_PRIVATE, &k1)); + DO(do_compare_testvector(buf, len, export_private, sizeof(export_private), "radix_test: dh_export+PK_PRIVATE mismatch", i*10 + 0)); + len = sizeof(buf); + DO(dh_export(buf, &len, PK_PUBLIC, &k1)); + DO(do_compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test: dh_export+PK_PUBLIC mismatch", i*10 + 1)); + len = sizeof(buf); + DO(dh_export_key(buf, &len, PK_PRIVATE, &k1)); + DO(do_compare_testvector(buf, len, xbin, sizeof(xbin), "radix_test: dh_export+PK_PRIVATE mismatch", i*10 + 2)); + len = sizeof(buf); + DO(dh_export_key(buf, &len, PK_PUBLIC, &k1)); + DO(do_compare_testvector(buf, len, ybin, sizeof(ybin), "radix_test: dh_export+PK_PUBLIC mismatch", i*10 + 3)); + dh_free(&k1); + + DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k1)); + DO(dh_set_key(test[i].x, test[i].xlen, PK_PRIVATE, &k1)); + + len = sizeof(buf); + DO(dh_export(buf, &len, PK_PRIVATE, &k1)); + DO(do_compare_testvector(buf, len, export_private, sizeof(export_private), "radix_test: dh_export+PK_PRIVATE mismatc", i*10 + 4)); + len = sizeof(buf); + DO(dh_export(buf, &len, PK_PUBLIC, &k1)); + DO(do_compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test: dh_export+PK_PUBLIC mismatch", i*10 + 5)); + dh_free(&k1); + + DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k2)); + DO(dh_set_key(test[i].y, test[i].ylen, PK_PUBLIC, &k2)); + + len = sizeof(buf); + DO(dh_export(buf, &len, PK_PUBLIC, &k2)); + DO(do_compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test: dh_export+PK_PUBLIC mismatch", i*10 + 6)); + len = sizeof(buf); + DO(dh_export_key(buf, &len, PK_PUBLIC, &k2)); + DO(do_compare_testvector(buf, len, ybin, sizeof(ybin), "radix_test: dh_export+PK_PUBLIC mismatch", i*10 + 7)); + dh_free(&k2); + + DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k3)); + DO(dh_generate_key(&yarrow_prng, find_prng("yarrow"), &k3)); + + len = mp_unsigned_bin_size(k3.prime); + DO(mp_to_unsigned_bin(k3.prime, buf)); + DO(do_compare_testvector(buf, len, pbin, sizeof(pbin), "radix_test: dh_make_key_ex prime mismatch", i*10 + 8)); + len = mp_unsigned_bin_size(k3.base); + DO(mp_to_unsigned_bin(k3.base, buf)); + DO(do_compare_testvector(buf, len, gbin, sizeof(gbin), "radix_test: dh_make_key_ex base mismatch", i*10 + 9)); + dh_free(&k3); + } + + return CRYPT_OK; +} + +static int s_basic_test(void) +{ + unsigned char buf[3][4096]; + unsigned long x, y, z; + int size, KEYSIZE; + dh_key usera, userb; + + /* tfm has a problem with larger sizes */ + KEYSIZE = (strcmp(ltc_mp.name, "TomsFastMath") == 0) ? 2048 : 4096; + + /* make up two keys */ + DO(dh_set_pg_groupsize(KEYSIZE/8, &usera)); + DO(dh_generate_key(&yarrow_prng, find_prng ("yarrow"), &usera)); + DO(dh_set_pg_groupsize(KEYSIZE/8, &userb)); + DO(dh_generate_key(&yarrow_prng, find_prng ("yarrow"), &userb)); + + /* make the shared secret */ + x = KEYSIZE; + DO(dh_shared_secret (&usera, &userb, buf[0], &x)); + + y = KEYSIZE; + DO(dh_shared_secret (&userb, &usera, buf[1], &y)); + if (y != x) { + fprintf(stderr, "DH Shared keys are not same size.\n"); + dh_free (&usera); + dh_free (&userb); + return CRYPT_ERROR; + } + if (memcmp (buf[0], buf[1], x)) { + fprintf(stderr, "DH Shared keys not same contents.\n"); + dh_free (&usera); + dh_free (&userb); + return CRYPT_ERROR; + } + + /* now export userb */ + y = KEYSIZE; + DO(dh_export (buf[1], &y, PK_PUBLIC, &userb)); + dh_free (&userb); + + /* import and make the shared secret again */ + DO(dh_import (buf[1], y, &userb)); + z = KEYSIZE; + DO(dh_shared_secret (&usera, &userb, buf[2], &z)); + + dh_free (&usera); + dh_free (&userb); + + if (z != x) { + fprintf(stderr, "failed. Size don't match?\n"); + return CRYPT_ERROR; + } + if (memcmp (buf[0], buf[2], x)) { + fprintf(stderr, "Failed. Content didn't match.\n"); + return CRYPT_ERROR; + } + + for (x = 0; ltc_dh_sets[x].size != 0; x++) { + /* tfm has a problem with larger sizes */ + if ((strcmp(ltc_mp.name, "TomsFastMath") == 0) && (ltc_dh_sets[x].size > 256)) break; + + DO(dh_set_pg_groupsize(ltc_dh_sets[x].size, &usera)); + DO(dh_generate_key(&yarrow_prng, find_prng ("yarrow"), &usera)); + size = dh_get_groupsize(&usera); + dh_free(&usera); + if (size != ltc_dh_sets[x].size) { + fprintf(stderr, "dh_groupsize mismatch %d %d\n", size, ltc_dh_sets[x].size); + return CRYPT_ERROR; + } + dh_free(&usera); + } + + return CRYPT_OK; +} + +int dh_test(void) +{ + int fails = 0; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + if (s_prime_test() != CRYPT_OK) fails++; + if (s_basic_test() != CRYPT_OK) fails++; + if (s_dhparam_test() != CRYPT_OK) fails++; + if (s_set_test() != CRYPT_OK) fails++; + return fails > 0 ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK; +} + +#else + +int dh_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/deps/libtomcrypt/tests/dsa_test.c b/deps/libtomcrypt/tests/dsa_test.c new file mode 100644 index 0000000..6a94a63 --- /dev/null +++ b/deps/libtomcrypt/tests/dsa_test.c @@ -0,0 +1,379 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_MDSA) + +/* This is the private key from test_dsa.key */ +static const unsigned char openssl_priv_dsa[] = { + 0x30, 0x82, 0x01, 0xbb, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xc5, + 0x0a, 0x37, 0x51, 0x5c, 0xab, 0xd6, 0x18, 0xd5, 0xa2, 0x70, 0xbd, 0x4a, + 0x6f, 0x6b, 0x4a, 0xf9, 0xe1, 0x39, 0x95, 0x0f, 0x2b, 0x99, 0x38, 0x7d, + 0x9a, 0x64, 0xd6, 0x4c, 0xb5, 0x96, 0x7a, 0xdc, 0xed, 0xac, 0xa8, 0xac, + 0xc6, 0x1b, 0x65, 0x5a, 0xde, 0xdb, 0x00, 0x61, 0x25, 0x1a, 0x18, 0x2c, + 0xee, 0xa1, 0x07, 0x90, 0x62, 0x5e, 0x4d, 0x12, 0x31, 0x90, 0xc7, 0x03, + 0x21, 0xfa, 0x09, 0xe7, 0xb1, 0x73, 0xd7, 0x8e, 0xaf, 0xdb, 0xfd, 0xbf, + 0xb3, 0xef, 0xad, 0xd1, 0xa1, 0x2a, 0x03, 0x6d, 0xe7, 0x06, 0x92, 0x4a, + 0x85, 0x2a, 0xff, 0x7a, 0x01, 0x66, 0x53, 0x1f, 0xea, 0xc6, 0x67, 0x41, + 0x84, 0x5a, 0xc0, 0x6c, 0xed, 0x62, 0xf9, 0xc2, 0x62, 0x62, 0x05, 0xa4, + 0xfa, 0x48, 0xa0, 0x66, 0xec, 0x35, 0xc9, 0xa8, 0x11, 0xfe, 0xb9, 0x81, + 0xab, 0xee, 0xbe, 0x31, 0xb6, 0xbf, 0xcf, 0x02, 0x15, 0x00, 0xaa, 0x5b, + 0xd7, 0xf4, 0xe5, 0x06, 0x24, 0x13, 0xe5, 0x88, 0x35, 0xca, 0x00, 0xc7, + 0xa6, 0x35, 0x71, 0x61, 0x94, 0xc5, 0x02, 0x81, 0x80, 0x3b, 0x92, 0xe4, + 0xff, 0x59, 0x29, 0x15, 0x0b, 0x08, 0x99, 0x5a, 0x7b, 0xf2, 0xad, 0x14, + 0x40, 0x55, 0x6f, 0xa0, 0x47, 0xff, 0x90, 0x99, 0xb3, 0x44, 0xb3, 0xd4, + 0xfc, 0x45, 0x15, 0x05, 0xae, 0x67, 0x22, 0x43, 0x9c, 0xba, 0x37, 0x10, + 0xa5, 0x89, 0x47, 0x37, 0xec, 0xcc, 0xf5, 0xae, 0xad, 0xa8, 0xb4, 0x7a, + 0x35, 0xcb, 0x9d, 0x93, 0x5c, 0xed, 0xe6, 0xb0, 0x7e, 0x96, 0x94, 0xc4, + 0xa6, 0x0c, 0x7d, 0xd6, 0x70, 0x8a, 0x09, 0x4f, 0x81, 0x4a, 0x0e, 0xc2, + 0x13, 0xfb, 0xeb, 0x16, 0xbf, 0xea, 0xa4, 0xf4, 0x56, 0xff, 0x72, 0x30, + 0x05, 0xde, 0x8a, 0x44, 0x3f, 0xbe, 0xc6, 0x85, 0x26, 0x55, 0xd6, 0x2d, + 0x1d, 0x1e, 0xdb, 0x15, 0xda, 0xa4, 0x45, 0x83, 0x3c, 0x17, 0x97, 0x98, + 0x0b, 0x8d, 0x87, 0xf3, 0x49, 0x0d, 0x90, 0xbd, 0xa9, 0xab, 0x67, 0x6e, + 0x87, 0x68, 0x72, 0x23, 0xdc, 0x02, 0x81, 0x80, 0x53, 0x16, 0xb0, 0xfb, + 0xbf, 0x59, 0x8a, 0x5e, 0x55, 0x95, 0xc1, 0x4f, 0xac, 0x43, 0xb8, 0x08, + 0x53, 0xe6, 0xcf, 0x0d, 0x92, 0x23, 0xfa, 0xb1, 0x84, 0x59, 0x52, 0x39, + 0xbf, 0xcb, 0xf2, 0x2d, 0x38, 0x3a, 0xdd, 0x93, 0x52, 0x05, 0x49, 0x7e, + 0x2b, 0x12, 0xc4, 0x61, 0x73, 0xe3, 0x6f, 0x54, 0xbd, 0x96, 0xe5, 0xa7, + 0xaa, 0xa9, 0x5a, 0x58, 0xa4, 0xb7, 0x67, 0xd2, 0xc0, 0xbd, 0xc8, 0x1e, + 0xb1, 0x3a, 0x12, 0x4f, 0x98, 0xc0, 0x05, 0xef, 0x39, 0x5d, 0x6a, 0xba, + 0xb7, 0x0b, 0x3b, 0xd8, 0xb7, 0x95, 0xdd, 0x79, 0x6e, 0xa2, 0xd2, 0x84, + 0x73, 0x47, 0x03, 0x88, 0xb4, 0x64, 0xd9, 0xb9, 0xb8, 0x4f, 0xf1, 0xc9, + 0x34, 0xbb, 0xf9, 0x73, 0x66, 0xf5, 0x7c, 0x2e, 0x11, 0xfe, 0xc3, 0x31, + 0xe6, 0x08, 0x38, 0x59, 0x67, 0x81, 0xeb, 0x6d, 0x41, 0x27, 0xd7, 0x0d, + 0x74, 0xaf, 0xa0, 0x35, 0x02, 0x15, 0x00, 0x99, 0x36, 0xe5, 0xe4, 0xe9, + 0xfb, 0x28, 0xbe, 0x91, 0xf5, 0x06, 0x5f, 0xe8, 0xc9, 0x35, 0xb3, 0xf5, + 0xd8, 0x1f, 0xc5 +}; + +/* private key - raw hexadecimal numbers */ +static const char *hex_g = "3B92E4FF5929150B08995A7BF2AD1440556FA047FF9099B344B3D4FC451505AE6722439CBA3710A5894737ECCCF5AEADA8B47A35CB9D935CEDE6B07E9694C4A60C7DD6708A094F814A0EC213FBEB16BFEAA4F456FF723005DE8A443FBEC6852655D62D1D1EDB15DAA445833C1797980B8D87F3490D90BDA9AB676E87687223DC"; +static const char *hex_p = "C50A37515CABD618D5A270BD4A6F6B4AF9E139950F2B99387D9A64D64CB5967ADCEDACA8ACC61B655ADEDB0061251A182CEEA10790625E4D123190C70321FA09E7B173D78EAFDBFDBFB3EFADD1A12A036DE706924A852AFF7A0166531FEAC66741845AC06CED62F9C2626205A4FA48A066EC35C9A811FEB981ABEEBE31B6BFCF"; +static const char *hex_q = "AA5BD7F4E5062413E58835CA00C7A635716194C5"; +static const char *hex_x = "9936E5E4E9FB28BE91F5065FE8C935B3F5D81FC5"; +static const char *hex_y = "5316B0FBBF598A5E5595C14FAC43B80853E6CF0D9223FAB184595239BFCBF22D383ADD935205497E2B12C46173E36F54BD96E5A7AAA95A58A4B767D2C0BDC81EB13A124F98C005EF395D6ABAB70B3BD8B795DD796EA2D28473470388B464D9B9B84FF1C934BBF97366F57C2E11FEC331E60838596781EB6D4127D70D74AFA035"; + +/* The public part of test_dsa.key in SubjectPublicKeyInfo format */ +static const unsigned char openssl_pub_dsa[] = { + 0x30, 0x82, 0x01, 0xb6, 0x30, 0x82, 0x01, 0x2b, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x38, 0x04, 0x01, 0x30, 0x82, 0x01, 0x1e, 0x02, 0x81, 0x81, + 0x00, 0xc5, 0x0a, 0x37, 0x51, 0x5c, 0xab, 0xd6, 0x18, 0xd5, 0xa2, 0x70, + 0xbd, 0x4a, 0x6f, 0x6b, 0x4a, 0xf9, 0xe1, 0x39, 0x95, 0x0f, 0x2b, 0x99, + 0x38, 0x7d, 0x9a, 0x64, 0xd6, 0x4c, 0xb5, 0x96, 0x7a, 0xdc, 0xed, 0xac, + 0xa8, 0xac, 0xc6, 0x1b, 0x65, 0x5a, 0xde, 0xdb, 0x00, 0x61, 0x25, 0x1a, + 0x18, 0x2c, 0xee, 0xa1, 0x07, 0x90, 0x62, 0x5e, 0x4d, 0x12, 0x31, 0x90, + 0xc7, 0x03, 0x21, 0xfa, 0x09, 0xe7, 0xb1, 0x73, 0xd7, 0x8e, 0xaf, 0xdb, + 0xfd, 0xbf, 0xb3, 0xef, 0xad, 0xd1, 0xa1, 0x2a, 0x03, 0x6d, 0xe7, 0x06, + 0x92, 0x4a, 0x85, 0x2a, 0xff, 0x7a, 0x01, 0x66, 0x53, 0x1f, 0xea, 0xc6, + 0x67, 0x41, 0x84, 0x5a, 0xc0, 0x6c, 0xed, 0x62, 0xf9, 0xc2, 0x62, 0x62, + 0x05, 0xa4, 0xfa, 0x48, 0xa0, 0x66, 0xec, 0x35, 0xc9, 0xa8, 0x11, 0xfe, + 0xb9, 0x81, 0xab, 0xee, 0xbe, 0x31, 0xb6, 0xbf, 0xcf, 0x02, 0x15, 0x00, + 0xaa, 0x5b, 0xd7, 0xf4, 0xe5, 0x06, 0x24, 0x13, 0xe5, 0x88, 0x35, 0xca, + 0x00, 0xc7, 0xa6, 0x35, 0x71, 0x61, 0x94, 0xc5, 0x02, 0x81, 0x80, 0x3b, + 0x92, 0xe4, 0xff, 0x59, 0x29, 0x15, 0x0b, 0x08, 0x99, 0x5a, 0x7b, 0xf2, + 0xad, 0x14, 0x40, 0x55, 0x6f, 0xa0, 0x47, 0xff, 0x90, 0x99, 0xb3, 0x44, + 0xb3, 0xd4, 0xfc, 0x45, 0x15, 0x05, 0xae, 0x67, 0x22, 0x43, 0x9c, 0xba, + 0x37, 0x10, 0xa5, 0x89, 0x47, 0x37, 0xec, 0xcc, 0xf5, 0xae, 0xad, 0xa8, + 0xb4, 0x7a, 0x35, 0xcb, 0x9d, 0x93, 0x5c, 0xed, 0xe6, 0xb0, 0x7e, 0x96, + 0x94, 0xc4, 0xa6, 0x0c, 0x7d, 0xd6, 0x70, 0x8a, 0x09, 0x4f, 0x81, 0x4a, + 0x0e, 0xc2, 0x13, 0xfb, 0xeb, 0x16, 0xbf, 0xea, 0xa4, 0xf4, 0x56, 0xff, + 0x72, 0x30, 0x05, 0xde, 0x8a, 0x44, 0x3f, 0xbe, 0xc6, 0x85, 0x26, 0x55, + 0xd6, 0x2d, 0x1d, 0x1e, 0xdb, 0x15, 0xda, 0xa4, 0x45, 0x83, 0x3c, 0x17, + 0x97, 0x98, 0x0b, 0x8d, 0x87, 0xf3, 0x49, 0x0d, 0x90, 0xbd, 0xa9, 0xab, + 0x67, 0x6e, 0x87, 0x68, 0x72, 0x23, 0xdc, 0x03, 0x81, 0x84, 0x00, 0x02, + 0x81, 0x80, 0x53, 0x16, 0xb0, 0xfb, 0xbf, 0x59, 0x8a, 0x5e, 0x55, 0x95, + 0xc1, 0x4f, 0xac, 0x43, 0xb8, 0x08, 0x53, 0xe6, 0xcf, 0x0d, 0x92, 0x23, + 0xfa, 0xb1, 0x84, 0x59, 0x52, 0x39, 0xbf, 0xcb, 0xf2, 0x2d, 0x38, 0x3a, + 0xdd, 0x93, 0x52, 0x05, 0x49, 0x7e, 0x2b, 0x12, 0xc4, 0x61, 0x73, 0xe3, + 0x6f, 0x54, 0xbd, 0x96, 0xe5, 0xa7, 0xaa, 0xa9, 0x5a, 0x58, 0xa4, 0xb7, + 0x67, 0xd2, 0xc0, 0xbd, 0xc8, 0x1e, 0xb1, 0x3a, 0x12, 0x4f, 0x98, 0xc0, + 0x05, 0xef, 0x39, 0x5d, 0x6a, 0xba, 0xb7, 0x0b, 0x3b, 0xd8, 0xb7, 0x95, + 0xdd, 0x79, 0x6e, 0xa2, 0xd2, 0x84, 0x73, 0x47, 0x03, 0x88, 0xb4, 0x64, + 0xd9, 0xb9, 0xb8, 0x4f, 0xf1, 0xc9, 0x34, 0xbb, 0xf9, 0x73, 0x66, 0xf5, + 0x7c, 0x2e, 0x11, 0xfe, 0xc3, 0x31, 0xe6, 0x08, 0x38, 0x59, 0x67, 0x81, + 0xeb, 0x6d, 0x41, 0x27, 0xd7, 0x0d, 0x74, 0xaf, 0xa0, 0x35 +}; + +static unsigned char dsaparam_der[] = { + 0x30, 0x82, 0x01, 0x1e, 0x02, 0x81, 0x81, 0x00, 0xc5, 0x0a, 0x37, 0x51, + 0x5c, 0xab, 0xd6, 0x18, 0xd5, 0xa2, 0x70, 0xbd, 0x4a, 0x6f, 0x6b, 0x4a, + 0xf9, 0xe1, 0x39, 0x95, 0x0f, 0x2b, 0x99, 0x38, 0x7d, 0x9a, 0x64, 0xd6, + 0x4c, 0xb5, 0x96, 0x7a, 0xdc, 0xed, 0xac, 0xa8, 0xac, 0xc6, 0x1b, 0x65, + 0x5a, 0xde, 0xdb, 0x00, 0x61, 0x25, 0x1a, 0x18, 0x2c, 0xee, 0xa1, 0x07, + 0x90, 0x62, 0x5e, 0x4d, 0x12, 0x31, 0x90, 0xc7, 0x03, 0x21, 0xfa, 0x09, + 0xe7, 0xb1, 0x73, 0xd7, 0x8e, 0xaf, 0xdb, 0xfd, 0xbf, 0xb3, 0xef, 0xad, + 0xd1, 0xa1, 0x2a, 0x03, 0x6d, 0xe7, 0x06, 0x92, 0x4a, 0x85, 0x2a, 0xff, + 0x7a, 0x01, 0x66, 0x53, 0x1f, 0xea, 0xc6, 0x67, 0x41, 0x84, 0x5a, 0xc0, + 0x6c, 0xed, 0x62, 0xf9, 0xc2, 0x62, 0x62, 0x05, 0xa4, 0xfa, 0x48, 0xa0, + 0x66, 0xec, 0x35, 0xc9, 0xa8, 0x11, 0xfe, 0xb9, 0x81, 0xab, 0xee, 0xbe, + 0x31, 0xb6, 0xbf, 0xcf, 0x02, 0x15, 0x00, 0xaa, 0x5b, 0xd7, 0xf4, 0xe5, + 0x06, 0x24, 0x13, 0xe5, 0x88, 0x35, 0xca, 0x00, 0xc7, 0xa6, 0x35, 0x71, + 0x61, 0x94, 0xc5, 0x02, 0x81, 0x80, 0x3b, 0x92, 0xe4, 0xff, 0x59, 0x29, + 0x15, 0x0b, 0x08, 0x99, 0x5a, 0x7b, 0xf2, 0xad, 0x14, 0x40, 0x55, 0x6f, + 0xa0, 0x47, 0xff, 0x90, 0x99, 0xb3, 0x44, 0xb3, 0xd4, 0xfc, 0x45, 0x15, + 0x05, 0xae, 0x67, 0x22, 0x43, 0x9c, 0xba, 0x37, 0x10, 0xa5, 0x89, 0x47, + 0x37, 0xec, 0xcc, 0xf5, 0xae, 0xad, 0xa8, 0xb4, 0x7a, 0x35, 0xcb, 0x9d, + 0x93, 0x5c, 0xed, 0xe6, 0xb0, 0x7e, 0x96, 0x94, 0xc4, 0xa6, 0x0c, 0x7d, + 0xd6, 0x70, 0x8a, 0x09, 0x4f, 0x81, 0x4a, 0x0e, 0xc2, 0x13, 0xfb, 0xeb, + 0x16, 0xbf, 0xea, 0xa4, 0xf4, 0x56, 0xff, 0x72, 0x30, 0x05, 0xde, 0x8a, + 0x44, 0x3f, 0xbe, 0xc6, 0x85, 0x26, 0x55, 0xd6, 0x2d, 0x1d, 0x1e, 0xdb, + 0x15, 0xda, 0xa4, 0x45, 0x83, 0x3c, 0x17, 0x97, 0x98, 0x0b, 0x8d, 0x87, + 0xf3, 0x49, 0x0d, 0x90, 0xbd, 0xa9, 0xab, 0x67, 0x6e, 0x87, 0x68, 0x72, + 0x23, 0xdc + }; + + +static int s_dsa_compat_test(void) +{ + dsa_key key; + unsigned char tmp[1024], buf[1024]; + unsigned long x, len; + unsigned char key_parts[5][256]; + unsigned long key_lens[5]; + int stat; + + DO(dsa_import(openssl_priv_dsa, sizeof(openssl_priv_dsa), &key)); + + x = sizeof(tmp); + DO(dsa_export(tmp, &x, PK_PRIVATE | PK_STD, &key)); + DO(do_compare_testvector(tmp, x, openssl_priv_dsa, sizeof(openssl_priv_dsa), + "DSA private export failed from dsa_import(priv_key)\n", __LINE__)); + + x = sizeof(tmp); + DO(dsa_export(tmp, &x, PK_PUBLIC | PK_STD, &key)); + DO(do_compare_testvector(tmp, x, openssl_pub_dsa, sizeof(openssl_pub_dsa), + "DSA public export failed from dsa_import(priv_key)\n", __LINE__)); + dsa_free(&key); + + DO(dsa_import(openssl_pub_dsa, sizeof(openssl_pub_dsa), &key)); + + x = sizeof(tmp); + DO(dsa_export(tmp, &x, PK_PUBLIC | PK_STD, &key)); + DO(do_compare_testvector(tmp, x, openssl_pub_dsa, sizeof(openssl_pub_dsa), + "DSA public export failed from dsa_import(pub_key)\n", __LINE__)); + dsa_free(&key); + + /* try import private key from raw hexadecimal numbers */ + for (x = 0; x < 5; ++x) { + key_lens[x] = sizeof(key_parts[x]); + } + DO(radix_to_bin(hex_p, 16, key_parts[0], &key_lens[0])); + DO(radix_to_bin(hex_q, 16, key_parts[1], &key_lens[1])); + DO(radix_to_bin(hex_g, 16, key_parts[2], &key_lens[2])); + DO(radix_to_bin(hex_y, 16, key_parts[3], &key_lens[3])); + DO(radix_to_bin(hex_x, 16, key_parts[4], &key_lens[4])); + + DO(dsa_set_pqg(key_parts[0], key_lens[0], + key_parts[1], key_lens[1], + key_parts[2], key_lens[2], + &key)); + DO(dsa_set_key(key_parts[4], key_lens[4], + PK_PRIVATE, + &key)); + len = sizeof(buf); + DO(dsa_export(buf, &len, PK_PRIVATE | PK_STD, &key)); + DO(do_compare_testvector(buf, len, openssl_priv_dsa, sizeof(openssl_priv_dsa), + "DSA private export failed from dsa_set_pqg() & dsa_set_key()\n", __LINE__)); + dsa_free(&key); + + /* try import public key from raw hexadecimal numbers */ + DO(dsa_set_pqg(key_parts[0], key_lens[0], + key_parts[1], key_lens[1], + key_parts[2], key_lens[2], + &key)); + DO(dsa_set_key(key_parts[3], key_lens[3], + PK_PUBLIC, + &key)); + len = sizeof(buf); + DO(dsa_export(buf, &len, PK_PUBLIC | PK_STD, &key)); + DO(do_compare_testvector(buf, len, openssl_pub_dsa, sizeof(openssl_pub_dsa), + "DSA public export failed from dsa_set_pqg() & dsa_set_key()\n", __LINE__)); + dsa_free(&key); + + /* try import dsaparam */ + DO(dsa_set_pqg_dsaparam(dsaparam_der, sizeof(dsaparam_der), &key)); + DO(dsa_generate_key(&yarrow_prng, find_prng("yarrow"), &key)); + /* verify it */ + DO(dsa_verify_key(&key, &stat)); + if (stat == 0) { + fprintf(stderr, "dsa_verify_key after dsa_set_pqg_dsaparam()"); + return CRYPT_FAIL_TESTVECTOR; + } + dsa_free(&key); + + /* try import dsaparam - our public key */ + DO(dsa_set_pqg_dsaparam(dsaparam_der, sizeof(dsaparam_der), &key)); + DO(dsa_set_key(key_parts[3], key_lens[3], + PK_PUBLIC, + &key)); + len = sizeof(buf); + DO(dsa_export(buf, &len, PK_PUBLIC | PK_STD, &key)); + DO(do_compare_testvector(buf, len, openssl_pub_dsa, sizeof(openssl_pub_dsa), + "DSA public export failed from dsa_set_pqg_dsaparam()\n", __LINE__)); + dsa_free(&key); + + /* try import dsaparam - our private key */ + DO(dsa_set_pqg_dsaparam(dsaparam_der, sizeof(dsaparam_der), &key)); + DO(dsa_set_key(key_parts[4], key_lens[4], + PK_PRIVATE, + &key)); + len = sizeof(buf); + DO(dsa_export(buf, &len, PK_PRIVATE | PK_STD, &key)); + DO(do_compare_testvector(buf, len, openssl_priv_dsa, sizeof(openssl_priv_dsa), + "DSA private export failed from dsa_set_pqg_dsaparam()\n", __LINE__)); + dsa_free(&key); + + return CRYPT_OK; +} + +static int s_dsa_wycheproof_test(void) +{ + /* test case from https://github.com/google/wycheproof/blob/master/testvectors/dsa_test.json + * + * "comment" : "appending unused 0's", + * "message" : "48656c6c6f", + * "result" : "invalid", + * "sig" : "303d021c1e41b479ad576905b960fe14eadb91b0ccf34843dab916173bb8c9cd021d00ade65988d237d30f9ef41dd424a4e1c8f16967cf3365813fe87862360000", + * "tcId" : 55 + */ + unsigned char msg[] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f }; + unsigned char sig[] = { 0x30, 0x3d, 0x02, 0x1c, 0x1e, 0x41, 0xb4, 0x79, 0xad, 0x57, 0x69, 0x05, 0xb9, 0x60, 0xfe, + 0x14, 0xea, 0xdb, 0x91, 0xb0, 0xcc, 0xf3, 0x48, 0x43, 0xda, 0xb9, 0x16, 0x17, 0x3b, 0xb8, + 0xc9, 0xcd, 0x02, 0x1d, 0x00, 0xad, 0xe6, 0x59, 0x88, 0xd2, 0x37, 0xd3, 0x0f, 0x9e, 0xf4, + 0x1d, 0xd4, 0x24, 0xa4, 0xe1, 0xc8, 0xf1, 0x69, 0x67, 0xcf, 0x33, 0x65, 0x81, 0x3f, 0xe8, + 0x78, 0x62, 0x36, 0x00, 0x00 }; + const char* b64key = + "MIIDQjCCAjUGByqGSM44BAEwggIoAoIBAQCPeTXZuarpv6vtiHrPSVG28y7FnjuvNxjo6sSWHz79" + "NgbnQ1GpxBgzObgJ58KuHFObp0dbhdARrbi0eYd1SYRpXKwOjxSzNggooi/6JxEKPWKpk0U0CaD+" + "aWxGWPhL3SCBnDcJoBBXsZWtzQAjPbpUhLYpH51kjviDRIZ3l5zsBLQ0pqwudemYXeI9sCkvwRGM" + "n/qdgYHnM423krcw17njSVkvaAmYchU5Feo9a4tGU8YzRY+AOzKkwuDycpAlbk4/ijsIOKHEUOTh" + "jBopo33fXqFD3ktm/wSQPtXPFiPhWNSHxgjpfyEc2B3KI8tuOAdl+CLjQr5ITAV2OTlgHNZnAh0A" + "uvaWpoV499/e5/pnyXfHhe8ysjO65YDAvNVpXQKCAQAWplxYIEhQcE51AqOXVwQNNNo6NHjBVNTk" + "pcAtJC7gT5bmHkvQkEq9rI837rHgnzGC0jyQQ8tkL4gAQWDt+coJsyB2p5wypifyRz6Rh5uixOdE" + "vSCBVEy1W4AsNo0fqD7UielOD6BojjJCilx4xHjGjQUntxyaOrsLC+EsRGiWOefTznTbEBplqiuH" + "9kxoJts+xy9LVZmDS7TtsC98kOmkltOlXVNb6/xF1PYZ9j897buHOSXC8iTgdzEpbaiH7B5HSPh+" + "+1/et1SEMWsiMt7lU92vAhErDR8C2jCXMiT+J67ai51LKSLZuovjntnhA6Y8UoELxoi34u1DFuHv" + "F9veA4IBBQACggEAHnf4QrGuD82ZKdOUFh1B4UYU/3UHqaMfSh8U0i4qYnofTllmJIg/GlsWjpQl" + "FG8i1fbuKHV0FHFLuZS6ESnwFdbgSnF+35tTCl1cq5TxRjHotM95rrNYzHQYRVU4QeisRhYw6ASm" + "L0Nna6Z5SvZomcN3uGnqYSp7n+ZhGqlr5S64tiyXkRe7vMqKfsHh/6scffz8cEhwDTrjhYE26Jdw" + "HXwpIbXf7x0fiX9Q2WyhtcLtxYytoYkZ41ZC8IB+6/oAyZoy9NCVwxiPeO1UcRvgMlxLUyrszWVA" + "pWfDJyJUQOoVMZveBlEEeaGGF5niW1fezHPANtdaBwK9NzyiMTSZMQ=="; + unsigned char derkey[838]; + unsigned long derlen = sizeof(derkey); + unsigned char hash[32]; + unsigned long hashlen = sizeof(hash); + dsa_key key; + int stat; + + DO(base64_decode(b64key, XSTRLEN(b64key), derkey, &derlen)); + if (derlen != 838) { + fprintf(stderr, "base64_decode failed, derlen=%lu (expected 838)\n", derlen); + return CRYPT_FAIL_TESTVECTOR; + } + DO(dsa_import(derkey, derlen, &key)); + DO(hash_memory(find_hash("sha224"), msg, sizeof(msg), hash, &hashlen)); + if (hashlen != 28) { + fprintf(stderr, "hash_memory failed, hashlen=%lu (expected 32)\n", hashlen); + return CRYPT_FAIL_TESTVECTOR; + } + + stat = 666; /* intentionally not one, not zero */ + DO(dsa_verify_hash(sig, sizeof(sig)-2, hash, hashlen, &stat, &key)); + /* without the last two 0x00 bytes it is a valid signature */ + if (stat != 1) { + fprintf(stderr, "dsa_verify_hash rejected valid signature\n"); + return CRYPT_FAIL_TESTVECTOR; + } + + stat = 666; /* intentionally not one, not zero */ + DOX(dsa_verify_hash(sig, sizeof(sig), hash, hashlen, &stat, &key) + == CRYPT_INPUT_TOO_LONG ? CRYPT_OK:CRYPT_INVALID_PACKET, "should be too long"); + /* this should be invalid */ + if (stat != 0) { + fprintf(stderr, "dsa_verify_hash did not reject invalid signature\n"); + return CRYPT_FAIL_TESTVECTOR; + } + + dsa_free(&key); + return CRYPT_OK; +} + +int dsa_test(void) +{ + unsigned char msg[16], out[1024], out2[1024], ch; + unsigned long x, y; + int stat1, stat2; + dsa_key key, key2; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(s_dsa_compat_test()); + DO(s_dsa_wycheproof_test()); + + /* make a random key */ + DO(dsa_generate_pqg(&yarrow_prng, find_prng("yarrow"), 20, 128, &key)); + DO(dsa_generate_key(&yarrow_prng, find_prng("yarrow"), &key)); + + /* verify it */ + DO(dsa_verify_key(&key, &stat1)); + if (stat1 == 0) { fprintf(stderr, "dsa_verify_key "); return 1; } + + /* encrypt a message */ + for (ch = 0; ch < 16; ch++) { msg[ch] = ch; } + x = sizeof(out); + DO(dsa_encrypt_key(msg, 16, out, &x, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), &key)); + + /* decrypt */ + y = sizeof(out2); + DO(dsa_decrypt_key(out, x, out2, &y, &key)); + + if (y != 16 || memcmp(out2, msg, 16)) { + fprintf(stderr, "dsa_decrypt failed, y == %lu\n", y); + return 1; + } + + /* sign the message */ + x = sizeof(out); + DO(dsa_sign_hash(msg, sizeof(msg), out, &x, &yarrow_prng, find_prng("yarrow"), &key)); + + /* verify it once */ + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key)); + + /* Modify and verify again */ + msg[0] ^= 1; + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key)); + msg[0] ^= 1; + if (!(stat1 == 1 && stat2 == 0)) { fprintf(stderr, "dsa_verify %d %d", stat1, stat2); return 1; } + + /* test exporting it */ + y = sizeof(out2); + DO(dsa_export(out2, &y, PK_PRIVATE, &key)); + DO(dsa_import(out2, y, &key2)); + + /* verify a signature with it */ + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)); + if (stat1 == 0) { fprintf(stderr, "dsa_verify (import private) %d ", stat1); return 1; } + dsa_free(&key2); + + /* export as public now */ + y = sizeof(out2); + DO(dsa_export(out2, &y, PK_PUBLIC, &key)); + + DO(dsa_import(out2, y, &key2)); + /* verify a signature with it */ + DO(dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)); + if (stat1 == 0) { fprintf(stderr, "dsa_verify (import public) %d ", stat1); return 1; } + dsa_free(&key2); + dsa_free(&key); + + return 0; +} + +#else + +int dsa_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/deps/libtomcrypt/tests/ecc_test.c b/deps/libtomcrypt/tests/ecc_test.c new file mode 100644 index 0000000..faa3104 --- /dev/null +++ b/deps/libtomcrypt/tests/ecc_test.c @@ -0,0 +1,1601 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_MECC) + +static unsigned int sizes[] = { +#ifdef LTC_ECC_SECP112R1 +14, +#endif +#ifdef LTC_ECC_SECP128R1 +16, +#endif +#ifdef LTC_ECC_SECP160R1 +20, +#endif +#ifdef LTC_ECC_SECP192R1 +24, +#endif +#ifdef LTC_ECC_SECP224R1 +28, +#endif +#ifdef LTC_ECC_SECP256R1 +32, +#endif +#ifdef LTC_ECC_SECP384R1 +48, +#endif +#ifdef LTC_ECC_SECP512R1 +66 +#endif +}; + +static const char* curvenames[] = { +#ifdef LTC_ECC_SECP112R1 + "SECP112R1", "ECC-112", + "secp112r1", /* name is case-insensitive */ + "S E C-P-1_1_2r1", /* should pass fuzzy matching */ +#endif +#ifdef LTC_ECC_SECP112R2 + "SECP112R2", +#endif +#ifdef LTC_ECC_SECP128R1 + "SECP128R1", "ECC-128", +#endif +#ifdef LTC_ECC_SECP128R2 + "SECP128R2", +#endif +#ifdef LTC_ECC_SECP160R1 + "SECP160R1", "ECC-160", +#endif +#ifdef LTC_ECC_SECP160R2 + "SECP160R2", +#endif +#ifdef LTC_ECC_SECP160K1 + "SECP160K1", +#endif +#ifdef LTC_ECC_BRAINPOOLP160R1 + "BRAINPOOLP160R1", +#endif +#ifdef LTC_ECC_SECP192R1 + "SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192", +#endif +#ifdef LTC_ECC_PRIME192V2 + "PRIME192V2", +#endif +#ifdef LTC_ECC_PRIME192V3 + "PRIME192V3", +#endif +#ifdef LTC_ECC_SECP192K1 + "SECP192K1", +#endif +#ifdef LTC_ECC_BRAINPOOLP192R1 + "BRAINPOOLP192R1", +#endif +#ifdef LTC_ECC_SECP224R1 + "SECP224R1", "NISTP224", "ECC-224", "P-224", +#endif +#ifdef LTC_ECC_SECP224K1 + "SECP224K1", +#endif +#ifdef LTC_ECC_BRAINPOOLP224R1 + "BRAINPOOLP224R1", +#endif +#ifdef LTC_ECC_PRIME239V1 + "PRIME239V1", +#endif +#ifdef LTC_ECC_PRIME239V2 + "PRIME239V2", +#endif +#ifdef LTC_ECC_PRIME239V3 + "PRIME239V3", +#endif +#ifdef LTC_ECC_SECP256R1 + "SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256", +#endif +#ifdef LTC_ECC_SECP256K1 + "SECP256K1", +#endif +#ifdef LTC_ECC_BRAINPOOLP256R1 + "BRAINPOOLP256R1", +#endif +#ifdef LTC_ECC_BRAINPOOLP320R1 + "BRAINPOOLP320R1", +#endif +#ifdef LTC_ECC_SECP384R1 + "SECP384R1", "NISTP384", "ECC-384", "P-384", +#endif +#ifdef LTC_ECC_BRAINPOOLP384R1 + "BRAINPOOLP384R1", +#endif +#ifdef LTC_ECC_BRAINPOOLP512R1 + "BRAINPOOLP512R1", +#endif +#ifdef LTC_ECC_SECP521R1 + "SECP521R1", "NISTP521", "ECC-521", "P-521", +#endif +}; + + +#ifdef LTC_ECC_SHAMIR +static int s_ecc_test_shamir(void) +{ + void *a, *modulus, *mp, *kA, *kB, *rA, *rB; + void *mu, *ma; + ecc_point *G, *A, *B, *C1, *C2; + int x, y, z; + unsigned char buf[ECC_BUF_SIZE]; + + DO(mp_init_multi(&kA, &kB, &rA, &rB, &modulus, &a, &mu, &ma, LTC_NULL)); + LTC_ARGCHK((G = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((A = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((B = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((C1 = ltc_ecc_new_point()) != NULL); + LTC_ARGCHK((C2 = ltc_ecc_new_point()) != NULL); + + for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) { + /* get the base point */ + for (z = 0; ltc_ecc_curves[z].prime != NULL; z++) { + DO(mp_read_radix(modulus, ltc_ecc_curves[z].prime, 16)); + if (sizes[x] <= mp_unsigned_bin_size(modulus)) break; + } + LTC_ARGCHK(ltc_ecc_curves[z].prime != NULL); + + /* load it */ + DO(mp_read_radix(G->x, ltc_ecc_curves[z].Gx, 16)); + DO(mp_read_radix(G->y, ltc_ecc_curves[z].Gy, 16)); + DO(mp_set(G->z, 1)); + DO(mp_read_radix(a, ltc_ecc_curves[z].A, 16)); + DO(mp_montgomery_setup(modulus, &mp)); + DO(mp_montgomery_normalization(mu, modulus)); + DO(mp_mulmod(a, mu, modulus, ma)); + + /* do 100 random tests */ + for (y = 0; y < 100; y++) { + /* pick a random r1, r2 */ + ENSURE(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(rA, buf, sizes[x])); + ENSURE(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(rB, buf, sizes[x])); + + /* compute rA * G = A */ + DO(ltc_mp.ecc_ptmul(rA, G, A, a, modulus, 1)); + + /* compute rB * G = B */ + DO(ltc_mp.ecc_ptmul(rB, G, B, a, modulus, 1)); + + /* pick a random kA, kB */ + ENSURE(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(kA, buf, sizes[x])); + ENSURE(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]); + DO(mp_read_unsigned_bin(kB, buf, sizes[x])); + + /* now, compute kA*A + kB*B = C1 using the older method */ + DO(ltc_mp.ecc_ptmul(kA, A, C1, a, modulus, 0)); + DO(ltc_mp.ecc_ptmul(kB, B, C2, a, modulus, 0)); + DO(ltc_mp.ecc_ptadd(C1, C2, C1, a, modulus, mp)); + DO(ltc_mp.ecc_map(C1, modulus, mp)); + + /* now compute using mul2add */ + DO(ltc_mp.ecc_mul2add(A, kA, B, kB, C2, ma, modulus)); + + /* is they the sames? */ + if ((mp_cmp(C1->x, C2->x) != LTC_MP_EQ) || (mp_cmp(C1->y, C2->y) != LTC_MP_EQ) || (mp_cmp(C1->z, C2->z) != LTC_MP_EQ)) { + fprintf(stderr, "ECC failed shamir test: size=%d, testno=%d\n", sizes[x], y); + return 1; + } + } + mp_montgomery_free(mp); + } + ltc_ecc_del_point(C2); + ltc_ecc_del_point(C1); + ltc_ecc_del_point(B); + ltc_ecc_del_point(A); + ltc_ecc_del_point(G); + mp_clear_multi(kA, kB, rA, rB, modulus, a, mu, ma, LTC_NULL); + return 0; +} +#endif + +/* https://github.com/libtom/libtomcrypt/issues/108 */ +static int s_ecc_issue108(void) +{ + void *a, *modulus, *order; + ecc_point *Q, *Result; + int err; + const ltc_ecc_curve* dp; + + /* init */ + if ((err = mp_init_multi(&modulus, &order, &a, LTC_NULL)) != CRYPT_OK) { return err; } + Q = ltc_ecc_new_point(); + Result = ltc_ecc_new_point(); + + /* ECC-224 AKA SECP224R1 */ + if ((err = ecc_find_curve("SECP224R1", &dp)) != CRYPT_OK) { goto done; } + /* read A */ + if ((err = mp_read_radix(a, (char *)dp->A, 16)) != CRYPT_OK) { goto done; } + /* read modulus */ + if ((err = mp_read_radix(modulus, (char *)dp->prime, 16)) != CRYPT_OK) { goto done; } + /* read order */ + if ((err = mp_read_radix(order, (char *)dp->order, 16)) != CRYPT_OK) { goto done; } + /* read Q */ + if ((err = mp_read_radix(Q->x, (char *)"EA3745501BBC6A70BBFDD8AEEDB18CF5073C6DC9AA7CBB5915170D60", 16)) != CRYPT_OK) { goto done; } + if ((err = mp_read_radix(Q->y, (char *)"6C9CB8E68AABFEC989CAC5E2326E0448B7E69C3E56039BA21A44FDAC", 16)) != CRYPT_OK) { goto done; } + mp_set(Q->z, 1); + /* calculate nQ */ + if ((err = ltc_mp.ecc_ptmul(order, Q, Result, a, modulus, 1)) != CRYPT_OK) { goto done; } + +done: + ltc_ecc_del_point(Result); + ltc_ecc_del_point(Q); + mp_clear_multi(modulus, order, a, LTC_NULL); + return err; +} + +/* https://github.com/libtom/libtomcrypt/issues/443 */ +/* https://github.com/libtom/libtomcrypt/issues/447 */ +static int s_ecc_issue443_447(void) +{ + const ltc_ecc_curve* cu; + ecc_key key; + int err, stat = 0; + unsigned char hash[64]; + unsigned long hashlen; + const unsigned char msg[] = { 0x54,0x65,0x73,0x74 }; + /* msg+pub1+sig1 test vector is from wycheproof - ecdsa_webcrypto_test (incorrect size of signature) */ + const unsigned char pub1[] = { + 0x04, + 0x4a,0x03,0xef,0x9f,0x92,0xeb,0x26,0x8c,0xaf,0xa6,0x01,0x07,0x24,0x89,0xa5,0x63, + 0x80,0xfa,0x0d,0xc4,0x31,0x71,0xd7,0x71,0x28,0x13,0xb3,0xa1,0x9a,0x1e,0xb5,0xe5, + 0x3e,0x21,0x3e,0x28,0xa6,0x08,0xce,0x9a,0x2f,0x4a,0x17,0xfd,0x83,0x0c,0x66,0x54, + 0x01,0x8a,0x79,0xb3,0xe0,0x26,0x3d,0x91,0xa8,0xba,0x90,0x62,0x2d,0xf6,0xf2,0xf0 + }; + const unsigned char sig1[] = { 0x05, 0x01 }; + /* msg+pub2+sig2 test vector is from wycheproof - ecdsa_webcrypto_test (incorrect size of signature) */ + const unsigned char pub2[] = { + 0x04, + 0x00,0x5f,0x50,0x59,0x30,0x83,0x49,0xf9,0xeb,0xbb,0x4d,0x1c,0x55,0xc0,0xaf,0xcc,0xf6,0x21,0x62,0xec,0x1d,0xd1, + 0x2e,0xf3,0xed,0x90,0x66,0x56,0x92,0x4f,0xfd,0x99,0xca,0xb9,0xf0,0x6b,0x0e,0xb2,0x18,0xcf,0xf0,0x78,0xa4,0x67, + 0x7a,0x5c,0xe1,0xcc,0x07,0x65,0x2b,0xc9,0x76,0xae,0xfc,0x73,0x2c,0x28,0xf6,0x7e,0xf0,0x78,0xa4,0x34,0xe9,0x99, + 0x00,0xa5,0xd1,0x4d,0xf3,0x10,0x63,0x0d,0x76,0xec,0x03,0xcb,0x6f,0x9b,0x95,0xbf,0x1a,0x22,0x43,0x81,0x05,0xc8, + 0x8c,0xd9,0xfd,0x3d,0xac,0x80,0xf8,0x57,0xad,0xd3,0x82,0x71,0xd8,0xba,0x90,0x16,0x84,0xb2,0x6d,0x43,0x6d,0x4a, + 0x85,0x9a,0xd4,0xcd,0xa5,0xe9,0x67,0x7b,0x73,0xca,0xb3,0xf3,0xe5,0xe4,0x1a,0x3d,0x79,0x96,0x60,0x72,0x79,0xab + }; + const unsigned char sig2[] = { 0x01, 0x01 }; + + hashlen = sizeof(hash); + DO(hash_memory(find_hash("sha256"), msg, sizeof(msg), hash, &hashlen)); + DO(ecc_find_curve("secp256r1", &cu)); + DO(ecc_set_curve(cu, &key)); + DO(ecc_set_key(pub1, sizeof(pub1), PK_PUBLIC, &key)); + err = ecc_verify_hash_rfc7518(sig1, sizeof(sig1), hash, hashlen, &stat, &key); /* should fail */ + ecc_free(&key); + if (err != CRYPT_INVALID_PACKET) return CRYPT_FAIL_TESTVECTOR; + + hashlen = sizeof(hash); + DO(hash_memory(find_hash("sha512"), msg, sizeof(msg), hash, &hashlen)); + DO(ecc_find_curve("secp521r1", &cu)); + DO(ecc_set_curve(cu, &key)); + DO(ecc_set_key(pub2, sizeof(pub2), PK_PUBLIC, &key)); + err = ecc_verify_hash_rfc7518(sig2, sizeof(sig2), hash, hashlen, &stat, &key); /* should fail */ + ecc_free(&key); + if (err != CRYPT_INVALID_PACKET) return CRYPT_FAIL_TESTVECTOR; + + return CRYPT_OK; +} + +static int s_ecc_test_mp(void) +{ + void *a, *modulus, *order; + ecc_point *G, *GG; + int i, err, primality; + char buf[4096]; + + DO(mp_init_multi(&modulus, &order, &a, LTC_NULL)); + + G = ltc_ecc_new_point(); + GG = ltc_ecc_new_point(); + if (G == NULL || GG == NULL) { + mp_clear_multi(modulus, order, LTC_NULL); + ltc_ecc_del_point(G); + ltc_ecc_del_point(GG); + return CRYPT_MEM; + } + + err = CRYPT_OK; + + for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) { + DO(mp_read_radix(a, (char *)ltc_ecc_curves[i].A, 16)); + DO(mp_read_radix(modulus, (char *)ltc_ecc_curves[i].prime, 16)); + DO(mp_read_radix(order, (char *)ltc_ecc_curves[i].order, 16)); + + /* is prime actually prime? */ + DO(mp_prime_is_prime(modulus, 8, &primality)); + if (primality == 0) { + err = CRYPT_FAIL_TESTVECTOR; + mp_tohex(modulus, buf); + printf("Modulus failed prime check: %s\n", buf); + } + + /* is order prime ? */ + DO(mp_prime_is_prime(order, 8, &primality)); + if (primality == 0) { + err = CRYPT_FAIL_TESTVECTOR; + mp_tohex(order, buf); + printf("Order failed prime check: %s\n", buf); + } + + DO(mp_read_radix(G->x, (char *)ltc_ecc_curves[i].Gx, 16)); + DO(mp_read_radix(G->y, (char *)ltc_ecc_curves[i].Gy, 16)); + mp_set(G->z, 1); + + /* then we should have G == (order + 1)G */ + DO(mp_add_d(order, 1, order)); + DO(ltc_mp.ecc_ptmul(order, G, GG, a, modulus, 1)); + if (mp_cmp(G->x, GG->x) != LTC_MP_EQ || mp_cmp(G->y, GG->y) != LTC_MP_EQ) { + err = CRYPT_FAIL_TESTVECTOR; + } + if (err != CRYPT_OK) { + goto done; + } + } + err = CRYPT_OK; +done: + ltc_ecc_del_point(GG); + ltc_ecc_del_point(G); + mp_clear_multi(order, modulus, a, LTC_NULL); + return err; +} + +static int s_ecc_old_api(void) +{ + unsigned char buf[4][4096], ch; + unsigned long x, y, z, s; + int stat, stat2; + ecc_key usera, userb, pubKey, privKey; + int low, high; + + ecc_sizes(&low, &high); + if (low < 14 || high < 14 || low > 100 || high > 100 || high < low) return CRYPT_FAIL_TESTVECTOR; + + for (s = 0; s < (sizeof(sizes)/sizeof(sizes[0])); s++) { + /* make up two keys */ + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &userb)); + if (ecc_get_size(&usera) != (int)sizes[s]) return CRYPT_FAIL_TESTVECTOR; + if (ecc_get_size(&userb) != (int)sizes[s]) return CRYPT_FAIL_TESTVECTOR; + + /* make the shared secret */ + x = sizeof(buf[0]); + DO(ecc_shared_secret (&usera, &userb, buf[0], &x)); + + y = sizeof(buf[1]); + DO(ecc_shared_secret (&userb, &usera, buf[1], &y)); + + DO(do_compare_testvector(buf[0], x, buf[1], y, "ecc Shared keys", s)); + + /* now export userb */ + y = sizeof(buf[0]); + DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb)); + ecc_free (&userb); + + /* import and make the shared secret again */ + DO(ecc_import (buf[1], y, &userb)); + + z = sizeof(buf[0]); + DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); + + if (z != x) { + fprintf(stderr, "failed. Size don't match?"); + return 1; + } + if (memcmp (buf[0], buf[2], x)) { + fprintf(stderr, "Failed. Contents didn't match."); + return 1; + } + + /* export with ANSI X9.63 */ + y = sizeof(buf[1]); + DO(ecc_ansi_x963_export(&userb, buf[1], &y)); + ecc_free (&userb); + + /* now import the ANSI key */ + DO(ecc_ansi_x963_import(buf[1], y, &userb)); + + /* shared secret */ + z = sizeof(buf[0]); + DO(ecc_shared_secret (&usera, &userb, buf[2], &z)); + + if (z != x) { + fprintf(stderr, "failed. Size don't match?"); + return 1; + } + if (memcmp (buf[0], buf[2], x)) { + fprintf(stderr, "Failed. Contents didn't match."); + return 1; + } + + ecc_free (&usera); + ecc_free (&userb); + + /* test encrypt_key */ + DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera)); + + /* export key */ + x = sizeof(buf[0]); + DO(ecc_export(buf[0], &x, PK_PUBLIC, &usera)); + DO(ecc_import(buf[0], x, &pubKey)); + x = sizeof(buf[0]); + DO(ecc_export(buf[0], &x, PK_PRIVATE, &usera)); + DO(ecc_import(buf[0], x, &privKey)); + + for (ch = 0; ch < 32; ch++) { + buf[0][ch] = ch; + } + y = sizeof (buf[1]); + DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("sha256"), &pubKey)); + zeromem (buf[0], sizeof (buf[0])); + x = sizeof (buf[0]); + DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &privKey)); + if (x != 32) { + fprintf(stderr, "Failed (length)"); + return 1; + } + for (ch = 0; ch < 32; ch++) { + if (buf[0][ch] != ch) { + fprintf(stderr, "Failed (contents)"); + return 1; + } + } + /* test sign_hash */ + for (ch = 0; ch < 16; ch++) { + buf[0][ch] = ch; + } + x = sizeof (buf[1]); + DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); + DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey)); + buf[0][0] ^= 1; + DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey)); + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "ecc_verify_hash failed %d, %d, ", stat, stat2); + return 1; + } + /* test sign_hash_rfc7518 */ + for (ch = 0; ch < 16; ch++) { + buf[0][ch] = ch; + } + x = sizeof (buf[1]); + DO(ecc_sign_hash_rfc7518(buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); + DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat, &pubKey)); + buf[0][0] ^= 1; + DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat2, &privKey)); + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "ecc_verify_hash_rfc7518 failed %d, %d, ", stat, stat2); + return 1; + } + ecc_free (&usera); + ecc_free (&pubKey); + ecc_free (&privKey); + } + return CRYPT_OK; +} + +static int s_ecc_key_cmp(const int should_type, const ecc_key *should, const ecc_key *is) +{ + if (should_type != is->type) return CRYPT_ERROR; + if (should_type == PK_PRIVATE) { + if (mp_cmp(should->k, is->k) != LTC_MP_EQ) return CRYPT_ERROR; + } + if (mp_cmp(should->dp.prime, is->dp.prime) != LTC_MP_EQ) return CRYPT_ERROR; + if (mp_cmp(should->dp.A, is->dp.A) != LTC_MP_EQ) return CRYPT_ERROR; + if (mp_cmp(should->dp.B, is->dp.B) != LTC_MP_EQ) return CRYPT_ERROR; + if (mp_cmp(should->dp.order, is->dp.order) != LTC_MP_EQ) return CRYPT_ERROR; + if (mp_cmp(should->dp.base.x, is->dp.base.x) != LTC_MP_EQ) return CRYPT_ERROR; + if (mp_cmp(should->dp.base.y, is->dp.base.y) != LTC_MP_EQ) return CRYPT_ERROR; + if (mp_cmp(should->pubkey.x, is->pubkey.x) != LTC_MP_EQ) return CRYPT_ERROR; + if (mp_cmp(should->pubkey.y, is->pubkey.y) != LTC_MP_EQ) return CRYPT_ERROR; + if (should->dp.size != is->dp.size) return CRYPT_ERROR; + if (should->dp.cofactor != is->dp.cofactor) return CRYPT_ERROR; + return CRYPT_OK; +} + +static int s_ecc_new_api(void) +{ + int i, j, stat; + const ltc_ecc_curve* dp; + ecc_key key, privkey, pubkey; + unsigned char buf[1000]; + unsigned long len; + unsigned char data16[16] = { 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 }; + unsigned long len16; + + for (i = 0; i < (int)(sizeof(curvenames)/sizeof(curvenames[0])); i++) { + DO(ecc_find_curve(curvenames[i], &dp)); + /* make new key */ + DO(ecc_make_key_ex(&yarrow_prng, find_prng ("yarrow"), &key, dp)); + len = sizeof(buf); + DO(ecc_export(buf, &len, PK_PRIVATE, &key)); + DO(ecc_import_ex(buf, len, &privkey, dp)); + ecc_free(&privkey); + len = sizeof(buf); + DO(ecc_export(buf, &len, PK_PUBLIC, &key)); + DO(ecc_import_ex(buf, len, &pubkey, dp)); + ecc_free(&pubkey); + len = sizeof(buf); + DO(ecc_ansi_x963_export(&key, buf, &len)); + ecc_free(&key); + DO(ecc_ansi_x963_import_ex(buf, len, &pubkey, dp)); + ecc_free(&pubkey); + + /* generate new key */ + DO(ecc_set_curve(dp, &key)); + DO(ecc_generate_key(&yarrow_prng, find_prng ("yarrow"), &key)); + len = sizeof(buf); + DO(ecc_get_key(buf, &len, PK_PRIVATE, &key)); + ecc_free(&key); + + /* load exported private key */ + DO(ecc_set_curve(dp, &privkey)); + DO(ecc_set_key(buf, len, PK_PRIVATE, &privkey)); + + if (strcmp(ltc_mp.name, "TomsFastMath") != 0) { + /* XXX-FIXME: TFM does not support sqrtmod_prime */ + /* export compressed public key */ + len = sizeof(buf); + DO(ecc_get_key(buf, &len, PK_PUBLIC|PK_COMPRESSED, &privkey)); + if (len != 1 + (unsigned)ecc_get_size(&privkey)) return CRYPT_FAIL_TESTVECTOR; + /* load exported public+compressed key */ + DO(ecc_set_curve(dp, &pubkey)); + DO(ecc_set_key(buf, len, PK_PUBLIC, &pubkey)); + ecc_free(&pubkey); + } + + /* export long public key */ + len = sizeof(buf); + DO(ecc_get_key(buf, &len, PK_PUBLIC, &privkey)); + if (len != 1 + 2 * (unsigned)ecc_get_size(&privkey)) return CRYPT_FAIL_TESTVECTOR; + /* load exported public key */ + DO(ecc_set_curve(dp, &pubkey)); + DO(ecc_set_key(buf, len, PK_PUBLIC, &pubkey)); + + /* test signature */ + len = sizeof(buf); + DO(ecc_sign_hash(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &privkey)); + stat = 0; + DO(ecc_verify_hash(buf, len, data16, 16, &stat, &pubkey)); + if (stat != 1) return CRYPT_FAIL_TESTVECTOR; + +#ifdef LTC_SSH + /* test SSH+ECDSA/RFC5656 signature */ + len = sizeof(buf); + DO(ecc_sign_hash_ex(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), + LTC_ECCSIG_RFC5656, NULL, &privkey)); + stat = 0; + DO(ecc_verify_hash_ex(buf, len, data16, 16, LTC_ECCSIG_RFC5656, &stat, &pubkey)); + if (stat != 1) return CRYPT_FAIL_TESTVECTOR; +#endif + +#ifdef LTC_ECC_SHAMIR + if (strcmp(ltc_mp.name, "TomsFastMath") != 0) { + /* XXX-FIXME: TFM does not support sqrtmod_prime */ + int found = 0; + ecc_key reckey; + /* test recovery */ + len = sizeof(buf); + DO(ecc_sign_hash(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &privkey)); + DO(ecc_set_curve(dp, &reckey)); + for (j = 0; j < 2*(1+(int)privkey.dp.cofactor); j++) { + stat = ecc_recover_key(buf, len, data16, 16, j, LTC_ECCSIG_ANSIX962, &reckey); + if (stat != CRYPT_OK) continue; /* last two will almost always fail, only possible if x<(prime mod order) */ + stat = s_ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey); + if (stat == CRYPT_OK) found++; + } + if (found != 1) return CRYPT_FAIL_TESTVECTOR; /* unique match */ + ecc_free(&reckey); + } +#endif + + /* test encryption */ + len = sizeof(buf); + DO(ecc_encrypt_key(data16, 16, buf, &len, &yarrow_prng, find_prng("yarrow"), find_hash("sha256"), &pubkey)); + zeromem(data16, 16); + len16 = 16; + DO(ecc_decrypt_key(buf, len, data16, &len16, &privkey)); + if (len16 != 16) return CRYPT_FAIL_TESTVECTOR; + for (j = 0; j < 16; j++) if (data16[j] != 0xd1) return CRYPT_FAIL_TESTVECTOR; + + /* cleanup */ + ecc_free(&privkey); + ecc_free(&pubkey); + } + return CRYPT_OK; +} + +static int s_ecc_import_export(void) { + const ltc_ecc_curve *cu; + ecc_key key, pri, pub; + unsigned char out[300]; + unsigned long outlen; + + /* the following test keys were generated by: + # no password + openssl ecparam -name secp256k1 -genkey -out main-key.pem + openssl ec -in main-key.pem -param_enc explicit -out long_pri.der -outform DER + openssl ec -in main-key.pem -param_enc explicit -conv_form compressed -out long_pric.der -outform DER + openssl ec -in main-key.pem -param_enc explicit -pubout -out long_pub.der -outform DER + openssl ec -in main-key.pem -param_enc explicit -pubout -conv_form compressed -out long_pubc.der -outform DER + openssl ec -in main-key.pem -param_enc named_curve -out short_pri.der -outform DER + openssl ec -in main-key.pem -param_enc named_curve -conv_form compressed -out short_pric.der -outform DER + openssl ec -in main-key.pem -param_enc named_curve -pubout -out short_pub.der -outform DER + openssl ec -in main-key.pem -param_enc named_curve -pubout -conv_form compressed -out short_pubc.der -outform DER + # X.509 EC certificates + openssl req -new -x509 -keyform der -key long_pri.der -sha512 -subj '/CN=Test Cert EC' -out x509_cert_long.der -outform der -days 365000 + openssl req -new -x509 -keyform der -key long_pric.der -sha512 -subj '/CN=Test Cert EC' -out x509_cert_longc.der -outform der -days 365000 + openssl req -new -x509 -keyform der -key short_pri.der -sha512 -subj '/CN=Test Cert EC' -out x509_cert_short.der -outform der -days 365000 + openssl req -new -x509 -keyform der -key short_pric.der -sha512 -subj '/CN=Test Cert EC' -out x509_cert_shortc.der -outform der -days 365000 + # pkcs8 without password + openssl pkcs8 -topk8 -inform DER -outform DER -nocrypt -in long_pri.der -out long_pri_pkcs8.der + openssl pkcs8 -topk8 -inform DER -outform DER -nocrypt -in long_pric.der -out long_pric_pkcs8.der + openssl pkcs8 -topk8 -inform DER -outform DER -nocrypt -in short_pri.der -out short_pri_pkcs8.der + openssl pkcs8 -topk8 -inform DER -outform DER -nocrypt -in short_pric.der -out short_pric_pkcs8.der + # password protected - PBES1 + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v1 PBE-MD2-DES -out long_pri_pkcs8_pbe_md2_des.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v1 PBE-MD2-RC2-64 -out long_pri_pkcs8_pbe_md2_rc2_64.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v1 PBE-MD5-DES -out long_pri_pkcs8_pbe_md5_des.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v1 PBE-SHA1-RC2-64 -out long_pri_pkcs8_pbe_sha1_rc2_64.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v1 PBE-MD5-RC2-64 -out long_pri_pkcs8_pbe_md5_rc2_64.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v1 PBE-SHA1-DES -out long_pri_pkcs8_pbe_sha1_des.der + # password protected - PBES2 + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v2 rc2 -out long_pri_pkcs8_pbkdf2_rc2_cbc.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v2 des -out long_pri_pkcs8_pbkdf2_des_cbc.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v2 des3 -out long_pri_pkcs8_pbkdf2_des_ede3_cbc.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v2 des3 -v2prf hmacWithSHA224 -out long_pri_pkcs8_pbkdf2_sha224_des_ede3_cbc.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v2 des3 -v2prf hmacWithSHA256 -out long_pri_pkcs8_pbkdf2_sha256_des_ede3_cbc.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v2 des3 -v2prf hmacWithSHA384 -out long_pri_pkcs8_pbkdf2_sha384_des_ede3_cbc.der + openssl pkcs8 -topk8 -inform DER -outform DER -passout pass:secret -in long_pri.der -v2 des3 -v2prf hmacWithSHA512 -out long_pri_pkcs8_pbkdf2_sha512_des_ede3_cbc.der + */ + static const unsigned char long_pri[] = { /* private + long public, explicit curve params */ + 0x30, 0x82, 0x01, 0x13, 0x02, 0x01, 0x01, 0x04, 0x20, 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, + 0x1b, 0xba, 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, 0xf7, 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, + 0x9f, 0x5f, 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, 0x23, 0xa0, 0x81, 0xa5, 0x30, 0x81, 0xa2, 0x02, + 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, + 0x30, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, 0x07, 0x04, 0x41, 0x04, 0x79, 0xbe, 0x66, 0x7e, 0xf9, + 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, + 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, 0xda, 0x77, 0x26, + 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, + 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, 0x02, 0x21, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, + 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, 0x02, 0x01, + 0x01, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, + 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, + 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, 0xb7, + 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, 0x6e, + 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d + }; + static const unsigned char long_pri_pkcs8[] = { /* private + long public, explicit curve params, PKCS8 */ + 0x30, 0x82, 0x01, 0x23, 0x02, 0x01, 0x00, 0x30, 0x81, 0xae, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x02, 0x01, 0x30, 0x81, 0xa2, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, 0x07, 0x04, + 0x41, 0x04, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, + 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, + 0x17, 0x98, 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, + 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, + 0xd4, 0xb8, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, + 0x8c, 0xd0, 0x36, 0x41, 0x41, 0x02, 0x01, 0x01, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, + 0x20, 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, 0xba, 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, + 0xf7, 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, 0x5f, 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, + 0x23, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, + 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, + 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, 0xb7, + 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, 0x6e, + 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d + }; +#if defined(LTC_MD2) && defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbe_md2_des[] = { + 0x30, 0x82, 0x01, 0x49, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x01, 0x30, 0x0e, 0x04, 0x08, 0xd8, 0x1c, 0x80, 0xac, 0xd9, 0xfa, 0x9d, 0xbc, 0x02, 0x02, 0x08, + 0x00, 0x04, 0x82, 0x01, 0x28, 0xe1, 0xd5, 0xa8, 0x9a, 0xa8, 0x23, 0x85, 0x53, 0x18, 0xb3, 0x96, + 0x67, 0x8d, 0x45, 0x72, 0xf8, 0x69, 0xc4, 0xb1, 0x01, 0x3e, 0x04, 0xf7, 0xf7, 0x5d, 0x07, 0xad, + 0xec, 0x8e, 0xd6, 0x23, 0x00, 0xe7, 0x59, 0xb0, 0x98, 0xbb, 0xdb, 0x85, 0xdb, 0x59, 0x4d, 0xb5, + 0x53, 0xb3, 0x32, 0x50, 0x66, 0x75, 0xc4, 0x69, 0x05, 0x07, 0xee, 0xd4, 0xd8, 0x33, 0xcd, 0x4c, + 0x94, 0xad, 0x82, 0xc7, 0x89, 0x53, 0x65, 0x9f, 0x55, 0x44, 0x95, 0x20, 0xe8, 0x4a, 0xc2, 0xef, + 0x41, 0xf2, 0x9d, 0xf8, 0x3d, 0x16, 0x8a, 0x6a, 0x4e, 0x85, 0x90, 0xa7, 0xf9, 0xf8, 0xac, 0x16, + 0x76, 0xf2, 0x29, 0x4b, 0x93, 0xec, 0xd8, 0x17, 0x3f, 0x89, 0x84, 0x79, 0x75, 0x90, 0x5f, 0xc3, + 0xf2, 0xb8, 0x1a, 0x0a, 0x25, 0xf4, 0xe2, 0x59, 0xe0, 0xea, 0xa6, 0x57, 0xc4, 0x9c, 0xce, 0xfd, + 0xa8, 0xbc, 0xf6, 0x0d, 0x3a, 0x47, 0x14, 0x9d, 0x6a, 0x92, 0x77, 0xe4, 0xcb, 0x88, 0x6e, 0xfa, + 0x19, 0xa4, 0x3d, 0x58, 0xdb, 0x5f, 0xc7, 0xad, 0x91, 0x64, 0xb0, 0x1f, 0xe2, 0x66, 0xc5, 0x5a, + 0x28, 0x21, 0xb0, 0xc1, 0xc8, 0x73, 0x55, 0xd8, 0x43, 0x66, 0x6a, 0x5c, 0xcd, 0xb0, 0x89, 0x60, + 0x59, 0x31, 0xe0, 0x2f, 0x20, 0x3b, 0x83, 0xdf, 0x27, 0xcf, 0x33, 0xcc, 0xb9, 0xb6, 0xe0, 0xec, + 0x8b, 0x94, 0x4b, 0xc4, 0x1c, 0x25, 0xba, 0x97, 0x6c, 0x83, 0x22, 0x8c, 0xca, 0x9d, 0xc6, 0xaa, + 0x74, 0x3f, 0x46, 0xdc, 0xba, 0x7a, 0x36, 0x04, 0xa7, 0xc8, 0x65, 0xb4, 0xf7, 0x14, 0x53, 0x8c, + 0xff, 0x4d, 0x19, 0xc1, 0xdb, 0xa4, 0xcc, 0x52, 0xc2, 0xd9, 0x38, 0x16, 0x8f, 0xd8, 0x6e, 0x55, + 0x41, 0xa8, 0xe0, 0x15, 0xd6, 0x2d, 0xa4, 0x37, 0x9f, 0xcc, 0x42, 0x3c, 0xcb, 0xcc, 0x92, 0x04, + 0xc8, 0xcf, 0xbc, 0x60, 0xfb, 0x45, 0xff, 0x62, 0x74, 0xa1, 0xe9, 0xba, 0x1e, 0x5d, 0x44, 0x6f, + 0x0e, 0xac, 0xdf, 0xde, 0xb1, 0xbb, 0x47, 0x5e, 0x0c, 0x88, 0x0a, 0x85, 0x0b, 0xa8, 0x9e, 0xcb, + 0x32, 0x99, 0x8d, 0xb1, 0xdd, 0x12, 0x08, 0xeb, 0x7e, 0x45, 0x70, 0x12, 0xe3 + }; +#endif +#if defined(LTC_MD2) && defined(LTC_RC2) + static const unsigned char long_pri_pkcs8_pbe_md2_rc2_64[] = { + 0x30, 0x82, 0x01, 0x49, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x04, 0x30, 0x0e, 0x04, 0x08, 0xa2, 0x28, 0xb7, 0x2a, 0x08, 0x1c, 0x4a, 0xc4, 0x02, 0x02, 0x08, + 0x00, 0x04, 0x82, 0x01, 0x28, 0x78, 0x12, 0x02, 0x58, 0x9b, 0xea, 0x77, 0xba, 0x84, 0x20, 0x96, + 0x63, 0xf0, 0xf3, 0x38, 0x0b, 0x98, 0x53, 0x63, 0x8d, 0xa4, 0x5a, 0xa0, 0xa9, 0x21, 0x93, 0xd0, + 0x56, 0xc9, 0xd2, 0x67, 0xb2, 0x5e, 0xb5, 0x9f, 0x15, 0x8c, 0x3c, 0x9a, 0xaf, 0x9c, 0xe5, 0x8b, + 0xe6, 0x61, 0xac, 0xa4, 0x26, 0x75, 0x96, 0xea, 0x73, 0xaf, 0xd6, 0xb7, 0x4c, 0x66, 0x33, 0x98, + 0x9e, 0x0b, 0xf8, 0xe6, 0x9c, 0xfd, 0x83, 0x0f, 0x55, 0x86, 0x9f, 0xa9, 0xf0, 0x23, 0xcb, 0x80, + 0xe5, 0x32, 0x50, 0xea, 0x5b, 0x7d, 0xe2, 0x69, 0xc4, 0x6b, 0x61, 0xb2, 0xb8, 0x81, 0xe9, 0x05, + 0xcb, 0x76, 0xae, 0xa5, 0x37, 0x0f, 0x3c, 0xe6, 0xde, 0x24, 0x6a, 0x9c, 0xf2, 0x0a, 0x28, 0x6a, + 0xc9, 0xec, 0xef, 0xd7, 0xda, 0xcc, 0xf4, 0x3b, 0x74, 0x36, 0xc5, 0xaf, 0x53, 0xd8, 0xf4, 0x30, + 0x0b, 0xd4, 0xb6, 0x36, 0xdc, 0x90, 0x4f, 0x83, 0x44, 0x79, 0xea, 0xc9, 0xb7, 0xb2, 0xd0, 0x03, + 0xa6, 0x63, 0x7e, 0x1d, 0xa8, 0x4e, 0x93, 0x16, 0x7a, 0x4f, 0xd2, 0x8b, 0xd6, 0x78, 0x7d, 0x48, + 0x41, 0x7c, 0xba, 0xc3, 0x64, 0x6f, 0x11, 0x22, 0x6d, 0x40, 0xb8, 0xc9, 0x03, 0x7a, 0x2c, 0xdf, + 0x76, 0x78, 0x4f, 0x5f, 0x50, 0x03, 0x7a, 0xaf, 0x78, 0x91, 0xbb, 0x2a, 0xe6, 0x5e, 0x0f, 0xf5, + 0x60, 0x9e, 0x8a, 0x2f, 0xdb, 0x9e, 0x57, 0xbe, 0xf6, 0x0f, 0x76, 0x6e, 0x44, 0x91, 0x7b, 0x36, + 0x88, 0x9c, 0xf9, 0xbe, 0x13, 0x3e, 0x6b, 0x85, 0x62, 0xda, 0x1f, 0xf9, 0x73, 0x98, 0x8a, 0x0d, + 0xdf, 0x11, 0x74, 0x18, 0xe1, 0x1c, 0xd1, 0x3f, 0x02, 0x43, 0xd4, 0x46, 0xe3, 0x8a, 0x3b, 0x6c, + 0x7f, 0x81, 0xb4, 0xc3, 0x85, 0x4f, 0x89, 0x67, 0x26, 0x5a, 0x08, 0x35, 0x31, 0xd3, 0x15, 0xbb, + 0xcc, 0x7d, 0x7b, 0x99, 0x41, 0xdb, 0x43, 0xa0, 0x83, 0x84, 0x74, 0x6c, 0x0a, 0x80, 0x46, 0xdc, + 0xc8, 0x88, 0x87, 0x01, 0x21, 0x19, 0xd4, 0x1e, 0xf4, 0x09, 0x0e, 0x18, 0x31, 0x91, 0x37, 0x35, + 0x1d, 0x07, 0xaf, 0x87, 0x92, 0x3d, 0xf8, 0xee, 0x6f, 0x87, 0x7b, 0x52, 0x3d + }; +#endif +#if defined(LTC_MD5) && defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbe_md5_des[] = { + 0x30, 0x82, 0x01, 0x49, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x03, 0x30, 0x0e, 0x04, 0x08, 0x33, 0xe7, 0xd9, 0xf1, 0x35, 0xd9, 0x74, 0x83, 0x02, 0x02, 0x08, + 0x00, 0x04, 0x82, 0x01, 0x28, 0x2f, 0x77, 0x7c, 0x48, 0xc9, 0x43, 0x6d, 0xdb, 0xd0, 0x1a, 0xef, + 0xfb, 0x29, 0x5e, 0x53, 0xa3, 0x52, 0x28, 0x27, 0x76, 0xc2, 0x01, 0x76, 0x5a, 0xea, 0x98, 0xe6, + 0x72, 0xdf, 0x06, 0xa2, 0xf5, 0xd0, 0x7b, 0x74, 0xe4, 0x6b, 0x98, 0xa6, 0xb5, 0xe1, 0x02, 0xf7, + 0xab, 0x2c, 0xf1, 0xeb, 0xf4, 0xec, 0xa6, 0xba, 0xd3, 0xd5, 0xb2, 0x26, 0x83, 0xeb, 0xff, 0xc9, + 0xf8, 0x7b, 0xbf, 0xab, 0xdc, 0xe5, 0xe4, 0x91, 0xd5, 0x48, 0xba, 0x49, 0xcb, 0xc5, 0xf1, 0x71, + 0x48, 0x1e, 0x96, 0x7c, 0x10, 0xe4, 0xa9, 0x35, 0xa7, 0xe6, 0x82, 0x97, 0x6f, 0xe4, 0x64, 0xd4, + 0x53, 0xa9, 0xf1, 0x1b, 0x6c, 0x31, 0xa1, 0xc7, 0x12, 0x46, 0x45, 0x6f, 0x45, 0xb2, 0x09, 0x3a, + 0xfe, 0x35, 0x4e, 0xbf, 0x7d, 0xf8, 0xcf, 0x94, 0x78, 0x0c, 0x78, 0xfb, 0xce, 0xc1, 0x30, 0xcd, + 0x6d, 0x6b, 0x08, 0x5e, 0xf6, 0xf5, 0x97, 0xff, 0x5e, 0x63, 0x44, 0x36, 0xa5, 0x71, 0x04, 0xe5, + 0x2d, 0xd9, 0xe3, 0x41, 0x91, 0x09, 0x1e, 0xa3, 0x30, 0xff, 0x12, 0x2a, 0x7a, 0xe1, 0x8f, 0x9c, + 0x38, 0x13, 0x3d, 0xc3, 0xbb, 0x68, 0xfa, 0xc0, 0xc6, 0x35, 0x77, 0xed, 0xe8, 0x73, 0xca, 0xc3, + 0x87, 0x62, 0xa9, 0x0e, 0xef, 0xcf, 0x73, 0x3c, 0xb3, 0xa0, 0x1b, 0xb5, 0x5d, 0x72, 0x89, 0x82, + 0xd4, 0xf6, 0x37, 0x0b, 0x57, 0x8f, 0x48, 0xd4, 0xf1, 0x10, 0xa1, 0xe5, 0x25, 0x90, 0xeb, 0xde, + 0x8d, 0x2a, 0x9d, 0xfb, 0x7c, 0x0d, 0xdc, 0x38, 0x45, 0x9e, 0xa0, 0x05, 0x98, 0x4e, 0x72, 0x9f, + 0x3d, 0xde, 0xc7, 0x00, 0xf9, 0xaf, 0xdc, 0x67, 0x47, 0x73, 0xf7, 0xcf, 0x63, 0x80, 0xe3, 0x05, + 0xb3, 0xda, 0x9f, 0x4b, 0x27, 0xd3, 0x14, 0xc9, 0x62, 0xd5, 0x09, 0xde, 0x4d, 0xe7, 0x21, 0x67, + 0xfa, 0x10, 0x34, 0x18, 0xbf, 0xde, 0xf7, 0x95, 0x25, 0x6d, 0xba, 0xe4, 0x10, 0xf0, 0x9d, 0x05, + 0x7b, 0xe4, 0xb5, 0xc0, 0x21, 0xb3, 0x7d, 0xcd, 0x1d, 0x80, 0xd0, 0x10, 0xd4, 0xdb, 0x9f, 0x06, + 0xd5, 0x86, 0xea, 0x62, 0x96, 0xb7, 0x31, 0x73, 0xde, 0x25, 0xd0, 0xbb, 0xb2 + }; +#endif +#if defined(LTC_MD5) && defined(LTC_RC2) + static const unsigned char long_pri_pkcs8_pbe_md5_rc2_64[] = { + 0x30, 0x82, 0x01, 0x49, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x06, 0x30, 0x0e, 0x04, 0x08, 0x95, 0x82, 0x6d, 0x08, 0xe4, 0x7e, 0xae, 0x5f, 0x02, 0x02, 0x08, + 0x00, 0x04, 0x82, 0x01, 0x28, 0x93, 0x2c, 0xd8, 0x27, 0xed, 0x13, 0xe1, 0x31, 0xef, 0x7c, 0x44, + 0x9c, 0xce, 0x85, 0x17, 0x38, 0x5a, 0xe3, 0xd8, 0xe9, 0xfd, 0x1e, 0x81, 0xae, 0x9c, 0xd7, 0x8b, + 0x11, 0x4e, 0x92, 0x08, 0x3a, 0x97, 0x2c, 0x4f, 0x9a, 0xb7, 0x10, 0xda, 0x6a, 0x06, 0x9e, 0xe2, + 0xb6, 0x41, 0xf8, 0xb3, 0xd4, 0x42, 0xcc, 0x67, 0xe8, 0x25, 0x76, 0x9a, 0xc2, 0x66, 0x1a, 0x94, + 0x19, 0x0c, 0xe1, 0x43, 0x27, 0x27, 0x1e, 0xad, 0xfb, 0xce, 0xb7, 0x96, 0xfb, 0x5d, 0x6d, 0xf3, + 0xe1, 0x73, 0xc5, 0x1c, 0xa0, 0xbe, 0x94, 0x2c, 0xe7, 0x1c, 0x04, 0xa9, 0xfe, 0xdf, 0x15, 0x79, + 0x0c, 0x5e, 0xf8, 0xe2, 0xb9, 0x4a, 0xa0, 0xc5, 0x89, 0x2c, 0xf8, 0x1d, 0x5f, 0xcc, 0xf0, 0xb6, + 0xe8, 0x31, 0xeb, 0xe5, 0xb4, 0x9d, 0x2a, 0xa8, 0x8d, 0xff, 0x69, 0xf7, 0x83, 0x65, 0xbb, 0xa2, + 0xdd, 0xcd, 0x97, 0x41, 0x6e, 0xfa, 0xb6, 0xe1, 0x76, 0x7e, 0xa3, 0x24, 0x9b, 0x23, 0x58, 0x0e, + 0xeb, 0x08, 0x00, 0x96, 0x53, 0xae, 0x6c, 0xb9, 0xaa, 0x5c, 0x9a, 0xf8, 0xee, 0xcd, 0xfd, 0xe5, + 0xc5, 0x40, 0x62, 0x58, 0x6d, 0xf0, 0x10, 0xd5, 0x85, 0xeb, 0xed, 0x8a, 0x75, 0xe9, 0x8c, 0x2b, + 0xe7, 0x39, 0xaf, 0xb1, 0x15, 0xdb, 0x4f, 0xe3, 0xa5, 0x24, 0x1d, 0xd2, 0xae, 0x82, 0x88, 0x1a, + 0x37, 0x4c, 0x6b, 0x30, 0x9d, 0x6f, 0x93, 0x9c, 0x87, 0x99, 0xd1, 0x1c, 0x93, 0x0c, 0xbb, 0xf9, + 0x70, 0x36, 0x28, 0x56, 0x68, 0x27, 0x2f, 0x1e, 0xf1, 0x86, 0x0a, 0x23, 0x04, 0xe6, 0x72, 0x1f, + 0x1b, 0x71, 0x45, 0x0b, 0xe7, 0x74, 0x45, 0x8e, 0x7f, 0x94, 0xbc, 0xcd, 0x6c, 0xf8, 0xf3, 0xed, + 0x44, 0x02, 0x4d, 0x0a, 0xdd, 0xe9, 0xe4, 0x46, 0x31, 0x94, 0x28, 0x9b, 0x5f, 0x05, 0x37, 0xf4, + 0x05, 0x9c, 0xa3, 0x9c, 0xdf, 0xb7, 0xfb, 0xab, 0xe0, 0x07, 0x26, 0x40, 0x79, 0x12, 0x9a, 0x78, + 0xf6, 0xb6, 0x30, 0x3d, 0x4e, 0x16, 0x2e, 0x39, 0x96, 0x98, 0x2a, 0x8c, 0xa7, 0xdb, 0xa0, 0x4a, + 0x3f, 0x42, 0x30, 0xd3, 0x5d, 0xd0, 0x26, 0xd0, 0xc5, 0xd5, 0xa4, 0x10, 0x10 + }; +#endif +#if defined(LTC_SHA1) && defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbe_sha1_des[] = { + 0x30, 0x82, 0x01, 0x49, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0a, 0x30, 0x0e, 0x04, 0x08, 0x7c, 0x01, 0xae, 0xc9, 0x05, 0x43, 0x40, 0x70, 0x02, 0x02, 0x08, + 0x00, 0x04, 0x82, 0x01, 0x28, 0xff, 0x96, 0x47, 0x56, 0x02, 0xd5, 0xd3, 0x2a, 0xf0, 0x44, 0x47, + 0x7e, 0x74, 0x28, 0x62, 0x3f, 0x2b, 0xd4, 0xa9, 0xcc, 0x2c, 0xb7, 0x03, 0xc7, 0xa6, 0x39, 0xde, + 0xc1, 0x46, 0xf1, 0xcd, 0x53, 0xb8, 0x76, 0xcd, 0xb8, 0xfd, 0xe8, 0x96, 0x1d, 0x52, 0xc5, 0xc2, + 0x33, 0x2c, 0x2e, 0x4a, 0xe1, 0x83, 0x2e, 0x8a, 0x3a, 0x73, 0xfe, 0x50, 0x70, 0xcf, 0x2a, 0x29, + 0xd5, 0x8a, 0x77, 0x96, 0xa3, 0x29, 0x7e, 0xfa, 0x74, 0xde, 0x78, 0x31, 0xd6, 0x78, 0x0a, 0x4f, + 0x67, 0x8e, 0x26, 0xc9, 0x64, 0xf3, 0xde, 0xda, 0x5d, 0x15, 0xc2, 0x6b, 0x22, 0x25, 0x9e, 0x98, + 0x41, 0x71, 0x4c, 0x09, 0x56, 0x90, 0x44, 0x7d, 0x16, 0xab, 0x7e, 0xd3, 0x75, 0x54, 0xbd, 0x88, + 0x85, 0x4a, 0x01, 0xf4, 0x17, 0x19, 0xe2, 0x43, 0x5f, 0x31, 0xf9, 0x0b, 0x78, 0xd3, 0xb6, 0xc8, + 0xa0, 0x29, 0x65, 0x86, 0xbc, 0x4b, 0xcb, 0xe2, 0xe8, 0xe7, 0x06, 0xe2, 0x27, 0xa3, 0x6a, 0xdc, + 0x9f, 0x42, 0x40, 0xc4, 0x38, 0x49, 0x3b, 0x15, 0x28, 0x82, 0x9f, 0xa0, 0x2d, 0x42, 0x30, 0xa9, + 0x28, 0x84, 0x41, 0x2b, 0xa3, 0xfb, 0xf1, 0x74, 0xa1, 0xfa, 0xff, 0x9d, 0xb6, 0x7e, 0x9b, 0x9f, + 0xfa, 0xbd, 0x00, 0x17, 0x17, 0xa6, 0xb5, 0x2a, 0x1f, 0x6b, 0x55, 0x6c, 0xd4, 0x4b, 0xbe, 0xbb, + 0xa5, 0xa7, 0x9f, 0x0c, 0x90, 0x04, 0x91, 0x09, 0x4d, 0x82, 0xe1, 0x67, 0x21, 0x96, 0x3a, 0x3b, + 0xcf, 0x7f, 0xe9, 0xb9, 0xcc, 0x56, 0xd8, 0xc7, 0xe4, 0x98, 0x30, 0x11, 0x8f, 0xfd, 0xe5, 0xbc, + 0x5e, 0xc4, 0x60, 0xe9, 0xd4, 0xc6, 0xf2, 0x60, 0xf3, 0xcd, 0x36, 0xa4, 0xe4, 0x6c, 0xfe, 0xbf, + 0xab, 0xd5, 0x2f, 0x12, 0xf4, 0xa2, 0xf0, 0xeb, 0x10, 0xd9, 0x74, 0xef, 0x7c, 0x37, 0x8d, 0xdd, + 0xc1, 0xaa, 0x84, 0xf6, 0xf1, 0xb6, 0x5b, 0x43, 0x51, 0x06, 0x78, 0xae, 0x8e, 0x9d, 0xc5, 0xc9, + 0x26, 0xdc, 0x05, 0xa3, 0x00, 0xfa, 0x4a, 0x27, 0x5f, 0x19, 0xf3, 0x88, 0x2e, 0x01, 0xb8, 0xe7, + 0x23, 0x37, 0x77, 0xa1, 0xbb, 0xb0, 0x66, 0xe2, 0xba, 0x10, 0x50, 0x06, 0x65 + }; +#endif +#if defined(LTC_SHA1) && defined(LTC_RC2) + static const unsigned char long_pri_pkcs8_pbe_sha1_rc2_64[] = { + 0x30, 0x82, 0x01, 0x49, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0b, 0x30, 0x0e, 0x04, 0x08, 0x64, 0x3c, 0xdb, 0x86, 0xd9, 0xa0, 0xae, 0x3e, 0x02, 0x02, 0x08, + 0x00, 0x04, 0x82, 0x01, 0x28, 0x78, 0x85, 0x55, 0x7f, 0x37, 0xb8, 0xf7, 0xff, 0x94, 0x94, 0xf3, + 0xf2, 0x21, 0x05, 0x6d, 0x75, 0xca, 0x03, 0x1c, 0xa3, 0x9f, 0x47, 0x41, 0x14, 0x57, 0xdd, 0x63, + 0x71, 0x6c, 0xc2, 0x51, 0x14, 0x4a, 0x0d, 0x63, 0x12, 0xa8, 0x27, 0xf6, 0x3c, 0xb7, 0x47, 0x6d, + 0xa0, 0x72, 0xfe, 0x60, 0x9f, 0x1c, 0xc8, 0xe4, 0xe5, 0xfe, 0x68, 0x9d, 0x85, 0x0f, 0x8e, 0x52, + 0x2e, 0x30, 0xd5, 0x81, 0xd8, 0xc9, 0x05, 0x14, 0x1b, 0x1b, 0xf3, 0xbc, 0x95, 0x6d, 0x5d, 0x94, + 0x71, 0xff, 0xa8, 0xfe, 0xa7, 0x34, 0xff, 0x30, 0xbe, 0x8e, 0xe4, 0x65, 0x6b, 0xd0, 0xa2, 0x43, + 0x42, 0x14, 0x63, 0x36, 0x6f, 0x5d, 0x79, 0x56, 0x1b, 0x23, 0xd6, 0xdf, 0x39, 0x75, 0x48, 0x07, + 0xa2, 0x5f, 0x8d, 0x11, 0x7c, 0x95, 0x48, 0x18, 0x2d, 0xdd, 0x92, 0x14, 0x4f, 0xfd, 0x45, 0x7e, + 0x60, 0x68, 0xde, 0x47, 0x04, 0x0d, 0x0a, 0xa6, 0x3a, 0x30, 0xcb, 0x29, 0xc7, 0x9e, 0x27, 0xc3, + 0x2d, 0x49, 0xbd, 0x1e, 0xc5, 0xc9, 0xd8, 0xd2, 0x22, 0x72, 0xe2, 0xd0, 0x8e, 0x03, 0xe8, 0x84, + 0xfd, 0x7e, 0xb8, 0x8a, 0xd7, 0x70, 0x6d, 0x0b, 0xec, 0x67, 0xd0, 0xb3, 0x08, 0x9a, 0x31, 0x32, + 0x43, 0x1f, 0xa3, 0xd1, 0x6b, 0x3a, 0x63, 0xbc, 0xca, 0x25, 0x1e, 0x55, 0xd7, 0x21, 0x68, 0x77, + 0xfa, 0x41, 0x70, 0xdc, 0x3a, 0xfb, 0x05, 0x19, 0xd8, 0x8a, 0xe3, 0xe7, 0xfc, 0xf1, 0xc1, 0x0d, + 0xd4, 0x9e, 0x64, 0xd0, 0x91, 0xa5, 0x4d, 0x7b, 0x8b, 0xd9, 0xee, 0xa7, 0x6b, 0x2b, 0x0f, 0xd9, + 0xcf, 0xb3, 0xb4, 0x5b, 0x4e, 0xcc, 0xac, 0x53, 0xe5, 0xd3, 0xdd, 0x73, 0x40, 0xa5, 0x35, 0x71, + 0xeb, 0xca, 0xa7, 0xc0, 0xae, 0x70, 0xdf, 0x14, 0x83, 0xbe, 0xd8, 0x37, 0xfa, 0x8b, 0x14, 0xdb, + 0x0c, 0x4e, 0x98, 0xc7, 0xe6, 0x40, 0x38, 0x94, 0x69, 0xd4, 0xd4, 0xa9, 0xb5, 0x3f, 0xec, 0xac, + 0x14, 0x59, 0x46, 0xb5, 0x98, 0xb0, 0x99, 0x89, 0xea, 0xf5, 0x43, 0xb4, 0x47, 0xa9, 0xb1, 0xf2, + 0x03, 0x2a, 0xaf, 0xd5, 0x5d, 0x81, 0xae, 0x3b, 0xb4, 0x52, 0x11, 0x85, 0xcb + }; +#endif +#if defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbkdf2_des_cbc[] = { + 0x30, 0x82, 0x01, 0x6b, 0x30, 0x3d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x30, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x0e, 0x04, 0x08, 0xda, 0x6b, 0x0a, 0x58, 0x7e, 0xd2, 0x9d, 0x38, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x11, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x07, 0x04, 0x08, 0xcc, 0x5c, 0x19, 0x7c, 0xa6, + 0x0d, 0x01, 0x4b, 0x04, 0x82, 0x01, 0x28, 0x02, 0x9d, 0xec, 0xa4, 0xe1, 0x42, 0xc4, 0xdb, 0x18, + 0x32, 0x26, 0x96, 0x8b, 0x87, 0x1a, 0xb7, 0x66, 0x8e, 0xfd, 0x23, 0x1e, 0x1e, 0x20, 0x18, 0xcd, + 0x81, 0x1b, 0x67, 0x86, 0x78, 0xae, 0xb3, 0x70, 0x81, 0xf9, 0x6a, 0x26, 0x4e, 0x31, 0x64, 0xf8, + 0x7e, 0xbf, 0xf3, 0xd3, 0xea, 0x7c, 0xda, 0x5d, 0x4d, 0xb7, 0xe2, 0xda, 0x9a, 0x80, 0x94, 0xd1, + 0x65, 0x5f, 0x57, 0x17, 0xbc, 0xac, 0xd3, 0xb4, 0x94, 0xdc, 0xd0, 0x34, 0xe9, 0xed, 0x57, 0x97, + 0x53, 0xe9, 0x24, 0x21, 0xac, 0x2b, 0xd1, 0xd9, 0x35, 0x7f, 0xf0, 0x79, 0x14, 0xce, 0x96, 0xe2, + 0x55, 0xfb, 0xb9, 0x6e, 0xeb, 0xbf, 0xc8, 0xf2, 0x66, 0xc1, 0x42, 0xee, 0x94, 0x22, 0xac, 0x6a, + 0xe2, 0xf6, 0xba, 0xfc, 0xeb, 0xc1, 0xd0, 0xec, 0x3c, 0x16, 0xa4, 0x36, 0x7a, 0xbf, 0xe9, 0x9d, + 0x39, 0xd6, 0x32, 0x54, 0x3e, 0x86, 0xcf, 0xe4, 0x32, 0x1c, 0xc5, 0x54, 0x3f, 0x8d, 0x6e, 0xb9, + 0x6c, 0x3d, 0xd7, 0x68, 0xd7, 0x67, 0xdd, 0x04, 0x0e, 0x8c, 0xfd, 0x62, 0x1a, 0x21, 0xa8, 0xcc, + 0x67, 0xbd, 0x4f, 0x9b, 0x3c, 0x99, 0xd5, 0xa5, 0x98, 0x12, 0x33, 0x04, 0xcf, 0x1b, 0x58, 0x3f, + 0xb2, 0x70, 0xfe, 0x92, 0xff, 0x7a, 0x73, 0xf9, 0x37, 0xd5, 0x20, 0x0e, 0x49, 0xed, 0xb3, 0x77, + 0x73, 0x0f, 0x3e, 0xf8, 0x15, 0xc1, 0xfc, 0x28, 0x47, 0x10, 0xe8, 0x30, 0xee, 0xa9, 0x96, 0xcf, + 0x39, 0xb6, 0x83, 0xe2, 0x84, 0x1d, 0x0e, 0x65, 0xb7, 0x02, 0x08, 0xf7, 0x8d, 0xe7, 0xf2, 0xcc, + 0x52, 0xc2, 0xe6, 0x1d, 0xf6, 0x96, 0x17, 0x3e, 0x3f, 0xd8, 0x70, 0x8d, 0x2c, 0x62, 0x00, 0xf3, + 0x32, 0xbd, 0x1c, 0x6b, 0x4a, 0x0c, 0xc6, 0x46, 0x61, 0x92, 0x1c, 0x01, 0x11, 0xbc, 0x55, 0xdd, + 0x82, 0xd1, 0xbf, 0x2e, 0x1e, 0x97, 0xbe, 0xa7, 0x6e, 0x5a, 0xcd, 0xc6, 0x8f, 0x38, 0x24, 0x8f, + 0xb8, 0x36, 0x3d, 0x06, 0x82, 0x14, 0x5b, 0x1a, 0x84, 0x1e, 0x47, 0x53, 0x3a, 0x12, 0x21, 0x23, + 0xbe, 0xe4, 0xf4, 0x57, 0xc7, 0x31, 0x45, 0x24, 0x46, 0x94, 0x53, 0x0b, 0x1d, 0xcd, 0x57 + }; +#endif +#if defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbkdf2_des_ede3_cbc[] = { + 0x30, 0x82, 0x01, 0x6e, 0x30, 0x40, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x33, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x0e, 0x04, 0x08, 0x6a, 0x99, 0x55, 0x06, 0x40, 0xd5, 0xe6, 0xc9, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x14, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x7f, 0xf2, + 0xa7, 0xa3, 0x2c, 0xbb, 0x8e, 0x78, 0x04, 0x82, 0x01, 0x28, 0x55, 0x4d, 0xcb, 0xab, 0xb8, 0x6e, + 0xcf, 0x00, 0xd2, 0xe8, 0x1e, 0x0e, 0xe1, 0x8f, 0x51, 0x8e, 0x32, 0x68, 0xaf, 0x44, 0xa6, 0xf2, + 0x9e, 0x11, 0xd7, 0x0f, 0xa7, 0xd5, 0x74, 0x77, 0xbc, 0x6b, 0x53, 0x40, 0x70, 0xb6, 0x02, 0xdb, + 0xa6, 0x2e, 0xc7, 0x20, 0x15, 0x78, 0x91, 0xcc, 0x5b, 0xa7, 0x15, 0x58, 0x65, 0xeb, 0xc7, 0x6f, + 0xb8, 0x14, 0xc9, 0x5f, 0x89, 0x58, 0xe2, 0xab, 0x69, 0x17, 0xe2, 0xe7, 0xe0, 0xa4, 0x59, 0xb7, + 0x6a, 0xc2, 0xe5, 0xba, 0x03, 0x0e, 0xcc, 0x0a, 0xb1, 0xf0, 0x69, 0xb2, 0x90, 0xac, 0x30, 0x79, + 0xd4, 0xa3, 0x90, 0xa2, 0x60, 0x37, 0x7d, 0xf8, 0xd9, 0x49, 0xa3, 0x0b, 0x6d, 0xd9, 0x98, 0x9e, + 0xb0, 0x6a, 0xad, 0x97, 0x08, 0xf1, 0xfd, 0xec, 0xf8, 0xa7, 0x3c, 0xf6, 0x48, 0x81, 0x5b, 0x6d, + 0x19, 0xcc, 0xed, 0x49, 0x94, 0x05, 0x6e, 0xa4, 0x9b, 0x58, 0xdd, 0xaf, 0xd7, 0x3d, 0x12, 0xe6, + 0xf4, 0x12, 0x46, 0xd9, 0x82, 0xde, 0xb7, 0xc4, 0xeb, 0x1c, 0x3a, 0xef, 0x93, 0x82, 0x3d, 0xf8, + 0x55, 0x88, 0xe5, 0x54, 0xd6, 0x74, 0x1c, 0x20, 0xbd, 0x40, 0x65, 0x99, 0x19, 0x5f, 0x25, 0x62, + 0x35, 0x6d, 0x32, 0x64, 0xd7, 0xa1, 0x45, 0xa8, 0xc4, 0x8d, 0xe0, 0x6d, 0x14, 0x85, 0x84, 0x75, + 0x62, 0x0f, 0xb0, 0xe9, 0xb1, 0xca, 0x31, 0x97, 0x22, 0x41, 0xb3, 0xf5, 0xdf, 0x5c, 0xbf, 0x3f, + 0x4f, 0x01, 0xf8, 0xe7, 0xbc, 0xdc, 0xb2, 0x9a, 0x7d, 0x0c, 0x96, 0x38, 0x48, 0x7a, 0x1b, 0x89, + 0x2b, 0xab, 0xa6, 0xbd, 0xee, 0x7a, 0xf8, 0x85, 0x82, 0x80, 0x8c, 0x3b, 0x05, 0x3c, 0x40, 0x69, + 0x97, 0x0a, 0x4c, 0x45, 0xae, 0x38, 0x22, 0xc5, 0x95, 0xf2, 0x4f, 0x0c, 0xd5, 0x54, 0x23, 0x92, + 0x9b, 0x06, 0x81, 0xca, 0xa5, 0x1e, 0x91, 0x7e, 0x2b, 0x85, 0xb4, 0xd4, 0xeb, 0xb6, 0xee, 0x22, + 0x10, 0x72, 0xaf, 0x9e, 0x6d, 0xcc, 0x16, 0x24, 0x01, 0x44, 0x48, 0xaa, 0xc9, 0xf8, 0x38, 0x72, + 0x7a, 0x35, 0x94, 0x20, 0x58, 0xa2, 0x1c, 0x81, 0xaf, 0x47, 0x3b, 0xb8, 0x23, 0xbb, 0x71, 0x09, + 0xbf, 0x93 + }; +#endif +#if defined(LTC_RC2) + static const unsigned char long_pri_pkcs8_pbkdf2_rc2_cbc[] = { + 0x30, 0x82, 0x01, 0x76, 0x30, 0x48, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x3b, 0x30, 0x1e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x11, 0x04, 0x08, 0xbf, 0xef, 0x1a, 0x42, 0x5d, 0xc3, 0x6b, 0x0f, 0x02, 0x02, 0x08, 0x00, + 0x02, 0x01, 0x10, 0x30, 0x19, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02, 0x30, + 0x0d, 0x02, 0x01, 0x3a, 0x04, 0x08, 0xfe, 0xf2, 0x09, 0x0c, 0xa4, 0xd0, 0xe6, 0x83, 0x04, 0x82, + 0x01, 0x28, 0x61, 0x18, 0x73, 0xb7, 0x9d, 0x58, 0xc8, 0x4a, 0xf4, 0x24, 0xec, 0xb4, 0xe6, 0x24, + 0xa7, 0xf0, 0x1e, 0xea, 0xc3, 0x57, 0x44, 0xb7, 0x5a, 0x77, 0xe5, 0x3c, 0x1c, 0x6a, 0x6b, 0x70, + 0x6e, 0x64, 0x35, 0xa5, 0x5d, 0x32, 0xe3, 0xce, 0xe8, 0x79, 0xa4, 0x7f, 0x2b, 0xfc, 0xcb, 0x07, + 0x62, 0xcd, 0xc9, 0x15, 0x30, 0xdf, 0x69, 0xae, 0xe8, 0xb4, 0x83, 0xec, 0x2a, 0xaf, 0xb3, 0x29, + 0x92, 0x77, 0xf3, 0x31, 0x4d, 0x5f, 0xcb, 0xea, 0xa2, 0x4d, 0xfb, 0xa1, 0x68, 0xbe, 0x00, 0x01, + 0x6d, 0x3f, 0xc6, 0xc1, 0x13, 0xee, 0xb0, 0x5a, 0x52, 0xce, 0xdc, 0x12, 0xf8, 0x42, 0x22, 0x2f, + 0x57, 0x2e, 0x54, 0xac, 0x48, 0x31, 0x4d, 0x3c, 0xa1, 0x97, 0x5e, 0x17, 0x74, 0x88, 0x9b, 0x31, + 0x91, 0x69, 0x00, 0x00, 0x15, 0x2c, 0xc2, 0xac, 0x70, 0x84, 0x9c, 0x7e, 0x5d, 0xc9, 0xee, 0x06, + 0xcc, 0x38, 0x9d, 0x7d, 0xea, 0x71, 0xc3, 0x4f, 0x99, 0x08, 0xde, 0xb0, 0x1b, 0x3b, 0x2a, 0xbd, + 0x7e, 0x01, 0x3b, 0x5e, 0xe5, 0xc2, 0x54, 0xf2, 0x30, 0xe5, 0xa0, 0xf3, 0x69, 0x87, 0x77, 0xed, + 0xa1, 0x37, 0x76, 0x6a, 0xec, 0xe2, 0x9c, 0x8d, 0x4c, 0xe9, 0xf4, 0xd0, 0xca, 0xb5, 0x8f, 0xd0, + 0x63, 0x17, 0x41, 0xcb, 0x29, 0x58, 0x4f, 0x2a, 0xd1, 0xe1, 0x03, 0x73, 0x09, 0xcc, 0x93, 0xc6, + 0xde, 0x1e, 0x34, 0x0f, 0xb3, 0x67, 0xfd, 0x5e, 0x49, 0x16, 0x84, 0x84, 0x6a, 0x8f, 0x55, 0x22, + 0x0b, 0xe4, 0xd8, 0xee, 0x2e, 0x9f, 0x25, 0x19, 0x89, 0x19, 0xe6, 0x8d, 0x64, 0x31, 0x38, 0x68, + 0xfa, 0x40, 0x84, 0xca, 0x39, 0xef, 0x1a, 0x4a, 0xe9, 0x04, 0xee, 0xcc, 0x4a, 0xea, 0x19, 0x96, + 0xa4, 0xcd, 0x62, 0x76, 0xb3, 0xc4, 0x2c, 0x23, 0x75, 0x24, 0xcd, 0x49, 0xe2, 0x17, 0x81, 0x45, + 0x24, 0x55, 0xeb, 0xe1, 0xb4, 0xeb, 0xda, 0xc5, 0x56, 0xac, 0xfa, 0x30, 0xbd, 0x05, 0xbb, 0x03, + 0x65, 0x50, 0xdc, 0xbf, 0xdf, 0xff, 0x2a, 0x80, 0x85, 0x6d, 0x6a, 0x5c, 0x93, 0xb8, 0x81, 0xc4, + 0xca, 0x91, 0x08, 0x7b, 0x8a, 0x9d, 0xe9, 0x2d, 0xfc, 0x3b + }; +#endif +#if defined(LTC_SHA224) && defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbkdf2_sha224_des_ede3_cbc[] = { + 0x30, 0x82, 0x01, 0x7c, 0x30, 0x4e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x41, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x1c, 0x04, 0x08, 0xb2, 0x82, 0x71, 0xc5, 0xd6, 0x3c, 0x2b, 0x92, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x08, 0x05, 0x00, 0x30, 0x14, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x4a, 0x46, 0x2a, 0xa9, + 0xd5, 0x9f, 0x79, 0xea, 0x04, 0x82, 0x01, 0x28, 0xc4, 0x27, 0x05, 0xa8, 0x01, 0xa7, 0xc9, 0x0d, + 0x0e, 0x74, 0x06, 0x4a, 0xb8, 0x07, 0x9f, 0x7b, 0x0f, 0x82, 0xfd, 0x2c, 0xb5, 0x4f, 0x63, 0xed, + 0xed, 0x86, 0x96, 0x79, 0x08, 0x2d, 0x5f, 0x6d, 0x8c, 0x83, 0xc9, 0xcc, 0xd4, 0x9b, 0x0a, 0x81, + 0x60, 0x22, 0x09, 0xb9, 0x12, 0xca, 0xf1, 0xad, 0x61, 0x22, 0xf0, 0x6b, 0xdb, 0x52, 0x99, 0xae, + 0x70, 0x2b, 0x61, 0x63, 0xdc, 0x2f, 0xc1, 0xd3, 0xb5, 0x28, 0xbb, 0xa1, 0xd2, 0xb7, 0xaf, 0xbb, + 0x86, 0xa1, 0x1b, 0x46, 0x0a, 0xc9, 0xab, 0x44, 0xd2, 0x9c, 0x16, 0x18, 0x8b, 0x4a, 0x92, 0x56, + 0x5b, 0x50, 0x39, 0x1b, 0x88, 0x50, 0x92, 0x35, 0xb8, 0x85, 0xc3, 0xaa, 0x56, 0x76, 0xde, 0xbf, + 0x68, 0x91, 0x2e, 0xc8, 0x28, 0x29, 0xd8, 0x71, 0x60, 0xe3, 0xf0, 0x5a, 0x66, 0x85, 0xdd, 0x6b, + 0x5c, 0xaf, 0xf1, 0x28, 0xf8, 0xdc, 0xa7, 0x8d, 0xc4, 0x9b, 0xcb, 0xb2, 0x99, 0x34, 0x4d, 0x76, + 0xa0, 0x8b, 0xf2, 0x18, 0x8e, 0x42, 0xe0, 0x79, 0xc3, 0xeb, 0x0f, 0x00, 0xe7, 0xbe, 0x83, 0xdf, + 0xba, 0xa5, 0xf1, 0x81, 0x05, 0x1c, 0xc9, 0xda, 0xea, 0xe1, 0xc4, 0x38, 0x24, 0x1e, 0xcf, 0xea, + 0x22, 0x05, 0x75, 0x43, 0xfe, 0xfe, 0x14, 0xf7, 0x6d, 0x41, 0x67, 0xcf, 0xfd, 0x57, 0xa7, 0xfc, + 0x22, 0x03, 0x14, 0xc1, 0xf6, 0x4d, 0x40, 0x4e, 0xf1, 0xec, 0x72, 0xec, 0x3c, 0xb1, 0x87, 0x44, + 0xe9, 0x72, 0xc5, 0x8b, 0x48, 0xd9, 0x98, 0x08, 0x55, 0xc5, 0x40, 0x26, 0xf5, 0x8d, 0x73, 0x5e, + 0x35, 0x98, 0x71, 0x09, 0x98, 0xfa, 0xb7, 0x1c, 0x35, 0xcd, 0xd4, 0xf1, 0x65, 0xb4, 0x59, 0xdb, + 0x9e, 0x79, 0xe7, 0x21, 0x99, 0xd7, 0x9e, 0x8c, 0x13, 0x77, 0x0c, 0x5e, 0xae, 0x43, 0x82, 0xf1, + 0x83, 0x79, 0x7d, 0x37, 0x51, 0xde, 0x65, 0x26, 0x1f, 0x8f, 0x81, 0x1c, 0x55, 0x40, 0xec, 0xaf, + 0x3f, 0x0a, 0x68, 0xd2, 0xc7, 0x59, 0x47, 0xda, 0x78, 0x0c, 0x0e, 0x59, 0x6a, 0x93, 0xcd, 0x05, + 0x09, 0x51, 0x47, 0xb1, 0x45, 0x3f, 0x67, 0xf8, 0x76, 0x50, 0x76, 0xa3, 0x2d, 0x31, 0x17, 0x73 + }; +#endif +#if defined(LTC_SHA256) && defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbkdf2_sha256_des_ede3_cbc[] = { + 0x30, 0x82, 0x01, 0x7c, 0x30, 0x4e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x41, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x1c, 0x04, 0x08, 0x93, 0x6e, 0x0a, 0x02, 0x8e, 0x72, 0xac, 0x98, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09, 0x05, 0x00, 0x30, 0x14, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x89, 0xa4, 0xc9, 0xd9, + 0x82, 0xfa, 0x02, 0x76, 0x04, 0x82, 0x01, 0x28, 0xec, 0xd9, 0xee, 0xbf, 0xfa, 0xe6, 0x51, 0xdb, + 0x02, 0xcb, 0xf3, 0x2c, 0x55, 0xdb, 0x83, 0x90, 0x5d, 0x9e, 0xf6, 0xbe, 0x10, 0xae, 0x35, 0x8c, + 0x22, 0x39, 0xfc, 0xf9, 0xd1, 0x23, 0x27, 0x68, 0xd3, 0x15, 0x46, 0xed, 0x5d, 0x15, 0xfb, 0xdf, + 0x6f, 0xe1, 0x01, 0x1c, 0xed, 0x4c, 0xfc, 0x78, 0x94, 0x47, 0x71, 0x92, 0xbc, 0xa1, 0xa6, 0x06, + 0x74, 0x22, 0xcc, 0xbb, 0x49, 0x98, 0x43, 0xf1, 0xc2, 0xde, 0x4e, 0xeb, 0x56, 0x0e, 0x03, 0xc1, + 0xf1, 0xc1, 0x80, 0x4b, 0x70, 0xd0, 0x8f, 0xf3, 0xd8, 0x18, 0x08, 0x41, 0x7a, 0xf9, 0x8b, 0x74, + 0xe5, 0x28, 0x61, 0x77, 0x2f, 0x84, 0xb3, 0xb3, 0x68, 0xce, 0x19, 0xf0, 0xc6, 0xa9, 0xc1, 0x29, + 0x96, 0xca, 0x3b, 0xdb, 0x13, 0x99, 0x86, 0xbe, 0x21, 0x0d, 0x00, 0xd7, 0x30, 0x15, 0x74, 0xfb, + 0x43, 0xf7, 0x14, 0x97, 0x6d, 0xed, 0xeb, 0xe3, 0x4d, 0x67, 0x80, 0x35, 0x03, 0x69, 0x0d, 0xbe, + 0xf1, 0x99, 0x6b, 0x53, 0xb7, 0xa3, 0xdf, 0xf4, 0xc3, 0xda, 0x20, 0x9b, 0xbf, 0xf9, 0x3f, 0x19, + 0xae, 0xd5, 0x37, 0x91, 0x36, 0x42, 0xf3, 0x7d, 0xad, 0x40, 0x3c, 0x2a, 0x7f, 0x2d, 0xf1, 0x79, + 0xee, 0x4c, 0x08, 0x3a, 0xd6, 0x35, 0x9b, 0xc9, 0xff, 0xd8, 0x41, 0x41, 0xd1, 0xc6, 0xa1, 0xba, + 0x4d, 0xc6, 0xb7, 0x85, 0x05, 0xa1, 0x8e, 0xeb, 0xd1, 0xd2, 0x3a, 0x13, 0xd7, 0xbd, 0xb0, 0x02, + 0xfe, 0x54, 0xfe, 0xf4, 0xfd, 0x31, 0x0c, 0x42, 0x78, 0xb9, 0x17, 0x90, 0x36, 0x17, 0xb8, 0x1a, + 0x08, 0xe8, 0x7e, 0x5f, 0xbb, 0x30, 0xc2, 0xec, 0xd5, 0x08, 0xbc, 0xae, 0x2f, 0xe0, 0xca, 0xf2, + 0x44, 0x2c, 0xa4, 0xb5, 0xec, 0xb9, 0xc2, 0xa3, 0x4a, 0x1a, 0x49, 0xfb, 0x3e, 0x5c, 0xb5, 0xd8, + 0xb6, 0xf0, 0xbc, 0xa2, 0xda, 0xaa, 0x7a, 0x05, 0x4d, 0x06, 0xc0, 0x4b, 0x8f, 0x59, 0xce, 0x56, + 0x02, 0x26, 0xb2, 0xa0, 0x5f, 0x74, 0xbb, 0x0b, 0x01, 0x1c, 0xb2, 0x0b, 0x8a, 0x80, 0xa4, 0x5d, + 0x6e, 0x52, 0x24, 0xd0, 0xbe, 0xf5, 0x8e, 0x9e, 0x9e, 0x02, 0x40, 0x08, 0x99, 0xe0, 0x2c, 0xf9 + }; +#endif +#if defined(LTC_SHA384) && defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbkdf2_sha384_des_ede3_cbc[] = { + 0x30, 0x82, 0x01, 0x7c, 0x30, 0x4e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x41, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x1c, 0x04, 0x08, 0xfd, 0x6c, 0xdf, 0x0b, 0x23, 0xed, 0x71, 0xf7, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0a, 0x05, 0x00, 0x30, 0x14, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x99, 0xd0, 0x84, 0x7d, + 0x6d, 0x4e, 0x82, 0xe1, 0x04, 0x82, 0x01, 0x28, 0xac, 0x9a, 0x2c, 0x71, 0xdf, 0x1a, 0x19, 0x38, + 0xee, 0xc4, 0x9d, 0x7a, 0x27, 0xe0, 0xb9, 0x69, 0x32, 0xed, 0xe7, 0xa1, 0x77, 0x16, 0x60, 0x18, + 0x7a, 0xf1, 0x47, 0xc1, 0x98, 0x48, 0xa4, 0xff, 0xab, 0x83, 0x1a, 0x7d, 0xe3, 0xdb, 0xcc, 0xf0, + 0x40, 0x94, 0x3a, 0x6a, 0x3f, 0xf7, 0x88, 0x19, 0x59, 0xf4, 0xd8, 0x1b, 0x87, 0x14, 0x5b, 0x9c, + 0x1f, 0xc5, 0xaf, 0x80, 0xe8, 0x06, 0xdb, 0xfa, 0x2c, 0xac, 0x61, 0x1c, 0xec, 0xec, 0x99, 0x5e, + 0x06, 0x6e, 0x68, 0x4c, 0xb0, 0xc8, 0x6f, 0x74, 0x2c, 0x1e, 0x58, 0x2f, 0x49, 0x82, 0xa4, 0x2b, + 0xb4, 0x4a, 0x2d, 0x77, 0x13, 0x87, 0xed, 0xbd, 0x71, 0x5a, 0x29, 0x29, 0x0c, 0x88, 0x4a, 0xf3, + 0x76, 0x37, 0x7e, 0x04, 0x3c, 0x45, 0x76, 0x98, 0x22, 0x20, 0x97, 0xef, 0xae, 0x4a, 0xa9, 0x08, + 0x54, 0xef, 0x43, 0xe0, 0x86, 0x54, 0x72, 0x44, 0xd1, 0x25, 0x9c, 0xb6, 0x7d, 0x88, 0xbd, 0x8f, + 0xbe, 0xcb, 0xa8, 0x63, 0xfe, 0x66, 0x54, 0xa2, 0xce, 0x77, 0x19, 0x7e, 0xdd, 0xf7, 0x4d, 0xdc, + 0xb1, 0xf7, 0xbf, 0x3c, 0xb5, 0xd2, 0x30, 0x9d, 0x3c, 0x35, 0x09, 0x37, 0xae, 0xae, 0x0f, 0x0b, + 0x9d, 0xf5, 0x10, 0xae, 0x56, 0x83, 0x4f, 0xd8, 0xcd, 0xfe, 0xb7, 0xa9, 0x54, 0xf9, 0xb3, 0x89, + 0xf6, 0x9a, 0x11, 0x60, 0x04, 0x4d, 0x80, 0xaf, 0x74, 0x73, 0x2d, 0xc4, 0x24, 0x23, 0xaa, 0x50, + 0x4c, 0xf1, 0xd6, 0x2d, 0xc6, 0x74, 0xeb, 0x62, 0x02, 0xda, 0x81, 0x68, 0xc8, 0x68, 0xf0, 0x82, + 0x71, 0xb2, 0xa5, 0x8e, 0x45, 0x93, 0x29, 0x94, 0x8f, 0xec, 0x11, 0x65, 0xcc, 0xd6, 0x4c, 0x2e, + 0x0d, 0x4e, 0x45, 0xb4, 0x4e, 0x97, 0x38, 0xd0, 0xc2, 0x61, 0x43, 0x78, 0xa4, 0x08, 0x0a, 0x58, + 0x3f, 0x66, 0xdb, 0x34, 0x42, 0x17, 0x42, 0x92, 0x04, 0x9a, 0x2d, 0x73, 0xaf, 0x58, 0x38, 0xc8, + 0x3f, 0x5b, 0x83, 0x95, 0x3d, 0xae, 0xae, 0x60, 0x2b, 0x6d, 0xd9, 0xb4, 0xe3, 0x97, 0x6b, 0x49, + 0xef, 0xd9, 0x68, 0xbb, 0x8d, 0x3a, 0x7e, 0xcb, 0x57, 0x33, 0xf5, 0x1a, 0x8d, 0xb4, 0x6d, 0xfb + }; +#endif +#if defined(LTC_SHA512) && defined(LTC_DES) + static const unsigned char long_pri_pkcs8_pbkdf2_sha512_des_ede3_cbc[] = { + 0x30, 0x82, 0x01, 0x7c, 0x30, 0x4e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, + 0x0d, 0x30, 0x41, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, + 0x30, 0x1c, 0x04, 0x08, 0xad, 0xb1, 0xe1, 0x21, 0xdc, 0xe5, 0x09, 0xee, 0x02, 0x02, 0x08, 0x00, + 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0b, 0x05, 0x00, 0x30, 0x14, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07, 0x04, 0x08, 0x1a, 0x8b, 0x81, 0x3b, + 0x97, 0x7d, 0xfa, 0x51, 0x04, 0x82, 0x01, 0x28, 0x6d, 0x6f, 0x93, 0x77, 0xcb, 0x52, 0x2d, 0x3b, + 0x82, 0x12, 0x80, 0xce, 0x9e, 0x69, 0x03, 0xe4, 0x64, 0xa1, 0x4b, 0x8e, 0x60, 0x51, 0x4d, 0x08, + 0xe1, 0x25, 0x5d, 0xe6, 0xed, 0x20, 0x23, 0x4c, 0x4e, 0xa3, 0xe8, 0xab, 0x7a, 0xf8, 0x54, 0x65, + 0x22, 0x92, 0x0c, 0x45, 0xab, 0x1c, 0xe2, 0x68, 0x4e, 0xf3, 0xa9, 0x61, 0xd6, 0x44, 0x9d, 0x55, + 0x19, 0xc6, 0xd9, 0x2a, 0x0d, 0x45, 0x7d, 0xca, 0xa4, 0x41, 0xb5, 0x6d, 0xd5, 0x09, 0xf2, 0xb6, + 0x81, 0x95, 0x64, 0xdb, 0x2b, 0xed, 0x83, 0x6b, 0x44, 0xa6, 0xce, 0x36, 0x8d, 0x23, 0x89, 0xb6, + 0xf3, 0xb0, 0xe0, 0xcf, 0x57, 0x72, 0xc7, 0x61, 0x3f, 0x29, 0xb9, 0xea, 0xe8, 0x7a, 0xca, 0x43, + 0x90, 0x79, 0x81, 0x8a, 0xe2, 0x3c, 0xd1, 0xa6, 0xd9, 0x09, 0xd8, 0x7d, 0xd0, 0x90, 0x69, 0x7e, + 0xdd, 0x40, 0xde, 0xba, 0x11, 0xc6, 0x6f, 0x75, 0xfc, 0xc3, 0x99, 0x43, 0xd2, 0xa4, 0x16, 0x2e, + 0x95, 0x99, 0x12, 0x77, 0xe8, 0x86, 0x9a, 0xf9, 0x97, 0xf4, 0x43, 0x99, 0x1d, 0x7b, 0xe0, 0x69, + 0xb0, 0xe9, 0x45, 0xd0, 0x0b, 0xaa, 0xd0, 0xa9, 0x90, 0x85, 0x39, 0xd9, 0xe0, 0xe4, 0xe5, 0xf3, + 0xcf, 0xb6, 0x60, 0x63, 0x51, 0x0b, 0xd8, 0x3d, 0xa2, 0x0f, 0xf6, 0x53, 0x09, 0x2e, 0x11, 0xc4, + 0xe6, 0xe3, 0xfa, 0xfb, 0x9f, 0x4d, 0xf4, 0xef, 0xb2, 0xf6, 0x9b, 0xc6, 0xb3, 0x75, 0x66, 0xfd, + 0x1b, 0x44, 0xba, 0x3c, 0xa8, 0x51, 0xbe, 0x97, 0xf1, 0x54, 0xb5, 0xcc, 0x6f, 0x5f, 0x1d, 0x9b, + 0xee, 0xed, 0x7a, 0x82, 0xfa, 0x40, 0x39, 0xa7, 0xf5, 0x8e, 0x5e, 0x42, 0xfa, 0x37, 0xcc, 0xe8, + 0x99, 0x38, 0xc1, 0xab, 0x83, 0xb8, 0x3c, 0x25, 0x17, 0x5f, 0xb7, 0x45, 0x0f, 0xcd, 0xec, 0x2a, + 0x47, 0x07, 0x02, 0xba, 0x92, 0xc1, 0x79, 0xf1, 0x95, 0xc7, 0x83, 0x46, 0xd7, 0x9e, 0x04, 0x96, + 0x3c, 0x5d, 0x7e, 0x70, 0xe6, 0x2b, 0x72, 0x70, 0x42, 0x66, 0x17, 0x0e, 0xc3, 0xcf, 0x32, 0x28, + 0x0c, 0xf9, 0x46, 0x38, 0xb7, 0x64, 0xd6, 0x51, 0xf9, 0xbd, 0x57, 0xf2, 0x7a, 0xcc, 0x02, 0xe3 + }; +#endif + static const unsigned char long_pric[] = { /* private + compressed public, explicit curve params */ + 0x30, 0x81, 0xd3, 0x02, 0x01, 0x01, 0x04, 0x20, 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, + 0xba, 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, 0xf7, 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, + 0x5f, 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, 0x23, 0xa0, 0x81, 0x85, 0x30, 0x81, 0x82, 0x02, 0x01, + 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x30, + 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, 0x07, 0x04, 0x21, 0x02, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, + 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, + 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, + 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, 0x02, 0x01, 0x01, + 0xa1, 0x24, 0x03, 0x22, 0x00, 0x03, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, + 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, + 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16 + }; + static const unsigned char long_pric_pkcs8[] = { /* private + compressed public, explicit curve params, PKCS8 */ + 0x30, 0x81, 0xe3, 0x02, 0x01, 0x00, 0x30, 0x81, 0x8e, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x02, 0x01, 0x30, 0x81, 0x82, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, 0x07, 0x04, 0x21, + 0x02, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, + 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, + 0x98, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, + 0xd0, 0x36, 0x41, 0x41, 0x02, 0x01, 0x01, 0x04, 0x4d, 0x30, 0x4b, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, 0xba, 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, 0xf7, + 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, 0x5f, 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, 0x23, + 0xa1, 0x24, 0x03, 0x22, 0x00, 0x03, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, + 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, + 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16 + }; + static const unsigned char long_pub[] = { /* long public, explicit curve params */ + 0x30, 0x81, 0xf5, 0x30, 0x81, 0xae, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, + 0x81, 0xa2, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, + 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, 0x07, 0x04, 0x41, 0x04, 0x79, 0xbe, + 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, + 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, + 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, + 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, 0x02, 0x21, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, + 0x41, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, + 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, + 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, + 0xb7, 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, + 0x6e, 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d + }; + static const unsigned char long_pubc[] = { /* compressed public, explicit curve params */ + 0x30, 0x81, 0xb5, 0x30, 0x81, 0x8e, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, + 0x81, 0x82, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, + 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, + 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01, 0x07, 0x04, 0x21, 0x02, 0x79, 0xbe, + 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, + 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x02, 0x21, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, + 0x41, 0x02, 0x01, 0x01, 0x03, 0x22, 0x00, 0x03, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, + 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, + 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16 + }; + static const unsigned char short_pri[] = { /* private + long public, curve by OID */ + 0x30, 0x74, 0x02, 0x01, 0x01, 0x04, 0x20, 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, 0xba, + 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, 0xf7, 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, 0x5f, + 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, 0x23, 0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, + 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, + 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, + 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, 0xb7, 0x6c, + 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, 0x6e, 0x4b, + 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d + }; + static const unsigned char short_pri_pkcs8[] = { /* private + long public, curve by OID, PKCS8 */ + 0x30, 0x81, 0x84, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, + 0x20, 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, 0xba, 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, + 0xf7, 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, 0x5f, 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, + 0x23, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, + 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, + 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, 0xb7, + 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, 0x6e, + 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d + }; + static const unsigned char short_pric[] = { /* private + compressed public, curve by OID */ + 0x30, 0x54, 0x02, 0x01, 0x01, 0x04, 0x20, 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, 0xba, + 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, 0xf7, 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, 0x5f, + 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, 0x23, 0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, + 0xa1, 0x24, 0x03, 0x22, 0x00, 0x03, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, + 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, + 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16 + }; + static const unsigned char short_pric_pkcs8[] = { /* private + compressed public, curve by OID, PKCS8 */ + 0x30, 0x64, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, + 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x04, 0x4d, 0x30, 0x4b, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, 0xba, 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, 0xf7, + 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, 0x5f, 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, 0x23, + 0xa1, 0x24, 0x03, 0x22, 0x00, 0x03, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, + 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, + 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16 + }; + static const unsigned char short_pub[] = { /* long public, curve by OID */ + 0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, + 0x81, 0x04, 0x00, 0x0a, 0x03, 0x42, 0x00, 0x04, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, + 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, + 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, + 0xb7, 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, + 0x6e, 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d + }; + static const unsigned char short_pubc[] = { /* compressed public, curve by OID */ + 0x30, 0x36, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, + 0x81, 0x04, 0x00, 0x0a, 0x03, 0x22, 0x00, 0x03, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, + 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, + 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16 + }; + static const unsigned char raw_pri[] = { /* raw private key */ + 0x0c, 0xf1, 0xad, 0x2f, 0x03, 0xf7, 0x91, 0x1b, 0xba, 0x03, 0xcf, 0x23, 0x37, 0xc8, 0xf2, 0xf7, + 0x36, 0xce, 0x65, 0xf1, 0x84, 0x2d, 0x7d, 0x9f, 0x5f, 0x9e, 0x21, 0xd9, 0x5e, 0x49, 0xbd, 0x23 + }; + static const unsigned char raw_pub[] = { /* raw public key - long form */ + 0x04, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, + 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, + 0x16, 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, 0xb7, 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, + 0x62, 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, 0x6e, 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, + 0x4d + }; + static const unsigned char raw_pubc[] = { /* raw public key - compressed form */ + 0x03, 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, + 0xb6, 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, + 0x16 + }; + static const unsigned char x509_cert_long[] = { /* X.509 cert, long pubkey, explicit curve params */ + 0x30, 0x82, 0x02, 0x13, 0x30, 0x82, 0x01, 0xba, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0xaf, 0x14, 0xe3, 0x53, 0x36, 0x06, 0x79, 0x34, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x04, 0x30, 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x20, 0x17, + 0x0d, 0x31, 0x37, 0x31, 0x32, 0x33, 0x30, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x18, 0x0f, + 0x33, 0x30, 0x31, 0x37, 0x30, 0x35, 0x30, 0x32, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x30, + 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x81, 0xf5, 0x30, 0x81, 0xae, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xa2, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, 0x01, 0x00, + 0x04, 0x01, 0x07, 0x04, 0x41, 0x04, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, + 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, + 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x48, 0x3a, 0xda, 0x77, 0x26, 0xa3, 0xc4, 0x65, 0x5d, 0xa4, + 0xfb, 0xfc, 0x0e, 0x11, 0x08, 0xa8, 0xfd, 0x17, 0xb4, 0x48, 0xa6, 0x85, 0x54, 0x19, 0x9c, 0x47, + 0xd0, 0x8f, 0xfb, 0x10, 0xd4, 0xb8, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, + 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, 0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, + 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, + 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, + 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, 0xb7, 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, + 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, 0x6e, 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d, + 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x66, + 0xc9, 0x90, 0x3c, 0x8a, 0x81, 0xa3, 0x1c, 0x20, 0x61, 0xd2, 0xf3, 0xf5, 0xae, 0xa8, 0x85, 0x70, + 0xf9, 0x1f, 0x2c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x66, 0xc9, 0x90, 0x3c, 0x8a, 0x81, 0xa3, 0x1c, 0x20, 0x61, 0xd2, 0xf3, 0xf5, 0xae, 0xa8, 0x85, + 0x70, 0xf9, 0x1f, 0x2c, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x03, 0x47, + 0x00, 0x30, 0x44, 0x02, 0x1f, 0x2a, 0x62, 0x64, 0x05, 0x67, 0xb0, 0x2c, 0xa0, 0xa3, 0xb8, 0x61, + 0x4e, 0x87, 0x06, 0x69, 0xf2, 0xda, 0x78, 0xd6, 0x0e, 0x8d, 0x9b, 0xf1, 0x43, 0x5f, 0xf6, 0x40, + 0x9d, 0x9d, 0xbd, 0xce, 0x02, 0x21, 0x00, 0xe9, 0x6f, 0x79, 0xb4, 0x4a, 0x00, 0xf7, 0xfa, 0x81, + 0x25, 0x29, 0xec, 0x79, 0xb2, 0xfa, 0x86, 0xf8, 0x84, 0xd1, 0x78, 0xe7, 0xf8, 0xfd, 0x76, 0x2d, + 0x4f, 0xfe, 0x02, 0x72, 0xba, 0x6c, 0xca + }; + static const unsigned char x509_cert_longc[] = { /* X.509 cert, compressed pubkey, explicit curve params */ + 0x30, 0x82, 0x01, 0xd3, 0x30, 0x82, 0x01, 0x7a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0x90, 0x5b, 0x48, 0x32, 0x37, 0x4b, 0x72, 0x54, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x04, 0x30, 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x20, 0x17, + 0x0d, 0x31, 0x37, 0x31, 0x32, 0x33, 0x30, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x18, 0x0f, + 0x33, 0x30, 0x31, 0x37, 0x30, 0x35, 0x30, 0x32, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x30, + 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x81, 0xb5, 0x30, 0x81, 0x8e, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0x82, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, + 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, 0x30, 0x06, 0x04, 0x01, 0x00, + 0x04, 0x01, 0x07, 0x04, 0x21, 0x02, 0x79, 0xbe, 0x66, 0x7e, 0xf9, 0xdc, 0xbb, 0xac, 0x55, 0xa0, + 0x62, 0x95, 0xce, 0x87, 0x0b, 0x07, 0x02, 0x9b, 0xfc, 0xdb, 0x2d, 0xce, 0x28, 0xd9, 0x59, 0xf2, + 0x81, 0x5b, 0x16, 0xf8, 0x17, 0x98, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, + 0x3b, 0xbf, 0xd2, 0x5e, 0x8c, 0xd0, 0x36, 0x41, 0x41, 0x02, 0x01, 0x01, 0x03, 0x22, 0x00, 0x03, + 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, + 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, + 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xca, + 0x2a, 0xa1, 0x12, 0x97, 0x96, 0x2c, 0x85, 0xd3, 0x1f, 0xb1, 0x34, 0x7c, 0x26, 0xe9, 0xd6, 0x49, + 0x9f, 0x98, 0xcf, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xca, 0x2a, 0xa1, 0x12, 0x97, 0x96, 0x2c, 0x85, 0xd3, 0x1f, 0xb1, 0x34, 0x7c, 0x26, 0xe9, 0xd6, + 0x49, 0x9f, 0x98, 0xcf, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x03, 0x47, + 0x00, 0x30, 0x44, 0x02, 0x20, 0x24, 0x7a, 0xc1, 0xb4, 0x7d, 0x1c, 0x3c, 0x23, 0xc6, 0xad, 0xea, + 0x04, 0x27, 0x27, 0x65, 0xb8, 0x72, 0x93, 0x46, 0xc9, 0xe9, 0x60, 0x8f, 0xca, 0x96, 0x30, 0x60, + 0xb3, 0x22, 0xf7, 0x3b, 0x01, 0x02, 0x20, 0x48, 0x30, 0x2a, 0x58, 0x18, 0x46, 0xdb, 0x50, 0x3e, + 0xad, 0xc3, 0xca, 0xcd, 0x6d, 0x83, 0xd4, 0xc3, 0xc4, 0xa4, 0x8f, 0x37, 0xc3, 0x1d, 0x83, 0x3c, + 0xd3, 0x1f, 0x8f, 0x38, 0x29, 0x75, 0x2c + }; + static const unsigned char x509_cert_short[] = { /* X.509 cert, long pubkey, curve by OID */ + 0x30, 0x82, 0x01, 0x74, 0x30, 0x82, 0x01, 0x1a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, + 0xbd, 0x81, 0x04, 0x29, 0x43, 0x12, 0x79, 0xce, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x04, 0x30, 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x20, 0x17, + 0x0d, 0x31, 0x37, 0x31, 0x32, 0x33, 0x30, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x18, 0x0f, + 0x33, 0x30, 0x31, 0x37, 0x30, 0x35, 0x30, 0x32, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x30, + 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x03, 0x42, 0x00, 0x04, + 0x2a, 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, + 0x7f, 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, + 0x91, 0xbd, 0xb2, 0xb9, 0x1b, 0x40, 0x10, 0x5a, 0xb7, 0x6c, 0x6e, 0x32, 0x5b, 0xf7, 0x63, 0x62, + 0x94, 0x24, 0x24, 0xdb, 0xec, 0x3f, 0x8b, 0xe5, 0x6e, 0x4b, 0x64, 0x37, 0x31, 0x24, 0x79, 0x4d, + 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x66, + 0xc9, 0x90, 0x3c, 0x8a, 0x81, 0xa3, 0x1c, 0x20, 0x61, 0xd2, 0xf3, 0xf5, 0xae, 0xa8, 0x85, 0x70, + 0xf9, 0x1f, 0x2c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x66, 0xc9, 0x90, 0x3c, 0x8a, 0x81, 0xa3, 0x1c, 0x20, 0x61, 0xd2, 0xf3, 0xf5, 0xae, 0xa8, 0x85, + 0x70, 0xf9, 0x1f, 0x2c, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x03, 0x48, + 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x9b, 0x4e, 0xb2, 0x6a, 0xcc, 0xfa, 0x02, 0x69, 0x22, 0x6a, + 0x32, 0x9c, 0x0c, 0xaa, 0x4c, 0xdf, 0xbb, 0x9b, 0x22, 0xfb, 0xd6, 0xec, 0x5d, 0xf9, 0x87, 0x82, + 0xeb, 0x37, 0xb8, 0x32, 0x7c, 0xd6, 0x02, 0x20, 0x50, 0x8b, 0x9f, 0xc1, 0xa8, 0x4a, 0xff, 0x49, + 0x0d, 0x7e, 0x04, 0x2d, 0x93, 0x3e, 0xdb, 0x30, 0xbc, 0x93, 0xd1, 0x16, 0x1d, 0x99, 0xbd, 0x3f, + 0xfa, 0x2a, 0x6d, 0xe0, 0x2a, 0x83, 0x55, 0x5d + }; + static const unsigned char x509_cert_shortc[] = { /* X.509 cert, compressed pubkey, curve by OID */ + 0x30, 0x82, 0x01, 0x54, 0x30, 0x81, 0xfa, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, + 0x45, 0x77, 0x75, 0x02, 0x95, 0xf7, 0x06, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x04, 0x03, 0x04, 0x30, 0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x20, 0x17, 0x0d, + 0x31, 0x37, 0x31, 0x32, 0x33, 0x30, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x18, 0x0f, 0x33, + 0x30, 0x31, 0x37, 0x30, 0x35, 0x30, 0x32, 0x32, 0x30, 0x33, 0x33, 0x34, 0x31, 0x5a, 0x30, 0x17, + 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x54, 0x65, 0x73, 0x74, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x20, 0x45, 0x43, 0x30, 0x36, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x03, 0x22, 0x00, 0x03, 0x2a, + 0xf9, 0x0b, 0xda, 0xbe, 0x71, 0x66, 0x9e, 0xd1, 0xcf, 0x12, 0xd0, 0x24, 0xaf, 0xba, 0xb6, 0x7f, + 0xfb, 0x96, 0x27, 0x3e, 0x2f, 0xbd, 0x1e, 0xd5, 0xf9, 0x8d, 0x6c, 0x73, 0x9d, 0xc5, 0x16, 0xa3, + 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xca, 0x2a, + 0xa1, 0x12, 0x97, 0x96, 0x2c, 0x85, 0xd3, 0x1f, 0xb1, 0x34, 0x7c, 0x26, 0xe9, 0xd6, 0x49, 0x9f, + 0x98, 0xcf, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xca, + 0x2a, 0xa1, 0x12, 0x97, 0x96, 0x2c, 0x85, 0xd3, 0x1f, 0xb1, 0x34, 0x7c, 0x26, 0xe9, 0xd6, 0x49, + 0x9f, 0x98, 0xcf, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x03, 0x49, 0x00, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xa4, 0xf9, 0x41, 0x2b, 0x4b, 0x56, 0xa5, 0xd4, 0x8c, 0xdf, 0xb0, + 0x14, 0xe3, 0xe7, 0xed, 0xcc, 0xc4, 0x46, 0x42, 0x04, 0xec, 0x15, 0x9f, 0xe1, 0xb2, 0x00, 0x07, + 0x8c, 0xc1, 0xf9, 0x25, 0xed, 0x02, 0x21, 0x00, 0x81, 0xd8, 0xc4, 0x3a, 0x9f, 0xdf, 0xc1, 0x70, + 0x9d, 0x7b, 0x70, 0x3e, 0xf5, 0x7d, 0xa4, 0xfd, 0x3c, 0xc6, 0x49, 0x93, 0xd3, 0x5b, 0xef, 0xc9, + 0xae, 0x97, 0xaf, 0x64, 0x64, 0xf9, 0x69, 0xd8 + }; + + if (ltc_mp.sqrtmod_prime == NULL) return CRYPT_NOP; /* we need compressed points which requires sqrtmod_prime */ + + DO(ecc_import_openssl(short_pub, sizeof(short_pub), &pub)); + DO(ecc_import_openssl(short_pri, sizeof(short_pri), &pri)); + DO(ecc_find_curve("SECP256K1", &cu)); + + /* import - raw keys */ + DO(ecc_set_curve(cu, &key)); + DO(ecc_set_key(raw_pri, sizeof(raw_pri), PK_PRIVATE, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_set_curve(cu, &key)); + DO(ecc_set_key(raw_pub, sizeof(raw_pub), PK_PUBLIC, &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + DO(ecc_set_curve(cu, &key)); + DO(ecc_set_key(raw_pubc, sizeof(raw_pubc), PK_PUBLIC, &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + + /* import - openssl compatible DER format */ + DO(ecc_import_openssl(long_pri, sizeof(long_pri), &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_import_openssl(long_pric, sizeof(long_pric), &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_import_openssl(long_pub, sizeof(long_pub), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + DO(ecc_import_openssl(long_pubc, sizeof(long_pubc), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + DO(ecc_import_openssl(short_pri, sizeof(short_pri), &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_import_openssl(short_pric, sizeof(short_pric), &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_import_openssl(short_pub, sizeof(short_pub), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + DO(ecc_import_openssl(short_pubc, sizeof(short_pubc), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + + /* import - private PKCS8 format - no password */ + DO(ecc_import_pkcs8(long_pri_pkcs8, sizeof(long_pri_pkcs8), NULL, 0, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_import_pkcs8(long_pric_pkcs8, sizeof(long_pric_pkcs8), NULL, 0, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_import_pkcs8(short_pri_pkcs8, sizeof(short_pri_pkcs8), NULL, 0, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + DO(ecc_import_pkcs8(short_pric_pkcs8, sizeof(short_pric_pkcs8), NULL, 0, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); + + /* import - private PKCS8 format - password protected (PBES1 algorithms) */ +#ifdef LTC_MD2 + DO(ecc_import_pkcs8(long_pri_pkcs8_pbe_md2_des, sizeof(long_pri_pkcs8_pbe_md2_des), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#ifdef LTC_MD5 + DO(ecc_import_pkcs8(long_pri_pkcs8_pbe_md5_des, sizeof(long_pri_pkcs8_pbe_md5_des), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#ifdef LTC_SHA1 + DO(ecc_import_pkcs8(long_pri_pkcs8_pbe_sha1_des, sizeof(long_pri_pkcs8_pbe_sha1_des), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_RC2) && defined(LTC_MD2) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbe_md2_rc2_64, sizeof(long_pri_pkcs8_pbe_md2_rc2_64), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_RC2) && defined(LTC_MD5) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbe_md5_rc2_64, sizeof(long_pri_pkcs8_pbe_md5_rc2_64), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_RC2) && defined(LTC_SHA1) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbe_sha1_rc2_64, sizeof(long_pri_pkcs8_pbe_sha1_rc2_64), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif + + /* import - private PKCS8 format - password protected (PBES2 algorithms) */ +#if defined(LTC_RC2) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbkdf2_rc2_cbc, sizeof(long_pri_pkcs8_pbkdf2_rc2_cbc), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_DES) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbkdf2_des_cbc, sizeof(long_pri_pkcs8_pbkdf2_des_cbc), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_DES) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbkdf2_des_ede3_cbc, sizeof(long_pri_pkcs8_pbkdf2_des_ede3_cbc), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_SHA224) && defined(LTC_DES) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbkdf2_sha224_des_ede3_cbc, sizeof(long_pri_pkcs8_pbkdf2_sha224_des_ede3_cbc), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_SHA256) && defined(LTC_DES) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbkdf2_sha256_des_ede3_cbc, sizeof(long_pri_pkcs8_pbkdf2_sha256_des_ede3_cbc), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_SHA384) && defined(LTC_DES) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbkdf2_sha384_des_ede3_cbc, sizeof(long_pri_pkcs8_pbkdf2_sha384_des_ede3_cbc), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif +#if defined(LTC_SHA512) && defined(LTC_DES) + DO(ecc_import_pkcs8(long_pri_pkcs8_pbkdf2_sha512_des_ede3_cbc, sizeof(long_pri_pkcs8_pbkdf2_sha512_des_ede3_cbc), "secret", 6, &key)); + DO(s_ecc_key_cmp(PK_PRIVATE, &pri, &key)); + ecc_free(&key); +#endif + + /* import - X.509 EC certificates */ + DO(ecc_import_x509(x509_cert_long, sizeof(x509_cert_long), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + DO(ecc_import_x509(x509_cert_longc, sizeof(x509_cert_longc), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + DO(ecc_import_x509(x509_cert_short, sizeof(x509_cert_short), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + DO(ecc_import_x509(x509_cert_shortc, sizeof(x509_cert_shortc), &key)); + DO(s_ecc_key_cmp(PK_PUBLIC, &pub, &key)); + ecc_free(&key); + + /* export - openssl compatible DER format */ + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PRIVATE, &pri)); + if (compare_testvector(out, outlen, long_pri, sizeof(long_pri), "e-long_pri", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PRIVATE|PK_COMPRESSED, &pri)); + if (compare_testvector(out, outlen, long_pric, sizeof(long_pric), "e-long_pric", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PUBLIC, &pub)); + if (compare_testvector(out, outlen, long_pub, sizeof(long_pub), "e-long_pub", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PUBLIC|PK_COMPRESSED, &pub)); + if (compare_testvector(out, outlen, long_pubc, sizeof(long_pubc), "e-long_pubc", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PRIVATE|PK_CURVEOID, &pri)); + if (compare_testvector(out, outlen, short_pri, sizeof(short_pri), "e-short_pri", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PRIVATE|PK_CURVEOID|PK_COMPRESSED, &pri)); + if (compare_testvector(out, outlen, short_pric, sizeof(short_pric), "e-short_pric", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PUBLIC|PK_CURVEOID, &pub)); + if (compare_testvector(out, outlen, short_pub, sizeof(short_pub), "e-short_pub", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_export_openssl(out, &outlen, PK_PUBLIC|PK_CURVEOID|PK_COMPRESSED, &pub)); + if (compare_testvector(out, outlen, short_pubc, sizeof(short_pubc), "e-short_pubc", 0)) return CRYPT_ERROR; + + /* export - raw keys */ + outlen = sizeof(out); + DO(ecc_get_key(out, &outlen, PK_PRIVATE, &pri)); + if (compare_testvector(out, outlen, raw_pri, sizeof(raw_pri), "e-raw_pri", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_get_key(out, &outlen, PK_PUBLIC, &pub)); + if (compare_testvector(out, outlen, raw_pub, sizeof(raw_pub), "e-raw_pub", 0)) return CRYPT_ERROR; + outlen = sizeof(out); + DO(ecc_get_key(out, &outlen, PK_PUBLIC|PK_COMPRESSED, &pub)); + if (compare_testvector(out, outlen, raw_pubc, sizeof(raw_pubc), "e-raw_pubc", 0)) return CRYPT_ERROR; + + ecc_free(&pri); + ecc_free(&pub); + return CRYPT_OK; +} + +#ifdef LTC_ECC_SHAMIR +static int s_ecc_test_recovery(void) +{ + int i, recid, stat; + const ltc_ecc_curve* dp; + ecc_key key, privkey, pubkey, reckey; + unsigned char buf[1000]; + unsigned long len; + unsigned char data16[16] = { 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 }; + unsigned char eth_hash[] = { /* Keccak-256 hash of "Hello World" */ + 0x59, 0x2f, 0xa7, 0x43, 0x88, 0x9f, 0xc7, 0xf9, 0x2a, 0xc2, 0xa3, 0x7b, 0xb1, 0xf5, 0xba, 0x1d, + 0xaf, 0x2a, 0x5c, 0x84, 0x74, 0x1c, 0xa0, 0xe0, 0x06, 0x1d, 0x24, 0x3a, 0x2e, 0x67, 0x07, 0xba + }; + unsigned char eth_pubkey[] = { /* Public part of randomly-generated key pair */ + 0x04, + 0xc6, 0x99, 0x5f, 0xdc, 0xf4, 0xf2, 0xda, 0x6e, 0x79, 0xe0, 0x47, 0x12, 0xd3, 0xbe, 0x22, 0xe7, + 0x65, 0xc6, 0xa3, 0x32, 0x89, 0x1b, 0x34, 0xba, 0xc1, 0xb7, 0x01, 0x83, 0xed, 0xdd, 0xf1, 0xcc, + 0xbf, 0x20, 0xdd, 0xcd, 0x05, 0x4e, 0x49, 0xc8, 0xcb, 0x66, 0x6c, 0xb7, 0x71, 0x2f, 0x7e, 0xc1, + 0xd6, 0x1a, 0x4a, 0x42, 0x3d, 0xe5, 0xc2, 0x8d, 0x74, 0x03, 0x81, 0xe7, 0xea, 0xc5, 0x3c, 0x10 + }; + unsigned char eth_sig[] = { /* Signature of eth_hash to be verified against eth_pubkey */ + 0xbd, 0x6d, 0xbb, 0xbe, 0x2d, 0xe7, 0x1d, 0x00, 0xae, 0x18, 0x57, 0x12, 0x1d, 0x63, 0xa5, 0x1b, + 0x0b, 0x42, 0x71, 0xa2, 0x80, 0x49, 0xe0, 0x5c, 0xfa, 0xc8, 0x1a, 0x0d, 0x8a, 0x88, 0x67, 0x56, + 0xf6, 0x67, 0x1b, 0x41, 0x46, 0x09, 0x4e, 0xd0, 0x44, 0x25, 0x18, 0xfd, 0xf4, 0xcd, 0x62, 0xa3, + 0xb7, 0x3c, 0x97, 0x55, 0xfa, 0x69, 0xf8, 0xef, 0xe9, 0xcf, 0x12, 0xaf, 0x48, 0x25, 0xe3, 0xe0, + 0x1b + }; + + /* XXX-FIXME: TFM does not support sqrtmod_prime */ + if (strcmp(ltc_mp.name, "TomsFastMath") == 0) return CRYPT_NOP; + +#ifdef LTC_ECC_SECP256K1 + DO(ecc_find_curve("SECP256K1", &dp)); + + DO(ecc_set_curve(dp, &pubkey)); + DO(ecc_set_key(eth_pubkey, sizeof(eth_pubkey), PK_PUBLIC, &pubkey)); + + DO(ecc_set_curve(dp, &reckey)); + stat = ecc_recover_key(eth_sig, sizeof(eth_sig)-1, eth_hash, sizeof(eth_hash), 0, LTC_ECCSIG_RFC7518, &reckey); + if (stat != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; + DO(s_ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey)); + ecc_free(&reckey); + + DO(ecc_set_curve(dp, &reckey)); + stat = ecc_recover_key(eth_sig, sizeof(eth_sig), eth_hash, sizeof(eth_hash), -1, LTC_ECCSIG_ETH27, &reckey); + if (stat != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; + DO(s_ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey)); + ecc_free(&reckey); + + ecc_free(&pubkey); +#endif + + for (i = 0; i < (int)(sizeof(curvenames)/sizeof(curvenames[0])); i++) { + DO(ecc_find_curve(curvenames[i], &dp)); + + /* generate new key */ + DO(ecc_set_curve(dp, &key)); + DO(ecc_generate_key(&yarrow_prng, find_prng ("yarrow"), &key)); + + /* export private key */ + len = sizeof(buf); + DO(ecc_get_key(buf, &len, PK_PRIVATE, &key)); + ecc_free(&key); + + /* load exported private key */ + DO(ecc_set_curve(dp, &privkey)); + DO(ecc_set_key(buf, len, PK_PRIVATE, &privkey)); + + /* export long public key */ + len = sizeof(buf); + DO(ecc_get_key(buf, &len, PK_PUBLIC, &privkey)); + if (len != 1 + 2 * (unsigned)ecc_get_size(&privkey)) return CRYPT_FAIL_TESTVECTOR; + + /* load exported public key */ + DO(ecc_set_curve(dp, &pubkey)); + DO(ecc_set_key(buf, len, PK_PUBLIC, &pubkey)); + + /* test signature */ + len = sizeof(buf); + recid = 0; + DO(ecc_sign_hash_ex(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), LTC_ECCSIG_RFC7518, &recid, &privkey)); + + /* test verification */ + stat = 0; + DO(ecc_verify_hash_ex(buf, len, data16, 16, LTC_ECCSIG_RFC7518, &stat, &pubkey)); + if (stat != 1) return CRYPT_FAIL_TESTVECTOR; + + /* test recovery */ + DO(ecc_set_curve(dp, &reckey)); + stat = ecc_recover_key(buf, len, data16, 16, recid, LTC_ECCSIG_RFC7518, &reckey); + if (stat != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; + DO(s_ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey)); + + /* cleanup */ + ecc_free(&reckey); + ecc_free(&privkey); + ecc_free(&pubkey); + } + + return CRYPT_OK; +} +#endif + +int ecc_test(void) +{ + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(s_ecc_old_api()); /* up to 1.18 */ + DO(s_ecc_new_api()); + DO(s_ecc_import_export()); + DO(s_ecc_test_mp()); + DO(s_ecc_issue108()); + DO(s_ecc_issue443_447()); +#ifdef LTC_ECC_SHAMIR + DO(s_ecc_test_shamir()); + DO(s_ecc_test_recovery()); +#endif + return CRYPT_OK; +} + +#endif diff --git a/deps/libtomcrypt/tests/ed25519_test.c b/deps/libtomcrypt/tests/ed25519_test.c new file mode 100644 index 0000000..e59f35b --- /dev/null +++ b/deps/libtomcrypt/tests/ed25519_test.c @@ -0,0 +1,428 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_test.h" + +/** + @file ed25519_test.c + Ed25519 tests, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static void xor_shuffle(unsigned char *buf, unsigned long size, unsigned char change) +{ + unsigned long i; + for(i = 0; i < size; i++) + buf[i] ^= change; +} + +static int s_rfc_8410_10_test(void) +{ + const struct { + const char* b64; + int type; + } rfc_8410_10[] = { + /* RFC 8410 - 10.1. Example Ed25519 Public Key */ + { "MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE=", PK_PUBLIC | PK_STD }, + /* Okay this is not from RFC 8410, but a custom generated certificate with Ed25519 Public Key. + * Since RFC 8410 has no testvector for that case, one had to be created. + * ( openssl req -verbose -new -x509 -subj "/CN=Public domain ed25519 self-signed certificate" -days 36525 -key <( openssl genpkey -algorithm ed25519 2>/dev/null | tee /dev/fd/3) | openssl x509 ) 3>&1 + * Thx @vdukhovni + */ + { "MIIBhDCCATagAwIBAgIUHDa8kJUZeCuIhknPJ/wDeBW6gZgwBQYDK2VwMDgxNjA0" + "BgNVBAMMLVB1YmxpYyBkb21haW4gZWQyNTUxOSBzZWxmLXNpZ25lZCBjZXJ0aWZp" + "Y2F0ZTAgFw0xOTA1MjMyMTAxMTZaGA8yMTE5MDUyNDIxMDExNlowODE2MDQGA1UE" + "AwwtUHVibGljIGRvbWFpbiBlZDI1NTE5IHNlbGYtc2lnbmVkIGNlcnRpZmljYXRl" + "MCowBQYDK2VwAyEAUEiKvHT0KHXOtNjIhaImokxbiog+Ki6lcgce05tf9UKjUDBO" + "MB0GA1UdDgQWBBS3fmpWaPK2fNpblEmg4tG4ZHO2BDAfBgNVHSMEGDAWgBS3fmpW" + "aPK2fNpblEmg4tG4ZHO2BDAMBgNVHRMEBTADAQH/MAUGAytlcANBADOnwkj8etmx" + "mTaXUP29RaenxpN8dQoQ4wnnIJwxQxTcVWOt2PlUxCFoB9gs0+YZOzhXnQg4hfqk" + "t/HPExwoZQg=", -2 }, + /* RFC 8410 - 10.3. Examples of Ed25519 Private Key */ + { "MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC", PK_PRIVATE | PK_STD }, + /* RFC 8410 - 10.3. Examples of Ed25519 Private Key with attribute */ + { "MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC" + "oB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrB" + "Z9w7lshQhqowtrbLDFw4rXAxZuE=", -1 }, + /* Another self-created testvector. + * `openssl genpkey -algorithm ed25519 -pass stdin -aes128` + */ + { "MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAiFflnrBOdwjwICCAAw" + "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEMzFYoqiT6gxwFx2EA55MUYEQFD1" + "ZLxPNhm4YAsMZaxu5qpLjiZbkWsTHxURb6WhSW8GAbNbTwxeOaA02sUhJg8rx44/" + "N9PzN2QGzIQ1Yv/vHqQ=", -1 }, + }; + unsigned n; + curve25519_key key; + unsigned char buf[1024]; + char tmp[512]; + unsigned long buflen, tmplen; + for (n = 0; n < sizeof(rfc_8410_10)/sizeof(rfc_8410_10[0]); ++n) { + buflen = sizeof(buf); + DO(base64_decode(rfc_8410_10[n].b64, XSTRLEN(rfc_8410_10[n].b64), buf, &buflen)); + switch (n) { + case 0: + DO(ed25519_import(buf, buflen, &key)); + break; + case 1: + DO(ed25519_import_x509(buf, buflen, &key)); + break; + case 2: + case 3: + DO(ed25519_import_pkcs8(buf, buflen, NULL, 0, &key)); + break; + case 4: + DO(ed25519_import_pkcs8(buf, buflen, "123456", 6, &key)); + break; + default: + return CRYPT_FAIL_TESTVECTOR; + } + zeromem(buf, sizeof(buf)); + if (rfc_8410_10[n].type > 0) { + buflen = sizeof(buf); + DO(ed25519_export(buf, &buflen, rfc_8410_10[n].type, &key)); + tmplen = sizeof(tmp); + DO(base64_encode(buf, buflen, tmp, &tmplen)); + DO(do_compare_testvector(tmp, tmplen, rfc_8410_10[n].b64, XSTRLEN(rfc_8410_10[n].b64), "Ed25519 export-import", n)); + } + } + return CRYPT_OK; +} + +typedef struct { + const char* secret_key; + const char* public_key; + const char* message; + const char* signature; + const char* context; +} rfc_8032_7_t; + +static int s_rfc_8032_7_1_test(void) +{ + const rfc_8032_7_t rfc_8032_7_1[] = { + { + /* SECRET KEY */ + "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", + /* PUBLIC KEY */ + "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", + /* MESSAGE (length 0 bytes) */ + "", + /* SIGNATURE */ + "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e06522490155" + "5fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b", + /* CONTEXT */ + NULL + }, + { + /* SECRET KEY */ + "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", + /* PUBLIC KEY */ + "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", + /* MESSAGE (length 1 byte) */ + "72", + /* SIGNATURE */ + "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da" + "085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00", + /* CONTEXT */ + NULL + }, + { + /* SECRET KEY */ + "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", + /* PUBLIC KEY */ + "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", + /* MESSAGE (length 2 bytes) */ + "af82", + /* SIGNATURE */ + "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac" + "18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a", + /* CONTEXT */ + NULL + }, + { + /* SECRET KEY */ + "f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5", + /* PUBLIC KEY */ + "278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e", + /* MESSAGE (length 1023 bytes) */ + "08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98" + "fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d8" + "79de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d" + "658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc" + "1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4fe" + "ba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e" + "06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbef" + "efd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7" + "aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed1" + "85ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2" + "d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24" + "554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f270" + "88d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc" + "2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b07" + "07e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128ba" + "b27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51a" + "ddd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429e" + "c96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb7" + "51fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c" + "42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8" + "ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34df" + "f7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08" + "d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649" + "de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e4" + "88acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a3" + "2ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e" + "6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5f" + "b93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b5" + "0d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1" + "369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380d" + "b2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c" + "0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0", + /* SIGNATURE */ + "0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350" + "aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03", + /* CONTEXT */ + NULL + }, + { + /* SECRET KEY */ + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", + /* PUBLIC KEY */ + "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", + /* MESSAGE (length 64 bytes) */ + "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" + "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", + /* SIGNATURE */ + "dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b589" + "09351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704", + /* CONTEXT */ + NULL + } + }; + unsigned int n; + unsigned long mlen, slen, plen, siglen, buflen; + unsigned char msg[1024], sec[32], pub[32], sig[64], buf[64]; + curve25519_key key, key2; + int ret; + const int should = 1; + for (n = 0; n < sizeof(rfc_8032_7_1)/sizeof(rfc_8032_7_1[0]); ++n) { + slen = sizeof(sec); + DO(base16_decode(rfc_8032_7_1[n].secret_key, XSTRLEN(rfc_8032_7_1[n].secret_key), sec, &slen)); + plen = sizeof(pub); + DO(base16_decode(rfc_8032_7_1[n].public_key, XSTRLEN(rfc_8032_7_1[n].public_key), pub, &plen)); + mlen = sizeof(msg); + DO(base16_decode(rfc_8032_7_1[n].message, XSTRLEN(rfc_8032_7_1[n].message), msg, &mlen)); + siglen = sizeof(sig); + DO(base16_decode(rfc_8032_7_1[n].signature, XSTRLEN(rfc_8032_7_1[n].signature), sig, &siglen)); + DO(ed25519_import_raw(sec, slen, PK_PRIVATE, &key)); + buflen = sizeof(buf); + DO(ed25519_sign(msg, mlen, buf, &buflen, &key)); + DO(do_compare_testvector(buf, buflen, sig, siglen, "Ed25519 RFC8032 7.1 - sign", n)); + DO(ed25519_verify(msg, mlen, sig, siglen, &ret, &key)); + DO(do_compare_testvector(&ret, sizeof(ret), &should, sizeof(should), "Ed25519 RFC8032 7.1 - verify w/ privkey", n)); + + xor_shuffle(sig, siglen, 0x8u); + DO( ed25519_verify(msg, mlen, sig, siglen, &ret, &key)); + ENSUREX(ret != 1, "ed25519_verify is expected to fail on the modified signature"); + xor_shuffle(msg, mlen, 0xfu); + DO( ed25519_verify(msg, mlen, sig, siglen, &ret, &key)); + ENSUREX(ret != 1, "ed25519_verify is expected to fail on the modified message"); + + plen = sizeof(pub); + DO(base16_decode(rfc_8032_7_1[n].public_key, XSTRLEN(rfc_8032_7_1[n].public_key), pub, &plen)); + mlen = sizeof(msg); + DO(base16_decode(rfc_8032_7_1[n].message, XSTRLEN(rfc_8032_7_1[n].message), msg, &mlen)); + siglen = sizeof(sig); + DO(base16_decode(rfc_8032_7_1[n].signature, XSTRLEN(rfc_8032_7_1[n].signature), sig, &siglen)); + DO(ed25519_import_raw(pub, plen, PK_PUBLIC, &key2)); + DO(ed25519_verify(msg, mlen, sig, siglen, &ret, &key2)); + DO(do_compare_testvector(&ret, sizeof(ret), &should, sizeof(should), "Ed25519 RFC8032 7.1 - verify w/ pubkey", n)); + + zeromem(&key, sizeof(key)); + zeromem(&key2, sizeof(key2)); + } + return CRYPT_OK; +} + +static int s_rfc_8032_7_2_test(void) +{ + const rfc_8032_7_t rfc_8032_7_2[] = { + { + /* SECRET KEY */ + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + /* PUBLIC KEY */ + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + /* MESSAGE (length 16 bytes) */ + "f726936d19c800494e3fdaff20b276a8", + /* SIGNATURE */ + "55a4cc2f70a54e04288c5f4cd1e45a7bb520b36292911876cada7323198dd87a" + "8b36950b95130022907a7fb7c4e9b2d5f6cca685a587b4b21f4b888e4e7edb0d", + /* CONTEXT */ + "666f6f", + }, + { + /* SECRET KEY */ + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + /* PUBLIC KEY */ + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + /* MESSAGE (length 16 bytes) */ + "f726936d19c800494e3fdaff20b276a8", + /* SIGNATURE */ + "fc60d5872fc46b3aa69f8b5b4351d5808f92bcc044606db097abab6dbcb1aee3" + "216c48e8b3b66431b5b186d1d28f8ee15a5ca2df6668346291c2043d4eb3e90d", + /* CONTEXT */ + "626172", + }, + { + /* SECRET KEY */ + "0305334e381af78f141cb666f6199f57bc3495335a256a95bd2a55bf546663f6", + /* PUBLIC KEY */ + "dfc9425e4f968f7f0c29f0259cf5f9aed6851c2bb4ad8bfb860cfee0ab248292", + /* MESSAGE (length 16 bytes) */ + "508e9e6882b979fea900f62adceaca35", + /* SIGNATURE */ + "8b70c1cc8310e1de20ac53ce28ae6e7207f33c3295e03bb5c0732a1d20dc6490" + "8922a8b052cf99b7c4fe107a5abb5b2c4085ae75890d02df26269d8945f84b0b", + /* CONTEXT */ + "666f6f", + }, + { + /* SECRET KEY */ + "ab9c2853ce297ddab85c993b3ae14bcad39b2c682beabc27d6d4eb20711d6560", + /* PUBLIC KEY */ + "0f1d1274943b91415889152e893d80e93275a1fc0b65fd71b4b0dda10ad7d772", + /* MESSAGE (length 16 bytes) */ + "f726936d19c800494e3fdaff20b276a8", + /* SIGNATURE */ + "21655b5f1aa965996b3f97b3c849eafba922a0a62992f73b3d1b73106a84ad85" + "e9b86a7b6005ea868337ff2d20a7f5fbd4cd10b0be49a68da2b2e0dc0ad8960f", + /* CONTEXT */ + "666f6f", + } + }; + + unsigned int n; + unsigned long mlen, slen, plen, siglen, buflen, ctxlen; + unsigned char msg[1024], sec[32], pub[32], sig[64], buf[64], ctx[64]; + curve25519_key key, key2; + int ret; + const int should = 1; + + for (n = 0; n < sizeof(rfc_8032_7_2)/sizeof(rfc_8032_7_2[0]); ++n) { + slen = sizeof(sec); + DO(base16_decode(rfc_8032_7_2[n].secret_key, XSTRLEN(rfc_8032_7_2[n].secret_key), sec, &slen)); + plen = sizeof(pub); + DO(base16_decode(rfc_8032_7_2[n].public_key, XSTRLEN(rfc_8032_7_2[n].public_key), pub, &plen)); + mlen = sizeof(msg); + DO(base16_decode(rfc_8032_7_2[n].message, XSTRLEN(rfc_8032_7_2[n].message), msg, &mlen)); + siglen = sizeof(sig); + DO(base16_decode(rfc_8032_7_2[n].signature, XSTRLEN(rfc_8032_7_2[n].signature), sig, &siglen)); + ctxlen = sizeof(ctx); + DO(base16_decode(rfc_8032_7_2[n].context, XSTRLEN(rfc_8032_7_2[n].context), ctx, &ctxlen)); + buflen = sizeof(buf); + + DO(ed25519_import_raw(sec, slen, PK_PRIVATE, &key)); + DO(ed25519ctx_sign(msg, mlen, buf, &buflen, ctx, ctxlen, &key)); + DO(do_compare_testvector(buf, buflen, sig, siglen, "Ed25519 RFC8032 7.2 - sign", n)); + DO(ed25519ctx_verify(msg, mlen, buf, buflen, ctx, ctxlen, &ret, &key)); + ENSUREX(ret == should, "Ed25519 RFC8032 7.2 - verify w/ privkey"); + + DO(ed25519_import_raw(pub, plen, PK_PUBLIC, &key2)); + DO(ed25519ctx_verify(msg, mlen, sig, siglen, ctx, ctxlen, &ret, &key2)); + ENSUREX(ret == should, "Ed25519 RFC8032 7.2 - verify w/ pubkey"); + + xor_shuffle(buf, buflen, 0x4u); + DO(ed25519ctx_verify(msg, mlen, buf, buflen, ctx, ctxlen, &ret, &key)); + ENSUREX(ret != 1, "ed25519ctx_verify is expected to fail on the modified signature"); + xor_shuffle(msg, mlen, 0x8u); + DO(ed25519ctx_verify(msg, mlen, buf, buflen, ctx, ctxlen, &ret, &key)); + ENSUREX(ret != 1, "ed25519ctx_verify is expected to fail on the modified message"); + + zeromem(&key, sizeof(key)); + zeromem(&key2, sizeof(key2)); + } + + return CRYPT_OK; +} + +static int s_rfc_8032_7_3_test(void) +{ + const rfc_8032_7_t rfc_8032_7_3[] = { + { + /* SECRET KEY */ + "833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42", + /* PUBLIC KEY */ + "ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf", + /* MESSAGE (length 16 bytes) */ + "616263", + /* SIGNATURE */ + "98a70222f0b8121aa9d30f813d683f809e462b469c7ff87639499bb94e6dae41" + "31f85042463c2a355a2003d062adf5aaa10b8c61e636062aaad11c2a26083406", + /* CONTEXT */ + NULL + }, + }; + + unsigned long mlen, slen, plen, siglen, buflen; + unsigned char msg[1024], sec[32], pub[32], sig[64], buf[64]; + curve25519_key key; + int ret; + const int should = 1; + + buflen = sizeof(buf); + slen = sizeof(sec); + DO(base16_decode(rfc_8032_7_3[0].secret_key, XSTRLEN(rfc_8032_7_3[0].secret_key), sec, &slen)); + plen = sizeof(pub); + DO(base16_decode(rfc_8032_7_3[0].public_key, XSTRLEN(rfc_8032_7_3[0].public_key), pub, &plen)); + mlen = sizeof(msg); + DO(base16_decode(rfc_8032_7_3[0].message, XSTRLEN(rfc_8032_7_3[0].message), msg, &mlen)); + siglen = sizeof(sig); + DO(base16_decode(rfc_8032_7_3[0].signature, XSTRLEN(rfc_8032_7_3[0].signature), sig, &siglen)); + + DO(ed25519_import_raw(sec, slen, PK_PRIVATE, &key)); + DO(ed25519ph_sign(msg, mlen, buf, &buflen, NULL, 0, &key)); + DO(do_compare_testvector(buf, buflen, sig, siglen, "Ed25519 RFC8032 7.3 - sign", 0)); + DO(ed25519ph_verify(msg, mlen, buf, buflen, NULL, 0, &ret, &key)); + ENSUREX(ret == should, "Ed25519 RFC8032 7.3 - verify w/ privkey"); + + return CRYPT_OK; +} + +/** + Test the ed25519 system + @return CRYPT_OK if successful +*/ +int ed25519_test(void) +{ + int ret; + curve25519_key key; + + if ((ret = ed25519_make_key(&yarrow_prng, find_prng("yarrow"), &key)) != CRYPT_OK) { + return ret; + } + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + if ((ret = s_rfc_8410_10_test()) != CRYPT_OK) { + return ret; + } + if ((ret = s_rfc_8032_7_1_test()) != CRYPT_OK) { + return ret; + } + if ((ret = s_rfc_8032_7_2_test()) != CRYPT_OK) { + return ret; + } + if ((ret = s_rfc_8032_7_3_test()) != CRYPT_OK) { + return ret; + } + + return ret; +} + +#else + +int ed25519_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/deps/libtomcrypt/tests/file_test.c b/deps/libtomcrypt/tests/file_test.c new file mode 100644 index 0000000..1a05ed1 --- /dev/null +++ b/deps/libtomcrypt/tests/file_test.c @@ -0,0 +1,110 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* test file related functions */ + +#include + +int file_test(void) +{ +#ifdef LTC_NO_FILE + return CRYPT_NOP; +#else + unsigned char key[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; + unsigned char buf[200]; + unsigned long len; +#ifdef CMAKE_SOURCE_DIR +#define FILE_IN_SOURCE_DIR(f) CMAKE_SOURCE_DIR "/" f +#else +#define FILE_IN_SOURCE_DIR(f) f +#endif + const char *fname = FILE_IN_SOURCE_DIR("tests/test.key"); + FILE *in; + int err, isha256, iaes; + + /* expected results */ + unsigned char exp_sha256[32] = { 0x76, 0xEC, 0x7F, 0xAE, 0xBD, 0xC4, 0x2A, 0x4D, 0xE3, 0x5C, 0xA7, 0x00, 0x24, 0xC2, 0xD2, 0x73, + 0xE9, 0xF7, 0x85, 0x6C, 0xA6, 0x16, 0x12, 0xE8, 0x9F, 0x5F, 0x66, 0x35, 0x0B, 0xA8, 0xCF, 0x5F }; + isha256 = find_hash("sha256"); + iaes = find_cipher("aes"); + + len = sizeof(buf); + if ((in = fopen(fname, "rb")) == NULL) return CRYPT_FILE_NOTFOUND; + err = hash_filehandle(isha256, in, buf, &len); + fclose(in); + DO(err); + DO(do_compare_testvector(buf, len, exp_sha256, 32, "hash_filehandle", 1)); + + len = sizeof(buf); + DO(hash_file(isha256, fname, buf, &len)); + DO(do_compare_testvector(buf, len, exp_sha256, 32, "hash_file", 1)); + +#ifdef LTC_HMAC + { + unsigned char exp_hmacsha256[32] = { 0xE4, 0x07, 0x74, 0x95, 0xF1, 0xF8, 0x5B, 0xB5, 0xF1, 0x4F, 0x7D, 0x4F, 0x59, 0x8E, 0x4B, 0xBC, + 0x8F, 0x68, 0xCF, 0xBA, 0x2E, 0xAD, 0xC4, 0x63, 0x9D, 0x7F, 0x02, 0x99, 0x8C, 0x08, 0xAC, 0xC0 }; + len = sizeof(buf); + DO(hmac_file(isha256, fname, key, 32, buf, &len)); + DO(do_compare_testvector(buf, len, exp_hmacsha256, 32, "hmac_file", 1)); + } +#endif +#ifdef LTC_OMAC + { + unsigned char exp_omacaes[16] = { 0x50, 0xB4, 0x6C, 0x62, 0xE9, 0xCA, 0x48, 0xFC, 0x38, 0x8D, 0xF4, 0xA2, 0x7D, 0x6A, 0x1E, 0xD8 }; + len = sizeof(buf); + DO(omac_file(iaes, key, 32, fname, buf, &len)); + DO(do_compare_testvector(buf, len, exp_omacaes, 16, "omac_file", 1)); + } +#endif +#ifdef LTC_PMAC + { + unsigned char exp_pmacaes[16] = { 0x7D, 0x65, 0xF0, 0x75, 0x4F, 0x8D, 0xE2, 0xB0, 0xE4, 0xFA, 0x54, 0x4E, 0x45, 0x01, 0x36, 0x1B }; + len = sizeof(buf); + DO(pmac_file(iaes, key, 32, fname, buf, &len)); + DO(do_compare_testvector(buf, len, exp_pmacaes, 16, "pmac_file", 1)); + } +#endif +#ifdef LTC_XCBC + { + unsigned char exp_xcbcaes[16] = { 0x9C, 0x73, 0xA2, 0xD7, 0x90, 0xA5, 0x86, 0x25, 0x4D, 0x3C, 0x8A, 0x6A, 0x24, 0x6D, 0xD1, 0xAB }; + len = sizeof(buf); + DO(xcbc_file(iaes, key, 32, fname, buf, &len)); + DO(do_compare_testvector(buf, len, exp_xcbcaes, 16, "xcbc_file", 1)); + } +#endif +#ifdef LTC_F9_MODE + { + unsigned char exp_f9aes[16] = { 0x6B, 0x6A, 0x18, 0x34, 0x13, 0x8E, 0x01, 0xEF, 0x33, 0x8E, 0x7A, 0x3F, 0x5B, 0x9A, 0xA6, 0x7A }; + len = sizeof(buf); + DO(f9_file(iaes, key, 32, fname, buf, &len)); + DO(do_compare_testvector(buf, len, exp_f9aes, 16, "f9_file", 1)); + } +#endif +#ifdef LTC_POLY1305 + { + unsigned char exp_poly1305[16] = { 0xD0, 0xC7, 0xFB, 0x13, 0xA8, 0x87, 0x84, 0x23, 0x21, 0xCC, 0xA9, 0x43, 0x81, 0x18, 0x75, 0xBE }; + len = sizeof(buf); + DO(poly1305_file(fname, key, 32, buf, &len)); + DO(do_compare_testvector(buf, len, exp_poly1305, 16, "poly1305_file", 1)); + } +#endif +#ifdef LTC_BLAKE2SMAC + { + unsigned char exp_blake2smac[16] = { 0x4f, 0x94, 0x45, 0x15, 0xcd, 0xd1, 0xca, 0x02, 0x1a, 0x0c, 0x7a, 0xe4, 0x6d, 0x2f, 0xe8, 0xb3 }; + len = 16; + DO(blake2smac_file(fname, key, 32, buf, &len)); + DO(do_compare_testvector(buf, len, exp_blake2smac, 16, "exp_blake2smac_file", 1)); + } +#endif +#ifdef LTC_BLAKE2BMAC + { + unsigned char exp_blake2bmac[16] = { 0xdf, 0x0e, 0x7a, 0xab, 0x96, 0x6b, 0x75, 0x4e, 0x52, 0x6a, 0x43, 0x96, 0xbd, 0xef, 0xab, 0x44 }; + len = 16; + DO(blake2bmac_file(fname, key, 32, buf, &len)); + DO(do_compare_testvector(buf, len, exp_blake2bmac, 16, "exp_blake2bmac_file", 1)); + } +#endif + + return CRYPT_OK; +#endif +} diff --git a/deps/libtomcrypt/tests/mac_test.c b/deps/libtomcrypt/tests/mac_test.c new file mode 100644 index 0000000..0121993 --- /dev/null +++ b/deps/libtomcrypt/tests/mac_test.c @@ -0,0 +1,54 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* test pmac/omac/hmac */ +#include + +int mac_test(void) +{ +#ifdef LTC_HMAC + DO(hmac_test()); +#endif +#ifdef LTC_PMAC + DO(pmac_test()); +#endif +#ifdef LTC_OMAC + DO(omac_test()); +#endif +#ifdef LTC_XCBC + DO(xcbc_test()); +#endif +#ifdef LTC_F9_MODE + DO(f9_test()); +#endif +#ifdef LTC_EAX_MODE + DO(eax_test()); +#endif +#ifdef LTC_OCB_MODE + DO(ocb_test()); +#endif +#ifdef LTC_OCB3_MODE + DO(ocb3_test()); +#endif +#ifdef LTC_CCM_MODE + DO(ccm_test()); +#endif +#ifdef LTC_GCM_MODE + DO(gcm_test()); +#endif +#ifdef LTC_PELICAN + DO(pelican_test()); +#endif +#ifdef LTC_POLY1305 + DO(poly1305_test()); +#endif +#ifdef LTC_CHACHA20POLY1305_MODE + DO(chacha20poly1305_test()); +#endif +#ifdef LTC_BLAKE2SMAC + DO(blake2smac_test()); +#endif +#ifdef LTC_BLAKE2BMAC + DO(blake2bmac_test()); +#endif + return 0; +} diff --git a/deps/libtomcrypt/tests/misc_test.c b/deps/libtomcrypt/tests/misc_test.c new file mode 100644 index 0000000..cf5cd21 --- /dev/null +++ b/deps/libtomcrypt/tests/misc_test.c @@ -0,0 +1,39 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +int misc_test(void) +{ +#ifdef LTC_BCRYPT + DO(bcrypt_test()); +#endif +#ifdef LTC_HKDF + DO(hkdf_test()); +#endif +#ifdef LTC_PKCS_5 + DO(pkcs_5_test()); +#endif +#ifdef LTC_PADDING + DO(padding_test()); +#endif +#ifdef LTC_BASE64 + DO(base64_test()); +#endif +#ifdef LTC_BASE32 + DO(base32_test()); +#endif +#ifdef LTC_BASE16 + DO(base16_test()); +#endif +#ifdef LTC_ADLER32 + DO(adler32_test()); +#endif +#ifdef LTC_CRC32 + DO(crc32_test()); +#endif +#ifdef LTC_SSH + ssh_test(); +#endif + no_null_termination_check_test(); + return 0; +} diff --git a/deps/libtomcrypt/tests/modes_test.c b/deps/libtomcrypt/tests/modes_test.c new file mode 100644 index 0000000..7b672a5 --- /dev/null +++ b/deps/libtomcrypt/tests/modes_test.c @@ -0,0 +1,120 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* test CFB/OFB/CBC modes */ +#include + +int modes_test(void) +{ + int ret = CRYPT_NOP; +#ifdef LTC_CBC_MODE + symmetric_CBC cbc; +#endif +#ifdef LTC_CFB_MODE + symmetric_CFB cfb; +#endif +#ifdef LTC_OFB_MODE + symmetric_OFB ofb; +#endif +#if defined(LTC_CBC_MODE) || defined(LTC_CFB_MODE) || defined(LTC_OFB_MODE) + unsigned char pt[64], ct[64], tmp[64], key[16], iv[16], iv2[16]; + int cipher_idx; + unsigned long l; + + /* make a random pt, key and iv */ + ENSURE(yarrow_read(pt, 64, &yarrow_prng) == 64); + ENSURE(yarrow_read(key, 16, &yarrow_prng) == 16); + ENSURE(yarrow_read(iv, 16, &yarrow_prng) == 16); + + /* get idx of AES handy */ + cipher_idx = find_cipher("aes"); + if (cipher_idx == -1) { + fprintf(stderr, "test requires AES"); + return 1; + } +#endif + +#ifdef LTC_F8_MODE + DO(ret = f8_test_mode()); +#endif + +#ifdef LTC_LRW_MODE + DO(ret = lrw_test()); +#endif + +#ifdef LTC_CBC_MODE + /* test CBC mode */ + /* encode the block */ + DO(ret = cbc_start(cipher_idx, iv, key, 16, 0, &cbc)); + l = sizeof(iv2); + DO(ret = cbc_getiv(iv2, &l, &cbc)); + if (l != 16 || memcmp(iv2, iv, 16)) { + fprintf(stderr, "cbc_getiv failed"); + return 1; + } + DO(ret = cbc_encrypt(pt, ct, 64, &cbc)); + + /* decode the block */ + DO(ret = cbc_setiv(iv2, l, &cbc)); + zeromem(tmp, sizeof(tmp)); + DO(ret = cbc_decrypt(ct, tmp, 64, &cbc)); + if (memcmp(tmp, pt, 64) != 0) { + fprintf(stderr, "CBC failed"); + return 1; + } +#endif + +#ifdef LTC_CFB_MODE + /* test CFB mode */ + /* encode the block */ + DO(ret = cfb_start(cipher_idx, iv, key, 16, 0, &cfb)); + l = sizeof(iv2); + DO(ret = cfb_getiv(iv2, &l, &cfb)); + /* note we don't memcmp iv2/iv since cfb_start processes the IV for the first block */ + if (l != 16) { + fprintf(stderr, "cfb_getiv failed"); + return 1; + } + DO(ret = cfb_encrypt(pt, ct, 64, &cfb)); + + /* decode the block */ + DO(ret = cfb_setiv(iv, l, &cfb)); + zeromem(tmp, sizeof(tmp)); + DO(ret = cfb_decrypt(ct, tmp, 64, &cfb)); + if (memcmp(tmp, pt, 64) != 0) { + fprintf(stderr, "CFB failed"); + return 1; + } +#endif + +#ifdef LTC_OFB_MODE + /* test OFB mode */ + /* encode the block */ + DO(ret = ofb_start(cipher_idx, iv, key, 16, 0, &ofb)); + l = sizeof(iv2); + DO(ret = ofb_getiv(iv2, &l, &ofb)); + if (l != 16 || memcmp(iv2, iv, 16)) { + fprintf(stderr, "ofb_getiv failed"); + return 1; + } + DO(ret = ofb_encrypt(pt, ct, 64, &ofb)); + + /* decode the block */ + DO(ret = ofb_setiv(iv2, l, &ofb)); + zeromem(tmp, sizeof(tmp)); + DO(ret = ofb_decrypt(ct, tmp, 64, &ofb)); + if (memcmp(tmp, pt, 64) != 0) { + fprintf(stderr, "OFB failed"); + return 1; + } +#endif + +#if defined(LTC_CTR_MODE) && defined(LTC_RIJNDAEL) + DO(ret = ctr_test()); +#endif + +#ifdef LTC_XTS_MODE + DO(ret = xts_test()); +#endif + + return 0; +} diff --git a/deps/libtomcrypt/tests/mpi_test.c b/deps/libtomcrypt/tests/mpi_test.c new file mode 100644 index 0000000..5e1fff9 --- /dev/null +++ b/deps/libtomcrypt/tests/mpi_test.c @@ -0,0 +1,144 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_MPI) +static int s_radix_to_bin_test(void) +{ + /* RADIX 16 */ + const char ghex[] = "2"; + const char phex[] = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22" + "514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E8603" + "9B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF"; + const char xhex[] = "A6681ADC386CE944C3DED9A7301DCC9C518250E3EDB62F959198F8DC0057DD6FB57ABAFD788198B1"; + const char yhex[] = "39046632C834418DFA07B3091538B614D1FB5DBB785C0FBEA3B98B295BC0CD076A88D9452141A269" + "E8BAEB1DD654EBA03A5705318D129754CDF4003A8C399240FBB8F162490F6F0DC70E414B6FEE8808" + "6AFAA48E9F3A248EDC093452663D34E0E809D4F6BADBB36F80B6813EBF7C3281B862209E5604BDEA" + "8B8F5F7BFDC3EEB7ADB73048289BCEA0F5A5CDEE7DF91CD1F0BA632F06DBE9BA7EF014B84B02D497" + "CA7D0C60F734752A649DA496946B4E531B30D9F82EDD855636C0B0F2AE232E4186454E8887BB423E" + "32A5A2495EACBA99620ACD03A38345EBB6735E62330A8EE9AA6C8370410F5CD45AF37EE90A0DA95B" + "E96FC939E88FE0BD2CD09FC8F524208C"; + /* RADIX 47 */ + const char gr47[] = "2"; + const char pr47[] = "F27Mg1SadOFIRbDOJ5dHgHiVF02Z1LHHQ6G5SLG2U8aTdfH1ETk4GARRE7WW99dBUBLb9e2OHFIaSM1A" + "ag2LNNjgYa9I9CjQGJihL3J7A2SGQe8j5Ch8EHMj5jVbAYDiQKhhPhM6Hc56fKS40GUfJkGO7KJ6EXZQ" + "VgbSa2AkPC65F91g0PaYie8AGNVaFKaV9HOQf3ia1iW4i6eCOB9CcBbH7TbQij8AEgjZ0VRBcLKc6UYO" + "1Zc3I2Jc0h1H2HBEH8ONI3OYBbaPV6XhAd8WCc60D0RDBU3H9U7cWL28a0c90XNO0dh5RXEFBbUCE2ZG" + "gh9XQSVIHkVbFIS5F5IGVOkiWAVc9i8BHB2V0UbGW6UdRTZVV"; + const char xr47[] = "6bhO7O9NWFRgEMjdU0Y5POj3c1JP15MYEdIg3FO1PEjUY2aGYNSXcaF01R"; + const char yr47[] = "3GNPNWEYfKML1cIbI7Cc1Z0O7aQLJgB734dO2i56LLYDdI4gHYk2GAbQH2WI97hNeC7dj3fPEH8I9gV9" + "U323AXj1AJXbFPFIHGOTdC29QUUeH2SSc6NWhfQDDXd5Q5iXCKEAUGX3SKcNFIfVOYJgZCLjfHYQdgOQ" + "GCjKNgbEV7Hj34MU3b79iANX2DbMYfb9iGi78BWH2HYAd7IAhk7U0OYGHKJX1bIUUj1KBLhAUg46GaER" + "G9W3ARMfBCj6kSdDF9TdkWAjWTDj722IeVJERC4bKU2VDFG20kDhCMF985efD1SS8DfXcdCHF1kDUkSA" + "884FHYiFEPkaagQOBQaN9BNaEHNbbd002DCIIX5eMP4HgPJPF"; + /* RADIX 64 */ + const char gr64[] = "2"; + const char pr64[] = "3//////////yaFsg8XQC8qnCPYYu3S7D4f0au8YcVCT08BlgOx4viYKKe8UOuq1DtlbHcppJf36p0h2c" + "toNnGtJ+4rRMrHmaNaXRLsObv+nlHCGkccD+rh2/zSjlG6j+tkE6lxMecVfQwV915yIn/cIIXcKUpaMp" + "t207oueME/1PZQI3OSLTEQQHO/gFqapr+3PLqZtAEjbXnYyrOWXLAxdjKf1t2Mbcrd33LEIhoO1F5qR0" + "ZA625yCf1UHYuspZlZddSi60w60vidWwBi1wAFjSLTy6zCKidUAylsbLWN63cLINpgbMhb5T8c69Zw1H" + "0LSevQYgogQF//////////"; + const char xr64[] = "2cQ1hSE6pfHCFUsQSm7SoSKO9Gu+ssBvMHcFZS05VTRxLwklruWPYn"; + const char yr64[] = "v16Ooo3H1ZVe7imaLEBOKqVjTktXS3xwZkOifMy3D1sg8sKKXGQ9fwBhh7TPKww0wLmKnZHANLCtq03g" + "CEP90+xZnOaaFRmt73a5BR+w826hwf8wVEYIEt0aqKcOzDE3e2TJskjkpRu2sWJw/V3A1k68WdbO4lUg" + "BZrzx/SFkjwstC4WecywWzQNDxdtv7D7mkcCl1jlfkdxm5BXB0jINodqCOFSqTIfadQIMb6jEKnimsVW" + "ktOLMDi2myguZBa66HKw8Xxj2FZAbeabUhBgPOWhD0wE3HUksSrvYCmgEwQfiWt113rpKMlD+wGeDgLl" + "fRyavw8/WlIpGdyZr922C"; + /* RADIX 256 */ + const unsigned char gbin[] = { 0x02 }; + const unsigned char pbin[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + const unsigned char xbin[] = { + 0xA6, 0x68, 0x1A, 0xDC, 0x38, 0x6C, 0xE9, 0x44, 0xC3, 0xDE, 0xD9, 0xA7, 0x30, 0x1D, 0xCC, 0x9C, + 0x51, 0x82, 0x50, 0xE3, 0xED, 0xB6, 0x2F, 0x95, 0x91, 0x98, 0xF8, 0xDC, 0x00, 0x57, 0xDD, 0x6F, + 0xB5, 0x7A, 0xBA, 0xFD, 0x78, 0x81, 0x98, 0xB1 + }; + const unsigned char ybin[] = { + 0x39, 0x04, 0x66, 0x32, 0xC8, 0x34, 0x41, 0x8D, 0xFA, 0x07, 0xB3, 0x09, 0x15, 0x38, 0xB6, 0x14, + 0xD1, 0xFB, 0x5D, 0xBB, 0x78, 0x5C, 0x0F, 0xBE, 0xA3, 0xB9, 0x8B, 0x29, 0x5B, 0xC0, 0xCD, 0x07, + 0x6A, 0x88, 0xD9, 0x45, 0x21, 0x41, 0xA2, 0x69, 0xE8, 0xBA, 0xEB, 0x1D, 0xD6, 0x54, 0xEB, 0xA0, + 0x3A, 0x57, 0x05, 0x31, 0x8D, 0x12, 0x97, 0x54, 0xCD, 0xF4, 0x00, 0x3A, 0x8C, 0x39, 0x92, 0x40, + 0xFB, 0xB8, 0xF1, 0x62, 0x49, 0x0F, 0x6F, 0x0D, 0xC7, 0x0E, 0x41, 0x4B, 0x6F, 0xEE, 0x88, 0x08, + 0x6A, 0xFA, 0xA4, 0x8E, 0x9F, 0x3A, 0x24, 0x8E, 0xDC, 0x09, 0x34, 0x52, 0x66, 0x3D, 0x34, 0xE0, + 0xE8, 0x09, 0xD4, 0xF6, 0xBA, 0xDB, 0xB3, 0x6F, 0x80, 0xB6, 0x81, 0x3E, 0xBF, 0x7C, 0x32, 0x81, + 0xB8, 0x62, 0x20, 0x9E, 0x56, 0x04, 0xBD, 0xEA, 0x8B, 0x8F, 0x5F, 0x7B, 0xFD, 0xC3, 0xEE, 0xB7, + 0xAD, 0xB7, 0x30, 0x48, 0x28, 0x9B, 0xCE, 0xA0, 0xF5, 0xA5, 0xCD, 0xEE, 0x7D, 0xF9, 0x1C, 0xD1, + 0xF0, 0xBA, 0x63, 0x2F, 0x06, 0xDB, 0xE9, 0xBA, 0x7E, 0xF0, 0x14, 0xB8, 0x4B, 0x02, 0xD4, 0x97, + 0xCA, 0x7D, 0x0C, 0x60, 0xF7, 0x34, 0x75, 0x2A, 0x64, 0x9D, 0xA4, 0x96, 0x94, 0x6B, 0x4E, 0x53, + 0x1B, 0x30, 0xD9, 0xF8, 0x2E, 0xDD, 0x85, 0x56, 0x36, 0xC0, 0xB0, 0xF2, 0xAE, 0x23, 0x2E, 0x41, + 0x86, 0x45, 0x4E, 0x88, 0x87, 0xBB, 0x42, 0x3E, 0x32, 0xA5, 0xA2, 0x49, 0x5E, 0xAC, 0xBA, 0x99, + 0x62, 0x0A, 0xCD, 0x03, 0xA3, 0x83, 0x45, 0xEB, 0xB6, 0x73, 0x5E, 0x62, 0x33, 0x0A, 0x8E, 0xE9, + 0xAA, 0x6C, 0x83, 0x70, 0x41, 0x0F, 0x5C, 0xD4, 0x5A, 0xF3, 0x7E, 0xE9, 0x0A, 0x0D, 0xA9, 0x5B, + 0xE9, 0x6F, 0xC9, 0x39, 0xE8, 0x8F, 0xE0, 0xBD, 0x2C, 0xD0, 0x9F, 0xC8, 0xF5, 0x24, 0x20, 0x8C + }; + +#define MPI_TEST(n) (n), sizeof(n) +#define MPI_TESTSET(t) MPI_TEST(g ## t), MPI_TEST(p ## t), MPI_TEST(x ## t), MPI_TEST(y ## t) + struct { + int radix; + const void* g; int glen; + const void* p; int plen; + const void* x; int xlen; + const void* y; int ylen; + } test[4] = { + /* ground-truth values in binary format */ + { 256, MPI_TESTSET(bin) }, + /* test-cases in different radices */ + { 16, MPI_TESTSET(hex) }, + { 47, MPI_TESTSET(r47) }, + { 64, MPI_TESTSET(r64) }, + }; +#undef MPI_TESTSET +#undef MPI_TEST + int i, j; + unsigned char key_parts[4][256]; + unsigned long key_lens[4]; + + for (i = 1; i < 4; i++) { + for (j = 0; j < 4; ++j) { + key_lens[j] = sizeof(key_parts[j]); + } + DO(radix_to_bin(test[i].x, test[i].radix, key_parts[0], &key_lens[0])); + DO(radix_to_bin(test[i].y, test[i].radix, key_parts[1], &key_lens[1])); + DO(radix_to_bin(test[i].p, test[i].radix, key_parts[2], &key_lens[2])); + DO(radix_to_bin(test[i].g, test[i].radix, key_parts[3], &key_lens[3])); + + DO(do_compare_testvector(key_parts[0], key_lens[0], test[0].x, test[0].xlen, "radix_to_bin(x)", i)); + DO(do_compare_testvector(key_parts[1], key_lens[1], test[0].y, test[0].ylen, "radix_to_bin(y)", i)); + DO(do_compare_testvector(key_parts[2], key_lens[2], test[0].p, test[0].plen, "radix_to_bin(p)", i)); + DO(do_compare_testvector(key_parts[3], key_lens[3], test[0].g, test[0].glen, "radix_to_bin(g)", i)); + } + return CRYPT_OK; +} + +int mpi_test(void) +{ + if (ltc_mp.name == NULL) return CRYPT_NOP; + return s_radix_to_bin_test(); +} +#else +int mpi_test(void) +{ + return CRYPT_NOP; +} +#endif diff --git a/deps/libtomcrypt/tests/multi_test.c b/deps/libtomcrypt/tests/multi_test.c new file mode 100644 index 0000000..dc46498 --- /dev/null +++ b/deps/libtomcrypt/tests/multi_test.c @@ -0,0 +1,236 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* test the multi helpers... */ +#include + +int multi_test(void) +{ + unsigned char key[32] = { 0 }; + unsigned char buf[2][MAXBLOCKSIZE]; + unsigned long len, len2; + +/* register algos */ + register_hash(&sha256_desc); + register_cipher(&aes_desc); + +/* HASH testing */ + len = sizeof(buf[0]); +#if defined(ENDIAN_32BITWORD) || defined(_WIN32) + len2 = 0x80000000UL; +#else + /* Check against the max. input limit of SHA-1 as of RFC8017 */ + len2 = 0x1ULL << 61; +#endif + SHOULD_FAIL_WITH(hash_memory(find_hash("sha256"), buf[0], len2, buf[0], &len), CRYPT_HASH_OVERFLOW); + + len = sizeof(buf[0]); + hash_memory(find_hash("sha256"), (unsigned char*)"hello", 5, buf[0], &len); + len2 = sizeof(buf[0]); + hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"hello", 5, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + +#ifdef LTC_HMAC + len = sizeof(buf[0]); + hmac_memory(find_hash("sha256"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); + len2 = sizeof(buf[0]); + hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + +#ifdef LTC_OMAC + len = sizeof(buf[0]); + omac_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); + len2 = sizeof(buf[0]); + omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + +#ifdef LTC_PMAC + len = sizeof(buf[0]); + pmac_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); + len2 = sizeof(buf[0]); + pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + +#ifdef LTC_XCBC + len = sizeof(buf[0]); + xcbc_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); + len2 = sizeof(buf[0]); + xcbc_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + xcbc_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + xcbc_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + +#ifdef LTC_F9 + len = sizeof(buf[0]); + f9_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); + len2 = sizeof(buf[0]); + f9_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + f9_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + f9_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + +#ifdef LTC_PELICAN + /* TODO: there is no pelican_memory_multi(..) */ +#endif + +#ifdef LTC_POLY1305 + len = sizeof(buf[0]); + poly1305_memory(key, 32, (unsigned char*)"hello", 5, buf[0], &len); + len2 = sizeof(buf[0]); + poly1305_memory_multi(key, 32, buf[1], &len2, (unsigned char*)"hello", 5, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + poly1305_memory_multi(key, 32, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = sizeof(buf[0]); + poly1305_memory_multi(key, 32, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + +#ifdef LTC_BLAKE2SMAC + len = 32; + blake2smac_memory(key, 16, (unsigned char*)"hello", 5, buf[0], &len); + len2 = 32; + blake2smac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"hello", 5, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = 32; + blake2smac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = 32; + blake2smac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + +#ifdef LTC_BLAKE2BMAC + len = 64; + blake2bmac_memory(key, 16, (unsigned char*)"hello", 5, buf[0], &len); + len2 = 64; + blake2bmac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"hello", 5, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = 64; + blake2bmac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } + len2 = 64; + blake2bmac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, LTC_NULL); + if (len != len2 || memcmp(buf[0], buf[1], len)) { + printf("Failed: %d %lu %lu\n", __LINE__, len, len2); + return CRYPT_FAIL_TESTVECTOR; + } +#endif + + return CRYPT_OK; +} diff --git a/deps/libtomcrypt/tests/no_null_termination_check_test.c b/deps/libtomcrypt/tests/no_null_termination_check_test.c new file mode 100644 index 0000000..329366c --- /dev/null +++ b/deps/libtomcrypt/tests/no_null_termination_check_test.c @@ -0,0 +1,12 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#define LTC_NO_NULL_TERMINATION_CHECK +#include "tomcrypt.h" + +#define NNTCT_NULL ((void *)0) + +int no_null_termination_check_test(void) +{ + return crypt_fsa(NNTCT_NULL, NNTCT_NULL, NNTCT_NULL, NNTCT_NULL, NNTCT_NULL, NNTCT_NULL, 0); +} diff --git a/deps/libtomcrypt/tests/no_prng.c b/deps/libtomcrypt/tests/no_prng.c new file mode 100644 index 0000000..81d1adb --- /dev/null +++ b/deps/libtomcrypt/tests/no_prng.c @@ -0,0 +1,182 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt.h" +#include "tomcrypt_test.h" + +/** + @file no_prng.c + NO PRNG, Steffen Jaeckel +*/ + +#ifdef LTC_PKCS_1 + +typedef struct +{ + struct ltc_prng_descriptor desc; + char name[64]; + unsigned char entropy[1024]; + unsigned long len; + unsigned long offset; +} no_prng_desc_t; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +static int no_prng_start(prng_state *prng) +{ + no_prng_desc_t *no_prng = (no_prng_desc_t*) prng; + LTC_ARGCHK(no_prng != NULL); + LTC_ARGCHK(no_prng->name == (char*)no_prng + offsetof(no_prng_desc_t, name)); + no_prng->len = 0; + no_prng->offset = 0; + + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +static int no_prng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + no_prng_desc_t *no_prng = (no_prng_desc_t*) prng; + LTC_ARGCHK(no_prng != NULL); + LTC_ARGCHK(no_prng->name == (char*)no_prng + offsetof(no_prng_desc_t, name)); + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen <= sizeof(no_prng->entropy)); + + no_prng->len = MIN(inlen, sizeof(no_prng->entropy)); + memcpy(no_prng->entropy, in, no_prng->len); + no_prng->offset = 0; + + return CRYPT_OK; + +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +static int no_prng_ready(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + + return CRYPT_OK; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +static unsigned long no_prng_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + no_prng_desc_t *no_prng = (no_prng_desc_t*) prng; + LTC_ARGCHK(no_prng != NULL); + LTC_ARGCHK(no_prng->name == (char*)no_prng + offsetof(no_prng_desc_t, name)); + LTC_ARGCHK(out != NULL); + + outlen = MIN(outlen, no_prng->len - no_prng->offset); + memcpy(out, &no_prng->entropy[no_prng->offset], outlen); + no_prng->offset += outlen; + + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +static int no_prng_done(prng_state *prng) +{ + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +static int no_prng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_UNUSED_PARAM(out); + LTC_UNUSED_PARAM(outlen); + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +static int no_prng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + LTC_UNUSED_PARAM(in); + LTC_UNUSED_PARAM(inlen); + LTC_UNUSED_PARAM(prng); + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +static int no_prng_test(void) +{ + return CRYPT_OK; +} + +static const struct ltc_prng_descriptor no_prng_desc = +{ + NULL, 0, + &no_prng_start, + &no_prng_add_entropy, + &no_prng_ready, + &no_prng_read, + &no_prng_done, + &no_prng_export, + &no_prng_import, + &no_prng_test +}; + +struct ltc_prng_descriptor* no_prng_desc_get(void) +{ + int ret; + no_prng_desc_t* no_prng = XMALLOC(sizeof(*no_prng)); + if (no_prng == NULL) return NULL; + XMEMCPY(&no_prng->desc, &no_prng_desc, sizeof(no_prng_desc)); + ret = snprintf(no_prng->name, sizeof(no_prng->name), "no_prng@%p", no_prng); + if((ret >= (int)sizeof(no_prng->name)) || (ret == -1)) { + XFREE(no_prng); + return NULL; + } + no_prng->desc.name = no_prng->name; + return &no_prng->desc; +} + +void no_prng_desc_free(struct ltc_prng_descriptor* prng) +{ + no_prng_desc_t *no_prng = (no_prng_desc_t*) prng; + LTC_ARGCHKVD(no_prng != NULL); + LTC_ARGCHKVD(no_prng->name == (char*)no_prng + offsetof(no_prng_desc_t, name)); + XFREE(no_prng); +} + +#endif + diff --git a/deps/libtomcrypt/tests/padding_test.c b/deps/libtomcrypt/tests/padding_test.c new file mode 100644 index 0000000..b111cc8 --- /dev/null +++ b/deps/libtomcrypt/tests/padding_test.c @@ -0,0 +1,220 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include + +#ifdef LTC_PADDING + +typedef struct padding_testcase_ padding_testcase; + +typedef int (*cmp_padding_testcase)(const padding_testcase*, const unsigned char*, unsigned long); + +struct padding_testcase_ { + unsigned long is, should, max, mode; + const char* name; + cmp_padding_testcase cmp; +}; + +#define EQ(a, b) s_eq((a), (b), #a, #b) + +static int s_eq(unsigned long a, unsigned long b, const char* s_a, const char* s_b) +{ + if (a == b) return CRYPT_OK; +#if defined(LTC_TEST) && defined(LTC_TEST_DBG) + else fprintf(stderr, "'%s == %s' failed, %lu is not equal to %lu\n", s_a, s_b, a, b); +#else + LTC_UNUSED_PARAM(s_a); + LTC_UNUSED_PARAM(s_b); +#endif + return CRYPT_FAIL_TESTVECTOR; +} + +static int s_cmp_pkcs7(const padding_testcase* t, const unsigned char* p, unsigned long len) +{ + unsigned long n, diff = len - t->is; + DOX(EQ(len, t->should), t->name); + for (n = len - diff; n < len; ++n) { + DOX(EQ(p[n], diff), t->name); + } + return CRYPT_OK; +} + +#ifdef LTC_RNG_GET_BYTES +static int s_cmp_iso_10126(const padding_testcase* t, const unsigned char* p, unsigned long len) +{ + LTC_UNUSED_PARAM(p); + if (len < t->should || len > t->max) { +#if defined(LTC_TEST) && defined(LTC_TEST_DBG) + fprintf(stderr, "(%lu < %lu || %lu > %lu) failed, %s\n", len, t->should, len, t->max, t->name); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + DOX(EQ(p[len - 1], len - t->is), t->name); + return CRYPT_OK; +} +#endif + +static int s_cmp_x923(const padding_testcase* t, const unsigned char* p, unsigned long len) +{ + unsigned long n, diff = len - t->is; + DOX(EQ(len, t->should), t->name); + for (n = len - diff; n < len - 1; ++n) { + DOX(EQ(p[n], 0x0), t->name); + } + DOX(EQ(p[len - 1], diff), t->name); + return CRYPT_OK; +} + +static int s_cmp_oaz(const padding_testcase* t, const unsigned char* p, unsigned long len) +{ + unsigned long n, diff = len - t->is; + DOX(EQ(len, t->should), t->name); + n = len - diff; + DOX(EQ(p[n], 0x80), t->name); + n++; + for (; n < len; ++n) { + DOX(EQ(p[n], 0x0), t->name); + } + return CRYPT_OK; +} + +static int s_cmp_zero(const padding_testcase* t, const unsigned char* p, unsigned long len) +{ + unsigned long n, diff = len - t->is; + DOX(EQ(len, t->should), t->name); + for (n = len - diff; n < len; ++n) { + DOX(EQ(p[n], 0x0), t->name); + } + return CRYPT_OK; +} + +static int s_cmp_ssh(const padding_testcase* t, const unsigned char* p, unsigned long len) +{ + unsigned long n, diff = len - t->is; + unsigned char pad = 0x1; + DOX(EQ(len, t->should), t->name); + for (n = len - diff; n < len; ++n) { + DOX(EQ(p[n], pad), t->name); + pad++; + } + return CRYPT_OK; +} + +static int s_padding_testrun(const padding_testcase* t) +{ + unsigned long len; + unsigned char buf[1024]; + + len = sizeof(buf); + XMEMSET(buf, 0xAA, t->is); + DO(padding_pad(buf, t->is, &len, t->mode)); + DO(t->cmp(t, buf, len)); + DO(padding_depad(buf, &len, t->mode)); + DO(EQ(len, t->is)); + return CRYPT_OK; +} + +int padding_test(void) +{ + const padding_testcase cases[] = { + { 0, 16, 0, LTC_PAD_PKCS7 | 16, "0-pkcs7", s_cmp_pkcs7 }, + { 1, 16, 0, LTC_PAD_PKCS7 | 16, "1-pkcs7", s_cmp_pkcs7 }, + { 15, 16, 0, LTC_PAD_PKCS7 | 16, "15-pkcs7", s_cmp_pkcs7 }, + { 16, 32, 0, LTC_PAD_PKCS7 | 16, "16-pkcs7", s_cmp_pkcs7 }, + { 255, 256, 0, LTC_PAD_PKCS7 | 16, "255-pkcs7", s_cmp_pkcs7 }, + { 256, 272, 0, LTC_PAD_PKCS7 | 16, "256-pkcs7", s_cmp_pkcs7 }, +#ifdef LTC_RNG_GET_BYTES + { 0, 16, 256, LTC_PAD_ISO_10126 | 16, "0-rand", s_cmp_iso_10126 }, + { 1, 16, 272, LTC_PAD_ISO_10126 | 16, "1-rand", s_cmp_iso_10126 }, + { 15, 16, 272, LTC_PAD_ISO_10126 | 16, "15-rand", s_cmp_iso_10126 }, + { 16, 32, 288, LTC_PAD_ISO_10126 | 16, "16-rand", s_cmp_iso_10126 }, + { 255, 256, 512, LTC_PAD_ISO_10126 | 16, "255-rand", s_cmp_iso_10126 }, + { 256, 272, 528, LTC_PAD_ISO_10126 | 16, "256-rand", s_cmp_iso_10126 }, +#endif + { 0, 16, 0, LTC_PAD_ANSI_X923 | 16, "0-x923", s_cmp_x923 }, + { 1, 16, 0, LTC_PAD_ANSI_X923 | 16, "1-x923", s_cmp_x923 }, + { 15, 16, 0, LTC_PAD_ANSI_X923 | 16, "15-x923", s_cmp_x923 }, + { 16, 32, 0, LTC_PAD_ANSI_X923 | 16, "16-x923", s_cmp_x923 }, + { 255, 256, 0, LTC_PAD_ANSI_X923 | 16, "255-x923", s_cmp_x923 }, + { 256, 272, 0, LTC_PAD_ANSI_X923 | 16, "256-x923", s_cmp_x923 }, + + { 0, 16, 0, LTC_PAD_SSH | 16, "0-ssh", s_cmp_ssh }, + { 1, 16, 0, LTC_PAD_SSH | 16, "1-ssh", s_cmp_ssh }, + { 15, 16, 0, LTC_PAD_SSH | 16, "15-ssh", s_cmp_ssh }, + { 16, 32, 0, LTC_PAD_SSH | 16, "16-ssh", s_cmp_ssh }, + { 255, 256, 0, LTC_PAD_SSH | 16, "255-ssh", s_cmp_ssh }, + { 256, 272, 0, LTC_PAD_SSH | 16, "256-ssh", s_cmp_ssh }, + + { 0, 16, 0, LTC_PAD_ONE_AND_ZERO | 16, "0-one-and-zero", s_cmp_oaz }, + { 1, 16, 0, LTC_PAD_ONE_AND_ZERO | 16, "1-one-and-zero", s_cmp_oaz }, + { 15, 16, 0, LTC_PAD_ONE_AND_ZERO | 16, "15-one-and-zero", s_cmp_oaz }, + { 16, 32, 0, LTC_PAD_ONE_AND_ZERO | 16, "16-one-and-zero", s_cmp_oaz }, + { 255, 256, 0, LTC_PAD_ONE_AND_ZERO | 16, "255-one-and-zero", s_cmp_oaz }, + { 256, 272, 0, LTC_PAD_ONE_AND_ZERO | 16, "256-one-and-zero", s_cmp_oaz }, + + { 0, 0, 0, LTC_PAD_ZERO | 16, "0-zero", s_cmp_zero }, + { 1, 16, 0, LTC_PAD_ZERO | 16, "1-zero", s_cmp_zero }, + { 15, 16, 0, LTC_PAD_ZERO | 16, "15-zero", s_cmp_zero }, + { 16, 16, 0, LTC_PAD_ZERO | 16, "16-zero", s_cmp_zero }, + { 255, 256, 0, LTC_PAD_ZERO | 16, "255-zero", s_cmp_zero }, + { 256, 256, 0, LTC_PAD_ZERO | 16, "256-zero", s_cmp_zero }, + + { 0, 16, 0, LTC_PAD_ZERO_ALWAYS | 16, "0-zero-always", s_cmp_zero }, + { 1, 16, 0, LTC_PAD_ZERO_ALWAYS | 16, "1-zero-always", s_cmp_zero }, + { 15, 16, 0, LTC_PAD_ZERO_ALWAYS | 16, "15-zero-always", s_cmp_zero }, + { 16, 32, 0, LTC_PAD_ZERO_ALWAYS | 16, "16-zero-always", s_cmp_zero }, + { 255, 256, 0, LTC_PAD_ZERO_ALWAYS | 16, "255-zero-always", s_cmp_zero }, + { 256, 272, 0, LTC_PAD_ZERO_ALWAYS | 16, "256-zero-always", s_cmp_zero }, + }; + unsigned i; + /* Examples from https://en.wikipedia.org/w/index.php?title=Padding_(cryptography)&oldid=823057951#Byte_padding */ + const struct { + unsigned char data[16]; + unsigned long len; + unsigned long mode; + } tv[] = { + { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, 0x04, 0x04, 0x04 }, 12, LTC_PAD_PKCS7 | 16 }, + { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x00, 0x00, 0x04 }, 12, LTC_PAD_ANSI_X923 | 16 }, +#ifdef LTC_RNG_GET_BYTES + { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x81, 0xA6, 0x23, 0x04 }, 12, LTC_PAD_ISO_10126 | 16 }, +#endif + { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x80, 0x00, 0x00, 0x00 }, 12, LTC_PAD_ONE_AND_ZERO | 16 }, + { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x80 }, 15, LTC_PAD_ONE_AND_ZERO | 16 }, + { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x00, 0x00, 0x00 }, 12, LTC_PAD_ZERO | 16 }, + }; + /* we need a big buffer like that as LTC_PAD_ISO_10126 + * is allowed to add 1-255 bytes of padding + */ + unsigned char buf[256 + 16]; + unsigned long l; + + for (i = 0; i < sizeof(cases)/sizeof(cases[0]); ++i) { + DOX(s_padding_testrun(&cases[i]), cases[i].name); + } + + for (i = 0; i < sizeof(tv)/sizeof(tv[0]); ++i) { + XMEMCPY(buf, tv[i].data, sizeof(tv[i].data)); + l = sizeof(tv[i].data); + DO(padding_depad(buf, &l, tv[i].mode)); + XMEMSET(buf, 0xDD, 16); + l = sizeof(buf); + DO(padding_pad(buf, tv[i].len, &l, tv[i].mode)); +#ifdef LTC_RNG_GET_BYTES + if ((tv[i].mode & LTC_PAD_MASK) != LTC_PAD_ISO_10126) +#endif + { + COMPARE_TESTVECTOR(tv[i].data, sizeof(tv[i].data), buf, l, "padding fixed TV", i); + } + } + + /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/454 */ + { + unsigned char data[] = { 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + unsigned long len = sizeof(data); + + SHOULD_FAIL(padding_depad(data, &len, (LTC_PAD_PKCS7 | 16))); + } + + return CRYPT_OK; +} +#endif diff --git a/deps/libtomcrypt/tests/pkcs_1_eme_test.c b/deps/libtomcrypt/tests/pkcs_1_eme_test.c new file mode 100644 index 0000000..217930d --- /dev/null +++ b/deps/libtomcrypt/tests/pkcs_1_eme_test.c @@ -0,0 +1,69 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_PKCS_1) + +#include "../notes/rsa-testvectors/pkcs1v15crypt-vectors.c" + + + +int pkcs_1_eme_test(void) +{ + struct ltc_prng_descriptor* no_prng_desc = no_prng_desc_get(); + int prng_idx = register_prng(no_prng_desc); + int hash_idx = find_hash("sha1"); + unsigned int i; + unsigned int j; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(prng_is_valid(prng_idx)); + DO(hash_is_valid(hash_idx)); + + for (i = 0; i < sizeof(testcases_eme)/sizeof(testcases_eme[0]); ++i) { + testcase_t* t = &testcases_eme[i]; + rsa_key k, *key = &k; + DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, + &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + + DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); + DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); + DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name); + DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name); + DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name); + DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name); + DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name); + DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name); + key->type = PK_PRIVATE; + + for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) { + rsaData_t* s = &t->data[j]; + unsigned char buf[256], obuf[256]; + unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); + int stat; + prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (void*)no_prng_desc); + DOX(rsa_encrypt_key_ex(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, (void*)no_prng_desc, prng_idx, -1, LTC_PKCS_1_V1_5, key), s->name); + COMPARE_TESTVECTOR(obuf, obuflen, s->o3, s->o3_l,s->name, j); + DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, LTC_PKCS_1_V1_5, &stat, key), s->name); + DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); + } /* for */ + + mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, LTC_NULL); + } /* for */ + + unregister_prng(no_prng_desc); + no_prng_desc_free(no_prng_desc); + + return 0; +} + +#else + +int pkcs_1_eme_test(void) +{ + return CRYPT_NOP; +} + +#endif + diff --git a/deps/libtomcrypt/tests/pkcs_1_emsa_test.c b/deps/libtomcrypt/tests/pkcs_1_emsa_test.c new file mode 100644 index 0000000..7f486bb --- /dev/null +++ b/deps/libtomcrypt/tests/pkcs_1_emsa_test.c @@ -0,0 +1,63 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_PKCS_1) + +#include "../notes/rsa-testvectors/pkcs1v15sign-vectors.c" + + + +int pkcs_1_emsa_test(void) +{ + int hash_idx = find_hash("sha1"); + unsigned int i; + unsigned int j; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(hash_is_valid(hash_idx)); + + for (i = 0; i < sizeof(testcases_emsa)/sizeof(testcases_emsa[0]); ++i) { + testcase_t* t = &testcases_emsa[i]; + rsa_key k, *key = &k; + DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, + &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + + DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); + DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); + DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name); + DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name); + DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name); + DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name); + DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name); + DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name); + key->type = PK_PRIVATE; + + for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) { + rsaData_t* s = &t->data[j]; + unsigned char buf[20], obuf[256]; + unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); + int stat; + DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name); + DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, 0, key), s->name); + COMPARE_TESTVECTOR(obuf, obuflen, s->o2, s->o2_l,s->name, j); + DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, 0, &stat, key), s->name); + DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); + } /* for */ + + mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, LTC_NULL); + } /* for */ + + return 0; +} + +#else + +int pkcs_1_emsa_test(void) +{ + return CRYPT_NOP; +} + +#endif + diff --git a/deps/libtomcrypt/tests/pkcs_1_oaep_test.c b/deps/libtomcrypt/tests/pkcs_1_oaep_test.c new file mode 100644 index 0000000..7391053 --- /dev/null +++ b/deps/libtomcrypt/tests/pkcs_1_oaep_test.c @@ -0,0 +1,69 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_PKCS_1) + +#include "../notes/rsa-testvectors/oaep-vect.c" + + + +int pkcs_1_oaep_test(void) +{ + struct ltc_prng_descriptor* no_prng_desc = no_prng_desc_get(); + int prng_idx = register_prng(no_prng_desc); + int hash_idx = find_hash("sha1"); + unsigned int i; + unsigned int j; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(prng_is_valid(prng_idx)); + DO(hash_is_valid(hash_idx)); + + for (i = 0; i < sizeof(testcases_oaep)/sizeof(testcases_oaep[0]); ++i) { + testcase_t* t = &testcases_oaep[i]; + rsa_key k, *key = &k; + DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, + &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + + DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); + DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); + DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name); + DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name); + DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name); + DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name); + DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name); + DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name); + key->type = PK_PRIVATE; + + for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) { + rsaData_t* s = &t->data[j]; + unsigned char buf[256], obuf[256]; + unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); + int stat; + prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (void*)no_prng_desc); + DOX(rsa_encrypt_key(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, (void*)no_prng_desc, prng_idx, hash_idx, key), s->name); + COMPARE_TESTVECTOR(obuf, obuflen, s->o3, s->o3_l,s->name, j); + DOX(rsa_decrypt_key(obuf, obuflen, buf, &buflen, NULL, 0, hash_idx, &stat, key), s->name); + DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); + } /* for */ + + mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, LTC_NULL); + } /* for */ + + unregister_prng(no_prng_desc); + no_prng_desc_free(no_prng_desc); + + return 0; +} + +#else + +int pkcs_1_oaep_test(void) +{ + return CRYPT_NOP; +} + +#endif + diff --git a/deps/libtomcrypt/tests/pkcs_1_pss_test.c b/deps/libtomcrypt/tests/pkcs_1_pss_test.c new file mode 100644 index 0000000..82bdb07 --- /dev/null +++ b/deps/libtomcrypt/tests/pkcs_1_pss_test.c @@ -0,0 +1,70 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_PKCS_1) + +#include "../notes/rsa-testvectors/pss-vect.c" + + + +int pkcs_1_pss_test(void) +{ + struct ltc_prng_descriptor* no_prng_desc = no_prng_desc_get(); + int prng_idx = register_prng(no_prng_desc); + int hash_idx = find_hash("sha1"); + unsigned int i; + unsigned int j; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(prng_is_valid(prng_idx)); + DO(hash_is_valid(hash_idx)); + + for (i = 0; i < sizeof(testcases_pss)/sizeof(testcases_pss[0]); ++i) { + testcase_t* t = &testcases_pss[i]; + rsa_key k, *key = &k; + DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, + &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + + DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); + DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); + DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name); + DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name); + DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name); + DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name); + DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name); + DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name); + key->type = PK_PRIVATE; + + for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) { + rsaData_t* s = &t->data[j]; + unsigned char buf[20], obuf[256]; + unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); + int stat; + prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (void*)no_prng_desc); + DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name); + DOX(rsa_sign_hash(buf, buflen, obuf, &obuflen, (void*)no_prng_desc, prng_idx, hash_idx, s->o2_l, key), s->name); + COMPARE_TESTVECTOR(obuf, obuflen, s->o3, s->o3_l,s->name, j); + DOX(rsa_verify_hash(obuf, obuflen, buf, buflen, hash_idx, s->o2_l, &stat, key), s->name); + DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); + } /* for */ + + mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, LTC_NULL); + } /* for */ + + unregister_prng(no_prng_desc); + no_prng_desc_free(no_prng_desc); + + return 0; +} + +#else + +int pkcs_1_pss_test(void) +{ + return CRYPT_NOP; +} + +#endif + diff --git a/deps/libtomcrypt/tests/pkcs_1_test.c b/deps/libtomcrypt/tests/pkcs_1_test.c new file mode 100644 index 0000000..9bc9a27 --- /dev/null +++ b/deps/libtomcrypt/tests/pkcs_1_test.c @@ -0,0 +1,96 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#ifdef LTC_PKCS_1 + +#ifdef LTC_TEST_REAL_RAND +#define LTC_TEST_RAND_SEED time(NULL) +#else +#define LTC_TEST_RAND_SEED 23 +#endif + +int pkcs_1_test(void) +{ + unsigned char buf[3][128]; + int res1, res2, res3, prng_idx, hash_idx; + unsigned long x, y, l1, l2, l3, i1, i2, lparamlen, saltlen, modlen; + static const unsigned char lparam[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }; + + /* get hash/prng */ + hash_idx = find_hash("sha1"); + prng_idx = find_prng("yarrow"); + + if (hash_idx == -1 || prng_idx == -1) { + fprintf(stderr, "pkcs_1 tests require sha1/yarrow"); + return 1; + } + + srand(LTC_TEST_RAND_SEED); + /* do many tests */ + for (x = 0; x < 100; x++) { + zeromem(buf, sizeof(buf)); + + /* make a dummy message (of random length) */ + l3 = (rand() & 31) + 8; + for (y = 0; y < l3; y++) buf[0][y] = rand() & 255; + + /* pick a random lparam len [0..16] */ + lparamlen = abs(rand()) % 17; + + /* pick a random saltlen 0..16 */ + saltlen = abs(rand()) % 17; + + /* PKCS #1 v2.0 supports modlens not multiple of 8 */ + modlen = 800 + (abs(rand()) % 224); + + /* encode it */ + l1 = sizeof(buf[1]); + DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &yarrow_prng, prng_idx, hash_idx, buf[1], &l1)); + + /* decode it */ + l2 = sizeof(buf[2]); + DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1)); + + if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) { + fprintf(stderr, "Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen); + fprintf(stderr, "ORIGINAL:\n"); + for (x = 0; x < l3; x++) { + fprintf(stderr, "%02x ", buf[0][x]); + } + fprintf(stderr, "\nRESULT:\n"); + for (x = 0; x < l2; x++) { + fprintf(stderr, "%02x ", buf[2][x]); + } + fprintf(stderr, "\n\n"); + return 1; + } + + /* test PSS */ + l1 = sizeof(buf[1]); + DO(pkcs_1_pss_encode(buf[0], l3, saltlen, &yarrow_prng, prng_idx, hash_idx, modlen, buf[1], &l1)); + DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res1)); + + buf[0][i1 = abs(rand()) % l3] ^= 1; + DO(pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res2)); + + buf[0][i1] ^= 1; + buf[1][i2 = abs(rand()) % (l1 - 1)] ^= 1; + pkcs_1_pss_decode(buf[0], l3, buf[1], l1, saltlen, hash_idx, modlen, &res3); + if (!(res1 == 1 && res2 == 0 && res3 == 0)) { + fprintf(stderr, "PSS failed: %d, %d, %d, %lu, %lu\n", res1, res2, res3, l3, saltlen); + return 1; + } + } + return 0; +} + +#else + +int pkcs_1_test(void) +{ + return CRYPT_NOP; +} + +#endif + diff --git a/deps/libtomcrypt/tests/prng_test.c b/deps/libtomcrypt/tests/prng_test.c new file mode 100644 index 0000000..15448dd --- /dev/null +++ b/deps/libtomcrypt/tests/prng_test.c @@ -0,0 +1,109 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#ifdef LTC_PRNG_ENABLE_LTC_RNG + +static unsigned long my_test_rng_read; + +static unsigned long my_test_rng(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + unsigned long n; + LTC_UNUSED_PARAM(callback); + for (n = 0; n < len; ++n) { + buf[n] = 4; + } + my_test_rng_read += n; + return n; +} + +#endif + +int prng_test(void) +{ + int err = CRYPT_NOP; + int x; + unsigned char buf[4096] = { 0 }; + unsigned long n, one; + prng_state nprng; + +#ifdef LTC_PRNG_ENABLE_LTC_RNG + unsigned long before; + + unsigned long (*previous)(unsigned char *, unsigned long , void (*)(void)) = ltc_rng; + ltc_rng = my_test_rng; + + before = my_test_rng_read; + + if ((err = rng_make_prng(128, find_prng("yarrow"), &nprng, NULL)) != CRYPT_OK) { + fprintf(stderr, "rng_make_prng with 'my_test_rng' failed: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + DO(yarrow_done(&nprng)); + + if (before == my_test_rng_read) { + fprintf(stderr, "somehow there was no read from the ltc_rng! %lu == %lu\n", before, my_test_rng_read); + exit(EXIT_FAILURE); + } + + ltc_rng = previous; +#endif + + /* test prngs (test, import/export) */ + for (x = 0; prng_descriptor[x].name != NULL; x++) { + if(strstr(prng_descriptor[x].name, "no_prng") == prng_descriptor[x].name) continue; + DOX(prng_descriptor[x].test(), prng_descriptor[x].name); + DOX(prng_descriptor[x].start(&nprng), prng_descriptor[x].name); + DOX(prng_descriptor[x].add_entropy((unsigned char *)"helloworld12", 12, &nprng), prng_descriptor[x].name); + DOX(prng_descriptor[x].ready(&nprng), prng_descriptor[x].name); + n = sizeof(buf); + if (strcmp(prng_descriptor[x].name, "sprng")) { + one = 1; + if (prng_descriptor[x].pexport(buf, &one, &nprng) != CRYPT_BUFFER_OVERFLOW) { + fprintf(stderr, "Error testing pexport with a short buffer (%s)\n", prng_descriptor[x].name); + return CRYPT_ERROR; + } + } + DOX(prng_descriptor[x].pexport(buf, &n, &nprng), prng_descriptor[x].name); + prng_descriptor[x].done(&nprng); + DOX(prng_descriptor[x].pimport(buf, n, &nprng), prng_descriptor[x].name); + DOX(prng_descriptor[x].pimport(buf, sizeof(buf), &nprng), prng_descriptor[x].name); /* try to import larger data */ + DOX(prng_descriptor[x].ready(&nprng), prng_descriptor[x].name); + if (prng_descriptor[x].read(buf, 100, &nprng) != 100) { + fprintf(stderr, "Error reading from imported PRNG (%s)!\n", prng_descriptor[x].name); + return CRYPT_ERROR; + } + prng_descriptor[x].done(&nprng); + } + + if ((err = rng_make_prng(-1, find_prng("yarrow"), &nprng, NULL)) != CRYPT_OK) { + fprintf(stderr, "rng_make_prng(-1,..) with 'yarrow' failed: %s\n", error_to_string(err)); + } + DO(yarrow_done(&nprng)); + +#ifdef LTC_FORTUNA + DO(fortuna_start(&nprng)); + DO(fortuna_add_entropy(buf, 32, &nprng)); + DO(fortuna_ready(&nprng)); + if (fortuna_read(buf + 32, 32, &nprng) != 32) { + fprintf(stderr, "Error reading from Fortuna after fortuna_add_entropy()!\n"); + return CRYPT_ERROR; + } + DO(fortuna_done(&nprng)); + + DO(fortuna_start(&nprng)); + DO(fortuna_add_random_event(0, 0, buf, 32, &nprng)); + DO(fortuna_ready(&nprng)); + if (fortuna_read(buf + 64, 32, &nprng) != 32) { + fprintf(stderr, "Error reading from Fortuna after fortuna_add_random_event()!\n"); + return CRYPT_ERROR; + } + DO(fortuna_done(&nprng)); + + if (compare_testvector(buf + 64, 32, buf + 32, 32, "fortuna_add_entropy() vs. fortuna_add_random_event()", 0) != 0) { + err = CRYPT_FAIL_TESTVECTOR; + } +#endif + return err; +} diff --git a/deps/libtomcrypt/tests/rotate_test.c b/deps/libtomcrypt/tests/rotate_test.c new file mode 100644 index 0000000..62e328c --- /dev/null +++ b/deps/libtomcrypt/tests/rotate_test.c @@ -0,0 +1,406 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +/* Test rotate macros */ +int rotate_test(void) +{ + ulong32 L32 = 0x12345678UL; + ulong64 L64 = CONST64(0x1122334455667788); + int err = 0; + + /* ROR */ + if (ROR(L32, 0 ) != 0x12345678UL) { fprintf(stderr, "ROR 0 failed\n"); err++; } + if (ROR(L32, 1 ) != 0x091a2b3cUL) { fprintf(stderr, "ROR 1 failed\n"); err++; } + if (ROR(L32, 2 ) != 0x048d159eUL) { fprintf(stderr, "ROR 2 failed\n"); err++; } + if (ROR(L32, 3 ) != 0x02468acfUL) { fprintf(stderr, "ROR 3 failed\n"); err++; } + if (ROR(L32, 4 ) != 0x81234567UL) { fprintf(stderr, "ROR 4 failed\n"); err++; } + if (ROR(L32, 5 ) != 0xc091a2b3UL) { fprintf(stderr, "ROR 5 failed\n"); err++; } + if (ROR(L32, 6 ) != 0xe048d159UL) { fprintf(stderr, "ROR 6 failed\n"); err++; } + if (ROR(L32, 7 ) != 0xf02468acUL) { fprintf(stderr, "ROR 7 failed\n"); err++; } + if (ROR(L32, 8 ) != 0x78123456UL) { fprintf(stderr, "ROR 8 failed\n"); err++; } + if (ROR(L32, 9 ) != 0x3c091a2bUL) { fprintf(stderr, "ROR 9 failed\n"); err++; } + if (ROR(L32, 10) != 0x9e048d15UL) { fprintf(stderr, "ROR 10 failed\n"); err++; } + if (ROR(L32, 11) != 0xcf02468aUL) { fprintf(stderr, "ROR 11 failed\n"); err++; } + if (ROR(L32, 12) != 0x67812345UL) { fprintf(stderr, "ROR 12 failed\n"); err++; } + if (ROR(L32, 13) != 0xb3c091a2UL) { fprintf(stderr, "ROR 13 failed\n"); err++; } + if (ROR(L32, 14) != 0x59e048d1UL) { fprintf(stderr, "ROR 14 failed\n"); err++; } + if (ROR(L32, 15) != 0xacf02468UL) { fprintf(stderr, "ROR 15 failed\n"); err++; } + if (ROR(L32, 16) != 0x56781234UL) { fprintf(stderr, "ROR 16 failed\n"); err++; } + if (ROR(L32, 17) != 0x2b3c091aUL) { fprintf(stderr, "ROR 17 failed\n"); err++; } + if (ROR(L32, 18) != 0x159e048dUL) { fprintf(stderr, "ROR 18 failed\n"); err++; } + if (ROR(L32, 19) != 0x8acf0246UL) { fprintf(stderr, "ROR 19 failed\n"); err++; } + if (ROR(L32, 20) != 0x45678123UL) { fprintf(stderr, "ROR 20 failed\n"); err++; } + if (ROR(L32, 21) != 0xa2b3c091UL) { fprintf(stderr, "ROR 21 failed\n"); err++; } + if (ROR(L32, 22) != 0xd159e048UL) { fprintf(stderr, "ROR 22 failed\n"); err++; } + if (ROR(L32, 23) != 0x68acf024UL) { fprintf(stderr, "ROR 23 failed\n"); err++; } + if (ROR(L32, 24) != 0x34567812UL) { fprintf(stderr, "ROR 24 failed\n"); err++; } + if (ROR(L32, 25) != 0x1a2b3c09UL) { fprintf(stderr, "ROR 25 failed\n"); err++; } + if (ROR(L32, 26) != 0x8d159e04UL) { fprintf(stderr, "ROR 26 failed\n"); err++; } + if (ROR(L32, 27) != 0x468acf02UL) { fprintf(stderr, "ROR 27 failed\n"); err++; } + if (ROR(L32, 28) != 0x23456781UL) { fprintf(stderr, "ROR 28 failed\n"); err++; } + if (ROR(L32, 29) != 0x91a2b3c0UL) { fprintf(stderr, "ROR 29 failed\n"); err++; } + if (ROR(L32, 30) != 0x48d159e0UL) { fprintf(stderr, "ROR 30 failed\n"); err++; } + if (ROR(L32, 31) != 0x2468acf0UL) { fprintf(stderr, "ROR 31 failed\n"); err++; } + /* ROR64 */ + if (ROR64(L64, 0 ) != CONST64(0x1122334455667788)) { fprintf(stderr, "ROR64 0 failed\n"); err++; } + if (ROR64(L64, 1 ) != CONST64(0x089119a22ab33bc4)) { fprintf(stderr, "ROR64 1 failed\n"); err++; } + if (ROR64(L64, 2 ) != CONST64(0x04488cd115599de2)) { fprintf(stderr, "ROR64 2 failed\n"); err++; } + if (ROR64(L64, 3 ) != CONST64(0x022446688aaccef1)) { fprintf(stderr, "ROR64 3 failed\n"); err++; } + if (ROR64(L64, 4 ) != CONST64(0x8112233445566778)) { fprintf(stderr, "ROR64 4 failed\n"); err++; } + if (ROR64(L64, 5 ) != CONST64(0x4089119a22ab33bc)) { fprintf(stderr, "ROR64 5 failed\n"); err++; } + if (ROR64(L64, 6 ) != CONST64(0x204488cd115599de)) { fprintf(stderr, "ROR64 6 failed\n"); err++; } + if (ROR64(L64, 7 ) != CONST64(0x1022446688aaccef)) { fprintf(stderr, "ROR64 7 failed\n"); err++; } + if (ROR64(L64, 8 ) != CONST64(0x8811223344556677)) { fprintf(stderr, "ROR64 8 failed\n"); err++; } + if (ROR64(L64, 9 ) != CONST64(0xc4089119a22ab33b)) { fprintf(stderr, "ROR64 9 failed\n"); err++; } + if (ROR64(L64, 10) != CONST64(0xe204488cd115599d)) { fprintf(stderr, "ROR64 10 failed\n"); err++; } + if (ROR64(L64, 11) != CONST64(0xf1022446688aacce)) { fprintf(stderr, "ROR64 11 failed\n"); err++; } + if (ROR64(L64, 12) != CONST64(0x7881122334455667)) { fprintf(stderr, "ROR64 12 failed\n"); err++; } + if (ROR64(L64, 13) != CONST64(0xbc4089119a22ab33)) { fprintf(stderr, "ROR64 13 failed\n"); err++; } + if (ROR64(L64, 14) != CONST64(0xde204488cd115599)) { fprintf(stderr, "ROR64 14 failed\n"); err++; } + if (ROR64(L64, 15) != CONST64(0xef1022446688aacc)) { fprintf(stderr, "ROR64 15 failed\n"); err++; } + if (ROR64(L64, 16) != CONST64(0x7788112233445566)) { fprintf(stderr, "ROR64 16 failed\n"); err++; } + if (ROR64(L64, 17) != CONST64(0x3bc4089119a22ab3)) { fprintf(stderr, "ROR64 17 failed\n"); err++; } + if (ROR64(L64, 18) != CONST64(0x9de204488cd11559)) { fprintf(stderr, "ROR64 18 failed\n"); err++; } + if (ROR64(L64, 19) != CONST64(0xcef1022446688aac)) { fprintf(stderr, "ROR64 19 failed\n"); err++; } + if (ROR64(L64, 20) != CONST64(0x6778811223344556)) { fprintf(stderr, "ROR64 20 failed\n"); err++; } + if (ROR64(L64, 21) != CONST64(0x33bc4089119a22ab)) { fprintf(stderr, "ROR64 21 failed\n"); err++; } + if (ROR64(L64, 22) != CONST64(0x99de204488cd1155)) { fprintf(stderr, "ROR64 22 failed\n"); err++; } + if (ROR64(L64, 23) != CONST64(0xccef1022446688aa)) { fprintf(stderr, "ROR64 23 failed\n"); err++; } + if (ROR64(L64, 24) != CONST64(0x6677881122334455)) { fprintf(stderr, "ROR64 24 failed\n"); err++; } + if (ROR64(L64, 25) != CONST64(0xb33bc4089119a22a)) { fprintf(stderr, "ROR64 25 failed\n"); err++; } + if (ROR64(L64, 26) != CONST64(0x599de204488cd115)) { fprintf(stderr, "ROR64 26 failed\n"); err++; } + if (ROR64(L64, 27) != CONST64(0xaccef1022446688a)) { fprintf(stderr, "ROR64 27 failed\n"); err++; } + if (ROR64(L64, 28) != CONST64(0x5667788112233445)) { fprintf(stderr, "ROR64 28 failed\n"); err++; } + if (ROR64(L64, 29) != CONST64(0xab33bc4089119a22)) { fprintf(stderr, "ROR64 29 failed\n"); err++; } + if (ROR64(L64, 30) != CONST64(0x5599de204488cd11)) { fprintf(stderr, "ROR64 30 failed\n"); err++; } + if (ROR64(L64, 31) != CONST64(0xaaccef1022446688)) { fprintf(stderr, "ROR64 31 failed\n"); err++; } + if (ROR64(L64, 32) != CONST64(0x5566778811223344)) { fprintf(stderr, "ROR64 32 failed\n"); err++; } + if (ROR64(L64, 33) != CONST64(0x2ab33bc4089119a2)) { fprintf(stderr, "ROR64 33 failed\n"); err++; } + if (ROR64(L64, 34) != CONST64(0x15599de204488cd1)) { fprintf(stderr, "ROR64 34 failed\n"); err++; } + if (ROR64(L64, 35) != CONST64(0x8aaccef102244668)) { fprintf(stderr, "ROR64 35 failed\n"); err++; } + if (ROR64(L64, 36) != CONST64(0x4556677881122334)) { fprintf(stderr, "ROR64 36 failed\n"); err++; } + if (ROR64(L64, 37) != CONST64(0x22ab33bc4089119a)) { fprintf(stderr, "ROR64 37 failed\n"); err++; } + if (ROR64(L64, 38) != CONST64(0x115599de204488cd)) { fprintf(stderr, "ROR64 38 failed\n"); err++; } + if (ROR64(L64, 39) != CONST64(0x88aaccef10224466)) { fprintf(stderr, "ROR64 39 failed\n"); err++; } + if (ROR64(L64, 40) != CONST64(0x4455667788112233)) { fprintf(stderr, "ROR64 40 failed\n"); err++; } + if (ROR64(L64, 41) != CONST64(0xa22ab33bc4089119)) { fprintf(stderr, "ROR64 41 failed\n"); err++; } + if (ROR64(L64, 42) != CONST64(0xd115599de204488c)) { fprintf(stderr, "ROR64 42 failed\n"); err++; } + if (ROR64(L64, 43) != CONST64(0x688aaccef1022446)) { fprintf(stderr, "ROR64 43 failed\n"); err++; } + if (ROR64(L64, 44) != CONST64(0x3445566778811223)) { fprintf(stderr, "ROR64 44 failed\n"); err++; } + if (ROR64(L64, 45) != CONST64(0x9a22ab33bc408911)) { fprintf(stderr, "ROR64 45 failed\n"); err++; } + if (ROR64(L64, 46) != CONST64(0xcd115599de204488)) { fprintf(stderr, "ROR64 46 failed\n"); err++; } + if (ROR64(L64, 47) != CONST64(0x6688aaccef102244)) { fprintf(stderr, "ROR64 47 failed\n"); err++; } + if (ROR64(L64, 48) != CONST64(0x3344556677881122)) { fprintf(stderr, "ROR64 48 failed\n"); err++; } + if (ROR64(L64, 49) != CONST64(0x19a22ab33bc40891)) { fprintf(stderr, "ROR64 49 failed\n"); err++; } + if (ROR64(L64, 50) != CONST64(0x8cd115599de20448)) { fprintf(stderr, "ROR64 50 failed\n"); err++; } + if (ROR64(L64, 51) != CONST64(0x46688aaccef10224)) { fprintf(stderr, "ROR64 51 failed\n"); err++; } + if (ROR64(L64, 52) != CONST64(0x2334455667788112)) { fprintf(stderr, "ROR64 52 failed\n"); err++; } + if (ROR64(L64, 53) != CONST64(0x119a22ab33bc4089)) { fprintf(stderr, "ROR64 53 failed\n"); err++; } + if (ROR64(L64, 54) != CONST64(0x88cd115599de2044)) { fprintf(stderr, "ROR64 54 failed\n"); err++; } + if (ROR64(L64, 55) != CONST64(0x446688aaccef1022)) { fprintf(stderr, "ROR64 55 failed\n"); err++; } + if (ROR64(L64, 56) != CONST64(0x2233445566778811)) { fprintf(stderr, "ROR64 56 failed\n"); err++; } + if (ROR64(L64, 57) != CONST64(0x9119a22ab33bc408)) { fprintf(stderr, "ROR64 57 failed\n"); err++; } + if (ROR64(L64, 58) != CONST64(0x488cd115599de204)) { fprintf(stderr, "ROR64 58 failed\n"); err++; } + if (ROR64(L64, 59) != CONST64(0x2446688aaccef102)) { fprintf(stderr, "ROR64 59 failed\n"); err++; } + if (ROR64(L64, 60) != CONST64(0x1223344556677881)) { fprintf(stderr, "ROR64 60 failed\n"); err++; } + if (ROR64(L64, 61) != CONST64(0x89119a22ab33bc40)) { fprintf(stderr, "ROR64 61 failed\n"); err++; } + if (ROR64(L64, 62) != CONST64(0x4488cd115599de20)) { fprintf(stderr, "ROR64 62 failed\n"); err++; } + if (ROR64(L64, 63) != CONST64(0x22446688aaccef10)) { fprintf(stderr, "ROR64 63 failed\n"); err++; } + /* ROL */ + if (ROL(L32, 0 ) != 0x12345678UL) { fprintf(stderr, "ROL 0 failed\n"); err++; } + if (ROL(L32, 1 ) != 0x2468acf0UL) { fprintf(stderr, "ROL 1 failed\n"); err++; } + if (ROL(L32, 2 ) != 0x48d159e0UL) { fprintf(stderr, "ROL 2 failed\n"); err++; } + if (ROL(L32, 3 ) != 0x91a2b3c0UL) { fprintf(stderr, "ROL 3 failed\n"); err++; } + if (ROL(L32, 4 ) != 0x23456781UL) { fprintf(stderr, "ROL 4 failed\n"); err++; } + if (ROL(L32, 5 ) != 0x468acf02UL) { fprintf(stderr, "ROL 5 failed\n"); err++; } + if (ROL(L32, 6 ) != 0x8d159e04UL) { fprintf(stderr, "ROL 6 failed\n"); err++; } + if (ROL(L32, 7 ) != 0x1a2b3c09UL) { fprintf(stderr, "ROL 7 failed\n"); err++; } + if (ROL(L32, 8 ) != 0x34567812UL) { fprintf(stderr, "ROL 8 failed\n"); err++; } + if (ROL(L32, 9 ) != 0x68acf024UL) { fprintf(stderr, "ROL 9 failed\n"); err++; } + if (ROL(L32, 10) != 0xd159e048UL) { fprintf(stderr, "ROL 10 failed\n"); err++; } + if (ROL(L32, 11) != 0xa2b3c091UL) { fprintf(stderr, "ROL 11 failed\n"); err++; } + if (ROL(L32, 12) != 0x45678123UL) { fprintf(stderr, "ROL 12 failed\n"); err++; } + if (ROL(L32, 13) != 0x8acf0246UL) { fprintf(stderr, "ROL 13 failed\n"); err++; } + if (ROL(L32, 14) != 0x159e048dUL) { fprintf(stderr, "ROL 14 failed\n"); err++; } + if (ROL(L32, 15) != 0x2b3c091aUL) { fprintf(stderr, "ROL 15 failed\n"); err++; } + if (ROL(L32, 16) != 0x56781234UL) { fprintf(stderr, "ROL 16 failed\n"); err++; } + if (ROL(L32, 17) != 0xacf02468UL) { fprintf(stderr, "ROL 17 failed\n"); err++; } + if (ROL(L32, 18) != 0x59e048d1UL) { fprintf(stderr, "ROL 18 failed\n"); err++; } + if (ROL(L32, 19) != 0xb3c091a2UL) { fprintf(stderr, "ROL 19 failed\n"); err++; } + if (ROL(L32, 20) != 0x67812345UL) { fprintf(stderr, "ROL 20 failed\n"); err++; } + if (ROL(L32, 21) != 0xcf02468aUL) { fprintf(stderr, "ROL 21 failed\n"); err++; } + if (ROL(L32, 22) != 0x9e048d15UL) { fprintf(stderr, "ROL 22 failed\n"); err++; } + if (ROL(L32, 23) != 0x3c091a2bUL) { fprintf(stderr, "ROL 23 failed\n"); err++; } + if (ROL(L32, 24) != 0x78123456UL) { fprintf(stderr, "ROL 24 failed\n"); err++; } + if (ROL(L32, 25) != 0xf02468acUL) { fprintf(stderr, "ROL 25 failed\n"); err++; } + if (ROL(L32, 26) != 0xe048d159UL) { fprintf(stderr, "ROL 26 failed\n"); err++; } + if (ROL(L32, 27) != 0xc091a2b3UL) { fprintf(stderr, "ROL 27 failed\n"); err++; } + if (ROL(L32, 28) != 0x81234567UL) { fprintf(stderr, "ROL 28 failed\n"); err++; } + if (ROL(L32, 29) != 0x02468acfUL) { fprintf(stderr, "ROL 29 failed\n"); err++; } + if (ROL(L32, 30) != 0x048d159eUL) { fprintf(stderr, "ROL 30 failed\n"); err++; } + if (ROL(L32, 31) != 0x091a2b3cUL) { fprintf(stderr, "ROL 31 failed\n"); err++; } + /* ROL64 */ + if (ROL64(L64, 0 ) != CONST64(0x1122334455667788)) { fprintf(stderr, "ROL64 0 failed\n"); err++; } + if (ROL64(L64, 1 ) != CONST64(0x22446688aaccef10)) { fprintf(stderr, "ROL64 1 failed\n"); err++; } + if (ROL64(L64, 2 ) != CONST64(0x4488cd115599de20)) { fprintf(stderr, "ROL64 2 failed\n"); err++; } + if (ROL64(L64, 3 ) != CONST64(0x89119a22ab33bc40)) { fprintf(stderr, "ROL64 3 failed\n"); err++; } + if (ROL64(L64, 4 ) != CONST64(0x1223344556677881)) { fprintf(stderr, "ROL64 4 failed\n"); err++; } + if (ROL64(L64, 5 ) != CONST64(0x2446688aaccef102)) { fprintf(stderr, "ROL64 5 failed\n"); err++; } + if (ROL64(L64, 6 ) != CONST64(0x488cd115599de204)) { fprintf(stderr, "ROL64 6 failed\n"); err++; } + if (ROL64(L64, 7 ) != CONST64(0x9119a22ab33bc408)) { fprintf(stderr, "ROL64 7 failed\n"); err++; } + if (ROL64(L64, 8 ) != CONST64(0x2233445566778811)) { fprintf(stderr, "ROL64 8 failed\n"); err++; } + if (ROL64(L64, 9 ) != CONST64(0x446688aaccef1022)) { fprintf(stderr, "ROL64 9 failed\n"); err++; } + if (ROL64(L64, 10) != CONST64(0x88cd115599de2044)) { fprintf(stderr, "ROL64 10 failed\n"); err++; } + if (ROL64(L64, 11) != CONST64(0x119a22ab33bc4089)) { fprintf(stderr, "ROL64 11 failed\n"); err++; } + if (ROL64(L64, 12) != CONST64(0x2334455667788112)) { fprintf(stderr, "ROL64 12 failed\n"); err++; } + if (ROL64(L64, 13) != CONST64(0x46688aaccef10224)) { fprintf(stderr, "ROL64 13 failed\n"); err++; } + if (ROL64(L64, 14) != CONST64(0x8cd115599de20448)) { fprintf(stderr, "ROL64 14 failed\n"); err++; } + if (ROL64(L64, 15) != CONST64(0x19a22ab33bc40891)) { fprintf(stderr, "ROL64 15 failed\n"); err++; } + if (ROL64(L64, 16) != CONST64(0x3344556677881122)) { fprintf(stderr, "ROL64 16 failed\n"); err++; } + if (ROL64(L64, 17) != CONST64(0x6688aaccef102244)) { fprintf(stderr, "ROL64 17 failed\n"); err++; } + if (ROL64(L64, 18) != CONST64(0xcd115599de204488)) { fprintf(stderr, "ROL64 18 failed\n"); err++; } + if (ROL64(L64, 19) != CONST64(0x9a22ab33bc408911)) { fprintf(stderr, "ROL64 19 failed\n"); err++; } + if (ROL64(L64, 20) != CONST64(0x3445566778811223)) { fprintf(stderr, "ROL64 20 failed\n"); err++; } + if (ROL64(L64, 21) != CONST64(0x688aaccef1022446)) { fprintf(stderr, "ROL64 21 failed\n"); err++; } + if (ROL64(L64, 22) != CONST64(0xd115599de204488c)) { fprintf(stderr, "ROL64 22 failed\n"); err++; } + if (ROL64(L64, 23) != CONST64(0xa22ab33bc4089119)) { fprintf(stderr, "ROL64 23 failed\n"); err++; } + if (ROL64(L64, 24) != CONST64(0x4455667788112233)) { fprintf(stderr, "ROL64 24 failed\n"); err++; } + if (ROL64(L64, 25) != CONST64(0x88aaccef10224466)) { fprintf(stderr, "ROL64 25 failed\n"); err++; } + if (ROL64(L64, 26) != CONST64(0x115599de204488cd)) { fprintf(stderr, "ROL64 26 failed\n"); err++; } + if (ROL64(L64, 27) != CONST64(0x22ab33bc4089119a)) { fprintf(stderr, "ROL64 27 failed\n"); err++; } + if (ROL64(L64, 28) != CONST64(0x4556677881122334)) { fprintf(stderr, "ROL64 28 failed\n"); err++; } + if (ROL64(L64, 29) != CONST64(0x8aaccef102244668)) { fprintf(stderr, "ROL64 29 failed\n"); err++; } + if (ROL64(L64, 30) != CONST64(0x15599de204488cd1)) { fprintf(stderr, "ROL64 30 failed\n"); err++; } + if (ROL64(L64, 31) != CONST64(0x2ab33bc4089119a2)) { fprintf(stderr, "ROL64 31 failed\n"); err++; } + if (ROL64(L64, 32) != CONST64(0x5566778811223344)) { fprintf(stderr, "ROL64 32 failed\n"); err++; } + if (ROL64(L64, 33) != CONST64(0xaaccef1022446688)) { fprintf(stderr, "ROL64 33 failed\n"); err++; } + if (ROL64(L64, 34) != CONST64(0x5599de204488cd11)) { fprintf(stderr, "ROL64 34 failed\n"); err++; } + if (ROL64(L64, 35) != CONST64(0xab33bc4089119a22)) { fprintf(stderr, "ROL64 35 failed\n"); err++; } + if (ROL64(L64, 36) != CONST64(0x5667788112233445)) { fprintf(stderr, "ROL64 36 failed\n"); err++; } + if (ROL64(L64, 37) != CONST64(0xaccef1022446688a)) { fprintf(stderr, "ROL64 37 failed\n"); err++; } + if (ROL64(L64, 38) != CONST64(0x599de204488cd115)) { fprintf(stderr, "ROL64 38 failed\n"); err++; } + if (ROL64(L64, 39) != CONST64(0xb33bc4089119a22a)) { fprintf(stderr, "ROL64 39 failed\n"); err++; } + if (ROL64(L64, 40) != CONST64(0x6677881122334455)) { fprintf(stderr, "ROL64 40 failed\n"); err++; } + if (ROL64(L64, 41) != CONST64(0xccef1022446688aa)) { fprintf(stderr, "ROL64 41 failed\n"); err++; } + if (ROL64(L64, 42) != CONST64(0x99de204488cd1155)) { fprintf(stderr, "ROL64 42 failed\n"); err++; } + if (ROL64(L64, 43) != CONST64(0x33bc4089119a22ab)) { fprintf(stderr, "ROL64 43 failed\n"); err++; } + if (ROL64(L64, 44) != CONST64(0x6778811223344556)) { fprintf(stderr, "ROL64 44 failed\n"); err++; } + if (ROL64(L64, 45) != CONST64(0xcef1022446688aac)) { fprintf(stderr, "ROL64 45 failed\n"); err++; } + if (ROL64(L64, 46) != CONST64(0x9de204488cd11559)) { fprintf(stderr, "ROL64 46 failed\n"); err++; } + if (ROL64(L64, 47) != CONST64(0x3bc4089119a22ab3)) { fprintf(stderr, "ROL64 47 failed\n"); err++; } + if (ROL64(L64, 48) != CONST64(0x7788112233445566)) { fprintf(stderr, "ROL64 48 failed\n"); err++; } + if (ROL64(L64, 49) != CONST64(0xef1022446688aacc)) { fprintf(stderr, "ROL64 49 failed\n"); err++; } + if (ROL64(L64, 50) != CONST64(0xde204488cd115599)) { fprintf(stderr, "ROL64 50 failed\n"); err++; } + if (ROL64(L64, 51) != CONST64(0xbc4089119a22ab33)) { fprintf(stderr, "ROL64 51 failed\n"); err++; } + if (ROL64(L64, 52) != CONST64(0x7881122334455667)) { fprintf(stderr, "ROL64 52 failed\n"); err++; } + if (ROL64(L64, 53) != CONST64(0xf1022446688aacce)) { fprintf(stderr, "ROL64 53 failed\n"); err++; } + if (ROL64(L64, 54) != CONST64(0xe204488cd115599d)) { fprintf(stderr, "ROL64 54 failed\n"); err++; } + if (ROL64(L64, 55) != CONST64(0xc4089119a22ab33b)) { fprintf(stderr, "ROL64 55 failed\n"); err++; } + if (ROL64(L64, 56) != CONST64(0x8811223344556677)) { fprintf(stderr, "ROL64 56 failed\n"); err++; } + if (ROL64(L64, 57) != CONST64(0x1022446688aaccef)) { fprintf(stderr, "ROL64 57 failed\n"); err++; } + if (ROL64(L64, 58) != CONST64(0x204488cd115599de)) { fprintf(stderr, "ROL64 58 failed\n"); err++; } + if (ROL64(L64, 59) != CONST64(0x4089119a22ab33bc)) { fprintf(stderr, "ROL64 59 failed\n"); err++; } + if (ROL64(L64, 60) != CONST64(0x8112233445566778)) { fprintf(stderr, "ROL64 60 failed\n"); err++; } + if (ROL64(L64, 61) != CONST64(0x022446688aaccef1)) { fprintf(stderr, "ROL64 61 failed\n"); err++; } + if (ROL64(L64, 62) != CONST64(0x04488cd115599de2)) { fprintf(stderr, "ROL64 62 failed\n"); err++; } + if (ROL64(L64, 63) != CONST64(0x089119a22ab33bc4)) { fprintf(stderr, "ROL64 63 failed\n"); err++; } + /* RORc */ + if (RORc(L32, 0 ) != 0x12345678UL) { fprintf(stderr, "RORc 0 failed\n"); err++; } + if (RORc(L32, 1 ) != 0x091a2b3cUL) { fprintf(stderr, "RORc 1 failed\n"); err++; } + if (RORc(L32, 2 ) != 0x048d159eUL) { fprintf(stderr, "RORc 2 failed\n"); err++; } + if (RORc(L32, 3 ) != 0x02468acfUL) { fprintf(stderr, "RORc 3 failed\n"); err++; } + if (RORc(L32, 4 ) != 0x81234567UL) { fprintf(stderr, "RORc 4 failed\n"); err++; } + if (RORc(L32, 5 ) != 0xc091a2b3UL) { fprintf(stderr, "RORc 5 failed\n"); err++; } + if (RORc(L32, 6 ) != 0xe048d159UL) { fprintf(stderr, "RORc 6 failed\n"); err++; } + if (RORc(L32, 7 ) != 0xf02468acUL) { fprintf(stderr, "RORc 7 failed\n"); err++; } + if (RORc(L32, 8 ) != 0x78123456UL) { fprintf(stderr, "RORc 8 failed\n"); err++; } + if (RORc(L32, 9 ) != 0x3c091a2bUL) { fprintf(stderr, "RORc 9 failed\n"); err++; } + if (RORc(L32, 10) != 0x9e048d15UL) { fprintf(stderr, "RORc 10 failed\n"); err++; } + if (RORc(L32, 11) != 0xcf02468aUL) { fprintf(stderr, "RORc 11 failed\n"); err++; } + if (RORc(L32, 12) != 0x67812345UL) { fprintf(stderr, "RORc 12 failed\n"); err++; } + if (RORc(L32, 13) != 0xb3c091a2UL) { fprintf(stderr, "RORc 13 failed\n"); err++; } + if (RORc(L32, 14) != 0x59e048d1UL) { fprintf(stderr, "RORc 14 failed\n"); err++; } + if (RORc(L32, 15) != 0xacf02468UL) { fprintf(stderr, "RORc 15 failed\n"); err++; } + if (RORc(L32, 16) != 0x56781234UL) { fprintf(stderr, "RORc 16 failed\n"); err++; } + if (RORc(L32, 17) != 0x2b3c091aUL) { fprintf(stderr, "RORc 17 failed\n"); err++; } + if (RORc(L32, 18) != 0x159e048dUL) { fprintf(stderr, "RORc 18 failed\n"); err++; } + if (RORc(L32, 19) != 0x8acf0246UL) { fprintf(stderr, "RORc 19 failed\n"); err++; } + if (RORc(L32, 20) != 0x45678123UL) { fprintf(stderr, "RORc 20 failed\n"); err++; } + if (RORc(L32, 21) != 0xa2b3c091UL) { fprintf(stderr, "RORc 21 failed\n"); err++; } + if (RORc(L32, 22) != 0xd159e048UL) { fprintf(stderr, "RORc 22 failed\n"); err++; } + if (RORc(L32, 23) != 0x68acf024UL) { fprintf(stderr, "RORc 23 failed\n"); err++; } + if (RORc(L32, 24) != 0x34567812UL) { fprintf(stderr, "RORc 24 failed\n"); err++; } + if (RORc(L32, 25) != 0x1a2b3c09UL) { fprintf(stderr, "RORc 25 failed\n"); err++; } + if (RORc(L32, 26) != 0x8d159e04UL) { fprintf(stderr, "RORc 26 failed\n"); err++; } + if (RORc(L32, 27) != 0x468acf02UL) { fprintf(stderr, "RORc 27 failed\n"); err++; } + if (RORc(L32, 28) != 0x23456781UL) { fprintf(stderr, "RORc 28 failed\n"); err++; } + if (RORc(L32, 29) != 0x91a2b3c0UL) { fprintf(stderr, "RORc 29 failed\n"); err++; } + if (RORc(L32, 30) != 0x48d159e0UL) { fprintf(stderr, "RORc 30 failed\n"); err++; } + if (RORc(L32, 31) != 0x2468acf0UL) { fprintf(stderr, "RORc 31 failed\n"); err++; } + /* ROR64c */ + if (ROR64c(L64, 0 ) != CONST64(0x1122334455667788)) { fprintf(stderr, "ROR64c 0 failed\n"); err++; } + if (ROR64c(L64, 1 ) != CONST64(0x089119a22ab33bc4)) { fprintf(stderr, "ROR64c 1 failed\n"); err++; } + if (ROR64c(L64, 2 ) != CONST64(0x04488cd115599de2)) { fprintf(stderr, "ROR64c 2 failed\n"); err++; } + if (ROR64c(L64, 3 ) != CONST64(0x022446688aaccef1)) { fprintf(stderr, "ROR64c 3 failed\n"); err++; } + if (ROR64c(L64, 4 ) != CONST64(0x8112233445566778)) { fprintf(stderr, "ROR64c 4 failed\n"); err++; } + if (ROR64c(L64, 5 ) != CONST64(0x4089119a22ab33bc)) { fprintf(stderr, "ROR64c 5 failed\n"); err++; } + if (ROR64c(L64, 6 ) != CONST64(0x204488cd115599de)) { fprintf(stderr, "ROR64c 6 failed\n"); err++; } + if (ROR64c(L64, 7 ) != CONST64(0x1022446688aaccef)) { fprintf(stderr, "ROR64c 7 failed\n"); err++; } + if (ROR64c(L64, 8 ) != CONST64(0x8811223344556677)) { fprintf(stderr, "ROR64c 8 failed\n"); err++; } + if (ROR64c(L64, 9 ) != CONST64(0xc4089119a22ab33b)) { fprintf(stderr, "ROR64c 9 failed\n"); err++; } + if (ROR64c(L64, 10) != CONST64(0xe204488cd115599d)) { fprintf(stderr, "ROR64c 10 failed\n"); err++; } + if (ROR64c(L64, 11) != CONST64(0xf1022446688aacce)) { fprintf(stderr, "ROR64c 11 failed\n"); err++; } + if (ROR64c(L64, 12) != CONST64(0x7881122334455667)) { fprintf(stderr, "ROR64c 12 failed\n"); err++; } + if (ROR64c(L64, 13) != CONST64(0xbc4089119a22ab33)) { fprintf(stderr, "ROR64c 13 failed\n"); err++; } + if (ROR64c(L64, 14) != CONST64(0xde204488cd115599)) { fprintf(stderr, "ROR64c 14 failed\n"); err++; } + if (ROR64c(L64, 15) != CONST64(0xef1022446688aacc)) { fprintf(stderr, "ROR64c 15 failed\n"); err++; } + if (ROR64c(L64, 16) != CONST64(0x7788112233445566)) { fprintf(stderr, "ROR64c 16 failed\n"); err++; } + if (ROR64c(L64, 17) != CONST64(0x3bc4089119a22ab3)) { fprintf(stderr, "ROR64c 17 failed\n"); err++; } + if (ROR64c(L64, 18) != CONST64(0x9de204488cd11559)) { fprintf(stderr, "ROR64c 18 failed\n"); err++; } + if (ROR64c(L64, 19) != CONST64(0xcef1022446688aac)) { fprintf(stderr, "ROR64c 19 failed\n"); err++; } + if (ROR64c(L64, 20) != CONST64(0x6778811223344556)) { fprintf(stderr, "ROR64c 20 failed\n"); err++; } + if (ROR64c(L64, 21) != CONST64(0x33bc4089119a22ab)) { fprintf(stderr, "ROR64c 21 failed\n"); err++; } + if (ROR64c(L64, 22) != CONST64(0x99de204488cd1155)) { fprintf(stderr, "ROR64c 22 failed\n"); err++; } + if (ROR64c(L64, 23) != CONST64(0xccef1022446688aa)) { fprintf(stderr, "ROR64c 23 failed\n"); err++; } + if (ROR64c(L64, 24) != CONST64(0x6677881122334455)) { fprintf(stderr, "ROR64c 24 failed\n"); err++; } + if (ROR64c(L64, 25) != CONST64(0xb33bc4089119a22a)) { fprintf(stderr, "ROR64c 25 failed\n"); err++; } + if (ROR64c(L64, 26) != CONST64(0x599de204488cd115)) { fprintf(stderr, "ROR64c 26 failed\n"); err++; } + if (ROR64c(L64, 27) != CONST64(0xaccef1022446688a)) { fprintf(stderr, "ROR64c 27 failed\n"); err++; } + if (ROR64c(L64, 28) != CONST64(0x5667788112233445)) { fprintf(stderr, "ROR64c 28 failed\n"); err++; } + if (ROR64c(L64, 29) != CONST64(0xab33bc4089119a22)) { fprintf(stderr, "ROR64c 29 failed\n"); err++; } + if (ROR64c(L64, 30) != CONST64(0x5599de204488cd11)) { fprintf(stderr, "ROR64c 30 failed\n"); err++; } + if (ROR64c(L64, 31) != CONST64(0xaaccef1022446688)) { fprintf(stderr, "ROR64c 31 failed\n"); err++; } + if (ROR64c(L64, 32) != CONST64(0x5566778811223344)) { fprintf(stderr, "ROR64c 32 failed\n"); err++; } + if (ROR64c(L64, 33) != CONST64(0x2ab33bc4089119a2)) { fprintf(stderr, "ROR64c 33 failed\n"); err++; } + if (ROR64c(L64, 34) != CONST64(0x15599de204488cd1)) { fprintf(stderr, "ROR64c 34 failed\n"); err++; } + if (ROR64c(L64, 35) != CONST64(0x8aaccef102244668)) { fprintf(stderr, "ROR64c 35 failed\n"); err++; } + if (ROR64c(L64, 36) != CONST64(0x4556677881122334)) { fprintf(stderr, "ROR64c 36 failed\n"); err++; } + if (ROR64c(L64, 37) != CONST64(0x22ab33bc4089119a)) { fprintf(stderr, "ROR64c 37 failed\n"); err++; } + if (ROR64c(L64, 38) != CONST64(0x115599de204488cd)) { fprintf(stderr, "ROR64c 38 failed\n"); err++; } + if (ROR64c(L64, 39) != CONST64(0x88aaccef10224466)) { fprintf(stderr, "ROR64c 39 failed\n"); err++; } + if (ROR64c(L64, 40) != CONST64(0x4455667788112233)) { fprintf(stderr, "ROR64c 40 failed\n"); err++; } + if (ROR64c(L64, 41) != CONST64(0xa22ab33bc4089119)) { fprintf(stderr, "ROR64c 41 failed\n"); err++; } + if (ROR64c(L64, 42) != CONST64(0xd115599de204488c)) { fprintf(stderr, "ROR64c 42 failed\n"); err++; } + if (ROR64c(L64, 43) != CONST64(0x688aaccef1022446)) { fprintf(stderr, "ROR64c 43 failed\n"); err++; } + if (ROR64c(L64, 44) != CONST64(0x3445566778811223)) { fprintf(stderr, "ROR64c 44 failed\n"); err++; } + if (ROR64c(L64, 45) != CONST64(0x9a22ab33bc408911)) { fprintf(stderr, "ROR64c 45 failed\n"); err++; } + if (ROR64c(L64, 46) != CONST64(0xcd115599de204488)) { fprintf(stderr, "ROR64c 46 failed\n"); err++; } + if (ROR64c(L64, 47) != CONST64(0x6688aaccef102244)) { fprintf(stderr, "ROR64c 47 failed\n"); err++; } + if (ROR64c(L64, 48) != CONST64(0x3344556677881122)) { fprintf(stderr, "ROR64c 48 failed\n"); err++; } + if (ROR64c(L64, 49) != CONST64(0x19a22ab33bc40891)) { fprintf(stderr, "ROR64c 49 failed\n"); err++; } + if (ROR64c(L64, 50) != CONST64(0x8cd115599de20448)) { fprintf(stderr, "ROR64c 50 failed\n"); err++; } + if (ROR64c(L64, 51) != CONST64(0x46688aaccef10224)) { fprintf(stderr, "ROR64c 51 failed\n"); err++; } + if (ROR64c(L64, 52) != CONST64(0x2334455667788112)) { fprintf(stderr, "ROR64c 52 failed\n"); err++; } + if (ROR64c(L64, 53) != CONST64(0x119a22ab33bc4089)) { fprintf(stderr, "ROR64c 53 failed\n"); err++; } + if (ROR64c(L64, 54) != CONST64(0x88cd115599de2044)) { fprintf(stderr, "ROR64c 54 failed\n"); err++; } + if (ROR64c(L64, 55) != CONST64(0x446688aaccef1022)) { fprintf(stderr, "ROR64c 55 failed\n"); err++; } + if (ROR64c(L64, 56) != CONST64(0x2233445566778811)) { fprintf(stderr, "ROR64c 56 failed\n"); err++; } + if (ROR64c(L64, 57) != CONST64(0x9119a22ab33bc408)) { fprintf(stderr, "ROR64c 57 failed\n"); err++; } + if (ROR64c(L64, 58) != CONST64(0x488cd115599de204)) { fprintf(stderr, "ROR64c 58 failed\n"); err++; } + if (ROR64c(L64, 59) != CONST64(0x2446688aaccef102)) { fprintf(stderr, "ROR64c 59 failed\n"); err++; } + if (ROR64c(L64, 60) != CONST64(0x1223344556677881)) { fprintf(stderr, "ROR64c 60 failed\n"); err++; } + if (ROR64c(L64, 61) != CONST64(0x89119a22ab33bc40)) { fprintf(stderr, "ROR64c 61 failed\n"); err++; } + if (ROR64c(L64, 62) != CONST64(0x4488cd115599de20)) { fprintf(stderr, "ROR64c 62 failed\n"); err++; } + if (ROR64c(L64, 63) != CONST64(0x22446688aaccef10)) { fprintf(stderr, "ROR64c 63 failed\n"); err++; } + /* ROLc */ + if (ROLc(L32, 0 ) != 0x12345678UL) { fprintf(stderr, "ROLc 0 failed\n"); err++; } + if (ROLc(L32, 1 ) != 0x2468acf0UL) { fprintf(stderr, "ROLc 1 failed\n"); err++; } + if (ROLc(L32, 2 ) != 0x48d159e0UL) { fprintf(stderr, "ROLc 2 failed\n"); err++; } + if (ROLc(L32, 3 ) != 0x91a2b3c0UL) { fprintf(stderr, "ROLc 3 failed\n"); err++; } + if (ROLc(L32, 4 ) != 0x23456781UL) { fprintf(stderr, "ROLc 4 failed\n"); err++; } + if (ROLc(L32, 5 ) != 0x468acf02UL) { fprintf(stderr, "ROLc 5 failed\n"); err++; } + if (ROLc(L32, 6 ) != 0x8d159e04UL) { fprintf(stderr, "ROLc 6 failed\n"); err++; } + if (ROLc(L32, 7 ) != 0x1a2b3c09UL) { fprintf(stderr, "ROLc 7 failed\n"); err++; } + if (ROLc(L32, 8 ) != 0x34567812UL) { fprintf(stderr, "ROLc 8 failed\n"); err++; } + if (ROLc(L32, 9 ) != 0x68acf024UL) { fprintf(stderr, "ROLc 9 failed\n"); err++; } + if (ROLc(L32, 10) != 0xd159e048UL) { fprintf(stderr, "ROLc 10 failed\n"); err++; } + if (ROLc(L32, 11) != 0xa2b3c091UL) { fprintf(stderr, "ROLc 11 failed\n"); err++; } + if (ROLc(L32, 12) != 0x45678123UL) { fprintf(stderr, "ROLc 12 failed\n"); err++; } + if (ROLc(L32, 13) != 0x8acf0246UL) { fprintf(stderr, "ROLc 13 failed\n"); err++; } + if (ROLc(L32, 14) != 0x159e048dUL) { fprintf(stderr, "ROLc 14 failed\n"); err++; } + if (ROLc(L32, 15) != 0x2b3c091aUL) { fprintf(stderr, "ROLc 15 failed\n"); err++; } + if (ROLc(L32, 16) != 0x56781234UL) { fprintf(stderr, "ROLc 16 failed\n"); err++; } + if (ROLc(L32, 17) != 0xacf02468UL) { fprintf(stderr, "ROLc 17 failed\n"); err++; } + if (ROLc(L32, 18) != 0x59e048d1UL) { fprintf(stderr, "ROLc 18 failed\n"); err++; } + if (ROLc(L32, 19) != 0xb3c091a2UL) { fprintf(stderr, "ROLc 19 failed\n"); err++; } + if (ROLc(L32, 20) != 0x67812345UL) { fprintf(stderr, "ROLc 20 failed\n"); err++; } + if (ROLc(L32, 21) != 0xcf02468aUL) { fprintf(stderr, "ROLc 21 failed\n"); err++; } + if (ROLc(L32, 22) != 0x9e048d15UL) { fprintf(stderr, "ROLc 22 failed\n"); err++; } + if (ROLc(L32, 23) != 0x3c091a2bUL) { fprintf(stderr, "ROLc 23 failed\n"); err++; } + if (ROLc(L32, 24) != 0x78123456UL) { fprintf(stderr, "ROLc 24 failed\n"); err++; } + if (ROLc(L32, 25) != 0xf02468acUL) { fprintf(stderr, "ROLc 25 failed\n"); err++; } + if (ROLc(L32, 26) != 0xe048d159UL) { fprintf(stderr, "ROLc 26 failed\n"); err++; } + if (ROLc(L32, 27) != 0xc091a2b3UL) { fprintf(stderr, "ROLc 27 failed\n"); err++; } + if (ROLc(L32, 28) != 0x81234567UL) { fprintf(stderr, "ROLc 28 failed\n"); err++; } + if (ROLc(L32, 29) != 0x02468acfUL) { fprintf(stderr, "ROLc 29 failed\n"); err++; } + if (ROLc(L32, 30) != 0x048d159eUL) { fprintf(stderr, "ROLc 30 failed\n"); err++; } + if (ROLc(L32, 31) != 0x091a2b3cUL) { fprintf(stderr, "ROLc 31 failed\n"); err++; } + /* ROL64c */ + if (ROL64c(L64, 0 ) != CONST64(0x1122334455667788)) { fprintf(stderr, "ROL64c 0 failed\n"); err++; } + if (ROL64c(L64, 1 ) != CONST64(0x22446688aaccef10)) { fprintf(stderr, "ROL64c 1 failed\n"); err++; } + if (ROL64c(L64, 2 ) != CONST64(0x4488cd115599de20)) { fprintf(stderr, "ROL64c 2 failed\n"); err++; } + if (ROL64c(L64, 3 ) != CONST64(0x89119a22ab33bc40)) { fprintf(stderr, "ROL64c 3 failed\n"); err++; } + if (ROL64c(L64, 4 ) != CONST64(0x1223344556677881)) { fprintf(stderr, "ROL64c 4 failed\n"); err++; } + if (ROL64c(L64, 5 ) != CONST64(0x2446688aaccef102)) { fprintf(stderr, "ROL64c 5 failed\n"); err++; } + if (ROL64c(L64, 6 ) != CONST64(0x488cd115599de204)) { fprintf(stderr, "ROL64c 6 failed\n"); err++; } + if (ROL64c(L64, 7 ) != CONST64(0x9119a22ab33bc408)) { fprintf(stderr, "ROL64c 7 failed\n"); err++; } + if (ROL64c(L64, 8 ) != CONST64(0x2233445566778811)) { fprintf(stderr, "ROL64c 8 failed\n"); err++; } + if (ROL64c(L64, 9 ) != CONST64(0x446688aaccef1022)) { fprintf(stderr, "ROL64c 9 failed\n"); err++; } + if (ROL64c(L64, 10) != CONST64(0x88cd115599de2044)) { fprintf(stderr, "ROL64c 10 failed\n"); err++; } + if (ROL64c(L64, 11) != CONST64(0x119a22ab33bc4089)) { fprintf(stderr, "ROL64c 11 failed\n"); err++; } + if (ROL64c(L64, 12) != CONST64(0x2334455667788112)) { fprintf(stderr, "ROL64c 12 failed\n"); err++; } + if (ROL64c(L64, 13) != CONST64(0x46688aaccef10224)) { fprintf(stderr, "ROL64c 13 failed\n"); err++; } + if (ROL64c(L64, 14) != CONST64(0x8cd115599de20448)) { fprintf(stderr, "ROL64c 14 failed\n"); err++; } + if (ROL64c(L64, 15) != CONST64(0x19a22ab33bc40891)) { fprintf(stderr, "ROL64c 15 failed\n"); err++; } + if (ROL64c(L64, 16) != CONST64(0x3344556677881122)) { fprintf(stderr, "ROL64c 16 failed\n"); err++; } + if (ROL64c(L64, 17) != CONST64(0x6688aaccef102244)) { fprintf(stderr, "ROL64c 17 failed\n"); err++; } + if (ROL64c(L64, 18) != CONST64(0xcd115599de204488)) { fprintf(stderr, "ROL64c 18 failed\n"); err++; } + if (ROL64c(L64, 19) != CONST64(0x9a22ab33bc408911)) { fprintf(stderr, "ROL64c 19 failed\n"); err++; } + if (ROL64c(L64, 20) != CONST64(0x3445566778811223)) { fprintf(stderr, "ROL64c 20 failed\n"); err++; } + if (ROL64c(L64, 21) != CONST64(0x688aaccef1022446)) { fprintf(stderr, "ROL64c 21 failed\n"); err++; } + if (ROL64c(L64, 22) != CONST64(0xd115599de204488c)) { fprintf(stderr, "ROL64c 22 failed\n"); err++; } + if (ROL64c(L64, 23) != CONST64(0xa22ab33bc4089119)) { fprintf(stderr, "ROL64c 23 failed\n"); err++; } + if (ROL64c(L64, 24) != CONST64(0x4455667788112233)) { fprintf(stderr, "ROL64c 24 failed\n"); err++; } + if (ROL64c(L64, 25) != CONST64(0x88aaccef10224466)) { fprintf(stderr, "ROL64c 25 failed\n"); err++; } + if (ROL64c(L64, 26) != CONST64(0x115599de204488cd)) { fprintf(stderr, "ROL64c 26 failed\n"); err++; } + if (ROL64c(L64, 27) != CONST64(0x22ab33bc4089119a)) { fprintf(stderr, "ROL64c 27 failed\n"); err++; } + if (ROL64c(L64, 28) != CONST64(0x4556677881122334)) { fprintf(stderr, "ROL64c 28 failed\n"); err++; } + if (ROL64c(L64, 29) != CONST64(0x8aaccef102244668)) { fprintf(stderr, "ROL64c 29 failed\n"); err++; } + if (ROL64c(L64, 30) != CONST64(0x15599de204488cd1)) { fprintf(stderr, "ROL64c 30 failed\n"); err++; } + if (ROL64c(L64, 31) != CONST64(0x2ab33bc4089119a2)) { fprintf(stderr, "ROL64c 31 failed\n"); err++; } + if (ROL64c(L64, 32) != CONST64(0x5566778811223344)) { fprintf(stderr, "ROL64c 32 failed\n"); err++; } + if (ROL64c(L64, 33) != CONST64(0xaaccef1022446688)) { fprintf(stderr, "ROL64c 33 failed\n"); err++; } + if (ROL64c(L64, 34) != CONST64(0x5599de204488cd11)) { fprintf(stderr, "ROL64c 34 failed\n"); err++; } + if (ROL64c(L64, 35) != CONST64(0xab33bc4089119a22)) { fprintf(stderr, "ROL64c 35 failed\n"); err++; } + if (ROL64c(L64, 36) != CONST64(0x5667788112233445)) { fprintf(stderr, "ROL64c 36 failed\n"); err++; } + if (ROL64c(L64, 37) != CONST64(0xaccef1022446688a)) { fprintf(stderr, "ROL64c 37 failed\n"); err++; } + if (ROL64c(L64, 38) != CONST64(0x599de204488cd115)) { fprintf(stderr, "ROL64c 38 failed\n"); err++; } + if (ROL64c(L64, 39) != CONST64(0xb33bc4089119a22a)) { fprintf(stderr, "ROL64c 39 failed\n"); err++; } + if (ROL64c(L64, 40) != CONST64(0x6677881122334455)) { fprintf(stderr, "ROL64c 40 failed\n"); err++; } + if (ROL64c(L64, 41) != CONST64(0xccef1022446688aa)) { fprintf(stderr, "ROL64c 41 failed\n"); err++; } + if (ROL64c(L64, 42) != CONST64(0x99de204488cd1155)) { fprintf(stderr, "ROL64c 42 failed\n"); err++; } + if (ROL64c(L64, 43) != CONST64(0x33bc4089119a22ab)) { fprintf(stderr, "ROL64c 43 failed\n"); err++; } + if (ROL64c(L64, 44) != CONST64(0x6778811223344556)) { fprintf(stderr, "ROL64c 44 failed\n"); err++; } + if (ROL64c(L64, 45) != CONST64(0xcef1022446688aac)) { fprintf(stderr, "ROL64c 45 failed\n"); err++; } + if (ROL64c(L64, 46) != CONST64(0x9de204488cd11559)) { fprintf(stderr, "ROL64c 46 failed\n"); err++; } + if (ROL64c(L64, 47) != CONST64(0x3bc4089119a22ab3)) { fprintf(stderr, "ROL64c 47 failed\n"); err++; } + if (ROL64c(L64, 48) != CONST64(0x7788112233445566)) { fprintf(stderr, "ROL64c 48 failed\n"); err++; } + if (ROL64c(L64, 49) != CONST64(0xef1022446688aacc)) { fprintf(stderr, "ROL64c 49 failed\n"); err++; } + if (ROL64c(L64, 50) != CONST64(0xde204488cd115599)) { fprintf(stderr, "ROL64c 50 failed\n"); err++; } + if (ROL64c(L64, 51) != CONST64(0xbc4089119a22ab33)) { fprintf(stderr, "ROL64c 51 failed\n"); err++; } + if (ROL64c(L64, 52) != CONST64(0x7881122334455667)) { fprintf(stderr, "ROL64c 52 failed\n"); err++; } + if (ROL64c(L64, 53) != CONST64(0xf1022446688aacce)) { fprintf(stderr, "ROL64c 53 failed\n"); err++; } + if (ROL64c(L64, 54) != CONST64(0xe204488cd115599d)) { fprintf(stderr, "ROL64c 54 failed\n"); err++; } + if (ROL64c(L64, 55) != CONST64(0xc4089119a22ab33b)) { fprintf(stderr, "ROL64c 55 failed\n"); err++; } + if (ROL64c(L64, 56) != CONST64(0x8811223344556677)) { fprintf(stderr, "ROL64c 56 failed\n"); err++; } + if (ROL64c(L64, 57) != CONST64(0x1022446688aaccef)) { fprintf(stderr, "ROL64c 57 failed\n"); err++; } + if (ROL64c(L64, 58) != CONST64(0x204488cd115599de)) { fprintf(stderr, "ROL64c 58 failed\n"); err++; } + if (ROL64c(L64, 59) != CONST64(0x4089119a22ab33bc)) { fprintf(stderr, "ROL64c 59 failed\n"); err++; } + if (ROL64c(L64, 60) != CONST64(0x8112233445566778)) { fprintf(stderr, "ROL64c 60 failed\n"); err++; } + if (ROL64c(L64, 61) != CONST64(0x022446688aaccef1)) { fprintf(stderr, "ROL64c 61 failed\n"); err++; } + if (ROL64c(L64, 62) != CONST64(0x04488cd115599de2)) { fprintf(stderr, "ROL64c 62 failed\n"); err++; } + if (ROL64c(L64, 63) != CONST64(0x089119a22ab33bc4)) { fprintf(stderr, "ROL64c 63 failed\n"); err++; } + + return err; +} diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/README.txt b/deps/libtomcrypt/tests/rsa-pkcs8/README.txt new file mode 100644 index 0000000..5051775 --- /dev/null +++ b/deps/libtomcrypt/tests/rsa-pkcs8/README.txt @@ -0,0 +1,29 @@ +# pkcs8 without password +openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in ../test.key -out key_pkcs8.der + +# password protected - PBES1 +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v1 PBE-MD2-RC2-64 -out key_pkcs8_pbe_md2_rc2_64.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v1 PBE-MD2-DES -out key_pkcs8_pbe_md2_des.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v1 PBE-MD5-DES -out key_pkcs8_pbe_md5_des.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v1 PBE-SHA1-RC2-64 -out key_pkcs8_pbe_sha1_rc2_64.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v1 PBE-MD5-RC2-64 -out key_pkcs8_pbe_md5_rc2_64.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v1 PBE-SHA1-DES -out key_pkcs8_pbe_sha1_des.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v1 PBE-SHA1-3DES -out key_pkcs8_pbe_sha1_3des.der + +# password protected - PBES2 +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 rc2 -out key_pkcs8_pbkdf2_rc2_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 des -out key_pkcs8_pbkdf2_des_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 des3 -out key_pkcs8_pbkdf2_des_ede3_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 des3 -v2prf hmacWithSHA224 -out key_pkcs8_pbkdf2_sha224_des_ede3_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 des3 -v2prf hmacWithSHA256 -out key_pkcs8_pbkdf2_sha256_des_ede3_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 des3 -v2prf hmacWithSHA384 -out key_pkcs8_pbkdf2_sha384_des_ede3_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 des3 -v2prf hmacWithSHA512 -out key_pkcs8_pbkdf2_sha512_des_ede3_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 aes128 -v2prf hmacWithSHA512 -out key_pkcs8_pbkdf2_sha512_aes128_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 aes192 -v2prf hmacWithSHA512 -out key_pkcs8_pbkdf2_sha512_aes192_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 aes256 -v2prf hmacWithSHA512 -out key_pkcs8_pbkdf2_sha512_aes256_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 aes256 -v2prf hmacWithSHA512-224 -out key_pkcs8_pbkdf2_sha512_224_aes256_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 aes256 -v2prf hmacWithSHA512-256 -out key_pkcs8_pbkdf2_sha512_256_aes256_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 rc2-40 -v2prf hmacWithSHA512 -out key_pkcs8_pbkdf2_sha512_rc2_40_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 rc2-40 -v2prf hmacWithSHA512-256 -out key_pkcs8_pbkdf2_sha512_256_rc2_40_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 rc2-64 -v2prf hmacWithSHA512 -out key_pkcs8_pbkdf2_sha512_rc2_64_cbc.der +openssl pkcs8 -topk8 -inform PEM -outform DER -passout pass:secret -in ../test.key -v2 rc2-64 -v2prf hmacWithSHA512-256 -out key_pkcs8_pbkdf2_sha512_256_rc2_64_cbc.der diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8.der new file mode 100644 index 0000000000000000000000000000000000000000..b8e023566840fd474cd28c96d6a4f31b9c8a2cbe GIT binary patch literal 636 zcmV-?0)zc9f&zE~0RS)!1_>&LNQUpVlaXNUIGCC0)c@5&zjz3irUCC zAgR}bF&R{{nuVvKw{;DU0 z)QC7qDsEf95;sS^1#7(9^X}vkjzMUAVH4Lv$bh~!kK720PpqWkb_~g5Y)M#??aZp& zB|8dWKZ{g4!%Z>gl%z!c0s{d60Rn-60LWsw>fS_C9afjwm!2BWFdhnsMTRLbqfMV- zWpm)xhmW@N2BU)9e60SPD4MSQ`~EKu*p~$3yC2c)4Z5RAe@Co}Ld&Ttsb`y zrBU=iV;=pz>YqWMsE{3R3R;yD5eV0zm-Qh7N^73j_#+Az<(h4T$|7HV|b`9#gaka)4YvS!NgJnDXgt zdIn6ac0KKkq0X%vy|jHOyyFfyjhWa5wWDzYKyB;8EiUk0q=+#EDFBMml_{Hp&vn}| z<9a9FI&?4$c1+YzDnKnc*_mUhU4X7r%9K9^BOdq#1mU&6z9RME?;jT*)P`UsMoan({%HI{Kpi;@h`>A$UG z3#I9?0zm-W%qPg?++s-8o3Hh&VD=&XQ{uN>3CS9v1gZRCEL{XxI$AmLN+DKf{mdYv Wk9Zhbc|9(UeufI>s58L?7fPR5fFyzd literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md2_des.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md2_des.der new file mode 100644 index 0000000000000000000000000000000000000000..f424601162c544844b123a5f5051c04c528e8b6d GIT binary patch literal 677 zcmV;W0$Tkrf&!s18wLp~hDe6@4FLrKFb)I=bx%=bgVmn(0s;sC1cCy9J-2OJb;cTw zP$c3^e^FuC!0(uY1(={$3_L(O`Y~h5fr+@PScUE_MBc$mk8m(selk^_hedy-kaN=> zncOsh>;`$?@ixY<4hPrk^8~PtwDtEj#>J{03WfE$fI=(9QJ8GOmZFki6#5Qa6)+4# zBy4R*_}zLhM5wWj==T`Kcq7;EjXl&`&D8dPblIEk=FX~qw*fLD^;$R?8jKio@^oTeko z51%Z`6~_>SI(LWUr-_M2HVpv)y;R4808<<8tnko8Q{)FLyBtzzmWz4&vpR?6v=v;^ L$OI4jeP_D6q9aHG literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md2_rc2_64.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md2_rc2_64.der new file mode 100644 index 0000000000000000000000000000000000000000..4471fa2f822328aeb3ab5bd49c28eba6ab7e90ad GIT binary patch literal 677 zcmV;W0$Tkrf&!s18wLp~hDe6@4FLrNFb)I=c6^2dc-ob30s;sC1cCy9&e<$8Q{XT* zFr0t=Ep>a)qqx__4j?My^aN!cr?@ZV{JoO;wdJ(`5Nd1~maBv83pKZ>RcInNWtM)&R3ROpX29qIwqNCiJk)?%F)j1R|B!cWy~x1+mY#+rd+ z;zw&(`O&R~n$~X3c_bn_+r4gmNsXZ?d&Nb4>}|DX+RUL+?)mxff@;jvzZkxOm$=+@ zm_5s*ggJVs;w9`rn_RrhAN=9(jztsfFM${d8~Pag_pP-UuH*pC8NsV-xwW*By{~7H zhRedyvBtCR^u~*UJ)ij~<5lnBqyS=QEqF}?Ra$@P#m8DLCIaj!6q?_!8^pL`rujyR1G};z7UZtzexC>H(h>`0tBgp@oH>{J>~($Gkkmj8E1KjazQD}36T+UWVVIYe@ zrp;M9+Yr*fUM_7s3GdNJ@c9I&cHB$7l?M8jSjrR0?zi=?7L~dF> z&+kTz=+MPs;Dn%gOls)Sr$|zfHmXf?WB)y+(pjU2+5Q=%s@0s;sC1cCy92&i#3)&kp* z$Lt=h`ogCxgf_PSH{%#CK`jle_J#&2-Sq?rRIQ8|+C;MwXPj zcAVvxr0Mkc9KgeMW7bwuwE~m|)3Q zSJJfI0!NOu7vz~EKSx{}EkbRM^m5H6X&HDP6tv=j5W--GVIw(PHA23&vT0@aaO;_w z?Im-F=Yvce{Ij|xVff-Q6 z04Uy~02XJsTGd}-KnyNN_m*Y_Dm_XP5M|P9|H1>p6v@=E9PnfeYMdkEy1BwDc z$JbYWH(Nj(_|z9w84IK1mxZpMDrzI4;Dx9Pev)gxQ#9^w$1~Q*-!K1NU3k5D)C3=SaGwgg?Av|_9g`ZZOQYxyh09bT@2*==lzSI26a)HV^NBw_? za^j}&vsIwn#Rb}_?J*o^u;s3G+h?#HzDfNUyoqO>sc|z;pA4JsN<2G1<;ABbNdbzW zlM4U$x;LM#+REL7Ba{>5TtOl=X0s-XRI=>15S09F1YSBQJsqu6Tx6gQj6BMd0SX>) Lzca-Pkeor#gAG5S literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md5_rc2_64.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_md5_rc2_64.der new file mode 100644 index 0000000000000000000000000000000000000000..073f79eb964a27d481a9426c8af8b46ef5ffaa73 GIT binary patch literal 677 zcmV;W0$Tkrf&!s18wLp~hDe6@4FLrPFb)I=GL!=z1sex;0s;sC1cCy9ro5%hiqbXw zRk0-tzr!V59jmM#Q(FuT|0E;JtGzCO)RO9GbnFb{#9kFWdD;OZD}2JOgsY^?kh;X~ zBb_NmEXrKS0|G4sa}-W12b_zXN`4q`6Mdc-F?drVqdO25v-U z*xocwA!8anjDn7SK|V%2y$Y5y?Uk5${gO$eL{_Z);+k*j+bCUk5zo)59kb)QB~o>; zMumcNMNw!~fQN*AsiO96i3A8Q8EDPq&m@!uj zGX}8FQ!b}x#jqlzd3%|hj=npfZuiK9iCOQ z`ST{VF(Ln%(MbXlQqSI}FoZt28`w4VO5|xB-Ay+i^x^1Je2E3tGO+}DsZlO*K4sj| zct=6{WxQ7{^^G07g_q5;wHt^0O4nP;?|u>FC}bU8xQlpx(EAPbo^ z=#=2=U0*l}7qHZ8AJVJWSvS=sVSuUtrI9RIVWs0S&O$y_baLmHo7-K1xvDJuneTCO zFK-Ow84u~F;8$%bIPKy%M~)+;33wIE>)gFWk}#Tpynm|~pKo5b=X4g7k8lr8S!RbW75aLOjGUa;?8+ID|UB)BrS(ejB>vGKDL3;C`7 z53=^rm%f?W9fbj3i8@~~!?$T+^GY?Eqyhp0ntOZ$7FgdZGDBBlbs}5Z5&H+nD12h@ z&xwSh{#_AgoBqf^XREGQuBo+mNPiH`eARiXl#6%nq2-~P@mL{FHVbKDzPN!cmBx(I z*i{;?CD@Ica||^EVT$96VXT%itn@6|iFC9j(Hlm*x)ZN_lNAXemK~g3;uG032vIlI2isp=gBr@V7*_YERh1ZqCTWUf!PT{${$BcoSRKQ1;f9sYfH(5?`>_8R;$ MozmCVbN9Ac!$DU{I{*Lx literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_sha1_des.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbe_sha1_des.der new file mode 100644 index 0000000000000000000000000000000000000000..07c1e03ed01ded6f14ebc329ed5c09a7acd2d6ca GIT binary patch literal 677 zcmV;W0$Tkrf&!s18wLp~hDe6@4FLrTFb)I=kddjiR@IjL0s;sC1cCy9mx{@L=)W zC0kUbUby3i!!svBH!ULB+MLMrt>}agu}I;@=x&v^O}qB2ygfeyiq25MtR$@Nrf-nd zXUW2biiw#-d0PPTzhf2Q9AAh9;gq?*qNUpVTyaP(w;2vH9CoIRRd}C8UUAHubw`J3H8a z5lrjVfNQfJvEQaBK0&lRp9L_vtI%GPN0&zXU0tZl(d#6Bnqzv!Ig4L^Bg4PCz2~>! zk9uDj(`x)JQgqW&tebRyNs)Sv$SvFH0qsdr1c6AJhDkm#Xcm*LK9tjb zGF!)_N$+yYLNX)9`_)1JgRr8eJ6FmMZpjv#=tUYoceQocST&pyw-|%#p_=qV(sL&$ zz=eM!9-fr-3H*&ja=pKT zuQT`v9{^C@1;};j)bi@M2TPnG9nLlh5^nPQbc@!dvv5(rskjEGL|UlBF8AB3X+>=S z5r{lSLZ;C|VV6M)AiCMQRvUD`MmvY-rzRyYcA_AUI0(N$es(0ZddF5<|OSCj;Xbf%!58~8y=sEAL!uBdQ4p+Ke&Li>k_kOppn|f9jTynx^l%KttwvEFK z+UOYjQYHe)tg<9gAI|ES`vr*qC(ghUIDqBYU&zQWzWc5JV!6BO7yj+cu#Hj0`Wt>J zv%5YYHJ*BgHBqy@99G6DZ$W^J^F5!1=m$y%SC0t2Z#{|g{nUET7!VOLPJD{1+&hnX zDkY;mrM{B^fKYO=P$b4bc#$fJ^aziApz@)*1xL%1Y4uRRsqg-H)Q$D#NIz`9UcNtf zEjC~h6f=dkW@+tC{@W??(A)(p1$Th2eP5K7i;r?t*US$F22UMG`UFN?!60~N4*Qr^ zOr7xRGGkKCD#D(;WP#9`b7H=4ktOG%2U`w1b2-WE9|Dpa3mFghZ@abfWcO^T$Wzt( zbd20v(q*zN2j^?Nq&%J>PvMqGy0k5##+9-C=t=8$iGoS=b|yzeCy#`IG?VT*X=i&3 z6M&0b!XyKqg>9!DiQNXa+Cu1UiUGk(PXSDJIdHYGag$P#Gto%h;#cMR36PB~ z^?EwBfrkSw@78z;z|;Uh5bIYfsjbH`AgkOwJv9NJ-vlj^(1`%_>F$2m}-AqN$ literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_des_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_des_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..f00879e4da840d91a01a45e28a94ad7d1bd53815 GIT binary patch literal 711 zcmV;&0yzCJf&#-ZJq8IXhDe6@4FLrWFfcG11_>&LNQU&4g?73-tS1+#+^$7 z0tf&w5e5Y-4g&%Q1PG!FMB3cWF?a-m0)T_3EGKSm-y}jBm23?bVq>SR9#2B`(h1LZ zVe1_#JSn=?@1d5{Qa-T>3Q`F8S7OY(*3)P*xsRpFf$pIXBkh8@gFYsFiBQ`AE^R$f z3*$&iwi<4gvWbBqH&qWVUbK(7Up3kNo>f64dZ^qR0WBmEdmeV_(zDI+ktE?j+dKLD z;VVRgZnuBbDf(WGN_~w>`c$KiS;CE8Es+H>jWfZ0 zq`uGf0_!ta=AKd%J_hrrV`?&U1SKqEYRy6fwVHUSb$)iKMd9fKBzTYx__^Nc5}XMt zd@2WnSwtozEIhvYh$Us5BF$=bzBA{KOA)rKVMywC)>yFkR*hG@t{}Fld17kC3q?Nm zvH0$f&%zG3Dl{$p49 zxUU?&eg#Rn=`*3zd{`V-{9O=aNwS)waisG+13|`5 tFAC7#aqCn;xtz17o5uZL-KQgQ*xShg;QX1`>;lVji%m$hwF^%L@i{)#QTqS@ literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_des_ede3_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_des_ede3_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..825e4bb6c35b22c32217164e05ccb96d9a46da37 GIT binary patch literal 714 zcmV;*0yX_Gf&#`cKn4jahDe6@4FLrWFf%Y41_>&LNQU&4g?5&eBHeJKPBM; z0tf&w6b1+?hDe6@4Fd-R2o@eG1lo7%2n2!xfV$D!wiBLg=%xHSb2TyZe~BCwKhKvvooi9z9iF!065)=sAdTlrAoX#s>RiqR5gZ zMC;Js!X*$!6Gx%={T?+&L5Ex-%G&^uI4;ag{mY4EBM=1=+1wpd5jt9v(P|y<>UmNU z1-uZ0+|(c2$X*JWW&44PlOlCT<~Qo0{>$jSZ~Xd*dJ;UwmT%Qc&tSb2&{8vG-=V8Q zkA>EM)p4a@ShyteVK7}eprjvNmbBs7#{BK36~B+#r1aNR&sJ)duK%MBuLgd3is0Gp zSGI4;CqUu+lY9PiR!0W;uKO9ZJxR<)Q^sNc{>s_nub3oXT>cD+TJDQL<-OG-4T# wCMY_E_;5(DD!lG$N(yALCNj~I-EttJ+T754wbnQ0G6X>8-?zO?IJ(oaVez6}p#T5? literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_rc2_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_rc2_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..d71aa789ddb3e21d897ce6ed3311a481d0d0df6d GIT binary patch literal 722 zcmV;@0xkV8f&$JkNCpWihDe6@4FLrWFgq|F1_>&LNQU&5d;VV2y(AT?~w-r z0tf&C0T3`51_&yKNQUHChhW);q7pp5aZlUP_y=dMEBO?tIqV26y`tvCD|%KM)ePnOU>CO+ zIL}blGU(O}yJvIpIdd==vX#vWT82Umyl@5jljX*zNc$0`Uv zQ0U$$n{8|bQzPxahVw#pgHEFhRYp-kOl+h-qhl9wO2Za#K;?WsK{1xXObFZp4z%Kv zHXN9Gr=~kVFJylyN?|pWrIROCbKXXBQ)B+23}4m#FfaOmIg{k2S|#n*W1Sj;+15^* z@xpc*UDl+lfmFS($(j*R7Wa&jK0!nuM&_t##+#05h&Uw_M2;9pZWA?Yw{G2+aX)pTLI&yoX;TL_%XMEs6XbeKJYgObjWu_1cOc-ZVY@zs6BQW<=I8+? zp`dCO)gp2f*(JA@p!iO z;w#J340oQXRpn*WusC!u9s`av96ESG9v$gOb|ypK_#!5Sng|p1xpTbO+lMcQnyA|k zSjvk^7u{dBBbNEYGLJyY6}fn-GWLBwBN%F5FzqvU2lYy)~K$Pk@@ zY%|VLm5n}M+O=vnHa}5$D%p~*qkn|y)|~aui`~1Nn)RIeuz#{aWb{&OT6W>+D7SyP z;-Pl`SVHhs~w-`GYdYzRC#N>}H8mzSI2S E8a-@Lpa1{> literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha224_des_ede3_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha224_des_ede3_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..a94765aaf3ee64be255444d5dc419056283ee54b GIT binary patch literal 728 zcmV;}0w?`2f&$bqP6i1ohDe6@4FLrWFhMXW1_>&LNQU&90Ulg4*!7R@uH^! z0tf&w3auAz0QSoE zlf*h{!2H%v&6ZJo67@B5A@v=<*;MQqwJsMo5Gi)ytbb+Po=l+4fQ;H@4lh{_md=L4 zAoE-$NJ;zUnFsLT60q1wgd%j&8xnlg_VBLqq#cERUm`wwm#rV1;8l!@`d6^xielRavTsNS@?;gV1mrJCp-@AcIy$Jt3$L08h)NwnkuHxvAN3{`QE z|5_3Q1Aj!2hcL`i zx4s3XMX*;T5gUBekrG^|?)t(KY>5m>Q>{FtZbA9=v{=?k>Fp);WAvK*B*aClqird9 z-Zr}rWS~_#0J>#l8xs5uyTI_gLvz&&;#%AvvmQp`!j)gQNEFzl%s$`t7Q3Y%9s>Z;=F<=AWwC?Sp8_Cz~Cd_ zfKt*b|Fos_SMc&mJ1(6zHv;G97j%%vn)(BnkeK_LOA=2g)^uaHD%QkZRZk0nZ74v^ KlQ)o291j>*Ra4Rc literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha256_des_ede3_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha256_des_ede3_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..7e4a159c2a38dcffc958902060ba2dd921f659da GIT binary patch literal 728 zcmV;}0w?`2f&$bqP6i1ohDe6@4FLrWFhMXW1_>&LNQU&90Ula5dzG@n+B%> z0tf&w3v2ZxKSbr3;cILn=3;qZZ|VuUHJa{chwjkqNmY!xgE%}Z+tZ2>cDj#i3tvyX+!pW z0xA#y%Dh+D+7^jjM@iiV!Z5@pxO#W*SrK-2;rGqeFcR7p9C(%nWi@>t__~_c%TGUc zUtynJKLP=>oB;Wn=g~jHscaD})liXgR^u%#O*)^<`PBMoT}DTpDJTDT*n+~2E8j>Q zw(}E68S>LyZp6E&+I2Q%BtZZH@xnFO!KP*5j{BS`Bdk}x;{B7IK2Bo$h zhi?r=%)_%#-}^aP;~|?d9QMN!U@%O4^S&aBlltuKFz{)W;NL3C^Jy8pES_(ngaZWi zO?`9vdvoRl6^&~>6iizRW4Kw3=8LW>QB)o9*M3b^qdjG}j!K6{!T5!3=zU;n*zxqr9mhN8Zta95D~z z6sW1TGlY^2b$_D KHi$pv!7-i(E=a8a literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha384_des_ede3_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha384_des_ede3_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..0ae0ea4c5727aa278ae8a714f53f897266ce5da1 GIT binary patch literal 728 zcmV;}0w?`2f&$bqP6i1ohDe6@4FLrWFhMXW1_>&LNQU&90Ulg&%9__R{_-m z0tf&w3p00 zrXg|A=Fk9bweBzUhhm%!6z^y2iE8pT^GgImC%_~8h*86-WM!cpNJkhD@-ob5;3UquvjsmUd>lee? z5ZWNEZM<05sJ&Yt2K8APTO+@}R|Lpu8M0zV&I>8K(V!Zv!uUBTh}5dZHw$6ZXK=V| z#z+eu4TTC&Tpq}z&dg=n;&`NfF4LL2G#Qn?WoqNRxS+;s?@^V{K^u{>blFtkxgF9* zP$<*Oro6m_4C`=29m=|&hY%@JxT&0V7sT~4EMp)~cm1P5j8%X2a$0TUlhQ5ey$pI{ zJvfU^;~d?5@`EPSMEik$IdB)VIgBDx(x5~U8&g*Du(}6Yu&`CArGY&_8IGh8GW__b zsKmLrU&_xsanc@@AJy@aPL!%UFUb)GCm`uKOf{07E8(8(S1sM3$_Nz`scVv{r^fL5 zr5v!|mv){2bK}78L2N=RR_p35!eV8v*er{9n$!IkDxtqznT*Juo_JcL;Ul^U# K>Tr7%3l4i*1zYF< literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_224_aes256_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_224_aes256_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..6237517124712723cac98013611028c50402764c GIT binary patch literal 737 zcmV<70v`P^f&$$zR|W|xhDe6@4FLrWFiJ2f1_>&LNQU&90Uk>dPT$e3quP6 z0tf&w39rEBi?6*nVb<&85?ZV8_$yF$$b*q<##^ zK2;#D0WszZUhZgH$zk$*drE55MKuKLBurfogaKk*|4SJp>ON3>O;Yuqyr<_!saPsq zXoa-0z~y8@P}7d0Bq%v?{;d4|X+apd>pBreFT{pmBE(GZSv?iLHYT|NokB?&5qfuI z;FhvFJNA)+eMzH0?iN>+x=ew7pli66TBy&~`%+bvhMy!C+uoJcuYDANVE{ify|v88 z5zaByePir=?25=saj}h|`Q2bOi$~$m7N1JkiLkss{-&DZdXrikZ^TF{dvi@K(;C28 zo~BtG;yr#<+XDpn;NLa&gJ*AXiQ+fZFki_AH}w%Oip~=Vui&Avcg7a=>0T7LrwF4U zva;}l+J;#x^P|-FUqMXkKit}@(;6be>6UJJO*iiv79x>U&-yO?Hgojzo8IJn%oy|M~Lj2{2`9-`AG$ASfM`_up3vAE3KLGG*r ze=YrSBGLWa?V?I|HHl}O+5|eOI%Tk%WpaLqd;HQ94xvX_gzG<&LNQU&90UmRGPBT#MYhiZ z0tf&w3mIB zsm zi2+Upl%#VVStS$i_7!a=`M5loTT+_0eR>#CX|*p@e8YWilF1Vc#yswpd#NE)p;=!D zAfDcV3Umuu*SV3|tA8?-qabQap{2-@kw#U`qHQKeRt$DinYnGHIz#ia+m~`+A0}4- z^ox0C=%)q0S_IrT*5tmrd``BpAnuPB^PSoOxK##MY`Sz3xq*A4_lj@*BGEcB7CTSU z02}(<6Wdg=)v=tx9mi;RQ{@j(rg^10Who^Z8NS@pdeNHucALucGn2bUpQrsfvEO)n z`H2TL&#Su$pOrJ+z{J%7a{0!pJ}L_seIg2VQ`!P>T{}}2?{6n@=_an++Qf3?DL}wF z9G67+{Q1=1Dz8&JPK_|ZMAVF<`ixOp|F$st4GloYM$i(W{6&upP5>E=-wa}+Pk@+- zqq`EPpt+^|r$5O8Iux(VU5}BShD!=bsv)r9{_y7U0jQt992`RZLP|G`$5m&ZLieXg zo($Oc+XL_@`H}lx}hZFJ#_f=u8hi`PL{g T8X3tnF&e;o#3^iMXQV8j2-{d? literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_256_rc2_40_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_256_rc2_40_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..232cbba569b0f047979e87b0019989aebb6d6317 GIT binary patch literal 737 zcmV<70v`P^f&$$zR|W|xhDe6@4FLrWFiJ2i1_>&LNQU&9|Q<%v(av+YVy7U z0tf&C0R=D&1_&yKNQU~+G>u~?ZJxqE39z=!;wf0|VS6<4#_Hr6%NU7XMCg1R!0 z&W6fa)!-7mtvm*=Z}mC{I3<{}7~Tt+eEv)eW=ir4L+t>ElbZpST9W$ea`9)Un>%!v z7m zg~`MT{(Hwv=;{5RH`JR^8ZFrA^D%wvwgym>JuE{aCi2*{@6+W2)+1dNJ7FN6dErW( z2w@fuP*hvD#+Kb9UD|#h6Q~v2TaH@gTf!4dI)obNfp-UaS&*A8{HsAPfQuqw0GY;j z>Op`80?0JZYBK+)!IZYKA{qFtP4G2YJShR&qij}z2Mu6L>fK67yYUCcp#Vbi1sEd& zQV^blGkP0v=`myGC1?dxYmDhVN~<;P!Gp0pzO8{_ z-`W-N5YD^crBi%WIJL^(U?M6JB+cq3 z-T^J}ZwwK({0`X92smXza#l_UvGWPh3%z7n_*Dkj$%tB0qKR_-H_1=iO-9IbJR2an T151SiYlxumoc)ggzlNdXlZ;cE literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_256_rc2_64_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_256_rc2_64_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..84d25b18f9bcbf14139f0aac72066337caf0c321 GIT binary patch literal 736 zcmV<60w4V_f&$zyRt5&LNQU&9|QCO0m#N~%3ha`DQC|SWT7~rz5d~x|uPRWO65|7888GCf`6$ryf@^FE1J=s}#1SfS zU3{2LgvN>lj+6`iZ3LPOGOZ9X!n&q0; zdn`Cn?SnWHr46mex@yYl6;Hh65rCCx@s zR(RYc@az!0taStLS>>9PEXEbwm*JWz3|6U9=t9)7a`BQ_?D<2s1FImQEp1qy_QU;i z!DuFKb%PC79JOw_ItHkCAUUIi%9RP_-`Gr7X=SNgv16?qj)~gh(q&KsR_4ao z%2CSjHK$uY@%E0Z%)$IyH+Ax5uNsh$Z|&rqcKGmWU=KM&w<1QD`63q^`9qg+ZilDb6vEWAt(!YUlYKJdGcQg-%>qDE;W3968)q4K3wtgOWA=%)nK_%> z+Z=*cq{c<|lHC#Zh8BZx<`SEt#bsuhox`PQ>_F;CD3%yRcq%As8$;$jB!qQ~hcgJ3 z%F1^9h)t)R9IGxcwzx_Fp%Oz2x^;m&!5mjH^PXcv^?^w_1=Xi(b6VAI;9MIx33G#v S;HN3ku@0zGGVH%SPOp>CuuYf% literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes128_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes128_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..9747770f259775e2041dde1a3930490a9c06ad9b GIT binary patch literal 737 zcmV<70v`P^f&$$zR|W|xhDe6@4FLrWFiJ2f1_>&LNQU&90Ul+7U_~U3w2il z0tf&w3L~b`8)dGsFSSe@?&{w_f87j&qIh9>HN*aYl1Nw zGx1gC@!&u-*)W+uD`ID~jN2Y6LVLP4^DHJ_sE`&JdRt#U0v#tgOA?p(qsI%SGSDDr z0H!`sh-@o(ddWwdi;`>#zY)3<(Q~Je)g&H7%omSYJTaBqF^DIbt-6R=GVB~(GdY99AreqIgC_;O&V6zgy`g+;qaqx%5ptgqmUy3JZNgf(q+`ot91G=XF4 zO+3_mGLjqc8bu)9|H;nf{Ht&(>73_C56Q2Znpp|{5%(^{*f=(H26E`X&ZXsH&4Few zkS2}K=*_7u&^p8w7BFpU63%t~?CDG?%wb62KbRh1jIi-wRho5V6dzLltJd!x0&`CB zbu_mh3@F72$0q4-7c*z^KzvQ~E1W9U^iT`ztdMXD?;SP%#d>NO*Z{}gquOzM)i-64 zWJ$ZS4fW<@?w%)hF+327brFxZJ zVK+XT8Xm3ANZkNWDVs9r?DfCjJrUa&(2`3FG3F1y%taGKA6aI4HA_KH?r literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes192_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes192_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..118fb72587ddf71057e1b88957fbb027c1faaac8 GIT binary patch literal 737 zcmV<70v`P^f&$$zR|W|xhDe6@4FLrWFiJ2f1_>&LNQU&90Ukp&{ufK*|ix0 z0tf&w30cwo49Yj-wDSa+O#t9dGXpGIXe4ro z&)C(M;hr_1SlTusTBTJD9 zs`fv40q4sRYPsp&B5Tf|S}j5;D&RDTW?LjRqtZpt*QKR`T|9!=q@IFT((!g>8RcSv zv-^L4`#J+u$FL?c2j|Eg*828JWQ6IJ@#N+1^3RHI6Oza-B`~C8WMx<+rnm4c23>rRLi<< zU9J9B7ML81)mbzDfIUa9;@m`E5Dwxv;WTa`Z79S8`w^TzFszwA(ZD>}^0lOyRs7PB T`PD*G-eRFa0#m}J;b{4e3NKYz literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes256_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_aes256_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..2a494ba53865e014a5939ed40013706eb79fe423 GIT binary patch literal 737 zcmV<70v`P^f&$$zR|W|xhDe6@4FLrWFiJ2f1_>&LNQU&90UjoRbSB53MFZXL3qH&APC?b1cCy9 zGC}2A{L%C@!N>Q!?E^?fC^O{VP^M<>U1Q4)DIcJ&G~`~D@frQb8!5kol2f_=XA*#Z zpM}4+S8F=oIEY1YO>|@J^OnR=2?WviQGjF9B}K1L(t9oEN_RMM8dm(cTr|kxvuf1s zBcw9p8LG_1)|G}0Bk~WrUZP=1RNgx zmmcCFeX)2uw5m>owc?Gy<$5&^s-QUnvY&`RrwJe_?#}~L!@EZ%s*n>%AZ)6|f-9+V z#thzE#A&M>d%taI)(OUJ!>c)&@fyYMnjW&Ii0bI5Qhm-ptQ8o$8g_4%rOf<-dZ-Gh z0kbn=Gj|Emq5$sw396U53!^5%Je5`AQDt0LUsbym7`034=V2%6?$R+YcLasneL zlZG-_*;=s9KjlKL17ne;T*VslV``AIgQ21Hs7PE1P>NI=^f>2XW|f>nMOWAnP^zIc zZdcTT1qrNDp@n3sMu%NdP9ejIKLpgMx zvjj~TH-G|oD1NRgac2{IY1-tOzeNy_Mwx{y_FqToY1XoKQ+*R6 TX)i`EWd(q4Fs4Q*#-ZF>S%Ofr literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_des_ede3_cbc.der b/deps/libtomcrypt/tests/rsa-pkcs8/key_pkcs8_pbkdf2_sha512_des_ede3_cbc.der new file mode 100644 index 0000000000000000000000000000000000000000..d88b6bd40c9e6992326766cd28600bdfbd1d254f GIT binary patch literal 728 zcmV;}0w?`2f&$bqP6i1ohDe6@4FLrWFhMXW1_>&LNQU&90Ul}!RD8}i~-LA z0tf&w3Bif&zd!=xAyMLOc7Z&Xh_PlK6#H)*VYI`4xdbJDQ$oi{B!0dNg)_R1iHD9Hq4#cA$1!Ap)~W#nf6 z{>;CcTjcJwiBL{6&lyoa6k>Dfub>*PqBRT@FWBKc>$sw~yXH$PnS;H`5{CPn8QKlQ z1jej>m{exu^sMZ9$eqB2qJ_k-=)uz0JOBo!p}1HShX3bNWj1s2cT*juiJEGXxzghe z+cZGcw90556BfFyo4U)i&a)Ub2WHwqnE53KBOSc%yrAJ%U2Uh_1;XHYu)F^_gL4ax z6ax(xY)O!1Y8ZGbO zKZVs1MoYVMwJU|ci9b6v_0I+~<%;T9TACV)MZOsK;#vFC+4~Av_z1L0wVHBIT_cuZ z;Rn9{2F4m*##7$|+W-33KH{RF+66hi@Bd%0TH!C`p|=JMwV}$DIdc5Y4)bg+e6JBi z&x1(|?>FO51BbAjw>l%o-|6xN<#Ya@CX*;f7cT$m`AgS&C_Vhwug6ZGMnX+p-c=43 zT`|EIMkDniGg9EQ;e{9(ZB|CyS5Y1ASR8k}l^xQn^RQKLp%)kPI8zt(koPlW8nBx$ zQt+L=BXvV5h+qp9i|SAKmoRfw8^^j1fIeCdznCKw*I71MQlwNAbP7p&LNQU&9|Q;^T{~ZLiTg7G z0tf&C0R=D&1_&yKNQUeQZh<2>U4+FE;H?fACVus zWy-Mw{(|w#^^Sb55HS|^mO6JoP)WZ8U~$c~GILXBuWviV*Vu6gKUr4ZU#j_us8^!X z_Ojtu#z*eDRSh% zHq@|YPYtmUv-ZA2=?I|_-~&UrRJUwW)FYLKsra|wE>N6%CA?Xtxb(LSJMsaSC*+Qt z*$ySV;g?>k?9Z8FFV1=@vyxDl%5H0^D+Fmyv*&VWRFW3&4Y|xHPuwPLvuAZF05UQj z26&|(z%LpRiE$F6AsK{&yCovgOXJ;fb-lFprEvbpq%R(obj78Eb@S4z5cjQ_py2AQ zK_Flem~Tdt@wvv3NnNNG4$ZO`6<%A04v z5L-#H8g$8A%kIU&iBzYMa|M-90zDTWHA67skA?n$3(6pNnq zn>Jd|(Ki{@2LY7qpQyqIgeDZ8Ej-C*bpm;KfXgX zzzCs`6Oc0y5d@&OxvD5a(@CBIZO|SFKmq7_(XYSH{>L?m80^G7>N&=Tq+u@^9t{h< zG5-S*c`l8K)!oT!4sksC-DZhMTtPB6Z0z&LNQU&9|Q=QrfXtzY1ldf z0tf&C0SGV*1_&yKNQU)h(jL(G4r>p>TPr~q%s{Zp}nQ$ zOgk#O;sOB6zL%!Qvhu6|`d0AEdQ!^*8irQ&Ah}#M*VngLl)mGvw!FK)5ogzvDz%_ct zuzwUMV^J=Mvd>Zhlu+J1-nL%T?;Rn1WABa(N1zXoy?~50&!gngA1Z8MD1R}$u!#y} zHz5NNJxh1z_zb4(0&PAS+y*nhuO^>qwlY4)2`uBmT;y!b^W5~3_JF?37st3E-PK!( zN+Kr$h`XA0!O7dJ-301#juZsw#@CPNsDbLv2^j~g%aQflKRE3w>YR7C!=Gsel8{GO zuUwHTrix-iI3x7fhX4_$O+-fZ#Sk#Qbs32s$;K9_UT<9?;J5hUz?95);G~wF1t{Nt zhV1(_`4_AYDI^@42_7E_#m$_KjKC?z6^%AM(Aps2-J^Hz66IQjf@=N>NnL`xjMONT zY!0ykn8UtixS;VU@I*2?jEnZK|Fb-}uJ@z5!JC9YxV1|Clf|G255pnV+oZuxm#Y1W z%_(i8(ON0pJV&^S4wc_J4i|bNHr?F!mmI*z^J7x44M?XxI-wURw%NDksSGHVUO<^C zQeE#$r@YbQ>Wd@mO~6Q%wOtIjgqz6@{%Ovrq|!~=^P7e_XOdlelN;y7na>~F-`GLg zXTiXaR%>S?+xn~F+jK|$E0&Pm9N)e78x^O0B@wvGVxgg1_hOc#_$~Y?i&)SghN9r6 Sw#+VGh?kG#0IMVJEl~D#dtML# literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa/rsa_size_1024_bits.der b/deps/libtomcrypt/tests/rsa/rsa_size_1024_bits.der new file mode 100644 index 0000000000000000000000000000000000000000..63d057324dc955270369448ea92485c2e07218da GIT binary patch literal 1293 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 WoQnDTT~gB*T=Qu8@Vxn#pD_ScIv_p( literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa/rsa_size_2048_bits.der b/deps/libtomcrypt/tests/rsa/rsa_size_2048_bits.der new file mode 100644 index 0000000000000000000000000000000000000000..7aaf80501de74153ccb22d8e2d7d96f01bae9edb GIT binary patch literal 1554 zcmXqLV&gMtV)?d!nTe5!Ns!^3V)M6%-Fgj=Lw88`K5)8jz{|#|)#lOmotKf3m6gGu zaj7A<0Vf-CC<~h~lZ&gNsDUtu!zIiUmYEomk(rkroS#-=C}_YB66O}>2udwZO)N^z zFtj$X1PL(<8zHMy2nu%84bH4eRR~EfE>Un!Eh@=O%S=uzNmbA=GBB}FNXjfJ)-=>N z(1p8$lTl0|B{45EHAgo$v8XsXBQYn(p)5181Y~O z<0vTC49Xoc{%B%ULXHAPRtDxKMt%l^CPpr%CPqev`-g=6a}N7w?OAHG5K(>dc2Lb+oz~FuD46Gj$Jw^#CUK^+D8xdnLAG3>O4C8b(Q3!rSm#` zbl3G4$C?z|MtT|8iA`_TW^Fn6&1}(WuKE6t=N;a$?I@4#>^;>^pY==rPH~Oa$@g@v z^IccVlHsDff1B3R{WtcAs)wmhR6AM~uQQ3aPNM(y8nwoH{a3HFOO4ESyVh>LJ7Mxy zh2k=w%5PKWOuZ`_ZSQP1Cn11|Z{ZeE+ej6+_{NNzR@)DFDt%niW9+*|rS9(i83*^B zJ2CH>bq8ySl9gMUnD(0RdwR=MC;zPZAGOO}bl3TQ_L)VB_lzsLraUhD!2i!jfS@8BbQ2k?}tZs{u2RGT;LV@PhlR zOfD(b%P7gs>0s(Ghgd2^XG>8_H(=IcWSDZPwRG;XsAc!^j@-N*!CET*?yY2Uq5ZAK zu=%SpGZbe(zHf6czhe5k_fFGuC;Eh)I+7z&Uns4Y7+qWV?Uzc|j!)|fukzW=e0C=9 z)!UZe0`J4irIp>qYK7va3txNbIoa{@&*xvZg`Tl0sr?tSVa-4D46!HW-T_`y9u%8j z*p%YCA;#_ADh`)lCZ8(oon}eMM=TRd;t$<=Z5_1kYP@7yit`1%QT oXxvplzN)iyea`AFFYW8k^e^zO?~iMpYA?a97AAc0hRCMX0Kcd*9smFU literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa/rsa_size_4096_bits.der b/deps/libtomcrypt/tests/rsa/rsa_size_4096_bits.der new file mode 100644 index 0000000000000000000000000000000000000000..2e3cc16421df6253451025dfc9fd824dcb484331 GIT binary patch literal 2066 zcmXqL;@~rAV*R#&nTe5!Ns!^3V)M6%-Fgj=Lw88`K5)8jz{|#|)#lOmotKf3m6gGu zaj7A<0Vf-CC<~h~lZ&gNsDUtu!zIiUmYEomk(rkroS#-=C}_YB66O}>2udwZO)N^z zFtj$X1PL(<8zHMy2nu%84bH4eRR~EfE>Un!Eh@=O%S=uzNmbA=F|agKNXjfJ)-=>N z(1p8$lTl0|B{45EHAgo$v8XsXBQYn(p)5181Y~O zlPDX`ps&vi@uPNu>{;bs7XRJ}#c8Z(!ZORb+ut_$%x104X8c$9C?* zs@=lo3S!S&FIE?3h+J43K2Ls&sO!4}d0E$Oe!keAoH(`DBwx;GX7C)l$qgp^SU3Ln zd8_R9SL(srxh~rtU3>H~y3lX7{+ZVf+MB9kUw>wl%h}y(`}Fj@)YoP=J|(Sq_-&h1}!IikZEa`zhun+fFgZMv__ zW+1}Gq0I&?*w~pF;VdSDVvq_!mK=kuMuH_xn^Q(fNkOrdzJ7UmxgJ_Eq+f?#Q0XTY z=jj>h=VzwGrzIwr6zgS_&zlq`F7;ZSsa~tN+Y6@xMTG+MU$O3Fludn3Pen_-u-U zrum`VZQHlbQEoD7m~PQudr&pHQ8+EY?#%}61*WmK_Pu>CvZ5V7@vg~cUc8qdh6ccq^~MhAG?mDq<* z+@5Twec;K%%KI-|oo>gSwTfpde)gqPy7uP=m!LD8kIrscyH%Ro(%0hFi*K9-dObQh z>~9yH4(!WtZ20``Vz;tN!1*<=T+@3OafEH-F|)qy`BM00UD^5_?>TBNKY!8P*0XJg z`^Ouv)qi_7-)-sqvR(DklVc@sR!1Drk&3yr-uKjr*u|_e=~FY+!`2GDS5R2QxH|Z0 zM)TgP-Q7J_0q+lf*mIaO$bYVUukfFn%O0^#Z*4y=*tXCw=;^h4%jJ1~8a>$e?OLP! z(mip$$7MF_v~$l2ocy*|_il_gtJ=wVb93*0ZEs_GpY(V0^Lgw-@e++3d)7>0F7;7j He6|1ps%0(A literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa/rsa_size_512_bits.der b/deps/libtomcrypt/tests/rsa/rsa_size_512_bits.der new file mode 100644 index 0000000000000000000000000000000000000000..1fe69549f5940b1f8a22a5134d851f4ec171c3b2 GIT binary patch literal 1157 zcmXqLVrevJV$oi}%*4pVB*<`1vH4rXZoP)bp*y5|A2?k%;AP{~YV&CO&dbQi%F1BS zxWtg#fRl|ml!Z;0$;H)B)Ib=-;S%Nv%S;T($jr+Q&QB{b6g1!m33Cf`1f>?ICKe@U z7+M)vfP|QZ4UttU1O+?l24_~KDukpKmnb-=7L{bCWhN(5H-mu(lOw}12^P0C$LB5W3)=VfyUo^n{|>FMt!Zk!@y)#G z-pK;Cq`e3_S9jx%V{xHO%!~|-i<_8C44Rk> z3}k`vBFo1j#v&5H{Y9v__l@_I1?T?lT-oaM-tKUpLE}S^yfRDUO@qd34OrDIY+SXZ zarqDl)g~;d9F$sRg&7(Dv#=U411SSOkN`hOfCZQ{*bEdvd{q!%%s_;VLz@kl8`zl{ z;VdSDVvq_!mK=kuMuO?H%_*a#q@dVJU%$M(Tn{br>erzsZ~esLJUv7G{LGa2w8Z3+ zV!e!#+?)=k4s(d5LUgtiwMbxgWT=qez4Q42=WLaa%`Z=C|69z#^+>(s?R&dD3Q_iJ ppZ*u^oYb+$27*xBD%(fdAw3jp|BbsYcz literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa/rsa_size_8192_bits.der b/deps/libtomcrypt/tests/rsa/rsa_size_8192_bits.der new file mode 100644 index 0000000000000000000000000000000000000000..faba635d554905ce8279823999951bfdeebba6de GIT binary patch literal 3090 zcmdUwc{J4PAIHsNEZJqa)~QJL?^tH+D#lns)r`Q`lXx##}wx##@;`<-+DdYz=&K7h)xRRjTp zz+geP!6R3;oLf~B<{g_Q=(DGP1$bdxipgflUwAehm(=URgfK&ri{O1ac$I~@z(uBZzOd*H%=9Mw>k+OulQ0qwl4EcMfPmE7< z_)kLm8jh`XetsKhka+u-rL3093mxF|7E-(dOU5^=3zpiti;b&G<>!W8Otjga@@C#f zyS6!E^Ai;d<9-pl9cEkc>E=ehw(@jx|LxZzdyD~l?iWm}@lbBW>~PRb)BW-7L#<@R z?Xj`wm&9rKPSn@v@|Ke|5)GVc+-L(kHKj(8g zcDoSo-o8>REQ{XyK1L6nF1l~zbTg~_gl4N00byy^EdNv_{QU+jox2!oW|1a*G}b%s zzU&2U2-}f+I|Ww%o6uaE!(3i$JJ8Fy@dMnr7TTD+0%s|uDs!ZR#*m}@d-5#7c_hZBa* z-`i}^ty4s!c__bDhFNkpIk?tGY6;5~+5N<5!1MWKj+Q}-$C@w*1s8{B(l!3aGuH_E zRc;~V_`$JsyCv`iUbsm|5(Z6OPj^qL2$E9AIkJ{_^MGLv>oCP%$ACFk}+cIY+p?U-u|K$-pl`xwAShteb&An*qtgCn@^?M0?vX% z__j)gP#Jm-%VVpU-B)itKn-7Kf=lB}1PJ?+LAUCt6Bq+${!OX)54Q|sr97_QUqGaP zbxwj|p60*DTt@pp7ioI!j3A!dr=8&=`~9R2J+I**3k3ScuBsZ{OidImSz z5GP%=S}nh@xziWqSgs&*B5?7t^tUR~ht{qw1CoZCdL>-e;mP^UzP)KM1jGg^p@Ovl zDi{e!{g|*)d{8*_ut|quDBBEZ#*G_r0N?H z6i5Tp(ElkF`ahTcH{E}r1;j@C+0&&*Ek*v0v_#@&9G`e)z9|pbOMIlpQha2;wrYaS zV6Vxr!*w;JgTKY9h!K+X`CT@G!(^B?@+SY<$^enVT@9}f(y@au|3yx%;*`YB-NCI} zBA$IH%ZO5FwAz`(wqE>-lAj*1#ax)L>^84uzr1^WcdQDo9_N{-O#NKvFQfU1?&Z-c z^>8FDz*%M3qCopmmSe-=pA8wke1Rn*%{S8LA58vQ*yxqHG1MZf@(SG4lOw~r`38g2 zpZ@$MIq5{6)^j7J-7AfEStmN>lBVQb(9aAIMtn9a~T z#s)bLn2FKaVXCZ`FiV#%yAt%Xul}Yv^)LTZ5E#7YhLrjqBU;ktv(Vi4`4$DE+46xg zrzNE_GQv{}u0JV3=WzdO4c@vXY9i|EA)8mx^+i$_?ru+lfKcEm{an{GA{$15&2HB) z;zn6k3X7X3(6;bPJhUv_d1sa9tHtB9eb?@GDuyu0&E}2?R=290UgMhkCEm`pa+**o z1~a$9c6oEO=#l3Zn=XY3eAstHGPctF%7&~hE!Vr7n`&B=b8`-T zj|(PLK0e=dtsc6fI^=i5yrzoPSzqsM(bKiV5cy!Z%DGZJ-eiC=OHp{d{ylf!u{-Re zgHMng7S(mJzG*@K-i&G68JcQhkG*BQGPSRAz}Te~-oy2&mu0M98ze1hk6<~S7BWH$ zigoG$8jV+_--7uu$jpe4qNj?7-ar(sJR~A>d#aqft6WaZ|$A^N%+9rS6ruF7AGA7RH zPwJSAjV=fb2xW|01(uw%82UIS&cU^~C$mZZmarcY5V-%P;`Lf(mFY#LrrPdJ=k|4T zY%BX9Y8eGQcfH%XO3^Ck{u;9}|9YhSLX85#w_gCsLUlLpWKo<=FD@q()ahbECB;_m zECn#r&P@n6R;!?o@7xN`cUqc_o7~fk)9;JaSTMldDq}v^{_7Wbv I-}!d$-=F<7XaE2J literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/rsa_test.c b/deps/libtomcrypt/tests/rsa_test.c new file mode 100644 index 0000000..d5515fa --- /dev/null +++ b/deps/libtomcrypt/tests/rsa_test.c @@ -0,0 +1,762 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_MRSA) +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 +#include +#define dbg_malloc_stats() do{ malloc_stats(); }while(0) +#else +#define dbg_malloc_stats() do{ }while(0) +#endif + +/* These are test keys [see file test.key] that I use to test my import/export against */ +static const unsigned char openssl_private_rsa[] = { + 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, 0x64, 0x8a, + 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, 0xa1, 0xb7, + 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, 0x65, 0xe5, + 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, 0x12, 0x8a, + 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, 0xbf, 0x12, + 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, 0x7c, 0x61, + 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, 0xe2, 0x76, + 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, 0x60, 0x3f, + 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, + 0x02, 0x81, 0x81, 0x00, 0xc8, 0x62, 0xb9, 0xea, 0xde, 0x44, 0x53, 0x1d, 0x56, 0x97, 0xd9, 0x97, + 0x9e, 0x1a, 0xcf, 0x30, 0x1e, 0x0a, 0x88, 0x45, 0x86, 0x29, 0x30, 0xa3, 0x4d, 0x9f, 0x61, 0x65, + 0x73, 0xe0, 0xd6, 0x87, 0x8f, 0xb6, 0xf3, 0x06, 0xa3, 0x82, 0xdc, 0x7c, 0xac, 0xfe, 0x9b, 0x28, + 0x9a, 0xae, 0xfd, 0xfb, 0xfe, 0x2f, 0x0e, 0xd8, 0x97, 0x04, 0xe3, 0xbb, 0x1f, 0xd1, 0xec, 0x0d, + 0xba, 0xa3, 0x49, 0x7f, 0x47, 0xac, 0x8a, 0x44, 0x04, 0x7e, 0x86, 0xb7, 0x39, 0x42, 0x3f, 0xad, + 0x1e, 0xb7, 0x0e, 0xa5, 0x51, 0xf4, 0x40, 0x63, 0x1e, 0xfd, 0xbd, 0xea, 0x9f, 0x41, 0x9f, 0xa8, + 0x90, 0x1d, 0x6f, 0x0a, 0x5a, 0x95, 0x13, 0x11, 0x0d, 0x80, 0xaf, 0x5f, 0x64, 0x98, 0x8a, 0x2c, + 0x78, 0x68, 0x65, 0xb0, 0x2b, 0x8b, 0xa2, 0x53, 0x87, 0xca, 0xf1, 0x64, 0x04, 0xab, 0xf2, 0x7b, + 0xdb, 0x83, 0xc8, 0x81, 0x02, 0x41, 0x00, 0xf7, 0xbe, 0x5e, 0x23, 0xc3, 0x32, 0x3f, 0xbf, 0x8b, + 0x8e, 0x3a, 0xee, 0xfc, 0xfc, 0xcb, 0xe5, 0xf7, 0xf1, 0x0b, 0xbc, 0x42, 0x82, 0xae, 0xd5, 0x7a, + 0x3e, 0xca, 0xf7, 0xd5, 0x69, 0x3f, 0x64, 0x25, 0xa2, 0x1f, 0xb7, 0x75, 0x75, 0x05, 0x92, 0x42, + 0xeb, 0xb8, 0xf1, 0xf3, 0x0a, 0x05, 0xe3, 0x94, 0xd1, 0x55, 0x78, 0x35, 0xa0, 0x36, 0xa0, 0x9b, + 0x7c, 0x92, 0x84, 0x6c, 0xdd, 0xdc, 0x4d, 0x02, 0x41, 0x00, 0xd6, 0x86, 0x0e, 0x85, 0x42, 0x0b, + 0x04, 0x08, 0x84, 0x21, 0x60, 0xf0, 0x0e, 0x0d, 0x88, 0xfd, 0x1e, 0x36, 0x10, 0x65, 0x4f, 0x1e, + 0x53, 0xb4, 0x08, 0x72, 0x80, 0x5c, 0x3f, 0x59, 0x66, 0x17, 0xe6, 0x98, 0xf2, 0xe9, 0x6c, 0x7a, + 0x06, 0x4c, 0xac, 0x76, 0x3d, 0xed, 0x8c, 0xa1, 0xce, 0xad, 0x1b, 0xbd, 0xb4, 0x7d, 0x28, 0xbc, + 0xe3, 0x0e, 0x38, 0x8d, 0x99, 0xd8, 0x05, 0xb5, 0xa3, 0x71, 0x02, 0x40, 0x6d, 0xeb, 0xc3, 0x2d, + 0x2e, 0xf0, 0x5e, 0xa4, 0x88, 0x31, 0x05, 0x29, 0x00, 0x8a, 0xd1, 0x95, 0x29, 0x9b, 0x83, 0xcf, + 0x75, 0xdb, 0x31, 0xe3, 0x7a, 0x27, 0xde, 0x3a, 0x74, 0x30, 0x0c, 0x76, 0x4c, 0xd4, 0x50, 0x2a, + 0x40, 0x2d, 0x39, 0xd9, 0x99, 0x63, 0xa9, 0x5d, 0x80, 0xae, 0x53, 0xca, 0x94, 0x3f, 0x05, 0x23, + 0x1e, 0xf8, 0x05, 0x04, 0xe1, 0xb8, 0x35, 0xf2, 0x17, 0xb3, 0xa0, 0x89, 0x02, 0x41, 0x00, 0xab, + 0x90, 0x88, 0xfa, 0x60, 0x08, 0x29, 0x50, 0x9a, 0x43, 0x8b, 0xa0, 0x50, 0xcc, 0xd8, 0x5a, 0xfe, + 0x97, 0x64, 0x63, 0x71, 0x74, 0x22, 0xa3, 0x20, 0x02, 0x5a, 0xcf, 0xeb, 0xc6, 0x16, 0x95, 0x54, + 0xd1, 0xcb, 0xab, 0x8d, 0x1a, 0xc6, 0x00, 0xfa, 0x08, 0x92, 0x9c, 0x71, 0xd5, 0x52, 0x52, 0x35, + 0x96, 0x71, 0x4b, 0x8b, 0x92, 0x0c, 0xd0, 0xe9, 0xbf, 0xad, 0x63, 0x0b, 0xa5, 0xe9, 0xb1, 0x02, + 0x41, 0x00, 0xdc, 0xcc, 0x27, 0xc8, 0xe4, 0xdc, 0x62, 0x48, 0xd5, 0x9b, 0xaf, 0xf5, 0xab, 0x60, + 0xf6, 0x21, 0xfd, 0x53, 0xe2, 0xb7, 0x5d, 0x09, 0xc9, 0x1a, 0xa1, 0x04, 0xa9, 0xfc, 0x61, 0x2c, + 0x5d, 0x04, 0x58, 0x3a, 0x5a, 0x39, 0xf1, 0x4a, 0x21, 0x56, 0x67, 0xfd, 0xcc, 0x20, 0xa3, 0x8f, + 0x78, 0x18, 0x5a, 0x79, 0x3d, 0x2e, 0x8e, 0x7e, 0x86, 0x0a, 0xe6, 0xa8, 0x33, 0xc1, 0x04, 0x17, + 0x4a, 0x9f, }; + +static const char x509_public_rsa[] = + "MIICdTCCAd4CCQCYjCwz0l9JpjANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJD\ + WjEPMA0GA1UECAwGTW9yYXZhMQ0wCwYDVQQHDARCcm5vMRAwDgYDVQQKDAdMVEMg\ + THRkMQ8wDQYDVQQLDAZDcnlwdG8xEjAQBgNVBAMMCVRlc3QgQ2VydDEYMBYGCSqG\ + SIb3DQEJARYJdGVzdEBjZXJ0MCAXDTE3MDMwOTIzNDMzOVoYDzIyOTAxMjIyMjM0\ + MzM5WjB+MQswCQYDVQQGEwJDWjEPMA0GA1UECAwGTW9yYXZhMQ0wCwYDVQQHDARC\ + cm5vMRAwDgYDVQQKDAdMVEMgTHRkMQ8wDQYDVQQLDAZDcnlwdG8xEjAQBgNVBAMM\ + CVRlc3QgQ2VydDEYMBYGCSqGSIb3DQEJARYJdGVzdEBjZXJ0MIGfMA0GCSqGSIb3\ + DQEBAQUAA4GNADCBiQKBgQDPmt5kitrIMyCp14MxGVSymoWnobd1M7aprIQks97b\ + fYUtlmXlP3KVJJ8oaMpP20QcPmASit0mpev/C17UiDhJKm5bvxI3R70Fa7zb8+7k\ + EY5BaHxhE9dCyIC+No/cCItPrKTidgzJY2xJWJPtzKrcJTsKYD+LVDrDTTHnlKRE\ + /QIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAApwWqupmmLGHeKOLFLcthQpAXXYep6T\ + 3S3e8X7fIG6TGhfvn5DHn+/V/C4184oOCwImI+VYRokdXdQ1AMGfVUomHJxsFPia\ + bv5Aw3hiKsIG3jigKHwmMScgkl3yn+8hLkx6thNbqQoa6Yyo20RqaEFBwlZ5G8lF\ + rZsdeO84SeCH"; + +static const unsigned char pkcs8_private_rsa[] = { + 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, + 0x00, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, 0x64, 0x8a, 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, + 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, 0xa1, 0xb7, 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, + 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, 0x65, 0xe5, 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, + 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, 0x12, 0x8a, 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, + 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, 0xbf, 0x12, 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, + 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, 0x7c, 0x61, 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, + 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, 0xe2, 0x76, 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, + 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, 0x60, 0x3f, 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, + 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x81, 0x00, 0xc8, 0x62, + 0xb9, 0xea, 0xde, 0x44, 0x53, 0x1d, 0x56, 0x97, 0xd9, 0x97, 0x9e, 0x1a, 0xcf, 0x30, 0x1e, 0x0a, + 0x88, 0x45, 0x86, 0x29, 0x30, 0xa3, 0x4d, 0x9f, 0x61, 0x65, 0x73, 0xe0, 0xd6, 0x87, 0x8f, 0xb6, + 0xf3, 0x06, 0xa3, 0x82, 0xdc, 0x7c, 0xac, 0xfe, 0x9b, 0x28, 0x9a, 0xae, 0xfd, 0xfb, 0xfe, 0x2f, + 0x0e, 0xd8, 0x97, 0x04, 0xe3, 0xbb, 0x1f, 0xd1, 0xec, 0x0d, 0xba, 0xa3, 0x49, 0x7f, 0x47, 0xac, + 0x8a, 0x44, 0x04, 0x7e, 0x86, 0xb7, 0x39, 0x42, 0x3f, 0xad, 0x1e, 0xb7, 0x0e, 0xa5, 0x51, 0xf4, + 0x40, 0x63, 0x1e, 0xfd, 0xbd, 0xea, 0x9f, 0x41, 0x9f, 0xa8, 0x90, 0x1d, 0x6f, 0x0a, 0x5a, 0x95, + 0x13, 0x11, 0x0d, 0x80, 0xaf, 0x5f, 0x64, 0x98, 0x8a, 0x2c, 0x78, 0x68, 0x65, 0xb0, 0x2b, 0x8b, + 0xa2, 0x53, 0x87, 0xca, 0xf1, 0x64, 0x04, 0xab, 0xf2, 0x7b, 0xdb, 0x83, 0xc8, 0x81, 0x02, 0x41, + 0x00, 0xf7, 0xbe, 0x5e, 0x23, 0xc3, 0x32, 0x3f, 0xbf, 0x8b, 0x8e, 0x3a, 0xee, 0xfc, 0xfc, 0xcb, + 0xe5, 0xf7, 0xf1, 0x0b, 0xbc, 0x42, 0x82, 0xae, 0xd5, 0x7a, 0x3e, 0xca, 0xf7, 0xd5, 0x69, 0x3f, + 0x64, 0x25, 0xa2, 0x1f, 0xb7, 0x75, 0x75, 0x05, 0x92, 0x42, 0xeb, 0xb8, 0xf1, 0xf3, 0x0a, 0x05, + 0xe3, 0x94, 0xd1, 0x55, 0x78, 0x35, 0xa0, 0x36, 0xa0, 0x9b, 0x7c, 0x92, 0x84, 0x6c, 0xdd, 0xdc, + 0x4d, 0x02, 0x41, 0x00, 0xd6, 0x86, 0x0e, 0x85, 0x42, 0x0b, 0x04, 0x08, 0x84, 0x21, 0x60, 0xf0, + 0x0e, 0x0d, 0x88, 0xfd, 0x1e, 0x36, 0x10, 0x65, 0x4f, 0x1e, 0x53, 0xb4, 0x08, 0x72, 0x80, 0x5c, + 0x3f, 0x59, 0x66, 0x17, 0xe6, 0x98, 0xf2, 0xe9, 0x6c, 0x7a, 0x06, 0x4c, 0xac, 0x76, 0x3d, 0xed, + 0x8c, 0xa1, 0xce, 0xad, 0x1b, 0xbd, 0xb4, 0x7d, 0x28, 0xbc, 0xe3, 0x0e, 0x38, 0x8d, 0x99, 0xd8, + 0x05, 0xb5, 0xa3, 0x71, 0x02, 0x40, 0x6d, 0xeb, 0xc3, 0x2d, 0x2e, 0xf0, 0x5e, 0xa4, 0x88, 0x31, + 0x05, 0x29, 0x00, 0x8a, 0xd1, 0x95, 0x29, 0x9b, 0x83, 0xcf, 0x75, 0xdb, 0x31, 0xe3, 0x7a, 0x27, + 0xde, 0x3a, 0x74, 0x30, 0x0c, 0x76, 0x4c, 0xd4, 0x50, 0x2a, 0x40, 0x2d, 0x39, 0xd9, 0x99, 0x63, + 0xa9, 0x5d, 0x80, 0xae, 0x53, 0xca, 0x94, 0x3f, 0x05, 0x23, 0x1e, 0xf8, 0x05, 0x04, 0xe1, 0xb8, + 0x35, 0xf2, 0x17, 0xb3, 0xa0, 0x89, 0x02, 0x41, 0x00, 0xab, 0x90, 0x88, 0xfa, 0x60, 0x08, 0x29, + 0x50, 0x9a, 0x43, 0x8b, 0xa0, 0x50, 0xcc, 0xd8, 0x5a, 0xfe, 0x97, 0x64, 0x63, 0x71, 0x74, 0x22, + 0xa3, 0x20, 0x02, 0x5a, 0xcf, 0xeb, 0xc6, 0x16, 0x95, 0x54, 0xd1, 0xcb, 0xab, 0x8d, 0x1a, 0xc6, + 0x00, 0xfa, 0x08, 0x92, 0x9c, 0x71, 0xd5, 0x52, 0x52, 0x35, 0x96, 0x71, 0x4b, 0x8b, 0x92, 0x0c, + 0xd0, 0xe9, 0xbf, 0xad, 0x63, 0x0b, 0xa5, 0xe9, 0xb1, 0x02, 0x41, 0x00, 0xdc, 0xcc, 0x27, 0xc8, + 0xe4, 0xdc, 0x62, 0x48, 0xd5, 0x9b, 0xaf, 0xf5, 0xab, 0x60, 0xf6, 0x21, 0xfd, 0x53, 0xe2, 0xb7, + 0x5d, 0x09, 0xc9, 0x1a, 0xa1, 0x04, 0xa9, 0xfc, 0x61, 0x2c, 0x5d, 0x04, 0x58, 0x3a, 0x5a, 0x39, + 0xf1, 0x4a, 0x21, 0x56, 0x67, 0xfd, 0xcc, 0x20, 0xa3, 0x8f, 0x78, 0x18, 0x5a, 0x79, 0x3d, 0x2e, + 0x8e, 0x7e, 0x86, 0x0a, 0xe6, 0xa8, 0x33, 0xc1, 0x04, 0x17, 0x4a, 0x9f }; + +/* private key - hexadecimal */ +enum { + pk_d , + pk_dP, + pk_dQ, + pk_e , + pk_N , + pk_p , + pk_q , + pk_qP, +}; +static const char *hex_key[] = { + "C862B9EADE44531D5697D9979E1ACF301E0A8845862930A34D9F616573E0D6878FB6F306A382DC7CACFE9B289AAEFDFBFE2F0ED89704E3BB1FD1EC0DBAA3497F47AC8A44047E86B739423FAD1EB70EA551F440631EFDBDEA9F419FA8901D6F0A5A9513110D80AF5F64988A2C786865B02B8BA25387CAF16404ABF27BDB83C881", + "6DEBC32D2EF05EA488310529008AD195299B83CF75DB31E37A27DE3A74300C764CD4502A402D39D99963A95D80AE53CA943F05231EF80504E1B835F217B3A089", + "AB9088FA600829509A438BA050CCD85AFE976463717422A320025ACFEBC6169554D1CBAB8D1AC600FA08929C71D552523596714B8B920CD0E9BFAD630BA5E9B1", + "010001", + "CF9ADE648ADAC83320A9D783311954B29A85A7A1B77533B6A9AC8424B3DEDB7D852D9665E53F7295249F2868CA4FDB441C3E60128ADD26A5EBFF0B5ED48838492A6E5BBF123747BD056BBCDBF3EEE4118E41687C6113D742C880BE368FDC088B4FACA4E2760CC9636C495893EDCCAADC253B0A603F8B543AC34D31E794A444FD", + "F7BE5E23C3323FBF8B8E3AEEFCFCCBE5F7F10BBC4282AED57A3ECAF7D5693F6425A21FB77575059242EBB8F1F30A05E394D1557835A036A09B7C92846CDDDC4D", + "D6860E85420B0408842160F00E0D88FD1E3610654F1E53B40872805C3F596617E698F2E96C7A064CAC763DED8CA1CEAD1BBDB47D28BCE30E388D99D805B5A371", + "DCCC27C8E4DC6248D59BAFF5AB60F621FD53E2B75D09C91AA104A9FC612C5D04583A5A39F14A215667FDCC20A38F78185A793D2E8E7E860AE6A833C104174A9F" }; + +/*** openssl public RSA key in DER format */ +static const unsigned char openssl_public_rsa[] = { + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, + 0x64, 0x8a, 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, + 0xa1, 0xb7, 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, + 0x65, 0xe5, 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, + 0x12, 0x8a, 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, + 0xbf, 0x12, 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, + 0x7c, 0x61, 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, + 0xe2, 0x76, 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, + 0x60, 0x3f, 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, + 0x00, 0x01, }; + +/* same key but with extra headers stripped */ +static const unsigned char openssl_public_rsa_stripped[] = { + 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, + 0x64, 0x8a, 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, + 0xa1, 0xb7, 0x75, 0x33, 0xb6, 0xa9, 0xac, 0x84, 0x24, 0xb3, 0xde, 0xdb, 0x7d, 0x85, 0x2d, 0x96, + 0x65, 0xe5, 0x3f, 0x72, 0x95, 0x24, 0x9f, 0x28, 0x68, 0xca, 0x4f, 0xdb, 0x44, 0x1c, 0x3e, 0x60, + 0x12, 0x8a, 0xdd, 0x26, 0xa5, 0xeb, 0xff, 0x0b, 0x5e, 0xd4, 0x88, 0x38, 0x49, 0x2a, 0x6e, 0x5b, + 0xbf, 0x12, 0x37, 0x47, 0xbd, 0x05, 0x6b, 0xbc, 0xdb, 0xf3, 0xee, 0xe4, 0x11, 0x8e, 0x41, 0x68, + 0x7c, 0x61, 0x13, 0xd7, 0x42, 0xc8, 0x80, 0xbe, 0x36, 0x8f, 0xdc, 0x08, 0x8b, 0x4f, 0xac, 0xa4, + 0xe2, 0x76, 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, + 0x60, 0x3f, 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, + 0x00, 0x01, }; + + +/* generated with the private key above as: + echo -n 'test' | openssl rsautl -sign -inkey rsa_private.pem -pkcs -hexdump + */ +static const unsigned char openssl_rsautl_pkcs[] = { + 0x24, 0xef, 0x54, 0xea, 0x1a, 0x12, 0x0c, 0xf4, 0x04, 0x0c, 0x48, 0xc8, 0xe8, 0x17, 0xd2, 0x6f, + 0xc3, 0x41, 0xb3, 0x97, 0x5c, 0xbc, 0xa3, 0x2d, 0x21, 0x00, 0x10, 0x0e, 0xbb, 0xf7, 0x30, 0x21, + 0x7e, 0x12, 0xd2, 0xdf, 0x26, 0x28, 0xd8, 0x0f, 0x6d, 0x4d, 0xc8, 0x4d, 0xa8, 0x78, 0xe7, 0x03, + 0xee, 0xbc, 0x68, 0xba, 0x98, 0xea, 0xe9, 0xb6, 0x06, 0x8d, 0x85, 0x5b, 0xdb, 0xa6, 0x49, 0x86, + 0x6f, 0xc7, 0x3d, 0xe0, 0x53, 0x83, 0xe0, 0xea, 0xb1, 0x08, 0x6a, 0x7b, 0xbd, 0xeb, 0xb5, 0x4a, + 0xdd, 0xbc, 0x64, 0x97, 0x8c, 0x17, 0x20, 0xa3, 0x5c, 0xd4, 0xb8, 0x87, 0x43, 0xc5, 0x13, 0xad, + 0x41, 0x6e, 0x45, 0x41, 0x32, 0xd4, 0x09, 0x12, 0x7f, 0xdc, 0x59, 0x1f, 0x28, 0x3f, 0x1e, 0xbc, + 0xef, 0x57, 0x23, 0x4b, 0x3a, 0xa3, 0x24, 0x91, 0x4d, 0xfb, 0xb2, 0xd4, 0xe7, 0x5e, 0x41, 0x7e, +}; + +extern const char ltc_der_tests_cacert_root_cert[]; +extern const unsigned long ltc_der_tests_cacert_root_cert_size; + +static int rsa_compat_test(void) +{ + rsa_key key, pubkey; + int stat, i; + unsigned char buf[1024], key_parts[8][128]; + unsigned long len, key_lens[8]; + + /* try reading the key */ + DO(rsa_import(openssl_private_rsa, sizeof(openssl_private_rsa), &key)); + DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &pubkey)); + + /* sign-verify a message with PKCS #1 v1.5 no ASN.1 */ + len = sizeof(buf); + DO(rsa_sign_hash_ex((unsigned char*)"test", 4, buf, &len, LTC_PKCS_1_V1_5_NA1, NULL, 0, 0, 0, &key)); + if (len != sizeof(openssl_rsautl_pkcs) || memcmp(buf, openssl_rsautl_pkcs, len)) { + fprintf(stderr, "RSA rsa_sign_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n"); + return 1; + } + stat = 0; + DO(rsa_verify_hash_ex(openssl_rsautl_pkcs, sizeof(openssl_rsautl_pkcs), (unsigned char*)"test", 4, LTC_PKCS_1_V1_5_NA1, 0, 0, &stat, &pubkey)); + if (stat != 1) { + fprintf(stderr, "RSA rsa_verify_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n"); + return 1; + } + rsa_free(&pubkey); + + /* now try to export private/public and compare */ + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PRIVATE, &key)); + DO(do_compare_testvector(buf, len, openssl_private_rsa, sizeof(openssl_private_rsa), "RSA private export (from OpenSSL)", 0)); + + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + DO(do_compare_testvector(buf, len, openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), "RSA public export (from OpenSSL private key)", 0)); + rsa_free(&key); + + /* try reading the public key */ + DO(rsa_import(openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + DO(do_compare_testvector(buf, len, openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), "RSA public export (from stripped OpenSSL)", 0)); + rsa_free(&key); + + /* try reading the public key */ + DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + DO(do_compare_testvector(buf, len, openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), "RSA public export (from OpenSSL)", 0)); + rsa_free(&key); + + /* try import private key in pkcs8 format */ + DO(rsa_import_pkcs8(pkcs8_private_rsa, sizeof(pkcs8_private_rsa), NULL, 0, &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PRIVATE, &key)); + DO(do_compare_testvector(buf, len, openssl_private_rsa, sizeof(openssl_private_rsa), "RSA private export (from PKCS#8)", 0)); + rsa_free(&key); + + /* convert raw hexadecimal numbers to binary */ + for (i = 0; i < 8; ++i) { + key_lens[i] = sizeof(key_parts[i]); + DO(radix_to_bin(hex_key[i], 16, key_parts[i], &key_lens[i])); + } + /* try import private key from converted raw hexadecimal numbers */ + DO(rsa_set_key(key_parts[pk_N], key_lens[pk_N], key_parts[pk_e], key_lens[pk_e], key_parts[pk_d], key_lens[pk_d], &key)); + DO(rsa_set_factors(key_parts[pk_p], key_lens[pk_p], key_parts[pk_q], key_lens[pk_q], &key)); + DO(rsa_set_crt_params(key_parts[pk_dP], key_lens[pk_dP], key_parts[pk_dQ], key_lens[pk_dQ], key_parts[pk_qP], key_lens[pk_qP], &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PRIVATE, &key)); + DO(do_compare_testvector(buf, len, openssl_private_rsa, sizeof(openssl_private_rsa), "RSA private export (from hex)", 0)); + rsa_free(&key); + + /* try import public key from converted raw hexadecimal numbers */ + DO(rsa_set_key(key_parts[pk_N], key_lens[pk_N], key_parts[pk_e], key_lens[pk_e], NULL, 0, &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + DO(do_compare_testvector(buf, len, openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), "RSA public export (from hex)", 0)); + rsa_free(&key); + + /* try export in SubjectPublicKeyInfo format of the public key */ + DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &key)); + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC | PK_STD, &key)); + DO(do_compare_testvector(buf, len, openssl_public_rsa, sizeof(openssl_public_rsa), "RSA public export (X.509)", 0)); + rsa_free(&key); + + return 0; +} + +static int s_rsa_key_cmp(const int should_type, const rsa_key *should, const rsa_key *is) +{ + if(should_type != is->type) + return CRYPT_ERROR; + if(should_type == PK_PRIVATE) { + if(mp_cmp(should->q, is->q) != LTC_MP_EQ) + return CRYPT_ERROR; + if(mp_cmp(should->p, is->p) != LTC_MP_EQ) + return CRYPT_ERROR; + if(mp_cmp(should->qP, is->qP) != LTC_MP_EQ) + return CRYPT_ERROR; + if(mp_cmp(should->dP, is->dP) != LTC_MP_EQ) + return CRYPT_ERROR; + if(mp_cmp(should->dQ, is->dQ) != LTC_MP_EQ) + return CRYPT_ERROR; + if(mp_cmp(should->d, is->d) != LTC_MP_EQ) + return CRYPT_ERROR; + } + if(mp_cmp(should->N, is->N) != LTC_MP_EQ) + return CRYPT_ERROR; + if(mp_cmp(should->e, is->e) != LTC_MP_EQ) + return CRYPT_ERROR; + return CRYPT_OK; +} + +/* https://github.com/DCIT/perl-CryptX/issues/69 */ +static int s_rsa_cryptx_issue_69(void) +{ + static const char *e = "03"; + static const char *N = "E932AC92252F585B3A80A4DD76A897C8B7652952FE788F6EC8DD640587A1EE5647670A8AD4C2BE0F9FA6E49C605ADF77B5174230" + "AF7BD50E5D6D6D6D28CCF0A886A514CC72E51D209CC772A52EF419F6A953F3135929588EBE9B351FCA61CED78F346FE00DBB6306" + "E5C2A4C6DFC3779AF85AB417371CF34D8387B9B30AE46D7A5FF5A655B8D8455F1B94AE736989D60A6F2FD5CADBFFBD504C5A756A" + "2E6BB5CECC13BCA7503F6DF8B52ACE5C410997E98809DB4DC30D943DE4E812A47553DCE54844A78E36401D13F77DC650619FED88" + "D8B3926E3D8E319C80C744779AC5D6ABE252896950917476ECE5E8FC27D5F053D6018D91B502C4787558A002B9283DA7"; + + static const char *sig1 = "8df69d774c6ac8b5f8aa16576ca37a4f948706c5daecb3c15cfd247a7657616b2bbb786b50158cac8c23e3" + "289d300d3fbb82380b8746d929df36bdaf43a5fc5d1d04c61c98d47c22de02d051be3ba9e42b1c47aa5192" + "66d4cae244e5ce99b24771a13a7c8c7b08868a3eccf70b4bc7570d5131a1ac8943d91b0151c39da2ad75cd" + "1b9a697d100eef6747217df581b272cfd1f549a901ff4951036a4eb28fd2ea1e9df3fa9fa457663f4259be" + "8e5f2f2fb84f831a0ca5320e2b79f04a17830f43062c4c8fc0d0b1ff90567f3342d524f682ca26661caadf" + "4272f2585e6013a92bfa68de72fe6174096890e4296aedd72da43aa508007df53fb852bd7162ab635b"; + static const char *sig2 = "1ee08947536e6b11d8923c3b00061d26a6933b5345077ea0214fdcbcc1ad68395008ff709117047e6b01dd" + "2a371dfa032c0732abc86ab2e0273bbd0dfe6b1c769e21bb9079982801d8f72e01be3244959312ab09bb8f" + "88572dc23216719b9810c73edf826749604feb8da1345f83f0209271aca462c1235b4cb4ba538f85a9c03d" + "d1dde1856fe73fd86b95566df2dfe8b0895c34489b97e02c8e48dabad7067619edec6267a776fa416fbcac" + "0fcacf3efa7852ce33ed63a9149c685c303d98c3dc37ee87521bc5b130377345fc95c87aa48505470deaf6" + "fb1064df041e3f03322b1ec90d3608deb17bf77f47066ecc6c511bfba69eed6da42881dcce603fcb2a"; + + static const char *hash = "7509e5bda0c762d2bac7f90d758b5b2263fa01ccbc542ab5e3df163be08e6ca9"; + rsa_key key; + unsigned char buf0[512], buf1[512]; + unsigned long l0, l1; + int stat; + + l0 = sizeof(buf0); + l1 = sizeof(buf1); + DO(radix_to_bin(e, 16, buf0, &l0)); + DO(radix_to_bin(N, 16, buf1, &l1)); + + DO(rsa_set_key(buf1, l1, buf0, l0, NULL, 0, &key)); + + l0 = sizeof(buf0); + l1 = sizeof(buf1); + DO(radix_to_bin(sig1, 16, buf0, &l0)); + DO(radix_to_bin(hash, 16, buf1, &l1)); + SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, &stat, &key)); + DO(radix_to_bin(sig2, 16, buf0, &l0)); + SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, &stat, &key)); + rsa_free(&key); + return CRYPT_OK; +} + +static int s_rsa_issue_301(int prng_idx) +{ + rsa_key key, key_in; + unsigned char buf[4096]; + unsigned long len; + + DO(rsa_make_key(&yarrow_prng, prng_idx, sizeof(buf)/8, 65537, &key)); + + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PRIVATE, &key)); + DO(rsa_import(buf, len, &key_in)); + + DO(s_rsa_key_cmp(PK_PRIVATE, &key, &key_in)); + rsa_free(&key_in); + + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC, &key)); + DO(rsa_import(buf, len, &key_in)); + + DO(s_rsa_key_cmp(PK_PUBLIC, &key, &key_in)); + rsa_free(&key_in); + + len = sizeof(buf); + DO(rsa_export(buf, &len, PK_PUBLIC | PK_STD, &key)); + DO(rsa_import(buf, len, &key_in)); + + DO(s_rsa_key_cmp(PK_PUBLIC, &key, &key_in)); + rsa_free(&key_in); + + rsa_free(&key); + return CRYPT_OK; +} + +static int s_rsa_public_ubin_e(int prng_idx) +{ + rsa_key key; + unsigned char e[32] = {0}; + unsigned long elen = sizeof(e); + + /* Check public exponent too small */ + e[elen - 1] = 1; + SHOULD_FAIL_WITH(rsa_make_key_ubin_e(&yarrow_prng, prng_idx, 128, e, elen, &key), + CRYPT_INVALID_ARG); + + /* + * Generate about 256 bits to check error when public exponent + * overflow. + */ + ENSURE(yarrow_read(e, elen, &yarrow_prng) == elen); + + /* Ensure that public exponent is: + * - odd value + * - MSB is even + */ + e[elen - 1] |= 0x1; + e[0] &= ~0x1; + + /* Check public exponent overflow */ + /* Set high bit of MSB set to get 256 bits, to get e overflow */ + e[0] |= 0x80; + SHOULD_FAIL_WITH(rsa_make_key_ubin_e(&yarrow_prng, prng_idx, 128, e, elen, &key), + CRYPT_INVALID_ARG); + + + /* Check public exponent not odd but e value < 256 bits */ + e[elen - 1] &= ~0x1; + e[0] &= ~0x80; + SHOULD_FAIL_WITH(rsa_make_key_ubin_e(&yarrow_prng, prng_idx, 128, e, elen, &key), + CRYPT_INVALID_ARG); + + /* Ensure that public exponent is odd value and e value < 256 bits */ + e[elen - 1] |= 0x1; + DO(rsa_make_key_ubin_e(&yarrow_prng, prng_idx, 128, e, elen, &key)); + rsa_free(&key); + + return CRYPT_OK; +} + +#ifdef LTC_TEST_READDIR +static int s_rsa_import_x509(const void *in, unsigned long inlen, void *key) +{ + /* here we use the filesize as indicator for the rsa size + * that would fail to import for tfm because it's fixed-size + */ + if ((strcmp(ltc_mp.name, "TomsFastMath") == 0) && (inlen > 2048)) { +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + fprintf(stderr, "Skipping testcase because of TomsFastMath\n"); +#endif + return CRYPT_NOP; + } + return rsa_import_x509(in, inlen, key); +} + +#if defined(LTC_MD2) && defined(LTC_MD5) && defined(LTC_RC2) +static int s_rsa_import_pkcs8(const void *in, unsigned long inlen, void *key) +{ + return rsa_import_pkcs8(in, inlen, "secret", 6, key); +} +#endif +#endif + +int rsa_test(void) +{ + unsigned char in[1024], out[1024], tmp[3072]; + rsa_key key, privKey, pubKey; + int hash_idx, prng_idx, stat, stat2, i; + unsigned long rsa_msgsize, len, len2, len3, cnt, cnt2; + static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 }; + void* dP; + unsigned char* p; + unsigned char* p2; + unsigned char* p3; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + if (rsa_compat_test() != 0) { + return 1; + } + + hash_idx = find_hash("sha1"); + prng_idx = find_prng("yarrow"); + if (hash_idx == -1 || prng_idx == -1) { + fprintf(stderr, "rsa_test requires LTC_SHA1 and yarrow"); + return 1; + } + +#ifdef LTC_TEST_READDIR + DO(test_process_dir("tests/rsa", &key, s_rsa_import_x509, (dir_cleanup_cb)rsa_free, "rsa_test")); +#if defined(LTC_MD2) && defined(LTC_MD5) && defined(LTC_RC2) + DO(test_process_dir("tests/rsa-pkcs8", &key, s_rsa_import_pkcs8, (dir_cleanup_cb)rsa_free, "rsa_pkcs8_test")); +#endif +#endif + + DO(s_rsa_cryptx_issue_69()); + DO(s_rsa_issue_301(prng_idx)); + DO(s_rsa_public_ubin_e(prng_idx)); + + /* make 10 random key */ + for (cnt = 0; cnt < 10; cnt++) { + DO(rsa_make_key(&yarrow_prng, prng_idx, 1024/8, 65537, &key)); + if (mp_count_bits(key.N) != 1024) { + fprintf(stderr, "rsa_1024 key modulus has %d bits\n", mp_count_bits(key.N)); + +len = mp_unsigned_bin_size(key.N); +mp_to_unsigned_bin(key.N, tmp); +print_hex("N", tmp, len); + +len = mp_unsigned_bin_size(key.p); +mp_to_unsigned_bin(key.p, tmp); +print_hex("p", tmp, len); + +len = mp_unsigned_bin_size(key.q); +mp_to_unsigned_bin(key.q, tmp); +print_hex("q", tmp, len); + + return 1; + } + if (cnt != 9) { + rsa_free(&key); + } + } + + /* encrypt the key (without lparam) */ + for (cnt = 0; cnt < 4; cnt++) { + for (rsa_msgsize = 0; rsa_msgsize <= 86; rsa_msgsize++) { + /* make a random key/msg */ + ENSURE(yarrow_read(in, rsa_msgsize, &yarrow_prng) == rsa_msgsize); + + len = sizeof(out); + len2 = rsa_msgsize; + + DO(rsa_encrypt_key(in, rsa_msgsize, out, &len, NULL, 0, &yarrow_prng, prng_idx, hash_idx, &key)); + /* change a byte */ + out[8] ^= 1; + SHOULD_FAIL(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, hash_idx, &stat2, &key)); + /* change a byte back */ + out[8] ^= 1; + ENSURE(len2 == rsa_msgsize); + + len2 = rsa_msgsize; + DO(rsa_decrypt_key(out, len, tmp, &len2, NULL, 0, hash_idx, &stat, &key)); + ENSUREX(stat == 1 && stat2 == 0, "rsa_decrypt_key (without lparam)"); + DO(do_compare_testvector(tmp, len2, in, rsa_msgsize, "rsa_decrypt_key (without lparam)", cnt << 8 | rsa_msgsize)); + } + } + + /* encrypt the key (with lparam) */ + for (rsa_msgsize = 0; rsa_msgsize <= 86; rsa_msgsize++) { + len = sizeof(out); + len2 = rsa_msgsize; + DO(rsa_encrypt_key(rsa_msgsize ? in : NULL, rsa_msgsize, out, &len, lparam, sizeof(lparam), &yarrow_prng, prng_idx, hash_idx, &key)); + /* change a byte */ + out[8] ^= 1; + SHOULD_FAIL(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), hash_idx, &stat2, &key)); + ENSURE(len2 == rsa_msgsize); + + /* change a byte back */ + out[8] ^= 1; + + len2 = rsa_msgsize; + DO(rsa_decrypt_key(out, len, tmp, &len2, lparam, sizeof(lparam), hash_idx, &stat, &key)); + ENSURE(stat == 1 && stat2 == 0); + DO(do_compare_testvector(tmp, len2, in, rsa_msgsize, "rsa_decrypt_key (with lparam)", rsa_msgsize)); + } + + /* encrypt the key PKCS #1 v1.5 (payload from 1 to 117 bytes) */ + for (rsa_msgsize = 0; rsa_msgsize <= 117; rsa_msgsize++) { + len = sizeof(out); + len2 = rsa_msgsize; + /* make a random key/msg */ + ENSURE(yarrow_read(in, rsa_msgsize, &yarrow_prng) == rsa_msgsize); + DO(rsa_encrypt_key_ex(in, rsa_msgsize, out, &len, NULL, 0, &yarrow_prng, prng_idx, 0, LTC_PKCS_1_V1_5, &key)); + + len2 = rsa_msgsize; + DO(rsa_decrypt_key_ex(out, len, tmp, &len2, NULL, 0, 0, LTC_PKCS_1_V1_5, &stat, &key)); + ENSURE(stat == 1); + DO(do_compare_testvector(tmp, len2, in, rsa_msgsize, "rsa_decrypt_key_ex", rsa_msgsize)); + } + + /* sign a message (unsalted, lower cholestorol and Atkins approved) now */ + len = sizeof(out); + DO(rsa_sign_hash(in, 20, out, &len, &yarrow_prng, prng_idx, hash_idx, 0, &key)); + +/* export key and import as both private and public */ + len2 = sizeof(tmp); + DO(rsa_export(tmp, &len2, PK_PRIVATE, &key)); + DO(rsa_import(tmp, len2, &privKey)); + len2 = sizeof(tmp); + DO(rsa_export(tmp, &len2, PK_PUBLIC, &key)); + DO(rsa_import(tmp, len2, &pubKey)); + + dbg_malloc_stats(); + rsa_shrink_key(&key); + dbg_malloc_stats(); + rsa_shrink_key(&pubKey); + dbg_malloc_stats(); + rsa_shrink_key(&privKey); + dbg_malloc_stats(); + + /* verify with original */ + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &key)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &key)); + + ENSUREX(stat == 1 && stat2 == 0, "rsa_verify_hash (unsalted, origKey) failed"); + + /* verify with privKey */ + /* change byte back to original */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &privKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &privKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* verify with privKey but remove pointer to dP to test without CRT */ + + dP = privKey.dP; + privKey.dP = NULL; + /* change byte back to original */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &privKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &privKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + privKey.dP = dP; + + /* verify with pubKey */ + /* change byte back to original */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &pubKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &pubKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (unsalted, pubkey) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* sign a message (salted) now (use privKey to make, pubKey to verify) */ + len = sizeof(out); + DO(rsa_sign_hash(in, 20, out, &len, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 8, &stat, &pubKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash(out, len, in, 20, hash_idx, 8, &stat2, &pubKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash (salted) failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* sign a message with PKCS #1 v1.5 */ + len = sizeof(out); + DO(rsa_sign_hash_ex(in, 20, out, &len, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); + DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 8, &stat, &pubKey)); + /* change a byte */ + in[0] ^= 1; + DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 8, &stat2, &pubKey)); + + if (!(stat == 1 && stat2 == 0)) { + fprintf(stderr, "rsa_verify_hash_ex failed, %d, %d", stat, stat2); + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 1; + } + + /* Testcase for Bleichenbacher attack + * + * (1) Create a valid signature + * (2) Check that it can be verified + * (3) Decrypt the package to fetch plain text + * (4) Forge the structure of PKCS#1-EMSA encoded data + * (4.1) Search for start and end of the padding string + * (4.2) Move the signature to the front of the padding string + * (4.3) Zero the message until the end + * (5) Encrypt the package again + * (6) Profit :) + * For PS lengths < 8: the verification process should fail + * For PS lengths >= 8: the verification process should succeed + * For all PS lengths: the result should not be valid + */ + + p = in; + p2 = out; + p3 = tmp; + for (i = 0; i < 9; ++i) { + len = sizeof(in); + len2 = sizeof(out); + /* (1) */ + DO(rsa_sign_hash_ex(p, 20, p2, &len2, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); + /* (2) */ + DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey), "should succeed"); + DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should succeed"); + len3 = sizeof(tmp); + /* (3) */ + DO(ltc_mp.rsa_me(p2, len2, p3, &len3, PK_PUBLIC, &key)); + /* (4) */ +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + print_hex("Original signature", p3, len3); +#endif + /* (4.1) */ + for (cnt = 0; cnt < len3; ++cnt) { + if (p3[cnt] == 0xff) + break; + } + for (cnt2 = cnt+1; cnt2 < len3; ++cnt2) { + if (p3[cnt2] != 0xff) + break; + } + /* (4.2) */ + memmove(&p3[cnt+i], &p3[cnt2], len3-cnt2); + /* (4.3) */ + for (cnt = cnt + len3-cnt2+i; cnt < len; ++cnt) { + p3[cnt] = 0; + } +#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 + print_hex("Forged signature", p3, len3); +#endif + + len2 = sizeof(out); + /* (5) */ + DO(ltc_mp.rsa_me(p3, len3, p2, &len2, PK_PRIVATE, &key)); + + len3 = sizeof(tmp); + /* (6) */ + SHOULD_FAIL(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey)); + DOX(stat == 0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should fail"); + } + rsa_free(&key); + + /* try reading the public RSA key from a X509 certificate */ + len3 = sizeof(tmp); + DO(base64_decode(x509_public_rsa, sizeof(x509_public_rsa), tmp, &len3)); + DO(rsa_import_x509(tmp, len3, &key)); + len = sizeof(tmp); + DO(rsa_export(tmp, &len, PK_PUBLIC, &key)); + DO(do_compare_testvector(tmp, len, openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), "RSA public export failed to match rsa_import_x509", 0)); + rsa_free(&key); + + len3 = sizeof(tmp); + DO(base64_decode(ltc_der_tests_cacert_root_cert, ltc_der_tests_cacert_root_cert_size, tmp, &len3)); + + DO(rsa_import_x509(tmp, len3, &key)); + + /* free the key and return */ + rsa_free(&key); + rsa_free(&pubKey); + rsa_free(&privKey); + return 0; +} + +#else + +int rsa_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/deps/libtomcrypt/tests/sources.cmake b/deps/libtomcrypt/tests/sources.cmake new file mode 100644 index 0000000..d63a1cc --- /dev/null +++ b/deps/libtomcrypt/tests/sources.cmake @@ -0,0 +1,35 @@ +set(SOURCES +base16_test.c +base32_test.c +base64_test.c +bcrypt_test.c +cipher_hash_test.c +common.c +der_test.c +dh_test.c +dsa_test.c +ecc_test.c +ed25519_test.c +file_test.c +mac_test.c +misc_test.c +modes_test.c +mpi_test.c +multi_test.c +no_null_termination_check_test.c +no_prng.c +padding_test.c +pkcs_1_eme_test.c +pkcs_1_emsa_test.c +pkcs_1_oaep_test.c +pkcs_1_pss_test.c +pkcs_1_test.c +prng_test.c +rotate_test.c +rsa_test.c +ssh_test.c +store_test.c +test.c +x25519_test.c +) + diff --git a/deps/libtomcrypt/tests/ssh_test.c b/deps/libtomcrypt/tests/ssh_test.c new file mode 100644 index 0000000..4760c64 --- /dev/null +++ b/deps/libtomcrypt/tests/ssh_test.c @@ -0,0 +1,356 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_test.h" + +/** + @file ssh_test.c + Support for SSH data formats (RFC4251), Russ Williams +*/ + +#ifdef LTC_SSH + +#define BUFSIZE 64 + +/** + Test vectors from from RFC4251, section 5 + + uint32: "the value 699921578 (0x29b7f4aa) is stored as 29 b7 f4 aa" + + string: "the US-ASCII string "testing" is represented as 00 00 00 07 t e s t i n g" + + mpint: + value (hex) representation (hex) + ----------- -------------------- + 0 00 00 00 00 + 9a378f9b2e332a7 00 00 00 08 09 a3 78 f9 b2 e3 32 a7 + 80 00 00 00 02 00 80 + -1234 00 00 00 02 ed cc + -deadbeef 00 00 00 05 ff 21 52 41 11 + + name-list: + value representation (hex) + ----- -------------------- + (), the empty name-list 00 00 00 00 + ("zlib") 00 00 00 04 7a 6c 69 62 + ("zlib,none") 00 00 00 09 7a 6c 69 62 2c 6e 6f 6e 65 +*/ +static const unsigned char byte1[] = {0x01}; +static const unsigned char byte2[] = {0x71}; +static const unsigned char uint32[] = {0x29, 0xb7, 0xf4, 0xaa}; +static const unsigned char uint64[] = {0x09, 0xa3, 0x78, 0xf9, 0xb2, 0xe3, 0x32, 0xa7}; +static const unsigned char string[] = {0x00, 0x00, 0x00, 0x07, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67}; +static const unsigned char mpint1[] = {0x00, 0x00, 0x00, 0x00}; +static const unsigned char mpint2[] = {0x00, 0x00, 0x00, 0x08, 0x09, 0xa3, 0x78, 0xf9, 0xb2, 0xe3, 0x32, 0xa7}; +static const unsigned char mpint3[] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x80}; +static const unsigned char nlist1[] = {0x00, 0x00, 0x00, 0x00}; +static const unsigned char nlist2[] = {0x00, 0x00, 0x00, 0x04, 0x7a, 0x6c, 0x69, 0x62}; +static const unsigned char nlist3[] = {0x00, 0x00, 0x00, 0x09, 0x7a, 0x6c, 0x69, 0x62, 0x2c, 0x6e, 0x6f, 0x6e, 0x65}; + + +/** + LTC_SSH encoding test + @return CRYPT_OK if successful +*/ +static int s_ssh_encoding_test(void) +{ + unsigned char buffer[BUFSIZE]; + unsigned long buflen; + unsigned long len; + void *v, *zero; + int err; + + /* Buffer too short */ + buflen = 3; + zeromem(buffer, BUFSIZE); + SHOULD_FAIL(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_UINT32, 0x29b7f4aa, + LTC_SSHDATA_EOL, NULL)); + + + /* byte */ + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_BYTE, 0x01, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, byte1, sizeof(byte1), "enc-byte", 1); + + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_BYTE, 0x71, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, byte2, sizeof(byte2), "enc-byte", 2); + if (XMEMCMP(buffer, byte2, buflen) != 0) return CRYPT_FAIL_TESTVECTOR; + + /* boolean */ + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_BOOLEAN, 0x01, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, byte1, sizeof(byte1), "enc-boolean", 1); + + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_BOOLEAN, 0x71, + LTC_SSHDATA_EOL, NULL)); + /* Should be written out as 0x01 */ + COMPARE_TESTVECTOR(buffer, buflen, byte1, sizeof(byte1), "enc-boolean", 2); + + /* uint32 */ + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_UINT32, 0x29b7f4aa, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, uint32, sizeof(uint32), "enc-uint32", 1); + + /* uint64 */ + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_UINT64, CONST64(0x09a378f9b2e332a7), + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, uint64, sizeof(uint64), "enc-uint64", 1); + + + /* string */ + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + len = strlen("testing"); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_STRING, "testing", len, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, string, sizeof(string), "enc-string", 1); + + + /* mpint */ + if ((err = mp_init_multi(&zero, &v, LTC_NULL)) != CRYPT_OK) { + return err; + } + + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(mp_set(zero, 0)); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_MPINT, zero, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, mpint1, sizeof(mpint1), "enc-mpint", 1); + + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(mp_read_radix(v, "9a378f9b2e332a7", 16)); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_MPINT, v, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, mpint2, sizeof(mpint2), "enc-mpint", 2); + + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + DO(mp_set(v, 0x80)); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_MPINT, v, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, mpint3, sizeof(mpint3), "enc-mpint", 3); + + mp_clear_multi(v, zero, LTC_NULL); + + + /* name-list */ + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + len = strlen(""); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_NAMELIST, "", len, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, nlist1, sizeof(nlist1), "enc-nlist", 1); + + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + len = strlen("zlib"); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_NAMELIST, "zlib", len, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, nlist2, sizeof(nlist2), "enc-nlist", 2); + + buflen = BUFSIZE; + zeromem(buffer, BUFSIZE); + len = strlen("zlib,none"); + DO(ssh_encode_sequence_multi(buffer, &buflen, + LTC_SSHDATA_NAMELIST, "zlib,none", len, + LTC_SSHDATA_EOL, NULL)); + COMPARE_TESTVECTOR(buffer, buflen, nlist3, sizeof(nlist3), "enc-nlist", 3); + + return CRYPT_OK; +} + +/** + LTC_SSH decoding test + @return CRYPT_OK if successful +*/ +static int s_ssh_decoding_test(void) +{ + char strbuf[BUFSIZE]; + void *u, *v; + unsigned long size; + ulong32 tmp32; + ulong64 tmp64; + unsigned char tmp8; + unsigned long len; + int err; + + /* Buffer longer */ + len = sizeof(strbuf); + strbuf[0] = 0; + DO(ssh_decode_sequence_multi((unsigned char*)strbuf, &len, + LTC_SSHDATA_BYTE, &tmp8, + LTC_SSHDATA_EOL, NULL)); + ENSURE(tmp8 == 0x00); + ENSURE(len == 1); + + + /* byte */ + len = sizeof(byte1); + DO(ssh_decode_sequence_multi(byte1, &len, + LTC_SSHDATA_BYTE, &tmp8, + LTC_SSHDATA_EOL, NULL)); + ENSURE(tmp8 == 0x01); + ENSURE(len == 1); + + len = sizeof(byte2); + DO(ssh_decode_sequence_multi(byte2, &len, + LTC_SSHDATA_BYTE, &tmp8, + LTC_SSHDATA_EOL, NULL)); + ENSURE(tmp8 == 0x71); + ENSURE(len == 1); + + /* boolean */ + len = sizeof(byte1); + DO(ssh_decode_sequence_multi(byte1, &len, + LTC_SSHDATA_BOOLEAN, &tmp8, + LTC_SSHDATA_EOL, NULL)); + ENSURE(tmp8 == 0x01); + ENSURE(len == 1); + + len = sizeof(byte2); + DO(ssh_decode_sequence_multi(byte2, &len, + LTC_SSHDATA_BOOLEAN, &tmp8, + LTC_SSHDATA_EOL, NULL)); + ENSURE(tmp8 == 0x01); + ENSURE(len == 1); + + /* uint32 */ + len = sizeof(uint32); + DO(ssh_decode_sequence_multi(uint32, &len, + LTC_SSHDATA_UINT32, &tmp32, + LTC_SSHDATA_EOL, NULL)); + ENSURE(tmp32 == 0x29b7f4aa); + ENSURE(len == 4); + + /* uint64 */ + len = sizeof(uint64); + DO(ssh_decode_sequence_multi(uint64, &len, + LTC_SSHDATA_UINT64, &tmp64, + LTC_SSHDATA_EOL, NULL)); + if (tmp64 != CONST64(0x09a378f9b2e332a7)) return CRYPT_FAIL_TESTVECTOR; + ENSURE(len == 8); + + /* string */ + zeromem(strbuf, BUFSIZE); + size = BUFSIZE; + len = sizeof(string); + DO(ssh_decode_sequence_multi(string, &len, + LTC_SSHDATA_STRING, strbuf, &size, + LTC_SSHDATA_EOL, NULL)); + ENSURE(strlen("testing") == size); + ENSURE(XSTRCMP(strbuf, "testing") == 0); + ENSURE(strlen("testing") + 4 == len); + + /* mpint */ + if ((err = mp_init_multi(&u, &v, LTC_NULL)) != CRYPT_OK) { + return err; + } + + len = sizeof(mpint1); + DO(ssh_decode_sequence_multi(mpint1, &len, + LTC_SSHDATA_MPINT, v, + LTC_SSHDATA_EOL, NULL)); + ENSURE(mp_cmp_d(v, 0) == LTC_MP_EQ); + ENSURE(sizeof(mpint1) == len); + + len = sizeof(mpint2); + DO(ssh_decode_sequence_multi(mpint2, &len, + LTC_SSHDATA_MPINT, v, + LTC_SSHDATA_EOL, NULL)); + DO(mp_read_radix(u, "9a378f9b2e332a7", 16)); + ENSURE(mp_cmp(u, v) == LTC_MP_EQ); + ENSURE(sizeof(mpint2) == len); + + len = sizeof(mpint3); + DO(ssh_decode_sequence_multi(mpint3, &len, + LTC_SSHDATA_MPINT, v, + LTC_SSHDATA_EOL, NULL)); + ENSURE(mp_cmp_d(v, 0x80) == LTC_MP_EQ); + ENSURE(sizeof(mpint3) == len); + + mp_clear_multi(v, u, LTC_NULL); + + /* name-list */ + zeromem(strbuf, BUFSIZE); + size = BUFSIZE; + len = sizeof(nlist1); + DO(ssh_decode_sequence_multi(nlist1, &len, + LTC_SSHDATA_NAMELIST, strbuf, &size, + LTC_SSHDATA_EOL, NULL)); + ENSURE(strlen("") == size); + ENSURE(XSTRCMP(strbuf, "") == 0); + + zeromem(strbuf, BUFSIZE); + size = BUFSIZE; + len = sizeof(nlist2); + DO(ssh_decode_sequence_multi(nlist2, &len, + LTC_SSHDATA_NAMELIST, strbuf, &size, + LTC_SSHDATA_EOL, NULL)); + ENSURE(strlen("zlib") == size); + ENSURE(XSTRCMP(strbuf, "zlib") == 0); + ENSURE(strlen("zlib") + 4 == len); + + zeromem(strbuf, BUFSIZE); + size = BUFSIZE; + len = sizeof(nlist3); + DO(ssh_decode_sequence_multi(nlist3, &len, + LTC_SSHDATA_NAMELIST, strbuf, &size, + LTC_SSHDATA_EOL, NULL)); + ENSURE(strlen("zlib,none") == size); + ENSURE(XSTRCMP(strbuf, "zlib,none") == 0); + ENSURE(strlen("zlib,none") + 4 == len); + + + return CRYPT_OK; +} + +/** + LTC_SSH self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int ssh_test(void) +{ + if (ltc_mp.name == NULL) return CRYPT_NOP; + + DO(s_ssh_encoding_test()); + DO(s_ssh_decoding_test()); + + return CRYPT_OK; +} + +#else + +int ssh_test(void) +{ + return CRYPT_NOP; +} + +#endif + diff --git a/deps/libtomcrypt/tests/store_test.c b/deps/libtomcrypt/tests/store_test.c new file mode 100644 index 0000000..03d733e --- /dev/null +++ b/deps/libtomcrypt/tests/store_test.c @@ -0,0 +1,76 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +/* Test store/load macros with offsets */ +int store_test(void) +{ + unsigned char buf[256]; + unsigned long y; + ulong32 L, L1; + ulong64 LL, LL1; +#ifdef LTC_FAST + unsigned long x, z; +#endif + + for (y = 0; y < 4; y++) { + L = 0x12345678UL; + L1 = 0; + STORE32L(L, buf + y); + LOAD32L(L1, buf + y); + if (L1 != L) { + fprintf(stderr, "\n32L failed at offset %lu\n", y); + return 1; + } + STORE32H(L, buf + y); + LOAD32H(L1, buf + y); + if (L1 != L) { + fprintf(stderr, "\n32H failed at offset %lu\n", y); + return 1; + } + } + + for (y = 0; y < 8; y++) { + LL = CONST64 (0x01020304050607); + LL1 = 0; + STORE64L(LL, buf + y); + LOAD64L(LL1, buf + y); + if (LL1 != LL) { + fprintf(stderr, "\n64L failed at offset %lu\n", y); + return 1; + } + STORE64H(LL, buf + y); + LOAD64H(LL1, buf + y); + if (LL1 != LL) { + fprintf(stderr, "\n64H failed at offset %lu\n", y); + return 1; + } + } + +/* test LTC_FAST */ +#ifdef LTC_FAST + y = 16; + + for (z = 0; z < y; z++) { + /* fill y bytes with random */ + ENSURE(yarrow_read(buf+z, y, &yarrow_prng) == y); + ENSURE(yarrow_read(buf+z+y, y, &yarrow_prng) == y); + + /* now XOR it byte for byte */ + for (x = 0; x < y; x++) { + buf[2*y+z+x] = buf[z+x] ^ buf[z+y+x]; + } + + /* now XOR it word for word */ + for (x = 0; x < y; x += sizeof(LTC_FAST_TYPE)) { + *(LTC_FAST_TYPE_PTR_CAST(&buf[3*y+z+x])) = *(LTC_FAST_TYPE_PTR_CAST(&buf[z+x])) ^ *(LTC_FAST_TYPE_PTR_CAST(&buf[z+y+x])); + } + + if (memcmp(&buf[2*y+z], &buf[3*y+z], y)) { + fprintf(stderr, "\nLTC_FAST failed at offset %lu\n", z); + return 1; + } + } +#endif + return 0; +} diff --git a/deps/libtomcrypt/tests/test.c b/deps/libtomcrypt/tests/test.c new file mode 100644 index 0000000..375beb2 --- /dev/null +++ b/deps/libtomcrypt/tests/test.c @@ -0,0 +1,435 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#ifndef GIT_VERSION +#define GIT_VERSION "Undefined version" +#endif + +#define LTC_TEST_FN(f) { f, #f } + +typedef struct { + int (*fn)(void); + const char* name; +} test_function; + +static const test_function test_functions[] = +{ + LTC_TEST_FN(store_test), + LTC_TEST_FN(rotate_test), + LTC_TEST_FN(misc_test), + LTC_TEST_FN(mpi_test), + LTC_TEST_FN(cipher_hash_test), + LTC_TEST_FN(mac_test), + LTC_TEST_FN(modes_test), + LTC_TEST_FN(der_test), + LTC_TEST_FN(pkcs_1_test), + LTC_TEST_FN(pkcs_1_pss_test), + LTC_TEST_FN(pkcs_1_oaep_test), + LTC_TEST_FN(pkcs_1_emsa_test), + LTC_TEST_FN(pkcs_1_eme_test), + LTC_TEST_FN(rsa_test), + LTC_TEST_FN(dh_test), + LTC_TEST_FN(ecc_test), + LTC_TEST_FN(dsa_test), + LTC_TEST_FN(ed25519_test), + LTC_TEST_FN(x25519_test), + LTC_TEST_FN(file_test), + LTC_TEST_FN(multi_test), + /* keep the prng_test always at the end as + * it has to be handled specially when + * testing with LTC_PTHREAD enabled + */ + LTC_TEST_FN(prng_test), +}; + + +#if defined(_WIN32) + #include /* GetSystemTimeAsFileTime */ +#else + #include +#endif + +/* microseconds since 1970 (UNIX epoch) */ +static ulong64 epoch_usec(void) +{ +#if defined(LTC_NO_TEST_TIMING) + return 0; +#elif defined(_WIN32) + FILETIME CurrentTime; + ulong64 cur_time; + ULARGE_INTEGER ul; + GetSystemTimeAsFileTime(&CurrentTime); + ul.LowPart = CurrentTime.dwLowDateTime; + ul.HighPart = CurrentTime.dwHighDateTime; + cur_time = ul.QuadPart; /* now we have 100ns intervals since 1 January 1601 */ + cur_time -= CONST64(116444736000000000); /* subtract 100ns intervals between 1601-1970 */ + cur_time /= 10; /* 100ns intervals > microseconds */ + return cur_time; +#elif defined(LTC_CLOCK_GETTIME) + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return (ulong64)(ts.tv_sec) * 1000000 + (ulong64)(ts.tv_nsec) / 1000; /* get microseconds */ +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return (ulong64)(tv.tv_sec) * 1000000 + (ulong64)(tv.tv_usec); /* get microseconds */ +#endif +} + +#ifdef LTC_PTHREAD +typedef struct +{ + pthread_t thread_id; + const test_function* t; + int err; + ulong64 delta; +} thread_info; + +static void *run(void *arg) +{ + thread_info *tinfo = arg; + ulong64 ts; + + ts = epoch_usec(); + tinfo->err = tinfo->t->fn(); + tinfo->delta = epoch_usec() - ts; + + return arg; +} +#endif + + +/* + * unregister ciphers, hashes & prngs + */ +static void s_unregister_all(void) +{ +#ifdef LTC_RIJNDAEL +#ifdef ENCRYPT_ONLY + /* alternative would be + * unregister_cipher(&rijndael_enc_desc); + */ + unregister_cipher(&aes_enc_desc); +#else + /* alternative would be + * unregister_cipher(&rijndael_desc); + */ + unregister_cipher(&aes_desc); +#endif +#endif +#ifdef LTC_BLOWFISH + unregister_cipher(&blowfish_desc); +#endif +#ifdef LTC_XTEA + unregister_cipher(&xtea_desc); +#endif +#ifdef LTC_RC5 + unregister_cipher(&rc5_desc); +#endif +#ifdef LTC_RC6 + unregister_cipher(&rc6_desc); +#endif +#ifdef LTC_SAFERP + unregister_cipher(&saferp_desc); +#endif +#ifdef LTC_TWOFISH + unregister_cipher(&twofish_desc); +#endif +#ifdef LTC_SAFER + unregister_cipher(&safer_k64_desc); + unregister_cipher(&safer_sk64_desc); + unregister_cipher(&safer_k128_desc); + unregister_cipher(&safer_sk128_desc); +#endif +#ifdef LTC_RC2 + unregister_cipher(&rc2_desc); +#endif +#ifdef LTC_DES + unregister_cipher(&des_desc); + unregister_cipher(&des3_desc); +#endif +#ifdef LTC_CAST5 + unregister_cipher(&cast5_desc); +#endif +#ifdef LTC_NOEKEON + unregister_cipher(&noekeon_desc); +#endif +#ifdef LTC_SKIPJACK + unregister_cipher(&skipjack_desc); +#endif +#ifdef LTC_KHAZAD + unregister_cipher(&khazad_desc); +#endif +#ifdef LTC_ANUBIS + unregister_cipher(&anubis_desc); +#endif +#ifdef LTC_KSEED + unregister_cipher(&kseed_desc); +#endif +#ifdef LTC_KASUMI + unregister_cipher(&kasumi_desc); +#endif +#ifdef LTC_MULTI2 + unregister_cipher(&multi2_desc); +#endif +#ifdef LTC_CAMELLIA + unregister_cipher(&camellia_desc); +#endif +#ifdef LTC_IDEA + unregister_cipher(&idea_desc); +#endif +#ifdef LTC_SERPENT + unregister_cipher(&serpent_desc); +#endif + +#ifdef LTC_TIGER + unregister_hash(&tiger_desc); +#endif +#ifdef LTC_MD2 + unregister_hash(&md2_desc); +#endif +#ifdef LTC_MD4 + unregister_hash(&md4_desc); +#endif +#ifdef LTC_MD5 + unregister_hash(&md5_desc); +#endif +#ifdef LTC_SHA1 + unregister_hash(&sha1_desc); +#endif +#ifdef LTC_SHA224 + unregister_hash(&sha224_desc); +#endif +#ifdef LTC_SHA256 + unregister_hash(&sha256_desc); +#endif +#ifdef LTC_SHA384 + unregister_hash(&sha384_desc); +#endif +#ifdef LTC_SHA512 + unregister_hash(&sha512_desc); +#endif +#ifdef LTC_SHA512_224 + unregister_hash(&sha512_224_desc); +#endif +#ifdef LTC_SHA512_256 + unregister_hash(&sha512_256_desc); +#endif +#ifdef LTC_SHA3 + unregister_hash(&sha3_224_desc); + unregister_hash(&sha3_256_desc); + unregister_hash(&sha3_384_desc); + unregister_hash(&sha3_512_desc); +#endif +#ifdef LTC_KECCAK + unregister_hash(&keccak_224_desc); + unregister_hash(&keccak_256_desc); + unregister_hash(&keccak_384_desc); + unregister_hash(&keccak_512_desc); +#endif +#ifdef LTC_RIPEMD128 + unregister_hash(&rmd128_desc); +#endif +#ifdef LTC_RIPEMD160 + unregister_hash(&rmd160_desc); +#endif +#ifdef LTC_RIPEMD256 + unregister_hash(&rmd256_desc); +#endif +#ifdef LTC_RIPEMD320 + unregister_hash(&rmd320_desc); +#endif +#ifdef LTC_WHIRLPOOL + unregister_hash(&whirlpool_desc); +#endif +#ifdef LTC_BLAKE2S + unregister_hash(&blake2s_128_desc); + unregister_hash(&blake2s_160_desc); + unregister_hash(&blake2s_224_desc); + unregister_hash(&blake2s_256_desc); +#endif +#ifdef LTC_BLAKE2B + unregister_hash(&blake2b_160_desc); + unregister_hash(&blake2b_256_desc); + unregister_hash(&blake2b_384_desc); + unregister_hash(&blake2b_512_desc); +#endif +#ifdef LTC_CHC_HASH + unregister_hash(&chc_desc); +#endif + + unregister_prng(&yarrow_desc); +#ifdef LTC_FORTUNA + unregister_prng(&fortuna_desc); +#endif +#ifdef LTC_RC4 + unregister_prng(&rc4_desc); +#endif +#ifdef LTC_CHACHA20_PRNG + unregister_prng(&chacha20_prng_desc); +#endif +#ifdef LTC_SOBER128 + unregister_prng(&sober128_desc); +#endif +#ifdef LTC_SPRNG + unregister_prng(&sprng_desc); +#endif +} /* s_cleanup() */ + +static void register_algs(void) +{ + int err; + + atexit(s_unregister_all); + +#ifndef LTC_YARROW + #error This demo requires Yarrow. +#endif + if ((err = register_all_ciphers()) != CRYPT_OK) { + fprintf(stderr, "register_all_ciphers err=%s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = register_all_hashes()) != CRYPT_OK) { + fprintf(stderr, "register_all_hashes err=%s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = register_all_prngs()) != CRYPT_OK) { + fprintf(stderr, "register_all_prngs err=%s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + if ((err = rng_make_prng(128, find_prng("yarrow"), &yarrow_prng, NULL)) != CRYPT_OK) { + fprintf(stderr, "rng_make_prng failed: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + + if (strcmp("CRYPT_OK", error_to_string(err))) { + exit(EXIT_FAILURE); + } +} + +int main(int argc, char **argv) +{ +#ifdef LTC_PTHREAD + thread_info *tinfo, *res; +#endif + int x, pass = 0, fail = 0, nop = 0; + size_t fn_len, i, dots; + const char* mpi_provider = NULL; + char *single_test = NULL; + ulong64 ts; + long delta, dur, real = 0; + register_algs(); + + printf("LTC_VERSION = %s\n%s\n\n", GIT_VERSION, crypt_build_settings); + +#ifdef USE_LTM + mpi_provider = "ltm"; +#elif defined(USE_TFM) + mpi_provider = "tfm"; +#elif defined(USE_GMP) + mpi_provider = "gmp"; +#elif defined(EXT_MATH_LIB) + mpi_provider = "ext"; +#endif + + if (argc > 2) { + mpi_provider = argv[2]; + } + + crypt_mp_init(mpi_provider); + + if (ltc_mp.name != NULL) { + printf("MP_PROVIDER = %s\n", ltc_mp.name); + printf("MP_DIGIT_BIT = %d\n", MP_DIGIT_BIT); + printf("sizeof(ltc_mp_digit) = %d\n", (int)sizeof(ltc_mp_digit)); + } else { + printf("NO math provider selected, all tests requiring MPI will 'nop'\n"); + } + +#ifdef LTC_PTHREAD + tinfo = XCALLOC(sizeof(test_functions)/sizeof(test_functions[0]), sizeof(thread_info)); + if (tinfo == NULL) { + printf("\n\nFAILURE: XCALLOC\n"); + return EXIT_FAILURE; + } +#endif + + fn_len = 0; + for (i = 0; i < sizeof(test_functions) / sizeof(test_functions[0]); ++i) { + size_t len = XSTRLEN(test_functions[i].name); + if (fn_len < len) fn_len = len; + +#ifdef LTC_PTHREAD + if(test_functions[i].fn == prng_test) continue; + tinfo[i].t = &test_functions[i]; + x = pthread_create(&tinfo[i].thread_id, NULL, run, &tinfo[i]); + if (x != 0) { + printf("\n\nFAILURE: pthread_create\n"); + return EXIT_FAILURE; + } +#endif + } + + fn_len = fn_len + (4 - (fn_len % 4)); + + /* single test name from commandline */ + if (argc > 1) single_test = argv[1]; + + dur = epoch_usec(); + for (i = 0; i < sizeof(test_functions)/sizeof(test_functions[0]); ++i) { + if (single_test && strstr(test_functions[i].name, single_test) == NULL) { + continue; + } + dots = fn_len - XSTRLEN(test_functions[i].name); + + printf("\n%s", test_functions[i].name); + while(dots--) printf("."); + fflush(stdout); + +#ifdef LTC_PTHREAD + if(test_functions[i].fn != prng_test) { + x = pthread_join(tinfo[i].thread_id, (void**)&res); + if (x != 0){ + printf("\n\nFAILURE: pthread_join\n"); + return EXIT_FAILURE; + } + x = res->err; + delta = res->delta; + } + else { + ts = epoch_usec(); + x = test_functions[i].fn(); + delta = (long)(epoch_usec() - ts); + } +#else + ts = epoch_usec(); + x = test_functions[i].fn(); + delta = (long)(epoch_usec() - ts); +#endif + real += delta; + + if (x == CRYPT_OK) { + printf("passed %10.3fms", (double)(delta)/1000); + pass++; + } + else if (x == CRYPT_NOP) { + printf("nop"); + nop++; + } + else { + printf("failed (%s) %10.3fms", error_to_string(x), (double)(delta)/1000); + fail++; + } + } + dur = epoch_usec() - dur; + +#ifdef LTC_PTHREAD + XFREE(tinfo); +#endif + + x = (fail > 0 || fail+pass+nop == 0) ? EXIT_FAILURE : EXIT_SUCCESS; + printf("\n\n%s: passed=%d failed=%d nop=%d duration=%.1fsec real=%.1fsec\n", x ? "FAILURE" : "SUCCESS", pass, fail, nop, (double)(dur)/(1000*1000), (double)(real)/(1000*1000)); + return x; +} diff --git a/deps/libtomcrypt/tests/test.der b/deps/libtomcrypt/tests/test.der new file mode 100644 index 0000000000000000000000000000000000000000..d7041f9bae4faee624fca2c73cc1c76ffbe64ffe GIT binary patch literal 162 zcmV;T0A2qufuAr91_>&LNQU;DU0)QC7qDsEf9 z5;sS^1#7(9^X}vkjzMUAVH4Lv$bh~!kK720PpqWkb_~g5Y)M#??aZp&B|8dWKZ{g4 Q!%Z>gl%z!c0s{d60p8$86aWAK literal 0 HcmV?d00001 diff --git a/deps/libtomcrypt/tests/test.key b/deps/libtomcrypt/tests/test.key new file mode 100644 index 0000000..e4996c3 --- /dev/null +++ b/deps/libtomcrypt/tests/test.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDPmt5kitrIMyCp14MxGVSymoWnobd1M7aprIQks97bfYUtlmXl +P3KVJJ8oaMpP20QcPmASit0mpev/C17UiDhJKm5bvxI3R70Fa7zb8+7kEY5BaHxh +E9dCyIC+No/cCItPrKTidgzJY2xJWJPtzKrcJTsKYD+LVDrDTTHnlKRE/QIDAQAB +AoGBAMhiuereRFMdVpfZl54azzAeCohFhikwo02fYWVz4NaHj7bzBqOC3Hys/pso +mq79+/4vDtiXBOO7H9HsDbqjSX9HrIpEBH6GtzlCP60etw6lUfRAYx79veqfQZ+o +kB1vClqVExENgK9fZJiKLHhoZbAri6JTh8rxZASr8nvbg8iBAkEA975eI8MyP7+L +jjru/PzL5ffxC7xCgq7Vej7K99VpP2Qloh+3dXUFkkLruPHzCgXjlNFVeDWgNqCb +fJKEbN3cTQJBANaGDoVCCwQIhCFg8A4NiP0eNhBlTx5TtAhygFw/WWYX5pjy6Wx6 +Bkysdj3tjKHOrRu9tH0ovOMOOI2Z2AW1o3ECQG3rwy0u8F6kiDEFKQCK0ZUpm4PP +ddsx43on3jp0MAx2TNRQKkAtOdmZY6ldgK5TypQ/BSMe+AUE4bg18hezoIkCQQCr +kIj6YAgpUJpDi6BQzNha/pdkY3F0IqMgAlrP68YWlVTRy6uNGsYA+giSnHHVUlI1 +lnFLi5IM0Om/rWMLpemxAkEA3MwnyOTcYkjVm6/1q2D2If1T4rddCckaoQSp/GEs +XQRYOlo58UohVmf9zCCjj3gYWnk9Lo5+hgrmqDPBBBdKnw== +-----END RSA PRIVATE KEY----- diff --git a/deps/libtomcrypt/tests/test_dsa.key b/deps/libtomcrypt/tests/test_dsa.key new file mode 100644 index 0000000..2f02669 --- /dev/null +++ b/deps/libtomcrypt/tests/test_dsa.key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQDFCjdRXKvWGNWicL1Kb2tK+eE5lQ8rmTh9mmTWTLWWetztrKis +xhtlWt7bAGElGhgs7qEHkGJeTRIxkMcDIfoJ57Fz146v2/2/s++t0aEqA23nBpJK +hSr/egFmUx/qxmdBhFrAbO1i+cJiYgWk+kigZuw1yagR/rmBq+6+Mba/zwIVAKpb +1/TlBiQT5Yg1ygDHpjVxYZTFAoGAO5Lk/1kpFQsImVp78q0UQFVvoEf/kJmzRLPU +/EUVBa5nIkOcujcQpYlHN+zM9a6tqLR6Ncudk1zt5rB+lpTEpgx91nCKCU+BSg7C +E/vrFr/qpPRW/3IwBd6KRD++xoUmVdYtHR7bFdqkRYM8F5eYC42H80kNkL2pq2du +h2hyI9wCgYBTFrD7v1mKXlWVwU+sQ7gIU+bPDZIj+rGEWVI5v8vyLTg63ZNSBUl+ +KxLEYXPjb1S9luWnqqlaWKS3Z9LAvcgesToST5jABe85XWq6tws72LeV3XluotKE +c0cDiLRk2bm4T/HJNLv5c2b1fC4R/sMx5gg4WWeB621BJ9cNdK+gNQIVAJk25eTp ++yi+kfUGX+jJNbP12B/F +-----END DSA PRIVATE KEY----- diff --git a/deps/libtomcrypt/tests/tomcrypt_test.h b/deps/libtomcrypt/tests/tomcrypt_test.h new file mode 100644 index 0000000..263c4e6 --- /dev/null +++ b/deps/libtomcrypt/tests/tomcrypt_test.h @@ -0,0 +1,52 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#ifndef TOMCRYPT_TEST_H_ +#define TOMCRYPT_TEST_H_ + +#include "tomcrypt_private.h" + +#include "common.h" + +typedef struct { + char *name, *prov, *req; + int (*entry)(void); +} test_entry; + +/* TESTS */ +int cipher_hash_test(void); +int modes_test(void); +int mac_test(void); +int pkcs_1_test(void); +int pkcs_1_pss_test(void); +int pkcs_1_oaep_test(void); +int pkcs_1_emsa_test(void); +int pkcs_1_eme_test(void); +int store_test(void); +int rotate_test(void); +int rsa_test(void); +int dh_test(void); +int ecc_test(void); +int dsa_test(void); +int der_test(void); +int misc_test(void); +int base64_test(void); +int base32_test(void); +int base16_test(void); +int file_test(void); +int multi_test(void); +int prng_test(void); +int mpi_test(void); +int padding_test(void); +int x25519_test(void); +int ed25519_test(void); +int ssh_test(void); +int bcrypt_test(void); +int no_null_termination_check_test(void); + +#ifdef LTC_PKCS_1 +struct ltc_prng_descriptor* no_prng_desc_get(void); +void no_prng_desc_free(struct ltc_prng_descriptor*); +#endif + +#endif diff --git a/deps/libtomcrypt/tests/x25519_test.c b/deps/libtomcrypt/tests/x25519_test.c new file mode 100644 index 0000000..0d44235 --- /dev/null +++ b/deps/libtomcrypt/tests/x25519_test.c @@ -0,0 +1,250 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_test.h" + +/** + @file x25519_test.c + x25519 tests, Steffen Jaeckel +*/ + +#ifdef LTC_CURVE25519 + +static int s_rfc_7748_5_2_test(void) +{ + /* RFC 7748 Ch. 5.2 */ + const struct { + unsigned char scalar[32]; + unsigned char u_in[32]; + unsigned char u_out[32]; + } rfc_7748_5_2[] = { + { + { 0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, + 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, + 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, + 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4 }, + { 0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, + 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, + 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, + 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c }, + { 0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, + 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f, + 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, + 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52 } + }, + { + { 0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, + 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5, + 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, + 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d }, + { 0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, + 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c, + 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, + 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93 }, + { 0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, + 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8, + 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, + 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57 } + } + }; + unsigned char out[32]; + unsigned long n; + + for (n = 0; n < sizeof(rfc_7748_5_2)/sizeof(rfc_7748_5_2[0]); ++n) { + tweetnacl_crypto_scalarmult(out, rfc_7748_5_2[n].scalar, rfc_7748_5_2[n].u_in); + if (compare_testvector(out, sizeof(out), rfc_7748_5_2[n].u_out, sizeof(rfc_7748_5_2[n].u_out), "x25519 RFC 7748 Ch. 5.2", n) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +} + +static int s_rfc_7748_6_test(void) +{ + /* RFC 7748 Ch. 6 */ + const unsigned char alice_private[] = { + 0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, + 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, + 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a, + 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a + }; + const unsigned char alice_public[] = { + 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, + 0x74, 0x8b, 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, + 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a, 0xf4, + 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a + }; + const unsigned char bob_private[] = { + 0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, + 0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6, + 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd, + 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb + }; + const unsigned char bob_public[] = { + 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, + 0xd3, 0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, + 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d, + 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f + }; + const unsigned char shared_secret[] = { + 0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, + 0x72, 0x8e, 0x3b, 0xf4, 0x80, 0x35, 0x0f, 0x25, + 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1, 0x9e, 0x33, + 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42 + }; + curve25519_key alice_priv, alice_pub, bob_priv, bob_pub; + unsigned char buf[32]; + unsigned long buflen = sizeof(buf); + + DO(x25519_import_raw(alice_private, sizeof(alice_private), PK_PRIVATE, &alice_priv)); + DO(x25519_import_raw(bob_private, sizeof(bob_private), PK_PRIVATE, &bob_priv)); + DO(x25519_import_raw(alice_public, sizeof(alice_public), PK_PUBLIC, &alice_pub)); + DO(x25519_import_raw(bob_public, sizeof(bob_public), PK_PUBLIC, &bob_pub)); + + DO(x25519_shared_secret(&alice_priv, &bob_pub, buf, &buflen)); + DO(compare_testvector(buf, buflen, shared_secret, sizeof(shared_secret), "x25519 - RFC 7748 Ch. 6", 0)); + + XMEMSET(buf, 0, sizeof(buf)); + + DO(x25519_shared_secret(&bob_priv, &alice_pub, buf, &buflen)); + DO(compare_testvector(buf, buflen, shared_secret, sizeof(shared_secret), "x25519 - RFC 7748 Ch. 6", 1)); + + return CRYPT_OK; +} + +static int s_rfc_8410_10_test(void) +{ + const struct { + const char *b64; + } rfc_8410_10[] = { + /* RFC 8410 - 10.2. Example X25519 Certificate */ + { "MIIBLDCB36ADAgECAghWAUdKKo3DMDAFBgMrZXAwGTEXMBUGA1UEAwwOSUVURiBUZX" + "N0IERlbW8wHhcNMTYwODAxMTIxOTI0WhcNNDAxMjMxMjM1OTU5WjAZMRcwFQYDVQQD" + "DA5JRVRGIFRlc3QgRGVtbzAqMAUGAytlbgMhAIUg8AmJMKdUdIt93LQ+91oNvzoNJj" + "ga9OukqY6qm05qo0UwQzAPBgNVHRMBAf8EBTADAQEAMA4GA1UdDwEBAAQEAwIDCDAg" + "BgNVHQ4BAQAEFgQUmx9e7e0EM4Xk97xiPFl1uQvIuzswBQYDK2VwA0EAryMB/t3J5v" + "/BzKc9dNZIpDmAgs3babFOTQbs+BolzlDUwsPrdGxO3YNGhW7Ibz3OGhhlxXrCe1Cg" + "w1AH9efZBw==" + }, + }; + unsigned n; + curve25519_key key; + unsigned char buf[1024]; + unsigned long buflen; + for (n = 0; n < sizeof(rfc_8410_10)/sizeof(rfc_8410_10[0]); ++n) { + buflen = sizeof(buf); + DO(base64_decode(rfc_8410_10[n].b64, XSTRLEN(rfc_8410_10[n].b64), buf, &buflen)); + DO(x25519_import_x509(buf, buflen, &key)); + zeromem(buf, sizeof(buf)); + } + return CRYPT_OK; +} + +static int s_x25519_pkcs8_test(void) +{ + const struct { + const char *b64, *pass; + } s_x25519_pkcs8[] = { + /* `openssl genpkey -algorithm x25519 -pass stdin -aes128` */ + { + "MIGbMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjG5kRkEihOvQICCAAw" + "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEHPLHLoCvesRyeToyMtGHWcEQM1+" + "FMpSO5DplX3d+YGTAvf0WxWaBff1q4bfKDn/7IoWQT1e4Fe6Psj62Vy9T69o3+Uy" + "VM6mdIOXGOkAtaMSsSk=", + "123456" + }, + /* `openssl genpkey -algorithm x25519 -pass stdin` */ + { + "MC4CAQAwBQYDK2VuBCIEIEAInaUdx+fQFfghpCzw/WdItRT3+FnPSkrU9TcIZTZW", + NULL + }, + }; + unsigned n; + curve25519_key key; + unsigned char buf[1024]; + unsigned long buflen, passlen; + for (n = 0; n < sizeof(s_x25519_pkcs8)/sizeof(s_x25519_pkcs8[0]); ++n) { + buflen = sizeof(buf); + DO(base64_decode(s_x25519_pkcs8[n].b64, XSTRLEN(s_x25519_pkcs8[n].b64), buf, &buflen)); + if (s_x25519_pkcs8[n].pass != NULL) passlen = XSTRLEN(s_x25519_pkcs8[n].pass); + else passlen = 0; + DO(x25519_import_pkcs8(buf, buflen, s_x25519_pkcs8[n].pass, passlen, &key)); + zeromem(buf, sizeof(buf)); + } + return CRYPT_OK; +} + +static int s_x25519_compat_test(void) +{ + curve25519_key priv, pub, imported; + unsigned char buf[1024]; + unsigned long buflen = sizeof(buf); + int prng_idx = find_prng("yarrow"); + + XMEMSET(&priv, 0, sizeof(priv)); + XMEMSET(&pub, 0, sizeof(pub)); + XMEMSET(&imported, 0, sizeof(imported)); + + DO(x25519_make_key(&yarrow_prng, prng_idx, &priv)); + + DO(x25519_export(buf, &buflen, PK_PRIVATE | PK_STD, &priv)); + DO(x25519_import_pkcs8(buf, buflen, NULL, 0, &imported)); + DO(do_compare_testvector(&priv, sizeof(priv), &imported, sizeof(imported), "priv after ex-&import", __LINE__)); + XMEMSET(&imported, 0, sizeof(imported)); + + buflen = sizeof(buf); + DO(x25519_export(buf, &buflen, PK_PUBLIC, &priv)); + DO(x25519_import_raw(buf, buflen, PK_PUBLIC, &pub)); + + buflen = sizeof(buf); + DO(x25519_export(buf, &buflen, PK_PUBLIC | PK_STD, &priv)); + DO(x25519_import(buf, buflen, &imported)); + + DO(do_compare_testvector(&pub, sizeof(pub), &imported, sizeof(imported), "pub after private ex-&import", __LINE__)); + XMEMSET(&imported, 0, sizeof(imported)); + + buflen = sizeof(buf); + DO(x25519_export(buf, &buflen, PK_PUBLIC | PK_STD, &pub)); + DO(x25519_import(buf, buflen, &imported)); + + DO(do_compare_testvector(&pub, sizeof(pub), &imported, sizeof(imported), "pub after public ex-&import", __LINE__)); + + return CRYPT_OK; +} + +/** + Test the x25519 system + @return CRYPT_OK if successful +*/ +int x25519_test(void) +{ + int ret; + + if (ltc_mp.name == NULL) return CRYPT_NOP; + + if ((ret = s_rfc_7748_5_2_test()) != CRYPT_OK) { + return ret; + } + if ((ret = s_rfc_7748_6_test()) != CRYPT_OK) { + return ret; + } + if ((ret = s_rfc_8410_10_test()) != CRYPT_OK) { + return ret; + } + if ((ret = s_x25519_pkcs8_test()) != CRYPT_OK) { + return ret; + } + if ((ret = s_x25519_compat_test()) != CRYPT_OK) { + return ret; + } + + return ret; +} + +#else + +int x25519_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/deps/libtomcrypt/updatemakes.sh b/deps/libtomcrypt/updatemakes.sh new file mode 100644 index 0000000..5acb953 --- /dev/null +++ b/deps/libtomcrypt/updatemakes.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +./helper.pl --update-makefiles || exit 1 + +makefiles=(makefile makefile_include.mk makefile.shared makefile.unix makefile.mingw makefile.msvc) +vcproj=(libtomcrypt_VS2008.vcproj) + +if [ $# -eq 1 ] && [ "$1" == "-c" ]; then + git add ${makefiles[@]} ${vcproj[@]} doc/Doxyfile && git commit -m 'Update makefiles' +fi + +exit 0 + +# ref: $Format:%D$ +# git commit: $Format:%H$ +# commit time: $Format:%ai$ diff --git a/deps/libtommath b/deps/libtommath deleted file mode 160000 index f6507b7..0000000 --- a/deps/libtommath +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f6507b7a1bef22965dd7a0e17bd010cd16704463 diff --git a/deps/libtommath/.gitattributes b/deps/libtommath/.gitattributes new file mode 100644 index 0000000..b522729 --- /dev/null +++ b/deps/libtommath/.gitattributes @@ -0,0 +1,5 @@ +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore + +/** export-subst diff --git a/deps/libtommath/.github/workflows/deploy.yml b/deps/libtommath/.github/workflows/deploy.yml new file mode 100644 index 0000000..3789236 --- /dev/null +++ b/deps/libtommath/.github/workflows/deploy.yml @@ -0,0 +1,47 @@ +############################################################################# +# # +# Packagecloud deployment via GH actions for LibTomMath # +# (https://github.com/libtom/libtommath.git) # +# # +############################################################################# + +name: Deploy + +on: + workflow_dispatch + +jobs: + deploy-to-packagecloud: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-20.04, ubuntu-22.04 ] + steps: + - uses: actions/checkout@v2 + - name: set Ubuntu codename + run: | + echo "ubuntu_codename="$(lsb_release -sc) >> "$GITHUB_ENV" + - name: install dependencies + run: | + wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null + echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${{ env.ubuntu_codename }} main" | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null + sudo apt-get update -qq + sudo apt-get install -y cmake gcc + - name: build static + run: | + mkdir -p build + cd build + cmake -DBUILD_SHARED_LIBS=Off -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + make -j$(nproc) + cpack -G DEB + cmake -DBUILD_SHARED_LIBS=On -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + make -j$(nproc) + cpack -G DEB + - name: push package to packagecloud.io + uses: computology/packagecloud-github-action@v0.6 + with: + PACKAGE-NAME: packages/ubuntu/${{ env.ubuntu_codename }}/*.deb + PACKAGECLOUD-USERNAME: libtom + PACKAGECLOUD-REPONAME: libtom + PACKAGECLOUD-DISTRO: ubuntu/${{ env.ubuntu_codename }} + PACKAGECLOUD-TOKEN: ${{ secrets.PACKAGECLOUD_TOKEN }} diff --git a/deps/libtommath/.github/workflows/main.yml b/deps/libtommath/.github/workflows/main.yml new file mode 100644 index 0000000..457216a --- /dev/null +++ b/deps/libtommath/.github/workflows/main.yml @@ -0,0 +1,202 @@ +############################################################################# +# # +# GitHub Actions test-suite for LibTomMath # +# (https://github.com/libtom/libtommath.git) # +# # +############################################################################# + +name: CI + +# Tests restricted to the following branches of LTM. +on: + push: + branches: + - master + - develop + - /^release\/.*$/ + - /^support\/.*$/ + - /^ci\/.*$/ + pull_request: + branches: + - master + - develop + - /^release\/.*$/ + - /^support\/.*$/ + - /^ci\/.*$/ + +jobs: + Testme: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-20.04 ] + # The environment given to the programs in the build + # We have only one program and the variable $BUILDOPTIONS + # has only the options to that program: testme.sh + + config: + # Check c89 <-> c99 roundtrip + - { BUILDOPTIONS: '--c89-c99-roundtrip', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + # Check source code format + - { BUILDOPTIONS: '--format', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'astyle' } + # Check public symbols of dynamic libraries + - { BUILDOPTIONS: '--symbols', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libtool-bin' } + # Run always with valgrind (no sanitizer, but debug info) + - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --with-valgrind', SANITIZER: '', COMPILE_DEBUG: '1', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + # Alternative big-int version of mp_log(_n) + - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --cflags=-DS_MP_WORD_TOO_SMALL_C="" --with-valgrind', SANITIZER: '', COMPILE_DEBUG: '1', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + # Shared library build + - { BUILDOPTIONS: '--with-cc=gcc --make-option=-f --make-option=makefile.shared', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '1', CONV_WARNINGS: '', OTHERDEPS: 'libtool-bin' } + # GCC for the 32-bit architecture (no valgrind) + - { BUILDOPTIONS: '--with-cc=gcc --with-m32', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libc6-dev-i386 gcc-multilib' } + # Alternative big-int version of mp_log(_n) for the 32-bit architecture (no valgrind) + - { BUILDOPTIONS: '--with-cc=gcc --with-m32 --cflags=-DS_MP_WORD_TOO_SMALL_C="" ', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libc6-dev-i386 gcc-multilib' } + # clang for the 32-bit architecture (no valgrind) + - { BUILDOPTIONS: '--with-cc=clang-10 --with-m32', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10 gcc-multilib' } + # RSA superclass with tests (no sanitizer, but debug info) + - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --cflags=-DLTM_NOTHING --cflags=-DSC_RSA_1_WITH_TESTS --limit-valgrind', SANITIZER: '', COMPILE_DEBUG: '1', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + + # Test "autotuning", the automatic evaluation and setting of the Toom-Cook cut-offs. + #- env: SANITIZER=1 BUILDOPTIONS='--with-cc=gcc-5 --cflags=-DMP_16BIT --limit-valgrind --make-option=tune' + #- env: SANITIZER=1 BUILDOPTIONS='--with-cc=gcc-5 --cflags=-DMP_32BIT --limit-valgrind --make-option=tune' + #- env: SANITIZER=1 BUILDOPTIONS='--with-cc=gcc-5 --limit-valgrind --make-option=tune' + #- env: SANITIZER=1 BUILDOPTIONS='--with-cc=clang-7 --cflags=-DMP_16BIT --limit-valgrind --make-option=tune' + #- env: SANITIZER=1 BUILDOPTIONS='--with-cc=clang-7 --cflags=-DMP_32BIT --limit-valgrind --make-option=tune' + - { BUILDOPTIONS: '--with-cc=clang-10 --limit-valgrind --make-option=tune', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10' } + + # GCC for the x86-64 architecture testing against a different Bigint-implementation + # with 333333 different inputs. + #- env: BUILDOPTIONS='--with-cc=gcc --test-vs-mtest=333333 --limit-valgrind' + # ... and a better random source. + - { BUILDOPTIONS: '--with-cc=gcc --test-vs-mtest=333333 --mtest-real-rand --limit-valgrind', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + + # clang for the x86-64 architecture testing against a different Bigint-implementation + # with 333333 different inputs + - { BUILDOPTIONS: '--with-cc=clang-10 --test-vs-mtest=333333 --limit-valgrind', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10' } + # ... and a better random source. + - { BUILDOPTIONS: '--with-cc=clang-10 --test-vs-mtest=333333 --mtest-real-rand --limit-valgrind', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10' } + + # GCC for the x64_32 architecture (32-bit longs and 32-bit pointers) + # TODO: Probably not possible to run anything in x32 in GH actions + # but needs to be checked to be sure. + - { BUILDOPTIONS: '--with-cc=gcc --with-mx32', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libc6-dev-x32 gcc-multilib' } + + # GCC for the x86-64 architecture (64-bit longs and 64-bit pointers) + - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + - { BUILDOPTIONS: '--with-cc=gcc-10 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'gcc-10' } + - { BUILDOPTIONS: '--with-cc=gcc-8 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'gcc-8' } + - { BUILDOPTIONS: '--with-cc=gcc-7 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'gcc-7' } + + # clang for x86-64 architecture (64-bit longs and 64-bit pointers) + - { BUILDOPTIONS: '--with-cc=clang-10 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: 'relaxed', OTHERDEPS: 'clang-10 llvm-10' } + - { BUILDOPTIONS: '--with-cc=clang-10 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: 'strict', OTHERDEPS: 'clang-10 llvm-10' } + - { BUILDOPTIONS: '--with-cc=clang-10 --cflags=-DMP_USE_MEMOPS --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: 'strict', OTHERDEPS: 'clang-10 llvm-10' } + - { BUILDOPTIONS: '--with-cc=clang-10 --c89 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: 'strict', OTHERDEPS: 'clang-10 llvm-10' } + - { BUILDOPTIONS: '--with-cc=clang-10 --with-m64 --limit-valgrind --cflags=-DMP_PREC=MP_MIN_PREC', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10' } + - { BUILDOPTIONS: '--with-cc=clang-12 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-12 llvm-12' } + - { BUILDOPTIONS: '--with-cc=clang-9 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-9 llvm-9' } + - { BUILDOPTIONS: '--with-cc=clang-8 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-8 llvm-8' } + - { BUILDOPTIONS: '--with-cc=clang-7 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-7 llvm-7' } + - { BUILDOPTIONS: '--with-cc=clang-6.0 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-6.0 llvm-6.0' } + # Link time optimization + - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '1', CONV_WARNINGS: '', OTHERDEPS: '' } + #- { BUILDOPTIONS: '--with-cc=clang-7 --with-m64 --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '1', CONV_WARNINGS: '', OTHERDEPS: '' } + + # GCC for the x86-64 architecture with restricted limb sizes + # formerly started with the option "--with-low-mp" to testme.sh + # but testing all three in one run took to long and timed out. + - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_16BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_32BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + # Alternative big-int version of mp_log(_n) + - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_16BIT --cflags=-DS_MP_WORD_TOO_SMALL_C="" --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_32BIT --cflags=-DS_MP_WORD_TOO_SMALL_C="" --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + + # clang for the x86-64 architecture with restricted limb sizes + - { BUILDOPTIONS: '--with-cc=clang --cflags=-DMP_16BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang llvm' } + - { BUILDOPTIONS: '--with-cc=clang --cflags=-DMP_32BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang llvm' } + steps: + - uses: actions/checkout@v2 + - name: install dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y valgrind ${{ matrix.config.OTHERDEPS }} + sudo apt-cache search gcc | grep '^gcc-[0-9\.]* ' + sudo apt-cache search clang | grep compiler + - name: run tests + env: + SANITIZER: ${{ matrix.config.SANITIZER }} + COMPILE_DEBUG: ${{ matrix.config.COMPILE_DEBUG }} + COMPILE_LTO: ${{ matrix.config.COMPILE_LTO }} + CONV_WARNINGS: ${{ matrix.config.CONV_WARNINGS }} + COMMIT_MESSAGE: ${{ github.event.commits[0].message }} + PR_NUMBER: ${{ github.event.number }} + # The actual script the jobs run. + run: | + ./testme.sh ${{ matrix.config.BUILDOPTIONS }} + # In case of a CI error a success might get signaled + # even without any test run. This file also keeps any notes + # printed from the tests which might come handy from time + # to time. + # Valgrid will print its output to stderr which will not show up + # in test_*.log. testme.sh accepts one additional option to + # valgrind and "--valgrind-options=--log-fd=1" sends the output + # of Valgrind to stdout instead. + - name: regular logs + if: ${{ !failure() }} + run: | + cat test_*.log || true + # Compilation failures are in gcc_errors_*.log + # Failed tests in test_*.log + # Files do not exist in case of success + - name: error logs + if: ${{ failure() }} + run: | + cat test_*.log || true + cat valgrind_test.log || true + cat gcc_errors_*.log || true + + amalgam: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v2 + - name: install dependencies + run: | + make amalgamated_timing + + CMake: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-20.04, ubuntu-22.04 ] + build_type: [ '', -DCMAKE_BUILD_TYPE=Debug, -DCMAKE_BUILD_TYPE=Release, -DCMAKE_BUILD_TYPE=RelWithDebInfo, -DCMAKE_BUILD_TYPE=MinSizeRel ] + cc: [ clang, gcc ] + config: + # Static library build + - { CMAKEOPTIONS: '-DBUILD_SHARED_LIBS=Off' } + # Shared library build + - { CMAKEOPTIONS: '-DBUILD_SHARED_LIBS=On' } + steps: + - uses: actions/checkout@v2 + - name: install dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y cmake gcc clang llvm + - name: build + run: | + mkdir build + cd build + CC=${{ matrix.cc }} cmake ${{ matrix.config.CMAKEOPTIONS }} ${{ matrix.build_type }} .. + make -j$(nproc) + - name: test + run: | + cd build + CC=${{ matrix.cc }} cmake ${{ matrix.config.CMAKEOPTIONS }} ${{ matrix.build_type }} -DBUILD_TESTING=On .. + make -j$(nproc) + ctest + - name: test (in demo folder) + run: | + mkdir -p demo/build + cd demo/build + CC=${{ matrix.cc }} cmake ${{ matrix.config.CMAKEOPTIONS }} ${{ matrix.build_type }} .. + make -j$(nproc) + ctest diff --git a/deps/libtommath/.gitignore b/deps/libtommath/.gitignore new file mode 100644 index 0000000..d2f0132 --- /dev/null +++ b/deps/libtommath/.gitignore @@ -0,0 +1,123 @@ +# suppress compiler/linker output +*.[oa] +*.l[oa] +*.obj +*.gcda +*.gcno +*.gcov +*.dll +*.exp +*.pdb +*.lib +*.tmp +[Dd]ebug/ +[Rr]elease/ +/MSVC_* +.libs/ +.coveralls.yml +coverage*/ +coverage.info +pre_gen/* + +# suppress output of build process and *nix/windows test executables +timing +timing.exe +test +test.exe +mtest +mtest.exe +mtest_opponent +mtest_opponent.exe + +# ignore eclipse project files +.cproject +.project +.settings + +# special MS Visual Studio section +# ignore non-compressed browse file (holds information for ClassView, IntelliSense and WizardBar) +*.ncb +# ignore user specific settings +*.user +*.suo +*.userosscache +*.sln.docstates +*.userprefs +# cache/options directory +.vs/ +# Backup & report files from converting an old project file to a newer Visual Studio version +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +# Visual Studio 6 build log + workspace options file +*.plg +*.opt +# visual studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Linux perf profiler +perf.data +perf.data.old + +# ignore tommath_amalgam.c generated by make +tommath_amalgam.c + +# ignore file generated by make tune +tuning_list +etc/tune + +# ignore stuff generated by "make manual" and "make poster" +*.aux +*.dvi +*.idx +*.lof +*.log +*.out +*.toc +*.ilg +*.ind +*.pdf +*.out +tommath.tex +libtommath.pc + +# ignore files generated by bibtex/biber +83aea75e0c59d1de027747003151d53dcb2a51c9.bib +*.bbl +*.bcf +*.blg +*.loa +*.lol +*.run.xml + + +# ignore files generated by testme.sh +gcc_errors_*.txt +test_*.txt + +.#* +*~ +*.bak +*.orig +*.asc +*.tar.xz +*.zip + +doc/pics/*.ps +doc/*.bak* + +logs/*.png +logs/*-*.dem + +callgraph.txt + +# cmake build directories +build*/ + +# kdevelop section +.kdev4/ +*.kdev4 diff --git a/deps/libtommath/CMakeLists.txt b/deps/libtommath/CMakeLists.txt new file mode 100644 index 0000000..8321c64 --- /dev/null +++ b/deps/libtommath/CMakeLists.txt @@ -0,0 +1,288 @@ +# SPDX-License-Identifier: Unlicense +# +# LibTomMath, a free open source portable number theoretic multiple-precision +# integer (MPI) library written entirely in C. +# + +cmake_minimum_required(VERSION 3.10) + +project(libtommath + VERSION 1.2.0 + DESCRIPTION "A free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C." + HOMEPAGE_URL "https://www.libtom.net/LibTomMath" + LANGUAGES C) + +# package release version +# bump if re-releasing the same VERSION + patches +# set to 1 if releasing a new VERSION +set(PACKAGE_RELEASE_VERSION 1) + +#----------------------------------------------------------------------------- +# Include cmake modules +#----------------------------------------------------------------------------- +include(GNUInstallDirs) +include(CheckIPOSupported) +include(CMakePackageConfigHelpers) +# default is "No tests" +option(BUILD_TESTING "" OFF) +include(CTest) +include(sources.cmake) + +# The only direct cmake argument for now +option(BUILD_SHARED_LIBS "Build shared library and only the shared library if \"ON\", default is static" OFF) + +#----------------------------------------------------------------------------- +# Compose CFLAGS +#----------------------------------------------------------------------------- + +# Some information ported from makefile_include.mk + + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to 'Release' as none was specified.") + set(CMAKE_BUILD_TYPE "Release") +endif() + +# We only differentiate between MSVC and GCC-compatible compilers +if(MSVC) + set(LTM_C_FLAGS -W3) +elseif(WATCOM) + set(LTM_C_FLAGS -fo=.obj -oaxt -3r -w3) +else() + set(LTM_C_FLAGS -Wall -Wsign-compare -Wextra -Wshadow + -Wdeclaration-after-statement -Wbad-function-cast -Wcast-align + -Wstrict-prototypes -Wpointer-arith -Wsystem-headers) + set(CMAKE_C_FLAGS_DEBUG "-g3") + set(CMAKE_C_FLAGS_RELEASE "-O3 -funroll-loops -fomit-frame-pointer") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g3 -O2") + set(CMAKE_C_FLAGS_MINSIZEREL "-Os") +endif() + +# What compiler do we have and what are their...uhm... peculiarities +if(CMAKE_C_COMPILER_ID MATCHES "(C|c?)lang") + list(APPEND LTM_C_FLAGS -Wno-typedef-redefinition -Wno-tautological-compare -Wno-builtin-requires-header) + # Clang requires at least '-O1' for dead code elimination + set(CMAKE_C_FLAGS_DEBUG "-O1 ${CMAKE_C_FLAGS_DEBUG}") +endif() +if(CMAKE_C_COMPILER MATCHES "mingw") + list(APPEND LTM_C_FLAGS -Wno-shadow -Wno-expansion-to-defined -Wno-declaration-after-statement -Wno-bad-function-cast) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + list(APPEND LTM_C_FLAGS -Wno-nullability-completeness) +endif() +if(CMAKE_SYSTEM_NAME MATCHES "CYGWIN") + list(APPEND LTM_C_FLAGS -no-undefined) +endif() + +# TODO: coverage (lgcov) + +# If the user set the environment variables at generate-time, append them +# in order to allow overriding our defaults. +# ${LTM_CFLAGS} means the user passed it via sth like: +# $ cmake -DLTM_CFLAGS="foo" +list(APPEND LTM_C_FLAGS ${LTM_CFLAGS}) +list(APPEND LTM_LD_FLAGS ${LTM_LDFLAGS}) + +#----------------------------------------------------------------------------- +# library target +#----------------------------------------------------------------------------- +add_library(${PROJECT_NAME} + ${SOURCES} + ${HEADERS} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + $ + $ +) + +target_compile_options(${PROJECT_NAME} BEFORE PRIVATE + ${LTM_C_FLAGS} +) +target_link_options(${PROJECT_NAME} BEFORE PRIVATE + ${LTM_LD_FLAGS} +) + +set(PUBLIC_HEADERS tommath.h) +set(C89 False CACHE BOOL "(Usually maintained automatically) Enable when the library is in c89 mode to package the correct header files on install") +if(C89) + list(APPEND PUBLIC_HEADERS tommath_c89.h) +endif() + +set_target_properties(${PROJECT_NAME} PROPERTIES + OUTPUT_NAME tommath + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + PUBLIC_HEADER "${PUBLIC_HEADERS}" +) + +option(COMPILE_LTO "Build with LTO enabled") +if(COMPILE_LTO) + check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) + if(COMPILER_SUPPORTS_LTO) + set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(SEND_ERROR "This compiler does not support LTO. Reconfigure ${PROJECT_NAME} with -DCOMPILE_LTO=OFF.") + endif() +endif() + +#----------------------------------------------------------------------------- +# demo target +#----------------------------------------------------------------------------- + +if(BUILD_TESTING) + enable_testing() + add_subdirectory(demo) +endif() + +#----------------------------------------------------------------------------- +# Install/export targets and files +#----------------------------------------------------------------------------- +set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") +set(PROJECT_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake") +set(PROJECT_CONFIG_FILE "${PROJECT_NAME}-config.cmake") +set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") + +install(TARGETS ${PROJECT_NAME} + EXPORT ${TARGETS_EXPORT_NAME} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} +) + +# Install libtommath.pc for pkg-config if we build a shared library +if(BUILD_SHARED_LIBS) + # Let the user override the default directory of the pkg-config file (usually this shouldn't be required to be changed) + set(CMAKE_INSTALL_PKGCONFIGDIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Folder where to install .pc files") + + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + @ONLY + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR} + ) +endif() + +# generate package version file +write_basic_package_version_file( + ${PROJECT_VERSION_FILE} + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + +# install version file +install(FILES ${PROJECT_VERSION_FILE} + DESTINATION ${CONFIG_INSTALL_DIR} +) + +# build directory package config +export(EXPORT ${TARGETS_EXPORT_NAME} + FILE ${PROJECT_CONFIG_FILE} +) + +# installed package config +install(EXPORT ${TARGETS_EXPORT_NAME} + DESTINATION ${CONFIG_INSTALL_DIR} + FILE ${PROJECT_CONFIG_FILE} +) + +# add to CMake registry +export(PACKAGE ${PROJECT_NAME}) + +#--------------------------------------------------------------------------------------- +# Create release packages +#--------------------------------------------------------------------------------------- + +# determine distribution and architecture +find_program(LSB_RELEASE lsb_release) +find_program(SYSCTL sysctl) +find_program(UNAME uname) + +if(UNAME) + execute_process(COMMAND uname -m OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +elseif(SYSCTL) + execute_process(COMMAND sysctl -b hw.machine_arch OUTPUT_VARIABLE MACHINE_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +else() + string(TOLOWER ${CMAKE_SYSTEM_NAME} MACHINE_ARCH) +endif() + +if(LSB_RELEASE) + execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE LINUX_DISTRO OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND lsb_release -sc OUTPUT_VARIABLE LINUX_DISTRO_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE LINUX_DISTRO_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) + + string(TOLOWER ${LINUX_DISTRO} LINUX_DISTRO) + if(LINUX_DISTRO_CODENAME STREQUAL "n/a") + set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_VERSION}/) + else() + set(DISTRO_PACK_PATH ${LINUX_DISTRO}/${LINUX_DISTRO_CODENAME}/) + endif() +else() + set(DISTRO_PACK_PATH ${CMAKE_SYSTEM_NAME}/) +endif() + +# make sure untagged versions get a different package name +execute_process(COMMAND git describe --exact-match --tags RESULT_VARIABLE REPO_HAS_TAG) +if(REPO_HAS_TAG EQUAL 0) + set(PACKAGE_NAME_SUFFIX "") +else() + set(PACKAGE_NAME_SUFFIX "-git") +endif() + +# default CPack generators +set(CPACK_GENERATOR TGZ STGZ) + +# extra CPack generators +if(LINUX_DISTRO STREQUAL "debian" OR LINUX_DISTRO STREQUAL "ubuntu" OR LINUX_DISTRO STREQUAL "linuxmint") + list(APPEND CPACK_GENERATOR DEB) +elseif(LINUX_DISTRO STREQUAL "fedora" OR LINUX_DISTRO STREQUAL "opensuse" OR LINUX_DISTRO STREQUAL "centos") + list(APPEND CPACK_GENERATOR RPM) +elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") + list(APPEND CPACK_GENERATOR FREEBSD) +endif() + +# general CPack config +set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/packages/${DISTRO_PACK_PATH}) +message(STATUS "CPack: packages will be generated under ${CPACK_PACKAGE_DIRECTORY}") +if(BUILD_SHARED_LIBS) + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}") +else() + set(CPACK_PACKAGE_NAME "${PROJECT_NAME}-devel") +endif() +set(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}${PACKAGE_NAME_SUFFIX}") +set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION}) +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "LibTomMath") +set(CPACK_PACKAGE_VENDOR "libtom projects") +set(CPACK_PACKAGE_CONTACT "libtom@googlegroups.com") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(PACKAGE_NAME_TRAILER ${CPACK_PACKAGE_VERSION}-${PACKAGE_RELEASE_VERSION}_${MACHINE_ARCH}) +set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${PACKAGE_NAME_TRAILER}) +set(CPACK_STRIP_FILES ON) + +# deb specific CPack config +set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) +set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) +set(CPACK_DEBIAN_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION}) +if(BUILD_SHARED_LIBS) + set(CPACK_DEBIAN_PACKAGE_SECTION "libs") +else() + set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}-dev") + set(CPACK_DEBIAN_PACKAGE_SECTION "devel") +endif() + +# rpm specific CPack config +set(CPACK_RPM_PACKAGE_RELEASE ${PACKAGE_RELEASE_VERSION}) +set(CPACK_RPM_PACKAGE_ARCHITECTURE ${MACHINE_ARCH}) +set(CPACK_RPM_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-${PROJECT_VERSION}") +set(CPACK_RPM_PACKAGE_LICENSE "The Unlicense") + +# FreeBSD specific CPack config +set(CPACK_FREEBSD_PACKAGE_MAINTAINER "gahr@FreeBSD.org") +set(CPACK_FREEBSD_PACKAGE_ORIGIN "math/libtommath") +set(CPACK_FREEBSD_PACKAGE_CATEGORIES "math") + +include(CPack) diff --git a/deps/libtommath/LICENSE b/deps/libtommath/LICENSE new file mode 100644 index 0000000..b23b3c8 --- /dev/null +++ b/deps/libtommath/LICENSE @@ -0,0 +1,26 @@ + The LibTom license + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/deps/libtommath/Package.swift b/deps/libtommath/Package.swift new file mode 100644 index 0000000..54a195b --- /dev/null +++ b/deps/libtommath/Package.swift @@ -0,0 +1,40 @@ +// swift-tools-version:5.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "tommath", + platforms: [ + .macOS(.v10_10), .iOS(.v9), .tvOS(.v9) + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "libtommath", + targets: ["libtommath"]) + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "libtommath", + path: ".", + exclude: ["demo", "doc", "etc", "logs", "mtest"], + sources: ["."], + publicHeadersPath: "modulemap", + cSettings: [ + .unsafeFlags(["-flto=thin"]) // for Dead Code Elimination + ]), + .testTarget(name: "TommathTests", + dependencies: ["libtommath"], + path: "demo", + sources: ["tommath_tests.swift"]) + ], + cLanguageStandard: .gnu11, + cxxLanguageStandard: .gnucxx14 +) diff --git a/deps/libtommath/README.md b/deps/libtommath/README.md new file mode 100644 index 0000000..7ee58bb --- /dev/null +++ b/deps/libtommath/README.md @@ -0,0 +1,58 @@ +# libtommath + +This is the git repository for [LibTomMath](http://www.libtom.net/LibTomMath/), a free open source portable number theoretic multiple-precision integer (MPI) library written entirely in C. + +## Build Status + +### Travis CI + +master: [![Build Status](https://github.com/libtom/libtommath/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/libtom/libtommath/actions/workflows/main.yml?query=branch%3Amaster+++) + +develop: [![Build Status](https://github.com/libtom/libtommath/actions/workflows/main.yml/badge.svg?branch=develop)](https://github.com/libtom/libtommath/actions/workflows/main.yml?query=branch%3Adevelop+++) + +### AppVeyor + +master: [![Build status](https://ci.appveyor.com/api/projects/status/b80lpolw3i8m6hsh/branch/master?svg=true)](https://ci.appveyor.com/project/libtom/libtommath/branch/master) + +develop: [![Build status](https://ci.appveyor.com/api/projects/status/b80lpolw3i8m6hsh/branch/develop?svg=true)](https://ci.appveyor.com/project/libtom/libtommath/branch/develop) + +### ABI Laboratory + +API/ABI changes: [check here](https://abi-laboratory.pro/tracker/timeline/libtommath/) + +## Summary + +The `develop` branch contains the in-development version. Stable releases are tagged. + +Documentation is built from the LaTeX file `bn.tex`. There is also limited documentation in `tommath.h`. +There is also a document, `tommath.pdf`, which describes the goals of the project and many of the algorithms used. + +The project can be build by using `make`. Along with the usual `make`, `make clean` and `make install`, +there are several other build targets, see the makefile for details. +There are also makefiles for certain specific platforms. + +## Testing + +Tests are located in `demo/` and can be built in two flavors. +* `make test` creates a stand-alone test binary that executes several test routines. +* `make mtest_opponent` creates a test binary that is intended to be run against `mtest`. + `mtest` can be built with `make mtest` and test execution is done like `./mtest/mtest | ./mtest_opponent`. + `mtest` is creating test vectors using an alternative MPI library and `test` is consuming these vectors to verify correct behavior of ltm + +## Building and Installing + +Building is straightforward for GNU Linux only, the section "Building LibTomMath" in the documentation in `doc/bn.pdf` has the details. + +### CMake support + +The project provides support for the CMake build system. + +``` +git clone https://github.com/libtom/libtommath.git +mkdir -p libtommath/build +cd libtommath/build +cmake .. +make -j$(nproc) +``` + +A shared library build can be done by setting `-DBUILD_SHARED_LIBS=On` when invoking the `cmake` command. diff --git a/deps/libtommath/appveyor.yml b/deps/libtommath/appveyor.yml new file mode 100644 index 0000000..3bf8daf --- /dev/null +++ b/deps/libtommath/appveyor.yml @@ -0,0 +1,26 @@ +version: 1.2.0-{build} +branches: + only: + - master + - develop + - /^release/ + - /^support/ + - /^build-ci/ +image: +- Visual Studio 2022 +- Visual Studio 2019 +- Visual Studio 2017 +- Visual Studio 2015 +build_script: +- cmd: >- + if "Visual Studio 2022"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2019"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2017"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 + if "Visual Studio 2015"=="%APPVEYOR_BUILD_WORKER_IMAGE%" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 + nmake -f makefile.msvc test.exe + nmake -f makefile.msvc clean-obj + nmake -f makefile.msvc test_dll.exe CFLAGS="/Ox /MD /DLTM_TEST_DYNAMIC" +test_script: +- cmd: test.exe +- cmd: test_dll.exe diff --git a/deps/libtommath/astylerc b/deps/libtommath/astylerc new file mode 100644 index 0000000..029f358 --- /dev/null +++ b/deps/libtommath/astylerc @@ -0,0 +1,30 @@ +# Artistic Style, see http://astyle.sourceforge.net/ +# full documentation, see: http://astyle.sourceforge.net/astyle.html +# +# usage: +# astyle --options=astylerc *.[ch] + +# Do not create backup, annoying in the times of git +suffix=none + +## Bracket Style Options +style=kr + +## Tab Options +indent=spaces=3 + +## Bracket Modify Options + +## Indentation Options +min-conditional-indent=0 + +## Padding Options +pad-header +unpad-paren +align-pointer=name + +## Formatting Options +break-after-logical +max-code-length=120 +convert-tabs +mode=c diff --git a/deps/libtommath/changes.txt b/deps/libtommath/changes.txt new file mode 100644 index 0000000..565500b --- /dev/null +++ b/deps/libtommath/changes.txt @@ -0,0 +1,497 @@ +Oct 22nd, 2019 +v1.2.0 + -- A huge refactoring of the library happened - renaming, + deprecating and replacing existing functions by improved API's. + + All deprecated functions, macros and symbols are only marked as such + so this version is still API and ABI compatible to v1.x. + + -- Daniel Mendler was pushing for those changes and contributing a load of patches, + refactorings, code reviews and whatnotelse. + -- Christoph Zurnieden re-worked internals of the library, improved the performance, + did code reviews and wrote documentation. + -- Francois Perrad did some refactoring and took again care of linting the sources and + provided all fixes. + -- Jan Nijtmans, Karel Miko and Joachim Breitner contributed various patches. + + -- Private symbols can now be hidden for the shared library builds, disabled by default. + -- All API's follow a single code style, are prefixed the same etc. + -- Unified, safer and improved API's + -- Less magic numbers - return values (where appropriate) and most flags are now enums, + this was implemented in a backwards compatible way where return values were int. + -- API's with return values are now by default marked as "warn on unused result", this + can be disabled if required (which will most likely hide bugs), c.f. MP_WUR in tommath.h + -- Provide a whole set of setters&getters for different primitive types (long, uint32_t, etc.) + -- All those primitive setters are now optimized. + -- It's possible to automatically tune the cutoff values for Karatsuba&Toom-Cook + -- The custom allocators which were formerly known as XMALLOC(), XFREE() etc. are now available + as MP_MALLOC(), MP_REALLOC(), MP_CALLOC() and MP_FREE(). MP_REALLOC() and MP_FREE() now also + provide the allocated size to ease the usage of simple allocators without tracking. + -- Building is now also possible with MSVC 2015, 2017 and 2019 (use makefile.msvc) + -- Added mp_decr() and mp_incr() + -- Added mp_log_u32() + -- Improved prime-checking + -- Improved Toom-Cook multiplication + -- Removed the LTM book (`make docs` now builds the user manual) + + +Jan 28th, 2019 +v1.1.0 + -- Christoph Zurnieden contributed FIPS 186.4 compliant + prime-checking (PR #113), several other fixes and a load of documentation + -- Daniel Mendler provided two's-complement functions (PR #124) + and mp_{set,get}_double() (PR #123) + -- Francois Perrad took care of linting the sources, provided all fixes and + a astylerc to auto-format the sources. + -- A bunch of patches by Kevin B Kenny have been back-ported from TCL + -- Jan Nijtmans provided the patches to `const`ify all API + function arguments (also from TCL) + -- mp_rand() has now several native random provider implementations + and doesn't rely on `rand()` anymore + -- Karel Miko provided fixes when building for MS Windows + and re-worked the makefile generating process + -- The entire environment and build logic has been extended and improved + regarding auto-detection of platforms, libtool and a lot more + -- Prevent some potential BOF cases + -- Improved/fixed mp_lshd() and mp_invmod() + -- A load more bugs were fixed by various contributors + + +Aug 29th, 2017 +v1.0.1 + -- Dmitry Kovalenko provided fixes to mp_add_d() and mp_init_copy() + -- Matt Johnston contributed some improvements to mp_div_2d(), + mp_exptmod_fast(), mp_mod() and mp_mulmod() + -- Julien Nabet provided a fix to the error handling in mp_init_multi() + -- Ben Gardner provided a fix regarding usage of reserved keywords + -- Fixed mp_rand() to fill the correct number of bits + -- Fixed mp_invmod() + -- Use the same 64-bit detection code as in libtomcrypt + -- Correct usage of DESTDIR, PREFIX, etc. when installing the library + -- Francois Perrad updated all the perl scripts to an actual perl version + + +Feb 5th, 2016 +v1.0 + -- Bump to 1.0 + -- Dirkjan Bussink provided a faster version of mp_expt_d() + -- Moritz Lenz contributed a fix to mp_mod() + and provided mp_get_long() and mp_set_long() + -- Fixed bugs in mp_read_radix(), mp_radix_size + Thanks to shameister, Gerhard R, + -- Christopher Brown provided mp_export() and mp_import() + -- Improvements in the code of mp_init_copy() + Thanks to ramkumarkoppu, + -- lomereiter provided mp_balance_mul() + -- Alexander Boström from the heimdal project contributed patches to + mp_prime_next_prime() and mp_invmod() and added a mp_isneg() macro + -- Fix build issues for Linux x32 ABI + -- Added mp_get_long_long() and mp_set_long_long() + -- Carlin provided a patch to use arc4random() instead of rand() + on platforms where it is supported + -- Karel Miko provided mp_sqrtmod_prime() + + +July 23rd, 2010 +v0.42.0 + -- Fix for mp_prime_next_prime() bug when checking generated prime + -- allow mp_shrink to shrink initialized, but empty MPI's + -- Added project and solution files for Visual Studio 2005 and Visual Studio 2008. + +March 10th, 2007 +v0.41 -- Wolfgang Ehrhardt suggested a quick fix to mp_div_d() which makes the detection of powers of two quicker. + -- [CRI] Added libtommath.dsp for Visual C++ users. + +December 24th, 2006 +v0.40 -- Updated makefile to properly support LIBNAME + -- Fixed bug in fast_s_mp_mul_high_digs() which overflowed (line 83), thanks Valgrind! + +April 4th, 2006 +v0.39 -- Jim Wigginton pointed out my Montgomery examples in figures 6.4 and 6.6 were off by one, k should be 9 not 8 + -- Bruce Guenter suggested I use --tag=CC for libtool builds where the compiler may think it's C++. + -- "mm" from sci.crypt pointed out that my mp_gcd was sub-optimal (I also updated and corrected the book) + -- updated some of the @@ tags in tommath.src to reflect source changes. + -- updated email and url info in all source files + +Jan 26th, 2006 +v0.38 -- broken makefile.shared fixed + -- removed some carry stores that were not required [updated text] + +November 18th, 2005 +v0.37 -- [Don Porter] reported on a TCL list [HEY SEND ME BUGREPORTS ALREADY!!!] that mp_add_d() would compute -0 with some inputs. Fixed. + -- [rinick@gmail.com] reported the makefile.bcc was messed up. Fixed. + -- [Kevin Kenny] reported some issues with mp_toradix_n(). Now it doesn't require a min of 3 chars of output. + -- Made the make command renamable. Wee + +August 1st, 2005 +v0.36 -- LTM_PRIME_2MSB_ON was fixed and the "OFF" flag was removed. + -- [Peter LaDow] found a typo in the XREALLOC macro + -- [Peter LaDow] pointed out that mp_read_(un)signed_bin should have "const" on the input + -- Ported LTC patch to fix the prime_random_ex() function to get the bitsize correct [and the maskOR flags] + -- Kevin Kenny pointed out a stray // + -- David Hulton pointed out a typo in the textbook [mp_montgomery_setup() pseudo-code] + -- Neal Hamilton (Elliptic Semiconductor) pointed out that my Karatsuba notation was backwards and that I could use + unsigned operations in the routine. + -- Paul Schmidt pointed out a linking error in mp_exptmod() when BN_S_MP_EXPTMOD_C is undefined (and another for read_radix) + -- Updated makefiles to be way more flexible + +March 12th, 2005 +v0.35 -- Stupid XOR function missing line again... oops. + -- Fixed bug in invmod not handling negative inputs correctly [Wolfgang Ehrhardt] + -- Made exteuclid always give positive u3 output...[ Wolfgang Ehrhardt ] + -- [Wolfgang Ehrhardt] Suggested a fix for mp_reduce() which avoided underruns. ;-) + -- mp_rand() would emit one too many digits and it was possible to get a 0 out of it ... oops + -- Added montgomery to the testing to make sure it handles 1..10 digit moduli correctly + -- Fixed bug in comba that would lead to possible erroneous outputs when "pa < digs" + -- Fixed bug in mp_toradix_size for "0" [Kevin Kenny] + -- Updated chapters 1-5 of the textbook ;-) It now talks about the new comba code! + +February 12th, 2005 +v0.34 -- Fixed two more small errors in mp_prime_random_ex() + -- Fixed overflow in mp_mul_d() [Kevin Kenny] + -- Added mp_to_(un)signed_bin_n() functions which do bounds checking for ya [and report the size] + -- Added "large" diminished radix support. Speeds up things like DSA where the moduli is of the form 2^k - P for some P < 2^(k/2) or so + Actually is faster than Montgomery on my AMD64 (and probably much faster on a P4) + -- Updated the manual a bit + -- Ok so I haven't done the textbook work yet... My current freelance gig has landed me in France till the + end of Feb/05. Once I get back I'll have tons of free time and I plan to go to town on the book. + As of this release the API will freeze. At least until the book catches up with all the changes. I welcome + bug reports but new algorithms will have to wait. + +December 23rd, 2004 +v0.33 -- Fixed "small" variant for mp_div() which would munge with negative dividends... + -- Fixed bug in mp_prime_random_ex() which would set the most significant byte to zero when + no special flags were set + -- Fixed overflow [minor] bug in fast_s_mp_sqr() + -- Made the makefiles easier to configure the group/user that ltm will install as + -- Fixed "final carry" bug in comba multipliers. (Volkan Ceylan) + -- Matt Johnston pointed out a missing semi-colon in mp_exptmod + +October 29th, 2004 +v0.32 -- Added "makefile.shared" for shared object support + -- Added more to the build options/configs in the manual + -- Started the Depends framework, wrote dep.pl to scan deps and + produce "callgraph.txt" ;-) + -- Wrote SC_RSA_1 which will enable close to the minimum required to perform + RSA on 32-bit [or 64-bit] platforms with LibTomCrypt + -- Merged in the small/slower mp_div replacement. You can now toggle which + you want to use as your mp_div() at build time. Saves roughly 8KB or so. + -- Renamed a few files and changed some comments to make depends system work better. + (No changes to function names) + -- Merged in new Combas that perform 2 reads per inner loop instead of the older + 3reads/2writes per inner loop of the old code. Really though if you want speed + learn to use TomsFastMath ;-) + +August 9th, 2004 +v0.31 -- "profiled" builds now :-) new timings for Intel Northwoods + -- Added "pretty" build target + -- Update mp_init() to actually assign 0's instead of relying on calloc() + -- "Wolfgang Ehrhardt" found a bug in mp_mul() where if + you multiply a negative by zero you get negative zero as the result. Oops. + -- J Harper from PeerSec let me toy with his AMD64 and I got 60-bit digits working properly + [this also means that I fixed a bug where if sizeof(int) < sizeof(mp_digit) it would bug] + +April 11th, 2004 +v0.30 -- Added "mp_toradix_n" which stores upto "n-1" least significant digits of an mp_int + -- Johan Lindh sent a patch so MSVC wouldn't whine about redefining malloc [in weird dll modes] + -- Henrik Goldman spotted a missing OPT_CAST in mp_fwrite() + -- Tuned tommath.h so that when MP_LOW_MEM is defined MP_PREC shall be reduced. + [I also allow MP_PREC to be externally defined now] + -- Sped up mp_cnt_lsb() by using a 4x4 table [e.g. 4x speedup] + -- Added mp_prime_random_ex() which is a more versatile prime generator accurate to + exact bit lengths (unlike the deprecated but still available mp_prime_random() which + is only accurate to byte lengths). See the new LTM_PRIME_* flags ;-) + -- Alex Polushin contributed an optimized mp_sqrt() as well as mp_get_int() and mp_is_square(). + I've cleaned them all up to be a little more consistent [along with one bug fix] for this release. + -- Added mp_init_set and mp_init_set_int to initialize and set small constants with one function + call. + -- Removed /etclib directory [um LibTomPoly deprecates this]. + -- Fixed mp_mod() so the sign of the result agrees with the sign of the modulus. + ++ N.B. My semester is almost up so expect updates to the textbook to be posted to the libtomcrypt.org + website. + +Jan 25th, 2004 +v0.29 ++ Note: "Henrik" from the v0.28 changelog refers to Henrik Goldman ;-) + -- Added fix to mp_shrink to prevent a realloc when used == 0 [e.g. realloc zero bytes???] + -- Made the mp_prime_rabin_miller_trials() function internal table smaller and also + set the minimum number of tests to two (sounds a bit safer). + -- Added a mp_exteuclid() which computes the extended euclidean algorithm. + -- Fixed a memory leak in s_mp_exptmod() [called when Barrett reduction is to be used] which would arise + if a multiplication or subsequent reduction failed [would not free the temp result]. + -- Made an API change to mp_radix_size(). It now returns an error code and stores the required size + through an "int star" passed to it. + +Dec 24th, 2003 +v0.28 -- Henrik Goldman suggested I add casts to the montomgery code [stores into mu...] so compilers wouldn't + spew [erroneous] diagnostics... fixed. + -- Henrik Goldman also spotted two typos. One in mp_radix_size() and another in mp_toradix(). + -- Added fix to mp_shrink() to avoid a memory leak. + -- Added mp_prime_random() which requires a callback to make truly random primes of a given nature + (idea from chat with Niels Ferguson at Crypto'03) + -- Picked up a second wind. I'm filled with Gooo. Mission Gooo! + -- Removed divisions from mp_reduce_is_2k() + -- Sped up mp_div_d() [general case] to use only one division per digit instead of two. + -- Added the heap macros from LTC to LTM. Now you can easily [by editing four lines of tommath.h] + change the name of the heap functions used in LTM [also compatible with LTC via MPI mode] + -- Added bn_prime_rabin_miller_trials() which gives the number of Rabin-Miller trials to achieve + a failure rate of less than 2^-96 + -- fixed bug in fast_mp_invmod(). The initial testing logic was wrong. An invalid input is not when + "a" and "b" are even it's when "b" is even [the algo is for odd moduli only]. + -- Started a new manual [finally]. It is incomplete and will be finished as time goes on. I had to stop + adding full demos around half way in chapter three so I could at least get a good portion of the + manual done. If you really need help using the library you can always email me! + -- My Textbook is now included as part of the package [all Public Domain] + +Sept 19th, 2003 +v0.27 -- Removed changes.txt~ which was made by accident since "kate" decided it was + a good time to re-enable backups... [kde is fun!] + -- In mp_grow() "a->dp" is not overwritten by realloc call [re: memory leak] + Now if mp_grow() fails the mp_int is still valid and can be cleared via + mp_clear() to reclaim the memory. + -- Henrik Goldman found a buffer overflow bug in mp_add_d(). Fixed. + -- Cleaned up mp_mul_d() to be much easier to read and follow. + +Aug 29th, 2003 +v0.26 -- Fixed typo that caused warning with GCC 3.2 + -- Martin Marcel noticed a bug in mp_neg() that allowed negative zeroes. + Also, Martin is the fellow who noted the bugs in mp_gcd() of 0.24/0.25. + -- Martin Marcel noticed an optimization [and slight bug] in mp_lcm(). + -- Added fix to mp_read_unsigned_bin to prevent a buffer overflow. + -- Beefed up the comments in the baseline multipliers [and montgomery] + -- Added "mont" demo to the makefile.msvc in etc/ + -- Optimized sign compares in mp_cmp from 4 to 2 cases. + +Aug 4th, 2003 +v0.25 -- Fix to mp_gcd again... oops (0,-a) == (-a, 0) == a + -- Fix to mp_clear which didn't reset the sign [Greg Rose] + -- Added mp_error_to_string() to convert return codes to strings. [Greg Rose] + -- Optimized fast_mp_invmod() to do the test for invalid inputs [both even] + first so temps don't have to be initialized if it's going to fail. + -- Optimized mp_gcd() by removing mp_div_2d calls for when one of the inputs + is odd. + -- Tons of new comments, some indentation fixups, etc. + -- mp_jacobi() returns MP_VAL if the modulus is less than or equal to zero. + -- fixed two typos in the header of each file :-) + -- LibTomMath is officially Public Domain [see LICENSE] + +July 15th, 2003 +v0.24 -- Optimized mp_add_d and mp_sub_d to not allocate temporary variables + -- Fixed mp_gcd() so the gcd of 0,0 is 0. Allows the gcd operation to be chained + e.g. (0,0,a) == a [instead of 1] + -- Should be one of the last release for a while. Working on LibTomMath book now. + -- optimized the pprime demo [/etc/pprime.c] to first make a huge table of single + digit primes then it reads them randomly instead of randomly choosing/testing single + digit primes. + +July 12th, 2003 +v0.23 -- Optimized mp_prime_next_prime() to not use mp_mod [via is_divisible()] in each + iteration. Instead now a smaller table is kept of the residues which can be updated + without division. + -- Fixed a bug in next_prime() where an input of zero would be treated as odd and + have two added to it [to move to the next odd]. + -- fixed a bug in prime_fermat() and prime_miller_rabin() which allowed the base + to be negative, zero or one. Normally the test is only valid if the base is + greater than one. + -- changed the next_prime() prototype to accept a new parameter "bbs_style" which + will find the next prime congruent to 3 mod 4. The default [bbs_style==0] will + make primes which are either congruent to 1 or 3 mod 4. + -- fixed mp_read_unsigned_bin() so that it doesn't include both code for + the case DIGIT_BIT < 8 and >= 8 + -- optimized div_d() to easy out on division by 1 [or if a == 0] and use + logical shifts if the divisor is a power of two. + -- the default DIGIT_BIT type was not int for non-default builds. Fixed. + +July 2nd, 2003 +v0.22 -- Fixed up mp_invmod so the result is properly in range now [was always congruent to the inverse...] + -- Fixed up s_mp_exptmod and mp_exptmod_fast so the lower half of the pre-computed table isn't allocated + which makes the algorithm use half as much ram. + -- Fixed the install script not to make the book :-) [which isn't included anyways] + -- added mp_cnt_lsb() which counts how many of the lsbs are zero + -- optimized mp_gcd() to use the new mp_cnt_lsb() to replace multiple divisions by two by a single division. + -- applied similar optimization to mp_prime_miller_rabin(). + -- Fixed a bug in both mp_invmod() and fast_mp_invmod() which tested for odd + via "mp_iseven() == 0" which is not valid [since zero is not even either]. + +June 19th, 2003 +v0.21 -- Fixed bug in mp_mul_d which would not handle sign correctly [would not always forward it] + -- Removed the #line lines from gen.pl [was in violation of ISO C] + +June 8th, 2003 +v0.20 -- Removed the book from the package. Added the TDCAL license document. + -- This release is officially pure-bred TDCAL again [last officially TDCAL based release was v0.16] + +June 6th, 2003 +v0.19 -- Fixed a bug in mp_montgomery_reduce() which was introduced when I tweaked mp_rshd() in the previous release. + Essentially the digits were not trimmed before the compare which cause a subtraction to occur all the time. + -- Fixed up etc/tune.c a bit to stop testing new cutoffs after 16 failures [to find more optimal points]. + Brute force ho! + + +May 29th, 2003 +v0.18 -- Fixed a bug in s_mp_sqr which would handle carries properly just not very elegantly. + (e.g. correct result, just bad looking code) + -- Fixed bug in mp_sqr which still had a 512 constant instead of MP_WARRAY + -- Added Toom-Cook multipliers [needs tuning!] + -- Added efficient divide by 3 algorithm mp_div_3 + -- Re-wrote mp_div_d to be faster than calling mp_div + -- Added in a donated BCC makefile and a single page LTM poster (ahalhabsi@sbcglobal.net) + -- Added mp_reduce_2k which reduces an input modulo n = 2**p - k for any single digit k + -- Made the exptmod system be aware of the 2k reduction algorithms. + -- Rewrote mp_dr_reduce to be smaller, simpler and easier to understand. + +May 17th, 2003 +v0.17 -- Benjamin Goldberg submitted optimized mp_add and mp_sub routines. A new gen.pl as well + as several smaller suggestions. Thanks! + -- removed call to mp_cmp in inner loop of mp_div and put mp_cmp_mag in its place :-) + -- Fixed bug in mp_exptmod that would cause it to fail for odd moduli when DIGIT_BIT != 28 + -- mp_exptmod now also returns errors if the modulus is negative and will handle negative exponents + -- mp_prime_is_prime will now return true if the input is one of the primes in the prime table + -- Damian M Gryski (dgryski@uwaterloo.ca) found a index out of bounds error in the + mp_fast_s_mp_mul_high_digs function which didn't come up before. (fixed) + -- Refactored the DR reduction code so there is only one function per file. + -- Fixed bug in the mp_mul() which would erroneously avoid the faster multiplier [comba] when it was + allowed. The bug would not cause the incorrect value to be produced just less efficient (fixed) + -- Fixed similar bug in the Montgomery reduction code. + -- Added tons of (mp_digit) casts so the 7/15/28/31 bit digit code will work flawlessly out of the box. + Also added limited support for 64-bit machines with a 60-bit digit. Both thanks to Tom Wu (tom@arcot.com) + -- Added new comments here and there, cleaned up some code [style stuff] + -- Fixed a lingering typo in mp_exptmod* that would set bitcnt to zero then one. Very silly stuff :-) + -- Fixed up mp_exptmod_fast so it would set "redux" to the comba Montgomery reduction if allowed. This + saves quite a few calls and if statements. + -- Added etc/mont.c a test of the Montgomery reduction [assuming all else works :-| ] + -- Fixed up etc/tune.c to use a wider test range [more appropriate] also added a x86 based addition which + uses RDTSC for high precision timing. + -- Updated demo/demo.c to remove MPI stuff [won't work anyways], made the tests run for 2 seconds each so its + not so insanely slow. Also made the output space delimited [and fixed up various errors] + -- Added logs directory, logs/graph.dem which will use gnuplot to make a series of PNG files + that go with the pre-made index.html. You have to build [via make timing] and run ltmtest first in the + root of the package. + -- Fixed a bug in mp_sub and mp_add where "-a - -a" or "-a + a" would produce -0 as the result [obviously invalid]. + -- Fixed a bug in mp_rshd. If the count == a.used it should zero/return [instead of shifting] + -- Fixed a "off-by-one" bug in mp_mul2d. The initial size check on alloc would be off by one if the residue + shifting caused a carry. + -- Fixed a bug where s_mp_mul_digs() would not call the Comba based routine if allowed. This made Barrett reduction + slower than it had to be. + +Mar 29th, 2003 +v0.16 -- Sped up mp_div by making normalization one shift call + -- Sped up mp_mul_2d/mp_div_2d by aliasing pointers :-) + -- Cleaned up mp_gcd to use the macros for odd/even detection + -- Added comments here and there, mostly there but occasionally here too. + +Mar 22nd, 2003 +v0.15 -- Added series of prime testing routines to lib + -- Fixed up etc/tune.c + -- Added DR reduction algorithm + -- Beefed up the manual more. + -- Fixed up demo/demo.c so it doesn't have so many warnings and it does the full series of + tests + -- Added "pre-gen" directory which will hold a "gen.pl"'ed copy of the entire lib [done at + zipup time so its always the latest] + -- Added conditional casts for C++ users [boo!] + +Mar 15th, 2003 +v0.14 -- Tons of manual updates + -- cleaned up the directory + -- added MSVC makefiles + -- source changes [that I don't recall] + -- Fixed up the lshd/rshd code to use pointer aliasing + -- Fixed up the mul_2d and div_2d to not call rshd/lshd unless needed + -- Fixed up etc/tune.c a tad + -- fixed up demo/demo.c to output comma-delimited results of timing + also fixed up timing demo to use a finer granularity for various functions + -- fixed up demo/demo.c testing to pause during testing so my Duron won't catch on fire + [stays around 31-35C during testing :-)] + +Feb 13th, 2003 +v0.13 -- tons of minor speed-ups in low level add, sub, mul_2 and div_2 which propagate + to other functions like mp_invmod, mp_div, etc... + -- Sped up mp_exptmod_fast by using new code to find R mod m [e.g. B^n mod m] + -- minor fixes + +Jan 17th, 2003 +v0.12 -- re-wrote the majority of the makefile so its more portable and will + install via "make install" on most *nix platforms + -- Re-packaged all the source as separate files. Means the library a single + file package any more. Instead of just adding "bn.c" you have to add + libtommath.a + -- Renamed "bn.h" to "tommath.h" + -- Changes to the manual to reflect all of this + -- Used GNU Indent to clean up the source + +Jan 15th, 2003 +v0.11 -- More subtle fixes + -- Moved to gentoo linux [hurrah!] so made *nix specific fixes to the make process + -- Sped up the montgomery reduction code quite a bit + -- fixed up demo so when building timing for the x86 it assumes ELF format now + +Jan 9th, 2003 +v0.10 -- Pekka Riikonen suggested fixes to the radix conversion code. + -- Added baseline montgomery and comba montgomery reductions, sped up exptmods + [to a point, see bn.h for MONTGOMERY_EXPT_CUTOFF] + +Jan 6th, 2003 +v0.09 -- Updated the manual to reflect recent changes. :-) + -- Added Jacobi function (mp_jacobi) to supplement the number theory side of the lib + -- Added a Mersenne prime finder demo in ./etc/mersenne.c + +Jan 2nd, 2003 +v0.08 -- Sped up the multipliers by moving the inner loop variables into a smaller scope + -- Corrected a bunch of small "warnings" + -- Added more comments + -- Made "mtest" be able to use /dev/random, /dev/urandom or stdin for RNG data + -- Corrected some bugs where error messages were potentially ignored + -- add etc/pprime.c program which makes numbers which are provably prime. + +Jan 1st, 2003 +v0.07 -- Removed a lot of heap operations from core functions to speed them up + -- Added a root finding function [and mp_sqrt macro like from MPI] + -- Added more to manual + +Dec 31st, 2002 +v0.06 -- Sped up the s_mp_add, s_mp_sub which inturn sped up mp_invmod, mp_exptmod, etc... + -- Cleaned up the header a bit more + +Dec 30th, 2002 +v0.05 -- Builds with MSVC out of the box + -- Fixed a bug in mp_invmod w.r.t. even moduli + -- Made mp_toradix and mp_read_radix use char instead of unsigned char arrays + -- Fixed up exptmod to use fewer multiplications + -- Fixed up mp_init_size to use only one heap operation + -- Note there is a slight "off-by-one" bug in the library somewhere + without the padding (see the source for comment) the library + crashes in libtomcrypt. Anyways a reasonable workaround is to pad the + numbers which will always correct it since as the numbers grow the padding + will still be beyond the end of the number + -- Added more to the manual + +Dec 29th, 2002 +v0.04 -- Fixed a memory leak in mp_to_unsigned_bin + -- optimized invmod code + -- Fixed bug in mp_div + -- use exchange instead of copy for results + -- added a bit more to the manual + +Dec 27th, 2002 +v0.03 -- Sped up s_mp_mul_high_digs by not computing the carries of the lower digits + -- Fixed a bug where mp_set_int wouldn't zero the value first and set the used member. + -- fixed a bug in s_mp_mul_high_digs where the limit placed on the result digits was not calculated properly + -- fixed bugs in add/sub/mul/sqr_mod functions where if the modulus and dest were the same it wouldn't work + -- fixed a bug in mp_mod and mp_mod_d concerning negative inputs + -- mp_mul_d didn't preserve sign + -- Many many many many fixes + -- Works in LibTomCrypt now :-) + -- Added iterations to the timing demos... more accurate. + -- Tom needs a job. + +Dec 26th, 2002 +v0.02 -- Fixed a few "slips" in the manual. This is "LibTomMath" afterall :-) + -- Added mp_cmp_mag, mp_neg, mp_abs and mp_radix_size that were missing. + -- Sped up the fast [comba] multipliers more [yahoo!] + +Dec 25th,2002 +v0.01 -- Initial release. Gimme a break. + -- Todo list, + add details to manual [e.g. algorithms] + more comments in code + example programs diff --git a/deps/libtommath/demo/CMakeLists.txt b/deps/libtommath/demo/CMakeLists.txt new file mode 100644 index 0000000..c44b7c2 --- /dev/null +++ b/deps/libtommath/demo/CMakeLists.txt @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: Unlicense +# +# LibTomMath, a free open source portable number theoretic multiple-precision +# integer (MPI) library written entirely in C. +# + +cmake_minimum_required(VERSION 3.10) + +set(LTM_TEST test-ltm) + +# This file can be included from the top level or used stand-alone +if(PROJECT_NAME) + set(LIBRARY_NAME ${PROJECT_NAME}) +else() + # Define an independent project and all the necessary stuff around + project(${LTM_TEST} + LANGUAGES C) + set(LIBRARY_NAME libtommath) + find_package(${LIBRARY_NAME}) + include(CTest) + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Release") + endif() +endif() + +#----------------------------------------------------------------------------- +# Compose CFLAGS etc. +#----------------------------------------------------------------------------- + +if(NOT MSVC) + set(CMAKE_C_FLAGS_DEBUG "-g3 -O1") +endif() + +#----------------------------------------------------------------------------- +# demo target +#----------------------------------------------------------------------------- + +add_executable(${LTM_TEST} + ${CMAKE_CURRENT_SOURCE_DIR}/shared.c + ${CMAKE_CURRENT_SOURCE_DIR}/test.c +) + +target_include_directories(${LTM_TEST} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + $<$:${CMAKE_CURRENT_SOURCE_DIR}/..> +) + +target_link_libraries(${LTM_TEST} PRIVATE + ${LIBRARY_NAME} +) + +target_compile_options(${LTM_TEST} PRIVATE + $<$,SHARED_LIBRARY>:-DLTM_TEST_DYNAMIC> + ${LTM_C_FLAGS} +) +target_link_options(${LTM_TEST} BEFORE PUBLIC + ${LTM_LD_FLAGS} +) + +#----------------------------------------------------------------------------- +# CTest +#----------------------------------------------------------------------------- +add_test(NAME ${LTM_TEST} COMMAND ${LTM_TEST}) + +find_program(MEMORYCHECK_COMMAND valgrind) +set(MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full") diff --git a/deps/libtommath/demo/mtest_opponent.c b/deps/libtommath/demo/mtest_opponent.c new file mode 100644 index 0000000..abd7c16 --- /dev/null +++ b/deps/libtommath/demo/mtest_opponent.c @@ -0,0 +1,441 @@ +#include "shared.h" + +#ifdef LTM_MTEST_REAL_RAND +#define LTM_MTEST_RAND_SEED time(NULL) +#else +#define LTM_MTEST_RAND_SEED 23 +#endif + +#define DRAW(a) do{ ndraw(&(a), #a); }while(0) + +/* + Get tokens. It is just a very(!) simple fgets(3) that does not keep line endings. + + Implementation follows along "man 3 fgets", some of which is quoted. + */ +static int s_mp_get_token(char *s, int size, FILE *stream) +{ + char *s_bar = s; + int c; + bool eol_hit = false; + + /* "fgets [...] reads in at most one less than size characters from stream" */ + while (--size) { + /* "Reading stops after an EOF or a newline." We stop only for EOF here */ + if ((c = fgetc(stream)) == EOF) { + /* "Returns [...] NULL on error or when end of file occurs while no characters have been read" */ + if ((s_bar == s) || (ferror(stream) != 0)) { + return -1; + } + break; + } + /* Ignore line-breaks but keep reading to get them out of the stream-buffer */ + if ((c == '\n') || (c == '\r')) { + eol_hit = true; + continue; + } + /* Stop reading after linebreak */ + if (eol_hit) { + /* We already read the character after the linebreak, put it back */ + ungetc(c, stream); + break; + } + *s_bar++ = c; + } + if (size == 0) return -2; + /* "A terminating null byte ('\0') is stored after the last character in the buffer" */ + *s_bar = '\0'; + return 0; +} + +#define TMP_(r,l) r ## _ ## l +#define TMP(r,l) TMP_(r,l) + +#define GET_TOKEN(str, stream) \ + do { \ + int TMP(ret,__LINE__) = s_mp_get_token((str), sizeof(str), (stream)); \ + if (TMP(ret,__LINE__) < 0) { fprintf(stderr, "\n%d: s_mp_get_token failed with error %d\n", __LINE__, TMP(ret,__LINE__)); goto LBL_ERR; } \ + } while(0) + +static int mtest_opponent(void) +{ + char cmd[4096]; + char buf[4096]; + int ix; + unsigned rr; + mp_int a, b, c, d, e, f; + unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, + gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n; + + srand(LTM_MTEST_RAND_SEED); + + if (mp_init_multi(&a, &b, &c, &d, &e, &f, NULL)!= MP_OKAY) + return EXIT_FAILURE; + + div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n = + sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = add_d_n = sub_d_n = 0; + +#ifndef MP_FIXED_CUTOFFS + /* force KARA and TOOM to enable despite cutoffs */ + MP_SQR_KARATSUBA_CUTOFF = MP_MUL_KARATSUBA_CUTOFF = 8; + MP_SQR_TOOM_CUTOFF = MP_MUL_TOOM_CUTOFF = 16; +#endif + + for (;;) { + /* randomly clear and re-init one variable, this has the effect of trimming the alloc space */ + switch (abs(rand()) % 7) { + case 0: + mp_clear(&a); + DO(mp_init(&a)); + break; + case 1: + mp_clear(&b); + DO(mp_init(&b)); + break; + case 2: + mp_clear(&c); + DO(mp_init(&c)); + break; + case 3: + mp_clear(&d); + DO(mp_init(&d)); + break; + case 4: + mp_clear(&e); + DO(mp_init(&e)); + break; + case 5: + mp_clear(&f); + DO(mp_init(&f)); + break; + case 6: + break; /* don't clear any */ + } + + + printf("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ", + add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, + expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n); + GET_TOKEN(cmd, stdin); + printf("%-6s ]\r", cmd); + fflush(stdout); + if (strcmp(cmd, "mul2d") == 0) { + ++mul2d_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + sscanf(buf, "%u", &rr); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + + DO(mp_mul_2d(&a, (int)rr, &a)); + a.sign = b.sign; + if (mp_cmp(&a, &b) != MP_EQ) { + printf("mul2d failed, rr == %u\n", rr); + DRAW(a); + DRAW(b); + goto LBL_ERR; + } + } else if (strcmp(cmd, "div2d") == 0) { + ++div2d_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + sscanf(buf, "%u", &rr); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + + DO(mp_div_2d(&a, (int)rr, &a, &e)); + a.sign = b.sign; + if ((a.used == b.used) && (a.used == 0)) { + a.sign = b.sign = MP_ZPOS; + } + if (mp_cmp(&a, &b) != MP_EQ) { + printf("div2d failed, rr == %u\n", rr); + DRAW(a); + DRAW(b); + goto LBL_ERR; + } + } else if (strcmp(cmd, "add") == 0) { + ++add_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + DO(mp_copy(&a, &d)); + DO(mp_add(&d, &b, &d)); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("add %lu failure!\n", add_n); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + goto LBL_ERR; + } + + /* test the sign/unsigned storage functions */ + + rr = (unsigned)mp_sbin_size(&c); + DO(mp_to_sbin(&c, (uint8_t *) cmd, (size_t)rr, NULL)); + memset(cmd + rr, rand() & 0xFF, sizeof(cmd) - rr); + DO(mp_from_sbin(&d, (uint8_t *) cmd, (size_t)rr)); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("mp_signed_bin failure!\n"); + DRAW(c); + DRAW(d); + goto LBL_ERR; + } + + rr = (unsigned)mp_ubin_size(&c); + DO(mp_to_ubin(&c, (uint8_t *) cmd, (size_t)rr, NULL)); + memset(cmd + rr, rand() & 0xFF, sizeof(cmd) - rr); + DO(mp_from_ubin(&d, (uint8_t *) cmd, (size_t)rr)); + if (mp_cmp_mag(&c, &d) != MP_EQ) { + printf("mp_unsigned_bin failure!\n"); + DRAW(c); + DRAW(d); + goto LBL_ERR; + } + + } else if (strcmp(cmd, "sub") == 0) { + ++sub_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + DO(mp_copy(&a, &d)); + DO(mp_sub(&d, &b, &d)); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("sub %lu failure!\n", sub_n); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + goto LBL_ERR; + } + } else if (strcmp(cmd, "mul") == 0) { + ++mul_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + DO(mp_copy(&a, &d)); + DO(mp_mul(&d, &b, &d)); + if (mp_cmp(&c, &d) != MP_EQ) { + printf("mul %lu failure!\n", mul_n); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + goto LBL_ERR; + } + } else if (strcmp(cmd, "div") == 0) { + ++div_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&d, buf, 64)); + + DO(mp_div(&a, &b, &e, &f)); + if ((mp_cmp(&c, &e) != MP_EQ) || (mp_cmp(&d, &f) != MP_EQ)) { + printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e), + mp_cmp(&d, &f)); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + DRAW(e); + DRAW(f); + goto LBL_ERR; + } + + } else if (strcmp(cmd, "sqr") == 0) { + ++sqr_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + DO(mp_copy(&a, &c)); + DO(mp_sqr(&c, &c)); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("sqr %lu failure!\n", sqr_n); + DRAW(a); + DRAW(b); + DRAW(c); + goto LBL_ERR; + } + } else if (strcmp(cmd, "gcd") == 0) { + ++gcd_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + DO(mp_copy(&a, &d)); + DO(mp_gcd(&d, &b, &d)); + d.sign = c.sign; + if (mp_cmp(&c, &d) != MP_EQ) { + printf("gcd %lu failure!\n", gcd_n); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + goto LBL_ERR; + } + } else if (strcmp(cmd, "lcm") == 0) { + ++lcm_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + DO(mp_copy(&a, &d)); + DO(mp_lcm(&d, &b, &d)); + d.sign = c.sign; + if (mp_cmp(&c, &d) != MP_EQ) { + printf("lcm %lu failure!\n", lcm_n); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + goto LBL_ERR; + } + } else if (strcmp(cmd, "expt") == 0) { + ++expt_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&d, buf, 64)); + DO(mp_copy(&a, &e)); + DO(mp_exptmod(&e, &b, &c, &e)); + if (mp_cmp(&d, &e) != MP_EQ) { + printf("expt %lu failure!\n", expt_n); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + DRAW(e); + goto LBL_ERR; + } + } else if (strcmp(cmd, "invmod") == 0) { + ++inv_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&c, buf, 64)); + DO(mp_invmod(&a, &b, &d)); + DO(mp_mulmod(&d, &a, &b, &e)); + if (mp_cmp_d(&e, 1u) != MP_EQ) { + printf("inv [wrong value from MPI?!] failure\n"); + DRAW(a); + DRAW(b); + DRAW(c); + DRAW(d); + DRAW(e); + DO(mp_gcd(&a, &b, &e)); + DRAW(e); + goto LBL_ERR; + } + + } else if (strcmp(cmd, "div2") == 0) { + ++div2_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + DO(mp_div_2(&a, &c)); + if (mp_cmp(&c, &b) != MP_EQ) { + printf("div_2 %lu failure\n", div2_n); + DRAW(a); + DRAW(b); + DRAW(c); + goto LBL_ERR; + } + } else if (strcmp(cmd, "mul2") == 0) { + ++mul2_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + DO(mp_mul_2(&a, &c)); + if (mp_cmp(&c, &b) != MP_EQ) { + printf("mul_2 %lu failure\n", mul2_n); + DRAW(a); + DRAW(b); + DRAW(c); + goto LBL_ERR; + } + } else if (strcmp(cmd, "add_d") == 0) { + ++add_d_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + sscanf(buf, "%d", &ix); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + DO(mp_add_d(&a, (mp_digit)ix, &c)); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("add_d %lu failure\n", add_d_n); + DRAW(a); + DRAW(b); + DRAW(c); + printf("d == %d\n", ix); + goto LBL_ERR; + } + } else if (strcmp(cmd, "sub_d") == 0) { + ++sub_d_n; + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&a, buf, 64)); + GET_TOKEN(buf, stdin); + sscanf(buf, "%d", &ix); + GET_TOKEN(buf, stdin); + DO(mp_read_radix(&b, buf, 64)); + DO(mp_sub_d(&a, (mp_digit)ix, &c)); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("sub_d %lu failure\n", sub_d_n); + DRAW(a); + DRAW(b); + DRAW(c); + printf("d == %d\n", ix); + goto LBL_ERR; + } + } else if (strcmp(cmd, "exit") == 0) { + printf("\nokay, exiting now\n"); + break; + } + } + + mp_clear_multi(&a, &b, &c, &d, &e, &f, NULL); + printf("\n"); + return 0; + +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, &e, &f, NULL); + printf("\n"); + return EXIT_FAILURE; +} + +int main(void) +{ + print_header(); + + return mtest_opponent(); +} diff --git a/deps/libtommath/demo/s_mp_rand_jenkins.c b/deps/libtommath/demo/s_mp_rand_jenkins.c new file mode 100644 index 0000000..9c77142 --- /dev/null +++ b/deps/libtommath/demo/s_mp_rand_jenkins.c @@ -0,0 +1,55 @@ +#include "tommath_private.h" +#ifdef S_MP_RAND_JENKINS_C +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Bob Jenkins' http://burtleburtle.net/bob/rand/smallprng.html */ +/* Chosen for speed and a good "mix" */ + +/* TODO: jenkins prng is not thread safe as of now */ + +typedef struct { + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +} ranctx; + +static ranctx jenkins_x; + +#define rot(x,k) (((x)<<(k))|((x)>>(64-(k)))) +static uint64_t s_rand_jenkins_val(void) +{ + uint64_t e = jenkins_x.a - rot(jenkins_x.b, 7); + jenkins_x.a = jenkins_x.b ^ rot(jenkins_x.c, 13); + jenkins_x.b = jenkins_x.c + rot(jenkins_x.d, 37); + jenkins_x.c = jenkins_x.d + e; + jenkins_x.d = e + jenkins_x.a; + return jenkins_x.d; +} + +static void s_mp_rand_jenkins_init(uint64_t seed) +{ + int i; + jenkins_x.a = 0xF1EA5EEDuL; + jenkins_x.b = jenkins_x.c = jenkins_x.d = seed; + for (i = 0; i < 20; ++i) { + (void)s_rand_jenkins_val(); + } +} + +static mp_err s_mp_rand_jenkins(void *p, size_t n) +{ + char *q = (char *)p; + while (n > 0u) { + int i; + uint64_t x = s_rand_jenkins_val(); + for (i = 0; (i < 8) && (n > 0u); ++i, --n) { + *q++ = (char)(x & 0xFFu); + x >>= 8; + } + } + return MP_OKAY; +} + +#endif diff --git a/deps/libtommath/demo/shared.c b/deps/libtommath/demo/shared.c new file mode 100644 index 0000000..536a1de --- /dev/null +++ b/deps/libtommath/demo/shared.c @@ -0,0 +1,49 @@ +#include "shared.h" + +void ndraw(const mp_int *a, const char *name) +{ + char *buf; + size_t size = 0; + mp_err err; + + if ((err = mp_radix_size_overestimate(a, 10, &size)) != MP_OKAY) { + fprintf(stderr, "\nndraw: mp_radix_size_overestimate(a, 10, %zu) failed - %s\n", size, mp_error_to_string(err)); + exit(EXIT_FAILURE); + } + buf = (char *)malloc(size); + if (buf == NULL) { + fprintf(stderr, "\nndraw: malloc(%zu) failed\n", size); + exit(EXIT_FAILURE); + } + + printf("%s: ", name); + if ((err = mp_to_decimal(a, buf, size)) != MP_OKAY) { + fprintf(stderr, "\nndraw: mp_to_decimal(a, buf, %zu) failed - %s\n", size, mp_error_to_string(err)); + exit(EXIT_FAILURE); + } + printf("%s\n", buf); + if ((err = mp_to_hex(a, buf, size)) != MP_OKAY) { + fprintf(stderr, "\nndraw: mp_to_hex(a, buf, %zu) failed - %s\n", size, mp_error_to_string(err)); + exit(EXIT_FAILURE); + } + printf("0x%s\n", buf); + + free(buf); +} + +void print_header(void) +{ +#ifdef MP_16BIT + printf("Digit size 16 Bit \n"); +#endif +#ifdef MP_32BIT + printf("Digit size 32 Bit \n"); +#endif +#ifdef MP_64BIT + printf("Digit size 64 Bit \n"); +#endif + printf("Size of mp_digit: %u\n", (unsigned int)sizeof(mp_digit)); + printf("Size of mp_word: %u\n", (unsigned int)sizeof(mp_word)); + printf("MP_DIGIT_BIT: %d\n", MP_DIGIT_BIT); + printf("MP_DEFAULT_DIGIT_COUNT: %d\n", MP_DEFAULT_DIGIT_COUNT); +} diff --git a/deps/libtommath/demo/shared.h b/deps/libtommath/demo/shared.h new file mode 100644 index 0000000..2a1ab3c --- /dev/null +++ b/deps/libtommath/demo/shared.h @@ -0,0 +1,27 @@ +#include +#include +#include + +/* + * Configuration + */ +#ifndef LTM_DEMO_TEST_REDUCE_2K_L +/* This test takes a moment so we disable it by default, but it can be: + * 0 to disable testing + * 1 to make the test with P = 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF + * 2 to make the test with P = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F + */ +#define LTM_DEMO_TEST_REDUCE_2K_L 0 +#endif + +#include "tommath_private.h" + + +#define EXPECT(a) do { if (!(a)) { fprintf(stderr, "%s, line %d: EXPECT(%s) failed\n", __func__, __LINE__, #a); goto LBL_ERR; } } while(0) +#define DO_WHAT(a, what) do { mp_err err; if ((err = (a)) != MP_OKAY) { fprintf(stderr, "%s, line %d: DO(%s) failed: %s\n", __func__, __LINE__, #a, mp_error_to_string(err)); what; } } while(0) +#define DO(a) DO_WHAT(a, goto LBL_ERR) +#define DOR(a) DO_WHAT(a, return EXIT_FAILURE) + + +extern void ndraw(const mp_int* a, const char* name); +extern void print_header(void); diff --git a/deps/libtommath/demo/test.c b/deps/libtommath/demo/test.c new file mode 100644 index 0000000..f868536 --- /dev/null +++ b/deps/libtommath/demo/test.c @@ -0,0 +1,2553 @@ +#include +#include "shared.h" + +#define S_MP_RAND_JENKINS_C +#include "s_mp_rand_jenkins.c" + +static long rand_long(void) +{ + long x; + if (s_mp_rand_jenkins(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static int rand_int(void) +{ + int x; + if (s_mp_rand_jenkins(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static int32_t rand_int32(void) +{ + int32_t x; + if (s_mp_rand_jenkins(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static int64_t rand_int64(void) +{ + int64_t x; + if (s_mp_rand_jenkins(&x, sizeof(x)) != MP_OKAY) { + fprintf(stderr, "s_mp_rand_source failed\n"); + exit(EXIT_FAILURE); + } + return x; +} + +static uint32_t uabs32(int32_t x) +{ + return (x > 0) ? (uint32_t)x : -(uint32_t)x; +} + +static uint64_t uabs64(int64_t x) +{ + return (x > 0) ? (uint64_t)x : -(uint64_t)x; +} + +/* This function prototype is needed + * to test dead code elimination + * which is used for feature detection. + * + * If the feature detection does not + * work as desired we will get a linker error. + */ +void does_not_exist(void); + +static int test_feature_detection(void) +{ +#define TEST_FEATURE1_C + if (!MP_HAS(TEST_FEATURE1)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define TEST_FEATURE2_C 1 + if (MP_HAS(TEST_FEATURE2)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define TEST_FEATURE3_C 0 + if (MP_HAS(TEST_FEATURE3)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define TEST_FEATURE4_C something + if (MP_HAS(TEST_FEATURE4)) { + does_not_exist(); + return EXIT_FAILURE; + } + + if (MP_HAS(TEST_FEATURE5)) { + does_not_exist(); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +static int test_trivial_stuff(void) +{ + mp_int a, b, c, d; + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + EXPECT(mp_error_to_string(MP_OKAY) != NULL); + + /* a: 0->5 */ + mp_set(&a, 5u); + /* a: 5-> b: -5 */ + DO(mp_neg(&a, &b)); + EXPECT(mp_cmp(&a, &b) == MP_GT); + EXPECT(mp_cmp(&b, &a) == MP_LT); + EXPECT(mp_isneg(&b)); + /* a: 5-> a: -5 */ + DO(mp_neg(&a, &a)); + EXPECT(mp_cmp(&b, &a) == MP_EQ); + EXPECT(mp_isneg(&a)); + /* a: -5-> b: 5 */ + DO(mp_abs(&a, &b)); + EXPECT(!mp_isneg(&b)); + /* a: -5-> b: -4 */ + DO(mp_add_d(&a, 1u, &b)); + EXPECT(mp_isneg(&b)); + EXPECT(mp_get_i32(&b) == -4); + EXPECT(mp_get_u32(&b) == (uint32_t)-4); + EXPECT(mp_get_mag_u32(&b) == 4); + /* a: -5-> b: 1 */ + DO(mp_add_d(&a, 6u, &b)); + EXPECT(mp_get_u32(&b) == 1); + /* a: -5-> a: 1 */ + DO(mp_add_d(&a, 6u, &a)); + EXPECT(mp_get_u32(&a) == 1); + mp_zero(&a); + /* a: 0-> a: 6 */ + DO(mp_add_d(&a, 6u, &a)); + EXPECT(mp_get_u32(&a) == 6); + + mp_set(&a, 42u); + mp_set(&b, 1u); + DO(mp_neg(&b, &b)); + mp_set(&c, 1u); + DO(mp_exptmod(&a, &b, &c, &d)); + + mp_set(&c, 7u); + /* same here */ + EXPECT(mp_exptmod(&a, &b, &c, &d) != MP_OKAY); + + EXPECT(mp_iseven(&a) != mp_isodd(&a)); + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_mp_hash(void) +{ + mp_int a; + mp_hval hash; + int i; + int len = 5; + + const char *input[] = { + "0", + "///////////////////////////////////////////////////////////////////", + "4n9cbk886QtLQmofprid3l2Q0GD8Yv979Lh8BdZkFE8g2pDUUSMBET/+M/YFyVZ3mBp", + "5NlgzHhmIX05O5YoW5yW5reAlVNtRAlIcN2dfoATnNdc1Cw5lHZUTwNthmK6/ZLKfY6", + "3gweiHDX+ji5utraSe46IJX+uuh7iggs63xIpMP5MriU4Np+LpHI5are8RzS9pKh9xP" + }; + const mp_hval hvals[] = { +#if (MP_DIGIT_BIT == 15) + 0x50c5d1f, + 0x51b3ba04, + 0xf83febd7, + 0x2dc8624c, + 0xf5c2996b +#elif (MP_DIGIT_BIT == 60) + 0xaf63bd4c8601b7df, + 0xdb090f8a5cd75210, + 0xabae35c7872c107d, + 0xfec74888bcef5fcd, + 0x27ba96030abceda5 +#elif (MP_DIGIT_BIT == 31) + 0xaf63bd4c8601b7df, + 0xec1be1c4749a7b86, + 0x138ac13639116f2e, + 0xdd317b32ac9dd90f, + 0x6f87eaac03140738 +#else + 0xaf63bd4c8601b7df, + 0x7e868fbf541faf44, + 0x420cca3a4cb623bb, + 0x16636d996304ee7f, + 0x33afc9f1b274fa67 +#endif + }; + + DOR(mp_init(&a)); + for (i = 0; i < len; ++i) { + DO(mp_read_radix(&a, input[i], 64)); + DO(mp_hash(&a, &hash)); + EXPECT(hash == hvals[i]); + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int check_get_set_i32(mp_int *a, int32_t b) +{ + mp_clear(a); + DO(mp_shrink(a)); + + mp_set_i32(a, b); + DO(mp_shrink(a)); + EXPECT(mp_get_i32(a) == b); + EXPECT(mp_get_u32(a) == (uint32_t)b); + EXPECT(mp_get_mag_u32(a) == uabs32(b)); + + mp_set_u32(a, (uint32_t)b); + EXPECT(mp_get_u32(a) == (uint32_t)b); + EXPECT(mp_get_i32(a) == (int32_t)(uint32_t)b); + + return EXIT_SUCCESS; +LBL_ERR: + return EXIT_FAILURE; +} + +static int test_mp_get_set_i32(void) +{ + int i; + mp_int a; + + DOR(mp_init(&a)); + + check_get_set_i32(&a, 0); + check_get_set_i32(&a, -1); + check_get_set_i32(&a, 1); + check_get_set_i32(&a, INT32_MIN); + check_get_set_i32(&a, INT32_MAX); + + for (i = 0; i < 1000; ++i) { + int32_t b = rand_int32(); + EXPECT(check_get_set_i32(&a, b) == EXIT_SUCCESS); + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int check_get_set_i64(mp_int *a, int64_t b) +{ + mp_clear(a); + if (mp_shrink(a) != MP_OKAY) return EXIT_FAILURE; + + mp_set_i64(a, b); + if (mp_shrink(a) != MP_OKAY) return EXIT_FAILURE; + if (mp_get_i64(a) != b) return EXIT_FAILURE; + if (mp_get_u64(a) != (uint64_t)b) return EXIT_FAILURE; + if (mp_get_mag_u64(a) != uabs64(b)) return EXIT_FAILURE; + + mp_set_u64(a, (uint64_t)b); + if (mp_get_u64(a) != (uint64_t)b) return EXIT_FAILURE; + if (mp_get_i64(a) != (int64_t)(uint64_t)b) return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static int test_mp_get_set_i64(void) +{ + int i; + mp_int a; + + DOR(mp_init(&a)); + + check_get_set_i64(&a, 0); + check_get_set_i64(&a, -1); + check_get_set_i64(&a, 1); + check_get_set_i64(&a, INT64_MIN); + check_get_set_i64(&a, INT64_MAX); + + for (i = 0; i < 1000; ++i) { + int64_t b = rand_int64(); + if (check_get_set_i64(&a, b) != EXIT_SUCCESS) { + goto LBL_ERR; + } + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int test_mp_fread_fwrite(void) +{ + mp_int a, b; + FILE *tmp = NULL; + DOR(mp_init_multi(&a, &b, NULL)); + + mp_set_ul(&a, 123456uL); + tmp = tmpfile(); + DO(mp_fwrite(&a, 64, tmp)); + rewind(tmp); + DO(mp_fread(&b, 64, tmp)); + EXPECT(mp_get_u32(&b) == 123456uL); + fclose(tmp); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + if (tmp != NULL) fclose(tmp); + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static mp_err very_random_source(void *out, size_t size) +{ + memset(out, 0xff, size); + return MP_OKAY; +} + +static int test_mp_rand(void) +{ + mp_int a, b; + int n; + mp_err e = MP_OKAY; + DOR(mp_init_multi(&a, &b, NULL)); + mp_rand_source(very_random_source); + for (n = 1; n < 1024; ++n) { + DO(mp_rand(&a, n)); + DO(mp_incr(&a)); + DO(mp_div_2d(&a, n * MP_DIGIT_BIT, &b, NULL)); + if (mp_cmp_d(&b, 1u) != MP_EQ) { + ndraw(&a, "mp_rand() a"); + ndraw(&b, "mp_rand() b"); + e = MP_ERR; + break; + } + } +LBL_ERR: + mp_rand_source(s_mp_rand_jenkins); + mp_clear_multi(&a, &b, NULL); + return (e == MP_OKAY) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int test_mp_kronecker(void) +{ + struct mp_kronecker_st { + long n; + int c[21]; + }; + static struct mp_kronecker_st kronecker[] = { + /*-10, -9, -8, -7,-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10*/ + { -10, { 0, -1, 0, -1, 0, 0, 0, 1, 0, -1, 0, 1, 0, -1, 0, 0, 0, 1, 0, 1, 0 } }, + { -9, { -1, 0, -1, 1, 0, -1, -1, 0, -1, -1, 0, 1, 1, 0, 1, 1, 0, -1, 1, 0, 1 } }, + { -8, { 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0 } }, + { -7, { 1, -1, -1, 0, 1, 1, -1, 1, -1, -1, 0, 1, 1, -1, 1, -1, -1, 0, 1, 1, -1 } }, + { -6, { 0, 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0 } }, + { -5, { 0, -1, 1, -1, 1, 0, -1, -1, 1, -1, 0, 1, -1, 1, 1, 0, -1, 1, -1, 1, 0 } }, + { -4, { 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0, -1, 0, 1, 0 } }, + { -3, { -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1 } }, + { -2, { 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0 } }, + { -1, { -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, 1 } }, + { 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 1, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }, + { 2, { 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0 } }, + { 3, { 1, 0, -1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, -1, 0, -1, -1, 0, 1 } }, + { 4, { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 } }, + { 5, { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1, 0, 1, -1, -1, 1, 0, 1, -1, -1, 1, 0 } }, + { 6, { 0, 0, 0, -1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, -1, 0, 0, 0 } }, + { 7, { -1, 1, 1, 0, 1, -1, 1, 1, 1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1, 1, -1 } }, + { 8, { 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0 } }, + { 9, { 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 } }, + { 10, { 0, 1, 0, -1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0 } } + }; + + long k, m; + int i, cnt; + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + + mp_set_ul(&a, 0uL); + mp_set_ul(&b, 1uL); + DO(mp_kronecker(&a, &b, &i)); + EXPECT(i == 1); + for (cnt = 0; cnt < (int)(sizeof(kronecker)/sizeof(kronecker[0])); ++cnt) { + k = kronecker[cnt].n; + mp_set_l(&a, k); + /* only test positive values of a */ + for (m = -10; m <= 10; m++) { + mp_set_l(&b, m); + DO(mp_kronecker(&a, &b, &i)); + EXPECT(i == kronecker[cnt].c[m + 10]); + } + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_complement(void) +{ + int i; + + mp_int a, b, c; + DOR(mp_init_multi(&a, &b, &c, NULL)); + + for (i = 0; i < 1000; ++i) { + long l = rand_long(); + mp_set_l(&a, l); + DO(mp_complement(&a, &b)); + + l = ~l; + mp_set_l(&c, l); + + EXPECT(mp_cmp(&b, &c) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_signed_rsh(void) +{ + int i; + + mp_int a, b, d; + DOR(mp_init_multi(&a, &b, &d, NULL)); + + for (i = 0; i < 1000; ++i) { + long l; + int em; + + l = rand_long(); + mp_set_l(&a, l); + + em = abs(rand_int()) % 32; + + mp_set_l(&d, l >> em); + + DO(mp_signed_rsh(&a, em, &b)); + EXPECT(mp_cmp(&b, &d) == MP_EQ); + } + + mp_clear_multi(&a, &b, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &d, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_xor(void) +{ + int i; + + mp_int a, b, c, d; + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + + for (i = 0; i < 1000; ++i) { + long l, em; + + l = rand_long(); + mp_set_l(&a,l); + + em = rand_long(); + mp_set_l(&b, em); + + mp_set_l(&d, l ^ em); + + DO(mp_xor(&a, &b, &c)); + EXPECT(mp_cmp(&c, &d) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_or(void) +{ + int i; + + mp_int a, b, c, d; + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + + for (i = 0; i < 1000; ++i) { + long l, em; + + l = rand_long(); + mp_set_l(&a, l); + + em = rand_long(); + mp_set_l(&b, em); + + mp_set_l(&d, l | em); + + DO(mp_or(&a, &b, &c)); + EXPECT(mp_cmp(&c, &d) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_mp_and(void) +{ + int i; + + mp_int a, b, c, d; + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + + for (i = 0; i < 1000; ++i) { + long l, em; + + l = rand_long(); + mp_set_l(&a, l); + + em = rand_long(); + mp_set_l(&b, em); + + mp_set_l(&d, l & em); + + DO(mp_and(&a, &b, &c)); + EXPECT(mp_cmp(&c, &d) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_mp_invmod(void) +{ + mp_int a, b, c, d; + int i, j, k; + int e; + + int results[21][21] = + /* Table generated with Pari/GP + + for(i=-10,10, + k=0; + d=0; + printf(" {"); + for(j=-10,10, + iferr( + printf(lift(Mod(1/i, j)) ", "), + k, + printf("-1, ")) + ); + print("},") + ) + + Changes to the output: replaced j < 1 with -1 for now and added the result of 0^(-1) mod (1) + + j = -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 */ + + { + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, 2, -1, 8, -1 }, /* i = -10 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 3, 1, -1, 3, 7, -1, 1 }, /* -9 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 3, -1, 6, -1, 1, -1 }, /* -8 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 1, 2, 5, -1, 1, 5, 7 }, /* -7 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, 1, -1, -1, -1 }, /* -6 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 3, -1, 1, 4, 3, 7, -1 }, /* -5 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, 1, -1, 5, -1, 2, -1 }, /* -4 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 3, -1, 2, 5, -1, 3 }, /* -3 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 2, -1, 3, -1, 4, -1 }, /* -2 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* -1 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* 0 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* 1 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 2, -1, 3, -1, 4, -1, 5, -1 }, /* 2 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 3, 2, -1, 5, 3, -1, 7 }, /* 3 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, 4, -1, 2, -1, 7, -1 }, /* 4 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 1, -1, 5, 3, 5, 2, -1 }, /* 5 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, -1, 6, -1, -1, -1 }, /* 6 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 1, 3, 3, 1, -1, 7, 4, 3 }, /* 7 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 2, -1, 2, -1, 1, -1, 8, -1 }, /* 8 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 1, 4, -1, 4, 1, -1, 9 }, /* 9 */ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, -1, -1, -1, 5, -1, 1, -1 } /* 10 */ + }; + + + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + + /* mp_invmod corner-case of https://github.com/libtom/libtommath/issues/118 */ + { + const char *a_ = "47182BB8DF0FFE9F61B1F269BACC066B48BA145D35137D426328DC3F88A5EA44"; + const char *b_ = "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF"; + const char *should_ = "0521A82E10376F8E4FDEF9A32A427AC2A0FFF686E00290D39E3E4B5522409596"; + + DO(mp_read_radix(&a, a_, 16)); + DO(mp_read_radix(&b, b_, 16)); + DO(mp_read_radix(&c, should_, 16)); + DO(mp_invmod(&a, &b, &d)); + EXPECT(mp_cmp(&c, &d) == MP_EQ); + } + + /* Some small general tests https://github.com/libtom/libtommath/issues/534 */ + for (i = -10; i < 11; i++) { + for (j = -10; j < 11; j++) { + mp_set_i32(&a, i); + mp_set_i32(&b, j); + e = mp_invmod(&a, &b, &c); + if (e != MP_OKAY) { + if (results[i+10][j+10] != -1) { + printf("error = %s from ", mp_error_to_string(e)); + printf("error at i = %d, j =%d should be an error but gave ",i,j); + e = mp_fwrite(&c,10,stdout); + printf("\n"); + goto LBL_ERR; + } + } else { + k = mp_get_i32(&c); + if (k != results[i+10][j+10]) { + printf("result at i = %d, j =%d is %d but should be %d \n", i,j,k,results[i+10][j+10]); + goto LBL_ERR; + } + } + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; + +} + +#if defined(MP_HAS_SET_DOUBLE) + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4723) /* potential divide by 0 */ +#endif +static int test_mp_set_double(void) +{ + int i; + double dbl_zero = 0.0; + + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + /* test mp_get_double/mp_set_double */ + EXPECT(mp_set_double(&a, +1.0/dbl_zero) == MP_VAL); + EXPECT(mp_set_double(&a, -1.0/dbl_zero) == MP_VAL); + EXPECT(mp_set_double(&a, +0.0/dbl_zero) == MP_VAL); + EXPECT(mp_set_double(&a, -0.0/dbl_zero) == MP_VAL); + + for (i = 0; i < 1000; ++i) { + int tmp = rand_int(); + double dbl = (double)tmp * rand_int() + 1; + DO(mp_set_double(&a, dbl)); + EXPECT(dbl == mp_get_double(&a)); + DO(mp_set_double(&a, -dbl)); + EXPECT(-dbl == mp_get_double(&a)); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif + +static int test_mp_get_u32(void) +{ + uint32_t t; + int i; + + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + + for (i = 0; i < 1000; ++i) { + t = (uint32_t)rand_long(); + mp_set_ul(&a, t); + EXPECT(t == mp_get_u32(&a)); + } + mp_set_ul(&a, 0uL); + EXPECT(mp_get_u32(&a) == 0); + mp_set_ul(&a, UINT32_MAX); + EXPECT(mp_get_u32(&a) == UINT32_MAX); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_get_ul(void) +{ + unsigned long s, t; + int i; + + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + + for (i = 0; i < ((int)MP_SIZEOF_BITS(unsigned long) - 1); ++i) { + t = (1UL << (i+1)) - 1; + if (!t) + t = ~0UL; + printf(" t = 0x%lx i = %d\r", t, i); + do { + mp_set_ul(&a, t); + s = mp_get_ul(&a); + EXPECT(s == t); + t <<= 1; + } while (t != 0uL); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_get_u64(void) +{ + uint64_t q, r; + int i; + + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + + for (i = 0; i < (int)(MP_SIZEOF_BITS(uint64_t) - 1); ++i) { + r = ((uint64_t)1 << (i+1)) - 1; + if (!r) + r = UINT64_MAX; + printf(" r = 0x%" PRIx64 " i = %d\r", r, i); + do { + mp_set_u64(&a, r); + q = mp_get_u64(&a); + EXPECT(q == r); + r <<= 1; + } while (r != 0u); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_sqrt(void) +{ + int i, n; + + mp_int a, b, c; + DOR(mp_init_multi(&a, &b, &c, NULL)); + + for (i = 0; i < 1000; ++i) { + printf("%6d\r", i); + fflush(stdout); + n = (rand_int() & 15) + 1; + DO(mp_rand(&a, n)); + DO(mp_sqrt(&a, &b)); + DO(mp_root_n(&a, 2, &c)); + EXPECT(mp_cmp_mag(&b, &c) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_is_square(void) +{ + int i, n; + + mp_int a, b; + bool res; + + DOR(mp_init_multi(&a, &b, NULL)); + + + /* Domain is {x \in \mathbb{Z} : x \le 0} */ + mp_set_l(&a, -1); + EXPECT(mp_is_square(&a, &res) == MP_VAL); + EXPECT(!res); + + /* Zero is a perfect square, too */ + mp_zero(&a); + DO(mp_is_square(&a, &res)); + EXPECT(res); + + for (i = 0; i < 1000; ++i) { + printf("%6d\r", i); + fflush(stdout); + + /* test mp_is_square false negatives */ + n = (rand_int() & 7) + 1; + DO(mp_rand(&a, n)); + DO(mp_sqr(&a, &a)); + DO(mp_is_square(&a, &res)); + EXPECT(res); + + /* test for false positives */ + DO(mp_add_d(&a, 1u, &a)); + DO(mp_is_square(&a, &res)); + EXPECT(!res); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_sqrtmod_prime(void) +{ + struct mp_sqrtmod_prime_st { + unsigned long p; + unsigned long n; + mp_digit r; + }; + + static struct mp_sqrtmod_prime_st sqrtmod_prime[] = { + { 5, 14, 3 }, /* 5 \cong 1 (mod 4) */ + { 7, 9, 4 }, /* 7 \cong 3 (mod 4) */ + { 113, 2, 62 } /* 113 \cong 1 (mod 4) */ + }; + int i; + + mp_int a, b, c; + DOR(mp_init_multi(&a, &b, &c, NULL)); + + /* r^2 = n (mod p) */ + for (i = 0; i < (int)(sizeof(sqrtmod_prime)/sizeof(sqrtmod_prime[0])); ++i) { + mp_set_ul(&a, sqrtmod_prime[i].p); + mp_set_ul(&b, sqrtmod_prime[i].n); + DO(mp_sqrtmod_prime(&b, &a, &c)); + EXPECT(mp_cmp_d(&c, sqrtmod_prime[i].r) == MP_EQ); + } + /* Check handling of wrong input (here: modulus is square and cong. 1 mod 4,24 ) */ + mp_set_ul(&a, 25); + mp_set_ul(&b, 2); + EXPECT(mp_sqrtmod_prime(&b, &a, &c) == MP_VAL); + /* b \cong 0 (mod a) */ + mp_set_ul(&a, 45); + mp_set_ul(&b, 3); + EXPECT(mp_sqrtmod_prime(&b, &a, &c) == MP_VAL); + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_prime_rand(void) +{ + int ix; + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + + /* test for size */ + for (ix = 10; ix < 128; ix++) { + printf("Testing (not safe-prime): %9d bits \n", ix); + fflush(stdout); + DO(mp_prime_rand(&a, 8, ix, (rand_int() & 1) ? 0 : MP_PRIME_2MSB_ON)); + EXPECT(mp_count_bits(&a) == ix); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_prime_is_prime(void) +{ + int ix; + mp_err e; + bool cnt, fu; + + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + + /* strong Miller-Rabin pseudoprime to the first 200 primes (F. Arnault) */ + printf("Testing mp_prime_is_prime() with Arnault's pseudoprime 803...901"); + DO(mp_read_radix(&a, + "91xLNF3roobhzgTzoFIG6P13ZqhOVYSN60Fa7Cj2jVR1g0k89zdahO9/kAiRprpfO1VAp1aBHucLFV/qLKLFb+zonV7R2Vxp1K13ClwUXStpV0oxTNQVjwybmFb5NBEHImZ6V7P6+udRJuH8VbMEnS0H8/pSqQrg82OoQQ2fPpAk6G1hkjqoCv5s/Yr", + 64)); + DO(mp_prime_is_prime(&a, mp_prime_rabin_miller_trials(mp_count_bits(&a)), &cnt)); + if (cnt) { + printf("Arnault's pseudoprime is not prime but mp_prime_is_prime says it is.\n"); + goto LBL_ERR; + } + /* About the same size as Arnault's pseudoprime */ + printf("\rTesting mp_prime_is_prime() with certified prime 2^1119 + 53 "); + mp_set(&a, 1u); + DO(mp_mul_2d(&a,1119,&a)); + DO(mp_add_d(&a, 53u, &a)); + e = mp_prime_is_prime(&a, mp_prime_rabin_miller_trials(mp_count_bits(&a)), &cnt); + /* small problem */ + if (e != MP_OKAY) { + printf("\nfailed with error: %s\n", mp_error_to_string(e)); + } + /* large problem */ + if (!cnt) { + printf("A certified prime is a prime but mp_prime_is_prime says it is not.\n"); + } + if ((e != MP_OKAY) || !cnt) { + printf("prime tested was: 0x"); + DO(mp_fwrite(&a,16,stdout)); + putchar('\n'); + goto LBL_ERR; + } + printf("\r "); + + for (ix = 16; ix < 128; ix++) { + printf("\rTesting ( safe-prime): %9d bits ", ix); + fflush(stdout); + DO(mp_prime_rand(&a, 8, ix, ((rand_int() & 1) ? 0 : MP_PRIME_2MSB_ON) | MP_PRIME_SAFE)); + EXPECT(mp_count_bits(&a) == ix); + /* let's see if it's really a safe prime */ + DO(mp_sub_d(&a, 1u, &b)); + DO(mp_div_2(&b, &b)); + DO(mp_prime_is_prime(&b, mp_prime_rabin_miller_trials(mp_count_bits(&b)), &cnt)); + /* large problem */ + EXPECT(cnt); + DO(mp_prime_frobenius_underwood(&b, &fu)); + EXPECT(fu); + if ((e != MP_OKAY) || !cnt) { + printf("prime tested was: 0x"); + DO(mp_fwrite(&a,16,stdout)); + putchar('\n'); + printf("sub tested was: 0x"); + DO(mp_fwrite(&b,16,stdout)); + putchar('\n'); + goto LBL_ERR; + } + + } + /* Check regarding problem #143 */ + DO(mp_read_radix(&a, + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", + 16)); + DO(mp_prime_strong_lucas_selfridge(&a, &cnt)); + /* large problem */ + EXPECT(cnt); + if ((e != MP_OKAY) || !cnt) { + printf("prime tested was: 0x"); + DO(mp_fwrite(&a,16,stdout)); + putchar('\n'); + goto LBL_ERR; + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} + + +static int test_mp_prime_next_prime(void) +{ + mp_int a, b, c; + + DOR(mp_init_multi(&a, &b, &c, NULL)); + + + /* edge cases */ + mp_set(&a, 0u); + DO(mp_prime_next_prime(&a, 5, false)); + if (mp_cmp_d(&a, 2u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 2 but was: "); + DO(mp_fwrite(&a,10,stdout)); + putchar('\n'); + goto LBL_ERR; + } + + mp_set(&a, 0u); + DO(mp_prime_next_prime(&a, 5, true)); + if (mp_cmp_d(&a, 3u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 3 but was: "); + DO(mp_fwrite(&a,10,stdout)); + putchar('\n'); + goto LBL_ERR; + } + + mp_set(&a, 2u); + DO(mp_prime_next_prime(&a, 5, false)); + if (mp_cmp_d(&a, 3u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 3 but was: "); + DO(mp_fwrite(&a,10,stdout)); + putchar('\n'); + goto LBL_ERR; + } + + mp_set(&a, 2u); + DO(mp_prime_next_prime(&a, 5, true)); + if (mp_cmp_d(&a, 3u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 3 but was: "); + DO(mp_fwrite(&a,10,stdout)); + putchar('\n'); + goto LBL_ERR; + } + mp_set(&a, 8u); + DO(mp_prime_next_prime(&a, 5, true)); + if (mp_cmp_d(&a, 11u) != MP_EQ) { + printf("mp_prime_next_prime: output should have been 11 but was: "); + DO(mp_fwrite(&a,10,stdout)); + putchar('\n'); + goto LBL_ERR; + } + /* 2^300 + 157 is a 300 bit large prime to guarantee a multi-limb bigint */ + DO(mp_2expt(&a, 300)); + mp_set_u32(&b, 157); + DO(mp_add(&a, &b, &a)); + DO(mp_copy(&a, &b)); + + /* 2^300 + 385 is the next prime */ + mp_set_u32(&c, 228); + DO(mp_add(&b, &c, &b)); + DO(mp_prime_next_prime(&a, 5, false)); + if (mp_cmp(&a, &b) != MP_EQ) { + printf("mp_prime_next_prime: output should have been\n"); + DO(mp_fwrite(&b,10,stdout)); + putchar('\n'); + printf("but was:\n"); + DO(mp_fwrite(&a,10,stdout)); + putchar('\n'); + goto LBL_ERR; + } + + /* Use another temporary variable or recompute? Mmh... */ + DO(mp_2expt(&a, 300)); + mp_set_u32(&b, 157); + DO(mp_add(&a, &b, &a)); + DO(mp_copy(&a, &b)); + + /* 2^300 + 631 is the next prime congruent to 3 mod 4*/ + mp_set_u32(&c, 474); + DO(mp_add(&b, &c, &b)); + DO(mp_prime_next_prime(&a, 5, true)); + if (mp_cmp(&a, &b) != MP_EQ) { + printf("mp_prime_next_prime (bbs): output should have been\n"); + DO(mp_fwrite(&b,10,stdout)); + putchar('\n'); + printf("but was:\n"); + DO(mp_fwrite(&a,10,stdout)); + putchar('\n'); + goto LBL_ERR; + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_montgomery_reduce(void) +{ + mp_digit mp; + int ix, i, n; + char buf[4096]; + + /* size_t written; */ + + mp_int a, b, c, d, e; + DOR(mp_init_multi(&a, &b, &c, &d, &e, NULL)); + + /* test montgomery */ + for (i = 1; i <= 10; i++) { + if (i == 10) + i = 1000; + printf(" digit size: %2d\r", i); + fflush(stdout); + for (n = 0; n < 1000; n++) { + DO(mp_rand(&a, i)); + a.dp[0] |= 1; + + /* let's see if R is right */ + DO(mp_montgomery_calc_normalization(&b, &a)); + DO(mp_montgomery_setup(&a, &mp)); + + /* now test a random reduction */ + for (ix = 0; ix < 100; ix++) { + DO(mp_rand(&c, 1 + (abs(rand_int()) % (2*i)))); + DO(mp_copy(&c, &d)); + DO(mp_copy(&c, &e)); + + DO(mp_mod(&d, &a, &d)); + DO(mp_montgomery_reduce(&c, &a, mp)); + DO(mp_mulmod(&c, &b, &a, &c)); + + if (mp_cmp(&c, &d) != MP_EQ) { +/* *INDENT-OFF* */ + printf("d = e mod a, c = e MOD a\n"); + DO(mp_to_decimal(&a, buf, sizeof(buf))); printf("a = %s\n", buf); + DO(mp_to_decimal(&e, buf, sizeof(buf))); printf("e = %s\n", buf); + DO(mp_to_decimal(&d, buf, sizeof(buf))); printf("d = %s\n", buf); + DO(mp_to_decimal(&c, buf, sizeof(buf))); printf("c = %s\n", buf); + + printf("compare no compare!\n"); goto LBL_ERR; +/* *INDENT-ON* */ + } + /* only one big montgomery reduction */ + if (i > 10) { + n = 1000; + ix = 100; + } + } + } + } + + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_read_radix(void) +{ + char buf[4096]; + size_t written; + + mp_int a; + DOR(mp_init_multi(&a, NULL)); + + DO(mp_read_radix(&a, "123456", 10)); + + DO(mp_to_radix(&a, buf, sizeof(buf), &written, 10)); + printf(" '123456' a == %s, length = %zu", buf, written); + + /* See comment in mp_to_radix.c */ + /* + if( (err = mp_to_radix(&a, buf, 3u, &written, 10) ) != MP_OKAY) goto LBL_ERR; + printf(" '56' a == %s, length = %zu\n", buf, written); + + if( (err = mp_to_radix(&a, buf, 4u, &written, 10) ) != MP_OKAY) goto LBL_ERR; + printf(" '456' a == %s, length = %zu\n", buf, written); + if( (err = mp_to_radix(&a, buf, 30u, &written, 10) ) != MP_OKAY) goto LBL_ERR; + printf(" '123456' a == %s, length = %zu, error = %s\n", + buf, written, mp_error_to_string(err)); + */ + DO(mp_read_radix(&a, "-123456", 10)); + DO(mp_to_radix(&a, buf, sizeof(buf), &written, 10)); + printf("\r '-123456' a == %s, length = %zu", buf, written); + + DO(mp_read_radix(&a, "0", 10)); + DO(mp_to_radix(&a, buf, sizeof(buf), &written, 10)); + printf("\r '0' a == %s, length = %zu", buf, written); + + while (0) { + char *s = fgets(buf, sizeof(buf), stdin); + if (s != buf) break; + DO(mp_read_radix(&a, buf, 10)); + DO(mp_prime_next_prime(&a, 5, true)); + DO(mp_to_radix(&a, buf, sizeof(buf), NULL, 10)); + printf("%s, %lu\n", buf, (unsigned long)a.dp[0] & 3uL); + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int test_mp_cnt_lsb(void) +{ + int ix; + + mp_int a, b; + DOR(mp_init_multi(&a, &b, NULL)); + + mp_set(&a, 1u); + for (ix = 0; ix < 1024; ix++) { + EXPECT(mp_cnt_lsb(&a) == ix); + DO(mp_mul_2(&a, &a)); + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; + +} + +static int test_mp_reduce_2k(void) +{ + int ix, cnt; + + mp_int a, b, c, d; + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + + /* test mp_reduce_2k */ + for (cnt = 3; cnt <= 128; ++cnt) { + mp_digit tmp; + + DO(mp_2expt(&a, cnt)); + DO(mp_sub_d(&a, 2u, &a)); /* a = 2**cnt - 2 */ + + printf("\r %4d bits", cnt); + printf("(%d)", mp_reduce_is_2k(&a)); + DO(mp_reduce_2k_setup(&a, &tmp)); + printf("(%lu)", (unsigned long) tmp); + for (ix = 0; ix < 1000; ix++) { + if (!(ix & 127)) { + printf("."); + fflush(stdout); + } + DO(mp_rand(&b, ((cnt / MP_DIGIT_BIT) + 1) * 2)); + DO(mp_copy(&c, &b)); + DO(mp_mod(&c, &a, &c)); + DO(mp_reduce_2k(&b, &a, 2u)); + EXPECT(mp_cmp(&c, &b) == MP_EQ); + } + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_div_3(void) +{ + int cnt; + + mp_int a, b, c, d, e; + DOR(mp_init_multi(&a, &b, &c, &d, &e, NULL)); + + /* test s_mp_div_3 */ + mp_set(&d, 3u); + for (cnt = 0; cnt < 10000;) { + mp_digit r2; + + if (!(++cnt & 127)) { + printf("\r %9d", cnt); + fflush(stdout); + } + DO(mp_rand(&a, (abs(rand_int()) % 128) + 1)); + DO(mp_div(&a, &d, &b, &e)); + DO(s_mp_div_3(&a, &c, &r2)); + + EXPECT(!mp_cmp(&b, &c) && !mp_cmp_d(&e, r2)); + } + printf("... passed!"); + + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, &e, NULL); + return EXIT_FAILURE; +} + +static int test_mp_dr_reduce(void) +{ + mp_digit mp; + int cnt; + unsigned rr; + int ix; + + mp_int a, b, c; + DOR(mp_init_multi(&a, &b, &c, NULL)); + + /* test the DR reduction */ + for (cnt = 2; cnt < 32; cnt++) { + printf("\r%d digit modulus", cnt); + DO(mp_grow(&a, cnt)); + mp_zero(&a); + for (ix = 1; ix < cnt; ix++) { + a.dp[ix] = MP_MASK; + } + a.used = cnt; + a.dp[0] = 3; + + DO(mp_rand(&b, cnt - 1)); + DO(mp_copy(&b, &c)); + + rr = 0; + do { + if (!(rr & 127)) { + printf("."); + fflush(stdout); + } + DO(mp_sqr(&b, &b)); + DO(mp_add_d(&b, 1u, &b)); + DO(mp_copy(&b, &c)); + + DO(mp_mod(&b, &a, &b)); + mp_dr_setup(&a, &mp); + DO(mp_dr_reduce(&c, &a, mp)); + + EXPECT(mp_cmp(&b, &c) == MP_EQ); + } while (++rr < 500); + printf(" passed"); + fflush(stdout); + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_reduce_2k_l(void) +{ +# if LTM_DEMO_TEST_REDUCE_2K_L + mp_int a, b, c, d; + int cnt; + char buf[4096]; + size_t length; + DOR(mp_init_multi(&a, &b, NULL)); + /* test the mp_reduce_2k_l code */ +# if LTM_DEMO_TEST_REDUCE_2K_L == 1 + /* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */ + DO(mp_2expt(&a, 1024)); + DO(mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16)); + DO(mp_sub(&a, &b, &a)); +# elif LTM_DEMO_TEST_REDUCE_2K_L == 2 + /* p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F */ + DO(mp_2expt(&a, 2048)); + DO(mp_read_radix(&b, + "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F", + 16)); + DO(mp_sub(&a, &b, &a)); +# else +# error oops +# endif + DO(mp_to_radix(&a, buf, sizeof(buf), &length, 10)); + printf("\n\np==%s, length = %zu\n", buf, length); + /* now mp_reduce_is_2k_l() should return */ + EXPECT(mp_reduce_is_2k_l(&a) == 1); + DO(mp_reduce_2k_setup_l(&a, &d)); + /* now do a million square+1 to see if it varies */ + DO(mp_rand(&b, 64)); + DO(mp_mod(&b, &a, &b)); + DO(mp_copy(&b, &c)); + printf("Testing: mp_reduce_2k_l..."); + fflush(stdout); + for (cnt = 0; cnt < (int)(1uL << 20); cnt++) { + DO(mp_sqr(&b, &b)); + DO(mp_add_d(&b, 1u, &b)); + DO(mp_reduce_2k_l(&b, &a, &d)); + DO(mp_sqr(&c, &c)); + DO(mp_add_d(&c, 1u, &c)); + DO(mp_mod(&c, &a, &c)); + if (mp_cmp(&b, &c) != MP_EQ) { + printf("mp_reduce_2k_l() failed at step %d\n", cnt); + DO(mp_to_hex(&b, buf, sizeof(buf))); + printf("b == %s\n", buf); + DO(mp_to_hex(&c, buf, sizeof(buf))); + printf("c == %s\n", buf); + goto LBL_ERR; + } + } + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +#else + return EXIT_SUCCESS; +# endif /* LTM_DEMO_TEST_REDUCE_2K_L */ +} +/* stripped down version of mp_radix_size. The faster version can be off by up to +3 */ +static mp_err s_rs(const mp_int *a, int radix, int *size) +{ + mp_err res; + int digs = 0u; + mp_int t; + mp_digit d; + *size = 0u; + if (mp_iszero(a)) { + *size = 2u; + return MP_OKAY; + } + if (radix == 2) { + *size = mp_count_bits(a) + 1; + return MP_OKAY; + } + DO_WHAT(mp_init_copy(&t, a), return MP_ERR); + t.sign = MP_ZPOS; + while (!mp_iszero(&t)) { + if ((res = mp_div_d(&t, (mp_digit)radix, &t, &d)) != MP_OKAY) { + mp_clear(&t); + return res; + } + ++digs; + } + mp_clear(&t); + *size = digs + 1; + return MP_OKAY; +} + + +static int test_mp_log_n(void) +{ + mp_int a; + mp_digit d; + int base, lb, size, i; + const int max_base = MP_MIN(INT_MAX, MP_DIGIT_MAX); + + if (MP_HAS(S_MP_WORD_TOO_SMALL)) { + fprintf(stderr, "Testing mp_log_n with restricted size of mp_word.\n"); + } else { + fprintf(stderr, "Testing mp_log_n with normal size of mp_word.\n"); + } + + DOR(mp_init(&a)); + + /* + base a result + 0 x MP_VAL + 1 x MP_VAL + */ + mp_set(&a, 42u); + base = 0u; + EXPECT(mp_log_n(&a, base, &lb) == MP_VAL); + base = 1u; + EXPECT(mp_log_n(&a, base, &lb) == MP_VAL); + /* + base a result + 2 0 MP_VAL + 2 1 0 + 2 2 1 + 2 3 1 + */ + base = 2u; + mp_zero(&a); + EXPECT(mp_log_n(&a, base, &lb) == MP_VAL); + + for (d = 1; d < 4; d++) { + mp_set(&a, d); + DO(mp_log_n(&a, base, &lb)); + EXPECT(lb == ((d == 1)?0:1)); + } + /* + base a result + 3 0 MP_VAL + 3 1 0 + 3 2 0 + 3 3 1 + */ + base = 3u; + mp_zero(&a); + EXPECT(mp_log_n(&a, base, &lb) == MP_VAL); + for (d = 1; d < 4; d++) { + mp_set(&a, d); + DO(mp_log_n(&a, base, &lb)); + EXPECT(lb == (((int)d < base)?0:1)); + } + + /* + bases 2..64 with "a" a random large constant. + The range of bases tested allows to check with + radix_size. + */ + DO(mp_rand(&a, 10)); + for (base = 2; base < 65; base++) { + DO(mp_log_n(&a, base, &lb)); + DO(s_rs(&a,base, &size)); + /* radix_size includes the memory needed for '\0', too*/ + size -= 2; + EXPECT(lb == size); + } + + /* + bases 2..64 with "a" a small constant and a small exponent "n" to test + in the range a^n - 10 .. a^n + 10. That will check the correction loops + and the test for perfect power. + For simplicity a = base and n = 23 (64^23 == 2^138 > 2^128) + */ + for (base = 2; base < 65; base++) { + mp_set(&a,(mp_digit)base); + DO(mp_expt_n(&a, 23, &a)); + DO(mp_sub_d(&a, 10u, &a)); + for (i = 0; i < 20; i++) { + DO(mp_log_n(&a, base, &lb)); + DO(s_rs(&a, base, &size)); + size -= 2; + EXPECT(lb == size); + DO(mp_add_d(&a, 1u, &a)); + } + } + + /*Test base upper edgecase with base = UINT32_MAX and number = (UINT32_MAX/2)*UINT32_MAX^10 */ + mp_set(&a, max_base); + DO(mp_expt_n(&a, 10uL, &a)); + DO(mp_add_d(&a, max_base / 2, &a)); + DO(mp_log_n(&a, max_base, &lb)); + EXPECT(lb == 10u); + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +static int test_mp_log(void) +{ + mp_int a, base, bn, t; + int lb, lb2, i, j; + + if (MP_HAS(S_MP_WORD_TOO_SMALL)) { + fprintf(stdout, "Testing mp_log with restricted size of mp_word.\n"); + } else { + fprintf(stdout, "Testing mp_log with normal size of mp_word.\n"); + } + + DOR(mp_init_multi(&a, &base, &bn, &t, NULL)); + + /* + The small values got tested above for mp_log_n already, leaving the big stuff + with bases larger than INT_MAX. + */ + + /* Edgecases a^b and -1+a^b (floor(log_2(256^129)) = 1032) */ + for (i = 2; i < 256; i++) { + mp_set_i32(&a,i); + for (j = 2; j < ((i/2)+1); j++) { + DO(mp_expt_n(&a, j, &bn)); + mp_set_i32(&base,j); + /* i^j a perfect power */ + DO(mp_log(&bn, &a, &lb)); + DO(mp_expt_n(&a, lb, &t)); + if (mp_cmp(&t, &bn) != MP_EQ) { + fprintf(stderr,"FAILURE mp_log for perf. power at i = %d, j = %d\n", i, j); + goto LBL_ERR; + } + /* -1 + i^j */ + DO(mp_decr(&bn)); + DO(mp_log(&bn, &a, &lb2)); + if (lb != (lb2+1)) { + fprintf(stderr,"FAILURE mp_log for -1 + i^j at i = %d, j = %d\n", i, j); + goto LBL_ERR; + } + } + } + + /* Random a, base */ + for (i = 1; i < 256; i++) { + do { + DO(mp_rand(&a, i)); + } while (mp_cmp_d(&a,2u) == MP_LT); + for (j = 1; j < ((i/2)+1); j++) { + do { + DO(mp_rand(&base, j)); + } while (mp_cmp_d(&base,2u) == MP_LT); + DO(mp_log(&a, &base, &lb)); + DO(mp_expt_n(&base, lb, &bn)); + /* "bn" must be smaller than or equal to "a" at this point. */ + if (mp_cmp(&bn, &a) == MP_GT) { + fprintf(stderr,"FAILURE mp_log random in GT check"); + goto LBL_ERR; + } + DO(mp_mul(&bn, &base, &bn)); + /* "bn" must be bigger than "a" at this point. */ + if (mp_cmp(&bn, &a) != MP_GT) { + fprintf(stderr,"FAILURE mp_log random in NOT GT check"); + goto LBL_ERR; + } + } + } + + mp_clear_multi(&a, &base, &bn, &t, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &base, &bn, &t, NULL); + return EXIT_FAILURE; +} + + +static int test_mp_incr(void) +{ + mp_int a, b; + + DOR(mp_init_multi(&a, &b, NULL)); + + /* Does it increment inside the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK/2); + DO(mp_incr(&a)); + EXPECT(mp_cmp_d(&a, (MP_MASK/2u) + 1u) == MP_EQ); + + /* Does it increment outside of the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK); + mp_set(&b, MP_MASK); + DO(mp_incr(&a)); + DO(mp_add_d(&b, 1u, &b)); + EXPECT(mp_cmp(&a, &b) == MP_EQ); + + /* Does it increment from -1 to 0? */ + mp_set(&a, 1u); + a.sign = MP_NEG; + DO(mp_incr(&a)); + EXPECT(mp_cmp_d(&a, 0u) == MP_EQ); + + /* Does it increment from -(MP_MASK + 1) to -MP_MASK? */ + mp_set(&a, MP_MASK); + DO(mp_add_d(&a, 1u, &a)); + a.sign = MP_NEG; + DO(mp_incr(&a)); + EXPECT(a.sign == MP_NEG); + + a.sign = MP_ZPOS; + EXPECT(mp_cmp_d(&a, MP_MASK) == MP_EQ); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +static int test_mp_decr(void) +{ + mp_int a, b; + + DOR(mp_init_multi(&a, &b, NULL)); + + /* Does it decrement inside the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK/2); + DO(mp_decr(&a)); + EXPECT(mp_cmp_d(&a, (MP_MASK/2u) - 1u) == MP_EQ); + + /* Does it decrement outside of the limits of a MP_xBIT limb? */ + mp_set(&a, MP_MASK); + DO(mp_add_d(&a, 1u, &a)); + DO(mp_decr(&a)); + EXPECT(mp_cmp_d(&a, MP_MASK) == MP_EQ); + + /* Does it decrement from 0 to -1? */ + mp_zero(&a); + DO(mp_decr(&a)); + if (a.sign == MP_NEG) { + a.sign = MP_ZPOS; + EXPECT(mp_cmp_d(&a, 1u) == MP_EQ); + } else { + goto LBL_ERR; + } + + + /* Does it decrement from -MP_MASK to -(MP_MASK + 1)? */ + mp_set(&a, MP_MASK); + a.sign = MP_NEG; + mp_set(&b, MP_MASK); + b.sign = MP_NEG; + DO(mp_sub_d(&b, 1u, &b)); + DO(mp_decr(&a)); + EXPECT(mp_cmp(&a, &b) == MP_EQ); + + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +/* + Cannot test mp_exp(_d) without mp_root_n and vice versa. + So one of the two has to be tested from scratch. + + Numbers generated by + for i in {1..10} + do + seed=$(head -c 10000 /dev/urandom | tr -dc '[:digit:]' | head -c 120); + echo $seed; + convertbase $seed 10 64; + done + + (The program "convertbase" uses libtommath's to/from_radix functions) + + Roots were precalculated with Pari/GP + + default(realprecision,1000); + for(n=3,100,r = floor(a^(1/n));printf("\"" r "\", ")) + + All numbers as strings to simplify things, especially for the + low-mp branch. +*/ + +static int test_mp_root_n(void) +{ + mp_int a, c, r; + int i, j; + + const char *input[] = { + "4n9cbk886QtLQmofprid3l2Q0GD8Yv979Lh8BdZkFE8g2pDUUSMBET/+M/YFyVZ3mBp", + "5NlgzHhmIX05O5YoW5yW5reAlVNtRAlIcN2dfoATnNdc1Cw5lHZUTwNthmK6/ZLKfY6", + "3gweiHDX+ji5utraSe46IJX+uuh7iggs63xIpMP5MriU4Np+LpHI5are8RzS9pKh9xP", + "5QOJUSKMrfe7LkeyJOlupS8h7bjT+TXmZkDzOjZtfj7mdA7cbg0lRX3CuafhjIrpK8S", + "4HtYFldVkyVbrlg/s7kmaA7j45PvLQm+1bbn6ehgP8tVoBmGbv2yDQI1iQQze4AlHyN", + "3bwCUx79NAR7c68OPSp5ZabhZ9aBEr7rWNTO2oMY7zhbbbw7p6shSMxqE9K9nrTNucf", + "4j5RGb78TfuYSzrXn0z6tiAoWiRI81hGY3el9AEa9S+gN4x/AmzotHT2Hvj6lyBpE7q", + "4lwg30SXqZhEHNsl5LIXdyu7UNt0VTWebP3m7+WUL+hsnFW9xJe7UnzYngZsvWh14IE", + "1+tcqFeRuGqjRADRoRUJ8gL4UUSFQVrVVoV6JpwVcKsuBq5G0pABn0dLcQQQMViiVRj", + "hXwxuFySNSFcmbrs/coz4FUAaUYaOEt+l4V5V8vY71KyBvQPxRq/6lsSrG2FHvWDax" + }; + /* roots 3-100 of the above */ + const char *root[10][100] = { + { + "9163694094944489658600517465135586130944", + "936597377180979771960755204040", "948947857956884030956907", + "95727185767390496595", "133844854039712620", "967779611885360", + "20926191452627", "974139547476", "79203891950", "9784027073", + "1667309744", "365848129", "98268452", "31109156", "11275351", + "4574515", "2040800", "986985", "511525", "281431", "163096", + "98914", "62437", "40832", "27556", "19127", "13614", "9913", + "7367", "5577", "4294", "3357", "2662", "2138", "1738", "1428", + "1185", "993", "839", "715", "613", "530", "461", "403", "355", + "314", "279", "249", "224", "202", "182", "166", "151", "138", + "126", "116", "107", "99", "92", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "9534798256755061606359588498764080011382", + "964902943621813525741417593772", "971822399862464674540423", + "97646291566833512831", "136141536090599560", "982294733581430", + "21204945933335", "985810529393", "80066084985", "9881613813", + "1682654547", "368973625", "99051783", "31341581", "11354620", + "4604882", "2053633", "992879", "514434", "282959", "163942", + "99406", "62736", "41020", "27678", "19208", "13670", "9952", + "7395", "5598", "4310", "3369", "2671", "2145", "1744", "1433", + "1189", "996", "842", "717", "615", "531", "462", "404", "356", + "315", "280", "250", "224", "202", "183", "166", "151", "138", + "127", "116", "107", "99", "92", "85", "80", "74", "70", "65", "61", + "58", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "29", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "8398539113202579297642815367509019445624", + "877309458945432597462853440936", "900579899458998599215071", + "91643543761699761637", "128935656335800903", "936647990947203", + "20326748623514", "948988882684", "77342677787", "9573063447", + "1634096832", "359076114", "96569670", "30604705", "11103188", + "4508519", "2012897", "974160", "505193", "278105", "161251", + "97842", "61788", "40423", "27291", "18949", "13492", "9826", + "7305", "5532", "4260", "3332", "2642", "2123", "1726", "1418", + "1177", "986", "834", "710", "610", "527", "458", "401", "353", + "312", "278", "248", "223", "201", "181", "165", "150", "137", + "126", "116", "107", "99", "91", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "35", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "22", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "9559098494021810340217797724866627755195", + "966746709063325235560830083787", "973307706084821682248292", + "97770642291138756434", "136290128605981259", "983232784778520", + "21222944848922", "986563584410", "80121684894", "9887903837", + "1683643206", "369174929", "99102220", "31356542", "11359721", + "4606836", "2054458", "993259", "514621", "283057", "163997", + "99437", "62755", "41032", "27686", "19213", "13674", "9955", + "7397", "5599", "4311", "3370", "2672", "2146", "1744", "1433", + "1189", "996", "842", "717", "615", "532", "462", "404", "356", + "315", "280", "250", "224", "202", "183", "166", "151", "138", + "127", "116", "107", "99", "92", "86", "80", "74", "70", "65", "61", + "58", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "29", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "8839202025813295923132694443541993309220", + "911611499784863252820288596270", "928640961450376817534853", + "94017030509441723821", "131792686685970629", "954783483196511", + "20676214073400", "963660189823", "78428929840", "9696237956", + "1653495486", "363032624", "97562430", "30899570", "11203842", + "4547110", "2029216", "981661", "508897", "280051", "162331", + "98469", "62168", "40663", "27446", "19053", "13563", "9877", + "7341", "5558", "4280", "3347", "2654", "2132", "1733", "1424", + "1182", "990", "837", "713", "612", "529", "460", "402", "354", + "313", "279", "249", "223", "201", "182", "165", "150", "138", + "126", "116", "107", "99", "92", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "36", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "8338442683973420410660145045849076963795", + "872596990706967613912664152945", "896707843885562730147307", + "91315073695274540969", "128539440806486007", "934129001105825", + "20278149285734", "946946589774", "77191347471", "9555892093", + "1631391010", "358523975", "96431070", "30563524", "11089126", + "4503126", "2010616", "973111", "504675", "277833", "161100", + "97754", "61734", "40390", "27269", "18934", "13482", "9819", + "7300", "5528", "4257", "3330", "2641", "2122", "1725", "1417", + "1177", "986", "833", "710", "609", "527", "458", "401", "353", + "312", "278", "248", "222", "200", "181", "165", "150", "137", + "126", "116", "107", "99", "91", "85", "79", "74", "69", "65", "61", + "57", "54", "51", "48", "46", "43", "41", "39", "37", "35", "34", + "32", "31", "30", "28", "27", "26", "25", "24", "23", "22", "22", + "21", "20", "20", "19", "18", "18", "17", "17", "16", "16", "15" + }, { + "9122818552483814953977703257848970704164", + "933462289569511464780529972314", "946405863353935713909178", + "95513446972056321834", "133588658082928446", + "966158521967027", "20895030642048", "972833934108", + "79107381638", "9773098125", "1665590516", "365497822", + "98180628", "31083090", "11266459", "4571108", "2039360", + "986323", "511198", "281260", "163001", "98858", + "62404", "40811", "27543", "19117", "13608", "9908", + "7363", "5575", "4292", "3356", "2661", "2138", + "1737", "1428", "1185", "993", "839", "714", "613", + "530", "461", "403", "355", "314", "279", "249", + "224", "202", "182", "165", "151", "138", "126", + "116", "107", "99", "92", "85", "79", "74", "69", + "65", "61", "57", "54", "51", "48", "46", "43", + "41", "39", "37", "36", "34", "32", "31", "30", + "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", + "16", "16", "15" + }, { + "9151329724083804100369546479681933027521", + "935649419557299174433860420387", "948179413831316112751907", + "95662582675170358900", "133767426788182384", + "967289728859610", "20916775466497", "973745045600", + "79174731802", "9780725058", "1666790321", "365742295", + "98241919", "31101281", "11272665", "4573486", "2040365", + "986785", "511426", "281380", "163067", "98897", + "62427", "40826", "27552", "19124", "13612", "9911", + "7366", "5576", "4294", "3357", "2662", "2138", + "1738", "1428", "1185", "993", "839", "715", "613", + "530", "461", "403", "355", "314", "279", "249", + "224", "202", "182", "165", "151", "138", "126", + "116", "107", "99", "92", "85", "79", "74", "69", + "65", "61", "57", "54", "51", "48", "46", "43", + "41", "39", "37", "36", "34", "32", "31", "30", + "28", "27", "26", "25", "24", "23", "23", "22", + "21", "20", "20", "19", "18", "18", "17", "17", + "16", "16", "15" + }, { + "6839396355168045468586008471269923213531", + "752078770083218822016981965090", "796178899357307807726034", + "82700643015444840424", "118072966296549115", + "867224751770392", "18981881485802", "892288574037", + "73130030771", "9093989389", "1558462688", "343617470", + "92683740", "29448679", "10708016", "4356820", "1948676", + "944610", "490587", "270425", "156989", "95362", + "60284", "39477", "26675", "18536", "13208", "9627", + "7161", "5426", "4181", "3272", "2596", "2087", + "1697", "1395", "1159", "971", "821", "700", "601", + "520", "452", "396", "348", "308", "274", "245", + "220", "198", "179", "163", "148", "136", "124", + "114", "106", "98", "91", "84", "78", "73", "68", + "64", "60", "57", "53", "50", "48", "45", "43", + "41", "39", "37", "35", "34", "32", "31", "29", + "28", "27", "26", "25", "24", "23", "22", "22", + "21", "20", "19", "19", "18", "18", "17", "17", + "16", "16", "15" + }, { + "4788090721380022347683138981782307670424", + "575601315594614059890185238256", "642831903229558719812840", + "69196031110028430211", "101340693763170691", + "758683936560287", "16854690815260", "801767985909", + "66353290503", "8318415180", "1435359033", "318340531", + "86304307", "27544217", "10054988", "4105446", "1841996", + "895414", "466223", "257591", "149855", "91205", + "57758", "37886", "25639", "17842", "12730", "9290", + "6918", "5248", "4048", "3170", "2518", "2026", + "1649", "1357", "1128", "946", "800", "682", "586", + "507", "441", "387", "341", "302", "268", "240", + "215", "194", "176", "160", "146", "133", "122", + "112", "104", "96", "89", "83", "77", "72", "67", + "63", "59", "56", "53", "50", "47", "45", "42", + "40", "38", "36", "35", "33", "32", "30", "29", + "28", "27", "26", "25", "24", "23", "22", "21", + "21", "20", "19", "19", "18", "17", "17", "16", + "16", "15", "15" + } + }; + + DOR(mp_init_multi(&a, &c, &r, NULL)); + for (i = 0; i < 10; i++) { + DO(mp_read_radix(&a, input[i], 64)); + for (j = 3; j < 100; j++) { + DO(mp_root_n(&a, j, &c)); + DO(mp_read_radix(&r, root[i][j-3], 10)); + EXPECT(mp_cmp(&r, &c) == MP_EQ); + } + } + mp_clear_multi(&a, &c, &r, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &c, &r, NULL); + return EXIT_FAILURE; +} + +/* Less error-prone than -1 + 2^n with mp_2expt */ +static mp_err s_fill_with_ones(mp_int *a, int size) +{ + int i; + mp_err err = MP_OKAY; + + mp_zero(a); + + if ((err = mp_grow(a, size)) != MP_OKAY) goto LTM_ERR; + for (i = 0; i < size; i++) { + a->dp[i] = (mp_digit)MP_MASK; + a->used++; + } + +LTM_ERR: + return err; +} + +static int test_s_mp_sqr(void) +{ + mp_int a, b, c; + int i; + + DOR(mp_init_multi(&a, &b, &c, NULL)); + + /* s_mp_mul() has a hardcoded branch to s_mul_comba if s_mul_comba is available, + so test another 10 just in case. */ + for (i = 1; i < MP_MAX_COMBA + 10; i++) { + DO(s_fill_with_ones(&a, i)); + DO(s_mp_sqr(&a, &b)); + DO(s_mp_mul(&a, &a, &c, 2*i + 1)); + EXPECT(mp_cmp(&b, &c) == MP_EQ); + DO(mp_rand(&a, i)); + DO(s_mp_sqr(&a, &b)); + DO(s_mp_mul(&a, &a, &c, 2*i + 1)); + EXPECT(mp_cmp(&b, &c) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_sqr_comba(void) +{ + mp_int a, r1, r2; + int i, j; + + DOR(mp_init_multi(&a, &r1, &r2, NULL)); + + for (i = 1; i <= MP_MAX_COMBA; i++) { + DO(s_fill_with_ones(&a, i)); + DO(s_mp_sqr_comba(&a, &r1)); + DO(s_mp_sqr(&a, &r2)); + EXPECT(mp_cmp(&r1, &r2) == MP_EQ); + for (j = 0; j < 20; j++) { + DO(mp_rand(&a, i)); + DO(s_mp_sqr_comba(&a, &r1)); + DO(s_mp_sqr(&a, &r2)); + EXPECT(mp_cmp(&r1, &r2) == MP_EQ); + } + } + + mp_clear_multi(&a, &r1, &r2, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &r1, &r2, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_mul_balance(void) +{ + mp_int a, b, c; + + const char *na = + "4b0I5uMTujCysw+1OOuOyH2FX2WymrHUqi8BBDb7XpkV/4i7vXTbEYUy/kdIfCKu5jT5JEqYkdmnn3jAYo8XShPzNLxZx9yoLjxYRyptSuOI2B1DspvbIVYXY12sxPZ4/HCJ4Usm2MU5lO/006KnDMxuxiv1rm6YZJZ0eZU"; + const char *nb = "3x9vs0yVi4hIq7poAeVcggC3WoRt0zRLKO"; + const char *nc = + "HzrSq9WVt1jDTVlwUxSKqxctu2GVD+N8+SVGaPFRqdxyld6IxDBbj27BPJzYUdR96k3sWpkO8XnDBvupGPnehpQe4KlO/KmN1PjFov/UTZYM+LYzkFcBPyV6hkkL8ePC1rlFLAHzgJMBCXVp4mRqtkQrDsZXXlcqlbTFu69wF6zDEysiX2cAtn/kP9ldblJiwYPCD8hG"; + + DOR(mp_init_multi(&a, &b, &c, NULL)); + + DO(mp_read_radix(&a, na, 64)); + DO(mp_read_radix(&b, nb, 64)); + + DO(s_mp_mul_balance(&a, &b, &c)); + + DO(mp_read_radix(&b, nc, 64)); + + EXPECT(mp_cmp(&b, &c) == MP_EQ); + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +#define s_mp_mul_full(a, b, c) s_mp_mul(a, b, c, (a)->used + (b)->used + 1) +static int test_s_mp_mul_karatsuba(void) +{ + mp_int a, b, c, d; + int size; + + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + for (size = MP_MUL_KARATSUBA_CUTOFF; size < (MP_MUL_KARATSUBA_CUTOFF + 20); size++) { + DO(mp_rand(&a, size)); + DO(mp_rand(&b, size)); + DO(s_mp_mul_karatsuba(&a, &b, &c)); + DO(s_mp_mul_full(&a,&b,&d)); + EXPECT(mp_cmp(&c, &d) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_sqr_karatsuba(void) +{ + mp_int a, b, c; + int size; + + DOR(mp_init_multi(&a, &b, &c, NULL)); + for (size = MP_SQR_KARATSUBA_CUTOFF; size < (MP_SQR_KARATSUBA_CUTOFF + 20); size++) { + DO(mp_rand(&a, size)); + DO(s_mp_sqr_karatsuba(&a, &b)); + DO(s_mp_sqr(&a, &c)); + EXPECT(mp_cmp(&b, &c) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_mul_toom(void) +{ + mp_int a, b, c, d; + int size; + +#if (MP_DIGIT_BIT == 60) + int tc_cutoff; +#endif + + DOR(mp_init_multi(&a, &b, &c, &d, NULL)); + /* This number construction is limb-size specific */ +#if (MP_DIGIT_BIT == 60) + DO(mp_rand(&a, 1196)); + DO(mp_mul_2d(&a,71787 - mp_count_bits(&a), &a)); + + DO(mp_rand(&b, 1338)); + DO(mp_mul_2d(&b, 80318 - mp_count_bits(&b), &b)); + DO(mp_mul_2d(&b, 6310, &b)); + DO(mp_2expt(&c, 99000 - 1000)); + DO(mp_add(&b, &c, &b)); + + tc_cutoff = MP_MUL_TOOM_CUTOFF; + MP_MUL_TOOM_CUTOFF = INT_MAX; + DO(mp_mul(&a, &b, &c)); + MP_MUL_TOOM_CUTOFF = tc_cutoff; + DO(mp_mul(&a, &b, &d)); + EXPECT(mp_cmp(&c, &d) == MP_EQ); +#endif + + for (size = MP_MUL_TOOM_CUTOFF; size < (MP_MUL_TOOM_CUTOFF + 20); size++) { + DO(mp_rand(&a, size)); + DO(mp_rand(&b, size)); + DO(s_mp_mul_toom(&a, &b, &c)); + DO(s_mp_mul_full(&a,&b,&d)); + EXPECT(mp_cmp(&c, &d) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_sqr_toom(void) +{ + mp_int a, b, c; + int size; + + DOR(mp_init_multi(&a, &b, &c, NULL)); + for (size = MP_SQR_TOOM_CUTOFF; size < (MP_SQR_TOOM_CUTOFF + 20); size++) { + DO(mp_rand(&a, size)); + DO(s_mp_sqr_toom(&a, &b)); + DO(s_mp_sqr(&a, &c)); + EXPECT(mp_cmp(&b, &c) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + + +static int test_mp_radix_size(void) +{ + mp_int a; + int radix; + size_t size; +/* *INDENT-OFF* */ + size_t results[65] = { + 0, 0, 1627, 1027, 814, 702, 630, 581, 543, + 514, 491, 471, 455, 441, 428, 418, 408, 399, + 391, 384, 378, 372, 366, 361, 356, 352, 347, + 343, 340, 336, 333, 330, 327, 324, 321, 318, + 316, 314, 311, 309, 307, 305, 303, 301, 299, + 298, 296, 294, 293, 291, 290, 288, 287, 285, + 284, 283, 281, 280, 279, 278, 277, 276, 275, + 273, 272 + }; +/* *INDENT-ON* */ + + DOR(mp_init(&a)); + + /* number to result in a different size for every base: 67^(4 * 67) */ + mp_set(&a, 67); + DO(mp_expt_n(&a, 268, &a)); + + for (radix = 2; radix < 65; radix++) { + DO(mp_radix_size(&a, radix, &size)); + EXPECT(size == results[radix]); + a.sign = MP_NEG; + DO(mp_radix_size(&a, radix, &size)); + EXPECT(size == (results[radix] + 1)); + a.sign = MP_ZPOS; + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + +#define PRINTERR_V(...) + +/* Some larger values to test the fast division algorithm */ +static int test_s_mp_div_recursive(void) +{ + mp_int a, b, c_q, c_r, d_q, d_r; + int size; + + DOR(mp_init_multi(&a, &b, &c_q, &c_r, &d_q, &d_r, NULL)); + + for (size = MP_MUL_KARATSUBA_CUTOFF; size < (3 * MP_MUL_KARATSUBA_CUTOFF); size += 10) { + printf("\rsizes = %d / %d", 10 * size, size); + /* Relation 10:1 */ + DO(mp_rand(&a, 10 * size)); + DO(mp_rand(&b, size)); + DO(s_mp_div_recursive(&a, &b, &c_q, &c_r)); + DO(s_mp_div_school(&a, &b, &d_q, &d_r)); + EXPECT(mp_cmp(&c_q, &d_q) == MP_EQ); + EXPECT(mp_cmp(&c_r, &d_r) == MP_EQ); + printf("\rsizes = %d / %d", 2 * size, size); + + /* Relation 10:1 negative numerator*/ + DO(mp_rand(&a, 10 * size)); + DO(mp_neg(&a, &a)); + DO(mp_rand(&b, size)); + DO(s_mp_div_recursive(&a, &b, &c_q, &c_r)); + DO(s_mp_div_school(&a, &b, &d_q, &d_r)); + EXPECT(mp_cmp(&c_q, &d_q) == MP_EQ); + EXPECT(mp_cmp(&c_r, &d_r) == MP_EQ); + printf("\rsizes = %d / %d, negative numerator", 2 * size, size); + + /* Relation 10:1 negative denominator*/ + DO(mp_rand(&a, 10 * size)); + DO(mp_rand(&b, size)); + DO(mp_neg(&b, &b)); + DO(s_mp_div_recursive(&a, &b, &c_q, &c_r)); + DO(s_mp_div_school(&a, &b, &d_q, &d_r)); + EXPECT(mp_cmp(&c_q, &d_q) == MP_EQ); + EXPECT(mp_cmp(&c_r, &d_r) == MP_EQ); + printf("\rsizes = %d / %d, negative denominator", 2 * size, size); + + /* Relation 2:1 */ + DO(mp_rand(&a, 2 * size)); + DO(mp_rand(&b, size)); + DO(s_mp_div_recursive(&a, &b, &c_q, &c_r)); + DO(s_mp_div_school(&a, &b, &d_q, &d_r)); + EXPECT(mp_cmp(&c_q, &d_q) == MP_EQ); + EXPECT(mp_cmp(&c_r, &d_r) == MP_EQ); + printf("\rsizes = %d / %d", 3 * size, 2 * size); + /* Upper limit 3:2 */ + DO(mp_rand(&a, 3 * size)); + DO(mp_rand(&b, 2 * size)); + DO(s_mp_div_recursive(&a, &b, &c_q, &c_r)); + DO(s_mp_div_school(&a, &b, &d_q, &d_r)); + EXPECT(mp_cmp(&c_q, &d_q) == MP_EQ); + EXPECT(mp_cmp(&c_r, &d_r) == MP_EQ); + } + + mp_clear_multi(&a, &b, &c_q, &c_r, &d_q, &d_r, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c_q, &c_r, &d_q, &d_r, NULL); + return EXIT_FAILURE; +} + +static int test_s_mp_div_small(void) +{ + mp_int a, b, c_q, c_r, d_q, d_r; + int size; + + DOR(mp_init_multi(&a, &b, &c_q, &c_r, &d_q, &d_r, NULL)); + for (size = 1; size < MP_MUL_KARATSUBA_CUTOFF; size += 10) { + printf("\rsizes = %d / %d", 2 * size, size); + /* Relation 10:1 */ + DO(mp_rand(&a, 2 * size)); + DO(mp_rand(&b, size)); + DO(s_mp_div_small(&a, &b, &c_q, &c_r)); + DO(s_mp_div_school(&a, &b, &d_q, &d_r)); + EXPECT(mp_cmp(&c_q, &d_q) == MP_EQ); + EXPECT(mp_cmp(&c_r, &d_r) == MP_EQ); + } + mp_clear_multi(&a, &b, &c_q, &c_r, &d_q, &d_r, NULL); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear_multi(&a, &b, &c_q, &c_r, &d_q, &d_r, NULL); + return EXIT_FAILURE; +} + + +static int test_s_mp_radix_size_overestimate(void) +{ + + mp_int a; + int radix, n; + size_t size, size2; +/* *INDENT-OFF* */ + size_t results[65] = { + 0u, 0u, 1627u, 1027u, 814u, 702u, 630u, 581u, 543u, + 514u, 491u, 471u, 455u, 441u, 428u, 418u, 408u, 399u, + 391u, 384u, 378u, 372u, 366u, 361u, 356u, 352u, 347u, + 343u, 340u, 336u, 333u, 330u, 327u, 324u, 321u, 318u, + 316u, 314u, 311u, 309u, 307u, 305u, 303u, 301u, 299u, + 298u, 296u, 294u, 293u, 291u, 290u, 288u, 287u, 285u, + 284u, 283u, 281u, 280u, 279u, 278u, 277u, 276u, 275u, + 273u, 272u + }; +/* *INDENT-ON* */ + + DO(mp_init(&a)); + + /* number to result in a different size for every base: 67^(4 * 67) */ + mp_set(&a, 67); + DO(mp_expt_n(&a, 268, &a)); + + for (radix = 2; radix < 65; radix++) { + DO(s_mp_radix_size_overestimate(&a, radix, &size)); + EXPECT(size >= results[radix]); + EXPECT(size < results[radix] + 20); /* some error bound */ + a.sign = MP_NEG; + DO(s_mp_radix_size_overestimate(&a, radix, &size)); + EXPECT(size >= results[radix]); + EXPECT(size < results[radix] + 20); /* some error bound */ + a.sign = MP_ZPOS; + } + + /* randomized test */ + for (n = 1; n < 1024; n += 1234) { + DO(mp_rand(&a, n)); + + for (radix = 2; radix < 65; radix++) { + DO(s_mp_radix_size_overestimate(&a, radix, &size)); + DO(mp_radix_size(&a, radix, &size2)); + EXPECT(size >= size2); + EXPECT(size < size2 + 20); /* some error bound */ + a.sign = MP_NEG; + DO(s_mp_radix_size_overestimate(&a, radix, &size)); + DO(mp_radix_size(&a, radix, &size2)); + EXPECT(size >= size2); + EXPECT(size < size2 + 20); /* some error bound */ + a.sign = MP_ZPOS; + } + } + + mp_clear(&a); + return EXIT_SUCCESS; +LBL_ERR: + mp_clear(&a); + return EXIT_FAILURE; +} + + +static int test_mp_read_write_ubin(void) +{ + mp_int a, b, c; + size_t size, len; + uint8_t *buf = NULL; + + DOR(mp_init_multi(&a, &b, &c, NULL)); + + DO(mp_rand(&a, 15)); + DO(mp_neg(&a, &b)); + + size = mp_ubin_size(&a); + printf("mp_to_ubin_size %zu - ", size); + buf = (uint8_t *)malloc(sizeof(*buf) * size); + if (buf == NULL) { + fprintf(stderr, "test_read_write_binaries (u) failed to allocate %zu bytes\n", + sizeof(*buf) * size); + goto LBL_ERR; + } + + DO(mp_to_ubin(&a, buf, size, &len)); + printf("mp_to_ubin len = %zu", len); + + DO(mp_from_ubin(&c, buf, len)); + + if (mp_cmp(&a, &c) != MP_EQ) { + fprintf(stderr, "to/from ubin cycle failed\n"); + goto LBL_ERR; + } + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_read_write_sbin(void) +{ + mp_int a, b, c; + size_t size, len; + uint8_t *buf = NULL; + + DOR(mp_init_multi(&a, &b, &c, NULL)); + + DO(mp_rand(&a, 15)); + DO(mp_neg(&a, &b)); + + size = mp_sbin_size(&a); + printf("mp_to_sbin_size %zu - ", size); + buf = (uint8_t *)malloc(sizeof(*buf) * size); + if (buf == NULL) { + fprintf(stderr, "test_read_write_binaries (s) failed to allocate %zu bytes\n", + sizeof(*buf) * size); + goto LBL_ERR; + } + + DO(mp_to_sbin(&b, buf, size, &len)); + printf("mp_to_sbin len = %zu", len); + + DO(mp_from_sbin(&c, buf, len)); + + if (mp_cmp(&b, &c) != MP_EQ) { + fprintf(stderr, "to/from ubin cycle failed\n"); + goto LBL_ERR; + } + + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_SUCCESS; +LBL_ERR: + free(buf); + mp_clear_multi(&a, &b, &c, NULL); + return EXIT_FAILURE; +} + +static int test_mp_pack_unpack(void) +{ + mp_int a, b; + size_t written, count; + uint8_t *buf = NULL; + + mp_order order = MP_LSB_FIRST; + mp_endian endianness = MP_NATIVE_ENDIAN; + + DOR(mp_init_multi(&a, &b, NULL)); + DO(mp_rand(&a, 15)); + + count = mp_pack_count(&a, 0uL, 1uL); + + buf = (uint8_t *)malloc(count); + if (buf == NULL) { + fprintf(stderr, "test_pack_unpack failed to allocate\n"); + goto LBL_ERR; + } + + DO(mp_pack((void *)buf, count, &written, order, 1uL, + endianness, 0uL, &a)); + DO(mp_unpack(&b, count, order, 1uL, + endianness, 0uL, (const void *)buf)); + + if (mp_cmp(&a, &b) != MP_EQ) { + fprintf(stderr, "pack/unpack cycle failed\n"); + goto LBL_ERR; + } + + free(buf); + mp_clear_multi(&a, &b, NULL); + return EXIT_SUCCESS; +LBL_ERR: + free(buf); + mp_clear_multi(&a, &b, NULL); + return EXIT_FAILURE; +} + +#ifndef LTM_TEST_DYNAMIC +#define ONLY_PUBLIC_API_C +#endif + +static int unit_tests(int argc, char **argv) +{ + static const struct { + const char *name; + int (*fn)(void); + } test[] = { +#define T0(n) { #n, test_##n } +#define T1(n, o) { #n, MP_HAS(o) ? test_##n : NULL } +#define T2(n, o1, o2) { #n, (MP_HAS(o1) && MP_HAS(o2)) ? test_##n : NULL } +#define T3(n, o1, o2, o3) { #n, (MP_HAS(o1) && MP_HAS(o2) && MP_HAS(o3)) ? test_##n : NULL } + T0(feature_detection), + T0(trivial_stuff), + T1(mp_hash, MP_HASH), + T2(mp_get_set_i32, MP_GET_I32, MP_GET_MAG_U32), + T2(mp_get_set_i64, MP_GET_I64, MP_GET_MAG_U64), + T1(mp_and, MP_AND), + T1(mp_cnt_lsb, MP_CNT_LSB), + T1(mp_complement, MP_COMPLEMENT), + T1(mp_decr, MP_SUB_D), + T2(s_mp_div_3, ONLY_PUBLIC_API, S_MP_DIV_3), + T1(mp_dr_reduce, MP_DR_REDUCE), + T2(mp_pack_unpack,MP_PACK, MP_UNPACK), + T2(mp_fread_fwrite, MP_FREAD, MP_FWRITE), + T1(mp_get_u32, MP_GET_I32), + T1(mp_get_u64, MP_GET_I64), + T1(mp_get_ul, MP_GET_L), + T1(mp_log_n, MP_LOG_N), + T1(mp_log, MP_LOG), + T1(mp_incr, MP_ADD_D), + T1(mp_invmod, MP_INVMOD), + T1(mp_is_square, MP_IS_SQUARE), + T1(mp_kronecker, MP_KRONECKER), + T1(mp_montgomery_reduce, MP_MONTGOMERY_REDUCE), + T1(mp_root_n, MP_ROOT_N), + T1(mp_or, MP_OR), + T1(mp_prime_is_prime, MP_PRIME_IS_PRIME), + T1(mp_prime_next_prime, MP_PRIME_NEXT_PRIME), + T1(mp_prime_rand, MP_PRIME_RAND), + T1(mp_rand, MP_RAND), + T1(mp_read_radix, MP_READ_RADIX), + T1(mp_read_write_ubin, MP_TO_UBIN), + T1(mp_read_write_sbin, MP_TO_SBIN), + T1(mp_reduce_2k, MP_REDUCE_2K), + T1(mp_reduce_2k_l, MP_REDUCE_2K_L), + T1(mp_radix_size, MP_RADIX_SIZE), + T2(s_mp_radix_size_overestimate, ONLY_PUBLIC_API, S_MP_RADIX_SIZE_OVERESTIMATE), +#if defined(MP_HAS_SET_DOUBLE) + T1(mp_set_double, MP_SET_DOUBLE), +#endif + T1(mp_signed_rsh, MP_SIGNED_RSH), + T2(mp_sqrt, MP_SQRT, MP_ROOT_N), + T1(mp_sqrtmod_prime, MP_SQRTMOD_PRIME), + T1(mp_xor, MP_XOR), + T3(s_mp_div_recursive, ONLY_PUBLIC_API, S_MP_DIV_RECURSIVE, S_MP_DIV_SCHOOL), + T3(s_mp_div_small, ONLY_PUBLIC_API, S_MP_DIV_SMALL, S_MP_DIV_SCHOOL), + T2(s_mp_sqr, ONLY_PUBLIC_API, S_MP_SQR), + /* s_mp_mul_comba not (yet) testable because s_mp_mul branches to s_mp_mul_comba automatically */ + T2(s_mp_sqr_comba, ONLY_PUBLIC_API, S_MP_SQR_COMBA), + T2(s_mp_mul_balance, ONLY_PUBLIC_API, S_MP_MUL_BALANCE), + T2(s_mp_mul_karatsuba, ONLY_PUBLIC_API, S_MP_MUL_KARATSUBA), + T2(s_mp_sqr_karatsuba, ONLY_PUBLIC_API, S_MP_SQR_KARATSUBA), + T2(s_mp_mul_toom, ONLY_PUBLIC_API, S_MP_MUL_TOOM), + T2(s_mp_sqr_toom, ONLY_PUBLIC_API, S_MP_SQR_TOOM) +#undef T3 +#undef T2 +#undef T1 + }; + unsigned long i, ok, fail, nop; + uint64_t t; + int j; + + ok = fail = nop = 0; + + t = (uint64_t)time(NULL); + printf("SEED: 0x%" PRIx64 "\n\n", t); + s_mp_rand_jenkins_init(t); + mp_rand_source(s_mp_rand_jenkins); + + for (i = 0; i < (sizeof(test) / sizeof(test[0])); ++i) { + if (argc > 1) { + for (j = 1; j < argc; ++j) { + if (strstr(test[i].name, argv[j]) != NULL) { + break; + } + } + if (j == argc) continue; + } + printf("TEST %s\n", test[i].name); + if (test[i].fn == NULL) { + nop++; + printf("NOP %s\n\n", test[i].name); + } else if (test[i].fn() == EXIT_SUCCESS) { + ok++; + printf("\n"); + } else { + fail++; + printf("\n\nFAIL %s\n\n", test[i].name); + } + } + fprintf(fail?stderr:stdout, "Tests OK/NOP/FAIL: %lu/%lu/%lu\n", ok, nop, fail); + + if (fail != 0) return EXIT_FAILURE; + else return EXIT_SUCCESS; +} + +int main(int argc, char **argv) +{ + print_header(); + + return unit_tests(argc, argv); +} diff --git a/deps/libtommath/demo/timing.c b/deps/libtommath/demo/timing.c new file mode 100644 index 0000000..a66ce85 --- /dev/null +++ b/deps/libtommath/demo/timing.c @@ -0,0 +1,429 @@ +#include +#include +#include +#include +#include + +#include + +#ifdef IOWNANATHLON +#include +#define SLEEP sleep(4) +#else +#define SLEEP +#endif + +#ifdef LTM_TIMING_REAL_RAND +#define LTM_TIMING_RAND_SEED time(NULL) +#else +#define LTM_TIMING_RAND_SEED 23 +#endif + +#ifndef MP_VERSION +#define MP_TIMING_VERSION +#else +#define MP_TIMING_VERSION "-" MP_VERSION +#endif + +#define CHECK_OK(x) do { mp_err err; if ((err = (x)) != MP_OKAY) { fprintf(stderr, "%d: CHECK_OK(%s) failed: %s\n", __LINE__, #x, mp_error_to_string(err)); exit(EXIT_FAILURE); } }while(0) + +static void ndraw(const mp_int *a, const char *name) +{ + char buf[4096]; + + printf("%s: ", name); + CHECK_OK(mp_to_radix(a, buf, sizeof(buf), NULL, 64)); + printf("%s\n", buf); +} + +static void draw(const mp_int *a) +{ + ndraw(a, ""); +} + + +static unsigned long lfsr = 0xAAAAAAAAuL; + +static unsigned int lbit(void) +{ + if ((lfsr & 0x80000000uL) != 0uL) { + lfsr = ((lfsr << 1) ^ 0x8000001BuL) & UINT32_MAX; + return 1u; + } else { + lfsr <<= 1; + return 0u; + } +} + +/* RDTSC from Scott Duplichan */ +static uint64_t TIMFUNC(void) +{ +#if defined __GNUC__ +#if defined(__i386__) || defined(__x86_64__) + /* version from http://www.mcs.anl.gov/~kazutomo/rdtsc.html + * the old code always got a warning issued by gcc, clang did not complain... + */ + unsigned hi, lo; + __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); + return ((uint64_t)lo)|(((uint64_t)hi)<<32); +#else /* gcc-IA64 version */ + unsigned long result; + __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory"); + + while (__builtin_expect((int) result == -1, 0)) + __asm__ __volatile__("mov %0=ar.itc":"=r"(result)::"memory"); + + return result; +#endif + + /* Microsoft and Intel Windows compilers */ +#elif defined _M_IX86 + __asm rdtsc +#elif defined _M_AMD64 + return __rdtsc(); +#elif defined _M_IA64 +#if defined __INTEL_COMPILER +#include +#endif + return __getReg(3116); +#else +#error need rdtsc function for this build +#endif +} + +#define DO2(x) do { mp_err err = x; err = x; (void)err; }while(0) +#define DO4(x) DO2(x); DO2(x) +#define DO8(x) DO4(x); DO4(x) + +#if 1 +#define DO(x) DO2(x) +#else +#define DO(x) DO8(x); DO8(x) +#endif + +#ifdef TIMING_NO_LOGS +#define FOPEN(a, b) NULL +#define FPRINTF(a,b,c,d) +#define FFLUSH(a) +#define FCLOSE(a) (void)(a) +#define PRINTLN(fm,b,n,m) printf(fm "\n", b, n, m) +#else +#define FOPEN(a,b) fopen(a,b) +#define FPRINTF(a,b,c,d) fprintf(a,b,c,d) +#define FFLUSH(a) fflush(a) +#define FCLOSE(a) fclose(a) +#define PRINTLN(fm,b,n,m) do { printf("\r" fm, b, n, m); fflush(stdout); }while(0) +#endif + +static int should_test(const char *test, int argc, char **argv) +{ + int j; + if (argc > 1) { + for (j = 1; j < argc; ++j) { + if (strstr(test, argv[j]) != NULL) { + return 1; + } + } + if (j == argc) return 0; + } + return 1; +} + +int main(int argc, char **argv) +{ + uint64_t tt, gg, CLK_PER_SEC; + FILE *log, *logb, *logc, *logd; + mp_int a, b, c, d, e, f; +#ifdef LTM_TIMING_PRIME_IS_PRIME + const char *name; + int m; +#endif + int n, cnt, ix, old_kara_m, old_kara_s, old_toom_m, old_toom_s; + unsigned rr; + + CHECK_OK(mp_init(&a)); + CHECK_OK(mp_init(&b)); + CHECK_OK(mp_init(&c)); + CHECK_OK(mp_init(&d)); + CHECK_OK(mp_init(&e)); + CHECK_OK(mp_init(&f)); + + srand(LTM_TIMING_RAND_SEED); + + + CLK_PER_SEC = TIMFUNC(); + sleep(1); + CLK_PER_SEC = TIMFUNC() - CLK_PER_SEC; + + printf("CLK_PER_SEC == %" PRIu64 "\n", CLK_PER_SEC); + +#ifdef LTM_TIMING_PRIME_IS_PRIME + if (should_test("prime", argc, argv) != 0) { + for (m = 0; m < 2; ++m) { + if (m == 0) { + name = " Arnault"; + CHECK_OK(mp_read_radix(&a, + "91xLNF3roobhzgTzoFIG6P13ZqhOVYSN60Fa7Cj2jVR1g0k89zdahO9/kAiRprpfO1VAp1aBHucLFV/qLKLFb+zonV7R2Vxp1K13ClwUXStpV0oxTNQVjwybmFb5NBEHImZ6V7P6+udRJuH8VbMEnS0H8/pSqQrg82OoQQ2fPpAk6G1hkjqoCv5s/Yr", + 64)); + } else { + name = "2^1119 + 53"; + mp_set(&a,1u); + CHECK_OK(mp_mul_2d(&a,1119,&a)); + CHECK_OK(mp_add_d(&a,53,&a)); + } + cnt = mp_prime_rabin_miller_trials(mp_count_bits(&a)); + ix = -cnt; + for (; cnt >= ix; cnt += ix) { + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_prime_is_prime(&a, cnt, &n)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + if ((m == 0) && n) { + printf("Arnault's pseudoprime is not prime but mp_prime_is_prime says it is.\n"); + return EXIT_FAILURE; + } + } while (++rr < 100u); + PRINTLN("Prime-check\t%s(%2d) => %9" PRIu64 "/sec, %9" PRIu64 " cycles", + name, cnt, CLK_PER_SEC / tt, tt); + } + } + } +#endif + + if (should_test("add", argc, argv) != 0) { + log = FOPEN("logs/add" MP_TIMING_VERSION ".log", "w"); + for (cnt = 8; cnt <= 128; cnt += 8) { + SLEEP; + CHECK_OK(mp_rand(&a, cnt)); + CHECK_OK(mp_rand(&b, cnt)); + DO8(mp_add(&a, &b, &c)); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_add(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100000u); + PRINTLN("Adding\t\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", cnt * MP_DIGIT_BIT, tt); + FFLUSH(log); + } + FCLOSE(log); + printf("\n"); + } + + if (should_test("sub", argc, argv) != 0) { + log = FOPEN("logs/sub" MP_TIMING_VERSION ".log", "w"); + for (cnt = 8; cnt <= 128; cnt += 8) { + SLEEP; + CHECK_OK(mp_rand(&a, cnt)); + CHECK_OK(mp_rand(&b, cnt)); + DO8(mp_sub(&a, &b, &c)); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_sub(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100000u); + + PRINTLN("Subtracting\t\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", cnt * MP_DIGIT_BIT, tt); + FFLUSH(log); + } + FCLOSE(log); + printf("\n\n"); + } + + if (should_test("mulsqr", argc, argv) != 0) { + /* do mult/square twice, first without karatsuba and second with */ + old_kara_m = MP_MUL_KARATSUBA_CUTOFF; + old_kara_s = MP_SQR_KARATSUBA_CUTOFF; + /* currently toom-cook cut-off is too high to kick in, so we just use the karatsuba values */ + old_toom_m = old_kara_m; + old_toom_s = old_kara_s; + for (ix = 0; ix < 3; ix++) { + printf("With%s Karatsuba, With%s Toom\n", (ix == 1) ? "" : "out", (ix == 2) ? "" : "out"); + + MP_MUL_KARATSUBA_CUTOFF = (ix == 1) ? old_kara_m : 9999; + MP_SQR_KARATSUBA_CUTOFF = (ix == 1) ? old_kara_s : 9999; + MP_MUL_TOOM_CUTOFF = (ix == 2) ? old_toom_m : 9999; + MP_SQR_TOOM_CUTOFF = (ix == 2) ? old_toom_s : 9999; + + log = FOPEN((ix == 0) ? "logs/mult" MP_TIMING_VERSION ".log" : (ix == 1) ? "logs/mult_kara" MP_TIMING_VERSION ".log" : + "logs/mult_toom" MP_TIMING_VERSION ".log", "w"); + for (cnt = 4; cnt <= (10240 / MP_DIGIT_BIT); cnt += 2) { + SLEEP; + CHECK_OK(mp_rand(&a, cnt)); + CHECK_OK(mp_rand(&b, cnt)); + DO8(mp_mul(&a, &b, &c)); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_mul(&a, &b, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100u); + PRINTLN("Multiplying\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", mp_count_bits(&a), tt); + FFLUSH(log); + } + FCLOSE(log); + printf("\n"); + + log = FOPEN((ix == 0) ? "logs/sqr" MP_TIMING_VERSION ".log" : (ix == 1) ? "logs/sqr_kara" MP_TIMING_VERSION ".log" : + "logs/sqr_toom" MP_TIMING_VERSION ".log", "w"); + for (cnt = 4; cnt <= (10240 / MP_DIGIT_BIT); cnt += 2) { + SLEEP; + CHECK_OK(mp_rand(&a, cnt)); + DO8(mp_sqr(&a, &b)); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_sqr(&a, &b)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 100u); + PRINTLN("Squaring\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", mp_count_bits(&a), tt); + FFLUSH(log); + } + FCLOSE(log); + printf("\n\n"); + + } + } + + if (should_test("expt", argc, argv) != 0) { + const char *primes[] = { + /* 2K large moduli */ + "179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586239334100047359817950870678242457666208137217", + "32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638099733077152121140120031150424541696791951097529546801429027668869927491725169", + "1044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085902995208257421855249796721729039744118165938433694823325696642096892124547425283", + /* 2K moduli mersenne primes */ + "6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", + "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502265229285668889329486246501015346579337652707239409519978766587351943831270835393219031728127", + "10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087", + "1475979915214180235084898622737381736312066145333169775147771216478570297878078949377407337049389289382748507531496480477281264838760259191814463365330269540496961201113430156902396093989090226259326935025281409614983499388222831448598601834318536230923772641390209490231836446899608210795482963763094236630945410832793769905399982457186322944729636418890623372171723742105636440368218459649632948538696905872650486914434637457507280441823676813517852099348660847172579408422316678097670224011990280170474894487426924742108823536808485072502240519452587542875349976558572670229633962575212637477897785501552646522609988869914013540483809865681250419497686697771007", + "259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071", + "190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991", + + /* DR moduli */ + "14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368612079", + "101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039", + "736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821797602431", + "38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783", + "542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147", + "1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503", + "1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679", + + /* generic unrestricted moduli */ + "17933601194860113372237070562165128350027320072176844226673287945873370751245439587792371960615073855669274087805055507977323024886880985062002853331424203", + "2893527720709661239493896562339544088620375736490408468011883030469939904368086092336458298221245707898933583190713188177399401852627749210994595974791782790253946539043962213027074922559572312141181787434278708783207966459019479487", + "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136319", + "47266428956356393164697365098120418976400602706072312735924071745438532218237979333351774907308168340693326687317443721193266215155735814510792148768576498491199122744351399489453533553203833318691678263241941706256996197460424029012419012634671862283532342656309677173602509498417976091509154360039893165037637034737020327399910409885798185771003505320583967737293415979917317338985837385734747478364242020380416892056650841470869294527543597349250299539682430605173321029026555546832473048600327036845781970289288898317888427517364945316709081173840186150794397479045034008257793436817683392375274635794835245695887", + "436463808505957768574894870394349739623346440601945961161254440072143298152040105676491048248110146278752857839930515766167441407021501229924721335644557342265864606569000117714935185566842453630868849121480179691838399545644365571106757731317371758557990781880691336695584799313313687287468894148823761785582982549586183756806449017542622267874275103877481475534991201849912222670102069951687572917937634467778042874315463238062009202992087620963771759666448266532858079402669920025224220613419441069718482837399612644978839925207109870840278194042158748845445131729137117098529028886770063736487420613144045836803985635654192482395882603511950547826439092832800532152534003936926017612446606135655146445620623395788978726744728503058670046885876251527122350275750995227", + "11424167473351836398078306042624362277956429440521137061889702611766348760692206243140413411077394583180726863277012016602279290144126785129569474909173584789822341986742719230331946072730319555984484911716797058875905400999504305877245849119687509023232790273637466821052576859232452982061831009770786031785669030271542286603956118755585683996118896215213488875253101894663403069677745948305893849505434201763745232895780711972432011344857521691017896316861403206449421332243658855453435784006517202894181640562433575390821384210960117518650374602256601091379644034244332285065935413233557998331562749140202965844219336298970011513882564935538704289446968322281451907487362046511461221329799897350993370560697505809686438782036235372137015731304779072430260986460269894522159103008260495503005267165927542949439526272736586626709581721032189532726389643625590680105784844246152702670169304203783072275089194754889511973916207", + "1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979", + NULL + }; + log = FOPEN("logs/expt" MP_TIMING_VERSION ".log", "w"); + logb = FOPEN("logs/expt_dr" MP_TIMING_VERSION ".log", "w"); + logc = FOPEN("logs/expt_2k" MP_TIMING_VERSION ".log", "w"); + logd = FOPEN("logs/expt_2kl" MP_TIMING_VERSION ".log", "w"); + for (n = 0; primes[n] != NULL; n++) { + SLEEP; + CHECK_OK(mp_read_radix(&a, primes[n], 10)); + mp_zero(&b); + for (rr = 0; rr < (unsigned) mp_count_bits(&a); rr++) { + CHECK_OK(mp_mul_2(&b, &b)); + b.dp[0] |= lbit(); + b.used += 1; + } + CHECK_OK(mp_sub_d(&a, 1uL, &c)); + CHECK_OK(mp_mod(&b, &c, &b)); + mp_set(&c, 3uL); + DO8(mp_exptmod(&c, &b, &a, &d)); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_exptmod(&c, &b, &a, &d)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 10u); + CHECK_OK(mp_sub_d(&a, 1uL, &e)); + CHECK_OK(mp_sub(&e, &b, &b)); + CHECK_OK(mp_exptmod(&c, &b, &a, &e)); /* c^(p-1-b) mod a */ + CHECK_OK(mp_mulmod(&e, &d, &a, &d)); /* c^b * c^(p-1-b) == c^p-1 == 1 */ + if (mp_cmp_d(&d, 1uL) != MP_EQ) { + printf("Different (%d)!!!\n", mp_count_bits(&a)); + draw(&d); + exit(0); + } + PRINTLN("Exponentiating\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF((n < 3) ? logd : (n < 9) ? logc : (n < 16) ? logb : log, + "%6d %9" PRIu64 "\n", mp_count_bits(&a), tt); + } + FCLOSE(log); + FCLOSE(logb); + FCLOSE(logc); + FCLOSE(logd); + printf("\n"); + } + + if (should_test("invmod", argc, argv) != 0) { + log = FOPEN("logs/invmod" MP_TIMING_VERSION ".log", "w"); + for (cnt = 4; cnt <= 32; cnt += 4) { + SLEEP; + CHECK_OK(mp_rand(&a, cnt)); + CHECK_OK(mp_rand(&b, cnt)); + + do { + CHECK_OK(mp_add_d(&b, 1uL, &b)); + CHECK_OK(mp_gcd(&a, &b, &c)); + } while (mp_cmp_d(&c, 1uL) != MP_EQ); + + DO2(mp_invmod(&b, &a, &c)); + rr = 0u; + tt = UINT64_MAX; + do { + gg = TIMFUNC(); + DO(mp_invmod(&b, &a, &c)); + gg = (TIMFUNC() - gg) >> 1; + if (tt > gg) + tt = gg; + } while (++rr < 1000u); + CHECK_OK(mp_mulmod(&b, &c, &a, &d)); + if (mp_cmp_d(&d, 1uL) != MP_EQ) { + printf("Failed to invert\n"); + return 0; + } + PRINTLN("Inverting mod\t%4d-bit => %9" PRIu64 "/sec, %9" PRIu64 " cycles", + mp_count_bits(&a), CLK_PER_SEC / tt, tt); + FPRINTF(log, "%6d %9" PRIu64 "\n", cnt * MP_DIGIT_BIT, tt); + } + FCLOSE(log); + printf("\n"); + } + + return 0; +} diff --git a/deps/libtommath/demo/tommath_tests.swift b/deps/libtommath/demo/tommath_tests.swift new file mode 100644 index 0000000..fd254da --- /dev/null +++ b/deps/libtommath/demo/tommath_tests.swift @@ -0,0 +1,94 @@ +import XCTest +import libtommath + +/* ---> Basic Manipulations <--- */ + +extension mp_int { + var isZero: Bool { used == 0 } + var isNeg: Bool { sign == MP_NEG } + var isEven: Bool { used == 0 || (dp[0] & 1) == 0 } + var isOdd: Bool { !isEven } +} + +func mp_get_u32(_ a: UnsafePointer) -> UInt32 { + return UInt32(bitPattern: mp_get_i32(a)) +} + +class LibTommathTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testTrivialStuff() throws { + var a = mp_int() + var b = mp_int() + var c = mp_int() + var d = mp_int() + + XCTAssertEqual(mp_init(&a), MP_OKAY) + XCTAssertEqual(mp_init(&b), MP_OKAY) + XCTAssertEqual(mp_init(&c), MP_OKAY) + XCTAssertEqual(mp_init(&d), MP_OKAY) + + defer { + mp_clear(&a) + mp_clear(&b) + mp_clear(&c) + mp_clear(&d) + } + + XCTAssert(mp_error_to_string(MP_OKAY) != nil) + + /* a: 0->5 */ + mp_set(&a, 5) + /* a: 5-> b: -5 */ + XCTAssertEqual(mp_neg(&a, &b), MP_OKAY) + XCTAssertEqual(mp_cmp(&a, &b), MP_GT) + XCTAssertEqual(mp_cmp(&b, &a), MP_LT) + XCTAssertTrue(b.isNeg) + /* a: 5-> a: -5 */ + var t = a // Fix compiler error: Overlapping accesses to 'a', but modification requires exclusive access; consider copying to a local variable + XCTAssertEqual(mp_neg(&t, &a), MP_OKAY) + XCTAssertEqual(mp_cmp(&b, &a), MP_EQ) + XCTAssertTrue(a.isNeg) + /* a: -5-> b: 5 */ + XCTAssertEqual(mp_abs(&a, &b), MP_OKAY) + XCTAssertTrue(!b.isNeg) + /* a: -5-> b: -4 */ + XCTAssertEqual(mp_add_d(&a, 1, &b), MP_OKAY) + XCTAssertTrue(b.isNeg) + XCTAssertEqual(mp_get_i32(&b), -4) + XCTAssertEqual(mp_get_u32(&b), UInt32(bitPattern: -4)) + XCTAssertEqual(mp_get_mag_u32(&b), 4) + /* a: -5-> b: 1 */ + XCTAssertEqual(mp_add_d(&a, 6, &b), MP_OKAY) + XCTAssertEqual(mp_get_u32(&b), 1) + /* a: -5-> a: 1 */ + t = a + XCTAssertEqual(mp_add_d(&t, 6, &a), MP_OKAY) + XCTAssertEqual(mp_get_u32(&a), 1) + mp_zero(&a); + /* a: 0-> a: 6 */ + t = a + XCTAssertEqual(mp_add_d(&t, 6, &a), MP_OKAY) + XCTAssertEqual(mp_get_u32(&a), 6) + + mp_set(&a, 42) + mp_set(&b, 1) + t = b + XCTAssertEqual(mp_neg(&t, &b), MP_OKAY) + mp_set(&c, 1) + XCTAssertEqual(mp_exptmod(&a, &b, &c, &d), MP_OKAY) + + mp_set(&c, 7) + /* same here */ + XCTAssertTrue(mp_exptmod(&a, &b, &c, &d) != MP_OKAY) + + XCTAssertTrue(a.isEven != a.isOdd) + } +} diff --git a/deps/libtommath/doc/.latexindent.yaml b/deps/libtommath/doc/.latexindent.yaml new file mode 100644 index 0000000..7409a04 --- /dev/null +++ b/deps/libtommath/doc/.latexindent.yaml @@ -0,0 +1,35 @@ +# 2 spaces +defaultIndent: " " +# verbatim environments- environments specified +# in this hash table will not be changed at all! +verbatimEnvironments: + verbatim: 1 + alltt: 1 +# verbatim commands such as \verb! body !, \lstinline$something else$ +verbatimCommands: + verb: 1 + +# no indent blocks (not necessarily verbatim +# environments) which are marked as %\begin{noindent} +# or anything else that the user puts in this hash +# table +noIndentBlock: + noindent: 1 + +# remove trailing whitespace from all lines +removeTrailingWhitespace: + beforeProcessing: 0 + afterProcessing: 1 + +indentAfterItems: + itemize: 1 + enumerate: 1 + description: 1 + list: 1 + +onlyOneBackUp: 1 + +modifyLineBreaks: + textWrapOptions: + columns: 100 + diff --git a/deps/libtommath/doc/bn.tex b/deps/libtommath/doc/bn.tex new file mode 100644 index 0000000..711ad0e --- /dev/null +++ b/deps/libtommath/doc/bn.tex @@ -0,0 +1,2749 @@ +\documentclass[synpaper]{book} +\usepackage{hyperref} +\usepackage{makeidx} +\usepackage{amssymb} +\usepackage{color} +\usepackage{alltt} +\usepackage{graphicx} +\usepackage{layout} +\usepackage{appendix} +\def\union{\cup} +\def\intersect{\cap} +\def\getsrandom{\stackrel{\rm R}{\gets}} +\def\cross{\times} +\def\cat{\hspace{0.5em} \| \hspace{0.5em}} +\def\catn{$\|$} +\def\divides{\hspace{0.3em} | \hspace{0.3em}} +\def\nequiv{\not\equiv} +\def\approx{\raisebox{0.2ex}{\mbox{\small $\sim$}}} +\def\lcm{{\rm lcm}} +\def\gcd{{\rm gcd}} +\def\log{{\rm log}} +\def\ord{{\rm ord}} +\def\abs{{\mathit abs}} +\def\rep{{\mathit rep}} +\def\mod{{\mathit\ mod\ }} +\renewcommand{\pmod}[1]{\ ({\rm mod\ }{#1})} +\newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} +\newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} +\def\Or{{\rm\ or\ }} +\def\And{{\rm\ and\ }} +\def\iff{\hspace{1em}\Longleftrightarrow\hspace{1em}} +\def\implies{\Rightarrow} +\def\undefined{{\rm ``undefined"}} +\def\Proof{\vspace{1ex}\noindent {\bf Proof:}\hspace{1em}} +\let\oldphi\phi +\def\phi{\varphi} +\def\Pr{{\rm Pr}} +\newcommand{\str}[1]{{\mathbf{#1}}} +\def\F{{\mathbb F}} +\def\N{{\mathbb N}} +\def\Z{{\mathbb Z}} +\def\R{{\mathbb R}} +\def\C{{\mathbb C}} +\def\Q{{\mathbb Q}} +\definecolor{DGray}{gray}{0.5} +\newcommand{\emailaddr}[1]{\mbox{$<${#1}$>$}} +\def\twiddle{\raisebox{0.3ex}{\mbox{\tiny $\sim$}}} +\def\gap{\vspace{0.5ex}} + +\makeindex +\begin{document} +\frontmatter +\pagestyle{empty} +\title{LibTomMath User Manual \\ v1.2.0} +\author{LibTom Projects \\ www.libtom.net} +\maketitle +This text, the library and the accompanying textbook are all hereby placed in the public domain. +This book has been +formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package. + +\vspace{10cm} + +\begin{flushright}Open Source. Open Academia. Open Minds. + + \mbox{ } + LibTom Projects + + \& originally + + Tom St Denis, + + Ontario, Canada +\end{flushright} + +\tableofcontents +\listoffigures +\mainmatter +\pagestyle{headings} +\chapter{Introduction} +\section{What is LibTomMath?} +LibTomMath is a library of source code which provides a series of efficient and carefully written +functions for manipulating large integer numbers. It was written in portable ISO C source code so +that it will build on any platform with a conforming C compiler. + +In a nutshell the library was written from scratch with verbose comments to help instruct computer +science students how to implement ``bignum'' math. However, the resulting code has proven to be +very useful. It has been used by numerous universities, commercial and open source software +developers. It has been used on a variety of platforms ranging from Linux and Windows based x86 to +ARM based Gameboys and PPC based MacOS machines. + +\section{License} +As of the v0.25 the library source code has been placed in the public domain with every new +release. As of the v0.28 release the textbook ``Implementing Multiple Precision Arithmetic'' has +been placed in the public domain with every new release as well. This textbook is meant to +compliment the project by providing a more solid walkthrough of the development algorithms used in +the library. + +Since both\footnote{Note that the MPI files under \texttt{mtest/} are copyrighted by Michael + Fromberger. They are not required to use LibTomMath.} are in the public domain everyone is +entitled +to do with them as they see fit. + +\section{Building LibTomMath} + +LibTomMath is meant to be very ``GCC friendly'' as it comes with a makefile well suited for GCC. +However, the library will also build in MSVC, Borland C out of the box. For any other ISO C +compiler a makefile will have to be made by the end +developer. Please consider to commit such a makefile to the LibTomMath developers, currently +residing at +\url{http://github.com/libtom/libtommath}, if successfully done so. + +Intel's C-compiler (ICC) is sufficiently compatible with GCC, at least the newer versions, to +replace GCC for building the static and the shared library. Editing the makefiles is not needed, +just set the shell variable \texttt{CC} as shown below. +\begin{alltt} +CC=/home/czurnieden/intel/bin/icc make +\end{alltt} + +ICC does not know all options available for GCC and LibTomMath uses two diagnostics +\texttt{-Wbad-function-cast} and \texttt{-Wcast-align} that are not supported by ICC resulting in +the warnings: +\begin{alltt} +icc: command line warning #10148: option '-Wbad-function-cast' not supported +icc: command line warning #10148: option '-Wcast-align' not supported +\end{alltt} +It is possible to mute this ICC warning with the compiler flag +\texttt{-diag-disable=10148}\footnote{It is not recommended to suppress warnings without a very + good reason but there is no harm in doing so in this very special case.}. + +\subsection{Static Libraries} +To build as a static library for GCC issue the following +\begin{alltt} +make +\end{alltt} + +command. This will build the library and archive the object files in ``libtommath.a''. Now you +link against that and include ``tommath.h'' within your programs. Alternatively to build with MSVC +issue the following +\begin{alltt} +nmake -f makefile.msvc +\end{alltt} + +This will build the library and archive the object files in ``tommath.lib''. This has been tested +with MSVC version 6.00 with service pack 5. + +To run a program to adapt the Toom--Cook cut--off values to your architecture type +\begin{alltt} +make tune +\end{alltt} +This will take some time. + +\subsection{Shared Libraries} +\subsubsection{GNU based Operating Systems} +To build as a shared library for GCC issue the following +\begin{alltt} +make -f makefile.shared +\end{alltt} +This requires the ``libtool'' package (common on most Linux/BSD systems). It will build LibTomMath +as both shared and static then install (by default) into /usr/lib as well as install the header +files in \texttt{/usr/include}. The shared library (resource) will be called +\texttt{libtommath.la} while the static library called \texttt{libtommath.a}. Generally you use +libtool to link your application against the shared object. + +To run a program to adapt the Toom--Cook cut--off values to your architecture type +\begin{alltt} +make -f makefile.shared tune +\end{alltt} +This will take some time. + +\subsubsection{Microsoft Windows based Operating Systems} +There is limited support for making a ``DLL'' in windows via the \texttt{makefile.cygwin\_dll} +makefile. It requires Cygwin to work with since it requires the auto-export/import functionality. +The resulting DLL and import library \texttt{libtommath.dll.a} can be used to link LibTomMath +dynamically to any Windows program using Cygwin. + +\subsubsection{OpenBSD} +OpenBSD replaced some of their GNU-tools, especially \texttt{libtool} with their own, slightly +different versions. To ease the workload of LibTomMath's developer team, only a static library can +be build with the included \texttt{makefile.unix}. + +The wrong \texttt{make} will result in errors like: +\begin{alltt} +*** Parse error in /home/user/GITHUB/libtommath: Need an operator in 'LIBNAME' ) +*** Parse error: Need an operator in 'endif' (makefile.shared:8) +*** Parse error: Need an operator in 'CROSS_COMPILE' (makefile_include.mk:16) +*** Parse error: Need an operator in 'endif' (makefile_include.mk:18) +*** Parse error: Missing dependency operator (makefile_include.mk:22) +*** Parse error: Missing dependency operator (makefile_include.mk:23) +... +\end{alltt} +The wrong \texttt{libtool} will build it all fine but when it comes to the final linking fails with +\begin{alltt} +... +cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo... +cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo... +cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo... +libtool --mode=link --tag=CC cc error.lo s_mp_invmod_fast.lo fast_mp_mo +libtool: link: cc error.lo s_mp_invmod_fast.lo s_mp_montgomery_reduce_fast0 +error.lo: file not recognized: File format not recognized +cc: error: linker command failed with exit code 1 (use -v to see invocation) +Error while executing cc error.lo s_mp_invmod_fast.lo fast_mp_montgomery0 +gmake: *** [makefile.shared:64: libtommath.la] Error 1 +\end{alltt} + +To build a shared library with OpenBSD\footnote{Tested with OpenBSD version 6.4} the GNU versions +of \texttt{make} and \texttt{libtool} are needed. +\begin{alltt} +$ sudo pkg_add gmake libtool +\end{alltt} +At this time two versions of \texttt{libtool} are installed and both are named \texttt{libtool}, +unfortunately but GNU \texttt{libtool} has been placed in \texttt{/usr/local/bin/} and the native +version in \texttt{/usr/bin/}. The path might be different in other versions of OpenBSD but both +programs differ in the output of \texttt{libtool --version} +\begin{alltt} +$ /usr/local/bin/libtool --version +libtool (GNU libtool) 2.4.2 +Written by Gordon Matzigkeit , 1996 + +Copyright (C) 2011 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +$ libtool --version +libtool (not (GNU libtool)) 1.5.26 +\end{alltt} + +The shared library should build now with +\begin{alltt} +LIBTOOL="/usr/local/bin/libtool" gmake -f makefile.shared +\end{alltt} +You might need to run a \texttt{gmake -f makefile.shared clean} first. + +\subsubsection{NetBSD} +NetBSD is not as strict as OpenBSD but still needs \texttt{gmake} to build the shared library. +\texttt{libtool} may also not exist in a fresh install. +\begin{alltt} +pkg_add gmake libtool +\end{alltt} +Please check with \texttt{libtool --version} that installed libtool is indeed a GNU libtool. +Build the shared library by typing: +\begin{alltt} +gmake -f makefile.shared +\end{alltt} + +\subsection{Testing} +To build the library and the test harness type + +\begin{alltt} +make test +\end{alltt} + +This will build the library, \texttt{test} and \texttt{mtest/mtest}. The \texttt{test} program +will accept test vectors and verify the results. \texttt{mtest/mtest} will generate test vectors +using the MPI library by Michael Fromberger\footnote{A copy of MPI is included in the package}. +Simply pipe \texttt{mtest} into \texttt{test} using + +\begin{alltt} +mtest/mtest | test +\end{alltt} + +If you do not have a \texttt{/dev/urandom} style RNG source you will have to write your own PRNG +and simply pipe that into \texttt{mtest}. For example, if your PRNG program is called +\texttt{myprng} simply invoke + +\begin{alltt} +myprng | mtest/mtest | test +\end{alltt} + +This will output a row of numbers that are increasing. Each column is a different test (such as +addition, multiplication, etc) that is being performed. The numbers represent how many times the +test was invoked. If an error is detected the program will exit with a dump of the relevant +numbers it was working with. + +\section{Build Configuration} +LibTomMath can configured at build time in two phases we shall call ``depends'' and +``trims''. Each phase changes how the library is built and they are applied one after another +respectively. + +To make the system more powerful you can tweak the build process. Classes are defined in the file +\texttt{tommath\_superclass.h}. By default, the symbol \texttt{LTM\_ALL} shall be defined which +simply instructs the system to build all of the functions. This is how LibTomMath used to be +packaged. This will give you access to every function LibTomMath offers. + +However, there are cases where such a build is not optional. For instance, you want to perform RSA +operations. You don't need the vast majority of the library to perform these operations. Aside +from \texttt{LTM\_ALL} there is another pre--defined class \texttt{SC\_RSA\_1} which works in +conjunction with the RSA from LibTomCrypt. Additional classes can be defined base on the need of +the user. + +\subsection{Build Depends} +In the file \texttt{tommath\_class.h} you will see a large list of C ``defines'' followed by a +series of ``ifdefs'' which further define symbols. All of the symbols (technically they're macros +$\ldots$) represent a given C source file. For instance, \texttt{MP\_ADD\_C} represents the file +\texttt{mp\_add.c}. When a define has been enabled the function in the respective file will be +compiled and linked into the library. Accordingly when the define is absent the file will not be +compiled and not contribute any size to the library. + +You will also note that the header \texttt{tommath\_class.h} is actually recursively included (it +includes itself twice). This is to help resolve as many dependencies as possible. In the last pass +the symbol \texttt{LTM\_LAST} will be defined. This is useful for ``trims''. + +Note that the configuration system relies +on dead code elimination. Unfortunately this can result in linking errors on compilers which +perform insufficient dead code elimination. In particular MSVC with the /Od option enabled shows this issue. +The issue can be resolved by passing the /O option instead to the compiler. + +\subsection{Build Trims} +A trim is a manner of removing functionality from a function that is not required. For instance, +to perform RSA cryptography you only require exponentiation with odd moduli so even moduli support +can be safely removed. Build trims are meant to be defined on the last pass of the configuration +which means they are to be defined only if \texttt{LTM\_LAST} has been defined. + +\subsubsection{Moduli Related} +\begin{small} + \begin{center} + \begin{tabular}{|l|l|} + \hline \textbf{Restriction} & \textbf{Undefine} \\ + \hline Exponentiation with odd moduli only & S\_MP\_EXPTMOD\_C \\ + & MP\_REDUCE\_C \\ + & MP\_REDUCE\_SETUP\_C \\ + & S\_MP\_MUL\_HIGH\_DIGS\_C \\ + & FAST\_S\_MP\_MUL\_HIGH\_DIGS\_C \\ + \hline Exponentiation with random odd moduli & (The above plus the following) \\ + & MP\_REDUCE\_2K\_C \\ + & MP\_REDUCE\_2K\_SETUP\_C \\ + & MP\_REDUCE\_IS\_2K\_C \\ + & MP\_DR\_IS\_MODULUS\_C \\ + & MP\_DR\_REDUCE\_C \\ + & MP\_DR\_SETUP\_C \\ + \hline Modular inverse odd moduli only & MP\_INVMOD\_SLOW\_C \\ + \hline Modular inverse (both, smaller/slower) & FAST\_MP\_INVMOD\_C \\ + \hline + \end{tabular} + \end{center} +\end{small} + +\subsubsection{Operand Size Related} +\begin{small} + \begin{center} + \begin{tabular}{|l|l|} + \hline \textbf{Restriction} & \textbf{Undefine} \\ + \hline Moduli $\le 2560$ bits & MP\_MONTGOMERY\_REDUCE\_C \\ + & S\_MP\_MUL\_DIGS\_C \\ + & S\_MP\_MUL\_HIGH\_DIGS\_C \\ + & S\_MP\_SQR\_C \\ + \hline Polynomial Schmolynomial & MP\_KARATSUBA\_MUL\_C \\ + & MP\_KARATSUBA\_SQR\_C \\ + & MP\_TOOM\_MUL\_C \\ + & MP\_TOOM\_SQR\_C \\ + + \hline + \end{tabular} + \end{center} +\end{small} + +\section{Purpose of LibTomMath} +Unlike GNU MP (GMP) Library, LIP, OpenSSL or various other commercial kits (Miracl), LibTomMath +was not written with bleeding edge performance in mind. First and foremost LibTomMath was written +to be entirely open. Not only is the source code public domain (unlike various other GPL/etc +licensed code), not only is the code freely downloadable but the source code is also accessible for +computer science students attempting to learn ``BigNum'' or multiple precision arithmetic +techniques. + +LibTomMath was written to be an instructive collection of source code. This is why there are many +comments, only one function per source file and often I use a ``middle-road'' approach where I +don't cut corners for an extra 2\% speed increase. + +Source code alone cannot really teach how the algorithms work which is why I also wrote a textbook +that accompanies the library (beat that!). + +So you may be thinking ``should I use LibTomMath?'' and the answer is a definite maybe. Let me +tabulate what I think are the pros and cons of LibTomMath by comparing it to the math routines from +GnuPG\footnote{GnuPG v1.2.3 versus LibTomMath v0.28}. + +\newpage\begin{figure}[h] + \begin{small} + \begin{center} + \begin{tabular}{|p{4.5cm}|c|c|p{4.5cm}|} + \hline \textbf{Criteria} & \textbf{Pro} & \textbf{Con} & \textbf{Notes} + \\ + \hline Few lines of code per file & X & & GnuPG $ = 300.9$ + \\ + & & & LibTomMath $ = + 71.97$\hfill + \\ + \hline Commented function prototypes & X & & GnuPG function + names are cryptic. + \\ + \hline Speed & & X & LibTomMath is + slower. + \\ + \hline Totally free & X & & GPL has + unfavourable restrictions. + \\ + \hline Large function base & X & & GnuPG is + barebones. + \\ + \hline Five modular reduction algorithms & X & & Faster modular + exponentiation for a variety of + moduli. + \\ + \hline Portable & X & & GnuPG requires + configuration to build. + \\ + \hline + \end{tabular} + \end{center} + \end{small} + \caption{LibTomMath Valuation} +\end{figure} + +It may seem odd to compare LibTomMath to GnuPG since the math in GnuPG is only a small portion of +the entire application. However, LibTomMath was written with cryptography in mind. It provides +essentially all of the functions a cryptosystem would require when working with large integers. + +So it may feel tempting to just rip the math code out of GnuPG (or GnuMP where it was taken from +originally) in your own application but I think there are reasons not to. While LibTomMath is +slower than libraries such as GnuMP it is not normally significantly slower. On x86 machines the +difference is normally a factor of two when performing modular exponentiations. It depends largely +on the processor, compiler and the moduli being used. + +Essentially the only time you wouldn't use LibTomMath is when blazing speed is the primary concern. +However, on the other side of the coin LibTomMath offers you a totally free (public domain) well +structured math library that is very flexible, complete and performs well in resource constrained +environments. Fast RSA for example can be performed with as little as 8 Kibibytes of RAM for data +(again depending on build options). + +\chapter{Getting Started with LibTomMath} +\section{Building Programs} +In order to use LibTomMath you must include ``tommath.h'' and link against the appropriate library +file (typically +libtommath.a). There is no library initialization required and the entire library is thread safe. + +\section{Return Codes} +There are five possible return codes a function may return. + +\index{MP\_OKAY}\index{MP\_VAL}\index{MP\_MEM}\index{MP\_ITER}\index{MP\_BUF} +\begin{figure}[h!] + \begin{center} + \begin{small} + \begin{tabular}{|l|l|} + \hline \textbf{Code} & \textbf{Meaning} \\ + \hline MP\_OKAY & The function succeeded. \\ + \hline MP\_VAL & The function input was invalid. \\ + \hline MP\_MEM & Heap memory exhausted. \\ + \hline MP\_ITER & Maximum iterations reached. \\ + \hline MP\_BUF & Buffer overflow, supplied buffer too small. \\ + \hline + \end{tabular} + \end{small} + \end{center} + \caption{Return Codes} +\end{figure} + +The error codes \texttt{MP\_OKAY},\texttt{MP\_VAL}, \texttt{MP\_MEM}, \texttt{MP\_ITER}, and +\texttt{MP\_BUF} are of the type \texttt{mp\_err}. + +The last two codes listed are not actually ``return'ed'' by a function. They are placed in an +integer (the caller must provide the address of an integer it can store to) which the caller can +access. To convert one of the three return codes to a string use the following function. + +\index{mp\_error\_to\_string} +\begin{alltt} +char *mp_error_to_string(mp_err code); +\end{alltt} + +This will return a pointer to a string which describes the given error code. + +\section{Data Types} +The basic ``multiple precision integer'' type is known as the \texttt{mp\_int} within LibTomMath. +This data type is used to organize all of the data required to manipulate the integer it +represents. Within LibTomMath it has been prototyped as the following. + +\index{mp\_int} +\begin{alltt} +typedef struct \{ + int used, alloc; + mp_sign sign; + mp_digit *dp; +\} mp_int; +\end{alltt} + +Where \texttt{mp\_digit} is a data type that represents individual digits of the integer. By +default, an \texttt{mp\_digit} is the ISO C \texttt{unsigned long} data type and each digit is +$28-$bits long. The \texttt{mp\_digit} type can be configured to suit other platforms by defining +the appropriate macros. + +All LTM functions that use the \texttt{mp\_int} type will expect a pointer to \texttt{mp\_int} +structure. You must allocate memory to hold the structure itself by yourself (whether off stack or +heap it doesn't matter). The very first thing that must be done to use an \texttt{mp\_int} is that +it must be initialized. + +\section{Function Organization} + +The arithmetic functions of the library are all organized to have the same style prototype. That +is source operands are passed on the left and the destination is on the right. For instance, +\begin{alltt} +mp_add(&a, &b, &c); /* c = a + b */ +mp_mul(&a, &a, &c); /* c = a * a */ +mp_div(&a, &b, &c, &d); /* c = [a/b], d = a mod b */ +\end{alltt} + +Another feature of the way the functions have been implemented is that source operands can be +destination operands as well. For instance, + +\begin{alltt} +mp_add(&a, &b, &b); /* b = a + b */ +mp_div(&a, &b, &a, &c); /* a = [a/b], c = a mod b */ +\end{alltt} + +This allows operands to be re--used which can make programming simpler. + +\section{Initialization} +\subsection{Single Initialization} +A single \texttt{mp\_int} can be initialized with the \texttt{mp\_init} function. + +\index{mp\_init} +\begin{alltt} +mp_err mp_init (mp_int *a); +\end{alltt} + +This function expects a pointer to an \texttt{mp\_int} structure and will initialize the members +of the structure so the \texttt{mp\_int} represents the default integer which is zero. If the +functions returns \texttt{MP\_OKAY} then the \texttt{mp\_int} is ready to be used by the other +LibTomMath functions. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + return EXIT_SUCCESS; +\} + \end{alltt} +\end{small} + +\subsection{Single Free} +When you are finished with an \texttt{mp\_int} it is ideal to return the heap it used back to the +system. The following function provides this functionality. +\index{mp\_clear} +\begin{alltt} +void mp_clear (mp_int *a); +\end{alltt} + +The function expects a pointer to a previously initialized \texttt{mp\_int} structure and frees the +heap it uses. It sets the pointer\footnote{The \texttt{dp} member.} within the \texttt{mp\_int} to +\texttt{NULL} which is used to prevent double free situations. Is is legal to call +\texttt{mp\_clear} twice on the same \texttt{mp\_int} in a row. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + /* We're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} + \end{alltt} +\end{small} + +\subsection{Multiple Initializations} +Certain algorithms require more than one large integer. In these instances it is ideal to +initialize all of the \texttt{mp\_int} variables in an ``all or nothing'' fashion. That is, they +are either all initialized successfully or they are all not initialized. + +The \texttt{mp\_init\_multi} function provides this functionality. + +\index{mp\_init\_multi} \index{mp\_clear\_multi} +\begin{alltt} +mp_err mp_init_multi(mp_int *mp, ...); +\end{alltt} + +It accepts a \texttt{NULL} terminated list of pointers to \texttt{mp\_int} structures. It will +attempt to initialize them all at once. If the function returns \texttt{MP\_OKAY} then all of the +\texttt{mp\_int} variables are ready to use, otherwise none of them are available for use. + +A complementary \texttt{mp\_clear\_multi} function allows multiple \texttt{mp\_int} variables to be +free'd +from the heap at the same time. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int num1, num2, num3; + mp_err result; + + if ((result = mp_init_multi(&num1, + &num2, + &num3, NULL)) != MP\_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the numbers */ + + /* We're done with them. */ + mp_clear_multi(&num1, &num2, &num3, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +\subsection{Other Initializers} +To initialized and make a copy of an \texttt{mp\_int} the \texttt{mp\_init\_copy} function has been +provided. + +\index{mp\_init\_copy} +\begin{alltt} +mp_err mp_init_copy (mp_int *a, mp_int *b); +\end{alltt} + +This function will initialize $a$ and make it a copy of $b$ if all goes well. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int num1, num2; + mp_err result; + + /* initialize and do work on num1 ... */ + + /* We want a copy of num1 in num2 now */ + if ((result = mp_init_copy(&num2, &num1)) != MP_OKAY) \{ + printf("Error initializing the copy. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now num2 is ready and contains a copy of num1 */ + + /* We're done with them. */ + mp_clear_multi(&num1, &num2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +Another less common initializer is \texttt{mp\_init\_size} which allows the user to initialize an +\texttt{mp\_int} with a given default number of digits. By default, all initializers allocate +\texttt{MP\_PREC} digits. This function lets you override this behaviour. + +\index{mp\_init\_size} +\begin{alltt} +mp_err mp_init_size (mp_int *a, int size); +\end{alltt} + +The $size$ parameter must be greater than zero. If the function succeeds the \texttt{mp\_int} $a$ +will be initialized to have $size$ digits (which are all initially zero). + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + /* we need a 60-digit number */ + if ((result = mp_init_size(&number, 60)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +\section{Maintenance Functions} +\subsection{Clear Leading Zeros} + +This is used to ensure that leading zero digits are trimmed and the leading "used" digit will be +non--zero. It also fixes the sign if there are no more leading digits. + +\index{mp\_clamp} +\begin{alltt} +void mp_clamp(mp_int *a); +\end{alltt} + +\subsection{Zero Out} + +This function will set the ``bigint'' to zeros without changing the amount of allocated memory. + +\index{mp\_zero} +\begin{alltt} +void mp_zero(mp_int *a); +\end{alltt} + +\subsection{Reducing Memory Usage} +When an \texttt{mp\_int} is in a state where it won't be changed again\footnote{A Diffie--Hellman + modulus for instance.} excess digits can be removed to return memory to the heap with the +\texttt{mp\_shrink} function. + +\index{mp\_shrink} +\begin{alltt} +mp_err mp_shrink (mp_int *a); +\end{alltt} + +This will remove excess digits of the \texttt{mp\_int} $a$. If the operation fails the +\texttt{mp\_int} should be intact without the excess digits being removed. Note that you can use a +shrunk \texttt{mp\_int} in further computations, however, such operations will require heap +operations which can be slow. It is not ideal to shrink \texttt{mp\_int} variables that you will +further modify in the system (unless you are seriously low on memory). + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number [e.g. pre-computation] */ + + /* We're done with it for now. */ + if ((result = mp_shrink(&number)) != MP_OKAY) \{ + printf("Error shrinking the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use it .... */ + + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +\subsection{Adding additional digits} + +Within the mp\_int structure are two parameters which control the limitations of the array of +digits that represent the integer the mp\_int is meant to equal. The \texttt{used} parameter +dictates how many digits are significant, that is, contribute to the value of the mp\_int. The +\texttt{alloc} parameter dictates how many digits are currently available in the array. If you +need to perform an operation that requires more digits you will have to \texttt{mp\_grow} the +\texttt{mp\_int} to your desired size. + +\index{mp\_grow} +\begin{alltt} +mp_err mp_grow (mp_int *a, int size); +\end{alltt} + +This will grow the array of digits of $a$ to $size$. If the \texttt{alloc} parameter is already +bigger than $size$ the function will not do anything. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* use the number */ + + /* We need to add 20 digits to the number */ + if ((result = mp_grow(&number, number.alloc + 20)) != MP_OKAY) \{ + printf("Error growing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + + /* use the number */ + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +\chapter{Basic Operations} +\section{Copying} + +A so called ``deep copy'', where new memory is allocated and all contents of $a$ are copied +verbatim into $b$ such that $b = a$ at the end. + +\index{mp\_copy} +\begin{alltt} +mp_err mp_copy (const mp_int *a, mp_int *b); +\end{alltt} + +You can also just swap $a$ and $b$. It does the normal pointer changing with a temporary pointer +variable, just that you do not have to. + +\index{mp\_exch} +\begin{alltt} +void mp_exch (mp_int *a, mp_int *b); +\end{alltt} + +\section{Bit Counting} + +To get the position of the lowest bit set (LSB, the Lowest Significant Bit; the number of bits +which are zero before the first zero bit ) + +\index{mp\_cnt\_lsb} +\begin{alltt} +int mp_cnt_lsb(const mp_int *a); +\end{alltt} + +To get the position of the highest bit set (MSB, the Most Significant Bit; the number of bits in +the ``bignum'') + +\index{mp\_count\_bits} +\begin{alltt} +int mp_count_bits(const mp_int *a); +\end{alltt} + +\section{Small Constants} +Setting an \texttt{mp\_int} to a small constant is a relatively common operation. To accommodate +these instances there is a small constant assignment function. This function is used to set a +single digit constant. The reason for this function is efficiency. Setting a single digit is quick +but the domain of a digit can change (it's always at least $0 \ldots 127$). + +\subsection{Single Digit} + +Setting a single digit can be accomplished with the following function. + +\index{mp\_set} +\begin{alltt} +void mp_set (mp_int *a, mp_digit b); +\end{alltt} + +This will zero the contents of $a$ and make it represent an integer equal to the value of $b$. Note +that this function has a return type of \texttt{void}. It cannot cause an error so it is safe to +assume the function succeeded. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 5 */ + mp_set(&number, 5); + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +\subsection{Int32 and Int64 Constants} + +These functions can be used to set a constant with 32 or 64 bits. + +\index{mp\_set\_i32} \index{mp\_set\_u32} +\index{mp\_set\_i64} \index{mp\_set\_u64} +\begin{alltt} +void mp_set_i32 (mp_int *a, int32_t b); +void mp_set_u32 (mp_int *a, uint32_t b); +void mp_set_i64 (mp_int *a, int64_t b); +void mp_set_u64 (mp_int *a, uint64_t b); +\end{alltt} + +These functions assign the sign and value of the input $b$ to the big integer $a$. +The value can be obtained again by calling the following functions. + +\index{mp\_get\_i32} \index{mp\_get\_u32} \index{mp\_get\_mag\_u32} +\index{mp\_get\_i64} \index{mp\_get\_u64} \index{mp\_get\_mag\_u64} +\begin{alltt} +int32_t mp_get_i32 (const mp_int *a); +uint32_t mp_get_u32 (const mp_int *a); +uint32_t mp_get_mag_u32 (const mp_int *a); +int64_t mp_get_i64 (const mp_int *a); +uint64_t mp_get_u64 (const mp_int *a); +uint64_t mp_get_mag_u64 (const mp_int *a); +\end{alltt} + +These functions return the 32 or 64 least significant bits of $a$ respectively. The unsigned +functions return negative values in a twos complement representation. The absolute value or +magnitude can be obtained using the \texttt{mp\_get\_mag*} functions. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 654321 (note this is bigger than 127) */ + mp_set_u32(&number, 654321); + + printf("number == \%" PRIi32 "\textbackslash{}n", mp_get_i32(&number)); + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +This should output the following if the program succeeds. + +\begin{alltt} +number == 654321 +\end{alltt} + +\subsection{Long Constants - platform dependant} + +\index{mp\_set\_l} \index{mp\_set\_ul} +\begin{alltt} +void mp_set_l (mp_int *a, long b); +void mp_set_ul (mp_int *a, unsigned long b); +\end{alltt} + +This will assign the value of the platform--dependent sized variable $b$ to the big integer $a$. + +To retrieve the value, the following functions can be used. + +\index{mp\_get\_l} \index{mp\_get\_ul} \index{mp\_get\_mag\_ul} +\begin{alltt} +long mp_get_l (const mp_int *a); +unsigned long mp_get_ul (const mp_int *a); +unsigned long mp_get_mag_ul (const mp_int *a); +\end{alltt} + +This will return the least significant bits of the big integer $a$ that fit into the native data +type \texttt{long}. + +\subsection{Floating Point Constants - platform dependant} + +\index{mp\_set\_double} +\begin{alltt} +mp_err mp_set_double(mp_int *a, double b); +\end{alltt} + +If the platform supports the floating point data type \texttt{double} (binary64) this function will +assign the integer part of \texttt{b} to the big integer $a$. This function will return +\texttt{MP\_VAL} if \texttt{b} is \texttt{+/-inf} or \texttt{NaN}. + +To convert a big integer to a \texttt{double} use + +\index{mp\_get\_double} +\begin{alltt} +double mp_get_double(const mp_int *a); +\end{alltt} + +\subsection{Initialize and Setting Constants} +To both initialize and set small constants the following nine functions are available. +\index{mp\_init\_set} \index{mp\_init\_i32} \index{mp\_init\_i64} \index{mp\_init\_u32} \index{mp\_init\_u64} +\index{mp\_init\_l} \index{mp\_init\_ul} +\begin{alltt} +mp_err mp_init_set (mp_int *a, mp_digit b); +mp_err mp_init_i32 (mp_int *a, int32_t b); +mp_err mp_init_u32 (mp_int *a, uint32_t b); +mp_err mp_init_i64 (mp_int *a, int64_t b); +mp_err mp_init_u64 (mp_int *a, uint64_t b); +mp_err mp_init_l (mp_int *a, long b); +mp_err mp_init_ul (mp_int *a, unsigned long b); +\end{alltt} + +Both functions work like the previous counterparts except they first initialize $a$ with the +function \texttt{mp\_init} before setting the values. +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number1, number2; + mp_err result; + + /* initialize and set a single digit */ + if ((result = mp_init_set(&number1, 100)) != MP_OKAY) \{ + printf("Error setting number1: \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* initialize and set a long */ + if ((result = mp_init_l(&number2, 1023)) != MP_OKAY) \{ + printf("Error setting number2: \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* display */ + printf("Number1, Number2 == \%" PRIi32 ", \%" PRIi32 "\textbackslash{}n", + mp_get_i32(&number1), mp_get_i32(&number2)); + + /* clear */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +If this program succeeds it shall output. +\begin{alltt} +Number1, Number2 == 100, 1023 +\end{alltt} + +\section{Comparisons} + +Comparisons in LibTomMath are always performed in a ``left to right'' fashion. There are three +possible return codes for any comparison. + +\index{MP\_GT} \index{MP\_EQ} \index{MP\_LT} +\begin{figure}[h] + \begin{center} + \begin{tabular}{|c|c|} + \hline \textbf{Result Code} & \textbf{Meaning} \\ + \hline MP\_GT & $a > b$ \\ + \hline MP\_EQ & $a = b$ \\ + \hline MP\_LT & $a < b$ \\ + \hline + \end{tabular} + \end{center} + \caption{Comparison Codes for $a, b$} + \label{fig:CMP} +\end{figure} + +In figure \ref{fig:CMP} two integers $a$ and $b$ are being compared. In this case $a$ is said to +be ``to the left'' of $b$. The return codes are of type \texttt{mp\_ord}. + +\subsection{Unsigned comparison} + +An unsigned comparison considers only the digits themselves and not the associated \texttt{sign} +flag of the \texttt{mp\_int} structures. This is analogous to an absolute comparison. The +function \texttt{mp\_cmp\_mag} will compare two \texttt{mp\_int} variables based on their digits +only. + +\index{mp\_cmp\_mag} +\begin{alltt} +mp_ord mp_cmp_mag(mp_int *a, mp_int *b); +\end{alltt} +This will compare $a$ to $b$ placing $a$ to the left of $b$. This function cannot fail and will +return one of the three compare codes listed in figure \ref{fig:CMP}. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number1, number2; + mp_err result; + + if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number1 to 5 */ + mp_set(&number1, 5); + + /* set the number2 to -6 */ + mp_set(&number2, 6); + if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{ + printf("Error negating number2. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + switch(mp_cmp_mag(&number1, &number2)) \{ + case MP_GT: printf("|number1| > |number2|"); break; + case MP_EQ: printf("|number1| = |number2|"); break; + case MP_LT: printf("|number1| < |number2|"); break; + \} + + /* we're done with it. */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +If this program\footnote{This function uses the \texttt{mp\_neg} function which is discussed in + section \ref{sec:NEG}.} completes successfully it should print the following. + +\begin{alltt} +|number1| < |number2| +\end{alltt} + +This is because $\vert -6 \vert = 6$ and obviously $5 < 6$. + +\subsection{Signed comparison} + +To compare two \texttt{mp\_int} variables based on their signed value the \texttt{mp\_cmp} function +is provided. + +\index{mp\_cmp} +\begin{alltt} +mp_ord mp_cmp(mp_int *a, mp_int *b); +\end{alltt} + +This will compare $a$ to the left of $b$. It will first compare the signs of the two +\texttt{mp\_int} variables. If they differ it will return immediately based on their signs. If +the signs are equal then it will compare the digits individually. This function will return one of +the compare conditions codes listed in figure \ref{fig:CMP}. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number1, number2; + mp_err result; + + if ((result = mp_init_multi(&number1, &number2, NULL)) != MP_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number1 to 5 */ + mp_set(&number1, 5); + + /* set the number2 to -6 */ + mp_set(&number2, 6); + if ((result = mp_neg(&number2, &number2)) != MP_OKAY) \{ + printf("Error negating number2. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + switch(mp_cmp(&number1, &number2)) \{ + case MP_GT: printf("number1 > number2"); break; + case MP_EQ: printf("number1 = number2"); break; + case MP_LT: printf("number1 < number2"); break; + \} + + /* we're done with it. */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +If this program\footnote{This function uses the \texttt{mp\_neg} function which is discussed in + section \ref{sec:NEG}.} completes successfully it should print the following. + +\begin{alltt} +number1 > number2 +\end{alltt} + +\subsection{Single Digit} + +To compare a single digit against an \texttt{mp\_int} the following function has been provided. + +\index{mp\_cmp\_d} +\begin{alltt} +mp_ord mp_cmp_d(mp_int *a, mp_digit b); +\end{alltt} + +This will compare $a$ to the left of $b$ using a signed comparison. Note that it will always +treat$b$ as positive. This function is rather handy when you have to compare against small values +such as $1$ (which often comes up in cryptography). The function cannot fail and will return one +of the tree compare condition codes listed in figure \ref{fig:CMP}. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 5 */ + mp_set(&number, 5); + + switch(mp_cmp_d(&number, 7)) \{ + case MP_GT: printf("number > 7"); break; + case MP_EQ: printf("number = 7"); break; + case MP_LT: printf("number < 7"); break; + \} + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +If this program functions properly it will print out the following. + +\begin{alltt} +number < 7 +\end{alltt} + +\section{Logical Operations} + +Logical operations are operations that can be performed either with simple shifts or boolean +operators such as AND, XOR and OR directly. These operations are very quick. + +\subsection{Multiplication by two} + +Multiplications and divisions by any power of two can be performed with quick logical shifts either +left or right depending on the operation. + +When multiplying or dividing by two a special case routine can be used which are as follows. +\index{mp\_mul\_2} \index{mp\_div\_2} +\begin{alltt} +mp_err mp_mul_2(const mp_int *a, mp_int *b); +mp_err mp_div_2(const mp_int *a, mp_int *b); +\end{alltt} + +The former will assign twice $a$ to $b$ while the latter will assign half $a$ to $b$. These +functions are fast since the shift counts and masks are hardcoded into the routines. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number; + mp_err result; + + if ((result = mp_init(&number)) != MP_OKAY) \{ + printf("Error initializing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the number to 5 */ + mp_set(&number, 5); + + /* multiply by two */ + if ((result = mp\_mul\_2(&number, &number)) != MP_OKAY) \{ + printf("Error multiplying the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + switch(mp_cmp_d(&number, 7)) \{ + case MP_GT: printf("2*number > 7"); break; + case MP_EQ: printf("2*number = 7"); break; + case MP_LT: printf("2*number < 7"); break; + \} + + /* now divide by two */ + if ((result = mp\_div\_2(&number, &number)) != MP_OKAY) \{ + printf("Error dividing the number. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + switch(mp_cmp_d(&number, 7)) \{ + case MP_GT: printf("2*number/2 > 7"); break; + case MP_EQ: printf("2*number/2 = 7"); break; + case MP_LT: printf("2*number/2 < 7"); break; + \} + + /* we're done with it. */ + mp_clear(&number); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +If this program is successful it will print out the following text. + +\begin{alltt} +2*number > 7 +2*number/2 < 7 +\end{alltt} + +Since $10 > 7$ and $5 < 7$. + +To multiply by a power of two the following function can be used. + +\index{mp\_mul\_2d} +\begin{alltt} +mp_err mp_mul_2d(const mp_int *a, int b, mp_int *c); +\end{alltt} + +This will multiply $a$ by $2^b$ and store the result in $c$. If the value of $b$ is less than or +equal to zero the function will copy $a$ to $c$ without performing any further actions. The +multiplication itself is implemented as a right--shift operation of $a$ by $b$ bits. To divide by a +power of two use the following. + +\index{mp\_div\_2d} +\begin{alltt} +mp_err mp_div_2d (const mp_int *a, int b, mp_int *c, mp_int *d); +\end{alltt} +Which will divide $a$ by $2^b$, store the quotient in $c$ and the remainder in $d$. If $b \le 0$ +then the function simply copies $a$ over to $c$ and zeroes $d$. The variable $d$ may be +passed as a \texttt{NULL} value to signal that the remainder is not desired. The division itself +is implemented as a left--shift operation of $a$ by $b$ bits. + +It is also not very uncommon to need just the power of two $2^b$; for example as a start--value +for +the Newton method. + +\index{mp\_2expt} +\begin{alltt} +mp_err mp_2expt(mp_int *a, int b); +\end{alltt} +It is faster than doing it by shifting $1$ with \texttt{mp\_mul\_2d}. + +\subsection{Polynomial Basis Operations} + +Strictly speaking the organization of the integers within the mp\_int structures is what is known +as a ``polynomial basis''. This simply means a field element is stored by divisions of a radix. +For example, if $f(x) = \sum_{i=0}^{k} y_ix^k$ for any vector $\vec y$ then the array of digits in +$\vec y$ are said to be the polynomial basis representation of $z$ if $f(\beta) = z$ for a given +radix $\beta$. + +To multiply by the polynomial $g(x) = x$ all you have todo is shift the digits of the basis left +one place. The following function provides this operation. + +\index{mp\_lshd} +\begin{alltt} +mp_err mp_lshd (mp_int *a, int b); +\end{alltt} + +This will multiply $a$ in place by $x^b$ which is equivalent to shifting the digits left $b$ places +and inserting zeroes in the least significant digits. Similarly to divide by a power of $x$ the +following function is provided. + +\index{mp\_rshd} +\begin{alltt} +void mp_rshd (mp_int *a, int b) +\end{alltt} +This will divide $a$ in place by $x^b$ and discard the remainder. This function cannot fail as it +performs the operations in place and no new digits are required to complete it. + +\subsection{AND, OR, XOR and COMPLEMENT Operations} + +While AND, OR and XOR operations compute arbitrary--precision bitwise operations. Negative numbers +are treated as if they are in two--complement representation, while internally they are +sign--magnitude however. + +\index{mp\_or} \index{mp\_and} \index{mp\_xor} \index{mp\_complement} \index{mp\_signed\_rsh} +\begin{alltt} +mp_err mp_or (const mp_int *a, mp_int *b, mp_int *c); +mp_err mp_and (const mp_int *a, mp_int *b, mp_int *c); +mp_err mp_xor (const mp_int *a, mp_int *b, mp_int *c); +mp_err mp_complement(const mp_int *a, mp_int *b); +mp_err mp_signed_rsh(const mp_int *a, int b, mp_int *c, mp_int *d); +\end{alltt} + +The function \texttt{mp\_complement} computes a two--complement $b = \sim a$. The function +\texttt{mp\_signed\_rsh} performs sign extending right shift. For positive numbers it is equivalent +to \texttt{mp\_div\_2d}. +\section{Addition and Subtraction} + +To compute an addition or subtraction the following two functions can be used. + +\index{mp\_add} \index{mp\_sub} +\begin{alltt} +mp_err mp_add (const mp_int *a, const mp_int *b, mp_int *c); +mp_err mp_sub (const mp_int *a, const mp_int *b, mp_int *c) +\end{alltt} + +Which perform $c = a \odot b$ where $\odot$ is one of signed addition or subtraction. The +operations are fully sign aware. + +\section{Sign Manipulation} +\subsection{Negation} +\label{sec:NEG} +Simple integer negation can be performed with the following. + +\index{mp\_neg} +\begin{alltt} +mp_err mp_neg (const mp_int *a, mp_int *b); +\end{alltt} + +Which assigns $-a$ to $b$. + +\subsection{Absolute} +Simple integer absolutes can be performed with the following. + +\index{mp\_abs} +\begin{alltt} +mp_err mp_abs (const mp_int *a, mp_int *b); +\end{alltt} + +Which assigns $\vert a \vert$ to $b$. + +\section{Integer Division and Remainder} +To perform a complete and general integer division with remainder use the following function. + +\index{mp\_div} +\begin{alltt} +mp_err mp_div (const mp_int *a, const mp_int *b, mp_int *c, mp_int *d); +\end{alltt} + +This divides $a$ by $b$ and stores the quotient in $c$ and $d$. The signed quotient is computed +such that $bc + d = a$. Note that either of $c$ or $d$ can be set to \texttt{NULL} if their value +is not required. If $b$ is zero the function returns \texttt{MP\_VAL}. + +\section{Hashing} +To get a non-cryptographic hash of an \texttt{mp\_int} use the following function. + +\index{mp\_hash} +\begin{alltt} +mp_err mp_hash (mp_int *a, mp_hval *hash); +\end{alltt} + +This will create the hash of $a$ following the \mbox{FNV-1a} algorithm as described on +\url{http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-1a}. With the +help of this function one can use an \texttt{mp\_int} as a key in a hash table. + +NB: The hashing is not stable over different widths of an \texttt{mp\_digit}. + +\chapter{Multiplication and Squaring} +\section{Multiplication} +A full signed integer multiplication can be performed with the following. +\index{mp\_mul} +\begin{alltt} +mp_err mp_mul (const mp_int *a, const mp_int *b, mp_int *c); +\end{alltt} +Which assigns the full signed product $ab$ to $c$. This function actually breaks into one of four +cases which are specific multiplication routines optimized for given parameters. First there are +the Toom--Cook multiplications which should only be used with very large inputs. This is followed +by the Karatsuba multiplications which are for moderate sized inputs. Then followed by the Comba +and baseline multipliers. + +Fortunately for the developer you don't really need to know this unless you really want to fine +tune the system. The function \texttt{mp\_mul} will determine on its own\footnote{Some tweaking may + be required but \texttt{make tune} will put some reasonable values in \texttt{bncore.c}} what +routine to use automatically when it is called. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int number1, number2; + mp_err result; + + /* Initialize the numbers */ + if ((result = mp_init_multi(&number1, + &number2, NULL)) != MP_OKAY) \{ + printf("Error initializing the numbers. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* set the terms */ + mp_set_i32(&number, 257); + mp_set_i32(&number2, 1023); + + /* multiply them */ + if ((result = mp_mul(&number1, &number2, + &number1)) != MP_OKAY) \{ + printf("Error multiplying terms. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* display */ + printf("number1 * number2 == \%" PRIi32, mp_get_i32(&number1)); + + /* free terms and return */ + mp_clear_multi(&number1, &number2, NULL); + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +If this program succeeds it shall output the following. + +\begin{alltt} +number1 * number2 == 262911 +\end{alltt} + +\section{Squaring} +Since squaring can be performed faster than multiplication it is performed it's own function +instead of just using +\texttt{mp\_mul}. + +\index{mp\_sqr} +\begin{alltt} +mp_err mp_sqr (const mp_int *a, mp_int *b); +\end{alltt} + +Will square $a$ and store it in $b$. Like the case of multiplication there are four different +squaring algorithms all which can be called from the function \texttt{mp\_sqr}. It is ideal to use +\texttt{mp\_sqr} over \texttt{mp\_mul} when squaring terms because of the speed difference. + +\section{Tuning Polynomial Basis Routines} + +Both of the Toom--Cook and Karatsuba multiplication algorithms are faster than the traditional +$O(n^2)$ approach that the Comba and baseline algorithms use. At $O(n^{1.464973})$ and +$O(n^{1.584962})$ running times respectively they require considerably less work. For example, a +$10\,000$-digit multiplication would take roughly $724\,000$ single precision multiplications with +Toom--Cook or $100\,000\,000$ single precision multiplications with the standard Comba (a factor of +$138$). + +So why not always use Karatsuba or Toom--Cook? The simple answer is that they have so much +overhead that they're not actually faster than Comba until you hit distinct ``cutoff'' points. +For Karatsuba with the default configuration, GCC 3.3.1 and an Athlon XP processor the cutoff point +is roughly 110 digits (about 70 for the Intel P4). That is, at 110 digits Karatsuba and Comba +multiplications just about break even and for 110+ digits Karatsuba is faster. + +To get reasonable values for the cut--off points for your architecture, type + +\begin{alltt} +make tune +\end{alltt} + +This will run a benchmark, computes the medians, rewrites \texttt{bncore.c}, and recompiles +\texttt{bncore.c} and relinks the library. + +The benchmark itself can be fine--tuned in the file \texttt{etc/tune\_it.sh}. + +The program \texttt{etc/tune} is also able to print a list of values for printing curves with e.g.: +\texttt{gnuplot}. type \texttt{./etc/tune -h} to get a list of all available options. + +\chapter{Modular Reduction} + +Modular reduction is process of taking the remainder of one quantity divided by another. Expressed +as (\ref{eqn:mod}) the modular reduction is equivalent to the remainder of $b$ divided by $c$. + +\begin{equation} + a \equiv b \mbox{ (mod }c\mbox{)} + \label{eqn:mod} +\end{equation} + +Of particular interest to cryptography are reductions where $b$ is limited to the range $0 \le b < + c^2$ since particularly fast reduction algorithms can be written for the limited range. + +Note that one of the four optimized reduction algorithms are automatically chosen in the modular +exponentiation algorithm \texttt{mp\_exptmod} when an appropriate modulus is detected. + +\section{Straight Division} +In order to effect an arbitrary modular reduction the following algorithm is provided. + +\index{mp\_mod} +\begin{alltt} +mp_err mp_mod(const mp_int *a,const mp_int *b, mp_int *c); +\end{alltt} + +This reduces $a$ modulo $b$ and stores the result in $c$. The sign of $c$ shall agree with the +sign of $b$. This algorithm accepts an input $a$ of any range and is not limited by $0 \le a < + b^2$. + +\section{Barrett Reduction} + +Barrett reduction is a generic optimized reduction algorithm that requires pre--computation to +achieve a decent speedup over straight division. First a $\mu$ value must be precomputed with the +following function. + +\index{mp\_reduce\_setup} +\begin{alltt} +mp_err mp_reduce_setup(const mp_int *a, mp_int *b); +\end{alltt} + +Given a modulus in $b$ this produces the required $\mu$ value in $a$. For any given modulus this +only has to be computed once. Modular reduction can now be performed with the following. + +\index{mp\_reduce} +\begin{alltt} +mp_err mp_reduce(const mp_int *a, const mp_int *b, mp_int *c); +\end{alltt} + +This will reduce $a$ in place modulo $b$ with the precomputed $\mu$ value in $c$. $a$ must be in +the range +$0 \le a < b^2$. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int a, b, c, mu; + mp_err result; + + /* initialize a,b to desired values, mp_init mu, + * c and set c to 1...we want to compute a^3 mod b + */ + + /* get mu value */ + if ((result = mp_reduce_setup(&mu, b)) != MP_OKAY) \{ + printf("Error getting mu. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* square a to get c = a^2 */ + if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{ + printf("Error squaring. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' modulo b */ + if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* multiply a to get c = a^3 */ + if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' modulo b */ + if ((result = mp_reduce(&c, &b, &mu)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* c now equals a^3 mod b */ + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +This program will calculate $a^3 \mbox{ mod }b$ if all the functions succeed. + +\section{Montgomery Reduction} + +Montgomery is a specialized reduction algorithm for any odd moduli. Like Barrett reduction a +pre--computation step is required. This isaccomplished with the following. + +\index{mp\_montgomery\_setup} +\begin{alltt} +mp_err mp_montgomery_setup(const mp_int *a, mp_digit *mp); +\end{alltt} + +For the given odd moduli $a$ the precomputation value is placed in $mp$. The reduction is computed +with the following. + +\index{mp\_montgomery\_reduce} +\begin{alltt} +mp_err mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); +\end{alltt} +This reduces $a$ in place modulo $m$ with the pre--computed value $mp$. $a$ must be in the range +$0 \le a < b^2$. + +Montgomery reduction is faster than Barrett reduction for moduli smaller than the ``Comba'' limit. +With the default setup for instance, the limit is $127$ digits ($3556$--bits). Note that this +function is not limited to $127$ digits just that it falls back to a baseline algorithm after that +point. + +An important observation is that this reduction does not return $a \mbox{ mod }m$ but $aR^{-1} + \mbox{ mod }m$ where $R = \beta^n$, $n$ is the n number of digits in $m$ and $\beta$ is the radix +used (default is $2^{28}$). + +To quickly calculate $R$ the following function was provided. + +\index{mp\_montgomery\_calc\_normalization} +\begin{alltt} +mp_err mp_montgomery_calc_normalization(mp_int *a, mp_int *b); +\end{alltt} +Which calculates $a = R$ for the odd moduli $b$ without using multiplication or division. + +The normal modus operandi for Montgomery reductions is to normalize the integers before entering +the system. For example, to calculate $a^3 \mbox { mod }b$ using Montgomery reduction the value of +$a$ can be normalized by multiplying it by $R$. Consider the following code snippet. + +\begin{small} + \begin{alltt} +int main(void) +\{ + mp_int a, b, c, R; + mp_digit mp; + mp_err result; + + /* initialize a,b to desired values, + * mp_init R, c and set c to 1.... + */ + + /* get normalization */ + if ((result = mp_montgomery_calc_normalization(&R, b)) != MP_OKAY) \{ + printf("Error getting norm. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* get mp value */ + if ((result = mp_montgomery_setup(&c, &mp)) != MP_OKAY) \{ + printf("Error setting up montgomery. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* normalize `a' so now a is equal to aR */ + if ((result = mp_mulmod(&a, &R, &b, &a)) != MP_OKAY) \{ + printf("Error computing aR. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* square a to get c = a^2R^2 */ + if ((result = mp_sqr(&a, &c)) != MP_OKAY) \{ + printf("Error squaring. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' back down to c = a^2R^2 * R^-1 == a^2R */ + if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* multiply a to get c = a^3R^2 */ + if ((result = mp_mul(&a, &c, &c)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce `c' back down to c = a^3R^2 * R^-1 == a^3R */ + if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* now reduce (again) `c' back down to c = a^3R * R^-1 == a^3 */ + if ((result = mp_montgomery_reduce(&c, &b, mp)) != MP_OKAY) \{ + printf("Error reducing. \%s", + mp_error_to_string(result)); + return EXIT_FAILURE; + \} + + /* c now equals a^3 mod b */ + + return EXIT_SUCCESS; +\} +\end{alltt} +\end{small} + +This particular example does not look too efficient but it demonstrates the point of the algorithm. +By normalizing the inputs the reduced results are always of the form $aR$ for some variable $a$. +This allows a single final reduction to correct for the normalization and the fast reduction used +within the algorithm. + +For more details consider examining the file \texttt{bn\_mp\_exptmod\_fast.c}. + +\section{Restricted Diminished Radix} + +``Diminished Radix'' reduction refers to reduction with respect to moduli that are amenable to +simple digit shifting and small multiplications. In this case the ``restricted'' variant refers to +moduli of the form $\beta^k - p$ for some $k \ge 0$ and $0 < p < \beta$ where $\beta$ is the radix +(default to $2^{28}$). + +As in the case of Montgomery reduction there is a pre--computation phase required for a given +modulus. + +\index{mp\_dr\_setup} +\begin{alltt} +void mp_dr_setup(const mp_int *a, mp_digit *d); +\end{alltt} + +This computes the value required for the modulus $a$ and stores it in $d$. This function cannot +fail and does not return any error codes. + +To determine if $a$ is a valid DR modulus: +\index{mp\_dr\_is\_modulus} +\begin{alltt} +bool mp_dr_is_modulus(const mp_int *a); +\end{alltt} + +After the pre--computation a reduction can be performed with the following. + +\index{mp\_dr\_reduce} +\begin{alltt} +mp_err mp_dr_reduce(mp_int *a, const mp_int *b, mp_digit mp); +\end{alltt} + +This reduces $a$ in place modulo $b$ with the pre--computed value $mp$. $b$ must be of a restricted +diminished radix form and $a$ must be in the range $0 \le a < b^2$. Diminished radix reductions +are much faster than both Barrett and Montgomery reductions as they have a much lower asymptotic +running time. + +Since the moduli are restricted this algorithm is not particularly useful for something like Rabin, +RSA or BBS cryptographic purposes. This reduction algorithm is useful for Diffie--Hellman and ECC +where fixed primes are acceptable. + +Note that unlike Montgomery reduction there is no normalization process. The result of this +function is equal to the correct residue. + +\section{Unrestricted Diminished Radix} + +Unrestricted reductions work much like the restricted counterparts except in this case the moduli +is of the form $2^k - p$ for $0 < p < \beta$. In this sense the unrestricted reductions are more +flexible as they can be applied to a wider range of numbers. + +\index{mp\_reduce\_2k\_setup}\index{mp\_reduce\_2k\_setup\_l} +\begin{alltt} +mp_err mp_reduce_2k_setup(const mp_int *a, mp_digit *d); +mp_err mp_reduce_2k_setup_l(const mp_int *a, mp_int *d); +\end{alltt} + +This will compute the required $d$ value for the given moduli $a$. + +\index{mp\_reduce\_2k}\index{mp\_reduce\_2k\_l} +\begin{alltt} +mp_err mp_reduce_2k(mp_int *a, const mp_int *n, mp_digit d); +mp_err mp_reduce_2k_l(mp_int *a, const mp_int *n, const mp_int *d); +\end{alltt} + +This will reduce $a$ in place modulo $n$ with the pre--computed value $d$. From my experience this +routine is slower than the function \texttt{mp\_dr\_reduce} but faster for most moduli sizes than +the Montgomery reduction. + +To determine if \texttt{mp\_reduce\_2k} can be used at all, ask the function +\texttt{mp\_reduce\_is\_2k}. + +\index{mp\_reduce\_is\_2k}\index{mp\_reduce\_is\_2k\_l} +\begin{alltt} +bool mp_reduce_is_2k(const mp_int *a); +bool mp_reduce_is_2k_l(const mp_int *a); +\end{alltt} + +\section{Combined Modular Reduction} + +Some of the combinations of an arithmetic operations followed by a modular reduction can be done in +a faster way. The ones implemented are: + +Addition $d = (a + b) \mod c$ +\index{mp\_addmod} +\begin{alltt} +mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + +Subtraction $d = (a - b) \mod c$ +\index{mp\_submod} +\begin{alltt} +mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + +Multiplication $d = (ab) \mod c$ +\index{mp\_mulmod} +\begin{alltt} +mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + +Squaring $d = (a^2) \mod c$ +\index{mp\_sqrmod} +\begin{alltt} +mp_err mp_sqrmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d); +\end{alltt} + +\chapter{Exponentiation} +\section{Single Digit Exponentiation} +\index{mp\_expt\_n} +\begin{alltt} +mp_err mp_expt_n(const mp_int *a, int b, int *c) +\end{alltt} +This function computes $c = a^b$. + +\section{Modular Exponentiation} +\index{mp\_exptmod} +\begin{alltt} +mp_err mp_exptmod (const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) +\end{alltt} +This computes $Y \equiv G^X \mbox{ (mod }P\mbox{)}$ using a variable width sliding window +algorithm. This function will automatically detect the fastest modular reduction technique to use +during the operation. For negative values of $X$ the operation is performed as $Y \equiv (G^{-1} + \mbox{ mod }P)^{\vert X \vert} \mbox{ (mod }P\mbox{)}$ provided that $gcd(G, P) = 1$. + +This function is actually a shell around the two internal exponentiation functions. This routine +will automatically detect when Barrett, Montgomery, Restricted and Unrestricted Diminished Radix +based exponentiation can be used. Generally moduli of the a ``restricted diminished radix'' form +lead to the fastest modular exponentiations. Followed by Montgomery and the other two algorithms. + +\section{Modulus a Power of Two} +\index{mp\_mod\_2d} +\begin{alltt} +mp_err mp_mod_2d(const mp_int *a, int b, mp_int *c) +\end{alltt} +It calculates $c = a \mod 2^b$. + +\section{Root Finding} +\index{mp\_root\_n} +\begin{alltt} +mp_err mp_root_n(const mp_int *a, int b, mp_int *c) +\end{alltt} +This computes $c = a^{1/b}$ such that $c^b \le a$ and $(c+1)^b > a$. Will return a positive root +only for even roots and return a root with the sign of the input for odd roots. For example, +performing $4^{1/2}$ will return $2$ whereas $(-8)^{1/3}$ will return $-2$. + +This algorithm uses the ``Newton Approximation'' method and will converge on the correct root +fairly quickly. + +The square root $c = a^{1/2}$ (with the same conditions $c^2 \le a$ and $(c+1)^2 > a$) is +implemented with a faster algorithm. + +\index{mp\_sqrt} +\begin{alltt} +mp_err mp_sqrt(const mp_int *arg, mp_int *ret) +\end{alltt} +\chapter{Logarithm} +\section{Integer Logarithm} +A logarithm function for positive integer input \texttt{a, base} computing $\floor{\log_bx}$ such +that $(\log_b x)^b \le x$. The function \texttt{mp\_log\_n} is just a wrapper that converts \texttt{base} +to a bigint and calls \texttt{mp\_log}. + +\index{mp\_log} +\begin{alltt} +mp_err mp_log(const mp_int *a, const mp_int *base, int *c) +\end{alltt} + +\index{mp\_log\_n} +\begin{alltt} +mp_err mp_log_n(const mp_int *a, int base, int *c) +\end{alltt} + +\subsection{Example} +Example given for \texttt{mp\_log\_n} only because the single difference is the type of \texttt{base}. +\begin{small} + \begin{alltt} +#include +#include +#include + +#include + +int main(int argc, char **argv) +{ + mp_int x; + int base, output; + mp_err e; + + if (argc != 3) { + fprintf(stderr,"Usage %s base x\textbackslash{}n", argv[0]); + exit(EXIT_FAILURE); + } + if ((e = mp_init(&x)) != MP_OKAY) { + fprintf(stderr,"mp_init failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n", + mp_error_to_string(e)); + exit(EXIT_FAILURE); + } + errno = 0; + base = (int)strtoul(argv[1], NULL, 10); + + if (errno == ERANGE) { + fprintf(stderr,"strtoul(l) failed: input out of range\textbackslash{}n"); + exit(EXIT_FAILURE); + } + if ((e = mp_read_radix(&x, argv[2], 10)) != MP_OKAY) { + fprintf(stderr,"mp_read_radix failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n", + mp_error_to_string(e)); + exit(EXIT_FAILURE); + } + if ((e = mp_log_n(&x, base, &output)) != MP_OKAY) { + fprintf(stderr,"mp_log_n failed: \textbackslash{}"%s\textbackslash{}"\textbackslash{}n", + mp_error_to_string(e)); + exit(EXIT_FAILURE); + } + printf("%d\n",output); + + mp_clear(&x); + exit(EXIT_SUCCESS); +} +\end{alltt} +\end{small} + + + + + +\chapter{Prime Numbers} + +\section{Fermat Test} +\index{mp\_prime\_fermat} +\begin{alltt} +mp_err mp_prime_fermat (const mp_int *a, const mp_int *b, int *result) +\end{alltt} +Performs a Fermat primality test to the base $b$. That is it computes $b^a \mbox{ mod }a$ and +tests whether the value is equal to $b$ or not. If the values are equal then $a$ is probably prime +and $result$ is set to one. Otherwise $result$ is set to zero. + +\section{Miller--Rabin Test} +\index{mp\_prime\_miller\_rabin} +\begin{alltt} +mp_err mp_prime_miller_rabin (const mp_int *a, const mp_int *b, int *result) +\end{alltt} +Performs a Miller--Rabin test to the base $b$ of $a$. This test is much stronger than the Fermat +test and is very hard to fool (besides with Carmichael numbers). If $a$ passes the test (therefore +is probably prime) $result$ is set to one. Otherwise $result$ is set to zero. + +Note that it is suggested that you use the Miller--Rabin test instead of the Fermat test since all +of the failures of Miller--Rabin are a subset of the failures of the Fermat test. + +\subsection{Required Number of Tests} +Generally to ensure a number is very likely to be prime you have to perform the Miller--Rabin with +at least a half--dozen or so unique bases. However, it has been proven that the probability of +failure goes down as the size of the input goes up. This is why a simple function has been provided +to help out. + +\index{mp\_prime\_rabin\_miller\_trials} +\begin{alltt} +mp_err mp_prime_rabin_miller_trials(int size) +\end{alltt} +This returns the number of trials required for a low probability of failure for a given +\texttt{size} expressed in bits. This comes in handy specially since larger numbers are slower to +test. For example, a 512--bit number would require 18 tests for a probability of $2^{-160}$ whereas +a 1024--bit number would only require 12 tests for a probability of $2^{-192}$. The exact values as +implemented are listed in table \ref{table:millerrabinrunsimpl}. + +\begin{table}[h] + \begin{center} + \begin{tabular}{c c c} + \textbf{bits} & \textbf{Rounds} & \textbf{Error} \\ + 80 & -1 & Use deterministic algorithm for size <= 80 bits \\ + 81 & 37 & $2^{-96}$ \\ + 96 & 32 & $2^{-96}$ \\ + 128 & 40 & $2^{-112}$ \\ + 160 & 35 & $2^{-112}$ \\ + 256 & 27 & $2^{-128}$ \\ + 384 & 16 & $2^{-128}$ \\ + 512 & 18 & $2^{-160}$ \\ + 768 & 11 & $2^{-160}$ \\ + 896 & 10 & $2^{-160}$ \\ + 1024 & 12 & $2^{-192}$ \\ + 1536 & 8 & $2^{-192}$ \\ + 2048 & 6 & $2^{-192}$ \\ + 3072 & 4 & $2^{-192}$ \\ + 4096 & 5 & $2^{-256}$ \\ + 5120 & 4 & $2^{-256}$ \\ + 6144 & 4 & $2^{-256}$ \\ + 8192 & 3 & $2^{-256}$ \\ + 9216 & 3 & $2^{-256}$ \\ + 10240 & 2 & $2^{-256}$ + \end{tabular} + \caption{ Number of Miller-Rabin rounds as implemented } \label{table:millerrabinrunsimpl} + \end{center} +\end{table} + +A small table, broke in two for typographical reasons, with the number of rounds of Miller--Rabin +tests is shown below. The numbers have been computed with a PARI/GP script listed in appendix +\ref{app:numberofmrcomp}. + +The first column is the number of bits $b$ in the prime $p = 2^b$, the numbers in the first row +represent the probability that the number that all of the Miller--Rabin tests deemed a pseudoprime +is actually a composite. There is a deterministic test for numbers smaller than $2^{80}$. + +\begin{table}[h] + \begin{center} + \begin{tabular}{c c c c c c c} + \textbf{bits} & $\mathbf{2^{-80}}$ & $\mathbf{2^{-96}}$ & $\mathbf{2^{-112}}$ & + $\mathbf{2^{-128}}$ + & $\mathbf{2^{-160}}$ & $\mathbf{2^{-192}}$ + \\ + 80 & 31 & 39 & 47 & 55 + & 71 & 87 \\ + 96 & 29 & 37 & 45 & 53 + & 69 & 85 \\ + 128 & 24 & 32 & 40 & 48 + & 64 & 80 \\ + 160 & 19 & 27 & 35 & 43 + & 59 & 75 \\ + 192 & 15 & 21 & 29 & 37 + & 53 & 69 \\ + 256 & 10 & 15 & 20 & 27 + & 43 & 59 \\ + 384 & 7 & 9 & 12 & 16 + & 25 & 38 \\ + 512 & 5 & 7 & 9 & 12 + & 18 & 26 \\ + 768 & 4 & 5 & 6 & 8 + & 11 & 16 \\ + 1024 & 3 & 4 & 5 & 6 + & 9 & 12 \\ + 1536 & 2 & 3 & 3 & 4 + & 6 & 8 \\ + 2048 & 2 & 2 & 3 & 3 + & 4 & 6 \\ + 3072 & 1 & 2 & 2 & 2 + & 3 & 4 \\ + 4096 & 1 & 1 & 2 & 2 + & 2 & 3 \\ + 6144 & 1 & 1 & 1 & 1 + & 2 & 2 \\ + 8192 & 1 & 1 & 1 & 1 + & 2 & 2 \\ + 12288 & 1 & 1 & 1 & 1 + & 1 & 1 \\ + 16384 & 1 & 1 & 1 & 1 + & 1 & 1 \\ + 24576 & 1 & 1 & 1 & 1 + & 1 & 1 \\ + 32768 & 1 & 1 & 1 & 1 + & 1 & 1 + \end{tabular} + \caption{ Number of Miller-Rabin rounds. Part I } \label{table:millerrabinrunsp1} + \end{center} +\end{table} +\newpage +\begin{table}[h] + \begin{center} + \begin{tabular}{c c c c c c c c} + \textbf{bits} & $\mathbf{2^{-224}}$ & $\mathbf{2^{-256}}$ & $\mathbf{2^{-288}}$ & + $\mathbf{2^{-320}}$ & $\mathbf{2^{-352}}$ & $\mathbf{2^{-384}}$ & $\mathbf{2^{-416}}$ + \\ + 80 & 103 & 119 & 135 & 151 & + 167 & 183 & 199 + \\ + 96 & 101 & 117 & 133 & 149 & + 165 & 181 & 197 + \\ + 128 & 96 & 112 & 128 & 144 & + 160 & 176 & 192 + \\ + 160 & 91 & 107 & 123 & 139 & + 155 & 171 & 187 + \\ + 192 & 85 & 101 & 117 & 133 & + 149 & 165 & 181 + \\ + 256 & 75 & 91 & 107 & 123 & + 139 & 155 & 171 + \\ + 384 & 54 & 70 & 86 & 102 & + 118 & 134 & 150 + \\ + 512 & 36 & 49 & 65 & 81 & + 97 & 113 & 129 + \\ + 768 & 22 & 29 & 37 & 47 & + 58 & 70 & 86 + \\ + 1024 & 16 & 21 & 26 & 33 & + 40 & 48 & 58 + \\ + 1536 & 10 & 13 & 17 & 21 & + 25 & 30 & 35 + \\ + 2048 & 8 & 10 & 13 & 15 & + 18 & 22 & 26 + \\ + 3072 & 5 & 7 & 8 & 10 & + 12 & 14 & 17 + \\ + 4096 & 4 & 5 & 6 & 8 & + 9 & 11 & 12 + \\ + 6144 & 3 & 4 & 4 & 5 & + 6 & 7 & 8 + \\ + 8192 & 2 & 3 & 3 & 4 & + 5 & 6 & 6 + \\ + 12288 & 2 & 2 & 2 & 3 & + 3 & 4 & 4 + \\ + 16384 & 1 & 2 & 2 & 2 & + 3 & 3 & 3 + \\ + 24576 & 1 & 1 & 2 & 2 & + 2 & 2 & 2 + \\ + 32768 & 1 & 1 & 1 & 1 & + 2 & 2 & 2 + \end{tabular} + \caption{ Number of Miller-Rabin rounds. Part II } \label{table:millerrabinrunsp2} + \end{center} +\end{table} + +Determining the probability needed to pick the right column is a bit harder. Fips 186.4, for +example has $2^{-80}$ for $512$ bit large numbers, $2^{-112}$ for $1024$ bits, and $2^{128}$ for +$1536$ bits. It can be seen in table \ref{table:millerrabinrunsp1} that those combinations follow +the diagonal from $(512,2^{-80})$ downwards and to the right to gain a lower probability of getting +a composite declared a pseudoprime for the same amount of work or less. + +If this version of the library has the strong Lucas--Selfridge and/or the Frobenius--Underwood test +implemented only one or two rounds of the Miller--Rabin test with a random base is necessary for +numbers larger than or equal to $1024$ bits. + +This function is meant for RSA. The number of rounds for DSA is $\lceil -log_2(p)/2\rceil$ with $p$ +the probability which is just the half of the absolute value of $p$ if given as a power of two. +E.g.: with $p = 2^{-128}$, $\lceil -log_2(p)/2\rceil = 64$. + +This function can be used to test a DSA prime directly if these rounds are followed by a Lucas +test. + +See also table C.1 in FIPS 186-4. + +\section{Strong Lucas--Selfridge Test} +\index{mp\_prime\_strong\_lucas\_selfridge} +\begin{alltt} +mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, bool *result) +\end{alltt} +Performs a strong Lucas--Selfridge test. The strong Lucas--Selfridge test together with the +Rabin--Miller test with bases $2$ and $3$ resemble the BPSW test. The single internal use is a +compile--time option in \texttt{mp\_prime\_is\_prime} and can be excluded from the Libtommath build +if not needed. + +\section{Frobenius (Underwood) Test} +\index{mp\_prime\_frobenius\_underwood} +\begin{alltt} +mp_err mp_prime_frobenius_underwood(const mp_int *N, bool *result) +\end{alltt} +Performs the variant of the Frobenius test as described by Paul Underwood. It can be included at +build--time if the preprocessor macro \texttt{LTM\_USE\_FROBENIUS\_TEST} is defined and will be +used +instead of the Lucas--Selfridge test. + +It returns \texttt{MP\_ITER} if the number of iterations is exhausted, assumes a composite as the +input and sets \texttt{result} accordingly. This will reduce the set of available pseudoprimes by a +very small amount: test with large datasets (more than $10^{10}$ numbers, both randomly chosen and +sequences of odd numbers with a random start point) found only 31 (thirty--one) numbers with $a > + 120$ and none at all with just an additional simple check for divisors $d < 2^8$. + +\section{Primality Testing} +Testing if a number is a square can be done a bit faster than just by calculating the square root. +It is used by the primality testing function described below. +\index{mp\_is\_square} +\begin{alltt} +mp_err mp_is_square(const mp_int *arg, bool *ret); +\end{alltt} + +\index{mp\_prime\_is\_prime} +\begin{alltt} +mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) +\end{alltt} +This will perform a trial division followed by two rounds of Miller--Rabin with bases 2 and 3 and a +Lucas--Selfridge test. The Frobenius--Underwood is available as a compile--time option with the +preprocessor macro \texttt{LTM\_USE\_FROBENIUS\_TEST}. See file \texttt{bn\_mp\_prime\_is\_prime.c} +for the necessary details. It shall be noted that both functions are much slower than the +Miller--Rabin test and if speed is an essential issue, the macro \texttt{LTM\_USE\_ONLY\_MR} +switches the Frobenius--Underwood test and the Lucas--Selfridge test off and their code will not +even be compiled into the library. + +If $t$ is set to a positive value $t$ additional rounds of the Miller--Rabin test with random bases +will be performed to allow for Fips 186.4 (vid.~p.~126ff) compliance. The function +\texttt{mp\_prime\_rabin\_miller\_trials} can be used to determine the number of rounds. It is +vital that the function \texttt{mp\_rand} has a cryptographically strong random number generator +available. + +One Miller--Rabin tests with a random base will be run automatically, so by setting $t$ to a +positive value this function will run $t + 1$ Miller--Rabin tests with random bases. + +If $t$ is set to a negative value the test will run the deterministic Miller--Rabin test for the +primes up to $3\,317\,044\,064\,679\,887\ 385\,961\,981$\footnote{The semiprime $1287836182261\cdot + 2575672364521$ with both factors smaller than $2^{64}$. An alternative with all factors smaller + than + $2^32$ is $4290067842\cdot 262853\cdot 1206721\cdot 2134439 + 3$}. That limit has to be checked +by +the caller. + +If $a$ passes all of the tests $result$ is set to \texttt{true}, otherwise it is set to +\texttt{false}. + +\section{Next Prime} +\index{mp\_prime\_next\_prime} +\begin{alltt} +mp_err mp_prime_next_prime(mp_int *a, int t, bool bbs_style) +\end{alltt} +This finds the next prime after $a$ that passes the function \texttt{mp\_prime\_is\_prime} with $t$ +tests but see the documentation for \texttt{mp\_prime\_is\_prime} for details regarding the use of +the argument $t$. Set $bbs\_style$ to \texttt{true} if you want only the next prime congruent +to $3 \mbox{ mod } 4$, otherwise set it to \texttt{false} to find any next prime. + +\section{Random Primes} +\index{mp\_prime\_rand} +\begin{alltt} +mp_err mp_prime_rand(mp_int *a, int t, int size, int flags); +\end{alltt} +This will generate a prime in $a$ using $t$ tests of the primality testing algorithms. See the +documentation for the function \texttt{mp\_prime\_is\_prime} for details regarding the use of the +argument \texttt{t}. The parameter \texttt{size} specifies the bit--length of the prime desired. +The parameter \texttt{flags} specifies one of several options available (see fig. +\ref{fig:primeopts}) which can be OR'ed together. + +The function \texttt{mp\_prime\_rand} is suitable for generating primes which must be secret (as in +the case of RSA) since there is no skew on the least significant bits. + +\begin{figure}[h] + \begin{center} + \begin{small} + \begin{tabular}{|r|l|} + \hline \textbf{Flag} & \textbf{Meaning} + \\ + \hline MP\_PRIME\_BBS & Make the prime congruent to $3$ modulo $4$ + \\ + \hline MP\_PRIME\_SAFE & Make a prime $p$ such that $(p - 1)/2$ is also prime. + \\ + & This option implies MP\_PRIME\_BBS as well. + \\ + \hline MP\_PRIME\_2MSB\_OFF & Makes sure that the bit adjacent to the most significant bit + \\ + & Is forced to zero. + \\ + \hline MP\_PRIME\_2MSB\_ON & Makes sure that the bit adjacent to the most significant bit + \\ + & Is forced to one. + \\ + \hline + \end{tabular} + \end{small} + \end{center} + \caption{Primality Generation Options} + \label{fig:primeopts} +\end{figure} + +\chapter{Random Number Generation} +\section{PRNG} +\index{mp\_rand} +\begin{alltt} +mp_err mp_rand(mp_int *a, int digits) +\end{alltt} +This function generates a random number of \texttt{digits} bits. + +The random number generated with these two functions is cryptographically secure if the source of +random numbers the operating systems offers is cryptographically secure. It will use +\texttt{arc4random()} if the OS is a BSD flavor, Wincrypt on Windows, or \texttt{/dev/urandom} on +all operating systems that have it. + +If you have a custom random source you might find the function \texttt{mp\_rand\_source()} useful. +\index{mp\_rand\_source} +\begin{alltt} +void mp_rand_source(mp_err(*source)(void *out, size_t size)); +\end{alltt} + +\chapter{Input and Output} +\section{ASCII Conversions} +\subsection{To ASCII} +\index{mp\_to\_radix} +\begin{alltt} +mp_err mp_to_radix (const mp_int *a, char *str, size_t maxlen, size_t *written, int radix); +\end{alltt} +This stores $a$ in \texttt{str} of maximum length \texttt{maxlen} as a base-\texttt{radix} string +of ASCII chars and appends a \texttt{NUL} character to terminate the string. + +Valid values of \texttt{radix} are in the range $[2, 64]$. + +The exact number of characters in \texttt{str} plus the \texttt{NUL} will be put in +\texttt{written} if that variable is not set to \texttt{NULL}. + +If \texttt{str} is not big enough to hold $a$, \texttt{str} will be filled with the least +significant digits of length \texttt{maxlen-1}, then \texttt{str} will be \texttt{NUL} terminated +and the error \texttt{MP\_BUF} is returned. + +Please be aware that this function cannot evaluate the actual size of the buffer, it relies on the +correctness of \texttt{maxlen}! + +\index{mp\_radix\_size} +\begin{alltt} +mp_err mp_radix_size (const mp_int *a, int radix, int *size) +\end{alltt} +This stores in \texttt{size} the number of characters (including space for the \texttt{NUL} +terminator) required. Upon error this function returns an error code and \texttt{size} will be +zero. This version of \texttt{mp\_radix\_size} uses \texttt{mp\_log} to calculate the size. It +is exact but slow for larger numbers. + +\index{mp\_radix\_size\_overestimate} +\begin{alltt} +mp_err mp_radix_size_overestimate (const mp_int *a, int radix, int *size) +\end{alltt} +This stores in \texttt{size} the number of characters (including space for the \texttt{NUL} +terminator) required. Upon error this function returns an error code and \texttt{size} will be +zero. This version of \texttt{mp\_radix\_size} is much faster than the exact version above but +introduces the relative error $\approx 10^{-8}$. That would be $22$ for $2^{2^{31}}-1$, the +largest possible number in LibTomMath. Experiments gave no absolute error over $+5$. + +The result is \emph{always} either exact or too large but it is \emph{never} too small. + + +If \texttt{MP\_NO\_FILE} is not defined a function to write to a file is also available. + +\index{mp\_fwrite} +\begin{alltt} +mp_err mp_fwrite(const mp_int *a, int radix, FILE *stream); +\end{alltt} + +\subsection{From ASCII} +\index{mp\_read\_radix} +\begin{alltt} +mp_err mp_read_radix (mp_int *a, const char *str, int radix); +\end{alltt} +This will read a \texttt{NUL} terminated string in base \texttt{radix} from \texttt{str} into $a$. +Valid values of \texttt{radix} are in the range $[2, 64]$. +%It will stop reading when it reads a character it does not recognize (which happens to include the +%\texttt{NUL} char\dots imagine that\dots). + +It returns \texttt{MP\_VAL} for any character {\em not} in the range allowed for the given base. +The list of characters is the same as for base-64 and also in the same order. +\begin{alltt} +0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/ +\end{alltt} + +A single leading $-$ (ASCII \texttt{0x20}) sign can be used to denote a negative number. The +plus sign $+$ (ASCII \texttt{0x2b}) is already in use (bases 63 and 64) and cannot be used +to denote positivity, no matter how good the mood of the number is. + +For all bases smaller than 37 the list is case-insensitive, e.g.:~the two hexadecimal numbers +$123abc_{16} = 1194684_{10}$ and $123ABC_{16} = 1194684_{10}$ are equivalent but the two base +64 numbers $123abc_{64} = 1108232550_{10}$ and $123ABC_{64} = 1108124364_{10}$ are not. + +The input encoding is currently restricted to ASCII only. + +If \texttt{MP\_NO\_FILE} is not defined a function to read from a file is also available. +\index{mp\_fread} +\begin{alltt} +mp_err mp_fread(mp_int *a, int radix, FILE *stream); +\end{alltt} + +\section{Binary Conversions} + +Converting an \texttt{mp\_int} to and from binary is another keen idea. + +\index{mp\_ubin\_size} +\begin{alltt} +size_t mp_ubin_size(const mp_int *a); +\end{alltt} + +This will return the number of bytes (octets) required to store the unsigned copy of the integer +$a$. + +\index{mp\_to\_ubin} +\begin{alltt} +mp_err mp_to_ubin(const mp_int *a, uint8_t *buf, size_t maxlen, size_t *written) +\end{alltt} +This will store $a$ into the buffer \texttt{buf} of size \texttt{maxlen} in big--endian format +storing the number of bytes written in \texttt{len}. Fortunately this is exactly what DER (or is +it ASN?) requires. It does not store the sign of the integer. + +\index{mp\_from\_ubin} +\begin{alltt} +mp_err mp_from_ubin(mp_int *a, uint8_t *b, size_t size); +\end{alltt} +This will read in an unsigned big--endian array of bytes (octets) from \texttt{b} of length +\texttt{size} into $a$. The resulting big--integer $a$ will always be positive. + +For those who acknowledge the existence of negative numbers (heretic!) there are ``signed'' +versions of the previous functions. +\index{mp\_sbin\_size} \index{mp\_from\_sbin} \index{mp\_to\_sbin} +\begin{alltt} +size_t mp_sbin_size(const mp_int *a); +mp_err mp_from_sbin(mp_int *a, const uint8_t *b, size_t size); +mp_err mp_to_sbin(const mp_int *a, uint8_t *b, size_t maxsize, size_t *len); +\end{alltt} +They operate essentially the same as the unsigned copies except they prefix the data with zero or +non--zero byte depending on the sign. If the sign is \texttt{MP\_ZPOS} (e.g. not negative) the +prefix is zero, otherwise the prefix is non--zero. + +The two functions \texttt{mp\_unpack} (get your gifts out of the box, import binary data) and +\texttt{mp\_pack} (put your gifts into the box, export binary data) implement the similarly working +GMP functions as described at \url{http://gmplib.org/manual/Integer-Import-and-Export.html} with +the exception that \texttt{mp\_pack} will not allocate memory if \texttt{rop} is \texttt{NULL}. +\index{mp\_unpack} \index{mp\_pack} +\begin{alltt} +mp_err mp_unpack(mp_int *rop, size_t count, mp_order order, size_t size, + mp_endian endian, size_t nails, const void *op, size_t maxsize); +mp_err mp_pack(void *rop, size_t *countp, mp_order order, size_t size, + mp_endian endian, size_t nails, const mp_int *op); +\end{alltt} +The function \texttt{mp\_pack} has the additional variable \texttt{maxsize} which must hold the +size of the buffer \texttt{rop} in bytes. Use +\index{mp\_pack\_count} +\begin{alltt} +/* Parameters "nails" and "size" are the same as in mp_pack */ +size_t mp_pack_count(const mp_int *a, size_t nails, size_t size); +\end{alltt} +To get the size in bytes necessary to be put in \texttt{maxsize}). + +To enhance the readability of your code, the following enums have been wrought for your +convenience. +\begin{alltt} +typedef enum { + MP_LSB_FIRST = -1, + MP_MSB_FIRST = 1 +} mp_order; +typedef enum { + MP_LITTLE_ENDIAN = -1, + MP_NATIVE_ENDIAN = 0, + MP_BIG_ENDIAN = 1 +} mp_endian; +\end{alltt} + +\chapter{Algebraic Functions} +\section{Extended Euclidean Algorithm} +\index{mp\_exteuclid} +\begin{alltt} +mp_err mp_exteuclid(const mp_int *a, const mp_int *b, + mp_int *U1, mp_int *U2, mp_int *U3); +\end{alltt} + +This finds the triple $U_1$/$U_2$/$U_3$ using the Extended Euclidean algorithm such that the +following equation holds. + +\begin{equation} + a \cdot U_1 + b \cdot U_2 = U_3 +\end{equation} + +Any of the \texttt{U1}/\texttt{U2}/\texttt{U3} parameters can be set to \textbf{NULL} if they are +not desired. + +\section{Greatest Common Divisor} +\index{mp\_gcd} +\begin{alltt} +mp_err mp_gcd (const mp_int *a, const mp_int *b, mp_int *c) +\end{alltt} +This will compute the greatest common divisor of $a$ and $b$ and store it in $c$. + +\section{Least Common Multiple} +\index{mp\_lcm} +\begin{alltt} +mp_err mp_lcm (const mp_int *a, const mp_int *b, mp_int *c) +\end{alltt} +This will compute the least common multiple of $a$ and $b$ and store it in $c$. + +\section{Kronecker Symbol} +\index{mp\_kronecker} +\begin{alltt} +mp_err mp_kronecker (const mp_int *a, const mp_int *p, int *c) +\end{alltt} +This will compute the Kronecker symbol (an extension of the Jacobi symbol) for $a$ with respect to +$p$ with $\lbrace a, p \rbrace \in \mathbb{Z}$. If $p$ is prime this essentially computes the +Legendre symbol. The result is stored in $c$ and can take on one of three values $\lbrace -1, 0, 1 + \rbrace$. If $p$ is prime then the result will be $-1$ when $a$ is not a quadratic residue +modulo +$p$. The result will be $0$ if $a$ divides $p$ and the result will be $1$ if $a$ is a quadratic +residue modulo $p$. + +\section{Modular square root} +\index{mp\_sqrtmod\_prime} +\begin{alltt} +mp_err mp_sqrtmod_prime(const mp_int *n, const mp_int *p, mp_int *r) +\end{alltt} + +This will solve the modular equation $r^2 = n \mod p$ where $p$ is a prime number greater than 2 +(odd prime). The result is returned in the third argument $r$, the function returns +\texttt{MP\_OKAY} on success, other return values indicate failure. + +The implementation is split for two different cases: + +1. if $p \mod 4 == 3$ we apply \href{http://cacr.uwaterloo.ca/hac/}{Handbook of Applied + Cryptography algorithm 3.36} and compute $r$ directly as $r = n^{(p+1)/4} \mod p$ + +2. otherwise we use \href{https://en.wikipedia.org/wiki/Tonelli-Shanks_algorithm}{Tonelli--Shanks + algorithm} + +The function does not check the primality of parameter $p$ thus it is up to the caller to assure +that this parameter is a prime number. When $p$ is a composite the function behaviour is undefined, +it may even return a false--positive \texttt{MP\_OKAY}. + +\section{Modular Inverse} +\index{mp\_invmod} +\begin{alltt} +mp_err mp_invmod (const mp_int *a, const mp_int *b, mp_int *c) +\end{alltt} +Computes the multiplicative inverse of $a$ modulo $b$ and stores the result in $c$ such that +$ac \equiv 1 \mbox{ (mod }b\mbox{)}$. + +\section{Single Digit Functions} + +For those using small numbers (\textit{snicker snicker}) there are several ``helper'' functions + +\index{mp\_add\_d} \index{mp\_sub\_d} \index{mp\_mul\_d} \index{mp\_div\_d} \index{mp\_mod\_d} +\begin{alltt} +mp_err mp_add_d(const mp_int *a, mp_digit b, mp_int *c); +mp_err mp_sub_d(const mp_int *a, mp_digit b, mp_int *c); +mp_err mp_mul_d(const mp_int *a, mp_digit b, mp_int *c); +mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d); +mp_err mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c); +\end{alltt} + +These work like the full \texttt{mp\_int} capable variants except the second parameter $b$ is a +\texttt{mp\_digit}. These functions come fairly handy if you have to work with relatively small numbers +since you will not have to allocate an entire \texttt{mp\_int} to store a number like $1$ or $2$. + +The functions \texttt{mp\_incr} and \texttt{mp\_decr} mimic the postfix operators \texttt{++} and +\texttt{--} respectively, to increment the input by one. They call the full single--digit functions +if the addition would carry. Both functions need to be included in a minimized library because they +call each other in case of a negative input, These functions change the inputs! +\index{mp\_incr} \index{mp\_decr} +\begin{alltt} +mp_err mp_incr(mp_int *a); +mp_err mp_decr(mp_int *a); +\end{alltt} + +\chapter{Little Helpers} +It is never wrong to have some useful little shortcuts at hand. +\section{Function Macros} +To make this overview simpler the macros are given as function prototypes. The return of logic +macros is \texttt{false} or \texttt{true} respectively. + +\index{mp\_iseven} +\begin{alltt} +bool mp_iseven(const mp_int *a) +\end{alltt} +Checks if $a = 0 \;\mathrm{mod}\; 2$ + +\index{mp\_isodd} +\begin{alltt} +bool mp_isodd(const mp_int *a) +\end{alltt} +Checks if $a = 1 \;\mathrm{mod}\; 2$ + +\index{mp\_isneg} +\begin{alltt} +bool mp_isneg(mp_int *a) +\end{alltt} +Checks if $a < 0$ + +\index{mp\_iszero} +\begin{alltt} +bool mp_iszero(mp_int *a) +\end{alltt} +Checks if $a = 0$. It does not check if the amount of memory allocated for $a$ is also minimal. + +Other macros which are either shortcuts to normal functions or just other names for them do have +their place in a programmer's life, too! + +\subsection{Shortcuts} + +\index{mp\_to\_binary} +\begin{alltt} +#define mp_to_binary(M, S, N) mp_to_radix((M), (S), (N), 2) +\end{alltt} + +\index{mp\_to\_octal} +\begin{alltt} +#define mp_to_octal(M, S, N) mp_to_radix((M), (S), (N), 8) +\end{alltt} + +\index{mp\_to\_decimal} +\begin{alltt} +#define mp_to_decimal(M, S, N) mp_to_radix((M), (S), (N), 10) +\end{alltt} + +\index{mp\_to\_hex} +\begin{alltt} +#define mp_to_hex(M, S, N) mp_to_radix((M), (S), (N), 16) +\end{alltt} + +\begin{appendices} + \appendixpage + %\noappendicestocpagenum + \addappheadtotoc + \chapter{Computing Number of Miller--Rabin Trials}\label{app:numberofmrcomp} + The number of Miller--Rabin rounds in the tables \ref{millerrabinrunsimpl}, + \ref{millerrabinrunsp1}, and \ref{millerrabinrunsp2} have been calculated with the formula in + FIPS + 186--4 appendix F.1 (page 117) implemented as a PARI/GP script. + + \begin{small} + \begin{alltt} +log2(x) = log(x)/log(2) + +fips_f1_sums(k, M, t) = { + local(s = 0); + s = sum(m=3,M, + 2^(m-t*(m-1)) * + sum(j=2,m, + 1/ ( 2^( j + (k-1)/j ) ) + ) + ); + return(s); +} + +fips_f1_2(k, t, M) = { + local(common_factor, t1, t2, f1, f2, ds, res); + + common_factor = 2.00743 * log(2) * k * 2^(-k); + t1 = 2^(k - 2 - M*t); + f1 = (8 * ((Pi^2) - 6))/3; + f2 = 2^(k - 2); + ds = t1 + f1 * f2 * fips_f1_sums(k, M, t); + res = common_factor * ds; + return(res); +} + +fips_f1_1(prime_length, ptarget)={ + local(t, t_end, M, M_end, pkt); + + t_end = ceil(-log2(ptarget)/2); + M_end = floor(2 * sqrt(prime_length-1) - 1); + + for(t = 1, t_end, + for(M = 3, M_end, + pkt = fips_f1_2(prime_length, t, M); + if(pkt <= ptarget, + return(t); + ); + ); + ); +} +\end{alltt} + \end{small} + + To get the number of rounds for a $1024$ bit large prime with a probability of $2^{-160}$: + \begin{alltt} +? fips_f1_1(1024,2^(-160)) +%1 = 9 +\end{alltt} +\end{appendices} +\input{bn.ind} + +\end{document} diff --git a/deps/libtommath/doc/makefile b/deps/libtommath/doc/makefile new file mode 100644 index 0000000..a8c6a65 --- /dev/null +++ b/deps/libtommath/doc/makefile @@ -0,0 +1,49 @@ +ifeq ($V,1) +silent_stdout= +else +silent_stdout= > /dev/null +endif + +PLATFORM := $(shell uname | sed -e 's/_.*//') +ifeq ($(PLATFORM), Darwin) +err: + $(error Docs can't be built on Mac) + +docs mandvi manual: err +endif + +docs: manual + +#LTM user manual +mandvi: bn.tex + cp bn.tex bn.bak + touch --reference=bn.tex bn.bak + (printf "%s" "\def\fixedpdfdate{"; date +'D:%Y%m%d%H%M%S%:z' -d @$$(stat --format=%Y bn.tex) | sed "s/:\([0-9][0-9]\)$$/'\1'}/g") > bn-deterministic.tex + printf "%s\n" "\pdfinfo{" >> bn-deterministic.tex + printf "%s\n" " /CreationDate (\fixedpdfdate)" >> bn-deterministic.tex + printf "%s\n}\n" " /ModDate (\fixedpdfdate)" >> bn-deterministic.tex + cat bn.tex >> bn-deterministic.tex + mv bn-deterministic.tex bn.tex + touch --reference=bn.bak bn.tex + echo "hello" > bn.ind + latex bn ${silent_stdout} + latex bn ${silent_stdout} + makeindex bn + latex bn ${silent_stdout} + +#LTM user manual [pdf] +manual: mandvi + pdflatex bn >/dev/null + sed -b -i 's,^/ID \[.*\]$$,/ID [<0> <0>],g' bn.pdf + mv bn.bak bn.tex + rm -f bn.aux bn.dvi bn.log bn.idx bn.lof bn.out bn.toc + +# The file latexindent.pl is in several LaTeX distributions, if not: +# https://ctan.org/pkg/latexindent +# Its configuration is well documented +# http://mirrors.ctan.org/support/latexindent/documentation/latexindent.pdf +pretty: + latexindent -s -w -m -l=.latexindent.yaml bn.tex + +clean: + rm -f *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log tommath.tex diff --git a/deps/libtommath/etc/2kprime.1 b/deps/libtommath/etc/2kprime.1 new file mode 100644 index 0000000..c41ded1 --- /dev/null +++ b/deps/libtommath/etc/2kprime.1 @@ -0,0 +1,2 @@ +256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823 +512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979 diff --git a/deps/libtommath/etc/2kprime.c b/deps/libtommath/etc/2kprime.c new file mode 100644 index 0000000..3a3e283 --- /dev/null +++ b/deps/libtommath/etc/2kprime.c @@ -0,0 +1,81 @@ +/* Makes safe primes of a 2k nature */ +#include +#include + +static int sizes[] = {256, 512, 768, 1024, 1536, 2048, 3072, 4096}; + +int main(void) +{ + char buf[2000]; + size_t x; + bool y; + mp_int q, p; + FILE *out; + clock_t t1; + mp_digit z; + + mp_init_multi(&q, &p, NULL); + + out = fopen("2kprime.1", "w"); + if (out != NULL) { + for (x = 0; x < (sizeof(sizes) / sizeof(sizes[0])); x++) { +top: + mp_2expt(&q, sizes[x]); + mp_add_d(&q, 3uL, &q); + z = -3; + + t1 = clock(); + for (;;) { + mp_sub_d(&q, 4uL, &q); + z += 4uL; + + if (z > MP_MASK) { + printf("No primes of size %d found\n", sizes[x]); + break; + } + + if ((clock() - t1) > CLOCKS_PER_SEC) { + printf("."); + fflush(stdout); + /* sleep((clock() - t1 + CLOCKS_PER_SEC/2)/CLOCKS_PER_SEC); */ + t1 = clock(); + } + + /* quick test on q */ + mp_prime_is_prime(&q, 1, &y); + if (!y) { + continue; + } + + /* find (q-1)/2 */ + mp_sub_d(&q, 1uL, &p); + mp_div_2(&p, &p); + mp_prime_is_prime(&p, 3, &y); + if (!y) { + continue; + } + + /* test on q */ + mp_prime_is_prime(&q, 3, &y); + if (!y) { + continue; + } + + break; + } + + if (!y) { + ++sizes[x]; + goto top; + } + + mp_to_decimal(&q, buf, sizeof(buf)); + printf("\n\n%d-bits (k = %lu) = %s\n", sizes[x], z, buf); + fprintf(out, "%d-bits (k = %lu) = %s\n", sizes[x], z, buf); + fflush(out); + } + fclose(out); + } + + return 0; +} diff --git a/deps/libtommath/etc/drprime.c b/deps/libtommath/etc/drprime.c new file mode 100644 index 0000000..31dff4e --- /dev/null +++ b/deps/libtommath/etc/drprime.c @@ -0,0 +1,67 @@ +/* Makes safe primes of a DR nature */ +#include + +static int sizes[] = { 1+256/MP_DIGIT_BIT, 1+512/MP_DIGIT_BIT, 1+768/MP_DIGIT_BIT, 1+1024/MP_DIGIT_BIT, 1+2048/MP_DIGIT_BIT, 1+4096/MP_DIGIT_BIT }; + +int main(void) +{ + bool res; + int x, y; + char buf[4096]; + FILE *out; + mp_int a, b; + + mp_init(&a); + mp_init(&b); + + out = fopen("drprimes.txt", "w"); + if (out != NULL) { + for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) { +top: + printf("Seeking a %d-bit safe prime\n", sizes[x] * MP_DIGIT_BIT); + mp_grow(&a, sizes[x]); + mp_zero(&a); + for (y = 1; y < sizes[x]; y++) { + a.dp[y] = MP_MASK; + } + + /* make a DR modulus */ + a.dp[0] = -1; + a.used = sizes[x]; + + /* now loop */ + res = false; + for (;;) { + a.dp[0] += 4uL; + if (a.dp[0] >= MP_MASK) break; + mp_prime_is_prime(&a, 1, &res); + if (!res) continue; + printf("."); + fflush(stdout); + mp_sub_d(&a, 1uL, &b); + mp_div_2(&b, &b); + mp_prime_is_prime(&b, 3, &res); + if (!res) continue; + mp_prime_is_prime(&a, 3, &res); + if (res) break; + } + + if (!res) { + printf("Error not DR modulus\n"); + sizes[x] += 1; + goto top; + } else { + mp_to_decimal(&a, buf, sizeof(buf)); + printf("\n\np == %s\n\n", buf); + fprintf(out, "%d-bit prime:\np == %s\n\n", mp_count_bits(&a), buf); + fflush(out); + } + } + fclose(out); + } + + mp_clear(&a); + mp_clear(&b); + + return 0; +} diff --git a/deps/libtommath/etc/drprimes.28 b/deps/libtommath/etc/drprimes.28 new file mode 100644 index 0000000..9d438ad --- /dev/null +++ b/deps/libtommath/etc/drprimes.28 @@ -0,0 +1,25 @@ +DR safe primes for 28-bit digits. + +224-bit prime: +p == 26959946667150639794667015087019630673637144422540572481103341844143 + +532-bit prime: +p == 14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368691747 + +784-bit prime: +p == 101745825697019260773923519755878567461315282017759829107608914364075275235254395622580447400994175578963163918967182013639660669771108475957692810857098847138903161308502419410142185759152435680068435915159402496058513611411688900243039 + +1036-bit prime: +p == 736335108039604595805923406147184530889923370574768772191969612422073040099331944991573923112581267542507986451953227192970402893063850485730703075899286013451337291468249027691733891486704001513279827771740183629161065194874727962517148100775228363421083691764065477590823919364012917984605619526140821798437127 + +1540-bit prime: +p == 38564998830736521417281865696453025806593491967131023221754800625044118265468851210705360385717536794615180260494208076605798671660719333199513807806252394423283413430106003596332513246682903994829528690198205120921557533726473585751382193953592127439965050261476810842071573684505878854588706623484573925925903505747545471088867712185004135201289273405614415899438276535626346098904241020877974002916168099951885406379295536200413493190419727789712076165162175783 + +2072-bit prime: +p == 542189391331696172661670440619180536749994166415993334151601745392193484590296600979602378676624808129613777993466242203025054573692562689251250471628358318743978285860720148446448885701001277560572526947619392551574490839286458454994488665744991822837769918095117129546414124448777033941223565831420390846864429504774477949153794689948747680362212954278693335653935890352619041936727463717926744868338358149568368643403037768649616778526013610493696186055899318268339432671541328195724261329606699831016666359440874843103020666106568222401047720269951530296879490444224546654729111504346660859907296364097126834834235287147 + +3080-bit prime: +p == 1487259134814709264092032648525971038895865645148901180585340454985524155135260217788758027400478312256339496385275012465661575576202252063145698732079880294664220579764848767704076761853197216563262660046602703973050798218246170835962005598561669706844469447435461092542265792444947706769615695252256130901271870341005768912974433684521436211263358097522726462083917939091760026658925757076733484173202927141441492573799914240222628795405623953109131594523623353044898339481494120112723445689647986475279242446083151413667587008191682564376412347964146113898565886683139407005941383669325997475076910488086663256335689181157957571445067490187939553165903773554290260531009121879044170766615232300936675369451260747671432073394867530820527479172464106442450727640226503746586340279816318821395210726268291535648506190714616083163403189943334431056876038286530365757187367147446004855912033137386225053275419626102417236133948503 + +4116-bit prime: +p == 1095121115716677802856811290392395128588168592409109494900178008967955253005183831872715423151551999734857184538199864469605657805519106717529655044054833197687459782636297255219742994736751541815269727940751860670268774903340296040006114013971309257028332849679096824800250742691718610670812374272414086863715763724622797509437062518082383056050144624962776302147890521249477060215148275163688301275847155316042279405557632639366066847442861422164832655874655824221577849928863023018366835675399949740429332468186340518172487073360822220449055340582568461568645259954873303616953776393853174845132081121976327462740354930744487429617202585015510744298530101547706821590188733515880733527449780963163909830077616357506845523215289297624086914545378511082534229620116563260168494523906566709418166011112754529766183554579321224940951177394088465596712620076240067370589036924024728375076210477267488679008016579588696191194060127319035195370137160936882402244399699172017835144537488486396906144217720028992863941288217185353914991583400421682751000603596655790990815525126154394344641336397793791497068253936771017031980867706707490224041075826337383538651825493679503771934836094655802776331664261631740148281763487765852746577808019633679 diff --git a/deps/libtommath/etc/drprimes.txt b/deps/libtommath/etc/drprimes.txt new file mode 100644 index 0000000..7c97f67 --- /dev/null +++ b/deps/libtommath/etc/drprimes.txt @@ -0,0 +1,9 @@ +300-bit prime: +p == 2037035976334486086268445688409378161051468393665936250636140449354381298610415201576637819 + +540-bit prime: +p == 3599131035634557106248430806148785487095757694641533306480604458089470064537190296255232548883112685719936728506816716098566612844395439751206810991770626477344739 + +780-bit prime: +p == 6359114106063703798370219984742410466332205126109989319225557147754704702203399726411277962562135973685197744935448875852478791860694279747355800678568677946181447581781401213133886609947027230004277244697462656003655947791725966271167 + diff --git a/deps/libtommath/etc/makefile b/deps/libtommath/etc/makefile new file mode 100644 index 0000000..52ad475 --- /dev/null +++ b/deps/libtommath/etc/makefile @@ -0,0 +1,43 @@ +LTM_TUNE_CFLAGS = $(CFLAGS) $(LTM_CFLAGS) -Wall -W -Wextra -Wshadow -O3 -I../ + +# default lib name (requires install with root) +# LIBNAME=-ltommath + +# libname when you can't install the lib with install +LIBNAME=../libtommath.a + +#provable primes +pprime: pprime.o + $(CC) $(LTM_TUNE_CFLAGS) pprime.o $(LIBNAME) -o pprime + +# portable [well requires clock()] tuning app +tune: tune.o + $(CC) $(LTM_TUNE_CFLAGS) tune.o $(LIBNAME) -o tune + ./tune_it.sh + +test_standalone: tune.o + # The benchmark program works as a testtool, too + $(CC) $(LTM_TUNE_CFLAGS) tune.o $(LIBNAME) -o test + +# spits out mersenne primes +mersenne: mersenne.o + $(CC) $(LTM_TUNE_CFLAGS) mersenne.o $(LIBNAME) -o mersenne + +# finds DR safe primes for the given config +drprime: drprime.o + $(CC) $(LTM_TUNE_CFLAGS) drprime.o $(LIBNAME) -o drprime + +# finds 2k safe primes for the given config +2kprime: 2kprime.o + $(CC) $(LTM_TUNE_CFLAGS) 2kprime.o $(LIBNAME) -o 2kprime + +mont: mont.o + $(CC) $(LTM_TUNE_CFLAGS) mont.o $(LIBNAME) -o mont + + +clean: + rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime mont 2kprime pprime.dat \ + tuning_list multiplying squaring test *.da *.dyn *.dpi *~ + rm -rf .libs + +.PHONY: tune diff --git a/deps/libtommath/etc/makefile.icc b/deps/libtommath/etc/makefile.icc new file mode 100644 index 0000000..9217f7b --- /dev/null +++ b/deps/libtommath/etc/makefile.icc @@ -0,0 +1,67 @@ +CC = icc + +CFLAGS += -I../ + +# optimize for SPEED +# +# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4 +# -ax? specifies make code specifically for ? but compatible with IA-32 +# -x? specifies compile solely for ? [not specifically IA-32 compatible] +# +# where ? is +# K - PIII +# W - first P4 [Williamette] +# N - P4 Northwood +# P - P4 Prescott +# B - Blend of P4 and PM [mobile] +# +# Default to just generic max opts +CFLAGS += -O3 -xP -ip + +# default lib name (requires install with root) +# LIBNAME=-ltommath + +# libname when you can't install the lib with install +LIBNAME=../libtommath.a + +#provable primes +pprime: pprime.o + $(CC) pprime.o $(LIBNAME) -o pprime + +tune: tune.o + $(CC) $(CFLAGS) tune.o $(LIBNAME) -o tune + ./tune_it.sh + +# same app but using RDTSC for higher precision [requires 80586+], coff based gcc installs [e.g. ming, cygwin, djgpp] +tune86: tune.c + nasm -f coff timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86 + +# for cygwin +tune86c: tune.c + nasm -f gnuwin32 timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86 + +#make tune86 for linux or any ELF format +tune86l: tune.c + nasm -f elf -DUSE_ELF timer.asm + $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86l + +# spits out mersenne primes +mersenne: mersenne.o + $(CC) mersenne.o $(LIBNAME) -o mersenne + +# fines DR safe primes for the given config +drprime: drprime.o + $(CC) drprime.o $(LIBNAME) -o drprime + +# fines 2k safe primes for the given config +2kprime: 2kprime.o + $(CC) 2kprime.o $(LIBNAME) -o 2kprime + +mont: mont.o + $(CC) mont.o $(LIBNAME) -o mont + + +clean: + rm -f *.log *.o *.obj *.exe pprime tune mersenne drprime tune86 tune86l mont 2kprime pprime.dat *.il tuning_list diff --git a/deps/libtommath/etc/makefile.msvc b/deps/libtommath/etc/makefile.msvc new file mode 100644 index 0000000..592a437 --- /dev/null +++ b/deps/libtommath/etc/makefile.msvc @@ -0,0 +1,24 @@ +#MSVC Makefile +# +#Tom St Denis + +CFLAGS = /I../ /Ox /DWIN32 /W3 + +pprime: pprime.obj + cl pprime.obj ../tommath.lib + +mersenne: mersenne.obj + cl mersenne.obj ../tommath.lib + +tune: tune.obj + cl tune.obj ../tommath.lib + + +mont: mont.obj + cl mont.obj ../tommath.lib + +drprime: drprime.obj + cl drprime.obj ../tommath.lib + +2kprime: 2kprime.obj + cl 2kprime.obj ../tommath.lib diff --git a/deps/libtommath/etc/mersenne.c b/deps/libtommath/etc/mersenne.c new file mode 100644 index 0000000..4d3939e --- /dev/null +++ b/deps/libtommath/etc/mersenne.c @@ -0,0 +1,138 @@ +/* Finds Mersenne primes using the Lucas-Lehmer test + * + * Tom St Denis, tomstdenis@gmail.com + */ +#include +#include + +static mp_err is_mersenne(long s, bool *pp) +{ + mp_int n, u; + mp_err res; + int k; + + *pp = false; + + if ((res = mp_init(&n)) != MP_OKAY) { + return res; + } + + if ((res = mp_init(&u)) != MP_OKAY) { + goto LBL_N; + } + + /* n = 2^s - 1 */ + if ((res = mp_2expt(&n, (int)s)) != MP_OKAY) { + goto LBL_MU; + } + if ((res = mp_sub_d(&n, 1uL, &n)) != MP_OKAY) { + goto LBL_MU; + } + + /* set u=4 */ + mp_set(&u, 4uL); + + /* for k=1 to s-2 do */ + for (k = 1; k <= (s - 2); k++) { + /* u = u^2 - 2 mod n */ + if ((res = mp_sqr(&u, &u)) != MP_OKAY) { + goto LBL_MU; + } + if ((res = mp_sub_d(&u, 2uL, &u)) != MP_OKAY) { + goto LBL_MU; + } + + /* make sure u is positive */ + while (mp_isneg(&u)) { + if ((res = mp_add(&u, &n, &u)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* reduce */ + if ((res = mp_reduce_2k(&u, &n, 1uL)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* if u == 0 then its prime */ + if (mp_iszero(&u)) { + mp_prime_is_prime(&n, 8, pp); + if (!*pp) printf("FAILURE\n"); + } + + res = MP_OKAY; +LBL_MU: + mp_clear(&u); +LBL_N: + mp_clear(&n); + return res; +} + +/* square root of a long < 65536 */ +static long i_sqrt(long x) +{ + long x1, x2; + + x2 = 16; + do { + x1 = x2; + x2 = x1 - ((x1 * x1) - x) / (2 * x1); + } while (x1 != x2); + + if ((x1 * x1) > x) { + --x1; + } + + return x1; +} + +/* is the long prime by brute force */ +static int isprime(long k) +{ + long y, z; + + y = i_sqrt(k); + for (z = 2; z <= y; z++) { + if ((k % z) == 0) + return 0; + } + return 1; +} + + +int main(void) +{ + bool pp; + long k; + clock_t tt; + + k = 3; + + for (;;) { + /* start time */ + tt = clock(); + + /* test if 2^k - 1 is prime */ + if (is_mersenne(k, &pp) != MP_OKAY) { + printf("Whoa error\n"); + return -1; + } + + if (pp) { + /* count time */ + tt = clock() - tt; + + /* display if prime */ + printf("2^%-5ld - 1 is prime, test took %ld ticks\n", k, (long)tt); + } + + /* goto next odd exponent */ + k += 2; + + /* but make sure its prime */ + while (isprime(k) == 0) { + k += 2; + } + } +} diff --git a/deps/libtommath/etc/mont.c b/deps/libtommath/etc/mont.c new file mode 100644 index 0000000..4652410 --- /dev/null +++ b/deps/libtommath/etc/mont.c @@ -0,0 +1,44 @@ +/* tests the montgomery routines */ +#include +#include +#include + +int main(void) +{ + mp_int modulus, R, p, pp; + mp_digit mp; + int x, y; + + srand(time(NULL)); + mp_init_multi(&modulus, &R, &p, &pp, NULL); + + /* loop through various sizes */ + for (x = 4; x < 256; x++) { + printf("DIGITS == %3d...", x); + fflush(stdout); + + /* make up the odd modulus */ + mp_rand(&modulus, x); + modulus.dp[0] |= 1uL; + + /* now find the R value */ + mp_montgomery_calc_normalization(&R, &modulus); + mp_montgomery_setup(&modulus, &mp); + + /* now run through a bunch tests */ + for (y = 0; y < 1000; y++) { + mp_rand(&p, x/2); /* p = random */ + mp_mul(&p, &R, &pp); /* pp = R * p */ + mp_montgomery_reduce(&pp, &modulus, mp); + + /* should be equal to p */ + if (mp_cmp(&pp, &p) != MP_EQ) { + printf("FAILURE!\n"); + exit(-1); + } + } + printf("PASSED\n"); + } + + return 0; +} diff --git a/deps/libtommath/etc/pprime.c b/deps/libtommath/etc/pprime.c new file mode 100644 index 0000000..1d59cab --- /dev/null +++ b/deps/libtommath/etc/pprime.c @@ -0,0 +1,411 @@ +/* Generates provable primes + * + * See http://gmail.com:8080/papers/pp.pdf for more info. + * + * Tom St Denis, tomstdenis@gmail.com, http://tom.gmail.com + */ +#include +#include +#include "tommath_private.h" + +static int n_prime; +static FILE *primes; + +/* fast square root */ +static mp_digit i_sqrt(mp_word x) +{ + mp_word x1, x2; + + x2 = x; + do { + x1 = x2; + x2 = x1 - ((x1 * x1) - x) / (2u * x1); + } while (x1 != x2); + + if ((x1 * x1) > x) { + --x1; + } + + return x1; +} + + +/* generates a prime digit */ +static void gen_prime(void) +{ + mp_digit r, x, y, next; + FILE *out; + + out = fopen("pprime.dat", "wb"); + if (out != NULL) { + + /* write first set of primes */ + /* *INDENT-OFF* */ + r = 3uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 5uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 7uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 11uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 13uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 17uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 19uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 23uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 29uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + r = 31uL; fwrite(&r, 1uL, sizeof(mp_digit), out); + /* *INDENT-ON* */ + + /* get square root, since if 'r' is composite its factors must be < than this */ + y = i_sqrt(r); + next = (y + 1uL) * (y + 1uL); + + for (;;) { + do { + r += 2uL; /* next candidate */ + r &= MP_MASK; + if (r < 31uL) break; + + /* update sqrt ? */ + if (next <= r) { + ++y; + next = (y + 1uL) * (y + 1uL); + } + + /* loop if divisible by 3,5,7,11,13,17,19,23,29 */ + if ((r % 3uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 5uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 7uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 11uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 13uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 17uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 19uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 23uL) == 0uL) { + x = 0uL; + continue; + } + if ((r % 29uL) == 0uL) { + x = 0uL; + continue; + } + + /* now check if r is divisible by x + k={1,7,11,13,17,19,23,29} */ + for (x = 30uL; x <= y; x += 30uL) { + if ((r % (x + 1uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 7uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 11uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 13uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 17uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 19uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 23uL)) == 0uL) { + x = 0uL; + break; + } + if ((r % (x + 29uL)) == 0uL) { + x = 0uL; + break; + } + } + } while (x == 0uL); + if (r > 31uL) { + fwrite(&r, 1uL, sizeof(mp_digit), out); + printf("%9lu\r", r); + fflush(stdout); + } + if (r < 31uL) break; + } + + fclose(out); + } +} + +static void load_tab(void) +{ + primes = fopen("pprime.dat", "rb"); + if (primes == NULL) { + gen_prime(); + primes = fopen("pprime.dat", "rb"); + } + fseek(primes, 0L, SEEK_END); + n_prime = ftell(primes) / sizeof(mp_digit); +} + +static mp_digit prime_digit(void) +{ + int n; + mp_digit d; + + n = abs(rand()) % n_prime; + fseek(primes, n * sizeof(mp_digit), SEEK_SET); + fread(&d, 1uL, sizeof(mp_digit), primes); + return d; +} + + +/* makes a prime of at least k bits */ +static mp_err pprime(int k, int li, mp_int *p, mp_int *q) +{ + mp_int a, b, c, n, x, y, z, v; + mp_err res; + int ii; + static const mp_digit bases[] = { 2, 3, 5, 7, 11, 13, 17, 19 }; + + /* single digit ? */ + if (k <= (int) MP_DIGIT_BIT) { + mp_set(p, prime_digit()); + return MP_OKAY; + } + + if ((res = mp_init(&c)) != MP_OKAY) { + return res; + } + + if ((res = mp_init(&v)) != MP_OKAY) { + goto LBL_C; + } + + /* product of first 50 primes */ + if ((res = + mp_read_radix(&v, + "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190", + 10)) != MP_OKAY) { + goto LBL_V; + } + + if ((res = mp_init(&a)) != MP_OKAY) { + goto LBL_V; + } + + /* set the prime */ + mp_set(&a, prime_digit()); + + if ((res = mp_init(&b)) != MP_OKAY) { + goto LBL_A; + } + + if ((res = mp_init(&n)) != MP_OKAY) { + goto LBL_B; + } + + if ((res = mp_init(&x)) != MP_OKAY) { + goto LBL_N; + } + + if ((res = mp_init(&y)) != MP_OKAY) { + goto LBL_X; + } + + if ((res = mp_init(&z)) != MP_OKAY) { + goto LBL_Y; + } + + /* now loop making the single digit */ + while (mp_count_bits(&a) < k) { + fprintf(stderr, "prime has %4d bits left\r", k - mp_count_bits(&a)); + fflush(stderr); +top: + mp_set(&b, prime_digit()); + + /* now compute z = a * b * 2 */ + if ((res = mp_mul(&a, &b, &z)) != MP_OKAY) { /* z = a * b */ + goto LBL_Z; + } + + if ((res = mp_copy(&z, &c)) != MP_OKAY) { /* c = a * b */ + goto LBL_Z; + } + + if ((res = mp_mul_2(&z, &z)) != MP_OKAY) { /* z = 2 * a * b */ + goto LBL_Z; + } + + /* n = z + 1 */ + if ((res = mp_add_d(&z, 1uL, &n)) != MP_OKAY) { /* n = z + 1 */ + goto LBL_Z; + } + + /* check (n, v) == 1 */ + if ((res = mp_gcd(&n, &v, &y)) != MP_OKAY) { /* y = (n, v) */ + goto LBL_Z; + } + + if (mp_cmp_d(&y, 1uL) != MP_EQ) + goto top; + + /* now try base x=bases[ii] */ + for (ii = 0; ii < li; ii++) { + mp_set(&x, bases[ii]); + + /* compute x^a mod n */ + if ((res = mp_exptmod(&x, &a, &n, &y)) != MP_OKAY) { /* y = x^a mod n */ + goto LBL_Z; + } + + /* if y == 1 loop */ + if (mp_cmp_d(&y, 1uL) == MP_EQ) + continue; + + /* now x^2a mod n */ + if ((res = mp_sqrmod(&y, &n, &y)) != MP_OKAY) { /* y = x^2a mod n */ + goto LBL_Z; + } + + if (mp_cmp_d(&y, 1uL) == MP_EQ) + continue; + + /* compute x^b mod n */ + if ((res = mp_exptmod(&x, &b, &n, &y)) != MP_OKAY) { /* y = x^b mod n */ + goto LBL_Z; + } + + /* if y == 1 loop */ + if (mp_cmp_d(&y, 1uL) == MP_EQ) + continue; + + /* now x^2b mod n */ + if ((res = mp_sqrmod(&y, &n, &y)) != MP_OKAY) { /* y = x^2b mod n */ + goto LBL_Z; + } + + if (mp_cmp_d(&y, 1uL) == MP_EQ) + continue; + + /* compute x^c mod n == x^ab mod n */ + if ((res = mp_exptmod(&x, &c, &n, &y)) != MP_OKAY) { /* y = x^ab mod n */ + goto LBL_Z; + } + + /* if y == 1 loop */ + if (mp_cmp_d(&y, 1uL) == MP_EQ) + continue; + + /* now compute (x^c mod n)^2 */ + if ((res = mp_sqrmod(&y, &n, &y)) != MP_OKAY) { /* y = x^2ab mod n */ + goto LBL_Z; + } + + /* y should be 1 */ + if (mp_cmp_d(&y, 1uL) != MP_EQ) + continue; + break; + } + + /* no bases worked? */ + if (ii == li) + goto top; + + { + char buf[4096]; + + mp_to_decimal(&n, buf, sizeof(buf)); + printf("Certificate of primality for:\n%s\n\n", buf); + mp_to_decimal(&a, buf, sizeof(buf)); + printf("A == \n%s\n\n", buf); + mp_to_decimal(&b, buf, sizeof(buf)); + printf("B == \n%s\n\nG == %lu\n", buf, bases[ii]); + printf("----------------------------------------------------------------\n"); + } + + /* a = n */ + mp_copy(&n, &a); + } + + /* get q to be the order of the large prime subgroup */ + mp_sub_d(&n, 1uL, q); + mp_div_2(q, q); + mp_div(q, &b, q, NULL); + + mp_exch(&n, p); + + res = MP_OKAY; +LBL_Z: + mp_clear(&z); +LBL_Y: + mp_clear(&y); +LBL_X: + mp_clear(&x); +LBL_N: + mp_clear(&n); +LBL_B: + mp_clear(&b); +LBL_A: + mp_clear(&a); +LBL_V: + mp_clear(&v); +LBL_C: + mp_clear(&c); + return res; +} + + +int main(void) +{ + mp_int p, q; + char buf[4096]; + int k, li; + clock_t t1; + + srand(time(NULL)); + load_tab(); + + printf("Enter # of bits: \n"); + fgets(buf, sizeof(buf), stdin); + sscanf(buf, "%d", &k); + + printf("Enter number of bases to try (1 to 8):\n"); + fgets(buf, sizeof(buf), stdin); + sscanf(buf, "%d", &li); + + + mp_init(&p); + mp_init(&q); + + t1 = clock(); + pprime(k, li, &p, &q); + t1 = clock() - t1; + + printf("\n\nTook %lu ticks, %d bits\n", t1, mp_count_bits(&p)); + + mp_to_decimal(&p, buf, sizeof(buf)); + printf("P == %s\n", buf); + mp_to_decimal(&q, buf, sizeof(buf)); + printf("Q == %s\n", buf); + + return 0; +} diff --git a/deps/libtommath/etc/prime.1024 b/deps/libtommath/etc/prime.1024 new file mode 100644 index 0000000..5636e2d --- /dev/null +++ b/deps/libtommath/etc/prime.1024 @@ -0,0 +1,414 @@ +Enter # of bits: +Enter number of bases to try (1 to 8): +Certificate of primality for: +36360080703173363 + +A == +89963569 + +B == +202082249 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +4851595597739856136987139 + +A == +36360080703173363 + +B == +66715963 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +19550639734462621430325731591027 + +A == +4851595597739856136987139 + +B == +2014867 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +10409036141344317165691858509923818734539 + +A == +19550639734462621430325731591027 + +B == +266207047 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1049829549988285012736475602118094726647504414203 + +A == +10409036141344317165691858509923818734539 + +B == +50428759 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +77194737385528288387712399596835459931920358844586615003 + +A == +1049829549988285012736475602118094726647504414203 + +B == +36765367 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +35663756695365208574443215955488689578374232732893628896541201763 + +A == +77194737385528288387712399596835459931920358844586615003 + +B == +230998627 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +16711831463502165169495622246023119698415848120292671294127567620396469803 + +A == +35663756695365208574443215955488689578374232732893628896541201763 + +B == +234297127 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +6163534781560285962890718925972249753147470953579266394395432475622345597103528739 + +A == +16711831463502165169495622246023119698415848120292671294127567620396469803 + +B == +184406323 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787 + +A == +6163534781560285962890718925972249753147470953579266394395432475622345597103528739 + +B == +66054487 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187 + +A == +814258256205243497704094951432575867360065658372158511036259934640748088306764553488803787 + +B == +108362239 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419 + +A == +176469695533271657902814176811660357049007467856432383037590673407330246967781451723764079581998187 + +B == +127286707 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059 + +A == +44924492859445516541759485198544012102424796403707253610035148063863073596051272171194806669756971406400419 + +B == +229284691 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979 + +A == +20600996927219343383225424320134474929609459588323857796871086845924186191561749519858600696159932468024710985371059 + +B == +152800771 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123 + +A == +6295696427695493110141186605837397185848992307978456138112526915330347715236378041486547994708748840844217371233735072572979 + +B == +246595759 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499 + +A == +3104984078042317488749073016454213579257792635142218294052134804187631661145261015102617582090263808696699966840735333252107678792123 + +B == +4252063 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163 + +A == +26405175827665701256325699315126705508919255051121452292124404943796947287968603975320562847910946802396632302209435206627913466015741799499 + +B == +210605419 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187 + +A == +11122146237908413610034600609460545703591095894418599759742741406628055069007082998134905595800236452010905900391505454890446585211975124558601770163 + +B == +74170111 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363 + +A == +1649861642047798890580354082088712649911849362201343649289384923147797960364736011515757482030049342943790127685185806092659832129486307035500638595572396187 + +B == +260016763 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283 + +A == +857983367126266717607389719637086684134462613006415859877666235955788392464081914127715967940968197765042399904117392707518175220864852816390004264107201177394565363 + +B == +102563707 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283 + +A == +175995909353623703257072120479340610010337144085688850745292031336724691277374210929188442230237711063783727092685448718515661641054886101716698390145283196296702450566161283 + +B == +137747527 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403 + +A == +48486002551155667224487059713350447239190772068092630563272168418880661006593537218144160068395218642353495339720640699721703003648144463556291315694787862009052641640656933232794283 + +B == +135672847 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123 + +A == +13156468011529105025061495011938518171328604045212410096476697450506055664012861932372156505805788068791146986282263016790631108386790291275939575123375304599622623328517354163964228279867403 + +B == +241523587 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083 + +A == +6355194692790533601105154341731997464407930009404822926832136060319955058388106456084549316415200519472481147942263916585428906582726749131479465958107142228236909665306781538860053107680830113869123 + +B == +248388667 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067 + +A == +3157116676535430302794438027544146642863331358530722860333745617571010460905857862561870488000265751138954271040017454405707755458702044884023184574412221802502351503929935224995314581932097706874819348858083 + +B == +61849651 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739 + +A == +390533129219992506725320633489467713907837370444962163378727819939092929448752905310115311180032249230394348337568973177802874166228132778126338883671958897238722734394783244237133367055422297736215754829839364158067 + +B == +62201707 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419 + +A == +48583654555070224891047847050732516652910250240135992225139515777200432486685999462997073444468380434359929499498804723793106565291183220444221080449740542884172281158126259373095216435009661050109711341419005972852770440739 + +B == +264832231 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387 + +A == +25733035251905120039135866524384525138869748427727001128764704499071378939227862068500633813538831598776578372709963673670934388213622433800015759585470542686333039614931682098922935087822950084908715298627996115185849260703525317419 + +B == +54494047 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547 + +A == +2804594464939948901906623499531073917980499195397462605359913717827014360538186518540781517129548650937632008683280555602633122170458773895504894807182664540529077836857897972175530148107545939211339044386106111633510166695386323426241809387 + +B == +131594179 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683 + +A == +738136612083433720096707308165797114449914259256979340471077690416567237592465306112484843530074782721390528773594351482384711900456440808251196845265132086486672447136822046628407467459921823150600138073268385534588238548865012638209515923513516547 + +B == +266107603 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627 + +A == +392847529056126766528615419937165193421166694172790666626558750047057558168124866940509180171236517681470100877687445134633784815352076138790217228749332398026714192707447855731679485746120589851992221508292976900578299504461333767437280988393026452846013683 + +B == +214408111 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643 + +A == +168459393231883505975876919268398655632763956627405508859662408056221544310200546265681845397346956580604208064328814319465940958080244889692368602591598503944015835190587740756859842792554282496742843600573336023639256008687581291233481455395123454655488735304365627 + +B == +44122723 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019 + +A == +14865774288636941404884923981945833072113667565310054952177860608355263252462409554658728941191929400198053290113492910272458441655458514080123870132092365833472436407455910185221474386718838138135065780840839893113912689594815485706154461164071775481134379794909690501684643 + +B == +40808563 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843 + +A == +1213301773203241614897109856134894783021668292000023984098824423682568173639394290886185366993108292039068940333907505157813934962357206131450244004178619265868614859794316361031904412926604138893775068853175215502104744339658944443630407632290152772487455298652998368296998719996019 + +B == +77035759 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683 + +A == +186935245989515158127969129347464851990429060640910951266513740972248428651109062997368144722015290092846666943896556191257222521203647606911446635194198213436423080005867489516421559330500722264446765608763224572386410155413161172707802334865729654109050873820610813855041667633843601286843 + +B == +222383587 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443 + +A == +83142661079751490510739960019112406284111408348732592580459037404394946037094409915127399165633756159385609671956087845517678367844901424617866988187132480585966721962585586730693443536100138246516868613250009028187662080828012497191775172228832247706080044971423654632146928165751885302331924491683 + +B == +23407687 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723 + +A == +3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443 + +B == +213701827 + +G == 2 +---------------------------------------------------------------- + + +Took 33057 ticks, 1048 bits +P == 1663606652988091811284014366560171522582683318514519379924950390627250155440313691226744227787921928894551755219495501365555370027257568506349958010457682898612082048959464465369892842603765280317696116552850664773291371490339084156052244256635115997453399761029567033971998617303988376172539172702246575225837054723 +Q == 3892354773803809855317742245039794448230625839512638747643814927766738642436392673485997449586432241626440927010641564064764336402368634186618250134234189066179771240232458249806850838490410473462391401438160528157981942499581634732706904411807195259620779379274017704050790865030808501633772117217899534443 diff --git a/deps/libtommath/etc/prime.512 b/deps/libtommath/etc/prime.512 new file mode 100644 index 0000000..cb6ec30 --- /dev/null +++ b/deps/libtommath/etc/prime.512 @@ -0,0 +1,205 @@ +Enter # of bits: +Enter number of bases to try (1 to 8): +Certificate of primality for: +85933926807634727 + +A == +253758023 + +B == +169322581 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +23930198825086241462113799 + +A == +85933926807634727 + +B == +139236037 + +G == 11 +---------------------------------------------------------------- +Certificate of primality for: +6401844647261612602378676572510019 + +A == +23930198825086241462113799 + +B == +133760791 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +269731366027728777712034888684015329354259 + +A == +6401844647261612602378676572510019 + +B == +21066691 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +37942338209025571690075025099189467992329684223707 + +A == +269731366027728777712034888684015329354259 + +B == +70333567 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +15306904714258982484473490774101705363308327436988160248323 + +A == +37942338209025571690075025099189467992329684223707 + +B == +201712723 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1616744757018513392810355191503853040357155275733333124624513530099 + +A == +15306904714258982484473490774101705363308327436988160248323 + +B == +52810963 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +464222094814208047161771036072622485188658077940154689939306386289983787983 + +A == +1616744757018513392810355191503853040357155275733333124624513530099 + +B == +143566909 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +187429931674053784626487560729643601208757374994177258429930699354770049369025096447 + +A == +464222094814208047161771036072622485188658077940154689939306386289983787983 + +B == +201875281 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563 + +A == +187429931674053784626487560729643601208757374994177258429930699354770049369025096447 + +B == +268311523 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163 + +A == +100579220846502621074093727119851331775052664444339632682598589456666938521976625305832917563 + +B == +5834287 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623 + +A == +1173616081309758475197022137833792133815753368965945885089720153370737965497134878651384030219765163 + +B == +81567097 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519 + +A == +191456913489905913185935197655672585713573070349044195411728114905691721186574907738081340754373032735283623 + +B == +151095433 + +G == 7 +---------------------------------------------------------------- +Certificate of primality for: +13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803 + +A == +57856530489201750164178576399448868489243874083056587683743345599898489554401618943240901541005080049321706789987519 + +B == +119178679 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979 + +A == +13790529750452576698109671710773784949185621244122040804792403407272729038377767162233653248852099545134831722512085881814803 + +B == +256552363 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463 + +A == +7075985989000817742677547821106534174334812111605018857703825637170140040509067704269696198231266351631132464035671858077052876058979 + +B == +86720989 + +G == 5 +---------------------------------------------------------------- +Certificate of primality for: +446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763 + +A == +1227273006232588072907488910282307435921226646895131225407452056677899411162892829564455154080310937471747140942360789623819327234258162420463 + +B == +182015287 + +G == 2 +---------------------------------------------------------------- +Certificate of primality for: +5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243 + +A == +446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763 + +B == +5920567 + +G == 2 +---------------------------------------------------------------- + + +Took 3454 ticks, 521 bits +P == 5290203010849586596974953717018896543907195901082056939587768479377028575911127944611236020459652034082251335583308070846379514569838984811187823420951275243 +Q == 446764896913554613686067036908702877942872355053329937790398156069936255759889884246832779737114032666318220500106499161852193765380831330106375235763 diff --git a/deps/libtommath/etc/timer.asm b/deps/libtommath/etc/timer.asm new file mode 100644 index 0000000..326a947 --- /dev/null +++ b/deps/libtommath/etc/timer.asm @@ -0,0 +1,37 @@ +; x86 timer in NASM +; +; Tom St Denis, tomstdenis@iahu.ca +[bits 32] +[section .data] +time dd 0, 0 + +[section .text] + +%ifdef USE_ELF +[global t_start] +t_start: +%else +[global _t_start] +_t_start: +%endif + push edx + push eax + rdtsc + mov [time+0],edx + mov [time+4],eax + pop eax + pop edx + ret + +%ifdef USE_ELF +[global t_read] +t_read: +%else +[global _t_read] +_t_read: +%endif + rdtsc + sub eax,[time+4] + sbb edx,[time+0] + ret + \ No newline at end of file diff --git a/deps/libtommath/etc/tune.c b/deps/libtommath/etc/tune.c new file mode 100644 index 0000000..8ad2028 --- /dev/null +++ b/deps/libtommath/etc/tune.c @@ -0,0 +1,544 @@ +/* Tune the Karatsuba parameters + * + * Tom St Denis, tstdenis82@gmail.com + */ +#include "tommath_private.h" +#include +#include +#include + +#define S_MP_RAND_JENKINS_C +#include "../demo/s_mp_rand_jenkins.c" + +/* + Please take in mind that both multiplicands are of the same size. The balancing + mechanism in mp_balance works well but has some overhead itself. You can test + the behaviour of it with the option "-o" followed by a (small) positive number 'x' + to generate ratios of the form 1:x. +*/ + +static uint64_t s_timer_function(void); +static void s_timer_start(void); +static uint64_t s_timer_stop(void); +static uint64_t s_time_mul(int size); +static uint64_t s_time_sqr(int size); +static void s_usage(char *s); + +static uint64_t s_timer_function(void) +{ +#if _POSIX_C_SOURCE >= 199309L +#define LTM_BILLION 1000000000 + struct timespec ts; + + /* TODO: Sets errno in case of error. Use? */ + clock_gettime(CLOCK_MONOTONIC, &ts); + return (((uint64_t)ts.tv_sec) * LTM_BILLION + (uint64_t)ts.tv_nsec); +#else + clock_t t; + t = clock(); + if (t < (clock_t)(0)) { + return (uint64_t)(0); + } + return (uint64_t)(t); +#endif +} + +/* generic ISO C timer */ +static uint64_t s_timer_tmp; +static void s_timer_start(void) +{ + s_timer_tmp = s_timer_function(); +} +static uint64_t s_timer_stop(void) +{ + return s_timer_function() - s_timer_tmp; +} + + +static int s_check_result; +static int s_number_of_test_loops; +static int s_stabilization_extra; +static int s_offset = 1; + +#define s_mp_mul_full(a, b, c) s_mp_mul(a, b, c, (a)->used + (b)->used + 1) +static uint64_t s_time_mul(int size) +{ + int x; + mp_err e; + mp_int a, b, c, d; + uint64_t t1; + + if ((e = mp_init_multi(&a, &b, &c, &d, NULL)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + + if ((e = mp_rand(&a, size * s_offset)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + if ((e = mp_rand(&b, size)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + + s_timer_start(); + for (x = 0; x < s_number_of_test_loops; x++) { + if ((e = mp_mul(&a,&b,&c)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + if (s_check_result == 1) { + if ((e = s_mp_mul_full(&a,&b,&d)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + if (mp_cmp(&c, &d) != MP_EQ) { + /* Time of 0 cannot happen (famous last words?) */ + t1 = 0u; + goto LBL_ERR; + } + } + } + + t1 = s_timer_stop(); +LBL_ERR: + mp_clear_multi(&a, &b, &c, &d, NULL); + return t1; +} + +static uint64_t s_time_sqr(int size) +{ + int x; + mp_err e; + mp_int a, b, c; + uint64_t t1; + + if ((e = mp_init_multi(&a, &b, &c, NULL)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + + if ((e = mp_rand(&a, size)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + + s_timer_start(); + for (x = 0; x < s_number_of_test_loops; x++) { + if ((e = mp_sqr(&a,&b)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + if (s_check_result == 1) { + if ((e = s_mp_sqr(&a,&c)) != MP_OKAY) { + t1 = UINT64_MAX; + goto LBL_ERR; + } + if (mp_cmp(&c, &b) != MP_EQ) { + t1 = 0u; + goto LBL_ERR; + } + } + } + + t1 = s_timer_stop(); +LBL_ERR: + mp_clear_multi(&a, &b, &c, NULL); + return t1; +} + +struct tune_args { + int testmode; + int verbose; + int print; + int bncore; + int terse; + int upper_limit_print; + int increment_print; +} args; + +static void s_run(const char *name, uint64_t (*op)(int size), int *cutoff) +{ + int x, count = 0; + uint64_t t1, t2; + if ((args.verbose == 1) || (args.testmode == 1)) { + printf("# %s.\n", name); + } + for (x = 8; x < args.upper_limit_print; x += args.increment_print) { + *cutoff = INT_MAX; + t1 = op(x); + if ((t1 == 0u) || (t1 == UINT64_MAX)) { + fprintf(stderr,"%s failed at x = INT_MAX (%s)\n", name, + (t1 == 0u)?"wrong result":"internal error"); + exit(EXIT_FAILURE); + } + *cutoff = x; + t2 = op(x); + if ((t2 == 0u) || (t2 == UINT64_MAX)) { + fprintf(stderr,"%s failed (%s)\n", name, + (t2 == 0u)?"wrong result":"internal error"); + exit(EXIT_FAILURE); + } + if (args.verbose == 1) { + printf("%d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + } + if (t2 < t1) { + if (count == s_stabilization_extra) { + count = 0; + break; + } else if (count < s_stabilization_extra) { + count++; + } + } else if (count > 0) { + count--; + } + } + *cutoff = x - s_stabilization_extra * args.increment_print; +} + +static long s_strtol(const char *str, char **endptr, const char *err) +{ + const int base = 10; + char *_endptr; + long val; + errno = 0; + val = strtol(str, &_endptr, base); + if ((val > INT_MAX || val < 0) || (errno != 0)) { + fprintf(stderr, "Value %s not usable\n", str); + exit(EXIT_FAILURE); + } + if (_endptr == str) { + fprintf(stderr, "%s\n", err); + exit(EXIT_FAILURE); + } + if (endptr != NULL) *endptr = _endptr; + return val; +} + +static int s_exit_code = EXIT_FAILURE; +static void s_usage(char *s) +{ + fprintf(stderr,"Usage: %s [TvcpGbtrSLFfMmosh]\n",s); + fprintf(stderr," -T testmode, for use with testme.sh\n"); + fprintf(stderr," -v verbose, print all timings\n"); + fprintf(stderr," -c check results\n"); + fprintf(stderr," -p print benchmark of final cutoffs in files \"multiplying\"\n"); + fprintf(stderr," and \"squaring\"\n"); + fprintf(stderr," -G [string] suffix for the filenames listed above\n"); + fprintf(stderr," Implies '-p'\n"); + fprintf(stderr," -b print benchmark of bncore.c\n"); + fprintf(stderr," -t prints space (0x20) separated results\n"); + fprintf(stderr," -r [64] number of rounds\n"); + fprintf(stderr," -S [0xdeadbeef] seed for PRNG\n"); + fprintf(stderr," -L [3] number of negative values accumulated until the result is accepted\n"); + fprintf(stderr," -M [3000] upper limit of T-C tests/prints\n"); + fprintf(stderr," -m [1] increment of T-C tests/prints\n"); + fprintf(stderr," -o [1] multiplier for the second multiplicand\n"); + fprintf(stderr," (Not for computing the cut-offs!)\n"); + fprintf(stderr," -s 'preset' use values in 'preset' for printing.\n"); + fprintf(stderr," 'preset' is a comma separated string with cut-offs for\n"); + fprintf(stderr," ksm, kss, tc3m, tc3s in that order\n"); + fprintf(stderr," ksm = karatsuba multiplication\n"); + fprintf(stderr," kss = karatsuba squaring\n"); + fprintf(stderr," tc3m = Toom-Cook 3-way multiplication\n"); + fprintf(stderr," tc3s = Toom-Cook 3-way squaring\n"); + fprintf(stderr," Implies '-p'\n"); + fprintf(stderr," -h this message\n"); + exit(s_exit_code); +} + +struct cutoffs { + int MUL_KARATSUBA, SQR_KARATSUBA; + int MUL_TOOM, SQR_TOOM; +}; + +const struct cutoffs max_cutoffs = +{ INT_MAX, INT_MAX, INT_MAX, INT_MAX }; + +static void set_cutoffs(const struct cutoffs *c) +{ + MP_MUL_KARATSUBA_CUTOFF = c->MUL_KARATSUBA; + MP_SQR_KARATSUBA_CUTOFF = c->SQR_KARATSUBA; + MP_MUL_TOOM_CUTOFF = c->MUL_TOOM; + MP_SQR_TOOM_CUTOFF = c->SQR_TOOM; +} + +static void get_cutoffs(struct cutoffs *c) +{ + c->MUL_KARATSUBA = MP_MUL_KARATSUBA_CUTOFF; + c->SQR_KARATSUBA = MP_SQR_KARATSUBA_CUTOFF; + c->MUL_TOOM = MP_MUL_TOOM_CUTOFF; + c->SQR_TOOM = MP_SQR_TOOM_CUTOFF; + +} + +int main(int argc, char **argv) +{ + uint64_t t1, t2; + int x, i, j; + size_t n; + + int printpreset = 0; + /*int preset[8];*/ + char *endptr, *str; + + uint64_t seed = 0xdeadbeefULL; + + int opt; + struct cutoffs orig, updated; + + FILE *squaring, *multiplying; + char mullog[256] = "multiplying"; + char sqrlog[256] = "squaring"; + s_number_of_test_loops = 64; + s_stabilization_extra = 3; + + s_mp_zero_buf(&args, sizeof(args)); + + args.testmode = 0; + args.verbose = 0; + args.print = 0; + args.bncore = 0; + args.terse = 0; + + args.upper_limit_print = 3000; + args.increment_print = 1; + + /* Very simple option parser, please treat it nicely. */ + if (argc != 1) { + for (opt = 1; (opt < argc) && (argv[opt][0] == '-'); opt++) { + switch (argv[opt][1]) { + case 'T': + args.testmode = 1; + s_check_result = 1; + args.upper_limit_print = 1000; + args.increment_print = 11; + s_number_of_test_loops = 1; + s_stabilization_extra = 1; + s_offset = 1; + break; + case 'v': + args.verbose = 1; + break; + case 'c': + s_check_result = 1; + break; + case 'p': + args.print = 1; + break; + case 'G': + args.print = 1; + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + /* manual strcat() */ + for (i = 0; i < 255; i++) { + if (mullog[i] == '\0') { + break; + } + } + for (j = 0; i < 255; j++, i++) { + mullog[i] = argv[opt][j]; + if (argv[opt][j] == '\0') { + break; + } + } + for (i = 0; i < 255; i++) { + if (sqrlog[i] == '\0') { + break; + } + } + for (j = 0; i < 255; j++, i++) { + sqrlog[i] = argv[opt][j]; + if (argv[opt][j] == '\0') { + break; + } + } + break; + case 'b': + args.bncore = 1; + break; + case 't': + args.terse = 1; + break; + case 'S': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + str = argv[opt]; + errno = 0; + seed = (uint64_t)s_strtol(argv[opt], NULL, "No seed given?\n"); + break; + case 'L': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + s_stabilization_extra = (int)s_strtol(argv[opt], NULL, "No value for option \"-L\"given"); + break; + case 'o': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + s_offset = (int)s_strtol(argv[opt], NULL, "No value for the offset given"); + break; + case 'r': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + s_number_of_test_loops = (int)s_strtol(argv[opt], NULL, "No value for the number of rounds given"); + break; + + case 'M': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + args.upper_limit_print = (int)s_strtol(argv[opt], NULL, "No value for the upper limit of T-C tests given"); + break; + case 'm': + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + args.increment_print = (int)s_strtol(argv[opt], NULL, "No value for the increment for the T-C tests given"); + break; + case 's': + printpreset = 1; + args.print = 1; + opt++; + if (opt >= argc) { + s_usage(argv[0]); + } + str = argv[opt]; + MP_MUL_KARATSUBA_CUTOFF = (int)s_strtol(str, &endptr, "[1/4] No value for MP_MUL_KARATSUBA_CUTOFF given"); + str = endptr + 1; + MP_SQR_KARATSUBA_CUTOFF = (int)s_strtol(str, &endptr, "[2/4] No value for MP_SQR_KARATSUBA_CUTOFF given"); + str = endptr + 1; + MP_MUL_TOOM_CUTOFF = (int)s_strtol(str, &endptr, "[3/4] No value for MP_MUL_TOOM_CUTOFF given"); + str = endptr + 1; + MP_SQR_TOOM_CUTOFF = (int)s_strtol(str, &endptr, "[4/4] No value for MP_SQR_TOOM_CUTOFF given"); + break; + case 'h': + s_exit_code = EXIT_SUCCESS; + /* FALLTHROUGH */ + default: + s_usage(argv[0]); + } + } + } + + /* + mp_rand uses the cryptographically secure + source of the OS by default. That is too expensive, too slow and + most important for a benchmark: it is not repeatable. + */ + s_mp_rand_jenkins_init(seed); + mp_rand_source(s_mp_rand_jenkins); + + get_cutoffs(&orig); + + updated = max_cutoffs; + if ((args.bncore == 0) && (printpreset == 0)) { + struct { + const char *name; + int *cutoff, *update; + uint64_t (*fn)(int size); + } test[] = { +#define T_MUL_SQR(n, o, f) { #n, &MP_##o##_CUTOFF, &(updated.o), MP_HAS(S_MP_##o) ? f : NULL } + /* + The influence of the Comba multiplication cannot be + eradicated programmatically. It depends on the size + of the macro MP_WPARRAY in tommath.h which needs to + be changed manually (to 0 (zero)). + */ + T_MUL_SQR("Karatsuba multiplication", MUL_KARATSUBA, s_time_mul), + T_MUL_SQR("Karatsuba squaring", SQR_KARATSUBA, s_time_sqr), + T_MUL_SQR("Toom-Cook 3-way multiplying", MUL_TOOM, s_time_mul), + T_MUL_SQR("Toom-Cook 3-way squaring", SQR_TOOM, s_time_sqr), +#undef T_MUL_SQR + }; + /* Turn all limits from bncore.c to the max */ + set_cutoffs(&max_cutoffs); + for (n = 0; n < sizeof(test)/sizeof(test[0]); ++n) { + if (test[n].fn != NULL) { + s_run(test[n].name, test[n].fn, test[n].cutoff); + *test[n].update = *test[n].cutoff; + *test[n].cutoff = INT_MAX; + } + } + } + if (args.terse == 1) { + printf("%d %d %d %d\n", + updated.MUL_KARATSUBA, + updated.SQR_KARATSUBA, + updated.MUL_TOOM, + updated.SQR_TOOM); + } else { + printf("MUL_KARATSUBA_CUTOFF = %d\n", updated.MUL_KARATSUBA); + printf("SQR_KARATSUBA_CUTOFF = %d\n", updated.SQR_KARATSUBA); + printf("MUL_TOOM_CUTOFF = %d\n", updated.MUL_TOOM); + printf("SQR_TOOM_CUTOFF = %d\n", updated.SQR_TOOM); + } + + if (args.print == 1) { + printf("Printing data for graphing to \"%s\" and \"%s\"\n",mullog, sqrlog); + + multiplying = fopen(mullog, "w+"); + if (multiplying == NULL) { + fprintf(stderr, "Opening file \"%s\" failed\n", mullog); + exit(EXIT_FAILURE); + } + + squaring = fopen(sqrlog, "w+"); + if (squaring == NULL) { + fprintf(stderr, "Opening file \"%s\" failed\n",sqrlog); + exit(EXIT_FAILURE); + } + + for (x = 8; x < args.upper_limit_print; x += args.increment_print) { + set_cutoffs(&max_cutoffs); + t1 = s_time_mul(x); + set_cutoffs(&orig); + t2 = s_time_mul(x); + fprintf(multiplying, "%d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(multiplying); + if (args.verbose == 1) { + printf("MUL %d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(stdout); + } + set_cutoffs(&max_cutoffs); + t1 = s_time_sqr(x); + set_cutoffs(&orig); + t2 = s_time_sqr(x); + fprintf(squaring,"%d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(squaring); + if (args.verbose == 1) { + printf("SQR %d: %9" PRIu64 " %9" PRIu64 ", %9" PRIi64 "\n", x, t1, t2, (int64_t)t2 - (int64_t)t1); + fflush(stdout); + } + } + printf("Finished. Data for graphing in \"%s\" and \"%s\"\n",mullog, sqrlog); + if (args.verbose == 1) { + set_cutoffs(&orig); + if (args.terse == 1) { + printf("%d %d %d %d\n", + MP_MUL_KARATSUBA_CUTOFF, + MP_SQR_KARATSUBA_CUTOFF, + MP_MUL_TOOM_CUTOFF, + MP_SQR_TOOM_CUTOFF); + } else { + printf("MUL_KARATSUBA_CUTOFF = %d\n", MP_MUL_KARATSUBA_CUTOFF); + printf("SQR_KARATSUBA_CUTOFF = %d\n", MP_SQR_KARATSUBA_CUTOFF); + printf("MUL_TOOM_CUTOFF = %d\n", MP_MUL_TOOM_CUTOFF); + printf("SQR_TOOM_CUTOFF = %d\n", MP_SQR_TOOM_CUTOFF); + } + } + } + exit(EXIT_SUCCESS); +} diff --git a/deps/libtommath/etc/tune_it.sh b/deps/libtommath/etc/tune_it.sh new file mode 100644 index 0000000..dba5b69 --- /dev/null +++ b/deps/libtommath/etc/tune_it.sh @@ -0,0 +1,106 @@ +#!/bin/sh + +die() { + echo "$1 failed" + echo "Exiting" + exit $2 +} +# A linear congruential generator is sufficient for the purpose. +SEED=3735928559 +LCG() { + SEED=$(((1103515245 * $SEED + 12345) % 2147483648)) + echo $SEED +} +median() { +# read everything besides the header from file $1 +# | cut-out the required column $2 +# | sort all the entries numerically +# | show only the first $3 entries +# | show only the last entry + tail -n +2 $1 | cut -d' ' -f$2 | sort -n | head -n $3 | tail -n 1 +} + +MPWD=$(dirname $(readlink -f "$0")) +FILE_NAME="tuning_list" +TOMMATH_CUTOFFS_H="$MPWD/../tommath_cutoffs.h" +BACKUP_SUFFIX=".orig" +RNUM=0 + +############################################################################# +# It would be a good idea to isolate these processes (with e.g.: cpuset) # +# # +# It is not a good idea to e.g: watch high resolution videos while this # +# test are running if you do not have enough memory to avoid page faults. # +############################################################################# + +# Number of rounds overall. +LIMIT=100 +# Number of loops for each input. +RLOOPS=10 +# Offset ( > 0 ) . Runs tests with asymmetric input of the form 1:OFFSET +# Please use another destination for TOMMATH_CUTOFFS_H if you change OFFSET, because the numbers +# with an offset different from 1 (one) are not usable as the general cut-off values +# in "tommath_cutoffs.h". +OFFSET=1 +# Number ( >= 3 ) of positive results (TC-is-faster) accumulated until it is accepted. +# Due to the algorithm used to compute the median in this Posix compliant shell script +# the value needs to be 3 (three), not less, to keep the variation small. +LAG=3 +# Keep the temporary file $FILE_NAME. Set to 0 (zero) to remove it at the end. +# The file is in a format fit to feed into R directly. If you do it and find the median +# of this program to be off by more than a couple: please contact the authors and report +# the numbers from this program and R and the standard deviation. This program is known +# to get larger errors if the standard deviation is larger than ~50. +KEEP_TEMP=1 + +echo "You might like to watch the numbers go up to $LIMIT but it will take a long time!" + +# Might not have sufficient rights or disc full. +echo "km ks tc3m tc3s" > $FILE_NAME || die "Writing header to $FILE_NAME" $? +i=1 +while [ $i -le $LIMIT ]; do + RNUM=$(LCG) + printf "\r%d" $i + "$MPWD"/tune -t -r $RLOOPS -L $LAG -S "$RNUM" -o $OFFSET >> $FILE_NAME || die "tune" $? + i=$((i + 1)) +done + +if [ $KEEP_TEMP -eq 0 ]; then + rm -v $FILE_NAME || die "Removing $KEEP_TEMP" $? +fi + +echo "Writing cut-off values to \"$TOMMATH_CUTOFFS_H\"." +echo "In case of failure: a copy of \"$TOMMATH_CUTOFFS_H\" is in \"$TOMMATH_CUTOFFS_H$BACKUP_SUFFIX\"" + +cp -v $TOMMATH_CUTOFFS_H $TOMMATH_CUTOFFS_H$BACKUP_SUFFIX || die "Making backup copy of $TOMMATH_CUTOFFS_H" $? + +cat << END_OF_INPUT > $TOMMATH_CUTOFFS_H || die "Writing header to $TOMMATH_CUTOFFS_H" $? +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +/* + Current values evaluated on an AMD A8-6600K (64-bit). + Type "make tune" to optimize them for your machine but + be aware that it may take a long time. It took 2:30 minutes + on the aforementioned machine for example. + */ +END_OF_INPUT + +# The Posix shell does not offer an array data type so we create +# the median with 'standard tools'^TM + +# read the file (without the first line) and count the lines +i=$(tail -n +2 $FILE_NAME | wc -l) +# our median point will be at $i entries +i=$(( (i / 2) + 1 )) +TMP=$(median $FILE_NAME 1 $i) +echo "#define MP_DEFAULT_MUL_KARATSUBA_CUTOFF $TMP" +echo "#define MP_DEFAULT_MUL_KARATSUBA_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(km) Appending to $TOMMATH_CUTOFFS_H" $? +TMP=$(median $FILE_NAME 2 $i) +echo "#define MP_DEFAULT_SQR_KARATSUBA_CUTOFF $TMP" +echo "#define MP_DEFAULT_SQR_KARATSUBA_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(ks) Appending to $TOMMATH_CUTOFFS_H" $? +TMP=$(median $FILE_NAME 3 $i) +echo "#define MP_DEFAULT_MUL_TOOM_CUTOFF $TMP" +echo "#define MP_DEFAULT_MUL_TOOM_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(tc3m) Appending to $TOMMATH_CUTOFFS_H" $? +TMP=$(median $FILE_NAME 4 $i) +echo "#define MP_DEFAULT_SQR_TOOM_CUTOFF $TMP" +echo "#define MP_DEFAULT_SQR_TOOM_CUTOFF $TMP" >> $TOMMATH_CUTOFFS_H || die "(tc3s) Appending to $TOMMATH_CUTOFFS_H" $? diff --git a/deps/libtommath/helper.pl b/deps/libtommath/helper.pl new file mode 100644 index 0000000..e5ad27a --- /dev/null +++ b/deps/libtommath/helper.pl @@ -0,0 +1,500 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Getopt::Long; +use File::Find 'find'; +use File::Basename 'basename'; +use File::Glob 'bsd_glob'; + +sub read_file { + my $f = shift; + open my $fh, "<", $f or die "FATAL: read_rawfile() cannot open file '$f': $!"; + binmode $fh; + return do { local $/; <$fh> }; +} + +sub write_file { + my ($f, $data) = @_; + die "FATAL: write_file() no data" unless defined $data; + open my $fh, ">", $f or die "FATAL: write_file() cannot open file '$f': $!"; + binmode $fh; + print $fh $data or die "FATAL: write_file() cannot write to '$f': $!"; + close $fh or die "FATAL: write_file() cannot close '$f': $!"; + return; +} + +sub sanitize_comments { + my($content) = @_; + $content =~ s{/\*(.*?)\*/}{my $x=$1; $x =~ s/\w/x/g; "/*$x*/";}egs; + return $content; +} + +sub check_source { + my @all_files = ( + bsd_glob("makefile*"), + bsd_glob("*.{h,c,sh,pl}"), + bsd_glob("*/*.{h,c,sh,pl}"), + ); + + my $fails = 0; + for my $file (sort @all_files) { + my $troubles = {}; + my $lineno = 1; + my $content = read_file($file); + $content = sanitize_comments $content; + push @{$troubles->{crlf_line_end}}, '?' if $content =~ /\r/; + for my $l (split /\n/, $content) { + push @{$troubles->{merge_conflict}}, $lineno if $l =~ /^(<<<<<<<|=======|>>>>>>>)([^<=>]|$)/; + push @{$troubles->{trailing_space}}, $lineno if $l =~ / $/; + push @{$troubles->{tab}}, $lineno if $l =~ /\t/ && basename($file) !~ /^makefile/i; + push @{$troubles->{non_ascii_char}}, $lineno if $l =~ /[^[:ascii:]]/; + push @{$troubles->{cpp_comment}}, $lineno if $file =~ /\.(c|h)$/ && ($l =~ /\s\/\// || $l =~ /\/\/\s/); + # we prefer using MP_MALLOC, MP_FREE, MP_REALLOC, MP_CALLOC ... + push @{$troubles->{unwanted_malloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmalloc\s*\(/; + push @{$troubles->{unwanted_realloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\brealloc\s*\(/; + push @{$troubles->{unwanted_calloc}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bcalloc\s*\(/; + push @{$troubles->{unwanted_free}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bfree\s*\(/; + # and we probably want to also avoid the following + push @{$troubles->{unwanted_memcpy}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemcpy\s*\(/ && $file !~ /s_mp_copy_digs.c/; + push @{$troubles->{unwanted_memset}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemset\s*\(/ && $file !~ /s_mp_zero_buf.c/ && $file !~ /s_mp_zero_digs.c/; + push @{$troubles->{unwanted_memmove}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemmove\s*\(/; + push @{$troubles->{unwanted_memcmp}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bmemcmp\s*\(/; + push @{$troubles->{unwanted_strcmp}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bstrcmp\s*\(/; + push @{$troubles->{unwanted_strcpy}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bstrcpy\s*\(/; + push @{$troubles->{unwanted_strncpy}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bstrncpy\s*\(/; + push @{$troubles->{unwanted_clock}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bclock\s*\(/; + push @{$troubles->{unwanted_qsort}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bqsort\s*\(/; + push @{$troubles->{sizeof_no_brackets}}, $lineno if $file =~ /^[^\/]+\.c$/ && $l =~ /\bsizeof\s*[^\(]/; + if ($file =~ m|^[^\/]+\.c$| && $l =~ /^static(\s+[a-zA-Z0-9_]+)+\s+([a-zA-Z0-9_]+)\s*\(/) { + my $funcname = $2; + # static functions should start with s_ + push @{$troubles->{staticfunc_name}}, "$lineno($funcname)" if $funcname !~ /^s_/; + } + $lineno++; + } + for my $k (sort keys %$troubles) { + warn "[$k] $file line:" . join(",", @{$troubles->{$k}}) . "\n"; + $fails++; + } + } + + warn( $fails > 0 ? "check-source: FAIL $fails\n" : "check-source: PASS\n" ); + return $fails; +} + +sub check_comments { + my $fails = 0; + my $first_comment = <<'MARKER'; +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +MARKER + #my @all_files = (bsd_glob("*.{h,c}"), bsd_glob("*/*.{h,c}")); + my @all_files = (bsd_glob("*.{h,c}")); + for my $f (@all_files) { + my $txt = read_file($f); + if ($txt !~ /\Q$first_comment\E/s) { + warn "[first_comment] $f\n"; + $fails++; + } + } + warn( $fails > 0 ? "check-comments: FAIL $fails\n" : "check-comments: PASS\n" ); + return $fails; +} + +sub check_doc { + my $fails = 0; + my $tex = read_file('doc/bn.tex'); + my $tmh = read_file('tommath.h'); + my @functions = $tmh =~ /\n\s*[a-zA-Z0-9_* ]+?(mp_[a-z0-9_]+)\s*\([^\)]+\)\s*[MP_WUR]+?;/sg; + my @macros = $tmh =~ /\n\s*#define\s+([a-z0-9_]+)\s*\([^\)]+\)/sg; + for my $n (sort @functions) { + (my $nn = $n) =~ s/_/\\_/g; # mp_sub_d >> mp\_sub\_d + if ($tex !~ /index\Q{$nn}\E/) { + warn "[missing_doc_for_function] $n\n"; + $fails++ + } + } + for my $n (sort @macros) { + (my $nn = $n) =~ s/_/\\_/g; # mp_iszero >> mp\_iszero + if ($tex !~ /index\Q{$nn}\E/) { + warn "[missing_doc_for_macro] $n\n"; + $fails++ + } + } + warn( $fails > 0 ? "check_doc: FAIL $fails\n" : "check-doc: PASS\n" ); + return $fails; +} + +sub prepare_variable { + my ($varname, @list) = @_; + my $output = "$varname="; + my $len = length($output); + foreach my $obj (sort @list) { + $len = $len + length $obj; + $obj =~ s/\*/\$/; + if ($len > 100) { + $output .= "\\\n"; + $len = length $obj; + } + $output .= $obj . ' '; + } + $output =~ s/ $//; + return $output; +} + +sub prepare_msvc_files_xml { + my ($all, $exclude_re, $targets) = @_; + my $last = []; + my $depth = 2; + + # sort files in the same order as visual studio (ugly, I know) + my @parts = (); + for my $orig (@$all) { + my $p = $orig; + $p =~ s|/|/~|g; + $p =~ s|/~([^/]+)$|/$1|g; + my @l = map { sprintf "% -99s", $_ } split /\//, $p; + push @parts, [ $orig, join(':', @l) ]; + } + my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } @parts; + + my $files = "\r\n"; + for my $full (@sorted) { + my @items = split /\//, $full; # split by '/' + $full =~ s|/|\\|g; # replace '/' bt '\' + shift @items; # drop first one (src) + pop @items; # drop last one (filename.ext) + my $current = \@items; + if (join(':', @$current) ne join(':', @$last)) { + my $common = 0; + $common++ while ($last->[$common] && $current->[$common] && $last->[$common] eq $current->[$common]); + my $back = @$last - $common; + if ($back > 0) { + $files .= ("\t" x --$depth) . "\r\n" for (1..$back); + } + my $fwd = [ @$current ]; splice(@$fwd, 0, $common); + for my $i (0..scalar(@$fwd) - 1) { + $files .= ("\t" x $depth) . "[$i]\"\r\n"; + $files .= ("\t" x $depth) . "\t>\r\n"; + $depth++; + } + $last = $current; + } + $files .= ("\t" x $depth) . "\r\n"; + if ($full =~ $exclude_re) { + for (@$targets) { + $files .= ("\t" x $depth) . "\t\r\n"; + $files .= ("\t" x $depth) . "\t\t\r\n"; + $files .= ("\t" x $depth) . "\t\r\n"; + } + } + $files .= ("\t" x $depth) . "\r\n"; + } + $files .= ("\t" x --$depth) . "\r\n" for (@$last); + $files .= "\t"; + return $files; +} + +sub patch_file { + my ($content, @variables) = @_; + for my $v (@variables) { + if ($v =~ /^([A-Z0-9_]+)\s*=.*$/si) { + my $name = $1; + $content =~ s/\n\Q$name\E\b.*?[^\\]\n/\n$v\n/s; + } + else { + die "patch_file failed: " . substr($v, 0, 30) . ".."; + } + } + return $content; +} + +sub make_sources_cmake { + my ($src_ref, $hdr_ref) = @_; + my @sources = @{ $src_ref }; + my @headers = @{ $hdr_ref }; + my $output = "# SPDX-License-Identifier: Unlicense +# Autogenerated File! Do not edit. + +set(SOURCES\n"; + foreach my $sobj (sort @sources) { + $output .= $sobj . "\n"; + } + $output .= ")\n\nset(HEADERS\n"; + foreach my $hobj (sort @headers) { + $output .= $hobj . "\n"; + } + $output .= ")\n"; + return $output; +} + +sub process_makefiles { + my $write = shift; + my $changed_count = 0; + my @headers = bsd_glob("*.h"); + my @sources = bsd_glob("*.c"); + my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } @sources; + my @all = sort(@sources, @headers); + + my $var_o = prepare_variable("OBJECTS", @o); + (my $var_obj = $var_o) =~ s/\.o\b/.obj/sg; + + # update MSVC project files + my $msvc_files = prepare_msvc_files_xml(\@all, qr/NOT_USED_HERE/, ['Debug|Win32', 'Release|Win32', 'Debug|x64', 'Release|x64']); + for my $m (qw/libtommath_VS2008.vcproj/) { + my $old = read_file($m); + my $new = $old; + $new =~ s|.*|$msvc_files|s; + if ($old ne $new) { + write_file($m, $new) if $write; + warn "changed: $m\n"; + $changed_count++; + } + } + + # update OBJECTS + HEADERS in makefile* + for my $m (qw/ makefile makefile.shared makefile_include.mk makefile.msvc makefile.unix makefile.mingw sources.cmake /) { + my $old = read_file($m); + my $new = $m eq 'makefile.msvc' ? patch_file($old, $var_obj) + : $m eq 'sources.cmake' ? make_sources_cmake(\@sources, \@headers) + : patch_file($old, $var_o); + + if ($old ne $new) { + write_file($m, $new) if $write; + warn "changed: $m\n"; + $changed_count++; + } + } + + if ($write) { + return 0; # no failures + } + else { + warn( $changed_count > 0 ? "check-makefiles: FAIL $changed_count\n" : "check-makefiles: PASS\n" ); + return $changed_count; + } +} + +sub draw_func +{ + my ($deplist, $depmap, $out, $indent, $funcslist) = @_; + my @funcs = split ',', $funcslist; + # try this if you want to have a look at a minimized version of the callgraph without all the trivial functions + #if ($deplist =~ /$funcs[0]/ || $funcs[0] =~ /MP_(ADD|SUB|CLEAR|CLEAR_\S+|DIV|MUL|COPY|ZERO|GROW|CLAMP|INIT|INIT_\S+|SET|ABS|CMP|CMP_D|EXCH)_C/) { + if ($deplist =~ /$funcs[0]/) { + return $deplist; + } else { + $deplist = $deplist . $funcs[0]; + } + if ($indent == 0) { + } elsif ($indent >= 1) { + print {$out} '| ' x ($indent - 1) . '+--->'; + } + print {$out} $funcs[0] . "\n"; + shift @funcs; + my $olddeplist = $deplist; + foreach my $i (@funcs) { + $deplist = draw_func($deplist, $depmap, $out, $indent + 1, ${$depmap}{$i}) if exists ${$depmap}{$i}; + } + return $olddeplist; +} + +sub update_dep +{ + #open class file and write preamble + open(my $class, '>', 'tommath_class.h') or die "Couldn't open tommath_class.h for writing\n"; + print {$class} << 'EOS'; +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#define LTM_INSIDE +#if defined(LTM2) +# define LTM3 +#endif +#if defined(LTM1) +# define LTM2 +#endif +#define LTM1 +#if defined(LTM_ALL) +EOS + + foreach my $filename (glob '*mp_*.c') { + my $define = $filename; + + print "Processing $filename\n"; + + # convert filename to upper case so we can use it as a define + $define =~ tr/[a-z]/[A-Z]/; + $define =~ tr/\./_/; + print {$class} "# define $define\n"; + + # now copy text and apply #ifdef as required + my $apply = 0; + open(my $src, '<', $filename); + open(my $out, '>', 'tmp'); + + # first line will be the #ifdef + my $line = <$src>; + if ($line =~ /include/) { + print {$out} $line; + } else { + print {$out} << "EOS"; +#include "tommath_private.h" +#ifdef $define +/* LibTomMath, multiple-precision integer library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +$line +EOS + $apply = 1; + } + while (<$src>) { + if ($_ !~ /tommath\.h/) { + print {$out} $_; + } + } + if ($apply == 1) { + print {$out} "#endif\n"; + } + close $src; + close $out; + + unlink $filename; + rename 'tmp', $filename; + } + print {$class} "#endif\n#endif\n"; + + # now do classes + my %depmap; + foreach my $filename (glob '*mp_*.c') { + my $content; + my $cc = $ENV{'CC'} || 'gcc'; + $content = `$cc -E -x c -DLTM_ALL $filename`; + $content =~ s/^# 1 "$filename".*?^# 2 "$filename"//ms; + + # convert filename to upper case so we can use it as a define + $filename =~ tr/[a-z]/[A-Z]/; + $filename =~ tr/\./_/; + + print {$class} "#if defined($filename)\n"; + my $list = $filename; + + # strip comments + $content =~ s{/\*.*?\*/}{}gs; + + # scan for mp_* and make classes + my @deps = (); + foreach my $line (split /\n/, $content) { + while ($line =~ /(fast_)?(s_)?mp\_[a-z_0-9]*((?=\;)|(?=\())|(?<=\()mp\_[a-z_0-9]*(?=\()/g) { + my $a = $&; + next if $a eq "mp_err"; + $a =~ tr/[a-z]/[A-Z]/; + $a = $a . '_C'; + push @deps, $a; + } + } + @deps = sort(@deps); + foreach my $a (@deps) { + if ($list !~ /$a/) { + print {$class} "# define $a\n"; + } + $list = $list . ',' . $a; + } + $depmap{$filename} = $list; + + print {$class} "#endif\n\n"; + } + + print {$class} << 'EOS'; +#ifdef LTM_INSIDE +#undef LTM_INSIDE +#ifdef LTM3 +# define LTM_LAST +#endif + +#include "tommath_superclass.h" +#include "tommath_class.h" +#else +# define LTM_LAST +#endif +EOS + close $class; + + #now let's make a cool call graph... + + open(my $out, '>', 'callgraph.txt'); + foreach (sort keys %depmap) { + draw_func("", \%depmap, $out, 0, $depmap{$_}); + print {$out} "\n\n"; + } + close $out; + + return 0; +} + +sub generate_def { + my @files = glob '*mp_*.c'; + @files = map { my $x = $_; $x =~ s/\.c$//g; $x; } @files; + @files = grep(!/mp_cutoffs/, @files); + + my $files = join("\n ", sort(grep(/^mp_/, @files))); + write_file "tommath.def", "; libtommath +; +; Use this command to produce a 32-bit .lib file, for use in any MSVC version +; lib -machine:X86 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; Use this command to produce a 64-bit .lib file, for use in any MSVC version +; lib -machine:X64 -name:libtommath.dll -def:tommath.def -out:tommath.lib +; +EXPORTS + $files + MP_MUL_KARATSUBA_CUTOFF + MP_SQR_KARATSUBA_CUTOFF + MP_MUL_TOOM_CUTOFF + MP_SQR_TOOM_CUTOFF +"; + return 0; +} + +sub die_usage { + die <<"MARKER"; +usage: $0 -s OR $0 --check-source + $0 -o OR $0 --check-comments + $0 -m OR $0 --check-makefiles + $0 -d OR $0 --check-doc + $0 -a OR $0 --check-all + $0 -u OR $0 --update-files +MARKER +} + +GetOptions( "s|check-source" => \my $check_source, + "o|check-comments" => \my $check_comments, + "m|check-makefiles" => \my $check_makefiles, + "d|check-doc" => \my $check_doc, + "a|check-all" => \my $check_all, + "u|update-files" => \my $update_files, + "h|help" => \my $help + ) or die_usage; + +my $failure; +$failure ||= check_source() if $check_all || $check_source; +$failure ||= check_comments() if $check_all || $check_comments; +$failure ||= check_doc() if $check_all || $check_doc; +$failure ||= process_makefiles(0) if $check_all || $check_makefiles; +$failure ||= process_makefiles(1) if $update_files; +$failure ||= update_dep() if $update_files; +$failure ||= generate_def() if $update_files; + +die_usage unless defined $failure; +exit $failure ? 1 : 0; diff --git a/deps/libtommath/libtommath.pc.in b/deps/libtommath/libtommath.pc.in new file mode 100644 index 0000000..ad8f5c3 --- /dev/null +++ b/deps/libtommath/libtommath.pc.in @@ -0,0 +1,9 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@ + +Name: LibTomMath +Description: public domain library for manipulating large integer numbers +Version: @PROJECT_VERSION@ +Libs: -L${libdir} -ltommath +Cflags: -I${includedir} diff --git a/deps/libtommath/libtommath_VS2008.sln b/deps/libtommath/libtommath_VS2008.sln new file mode 100644 index 0000000..935cd6a --- /dev/null +++ b/deps/libtommath/libtommath_VS2008.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tommath", "libtommath_VS2008.vcproj", "{42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|Win32.ActiveCfg = Debug|Win32 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|Win32.Build.0 = Debug|Win32 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|x64.ActiveCfg = Debug|x64 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Debug|x64.Build.0 = Debug|x64 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|Win32.ActiveCfg = Release|Win32 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|Win32.Build.0 = Release|Win32 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x64.ActiveCfg = Release|x64 + {42109FEE-B0B9-4FCD-9E56-2863BF8C55D2}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {83B84178-7B4F-4B78-9C5D-17B8201D5B61} + EndGlobalSection +EndGlobal diff --git a/deps/libtommath/libtommath_VS2008.vcproj b/deps/libtommath/libtommath_VS2008.vcproj new file mode 100644 index 0000000..50a2dd6 --- /dev/null +++ b/deps/libtommath/libtommath_VS2008.vcproj @@ -0,0 +1,966 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deps/libtommath/logs/Makefile b/deps/libtommath/logs/Makefile new file mode 100644 index 0000000..59987e5 --- /dev/null +++ b/deps/libtommath/logs/Makefile @@ -0,0 +1,9 @@ +all: + sed -e 's@\.log@-$(VERSION)\.log@g' graphs.dem > graphs-$(VERSION).dem + gnuplot graphs-$(VERSION).dem + +cmp: + gnuplot before_after.dem + +clean: + rm -f *-*.log *.png graphs-*.dem diff --git a/deps/libtommath/logs/README b/deps/libtommath/logs/README new file mode 100644 index 0000000..965e7c8 --- /dev/null +++ b/deps/libtommath/logs/README @@ -0,0 +1,13 @@ +To use the pretty graphs you have to first build/run the ltmtest from the root directory of the package. +Todo this type + +make timing ; ltmtest + +in the root. It will run for a while [about ten minutes on most PCs] and produce a series of .log files in logs/. + +After doing that run "gnuplot graphs.dem" to make the PNGs. If you managed todo that all so far just open index.html to view +them all :-) + +Have fun + +Tom \ No newline at end of file diff --git a/deps/libtommath/logs/before_after.dem b/deps/libtommath/logs/before_after.dem new file mode 100644 index 0000000..33721ad --- /dev/null +++ b/deps/libtommath/logs/before_after.dem @@ -0,0 +1,36 @@ +set terminal png +set ylabel "Cycles per Operation" +set xlabel "Operand size (bits)" + +set output "addsub-ba.png" +plot 'add-before.log' smooth bezier title "Addition (before)", \ + 'add-after.log' smooth bezier title "Addition (after)", \ + 'sub-before.log' smooth bezier title "Subtraction (before)", \ + 'sub-after.log' smooth bezier title "Subtraction (after)" + +set output "mult-ba.png" +plot 'mult-before.log' smooth bezier title "Multiplication (without Karatsuba) (before)", \ + 'mult-after.log' smooth bezier title "Multiplication (without Karatsuba) (after)", \ + 'mult_kara-before.log' smooth bezier title "Multiplication (Karatsuba) (before)", \ + 'mult_kara-after.log' smooth bezier title "Multiplication (Karatsuba) (after)" + +set output "sqr-ba.png" +plot 'sqr-before.log' smooth bezier title "Squaring (without Karatsuba) (before)", \ + 'sqr-after.log' smooth bezier title "Squaring (without Karatsuba) (after)", \ + 'sqr_kara-before.log' smooth bezier title "Squaring (Karatsuba) (before)", \ + 'sqr_kara-after.log' smooth bezier title "Squaring (Karatsuba) (after)" + +set output "expt-ba.png" +plot 'expt-before.log' smooth bezier title "Exptmod (Montgomery) (before)", \ + 'expt-after.log' smooth bezier title "Exptmod (Montgomery) (after)", \ + 'expt_dr-before.log' smooth bezier title "Exptmod (Diminished Radix) (before)", \ + 'expt_dr-after.log' smooth bezier title "Exptmod (Diminished Radix) (after)", \ + 'expt_2k-before.log' smooth bezier title "Exptmod (2k Reduction) (before)", \ + 'expt_2k-after.log' smooth bezier title "Exptmod (2k Reduction) (after)", \ + 'expt_2kl-before.log' smooth bezier title "Exptmod (2k-l Reduction) (before)", \ + 'expt_2kl-after.log' smooth bezier title "Exptmod (2k-l Reduction) (after)" + +set output "invmod-ba.png" +plot 'invmod-before.log' smooth bezier title "Modular Inverse (before)", \ + 'invmod-after.log' smooth bezier title "Modular Inverse (after)" + diff --git a/deps/libtommath/logs/before_after.html b/deps/libtommath/logs/before_after.html new file mode 100644 index 0000000..bc866f2 --- /dev/null +++ b/deps/libtommath/logs/before_after.html @@ -0,0 +1,28 @@ + + +LibTomMath Log Plots + + + +

    Swc2-Txe#!VY8AKa*9IV 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